@decaf-ts/utils 0.10.3 → 0.11.1-0.experimental.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/README.md +1 -1
  2. package/dist/utils.cjs +2561 -2
  3. package/dist/utils.js +2602 -2
  4. package/lib/assets/slogans.cjs +1 -1
  5. package/lib/bin/build-scripts.cjs +1 -1
  6. package/lib/bin/tag-release.cjs +1 -1
  7. package/lib/cli/command.cjs +1 -1
  8. package/lib/cli/commands/build-scripts.cjs +74 -14
  9. package/lib/cli/commands/build-scripts.d.ts +62 -2
  10. package/lib/cli/commands/index.cjs +1 -1
  11. package/lib/cli/commands/tag-release.cjs +1 -1
  12. package/lib/cli/constants.cjs +1 -1
  13. package/lib/cli/index.cjs +1 -1
  14. package/lib/cli/types.cjs +1 -1
  15. package/lib/esm/assets/slogans.js +1 -1
  16. package/lib/esm/bin/build-scripts.js +1 -1
  17. package/lib/esm/bin/tag-release.js +1 -1
  18. package/lib/esm/cli/command.js +1 -1
  19. package/lib/esm/cli/commands/build-scripts.d.ts +62 -2
  20. package/lib/esm/cli/commands/build-scripts.js +74 -14
  21. package/lib/esm/cli/commands/index.js +1 -1
  22. package/lib/esm/cli/commands/tag-release.js +1 -1
  23. package/lib/esm/cli/constants.js +1 -1
  24. package/lib/esm/cli/index.js +1 -1
  25. package/lib/esm/cli/types.js +1 -1
  26. package/lib/esm/index.d.ts +1 -1
  27. package/lib/esm/index.js +2 -2
  28. package/lib/esm/input/index.js +1 -1
  29. package/lib/esm/input/input.js +1 -1
  30. package/lib/esm/input/types.js +1 -1
  31. package/lib/esm/output/common.js +1 -1
  32. package/lib/esm/output/index.js +1 -1
  33. package/lib/esm/tests/Consumer.d.ts +106 -0
  34. package/lib/esm/tests/Consumer.js +79 -1
  35. package/lib/esm/tests/ProducerChildProcess.js +1 -1
  36. package/lib/esm/tests/TestReporter.d.ts +3 -0
  37. package/lib/esm/tests/TestReporter.js +20 -2
  38. package/lib/esm/tests/index.d.ts +3 -1
  39. package/lib/esm/tests/index.js +4 -2
  40. package/lib/esm/tests/jestPerformanceRunner.d.ts +7 -0
  41. package/lib/esm/tests/jestPerformanceRunner.js +15 -0
  42. package/lib/esm/tests/utils.d.ts +5 -0
  43. package/lib/esm/tests/utils.js +33 -0
  44. package/lib/esm/utils/constants.js +1 -1
  45. package/lib/esm/utils/fs.d.ts +1 -1
  46. package/lib/esm/utils/fs.js +76 -29
  47. package/lib/esm/utils/http.js +1 -1
  48. package/lib/esm/utils/index.d.ts +1 -0
  49. package/lib/esm/utils/index.js +2 -1
  50. package/lib/esm/utils/md.js +1 -1
  51. package/lib/esm/utils/performanceRunner.d.ts +126 -0
  52. package/lib/esm/utils/performanceRunner.js +344 -0
  53. package/lib/esm/utils/timeout.js +1 -1
  54. package/lib/esm/utils/types.js +1 -1
  55. package/lib/esm/utils/utils.js +1 -1
  56. package/lib/esm/writers/OutputWriter.js +1 -1
  57. package/lib/esm/writers/RegexpOutputWriter.js +1 -1
  58. package/lib/esm/writers/StandardOutputWriter.js +11 -4
  59. package/lib/esm/writers/index.js +1 -1
  60. package/lib/esm/writers/types.js +1 -1
  61. package/lib/index.cjs +2 -2
  62. package/lib/index.d.ts +1 -1
  63. package/lib/input/index.cjs +1 -1
  64. package/lib/input/input.cjs +1 -1
  65. package/lib/input/types.cjs +1 -1
  66. package/lib/output/common.cjs +1 -1
  67. package/lib/output/index.cjs +1 -1
  68. package/lib/tests/Consumer.cjs +79 -1
  69. package/lib/tests/Consumer.d.ts +106 -0
  70. package/lib/tests/ProducerChildProcess.cjs +1 -1
  71. package/lib/tests/TestReporter.cjs +20 -2
  72. package/lib/tests/TestReporter.d.ts +3 -0
  73. package/lib/tests/index.cjs +4 -2
  74. package/lib/tests/index.d.ts +3 -1
  75. package/lib/tests/jestPerformanceRunner.cjs +19 -0
  76. package/lib/tests/jestPerformanceRunner.d.ts +7 -0
  77. package/lib/tests/utils.cjs +36 -0
  78. package/lib/tests/utils.d.ts +5 -0
  79. package/lib/utils/constants.cjs +1 -1
  80. package/lib/utils/fs.cjs +76 -29
  81. package/lib/utils/fs.d.ts +1 -1
  82. package/lib/utils/http.cjs +1 -1
  83. package/lib/utils/index.cjs +2 -1
  84. package/lib/utils/index.d.ts +1 -0
  85. package/lib/utils/md.cjs +1 -1
  86. package/lib/utils/performanceRunner.cjs +384 -0
  87. package/lib/utils/performanceRunner.d.ts +126 -0
  88. package/lib/utils/timeout.cjs +1 -1
  89. package/lib/utils/types.cjs +1 -1
  90. package/lib/utils/utils.cjs +1 -1
  91. package/lib/writers/OutputWriter.cjs +1 -1
  92. package/lib/writers/RegexpOutputWriter.cjs +1 -1
  93. package/lib/writers/StandardOutputWriter.cjs +11 -4
  94. package/lib/writers/index.cjs +1 -1
  95. package/lib/writers/types.cjs +1 -1
  96. package/package.json +17 -10
  97. package/workdocs/assets/slogans.json +802 -0
  98. package/dist/utils.cjs.map +0 -1
  99. package/dist/utils.js.map +0 -1
  100. package/lib/assets/slogans.js.map +0 -1
  101. package/lib/bin/build-scripts.js.map +0 -1
  102. package/lib/bin/tag-release.js.map +0 -1
  103. package/lib/cli/command.js.map +0 -1
  104. package/lib/cli/commands/build-scripts.js.map +0 -1
  105. package/lib/cli/commands/index.js.map +0 -1
  106. package/lib/cli/commands/tag-release.js.map +0 -1
  107. package/lib/cli/constants.js.map +0 -1
  108. package/lib/cli/index.js.map +0 -1
  109. package/lib/cli/types.js.map +0 -1
  110. package/lib/esm/assets/slogans.js.map +0 -1
  111. package/lib/esm/bin/build-scripts.js.map +0 -1
  112. package/lib/esm/bin/tag-release.js.map +0 -1
  113. package/lib/esm/cli/command.js.map +0 -1
  114. package/lib/esm/cli/commands/build-scripts.js.map +0 -1
  115. package/lib/esm/cli/commands/index.js.map +0 -1
  116. package/lib/esm/cli/commands/tag-release.js.map +0 -1
  117. package/lib/esm/cli/constants.js.map +0 -1
  118. package/lib/esm/cli/index.js.map +0 -1
  119. package/lib/esm/cli/types.js.map +0 -1
  120. package/lib/esm/index.js.map +0 -1
  121. package/lib/esm/input/index.js.map +0 -1
  122. package/lib/esm/input/input.js.map +0 -1
  123. package/lib/esm/input/types.js.map +0 -1
  124. package/lib/esm/output/common.js.map +0 -1
  125. package/lib/esm/output/index.js.map +0 -1
  126. package/lib/esm/tests/Consumer.js.map +0 -1
  127. package/lib/esm/tests/ProducerChildProcess.js.map +0 -1
  128. package/lib/esm/tests/TestReporter.js.map +0 -1
  129. package/lib/esm/tests/index.js.map +0 -1
  130. package/lib/esm/utils/constants.js.map +0 -1
  131. package/lib/esm/utils/fs.js.map +0 -1
  132. package/lib/esm/utils/http.js.map +0 -1
  133. package/lib/esm/utils/index.js.map +0 -1
  134. package/lib/esm/utils/md.js.map +0 -1
  135. package/lib/esm/utils/tests.d.ts +0 -1
  136. package/lib/esm/utils/tests.js +0 -2
  137. package/lib/esm/utils/tests.js.map +0 -1
  138. package/lib/esm/utils/timeout.js.map +0 -1
  139. package/lib/esm/utils/types.js.map +0 -1
  140. package/lib/esm/utils/utils.js.map +0 -1
  141. package/lib/esm/writers/OutputWriter.js.map +0 -1
  142. package/lib/esm/writers/RegexpOutputWriter.js.map +0 -1
  143. package/lib/esm/writers/StandardOutputWriter.js.map +0 -1
  144. package/lib/esm/writers/index.js.map +0 -1
  145. package/lib/esm/writers/types.js.map +0 -1
  146. package/lib/index.js.map +0 -1
  147. package/lib/input/index.js.map +0 -1
  148. package/lib/input/input.js.map +0 -1
  149. package/lib/input/types.js.map +0 -1
  150. package/lib/output/common.js.map +0 -1
  151. package/lib/output/index.js.map +0 -1
  152. package/lib/tests/Consumer.js.map +0 -1
  153. package/lib/tests/ProducerChildProcess.js.map +0 -1
  154. package/lib/tests/TestReporter.js.map +0 -1
  155. package/lib/tests/index.js.map +0 -1
  156. package/lib/utils/constants.js.map +0 -1
  157. package/lib/utils/fs.js.map +0 -1
  158. package/lib/utils/http.js.map +0 -1
  159. package/lib/utils/index.js.map +0 -1
  160. package/lib/utils/md.js.map +0 -1
  161. package/lib/utils/tests.cjs +0 -18
  162. package/lib/utils/tests.d.ts +0 -1
  163. package/lib/utils/tests.js.map +0 -1
  164. package/lib/utils/timeout.js.map +0 -1
  165. package/lib/utils/types.js.map +0 -1
  166. package/lib/utils/utils.js.map +0 -1
  167. package/lib/writers/OutputWriter.js.map +0 -1
  168. package/lib/writers/RegexpOutputWriter.js.map +0 -1
  169. package/lib/writers/StandardOutputWriter.js.map +0 -1
  170. package/lib/writers/index.js.map +0 -1
  171. package/lib/writers/types.js.map +0 -1
package/dist/utils.js CHANGED
@@ -1,2 +1,2602 @@
1
- import e from"prompts";import{parseArgs as t}from"util";import{Logging as o,escapeRegExp as a,LoggedClass as s,LoggedEnvironment as r,LogLevel as n}from"@decaf-ts/logging";import i from"fs";import c from"path";import{spawn as l}from"child_process";import{style as g}from"styled-string-builder";import f from"zlib";import d from"https";import{rollup as h}from"rollup";import u from"@rollup/plugin-typescript";import m from"@rollup/plugin-commonjs";import{nodeResolve as p}from"@rollup/plugin-node-resolve";import S from"@rollup/plugin-json";import{builtinModules as y}from"module";import*as T from"typescript";import{ModuleKind as b}from"typescript";class w{static{this.logger=o.for(w)}constructor(e){this.type="text",this.name=e}setType(e){return w.logger.verbose("Setting type to: "+e),this.type=e,this}setMessage(e){return w.logger.verbose("Setting message to: "+e),this.message=e,this}setInitial(e){return w.logger.verbose("Setting initial value to: "+e),this.initial=e,this}setStyle(e){return w.logger.verbose("Setting style to: "+e),this.style=e,this}setFormat(e){return w.logger.verbose("Setting format function"),this.format=e,this}setValidate(e){return w.logger.verbose("Setting validate function"),this.validate=e,this}setOnState(e){return w.logger.verbose("Setting onState callback"),this.onState=e,this}setMin(e){return w.logger.verbose("Setting min value to: "+e),this.min=e,this}setMax(e){return w.logger.verbose("Setting max value to: "+e),this.max=e,this}setFloat(e){return w.logger.verbose("Setting float to: "+e),this.float=e,this}setRound(e){return w.logger.verbose("Setting round to: "+e),this.round=e,this}setInstructions(e){return w.logger.verbose("Setting instructions to: "+e),this.instructions=e,this}setIncrement(e){return w.logger.verbose("Setting increment to: "+e),this.increment=e,this}setSeparator(e){return w.logger.verbose("Setting separator to: "+e),this.separator=e,this}setActive(e){return w.logger.verbose("Setting active style to: "+e),this.active=e,this}setInactive(e){return w.logger.verbose("Setting inactive style to: "+e),this.inactive=e,this}setChoices(e){return w.logger.verbose("Setting choices: "+JSON.stringify(e)),this.choices=e,this}setHint(e){return w.logger.verbose("Setting hint to: "+e),this.hint=e,this}setWarn(e){return w.logger.verbose("Setting warn to: "+e),this.warn=e,this}setSuggest(e){return w.logger.verbose("Setting suggest function"),this.suggest=e,this}setLimit(e){return w.logger.verbose("Setting limit to: "+e),this.limit=e,this}setMask(e){return w.logger.verbose("Setting mask to: "+e),this.mask=e,this}setStdout(e){return w.logger.verbose("Setting stdout stream"),this.stdout=e,this}setStdin(e){return this.stdin=e,this}async ask(){return(await w.ask(this))[this.name]}static async ask(t){const o=w.logger.for(this.ask);let a;Array.isArray(t)||(t=[t]);try{o.verbose("Asking questions: "+t.map(e=>e.name).join(", ")),a=await e(t),o.verbose("Received answers: "+JSON.stringify(a,null,2))}catch(e){throw Error("Error while getting input: "+e)}return a}static async askNumber(e,t,o,a,s){w.logger.for(this.askNumber).verbose(`Asking number input: undefined, question: ${t}, min: ${o}, max: ${a}, initial: ${s}`);const r=new w(e).setMessage(t).setType("number");return"number"==typeof o&&r.setMin(o),"number"==typeof a&&r.setMax(a),"number"==typeof s&&r.setInitial(s),(await this.ask(r))[e]}static async askText(e,t,o=void 0,a){w.logger.for(this.askText).verbose(`Asking text input: undefined, question: ${t}, mask: ${o}, initial: ${a}`);const s=new w(e).setMessage(t);return o&&s.setMask(o),"string"==typeof a&&s.setInitial(a),(await this.ask(s))[e]}static async askConfirmation(e,t,o){w.logger.for(this.askConfirmation).verbose(`Asking confirmation input: undefined, question: ${t}, initial: ${o}`);const a=new w(e).setMessage(t).setType("confirm");return void 0!==o&&a.setInitial(o),(await this.ask(a))[e]}static async insist(e,t,o,a=1){const s=w.logger.for(this.insist);let r;s.verbose(`Insisting on input: ${e.name}, test: ${t.toString()}, defaultConfirmation: ${o}, limit: ${a}`);let n,i=0;try{do{r=(await w.ask(e))[e.name],t(r)?(n=await w.askConfirmation(e.name+"-confirm",`Is the ${e.type} correct?`,o),n||(r=void 0)):r=void 0}while(void 0===r&&a>1&&i++<a)}catch(e){throw s.error("Error while insisting: "+e),e}return void 0===r&&s.info("no selection..."),r}static async insistForText(e,t,o,a=void 0,s,r=!1,n=-1){w.logger.for(this.insistForText).verbose(`Insisting for text input: undefined, question: ${t}, test: ${o.toString()}, mask: ${a}, initial: ${s}, defaultConfirmation: ${r}, limit: ${n}`);const i=new w(e).setMessage(t);return a&&i.setMask(a),"string"==typeof s&&i.setInitial(s),await this.insist(i,o,r,n)}static async insistForNumber(e,t,o,a,s,r,n=!1,i=-1){w.logger.for(this.insistForNumber).verbose(`Insisting for number input: undefined, question: ${t}, test: ${o.toString()}, min: ${a}, max: ${s}, initial: ${r}, defaultConfirmation: ${n}, limit: ${i}`);const c=new w(e).setMessage(t).setType("number");return"number"==typeof a&&c.setMin(a),"number"==typeof s&&c.setMax(s),"number"==typeof r&&c.setInitial(r),await this.insist(c,o,n,i)}static parseArgs(e){const o=w.logger.for(this.parseArgs),a={args:process.argv.slice(2),options:e};o.debug("Parsing arguments: "+JSON.stringify(a,null,2));try{return t(a)}catch(t){throw o.debug(`Error while parsing arguments:\n${JSON.stringify(a,null,2)}\n | options\n${JSON.stringify(e,null,2)}\n | ${t}`),Error("Error while parsing arguments: "+t)}}}const C={verbose:{type:"boolean",short:"V",default:void 0},version:{type:"boolean",short:"v",default:void 0},help:{type:"boolean",short:"h",default:!1},logLevel:{type:"string",default:"info"},logStyle:{type:"boolean",default:!0},timestamp:{type:"boolean",default:!0},banner:{type:"boolean",default:!0}},D=Object.keys(C).reduce((e,t)=>(e[t]=C[t].default,e),{}),v="utf-8",k=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z])))/g;var $;(e=>{e.PATCH="patch",e.MINOR="minor",e.MAJOR="major"})($||($={}));const E="-no-ci",I="postinstall";var F;(e=>{e.GIT=".token",e.NPM=".npmtoken",e.DOCKER=".dockertoken",e.CONFLUENCE=".confluence-token"})(F||(F={}));const N="Aborted";class x{constructor(e,t,...a){this.cmd=e,this.lock=t,this.logger=o.for(this.cmd)}log(e,t){t=Buffer.isBuffer(t)?t.toString(v):t;const o="stderr"===e?g(t).red.text:t;this.logger.info(o)}data(e){this.log("stdout",e+"")}error(e){this.log("stderr",e+"")}errors(e){this.log("stderr","Error executing command exited : "+e)}exit(e,t){this.log("stdout","command exited code : "+(0===e?g(e.toString()).green.text:g(null===e?"null":e.toString()).red.text)),0===e?this.resolve(t.map(e=>e.trim()).join("\n")):this.reject(Error(t.length?t.join("\n"):e.toString()))}parseCommand(e){return e="string"==typeof e?e.split(" "):e,this.cmd=e.join(" "),[e[0],e.slice(1)]}resolve(e){this.log("stdout",`${this.cmd} executed successfully: ${g(e?"ran to completion":e).green}`),this.lock.resolve(e)}reject(e){e instanceof Error||(e=Error("number"==typeof e?"Exit code "+e:e)),this.log("stderr",`${this.cmd} failed to execute: ${g(e.message).red}`),this.lock.reject(e)}}function A(e){let t=Promise.resolve();return(...o)=>{const a=t.then(()=>e(...o));return t=a.catch(()=>{}),a}}function j(e,...t){let o,a;if(e instanceof AbortSignal?(a=new AbortController,o=[e,...t]):(a=e,o=t),a.signal.aborted)return a;const s=()=>a.abort();for(const e of o){if(e.aborted){a.abort();break}e.addEventListener("abort",s,{once:!0,signal:a.signal})}return a}function B(e,t,o,a,s){function r(t,a){const[r,n]=e.parseCommand(t);s.info("Running command: "+r),s.debug("with args: "+n.join(" "));const i=l(r,n,{...o,cwd:o.cwd||process.cwd(),env:Object.assign({},process.env,o.env,{PATH:process.env.PATH}),shell:o.shell||!1,signal:a.signal});return s.verbose("pid : "+i.pid),i}const n=t.match(/[<>$#]/g);if(n)throw Error(`Invalid command: ${t}. contains invalid characters: ${n}`);if(t.includes(" | ")){const e=t.split(" | "),o=[],s=Array(e.length);s[0]=a;for(let t=0;t<e.length;t++)0!==t&&(s[t]=j(s[t-1].signal)),o.push(r(e[t],s[t])),0!==t&&o[t-1].stdout.pipe(o[t].stdin);return o[e.length-1]}return r(t,a)}function M(e,t={},a=x,...s){const r=o.for(M),n=new AbortController,i={abort:n,command:e,logs:[],errs:[]},c=new Promise((o,c)=>{let l;try{l=new a(e,{resolve:o,reject:c},...s),i.cmd=B(l,e,t,n,r)}catch(t){return c(Error(`Error running command ${e}: ${t}`))}i.cmd.stdout.setEncoding("utf8"),i.cmd.stdout.on("data",e=>{e=e.toString(),i.logs.push(e),l.data(e)}),i.cmd.stderr.on("data",e=>{e=e.toString(),i.errs.push(e),l.error(e)}),i.cmd.once("error",e=>{l.exit(e.message,i.errs)}),i.cmd.once("exit",(e=0)=>{n.signal.aborted&&null===e&&(e=N),l.exit(e,0===e?i.logs:i.errs)})});return Object.assign(i,{promise:c,pipe:async t=>{const o=r.for("pipe");try{o.verbose(`Executing pipe function ${e}...`);const a=await c;return o.verbose(`Piping output to ${t.name}: ${a}`),t(a)}catch(e){throw o.error("Error piping command output: "+e),e}}}),i}const P=o.for("fs");function U(e,t,o){const s=P.for(U);if(!i.existsSync(e))throw Error(`File not found at path "${e}".`);let r=O(e);s.verbose(`Patching file "${e}"...`),s.debug("with value: "+JSON.stringify(t));try{r=((e,t,o="g",s)=>(Object.entries(t).forEach(([t,r])=>{const n=RegExp(a(t),o);e=e.replace(n,e=>(!s||s(e),r))}),e))(r,t,"g",o)}catch(e){throw Error("Error patching file: "+e)}L(e,r)}function O(e){const t=P.for(O);try{return t.verbose(`Reading file "${e}"...`),i.readFileSync(e,"utf8")}catch(o){throw t.verbose(`Error reading file "${e}": ${o}`),Error(`Error reading file "${e}": ${o}`)}}function L(e,t){const o=P.for(L);try{o.verbose(`Writing file "${e} with ${t.length} bytes...`),i.writeFileSync(e,t,"utf8")}catch(t){throw o.verbose(`Error writing file "${e}": ${t}`),Error(`Error writing file "${e}": ${t}`)}}function R(e,t){const o=P.for(R),a=[];try{return o.verbose(`Retrieving all files from "${e}"...`),i.readdirSync(e).forEach(t=>{const o=c.join(e,t),s=i.statSync(o);s.isFile()?a.push(o):s.isDirectory()&&a.push(...R(o))}),t?a.filter(t):a}catch(t){throw o.verbose(`Error retrieving files from "${e}": ${t}`),Error(`Error retrieving files from "${e}": ${t}`)}}async function J(e,t){const o=P.for(J);let a,s;try{a=i.statSync(e)}catch(t){throw o.verbose(`Source path "${e}" does not exist: ${t}`),Error(`Source path "${e}" does not exist: ${t}`)}try{s=i.statSync(t)}catch(e){}if(s)throw o.verbose(`Destination path "${t}" already exists`),Error(`Destination path "${t}" already exists`);try{o.verbose(`Renaming ${a.isFile()?"file":"directory"} "${e}" to "${t}...`),i.renameSync(e,t),o.verbose(`Successfully renamed to "${t}"`)}catch(s){throw o.verbose(`Error renaming ${a.isFile()?"file":"directory"} "${e}" to "${t}": ${s}`),Error(`Error renaming ${a.isFile()?"file":"directory"} "${e}" to "${t}": ${s}`)}}function W(e,t){const o=P.for(W);let a,s;try{a=i.statSync(e)}catch(t){throw o.verbose(`Source path "${e}" does not exist: ${t}`),Error(`Source path "${e}" does not exist: ${t}`)}try{s=i.statSync(t)}catch(e){a.isDirectory()&&(o.verbose(`Dest path "${t}" does not exist. creating`),i.mkdirSync(t,{recursive:!0}))}try{o.verbose(`Copying ${a.isFile()?"file":"directory"} "${e}" to "${t}...`),i.cpSync(e,t,{recursive:!0})}catch(s){throw o.verbose(`Error copying ${a.isFile()?"file":"directory"} "${e}" to "${t}: ${s}`),Error(`Error copying ${a.isFile()?"file":"directory"} "${e}" to "${t}: ${s}`)}}function X(e){const t=P.for(X);try{const o=i.statSync(e);o.isFile()?(t.verbose(`Deleting file "${e}...`),i.rmSync(e,{recursive:!0,force:!0})):o.isDirectory()&&i.rmSync(e,{recursive:!0,force:!0})}catch(o){throw t.verbose(`Error Deleting "${e}": ${o}`),Error(`Error Deleting "${e}": ${o}`)}}function V(e=process.cwd(),t){let o;try{o=JSON.parse(O(c.join(e,"package.json")))}catch(e){throw Error('Failed to retrieve package information" '+e)}if(t){if(!(t in o))throw Error(`Property "${t}" not found in package.json`);return o[t]}return o}function G(e,t,o=process.cwd()){const a=V(o);a[e]=t,L(c.join(o,"package.json"),JSON.stringify(a,null,2))}function _(e=process.cwd()){return V(e,"version")}async function H(e=process.cwd()){let t;try{t=JSON.parse(await M("npm ls --json",{cwd:e}).promise)}catch(e){throw Error("Failed to retrieve dependencies: "+e)}const o=(e,t)=>({name:e[0],version:e[1].version});return{prod:Object.entries(t.dependencies||{}).map(o),dev:Object.entries(t.devDependencies||{}).map(o),peer:Object.entries(t.peerDependencies||{}).map(o)}}async function K(){const e=P.for(K);e.info("checking for updates..."),await M("npx npm-check-updates -u").promise,e.info("updating..."),await M("npx npm run do-install").promise}async function z(e,t){if(!t){const e=await H();t={prod:e.prod?.map(e=>e.name)||[],dev:e.dev?.map(e=>e.name)||[],peer:e.peer?.map(e=>e.name)||[]}}const{prod:o,dev:a,peer:s}=t,r=Array.from(new Set([...o||[],...a||[],...s||[]])),n=(e="string"==typeof e?[e]:e).filter(e=>!r.includes(e));return n.length&&await q({dev:n}),t.dev=t.dev||[],t.dev.push(...n),t}async function Y(){const e=P.for(Y),t=await M("git config user.name").promise,o=await M("git config user.email").promise;e.verbose(`cached git id: ${t}/${o}. changing to automation`),await M('git config user.email "automation@decaf.ts"').promise,await M('git config user.name "decaf"').promise,e.info("Pushing changes to git..."),await M("git add .").promise,await M('git commit -m "refs #1 - after repo setup"').promise,await M("git push").promise,await M(`git config user.email "${o}"`).promise,await M(`git config user.name "${t}"`).promise,e.verbose(`reverted to git id: ${t}/${o}`)}async function q(e){const t=P.for(q),o=e.prod||[],a=e.dev||[],s=e.peer||[];o.length&&(t.info(`Installing dependencies ${o.join(", ")}...`),await M("npm install "+o.join(" "),{cwd:process.cwd()}).promise),a.length&&(t.info(`Installing devDependencies ${a.join(", ")}...`),await M("npm install --save-dev "+a.join(" "),{cwd:process.cwd()}).promise),s.length&&(t.info(`Installing peerDependencies ${s.join(", ")}...`),await M("npm install --save-peer "+s.join(" "),{cwd:process.cwd()}).promise)}async function Z(e){return e.then(e=>e.default||e)}async function Q(e){const t=P.for(Q);try{const o=i.readdirSync(e).map(t=>c.join(e,t)).filter(e=>{try{return i.statSync(e).isFile()&&(e.endsWith(".js")||e.endsWith(".cjs")||e.endsWith(".mjs"))}catch{return!1}});if(0===o.length)throw Error("No JS files found in directory "+e);let a=o[0],s=i.statSync(a).size;for(const e of o.slice(1)){const t=i.statSync(e).size;s>t&&(a=e,s=t)}t.verbose(`Selected smallest bundle: ${a} (${s} bytes)`);const r=i.readFileSync(a),n=f.gzipSync(r),l=Number((n.length/1024).toFixed(1));return t.verbose(`Gzipped size: ${n.length} bytes (${l} KB)`),l}catch(o){throw t.verbose(`Failed to compute gzipped size for ${e}: ${o}`),o}}function ee(e=process.cwd(),t){const o=P.for(ee);try{return i.existsSync(e)?i.readdirSync(e,{withFileTypes:!0}).filter(e=>!t||t(e.name,e)).map(e=>e.name):[]}catch(t){return o.verbose(`Failed to list folder ${e}: ${t}`),[]}}function te(e=c.join(process.cwd(),"node_modules")){const t=P.for(te);try{if(!i.existsSync(e))return[];const o=i.readdirSync(e,{withFileTypes:!0}),a=[];for(const s of o)try{if(!s.isDirectory())continue;if(s.name.startsWith("."))continue;if(s.name.startsWith("@")){const o=c.join(e,s.name);try{const e=i.readdirSync(o,{withFileTypes:!0});for(const t of e)t.isDirectory()&&!t.name.startsWith(".")&&a.push(`${s.name}/${t.name}`)}catch(e){t.verbose(`Failed to read scope ${o}: ${e}`)}}else a.push(s.name)}catch(e){t.verbose(`Skipping entry ${s.name} due to error: ${e}`)}return a}catch(o){return t.verbose(`Failed to list node_modules packages at ${e}: ${o}`),[]}}const oe=[{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That's Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"No caffeine, no chaos. Just clean code.",Tags:"Coffee-themed, Calm, Tech"},{Slogan:"Full flavor, no jitters. That\u2019s Decaf-TS.",Tags:"Coffee-themed, Cheerful"},{Slogan:"Chill fullstack. Powered by Decaf.",Tags:"Coffee-themed, Fun, Tech"},{Slogan:"Decaf-TS: Brewed for calm code.",Tags:"Coffee-themed, Branding"},{Slogan:"Smooth as your morning Decaf.",Tags:"Coffee-themed, Chill"},{Slogan:"All the kick, none of the crash.",Tags:"Coffee-themed, Energetic"},{Slogan:"Sip back and ship faster.",Tags:"Coffee-themed, Fun"},{Slogan:"Keep calm and code Decaf.",Tags:"Coffee-themed, Playful"},{Slogan:"Code without the caffeine shakes.",Tags:"Coffee-themed, Humorous"},{Slogan:"Your fullstack, decaffeinated.",Tags:"Coffee-themed, Technical"},{Slogan:"Decaf-TS: Where smart contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No CRUD, no problem \u2014 Decaf your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS: Your frontend already understands your smart contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye CRUD, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From smart contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No CRUD. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem \u2014 Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem \u2014 Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem \u2014 Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"},{Slogan:"Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",Tags:"Blockchain, Smart Contracts, Tech"},{Slogan:"Ship dApps without the stress.",Tags:"Blockchain, Cheerful, Developer"},{Slogan:"No boilerplate, no problem \u2014 Decaf-TS your data.",Tags:"Data, No-CRUD, Chill"},{Slogan:"From DID to UI, without breaking a sweat.",Tags:"DID, SSI, UI, Calm"},{Slogan:"Decaf-TS-TS: Your frontend already understands your blockchain contract.",Tags:"Smart Contracts, DX, Magic"},{Slogan:"Self-sovereign by design. Productive by default.",Tags:"SSI, Developer, Calm"},{Slogan:"Build once. Deploy everywhere. Decentralized and delightful.",Tags:"Blockchain, Multi-platform, Happy"},{Slogan:"Data that defines its own destiny.",Tags:"SSI, Data-driven, Empowerment"},{Slogan:"Goodbye boilerplate, hello intent-based interfaces.",Tags:"No-CRUD, UI, Technical"},{Slogan:"The smoothest path from DID to done.",Tags:"DID, Workflow, Chill"},{Slogan:"Because your dApp deserves more than boilerplate.",Tags:"Blockchain, DevX, Efficiency"},{Slogan:"Own your data. Own your flow.",Tags:"SSI, Control, Ownership"},{Slogan:"Write logic like it belongs with the data \u2014 because it does.",Tags:"Data Logic, Developer, Smart"},{Slogan:"From blockchain contracts to smarter frontends.",Tags:"Smart Contracts, UI, DX"},{Slogan:"No caffeine. No boilerplate. Just the future.",Tags:"No-CRUD, Coffee-themed, Futuristic"},{Slogan:"The future of web3 UX is Decaf-TS.",Tags:"Blockchain, UX, Vision"},{Slogan:"Code with confidence. Govern with clarity.",Tags:"Blockchain, Governance, Calm"},{Slogan:"Interfaces that obey the data, not the other way around.",Tags:"UI, Data Logic, Self-aware"},{Slogan:"Brew business logic right into your bytes.",Tags:"Data Logic, Coffee-themed, Fun"},{Slogan:"DIDs done differently \u2014 and delightfully.",Tags:"DID, Self-Sovereign, Playful"}],ae=["\x1b[38;5;215m","\x1b[38;5;209m","\x1b[38;5;205m","\x1b[38;5;210m","\x1b[38;5;217m","\x1b[38;5;216m","\x1b[38;5;224m","\x1b[38;5;230m","\x1b[38;5;230m"];function se(e){const t=re(),o="# \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \n# ( ( \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \n# ) ) \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \n# [=======] \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \n# `-----\xb4 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \n# \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \n# \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2593\u2592\u2591 \n#".split("\n"),a=o.reduce((e,t)=>Math.max(e,t.length),0);o.push("# "+t.padStart(a-3)),o.forEach((t,o)=>{(e?e.info.bind(e):(()=>{}).bind())(g(t||"").raw(ae[o]).text)})}function re(e){try{return e=void 0===e?Math.floor(Math.random()*oe.length):e,oe[e].Slogan}catch(e){throw Error("Failed to retrieve slogans: "+e)}}class ne extends s{constructor(e,t={},a=[]){super(),this.name=e,this.inputs=t,this.requirements=a,ne.log||Object.defineProperty(ne,"log",{writable:!1,value:o.for(ne.name)}),this.inputs=Object.assign({},C,t)}async checkRequirements(){const{prod:e,dev:t,peer:o}=await H(),a=[],s=Array.from(new Set([...e,...t,...o]).values()).map(e=>e.name);for(const e of this.requirements)s.includes(e)||a.push(e);a.length}help(e){return this.log.info("This is help. I'm no use because I should have been overridden.")}async execute(){const e=w.parseArgs(this.inputs),t=r.accumulate(D).accumulate(e.values),{version:o,help:a,banner:s}=t;if(o)return _();if(a)return this.help(e);let n;s&&se(this.log.for(se,{timestamp:!1,style:!1,context:!1,logLevel:!1}));try{n=await this.run(t)}catch(e){throw e}return n}}class ie{static{this.log=o.for(ie)}static async downloadFile(e){return new Promise((t,o)=>{!function e(a){a=encodeURI(a),d.get(a,s=>{if(301===s.statusCode||307===s.statusCode)return e(s.headers.location);if(200!==s.statusCode)return ie.log.error(`Failed to fetch ${a} (status: ${s.statusCode})`),o(Error("Failed to fetch "+a));let r="";s.on("data",e=>{r+=e}),s.on("error",e=>{o(e)}),s.on("end",()=>{t(r)})})}(e)})}}function ce(e){return e?Array.isArray(e)?e.map(e=>(""+e).trim()).filter(Boolean):(""+e).split(",").map(e=>e.trim()).filter(Boolean):[]}function le(e){return e.replace(/^@/,"").split(/[/\-_.]+/).filter(Boolean).map((e,t)=>0===t?e.replace(/[^a-zA-Z0-9]/g,""):`${e.charAt(0).toUpperCase()}${e.slice(1)}`).join("")}function ge(){let e;try{e=V(process.cwd())}catch{e=void 0}try{if(!e||!(Object.keys(e.dependencies||{}).length>0||Object.keys(e.devDependencies||{}).length>0||Object.keys(e.peerDependencies||{}).length>0)){const t=c.resolve(__dirname,"../../..");try{e=V(t)}catch{}}}catch{}const t=Object.keys(e&&e.dependencies||{}),o=Object.keys(e&&e.peerDependencies||{}),a=Object.keys(e&&e.devDependencies||{});return Array.from(new Set([...t,...o,...a]))}const fe="##VERSION##",de="##PACKAGE##",he="##PACKAGE_SIZE##";var ue,me;(e=>{e.CJS="commonjs",e.ESM="es2022"})(ue||(ue={})),(e=>{e.BUILD="build",e.BUNDLE="bundle",e.ALL="all"})(me||(me={}));const pe={prod:{type:"boolean",default:!1},dev:{type:"boolean",default:!1},buildMode:{type:"string",default:me.ALL},includes:{type:"string",default:""},externals:{type:"string",default:""},docs:{type:"boolean",default:!1},commands:{type:"boolean",default:!1},banner:{type:"boolean",default:!1}},Se=(e=".cjs")=>{const t=ye.log.for(Se),o=new Map;return a=>s=>{const r=c.dirname(s.fileName);function n(a){const s=JSON.stringify([r,a]),n=o.get(s);if(null!=n)return n;let l,g=a;try{g=c.resolve(r,g+".ts")}catch(e){throw Error(`Failed to resolve path ${a}: ${e}`)}try{l=i.statSync(g)}catch(e){try{t.verbose(`Testing existence of path ${g} as a folder defaulting to index file`),l=i.statSync(g.replace(/\.ts$/gm,""))}catch(t){throw Error(`Failed to resolve path ${a}: ${e}, ${t}`)}}if(l.isDirectory()&&(g=g.replace(/\.ts$/gm,"/index.ts")),c.isAbsolute(g)){const t=(/\.tsx?$/.exec(c.basename(g))||[])[0]||void 0;g="./"+c.relative(r,c.resolve(c.dirname(g),c.basename(g,t)+e))}return o.set(s,g),g}return T.visitNode(s,function e(t){if((e=>!(!T.isImportDeclaration(e)&&!T.isExportDeclaration(e)||void 0===e.moduleSpecifier||!T.isStringLiteral(e.moduleSpecifier)||!e.moduleSpecifier.text.startsWith("./")&&!e.moduleSpecifier.text.startsWith("../")||""!==c.extname(e.moduleSpecifier.text)))(t)){if(T.isImportDeclaration(t)){const e=n(t.moduleSpecifier.text),o=a.factory.createStringLiteral(e);return a.factory.updateImportDeclaration(t,t.modifiers,t.importClause,o,void 0)}if(T.isExportDeclaration(t)){const e=n(t.moduleSpecifier.text),o=a.factory.createStringLiteral(e);return a.factory.updateExportDeclaration(t,t.modifiers,t.isTypeOnly,t.exportClause,o,void 0)}}return T.visitEachChild(t,e,a)})}};class ye extends ne{constructor(){super("BuildScripts",Object.assign({},C,pe)),this.replacements={};const e=V(),{name:t,version:o}=e;this.pkgName=t.includes("@")?t.split("/")[1]:t,this.pkgVersion=o,this.replacements[fe]=this.pkgVersion,this.replacements[de]=t}patchFiles(e){const t=this.log.for(this.patchFiles),{name:o,version:a}=V();t.info(`Patching ${o} ${a} module in ${e}...`),i.statSync(e).isDirectory()&&i.readdirSync(e,{withFileTypes:!0,recursive:!0}).filter(e=>e.isFile()).forEach(e=>U(c.join(e.parentPath,e.name),Object.entries(this.replacements).reduce((e,[o,a])=>{switch(o){case fe:t.debug("Found VERSION string to replace"),e[`VERSION = "${fe}";`]=`VERSION = "${a}";`;break;case de:t.debug("Found PACKAGE_NAME string to replace"),e[`PACKAGE_NAME = "${de}";`]=`PACKAGE_NAME = "${a}";`;break;default:e[o]=a}return e},{}))),t.verbose(`Module ${o} ${a} patched in ${e}...`)}reportDiagnostics(e,t){const o=this.formatDiagnostics(e);try{this.log[t](o)}catch(e){throw e}return o}formatDiagnostics(e){return e.map(e=>{let t="";if(e.file&&e.start){const{line:o,character:a}=e.file.getLineAndCharacterOfPosition(e.start);t+=`${e.file.fileName} (${o+1},${a+1})`}return t+=": "+T.flattenDiagnosticMessageText(e.messageText,"\n"),t}).join("\n")}readConfigFile(e){const t=i.readFileSync(e).toString(),o=T.parseConfigFileTextToJson(e,t),a=o.config;a||this.reportDiagnostics([o.error],n.error);const s=T.parseJsonConfigFileContent(a,T.sys,c.dirname(e));return s.errors.length>0&&this.reportDiagnostics(s.errors,n.error),s}evalDiagnostics(e){if(e&&e.length>0){const t=e.filter(e=>e.category===T.DiagnosticCategory.Error),o=e.filter(e=>e.category===T.DiagnosticCategory.Warning),a=e.filter(e=>e.category===T.DiagnosticCategory.Suggestion),s=e.filter(e=>e.category===T.DiagnosticCategory.Message);if(o.length&&this.reportDiagnostics(o,n.warn),t.length)throw this.reportDiagnostics(e,n.error),Error(`TypeScript reported ${e.length} diagnostic(s) during check; aborting.`);a.length&&this.reportDiagnostics(a,n.info),s.length&&this.reportDiagnostics(s,n.info)}}preCheckDiagnostics(e){const t=T.getPreEmitDiagnostics(e);this.evalDiagnostics(t)}async checkTsDiagnostics(e,t,o=!1){const a=this.log.for(this.checkTsDiagnostics);let s;try{s=this.readConfigFile("./tsconfig.json")}catch(e){throw Error("Failed to parse tsconfig.json: "+e)}o?(s.options.module=b.AMD,s.options.outDir="dist",s.options.isolatedModules=!1,s.options.outFile=this.pkgName):(s.options.outDir="lib"+(t===ue.ESM?"/esm":""),s.options.module=t===ue.ESM?b.ES2022:b.CommonJS),s.options.inlineSourceMap=!1,s.options.inlineSources=!1,s.options.sourceMap=!0;const r=T.createProgram(s.fileNames,s.options);this.preCheckDiagnostics(r),a.verbose(`TypeScript checks passed (${o?"bundle":"normal"} mode).`)}async buildTs(e,t,o=!1){let a;this.log.for(this.buildTs).info(`Building ${this.pkgName} ${this.pkgVersion} module (${t}) in ${e?"dev":"prod"} mode...`);try{a=this.readConfigFile("./tsconfig.json")}catch(e){throw Error("Failed to parse tsconfig.json: "+e)}o?(a.options.module=b.AMD,a.options.outDir="dist",a.options.isolatedModules=!1,a.options.outFile=this.pkgName):(a.options.outDir="lib"+(t===ue.ESM?"/esm":""),a.options.module=t===ue.ESM?b.ES2022:b.CommonJS),e?(a.options.inlineSourceMap=!0,a.options.inlineSources=!0,a.options.sourceMap=!1):(a.options.inlineSourceMap=!1,a.options.inlineSources=!1,a.options.sourceMap=!0);const s=T.createProgram(a.fileNames,a.options),r={};t===ue.CJS?r.before=[Se(".cjs")]:t===ue.ESM&&(r.before=[Se(".js")]);const n=s.emit(void 0,void 0,void 0,void 0,r),i=T.getPreEmitDiagnostics(s).concat(n.diagnostics);this.evalDiagnostics(i)}async build(e,t,o=!1){const a=this.log.for(this.build);if(await this.buildTs(e,t,o),a.verbose(`Module ${this.pkgName} ${this.pkgVersion} (${t}) built in ${e?"dev":"prod"} mode...`),t===ue.CJS&&!o){const e=R("lib",e=>e.endsWith(".js")&&!e.includes("/esm/"));for(const t of e){a.verbose(`Patching ${t}'s cjs imports...`);const e=t.replace(".js",".cjs");await J(t,e)}}}copyAssets(e){const t=this.log.for(this.copyAssets);let o=!1;try{o=i.statSync("./src/assets").isDirectory()}catch(e){return t.verbose("No assets found in ./src/assets to copy")}o&&W("./src/assets",`./${e===ue.CJS?"lib":"dist"}/assets`)}async bundle(e,t,o,a="src/index.ts",s=this.pkgName,r,n=["prompts","styled-string-builder","typed-object-accumulator","@decaf-ts/logging"]){await this.checkTsDiagnostics(t,e,!0);const i=e===ue.ESM,l=this.pkgName,g=this.log,f=Array.from(new Set([...ce(n)]));let d=ce(r);if(0===d.length){try{d=te(c.join(process.cwd(),"node_modules"))}catch{}d&&0!==d.length||(d=ge())}const T=Array.from(new Set([...(()=>{try{return Array.isArray(y)?y:[]}catch{return["fs","path","process","child_process","util","https","http","os","stream","crypto","zlib","net","tls","url","querystring","assert","events","tty","dns","querystring"]}})(),...d])),b=!t||"inline",w=[u({compilerOptions:{module:"esnext",declaration:!1,outDir:o?"bin":"dist",sourceMap:!t,inlineSourceMap:!!t,inlineSources:!!t},include:["src/**/*.ts"],exclude:["node_modules","**/*.spec.ts"],tsconfig:"./tsconfig.json"}),S()];o&&w.push(m({include:[],exclude:d}),p({resolveOnly:f}));try{const k=await import("@rollup/plugin-terser"),$=k&&k.terser||k.default||k,E={parse:{ecma:2020},compress:!1,mangle:!1,format:{comments:!1,beautify:!0}},I={parse:{ecma:2020},compress:{ecma:2020,passes:5,drop_console:!0,drop_debugger:!0,toplevel:!0,module:i,unsafe:!0,unsafe_arrows:!0,unsafe_comps:!0,collapse_vars:!0,reduce_funcs:!0,reduce_vars:!0},mangle:{toplevel:!0},format:{comments:!1,ascii_only:!0},toplevel:!0};w.push($(t?E:I))}catch{}const C={input:a,plugins:w,external:T,onwarn:void 0,treeshake:!t},D={};T.forEach(e=>{D[e]=le(e)});const v=[{file:`${o?"bin/":"dist/"}${s||".bundle."+(t?"":"min")}${i?".js":".cjs"}`,format:o?"cjs":i?"esm":"umd",name:l,esModule:i,sourcemap:b,globals:D,exports:"auto"}];try{const F=await h(C);async function N(e){for(const t of v)await e.write(t)}g.verbose(F.watchFiles),await N(F)}catch(x){throw Error("Failed to bundle: "+x)}}async buildByEnv(e,t=me.ALL,o,a){try{X("lib")}catch(e){}try{X("dist")}catch(e){}i.mkdirSync("lib"),i.mkdirSync("dist"),[me.ALL,me.BUILD].includes(t)&&(await this.build(e,ue.ESM),await this.build(e,ue.CJS),this.patchFiles("lib")),[me.ALL,me.BUNDLE].includes(t)&&(await this.bundle(ue.ESM,e,!1,"src/index.ts",this.pkgName,a,o),await this.bundle(ue.CJS,e,!1,"src/index.ts",this.pkgName,a,o),this.patchFiles("dist")),this.copyAssets(ue.CJS),this.copyAssets(ue.ESM)}async buildDev(e=me.ALL,t,o){return this.buildByEnv(!0,e,t,o)}async buildProd(e=me.ALL,t,o){return this.buildByEnv(!1,e,t,o)}async buildDocs(){await M("npm install better-docs taffydb").promise,await M("npx markdown-include ./workdocs/readme-md.json").promise,await M("npx jsdoc -c ./workdocs/jsdocs.json -t ./node_modules/better-docs").promise,await M("npm remove better-docs taffydb").promise,[{src:"workdocs/assets",dest:"./docs/workdocs/assets"},{src:"workdocs/reports/coverage",dest:"./docs/workdocs/reports/coverage"},{src:"workdocs/reports/html",dest:"./docs/workdocs/reports/html"},{src:"workdocs/resources",dest:"./docs/workdocs/resources"},{src:"LICENSE.md",dest:"./docs/LICENSE.md"}].forEach(e=>{const{src:t,dest:o}=e;W(t,o)});try{const e=await Q(c.resolve(c.join(process.cwd(),"dist")));this.replacements[he]=e+" KB"}catch{this.replacements[he]="unknown"}try{U("./README.md",this.replacements)}catch(e){this.log.for(this.buildDocs).verbose("Failed to patch README.md: "+e)}}async run(e){const{dev:t,prod:o,docs:a,buildMode:s,includes:r,externals:n}=e;return t?await this.buildDev(s,r,n):o?await this.buildProd(s,r,n):a?await this.buildDocs():void 0}}const Te={ci:{type:"boolean",default:!0},message:{type:"string",short:"m"},tag:{type:"string",short:"t",default:void 0}};class be extends ne{constructor(){super("ReleaseScript",Te)}async prepareVersion(e){const t=this.log.for(this.prepareVersion);return(e=this.testVersion(e||""))||(t.verbose("No release message provided. Prompting for one:"),t.info("Listing latest git tags:"),await M("git tag --sort=-taggerdate | head -n 5").promise,await w.insistForText("tag","Enter the new tag number (accepts v*.*.*[-...])",e=>!!e.toString().match(/^v[0-9]+\.[0-9]+.[0-9]+(-[0-9a-zA-Z-]+)?$/)))}testVersion(e){const t=this.log.for(this.testVersion);switch(e=e.trim().toLowerCase()){case $.PATCH:case $.MINOR:case $.MAJOR:return t.verbose("Using provided SemVer update: "+e,1),e;default:return t.verbose("Testing provided version for SemVer compatibility: "+e,1),RegExp(k).test(e)?(t.verbose("version approved: "+e,1),e):void t.debug("Invalid version number: "+e)}}async prepareMessage(e){const t=this.log.for(this.prepareMessage);return e||(t.verbose("No release message provided. Prompting for one"),await w.insistForText("message","What should be the release message/ticket?",e=>!!e&&e.toString().length>5))}async run(e){let t;const{ci:o}=e;let{tag:a,message:s}=e;a=await this.prepareVersion(a),s=await this.prepareMessage(s),t=await M(`npm run prepare-release -- ${a} ${s}`,{cwd:process.cwd()}).promise,t=await M("git status --porcelain").promise,await t,t.logs.length&&await w.askConfirmation("git-changes","Do you want to push the changes to the remote repository?",!0)&&(await M("git add .").promise,await M(`git commit -m "${a} - ${s} - after release preparation${o?"":E}"`).promise),await M(`npm version "${a}" -m "${s}${o?"":E}"`).promise,await M("git push --follow-tags").promise,o||await M("NPM_TOKEN=$(cat .npmtoken) npm publish --access public").promise}}class we extends x{constructor(e,t,o,a="g"){super(e,t);try{this.regexp="string"==typeof o?RegExp(o,a):o}catch(e){throw Error("Invalid regular expression: "+e)}}test(e){let t;this.regexp.lastIndex=0;try{t=this.regexp.exec(e)}catch(e){return}return t}testAndResolve(e){const t=this.test(e);t&&this.resolve(t[0])}testAndReject(e){const t=this.test(e);t&&this.reject(t[0])}data(e){super.data(e),this.testAndResolve(e+"")}error(e){super.error(e),this.testAndReject(e+"")}}const Ce="##VERSION##",De="##PACKAGE##";export{N as AbortCode,ye as BuildScripts,ne as Command,C as DefaultCommandOptions,D as DefaultCommandValues,v as Encoding,ie as HttpClient,E as NoCIFLag,De as PACKAGE_NAME,we as RegexpOutputWriter,be as ReleaseScript,$ as SemVersion,k as SemVersionRegex,I as SetupScriptKey,x as StandardOutputWriter,F as Tokens,w as UserInput,Ce as VERSION,j as chainAbortController,W as copyFile,X as deletePath,R as getAllFiles,H as getDependencies,Q as getFileSizeZipped,V as getPackage,ge as getPackageDependencies,_ as getPackageVersion,re as getSlogan,q as installDependencies,z as installIfNotAvailable,ee as listFolder,te as listNodeModulesPackages,A as lockify,Z as normalizeImport,le as packageToGlobal,ce as parseList,U as patchFile,se as printBanner,Y as pushToGit,O as readFile,J as renameFile,M as runCommand,G as setPackageAttribute,B as spawnCommand,K as updateDependencies,L as writeFile};
2
- //# sourceMappingURL=utils.js.map
1
+ import prompts from "prompts";
2
+
3
+ import { parseArgs } from "util";
4
+
5
+ import { Logging, escapeRegExp, LoggedClass, LoggedEnvironment, StopWatch, LogLevel } from "@decaf-ts/logging";
6
+
7
+ import fs from "fs";
8
+
9
+ import path from "path";
10
+
11
+ import { createRequire, builtinModules } from "module";
12
+
13
+ import { spawn } from "child_process";
14
+
15
+ import { style } from "styled-string-builder";
16
+
17
+ import { parse } from "shell-quote";
18
+
19
+ import zlib from "zlib";
20
+
21
+ import https from "https";
22
+
23
+ import { mkdir, writeFile as writeFile$1 } from "fs/promises";
24
+
25
+ import { rollup } from "rollup";
26
+
27
+ import typescript from "@rollup/plugin-typescript";
28
+
29
+ import commonjs from "@rollup/plugin-commonjs";
30
+
31
+ import { nodeResolve } from "@rollup/plugin-node-resolve";
32
+
33
+ import json from "@rollup/plugin-json";
34
+
35
+ import * as ts from "typescript";
36
+
37
+ import { ModuleKind } from "typescript";
38
+
39
+ class UserInput {
40
+ static {
41
+ this.logger = Logging.for(UserInput);
42
+ }
43
+ constructor(name) {
44
+ this.type = "text";
45
+ this.name = name;
46
+ }
47
+ setType(type) {
48
+ UserInput.logger.verbose(`Setting type to: ${type}`);
49
+ this.type = type;
50
+ return this;
51
+ }
52
+ setMessage(value) {
53
+ UserInput.logger.verbose(`Setting message to: ${value}`);
54
+ this.message = value;
55
+ return this;
56
+ }
57
+ setInitial(value) {
58
+ UserInput.logger.verbose(`Setting initial value to: ${value}`);
59
+ this.initial = value;
60
+ return this;
61
+ }
62
+ setStyle(value) {
63
+ UserInput.logger.verbose(`Setting style to: ${value}`);
64
+ this.style = value;
65
+ return this;
66
+ }
67
+ setFormat(value) {
68
+ UserInput.logger.verbose(`Setting format function`);
69
+ this.format = value;
70
+ return this;
71
+ }
72
+ setValidate(value) {
73
+ UserInput.logger.verbose(`Setting validate function`);
74
+ this.validate = value;
75
+ return this;
76
+ }
77
+ setOnState(value) {
78
+ UserInput.logger.verbose(`Setting onState callback`);
79
+ this.onState = value;
80
+ return this;
81
+ }
82
+ setMin(value) {
83
+ UserInput.logger.verbose(`Setting min value to: ${value}`);
84
+ this.min = value;
85
+ return this;
86
+ }
87
+ setMax(value) {
88
+ UserInput.logger.verbose(`Setting max value to: ${value}`);
89
+ this.max = value;
90
+ return this;
91
+ }
92
+ setFloat(value) {
93
+ UserInput.logger.verbose(`Setting float to: ${value}`);
94
+ this.float = value;
95
+ return this;
96
+ }
97
+ setRound(value) {
98
+ UserInput.logger.verbose(`Setting round to: ${value}`);
99
+ this.round = value;
100
+ return this;
101
+ }
102
+ setInstructions(value) {
103
+ UserInput.logger.verbose(`Setting instructions to: ${value}`);
104
+ this.instructions = value;
105
+ return this;
106
+ }
107
+ setIncrement(value) {
108
+ UserInput.logger.verbose(`Setting increment to: ${value}`);
109
+ this.increment = value;
110
+ return this;
111
+ }
112
+ setSeparator(value) {
113
+ UserInput.logger.verbose(`Setting separator to: ${value}`);
114
+ this.separator = value;
115
+ return this;
116
+ }
117
+ setActive(value) {
118
+ UserInput.logger.verbose(`Setting active style to: ${value}`);
119
+ this.active = value;
120
+ return this;
121
+ }
122
+ setInactive(value) {
123
+ UserInput.logger.verbose(`Setting inactive style to: ${value}`);
124
+ this.inactive = value;
125
+ return this;
126
+ }
127
+ setChoices(value) {
128
+ UserInput.logger.verbose(`Setting choices: ${JSON.stringify(value)}`);
129
+ this.choices = value;
130
+ return this;
131
+ }
132
+ setHint(value) {
133
+ UserInput.logger.verbose(`Setting hint to: ${value}`);
134
+ this.hint = value;
135
+ return this;
136
+ }
137
+ setWarn(value) {
138
+ UserInput.logger.verbose(`Setting warn to: ${value}`);
139
+ this.warn = value;
140
+ return this;
141
+ }
142
+ setSuggest(value) {
143
+ UserInput.logger.verbose(`Setting suggest function`);
144
+ this.suggest = value;
145
+ return this;
146
+ }
147
+ setLimit(value) {
148
+ UserInput.logger.verbose(`Setting limit to: ${value}`);
149
+ this.limit = value;
150
+ return this;
151
+ }
152
+ setMask(value) {
153
+ UserInput.logger.verbose(`Setting mask to: ${value}`);
154
+ this.mask = value;
155
+ return this;
156
+ }
157
+ setStdout(value) {
158
+ UserInput.logger.verbose(`Setting stdout stream`);
159
+ this.stdout = value;
160
+ return this;
161
+ }
162
+ setStdin(value) {
163
+ this.stdin = value;
164
+ return this;
165
+ }
166
+ async ask() {
167
+ return (await UserInput.ask(this))[this.name];
168
+ }
169
+ static async ask(question) {
170
+ const log = UserInput.logger.for(this.ask);
171
+ if (!Array.isArray(question)) {
172
+ question = [ question ];
173
+ }
174
+ let answers;
175
+ try {
176
+ log.verbose(`Asking questions: ${question.map(q => q.name).join(", ")}`);
177
+ answers = await prompts(question);
178
+ log.verbose(`Received answers: ${JSON.stringify(answers, null, 2)}`);
179
+ } catch (error) {
180
+ throw new Error(`Error while getting input: ${error}`);
181
+ }
182
+ return answers;
183
+ }
184
+ static async askNumber(name, question, min, max, initial) {
185
+ const log = UserInput.logger.for(this.askNumber);
186
+ log.verbose(`Asking number input: undefined, question: ${question}, min: ${min}, max: ${max}, initial: ${initial}`);
187
+ const userInput = new UserInput(name).setMessage(question).setType("number");
188
+ if (typeof min === "number") userInput.setMin(min);
189
+ if (typeof max === "number") userInput.setMax(max);
190
+ if (typeof initial === "number") userInput.setInitial(initial);
191
+ return (await this.ask(userInput))[name];
192
+ }
193
+ static async askText(name, question, mask = undefined, initial) {
194
+ const log = UserInput.logger.for(this.askText);
195
+ log.verbose(`Asking text input: undefined, question: ${question}, mask: ${mask}, initial: ${initial}`);
196
+ const userInput = new UserInput(name).setMessage(question);
197
+ if (mask) userInput.setMask(mask);
198
+ if (typeof initial === "string") userInput.setInitial(initial);
199
+ return (await this.ask(userInput))[name];
200
+ }
201
+ static async askConfirmation(name, question, initial) {
202
+ const log = UserInput.logger.for(this.askConfirmation);
203
+ log.verbose(`Asking confirmation input: undefined, question: ${question}, initial: ${initial}`);
204
+ const userInput = new UserInput(name).setMessage(question).setType("confirm");
205
+ if (typeof initial !== "undefined") userInput.setInitial(initial);
206
+ return (await this.ask(userInput))[name];
207
+ }
208
+ static async insist(input, test, defaultConfirmation, limit = 1) {
209
+ const log = UserInput.logger.for(this.insist);
210
+ log.verbose(`Insisting on input: ${input.name}, test: ${test.toString()}, defaultConfirmation: ${defaultConfirmation}, limit: ${limit}`);
211
+ let result = undefined;
212
+ let count = 0;
213
+ let confirmation;
214
+ try {
215
+ do {
216
+ result = (await UserInput.ask(input))[input.name];
217
+ if (!test(result)) {
218
+ result = undefined;
219
+ continue;
220
+ }
221
+ confirmation = await UserInput.askConfirmation(`${input.name}-confirm`, `Is the ${input.type} correct?`, defaultConfirmation);
222
+ if (!confirmation) result = undefined;
223
+ } while (typeof result === "undefined" && limit > 1 && count++ < limit);
224
+ } catch (e) {
225
+ log.error(`Error while insisting: ${e}`);
226
+ throw e;
227
+ }
228
+ if (typeof result === "undefined") log.info("no selection...");
229
+ return result;
230
+ }
231
+ static async insistForText(name, question, test, mask = undefined, initial, defaultConfirmation = false, limit = -1) {
232
+ const log = UserInput.logger.for(this.insistForText);
233
+ log.verbose(`Insisting for text input: undefined, question: ${question}, test: ${test.toString()}, mask: ${mask}, initial: ${initial}, defaultConfirmation: ${defaultConfirmation}, limit: ${limit}`);
234
+ const userInput = new UserInput(name).setMessage(question);
235
+ if (mask) userInput.setMask(mask);
236
+ if (typeof initial === "string") userInput.setInitial(initial);
237
+ return await this.insist(userInput, test, defaultConfirmation, limit);
238
+ }
239
+ static async insistForNumber(name, question, test, min, max, initial, defaultConfirmation = false, limit = -1) {
240
+ const log = UserInput.logger.for(this.insistForNumber);
241
+ log.verbose(`Insisting for number input: undefined, question: ${question}, test: ${test.toString()}, min: ${min}, max: ${max}, initial: ${initial}, defaultConfirmation: ${defaultConfirmation}, limit: ${limit}`);
242
+ const userInput = new UserInput(name).setMessage(question).setType("number");
243
+ if (typeof min === "number") userInput.setMin(min);
244
+ if (typeof max === "number") userInput.setMax(max);
245
+ if (typeof initial === "number") userInput.setInitial(initial);
246
+ return await this.insist(userInput, test, defaultConfirmation, limit);
247
+ }
248
+ static parseArgs(options) {
249
+ const log = UserInput.logger.for(this.parseArgs);
250
+ const args = {
251
+ args: process.argv.slice(2),
252
+ options: options
253
+ };
254
+ log.debug(`Parsing arguments: ${JSON.stringify(args, null, 2)}`);
255
+ try {
256
+ return parseArgs(args);
257
+ } catch (error) {
258
+ log.debug(`Error while parsing arguments:\n${JSON.stringify(args, null, 2)}\n | options\n${JSON.stringify(options, null, 2)}\n | ${error}`);
259
+ throw new Error(`Error while parsing arguments: ${error}`);
260
+ }
261
+ }
262
+ }
263
+
264
+ const DefaultCommandOptions = {
265
+ verbose: {
266
+ type: "boolean",
267
+ short: "V",
268
+ default: undefined
269
+ },
270
+ version: {
271
+ type: "boolean",
272
+ short: "v",
273
+ default: undefined
274
+ },
275
+ help: {
276
+ type: "boolean",
277
+ short: "h",
278
+ default: false
279
+ },
280
+ logLevel: {
281
+ type: "string",
282
+ default: "info"
283
+ },
284
+ logStyle: {
285
+ type: "boolean",
286
+ default: true
287
+ },
288
+ timestamp: {
289
+ type: "boolean",
290
+ default: true
291
+ },
292
+ banner: {
293
+ type: "boolean",
294
+ default: true
295
+ }
296
+ };
297
+
298
+ const DefaultCommandValues = Object.keys(DefaultCommandOptions).reduce((acc, key) => {
299
+ acc[key] = DefaultCommandOptions[key].default;
300
+ return acc;
301
+ }, {});
302
+
303
+ const Encoding = "utf-8";
304
+
305
+ const SemVersionRegex = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z])))/g;
306
+
307
+ var SemVersion;
308
+
309
+ (function(SemVersion) {
310
+ SemVersion["PATCH"] = "patch";
311
+ SemVersion["MINOR"] = "minor";
312
+ SemVersion["MAJOR"] = "major";
313
+ })(SemVersion || (SemVersion = {}));
314
+
315
+ const NoCIFLag = "-no-ci";
316
+
317
+ const SetupScriptKey = "postinstall";
318
+
319
+ var Tokens;
320
+
321
+ (function(Tokens) {
322
+ Tokens["GIT"] = ".token";
323
+ Tokens["NPM"] = ".npmtoken";
324
+ Tokens["DOCKER"] = ".dockertoken";
325
+ Tokens["CONFLUENCE"] = ".confluence-token";
326
+ })(Tokens || (Tokens = {}));
327
+
328
+ const AbortCode = "Aborted";
329
+
330
+ class StandardOutputWriter {
331
+ constructor(cmd, lock, ...args) {
332
+ this.cmd = cmd;
333
+ this.lock = lock;
334
+ this.logger = Logging.for(this.cmd);
335
+ }
336
+ log(type, data) {
337
+ data = Buffer.isBuffer(data) ? data.toString(Encoding) : data;
338
+ const log = type === "stderr" ? style(data).red.text : data;
339
+ this.logger.info(log);
340
+ }
341
+ data(chunk) {
342
+ this.log("stdout", String(chunk));
343
+ }
344
+ error(chunk) {
345
+ this.log("stderr", String(chunk));
346
+ }
347
+ errors(err) {
348
+ this.log("stderr", `Error executing command exited : ${err}`);
349
+ }
350
+ exit(code, logs) {
351
+ this.log("stdout", `command exited code : ${code === 0 ? style(code.toString()).green.text : style(code === null ? "null" : code.toString()).red.text}`);
352
+ if (code === 0) {
353
+ this.resolve(logs.map(l => l.trim()).join("\n"));
354
+ } else {
355
+ this.reject(new Error(logs.length ? logs.join("\n") : code.toString()));
356
+ }
357
+ }
358
+ parseCommand(command) {
359
+ if (Array.isArray(command)) {
360
+ this.cmd = command.join(" ");
361
+ return [ command[0], command.slice(1) ];
362
+ }
363
+ const parts = parse(command).filter(p => typeof p === "string").map(String);
364
+ this.cmd = parts.join(" ");
365
+ return [ parts[0], parts.slice(1) ];
366
+ }
367
+ resolve(reason) {
368
+ this.log("stdout", `${this.cmd} executed successfully: ${style(reason ? "ran to completion" : reason).green}`);
369
+ this.lock.resolve(reason);
370
+ }
371
+ reject(reason) {
372
+ if (!(reason instanceof Error)) {
373
+ reason = new Error(typeof reason === "number" ? `Exit code ${reason}` : reason);
374
+ }
375
+ this.log("stderr", `${this.cmd} failed to execute: ${style(reason.message).red}`);
376
+ this.lock.reject(reason);
377
+ }
378
+ }
379
+
380
+ function lockify(f) {
381
+ let lock = Promise.resolve();
382
+ return (...params) => {
383
+ const result = lock.then(() => f(...params));
384
+ lock = result.catch(() => {});
385
+ return result;
386
+ };
387
+ }
388
+
389
+ function chainAbortController(argument0, ...remainder) {
390
+ let signals;
391
+ let controller;
392
+ if (argument0 instanceof AbortSignal) {
393
+ controller = new AbortController;
394
+ signals = [ argument0, ...remainder ];
395
+ } else {
396
+ controller = argument0;
397
+ signals = remainder;
398
+ }
399
+ if (controller.signal.aborted) {
400
+ return controller;
401
+ }
402
+ const handler = () => controller.abort();
403
+ for (const signal of signals) {
404
+ if (signal.aborted) {
405
+ controller.abort();
406
+ break;
407
+ }
408
+ signal.addEventListener("abort", handler, {
409
+ once: true,
410
+ signal: controller.signal
411
+ });
412
+ }
413
+ return controller;
414
+ }
415
+
416
+ function spawnCommand(output, command, opts, abort, logger) {
417
+ function spawnInner(command, controller) {
418
+ const [cmd, argz] = output.parseCommand(command);
419
+ logger.info(`Running command: ${cmd}`);
420
+ logger.debug(`with args: ${argz.join(" ")}`);
421
+ const childProcess = spawn(cmd, argz, {
422
+ ...opts,
423
+ cwd: opts.cwd || process.cwd(),
424
+ env: Object.assign({}, process.env, opts.env, {
425
+ PATH: process.env.PATH
426
+ }),
427
+ shell: opts.shell || false,
428
+ signal: controller.signal
429
+ });
430
+ logger.verbose(`pid : ${childProcess.pid}`);
431
+ return childProcess;
432
+ }
433
+ const m = command.match(/[<>$#]/g);
434
+ if (m) throw new Error(`Invalid command: ${command}. contains invalid characters: ${m}`);
435
+ if (command.includes(" | ")) {
436
+ const cmds = command.split(" | ");
437
+ const spawns = [];
438
+ const controllers = new Array(cmds.length);
439
+ controllers[0] = abort;
440
+ for (let i = 0; i < cmds.length; i++) {
441
+ if (i !== 0) controllers[i] = chainAbortController(controllers[i - 1].signal);
442
+ spawns.push(spawnInner(cmds[i], controllers[i]));
443
+ if (i === 0) continue;
444
+ spawns[i - 1].stdout.pipe(spawns[i].stdin);
445
+ }
446
+ return spawns[cmds.length - 1];
447
+ }
448
+ return spawnInner(command, abort);
449
+ }
450
+
451
+ function runCommand(command, opts = {}, outputConstructor = StandardOutputWriter, ...args) {
452
+ const logger = Logging.for(runCommand);
453
+ const abort = new AbortController;
454
+ const result = {
455
+ abort: abort,
456
+ command: command,
457
+ logs: [],
458
+ errs: []
459
+ };
460
+ const lock = new Promise((resolve, reject) => {
461
+ let output;
462
+ try {
463
+ output = new outputConstructor(command, {
464
+ resolve: resolve,
465
+ reject: reject
466
+ }, ...args);
467
+ result.cmd = spawnCommand(output, command, opts, abort, logger);
468
+ } catch (e) {
469
+ return reject(new Error(`Error running command ${command}: ${e}`));
470
+ }
471
+ result.cmd.stdout.setEncoding("utf8");
472
+ result.cmd.stdout.on("data", chunk => {
473
+ chunk = chunk.toString();
474
+ result.logs.push(chunk);
475
+ output.data(chunk);
476
+ });
477
+ result.cmd.stderr.on("data", data => {
478
+ data = data.toString();
479
+ result.errs.push(data);
480
+ output.error(data);
481
+ });
482
+ result.cmd.once("error", err => {
483
+ output.exit(err.message, result.errs);
484
+ });
485
+ result.cmd.once("exit", (code = 0) => {
486
+ if (abort.signal.aborted && code === null) code = AbortCode;
487
+ output.exit(code, code === 0 ? result.logs : result.errs);
488
+ });
489
+ });
490
+ Object.assign(result, {
491
+ promise: lock,
492
+ pipe: async cb => {
493
+ const l = logger.for("pipe");
494
+ try {
495
+ l.verbose(`Executing pipe function ${command}...`);
496
+ const result = await lock;
497
+ l.verbose(`Piping output to ${cb.name}: ${result}`);
498
+ return cb(result);
499
+ } catch (e) {
500
+ l.error(`Error piping command output: ${e}`);
501
+ throw e;
502
+ }
503
+ }
504
+ });
505
+ return result;
506
+ }
507
+
508
+ const logger = Logging.for("fs");
509
+
510
+ const localRequire = createRequire(`${process.cwd()}/package.json`);
511
+
512
+ function isTestEnvironment() {
513
+ return process.env.NODE_ENV === "test" || typeof process.env.JEST_WORKER_ID !== "undefined";
514
+ }
515
+
516
+ function patchString(input, values, flags = "g", filter) {
517
+ Object.entries(values).forEach(([key, val]) => {
518
+ const regexp = new RegExp(escapeRegExp(key), flags);
519
+ input = input.replace(regexp, subStr => {
520
+ if (!filter || filter(subStr)) {
521
+ return val;
522
+ }
523
+ return val;
524
+ });
525
+ });
526
+ return input;
527
+ }
528
+
529
+ function patchFile(path, values, filter) {
530
+ const log = logger.for(patchFile);
531
+ if (!fs.existsSync(path)) throw new Error(`File not found at path "${path}".`);
532
+ let content = readFile(path);
533
+ log.verbose(`Patching file "${path}"...`);
534
+ log.debug(`with value: ${JSON.stringify(values)}`);
535
+ try {
536
+ content = patchString(content, values, "g", filter);
537
+ } catch (error) {
538
+ throw new Error(`Error patching file: ${error}`);
539
+ }
540
+ writeFile(path, content);
541
+ }
542
+
543
+ function readFile(path) {
544
+ const log = logger.for(readFile);
545
+ try {
546
+ log.verbose(`Reading file "${path}"...`);
547
+ return fs.readFileSync(path, "utf8");
548
+ } catch (error) {
549
+ log.verbose(`Error reading file "${path}": ${error}`);
550
+ throw new Error(`Error reading file "${path}": ${error}`);
551
+ }
552
+ }
553
+
554
+ function writeFile(path, data) {
555
+ const log = logger.for(writeFile);
556
+ try {
557
+ log.verbose(`Writing file "${path} with ${data.length} bytes...`);
558
+ fs.writeFileSync(path, data, "utf8");
559
+ } catch (error) {
560
+ log.verbose(`Error writing file "${path}": ${error}`);
561
+ throw new Error(`Error writing file "${path}": ${error}`);
562
+ }
563
+ }
564
+
565
+ function getAllFiles(p, filter) {
566
+ const log = logger.for(getAllFiles);
567
+ const files = [];
568
+ try {
569
+ log.verbose(`Retrieving all files from "${p}"...`);
570
+ const entries = fs.readdirSync(p);
571
+ entries.forEach(entry => {
572
+ const fullPath = path.join(p, entry);
573
+ const stat = fs.statSync(fullPath);
574
+ if (stat.isFile()) {
575
+ files.push(fullPath);
576
+ } else if (stat.isDirectory()) {
577
+ files.push(...getAllFiles(fullPath));
578
+ }
579
+ });
580
+ if (!filter) return files;
581
+ return files.filter(filter);
582
+ } catch (error) {
583
+ log.verbose(`Error retrieving files from "${p}": ${error}`);
584
+ throw new Error(`Error retrieving files from "${p}": ${error}`);
585
+ }
586
+ }
587
+
588
+ async function renameFile(source, dest) {
589
+ const log = logger.for(renameFile);
590
+ let descriptorSource, descriptorDest;
591
+ try {
592
+ descriptorSource = fs.statSync(source);
593
+ } catch (error) {
594
+ log.verbose(`Source path "${source}" does not exist: ${error}`);
595
+ throw new Error(`Source path "${source}" does not exist: ${error}`);
596
+ }
597
+ try {
598
+ descriptorDest = fs.statSync(dest);
599
+ } catch (e) {}
600
+ if (descriptorDest) {
601
+ log.verbose(`Destination path "${dest}" already exists`);
602
+ throw new Error(`Destination path "${dest}" already exists`);
603
+ }
604
+ try {
605
+ log.verbose(`Renaming ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}...`);
606
+ fs.renameSync(source, dest);
607
+ log.verbose(`Successfully renamed to "${dest}"`);
608
+ } catch (error) {
609
+ log.verbose(`Error renaming ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}": ${error}`);
610
+ throw new Error(`Error renaming ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}": ${error}`);
611
+ }
612
+ }
613
+
614
+ function copyFile(source, dest) {
615
+ const log = logger.for(copyFile);
616
+ let descriptorSource, descriptorDest;
617
+ try {
618
+ descriptorSource = fs.statSync(source);
619
+ } catch (error) {
620
+ log.verbose(`Source path "${source}" does not exist: ${error}`);
621
+ throw new Error(`Source path "${source}" does not exist: ${error}`);
622
+ }
623
+ try {
624
+ descriptorDest = fs.statSync(dest);
625
+ } catch (error) {
626
+ if (descriptorSource.isDirectory()) {
627
+ log.verbose(`Dest path "${dest}" does not exist. creating`);
628
+ fs.mkdirSync(dest, {
629
+ recursive: true
630
+ });
631
+ }
632
+ }
633
+ try {
634
+ log.verbose(`Copying ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}...`);
635
+ fs.cpSync(source, dest, {
636
+ recursive: true
637
+ });
638
+ } catch (error) {
639
+ log.verbose(`Error copying ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}: ${error}`);
640
+ throw new Error(`Error copying ${descriptorSource.isFile() ? "file" : "directory"} "${source}" to "${dest}: ${error}`);
641
+ }
642
+ }
643
+
644
+ function deletePath(p) {
645
+ const log = logger.for(deletePath);
646
+ try {
647
+ const descriptor = fs.statSync(p);
648
+ if (descriptor.isFile()) {
649
+ log.verbose(`Deleting file "${p}...`);
650
+ fs.rmSync(p, {
651
+ recursive: true,
652
+ force: true
653
+ });
654
+ } else if (descriptor.isDirectory()) fs.rmSync(p, {
655
+ recursive: true,
656
+ force: true
657
+ });
658
+ } catch (error) {
659
+ log.verbose(`Error Deleting "${p}": ${error}`);
660
+ throw new Error(`Error Deleting "${p}": ${error}`);
661
+ }
662
+ }
663
+
664
+ function getPackage(p = process.cwd(), property) {
665
+ let pkg;
666
+ try {
667
+ pkg = JSON.parse(readFile(path.join(p, `package.json`)));
668
+ } catch (error) {
669
+ throw new Error(`Failed to retrieve package information" ${error}`);
670
+ }
671
+ if (property) {
672
+ if (!(property in pkg)) throw new Error(`Property "${property}" not found in package.json`);
673
+ return pkg[property];
674
+ }
675
+ return pkg;
676
+ }
677
+
678
+ function setPackageAttribute(attr, value, p = process.cwd()) {
679
+ const pkg = getPackage(p);
680
+ pkg[attr] = value;
681
+ writeFile(path.join(p, `package.json`), JSON.stringify(pkg, null, 2));
682
+ }
683
+
684
+ function getPackageVersion(p = process.cwd()) {
685
+ return getPackage(p, "version");
686
+ }
687
+
688
+ async function getDependencies(p = process.cwd()) {
689
+ const pkgPath = path.join(p, "package.json");
690
+ const lockPath = path.join(p, "package-lock.json");
691
+ let pkg;
692
+ try {
693
+ pkg = JSON.parse(readFile(pkgPath));
694
+ } catch (error) {
695
+ throw new Error(`Could not read package.json at ${pkgPath}: ${error}`);
696
+ }
697
+ let lock;
698
+ if (fs.existsSync(lockPath)) {
699
+ try {
700
+ lock = JSON.parse(readFile(lockPath));
701
+ } catch (error) {
702
+ logger.warn(`Unable to parse package-lock.json at ${lockPath}: ${error}`);
703
+ }
704
+ }
705
+ const mapDeps = (entries = {}) => Object.entries(entries).map(([name, version]) => ({
706
+ name: name,
707
+ version: resolveDependencyVersion(lock, name, version)
708
+ }));
709
+ return {
710
+ prod: mapDeps(pkg.dependencies),
711
+ dev: mapDeps(pkg.devDependencies),
712
+ peer: mapDeps(pkg.peerDependencies)
713
+ };
714
+ }
715
+
716
+ function resolveDependencyVersion(lock, name, fallback) {
717
+ if (lock) {
718
+ const packages = lock.packages || {};
719
+ const key = `node_modules/${name}`;
720
+ if (packages[key] && packages[key].version) {
721
+ return packages[key].version;
722
+ }
723
+ if (lock.dependencies && lock.dependencies[name]) {
724
+ return lock.dependencies[name].version || fallback;
725
+ }
726
+ }
727
+ return fallback;
728
+ }
729
+
730
+ async function updateDependencies() {
731
+ const log = logger.for(updateDependencies);
732
+ log.info("checking for updates...");
733
+ await runCommand("npx npm-check-updates -u").promise;
734
+ log.info("updating...");
735
+ await runCommand("npx npm run do-install").promise;
736
+ }
737
+
738
+ async function installIfNotAvailable(deps, dependencies) {
739
+ deps = typeof deps === "string" ? [ deps ] : deps;
740
+ const current = {
741
+ prod: dependencies?.prod ? [ ...dependencies.prod ] : [],
742
+ dev: dependencies?.dev ? [ ...dependencies.dev ] : [],
743
+ peer: dependencies?.peer ? [ ...dependencies.peer ] : []
744
+ };
745
+ const known = new Set([ ...current.prod ?? [], ...current.dev ?? [], ...current.peer ?? [] ]);
746
+ const toInstall = [];
747
+ for (const dep of deps) {
748
+ if (known.has(dep)) continue;
749
+ try {
750
+ localRequire.resolve(dep);
751
+ known.add(dep);
752
+ } catch {
753
+ toInstall.push(dep);
754
+ }
755
+ }
756
+ if (toInstall.length) {
757
+ if (isTestEnvironment()) {
758
+ logger.verbose(`Skipping dependency install in test environment for: ${toInstall.join(", ")}`);
759
+ } else {
760
+ await installDependencies({
761
+ dev: toInstall
762
+ });
763
+ }
764
+ const devDeps = new Set(current.dev ?? []);
765
+ toInstall.forEach(dep => devDeps.add(dep));
766
+ current.dev = Array.from(devDeps);
767
+ }
768
+ return current;
769
+ }
770
+
771
+ async function pushToGit() {
772
+ const log = logger.for(pushToGit);
773
+ const gitUser = await runCommand("git config user.name").promise;
774
+ const gitEmail = await runCommand("git config user.email").promise;
775
+ log.verbose(`cached git id: ${gitUser}/${gitEmail}. changing to automation`);
776
+ await runCommand('git config user.email "automation@decaf.ts"').promise;
777
+ await runCommand('git config user.name "decaf"').promise;
778
+ log.info("Pushing changes to git...");
779
+ await runCommand("git add .").promise;
780
+ await runCommand(`git commit -m "refs #1 - after repo setup"`).promise;
781
+ await runCommand("git push").promise;
782
+ await runCommand(`git config user.email "${gitEmail}"`).promise;
783
+ await runCommand(`git config user.name "${gitUser}"`).promise;
784
+ log.verbose(`reverted to git id: ${gitUser}/${gitEmail}`);
785
+ }
786
+
787
+ async function installDependencies(dependencies) {
788
+ const log = logger.for(installDependencies);
789
+ const prod = dependencies.prod || [];
790
+ const dev = dependencies.dev || [];
791
+ const peer = dependencies.peer || [];
792
+ if (prod.length) {
793
+ log.info(`Installing dependencies ${prod.join(", ")}...`);
794
+ await runCommand(`npm install ${prod.join(" ")}`, {
795
+ cwd: process.cwd()
796
+ }).promise;
797
+ }
798
+ if (dev.length) {
799
+ log.info(`Installing devDependencies ${dev.join(", ")}...`);
800
+ await runCommand(`npm install --save-dev ${dev.join(" ")}`, {
801
+ cwd: process.cwd()
802
+ }).promise;
803
+ }
804
+ if (peer.length) {
805
+ log.info(`Installing peerDependencies ${peer.join(", ")}...`);
806
+ await runCommand(`npm install --save-peer ${peer.join(" ")}`, {
807
+ cwd: process.cwd()
808
+ }).promise;
809
+ }
810
+ }
811
+
812
+ async function normalizeImport(importPromise) {
813
+ return importPromise.then(m => m.default || m);
814
+ }
815
+
816
+ async function getFileSizeZipped(dir) {
817
+ const log = logger.for(getFileSizeZipped);
818
+ try {
819
+ const entries = fs.readdirSync(dir);
820
+ const candidates = entries.map(e => path.join(dir, e)).filter(p => {
821
+ try {
822
+ const s = fs.statSync(p);
823
+ return s.isFile() && (p.endsWith(".js") || p.endsWith(".cjs") || p.endsWith(".mjs"));
824
+ } catch {
825
+ return false;
826
+ }
827
+ });
828
+ if (candidates.length === 0) {
829
+ throw new Error(`No JS files found in directory ${dir}`);
830
+ }
831
+ let smallest = candidates[0];
832
+ let smallestSize = fs.statSync(smallest).size;
833
+ for (const c of candidates.slice(1)) {
834
+ const s = fs.statSync(c).size;
835
+ if (s < smallestSize) {
836
+ smallest = c;
837
+ smallestSize = s;
838
+ }
839
+ }
840
+ log.verbose(`Selected smallest bundle: ${smallest} (${smallestSize} bytes)`);
841
+ const buffer = fs.readFileSync(smallest);
842
+ const gz = zlib.gzipSync(buffer);
843
+ const sizeKb = Number((gz.length / 1024).toFixed(1));
844
+ log.verbose(`Gzipped size: ${gz.length} bytes (${sizeKb} KB)`);
845
+ return sizeKb;
846
+ } catch (e) {
847
+ log.verbose(`Failed to compute gzipped size for ${dir}: ${e}`);
848
+ throw e;
849
+ }
850
+ }
851
+
852
+ function listFolder(basePath = process.cwd(), filter) {
853
+ const log = logger.for(listFolder);
854
+ try {
855
+ if (!fs.existsSync(basePath)) return [];
856
+ const entries = fs.readdirSync(basePath, {
857
+ withFileTypes: true
858
+ });
859
+ const names = entries.filter(d => filter ? filter(d.name, d) : true).map(d => d.name);
860
+ return names;
861
+ } catch (e) {
862
+ log.verbose(`Failed to list folder ${basePath}: ${e}`);
863
+ return [];
864
+ }
865
+ }
866
+
867
+ function listNodeModulesPackages(basePath = path.join(process.cwd(), "node_modules")) {
868
+ const log = logger.for(listNodeModulesPackages);
869
+ try {
870
+ if (!fs.existsSync(basePath)) return [];
871
+ const entries = fs.readdirSync(basePath, {
872
+ withFileTypes: true
873
+ });
874
+ const names = [];
875
+ for (const e of entries) {
876
+ try {
877
+ if (!e.isDirectory()) continue;
878
+ if (e.name.startsWith(".")) continue;
879
+ if (e.name.startsWith("@")) {
880
+ const scopePath = path.join(basePath, e.name);
881
+ try {
882
+ const scoped = fs.readdirSync(scopePath, {
883
+ withFileTypes: true
884
+ });
885
+ for (const s of scoped) {
886
+ if (s.isDirectory() && !s.name.startsWith(".")) {
887
+ names.push(`${e.name}/${s.name}`);
888
+ }
889
+ }
890
+ } catch (err) {
891
+ log.verbose(`Failed to read scope ${scopePath}: ${err}`);
892
+ }
893
+ } else {
894
+ names.push(e.name);
895
+ }
896
+ } catch (err) {
897
+ log.verbose(`Skipping entry ${e.name} due to error: ${err}`);
898
+ }
899
+ }
900
+ return names;
901
+ } catch (e) {
902
+ log.verbose(`Failed to list node_modules packages at ${basePath}: ${e}`);
903
+ return [];
904
+ }
905
+ }
906
+
907
+ const slogans = [ {
908
+ Slogan: "No caffeine, no chaos. Just clean code.",
909
+ Tags: "Coffee-themed, Calm, Tech"
910
+ }, {
911
+ Slogan: "Full flavor, no jitters. That's Decaf-TS.",
912
+ Tags: "Coffee-themed, Cheerful"
913
+ }, {
914
+ Slogan: "Chill fullstack. Powered by Decaf.",
915
+ Tags: "Coffee-themed, Fun, Tech"
916
+ }, {
917
+ Slogan: "Decaf-TS: Brewed for calm code.",
918
+ Tags: "Coffee-themed, Branding"
919
+ }, {
920
+ Slogan: "Smooth as your morning Decaf.",
921
+ Tags: "Coffee-themed, Chill"
922
+ }, {
923
+ Slogan: "All the kick, none of the crash.",
924
+ Tags: "Coffee-themed, Energetic"
925
+ }, {
926
+ Slogan: "Sip back and ship faster.",
927
+ Tags: "Coffee-themed, Fun"
928
+ }, {
929
+ Slogan: "Keep calm and code Decaf.",
930
+ Tags: "Coffee-themed, Playful"
931
+ }, {
932
+ Slogan: "Code without the caffeine shakes.",
933
+ Tags: "Coffee-themed, Humorous"
934
+ }, {
935
+ Slogan: "Your fullstack, decaffeinated.",
936
+ Tags: "Coffee-themed, Technical"
937
+ }, {
938
+ Slogan: "No caffeine, no chaos. Just clean code.",
939
+ Tags: "Coffee-themed, Calm, Tech"
940
+ }, {
941
+ Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
942
+ Tags: "Coffee-themed, Cheerful"
943
+ }, {
944
+ Slogan: "Chill fullstack. Powered by Decaf.",
945
+ Tags: "Coffee-themed, Fun, Tech"
946
+ }, {
947
+ Slogan: "Decaf-TS: Brewed for calm code.",
948
+ Tags: "Coffee-themed, Branding"
949
+ }, {
950
+ Slogan: "Smooth as your morning Decaf.",
951
+ Tags: "Coffee-themed, Chill"
952
+ }, {
953
+ Slogan: "All the kick, none of the crash.",
954
+ Tags: "Coffee-themed, Energetic"
955
+ }, {
956
+ Slogan: "Sip back and ship faster.",
957
+ Tags: "Coffee-themed, Fun"
958
+ }, {
959
+ Slogan: "Keep calm and code Decaf.",
960
+ Tags: "Coffee-themed, Playful"
961
+ }, {
962
+ Slogan: "Code without the caffeine shakes.",
963
+ Tags: "Coffee-themed, Humorous"
964
+ }, {
965
+ Slogan: "Your fullstack, decaffeinated.",
966
+ Tags: "Coffee-themed, Technical"
967
+ }, {
968
+ Slogan: "No caffeine, no chaos. Just clean code.",
969
+ Tags: "Coffee-themed, Calm, Tech"
970
+ }, {
971
+ Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
972
+ Tags: "Coffee-themed, Cheerful"
973
+ }, {
974
+ Slogan: "Chill fullstack. Powered by Decaf.",
975
+ Tags: "Coffee-themed, Fun, Tech"
976
+ }, {
977
+ Slogan: "Decaf-TS: Brewed for calm code.",
978
+ Tags: "Coffee-themed, Branding"
979
+ }, {
980
+ Slogan: "Smooth as your morning Decaf.",
981
+ Tags: "Coffee-themed, Chill"
982
+ }, {
983
+ Slogan: "All the kick, none of the crash.",
984
+ Tags: "Coffee-themed, Energetic"
985
+ }, {
986
+ Slogan: "Sip back and ship faster.",
987
+ Tags: "Coffee-themed, Fun"
988
+ }, {
989
+ Slogan: "Keep calm and code Decaf.",
990
+ Tags: "Coffee-themed, Playful"
991
+ }, {
992
+ Slogan: "Code without the caffeine shakes.",
993
+ Tags: "Coffee-themed, Humorous"
994
+ }, {
995
+ Slogan: "Your fullstack, decaffeinated.",
996
+ Tags: "Coffee-themed, Technical"
997
+ }, {
998
+ Slogan: "No caffeine, no chaos. Just clean code.",
999
+ Tags: "Coffee-themed, Calm, Tech"
1000
+ }, {
1001
+ Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
1002
+ Tags: "Coffee-themed, Cheerful"
1003
+ }, {
1004
+ Slogan: "Chill fullstack. Powered by Decaf.",
1005
+ Tags: "Coffee-themed, Fun, Tech"
1006
+ }, {
1007
+ Slogan: "Decaf-TS: Brewed for calm code.",
1008
+ Tags: "Coffee-themed, Branding"
1009
+ }, {
1010
+ Slogan: "Smooth as your morning Decaf.",
1011
+ Tags: "Coffee-themed, Chill"
1012
+ }, {
1013
+ Slogan: "All the kick, none of the crash.",
1014
+ Tags: "Coffee-themed, Energetic"
1015
+ }, {
1016
+ Slogan: "Sip back and ship faster.",
1017
+ Tags: "Coffee-themed, Fun"
1018
+ }, {
1019
+ Slogan: "Keep calm and code Decaf.",
1020
+ Tags: "Coffee-themed, Playful"
1021
+ }, {
1022
+ Slogan: "Code without the caffeine shakes.",
1023
+ Tags: "Coffee-themed, Humorous"
1024
+ }, {
1025
+ Slogan: "Your fullstack, decaffeinated.",
1026
+ Tags: "Coffee-themed, Technical"
1027
+ }, {
1028
+ Slogan: "No caffeine, no chaos. Just clean code.",
1029
+ Tags: "Coffee-themed, Calm, Tech"
1030
+ }, {
1031
+ Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
1032
+ Tags: "Coffee-themed, Cheerful"
1033
+ }, {
1034
+ Slogan: "Chill fullstack. Powered by Decaf.",
1035
+ Tags: "Coffee-themed, Fun, Tech"
1036
+ }, {
1037
+ Slogan: "Decaf-TS: Brewed for calm code.",
1038
+ Tags: "Coffee-themed, Branding"
1039
+ }, {
1040
+ Slogan: "Smooth as your morning Decaf.",
1041
+ Tags: "Coffee-themed, Chill"
1042
+ }, {
1043
+ Slogan: "All the kick, none of the crash.",
1044
+ Tags: "Coffee-themed, Energetic"
1045
+ }, {
1046
+ Slogan: "Sip back and ship faster.",
1047
+ Tags: "Coffee-themed, Fun"
1048
+ }, {
1049
+ Slogan: "Keep calm and code Decaf.",
1050
+ Tags: "Coffee-themed, Playful"
1051
+ }, {
1052
+ Slogan: "Code without the caffeine shakes.",
1053
+ Tags: "Coffee-themed, Humorous"
1054
+ }, {
1055
+ Slogan: "Your fullstack, decaffeinated.",
1056
+ Tags: "Coffee-themed, Technical"
1057
+ }, {
1058
+ Slogan: "No caffeine, no chaos. Just clean code.",
1059
+ Tags: "Coffee-themed, Calm, Tech"
1060
+ }, {
1061
+ Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
1062
+ Tags: "Coffee-themed, Cheerful"
1063
+ }, {
1064
+ Slogan: "Chill fullstack. Powered by Decaf.",
1065
+ Tags: "Coffee-themed, Fun, Tech"
1066
+ }, {
1067
+ Slogan: "Decaf-TS: Brewed for calm code.",
1068
+ Tags: "Coffee-themed, Branding"
1069
+ }, {
1070
+ Slogan: "Smooth as your morning Decaf.",
1071
+ Tags: "Coffee-themed, Chill"
1072
+ }, {
1073
+ Slogan: "All the kick, none of the crash.",
1074
+ Tags: "Coffee-themed, Energetic"
1075
+ }, {
1076
+ Slogan: "Sip back and ship faster.",
1077
+ Tags: "Coffee-themed, Fun"
1078
+ }, {
1079
+ Slogan: "Keep calm and code Decaf.",
1080
+ Tags: "Coffee-themed, Playful"
1081
+ }, {
1082
+ Slogan: "Code without the caffeine shakes.",
1083
+ Tags: "Coffee-themed, Humorous"
1084
+ }, {
1085
+ Slogan: "Your fullstack, decaffeinated.",
1086
+ Tags: "Coffee-themed, Technical"
1087
+ }, {
1088
+ Slogan: "No caffeine, no chaos. Just clean code.",
1089
+ Tags: "Coffee-themed, Calm, Tech"
1090
+ }, {
1091
+ Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
1092
+ Tags: "Coffee-themed, Cheerful"
1093
+ }, {
1094
+ Slogan: "Chill fullstack. Powered by Decaf.",
1095
+ Tags: "Coffee-themed, Fun, Tech"
1096
+ }, {
1097
+ Slogan: "Decaf-TS: Brewed for calm code.",
1098
+ Tags: "Coffee-themed, Branding"
1099
+ }, {
1100
+ Slogan: "Smooth as your morning Decaf.",
1101
+ Tags: "Coffee-themed, Chill"
1102
+ }, {
1103
+ Slogan: "All the kick, none of the crash.",
1104
+ Tags: "Coffee-themed, Energetic"
1105
+ }, {
1106
+ Slogan: "Sip back and ship faster.",
1107
+ Tags: "Coffee-themed, Fun"
1108
+ }, {
1109
+ Slogan: "Keep calm and code Decaf.",
1110
+ Tags: "Coffee-themed, Playful"
1111
+ }, {
1112
+ Slogan: "Code without the caffeine shakes.",
1113
+ Tags: "Coffee-themed, Humorous"
1114
+ }, {
1115
+ Slogan: "Your fullstack, decaffeinated.",
1116
+ Tags: "Coffee-themed, Technical"
1117
+ }, {
1118
+ Slogan: "No caffeine, no chaos. Just clean code.",
1119
+ Tags: "Coffee-themed, Calm, Tech"
1120
+ }, {
1121
+ Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
1122
+ Tags: "Coffee-themed, Cheerful"
1123
+ }, {
1124
+ Slogan: "Chill fullstack. Powered by Decaf.",
1125
+ Tags: "Coffee-themed, Fun, Tech"
1126
+ }, {
1127
+ Slogan: "Decaf-TS: Brewed for calm code.",
1128
+ Tags: "Coffee-themed, Branding"
1129
+ }, {
1130
+ Slogan: "Smooth as your morning Decaf.",
1131
+ Tags: "Coffee-themed, Chill"
1132
+ }, {
1133
+ Slogan: "All the kick, none of the crash.",
1134
+ Tags: "Coffee-themed, Energetic"
1135
+ }, {
1136
+ Slogan: "Sip back and ship faster.",
1137
+ Tags: "Coffee-themed, Fun"
1138
+ }, {
1139
+ Slogan: "Keep calm and code Decaf.",
1140
+ Tags: "Coffee-themed, Playful"
1141
+ }, {
1142
+ Slogan: "Code without the caffeine shakes.",
1143
+ Tags: "Coffee-themed, Humorous"
1144
+ }, {
1145
+ Slogan: "Your fullstack, decaffeinated.",
1146
+ Tags: "Coffee-themed, Technical"
1147
+ }, {
1148
+ Slogan: "No caffeine, no chaos. Just clean code.",
1149
+ Tags: "Coffee-themed, Calm, Tech"
1150
+ }, {
1151
+ Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
1152
+ Tags: "Coffee-themed, Cheerful"
1153
+ }, {
1154
+ Slogan: "Chill fullstack. Powered by Decaf.",
1155
+ Tags: "Coffee-themed, Fun, Tech"
1156
+ }, {
1157
+ Slogan: "Decaf-TS: Brewed for calm code.",
1158
+ Tags: "Coffee-themed, Branding"
1159
+ }, {
1160
+ Slogan: "Smooth as your morning Decaf.",
1161
+ Tags: "Coffee-themed, Chill"
1162
+ }, {
1163
+ Slogan: "All the kick, none of the crash.",
1164
+ Tags: "Coffee-themed, Energetic"
1165
+ }, {
1166
+ Slogan: "Sip back and ship faster.",
1167
+ Tags: "Coffee-themed, Fun"
1168
+ }, {
1169
+ Slogan: "Keep calm and code Decaf.",
1170
+ Tags: "Coffee-themed, Playful"
1171
+ }, {
1172
+ Slogan: "Code without the caffeine shakes.",
1173
+ Tags: "Coffee-themed, Humorous"
1174
+ }, {
1175
+ Slogan: "Your fullstack, decaffeinated.",
1176
+ Tags: "Coffee-themed, Technical"
1177
+ }, {
1178
+ Slogan: "No caffeine, no chaos. Just clean code.",
1179
+ Tags: "Coffee-themed, Calm, Tech"
1180
+ }, {
1181
+ Slogan: "Full flavor, no jitters. That’s Decaf-TS.",
1182
+ Tags: "Coffee-themed, Cheerful"
1183
+ }, {
1184
+ Slogan: "Chill fullstack. Powered by Decaf.",
1185
+ Tags: "Coffee-themed, Fun, Tech"
1186
+ }, {
1187
+ Slogan: "Decaf-TS: Brewed for calm code.",
1188
+ Tags: "Coffee-themed, Branding"
1189
+ }, {
1190
+ Slogan: "Smooth as your morning Decaf.",
1191
+ Tags: "Coffee-themed, Chill"
1192
+ }, {
1193
+ Slogan: "All the kick, none of the crash.",
1194
+ Tags: "Coffee-themed, Energetic"
1195
+ }, {
1196
+ Slogan: "Sip back and ship faster.",
1197
+ Tags: "Coffee-themed, Fun"
1198
+ }, {
1199
+ Slogan: "Keep calm and code Decaf.",
1200
+ Tags: "Coffee-themed, Playful"
1201
+ }, {
1202
+ Slogan: "Code without the caffeine shakes.",
1203
+ Tags: "Coffee-themed, Humorous"
1204
+ }, {
1205
+ Slogan: "Your fullstack, decaffeinated.",
1206
+ Tags: "Coffee-themed, Technical"
1207
+ }, {
1208
+ Slogan: "Decaf-TS: Where smart contracts meet smart interfaces.",
1209
+ Tags: "Blockchain, Smart Contracts, Tech"
1210
+ }, {
1211
+ Slogan: "Ship dApps without the stress.",
1212
+ Tags: "Blockchain, Cheerful, Developer"
1213
+ }, {
1214
+ Slogan: "No CRUD, no problem — Decaf your data.",
1215
+ Tags: "Data, No-CRUD, Chill"
1216
+ }, {
1217
+ Slogan: "From DID to UI, without breaking a sweat.",
1218
+ Tags: "DID, SSI, UI, Calm"
1219
+ }, {
1220
+ Slogan: "Decaf-TS: Your frontend already understands your smart contract.",
1221
+ Tags: "Smart Contracts, DX, Magic"
1222
+ }, {
1223
+ Slogan: "Self-sovereign by design. Productive by default.",
1224
+ Tags: "SSI, Developer, Calm"
1225
+ }, {
1226
+ Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
1227
+ Tags: "Blockchain, Multi-platform, Happy"
1228
+ }, {
1229
+ Slogan: "Data that defines its own destiny.",
1230
+ Tags: "SSI, Data-driven, Empowerment"
1231
+ }, {
1232
+ Slogan: "Goodbye CRUD, hello intent-based interfaces.",
1233
+ Tags: "No-CRUD, UI, Technical"
1234
+ }, {
1235
+ Slogan: "The smoothest path from DID to done.",
1236
+ Tags: "DID, Workflow, Chill"
1237
+ }, {
1238
+ Slogan: "Because your dApp deserves more than boilerplate.",
1239
+ Tags: "Blockchain, DevX, Efficiency"
1240
+ }, {
1241
+ Slogan: "Own your data. Own your flow.",
1242
+ Tags: "SSI, Control, Ownership"
1243
+ }, {
1244
+ Slogan: "Write logic like it belongs with the data — because it does.",
1245
+ Tags: "Data Logic, Developer, Smart"
1246
+ }, {
1247
+ Slogan: "From smart contracts to smarter frontends.",
1248
+ Tags: "Smart Contracts, UI, DX"
1249
+ }, {
1250
+ Slogan: "No caffeine. No CRUD. Just the future.",
1251
+ Tags: "No-CRUD, Coffee-themed, Futuristic"
1252
+ }, {
1253
+ Slogan: "The future of web3 UX is Decaf.",
1254
+ Tags: "Blockchain, UX, Vision"
1255
+ }, {
1256
+ Slogan: "Code with confidence. Govern with clarity.",
1257
+ Tags: "Blockchain, Governance, Calm"
1258
+ }, {
1259
+ Slogan: "Interfaces that obey the data, not the other way around.",
1260
+ Tags: "UI, Data Logic, Self-aware"
1261
+ }, {
1262
+ Slogan: "Brew business logic right into your bytes.",
1263
+ Tags: "Data Logic, Coffee-themed, Fun"
1264
+ }, {
1265
+ Slogan: "DIDs done differently — and delightfully.",
1266
+ Tags: "DID, Self-Sovereign, Playful"
1267
+ }, {
1268
+ Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
1269
+ Tags: "Blockchain, Smart Contracts, Tech"
1270
+ }, {
1271
+ Slogan: "Ship dApps without the stress.",
1272
+ Tags: "Blockchain, Cheerful, Developer"
1273
+ }, {
1274
+ Slogan: "No boilerplate, no problem — Decaf-TS your data.",
1275
+ Tags: "Data, No-CRUD, Chill"
1276
+ }, {
1277
+ Slogan: "From DID to UI, without breaking a sweat.",
1278
+ Tags: "DID, SSI, UI, Calm"
1279
+ }, {
1280
+ Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
1281
+ Tags: "Smart Contracts, DX, Magic"
1282
+ }, {
1283
+ Slogan: "Self-sovereign by design. Productive by default.",
1284
+ Tags: "SSI, Developer, Calm"
1285
+ }, {
1286
+ Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
1287
+ Tags: "Blockchain, Multi-platform, Happy"
1288
+ }, {
1289
+ Slogan: "Data that defines its own destiny.",
1290
+ Tags: "SSI, Data-driven, Empowerment"
1291
+ }, {
1292
+ Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
1293
+ Tags: "No-CRUD, UI, Technical"
1294
+ }, {
1295
+ Slogan: "The smoothest path from DID to done.",
1296
+ Tags: "DID, Workflow, Chill"
1297
+ }, {
1298
+ Slogan: "Because your dApp deserves more than boilerplate.",
1299
+ Tags: "Blockchain, DevX, Efficiency"
1300
+ }, {
1301
+ Slogan: "Own your data. Own your flow.",
1302
+ Tags: "SSI, Control, Ownership"
1303
+ }, {
1304
+ Slogan: "Write logic like it belongs with the data — because it does.",
1305
+ Tags: "Data Logic, Developer, Smart"
1306
+ }, {
1307
+ Slogan: "From blockchain contracts to smarter frontends.",
1308
+ Tags: "Smart Contracts, UI, DX"
1309
+ }, {
1310
+ Slogan: "No caffeine. No boilerplate. Just the future.",
1311
+ Tags: "No-CRUD, Coffee-themed, Futuristic"
1312
+ }, {
1313
+ Slogan: "The future of web3 UX is Decaf-TS.",
1314
+ Tags: "Blockchain, UX, Vision"
1315
+ }, {
1316
+ Slogan: "Code with confidence. Govern with clarity.",
1317
+ Tags: "Blockchain, Governance, Calm"
1318
+ }, {
1319
+ Slogan: "Interfaces that obey the data, not the other way around.",
1320
+ Tags: "UI, Data Logic, Self-aware"
1321
+ }, {
1322
+ Slogan: "Brew business logic right into your bytes.",
1323
+ Tags: "Data Logic, Coffee-themed, Fun"
1324
+ }, {
1325
+ Slogan: "DIDs done differently — and delightfully.",
1326
+ Tags: "DID, Self-Sovereign, Playful"
1327
+ }, {
1328
+ Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
1329
+ Tags: "Blockchain, Smart Contracts, Tech"
1330
+ }, {
1331
+ Slogan: "Ship dApps without the stress.",
1332
+ Tags: "Blockchain, Cheerful, Developer"
1333
+ }, {
1334
+ Slogan: "No boilerplate, no problem — Decaf-TS your data.",
1335
+ Tags: "Data, No-CRUD, Chill"
1336
+ }, {
1337
+ Slogan: "From DID to UI, without breaking a sweat.",
1338
+ Tags: "DID, SSI, UI, Calm"
1339
+ }, {
1340
+ Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
1341
+ Tags: "Smart Contracts, DX, Magic"
1342
+ }, {
1343
+ Slogan: "Self-sovereign by design. Productive by default.",
1344
+ Tags: "SSI, Developer, Calm"
1345
+ }, {
1346
+ Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
1347
+ Tags: "Blockchain, Multi-platform, Happy"
1348
+ }, {
1349
+ Slogan: "Data that defines its own destiny.",
1350
+ Tags: "SSI, Data-driven, Empowerment"
1351
+ }, {
1352
+ Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
1353
+ Tags: "No-CRUD, UI, Technical"
1354
+ }, {
1355
+ Slogan: "The smoothest path from DID to done.",
1356
+ Tags: "DID, Workflow, Chill"
1357
+ }, {
1358
+ Slogan: "Because your dApp deserves more than boilerplate.",
1359
+ Tags: "Blockchain, DevX, Efficiency"
1360
+ }, {
1361
+ Slogan: "Own your data. Own your flow.",
1362
+ Tags: "SSI, Control, Ownership"
1363
+ }, {
1364
+ Slogan: "Write logic like it belongs with the data — because it does.",
1365
+ Tags: "Data Logic, Developer, Smart"
1366
+ }, {
1367
+ Slogan: "From blockchain contracts to smarter frontends.",
1368
+ Tags: "Smart Contracts, UI, DX"
1369
+ }, {
1370
+ Slogan: "No caffeine. No boilerplate. Just the future.",
1371
+ Tags: "No-CRUD, Coffee-themed, Futuristic"
1372
+ }, {
1373
+ Slogan: "The future of web3 UX is Decaf-TS.",
1374
+ Tags: "Blockchain, UX, Vision"
1375
+ }, {
1376
+ Slogan: "Code with confidence. Govern with clarity.",
1377
+ Tags: "Blockchain, Governance, Calm"
1378
+ }, {
1379
+ Slogan: "Interfaces that obey the data, not the other way around.",
1380
+ Tags: "UI, Data Logic, Self-aware"
1381
+ }, {
1382
+ Slogan: "Brew business logic right into your bytes.",
1383
+ Tags: "Data Logic, Coffee-themed, Fun"
1384
+ }, {
1385
+ Slogan: "DIDs done differently — and delightfully.",
1386
+ Tags: "DID, Self-Sovereign, Playful"
1387
+ }, {
1388
+ Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
1389
+ Tags: "Blockchain, Smart Contracts, Tech"
1390
+ }, {
1391
+ Slogan: "Ship dApps without the stress.",
1392
+ Tags: "Blockchain, Cheerful, Developer"
1393
+ }, {
1394
+ Slogan: "No boilerplate, no problem — Decaf-TS your data.",
1395
+ Tags: "Data, No-CRUD, Chill"
1396
+ }, {
1397
+ Slogan: "From DID to UI, without breaking a sweat.",
1398
+ Tags: "DID, SSI, UI, Calm"
1399
+ }, {
1400
+ Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
1401
+ Tags: "Smart Contracts, DX, Magic"
1402
+ }, {
1403
+ Slogan: "Self-sovereign by design. Productive by default.",
1404
+ Tags: "SSI, Developer, Calm"
1405
+ }, {
1406
+ Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
1407
+ Tags: "Blockchain, Multi-platform, Happy"
1408
+ }, {
1409
+ Slogan: "Data that defines its own destiny.",
1410
+ Tags: "SSI, Data-driven, Empowerment"
1411
+ }, {
1412
+ Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
1413
+ Tags: "No-CRUD, UI, Technical"
1414
+ }, {
1415
+ Slogan: "The smoothest path from DID to done.",
1416
+ Tags: "DID, Workflow, Chill"
1417
+ }, {
1418
+ Slogan: "Because your dApp deserves more than boilerplate.",
1419
+ Tags: "Blockchain, DevX, Efficiency"
1420
+ }, {
1421
+ Slogan: "Own your data. Own your flow.",
1422
+ Tags: "SSI, Control, Ownership"
1423
+ }, {
1424
+ Slogan: "Write logic like it belongs with the data — because it does.",
1425
+ Tags: "Data Logic, Developer, Smart"
1426
+ }, {
1427
+ Slogan: "From blockchain contracts to smarter frontends.",
1428
+ Tags: "Smart Contracts, UI, DX"
1429
+ }, {
1430
+ Slogan: "No caffeine. No boilerplate. Just the future.",
1431
+ Tags: "No-CRUD, Coffee-themed, Futuristic"
1432
+ }, {
1433
+ Slogan: "The future of web3 UX is Decaf-TS.",
1434
+ Tags: "Blockchain, UX, Vision"
1435
+ }, {
1436
+ Slogan: "Code with confidence. Govern with clarity.",
1437
+ Tags: "Blockchain, Governance, Calm"
1438
+ }, {
1439
+ Slogan: "Interfaces that obey the data, not the other way around.",
1440
+ Tags: "UI, Data Logic, Self-aware"
1441
+ }, {
1442
+ Slogan: "Brew business logic right into your bytes.",
1443
+ Tags: "Data Logic, Coffee-themed, Fun"
1444
+ }, {
1445
+ Slogan: "DIDs done differently — and delightfully.",
1446
+ Tags: "DID, Self-Sovereign, Playful"
1447
+ }, {
1448
+ Slogan: "Decaf-TS-TS: Where blockchain contracts meet smart interfaces.",
1449
+ Tags: "Blockchain, Smart Contracts, Tech"
1450
+ }, {
1451
+ Slogan: "Ship dApps without the stress.",
1452
+ Tags: "Blockchain, Cheerful, Developer"
1453
+ }, {
1454
+ Slogan: "No boilerplate, no problem — Decaf-TS your data.",
1455
+ Tags: "Data, No-CRUD, Chill"
1456
+ }, {
1457
+ Slogan: "From DID to UI, without breaking a sweat.",
1458
+ Tags: "DID, SSI, UI, Calm"
1459
+ }, {
1460
+ Slogan: "Decaf-TS-TS: Your frontend already understands your blockchain contract.",
1461
+ Tags: "Smart Contracts, DX, Magic"
1462
+ }, {
1463
+ Slogan: "Self-sovereign by design. Productive by default.",
1464
+ Tags: "SSI, Developer, Calm"
1465
+ }, {
1466
+ Slogan: "Build once. Deploy everywhere. Decentralized and delightful.",
1467
+ Tags: "Blockchain, Multi-platform, Happy"
1468
+ }, {
1469
+ Slogan: "Data that defines its own destiny.",
1470
+ Tags: "SSI, Data-driven, Empowerment"
1471
+ }, {
1472
+ Slogan: "Goodbye boilerplate, hello intent-based interfaces.",
1473
+ Tags: "No-CRUD, UI, Technical"
1474
+ }, {
1475
+ Slogan: "The smoothest path from DID to done.",
1476
+ Tags: "DID, Workflow, Chill"
1477
+ }, {
1478
+ Slogan: "Because your dApp deserves more than boilerplate.",
1479
+ Tags: "Blockchain, DevX, Efficiency"
1480
+ }, {
1481
+ Slogan: "Own your data. Own your flow.",
1482
+ Tags: "SSI, Control, Ownership"
1483
+ }, {
1484
+ Slogan: "Write logic like it belongs with the data — because it does.",
1485
+ Tags: "Data Logic, Developer, Smart"
1486
+ }, {
1487
+ Slogan: "From blockchain contracts to smarter frontends.",
1488
+ Tags: "Smart Contracts, UI, DX"
1489
+ }, {
1490
+ Slogan: "No caffeine. No boilerplate. Just the future.",
1491
+ Tags: "No-CRUD, Coffee-themed, Futuristic"
1492
+ }, {
1493
+ Slogan: "The future of web3 UX is Decaf-TS.",
1494
+ Tags: "Blockchain, UX, Vision"
1495
+ }, {
1496
+ Slogan: "Code with confidence. Govern with clarity.",
1497
+ Tags: "Blockchain, Governance, Calm"
1498
+ }, {
1499
+ Slogan: "Interfaces that obey the data, not the other way around.",
1500
+ Tags: "UI, Data Logic, Self-aware"
1501
+ }, {
1502
+ Slogan: "Brew business logic right into your bytes.",
1503
+ Tags: "Data Logic, Coffee-themed, Fun"
1504
+ }, {
1505
+ Slogan: "DIDs done differently — and delightfully.",
1506
+ Tags: "DID, Self-Sovereign, Playful"
1507
+ } ];
1508
+
1509
+ const colors = [ "", "", "", "", "", "", "", "", "" ];
1510
+
1511
+ function printBanner(logger) {
1512
+ const message = getSlogan();
1513
+ const banner = `# ░▒▓███████▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓██████▓▒░ ░▒▓████████▓▒░ ░▒▓████████▓▒░ ░▒▓███████▓▒░ \n# ( ( ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# ) ) ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# [=======] ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓██████▓▒░ \n# \`-----´ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ \n# ░▒▓███████▓▒░ ░▒▓████████▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓███████▓▒░ \n#`.split("\n");
1514
+ const maxLength = banner.reduce((max, line) => Math.max(max, line.length), 0);
1515
+ banner.push(`# ${message.padStart(maxLength - 3)}`);
1516
+ banner.forEach((line, index) => {
1517
+ (logger ? logger.info.bind(logger) : console.log.bind(console))(style(line || "").raw(colors[index]).text);
1518
+ });
1519
+ }
1520
+
1521
+ function getSlogan(i) {
1522
+ try {
1523
+ i = typeof i === "undefined" ? Math.floor(Math.random() * slogans.length) : i;
1524
+ return slogans[i].Slogan;
1525
+ } catch (error) {
1526
+ throw new Error(`Failed to retrieve slogans: ${error}`);
1527
+ }
1528
+ }
1529
+
1530
+ class Command extends LoggedClass {
1531
+ constructor(name, inputs = {}, requirements = []) {
1532
+ super();
1533
+ this.name = name;
1534
+ this.inputs = inputs;
1535
+ this.requirements = requirements;
1536
+ if (!Command.log) {
1537
+ Object.defineProperty(Command, "log", {
1538
+ writable: false,
1539
+ value: Logging.for(Command.name)
1540
+ });
1541
+ }
1542
+ this.inputs = Object.assign({}, DefaultCommandOptions, inputs);
1543
+ }
1544
+ async checkRequirements() {
1545
+ const {prod: prod, dev: dev, peer: peer} = await getDependencies();
1546
+ const missing = [];
1547
+ const fullList = Array.from(new Set([ ...prod, ...dev, ...peer ]).values()).map(d => d.name);
1548
+ for (const dep of this.requirements) if (!fullList.includes(dep)) missing.push(dep);
1549
+ if (!missing.length) return;
1550
+ }
1551
+ help(args) {
1552
+ return this.log.info(`This is help. I'm no use because I should have been overridden.`);
1553
+ }
1554
+ async execute() {
1555
+ const args = UserInput.parseArgs(this.inputs);
1556
+ const env = LoggedEnvironment.accumulate(DefaultCommandValues).accumulate(args.values);
1557
+ const {version: version, help: help, banner: banner} = env;
1558
+ if (version) {
1559
+ return getPackageVersion();
1560
+ }
1561
+ if (help) {
1562
+ return this.help(args);
1563
+ }
1564
+ if (banner) printBanner(this.log.for(printBanner, {
1565
+ timestamp: false,
1566
+ style: false,
1567
+ context: false,
1568
+ logLevel: false
1569
+ }));
1570
+ let result;
1571
+ try {
1572
+ result = await this.run(env);
1573
+ } catch (e) {
1574
+ throw e;
1575
+ }
1576
+ return result;
1577
+ }
1578
+ }
1579
+
1580
+ class HttpClient {
1581
+ static {
1582
+ this.log = Logging.for(HttpClient);
1583
+ }
1584
+ static async downloadFile(url) {
1585
+ return new Promise((resolve, reject) => {
1586
+ function request(url) {
1587
+ url = encodeURI(url);
1588
+ https.get(url, res => {
1589
+ if (res.statusCode === 301 || res.statusCode === 307) return request(res.headers.location);
1590
+ if (res.statusCode !== 200) {
1591
+ HttpClient.log.error(`Failed to fetch ${url} (status: ${res.statusCode})`);
1592
+ return reject(new Error(`Failed to fetch ${url}`));
1593
+ }
1594
+ let data = "";
1595
+ res.on("data", chunk => {
1596
+ data += chunk;
1597
+ });
1598
+ res.on("error", error => {
1599
+ reject(error);
1600
+ });
1601
+ res.on("end", () => {
1602
+ resolve(data);
1603
+ });
1604
+ });
1605
+ }
1606
+ request(url);
1607
+ });
1608
+ }
1609
+ }
1610
+
1611
+ const defaultCanvasOptions = {
1612
+ width: 1200,
1613
+ height: 260,
1614
+ padding: 32,
1615
+ backgroundColor: "#0f172a",
1616
+ headerFont: "bold 18px 'Segoe UI', sans-serif",
1617
+ rowFont: "14px 'Segoe UI', sans-serif",
1618
+ headerColor: "#f8fafc",
1619
+ rowColor: "#cbd5f5"
1620
+ };
1621
+
1622
+ const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
1623
+
1624
+ const perfDebugEnabled = process.env.PERF_VERBOSE === "true";
1625
+
1626
+ const debugLog = (...args) => {
1627
+ if (perfDebugEnabled) {
1628
+ console.debug(...args);
1629
+ }
1630
+ };
1631
+
1632
+ const formatTable = (title, headers, rows) => {
1633
+ const columnWidths = headers.map((header, index) => Math.max(header.length, ...rows.map(row => row[index]?.length ?? 0)));
1634
+ const formatRow = values => "| " + values.map((value, index) => value.padEnd(columnWidths[index])).join(" | ") + " |";
1635
+ const headerLine = formatRow(headers);
1636
+ const divider = "| " + columnWidths.map(width => "-".repeat(width)).join(" | ") + " |";
1637
+ const body = rows.map(formatRow).join("\n");
1638
+ return `${title}\n${headerLine}\n${divider}\n${body}`;
1639
+ };
1640
+
1641
+ const ensureDirectory = async targetPath => {
1642
+ await mkdir(path.dirname(targetPath), {
1643
+ recursive: true
1644
+ });
1645
+ };
1646
+
1647
+ const renderMetricsTableToCanvas = async (headers, rows, options, outputPath) => {
1648
+ const config = {
1649
+ ...defaultCanvasOptions,
1650
+ ...options
1651
+ };
1652
+ let createCanvas;
1653
+ try {
1654
+ const canvasModule = await import("canvas");
1655
+ createCanvas = canvasModule.createCanvas;
1656
+ } catch (error) {
1657
+ console.warn("[PerfRunner] Canvas module not available, skipping chart.", error);
1658
+ return;
1659
+ }
1660
+ const canvas = createCanvas(config.width, config.height);
1661
+ const ctx = canvas.getContext("2d");
1662
+ ctx.fillStyle = config.backgroundColor;
1663
+ ctx.fillRect(0, 0, config.width, config.height);
1664
+ ctx.font = config.headerFont;
1665
+ ctx.fillStyle = config.headerColor;
1666
+ const columnWidth = (config.width - config.padding * 2) / headers.length;
1667
+ const headerY = config.padding + 24;
1668
+ headers.forEach((header, index) => {
1669
+ ctx.fillText(header, config.padding + columnWidth * index, headerY);
1670
+ });
1671
+ ctx.font = config.rowFont;
1672
+ ctx.fillStyle = config.rowColor;
1673
+ const rowHeight = 24;
1674
+ rows.forEach((row, rowIndex) => {
1675
+ const y = headerY + 12 + rowHeight * (rowIndex + 1);
1676
+ row.forEach((cell, cellIndex) => {
1677
+ ctx.fillText(cell, config.padding + columnWidth * cellIndex, y);
1678
+ });
1679
+ });
1680
+ await ensureDirectory(outputPath);
1681
+ await writeFile$1(outputPath, canvas.toBuffer("image/png"));
1682
+ console.log(`Stored performance chart at ${outputPath}`);
1683
+ };
1684
+
1685
+ class PerformanceRunner {
1686
+ constructor(scenario) {
1687
+ this.scenario = scenario;
1688
+ }
1689
+ async run() {
1690
+ if (this.scenario.initialize) {
1691
+ await this.scenario.initialize();
1692
+ }
1693
+ let phaseCounter = 0;
1694
+ const queue = this.scenario.phases.map(phase => ({
1695
+ phase: phase,
1696
+ phaseNumber: ++phaseCounter
1697
+ }));
1698
+ const results = [];
1699
+ while (queue.length) {
1700
+ const item = queue.shift();
1701
+ const phase = item.phase;
1702
+ const context = this.mergeContext(phase);
1703
+ console.info(`[PerfRunner] Starting phase #${item.phaseNumber} "${phase.name}"`, {
1704
+ iterations: phase.config.iterations,
1705
+ mode: phase.config.mode,
1706
+ concurrency: phase.config.concurrency,
1707
+ burst: phase.config.burst
1708
+ });
1709
+ const result = await this.runPhase(phase, context);
1710
+ console.info(`[PerfRunner] Completed phase #${item.phaseNumber} "${phase.name}"`, {
1711
+ total: result.aggregated.totalDurationMs.toFixed(2),
1712
+ avg: result.aggregated.averageMs.toFixed(2),
1713
+ failureCount: result.aggregated.failureCount
1714
+ });
1715
+ results.push(result);
1716
+ if (phase.generator) {
1717
+ const historySnapshot = [ ...results ];
1718
+ const metadata = {
1719
+ phaseNumber: item.phaseNumber,
1720
+ phaseName: phase.name,
1721
+ iterationCount: phase.config.iterations,
1722
+ burstSegments: result.segmentCount,
1723
+ segmentCount: result.segmentCount,
1724
+ mode: phase.config.mode,
1725
+ history: historySnapshot
1726
+ };
1727
+ const generatorResult = await phase.generator({
1728
+ result: result,
1729
+ history: historySnapshot,
1730
+ metadata: metadata
1731
+ });
1732
+ if (generatorResult) {
1733
+ const nextPhase = "config" in generatorResult ? {
1734
+ name: generatorResult.name ?? `${phase.name} → gen`,
1735
+ config: generatorResult.config,
1736
+ generator: phase.generator
1737
+ } : {
1738
+ name: `${phase.name} → gen`,
1739
+ config: generatorResult,
1740
+ generator: phase.generator
1741
+ };
1742
+ queue.push({
1743
+ phase: nextPhase,
1744
+ phaseNumber: ++phaseCounter
1745
+ });
1746
+ }
1747
+ }
1748
+ }
1749
+ await this.logSummary(results);
1750
+ return results;
1751
+ }
1752
+ async runPhase(phase, context) {
1753
+ await this.runWarmup(phase, context);
1754
+ const segments = this.buildSegmentIndices(phase.config.iterations, phase.config.burst);
1755
+ const collected = [];
1756
+ for (let segmentIndex = 0; segmentIndex < segments.length; segmentIndex += 1) {
1757
+ const indices = segments[segmentIndex];
1758
+ if (!indices.length) {
1759
+ continue;
1760
+ }
1761
+ debugLog(`[PerfRunner] Phase "${phase.name}" executing segment ${segmentIndex + 1}/${segments.length} (iterations ${indices[0]}-${indices[indices.length - 1]})`);
1762
+ const metrics = await this.executeSegment(this.scenario.handler, phase.config, context, indices);
1763
+ collected.push(...metrics);
1764
+ const burstInterval = phase.config.burst?.intervalMs;
1765
+ if (burstInterval && segmentIndex < segments.length - 1) {
1766
+ await delay(burstInterval);
1767
+ }
1768
+ }
1769
+ const sorted = [ ...collected ].sort((a, b) => a.iteration - b.iteration);
1770
+ const aggregated = this.aggregateMetrics(sorted);
1771
+ if (phase.config.pauseAfterMs) {
1772
+ await delay(phase.config.pauseAfterMs);
1773
+ }
1774
+ if (aggregated.failureCount > 0 && this.scenario.failOnError !== false) {
1775
+ throw new Error(`Phase ${phase.name} recorded ${aggregated.failureCount} failures`);
1776
+ }
1777
+ return {
1778
+ phase: phase,
1779
+ config: phase.config,
1780
+ iterationMetrics: sorted,
1781
+ aggregated: aggregated,
1782
+ context: context,
1783
+ segmentCount: segments.length
1784
+ };
1785
+ }
1786
+ async runWarmup(phase, context) {
1787
+ const warmup = phase.config.warmup;
1788
+ if (!warmup?.iterations) {
1789
+ return;
1790
+ }
1791
+ const handler = warmup.handler ?? this.scenario.handler;
1792
+ for (let index = 0; index < warmup.iterations; index += 1) {
1793
+ await handler({
1794
+ iteration: index,
1795
+ config: phase.config,
1796
+ loadFactor: this.computeLoadFactor(phase.config, index),
1797
+ context: context
1798
+ });
1799
+ if (warmup.delayBetweenIterationsMs && index < warmup.iterations - 1) {
1800
+ await delay(warmup.delayBetweenIterationsMs);
1801
+ }
1802
+ }
1803
+ }
1804
+ computeLoadFactor(config, iteration) {
1805
+ const base = config.loadStart ?? 1;
1806
+ const step = config.loadStep ?? 0;
1807
+ const multiplier = config.loadMultiplier ?? 1;
1808
+ return (base + step * iteration) * multiplier;
1809
+ }
1810
+ buildSegmentIndices(iterations, burst) {
1811
+ const total = Math.max(0, iterations);
1812
+ if (total === 0) {
1813
+ return [];
1814
+ }
1815
+ const chunk = burst?.size && burst.size > 0 ? Math.min(burst.size, total) : total;
1816
+ const segments = [];
1817
+ for (let cursor = 0; cursor < total; cursor += chunk) {
1818
+ const end = Math.min(total, cursor + chunk);
1819
+ segments.push(Array.from({
1820
+ length: end - cursor
1821
+ }, (_, idx) => cursor + idx));
1822
+ }
1823
+ return segments;
1824
+ }
1825
+ mergeContext(phase) {
1826
+ const baseContext = this.scenario.baseContext ?? {};
1827
+ const phaseContext = phase.config.context ?? {};
1828
+ return this.mergeContexts(baseContext, phaseContext);
1829
+ }
1830
+ mergeContexts(a, b) {
1831
+ return Object.assign({}, a, b);
1832
+ }
1833
+ async executeSegment(handler, config, context, indices) {
1834
+ if (!indices.length) {
1835
+ return [];
1836
+ }
1837
+ if (config.mode === "concurrent") {
1838
+ return this.collectConcurrent(handler, config, context, indices);
1839
+ }
1840
+ return this.collectSequential(handler, config, context, indices);
1841
+ }
1842
+ async collectSequential(handler, config, context, indices) {
1843
+ const metrics = [];
1844
+ const delayBetween = config.delayBetweenIterationsMs;
1845
+ for (let idx = 0; idx < indices.length; idx += 1) {
1846
+ metrics.push(await this.runIteration(handler, config, context, indices[idx]));
1847
+ if (delayBetween && idx < indices.length - 1) {
1848
+ await delay(delayBetween);
1849
+ }
1850
+ }
1851
+ return metrics;
1852
+ }
1853
+ async collectConcurrent(handler, config, context, indices) {
1854
+ const concurrency = Math.max(1, Math.min(config.concurrency ?? indices.length, indices.length));
1855
+ const metrics = [];
1856
+ let pointer = 0;
1857
+ const worker = async () => {
1858
+ while (pointer < indices.length) {
1859
+ const iteration = indices[pointer];
1860
+ pointer += 1;
1861
+ metrics.push(await this.runIteration(handler, config, context, iteration));
1862
+ }
1863
+ };
1864
+ await Promise.all(Array.from({
1865
+ length: concurrency
1866
+ }, () => worker()));
1867
+ return metrics;
1868
+ }
1869
+ async runIteration(handler, config, context, iteration) {
1870
+ const loadFactor = this.computeLoadFactor(config, iteration);
1871
+ const stopwatch = new StopWatch(true);
1872
+ let success = true;
1873
+ let meta;
1874
+ debugLog(`[PerfRunner] Iteration ${iteration} (phase=${config.metadata?.phaseName ?? "n/a"}, load=${loadFactor.toFixed(2)}) starting`);
1875
+ try {
1876
+ const result = await handler({
1877
+ iteration: iteration,
1878
+ config: config,
1879
+ loadFactor: loadFactor,
1880
+ context: context
1881
+ });
1882
+ if (typeof result?.success === "boolean") {
1883
+ success = result.success;
1884
+ }
1885
+ meta = result?.meta;
1886
+ } catch (error) {
1887
+ success = false;
1888
+ meta = {
1889
+ error: error instanceof Error ? error.message : String(error)
1890
+ };
1891
+ }
1892
+ const durationMs = stopwatch.stop();
1893
+ debugLog(`[PerfRunner] Iteration ${iteration} complete in ${durationMs.toFixed(2)}ms, success=${success}`);
1894
+ return {
1895
+ iteration: iteration,
1896
+ durationMs: durationMs,
1897
+ success: success,
1898
+ meta: meta,
1899
+ loadFactor: loadFactor
1900
+ };
1901
+ }
1902
+ aggregateMetrics(metrics) {
1903
+ if (metrics.length === 0) {
1904
+ return {
1905
+ totalDurationMs: 0,
1906
+ minMs: 0,
1907
+ maxMs: 0,
1908
+ averageMs: 0,
1909
+ successCount: 0,
1910
+ failureCount: 0,
1911
+ loadStart: 0,
1912
+ loadEnd: 0
1913
+ };
1914
+ }
1915
+ const totalDurationMs = metrics.reduce((acc, metric) => acc + metric.durationMs, 0);
1916
+ const minMs = Math.min(...metrics.map(metric => metric.durationMs));
1917
+ const maxMs = Math.max(...metrics.map(metric => metric.durationMs));
1918
+ const averageMs = totalDurationMs / metrics.length;
1919
+ const successCount = metrics.filter(metric => metric.success).length;
1920
+ const failureCount = metrics.length - successCount;
1921
+ const loadStart = metrics[0]?.loadFactor ?? 0;
1922
+ const loadEnd = metrics[metrics.length - 1]?.loadFactor ?? loadStart;
1923
+ return {
1924
+ totalDurationMs: totalDurationMs,
1925
+ minMs: minMs,
1926
+ maxMs: maxMs,
1927
+ averageMs: averageMs,
1928
+ successCount: successCount,
1929
+ failureCount: failureCount,
1930
+ loadStart: loadStart,
1931
+ loadEnd: loadEnd
1932
+ };
1933
+ }
1934
+ async logSummary(results) {
1935
+ if (!results.length) {
1936
+ return;
1937
+ }
1938
+ const headers = [ "Phase", "Mode", "Iterations", "Total ms", "Avg ms", "Min ms", "Max ms", "Success", "Failures", "Load range" ];
1939
+ const rows = results.map(result => [ result.phase.name, result.config.mode, result.config.iterations.toString(), result.aggregated.totalDurationMs.toFixed(2), result.aggregated.averageMs.toFixed(2), result.aggregated.minMs.toFixed(2), result.aggregated.maxMs.toFixed(2), result.aggregated.successCount.toString(), result.aggregated.failureCount.toString(), `${result.aggregated.loadStart.toFixed(2)} → ${result.aggregated.loadEnd.toFixed(2)}` ]);
1940
+ console.log(formatTable(`Performance summary for ${this.scenario.name}`, headers, rows));
1941
+ if (this.shouldRenderCanvas()) {
1942
+ const chartPath = this.scenario.canvasOutputPath ?? path.join(process.cwd(), "workdocs", "reports", "performance-runner.png");
1943
+ await renderMetricsTableToCanvas(headers, rows, this.scenario.canvasOptions ?? defaultCanvasOptions, chartPath);
1944
+ }
1945
+ }
1946
+ shouldRenderCanvas() {
1947
+ return this.scenario.enableCanvas ?? Boolean(this.scenario.canvasOptions);
1948
+ }
1949
+ }
1950
+
1951
+ function parseList(input) {
1952
+ if (!input) return [];
1953
+ if (Array.isArray(input)) return input.map(i => `${i}`.trim()).filter(Boolean);
1954
+ return `${input}`.split(",").map(p => p.trim()).filter(Boolean);
1955
+ }
1956
+
1957
+ function packageToGlobal(name) {
1958
+ const withoutScope = name.replace(/^@/, "");
1959
+ const parts = withoutScope.split(/[/\-_.]+/).filter(Boolean);
1960
+ return parts.map((p, i) => i === 0 ? p.replace(/[^a-zA-Z0-9]/g, "") : `${p.charAt(0).toUpperCase()}${p.slice(1)}`).join("");
1961
+ }
1962
+
1963
+ function getPackageDependencies() {
1964
+ let pkg;
1965
+ try {
1966
+ pkg = getPackage(process.cwd());
1967
+ } catch {
1968
+ pkg = undefined;
1969
+ }
1970
+ try {
1971
+ const hasDeps = pkg && (Object.keys(pkg.dependencies || {}).length > 0 || Object.keys(pkg.devDependencies || {}).length > 0 || Object.keys(pkg.peerDependencies || {}).length > 0);
1972
+ if (!hasDeps) {
1973
+ const fallbackDir = path.resolve(__dirname, "../../..");
1974
+ try {
1975
+ pkg = getPackage(fallbackDir);
1976
+ } catch {}
1977
+ }
1978
+ } catch {}
1979
+ const deps = Object.keys(pkg && pkg.dependencies || {});
1980
+ const peer = Object.keys(pkg && pkg.peerDependencies || {});
1981
+ const dev = Object.keys(pkg && pkg.devDependencies || {});
1982
+ return Array.from(new Set([ ...deps, ...peer, ...dev ]));
1983
+ }
1984
+
1985
+ const VERSION_STRING = "##VERSION##";
1986
+
1987
+ const PACKAGE_STRING = "##PACKAGE##";
1988
+
1989
+ const PACKAGE_SIZE_STRING = "##PACKAGE_SIZE##";
1990
+
1991
+ var Modes;
1992
+
1993
+ (function(Modes) {
1994
+ Modes["CJS"] = "commonjs";
1995
+ Modes["ESM"] = "es2022";
1996
+ })(Modes || (Modes = {}));
1997
+
1998
+ var BuildMode;
1999
+
2000
+ (function(BuildMode) {
2001
+ BuildMode["BUILD"] = "build";
2002
+ BuildMode["BUNDLE"] = "bundle";
2003
+ BuildMode["ALL"] = "all";
2004
+ })(BuildMode || (BuildMode = {}));
2005
+
2006
+ const options$1 = {
2007
+ prod: {
2008
+ type: "boolean",
2009
+ default: false
2010
+ },
2011
+ dev: {
2012
+ type: "boolean",
2013
+ default: false
2014
+ },
2015
+ buildMode: {
2016
+ type: "string",
2017
+ default: BuildMode.ALL
2018
+ },
2019
+ includes: {
2020
+ type: "string",
2021
+ default: ""
2022
+ },
2023
+ externals: {
2024
+ type: "string",
2025
+ default: ""
2026
+ },
2027
+ docs: {
2028
+ type: "boolean",
2029
+ default: false
2030
+ },
2031
+ commands: {
2032
+ type: "boolean",
2033
+ default: false
2034
+ },
2035
+ entry: {
2036
+ type: "string",
2037
+ default: "./src/index.ts"
2038
+ },
2039
+ banner: {
2040
+ type: "boolean",
2041
+ default: false
2042
+ }
2043
+ };
2044
+
2045
+ const cjs2Transformer = (ext = ".cjs") => {
2046
+ const log = BuildScripts.log.for(cjs2Transformer);
2047
+ const resolutionCache = new Map;
2048
+ return transformationContext => sourceFile => {
2049
+ const sourceDir = path.dirname(sourceFile.fileName);
2050
+ function resolvePath(importPath) {
2051
+ const cacheKey = JSON.stringify([ sourceDir, importPath ]);
2052
+ const cachedValue = resolutionCache.get(cacheKey);
2053
+ if (cachedValue != null) return cachedValue;
2054
+ let resolvedPath = importPath;
2055
+ try {
2056
+ resolvedPath = path.resolve(sourceDir, resolvedPath + ".ts");
2057
+ } catch (error) {
2058
+ throw new Error(`Failed to resolve path ${importPath}: ${error}`);
2059
+ }
2060
+ let stat;
2061
+ try {
2062
+ stat = fs.statSync(resolvedPath);
2063
+ } catch (e) {
2064
+ try {
2065
+ log.verbose(`Testing existence of path ${resolvedPath} as a folder defaulting to index file`);
2066
+ stat = fs.statSync(resolvedPath.replace(/\.ts$/gm, ""));
2067
+ } catch (e2) {
2068
+ throw new Error(`Failed to resolve path ${importPath}: ${e}, ${e2}`);
2069
+ }
2070
+ }
2071
+ if (stat.isDirectory()) resolvedPath = resolvedPath.replace(/\.ts$/gm, "/index.ts");
2072
+ if (path.isAbsolute(resolvedPath)) {
2073
+ const extension = (/\.tsx?$/.exec(path.basename(resolvedPath)) || [])[0] || void 0;
2074
+ resolvedPath = "./" + path.relative(sourceDir, path.resolve(path.dirname(resolvedPath), path.basename(resolvedPath, extension) + ext));
2075
+ }
2076
+ resolutionCache.set(cacheKey, resolvedPath);
2077
+ return resolvedPath;
2078
+ }
2079
+ function visitNode(node) {
2080
+ if (shouldMutateModuleSpecifier(node)) {
2081
+ if (ts.isImportDeclaration(node)) {
2082
+ const resolvedPath = resolvePath(node.moduleSpecifier.text);
2083
+ const newModuleSpecifier = transformationContext.factory.createStringLiteral(resolvedPath);
2084
+ return transformationContext.factory.updateImportDeclaration(node, node.modifiers, node.importClause, newModuleSpecifier, undefined);
2085
+ } else if (ts.isExportDeclaration(node)) {
2086
+ const resolvedPath = resolvePath(node.moduleSpecifier.text);
2087
+ const newModuleSpecifier = transformationContext.factory.createStringLiteral(resolvedPath);
2088
+ return transformationContext.factory.updateExportDeclaration(node, node.modifiers, node.isTypeOnly, node.exportClause, newModuleSpecifier, undefined);
2089
+ }
2090
+ }
2091
+ return ts.visitEachChild(node, visitNode, transformationContext);
2092
+ }
2093
+ function shouldMutateModuleSpecifier(node) {
2094
+ if (!ts.isImportDeclaration(node) && !ts.isExportDeclaration(node)) return false;
2095
+ if (node.moduleSpecifier === undefined) return false;
2096
+ if (!ts.isStringLiteral(node.moduleSpecifier)) return false;
2097
+ if (!node.moduleSpecifier.text.startsWith("./") && !node.moduleSpecifier.text.startsWith("../")) return false;
2098
+ if (path.extname(node.moduleSpecifier.text) !== "") return false;
2099
+ return true;
2100
+ }
2101
+ return ts.visitNode(sourceFile, visitNode);
2102
+ };
2103
+ };
2104
+
2105
+ class BuildScripts extends Command {
2106
+ constructor() {
2107
+ super("BuildScripts", Object.assign({}, DefaultCommandOptions, options$1));
2108
+ this.replacements = {};
2109
+ const pkg = getPackage();
2110
+ const {name: name, version: version} = pkg;
2111
+ this.pkgName = name.includes("@") ? name.split("/")[1] : name;
2112
+ this.pkgVersion = version;
2113
+ this.replacements[VERSION_STRING] = this.pkgVersion;
2114
+ this.replacements[PACKAGE_STRING] = name;
2115
+ }
2116
+ patchFiles(p) {
2117
+ const log = this.log.for(this.patchFiles);
2118
+ const {name: name, version: version} = getPackage();
2119
+ log.info(`Patching ${name} ${version} module in ${p}...`);
2120
+ const stat = fs.statSync(p);
2121
+ if (stat.isDirectory()) fs.readdirSync(p, {
2122
+ withFileTypes: true,
2123
+ recursive: true
2124
+ }).filter(p => p.isFile()).forEach(file => patchFile(path.join(file.parentPath, file.name), Object.entries(this.replacements).reduce((acc, [key, val]) => {
2125
+ switch (key) {
2126
+ case VERSION_STRING:
2127
+ log.debug("Found VERSION string to replace");
2128
+ acc[`VERSION = "${VERSION_STRING}";`] = `VERSION = "${val}";`;
2129
+ break;
2130
+
2131
+ case PACKAGE_STRING:
2132
+ log.debug("Found PACKAGE_NAME string to replace");
2133
+ acc[`PACKAGE_NAME = "${PACKAGE_STRING}";`] = `PACKAGE_NAME = "${val}";`;
2134
+ break;
2135
+
2136
+ default:
2137
+ acc[key] = val;
2138
+ }
2139
+ return acc;
2140
+ }, {})));
2141
+ log.verbose(`Module ${name} ${version} patched in ${p}...`);
2142
+ }
2143
+ reportDiagnostics(diagnostics, logLevel) {
2144
+ const msg = this.formatDiagnostics(diagnostics);
2145
+ try {
2146
+ this.log[logLevel](msg);
2147
+ } catch (e) {
2148
+ console.warn(`Failed to get logger for ${logLevel}`);
2149
+ throw e;
2150
+ }
2151
+ return msg;
2152
+ }
2153
+ formatDiagnostics(diagnostics) {
2154
+ return diagnostics.map(diagnostic => {
2155
+ let message = "";
2156
+ if (diagnostic.file && diagnostic.start) {
2157
+ const {line: line, character: character} = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
2158
+ message += `${diagnostic.file.fileName} (${line + 1},${character + 1})`;
2159
+ }
2160
+ message += ": " + ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
2161
+ return message;
2162
+ }).join("\n");
2163
+ }
2164
+ readConfigFile(configFileName) {
2165
+ const configFileText = fs.readFileSync(configFileName).toString();
2166
+ const result = ts.parseConfigFileTextToJson(configFileName, configFileText);
2167
+ const configObject = result.config;
2168
+ if (!configObject) {
2169
+ this.reportDiagnostics([ result.error ], LogLevel.error);
2170
+ }
2171
+ const configParseResult = ts.parseJsonConfigFileContent(configObject, ts.sys, path.dirname(configFileName));
2172
+ if (configParseResult.errors.length > 0) this.reportDiagnostics(configParseResult.errors, LogLevel.error);
2173
+ return configParseResult;
2174
+ }
2175
+ evalDiagnostics(diagnostics) {
2176
+ if (diagnostics && diagnostics.length > 0) {
2177
+ const errors = diagnostics.filter(d => d.category === ts.DiagnosticCategory.Error);
2178
+ const warnings = diagnostics.filter(d => d.category === ts.DiagnosticCategory.Warning);
2179
+ const suggestions = diagnostics.filter(d => d.category === ts.DiagnosticCategory.Suggestion);
2180
+ const messages = diagnostics.filter(d => d.category === ts.DiagnosticCategory.Message);
2181
+ if (warnings.length) this.reportDiagnostics(warnings, LogLevel.warn);
2182
+ if (errors.length) {
2183
+ this.reportDiagnostics(diagnostics, LogLevel.error);
2184
+ throw new Error(`TypeScript reported ${diagnostics.length} diagnostic(s) during check; aborting.`);
2185
+ }
2186
+ if (suggestions.length) this.reportDiagnostics(suggestions, LogLevel.info);
2187
+ if (messages.length) this.reportDiagnostics(messages, LogLevel.info);
2188
+ }
2189
+ }
2190
+ preCheckDiagnostics(program) {
2191
+ const diagnostics = ts.getPreEmitDiagnostics(program);
2192
+ this.evalDiagnostics(diagnostics);
2193
+ }
2194
+ async checkTsDiagnostics(isDev, mode, bundle = false) {
2195
+ const log = this.log.for(this.checkTsDiagnostics);
2196
+ let tsConfig;
2197
+ try {
2198
+ tsConfig = this.readConfigFile("./tsconfig.json");
2199
+ } catch (e) {
2200
+ throw new Error(`Failed to parse tsconfig.json: ${e}`);
2201
+ }
2202
+ if (bundle) {
2203
+ tsConfig.options.module = ModuleKind.AMD;
2204
+ tsConfig.options.outDir = "dist";
2205
+ tsConfig.options.isolatedModules = false;
2206
+ tsConfig.options.outFile = this.pkgName;
2207
+ } else {
2208
+ tsConfig.options.outDir = `lib${mode === Modes.ESM ? "/esm" : ""}`;
2209
+ tsConfig.options.module = mode === Modes.ESM ? ModuleKind.ES2022 : ModuleKind.CommonJS;
2210
+ }
2211
+ tsConfig.options.inlineSourceMap = false;
2212
+ tsConfig.options.inlineSources = false;
2213
+ tsConfig.options.sourceMap = true;
2214
+ const program = ts.createProgram(tsConfig.fileNames, tsConfig.options);
2215
+ this.preCheckDiagnostics(program);
2216
+ log.verbose(`TypeScript checks passed (${bundle ? "bundle" : "normal"} mode).`);
2217
+ }
2218
+ async buildTs(isDev, mode, bundle = false) {
2219
+ const log = this.log.for(this.buildTs);
2220
+ log.info(`Building ${this.pkgName} ${this.pkgVersion} module (${mode}) in ${isDev ? "dev" : "prod"} mode...`);
2221
+ let tsConfig;
2222
+ try {
2223
+ tsConfig = this.readConfigFile("./tsconfig.json");
2224
+ } catch (e) {
2225
+ throw new Error(`Failed to parse tsconfig.json: ${e}`);
2226
+ }
2227
+ if (bundle) {
2228
+ tsConfig.options.module = ModuleKind.AMD;
2229
+ tsConfig.options.outDir = "dist";
2230
+ tsConfig.options.isolatedModules = false;
2231
+ tsConfig.options.outFile = this.pkgName;
2232
+ } else {
2233
+ tsConfig.options.outDir = `lib${mode === Modes.ESM ? "/esm" : ""}`;
2234
+ tsConfig.options.module = mode === Modes.ESM ? ModuleKind.ES2022 : ModuleKind.CommonJS;
2235
+ }
2236
+ if (isDev) {
2237
+ tsConfig.options.inlineSourceMap = true;
2238
+ tsConfig.options.inlineSources = true;
2239
+ tsConfig.options.sourceMap = false;
2240
+ } else {
2241
+ tsConfig.options.inlineSourceMap = false;
2242
+ tsConfig.options.inlineSources = false;
2243
+ tsConfig.options.sourceMap = true;
2244
+ }
2245
+ const program = ts.createProgram(tsConfig.fileNames, tsConfig.options);
2246
+ const transformations = {};
2247
+ if (mode === Modes.CJS) {
2248
+ transformations.before = [ cjs2Transformer(".cjs") ];
2249
+ } else if (mode === Modes.ESM) {
2250
+ transformations.before = [ cjs2Transformer(".js") ];
2251
+ }
2252
+ const emitResult = program.emit(undefined, undefined, undefined, undefined, transformations);
2253
+ const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
2254
+ this.evalDiagnostics(allDiagnostics);
2255
+ }
2256
+ async build(isDev, mode, bundle = false) {
2257
+ const log = this.log.for(this.build);
2258
+ await this.buildTs(isDev, mode, bundle);
2259
+ log.verbose(`Module ${this.pkgName} ${this.pkgVersion} (${mode}) built in ${isDev ? "dev" : "prod"} mode...`);
2260
+ if (mode === Modes.CJS && !bundle) {
2261
+ const files = getAllFiles("lib", file => file.endsWith(".js") && !file.includes("/esm/"));
2262
+ for (const file of files) {
2263
+ log.verbose(`Patching ${file}'s cjs imports...`);
2264
+ const f = file.replace(".js", ".cjs");
2265
+ await renameFile(file, f);
2266
+ }
2267
+ }
2268
+ }
2269
+ copyAssets(mode) {
2270
+ const log = this.log.for(this.copyAssets);
2271
+ let hasAssets = false;
2272
+ try {
2273
+ hasAssets = fs.statSync("./src/assets").isDirectory();
2274
+ } catch (e) {
2275
+ return log.verbose(`No assets found in ./src/assets to copy`);
2276
+ }
2277
+ if (hasAssets) copyFile("./src/assets", `./${mode === Modes.CJS ? "lib" : "dist"}/assets`);
2278
+ }
2279
+ async bundle(mode, isDev, isLib, entryFile = "./src/index.ts", nameOverride = this.pkgName, externalsArg, includeArg = [ "prompts", "styled-string-builder", "typed-object-accumulator", "@decaf-ts/logging" ]) {
2280
+ await this.checkTsDiagnostics(isDev, mode, true);
2281
+ const isEsm = mode === Modes.ESM;
2282
+ const pkgName = this.pkgName;
2283
+ const log = this.log;
2284
+ const include = Array.from(new Set([ ...parseList(includeArg) ]));
2285
+ let externalsList = parseList(externalsArg);
2286
+ if (externalsList.length === 0) {
2287
+ try {
2288
+ externalsList = listNodeModulesPackages(path.join(process.cwd(), "node_modules"));
2289
+ } catch {}
2290
+ if (!externalsList || externalsList.length === 0) {
2291
+ externalsList = getPackageDependencies();
2292
+ }
2293
+ }
2294
+ const ext = Array.from(new Set([ ...function builtinList() {
2295
+ try {
2296
+ return Array.isArray(builtinModules) ? builtinModules : [];
2297
+ } catch {
2298
+ return [ "fs", "path", "process", "child_process", "util", "https", "http", "os", "stream", "crypto", "zlib", "net", "tls", "url", "querystring", "assert", "events", "tty", "dns", "querystring" ];
2299
+ }
2300
+ }(), ...externalsList ]));
2301
+ const rollupSourceMapOutput = isDev ? "inline" : true;
2302
+ const plugins = [ typescript({
2303
+ compilerOptions: {
2304
+ module: "esnext",
2305
+ declaration: false,
2306
+ outDir: isLib ? "bin" : "dist",
2307
+ sourceMap: isDev ? false : true,
2308
+ inlineSourceMap: isDev ? true : false,
2309
+ inlineSources: isDev ? true : false
2310
+ },
2311
+ include: [ "src/**/*.ts" ],
2312
+ exclude: [ "node_modules", "**/*.spec.ts" ],
2313
+ tsconfig: "./tsconfig.json"
2314
+ }), json() ];
2315
+ if (isLib) {
2316
+ plugins.push(commonjs({
2317
+ include: [],
2318
+ exclude: externalsList
2319
+ }), nodeResolve({
2320
+ resolveOnly: include
2321
+ }));
2322
+ }
2323
+ try {
2324
+ const terserMod = await import("@rollup/plugin-terser");
2325
+ const terserFn = terserMod && terserMod.terser || terserMod.default || terserMod;
2326
+ const terserOptionsDev = {
2327
+ parse: {
2328
+ ecma: 2020
2329
+ },
2330
+ compress: false,
2331
+ mangle: false,
2332
+ format: {
2333
+ comments: false,
2334
+ beautify: true
2335
+ }
2336
+ };
2337
+ const terserOptionsProd = {
2338
+ parse: {
2339
+ ecma: 2020
2340
+ },
2341
+ compress: {
2342
+ ecma: 2020,
2343
+ passes: 5,
2344
+ drop_console: true,
2345
+ drop_debugger: true,
2346
+ toplevel: true,
2347
+ module: isEsm,
2348
+ unsafe: true,
2349
+ unsafe_arrows: true,
2350
+ unsafe_comps: true,
2351
+ collapse_vars: true,
2352
+ reduce_funcs: true,
2353
+ reduce_vars: true
2354
+ },
2355
+ mangle: {
2356
+ toplevel: true
2357
+ },
2358
+ format: {
2359
+ comments: false,
2360
+ ascii_only: true
2361
+ },
2362
+ toplevel: true
2363
+ };
2364
+ plugins.push(terserFn(isDev ? terserOptionsDev : terserOptionsProd));
2365
+ } catch {}
2366
+ const input = {
2367
+ input: entryFile,
2368
+ plugins: plugins,
2369
+ external: ext,
2370
+ onwarn: undefined,
2371
+ treeshake: !isDev
2372
+ };
2373
+ const globals = {};
2374
+ ext.forEach(e => {
2375
+ globals[e] = packageToGlobal(e);
2376
+ });
2377
+ const outputs = [ {
2378
+ file: `${isLib ? "bin/" : "dist/"}${nameOverride ? nameOverride : `.bundle.${!isDev ? "min" : ""}`}${isEsm ? ".js" : ".cjs"}`,
2379
+ format: isLib ? "cjs" : isEsm ? "esm" : "umd",
2380
+ name: pkgName,
2381
+ esModule: isEsm,
2382
+ sourcemap: rollupSourceMapOutput,
2383
+ globals: globals,
2384
+ exports: "auto"
2385
+ } ];
2386
+ try {
2387
+ const bundle = await rollup(input);
2388
+ log.verbose(bundle.watchFiles);
2389
+ async function generateOutputs(bundle) {
2390
+ for (const outputOptions of outputs) {
2391
+ await bundle.write(outputOptions);
2392
+ }
2393
+ }
2394
+ await generateOutputs(bundle);
2395
+ } catch (e) {
2396
+ throw new Error(`Failed to bundle: ${e}`);
2397
+ }
2398
+ }
2399
+ async buildByEnv(entryFile = "./src/index.ts", isDev, mode = BuildMode.ALL, includesArg, externalsArg) {
2400
+ try {
2401
+ deletePath("lib");
2402
+ } catch (e) {}
2403
+ try {
2404
+ deletePath("dist");
2405
+ } catch (e) {}
2406
+ if ([ BuildMode.ALL, BuildMode.BUILD ].includes(mode)) {
2407
+ fs.mkdirSync("lib");
2408
+ await this.build(isDev, Modes.ESM);
2409
+ await this.build(isDev, Modes.CJS);
2410
+ this.patchFiles("lib");
2411
+ }
2412
+ if ([ BuildMode.ALL, BuildMode.BUNDLE ].includes(mode)) {
2413
+ fs.mkdirSync("dist");
2414
+ await this.bundle(Modes.ESM, isDev, false, entryFile || "./src/index.ts", this.pkgName, externalsArg, includesArg);
2415
+ await this.bundle(Modes.CJS, isDev, false, entryFile || "./src/index.ts", this.pkgName, externalsArg, includesArg);
2416
+ this.patchFiles("dist");
2417
+ }
2418
+ this.copyAssets(Modes.CJS);
2419
+ this.copyAssets(Modes.ESM);
2420
+ }
2421
+ async buildDev(entryFile = "./src/index.ts", mode = BuildMode.ALL, includesArg, externalsArg) {
2422
+ return this.buildByEnv(entryFile, true, mode, includesArg, externalsArg);
2423
+ }
2424
+ async buildProd(entryFile = "./src/index.ts", mode = BuildMode.ALL, includesArg, externalsArg) {
2425
+ return this.buildByEnv(entryFile, false, mode, includesArg, externalsArg);
2426
+ }
2427
+ async buildDocs() {
2428
+ await runCommand(`npm install better-docs taffydb`).promise;
2429
+ await runCommand(`npx markdown-include ./workdocs/readme-md.json`).promise;
2430
+ await runCommand(`npx jsdoc -c ./workdocs/jsdocs.json -t ./node_modules/better-docs`).promise;
2431
+ await runCommand(`npm remove better-docs taffydb`).promise;
2432
+ [ {
2433
+ src: "workdocs/assets",
2434
+ dest: "./docs/workdocs/assets"
2435
+ }, {
2436
+ src: "workdocs/reports/coverage",
2437
+ dest: "./docs/workdocs/reports/coverage"
2438
+ }, {
2439
+ src: "workdocs/reports/html",
2440
+ dest: "./docs/workdocs/reports/html"
2441
+ }, {
2442
+ src: "workdocs/resources",
2443
+ dest: "./docs/workdocs/resources"
2444
+ }, {
2445
+ src: "LICENSE.md",
2446
+ dest: "./docs/LICENSE.md"
2447
+ } ].forEach(f => {
2448
+ const {src: src, dest: dest} = f;
2449
+ copyFile(src, dest);
2450
+ });
2451
+ try {
2452
+ const sizeKb = await getFileSizeZipped(path.resolve(path.join(process.cwd(), "dist")));
2453
+ this.replacements[PACKAGE_SIZE_STRING] = `${sizeKb} KB`;
2454
+ } catch {
2455
+ this.replacements[PACKAGE_SIZE_STRING] = "unknown";
2456
+ }
2457
+ try {
2458
+ patchFile("./README.md", this.replacements);
2459
+ } catch (e) {
2460
+ const log = this.log.for(this.buildDocs);
2461
+ log.verbose(`Failed to patch README.md: ${e}`);
2462
+ }
2463
+ }
2464
+ async run(answers) {
2465
+ const {dev: dev, prod: prod, docs: docs, buildMode: buildMode, includes: includes, externals: externals, entry: entry} = answers;
2466
+ if (dev) {
2467
+ return await this.buildDev(entry || "./src/index.ts", buildMode, includes, externals);
2468
+ }
2469
+ if (prod) {
2470
+ return await this.buildProd(entry || "./src/index.ts", buildMode, includes, externals);
2471
+ }
2472
+ if (docs) {
2473
+ return await this.buildDocs();
2474
+ }
2475
+ }
2476
+ }
2477
+
2478
+ const options = {
2479
+ ci: {
2480
+ type: "boolean",
2481
+ default: true
2482
+ },
2483
+ message: {
2484
+ type: "string",
2485
+ short: "m"
2486
+ },
2487
+ tag: {
2488
+ type: "string",
2489
+ short: "t",
2490
+ default: undefined
2491
+ }
2492
+ };
2493
+
2494
+ class ReleaseScript extends Command {
2495
+ constructor() {
2496
+ super("ReleaseScript", options);
2497
+ }
2498
+ async prepareVersion(tag) {
2499
+ const log = this.log.for(this.prepareVersion);
2500
+ tag = this.testVersion(tag || "");
2501
+ if (!tag) {
2502
+ log.verbose("No release message provided. Prompting for one:");
2503
+ log.info(`Listing latest git tags:`);
2504
+ await runCommand("git tag --sort=-taggerdate | head -n 5").promise;
2505
+ return await UserInput.insistForText("tag", "Enter the new tag number (accepts v*.*.*[-...])", val => !!val.toString().match(/^v[0-9]+\.[0-9]+.[0-9]+(-[0-9a-zA-Z-]+)?$/));
2506
+ }
2507
+ return tag;
2508
+ }
2509
+ testVersion(version) {
2510
+ const log = this.log.for(this.testVersion);
2511
+ version = version.trim().toLowerCase();
2512
+ switch (version) {
2513
+ case SemVersion.PATCH:
2514
+ case SemVersion.MINOR:
2515
+ case SemVersion.MAJOR:
2516
+ log.verbose(`Using provided SemVer update: ${version}`, 1);
2517
+ return version;
2518
+
2519
+ default:
2520
+ log.verbose(`Testing provided version for SemVer compatibility: ${version}`, 1);
2521
+ if (!new RegExp(SemVersionRegex).test(version)) {
2522
+ log.debug(`Invalid version number: ${version}`);
2523
+ return undefined;
2524
+ }
2525
+ log.verbose(`version approved: ${version}`, 1);
2526
+ return version;
2527
+ }
2528
+ }
2529
+ async prepareMessage(message) {
2530
+ const log = this.log.for(this.prepareMessage);
2531
+ if (!message) {
2532
+ log.verbose("No release message provided. Prompting for one");
2533
+ return await UserInput.insistForText("message", "What should be the release message/ticket?", val => !!val && val.toString().length > 5);
2534
+ }
2535
+ return message;
2536
+ }
2537
+ async run(args) {
2538
+ let result;
2539
+ const {ci: ci} = args;
2540
+ let {tag: tag, message: message} = args;
2541
+ tag = await this.prepareVersion(tag);
2542
+ message = await this.prepareMessage(message);
2543
+ result = await runCommand(`npm run prepare-release -- ${tag} ${message}`, {
2544
+ cwd: process.cwd()
2545
+ }).promise;
2546
+ result = await runCommand("git status --porcelain").promise;
2547
+ await result;
2548
+ if (result.logs.length && await UserInput.askConfirmation("git-changes", "Do you want to push the changes to the remote repository?", true)) {
2549
+ await runCommand("git add .").promise;
2550
+ await runCommand(`git commit -m "${tag} - ${message} - after release preparation${ci ? "" : NoCIFLag}"`).promise;
2551
+ }
2552
+ await runCommand(`npm version "${tag}" -m "${message}${ci ? "" : NoCIFLag}"`).promise;
2553
+ await runCommand("git push --follow-tags").promise;
2554
+ if (!ci) {
2555
+ await runCommand("NPM_TOKEN=$(cat .npmtoken) npm publish --access public").promise;
2556
+ }
2557
+ }
2558
+ }
2559
+
2560
+ class RegexpOutputWriter extends StandardOutputWriter {
2561
+ constructor(cmd, lock, regexp, flags = "g") {
2562
+ super(cmd, lock);
2563
+ try {
2564
+ this.regexp = typeof regexp === "string" ? new RegExp(regexp, flags) : regexp;
2565
+ } catch (e) {
2566
+ throw new Error(`Invalid regular expression: ${e}`);
2567
+ }
2568
+ }
2569
+ test(data) {
2570
+ this.regexp.lastIndex = 0;
2571
+ let match;
2572
+ try {
2573
+ match = this.regexp.exec(data);
2574
+ } catch (e) {
2575
+ return console.debug(`Failed to parse chunk: ${data}\nError: ${e} `);
2576
+ }
2577
+ return match;
2578
+ }
2579
+ testAndResolve(data) {
2580
+ const match = this.test(data);
2581
+ if (match) this.resolve(match[0]);
2582
+ }
2583
+ testAndReject(data) {
2584
+ const match = this.test(data);
2585
+ if (match) this.reject(match[0]);
2586
+ }
2587
+ data(chunk) {
2588
+ super.data(chunk);
2589
+ this.testAndResolve(String(chunk));
2590
+ }
2591
+ error(chunk) {
2592
+ super.error(chunk);
2593
+ this.testAndReject(String(chunk));
2594
+ }
2595
+ }
2596
+
2597
+ const VERSION = "0.11.10.experimental.1";
2598
+
2599
+ const PACKAGE_NAME = "@decaf-ts/utils";
2600
+
2601
+ export { AbortCode, BuildScripts, Command, DefaultCommandOptions, DefaultCommandValues, Encoding, HttpClient, NoCIFLag, PACKAGE_NAME, PerformanceRunner, RegexpOutputWriter, ReleaseScript, SemVersion, SemVersionRegex, SetupScriptKey, StandardOutputWriter, Tokens, UserInput, VERSION, chainAbortController, copyFile, defaultCanvasOptions, deletePath, getAllFiles, getDependencies, getFileSizeZipped, getPackage, getPackageDependencies, getPackageVersion, getSlogan, installDependencies, installIfNotAvailable, listFolder, listNodeModulesPackages, lockify, normalizeImport, packageToGlobal, parseList, patchFile, printBanner, pushToGit, readFile, renameFile, runCommand, setPackageAttribute, spawnCommand, updateDependencies, writeFile };
2602
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbnB1dC9pbnB1dC50cyIsIi4uL3NyYy9jbGkvY29uc3RhbnRzLnRzIiwiLi4vc3JjL3V0aWxzL2NvbnN0YW50cy50cyIsIi4uL3NyYy93cml0ZXJzL1N0YW5kYXJkT3V0cHV0V3JpdGVyLnRzIiwiLi4vc3JjL3V0aWxzL3V0aWxzLnRzIiwiLi4vc3JjL3V0aWxzL2ZzLnRzIiwiLi4vc3JjL2Fzc2V0cy9zbG9nYW5zLnRzIiwiLi4vc3JjL291dHB1dC9jb21tb24udHMiLCIuLi9zcmMvY2xpL2NvbW1hbmQudHMiLCIuLi9zcmMvdXRpbHMvaHR0cC50cyIsIi4uL3NyYy91dGlscy9wZXJmb3JtYW5jZVJ1bm5lci50cyIsIi4uL3NyYy9jbGkvY29tbWFuZHMvYnVpbGQtc2NyaXB0cy50cyIsIi4uL3NyYy9jbGkvY29tbWFuZHMvdGFnLXJlbGVhc2UudHMiLCIuLi9zcmMvd3JpdGVycy9SZWdleHBPdXRwdXRXcml0ZXIudHMiLCIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQW5zd2VycyxcbiAgQ2hvaWNlLFxuICBGYWxzeSxcbiAgSW5pdGlhbFJldHVyblZhbHVlLFxuICBQcmV2Q2FsbGVyLFxuICBQcm9tcHRPYmplY3QsXG4gIFByb21wdFR5cGUsXG4gIFZhbHVlT3JGdW5jLFxufSBmcm9tIFwicHJvbXB0c1wiO1xuaW1wb3J0IHByb21wdHMgZnJvbSBcInByb21wdHNcIjtcbmltcG9ydCB7IHBhcnNlQXJncywgUGFyc2VBcmdzQ29uZmlnIH0gZnJvbSBcInV0aWxcIjtcbmltcG9ydCB7IFdyaXRhYmxlLCBSZWFkYWJsZSB9IGZyb20gXCJzdHJlYW1cIjtcbmltcG9ydCB7IFBhcnNlQXJnc09wdGlvbnNDb25maWcsIFBhcnNlQXJnc1Jlc3VsdCB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlcHJlc2VudHMgYSB1c2VyIGlucHV0IHByb21wdCB3aXRoIHZhcmlvdXMgY29uZmlndXJhdGlvbiBvcHRpb25zLlxuICogQHN1bW1hcnkgVGhpcyBjbGFzcyBwcm92aWRlcyBhIGZsZXhpYmxlIGludGVyZmFjZSBmb3IgY3JlYXRpbmcgYW5kIG1hbmFnaW5nIHVzZXIgaW5wdXQgcHJvbXB0cy5cbiAqIEl0IGltcGxlbWVudHMgdGhlIFByb21wdE9iamVjdCBpbnRlcmZhY2UgZnJvbSB0aGUgJ3Byb21wdHMnIGxpYnJhcnkgYW5kIG9mZmVycyBtZXRob2RzIHRvIHNldFxuICogdmFyaW91cyBwcm9wZXJ0aWVzIG9mIHRoZSBwcm9tcHQuIFRoZSBjbGFzcyBhbHNvIGluY2x1ZGVzIHN0YXRpYyBtZXRob2RzIGZvciBjb21tb24gaW5wdXQgc2NlbmFyaW9zXG4gKiBhbmQgYXJndW1lbnQgcGFyc2luZy5cbiAqXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSB0eXBlIG9mIHRoZSBwcm9tcHQgbmFtZSwgZXh0ZW5kaW5nIHN0cmluZy5cbiAqXG4gKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gKlxuICogQGNsYXNzXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgVXNlcklucHV0IH0gZnJvbSAnQGRlY2FmLXRzL3V0aWxzJztcbiAqXG4gKiAvLyBDcmVhdGUgYSBzaW1wbGUgdGV4dCBpbnB1dFxuICogY29uc3QgbmFtZUlucHV0ID0gbmV3IFVzZXJJbnB1dCgnbmFtZScpXG4gKiAgIC5zZXRNZXNzYWdlKCdXaGF0IGlzIHlvdXIgbmFtZT8nKVxuICogICAuc2V0SW5pdGlhbCgnVXNlcicpO1xuICpcbiAqIC8vIENyZWF0ZSBhIG51bWJlciBpbnB1dCB3aXRoIHZhbGlkYXRpb25cbiAqIGNvbnN0IGFnZUlucHV0ID0gbmV3IFVzZXJJbnB1dCgnYWdlJylcbiAqICAgLnNldFR5cGUoJ251bWJlcicpXG4gKiAgIC5zZXRNZXNzYWdlKCdIb3cgb2xkIGFyZSB5b3U/JylcbiAqICAgLnNldE1pbigwKVxuICogICAuc2V0TWF4KDEyMCk7XG4gKlxuICogLy8gQXNrIGZvciBpbnB1dCBhbmQgcHJvY2VzcyB0aGUgcmVzdWx0c1xuICogYXN5bmMgZnVuY3Rpb24gZ2V0VXNlckluZm8oKSB7XG4gKiAgIGNvbnN0IGFuc3dlcnMgPSBhd2FpdCBVc2VySW5wdXQuYXNrKFtuYW1lSW5wdXQsIGFnZUlucHV0XSk7XG4gKiAgIGNvbnNvbGUubG9nKGBIZWxsbyAke2Fuc3dlcnMubmFtZX0sIHlvdSBhcmUgJHthbnN3ZXJzLmFnZX0geWVhcnMgb2xkLmApO1xuICogfVxuICpcbiAqIGdldFVzZXJJbmZvKCk7XG4gKiBgYGBcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICogICBwYXJ0aWNpcGFudCBVc2VySW5wdXRcbiAqICAgcGFydGljaXBhbnQgUHJvbXB0TGlicmFyeVxuICpcbiAqICAgQ2xpZW50LT4+VXNlcklucHV0OiBuZXcgVXNlcklucHV0KG5hbWUpXG4gKiAgIENsaWVudC0+PlVzZXJJbnB1dDogc2V0TWVzc2FnZShtZXNzYWdlKVxuICogICBDbGllbnQtPj5Vc2VySW5wdXQ6IHNldFR5cGUodHlwZSlcbiAqICAgQ2xpZW50LT4+VXNlcklucHV0OiBzZXRJbml0aWFsKGluaXRpYWwpXG4gKiAgIENsaWVudC0+PlVzZXJJbnB1dDogT3RoZXIgY29uZmlndXJhdGlvbiBtZXRob2RzXG4gKlxuICogICBDbGllbnQtPj5Vc2VySW5wdXQ6IGFzaygpXG4gKiAgIFVzZXJJbnB1dC0+PlByb21wdExpYnJhcnk6IHByb21wdHMocXVlc3Rpb24pXG4gKiAgIFByb21wdExpYnJhcnktPj5DbGllbnQ6IERpc3BsYXkgcHJvbXB0XG4gKiAgIENsaWVudC0+PlByb21wdExpYnJhcnk6IFVzZXIgcHJvdmlkZXMgaW5wdXRcbiAqICAgUHJvbXB0TGlicmFyeS0+PlVzZXJJbnB1dDogUmV0dXJuIGFuc3dlcnNcbiAqICAgVXNlcklucHV0LT4+Q2xpZW50OiBSZXR1cm4gcHJvY2Vzc2VkIGFuc3dlcnNcbiAqL1xuZXhwb3J0IGNsYXNzIFVzZXJJbnB1dDxSIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nPiBpbXBsZW1lbnRzIFByb21wdE9iamVjdDxSPiB7XG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IGxvZ2dlciA9IExvZ2dpbmcuZm9yKFVzZXJJbnB1dCk7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHR5cGUgb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyB0aGUgaW5wdXQgbWV0aG9kIChlLmcuLCB0ZXh0LCBudW1iZXIsIGNvbmZpcm0pLlxuICAgKi9cbiAgdHlwZTogUHJvbXB0VHlwZSB8IEZhbHN5IHwgUHJldkNhbGxlcjxSLCBQcm9tcHRUeXBlIHwgRmFsc3k+ID0gXCJ0ZXh0XCI7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbmFtZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBVc2VkIGFzIHRoZSBrZXkgaW4gdGhlIHJldHVybmVkIGFuc3dlcnMgb2JqZWN0LlxuICAgKi9cbiAgbmFtZTogVmFsdWVPckZ1bmM8Uj47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbWVzc2FnZSBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG4gICAqIEBzdW1tYXJ5IFRoZSBxdWVzdGlvbiBvciBpbnN0cnVjdGlvbiBwcmVzZW50ZWQgdG8gdGhlIHVzZXIuXG4gICAqL1xuICBtZXNzYWdlPzogVmFsdWVPckZ1bmM8c3RyaW5nPiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBpbml0aWFsIHZhbHVlIG9mIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IFRoZSBkZWZhdWx0IHZhbHVlIHByZXNlbnRlZCB0byB0aGUgdXNlci5cbiAgICovXG4gIGluaXRpYWw/OlxuICAgIHwgSW5pdGlhbFJldHVyblZhbHVlXG4gICAgfCBQcmV2Q2FsbGVyPFIsIEluaXRpYWxSZXR1cm5WYWx1ZSB8IFByb21pc2U8SW5pdGlhbFJldHVyblZhbHVlPj5cbiAgICB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBzdHlsZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBEZXRlcm1pbmVzIHRoZSB2aXN1YWwgc3R5bGUgb2YgdGhlIHByb21wdC5cbiAgICovXG4gIHN0eWxlPzogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgZm9ybWF0IGZ1bmN0aW9uIGZvciB0aGUgaW5wdXQuXG4gICAqIEBzdW1tYXJ5IEEgZnVuY3Rpb24gdG8gZm9ybWF0IHRoZSB1c2VyJ3MgaW5wdXQgYmVmb3JlIGl0J3MgcmV0dXJuZWQuXG4gICAqL1xuICBmb3JtYXQ/OiBQcmV2Q2FsbGVyPFIsIHZvaWQ+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHZhbGlkYXRpb24gZnVuY3Rpb24gZm9yIHRoZSBpbnB1dC5cbiAgICogQHN1bW1hcnkgQSBmdW5jdGlvbiB0byB2YWxpZGF0ZSB0aGUgdXNlcidzIGlucHV0LlxuICAgKi9cbiAgdmFsaWRhdGU/OlxuICAgIHwgUHJldkNhbGxlcjxSLCBib29sZWFuIHwgc3RyaW5nIHwgUHJvbWlzZTxib29sZWFuIHwgc3RyaW5nPj5cbiAgICB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBvblN0YXRlIGNhbGxiYWNrIGZ1bmN0aW9uLlxuICAgKiBAc3VtbWFyeSBBIGZ1bmN0aW9uIGNhbGxlZCB3aGVuIHRoZSBzdGF0ZSBvZiB0aGUgcHJvbXB0IGNoYW5nZXMuXG4gICAqL1xuICBvblN0YXRlPzogUHJldkNhbGxlcjxSLCB2b2lkPiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBtaW5pbXVtIHZhbHVlIGZvciBudW1iZXIgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBUaGUgbG93ZXN0IG51bWJlciB0aGUgdXNlciBjYW4gaW5wdXQuXG4gICAqL1xuICBtaW4/OiBudW1iZXIgfCBQcmV2Q2FsbGVyPFIsIG51bWJlciB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBtYXhpbXVtIHZhbHVlIGZvciBudW1iZXIgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBUaGUgaGlnaGVzdCBudW1iZXIgdGhlIHVzZXIgY2FuIGlucHV0LlxuICAgKi9cbiAgbWF4PzogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBXaGV0aGVyIHRvIGFsbG93IGZsb2F0IHZhbHVlcyBmb3IgbnVtYmVyIGlucHV0cy5cbiAgICogQHN1bW1hcnkgSWYgdHJ1ZSwgYWxsb3dzIGRlY2ltYWwgbnVtYmVycy5cbiAgICovXG4gIGZsb2F0PzogYm9vbGVhbiB8IFByZXZDYWxsZXI8UiwgYm9vbGVhbiB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8gcm91bmQgdG8gZm9yIGZsb2F0IGlucHV0cy5cbiAgICogQHN1bW1hcnkgRGV0ZXJtaW5lcyB0aGUgcHJlY2lzaW9uIG9mIGZsb2F0IGlucHV0cy5cbiAgICovXG4gIHJvdW5kPzogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJbnN0cnVjdGlvbnMgZm9yIHRoZSB1c2VyLlxuICAgKiBAc3VtbWFyeSBBZGRpdGlvbmFsIGd1aWRhbmNlIHByb3ZpZGVkIHRvIHRoZSB1c2VyLlxuICAgKi9cbiAgaW5zdHJ1Y3Rpb25zPzogc3RyaW5nIHwgYm9vbGVhbiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBpbmNyZW1lbnQgdmFsdWUgZm9yIG51bWJlciBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IFRoZSBzdGVwIHNpemUgd2hlbiBpbmNyZWFzaW5nIG9yIGRlY3JlYXNpbmcgdGhlIG51bWJlci5cbiAgICovXG4gIGluY3JlbWVudD86IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHNlcGFyYXRvciBmb3IgbGlzdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IFRoZSBjaGFyYWN0ZXIgdXNlZCB0byBzZXBhcmF0ZSBsaXN0IGl0ZW1zLlxuICAgKi9cbiAgc2VwYXJhdG9yPzogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgYWN0aXZlIG9wdGlvbiBzdHlsZSBmb3Igc2VsZWN0IGlucHV0cy5cbiAgICogQHN1bW1hcnkgVGhlIHN0eWxlIGFwcGxpZWQgdG8gdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBvcHRpb24uXG4gICAqL1xuICBhY3RpdmU/OiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBpbmFjdGl2ZSBvcHRpb24gc3R5bGUgZm9yIHNlbGVjdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IFRoZSBzdHlsZSBhcHBsaWVkIHRvIG5vbi1zZWxlY3RlZCBvcHRpb25zLlxuICAgKi9cbiAgaW5hY3RpdmU/OiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBhdmFpbGFibGUgY2hvaWNlcyBmb3Igc2VsZWN0LCBtdWx0aXNlbGVjdCwgb3IgYXV0b2NvbXBsZXRlIGlucHV0cy5cbiAgICogQHN1bW1hcnkgQW4gYXJyYXkgb2Ygb3B0aW9ucyB0aGF0IHRoZSB1c2VyIGNhbiBzZWxlY3QgZnJvbSBpbiBjaG9pY2UtYmFzZWQgcHJvbXB0cy5cbiAgICovXG4gIGNob2ljZXM/OiBDaG9pY2VbXSB8IFByZXZDYWxsZXI8UiwgQ2hvaWNlW10gfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgaGludCB0ZXh0IGZvciB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBBZGRpdGlvbmFsIGluZm9ybWF0aW9uIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICovXG4gIGhpbnQ/OiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSB3YXJuaW5nIHRleHQgZm9yIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IEEgd2FybmluZyBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICovXG4gIHdhcm4/OiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZDtcblxuICBzdWdnZXN0PzogKChpbnB1dDogYW55LCBjaG9pY2VzOiBDaG9pY2VbXSkgPT4gUHJvbWlzZTxhbnk+KSB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFRoZSBsaW1pdCBmb3IgbGlzdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IFRoZSBtYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0aGF0IGNhbiBiZSBzZWxlY3RlZC5cbiAgICovXG4gIGxpbWl0PzogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgbWFzayBmb3IgcGFzc3dvcmQgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBUaGUgY2hhcmFjdGVyIHVzZWQgdG8gaGlkZSB0aGUgdXNlcidzIGlucHV0LlxuICAgKi9cbiAgbWFzaz86IHN0cmluZyB8IFByZXZDYWxsZXI8Uiwgc3RyaW5nIHwgRmFsc3k+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHN0ZG91dCBzdHJlYW0gZm9yIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IFRoZSBvdXRwdXQgc3RyZWFtIHVzZWQgYnkgdGhlIHByb21wdC5cbiAgICovXG4gIHN0ZG91dD86IFdyaXRhYmxlIHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGhlIHN0ZGluIHN0cmVhbSBmb3IgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgVGhlIGlucHV0IHN0cmVhbSB1c2VkIGJ5IHRoZSBwcm9tcHQuXG4gICAqL1xuICBzdGRpbj86IFJlYWRhYmxlIHwgdW5kZWZpbmVkO1xuXG4gIGNvbnN0cnVjdG9yKG5hbWU6IFZhbHVlT3JGdW5jPFI+KSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgdHlwZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBpbnB1dCBtZXRob2QgZm9yIHRoZSBwcm9tcHQuXG4gICAqXG4gICAqIEBwYXJhbSB0eXBlIC0gVGhlIHR5cGUgb2YgdGhlIHByb21wdC5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldFR5cGUodHlwZTogUHJvbXB0VHlwZSB8IEZhbHN5IHwgUHJldkNhbGxlcjxSLCBQcm9tcHRUeXBlIHwgRmFsc3k+KTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIHR5cGUgdG86ICR7dHlwZX1gKTtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBtZXNzYWdlIG9mIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIHF1ZXN0aW9uIG9yIGluc3RydWN0aW9uIHByZXNlbnRlZCB0byB0aGUgdXNlci5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIG1lc3NhZ2UgdG8gYmUgZGlzcGxheWVkLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0TWVzc2FnZSh2YWx1ZTogVmFsdWVPckZ1bmM8c3RyaW5nPiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBtZXNzYWdlIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMubWVzc2FnZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBpbml0aWFsIHZhbHVlIG9mIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGRlZmF1bHQgdmFsdWUgcHJlc2VudGVkIHRvIHRoZSB1c2VyLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgaW5pdGlhbCB2YWx1ZS5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldEluaXRpYWwoXG4gICAgdmFsdWU6XG4gICAgICB8IEluaXRpYWxSZXR1cm5WYWx1ZVxuICAgICAgfCBQcmV2Q2FsbGVyPFIsIEluaXRpYWxSZXR1cm5WYWx1ZSB8IFByb21pc2U8SW5pdGlhbFJldHVyblZhbHVlPj5cbiAgICAgIHwgdW5kZWZpbmVkXG4gICk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBpbml0aWFsIHZhbHVlIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuaW5pdGlhbCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBzdHlsZSBvZiB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSB2aXN1YWwgc3R5bGUgb2YgdGhlIHByb21wdC5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHN0eWxlIHRvIGJlIGFwcGxpZWQuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRTdHlsZSh2YWx1ZTogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgc3R5bGUgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5zdHlsZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBmb3JtYXQgZnVuY3Rpb24gb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyBhIGZ1bmN0aW9uIHRvIGZvcm1hdCB0aGUgdXNlcidzIGlucHV0IGJlZm9yZSBpdCdzIHJldHVybmVkLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgZm9ybWF0IGZ1bmN0aW9uLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0Rm9ybWF0KHZhbHVlOiBQcmV2Q2FsbGVyPFIsIHZvaWQ+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGZvcm1hdCBmdW5jdGlvbmApO1xuICAgIHRoaXMuZm9ybWF0ID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIHZhbGlkYXRpb24gZnVuY3Rpb24gb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyBhIGZ1bmN0aW9uIHRvIHZhbGlkYXRlIHRoZSB1c2VyJ3MgaW5wdXQuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWxpZGF0aW9uIGZ1bmN0aW9uLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0VmFsaWRhdGUoXG4gICAgdmFsdWU6XG4gICAgICB8IFByZXZDYWxsZXI8UiwgYm9vbGVhbiB8IHN0cmluZyB8IFByb21pc2U8Ym9vbGVhbiB8IHN0cmluZz4+XG4gICAgICB8IHVuZGVmaW5lZFxuICApOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgdmFsaWRhdGUgZnVuY3Rpb25gKTtcbiAgICB0aGlzLnZhbGlkYXRlID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIG9uU3RhdGUgY2FsbGJhY2sgb2YgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyBhIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBzdGF0ZSBvZiB0aGUgcHJvbXB0IGNoYW5nZXMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBvblN0YXRlIGNhbGxiYWNrIGZ1bmN0aW9uLlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0T25TdGF0ZSh2YWx1ZTogUHJldkNhbGxlcjxSLCB2b2lkPiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBvblN0YXRlIGNhbGxiYWNrYCk7XG4gICAgdGhpcy5vblN0YXRlID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIG1pbmltdW0gdmFsdWUgZm9yIG51bWJlciBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGxvd2VzdCBudW1iZXIgdGhlIHVzZXIgY2FuIGlucHV0LlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgbWluaW11bSB2YWx1ZS5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldE1pbih2YWx1ZTogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgbWluIHZhbHVlIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMubWluID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIG1heGltdW0gdmFsdWUgZm9yIG51bWJlciBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIGhpZ2hlc3QgbnVtYmVyIHRoZSB1c2VyIGNhbiBpbnB1dC5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIG1heGltdW0gdmFsdWUuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRNYXgodmFsdWU6IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIG1heCB2YWx1ZSB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLm1heCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHdoZXRoZXIgdG8gYWxsb3cgZmxvYXQgdmFsdWVzIGZvciBudW1iZXIgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHdoZXRoZXIgZGVjaW1hbCBudW1iZXJzIGFyZSBhbGxvd2VkLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBXaGV0aGVyIHRvIGFsbG93IGZsb2F0IHZhbHVlcy5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldEZsb2F0KHZhbHVlOiBib29sZWFuIHwgUHJldkNhbGxlcjxSLCBib29sZWFuIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGZsb2F0IHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuZmxvYXQgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHJvdW5kIHRvIGZvciBmbG9hdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIHByZWNpc2lvbiBvZiBmbG9hdCBpbnB1dHMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRSb3VuZCh2YWx1ZTogbnVtYmVyIHwgUHJldkNhbGxlcjxSLCBudW1iZXIgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgcm91bmQgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5yb3VuZCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBpbnN0cnVjdGlvbnMgZm9yIHRoZSB1c2VyLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIGFkZGl0aW9uYWwgZ3VpZGFuY2UgcHJvdmlkZWQgdG8gdGhlIHVzZXIuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBpbnN0cnVjdGlvbnMuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRJbnN0cnVjdGlvbnModmFsdWU6IHN0cmluZyB8IGJvb2xlYW4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgaW5zdHJ1Y3Rpb25zIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuaW5zdHJ1Y3Rpb25zID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIGluY3JlbWVudCB2YWx1ZSBmb3IgbnVtYmVyIGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgc3RlcCBzaXplIHdoZW4gaW5jcmVhc2luZyBvciBkZWNyZWFzaW5nIHRoZSBudW1iZXIuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBpbmNyZW1lbnQgdmFsdWUuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRJbmNyZW1lbnQoXG4gICAgdmFsdWU6IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkXG4gICk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBpbmNyZW1lbnQgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5pbmNyZW1lbnQgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgc2VwYXJhdG9yIGZvciBsaXN0IGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgY2hhcmFjdGVyIHVzZWQgdG8gc2VwYXJhdGUgbGlzdCBpdGVtcy5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHNlcGFyYXRvciBjaGFyYWN0ZXIuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRTZXBhcmF0b3IoXG4gICAgdmFsdWU6IHN0cmluZyB8IFByZXZDYWxsZXI8Uiwgc3RyaW5nIHwgRmFsc3k+IHwgdW5kZWZpbmVkXG4gICk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBzZXBhcmF0b3IgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5zZXBhcmF0b3IgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgYWN0aXZlIG9wdGlvbiBzdHlsZSBmb3Igc2VsZWN0IGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgc3R5bGUgYXBwbGllZCB0byB0aGUgY3VycmVudGx5IHNlbGVjdGVkIG9wdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGFjdGl2ZSBvcHRpb24gc3R5bGUuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRBY3RpdmUodmFsdWU6IHN0cmluZyB8IFByZXZDYWxsZXI8Uiwgc3RyaW5nIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGFjdGl2ZSBzdHlsZSB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLmFjdGl2ZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBpbmFjdGl2ZSBvcHRpb24gc3R5bGUgZm9yIHNlbGVjdCBpbnB1dHMuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgdGhlIHN0eWxlIGFwcGxpZWQgdG8gbm9uLXNlbGVjdGVkIG9wdGlvbnMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBpbmFjdGl2ZSBvcHRpb24gc3R5bGUuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRJbmFjdGl2ZSh2YWx1ZTogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgaW5hY3RpdmUgc3R5bGUgdG86ICR7dmFsdWV9YCk7XG4gICAgdGhpcy5pbmFjdGl2ZSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBjaG9pY2VzIGZvciBzZWxlY3QsIG11bHRpc2VsZWN0LCBvciBhdXRvY29tcGxldGUgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBhdmFpbGFibGUgb3B0aW9ucyB0aGF0IHRoZSB1c2VyIGNhbiBzZWxlY3QgZnJvbSBpbiBjaG9pY2UtYmFzZWQgcHJvbXB0cy5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGFycmF5IG9mIGNob2ljZXMgb3IgYSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgdGhlIGNob2ljZXMuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRDaG9pY2VzKFxuICAgIHZhbHVlOiBDaG9pY2VbXSB8IFByZXZDYWxsZXI8UiwgQ2hvaWNlW10gfCBGYWxzeT4gfCB1bmRlZmluZWRcbiAgKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGNob2ljZXM6ICR7SlNPTi5zdHJpbmdpZnkodmFsdWUpfWApO1xuICAgIHRoaXMuY2hvaWNlcyA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBoaW50IHRleHQgZm9yIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBkaXNwbGF5ZWQgdG8gdGhlIHVzZXIuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBoaW50IHRleHQuXG4gICAqIEByZXR1cm5zIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRIaW50KHZhbHVlOiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBoaW50IHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMuaGludCA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSB3YXJuaW5nIHRleHQgZm9yIHRoZSBwcm9tcHQuXG4gICAqIEBzdW1tYXJ5IENvbmZpZ3VyZXMgYSB3YXJuaW5nIG1lc3NhZ2UgZGlzcGxheWVkIHRvIHRoZSB1c2VyLlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgd2FybmluZyB0ZXh0LlxuICAgKiBAcmV0dXJucyBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0V2Fybih2YWx1ZTogc3RyaW5nIHwgUHJldkNhbGxlcjxSLCBzdHJpbmcgfCBGYWxzeT4gfCB1bmRlZmluZWQpOiB0aGlzIHtcbiAgICBVc2VySW5wdXQubG9nZ2VyLnZlcmJvc2UoYFNldHRpbmcgd2FybiB0bzogJHt2YWx1ZX1gKTtcbiAgICB0aGlzLndhcm4gPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgc3VnZ2VzdGlvbiBmdW5jdGlvbiBmb3IgYXV0b2NvbXBsZXRlIGlucHV0cy5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyBhIGZ1bmN0aW9uIHRoYXQgcHJvdmlkZXMgc3VnZ2VzdGlvbnMgYmFzZWQgb24gdGhlIHVzZXIncyBpbnB1dCBhbmQgYXZhaWxhYmxlIGNob2ljZXMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIEEgZnVuY3Rpb24gdGhhdCB0YWtlcyB0aGUgY3VycmVudCBpbnB1dCBhbmQgYXZhaWxhYmxlIGNob2ljZXMgYW5kIHJldHVybnMgYSBQcm9taXNlIHJlc29sdmluZyB0byBzdWdnZXN0aW9ucy5cbiAgICogQHJldHVybnMgVGhpcyBVc2VySW5wdXQgaW5zdGFuY2UgZm9yIG1ldGhvZCBjaGFpbmluZy5cbiAgICovXG4gIHNldFN1Z2dlc3QoXG4gICAgdmFsdWU6ICgoaW5wdXQ6IGFueSwgY2hvaWNlczogQ2hvaWNlW10pID0+IFByb21pc2U8YW55PikgfCB1bmRlZmluZWRcbiAgKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIHN1Z2dlc3QgZnVuY3Rpb25gKTtcbiAgICB0aGlzLnN1Z2dlc3QgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgbGltaXQgZm9yIGxpc3QgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBtYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0aGF0IGNhbiBiZSBzZWxlY3RlZCBpbiBsaXN0LXR5cGUgcHJvbXB0cy5cbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgcHJvbXB0IG5hbWUsIGV4dGVuZGluZyBzdHJpbmcuXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBtYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0aGF0IGNhbiBiZSBzZWxlY3RlZCwgb3IgYSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgdGhpcyB2YWx1ZS5cbiAgICogQHJldHVybiBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0TGltaXQodmFsdWU6IG51bWJlciB8IFByZXZDYWxsZXI8UiwgbnVtYmVyIHwgRmFsc3k+IHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgVXNlcklucHV0LmxvZ2dlci52ZXJib3NlKGBTZXR0aW5nIGxpbWl0IHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMubGltaXQgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gU2V0cyB0aGUgbWFzayBmb3IgcGFzc3dvcmQgaW5wdXRzLlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBjaGFyYWN0ZXIgdXNlZCB0byBoaWRlIHRoZSB1c2VyJ3MgaW5wdXQgaW4gcGFzc3dvcmQtdHlwZSBwcm9tcHRzLlxuICAgKiBAdGVtcGxhdGUgUiAtIFRoZSB0eXBlIG9mIHRoZSBwcm9tcHQgbmFtZSwgZXh0ZW5kaW5nIHN0cmluZy5cbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIGNoYXJhY3RlciB1c2VkIHRvIG1hc2sgdGhlIGlucHV0LCBvciBhIGZ1bmN0aW9uIHRvIGRldGVybWluZSB0aGlzIHZhbHVlLlxuICAgKiBAcmV0dXJuIFRoaXMgVXNlcklucHV0IGluc3RhbmNlIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAqL1xuICBzZXRNYXNrKHZhbHVlOiBzdHJpbmcgfCBQcmV2Q2FsbGVyPFIsIHN0cmluZyB8IEZhbHN5PiB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBtYXNrIHRvOiAke3ZhbHVlfWApO1xuICAgIHRoaXMubWFzayA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBTZXRzIHRoZSBzdGRvdXQgc3RyZWFtIGZvciB0aGUgcHJvbXB0LlxuICAgKiBAc3VtbWFyeSBDb25maWd1cmVzIHRoZSBvdXRwdXQgc3RyZWFtIHVzZWQgYnkgdGhlIHByb21wdCBmb3IgZGlzcGxheWluZyBtZXNzYWdlcyBhbmQgcmVzdWx0cy5cbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIFdyaXRhYmxlIHN0cmVhbSB0byBiZSB1c2VkIGFzIHN0ZG91dC5cbiAgICogQHJldHVybiBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0U3Rkb3V0KHZhbHVlOiBXcml0YWJsZSB8IHVuZGVmaW5lZCk6IHRoaXMge1xuICAgIFVzZXJJbnB1dC5sb2dnZXIudmVyYm9zZShgU2V0dGluZyBzdGRvdXQgc3RyZWFtYCk7XG4gICAgdGhpcy5zdGRvdXQgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFNldHMgdGhlIHN0ZGluIHN0cmVhbSBmb3IgdGhlIHByb21wdC5cbiAgICogQHN1bW1hcnkgQ29uZmlndXJlcyB0aGUgaW5wdXQgc3RyZWFtIHVzZWQgYnkgdGhlIHByb21wdCBmb3IgcmVjZWl2aW5nIHVzZXIgaW5wdXQuXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBSZWFkYWJsZSBzdHJlYW0gdG8gYmUgdXNlZCBhcyBzdGRpbi5cbiAgICogQHJldHVybiBUaGlzIFVzZXJJbnB1dCBpbnN0YW5jZSBmb3IgbWV0aG9kIGNoYWluaW5nLlxuICAgKi9cbiAgc2V0U3RkaW4odmFsdWU6IFJlYWRhYmxlIHwgdW5kZWZpbmVkKTogdGhpcyB7XG4gICAgdGhpcy5zdGRpbiA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBc2tzIHRoZSB1c2VyIGZvciBpbnB1dCBiYXNlZCBvbiB0aGUgY3VycmVudCBVc2VySW5wdXQgY29uZmlndXJhdGlvbi5cbiAgICogQHN1bW1hcnkgUHJvbXB0cyB0aGUgdXNlciBhbmQgcmV0dXJucyB0aGVpciByZXNwb25zZSBhcyBhIHNpbmdsZSB2YWx1ZS5cbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgcHJvbXB0IG5hbWUsIGV4dGVuZGluZyBzdHJpbmcuXG4gICAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHVzZXIncyBhbnN3ZXIuXG4gICAqL1xuICBhc3luYyBhc2soKSB7XG4gICAgcmV0dXJuIChhd2FpdCBVc2VySW5wdXQuYXNrKHRoaXMpKVt0aGlzLm5hbWUgYXMga2V5b2YgQW5zd2VyczxSPl07XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFza3MgdGhlIHVzZXIgb25lIG9yIG1vcmUgcXVlc3Rpb25zIGJhc2VkIG9uIHRoZSBwcm92aWRlZCBVc2VySW5wdXQgY29uZmlndXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IFByb21wdHMgdGhlIHVzZXIgd2l0aCBvbmUgb3IgbW9yZSBxdWVzdGlvbnMgYW5kIHJldHVybnMgdGhlaXIgYW5zd2VycyBhcyBhbiBvYmplY3QuXG4gICAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgdGhlIHByb21wdCBuYW1lLCBleHRlbmRpbmcgc3RyaW5nLlxuICAgKiBAcGFyYW0gcXVlc3Rpb24gLSBBIHNpbmdsZSBVc2VySW5wdXQgaW5zdGFuY2Ugb3IgYW4gYXJyYXkgb2YgVXNlcklucHV0IGluc3RhbmNlcy5cbiAgICogQHJldHVybiBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgdXNlcidzIGFuc3dlcnMuXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IFUgYXMgVXNlclxuICAgKiAgIHBhcnRpY2lwYW50IEEgYXMgYXNrIG1ldGhvZFxuICAgKiAgIHBhcnRpY2lwYW50IFAgYXMgcHJvbXB0cyBsaWJyYXJ5XG4gICAqICAgQS0+PlA6IENhbGwgcHJvbXB0cyB3aXRoIHF1ZXN0aW9uKHMpXG4gICAqICAgUC0+PlU6IERpc3BsYXkgcHJvbXB0KHMpXG4gICAqICAgVS0+PlA6IFByb3ZpZGUgaW5wdXRcbiAgICogICBQLT4+QTogUmV0dXJuIGFuc3dlcnNcbiAgICogICBBLT4+QTogUHJvY2VzcyBhbnN3ZXJzXG4gICAqICAgQS0tPj5DYWxsZXI6IFJldHVybiBwcm9jZXNzZWQgYW5zd2Vyc1xuICAgKi9cbiAgc3RhdGljIGFzeW5jIGFzazxSIGV4dGVuZHMgc3RyaW5nID0gc3RyaW5nPihcbiAgICBxdWVzdGlvbjogVXNlcklucHV0PFI+IHwgVXNlcklucHV0PFI+W11cbiAgKSB7XG4gICAgY29uc3QgbG9nID0gVXNlcklucHV0LmxvZ2dlci5mb3IodGhpcy5hc2spO1xuICAgIGlmICghQXJyYXkuaXNBcnJheShxdWVzdGlvbikpIHtcbiAgICAgIHF1ZXN0aW9uID0gW3F1ZXN0aW9uXTtcbiAgICB9XG4gICAgbGV0IGFuc3dlcnM6IEFuc3dlcnM8Uj47XG4gICAgdHJ5IHtcbiAgICAgIGxvZy52ZXJib3NlKFxuICAgICAgICBgQXNraW5nIHF1ZXN0aW9uczogJHtxdWVzdGlvbi5tYXAoKHEpID0+IHEubmFtZSkuam9pbihcIiwgXCIpfWBcbiAgICAgICk7XG4gICAgICBhbnN3ZXJzID0gYXdhaXQgcHJvbXB0cyhxdWVzdGlvbik7XG4gICAgICBsb2cudmVyYm9zZShgUmVjZWl2ZWQgYW5zd2VyczogJHtKU09OLnN0cmluZ2lmeShhbnN3ZXJzLCBudWxsLCAyKX1gKTtcbiAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciB3aGlsZSBnZXR0aW5nIGlucHV0OiAke2Vycm9yfWApO1xuICAgIH1cbiAgICByZXR1cm4gYW5zd2VycztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXNrcyB0aGUgdXNlciBmb3IgYSBudW1iZXIgaW5wdXQuXG4gICAqIEBzdW1tYXJ5IFByb21wdHMgdGhlIHVzZXIgdG8gZW50ZXIgYSBudW1iZXIsIHdpdGggb3B0aW9uYWwgbWluaW11bSwgbWF4aW11bSwgYW5kIGluaXRpYWwgdmFsdWVzLlxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gICAqIEBwYXJhbSBxdWVzdGlvbiAtIFRoZSBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICogQHBhcmFtIG1pbiAtIFRoZSBtaW5pbXVtIGFsbG93ZWQgdmFsdWUgKG9wdGlvbmFsKS5cbiAgICogQHBhcmFtIG1heCAtIFRoZSBtYXhpbXVtIGFsbG93ZWQgdmFsdWUgKG9wdGlvbmFsKS5cbiAgICogQHBhcmFtIGluaXRpYWwgLSBUaGUgaW5pdGlhbCB2YWx1ZSBwcmVzZW50ZWQgdG8gdGhlIHVzZXIgKG9wdGlvbmFsKS5cbiAgICogQHJldHVybiBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgbnVtYmVyIGVudGVyZWQgYnkgdGhlIHVzZXIuXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgYXNrTnVtYmVyKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBxdWVzdGlvbjogc3RyaW5nLFxuICAgIG1pbj86IG51bWJlcixcbiAgICBtYXg/OiBudW1iZXIsXG4gICAgaW5pdGlhbD86IG51bWJlclxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGxvZyA9IFVzZXJJbnB1dC5sb2dnZXIuZm9yKHRoaXMuYXNrTnVtYmVyKTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBBc2tpbmcgbnVtYmVyIGlucHV0OiB1bmRlZmluZWQsIHF1ZXN0aW9uOiAke3F1ZXN0aW9ufSwgbWluOiAke21pbn0sIG1heDogJHttYXh9LCBpbml0aWFsOiAke2luaXRpYWx9YFxuICAgICk7XG4gICAgY29uc3QgdXNlcklucHV0ID0gbmV3IFVzZXJJbnB1dChuYW1lKVxuICAgICAgLnNldE1lc3NhZ2UocXVlc3Rpb24pXG4gICAgICAuc2V0VHlwZShcIm51bWJlclwiKTtcblxuICAgIGlmICh0eXBlb2YgbWluID09PSBcIm51bWJlclwiKSB1c2VySW5wdXQuc2V0TWluKG1pbik7XG5cbiAgICBpZiAodHlwZW9mIG1heCA9PT0gXCJudW1iZXJcIikgdXNlcklucHV0LnNldE1heChtYXgpO1xuXG4gICAgaWYgKHR5cGVvZiBpbml0aWFsID09PSBcIm51bWJlclwiKSB1c2VySW5wdXQuc2V0SW5pdGlhbChpbml0aWFsKTtcblxuICAgIHJldHVybiAoYXdhaXQgdGhpcy5hc2sodXNlcklucHV0KSlbbmFtZV07XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEFza3MgdGhlIHVzZXIgZm9yIGEgdGV4dCBpbnB1dC5cbiAgICogQHN1bW1hcnkgUHJvbXB0cyB0aGUgdXNlciB0byBlbnRlciB0ZXh0LCB3aXRoIG9wdGlvbmFsIG1hc2tpbmcgYW5kIGluaXRpYWwgdmFsdWUuXG4gICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHByb21wdCwgdXNlZCBhcyB0aGUga2V5IGluIHRoZSByZXR1cm5lZCBhbnN3ZXJzIG9iamVjdC5cbiAgICogQHBhcmFtIHF1ZXN0aW9uIC0gVGhlIG1lc3NhZ2UgZGlzcGxheWVkIHRvIHRoZSB1c2VyLlxuICAgKiBAcGFyYW0gbWFzayAtIFRoZSBjaGFyYWN0ZXIgdXNlZCB0byBtYXNrIHRoZSBpbnB1dCAob3B0aW9uYWwsIGZvciBwYXNzd29yZC1saWtlIGlucHV0cykuXG4gICAqIEBwYXJhbSBpbml0aWFsIC0gVGhlIGluaXRpYWwgdmFsdWUgcHJlc2VudGVkIHRvIHRoZSB1c2VyIChvcHRpb25hbCkuXG4gICAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHRleHQgZW50ZXJlZCBieSB0aGUgdXNlci5cbiAgICovXG4gIHN0YXRpYyBhc3luYyBhc2tUZXh0KFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBxdWVzdGlvbjogc3RyaW5nLFxuICAgIG1hc2s6IHN0cmluZyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZCxcbiAgICBpbml0aWFsPzogc3RyaW5nXG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgbG9nID0gVXNlcklucHV0LmxvZ2dlci5mb3IodGhpcy5hc2tUZXh0KTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBBc2tpbmcgdGV4dCBpbnB1dDogdW5kZWZpbmVkLCBxdWVzdGlvbjogJHtxdWVzdGlvbn0sIG1hc2s6ICR7bWFza30sIGluaXRpYWw6ICR7aW5pdGlhbH1gXG4gICAgKTtcbiAgICBjb25zdCB1c2VySW5wdXQgPSBuZXcgVXNlcklucHV0KG5hbWUpLnNldE1lc3NhZ2UocXVlc3Rpb24pO1xuXG4gICAgaWYgKG1hc2spIHVzZXJJbnB1dC5zZXRNYXNrKG1hc2spO1xuICAgIGlmICh0eXBlb2YgaW5pdGlhbCA9PT0gXCJzdHJpbmdcIikgdXNlcklucHV0LnNldEluaXRpYWwoaW5pdGlhbCk7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLmFzayh1c2VySW5wdXQpKVtuYW1lXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQXNrcyB0aGUgdXNlciBmb3IgYSBjb25maXJtYXRpb24gKHllcy9ubykuXG4gICAqIEBzdW1tYXJ5IFByb21wdHMgdGhlIHVzZXIgd2l0aCBhIHllcy9ubyBxdWVzdGlvbiBhbmQgcmV0dXJucyBhIGJvb2xlYW4gcmVzdWx0LlxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gICAqIEBwYXJhbSBxdWVzdGlvbiAtIFRoZSBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICogQHBhcmFtIGluaXRpYWwgLSBUaGUgaW5pdGlhbCB2YWx1ZSBwcmVzZW50ZWQgdG8gdGhlIHVzZXIgKG9wdGlvbmFsKS5cbiAgICogQHJldHVybiBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSB1c2VyJ3MgYW5zd2VyLlxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGFza0NvbmZpcm1hdGlvbihcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgcXVlc3Rpb246IHN0cmluZyxcbiAgICBpbml0aWFsPzogYm9vbGVhblxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBsb2cgPSBVc2VySW5wdXQubG9nZ2VyLmZvcih0aGlzLmFza0NvbmZpcm1hdGlvbik7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgQXNraW5nIGNvbmZpcm1hdGlvbiBpbnB1dDogdW5kZWZpbmVkLCBxdWVzdGlvbjogJHtxdWVzdGlvbn0sIGluaXRpYWw6ICR7aW5pdGlhbH1gXG4gICAgKTtcbiAgICBjb25zdCB1c2VySW5wdXQgPSBuZXcgVXNlcklucHV0KG5hbWUpXG4gICAgICAuc2V0TWVzc2FnZShxdWVzdGlvbilcbiAgICAgIC5zZXRUeXBlKFwiY29uZmlybVwiKTtcblxuICAgIGlmICh0eXBlb2YgaW5pdGlhbCAhPT0gXCJ1bmRlZmluZWRcIikgdXNlcklucHV0LnNldEluaXRpYWwoaW5pdGlhbCk7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLmFzayh1c2VySW5wdXQpKVtuYW1lXTtcbiAgfVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlcGVhdGVkbHkgYXNrcyBmb3IgaW5wdXQgdW50aWwgYSB2YWxpZCByZXNwb25zZSBpcyBnaXZlbiBvciB0aGUgbGltaXQgaXMgcmVhY2hlZC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgaW5zaXN0cyBvbiBnZXR0aW5nIGEgdmFsaWQgaW5wdXQgZnJvbSB0aGUgdXNlciwgYWxsb3dpbmcgZm9yIGEgc3BlY2lmaWVkIG51bWJlciBvZiBhdHRlbXB0cy5cbiAgICpcbiAgICogQHRlbXBsYXRlIFIgLSBUaGUgdHlwZSBvZiB0aGUgZXhwZWN0ZWQgcmVzdWx0LlxuICAgKiBAcGFyYW0gaW5wdXQgLSBUaGUgVXNlcklucHV0IGluc3RhbmNlIHRvIHVzZSBmb3IgcHJvbXB0aW5nLlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKHN0cmluZyk6Ym9vbGVhbn0gdGVzdCAtIFZhbGlkYXRvciBmdW5jdGlvbiByZWNlaXZpbmcgdGhlIHVzZXIgaW5wdXQgYW5kIHJldHVybmluZyB3aGV0aGVyIGl0IGlzIHZhbGlkLlxuICAgKiBAcGFyYW0gZGVmYXVsdENvbmZpcm1hdGlvbiAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB0aGUgY29uZmlybWF0aW9uIHByb21wdCAodHJ1ZSBmb3IgeWVzLCBmYWxzZSBmb3Igbm8pLlxuICAgKiBAcGFyYW0gbGltaXQgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgYXR0ZW1wdHMgYWxsb3dlZCAoZGVmYXVsdCBpcyAxKS5cbiAgICogQHJldHVybiBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgdmFsaWQgaW5wdXQgb3IgdW5kZWZpbmVkIGlmIHRoZSBsaW1pdCBpcyByZWFjaGVkLlxuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXJcbiAgICogICBwYXJ0aWNpcGFudCBJIGFzIGluc2lzdCBtZXRob2RcbiAgICogICBwYXJ0aWNpcGFudCBBIGFzIGFzayBtZXRob2RcbiAgICogICBwYXJ0aWNpcGFudCBUIGFzIHRlc3QgZnVuY3Rpb25cbiAgICogICBwYXJ0aWNpcGFudCBDIGFzIGFza0NvbmZpcm1hdGlvbiBtZXRob2RcbiAgICogICBsb29wIFVudGlsIHZhbGlkIGlucHV0IG9yIGxpbWl0IHJlYWNoZWRcbiAgICogICAgIEktPj5BOiBDYWxsIGFzayB3aXRoIGlucHV0XG4gICAqICAgICBBLT4+VTogUHJvbXB0IHVzZXJcbiAgICogICAgIFUtPj5BOiBQcm92aWRlIGlucHV0XG4gICAqICAgICBBLT4+STogUmV0dXJuIHJlc3VsdFxuICAgKiAgICAgSS0+PlQ6IFRlc3QgcmVzdWx0XG4gICAqICAgICBhbHQgVGVzdCBwYXNzZXNcbiAgICogICAgICAgSS0+PkM6IEFzayBmb3IgY29uZmlybWF0aW9uXG4gICAqICAgICAgIEMtPj5VOiBDb25maXJtIGlucHV0XG4gICAqICAgICAgIFUtPj5DOiBQcm92aWRlIGNvbmZpcm1hdGlvblxuICAgKiAgICAgICBDLT4+STogUmV0dXJuIGNvbmZpcm1hdGlvblxuICAgKiAgICAgICBhbHQgQ29uZmlybWVkXG4gICAqICAgICAgICAgSS0tPj5DYWxsZXI6IFJldHVybiB2YWxpZCByZXN1bHRcbiAgICogICAgICAgZWxzZSBOb3QgY29uZmlybWVkXG4gICAqICAgICAgICAgSS0+Pkk6IENvbnRpbnVlIGxvb3BcbiAgICogICAgICAgZW5kXG4gICAqICAgICBlbHNlIFRlc3QgZmFpbHNcbiAgICogICAgICAgSS0+Pkk6IENvbnRpbnVlIGxvb3BcbiAgICogICAgIGVuZFxuICAgKiAgIGVuZFxuICAgKiAgIEktLT4+Q2FsbGVyOiBSZXR1cm4gdW5kZWZpbmVkIGlmIGxpbWl0IHJlYWNoZWRcbiAgICovXG4gIHN0YXRpYyBhc3luYyBpbnNpc3Q8Uj4oXG4gICAgaW5wdXQ6IFVzZXJJbnB1dCxcbiAgICB0ZXN0OiAocmVzOiBzdHJpbmcgfCBudW1iZXIpID0+IGJvb2xlYW4sXG4gICAgZGVmYXVsdENvbmZpcm1hdGlvbjogYm9vbGVhbixcbiAgICBsaW1pdCA9IDFcbiAgKTogUHJvbWlzZTxSIHwgdW5kZWZpbmVkPiB7XG4gICAgY29uc3QgbG9nID0gVXNlcklucHV0LmxvZ2dlci5mb3IodGhpcy5pbnNpc3QpO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYEluc2lzdGluZyBvbiBpbnB1dDogJHtpbnB1dC5uYW1lfSwgdGVzdDogJHt0ZXN0LnRvU3RyaW5nKCl9LCBkZWZhdWx0Q29uZmlybWF0aW9uOiAke2RlZmF1bHRDb25maXJtYXRpb259LCBsaW1pdDogJHtsaW1pdH1gXG4gICAgKTtcbiAgICBsZXQgcmVzdWx0OiBzdHJpbmcgfCBudW1iZXIgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgbGV0IGNvdW50ID0gMDtcbiAgICBsZXQgY29uZmlybWF0aW9uOiBib29sZWFuO1xuICAgIHRyeSB7XG4gICAgICBkbyB7XG4gICAgICAgIHJlc3VsdCA9IChhd2FpdCBVc2VySW5wdXQuYXNrKGlucHV0KSlbXG4gICAgICAgICAgaW5wdXQubmFtZSBhcyBrZXlvZiBBbnN3ZXJzPHN0cmluZz5cbiAgICAgICAgXSBhcyBzdHJpbmc7XG4gICAgICAgIGlmICghdGVzdChyZXN1bHQpKSB7XG4gICAgICAgICAgcmVzdWx0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbmZpcm1hdGlvbiA9IGF3YWl0IFVzZXJJbnB1dC5hc2tDb25maXJtYXRpb24oXG4gICAgICAgICAgYCR7aW5wdXQubmFtZX0tY29uZmlybWAsXG4gICAgICAgICAgYElzIHRoZSAke2lucHV0LnR5cGV9IGNvcnJlY3Q/YCxcbiAgICAgICAgICBkZWZhdWx0Q29uZmlybWF0aW9uXG4gICAgICAgICk7XG4gICAgICAgIGlmICghY29uZmlybWF0aW9uKSByZXN1bHQgPSB1bmRlZmluZWQ7XG4gICAgICB9IHdoaWxlICh0eXBlb2YgcmVzdWx0ID09PSBcInVuZGVmaW5lZFwiICYmIGxpbWl0ID4gMSAmJiBjb3VudCsrIDwgbGltaXQpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGxvZy5lcnJvcihgRXJyb3Igd2hpbGUgaW5zaXN0aW5nOiAke2V9YCk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgcmVzdWx0ID09PSBcInVuZGVmaW5lZFwiKSBsb2cuaW5mbyhcIm5vIHNlbGVjdGlvbi4uLlwiKTtcbiAgICByZXR1cm4gcmVzdWx0IGFzIFIgfCB1bmRlZmluZWQ7XG4gIH1cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXBlYXRlZGx5IGFza3MgZm9yIHRleHQgaW5wdXQgdW50aWwgYSB2YWxpZCByZXNwb25zZSBpcyBnaXZlbiBvciB0aGUgbGltaXQgaXMgcmVhY2hlZC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgaW5zaXN0cyBvbiBnZXR0aW5nIGEgdmFsaWQgdGV4dCBpbnB1dCBmcm9tIHRoZSB1c2VyLCBhbGxvd2luZyBmb3IgYSBzcGVjaWZpZWQgbnVtYmVyIG9mIGF0dGVtcHRzLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gICAqIEBwYXJhbSBxdWVzdGlvbiAtIFRoZSBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICogQHBhcmFtIHtmdW5jdGlvbihudW1iZXIpOmJvb2xlYW59IHRlc3QgLSBWYWxpZGF0b3IgZnVuY3Rpb24gcmVjZWl2aW5nIHRoZSB1c2VyIGlucHV0IGFuZCByZXR1cm5pbmcgd2hldGhlciBpdCBpcyB2YWxpZC5cbiAgICogQHBhcmFtIG1hc2sgLSBUaGUgY2hhcmFjdGVyIHVzZWQgdG8gbWFzayB0aGUgaW5wdXQgKG9wdGlvbmFsLCBmb3IgcGFzc3dvcmQtbGlrZSBpbnB1dHMpLlxuICAgKiBAcGFyYW0gaW5pdGlhbCAtIFRoZSBpbml0aWFsIHZhbHVlIHByZXNlbnRlZCB0byB0aGUgdXNlciAob3B0aW9uYWwpLlxuICAgKiBAcGFyYW0gZGVmYXVsdENvbmZpcm1hdGlvbiAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB0aGUgY29uZmlybWF0aW9uIHByb21wdCAodHJ1ZSBmb3IgeWVzLCBmYWxzZSBmb3Igbm8pLlxuICAgKiBAcGFyYW0gbGltaXQgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgYXR0ZW1wdHMgYWxsb3dlZCAoZGVmYXVsdCBpcyAtMSwgbWVhbmluZyB1bmxpbWl0ZWQpLlxuICAgKiBAcmV0dXJuIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSB2YWxpZCBpbnB1dCBvciB1bmRlZmluZWQgaWYgdGhlIGxpbWl0IGlzIHJlYWNoZWQuXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgaW5zaXN0Rm9yVGV4dChcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgcXVlc3Rpb246IHN0cmluZyxcbiAgICB0ZXN0OiAocmVzOiBzdHJpbmcpID0+IGJvb2xlYW4sXG4gICAgbWFzazogc3RyaW5nIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkLFxuICAgIGluaXRpYWw/OiBzdHJpbmcsXG4gICAgZGVmYXVsdENvbmZpcm1hdGlvbiA9IGZhbHNlLFxuICAgIGxpbWl0ID0gLTFcbiAgKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBsb2cgPSBVc2VySW5wdXQubG9nZ2VyLmZvcih0aGlzLmluc2lzdEZvclRleHQpO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYEluc2lzdGluZyBmb3IgdGV4dCBpbnB1dDogdW5kZWZpbmVkLCBxdWVzdGlvbjogJHtxdWVzdGlvbn0sIHRlc3Q6ICR7dGVzdC50b1N0cmluZygpfSwgbWFzazogJHttYXNrfSwgaW5pdGlhbDogJHtpbml0aWFsfSwgZGVmYXVsdENvbmZpcm1hdGlvbjogJHtkZWZhdWx0Q29uZmlybWF0aW9ufSwgbGltaXQ6ICR7bGltaXR9YFxuICAgICk7XG4gICAgY29uc3QgdXNlcklucHV0ID0gbmV3IFVzZXJJbnB1dChuYW1lKS5zZXRNZXNzYWdlKHF1ZXN0aW9uKTtcblxuICAgIGlmIChtYXNrKSB1c2VySW5wdXQuc2V0TWFzayhtYXNrKTtcbiAgICBpZiAodHlwZW9mIGluaXRpYWwgPT09IFwic3RyaW5nXCIpIHVzZXJJbnB1dC5zZXRJbml0aWFsKGluaXRpYWwpO1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5pbnNpc3QoXG4gICAgICB1c2VySW5wdXQsXG4gICAgICB0ZXN0IGFzIChyZXM6IHN0cmluZyB8IG51bWJlcikgPT4gYm9vbGVhbixcbiAgICAgIGRlZmF1bHRDb25maXJtYXRpb24sXG4gICAgICBsaW1pdFxuICAgICkpIGFzIHN0cmluZztcbiAgfVxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlcGVhdGVkbHkgYXNrcyBmb3IgbnVtYmVyIGlucHV0IHVudGlsIGEgdmFsaWQgcmVzcG9uc2UgaXMgZ2l2ZW4gb3IgdGhlIGxpbWl0IGlzIHJlYWNoZWQuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIGluc2lzdHMgb24gZ2V0dGluZyBhIHZhbGlkIG51bWJlciBpbnB1dCBmcm9tIHRoZSB1c2VyLCBhbGxvd2luZyBmb3IgYSBzcGVjaWZpZWQgbnVtYmVyIG9mIGF0dGVtcHRzLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9tcHQsIHVzZWQgYXMgdGhlIGtleSBpbiB0aGUgcmV0dXJuZWQgYW5zd2VycyBvYmplY3QuXG4gICAqIEBwYXJhbSBxdWVzdGlvbiAtIFRoZSBtZXNzYWdlIGRpc3BsYXllZCB0byB0aGUgdXNlci5cbiAgICogQHBhcmFtIHRlc3QgLSBBIGZ1bmN0aW9uIHRvIHZhbGlkYXRlIHRoZSB1c2VyJ3MgaW5wdXQuXG4gICAqIEBwYXJhbSBtaW4gLSBUaGUgbWluaW11bSBhbGxvd2VkIHZhbHVlIChvcHRpb25hbCkuXG4gICAqIEBwYXJhbSBtYXggLSBUaGUgbWF4aW11bSBhbGxvd2VkIHZhbHVlIChvcHRpb25hbCkuXG4gICAqIEBwYXJhbSBpbml0aWFsIC0gVGhlIGluaXRpYWwgdmFsdWUgcHJlc2VudGVkIHRvIHRoZSB1c2VyIChvcHRpb25hbCkuXG4gICAqIEBwYXJhbSBkZWZhdWx0Q29uZmlybWF0aW9uIC0gVGhlIGRlZmF1bHQgdmFsdWUgZm9yIHRoZSBjb25maXJtYXRpb24gcHJvbXB0ICh0cnVlIGZvciB5ZXMsIGZhbHNlIGZvciBubykuXG4gICAqIEBwYXJhbSBsaW1pdCAtIFRoZSBtYXhpbXVtIG51bWJlciBvZiBhdHRlbXB0cyBhbGxvd2VkIChkZWZhdWx0IGlzIC0xLCBtZWFuaW5nIHVubGltaXRlZCkuXG4gICAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHZhbGlkIGlucHV0IG9yIHVuZGVmaW5lZCBpZiB0aGUgbGltaXQgaXMgcmVhY2hlZC5cbiAgICovXG4gIHN0YXRpYyBhc3luYyBpbnNpc3RGb3JOdW1iZXIoXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIHF1ZXN0aW9uOiBzdHJpbmcsXG4gICAgdGVzdDogKHJlczogbnVtYmVyKSA9PiBib29sZWFuLFxuICAgIG1pbj86IG51bWJlcixcbiAgICBtYXg/OiBudW1iZXIsXG4gICAgaW5pdGlhbD86IG51bWJlcixcbiAgICBkZWZhdWx0Q29uZmlybWF0aW9uID0gZmFsc2UsXG4gICAgbGltaXQgPSAtMVxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGxvZyA9IFVzZXJJbnB1dC5sb2dnZXIuZm9yKHRoaXMuaW5zaXN0Rm9yTnVtYmVyKTtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBJbnNpc3RpbmcgZm9yIG51bWJlciBpbnB1dDogdW5kZWZpbmVkLCBxdWVzdGlvbjogJHtxdWVzdGlvbn0sIHRlc3Q6ICR7dGVzdC50b1N0cmluZygpfSwgbWluOiAke21pbn0sIG1heDogJHttYXh9LCBpbml0aWFsOiAke2luaXRpYWx9LCBkZWZhdWx0Q29uZmlybWF0aW9uOiAke2RlZmF1bHRDb25maXJtYXRpb259LCBsaW1pdDogJHtsaW1pdH1gXG4gICAgKTtcbiAgICBjb25zdCB1c2VySW5wdXQgPSBuZXcgVXNlcklucHV0KG5hbWUpXG4gICAgICAuc2V0TWVzc2FnZShxdWVzdGlvbilcbiAgICAgIC5zZXRUeXBlKFwibnVtYmVyXCIpO1xuXG4gICAgaWYgKHR5cGVvZiBtaW4gPT09IFwibnVtYmVyXCIpIHVzZXJJbnB1dC5zZXRNaW4obWluKTtcblxuICAgIGlmICh0eXBlb2YgbWF4ID09PSBcIm51bWJlclwiKSB1c2VySW5wdXQuc2V0TWF4KG1heCk7XG5cbiAgICBpZiAodHlwZW9mIGluaXRpYWwgPT09IFwibnVtYmVyXCIpIHVzZXJJbnB1dC5zZXRJbml0aWFsKGluaXRpYWwpO1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5pbnNpc3QoXG4gICAgICB1c2VySW5wdXQsXG4gICAgICB0ZXN0IGFzIChyZXM6IHN0cmluZyB8IG51bWJlcikgPT4gYm9vbGVhbixcbiAgICAgIGRlZmF1bHRDb25maXJtYXRpb24sXG4gICAgICBsaW1pdFxuICAgICkpIGFzIG51bWJlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUGFyc2VzIGNvbW1hbmQtbGluZSBhcmd1bWVudHMgYmFzZWQgb24gdGhlIHByb3ZpZGVkIG9wdGlvbnMuXG4gICAqIEBzdW1tYXJ5IFVzZXMgTm9kZS5qcydzIHV0aWwucGFyc2VBcmdzIHRvIHBhcnNlIGNvbW1hbmQtbGluZSBhcmd1bWVudHMgYW5kIHJldHVybiB0aGUgcmVzdWx0LlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgcGFyc2luZyBhcmd1bWVudHMuXG4gICAqIEByZXR1cm4gQW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIHBhcnNlZCBhcmd1bWVudHMuXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IEMgYXMgQ2FsbGVyXG4gICAqICAgcGFydGljaXBhbnQgUCBhcyBwYXJzZUFyZ3MgbWV0aG9kXG4gICAqICAgcGFydGljaXBhbnQgVSBhcyB1dGlsLnBhcnNlQXJnc1xuICAgKiAgIEMtPj5QOiBDYWxsIHdpdGggb3B0aW9uc1xuICAgKiAgIFAtPj5QOiBQcmVwYXJlIGFyZ3Mgb2JqZWN0XG4gICAqICAgUC0+PlU6IENhbGwgcGFyc2VBcmdzIHdpdGggcHJlcGFyZWQgYXJnc1xuICAgKiAgIFUtPj5QOiBSZXR1cm4gcGFyc2VkIHJlc3VsdFxuICAgKiAgIFAtLT4+QzogUmV0dXJuIFBhcnNlQXJnc1Jlc3VsdFxuICAgKi9cbiAgc3RhdGljIHBhcnNlQXJncyhvcHRpb25zOiBQYXJzZUFyZ3NPcHRpb25zQ29uZmlnKTogUGFyc2VBcmdzUmVzdWx0IHtcbiAgICBjb25zdCBsb2cgPSBVc2VySW5wdXQubG9nZ2VyLmZvcih0aGlzLnBhcnNlQXJncyk7XG4gICAgY29uc3QgYXJnczogUGFyc2VBcmdzQ29uZmlnID0ge1xuICAgICAgYXJnczogcHJvY2Vzcy5hcmd2LnNsaWNlKDIpLFxuICAgICAgb3B0aW9uczogb3B0aW9ucyxcbiAgICB9O1xuICAgIGxvZy5kZWJ1ZyhgUGFyc2luZyBhcmd1bWVudHM6ICR7SlNPTi5zdHJpbmdpZnkoYXJncywgbnVsbCwgMil9YCk7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBwYXJzZUFyZ3MoYXJncyk7XG4gICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIGxvZy5kZWJ1ZyhcbiAgICAgICAgYEVycm9yIHdoaWxlIHBhcnNpbmcgYXJndW1lbnRzOlxcbiR7SlNPTi5zdHJpbmdpZnkoYXJncywgbnVsbCwgMil9XFxuIHwgb3B0aW9uc1xcbiR7SlNPTi5zdHJpbmdpZnkob3B0aW9ucywgbnVsbCwgMil9XFxuIHwgJHtlcnJvcn1gXG4gICAgICApO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciB3aGlsZSBwYXJzaW5nIGFyZ3VtZW50czogJHtlcnJvcn1gKTtcbiAgICB9XG4gIH1cbn1cbiIsIi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgY29tbWFuZCBvcHRpb25zIGZvciBDTEkgY29tbWFuZHMuXG4gKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSBzdHJ1Y3R1cmUgYW5kIGRlZmF1bHQgdmFsdWVzIGZvciBjb21tb24gY29tbWFuZC1saW5lIG9wdGlvbnMgdXNlZCBhY3Jvc3MgdmFyaW91cyBDTEkgY29tbWFuZHMuXG4gKiBAY29uc3QgRGVmYXVsdENvbW1hbmRPcHRpb25zXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBEZWZhdWx0Q29tbWFuZE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSB2ZXJib3NlIC0gVmVyYm9zaXR5IGxldmVsIG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB2ZXJib3NlLnR5cGUgLSBUaGUgdHlwZSBvZiB0aGUgdmVyYm9zZSBvcHRpb24gKG51bWJlcikuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdmVyYm9zZS5zaG9ydCAtIFRoZSBzaG9ydCBmbGFnIGZvciB0aGUgdmVyYm9zZSBvcHRpb24gKFYpLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IHZlcmJvc2UuZGVmYXVsdCAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB2ZXJib3NpdHkgKDApLlxuICogQHByb3BlcnR5IHtPYmplY3R9IHZlcnNpb24gLSBWZXJzaW9uIGRpc3BsYXkgb3B0aW9uLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHZlcnNpb24udHlwZSAtIFRoZSB0eXBlIG9mIHRoZSB2ZXJzaW9uIG9wdGlvbiAoYm9vbGVhbikuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdmVyc2lvbi5zaG9ydCAtIFRoZSBzaG9ydCBmbGFnIGZvciB0aGUgdmVyc2lvbiBvcHRpb24gKHYpLlxuICogQHByb3BlcnR5IHt1bmRlZmluZWR9IHZlcnNpb24uZGVmYXVsdCAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciB2ZXJzaW9uIGRpc3BsYXkgKHVuZGVmaW5lZCkuXG4gKiBAcHJvcGVydHkge09iamVjdH0gaGVscCAtIEhlbHAgZGlzcGxheSBvcHRpb24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gaGVscC50eXBlIC0gVGhlIHR5cGUgb2YgdGhlIGhlbHAgb3B0aW9uIChib29sZWFuKS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBoZWxwLnNob3J0IC0gVGhlIHNob3J0IGZsYWcgZm9yIHRoZSBoZWxwIG9wdGlvbiAoaCkuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGhlbHAuZGVmYXVsdCAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciBoZWxwIGRpc3BsYXkgKGZhbHNlKS5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBsb2dMZXZlbCAtIExvZyBsZXZlbCBvcHRpb24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gbG9nTGV2ZWwudHlwZSAtIFRoZSB0eXBlIG9mIHRoZSBsb2dMZXZlbCBvcHRpb24gKHN0cmluZykuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gbG9nTGV2ZWwuZGVmYXVsdCAtIFRoZSBkZWZhdWx0IHZhbHVlIGZvciBsb2cgbGV2ZWwgKFwiaW5mb1wiKS5cbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBsb2dTdHlsZSAtIExvZyBzdHlsaW5nIG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBsb2dTdHlsZS50eXBlIC0gVGhlIHR5cGUgb2YgdGhlIGxvZ1N0eWxlIG9wdGlvbiAoYm9vbGVhbikuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGxvZ1N0eWxlLmRlZmF1bHQgLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgbG9nIHN0eWxpbmcgKHRydWUpLlxuICogQHByb3BlcnR5IHtPYmplY3R9IHRpbWVzdGFtcCAtIFRpbWVzdGFtcCBkaXNwbGF5IG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB0aW1lc3RhbXAudHlwZSAtIFRoZSB0eXBlIG9mIHRoZSB0aW1lc3RhbXAgb3B0aW9uIChib29sZWFuKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gdGltZXN0YW1wLmRlZmF1bHQgLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgdGltZXN0YW1wIGRpc3BsYXkgKHRydWUpLlxuICogQHByb3BlcnR5IHtPYmplY3R9IGJhbm5lciAtIEJhbm5lciBkaXNwbGF5IG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBiYW5uZXIudHlwZSAtIFRoZSB0eXBlIG9mIHRoZSBiYW5uZXIgb3B0aW9uIChib29sZWFuKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gYmFubmVyLmRlZmF1bHQgLSBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgYmFubmVyIGRpc3BsYXkgKGZhbHNlKS5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGNvbnN0IERlZmF1bHRDb21tYW5kT3B0aW9ucyA9IHtcbiAgdmVyYm9zZToge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICAgIHNob3J0OiBcIlZcIixcbiAgICBkZWZhdWx0OiB1bmRlZmluZWQsXG4gIH0sXG4gIHZlcnNpb246IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgICBzaG9ydDogXCJ2XCIsXG4gICAgZGVmYXVsdDogdW5kZWZpbmVkLFxuICB9LFxuICBoZWxwOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgc2hvcnQ6IFwiaFwiLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxuICBsb2dMZXZlbDoge1xuICAgIHR5cGU6IFwic3RyaW5nXCIsXG4gICAgZGVmYXVsdDogXCJpbmZvXCIsXG4gIH0sXG4gIGxvZ1N0eWxlOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgfSxcbiAgdGltZXN0YW1wOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgfSxcbiAgYmFubmVyOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogdHJ1ZSxcbiAgfSxcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgY29tbWFuZCB2YWx1ZXMgZGVyaXZlZCBmcm9tIERlZmF1bHRDb21tYW5kT3B0aW9ucy5cbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYW4gb2JqZWN0IHdpdGggdGhlIGRlZmF1bHQgdmFsdWVzIG9mIGFsbCBvcHRpb25zIGRlZmluZWQgaW4gRGVmYXVsdENvbW1hbmRPcHRpb25zLlxuICogQGNvbnN0IERlZmF1bHRDb21tYW5kVmFsdWVzXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBEZWZhdWx0Q29tbWFuZFZhbHVlc1xuICogQHByb3BlcnR5IHt1bmtub3dufSBba2V5OiBzdHJpbmddIC0gVGhlIGRlZmF1bHQgdmFsdWUgZm9yIGVhY2ggb3B0aW9uIGluIERlZmF1bHRDb21tYW5kT3B0aW9ucy5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGNvbnN0IERlZmF1bHRDb21tYW5kVmFsdWVzOiB7XG4gIFtrIGluIGtleW9mIHR5cGVvZiBEZWZhdWx0Q29tbWFuZE9wdGlvbnNdOiB1bmtub3duO1xufSA9IE9iamVjdC5rZXlzKERlZmF1bHRDb21tYW5kT3B0aW9ucykucmVkdWNlKFxuICAoYWNjOiBSZWNvcmQ8a2V5b2YgdHlwZW9mIERlZmF1bHRDb21tYW5kT3B0aW9ucywgdW5rbm93bj4sIGtleTogc3RyaW5nKSA9PiB7XG4gICAgYWNjW2tleSBhcyBrZXlvZiB0eXBlb2YgRGVmYXVsdENvbW1hbmRPcHRpb25zXSA9XG4gICAgICBEZWZhdWx0Q29tbWFuZE9wdGlvbnNba2V5IGFzIGtleW9mIHR5cGVvZiBEZWZhdWx0Q29tbWFuZE9wdGlvbnNdLmRlZmF1bHQ7XG4gICAgcmV0dXJuIGFjYztcbiAgfSxcbiAge30gYXMgUmVjb3JkPGtleW9mIHR5cGVvZiBEZWZhdWx0Q29tbWFuZFZhbHVlcywgdW5rbm93bj5cbik7XG4iLCIvKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IGVuY29kaW5nIGZvciB0ZXh0IG9wZXJhdGlvbnMuXG4gKiBAc3VtbWFyeSBUaGUgc3RhbmRhcmQgVVRGLTggZW5jb2RpbmcgdXNlZCBmb3IgdGV4dCBwcm9jZXNzaW5nLlxuICogQGNvbnN0IHtzdHJpbmd9IEVuY29kaW5nXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBFbmNvZGluZyA9IFwidXRmLThcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVndWxhciBleHByZXNzaW9uIGZvciBzZW1hbnRpYyB2ZXJzaW9uaW5nLlxuICogQHN1bW1hcnkgQSByZWdleCBwYXR0ZXJuIHRvIG1hdGNoIGFuZCBwYXJzZSBzZW1hbnRpYyB2ZXJzaW9uIHN0cmluZ3MuXG4gKiBAY29uc3Qge1JlZ0V4cH0gU2VtVmVyc2lvblJlZ2V4XG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBTZW1WZXJzaW9uUmVnZXggPVxuICAvXihcXGQrKVxcLihcXGQrKVxcLihcXGQrKSg/Oi0oWzAtOUEtWmEtei1dKyg/OlxcLlswLTlBLVphLXpdKSkpL2c7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVudW0gZm9yIHNlbWFudGljIHZlcnNpb24gY29tcG9uZW50cy5cbiAqIEBzdW1tYXJ5IERlZmluZXMgdGhlIHRocmVlIGxldmVscyBvZiBzZW1hbnRpYyB2ZXJzaW9uaW5nOiBQQVRDSCwgTUlOT1IsIGFuZCBNQUpPUi5cbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBlbnVtIFNlbVZlcnNpb24ge1xuICAvKiogUGF0Y2ggdmVyc2lvbiBmb3IgYmFja3dhcmRzLWNvbXBhdGlibGUgYnVnIGZpeGVzLiAqL1xuICBQQVRDSCA9IFwicGF0Y2hcIixcbiAgLyoqIE1pbm9yIHZlcnNpb24gZm9yIGJhY2t3YXJkcy1jb21wYXRpYmxlIG5ldyBmZWF0dXJlcy4gKi9cbiAgTUlOT1IgPSBcIm1pbm9yXCIsXG4gIC8qKiBNYWpvciB2ZXJzaW9uIGZvciBjaGFuZ2VzIHRoYXQgYnJlYWsgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkuICovXG4gIE1BSk9SID0gXCJtYWpvclwiLFxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBGbGFnIHRvIGluZGljYXRlIG5vbi1DSSBlbnZpcm9ubWVudC5cbiAqIEBzdW1tYXJ5IFVzZWQgdG8gc3BlY2lmeSB0aGF0IGEgY29tbWFuZCBzaG91bGQgcnVuIG91dHNpZGUgb2YgYSBDb250aW51b3VzIEludGVncmF0aW9uIGVudmlyb25tZW50LlxuICogQGNvbnN0IHtzdHJpbmd9IE5vQ0lGTGFnXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBOb0NJRkxhZyA9IFwiLW5vLWNpXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEtleSBmb3IgdGhlIHNldHVwIHNjcmlwdCBpbiBwYWNrYWdlLmpzb24uXG4gKiBAc3VtbWFyeSBJZGVudGlmaWVzIHRoZSBzY3JpcHQgdGhhdCBydW5zIGFmdGVyIHBhY2thZ2UgaW5zdGFsbGF0aW9uLlxuICogQGNvbnN0IHtzdHJpbmd9IFNldHVwU2NyaXB0S2V5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBTZXR1cFNjcmlwdEtleSA9IFwicG9zdGluc3RhbGxcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRW51bSBmb3IgdmFyaW91cyBhdXRoZW50aWNhdGlvbiB0b2tlbnMuXG4gKiBAc3VtbWFyeSBEZWZpbmVzIHRoZSBmaWxlIG5hbWVzIGZvciBzdG9yaW5nIGRpZmZlcmVudCB0eXBlcyBvZiBhdXRoZW50aWNhdGlvbiB0b2tlbnMuXG4gKiBAZW51bSB7c3RyaW5nfVxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZW51bSBUb2tlbnMge1xuICAvKiogR2l0IGF1dGhlbnRpY2F0aW9uIHRva2VuIGZpbGUgbmFtZS4gKi9cbiAgR0lUID0gXCIudG9rZW5cIixcbiAgLyoqIE5QTSBhdXRoZW50aWNhdGlvbiB0b2tlbiBmaWxlIG5hbWUuICovXG4gIE5QTSA9IFwiLm5wbXRva2VuXCIsXG4gIC8qKiBEb2NrZXIgYXV0aGVudGljYXRpb24gdG9rZW4gZmlsZSBuYW1lLiAqL1xuICBET0NLRVIgPSBcIi5kb2NrZXJ0b2tlblwiLFxuICAvKiogQ29uZmx1ZW5jZSBhdXRoZW50aWNhdGlvbiB0b2tlbiBmaWxlIG5hbWUuICovXG4gIENPTkZMVUVOQ0UgPSBcIi5jb25mbHVlbmNlLXRva2VuXCIsXG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvZGUgdXNlZCB0byBpbmRpY2F0ZSBhbiBvcGVyYXRpb24gd2FzIGFib3J0ZWQuXG4gKiBAc3VtbWFyeSBTdGFuZGFyZCBtZXNzYWdlIHVzZWQgd2hlbiBhIHByb2Nlc3MgaXMgbWFudWFsbHkgdGVybWluYXRlZC5cbiAqIEBjb25zdCB7c3RyaW5nfSBBYm9ydENvZGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGNvbnN0IEFib3J0Q29kZSA9IFwiQWJvcnRlZFwiO1xuIiwiaW1wb3J0IHsgRW5jb2RpbmcgfSBmcm9tIFwiLi4vdXRpbHMvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBPdXRwdXRXcml0ZXIgfSBmcm9tIFwiLi9PdXRwdXRXcml0ZXJcIjtcbmltcG9ydCB7IFByb21pc2VFeGVjdXRvciB9IGZyb20gXCIuLi91dGlscy90eXBlc1wiO1xuaW1wb3J0IHsgT3V0cHV0VHlwZSB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBzdHlsZSB9IGZyb20gXCJzdHlsZWQtc3RyaW5nLWJ1aWxkZXJcIjtcbmltcG9ydCB7IExvZ2dlciwgTG9nZ2luZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuaW1wb3J0IHsgcGFyc2UgfSBmcm9tIFwic2hlbGwtcXVvdGVcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQSBzdGFuZGFyZCBvdXRwdXQgd3JpdGVyIGZvciBoYW5kbGluZyBjb21tYW5kIGV4ZWN1dGlvbiBvdXRwdXQuXG4gKiBAc3VtbWFyeSBUaGlzIGNsYXNzIGltcGxlbWVudHMgdGhlIE91dHB1dFdyaXRlciBpbnRlcmZhY2UgYW5kIHByb3ZpZGVzIG1ldGhvZHMgZm9yXG4gKiBoYW5kbGluZyB2YXJpb3VzIHR5cGVzIG9mIG91dHB1dCBmcm9tIGNvbW1hbmQgZXhlY3V0aW9uLCBpbmNsdWRpbmcgc3RhbmRhcmQgb3V0cHV0LFxuICogZXJyb3Igb3V0cHV0LCBhbmQgZXhpdCBjb2Rlcy4gSXQgYWxzbyBpbmNsdWRlcyB1dGlsaXR5IG1ldGhvZHMgZm9yIHBhcnNpbmcgY29tbWFuZHNcbiAqIGFuZCByZXNvbHZpbmcgb3IgcmVqZWN0aW5nIHByb21pc2VzIGJhc2VkIG9uIGV4ZWN1dGlvbiByZXN1bHRzLlxuICpcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgdGhlIHJlc29sdmVkIHZhbHVlLCBkZWZhdWx0aW5nIHRvIHN0cmluZy5cbiAqXG4gKiBAcGFyYW0gY21kIC0gVGhlIGNvbW1hbmQgc3RyaW5nIHRvIGJlIGV4ZWN1dGVkLlxuICogQHBhcmFtIGxvY2sgLSBBIFByb21pc2VFeGVjdXRvciB0byBjb250cm9sIHRoZSBhc3luY2hyb25vdXMgZmxvdy5cbiAqIEBwYXJhbSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgKHVudXNlZCBpbiB0aGUgY3VycmVudCBpbXBsZW1lbnRhdGlvbikuXG4gKlxuICogQGNsYXNzXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgU3RhbmRhcmRPdXRwdXRXcml0ZXIgfSBmcm9tICdAZGVjYWYtdHMvdXRpbHMnO1xuICogaW1wb3J0IHsgUHJvbWlzZUV4ZWN1dG9yIH0gZnJvbSAnQGRlY2FmLXRzL3V0aWxzJztcbiAqXG4gKiAvLyBDcmVhdGUgYSBwcm9taXNlIGV4ZWN1dG9yXG4gKiBjb25zdCBleGVjdXRvcjogUHJvbWlzZUV4ZWN1dG9yPHN0cmluZz4gPSB7XG4gKiAgIHJlc29sdmU6ICh2YWx1ZSkgPT4gY29uc29sZS5sb2coYFJlc29sdmVkOiAke3ZhbHVlfWApLFxuICogICByZWplY3Q6IChlcnJvcikgPT4gY29uc29sZS5lcnJvcihgUmVqZWN0ZWQ6ICR7ZXJyb3IubWVzc2FnZX1gKVxuICogfTtcbiAqXG4gKiAvLyBDcmVhdGUgYSBzdGFuZGFyZCBvdXRwdXQgd3JpdGVyXG4gKiBjb25zdCB3cml0ZXIgPSBuZXcgU3RhbmRhcmRPdXRwdXRXcml0ZXIoJ2xzIC1sYScsIGV4ZWN1dG9yKTtcbiAqXG4gKiAvLyBVc2UgdGhlIHdyaXRlciB0byBoYW5kbGUgY29tbWFuZCBvdXRwdXRcbiAqIHdyaXRlci5kYXRhKCdGaWxlIGxpc3Qgb3V0cHV0Li4uJyk7XG4gKiB3cml0ZXIuZXhpdCgwLCBbJ0NvbW1hbmQgZXhlY3V0ZWQgc3VjY2Vzc2Z1bGx5J10pO1xuICogYGBgXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgU3RhbmRhcmRPdXRwdXRXcml0ZXJcbiAqICAgcGFydGljaXBhbnQgTG9nZ2VyXG4gKiAgIHBhcnRpY2lwYW50IFByb21pc2VFeGVjdXRvclxuICpcbiAqICAgQ2xpZW50LT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IG5ldyBTdGFuZGFyZE91dHB1dFdyaXRlcihjbWQsIGxvY2spXG4gKiAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+TG9nZ2VyOiBMb2dnaW5nLmZvcihjbWQpXG4gKlxuICogICBDbGllbnQtPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogZGF0YShjaHVuaylcbiAqICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogbG9nKFwic3Rkb3V0XCIsIGNodW5rKVxuICogICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PkxvZ2dlcjogbG9nZ2VyLmluZm8obG9nKVxuICpcbiAqICAgQ2xpZW50LT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IGVycm9yKGNodW5rKVxuICogICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiBsb2coXCJzdGRlcnJcIiwgY2h1bmspXG4gKiAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+TG9nZ2VyOiBsb2dnZXIuaW5mbyhsb2cpXG4gKlxuICogICBDbGllbnQtPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogZXhpdChjb2RlLCBsb2dzKVxuICogICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiBsb2coXCJzdGRvdXRcIiwgZXhpdE1lc3NhZ2UpXG4gKiAgIGFsdCBjb2RlID09PSAwXG4gKiAgICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogcmVzb2x2ZShsb2dzKVxuICogICAgIFN0YW5kYXJkT3V0cHV0V3JpdGVyLT4+UHJvbWlzZUV4ZWN1dG9yOiBsb2NrLnJlc29sdmUocmVhc29uKVxuICogICBlbHNlIGNvZGUgIT09IDBcbiAqICAgICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PlN0YW5kYXJkT3V0cHV0V3JpdGVyOiByZWplY3QoZXJyb3IpXG4gKiAgICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5Qcm9taXNlRXhlY3V0b3I6IGxvY2sucmVqZWN0KHJlYXNvbilcbiAqICAgZW5kXG4gKi9cbmV4cG9ydCBjbGFzcyBTdGFuZGFyZE91dHB1dFdyaXRlcjxSID0gc3RyaW5nPiBpbXBsZW1lbnRzIE91dHB1dFdyaXRlciB7XG4gIHByb3RlY3RlZCBsb2dnZXI6IExvZ2dlcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgY21kOiBzdHJpbmcsXG4gICAgcHJvdGVjdGVkIGxvY2s6IFByb21pc2VFeGVjdXRvcjxSPixcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgLi4uYXJnczogdW5rbm93bltdXG4gICkge1xuICAgIHRoaXMubG9nZ2VyID0gTG9nZ2luZy5mb3IodGhpcy5jbWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBMb2dzIG91dHB1dCB0byB0aGUgY29uc29sZS5cbiAgICogQHN1bW1hcnkgRm9ybWF0cyBhbmQgbG9ncyB0aGUgZ2l2ZW4gZGF0YSB3aXRoIGEgdGltZXN0YW1wIGFuZCB0eXBlIGluZGljYXRvci5cbiAgICpcbiAgICogQHBhcmFtIHR5cGUgLSBUaGUgdHlwZSBvZiBvdXRwdXQgKHN0ZG91dCBvciBzdGRlcnIpLlxuICAgKiBAcGFyYW0gZGF0YSAtIFRoZSBkYXRhIHRvIGJlIGxvZ2dlZC5cbiAgICovXG4gIHByb3RlY3RlZCBsb2codHlwZTogT3V0cHV0VHlwZSwgZGF0YTogc3RyaW5nIHwgQnVmZmVyKSB7XG4gICAgZGF0YSA9IEJ1ZmZlci5pc0J1ZmZlcihkYXRhKSA/IGRhdGEudG9TdHJpbmcoRW5jb2RpbmcpIDogZGF0YTtcbiAgICBjb25zdCBsb2cgPSB0eXBlID09PSBcInN0ZGVyclwiID8gc3R5bGUoZGF0YSkucmVkLnRleHQgOiBkYXRhO1xuICAgIHRoaXMubG9nZ2VyLmluZm8obG9nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBzdGFuZGFyZCBvdXRwdXQgZGF0YS5cbiAgICogQHN1bW1hcnkgTG9ncyB0aGUgZ2l2ZW4gY2h1bmsgYXMgc3RhbmRhcmQgb3V0cHV0LlxuICAgKlxuICAgKiBAcGFyYW0gY2h1bmsgLSBUaGUgZGF0YSBjaHVuayB0byBiZSBsb2dnZWQuXG4gICAqL1xuICBkYXRhKGNodW5rOiBhbnkpIHtcbiAgICB0aGlzLmxvZyhcInN0ZG91dFwiLCBTdHJpbmcoY2h1bmspKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBlcnJvciBvdXRwdXQgZGF0YS5cbiAgICogQHN1bW1hcnkgTG9ncyB0aGUgZ2l2ZW4gY2h1bmsgYXMgZXJyb3Igb3V0cHV0LlxuICAgKlxuICAgKiBAcGFyYW0gY2h1bmsgLSBUaGUgZXJyb3IgZGF0YSBjaHVuayB0byBiZSBsb2dnZWQuXG4gICAqL1xuICBlcnJvcihjaHVuazogYW55KSB7XG4gICAgdGhpcy5sb2coXCJzdGRlcnJcIiwgU3RyaW5nKGNodW5rKSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgZXJyb3Igb2JqZWN0cy5cbiAgICogQHN1bW1hcnkgTG9ncyB0aGUgZXJyb3IgbWVzc2FnZSBmcm9tIHRoZSBnaXZlbiBFcnJvciBvYmplY3QuXG4gICAqXG4gICAqIEBwYXJhbSBlcnIgLSBUaGUgRXJyb3Igb2JqZWN0IHRvIGJlIGxvZ2dlZC5cbiAgICovXG4gIGVycm9ycyhlcnI6IEVycm9yKSB7XG4gICAgdGhpcy5sb2coXCJzdGRlcnJcIiwgYEVycm9yIGV4ZWN1dGluZyBjb21tYW5kIGV4aXRlZCA6ICR7ZXJyfWApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBIYW5kbGVzIHRoZSBleGl0IG9mIGEgY29tbWFuZC5cbiAgICogQHN1bW1hcnkgTG9ncyB0aGUgZXhpdCBjb2RlIGFuZCByZXNvbHZlcyBvciByZWplY3RzIHRoZSBwcm9taXNlIGJhc2VkIG9uIHRoZSBjb2RlLlxuICAgKlxuICAgKiBAcGFyYW0gY29kZSAtIFRoZSBleGl0IGNvZGUgb2YgdGhlIGNvbW1hbmQuXG4gICAqIEBwYXJhbSBsb2dzIC0gQXJyYXkgb2YgbG9nIG1lc3NhZ2VzIHRvIGJlIHByb2Nlc3NlZCBiZWZvcmUgZXhpdGluZy5cbiAgICovXG4gIGV4aXQoY29kZTogbnVtYmVyIHwgc3RyaW5nLCBsb2dzOiBzdHJpbmdbXSkge1xuICAgIHRoaXMubG9nKFxuICAgICAgXCJzdGRvdXRcIixcbiAgICAgIGBjb21tYW5kIGV4aXRlZCBjb2RlIDogJHtjb2RlID09PSAwID8gc3R5bGUoY29kZS50b1N0cmluZygpKS5ncmVlbi50ZXh0IDogc3R5bGUoY29kZSA9PT0gbnVsbCA/IFwibnVsbFwiIDogY29kZS50b1N0cmluZygpKS5yZWQudGV4dH1gXG4gICAgKTtcbiAgICBpZiAoY29kZSA9PT0gMCkge1xuICAgICAgdGhpcy5yZXNvbHZlKGxvZ3MubWFwKChsKSA9PiBsLnRyaW0oKSkuam9pbihcIlxcblwiKSBhcyBSKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZWplY3QobmV3IEVycm9yKGxvZ3MubGVuZ3RoID8gbG9ncy5qb2luKFwiXFxuXCIpIDogY29kZS50b1N0cmluZygpKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQYXJzZXMgYSBjb21tYW5kIHN0cmluZyBvciBhcnJheSBpbnRvIGNvbXBvbmVudHMuXG4gICAqIEBzdW1tYXJ5IENvbnZlcnRzIHRoZSBjb21tYW5kIGludG8gYSBjb25zaXN0ZW50IGZvcm1hdCBhbmQgc3RvcmVzIGl0LCB0aGVuIHJldHVybnMgaXQgc3BsaXQgaW50byBjb21tYW5kIGFuZCBhcmd1bWVudHMuXG4gICAqXG4gICAqIEBwYXJhbSBjb21tYW5kIC0gVGhlIGNvbW1hbmQgYXMgYSBzdHJpbmcgb3IgYXJyYXkgb2Ygc3RyaW5ncy5cbiAgICogQHJldHVybiBBIHR1cGxlIGNvbnRhaW5pbmcgdGhlIGNvbW1hbmQgYW5kIGl0cyBhcmd1bWVudHMgYXMgc2VwYXJhdGUgZWxlbWVudHMuXG4gICAqL1xuICBwYXJzZUNvbW1hbmQoY29tbWFuZDogc3RyaW5nIHwgc3RyaW5nW10pOiBbc3RyaW5nLCBzdHJpbmdbXV0ge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbW1hbmQpKSB7XG4gICAgICB0aGlzLmNtZCA9IGNvbW1hbmQuam9pbihcIiBcIik7XG4gICAgICByZXR1cm4gW2NvbW1hbmRbMF0sIGNvbW1hbmQuc2xpY2UoMSldO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcnRzID0gcGFyc2UoY29tbWFuZClcbiAgICAgIC5maWx0ZXIoKHApID0+IHR5cGVvZiBwID09PSBcInN0cmluZ1wiKVxuICAgICAgLm1hcChTdHJpbmcpO1xuXG4gICAgdGhpcy5jbWQgPSBwYXJ0cy5qb2luKFwiIFwiKTtcbiAgICByZXR1cm4gW3BhcnRzWzBdLCBwYXJ0cy5zbGljZSgxKV07XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlc29sdmVzIHRoZSBwcm9taXNlIHdpdGggYSBzdWNjZXNzIG1lc3NhZ2UuXG4gICAqIEBzdW1tYXJ5IExvZ3MgYSBzdWNjZXNzIG1lc3NhZ2UgYW5kIHJlc29sdmVzIHRoZSBwcm9taXNlIHdpdGggdGhlIGdpdmVuIHJlYXNvbi5cbiAgICpcbiAgICogQHBhcmFtIHJlYXNvbiAtIFRoZSByZWFzb24gZm9yIHJlc29sdmluZyB0aGUgcHJvbWlzZS5cbiAgICovXG4gIHByb3RlY3RlZCByZXNvbHZlKHJlYXNvbjogUikge1xuICAgIHRoaXMubG9nKFxuICAgICAgXCJzdGRvdXRcIixcbiAgICAgIGAke3RoaXMuY21kfSBleGVjdXRlZCBzdWNjZXNzZnVsbHk6ICR7c3R5bGUocmVhc29uID8gXCJyYW4gdG8gY29tcGxldGlvblwiIDogKHJlYXNvbiBhcyBzdHJpbmcpKS5ncmVlbn1gXG4gICAgKTtcbiAgICB0aGlzLmxvY2sucmVzb2x2ZShyZWFzb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZWplY3RzIHRoZSBwcm9taXNlIHdpdGggYW4gZXJyb3IgbWVzc2FnZS5cbiAgICogQHN1bW1hcnkgTG9ncyBhbiBlcnJvciBtZXNzYWdlIGFuZCByZWplY3RzIHRoZSBwcm9taXNlIHdpdGggdGhlIGdpdmVuIHJlYXNvbi5cbiAgICpcbiAgICogQHBhcmFtIHJlYXNvbiAtIFRoZSByZWFzb24gZm9yIHJlamVjdGluZyB0aGUgcHJvbWlzZSwgZWl0aGVyIGEgbnVtYmVyIChleGl0IGNvZGUpIG9yIGEgc3RyaW5nLlxuICAgKi9cbiAgcHJvdGVjdGVkIHJlamVjdChyZWFzb246IG51bWJlciB8IHN0cmluZyB8IEVycm9yKSB7XG4gICAgaWYgKCEocmVhc29uIGluc3RhbmNlb2YgRXJyb3IpKSB7XG4gICAgICByZWFzb24gPSBuZXcgRXJyb3IoXG4gICAgICAgIHR5cGVvZiByZWFzb24gPT09IFwibnVtYmVyXCIgPyBgRXhpdCBjb2RlICR7cmVhc29ufWAgOiByZWFzb25cbiAgICAgICk7XG4gICAgfVxuICAgIHRoaXMubG9nKFxuICAgICAgXCJzdGRlcnJcIixcbiAgICAgIGAke3RoaXMuY21kfSBmYWlsZWQgdG8gZXhlY3V0ZTogJHtzdHlsZShyZWFzb24ubWVzc2FnZSkucmVkfWBcbiAgICApO1xuICAgIHRoaXMubG9jay5yZWplY3QocmVhc29uKTtcbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgQ2hpbGRQcm9jZXNzV2l0aG91dE51bGxTdHJlYW1zLFxuICBzcGF3bixcbiAgU3Bhd25PcHRpb25zV2l0aG91dFN0ZGlvLFxufSBmcm9tIFwiY2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgU3RhbmRhcmRPdXRwdXRXcml0ZXIgfSBmcm9tIFwiLi4vd3JpdGVycy9TdGFuZGFyZE91dHB1dFdyaXRlclwiO1xuaW1wb3J0IHsgQ29tbWFuZFJlc3VsdCB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBPdXRwdXRXcml0ZXJDb25zdHJ1Y3RvciB9IGZyb20gXCIuLi93cml0ZXJzL3R5cGVzXCI7XG5pbXBvcnQgeyBBYm9ydENvZGUgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IExvZ2dlciwgTG9nZ2luZyB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbG9ja2VkIHZlcnNpb24gb2YgYSBmdW5jdGlvbi5cbiAqIEBzdW1tYXJ5IFRoaXMgaGlnaGVyLW9yZGVyIGZ1bmN0aW9uIHRha2VzIGEgZnVuY3Rpb24gYW5kIHJldHVybnMgYSBuZXcgZnVuY3Rpb24gdGhhdCBlbnN1cmVzXG4gKiBzZXF1ZW50aWFsIGV4ZWN1dGlvbiBvZiB0aGUgb3JpZ2luYWwgZnVuY3Rpb24sIGV2ZW4gd2hlbiBjYWxsZWQgbXVsdGlwbGUgdGltZXMgY29uY3VycmVudGx5LlxuICogSXQgdXNlcyBhIFByb21pc2UtYmFzZWQgbG9ja2luZyBtZWNoYW5pc20gdG8gcXVldWUgZnVuY3Rpb24gY2FsbHMuXG4gKlxuICogQHRlbXBsYXRlIFIgLSBUaGUgcmV0dXJuIHR5cGUgb2YgdGhlIGlucHV0IGZ1bmN0aW9uLlxuICpcbiAqIEBwYXJhbSBmIC0gVGhlIGZ1bmN0aW9uIHRvIGJlIGxvY2tlZC4gSXQgY2FuIHRha2UgYW55IG51bWJlciBvZiBwYXJhbWV0ZXJzIGFuZCByZXR1cm4gYSB2YWx1ZSBvZiB0eXBlIFIuXG4gKiBAcmV0dXJuIEEgbmV3IGZ1bmN0aW9uIHdpdGggdGhlIHNhbWUgc2lnbmF0dXJlIGFzIHRoZSBpbnB1dCBmdW5jdGlvbiwgYnV0IHdpdGggc2VxdWVudGlhbCBleGVjdXRpb24gZ3VhcmFudGVlZC5cbiAqXG4gKiBAZnVuY3Rpb24gbG9ja2lmeVxuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IExvY2tlZEZ1bmN0aW9uXG4gKiAgIHBhcnRpY2lwYW50IE9yaWdpbmFsRnVuY3Rpb25cbiAqICAgQ2FsbGVyLT4+TG9ja2VkRnVuY3Rpb246IENhbGwgd2l0aCBwYXJhbXNcbiAqICAgTG9ja2VkRnVuY3Rpb24tPj5Mb2NrZWRGdW5jdGlvbjogQ2hlY2sgY3VycmVudCBsb2NrXG4gKiAgIGFsdCBMb2NrIGlzIHJlc29sdmVkXG4gKiAgICAgTG9ja2VkRnVuY3Rpb24tPj5PcmlnaW5hbEZ1bmN0aW9uOiBFeGVjdXRlIHdpdGggcGFyYW1zXG4gKiAgICAgT3JpZ2luYWxGdW5jdGlvbi0tPj5Mb2NrZWRGdW5jdGlvbjogUmV0dXJuIHJlc3VsdFxuICogICAgIExvY2tlZEZ1bmN0aW9uLS0+PkNhbGxlcjogUmV0dXJuIHJlc3VsdFxuICogICBlbHNlIExvY2sgaXMgcGVuZGluZ1xuICogICAgIExvY2tlZEZ1bmN0aW9uLT4+TG9ja2VkRnVuY3Rpb246IFF1ZXVlIGV4ZWN1dGlvblxuICogICAgIExvY2tlZEZ1bmN0aW9uLS0+PkNhbGxlcjogUmV0dXJuIHByb21pc2VcbiAqICAgICBOb3RlIG92ZXIgTG9ja2VkRnVuY3Rpb246IFdhaXQgZm9yIHByZXZpb3VzIGV4ZWN1dGlvblxuICogICAgIExvY2tlZEZ1bmN0aW9uLT4+T3JpZ2luYWxGdW5jdGlvbjogRXhlY3V0ZSB3aXRoIHBhcmFtc1xuICogICAgIE9yaWdpbmFsRnVuY3Rpb24tLT4+TG9ja2VkRnVuY3Rpb246IFJldHVybiByZXN1bHRcbiAqICAgICBMb2NrZWRGdW5jdGlvbi0tPj5DYWxsZXI6IFJlc29sdmUgcHJvbWlzZSB3aXRoIHJlc3VsdFxuICogICBlbmRcbiAqICAgTG9ja2VkRnVuY3Rpb24tPj5Mb2NrZWRGdW5jdGlvbjogVXBkYXRlIGxvY2tcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsb2NraWZ5PFI+KGY6ICguLi5wYXJhbXM6IHVua25vd25bXSkgPT4gUikge1xuICBsZXQgbG9jazogUHJvbWlzZTxSIHwgdm9pZD4gPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgcmV0dXJuICguLi5wYXJhbXM6IHVua25vd25bXSkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IGxvY2sudGhlbigoKSA9PiBmKC4uLnBhcmFtcykpO1xuICAgIGxvY2sgPSByZXN1bHQuY2F0Y2goKCkgPT4ge30pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENoYWlucyBtdWx0aXBsZSBhYm9ydCBzaWduYWxzIHRvIGEgY29udHJvbGxlci5cbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBtZWNoYW5pc20gd2hlcmUgbXVsdGlwbGUgYWJvcnQgc2lnbmFscyBjYW4gdHJpZ2dlciBhIHNpbmdsZSBhYm9ydCBjb250cm9sbGVyLlxuICogVGhpcyBpcyB1c2VmdWwgZm9yIGNvb3JkaW5hdGluZyBjYW5jZWxsYXRpb24gYWNyb3NzIG11bHRpcGxlIGFzeW5jaHJvbm91cyBvcGVyYXRpb25zLlxuICpcbiAqIEBwYXJhbSB7QWJvcnRDb250cm9sbGVyfSBjb250cm9sbGVyIC0gVGhlIGFib3J0IGNvbnRyb2xsZXIgdG8gYmUgdHJpZ2dlcmVkIGJ5IHNpZ25hbHMuXG4gKiBAcGFyYW0gey4uLkFib3J0U2lnbmFsfSBzaWduYWxzIC0gT25lIG9yIG1vcmUgYWJvcnQgc2lnbmFscyB0aGF0IGNhbiB0cmlnZ2VyIHRoZSBjb250cm9sbGVyLlxuICogQHJldHVybiB7QWJvcnRDb250cm9sbGVyfSBUaGUgaW5wdXQgY29udHJvbGxlciwgbm93IGNvbm5lY3RlZCB0byB0aGUgc2lnbmFscy5cbiAqXG4gKiBAZnVuY3Rpb24gY2hhaW5BYm9ydENvbnRyb2xsZXJcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGFpbkFib3J0Q29udHJvbGxlcihcbiAgY29udHJvbGxlcjogQWJvcnRDb250cm9sbGVyLFxuICAuLi5zaWduYWxzOiBBYm9ydFNpZ25hbFtdXG4pOiBBYm9ydENvbnRyb2xsZXI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgY29udHJvbGxlciBjaGFpbmVkIHRvIG11bHRpcGxlIGFib3J0IHNpZ25hbHMuXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgbmV3IGFib3J0IGNvbnRyb2xsZXIgdGhhdCB3aWxsIGJlIHRyaWdnZXJlZCBpZiBhbnkgb2YgdGhlIHByb3ZpZGVkIHNpZ25hbHMgYXJlIGFib3J0ZWQuXG4gKlxuICogQHBhcmFtIHsuLi5BYm9ydFNpZ25hbH0gc2lnbmFscyAtIE9uZSBvciBtb3JlIGFib3J0IHNpZ25hbHMgdGhhdCBjYW4gdHJpZ2dlciB0aGUgbmV3IGNvbnRyb2xsZXIuXG4gKiBAcmV0dXJuIHtBYm9ydENvbnRyb2xsZXJ9IEEgbmV3IGFib3J0IGNvbnRyb2xsZXIgY29ubmVjdGVkIHRvIHRoZSBzaWduYWxzLlxuICpcbiAqIEBmdW5jdGlvbiBjaGFpbkFib3J0Q29udHJvbGxlclxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoYWluQWJvcnRDb250cm9sbGVyKFxuICAuLi5zaWduYWxzOiBBYm9ydFNpZ25hbFtdXG4pOiBBYm9ydENvbnRyb2xsZXI7XG5cbmV4cG9ydCBmdW5jdGlvbiBjaGFpbkFib3J0Q29udHJvbGxlcihcbiAgYXJndW1lbnQwOiBBYm9ydENvbnRyb2xsZXIgfCBBYm9ydFNpZ25hbCxcbiAgLi4ucmVtYWluZGVyOiBBYm9ydFNpZ25hbFtdXG4pOiBBYm9ydENvbnRyb2xsZXIge1xuICBsZXQgc2lnbmFsczogQWJvcnRTaWduYWxbXTtcbiAgbGV0IGNvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcjtcblxuICAvLyBub3JtYWxpemUgYXJnc1xuICBpZiAoYXJndW1lbnQwIGluc3RhbmNlb2YgQWJvcnRTaWduYWwpIHtcbiAgICBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgIHNpZ25hbHMgPSBbYXJndW1lbnQwLCAuLi5yZW1haW5kZXJdO1xuICB9IGVsc2Uge1xuICAgIGNvbnRyb2xsZXIgPSBhcmd1bWVudDA7XG4gICAgc2lnbmFscyA9IHJlbWFpbmRlcjtcbiAgfVxuXG4gIC8vIGlmIHRoZSBjb250cm9sbGVyIGlzIGFscmVhZHkgYWJvcnRlZCwgZXhpdCBlYXJseVxuICBpZiAoY29udHJvbGxlci5zaWduYWwuYWJvcnRlZCkge1xuICAgIHJldHVybiBjb250cm9sbGVyO1xuICB9XG5cbiAgY29uc3QgaGFuZGxlciA9ICgpID0+IGNvbnRyb2xsZXIuYWJvcnQoKTtcblxuICBmb3IgKGNvbnN0IHNpZ25hbCBvZiBzaWduYWxzKSB7XG4gICAgLy8gY2hlY2sgYmVmb3JlIGFkZGluZyEgKGFuZCBhc3N1bWUgdGhlcmUgaXMgbm8gcG9zc2libGUgd2F5IHRoYXQgdGhlIHNpZ25hbCBjb3VsZFxuICAgIC8vIGFib3J0IGJldHdlZW4gdGhlIGBpZmAgY2hlY2sgYW5kIGFkZGluZyB0aGUgZXZlbnQgbGlzdGVuZXIpXG4gICAgaWYgKHNpZ25hbC5hYm9ydGVkKSB7XG4gICAgICBjb250cm9sbGVyLmFib3J0KCk7XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCBoYW5kbGVyLCB7XG4gICAgICBvbmNlOiB0cnVlLFxuICAgICAgc2lnbmFsOiBjb250cm9sbGVyLnNpZ25hbCxcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBjb250cm9sbGVyO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTcGF3bnMgYSBjb21tYW5kIGFzIGEgY2hpbGQgcHJvY2VzcyB3aXRoIG91dHB1dCBoYW5kbGluZy5cbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBjaGlsZCBwcm9jZXNzIHRvIGV4ZWN1dGUgYSBjb21tYW5kIHdpdGggc3VwcG9ydCBmb3IgcGlwaW5nIG11bHRpcGxlIGNvbW1hbmRzLFxuICogY3VzdG9tIG91dHB1dCBoYW5kbGluZywgYW5kIGFib3J0IGNvbnRyb2wuIFRoaXMgZnVuY3Rpb24gaGFuZGxlcyB0aGUgbG93LWxldmVsIGRldGFpbHMgb2ZcbiAqIHNwYXduaW5nIHByb2Nlc3NlcyBhbmQgY29ubmVjdGluZyB0aGVpciBpbnB1dHMvb3V0cHV0cyB3aGVuIHBpcGluZyBpcyB1c2VkLlxuICpcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHR5cGUgb2YgdGhlIHByb2Nlc3NlZCBvdXRwdXQsIGRlZmF1bHRpbmcgdG8gc3RyaW5nLlxuICogQHBhcmFtIHtTdGFuZGFyZE91dHB1dFdyaXRlcjxSPn0gb3V0cHV0IC0gVGhlIG91dHB1dCB3cml0ZXIgdG8gaGFuZGxlIGNvbW1hbmQgb3V0cHV0LlxuICogQHBhcmFtIHtzdHJpbmd9IGNvbW1hbmQgLSBUaGUgY29tbWFuZCB0byBleGVjdXRlLCBjYW4gaW5jbHVkZSBwaXBlIG9wZXJhdG9ycy5cbiAqIEBwYXJhbSB7U3Bhd25PcHRpb25zV2l0aG91dFN0ZGlvfSBvcHRzIC0gT3B0aW9ucyBmb3IgdGhlIHNwYXduZWQgcHJvY2Vzcy5cbiAqIEBwYXJhbSB7QWJvcnRDb250cm9sbGVyfSBhYm9ydCAtIENvbnRyb2xsZXIgdG8gYWJvcnQgdGhlIGNvbW1hbmQgZXhlY3V0aW9uLlxuICogQHBhcmFtIHtMb2dnZXJ9IGxvZ2dlciAtIExvZ2dlciBmb3IgcmVjb3JkaW5nIGNvbW1hbmQgZXhlY3V0aW9uIGRldGFpbHMuXG4gKiBAcmV0dXJuIHtDaGlsZFByb2Nlc3NXaXRob3V0TnVsbFN0cmVhbXN9IFRoZSBzcGF3bmVkIGNoaWxkIHByb2Nlc3MuXG4gKlxuICogQGZ1bmN0aW9uIHNwYXduQ29tbWFuZFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNwYXduQ29tbWFuZDxSID0gc3RyaW5nPihcbiAgb3V0cHV0OiBTdGFuZGFyZE91dHB1dFdyaXRlcjxSPixcbiAgY29tbWFuZDogc3RyaW5nLFxuICBvcHRzOiBTcGF3bk9wdGlvbnNXaXRob3V0U3RkaW8sXG4gIGFib3J0OiBBYm9ydENvbnRyb2xsZXIsXG4gIGxvZ2dlcjogTG9nZ2VyXG4pOiBDaGlsZFByb2Nlc3NXaXRob3V0TnVsbFN0cmVhbXMge1xuICBmdW5jdGlvbiBzcGF3bklubmVyKGNvbW1hbmQ6IHN0cmluZywgY29udHJvbGxlcjogQWJvcnRDb250cm9sbGVyKSB7XG4gICAgY29uc3QgW2NtZCwgYXJnel0gPSBvdXRwdXQucGFyc2VDb21tYW5kKGNvbW1hbmQpO1xuICAgIGxvZ2dlci5pbmZvKGBSdW5uaW5nIGNvbW1hbmQ6ICR7Y21kfWApO1xuICAgIGxvZ2dlci5kZWJ1Zyhgd2l0aCBhcmdzOiAke2FyZ3ouam9pbihcIiBcIil9YCk7XG4gICAgY29uc3QgY2hpbGRQcm9jZXNzID0gc3Bhd24oY21kLCBhcmd6LCB7XG4gICAgICAuLi5vcHRzLFxuICAgICAgY3dkOiBvcHRzLmN3ZCB8fCBwcm9jZXNzLmN3ZCgpLFxuICAgICAgZW52OiBPYmplY3QuYXNzaWduKHt9LCBwcm9jZXNzLmVudiwgb3B0cy5lbnYsIHsgUEFUSDogcHJvY2Vzcy5lbnYuUEFUSCB9KSxcbiAgICAgIHNoZWxsOiBvcHRzLnNoZWxsIHx8IGZhbHNlLFxuICAgICAgc2lnbmFsOiBjb250cm9sbGVyLnNpZ25hbCxcbiAgICB9KTtcbiAgICBsb2dnZXIudmVyYm9zZShgcGlkIDogJHtjaGlsZFByb2Nlc3MucGlkfWApO1xuICAgIHJldHVybiBjaGlsZFByb2Nlc3M7XG4gIH1cblxuICBjb25zdCBtID0gY29tbWFuZC5tYXRjaCgvWzw+JCNdL2cpO1xuICBpZiAobSlcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgSW52YWxpZCBjb21tYW5kOiAke2NvbW1hbmR9LiBjb250YWlucyBpbnZhbGlkIGNoYXJhY3RlcnM6ICR7bX1gXG4gICAgKTtcbiAgaWYgKGNvbW1hbmQuaW5jbHVkZXMoXCIgfCBcIikpIHtcbiAgICBjb25zdCBjbWRzID0gY29tbWFuZC5zcGxpdChcIiB8IFwiKTtcbiAgICBjb25zdCBzcGF3bnMgPSBbXTtcbiAgICBjb25zdCBjb250cm9sbGVycyA9IG5ldyBBcnJheShjbWRzLmxlbmd0aCk7XG4gICAgY29udHJvbGxlcnNbMF0gPSBhYm9ydDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNtZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChpICE9PSAwKVxuICAgICAgICBjb250cm9sbGVyc1tpXSA9IGNoYWluQWJvcnRDb250cm9sbGVyKGNvbnRyb2xsZXJzW2kgLSAxXS5zaWduYWwpO1xuICAgICAgc3Bhd25zLnB1c2goc3Bhd25Jbm5lcihjbWRzW2ldLCBjb250cm9sbGVyc1tpXSkpO1xuICAgICAgaWYgKGkgPT09IDApIGNvbnRpbnVlO1xuICAgICAgc3Bhd25zW2kgLSAxXS5zdGRvdXQucGlwZShzcGF3bnNbaV0uc3RkaW4pO1xuICAgIH1cbiAgICByZXR1cm4gc3Bhd25zW2NtZHMubGVuZ3RoIC0gMV07XG4gIH1cblxuICByZXR1cm4gc3Bhd25Jbm5lcihjb21tYW5kLCBhYm9ydCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEV4ZWN1dGVzIGEgY29tbWFuZCBhc3luY2hyb25vdXNseSB3aXRoIGN1c3RvbWl6YWJsZSBvdXRwdXQgaGFuZGxpbmcuXG4gKiBAc3VtbWFyeSBUaGlzIGZ1bmN0aW9uIHJ1bnMgYSBzaGVsbCBjb21tYW5kIGFzIGEgY2hpbGQgcHJvY2VzcywgcHJvdmlkaW5nIGZpbmUtZ3JhaW5lZFxuICogY29udHJvbCBvdmVyIGl0cyBleGVjdXRpb24gYW5kIG91dHB1dCBoYW5kbGluZy4gSXQgc3VwcG9ydHMgY3VzdG9tIG91dHB1dCB3cml0ZXJzLFxuICogYWxsb3dzIGZvciBjb21tYW5kIGFib3J0aW9uLCBhbmQgY2FwdHVyZXMgYm90aCBzdGRvdXQgYW5kIHN0ZGVyci5cbiAqXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSB0eXBlIG9mIHRoZSByZXNvbHZlZCB2YWx1ZSBmcm9tIHRoZSBjb21tYW5kIGV4ZWN1dGlvbi5cbiAqXG4gKiBAcGFyYW0gY29tbWFuZCAtIFRoZSBjb21tYW5kIHRvIHJ1biwgZWl0aGVyIGFzIGEgc3RyaW5nIG9yIGFuIGFycmF5IG9mIHN0cmluZ3MuXG4gKiBAcGFyYW0gb3B0cyAtIFNwYXduIG9wdGlvbnMgZm9yIHRoZSBjaGlsZCBwcm9jZXNzLiBEZWZhdWx0cyB0byBhbiBlbXB0eSBvYmplY3QuXG4gKiBAcGFyYW0gb3V0cHV0Q29uc3RydWN0b3IgLSBDb25zdHJ1Y3RvciBmb3IgdGhlIG91dHB1dCB3cml0ZXIuIERlZmF1bHRzIHRvIFN0YW5kYXJkT3V0cHV0V3JpdGVyLlxuICogQHBhcmFtIGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBvdXRwdXQgY29uc3RydWN0b3IuXG4gKiBAcmV0dXJuIHtDb21tYW5kUmVzdWx0fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgY29tbWFuZCByZXN1bHQgb2YgdHlwZSBSLlxuICpcbiAqIEBmdW5jdGlvbiBydW5Db21tYW5kXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgcnVuQ29tbWFuZFxuICogICBwYXJ0aWNpcGFudCBPdXRwdXRXcml0ZXJcbiAqICAgcGFydGljaXBhbnQgQ2hpbGRQcm9jZXNzXG4gKiAgIENhbGxlci0+PnJ1bkNvbW1hbmQ6IENhbGwgd2l0aCBjb21tYW5kIGFuZCBvcHRpb25zXG4gKiAgIHJ1bkNvbW1hbmQtPj5PdXRwdXRXcml0ZXI6IENyZWF0ZSBuZXcgaW5zdGFuY2VcbiAqICAgcnVuQ29tbWFuZC0+Pk91dHB1dFdyaXRlcjogUGFyc2UgY29tbWFuZFxuICogICBydW5Db21tYW5kLT4+Q2hpbGRQcm9jZXNzOiBTcGF3biBwcm9jZXNzXG4gKiAgIENoaWxkUHJvY2Vzcy0tPj5ydW5Db21tYW5kOiBSZXR1cm4gcHJvY2VzcyBvYmplY3RcbiAqICAgcnVuQ29tbWFuZC0+PkNoaWxkUHJvY2VzczogU2V0IHVwIGV2ZW50IGxpc3RlbmVyc1xuICogICBsb29wIEZvciBlYWNoIHN0ZG91dCBkYXRhXG4gKiAgICAgQ2hpbGRQcm9jZXNzLT4+cnVuQ29tbWFuZDogRW1pdCBzdGRvdXQgZGF0YVxuICogICAgIHJ1bkNvbW1hbmQtPj5PdXRwdXRXcml0ZXI6IEhhbmRsZSBzdGRvdXQgZGF0YVxuICogICBlbmRcbiAqICAgbG9vcCBGb3IgZWFjaCBzdGRlcnIgZGF0YVxuICogICAgIENoaWxkUHJvY2Vzcy0+PnJ1bkNvbW1hbmQ6IEVtaXQgc3RkZXJyIGRhdGFcbiAqICAgICBydW5Db21tYW5kLT4+T3V0cHV0V3JpdGVyOiBIYW5kbGUgc3RkZXJyIGRhdGFcbiAqICAgZW5kXG4gKiAgIENoaWxkUHJvY2Vzcy0+PnJ1bkNvbW1hbmQ6IEVtaXQgZXJyb3IgKGlmIGFueSlcbiAqICAgcnVuQ29tbWFuZC0+Pk91dHB1dFdyaXRlcjogSGFuZGxlIGVycm9yXG4gKiAgIENoaWxkUHJvY2Vzcy0+PnJ1bkNvbW1hbmQ6IEVtaXQgZXhpdFxuICogICBydW5Db21tYW5kLT4+T3V0cHV0V3JpdGVyOiBIYW5kbGUgZXhpdFxuICogICBPdXRwdXRXcml0ZXItLT4+cnVuQ29tbWFuZDogUmVzb2x2ZSBvciByZWplY3QgcHJvbWlzZVxuICogICBydW5Db21tYW5kLS0+PkNhbGxlcjogUmV0dXJuIENvbW1hbmRSZXN1bHRcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBydW5Db21tYW5kPFIgPSBzdHJpbmc+KFxuICBjb21tYW5kOiBzdHJpbmcsXG4gIG9wdHM6IFNwYXduT3B0aW9uc1dpdGhvdXRTdGRpbyA9IHt9LFxuICBvdXRwdXRDb25zdHJ1Y3RvcjogT3V0cHV0V3JpdGVyQ29uc3RydWN0b3I8XG4gICAgUixcbiAgICBTdGFuZGFyZE91dHB1dFdyaXRlcjxSPixcbiAgICBFcnJvclxuICA+ID0gU3RhbmRhcmRPdXRwdXRXcml0ZXI8Uj4sXG4gIC4uLmFyZ3M6IHVua25vd25bXVxuKTogQ29tbWFuZFJlc3VsdDxSPiB7XG4gIGNvbnN0IGxvZ2dlciA9IExvZ2dpbmcuZm9yKHJ1bkNvbW1hbmQpO1xuICBjb25zdCBhYm9ydCA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblxuICBjb25zdCByZXN1bHQ6IE9taXQ8Q29tbWFuZFJlc3VsdCwgXCJwcm9taXNlXCIgfCBcInBpcGVcIj4gPSB7XG4gICAgYWJvcnQ6IGFib3J0LFxuICAgIGNvbW1hbmQ6IGNvbW1hbmQsXG4gICAgbG9nczogW10sXG4gICAgZXJyczogW10sXG4gIH07XG5cbiAgY29uc3QgbG9jayA9IG5ldyBQcm9taXNlPFI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBsZXQgb3V0cHV0O1xuICAgIHRyeSB7XG4gICAgICBvdXRwdXQgPSBuZXcgb3V0cHV0Q29uc3RydWN0b3IoXG4gICAgICAgIGNvbW1hbmQsXG4gICAgICAgIHtcbiAgICAgICAgICByZXNvbHZlLFxuICAgICAgICAgIHJlamVjdCxcbiAgICAgICAgfSxcbiAgICAgICAgLi4uYXJnc1xuICAgICAgKTtcblxuICAgICAgcmVzdWx0LmNtZCA9IHNwYXduQ29tbWFuZDxSPihvdXRwdXQsIGNvbW1hbmQsIG9wdHMsIGFib3J0LCBsb2dnZXIpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKGBFcnJvciBydW5uaW5nIGNvbW1hbmQgJHtjb21tYW5kfTogJHtlfWApKTtcbiAgICB9XG5cbiAgICByZXN1bHQuY21kLnN0ZG91dC5zZXRFbmNvZGluZyhcInV0ZjhcIik7XG5cbiAgICByZXN1bHQuY21kLnN0ZG91dC5vbihcImRhdGFcIiwgKGNodW5rOiBhbnkpID0+IHtcbiAgICAgIGNodW5rID0gY2h1bmsudG9TdHJpbmcoKTtcbiAgICAgIHJlc3VsdC5sb2dzLnB1c2goY2h1bmspO1xuICAgICAgb3V0cHV0LmRhdGEoY2h1bmspO1xuICAgIH0pO1xuXG4gICAgcmVzdWx0LmNtZC5zdGRlcnIub24oXCJkYXRhXCIsIChkYXRhOiBhbnkpID0+IHtcbiAgICAgIGRhdGEgPSBkYXRhLnRvU3RyaW5nKCk7XG4gICAgICByZXN1bHQuZXJycy5wdXNoKGRhdGEpO1xuICAgICAgb3V0cHV0LmVycm9yKGRhdGEpO1xuICAgIH0pO1xuXG4gICAgcmVzdWx0LmNtZC5vbmNlKFwiZXJyb3JcIiwgKGVycjogRXJyb3IpID0+IHtcbiAgICAgIG91dHB1dC5leGl0KGVyci5tZXNzYWdlLCByZXN1bHQuZXJycyk7XG4gICAgfSk7XG5cbiAgICByZXN1bHQuY21kLm9uY2UoXCJleGl0XCIsIChjb2RlOiBudW1iZXIgPSAwKSA9PiB7XG4gICAgICBpZiAoYWJvcnQuc2lnbmFsLmFib3J0ZWQgJiYgY29kZSA9PT0gbnVsbCkgY29kZSA9IEFib3J0Q29kZSBhcyBhbnk7XG4gICAgICBvdXRwdXQuZXhpdChjb2RlLCBjb2RlID09PSAwID8gcmVzdWx0LmxvZ3MgOiByZXN1bHQuZXJycyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIE9iamVjdC5hc3NpZ24ocmVzdWx0LCB7XG4gICAgcHJvbWlzZTogbG9jayxcbiAgICBwaXBlOiBhc3luYyA8RT4oY2I6IChyOiBSKSA9PiBFKSA9PiB7XG4gICAgICBjb25zdCBsID0gbG9nZ2VyLmZvcihcInBpcGVcIik7XG4gICAgICB0cnkge1xuICAgICAgICBsLnZlcmJvc2UoYEV4ZWN1dGluZyBwaXBlIGZ1bmN0aW9uICR7Y29tbWFuZH0uLi5gKTtcbiAgICAgICAgY29uc3QgcmVzdWx0OiBSID0gYXdhaXQgbG9jaztcbiAgICAgICAgbC52ZXJib3NlKGBQaXBpbmcgb3V0cHV0IHRvICR7Y2IubmFtZX06ICR7cmVzdWx0fWApO1xuICAgICAgICByZXR1cm4gY2IocmVzdWx0KTtcbiAgICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgICAgbC5lcnJvcihgRXJyb3IgcGlwaW5nIGNvbW1hbmQgb3V0cHV0OiAke2V9YCk7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfSxcbiAgfSk7XG5cbiAgcmV0dXJuIHJlc3VsdCBhcyBDb21tYW5kUmVzdWx0PFI+O1xufVxuIiwiaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IGNyZWF0ZVJlcXVpcmUgfSBmcm9tIFwibW9kdWxlXCI7XG5pbXBvcnQgeyBydW5Db21tYW5kIH0gZnJvbSBcIi4vdXRpbHNcIjtcbmltcG9ydCB7IERlcGVuZGVuY3lNYXAsIFNpbXBsZURlcGVuZGVuY3lNYXAgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgZXNjYXBlUmVnRXhwLCBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5pbXBvcnQgemxpYiBmcm9tIFwiemxpYlwiO1xuXG5jb25zdCBsb2dnZXIgPSBMb2dnaW5nLmZvcihcImZzXCIpO1xuY29uc3QgbG9jYWxSZXF1aXJlID0gY3JlYXRlUmVxdWlyZShgJHtwcm9jZXNzLmN3ZCgpfS9wYWNrYWdlLmpzb25gKTtcbmZ1bmN0aW9uIGlzVGVzdEVudmlyb25tZW50KCkge1xuICByZXR1cm4gKFxuICAgIHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSBcInRlc3RcIiB8fFxuICAgIHR5cGVvZiBwcm9jZXNzLmVudi5KRVNUX1dPUktFUl9JRCAhPT0gXCJ1bmRlZmluZWRcIlxuICApO1xufVxuXG5mdW5jdGlvbiBwYXRjaFN0cmluZyhcbiAgaW5wdXQ6IHN0cmluZyxcbiAgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXIgfCBzdHJpbmc+LFxuICBmbGFnczogc3RyaW5nID0gXCJnXCIsXG4gIGZpbHRlcj86IChzdHI6IHN0cmluZykgPT4gYm9vbGVhblxuKTogc3RyaW5nIHtcbiAgT2JqZWN0LmVudHJpZXModmFsdWVzKS5mb3JFYWNoKChba2V5LCB2YWxdKSA9PiB7XG4gICAgY29uc3QgcmVnZXhwID0gbmV3IFJlZ0V4cChlc2NhcGVSZWdFeHAoa2V5KSwgZmxhZ3MpO1xuICAgIGlucHV0ID0gaW5wdXQucmVwbGFjZShyZWdleHAsIChzdWJTdHI6IHN0cmluZykgPT4ge1xuICAgICAgaWYgKCFmaWx0ZXIgfHwgZmlsdGVyKHN1YlN0cikpIHtcbiAgICAgICAgcmV0dXJuIHZhbCBhcyBzdHJpbmc7XG4gICAgICB9XG4gICAgICByZXR1cm4gdmFsIGFzIHN0cmluZztcbiAgICB9KTtcbiAgfSk7XG4gIHJldHVybiBpbnB1dDtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUGF0Y2hlcyBhIGZpbGUgd2l0aCBnaXZlbiB2YWx1ZXMuXG4gKiBAc3VtbWFyeSBSZWFkcyBhIGZpbGUsIGFwcGxpZXMgcGF0Y2hlcyB1c2luZyBUZXh0VXRpbHMsIGFuZCB3cml0ZXMgdGhlIHJlc3VsdCBiYWNrIHRvIHRoZSBmaWxlLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gVGhlIHBhdGggdG8gdGhlIGZpbGUgdG8gYmUgcGF0Y2hlZC5cbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgbnVtYmVyIHwgc3RyaW5nPn0gdmFsdWVzIC0gVGhlIHZhbHVlcyB0byBwYXRjaCBpbnRvIHRoZSBmaWxlLlxuICogQHJldHVybiB7dm9pZH1cbiAqXG4gKiBAZnVuY3Rpb24gcGF0Y2hGaWxlXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgcGF0Y2hGaWxlXG4gKiAgIHBhcnRpY2lwYW50IGZzXG4gKiAgIHBhcnRpY2lwYW50IHJlYWRGaWxlXG4gKiAgIHBhcnRpY2lwYW50IFRleHRVdGlsc1xuICogICBwYXJ0aWNpcGFudCB3cml0ZUZpbGVcbiAqICAgQ2FsbGVyLT4+cGF0Y2hGaWxlOiBDYWxsIHdpdGggcGF0aCBhbmQgdmFsdWVzXG4gKiAgIHBhdGNoRmlsZS0+PmZzOiBDaGVjayBpZiBmaWxlIGV4aXN0c1xuICogICBwYXRjaEZpbGUtPj5yZWFkRmlsZTogUmVhZCBmaWxlIGNvbnRlbnRcbiAqICAgcmVhZEZpbGUtPj5mczogUmVhZCBmaWxlXG4gKiAgIGZzLS0+PnJlYWRGaWxlOiBSZXR1cm4gZmlsZSBjb250ZW50XG4gKiAgIHJlYWRGaWxlLS0+PnBhdGNoRmlsZTogUmV0dXJuIGZpbGUgY29udGVudFxuICogICBwYXRjaEZpbGUtPj5UZXh0VXRpbHM6IFBhdGNoIHN0cmluZ1xuICogICBUZXh0VXRpbHMtLT4+cGF0Y2hGaWxlOiBSZXR1cm4gcGF0Y2hlZCBjb250ZW50XG4gKiAgIHBhdGNoRmlsZS0+PndyaXRlRmlsZTogV3JpdGUgcGF0Y2hlZCBjb250ZW50XG4gKiAgIHdyaXRlRmlsZS0+PmZzOiBXcml0ZSB0byBmaWxlXG4gKiAgIGZzLS0+PndyaXRlRmlsZTogRmlsZSB3cml0dGVuXG4gKiAgIHdyaXRlRmlsZS0tPj5wYXRjaEZpbGU6IEZpbGUgd3JpdHRlblxuICogICBwYXRjaEZpbGUtLT4+Q2FsbGVyOiBQYXRjaGluZyBjb21wbGV0ZVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhdGNoRmlsZShcbiAgcGF0aDogc3RyaW5nLFxuICB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIG51bWJlciB8IHN0cmluZz4sXG4gIGZpbHRlcj86IChzdHI6IHN0cmluZykgPT4gYm9vbGVhblxuKSB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IocGF0Y2hGaWxlKTtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKHBhdGgpKVxuICAgIHRocm93IG5ldyBFcnJvcihgRmlsZSBub3QgZm91bmQgYXQgcGF0aCBcIiR7cGF0aH1cIi5gKTtcbiAgbGV0IGNvbnRlbnQgPSByZWFkRmlsZShwYXRoKTtcblxuICBsb2cudmVyYm9zZShgUGF0Y2hpbmcgZmlsZSBcIiR7cGF0aH1cIi4uLmApO1xuICBsb2cuZGVidWcoYHdpdGggdmFsdWU6ICR7SlNPTi5zdHJpbmdpZnkodmFsdWVzKX1gKTtcbiAgdHJ5IHtcbiAgICBjb250ZW50ID0gcGF0Y2hTdHJpbmcoY29udGVudCwgdmFsdWVzLCBcImdcIiwgZmlsdGVyKTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHBhdGNoaW5nIGZpbGU6ICR7ZXJyb3J9YCk7XG4gIH1cbiAgd3JpdGVGaWxlKHBhdGgsIGNvbnRlbnQpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZWFkcyBhIGZpbGUgYW5kIHJldHVybnMgaXRzIGNvbnRlbnQuXG4gKiBAc3VtbWFyeSBSZWFkcyB0aGUgY29udGVudCBvZiBhIGZpbGUgYXQgdGhlIHNwZWNpZmllZCBwYXRoIGFuZCByZXR1cm5zIGl0IGFzIGEgc3RyaW5nLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gVGhlIHBhdGggdG8gdGhlIGZpbGUgdG8gYmUgcmVhZC5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGNvbnRlbnQgb2YgdGhlIGZpbGUuXG4gKlxuICogQGZ1bmN0aW9uIHJlYWRGaWxlXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZEZpbGUocGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcihyZWFkRmlsZSk7XG4gIHRyeSB7XG4gICAgbG9nLnZlcmJvc2UoYFJlYWRpbmcgZmlsZSBcIiR7cGF0aH1cIi4uLmApO1xuICAgIHJldHVybiBmcy5yZWFkRmlsZVN5bmMocGF0aCwgXCJ1dGY4XCIpO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIGxvZy52ZXJib3NlKGBFcnJvciByZWFkaW5nIGZpbGUgXCIke3BhdGh9XCI6ICR7ZXJyb3J9YCk7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciByZWFkaW5nIGZpbGUgXCIke3BhdGh9XCI6ICR7ZXJyb3J9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gV3JpdGVzIGRhdGEgdG8gYSBmaWxlLlxuICogQHN1bW1hcnkgV3JpdGVzIHRoZSBwcm92aWRlZCBkYXRhIHRvIGEgZmlsZSBhdCB0aGUgc3BlY2lmaWVkIHBhdGguXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBUaGUgcGF0aCB0byB0aGUgZmlsZSB0byBiZSB3cml0dGVuLlxuICogQHBhcmFtIHtzdHJpbmcgfCBCdWZmZXJ9IGRhdGEgLSBUaGUgZGF0YSB0byBiZSB3cml0dGVuIHRvIHRoZSBmaWxlLlxuICogQHJldHVybiB7dm9pZH1cbiAqXG4gKiBAZnVuY3Rpb24gd3JpdGVGaWxlXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gd3JpdGVGaWxlKHBhdGg6IHN0cmluZywgZGF0YTogc3RyaW5nIHwgQnVmZmVyKTogdm9pZCB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3Iod3JpdGVGaWxlKTtcbiAgdHJ5IHtcbiAgICBsb2cudmVyYm9zZShgV3JpdGluZyBmaWxlIFwiJHtwYXRofSB3aXRoICR7ZGF0YS5sZW5ndGh9IGJ5dGVzLi4uYCk7XG4gICAgZnMud3JpdGVGaWxlU3luYyhwYXRoLCBkYXRhLCBcInV0ZjhcIik7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoYEVycm9yIHdyaXRpbmcgZmlsZSBcIiR7cGF0aH1cIjogJHtlcnJvcn1gKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdyaXRpbmcgZmlsZSBcIiR7cGF0aH1cIjogJHtlcnJvcn1gKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYWxsIGZpbGVzIHJlY3Vyc2l2ZWx5IGZyb20gYSBkaXJlY3RvcnkuXG4gKiBAc3VtbWFyeSBUcmF2ZXJzZXMgdGhyb3VnaCBkaXJlY3RvcmllcyBhbmQgc3ViZGlyZWN0b3JpZXMgdG8gY29sbGVjdCBhbGwgZmlsZSBwYXRocy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcCAtIFRoZSBwYXRoIHRvIHN0YXJ0IHNlYXJjaGluZyBmcm9tLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gW2ZpbHRlcl0gLSBPcHRpb25hbCBmdW5jdGlvbiB0byBmaWx0ZXIgZmlsZXMgYnkgbmFtZSBvciBpbmRleC5cbiAqIEByZXR1cm4ge3N0cmluZ1tdfSBBcnJheSBvZiBmaWxlIHBhdGhzLlxuICpcbiAqIEBmdW5jdGlvbiBnZXRBbGxGaWxlc1xuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFsbEZpbGVzKFxuICBwOiBzdHJpbmcsXG4gIGZpbHRlcj86IChmOiBzdHJpbmcsIGk/OiBudW1iZXIpID0+IGJvb2xlYW5cbik6IHN0cmluZ1tdIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcihnZXRBbGxGaWxlcyk7XG4gIGNvbnN0IGZpbGVzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIHRyeSB7XG4gICAgbG9nLnZlcmJvc2UoYFJldHJpZXZpbmcgYWxsIGZpbGVzIGZyb20gXCIke3B9XCIuLi5gKTtcbiAgICBjb25zdCBlbnRyaWVzID0gZnMucmVhZGRpclN5bmMocCk7XG5cbiAgICBlbnRyaWVzLmZvckVhY2goKGVudHJ5KSA9PiB7XG4gICAgICBjb25zdCBmdWxsUGF0aCA9IHBhdGguam9pbihwLCBlbnRyeSk7XG4gICAgICBjb25zdCBzdGF0ID0gZnMuc3RhdFN5bmMoZnVsbFBhdGgpO1xuXG4gICAgICBpZiAoc3RhdC5pc0ZpbGUoKSkge1xuICAgICAgICBmaWxlcy5wdXNoKGZ1bGxQYXRoKTtcbiAgICAgIH0gZWxzZSBpZiAoc3RhdC5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICAgIGZpbGVzLnB1c2goLi4uZ2V0QWxsRmlsZXMoZnVsbFBhdGgpKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAoIWZpbHRlcikgcmV0dXJuIGZpbGVzO1xuICAgIHJldHVybiBmaWxlcy5maWx0ZXIoZmlsdGVyKTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBsb2cudmVyYm9zZShgRXJyb3IgcmV0cmlldmluZyBmaWxlcyBmcm9tIFwiJHtwfVwiOiAke2Vycm9yfWApO1xuICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgcmV0cmlldmluZyBmaWxlcyBmcm9tIFwiJHtwfVwiOiAke2Vycm9yfWApO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFJlbmFtZXMgYSBmaWxlIG9yIGRpcmVjdG9yeS5cbiAqIEBzdW1tYXJ5IE1vdmVzIGEgZmlsZSBvciBkaXJlY3RvcnkgZnJvbSB0aGUgc291cmNlIHBhdGggdG8gdGhlIGRlc3RpbmF0aW9uIHBhdGguXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIFRoZSBzb3VyY2UgcGF0aCBvZiB0aGUgZmlsZSBvciBkaXJlY3RvcnkuXG4gKiBAcGFyYW0ge3N0cmluZ30gZGVzdCAtIFRoZSBkZXN0aW5hdGlvbiBwYXRoIGZvciB0aGUgZmlsZSBvciBkaXJlY3RvcnkuXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSByZW5hbWUgb3BlcmF0aW9uIGlzIGNvbXBsZXRlLlxuICpcbiAqIEBmdW5jdGlvbiByZW5hbWVGaWxlXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVuYW1lRmlsZShzb3VyY2U6IHN0cmluZywgZGVzdDogc3RyaW5nKSB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IocmVuYW1lRmlsZSk7XG4gIGxldCBkZXNjcmlwdG9yU291cmNlLCBkZXNjcmlwdG9yRGVzdDtcblxuICB0cnkge1xuICAgIGRlc2NyaXB0b3JTb3VyY2UgPSBmcy5zdGF0U3luYyhzb3VyY2UpO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIGxvZy52ZXJib3NlKGBTb3VyY2UgcGF0aCBcIiR7c291cmNlfVwiIGRvZXMgbm90IGV4aXN0OiAke2Vycm9yfWApO1xuICAgIHRocm93IG5ldyBFcnJvcihgU291cmNlIHBhdGggXCIke3NvdXJjZX1cIiBkb2VzIG5vdCBleGlzdDogJHtlcnJvcn1gKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgZGVzY3JpcHRvckRlc3QgPSBmcy5zdGF0U3luYyhkZXN0KTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAvLyBkbyBub3RoaW5nLiBpdHMgb2tcbiAgfVxuICBpZiAoZGVzY3JpcHRvckRlc3QpIHtcbiAgICBsb2cudmVyYm9zZShgRGVzdGluYXRpb24gcGF0aCBcIiR7ZGVzdH1cIiBhbHJlYWR5IGV4aXN0c2ApO1xuICAgIHRocm93IG5ldyBFcnJvcihgRGVzdGluYXRpb24gcGF0aCBcIiR7ZGVzdH1cIiBhbHJlYWR5IGV4aXN0c2ApO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBSZW5hbWluZyAke2Rlc2NyaXB0b3JTb3VyY2UuaXNGaWxlKCkgPyBcImZpbGVcIiA6IFwiZGlyZWN0b3J5XCJ9IFwiJHtzb3VyY2V9XCIgdG8gXCIke2Rlc3R9Li4uYFxuICAgICk7XG4gICAgZnMucmVuYW1lU3luYyhzb3VyY2UsIGRlc3QpO1xuICAgIGxvZy52ZXJib3NlKGBTdWNjZXNzZnVsbHkgcmVuYW1lZCB0byBcIiR7ZGVzdH1cImApO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYEVycm9yIHJlbmFtaW5nICR7ZGVzY3JpcHRvclNvdXJjZS5pc0ZpbGUoKSA/IFwiZmlsZVwiIDogXCJkaXJlY3RvcnlcIn0gXCIke3NvdXJjZX1cIiB0byBcIiR7ZGVzdH1cIjogJHtlcnJvcn1gXG4gICAgKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgRXJyb3IgcmVuYW1pbmcgJHtkZXNjcmlwdG9yU291cmNlLmlzRmlsZSgpID8gXCJmaWxlXCIgOiBcImRpcmVjdG9yeVwifSBcIiR7c291cmNlfVwiIHRvIFwiJHtkZXN0fVwiOiAke2Vycm9yfWBcbiAgICApO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvcGllcyBhIGZpbGUgb3IgZGlyZWN0b3J5LlxuICogQHN1bW1hcnkgQ3JlYXRlcyBhIGNvcHkgb2YgYSBmaWxlIG9yIGRpcmVjdG9yeSBmcm9tIHRoZSBzb3VyY2UgcGF0aCB0byB0aGUgZGVzdGluYXRpb24gcGF0aC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gVGhlIHNvdXJjZSBwYXRoIG9mIHRoZSBmaWxlIG9yIGRpcmVjdG9yeS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkZXN0IC0gVGhlIGRlc3RpbmF0aW9uIHBhdGggZm9yIHRoZSBmaWxlIG9yIGRpcmVjdG9yeS5cbiAqIEByZXR1cm4ge3ZvaWR9XG4gKlxuICogQGZ1bmN0aW9uIGNvcHlGaWxlXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gY29weUZpbGUoc291cmNlOiBzdHJpbmcsIGRlc3Q6IHN0cmluZykge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKGNvcHlGaWxlKTtcbiAgbGV0IGRlc2NyaXB0b3JTb3VyY2UsIGRlc2NyaXB0b3JEZXN0O1xuICB0cnkge1xuICAgIGRlc2NyaXB0b3JTb3VyY2UgPSBmcy5zdGF0U3luYyhzb3VyY2UpO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIGxvZy52ZXJib3NlKGBTb3VyY2UgcGF0aCBcIiR7c291cmNlfVwiIGRvZXMgbm90IGV4aXN0OiAke2Vycm9yfWApO1xuICAgIHRocm93IG5ldyBFcnJvcihgU291cmNlIHBhdGggXCIke3NvdXJjZX1cIiBkb2VzIG5vdCBleGlzdDogJHtlcnJvcn1gKTtcbiAgfVxuICB0cnkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICBkZXNjcmlwdG9yRGVzdCA9IGZzLnN0YXRTeW5jKGRlc3QpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICBpZiAoZGVzY3JpcHRvclNvdXJjZS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICBsb2cudmVyYm9zZShgRGVzdCBwYXRoIFwiJHtkZXN0fVwiIGRvZXMgbm90IGV4aXN0LiBjcmVhdGluZ2ApO1xuICAgICAgZnMubWtkaXJTeW5jKGRlc3QsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIH1cbiAgfVxuXG4gIHRyeSB7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgQ29weWluZyAke2Rlc2NyaXB0b3JTb3VyY2UuaXNGaWxlKCkgPyBcImZpbGVcIiA6IFwiZGlyZWN0b3J5XCJ9IFwiJHtzb3VyY2V9XCIgdG8gXCIke2Rlc3R9Li4uYFxuICAgICk7XG4gICAgZnMuY3BTeW5jKHNvdXJjZSwgZGVzdCwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgRXJyb3IgY29weWluZyAke2Rlc2NyaXB0b3JTb3VyY2UuaXNGaWxlKCkgPyBcImZpbGVcIiA6IFwiZGlyZWN0b3J5XCJ9IFwiJHtzb3VyY2V9XCIgdG8gXCIke2Rlc3R9OiAke2Vycm9yfWBcbiAgICApO1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBFcnJvciBjb3B5aW5nICR7ZGVzY3JpcHRvclNvdXJjZS5pc0ZpbGUoKSA/IFwiZmlsZVwiIDogXCJkaXJlY3RvcnlcIn0gXCIke3NvdXJjZX1cIiB0byBcIiR7ZGVzdH06ICR7ZXJyb3J9YFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVsZXRlcyBhIGZpbGUgb3IgZGlyZWN0b3J5LlxuICogQHN1bW1hcnkgUmVtb3ZlcyBhIGZpbGUgb3IgZGlyZWN0b3J5IGF0IHRoZSBzcGVjaWZpZWQgcGF0aCwgd2l0aCByZWN1cnNpdmUgYW5kIGZvcmNlIG9wdGlvbnMgZW5hYmxlZC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcCAtIFRoZSBwYXRoIHRvIHRoZSBmaWxlIG9yIGRpcmVjdG9yeSB0byBkZWxldGUuXG4gKiBAcmV0dXJuIHt2b2lkfVxuICpcbiAqIEBmdW5jdGlvbiBkZWxldGVQYXRoXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZGVsZXRlUGF0aChwOiBzdHJpbmcpIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcihkZWxldGVQYXRoKTtcbiAgdHJ5IHtcbiAgICBjb25zdCBkZXNjcmlwdG9yID0gZnMuc3RhdFN5bmMocCk7XG4gICAgaWYgKGRlc2NyaXB0b3IuaXNGaWxlKCkpIHtcbiAgICAgIGxvZy52ZXJib3NlKGBEZWxldGluZyBmaWxlIFwiJHtwfS4uLmApO1xuICAgICAgZnMucm1TeW5jKHAsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgICB9IGVsc2UgaWYgKGRlc2NyaXB0b3IuaXNEaXJlY3RvcnkoKSlcbiAgICAgIGZzLnJtU3luYyhwLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgbG9nLnZlcmJvc2UoYEVycm9yIERlbGV0aW5nIFwiJHtwfVwiOiAke2Vycm9yfWApO1xuICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgRGVsZXRpbmcgXCIke3B9XCI6ICR7ZXJyb3J9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIHBhY2thZ2UgaW5mb3JtYXRpb24gZnJvbSBwYWNrYWdlLmpzb24uXG4gKiBAc3VtbWFyeSBMb2FkcyBhbmQgcGFyc2VzIHRoZSBwYWNrYWdlLmpzb24gZmlsZSBmcm9tIGEgc3BlY2lmaWVkIGRpcmVjdG9yeSBvciB0aGUgY3VycmVudCB3b3JraW5nIGRpcmVjdG9yeS4gQ2FuIHJldHVybiB0aGUgZW50aXJlIHBhY2thZ2Ugb2JqZWN0IG9yIGEgc3BlY2lmaWMgcHJvcGVydHkuXG4gKiBAcGFyYW0ge3N0cmluZ30gW3A9cHJvY2Vzcy5jd2QoKV0gLSBUaGUgZGlyZWN0b3J5IHBhdGggd2hlcmUgdGhlIHBhY2thZ2UuanNvbiBmaWxlIGlzIGxvY2F0ZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gW3Byb3BlcnR5XSAtIE9wdGlvbmFsLiBUaGUgc3BlY2lmaWMgcHJvcGVydHkgdG8gcmV0cmlldmUgZnJvbSBwYWNrYWdlLmpzb24uXG4gKiBAcmV0dXJuIHtvYmplY3QgfCBzdHJpbmd9IFRoZSBwYXJzZWQgY29udGVudHMgb2YgcGFja2FnZS5qc29uIG9yIHRoZSB2YWx1ZSBvZiB0aGUgc3BlY2lmaWVkIHByb3BlcnR5LlxuICogQGZ1bmN0aW9uIGdldFBhY2thZ2VcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IGdldFBhY2thZ2VcbiAqICAgcGFydGljaXBhbnQgcmVhZEZpbGVcbiAqICAgcGFydGljaXBhbnQgSlNPTlxuICogICBDYWxsZXItPj5nZXRQYWNrYWdlOiBDYWxsIHdpdGggcGF0aCBhbmQgb3B0aW9uYWwgcHJvcGVydHlcbiAqICAgZ2V0UGFja2FnZS0+PnJlYWRGaWxlOiBSZWFkIHBhY2thZ2UuanNvblxuICogICByZWFkRmlsZS0tPj5nZXRQYWNrYWdlOiBSZXR1cm4gZmlsZSBjb250ZW50XG4gKiAgIGdldFBhY2thZ2UtPj5KU09OOiBQYXJzZSBmaWxlIGNvbnRlbnRcbiAqICAgSlNPTi0tPj5nZXRQYWNrYWdlOiBSZXR1cm4gcGFyc2VkIG9iamVjdFxuICogICBhbHQgcHJvcGVydHkgc3BlY2lmaWVkXG4gKiAgICAgZ2V0UGFja2FnZS0+PmdldFBhY2thZ2U6IENoZWNrIGlmIHByb3BlcnR5IGV4aXN0c1xuICogICAgIGFsdCBwcm9wZXJ0eSBleGlzdHNcbiAqICAgICAgIGdldFBhY2thZ2UtLT4+Q2FsbGVyOiBSZXR1cm4gcHJvcGVydHkgdmFsdWVcbiAqICAgICBlbHNlIHByb3BlcnR5IGRvZXNuJ3QgZXhpc3RcbiAqICAgICAgIGdldFBhY2thZ2UtLT4+Q2FsbGVyOiBUaHJvdyBFcnJvclxuICogICAgIGVuZFxuICogICBlbHNlIG5vIHByb3BlcnR5IHNwZWNpZmllZFxuICogICAgIGdldFBhY2thZ2UtLT4+Q2FsbGVyOiBSZXR1cm4gZW50aXJlIHBhY2thZ2Ugb2JqZWN0XG4gKiAgIGVuZFxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UGFja2FnZShcbiAgcDogc3RyaW5nID0gcHJvY2Vzcy5jd2QoKSxcbiAgcHJvcGVydHk/OiBzdHJpbmdcbik6IG9iamVjdCB8IHN0cmluZyB7XG4gIGxldCBwa2c6IGFueTtcbiAgdHJ5IHtcbiAgICBwa2cgPSBKU09OLnBhcnNlKHJlYWRGaWxlKHBhdGguam9pbihwLCBgcGFja2FnZS5qc29uYCkpKTtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byByZXRyaWV2ZSBwYWNrYWdlIGluZm9ybWF0aW9uXCIgJHtlcnJvcn1gKTtcbiAgfVxuXG4gIGlmIChwcm9wZXJ0eSkge1xuICAgIGlmICghKHByb3BlcnR5IGluIHBrZykpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5IFwiJHtwcm9wZXJ0eX1cIiBub3QgZm91bmQgaW4gcGFja2FnZS5qc29uYCk7XG4gICAgcmV0dXJuIHBrZ1twcm9wZXJ0eV0gYXMgc3RyaW5nO1xuICB9XG4gIHJldHVybiBwa2c7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFNldHMgYW4gYXR0cmlidXRlIGluIHRoZSBwYWNrYWdlLmpzb24gZmlsZS5cbiAqIEBzdW1tYXJ5IFVwZGF0ZXMgYSBzcGVjaWZpYyBhdHRyaWJ1dGUgaW4gdGhlIHBhY2thZ2UuanNvbiBmaWxlIHdpdGggdGhlIHByb3ZpZGVkIHZhbHVlLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBhdHRyIC0gVGhlIGF0dHJpYnV0ZSBuYW1lIHRvIHNldCBpbiBwYWNrYWdlLmpzb24uXG4gKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlciB8IG9iamVjdH0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gc2V0IGZvciB0aGUgYXR0cmlidXRlLlxuICogQHBhcmFtIHtzdHJpbmd9IFtwPXByb2Nlc3MuY3dkKCldIC0gVGhlIGRpcmVjdG9yeSBwYXRoIHdoZXJlIHRoZSBwYWNrYWdlLmpzb24gZmlsZSBpcyBsb2NhdGVkLlxuICogQHJldHVybiB7dm9pZH1cbiAqXG4gKiBAZnVuY3Rpb24gc2V0UGFja2FnZUF0dHJpYnV0ZVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldFBhY2thZ2VBdHRyaWJ1dGUoXG4gIGF0dHI6IHN0cmluZyxcbiAgdmFsdWU6IHN0cmluZyxcbiAgcDogc3RyaW5nID0gcHJvY2Vzcy5jd2QoKVxuKTogdm9pZCB7XG4gIGNvbnN0IHBrZyA9IGdldFBhY2thZ2UocCkgYXMgUmVjb3JkPHN0cmluZywgYW55PjtcbiAgcGtnW2F0dHJdID0gdmFsdWU7XG4gIHdyaXRlRmlsZShwYXRoLmpvaW4ocCwgYHBhY2thZ2UuanNvbmApLCBKU09OLnN0cmluZ2lmeShwa2csIG51bGwsIDIpKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIHRoZSB2ZXJzaW9uIGZyb20gcGFja2FnZS5qc29uLlxuICogQHN1bW1hcnkgQSBjb252ZW5pZW5jZSBmdW5jdGlvbiB0aGF0IGNhbGxzIGdldFBhY2thZ2UgdG8gcmV0cmlldmUgdGhlIFwidmVyc2lvblwiIHByb3BlcnR5IGZyb20gcGFja2FnZS5qc29uLlxuICogQHBhcmFtIHtzdHJpbmd9IFtwPXByb2Nlc3MuY3dkKCldIC0gVGhlIGRpcmVjdG9yeSBwYXRoIHdoZXJlIHRoZSBwYWNrYWdlLmpzb24gZmlsZSBpcyBsb2NhdGVkLlxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgdmVyc2lvbiBzdHJpbmcgZnJvbSBwYWNrYWdlLmpzb24uXG4gKiBAZnVuY3Rpb24gZ2V0UGFja2FnZVZlcnNpb25cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFBhY2thZ2VWZXJzaW9uKHAgPSBwcm9jZXNzLmN3ZCgpKTogc3RyaW5nIHtcbiAgcmV0dXJuIGdldFBhY2thZ2UocCwgXCJ2ZXJzaW9uXCIpIGFzIHN0cmluZztcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGFsbCBkZXBlbmRlbmNpZXMgZnJvbSB0aGUgcHJvamVjdC5cbiAqIEBzdW1tYXJ5IEV4ZWN1dGVzICducG0gbHMgLS1qc29uJyBjb21tYW5kIHRvIGdldCBhIGRldGFpbGVkIGxpc3Qgb2YgYWxsIGRlcGVuZGVuY2llcyAocHJvZHVjdGlvbiwgZGV2ZWxvcG1lbnQsIGFuZCBwZWVyKSBhbmQgdGhlaXIgdmVyc2lvbnMuXG4gKiBAcGFyYW0ge3N0cmluZ30gW3BhdGg9cHJvY2Vzcy5jd2QoKV0gLSBUaGUgZGlyZWN0b3J5IHBhdGggb2YgdGhlIHByb2plY3QuXG4gKiBAcmV0dXJuIHtQcm9taXNlPHtwcm9kOiBBcnJheTx7bmFtZTogc3RyaW5nLCB2ZXJzaW9uOiBzdHJpbmd9PiwgZGV2OiBBcnJheTx7bmFtZTogc3RyaW5nLCB2ZXJzaW9uOiBzdHJpbmd9PiwgcGVlcjogQXJyYXk8e25hbWU6IHN0cmluZywgdmVyc2lvbjogc3RyaW5nfT59Pn0gQW4gb2JqZWN0IGNvbnRhaW5pbmcgYXJyYXlzIG9mIHByb2R1Y3Rpb24sIGRldmVsb3BtZW50LCBhbmQgcGVlciBkZXBlbmRlbmNpZXMuXG4gKiBAZnVuY3Rpb24gZ2V0RGVwZW5kZW5jaWVzXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENhbGxlclxuICogICBwYXJ0aWNpcGFudCBnZXREZXBlbmRlbmNpZXNcbiAqICAgcGFydGljaXBhbnQgcnVuQ29tbWFuZFxuICogICBwYXJ0aWNpcGFudCBKU09OXG4gKiAgIENhbGxlci0+PmdldERlcGVuZGVuY2llczogQ2FsbCB3aXRoIG9wdGlvbmFsIHBhdGhcbiAqICAgZ2V0RGVwZW5kZW5jaWVzLT4+cnVuQ29tbWFuZDogRXhlY3V0ZSAnbnBtIGxzIC0tanNvbidcbiAqICAgcnVuQ29tbWFuZC0tPj5nZXREZXBlbmRlbmNpZXM6IFJldHVybiBjb21tYW5kIG91dHB1dFxuICogICBnZXREZXBlbmRlbmNpZXMtPj5KU09OOiBQYXJzZSBjb21tYW5kIG91dHB1dFxuICogICBKU09OLS0+PmdldERlcGVuZGVuY2llczogUmV0dXJuIHBhcnNlZCBvYmplY3RcbiAqICAgZ2V0RGVwZW5kZW5jaWVzLT4+Z2V0RGVwZW5kZW5jaWVzOiBQcm9jZXNzIGRlcGVuZGVuY2llc1xuICogICBnZXREZXBlbmRlbmNpZXMtLT4+Q2FsbGVyOiBSZXR1cm4gcHJvY2Vzc2VkIGRlcGVuZGVuY2llc1xuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0RGVwZW5kZW5jaWVzKFxuICBwOiBzdHJpbmcgPSBwcm9jZXNzLmN3ZCgpXG4pOiBQcm9taXNlPERlcGVuZGVuY3lNYXA+IHtcbiAgY29uc3QgcGtnUGF0aCA9IHBhdGguam9pbihwLCBcInBhY2thZ2UuanNvblwiKTtcbiAgY29uc3QgbG9ja1BhdGggPSBwYXRoLmpvaW4ocCwgXCJwYWNrYWdlLWxvY2suanNvblwiKTtcbiAgbGV0IHBrZzogYW55O1xuICB0cnkge1xuICAgIHBrZyA9IEpTT04ucGFyc2UocmVhZEZpbGUocGtnUGF0aCkpO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IHJlYWQgcGFja2FnZS5qc29uIGF0ICR7cGtnUGF0aH06ICR7ZXJyb3J9YCk7XG4gIH1cblxuICBsZXQgbG9jazogYW55O1xuICBpZiAoZnMuZXhpc3RzU3luYyhsb2NrUGF0aCkpIHtcbiAgICB0cnkge1xuICAgICAgbG9jayA9IEpTT04ucGFyc2UocmVhZEZpbGUobG9ja1BhdGgpKTtcbiAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgbG9nZ2VyLndhcm4oYFVuYWJsZSB0byBwYXJzZSBwYWNrYWdlLWxvY2suanNvbiBhdCAke2xvY2tQYXRofTogJHtlcnJvcn1gKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBtYXBEZXBzID0gKGVudHJpZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fSkgPT5cbiAgICBPYmplY3QuZW50cmllcyhlbnRyaWVzKS5tYXAoKFtuYW1lLCB2ZXJzaW9uXSkgPT4gKHtcbiAgICAgIG5hbWUsXG4gICAgICB2ZXJzaW9uOiByZXNvbHZlRGVwZW5kZW5jeVZlcnNpb24obG9jaywgbmFtZSwgdmVyc2lvbiksXG4gICAgfSkpO1xuXG4gIHJldHVybiB7XG4gICAgcHJvZDogbWFwRGVwcyhwa2cuZGVwZW5kZW5jaWVzKSxcbiAgICBkZXY6IG1hcERlcHMocGtnLmRldkRlcGVuZGVuY2llcyksXG4gICAgcGVlcjogbWFwRGVwcyhwa2cucGVlckRlcGVuZGVuY2llcyksXG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVEZXBlbmRlbmN5VmVyc2lvbihcbiAgbG9jazogYW55LFxuICBuYW1lOiBzdHJpbmcsXG4gIGZhbGxiYWNrOiBzdHJpbmdcbik6IHN0cmluZyB7XG4gIGlmIChsb2NrKSB7XG4gICAgY29uc3QgcGFja2FnZXMgPSBsb2NrLnBhY2thZ2VzIHx8IHt9O1xuICAgIGNvbnN0IGtleSA9IGBub2RlX21vZHVsZXMvJHtuYW1lfWA7XG4gICAgaWYgKHBhY2thZ2VzW2tleV0gJiYgcGFja2FnZXNba2V5XS52ZXJzaW9uKSB7XG4gICAgICByZXR1cm4gcGFja2FnZXNba2V5XS52ZXJzaW9uO1xuICAgIH1cbiAgICBpZiAobG9jay5kZXBlbmRlbmNpZXMgJiYgbG9jay5kZXBlbmRlbmNpZXNbbmFtZV0pIHtcbiAgICAgIHJldHVybiBsb2NrLmRlcGVuZGVuY2llc1tuYW1lXS52ZXJzaW9uIHx8IGZhbGxiYWNrO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsbGJhY2s7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFVwZGF0ZXMgcHJvamVjdCBkZXBlbmRlbmNpZXMgdG8gdGhlaXIgbGF0ZXN0IHZlcnNpb25zLlxuICogQHN1bW1hcnkgUnVucyBucG0tY2hlY2stdXBkYXRlcyB0byB1cGRhdGUgcGFja2FnZS5qc29uIGFuZCB0aGVuIGluc3RhbGxzIHRoZSB1cGRhdGVkIGRlcGVuZGVuY2llcy5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGRlcGVuZGVuY2llcyBhcmUgdXBkYXRlZC5cbiAqXG4gKiBAZnVuY3Rpb24gdXBkYXRlRGVwZW5kZW5jaWVzXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdXBkYXRlRGVwZW5kZW5jaWVzKCkge1xuICBjb25zdCBsb2cgPSBsb2dnZXIuZm9yKHVwZGF0ZURlcGVuZGVuY2llcyk7XG4gIGxvZy5pbmZvKFwiY2hlY2tpbmcgZm9yIHVwZGF0ZXMuLi5cIik7XG4gIGF3YWl0IHJ1bkNvbW1hbmQoXCJucHggbnBtLWNoZWNrLXVwZGF0ZXMgLXVcIikucHJvbWlzZTtcbiAgbG9nLmluZm8oXCJ1cGRhdGluZy4uLlwiKTtcbiAgYXdhaXQgcnVuQ29tbWFuZChcIm5weCBucG0gcnVuIGRvLWluc3RhbGxcIikucHJvbWlzZTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSW5zdGFsbHMgZGVwZW5kZW5jaWVzIGlmIHRoZXkgYXJlIG5vdCBhbHJlYWR5IGF2YWlsYWJsZS5cbiAqIEBzdW1tYXJ5IENoZWNrcyBpZiBzcGVjaWZpZWQgZGVwZW5kZW5jaWVzIGFyZSBpbnN0YWxsZWQgYW5kIGluc3RhbGxzIGFueSB0aGF0IGFyZSBtaXNzaW5nLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nW10gfCBzdHJpbmd9IGRlcHMgLSBUaGUgZGVwZW5kZW5jaWVzIHRvIGNoZWNrIGFuZCBwb3RlbnRpYWxseSBpbnN0YWxsLlxuICogQHBhcmFtIHtTaW1wbGVEZXBlbmRlbmN5TWFwfSBbZGVwZW5kZW5jaWVzXSAtIE9wdGlvbmFsIG1hcCBvZiBleGlzdGluZyBkZXBlbmRlbmNpZXMuXG4gKiBAcmV0dXJuIHtQcm9taXNlPFNpbXBsZURlcGVuZGVuY3lNYXA+fSBVcGRhdGVkIG1hcCBvZiBkZXBlbmRlbmNpZXMuXG4gKlxuICogQGZ1bmN0aW9uIGluc3RhbGxJZk5vdEF2YWlsYWJsZVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGluc3RhbGxJZk5vdEF2YWlsYWJsZShcbiAgZGVwczogc3RyaW5nW10gfCBzdHJpbmcsXG4gIGRlcGVuZGVuY2llcz86IFNpbXBsZURlcGVuZGVuY3lNYXBcbikge1xuICBkZXBzID0gdHlwZW9mIGRlcHMgPT09IFwic3RyaW5nXCIgPyBbZGVwc10gOiBkZXBzO1xuICBjb25zdCBjdXJyZW50OiBTaW1wbGVEZXBlbmRlbmN5TWFwID0ge1xuICAgIHByb2Q6IGRlcGVuZGVuY2llcz8ucHJvZCA/IFsuLi5kZXBlbmRlbmNpZXMucHJvZF0gOiBbXSxcbiAgICBkZXY6IGRlcGVuZGVuY2llcz8uZGV2ID8gWy4uLmRlcGVuZGVuY2llcy5kZXZdIDogW10sXG4gICAgcGVlcjogZGVwZW5kZW5jaWVzPy5wZWVyID8gWy4uLmRlcGVuZGVuY2llcy5wZWVyXSA6IFtdLFxuICB9O1xuXG4gIGNvbnN0IGtub3duID0gbmV3IFNldChbXG4gICAgLi4uKGN1cnJlbnQucHJvZCA/PyBbXSksXG4gICAgLi4uKGN1cnJlbnQuZGV2ID8/IFtdKSxcbiAgICAuLi4oY3VycmVudC5wZWVyID8/IFtdKSxcbiAgXSk7XG5cbiAgY29uc3QgdG9JbnN0YWxsOiBzdHJpbmdbXSA9IFtdO1xuICBmb3IgKGNvbnN0IGRlcCBvZiBkZXBzKSB7XG4gICAgaWYgKGtub3duLmhhcyhkZXApKSBjb250aW51ZTtcbiAgICB0cnkge1xuICAgICAgbG9jYWxSZXF1aXJlLnJlc29sdmUoZGVwKTtcbiAgICAgIGtub3duLmFkZChkZXApO1xuICAgIH0gY2F0Y2gge1xuICAgICAgdG9JbnN0YWxsLnB1c2goZGVwKTtcbiAgICB9XG4gIH1cblxuICBpZiAodG9JbnN0YWxsLmxlbmd0aCkge1xuICAgIGlmIChpc1Rlc3RFbnZpcm9ubWVudCgpKSB7XG4gICAgICBsb2dnZXIudmVyYm9zZShcbiAgICAgICAgYFNraXBwaW5nIGRlcGVuZGVuY3kgaW5zdGFsbCBpbiB0ZXN0IGVudmlyb25tZW50IGZvcjogJHt0b0luc3RhbGwuam9pbihcbiAgICAgICAgICBcIiwgXCJcbiAgICAgICAgKX1gXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCBpbnN0YWxsRGVwZW5kZW5jaWVzKHsgZGV2OiB0b0luc3RhbGwgfSk7XG4gICAgfVxuICAgIGNvbnN0IGRldkRlcHMgPSBuZXcgU2V0KGN1cnJlbnQuZGV2ID8/IFtdKTtcbiAgICB0b0luc3RhbGwuZm9yRWFjaCgoZGVwKSA9PiBkZXZEZXBzLmFkZChkZXApKTtcbiAgICBjdXJyZW50LmRldiA9IEFycmF5LmZyb20oZGV2RGVwcyk7XG4gIH1cblxuICByZXR1cm4gY3VycmVudDtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUHVzaGVzIGNoYW5nZXMgdG8gR2l0IHJlcG9zaXRvcnkuXG4gKiBAc3VtbWFyeSBUZW1wb3JhcmlseSBjaGFuZ2VzIEdpdCB1c2VyIGNvbmZpZ3VyYXRpb24sIGNvbW1pdHMgYWxsIGNoYW5nZXMsIHB1c2hlcyB0byByZW1vdGUsIGFuZCByZXN0b3JlcyBvcmlnaW5hbCB1c2VyIGNvbmZpZ3VyYXRpb24uXG4gKlxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBjaGFuZ2VzIGFyZSBwdXNoZWQuXG4gKlxuICogQGZ1bmN0aW9uIHB1c2hUb0dpdFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHB1c2hUb0dpdCgpIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcihwdXNoVG9HaXQpO1xuICBjb25zdCBnaXRVc2VyID0gYXdhaXQgcnVuQ29tbWFuZChcImdpdCBjb25maWcgdXNlci5uYW1lXCIpLnByb21pc2U7XG4gIGNvbnN0IGdpdEVtYWlsID0gYXdhaXQgcnVuQ29tbWFuZChcImdpdCBjb25maWcgdXNlci5lbWFpbFwiKS5wcm9taXNlO1xuICBsb2cudmVyYm9zZShgY2FjaGVkIGdpdCBpZDogJHtnaXRVc2VyfS8ke2dpdEVtYWlsfS4gY2hhbmdpbmcgdG8gYXV0b21hdGlvbmApO1xuICBhd2FpdCBydW5Db21tYW5kKCdnaXQgY29uZmlnIHVzZXIuZW1haWwgXCJhdXRvbWF0aW9uQGRlY2FmLnRzXCInKS5wcm9taXNlO1xuICBhd2FpdCBydW5Db21tYW5kKCdnaXQgY29uZmlnIHVzZXIubmFtZSBcImRlY2FmXCInKS5wcm9taXNlO1xuICBsb2cuaW5mbyhcIlB1c2hpbmcgY2hhbmdlcyB0byBnaXQuLi5cIik7XG4gIGF3YWl0IHJ1bkNvbW1hbmQoXCJnaXQgYWRkIC5cIikucHJvbWlzZTtcbiAgYXdhaXQgcnVuQ29tbWFuZChgZ2l0IGNvbW1pdCAtbSBcInJlZnMgIzEgLSBhZnRlciByZXBvIHNldHVwXCJgKS5wcm9taXNlO1xuICBhd2FpdCBydW5Db21tYW5kKFwiZ2l0IHB1c2hcIikucHJvbWlzZTtcbiAgYXdhaXQgcnVuQ29tbWFuZChgZ2l0IGNvbmZpZyB1c2VyLmVtYWlsIFwiJHtnaXRFbWFpbH1cImApLnByb21pc2U7XG4gIGF3YWl0IHJ1bkNvbW1hbmQoYGdpdCBjb25maWcgdXNlci5uYW1lIFwiJHtnaXRVc2VyfVwiYCkucHJvbWlzZTtcbiAgbG9nLnZlcmJvc2UoYHJldmVydGVkIHRvIGdpdCBpZDogJHtnaXRVc2VyfS8ke2dpdEVtYWlsfWApO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBJbnN0YWxscyBwcm9qZWN0IGRlcGVuZGVuY2llcy5cbiAqIEBzdW1tYXJ5IEluc3RhbGxzIHByb2R1Y3Rpb24sIGRldmVsb3BtZW50LCBhbmQgcGVlciBkZXBlbmRlbmNpZXMgYXMgc3BlY2lmaWVkLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBkZXBlbmRlbmNpZXMgLSBPYmplY3QgY29udGFpbmluZyBhcnJheXMgb2YgZGVwZW5kZW5jaWVzIHRvIGluc3RhbGwuXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBbZGVwZW5kZW5jaWVzLnByb2RdIC0gUHJvZHVjdGlvbiBkZXBlbmRlbmNpZXMgdG8gaW5zdGFsbC5cbiAqIEBwYXJhbSB7c3RyaW5nW119IFtkZXBlbmRlbmNpZXMuZGV2XSAtIERldmVsb3BtZW50IGRlcGVuZGVuY2llcyB0byBpbnN0YWxsLlxuICogQHBhcmFtIHtzdHJpbmdbXX0gW2RlcGVuZGVuY2llcy5wZWVyXSAtIFBlZXIgZGVwZW5kZW5jaWVzIHRvIGluc3RhbGwuXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGFsbCBkZXBlbmRlbmNpZXMgYXJlIGluc3RhbGxlZC5cbiAqXG4gKiBAZnVuY3Rpb24gaW5zdGFsbERlcGVuZGVuY2llc1xuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGluc3RhbGxEZXBlbmRlbmNpZXMoZGVwZW5kZW5jaWVzOiB7XG4gIHByb2Q/OiBzdHJpbmdbXTtcbiAgZGV2Pzogc3RyaW5nW107XG4gIHBlZXI/OiBzdHJpbmdbXTtcbn0pIHtcbiAgY29uc3QgbG9nID0gbG9nZ2VyLmZvcihpbnN0YWxsRGVwZW5kZW5jaWVzKTtcbiAgY29uc3QgcHJvZCA9IGRlcGVuZGVuY2llcy5wcm9kIHx8IFtdO1xuICBjb25zdCBkZXYgPSBkZXBlbmRlbmNpZXMuZGV2IHx8IFtdO1xuICBjb25zdCBwZWVyID0gZGVwZW5kZW5jaWVzLnBlZXIgfHwgW107XG4gIGlmIChwcm9kLmxlbmd0aCkge1xuICAgIGxvZy5pbmZvKGBJbnN0YWxsaW5nIGRlcGVuZGVuY2llcyAke3Byb2Quam9pbihcIiwgXCIpfS4uLmApO1xuICAgIGF3YWl0IHJ1bkNvbW1hbmQoYG5wbSBpbnN0YWxsICR7cHJvZC5qb2luKFwiIFwiKX1gLCB7IGN3ZDogcHJvY2Vzcy5jd2QoKSB9KVxuICAgICAgLnByb21pc2U7XG4gIH1cbiAgaWYgKGRldi5sZW5ndGgpIHtcbiAgICBsb2cuaW5mbyhgSW5zdGFsbGluZyBkZXZEZXBlbmRlbmNpZXMgJHtkZXYuam9pbihcIiwgXCIpfS4uLmApO1xuICAgIGF3YWl0IHJ1bkNvbW1hbmQoYG5wbSBpbnN0YWxsIC0tc2F2ZS1kZXYgJHtkZXYuam9pbihcIiBcIil9YCwge1xuICAgICAgY3dkOiBwcm9jZXNzLmN3ZCgpLFxuICAgIH0pLnByb21pc2U7XG4gIH1cbiAgaWYgKHBlZXIubGVuZ3RoKSB7XG4gICAgbG9nLmluZm8oYEluc3RhbGxpbmcgcGVlckRlcGVuZGVuY2llcyAke3BlZXIuam9pbihcIiwgXCIpfS4uLmApO1xuICAgIGF3YWl0IHJ1bkNvbW1hbmQoYG5wbSBpbnN0YWxsIC0tc2F2ZS1wZWVyICR7cGVlci5qb2luKFwiIFwiKX1gLCB7XG4gICAgICBjd2Q6IHByb2Nlc3MuY3dkKCksXG4gICAgfSkucHJvbWlzZTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBOb3JtYWxpemVzIGltcG9ydHMgdG8gaGFuZGxlIGJvdGggQ29tbW9uSlMgYW5kIEVTTW9kdWxlIGZvcm1hdHMuXG4gKiBAc3VtbWFyeSBVdGlsaXR5IGZ1bmN0aW9uIHRvIGhhbmRsZSBtb2R1bGUgaW1wb3J0IGRpZmZlcmVuY2VzIGJldHdlZW4gZm9ybWF0cy5cbiAqXG4gKiBAdGVtcGxhdGUgVCAtIFR5cGUgb2YgdGhlIGltcG9ydGVkIG1vZHVsZS5cbiAqIEBwYXJhbSB7UHJvbWlzZTxUPn0gaW1wb3J0UHJvbWlzZSAtIFByb21pc2UgcmV0dXJuZWQgYnkgZHluYW1pYyBpbXBvcnQuXG4gKiBAcmV0dXJuIHtQcm9taXNlPFQ+fSBOb3JtYWxpemVkIG1vZHVsZS5cbiAqXG4gKiBAZnVuY3Rpb24gbm9ybWFsaXplSW1wb3J0XG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTp1dGlsc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbm9ybWFsaXplSW1wb3J0PFQ+KFxuICBpbXBvcnRQcm9taXNlOiBQcm9taXNlPFQ+XG4pOiBQcm9taXNlPFQ+IHtcbiAgLy8gQ29tbW9uSlMncyBgbW9kdWxlLmV4cG9ydHNgIGlzIHdyYXBwZWQgYXMgYGRlZmF1bHRgIGluIEVTTW9kdWxlLlxuICByZXR1cm4gaW1wb3J0UHJvbWlzZS50aGVuKChtOiBhbnkpID0+IChtLmRlZmF1bHQgfHwgbSkgYXMgVCk7XG59XG5cbi8vIE5ldyBoZWxwZXI6IGNvbXB1dGUgZ3ppcHBlZCBzaXplIG9mIHNtYWxsZXN0IEpTIGZpbGUgaW4gYSBkaXJlY3RvcnlcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRGaWxlU2l6ZVppcHBlZChkaXI6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IoZ2V0RmlsZVNpemVaaXBwZWQpO1xuICB0cnkge1xuICAgIGNvbnN0IGVudHJpZXMgPSBmcy5yZWFkZGlyU3luYyhkaXIpO1xuICAgIGNvbnN0IGNhbmRpZGF0ZXMgPSBlbnRyaWVzXG4gICAgICAubWFwKChlKSA9PiBwYXRoLmpvaW4oZGlyLCBlKSlcbiAgICAgIC5maWx0ZXIoKHApID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBzID0gZnMuc3RhdFN5bmMocCk7XG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIHMuaXNGaWxlKCkgJiZcbiAgICAgICAgICAgIChwLmVuZHNXaXRoKFwiLmpzXCIpIHx8IHAuZW5kc1dpdGgoXCIuY2pzXCIpIHx8IHAuZW5kc1dpdGgoXCIubWpzXCIpKVxuICAgICAgICAgICk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICBpZiAoY2FuZGlkYXRlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gSlMgZmlsZXMgZm91bmQgaW4gZGlyZWN0b3J5ICR7ZGlyfWApO1xuICAgIH1cblxuICAgIC8vIGNob29zZSB0aGUgc21hbGxlc3QgYnkgcmF3IGZpbGUgc2l6ZVxuICAgIGxldCBzbWFsbGVzdCA9IGNhbmRpZGF0ZXNbMF07XG4gICAgbGV0IHNtYWxsZXN0U2l6ZSA9IGZzLnN0YXRTeW5jKHNtYWxsZXN0KS5zaXplO1xuICAgIGZvciAoY29uc3QgYyBvZiBjYW5kaWRhdGVzLnNsaWNlKDEpKSB7XG4gICAgICBjb25zdCBzID0gZnMuc3RhdFN5bmMoYykuc2l6ZTtcbiAgICAgIGlmIChzIDwgc21hbGxlc3RTaXplKSB7XG4gICAgICAgIHNtYWxsZXN0ID0gYztcbiAgICAgICAgc21hbGxlc3RTaXplID0gcztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsb2cudmVyYm9zZShcbiAgICAgIGBTZWxlY3RlZCBzbWFsbGVzdCBidW5kbGU6ICR7c21hbGxlc3R9ICgke3NtYWxsZXN0U2l6ZX0gYnl0ZXMpYFxuICAgICk7XG5cbiAgICBjb25zdCBidWZmZXIgPSBmcy5yZWFkRmlsZVN5bmMoc21hbGxlc3QpO1xuICAgIGNvbnN0IGd6ID0gemxpYi5nemlwU3luYyhidWZmZXIpO1xuICAgIGNvbnN0IHNpemVLYiA9IE51bWJlcigoZ3oubGVuZ3RoIC8gMTAyNCkudG9GaXhlZCgxKSk7XG4gICAgbG9nLnZlcmJvc2UoYEd6aXBwZWQgc2l6ZTogJHtnei5sZW5ndGh9IGJ5dGVzICgke3NpemVLYn0gS0IpYCk7XG4gICAgcmV0dXJuIHNpemVLYjtcbiAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgIGxvZy52ZXJib3NlKGBGYWlsZWQgdG8gY29tcHV0ZSBnemlwcGVkIHNpemUgZm9yICR7ZGlyfTogJHtlfWApO1xuICAgIHRocm93IGUgYXMgRXJyb3I7XG4gIH1cbn1cblxuLy8gTmV3IGhlbHBlcjogbGlzdCBmb2xkZXIgZW50cmllcyAobmFtZXMpIHdpdGggb3B0aW9uYWwgZmlsdGVyXG5leHBvcnQgZnVuY3Rpb24gbGlzdEZvbGRlcihcbiAgYmFzZVBhdGg6IHN0cmluZyA9IHByb2Nlc3MuY3dkKCksXG4gIGZpbHRlcj86IChuYW1lOiBzdHJpbmcsIGRpcmVudDogZnMuRGlyZW50KSA9PiBib29sZWFuXG4pOiBzdHJpbmdbXSB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IobGlzdEZvbGRlcik7XG4gIHRyeSB7XG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKGJhc2VQYXRoKSkgcmV0dXJuIFtdO1xuICAgIGNvbnN0IGVudHJpZXMgPSBmcy5yZWFkZGlyU3luYyhiYXNlUGF0aCwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pO1xuICAgIGNvbnN0IG5hbWVzID0gZW50cmllc1xuICAgICAgLmZpbHRlcigoZCkgPT4gKGZpbHRlciA/IGZpbHRlcihkLm5hbWUsIGQpIDogdHJ1ZSkpXG4gICAgICAubWFwKChkKSA9PiBkLm5hbWUpO1xuICAgIHJldHVybiBuYW1lcztcbiAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgIGxvZy52ZXJib3NlKGBGYWlsZWQgdG8gbGlzdCBmb2xkZXIgJHtiYXNlUGF0aH06ICR7ZX1gKTtcbiAgICByZXR1cm4gW107XG4gIH1cbn1cblxuLy8gTmV3IGhlbHBlcjogbGlzdCBub2RlX21vZHVsZXMgcGFja2FnZSBuYW1lcywgZXhwYW5kaW5nIHNjb3BlZCBwYWNrYWdlc1xuZXhwb3J0IGZ1bmN0aW9uIGxpc3ROb2RlTW9kdWxlc1BhY2thZ2VzKFxuICBiYXNlUGF0aDogc3RyaW5nID0gcGF0aC5qb2luKHByb2Nlc3MuY3dkKCksIFwibm9kZV9tb2R1bGVzXCIpXG4pOiBzdHJpbmdbXSB7XG4gIGNvbnN0IGxvZyA9IGxvZ2dlci5mb3IobGlzdE5vZGVNb2R1bGVzUGFja2FnZXMpO1xuICB0cnkge1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhiYXNlUGF0aCkpIHJldHVybiBbXTtcbiAgICBjb25zdCBlbnRyaWVzID0gZnMucmVhZGRpclN5bmMoYmFzZVBhdGgsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KTtcbiAgICBjb25zdCBuYW1lczogc3RyaW5nW10gPSBbXTtcblxuICAgIGZvciAoY29uc3QgZSBvZiBlbnRyaWVzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoIWUuaXNEaXJlY3RvcnkoKSkgY29udGludWU7XG4gICAgICAgIC8vIGlnbm9yZSBoaWRkZW4gZm9sZGVyc1xuICAgICAgICBpZiAoZS5uYW1lLnN0YXJ0c1dpdGgoXCIuXCIpKSBjb250aW51ZTtcbiAgICAgICAgaWYgKGUubmFtZS5zdGFydHNXaXRoKFwiQFwiKSkge1xuICAgICAgICAgIC8vIGEgc2NvcGUgZm9sZGVyOyBleHBhbmQgY29udGFpbmVkIHBhY2thZ2VzXG4gICAgICAgICAgY29uc3Qgc2NvcGVQYXRoID0gcGF0aC5qb2luKGJhc2VQYXRoLCBlLm5hbWUpO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBzY29wZWQgPSBmcy5yZWFkZGlyU3luYyhzY29wZVBhdGgsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcyBvZiBzY29wZWQpIHtcbiAgICAgICAgICAgICAgaWYgKHMuaXNEaXJlY3RvcnkoKSAmJiAhcy5uYW1lLnN0YXJ0c1dpdGgoXCIuXCIpKSB7XG4gICAgICAgICAgICAgICAgbmFtZXMucHVzaChgJHtlLm5hbWV9LyR7cy5uYW1lfWApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAvLyBpZ25vcmUgc2NvcGUgcmVhZCBlcnJvcnNcbiAgICAgICAgICAgIGxvZy52ZXJib3NlKGBGYWlsZWQgdG8gcmVhZCBzY29wZSAke3Njb3BlUGF0aH06ICR7ZXJyfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuYW1lcy5wdXNoKGUubmFtZSk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBsb2cudmVyYm9zZShgU2tpcHBpbmcgZW50cnkgJHtlLm5hbWV9IGR1ZSB0byBlcnJvcjogJHtlcnJ9YCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBuYW1lcztcbiAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgIGxvZy52ZXJib3NlKGBGYWlsZWQgdG8gbGlzdCBub2RlX21vZHVsZXMgcGFja2FnZXMgYXQgJHtiYXNlUGF0aH06ICR7ZX1gKTtcbiAgICByZXR1cm4gW107XG4gIH1cbn1cbiIsIi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmluaXRpb24gb2YgYSBzbG9nYW4gaXRlbS5cbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBzaW5nbGUgc2xvZ2FuIGVudHJ5IHdpdGggdGV4dCBhbmQgdGFncy5cbiAqIEB0eXBlZGVmIHtPYmplY3R9IFNsb2dhbkl0ZW1cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBTbG9nYW4gLSBUaGUgc2xvZ2FuIHRleHQuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gVGFncyAtIENvbW1hLXNlcGFyYXRlZCB0YWdzIGRlc2NyaWJpbmcgdGhlIHNsb2dhbi5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBMaXN0IG9mIGF2YWlsYWJsZSBzbG9nYW5zIGZvciBiYW5uZXJzIGFuZCBtZXNzYWdlcy5cbiAqIEBzdW1tYXJ5IEltbXV0YWJsZSBhcnJheSBvZiBzbG9nYW4gZW50cmllcyB1c2VkIGJ5IHtAbGluayBnZXRTbG9nYW59IGFuZCBiYW5uZXIgcmVuZGVyaW5nLlxuICogQHR5cGUge1Nsb2dhbkl0ZW1bXX1cbiAqIEBjb25zdCBzbG9nYW5zXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBzbG9nYW5zID0gW1xuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLCBubyBjaGFvcy4gSnVzdCBjbGVhbiBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2FsbSwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZ1bGwgZmxhdm9yLCBubyBqaXR0ZXJzLiBUaGF0J3MgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGVlcmZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNoaWxsIGZ1bGxzdGFjay4gUG93ZXJlZCBieSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1biwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBCcmV3ZWQgZm9yIGNhbG0gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEJyYW5kaW5nXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU21vb3RoIGFzIHlvdXIgbW9ybmluZyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQWxsIHRoZSBraWNrLCBub25lIG9mIHRoZSBjcmFzaC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEVuZXJnZXRpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNpcCBiYWNrIGFuZCBzaGlwIGZhc3Rlci5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIktlZXAgY2FsbSBhbmQgY29kZSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGhvdXQgdGhlIGNhZmZlaW5lIHNoYWtlcy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEh1bW9yb3VzXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiWW91ciBmdWxsc3RhY2ssIGRlY2FmZmVpbmF0ZWQuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZSwgbm8gY2hhb3MuIEp1c3QgY2xlYW4gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENhbG0sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGdWxsIGZsYXZvciwgbm8gaml0dGVycy4gVGhhdFxcdTIwMTlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hlZXJmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDaGlsbCBmdWxsc3RhY2suIFBvd2VyZWQgYnkgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW4sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogQnJld2VkIGZvciBjYWxtIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBCcmFuZGluZ1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNtb290aCBhcyB5b3VyIG1vcm5pbmcgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkFsbCB0aGUga2ljaywgbm9uZSBvZiB0aGUgY3Jhc2guXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBFbmVyZ2V0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaXAgYmFjayBhbmQgc2hpcCBmYXN0ZXIuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJLZWVwIGNhbG0gYW5kIGNvZGUgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRob3V0IHRoZSBjYWZmZWluZSBzaGFrZXMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBIdW1vcm91c1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIllvdXIgZnVsbHN0YWNrLCBkZWNhZmZlaW5hdGVkLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUsIG5vIGNoYW9zLiBKdXN0IGNsZWFuIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDYWxtLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnVsbCBmbGF2b3IsIG5vIGppdHRlcnMuIFRoYXRcXHUyMDE5cyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoZWVyZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ2hpbGwgZnVsbHN0YWNrLiBQb3dlcmVkIGJ5IERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IEJyZXdlZCBmb3IgY2FsbSBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQnJhbmRpbmdcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTbW9vdGggYXMgeW91ciBtb3JuaW5nIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJBbGwgdGhlIGtpY2ssIG5vbmUgb2YgdGhlIGNyYXNoLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRW5lcmdldGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2lwIGJhY2sgYW5kIHNoaXAgZmFzdGVyLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiS2VlcCBjYWxtIGFuZCBjb2RlIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aG91dCB0aGUgY2FmZmVpbmUgc2hha2VzLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgSHVtb3JvdXNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJZb3VyIGZ1bGxzdGFjaywgZGVjYWZmZWluYXRlZC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLCBubyBjaGFvcy4gSnVzdCBjbGVhbiBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2FsbSwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZ1bGwgZmxhdm9yLCBubyBqaXR0ZXJzLiBUaGF0XFx1MjAxOXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGVlcmZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNoaWxsIGZ1bGxzdGFjay4gUG93ZXJlZCBieSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1biwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBCcmV3ZWQgZm9yIGNhbG0gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEJyYW5kaW5nXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU21vb3RoIGFzIHlvdXIgbW9ybmluZyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQWxsIHRoZSBraWNrLCBub25lIG9mIHRoZSBjcmFzaC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEVuZXJnZXRpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNpcCBiYWNrIGFuZCBzaGlwIGZhc3Rlci5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIktlZXAgY2FsbSBhbmQgY29kZSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGhvdXQgdGhlIGNhZmZlaW5lIHNoYWtlcy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEh1bW9yb3VzXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiWW91ciBmdWxsc3RhY2ssIGRlY2FmZmVpbmF0ZWQuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZSwgbm8gY2hhb3MuIEp1c3QgY2xlYW4gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENhbG0sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGdWxsIGZsYXZvciwgbm8gaml0dGVycy4gVGhhdFxcdTIwMTlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hlZXJmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDaGlsbCBmdWxsc3RhY2suIFBvd2VyZWQgYnkgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW4sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogQnJld2VkIGZvciBjYWxtIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBCcmFuZGluZ1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNtb290aCBhcyB5b3VyIG1vcm5pbmcgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkFsbCB0aGUga2ljaywgbm9uZSBvZiB0aGUgY3Jhc2guXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBFbmVyZ2V0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaXAgYmFjayBhbmQgc2hpcCBmYXN0ZXIuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJLZWVwIGNhbG0gYW5kIGNvZGUgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRob3V0IHRoZSBjYWZmZWluZSBzaGFrZXMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBIdW1vcm91c1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIllvdXIgZnVsbHN0YWNrLCBkZWNhZmZlaW5hdGVkLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUsIG5vIGNoYW9zLiBKdXN0IGNsZWFuIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDYWxtLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnVsbCBmbGF2b3IsIG5vIGppdHRlcnMuIFRoYXRcXHUyMDE5cyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoZWVyZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ2hpbGwgZnVsbHN0YWNrLiBQb3dlcmVkIGJ5IERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IEJyZXdlZCBmb3IgY2FsbSBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQnJhbmRpbmdcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTbW9vdGggYXMgeW91ciBtb3JuaW5nIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJBbGwgdGhlIGtpY2ssIG5vbmUgb2YgdGhlIGNyYXNoLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRW5lcmdldGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2lwIGJhY2sgYW5kIHNoaXAgZmFzdGVyLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiS2VlcCBjYWxtIGFuZCBjb2RlIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aG91dCB0aGUgY2FmZmVpbmUgc2hha2VzLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgSHVtb3JvdXNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJZb3VyIGZ1bGxzdGFjaywgZGVjYWZmZWluYXRlZC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLCBubyBjaGFvcy4gSnVzdCBjbGVhbiBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2FsbSwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZ1bGwgZmxhdm9yLCBubyBqaXR0ZXJzLiBUaGF0XFx1MjAxOXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGVlcmZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNoaWxsIGZ1bGxzdGFjay4gUG93ZXJlZCBieSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1biwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBCcmV3ZWQgZm9yIGNhbG0gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEJyYW5kaW5nXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU21vb3RoIGFzIHlvdXIgbW9ybmluZyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQWxsIHRoZSBraWNrLCBub25lIG9mIHRoZSBjcmFzaC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEVuZXJnZXRpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNpcCBiYWNrIGFuZCBzaGlwIGZhc3Rlci5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIktlZXAgY2FsbSBhbmQgY29kZSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGhvdXQgdGhlIGNhZmZlaW5lIHNoYWtlcy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEh1bW9yb3VzXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiWW91ciBmdWxsc3RhY2ssIGRlY2FmZmVpbmF0ZWQuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZSwgbm8gY2hhb3MuIEp1c3QgY2xlYW4gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENhbG0sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGdWxsIGZsYXZvciwgbm8gaml0dGVycy4gVGhhdFxcdTIwMTlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hlZXJmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDaGlsbCBmdWxsc3RhY2suIFBvd2VyZWQgYnkgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW4sIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogQnJld2VkIGZvciBjYWxtIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBCcmFuZGluZ1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNtb290aCBhcyB5b3VyIG1vcm5pbmcgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkFsbCB0aGUga2ljaywgbm9uZSBvZiB0aGUgY3Jhc2guXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBFbmVyZ2V0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaXAgYmFjayBhbmQgc2hpcCBmYXN0ZXIuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJLZWVwIGNhbG0gYW5kIGNvZGUgRGVjYWYuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRob3V0IHRoZSBjYWZmZWluZSBzaGFrZXMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBIdW1vcm91c1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIllvdXIgZnVsbHN0YWNrLCBkZWNhZmZlaW5hdGVkLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUsIG5vIGNoYW9zLiBKdXN0IGNsZWFuIGNvZGUuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDYWxtLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnVsbCBmbGF2b3IsIG5vIGppdHRlcnMuIFRoYXRcXHUyMDE5cyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoZWVyZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ2hpbGwgZnVsbHN0YWNrLiBQb3dlcmVkIGJ5IERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFM6IEJyZXdlZCBmb3IgY2FsbSBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQnJhbmRpbmdcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTbW9vdGggYXMgeW91ciBtb3JuaW5nIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJBbGwgdGhlIGtpY2ssIG5vbmUgb2YgdGhlIGNyYXNoLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRW5lcmdldGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2lwIGJhY2sgYW5kIHNoaXAgZmFzdGVyLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiS2VlcCBjYWxtIGFuZCBjb2RlIERlY2FmLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aG91dCB0aGUgY2FmZmVpbmUgc2hha2VzLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgSHVtb3JvdXNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJZb3VyIGZ1bGxzdGFjaywgZGVjYWZmZWluYXRlZC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLCBubyBjaGFvcy4gSnVzdCBjbGVhbiBjb2RlLlwiLFxuICAgIFRhZ3M6IFwiQ29mZmVlLXRoZW1lZCwgQ2FsbSwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZ1bGwgZmxhdm9yLCBubyBqaXR0ZXJzLiBUaGF0XFx1MjAxOXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBDaGVlcmZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNoaWxsIGZ1bGxzdGFjay4gUG93ZXJlZCBieSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1biwgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTOiBCcmV3ZWQgZm9yIGNhbG0gY29kZS5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEJyYW5kaW5nXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU21vb3RoIGFzIHlvdXIgbW9ybmluZyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQWxsIHRoZSBraWNrLCBub25lIG9mIHRoZSBjcmFzaC5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEVuZXJnZXRpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNpcCBiYWNrIGFuZCBzaGlwIGZhc3Rlci5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIktlZXAgY2FsbSBhbmQgY29kZSBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGhvdXQgdGhlIGNhZmZlaW5lIHNoYWtlcy5cIixcbiAgICBUYWdzOiBcIkNvZmZlZS10aGVtZWQsIEh1bW9yb3VzXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiWW91ciBmdWxsc3RhY2ssIGRlY2FmZmVpbmF0ZWQuXCIsXG4gICAgVGFnczogXCJDb2ZmZWUtdGhlbWVkLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogV2hlcmUgc21hcnQgY29udHJhY3RzIG1lZXQgc21hcnQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFNtYXJ0IENvbnRyYWN0cywgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNoaXAgZEFwcHMgd2l0aG91dCB0aGUgc3RyZXNzLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgQ2hlZXJmdWwsIERldmVsb3BlclwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIENSVUQsIG5vIHByb2JsZW0gXFx1MjAxNCBEZWNhZiB5b3VyIGRhdGEuXCIsXG4gICAgVGFnczogXCJEYXRhLCBOby1DUlVELCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZyb20gRElEIHRvIFVJLCB3aXRob3V0IGJyZWFraW5nIGEgc3dlYXQuXCIsXG4gICAgVGFnczogXCJESUQsIFNTSSwgVUksIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUzogWW91ciBmcm9udGVuZCBhbHJlYWR5IHVuZGVyc3RhbmRzIHlvdXIgc21hcnQgY29udHJhY3QuXCIsXG4gICAgVGFnczogXCJTbWFydCBDb250cmFjdHMsIERYLCBNYWdpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNlbGYtc292ZXJlaWduIGJ5IGRlc2lnbi4gUHJvZHVjdGl2ZSBieSBkZWZhdWx0LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBEZXZlbG9wZXIsIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCdWlsZCBvbmNlLiBEZXBsb3kgZXZlcnl3aGVyZS4gRGVjZW50cmFsaXplZCBhbmQgZGVsaWdodGZ1bC5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIE11bHRpLXBsYXRmb3JtLCBIYXBweVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRhdGEgdGhhdCBkZWZpbmVzIGl0cyBvd24gZGVzdGlueS5cIixcbiAgICBUYWdzOiBcIlNTSSwgRGF0YS1kcml2ZW4sIEVtcG93ZXJtZW50XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiR29vZGJ5ZSBDUlVELCBoZWxsbyBpbnRlbnQtYmFzZWQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIk5vLUNSVUQsIFVJLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJUaGUgc21vb3RoZXN0IHBhdGggZnJvbSBESUQgdG8gZG9uZS5cIixcbiAgICBUYWdzOiBcIkRJRCwgV29ya2Zsb3csIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQmVjYXVzZSB5b3VyIGRBcHAgZGVzZXJ2ZXMgbW9yZSB0aGFuIGJvaWxlcnBsYXRlLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgRGV2WCwgRWZmaWNpZW5jeVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk93biB5b3VyIGRhdGEuIE93biB5b3VyIGZsb3cuXCIsXG4gICAgVGFnczogXCJTU0ksIENvbnRyb2wsIE93bmVyc2hpcFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIldyaXRlIGxvZ2ljIGxpa2UgaXQgYmVsb25ncyB3aXRoIHRoZSBkYXRhIFxcdTIwMTQgYmVjYXVzZSBpdCBkb2VzLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSBMb2dpYywgRGV2ZWxvcGVyLCBTbWFydFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZyb20gc21hcnQgY29udHJhY3RzIHRvIHNtYXJ0ZXIgZnJvbnRlbmRzLlwiLFxuICAgIFRhZ3M6IFwiU21hcnQgQ29udHJhY3RzLCBVSSwgRFhcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZS4gTm8gQ1JVRC4gSnVzdCB0aGUgZnV0dXJlLlwiLFxuICAgIFRhZ3M6IFwiTm8tQ1JVRCwgQ29mZmVlLXRoZW1lZCwgRnV0dXJpc3RpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlRoZSBmdXR1cmUgb2Ygd2ViMyBVWCBpcyBEZWNhZi5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFVYLCBWaXNpb25cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGggY29uZmlkZW5jZS4gR292ZXJuIHdpdGggY2xhcml0eS5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIEdvdmVybmFuY2UsIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJJbnRlcmZhY2VzIHRoYXQgb2JleSB0aGUgZGF0YSwgbm90IHRoZSBvdGhlciB3YXkgYXJvdW5kLlwiLFxuICAgIFRhZ3M6IFwiVUksIERhdGEgTG9naWMsIFNlbGYtYXdhcmVcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCcmV3IGJ1c2luZXNzIGxvZ2ljIHJpZ2h0IGludG8geW91ciBieXRlcy5cIixcbiAgICBUYWdzOiBcIkRhdGEgTG9naWMsIENvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRJRHMgZG9uZSBkaWZmZXJlbnRseSBcXHUyMDE0IGFuZCBkZWxpZ2h0ZnVsbHkuXCIsXG4gICAgVGFnczogXCJESUQsIFNlbGYtU292ZXJlaWduLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFMtVFM6IFdoZXJlIGJsb2NrY2hhaW4gY29udHJhY3RzIG1lZXQgc21hcnQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFNtYXJ0IENvbnRyYWN0cywgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNoaXAgZEFwcHMgd2l0aG91dCB0aGUgc3RyZXNzLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgQ2hlZXJmdWwsIERldmVsb3BlclwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGJvaWxlcnBsYXRlLCBubyBwcm9ibGVtIFxcdTIwMTQgRGVjYWYtVFMgeW91ciBkYXRhLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSwgTm8tQ1JVRCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGcm9tIERJRCB0byBVSSwgd2l0aG91dCBicmVha2luZyBhIHN3ZWF0LlwiLFxuICAgIFRhZ3M6IFwiRElELCBTU0ksIFVJLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46XG4gICAgICBcIkRlY2FmLVRTLVRTOiBZb3VyIGZyb250ZW5kIGFscmVhZHkgdW5kZXJzdGFuZHMgeW91ciBibG9ja2NoYWluIGNvbnRyYWN0LlwiLFxuICAgIFRhZ3M6IFwiU21hcnQgQ29udHJhY3RzLCBEWCwgTWFnaWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTZWxmLXNvdmVyZWlnbiBieSBkZXNpZ24uIFByb2R1Y3RpdmUgYnkgZGVmYXVsdC5cIixcbiAgICBUYWdzOiBcIlNTSSwgRGV2ZWxvcGVyLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQnVpbGQgb25jZS4gRGVwbG95IGV2ZXJ5d2hlcmUuIERlY2VudHJhbGl6ZWQgYW5kIGRlbGlnaHRmdWwuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBNdWx0aS1wbGF0Zm9ybSwgSGFwcHlcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEYXRhIHRoYXQgZGVmaW5lcyBpdHMgb3duIGRlc3RpbnkuXCIsXG4gICAgVGFnczogXCJTU0ksIERhdGEtZHJpdmVuLCBFbXBvd2VybWVudFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkdvb2RieWUgYm9pbGVycGxhdGUsIGhlbGxvIGludGVudC1iYXNlZCBpbnRlcmZhY2VzLlwiLFxuICAgIFRhZ3M6IFwiTm8tQ1JVRCwgVUksIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlRoZSBzbW9vdGhlc3QgcGF0aCBmcm9tIERJRCB0byBkb25lLlwiLFxuICAgIFRhZ3M6IFwiRElELCBXb3JrZmxvdywgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCZWNhdXNlIHlvdXIgZEFwcCBkZXNlcnZlcyBtb3JlIHRoYW4gYm9pbGVycGxhdGUuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBEZXZYLCBFZmZpY2llbmN5XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiT3duIHlvdXIgZGF0YS4gT3duIHlvdXIgZmxvdy5cIixcbiAgICBUYWdzOiBcIlNTSSwgQ29udHJvbCwgT3duZXJzaGlwXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiV3JpdGUgbG9naWMgbGlrZSBpdCBiZWxvbmdzIHdpdGggdGhlIGRhdGEgXFx1MjAxNCBiZWNhdXNlIGl0IGRvZXMuXCIsXG4gICAgVGFnczogXCJEYXRhIExvZ2ljLCBEZXZlbG9wZXIsIFNtYXJ0XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnJvbSBibG9ja2NoYWluIGNvbnRyYWN0cyB0byBzbWFydGVyIGZyb250ZW5kcy5cIixcbiAgICBUYWdzOiBcIlNtYXJ0IENvbnRyYWN0cywgVUksIERYXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUuIE5vIGJvaWxlcnBsYXRlLiBKdXN0IHRoZSBmdXR1cmUuXCIsXG4gICAgVGFnczogXCJOby1DUlVELCBDb2ZmZWUtdGhlbWVkLCBGdXR1cmlzdGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiVGhlIGZ1dHVyZSBvZiB3ZWIzIFVYIGlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgVVgsIFZpc2lvblwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aCBjb25maWRlbmNlLiBHb3Zlcm4gd2l0aCBjbGFyaXR5LlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgR292ZXJuYW5jZSwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkludGVyZmFjZXMgdGhhdCBvYmV5IHRoZSBkYXRhLCBub3QgdGhlIG90aGVyIHdheSBhcm91bmQuXCIsXG4gICAgVGFnczogXCJVSSwgRGF0YSBMb2dpYywgU2VsZi1hd2FyZVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJyZXcgYnVzaW5lc3MgbG9naWMgcmlnaHQgaW50byB5b3VyIGJ5dGVzLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSBMb2dpYywgQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRElEcyBkb25lIGRpZmZlcmVudGx5IFxcdTIwMTQgYW5kIGRlbGlnaHRmdWxseS5cIixcbiAgICBUYWdzOiBcIkRJRCwgU2VsZi1Tb3ZlcmVpZ24sIFBsYXlmdWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEZWNhZi1UUy1UUzogV2hlcmUgYmxvY2tjaGFpbiBjb250cmFjdHMgbWVldCBzbWFydCBpbnRlcmZhY2VzLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgU21hcnQgQ29udHJhY3RzLCBUZWNoXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2hpcCBkQXBwcyB3aXRob3V0IHRoZSBzdHJlc3MuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBDaGVlcmZ1bCwgRGV2ZWxvcGVyXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gYm9pbGVycGxhdGUsIG5vIHByb2JsZW0gXFx1MjAxNCBEZWNhZi1UUyB5b3VyIGRhdGEuXCIsXG4gICAgVGFnczogXCJEYXRhLCBOby1DUlVELCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZyb20gRElEIHRvIFVJLCB3aXRob3V0IGJyZWFraW5nIGEgc3dlYXQuXCIsXG4gICAgVGFnczogXCJESUQsIFNTSSwgVUksIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjpcbiAgICAgIFwiRGVjYWYtVFMtVFM6IFlvdXIgZnJvbnRlbmQgYWxyZWFkeSB1bmRlcnN0YW5kcyB5b3VyIGJsb2NrY2hhaW4gY29udHJhY3QuXCIsXG4gICAgVGFnczogXCJTbWFydCBDb250cmFjdHMsIERYLCBNYWdpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNlbGYtc292ZXJlaWduIGJ5IGRlc2lnbi4gUHJvZHVjdGl2ZSBieSBkZWZhdWx0LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBEZXZlbG9wZXIsIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCdWlsZCBvbmNlLiBEZXBsb3kgZXZlcnl3aGVyZS4gRGVjZW50cmFsaXplZCBhbmQgZGVsaWdodGZ1bC5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIE11bHRpLXBsYXRmb3JtLCBIYXBweVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRhdGEgdGhhdCBkZWZpbmVzIGl0cyBvd24gZGVzdGlueS5cIixcbiAgICBUYWdzOiBcIlNTSSwgRGF0YS1kcml2ZW4sIEVtcG93ZXJtZW50XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiR29vZGJ5ZSBib2lsZXJwbGF0ZSwgaGVsbG8gaW50ZW50LWJhc2VkIGludGVyZmFjZXMuXCIsXG4gICAgVGFnczogXCJOby1DUlVELCBVSSwgVGVjaG5pY2FsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiVGhlIHNtb290aGVzdCBwYXRoIGZyb20gRElEIHRvIGRvbmUuXCIsXG4gICAgVGFnczogXCJESUQsIFdvcmtmbG93LCBDaGlsbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJlY2F1c2UgeW91ciBkQXBwIGRlc2VydmVzIG1vcmUgdGhhbiBib2lsZXJwbGF0ZS5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIERldlgsIEVmZmljaWVuY3lcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJPd24geW91ciBkYXRhLiBPd24geW91ciBmbG93LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBDb250cm9sLCBPd25lcnNoaXBcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJXcml0ZSBsb2dpYyBsaWtlIGl0IGJlbG9uZ3Mgd2l0aCB0aGUgZGF0YSBcXHUyMDE0IGJlY2F1c2UgaXQgZG9lcy5cIixcbiAgICBUYWdzOiBcIkRhdGEgTG9naWMsIERldmVsb3BlciwgU21hcnRcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGcm9tIGJsb2NrY2hhaW4gY29udHJhY3RzIHRvIHNtYXJ0ZXIgZnJvbnRlbmRzLlwiLFxuICAgIFRhZ3M6IFwiU21hcnQgQ29udHJhY3RzLCBVSSwgRFhcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBjYWZmZWluZS4gTm8gYm9pbGVycGxhdGUuIEp1c3QgdGhlIGZ1dHVyZS5cIixcbiAgICBUYWdzOiBcIk5vLUNSVUQsIENvZmZlZS10aGVtZWQsIEZ1dHVyaXN0aWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJUaGUgZnV0dXJlIG9mIHdlYjMgVVggaXMgRGVjYWYtVFMuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBVWCwgVmlzaW9uXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQ29kZSB3aXRoIGNvbmZpZGVuY2UuIEdvdmVybiB3aXRoIGNsYXJpdHkuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBHb3Zlcm5hbmNlLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiSW50ZXJmYWNlcyB0aGF0IG9iZXkgdGhlIGRhdGEsIG5vdCB0aGUgb3RoZXIgd2F5IGFyb3VuZC5cIixcbiAgICBUYWdzOiBcIlVJLCBEYXRhIExvZ2ljLCBTZWxmLWF3YXJlXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQnJldyBidXNpbmVzcyBsb2dpYyByaWdodCBpbnRvIHlvdXIgYnl0ZXMuXCIsXG4gICAgVGFnczogXCJEYXRhIExvZ2ljLCBDb2ZmZWUtdGhlbWVkLCBGdW5cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJESURzIGRvbmUgZGlmZmVyZW50bHkgXFx1MjAxNCBhbmQgZGVsaWdodGZ1bGx5LlwiLFxuICAgIFRhZ3M6IFwiRElELCBTZWxmLVNvdmVyZWlnbiwgUGxheWZ1bFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRlY2FmLVRTLVRTOiBXaGVyZSBibG9ja2NoYWluIGNvbnRyYWN0cyBtZWV0IHNtYXJ0IGludGVyZmFjZXMuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBTbWFydCBDb250cmFjdHMsIFRlY2hcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTaGlwIGRBcHBzIHdpdGhvdXQgdGhlIHN0cmVzcy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIENoZWVyZnVsLCBEZXZlbG9wZXJcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJObyBib2lsZXJwbGF0ZSwgbm8gcHJvYmxlbSBcXHUyMDE0IERlY2FmLVRTIHlvdXIgZGF0YS5cIixcbiAgICBUYWdzOiBcIkRhdGEsIE5vLUNSVUQsIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnJvbSBESUQgdG8gVUksIHdpdGhvdXQgYnJlYWtpbmcgYSBzd2VhdC5cIixcbiAgICBUYWdzOiBcIkRJRCwgU1NJLCBVSSwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOlxuICAgICAgXCJEZWNhZi1UUy1UUzogWW91ciBmcm9udGVuZCBhbHJlYWR5IHVuZGVyc3RhbmRzIHlvdXIgYmxvY2tjaGFpbiBjb250cmFjdC5cIixcbiAgICBUYWdzOiBcIlNtYXJ0IENvbnRyYWN0cywgRFgsIE1hZ2ljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiU2VsZi1zb3ZlcmVpZ24gYnkgZGVzaWduLiBQcm9kdWN0aXZlIGJ5IGRlZmF1bHQuXCIsXG4gICAgVGFnczogXCJTU0ksIERldmVsb3BlciwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJ1aWxkIG9uY2UuIERlcGxveSBldmVyeXdoZXJlLiBEZWNlbnRyYWxpemVkIGFuZCBkZWxpZ2h0ZnVsLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgTXVsdGktcGxhdGZvcm0sIEhhcHB5XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGF0YSB0aGF0IGRlZmluZXMgaXRzIG93biBkZXN0aW55LlwiLFxuICAgIFRhZ3M6IFwiU1NJLCBEYXRhLWRyaXZlbiwgRW1wb3dlcm1lbnRcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJHb29kYnllIGJvaWxlcnBsYXRlLCBoZWxsbyBpbnRlbnQtYmFzZWQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIk5vLUNSVUQsIFVJLCBUZWNobmljYWxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJUaGUgc21vb3RoZXN0IHBhdGggZnJvbSBESUQgdG8gZG9uZS5cIixcbiAgICBUYWdzOiBcIkRJRCwgV29ya2Zsb3csIENoaWxsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQmVjYXVzZSB5b3VyIGRBcHAgZGVzZXJ2ZXMgbW9yZSB0aGFuIGJvaWxlcnBsYXRlLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgRGV2WCwgRWZmaWNpZW5jeVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk93biB5b3VyIGRhdGEuIE93biB5b3VyIGZsb3cuXCIsXG4gICAgVGFnczogXCJTU0ksIENvbnRyb2wsIE93bmVyc2hpcFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIldyaXRlIGxvZ2ljIGxpa2UgaXQgYmVsb25ncyB3aXRoIHRoZSBkYXRhIFxcdTIwMTQgYmVjYXVzZSBpdCBkb2VzLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSBMb2dpYywgRGV2ZWxvcGVyLCBTbWFydFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkZyb20gYmxvY2tjaGFpbiBjb250cmFjdHMgdG8gc21hcnRlciBmcm9udGVuZHMuXCIsXG4gICAgVGFnczogXCJTbWFydCBDb250cmFjdHMsIFVJLCBEWFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGNhZmZlaW5lLiBObyBib2lsZXJwbGF0ZS4gSnVzdCB0aGUgZnV0dXJlLlwiLFxuICAgIFRhZ3M6IFwiTm8tQ1JVRCwgQ29mZmVlLXRoZW1lZCwgRnV0dXJpc3RpY1wiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlRoZSBmdXR1cmUgb2Ygd2ViMyBVWCBpcyBEZWNhZi1UUy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFVYLCBWaXNpb25cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJDb2RlIHdpdGggY29uZmlkZW5jZS4gR292ZXJuIHdpdGggY2xhcml0eS5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIEdvdmVybmFuY2UsIENhbG1cIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJJbnRlcmZhY2VzIHRoYXQgb2JleSB0aGUgZGF0YSwgbm90IHRoZSBvdGhlciB3YXkgYXJvdW5kLlwiLFxuICAgIFRhZ3M6IFwiVUksIERhdGEgTG9naWMsIFNlbGYtYXdhcmVcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCcmV3IGJ1c2luZXNzIGxvZ2ljIHJpZ2h0IGludG8geW91ciBieXRlcy5cIixcbiAgICBUYWdzOiBcIkRhdGEgTG9naWMsIENvZmZlZS10aGVtZWQsIEZ1blwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkRJRHMgZG9uZSBkaWZmZXJlbnRseSBcXHUyMDE0IGFuZCBkZWxpZ2h0ZnVsbHkuXCIsXG4gICAgVGFnczogXCJESUQsIFNlbGYtU292ZXJlaWduLCBQbGF5ZnVsXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRGVjYWYtVFMtVFM6IFdoZXJlIGJsb2NrY2hhaW4gY29udHJhY3RzIG1lZXQgc21hcnQgaW50ZXJmYWNlcy5cIixcbiAgICBUYWdzOiBcIkJsb2NrY2hhaW4sIFNtYXJ0IENvbnRyYWN0cywgVGVjaFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlNoaXAgZEFwcHMgd2l0aG91dCB0aGUgc3RyZXNzLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgQ2hlZXJmdWwsIERldmVsb3BlclwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIk5vIGJvaWxlcnBsYXRlLCBubyBwcm9ibGVtIFxcdTIwMTQgRGVjYWYtVFMgeW91ciBkYXRhLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSwgTm8tQ1JVRCwgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJGcm9tIERJRCB0byBVSSwgd2l0aG91dCBicmVha2luZyBhIHN3ZWF0LlwiLFxuICAgIFRhZ3M6IFwiRElELCBTU0ksIFVJLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46XG4gICAgICBcIkRlY2FmLVRTLVRTOiBZb3VyIGZyb250ZW5kIGFscmVhZHkgdW5kZXJzdGFuZHMgeW91ciBibG9ja2NoYWluIGNvbnRyYWN0LlwiLFxuICAgIFRhZ3M6IFwiU21hcnQgQ29udHJhY3RzLCBEWCwgTWFnaWNcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJTZWxmLXNvdmVyZWlnbiBieSBkZXNpZ24uIFByb2R1Y3RpdmUgYnkgZGVmYXVsdC5cIixcbiAgICBUYWdzOiBcIlNTSSwgRGV2ZWxvcGVyLCBDYWxtXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiQnVpbGQgb25jZS4gRGVwbG95IGV2ZXJ5d2hlcmUuIERlY2VudHJhbGl6ZWQgYW5kIGRlbGlnaHRmdWwuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBNdWx0aS1wbGF0Zm9ybSwgSGFwcHlcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJEYXRhIHRoYXQgZGVmaW5lcyBpdHMgb3duIGRlc3RpbnkuXCIsXG4gICAgVGFnczogXCJTU0ksIERhdGEtZHJpdmVuLCBFbXBvd2VybWVudFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkdvb2RieWUgYm9pbGVycGxhdGUsIGhlbGxvIGludGVudC1iYXNlZCBpbnRlcmZhY2VzLlwiLFxuICAgIFRhZ3M6IFwiTm8tQ1JVRCwgVUksIFRlY2huaWNhbFwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIlRoZSBzbW9vdGhlc3QgcGF0aCBmcm9tIERJRCB0byBkb25lLlwiLFxuICAgIFRhZ3M6IFwiRElELCBXb3JrZmxvdywgQ2hpbGxcIixcbiAgfSxcbiAge1xuICAgIFNsb2dhbjogXCJCZWNhdXNlIHlvdXIgZEFwcCBkZXNlcnZlcyBtb3JlIHRoYW4gYm9pbGVycGxhdGUuXCIsXG4gICAgVGFnczogXCJCbG9ja2NoYWluLCBEZXZYLCBFZmZpY2llbmN5XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiT3duIHlvdXIgZGF0YS4gT3duIHlvdXIgZmxvdy5cIixcbiAgICBUYWdzOiBcIlNTSSwgQ29udHJvbCwgT3duZXJzaGlwXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiV3JpdGUgbG9naWMgbGlrZSBpdCBiZWxvbmdzIHdpdGggdGhlIGRhdGEgXFx1MjAxNCBiZWNhdXNlIGl0IGRvZXMuXCIsXG4gICAgVGFnczogXCJEYXRhIExvZ2ljLCBEZXZlbG9wZXIsIFNtYXJ0XCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRnJvbSBibG9ja2NoYWluIGNvbnRyYWN0cyB0byBzbWFydGVyIGZyb250ZW5kcy5cIixcbiAgICBUYWdzOiBcIlNtYXJ0IENvbnRyYWN0cywgVUksIERYXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiTm8gY2FmZmVpbmUuIE5vIGJvaWxlcnBsYXRlLiBKdXN0IHRoZSBmdXR1cmUuXCIsXG4gICAgVGFnczogXCJOby1DUlVELCBDb2ZmZWUtdGhlbWVkLCBGdXR1cmlzdGljXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiVGhlIGZ1dHVyZSBvZiB3ZWIzIFVYIGlzIERlY2FmLVRTLlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgVVgsIFZpc2lvblwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkNvZGUgd2l0aCBjb25maWRlbmNlLiBHb3Zlcm4gd2l0aCBjbGFyaXR5LlwiLFxuICAgIFRhZ3M6IFwiQmxvY2tjaGFpbiwgR292ZXJuYW5jZSwgQ2FsbVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkludGVyZmFjZXMgdGhhdCBvYmV5IHRoZSBkYXRhLCBub3QgdGhlIG90aGVyIHdheSBhcm91bmQuXCIsXG4gICAgVGFnczogXCJVSSwgRGF0YSBMb2dpYywgU2VsZi1hd2FyZVwiLFxuICB9LFxuICB7XG4gICAgU2xvZ2FuOiBcIkJyZXcgYnVzaW5lc3MgbG9naWMgcmlnaHQgaW50byB5b3VyIGJ5dGVzLlwiLFxuICAgIFRhZ3M6IFwiRGF0YSBMb2dpYywgQ29mZmVlLXRoZW1lZCwgRnVuXCIsXG4gIH0sXG4gIHtcbiAgICBTbG9nYW46IFwiRElEcyBkb25lIGRpZmZlcmVudGx5IFxcdTIwMTQgYW5kIGRlbGlnaHRmdWxseS5cIixcbiAgICBUYWdzOiBcIkRJRCwgU2VsZi1Tb3ZlcmVpZ24sIFBsYXlmdWxcIixcbiAgfSxcbl07XG4iLCJpbXBvcnQgeyBzbG9nYW5zIH0gZnJvbSBcIi4uL2Fzc2V0cy9zbG9nYW5zXCI7XG5pbXBvcnQgeyBzdHlsZSB9IGZyb20gXCJzdHlsZWQtc3RyaW5nLWJ1aWxkZXJcIjtcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBBcnJheSBvZiBBTlNJIGNvbG9yIGNvZGVzIGZvciBiYW5uZXIgc3R5bGluZy5cbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBzZXQgb2YgQU5TSSBjb2xvciBjb2RlcyB1c2VkIHRvIHN0eWxlIHRoZSBiYW5uZXIgdGV4dC5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuY29uc3QgY29sb3JzID0gW1xuICBcIlxceDFiWzM4OzU7MjE1bVwiLCAvLyBzb2Z0IG9yYW5nZVxuICBcIlxceDFiWzM4OzU7MjA5bVwiLCAvLyBjb3JhbFxuICBcIlxceDFiWzM4OzU7MjA1bVwiLCAvLyBwaW5rXG4gIFwiXFx4MWJbMzg7NTsyMTBtXCIsIC8vIHBlYWNoeVxuICBcIlxceDFiWzM4OzU7MjE3bVwiLCAvLyBzYWxtb25cbiAgXCJcXHgxYlszODs1OzIxNm1cIiwgLy8gbGlnaHQgY29yYWxcbiAgXCJcXHgxYlszODs1OzIyNG1cIiwgLy8gbGlnaHQgcGVhY2hcbiAgXCJcXHgxYlszODs1OzIzMG1cIiwgLy8gc29mdCBjcmVhbVxuICBcIlxceDFiWzM4OzU7MjMwbVwiLCAvLyBzb2Z0IGNyZWFtXG5dO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBQcmludHMgYSBzdHlsZWQgYmFubmVyIHRvIHRoZSBjb25zb2xlLlxuICogQHN1bW1hcnkgR2VuZXJhdGVzIGFuZCBwcmludHMgYSBjb2xvcmZ1bCBBU0NJSSBhcnQgYmFubmVyIHdpdGggYSByYW5kb20gc2xvZ2FuLlxuICogQHBhcmFtIHtMb2dnZXJ9IFtsb2dnZXJdIC0gT3B0aW9uYWwgbG9nZ2VyIGZvciB2ZXJib3NlIG91dHB1dC5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqIEBmdW5jdGlvbiBwcmludEJhbm5lclxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBwcmludEJhbm5lclxuICogICBwYXJ0aWNpcGFudCBnZXRTbG9nYW5cbiAqICAgcGFydGljaXBhbnQgcGFkRW5kXG4gKiAgIHBhcnRpY2lwYW50IGNvbnNvbGVcbiAqICAgcHJpbnRCYW5uZXItPj5nZXRTbG9nYW46IENhbGwgZ2V0U2xvZ2FuKClcbiAqICAgZ2V0U2xvZ2FuLS0+PnByaW50QmFubmVyOiBSZXR1cm4gcmFuZG9tIHNsb2dhblxuICogICBwcmludEJhbm5lci0+PnByaW50QmFubmVyOiBDcmVhdGUgYmFubmVyIEFTQ0lJIGFydFxuICogICBwcmludEJhbm5lci0+PnByaW50QmFubmVyOiBTcGxpdCBiYW5uZXIgaW50byBsaW5lc1xuICogICBwcmludEJhbm5lci0+PnByaW50QmFubmVyOiBDYWxjdWxhdGUgbWF4IGxpbmUgbGVuZ3RoXG4gKiAgIHByaW50QmFubmVyLT4+cGFkRW5kOiBDYWxsIHBhZEVuZCB3aXRoIHNsb2dhblxuICogICBwYWRFbmQtLT4+cHJpbnRCYW5uZXI6IFJldHVybiBwYWRkZWQgc2xvZ2FuIGxpbmVcbiAqICAgbG9vcCBGb3IgZWFjaCBiYW5uZXIgbGluZVxuICogICAgIHByaW50QmFubmVyLT4+c3R5bGU6IENhbGwgc3R5bGUobGluZSlcbiAqICAgICBzdHlsZS0tPj5wcmludEJhbm5lcjogUmV0dXJuIHN0eWxlZCBsaW5lXG4gKiAgICAgcHJpbnRCYW5uZXItPj5jb25zb2xlOiBMb2cgc3R5bGVkIGxpbmVcbiAqICAgZW5kXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcmludEJhbm5lcihsb2dnZXI/OiBMb2dnZXIpIHtcbiAgY29uc3QgbWVzc2FnZSA9IGdldFNsb2dhbigpO1xuICBjb25zdCBiYW5uZXI6IHN0cmluZyB8IHN0cmluZ1tdID1cbiAgICBgIyAgICAgICAgICAgICAgICAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paI4paT4paS4paRICDilpHilpLilpPilojilojilojilojilojilojilojilojilpPilpLilpEgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paI4paI4paT4paS4paRICAgICAgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paI4paT4paS4paRIFxuIyAgICAgICggKCAgICAgICAg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpEgICAgICAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAg4paR4paS4paT4paI4paT4paS4paRICAgICAgICBcbiMgICAgICAgKSApICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpEgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAgICAgICAgICAg4paR4paS4paT4paI4paT4paS4paRICAgICDilpHilpLilpPilojilpPilpLilpEgICAgICAgIFxuIyAgICBbPT09PT09PV0gICAg4paR4paS4paT4paI4paT4paS4paR4paR4paS4paT4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paI4paI4paT4paS4paRIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAgXG4jICAgICBcXGAtLS0tLcK0ICAgICDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paT4paS4paRICAgICAgICDilpHilpLilpPilojilpPilpLilpEgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpEgICAgICAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkSBcbiMgICAgICAgICAgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpEgICAgICAgIOKWkeKWkuKWk+KWiOKWk+KWkuKWkeKWkeKWkuKWk+KWiOKWk+KWkuKWkSDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paT4paS4paRICAgICAgICAgICAgICAgICDilpHilpLilpPilojilpPilpLilpEgICAgICAgICAgICDilpHilpLilpPilojilpPilpLilpEgXG4jICAgICAgICAgICAgICAgICDilpHilpLilpPilojilojilojilojilojilojilojilpPilpLilpEgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAg4paR4paS4paT4paI4paI4paI4paI4paI4paI4paT4paS4paRICDilpHilpLilpPilojilpPilpLilpHilpHilpLilpPilojilpPilpLilpEg4paR4paS4paT4paI4paT4paS4paRICAgICAgICAgICAgICAgICDilpHilpLilpPilojilpPilpLilpEgICAgIOKWkeKWkuKWk+KWiOKWiOKWiOKWiOKWiOKWiOKWiOKWk+KWkuKWkSAgXG4jYC5zcGxpdChcIlxcblwiKTtcbiAgY29uc3QgbWF4TGVuZ3RoID0gYmFubmVyLnJlZHVjZSgobWF4LCBsaW5lKSA9PiBNYXRoLm1heChtYXgsIGxpbmUubGVuZ3RoKSwgMCk7XG4gIGJhbm5lci5wdXNoKGAjICAke21lc3NhZ2UucGFkU3RhcnQobWF4TGVuZ3RoIC0gMyl9YCk7XG4gIGJhbm5lci5mb3JFYWNoKChsaW5lLCBpbmRleCkgPT4ge1xuICAgIChsb2dnZXIgPyBsb2dnZXIuaW5mby5iaW5kKGxvZ2dlcikgOiBjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpKShcbiAgICAgIHN0eWxlKGxpbmUgfHwgXCJcIikucmF3KGNvbG9yc1tpbmRleF0pLnRleHRcbiAgICApO1xuICB9KTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgc2xvZ2FuIGZyb20gdGhlIHByZWRlZmluZWQgbGlzdC5cbiAqIEBzdW1tYXJ5IEZldGNoZXMgYSByYW5kb20gc2xvZ2FuIG9yIGEgc3BlY2lmaWMgb25lIGJ5IGluZGV4IGZyb20gdGhlIHNsb2dhbnMgbGlzdC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbaV0gLSBPcHRpb25hbCBpbmRleCB0byByZXRyaWV2ZSBhIHNwZWNpZmljIHNsb2dhbi5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHNlbGVjdGVkIHNsb2dhbi5cbiAqIEBmdW5jdGlvbiBnZXRTbG9nYW5cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgZ2V0U2xvZ2FuXG4gKiAgIHBhcnRpY2lwYW50IE1hdGgucmFuZG9tXG4gKiAgIHBhcnRpY2lwYW50IHNsb2dhbnNcbiAqICAgYWx0IGkgaXMgdW5kZWZpbmVkXG4gKiAgICAgZ2V0U2xvZ2FuLT4+TWF0aC5yYW5kb206IEdlbmVyYXRlIHJhbmRvbSBpbmRleFxuICogICAgIE1hdGgucmFuZG9tLS0+PmdldFNsb2dhbjogUmV0dXJuIHJhbmRvbSBpbmRleFxuICogICBlbHNlIGkgaXMgZGVmaW5lZFxuICogICAgIE5vdGUgb3ZlciBnZXRTbG9nYW46IFVzZSBwcm92aWRlZCBpbmRleFxuICogICBlbmRcbiAqICAgZ2V0U2xvZ2FuLT4+c2xvZ2FuczogQWNjZXNzIHNsb2dhbiBhdCBpbmRleFxuICogICBzbG9nYW5zLS0+PmdldFNsb2dhbjogUmV0dXJuIHNsb2dhblxuICogICBhbHQgRXJyb3Igb2NjdXJzXG4gKiAgICAgZ2V0U2xvZ2FuLT4+Z2V0U2xvZ2FuOiBUaHJvdyBlcnJvclxuICogICBlbmRcbiAqICAgZ2V0U2xvZ2FuLS0+PkNhbGxlcjogUmV0dXJuIHNsb2dhblxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2xvZ2FuKGk/OiBudW1iZXIpOiBzdHJpbmcge1xuICB0cnkge1xuICAgIGkgPVxuICAgICAgdHlwZW9mIGkgPT09IFwidW5kZWZpbmVkXCIgPyBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBzbG9nYW5zLmxlbmd0aCkgOiBpO1xuICAgIHJldHVybiBzbG9nYW5zW2ldLlNsb2dhbjtcbiAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byByZXRyaWV2ZSBzbG9nYW5zOiAke2Vycm9yfWApO1xuICB9XG59XG4iLCJpbXBvcnQgeyBQYXJzZUFyZ3NSZXN1bHQgfSBmcm9tIFwiLi4vaW5wdXQvdHlwZXNcIjtcbmltcG9ydCB7IENvbW1hbmRPcHRpb25zIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IFVzZXJJbnB1dCB9IGZyb20gXCIuLi9pbnB1dC9pbnB1dFwiO1xuaW1wb3J0IHsgRGVmYXVsdENvbW1hbmRPcHRpb25zLCBEZWZhdWx0Q29tbWFuZFZhbHVlcyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgZ2V0RGVwZW5kZW5jaWVzLCBnZXRQYWNrYWdlVmVyc2lvbiB9IGZyb20gXCIuLi91dGlscy9mc1wiO1xuaW1wb3J0IHsgcHJpbnRCYW5uZXIgfSBmcm9tIFwiLi4vb3V0cHV0L2NvbW1vblwiO1xuaW1wb3J0IHtcbiAgTG9nZ2VkQ2xhc3MsXG4gIExvZ2dlZEVudmlyb25tZW50LFxuICBMb2dnZXIsXG4gIExvZ2dpbmcsXG4gIExvZ2dpbmdDb25maWcsXG59IGZyb20gXCJAZGVjYWYtdHMvbG9nZ2luZ1wiO1xuXG4vKipcbiAqIEBjbGFzcyBDb21tYW5kXG4gKiBAYWJzdHJhY3RcbiAqIEB0ZW1wbGF0ZSBJIC0gVGhlIHR5cGUgb2YgaW5wdXQgb3B0aW9ucyBmb3IgdGhlIGNvbW1hbmQuXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXR1cm4gdHlwZSBvZiB0aGUgY29tbWFuZCBleGVjdXRpb24uXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKiBAZGVzY3JpcHRpb24gQWJzdHJhY3QgYmFzZSBjbGFzcyBmb3IgY29tbWFuZCBpbXBsZW1lbnRhdGlvbi5cbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIGEgc3RydWN0dXJlIGZvciBjcmVhdGluZyBjb21tYW5kLWxpbmUgaW50ZXJmYWNlIGNvbW1hbmRzIHdpdGggaW5wdXQgaGFuZGxpbmcsIGxvZ2dpbmcsIGFuZCBleGVjdXRpb24gZmxvdy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBjb21tYW5kLlxuICogQHBhcmFtIHtDb21tYW5kT3B0aW9uczxJPn0gW2lucHV0c10gLSBUaGUgaW5wdXQgb3B0aW9ucyBmb3IgdGhlIGNvbW1hbmQuXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBbcmVxdWlyZW1lbnRzXSAtIFRoZSBsaXN0IG9mIHJlcXVpcmVkIGRlcGVuZGVuY2llcyBmb3IgdGhlIGNvbW1hbmQuXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBDb21tYW5kPEksIFI+IGV4dGVuZHMgTG9nZ2VkQ2xhc3Mge1xuICAvKipcbiAgICogQHN0YXRpY1xuICAgKiBAZGVzY3JpcHRpb24gU3RhdGljIGxvZ2dlciBmb3IgdGhlIENvbW1hbmQgY2xhc3MuXG4gICAqIEB0eXBlIHtMb2dnZXJ9XG4gICAqL1xuICBzdGF0aWMgbG9nOiBMb2dnZXI7XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBuYW1lOiBzdHJpbmcsXG4gICAgcHJvdGVjdGVkIGlucHV0czogQ29tbWFuZE9wdGlvbnM8ST4gPSB7fSBhcyB1bmtub3duIGFzIENvbW1hbmRPcHRpb25zPEk+LFxuICAgIHByb3RlY3RlZCByZXF1aXJlbWVudHM6IHN0cmluZ1tdID0gW11cbiAgKSB7XG4gICAgc3VwZXIoKTtcbiAgICBpZiAoIUNvbW1hbmQubG9nKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQ29tbWFuZCwgXCJsb2dcIiwge1xuICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgIHZhbHVlOiBMb2dnaW5nLmZvcihDb21tYW5kLm5hbWUpLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHRoaXMuaW5wdXRzID0gT2JqZWN0LmFzc2lnbihcbiAgICAgIHt9LFxuICAgICAgRGVmYXVsdENvbW1hbmRPcHRpb25zLFxuICAgICAgaW5wdXRzXG4gICAgKSBhcyBDb21tYW5kT3B0aW9uczxJPjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvdGVjdGVkXG4gICAqIEBhc3luY1xuICAgKiBAZGVzY3JpcHRpb24gQ2hlY2tzIGlmIGFsbCByZXF1aXJlZCBkZXBlbmRlbmNpZXMgYXJlIHByZXNlbnQuXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyB0aGUgbGlzdCBvZiBkZXBlbmRlbmNpZXMgYW5kIGNvbXBhcmVzIGl0IGFnYWluc3QgdGhlIHJlcXVpcmVkIGRlcGVuZGVuY2llcyBmb3IgdGhlIGNvbW1hbmQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBjaGVjayBpcyBjb21wbGV0ZS5cbiAgICpcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ29tbWFuZFxuICAgKiAgIHBhcnRpY2lwYW50IGdldERlcGVuZGVuY2llc1xuICAgKiAgIHBhcnRpY2lwYW50IFNldFxuICAgKiAgIENvbW1hbmQtPj5nZXREZXBlbmRlbmNpZXM6IENhbGxcbiAgICogICBnZXREZXBlbmRlbmNpZXMtLT4+Q29tbWFuZDogUmV0dXJuIHtwcm9kLCBkZXYsIHBlZXJ9XG4gICAqICAgQ29tbWFuZC0+PlNldDogQ3JlYXRlIFNldCBmcm9tIHByb2QsIGRldiwgcGVlclxuICAgKiAgIFNldC0tPj5Db21tYW5kOiBSZXR1cm4gdW5pcXVlIGRlcGVuZGVuY2llc1xuICAgKiAgIENvbW1hbmQtPj5Db21tYW5kOiBDb21wYXJlIGFnYWluc3QgcmVxdWlyZW1lbnRzXG4gICAqICAgYWx0IE1pc3NpbmcgZGVwZW5kZW5jaWVzXG4gICAqICAgICBDb21tYW5kLT4+Q29tbWFuZDogQWRkIHRvIG1pc3NpbmcgbGlzdFxuICAgKiAgIGVuZFxuICAgKiAgIE5vdGUgb3ZlciBDb21tYW5kOiBJZiBtaXNzaW5nLmxlbmd0aCA+IDAsIGhhbmRsZSBtaXNzaW5nIGRlcGVuZGVuY2llc1xuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGNoZWNrUmVxdWlyZW1lbnRzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgcHJvZCwgZGV2LCBwZWVyIH0gPSBhd2FpdCBnZXREZXBlbmRlbmNpZXMoKTtcbiAgICBjb25zdCBtaXNzaW5nID0gW107XG4gICAgY29uc3QgZnVsbExpc3QgPSBBcnJheS5mcm9tKFxuICAgICAgbmV3IFNldChbLi4ucHJvZCwgLi4uZGV2LCAuLi5wZWVyXSkudmFsdWVzKClcbiAgICApLm1hcCgoZCkgPT4gZC5uYW1lKTtcbiAgICBmb3IgKGNvbnN0IGRlcCBvZiB0aGlzLnJlcXVpcmVtZW50cylcbiAgICAgIGlmICghZnVsbExpc3QuaW5jbHVkZXMoZGVwKSkgbWlzc2luZy5wdXNoKGRlcCk7XG5cbiAgICBpZiAoIW1pc3NpbmcubGVuZ3RoKSByZXR1cm47XG4gIH1cblxuICAvKipcbiAgICogQHByb3RlY3RlZFxuICAgKiBAZGVzY3JpcHRpb24gUHJvdmlkZXMgaGVscCBpbmZvcm1hdGlvbiBmb3IgdGhlIGNvbW1hbmQuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIHNob3VsZCBiZSBvdmVycmlkZGVuIGluIGRlcml2ZWQgY2xhc3NlcyB0byBwcm92aWRlIHNwZWNpZmljIGhlbHAgaW5mb3JtYXRpb24uXG4gICAqIEBwYXJhbSB7UGFyc2VBcmdzUmVzdWx0fSBhcmdzIC0gVGhlIHBhcnNlZCBjb21tYW5kLWxpbmUgYXJndW1lbnRzLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgcHJvdGVjdGVkIGhlbHAoYXJnczogUGFyc2VBcmdzUmVzdWx0KTogdm9pZCB7XG4gICAgcmV0dXJuIHRoaXMubG9nLmluZm8oXG4gICAgICBgVGhpcyBpcyBoZWxwLiBJJ20gbm8gdXNlIGJlY2F1c2UgSSBzaG91bGQgaGF2ZSBiZWVuIG92ZXJyaWRkZW4uYFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3RlY3RlZFxuICAgKiBAYWJzdHJhY3RcbiAgICogQGRlc2NyaXB0aW9uIFJ1bnMgdGhlIGNvbW1hbmQgd2l0aCB0aGUgcHJvdmlkZWQgYXJndW1lbnRzLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBzaG91bGQgYmUgaW1wbGVtZW50ZWQgaW4gZGVyaXZlZCBjbGFzc2VzIHRvIGRlZmluZSB0aGUgY29tbWFuZCdzIGJlaGF2aW9yLlxuICAgKiBAcGFyYW0ge1BhcnNlQXJnc1Jlc3VsdH0gYW5zd2VycyAtIFRoZSBwYXJzZWQgY29tbWFuZC1saW5lIGFyZ3VtZW50cy5cbiAgICogQHJldHVybnMge1Byb21pc2U8UiB8IHN0cmluZyB8IHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBjb21tYW5kJ3MgcmVzdWx0LlxuICAgKi9cbiAgcHJvdGVjdGVkIGFic3RyYWN0IHJ1bjxSPihcbiAgICBhbnN3ZXJzOiBMb2dnaW5nQ29uZmlnICZcbiAgICAgIHR5cGVvZiBEZWZhdWx0Q29tbWFuZFZhbHVlcyAmIHsgW2sgaW4ga2V5b2YgSV06IHVua25vd24gfVxuICApOiBQcm9taXNlPFIgfCBzdHJpbmcgfCB2b2lkPjtcblxuICAvKipcbiAgICogQGFzeW5jXG4gICAqIEBkZXNjcmlwdGlvbiBFeGVjdXRlcyB0aGUgY29tbWFuZC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgaGFuZGxlcyB0aGUgb3ZlcmFsbCBleGVjdXRpb24gZmxvdyBvZiB0aGUgY29tbWFuZCwgaW5jbHVkaW5nIHBhcnNpbmcgYXJndW1lbnRzLFxuICAgKiBzZXR0aW5nIHVwIGxvZ2dpbmcsIGNoZWNraW5nIGZvciB2ZXJzaW9uIG9yIGhlbHAgcmVxdWVzdHMsIGFuZCBydW5uaW5nIHRoZSBjb21tYW5kLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSIHwgc3RyaW5nIHwgdm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGNvbW1hbmQncyByZXN1bHQuXG4gICAqXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IENvbW1hbmRcbiAgICogICBwYXJ0aWNpcGFudCBVc2VySW5wdXRcbiAgICogICBwYXJ0aWNpcGFudCBMb2dnaW5nXG4gICAqICAgcGFydGljaXBhbnQgZ2V0UGFja2FnZVZlcnNpb25cbiAgICogICBwYXJ0aWNpcGFudCBwcmludEJhbm5lclxuICAgKiAgIENvbW1hbmQtPj5Vc2VySW5wdXQ6IHBhcnNlQXJncyhpbnB1dHMpXG4gICAqICAgVXNlcklucHV0LS0+PkNvbW1hbmQ6IFJldHVybiBQYXJzZUFyZ3NSZXN1bHRcbiAgICogICBDb21tYW5kLT4+Q29tbWFuZDogUHJvY2VzcyBvcHRpb25zXG4gICAqICAgQ29tbWFuZC0+PkxvZ2dpbmc6IHNldENvbmZpZyhvcHRpb25zKVxuICAgKiAgIGFsdCB2ZXJzaW9uIHJlcXVlc3RlZFxuICAgKiAgICAgQ29tbWFuZC0+PmdldFBhY2thZ2VWZXJzaW9uOiBDYWxsXG4gICAqICAgICBnZXRQYWNrYWdlVmVyc2lvbi0tPj5Db21tYW5kOiBSZXR1cm4gdmVyc2lvblxuICAgKiAgIGVsc2UgaGVscCByZXF1ZXN0ZWRcbiAgICogICAgIENvbW1hbmQtPj5Db21tYW5kOiBoZWxwKGFyZ3MpXG4gICAqICAgZWxzZSBiYW5uZXIgcmVxdWVzdGVkXG4gICAqICAgICBDb21tYW5kLT4+cHJpbnRCYW5uZXI6IENhbGxcbiAgICogICBlbmRcbiAgICogICBDb21tYW5kLT4+Q29tbWFuZDogcnVuKGFyZ3MpXG4gICAqICAgYWx0IGVycm9yIG9jY3Vyc1xuICAgKiAgICAgQ29tbWFuZC0+PkNvbW1hbmQ6IExvZyBlcnJvclxuICAgKiAgIGVuZFxuICAgKiAgIENvbW1hbmQtLT4+Q29tbWFuZDogUmV0dXJuIHJlc3VsdFxuICAgKi9cbiAgYXN5bmMgZXhlY3V0ZSgpOiBQcm9taXNlPFIgfCBzdHJpbmcgfCB2b2lkPiB7XG4gICAgY29uc3QgYXJnczogUGFyc2VBcmdzUmVzdWx0ID0gVXNlcklucHV0LnBhcnNlQXJncyh0aGlzLmlucHV0cyk7XG4gICAgY29uc3QgZW52ID0gTG9nZ2VkRW52aXJvbm1lbnQuYWNjdW11bGF0ZShEZWZhdWx0Q29tbWFuZFZhbHVlcykuYWNjdW11bGF0ZShcbiAgICAgIGFyZ3MudmFsdWVzXG4gICAgKTtcbiAgICBjb25zdCB7IHZlcnNpb24sIGhlbHAsIGJhbm5lciB9ID0gZW52O1xuXG4gICAgaWYgKHZlcnNpb24pIHtcbiAgICAgIHJldHVybiBnZXRQYWNrYWdlVmVyc2lvbigpO1xuICAgIH1cblxuICAgIGlmIChoZWxwKSB7XG4gICAgICByZXR1cm4gdGhpcy5oZWxwKGFyZ3MpO1xuICAgIH1cblxuICAgIGlmIChiYW5uZXIpXG4gICAgICBwcmludEJhbm5lcihcbiAgICAgICAgdGhpcy5sb2cuZm9yKHByaW50QmFubmVyLCB7XG4gICAgICAgICAgdGltZXN0YW1wOiBmYWxzZSxcbiAgICAgICAgICBzdHlsZTogZmFsc2UsXG4gICAgICAgICAgY29udGV4dDogZmFsc2UsXG4gICAgICAgICAgbG9nTGV2ZWw6IGZhbHNlLFxuICAgICAgICB9KVxuICAgICAgKTtcblxuICAgIGxldCByZXN1bHQ7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVzZWxlc3MtY2F0Y2hcbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gYXdhaXQgdGhpcy5ydW4oZW52IGFzIGFueSk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0IGFzIFI7XG4gIH1cbn1cbiIsIi8qIGlzdGFuYnVsIGlnbm9yZSBmaWxlICovXG5pbXBvcnQgaHR0cHMgZnJvbSBcImh0dHBzXCI7XG5pbXBvcnQgeyBMb2dnaW5nIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEEgc2ltcGxlIEhUVFAgY2xpZW50IGZvciBkb3dubG9hZGluZyBmaWxlcy5cbiAqIEBzdW1tYXJ5IFRoaXMgY2xhc3MgcHJvdmlkZXMgZnVuY3Rpb25hbGl0eSB0byBkb3dubG9hZCBmaWxlcyBmcm9tIEhUVFBTIFVSTHMuXG4gKiBJdCB1c2VzIE5vZGUuanMgYnVpbHQtaW4gaHR0cHMgbW9kdWxlIHRvIG1ha2UgcmVxdWVzdHMuXG4gKlxuICogQGNsYXNzIEh0dHBDbGllbnRcbiAqL1xuZXhwb3J0IGNsYXNzIEh0dHBDbGllbnQge1xuICBwcm90ZWN0ZWQgc3RhdGljIGxvZyA9IExvZ2dpbmcuZm9yKEh0dHBDbGllbnQpO1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERvd25sb2FkcyBhIGZpbGUgZnJvbSBhIGdpdmVuIFVSTC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2Qgc2VuZHMgYSBHRVQgcmVxdWVzdCB0byB0aGUgc3BlY2lmaWVkIFVSTCBhbmQgcmV0dXJucyB0aGUgcmVzcG9uc2UgYm9keSBhcyBhIHN0cmluZy5cbiAgICogSXQgaGFuZGxlcyBkaWZmZXJlbnQgc2NlbmFyaW9zIHN1Y2ggYXMgbm9uLTIwMCBzdGF0dXMgY29kZXMgYW5kIG5ldHdvcmsgZXJyb3JzLlxuICAgKlxuICAgKiBAcGFyYW0gdXJsIC0gVGhlIFVSTCBvZiB0aGUgZmlsZSB0byBkb3dubG9hZC5cbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBmaWxlIGNvbnRlbnQgYXMgYSBzdHJpbmcuXG4gICAqXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICAgKiAgIHBhcnRpY2lwYW50IEh0dHBDbGllbnRcbiAgICogICBwYXJ0aWNpcGFudCBIVFRQU1xuICAgKiAgIHBhcnRpY2lwYW50IFNlcnZlclxuICAgKiAgIENsaWVudC0+Pkh0dHBDbGllbnQ6IGRvd25sb2FkRmlsZSh1cmwpXG4gICAqICAgSHR0cENsaWVudC0+PkhUVFBTOiBnZXQodXJsKVxuICAgKiAgIEhUVFBTLT4+U2VydmVyOiBHRVQgcmVxdWVzdFxuICAgKiAgIFNlcnZlci0tPj5IVFRQUzogUmVzcG9uc2VcbiAgICogICBIVFRQUy0tPj5IdHRwQ2xpZW50OiBSZXNwb25zZSBvYmplY3RcbiAgICogICBhbHQgU3RhdHVzIGNvZGUgaXMgMjAwXG4gICAqICAgICBsb29wIEZvciBlYWNoIGRhdGEgY2h1bmtcbiAgICogICAgICAgSFRUUFMtPj5IdHRwQ2xpZW50OiAnZGF0YScgZXZlbnRcbiAgICogICAgICAgSHR0cENsaWVudC0+Pkh0dHBDbGllbnQ6IEFjY3VtdWxhdGUgZGF0YVxuICAgKiAgICAgZW5kXG4gICAqICAgICBIVFRQUy0+Pkh0dHBDbGllbnQ6ICdlbmQnIGV2ZW50XG4gICAqICAgICBIdHRwQ2xpZW50LS0+PkNsaWVudDogUmVzb2x2ZSB3aXRoIGRhdGFcbiAgICogICBlbHNlIFN0YXR1cyBjb2RlIGlzIG5vdCAyMDBcbiAgICogICAgIEh0dHBDbGllbnQtLT4+Q2xpZW50OiBSZWplY3Qgd2l0aCBlcnJvclxuICAgKiAgIGVuZFxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGRvd25sb2FkRmlsZSh1cmw6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPHN0cmluZz4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgZnVuY3Rpb24gcmVxdWVzdCh1cmw6IHN0cmluZykge1xuICAgICAgICB1cmwgPSBlbmNvZGVVUkkodXJsKTtcbiAgICAgICAgaHR0cHMuZ2V0KHVybCwgKHJlcykgPT4ge1xuICAgICAgICAgIGlmIChyZXMuc3RhdHVzQ29kZSA9PT0gMzAxIHx8IHJlcy5zdGF0dXNDb2RlID09PSAzMDcpXG4gICAgICAgICAgICByZXR1cm4gcmVxdWVzdChyZXMuaGVhZGVycy5sb2NhdGlvbiBhcyBzdHJpbmcpO1xuXG4gICAgICAgICAgaWYgKHJlcy5zdGF0dXNDb2RlICE9PSAyMDApIHtcbiAgICAgICAgICAgIEh0dHBDbGllbnQubG9nLmVycm9yKFxuICAgICAgICAgICAgICBgRmFpbGVkIHRvIGZldGNoICR7dXJsfSAoc3RhdHVzOiAke3Jlcy5zdGF0dXNDb2RlfSlgXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXcgRXJyb3IoYEZhaWxlZCB0byBmZXRjaCAke3VybH1gKSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGxldCBkYXRhID0gXCJcIjtcbiAgICAgICAgICByZXMub24oXCJkYXRhXCIsIChjaHVuaykgPT4ge1xuICAgICAgICAgICAgZGF0YSArPSBjaHVuaztcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXMub24oXCJlcnJvclwiLCAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICByZXMub24oXCJlbmRcIiwgKCkgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZShkYXRhKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXF1ZXN0KHVybCk7XG4gICAgfSk7XG4gIH1cbn1cbiIsImltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBta2Rpciwgd3JpdGVGaWxlIH0gZnJvbSBcImZzL3Byb21pc2VzXCI7XG5pbXBvcnQgeyBTdG9wV2F0Y2ggfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcblxuZXhwb3J0IHR5cGUgRXhlY3V0aW9uTW9kZSA9IFwic2VxdWVudGlhbFwiIHwgXCJjb25jdXJyZW50XCIgfCBcImJ1cnN0XCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGhhc2VCdXJzdENvbmZpZyB7XG4gIHNpemU6IG51bWJlcjtcbiAgaW50ZXJ2YWxNcz86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQaGFzZVdhcm11cENvbmZpZzxUQ29udGV4dCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+PiB7XG4gIGl0ZXJhdGlvbnM6IG51bWJlcjtcbiAgaGFuZGxlcj86IFBlcmZvcm1hbmNlSGFuZGxlcjxUQ29udGV4dD47XG4gIGRlbGF5QmV0d2Vlbkl0ZXJhdGlvbnNNcz86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQaGFzZUNvbmZpZzxUQ29udGV4dCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+PiB7XG4gIGl0ZXJhdGlvbnM6IG51bWJlcjtcbiAgbW9kZTogRXhlY3V0aW9uTW9kZTtcbiAgY29uY3VycmVuY3k/OiBudW1iZXI7XG4gIGRlbGF5QmV0d2Vlbkl0ZXJhdGlvbnNNcz86IG51bWJlcjtcbiAgYnVyc3Q/OiBQaGFzZUJ1cnN0Q29uZmlnO1xuICBsb2FkU3RhcnQ/OiBudW1iZXI7XG4gIGxvYWRTdGVwPzogbnVtYmVyO1xuICBsb2FkTXVsdGlwbGllcj86IG51bWJlcjtcbiAgY29udGV4dD86IFBhcnRpYWw8VENvbnRleHQ+O1xuICBtZXRhZGF0YT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICB3YXJtdXA/OiBQaGFzZVdhcm11cENvbmZpZzxUQ29udGV4dD47XG4gIHBhdXNlQWZ0ZXJNcz86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQaGFzZTxUQ29udGV4dCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+PiB7XG4gIG5hbWU6IHN0cmluZztcbiAgY29uZmlnOiBQaGFzZUNvbmZpZzxUQ29udGV4dD47XG4gIGdlbmVyYXRvcj86IFBoYXNlR2VuZXJhdG9yPFRDb250ZXh0PjtcbiAgc3ViUGhhc2VzPzogUGhhc2U8VENvbnRleHQ+W107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGhhc2VHZW5lcmF0b3JQaGFzZTxUQ29udGV4dD4ge1xuICBuYW1lPzogc3RyaW5nO1xuICBjb25maWc6IFBoYXNlQ29uZmlnPFBhcnRpYWw8VENvbnRleHQ+Pjtcbn1cblxuZXhwb3J0IHR5cGUgUGhhc2VHZW5lcmF0b3JSZXN1bHQ8VENvbnRleHQ+ID1cbiAgfCBQaGFzZUNvbmZpZzxUQ29udGV4dD5cbiAgfCBQaGFzZUdlbmVyYXRvclBoYXNlPFRDb250ZXh0PjtcblxuZXhwb3J0IHR5cGUgUGhhc2VHZW5lcmF0b3I8VENvbnRleHQ+ID0gKFxuICBwYXlsb2FkOiBQaGFzZUdlbmVyYXRvclBheWxvYWQ8VENvbnRleHQ+XG4pID0+XG4gIHwgUHJvbWlzZTxQaGFzZUdlbmVyYXRvclJlc3VsdDxUQ29udGV4dD4gfCB1bmRlZmluZWQ+XG4gIHwgUGhhc2VHZW5lcmF0b3JSZXN1bHQ8VENvbnRleHQ+XG4gIHwgdW5kZWZpbmVkO1xuXG5leHBvcnQgaW50ZXJmYWNlIFBoYXNlUmVzdWx0PFRDb250ZXh0ID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4+IHtcbiAgcGhhc2U6IFBoYXNlPFRDb250ZXh0PjtcbiAgY29uZmlnOiBQaGFzZUNvbmZpZzxUQ29udGV4dD47XG4gIGl0ZXJhdGlvbk1ldHJpY3M6IEl0ZXJhdGlvbk1ldHJpY1tdO1xuICBhZ2dyZWdhdGVkOiBBZ2dyZWdhdGVkTWV0cmljcztcbiAgY29udGV4dDogVENvbnRleHQ7XG4gIHNlZ21lbnRDb3VudDogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBoYXNlR2VuZXJhdG9yTWV0YWRhdGE8VENvbnRleHQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4ge1xuICBwaGFzZU51bWJlcjogbnVtYmVyO1xuICBwaGFzZU5hbWU6IHN0cmluZztcbiAgaXRlcmF0aW9uQ291bnQ6IG51bWJlcjtcbiAgYnVyc3RTZWdtZW50czogbnVtYmVyO1xuICBzZWdtZW50Q291bnQ6IG51bWJlcjtcbiAgbW9kZTogRXhlY3V0aW9uTW9kZTtcbiAgaGlzdG9yeTogUGhhc2VSZXN1bHQ8VENvbnRleHQ+W107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGhhc2VHZW5lcmF0b3JQYXlsb2FkPFRDb250ZXh0ID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4+IHtcbiAgcmVzdWx0OiBQaGFzZVJlc3VsdDxUQ29udGV4dD47XG4gIGhpc3Rvcnk6IFBoYXNlUmVzdWx0PFRDb250ZXh0PltdO1xuICBtZXRhZGF0YTogUGhhc2VHZW5lcmF0b3JNZXRhZGF0YTxUQ29udGV4dD47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWdncmVnYXRlZE1ldHJpY3Mge1xuICB0b3RhbER1cmF0aW9uTXM6IG51bWJlcjtcbiAgbWluTXM6IG51bWJlcjtcbiAgbWF4TXM6IG51bWJlcjtcbiAgYXZlcmFnZU1zOiBudW1iZXI7XG4gIHN1Y2Nlc3NDb3VudDogbnVtYmVyO1xuICBmYWlsdXJlQ291bnQ6IG51bWJlcjtcbiAgbG9hZFN0YXJ0OiBudW1iZXI7XG4gIGxvYWRFbmQ6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJdGVyYXRpb25NZXRyaWMge1xuICBpdGVyYXRpb246IG51bWJlcjtcbiAgZHVyYXRpb25NczogbnVtYmVyO1xuICBzdWNjZXNzOiBib29sZWFuO1xuICBtZXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGxvYWRGYWN0b3I6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBIYW5kbGVyUGF5bG9hZDxUQ29udGV4dCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+PiB7XG4gIGl0ZXJhdGlvbjogbnVtYmVyO1xuICBjb25maWc6IFBoYXNlQ29uZmlnPFRDb250ZXh0PjtcbiAgbG9hZEZhY3RvcjogbnVtYmVyO1xuICBjb250ZXh0OiBUQ29udGV4dDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBIYW5kbGVyUmVzdWx0IHtcbiAgc3VjY2Vzcz86IGJvb2xlYW47XG4gIG1ldGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuZXhwb3J0IHR5cGUgUGVyZm9ybWFuY2VIYW5kbGVyPFRDb250ZXh0ID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4+ID0gKFxuICBwYXlsb2FkOiBIYW5kbGVyUGF5bG9hZDxUQ29udGV4dD5cbikgPT4gUHJvbWlzZTxIYW5kbGVyUmVzdWx0PiB8IEhhbmRsZXJSZXN1bHQ7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2FudmFzUmVuZGVyT3B0aW9ucyB7XG4gIHdpZHRoPzogbnVtYmVyO1xuICBoZWlnaHQ/OiBudW1iZXI7XG4gIHBhZGRpbmc/OiBudW1iZXI7XG4gIGJhY2tncm91bmRDb2xvcj86IHN0cmluZztcbiAgaGVhZGVyRm9udD86IHN0cmluZztcbiAgcm93Rm9udD86IHN0cmluZztcbiAgaGVhZGVyQ29sb3I/OiBzdHJpbmc7XG4gIHJvd0NvbG9yPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBlcmZvcm1hbmNlU2NlbmFyaW88VENvbnRleHQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4ge1xuICBuYW1lOiBzdHJpbmc7XG4gIGhhbmRsZXI6IFBlcmZvcm1hbmNlSGFuZGxlcjxUQ29udGV4dD47XG4gIHBoYXNlczogUGhhc2U8VENvbnRleHQ+W107XG4gIGJhc2VDb250ZXh0PzogVENvbnRleHQ7XG4gIGZhaWxPbkVycm9yPzogYm9vbGVhbjtcbiAgaW5pdGlhbGl6ZT86ICgpID0+IFByb21pc2U8dm9pZD4gfCB2b2lkO1xuICBjYW52YXNPcHRpb25zPzogQ2FudmFzUmVuZGVyT3B0aW9ucztcbiAgY2FudmFzT3V0cHV0UGF0aD86IHN0cmluZztcbiAgZW5hYmxlQ2FudmFzPzogYm9vbGVhbjtcbn1cblxuaW50ZXJmYWNlIFBoYXNlUXVldWVJdGVtPFRDb250ZXh0PiB7XG4gIHBoYXNlOiBQaGFzZTxUQ29udGV4dD47XG4gIHBoYXNlTnVtYmVyOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCBkZWZhdWx0Q2FudmFzT3B0aW9uczogUmVxdWlyZWQ8Q2FudmFzUmVuZGVyT3B0aW9ucz4gPSB7XG4gIHdpZHRoOiAxMjAwLFxuICBoZWlnaHQ6IDI2MCxcbiAgcGFkZGluZzogMzIsXG4gIGJhY2tncm91bmRDb2xvcjogXCIjMGYxNzJhXCIsXG4gIGhlYWRlckZvbnQ6IFwiYm9sZCAxOHB4ICdTZWdvZSBVSScsIHNhbnMtc2VyaWZcIixcbiAgcm93Rm9udDogXCIxNHB4ICdTZWdvZSBVSScsIHNhbnMtc2VyaWZcIixcbiAgaGVhZGVyQ29sb3I6IFwiI2Y4ZmFmY1wiLFxuICByb3dDb2xvcjogXCIjY2JkNWY1XCIsXG59O1xuXG5jb25zdCBkZWxheSA9IChtczogbnVtYmVyKSA9PiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCBtcykpO1xuY29uc3QgcGVyZkRlYnVnRW5hYmxlZCA9IHByb2Nlc3MuZW52LlBFUkZfVkVSQk9TRSA9PT0gXCJ0cnVlXCI7XG5jb25zdCBkZWJ1Z0xvZyA9ICguLi5hcmdzOiB1bmtub3duW10pID0+IHtcbiAgaWYgKHBlcmZEZWJ1Z0VuYWJsZWQpIHtcbiAgICBjb25zb2xlLmRlYnVnKC4uLmFyZ3MpO1xuICB9XG59O1xuXG5jb25zdCBmb3JtYXRUYWJsZSA9IChcbiAgdGl0bGU6IHN0cmluZyxcbiAgaGVhZGVyczogc3RyaW5nW10sXG4gIHJvd3M6IHN0cmluZ1tdW11cbik6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGNvbHVtbldpZHRocyA9IGhlYWRlcnMubWFwKChoZWFkZXIsIGluZGV4KSA9PlxuICAgIE1hdGgubWF4KGhlYWRlci5sZW5ndGgsIC4uLnJvd3MubWFwKChyb3cpID0+IHJvd1tpbmRleF0/Lmxlbmd0aCA/PyAwKSlcbiAgKTtcbiAgY29uc3QgZm9ybWF0Um93ID0gKHZhbHVlczogc3RyaW5nW10pID0+XG4gICAgXCJ8IFwiICtcbiAgICB2YWx1ZXNcbiAgICAgIC5tYXAoKHZhbHVlLCBpbmRleCkgPT4gdmFsdWUucGFkRW5kKGNvbHVtbldpZHRoc1tpbmRleF0pKVxuICAgICAgLmpvaW4oXCIgfCBcIikgK1xuICAgIFwiIHxcIjtcbiAgY29uc3QgaGVhZGVyTGluZSA9IGZvcm1hdFJvdyhoZWFkZXJzKTtcbiAgY29uc3QgZGl2aWRlciA9XG4gICAgXCJ8IFwiICsgY29sdW1uV2lkdGhzLm1hcCgod2lkdGgpID0+IFwiLVwiLnJlcGVhdCh3aWR0aCkpLmpvaW4oXCIgfCBcIikgKyBcIiB8XCI7XG4gIGNvbnN0IGJvZHkgPSByb3dzLm1hcChmb3JtYXRSb3cpLmpvaW4oXCJcXG5cIik7XG4gIHJldHVybiBgJHt0aXRsZX1cXG4ke2hlYWRlckxpbmV9XFxuJHtkaXZpZGVyfVxcbiR7Ym9keX1gO1xufTtcblxuY29uc3QgZW5zdXJlRGlyZWN0b3J5ID0gYXN5bmMgKHRhcmdldFBhdGg6IHN0cmluZykgPT4ge1xuICBhd2FpdCBta2RpcihwYXRoLmRpcm5hbWUodGFyZ2V0UGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xufTtcblxuY29uc3QgcmVuZGVyTWV0cmljc1RhYmxlVG9DYW52YXMgPSBhc3luYyAoXG4gIGhlYWRlcnM6IHN0cmluZ1tdLFxuICByb3dzOiBzdHJpbmdbXVtdLFxuICBvcHRpb25zOiBDYW52YXNSZW5kZXJPcHRpb25zLFxuICBvdXRwdXRQYXRoOiBzdHJpbmdcbikgPT4ge1xuICBjb25zdCBjb25maWcgPSB7IC4uLmRlZmF1bHRDYW52YXNPcHRpb25zLCAuLi5vcHRpb25zIH07XG4gIC8vIEB0cy1leHBlY3QtZXJyb3IgY2FudmFzIGltcG9ydFxuICBsZXQgY3JlYXRlQ2FudmFzOiAodHlwZW9mIGltcG9ydChcImNhbnZhc1wiKSlbXCJjcmVhdGVDYW52YXNcIl07XG4gIHRyeSB7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciBiZWNhdXNlIHdlIGFsbG93IG9wdGlvbmFsIGRlcGVuZGVuY3lcbiAgICBjb25zdCBjYW52YXNNb2R1bGUgPSBhd2FpdCBpbXBvcnQoXCJjYW52YXNcIik7XG4gICAgY3JlYXRlQ2FudmFzID0gY2FudmFzTW9kdWxlLmNyZWF0ZUNhbnZhcztcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zb2xlLndhcm4oXG4gICAgICBcIltQZXJmUnVubmVyXSBDYW52YXMgbW9kdWxlIG5vdCBhdmFpbGFibGUsIHNraXBwaW5nIGNoYXJ0LlwiLFxuICAgICAgZXJyb3JcbiAgICApO1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBjYW52YXMgPSBjcmVhdGVDYW52YXMoY29uZmlnLndpZHRoLCBjb25maWcuaGVpZ2h0KTtcbiAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcblxuICBjdHguZmlsbFN0eWxlID0gY29uZmlnLmJhY2tncm91bmRDb2xvcjtcbiAgY3R4LmZpbGxSZWN0KDAsIDAsIGNvbmZpZy53aWR0aCwgY29uZmlnLmhlaWdodCk7XG5cbiAgY3R4LmZvbnQgPSBjb25maWcuaGVhZGVyRm9udDtcbiAgY3R4LmZpbGxTdHlsZSA9IGNvbmZpZy5oZWFkZXJDb2xvcjtcbiAgY29uc3QgY29sdW1uV2lkdGggPSAoY29uZmlnLndpZHRoIC0gY29uZmlnLnBhZGRpbmcgKiAyKSAvIGhlYWRlcnMubGVuZ3RoO1xuICBjb25zdCBoZWFkZXJZID0gY29uZmlnLnBhZGRpbmcgKyAyNDtcblxuICBoZWFkZXJzLmZvckVhY2goKGhlYWRlciwgaW5kZXgpID0+IHtcbiAgICBjdHguZmlsbFRleHQoaGVhZGVyLCBjb25maWcucGFkZGluZyArIGNvbHVtbldpZHRoICogaW5kZXgsIGhlYWRlclkpO1xuICB9KTtcblxuICBjdHguZm9udCA9IGNvbmZpZy5yb3dGb250O1xuICBjdHguZmlsbFN0eWxlID0gY29uZmlnLnJvd0NvbG9yO1xuICBjb25zdCByb3dIZWlnaHQgPSAyNDtcbiAgcm93cy5mb3JFYWNoKChyb3csIHJvd0luZGV4KSA9PiB7XG4gICAgY29uc3QgeSA9IGhlYWRlclkgKyAxMiArIHJvd0hlaWdodCAqIChyb3dJbmRleCArIDEpO1xuICAgIHJvdy5mb3JFYWNoKChjZWxsLCBjZWxsSW5kZXgpID0+IHtcbiAgICAgIGN0eC5maWxsVGV4dChjZWxsLCBjb25maWcucGFkZGluZyArIGNvbHVtbldpZHRoICogY2VsbEluZGV4LCB5KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgYXdhaXQgZW5zdXJlRGlyZWN0b3J5KG91dHB1dFBhdGgpO1xuICBhd2FpdCB3cml0ZUZpbGUob3V0cHV0UGF0aCwgY2FudmFzLnRvQnVmZmVyKFwiaW1hZ2UvcG5nXCIpKTtcbiAgY29uc29sZS5sb2coYFN0b3JlZCBwZXJmb3JtYW5jZSBjaGFydCBhdCAke291dHB1dFBhdGh9YCk7XG59O1xuXG5leHBvcnQgY2xhc3MgUGVyZm9ybWFuY2VSdW5uZXI8VENvbnRleHQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4ge1xuICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgcmVhZG9ubHkgc2NlbmFyaW86IFBlcmZvcm1hbmNlU2NlbmFyaW88VENvbnRleHQ+KSB7fVxuXG4gIHB1YmxpYyBhc3luYyBydW4oKTogUHJvbWlzZTxQaGFzZVJlc3VsdDxUQ29udGV4dD5bXT4ge1xuICAgIGlmICh0aGlzLnNjZW5hcmlvLmluaXRpYWxpemUpIHtcbiAgICAgIGF3YWl0IHRoaXMuc2NlbmFyaW8uaW5pdGlhbGl6ZSgpO1xuICAgIH1cblxuICAgIGxldCBwaGFzZUNvdW50ZXIgPSAwO1xuICAgIGNvbnN0IHF1ZXVlOiBQaGFzZVF1ZXVlSXRlbTxUQ29udGV4dD5bXSA9IHRoaXMuc2NlbmFyaW8ucGhhc2VzLm1hcChcbiAgICAgIChwaGFzZSkgPT4gKHsgcGhhc2UsIHBoYXNlTnVtYmVyOiArK3BoYXNlQ291bnRlciB9KVxuICAgICk7XG4gICAgY29uc3QgcmVzdWx0czogUGhhc2VSZXN1bHQ8VENvbnRleHQ+W10gPSBbXTtcblxuICAgIHdoaWxlIChxdWV1ZS5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IGl0ZW0gPSBxdWV1ZS5zaGlmdCgpITtcbiAgICAgIGNvbnN0IHBoYXNlID0gaXRlbS5waGFzZTtcbiAgICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLm1lcmdlQ29udGV4dChwaGFzZSk7XG4gICAgICBjb25zb2xlLmluZm8oXG4gICAgICAgIGBbUGVyZlJ1bm5lcl0gU3RhcnRpbmcgcGhhc2UgIyR7aXRlbS5waGFzZU51bWJlcn0gXCIke3BoYXNlLm5hbWV9XCJgLFxuICAgICAgICB7XG4gICAgICAgICAgaXRlcmF0aW9uczogcGhhc2UuY29uZmlnLml0ZXJhdGlvbnMsXG4gICAgICAgICAgbW9kZTogcGhhc2UuY29uZmlnLm1vZGUsXG4gICAgICAgICAgY29uY3VycmVuY3k6IHBoYXNlLmNvbmZpZy5jb25jdXJyZW5jeSxcbiAgICAgICAgICBidXJzdDogcGhhc2UuY29uZmlnLmJ1cnN0LFxuICAgICAgICB9XG4gICAgICApO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5ydW5QaGFzZShwaGFzZSwgY29udGV4dCk7XG4gICAgICBjb25zb2xlLmluZm8oXG4gICAgICAgIGBbUGVyZlJ1bm5lcl0gQ29tcGxldGVkIHBoYXNlICMke2l0ZW0ucGhhc2VOdW1iZXJ9IFwiJHtwaGFzZS5uYW1lfVwiYCxcbiAgICAgICAge1xuICAgICAgICAgIHRvdGFsOiByZXN1bHQuYWdncmVnYXRlZC50b3RhbER1cmF0aW9uTXMudG9GaXhlZCgyKSxcbiAgICAgICAgICBhdmc6IHJlc3VsdC5hZ2dyZWdhdGVkLmF2ZXJhZ2VNcy50b0ZpeGVkKDIpLFxuICAgICAgICAgIGZhaWx1cmVDb3VudDogcmVzdWx0LmFnZ3JlZ2F0ZWQuZmFpbHVyZUNvdW50LFxuICAgICAgICB9XG4gICAgICApO1xuICAgICAgcmVzdWx0cy5wdXNoKHJlc3VsdCk7XG5cbiAgICAgIGlmIChwaGFzZS5nZW5lcmF0b3IpIHtcbiAgICAgICAgY29uc3QgaGlzdG9yeVNuYXBzaG90ID0gWy4uLnJlc3VsdHNdO1xuICAgICAgICBjb25zdCBtZXRhZGF0YTogUGhhc2VHZW5lcmF0b3JNZXRhZGF0YTxUQ29udGV4dD4gPSB7XG4gICAgICAgICAgcGhhc2VOdW1iZXI6IGl0ZW0ucGhhc2VOdW1iZXIsXG4gICAgICAgICAgcGhhc2VOYW1lOiBwaGFzZS5uYW1lLFxuICAgICAgICAgIGl0ZXJhdGlvbkNvdW50OiBwaGFzZS5jb25maWcuaXRlcmF0aW9ucyxcbiAgICAgICAgICBidXJzdFNlZ21lbnRzOiByZXN1bHQuc2VnbWVudENvdW50LFxuICAgICAgICAgIHNlZ21lbnRDb3VudDogcmVzdWx0LnNlZ21lbnRDb3VudCxcbiAgICAgICAgICBtb2RlOiBwaGFzZS5jb25maWcubW9kZSxcbiAgICAgICAgICBoaXN0b3J5OiBoaXN0b3J5U25hcHNob3QsXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGdlbmVyYXRvclJlc3VsdCA9IGF3YWl0IHBoYXNlLmdlbmVyYXRvcih7XG4gICAgICAgICAgcmVzdWx0LFxuICAgICAgICAgIGhpc3Rvcnk6IGhpc3RvcnlTbmFwc2hvdCxcbiAgICAgICAgICBtZXRhZGF0YSxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChnZW5lcmF0b3JSZXN1bHQpIHtcbiAgICAgICAgICBjb25zdCBuZXh0UGhhc2U6IFBoYXNlPFRDb250ZXh0PiA9IChcbiAgICAgICAgICAgIFwiY29uZmlnXCIgaW4gZ2VuZXJhdG9yUmVzdWx0XG4gICAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgICAgbmFtZTogZ2VuZXJhdG9yUmVzdWx0Lm5hbWUgPz8gYCR7cGhhc2UubmFtZX0g4oaSIGdlbmAsXG4gICAgICAgICAgICAgICAgICBjb25maWc6IGdlbmVyYXRvclJlc3VsdC5jb25maWcsXG4gICAgICAgICAgICAgICAgICBnZW5lcmF0b3I6IHBoYXNlLmdlbmVyYXRvcixcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgICAgbmFtZTogYCR7cGhhc2UubmFtZX0g4oaSIGdlbmAsXG4gICAgICAgICAgICAgICAgICBjb25maWc6IGdlbmVyYXRvclJlc3VsdCxcbiAgICAgICAgICAgICAgICAgIGdlbmVyYXRvcjogcGhhc2UuZ2VuZXJhdG9yLFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICApIGFzIGFueTtcbiAgICAgICAgICBxdWV1ZS5wdXNoKHtcbiAgICAgICAgICAgIHBoYXNlOiBuZXh0UGhhc2UsXG4gICAgICAgICAgICBwaGFzZU51bWJlcjogKytwaGFzZUNvdW50ZXIsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLmxvZ1N1bW1hcnkocmVzdWx0cyk7XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgcnVuUGhhc2UoXG4gICAgcGhhc2U6IFBoYXNlPFRDb250ZXh0PixcbiAgICBjb250ZXh0OiBUQ29udGV4dFxuICApOiBQcm9taXNlPFBoYXNlUmVzdWx0PFRDb250ZXh0Pj4ge1xuICAgIGF3YWl0IHRoaXMucnVuV2FybXVwKHBoYXNlLCBjb250ZXh0KTtcbiAgICBjb25zdCBzZWdtZW50cyA9IHRoaXMuYnVpbGRTZWdtZW50SW5kaWNlcyhcbiAgICAgIHBoYXNlLmNvbmZpZy5pdGVyYXRpb25zLFxuICAgICAgcGhhc2UuY29uZmlnLmJ1cnN0XG4gICAgKTtcbiAgICBjb25zdCBjb2xsZWN0ZWQ6IEl0ZXJhdGlvbk1ldHJpY1tdID0gW107XG5cbiAgICBmb3IgKFxuICAgICAgbGV0IHNlZ21lbnRJbmRleCA9IDA7XG4gICAgICBzZWdtZW50SW5kZXggPCBzZWdtZW50cy5sZW5ndGg7XG4gICAgICBzZWdtZW50SW5kZXggKz0gMVxuICAgICkge1xuICAgICAgY29uc3QgaW5kaWNlcyA9IHNlZ21lbnRzW3NlZ21lbnRJbmRleF07XG4gICAgICBpZiAoIWluZGljZXMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBkZWJ1Z0xvZyhcbiAgICAgICAgYFtQZXJmUnVubmVyXSBQaGFzZSBcIiR7cGhhc2UubmFtZX1cIiBleGVjdXRpbmcgc2VnbWVudCAke3NlZ21lbnRJbmRleCArIDF9LyR7XG4gICAgICAgICAgc2VnbWVudHMubGVuZ3RoXG4gICAgICAgIH0gKGl0ZXJhdGlvbnMgJHtpbmRpY2VzWzBdfS0ke2luZGljZXNbaW5kaWNlcy5sZW5ndGggLSAxXX0pYFxuICAgICAgKTtcblxuICAgICAgY29uc3QgbWV0cmljcyA9IGF3YWl0IHRoaXMuZXhlY3V0ZVNlZ21lbnQoXG4gICAgICAgIHRoaXMuc2NlbmFyaW8uaGFuZGxlcixcbiAgICAgICAgcGhhc2UuY29uZmlnLFxuICAgICAgICBjb250ZXh0LFxuICAgICAgICBpbmRpY2VzXG4gICAgICApO1xuICAgICAgY29sbGVjdGVkLnB1c2goLi4ubWV0cmljcyk7XG5cbiAgICAgIGNvbnN0IGJ1cnN0SW50ZXJ2YWwgPSBwaGFzZS5jb25maWcuYnVyc3Q/LmludGVydmFsTXM7XG4gICAgICBpZiAoYnVyc3RJbnRlcnZhbCAmJiBzZWdtZW50SW5kZXggPCBzZWdtZW50cy5sZW5ndGggLSAxKSB7XG4gICAgICAgIGF3YWl0IGRlbGF5KGJ1cnN0SW50ZXJ2YWwpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHNvcnRlZCA9IFsuLi5jb2xsZWN0ZWRdLnNvcnQoKGEsIGIpID0+IGEuaXRlcmF0aW9uIC0gYi5pdGVyYXRpb24pO1xuICAgIGNvbnN0IGFnZ3JlZ2F0ZWQgPSB0aGlzLmFnZ3JlZ2F0ZU1ldHJpY3Moc29ydGVkKTtcblxuICAgIGlmIChwaGFzZS5jb25maWcucGF1c2VBZnRlck1zKSB7XG4gICAgICBhd2FpdCBkZWxheShwaGFzZS5jb25maWcucGF1c2VBZnRlck1zKTtcbiAgICB9XG5cbiAgICBpZiAoYWdncmVnYXRlZC5mYWlsdXJlQ291bnQgPiAwICYmIHRoaXMuc2NlbmFyaW8uZmFpbE9uRXJyb3IgIT09IGZhbHNlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBQaGFzZSAke3BoYXNlLm5hbWV9IHJlY29yZGVkICR7YWdncmVnYXRlZC5mYWlsdXJlQ291bnR9IGZhaWx1cmVzYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcGhhc2UsXG4gICAgICBjb25maWc6IHBoYXNlLmNvbmZpZyxcbiAgICAgIGl0ZXJhdGlvbk1ldHJpY3M6IHNvcnRlZCxcbiAgICAgIGFnZ3JlZ2F0ZWQsXG4gICAgICBjb250ZXh0LFxuICAgICAgc2VnbWVudENvdW50OiBzZWdtZW50cy5sZW5ndGgsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBydW5XYXJtdXAoXG4gICAgcGhhc2U6IFBoYXNlPFRDb250ZXh0PixcbiAgICBjb250ZXh0OiBUQ29udGV4dFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB3YXJtdXAgPSBwaGFzZS5jb25maWcud2FybXVwO1xuICAgIGlmICghd2FybXVwPy5pdGVyYXRpb25zKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgaGFuZGxlciA9IHdhcm11cC5oYW5kbGVyID8/IHRoaXMuc2NlbmFyaW8uaGFuZGxlcjtcbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgd2FybXVwLml0ZXJhdGlvbnM7IGluZGV4ICs9IDEpIHtcbiAgICAgIGF3YWl0IGhhbmRsZXIoe1xuICAgICAgICBpdGVyYXRpb246IGluZGV4LFxuICAgICAgICBjb25maWc6IHBoYXNlLmNvbmZpZyxcbiAgICAgICAgbG9hZEZhY3RvcjogdGhpcy5jb21wdXRlTG9hZEZhY3RvcihwaGFzZS5jb25maWcsIGluZGV4KSxcbiAgICAgICAgY29udGV4dCxcbiAgICAgIH0pO1xuICAgICAgaWYgKHdhcm11cC5kZWxheUJldHdlZW5JdGVyYXRpb25zTXMgJiYgaW5kZXggPCB3YXJtdXAuaXRlcmF0aW9ucyAtIDEpIHtcbiAgICAgICAgYXdhaXQgZGVsYXkod2FybXVwLmRlbGF5QmV0d2Vlbkl0ZXJhdGlvbnNNcyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGNvbXB1dGVMb2FkRmFjdG9yKFxuICAgIGNvbmZpZzogUGhhc2VDb25maWc8VENvbnRleHQ+LFxuICAgIGl0ZXJhdGlvbjogbnVtYmVyXG4gICk6IG51bWJlciB7XG4gICAgY29uc3QgYmFzZSA9IGNvbmZpZy5sb2FkU3RhcnQgPz8gMTtcbiAgICBjb25zdCBzdGVwID0gY29uZmlnLmxvYWRTdGVwID8/IDA7XG4gICAgY29uc3QgbXVsdGlwbGllciA9IGNvbmZpZy5sb2FkTXVsdGlwbGllciA/PyAxO1xuICAgIHJldHVybiAoYmFzZSArIHN0ZXAgKiBpdGVyYXRpb24pICogbXVsdGlwbGllcjtcbiAgfVxuXG4gIHByb3RlY3RlZCBidWlsZFNlZ21lbnRJbmRpY2VzKFxuICAgIGl0ZXJhdGlvbnM6IG51bWJlcixcbiAgICBidXJzdD86IFBoYXNlQnVyc3RDb25maWdcbiAgKTogbnVtYmVyW11bXSB7XG4gICAgY29uc3QgdG90YWwgPSBNYXRoLm1heCgwLCBpdGVyYXRpb25zKTtcbiAgICBpZiAodG90YWwgPT09IDApIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG5cbiAgICBjb25zdCBjaHVuayA9XG4gICAgICBidXJzdD8uc2l6ZSAmJiBidXJzdC5zaXplID4gMCA/IE1hdGgubWluKGJ1cnN0LnNpemUsIHRvdGFsKSA6IHRvdGFsO1xuICAgIGNvbnN0IHNlZ21lbnRzOiBudW1iZXJbXVtdID0gW107XG5cbiAgICBmb3IgKGxldCBjdXJzb3IgPSAwOyBjdXJzb3IgPCB0b3RhbDsgY3Vyc29yICs9IGNodW5rKSB7XG4gICAgICBjb25zdCBlbmQgPSBNYXRoLm1pbih0b3RhbCwgY3Vyc29yICsgY2h1bmspO1xuICAgICAgc2VnbWVudHMucHVzaChcbiAgICAgICAgQXJyYXkuZnJvbSh7IGxlbmd0aDogZW5kIC0gY3Vyc29yIH0sIChfLCBpZHgpID0+IGN1cnNvciArIGlkeClcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlZ21lbnRzO1xuICB9XG5cbiAgcHJvdGVjdGVkIG1lcmdlQ29udGV4dChwaGFzZTogUGhhc2U8VENvbnRleHQ+KTogVENvbnRleHQge1xuICAgIGNvbnN0IGJhc2VDb250ZXh0ID0gdGhpcy5zY2VuYXJpby5iYXNlQ29udGV4dCA/PyAoe30gYXMgVENvbnRleHQpO1xuICAgIGNvbnN0IHBoYXNlQ29udGV4dCA9IHBoYXNlLmNvbmZpZy5jb250ZXh0ID8/ICh7fSBhcyBUQ29udGV4dCk7XG4gICAgcmV0dXJuIHRoaXMubWVyZ2VDb250ZXh0cyhiYXNlQ29udGV4dCwgcGhhc2VDb250ZXh0KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBtZXJnZUNvbnRleHRzKGE6IFRDb250ZXh0LCBiOiBQYXJ0aWFsPFRDb250ZXh0Pik6IFRDb250ZXh0IHtcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgYSwgYik7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgZXhlY3V0ZVNlZ21lbnQoXG4gICAgaGFuZGxlcjogUGVyZm9ybWFuY2VIYW5kbGVyPFRDb250ZXh0PixcbiAgICBjb25maWc6IFBoYXNlQ29uZmlnPFRDb250ZXh0PixcbiAgICBjb250ZXh0OiBUQ29udGV4dCxcbiAgICBpbmRpY2VzOiBudW1iZXJbXVxuICApOiBQcm9taXNlPEl0ZXJhdGlvbk1ldHJpY1tdPiB7XG4gICAgaWYgKCFpbmRpY2VzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGlmIChjb25maWcubW9kZSA9PT0gXCJjb25jdXJyZW50XCIpIHtcbiAgICAgIHJldHVybiB0aGlzLmNvbGxlY3RDb25jdXJyZW50KGhhbmRsZXIsIGNvbmZpZywgY29udGV4dCwgaW5kaWNlcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuY29sbGVjdFNlcXVlbnRpYWwoaGFuZGxlciwgY29uZmlnLCBjb250ZXh0LCBpbmRpY2VzKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBjb2xsZWN0U2VxdWVudGlhbChcbiAgICBoYW5kbGVyOiBQZXJmb3JtYW5jZUhhbmRsZXI8VENvbnRleHQ+LFxuICAgIGNvbmZpZzogUGhhc2VDb25maWc8VENvbnRleHQ+LFxuICAgIGNvbnRleHQ6IFRDb250ZXh0LFxuICAgIGluZGljZXM6IG51bWJlcltdXG4gICk6IFByb21pc2U8SXRlcmF0aW9uTWV0cmljW10+IHtcbiAgICBjb25zdCBtZXRyaWNzOiBJdGVyYXRpb25NZXRyaWNbXSA9IFtdO1xuICAgIGNvbnN0IGRlbGF5QmV0d2VlbiA9IGNvbmZpZy5kZWxheUJldHdlZW5JdGVyYXRpb25zTXM7XG5cbiAgICBmb3IgKGxldCBpZHggPSAwOyBpZHggPCBpbmRpY2VzLmxlbmd0aDsgaWR4ICs9IDEpIHtcbiAgICAgIG1ldHJpY3MucHVzaChcbiAgICAgICAgYXdhaXQgdGhpcy5ydW5JdGVyYXRpb24oaGFuZGxlciwgY29uZmlnLCBjb250ZXh0LCBpbmRpY2VzW2lkeF0pXG4gICAgICApO1xuICAgICAgaWYgKGRlbGF5QmV0d2VlbiAmJiBpZHggPCBpbmRpY2VzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgYXdhaXQgZGVsYXkoZGVsYXlCZXR3ZWVuKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbWV0cmljcztcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBjb2xsZWN0Q29uY3VycmVudChcbiAgICBoYW5kbGVyOiBQZXJmb3JtYW5jZUhhbmRsZXI8VENvbnRleHQ+LFxuICAgIGNvbmZpZzogUGhhc2VDb25maWc8VENvbnRleHQ+LFxuICAgIGNvbnRleHQ6IFRDb250ZXh0LFxuICAgIGluZGljZXM6IG51bWJlcltdXG4gICk6IFByb21pc2U8SXRlcmF0aW9uTWV0cmljW10+IHtcbiAgICBjb25zdCBjb25jdXJyZW5jeSA9IE1hdGgubWF4KFxuICAgICAgMSxcbiAgICAgIE1hdGgubWluKGNvbmZpZy5jb25jdXJyZW5jeSA/PyBpbmRpY2VzLmxlbmd0aCwgaW5kaWNlcy5sZW5ndGgpXG4gICAgKTtcbiAgICBjb25zdCBtZXRyaWNzOiBJdGVyYXRpb25NZXRyaWNbXSA9IFtdO1xuICAgIGxldCBwb2ludGVyID0gMDtcblxuICAgIGNvbnN0IHdvcmtlciA9IGFzeW5jICgpID0+IHtcbiAgICAgIHdoaWxlIChwb2ludGVyIDwgaW5kaWNlcy5sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgaXRlcmF0aW9uID0gaW5kaWNlc1twb2ludGVyXTtcbiAgICAgICAgcG9pbnRlciArPSAxO1xuICAgICAgICBtZXRyaWNzLnB1c2goXG4gICAgICAgICAgYXdhaXQgdGhpcy5ydW5JdGVyYXRpb24oaGFuZGxlciwgY29uZmlnLCBjb250ZXh0LCBpdGVyYXRpb24pXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGF3YWl0IFByb21pc2UuYWxsKEFycmF5LmZyb20oeyBsZW5ndGg6IGNvbmN1cnJlbmN5IH0sICgpID0+IHdvcmtlcigpKSk7XG4gICAgcmV0dXJuIG1ldHJpY3M7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgcnVuSXRlcmF0aW9uKFxuICAgIGhhbmRsZXI6IFBlcmZvcm1hbmNlSGFuZGxlcjxUQ29udGV4dD4sXG4gICAgY29uZmlnOiBQaGFzZUNvbmZpZzxUQ29udGV4dD4sXG4gICAgY29udGV4dDogVENvbnRleHQsXG4gICAgaXRlcmF0aW9uOiBudW1iZXJcbiAgKTogUHJvbWlzZTxJdGVyYXRpb25NZXRyaWM+IHtcbiAgICBjb25zdCBsb2FkRmFjdG9yID0gdGhpcy5jb21wdXRlTG9hZEZhY3Rvcihjb25maWcsIGl0ZXJhdGlvbik7XG4gICAgY29uc3Qgc3RvcHdhdGNoID0gbmV3IFN0b3BXYXRjaCh0cnVlKTtcbiAgICBsZXQgc3VjY2VzcyA9IHRydWU7XG4gICAgbGV0IG1ldGE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkO1xuXG4gICAgZGVidWdMb2coXG4gICAgICBgW1BlcmZSdW5uZXJdIEl0ZXJhdGlvbiAke2l0ZXJhdGlvbn0gKHBoYXNlPSR7Y29uZmlnLm1ldGFkYXRhPy5waGFzZU5hbWUgPz8gXCJuL2FcIn0sIGxvYWQ9JHtsb2FkRmFjdG9yLnRvRml4ZWQoXG4gICAgICAgIDJcbiAgICAgICl9KSBzdGFydGluZ2BcbiAgICApO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBoYW5kbGVyKHsgaXRlcmF0aW9uLCBjb25maWcsIGxvYWRGYWN0b3IsIGNvbnRleHQgfSk7XG4gICAgICBpZiAodHlwZW9mIHJlc3VsdD8uc3VjY2VzcyA9PT0gXCJib29sZWFuXCIpIHtcbiAgICAgICAgc3VjY2VzcyA9IHJlc3VsdC5zdWNjZXNzO1xuICAgICAgfVxuICAgICAgbWV0YSA9IHJlc3VsdD8ubWV0YTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgc3VjY2VzcyA9IGZhbHNlO1xuICAgICAgbWV0YSA9IHsgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKSB9O1xuICAgIH1cblxuICAgIGNvbnN0IGR1cmF0aW9uTXMgPSBzdG9wd2F0Y2guc3RvcCgpO1xuICAgIGRlYnVnTG9nKFxuICAgICAgYFtQZXJmUnVubmVyXSBJdGVyYXRpb24gJHtpdGVyYXRpb259IGNvbXBsZXRlIGluICR7ZHVyYXRpb25Ncy50b0ZpeGVkKDIpfW1zLCBzdWNjZXNzPSR7c3VjY2Vzc31gXG4gICAgKTtcbiAgICByZXR1cm4geyBpdGVyYXRpb24sIGR1cmF0aW9uTXMsIHN1Y2Nlc3MsIG1ldGEsIGxvYWRGYWN0b3IgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhZ2dyZWdhdGVNZXRyaWNzKG1ldHJpY3M6IEl0ZXJhdGlvbk1ldHJpY1tdKTogQWdncmVnYXRlZE1ldHJpY3Mge1xuICAgIGlmIChtZXRyaWNzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdG90YWxEdXJhdGlvbk1zOiAwLFxuICAgICAgICBtaW5NczogMCxcbiAgICAgICAgbWF4TXM6IDAsXG4gICAgICAgIGF2ZXJhZ2VNczogMCxcbiAgICAgICAgc3VjY2Vzc0NvdW50OiAwLFxuICAgICAgICBmYWlsdXJlQ291bnQ6IDAsXG4gICAgICAgIGxvYWRTdGFydDogMCxcbiAgICAgICAgbG9hZEVuZDogMCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgdG90YWxEdXJhdGlvbk1zID0gbWV0cmljcy5yZWR1Y2UoXG4gICAgICAoYWNjLCBtZXRyaWMpID0+IGFjYyArIG1ldHJpYy5kdXJhdGlvbk1zLFxuICAgICAgMFxuICAgICk7XG4gICAgY29uc3QgbWluTXMgPSBNYXRoLm1pbiguLi5tZXRyaWNzLm1hcCgobWV0cmljKSA9PiBtZXRyaWMuZHVyYXRpb25NcykpO1xuICAgIGNvbnN0IG1heE1zID0gTWF0aC5tYXgoLi4ubWV0cmljcy5tYXAoKG1ldHJpYykgPT4gbWV0cmljLmR1cmF0aW9uTXMpKTtcbiAgICBjb25zdCBhdmVyYWdlTXMgPSB0b3RhbER1cmF0aW9uTXMgLyBtZXRyaWNzLmxlbmd0aDtcbiAgICBjb25zdCBzdWNjZXNzQ291bnQgPSBtZXRyaWNzLmZpbHRlcigobWV0cmljKSA9PiBtZXRyaWMuc3VjY2VzcykubGVuZ3RoO1xuICAgIGNvbnN0IGZhaWx1cmVDb3VudCA9IG1ldHJpY3MubGVuZ3RoIC0gc3VjY2Vzc0NvdW50O1xuICAgIGNvbnN0IGxvYWRTdGFydCA9IG1ldHJpY3NbMF0/LmxvYWRGYWN0b3IgPz8gMDtcbiAgICBjb25zdCBsb2FkRW5kID0gbWV0cmljc1ttZXRyaWNzLmxlbmd0aCAtIDFdPy5sb2FkRmFjdG9yID8/IGxvYWRTdGFydDtcblxuICAgIHJldHVybiB7XG4gICAgICB0b3RhbER1cmF0aW9uTXMsXG4gICAgICBtaW5NcyxcbiAgICAgIG1heE1zLFxuICAgICAgYXZlcmFnZU1zLFxuICAgICAgc3VjY2Vzc0NvdW50LFxuICAgICAgZmFpbHVyZUNvdW50LFxuICAgICAgbG9hZFN0YXJ0LFxuICAgICAgbG9hZEVuZCxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGxvZ1N1bW1hcnkocmVzdWx0czogUGhhc2VSZXN1bHQ8VENvbnRleHQ+W10pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXJlc3VsdHMubGVuZ3RoKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZGVycyA9IFtcbiAgICAgIFwiUGhhc2VcIixcbiAgICAgIFwiTW9kZVwiLFxuICAgICAgXCJJdGVyYXRpb25zXCIsXG4gICAgICBcIlRvdGFsIG1zXCIsXG4gICAgICBcIkF2ZyBtc1wiLFxuICAgICAgXCJNaW4gbXNcIixcbiAgICAgIFwiTWF4IG1zXCIsXG4gICAgICBcIlN1Y2Nlc3NcIixcbiAgICAgIFwiRmFpbHVyZXNcIixcbiAgICAgIFwiTG9hZCByYW5nZVwiLFxuICAgIF07XG5cbiAgICBjb25zdCByb3dzID0gcmVzdWx0cy5tYXAoKHJlc3VsdCkgPT4gW1xuICAgICAgcmVzdWx0LnBoYXNlLm5hbWUsXG4gICAgICByZXN1bHQuY29uZmlnLm1vZGUsXG4gICAgICByZXN1bHQuY29uZmlnLml0ZXJhdGlvbnMudG9TdHJpbmcoKSxcbiAgICAgIHJlc3VsdC5hZ2dyZWdhdGVkLnRvdGFsRHVyYXRpb25Ncy50b0ZpeGVkKDIpLFxuICAgICAgcmVzdWx0LmFnZ3JlZ2F0ZWQuYXZlcmFnZU1zLnRvRml4ZWQoMiksXG4gICAgICByZXN1bHQuYWdncmVnYXRlZC5taW5Ncy50b0ZpeGVkKDIpLFxuICAgICAgcmVzdWx0LmFnZ3JlZ2F0ZWQubWF4TXMudG9GaXhlZCgyKSxcbiAgICAgIHJlc3VsdC5hZ2dyZWdhdGVkLnN1Y2Nlc3NDb3VudC50b1N0cmluZygpLFxuICAgICAgcmVzdWx0LmFnZ3JlZ2F0ZWQuZmFpbHVyZUNvdW50LnRvU3RyaW5nKCksXG4gICAgICBgJHtyZXN1bHQuYWdncmVnYXRlZC5sb2FkU3RhcnQudG9GaXhlZCgyKX0g4oaSICR7cmVzdWx0LmFnZ3JlZ2F0ZWQubG9hZEVuZC50b0ZpeGVkKDIpfWAsXG4gICAgXSk7XG5cbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIGZvcm1hdFRhYmxlKFxuICAgICAgICBgUGVyZm9ybWFuY2Ugc3VtbWFyeSBmb3IgJHt0aGlzLnNjZW5hcmlvLm5hbWV9YCxcbiAgICAgICAgaGVhZGVycyxcbiAgICAgICAgcm93c1xuICAgICAgKVxuICAgICk7XG5cbiAgICBpZiAodGhpcy5zaG91bGRSZW5kZXJDYW52YXMoKSkge1xuICAgICAgY29uc3QgY2hhcnRQYXRoID1cbiAgICAgICAgdGhpcy5zY2VuYXJpby5jYW52YXNPdXRwdXRQYXRoID8/XG4gICAgICAgIHBhdGguam9pbihcbiAgICAgICAgICBwcm9jZXNzLmN3ZCgpLFxuICAgICAgICAgIFwid29ya2RvY3NcIixcbiAgICAgICAgICBcInJlcG9ydHNcIixcbiAgICAgICAgICBcInBlcmZvcm1hbmNlLXJ1bm5lci5wbmdcIlxuICAgICAgICApO1xuICAgICAgYXdhaXQgcmVuZGVyTWV0cmljc1RhYmxlVG9DYW52YXMoXG4gICAgICAgIGhlYWRlcnMsXG4gICAgICAgIHJvd3MsXG4gICAgICAgIHRoaXMuc2NlbmFyaW8uY2FudmFzT3B0aW9ucyA/PyBkZWZhdWx0Q2FudmFzT3B0aW9ucyxcbiAgICAgICAgY2hhcnRQYXRoXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBzaG91bGRSZW5kZXJDYW52YXMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuc2NlbmFyaW8uZW5hYmxlQ2FudmFzID8/IEJvb2xlYW4odGhpcy5zY2VuYXJpby5jYW52YXNPcHRpb25zKTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gXCIuLi9jb21tYW5kXCI7XG5pbXBvcnQgeyBDb21tYW5kT3B0aW9ucyB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgRGVmYXVsdENvbW1hbmRPcHRpb25zLCBEZWZhdWx0Q29tbWFuZFZhbHVlcyB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcbmltcG9ydCB7XG4gIGNvcHlGaWxlLFxuICBkZWxldGVQYXRoLFxuICBnZXRBbGxGaWxlcyxcbiAgZ2V0UGFja2FnZSxcbiAgcGF0Y2hGaWxlLFxuICByZW5hbWVGaWxlLFxuICBydW5Db21tYW5kLFxuICBnZXRGaWxlU2l6ZVppcHBlZCxcbiAgbGlzdE5vZGVNb2R1bGVzUGFja2FnZXMsXG59IGZyb20gXCIuLi8uLi91dGlsc1wiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IElucHV0T3B0aW9ucywgT3V0cHV0T3B0aW9ucywgcm9sbHVwLCBSb2xsdXBCdWlsZCB9IGZyb20gXCJyb2xsdXBcIjtcbmltcG9ydCB0eXBlc2NyaXB0IGZyb20gXCJAcm9sbHVwL3BsdWdpbi10eXBlc2NyaXB0XCI7XG5pbXBvcnQgY29tbW9uanMgZnJvbSBcIkByb2xsdXAvcGx1Z2luLWNvbW1vbmpzXCI7XG5pbXBvcnQgeyBub2RlUmVzb2x2ZSB9IGZyb20gXCJAcm9sbHVwL3BsdWdpbi1ub2RlLXJlc29sdmVcIjtcbmltcG9ydCBqc29uIGZyb20gXCJAcm9sbHVwL3BsdWdpbi1qc29uXCI7XG5pbXBvcnQgeyBidWlsdGluTW9kdWxlcyB9IGZyb20gXCJtb2R1bGVcIjtcbmltcG9ydCB7IExvZ2dpbmdDb25maWcsIExvZ0xldmVsIH0gZnJvbSBcIkBkZWNhZi10cy9sb2dnaW5nXCI7XG5cbi8vIGRlY2xhcmUgb3B0aW9uYWwgdGVyc2VyIG1vZHVsZSB0byBzYXRpc2Z5IFR5cGVTY3JpcHQgd2hlbiB0eXBlcyBhcmVuJ3QgaW5zdGFsbGVkXG5kZWNsYXJlIG1vZHVsZSBcIkByb2xsdXAvcGx1Z2luLXRlcnNlclwiO1xuXG5pbXBvcnQgKiBhcyB0cyBmcm9tIFwidHlwZXNjcmlwdFwiO1xuaW1wb3J0IHsgRGlhZ25vc3RpYywgRW1pdFJlc3VsdCwgTW9kdWxlS2luZCwgU291cmNlRmlsZSB9IGZyb20gXCJ0eXBlc2NyaXB0XCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUxpc3QoaW5wdXQ/OiBzdHJpbmcgfCBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcbiAgaWYgKCFpbnB1dCkgcmV0dXJuIFtdO1xuICBpZiAoQXJyYXkuaXNBcnJheShpbnB1dCkpXG4gICAgcmV0dXJuIGlucHV0Lm1hcCgoaSkgPT4gYCR7aX1gLnRyaW0oKSkuZmlsdGVyKEJvb2xlYW4pO1xuICByZXR1cm4gYCR7aW5wdXR9YFxuICAgIC5zcGxpdChcIixcIilcbiAgICAubWFwKChwKSA9PiBwLnRyaW0oKSlcbiAgICAuZmlsdGVyKEJvb2xlYW4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFja2FnZVRvR2xvYmFsKG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIC8vIFJlbW92ZSBzY29wZSBhbmQgc3BsaXQgYnkgbm9uLWFscGhhbnVtZXJpYyBjaGFycywgdGhlbiBjYW1lbENhc2VcbiAgY29uc3Qgd2l0aG91dFNjb3BlID0gbmFtZS5yZXBsYWNlKC9eQC8sIFwiXCIpO1xuICBjb25zdCBwYXJ0cyA9IHdpdGhvdXRTY29wZS5zcGxpdCgvWy9cXC1fLl0rLykuZmlsdGVyKEJvb2xlYW4pO1xuICByZXR1cm4gcGFydHNcbiAgICAubWFwKChwLCBpKSA9PlxuICAgICAgaSA9PT0gMFxuICAgICAgICA/IHAucmVwbGFjZSgvW15hLXpBLVowLTldL2csIFwiXCIpXG4gICAgICAgIDogYCR7cC5jaGFyQXQoMCkudG9VcHBlckNhc2UoKX0ke3Auc2xpY2UoMSl9YFxuICAgIClcbiAgICAuam9pbihcIlwiKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFBhY2thZ2VEZXBlbmRlbmNpZXMoKTogc3RyaW5nW10ge1xuICAvLyBUcnkgdGhlIGN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnkgZmlyc3RcbiAgbGV0IHBrZzogYW55O1xuICB0cnkge1xuICAgIHBrZyA9IGdldFBhY2thZ2UocHJvY2Vzcy5jd2QoKSkgYXMgYW55O1xuICB9IGNhdGNoIHtcbiAgICBwa2cgPSB1bmRlZmluZWQ7XG4gIH1cblxuICAvLyBJZiBubyBkZXBlbmRlbmNpZXMgZm91bmQgaW4gY3dkLCB0cnkgdGhlIHBhY2thZ2UgbmV4dCB0byB0aGlzIHNvdXJjZSBmaWxlIChmYWxsYmFjayBmb3IgdGVzdHMpXG4gIHRyeSB7XG4gICAgY29uc3QgaGFzRGVwcyA9XG4gICAgICBwa2cgJiZcbiAgICAgIChPYmplY3Qua2V5cyhwa2cuZGVwZW5kZW5jaWVzIHx8IHt9KS5sZW5ndGggPiAwIHx8XG4gICAgICAgIE9iamVjdC5rZXlzKHBrZy5kZXZEZXBlbmRlbmNpZXMgfHwge30pLmxlbmd0aCA+IDAgfHxcbiAgICAgICAgT2JqZWN0LmtleXMocGtnLnBlZXJEZXBlbmRlbmNpZXMgfHwge30pLmxlbmd0aCA+IDApO1xuICAgIGlmICghaGFzRGVwcykge1xuICAgICAgY29uc3QgZmFsbGJhY2tEaXIgPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCBcIi4uLy4uLy4uXCIpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcGtnID0gZ2V0UGFja2FnZShmYWxsYmFja0RpcikgYXMgYW55O1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIGlnbm9yZSBhbmQga2VlcCBwa2cgYXMtaXNcbiAgICAgIH1cbiAgICB9XG4gIH0gY2F0Y2gge1xuICAgIC8vIGlnbm9yZVxuICB9XG5cbiAgY29uc3QgZGVwcyA9IE9iamVjdC5rZXlzKChwa2cgJiYgcGtnLmRlcGVuZGVuY2llcykgfHwge30pO1xuICBjb25zdCBwZWVyID0gT2JqZWN0LmtleXMoKHBrZyAmJiBwa2cucGVlckRlcGVuZGVuY2llcykgfHwge30pO1xuICBjb25zdCBkZXYgPSBPYmplY3Qua2V5cygocGtnICYmIHBrZy5kZXZEZXBlbmRlbmNpZXMpIHx8IHt9KTtcbiAgcmV0dXJuIEFycmF5LmZyb20obmV3IFNldChbLi4uZGVwcywgLi4ucGVlciwgLi4uZGV2XSkpO1xufVxuXG5jb25zdCBWRVJTSU9OX1NUUklORyA9IFwiIyNWRVJTSU9OIyNcIjtcbmNvbnN0IFBBQ0tBR0VfU1RSSU5HID0gXCIjI1BBQ0tBR0UjI1wiO1xuY29uc3QgUEFDS0FHRV9TSVpFX1NUUklORyA9IFwiIyNQQUNLQUdFX1NJWkUjI1wiO1xuXG5lbnVtIE1vZGVzIHtcbiAgQ0pTID0gXCJjb21tb25qc1wiLFxuICBFU00gPSBcImVzMjAyMlwiLFxufVxuXG5lbnVtIEJ1aWxkTW9kZSB7XG4gIEJVSUxEID0gXCJidWlsZFwiLFxuICBCVU5ETEUgPSBcImJ1bmRsZVwiLFxuICBBTEwgPSBcImFsbFwiLFxufVxuXG5jb25zdCBvcHRpb25zID0ge1xuICBwcm9kOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG4gIGRldjoge1xuICAgIHR5cGU6IFwiYm9vbGVhblwiLFxuICAgIGRlZmF1bHQ6IGZhbHNlLFxuICB9LFxuICBidWlsZE1vZGU6IHtcbiAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgIGRlZmF1bHQ6IEJ1aWxkTW9kZS5BTEwsXG4gIH0sXG4gIGluY2x1ZGVzOiB7XG4gICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICBkZWZhdWx0OiBcIlwiLFxuICB9LFxuICBleHRlcm5hbHM6IHtcbiAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgIGRlZmF1bHQ6IFwiXCIsXG4gIH0sXG4gIGRvY3M6IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgY29tbWFuZHM6IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgICBkZWZhdWx0OiBmYWxzZSxcbiAgfSxcbiAgZW50cnk6IHtcbiAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgIGRlZmF1bHQ6IFwiLi9zcmMvaW5kZXgudHNcIixcbiAgfSxcbiAgYmFubmVyOiB7XG4gICAgdHlwZTogXCJib29sZWFuXCIsXG4gICAgZGVmYXVsdDogZmFsc2UsXG4gIH0sXG59O1xuXG5jb25zdCBjanMyVHJhbnNmb3JtZXIgPSAoZXh0ID0gXCIuY2pzXCIpID0+IHtcbiAgY29uc3QgbG9nID0gQnVpbGRTY3JpcHRzLmxvZy5mb3IoY2pzMlRyYW5zZm9ybWVyKTtcbiAgY29uc3QgcmVzb2x1dGlvbkNhY2hlID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcblxuICByZXR1cm4gKHRyYW5zZm9ybWF0aW9uQ29udGV4dDogdHMuVHJhbnNmb3JtYXRpb25Db250ZXh0KSA9PiB7XG4gICAgcmV0dXJuIChzb3VyY2VGaWxlOiB0cy5Tb3VyY2VGaWxlKSA9PiB7XG4gICAgICBjb25zdCBzb3VyY2VEaXIgPSBwYXRoLmRpcm5hbWUoc291cmNlRmlsZS5maWxlTmFtZSk7XG5cbiAgICAgIGZ1bmN0aW9uIHJlc29sdmVQYXRoKGltcG9ydFBhdGg6IHN0cmluZykge1xuICAgICAgICBjb25zdCBjYWNoZUtleSA9IEpTT04uc3RyaW5naWZ5KFtzb3VyY2VEaXIsIGltcG9ydFBhdGhdKTtcbiAgICAgICAgY29uc3QgY2FjaGVkVmFsdWUgPSByZXNvbHV0aW9uQ2FjaGUuZ2V0KGNhY2hlS2V5KTtcbiAgICAgICAgaWYgKGNhY2hlZFZhbHVlICE9IG51bGwpIHJldHVybiBjYWNoZWRWYWx1ZTtcblxuICAgICAgICBsZXQgcmVzb2x2ZWRQYXRoID0gaW1wb3J0UGF0aDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXNvbHZlZFBhdGggPSBwYXRoLnJlc29sdmUoc291cmNlRGlyLCByZXNvbHZlZFBhdGggKyBcIi50c1wiKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byByZXNvbHZlIHBhdGggJHtpbXBvcnRQYXRofTogJHtlcnJvcn1gKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgc3RhdDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBzdGF0ID0gZnMuc3RhdFN5bmMocmVzb2x2ZWRQYXRoKTtcbiAgICAgICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsb2cudmVyYm9zZShcbiAgICAgICAgICAgICAgYFRlc3RpbmcgZXhpc3RlbmNlIG9mIHBhdGggJHtyZXNvbHZlZFBhdGh9IGFzIGEgZm9sZGVyIGRlZmF1bHRpbmcgdG8gaW5kZXggZmlsZWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBzdGF0ID0gZnMuc3RhdFN5bmMocmVzb2x2ZWRQYXRoLnJlcGxhY2UoL1xcLnRzJC9nbSwgXCJcIikpO1xuICAgICAgICAgIH0gY2F0Y2ggKGUyOiB1bmtub3duKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgIGBGYWlsZWQgdG8gcmVzb2x2ZSBwYXRoICR7aW1wb3J0UGF0aH06ICR7ZX0sICR7ZTJ9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0YXQuaXNEaXJlY3RvcnkoKSlcbiAgICAgICAgICByZXNvbHZlZFBhdGggPSByZXNvbHZlZFBhdGgucmVwbGFjZSgvXFwudHMkL2dtLCBcIi9pbmRleC50c1wiKTtcblxuICAgICAgICBpZiAocGF0aC5pc0Fic29sdXRlKHJlc29sdmVkUGF0aCkpIHtcbiAgICAgICAgICBjb25zdCBleHRlbnNpb24gPVxuICAgICAgICAgICAgKC9cXC50c3g/JC8uZXhlYyhwYXRoLmJhc2VuYW1lKHJlc29sdmVkUGF0aCkpIHx8IFtdKVswXSB8fCB2b2lkIDA7XG5cbiAgICAgICAgICByZXNvbHZlZFBhdGggPVxuICAgICAgICAgICAgXCIuL1wiICtcbiAgICAgICAgICAgIHBhdGgucmVsYXRpdmUoXG4gICAgICAgICAgICAgIHNvdXJjZURpcixcbiAgICAgICAgICAgICAgcGF0aC5yZXNvbHZlKFxuICAgICAgICAgICAgICAgIHBhdGguZGlybmFtZShyZXNvbHZlZFBhdGgpLFxuICAgICAgICAgICAgICAgIHBhdGguYmFzZW5hbWUocmVzb2x2ZWRQYXRoLCBleHRlbnNpb24pICsgZXh0XG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICByZXNvbHV0aW9uQ2FjaGUuc2V0KGNhY2hlS2V5LCByZXNvbHZlZFBhdGgpO1xuICAgICAgICByZXR1cm4gcmVzb2x2ZWRQYXRoO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiB2aXNpdE5vZGUobm9kZTogdHMuTm9kZSk6IHRzLlZpc2l0UmVzdWx0PHRzLk5vZGU+IHtcbiAgICAgICAgaWYgKHNob3VsZE11dGF0ZU1vZHVsZVNwZWNpZmllcihub2RlKSkge1xuICAgICAgICAgIGlmICh0cy5pc0ltcG9ydERlY2xhcmF0aW9uKG5vZGUpKSB7XG4gICAgICAgICAgICBjb25zdCByZXNvbHZlZFBhdGggPSByZXNvbHZlUGF0aChub2RlLm1vZHVsZVNwZWNpZmllci50ZXh0KTtcbiAgICAgICAgICAgIGNvbnN0IG5ld01vZHVsZVNwZWNpZmllciA9XG4gICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uQ29udGV4dC5mYWN0b3J5LmNyZWF0ZVN0cmluZ0xpdGVyYWwocmVzb2x2ZWRQYXRoKTtcbiAgICAgICAgICAgIHJldHVybiB0cmFuc2Zvcm1hdGlvbkNvbnRleHQuZmFjdG9yeS51cGRhdGVJbXBvcnREZWNsYXJhdGlvbihcbiAgICAgICAgICAgICAgbm9kZSxcbiAgICAgICAgICAgICAgbm9kZS5tb2RpZmllcnMsXG4gICAgICAgICAgICAgIG5vZGUuaW1wb3J0Q2xhdXNlLFxuICAgICAgICAgICAgICBuZXdNb2R1bGVTcGVjaWZpZXIsXG4gICAgICAgICAgICAgIHVuZGVmaW5lZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHRzLmlzRXhwb3J0RGVjbGFyYXRpb24obm9kZSkpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlc29sdmVkUGF0aCA9IHJlc29sdmVQYXRoKG5vZGUubW9kdWxlU3BlY2lmaWVyLnRleHQpO1xuICAgICAgICAgICAgY29uc3QgbmV3TW9kdWxlU3BlY2lmaWVyID1cbiAgICAgICAgICAgICAgdHJhbnNmb3JtYXRpb25Db250ZXh0LmZhY3RvcnkuY3JlYXRlU3RyaW5nTGl0ZXJhbChyZXNvbHZlZFBhdGgpO1xuICAgICAgICAgICAgcmV0dXJuIHRyYW5zZm9ybWF0aW9uQ29udGV4dC5mYWN0b3J5LnVwZGF0ZUV4cG9ydERlY2xhcmF0aW9uKFxuICAgICAgICAgICAgICBub2RlLFxuICAgICAgICAgICAgICBub2RlLm1vZGlmaWVycyxcbiAgICAgICAgICAgICAgbm9kZS5pc1R5cGVPbmx5LFxuICAgICAgICAgICAgICBub2RlLmV4cG9ydENsYXVzZSxcbiAgICAgICAgICAgICAgbmV3TW9kdWxlU3BlY2lmaWVyLFxuICAgICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRzLnZpc2l0RWFjaENoaWxkKG5vZGUsIHZpc2l0Tm9kZSwgdHJhbnNmb3JtYXRpb25Db250ZXh0KTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gc2hvdWxkTXV0YXRlTW9kdWxlU3BlY2lmaWVyKG5vZGU6IHRzLk5vZGUpOiBub2RlIGlzIChcbiAgICAgICAgfCB0cy5JbXBvcnREZWNsYXJhdGlvblxuICAgICAgICB8IHRzLkV4cG9ydERlY2xhcmF0aW9uXG4gICAgICApICYge1xuICAgICAgICBtb2R1bGVTcGVjaWZpZXI6IHRzLlN0cmluZ0xpdGVyYWw7XG4gICAgICB9IHtcbiAgICAgICAgaWYgKCF0cy5pc0ltcG9ydERlY2xhcmF0aW9uKG5vZGUpICYmICF0cy5pc0V4cG9ydERlY2xhcmF0aW9uKG5vZGUpKVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgICAgICBpZiAobm9kZS5tb2R1bGVTcGVjaWZpZXIgPT09IHVuZGVmaW5lZCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAvLyBvbmx5IHdoZW4gbW9kdWxlIHNwZWNpZmllciBpcyB2YWxpZFxuICAgICAgICBpZiAoIXRzLmlzU3RyaW5nTGl0ZXJhbChub2RlLm1vZHVsZVNwZWNpZmllcikpIHJldHVybiBmYWxzZTtcbiAgICAgICAgLy8gb25seSB3aGVuIHBhdGggaXMgcmVsYXRpdmVcbiAgICAgICAgaWYgKFxuICAgICAgICAgICFub2RlLm1vZHVsZVNwZWNpZmllci50ZXh0LnN0YXJ0c1dpdGgoXCIuL1wiKSAmJlxuICAgICAgICAgICFub2RlLm1vZHVsZVNwZWNpZmllci50ZXh0LnN0YXJ0c1dpdGgoXCIuLi9cIilcbiAgICAgICAgKVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgLy8gb25seSB3aGVuIG1vZHVsZSBzcGVjaWZpZXIgaGFzIG5vIGV4dGVuc2lvblxuICAgICAgICBpZiAocGF0aC5leHRuYW1lKG5vZGUubW9kdWxlU3BlY2lmaWVyLnRleHQpICE9PSBcIlwiKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdHMudmlzaXROb2RlKHNvdXJjZUZpbGUsIHZpc2l0Tm9kZSkgYXMgU291cmNlRmlsZTtcbiAgICB9O1xuICB9O1xufTtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQSBjb21tYW5kLWxpbmUgc2NyaXB0IGZvciBidWlsZGluZyBhbmQgYnVuZGxpbmcgVHlwZVNjcmlwdCBwcm9qZWN0cy5cbiAqIEBzdW1tYXJ5IFRoaXMgY2xhc3MgcHJvdmlkZXMgYSBjb21wcmVoZW5zaXZlIGJ1aWxkIHNjcmlwdCB0aGF0IGhhbmRsZXMgVHlwZVNjcmlwdCBjb21waWxhdGlvbixcbiAqIGJ1bmRsaW5nIHdpdGggUm9sbHVwLCBhbmQgZG9jdW1lbnRhdGlvbiBnZW5lcmF0aW9uLiBJdCBzdXBwb3J0cyBkaWZmZXJlbnQgYnVpbGQgbW9kZXNcbiAqIChkZXZlbG9wbWVudCwgcHJvZHVjdGlvbiksIG1vZHVsZSBmb3JtYXRzIChDSlMsIEVTTSksIGFuZCBjYW4gYmUgZXh0ZW5kZWQgd2l0aCBjdXN0b21cbiAqIGNvbmZpZ3VyYXRpb25zLlxuICogQGNsYXNzIEJ1aWxkU2NyaXB0c1xuICovXG5leHBvcnQgY2xhc3MgQnVpbGRTY3JpcHRzIGV4dGVuZHMgQ29tbWFuZDxcbiAgQ29tbWFuZE9wdGlvbnM8dHlwZW9mIG9wdGlvbnM+LFxuICB2b2lkXG4+IHtcbiAgcHJpdmF0ZSByZXBsYWNlbWVudHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgcHJpdmF0ZSByZWFkb25seSBwa2dWZXJzaW9uOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGtnTmFtZTogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKFxuICAgICAgXCJCdWlsZFNjcmlwdHNcIixcbiAgICAgIE9iamVjdC5hc3NpZ24oe30sIERlZmF1bHRDb21tYW5kT3B0aW9ucywgb3B0aW9ucykgYXMgQ29tbWFuZE9wdGlvbnM8XG4gICAgICAgIHR5cGVvZiBvcHRpb25zXG4gICAgICA+XG4gICAgKTtcbiAgICBjb25zdCBwa2cgPSBnZXRQYWNrYWdlKCkgYXMgeyBuYW1lOiBzdHJpbmc7IHZlcnNpb246IHN0cmluZyB9O1xuICAgIGNvbnN0IHsgbmFtZSwgdmVyc2lvbiB9ID0gcGtnO1xuICAgIHRoaXMucGtnTmFtZSA9IG5hbWUuaW5jbHVkZXMoXCJAXCIpID8gbmFtZS5zcGxpdChcIi9cIilbMV0gOiBuYW1lO1xuICAgIHRoaXMucGtnVmVyc2lvbiA9IHZlcnNpb247XG4gICAgdGhpcy5yZXBsYWNlbWVudHNbVkVSU0lPTl9TVFJJTkddID0gdGhpcy5wa2dWZXJzaW9uO1xuICAgIHRoaXMucmVwbGFjZW1lbnRzW1BBQ0tBR0VfU1RSSU5HXSA9IG5hbWU7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFBhdGNoZXMgZmlsZXMgd2l0aCB2ZXJzaW9uIGFuZCBwYWNrYWdlIG5hbWUuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIHJlYWRzIGFsbCBmaWxlcyBpbiBhIGRpcmVjdG9yeSwgZmluZHMgcGxhY2Vob2xkZXJzIGZvciB2ZXJzaW9uXG4gICAqIGFuZCBwYWNrYWdlIG5hbWUsIGFuZCByZXBsYWNlcyB0aGVtIHdpdGggdGhlIGFjdHVhbCB2YWx1ZXMgZnJvbSBwYWNrYWdlLmpzb24uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwIC0gVGhlIHBhdGggdG8gdGhlIGRpcmVjdG9yeSBjb250YWluaW5nIHRoZSBmaWxlcyB0byBwYXRjaC5cbiAgICovXG4gIHBhdGNoRmlsZXMocDogc3RyaW5nKSB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMucGF0Y2hGaWxlcyk7XG4gICAgY29uc3QgeyBuYW1lLCB2ZXJzaW9uIH0gPSBnZXRQYWNrYWdlKCkgYXMgYW55O1xuICAgIGxvZy5pbmZvKGBQYXRjaGluZyAke25hbWV9ICR7dmVyc2lvbn0gbW9kdWxlIGluICR7cH0uLi5gKTtcbiAgICBjb25zdCBzdGF0ID0gZnMuc3RhdFN5bmMocCk7XG4gICAgaWYgKHN0YXQuaXNEaXJlY3RvcnkoKSlcbiAgICAgIGZzLnJlYWRkaXJTeW5jKHAsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSwgcmVjdXJzaXZlOiB0cnVlIH0pXG4gICAgICAgIC5maWx0ZXIoKHApID0+IHAuaXNGaWxlKCkpXG4gICAgICAgIC5mb3JFYWNoKChmaWxlKSA9PlxuICAgICAgICAgIHBhdGNoRmlsZShcbiAgICAgICAgICAgIHBhdGguam9pbihmaWxlLnBhcmVudFBhdGgsIGZpbGUubmFtZSksXG4gICAgICAgICAgICBPYmplY3QuZW50cmllcyh0aGlzLnJlcGxhY2VtZW50cykucmVkdWNlKFxuICAgICAgICAgICAgICAoYWNjOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgICAgICAgICAgIGNhc2UgVkVSU0lPTl9TVFJJTkc6XG4gICAgICAgICAgICAgICAgICAgIGxvZy5kZWJ1ZyhcIkZvdW5kIFZFUlNJT04gc3RyaW5nIHRvIHJlcGxhY2VcIik7XG4gICAgICAgICAgICAgICAgICAgIGFjY1tgVkVSU0lPTiA9IFwiJHtWRVJTSU9OX1NUUklOR31cIjtgXSA9XG4gICAgICAgICAgICAgICAgICAgICAgYFZFUlNJT04gPSBcIiR7dmFsfVwiO2A7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgY2FzZSBQQUNLQUdFX1NUUklORzpcbiAgICAgICAgICAgICAgICAgICAgbG9nLmRlYnVnKFwiRm91bmQgUEFDS0FHRV9OQU1FIHN0cmluZyB0byByZXBsYWNlXCIpO1xuICAgICAgICAgICAgICAgICAgICBhY2NbYFBBQ0tBR0VfTkFNRSA9IFwiJHtQQUNLQUdFX1NUUklOR31cIjtgXSA9XG4gICAgICAgICAgICAgICAgICAgICAgYFBBQ0tBR0VfTkFNRSA9IFwiJHt2YWx9XCI7YDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBhY2Nba2V5XSA9IHZhbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAge31cbiAgICAgICAgICAgIClcbiAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgbG9nLnZlcmJvc2UoYE1vZHVsZSAke25hbWV9ICR7dmVyc2lvbn0gcGF0Y2hlZCBpbiAke3B9Li4uYCk7XG4gIH1cblxuICBwcml2YXRlIHJlcG9ydERpYWdub3N0aWNzKFxuICAgIGRpYWdub3N0aWNzOiBEaWFnbm9zdGljW10sXG4gICAgbG9nTGV2ZWw6IExvZ0xldmVsXG4gICk6IHN0cmluZyB7XG4gICAgY29uc3QgbXNnID0gdGhpcy5mb3JtYXREaWFnbm9zdGljcyhkaWFnbm9zdGljcyk7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMubG9nW2xvZ0xldmVsXShtc2cpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGNvbnNvbGUud2FybihgRmFpbGVkIHRvIGdldCBsb2dnZXIgZm9yICR7bG9nTGV2ZWx9YCk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgICByZXR1cm4gbXNnO1xuICB9XG5cbiAgLy8gRm9ybWF0IGRpYWdub3N0aWNzIGludG8gYSBzaW5nbGUgc3RyaW5nIGZvciB0aHJvd2luZyBvciBsb2dnaW5nXG4gIHByaXZhdGUgZm9ybWF0RGlhZ25vc3RpY3MoZGlhZ25vc3RpY3M6IERpYWdub3N0aWNbXSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGRpYWdub3N0aWNzXG4gICAgICAubWFwKChkaWFnbm9zdGljKSA9PiB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gXCJcIjtcbiAgICAgICAgaWYgKGRpYWdub3N0aWMuZmlsZSAmJiBkaWFnbm9zdGljLnN0YXJ0KSB7XG4gICAgICAgICAgY29uc3QgeyBsaW5lLCBjaGFyYWN0ZXIgfSA9XG4gICAgICAgICAgICBkaWFnbm9zdGljLmZpbGUuZ2V0TGluZUFuZENoYXJhY3Rlck9mUG9zaXRpb24oZGlhZ25vc3RpYy5zdGFydCk7XG4gICAgICAgICAgbWVzc2FnZSArPSBgJHtkaWFnbm9zdGljLmZpbGUuZmlsZU5hbWV9ICgke2xpbmUgKyAxfSwke2NoYXJhY3RlciArIDF9KWA7XG4gICAgICAgIH1cbiAgICAgICAgbWVzc2FnZSArPVxuICAgICAgICAgIFwiOiBcIiArIHRzLmZsYXR0ZW5EaWFnbm9zdGljTWVzc2FnZVRleHQoZGlhZ25vc3RpYy5tZXNzYWdlVGV4dCwgXCJcXG5cIik7XG4gICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgfSlcbiAgICAgIC5qb2luKFwiXFxuXCIpO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkQ29uZmlnRmlsZShjb25maWdGaWxlTmFtZTogc3RyaW5nKSB7XG4gICAgLy8gUmVhZCBjb25maWcgZmlsZVxuICAgIGNvbnN0IGNvbmZpZ0ZpbGVUZXh0ID0gZnMucmVhZEZpbGVTeW5jKGNvbmZpZ0ZpbGVOYW1lKS50b1N0cmluZygpO1xuXG4gICAgLy8gUGFyc2UgSlNPTiwgYWZ0ZXIgcmVtb3ZpbmcgY29tbWVudHMuIEp1c3QgZmFuY2llciBKU09OLnBhcnNlXG4gICAgY29uc3QgcmVzdWx0ID0gdHMucGFyc2VDb25maWdGaWxlVGV4dFRvSnNvbihjb25maWdGaWxlTmFtZSwgY29uZmlnRmlsZVRleHQpO1xuICAgIGNvbnN0IGNvbmZpZ09iamVjdCA9IHJlc3VsdC5jb25maWc7XG4gICAgaWYgKCFjb25maWdPYmplY3QpIHtcbiAgICAgIHRoaXMucmVwb3J0RGlhZ25vc3RpY3MoW3Jlc3VsdC5lcnJvciFdLCBMb2dMZXZlbC5lcnJvcik7XG4gICAgfVxuXG4gICAgLy8gRXh0cmFjdCBjb25maWcgaW5mcm9tYXRpb25cbiAgICBjb25zdCBjb25maWdQYXJzZVJlc3VsdCA9IHRzLnBhcnNlSnNvbkNvbmZpZ0ZpbGVDb250ZW50KFxuICAgICAgY29uZmlnT2JqZWN0LFxuICAgICAgdHMuc3lzLFxuICAgICAgcGF0aC5kaXJuYW1lKGNvbmZpZ0ZpbGVOYW1lKVxuICAgICk7XG4gICAgaWYgKGNvbmZpZ1BhcnNlUmVzdWx0LmVycm9ycy5sZW5ndGggPiAwKVxuICAgICAgdGhpcy5yZXBvcnREaWFnbm9zdGljcyhjb25maWdQYXJzZVJlc3VsdC5lcnJvcnMsIExvZ0xldmVsLmVycm9yKTtcblxuICAgIHJldHVybiBjb25maWdQYXJzZVJlc3VsdDtcbiAgfVxuXG4gIHByaXZhdGUgZXZhbERpYWdub3N0aWNzKGRpYWdub3N0aWNzOiBEaWFnbm9zdGljW10pIHtcbiAgICBpZiAoZGlhZ25vc3RpY3MgJiYgZGlhZ25vc3RpY3MubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgZXJyb3JzID0gZGlhZ25vc3RpY3MuZmlsdGVyKFxuICAgICAgICAoZCkgPT4gZC5jYXRlZ29yeSA9PT0gdHMuRGlhZ25vc3RpY0NhdGVnb3J5LkVycm9yXG4gICAgICApO1xuICAgICAgY29uc3Qgd2FybmluZ3MgPSBkaWFnbm9zdGljcy5maWx0ZXIoXG4gICAgICAgIChkKSA9PiBkLmNhdGVnb3J5ID09PSB0cy5EaWFnbm9zdGljQ2F0ZWdvcnkuV2FybmluZ1xuICAgICAgKTtcbiAgICAgIGNvbnN0IHN1Z2dlc3Rpb25zID0gZGlhZ25vc3RpY3MuZmlsdGVyKFxuICAgICAgICAoZCkgPT4gZC5jYXRlZ29yeSA9PT0gdHMuRGlhZ25vc3RpY0NhdGVnb3J5LlN1Z2dlc3Rpb25cbiAgICAgICk7XG4gICAgICBjb25zdCBtZXNzYWdlcyA9IGRpYWdub3N0aWNzLmZpbHRlcihcbiAgICAgICAgKGQpID0+IGQuY2F0ZWdvcnkgPT09IHRzLkRpYWdub3N0aWNDYXRlZ29yeS5NZXNzYWdlXG4gICAgICApO1xuICAgICAgLy8gTG9nIGRpYWdub3N0aWNzIHRvIGNvbnNvbGVcblxuICAgICAgaWYgKHdhcm5pbmdzLmxlbmd0aCkgdGhpcy5yZXBvcnREaWFnbm9zdGljcyh3YXJuaW5ncywgTG9nTGV2ZWwud2Fybik7XG4gICAgICBpZiAoZXJyb3JzLmxlbmd0aCkge1xuICAgICAgICB0aGlzLnJlcG9ydERpYWdub3N0aWNzKGRpYWdub3N0aWNzIGFzIERpYWdub3N0aWNbXSwgTG9nTGV2ZWwuZXJyb3IpO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYFR5cGVTY3JpcHQgcmVwb3J0ZWQgJHtkaWFnbm9zdGljcy5sZW5ndGh9IGRpYWdub3N0aWMocykgZHVyaW5nIGNoZWNrOyBhYm9ydGluZy5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoc3VnZ2VzdGlvbnMubGVuZ3RoKVxuICAgICAgICB0aGlzLnJlcG9ydERpYWdub3N0aWNzKHN1Z2dlc3Rpb25zLCBMb2dMZXZlbC5pbmZvKTtcbiAgICAgIGlmIChtZXNzYWdlcy5sZW5ndGgpIHRoaXMucmVwb3J0RGlhZ25vc3RpY3MobWVzc2FnZXMsIExvZ0xldmVsLmluZm8pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcHJlQ2hlY2tEaWFnbm9zdGljcyhwcm9ncmFtOiB0cy5Qcm9ncmFtKSB7XG4gICAgY29uc3QgZGlhZ25vc3RpY3MgPSB0cy5nZXRQcmVFbWl0RGlhZ25vc3RpY3MocHJvZ3JhbSk7XG4gICAgdGhpcy5ldmFsRGlhZ25vc3RpY3MoZGlhZ25vc3RpY3MgYXMgYW55KTtcbiAgfVxuXG4gIC8vIENyZWF0ZSBhIFR5cGVTY3JpcHQgcHJvZ3JhbSBmb3IgdGhlIGN1cnJlbnQgdHNjb25maWcgYW5kIGZhaWwgaWYgdGhlcmUgYXJlIGFueSBlcnJvciBkaWFnbm9zdGljcy5cbiAgcHJpdmF0ZSBhc3luYyBjaGVja1RzRGlhZ25vc3RpY3MoXG4gICAgaXNEZXY6IGJvb2xlYW4sXG4gICAgbW9kZTogTW9kZXMsXG4gICAgYnVuZGxlID0gZmFsc2VcbiAgKSB7XG4gICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuY2hlY2tUc0RpYWdub3N0aWNzKTtcbiAgICBsZXQgdHNDb25maWc7XG4gICAgdHJ5IHtcbiAgICAgIHRzQ29uZmlnID0gdGhpcy5yZWFkQ29uZmlnRmlsZShcIi4vdHNjb25maWcuanNvblwiKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBwYXJzZSB0c2NvbmZpZy5qc29uOiAke2V9YCk7XG4gICAgfVxuXG4gICAgaWYgKGJ1bmRsZSkge1xuICAgICAgdHNDb25maWcub3B0aW9ucy5tb2R1bGUgPSBNb2R1bGVLaW5kLkFNRDtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMub3V0RGlyID0gXCJkaXN0XCI7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLmlzb2xhdGVkTW9kdWxlcyA9IGZhbHNlO1xuICAgICAgdHNDb25maWcub3B0aW9ucy5vdXRGaWxlID0gdGhpcy5wa2dOYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLm91dERpciA9IGBsaWIke21vZGUgPT09IE1vZGVzLkVTTSA/IFwiL2VzbVwiIDogXCJcIn1gO1xuICAgICAgdHNDb25maWcub3B0aW9ucy5tb2R1bGUgPVxuICAgICAgICBtb2RlID09PSBNb2Rlcy5FU00gPyBNb2R1bGVLaW5kLkVTMjAyMiA6IE1vZHVsZUtpbmQuQ29tbW9uSlM7XG4gICAgfVxuXG4gICAgLy8gRW5zdXJlIFR5cGVTY3JpcHQgZW1pdHMgaW5saW5lIHNvdXJjZSBtYXBzIGZvciBib3RoIGRldiBhbmQgcHJvZCAoYnVuZGxlcnMgd2lsbCBjb250cm9sIGV4dGVybmFsIG1hcHMpXG4gICAgLy8gS2VlcCBjb21tZW50cyBpbiBUUyBlbWl0IGJ5IGRlZmF1bHQ7IGJ1bmRsaW5nL21pbmlmaWNhdGlvbiB3aWxsIGhhbmRsZSByZW1vdmFsIHdoZXJlIHJlcXVlc3RlZC5cbiAgICAvLyBFbWl0IGV4dGVybmFsIHNvdXJjZSBtYXBzIGZyb20gVHlwZVNjcmlwdCBzbyBlZGl0b3JzL2RlYnVnZ2VycyBjYW4gZmluZCB0aGVtLlxuICAgIC8vIFR1cm4gb2ZmIGlubGluZSBtYXBzL3NvdXJjZXMgc28gYnVuZGxlcnMgKFJvbGx1cCkgY2FuIGNvbnRyb2wgd2hldGhlciBtYXBzIGFyZSBpbmxpbmVkIG9yIHdyaXR0ZW4gZXh0ZXJuYWxseS5cbiAgICB0c0NvbmZpZy5vcHRpb25zLmlubGluZVNvdXJjZU1hcCA9IGZhbHNlO1xuICAgIHRzQ29uZmlnLm9wdGlvbnMuaW5saW5lU291cmNlcyA9IGZhbHNlO1xuICAgIHRzQ29uZmlnLm9wdGlvbnMuc291cmNlTWFwID0gdHJ1ZTtcblxuICAgIGNvbnN0IHByb2dyYW0gPSB0cy5jcmVhdGVQcm9ncmFtKHRzQ29uZmlnLmZpbGVOYW1lcywgdHNDb25maWcub3B0aW9ucyk7XG4gICAgdGhpcy5wcmVDaGVja0RpYWdub3N0aWNzKHByb2dyYW0pO1xuICAgIGxvZy52ZXJib3NlKFxuICAgICAgYFR5cGVTY3JpcHQgY2hlY2tzIHBhc3NlZCAoJHtidW5kbGUgPyBcImJ1bmRsZVwiIDogXCJub3JtYWxcIn0gbW9kZSkuYFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJ1aWxkVHMoaXNEZXY6IGJvb2xlYW4sIG1vZGU6IE1vZGVzLCBidW5kbGUgPSBmYWxzZSkge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLmJ1aWxkVHMpO1xuICAgIGxvZy5pbmZvKFxuICAgICAgYEJ1aWxkaW5nICR7dGhpcy5wa2dOYW1lfSAke3RoaXMucGtnVmVyc2lvbn0gbW9kdWxlICgke21vZGV9KSBpbiAke2lzRGV2ID8gXCJkZXZcIiA6IFwicHJvZFwifSBtb2RlLi4uYFxuICAgICk7XG4gICAgbGV0IHRzQ29uZmlnO1xuICAgIHRyeSB7XG4gICAgICB0c0NvbmZpZyA9IHRoaXMucmVhZENvbmZpZ0ZpbGUoXCIuL3RzY29uZmlnLmpzb25cIik7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gcGFyc2UgdHNjb25maWcuanNvbjogJHtlfWApO1xuICAgIH1cblxuICAgIGlmIChidW5kbGUpIHtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMubW9kdWxlID0gTW9kdWxlS2luZC5BTUQ7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLm91dERpciA9IFwiZGlzdFwiO1xuICAgICAgdHNDb25maWcub3B0aW9ucy5pc29sYXRlZE1vZHVsZXMgPSBmYWxzZTtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMub3V0RmlsZSA9IHRoaXMucGtnTmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdHNDb25maWcub3B0aW9ucy5vdXREaXIgPSBgbGliJHttb2RlID09PSBNb2Rlcy5FU00gPyBcIi9lc21cIiA6IFwiXCJ9YDtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMubW9kdWxlID1cbiAgICAgICAgbW9kZSA9PT0gTW9kZXMuRVNNID8gTW9kdWxlS2luZC5FUzIwMjIgOiBNb2R1bGVLaW5kLkNvbW1vbkpTO1xuICAgIH1cblxuICAgIC8vIEFsd2F5cyBlbWl0IGlubGluZSBzb3VyY2UgbWFwcyBmcm9tIHRzYyAoYnVuZGxlciB3aWxsIGVtaXQgZXh0ZXJuYWwgbWFwcyBmb3IgcHJvZHVjdGlvbiBidW5kbGVzKS5cbiAgICAvLyBGb3IgZGV2IGJ1aWxkcyB3ZSB3YW50IFR5cGVTY3JpcHQgdG8gZW1pdCBpbmxpbmUgc291cmNlIG1hcHMgc28gbm8gc2VwYXJhdGUgLm1hcCBmaWxlcyBhcmUgcHJvZHVjZWQuXG4gICAgLy8gRm9yIHByb2R1Y3Rpb24gd2UgZW1pdCBleHRlcm5hbCBzb3VyY2UgbWFwcyBzbyB0aGUgYnVuZGxlciBjYW4gZnVydGhlciB0cmFuc2Zvcm0gYW5kIGVtaXQgdGhlbS5cbiAgICBpZiAoaXNEZXYpIHtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMuaW5saW5lU291cmNlTWFwID0gdHJ1ZTtcbiAgICAgIHRzQ29uZmlnLm9wdGlvbnMuaW5saW5lU291cmNlcyA9IHRydWU7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLnNvdXJjZU1hcCA9IGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLmlubGluZVNvdXJjZU1hcCA9IGZhbHNlO1xuICAgICAgdHNDb25maWcub3B0aW9ucy5pbmxpbmVTb3VyY2VzID0gZmFsc2U7XG4gICAgICB0c0NvbmZpZy5vcHRpb25zLnNvdXJjZU1hcCA9IHRydWU7XG4gICAgfVxuXG4gICAgLy8gRm9yIHByb2R1Y3Rpb24gYnVpbGRzIHdlIHN0aWxsIGtlZXAgVHlwZVNjcmlwdCBjb21tZW50cyAocmVtb3ZlQ29tbWVudHM9ZmFsc2UgaW4gdHNjb25maWcpXG4gICAgLy8gQnVuZGxlci90ZXJzZXIgd2lsbCBzdHJpcCBjb21tZW50cyBmb3IgcHJvZHVjdGlvbiBidW5kbGVzIGFzIHJlcXVlc3RlZC5cblxuICAgIGNvbnN0IHByb2dyYW0gPSB0cy5jcmVhdGVQcm9ncmFtKHRzQ29uZmlnLmZpbGVOYW1lcywgdHNDb25maWcub3B0aW9ucyk7XG5cbiAgICBjb25zdCB0cmFuc2Zvcm1hdGlvbnM6IHsgYmVmb3JlPzogYW55W10gfSA9IHt9O1xuICAgIGlmIChtb2RlID09PSBNb2Rlcy5DSlMpIHtcbiAgICAgIHRyYW5zZm9ybWF0aW9ucy5iZWZvcmUgPSBbY2pzMlRyYW5zZm9ybWVyKFwiLmNqc1wiKV07XG4gICAgfSBlbHNlIGlmIChtb2RlID09PSBNb2Rlcy5FU00pIHtcbiAgICAgIHRyYW5zZm9ybWF0aW9ucy5iZWZvcmUgPSBbY2pzMlRyYW5zZm9ybWVyKFwiLmpzXCIpXTtcbiAgICB9XG5cbiAgICBjb25zdCBlbWl0UmVzdWx0OiBFbWl0UmVzdWx0ID0gcHJvZ3JhbS5lbWl0KFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgdHJhbnNmb3JtYXRpb25zXG4gICAgKTtcblxuICAgIGNvbnN0IGFsbERpYWdub3N0aWNzID0gdHNcbiAgICAgIC5nZXRQcmVFbWl0RGlhZ25vc3RpY3MocHJvZ3JhbSlcbiAgICAgIC5jb25jYXQoZW1pdFJlc3VsdC5kaWFnbm9zdGljcyk7XG5cbiAgICB0aGlzLmV2YWxEaWFnbm9zdGljcyhhbGxEaWFnbm9zdGljcyk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJ1aWxkKGlzRGV2OiBib29sZWFuLCBtb2RlOiBNb2RlcywgYnVuZGxlID0gZmFsc2UpIHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5idWlsZCk7XG4gICAgYXdhaXQgdGhpcy5idWlsZFRzKGlzRGV2LCBtb2RlLCBidW5kbGUpO1xuXG4gICAgbG9nLnZlcmJvc2UoXG4gICAgICBgTW9kdWxlICR7dGhpcy5wa2dOYW1lfSAke3RoaXMucGtnVmVyc2lvbn0gKCR7bW9kZX0pIGJ1aWx0IGluICR7aXNEZXYgPyBcImRldlwiIDogXCJwcm9kXCJ9IG1vZGUuLi5gXG4gICAgKTtcbiAgICBpZiAobW9kZSA9PT0gTW9kZXMuQ0pTICYmICFidW5kbGUpIHtcbiAgICAgIGNvbnN0IGZpbGVzID0gZ2V0QWxsRmlsZXMoXG4gICAgICAgIFwibGliXCIsXG4gICAgICAgIChmaWxlKSA9PiBmaWxlLmVuZHNXaXRoKFwiLmpzXCIpICYmICFmaWxlLmluY2x1ZGVzKFwiL2VzbS9cIilcbiAgICAgICk7XG5cbiAgICAgIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgICAgICBsb2cudmVyYm9zZShgUGF0Y2hpbmcgJHtmaWxlfSdzIGNqcyBpbXBvcnRzLi4uYCk7XG4gICAgICAgIGNvbnN0IGYgPSBmaWxlLnJlcGxhY2UoXCIuanNcIiwgXCIuY2pzXCIpO1xuICAgICAgICBhd2FpdCByZW5hbWVGaWxlKGZpbGUsIGYpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ29waWVzIGFzc2V0cyB0byB0aGUgYnVpbGQgb3V0cHV0IGRpcmVjdG9yeS5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgY2hlY2tzIGZvciB0aGUgZXhpc3RlbmNlIG9mIGFuICdhc3NldHMnIGRpcmVjdG9yeSBpbiB0aGUgc291cmNlXG4gICAqIGFuZCBjb3BpZXMgaXQgdG8gdGhlIGFwcHJvcHJpYXRlIGJ1aWxkIG91dHB1dCBkaXJlY3RvcnkgKGxpYiBvciBkaXN0KS5cbiAgICogQHBhcmFtIHtNb2Rlc30gbW9kZSAtIFRoZSBidWlsZCBtb2RlIChDSlMgb3IgRVNNKS5cbiAgICovXG4gIGNvcHlBc3NldHMobW9kZTogTW9kZXMpIHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5jb3B5QXNzZXRzKTtcbiAgICBsZXQgaGFzQXNzZXRzID0gZmFsc2U7XG4gICAgdHJ5IHtcbiAgICAgIGhhc0Fzc2V0cyA9IGZzLnN0YXRTeW5jKFwiLi9zcmMvYXNzZXRzXCIpLmlzRGlyZWN0b3J5KCk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgcmV0dXJuIGxvZy52ZXJib3NlKGBObyBhc3NldHMgZm91bmQgaW4gLi9zcmMvYXNzZXRzIHRvIGNvcHlgKTtcbiAgICB9XG4gICAgaWYgKGhhc0Fzc2V0cylcbiAgICAgIGNvcHlGaWxlKFxuICAgICAgICBcIi4vc3JjL2Fzc2V0c1wiLFxuICAgICAgICBgLi8ke21vZGUgPT09IE1vZGVzLkNKUyA/IFwibGliXCIgOiBcImRpc3RcIn0vYXNzZXRzYFxuICAgICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQnVuZGxlcyB0aGUgcHJvamVjdCB1c2luZyBSb2xsdXAuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIGNvbmZpZ3VyZXMgYW5kIHJ1bnMgUm9sbHVwIHRvIGJ1bmRsZSB0aGUgcHJvamVjdC4gSXQgaGFuZGxlc1xuICAgKiBkaWZmZXJlbnQgbW9kdWxlIGZvcm1hdHMsIGRldmVsb3BtZW50IGFuZCBwcm9kdWN0aW9uIGJ1aWxkcywgYW5kIGV4dGVybmFsIGRlcGVuZGVuY2llcy5cbiAgICogQHBhcmFtIHtNb2Rlc30gbW9kZSAtIFRoZSBtb2R1bGUgZm9ybWF0IChDSlMgb3IgRVNNKS5cbiAgICogQHBhcmFtIHtib29sZWFufSBpc0RldiAtIFdoZXRoZXIgaXQncyBhIGRldmVsb3BtZW50IGJ1aWxkLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzTGliIC0gV2hldGhlciBpdCdzIGEgbGlicmFyeSBidWlsZC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtlbnRyeUZpbGU9XCJzcmMvaW5kZXgudHNcIl0gLSBUaGUgZW50cnkgZmlsZSBmb3IgdGhlIGJ1bmRsZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtuYW1lT3ZlcnJpZGU9dGhpcy5wa2dOYW1lXSAtIFRoZSBuYW1lIG9mIHRoZSBvdXRwdXQgYnVuZGxlLlxuICAgKiBAcGFyYW0ge3N0cmluZ3xzdHJpbmdbXX0gW2V4dGVybmFsc0FyZ10gLSBBIGxpc3Qgb2YgZXh0ZXJuYWwgZGVwZW5kZW5jaWVzLlxuICAgKiBAcGFyYW0ge3N0cmluZ3xzdHJpbmdbXX0gW2luY2x1ZGVBcmddIC0gQSBsaXN0IG9mIGRlcGVuZGVuY2llcyB0byBpbmNsdWRlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIGJ1bmRsZShcbiAgICBtb2RlOiBNb2RlcyxcbiAgICBpc0RldjogYm9vbGVhbixcbiAgICBpc0xpYjogYm9vbGVhbixcbiAgICBlbnRyeUZpbGU6IHN0cmluZyA9IFwiLi9zcmMvaW5kZXgudHNcIixcbiAgICBuYW1lT3ZlcnJpZGU6IHN0cmluZyA9IHRoaXMucGtnTmFtZSxcbiAgICBleHRlcm5hbHNBcmc/OiBzdHJpbmcgfCBzdHJpbmdbXSxcbiAgICBpbmNsdWRlQXJnOiBzdHJpbmcgfCBzdHJpbmdbXSA9IFtcbiAgICAgIFwicHJvbXB0c1wiLFxuICAgICAgXCJzdHlsZWQtc3RyaW5nLWJ1aWxkZXJcIixcbiAgICAgIFwidHlwZWQtb2JqZWN0LWFjY3VtdWxhdG9yXCIsXG4gICAgICBcIkBkZWNhZi10cy9sb2dnaW5nXCIsXG4gICAgXVxuICApIHtcbiAgICAvLyBSdW4gYSBUeXBlU2NyaXB0LW9ubHkgZGlhZ25vc3RpYyBjaGVjayBmb3IgdGhlIGJ1bmRsaW5nIGNvbmZpZ3VyYXRpb24gYW5kIGZhaWwgZmFzdCBvbiBhbnkgZXJyb3JzLlxuICAgIGF3YWl0IHRoaXMuY2hlY2tUc0RpYWdub3N0aWNzKGlzRGV2LCBtb2RlLCB0cnVlKTtcbiAgICBjb25zdCBpc0VzbSA9IG1vZGUgPT09IE1vZGVzLkVTTTtcbiAgICBjb25zdCBwa2dOYW1lID0gdGhpcy5wa2dOYW1lO1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nO1xuXG4gICAgLy8gbm9ybWFsaXplIGluY2x1ZGUgYW5kIGV4dGVybmFsc1xuICAgIGNvbnN0IGluY2x1ZGUgPSBBcnJheS5mcm9tKFxuICAgICAgbmV3IFNldChbLi4uKHBhcnNlTGlzdChpbmNsdWRlQXJnKSBhcyBzdHJpbmdbXSldKVxuICAgICk7XG4gICAgbGV0IGV4dGVybmFsc0xpc3QgPSBwYXJzZUxpc3QoZXh0ZXJuYWxzQXJnKTtcbiAgICBpZiAoZXh0ZXJuYWxzTGlzdC5sZW5ndGggPT09IDApIHtcbiAgICAgIC8vIGlmIG5vIGV4dGVybmFscyBzcGVjaWZpZWQsIGxpc3QgdG9wLWxldmVsIHBhY2thZ2VzIGluIG5vZGVfbW9kdWxlcyAoZXhwYW5kIHNjb3BlcylcbiAgICAgIHRyeSB7XG4gICAgICAgIGV4dGVybmFsc0xpc3QgPSBsaXN0Tm9kZU1vZHVsZXNQYWNrYWdlcyhcbiAgICAgICAgICBwYXRoLmpvaW4ocHJvY2Vzcy5jd2QoKSwgXCJub2RlX21vZHVsZXNcIilcbiAgICAgICAgKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBmYWxsYmFjayB0byBwYWNrYWdlLmpzb24gZGVwZW5kZW5jaWVzIGlmIGxpc3RpbmcgZmFpbHMgb3IgeWllbGRzIG5vdGhpbmdcbiAgICAgIH1cbiAgICAgIGlmICghZXh0ZXJuYWxzTGlzdCB8fCBleHRlcm5hbHNMaXN0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBleHRlcm5hbHNMaXN0ID0gZ2V0UGFja2FnZURlcGVuZGVuY2llcygpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGV4dCA9IEFycmF5LmZyb20oXG4gICAgICBuZXcgU2V0KFtcbiAgICAgICAgLy8gYnVpbHRpbnMgYW5kIGFsd2F5cyBleHRlcm5hbCBydW50aW1lIGRlcHNcbiAgICAgICAgLi4uKGZ1bmN0aW9uIGJ1aWx0aW5MaXN0KCk6IHN0cmluZ1tdIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShidWlsdGluTW9kdWxlcykgPyBidWlsdGluTW9kdWxlcyA6IFtdXG4gICAgICAgICAgICApIGFzIHN0cmluZ1tdO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgLy8gZmFsbGJhY2sgdG8gYSByZWFzb25hYmxlIHN1YnNldCBpZiBgYnVpbHRpbk1vZHVsZXNgIGlzIHVuYXZhaWxhYmxlXG4gICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICBcImZzXCIsXG4gICAgICAgICAgICAgIFwicGF0aFwiLFxuICAgICAgICAgICAgICBcInByb2Nlc3NcIixcbiAgICAgICAgICAgICAgXCJjaGlsZF9wcm9jZXNzXCIsXG4gICAgICAgICAgICAgIFwidXRpbFwiLFxuICAgICAgICAgICAgICBcImh0dHBzXCIsXG4gICAgICAgICAgICAgIFwiaHR0cFwiLFxuICAgICAgICAgICAgICBcIm9zXCIsXG4gICAgICAgICAgICAgIFwic3RyZWFtXCIsXG4gICAgICAgICAgICAgIFwiY3J5cHRvXCIsXG4gICAgICAgICAgICAgIFwiemxpYlwiLFxuICAgICAgICAgICAgICBcIm5ldFwiLFxuICAgICAgICAgICAgICBcInRsc1wiLFxuICAgICAgICAgICAgICBcInVybFwiLFxuICAgICAgICAgICAgICBcInF1ZXJ5c3RyaW5nXCIsXG4gICAgICAgICAgICAgIFwiYXNzZXJ0XCIsXG4gICAgICAgICAgICAgIFwiZXZlbnRzXCIsXG4gICAgICAgICAgICAgIFwidHR5XCIsXG4gICAgICAgICAgICAgIFwiZG5zXCIsXG4gICAgICAgICAgICAgIFwicXVlcnlzdHJpbmdcIixcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpLFxuICAgICAgICAuLi5leHRlcm5hbHNMaXN0LFxuICAgICAgXSlcbiAgICApO1xuXG4gICAgLy8gRm9yIHBsdWdpbi10eXBlc2NyaXB0IHdlIHdhbnQgaXQgdG8gZW1pdCBzb3VyY2UgbWFwcyAobm90IGlubGluZSkgc28gUm9sbHVwIGNhblxuICAgIC8vIGRlY2lkZSB3aGV0aGVyIHRvIGlubGluZSBvciBlbWl0IGV4dGVybmFsIGZpbGVzLiBUaGUgUm9sbHVwIG91dHB1dC5zb3VyY2VtYXBcbiAgICAvLyBjb250cm9scyBmaW5hbCBtYXAgcGxhY2VtZW50LiBEbyBOT1Qgc2V0IGEgbm9uLXN0YW5kYXJkIGBzb3VyY2VtYXBgIGZpZWxkIG9uXG4gICAgLy8gdGhlIHJvbGx1cCBpbnB1dCBvcHRpb25zIChSb2xsdXAgd2lsbCByZWplY3QgaXQpLlxuICAgIGNvbnN0IHJvbGx1cFNvdXJjZU1hcE91dHB1dDogZmFsc2UgfCB0cnVlIHwgXCJpbmxpbmVcIiB8IFwiaGlkZGVuXCIgPSBpc0RldlxuICAgICAgPyBcImlubGluZVwiXG4gICAgICA6IHRydWU7XG5cbiAgICBjb25zdCBwbHVnaW5zID0gW1xuICAgICAgdHlwZXNjcmlwdCh7XG4gICAgICAgIGNvbXBpbGVyT3B0aW9uczoge1xuICAgICAgICAgIG1vZHVsZTogXCJlc25leHRcIixcbiAgICAgICAgICBkZWNsYXJhdGlvbjogZmFsc2UsXG4gICAgICAgICAgb3V0RGlyOiBpc0xpYiA/IFwiYmluXCIgOiBcImRpc3RcIixcbiAgICAgICAgICAvLyBGb3IgZGV2IGJ1bmRsZXMgZW1pdCBpbmxpbmUgc291cmNlIG1hcHMgKG5vIHNlcGFyYXRlIC5tYXAgZmlsZXMpLlxuICAgICAgICAgIC8vIEZvciBwcm9kIGJ1bmRsZXMgZW1pdCBleHRlcm5hbCBtYXBzIHNvIFJvbGx1cCBjYW4gd3JpdGUgdGhlbSB0byBkaXNrLlxuICAgICAgICAgIHNvdXJjZU1hcDogaXNEZXYgPyBmYWxzZSA6IHRydWUsXG4gICAgICAgICAgaW5saW5lU291cmNlTWFwOiBpc0RldiA/IHRydWUgOiBmYWxzZSxcbiAgICAgICAgICBpbmxpbmVTb3VyY2VzOiBpc0RldiA/IHRydWUgOiBmYWxzZSxcbiAgICAgICAgfSxcbiAgICAgICAgaW5jbHVkZTogW1wic3JjLyoqLyoudHNcIl0sXG4gICAgICAgIGV4Y2x1ZGU6IFtcIm5vZGVfbW9kdWxlc1wiLCBcIioqLyouc3BlYy50c1wiXSxcbiAgICAgICAgdHNjb25maWc6IFwiLi90c2NvbmZpZy5qc29uXCIsXG4gICAgICB9KSxcbiAgICAgIGpzb24oKSxcbiAgICBdO1xuXG4gICAgaWYgKGlzTGliKSB7XG4gICAgICBwbHVnaW5zLnB1c2goXG4gICAgICAgIGNvbW1vbmpzKHtcbiAgICAgICAgICBpbmNsdWRlOiBbXSxcbiAgICAgICAgICBleGNsdWRlOiBleHRlcm5hbHNMaXN0LFxuICAgICAgICB9KSxcbiAgICAgICAgbm9kZVJlc29sdmUoe1xuICAgICAgICAgIHJlc29sdmVPbmx5OiBpbmNsdWRlLFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBwcm9kdWN0aW9uIG1pbmlmaWNhdGlvbjogYWRkIHRlcnNlciBsYXN0IHNvIGl0IHNlZXMgcHJpb3Igc291cmNlIG1hcHNcbiAgICB0cnkge1xuICAgICAgY29uc3QgdGVyc2VyTW9kOiBhbnkgPSBhd2FpdCBpbXBvcnQoXCJAcm9sbHVwL3BsdWdpbi10ZXJzZXJcIik7XG4gICAgICBjb25zdCB0ZXJzZXJGbiA9XG4gICAgICAgICh0ZXJzZXJNb2QgJiYgdGVyc2VyTW9kLnRlcnNlcikgfHwgdGVyc2VyTW9kLmRlZmF1bHQgfHwgdGVyc2VyTW9kO1xuXG4gICAgICBjb25zdCB0ZXJzZXJPcHRpb25zRGV2OiBhbnkgPSB7XG4gICAgICAgIHBhcnNlOiB7IGVjbWE6IDIwMjAgfSxcbiAgICAgICAgY29tcHJlc3M6IGZhbHNlLFxuICAgICAgICBtYW5nbGU6IGZhbHNlLFxuICAgICAgICBmb3JtYXQ6IHtcbiAgICAgICAgICBjb21tZW50czogZmFsc2UsXG4gICAgICAgICAgYmVhdXRpZnk6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0ZXJzZXJPcHRpb25zUHJvZDogYW55ID0ge1xuICAgICAgICBwYXJzZTogeyBlY21hOiAyMDIwIH0sXG4gICAgICAgIGNvbXByZXNzOiB7XG4gICAgICAgICAgZWNtYTogMjAyMCxcbiAgICAgICAgICBwYXNzZXM6IDUsXG4gICAgICAgICAgZHJvcF9jb25zb2xlOiB0cnVlLFxuICAgICAgICAgIGRyb3BfZGVidWdnZXI6IHRydWUsXG4gICAgICAgICAgdG9wbGV2ZWw6IHRydWUsXG4gICAgICAgICAgbW9kdWxlOiBpc0VzbSxcbiAgICAgICAgICB1bnNhZmU6IHRydWUsXG4gICAgICAgICAgdW5zYWZlX2Fycm93czogdHJ1ZSxcbiAgICAgICAgICB1bnNhZmVfY29tcHM6IHRydWUsXG4gICAgICAgICAgY29sbGFwc2VfdmFyczogdHJ1ZSxcbiAgICAgICAgICByZWR1Y2VfZnVuY3M6IHRydWUsXG4gICAgICAgICAgcmVkdWNlX3ZhcnM6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICAgIG1hbmdsZToge1xuICAgICAgICAgIHRvcGxldmVsOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgICBmb3JtYXQ6IHtcbiAgICAgICAgICBjb21tZW50czogZmFsc2UsXG4gICAgICAgICAgYXNjaWlfb25seTogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgICAgdG9wbGV2ZWw6IHRydWUsXG4gICAgICB9O1xuXG4gICAgICBwbHVnaW5zLnB1c2godGVyc2VyRm4oaXNEZXYgPyB0ZXJzZXJPcHRpb25zRGV2IDogdGVyc2VyT3B0aW9uc1Byb2QpKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIGlmIHRlcnNlciBpc24ndCBhdmFpbGFibGUsIGlnbm9yZVxuICAgIH1cblxuICAgIGNvbnN0IGlucHV0OiBJbnB1dE9wdGlvbnMgPSB7XG4gICAgICBpbnB1dDogZW50cnlGaWxlLFxuICAgICAgcGx1Z2luczogcGx1Z2lucyxcbiAgICAgIGV4dGVybmFsOiBleHQsXG4gICAgICBvbndhcm46IHVuZGVmaW5lZCxcbiAgICAgIC8vIGVuYWJsZSB0cmVlLXNoYWtpbmcgZm9yIHByb2R1Y3Rpb24gYnVuZGxlc1xuICAgICAgdHJlZXNoYWtlOiAhaXNEZXYsXG4gICAgfSBhcyBhbnk7XG5cbiAgICAvLyBwcmVwYXJlIG91dHB1dCBnbG9iYWxzIG1hcHBpbmcgZm9yIGV4dGVybmFsc1xuICAgIGNvbnN0IGdsb2JhbHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICAvLyBpbmNsdWRlIGFsbCBleHRlcm5hbHMgYW5kIGJ1aWx0aW5zIChleHQpIHNvIFJvbGx1cCB3b24ndCBndWVzcyBuYW1lcyBmb3IgYnVpbHRpbnNcbiAgICBleHQuZm9yRWFjaCgoZSkgPT4ge1xuICAgICAgZ2xvYmFsc1tlXSA9IHBhY2thZ2VUb0dsb2JhbChlKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IG91dHB1dHM6IE91dHB1dE9wdGlvbnNbXSA9IFtcbiAgICAgIHtcbiAgICAgICAgZmlsZTogYCR7aXNMaWIgPyBcImJpbi9cIiA6IFwiZGlzdC9cIn0ke25hbWVPdmVycmlkZSA/IG5hbWVPdmVycmlkZSA6IGAuYnVuZGxlLiR7IWlzRGV2ID8gXCJtaW5cIiA6IFwiXCJ9YH0ke2lzRXNtID8gXCIuanNcIiA6IFwiLmNqc1wifWAsXG4gICAgICAgIGZvcm1hdDogaXNMaWIgPyBcImNqc1wiIDogaXNFc20gPyBcImVzbVwiIDogXCJ1bWRcIixcbiAgICAgICAgbmFtZTogcGtnTmFtZSxcbiAgICAgICAgZXNNb2R1bGU6IGlzRXNtLFxuICAgICAgICAvLyBvdXRwdXQgc291cmNlbWFwOiBpbmxpbmUgZm9yIGRldiwgZXh0ZXJuYWwgZm9yIHByb2RcbiAgICAgICAgc291cmNlbWFwOiByb2xsdXBTb3VyY2VNYXBPdXRwdXQsXG4gICAgICAgIGdsb2JhbHM6IGdsb2JhbHMsXG4gICAgICAgIGV4cG9ydHM6IFwiYXV0b1wiLFxuICAgICAgfSxcbiAgICBdO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGJ1bmRsZSA9IGF3YWl0IHJvbGx1cChpbnB1dCBhcyBhbnkpO1xuICAgICAgLy8gb25seSBsb2cgd2F0Y2hGaWxlcyBhdCB2ZXJib3NlIGxldmVsIHRvIGF2b2lkIG5vaXN5IGNvbnNvbGUgb3V0cHV0XG4gICAgICBsb2cudmVyYm9zZShidW5kbGUud2F0Y2hGaWxlcyk7XG4gICAgICBhc3luYyBmdW5jdGlvbiBnZW5lcmF0ZU91dHB1dHMoYnVuZGxlOiBSb2xsdXBCdWlsZCkge1xuICAgICAgICBmb3IgKGNvbnN0IG91dHB1dE9wdGlvbnMgb2Ygb3V0cHV0cykge1xuICAgICAgICAgIGF3YWl0IGJ1bmRsZS53cml0ZShvdXRwdXRPcHRpb25zKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBhd2FpdCBnZW5lcmF0ZU91dHB1dHMoYnVuZGxlKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBidW5kbGU6ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJ1aWxkQnlFbnYoXG4gICAgZW50cnlGaWxlOiBzdHJpbmcgPSBcIi4vc3JjL2luZGV4LnRzXCIsXG4gICAgaXNEZXY6IGJvb2xlYW4sXG4gICAgbW9kZTogQnVpbGRNb2RlID0gQnVpbGRNb2RlLkFMTCxcbiAgICBpbmNsdWRlc0FyZz86IHN0cmluZyB8IHN0cmluZ1tdLFxuICAgIGV4dGVybmFsc0FyZz86IHN0cmluZyB8IHN0cmluZ1tdXG4gICkge1xuICAgIC8vIG5vdGU6IGluY2x1ZGVzIGFuZCBleHRlcm5hbHMgd2lsbCBiZSBwYXNzZWQgdGhyb3VnaCBmcm9tIHJ1bigpIGludG8gdGhpcyBtZXRob2QgYnkgY2FsbGVyc1xuICAgIHRyeSB7XG4gICAgICBkZWxldGVQYXRoKFwibGliXCIpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGRlbGV0ZVBhdGgoXCJkaXN0XCIpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICB9XG5cbiAgICBpZiAoW0J1aWxkTW9kZS5BTEwsIEJ1aWxkTW9kZS5CVUlMRF0uaW5jbHVkZXMobW9kZSkpIHtcbiAgICAgIGZzLm1rZGlyU3luYyhcImxpYlwiKTtcbiAgICAgIGF3YWl0IHRoaXMuYnVpbGQoaXNEZXYsIE1vZGVzLkVTTSk7XG4gICAgICBhd2FpdCB0aGlzLmJ1aWxkKGlzRGV2LCBNb2Rlcy5DSlMpO1xuICAgICAgdGhpcy5wYXRjaEZpbGVzKFwibGliXCIpO1xuICAgIH1cblxuICAgIGlmIChbQnVpbGRNb2RlLkFMTCwgQnVpbGRNb2RlLkJVTkRMRV0uaW5jbHVkZXMobW9kZSkpIHtcbiAgICAgIGZzLm1rZGlyU3luYyhcImRpc3RcIik7XG4gICAgICBhd2FpdCB0aGlzLmJ1bmRsZShcbiAgICAgICAgTW9kZXMuRVNNLFxuICAgICAgICBpc0RldixcbiAgICAgICAgZmFsc2UsXG4gICAgICAgIGVudHJ5RmlsZSB8fCBcIi4vc3JjL2luZGV4LnRzXCIsXG4gICAgICAgIHRoaXMucGtnTmFtZSxcbiAgICAgICAgZXh0ZXJuYWxzQXJnLFxuICAgICAgICBpbmNsdWRlc0FyZ1xuICAgICAgKTtcbiAgICAgIGF3YWl0IHRoaXMuYnVuZGxlKFxuICAgICAgICBNb2Rlcy5DSlMsXG4gICAgICAgIGlzRGV2LFxuICAgICAgICBmYWxzZSxcbiAgICAgICAgZW50cnlGaWxlIHx8IFwiLi9zcmMvaW5kZXgudHNcIixcbiAgICAgICAgdGhpcy5wa2dOYW1lLFxuICAgICAgICBleHRlcm5hbHNBcmcsXG4gICAgICAgIGluY2x1ZGVzQXJnXG4gICAgICApO1xuICAgICAgdGhpcy5wYXRjaEZpbGVzKFwiZGlzdFwiKTtcbiAgICB9XG5cbiAgICB0aGlzLmNvcHlBc3NldHMoTW9kZXMuQ0pTKTtcbiAgICB0aGlzLmNvcHlBc3NldHMoTW9kZXMuRVNNKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQnVpbGRzIHRoZSBwcm9qZWN0IGZvciBkZXZlbG9wbWVudC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgcnVucyB0aGUgYnVpbGQgcHJvY2VzcyB3aXRoIGRldmVsb3BtZW50LXNwZWNpZmljIGNvbmZpZ3VyYXRpb25zLlxuICAgKiBAcGFyYW0ge0J1aWxkTW9kZX0gW21vZGU9QnVpbGRNb2RlLkFMTF0gLSBUaGUgYnVpbGQgbW9kZSAoYnVpbGQsIGJ1bmRsZSwgb3IgYWxsKS5cbiAgICogQHBhcmFtIHtzdHJpbmd8c3RyaW5nW119IFtpbmNsdWRlc0FyZ10gLSBBIGxpc3Qgb2YgZGVwZW5kZW5jaWVzIHRvIGluY2x1ZGUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfHN0cmluZ1tdfSBbZXh0ZXJuYWxzQXJnXSAtIEEgbGlzdCBvZiBleHRlcm5hbCBkZXBlbmRlbmNpZXMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgYnVpbGREZXYoXG4gICAgZW50cnlGaWxlOiBzdHJpbmcgPSBcIi4vc3JjL2luZGV4LnRzXCIsXG4gICAgbW9kZTogQnVpbGRNb2RlID0gQnVpbGRNb2RlLkFMTCxcbiAgICBpbmNsdWRlc0FyZz86IHN0cmluZyB8IHN0cmluZ1tdLFxuICAgIGV4dGVybmFsc0FyZz86IHN0cmluZyB8IHN0cmluZ1tdXG4gICkge1xuICAgIHJldHVybiB0aGlzLmJ1aWxkQnlFbnYoZW50cnlGaWxlLCB0cnVlLCBtb2RlLCBpbmNsdWRlc0FyZywgZXh0ZXJuYWxzQXJnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQnVpbGRzIHRoZSBwcm9qZWN0IGZvciBwcm9kdWN0aW9uLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBydW5zIHRoZSBidWlsZCBwcm9jZXNzIHdpdGggcHJvZHVjdGlvbi1zcGVjaWZpYyBjb25maWd1cmF0aW9ucyxcbiAgICogaW5jbHVkaW5nIG1pbmlmaWNhdGlvbiBhbmQgb3RoZXIgb3B0aW1pemF0aW9ucy5cbiAgICogQHBhcmFtIHtCdWlsZE1vZGV9IFttb2RlPUJ1aWxkTW9kZS5BTExdIC0gVGhlIGJ1aWxkIG1vZGUgKGJ1aWxkLCBidW5kbGUsIG9yIGFsbCkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfHN0cmluZ1tdfSBbaW5jbHVkZXNBcmddIC0gQSBsaXN0IG9mIGRlcGVuZGVuY2llcyB0byBpbmNsdWRlLlxuICAgKiBAcGFyYW0ge3N0cmluZ3xzdHJpbmdbXX0gW2V4dGVybmFsc0FyZ10gLSBBIGxpc3Qgb2YgZXh0ZXJuYWwgZGVwZW5kZW5jaWVzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIGJ1aWxkUHJvZChcbiAgICBlbnRyeUZpbGU6IHN0cmluZyA9IFwiLi9zcmMvaW5kZXgudHNcIixcbiAgICBtb2RlOiBCdWlsZE1vZGUgPSBCdWlsZE1vZGUuQUxMLFxuICAgIGluY2x1ZGVzQXJnPzogc3RyaW5nIHwgc3RyaW5nW10sXG4gICAgZXh0ZXJuYWxzQXJnPzogc3RyaW5nIHwgc3RyaW5nW11cbiAgKSB7XG4gICAgcmV0dXJuIHRoaXMuYnVpbGRCeUVudihlbnRyeUZpbGUsIGZhbHNlLCBtb2RlLCBpbmNsdWRlc0FyZywgZXh0ZXJuYWxzQXJnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2VuZXJhdGVzIHRoZSBwcm9qZWN0IGRvY3VtZW50YXRpb24uXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIHVzZXMgSlNEb2MgYW5kIG90aGVyIHRvb2xzIHRvIGdlbmVyYXRlIEhUTUwgZG9jdW1lbnRhdGlvbiBmb3IgdGhlIHByb2plY3QuXG4gICAqIEl0IGFsc28gcGF0Y2hlcyB0aGUgUkVBRE1FLm1kIGZpbGUgd2l0aCB2ZXJzaW9uIGFuZCBwYWNrYWdlIHNpemUgaW5mb3JtYXRpb24uXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgYnVpbGREb2NzKCkge1xuICAgIGF3YWl0IHJ1bkNvbW1hbmQoYG5wbSBpbnN0YWxsIGJldHRlci1kb2NzIHRhZmZ5ZGJgKS5wcm9taXNlO1xuICAgIGF3YWl0IHJ1bkNvbW1hbmQoYG5weCBtYXJrZG93bi1pbmNsdWRlIC4vd29ya2RvY3MvcmVhZG1lLW1kLmpzb25gKS5wcm9taXNlO1xuICAgIGF3YWl0IHJ1bkNvbW1hbmQoXG4gICAgICBgbnB4IGpzZG9jIC1jIC4vd29ya2RvY3MvanNkb2NzLmpzb24gLXQgLi9ub2RlX21vZHVsZXMvYmV0dGVyLWRvY3NgXG4gICAgKS5wcm9taXNlO1xuICAgIGF3YWl0IHJ1bkNvbW1hbmQoYG5wbSByZW1vdmUgYmV0dGVyLWRvY3MgdGFmZnlkYmApLnByb21pc2U7XG4gICAgW1xuICAgICAge1xuICAgICAgICBzcmM6IFwid29ya2RvY3MvYXNzZXRzXCIsXG4gICAgICAgIGRlc3Q6IFwiLi9kb2NzL3dvcmtkb2NzL2Fzc2V0c1wiLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgc3JjOiBcIndvcmtkb2NzL3JlcG9ydHMvY292ZXJhZ2VcIixcbiAgICAgICAgZGVzdDogXCIuL2RvY3Mvd29ya2RvY3MvcmVwb3J0cy9jb3ZlcmFnZVwiLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgc3JjOiBcIndvcmtkb2NzL3JlcG9ydHMvaHRtbFwiLFxuICAgICAgICBkZXN0OiBcIi4vZG9jcy93b3JrZG9jcy9yZXBvcnRzL2h0bWxcIixcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHNyYzogXCJ3b3JrZG9jcy9yZXNvdXJjZXNcIixcbiAgICAgICAgZGVzdDogXCIuL2RvY3Mvd29ya2RvY3MvcmVzb3VyY2VzXCIsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBzcmM6IFwiTElDRU5TRS5tZFwiLFxuICAgICAgICBkZXN0OiBcIi4vZG9jcy9MSUNFTlNFLm1kXCIsXG4gICAgICB9LFxuICAgIF0uZm9yRWFjaCgoZikgPT4ge1xuICAgICAgY29uc3QgeyBzcmMsIGRlc3QgfSA9IGY7XG4gICAgICBjb3B5RmlsZShzcmMsIGRlc3QpO1xuICAgIH0pO1xuXG4gICAgLy8gcGF0Y2ggLi9SRUFETUUubWQgZmlsZSB0byByZXBsYWNlIHZlcnNpb24vcGFja2FnZS9wYWNrYWdlIHNpemUgc3RyaW5nc1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBzaXplS2IgPSBhd2FpdCBnZXRGaWxlU2l6ZVppcHBlZChcbiAgICAgICAgcGF0aC5yZXNvbHZlKHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCBcImRpc3RcIikpXG4gICAgICApO1xuICAgICAgdGhpcy5yZXBsYWNlbWVudHNbUEFDS0FHRV9TSVpFX1NUUklOR10gPSBgJHtzaXplS2J9IEtCYDtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIGlmIHdlIGNvdWxkbid0IGNvbXB1dGUgc2l6ZSwgbGVhdmUgcGxhY2Vob2xkZXIgb3Igc2V0IHRvIHVua25vd25cbiAgICAgIHRoaXMucmVwbGFjZW1lbnRzW1BBQ0tBR0VfU0laRV9TVFJJTkddID0gXCJ1bmtub3duXCI7XG4gICAgfVxuXG4gICAgLy8gUGF0Y2ggUkVBRE1FLm1kIGluIHByb2plY3Qgcm9vdFxuICAgIHRyeSB7XG4gICAgICBwYXRjaEZpbGUoXCIuL1JFQURNRS5tZFwiLCB0aGlzLnJlcGxhY2VtZW50cyk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgY29uc3QgbG9nID0gdGhpcy5sb2cuZm9yKHRoaXMuYnVpbGREb2NzIGFzIGFueSk7XG4gICAgICBsb2cudmVyYm9zZShgRmFpbGVkIHRvIHBhdGNoIFJFQURNRS5tZDogJHtlfWApO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBydW48Uj4oXG4gICAgYW5zd2VyczogTG9nZ2luZ0NvbmZpZyAmXG4gICAgICB0eXBlb2YgRGVmYXVsdENvbW1hbmRWYWx1ZXMgJiB7IFtrIGluIGtleW9mIHR5cGVvZiBvcHRpb25zXTogdW5rbm93biB9XG4gICk6IFByb21pc2U8c3RyaW5nIHwgdm9pZCB8IFI+IHtcbiAgICBjb25zdCB7IGRldiwgcHJvZCwgZG9jcywgYnVpbGRNb2RlLCBpbmNsdWRlcywgZXh0ZXJuYWxzLCBlbnRyeSB9ID1cbiAgICAgIGFuc3dlcnMgYXMgYW55O1xuICAgIGlmIChkZXYpIHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLmJ1aWxkRGV2KFxuICAgICAgICBlbnRyeSB8fCBcIi4vc3JjL2luZGV4LnRzXCIsXG4gICAgICAgIGJ1aWxkTW9kZSBhcyBCdWlsZE1vZGUsXG4gICAgICAgIGluY2x1ZGVzLFxuICAgICAgICBleHRlcm5hbHNcbiAgICAgICk7XG4gICAgfVxuICAgIGlmIChwcm9kKSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5idWlsZFByb2QoXG4gICAgICAgIGVudHJ5IHx8IFwiLi9zcmMvaW5kZXgudHNcIixcbiAgICAgICAgYnVpbGRNb2RlIGFzIEJ1aWxkTW9kZSxcbiAgICAgICAgaW5jbHVkZXMsXG4gICAgICAgIGV4dGVybmFsc1xuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKGRvY3MpIHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLmJ1aWxkRG9jcygpO1xuICAgIH1cbiAgfVxufVxuIiwiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCB7IHJ1bkNvbW1hbmQgfSBmcm9tIFwiLi4vLi4vdXRpbHMvdXRpbHNcIjtcbmltcG9ydCB7IE5vQ0lGTGFnLCBTZW1WZXJzaW9uLCBTZW1WZXJzaW9uUmVnZXggfSBmcm9tIFwiLi4vLi4vdXRpbHMvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBVc2VySW5wdXQgfSBmcm9tIFwiLi4vLi4vaW5wdXQvaW5wdXRcIjtcbmltcG9ydCB7IENvbW1hbmQgfSBmcm9tIFwiLi4vY29tbWFuZFwiO1xuaW1wb3J0IHsgRGVmYXVsdENvbW1hbmRWYWx1ZXMgfSBmcm9tIFwiLi4vaW5kZXhcIjtcbmltcG9ydCB7IExvZ2dpbmdDb25maWcgfSBmcm9tIFwiQGRlY2FmLXRzL2xvZ2dpbmdcIjtcblxuY29uc3Qgb3B0aW9ucyA9IHtcbiAgY2k6IHtcbiAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgICBkZWZhdWx0OiB0cnVlLFxuICB9LFxuICBtZXNzYWdlOiB7XG4gICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICBzaG9ydDogXCJtXCIsXG4gIH0sXG4gIHRhZzoge1xuICAgIHR5cGU6IFwic3RyaW5nXCIsXG4gICAgc2hvcnQ6IFwidFwiLFxuICAgIGRlZmF1bHQ6IHVuZGVmaW5lZCxcbiAgfSxcbn07XG5cbi8qKlxuICogQGNsYXNzIFJlbGVhc2VTY3JpcHRcbiAqIEBleHRlbmRzIHtDb21tYW5kfVxuICogQGNhdmVnb3J5IHNjcmlwdHNcbiAqIEBkZXNjcmlwdGlvbiBBIGNvbW1hbmQtbGluZSBzY3JpcHQgZm9yIG1hbmFnaW5nIHJlbGVhc2VzIGFuZCB2ZXJzaW9uIHVwZGF0ZXMuXG4gKiBAc3VtbWFyeSBUaGlzIHNjcmlwdCBhdXRvbWF0ZXMgdGhlIHByb2Nlc3Mgb2YgY3JlYXRpbmcgYW5kIHB1c2hpbmcgbmV3IHJlbGVhc2VzLiBJdCBoYW5kbGVzIHZlcnNpb24gdXBkYXRlcyxcbiAqIGNvbW1pdCBtZXNzYWdlcywgYW5kIG9wdGlvbmFsbHkgcHVibGlzaGVzIHRvIE5QTS4gVGhlIHNjcmlwdCBzdXBwb3J0cyBzZW1hbnRpYyB2ZXJzaW9uaW5nIGFuZCBjYW4gd29yayBpbiBib3RoIENJIGFuZCBub24tQ0kgZW52aXJvbm1lbnRzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciB0aGUgc2NyaXB0XG4gKiBAcGFyYW0ge2Jvb2xlYW59IG9wdGlvbnMuY2kgLSBXaGV0aGVyIHRoZSBzY3JpcHQgaXMgcnVubmluZyBpbiBhIENJIGVudmlyb25tZW50IChkZWZhdWx0OiB0cnVlKVxuICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMubWVzc2FnZSAtIFRoZSByZWxlYXNlIG1lc3NhZ2UgKHNob3J0OiAnbScpXG4gKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy50YWcgLSBUaGUgdmVyc2lvbiB0YWcgdG8gdXNlIChzaG9ydDogJ3QnLCBkZWZhdWx0OiB1bmRlZmluZWQpXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWxlYXNlU2NyaXB0IGV4dGVuZHMgQ29tbWFuZDx0eXBlb2Ygb3B0aW9ucywgdm9pZD4ge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcihcIlJlbGVhc2VTY3JpcHRcIiwgb3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIHRoZSB2ZXJzaW9uIGZvciB0aGUgcmVsZWFzZS5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgdmFsaWRhdGVzIHRoZSBwcm92aWRlZCB0YWcgb3IgcHJvbXB0cyB0aGUgdXNlciBmb3IgYSBuZXcgb25lIGlmIG5vdCBwcm92aWRlZCBvciBpbnZhbGlkLlxuICAgKiBJdCBhbHNvIGRpc3BsYXlzIHRoZSBsYXRlc3QgZ2l0IHRhZ3MgZm9yIHJlZmVyZW5jZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHRhZyAtIFRoZSB2ZXJzaW9uIHRhZyB0byBwcmVwYXJlXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IFRoZSBwcmVwYXJlZCB2ZXJzaW9uIHRhZ1xuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBSIGFzIFJlbGVhc2VTY3JpcHRcbiAgICogICBwYXJ0aWNpcGFudCBUIGFzIFRlc3RWZXJzaW9uXG4gICAqICAgcGFydGljaXBhbnQgVSBhcyBVc2VySW5wdXRcbiAgICogICBwYXJ0aWNpcGFudCBHIGFzIEdpdFxuICAgKiAgIFItPj5UOiB0ZXN0VmVyc2lvbih0YWcpXG4gICAqICAgYWx0IHRhZyBpcyB2YWxpZFxuICAgKiAgICAgVC0tPj5SOiByZXR1cm4gdGFnXG4gICAqICAgZWxzZSB0YWcgaXMgaW52YWxpZCBvciBub3QgcHJvdmlkZWRcbiAgICogICAgIFItPj5HOiBMaXN0IGxhdGVzdCBnaXQgdGFnc1xuICAgKiAgICAgUi0+PlU6IFByb21wdCBmb3IgbmV3IHRhZ1xuICAgKiAgICAgVS0tPj5SOiByZXR1cm4gbmV3IHRhZ1xuICAgKiAgIGVuZFxuICAgKi9cbiAgYXN5bmMgcHJlcGFyZVZlcnNpb24odGFnPzogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5wcmVwYXJlVmVyc2lvbik7XG4gICAgdGFnID0gdGhpcy50ZXN0VmVyc2lvbigodGFnIGFzIHN0cmluZykgfHwgXCJcIik7XG4gICAgaWYgKCF0YWcpIHtcbiAgICAgIGxvZy52ZXJib3NlKFwiTm8gcmVsZWFzZSBtZXNzYWdlIHByb3ZpZGVkLiBQcm9tcHRpbmcgZm9yIG9uZTpcIik7XG4gICAgICBsb2cuaW5mbyhgTGlzdGluZyBsYXRlc3QgZ2l0IHRhZ3M6YCk7XG4gICAgICBhd2FpdCBydW5Db21tYW5kKFwiZ2l0IHRhZyAtLXNvcnQ9LXRhZ2dlcmRhdGUgfCBoZWFkIC1uIDVcIikucHJvbWlzZTtcbiAgICAgIHJldHVybiBhd2FpdCBVc2VySW5wdXQuaW5zaXN0Rm9yVGV4dChcbiAgICAgICAgXCJ0YWdcIixcbiAgICAgICAgXCJFbnRlciB0aGUgbmV3IHRhZyBudW1iZXIgKGFjY2VwdHMgdiouKi4qWy0uLi5dKVwiLFxuICAgICAgICAodmFsKSA9PlxuICAgICAgICAgICEhdmFsLnRvU3RyaW5nKCkubWF0Y2goL152WzAtOV0rXFwuWzAtOV0rLlswLTldKygtWzAtOWEtekEtWi1dKyk/JC8pXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdGFnO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUZXN0cyBpZiB0aGUgcHJvdmlkZWQgdmVyc2lvbiBpcyB2YWxpZC5cbiAgICogQHN1bW1hcnkgVGhpcyBtZXRob2QgY2hlY2tzIGlmIHRoZSB2ZXJzaW9uIGlzIGEgdmFsaWQgc2VtYW50aWMgdmVyc2lvbiBvciBhIHByZWRlZmluZWQgdXBkYXRlIHR5cGUgKFBBVENILCBNSU5PUiwgTUFKT1IpLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdmVyc2lvbiAtIFRoZSB2ZXJzaW9uIHRvIHRlc3RcbiAgICogQHJldHVybnMge3N0cmluZyB8IHVuZGVmaW5lZH0gVGhlIHZhbGlkYXRlZCB2ZXJzaW9uIG9yIHVuZGVmaW5lZCBpZiBpbnZhbGlkXG4gICAqL1xuICB0ZXN0VmVyc2lvbih2ZXJzaW9uOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGxvZyA9IHRoaXMubG9nLmZvcih0aGlzLnRlc3RWZXJzaW9uKTtcbiAgICB2ZXJzaW9uID0gdmVyc2lvbi50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgICBzd2l0Y2ggKHZlcnNpb24pIHtcbiAgICAgIGNhc2UgU2VtVmVyc2lvbi5QQVRDSDpcbiAgICAgIGNhc2UgU2VtVmVyc2lvbi5NSU5PUjpcbiAgICAgIGNhc2UgU2VtVmVyc2lvbi5NQUpPUjpcbiAgICAgICAgbG9nLnZlcmJvc2UoYFVzaW5nIHByb3ZpZGVkIFNlbVZlciB1cGRhdGU6ICR7dmVyc2lvbn1gLCAxKTtcbiAgICAgICAgcmV0dXJuIHZlcnNpb247XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBsb2cudmVyYm9zZShcbiAgICAgICAgICBgVGVzdGluZyBwcm92aWRlZCB2ZXJzaW9uIGZvciBTZW1WZXIgY29tcGF0aWJpbGl0eTogJHt2ZXJzaW9ufWAsXG4gICAgICAgICAgMVxuICAgICAgICApO1xuICAgICAgICBpZiAoIW5ldyBSZWdFeHAoU2VtVmVyc2lvblJlZ2V4KS50ZXN0KHZlcnNpb24pKSB7XG4gICAgICAgICAgbG9nLmRlYnVnKGBJbnZhbGlkIHZlcnNpb24gbnVtYmVyOiAke3ZlcnNpb259YCk7XG4gICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBsb2cudmVyYm9zZShgdmVyc2lvbiBhcHByb3ZlZDogJHt2ZXJzaW9ufWAsIDEpO1xuICAgICAgICByZXR1cm4gdmVyc2lvbjtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIHRoZSByZWxlYXNlIG1lc3NhZ2UuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIGVpdGhlciByZXR1cm5zIHRoZSBwcm92aWRlZCBtZXNzYWdlIG9yIHByb21wdHMgdGhlIHVzZXIgZm9yIGEgbmV3IG9uZSBpZiBub3QgcHJvdmlkZWQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbbWVzc2FnZV0gLSBUaGUgcmVsZWFzZSBtZXNzYWdlXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IFRoZSBwcmVwYXJlZCByZWxlYXNlIG1lc3NhZ2VcbiAgICovXG4gIGFzeW5jIHByZXBhcmVNZXNzYWdlKG1lc3NhZ2U/OiBzdHJpbmcpIHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5wcmVwYXJlTWVzc2FnZSk7XG4gICAgaWYgKCFtZXNzYWdlKSB7XG4gICAgICBsb2cudmVyYm9zZShcIk5vIHJlbGVhc2UgbWVzc2FnZSBwcm92aWRlZC4gUHJvbXB0aW5nIGZvciBvbmVcIik7XG4gICAgICByZXR1cm4gYXdhaXQgVXNlcklucHV0Lmluc2lzdEZvclRleHQoXG4gICAgICAgIFwibWVzc2FnZVwiLFxuICAgICAgICBcIldoYXQgc2hvdWxkIGJlIHRoZSByZWxlYXNlIG1lc3NhZ2UvdGlja2V0P1wiLFxuICAgICAgICAodmFsKSA9PiAhIXZhbCAmJiB2YWwudG9TdHJpbmcoKS5sZW5ndGggPiA1XG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUnVucyB0aGUgcmVsZWFzZSBzY3JpcHQuXG4gICAqIEBzdW1tYXJ5IFRoaXMgbWV0aG9kIG9yY2hlc3RyYXRlcyB0aGUgZW50aXJlIHJlbGVhc2UgcHJvY2VzcywgaW5jbHVkaW5nIHZlcnNpb24gcHJlcGFyYXRpb24sIG1lc3NhZ2UgY3JlYXRpb24sXG4gICAqIGdpdCBvcGVyYXRpb25zLCBhbmQgbnBtIHB1Ymxpc2hpbmcgKGlmIG5vdCBpbiBDSSBlbnZpcm9ubWVudCkuXG4gICAqIEBwYXJhbSB7UGFyc2VBcmdzUmVzdWx0fSBhcmdzIC0gVGhlIHBhcnNlZCBjb21tYW5kLWxpbmUgYXJndW1lbnRzXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBSIGFzIFJlbGVhc2VTY3JpcHRcbiAgICogICBwYXJ0aWNpcGFudCBWIGFzIFByZXBhcmVWZXJzaW9uXG4gICAqICAgcGFydGljaXBhbnQgTSBhcyBQcmVwYXJlTWVzc2FnZVxuICAgKiAgIHBhcnRpY2lwYW50IE4gYXMgTlBNXG4gICAqICAgcGFydGljaXBhbnQgRyBhcyBHaXRcbiAgICogICBwYXJ0aWNpcGFudCBVIGFzIFVzZXJJbnB1dFxuICAgKiAgIFItPj5WOiBwcmVwYXJlVmVyc2lvbih0YWcpXG4gICAqICAgUi0+Pk06IHByZXBhcmVNZXNzYWdlKG1lc3NhZ2UpXG4gICAqICAgUi0+Pk46IFJ1biBwcmVwYXJlLXJlbGVhc2Ugc2NyaXB0XG4gICAqICAgUi0+Pkc6IENoZWNrIGdpdCBzdGF0dXNcbiAgICogICBhbHQgY2hhbmdlcyBleGlzdFxuICAgKiAgICAgUi0+PlU6IEFzayBmb3IgY29uZmlybWF0aW9uXG4gICAqICAgICBVLS0+PlI6IENvbmZpcm1cbiAgICogICAgIFItPj5HOiBBZGQgYW5kIGNvbW1pdCBjaGFuZ2VzXG4gICAqICAgZW5kXG4gICAqICAgUi0+Pk46IFVwZGF0ZSBucG0gdmVyc2lvblxuICAgKiAgIFItPj5HOiBQdXNoIGNoYW5nZXMgYW5kIHRhZ3NcbiAgICogICBhbHQgbm90IENJIGVudmlyb25tZW50XG4gICAqICAgICBSLT4+TjogUHVibGlzaCB0byBucG1cbiAgICogICBlbmRcbiAgICovXG4gIGFzeW5jIHJ1bihcbiAgICBhcmdzOiBMb2dnaW5nQ29uZmlnICZcbiAgICAgIHR5cGVvZiBEZWZhdWx0Q29tbWFuZFZhbHVlcyAmIHsgW2sgaW4ga2V5b2YgdHlwZW9mIG9wdGlvbnNdOiB1bmtub3duIH1cbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IHJlc3VsdDogYW55O1xuICAgIGNvbnN0IHsgY2kgfSA9IGFyZ3M7XG4gICAgbGV0IHsgdGFnLCBtZXNzYWdlIH0gPSBhcmdzO1xuICAgIHRhZyA9IGF3YWl0IHRoaXMucHJlcGFyZVZlcnNpb24odGFnIGFzIHN0cmluZyk7XG4gICAgbWVzc2FnZSA9IGF3YWl0IHRoaXMucHJlcGFyZU1lc3NhZ2UobWVzc2FnZSBhcyBzdHJpbmcpO1xuICAgIHJlc3VsdCA9IGF3YWl0IHJ1bkNvbW1hbmQoYG5wbSBydW4gcHJlcGFyZS1yZWxlYXNlIC0tICR7dGFnfSAke21lc3NhZ2V9YCwge1xuICAgICAgY3dkOiBwcm9jZXNzLmN3ZCgpLFxuICAgIH0pLnByb21pc2U7XG4gICAgcmVzdWx0ID0gYXdhaXQgcnVuQ29tbWFuZChcImdpdCBzdGF0dXMgLS1wb3JjZWxhaW5cIikucHJvbWlzZTtcbiAgICBhd2FpdCByZXN1bHQ7XG4gICAgaWYgKFxuICAgICAgcmVzdWx0LmxvZ3MubGVuZ3RoICYmXG4gICAgICAoYXdhaXQgVXNlcklucHV0LmFza0NvbmZpcm1hdGlvbihcbiAgICAgICAgXCJnaXQtY2hhbmdlc1wiLFxuICAgICAgICBcIkRvIHlvdSB3YW50IHRvIHB1c2ggdGhlIGNoYW5nZXMgdG8gdGhlIHJlbW90ZSByZXBvc2l0b3J5P1wiLFxuICAgICAgICB0cnVlXG4gICAgICApKVxuICAgICkge1xuICAgICAgYXdhaXQgcnVuQ29tbWFuZChcImdpdCBhZGQgLlwiKS5wcm9taXNlO1xuICAgICAgYXdhaXQgcnVuQ29tbWFuZChcbiAgICAgICAgYGdpdCBjb21taXQgLW0gXCIke3RhZ30gLSAke21lc3NhZ2V9IC0gYWZ0ZXIgcmVsZWFzZSBwcmVwYXJhdGlvbiR7Y2kgPyBcIlwiIDogTm9DSUZMYWd9XCJgXG4gICAgICApLnByb21pc2U7XG4gICAgfVxuICAgIGF3YWl0IHJ1bkNvbW1hbmQoXG4gICAgICBgbnBtIHZlcnNpb24gXCIke3RhZ31cIiAtbSBcIiR7bWVzc2FnZX0ke2NpID8gXCJcIiA6IE5vQ0lGTGFnfVwiYFxuICAgICkucHJvbWlzZTtcbiAgICBhd2FpdCBydW5Db21tYW5kKFwiZ2l0IHB1c2ggLS1mb2xsb3ctdGFnc1wiKS5wcm9taXNlO1xuICAgIGlmICghY2kpIHtcbiAgICAgIGF3YWl0IHJ1bkNvbW1hbmQoXCJOUE1fVE9LRU49JChjYXQgLm5wbXRva2VuKSBucG0gcHVibGlzaCAtLWFjY2VzcyBwdWJsaWNcIilcbiAgICAgICAgLnByb21pc2U7XG4gICAgfVxuICB9XG59XG4iLCJpbXBvcnQgeyBTdGFuZGFyZE91dHB1dFdyaXRlciB9IGZyb20gXCIuL1N0YW5kYXJkT3V0cHV0V3JpdGVyXCI7XG5pbXBvcnQgeyBQcm9taXNlRXhlY3V0b3IgfSBmcm9tIFwiLi4vdXRpbHMvdHlwZXNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQSBzcGVjaWFsaXplZCBvdXRwdXQgd3JpdGVyIHRoYXQgdXNlcyByZWd1bGFyIGV4cHJlc3Npb25zIHRvIHByb2Nlc3Mgb3V0cHV0LlxuICogQHN1bW1hcnkgVGhpcyBjbGFzcyBleHRlbmRzIFN0YW5kYXJkT3V0cHV0V3JpdGVyIHRvIHByb3ZpZGUgcmVnZXgtYmFzZWQgb3V0cHV0IHByb2Nlc3NpbmcuXG4gKiBJdCBhbGxvd3MgZm9yIHBhdHRlcm4gbWF0Y2hpbmcgaW4gdGhlIG91dHB1dCBzdHJlYW0gYW5kIGNhbiB0cmlnZ2VyIHNwZWNpZmljIGFjdGlvbnNcbiAqIGJhc2VkIG9uIG1hdGNoZWQgcGF0dGVybnMuXG4gKlxuICogQHRlbXBsYXRlIFQgLSBUaGUgdHlwZSBvZiB0aGUgcmVzb2x2ZWQgdmFsdWUsIGRlZmF1bHRpbmcgdG8gc3RyaW5nLlxuICpcbiAqIEBwYXJhbSBjbWQgLSBUaGUgY29tbWFuZCBzdHJpbmcgdG8gYmUgZXhlY3V0ZWQuXG4gKiBAcGFyYW0gbG9jayAtIEEgUHJvbWlzZUV4ZWN1dG9yIHRvIGNvbnRyb2wgdGhlIGFzeW5jaHJvbm91cyBmbG93LlxuICogQHBhcmFtIHJlZ2V4cCAtIEEgc3RyaW5nIG9yIFJlZ0V4cCB0byBtYXRjaCBhZ2FpbnN0IHRoZSBvdXRwdXQuXG4gKiBAcGFyYW0gZmxhZ3MgLSBPcHRpb25hbCBmbGFncyBmb3IgdGhlIFJlZ0V4cCBjb25zdHJ1Y3RvciwgZGVmYXVsdHMgdG8gXCJnXCIuXG4gKlxuICogQGNsYXNzXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgUmVnZXhwT3V0cHV0V3JpdGVyIH0gZnJvbSAnQGRlY2FmLXRzL3V0aWxzJztcbiAqIGltcG9ydCB7IFByb21pc2VFeGVjdXRvciB9IGZyb20gJ0BkZWNhZi10cy91dGlscyc7XG4gKiBcbiAqIC8vIENyZWF0ZSBhIHByb21pc2UgZXhlY3V0b3JcbiAqIGNvbnN0IGV4ZWN1dG9yOiBQcm9taXNlRXhlY3V0b3I8c3RyaW5nLCBFcnJvcj4gPSB7XG4gKiAgIHJlc29sdmU6ICh2YWx1ZSkgPT4gY29uc29sZS5sb2coYFJlc29sdmVkOiAke3ZhbHVlfWApLFxuICogICByZWplY3Q6IChlcnJvcikgPT4gY29uc29sZS5lcnJvcihgUmVqZWN0ZWQ6ICR7ZXJyb3IubWVzc2FnZX1gKVxuICogfTtcbiAqIFxuICogLy8gQ3JlYXRlIGEgcmVnZXhwIG91dHB1dCB3cml0ZXIgdGhhdCBtYXRjaGVzIHZlcnNpb24gbnVtYmVyc1xuICogY29uc3Qgd3JpdGVyID0gbmV3IFJlZ2V4cE91dHB1dFdyaXRlcignbm9kZSAtLXZlcnNpb24nLCBleGVjdXRvciwgL3YoXFxkK1xcLlxcZCtcXC5cXGQrKS8pO1xuICogXG4gKiAvLyBVc2UgdGhlIHdyaXRlciB0byBoYW5kbGUgY29tbWFuZCBvdXRwdXRcbiAqIHdyaXRlci5kYXRhKCd2MTQuMTcuMCcpOyAgLy8gVGhpcyB3aWxsIGF1dG9tYXRpY2FsbHkgcmVzb2x2ZSB3aXRoIFwidjE0LjE3LjBcIlxuICogYGBgXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgUmVnZXhwT3V0cHV0V3JpdGVyXG4gKiAgIHBhcnRpY2lwYW50IFN0YW5kYXJkT3V0cHV0V3JpdGVyXG4gKiAgIHBhcnRpY2lwYW50IExvZ2dlclxuICogICBcbiAqICAgQ2xpZW50LT4+UmVnZXhwT3V0cHV0V3JpdGVyOiBuZXcgUmVnZXhwT3V0cHV0V3JpdGVyKGNtZCwgbG9jaywgcmVnZXhwLCBmbGFncylcbiAqICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IHN1cGVyKGNtZCwgbG9jaylcbiAqICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5Mb2dnZXI6IExvZ2dpbmcuZm9yKGNtZClcbiAqICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+UmVnZXhwT3V0cHV0V3JpdGVyOiBjb21waWxlIHJlZ2V4cFxuICogICBcbiAqICAgQ2xpZW50LT4+UmVnZXhwT3V0cHV0V3JpdGVyOiBkYXRhKGNodW5rKVxuICogICBSZWdleHBPdXRwdXRXcml0ZXItPj5TdGFuZGFyZE91dHB1dFdyaXRlcjogc3VwZXIuZGF0YShjaHVuaylcbiAqICAgU3RhbmRhcmRPdXRwdXRXcml0ZXItPj5Mb2dnZXI6IGxvZ2dlci5pbmZvKGxvZylcbiAqICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+UmVnZXhwT3V0cHV0V3JpdGVyOiB0ZXN0QW5kUmVzb2x2ZShjaHVuaylcbiAqICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+UmVnZXhwT3V0cHV0V3JpdGVyOiB0ZXN0KGNodW5rKVxuICogICBhbHQgbWF0Y2ggZm91bmRcbiAqICAgICBSZWdleHBPdXRwdXRXcml0ZXItPj5SZWdleHBPdXRwdXRXcml0ZXI6IHJlc29sdmUobWF0Y2hbMF0pXG4gKiAgICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IHJlc29sdmUobWF0Y2hbMF0pXG4gKiAgIGVuZFxuICogICBcbiAqICAgQ2xpZW50LT4+UmVnZXhwT3V0cHV0V3JpdGVyOiBlcnJvcihjaHVuaylcbiAqICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IHN1cGVyLmVycm9yKGNodW5rKVxuICogICBTdGFuZGFyZE91dHB1dFdyaXRlci0+PkxvZ2dlcjogbG9nZ2VyLmluZm8obG9nKVxuICogICBSZWdleHBPdXRwdXRXcml0ZXItPj5SZWdleHBPdXRwdXRXcml0ZXI6IHRlc3RBbmRSZWplY3QoY2h1bmspXG4gKiAgIFJlZ2V4cE91dHB1dFdyaXRlci0+PlJlZ2V4cE91dHB1dFdyaXRlcjogdGVzdChjaHVuaylcbiAqICAgYWx0IG1hdGNoIGZvdW5kXG4gKiAgICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+UmVnZXhwT3V0cHV0V3JpdGVyOiByZWplY3QobWF0Y2hbMF0pXG4gKiAgICAgUmVnZXhwT3V0cHV0V3JpdGVyLT4+U3RhbmRhcmRPdXRwdXRXcml0ZXI6IHJlamVjdChtYXRjaFswXSlcbiAqICAgZW5kXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWdleHBPdXRwdXRXcml0ZXIgZXh0ZW5kcyBTdGFuZGFyZE91dHB1dFdyaXRlcjxzdHJpbmc+IHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUaGUgcmVndWxhciBleHByZXNzaW9uIHVzZWQgZm9yIG1hdGNoaW5nIG91dHB1dC5cbiAgICogQHN1bW1hcnkgVGhpcyByZWFkb25seSBwcm9wZXJ0eSBzdG9yZXMgdGhlIGNvbXBpbGVkIFJlZ0V4cCB1c2VkIGZvciBwYXR0ZXJuIG1hdGNoaW5nLlxuICAgKi9cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHJlZ2V4cDogUmVnRXhwO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGNtZDogc3RyaW5nLFxuICAgIGxvY2s6IFByb21pc2VFeGVjdXRvcjxzdHJpbmcsIEVycm9yPixcbiAgICByZWdleHA6IHN0cmluZyB8IFJlZ0V4cCxcbiAgICBmbGFncyA9IFwiZ1wiXG4gICkge1xuICAgIHN1cGVyKGNtZCwgbG9jayk7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMucmVnZXhwID1cbiAgICAgICAgdHlwZW9mIHJlZ2V4cCA9PT0gXCJzdHJpbmdcIiA/IG5ldyBSZWdFeHAocmVnZXhwLCBmbGFncykgOiByZWdleHA7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHJlZ3VsYXIgZXhwcmVzc2lvbjogJHtlfWApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVGVzdHMgdGhlIGlucHV0IGRhdGEgYWdhaW5zdCB0aGUgc3RvcmVkIHJlZ3VsYXIgZXhwcmVzc2lvbi5cbiAgICogQHN1bW1hcnkgRXhlY3V0ZXMgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbiBvbiB0aGUgaW5wdXQgZGF0YSBhbmQgcmV0dXJucyB0aGUgbWF0Y2ggcmVzdWx0LlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFRoZSBzdHJpbmcgdG8gdGVzdCBhZ2FpbnN0IHRoZSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAqIEByZXR1cm4gVGhlIHJlc3VsdCBvZiB0aGUgcmVndWxhciBleHByZXNzaW9uIGV4ZWN1dGlvbiwgb3IgdW5kZWZpbmVkIGlmIGFuIGVycm9yIG9jY3Vycy5cbiAgICovXG4gIHByaXZhdGUgdGVzdChkYXRhOiBzdHJpbmcpIHtcbiAgICB0aGlzLnJlZ2V4cC5sYXN0SW5kZXggPSAwO1xuICAgIGxldCBtYXRjaDtcbiAgICB0cnkge1xuICAgICAgbWF0Y2ggPSB0aGlzLnJlZ2V4cC5leGVjKGRhdGEpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHJldHVybiBjb25zb2xlLmRlYnVnKGBGYWlsZWQgdG8gcGFyc2UgY2h1bms6ICR7ZGF0YX1cXG5FcnJvcjogJHtlfSBgKTtcbiAgICB9XG4gICAgcmV0dXJuIG1hdGNoO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUZXN0cyB0aGUgZGF0YSBhbmQgcmVzb2x2ZXMgdGhlIHByb21pc2UgaWYgYSBtYXRjaCBpcyBmb3VuZC5cbiAgICogQHN1bW1hcnkgRXhlY3V0ZXMgdGhlIHRlc3QgbWV0aG9kIGFuZCByZXNvbHZlcyB0aGUgcHJvbWlzZSB3aXRoIHRoZSBmaXJzdCBtYXRjaCBncm91cCBpZiBzdWNjZXNzZnVsLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSAtIFRoZSBzdHJpbmcgdG8gdGVzdCBhZ2FpbnN0IHRoZSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAqL1xuICBwcm90ZWN0ZWQgdGVzdEFuZFJlc29sdmUoZGF0YTogc3RyaW5nKSB7XG4gICAgY29uc3QgbWF0Y2ggPSB0aGlzLnRlc3QoZGF0YSk7XG4gICAgaWYgKG1hdGNoKSB0aGlzLnJlc29sdmUobWF0Y2hbMF0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBUZXN0cyB0aGUgZGF0YSBhbmQgcmVqZWN0cyB0aGUgcHJvbWlzZSBpZiBhIG1hdGNoIGlzIGZvdW5kLlxuICAgKiBAc3VtbWFyeSBFeGVjdXRlcyB0aGUgdGVzdCBtZXRob2QgYW5kIHJlamVjdHMgdGhlIHByb21pc2Ugd2l0aCB0aGUgZmlyc3QgbWF0Y2ggZ3JvdXAgaWYgc3VjY2Vzc2Z1bC5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBUaGUgc3RyaW5nIHRvIHRlc3QgYWdhaW5zdCB0aGUgcmVndWxhciBleHByZXNzaW9uLlxuICAgKi9cbiAgcHJvdGVjdGVkIHRlc3RBbmRSZWplY3QoZGF0YTogc3RyaW5nKSB7XG4gICAgY29uc3QgbWF0Y2ggPSB0aGlzLnRlc3QoZGF0YSk7XG4gICAgaWYgKG1hdGNoKSB0aGlzLnJlamVjdChtYXRjaFswXSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByb2Nlc3NlcyBpbmNvbWluZyBkYXRhIGNodW5rcy5cbiAgICogQHN1bW1hcnkgQ2FsbHMgdGhlIHBhcmVudCBjbGFzcyBkYXRhIG1ldGhvZCBhbmQgdGhlbiB0ZXN0cyB0aGUgZGF0YSBmb3IgYSBtYXRjaCB0byBwb3RlbnRpYWxseSByZXNvbHZlIHRoZSBwcm9taXNlLlxuICAgKlxuICAgKiBAcGFyYW0gY2h1bmsgLSBUaGUgZGF0YSBjaHVuayB0byBwcm9jZXNzLlxuICAgKi9cbiAgb3ZlcnJpZGUgZGF0YShjaHVuazogYW55KSB7XG4gICAgc3VwZXIuZGF0YShjaHVuayk7XG4gICAgdGhpcy50ZXN0QW5kUmVzb2x2ZShTdHJpbmcoY2h1bmspKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJvY2Vzc2VzIGluY29taW5nIGVycm9yIGNodW5rcy5cbiAgICogQHN1bW1hcnkgQ2FsbHMgdGhlIHBhcmVudCBjbGFzcyBlcnJvciBtZXRob2QgYW5kIHRoZW4gdGVzdHMgdGhlIGRhdGEgZm9yIGEgbWF0Y2ggdG8gcG90ZW50aWFsbHkgcmVqZWN0IHRoZSBwcm9taXNlLlxuICAgKlxuICAgKiBAcGFyYW0gY2h1bmsgLSBUaGUgZXJyb3IgY2h1bmsgdG8gcHJvY2Vzcy5cbiAgICovXG4gIG92ZXJyaWRlIGVycm9yKGNodW5rOiBhbnkpIHtcbiAgICBzdXBlci5lcnJvcihjaHVuayk7XG4gICAgdGhpcy50ZXN0QW5kUmVqZWN0KFN0cmluZyhjaHVuaykpO1xuICB9XG59XG4iLCJleHBvcnQgKiBmcm9tIFwiLi9jbGlcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2lucHV0XCI7XG5leHBvcnQgKiBmcm9tIFwiLi9vdXRwdXRcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3V0aWxzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi93cml0ZXJzXCI7XG5cbi8qKlxuICogQG1vZHVsZSB1dGlsc1xuICogQGRlc2NyaXB0aW9uIFV0aWxpdGllcyBhbmQgYnVpbGRpbmcgYmxvY2tzIGZvciBEZWNhZi1UUyBDTEkgYW5kIHNjcmlwdGluZy5cbiAqIEBzdW1tYXJ5IEFnZ3JlZ2F0ZXMgQ0xJIGNvbW1hbmQgaW5mcmFzdHJ1Y3R1cmUsIGlucHV0IGhlbHBlcnMsIG91dHB1dCB3cml0ZXJzLCBmaWxlc3lzdGVtL25ldHdvcmsgdXRpbGl0aWVzLFxuICogYW5kIHNoYXJlZCB0eXBlcy4gQ29uc3VtZXJzIHR5cGljYWxseSB1c2Uge0BsaW5rIENvbW1hbmR9LCB7QGxpbmsgVXNlcklucHV0fSwge0BsaW5rIFN0YW5kYXJkT3V0cHV0V3JpdGVyfSxcbiAqIHtAbGluayBwcmludEJhbm5lcn0sIGFuZCB1dGlsaXRpZXMgZnJvbSB7QGxpbmsgbW9kdWxlOnV0aWxzfHV0aWxzfS5cbiAqXG4gKiBUaGlzIGVudHJ5cG9pbnQgcmUtZXhwb3J0cyBzdWJwYWNrYWdlczpcbiAqIC0gQ0xJIGZyYW1ld29yayB1bmRlciBgLi9jbGlgIChjb21tYW5kIGJhc2UsIG9wdGlvbnMsIGJ1aWx0LWluIGNvbW1hbmRzKVxuICogLSBJbnB1dCBoZWxwZXJzIHVuZGVyIGAuL2lucHV0YCAocHJvbXB0aW5nIGFuZCBhcmcgcGFyc2luZylcbiAqIC0gT3V0cHV0IGhlbHBlcnMgdW5kZXIgYC4vb3V0cHV0YCAoYmFubmVyIGFuZCBzdHlsaW5nKVxuICogLSBHZW5lcmFsIHV0aWxpdGllcyB1bmRlciBgLi91dGlsc2AgKGZzLCBodHRwLCBleGVjLCB0eXBlcylcbiAqIC0gV3JpdGVycyB1bmRlciBgLi93cml0ZXJzYCAoc3Rkb3V0L3N0ZGVyciBwcm9jZXNzb3JzKVxuICpcbiAqIE5vdGU6IEluZGl2aWR1YWwgZXhwb3J0cyBhcmUgZG9jdW1lbnRlZCBpbiB0aGVpciBzb3VyY2UgZmlsZXMuXG4gKi9cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmVwcmVzZW50cyB0aGUgY3VycmVudCB2ZXJzaW9uIG9mIHRoZSBtb2R1bGUuXG4gKiBAc3VtbWFyeSBTdG9yZXMgdGhlIHZlcnNpb24gZm9yIHRoZSBAZGVjYWYtdHMvdXRpbHMgcGFja2FnZS4gVGhlIGJ1aWxkIHJlcGxhY2VzXG4gKiB0aGUgcGxhY2Vob2xkZXIgd2l0aCB0aGUgYWN0dWFsIHZlcnNpb24gbnVtYmVyIGF0IHB1Ymxpc2ggdGltZS5cbiAqIEBjb25zdCBWRVJTSU9OXG4gKiBAbWVtYmVyT2YgbW9kdWxlOnV0aWxzXG4gKi9cbmV4cG9ydCBjb25zdCBWRVJTSU9OID0gXCIjI1ZFUlNJT04jI1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZXByZXNlbnRzIHRoZSBjdXJyZW50IHZlcnNpb24gb2YgdGhlIG1vZHVsZS5cbiAqIEBzdW1tYXJ5IFN0b3JlcyB0aGUgdmVyc2lvbiBmb3IgdGhlIEBkZWNhZi10cy91dGlscyBwYWNrYWdlLiBUaGUgYnVpbGQgcmVwbGFjZXNcbiAqIHRoZSBwbGFjZWhvbGRlciB3aXRoIHRoZSBhY3R1YWwgdmVyc2lvbiBudW1iZXIgYXQgcHVibGlzaCB0aW1lLlxuICogQGNvbnN0IFZFUlNJT05cbiAqIEBtZW1iZXJPZiBtb2R1bGU6dXRpbHNcbiAqL1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfTkFNRSA9IFwiIyNQQUNLQUdFIyNcIjtcbiJdLCJuYW1lcyI6WyJVc2VySW5wdXQiLCJ0aGlzIiwibG9nZ2VyIiwiTG9nZ2luZyIsImZvciIsImNvbnN0cnVjdG9yIiwibmFtZSIsInR5cGUiLCJzZXRUeXBlIiwidmVyYm9zZSIsInNldE1lc3NhZ2UiLCJ2YWx1ZSIsIm1lc3NhZ2UiLCJzZXRJbml0aWFsIiwiaW5pdGlhbCIsInNldFN0eWxlIiwic3R5bGUiLCJzZXRGb3JtYXQiLCJmb3JtYXQiLCJzZXRWYWxpZGF0ZSIsInZhbGlkYXRlIiwic2V0T25TdGF0ZSIsIm9uU3RhdGUiLCJzZXRNaW4iLCJtaW4iLCJzZXRNYXgiLCJtYXgiLCJzZXRGbG9hdCIsImZsb2F0Iiwic2V0Um91bmQiLCJyb3VuZCIsInNldEluc3RydWN0aW9ucyIsImluc3RydWN0aW9ucyIsInNldEluY3JlbWVudCIsImluY3JlbWVudCIsInNldFNlcGFyYXRvciIsInNlcGFyYXRvciIsInNldEFjdGl2ZSIsImFjdGl2ZSIsInNldEluYWN0aXZlIiwiaW5hY3RpdmUiLCJzZXRDaG9pY2VzIiwiSlNPTiIsInN0cmluZ2lmeSIsImNob2ljZXMiLCJzZXRIaW50IiwiaGludCIsInNldFdhcm4iLCJ3YXJuIiwic2V0U3VnZ2VzdCIsInN1Z2dlc3QiLCJzZXRMaW1pdCIsImxpbWl0Iiwic2V0TWFzayIsIm1hc2siLCJzZXRTdGRvdXQiLCJzdGRvdXQiLCJzZXRTdGRpbiIsInN0ZGluIiwiYXNrIiwicXVlc3Rpb24iLCJsb2ciLCJBcnJheSIsImlzQXJyYXkiLCJhbnN3ZXJzIiwibWFwIiwicSIsImpvaW4iLCJwcm9tcHRzIiwiZXJyb3IiLCJFcnJvciIsImFza051bWJlciIsInVzZXJJbnB1dCIsImFza1RleHQiLCJ1bmRlZmluZWQiLCJhc2tDb25maXJtYXRpb24iLCJpbnNpc3QiLCJpbnB1dCIsInRlc3QiLCJkZWZhdWx0Q29uZmlybWF0aW9uIiwidG9TdHJpbmciLCJyZXN1bHQiLCJjb3VudCIsImNvbmZpcm1hdGlvbiIsImUiLCJpbmZvIiwiaW5zaXN0Rm9yVGV4dCIsImluc2lzdEZvck51bWJlciIsInBhcnNlQXJncyIsIm9wdGlvbnMiLCJhcmdzIiwicHJvY2VzcyIsImFyZ3YiLCJzbGljZSIsImRlYnVnIiwiRGVmYXVsdENvbW1hbmRPcHRpb25zIiwic2hvcnQiLCJkZWZhdWx0IiwidmVyc2lvbiIsImhlbHAiLCJsb2dMZXZlbCIsImxvZ1N0eWxlIiwidGltZXN0YW1wIiwiYmFubmVyIiwiRGVmYXVsdENvbW1hbmRWYWx1ZXMiLCJPYmplY3QiLCJrZXlzIiwicmVkdWNlIiwiYWNjIiwia2V5IiwiRW5jb2RpbmciLCJTZW1WZXJzaW9uUmVnZXgiLCJTZW1WZXJzaW9uIiwiTm9DSUZMYWciLCJTZXR1cFNjcmlwdEtleSIsIlRva2VucyIsIkFib3J0Q29kZSIsIlN0YW5kYXJkT3V0cHV0V3JpdGVyIiwiY21kIiwibG9jayIsImRhdGEiLCJCdWZmZXIiLCJpc0J1ZmZlciIsInJlZCIsInRleHQiLCJjaHVuayIsIlN0cmluZyIsImVycm9ycyIsImVyciIsImV4aXQiLCJjb2RlIiwibG9ncyIsImdyZWVuIiwicmVzb2x2ZSIsImwiLCJ0cmltIiwicmVqZWN0IiwibGVuZ3RoIiwicGFyc2VDb21tYW5kIiwiY29tbWFuZCIsInBhcnRzIiwicGFyc2UiLCJmaWx0ZXIiLCJwIiwicmVhc29uIiwibG9ja2lmeSIsImYiLCJQcm9taXNlIiwicGFyYW1zIiwidGhlbiIsImNhdGNoIiwiY2hhaW5BYm9ydENvbnRyb2xsZXIiLCJhcmd1bWVudDAiLCJyZW1haW5kZXIiLCJzaWduYWxzIiwiY29udHJvbGxlciIsIkFib3J0U2lnbmFsIiwiQWJvcnRDb250cm9sbGVyIiwic2lnbmFsIiwiYWJvcnRlZCIsImhhbmRsZXIiLCJhYm9ydCIsImFkZEV2ZW50TGlzdGVuZXIiLCJvbmNlIiwic3Bhd25Db21tYW5kIiwib3V0cHV0Iiwib3B0cyIsInNwYXduSW5uZXIiLCJhcmd6IiwiY2hpbGRQcm9jZXNzIiwic3Bhd24iLCJjd2QiLCJlbnYiLCJhc3NpZ24iLCJQQVRIIiwic2hlbGwiLCJwaWQiLCJtIiwibWF0Y2giLCJpbmNsdWRlcyIsImNtZHMiLCJzcGxpdCIsInNwYXducyIsImNvbnRyb2xsZXJzIiwiaSIsInB1c2giLCJwaXBlIiwicnVuQ29tbWFuZCIsIm91dHB1dENvbnN0cnVjdG9yIiwiZXJycyIsInNldEVuY29kaW5nIiwib24iLCJzdGRlcnIiLCJwcm9taXNlIiwiYXN5bmMiLCJjYiIsImxvY2FsUmVxdWlyZSIsImNyZWF0ZVJlcXVpcmUiLCJpc1Rlc3RFbnZpcm9ubWVudCIsIk5PREVfRU5WIiwiSkVTVF9XT1JLRVJfSUQiLCJwYXRjaFN0cmluZyIsInZhbHVlcyIsImZsYWdzIiwiZW50cmllcyIsImZvckVhY2giLCJ2YWwiLCJyZWdleHAiLCJSZWdFeHAiLCJlc2NhcGVSZWdFeHAiLCJyZXBsYWNlIiwic3ViU3RyIiwicGF0Y2hGaWxlIiwicGF0aCIsImZzIiwiZXhpc3RzU3luYyIsImNvbnRlbnQiLCJyZWFkRmlsZSIsIndyaXRlRmlsZSIsInJlYWRGaWxlU3luYyIsIndyaXRlRmlsZVN5bmMiLCJnZXRBbGxGaWxlcyIsImZpbGVzIiwicmVhZGRpclN5bmMiLCJlbnRyeSIsImZ1bGxQYXRoIiwic3RhdCIsInN0YXRTeW5jIiwiaXNGaWxlIiwiaXNEaXJlY3RvcnkiLCJyZW5hbWVGaWxlIiwic291cmNlIiwiZGVzdCIsImRlc2NyaXB0b3JTb3VyY2UiLCJkZXNjcmlwdG9yRGVzdCIsInJlbmFtZVN5bmMiLCJjb3B5RmlsZSIsIm1rZGlyU3luYyIsInJlY3Vyc2l2ZSIsImNwU3luYyIsImRlbGV0ZVBhdGgiLCJkZXNjcmlwdG9yIiwicm1TeW5jIiwiZm9yY2UiLCJnZXRQYWNrYWdlIiwicHJvcGVydHkiLCJwa2ciLCJzZXRQYWNrYWdlQXR0cmlidXRlIiwiYXR0ciIsImdldFBhY2thZ2VWZXJzaW9uIiwiZ2V0RGVwZW5kZW5jaWVzIiwicGtnUGF0aCIsImxvY2tQYXRoIiwibWFwRGVwcyIsInJlc29sdmVEZXBlbmRlbmN5VmVyc2lvbiIsInByb2QiLCJkZXBlbmRlbmNpZXMiLCJkZXYiLCJkZXZEZXBlbmRlbmNpZXMiLCJwZWVyIiwicGVlckRlcGVuZGVuY2llcyIsImZhbGxiYWNrIiwicGFja2FnZXMiLCJ1cGRhdGVEZXBlbmRlbmNpZXMiLCJpbnN0YWxsSWZOb3RBdmFpbGFibGUiLCJkZXBzIiwiY3VycmVudCIsImtub3duIiwiU2V0IiwidG9JbnN0YWxsIiwiZGVwIiwiaGFzIiwiYWRkIiwiaW5zdGFsbERlcGVuZGVuY2llcyIsImRldkRlcHMiLCJmcm9tIiwicHVzaFRvR2l0IiwiZ2l0VXNlciIsImdpdEVtYWlsIiwibm9ybWFsaXplSW1wb3J0IiwiaW1wb3J0UHJvbWlzZSIsImdldEZpbGVTaXplWmlwcGVkIiwiZGlyIiwiY2FuZGlkYXRlcyIsInMiLCJlbmRzV2l0aCIsInNtYWxsZXN0Iiwic21hbGxlc3RTaXplIiwic2l6ZSIsImMiLCJidWZmZXIiLCJneiIsInpsaWIiLCJnemlwU3luYyIsInNpemVLYiIsIk51bWJlciIsInRvRml4ZWQiLCJsaXN0Rm9sZGVyIiwiYmFzZVBhdGgiLCJ3aXRoRmlsZVR5cGVzIiwibmFtZXMiLCJkIiwibGlzdE5vZGVNb2R1bGVzUGFja2FnZXMiLCJzdGFydHNXaXRoIiwic2NvcGVQYXRoIiwic2NvcGVkIiwic2xvZ2FucyIsIlNsb2dhbiIsIlRhZ3MiLCJjb2xvcnMiLCJwcmludEJhbm5lciIsImdldFNsb2dhbiIsIm1heExlbmd0aCIsImxpbmUiLCJNYXRoIiwicGFkU3RhcnQiLCJpbmRleCIsImJpbmQiLCJjb25zb2xlIiwicmF3IiwiZmxvb3IiLCJyYW5kb20iLCJDb21tYW5kIiwiTG9nZ2VkQ2xhc3MiLCJpbnB1dHMiLCJyZXF1aXJlbWVudHMiLCJzdXBlciIsImRlZmluZVByb3BlcnR5Iiwid3JpdGFibGUiLCJjaGVja1JlcXVpcmVtZW50cyIsIm1pc3NpbmciLCJmdWxsTGlzdCIsImV4ZWN1dGUiLCJMb2dnZWRFbnZpcm9ubWVudCIsImFjY3VtdWxhdGUiLCJjb250ZXh0IiwicnVuIiwiSHR0cENsaWVudCIsImRvd25sb2FkRmlsZSIsInVybCIsInJlcXVlc3QiLCJlbmNvZGVVUkkiLCJodHRwcyIsImdldCIsInJlcyIsInN0YXR1c0NvZGUiLCJoZWFkZXJzIiwibG9jYXRpb24iLCJkZWZhdWx0Q2FudmFzT3B0aW9ucyIsIndpZHRoIiwiaGVpZ2h0IiwicGFkZGluZyIsImJhY2tncm91bmRDb2xvciIsImhlYWRlckZvbnQiLCJyb3dGb250IiwiaGVhZGVyQ29sb3IiLCJyb3dDb2xvciIsImRlbGF5IiwibXMiLCJzZXRUaW1lb3V0IiwicGVyZkRlYnVnRW5hYmxlZCIsIlBFUkZfVkVSQk9TRSIsImRlYnVnTG9nIiwiZm9ybWF0VGFibGUiLCJ0aXRsZSIsInJvd3MiLCJjb2x1bW5XaWR0aHMiLCJoZWFkZXIiLCJyb3ciLCJmb3JtYXRSb3ciLCJwYWRFbmQiLCJoZWFkZXJMaW5lIiwiZGl2aWRlciIsInJlcGVhdCIsImJvZHkiLCJlbnN1cmVEaXJlY3RvcnkiLCJ0YXJnZXRQYXRoIiwibWtkaXIiLCJkaXJuYW1lIiwicmVuZGVyTWV0cmljc1RhYmxlVG9DYW52YXMiLCJvdXRwdXRQYXRoIiwiY29uZmlnIiwiY3JlYXRlQ2FudmFzIiwiY2FudmFzTW9kdWxlIiwiaW1wb3J0IiwiY2FudmFzIiwiY3R4IiwiZ2V0Q29udGV4dCIsImZpbGxTdHlsZSIsImZpbGxSZWN0IiwiZm9udCIsImNvbHVtbldpZHRoIiwiaGVhZGVyWSIsImZpbGxUZXh0Iiwicm93SGVpZ2h0Iiwicm93SW5kZXgiLCJ5IiwiY2VsbCIsImNlbGxJbmRleCIsInRvQnVmZmVyIiwiUGVyZm9ybWFuY2VSdW5uZXIiLCJzY2VuYXJpbyIsImluaXRpYWxpemUiLCJwaGFzZUNvdW50ZXIiLCJxdWV1ZSIsInBoYXNlcyIsInBoYXNlIiwicGhhc2VOdW1iZXIiLCJyZXN1bHRzIiwiaXRlbSIsInNoaWZ0IiwibWVyZ2VDb250ZXh0IiwiaXRlcmF0aW9ucyIsIm1vZGUiLCJjb25jdXJyZW5jeSIsImJ1cnN0IiwicnVuUGhhc2UiLCJ0b3RhbCIsImFnZ3JlZ2F0ZWQiLCJ0b3RhbER1cmF0aW9uTXMiLCJhdmciLCJhdmVyYWdlTXMiLCJmYWlsdXJlQ291bnQiLCJnZW5lcmF0b3IiLCJoaXN0b3J5U25hcHNob3QiLCJtZXRhZGF0YSIsInBoYXNlTmFtZSIsIml0ZXJhdGlvbkNvdW50IiwiYnVyc3RTZWdtZW50cyIsInNlZ21lbnRDb3VudCIsImhpc3RvcnkiLCJnZW5lcmF0b3JSZXN1bHQiLCJuZXh0UGhhc2UiLCJsb2dTdW1tYXJ5IiwicnVuV2FybXVwIiwic2VnbWVudHMiLCJidWlsZFNlZ21lbnRJbmRpY2VzIiwiY29sbGVjdGVkIiwic2VnbWVudEluZGV4IiwiaW5kaWNlcyIsIm1ldHJpY3MiLCJleGVjdXRlU2VnbWVudCIsImJ1cnN0SW50ZXJ2YWwiLCJpbnRlcnZhbE1zIiwic29ydGVkIiwic29ydCIsImEiLCJiIiwiaXRlcmF0aW9uIiwiYWdncmVnYXRlTWV0cmljcyIsInBhdXNlQWZ0ZXJNcyIsImZhaWxPbkVycm9yIiwiaXRlcmF0aW9uTWV0cmljcyIsIndhcm11cCIsImxvYWRGYWN0b3IiLCJjb21wdXRlTG9hZEZhY3RvciIsImRlbGF5QmV0d2Vlbkl0ZXJhdGlvbnNNcyIsImJhc2UiLCJsb2FkU3RhcnQiLCJzdGVwIiwibG9hZFN0ZXAiLCJtdWx0aXBsaWVyIiwibG9hZE11bHRpcGxpZXIiLCJjdXJzb3IiLCJlbmQiLCJfIiwiaWR4IiwiYmFzZUNvbnRleHQiLCJwaGFzZUNvbnRleHQiLCJtZXJnZUNvbnRleHRzIiwiY29sbGVjdENvbmN1cnJlbnQiLCJjb2xsZWN0U2VxdWVudGlhbCIsImRlbGF5QmV0d2VlbiIsInJ1bkl0ZXJhdGlvbiIsInBvaW50ZXIiLCJ3b3JrZXIiLCJhbGwiLCJzdG9wd2F0Y2giLCJTdG9wV2F0Y2giLCJzdWNjZXNzIiwibWV0YSIsImR1cmF0aW9uTXMiLCJzdG9wIiwibWluTXMiLCJtYXhNcyIsInN1Y2Nlc3NDb3VudCIsImxvYWRFbmQiLCJtZXRyaWMiLCJzaG91bGRSZW5kZXJDYW52YXMiLCJjaGFydFBhdGgiLCJjYW52YXNPdXRwdXRQYXRoIiwiY2FudmFzT3B0aW9ucyIsImVuYWJsZUNhbnZhcyIsIkJvb2xlYW4iLCJwYXJzZUxpc3QiLCJwYWNrYWdlVG9HbG9iYWwiLCJ3aXRob3V0U2NvcGUiLCJjaGFyQXQiLCJ0b1VwcGVyQ2FzZSIsImdldFBhY2thZ2VEZXBlbmRlbmNpZXMiLCJoYXNEZXBzIiwiZmFsbGJhY2tEaXIiLCJfX2Rpcm5hbWUiLCJWRVJTSU9OX1NUUklORyIsIlBBQ0tBR0VfU1RSSU5HIiwiUEFDS0FHRV9TSVpFX1NUUklORyIsIk1vZGVzIiwiQnVpbGRNb2RlIiwiYnVpbGRNb2RlIiwiQUxMIiwiZXh0ZXJuYWxzIiwiZG9jcyIsImNvbW1hbmRzIiwiY2pzMlRyYW5zZm9ybWVyIiwiZXh0IiwiQnVpbGRTY3JpcHRzIiwicmVzb2x1dGlvbkNhY2hlIiwiTWFwIiwidHJhbnNmb3JtYXRpb25Db250ZXh0Iiwic291cmNlRmlsZSIsInNvdXJjZURpciIsImZpbGVOYW1lIiwicmVzb2x2ZVBhdGgiLCJpbXBvcnRQYXRoIiwiY2FjaGVLZXkiLCJjYWNoZWRWYWx1ZSIsInJlc29sdmVkUGF0aCIsImUyIiwiaXNBYnNvbHV0ZSIsImV4dGVuc2lvbiIsImV4ZWMiLCJiYXNlbmFtZSIsInJlbGF0aXZlIiwic2V0IiwidmlzaXROb2RlIiwibm9kZSIsInNob3VsZE11dGF0ZU1vZHVsZVNwZWNpZmllciIsInRzIiwiaXNJbXBvcnREZWNsYXJhdGlvbiIsIm1vZHVsZVNwZWNpZmllciIsIm5ld01vZHVsZVNwZWNpZmllciIsImZhY3RvcnkiLCJjcmVhdGVTdHJpbmdMaXRlcmFsIiwidXBkYXRlSW1wb3J0RGVjbGFyYXRpb24iLCJtb2RpZmllcnMiLCJpbXBvcnRDbGF1c2UiLCJpc0V4cG9ydERlY2xhcmF0aW9uIiwidXBkYXRlRXhwb3J0RGVjbGFyYXRpb24iLCJpc1R5cGVPbmx5IiwiZXhwb3J0Q2xhdXNlIiwidmlzaXRFYWNoQ2hpbGQiLCJpc1N0cmluZ0xpdGVyYWwiLCJleHRuYW1lIiwicmVwbGFjZW1lbnRzIiwicGtnTmFtZSIsInBrZ1ZlcnNpb24iLCJwYXRjaEZpbGVzIiwiZmlsZSIsInBhcmVudFBhdGgiLCJyZXBvcnREaWFnbm9zdGljcyIsImRpYWdub3N0aWNzIiwibXNnIiwiZm9ybWF0RGlhZ25vc3RpY3MiLCJkaWFnbm9zdGljIiwic3RhcnQiLCJjaGFyYWN0ZXIiLCJnZXRMaW5lQW5kQ2hhcmFjdGVyT2ZQb3NpdGlvbiIsImZsYXR0ZW5EaWFnbm9zdGljTWVzc2FnZVRleHQiLCJtZXNzYWdlVGV4dCIsInJlYWRDb25maWdGaWxlIiwiY29uZmlnRmlsZU5hbWUiLCJjb25maWdGaWxlVGV4dCIsInBhcnNlQ29uZmlnRmlsZVRleHRUb0pzb24iLCJjb25maWdPYmplY3QiLCJMb2dMZXZlbCIsImNvbmZpZ1BhcnNlUmVzdWx0IiwicGFyc2VKc29uQ29uZmlnRmlsZUNvbnRlbnQiLCJzeXMiLCJldmFsRGlhZ25vc3RpY3MiLCJjYXRlZ29yeSIsIkRpYWdub3N0aWNDYXRlZ29yeSIsIndhcm5pbmdzIiwiV2FybmluZyIsInN1Z2dlc3Rpb25zIiwiU3VnZ2VzdGlvbiIsIm1lc3NhZ2VzIiwiTWVzc2FnZSIsInByZUNoZWNrRGlhZ25vc3RpY3MiLCJwcm9ncmFtIiwiZ2V0UHJlRW1pdERpYWdub3N0aWNzIiwiY2hlY2tUc0RpYWdub3N0aWNzIiwiaXNEZXYiLCJidW5kbGUiLCJ0c0NvbmZpZyIsIm1vZHVsZSIsIk1vZHVsZUtpbmQiLCJBTUQiLCJvdXREaXIiLCJpc29sYXRlZE1vZHVsZXMiLCJvdXRGaWxlIiwiRVNNIiwiRVMyMDIyIiwiQ29tbW9uSlMiLCJpbmxpbmVTb3VyY2VNYXAiLCJpbmxpbmVTb3VyY2VzIiwic291cmNlTWFwIiwiY3JlYXRlUHJvZ3JhbSIsImZpbGVOYW1lcyIsImJ1aWxkVHMiLCJ0cmFuc2Zvcm1hdGlvbnMiLCJDSlMiLCJiZWZvcmUiLCJlbWl0UmVzdWx0IiwiZW1pdCIsImFsbERpYWdub3N0aWNzIiwiY29uY2F0IiwiYnVpbGQiLCJjb3B5QXNzZXRzIiwiaGFzQXNzZXRzIiwiaXNMaWIiLCJlbnRyeUZpbGUiLCJuYW1lT3ZlcnJpZGUiLCJleHRlcm5hbHNBcmciLCJpbmNsdWRlQXJnIiwiaXNFc20iLCJpbmNsdWRlIiwiZXh0ZXJuYWxzTGlzdCIsImJ1aWx0aW5MaXN0IiwiYnVpbHRpbk1vZHVsZXMiLCJyb2xsdXBTb3VyY2VNYXBPdXRwdXQiLCJwbHVnaW5zIiwidHlwZXNjcmlwdCIsImNvbXBpbGVyT3B0aW9ucyIsImRlY2xhcmF0aW9uIiwiZXhjbHVkZSIsInRzY29uZmlnIiwianNvbiIsImNvbW1vbmpzIiwibm9kZVJlc29sdmUiLCJyZXNvbHZlT25seSIsInRlcnNlck1vZCIsInRlcnNlckZuIiwidGVyc2VyIiwidGVyc2VyT3B0aW9uc0RldiIsImVjbWEiLCJjb21wcmVzcyIsIm1hbmdsZSIsImNvbW1lbnRzIiwiYmVhdXRpZnkiLCJ0ZXJzZXJPcHRpb25zUHJvZCIsInBhc3NlcyIsImRyb3BfY29uc29sZSIsImRyb3BfZGVidWdnZXIiLCJ0b3BsZXZlbCIsInVuc2FmZSIsInVuc2FmZV9hcnJvd3MiLCJ1bnNhZmVfY29tcHMiLCJjb2xsYXBzZV92YXJzIiwicmVkdWNlX2Z1bmNzIiwicmVkdWNlX3ZhcnMiLCJhc2NpaV9vbmx5IiwiZXh0ZXJuYWwiLCJvbndhcm4iLCJ0cmVlc2hha2UiLCJnbG9iYWxzIiwib3V0cHV0cyIsImVzTW9kdWxlIiwic291cmNlbWFwIiwiZXhwb3J0cyIsInJvbGx1cCIsIndhdGNoRmlsZXMiLCJnZW5lcmF0ZU91dHB1dHMiLCJvdXRwdXRPcHRpb25zIiwid3JpdGUiLCJidWlsZEJ5RW52IiwiaW5jbHVkZXNBcmciLCJCVUlMRCIsIkJVTkRMRSIsImJ1aWxkRGV2IiwiYnVpbGRQcm9kIiwiYnVpbGREb2NzIiwic3JjIiwiY2kiLCJ0YWciLCJSZWxlYXNlU2NyaXB0IiwicHJlcGFyZVZlcnNpb24iLCJ0ZXN0VmVyc2lvbiIsInRvTG93ZXJDYXNlIiwiUEFUQ0giLCJNSU5PUiIsIk1BSk9SIiwicHJlcGFyZU1lc3NhZ2UiLCJSZWdleHBPdXRwdXRXcml0ZXIiLCJsYXN0SW5kZXgiLCJ0ZXN0QW5kUmVzb2x2ZSIsInRlc3RBbmRSZWplY3QiLCJWRVJTSU9OIiwiUEFDS0FHRV9OQU1FIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztNQXdFYUE7O1FBQ2FDLEtBQUFDLFNBQVNDLFFBQVFDLElBQUlKO0FBQVc7SUF3SnhELFdBQUFLLENBQVlDO1FBbkpaTCxLQUFBTSxPQUErRDtRQW9KN0ROLEtBQUtLLE9BQU9BO0FBQ2Q7SUFTQSxPQUFBRSxDQUFRRDtRQUNOUCxVQUFVRSxPQUFPTyxR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UkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQ0U7SUFDRkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQ0U7SUFDRkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQ0U7SUFDRkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQ0U7SUFDRkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTtHQUVSO0lBQ0VELFFBQVE7SUFDUkMsTUFBTTs7O0FDMXlCVixNQUFNQyxTQUFTLEVBQ2IsZUFDQSxlQUNBLGVBQ0EsZUFDQSxlQUNBLGVBQ0EsZUFDQSxlQUNBOztBQTRCSSxTQUFVQyxZQUFZcFQ7SUFDMUIsTUFBTVUsVUFBVTJTO0lBQ2hCLE1BQU1oTixTQUNKLDA1QkFPRDhFLE1BQU07SUFDUCxNQUFNbUksWUFBWWpOLE9BQU9JLE9BQU8sQ0FBQ2pGLEtBQUsrUixTQUFTQyxLQUFLaFMsSUFBSUEsS0FBSytSLEtBQUtoTCxTQUFTO0lBQzNFbEMsT0FBT2tGLEtBQUssTUFBTTdLLFFBQVErUyxTQUFTSCxZQUFZO0lBQy9Dak4sT0FBT3NHLFFBQVEsQ0FBQzRHLE1BQU1HO1NBQ25CMVQsU0FBU0EsT0FBT21GLEtBQUt3TyxLQUFLM1QsVUFBVTRULFFBQVFqUSxJQUFJZ1EsS0FBS0MsVUFDcEQ5UyxNQUFNeVMsUUFBUSxJQUFJTSxJQUFJVixPQUFPTyxRQUFRaE07O0FBRzNDOztBQTJCTSxTQUFVMkwsVUFBVS9IO0lBQ3hCO1FBQ0VBLFdBQ1NBLE1BQU0sY0FBY2tJLEtBQUtNLE1BQU1OLEtBQUtPLFdBQVdmLFFBQVF6SyxVQUFVK0M7UUFDMUUsT0FBTzBILFFBQVExSCxHQUFHMkg7QUFDcEIsTUFBRSxPQUFPOU87UUFDUCxNQUFNLElBQUlDLE1BQU0sK0JBQStCRDtBQUNqRDtBQUNGOztBQ3hFTSxNQUFnQjZQLGdCQUFzQkM7SUFRMUMsV0FBQTlULENBQ1lDLE1BQ0E4VCxTQUE0QixDQUFBLEdBQzVCQyxlQUF5QjtRQUVuQ0M7UUFKVXJVLEtBQUFLLE9BQUFBO1FBQ0FMLEtBQUFtVSxTQUFBQTtRQUNBblUsS0FBQW9VLGVBQUFBO1FBR1YsS0FBS0gsUUFBUXJRLEtBQUs7WUFDaEI0QyxPQUFPOE4sZUFBZUwsU0FBUyxPQUFPO2dCQUNwQ00sVUFBVTtnQkFDVjdULE9BQU9SLFFBQVFDLElBQUk4VCxRQUFRNVQ7O0FBRS9CO1FBQ0FMLEtBQUttVSxTQUFTM04sT0FBT29FLE9BQ25CLENBQUEsR0FDQTlFLHVCQUNBcU87QUFFSjtJQXdCVSx1QkFBTUs7UUFDZCxPQUFNMUUsTUFBRUEsTUFBSUUsS0FBRUEsS0FBR0UsTUFBRUEsY0FBZVQ7UUFDbEMsTUFBTWdGLFVBQVU7UUFDaEIsTUFBTUMsV0FBVzdRLE1BQU1xTixLQUNyQixJQUFJUCxJQUFJLEtBQUliLFNBQVNFLFFBQVFFLFFBQU96RCxVQUNwQ3pJLElBQUs0TyxLQUFNQSxFQUFFdlM7UUFDZixLQUFLLE1BQU13USxPQUFPN1EsS0FBS29VLGNBQ3JCLEtBQUtNLFNBQVN4SixTQUFTMkYsTUFBTTRELFFBQVFqSixLQUFLcUY7UUFFNUMsS0FBSzRELFFBQVFqTSxRQUFRO0FBQ3ZCO0lBVVUsSUFBQXRDLENBQUtUO1FBQ2IsT0FBT3pGLEtBQUs0RCxJQUFJd0IsS0FDZDtBQUVKO0lBK0NBLGFBQU11UDtRQUNKLE1BQU1sUCxPQUF3QjFGLFVBQVV3RixVQUFVdkYsS0FBS21VO1FBQ3ZELE1BQU14SixNQUFNaUssa0JBQWtCQyxXQUFXdE8sc0JBQXNCc08sV0FDN0RwUCxLQUFLZ0g7UUFFUCxPQUFNeEcsU0FBRUEsU0FBT0MsTUFBRUEsTUFBSUksUUFBRUEsVUFBV3FFO1FBRWxDLElBQUkxRSxTQUFTO1lBQ1gsT0FBT3VKO0FBQ1Q7UUFFQSxJQUFJdEosTUFBTTtZQUNSLE9BQU9sRyxLQUFLa0csS0FBS1Q7QUFDbkI7UUFFQSxJQUFJYSxRQUNGK00sWUFDRXJULEtBQUs0RCxJQUFJekQsSUFBSWtULGFBQWE7WUFDeEJoTixXQUFXO1lBQ1h0RixPQUFPO1lBQ1ArVCxTQUFTO1lBQ1QzTyxVQUFVOztRQUloQixJQUFJbkI7UUFFSjtZQUNFQSxlQUFlaEYsS0FBSytVLElBQUlwSztBQUMxQixVQUFFLE9BQU94RjtZQUNQLE1BQU1BO0FBQ1I7UUFFQSxPQUFPSDtBQUNUOzs7TUMxS1dnUTs7UUFDTWhWLEtBQUE0RCxNQUFNMUQsUUFBUUMsSUFBSTZVO0FBQVk7SUErQi9DLHlCQUFhQyxDQUFhQztRQUN4QixPQUFPLElBQUloTSxRQUFnQixDQUFDZCxTQUFTRztZQUNuQyxTQUFTNE0sUUFBUUQ7Z0JBQ2ZBLE1BQU1FLFVBQVVGO2dCQUNoQkcsTUFBTUMsSUFBSUosS0FBTUs7b0JBQ2QsSUFBSUEsSUFBSUMsZUFBZSxPQUFPRCxJQUFJQyxlQUFlLEtBQy9DLE9BQU9MLFFBQVFJLElBQUlFLFFBQVFDO29CQUU3QixJQUFJSCxJQUFJQyxlQUFlLEtBQUs7d0JBQzFCUixXQUFXcFIsSUFBSVEsTUFDYixtQkFBbUI4USxnQkFBZ0JLLElBQUlDO3dCQUV6QyxPQUFPak4sT0FBTyxJQUFJbEUsTUFBTSxtQkFBbUI2UTtBQUM3QztvQkFDQSxJQUFJM04sT0FBTztvQkFDWGdPLElBQUl6SixHQUFHLFFBQVNsRTt3QkFDZEwsUUFBUUs7O29CQUVWMk4sSUFBSXpKLEdBQUcsU0FBVTFIO3dCQUNmbUUsT0FBT25FOztvQkFHVG1SLElBQUl6SixHQUFHLE9BQU87d0JBQ1oxRCxRQUFRYjs7O0FBR2Q7WUFDQTROLFFBQVFEOztBQUVaOzs7QUN1RUssTUFBTVMsdUJBQXNEO0lBQ2pFQyxPQUFPO0lBQ1BDLFFBQVE7SUFDUkMsU0FBUztJQUNUQyxpQkFBaUI7SUFDakJDLFlBQVk7SUFDWkMsU0FBUztJQUNUQyxhQUFhO0lBQ2JDLFVBQVU7OztBQUdaLE1BQU1DLFFBQVNDLE1BQWUsSUFBSW5OLFFBQVNkLFdBQVlrTyxXQUFXbE8sU0FBU2lPOztBQUMzRSxNQUFNRSxtQkFBbUI3USxRQUFRaUYsSUFBSTZMLGlCQUFpQjs7QUFDdEQsTUFBTUMsV0FBVyxJQUFJaFI7SUFDbkIsSUFBSThRLGtCQUFrQjtRQUNwQjFDLFFBQVFoTyxTQUFTSjtBQUNuQjs7O0FBR0YsTUFBTWlSLGNBQWMsQ0FDbEJDLE9BQ0FsQixTQUNBbUI7SUFFQSxNQUFNQyxlQUFlcEIsUUFBUXpSLElBQUksQ0FBQzhTLFFBQVFuRCxVQUN4Q0YsS0FBS2hTLElBQUlxVixPQUFPdE8sV0FBV29PLEtBQUs1UyxJQUFLK1MsT0FBUUEsSUFBSXBELFFBQVFuTCxVQUFVO0lBRXJFLE1BQU13TyxZQUFhdkssVUFDakIsT0FDQUEsT0FDR3pJLElBQUksQ0FBQ3RELE9BQU9pVCxVQUFValQsTUFBTXVXLE9BQU9KLGFBQWFsRCxTQUNoRHpQLEtBQUssU0FDUjtJQUNGLE1BQU1nVCxhQUFhRixVQUFVdkI7SUFDN0IsTUFBTTBCLFVBQ0osT0FBT04sYUFBYTdTLElBQUs0UixTQUFVLElBQUl3QixPQUFPeEIsUUFBUTFSLEtBQUssU0FBUztJQUN0RSxNQUFNbVQsT0FBT1QsS0FBSzVTLElBQUlnVCxXQUFXOVMsS0FBSztJQUN0QyxPQUFPLEdBQUd5UyxVQUFVTyxlQUFlQyxZQUFZRTs7O0FBR2pELE1BQU1DLGtCQUFrQnJMLE1BQU9zTDtVQUN2QkMsTUFBTXBLLEtBQUtxSyxRQUFRRixhQUFhO1FBQUUxSSxXQUFXOzs7O0FBR3JELE1BQU02SSw2QkFBNkJ6TCxPQUNqQ3dKLFNBQ0FtQixNQUNBcFIsU0FDQW1TO0lBRUEsTUFBTUMsU0FBUztXQUFLakM7V0FBeUJuUTs7SUFFN0MsSUFBSXFTO0lBQ0o7UUFFRSxNQUFNQyxxQkFBcUJDLE9BQU87UUFDbENGLGVBQWVDLGFBQWFEO0FBQzlCLE1BQUUsT0FBT3pUO1FBQ1B5UCxRQUFROVEsS0FDTiw2REFDQXFCO1FBRUY7QUFDRjtJQUNBLE1BQU00VCxTQUFTSCxhQUFhRCxPQUFPaEMsT0FBT2dDLE9BQU8vQjtJQUNqRCxNQUFNb0MsTUFBTUQsT0FBT0UsV0FBVztJQUU5QkQsSUFBSUUsWUFBWVAsT0FBTzdCO0lBQ3ZCa0MsSUFBSUcsU0FBUyxHQUFHLEdBQUdSLE9BQU9oQyxPQUFPZ0MsT0FBTy9CO0lBRXhDb0MsSUFBSUksT0FBT1QsT0FBTzVCO0lBQ2xCaUMsSUFBSUUsWUFBWVAsT0FBTzFCO0lBQ3ZCLE1BQU1vQyxlQUFlVixPQUFPaEMsUUFBUWdDLE9BQU85QixVQUFVLEtBQUtMLFFBQVFqTjtJQUNsRSxNQUFNK1AsVUFBVVgsT0FBTzlCLFVBQVU7SUFFakNMLFFBQVE3SSxRQUFRLENBQUNrSyxRQUFRbkQ7UUFDdkJzRSxJQUFJTyxTQUFTMUIsUUFBUWMsT0FBTzlCLFVBQVV3QyxjQUFjM0UsT0FBTzRFOztJQUc3RE4sSUFBSUksT0FBT1QsT0FBTzNCO0lBQ2xCZ0MsSUFBSUUsWUFBWVAsT0FBT3pCO0lBQ3ZCLE1BQU1zQyxZQUFZO0lBQ2xCN0IsS0FBS2hLLFFBQVEsQ0FBQ21LLEtBQUsyQjtRQUNqQixNQUFNQyxJQUFJSixVQUFVLEtBQUtFLGFBQWFDLFdBQVc7UUFDakQzQixJQUFJbkssUUFBUSxDQUFDZ00sTUFBTUM7WUFDakJaLElBQUlPLFNBQVNJLE1BQU1oQixPQUFPOUIsVUFBVXdDLGNBQWNPLFdBQVdGOzs7VUFJM0RyQixnQkFBZ0JLO1VBQ2hCbEssWUFBVWtLLFlBQVlLLE9BQU9jLFNBQVM7SUFDNUNqRixRQUFRalEsSUFBSSwrQkFBK0IrVDs7O01BR2hDb0I7SUFDWCxXQUFBM1ksQ0FBK0I0WTtRQUFBaFosS0FBQWdaLFdBQUFBO0FBQTBDO0lBRWxFLFNBQU1qRTtRQUNYLElBQUkvVSxLQUFLZ1osU0FBU0MsWUFBWTtrQkFDdEJqWixLQUFLZ1osU0FBU0M7QUFDdEI7UUFFQSxJQUFJQyxlQUFlO1FBQ25CLE1BQU1DLFFBQW9DblosS0FBS2daLFNBQVNJLE9BQU9wVixJQUM1RHFWLFVBQUs7WUFBUUE7WUFBT0MsZUFBZUo7O1FBRXRDLE1BQU1LLFVBQW1DO1FBRXpDLE9BQU9KLE1BQU0zUSxRQUFRO1lBQ25CLE1BQU1nUixPQUFPTCxNQUFNTTtZQUNuQixNQUFNSixRQUFRRyxLQUFLSDtZQUNuQixNQUFNdkUsVUFBVTlVLEtBQUswWixhQUFhTDtZQUNsQ3hGLFFBQVF6TyxLQUNOLGdDQUFnQ29VLEtBQUtGLGdCQUFnQkQsTUFBTWhaLFNBQzNEO2dCQUNFc1osWUFBWU4sTUFBTXpCLE9BQU8rQjtnQkFDekJDLE1BQU1QLE1BQU16QixPQUFPZ0M7Z0JBQ25CQyxhQUFhUixNQUFNekIsT0FBT2lDO2dCQUMxQkMsT0FBT1QsTUFBTXpCLE9BQU9rQzs7WUFHeEIsTUFBTTlVLGVBQWVoRixLQUFLK1osU0FBU1YsT0FBT3ZFO1lBQzFDakIsUUFBUXpPLEtBQ04saUNBQWlDb1UsS0FBS0YsZ0JBQWdCRCxNQUFNaFosU0FDNUQ7Z0JBQ0UyWixPQUFPaFYsT0FBT2lWLFdBQVdDLGdCQUFnQjNILFFBQVE7Z0JBQ2pENEgsS0FBS25WLE9BQU9pVixXQUFXRyxVQUFVN0gsUUFBUTtnQkFDekM4SCxjQUFjclYsT0FBT2lWLFdBQVdJOztZQUdwQ2QsUUFBUS9OLEtBQUt4RztZQUViLElBQUlxVSxNQUFNaUIsV0FBVztnQkFDbkIsTUFBTUMsa0JBQWtCLEtBQUloQjtnQkFDNUIsTUFBTWlCLFdBQTZDO29CQUNqRGxCLGFBQWFFLEtBQUtGO29CQUNsQm1CLFdBQVdwQixNQUFNaFo7b0JBQ2pCcWEsZ0JBQWdCckIsTUFBTXpCLE9BQU8rQjtvQkFDN0JnQixlQUFlM1YsT0FBTzRWO29CQUN0QkEsY0FBYzVWLE9BQU80VjtvQkFDckJoQixNQUFNUCxNQUFNekIsT0FBT2dDO29CQUNuQmlCLFNBQVNOOztnQkFFWCxNQUFNTyx3QkFBd0J6QixNQUFNaUIsVUFBVTtvQkFDNUN0VjtvQkFDQTZWLFNBQVNOO29CQUNUQzs7Z0JBRUYsSUFBSU0saUJBQWlCO29CQUNuQixNQUFNQyxZQUNKLFlBQVlELGtCQUNSO3dCQUNFemEsTUFBTXlhLGdCQUFnQnphLFFBQVEsR0FBR2daLE1BQU1oWjt3QkFDdkN1WCxRQUFRa0QsZ0JBQWdCbEQ7d0JBQ3hCMEMsV0FBV2pCLE1BQU1pQjt3QkFFbkI7d0JBQ0VqYSxNQUFNLEdBQUdnWixNQUFNaFo7d0JBQ2Z1WCxRQUFRa0Q7d0JBQ1JSLFdBQVdqQixNQUFNaUI7O29CQUd6Qm5CLE1BQU0zTixLQUFLO3dCQUNUNk4sT0FBTzBCO3dCQUNQekIsZUFBZUo7O0FBRW5CO0FBQ0Y7QUFDRjtjQUVNbFosS0FBS2diLFdBQVd6QjtRQUN0QixPQUFPQTtBQUNUO0lBRVUsY0FBTVEsQ0FDZFYsT0FDQXZFO2NBRU05VSxLQUFLaWIsVUFBVTVCLE9BQU92RTtRQUM1QixNQUFNb0csV0FBV2xiLEtBQUttYixvQkFDcEI5QixNQUFNekIsT0FBTytCLFlBQ2JOLE1BQU16QixPQUFPa0M7UUFFZixNQUFNc0IsWUFBK0I7UUFFckMsS0FDRSxJQUFJQyxlQUFlLEdBQ25CQSxlQUFlSCxTQUFTMVMsUUFDeEI2UyxnQkFBZ0IsR0FDaEI7WUFDQSxNQUFNQyxVQUFVSixTQUFTRztZQUN6QixLQUFLQyxRQUFROVMsUUFBUTtnQkFDbkI7QUFDRjtZQUVBaU8sU0FDRSx1QkFBdUI0QyxNQUFNaFosMkJBQTJCZ2IsZUFBZSxLQUNyRUgsU0FBUzFTLHNCQUNLOFMsUUFBUSxNQUFNQSxRQUFRQSxRQUFROVMsU0FBUztZQUd6RCxNQUFNK1MsZ0JBQWdCdmIsS0FBS3diLGVBQ3pCeGIsS0FBS2daLFNBQVNqUCxTQUNkc1AsTUFBTXpCLFFBQ045QyxTQUNBd0c7WUFFRkYsVUFBVTVQLFFBQVErUDtZQUVsQixNQUFNRSxnQkFBZ0JwQyxNQUFNekIsT0FBT2tDLE9BQU80QjtZQUMxQyxJQUFJRCxpQkFBaUJKLGVBQWVILFNBQVMxUyxTQUFTLEdBQUc7c0JBQ2pENE4sTUFBTXFGO0FBQ2Q7QUFDRjtRQUVBLE1BQU1FLFNBQVMsS0FBSVAsWUFBV1EsS0FBSyxDQUFDQyxHQUFHQyxNQUFNRCxFQUFFRSxZQUFZRCxFQUFFQztRQUM3RCxNQUFNOUIsYUFBYWphLEtBQUtnYyxpQkFBaUJMO1FBRXpDLElBQUl0QyxNQUFNekIsT0FBT3FFLGNBQWM7a0JBQ3ZCN0YsTUFBTWlELE1BQU16QixPQUFPcUU7QUFDM0I7UUFFQSxJQUFJaEMsV0FBV0ksZUFBZSxLQUFLcmEsS0FBS2daLFNBQVNrRCxnQkFBZ0IsT0FBTztZQUN0RSxNQUFNLElBQUk3WCxNQUNSLFNBQVNnVixNQUFNaFosaUJBQWlCNFosV0FBV0k7QUFFL0M7UUFFQSxPQUFPO1lBQ0xoQjtZQUNBekIsUUFBUXlCLE1BQU16QjtZQUNkdUUsa0JBQWtCUjtZQUNsQjFCO1lBQ0FuRjtZQUNBOEYsY0FBY00sU0FBUzFTOztBQUUzQjtJQUVVLGVBQU15UyxDQUNkNUIsT0FDQXZFO1FBRUEsTUFBTXNILFNBQVMvQyxNQUFNekIsT0FBT3dFO1FBQzVCLEtBQUtBLFFBQVF6QyxZQUFZO1lBQ3ZCO0FBQ0Y7UUFFQSxNQUFNNVAsVUFBVXFTLE9BQU9yUyxXQUFXL0osS0FBS2daLFNBQVNqUDtRQUNoRCxLQUFLLElBQUk0SixRQUFRLEdBQUdBLFFBQVF5SSxPQUFPekMsWUFBWWhHLFNBQVMsR0FBRztrQkFDbkQ1SixRQUFRO2dCQUNaZ1MsV0FBV3BJO2dCQUNYaUUsUUFBUXlCLE1BQU16QjtnQkFDZHlFLFlBQVlyYyxLQUFLc2Msa0JBQWtCakQsTUFBTXpCLFFBQVFqRTtnQkFDakRtQjs7WUFFRixJQUFJc0gsT0FBT0csNEJBQTRCNUksUUFBUXlJLE9BQU96QyxhQUFhLEdBQUc7c0JBQzlEdkQsTUFBTWdHLE9BQU9HO0FBQ3JCO0FBQ0Y7QUFDRjtJQUVVLGlCQUFBRCxDQUNSMUUsUUFDQW1FO1FBRUEsTUFBTVMsT0FBTzVFLE9BQU82RSxhQUFhO1FBQ2pDLE1BQU1DLE9BQU85RSxPQUFPK0UsWUFBWTtRQUNoQyxNQUFNQyxhQUFhaEYsT0FBT2lGLGtCQUFrQjtRQUM1QyxRQUFRTCxPQUFPRSxPQUFPWCxhQUFhYTtBQUNyQztJQUVVLG1CQUFBekIsQ0FDUnhCLFlBQ0FHO1FBRUEsTUFBTUUsUUFBUXZHLEtBQUtoUyxJQUFJLEdBQUdrWTtRQUMxQixJQUFJSyxVQUFVLEdBQUc7WUFDZixPQUFPO0FBQ1Q7UUFFQSxNQUFNcFMsUUFDSmtTLE9BQU8vSCxRQUFRK0gsTUFBTS9ILE9BQU8sSUFBSTBCLEtBQUtsUyxJQUFJdVksTUFBTS9ILE1BQU1pSSxTQUFTQTtRQUNoRSxNQUFNa0IsV0FBdUI7UUFFN0IsS0FBSyxJQUFJNEIsU0FBUyxHQUFHQSxTQUFTOUMsT0FBTzhDLFVBQVVsVixPQUFPO1lBQ3BELE1BQU1tVixNQUFNdEosS0FBS2xTLElBQUl5WSxPQUFPOEMsU0FBU2xWO1lBQ3JDc1QsU0FBUzFQLEtBQ1AzSCxNQUFNcU4sS0FBSztnQkFBRTFJLFFBQVF1VSxNQUFNRDtlQUFVLENBQUNFLEdBQUdDLFFBQVFILFNBQVNHO0FBRTlEO1FBRUEsT0FBTy9CO0FBQ1Q7SUFFVSxZQUFBeEIsQ0FBYUw7UUFDckIsTUFBTTZELGNBQWNsZCxLQUFLZ1osU0FBU2tFLGVBQWdCLENBQUE7UUFDbEQsTUFBTUMsZUFBZTlELE1BQU16QixPQUFPOUMsV0FBWSxDQUFBO1FBQzlDLE9BQU85VSxLQUFLb2QsY0FBY0YsYUFBYUM7QUFDekM7SUFFVSxhQUFBQyxDQUFjdkIsR0FBYUM7UUFDbkMsT0FBT3RWLE9BQU9vRSxPQUFPLElBQUlpUixHQUFHQztBQUM5QjtJQUVVLG9CQUFNTixDQUNkelIsU0FDQTZOLFFBQ0E5QyxTQUNBd0c7UUFFQSxLQUFLQSxRQUFROVMsUUFBUTtZQUNuQixPQUFPO0FBQ1Q7UUFFQSxJQUFJb1AsT0FBT2dDLFNBQVMsY0FBYztZQUNoQyxPQUFPNVosS0FBS3FkLGtCQUFrQnRULFNBQVM2TixRQUFROUMsU0FBU3dHO0FBQzFEO1FBRUEsT0FBT3RiLEtBQUtzZCxrQkFBa0J2VCxTQUFTNk4sUUFBUTlDLFNBQVN3RztBQUMxRDtJQUVVLHVCQUFNZ0MsQ0FDZHZULFNBQ0E2TixRQUNBOUMsU0FDQXdHO1FBRUEsTUFBTUMsVUFBNkI7UUFDbkMsTUFBTWdDLGVBQWUzRixPQUFPMkU7UUFFNUIsS0FBSyxJQUFJVSxNQUFNLEdBQUdBLE1BQU0zQixRQUFROVMsUUFBUXlVLE9BQU8sR0FBRztZQUNoRDFCLFFBQVEvUCxXQUNBeEwsS0FBS3dkLGFBQWF6VCxTQUFTNk4sUUFBUTlDLFNBQVN3RyxRQUFRMkI7WUFFNUQsSUFBSU0sZ0JBQWdCTixNQUFNM0IsUUFBUTlTLFNBQVMsR0FBRztzQkFDdEM0TixNQUFNbUg7QUFDZDtBQUNGO1FBRUEsT0FBT2hDO0FBQ1Q7SUFFVSx1QkFBTThCLENBQ2R0VCxTQUNBNk4sUUFDQTlDLFNBQ0F3RztRQUVBLE1BQU16QixjQUFjcEcsS0FBS2hTLElBQ3ZCLEdBQ0FnUyxLQUFLbFMsSUFBSXFXLE9BQU9pQyxlQUFleUIsUUFBUTlTLFFBQVE4UyxRQUFROVM7UUFFekQsTUFBTStTLFVBQTZCO1FBQ25DLElBQUlrQyxVQUFVO1FBRWQsTUFBTUMsU0FBU3pSO1lBQ2IsT0FBT3dSLFVBQVVuQyxRQUFROVMsUUFBUTtnQkFDL0IsTUFBTXVULFlBQVlULFFBQVFtQztnQkFDMUJBLFdBQVc7Z0JBQ1hsQyxRQUFRL1AsV0FDQXhMLEtBQUt3ZCxhQUFhelQsU0FBUzZOLFFBQVE5QyxTQUFTaUg7QUFFdEQ7O2NBR0k3UyxRQUFReVUsSUFBSTlaLE1BQU1xTixLQUFLO1lBQUUxSSxRQUFRcVI7V0FBZSxNQUFNNkQ7UUFDNUQsT0FBT25DO0FBQ1Q7SUFFVSxrQkFBTWlDLENBQ2R6VCxTQUNBNk4sUUFDQTlDLFNBQ0FpSDtRQUVBLE1BQU1NLGFBQWFyYyxLQUFLc2Msa0JBQWtCMUUsUUFBUW1FO1FBQ2xELE1BQU02QixZQUFZLElBQUlDLFVBQVU7UUFDaEMsSUFBSUMsVUFBVTtRQUNkLElBQUlDO1FBRUp0SCxTQUNFLDBCQUEwQnNGLG9CQUFvQm5FLE9BQU80QyxVQUFVQyxhQUFhLGVBQWU0QixXQUFXOUosUUFDcEc7UUFHSjtZQUNFLE1BQU12TixlQUFlK0UsUUFBUTtnQkFBRWdTO2dCQUFXbkU7Z0JBQVF5RTtnQkFBWXZIOztZQUM5RCxXQUFXOVAsUUFBUThZLFlBQVksV0FBVztnQkFDeENBLFVBQVU5WSxPQUFPOFk7QUFDbkI7WUFDQUMsT0FBTy9ZLFFBQVErWTtBQUNqQixVQUFFLE9BQU8zWjtZQUNQMFosVUFBVTtZQUNWQyxPQUFPO2dCQUFFM1osT0FBT0EsaUJBQWlCQyxRQUFRRCxNQUFNekQsVUFBVWtILE9BQU96RDs7QUFDbEU7UUFFQSxNQUFNNFosYUFBYUosVUFBVUs7UUFDN0J4SCxTQUNFLDBCQUEwQnNGLHlCQUF5QmlDLFdBQVd6TCxRQUFRLGlCQUFpQnVMO1FBRXpGLE9BQU87WUFBRS9CO1lBQVdpQztZQUFZRjtZQUFTQztZQUFNMUI7O0FBQ2pEO0lBRVUsZ0JBQUFMLENBQWlCVDtRQUN6QixJQUFJQSxRQUFRL1MsV0FBVyxHQUFHO1lBQ3hCLE9BQU87Z0JBQ0wwUixpQkFBaUI7Z0JBQ2pCZ0UsT0FBTztnQkFDUEMsT0FBTztnQkFDUC9ELFdBQVc7Z0JBQ1hnRSxjQUFjO2dCQUNkL0QsY0FBYztnQkFDZG9DLFdBQVc7Z0JBQ1g0QixTQUFTOztBQUViO1FBRUEsTUFBTW5FLGtCQUFrQnFCLFFBQVE3VSxPQUM5QixDQUFDQyxLQUFLMlgsV0FBVzNYLE1BQU0yWCxPQUFPTixZQUM5QjtRQUVGLE1BQU1FLFFBQVF6SyxLQUFLbFMsT0FBT2dhLFFBQVF2WCxJQUFLc2EsVUFBV0EsT0FBT047UUFDekQsTUFBTUcsUUFBUTFLLEtBQUtoUyxPQUFPOFosUUFBUXZYLElBQUtzYSxVQUFXQSxPQUFPTjtRQUN6RCxNQUFNNUQsWUFBWUYsa0JBQWtCcUIsUUFBUS9TO1FBQzVDLE1BQU00VixlQUFlN0MsUUFBUTFTLE9BQVF5VixVQUFXQSxPQUFPUixTQUFTdFY7UUFDaEUsTUFBTTZSLGVBQWVrQixRQUFRL1MsU0FBUzRWO1FBQ3RDLE1BQU0zQixZQUFZbEIsUUFBUSxJQUFJYyxjQUFjO1FBQzVDLE1BQU1nQyxVQUFVOUMsUUFBUUEsUUFBUS9TLFNBQVMsSUFBSTZULGNBQWNJO1FBRTNELE9BQU87WUFDTHZDO1lBQ0FnRTtZQUNBQztZQUNBL0Q7WUFDQWdFO1lBQ0EvRDtZQUNBb0M7WUFDQTRCOztBQUVKO0lBRVUsZ0JBQU1yRCxDQUFXekI7UUFDekIsS0FBS0EsUUFBUS9RLFFBQVE7WUFDbkI7QUFDRjtRQUVBLE1BQU1pTixVQUFVLEVBQ2QsU0FDQSxRQUNBLGNBQ0EsWUFDQSxVQUNBLFVBQ0EsVUFDQSxXQUNBLFlBQ0E7UUFHRixNQUFNbUIsT0FBTzJDLFFBQVF2VixJQUFLZ0IsVUFBVyxFQUNuQ0EsT0FBT3FVLE1BQU1oWixNQUNiMkUsT0FBTzRTLE9BQU9nQyxNQUNkNVUsT0FBTzRTLE9BQU8rQixXQUFXNVUsWUFDekJDLE9BQU9pVixXQUFXQyxnQkFBZ0IzSCxRQUFRLElBQzFDdk4sT0FBT2lWLFdBQVdHLFVBQVU3SCxRQUFRLElBQ3BDdk4sT0FBT2lWLFdBQVdpRSxNQUFNM0wsUUFBUSxJQUNoQ3ZOLE9BQU9pVixXQUFXa0UsTUFBTTVMLFFBQVEsSUFDaEN2TixPQUFPaVYsV0FBV21FLGFBQWFyWixZQUMvQkMsT0FBT2lWLFdBQVdJLGFBQWF0VixZQUMvQixHQUFHQyxPQUFPaVYsV0FBV3dDLFVBQVVsSyxRQUFRLFFBQVF2TixPQUFPaVYsV0FBV29FLFFBQVE5TCxRQUFRO1FBR25Gc0IsUUFBUWpRLElBQ044UyxZQUNFLDJCQUEyQjFXLEtBQUtnWixTQUFTM1ksUUFDekNvVixTQUNBbUI7UUFJSixJQUFJNVcsS0FBS3VlLHNCQUFzQjtZQUM3QixNQUFNQyxZQUNKeGUsS0FBS2daLFNBQVN5RixvQkFDZHJSLEtBQUtsSixLQUNId0IsUUFBUWdGLE9BQ1IsWUFDQSxXQUNBO2tCQUVFZ04sMkJBQ0pqQyxTQUNBbUIsTUFDQTVXLEtBQUtnWixTQUFTMEYsaUJBQWlCL0ksc0JBQy9CNkk7QUFFSjtBQUNGO0lBRVUsa0JBQUFEO1FBQ1IsT0FBT3ZlLEtBQUtnWixTQUFTMkYsZ0JBQWdCQyxRQUFRNWUsS0FBS2daLFNBQVMwRjtBQUM3RDs7O0FDcm1CSSxTQUFVRyxVQUFVamE7SUFDeEIsS0FBS0EsT0FBTyxPQUFPO0lBQ25CLElBQUlmLE1BQU1DLFFBQVFjLFFBQ2hCLE9BQU9BLE1BQU1aLElBQUt1SCxLQUFNLEdBQUdBLElBQUlqRCxRQUFRTyxPQUFPK1Y7SUFDaEQsT0FBTyxHQUFHaGEsUUFDUHdHLE1BQU0sS0FDTnBILElBQUs4RSxLQUFNQSxFQUFFUixRQUNiTyxPQUFPK1Y7QUFDWjs7QUFFTSxTQUFVRSxnQkFBZ0J6ZTtJQUU5QixNQUFNMGUsZUFBZTFlLEtBQUs0TSxRQUFRLE1BQU07SUFDeEMsTUFBTXRFLFFBQVFvVyxhQUFhM1QsTUFBTSxZQUFZdkMsT0FBTytWO0lBQ3BELE9BQU9qVyxNQUNKM0UsSUFBSSxDQUFDOEUsR0FBR3lDLE1BQ1BBLE1BQU0sSUFDRnpDLEVBQUVtRSxRQUFRLGlCQUFpQixNQUMzQixHQUFHbkUsRUFBRWtXLE9BQU8sR0FBR0MsZ0JBQWdCblcsRUFBRWxELE1BQU0sTUFFNUMxQixLQUFLO0FBQ1Y7O1NBRWdCZ2I7SUFFZCxJQUFJN1A7SUFDSjtRQUNFQSxNQUFNRixXQUFXekosUUFBUWdGO0FBQzNCLE1BQUU7UUFDQTJFLE1BQU01SztBQUNSO0lBR0E7UUFDRSxNQUFNMGEsVUFDSjlQLFFBQ0M3SSxPQUFPQyxLQUFLNEksSUFBSVUsZ0JBQWdCLENBQUEsR0FBSXZILFNBQVMsS0FDNUNoQyxPQUFPQyxLQUFLNEksSUFBSVksbUJBQW1CLENBQUEsR0FBSXpILFNBQVMsS0FDaERoQyxPQUFPQyxLQUFLNEksSUFBSWMsb0JBQW9CLENBQUEsR0FBSTNILFNBQVM7UUFDckQsS0FBSzJXLFNBQVM7WUFDWixNQUFNQyxjQUFjaFMsS0FBS2hGLFFBQVFpWCxXQUFXO1lBQzVDO2dCQUNFaFEsTUFBTUYsV0FBV2lRO0FBQ25CLGNBQUUsT0FFRjtBQUNGO0FBQ0YsTUFBRSxPQUVGO0lBRUEsTUFBTTVPLE9BQU9oSyxPQUFPQyxLQUFNNEksT0FBT0EsSUFBSVUsZ0JBQWlCO0lBQ3RELE1BQU1HLE9BQU8xSixPQUFPQyxLQUFNNEksT0FBT0EsSUFBSWMsb0JBQXFCO0lBQzFELE1BQU1ILE1BQU14SixPQUFPQyxLQUFNNEksT0FBT0EsSUFBSVksbUJBQW9CO0lBQ3hELE9BQU9wTSxNQUFNcU4sS0FBSyxJQUFJUCxJQUFJLEtBQUlILFNBQVNOLFNBQVNGO0FBQ2xEOztBQUVBLE1BQU1zUCxpQkFBaUI7O0FBQ3ZCLE1BQU1DLGlCQUFpQjs7QUFDdkIsTUFBTUMsc0JBQXNCOztBQUU1QixJQUFLQzs7Q0FBTCxTQUFLQTtJQUNIQSxNQUFBLFNBQUE7SUFDQUEsTUFBQSxTQUFBO0FBQ0QsRUFIRCxDQUFLQSxVQUFBQSxRQUFLLENBQUE7O0FBS1YsSUFBS0M7O0NBQUwsU0FBS0E7SUFDSEEsVUFBQSxXQUFBO0lBQ0FBLFVBQUEsWUFBQTtJQUNBQSxVQUFBLFNBQUE7QUFDRCxFQUpELENBQUtBLGNBQUFBLFlBQVMsQ0FBQTs7QUFNZCxNQUFNbGEsWUFBVTtJQUNkc0ssTUFBTTtRQUNKeFAsTUFBTTtRQUNOMEYsU0FBUzs7SUFFWGdLLEtBQUs7UUFDSDFQLE1BQU07UUFDTjBGLFNBQVM7O0lBRVgyWixXQUFXO1FBQ1RyZixNQUFNO1FBQ04wRixTQUFTMFosVUFBVUU7O0lBRXJCMVUsVUFBVTtRQUNSNUssTUFBTTtRQUNOMEYsU0FBUzs7SUFFWDZaLFdBQVc7UUFDVHZmLE1BQU07UUFDTjBGLFNBQVM7O0lBRVg4WixNQUFNO1FBQ0p4ZixNQUFNO1FBQ04wRixTQUFTOztJQUVYK1osVUFBVTtRQUNSemYsTUFBTTtRQUNOMEYsU0FBUzs7SUFFWCtILE9BQU87UUFDTHpOLE1BQU07UUFDTjBGLFNBQVM7O0lBRVhNLFFBQVE7UUFDTmhHLE1BQU07UUFDTjBGLFNBQVM7Ozs7QUFJYixNQUFNZ2Esa0JBQWtCLENBQUNDLE1BQU07SUFDN0IsTUFBTXJjLE1BQU1zYyxhQUFhdGMsSUFBSXpELElBQUk2ZjtJQUNqQyxNQUFNRyxrQkFBa0IsSUFBSUM7SUFFNUIsT0FBUUMseUJBQ0VDO1FBQ04sTUFBTUMsWUFBWW5ULEtBQUtxSyxRQUFRNkksV0FBV0U7UUFFMUMsU0FBU0MsWUFBWUM7WUFDbkIsTUFBTUMsV0FBV2xlLEtBQUtDLFVBQVUsRUFBQzZkLFdBQVdHO1lBQzVDLE1BQU1FLGNBQWNULGdCQUFnQjdLLElBQUlxTDtZQUN4QyxJQUFJQyxlQUFlLE1BQU0sT0FBT0E7WUFFaEMsSUFBSUMsZUFBZUg7WUFDbkI7Z0JBQ0VHLGVBQWV6VCxLQUFLaEYsUUFBUW1ZLFdBQVdNLGVBQWU7QUFDeEQsY0FBRSxPQUFPemM7Z0JBQ1AsTUFBTSxJQUFJQyxNQUFNLDBCQUEwQnFjLGVBQWV0YztBQUMzRDtZQUNBLElBQUk2SjtZQUNKO2dCQUNFQSxPQUFPWixHQUFHYSxTQUFTMlM7QUFDckIsY0FBRSxPQUFPMWI7Z0JBQ1A7b0JBQ0V2QixJQUFJcEQsUUFDRiw2QkFBNkJxZ0I7b0JBRS9CNVMsT0FBT1osR0FBR2EsU0FBUzJTLGFBQWE1VCxRQUFRLFdBQVc7QUFDckQsa0JBQUUsT0FBTzZUO29CQUNQLE1BQU0sSUFBSXpjLE1BQ1IsMEJBQTBCcWMsZUFBZXZiLE1BQU0yYjtBQUVuRDtBQUNGO1lBQ0EsSUFBSTdTLEtBQUtHLGVBQ1B5UyxlQUFlQSxhQUFhNVQsUUFBUSxXQUFXO1lBRWpELElBQUlHLEtBQUsyVCxXQUFXRixlQUFlO2dCQUNqQyxNQUFNRyxhQUNILFVBQVVDLEtBQUs3VCxLQUFLOFQsU0FBU0wsa0JBQWtCLElBQUksV0FBVztnQkFFakVBLGVBQ0UsT0FDQXpULEtBQUsrVCxTQUNIWixXQUNBblQsS0FBS2hGLFFBQ0hnRixLQUFLcUssUUFBUW9KLGVBQ2J6VCxLQUFLOFQsU0FBU0wsY0FBY0csYUFBYWY7QUFHakQ7WUFFQUUsZ0JBQWdCaUIsSUFBSVQsVUFBVUU7WUFDOUIsT0FBT0E7QUFDVDtRQUVBLFNBQVNRLFVBQVVDO1lBQ2pCLElBQUlDLDRCQUE0QkQsT0FBTztnQkFDckMsSUFBSUUsR0FBR0Msb0JBQW9CSCxPQUFPO29CQUNoQyxNQUFNVCxlQUFlSixZQUFZYSxLQUFLSSxnQkFBZ0IvWjtvQkFDdEQsTUFBTWdhLHFCQUNKdEIsc0JBQXNCdUIsUUFBUUMsb0JBQW9CaEI7b0JBQ3BELE9BQU9SLHNCQUFzQnVCLFFBQVFFLHdCQUNuQ1IsTUFDQUEsS0FBS1MsV0FDTFQsS0FBS1UsY0FDTEwsb0JBQ0FsZDtBQUVKLHVCQUFPLElBQUkrYyxHQUFHUyxvQkFBb0JYLE9BQU87b0JBQ3ZDLE1BQU1ULGVBQWVKLFlBQVlhLEtBQUtJLGdCQUFnQi9aO29CQUN0RCxNQUFNZ2EscUJBQ0p0QixzQkFBc0J1QixRQUFRQyxvQkFBb0JoQjtvQkFDcEQsT0FBT1Isc0JBQXNCdUIsUUFBUU0sd0JBQ25DWixNQUNBQSxLQUFLUyxXQUNMVCxLQUFLYSxZQUNMYixLQUFLYyxjQUNMVCxvQkFDQWxkO0FBRUo7QUFDRjtZQUVBLE9BQU8rYyxHQUFHYSxlQUFlZixNQUFNRCxXQUFXaEI7QUFDNUM7UUFFQSxTQUFTa0IsNEJBQTRCRDtZQU1uQyxLQUFLRSxHQUFHQyxvQkFBb0JILFVBQVVFLEdBQUdTLG9CQUFvQlgsT0FDM0QsT0FBTztZQUVULElBQUlBLEtBQUtJLG9CQUFvQmpkLFdBQVcsT0FBTztZQUUvQyxLQUFLK2MsR0FBR2MsZ0JBQWdCaEIsS0FBS0ksa0JBQWtCLE9BQU87WUFFdEQsS0FDR0osS0FBS0ksZ0JBQWdCL1osS0FBS21MLFdBQVcsVUFDckN3TyxLQUFLSSxnQkFBZ0IvWixLQUFLbUwsV0FBVyxRQUV0QyxPQUFPO1lBRVQsSUFBSTFGLEtBQUttVixRQUFRakIsS0FBS0ksZ0JBQWdCL1osVUFBVSxJQUFJLE9BQU87WUFDM0QsT0FBTztBQUNUO1FBRUEsT0FBTzZaLEdBQUdILFVBQVVmLFlBQVllOzs7O0FBYWhDLE1BQU9uQixxQkFBcUJqTTtJQVFoQyxXQUFBN1Q7UUFDRWlVLE1BQ0UsZ0JBQ0E3TixPQUFPb0UsT0FBTyxDQUFBLEdBQUk5RSx1QkFBdUJOO1FBUHJDeEYsS0FBQXdpQixlQUF1QyxDQUFBO1FBVzdDLE1BQU1uVCxNQUFNRjtRQUNaLE9BQU05TyxNQUFFQSxNQUFJNEYsU0FBRUEsV0FBWW9KO1FBQzFCclAsS0FBS3lpQixVQUFVcGlCLEtBQUs2SyxTQUFTLE9BQU83SyxLQUFLK0ssTUFBTSxLQUFLLEtBQUsvSztRQUN6REwsS0FBSzBpQixhQUFhemM7UUFDbEJqRyxLQUFLd2lCLGFBQWFsRCxrQkFBa0J0ZixLQUFLMGlCO1FBQ3pDMWlCLEtBQUt3aUIsYUFBYWpELGtCQUFrQmxmO0FBQ3RDO0lBUUEsVUFBQXNpQixDQUFXN1o7UUFDVCxNQUFNbEYsTUFBTTVELEtBQUs0RCxJQUFJekQsSUFBSUgsS0FBSzJpQjtRQUM5QixPQUFNdGlCLE1BQUVBLE1BQUk0RixTQUFFQSxXQUFZa0o7UUFDMUJ2TCxJQUFJd0IsS0FBSyxZQUFZL0UsUUFBUTRGLHFCQUFxQjZDO1FBQ2xELE1BQU1tRixPQUFPWixHQUFHYSxTQUFTcEY7UUFDekIsSUFBSW1GLEtBQUtHLGVBQ1BmLEdBQUdTLFlBQVloRixHQUFHO1lBQUU0SixlQUFlO1lBQU03RCxXQUFXO1dBQ2pEaEcsT0FBUUMsS0FBTUEsRUFBRXFGLFVBQ2hCdkIsUUFBU2dXLFFBQ1J6VixVQUNFQyxLQUFLbEosS0FBSzBlLEtBQUtDLFlBQVlELEtBQUt2aUIsT0FDaENtRyxPQUFPbUcsUUFBUTNNLEtBQUt3aUIsY0FBYzliLE9BQ2hDLENBQUNDLE1BQTJCQyxLQUFLaUc7WUFDL0IsUUFBUWpHO2NBQ04sS0FBSzBZO2dCQUNIMWIsSUFBSWlDLE1BQU07Z0JBQ1ZjLElBQUksY0FBYzJZLHNCQUNoQixjQUFjelM7Z0JBQ2hCOztjQUNGLEtBQUswUztnQkFDSDNiLElBQUlpQyxNQUFNO2dCQUNWYyxJQUFJLG1CQUFtQjRZLHNCQUNyQixtQkFBbUIxUztnQkFDckI7O2NBQ0Y7Z0JBQ0VsRyxJQUFJQyxPQUFPaUc7O1lBRWYsT0FBT2xHO1dBRVQsQ0FBQTtRQUlWL0MsSUFBSXBELFFBQVEsVUFBVUgsUUFBUTRGLHNCQUFzQjZDO0FBQ3REO0lBRVEsaUJBQUFnYSxDQUNOQyxhQUNBNWM7UUFFQSxNQUFNNmMsTUFBTWhqQixLQUFLaWpCLGtCQUFrQkY7UUFDbkM7WUFDRS9pQixLQUFLNEQsSUFBSXVDLFVBQVU2YztBQUNyQixVQUFFLE9BQU83ZDtZQUNQME8sUUFBUTlRLEtBQUssNEJBQTRCb0Q7WUFDekMsTUFBTWhCO0FBQ1I7UUFDQSxPQUFPNmQ7QUFDVDtJQUdRLGlCQUFBQyxDQUFrQkY7UUFDeEIsT0FBT0EsWUFDSi9lLElBQUtrZjtZQUNKLElBQUl2aUIsVUFBVTtZQUNkLElBQUl1aUIsV0FBV04sUUFBUU0sV0FBV0MsT0FBTztnQkFDdkMsT0FBTTNQLE1BQUVBLE1BQUk0UCxXQUFFQSxhQUNaRixXQUFXTixLQUFLUyw4QkFBOEJILFdBQVdDO2dCQUMzRHhpQixXQUFXLEdBQUd1aUIsV0FBV04sS0FBS3BDLGFBQWFoTixPQUFPLEtBQUs0UCxZQUFZO0FBQ3JFO1lBQ0F6aUIsV0FDRSxPQUFPNmdCLEdBQUc4Qiw2QkFBNkJKLFdBQVdLLGFBQWE7WUFDakUsT0FBTzVpQjtXQUVSdUQsS0FBSztBQUNWO0lBRVEsY0FBQXNmLENBQWVDO1FBRXJCLE1BQU1DLGlCQUFpQnJXLEdBQUdLLGFBQWErVixnQkFBZ0IxZTtRQUd2RCxNQUFNQyxTQUFTd2MsR0FBR21DLDBCQUEwQkYsZ0JBQWdCQztRQUM1RCxNQUFNRSxlQUFlNWUsT0FBTzRTO1FBQzVCLEtBQUtnTSxjQUFjO1lBQ2pCNWpCLEtBQUs4aUIsa0JBQWtCLEVBQUM5ZCxPQUFPWixTQUFTeWYsU0FBU3pmO0FBQ25EO1FBR0EsTUFBTTBmLG9CQUFvQnRDLEdBQUd1QywyQkFDM0JILGNBQ0FwQyxHQUFHd0MsS0FDSDVXLEtBQUtxSyxRQUFRZ007UUFFZixJQUFJSyxrQkFBa0JoYyxPQUFPVSxTQUFTLEdBQ3BDeEksS0FBSzhpQixrQkFBa0JnQixrQkFBa0JoYyxRQUFRK2IsU0FBU3pmO1FBRTVELE9BQU8wZjtBQUNUO0lBRVEsZUFBQUcsQ0FBZ0JsQjtRQUN0QixJQUFJQSxlQUFlQSxZQUFZdmEsU0FBUyxHQUFHO1lBQ3pDLE1BQU1WLFNBQVNpYixZQUFZbGEsT0FDeEIrSixLQUFNQSxFQUFFc1IsYUFBYTFDLEdBQUcyQyxtQkFBbUI5ZjtZQUU5QyxNQUFNK2YsV0FBV3JCLFlBQVlsYSxPQUMxQitKLEtBQU1BLEVBQUVzUixhQUFhMUMsR0FBRzJDLG1CQUFtQkU7WUFFOUMsTUFBTUMsY0FBY3ZCLFlBQVlsYSxPQUM3QitKLEtBQU1BLEVBQUVzUixhQUFhMUMsR0FBRzJDLG1CQUFtQkk7WUFFOUMsTUFBTUMsV0FBV3pCLFlBQVlsYSxPQUMxQitKLEtBQU1BLEVBQUVzUixhQUFhMUMsR0FBRzJDLG1CQUFtQk07WUFJOUMsSUFBSUwsU0FBUzViLFFBQVF4SSxLQUFLOGlCLGtCQUFrQnNCLFVBQVVQLFNBQVM5Z0I7WUFDL0QsSUFBSStFLE9BQU9VLFFBQVE7Z0JBQ2pCeEksS0FBSzhpQixrQkFBa0JDLGFBQTZCYyxTQUFTemY7Z0JBQzdELE1BQU0sSUFBSUMsTUFDUix1QkFBdUIwZSxZQUFZdmE7QUFFdkM7WUFDQSxJQUFJOGIsWUFBWTliLFFBQ2R4SSxLQUFLOGlCLGtCQUFrQndCLGFBQWFULFNBQVN6ZTtZQUMvQyxJQUFJb2YsU0FBU2hjLFFBQVF4SSxLQUFLOGlCLGtCQUFrQjBCLFVBQVVYLFNBQVN6ZTtBQUNqRTtBQUNGO0lBRVEsbUJBQUFzZixDQUFvQkM7UUFDMUIsTUFBTTVCLGNBQWN2QixHQUFHb0Qsc0JBQXNCRDtRQUM3QzNrQixLQUFLaWtCLGdCQUFnQmxCO0FBQ3ZCO0lBR1Esd0JBQU04QixDQUNaQyxPQUNBbEwsTUFDQW1MLFNBQVM7UUFFVCxNQUFNbmhCLE1BQU01RCxLQUFLNEQsSUFBSXpELElBQUlILEtBQUs2a0I7UUFDOUIsSUFBSUc7UUFDSjtZQUNFQSxXQUFXaGxCLEtBQUt3akIsZUFBZTtBQUNqQyxVQUFFLE9BQU9yZTtZQUNQLE1BQU0sSUFBSWQsTUFBTSxrQ0FBa0NjO0FBQ3BEO1FBRUEsSUFBSTRmLFFBQVE7WUFDVkMsU0FBU3hmLFFBQVF5ZixTQUFTQyxXQUFXQztZQUNyQ0gsU0FBU3hmLFFBQVE0ZixTQUFTO1lBQzFCSixTQUFTeGYsUUFBUTZmLGtCQUFrQjtZQUNuQ0wsU0FBU3hmLFFBQVE4ZixVQUFVdGxCLEtBQUt5aUI7QUFDbEMsZUFBTztZQUNMdUMsU0FBU3hmLFFBQVE0ZixTQUFTLE1BQU14TCxTQUFTNkYsTUFBTThGLE1BQU0sU0FBUztZQUM5RFAsU0FBU3hmLFFBQVF5ZixTQUNmckwsU0FBUzZGLE1BQU04RixNQUFNTCxXQUFXTSxTQUFTTixXQUFXTztBQUN4RDtRQU1BVCxTQUFTeGYsUUFBUWtnQixrQkFBa0I7UUFDbkNWLFNBQVN4ZixRQUFRbWdCLGdCQUFnQjtRQUNqQ1gsU0FBU3hmLFFBQVFvZ0IsWUFBWTtRQUU3QixNQUFNakIsVUFBVW5ELEdBQUdxRSxjQUFjYixTQUFTYyxXQUFXZCxTQUFTeGY7UUFDOUR4RixLQUFLMGtCLG9CQUFvQkM7UUFDekIvZ0IsSUFBSXBELFFBQ0YsNkJBQTZCdWtCLFNBQVMsV0FBVztBQUVyRDtJQUVRLGFBQU1nQixDQUFRakIsT0FBZ0JsTCxNQUFhbUwsU0FBUztRQUMxRCxNQUFNbmhCLE1BQU01RCxLQUFLNEQsSUFBSXpELElBQUlILEtBQUsrbEI7UUFDOUJuaUIsSUFBSXdCLEtBQ0YsWUFBWXBGLEtBQUt5aUIsV0FBV3ppQixLQUFLMGlCLHNCQUFzQjlJLFlBQVlrTCxRQUFRLFFBQVE7UUFFckYsSUFBSUU7UUFDSjtZQUNFQSxXQUFXaGxCLEtBQUt3akIsZUFBZTtBQUNqQyxVQUFFLE9BQU9yZTtZQUNQLE1BQU0sSUFBSWQsTUFBTSxrQ0FBa0NjO0FBQ3BEO1FBRUEsSUFBSTRmLFFBQVE7WUFDVkMsU0FBU3hmLFFBQVF5ZixTQUFTQyxXQUFXQztZQUNyQ0gsU0FBU3hmLFFBQVE0ZixTQUFTO1lBQzFCSixTQUFTeGYsUUFBUTZmLGtCQUFrQjtZQUNuQ0wsU0FBU3hmLFFBQVE4ZixVQUFVdGxCLEtBQUt5aUI7QUFDbEMsZUFBTztZQUNMdUMsU0FBU3hmLFFBQVE0ZixTQUFTLE1BQU14TCxTQUFTNkYsTUFBTThGLE1BQU0sU0FBUztZQUM5RFAsU0FBU3hmLFFBQVF5ZixTQUNmckwsU0FBUzZGLE1BQU04RixNQUFNTCxXQUFXTSxTQUFTTixXQUFXTztBQUN4RDtRQUtBLElBQUlYLE9BQU87WUFDVEUsU0FBU3hmLFFBQVFrZ0Isa0JBQWtCO1lBQ25DVixTQUFTeGYsUUFBUW1nQixnQkFBZ0I7WUFDakNYLFNBQVN4ZixRQUFRb2dCLFlBQVk7QUFDL0IsZUFBTztZQUNMWixTQUFTeGYsUUFBUWtnQixrQkFBa0I7WUFDbkNWLFNBQVN4ZixRQUFRbWdCLGdCQUFnQjtZQUNqQ1gsU0FBU3hmLFFBQVFvZ0IsWUFBWTtBQUMvQjtRQUtBLE1BQU1qQixVQUFVbkQsR0FBR3FFLGNBQWNiLFNBQVNjLFdBQVdkLFNBQVN4ZjtRQUU5RCxNQUFNd2dCLGtCQUFzQyxDQUFBO1FBQzVDLElBQUlwTSxTQUFTNkYsTUFBTXdHLEtBQUs7WUFDdEJELGdCQUFnQkUsU0FBUyxFQUFDbEcsZ0JBQWdCO0FBQzVDLGVBQU8sSUFBSXBHLFNBQVM2RixNQUFNOEYsS0FBSztZQUM3QlMsZ0JBQWdCRSxTQUFTLEVBQUNsRyxnQkFBZ0I7QUFDNUM7UUFFQSxNQUFNbUcsYUFBeUJ4QixRQUFReUIsS0FDckMzaEIsV0FDQUEsV0FDQUEsV0FDQUEsV0FDQXVoQjtRQUdGLE1BQU1LLGlCQUFpQjdFLEdBQ3BCb0Qsc0JBQXNCRCxTQUN0QjJCLE9BQU9ILFdBQVdwRDtRQUVyQi9pQixLQUFLaWtCLGdCQUFnQm9DO0FBQ3ZCO0lBRVEsV0FBTUUsQ0FBTXpCLE9BQWdCbEwsTUFBYW1MLFNBQVM7UUFDeEQsTUFBTW5oQixNQUFNNUQsS0FBSzRELElBQUl6RCxJQUFJSCxLQUFLdW1CO2NBQ3hCdm1CLEtBQUsrbEIsUUFBUWpCLE9BQU9sTCxNQUFNbUw7UUFFaENuaEIsSUFBSXBELFFBQ0YsVUFBVVIsS0FBS3lpQixXQUFXemlCLEtBQUswaUIsZUFBZTlJLGtCQUFrQmtMLFFBQVEsUUFBUTtRQUVsRixJQUFJbEwsU0FBUzZGLE1BQU13RyxRQUFRbEIsUUFBUTtZQUNqQyxNQUFNbFgsUUFBUUQsWUFDWixPQUNDZ1YsUUFBU0EsS0FBS2hSLFNBQVMsV0FBV2dSLEtBQUsxWCxTQUFTO1lBR25ELEtBQUssTUFBTTBYLFFBQVEvVSxPQUFPO2dCQUN4QmpLLElBQUlwRCxRQUFRLFlBQVlvaUI7Z0JBQ3hCLE1BQU0zWixJQUFJMlosS0FBSzNWLFFBQVEsT0FBTztzQkFDeEJvQixXQUFXdVUsTUFBTTNaO0FBQ3pCO0FBQ0Y7QUFDRjtJQVFBLFVBQUF1ZCxDQUFXNU07UUFDVCxNQUFNaFcsTUFBTTVELEtBQUs0RCxJQUFJekQsSUFBSUgsS0FBS3dtQjtRQUM5QixJQUFJQyxZQUFZO1FBQ2hCO1lBQ0VBLFlBQVlwWixHQUFHYSxTQUFTLGdCQUFnQkU7QUFFMUMsVUFBRSxPQUFPako7WUFDUCxPQUFPdkIsSUFBSXBELFFBQVE7QUFDckI7UUFDQSxJQUFJaW1CLFdBQ0Y5WCxTQUNFLGdCQUNBLEtBQUtpTCxTQUFTNkYsTUFBTXdHLE1BQU0sUUFBUTtBQUV4QztJQWVBLFlBQU1sQixDQUNKbkwsTUFDQWtMLE9BQ0E0QixPQUNBQyxZQUFvQixrQkFDcEJDLGVBQXVCNW1CLEtBQUt5aUIsU0FDNUJvRSxjQUNBQyxhQUFnQyxFQUM5QixXQUNBLHlCQUNBLDRCQUNBO2NBSUk5bUIsS0FBSzZrQixtQkFBbUJDLE9BQU9sTCxNQUFNO1FBQzNDLE1BQU1tTixRQUFRbk4sU0FBUzZGLE1BQU04RjtRQUM3QixNQUFNOUMsVUFBVXppQixLQUFLeWlCO1FBQ3JCLE1BQU03ZSxNQUFNNUQsS0FBSzREO1FBR2pCLE1BQU1vakIsVUFBVW5qQixNQUFNcU4sS0FDcEIsSUFBSVAsSUFBSSxLQUFLa08sVUFBVWlJO1FBRXpCLElBQUlHLGdCQUFnQnBJLFVBQVVnSTtRQUM5QixJQUFJSSxjQUFjemUsV0FBVyxHQUFHO1lBRTlCO2dCQUNFeWUsZ0JBQWdCcFUsd0JBQ2R6RixLQUFLbEosS0FBS3dCLFFBQVFnRixPQUFPO0FBRTdCLGNBQUUsT0FFRjtZQUNBLEtBQUt1YyxpQkFBaUJBLGNBQWN6ZSxXQUFXLEdBQUc7Z0JBQ2hEeWUsZ0JBQWdCL0g7QUFDbEI7QUFDRjtRQUVBLE1BQU1lLE1BQU1wYyxNQUFNcU4sS0FDaEIsSUFBSVAsSUFBSSxLQUVILFNBQVV1VztZQUNYO2dCQUNFLE9BQ0VyakIsTUFBTUMsUUFBUXFqQixrQkFBa0JBLGlCQUFpQjtBQUVyRCxjQUFFO2dCQUVBLE9BQU8sRUFDTCxNQUNBLFFBQ0EsV0FDQSxpQkFDQSxRQUNBLFNBQ0EsUUFDQSxNQUNBLFVBQ0EsVUFDQSxRQUNBLE9BQ0EsT0FDQSxPQUNBLGVBQ0EsVUFDQSxVQUNBLE9BQ0EsT0FDQTtBQUVKO0FBQ0QsU0E5QkUsT0ErQkFGO1FBUVAsTUFBTUcsd0JBQTREdEMsUUFDOUQsV0FDQTtRQUVKLE1BQU11QyxVQUFVLEVBQ2RDLFdBQVc7WUFDVEMsaUJBQWlCO2dCQUNmdEMsUUFBUTtnQkFDUnVDLGFBQWE7Z0JBQ2JwQyxRQUFRc0IsUUFBUSxRQUFRO2dCQUd4QmQsV0FBV2QsUUFBUSxRQUFRO2dCQUMzQlksaUJBQWlCWixRQUFRLE9BQU87Z0JBQ2hDYSxlQUFlYixRQUFRLE9BQU87O1lBRWhDa0MsU0FBUyxFQUFDO1lBQ1ZTLFNBQVMsRUFBQyxnQkFBZ0I7WUFDMUJDLFVBQVU7WUFFWkM7UUFHRixJQUFJakIsT0FBTztZQUNUVyxRQUFRN2IsS0FDTm9jLFNBQVM7Z0JBQ1BaLFNBQVM7Z0JBQ1RTLFNBQVNSO2dCQUVYWSxZQUFZO2dCQUNWQyxhQUFhZDs7QUFHbkI7UUFHQTtZQUNFLE1BQU1lLGtCQUF1QmhRLE9BQU87WUFDcEMsTUFBTWlRLFdBQ0hELGFBQWFBLFVBQVVFLFVBQVdGLFVBQVUvaEIsV0FBVytoQjtZQUUxRCxNQUFNRyxtQkFBd0I7Z0JBQzVCdGYsT0FBTztvQkFBRXVmLE1BQU07O2dCQUNmQyxVQUFVO2dCQUNWQyxRQUFRO2dCQUNScG5CLFFBQVE7b0JBQ05xbkIsVUFBVTtvQkFDVkMsVUFBVTs7O1lBSWQsTUFBTUMsb0JBQXlCO2dCQUM3QjVmLE9BQU87b0JBQUV1ZixNQUFNOztnQkFDZkMsVUFBVTtvQkFDUkQsTUFBTTtvQkFDTk0sUUFBUTtvQkFDUkMsY0FBYztvQkFDZEMsZUFBZTtvQkFDZkMsVUFBVTtvQkFDVjNELFFBQVE4QjtvQkFDUjhCLFFBQVE7b0JBQ1JDLGVBQWU7b0JBQ2ZDLGNBQWM7b0JBQ2RDLGVBQWU7b0JBQ2ZDLGNBQWM7b0JBQ2RDLGFBQWE7O2dCQUVmYixRQUFRO29CQUNOTyxVQUFVOztnQkFFWjNuQixRQUFRO29CQUNOcW5CLFVBQVU7b0JBQ1ZhLFlBQVk7O2dCQUVkUCxVQUFVOztZQUdadkIsUUFBUTdiLEtBQUt3YyxTQUFTbEQsUUFBUW9ELG1CQUFtQk07QUFDbkQsVUFBRSxPQUVGO1FBRUEsTUFBTTVqQixRQUFzQjtZQUMxQkEsT0FBTytoQjtZQUNQVSxTQUFTQTtZQUNUK0IsVUFBVW5KO1lBQ1ZvSixRQUFRNWtCO1lBRVI2a0IsWUFBWXhFOztRQUlkLE1BQU15RSxVQUFrQyxDQUFBO1FBRXhDdEosSUFBSXJULFFBQVN6SDtZQUNYb2tCLFFBQVFwa0IsS0FBSzJaLGdCQUFnQjNaOztRQUcvQixNQUFNcWtCLFVBQTJCLEVBQy9CO1lBQ0U1RyxNQUFNLEdBQUc4RCxRQUFRLFNBQVMsVUFBVUUsZUFBZUEsZUFBZSxZQUFZOUIsUUFBUSxRQUFRLE9BQU9pQyxRQUFRLFFBQVE7WUFDckg5bEIsUUFBUXlsQixRQUFRLFFBQVFLLFFBQVEsUUFBUTtZQUN4QzFtQixNQUFNb2lCO1lBQ05nSCxVQUFVMUM7WUFFVjJDLFdBQVd0QztZQUNYbUMsU0FBU0E7WUFDVEksU0FBUzs7UUFJYjtZQUNFLE1BQU01RSxlQUFlNkUsT0FBT2hsQjtZQUU1QmhCLElBQUlwRCxRQUFRdWtCLE9BQU84RTtZQUNuQjVkLGVBQWU2ZCxnQkFBZ0IvRTtnQkFDN0IsS0FBSyxNQUFNZ0YsaUJBQWlCUCxTQUFTOzBCQUM3QnpFLE9BQU9pRixNQUFNRDtBQUNyQjtBQUNGO2tCQUVNRCxnQkFBZ0IvRTtBQUN4QixVQUFFLE9BQU81ZjtZQUNQLE1BQU0sSUFBSWQsTUFBTSxxQkFBcUJjO0FBQ3ZDO0FBQ0Y7SUFFUSxnQkFBTThrQixDQUNadEQsWUFBb0Isa0JBQ3BCN0IsT0FDQWxMLE9BQWtCOEYsVUFBVUUsS0FDNUJzSyxhQUNBckQ7UUFHQTtZQUNFOVgsV0FBVztBQUViLFVBQUUsT0FBTzVKLElBRVQ7UUFDQTtZQUNFNEosV0FBVztBQUViLFVBQUUsT0FBTzVKLElBRVQ7UUFFQSxJQUFJLEVBQUN1YSxVQUFVRSxLQUFLRixVQUFVeUssUUFBT2pmLFNBQVMwTyxPQUFPO1lBQ25Edk0sR0FBR3VCLFVBQVU7a0JBQ1A1TyxLQUFLdW1CLE1BQU16QixPQUFPckYsTUFBTThGO2tCQUN4QnZsQixLQUFLdW1CLE1BQU16QixPQUFPckYsTUFBTXdHO1lBQzlCam1CLEtBQUsyaUIsV0FBVztBQUNsQjtRQUVBLElBQUksRUFBQ2pELFVBQVVFLEtBQUtGLFVBQVUwSyxTQUFRbGYsU0FBUzBPLE9BQU87WUFDcER2TSxHQUFHdUIsVUFBVTtrQkFDUDVPLEtBQUsra0IsT0FDVHRGLE1BQU04RixLQUNOVCxPQUNBLE9BQ0E2QixhQUFhLGtCQUNiM21CLEtBQUt5aUIsU0FDTG9FLGNBQ0FxRDtrQkFFSWxxQixLQUFLK2tCLE9BQ1R0RixNQUFNd0csS0FDTm5CLE9BQ0EsT0FDQTZCLGFBQWEsa0JBQ2IzbUIsS0FBS3lpQixTQUNMb0UsY0FDQXFEO1lBRUZscUIsS0FBSzJpQixXQUFXO0FBQ2xCO1FBRUEzaUIsS0FBS3dtQixXQUFXL0csTUFBTXdHO1FBQ3RCam1CLEtBQUt3bUIsV0FBVy9HLE1BQU04RjtBQUN4QjtJQVVBLGNBQU04RSxDQUNKMUQsWUFBb0Isa0JBQ3BCL00sT0FBa0I4RixVQUFVRSxLQUM1QnNLLGFBQ0FyRDtRQUVBLE9BQU83bUIsS0FBS2lxQixXQUFXdEQsV0FBVyxNQUFNL00sTUFBTXNRLGFBQWFyRDtBQUM3RDtJQVdBLGVBQU15RCxDQUNKM0QsWUFBb0Isa0JBQ3BCL00sT0FBa0I4RixVQUFVRSxLQUM1QnNLLGFBQ0FyRDtRQUVBLE9BQU83bUIsS0FBS2lxQixXQUFXdEQsV0FBVyxPQUFPL00sTUFBTXNRLGFBQWFyRDtBQUM5RDtJQVFBLGVBQU0wRDtjQUNFN2UsV0FBVyxtQ0FBbUNNO2NBQzlDTixXQUFXLGtEQUFrRE07Y0FDN0ROLFdBQ0oscUVBQ0FNO2NBQ0lOLFdBQVcsa0NBQWtDTTtRQUNuRCxFQUNFO1lBQ0V3ZSxLQUFLO1lBQ0xqYyxNQUFNO1dBRVI7WUFDRWljLEtBQUs7WUFDTGpjLE1BQU07V0FFUjtZQUNFaWMsS0FBSztZQUNMamMsTUFBTTtXQUVSO1lBQ0VpYyxLQUFLO1lBQ0xqYyxNQUFNO1dBRVI7WUFDRWljLEtBQUs7WUFDTGpjLE1BQU07WUFFUjNCLFFBQVMzRDtZQUNULE9BQU11aEIsS0FBRUEsS0FBR2pjLE1BQUVBLFFBQVN0RjtZQUN0QjBGLFNBQVM2YixLQUFLamM7O1FBSWhCO1lBQ0UsTUFBTThELGVBQWViLGtCQUNuQnBFLEtBQUtoRixRQUFRZ0YsS0FBS2xKLEtBQUt3QixRQUFRZ0YsT0FBTztZQUV4QzFLLEtBQUt3aUIsYUFBYWhELHVCQUF1QixHQUFHbk47QUFDOUMsVUFBRTtZQUVBclMsS0FBS3dpQixhQUFhaEQsdUJBQXVCO0FBQzNDO1FBR0E7WUFDRXJTLFVBQVUsZUFBZW5OLEtBQUt3aUI7QUFDaEMsVUFBRSxPQUFPcmQ7WUFDUCxNQUFNdkIsTUFBTTVELEtBQUs0RCxJQUFJekQsSUFBSUgsS0FBS3VxQjtZQUM5QjNtQixJQUFJcEQsUUFBUSw4QkFBOEIyRTtBQUM1QztBQUNGO0lBRVUsU0FBTTRQLENBQ2RoUjtRQUdBLE9BQU1pTSxLQUFFQSxLQUFHRixNQUFFQSxNQUFJZ1EsTUFBRUEsTUFBSUgsV0FBRUEsV0FBU3pVLFVBQUVBLFVBQVEyVSxXQUFFQSxXQUFTOVIsT0FBRUEsU0FDdkRoSztRQUNGLElBQUlpTSxLQUFLO1lBQ1AsYUFBYWhRLEtBQUtxcUIsU0FDaEJ0YyxTQUFTLGtCQUNUNFIsV0FDQXpVLFVBQ0EyVTtBQUVKO1FBQ0EsSUFBSS9QLE1BQU07WUFDUixhQUFhOVAsS0FBS3NxQixVQUNoQnZjLFNBQVMsa0JBQ1Q0UixXQUNBelUsVUFDQTJVO0FBRUo7UUFDQSxJQUFJQyxNQUFNO1lBQ1IsYUFBYTlmLEtBQUt1cUI7QUFDcEI7QUFDRjs7O0FDdDdCRixNQUFNL2tCLFVBQVU7SUFDZGlsQixJQUFJO1FBQ0ZucUIsTUFBTTtRQUNOMEYsU0FBUzs7SUFFWHJGLFNBQVM7UUFDUEwsTUFBTTtRQUNOeUYsT0FBTzs7SUFFVDJrQixLQUFLO1FBQ0hwcUIsTUFBTTtRQUNOeUYsT0FBTztRQUNQQyxTQUFTdkI7Ozs7QUFpQlAsTUFBT2ttQixzQkFBc0IxVztJQUNqQyxXQUFBN1Q7UUFDRWlVLE1BQU0saUJBQWlCN087QUFDekI7SUF3QkEsb0JBQU1vbEIsQ0FBZUY7UUFDbkIsTUFBTTltQixNQUFNNUQsS0FBSzRELElBQUl6RCxJQUFJSCxLQUFLNHFCO1FBQzlCRixNQUFNMXFCLEtBQUs2cUIsWUFBYUgsT0FBa0I7UUFDMUMsS0FBS0EsS0FBSztZQUNSOW1CLElBQUlwRCxRQUFRO1lBQ1pvRCxJQUFJd0IsS0FBSztrQkFDSHNHLFdBQVcsMENBQTBDTTtZQUMzRCxhQUFhak0sVUFBVXNGLGNBQ3JCLE9BQ0EsbURBQ0N3SCxTQUNHQSxJQUFJOUgsV0FBV2tHLE1BQU07QUFFN0I7UUFDQSxPQUFPeWY7QUFDVDtJQVFBLFdBQUFHLENBQVk1a0I7UUFDVixNQUFNckMsTUFBTTVELEtBQUs0RCxJQUFJekQsSUFBSUgsS0FBSzZxQjtRQUM5QjVrQixVQUFVQSxRQUFRcUMsT0FBT3dpQjtRQUN6QixRQUFRN2tCO1VBQ04sS0FBS2MsV0FBV2drQjtVQUNoQixLQUFLaGtCLFdBQVdpa0I7VUFDaEIsS0FBS2prQixXQUFXa2tCO1lBQ2RybkIsSUFBSXBELFFBQVEsaUNBQWlDeUYsV0FBVztZQUN4RCxPQUFPQTs7VUFDVDtZQUNFckMsSUFBSXBELFFBQ0Ysc0RBQXNEeUYsV0FDdEQ7WUFFRixLQUFLLElBQUk4RyxPQUFPakcsaUJBQWlCakMsS0FBS29CLFVBQVU7Z0JBQzlDckMsSUFBSWlDLE1BQU0sMkJBQTJCSTtnQkFDckMsT0FBT3hCO0FBQ1Q7WUFDQWIsSUFBSXBELFFBQVEscUJBQXFCeUYsV0FBVztZQUM1QyxPQUFPQTs7QUFFYjtJQVFBLG9CQUFNaWxCLENBQWV2cUI7UUFDbkIsTUFBTWlELE1BQU01RCxLQUFLNEQsSUFBSXpELElBQUlILEtBQUtrckI7UUFDOUIsS0FBS3ZxQixTQUFTO1lBQ1ppRCxJQUFJcEQsUUFBUTtZQUNaLGFBQWFULFVBQVVzRixjQUNyQixXQUNBLDhDQUNDd0gsU0FBVUEsT0FBT0EsSUFBSTlILFdBQVd5RCxTQUFTO0FBRTlDO1FBQ0EsT0FBTzdIO0FBQ1Q7SUFnQ0EsU0FBTW9VLENBQ0p0UDtRQUdBLElBQUlUO1FBQ0osT0FBTXlsQixJQUFFQSxNQUFPaGxCO1FBQ2YsS0FBSWlsQixLQUFFQSxLQUFHL3BCLFNBQUVBLFdBQVk4RTtRQUN2QmlsQixZQUFZMXFCLEtBQUs0cUIsZUFBZUY7UUFDaEMvcEIsZ0JBQWdCWCxLQUFLa3JCLGVBQWV2cUI7UUFDcENxRSxlQUFlMEcsV0FBVyw4QkFBOEJnZixPQUFPL3BCLFdBQVc7WUFDeEUrSixLQUFLaEYsUUFBUWdGO1dBQ1pzQjtRQUNIaEgsZUFBZTBHLFdBQVcsMEJBQTBCTTtjQUM5Q2hIO1FBQ04sSUFDRUEsT0FBT2tELEtBQUtNLGdCQUNMekksVUFBVTJFLGdCQUNmLGVBQ0EsNkRBQ0EsT0FFRjtrQkFDTWdILFdBQVcsYUFBYU07a0JBQ3hCTixXQUNKLGtCQUFrQmdmLFNBQVMvcEIsc0NBQXNDOHBCLEtBQUssS0FBS3pqQixhQUMzRWdGO0FBQ0o7Y0FDTU4sV0FDSixnQkFBZ0JnZixZQUFZL3BCLFVBQVU4cEIsS0FBSyxLQUFLempCLGFBQ2hEZ0Y7Y0FDSU4sV0FBVywwQkFBMEJNO1FBQzNDLEtBQUt5ZSxJQUFJO2tCQUNEL2UsV0FBVywwREFDZE07QUFDTDtBQUNGOzs7QUMvSEksTUFBT21mLDJCQUEyQi9qQjtJQU90QyxXQUFBaEgsQ0FDRWlILEtBQ0FDLE1BQ0F3RixRQUNBSixRQUFRO1FBRVIySCxNQUFNaE4sS0FBS0M7UUFDWDtZQUNFdEgsS0FBSzhNLGdCQUNJQSxXQUFXLFdBQVcsSUFBSUMsT0FBT0QsUUFBUUosU0FBU0k7QUFDN0QsVUFBRSxPQUFPM0g7WUFDUCxNQUFNLElBQUlkLE1BQU0sK0JBQStCYztBQUNqRDtBQUNGO0lBU1EsSUFBQU4sQ0FBSzBDO1FBQ1h2SCxLQUFLOE0sT0FBT3NlLFlBQVk7UUFDeEIsSUFBSW5nQjtRQUNKO1lBQ0VBLFFBQVFqTCxLQUFLOE0sT0FBT21VLEtBQUsxWjtBQUMzQixVQUFFLE9BQU9wQztZQUNQLE9BQU8wTyxRQUFRaE8sTUFBTSwwQkFBMEIwQixnQkFBZ0JwQztBQUNqRTtRQUNBLE9BQU84RjtBQUNUO0lBUVUsY0FBQW9nQixDQUFlOWpCO1FBQ3ZCLE1BQU0wRCxRQUFRakwsS0FBSzZFLEtBQUswQztRQUN4QixJQUFJMEQsT0FBT2pMLEtBQUtvSSxRQUFRNkMsTUFBTTtBQUNoQztJQVFVLGFBQUFxZ0IsQ0FBYy9qQjtRQUN0QixNQUFNMEQsUUFBUWpMLEtBQUs2RSxLQUFLMEM7UUFDeEIsSUFBSTBELE9BQU9qTCxLQUFLdUksT0FBTzBDLE1BQU07QUFDL0I7SUFRUyxJQUFBMUQsQ0FBS0s7UUFDWnlNLE1BQU05TSxLQUFLSztRQUNYNUgsS0FBS3FyQixlQUFleGpCLE9BQU9EO0FBQzdCO0lBUVMsS0FBQXhELENBQU13RDtRQUNieU0sTUFBTWpRLE1BQU13RDtRQUNaNUgsS0FBS3NyQixjQUFjempCLE9BQU9EO0FBQzVCOzs7QUN2SEssTUFBTTJqQixVQUFVOztBQVNoQixNQUFNQyxlQUFlOzsifQ==