js.blend.js 139 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545
  1. (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  2. 'use strict'
  3. exports.byteLength = byteLength
  4. exports.toByteArray = toByteArray
  5. exports.fromByteArray = fromByteArray
  6. var lookup = []
  7. var revLookup = []
  8. var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
  9. var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  10. for (var i = 0, len = code.length; i < len; ++i) {
  11. lookup[i] = code[i]
  12. revLookup[code.charCodeAt(i)] = i
  13. }
  14. revLookup['-'.charCodeAt(0)] = 62
  15. revLookup['_'.charCodeAt(0)] = 63
  16. function placeHoldersCount (b64) {
  17. var len = b64.length
  18. if (len % 4 > 0) {
  19. throw new Error('Invalid string. Length must be a multiple of 4')
  20. }
  21. // the number of equal signs (place holders)
  22. // if there are two placeholders, than the two characters before it
  23. // represent one byte
  24. // if there is only one, then the three characters before it represent 2 bytes
  25. // this is just a cheap hack to not do indexOf twice
  26. return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0
  27. }
  28. function byteLength (b64) {
  29. // base64 is 4/3 + up to two characters of the original data
  30. return (b64.length * 3 / 4) - placeHoldersCount(b64)
  31. }
  32. function toByteArray (b64) {
  33. var i, l, tmp, placeHolders, arr
  34. var len = b64.length
  35. placeHolders = placeHoldersCount(b64)
  36. arr = new Arr((len * 3 / 4) - placeHolders)
  37. // if there are placeholders, only get up to the last complete 4 chars
  38. l = placeHolders > 0 ? len - 4 : len
  39. var L = 0
  40. for (i = 0; i < l; i += 4) {
  41. tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
  42. arr[L++] = (tmp >> 16) & 0xFF
  43. arr[L++] = (tmp >> 8) & 0xFF
  44. arr[L++] = tmp & 0xFF
  45. }
  46. if (placeHolders === 2) {
  47. tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
  48. arr[L++] = tmp & 0xFF
  49. } else if (placeHolders === 1) {
  50. tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
  51. arr[L++] = (tmp >> 8) & 0xFF
  52. arr[L++] = tmp & 0xFF
  53. }
  54. return arr
  55. }
  56. function tripletToBase64 (num) {
  57. return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
  58. }
  59. function encodeChunk (uint8, start, end) {
  60. var tmp
  61. var output = []
  62. for (var i = start; i < end; i += 3) {
  63. tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
  64. output.push(tripletToBase64(tmp))
  65. }
  66. return output.join('')
  67. }
  68. function fromByteArray (uint8) {
  69. var tmp
  70. var len = uint8.length
  71. var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
  72. var output = ''
  73. var parts = []
  74. var maxChunkLength = 16383 // must be multiple of 3
  75. // go through the array every three bytes, we'll deal with trailing stuff later
  76. for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
  77. parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
  78. }
  79. // pad the end with zeros, but make sure to not forget the extra bytes
  80. if (extraBytes === 1) {
  81. tmp = uint8[len - 1]
  82. output += lookup[tmp >> 2]
  83. output += lookup[(tmp << 4) & 0x3F]
  84. output += '=='
  85. } else if (extraBytes === 2) {
  86. tmp = (uint8[len - 2] << 8) + (uint8[len - 1])
  87. output += lookup[tmp >> 10]
  88. output += lookup[(tmp >> 4) & 0x3F]
  89. output += lookup[(tmp << 2) & 0x3F]
  90. output += '='
  91. }
  92. parts.push(output)
  93. return parts.join('')
  94. }
  95. },{}],2:[function(require,module,exports){
  96. /*jshint esversion: 6 */
  97. const three = require("./threejs/blend_three.js");
  98. const parser = require("./parser/parser.js")();
  99. function loadFile(blender_file, res, rej){
  100. three_module = three(blender_file);
  101. //TODO: Report any errors with ThreeJS before continuing.
  102. res({
  103. file : blender_file,
  104. three : three_module
  105. });
  106. }
  107. /* This represents a parsed blendfile instance if parsing is successful. It will accept a string or a binary data object. Strings must be a valid URI to a blender file. Binary data may be in the form of an ArrayBuffer, TypedArray, or a Blob. Binary data must also contain the binary data of a blender file.*/
  108. JSBLEND = (fileuri_or_filedata, name = "")=>{
  109. const promise = new Promise(
  110. (res, rej) =>{
  111. parser.onParseReady = (blender_file) => {
  112. loadFile(blender_file, res, rej);
  113. };
  114. //If fileuri_or_filedata is a string, attempt to load the file asynchronously
  115. if(typeof fileuri_or_filedata == "string"){
  116. let request = new XMLHttpRequest();
  117. request.open("GET", fileuri_or_filedata, true);
  118. request.responseType = 'blob';
  119. request.onload = () => {
  120. let file = request.response;
  121. parser.loadBlendFromBlob(new Blob([file]), fileuri_or_filedata);
  122. };
  123. request.send();
  124. return;
  125. }
  126. debugger
  127. if(typeof fileuri_or_filedata == "object"){
  128. //Attempt to load from blob or array buffer;
  129. if(fileuri_or_filedata instanceof ArrayBuffer){
  130. parser.loadBlendFromArrayBuffer(fileuri_or_filedata, name);
  131. return;
  132. }
  133. if(fileuri_or_filedata instanceof Blob){
  134. parser.loadBlendFromBlob(fileuri_or_filedata, name);
  135. return;
  136. }
  137. }
  138. //Unknown file type passed -> abort and reject
  139. console.warn("Unsupported file type passed to JSBlend", fileuri_or_filedata);
  140. rej("Unsupported file type passed to JSBlend");
  141. }
  142. );
  143. return promise;
  144. };
  145. },{"./parser/parser.js":3,"./threejs/blend_three.js":4}],3:[function(require,module,exports){
  146. /*jshint esversion: 6 */
  147. const DNA1 = 826363460;
  148. const ENDB = 1111772741;
  149. /* Note: Blender cooridinates treat the Z axis as the verticle and Y as depth. */
  150. module.exports = (function(unzipper) {
  151. //A helper object to identify Blender Object structs by type name.
  152. var blender_types = {
  153. mesh_object: 1,
  154. lamp: 10,
  155. };
  156. //web worker not functional in this version
  157. USE_WEBWORKER = false;
  158. var worker = null,
  159. FR = new FileReader(),
  160. return_object = {
  161. loadBlendFromArrayBuffer: function(array_buffer) {
  162. return_object.ready = false;
  163. if (USE_WEBWORKER) {
  164. worker.postMessage(array_buffer, array_buffer);
  165. } else {
  166. worker.onmessage({
  167. data: array_buffer
  168. });
  169. }
  170. },
  171. loadBlendFromBlob: function(blob) {
  172. FR.onload = function() {
  173. return_object.loadBlendFromArrayBuffer(this.result);
  174. };
  175. FR.readAsArrayBuffer(blob);
  176. },
  177. ready: true,
  178. onParseReady: function() {},
  179. };
  180. worker = new worker_code();
  181. worker.postMessage = function(message) {
  182. return_object.onParseReady(message);
  183. };
  184. function worker_code() {
  185. "use strict";
  186. var data = null,
  187. _data = null,
  188. BIG_ENDIAN = false,
  189. pointer_size = 0,
  190. struct_names = [],
  191. offset = 0,
  192. working_blend_file = null,
  193. current_SDNA_template = null,
  194. templates = {},
  195. finished_objects = [],
  196. FILE = null,
  197. AB = null;
  198. function parseFile(msg) {
  199. var self = this;
  200. if (typeof msg.data == "object") {
  201. // reset global variables
  202. AB = null;
  203. data = null;
  204. BIG_ENDIAN = false;
  205. pointer_size = 0;
  206. struct_names = [];
  207. offset = 0;
  208. working_blend_file = null;
  209. finished_objects = [];
  210. current_SDNA_template = null;
  211. // set data
  212. _data = msg.data;
  213. AB = _data.slice();
  214. data = new DataView(_data);
  215. FILE = new BLENDER_FILE(AB);
  216. //start parsing
  217. readFile();
  218. //export parsed data
  219. self.postMessage(FILE);
  220. }
  221. }
  222. /*
  223. Export object for a parsed __blender_file__.
  224. */
  225. var BLENDER_FILE = function(AB) {
  226. this.AB = AB;
  227. //this.double = new Float64Array(AB);
  228. this.byte = new Uint8Array(AB);
  229. this.dv = new DataView(AB);
  230. this.objects = {};
  231. this.memory_lookup = {},
  232. this.object_array = [];
  233. this.template = null;
  234. };
  235. BLENDER_FILE.prototype = {
  236. addObject: function(obj) {
  237. this.object_array.push(obj);
  238. if (!this.objects[obj.blender_name]) this.objects[obj.blender_name] = [];
  239. this.objects[obj.blender_name].push(obj);
  240. },
  241. primeTypes: function(list_of_dna_names) {
  242. for (var i = 0; i < list_of_dna_names.length; i++) {
  243. //this.objects[list_of_dna_names[i]] = [];
  244. }
  245. },
  246. getPointer: function(offset) {
  247. var pointerLow = this.dv.getUint32(offset, this.template.endianess);
  248. if (this.template.pointer_size > 4) {
  249. var pointerHigh = this.dv.getUint32(offset + 4, this.template.endianess);
  250. if (this.template.endianess) {
  251. return (pointerLow) + "l|h" + pointerHigh;
  252. } else {
  253. return (pointerHigh) + "h|l" + pointerLow;
  254. }
  255. } else {
  256. return pointerLow;
  257. }
  258. }
  259. };
  260. function getDocument(data) {
  261. var obj = readFile(null, data);
  262. }
  263. self.onmessage = parseFile;
  264. this.onmessage = parseFile;
  265. /*
  266. These functions map offsets in the blender __blender_file__ to basic types (byte,short,int,float) through TypedArrays;
  267. This allows the underlying binary data to be changed.
  268. */
  269. function float64Prop(offset, Blender_Array_Length, length) {
  270. return {
  271. get: function() {
  272. return (Blender_Array_Length > 1) ?
  273. new Float64Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
  274. this.__blender_file__.dv.getFloat64(this.__data_address__ + offset, this.__blender_file__.template.endianess);
  275. },
  276. set: function(float) {
  277. if (Blender_Array_Length > 1) {} else {
  278. this.__blender_file__.dv.setFloat64(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
  279. }
  280. },
  281. };
  282. }
  283. function floatProp(offset, Blender_Array_Length, length) {
  284. return {
  285. get: function() {
  286. return (Blender_Array_Length > 1) ?
  287. new Float32Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
  288. this.__blender_file__.dv.getFloat32(this.__data_address__ + offset, this.__blender_file__.template.endianess);
  289. },
  290. set: function(float) {
  291. if (Blender_Array_Length > 1) {} else {
  292. this.__blender_file__.dv.setFloat32(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
  293. }
  294. },
  295. };
  296. }
  297. function intProp(offset, Blender_Array_Length, length) {
  298. return {
  299. get: function() {
  300. return (Blender_Array_Length > 1) ?
  301. new Int32Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
  302. this.__blender_file__.dv.getInt32(this.__data_address__ + offset, this.__blender_file__.template.endianess);
  303. },
  304. set: function(int) {
  305. if (Blender_Array_Length > 1) {} else {
  306. this.__blender_file__.dv.setInt32(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
  307. }
  308. },
  309. };
  310. }
  311. function uIntProp(offset, Blender_Array_Length, length) {
  312. return {
  313. get: function() {
  314. return (Blender_Array_Length > 1) ?
  315. new Uint32Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
  316. this.__blender_file__.dv.getUint32(this.__data_address__ + offset, this.__blender_file__.template.endianess);
  317. },
  318. set: function(int) {
  319. if (Blender_Array_Length > 1) {} else {
  320. this.__blender_file__.dv.setUint32(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
  321. }
  322. },
  323. };
  324. }
  325. function shortProp(offset, Blender_Array_Length, length) {
  326. return {
  327. get: function() {
  328. return (Blender_Array_Length > 1) ?
  329. new Int16Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
  330. this.__blender_file__.dv.getInt16(this.__data_address__ + offset, this.__blender_file__.template.endianess);
  331. },
  332. set: function(float) {
  333. if (Blender_Array_Length > 1) {} else {
  334. this.__blender_file__.dv.setInt16(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
  335. }
  336. },
  337. };
  338. }
  339. var uShortProp = (offset, Blender_Array_Length, length) => {
  340. return {
  341. get: function() {
  342. return (Blender_Array_Length > 1) ?
  343. new Uint16Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
  344. this.__blender_file__.dv.getUint16(this.__data_address__ + offset, this.__blender_file__.template.endianess);
  345. },
  346. set: function(float) {
  347. if (Blender_Array_Length > 1) {} else {
  348. this.__blender_file__.dv.setUint16(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
  349. }
  350. },
  351. };
  352. }
  353. function charProp(offset, Blender_Array_Length, length) {
  354. return {
  355. get: function() {
  356. if (Blender_Array_Length > 1) {
  357. let start = this.__data_address__ + offset;
  358. let end = start;
  359. let buffer_guard = 0;
  360. while (this.__blender_file__.byte[end] != 0 && buffer_guard++ < length) end++;
  361. return toString(this.__blender_file__.AB, start, end)
  362. }
  363. return this.__blender_file__.byte[(this.__data_address__ + offset)];
  364. },
  365. set: function(byte) {
  366. if (Blender_Array_Length > 1) {
  367. var string = byte + "",
  368. i = 0,
  369. l = string.length;
  370. while (i < length) {
  371. if (i < l) {
  372. this.__blender_file__.byte[(this.__data_address__ + offset + i)] = string.charCodeAt(i) | 0;
  373. } else {
  374. this.__blender_file__.byte[(this.__data_address__ + offset + i)] = 0;
  375. }
  376. i++;
  377. }
  378. } else {
  379. this.__blender_file__.byte[(this.__data_address__ + offset)] = byte | 0;
  380. }
  381. }
  382. };
  383. }
  384. function pointerProp2(offset) {
  385. return {
  386. get: function() {
  387. let pointer = this.__blender_file__.getPointer(this.__data_address__ + offset, this.__blender_file__);
  388. var link = this.__blender_file__.memory_lookup[pointer];
  389. var results = [];
  390. if (link) {
  391. var address = link.__data_address__;
  392. let j = 0;
  393. while (true) {
  394. pointer = this.__blender_file__.getPointer(address + j * 8, this.__blender_file__);
  395. let obj = this.__blender_file__.memory_lookup[pointer];
  396. if (!obj) break;
  397. results.push(obj);
  398. j++
  399. }
  400. };
  401. return results;
  402. },
  403. set: function() {}
  404. }
  405. }
  406. function pointerProp(offset, Blender_Array_Length, length) {
  407. return {
  408. get: function() {
  409. if (Blender_Array_Length > 1) {
  410. let array = [];
  411. let j = 0;
  412. let off = offset;
  413. while (j < Blender_Array_Length) {
  414. let pointer = this.__blender_file__.getPointer(this.__data_address__ + off, this.__blender_file__);
  415. array.push(this.__blender_file__.memory_lookup[pointer]);
  416. off += length ///this.__blender_file__.template.pointer_size;
  417. j++;
  418. }
  419. return array;
  420. } else {
  421. let pointer = this.__blender_file__.getPointer(this.__data_address__ + offset, this.__blender_file__);
  422. return this.__blender_file__.memory_lookup[pointer];
  423. }
  424. },
  425. set: function() {}
  426. }
  427. }
  428. function compileProp(obj, name, type, offset, array_size, IS_POINTER, pointer_size, length) {
  429. if (!IS_POINTER) {
  430. switch (type) {
  431. case "double":
  432. Object.defineProperty(obj, name, float64Prop(offset, array_size, length >> 3));
  433. break;
  434. case "float":
  435. Object.defineProperty(obj, name, floatProp(offset, array_size, length >> 2));
  436. break;
  437. case "int":
  438. Object.defineProperty(obj, name, intProp(offset, array_size, length >> 2));
  439. break;
  440. case "short":
  441. case "ushort":
  442. Object.defineProperty(obj, name, shortProp(offset, array_size, length >> 1));
  443. break;
  444. case "char":
  445. case "uchar":
  446. Object.defineProperty(obj, name, charProp(offset, array_size, length));
  447. break;
  448. default:
  449. //compile list to
  450. obj[name] = {};
  451. obj.__list__.push(name, type, length, offset, array_size, IS_POINTER);
  452. }
  453. obj._length += length;
  454. offset += length;
  455. } else {
  456. Object.defineProperty(obj, name, pointerProp(offset, array_size, pointer_size));
  457. offset += pointer_size * array_size;
  458. }
  459. return offset;
  460. }
  461. //Store final DNA structs
  462. var MASTER_SDNA_SCHEMA = function(version) {
  463. this.version = version;
  464. this.SDNA_SET = false;
  465. this.byte_size = 0;
  466. this.struct_index = 0;
  467. this.structs = {};
  468. this.SDNA = {};
  469. this.endianess = false;
  470. };
  471. MASTER_SDNA_SCHEMA.prototype = {
  472. getSDNAStructureConstructor: function(name, struct) {
  473. if (struct) {
  474. var blen_struct = Function("function " + name + "(){}; return " + name)();
  475. blen_struct.prototype = new BLENDER_STRUCTURE();
  476. blen_struct.prototype.blender_name = name;
  477. blen_struct.prototype.__pointers = [];
  478. blen_struct.prototype.__list__ = [];
  479. var offset = 0;
  480. //Create properties of struct
  481. for (var i = 0; i < struct.length; i += 3) {
  482. var _name = struct[i],
  483. n = _name,
  484. type = struct[i + 1],
  485. length = struct[i + 2],
  486. array_length = 0,
  487. match = null,
  488. Blender_Array_Length = 1,
  489. Suparray_match = 1,
  490. PointerToArray = false,
  491. Pointer_Match = 0;
  492. var DNA = this.SDNA[name] = {
  493. constructor: blen_struct
  494. };
  495. let original_name = _name;
  496. //mini type parser
  497. if ((match = _name.match(/(\*?)(\*?)(\w+)(\[(\w*)\])?(\[(\w*)\])?/))) {
  498. //base name
  499. _name = match[3];
  500. //pointer type
  501. if (match[1]) {
  502. Pointer_Match = 10;
  503. blen_struct.prototype.__pointers.push(_name);
  504. }
  505. if (match[2]) {
  506. PointerToArray = true;
  507. }
  508. //arrays
  509. if (match[4]) {
  510. if (match[6]) {
  511. Suparray_match = parseInt(match[5]);
  512. Blender_Array_Length = parseInt(match[7]);
  513. } else {
  514. Blender_Array_Length = parseInt(match[5]);
  515. }
  516. }
  517. array_length = Blender_Array_Length * length;
  518. length = array_length * Suparray_match;
  519. }
  520. DNA[n] = {
  521. type: type,
  522. length: length,
  523. isArray: (Blender_Array_Length > 0),
  524. };
  525. if (PointerToArray) {
  526. Object.defineProperty(blen_struct.prototype, _name, pointerProp2(offset));
  527. offset += pointer_size;
  528. } else if (Suparray_match > 1) {
  529. var array_names = new Array(Suparray_match);
  530. //construct sub_array object that will return the correct structs
  531. for (var j = 0; j < Suparray_match; j++) {
  532. let array_name_ = `__${_name}[${j}]__`;
  533. array_names[j] = array_name_;
  534. offset = compileProp(blen_struct.prototype, array_name_, type, offset, Blender_Array_Length, Pointer_Match, pointer_size, array_length);
  535. }
  536. Object.defineProperty(blen_struct.prototype, _name, {
  537. get: (function(array_names) {
  538. return function() {
  539. var array = [];
  540. for (var i = 0; i < array_names.length; i++) {
  541. array.push(this[array_names[i]])
  542. }
  543. return array;
  544. }
  545. })(array_names)
  546. });
  547. } else {
  548. offset = compileProp(blen_struct.prototype, _name, type, offset, Blender_Array_Length, Pointer_Match, pointer_size, length);
  549. }
  550. }
  551. return this.SDNA[name].constructor;
  552. } else {
  553. if (!this.SDNA[name]) {
  554. return null;
  555. }
  556. return this.SDNA[name].constructor;
  557. }
  558. }
  559. };
  560. var BLENDER_STRUCTURE = function() {
  561. this.__blender_file__ = null;
  562. this.__list__ = null;
  563. this.__super_array_list__ = null;
  564. this.blender_name = "";
  565. this.__pointers = null;
  566. this.address = null;
  567. this.length = 0;
  568. this.__data_address__ = 0;
  569. this.blender_name = "";
  570. this._length = 0;
  571. };
  572. /*
  573. Returns a pre-constructed BLENDER_STRUCTURE or creates a new BLENDER_STRUCTURE to match the DNA struct type
  574. */
  575. var pointer_function = (pointer) => () => {
  576. return FILE.memory_lookup[pointer]
  577. };
  578. function getPointer(offset) {
  579. var pointerLow = data.getUint32(offset, BIG_ENDIAN);
  580. if (pointer_size > 4) {
  581. var pointerHigh = data.getUint32(offset + 4, BIG_ENDIAN);
  582. if (BIG_ENDIAN) {
  583. return (pointerLow) + "" + pointerHigh;
  584. } else {
  585. return (pointerHigh) + "" + pointerLow;
  586. }
  587. } else {
  588. return pointerLow;
  589. }
  590. }
  591. BLENDER_STRUCTURE.prototype = {
  592. setData: function(pointer, _data_offset, data_block_length, BLENDER_FILE) {
  593. if (this.__list__ == null) return this;
  594. BLENDER_FILE.addObject(this);
  595. this.__blender_file__ = BLENDER_FILE;
  596. var struct = this.__list__,
  597. j = 0,
  598. i = 0,
  599. obj, name = "",
  600. type, length, Blender_Array_Length, Pointer_Match, offset, constructor;
  601. this.__data_address__ = _data_offset;
  602. if (struct === null) return this;
  603. for (i = 0; i < struct.length; i += 6) {
  604. obj = null;
  605. name = struct[i];
  606. type = struct[i + 1];
  607. Blender_Array_Length = struct[i + 4];
  608. Pointer_Match = struct[i + 5];
  609. offset = this.__data_address__ + struct[i + 3];
  610. if (Blender_Array_Length > 1) {
  611. this[name] = [];
  612. j = 0;
  613. while (j < Blender_Array_Length) {
  614. if (current_SDNA_template.getSDNAStructureConstructor(type)) {
  615. constructor = current_SDNA_template.getSDNAStructureConstructor(type);
  616. this[name].push((new constructor()).setData(0, offset, offset + length / Blender_Array_Length, BLENDER_FILE));
  617. } else this[name].push(null);
  618. offset += length / Blender_Array_Length;
  619. j++;
  620. }
  621. } else {
  622. if (current_SDNA_template.getSDNAStructureConstructor(type)) {
  623. constructor = current_SDNA_template.getSDNAStructureConstructor(type);
  624. this[name] = (new constructor()).setData(0, offset, length + offset, BLENDER_FILE);
  625. } else this[name] = null;
  626. }
  627. }
  628. //break connection to configuration list
  629. this.__list__ = null;
  630. return this;
  631. },
  632. get aname() {
  633. if (this.id) return this.id.name.slice(2);
  634. else return undefined;
  635. }
  636. };
  637. function toString(buffer, _in, _out) {
  638. return String.fromCharCode.apply(String, new Uint8Array(buffer, _in, _out - _in));
  639. }
  640. //Begin parsing blender __blender_file__
  641. function readFile() {
  642. var count = 0;
  643. var offset2 = 0;
  644. var root = 0;
  645. var i = 0;
  646. var data_offset = 0;
  647. var sdna_index = 0;
  648. var code = "";
  649. var block_length = 0;
  650. var curr_count = 0;
  651. var curr_count2 = 0;
  652. FILE.memory_lookup = {};
  653. struct_names = [];
  654. offset = 0;
  655. // Make sure we have a .blend __blender_file__. All blend files have the first 12bytes
  656. // set with BLENDER-v### in Utf-8
  657. if (toString(_data, offset, 7) !== "BLENDER") return console.warn("File supplied is not a .blend compatible Blender file.");
  658. // otherwise get templete from save version.
  659. offset += 7;
  660. pointer_size = ((toString(_data, offset++, offset)) == "_") ? 4 : 8;
  661. BIG_ENDIAN = toString(_data, offset++, offset) !== "V";
  662. var version = toString(_data, offset, offset + 3);
  663. //create new master template if none exist for current blender version;
  664. if (!templates[version]) {
  665. templates[version] = new MASTER_SDNA_SCHEMA(version);
  666. }
  667. current_SDNA_template = templates[version];
  668. FILE.template = current_SDNA_template;
  669. offset += 3;
  670. //Set SDNA structs if template hasn't been set.
  671. //Todo: Move the following block into the MASTER_SDNA_SCHEMA object.
  672. //*Like so:*/ current_SDNA_template.set(AB);
  673. if (!current_SDNA_template.SDNA_SET) {
  674. current_SDNA_template.endianess = BIG_ENDIAN;
  675. current_SDNA_template.pointer_size = pointer_size;
  676. //find DNA1 data block
  677. offset2 = offset;
  678. while (true) {
  679. sdna_index = data.getInt32(offset2 + pointer_size + 8, BIG_ENDIAN);
  680. code = toString(_data, offset2, offset2 + 4).replace(/\u0000/g, "");
  681. block_length = data.getInt32(offset2 + 4, true);
  682. offset2 += 16 + (pointer_size);
  683. if (code === "DNA1") {
  684. // DNA found; This is the core of the __blender_file__ and contains all the structure for the various data types used in Blender.
  685. count = 0;
  686. var types = [],
  687. fields = [],
  688. names = [],
  689. lengths = [],
  690. name = "",
  691. curr_name = "";
  692. //skip SDNA and NAME identifiers
  693. offset2 += 8;
  694. //Number of structs.
  695. count = data.getInt32(offset2, true);
  696. offset2 += 4;
  697. curr_count = 0;
  698. //Build up list of names for structs
  699. while (curr_count < count) {
  700. curr_name = "";
  701. while (data.getInt8(offset2) !== 0) {
  702. curr_name += toString(_data, offset2, offset2 + 1);
  703. offset2++;
  704. }
  705. names.push(curr_name);
  706. offset2++;
  707. curr_count++;
  708. }
  709. //Adjust for 4byte alignment
  710. if ((offset2 % 4) > 0) offset2 = (4 - (offset2 % 4)) + offset2;
  711. offset2 += 4;
  712. //Number of struct types
  713. count = data.getInt32(offset2, true);
  714. offset2 += 4;
  715. curr_count = 0;
  716. //Build up list of types
  717. while (curr_count < count) {
  718. curr_name = "";
  719. while (data.getInt8(offset2) !== 0) {
  720. curr_name += toString(_data, offset2, offset2 + 1);
  721. offset2++;
  722. }
  723. types.push(curr_name);
  724. offset2++;
  725. curr_count++;
  726. }
  727. //Adjust for 4byte alignment
  728. if ((offset2 % 4) > 0) offset2 = (4 - (offset2 % 4)) + offset2;
  729. offset2 += 4;
  730. curr_count = 0;
  731. //Build up list of byte lengths for types
  732. while (curr_count < count) {
  733. lengths.push(data.getInt16(offset2, BIG_ENDIAN));
  734. offset2 += 2;
  735. curr_count++;
  736. }
  737. //Adjust for 4byte alignment
  738. if ((offset2 % 4) > 0) offset2 = (4 - (offset2 % 4)) + offset2;
  739. offset2 += 4;
  740. //Number of structures
  741. var structure_count = data.getInt32(offset2, BIG_ENDIAN);
  742. offset2 += 4;
  743. curr_count = 0;
  744. //Create constructor objects from list of SDNA structs
  745. while (curr_count < structure_count) {
  746. var struct_name = types[data.getInt16(offset2, BIG_ENDIAN)];
  747. offset2 += 2;
  748. obj = [];
  749. count = data.getInt16(offset2, BIG_ENDIAN);
  750. offset2 += 2;
  751. curr_count2 = 0;
  752. struct_names.push(struct_name);
  753. //Fill an array with name, type, and length for each SDNA struct property
  754. while (curr_count2 < count) {
  755. obj.push(names[data.getInt16(offset2 + 2, BIG_ENDIAN)], types[data.getInt16(offset2, BIG_ENDIAN)], lengths[data.getInt16(offset2, BIG_ENDIAN)]);
  756. offset2 += 4;
  757. curr_count2++;
  758. }
  759. //Create a SDNA constructor by passing [type,name,lenth] array as second argument
  760. current_SDNA_template.getSDNAStructureConstructor(struct_name, obj);
  761. curr_count++;
  762. }
  763. current_SDNA_template.SDNA_SET = true;
  764. current_SDNA_template.SDNA_NAMES = struct_names;
  765. break;
  766. }
  767. offset2 += block_length;
  768. }
  769. }
  770. //parse the rest of the data, starting back at the top.
  771. //TODO: turn into "on-demand" parsing.
  772. while (true) {
  773. if ((offset % 4) > 0) {
  774. offset = (4 - (offset % 4)) + offset;
  775. }
  776. data_offset = offset;
  777. sdna_index = data.getInt32(offset + pointer_size + 8, BIG_ENDIAN);
  778. let code_uint = data.getUint32(offset, BIG_ENDIAN);
  779. offset2 = offset + 16 + (pointer_size);
  780. offset += data.getInt32(offset + 4, true) + 16 + (pointer_size);
  781. if (code_uint === DNA1); //skip - already processed at this point
  782. else if (code_uint === ENDB) break; //end of __blender_file__ found
  783. else {
  784. //Create a Blender object using a constructor template from current_SDNA_template
  785. var data_start = data_offset + pointer_size + 16;
  786. //Get a SDNA constructor by name;
  787. var constructor = current_SDNA_template.getSDNAStructureConstructor(current_SDNA_template.SDNA_NAMES[sdna_index]);
  788. var size = data.getInt32(data_offset + 4, BIG_ENDIAN);
  789. count = data.getInt32(data_offset + 12 + pointer_size, BIG_ENDIAN);
  790. if (count > 0) {
  791. var obj = new constructor();
  792. var length = constructor.prototype._length;
  793. var address = FILE.getPointer(data_offset + 8);
  794. obj.address = address + "";
  795. obj.setData(address, data_start, data_start + size, FILE);
  796. if (count > 1) {
  797. let array = [];
  798. array.push(obj);
  799. for (var u = 1; u < count; u++) {
  800. obj = new constructor();
  801. obj.setData(address, data_start + length * u, data_start + (length * u) + length, FILE);
  802. array.push(obj);
  803. }
  804. FILE.memory_lookup[address] = array;
  805. } else {
  806. FILE.memory_lookup[address] = obj;
  807. }
  808. }
  809. }
  810. }
  811. }
  812. }
  813. return return_object;
  814. });
  815. },{}],4:[function(require,module,exports){
  816. /*jshint esversion: 6 */
  817. const createMaterial = require("./material.js");
  818. const createTexture = require("./texture.js");
  819. const createMesh = require("./mesh.js");
  820. const createLight = require("./light.js");
  821. function loadModel(three_scene, model_name, blender_file, cache) {
  822. var mats = blender_mesh.mat,
  823. materials = [];
  824. for (var i = 0; i < mats.length; i++) {
  825. var material = createThreeJSMaterial(mats[i]);
  826. materials.push(material);
  827. }
  828. }
  829. var blender_types = {
  830. mesh_object: 1,
  831. lamp: 10
  832. };
  833. function loadScene(three_scene, blender_file, cache) {
  834. //build object from blender mesh object
  835. for (let i = 0; i < blender_file.objects.Object.length; i++) {
  836. let obj = blender_file.objects.Object[i];
  837. //Load Lights
  838. if (obj.type == blender_types.lamp) {
  839. let light = createLight(obj, blender_file);
  840. three_scene.add(light);
  841. }
  842. //Load Meshes
  843. if (obj.type == blender_types.mesh_object) {
  844. if (obj.data) {
  845. //get the mesh
  846. var buffered_geometry = createMesh(obj.data, [0, 0, 0]);
  847. var blend_material = obj.data.mat[0];
  848. if(blend_material){
  849. var material = createMaterial(blend_material);
  850. }else{
  851. //create generic material
  852. }
  853. //var geometry = createThreeJSGeometry(obj.data, [0, 0, 0]);
  854. ///*
  855. //create a transform from the mesh object
  856. var mesh = new THREE.Mesh(buffered_geometry, material);
  857. mesh.castShadow = true;
  858. mesh.receiveShadow = true;
  859. three_scene.add(mesh);
  860. mesh.rotateZ(obj.rot[2]);
  861. mesh.rotateY(obj.rot[1]);
  862. mesh.rotateX(obj.rot[0]);
  863. mesh.scale.fromArray(obj.size, 0);
  864. mesh.position.fromArray([obj.loc[0], (obj.loc[2]), (-obj.loc[1])], 0);
  865. //*/
  866. }
  867. }
  868. }
  869. }
  870. module.exports = (blender_file) => {
  871. if (!THREE) {
  872. console.warn("No ThreeJS object detected");
  873. return {};
  874. }
  875. var cache = {};
  876. return {
  877. loadScene: (three_scene) => loadScene(three_scene, blender_file, cache),
  878. loadModel: (model_name) => loadModel(model_name, blender_file, cache)
  879. };
  880. };
  881. },{"./light.js":5,"./material.js":6,"./mesh.js":7,"./texture.js":8}],5:[function(require,module,exports){
  882. /*jshint esversion: 6 */
  883. var blender_light_types = {
  884. point: 0,
  885. sun: 1,
  886. spot: 0,
  887. hemi: 0,
  888. area: 0
  889. };
  890. module.exports = function createThreeJSLamp(blend_lamp) {
  891. let ldata = blend_lamp.data;
  892. let pos_array = [blend_lamp.loc[0], blend_lamp.loc[2], -blend_lamp.loc[1]];
  893. let color = ((ldata.r * 255) << 16) | ((ldata.g * 255) << 8) | ((ldata.b * 255) << 0);
  894. let intesity = ldata.energy;
  895. let distance = 0;
  896. var three_light = null;
  897. switch (ldata.type) {
  898. case blender_light_types.point:
  899. var three_light = new THREE.PointLight(color, intesity, distance);
  900. three_light.position.fromArray(pos_array, 0);
  901. three_light.castShadow = true;
  902. break;
  903. case blender_light_types.sun:
  904. var three_light = new THREE.PointLight(color, intesity, distance);
  905. three_light.position.fromArray(pos_array, 0);
  906. three_light.castShadow = true;
  907. three_light.shadow.mapSize.width = 1024;
  908. three_light.shadow.mapSize.height = 1024;
  909. three_light.shadow.camera.near = 0.01;
  910. three_light.shadow.camera.far = 500;
  911. break;
  912. }
  913. return three_light;
  914. }
  915. },{}],6:[function(require,module,exports){
  916. /*jshint esversion: 6 */
  917. module.exports = (() => {
  918. const createTexture = require("./texture.js");
  919. var texture_mappings = {
  920. diff_color: 1,
  921. normal: 2,
  922. mirror: 8,
  923. diff_intensity: 16,
  924. spec_intensity: 32,
  925. emit: 32,
  926. alpha: 128,
  927. spec_hardness: 256,
  928. ray_mirror: 512,
  929. translucency: 1024,
  930. ambient: 2048,
  931. displacement: 4096,
  932. warp: 8192
  933. };
  934. let blender_specular_types = {
  935. cooktorr: 0,
  936. phong: 1,
  937. blinn: 2,
  938. toon: 3,
  939. wardiso: 4
  940. };
  941. function applyColorMapping(blender_texture, three_texture, material) {
  942. if (blender_texture.mapto & texture_mappings.diff_color) {
  943. material.map = three_texture;
  944. }
  945. }
  946. function applySpecMapping(blender_texture, three_texture, material) {
  947. if (blender_texture.mapto & texture_mappings.spec_color && material.type != "MeshStandardMaterial") {
  948. material.specularMap = three_texture;
  949. }
  950. if (blender_texture.mapto & texture_mappings.spec_intensity && material.type != "MeshStandardMaterial") {
  951. material.roughnessMap = three_texture;
  952. }
  953. }
  954. function applyAlphaMapping(blender_texture, three_texture, material) {
  955. if (blender_texture.mapto & texture_mappings.alpha) {
  956. material.alphaMap = three_texture;
  957. }
  958. }
  959. function applyNormalMapping(blender_texture, three_texture, material) {
  960. if (blender_texture.mapto & texture_mappings.normal) {
  961. material.normalMap = three_texture;
  962. material.normalScale = {
  963. x: blender_texture.norfac,
  964. y: blender_texture.norfac
  965. };
  966. }
  967. }
  968. function applyMirrorMapping(blender_texture, three_texture, material) {
  969. if (blender_texture.mapto & texture_mappings.mirror) {
  970. material.envMap = three_texture;
  971. material.envMapIntensity = blender_texture.mirrfac;
  972. }
  973. }
  974. var blender_texture_coordinates = {
  975. GENERATED : 1,
  976. REFLECTION : 2,
  977. NORMAL:4,
  978. GLOBAL : 8,
  979. UV : 16,
  980. OBJECT : 32,
  981. WINDOW: 1024,
  982. TANGENT:4096,
  983. PARTICLE: 8192,
  984. STRESS:16384
  985. }
  986. var blender_texture_mapping = {
  987. FLAT : 0,
  988. CUBE : 1,
  989. TUBE : 2,
  990. SPHERE : 3
  991. }
  992. function applyTexture(blender_texture, material) {
  993. //extract blender_texture data. Use Only if image has been supplied.
  994. if (blender_texture && blender_texture.tex && blender_texture.tex.ima) {
  995. let three_texture = createTexture(blender_texture.tex.ima);
  996. if(blender_texture.texco == blender_texture_coordinates.REFLECTION){
  997. switch(blender_texture.mapping){
  998. case blender_texture_mapping.FLAT:
  999. three_texture.mapping = THREE.EquirectangularReflectionMapping;
  1000. break;
  1001. case blender_texture_mapping.SPHERE:
  1002. three_texture.mapping = THREE.SphericalReflectionMapping;
  1003. break;
  1004. }
  1005. //three_texture.mapping = THREE.EquirectangularRefractionMapping;
  1006. }
  1007. applyColorMapping(blender_texture, three_texture, material);
  1008. applySpecMapping(blender_texture, three_texture, material);
  1009. applyAlphaMapping(blender_texture, three_texture, material);
  1010. applyNormalMapping(blender_texture, three_texture, material);
  1011. applyMirrorMapping(blender_texture, three_texture, material);
  1012. }
  1013. }
  1014. return function createThreeJSMaterial(blend_mat) {
  1015. var material = null;
  1016. var textures = blend_mat.mtex;
  1017. switch (blend_mat.spec_shader) {
  1018. case blender_specular_types.lambert:
  1019. material = new THREE.MeshLambertMaterial();
  1020. material.color.setRGB(blend_mat.r, blend_mat.g, blend_mat.b);
  1021. break;
  1022. case blender_specular_types.blinn:
  1023. case blender_specular_types.phong:
  1024. material = new THREE.MeshStandardMaterial();
  1025. material.color.setRGB(blend_mat.r, blend_mat.g, blend_mat.b);
  1026. //material.specular.setRGB(blend_mat.specr, blend_mat.specg, blend_mat.specb);
  1027. material.roughness = (1 - (blend_mat.har / 512));
  1028. material.metalness = 1 - blend_mat.ref;
  1029. if(blend_mat.alpha < 0.98){
  1030. material.transparent = true;
  1031. material.opacity = blend_mat.alpha;
  1032. console.log(blend_mat, material)
  1033. }
  1034. break;
  1035. case blender_specular_types.wardiso:
  1036. case blender_specular_types.cooktorr:
  1037. material = new THREE.MeshPhongMaterial();
  1038. material.color.setRGB(blend_mat.r, blend_mat.g, blend_mat.b);
  1039. material.specular.setRGB(blend_mat.specr, blend_mat.specg, blend_mat.specb);
  1040. material.shininess = blend_mat.har / 512;
  1041. material.reflectivity = blend_mat.ref * 100;
  1042. break;
  1043. default:
  1044. material = new THREE.MeshLambertMaterial();
  1045. material.color.setRGB(blend_mat.r, blend_mat.g, blend_mat.b);
  1046. break;
  1047. }
  1048. var at = (texture) => applyTexture(texture, material);
  1049. if (textures && textures.length) textures.map(at);
  1050. return material;
  1051. };
  1052. })();
  1053. },{"./texture.js":8}],7:[function(require,module,exports){
  1054. /*jshint esversion: 6 */
  1055. module.exports = function createThreeJSBufferGeometry(blender_mesh, origin) {
  1056. //get materials
  1057. let pick_material = 0,
  1058. mesh = blender_mesh,
  1059. faces = mesh.mpoly,
  1060. loops = mesh.mloop,
  1061. UV = mesh.mloopuv,
  1062. verts = mesh.mvert;
  1063. var geometry = new THREE.BufferGeometry();
  1064. if (!faces) return geometry;
  1065. var index_count = 0;
  1066. //precalculate the size of the array needed for faces
  1067. var face_indice_count = 0;
  1068. var face_indice_counta = 0;
  1069. for (var i = 0; i < faces.length; i++) {
  1070. var face = faces[i] || faces;
  1071. var len = face.totloop;
  1072. var indexi = 1;
  1073. face_indice_counta += (len * 2 / 3) | 0;
  1074. while (indexi < len) {
  1075. face_indice_count += 3;
  1076. indexi += 2;
  1077. }
  1078. }
  1079. //extract face info and dump into array buffer;
  1080. var face_buffer = new Uint32Array(face_indice_count);
  1081. var uv_buffer = new Float32Array(face_indice_count * 2);
  1082. var normal_buffer = new Float32Array(face_indice_count * 3);
  1083. var verts_array_buff = new Float32Array(face_indice_count * 3);
  1084. for (var i = 0; i < faces.length; i++) {
  1085. var face = faces[i] || faces;
  1086. var len = face.totloop;
  1087. var start = face.loopstart;
  1088. var indexi = 1;
  1089. var offset = 0;
  1090. while (indexi < len) {
  1091. var face_normals = [];
  1092. var face_index_array = [];
  1093. var face_uvs = [];
  1094. let index = 0;
  1095. for (var l = 0; l < 3; l++) {
  1096. //Per Vertice
  1097. if ((indexi - 1) + l < len) {
  1098. index = start + (indexi - 1) + l;
  1099. } else {
  1100. index = start;
  1101. }
  1102. var v = loops[index].v;
  1103. var vert = verts[v];
  1104. face_buffer[index_count] = index_count;
  1105. //get normals, which are 16byte ints, and norm them back into floats.
  1106. verts_array_buff[index_count * 3 + 0] = vert.co[0] + origin[0];
  1107. verts_array_buff[index_count * 3 + 1] = vert.co[2] + origin[2];
  1108. verts_array_buff[index_count * 3 + 2] = -vert.co[1] + -origin[1];
  1109. normal_buffer[index_count * 3 + 0] = vert.no[0];
  1110. normal_buffer[index_count * 3 + 1] = vert.no[2];
  1111. normal_buffer[index_count * 3 + 2] = (-vert.no[1]);
  1112. if (UV) {
  1113. var uv = UV[index].uv;
  1114. uv_buffer[index_count * 2 + 0] = uv[0];
  1115. uv_buffer[index_count * 2 + 1] = uv[1];
  1116. }
  1117. index_count++;
  1118. }
  1119. indexi += 2;
  1120. }
  1121. }
  1122. geometry.addAttribute('position', new THREE.BufferAttribute(verts_array_buff, 3));
  1123. geometry.setIndex(new THREE.BufferAttribute(face_buffer, 1));
  1124. geometry.addAttribute('normal', new THREE.BufferAttribute(normal_buffer, 3));
  1125. geometry.addAttribute('uv', new THREE.BufferAttribute(uv_buffer, 2));
  1126. //geometry.blend_mat = materials[pick_material];
  1127. return geometry;
  1128. };
  1129. function createThreeJSGeometry(blender_mesh, origin) {
  1130. //get materials
  1131. var mats = blender_mesh.mat,
  1132. materials = [];
  1133. for (var i = 0; i < mats.length; i++) {
  1134. var material = createThreeJSMaterial(mats[i]);
  1135. materials.push(material);
  1136. }
  1137. let pick_material = 0,
  1138. mesh = blender_mesh,
  1139. faces = mesh.mpoly,
  1140. loops = mesh.mloop,
  1141. UV = mesh.mloopuv,
  1142. verts = mesh.mvert,
  1143. vert_array = [],
  1144. face_array = [],
  1145. uv_array = [],
  1146. normal_array = [];
  1147. var geometry = new THREE.Geometry();
  1148. if (!faces) return geometry;
  1149. var index_count = 0;
  1150. let verts_array_buff = new Float32Array(verts.length * 3);
  1151. for (var i = 0; i < verts.length; i++) {
  1152. let vert = verts[i];
  1153. vert_array.push(new THREE.Vector3(vert.co[0] + origin[0], vert.co[2] + origin[2], -vert.co[1] - origin[1]));
  1154. }
  1155. for (var i = 0; i < faces.length; i++) {
  1156. var face = faces[i] || faces;
  1157. var len = face.totloop;
  1158. var start = face.loopstart;
  1159. var indexi = 1;
  1160. pick_material = face.mat_nr;
  1161. while (indexi < len) {
  1162. var face_normals = [];
  1163. var face_index_array = [];
  1164. var face_uvs = [];
  1165. let index = 0;
  1166. for (var l = 0; l < 3; l++) {
  1167. //Per Vertice
  1168. if ((indexi - 1) + l < len) {
  1169. index = start + (indexi - 1) + l;
  1170. } else {
  1171. index = start;
  1172. }
  1173. var v = loops[index].v;
  1174. var vert = verts[v];
  1175. face_index_array.push(v);
  1176. index_count++;
  1177. //get normals, which are 16byte ints, and norm them back into floats.
  1178. var
  1179. n1 = vert.no[0],
  1180. n2 = vert.no[2],
  1181. n3 = -vert.no[1];
  1182. var nl = 1;
  1183. Math.sqrt((n1 * n1) + (n2 * n2) + (n3 * n3));
  1184. face_normals.push(new THREE.Vector3(n1 / nl, n2 / nl, n3 / nl));
  1185. if (UV) {
  1186. var uv = UV[index].uv;
  1187. face_uvs.push(new THREE.Vector2(uv[0], uv[1]));
  1188. }
  1189. }
  1190. uv_array.push(face_uvs);
  1191. face_array.push(new THREE.Face3(
  1192. face_index_array[0], face_index_array[1], face_index_array[2],
  1193. face_normals
  1194. ));
  1195. indexi += 2;
  1196. }
  1197. }
  1198. geometry.blend_mat = materials[pick_material];
  1199. geometry.vertices = vert_array;
  1200. geometry.faces = face_array;
  1201. if (uv_array.length > 0) {
  1202. geometry.faceVertexUvs = [uv_array];
  1203. }
  1204. geometry.uvsNeedUpdate = true;
  1205. //Well, using blender file normals does not work. Will need to investigate why normals from the blender file do not provide correct results.
  1206. //For now, have Three calculate normals.
  1207. geometry.computeVertexNormals();
  1208. return geometry;
  1209. };
  1210. },{}],8:[function(require,module,exports){
  1211. /*jshint esversion: 6 */
  1212. let blender_texture_cache = {};
  1213. module.exports = function createThreeJSTexture(image) {
  1214. let base64 = require("base64-js");
  1215. let parsed_blend_file = image.__blender_file__;
  1216. let texture = null;
  1217. let name = image.aname;
  1218. if (image.packedfile) {
  1219. if (blender_texture_cache[name]) {
  1220. texture = blender_texture_cache[name];
  1221. } else {
  1222. //get the extension
  1223. let ext = name.split('.').pop();
  1224. let data = image.packedfile;
  1225. let size = data.size;
  1226. let offset = data.data.__data_address__;
  1227. let raw_data = parsed_blend_file.byte.slice(offset, offset + size);
  1228. let encodedData = base64.fromByteArray(raw_data);
  1229. let dataURI;
  1230. switch (ext) {
  1231. case "png":
  1232. dataURI = "data:image/png;base64," + encodedData;
  1233. break;
  1234. case "jpg":
  1235. dataURI = "data:image/jpeg;base64," + encodedData;
  1236. break;
  1237. }
  1238. let img = new Image();
  1239. img.src = dataURI;
  1240. texture = new THREE.Texture(img);
  1241. img.onload = () => {
  1242. texture.needsUpdate = true;
  1243. };
  1244. blender_texture_cache[name] = texture;
  1245. }
  1246. }
  1247. return texture;
  1248. };
  1249. },{"base64-js":1}]},{},[2])
  1250. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL0FwcERhdGEvUm9hbWluZy9ucG0vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIm5vZGVfbW9kdWxlcy9iYXNlNjQtanMvaW5kZXguanMiLCJzb3VyY2UvbWFpbi5qcyIsInNvdXJjZS9wYXJzZXIvcGFyc2VyLmpzIiwic291cmNlL3RocmVlanMvYmxlbmRfdGhyZWUuanMiLCJzb3VyY2UvdGhyZWVqcy9saWdodC5qcyIsInNvdXJjZS90aHJlZWpzL21hdGVyaWFsLmpzIiwic291cmNlL3RocmVlanMvbWVzaC5qcyIsInNvdXJjZS90aHJlZWpzL3RleHR1cmUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2eEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIid1c2Ugc3RyaWN0J1xuXG5leHBvcnRzLmJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoXG5leHBvcnRzLnRvQnl0ZUFycmF5ID0gdG9CeXRlQXJyYXlcbmV4cG9ydHMuZnJvbUJ5dGVBcnJheSA9IGZyb21CeXRlQXJyYXlcblxudmFyIGxvb2t1cCA9IFtdXG52YXIgcmV2TG9va3VwID0gW11cbnZhciBBcnIgPSB0eXBlb2YgVWludDhBcnJheSAhPT0gJ3VuZGVmaW5lZCcgPyBVaW50OEFycmF5IDogQXJyYXlcblxudmFyIGNvZGUgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLydcbmZvciAodmFyIGkgPSAwLCBsZW4gPSBjb2RlLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XG4gIGxvb2t1cFtpXSA9IGNvZGVbaV1cbiAgcmV2TG9va3VwW2NvZGUuY2hhckNvZGVBdChpKV0gPSBpXG59XG5cbnJldkxvb2t1cFsnLScuY2hhckNvZGVBdCgwKV0gPSA2MlxucmV2TG9va3VwWydfJy5jaGFyQ29kZUF0KDApXSA9IDYzXG5cbmZ1bmN0aW9uIHBsYWNlSG9sZGVyc0NvdW50IChiNjQpIHtcbiAgdmFyIGxlbiA9IGI2NC5sZW5ndGhcbiAgaWYgKGxlbiAlIDQgPiAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHN0cmluZy4gTGVuZ3RoIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA0JylcbiAgfVxuXG4gIC8vIHRoZSBudW1iZXIgb2YgZXF1YWwgc2lnbnMgKHBsYWNlIGhvbGRlcnMpXG4gIC8vIGlmIHRoZXJlIGFyZSB0d28gcGxhY2Vob2xkZXJzLCB0aGFuIHRoZSB0d28gY2hhcmFjdGVycyBiZWZvcmUgaXRcbiAgLy8gcmVwcmVzZW50IG9uZSBieXRlXG4gIC8vIGlmIHRoZXJlIGlzIG9ubHkgb25lLCB0aGVuIHRoZSB0aHJlZSBjaGFyYWN0ZXJzIGJlZm9yZSBpdCByZXByZXNlbnQgMiBieXRlc1xuICAvLyB0aGlzIGlzIGp1c3QgYSBjaGVhcCBoYWNrIHRvIG5vdCBkbyBpbmRleE9mIHR3aWNlXG4gIHJldHVybiBiNjRbbGVuIC0gMl0gPT09ICc9JyA/IDIgOiBiNjRbbGVuIC0gMV0gPT09ICc9JyA/IDEgOiAwXG59XG5cbmZ1bmN0aW9uIGJ5dGVMZW5ndGggKGI2NCkge1xuICAvLyBiYXNlNjQgaXMgNC8zICsgdXAgdG8gdHdvIGNoYXJhY3RlcnMgb2YgdGhlIG9yaWdpbmFsIGRhdGFcbiAgcmV0dXJuIChiNjQubGVuZ3RoICogMyAvIDQpIC0gcGxhY2VIb2xkZXJzQ291bnQoYjY0KVxufVxuXG5mdW5jdGlvbiB0b0J5dGVBcnJheSAoYjY0KSB7XG4gIHZhciBpLCBsLCB0bXAsIHBsYWNlSG9sZGVycywgYXJyXG4gIHZhciBsZW4gPSBiNjQubGVuZ3RoXG4gIHBsYWNlSG9sZGVycyA9IHBsYWNlSG9sZGVyc0NvdW50KGI2NClcblxuICBhcnIgPSBuZXcgQXJyKChsZW4gKiAzIC8gNCkgLSBwbGFjZUhvbGRlcnMpXG5cbiAgLy8gaWYgdGhlcmUgYXJlIHBsYWNlaG9sZGVycywgb25seSBnZXQgdXAgdG8gdGhlIGxhc3QgY29tcGxldGUgNCBjaGFyc1xuICBsID0gcGxhY2VIb2xkZXJzID4gMCA/IGxlbiAtIDQgOiBsZW5cblxuICB2YXIgTCA9IDBcblxuICBmb3IgKGkgPSAwOyBpIDwgbDsgaSArPSA0KSB7XG4gICAgdG1wID0gKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKV0gPDwgMTgpIHwgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMSldIDw8IDEyKSB8IChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDIpXSA8PCA2KSB8IHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMyldXG4gICAgYXJyW0wrK10gPSAodG1wID4+IDE2KSAmIDB4RkZcbiAgICBhcnJbTCsrXSA9ICh0bXAgPj4gOCkgJiAweEZGXG4gICAgYXJyW0wrK10gPSB0bXAgJiAweEZGXG4gIH1cblxuICBpZiAocGxhY2VIb2xkZXJzID09PSAyKSB7XG4gICAgdG1wID0gKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKV0gPDwgMikgfCAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAxKV0gPj4gNClcbiAgICBhcnJbTCsrXSA9IHRtcCAmIDB4RkZcbiAgfSBlbHNlIGlmIChwbGFjZUhvbGRlcnMgPT09IDEpIHtcbiAgICB0bXAgPSAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXSA8PCAxMCkgfCAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAxKV0gPDwgNCkgfCAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAyKV0gPj4gMilcbiAgICBhcnJbTCsrXSA9ICh0bXAgPj4gOCkgJiAweEZGXG4gICAgYXJyW0wrK10gPSB0bXAgJiAweEZGXG4gIH1cblxuICByZXR1cm4gYXJyXG59XG5cbmZ1bmN0aW9uIHRyaXBsZXRUb0Jhc2U2NCAobnVtKSB7XG4gIHJldHVybiBsb29rdXBbbnVtID4+IDE4ICYgMHgzRl0gKyBsb29rdXBbbnVtID4+IDEyICYgMHgzRl0gKyBsb29rdXBbbnVtID4+IDYgJiAweDNGXSArIGxvb2t1cFtudW0gJiAweDNGXVxufVxuXG5mdW5jdGlvbiBlbmNvZGVDaHVuayAodWludDgsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHRtcFxuICB2YXIgb3V0cHV0ID0gW11cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpICs9IDMpIHtcbiAgICB0bXAgPSAodWludDhbaV0gPDwgMTYpICsgKHVpbnQ4W2kgKyAxXSA8PCA4KSArICh1aW50OFtpICsgMl0pXG4gICAgb3V0cHV0LnB1c2godHJpcGxldFRvQmFzZTY0KHRtcCkpXG4gIH1cbiAgcmV0dXJuIG91dHB1dC5qb2luKCcnKVxufVxuXG5mdW5jdGlvbiBmcm9tQnl0ZUFycmF5ICh1aW50OCkge1xuICB2YXIgdG1wXG4gIHZhciBsZW4gPSB1aW50OC5sZW5ndGhcbiAgdmFyIGV4dHJhQnl0ZXMgPSBsZW4gJSAzIC8vIGlmIHdlIGhhdmUgMSBieXRlIGxlZnQsIHBhZCAyIGJ5dGVzXG4gIHZhciBvdXRwdXQgPSAnJ1xuICB2YXIgcGFydHMgPSBbXVxuICB2YXIgbWF4Q2h1bmtMZW5ndGggPSAxNjM4MyAvLyBtdXN0IGJlIG11bHRpcGxlIG9mIDNcblxuICAvLyBnbyB0aHJvdWdoIHRoZSBhcnJheSBldmVyeSB0aHJlZSBieXRlcywgd2UnbGwgZGVhbCB3aXRoIHRyYWlsaW5nIHN0dWZmIGxhdGVyXG4gIGZvciAodmFyIGkgPSAwLCBsZW4yID0gbGVuIC0gZXh0cmFCeXRlczsgaSA8IGxlbjI7IGkgKz0gbWF4Q2h1bmtMZW5ndGgpIHtcbiAgICBwYXJ0cy5wdXNoKGVuY29kZUNodW5rKHVpbnQ4LCBpLCAoaSArIG1heENodW5rTGVuZ3RoKSA+IGxlbjIgPyBsZW4yIDogKGkgKyBtYXhDaHVua0xlbmd0aCkpKVxuICB9XG5cbiAgLy8gcGFkIHRoZSBlbmQgd2l0aCB6ZXJvcywgYnV0IG1ha2Ugc3VyZSB0byBub3QgZm9yZ2V0IHRoZSBleHRyYSBieXRlc1xuICBpZiAoZXh0cmFCeXRlcyA9PT0gMSkge1xuICAgIHRtcCA9IHVpbnQ4W2xlbiAtIDFdXG4gICAgb3V0cHV0ICs9IGxvb2t1cFt0bXAgPj4gMl1cbiAgICBvdXRwdXQgKz0gbG9va3VwWyh0bXAgPDwgNCkgJiAweDNGXVxuICAgIG91dHB1dCArPSAnPT0nXG4gIH0gZWxzZSBpZiAoZXh0cmFCeXRlcyA9PT0gMikge1xuICAgIHRtcCA9ICh1aW50OFtsZW4gLSAyXSA8PCA4KSArICh1aW50OFtsZW4gLSAxXSlcbiAgICBvdXRwdXQgKz0gbG9va3VwW3RtcCA+PiAxMF1cbiAgICBvdXRwdXQgKz0gbG9va3VwWyh0bXAgPj4gNCkgJiAweDNGXVxuICAgIG91dHB1dCArPSBsb29rdXBbKHRtcCA8PCAyKSAmIDB4M0ZdXG4gICAgb3V0cHV0ICs9ICc9J1xuICB9XG5cbiAgcGFydHMucHVzaChvdXRwdXQpXG5cbiAgcmV0dXJuIHBhcnRzLmpvaW4oJycpXG59XG4iLCJcclxuLypqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXHJcblxyXG5jb25zdCB0aHJlZSA9IHJlcXVpcmUoXCIuL3RocmVlanMvYmxlbmRfdGhyZWUuanNcIik7XHJcblxyXG5jb25zdCBwYXJzZXIgPSByZXF1aXJlKFwiLi9wYXJzZXIvcGFyc2VyLmpzXCIpKCk7XHJcblxyXG5cclxuZnVuY3Rpb24gbG9hZEZpbGUoYmxlbmRlcl9maWxlLCByZXMsIHJlail7XHRcclxuXHR0aHJlZV9tb2R1bGUgPSB0aHJlZShibGVuZGVyX2ZpbGUpO1xyXG5cclxuXHQvL1RPRE86IFJlcG9ydCBhbnkgZXJyb3JzIHdpdGggVGhyZWVKUyBiZWZvcmUgY29udGludWluZy5cclxuXHRcclxuXHRyZXMoe1xyXG5cdFx0ZmlsZSA6IGJsZW5kZXJfZmlsZSxcclxuXHRcdHRocmVlIDogdGhyZWVfbW9kdWxlXHJcblx0fSk7XHJcbn1cclxuXHJcbi8qIFRoaXMgcmVwcmVzZW50cyBhIHBhcnNlZCBibGVuZGZpbGUgaW5zdGFuY2UgaWYgcGFyc2luZyBpcyBzdWNjZXNzZnVsLiBJdCB3aWxsIGFjY2VwdCBhIHN0cmluZyBvciBhIGJpbmFyeSBkYXRhIG9iamVjdC4gU3RyaW5ncyBtdXN0IGJlIGEgdmFsaWQgVVJJIHRvIGEgYmxlbmRlciBmaWxlLiBCaW5hcnkgZGF0YSBtYXkgYmUgaW4gdGhlIGZvcm0gb2YgYW4gQXJyYXlCdWZmZXIsIFR5cGVkQXJyYXksIG9yIGEgQmxvYi4gQmluYXJ5IGRhdGEgbXVzdCBhbHNvIGNvbnRhaW4gdGhlIGJpbmFyeSBkYXRhIG9mIGEgYmxlbmRlciBmaWxlLiovXHJcblxyXG5KU0JMRU5EID0gKGZpbGV1cmlfb3JfZmlsZWRhdGEsIG5hbWUgPSBcIlwiKT0+e1xyXG5cclxuXHRjb25zdCBwcm9taXNlID0gbmV3IFByb21pc2UoXHJcblx0XHQocmVzLCByZWopID0+e1xyXG5cdFx0XHRwYXJzZXIub25QYXJzZVJlYWR5ID0gKGJsZW5kZXJfZmlsZSkgPT4ge1xyXG5cdFx0XHRcdGxvYWRGaWxlKGJsZW5kZXJfZmlsZSwgcmVzLCByZWopO1xyXG5cdFx0XHR9O1xyXG5cclxuXHRcdFx0Ly9JZiBmaWxldXJpX29yX2ZpbGVkYXRhIGlzIGEgc3RyaW5nLCBhdHRlbXB0IHRvIGxvYWQgdGhlIGZpbGUgYXN5bmNocm9ub3VzbHlcclxuXHRcdFx0aWYodHlwZW9mIGZpbGV1cmlfb3JfZmlsZWRhdGEgPT0gXCJzdHJpbmdcIil7XHJcblx0XHRcdFx0XHJcblx0XHRcdFx0bGV0IHJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcclxuXHRcdFx0ICAgIFxyXG5cdFx0XHQgICAgcmVxdWVzdC5vcGVuKFwiR0VUXCIsIGZpbGV1cmlfb3JfZmlsZWRhdGEsIHRydWUpO1xyXG5cdFx0XHQgICAgXHJcblx0XHRcdCAgICByZXF1ZXN0LnJlc3BvbnNlVHlwZSA9ICdibG9iJztcclxuXHRcdFx0ICAgIFxyXG5cdFx0XHQgICAgcmVxdWVzdC5vbmxvYWQgPSAoKSA9PiB7XHJcblx0XHRcdCAgICAgICAgbGV0IGZpbGUgPSByZXF1ZXN0LnJlc3BvbnNlO1xyXG5cdFx0XHQgICAgICAgIFxyXG5cdFx0XHQgICAgICAgIHBhcnNlci5sb2FkQmxlbmRGcm9tQmxvYihuZXcgQmxvYihbZmlsZV0pLCBmaWxldXJpX29yX2ZpbGVkYXRhKTtcclxuXHRcdFx0ICAgIH07XHJcblx0XHRcdCAgICBcclxuXHRcdFx0ICAgIHJlcXVlc3Quc2VuZCgpO1xyXG5cclxuXHRcdFx0ICAgIHJldHVybjtcclxuXHRcdFx0fVxyXG5cdFx0XHRkZWJ1Z2dlclxyXG5cclxuXHRcdFx0aWYodHlwZW9mIGZpbGV1cmlfb3JfZmlsZWRhdGEgPT0gXCJvYmplY3RcIil7XHJcblx0XHRcdFx0Ly9BdHRlbXB0IHRvIGxvYWQgZnJvbSBibG9iIG9yIGFycmF5IGJ1ZmZlcjtcclxuXHRcdFx0XHRpZihmaWxldXJpX29yX2ZpbGVkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpe1xyXG5cdFx0XHRcdFx0cGFyc2VyLmxvYWRCbGVuZEZyb21BcnJheUJ1ZmZlcihmaWxldXJpX29yX2ZpbGVkYXRhLCBuYW1lKTtcclxuXHRcdFx0XHRcdHJldHVybjtcclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdGlmKGZpbGV1cmlfb3JfZmlsZWRhdGEgaW5zdGFuY2VvZiBCbG9iKXtcclxuXHRcdFx0XHRcdHBhcnNlci5sb2FkQmxlbmRGcm9tQmxvYihmaWxldXJpX29yX2ZpbGVkYXRhLCBuYW1lKTtcclxuXHRcdFx0XHRcdHJldHVybjtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vVW5rbm93biBmaWxlIHR5cGUgcGFzc2VkIC0+IGFib3J0IGFuZCByZWplY3RcclxuXHJcblx0XHRcdGNvbnNvbGUud2FybihcIlVuc3VwcG9ydGVkIGZpbGUgdHlwZSBwYXNzZWQgdG8gSlNCbGVuZFwiLCBmaWxldXJpX29yX2ZpbGVkYXRhKTtcclxuXHRcdFx0XHJcblx0XHRcdHJlaihcIlVuc3VwcG9ydGVkIGZpbGUgdHlwZSBwYXNzZWQgdG8gSlNCbGVuZFwiKTtcclxuXHRcdH1cclxuXHQpO1xyXG5cclxuXHRyZXR1cm4gcHJvbWlzZTtcclxufTsiLCIvKmpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuY29uc3QgRE5BMSA9IDgyNjM2MzQ2MDtcbmNvbnN0IEVOREIgPSAxMTExNzcyNzQxO1xuXG4vKiBOb3RlOiBCbGVuZGVyIGNvb3JpZGluYXRlcyB0cmVhdCB0aGUgWiBheGlzIGFzIHRoZSB2ZXJ0aWNsZSBhbmQgIFkgYXMgZGVwdGguICovXG5tb2R1bGUuZXhwb3J0cyAgPSAoZnVuY3Rpb24odW56aXBwZXIpIHtcbiAgICAvL0EgaGVscGVyIG9iamVjdCB0byBpZGVudGlmeSBCbGVuZGVyIE9iamVjdCBzdHJ1Y3RzIGJ5IHR5cGUgbmFtZS4gXG4gICAgdmFyIGJsZW5kZXJfdHlwZXMgPSB7XG4gICAgICAgIG1lc2hfb2JqZWN0OiAxLFxuICAgICAgICBsYW1wOiAxMCxcbiAgICB9O1xuXG4gICAgLy93ZWIgd29ya2VyIG5vdCBmdW5jdGlvbmFsIGluIHRoaXMgdmVyc2lvblxuICAgIFVTRV9XRUJXT1JLRVIgPSBmYWxzZTtcblxuICAgIHZhciB3b3JrZXIgPSBudWxsLFxuXG4gICAgICAgIEZSID0gbmV3IEZpbGVSZWFkZXIoKSxcblxuICAgICAgICByZXR1cm5fb2JqZWN0ID0ge1xuICAgICAgICAgICAgbG9hZEJsZW5kRnJvbUFycmF5QnVmZmVyOiBmdW5jdGlvbihhcnJheV9idWZmZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5fb2JqZWN0LnJlYWR5ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgaWYgKFVTRV9XRUJXT1JLRVIpIHtcbiAgICAgICAgICAgICAgICAgICAgd29ya2VyLnBvc3RNZXNzYWdlKGFycmF5X2J1ZmZlciwgYXJyYXlfYnVmZmVyKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB3b3JrZXIub25tZXNzYWdlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IGFycmF5X2J1ZmZlclxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbG9hZEJsZW5kRnJvbUJsb2I6IGZ1bmN0aW9uKGJsb2IpIHtcbiAgICAgICAgICAgICAgICBGUi5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuX29iamVjdC5sb2FkQmxlbmRGcm9tQXJyYXlCdWZmZXIodGhpcy5yZXN1bHQpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgRlIucmVhZEFzQXJyYXlCdWZmZXIoYmxvYik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVhZHk6IHRydWUsXG4gICAgICAgICAgICBvblBhcnNlUmVhZHk6IGZ1bmN0aW9uKCkge30sXG4gICAgICAgIH07XG5cbiAgICB3b3JrZXIgPSBuZXcgd29ya2VyX2NvZGUoKTtcblxuICAgIHdvcmtlci5wb3N0TWVzc2FnZSA9IGZ1bmN0aW9uKG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuX29iamVjdC5vblBhcnNlUmVhZHkobWVzc2FnZSk7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIHdvcmtlcl9jb2RlKCkge1xuICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICB2YXIgZGF0YSA9IG51bGwsXG4gICAgICAgICAgICBfZGF0YSA9IG51bGwsXG4gICAgICAgICAgICBCSUdfRU5ESUFOID0gZmFsc2UsXG4gICAgICAgICAgICBwb2ludGVyX3NpemUgPSAwLFxuICAgICAgICAgICAgc3RydWN0X25hbWVzID0gW10sXG4gICAgICAgICAgICBvZmZzZXQgPSAwLFxuICAgICAgICAgICAgd29ya2luZ19ibGVuZF9maWxlID0gbnVsbCxcbiAgICAgICAgICAgIGN1cnJlbnRfU0ROQV90ZW1wbGF0ZSA9IG51bGwsXG4gICAgICAgICAgICB0ZW1wbGF0ZXMgPSB7fSxcbiAgICAgICAgICAgIGZpbmlzaGVkX29iamVjdHMgPSBbXSxcbiAgICAgICAgICAgIEZJTEUgPSBudWxsLFxuICAgICAgICAgICAgQUIgPSBudWxsO1xuXG4gICAgICAgIGZ1bmN0aW9uIHBhcnNlRmlsZShtc2cpIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbXNnLmRhdGEgPT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgIC8vIHJlc2V0IGdsb2JhbCB2YXJpYWJsZXNcbiAgICAgICAgICAgICAgICBBQiA9IG51bGw7XG4gICAgICAgICAgICAgICAgZGF0YSA9IG51bGw7XG4gICAgICAgICAgICAgICAgQklHX0VORElBTiA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHBvaW50ZXJfc2l6ZSA9IDA7XG4gICAgICAgICAgICAgICAgc3RydWN0X25hbWVzID0gW107XG4gICAgICAgICAgICAgICAgb2Zmc2V0ID0gMDtcbiAgICAgICAgICAgICAgICB3b3JraW5nX2JsZW5kX2ZpbGUgPSBudWxsO1xuICAgICAgICAgICAgICAgIGZpbmlzaGVkX29iamVjdHMgPSBbXTtcbiAgICAgICAgICAgICAgICBjdXJyZW50X1NETkFfdGVtcGxhdGUgPSBudWxsO1xuXG5cbiAgICAgICAgICAgICAgICAvLyBzZXQgZGF0YVxuICAgICAgICAgICAgICAgIF9kYXRhID0gbXNnLmRhdGE7XG5cbiAgICAgICAgICAgICAgICBBQiA9IF9kYXRhLnNsaWNlKCk7XG5cbiAgICAgICAgICAgICAgICBkYXRhID0gbmV3IERhdGFWaWV3KF9kYXRhKTtcblxuXG4gICAgICAgICAgICAgICAgRklMRSA9IG5ldyBCTEVOREVSX0ZJTEUoQUIpO1xuXG4gICAgICAgICAgICAgICAgLy9zdGFydCBwYXJzaW5nXG4gICAgICAgICAgICAgICAgcmVhZEZpbGUoKTtcblxuICAgICAgICAgICAgICAgIC8vZXhwb3J0IHBhcnNlZCBkYXRhXG4gICAgICAgICAgICAgICAgc2VsZi5wb3N0TWVzc2FnZShGSUxFKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8qXG4gICAgICAgICAgICBFeHBvcnQgb2JqZWN0IGZvciBhIHBhcnNlZCBfX2JsZW5kZXJfZmlsZV9fLlxuICAgICAgICAqL1xuXG4gICAgICAgIHZhciBCTEVOREVSX0ZJTEUgPSBmdW5jdGlvbihBQikge1xuICAgICAgICAgICAgdGhpcy5BQiA9IEFCO1xuICAgICAgICAgICAgLy90aGlzLmRvdWJsZSA9IG5ldyBGbG9hdDY0QXJyYXkoQUIpO1xuICAgICAgICAgICAgdGhpcy5ieXRlID0gbmV3IFVpbnQ4QXJyYXkoQUIpO1xuXG4gICAgICAgICAgICB0aGlzLmR2ID0gbmV3IERhdGFWaWV3KEFCKTtcblxuICAgICAgICAgICAgdGhpcy5vYmplY3RzID0ge307XG4gICAgICAgICAgICB0aGlzLm1lbW9yeV9sb29rdXAgPSB7fSxcbiAgICAgICAgICAgICAgICB0aGlzLm9iamVjdF9hcnJheSA9IFtdO1xuXG4gICAgICAgICAgICB0aGlzLnRlbXBsYXRlID0gbnVsbDtcbiAgICAgICAgfTtcblxuICAgICAgICBCTEVOREVSX0ZJTEUucHJvdG90eXBlID0ge1xuICAgICAgICAgICAgYWRkT2JqZWN0OiBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9iamVjdF9hcnJheS5wdXNoKG9iaik7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLm9iamVjdHNbb2JqLmJsZW5kZXJfbmFtZV0pIHRoaXMub2JqZWN0c1tvYmouYmxlbmRlcl9uYW1lXSA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMub2JqZWN0c1tvYmouYmxlbmRlcl9uYW1lXS5wdXNoKG9iaik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcHJpbWVUeXBlczogZnVuY3Rpb24obGlzdF9vZl9kbmFfbmFtZXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3Rfb2ZfZG5hX25hbWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vdGhpcy5vYmplY3RzW2xpc3Rfb2ZfZG5hX25hbWVzW2ldXSA9IFtdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXRQb2ludGVyOiBmdW5jdGlvbihvZmZzZXQpIHtcbiAgICAgICAgICAgICAgICB2YXIgcG9pbnRlckxvdyA9IHRoaXMuZHYuZ2V0VWludDMyKG9mZnNldCwgdGhpcy50ZW1wbGF0ZS5lbmRpYW5lc3MpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnRlbXBsYXRlLnBvaW50ZXJfc2l6ZSA+IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBvaW50ZXJIaWdoID0gdGhpcy5kdi5nZXRVaW50MzIob2Zmc2V0ICsgNCwgdGhpcy50ZW1wbGF0ZS5lbmRpYW5lc3MpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy50ZW1wbGF0ZS5lbmRpYW5lc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAocG9pbnRlckxvdykgKyBcImx8aFwiICsgcG9pbnRlckhpZ2g7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKHBvaW50ZXJIaWdoKSArIFwiaHxsXCIgKyBwb2ludGVyTG93O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBvaW50ZXJMb3c7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGZ1bmN0aW9uIGdldERvY3VtZW50KGRhdGEpIHtcbiAgICAgICAgICAgIHZhciBvYmogPSByZWFkRmlsZShudWxsLCBkYXRhKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbGYub25tZXNzYWdlID0gcGFyc2VGaWxlO1xuICAgICAgICB0aGlzLm9ubWVzc2FnZSA9IHBhcnNlRmlsZTtcblxuICAgICAgICAvKlxuICAgICAgICAgICAgVGhlc2UgZnVuY3Rpb25zIG1hcCBvZmZzZXRzIGluIHRoZSBibGVuZGVyIF9fYmxlbmRlcl9maWxlX18gdG8gYmFzaWMgdHlwZXMgKGJ5dGUsc2hvcnQsaW50LGZsb2F0KSB0aHJvdWdoIFR5cGVkQXJyYXlzO1xuICAgICAgICAgICAgVGhpcyBhbGxvd3MgdGhlIHVuZGVybHlpbmcgYmluYXJ5IGRhdGEgdG8gYmUgY2hhbmdlZC5cbiAgICAgICAgKi9cblxuICAgICAgICBmdW5jdGlvbiBmbG9hdDY0UHJvcChvZmZzZXQsIEJsZW5kZXJfQXJyYXlfTGVuZ3RoLCBsZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChCbGVuZGVyX0FycmF5X0xlbmd0aCA+IDEpID9cbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBGbG9hdDY0QXJyYXkodGhpcy5fX2JsZW5kZXJfZmlsZV9fLkFCLCB0aGlzLl9fZGF0YV9hZGRyZXNzX18gKyBvZmZzZXQsIGxlbmd0aCkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fX2JsZW5kZXJfZmlsZV9fLmR2LmdldEZsb2F0NjQodGhpcy5fX2RhdGFfYWRkcmVzc19fICsgb2Zmc2V0LCB0aGlzLl9fYmxlbmRlcl9maWxlX18udGVtcGxhdGUuZW5kaWFuZXNzKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24oZmxvYXQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEJsZW5kZXJfQXJyYXlfTGVuZ3RoID4gMSkge30gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9fYmxlbmRlcl9maWxlX18uZHYuc2V0RmxvYXQ2NCh0aGlzLl9fZGF0YV9hZGRyZXNzX18gKyBvZmZzZXQsIGZsb2F0LCB0aGlzLl9fYmxlbmRlcl9maWxlX18udGVtcGxhdGUuZW5kaWFuZXNzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gZmxvYXRQcm9wKG9mZnNldCwgQmxlbmRlcl9BcnJheV9MZW5ndGgsIGxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKEJsZW5kZXJfQXJyYXlfTGVuZ3RoID4gMSkgP1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3IEZsb2F0MzJBcnJheSh0aGlzLl9fYmxlbmRlcl9maWxlX18uQUIsIHRoaXMuX19kYXRhX2FkZHJlc3NfXyArIG9mZnNldCwgbGVuZ3RoKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9fYmxlbmRlcl9maWxlX18uZHYuZ2V0RmxvYXQzMih0aGlzLl9fZGF0YV9hZGRyZXNzX18gKyBvZmZzZXQsIHRoaXMuX19ibGVuZGVyX2ZpbGVfXy50ZW1wbGF0ZS5lbmRpYW5lc3MpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2V0OiBmdW5jdGlvbihmbG9hdCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoQmxlbmRlcl9BcnJheV9MZW5ndGggPiAxKSB7fSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX19ibGVuZGVyX2ZpbGVfXy5kdi5zZXRGbG9hdDMyKHRoaXMuX19kYXRhX2FkZHJlc3NfXyArIG9mZnNldCwgZmxvYXQsIHRoaXMuX19ibGVuZGVyX2ZpbGVfXy50ZW1wbGF0ZS5lbmRpYW5lc3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBpbnRQcm9wKG9mZnNldCwgQmxlbmRlcl9BcnJheV9MZW5ndGgsIGxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKEJsZW5kZXJfQXJyYXlfTGVuZ3RoID4gMSkgP1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3IEludDMyQXJyYXkodGhpcy5fX2JsZW5kZXJfZmlsZV9fLkFCLCB0aGlzLl9fZGF0YV9hZGRyZXNzX18gKyBvZmZzZXQsIGxlbmd0aCkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fX2JsZW5kZXJfZmlsZV9fLmR2LmdldEludDMyKHRoaXMuX19kYXRhX2FkZHJlc3NfXyArIG9mZnNldCwgdGhpcy5fX2JsZW5kZXJfZmlsZV9fLnRlbXBsYXRlLmVuZGlhbmVzcyk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzZXQ6IGZ1bmN0aW9uKGludCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoQmxlbmRlcl9BcnJheV9MZW5ndGggPiAxKSB7fSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX19ibGVuZGVyX2ZpbGVfXy5kdi5zZXRJbnQzMih0aGlzLl9fZGF0YV9hZGRyZXNzX18gKyBvZmZzZXQsIGZsb2F0LCB0aGlzLl9fYmxlbmRlcl9maWxlX18udGVtcGxhdGUuZW5kaWFuZXNzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gdUludFByb3Aob2Zmc2V0LCBCbGVuZGVyX0FycmF5X0xlbmd0aCwgbGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoQmxlbmRlcl9BcnJheV9MZW5ndGggPiAxKSA/XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXcgVWludDMyQXJyYXkodGhpcy5fX2JsZW5kZXJfZmlsZV9fLkFCLCB0aGlzLl9fZGF0YV9hZGRyZXNzX18gKyBvZmZzZXQsIGxlbmd0aCkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fX2JsZW5kZXJfZmlsZV9fLmR2LmdldFVpbnQzMih0aGlzLl9fZGF0YV9hZGRyZXNzX18gKyBvZmZzZXQsIHRoaXMuX19ibGVuZGVyX2ZpbGVfXy50ZW1wbGF0ZS5lbmRpYW5lc3MpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgc2V0OiBmdW5jdGlvbihpbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEJsZW5kZXJfQXJyYXlfTGVuZ3RoID4gMSkge30gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9fYmxlbmRlcl9maWxlX18uZHYuc2V0VWludDMyKHRoaXMuX19kYXRhX2FkZHJlc3NfXyArIG9mZnNldCwgZmxvYXQsIHRoaXMuX19ibGVuZGVyX2ZpbGVfXy50ZW1wbGF0ZS5lbmRpYW5lc3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBzaG9ydFByb3Aob2Zmc2V0LCBCbGVuZGVyX0FycmF5X0xlbmd0aCwgbGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoQmxlbmRlcl9BcnJheV9MZW5ndGggPiAxKSA/XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXcgSW50MTZBcnJheSh0aGlzLl9fYmxlbmRlcl9maWxlX18uQUIsIHRoaXMuX19kYXRhX2FkZHJlc3NfXyArIG9mZnNldCwgbGVuZ3RoKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9fYmxlbmRlcl9maWxlX18uZHYuZ2V0SW50MTYodGhpcy5fX2RhdGFfYWRkcmVzc19fICsgb2Zmc2V0LCB0aGlzLl9fYmxlbmRlcl9maWxlX18udGVtcGxhdGUuZW5kaWFuZXNzKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24oZmxvYXQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEJsZW5kZXJfQXJyYXlfTGVuZ3RoID4gMSkge30gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9fYmxlbmRlcl9maWxlX18uZHYuc2V0SW50MTYodGhpcy5fX2RhdGFfYWRkcmVzc19fICsgb2Zmc2V0LCBmbG9hdCwgdGhpcy5fX2JsZW5kZXJfZmlsZV9fLnRlbXBsYXRlLmVuZGlhbmVzcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB1U2hvcnRQcm9wID0gKG9mZnNldCwgQmxlbmRlcl9BcnJheV9MZW5ndGgsIGxlbmd0aCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKEJsZW5kZXJfQXJyYXlfTGVuZ3RoID4gMSkgP1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3IFVpbnQxNkFycmF5KHRoaXMuX19ibGVuZGVyX2ZpbGVfXy5BQiwgdGhpcy5fX2RhdGFfYWRkcmVzc19fICsgb2Zmc2V0LCBsZW5ndGgpIDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX19ibGVuZGVyX2ZpbGVfXy5kdi5nZXRVaW50MTYodGhpcy5fX2RhdGFfYWRkcmVzc19fICsgb2Zmc2V0LCB0aGlzLl9fYmxlbmRlcl9maWxlX18udGVtcGxhdGUuZW5kaWFuZXNzKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24oZmxvYXQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEJsZW5kZXJfQXJyYXlfTGVuZ3RoID4gMSkge30gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9fYmxlbmRlcl9maWxlX18uZHYuc2V0VWludDE2KHRoaXMuX19kYXRhX2FkZHJlc3NfXyArIG9mZnNldCwgZmxvYXQsIHRoaXMuX19ibGVuZGVyX2ZpbGVfXy50ZW1wbGF0ZS5lbmRpYW5lc3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuXG4gICAgICAgIGZ1bmN0aW9uIGNoYXJQcm9wKG9mZnNldCwgQmxlbmRlcl9BcnJheV9MZW5ndGgsIGxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoQmxlbmRlcl9BcnJheV9MZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RhcnQgPSB0aGlzLl9fZGF0YV9hZGRyZXNzX18gKyBvZmZzZXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZW5kID0gc3RhcnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgYnVmZmVyX2d1YXJkID0gMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHRoaXMuX19ibGVuZGVyX2ZpbGVfXy5ieXRlW2VuZF0gIT0gMCAmJiBidWZmZXJfZ3VhcmQrKyA8IGxlbmd0aCkgZW5kKys7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZyh0aGlzLl9fYmxlbmRlcl9maWxlX18uQUIsIHN0YXJ0LCBlbmQpXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX19ibGVuZGVyX2ZpbGVfXy5ieXRlWyh0aGlzLl9fZGF0YV9hZGRyZXNzX18gKyBvZmZzZXQpXTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24oYnl0ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoQmxlbmRlcl9BcnJheV9MZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgc3RyaW5nID0gYnl0ZSArIFwiXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaSA9IDAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbCA9IHN0cmluZy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaSA8IGxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpIDwgbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9fYmxlbmRlcl9maWxlX18uYnl0ZVsodGhpcy5fX2RhdGFfYWRkcmVzc19fICsgb2Zmc2V0ICsgaSldID0gc3RyaW5nLmNoYXJDb2RlQXQoaSkgfCAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX19ibGVuZGVyX2ZpbGVfXy5ieXRlWyh0aGlzLl9fZGF0YV9hZGRyZXNzX18gKyBvZmZzZXQgKyBpKV0gPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9fYmxlbmRlcl9maWxlX18uYnl0ZVsodGhpcy5fX2RhdGFfYWRkcmVzc19fICsgb2Zmc2V0KV0gPSBieXRlIHwgMDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBwb2ludGVyUHJvcDIob2Zmc2V0KSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBwb2ludGVyID0gdGhpcy5fX2JsZW5kZXJfZmlsZV9fLmdldFBvaW50ZXIodGhpcy5fX2RhdGFfYWRkcmVzc19fICsgb2Zmc2V0LCB0aGlzLl9fYmxlbmRlcl9maWxlX18pO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGluayA9IHRoaXMuX19ibGVuZGVyX2ZpbGVfXy5tZW1vcnlfbG9va3VwW3BvaW50ZXJdO1xuXG4gICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHRzID0gW107XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpbmspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhZGRyZXNzID0gbGluay5fX2RhdGFfYWRkcmVzc19fO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGogPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludGVyID0gdGhpcy5fX2JsZW5kZXJfZmlsZV9fLmdldFBvaW50ZXIoYWRkcmVzcyArIGogKiA4LCB0aGlzLl9fYmxlbmRlcl9maWxlX18pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBvYmogPSB0aGlzLl9fYmxlbmRlcl9maWxlX18ubWVtb3J5X2xvb2t1cFtwb2ludGVyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW9iaikgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cy5wdXNoKG9iaik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaisrXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24oKSB7fVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gcG9pbnRlclByb3Aob2Zmc2V0LCBCbGVuZGVyX0FycmF5X0xlbmd0aCwgbGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChCbGVuZGVyX0FycmF5X0xlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBhcnJheSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGogPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG9mZiA9IG9mZnNldDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChqIDwgQmxlbmRlcl9BcnJheV9MZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgcG9pbnRlciA9IHRoaXMuX19ibGVuZGVyX2ZpbGVfXy5nZXRQb2ludGVyKHRoaXMuX19kYXRhX2FkZHJlc3NfXyArIG9mZiwgdGhpcy5fX2JsZW5kZXJfZmlsZV9fKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5LnB1c2godGhpcy5fX2JsZW5kZXJfZmlsZV9fLm1lbW9yeV9sb29rdXBbcG9pbnRlcl0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZiArPSBsZW5ndGggLy8vdGhpcy5fX2JsZW5kZXJfZmlsZV9fLnRlbXBsYXRlLnBvaW50ZXJfc2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhcnJheTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBwb2ludGVyID0gdGhpcy5fX2JsZW5kZXJfZmlsZV9fLmdldFBvaW50ZXIodGhpcy5fX2RhdGFfYWRkcmVzc19fICsgb2Zmc2V0LCB0aGlzLl9fYmxlbmRlcl9maWxlX18pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX19ibGVuZGVyX2ZpbGVfXy5tZW1vcnlfbG9va3VwW3BvaW50ZXJdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzZXQ6IGZ1bmN0aW9uKCkge31cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGNvbXBpbGVQcm9wKG9iaiwgbmFtZSwgdHlwZSwgb2Zmc2V0LCBhcnJheV9zaXplLCBJU19QT0lOVEVSLCBwb2ludGVyX3NpemUsIGxlbmd0aCkge1xuXG4gICAgICAgICAgICBpZiAoIUlTX1BPSU5URVIpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImRvdWJsZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwgbmFtZSwgZmxvYXQ2NFByb3Aob2Zmc2V0LCBhcnJheV9zaXplLCBsZW5ndGggPj4gMykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJmbG9hdFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwgbmFtZSwgZmxvYXRQcm9wKG9mZnNldCwgYXJyYXlfc2l6ZSwgbGVuZ3RoID4+IDIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiaW50XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBuYW1lLCBpbnRQcm9wKG9mZnNldCwgYXJyYXlfc2l6ZSwgbGVuZ3RoID4+IDIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwic2hvcnRcIjpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInVzaG9ydFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwgbmFtZSwgc2hvcnRQcm9wKG9mZnNldCwgYXJyYXlfc2l6ZSwgbGVuZ3RoID4+IDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiY2hhclwiOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwidWNoYXJcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIG5hbWUsIGNoYXJQcm9wKG9mZnNldCwgYXJyYXlfc2l6ZSwgbGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vY29tcGlsZSBsaXN0IHRvIFxuICAgICAgICAgICAgICAgICAgICAgICAgb2JqW25hbWVdID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICBvYmouX19saXN0X18ucHVzaChuYW1lLCB0eXBlLCBsZW5ndGgsIG9mZnNldCwgYXJyYXlfc2l6ZSwgSVNfUE9JTlRFUik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG9iai5fbGVuZ3RoICs9IGxlbmd0aDtcbiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gbGVuZ3RoO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBuYW1lLCBwb2ludGVyUHJvcChvZmZzZXQsIGFycmF5X3NpemUsIHBvaW50ZXJfc2l6ZSkpO1xuICAgICAgICAgICAgICAgIG9mZnNldCArPSBwb2ludGVyX3NpemUgKiBhcnJheV9zaXplO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gb2Zmc2V0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy9TdG9yZSBmaW5hbCBETkEgc3RydWN0c1xuICAgICAgICB2YXIgTUFTVEVSX1NETkFfU0NIRU1BID0gZnVuY3Rpb24odmVyc2lvbikge1xuICAgICAgICAgICAgdGhpcy52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIHRoaXMuU0ROQV9TRVQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuYnl0ZV9zaXplID0gMDtcbiAgICAgICAgICAgIHRoaXMuc3RydWN0X2luZGV4ID0gMDtcbiAgICAgICAgICAgIHRoaXMuc3RydWN0cyA9IHt9O1xuICAgICAgICAgICAgdGhpcy5TRE5BID0ge307XG4gICAgICAgICAgICB0aGlzLmVuZGlhbmVzcyA9IGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIE1BU1RFUl9TRE5BX1NDSEVNQS5wcm90b3R5cGUgPSB7XG4gICAgICAgICAgICBnZXRTRE5BU3RydWN0dXJlQ29uc3RydWN0b3I6IGZ1bmN0aW9uKG5hbWUsIHN0cnVjdCkge1xuICAgICAgICAgICAgICAgIGlmIChzdHJ1Y3QpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJsZW5fc3RydWN0ID0gRnVuY3Rpb24oXCJmdW5jdGlvbiBcIiArIG5hbWUgKyBcIigpe307IHJldHVybiBcIiArIG5hbWUpKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgYmxlbl9zdHJ1Y3QucHJvdG90eXBlID0gbmV3IEJMRU5ERVJfU1RSVUNUVVJFKCk7XG4gICAgICAgICAgICAgICAgICAgIGJsZW5fc3RydWN0LnByb3RvdHlwZS5ibGVuZGVyX25hbWUgPSBuYW1lO1xuICAgICAgICAgICAgICAgICAgICBibGVuX3N0cnVjdC5wcm90b3R5cGUuX19wb2ludGVycyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBibGVuX3N0cnVjdC5wcm90b3R5cGUuX19saXN0X18gPSBbXTtcblxuICAgICAgICAgICAgICAgICAgICB2YXIgb2Zmc2V0ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgLy9DcmVhdGUgcHJvcGVydGllcyBvZiBzdHJ1Y3RcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHJ1Y3QubGVuZ3RoOyBpICs9IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfbmFtZSA9IHN0cnVjdFtpXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuID0gX25hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHN0cnVjdFtpICsgMV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoID0gc3RydWN0W2kgKyAyXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJheV9sZW5ndGggPSAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoID0gbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBCbGVuZGVyX0FycmF5X0xlbmd0aCA9IDEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgU3VwYXJyYXlfbWF0Y2ggPSAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBvaW50ZXJUb0FycmF5ID0gZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgUG9pbnRlcl9NYXRjaCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgRE5BID0gdGhpcy5TRE5BW25hbWVdID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yOiBibGVuX3N0cnVjdFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgb3JpZ2luYWxfbmFtZSA9IF9uYW1lO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL21pbmkgdHlwZSBwYXJzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgobWF0Y2ggPSBfbmFtZS5tYXRjaCgvKFxcKj8pKFxcKj8pKFxcdyspKFxcWyhcXHcqKVxcXSk/KFxcWyhcXHcqKVxcXSk/LykpKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL2Jhc2UgbmFtZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9uYW1lID0gbWF0Y2hbM107XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL3BvaW50ZXIgdHlwZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaFsxXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQb2ludGVyX01hdGNoID0gMTA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJsZW5fc3RydWN0LnByb3RvdHlwZS5fX3BvaW50ZXJzLnB1c2goX25hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaFsyXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQb2ludGVyVG9BcnJheSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9hcnJheXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2hbNF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoWzZdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdXBhcnJheV9tYXRjaCA9IHBhcnNlSW50KG1hdGNoWzVdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJsZW5kZXJfQXJyYXlfTGVuZ3RoID0gcGFyc2VJbnQobWF0Y2hbN10pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQmxlbmRlcl9BcnJheV9MZW5ndGggPSBwYXJzZUludChtYXRjaFs1XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXlfbGVuZ3RoID0gQmxlbmRlcl9BcnJheV9MZW5ndGggKiBsZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoID0gYXJyYXlfbGVuZ3RoICogU3VwYXJyYXlfbWF0Y2g7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIEROQVtuXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aDogbGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzQXJyYXk6IChCbGVuZGVyX0FycmF5X0xlbmd0aCA+IDApLFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFBvaW50ZXJUb0FycmF5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGJsZW5fc3RydWN0LnByb3RvdHlwZSwgX25hbWUsIHBvaW50ZXJQcm9wMihvZmZzZXQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQgKz0gcG9pbnRlcl9zaXplO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChTdXBhcnJheV9tYXRjaCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXJyYXlfbmFtZXMgPSBuZXcgQXJyYXkoU3VwYXJyYXlfbWF0Y2gpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9jb25zdHJ1Y3Qgc3ViX2FycmF5IG9iamVjdCB0aGF0IHdpbGwgcmV0dXJuIHRoZSBjb3JyZWN0IHN0cnVjdHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IFN1cGFycmF5X21hdGNoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFycmF5X25hbWVfID0gYF9fJHtfbmFtZX1bJHtqfV1fX2A7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5X25hbWVzW2pdID0gYXJyYXlfbmFtZV87XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0ID0gY29tcGlsZVByb3AoYmxlbl9zdHJ1Y3QucHJvdG90eXBlLCBhcnJheV9uYW1lXywgdHlwZSwgb2Zmc2V0LCBCbGVuZGVyX0FycmF5X0xlbmd0aCwgUG9pbnRlcl9NYXRjaCwgcG9pbnRlcl9zaXplLCBhcnJheV9sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShibGVuX3N0cnVjdC5wcm90b3R5cGUsIF9uYW1lLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldDogKGZ1bmN0aW9uKGFycmF5X25hbWVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFycmF5ID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcnJheV9uYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJheS5wdXNoKHRoaXNbYXJyYXlfbmFtZXNbaV1dKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXJyYXk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKGFycmF5X25hbWVzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQgPSBjb21waWxlUHJvcChibGVuX3N0cnVjdC5wcm90b3R5cGUsIF9uYW1lLCB0eXBlLCBvZmZzZXQsIEJsZW5kZXJfQXJyYXlfTGVuZ3RoLCBQb2ludGVyX01hdGNoLCBwb2ludGVyX3NpemUsIGxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5TRE5BW25hbWVdLmNvbnN0cnVjdG9yO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLlNETkFbbmFtZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLlNETkFbbmFtZV0uY29uc3RydWN0b3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBCTEVOREVSX1NUUlVDVFVSRSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdGhpcy5fX2JsZW5kZXJfZmlsZV9fID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuX19saXN0X18gPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5fX3N1cGVyX2FycmF5X2xpc3RfXyA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmJsZW5kZXJfbmFtZSA9IFwiXCI7XG4gICAgICAgICAgICB0aGlzLl9fcG9pbnRlcnMgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5hZGRyZXNzID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMubGVuZ3RoID0gMDtcbiAgICAgICAgICAgIHRoaXMuX19kYXRhX2FkZHJlc3NfXyA9IDA7XG4gICAgICAgICAgICB0aGlzLmJsZW5kZXJfbmFtZSA9IFwiXCI7XG4gICAgICAgICAgICB0aGlzLl9sZW5ndGggPSAwO1xuICAgICAgICB9O1xuXG5cbiAgICAgICAgLypcbiAgICAgICAgICAgIFJldHVybnMgYSBwcmUtY29uc3RydWN0ZWQgQkxFTkRFUl9TVFJVQ1RVUkUgb3IgY3JlYXRlcyBhIG5ldyBCTEVOREVSX1NUUlVDVFVSRSB0byBtYXRjaCB0aGUgRE5BIHN0cnVjdCB0eXBlXG4gICAgICAgICovXG4gICAgICAgIHZhciBwb2ludGVyX2Z1bmN0aW9uID0gKHBvaW50ZXIpID0+ICgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBGSUxFLm1lbW9yeV9sb29rdXBbcG9pbnRlcl1cbiAgICAgICAgfTtcblxuICAgICAgICBmdW5jdGlvbiBnZXRQb2ludGVyKG9mZnNldCkge1xuICAgICAgICAgICAgdmFyIHBvaW50ZXJMb3cgPSBkYXRhLmdldFVpbnQzMihvZmZzZXQsIEJJR19FTkRJQU4pO1xuICAgICAgICAgICAgaWYgKHBvaW50ZXJfc2l6ZSA+IDQpIHtcbiAgICAgICAgICAgICAgICB2YXIgcG9pbnRlckhpZ2ggPSBkYXRhLmdldFVpbnQzMihvZmZzZXQgKyA0LCBCSUdfRU5ESUFOKTtcblxuICAgICAgICAgICAgICAgIGlmIChCSUdfRU5ESUFOKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAocG9pbnRlckxvdykgKyBcIlwiICsgcG9pbnRlckhpZ2g7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChwb2ludGVySGlnaCkgKyBcIlwiICsgcG9pbnRlckxvdztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBwb2ludGVyTG93O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgQkxFTkRFUl9TVFJVQ1RVUkUucHJvdG90eXBlID0ge1xuICAgICAgICAgICAgc2V0RGF0YTogZnVuY3Rpb24ocG9pbnRlciwgX2RhdGFfb2Zmc2V0LCBkYXRhX2Jsb2NrX2xlbmd0aCwgQkxFTkRFUl9GSUxFKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX19saXN0X18gPT0gbnVsbCkgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICAgICAgQkxFTkRFUl9GSUxFLmFkZE9iamVjdCh0aGlzKTtcblxuICAgICAgICAgICAgICAgIHRoaXMuX19ibGVuZGVyX2ZpbGVfXyA9IEJMRU5ERVJfRklMRTtcblxuICAgICAgICAgICAgICAgIHZhciBzdHJ1Y3QgPSB0aGlzLl9fbGlzdF9fLFxuICAgICAgICAgICAgICAgICAgICBqID0gMCxcbiAgICAgICAgICAgICAgICAgICAgaSA9IDAsXG4gICAgICAgICAgICAgICAgICAgIG9iaiwgbmFtZSA9IFwiXCIsXG4gICAgICAgICAgICAgICAgICAgIHR5cGUsIGxlbmd0aCwgQmxlbmRlcl9BcnJheV9MZW5ndGgsIFBvaW50ZXJfTWF0Y2gsIG9mZnNldCwgY29uc3RydWN0b3I7XG5cbiAgICAgICAgICAgICAgICB0aGlzLl9fZGF0YV9hZGRyZXNzX18gPSBfZGF0YV9vZmZzZXQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoc3RydWN0ID09PSBudWxsKSByZXR1cm4gdGhpcztcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBzdHJ1Y3QubGVuZ3RoOyBpICs9IDYpIHtcbiAgICAgICAgICAgICAgICAgICAgb2JqID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgbmFtZSA9IHN0cnVjdFtpXTtcbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHN0cnVjdFtpICsgMV07XG4gICAgICAgICAgICAgICAgICAgIEJsZW5kZXJfQXJyYXlfTGVuZ3RoID0gc3RydWN0W2kgKyA0XTtcbiAgICAgICAgICAgICAgICAgICAgUG9pbnRlcl9NYXRjaCA9IHN0cnVjdFtpICsgNV07XG4gICAgICAgICAgICAgICAgICAgIG9mZnNldCA9IHRoaXMuX19kYXRhX2FkZHJlc3NfXyArIHN0cnVjdFtpICsgM107XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKEJsZW5kZXJfQXJyYXlfTGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1tuYW1lXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaiA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaiA8IEJsZW5kZXJfQXJyYXlfTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRfU0ROQV90ZW1wbGF0ZS5nZXRTRE5BU3RydWN0dXJlQ29uc3RydWN0b3IodHlwZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IgPSBjdXJyZW50X1NETkFfdGVtcGxhdGUuZ2V0U0ROQVN0cnVjdHVyZUNvbnN0cnVjdG9yKHR5cGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW25hbWVdLnB1c2goKG5ldyBjb25zdHJ1Y3RvcigpKS5zZXREYXRhKDAsIG9mZnNldCwgb2Zmc2V0ICsgbGVuZ3RoIC8gQmxlbmRlcl9BcnJheV9MZW5ndGgsIEJMRU5ERVJfRklMRSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB0aGlzW25hbWVdLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0ICs9IGxlbmd0aCAvIEJsZW5kZXJfQXJyYXlfTGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGorKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50X1NETkFfdGVtcGxhdGUuZ2V0U0ROQVN0cnVjdHVyZUNvbnN0cnVjdG9yKHR5cGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IgPSBjdXJyZW50X1NETkFfdGVtcGxhdGUuZ2V0U0ROQVN0cnVjdHVyZUNvbnN0cnVjdG9yKHR5cGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNbbmFtZV0gPSAobmV3IGNvbnN0cnVjdG9yKCkpLnNldERhdGEoMCwgb2Zmc2V0LCBsZW5ndGggKyBvZmZzZXQsIEJMRU5ERVJfRklMRSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgdGhpc1tuYW1lXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy9icmVhayBjb25uZWN0aW9uIHRvIGNvbmZpZ3VyYXRpb24gbGlzdFxuICAgICAgICAgICAgICAgIHRoaXMuX19saXN0X18gPSBudWxsO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZ2V0IGFuYW1lKCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlkKSByZXR1cm4gdGhpcy5pZC5uYW1lLnNsaWNlKDIpO1xuICAgICAgICAgICAgICAgIGVsc2UgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBmdW5jdGlvbiB0b1N0cmluZyhidWZmZXIsIF9pbiwgX291dCkge1xuICAgICAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBuZXcgVWludDhBcnJheShidWZmZXIsIF9pbiwgX291dCAtIF9pbikpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9CZWdpbiBwYXJzaW5nIGJsZW5kZXIgX19ibGVuZGVyX2ZpbGVfX1xuICAgICAgICBmdW5jdGlvbiByZWFkRmlsZSgpIHtcbiAgICAgICAgICAgIHZhciBjb3VudCA9IDA7XG4gICAgICAgICAgICB2YXIgb2Zmc2V0MiA9IDA7XG4gICAgICAgICAgICB2YXIgcm9vdCA9IDA7XG4gICAgICAgICAgICB2YXIgaSA9IDA7XG4gICAgICAgICAgICB2YXIgZGF0YV9vZmZzZXQgPSAwO1xuICAgICAgICAgICAgdmFyIHNkbmFfaW5kZXggPSAwO1xuICAgICAgICAgICAgdmFyIGNvZGUgPSBcIlwiO1xuICAgICAgICAgICAgdmFyIGJsb2NrX2xlbmd0aCA9IDA7XG4gICAgICAgICAgICB2YXIgY3Vycl9jb3VudCA9IDA7XG4gICAgICAgICAgICB2YXIgY3Vycl9jb3VudDIgPSAwO1xuXG4gICAgICAgICAgICBGSUxFLm1lbW9yeV9sb29rdXAgPSB7fTtcbiAgICAgICAgICAgIHN0cnVjdF9uYW1lcyA9IFtdO1xuICAgICAgICAgICAgb2Zmc2V0ID0gMDtcblxuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHdlIGhhdmUgYSAuYmxlbmQgX19ibGVuZGVyX2ZpbGVfXy4gQWxsIGJsZW5kIGZpbGVzIGhhdmUgdGhlIGZpcnN0IDEyYnl0ZXNcbiAgICAgICAgICAgIC8vIHNldCB3aXRoIEJMRU5ERVItdiMjIyBpbiBVdGYtOFxuICAgICAgICAgICAgaWYgKHRvU3RyaW5nKF9kYXRhLCBvZmZzZXQsIDcpICE9PSBcIkJMRU5ERVJcIikgcmV0dXJuIGNvbnNvbGUud2FybihcIkZpbGUgc3VwcGxpZWQgaXMgbm90IGEgLmJsZW5kIGNvbXBhdGlibGUgQmxlbmRlciBmaWxlLlwiKTtcblxuICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIGdldCB0ZW1wbGV0ZSBmcm9tIHNhdmUgdmVyc2lvbi5cblxuICAgICAgICAgICAgb2Zmc2V0ICs9IDc7XG4gICAgICAgICAgICBwb2ludGVyX3NpemUgPSAoKHRvU3RyaW5nKF9kYXRhLCBvZmZzZXQrKywgb2Zmc2V0KSkgPT0gXCJfXCIpID8gNCA6IDg7XG4gICAgICAgICAgICBCSUdfRU5ESUFOID0gdG9TdHJpbmcoX2RhdGEsIG9mZnNldCsrLCBvZmZzZXQpICE9PSBcIlZcIjtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gdG9TdHJpbmcoX2RhdGEsIG9mZnNldCwgb2Zmc2V0ICsgMyk7XG5cblxuICAgICAgICAgICAgLy9jcmVhdGUgbmV3IG1hc3RlciB0ZW1wbGF0ZSBpZiBub25lIGV4aXN0IGZvciBjdXJyZW50IGJsZW5kZXIgdmVyc2lvbjtcbiAgICAgICAgICAgIGlmICghdGVtcGxhdGVzW3ZlcnNpb25dKSB7XG4gICAgICAgICAgICAgICAgdGVtcGxhdGVzW3ZlcnNpb25dID0gbmV3IE1BU1RFUl9TRE5BX1NDSEVNQSh2ZXJzaW9uKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY3VycmVudF9TRE5BX3RlbXBsYXRlID0gdGVtcGxhdGVzW3ZlcnNpb25dO1xuXG4gICAgICAgICAgICBGSUxFLnRlbXBsYXRlID0gY3VycmVudF9TRE5BX3RlbXBsYXRlO1xuXG4gICAgICAgICAgICBvZmZzZXQgKz0gMztcblxuICAgICAgICAgICAgLy9TZXQgU0ROQSBzdHJ1Y3RzIGlmIHRlbXBsYXRlIGhhc24ndCBiZWVuIHNldC5cbiAgICAgICAgICAgIC8vVG9kbzogTW92ZSB0aGUgZm9sbG93aW5nIGJsb2NrIGludG8gdGhlIE1BU1RFUl9TRE5BX1NDSEVNQSBvYmplY3QuXG4gICAgICAgICAgICAvLypMaWtlIHNvOiovIGN1cnJlbnRfU0ROQV90ZW1wbGF0ZS5zZXQoQUIpO1xuXG4gICAgICAgICAgICBpZiAoIWN1cnJlbnRfU0ROQV90ZW1wbGF0ZS5TRE5BX1NFVCkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRfU0ROQV90ZW1wbGF0ZS5lbmRpYW5lc3MgPSBCSUdfRU5ESUFOO1xuICAgICAgICAgICAgICAgIGN1cnJlbnRfU0ROQV90ZW1wbGF0ZS5wb2ludGVyX3NpemUgPSBwb2ludGVyX3NpemU7XG4gICAgICAgICAgICAgICAgLy9maW5kIEROQTEgZGF0YSBibG9ja1xuICAgICAgICAgICAgICAgIG9mZnNldDIgPSBvZmZzZXQ7XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICBzZG5hX2luZGV4ID0gZGF0YS5nZXRJbnQzMihvZmZzZXQyICsgcG9pbnRlcl9zaXplICsgOCwgQklHX0VORElBTik7XG4gICAgICAgICAgICAgICAgICAgIGNvZGUgPSB0b1N0cmluZyhfZGF0YSwgb2Zmc2V0Miwgb2Zmc2V0MiArIDQpLnJlcGxhY2UoL1xcdTAwMDAvZywgXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIGJsb2NrX2xlbmd0aCA9IGRhdGEuZ2V0SW50MzIob2Zmc2V0MiArIDQsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBvZmZzZXQyICs9IDE2ICsgKHBvaW50ZXJfc2l6ZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb2RlID09PSBcIkROQTFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRE5BIGZvdW5kOyBUaGlzIGlzIHRoZSBjb3JlIG9mIHRoZSBfX2JsZW5kZXJfZmlsZV9fIGFuZCBjb250YWlucyBhbGwgdGhlIHN0cnVjdHVyZSBmb3IgdGhlIHZhcmlvdXMgZGF0YSB0eXBlcyB1c2VkIGluIEJsZW5kZXIuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHlwZXMgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHMgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lcyA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aHMgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gXCJcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyX25hbWUgPSBcIlwiO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL3NraXAgU0ROQSBhbmQgTkFNRSBpZGVudGlmaWVyc1xuICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0MiArPSA4O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL051bWJlciBvZiBzdHJ1Y3RzLlxuICAgICAgICAgICAgICAgICAgICAgICAgY291bnQgPSBkYXRhLmdldEludDMyKG9mZnNldDIsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0MiArPSA0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyX2NvdW50ID0gMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy9CdWlsZCB1cCBsaXN0IG9mIG5hbWVzIGZvciBzdHJ1Y3RzXG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoY3Vycl9jb3VudCA8IGNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3Vycl9uYW1lID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoZGF0YS5nZXRJbnQ4KG9mZnNldDIpICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJfbmFtZSArPSB0b1N0cmluZyhfZGF0YSwgb2Zmc2V0Miwgb2Zmc2V0MiArIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQyKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzLnB1c2goY3Vycl9uYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQyKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3Vycl9jb3VudCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vQWRqdXN0IGZvciA0Ynl0ZSBhbGlnbm1lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgob2Zmc2V0MiAlIDQpID4gMCkgb2Zmc2V0MiA9ICg0IC0gKG9mZnNldDIgJSA0KSkgKyBvZmZzZXQyO1xuICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0MiArPSA0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL051bWJlciBvZiBzdHJ1Y3QgdHlwZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ID0gZGF0YS5nZXRJbnQzMihvZmZzZXQyLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldDIgKz0gNDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJfY291bnQgPSAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL0J1aWxkIHVwIGxpc3Qgb2YgdHlwZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChjdXJyX2NvdW50IDwgY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyX25hbWUgPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChkYXRhLmdldEludDgob2Zmc2V0MikgIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3Vycl9uYW1lICs9IHRvU3RyaW5nKF9kYXRhLCBvZmZzZXQyLCBvZmZzZXQyICsgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldDIrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZXMucHVzaChjdXJyX25hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldDIrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyX2NvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vQWRqdXN0IGZvciA0Ynl0ZSBhbGlnbm1lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgob2Zmc2V0MiAlIDQpID4gMCkgb2Zmc2V0MiA9ICg0IC0gKG9mZnNldDIgJSA0KSkgKyBvZmZzZXQyO1xuICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0MiArPSA0O1xuICAgICAgICAgICAgICAgICAgICAgICAgY3Vycl9jb3VudCA9IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vQnVpbGQgdXAgbGlzdCBvZiBieXRlIGxlbmd0aHMgZm9yIHR5cGVzXG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoY3Vycl9jb3VudCA8IGNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3Rocy5wdXNoKGRhdGEuZ2V0SW50MTYob2Zmc2V0MiwgQklHX0VORElBTikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldDIgKz0gMjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyX2NvdW50Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vQWRqdXN0IGZvciA0Ynl0ZSBhbGlnbm1lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgob2Zmc2V0MiAlIDQpID4gMCkgb2Zmc2V0MiA9ICg0IC0gKG9mZnNldDIgJSA0KSkgKyBvZmZzZXQyO1xuICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0MiArPSA0O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL051bWJlciBvZiBzdHJ1Y3R1cmVzXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgc3RydWN0dXJlX2NvdW50ID0gZGF0YS5nZXRJbnQzMihvZmZzZXQyLCBCSUdfRU5ESUFOKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldDIgKz0gNDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJfY291bnQgPSAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL0NyZWF0ZSBjb25zdHJ1Y3RvciBvYmplY3RzIGZyb20gbGlzdCBvZiBTRE5BIHN0cnVjdHNcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChjdXJyX2NvdW50IDwgc3RydWN0dXJlX2NvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHN0cnVjdF9uYW1lID0gdHlwZXNbZGF0YS5nZXRJbnQxNihvZmZzZXQyLCBCSUdfRU5ESUFOKV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0MiArPSAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9iaiA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ID0gZGF0YS5nZXRJbnQxNihvZmZzZXQyLCBCSUdfRU5ESUFOKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQyICs9IDI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3Vycl9jb3VudDIgPSAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdF9uYW1lcy5wdXNoKHN0cnVjdF9uYW1lKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vRmlsbCBhbiBhcnJheSB3aXRoIG5hbWUsIHR5cGUsIGFuZCBsZW5ndGggZm9yIGVhY2ggU0ROQSBzdHJ1Y3QgcHJvcGVydHlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoY3Vycl9jb3VudDIgPCBjb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYmoucHVzaChuYW1lc1tkYXRhLmdldEludDE2KG9mZnNldDIgKyAyLCBCSUdfRU5ESUFOKV0sIHR5cGVzW2RhdGEuZ2V0SW50MTYob2Zmc2V0MiwgQklHX0VORElBTildLCBsZW5ndGhzW2RhdGEuZ2V0SW50MTYob2Zmc2V0MiwgQklHX0VORElBTildKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0MiArPSA0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyX2NvdW50MisrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vQ3JlYXRlIGEgU0ROQSBjb25zdHJ1Y3RvciBieSBwYXNzaW5nIFt0eXBlLG5hbWUsbGVudGhdIGFycmF5IGFzIHNlY29uZCBhcmd1bWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRfU0ROQV90ZW1wbGF0ZS5nZXRTRE5BU3RydWN0dXJlQ29uc3RydWN0b3Ioc3RydWN0X25hbWUsIG9iaik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY3Vycl9jb3VudCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudF9TRE5BX3RlbXBsYXRlLlNETkFfU0VUID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRfU0ROQV90ZW1wbGF0ZS5TRE5BX05BTUVTID0gc3RydWN0X25hbWVzO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0MiArPSBibG9ja19sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvL3BhcnNlIHRoZSByZXN0IG9mIHRoZSBkYXRhLCBzdGFydGluZyBiYWNrIGF0IHRoZSB0b3AuXG4gICAgICAgICAgICAvL1RPRE86IHR1cm4gaW50byBcIm9uLWRlbWFuZFwiIHBhcnNpbmcuXG5cbiAgICAgICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKChvZmZzZXQgJSA0KSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0ID0gKDQgLSAob2Zmc2V0ICUgNCkpICsgb2Zmc2V0O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRhdGFfb2Zmc2V0ID0gb2Zmc2V0O1xuICAgICAgICAgICAgICAgIHNkbmFfaW5kZXggPSBkYXRhLmdldEludDMyKG9mZnNldCArIHBvaW50ZXJfc2l6ZSArIDgsIEJJR19FTkRJQU4pO1xuICAgICAgICAgICAgICAgIGxldCBjb2RlX3VpbnQgPSBkYXRhLmdldFVpbnQzMihvZmZzZXQsIEJJR19FTkRJQU4pO1xuICAgICAgICAgICAgICAgIG9mZnNldDIgPSBvZmZzZXQgKyAxNiArIChwb2ludGVyX3NpemUpO1xuICAgICAgICAgICAgICAgIG9mZnNldCArPSBkYXRhLmdldEludDMyKG9mZnNldCArIDQsIHRydWUpICsgMTYgKyAocG9pbnRlcl9zaXplKTtcblxuICAgICAgICAgICAgICAgIGlmIChjb2RlX3VpbnQgPT09IEROQTEpOyAvL3NraXAgLSBhbHJlYWR5IHByb2Nlc3NlZCBhdCB0aGlzIHBvaW50ICAgIFxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGNvZGVfdWludCA9PT0gRU5EQikgYnJlYWs7IC8vZW5kIG9mIF9fYmxlbmRlcl9maWxlX18gZm91bmRcbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy9DcmVhdGUgYSBCbGVuZGVyIG9iamVjdCB1c2luZyBhIGNvbnN0cnVjdG9yIHRlbXBsYXRlIGZyb20gY3VycmVudF9TRE5BX3RlbXBsYXRlXG4gICAgICAgICAgICAgICAgICAgIHZhciBkYXRhX3N0YXJ0ID0gZGF0YV9vZmZzZXQgKyBwb2ludGVyX3NpemUgKyAxNjtcblxuICAgICAgICAgICAgICAgICAgICAvL0dldCBhIFNETkEgY29uc3RydWN0b3IgYnkgbmFtZTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbnN0cnVjdG9yID0gY3VycmVudF9TRE5BX3RlbXBsYXRlLmdldFNETkFTdHJ1Y3R1cmVDb25zdHJ1Y3RvcihjdXJyZW50X1NETkFfdGVtcGxhdGUuU0ROQV9OQU1FU1tzZG5hX2luZGV4XSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHNpemUgPSBkYXRhLmdldEludDMyKGRhdGFfb2Zmc2V0ICsgNCwgQklHX0VORElBTik7XG5cbiAgICAgICAgICAgICAgICAgICAgY291bnQgPSBkYXRhLmdldEludDMyKGRhdGFfb2Zmc2V0ICsgMTIgKyBwb2ludGVyX3NpemUsIEJJR19FTkRJQU4pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb3VudCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmogPSBuZXcgY29uc3RydWN0b3IoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNvbnN0cnVjdG9yLnByb3RvdHlwZS5fbGVuZ3RoO1xuXG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhZGRyZXNzID0gRklMRS5nZXRQb2ludGVyKGRhdGFfb2Zmc2V0ICsgOCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIG9iai5hZGRyZXNzID0gYWRkcmVzcyArIFwiXCI7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIG9iai5zZXREYXRhKGFkZHJlc3MsIGRhdGFfc3RhcnQsIGRhdGFfc3RhcnQgKyBzaXplLCBGSUxFKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvdW50ID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBhcnJheSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5LnB1c2gob2JqKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciB1ID0gMTsgdSA8IGNvdW50OyB1KyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JqID0gbmV3IGNvbnN0cnVjdG9yKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9iai5zZXREYXRhKGFkZHJlc3MsIGRhdGFfc3RhcnQgKyBsZW5ndGggKiB1LCBkYXRhX3N0YXJ0ICsgKGxlbmd0aCAqIHUpICsgbGVuZ3RoLCBGSUxFKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJyYXkucHVzaChvYmopO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBGSUxFLm1lbW9yeV9sb29rdXBbYWRkcmVzc10gPSBhcnJheTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgRklMRS5tZW1vcnlfbG9va3VwW2FkZHJlc3NdID0gb2JqO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXR1cm5fb2JqZWN0O1xufSk7IiwiLypqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXHJcblxyXG5jb25zdCBjcmVhdGVNYXRlcmlhbCA9IHJlcXVpcmUoXCIuL21hdGVyaWFsLmpzXCIpO1xyXG5jb25zdCBjcmVhdGVUZXh0dXJlID0gcmVxdWlyZShcIi4vdGV4dHVyZS5qc1wiKTtcclxuY29uc3QgY3JlYXRlTWVzaCA9IHJlcXVpcmUoXCIuL21lc2guanNcIik7XHJcbmNvbnN0IGNyZWF0ZUxpZ2h0ID0gcmVxdWlyZShcIi4vbGlnaHQuanNcIik7XHJcblxyXG5mdW5jdGlvbiBsb2FkTW9kZWwodGhyZWVfc2NlbmUsIG1vZGVsX25hbWUsIGJsZW5kZXJfZmlsZSwgY2FjaGUpIHtcclxuXHR2YXIgbWF0cyA9IGJsZW5kZXJfbWVzaC5tYXQsXHJcblx0XHRtYXRlcmlhbHMgPSBbXTtcclxuXHRmb3IgKHZhciBpID0gMDsgaSA8IG1hdHMubGVuZ3RoOyBpKyspIHtcclxuXHRcdHZhciBtYXRlcmlhbCA9IGNyZWF0ZVRocmVlSlNNYXRlcmlhbChtYXRzW2ldKTtcclxuXHRcdG1hdGVyaWFscy5wdXNoKG1hdGVyaWFsKTtcclxuXHR9XHJcbn1cclxuXHJcbnZhciBibGVuZGVyX3R5cGVzID0ge1xyXG5cdG1lc2hfb2JqZWN0OiAxLFxyXG5cdGxhbXA6IDEwXHJcbn07XHJcblxyXG5mdW5jdGlvbiBsb2FkU2NlbmUodGhyZWVfc2NlbmUsIGJsZW5kZXJfZmlsZSwgY2FjaGUpIHtcclxuXHQvL2J1aWxkIG9iamVjdCBmcm9tIGJsZW5kZXIgbWVzaCBvYmplY3RcclxuXHRmb3IgKGxldCBpID0gMDsgaSA8IGJsZW5kZXJfZmlsZS5vYmplY3RzLk9iamVjdC5sZW5ndGg7IGkrKykge1xyXG5cclxuXHRcdGxldCBvYmogPSBibGVuZGVyX2ZpbGUub2JqZWN0cy5PYmplY3RbaV07XHJcblxyXG5cdFx0Ly9Mb2FkIExpZ2h0c1xyXG5cclxuXHRcdGlmIChvYmoudHlwZSA9PSBibGVuZGVyX3R5cGVzLmxhbXApIHtcclxuXHJcblx0XHRcdGxldCBsaWdodCA9IGNyZWF0ZUxpZ2h0KG9iaiwgYmxlbmRlcl9maWxlKTtcclxuXHJcblx0XHRcdHRocmVlX3NjZW5lLmFkZChsaWdodCk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly9Mb2FkIE1lc2hlc1xyXG5cclxuXHRcdGlmIChvYmoudHlwZSA9PSBibGVuZGVyX3R5cGVzLm1lc2hfb2JqZWN0KSB7XHJcblx0XHRcdGlmIChvYmouZGF0YSkge1xyXG5cdFx0XHRcdC8vZ2V0IHRoZSBtZXNoIFxyXG5cdFx0XHRcdHZhciBidWZmZXJlZF9nZW9tZXRyeSA9IGNyZWF0ZU1lc2gob2JqLmRhdGEsIFswLCAwLCAwXSk7XHJcblx0XHRcdFx0XHRcclxuXHRcdFx0XHR2YXIgYmxlbmRfbWF0ZXJpYWwgPSBvYmouZGF0YS5tYXRbMF07XHJcblx0XHRcdFx0XHJcblx0XHRcdFx0aWYoYmxlbmRfbWF0ZXJpYWwpe1xyXG5cdFx0XHRcdFx0dmFyIG1hdGVyaWFsID0gY3JlYXRlTWF0ZXJpYWwoYmxlbmRfbWF0ZXJpYWwpO1xyXG5cdFx0XHRcdH1lbHNle1xyXG5cdFx0XHRcdFx0Ly9jcmVhdGUgZ2VuZXJpYyBtYXRlcmlhbFxyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0Ly92YXIgZ2VvbWV0cnkgPSBjcmVhdGVUaHJlZUpTR2VvbWV0cnkob2JqLmRhdGEsIFswLCAwLCAwXSk7XHJcblx0XHRcdFx0Ly8vKlxyXG5cdFx0XHRcdC8vY3JlYXRlIGEgdHJhbnNmb3JtIGZyb20gdGhlIG1lc2ggb2JqZWN0XHJcblx0XHRcdFx0dmFyIG1lc2ggPSBuZXcgVEhSRUUuTWVzaChidWZmZXJlZF9nZW9tZXRyeSwgbWF0ZXJpYWwpO1xyXG5cclxuXHRcdFx0XHRtZXNoLmNhc3RTaGFkb3cgPSB0cnVlO1xyXG5cdFx0XHRcdG1lc2gucmVjZWl2ZVNoYWRvdyA9IHRydWU7XHJcblxyXG5cdFx0XHRcdHRocmVlX3NjZW5lLmFkZChtZXNoKTtcclxuXHJcblx0XHRcdFx0bWVzaC5yb3RhdGVaKG9iai5yb3RbMl0pO1xyXG5cdFx0XHRcdG1lc2gucm90YXRlWShvYmoucm90WzFdKTtcclxuXHRcdFx0XHRtZXNoLnJvdGF0ZVgob2JqLnJvdFswXSk7XHJcblx0XHRcdFx0bWVzaC5zY2FsZS5mcm9tQXJyYXkob2JqLnNpemUsIDApO1xyXG5cdFx0XHRcdG1lc2gucG9zaXRpb24uZnJvbUFycmF5KFtvYmoubG9jWzBdLCAob2JqLmxvY1syXSksICgtb2JqLmxvY1sxXSldLCAwKTtcclxuXHRcdFx0XHQvLyovXHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcbn1cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gKGJsZW5kZXJfZmlsZSkgPT4ge1xyXG5cclxuXHRpZiAoIVRIUkVFKSB7XHJcblx0XHRjb25zb2xlLndhcm4oXCJObyBUaHJlZUpTIG9iamVjdCBkZXRlY3RlZFwiKTtcclxuXHRcdHJldHVybiB7fTtcclxuXHR9XHJcblxyXG5cdHZhciBjYWNoZSA9IHt9O1xyXG5cclxuXHRyZXR1cm4ge1xyXG5cdFx0bG9hZFNjZW5lOiAodGhyZWVfc2NlbmUpID0+IGxvYWRTY2VuZSh0aHJlZV9zY2VuZSwgYmxlbmRlcl9maWxlLCBjYWNoZSksXHJcblx0XHRsb2FkTW9kZWw6IChtb2RlbF9uYW1lKSA9PiBsb2FkTW9kZWwobW9kZWxfbmFtZSwgYmxlbmRlcl9maWxlLCBjYWNoZSlcclxuXHR9O1xyXG59OyIsIi8qanNoaW50IGVzdmVyc2lvbjogNiAqL1xyXG5cclxudmFyIGJsZW5kZXJfbGlnaHRfdHlwZXMgPSB7XHJcblx0cG9pbnQ6IDAsXHJcblx0c3VuOiAxLFxyXG5cdHNwb3Q6IDAsXHJcblx0aGVtaTogMCxcclxuXHRhcmVhOiAwXHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGNyZWF0ZVRocmVlSlNMYW1wKGJsZW5kX2xhbXApIHtcclxuXHJcblx0bGV0IGxkYXRhID0gYmxlbmRfbGFtcC5kYXRhO1xyXG5cclxuXHRsZXQgcG9zX2FycmF5ID0gW2JsZW5kX2xhbXAubG9jWzBdLCBibGVuZF9sYW1wLmxvY1syXSwgLWJsZW5kX2xhbXAubG9jWzFdXTtcclxuXHJcblx0bGV0IGNvbG9yID0gKChsZGF0YS5yICogMjU1KSA8PCAxNikgfCAoKGxkYXRhLmcgKiAyNTUpIDw8IDgpIHwgKChsZGF0YS5iICogMjU1KSA8PCAwKTtcclxuXHRsZXQgaW50ZXNpdHkgPSBsZGF0YS5lbmVyZ3k7XHJcblx0bGV0IGRpc3RhbmNlID0gMDtcclxuXHJcblx0dmFyIHRocmVlX2xpZ2h0ID0gbnVsbDtcclxuXHJcblx0c3dpdGNoIChsZGF0YS50eXBlKSB7XHJcblx0XHRjYXNlIGJsZW5kZXJfbGlnaHRfdHlwZXMucG9pbnQ6XHJcblx0XHRcdHZhciB0aHJlZV9saWdodCA9IG5ldyBUSFJFRS5Qb2ludExpZ2h0KGNvbG9yLCBpbnRlc2l0eSwgZGlzdGFuY2UpO1xyXG5cdFx0XHR0aHJlZV9saWdodC5wb3NpdGlvbi5mcm9tQXJyYXkocG9zX2FycmF5LCAwKTtcclxuXHRcdFx0dGhyZWVfbGlnaHQuY2FzdFNoYWRvdyA9IHRydWU7XHJcblx0XHRcdGJyZWFrO1xyXG5cdFx0Y2FzZSBibGVuZGVyX2xpZ2h0X3R5cGVzLnN1bjpcclxuXHRcdFx0dmFyIHRocmVlX2xpZ2h0ID0gbmV3IFRIUkVFLlBvaW50TGlnaHQoY29sb3IsIGludGVzaXR5LCBkaXN0YW5jZSk7XHJcblx0XHRcdHRocmVlX2xpZ2h0LnBvc2l0aW9uLmZyb21BcnJheShwb3NfYXJyYXksIDApO1xyXG5cdFx0XHR0aHJlZV9saWdodC5jYXN0U2hhZG93ID0gdHJ1ZTtcclxuXHRcdFx0dGhyZWVfbGlnaHQuc2hhZG93Lm1hcFNpemUud2lkdGggPSAxMDI0O1xyXG5cdFx0XHR0aHJlZV9saWdodC5zaGFkb3cubWFwU2l6ZS5oZWlnaHQgPSAxMDI0O1xyXG5cdFx0XHR0aHJlZV9saWdodC5zaGFkb3cuY2FtZXJhLm5lYXIgPSAwLjAxO1xyXG5cdFx0XHR0aHJlZV9saWdodC5zaGFkb3cuY2FtZXJhLmZhciA9IDUwMDtcclxuXHRcdFx0YnJlYWs7XHJcblx0fVxyXG5cclxuXHRyZXR1cm4gdGhyZWVfbGlnaHQ7XHJcbn0iLCIvKmpzaGludCBlc3ZlcnNpb246IDYgKi9cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gKCgpID0+IHtcclxuICAgIGNvbnN0IGNyZWF0ZVRleHR1cmUgPSByZXF1aXJlKFwiLi90ZXh0dXJlLmpzXCIpO1xyXG5cclxuICAgIHZhciB0ZXh0dXJlX21hcHBpbmdzID0ge1xyXG4gICAgICAgIGRpZmZfY29sb3I6IDEsXHJcbiAgICAgICAgbm9ybWFsOiAyLFxyXG4gICAgICAgIG1pcnJvcjogOCxcclxuICAgICAgICBkaWZmX2ludGVuc2l0eTogMTYsXHJcbiAgICAgICAgc3BlY19pbnRlbnNpdHk6IDMyLFxyXG4gICAgICAgIGVtaXQ6IDMyLFxyXG4gICAgICAgIGFscGhhOiAxMjgsXHJcbiAgICAgICAgc3BlY19oYXJkbmVzczogMjU2LFxyXG4gICAgICAgIHJheV9taXJyb3I6IDUxMixcclxuICAgICAgICB0cmFuc2x1Y2VuY3k6IDEwMjQsXHJcbiAgICAgICAgYW1iaWVudDogMjA0OCxcclxuICAgICAgICBkaXNwbGFjZW1lbnQ6IDQwOTYsXHJcbiAgICAgICAgd2FycDogODE5MlxyXG4gICAgfTtcclxuXHJcbiAgICBsZXQgYmxlbmRlcl9zcGVjdWxhcl90eXBlcyA9IHtcclxuICAgICAgICBjb29rdG9ycjogMCxcclxuICAgICAgICBwaG9uZzogMSxcclxuICAgICAgICBibGlubjogMixcclxuICAgICAgICB0b29uOiAzLFxyXG4gICAgICAgIHdhcmRpc286IDRcclxuICAgIH07XHJcblxyXG4gICAgZnVuY3Rpb24gYXBwbHlDb2xvck1hcHBpbmcoYmxlbmRlcl90ZXh0dXJlLCB0aHJlZV90ZXh0dXJlLCBtYXRlcmlhbCkge1xyXG4gICAgICAgIGlmIChibGVuZGVyX3RleHR1cmUubWFwdG8gJiB0ZXh0dXJlX21hcHBpbmdzLmRpZmZfY29sb3IpIHtcclxuICAgICAgICAgICAgbWF0ZXJpYWwubWFwID0gdGhyZWVfdGV4dHVyZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgZnVuY3Rpb24gYXBwbHlTcGVjTWFwcGluZyhibGVuZGVyX3RleHR1cmUsIHRocmVlX3RleHR1cmUsIG1hdGVyaWFsKSB7XHJcbiAgICAgICAgaWYgKGJsZW5kZXJfdGV4dHVyZS5tYXB0byAmIHRleHR1cmVfbWFwcGluZ3Muc3BlY19jb2xvciAmJiBtYXRlcmlhbC50eXBlICE9IFwiTWVzaFN0YW5kYXJkTWF0ZXJpYWxcIikge1xyXG4gICAgICAgICAgICBtYXRlcmlhbC5zcGVjdWxhck1hcCA9IHRocmVlX3RleHR1cmU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoYmxlbmRlcl90ZXh0dXJlLm1hcHRvICYgdGV4dHVyZV9tYXBwaW5ncy5zcGVjX2ludGVuc2l0eSAmJiBtYXRlcmlhbC50eXBlICE9IFwiTWVzaFN0YW5kYXJkTWF0ZXJpYWxcIikge1xyXG4gICAgICAgICAgICBtYXRlcmlhbC5yb3VnaG5lc3NNYXAgPSB0aHJlZV90ZXh0dXJlO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiBhcHBseUFscGhhTWFwcGluZyhibGVuZGVyX3RleHR1cmUsIHRocmVlX3RleHR1cmUsIG1hdGVyaWFsKSB7XHJcbiAgICAgICAgaWYgKGJsZW5kZXJfdGV4dHVyZS5tYXB0byAmIHRleHR1cmVfbWFwcGluZ3MuYWxwaGEpIHtcclxuICAgICAgICAgICAgbWF0ZXJpYWwuYWxwaGFNYXAgPSB0aHJlZV90ZXh0dXJlO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiBhcHBseU5vcm1hbE1hcHBpbmcoYmxlbmRlcl90ZXh0dXJlLCB0aHJlZV90ZXh0dXJlLCBtYXRlcmlhbCkge1xyXG4gICAgICAgIGlmIChibGVuZGVyX3RleHR1cmUubWFwdG8gJiB0ZXh0dXJlX21hcHBpbmdzLm5vcm1hbCkge1xyXG4gICAgICAgICAgICBtYXRlcmlhbC5ub3JtYWxNYXAgPSB0aHJlZV90ZXh0dXJlO1xyXG4gICAgICAgICAgICBtYXRlcmlhbC5ub3JtYWxTY2FsZSA9IHtcclxuICAgICAgICAgICAgICAgIHg6IGJsZW5kZXJfdGV4dHVyZS5ub3JmYWMsXHJcbiAgICAgICAgICAgICAgICB5OiBibGVuZGVyX3RleHR1cmUubm9yZmFjXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGZ1bmN0aW9uIGFwcGx5TWlycm9yTWFwcGluZyhibGVuZGVyX3RleHR1cmUsIHRocmVlX3RleHR1cmUsIG1hdGVyaWFsKSB7XHJcbiAgICAgICAgaWYgKGJsZW5kZXJfdGV4dHVyZS5tYXB0byAmIHRleHR1cmVfbWFwcGluZ3MubWlycm9yKSB7XHJcbiAgICAgICAgICAgIG1hdGVyaWFsLmVudk1hcCA9IHRocmVlX3RleHR1cmU7XHJcbiAgICAgICAgICAgIG1hdGVyaWFsLmVudk1hcEludGVuc2l0eSA9IGJsZW5kZXJfdGV4dHVyZS5taXJyZmFjO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB2YXIgYmxlbmRlcl90ZXh0dXJlX2Nvb3JkaW5hdGVzID0ge1xyXG4gICAgICAgIEdFTkVSQVRFRCA6IDEsXHJcbiAgICAgICAgUkVGTEVDVElPTiA6IDIsXHJcbiAgICAgICAgTk9STUFMOjQsXHJcbiAgICAgICAgR0xPQkFMIDogOCxcclxuICAgICAgICBVViA6IDE2LFxyXG4gICAgICAgIE9CSkVDVCA6IDMyLFxyXG4gICAgICAgIFdJTkRPVzogMTAyNCxcclxuICAgICAgICBUQU5HRU5UOjQwOTYsXHJcbiAgICAgICAgUEFSVElDTEU6IDgxOTIsXHJcbiAgICAgICAgU1RSRVNTOjE2Mzg0XHJcbiAgICB9XHJcblxyXG4gICAgdmFyIGJsZW5kZXJfdGV4dHVyZV9tYXBwaW5nID0ge1xyXG4gICAgICAgIEZMQVQgOiAwLFxyXG4gICAgICAgIENVQkUgOiAxLFxyXG4gICAgICAgIFRVQkUgOiAyLFxyXG4gICAgICAgIFNQSEVSRSA6IDNcclxuICAgIH1cclxuXHJcbiAgICBmdW5jdGlvbiBhcHBseVRleHR1cmUoYmxlbmRlcl90ZXh0dXJlLCBtYXRlcmlhbCkge1xyXG4gICAgICAgIC8vZXh0cmFjdCBibGVuZGVyX3RleHR1cmUgZGF0YS4gVXNlIE9ubHkgaWYgaW1hZ2UgaGFzIGJlZW4gc3VwcGxpZWQuXHJcbiAgICAgICAgaWYgKGJsZW5kZXJfdGV4dHVyZSAmJiBibGVuZGVyX3RleHR1cmUudGV4ICYmIGJsZW5kZXJfdGV4dHVyZS50ZXguaW1hKSB7XHJcblxyXG4gICAgICAgICAgICBsZXQgdGhyZWVfdGV4dHVyZSA9IGNyZWF0ZVRleHR1cmUoYmxlbmRlcl90ZXh0dXJlLnRleC5pbWEpO1xyXG5cclxuICAgICAgICAgICAgaWYoYmxlbmRlcl90ZXh0dXJlLnRleGNvID09IGJsZW5kZXJfdGV4dHVyZV9jb29yZGluYXRlcy5SRUZMRUNUSU9OKXtcclxuICAgICAgICAgICAgICAgIHN3aXRjaChibGVuZGVyX3RleHR1cmUubWFwcGluZyl7XHJcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBibGVuZGVyX3RleHR1cmVfbWFwcGluZy5GTEFUOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJlZV90ZXh0dXJlLm1hcHBpbmcgPSBUSFJFRS5FcXVpcmVjdGFuZ3VsYXJSZWZsZWN0aW9uTWFwcGluZztcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICBjYXNlIGJsZW5kZXJfdGV4dHVyZV9tYXBwaW5nLlNQSEVSRTpcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyZWVfdGV4dHVyZS5tYXBwaW5nID0gVEhSRUUuU3BoZXJpY2FsUmVmbGVjdGlvbk1hcHBpbmc7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgLy90aHJlZV90ZXh0dXJlLm1hcHBpbmcgPSBUSFJFRS5FcXVpcmVjdGFuZ3VsYXJSZWZyYWN0aW9uTWFwcGluZztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgYXBwbHlDb2xvck1hcHBpbmcoYmxlbmRlcl90ZXh0dXJlLCB0aHJlZV90ZXh0dXJlLCBtYXRlcmlhbCk7XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBhcHBseVNwZWNNYXBwaW5nKGJsZW5kZXJfdGV4dHVyZSwgdGhyZWVfdGV4dHVyZSwgbWF0ZXJpYWwpO1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgYXBwbHlBbHBoYU1hcHBpbmcoYmxlbmRlcl90ZXh0dXJlLCB0aHJlZV90ZXh0dXJlLCBtYXRlcmlhbCk7XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBhcHBseU5vcm1hbE1hcHBpbmcoYmxlbmRlcl90ZXh0dXJlLCB0aHJlZV90ZXh0dXJlLCBtYXRlcmlhbCk7XHJcblxyXG4gICAgICAgICAgICBhcHBseU1pcnJvck1hcHBpbmcoYmxlbmRlcl90ZXh0dXJlLCB0aHJlZV90ZXh0dXJlLCBtYXRlcmlhbCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBmdW5jdGlvbiBjcmVhdGVUaHJlZUpTTWF0ZXJpYWwoYmxlbmRfbWF0KSB7XHJcblxyXG4gICAgICAgIHZhciBtYXRlcmlhbCA9IG51bGw7XHJcblxyXG4gICAgICAgIHZhciB0ZXh0dXJlcyA9IGJsZW5kX21hdC5tdGV4O1xyXG5cclxuICAgICAgICBzd2l0Y2ggKGJsZW5kX21hdC5zcGVjX3NoYWRlcikge1xyXG4gICAgICAgICAgICBjYXNlIGJsZW5kZXJfc3BlY3VsYXJfdHlwZXMubGFtYmVydDpcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsID0gbmV3IFRIUkVFLk1lc2hMYW1iZXJ0TWF0ZXJpYWwoKTtcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsLmNvbG9yLnNldFJHQihibGVuZF9tYXQuciwgYmxlbmRfbWF0LmcsIGJsZW5kX21hdC5iKTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIGJsZW5kZXJfc3BlY3VsYXJfdHlwZXMuYmxpbm46XHJcbiAgICAgICAgICAgIGNhc2UgYmxlbmRlcl9zcGVjdWxhcl90eXBlcy5waG9uZzpcclxuXHJcbiAgICAgICAgICAgICAgICBtYXRlcmlhbCA9IG5ldyBUSFJFRS5NZXNoU3RhbmRhcmRNYXRlcmlhbCgpO1xyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwuY29sb3Iuc2V0UkdCKGJsZW5kX21hdC5yLCBibGVuZF9tYXQuZywgYmxlbmRfbWF0LmIpO1xyXG4gICAgICAgICAgICAgICAgLy9tYXRlcmlhbC5zcGVjdWxhci5zZXRSR0IoYmxlbmRfbWF0LnNwZWNyLCBibGVuZF9tYXQuc3BlY2csIGJsZW5kX21hdC5zcGVjYik7XHJcbiAgICAgICAgICAgICAgICBtYXRlcmlhbC5yb3VnaG5lc3MgPSAoMSAtIChibGVuZF9tYXQuaGFyIC8gNTEyKSk7XHJcbiAgICAgICAgICAgICAgICBtYXRlcmlhbC5tZXRhbG5lc3MgPSAxIC0gYmxlbmRfbWF0LnJlZjtcclxuICAgICAgICAgICAgICAgIGlmKGJsZW5kX21hdC5hbHBoYSA8IDAuOTgpe1xyXG4gICAgICAgICAgICAgICAgICAgIG1hdGVyaWFsLnRyYW5zcGFyZW50ID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICBtYXRlcmlhbC5vcGFjaXR5ID0gYmxlbmRfbWF0LmFscGhhO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGJsZW5kX21hdCwgbWF0ZXJpYWwpXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSBibGVuZGVyX3NwZWN1bGFyX3R5cGVzLndhcmRpc286XHJcbiAgICAgICAgICAgIGNhc2UgYmxlbmRlcl9zcGVjdWxhcl90eXBlcy5jb29rdG9ycjpcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsID0gbmV3IFRIUkVFLk1lc2hQaG9uZ01hdGVyaWFsKCk7XHJcbiAgICAgICAgICAgICAgICBtYXRlcmlhbC5jb2xvci5zZXRSR0IoYmxlbmRfbWF0LnIsIGJsZW5kX21hdC5nLCBibGVuZF9tYXQuYik7XHJcbiAgICAgICAgICAgICAgICBtYXRlcmlhbC5zcGVjdWxhci5zZXRSR0IoYmxlbmRfbWF0LnNwZWNyLCBibGVuZF9tYXQuc3BlY2csIGJsZW5kX21hdC5zcGVjYik7XHJcbiAgICAgICAgICAgICAgICBtYXRlcmlhbC5zaGluaW5lc3MgPSBibGVuZF9tYXQuaGFyIC8gNTEyO1xyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwucmVmbGVjdGl2aXR5ID0gYmxlbmRfbWF0LnJlZiAqIDEwMDtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwgPSBuZXcgVEhSRUUuTWVzaExhbWJlcnRNYXRlcmlhbCgpO1xyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwuY29sb3Iuc2V0UkdCKGJsZW5kX21hdC5yLCBibGVuZF9tYXQuZywgYmxlbmRfbWF0LmIpO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB2YXIgYXQgPSAodGV4dHVyZSkgPT4gYXBwbHlUZXh0dXJlKHRleHR1cmUsIG1hdGVyaWFsKTtcclxuXHJcblxyXG4gICAgICAgIGlmICh0ZXh0dXJlcyAmJiB0ZXh0dXJlcy5sZW5ndGgpIHRleHR1cmVzLm1hcChhdCk7XHJcblxyXG4gICAgICAgIHJldHVybiBtYXRlcmlhbDtcclxuICAgIH07XHJcbn0pKCk7IiwiLypqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXHJcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY3JlYXRlVGhyZWVKU0J1ZmZlckdlb21ldHJ5KGJsZW5kZXJfbWVzaCwgb3JpZ2luKSB7XHJcbiAgICAvL2dldCBtYXRlcmlhbHNcclxuICAgIGxldCBwaWNrX21hdGVyaWFsID0gMCxcclxuICAgICAgICBtZXNoID0gYmxlbmRlcl9tZXNoLFxyXG4gICAgICAgIGZhY2VzID0gbWVzaC5tcG9seSxcclxuICAgICAgICBsb29wcyA9IG1lc2gubWxvb3AsXHJcbiAgICAgICAgVVYgPSBtZXNoLm1sb29wdXYsXHJcbiAgICAgICAgdmVydHMgPSBtZXNoLm12ZXJ0O1xyXG5cclxuICAgIHZhciBnZW9tZXRyeSA9IG5ldyBUSFJFRS5CdWZmZXJHZW9tZXRyeSgpO1xyXG5cclxuICAgIGlmICghZmFjZXMpIHJldHVybiBnZW9tZXRyeTtcclxuXHJcbiAgICB2YXIgaW5kZXhfY291bnQgPSAwO1xyXG5cclxuICAgIC8vcHJlY2FsY3VsYXRlIHRoZSBzaXplIG9mIHRoZSBhcnJheSBuZWVkZWQgZm9yIGZhY2VzXHJcbiAgICB2YXIgZmFjZV9pbmRpY2VfY291bnQgPSAwO1xyXG4gICAgdmFyIGZhY2VfaW5kaWNlX2NvdW50YSA9IDA7XHJcblxyXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmYWNlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIHZhciBmYWNlID0gZmFjZXNbaV0gfHwgZmFjZXM7XHJcbiAgICAgICAgdmFyIGxlbiA9IGZhY2UudG90bG9vcDtcclxuICAgICAgICB2YXIgaW5kZXhpID0gMTtcclxuXHJcbiAgICAgICAgZmFjZV9pbmRpY2VfY291bnRhICs9IChsZW4gKiAyIC8gMykgfCAwO1xyXG5cclxuICAgICAgICB3aGlsZSAoaW5kZXhpIDwgbGVuKSB7XHJcbiAgICAgICAgICAgIGZhY2VfaW5kaWNlX2NvdW50ICs9IDM7XHJcbiAgICAgICAgICAgIGluZGV4aSArPSAyO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvL2V4dHJhY3QgZmFjZSBpbmZvIGFuZCBkdW1wIGludG8gYXJyYXkgYnVmZmVyO1xyXG4gICAgdmFyIGZhY2VfYnVmZmVyID0gbmV3IFVpbnQzMkFycmF5KGZhY2VfaW5kaWNlX2NvdW50KTtcclxuICAgIHZhciB1dl9idWZmZXIgPSBuZXcgRmxvYXQzMkFycmF5KGZhY2VfaW5kaWNlX2NvdW50ICogMik7XHJcbiAgICB2YXIgbm9ybWFsX2J1ZmZlciA9IG5ldyBGbG9hdDMyQXJyYXkoZmFjZV9pbmRpY2VfY291bnQgKiAzKTtcclxuICAgIHZhciB2ZXJ0c19hcnJheV9idWZmID0gbmV3IEZsb2F0MzJBcnJheShmYWNlX2luZGljZV9jb3VudCAqIDMpO1xyXG5cclxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmFjZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICB2YXIgZmFjZSA9IGZhY2VzW2ldIHx8IGZhY2VzO1xyXG4gICAgICAgIHZhciBsZW4gPSBmYWNlLnRvdGxvb3A7XHJcbiAgICAgICAgdmFyIHN0YXJ0ID0gZmFjZS5sb29wc3RhcnQ7XHJcbiAgICAgICAgdmFyIGluZGV4aSA9IDE7XHJcbiAgICAgICAgdmFyIG9mZnNldCA9IDA7XHJcblxyXG4gICAgICAgIHdoaWxlIChpbmRleGkgPCBsZW4pIHtcclxuICAgICAgICAgICAgdmFyIGZhY2Vfbm9ybWFscyA9IFtdO1xyXG4gICAgICAgICAgICB2YXIgZmFjZV9pbmRleF9hcnJheSA9IFtdO1xyXG4gICAgICAgICAgICB2YXIgZmFjZV91dnMgPSBbXTtcclxuXHJcbiAgICAgICAgICAgIGxldCBpbmRleCA9IDA7XHJcblxyXG4gICAgICAgICAgICBmb3IgKHZhciBsID0gMDsgbCA8IDM7IGwrKykge1xyXG4gICAgICAgICAgICAgICAgLy9QZXIgVmVydGljZSBcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoKGluZGV4aSAtIDEpICsgbCA8IGxlbikge1xyXG4gICAgICAgICAgICAgICAgICAgIGluZGV4ID0gc3RhcnQgKyAoaW5kZXhpIC0gMSkgKyBsO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBpbmRleCA9IHN0YXJ0O1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHZhciB2ID0gbG9vcHNbaW5kZXhdLnY7XHJcbiAgICAgICAgICAgICAgICB2YXIgdmVydCA9IHZlcnRzW3ZdO1xyXG4gICAgICAgICAgICAgICAgZmFjZV9idWZmZXJbaW5kZXhfY291bnRdID0gaW5kZXhfY291bnQ7XHJcbiAgICAgICAgICAgICAgICAvL2dldCBub3JtYWxzLCB3aGljaCBhcmUgMTZieXRlIGludHMsIGFuZCBub3JtIHRoZW0gYmFjayBpbnRvIGZsb2F0cy5cclxuXHJcbiAgICAgICAgICAgICAgICB2ZXJ0c19hcnJheV9idWZmW2luZGV4X2NvdW50ICogMyArIDBdID0gdmVydC5jb1swXSArIG9yaWdpblswXTtcclxuICAgICAgICAgICAgICAgIHZlcnRzX2FycmF5X2J1ZmZbaW5kZXhfY291bnQgKiAzICsgMV0gPSB2ZXJ0LmNvWzJdICsgb3JpZ2luWzJdO1xyXG4gICAgICAgICAgICAgICAgdmVydHNfYXJyYXlfYnVmZltpbmRleF9jb3VudCAqIDMgKyAyXSA9IC12ZXJ0LmNvWzFdICsgLW9yaWdpblsxXTtcclxuXHJcbiAgICAgICAgICAgICAgICBub3JtYWxfYnVmZmVyW2luZGV4X2NvdW50ICogMyArIDBdID0gdmVydC5ub1swXTtcclxuICAgICAgICAgICAgICAgIG5vcm1hbF9idWZmZXJbaW5kZXhfY291bnQgKiAzICsgMV0gPSB2ZXJ0Lm5vWzJdO1xyXG4gICAgICAgICAgICAgICAgbm9ybWFsX2J1ZmZlcltpbmRleF9jb3VudCAqIDMgKyAyXSA9ICgtdmVydC5ub1sxXSk7XHJcblxyXG5cclxuICAgICAgICAgICAgICAgIGlmIChVVikge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciB1diA9IFVWW2luZGV4XS51djtcclxuICAgICAgICAgICAgICAgICAgICB1dl9idWZmZXJbaW5kZXhfY291bnQgKiAyICsgMF0gPSB1dlswXTtcclxuICAgICAgICAgICAgICAgICAgICB1dl9idWZmZXJbaW5kZXhfY291bnQgKiAyICsgMV0gPSB1dlsxXTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpbmRleF9jb3VudCsrO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpbmRleGkgKz0gMjtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgZ2VvbWV0cnkuYWRkQXR0cmlidXRlKCdwb3NpdGlvbicsIG5ldyBUSFJFRS5CdWZmZXJBdHRyaWJ1dGUodmVydHNfYXJyYXlfYnVmZiwgMykpO1xyXG4gICAgZ2VvbWV0cnkuc2V0SW5kZXgobmV3IFRIUkVFLkJ1ZmZlckF0dHJpYnV0ZShmYWNlX2J1ZmZlciwgMSkpO1xyXG4gICAgZ2VvbWV0cnkuYWRkQXR0cmlidXRlKCdub3JtYWwnLCBuZXcgVEhSRUUuQnVmZmVyQXR0cmlidXRlKG5vcm1hbF9idWZmZXIsIDMpKTtcclxuICAgIGdlb21ldHJ5LmFkZEF0dHJpYnV0ZSgndXYnLCBuZXcgVEhSRUUuQnVmZmVyQXR0cmlidXRlKHV2X2J1ZmZlciwgMikpO1xyXG4gICAgLy9nZW9tZXRyeS5ibGVuZF9tYXQgPSBtYXRlcmlhbHNbcGlja19tYXRlcmlhbF07XHJcblxyXG4gICAgcmV0dXJuIGdlb21ldHJ5O1xyXG59O1xyXG5cclxuZnVuY3Rpb24gY3JlYXRlVGhyZWVKU0dlb21ldHJ5KGJsZW5kZXJfbWVzaCwgb3JpZ2luKSB7XHJcbiAgICAvL2dldCBtYXRlcmlhbHNcclxuICAgIHZhciBtYXRzID0gYmxlbmRlcl9tZXNoLm1hdCxcclxuICAgICAgICBtYXRlcmlhbHMgPSBbXTtcclxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWF0cy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIHZhciBtYXRlcmlhbCA9IGNyZWF0ZVRocmVlSlNNYXRlcmlhbChtYXRzW2ldKTtcclxuICAgICAgICBtYXRlcmlhbHMucHVzaChtYXRlcmlhbCk7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHBpY2tfbWF0ZXJpYWwgPSAwLFxyXG4gICAgICAgIG1lc2ggPSBibGVuZGVyX21lc2gsXHJcbiAgICAgICAgZmFjZXMgPSBtZXNoLm1wb2x5LFxyXG4gICAgICAgIGxvb3BzID0gbWVzaC5tbG9vcCxcclxuICAgICAgICBVViA9IG1lc2gubWxvb3B1dixcclxuICAgICAgICB2ZXJ0cyA9IG1lc2gubXZlcnQsXHJcbiAgICAgICAgdmVydF9hcnJheSA9IFtdLFxyXG4gICAgICAgIGZhY2VfYXJyYXkgPSBbXSxcclxuICAgICAgICB1dl9hcnJheSA9IFtdLFxyXG4gICAgICAgIG5vcm1hbF9hcnJheSA9IFtdO1xyXG5cclxuICAgIHZhciBnZW9tZXRyeSA9IG5ldyBUSFJFRS5HZW9tZXRyeSgpO1xyXG5cclxuICAgIGlmICghZmFjZXMpIHJldHVybiBnZW9tZXRyeTtcclxuXHJcblxyXG4gICAgdmFyIGluZGV4X2NvdW50ID0gMDtcclxuXHJcbiAgICBsZXQgdmVydHNfYXJyYXlfYnVmZiA9IG5ldyBGbG9hdDMyQXJyYXkodmVydHMubGVuZ3RoICogMyk7XHJcblxyXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2ZXJ0cy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIGxldCB2ZXJ0ID0gdmVydHNbaV07XHJcbiAgICAgICAgdmVydF9hcnJheS5wdXNoKG5ldyBUSFJFRS5WZWN0b3IzKHZlcnQuY29bMF0gKyBvcmlnaW5bMF0sIHZlcnQuY29bMl0gKyBvcmlnaW5bMl0sIC12ZXJ0LmNvWzFdIC0gb3JpZ2luWzFdKSk7XHJcbiAgICB9XHJcblxyXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmYWNlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIHZhciBmYWNlID0gZmFjZXNbaV0gfHwgZmFjZXM7XHJcbiAgICAgICAgdmFyIGxlbiA9IGZhY2UudG90bG9vcDtcclxuICAgICAgICB2YXIgc3RhcnQgPSBmYWNlLmxvb3BzdGFydDtcclxuICAgICAgICB2YXIgaW5kZXhpID0gMTtcclxuXHJcbiAgICAgICAgcGlja19tYXRlcmlhbCA9IGZhY2UubWF0X25yO1xyXG5cclxuICAgICAgICB3aGlsZSAoaW5kZXhpIDwgbGVuKSB7XHJcbiAgICAgICAgICAgIHZhciBmYWNlX25vcm1hbHMgPSBbXTtcclxuICAgICAgICAgICAgdmFyIGZhY2VfaW5kZXhfYXJyYXkgPSBbXTtcclxuICAgICAgICAgICAgdmFyIGZhY2VfdXZzID0gW107XHJcblxyXG4gICAgICAgICAgICBsZXQgaW5kZXggPSAwO1xyXG5cclxuICAgICAgICAgICAgZm9yICh2YXIgbCA9IDA7IGwgPCAzOyBsKyspIHtcclxuICAgICAgICAgICAgICAgIC8vUGVyIFZlcnRpY2UgXHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKChpbmRleGkgLSAxKSArIGwgPCBsZW4pIHtcclxuICAgICAgICAgICAgICAgICAgICBpbmRleCA9IHN0YXJ0ICsgKGluZGV4aSAtIDEpICsgbDtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggPSBzdGFydDtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICB2YXIgdiA9IGxvb3BzW2luZGV4XS52O1xyXG4gICAgICAgICAgICAgICAgdmFyIHZlcnQgPSB2ZXJ0c1t2XTtcclxuXHJcbiAgICAgICAgICAgICAgICBmYWNlX2luZGV4X2FycmF5LnB1c2godik7XHJcblxyXG4gICAgICAgICAgICAgICAgaW5kZXhfY291bnQrKztcclxuXHJcbiAgICAgICAgICAgICAgICAvL2dldCBub3JtYWxzLCB3aGljaCBhcmUgMTZieXRlIGludHMsIGFuZCBub3JtIHRoZW0gYmFjayBpbnRvIGZsb2F0cy5cclxuXHJcbiAgICAgICAgICAgICAgICB2YXJcclxuICAgICAgICAgICAgICAgICAgICBuMSA9IHZlcnQubm9bMF0sXHJcbiAgICAgICAgICAgICAgICAgICAgbjIgPSB2ZXJ0Lm5vWzJdLFxyXG4gICAgICAgICAgICAgICAgICAgIG4zID0gLXZlcnQubm9bMV07XHJcblxyXG4gICAgICAgICAgICAgICAgdmFyIG5sID0gMTtcclxuXHJcbiAgICAgICAgICAgICAgICBNYXRoLnNxcnQoKG4xICogbjEpICsgKG4yICogbjIpICsgKG4zICogbjMpKTtcclxuXHJcbiAgICAgICAgICAgICAgICBmYWNlX25vcm1hbHMucHVzaChuZXcgVEhSRUUuVmVjdG9yMyhuMSAvIG5sLCBuMiAvIG5sLCBuMyAvIG5sKSk7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKFVWKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIHV2ID0gVVZbaW5kZXhdLnV2O1xyXG4gICAgICAgICAgICAgICAgICAgIGZhY2VfdXZzLnB1c2gobmV3IFRIUkVFLlZlY3RvcjIodXZbMF0sIHV2WzFdKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdXZfYXJyYXkucHVzaChmYWNlX3V2cyk7XHJcbiAgICAgICAgICAgIGZhY2VfYXJyYXkucHVzaChuZXcgVEhSRUUuRmFjZTMoXHJcbiAgICAgICAgICAgICAgICBmYWNlX2luZGV4X2FycmF5WzBdLCBmYWNlX2luZGV4X2FycmF5WzFdLCBmYWNlX2luZGV4X2FycmF5WzJdLFxyXG4gICAgICAgICAgICAgICAgZmFjZV9ub3JtYWxzXHJcbiAgICAgICAgICAgICkpO1xyXG5cclxuICAgICAgICAgICAgaW5kZXhpICs9IDI7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgZ2VvbWV0cnkuYmxlbmRfbWF0ID0gbWF0ZXJpYWxzW3BpY2tfbWF0ZXJpYWxdO1xyXG4gICAgZ2VvbWV0cnkudmVydGljZXMgPSB2ZXJ0X2FycmF5O1xyXG4gICAgZ2VvbWV0cnkuZmFjZXMgPSBmYWNlX2FycmF5O1xyXG4gICAgaWYgKHV2X2FycmF5Lmxlbmd0aCA+IDApIHtcclxuICAgICAgICBnZW9tZXRyeS5mYWNlVmVydGV4VXZzID0gW3V2X2FycmF5XTtcclxuICAgIH1cclxuXHJcbiAgICBnZW9tZXRyeS51dnNOZWVkVXBkYXRlID0gdHJ1ZTtcclxuXHJcbiAgICAvL1dlbGwsIHVzaW5nIGJsZW5kZXIgZmlsZSBub3JtYWxzIGRvZXMgbm90IHdvcmsuIFdpbGwgbmVlZCB0byBpbnZlc3RpZ2F0ZSB3aHkgbm9ybWFscyBmcm9tIHRoZSBibGVuZGVyIGZpbGUgZG8gbm90IHByb3ZpZGUgY29ycmVjdCByZXN1bHRzLiBcclxuICAgIC8vRm9yIG5vdywgaGF2ZSBUaHJlZSBjYWxjdWxhdGUgbm9ybWFscy4gXHJcblxyXG4gICAgZ2VvbWV0cnkuY29tcHV0ZVZlcnRleE5vcm1hbHMoKTtcclxuXHJcblxyXG4gICAgcmV0dXJuIGdlb21ldHJ5O1xyXG59OyIsIi8qanNoaW50IGVzdmVyc2lvbjogNiAqL1xyXG5cclxubGV0IGJsZW5kZXJfdGV4dHVyZV9jYWNoZSA9IHt9O1xyXG5cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY3JlYXRlVGhyZWVKU1RleHR1cmUoaW1hZ2UpIHtcclxuICAgIGxldCBiYXNlNjQgPSByZXF1aXJlKFwiYmFzZTY0LWpzXCIpO1xyXG4gICAgbGV0IHBhcnNlZF9ibGVuZF9maWxlID0gaW1hZ2UuX19ibGVuZGVyX2ZpbGVfXztcclxuICAgIGxldCB0ZXh0dXJlID0gbnVsbDtcclxuICAgIGxldCBuYW1lID0gaW1hZ2UuYW5hbWU7XHJcblxyXG4gICAgaWYgKGltYWdlLnBhY2tlZGZpbGUpIHtcclxuXHJcbiAgICAgICAgaWYgKGJsZW5kZXJfdGV4dHVyZV9jYWNoZVtuYW1lXSkge1xyXG4gICAgICAgICAgICB0ZXh0dXJlID0gYmxlbmRlcl90ZXh0dXJlX2NhY2hlW25hbWVdO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcblxyXG4gICAgICAgICAgICAvL2dldCB0aGUgZXh0ZW5zaW9uXHJcbiAgICAgICAgICAgIGxldCBleHQgPSBuYW1lLnNwbGl0KCcuJykucG9wKCk7XHJcblxyXG4gICAgICAgICAgICBsZXQgZGF0YSA9IGltYWdlLnBhY2tlZGZpbGU7XHJcblxyXG4gICAgICAgICAgICBsZXQgc2l6ZSA9IGRhdGEuc2l6ZTtcclxuXHJcbiAgICAgICAgICAgIGxldCBvZmZzZXQgPSBkYXRhLmRhdGEuX19kYXRhX2FkZHJlc3NfXztcclxuXHJcbiAgICAgICAgICAgIGxldCByYXdfZGF0YSA9IHBhcnNlZF9ibGVuZF9maWxlLmJ5dGUuc2xpY2Uob2Zmc2V0LCBvZmZzZXQgKyBzaXplKTtcclxuXHJcbiAgICAgICAgICAgIGxldCBlbmNvZGVkRGF0YSA9IGJhc2U2NC5mcm9tQnl0ZUFycmF5KHJhd19kYXRhKTtcclxuXHJcbiAgICAgICAgICAgIGxldCBkYXRhVVJJO1xyXG5cclxuICAgICAgICAgICAgc3dpdGNoIChleHQpIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgXCJwbmdcIjpcclxuICAgICAgICAgICAgICAgICAgICBkYXRhVVJJID0gXCJkYXRhOmltYWdlL3BuZztiYXNlNjQsXCIgKyBlbmNvZGVkRGF0YTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgXCJqcGdcIjpcclxuICAgICAgICAgICAgICAgICAgICBkYXRhVVJJID0gXCJkYXRhOmltYWdlL2pwZWc7YmFzZTY0LFwiICsgZW5jb2RlZERhdGE7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGxldCBpbWcgPSBuZXcgSW1hZ2UoKTtcclxuXHJcbiAgICAgICAgICAgIGltZy5zcmMgPSBkYXRhVVJJO1xyXG5cclxuICAgICAgICAgICAgdGV4dHVyZSA9IG5ldyBUSFJFRS5UZXh0dXJlKGltZyk7XHJcblxyXG4gICAgICAgICAgICBpbWcub25sb2FkID0gKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgdGV4dHVyZS5uZWVkc1VwZGF0ZSA9IHRydWU7XHJcbiAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICBibGVuZGVyX3RleHR1cmVfY2FjaGVbbmFtZV0gPSB0ZXh0dXJlO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiB0ZXh0dXJlO1xyXG59OyJdfQ==