1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.QRCode = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
2 | // can-promise has a crash in some versions of react native that dont have
|
3 | // standard global objects
|
4 | // https://github.com/soldair/node-qrcode/issues/157
|
5 |
|
6 | module.exports = function () {
|
7 | return typeof Promise === 'function' && Promise.prototype && Promise.prototype.then
|
8 | }
|
9 |
|
10 | },{}],2:[function(require,module,exports){
|
11 | /**
|
12 | * Alignment pattern are fixed reference pattern in defined positions
|
13 | * in a matrix symbology, which enables the decode software to re-synchronise
|
14 | * the coordinate mapping of the image modules in the event of moderate amounts
|
15 | * of distortion of the image.
|
16 | *
|
17 | * Alignment patterns are present only in QR Code symbols of version 2 or larger
|
18 | * and their number depends on the symbol version.
|
19 | */
|
20 |
|
21 | var getSymbolSize = require('./utils').getSymbolSize
|
22 |
|
23 | /**
|
24 | * Calculate the row/column coordinates of the center module of each alignment pattern
|
25 | * for the specified QR Code version.
|
26 | *
|
27 | * The alignment patterns are positioned symmetrically on either side of the diagonal
|
28 | * running from the top left corner of the symbol to the bottom right corner.
|
29 | *
|
30 | * Since positions are simmetrical only half of the coordinates are returned.
|
31 | * Each item of the array will represent in turn the x and y coordinate.
|
32 | * @see {@link getPositions}
|
33 | *
|
34 | * @param {Number} version QR Code version
|
35 | * @return {Array} Array of coordinate
|
36 | */
|
37 | exports.getRowColCoords = function getRowColCoords (version) {
|
38 | if (version === 1) return []
|
39 |
|
40 | var posCount = Math.floor(version / 7) + 2
|
41 | var size = getSymbolSize(version)
|
42 | var intervals = size === 145 ? 26 : Math.ceil((size - 13) / (2 * posCount - 2)) * 2
|
43 | var positions = [size - 7] // Last coord is always (size - 7)
|
44 |
|
45 | for (var i = 1; i < posCount - 1; i++) {
|
46 | positions[i] = positions[i - 1] - intervals
|
47 | }
|
48 |
|
49 | positions.push(6) // First coord is always 6
|
50 |
|
51 | return positions.reverse()
|
52 | }
|
53 |
|
54 | /**
|
55 | * Returns an array containing the positions of each alignment pattern.
|
56 | * Each array's element represent the center point of the pattern as (x, y) coordinates
|
57 | *
|
58 | * Coordinates are calculated expanding the row/column coordinates returned by {@link getRowColCoords}
|
59 | * and filtering out the items that overlaps with finder pattern
|
60 | *
|
61 | * @example
|
62 | * For a Version 7 symbol {@link getRowColCoords} returns values 6, 22 and 38.
|
63 | * The alignment patterns, therefore, are to be centered on (row, column)
|
64 | * positions (6,22), (22,6), (22,22), (22,38), (38,22), (38,38).
|
65 | * Note that the coordinates (6,6), (6,38), (38,6) are occupied by finder patterns
|
66 | * and are not therefore used for alignment patterns.
|
67 | *
|
68 | * var pos = getPositions(7)
|
69 | * // [[6,22], [22,6], [22,22], [22,38], [38,22], [38,38]]
|
70 | *
|
71 | * @param {Number} version QR Code version
|
72 | * @return {Array} Array of coordinates
|
73 | */
|
74 | exports.getPositions = function getPositions (version) {
|
75 | var coords = []
|
76 | var pos = exports.getRowColCoords(version)
|
77 | var posLength = pos.length
|
78 |
|
79 | for (var i = 0; i < posLength; i++) {
|
80 | for (var j = 0; j < posLength; j++) {
|
81 | // Skip if position is occupied by finder patterns
|
82 | if ((i === 0 && j === 0) || // top-left
|
83 | (i === 0 && j === posLength - 1) || // bottom-left
|
84 | (i === posLength - 1 && j === 0)) { // top-right
|
85 | continue
|
86 | }
|
87 |
|
88 | coords.push([pos[i], pos[j]])
|
89 | }
|
90 | }
|
91 |
|
92 | return coords
|
93 | }
|
94 |
|
95 | },{"./utils":21}],3:[function(require,module,exports){
|
96 | var Mode = require('./mode')
|
97 |
|
98 | /**
|
99 | * Array of characters available in alphanumeric mode
|
100 | *
|
101 | * As per QR Code specification, to each character
|
102 | * is assigned a value from 0 to 44 which in this case coincides
|
103 | * with the array index
|
104 | *
|
105 | * @type {Array}
|
106 | */
|
107 | var ALPHA_NUM_CHARS = [
|
108 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
109 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
110 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
111 | ' ', '$', '%', '*', '+', '-', '.', '/', ':'
|
112 | ]
|
113 |
|
114 | function AlphanumericData (data) {
|
115 | this.mode = Mode.ALPHANUMERIC
|
116 | this.data = data
|
117 | }
|
118 |
|
119 | AlphanumericData.getBitsLength = function getBitsLength (length) {
|
120 | return 11 * Math.floor(length / 2) + 6 * (length % 2)
|
121 | }
|
122 |
|
123 | AlphanumericData.prototype.getLength = function getLength () {
|
124 | return this.data.length
|
125 | }
|
126 |
|
127 | AlphanumericData.prototype.getBitsLength = function getBitsLength () {
|
128 | return AlphanumericData.getBitsLength(this.data.length)
|
129 | }
|
130 |
|
131 | AlphanumericData.prototype.write = function write (bitBuffer) {
|
132 | var i
|
133 |
|
134 | // Input data characters are divided into groups of two characters
|
135 | // and encoded as 11-bit binary codes.
|
136 | for (i = 0; i + 2 <= this.data.length; i += 2) {
|
137 | // The character value of the first character is multiplied by 45
|
138 | var value = ALPHA_NUM_CHARS.indexOf(this.data[i]) * 45
|
139 |
|
140 | // The character value of the second digit is added to the product
|
141 | value += ALPHA_NUM_CHARS.indexOf(this.data[i + 1])
|
142 |
|
143 | // The sum is then stored as 11-bit binary number
|
144 | bitBuffer.put(value, 11)
|
145 | }
|
146 |
|
147 | // If the number of input data characters is not a multiple of two,
|
148 | // the character value of the final character is encoded as a 6-bit binary number.
|
149 | if (this.data.length % 2) {
|
150 | bitBuffer.put(ALPHA_NUM_CHARS.indexOf(this.data[i]), 6)
|
151 | }
|
152 | }
|
153 |
|
154 | module.exports = AlphanumericData
|
155 |
|
156 | },{"./mode":14}],4:[function(require,module,exports){
|
157 | function BitBuffer () {
|
158 | this.buffer = []
|
159 | this.length = 0
|
160 | }
|
161 |
|
162 | BitBuffer.prototype = {
|
163 |
|
164 | get: function (index) {
|
165 | var bufIndex = Math.floor(index / 8)
|
166 | return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) === 1
|
167 | },
|
168 |
|
169 | put: function (num, length) {
|
170 | for (var i = 0; i < length; i++) {
|
171 | this.putBit(((num >>> (length - i - 1)) & 1) === 1)
|
172 | }
|
173 | },
|
174 |
|
175 | getLengthInBits: function () {
|
176 | return this.length
|
177 | },
|
178 |
|
179 | putBit: function (bit) {
|
180 | var bufIndex = Math.floor(this.length / 8)
|
181 | if (this.buffer.length <= bufIndex) {
|
182 | this.buffer.push(0)
|
183 | }
|
184 |
|
185 | if (bit) {
|
186 | this.buffer[bufIndex] |= (0x80 >>> (this.length % 8))
|
187 | }
|
188 |
|
189 | this.length++
|
190 | }
|
191 | }
|
192 |
|
193 | module.exports = BitBuffer
|
194 |
|
195 | },{}],5:[function(require,module,exports){
|
196 | var Buffer = require('../utils/buffer')
|
197 |
|
198 | /**
|
199 | * Helper class to handle QR Code symbol modules
|
200 | *
|
201 | * @param {Number} size Symbol size
|
202 | */
|
203 | function BitMatrix (size) {
|
204 | if (!size || size < 1) {
|
205 | throw new Error('BitMatrix size must be defined and greater than 0')
|
206 | }
|
207 |
|
208 | this.size = size
|
209 | this.data = new Buffer(size * size)
|
210 | this.data.fill(0)
|
211 | this.reservedBit = new Buffer(size * size)
|
212 | this.reservedBit.fill(0)
|
213 | }
|
214 |
|
215 | /**
|
216 | * Set bit value at specified location
|
217 | * If reserved flag is set, this bit will be ignored during masking process
|
218 | *
|
219 | * @param {Number} row
|
220 | * @param {Number} col
|
221 | * @param {Boolean} value
|
222 | * @param {Boolean} reserved
|
223 | */
|
224 | BitMatrix.prototype.set = function (row, col, value, reserved) {
|
225 | var index = row * this.size + col
|
226 | this.data[index] = value
|
227 | if (reserved) this.reservedBit[index] = true
|
228 | }
|
229 |
|
230 | /**
|
231 | * Returns bit value at specified location
|
232 | *
|
233 | * @param {Number} row
|
234 | * @param {Number} col
|
235 | * @return {Boolean}
|
236 | */
|
237 | BitMatrix.prototype.get = function (row, col) {
|
238 | return this.data[row * this.size + col]
|
239 | }
|
240 |
|
241 | /**
|
242 | * Applies xor operator at specified location
|
243 | * (used during masking process)
|
244 | *
|
245 | * @param {Number} row
|
246 | * @param {Number} col
|
247 | * @param {Boolean} value
|
248 | */
|
249 | BitMatrix.prototype.xor = function (row, col, value) {
|
250 | this.data[row * this.size + col] ^= value
|
251 | }
|
252 |
|
253 | /**
|
254 | * Check if bit at specified location is reserved
|
255 | *
|
256 | * @param {Number} row
|
257 | * @param {Number} col
|
258 | * @return {Boolean}
|
259 | */
|
260 | BitMatrix.prototype.isReserved = function (row, col) {
|
261 | return this.reservedBit[row * this.size + col]
|
262 | }
|
263 |
|
264 | module.exports = BitMatrix
|
265 |
|
266 | },{"../utils/buffer":28}],6:[function(require,module,exports){
|
267 | var Buffer = require('../utils/buffer')
|
268 | var Mode = require('./mode')
|
269 |
|
270 | function ByteData (data) {
|
271 | this.mode = Mode.BYTE
|
272 | this.data = new Buffer(data)
|
273 | }
|
274 |
|
275 | ByteData.getBitsLength = function getBitsLength (length) {
|
276 | return length * 8
|
277 | }
|
278 |
|
279 | ByteData.prototype.getLength = function getLength () {
|
280 | return this.data.length
|
281 | }
|
282 |
|
283 | ByteData.prototype.getBitsLength = function getBitsLength () {
|
284 | return ByteData.getBitsLength(this.data.length)
|
285 | }
|
286 |
|
287 | ByteData.prototype.write = function (bitBuffer) {
|
288 | for (var i = 0, l = this.data.length; i < l; i++) {
|
289 | bitBuffer.put(this.data[i], 8)
|
290 | }
|
291 | }
|
292 |
|
293 | module.exports = ByteData
|
294 |
|
295 | },{"../utils/buffer":28,"./mode":14}],7:[function(require,module,exports){
|
296 | var ECLevel = require('./error-correction-level')
|
297 |
|
298 | var EC_BLOCKS_TABLE = [
|
299 | // L M Q H
|
300 | 1, 1, 1, 1,
|
301 | 1, 1, 1, 1,
|
302 | 1, 1, 2, 2,
|
303 | 1, 2, 2, 4,
|
304 | 1, 2, 4, 4,
|
305 | 2, 4, 4, 4,
|
306 | 2, 4, 6, 5,
|
307 | 2, 4, 6, 6,
|
308 | 2, 5, 8, 8,
|
309 | 4, 5, 8, 8,
|
310 | 4, 5, 8, 11,
|
311 | 4, 8, 10, 11,
|
312 | 4, 9, 12, 16,
|
313 | 4, 9, 16, 16,
|
314 | 6, 10, 12, 18,
|
315 | 6, 10, 17, 16,
|
316 | 6, 11, 16, 19,
|
317 | 6, 13, 18, 21,
|
318 | 7, 14, 21, 25,
|
319 | 8, 16, 20, 25,
|
320 | 8, 17, 23, 25,
|
321 | 9, 17, 23, 34,
|
322 | 9, 18, 25, 30,
|
323 | 10, 20, 27, 32,
|
324 | 12, 21, 29, 35,
|
325 | 12, 23, 34, 37,
|
326 | 12, 25, 34, 40,
|
327 | 13, 26, 35, 42,
|
328 | 14, 28, 38, 45,
|
329 | 15, 29, 40, 48,
|
330 | 16, 31, 43, 51,
|
331 | 17, 33, 45, 54,
|
332 | 18, 35, 48, 57,
|
333 | 19, 37, 51, 60,
|
334 | 19, 38, 53, 63,
|
335 | 20, 40, 56, 66,
|
336 | 21, 43, 59, 70,
|
337 | 22, 45, 62, 74,
|
338 | 24, 47, 65, 77,
|
339 | 25, 49, 68, 81
|
340 | ]
|
341 |
|
342 | var EC_CODEWORDS_TABLE = [
|
343 | // L M Q H
|
344 | 7, 10, 13, 17,
|
345 | 10, 16, 22, 28,
|
346 | 15, 26, 36, 44,
|
347 | 20, 36, 52, 64,
|
348 | 26, 48, 72, 88,
|
349 | 36, 64, 96, 112,
|
350 | 40, 72, 108, 130,
|
351 | 48, 88, 132, 156,
|
352 | 60, 110, 160, 192,
|
353 | 72, 130, 192, 224,
|
354 | 80, 150, 224, 264,
|
355 | 96, 176, 260, 308,
|
356 | 104, 198, 288, 352,
|
357 | 120, 216, 320, 384,
|
358 | 132, 240, 360, 432,
|
359 | 144, 280, 408, 480,
|
360 | 168, 308, 448, 532,
|
361 | 180, 338, 504, 588,
|
362 | 196, 364, 546, 650,
|
363 | 224, 416, 600, 700,
|
364 | 224, 442, 644, 750,
|
365 | 252, 476, 690, 816,
|
366 | 270, 504, 750, 900,
|
367 | 300, 560, 810, 960,
|
368 | 312, 588, 870, 1050,
|
369 | 336, 644, 952, 1110,
|
370 | 360, 700, 1020, 1200,
|
371 | 390, 728, 1050, 1260,
|
372 | 420, 784, 1140, 1350,
|
373 | 450, 812, 1200, 1440,
|
374 | 480, 868, 1290, 1530,
|
375 | 510, 924, 1350, 1620,
|
376 | 540, 980, 1440, 1710,
|
377 | 570, 1036, 1530, 1800,
|
378 | 570, 1064, 1590, 1890,
|
379 | 600, 1120, 1680, 1980,
|
380 | 630, 1204, 1770, 2100,
|
381 | 660, 1260, 1860, 2220,
|
382 | 720, 1316, 1950, 2310,
|
383 | 750, 1372, 2040, 2430
|
384 | ]
|
385 |
|
386 | /**
|
387 | * Returns the number of error correction block that the QR Code should contain
|
388 | * for the specified version and error correction level.
|
389 | *
|
390 | * @param {Number} version QR Code version
|
391 | * @param {Number} errorCorrectionLevel Error correction level
|
392 | * @return {Number} Number of error correction blocks
|
393 | */
|
394 | exports.getBlocksCount = function getBlocksCount (version, errorCorrectionLevel) {
|
395 | switch (errorCorrectionLevel) {
|
396 | case ECLevel.L:
|
397 | return EC_BLOCKS_TABLE[(version - 1) * 4 + 0]
|
398 | case ECLevel.M:
|
399 | return EC_BLOCKS_TABLE[(version - 1) * 4 + 1]
|
400 | case ECLevel.Q:
|
401 | return EC_BLOCKS_TABLE[(version - 1) * 4 + 2]
|
402 | case ECLevel.H:
|
403 | return EC_BLOCKS_TABLE[(version - 1) * 4 + 3]
|
404 | default:
|
405 | return undefined
|
406 | }
|
407 | }
|
408 |
|
409 | /**
|
410 | * Returns the number of error correction codewords to use for the specified
|
411 | * version and error correction level.
|
412 | *
|
413 | * @param {Number} version QR Code version
|
414 | * @param {Number} errorCorrectionLevel Error correction level
|
415 | * @return {Number} Number of error correction codewords
|
416 | */
|
417 | exports.getTotalCodewordsCount = function getTotalCodewordsCount (version, errorCorrectionLevel) {
|
418 | switch (errorCorrectionLevel) {
|
419 | case ECLevel.L:
|
420 | return EC_CODEWORDS_TABLE[(version - 1) * 4 + 0]
|
421 | case ECLevel.M:
|
422 | return EC_CODEWORDS_TABLE[(version - 1) * 4 + 1]
|
423 | case ECLevel.Q:
|
424 | return EC_CODEWORDS_TABLE[(version - 1) * 4 + 2]
|
425 | case ECLevel.H:
|
426 | return EC_CODEWORDS_TABLE[(version - 1) * 4 + 3]
|
427 | default:
|
428 | return undefined
|
429 | }
|
430 | }
|
431 |
|
432 | },{"./error-correction-level":8}],8:[function(require,module,exports){
|
433 | exports.L = { bit: 1 }
|
434 | exports.M = { bit: 0 }
|
435 | exports.Q = { bit: 3 }
|
436 | exports.H = { bit: 2 }
|
437 |
|
438 | function fromString (string) {
|
439 | if (typeof string !== 'string') {
|
440 | throw new Error('Param is not a string')
|
441 | }
|
442 |
|
443 | var lcStr = string.toLowerCase()
|
444 |
|
445 | switch (lcStr) {
|
446 | case 'l':
|
447 | case 'low':
|
448 | return exports.L
|
449 |
|
450 | case 'm':
|
451 | case 'medium':
|
452 | return exports.M
|
453 |
|
454 | case 'q':
|
455 | case 'quartile':
|
456 | return exports.Q
|
457 |
|
458 | case 'h':
|
459 | case 'high':
|
460 | return exports.H
|
461 |
|
462 | default:
|
463 | throw new Error('Unknown EC Level: ' + string)
|
464 | }
|
465 | }
|
466 |
|
467 | exports.isValid = function isValid (level) {
|
468 | return level && typeof level.bit !== 'undefined' &&
|
469 | level.bit >= 0 && level.bit < 4
|
470 | }
|
471 |
|
472 | exports.from = function from (value, defaultValue) {
|
473 | if (exports.isValid(value)) {
|
474 | return value
|
475 | }
|
476 |
|
477 | try {
|
478 | return fromString(value)
|
479 | } catch (e) {
|
480 | return defaultValue
|
481 | }
|
482 | }
|
483 |
|
484 | },{}],9:[function(require,module,exports){
|
485 | var getSymbolSize = require('./utils').getSymbolSize
|
486 | var FINDER_PATTERN_SIZE = 7
|
487 |
|
488 | /**
|
489 | * Returns an array containing the positions of each finder pattern.
|
490 | * Each array's element represent the top-left point of the pattern as (x, y) coordinates
|
491 | *
|
492 | * @param {Number} version QR Code version
|
493 | * @return {Array} Array of coordinates
|
494 | */
|
495 | exports.getPositions = function getPositions (version) {
|
496 | var size = getSymbolSize(version)
|
497 |
|
498 | return [
|
499 | // top-left
|
500 | [0, 0],
|
501 | // top-right
|
502 | [size - FINDER_PATTERN_SIZE, 0],
|
503 | // bottom-left
|
504 | [0, size - FINDER_PATTERN_SIZE]
|
505 | ]
|
506 | }
|
507 |
|
508 | },{"./utils":21}],10:[function(require,module,exports){
|
509 | var Utils = require('./utils')
|
510 |
|
511 | var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0)
|
512 | var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1)
|
513 | var G15_BCH = Utils.getBCHDigit(G15)
|
514 |
|
515 | /**
|
516 | * Returns format information with relative error correction bits
|
517 | *
|
518 | * The format information is a 15-bit sequence containing 5 data bits,
|
519 | * with 10 error correction bits calculated using the (15, 5) BCH code.
|
520 | *
|
521 | * @param {Number} errorCorrectionLevel Error correction level
|
522 | * @param {Number} mask Mask pattern
|
523 | * @return {Number} Encoded format information bits
|
524 | */
|
525 | exports.getEncodedBits = function getEncodedBits (errorCorrectionLevel, mask) {
|
526 | var data = ((errorCorrectionLevel.bit << 3) | mask)
|
527 | var d = data << 10
|
528 |
|
529 | while (Utils.getBCHDigit(d) - G15_BCH >= 0) {
|
530 | d ^= (G15 << (Utils.getBCHDigit(d) - G15_BCH))
|
531 | }
|
532 |
|
533 | // xor final data with mask pattern in order to ensure that
|
534 | // no combination of Error Correction Level and data mask pattern
|
535 | // will result in an all-zero data string
|
536 | return ((data << 10) | d) ^ G15_MASK
|
537 | }
|
538 |
|
539 | },{"./utils":21}],11:[function(require,module,exports){
|
540 | var Buffer = require('../utils/buffer')
|
541 |
|
542 | var EXP_TABLE
|
543 | var LOG_TABLE
|
544 |
|
545 | if (Buffer.alloc) {
|
546 | EXP_TABLE = Buffer.alloc(512)
|
547 | LOG_TABLE = Buffer.alloc(256)
|
548 | } else {
|
549 | EXP_TABLE = new Buffer(512)
|
550 | LOG_TABLE = new Buffer(256)
|
551 | }
|
552 | /**
|
553 | * Precompute the log and anti-log tables for faster computation later
|
554 | *
|
555 | * For each possible value in the galois field 2^8, we will pre-compute
|
556 | * the logarithm and anti-logarithm (exponential) of this value
|
557 | *
|
558 | * ref {@link https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders#Introduction_to_mathematical_fields}
|
559 | */
|
560 | ;(function initTables () {
|
561 | var x = 1
|
562 | for (var i = 0; i < 255; i++) {
|
563 | EXP_TABLE[i] = x
|
564 | LOG_TABLE[x] = i
|
565 |
|
566 | x <<= 1 // multiply by 2
|
567 |
|
568 | // The QR code specification says to use byte-wise modulo 100011101 arithmetic.
|
569 | // This means that when a number is 256 or larger, it should be XORed with 0x11D.
|
570 | if (x & 0x100) { // similar to x >= 256, but a lot faster (because 0x100 == 256)
|
571 | x ^= 0x11D
|
572 | }
|
573 | }
|
574 |
|
575 | // Optimization: double the size of the anti-log table so that we don't need to mod 255 to
|
576 | // stay inside the bounds (because we will mainly use this table for the multiplication of
|
577 | // two GF numbers, no more).
|
578 | // @see {@link mul}
|
579 | for (i = 255; i < 512; i++) {
|
580 | EXP_TABLE[i] = EXP_TABLE[i - 255]
|
581 | }
|
582 | }())
|
583 |
|
584 | /**
|
585 | * Returns log value of n inside Galois Field
|
586 | *
|
587 | * @param {Number} n
|
588 | * @return {Number}
|
589 | */
|
590 | exports.log = function log (n) {
|
591 | if (n < 1) throw new Error('log(' + n + ')')
|
592 | return LOG_TABLE[n]
|
593 | }
|
594 |
|
595 | /**
|
596 | * Returns anti-log value of n inside Galois Field
|
597 | *
|
598 | * @param {Number} n
|
599 | * @return {Number}
|
600 | */
|
601 | exports.exp = function exp (n) {
|
602 | return EXP_TABLE[n]
|
603 | }
|
604 |
|
605 | /**
|
606 | * Multiplies two number inside Galois Field
|
607 | *
|
608 | * @param {Number} x
|
609 | * @param {Number} y
|
610 | * @return {Number}
|
611 | */
|
612 | exports.mul = function mul (x, y) {
|
613 | if (x === 0 || y === 0) return 0
|
614 |
|
615 | // should be EXP_TABLE[(LOG_TABLE[x] + LOG_TABLE[y]) % 255] if EXP_TABLE wasn't oversized
|
616 | // @see {@link initTables}
|
617 | return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]]
|
618 | }
|
619 |
|
620 | },{"../utils/buffer":28}],12:[function(require,module,exports){
|
621 | var Mode = require('./mode')
|
622 | var Utils = require('./utils')
|
623 |
|
624 | function KanjiData (data) {
|
625 | this.mode = Mode.KANJI
|
626 | this.data = data
|
627 | }
|
628 |
|
629 | KanjiData.getBitsLength = function getBitsLength (length) {
|
630 | return length * 13
|
631 | }
|
632 |
|
633 | KanjiData.prototype.getLength = function getLength () {
|
634 | return this.data.length
|
635 | }
|
636 |
|
637 | KanjiData.prototype.getBitsLength = function getBitsLength () {
|
638 | return KanjiData.getBitsLength(this.data.length)
|
639 | }
|
640 |
|
641 | KanjiData.prototype.write = function (bitBuffer) {
|
642 | var i
|
643 |
|
644 | // In the Shift JIS system, Kanji characters are represented by a two byte combination.
|
645 | // These byte values are shifted from the JIS X 0208 values.
|
646 | // JIS X 0208 gives details of the shift coded representation.
|
647 | for (i = 0; i < this.data.length; i++) {
|
648 | var value = Utils.toSJIS(this.data[i])
|
649 |
|
650 | // For characters with Shift JIS values from 0x8140 to 0x9FFC:
|
651 | if (value >= 0x8140 && value <= 0x9FFC) {
|
652 | // Subtract 0x8140 from Shift JIS value
|
653 | value -= 0x8140
|
654 |
|
655 | // For characters with Shift JIS values from 0xE040 to 0xEBBF
|
656 | } else if (value >= 0xE040 && value <= 0xEBBF) {
|
657 | // Subtract 0xC140 from Shift JIS value
|
658 | value -= 0xC140
|
659 | } else {
|
660 | throw new Error(
|
661 | 'Invalid SJIS character: ' + this.data[i] + '\n' +
|
662 | 'Make sure your charset is UTF-8')
|
663 | }
|
664 |
|
665 | // Multiply most significant byte of result by 0xC0
|
666 | // and add least significant byte to product
|
667 | value = (((value >>> 8) & 0xff) * 0xC0) + (value & 0xff)
|
668 |
|
669 | // Convert result to a 13-bit binary string
|
670 | bitBuffer.put(value, 13)
|
671 | }
|
672 | }
|
673 |
|
674 | module.exports = KanjiData
|
675 |
|
676 | },{"./mode":14,"./utils":21}],13:[function(require,module,exports){
|
677 | /**
|
678 | * Data mask pattern reference
|
679 | * @type {Object}
|
680 | */
|
681 | exports.Patterns = {
|
682 | PATTERN000: 0,
|
683 | PATTERN001: 1,
|
684 | PATTERN010: 2,
|
685 | PATTERN011: 3,
|
686 | PATTERN100: 4,
|
687 | PATTERN101: 5,
|
688 | PATTERN110: 6,
|
689 | PATTERN111: 7
|
690 | }
|
691 |
|
692 | /**
|
693 | * Weighted penalty scores for the undesirable features
|
694 | * @type {Object}
|
695 | */
|
696 | var PenaltyScores = {
|
697 | N1: 3,
|
698 | N2: 3,
|
699 | N3: 40,
|
700 | N4: 10
|
701 | }
|
702 |
|
703 | /**
|
704 | * Check if mask pattern value is valid
|
705 | *
|
706 | * @param {Number} mask Mask pattern
|
707 | * @return {Boolean} true if valid, false otherwise
|
708 | */
|
709 | exports.isValid = function isValid (mask) {
|
710 | return mask != null && mask !== '' && !isNaN(mask) && mask >= 0 && mask <= 7
|
711 | }
|
712 |
|
713 | /**
|
714 | * Returns mask pattern from a value.
|
715 | * If value is not valid, returns undefined
|
716 | *
|
717 | * @param {Number|String} value Mask pattern value
|
718 | * @return {Number} Valid mask pattern or undefined
|
719 | */
|
720 | exports.from = function from (value) {
|
721 | return exports.isValid(value) ? parseInt(value, 10) : undefined
|
722 | }
|
723 |
|
724 | /**
|
725 | * Find adjacent modules in row/column with the same color
|
726 | * and assign a penalty value.
|
727 | *
|
728 | * Points: N1 + i
|
729 | * i is the amount by which the number of adjacent modules of the same color exceeds 5
|
730 | */
|
731 | exports.getPenaltyN1 = function getPenaltyN1 (data) {
|
732 | var size = data.size
|
733 | var points = 0
|
734 | var sameCountCol = 0
|
735 | var sameCountRow = 0
|
736 | var lastCol = null
|
737 | var lastRow = null
|
738 |
|
739 | for (var row = 0; row < size; row++) {
|
740 | sameCountCol = sameCountRow = 0
|
741 | lastCol = lastRow = null
|
742 |
|
743 | for (var col = 0; col < size; col++) {
|
744 | var module = data.get(row, col)
|
745 | if (module === lastCol) {
|
746 | sameCountCol++
|
747 | } else {
|
748 | if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5)
|
749 | lastCol = module
|
750 | sameCountCol = 1
|
751 | }
|
752 |
|
753 | module = data.get(col, row)
|
754 | if (module === lastRow) {
|
755 | sameCountRow++
|
756 | } else {
|
757 | if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5)
|
758 | lastRow = module
|
759 | sameCountRow = 1
|
760 | }
|
761 | }
|
762 |
|
763 | if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5)
|
764 | if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5)
|
765 | }
|
766 |
|
767 | return points
|
768 | }
|
769 |
|
770 | /**
|
771 | * Find 2x2 blocks with the same color and assign a penalty value
|
772 | *
|
773 | * Points: N2 * (m - 1) * (n - 1)
|
774 | */
|
775 | exports.getPenaltyN2 = function getPenaltyN2 (data) {
|
776 | var size = data.size
|
777 | var points = 0
|
778 |
|
779 | for (var row = 0; row < size - 1; row++) {
|
780 | for (var col = 0; col < size - 1; col++) {
|
781 | var last = data.get(row, col) +
|
782 | data.get(row, col + 1) +
|
783 | data.get(row + 1, col) +
|
784 | data.get(row + 1, col + 1)
|
785 |
|
786 | if (last === 4 || last === 0) points++
|
787 | }
|
788 | }
|
789 |
|
790 | return points * PenaltyScores.N2
|
791 | }
|
792 |
|
793 | /**
|
794 | * Find 1:1:3:1:1 ratio (dark:light:dark:light:dark) pattern in row/column,
|
795 | * preceded or followed by light area 4 modules wide
|
796 | *
|
797 | * Points: N3 * number of pattern found
|
798 | */
|
799 | exports.getPenaltyN3 = function getPenaltyN3 (data) {
|
800 | var size = data.size
|
801 | var points = 0
|
802 | var bitsCol = 0
|
803 | var bitsRow = 0
|
804 |
|
805 | for (var row = 0; row < size; row++) {
|
806 | bitsCol = bitsRow = 0
|
807 | for (var col = 0; col < size; col++) {
|
808 | bitsCol = ((bitsCol << 1) & 0x7FF) | data.get(row, col)
|
809 | if (col >= 10 && (bitsCol === 0x5D0 || bitsCol === 0x05D)) points++
|
810 |
|
811 | bitsRow = ((bitsRow << 1) & 0x7FF) | data.get(col, row)
|
812 | if (col >= 10 && (bitsRow === 0x5D0 || bitsRow === 0x05D)) points++
|
813 | }
|
814 | }
|
815 |
|
816 | return points * PenaltyScores.N3
|
817 | }
|
818 |
|
819 | /**
|
820 | * Calculate proportion of dark modules in entire symbol
|
821 | *
|
822 | * Points: N4 * k
|
823 | *
|
824 | * k is the rating of the deviation of the proportion of dark modules
|
825 | * in the symbol from 50% in steps of 5%
|
826 | */
|
827 | exports.getPenaltyN4 = function getPenaltyN4 (data) {
|
828 | var darkCount = 0
|
829 | var modulesCount = data.data.length
|
830 |
|
831 | for (var i = 0; i < modulesCount; i++) darkCount += data.data[i]
|
832 |
|
833 | var k = Math.abs(Math.ceil((darkCount * 100 / modulesCount) / 5) - 10)
|
834 |
|
835 | return k * PenaltyScores.N4
|
836 | }
|
837 |
|
838 | /**
|
839 | * Return mask value at given position
|
840 | *
|
841 | * @param {Number} maskPattern Pattern reference value
|
842 | * @param {Number} i Row
|
843 | * @param {Number} j Column
|
844 | * @return {Boolean} Mask value
|
845 | */
|
846 | function getMaskAt (maskPattern, i, j) {
|
847 | switch (maskPattern) {
|
848 | case exports.Patterns.PATTERN000: return (i + j) % 2 === 0
|
849 | case exports.Patterns.PATTERN001: return i % 2 === 0
|
850 | case exports.Patterns.PATTERN010: return j % 3 === 0
|
851 | case exports.Patterns.PATTERN011: return (i + j) % 3 === 0
|
852 | case exports.Patterns.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0
|
853 | case exports.Patterns.PATTERN101: return (i * j) % 2 + (i * j) % 3 === 0
|
854 | case exports.Patterns.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 === 0
|
855 | case exports.Patterns.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 === 0
|
856 |
|
857 | default: throw new Error('bad maskPattern:' + maskPattern)
|
858 | }
|
859 | }
|
860 |
|
861 | /**
|
862 | * Apply a mask pattern to a BitMatrix
|
863 | *
|
864 | * @param {Number} pattern Pattern reference number
|
865 | * @param {BitMatrix} data BitMatrix data
|
866 | */
|
867 | exports.applyMask = function applyMask (pattern, data) {
|
868 | var size = data.size
|
869 |
|
870 | for (var col = 0; col < size; col++) {
|
871 | for (var row = 0; row < size; row++) {
|
872 | if (data.isReserved(row, col)) continue
|
873 | data.xor(row, col, getMaskAt(pattern, row, col))
|
874 | }
|
875 | }
|
876 | }
|
877 |
|
878 | /**
|
879 | * Returns the best mask pattern for data
|
880 | *
|
881 | * @param {BitMatrix} data
|
882 | * @return {Number} Mask pattern reference number
|
883 | */
|
884 | exports.getBestMask = function getBestMask (data, setupFormatFunc) {
|
885 | var numPatterns = Object.keys(exports.Patterns).length
|
886 | var bestPattern = 0
|
887 | var lowerPenalty = Infinity
|
888 |
|
889 | for (var p = 0; p < numPatterns; p++) {
|
890 | setupFormatFunc(p)
|
891 | exports.applyMask(p, data)
|
892 |
|
893 | // Calculate penalty
|
894 | var penalty =
|
895 | exports.getPenaltyN1(data) +
|
896 | exports.getPenaltyN2(data) +
|
897 | exports.getPenaltyN3(data) +
|
898 | exports.getPenaltyN4(data)
|
899 |
|
900 | // Undo previously applied mask
|
901 | exports.applyMask(p, data)
|
902 |
|
903 | if (penalty < lowerPenalty) {
|
904 | lowerPenalty = penalty
|
905 | bestPattern = p
|
906 | }
|
907 | }
|
908 |
|
909 | return bestPattern
|
910 | }
|
911 |
|
912 | },{}],14:[function(require,module,exports){
|
913 | var VersionCheck = require('./version-check')
|
914 | var Regex = require('./regex')
|
915 |
|
916 | /**
|
917 | * Numeric mode encodes data from the decimal digit set (0 - 9)
|
918 | * (byte values 30HEX to 39HEX).
|
919 | * Normally, 3 data characters are represented by 10 bits.
|
920 | *
|
921 | * @type {Object}
|
922 | */
|
923 | exports.NUMERIC = {
|
924 | id: 'Numeric',
|
925 | bit: 1 << 0,
|
926 | ccBits: [10, 12, 14]
|
927 | }
|
928 |
|
929 | /**
|
930 | * Alphanumeric mode encodes data from a set of 45 characters,
|
931 | * i.e. 10 numeric digits (0 - 9),
|
932 | * 26 alphabetic characters (A - Z),
|
933 | * and 9 symbols (SP, $, %, *, +, -, ., /, :).
|
934 | * Normally, two input characters are represented by 11 bits.
|
935 | *
|
936 | * @type {Object}
|
937 | */
|
938 | exports.ALPHANUMERIC = {
|
939 | id: 'Alphanumeric',
|
940 | bit: 1 << 1,
|
941 | ccBits: [9, 11, 13]
|
942 | }
|
943 |
|
944 | /**
|
945 | * In byte mode, data is encoded at 8 bits per character.
|
946 | *
|
947 | * @type {Object}
|
948 | */
|
949 | exports.BYTE = {
|
950 | id: 'Byte',
|
951 | bit: 1 << 2,
|
952 | ccBits: [8, 16, 16]
|
953 | }
|
954 |
|
955 | /**
|
956 | * The Kanji mode efficiently encodes Kanji characters in accordance with
|
957 | * the Shift JIS system based on JIS X 0208.
|
958 | * The Shift JIS values are shifted from the JIS X 0208 values.
|
959 | * JIS X 0208 gives details of the shift coded representation.
|
960 | * Each two-byte character value is compacted to a 13-bit binary codeword.
|
961 | *
|
962 | * @type {Object}
|
963 | */
|
964 | exports.KANJI = {
|
965 | id: 'Kanji',
|
966 | bit: 1 << 3,
|
967 | ccBits: [8, 10, 12]
|
968 | }
|
969 |
|
970 | /**
|
971 | * Mixed mode will contain a sequences of data in a combination of any of
|
972 | * the modes described above
|
973 | *
|
974 | * @type {Object}
|
975 | */
|
976 | exports.MIXED = {
|
977 | bit: -1
|
978 | }
|
979 |
|
980 | /**
|
981 | * Returns the number of bits needed to store the data length
|
982 | * according to QR Code specifications.
|
983 | *
|
984 | * @param {Mode} mode Data mode
|
985 | * @param {Number} version QR Code version
|
986 | * @return {Number} Number of bits
|
987 | */
|
988 | exports.getCharCountIndicator = function getCharCountIndicator (mode, version) {
|
989 | if (!mode.ccBits) throw new Error('Invalid mode: ' + mode)
|
990 |
|
991 | if (!VersionCheck.isValid(version)) {
|
992 | throw new Error('Invalid version: ' + version)
|
993 | }
|
994 |
|
995 | if (version >= 1 && version < 10) return mode.ccBits[0]
|
996 | else if (version < 27) return mode.ccBits[1]
|
997 | return mode.ccBits[2]
|
998 | }
|
999 |
|
1000 | /**
|
1001 | * Returns the most efficient mode to store the specified data
|
1002 | *
|
1003 | * @param {String} dataStr Input data string
|
1004 | * @return {Mode} Best mode
|
1005 | */
|
1006 | exports.getBestModeForData = function getBestModeForData (dataStr) {
|
1007 | if (Regex.testNumeric(dataStr)) return exports.NUMERIC
|
1008 | else if (Regex.testAlphanumeric(dataStr)) return exports.ALPHANUMERIC
|
1009 | else if (Regex.testKanji(dataStr)) return exports.KANJI
|
1010 | else return exports.BYTE
|
1011 | }
|
1012 |
|
1013 | /**
|
1014 | * Return mode name as string
|
1015 | *
|
1016 | * @param {Mode} mode Mode object
|
1017 | * @returns {String} Mode name
|
1018 | */
|
1019 | exports.toString = function toString (mode) {
|
1020 | if (mode && mode.id) return mode.id
|
1021 | throw new Error('Invalid mode')
|
1022 | }
|
1023 |
|
1024 | /**
|
1025 | * Check if input param is a valid mode object
|
1026 | *
|
1027 | * @param {Mode} mode Mode object
|
1028 | * @returns {Boolean} True if valid mode, false otherwise
|
1029 | */
|
1030 | exports.isValid = function isValid (mode) {
|
1031 | return mode && mode.bit && mode.ccBits
|
1032 | }
|
1033 |
|
1034 | /**
|
1035 | * Get mode object from its name
|
1036 | *
|
1037 | * @param {String} string Mode name
|
1038 | * @returns {Mode} Mode object
|
1039 | */
|
1040 | function fromString (string) {
|
1041 | if (typeof string !== 'string') {
|
1042 | throw new Error('Param is not a string')
|
1043 | }
|
1044 |
|
1045 | var lcStr = string.toLowerCase()
|
1046 |
|
1047 | switch (lcStr) {
|
1048 | case 'numeric':
|
1049 | return exports.NUMERIC
|
1050 | case 'alphanumeric':
|
1051 | return exports.ALPHANUMERIC
|
1052 | case 'kanji':
|
1053 | return exports.KANJI
|
1054 | case 'byte':
|
1055 | return exports.BYTE
|
1056 | default:
|
1057 | throw new Error('Unknown mode: ' + string)
|
1058 | }
|
1059 | }
|
1060 |
|
1061 | /**
|
1062 | * Returns mode from a value.
|
1063 | * If value is not a valid mode, returns defaultValue
|
1064 | *
|
1065 | * @param {Mode|String} value Encoding mode
|
1066 | * @param {Mode} defaultValue Fallback value
|
1067 | * @return {Mode} Encoding mode
|
1068 | */
|
1069 | exports.from = function from (value, defaultValue) {
|
1070 | if (exports.isValid(value)) {
|
1071 | return value
|
1072 | }
|
1073 |
|
1074 | try {
|
1075 | return fromString(value)
|
1076 | } catch (e) {
|
1077 | return defaultValue
|
1078 | }
|
1079 | }
|
1080 |
|
1081 | },{"./regex":19,"./version-check":22}],15:[function(require,module,exports){
|
1082 | var Mode = require('./mode')
|
1083 |
|
1084 | function NumericData (data) {
|
1085 | this.mode = Mode.NUMERIC
|
1086 | this.data = data.toString()
|
1087 | }
|
1088 |
|
1089 | NumericData.getBitsLength = function getBitsLength (length) {
|
1090 | return 10 * Math.floor(length / 3) + ((length % 3) ? ((length % 3) * 3 + 1) : 0)
|
1091 | }
|
1092 |
|
1093 | NumericData.prototype.getLength = function getLength () {
|
1094 | return this.data.length
|
1095 | }
|
1096 |
|
1097 | NumericData.prototype.getBitsLength = function getBitsLength () {
|
1098 | return NumericData.getBitsLength(this.data.length)
|
1099 | }
|
1100 |
|
1101 | NumericData.prototype.write = function write (bitBuffer) {
|
1102 | var i, group, value
|
1103 |
|
1104 | // The input data string is divided into groups of three digits,
|
1105 | // and each group is converted to its 10-bit binary equivalent.
|
1106 | for (i = 0; i + 3 <= this.data.length; i += 3) {
|
1107 | group = this.data.substr(i, 3)
|
1108 | value = parseInt(group, 10)
|
1109 |
|
1110 | bitBuffer.put(value, 10)
|
1111 | }
|
1112 |
|
1113 | // If the number of input digits is not an exact multiple of three,
|
1114 | // the final one or two digits are converted to 4 or 7 bits respectively.
|
1115 | var remainingNum = this.data.length - i
|
1116 | if (remainingNum > 0) {
|
1117 | group = this.data.substr(i)
|
1118 | value = parseInt(group, 10)
|
1119 |
|
1120 | bitBuffer.put(value, remainingNum * 3 + 1)
|
1121 | }
|
1122 | }
|
1123 |
|
1124 | module.exports = NumericData
|
1125 |
|
1126 | },{"./mode":14}],16:[function(require,module,exports){
|
1127 | var Buffer = require('../utils/buffer')
|
1128 | var GF = require('./galois-field')
|
1129 |
|
1130 | /**
|
1131 | * Multiplies two polynomials inside Galois Field
|
1132 | *
|
1133 | * @param {Buffer} p1 Polynomial
|
1134 | * @param {Buffer} p2 Polynomial
|
1135 | * @return {Buffer} Product of p1 and p2
|
1136 | */
|
1137 | exports.mul = function mul (p1, p2) {
|
1138 | var coeff = new Buffer(p1.length + p2.length - 1)
|
1139 | coeff.fill(0)
|
1140 |
|
1141 | for (var i = 0; i < p1.length; i++) {
|
1142 | for (var j = 0; j < p2.length; j++) {
|
1143 | coeff[i + j] ^= GF.mul(p1[i], p2[j])
|
1144 | }
|
1145 | }
|
1146 |
|
1147 | return coeff
|
1148 | }
|
1149 |
|
1150 | /**
|
1151 | * Calculate the remainder of polynomials division
|
1152 | *
|
1153 | * @param {Buffer} divident Polynomial
|
1154 | * @param {Buffer} divisor Polynomial
|
1155 | * @return {Buffer} Remainder
|
1156 | */
|
1157 | exports.mod = function mod (divident, divisor) {
|
1158 | var result = new Buffer(divident)
|
1159 |
|
1160 | while ((result.length - divisor.length) >= 0) {
|
1161 | var coeff = result[0]
|
1162 |
|
1163 | for (var i = 0; i < divisor.length; i++) {
|
1164 | result[i] ^= GF.mul(divisor[i], coeff)
|
1165 | }
|
1166 |
|
1167 | // remove all zeros from buffer head
|
1168 | var offset = 0
|
1169 | while (offset < result.length && result[offset] === 0) offset++
|
1170 | result = result.slice(offset)
|
1171 | }
|
1172 |
|
1173 | return result
|
1174 | }
|
1175 |
|
1176 | /**
|
1177 | * Generate an irreducible generator polynomial of specified degree
|
1178 | * (used by Reed-Solomon encoder)
|
1179 | *
|
1180 | * @param {Number} degree Degree of the generator polynomial
|
1181 | * @return {Buffer} Buffer containing polynomial coefficients
|
1182 | */
|
1183 | exports.generateECPolynomial = function generateECPolynomial (degree) {
|
1184 | var poly = new Buffer([1])
|
1185 | for (var i = 0; i < degree; i++) {
|
1186 | poly = exports.mul(poly, [1, GF.exp(i)])
|
1187 | }
|
1188 |
|
1189 | return poly
|
1190 | }
|
1191 |
|
1192 | },{"../utils/buffer":28,"./galois-field":11}],17:[function(require,module,exports){
|
1193 | var Buffer = require('../utils/buffer')
|
1194 | var Utils = require('./utils')
|
1195 | var ECLevel = require('./error-correction-level')
|
1196 | var BitBuffer = require('./bit-buffer')
|
1197 | var BitMatrix = require('./bit-matrix')
|
1198 | var AlignmentPattern = require('./alignment-pattern')
|
1199 | var FinderPattern = require('./finder-pattern')
|
1200 | var MaskPattern = require('./mask-pattern')
|
1201 | var ECCode = require('./error-correction-code')
|
1202 | var ReedSolomonEncoder = require('./reed-solomon-encoder')
|
1203 | var Version = require('./version')
|
1204 | var FormatInfo = require('./format-info')
|
1205 | var Mode = require('./mode')
|
1206 | var Segments = require('./segments')
|
1207 | var isArray = require('isarray')
|
1208 |
|
1209 | /**
|
1210 | * QRCode for JavaScript
|
1211 | *
|
1212 | * modified by Ryan Day for nodejs support
|
1213 | * Copyright (c) 2011 Ryan Day
|
1214 | *
|
1215 | * Licensed under the MIT license:
|
1216 | * http://www.opensource.org/licenses/mit-license.php
|
1217 | *
|
1218 | //---------------------------------------------------------------------
|
1219 | // QRCode for JavaScript
|
1220 | //
|
1221 | // Copyright (c) 2009 Kazuhiko Arase
|
1222 | //
|
1223 | // URL: http://www.d-project.com/
|
1224 | //
|
1225 | // Licensed under the MIT license:
|
1226 | // http://www.opensource.org/licenses/mit-license.php
|
1227 | //
|
1228 | // The word "QR Code" is registered trademark of
|
1229 | // DENSO WAVE INCORPORATED
|
1230 | // http://www.denso-wave.com/qrcode/faqpatent-e.html
|
1231 | //
|
1232 | //---------------------------------------------------------------------
|
1233 | */
|
1234 |
|
1235 | /**
|
1236 | * Add finder patterns bits to matrix
|
1237 | *
|
1238 | * @param {BitMatrix} matrix Modules matrix
|
1239 | * @param {Number} version QR Code version
|
1240 | */
|
1241 | function setupFinderPattern (matrix, version) {
|
1242 | var size = matrix.size
|
1243 | var pos = FinderPattern.getPositions(version)
|
1244 |
|
1245 | for (var i = 0; i < pos.length; i++) {
|
1246 | var row = pos[i][0]
|
1247 | var col = pos[i][1]
|
1248 |
|
1249 | for (var r = -1; r <= 7; r++) {
|
1250 | if (row + r <= -1 || size <= row + r) continue
|
1251 |
|
1252 | for (var c = -1; c <= 7; c++) {
|
1253 | if (col + c <= -1 || size <= col + c) continue
|
1254 |
|
1255 | if ((r >= 0 && r <= 6 && (c === 0 || c === 6)) ||
|
1256 | (c >= 0 && c <= 6 && (r === 0 || r === 6)) ||
|
1257 | (r >= 2 && r <= 4 && c >= 2 && c <= 4)) {
|
1258 | matrix.set(row + r, col + c, true, true)
|
1259 | } else {
|
1260 | matrix.set(row + r, col + c, false, true)
|
1261 | }
|
1262 | }
|
1263 | }
|
1264 | }
|
1265 | }
|
1266 |
|
1267 | /**
|
1268 | * Add timing pattern bits to matrix
|
1269 | *
|
1270 | * Note: this function must be called before {@link setupAlignmentPattern}
|
1271 | *
|
1272 | * @param {BitMatrix} matrix Modules matrix
|
1273 | */
|
1274 | function setupTimingPattern (matrix) {
|
1275 | var size = matrix.size
|
1276 |
|
1277 | for (var r = 8; r < size - 8; r++) {
|
1278 | var value = r % 2 === 0
|
1279 | matrix.set(r, 6, value, true)
|
1280 | matrix.set(6, r, value, true)
|
1281 | }
|
1282 | }
|
1283 |
|
1284 | /**
|
1285 | * Add alignment patterns bits to matrix
|
1286 | *
|
1287 | * Note: this function must be called after {@link setupTimingPattern}
|
1288 | *
|
1289 | * @param {BitMatrix} matrix Modules matrix
|
1290 | * @param {Number} version QR Code version
|
1291 | */
|
1292 | function setupAlignmentPattern (matrix, version) {
|
1293 | var pos = AlignmentPattern.getPositions(version)
|
1294 |
|
1295 | for (var i = 0; i < pos.length; i++) {
|
1296 | var row = pos[i][0]
|
1297 | var col = pos[i][1]
|
1298 |
|
1299 | for (var r = -2; r <= 2; r++) {
|
1300 | for (var c = -2; c <= 2; c++) {
|
1301 | if (r === -2 || r === 2 || c === -2 || c === 2 ||
|
1302 | (r === 0 && c === 0)) {
|
1303 | matrix.set(row + r, col + c, true, true)
|
1304 | } else {
|
1305 | matrix.set(row + r, col + c, false, true)
|
1306 | }
|
1307 | }
|
1308 | }
|
1309 | }
|
1310 | }
|
1311 |
|
1312 | /**
|
1313 | * Add version info bits to matrix
|
1314 | *
|
1315 | * @param {BitMatrix} matrix Modules matrix
|
1316 | * @param {Number} version QR Code version
|
1317 | */
|
1318 | function setupVersionInfo (matrix, version) {
|
1319 | var size = matrix.size
|
1320 | var bits = Version.getEncodedBits(version)
|
1321 | var row, col, mod
|
1322 |
|
1323 | for (var i = 0; i < 18; i++) {
|
1324 | row = Math.floor(i / 3)
|
1325 | col = i % 3 + size - 8 - 3
|
1326 | mod = ((bits >> i) & 1) === 1
|
1327 |
|
1328 | matrix.set(row, col, mod, true)
|
1329 | matrix.set(col, row, mod, true)
|
1330 | }
|
1331 | }
|
1332 |
|
1333 | /**
|
1334 | * Add format info bits to matrix
|
1335 | *
|
1336 | * @param {BitMatrix} matrix Modules matrix
|
1337 | * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level
|
1338 | * @param {Number} maskPattern Mask pattern reference value
|
1339 | */
|
1340 | function setupFormatInfo (matrix, errorCorrectionLevel, maskPattern) {
|
1341 | var size = matrix.size
|
1342 | var bits = FormatInfo.getEncodedBits(errorCorrectionLevel, maskPattern)
|
1343 | var i, mod
|
1344 |
|
1345 | for (i = 0; i < 15; i++) {
|
1346 | mod = ((bits >> i) & 1) === 1
|
1347 |
|
1348 | // vertical
|
1349 | if (i < 6) {
|
1350 | matrix.set(i, 8, mod, true)
|
1351 | } else if (i < 8) {
|
1352 | matrix.set(i + 1, 8, mod, true)
|
1353 | } else {
|
1354 | matrix.set(size - 15 + i, 8, mod, true)
|
1355 | }
|
1356 |
|
1357 | // horizontal
|
1358 | if (i < 8) {
|
1359 | matrix.set(8, size - i - 1, mod, true)
|
1360 | } else if (i < 9) {
|
1361 | matrix.set(8, 15 - i - 1 + 1, mod, true)
|
1362 | } else {
|
1363 | matrix.set(8, 15 - i - 1, mod, true)
|
1364 | }
|
1365 | }
|
1366 |
|
1367 | // fixed module
|
1368 | matrix.set(size - 8, 8, 1, true)
|
1369 | }
|
1370 |
|
1371 | /**
|
1372 | * Add encoded data bits to matrix
|
1373 | *
|
1374 | * @param {BitMatrix} matrix Modules matrix
|
1375 | * @param {Buffer} data Data codewords
|
1376 | */
|
1377 | function setupData (matrix, data) {
|
1378 | var size = matrix.size
|
1379 | var inc = -1
|
1380 | var row = size - 1
|
1381 | var bitIndex = 7
|
1382 | var byteIndex = 0
|
1383 |
|
1384 | for (var col = size - 1; col > 0; col -= 2) {
|
1385 | if (col === 6) col--
|
1386 |
|
1387 | while (true) {
|
1388 | for (var c = 0; c < 2; c++) {
|
1389 | if (!matrix.isReserved(row, col - c)) {
|
1390 | var dark = false
|
1391 |
|
1392 | if (byteIndex < data.length) {
|
1393 | dark = (((data[byteIndex] >>> bitIndex) & 1) === 1)
|
1394 | }
|
1395 |
|
1396 | matrix.set(row, col - c, dark)
|
1397 | bitIndex--
|
1398 |
|
1399 | if (bitIndex === -1) {
|
1400 | byteIndex++
|
1401 | bitIndex = 7
|
1402 | }
|
1403 | }
|
1404 | }
|
1405 |
|
1406 | row += inc
|
1407 |
|
1408 | if (row < 0 || size <= row) {
|
1409 | row -= inc
|
1410 | inc = -inc
|
1411 | break
|
1412 | }
|
1413 | }
|
1414 | }
|
1415 | }
|
1416 |
|
1417 | /**
|
1418 | * Create encoded codewords from data input
|
1419 | *
|
1420 | * @param {Number} version QR Code version
|
1421 | * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level
|
1422 | * @param {ByteData} data Data input
|
1423 | * @return {Buffer} Buffer containing encoded codewords
|
1424 | */
|
1425 | function createData (version, errorCorrectionLevel, segments) {
|
1426 | // Prepare data buffer
|
1427 | var buffer = new BitBuffer()
|
1428 |
|
1429 | segments.forEach(function (data) {
|
1430 | // prefix data with mode indicator (4 bits)
|
1431 | buffer.put(data.mode.bit, 4)
|
1432 |
|
1433 | // Prefix data with character count indicator.
|
1434 | // The character count indicator is a string of bits that represents the
|
1435 | // number of characters that are being encoded.
|
1436 | // The character count indicator must be placed after the mode indicator
|
1437 | // and must be a certain number of bits long, depending on the QR version
|
1438 | // and data mode
|
1439 | // @see {@link Mode.getCharCountIndicator}.
|
1440 | buffer.put(data.getLength(), Mode.getCharCountIndicator(data.mode, version))
|
1441 |
|
1442 | // add binary data sequence to buffer
|
1443 | data.write(buffer)
|
1444 | })
|
1445 |
|
1446 | // Calculate required number of bits
|
1447 | var totalCodewords = Utils.getSymbolTotalCodewords(version)
|
1448 | var ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel)
|
1449 | var dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8
|
1450 |
|
1451 | // Add a terminator.
|
1452 | // If the bit string is shorter than the total number of required bits,
|
1453 | // a terminator of up to four 0s must be added to the right side of the string.
|
1454 | // If the bit string is more than four bits shorter than the required number of bits,
|
1455 | // add four 0s to the end.
|
1456 | if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) {
|
1457 | buffer.put(0, 4)
|
1458 | }
|
1459 |
|
1460 | // If the bit string is fewer than four bits shorter, add only the number of 0s that
|
1461 | // are needed to reach the required number of bits.
|
1462 |
|
1463 | // After adding the terminator, if the number of bits in the string is not a multiple of 8,
|
1464 | // pad the string on the right with 0s to make the string's length a multiple of 8.
|
1465 | while (buffer.getLengthInBits() % 8 !== 0) {
|
1466 | buffer.putBit(0)
|
1467 | }
|
1468 |
|
1469 | // Add pad bytes if the string is still shorter than the total number of required bits.
|
1470 | // Extend the buffer to fill the data capacity of the symbol corresponding to
|
1471 | // the Version and Error Correction Level by adding the Pad Codewords 11101100 (0xEC)
|
1472 | // and 00010001 (0x11) alternately.
|
1473 | var remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8
|
1474 | for (var i = 0; i < remainingByte; i++) {
|
1475 | buffer.put(i % 2 ? 0x11 : 0xEC, 8)
|
1476 | }
|
1477 |
|
1478 | return createCodewords(buffer, version, errorCorrectionLevel)
|
1479 | }
|
1480 |
|
1481 | /**
|
1482 | * Encode input data with Reed-Solomon and return codewords with
|
1483 | * relative error correction bits
|
1484 | *
|
1485 | * @param {BitBuffer} bitBuffer Data to encode
|
1486 | * @param {Number} version QR Code version
|
1487 | * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level
|
1488 | * @return {Buffer} Buffer containing encoded codewords
|
1489 | */
|
1490 | function createCodewords (bitBuffer, version, errorCorrectionLevel) {
|
1491 | // Total codewords for this QR code version (Data + Error correction)
|
1492 | var totalCodewords = Utils.getSymbolTotalCodewords(version)
|
1493 |
|
1494 | // Total number of error correction codewords
|
1495 | var ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel)
|
1496 |
|
1497 | // Total number of data codewords
|
1498 | var dataTotalCodewords = totalCodewords - ecTotalCodewords
|
1499 |
|
1500 | // Total number of blocks
|
1501 | var ecTotalBlocks = ECCode.getBlocksCount(version, errorCorrectionLevel)
|
1502 |
|
1503 | // Calculate how many blocks each group should contain
|
1504 | var blocksInGroup2 = totalCodewords % ecTotalBlocks
|
1505 | var blocksInGroup1 = ecTotalBlocks - blocksInGroup2
|
1506 |
|
1507 | var totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks)
|
1508 |
|
1509 | var dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks)
|
1510 | var dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1
|
1511 |
|
1512 | // Number of EC codewords is the same for both groups
|
1513 | var ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1
|
1514 |
|
1515 | // Initialize a Reed-Solomon encoder with a generator polynomial of degree ecCount
|
1516 | var rs = new ReedSolomonEncoder(ecCount)
|
1517 |
|
1518 | var offset = 0
|
1519 | var dcData = new Array(ecTotalBlocks)
|
1520 | var ecData = new Array(ecTotalBlocks)
|
1521 | var maxDataSize = 0
|
1522 | var buffer = new Buffer(bitBuffer.buffer)
|
1523 |
|
1524 | // Divide the buffer into the required number of blocks
|
1525 | for (var b = 0; b < ecTotalBlocks; b++) {
|
1526 | var dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2
|
1527 |
|
1528 | // extract a block of data from buffer
|
1529 | dcData[b] = buffer.slice(offset, offset + dataSize)
|
1530 |
|
1531 | // Calculate EC codewords for this data block
|
1532 | ecData[b] = rs.encode(dcData[b])
|
1533 |
|
1534 | offset += dataSize
|
1535 | maxDataSize = Math.max(maxDataSize, dataSize)
|
1536 | }
|
1537 |
|
1538 | // Create final data
|
1539 | // Interleave the data and error correction codewords from each block
|
1540 | var data = new Buffer(totalCodewords)
|
1541 | var index = 0
|
1542 | var i, r
|
1543 |
|
1544 | // Add data codewords
|
1545 | for (i = 0; i < maxDataSize; i++) {
|
1546 | for (r = 0; r < ecTotalBlocks; r++) {
|
1547 | if (i < dcData[r].length) {
|
1548 | data[index++] = dcData[r][i]
|
1549 | }
|
1550 | }
|
1551 | }
|
1552 |
|
1553 | // Apped EC codewords
|
1554 | for (i = 0; i < ecCount; i++) {
|
1555 | for (r = 0; r < ecTotalBlocks; r++) {
|
1556 | data[index++] = ecData[r][i]
|
1557 | }
|
1558 | }
|
1559 |
|
1560 | return data
|
1561 | }
|
1562 |
|
1563 | /**
|
1564 | * Build QR Code symbol
|
1565 | *
|
1566 | * @param {String} data Input string
|
1567 | * @param {Number} version QR Code version
|
1568 | * @param {ErrorCorretionLevel} errorCorrectionLevel Error level
|
1569 | * @param {MaskPattern} maskPattern Mask pattern
|
1570 | * @return {Object} Object containing symbol data
|
1571 | */
|
1572 | function createSymbol (data, version, errorCorrectionLevel, maskPattern) {
|
1573 | var segments
|
1574 |
|
1575 | if (isArray(data)) {
|
1576 | segments = Segments.fromArray(data)
|
1577 | } else if (typeof data === 'string') {
|
1578 | var estimatedVersion = version
|
1579 |
|
1580 | if (!estimatedVersion) {
|
1581 | var rawSegments = Segments.rawSplit(data)
|
1582 |
|
1583 | // Estimate best version that can contain raw splitted segments
|
1584 | estimatedVersion = Version.getBestVersionForData(rawSegments,
|
1585 | errorCorrectionLevel)
|
1586 | }
|
1587 |
|
1588 | // Build optimized segments
|
1589 | // If estimated version is undefined, try with the highest version
|
1590 | segments = Segments.fromString(data, estimatedVersion || 40)
|
1591 | } else {
|
1592 | throw new Error('Invalid data')
|
1593 | }
|
1594 |
|
1595 | // Get the min version that can contain data
|
1596 | var bestVersion = Version.getBestVersionForData(segments,
|
1597 | errorCorrectionLevel)
|
1598 |
|
1599 | // If no version is found, data cannot be stored
|
1600 | if (!bestVersion) {
|
1601 | throw new Error('The amount of data is too big to be stored in a QR Code')
|
1602 | }
|
1603 |
|
1604 | // If not specified, use min version as default
|
1605 | if (!version) {
|
1606 | version = bestVersion
|
1607 |
|
1608 | // Check if the specified version can contain the data
|
1609 | } else if (version < bestVersion) {
|
1610 | throw new Error('\n' +
|
1611 | 'The chosen QR Code version cannot contain this amount of data.\n' +
|
1612 | 'Minimum version required to store current data is: ' + bestVersion + '.\n'
|
1613 | )
|
1614 | }
|
1615 |
|
1616 | var dataBits = createData(version, errorCorrectionLevel, segments)
|
1617 |
|
1618 | // Allocate matrix buffer
|
1619 | var moduleCount = Utils.getSymbolSize(version)
|
1620 | var modules = new BitMatrix(moduleCount)
|
1621 |
|
1622 | // Add function modules
|
1623 | setupFinderPattern(modules, version)
|
1624 | setupTimingPattern(modules)
|
1625 | setupAlignmentPattern(modules, version)
|
1626 |
|
1627 | // Add temporary dummy bits for format info just to set them as reserved.
|
1628 | // This is needed to prevent these bits from being masked by {@link MaskPattern.applyMask}
|
1629 | // since the masking operation must be performed only on the encoding region.
|
1630 | // These blocks will be replaced with correct values later in code.
|
1631 | setupFormatInfo(modules, errorCorrectionLevel, 0)
|
1632 |
|
1633 | if (version >= 7) {
|
1634 | setupVersionInfo(modules, version)
|
1635 | }
|
1636 |
|
1637 | // Add data codewords
|
1638 | setupData(modules, dataBits)
|
1639 |
|
1640 | if (isNaN(maskPattern)) {
|
1641 | // Find best mask pattern
|
1642 | maskPattern = MaskPattern.getBestMask(modules,
|
1643 | setupFormatInfo.bind(null, modules, errorCorrectionLevel))
|
1644 | }
|
1645 |
|
1646 | // Apply mask pattern
|
1647 | MaskPattern.applyMask(maskPattern, modules)
|
1648 |
|
1649 | // Replace format info bits with correct values
|
1650 | setupFormatInfo(modules, errorCorrectionLevel, maskPattern)
|
1651 |
|
1652 | return {
|
1653 | modules: modules,
|
1654 | version: version,
|
1655 | errorCorrectionLevel: errorCorrectionLevel,
|
1656 | maskPattern: maskPattern,
|
1657 | segments: segments
|
1658 | }
|
1659 | }
|
1660 |
|
1661 | /**
|
1662 | * QR Code
|
1663 | *
|
1664 | * @param {String | Array} data Input data
|
1665 | * @param {Object} options Optional configurations
|
1666 | * @param {Number} options.version QR Code version
|
1667 | * @param {String} options.errorCorrectionLevel Error correction level
|
1668 | * @param {Function} options.toSJISFunc Helper func to convert utf8 to sjis
|
1669 | */
|
1670 | exports.create = function create (data, options) {
|
1671 | if (typeof data === 'undefined' || data === '') {
|
1672 | throw new Error('No input text')
|
1673 | }
|
1674 |
|
1675 | var errorCorrectionLevel = ECLevel.M
|
1676 | var version
|
1677 | var mask
|
1678 |
|
1679 | if (typeof options !== 'undefined') {
|
1680 | // Use higher error correction level as default
|
1681 | errorCorrectionLevel = ECLevel.from(options.errorCorrectionLevel, ECLevel.M)
|
1682 | version = Version.from(options.version)
|
1683 | mask = MaskPattern.from(options.maskPattern)
|
1684 |
|
1685 | if (options.toSJISFunc) {
|
1686 | Utils.setToSJISFunction(options.toSJISFunc)
|
1687 | }
|
1688 | }
|
1689 |
|
1690 | return createSymbol(data, version, errorCorrectionLevel, mask)
|
1691 | }
|
1692 |
|
1693 | },{"../utils/buffer":28,"./alignment-pattern":2,"./bit-buffer":4,"./bit-matrix":5,"./error-correction-code":7,"./error-correction-level":8,"./finder-pattern":9,"./format-info":10,"./mask-pattern":13,"./mode":14,"./reed-solomon-encoder":18,"./segments":20,"./utils":21,"./version":23,"isarray":30}],18:[function(require,module,exports){
|
1694 | var Buffer = require('../utils/buffer')
|
1695 | var Polynomial = require('./polynomial')
|
1696 |
|
1697 | function ReedSolomonEncoder (degree) {
|
1698 | this.genPoly = undefined
|
1699 | this.degree = degree
|
1700 |
|
1701 | if (this.degree) this.initialize(this.degree)
|
1702 | }
|
1703 |
|
1704 | /**
|
1705 | * Initialize the encoder.
|
1706 | * The input param should correspond to the number of error correction codewords.
|
1707 | *
|
1708 | * @param {Number} degree
|
1709 | */
|
1710 | ReedSolomonEncoder.prototype.initialize = function initialize (degree) {
|
1711 | // create an irreducible generator polynomial
|
1712 | this.degree = degree
|
1713 | this.genPoly = Polynomial.generateECPolynomial(this.degree)
|
1714 | }
|
1715 |
|
1716 | /**
|
1717 | * Encodes a chunk of data
|
1718 | *
|
1719 | * @param {Buffer} data Buffer containing input data
|
1720 | * @return {Buffer} Buffer containing encoded data
|
1721 | */
|
1722 | ReedSolomonEncoder.prototype.encode = function encode (data) {
|
1723 | if (!this.genPoly) {
|
1724 | throw new Error('Encoder not initialized')
|
1725 | }
|
1726 |
|
1727 | // Calculate EC for this data block
|
1728 | // extends data size to data+genPoly size
|
1729 | var pad = new Buffer(this.degree)
|
1730 | pad.fill(0)
|
1731 | var paddedData = Buffer.concat([data, pad], data.length + this.degree)
|
1732 |
|
1733 | // The error correction codewords are the remainder after dividing the data codewords
|
1734 | // by a generator polynomial
|
1735 | var remainder = Polynomial.mod(paddedData, this.genPoly)
|
1736 |
|
1737 | // return EC data blocks (last n byte, where n is the degree of genPoly)
|
1738 | // If coefficients number in remainder are less than genPoly degree,
|
1739 | // pad with 0s to the left to reach the needed number of coefficients
|
1740 | var start = this.degree - remainder.length
|
1741 | if (start > 0) {
|
1742 | var buff = new Buffer(this.degree)
|
1743 | buff.fill(0)
|
1744 | remainder.copy(buff, start)
|
1745 |
|
1746 | return buff
|
1747 | }
|
1748 |
|
1749 | return remainder
|
1750 | }
|
1751 |
|
1752 | module.exports = ReedSolomonEncoder
|
1753 |
|
1754 | },{"../utils/buffer":28,"./polynomial":16}],19:[function(require,module,exports){
|
1755 | var numeric = '[0-9]+'
|
1756 | var alphanumeric = '[A-Z $%*+\\-./:]+'
|
1757 | var kanji = '(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|' +
|
1758 | '[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|' +
|
1759 | '[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|' +
|
1760 | '[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+'
|
1761 | kanji = kanji.replace(/u/g, '\\u')
|
1762 |
|
1763 | var byte = '(?:(?![A-Z0-9 $%*+\\-./:]|' + kanji + ')(?:.|[\r\n]))+'
|
1764 |
|
1765 | exports.KANJI = new RegExp(kanji, 'g')
|
1766 | exports.BYTE_KANJI = new RegExp('[^A-Z0-9 $%*+\\-./:]+', 'g')
|
1767 | exports.BYTE = new RegExp(byte, 'g')
|
1768 | exports.NUMERIC = new RegExp(numeric, 'g')
|
1769 | exports.ALPHANUMERIC = new RegExp(alphanumeric, 'g')
|
1770 |
|
1771 | var TEST_KANJI = new RegExp('^' + kanji + '$')
|
1772 | var TEST_NUMERIC = new RegExp('^' + numeric + '$')
|
1773 | var TEST_ALPHANUMERIC = new RegExp('^[A-Z0-9 $%*+\\-./:]+$')
|
1774 |
|
1775 | exports.testKanji = function testKanji (str) {
|
1776 | return TEST_KANJI.test(str)
|
1777 | }
|
1778 |
|
1779 | exports.testNumeric = function testNumeric (str) {
|
1780 | return TEST_NUMERIC.test(str)
|
1781 | }
|
1782 |
|
1783 | exports.testAlphanumeric = function testAlphanumeric (str) {
|
1784 | return TEST_ALPHANUMERIC.test(str)
|
1785 | }
|
1786 |
|
1787 | },{}],20:[function(require,module,exports){
|
1788 | var Mode = require('./mode')
|
1789 | var NumericData = require('./numeric-data')
|
1790 | var AlphanumericData = require('./alphanumeric-data')
|
1791 | var ByteData = require('./byte-data')
|
1792 | var KanjiData = require('./kanji-data')
|
1793 | var Regex = require('./regex')
|
1794 | var Utils = require('./utils')
|
1795 | var dijkstra = require('dijkstrajs')
|
1796 |
|
1797 | /**
|
1798 | * Returns UTF8 byte length
|
1799 | *
|
1800 | * @param {String} str Input string
|
1801 | * @return {Number} Number of byte
|
1802 | */
|
1803 | function getStringByteLength (str) {
|
1804 | return unescape(encodeURIComponent(str)).length
|
1805 | }
|
1806 |
|
1807 | /**
|
1808 | * Get a list of segments of the specified mode
|
1809 | * from a string
|
1810 | *
|
1811 | * @param {Mode} mode Segment mode
|
1812 | * @param {String} str String to process
|
1813 | * @return {Array} Array of object with segments data
|
1814 | */
|
1815 | function getSegments (regex, mode, str) {
|
1816 | var segments = []
|
1817 | var result
|
1818 |
|
1819 | while ((result = regex.exec(str)) !== null) {
|
1820 | segments.push({
|
1821 | data: result[0],
|
1822 | index: result.index,
|
1823 | mode: mode,
|
1824 | length: result[0].length
|
1825 | })
|
1826 | }
|
1827 |
|
1828 | return segments
|
1829 | }
|
1830 |
|
1831 | /**
|
1832 | * Extracts a series of segments with the appropriate
|
1833 | * modes from a string
|
1834 | *
|
1835 | * @param {String} dataStr Input string
|
1836 | * @return {Array} Array of object with segments data
|
1837 | */
|
1838 | function getSegmentsFromString (dataStr) {
|
1839 | var numSegs = getSegments(Regex.NUMERIC, Mode.NUMERIC, dataStr)
|
1840 | var alphaNumSegs = getSegments(Regex.ALPHANUMERIC, Mode.ALPHANUMERIC, dataStr)
|
1841 | var byteSegs
|
1842 | var kanjiSegs
|
1843 |
|
1844 | if (Utils.isKanjiModeEnabled()) {
|
1845 | byteSegs = getSegments(Regex.BYTE, Mode.BYTE, dataStr)
|
1846 | kanjiSegs = getSegments(Regex.KANJI, Mode.KANJI, dataStr)
|
1847 | } else {
|
1848 | byteSegs = getSegments(Regex.BYTE_KANJI, Mode.BYTE, dataStr)
|
1849 | kanjiSegs = []
|
1850 | }
|
1851 |
|
1852 | var segs = numSegs.concat(alphaNumSegs, byteSegs, kanjiSegs)
|
1853 |
|
1854 | return segs
|
1855 | .sort(function (s1, s2) {
|
1856 | return s1.index - s2.index
|
1857 | })
|
1858 | .map(function (obj) {
|
1859 | return {
|
1860 | data: obj.data,
|
1861 | mode: obj.mode,
|
1862 | length: obj.length
|
1863 | }
|
1864 | })
|
1865 | }
|
1866 |
|
1867 | /**
|
1868 | * Returns how many bits are needed to encode a string of
|
1869 | * specified length with the specified mode
|
1870 | *
|
1871 | * @param {Number} length String length
|
1872 | * @param {Mode} mode Segment mode
|
1873 | * @return {Number} Bit length
|
1874 | */
|
1875 | function getSegmentBitsLength (length, mode) {
|
1876 | switch (mode) {
|
1877 | case Mode.NUMERIC:
|
1878 | return NumericData.getBitsLength(length)
|
1879 | case Mode.ALPHANUMERIC:
|
1880 | return AlphanumericData.getBitsLength(length)
|
1881 | case Mode.KANJI:
|
1882 | return KanjiData.getBitsLength(length)
|
1883 | case Mode.BYTE:
|
1884 | return ByteData.getBitsLength(length)
|
1885 | }
|
1886 | }
|
1887 |
|
1888 | /**
|
1889 | * Merges adjacent segments which have the same mode
|
1890 | *
|
1891 | * @param {Array} segs Array of object with segments data
|
1892 | * @return {Array} Array of object with segments data
|
1893 | */
|
1894 | function mergeSegments (segs) {
|
1895 | return segs.reduce(function (acc, curr) {
|
1896 | var prevSeg = acc.length - 1 >= 0 ? acc[acc.length - 1] : null
|
1897 | if (prevSeg && prevSeg.mode === curr.mode) {
|
1898 | acc[acc.length - 1].data += curr.data
|
1899 | return acc
|
1900 | }
|
1901 |
|
1902 | acc.push(curr)
|
1903 | return acc
|
1904 | }, [])
|
1905 | }
|
1906 |
|
1907 | /**
|
1908 | * Generates a list of all possible nodes combination which
|
1909 | * will be used to build a segments graph.
|
1910 | *
|
1911 | * Nodes are divided by groups. Each group will contain a list of all the modes
|
1912 | * in which is possible to encode the given text.
|
1913 | *
|
1914 | * For example the text '12345' can be encoded as Numeric, Alphanumeric or Byte.
|
1915 | * The group for '12345' will contain then 3 objects, one for each
|
1916 | * possible encoding mode.
|
1917 | *
|
1918 | * Each node represents a possible segment.
|
1919 | *
|
1920 | * @param {Array} segs Array of object with segments data
|
1921 | * @return {Array} Array of object with segments data
|
1922 | */
|
1923 | function buildNodes (segs) {
|
1924 | var nodes = []
|
1925 | for (var i = 0; i < segs.length; i++) {
|
1926 | var seg = segs[i]
|
1927 |
|
1928 | switch (seg.mode) {
|
1929 | case Mode.NUMERIC:
|
1930 | nodes.push([seg,
|
1931 | { data: seg.data, mode: Mode.ALPHANUMERIC, length: seg.length },
|
1932 | { data: seg.data, mode: Mode.BYTE, length: seg.length }
|
1933 | ])
|
1934 | break
|
1935 | case Mode.ALPHANUMERIC:
|
1936 | nodes.push([seg,
|
1937 | { data: seg.data, mode: Mode.BYTE, length: seg.length }
|
1938 | ])
|
1939 | break
|
1940 | case Mode.KANJI:
|
1941 | nodes.push([seg,
|
1942 | { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) }
|
1943 | ])
|
1944 | break
|
1945 | case Mode.BYTE:
|
1946 | nodes.push([
|
1947 | { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) }
|
1948 | ])
|
1949 | }
|
1950 | }
|
1951 |
|
1952 | return nodes
|
1953 | }
|
1954 |
|
1955 | /**
|
1956 | * Builds a graph from a list of nodes.
|
1957 | * All segments in each node group will be connected with all the segments of
|
1958 | * the next group and so on.
|
1959 | *
|
1960 | * At each connection will be assigned a weight depending on the
|
1961 | * segment's byte length.
|
1962 | *
|
1963 | * @param {Array} nodes Array of object with segments data
|
1964 | * @param {Number} version QR Code version
|
1965 | * @return {Object} Graph of all possible segments
|
1966 | */
|
1967 | function buildGraph (nodes, version) {
|
1968 | var table = {}
|
1969 | var graph = {'start': {}}
|
1970 | var prevNodeIds = ['start']
|
1971 |
|
1972 | for (var i = 0; i < nodes.length; i++) {
|
1973 | var nodeGroup = nodes[i]
|
1974 | var currentNodeIds = []
|
1975 |
|
1976 | for (var j = 0; j < nodeGroup.length; j++) {
|
1977 | var node = nodeGroup[j]
|
1978 | var key = '' + i + j
|
1979 |
|
1980 | currentNodeIds.push(key)
|
1981 | table[key] = { node: node, lastCount: 0 }
|
1982 | graph[key] = {}
|
1983 |
|
1984 | for (var n = 0; n < prevNodeIds.length; n++) {
|
1985 | var prevNodeId = prevNodeIds[n]
|
1986 |
|
1987 | if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) {
|
1988 | graph[prevNodeId][key] =
|
1989 | getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) -
|
1990 | getSegmentBitsLength(table[prevNodeId].lastCount, node.mode)
|
1991 |
|
1992 | table[prevNodeId].lastCount += node.length
|
1993 | } else {
|
1994 | if (table[prevNodeId]) table[prevNodeId].lastCount = node.length
|
1995 |
|
1996 | graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) +
|
1997 | 4 + Mode.getCharCountIndicator(node.mode, version) // switch cost
|
1998 | }
|
1999 | }
|
2000 | }
|
2001 |
|
2002 | prevNodeIds = currentNodeIds
|
2003 | }
|
2004 |
|
2005 | for (n = 0; n < prevNodeIds.length; n++) {
|
2006 | graph[prevNodeIds[n]]['end'] = 0
|
2007 | }
|
2008 |
|
2009 | return { map: graph, table: table }
|
2010 | }
|
2011 |
|
2012 | /**
|
2013 | * Builds a segment from a specified data and mode.
|
2014 | * If a mode is not specified, the more suitable will be used.
|
2015 | *
|
2016 | * @param {String} data Input data
|
2017 | * @param {Mode | String} modesHint Data mode
|
2018 | * @return {Segment} Segment
|
2019 | */
|
2020 | function buildSingleSegment (data, modesHint) {
|
2021 | var mode
|
2022 | var bestMode = Mode.getBestModeForData(data)
|
2023 |
|
2024 | mode = Mode.from(modesHint, bestMode)
|
2025 |
|
2026 | // Make sure data can be encoded
|
2027 | if (mode !== Mode.BYTE && mode.bit < bestMode.bit) {
|
2028 | throw new Error('"' + data + '"' +
|
2029 | ' cannot be encoded with mode ' + Mode.toString(mode) +
|
2030 | '.\n Suggested mode is: ' + Mode.toString(bestMode))
|
2031 | }
|
2032 |
|
2033 | // Use Mode.BYTE if Kanji support is disabled
|
2034 | if (mode === Mode.KANJI && !Utils.isKanjiModeEnabled()) {
|
2035 | mode = Mode.BYTE
|
2036 | }
|
2037 |
|
2038 | switch (mode) {
|
2039 | case Mode.NUMERIC:
|
2040 | return new NumericData(data)
|
2041 |
|
2042 | case Mode.ALPHANUMERIC:
|
2043 | return new AlphanumericData(data)
|
2044 |
|
2045 | case Mode.KANJI:
|
2046 | return new KanjiData(data)
|
2047 |
|
2048 | case Mode.BYTE:
|
2049 | return new ByteData(data)
|
2050 | }
|
2051 | }
|
2052 |
|
2053 | /**
|
2054 | * Builds a list of segments from an array.
|
2055 | * Array can contain Strings or Objects with segment's info.
|
2056 | *
|
2057 | * For each item which is a string, will be generated a segment with the given
|
2058 | * string and the more appropriate encoding mode.
|
2059 | *
|
2060 | * For each item which is an object, will be generated a segment with the given
|
2061 | * data and mode.
|
2062 | * Objects must contain at least the property "data".
|
2063 | * If property "mode" is not present, the more suitable mode will be used.
|
2064 | *
|
2065 | * @param {Array} array Array of objects with segments data
|
2066 | * @return {Array} Array of Segments
|
2067 | */
|
2068 | exports.fromArray = function fromArray (array) {
|
2069 | return array.reduce(function (acc, seg) {
|
2070 | if (typeof seg === 'string') {
|
2071 | acc.push(buildSingleSegment(seg, null))
|
2072 | } else if (seg.data) {
|
2073 | acc.push(buildSingleSegment(seg.data, seg.mode))
|
2074 | }
|
2075 |
|
2076 | return acc
|
2077 | }, [])
|
2078 | }
|
2079 |
|
2080 | /**
|
2081 | * Builds an optimized sequence of segments from a string,
|
2082 | * which will produce the shortest possible bitstream.
|
2083 | *
|
2084 | * @param {String} data Input string
|
2085 | * @param {Number} version QR Code version
|
2086 | * @return {Array} Array of segments
|
2087 | */
|
2088 | exports.fromString = function fromString (data, version) {
|
2089 | var segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled())
|
2090 |
|
2091 | var nodes = buildNodes(segs)
|
2092 | var graph = buildGraph(nodes, version)
|
2093 | var path = dijkstra.find_path(graph.map, 'start', 'end')
|
2094 |
|
2095 | var optimizedSegs = []
|
2096 | for (var i = 1; i < path.length - 1; i++) {
|
2097 | optimizedSegs.push(graph.table[path[i]].node)
|
2098 | }
|
2099 |
|
2100 | return exports.fromArray(mergeSegments(optimizedSegs))
|
2101 | }
|
2102 |
|
2103 | /**
|
2104 | * Splits a string in various segments with the modes which
|
2105 | * best represent their content.
|
2106 | * The produced segments are far from being optimized.
|
2107 | * The output of this function is only used to estimate a QR Code version
|
2108 | * which may contain the data.
|
2109 | *
|
2110 | * @param {string} data Input string
|
2111 | * @return {Array} Array of segments
|
2112 | */
|
2113 | exports.rawSplit = function rawSplit (data) {
|
2114 | return exports.fromArray(
|
2115 | getSegmentsFromString(data, Utils.isKanjiModeEnabled())
|
2116 | )
|
2117 | }
|
2118 |
|
2119 | },{"./alphanumeric-data":3,"./byte-data":6,"./kanji-data":12,"./mode":14,"./numeric-data":15,"./regex":19,"./utils":21,"dijkstrajs":29}],21:[function(require,module,exports){
|
2120 | var toSJISFunction
|
2121 | var CODEWORDS_COUNT = [
|
2122 | 0, // Not used
|
2123 | 26, 44, 70, 100, 134, 172, 196, 242, 292, 346,
|
2124 | 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085,
|
2125 | 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185,
|
2126 | 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706
|
2127 | ]
|
2128 |
|
2129 | /**
|
2130 | * Returns the QR Code size for the specified version
|
2131 | *
|
2132 | * @param {Number} version QR Code version
|
2133 | * @return {Number} size of QR code
|
2134 | */
|
2135 | exports.getSymbolSize = function getSymbolSize (version) {
|
2136 | if (!version) throw new Error('"version" cannot be null or undefined')
|
2137 | if (version < 1 || version > 40) throw new Error('"version" should be in range from 1 to 40')
|
2138 | return version * 4 + 17
|
2139 | }
|
2140 |
|
2141 | /**
|
2142 | * Returns the total number of codewords used to store data and EC information.
|
2143 | *
|
2144 | * @param {Number} version QR Code version
|
2145 | * @return {Number} Data length in bits
|
2146 | */
|
2147 | exports.getSymbolTotalCodewords = function getSymbolTotalCodewords (version) {
|
2148 | return CODEWORDS_COUNT[version]
|
2149 | }
|
2150 |
|
2151 | /**
|
2152 | * Encode data with Bose-Chaudhuri-Hocquenghem
|
2153 | *
|
2154 | * @param {Number} data Value to encode
|
2155 | * @return {Number} Encoded value
|
2156 | */
|
2157 | exports.getBCHDigit = function (data) {
|
2158 | var digit = 0
|
2159 |
|
2160 | while (data !== 0) {
|
2161 | digit++
|
2162 | data >>>= 1
|
2163 | }
|
2164 |
|
2165 | return digit
|
2166 | }
|
2167 |
|
2168 | exports.setToSJISFunction = function setToSJISFunction (f) {
|
2169 | if (typeof f !== 'function') {
|
2170 | throw new Error('"toSJISFunc" is not a valid function.')
|
2171 | }
|
2172 |
|
2173 | toSJISFunction = f
|
2174 | }
|
2175 |
|
2176 | exports.isKanjiModeEnabled = function () {
|
2177 | return typeof toSJISFunction !== 'undefined'
|
2178 | }
|
2179 |
|
2180 | exports.toSJIS = function toSJIS (kanji) {
|
2181 | return toSJISFunction(kanji)
|
2182 | }
|
2183 |
|
2184 | },{}],22:[function(require,module,exports){
|
2185 | /**
|
2186 | * Check if QR Code version is valid
|
2187 | *
|
2188 | * @param {Number} version QR Code version
|
2189 | * @return {Boolean} true if valid version, false otherwise
|
2190 | */
|
2191 | exports.isValid = function isValid (version) {
|
2192 | return !isNaN(version) && version >= 1 && version <= 40
|
2193 | }
|
2194 |
|
2195 | },{}],23:[function(require,module,exports){
|
2196 | var Utils = require('./utils')
|
2197 | var ECCode = require('./error-correction-code')
|
2198 | var ECLevel = require('./error-correction-level')
|
2199 | var Mode = require('./mode')
|
2200 | var VersionCheck = require('./version-check')
|
2201 | var isArray = require('isarray')
|
2202 |
|
2203 | // Generator polynomial used to encode version information
|
2204 | var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0)
|
2205 | var G18_BCH = Utils.getBCHDigit(G18)
|
2206 |
|
2207 | function getBestVersionForDataLength (mode, length, errorCorrectionLevel) {
|
2208 | for (var currentVersion = 1; currentVersion <= 40; currentVersion++) {
|
2209 | if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, mode)) {
|
2210 | return currentVersion
|
2211 | }
|
2212 | }
|
2213 |
|
2214 | return undefined
|
2215 | }
|
2216 |
|
2217 | function getReservedBitsCount (mode, version) {
|
2218 | // Character count indicator + mode indicator bits
|
2219 | return Mode.getCharCountIndicator(mode, version) + 4
|
2220 | }
|
2221 |
|
2222 | function getTotalBitsFromDataArray (segments, version) {
|
2223 | var totalBits = 0
|
2224 |
|
2225 | segments.forEach(function (data) {
|
2226 | var reservedBits = getReservedBitsCount(data.mode, version)
|
2227 | totalBits += reservedBits + data.getBitsLength()
|
2228 | })
|
2229 |
|
2230 | return totalBits
|
2231 | }
|
2232 |
|
2233 | function getBestVersionForMixedData (segments, errorCorrectionLevel) {
|
2234 | for (var currentVersion = 1; currentVersion <= 40; currentVersion++) {
|
2235 | var length = getTotalBitsFromDataArray(segments, currentVersion)
|
2236 | if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, Mode.MIXED)) {
|
2237 | return currentVersion
|
2238 | }
|
2239 | }
|
2240 |
|
2241 | return undefined
|
2242 | }
|
2243 |
|
2244 | /**
|
2245 | * Returns version number from a value.
|
2246 | * If value is not a valid version, returns defaultValue
|
2247 | *
|
2248 | * @param {Number|String} value QR Code version
|
2249 | * @param {Number} defaultValue Fallback value
|
2250 | * @return {Number} QR Code version number
|
2251 | */
|
2252 | exports.from = function from (value, defaultValue) {
|
2253 | if (VersionCheck.isValid(value)) {
|
2254 | return parseInt(value, 10)
|
2255 | }
|
2256 |
|
2257 | return defaultValue
|
2258 | }
|
2259 |
|
2260 | /**
|
2261 | * Returns how much data can be stored with the specified QR code version
|
2262 | * and error correction level
|
2263 | *
|
2264 | * @param {Number} version QR Code version (1-40)
|
2265 | * @param {Number} errorCorrectionLevel Error correction level
|
2266 | * @param {Mode} mode Data mode
|
2267 | * @return {Number} Quantity of storable data
|
2268 | */
|
2269 | exports.getCapacity = function getCapacity (version, errorCorrectionLevel, mode) {
|
2270 | if (!VersionCheck.isValid(version)) {
|
2271 | throw new Error('Invalid QR Code version')
|
2272 | }
|
2273 |
|
2274 | // Use Byte mode as default
|
2275 | if (typeof mode === 'undefined') mode = Mode.BYTE
|
2276 |
|
2277 | // Total codewords for this QR code version (Data + Error correction)
|
2278 | var totalCodewords = Utils.getSymbolTotalCodewords(version)
|
2279 |
|
2280 | // Total number of error correction codewords
|
2281 | var ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel)
|
2282 |
|
2283 | // Total number of data codewords
|
2284 | var dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8
|
2285 |
|
2286 | if (mode === Mode.MIXED) return dataTotalCodewordsBits
|
2287 |
|
2288 | var usableBits = dataTotalCodewordsBits - getReservedBitsCount(mode, version)
|
2289 |
|
2290 | // Return max number of storable codewords
|
2291 | switch (mode) {
|
2292 | case Mode.NUMERIC:
|
2293 | return Math.floor((usableBits / 10) * 3)
|
2294 |
|
2295 | case Mode.ALPHANUMERIC:
|
2296 | return Math.floor((usableBits / 11) * 2)
|
2297 |
|
2298 | case Mode.KANJI:
|
2299 | return Math.floor(usableBits / 13)
|
2300 |
|
2301 | case Mode.BYTE:
|
2302 | default:
|
2303 | return Math.floor(usableBits / 8)
|
2304 | }
|
2305 | }
|
2306 |
|
2307 | /**
|
2308 | * Returns the minimum version needed to contain the amount of data
|
2309 | *
|
2310 | * @param {Segment} data Segment of data
|
2311 | * @param {Number} [errorCorrectionLevel=H] Error correction level
|
2312 | * @param {Mode} mode Data mode
|
2313 | * @return {Number} QR Code version
|
2314 | */
|
2315 | exports.getBestVersionForData = function getBestVersionForData (data, errorCorrectionLevel) {
|
2316 | var seg
|
2317 |
|
2318 | var ecl = ECLevel.from(errorCorrectionLevel, ECLevel.M)
|
2319 |
|
2320 | if (isArray(data)) {
|
2321 | if (data.length > 1) {
|
2322 | return getBestVersionForMixedData(data, ecl)
|
2323 | }
|
2324 |
|
2325 | if (data.length === 0) {
|
2326 | return 1
|
2327 | }
|
2328 |
|
2329 | seg = data[0]
|
2330 | } else {
|
2331 | seg = data
|
2332 | }
|
2333 |
|
2334 | return getBestVersionForDataLength(seg.mode, seg.getLength(), ecl)
|
2335 | }
|
2336 |
|
2337 | /**
|
2338 | * Returns version information with relative error correction bits
|
2339 | *
|
2340 | * The version information is included in QR Code symbols of version 7 or larger.
|
2341 | * It consists of an 18-bit sequence containing 6 data bits,
|
2342 | * with 12 error correction bits calculated using the (18, 6) Golay code.
|
2343 | *
|
2344 | * @param {Number} version QR Code version
|
2345 | * @return {Number} Encoded version info bits
|
2346 | */
|
2347 | exports.getEncodedBits = function getEncodedBits (version) {
|
2348 | if (!VersionCheck.isValid(version) || version < 7) {
|
2349 | throw new Error('Invalid QR Code version')
|
2350 | }
|
2351 |
|
2352 | var d = version << 12
|
2353 |
|
2354 | while (Utils.getBCHDigit(d) - G18_BCH >= 0) {
|
2355 | d ^= (G18 << (Utils.getBCHDigit(d) - G18_BCH))
|
2356 | }
|
2357 |
|
2358 | return (version << 12) | d
|
2359 | }
|
2360 |
|
2361 | },{"./error-correction-code":7,"./error-correction-level":8,"./mode":14,"./utils":21,"./version-check":22,"isarray":30}],24:[function(require,module,exports){
|
2362 |
|
2363 | var canPromise = require('./can-promise')
|
2364 |
|
2365 | var QRCode = require('./core/qrcode')
|
2366 | var CanvasRenderer = require('./renderer/canvas')
|
2367 | var SvgRenderer = require('./renderer/svg-tag.js')
|
2368 |
|
2369 | function renderCanvas (renderFunc, canvas, text, opts, cb) {
|
2370 | var args = [].slice.call(arguments, 1)
|
2371 | var argsNum = args.length
|
2372 | var isLastArgCb = typeof args[argsNum - 1] === 'function'
|
2373 |
|
2374 | if (!isLastArgCb && !canPromise()) {
|
2375 | throw new Error('Callback required as last argument')
|
2376 | }
|
2377 |
|
2378 | if (isLastArgCb) {
|
2379 | if (argsNum < 2) {
|
2380 | throw new Error('Too few arguments provided')
|
2381 | }
|
2382 |
|
2383 | if (argsNum === 2) {
|
2384 | cb = text
|
2385 | text = canvas
|
2386 | canvas = opts = undefined
|
2387 | } else if (argsNum === 3) {
|
2388 | if (canvas.getContext && typeof cb === 'undefined') {
|
2389 | cb = opts
|
2390 | opts = undefined
|
2391 | } else {
|
2392 | cb = opts
|
2393 | opts = text
|
2394 | text = canvas
|
2395 | canvas = undefined
|
2396 | }
|
2397 | }
|
2398 | } else {
|
2399 | if (argsNum < 1) {
|
2400 | throw new Error('Too few arguments provided')
|
2401 | }
|
2402 |
|
2403 | if (argsNum === 1) {
|
2404 | text = canvas
|
2405 | canvas = opts = undefined
|
2406 | } else if (argsNum === 2 && !canvas.getContext) {
|
2407 | opts = text
|
2408 | text = canvas
|
2409 | canvas = undefined
|
2410 | }
|
2411 |
|
2412 | return new Promise(function (resolve, reject) {
|
2413 | try {
|
2414 | var data = QRCode.create(text, opts)
|
2415 | resolve(renderFunc(data, canvas, opts))
|
2416 | } catch (e) {
|
2417 | reject(e)
|
2418 | }
|
2419 | })
|
2420 | }
|
2421 |
|
2422 | try {
|
2423 | var data = QRCode.create(text, opts)
|
2424 | cb(null, renderFunc(data, canvas, opts))
|
2425 | } catch (e) {
|
2426 | cb(e)
|
2427 | }
|
2428 | }
|
2429 |
|
2430 | exports.create = QRCode.create
|
2431 | exports.toCanvas = renderCanvas.bind(null, CanvasRenderer.render)
|
2432 | exports.toDataURL = renderCanvas.bind(null, CanvasRenderer.renderToDataURL)
|
2433 |
|
2434 | // only svg for now.
|
2435 | exports.toString = renderCanvas.bind(null, function (data, _, opts) {
|
2436 | return SvgRenderer.render(data, opts)
|
2437 | })
|
2438 |
|
2439 | },{"./can-promise":1,"./core/qrcode":17,"./renderer/canvas":25,"./renderer/svg-tag.js":26}],25:[function(require,module,exports){
|
2440 | var Utils = require('./utils')
|
2441 |
|
2442 | function clearCanvas (ctx, canvas, size) {
|
2443 | ctx.clearRect(0, 0, canvas.width, canvas.height)
|
2444 |
|
2445 | if (!canvas.style) canvas.style = {}
|
2446 | canvas.height = size
|
2447 | canvas.width = size
|
2448 | canvas.style.height = size + 'px'
|
2449 | canvas.style.width = size + 'px'
|
2450 | }
|
2451 |
|
2452 | function getCanvasElement () {
|
2453 | try {
|
2454 | return document.createElement('canvas')
|
2455 | } catch (e) {
|
2456 | throw new Error('You need to specify a canvas element')
|
2457 | }
|
2458 | }
|
2459 |
|
2460 | exports.render = function render (qrData, canvas, options) {
|
2461 | var opts = options
|
2462 | var canvasEl = canvas
|
2463 |
|
2464 | if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) {
|
2465 | opts = canvas
|
2466 | canvas = undefined
|
2467 | }
|
2468 |
|
2469 | if (!canvas) {
|
2470 | canvasEl = getCanvasElement()
|
2471 | }
|
2472 |
|
2473 | opts = Utils.getOptions(opts)
|
2474 | var size = Utils.getImageWidth(qrData.modules.size, opts)
|
2475 |
|
2476 | var ctx = canvasEl.getContext('2d')
|
2477 | var image = ctx.createImageData(size, size)
|
2478 | Utils.qrToImageData(image.data, qrData, opts)
|
2479 |
|
2480 | clearCanvas(ctx, canvasEl, size)
|
2481 | ctx.putImageData(image, 0, 0)
|
2482 |
|
2483 | return canvasEl
|
2484 | }
|
2485 |
|
2486 | exports.renderToDataURL = function renderToDataURL (qrData, canvas, options) {
|
2487 | var opts = options
|
2488 |
|
2489 | if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) {
|
2490 | opts = canvas
|
2491 | canvas = undefined
|
2492 | }
|
2493 |
|
2494 | if (!opts) opts = {}
|
2495 |
|
2496 | var canvasEl = exports.render(qrData, canvas, opts)
|
2497 |
|
2498 | var type = opts.type || 'image/png'
|
2499 | var rendererOpts = opts.rendererOpts || {}
|
2500 |
|
2501 | return canvasEl.toDataURL(type, rendererOpts.quality)
|
2502 | }
|
2503 |
|
2504 | },{"./utils":27}],26:[function(require,module,exports){
|
2505 | var Utils = require('./utils')
|
2506 |
|
2507 | function getColorAttrib (color, attrib) {
|
2508 | var alpha = color.a / 255
|
2509 | var str = attrib + '="' + color.hex + '"'
|
2510 |
|
2511 | return alpha < 1
|
2512 | ? str + ' ' + attrib + '-opacity="' + alpha.toFixed(2).slice(1) + '"'
|
2513 | : str
|
2514 | }
|
2515 |
|
2516 | function svgCmd (cmd, x, y) {
|
2517 | var str = cmd + x
|
2518 | if (typeof y !== 'undefined') str += ' ' + y
|
2519 |
|
2520 | return str
|
2521 | }
|
2522 |
|
2523 | function qrToPath (data, size, margin) {
|
2524 | var path = ''
|
2525 | var moveBy = 0
|
2526 | var newRow = false
|
2527 | var lineLength = 0
|
2528 |
|
2529 | for (var i = 0; i < data.length; i++) {
|
2530 | var col = Math.floor(i % size)
|
2531 | var row = Math.floor(i / size)
|
2532 |
|
2533 | if (!col && !newRow) newRow = true
|
2534 |
|
2535 | if (data[i]) {
|
2536 | lineLength++
|
2537 |
|
2538 | if (!(i > 0 && col > 0 && data[i - 1])) {
|
2539 | path += newRow
|
2540 | ? svgCmd('M', col + margin, 0.5 + row + margin)
|
2541 | : svgCmd('m', moveBy, 0)
|
2542 |
|
2543 | moveBy = 0
|
2544 | newRow = false
|
2545 | }
|
2546 |
|
2547 | if (!(col + 1 < size && data[i + 1])) {
|
2548 | path += svgCmd('h', lineLength)
|
2549 | lineLength = 0
|
2550 | }
|
2551 | } else {
|
2552 | moveBy++
|
2553 | }
|
2554 | }
|
2555 |
|
2556 | return path
|
2557 | }
|
2558 |
|
2559 | exports.render = function render (qrData, options, cb) {
|
2560 | var opts = Utils.getOptions(options)
|
2561 | var size = qrData.modules.size
|
2562 | var data = qrData.modules.data
|
2563 | var qrcodesize = size + opts.margin * 2
|
2564 |
|
2565 | var bg = !opts.color.light.a
|
2566 | ? ''
|
2567 | : '<path ' + getColorAttrib(opts.color.light, 'fill') +
|
2568 | ' d="M0 0h' + qrcodesize + 'v' + qrcodesize + 'H0z"/>'
|
2569 |
|
2570 | var path =
|
2571 | '<path ' + getColorAttrib(opts.color.dark, 'stroke') +
|
2572 | ' d="' + qrToPath(data, size, opts.margin) + '"/>'
|
2573 |
|
2574 | var viewBox = 'viewBox="' + '0 0 ' + qrcodesize + ' ' + qrcodesize + '"'
|
2575 |
|
2576 | var width = !opts.width ? '' : 'width="' + opts.width + '" height="' + opts.width + '" '
|
2577 |
|
2578 | var svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg + path + '</svg>\n'
|
2579 |
|
2580 | if (typeof cb === 'function') {
|
2581 | cb(null, svgTag)
|
2582 | }
|
2583 |
|
2584 | return svgTag
|
2585 | }
|
2586 |
|
2587 | },{"./utils":27}],27:[function(require,module,exports){
|
2588 | function hex2rgba (hex) {
|
2589 | if (typeof hex === 'number') {
|
2590 | hex = hex.toString()
|
2591 | }
|
2592 |
|
2593 | if (typeof hex !== 'string') {
|
2594 | throw new Error('Color should be defined as hex string')
|
2595 | }
|
2596 |
|
2597 | var hexCode = hex.slice().replace('#', '').split('')
|
2598 | if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) {
|
2599 | throw new Error('Invalid hex color: ' + hex)
|
2600 | }
|
2601 |
|
2602 | // Convert from short to long form (fff -> ffffff)
|
2603 | if (hexCode.length === 3 || hexCode.length === 4) {
|
2604 | hexCode = Array.prototype.concat.apply([], hexCode.map(function (c) {
|
2605 | return [c, c]
|
2606 | }))
|
2607 | }
|
2608 |
|
2609 | // Add default alpha value
|
2610 | if (hexCode.length === 6) hexCode.push('F', 'F')
|
2611 |
|
2612 | var hexValue = parseInt(hexCode.join(''), 16)
|
2613 |
|
2614 | return {
|
2615 | r: (hexValue >> 24) & 255,
|
2616 | g: (hexValue >> 16) & 255,
|
2617 | b: (hexValue >> 8) & 255,
|
2618 | a: hexValue & 255,
|
2619 | hex: '#' + hexCode.slice(0, 6).join('')
|
2620 | }
|
2621 | }
|
2622 |
|
2623 | exports.getOptions = function getOptions (options) {
|
2624 | if (!options) options = {}
|
2625 | if (!options.color) options.color = {}
|
2626 |
|
2627 | var margin = typeof options.margin === 'undefined' ||
|
2628 | options.margin === null ||
|
2629 | options.margin < 0 ? 4 : options.margin
|
2630 |
|
2631 | var width = options.width && options.width >= 21 ? options.width : undefined
|
2632 | var scale = options.scale || 4
|
2633 |
|
2634 | return {
|
2635 | width: width,
|
2636 | scale: width ? 4 : scale,
|
2637 | margin: margin,
|
2638 | color: {
|
2639 | dark: hex2rgba(options.color.dark || '#000000ff'),
|
2640 | light: hex2rgba(options.color.light || '#ffffffff')
|
2641 | },
|
2642 | type: options.type,
|
2643 | rendererOpts: options.rendererOpts || {}
|
2644 | }
|
2645 | }
|
2646 |
|
2647 | exports.getScale = function getScale (qrSize, opts) {
|
2648 | return opts.width && opts.width >= qrSize + opts.margin * 2
|
2649 | ? opts.width / (qrSize + opts.margin * 2)
|
2650 | : opts.scale
|
2651 | }
|
2652 |
|
2653 | exports.getImageWidth = function getImageWidth (qrSize, opts) {
|
2654 | var scale = exports.getScale(qrSize, opts)
|
2655 | return Math.floor((qrSize + opts.margin * 2) * scale)
|
2656 | }
|
2657 |
|
2658 | exports.qrToImageData = function qrToImageData (imgData, qr, opts) {
|
2659 | var size = qr.modules.size
|
2660 | var data = qr.modules.data
|
2661 | var scale = exports.getScale(size, opts)
|
2662 | var symbolSize = Math.floor((size + opts.margin * 2) * scale)
|
2663 | var scaledMargin = opts.margin * scale
|
2664 | var palette = [opts.color.light, opts.color.dark]
|
2665 |
|
2666 | for (var i = 0; i < symbolSize; i++) {
|
2667 | for (var j = 0; j < symbolSize; j++) {
|
2668 | var posDst = (i * symbolSize + j) * 4
|
2669 | var pxColor = opts.color.light
|
2670 |
|
2671 | if (i >= scaledMargin && j >= scaledMargin &&
|
2672 | i < symbolSize - scaledMargin && j < symbolSize - scaledMargin) {
|
2673 | var iSrc = Math.floor((i - scaledMargin) / scale)
|
2674 | var jSrc = Math.floor((j - scaledMargin) / scale)
|
2675 | pxColor = palette[data[iSrc * size + jSrc] ? 1 : 0]
|
2676 | }
|
2677 |
|
2678 | imgData[posDst++] = pxColor.r
|
2679 | imgData[posDst++] = pxColor.g
|
2680 | imgData[posDst++] = pxColor.b
|
2681 | imgData[posDst] = pxColor.a
|
2682 | }
|
2683 | }
|
2684 | }
|
2685 |
|
2686 | },{}],28:[function(require,module,exports){
|
2687 | /**
|
2688 | * Implementation of a subset of node.js Buffer methods for the browser.
|
2689 | * Based on https://github.com/feross/buffer
|
2690 | */
|
2691 |
|
2692 | /* eslint-disable no-proto */
|
2693 |
|
2694 |
|
2695 |
|
2696 | var isArray = require('isarray')
|
2697 |
|
2698 | function typedArraySupport () {
|
2699 | // Can typed array instances be augmented?
|
2700 | try {
|
2701 | var arr = new Uint8Array(1)
|
2702 | arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}
|
2703 | return arr.foo() === 42
|
2704 | } catch (e) {
|
2705 | return false
|
2706 | }
|
2707 | }
|
2708 |
|
2709 | Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport()
|
2710 |
|
2711 | var K_MAX_LENGTH = Buffer.TYPED_ARRAY_SUPPORT
|
2712 | ? 0x7fffffff
|
2713 | : 0x3fffffff
|
2714 |
|
2715 | function Buffer (arg, offset, length) {
|
2716 | if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) {
|
2717 | return new Buffer(arg, offset, length)
|
2718 | }
|
2719 |
|
2720 | if (typeof arg === 'number') {
|
2721 | return allocUnsafe(this, arg)
|
2722 | }
|
2723 |
|
2724 | return from(this, arg, offset, length)
|
2725 | }
|
2726 |
|
2727 | if (Buffer.TYPED_ARRAY_SUPPORT) {
|
2728 | Buffer.prototype.__proto__ = Uint8Array.prototype
|
2729 | Buffer.__proto__ = Uint8Array
|
2730 |
|
2731 | // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
|
2732 | if (typeof Symbol !== 'undefined' && Symbol.species &&
|
2733 | Buffer[Symbol.species] === Buffer) {
|
2734 | Object.defineProperty(Buffer, Symbol.species, {
|
2735 | value: null,
|
2736 | configurable: true,
|
2737 | enumerable: false,
|
2738 | writable: false
|
2739 | })
|
2740 | }
|
2741 | }
|
2742 |
|
2743 | function checked (length) {
|
2744 | // Note: cannot use `length < K_MAX_LENGTH` here because that fails when
|
2745 | // length is NaN (which is otherwise coerced to zero.)
|
2746 | if (length >= K_MAX_LENGTH) {
|
2747 | throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
|
2748 | 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes')
|
2749 | }
|
2750 | return length | 0
|
2751 | }
|
2752 |
|
2753 | function isnan (val) {
|
2754 | return val !== val // eslint-disable-line no-self-compare
|
2755 | }
|
2756 |
|
2757 | function createBuffer (that, length) {
|
2758 | var buf
|
2759 | if (Buffer.TYPED_ARRAY_SUPPORT) {
|
2760 | buf = new Uint8Array(length)
|
2761 | buf.__proto__ = Buffer.prototype
|
2762 | } else {
|
2763 | // Fallback: Return an object instance of the Buffer class
|
2764 | buf = that
|
2765 | if (buf === null) {
|
2766 | buf = new Buffer(length)
|
2767 | }
|
2768 | buf.length = length
|
2769 | }
|
2770 |
|
2771 | return buf
|
2772 | }
|
2773 |
|
2774 | function allocUnsafe (that, size) {
|
2775 | var buf = createBuffer(that, size < 0 ? 0 : checked(size) | 0)
|
2776 |
|
2777 | if (!Buffer.TYPED_ARRAY_SUPPORT) {
|
2778 | for (var i = 0; i < size; ++i) {
|
2779 | buf[i] = 0
|
2780 | }
|
2781 | }
|
2782 |
|
2783 | return buf
|
2784 | }
|
2785 |
|
2786 | function fromString (that, string) {
|
2787 | var length = byteLength(string) | 0
|
2788 | var buf = createBuffer(that, length)
|
2789 |
|
2790 | var actual = buf.write(string)
|
2791 |
|
2792 | if (actual !== length) {
|
2793 | // Writing a hex string, for example, that contains invalid characters will
|
2794 | // cause everything after the first invalid character to be ignored. (e.g.
|
2795 | // 'abxxcd' will be treated as 'ab')
|
2796 | buf = buf.slice(0, actual)
|
2797 | }
|
2798 |
|
2799 | return buf
|
2800 | }
|
2801 |
|
2802 | function fromArrayLike (that, array) {
|
2803 | var length = array.length < 0 ? 0 : checked(array.length) | 0
|
2804 | var buf = createBuffer(that, length)
|
2805 | for (var i = 0; i < length; i += 1) {
|
2806 | buf[i] = array[i] & 255
|
2807 | }
|
2808 | return buf
|
2809 | }
|
2810 |
|
2811 | function fromArrayBuffer (that, array, byteOffset, length) {
|
2812 | if (byteOffset < 0 || array.byteLength < byteOffset) {
|
2813 | throw new RangeError('\'offset\' is out of bounds')
|
2814 | }
|
2815 |
|
2816 | if (array.byteLength < byteOffset + (length || 0)) {
|
2817 | throw new RangeError('\'length\' is out of bounds')
|
2818 | }
|
2819 |
|
2820 | var buf
|
2821 | if (byteOffset === undefined && length === undefined) {
|
2822 | buf = new Uint8Array(array)
|
2823 | } else if (length === undefined) {
|
2824 | buf = new Uint8Array(array, byteOffset)
|
2825 | } else {
|
2826 | buf = new Uint8Array(array, byteOffset, length)
|
2827 | }
|
2828 |
|
2829 | if (Buffer.TYPED_ARRAY_SUPPORT) {
|
2830 | // Return an augmented `Uint8Array` instance, for best performance
|
2831 | buf.__proto__ = Buffer.prototype
|
2832 | } else {
|
2833 | // Fallback: Return an object instance of the Buffer class
|
2834 | buf = fromArrayLike(that, buf)
|
2835 | }
|
2836 |
|
2837 | return buf
|
2838 | }
|
2839 |
|
2840 | function fromObject (that, obj) {
|
2841 | if (Buffer.isBuffer(obj)) {
|
2842 | var len = checked(obj.length) | 0
|
2843 | var buf = createBuffer(that, len)
|
2844 |
|
2845 | if (buf.length === 0) {
|
2846 | return buf
|
2847 | }
|
2848 |
|
2849 | obj.copy(buf, 0, 0, len)
|
2850 | return buf
|
2851 | }
|
2852 |
|
2853 | if (obj) {
|
2854 | if ((typeof ArrayBuffer !== 'undefined' &&
|
2855 | obj.buffer instanceof ArrayBuffer) || 'length' in obj) {
|
2856 | if (typeof obj.length !== 'number' || isnan(obj.length)) {
|
2857 | return createBuffer(that, 0)
|
2858 | }
|
2859 | return fromArrayLike(that, obj)
|
2860 | }
|
2861 |
|
2862 | if (obj.type === 'Buffer' && Array.isArray(obj.data)) {
|
2863 | return fromArrayLike(that, obj.data)
|
2864 | }
|
2865 | }
|
2866 |
|
2867 | throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')
|
2868 | }
|
2869 |
|
2870 | function utf8ToBytes (string, units) {
|
2871 | units = units || Infinity
|
2872 | var codePoint
|
2873 | var length = string.length
|
2874 | var leadSurrogate = null
|
2875 | var bytes = []
|
2876 |
|
2877 | for (var i = 0; i < length; ++i) {
|
2878 | codePoint = string.charCodeAt(i)
|
2879 |
|
2880 | // is surrogate component
|
2881 | if (codePoint > 0xD7FF && codePoint < 0xE000) {
|
2882 | // last char was a lead
|
2883 | if (!leadSurrogate) {
|
2884 | // no lead yet
|
2885 | if (codePoint > 0xDBFF) {
|
2886 | // unexpected trail
|
2887 | if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
2888 | continue
|
2889 | } else if (i + 1 === length) {
|
2890 | // unpaired lead
|
2891 | if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
2892 | continue
|
2893 | }
|
2894 |
|
2895 | // valid lead
|
2896 | leadSurrogate = codePoint
|
2897 |
|
2898 | continue
|
2899 | }
|
2900 |
|
2901 | // 2 leads in a row
|
2902 | if (codePoint < 0xDC00) {
|
2903 | if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
2904 | leadSurrogate = codePoint
|
2905 | continue
|
2906 | }
|
2907 |
|
2908 | // valid surrogate pair
|
2909 | codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
|
2910 | } else if (leadSurrogate) {
|
2911 | // valid bmp char, but last char was a lead
|
2912 | if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
2913 | }
|
2914 |
|
2915 | leadSurrogate = null
|
2916 |
|
2917 | // encode utf8
|
2918 | if (codePoint < 0x80) {
|
2919 | if ((units -= 1) < 0) break
|
2920 | bytes.push(codePoint)
|
2921 | } else if (codePoint < 0x800) {
|
2922 | if ((units -= 2) < 0) break
|
2923 | bytes.push(
|
2924 | codePoint >> 0x6 | 0xC0,
|
2925 | codePoint & 0x3F | 0x80
|
2926 | )
|
2927 | } else if (codePoint < 0x10000) {
|
2928 | if ((units -= 3) < 0) break
|
2929 | bytes.push(
|
2930 | codePoint >> 0xC | 0xE0,
|
2931 | codePoint >> 0x6 & 0x3F | 0x80,
|
2932 | codePoint & 0x3F | 0x80
|
2933 | )
|
2934 | } else if (codePoint < 0x110000) {
|
2935 | if ((units -= 4) < 0) break
|
2936 | bytes.push(
|
2937 | codePoint >> 0x12 | 0xF0,
|
2938 | codePoint >> 0xC & 0x3F | 0x80,
|
2939 | codePoint >> 0x6 & 0x3F | 0x80,
|
2940 | codePoint & 0x3F | 0x80
|
2941 | )
|
2942 | } else {
|
2943 | throw new Error('Invalid code point')
|
2944 | }
|
2945 | }
|
2946 |
|
2947 | return bytes
|
2948 | }
|
2949 |
|
2950 | function byteLength (string) {
|
2951 | if (Buffer.isBuffer(string)) {
|
2952 | return string.length
|
2953 | }
|
2954 | if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' &&
|
2955 | (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) {
|
2956 | return string.byteLength
|
2957 | }
|
2958 | if (typeof string !== 'string') {
|
2959 | string = '' + string
|
2960 | }
|
2961 |
|
2962 | var len = string.length
|
2963 | if (len === 0) return 0
|
2964 |
|
2965 | return utf8ToBytes(string).length
|
2966 | }
|
2967 |
|
2968 | function blitBuffer (src, dst, offset, length) {
|
2969 | for (var i = 0; i < length; ++i) {
|
2970 | if ((i + offset >= dst.length) || (i >= src.length)) break
|
2971 | dst[i + offset] = src[i]
|
2972 | }
|
2973 | return i
|
2974 | }
|
2975 |
|
2976 | function utf8Write (buf, string, offset, length) {
|
2977 | return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
|
2978 | }
|
2979 |
|
2980 | function from (that, value, offset, length) {
|
2981 | if (typeof value === 'number') {
|
2982 | throw new TypeError('"value" argument must not be a number')
|
2983 | }
|
2984 |
|
2985 | if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
|
2986 | return fromArrayBuffer(that, value, offset, length)
|
2987 | }
|
2988 |
|
2989 | if (typeof value === 'string') {
|
2990 | return fromString(that, value, offset)
|
2991 | }
|
2992 |
|
2993 | return fromObject(that, value)
|
2994 | }
|
2995 |
|
2996 | Buffer.prototype.write = function write (string, offset, length) {
|
2997 | // Buffer#write(string)
|
2998 | if (offset === undefined) {
|
2999 | length = this.length
|
3000 | offset = 0
|
3001 | // Buffer#write(string, encoding)
|
3002 | } else if (length === undefined && typeof offset === 'string') {
|
3003 | length = this.length
|
3004 | offset = 0
|
3005 | // Buffer#write(string, offset[, length])
|
3006 | } else if (isFinite(offset)) {
|
3007 | offset = offset | 0
|
3008 | if (isFinite(length)) {
|
3009 | length = length | 0
|
3010 | } else {
|
3011 | length = undefined
|
3012 | }
|
3013 | }
|
3014 |
|
3015 | var remaining = this.length - offset
|
3016 | if (length === undefined || length > remaining) length = remaining
|
3017 |
|
3018 | if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
|
3019 | throw new RangeError('Attempt to write outside buffer bounds')
|
3020 | }
|
3021 |
|
3022 | return utf8Write(this, string, offset, length)
|
3023 | }
|
3024 |
|
3025 | Buffer.prototype.slice = function slice (start, end) {
|
3026 | var len = this.length
|
3027 | start = ~~start
|
3028 | end = end === undefined ? len : ~~end
|
3029 |
|
3030 | if (start < 0) {
|
3031 | start += len
|
3032 | if (start < 0) start = 0
|
3033 | } else if (start > len) {
|
3034 | start = len
|
3035 | }
|
3036 |
|
3037 | if (end < 0) {
|
3038 | end += len
|
3039 | if (end < 0) end = 0
|
3040 | } else if (end > len) {
|
3041 | end = len
|
3042 | }
|
3043 |
|
3044 | if (end < start) end = start
|
3045 |
|
3046 | var newBuf
|
3047 | if (Buffer.TYPED_ARRAY_SUPPORT) {
|
3048 | newBuf = this.subarray(start, end)
|
3049 | // Return an augmented `Uint8Array` instance
|
3050 | newBuf.__proto__ = Buffer.prototype
|
3051 | } else {
|
3052 | var sliceLen = end - start
|
3053 | newBuf = new Buffer(sliceLen, undefined)
|
3054 | for (var i = 0; i < sliceLen; ++i) {
|
3055 | newBuf[i] = this[i + start]
|
3056 | }
|
3057 | }
|
3058 |
|
3059 | return newBuf
|
3060 | }
|
3061 |
|
3062 | Buffer.prototype.copy = function copy (target, targetStart, start, end) {
|
3063 | if (!start) start = 0
|
3064 | if (!end && end !== 0) end = this.length
|
3065 | if (targetStart >= target.length) targetStart = target.length
|
3066 | if (!targetStart) targetStart = 0
|
3067 | if (end > 0 && end < start) end = start
|
3068 |
|
3069 | // Copy 0 bytes; we're done
|
3070 | if (end === start) return 0
|
3071 | if (target.length === 0 || this.length === 0) return 0
|
3072 |
|
3073 | // Fatal error conditions
|
3074 | if (targetStart < 0) {
|
3075 | throw new RangeError('targetStart out of bounds')
|
3076 | }
|
3077 | if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
|
3078 | if (end < 0) throw new RangeError('sourceEnd out of bounds')
|
3079 |
|
3080 | // Are we oob?
|
3081 | if (end > this.length) end = this.length
|
3082 | if (target.length - targetStart < end - start) {
|
3083 | end = target.length - targetStart + start
|
3084 | }
|
3085 |
|
3086 | var len = end - start
|
3087 | var i
|
3088 |
|
3089 | if (this === target && start < targetStart && targetStart < end) {
|
3090 | // descending copy from end
|
3091 | for (i = len - 1; i >= 0; --i) {
|
3092 | target[i + targetStart] = this[i + start]
|
3093 | }
|
3094 | } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
|
3095 | // ascending copy from start
|
3096 | for (i = 0; i < len; ++i) {
|
3097 | target[i + targetStart] = this[i + start]
|
3098 | }
|
3099 | } else {
|
3100 | Uint8Array.prototype.set.call(
|
3101 | target,
|
3102 | this.subarray(start, start + len),
|
3103 | targetStart
|
3104 | )
|
3105 | }
|
3106 |
|
3107 | return len
|
3108 | }
|
3109 |
|
3110 | Buffer.prototype.fill = function fill (val, start, end) {
|
3111 | // Handle string cases:
|
3112 | if (typeof val === 'string') {
|
3113 | if (typeof start === 'string') {
|
3114 | start = 0
|
3115 | end = this.length
|
3116 | } else if (typeof end === 'string') {
|
3117 | end = this.length
|
3118 | }
|
3119 | if (val.length === 1) {
|
3120 | var code = val.charCodeAt(0)
|
3121 | if (code < 256) {
|
3122 | val = code
|
3123 | }
|
3124 | }
|
3125 | } else if (typeof val === 'number') {
|
3126 | val = val & 255
|
3127 | }
|
3128 |
|
3129 | // Invalid ranges are not set to a default, so can range check early.
|
3130 | if (start < 0 || this.length < start || this.length < end) {
|
3131 | throw new RangeError('Out of range index')
|
3132 | }
|
3133 |
|
3134 | if (end <= start) {
|
3135 | return this
|
3136 | }
|
3137 |
|
3138 | start = start >>> 0
|
3139 | end = end === undefined ? this.length : end >>> 0
|
3140 |
|
3141 | if (!val) val = 0
|
3142 |
|
3143 | var i
|
3144 | if (typeof val === 'number') {
|
3145 | for (i = start; i < end; ++i) {
|
3146 | this[i] = val
|
3147 | }
|
3148 | } else {
|
3149 | var bytes = Buffer.isBuffer(val)
|
3150 | ? val
|
3151 | : new Buffer(val)
|
3152 | var len = bytes.length
|
3153 | for (i = 0; i < end - start; ++i) {
|
3154 | this[i + start] = bytes[i % len]
|
3155 | }
|
3156 | }
|
3157 |
|
3158 | return this
|
3159 | }
|
3160 |
|
3161 | Buffer.concat = function concat (list, length) {
|
3162 | if (!isArray(list)) {
|
3163 | throw new TypeError('"list" argument must be an Array of Buffers')
|
3164 | }
|
3165 |
|
3166 | if (list.length === 0) {
|
3167 | return createBuffer(null, 0)
|
3168 | }
|
3169 |
|
3170 | var i
|
3171 | if (length === undefined) {
|
3172 | length = 0
|
3173 | for (i = 0; i < list.length; ++i) {
|
3174 | length += list[i].length
|
3175 | }
|
3176 | }
|
3177 |
|
3178 | var buffer = allocUnsafe(null, length)
|
3179 | var pos = 0
|
3180 | for (i = 0; i < list.length; ++i) {
|
3181 | var buf = list[i]
|
3182 | if (!Buffer.isBuffer(buf)) {
|
3183 | throw new TypeError('"list" argument must be an Array of Buffers')
|
3184 | }
|
3185 | buf.copy(buffer, pos)
|
3186 | pos += buf.length
|
3187 | }
|
3188 | return buffer
|
3189 | }
|
3190 |
|
3191 | Buffer.byteLength = byteLength
|
3192 |
|
3193 | Buffer.prototype._isBuffer = true
|
3194 | Buffer.isBuffer = function isBuffer (b) {
|
3195 | return !!(b != null && b._isBuffer)
|
3196 | }
|
3197 |
|
3198 | module.exports = Buffer
|
3199 |
|
3200 | },{"isarray":30}],29:[function(require,module,exports){
|
3201 | ;
|
3202 |
|
3203 | /******************************************************************************
|
3204 | * Created 2008-08-19.
|
3205 | *
|
3206 | * Dijkstra path-finding functions. Adapted from the Dijkstar Python project.
|
3207 | *
|
3208 | * Copyright (C) 2008
|
3209 | * Wyatt Baldwin <self@wyattbaldwin.com>
|
3210 | * All rights reserved
|
3211 | *
|
3212 | * Licensed under the MIT license.
|
3213 | *
|
3214 | * http://www.opensource.org/licenses/mit-license.php
|
3215 | *
|
3216 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
3217 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
3218 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
3219 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
3220 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
3221 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
3222 | * THE SOFTWARE.
|
3223 | *****************************************************************************/
|
3224 | var dijkstra = {
|
3225 | single_source_shortest_paths: function(graph, s, d) {
|
3226 | // Predecessor map for each node that has been encountered.
|
3227 | // node ID => predecessor node ID
|
3228 | var predecessors = {};
|
3229 |
|
3230 | // Costs of shortest paths from s to all nodes encountered.
|
3231 | // node ID => cost
|
3232 | var costs = {};
|
3233 | costs[s] = 0;
|
3234 |
|
3235 | // Costs of shortest paths from s to all nodes encountered; differs from
|
3236 | // `costs` in that it provides easy access to the node that currently has
|
3237 | // the known shortest path from s.
|
3238 | // XXX: Do we actually need both `costs` and `open`?
|
3239 | var open = dijkstra.PriorityQueue.make();
|
3240 | open.push(s, 0);
|
3241 |
|
3242 | var closest,
|
3243 | u, v,
|
3244 | cost_of_s_to_u,
|
3245 | adjacent_nodes,
|
3246 | cost_of_e,
|
3247 | cost_of_s_to_u_plus_cost_of_e,
|
3248 | cost_of_s_to_v,
|
3249 | first_visit;
|
3250 | while (!open.empty()) {
|
3251 | // In the nodes remaining in graph that have a known cost from s,
|
3252 | // find the node, u, that currently has the shortest path from s.
|
3253 | closest = open.pop();
|
3254 | u = closest.value;
|
3255 | cost_of_s_to_u = closest.cost;
|
3256 |
|
3257 | // Get nodes adjacent to u...
|
3258 | adjacent_nodes = graph[u] || {};
|
3259 |
|
3260 | // ...and explore the edges that connect u to those nodes, updating
|
3261 | // the cost of the shortest paths to any or all of those nodes as
|
3262 | // necessary. v is the node across the current edge from u.
|
3263 | for (v in adjacent_nodes) {
|
3264 | if (adjacent_nodes.hasOwnProperty(v)) {
|
3265 | // Get the cost of the edge running from u to v.
|
3266 | cost_of_e = adjacent_nodes[v];
|
3267 |
|
3268 | // Cost of s to u plus the cost of u to v across e--this is *a*
|
3269 | // cost from s to v that may or may not be less than the current
|
3270 | // known cost to v.
|
3271 | cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e;
|
3272 |
|
3273 | // If we haven't visited v yet OR if the current known cost from s to
|
3274 | // v is greater than the new cost we just found (cost of s to u plus
|
3275 | // cost of u to v across e), update v's cost in the cost list and
|
3276 | // update v's predecessor in the predecessor list (it's now u).
|
3277 | cost_of_s_to_v = costs[v];
|
3278 | first_visit = (typeof costs[v] === 'undefined');
|
3279 | if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) {
|
3280 | costs[v] = cost_of_s_to_u_plus_cost_of_e;
|
3281 | open.push(v, cost_of_s_to_u_plus_cost_of_e);
|
3282 | predecessors[v] = u;
|
3283 | }
|
3284 | }
|
3285 | }
|
3286 | }
|
3287 |
|
3288 | if (typeof d !== 'undefined' && typeof costs[d] === 'undefined') {
|
3289 | var msg = ['Could not find a path from ', s, ' to ', d, '.'].join('');
|
3290 | throw new Error(msg);
|
3291 | }
|
3292 |
|
3293 | return predecessors;
|
3294 | },
|
3295 |
|
3296 | extract_shortest_path_from_predecessor_list: function(predecessors, d) {
|
3297 | var nodes = [];
|
3298 | var u = d;
|
3299 | var predecessor;
|
3300 | while (u) {
|
3301 | nodes.push(u);
|
3302 | predecessor = predecessors[u];
|
3303 | u = predecessors[u];
|
3304 | }
|
3305 | nodes.reverse();
|
3306 | return nodes;
|
3307 | },
|
3308 |
|
3309 | find_path: function(graph, s, d) {
|
3310 | var predecessors = dijkstra.single_source_shortest_paths(graph, s, d);
|
3311 | return dijkstra.extract_shortest_path_from_predecessor_list(
|
3312 | predecessors, d);
|
3313 | },
|
3314 |
|
3315 | /**
|
3316 | * A very naive priority queue implementation.
|
3317 | */
|
3318 | PriorityQueue: {
|
3319 | make: function (opts) {
|
3320 | var T = dijkstra.PriorityQueue,
|
3321 | t = {},
|
3322 | key;
|
3323 | opts = opts || {};
|
3324 | for (key in T) {
|
3325 | if (T.hasOwnProperty(key)) {
|
3326 | t[key] = T[key];
|
3327 | }
|
3328 | }
|
3329 | t.queue = [];
|
3330 | t.sorter = opts.sorter || T.default_sorter;
|
3331 | return t;
|
3332 | },
|
3333 |
|
3334 | default_sorter: function (a, b) {
|
3335 | return a.cost - b.cost;
|
3336 | },
|
3337 |
|
3338 | /**
|
3339 | * Add a new item to the queue and ensure the highest priority element
|
3340 | * is at the front of the queue.
|
3341 | */
|
3342 | push: function (value, cost) {
|
3343 | var item = {value: value, cost: cost};
|
3344 | this.queue.push(item);
|
3345 | this.queue.sort(this.sorter);
|
3346 | },
|
3347 |
|
3348 | /**
|
3349 | * Return the highest priority element in the queue.
|
3350 | */
|
3351 | pop: function () {
|
3352 | return this.queue.shift();
|
3353 | },
|
3354 |
|
3355 | empty: function () {
|
3356 | return this.queue.length === 0;
|
3357 | }
|
3358 | }
|
3359 | };
|
3360 |
|
3361 |
|
3362 | // node.js module exports
|
3363 | if (typeof module !== 'undefined') {
|
3364 | module.exports = dijkstra;
|
3365 | }
|
3366 |
|
3367 | },{}],30:[function(require,module,exports){
|
3368 | var toString = {}.toString;
|
3369 |
|
3370 | module.exports = Array.isArray || function (arr) {
|
3371 | return toString.call(arr) == '[object Array]';
|
3372 | };
|
3373 |
|
3374 | },{}]},{},[24])(24)
|
3375 | });
|
3376 |
|
3377 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJsaWIvY2FuLXByb21pc2UuanMiLCJsaWIvY29yZS9hbGlnbm1lbnQtcGF0dGVybi5qcyIsImxpYi9jb3JlL2FscGhhbnVtZXJpYy1kYXRhLmpzIiwibGliL2NvcmUvYml0LWJ1ZmZlci5qcyIsImxpYi9jb3JlL2JpdC1tYXRyaXguanMiLCJsaWIvY29yZS9ieXRlLWRhdGEuanMiLCJsaWIvY29yZS9lcnJvci1jb3JyZWN0aW9uLWNvZGUuanMiLCJsaWIvY29yZS9lcnJvci1jb3JyZWN0aW9uLWxldmVsLmpzIiwibGliL2NvcmUvZmluZGVyLXBhdHRlcm4uanMiLCJsaWIvY29yZS9mb3JtYXQtaW5mby5qcyIsImxpYi9jb3JlL2dhbG9pcy1maWVsZC5qcyIsImxpYi9jb3JlL2thbmppLWRhdGEuanMiLCJsaWIvY29yZS9tYXNrLXBhdHRlcm4uanMiLCJsaWIvY29yZS9tb2RlLmpzIiwibGliL2NvcmUvbnVtZXJpYy1kYXRhLmpzIiwibGliL2NvcmUvcG9seW5vbWlhbC5qcyIsImxpYi9jb3JlL3FyY29kZS5qcyIsImxpYi9jb3JlL3JlZWQtc29sb21vbi1lbmNvZGVyLmpzIiwibGliL2NvcmUvcmVnZXguanMiLCJsaWIvY29yZS9zZWdtZW50cy5qcyIsImxpYi9jb3JlL3V0aWxzLmpzIiwibGliL2NvcmUvdmVyc2lvbi1jaGVjay5qcyIsImxpYi9jb3JlL3ZlcnNpb24uanMiLCJsaWIvaW5kZXguanMiLCJsaWIvcmVuZGVyZXIvY2FudmFzLmpzIiwibGliL3JlbmRlcmVyL3N2Zy10YWcuanMiLCJsaWIvcmVuZGVyZXIvdXRpbHMuanMiLCJsaWIvdXRpbHMvdHlwZWRhcnJheS1idWZmZXIuanMiLCJub2RlX21vZHVsZXMvZGlqa3N0cmFqcy9kaWprc3RyYS5qcyIsIm5vZGVfbW9kdWxlcy9pc2FycmF5L2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3REQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25mQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoZ0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvLyBjYW4tcHJvbWlzZSBoYXMgYSBjcmFzaCBpbiBzb21lIHZlcnNpb25zIG9mIHJlYWN0IG5hdGl2ZSB0aGF0IGRvbnQgaGF2ZVxuLy8gc3RhbmRhcmQgZ2xvYmFsIG9iamVjdHNcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9zb2xkYWlyL25vZGUtcXJjb2RlL2lzc3Vlcy8xNTdcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0eXBlb2YgUHJvbWlzZSA9PT0gJ2Z1bmN0aW9uJyAmJiBQcm9taXNlLnByb3RvdHlwZSAmJiBQcm9taXNlLnByb3RvdHlwZS50aGVuXG59XG4iLCIvKipcbiAqIEFsaWdubWVudCBwYXR0ZXJuIGFyZSBmaXhlZCByZWZlcmVuY2UgcGF0dGVybiBpbiBkZWZpbmVkIHBvc2l0aW9uc1xuICogaW4gYSBtYXRyaXggc3ltYm9sb2d5LCB3aGljaCBlbmFibGVzIHRoZSBkZWNvZGUgc29mdHdhcmUgdG8gcmUtc3luY2hyb25pc2VcbiAqIHRoZSBjb29yZGluYXRlIG1hcHBpbmcgb2YgdGhlIGltYWdlIG1vZHVsZXMgaW4gdGhlIGV2ZW50IG9mIG1vZGVyYXRlIGFtb3VudHNcbiAqIG9mIGRpc3RvcnRpb24gb2YgdGhlIGltYWdlLlxuICpcbiAqIEFsaWdubWVudCBwYXR0ZXJucyBhcmUgcHJlc2VudCBvbmx5IGluIFFSIENvZGUgc3ltYm9scyBvZiB2ZXJzaW9uIDIgb3IgbGFyZ2VyXG4gKiBhbmQgdGhlaXIgbnVtYmVyIGRlcGVuZHMgb24gdGhlIHN5bWJvbCB2ZXJzaW9uLlxuICovXG5cbnZhciBnZXRTeW1ib2xTaXplID0gcmVxdWlyZSgnLi91dGlscycpLmdldFN5bWJvbFNpemVcblxuLyoqXG4gKiBDYWxjdWxhdGUgdGhlIHJvdy9jb2x1bW4gY29vcmRpbmF0ZXMgb2YgdGhlIGNlbnRlciBtb2R1bGUgb2YgZWFjaCBhbGlnbm1lbnQgcGF0dGVyblxuICogZm9yIHRoZSBzcGVjaWZpZWQgUVIgQ29kZSB2ZXJzaW9uLlxuICpcbiAqIFRoZSBhbGlnbm1lbnQgcGF0dGVybnMgYXJlIHBvc2l0aW9uZWQgc3ltbWV0cmljYWxseSBvbiBlaXRoZXIgc2lkZSBvZiB0aGUgZGlhZ29uYWxcbiAqIHJ1bm5pbmcgZnJvbSB0aGUgdG9wIGxlZnQgY29ybmVyIG9mIHRoZSBzeW1ib2wgdG8gdGhlIGJvdHRvbSByaWdodCBjb3JuZXIuXG4gKlxuICogU2luY2UgcG9zaXRpb25zIGFyZSBzaW1tZXRyaWNhbCBvbmx5IGhhbGYgb2YgdGhlIGNvb3JkaW5hdGVzIGFyZSByZXR1cm5lZC5cbiAqIEVhY2ggaXRlbSBvZiB0aGUgYXJyYXkgd2lsbCByZXByZXNlbnQgaW4gdHVybiB0aGUgeCBhbmQgeSBjb29yZGluYXRlLlxuICogQHNlZSB7QGxpbmsgZ2V0UG9zaXRpb25zfVxuICpcbiAqIEBwYXJhbSAge051bWJlcn0gdmVyc2lvbiBRUiBDb2RlIHZlcnNpb25cbiAqIEByZXR1cm4ge0FycmF5fSAgICAgICAgICBBcnJheSBvZiBjb29yZGluYXRlXG4gKi9cbmV4cG9ydHMuZ2V0Um93Q29sQ29vcmRzID0gZnVuY3Rpb24gZ2V0Um93Q29sQ29vcmRzICh2ZXJzaW9uKSB7XG4gIGlmICh2ZXJzaW9uID09PSAxKSByZXR1cm4gW11cblxuICB2YXIgcG9zQ291bnQgPSBNYXRoLmZsb29yKHZlcnNpb24gLyA3KSArIDJcbiAgdmFyIHNpemUgPSBnZXRTeW1ib2xTaXplKHZlcnNpb24pXG4gIHZhciBpbnRlcnZhbHMgPSBzaXplID09PSAxNDUgPyAyNiA6IE1hdGguY2VpbCgoc2l6ZSAtIDEzKSAvICgyICogcG9zQ291bnQgLSAyKSkgKiAyXG4gIHZhciBwb3NpdGlvbnMgPSBbc2l6ZSAtIDddIC8vIExhc3QgY29vcmQgaXMgYWx3YXlzIChzaXplIC0gNylcblxuICBmb3IgKHZhciBpID0gMTsgaSA8IHBvc0NvdW50IC0gMTsgaSsrKSB7XG4gICAgcG9zaXRpb25zW2ldID0gcG9zaXRpb25zW2kgLSAxXSAtIGludGVydmFsc1xuICB9XG5cbiAgcG9zaXRpb25zLnB1c2goNikgLy8gRmlyc3QgY29vcmQgaXMgYWx3YXlzIDZcblxuICByZXR1cm4gcG9zaXRpb25zLnJldmVyc2UoKVxufVxuXG4vKipcbiAqIFJldHVybnMgYW4gYXJyYXkgY29udGFpbmluZyB0aGUgcG9zaXRpb25zIG9mIGVhY2ggYWxpZ25tZW50IHBhdHRlcm4uXG4gKiBFYWNoIGFycmF5J3MgZWxlbWVudCByZXByZXNlbnQgdGhlIGNlbnRlciBwb2ludCBvZiB0aGUgcGF0dGVybiBhcyAoeCwgeSkgY29vcmRpbmF0ZXNcbiAqXG4gKiBDb29yZGluYXRlcyBhcmUgY2FsY3VsYXRlZCBleHBhbmRpbmcgdGhlIHJvdy9jb2x1bW4gY29vcmRpbmF0ZXMgcmV0dXJuZWQgYnkge0BsaW5rIGdldFJvd0NvbENvb3Jkc31cbiAqIGFuZCBmaWx0ZXJpbmcgb3V0IHRoZSBpdGVtcyB0aGF0IG92ZXJsYXBzIHdpdGggZmluZGVyIHBhdHRlcm5cbiAqXG4gKiBAZXhhbXBsZVxuICogRm9yIGEgVmVyc2lvbiA3IHN5bWJvbCB7QGxpbmsgZ2V0Um93Q29sQ29vcmRzfSByZXR1cm5zIHZhbHVlcyA2LCAyMiBhbmQgMzguXG4gKiBUaGUgYWxpZ25tZW50IHBhdHRlcm5zLCB0aGVyZWZvcmUsIGFyZSB0byBiZSBjZW50ZXJlZCBvbiAocm93LCBjb2x1bW4pXG4gKiBwb3NpdGlvbnMgKDYsMjIpLCAoMjIsNiksICgyMiwyMiksICgyMiwzOCksICgzOCwyMiksICgzOCwzOCkuXG4gKiBOb3RlIHRoYXQgdGhlIGNvb3JkaW5hdGVzICg2LDYpLCAoNiwzOCksICgzOCw2KSBhcmUgb2NjdXBpZWQgYnkgZmluZGVyIHBhdHRlcm5zXG4gKiBhbmQgYXJlIG5vdCB0aGVyZWZvcmUgdXNlZCBmb3IgYWxpZ25tZW50IHBhdHRlcm5zLlxuICpcbiAqIHZhciBwb3MgPSBnZXRQb3NpdGlvbnMoNylcbiAqIC8vIFtbNiwyMl0sIFsyMiw2XSwgWzIyLDIyXSwgWzIyLDM4XSwgWzM4LDIyXSwgWzM4LDM4XV1cbiAqXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IHZlcnNpb24gUVIgQ29kZSB2ZXJzaW9uXG4gKiBAcmV0dXJuIHtBcnJheX0gICAgICAgICAgQXJyYXkgb2YgY29vcmRpbmF0ZXNcbiAqL1xuZXhwb3J0cy5nZXRQb3NpdGlvbnMgPSBmdW5jdGlvbiBnZXRQb3NpdGlvbnMgKHZlcnNpb24pIHtcbiAgdmFyIGNvb3JkcyA9IFtdXG4gIHZhciBwb3MgPSBleHBvcnRzLmdldFJvd0NvbENvb3Jkcyh2ZXJzaW9uKVxuICB2YXIgcG9zTGVuZ3RoID0gcG9zLmxlbmd0aFxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcG9zTGVuZ3RoOyBpKyspIHtcbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IHBvc0xlbmd0aDsgaisrKSB7XG4gICAgICAvLyBTa2lwIGlmIHBvc2l0aW9uIGlzIG9jY3VwaWVkIGJ5IGZpbmRlciBwYXR0ZXJuc1xuICAgICAgaWYgKChpID09PSAwICYmIGogPT09IDApIHx8ICAgICAgICAgICAgIC8vIHRvcC1sZWZ0XG4gICAgICAgICAgKGkgPT09IDAgJiYgaiA9PT0gcG9zTGVuZ3RoIC0gMSkgfHwgLy8gYm90dG9tLWxlZnRcbiAgICAgICAgICAoaSA9PT0gcG9zTGVuZ3RoIC0gMSAmJiBqID09PSAwKSkgeyAvLyB0b3AtcmlnaHRcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgY29vcmRzLnB1c2goW3Bvc1tpXSwgcG9zW2pdXSlcbiAgICB9XG4gIH1cblxuICByZXR1cm4gY29vcmRzXG59XG4iLCJ2YXIgTW9kZSA9IHJlcXVpcmUoJy4vbW9kZScpXG5cbi8qKlxuICogQXJyYXkgb2YgY2hhcmFjdGVycyBhdmFpbGFibGUgaW4gYWxwaGFudW1lcmljIG1vZGVcbiAqXG4gKiBBcyBwZXIgUVIgQ29kZSBzcGVjaWZpY2F0aW9uLCB0byBlYWNoIGNoYXJhY3RlclxuICogaXMgYXNzaWduZWQgYSB2YWx1ZSBmcm9tIDAgdG8gNDQgd2hpY2ggaW4gdGhpcyBjYXNlIGNvaW5jaWRlc1xuICogd2l0aCB0aGUgYXJyYXkgaW5kZXhcbiAqXG4gKiBAdHlwZSB7QXJyYXl9XG4gKi9cbnZhciBBTFBIQV9OVU1fQ0hBUlMgPSBbXG4gICcwJywgJzEnLCAnMicsICczJywgJzQnLCAnNScsICc2JywgJzcnLCAnOCcsICc5JyxcbiAgJ0EnLCAnQicsICdDJywgJ0QnLCAnRScsICdGJywgJ0cnLCAnSCcsICdJJywgJ0onLCAnSycsICdMJywgJ00nLFxuICAnTicsICdPJywgJ1AnLCAnUScsICdSJywgJ1MnLCAnVCcsICdVJywgJ1YnLCAnVycsICdYJywgJ1knLCAnWicsXG4gICcgJywgJyQnLCAnJScsICcqJywgJysnLCAnLScsICcuJywgJy8nLCAnOidcbl1cblxuZnVuY3Rpb24gQWxwaGFudW1lcmljRGF0YSAoZGF0YSkge1xuICB0aGlzLm1vZGUgPSBNb2RlLkFMUEhBTlVNRVJJQ1xuICB0aGlzLmRhdGEgPSBkYXRhXG59XG5cbkFscGhhbnVtZXJpY0RhdGEuZ2V0Qml0c0xlbmd0aCA9IGZ1bmN0aW9uIGdldEJpdHNMZW5ndGggKGxlbmd0aCkge1xuICByZXR1cm4gMTEgKiBNYXRoLmZsb29yKGxlbmd0aCAvIDIpICsgNiAqIChsZW5ndGggJSAyKVxufVxuXG5BbHBoYW51bWVyaWNEYXRhLnByb3RvdHlwZS5nZXRMZW5ndGggPSBmdW5jdGlvbiBnZXRMZW5ndGggKCkge1xuICByZXR1cm4gdGhpcy5kYXRhLmxlbmd0aFxufVxuXG5BbHBoYW51bWVyaWNEYXRhLnByb3RvdHlwZS5nZXRCaXRzTGVuZ3RoID0gZnVuY3Rpb24gZ2V0Qml0c0xlbmd0aCAoKSB7XG4gIHJldHVybiBBbHBoYW51bWVyaWNEYXRhLmdldEJpdHNMZW5ndGgodGhpcy5kYXRhLmxlbmd0aClcbn1cblxuQWxwaGFudW1lcmljRGF0YS5wcm90b3R5cGUud3JpdGUgPSBmdW5jdGlvbiB3cml0ZSAoYml0QnVmZmVyKSB7XG4gIHZhciBpXG5cbiAgLy8gSW5wdXQgZGF0YSBjaGFyYWN0ZXJzIGFyZSBkaXZpZGVkIGludG8gZ3JvdXBzIG9mIHR3byBjaGFyYWN0ZXJzXG4gIC8vIGFuZCBlbmNvZGVkIGFzIDExLWJpdCBiaW5hcnkgY29kZXMuXG4gIGZvciAoaSA9IDA7IGkgKyAyIDw9IHRoaXMuZGF0YS5sZW5ndGg7IGkgKz0gMikge1xuICAgIC8vIFRoZSBjaGFyYWN0ZXIgdmFsdWUgb2YgdGhlIGZpcnN0IGNoYXJhY3RlciBpcyBtdWx0aXBsaWVkIGJ5IDQ1XG4gICAgdmFyIHZhbHVlID0gQUxQSEFfTlVNX0NIQVJTLmluZGV4T2YodGhpcy5kYXRhW2ldKSAqIDQ1XG5cbiAgICAvLyBUaGUgY2hhcmFjdGVyIHZhbHVlIG9mIHRoZSBzZWNvbmQgZGlnaXQgaXMgYWRkZWQgdG8gdGhlIHByb2R1Y3RcbiAgICB2YWx1ZSArPSBBTFBIQV9OVU1fQ0hBUlMuaW5kZXhPZih0aGlzLmRhdGFbaSArIDFdKVxuXG4gICAgLy8gVGhlIHN1bSBpcyB0aGVuIHN0b3JlZCBhcyAxMS1iaXQgYmluYXJ5IG51bWJlclxuICAgIGJpdEJ1ZmZlci5wdXQodmFsdWUsIDExKVxuICB9XG5cbiAgLy8gSWYgdGhlIG51bWJlciBvZiBpbnB1dCBkYXRhIGNoYXJhY3RlcnMgaXMgbm90IGEgbXVsdGlwbGUgb2YgdHdvLFxuICAvLyB0aGUgY2hhcmFjdGVyIHZhbHVlIG9mIHRoZSBmaW5hbCBjaGFyYWN0ZXIgaXMgZW5jb2RlZCBhcyBhIDYtYml0IGJpbmFyeSBudW1iZXIuXG4gIGlmICh0aGlzLmRhdGEubGVuZ3RoICUgMikge1xuICAgIGJpdEJ1ZmZlci5wdXQoQUxQSEFfTlVNX0NIQVJTLmluZGV4T2YodGhpcy5kYXRhW2ldKSwgNilcbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IEFscGhhbnVtZXJpY0RhdGFcbiIsImZ1bmN0aW9uIEJpdEJ1ZmZlciAoKSB7XG4gIHRoaXMuYnVmZmVyID0gW11cbiAgdGhpcy5sZW5ndGggPSAwXG59XG5cbkJpdEJ1ZmZlci5wcm90b3R5cGUgPSB7XG5cbiAgZ2V0OiBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgICB2YXIgYnVmSW5kZXggPSBNYXRoLmZsb29yKGluZGV4IC8gOClcbiAgICByZXR1cm4gKCh0aGlzLmJ1ZmZlcltidWZJbmRleF0gPj4+ICg3IC0gaW5kZXggJSA4KSkgJiAxKSA9PT0gMVxuICB9LFxuXG4gIHB1dDogZnVuY3Rpb24gKG51bSwgbGVuZ3RoKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5wdXRCaXQoKChudW0gPj4+IChsZW5ndGggLSBpIC0gMSkpICYgMSkgPT09IDEpXG4gICAgfVxuICB9LFxuXG4gIGdldExlbmd0aEluQml0czogZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmxlbmd0aFxuICB9LFxuXG4gIHB1dEJpdDogZnVuY3Rpb24gKGJpdCkge1xuICAgIHZhciBidWZJbmRleCA9IE1hdGguZmxvb3IodGhpcy5sZW5ndGggLyA4KVxuICAgIGlmICh0aGlzLmJ1ZmZlci5sZW5ndGggPD0gYnVmSW5kZXgpIHtcbiAgICAgIHRoaXMuYnVmZmVyLnB1c2goMClcbiAgICB9XG5cbiAgICBpZiAoYml0KSB7XG4gICAgICB0aGlzLmJ1ZmZlcltidWZJbmRleF0gfD0gKDB4ODAgPj4+ICh0aGlzLmxlbmd0aCAlIDgpKVxuICAgIH1cblxuICAgIHRoaXMubGVuZ3RoKytcbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IEJpdEJ1ZmZlclxuIiwidmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4uL3V0aWxzL2J1ZmZlcicpXG5cbi8qKlxuICogSGVscGVyIGNsYXNzIHRvIGhhbmRsZSBRUiBDb2RlIHN5bWJvbCBtb2R1bGVzXG4gKlxuICogQHBhcmFtIHtOdW1iZXJ9IHNpemUgU3ltYm9sIHNpemVcbiAqL1xuZnVuY3Rpb24gQml0TWF0cml4IChzaXplKSB7XG4gIGlmICghc2l6ZSB8fCBzaXplIDwgMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQml0TWF0cml4IHNpemUgbXVzdCBiZSBkZWZpbmVkIGFuZCBncmVhdGVyIHRoYW4gMCcpXG4gIH1cblxuICB0aGlzLnNpemUgPSBzaXplXG4gIHRoaXMuZGF0YSA9IG5ldyBCdWZmZXIoc2l6ZSAqIHNpemUpXG4gIHRoaXMuZGF0YS5maWxsKDApXG4gIHRoaXMucmVzZXJ2ZWRCaXQgPSBuZXcgQnVmZmVyKHNpemUgKiBzaXplKVxuICB0aGlzLnJlc2VydmVkQml0LmZpbGwoMClcbn1cblxuLyoqXG4gKiBTZXQgYml0IHZhbHVlIGF0IHNwZWNpZmllZCBsb2NhdGlvblxuICogSWYgcmVzZXJ2ZWQgZmxhZyBpcyBzZXQsIHRoaXMgYml0IHdpbGwgYmUgaWdub3JlZCBkdXJpbmcgbWFza2luZyBwcm9jZXNzXG4gKlxuICogQHBhcmFtIHtOdW1iZXJ9ICByb3dcbiAqIEBwYXJhbSB7TnVtYmVyfSAgY29sXG4gKiBAcGFyYW0ge0Jvb2xlYW59IHZhbHVlXG4gKiBAcGFyYW0ge0Jvb2xlYW59IHJlc2VydmVkXG4gKi9cbkJpdE1hdHJpeC5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24gKHJvdywgY29sLCB2YWx1ZSwgcmVzZXJ2ZWQpIHtcbiAgdmFyIGluZGV4ID0gcm93ICogdGhpcy5zaXplICsgY29sXG4gIHRoaXMuZGF0YVtpbmRleF0gPSB2YWx1ZVxuICBpZiAocmVzZXJ2ZWQpIHRoaXMucmVzZXJ2ZWRCaXRbaW5kZXhdID0gdHJ1ZVxufVxuXG4vKipcbiAqIFJldHVybnMgYml0IHZhbHVlIGF0IHNwZWNpZmllZCBsb2NhdGlvblxuICpcbiAqIEBwYXJhbSAge051bWJlcn0gIHJvd1xuICogQHBhcmFtICB7TnVtYmVyfSAgY29sXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICovXG5CaXRNYXRyaXgucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uIChyb3csIGNvbCkge1xuICByZXR1cm4gdGhpcy5kYXRhW3JvdyAqIHRoaXMuc2l6ZSArIGNvbF1cbn1cblxuLyoqXG4gKiBBcHBsaWVzIHhvciBvcGVyYXRvciBhdCBzcGVjaWZpZWQgbG9jYXRpb25cbiAqICh1c2VkIGR1cmluZyBtYXNraW5nIHByb2Nlc3MpXG4gKlxuICogQHBhcmFtIHtOdW1iZXJ9ICByb3dcbiAqIEBwYXJhbSB7TnVtYmVyfSAgY29sXG4gKiBAcGFyYW0ge0Jvb2xlYW59IHZhbHVlXG4gKi9cbkJpdE1hdHJpeC5wcm90b3R5cGUueG9yID0gZnVuY3Rpb24gKHJvdywgY29sLCB2YWx1ZSkge1xuICB0aGlzLmRhdGFbcm93ICogdGhpcy5zaXplICsgY29sXSBePSB2YWx1ZVxufVxuXG4vKipcbiAqIENoZWNrIGlmIGJpdCBhdCBzcGVjaWZpZWQgbG9jYXRpb24gaXMgcmVzZXJ2ZWRcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0gICByb3dcbiAqIEBwYXJhbSB7TnVtYmVyfSAgIGNvbFxuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqL1xuQml0TWF0cml4LnByb3RvdHlwZS5pc1Jlc2VydmVkID0gZnVuY3Rpb24gKHJvdywgY29sKSB7XG4gIHJldHVybiB0aGlzLnJlc2VydmVkQml0W3JvdyAqIHRoaXMuc2l6ZSArIGNvbF1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBCaXRNYXRyaXhcbiIsInZhciBCdWZmZXIgPSByZXF1aXJlKCcuLi91dGlscy9idWZmZXInKVxudmFyIE1vZGUgPSByZXF1aXJlKCcuL21vZGUnKVxuXG5mdW5jdGlvbiBCeXRlRGF0YSAoZGF0YSkge1xuICB0aGlzLm1vZGUgPSBNb2RlLkJZVEVcbiAgdGhpcy5kYXRhID0gbmV3IEJ1ZmZlcihkYXRhKVxufVxuXG5CeXRlRGF0YS5nZXRCaXRzTGVuZ3RoID0gZnVuY3Rpb24gZ2V0Qml0c0xlbmd0aCAobGVuZ3RoKSB7XG4gIHJldHVybiBsZW5ndGggKiA4XG59XG5cbkJ5dGVEYXRhLnByb3RvdHlwZS5nZXRMZW5ndGggPSBmdW5jdGlvbiBnZXRMZW5ndGggKCkge1xuICByZXR1cm4gdGhpcy5kYXRhLmxlbmd0aFxufVxuXG5CeXRlRGF0YS5wcm90b3R5cGUuZ2V0Qml0c0xlbmd0aCA9IGZ1bmN0aW9uIGdldEJpdHNMZW5ndGggKCkge1xuICByZXR1cm4gQnl0ZURhdGEuZ2V0Qml0c0xlbmd0aCh0aGlzLmRhdGEubGVuZ3RoKVxufVxuXG5CeXRlRGF0YS5wcm90b3R5cGUud3JpdGUgPSBmdW5jdGlvbiAoYml0QnVmZmVyKSB7XG4gIGZvciAodmFyIGkgPSAwLCBsID0gdGhpcy5kYXRhLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIGJpdEJ1ZmZlci5wdXQodGhpcy5kYXRhW2ldLCA4KVxuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gQnl0ZURhdGFcbiIsInZhciBFQ0xldmVsID0gcmVxdWlyZSgnLi9lcnJvci1jb3JyZWN0aW9uLWxldmVsJylcclxuXHJcbnZhciBFQ19CTE9DS1NfVEFCTEUgPSBbXHJcbi8vIEwgIE0gIFEgIEhcclxuICAxLCAxLCAxLCAxLFxyXG4gIDEsIDEsIDEsIDEsXHJcbiAgMSwgMSwgMiwgMixcclxuICAxLCAyLCAyLCA0LFxyXG4gIDEsIDIsIDQsIDQsXHJcbiAgMiwgNCwgNCwgNCxcclxuICAyLCA0LCA2LCA1LFxyXG4gIDIsIDQsIDYsIDYsXHJcbiAgMiwgNSwgOCwgOCxcclxuICA0LCA1LCA4LCA4LFxyXG4gIDQsIDUsIDgsIDExLFxyXG4gIDQsIDgsIDEwLCAxMSxcclxuICA0LCA5LCAxMiwgMTYsXHJcbiAgNCwgOSwgMTYsIDE2LFxyXG4gIDYsIDEwLCAxMiwgMTgsXHJcbiAgNiwgMTAsIDE3LCAxNixcclxuICA2LCAxMSwgMTYsIDE5LFxyXG4gIDYsIDEzLCAxOCwgMjEsXHJcbiAgNywgMTQsIDIxLCAyNSxcclxuICA4LCAxNiwgMjAsIDI1LFxyXG4gIDgsIDE3LCAyMywgMjUsXHJcbiAgOSwgMTcsIDIzLCAzNCxcclxuICA5LCAxOCwgMjUsIDMwLFxyXG4gIDEwLCAyMCwgMjcsIDMyLFxyXG4gIDEyLCAyMSwgMjksIDM1LFxyXG4gIDEyLCAyMywgMzQsIDM3LFxyXG4gIDEyLCAyNSwgMzQsIDQwLFxyXG4gIDEzLCAyNiwgMzUsIDQyLFxyXG4gIDE0LCAyOCwgMzgsIDQ1LFxyXG4gIDE1LCAyOSwgNDAsIDQ4LFxyXG4gIDE2LCAzMSwgNDMsIDUxLFxyXG4gIDE3LCAzMywgNDUsIDU0LFxyXG4gIDE4LCAzNSwgNDgsIDU3LFxyXG4gIDE5LCAzNywgNTEsIDYwLFxyXG4gIDE5LCAzOCwgNTMsIDYzLFxyXG4gIDIwLCA0MCwgNTYsIDY2LFxyXG4gIDIxLCA0MywgNTksIDcwLFxyXG4gIDIyLCA0NSwgNjIsIDc0LFxyXG4gIDI0LCA0NywgNjUsIDc3LFxyXG4gIDI1LCA0OSwgNjgsIDgxXHJcbl1cclxuXHJcbnZhciBFQ19DT0RFV09SRFNfVEFCTEUgPSBbXHJcbi8vIEwgIE0gIFEgIEhcclxuICA3LCAxMCwgMTMsIDE3LFxyXG4gIDEwLCAxNiwgMjIsIDI4LFxyXG4gIDE1LCAyNiwgMzYsIDQ0LFxyXG4gIDIwLCAzNiwgNTIsIDY0LFxyXG4gIDI2LCA0OCwgNzIsIDg4LFxyXG4gIDM2LCA2NCwgOTYsIDExMixcclxuICA0MCwgNzIsIDEwOCwgMTMwLFxyXG4gIDQ4LCA4OCwgMTMyLCAxNTYsXHJcbiAgNjAsIDExMCwgMTYwLCAxOTIsXHJcbiAgNzIsIDEzMCwgMTkyLCAyMjQsXHJcbiAgODAsIDE1MCwgMjI0LCAyNjQsXHJcbiAgOTYsIDE3NiwgMjYwLCAzMDgsXHJcbiAgMTA0LCAxOTgsIDI4OCwgMzUyLFxyXG4gIDEyMCwgMjE2LCAzMjAsIDM4NCxcclxuICAxMzIsIDI0MCwgMzYwLCA0MzIsXHJcbiAgMTQ0LCAyODAsIDQwOCwgNDgwLFxyXG4gIDE2OCwgMzA4LCA0NDgsIDUzMixcclxuICAxODAsIDMzOCwgNTA0LCA1ODgsXHJcbiAgMTk2LCAzNjQsIDU0NiwgNjUwLFxyXG4gIDIyNCwgNDE2LCA2MDAsIDcwMCxcclxuICAyMjQsIDQ0MiwgNjQ0LCA3NTAsXHJcbiAgMjUyLCA0NzYsIDY5MCwgODE2LFxyXG4gIDI3MCwgNTA0LCA3NTAsIDkwMCxcclxuICAzMDAsIDU2MCwgODEwLCA5NjAsXHJcbiAgMzEyLCA1ODgsIDg3MCwgMTA1MCxcclxuICAzMzYsIDY0NCwgOTUyLCAxMTEwLFxyXG4gIDM2MCwgNzAwLCAxMDIwLCAxMjAwLFxyXG4gIDM5MCwgNzI4LCAxMDUwLCAxMjYwLFxyXG4gIDQyMCwgNzg0LCAxMTQwLCAxMzUwLFxyXG4gIDQ1MCwgODEyLCAxMjAwLCAxNDQwLFxyXG4gIDQ4MCwgODY4LCAxMjkwLCAxNTMwLFxyXG4gIDUxMCwgOTI0LCAxMzUwLCAxNjIwLFxyXG4gIDU0MCwgOTgwLCAxNDQwLCAxNzEwLFxyXG4gIDU3MCwgMTAzNiwgMTUzMCwgMTgwMCxcclxuICA1NzAsIDEwNjQsIDE1OTAsIDE4OTAsXHJcbiAgNjAwLCAxMTIwLCAxNjgwLCAxOTgwLFxyXG4gIDYzMCwgMTIwNCwgMTc3MCwgMjEwMCxcclxuICA2NjAsIDEyNjAsIDE4NjAsIDIyMjAsXHJcbiAgNzIwLCAxMzE2LCAxOTUwLCAyMzEwLFxyXG4gIDc1MCwgMTM3MiwgMjA0MCwgMjQzMFxyXG5dXHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIGVycm9yIGNvcnJlY3Rpb24gYmxvY2sgdGhhdCB0aGUgUVIgQ29kZSBzaG91bGQgY29udGFpblxyXG4gKiBmb3IgdGhlIHNwZWNpZmllZCB2ZXJzaW9uIGFuZCBlcnJvciBjb3JyZWN0aW9uIGxldmVsLlxyXG4gKlxyXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IHZlcnNpb24gICAgICAgICAgICAgIFFSIENvZGUgdmVyc2lvblxyXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IGVycm9yQ29ycmVjdGlvbkxldmVsIEVycm9yIGNvcnJlY3Rpb24gbGV2ZWxcclxuICogQHJldHVybiB7TnVtYmVyfSAgICAgICAgICAgICAgICAgICAgICBOdW1iZXIgb2YgZXJyb3IgY29ycmVjdGlvbiBibG9ja3NcclxuICovXHJcbmV4cG9ydHMuZ2V0QmxvY2tzQ291bnQgPSBmdW5jdGlvbiBnZXRCbG9ja3NDb3VudCAodmVyc2lvbiwgZXJyb3JDb3JyZWN0aW9uTGV2ZWwpIHtcclxuICBzd2l0Y2ggKGVycm9yQ29ycmVjdGlvbkxldmVsKSB7XHJcbiAgICBjYXNlIEVDTGV2ZWwuTDpcclxuICAgICAgcmV0dXJuIEVDX0JMT0NLU19UQUJMRVsodmVyc2lvbiAtIDEpICogNCArIDBdXHJcbiAgICBjYXNlIEVDTGV2ZWwuTTpcclxuICAgICAgcmV0dXJuIEVDX0JMT0NLU19UQUJMRVsodmVyc2lvbiAtIDEpICogNCArIDFdXHJcbiAgICBjYXNlIEVDTGV2ZWwuUTpcclxuICAgICAgcmV0dXJuIEVDX0JMT0NLU19UQUJMRVsodmVyc2lvbiAtIDEpICogNCArIDJdXHJcbiAgICBjYXNlIEVDTGV2ZWwuSDpcclxuICAgICAgcmV0dXJuIEVDX0JMT0NLU19UQUJMRVsodmVyc2lvbiAtIDEpICogNCArIDNdXHJcbiAgICBkZWZhdWx0OlxyXG4gICAgICByZXR1cm4gdW5kZWZpbmVkXHJcbiAgfVxyXG59XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIGVycm9yIGNvcnJlY3Rpb24gY29kZXdvcmRzIHRvIHVzZSBmb3IgdGhlIHNwZWNpZmllZFxyXG4gKiB2ZXJzaW9uIGFuZCBlcnJvciBjb3JyZWN0aW9uIGxldmVsLlxyXG4gKlxyXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IHZlcnNpb24gICAgICAgICAgICAgIFFSIENvZGUgdmVyc2lvblxyXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IGVycm9yQ29ycmVjdGlvbkxldmVsIEVycm9yIGNvcnJlY3Rpb24gbGV2ZWxcclxuICogQHJldHVybiB7TnVtYmVyfSAgICAgICAgICAgICAgICAgICAgICBOdW1iZXIgb2YgZXJyb3IgY29ycmVjdGlvbiBjb2Rld29yZHNcclxuICovXHJcbmV4cG9ydHMuZ2V0VG90YWxDb2Rld29yZHNDb3VudCA9IGZ1bmN0aW9uIGdldFRvdGFsQ29kZXdvcmRzQ291bnQgKHZlcnNpb24sIGVycm9yQ29ycmVjdGlvbkxldmVsKSB7XHJcbiAgc3dpdGNoIChlcnJvckNvcnJlY3Rpb25MZXZlbCkge1xyXG4gICAgY2FzZSBFQ0xldmVsLkw6XHJcbiAgICAgIHJldHVybiBFQ19DT0RFV09SRFNfVEFCTEVbKHZlcnNpb24gLSAxKSAqIDQgKyAwXVxyXG4gICAgY2FzZSBFQ0xldmVsLk06XHJcbiAgICAgIHJldHVybiBFQ19DT0RFV09SRFNfVEFCTEVbKHZlcnNpb24gLSAxKSAqIDQgKyAxXVxyXG4gICAgY2FzZSBFQ0xldmVsLlE6XHJcbiAgICAgIHJldHVybiBFQ19DT0RFV09SRFNfVEFCTEVbKHZlcnNpb24gLSAxKSAqIDQgKyAyXVxyXG4gICAgY2FzZSBFQ0xldmVsLkg6XHJcbiAgICAgIHJldHVybiBFQ19DT0RFV09SRFNfVEFCTEVbKHZlcnNpb24gLSAxKSAqIDQgKyAzXVxyXG4gICAgZGVmYXVsdDpcclxuICAgICAgcmV0dXJuIHVuZGVmaW5lZFxyXG4gIH1cclxufVxyXG4iLCJleHBvcnRzLkwgPSB7IGJpdDogMSB9XG5leHBvcnRzLk0gPSB7IGJpdDogMCB9XG5leHBvcnRzLlEgPSB7IGJpdDogMyB9XG5leHBvcnRzLkggPSB7IGJpdDogMiB9XG5cbmZ1bmN0aW9uIGZyb21TdHJpbmcgKHN0cmluZykge1xuICBpZiAodHlwZW9mIHN0cmluZyAhPT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1BhcmFtIGlzIG5vdCBhIHN0cmluZycpXG4gIH1cblxuICB2YXIgbGNTdHIgPSBzdHJpbmcudG9Mb3dlckNhc2UoKVxuXG4gIHN3aXRjaCAobGNTdHIpIHtcbiAgICBjYXNlICdsJzpcbiAgICBjYXNlICdsb3cnOlxuICAgICAgcmV0dXJuIGV4cG9ydHMuTFxuXG4gICAgY2FzZSAnbSc6XG4gICAgY2FzZSAnbWVkaXVtJzpcbiAgICAgIHJldHVybiBleHBvcnRzLk1cblxuICAgIGNhc2UgJ3EnOlxuICAgIGNhc2UgJ3F1YXJ0aWxlJzpcbiAgICAgIHJldHVybiBleHBvcnRzLlFcblxuICAgIGNhc2UgJ2gnOlxuICAgIGNhc2UgJ2hpZ2gnOlxuICAgICAgcmV0dXJuIGV4cG9ydHMuSFxuXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5rbm93biBFQyBMZXZlbDogJyArIHN0cmluZylcbiAgfVxufVxuXG5leHBvcnRzLmlzVmFsaWQgPSBmdW5jdGlvbiBpc1ZhbGlkIChsZXZlbCkge1xuICByZXR1cm4gbGV2ZWwgJiYgdHlwZW9mIGxldmVsLmJpdCAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICBsZXZlbC5iaXQgPj0gMCAmJiBsZXZlbC5iaXQgPCA0XG59XG5cbmV4cG9ydHMuZnJvbSA9IGZ1bmN0aW9uIGZyb20gKHZhbHVlLCBkZWZhdWx0VmFsdWUpIHtcbiAgaWYgKGV4cG9ydHMuaXNWYWxpZCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gdmFsdWVcbiAgfVxuXG4gIHRyeSB7XG4gICAgcmV0dXJuIGZyb21TdHJpbmcodmFsdWUpXG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZGVmYXVsdFZhbHVlXG4gIH1cbn1cbiIsInZhciBnZXRTeW1ib2xTaXplID0gcmVxdWlyZSgnLi91dGlscycpLmdldFN5bWJvbFNpemVcbnZhciBGSU5ERVJfUEFUVEVSTl9TSVpFID0gN1xuXG4vKipcbiAqIFJldHVybnMgYW4gYXJyYXkgY29udGFpbmluZyB0aGUgcG9zaXRpb25zIG9mIGVhY2ggZmluZGVyIHBhdHRlcm4uXG4gKiBFYWNoIGFycmF5J3MgZWxlbWVudCByZXByZXNlbnQgdGhlIHRvcC1sZWZ0IHBvaW50IG9mIHRoZSBwYXR0ZXJuIGFzICh4LCB5KSBjb29yZGluYXRlc1xuICpcbiAqIEBwYXJhbSAge051bWJlcn0gdmVyc2lvbiBRUiBDb2RlIHZlcnNpb25cbiAqIEByZXR1cm4ge0FycmF5fSAgICAgICAgICBBcnJheSBvZiBjb29yZGluYXRlc1xuICovXG5leHBvcnRzLmdldFBvc2l0aW9ucyA9IGZ1bmN0aW9uIGdldFBvc2l0aW9ucyAodmVyc2lvbikge1xuICB2YXIgc2l6ZSA9IGdldFN5bWJvbFNpemUodmVyc2lvbilcblxuICByZXR1cm4gW1xuICAgIC8vIHRvcC1sZWZ0XG4gICAgWzAsIDBdLFxuICAgIC8vIHRvcC1yaWdodFxuICAgIFtzaXplIC0gRklOREVSX1BBVFRFUk5fU0laRSwgMF0sXG4gICAgLy8gYm90dG9tLWxlZnRcbiAgICBbMCwgc2l6ZSAtIEZJTkRFUl9QQVRURVJOX1NJWkVdXG4gIF1cbn1cbiIsInZhciBVdGlscyA9IHJlcXVpcmUoJy4vdXRpbHMnKVxuXG52YXIgRzE1ID0gKDEgPDwgMTApIHwgKDEgPDwgOCkgfCAoMSA8PCA1KSB8ICgxIDw8IDQpIHwgKDEgPDwgMikgfCAoMSA8PCAxKSB8ICgxIDw8IDApXG52YXIgRzE1X01BU0sgPSAoMSA8PCAxNCkgfCAoMSA8PCAxMikgfCAoMSA8PCAxMCkgfCAoMSA8PCA0KSB8ICgxIDw8IDEpXG52YXIgRzE1X0JDSCA9IFV0aWxzLmdldEJDSERpZ2l0KEcxNSlcblxuLyoqXG4gKiBSZXR1cm5zIGZvcm1hdCBpbmZvcm1hdGlvbiB3aXRoIHJlbGF0aXZlIGVycm9yIGNvcnJlY3Rpb24gYml0c1xuICpcbiAqIFRoZSBmb3JtYXQgaW5mb3JtYXRpb24gaXMgYSAxNS1iaXQgc2VxdWVuY2UgY29udGFpbmluZyA1IGRhdGEgYml0cyxcbiAqIHdpdGggMTAgZXJyb3IgY29ycmVjdGlvbiBiaXRzIGNhbGN1bGF0ZWQgdXNpbmcgdGhlICgxNSwgNSkgQkNIIGNvZGUuXG4gKlxuICogQHBhcmFtICB7TnVtYmVyfSBlcnJvckNvcnJlY3Rpb25MZXZlbCBFcnJvciBjb3JyZWN0aW9uIGxldmVsXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IG1hc2sgICAgICAgICAgICAgICAgIE1hc2sgcGF0dGVyblxuICogQHJldHVybiB7TnVtYmVyfSAgICAgICAgICAgICAgICAgICAgICBFbmNvZGVkIGZvcm1hdCBpbmZvcm1hdGlvbiBiaXRzXG4gKi9cbmV4cG9ydHMuZ2V0RW5jb2RlZEJpdHMgPSBmdW5jdGlvbiBnZXRFbmNvZGVkQml0cyAoZXJyb3JDb3JyZWN0aW9uTGV2ZWwsIG1hc2spIHtcbiAgdmFyIGRhdGEgPSAoKGVycm9yQ29ycmVjdGlvbkxldmVsLmJpdCA8PCAzKSB8IG1hc2spXG4gIHZhciBkID0gZGF0YSA8PCAxMFxuXG4gIHdoaWxlIChVdGlscy5nZXRCQ0hEaWdpdChkKSAtIEcxNV9CQ0ggPj0gMCkge1xuICAgIGQgXj0gKEcxNSA8PCAoVXRpbHMuZ2V0QkNIRGlnaXQoZCkgLSBHMTVfQkNIKSlcbiAgfVxuXG4gIC8vIHhvciBmaW5hbCBkYXRhIHdpdGggbWFzayBwYXR0ZXJuIGluIG9yZGVyIHRvIGVuc3VyZSB0aGF0XG4gIC8vIG5vIGNvbWJpbmF0aW9uIG9mIEVycm9yIENvcnJlY3Rpb24gTGV2ZWwgYW5kIGRhdGEgbWFzayBwYXR0ZXJuXG4gIC8vIHdpbGwgcmVzdWx0IGluIGFuIGFsbC16ZXJvIGRhdGEgc3RyaW5nXG4gIHJldHVybiAoKGRhdGEgPDwgMTApIHwgZCkgXiBHMTVfTUFTS1xufVxuIiwidmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4uL3V0aWxzL2J1ZmZlcicpXG5cbnZhciBFWFBfVEFCTEVcbnZhciBMT0dfVEFCTEVcblxuaWYgKEJ1ZmZlci5hbGxvYykge1xuICBFWFBfVEFCTEUgPSBCdWZmZXIuYWxsb2MoNTEyKVxuICBMT0dfVEFCTEUgPSBCdWZmZXIuYWxsb2MoMjU2KVxufSBlbHNlIHtcbiAgRVhQX1RBQkxFID0gbmV3IEJ1ZmZlcig1MTIpXG4gIExPR19UQUJMRSA9IG5ldyBCdWZmZXIoMjU2KVxufVxuLyoqXG4gKiBQcmVjb21wdXRlIHRoZSBsb2cgYW5kIGFudGktbG9nIHRhYmxlcyBmb3IgZmFzdGVyIGNvbXB1dGF0aW9uIGxhdGVyXG4gKlxuICogRm9yIGVhY2ggcG9zc2libGUgdmFsdWUgaW4gdGhlIGdhbG9pcyBmaWVsZCAyXjgsIHdlIHdpbGwgcHJlLWNvbXB1dGVcbiAqIHRoZSBsb2dhcml0aG0gYW5kIGFudGktbG9nYXJpdGhtIChleHBvbmVudGlhbCkgb2YgdGhpcyB2YWx1ZVxuICpcbiAqIHJlZiB7QGxpbmsgaHR0cHM6Ly9lbi53aWtpdmVyc2l0eS5vcmcvd2lraS9SZWVkJUUyJTgwJTkzU29sb21vbl9jb2Rlc19mb3JfY29kZXJzI0ludHJvZHVjdGlvbl90b19tYXRoZW1hdGljYWxfZmllbGRzfVxuICovXG47KGZ1bmN0aW9uIGluaXRUYWJsZXMgKCkge1xuICB2YXIgeCA9IDFcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAyNTU7IGkrKykge1xuICAgIEVYUF9UQUJMRVtpXSA9IHhcbiAgICBMT0dfVEFCTEVbeF0gPSBpXG5cbiAgICB4IDw8PSAxIC8vIG11bHRpcGx5IGJ5IDJcblxuICAgIC8vIFRoZSBRUiBjb2RlIHNwZWNpZmljYXRpb24gc2F5cyB0byB1c2UgYnl0ZS13aXNlIG1vZHVsbyAxMDAwMTExMDEgYXJpdGhtZXRpYy5cbiAgICAvLyBUaGlzIG1lYW5zIHRoYXQgd2hlbiBhIG51bWJlciBpcyAyNTYgb3IgbGFyZ2VyLCBpdCBzaG91bGQgYmUgWE9SZWQgd2l0aCAweDExRC5cbiAgICBpZiAoeCAmIDB4MTAwKSB7IC8vIHNpbWlsYXIgdG8geCA+PSAyNTYsIGJ1dCBhIGxvdCBmYXN0ZXIgKGJlY2F1c2UgMHgxMDAgPT0gMjU2KVxuICAgICAgeCBePSAweDExRFxuICAgIH1cbiAgfVxuXG4gIC8vIE9wdGltaXphdGlvbjogZG91YmxlIHRoZSBzaXplIG9mIHRoZSBhbnRpLWxvZyB0YWJsZSBzbyB0aGF0IHdlIGRvbid0IG5lZWQgdG8gbW9kIDI1NSB0b1xuICAvLyBzdGF5IGluc2lkZSB0aGUgYm91bmRzIChiZWNhdXNlIHdlIHdpbGwgbWFpbmx5IHVzZSB0aGlzIHRhYmxlIGZvciB0aGUgbXVsdGlwbGljYXRpb24gb2ZcbiAgLy8gdHdvIEdGIG51bWJlcnMsIG5vIG1vcmUpLlxuICAvLyBAc2VlIHtAbGluayBtdWx9XG4gIGZvciAoaSA9IDI1NTsgaSA8IDUxMjsgaSsrKSB7XG4gICAgRVhQX1RBQkxFW2ldID0gRVhQX1RBQkxFW2kgLSAyNTVdXG4gIH1cbn0oKSlcblxuLyoqXG4gKiBSZXR1cm5zIGxvZyB2YWx1ZSBvZiBuIGluc2lkZSBHYWxvaXMgRmllbGRcbiAqXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IG5cbiAqIEByZXR1cm4ge051bWJlcn1cbiAqL1xuZXhwb3J0cy5sb2cgPSBmdW5jdGlvbiBsb2cgKG4pIHtcbiAgaWYgKG4gPCAxKSB0aHJvdyBuZXcgRXJyb3IoJ2xvZygnICsgbiArICcpJylcbiAgcmV0dXJuIExPR19UQUJMRVtuXVxufVxuXG4vKipcbiAqIFJldHVybnMgYW50aS1sb2cgdmFsdWUgb2YgbiBpbnNpZGUgR2Fsb2lzIEZpZWxkXG4gKlxuICogQHBhcmFtICB7TnVtYmVyfSBuXG4gKiBAcmV0dXJuIHtOdW1iZXJ9XG4gKi9cbmV4cG9ydHMuZXhwID0gZnVuY3Rpb24gZXhwIChuKSB7XG4gIHJldHVybiBFWFBfVEFCTEVbbl1cbn1cblxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byBudW1iZXIgaW5zaWRlIEdhbG9pcyBGaWVsZFxuICpcbiAqIEBwYXJhbSAge051bWJlcn0geFxuICogQHBhcmFtICB7TnVtYmVyfSB5XG4gKiBAcmV0dXJuIHtOdW1iZXJ9XG4gKi9cbmV4cG9ydHMubXVsID0gZnVuY3Rpb24gbXVsICh4LCB5KSB7XG4gIGlmICh4ID09PSAwIHx8IHkgPT09IDApIHJldHVybiAwXG5cbiAgLy8gc2hvdWxkIGJlIEVYUF9UQUJMRVsoTE9HX1RBQkxFW3hdICsgTE9HX1RBQkxFW3ldKSAlIDI1NV0gaWYgRVhQX1RBQkxFIHdhc24ndCBvdmVyc2l6ZWRcbiAgLy8gQHNlZSB7QGxpbmsgaW5pdFRhYmxlc31cbiAgcmV0dXJuIEVYUF9UQUJMRVtMT0dfVEFCTEVbeF0gKyBMT0dfVEFCTEVbeV1dXG59XG4iLCJ2YXIgTW9kZSA9IHJlcXVpcmUoJy4vbW9kZScpXG52YXIgVXRpbHMgPSByZXF1aXJlKCcuL3V0aWxzJylcblxuZnVuY3Rpb24gS2FuamlEYXRhIChkYXRhKSB7XG4gIHRoaXMubW9kZSA9IE1vZGUuS0FOSklcbiAgdGhpcy5kYXRhID0gZGF0YVxufVxuXG5LYW5qaURhdGEuZ2V0Qml0c0xlbmd0aCA9IGZ1bmN0aW9uIGdldEJpdHNMZW5ndGggKGxlbmd0aCkge1xuICByZXR1cm4gbGVuZ3RoICogMTNcbn1cblxuS2FuamlEYXRhLnByb3RvdHlwZS5nZXRMZW5ndGggPSBmdW5jdGlvbiBnZXRMZW5ndGggKCkge1xuICByZXR1cm4gdGhpcy5kYXRhLmxlbmd0aFxufVxuXG5LYW5qaURhdGEucHJvdG90eXBlLmdldEJpdHNMZW5ndGggPSBmdW5jdGlvbiBnZXRCaXRzTGVuZ3RoICgpIHtcbiAgcmV0dXJuIEthbmppRGF0YS5nZXRCaXRzTGVuZ3RoKHRoaXMuZGF0YS5sZW5ndGgpXG59XG5cbkthbmppRGF0YS5wcm90b3R5cGUud3JpdGUgPSBmdW5jdGlvbiAoYml0QnVmZmVyKSB7XG4gIHZhciBpXG5cbiAgLy8gSW4gdGhlIFNoaWZ0IEpJUyBzeXN0ZW0sIEthbmppIGNoYXJhY3RlcnMgYXJlIHJlcHJlc2VudGVkIGJ5IGEgdHdvIGJ5dGUgY29tYmluYXRpb24uXG4gIC8vIFRoZXNlIGJ5dGUgdmFsdWVzIGFyZSBzaGlmdGVkIGZyb20gdGhlIEpJUyBYIDAyMDggdmFsdWVzLlxuICAvLyBKSVMgWCAwMjA4IGdpdmVzIGRldGFpbHMgb2YgdGhlIHNoaWZ0IGNvZGVkIHJlcHJlc2VudGF0aW9uLlxuICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5kYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHZhbHVlID0gVXRpbHMudG9TSklTKHRoaXMuZGF0YVtpXSlcblxuICAgIC8vIEZvciBjaGFyYWN0ZXJzIHdpdGggU2hpZnQgSklTIHZhbHVlcyBmcm9tIDB4ODE0MCB0byAweDlGRkM6XG4gICAgaWYgKHZhbHVlID49IDB4ODE0MCAmJiB2YWx1ZSA8PSAweDlGRkMpIHtcbiAgICAgIC8vIFN1YnRyYWN0IDB4ODE0MCBmcm9tIFNoaWZ0IEpJUyB2YWx1ZVxuICAgICAgdmFsdWUgLT0gMHg4MTQwXG5cbiAgICAvLyBGb3IgY2hhcmFjdGVycyB3aXRoIFNoaWZ0IEpJUyB2YWx1ZXMgZnJvbSAweEUwNDAgdG8gMHhFQkJGXG4gICAgfSBlbHNlIGlmICh2YWx1ZSA+PSAweEUwNDAgJiYgdmFsdWUgPD0gMHhFQkJGKSB7XG4gICAgICAvLyBTdWJ0cmFjdCAweEMxNDAgZnJvbSBTaGlmdCBKSVMgdmFsdWVcbiAgICAgIHZhbHVlIC09IDB4QzE0MFxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdJbnZhbGlkIFNKSVMgY2hhcmFjdGVyOiAnICsgdGhpcy5kYXRhW2ldICsgJ1xcbicgK1xuICAgICAgICAnTWFrZSBzdXJlIHlvdXIgY2hhcnNldCBpcyBVVEYtOCcpXG4gICAgfVxuXG4gICAgLy8gTXVsdGlwbHkgbW9zdCBzaWduaWZpY2FudCBieXRlIG9mIHJlc3VsdCBieSAweEMwXG4gICAgLy8gYW5kIGFkZCBsZWFzdCBzaWduaWZpY2FudCBieXRlIHRvIHByb2R1Y3RcbiAgICB2YWx1ZSA9ICgoKHZhbHVlID4+PiA4KSAmIDB4ZmYpICogMHhDMCkgKyAodmFsdWUgJiAweGZmKVxuXG4gICAgLy8gQ29udmVydCByZXN1bHQgdG8gYSAxMy1iaXQgYmluYXJ5IHN0cmluZ1xuICAgIGJpdEJ1ZmZlci5wdXQodmFsdWUsIDEzKVxuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gS2FuamlEYXRhXG4iLCIvKipcbiAqIERhdGEgbWFzayBwYXR0ZXJuIHJlZmVyZW5jZVxuICogQHR5cGUge09iamVjdH1cbiAqL1xuZXhwb3J0cy5QYXR0ZXJucyA9IHtcbiAgUEFUVEVSTjAwMDogMCxcbiAgUEFUVEVSTjAwMTogMSxcbiAgUEFUVEVSTjAxMDogMixcbiAgUEFUVEVSTjAxMTogMyxcbiAgUEFUVEVSTjEwMDogNCxcbiAgUEFUVEVSTjEwMTogNSxcbiAgUEFUVEVSTjExMDogNixcbiAgUEFUVEVSTjExMTogN1xufVxuXG4vKipcbiAqIFdlaWdodGVkIHBlbmFsdHkgc2NvcmVzIGZvciB0aGUgdW5kZXNpcmFibGUgZmVhdHVyZXNcbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cbnZhciBQZW5hbHR5U2NvcmVzID0ge1xuICBOMTogMyxcbiAgTjI6IDMsXG4gIE4zOiA0MCxcbiAgTjQ6IDEwXG59XG5cbi8qKlxuICogQ2hlY2sgaWYgbWFzayBwYXR0ZXJuIHZhbHVlIGlzIHZhbGlkXG4gKlxuICogQHBhcmFtICB7TnVtYmVyfSAgbWFzayAgICBNYXNrIHBhdHRlcm5cbiAqIEByZXR1cm4ge0Jvb2xlYW59ICAgICAgICAgdHJ1ZSBpZiB2YWxpZCwgZmFsc2Ugb3RoZXJ3aXNlXG4gKi9cbmV4cG9ydHMuaXNWYWxpZCA9IGZ1bmN0aW9uIGlzVmFsaWQgKG1hc2spIHtcbiAgcmV0dXJuIG1hc2sgIT0gbnVsbCAmJiBtYXNrICE9PSAnJyAmJiAhaXNOYU4obWFzaykgJiYgbWFzayA+PSAwICYmIG1hc2sgPD0gN1xufVxuXG4vKipcbiAqIFJldHVybnMgbWFzayBwYXR0ZXJuIGZyb20gYSB2YWx1ZS5cbiAqIElmIHZhbHVlIGlzIG5vdCB2YWxpZCwgcmV0dXJucyB1bmRlZmluZWRcbiAqXG4gKiBAcGFyYW0gIHtOdW1iZXJ8U3RyaW5nfSB2YWx1ZSAgICAgICAgTWFzayBwYXR0ZXJuIHZhbHVlXG4gKiBAcmV0dXJuIHtOdW1iZXJ9ICAgICAgICAgICAgICAgICAgICAgVmFsaWQgbWFzayBwYXR0ZXJuIG9yIHVuZGVmaW5lZFxuICovXG5leHBvcnRzLmZyb20gPSBmdW5jdGlvbiBmcm9tICh2YWx1ZSkge1xuICByZXR1cm4gZXhwb3J0cy5pc1ZhbGlkKHZhbHVlKSA/IHBhcnNlSW50KHZhbHVlLCAxMCkgOiB1bmRlZmluZWRcbn1cblxuLyoqXG4qIEZpbmQgYWRqYWNlbnQgbW9kdWxlcyBpbiByb3cvY29sdW1uIHdpdGggdGhlIHNhbWUgY29sb3JcbiogYW5kIGFzc2lnbiBhIHBlbmFsdHkgdmFsdWUuXG4qXG4qIFBvaW50czogTjEgKyBpXG4qIGkgaXMgdGhlIGFtb3VudCBieSB3aGljaCB0aGUgbnVtYmVyIG9mIGFkamFjZW50IG1vZHVsZXMgb2YgdGhlIHNhbWUgY29sb3IgZXhjZWVkcyA1XG4qL1xuZXhwb3J0cy5nZXRQZW5hbHR5TjEgPSBmdW5jdGlvbiBnZXRQZW5hbHR5TjEgKGRhdGEpIHtcbiAgdmFyIHNpemUgPSBkYXRhLnNpemVcbiAgdmFyIHBvaW50cyA9IDBcbiAgdmFyIHNhbWVDb3VudENvbCA9IDBcbiAgdmFyIHNhbWVDb3VudFJvdyA9IDBcbiAgdmFyIGxhc3RDb2wgPSBudWxsXG4gIHZhciBsYXN0Um93ID0gbnVsbFxuXG4gIGZvciAodmFyIHJvdyA9IDA7IHJvdyA8IHNpemU7IHJvdysrKSB7XG4gICAgc2FtZUNvdW50Q29sID0gc2FtZUNvdW50Um93ID0gMFxuICAgIGxhc3RDb2wgPSBsYXN0Um93ID0gbnVsbFxuXG4gICAgZm9yICh2YXIgY29sID0gMDsgY29sIDwgc2l6ZTsgY29sKyspIHtcbiAgICAgIHZhciBtb2R1bGUgPSBkYXRhLmdldChyb3csIGNvbClcbiAgICAgIGlmIChtb2R1bGUgPT09IGxhc3RDb2wpIHtcbiAgICAgICAgc2FtZUNvdW50Q29sKytcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChzYW1lQ291bnRDb2wgPj0gNSkgcG9pbnRzICs9IFBlbmFsdHlTY29yZXMuTjEgKyAoc2FtZUNvdW50Q29sIC0gNSlcbiAgICAgICAgbGFzdENvbCA9IG1vZHVsZVxuICAgICAgICBzYW1lQ291bnRDb2wgPSAxXG4gICAgICB9XG5cbiAgICAgIG1vZHVsZSA9IGRhdGEuZ2V0KGNvbCwgcm93KVxuICAgICAgaWYgKG1vZHVsZSA9PT0gbGFzdFJvdykge1xuICAgICAgICBzYW1lQ291bnRSb3crK1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHNhbWVDb3VudFJvdyA+PSA1KSBwb2ludHMgKz0gUGVuYWx0eVNjb3Jlcy5OMSArIChzYW1lQ291bnRSb3cgLSA1KVxuICAgICAgICBsYXN0Um93ID0gbW9kdWxlXG4gICAgICAgIHNhbWVDb3VudFJvdyA9IDFcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoc2FtZUNvdW50Q29sID49IDUpIHBvaW50cyArPSBQZW5hbHR5U2NvcmVzLk4xICsgKHNhbWVDb3VudENvbCAtIDUpXG4gICAgaWYgKHNhbWVDb3VudFJvdyA+PSA1KSBwb2ludHMgKz0gUGVuYWx0eVNjb3Jlcy5OMSArIChzYW1lQ291bnRSb3cgLSA1KVxuICB9XG5cbiAgcmV0dXJuIHBvaW50c1xufVxuXG4vKipcbiAqIEZpbmQgMngyIGJsb2NrcyB3aXRoIHRoZSBzYW1lIGNvbG9yIGFuZCBhc3NpZ24gYSBwZW5hbHR5IHZhbHVlXG4gKlxuICogUG9pbnRzOiBOMiAqIChtIC0gMSkgKiAobiAtIDEpXG4gKi9cbmV4cG9ydHMuZ2V0UGVuYWx0eU4yID0gZnVuY3Rpb24gZ2V0UGVuYWx0eU4yIChkYXRhKSB7XG4gIHZhciBzaXplID0gZGF0YS5zaXplXG4gIHZhciBwb2ludHMgPSAwXG5cbiAgZm9yICh2YXIgcm93ID0gMDsgcm93IDwgc2l6ZSAtIDE7IHJvdysrKSB7XG4gICAgZm9yICh2YXIgY29sID0gMDsgY29sIDwgc2l6ZSAtIDE7IGNvbCsrKSB7XG4gICAgICB2YXIgbGFzdCA9IGRhdGEuZ2V0KHJvdywgY29sKSArXG4gICAgICAgIGRhdGEuZ2V0KHJvdywgY29sICsgMSkgK1xuICAgICAgICBkYXRhLmdldChyb3cgKyAxLCBjb2wpICtcbiAgICAgICAgZGF0YS5nZXQocm93ICsgMSwgY29sICsgMSlcblxuICAgICAgaWYgKGxhc3QgPT09IDQgfHwgbGFzdCA9PT0gMCkgcG9pbnRzKytcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcG9pbnRzICogUGVuYWx0eVNjb3Jlcy5OMlxufVxuXG4vKipcbiAqIEZpbmQgMToxOjM6MToxIHJhdGlvIChkYXJrOmxpZ2h0OmRhcms6bGlnaHQ6ZGFyaykgcGF0dGVybiBpbiByb3cvY29sdW1uLFxuICogcHJlY2VkZWQgb3IgZm9sbG93ZWQgYnkgbGlnaHQgYXJlYSA0IG1vZHVsZXMgd2lkZVxuICpcbiAqIFBvaW50czogTjMgKiBudW1iZXIgb2YgcGF0dGVybiBmb3VuZFxuICovXG5leHBvcnRzLmdldFBlbmFsdHlOMyA9IGZ1bmN0aW9uIGdldFBlbmFsdHlOMyAoZGF0YSkge1xuICB2YXIgc2l6ZSA9IGRhdGEuc2l6ZVxuICB2YXIgcG9pbnRzID0gMFxuICB2YXIgYml0c0NvbCA9IDBcbiAgdmFyIGJpdHNSb3cgPSAwXG5cbiAgZm9yICh2YXIgcm93ID0gMDsgcm93IDwgc2l6ZTsgcm93KyspIHtcbiAgICBiaXRzQ29sID0gYml0c1JvdyA9IDBcbiAgICBmb3IgKHZhciBjb2wgPSAwOyBjb2wgPCBzaXplOyBjb2wrKykge1xuICAgICAgYml0c0NvbCA9ICgoYml0c0NvbCA8PCAxKSAmIDB4N0ZGKSB8IGRhdGEuZ2V0KHJvdywgY29sKVxuICAgICAgaWYgKGNvbCA+PSAxMCAmJiAoYml0c0NvbCA9PT0gMHg1RDAgfHwgYml0c0NvbCA9PT0gMHgwNUQpKSBwb2ludHMrK1xuXG4gICAgICBiaXRzUm93ID0gKChiaXRzUm93IDw8IDEpICYgMHg3RkYpIHwgZGF0YS5nZXQoY29sLCByb3cpXG4gICAgICBpZiAoY29sID49IDEwICYmIChiaXRzUm93ID09PSAweDVEMCB8fCBiaXRzUm93ID09PSAweDA1RCkpIHBvaW50cysrXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHBvaW50cyAqIFBlbmFsdHlTY29yZXMuTjNcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGUgcHJvcG9ydGlvbiBvZiBkYXJrIG1vZHVsZXMgaW4gZW50aXJlIHN5bWJvbFxuICpcbiAqIFBvaW50czogTjQgKiBrXG4gKlxuICogayBpcyB0aGUgcmF0aW5nIG9mIHRoZSBkZXZpYXRpb24gb2YgdGhlIHByb3BvcnRpb24gb2YgZGFyayBtb2R1bGVzXG4gKiBpbiB0aGUgc3ltYm9sIGZyb20gNTAlIGluIHN0ZXBzIG9mIDUlXG4gKi9cbmV4cG9ydHMuZ2V0UGVuYWx0eU40ID0gZnVuY3Rpb24gZ2V0UGVuYWx0eU40IChkYXRhKSB7XG4gIHZhciBkYXJrQ291bnQgPSAwXG4gIHZhciBtb2R1bGVzQ291bnQgPSBkYXRhLmRhdGEubGVuZ3RoXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb2R1bGVzQ291bnQ7IGkrKykgZGFya0NvdW50ICs9IGRhdGEuZGF0YVtpXVxuXG4gIHZhciBrID0gTWF0aC5hYnMoTWF0aC5jZWlsKChkYXJrQ291bnQgKiAxMDAgLyBtb2R1bGVzQ291bnQpIC8gNSkgLSAxMClcblxuICByZXR1cm4gayAqIFBlbmFsdHlTY29yZXMuTjRcbn1cblxuLyoqXG4gKiBSZXR1cm4gbWFzayB2YWx1ZSBhdCBnaXZlbiBwb3NpdGlvblxuICpcbiAqIEBwYXJhbSAge051bWJlcn0gbWFza1BhdHRlcm4gUGF0dGVybiByZWZlcmVuY2UgdmFsdWVcbiAqIEBwYXJhbSAge051bWJlcn0gaSAgICAgICAgICAgUm93XG4gKiBAcGFyYW0gIHtOdW1iZXJ9IGogICAgICAgICAgIENvbHVtblxuICogQHJldHVybiB7Qm9vbGVhbn0gICAgICAgICAgICBNYXNrIHZhbHVlXG4gKi9cbmZ1bmN0aW9uIGdldE1hc2tBdCAobWFza1BhdHRlcm4sIGksIGopIHtcbiAgc3dpdGNoIChtYXNrUGF0dGVybikge1xuICAgIGNhc2UgZXhwb3J0cy5QYXR0ZXJucy5QQVRURVJOMDAwOiByZXR1cm4gKGkgKyBqKSAlIDIgPT09IDBcbiAgICBjYXNlIGV4cG9ydHMuUGF0dGVybnMuUEFUVEVSTjAwMTogcmV0dXJuIGkgJSAyID09PSAwXG4gICAgY2FzZSBleHBvcnRzLlBhdHRlcm5zLlBBVFRFUk4wMTA6IHJldHVybiBqICUgMyA9PT0gMFxuICAgIGNhc2UgZXhwb3J0cy5QYXR0ZXJucy5QQVRURVJOMDExOiByZXR1cm4gKGkgKyBqKSAlIDMgPT09IDBcbiAgICBjYXNlIGV4cG9ydHMuUGF0dGVybnMuUEFUVEVSTjEwMDogcmV0dXJuIChNYXRoLmZsb29yKGkgLyAyKSArIE1hdGguZmxvb3IoaiAvIDMpKSAlIDIgPT09IDBcbiAgICBjYXNlIGV4cG9ydHMuUGF0dGVybnMuUEFUVEVSTjEwMTogcmV0dXJuIChpICogaikgJSAyICsgKGkgKiBqKSAlIDMgPT09IDBcbiAgICBjYXNlIGV4cG9ydHMuUGF0dGVybnMuUEFUVEVSTjExMDogcmV0dXJuICgoaSAqIGopICUgMiArIChpICogaikgJSAzKSAlIDIgPT09IDBcbiAgICBjYXNlIGV4cG9ydHMuUGF0dGVybnMuUEFUVEVSTjExMTogcmV0dXJuICgoaSAqIGopICUgMyArIChpICsgaikgJSAyKSAlIDIgPT09IDBcblxuICAgIGRlZmF1bHQ6IHRocm93IG5ldyBFcnJvcignYmFkIG1hc2tQYXR0ZXJuOicgKyBtYXNrUGF0dGVybilcbiAgfVxufVxuXG4vKipcbiAqIEFwcGx5IGEgbWFzayBwYXR0ZXJuIHRvIGEgQml0TWF0cml4XG4gKlxuICogQHBhcmFtICB7TnVtYmVyfSAgICBwYXR0ZXJuIFBhdHRlcm4gcmVmZXJlbmNlIG51bWJlclxuICogQHBhcmFtICB7Qml0TWF0cml4fSBkYXRhICAgIEJpdE1hdHJpeCBkYXRhXG4gKi9cbmV4cG9ydHMuYXBwbHlNYXNrID0gZnVuY3Rpb24gYXBwbHlNYXNrIChwYXR0ZXJuLCBkYXRhKSB7XG4gIHZhciBzaXplID0gZGF0YS5zaXplXG5cbiAgZm9yICh2YXIgY29sID0gMDsgY29sIDwgc2l6ZTsgY29sKyspIHtcbiAgICBmb3IgKHZhciByb3cgPSAwOyByb3cgPCBzaXplOyByb3crKykge1xuICAgICAgaWYgKGRhdGEuaXNSZXNlcnZlZChyb3csIGNvbCkpIGNvbnRpbnVlXG4gICAgICBkYXRhLnhvcihyb3csIGNvbCwgZ2V0TWFza0F0KHBhdHRlcm4sIHJvdywgY29sKSlcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBiZXN0IG1hc2sgcGF0dGVybiBmb3IgZGF0YVxuICpcbiAqIEBwYXJhbSAge0JpdE1hdHJpeH0gZGF0YVxuICogQHJldHVybiB7TnVtYmVyfSBNYXNrIHBhdHRlcm4gcmVmZXJlbmNlIG51bWJlclxuICovXG5leHBvcnRzLmdldEJlc3RNYXNrID0gZnVuY3Rpb24gZ2V0QmVzdE1hc2sgKGRhdGEsIHNldHVwRm9ybWF0RnVuYykge1xuICB2YXIgbnVtUGF0dGVybnMgPSBPYmplY3Qua2V5cyhleHBvcnRzLlBhdHRlcm5zKS5sZW5ndGhcbiAgdmFyIGJlc3RQYXR0ZXJuID0gMFxuICB2YXIgbG93ZXJQZW5hbHR5ID0gSW5maW5pdHlcblxuICBmb3IgKHZhciBwID0gMDsgcCA8IG51bVBhdHRlcm5zOyBwKyspIHtcbiAgICBzZXR1cEZvcm1hdEZ1bmMocClcbiAgICBleHBvcnRzLmFwcGx5TWFzayhwLCBkYXRhKVxuXG4gICAgLy8gQ2FsY3VsYXRlIHBlbmFsdHlcbiAgICB2YXIgcGVuYWx0eSA9XG4gICAgICBleHBvcnRzLmdldFBlbmFsdHlOMShkYXRhKSArXG4gICAgICBleHBvcnRzLmdldFBlbmFsdHlOMihkYXRhKSArXG4gICAgICBleHBvcnRzLmdldFBlbmFsdHlOMyhkYXRhKSArXG4gICAgICBleHBvcnRzLmdldFBlbmFsdHlONChkYXRhKVxuXG4gICAgLy8gVW5kbyBwcmV2aW91c2x5IGFwcGxpZWQgbWFza1xuICAgIGV4cG9ydHMuYXBwbHlNYXNrKHAsIGRhdGEpXG5cbiAgICBpZiAocGVuYWx0eSA8IGxvd2VyUGVuYWx0eSkge1xuICAgICAgbG93ZXJQZW5hbHR5ID0gcGVuYWx0eVxuICAgICAgYmVzdFBhdHRlcm4gPSBwXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJlc3RQYXR0ZXJuXG59XG4iLCJ2YXIgVmVyc2lvbkNoZWNrID0gcmVxdWlyZSgnLi92ZXJzaW9uLWNoZWNrJylcbnZhciBSZWdleCA9IHJlcXVpcmUoJy4vcmVnZXgnKVxuXG4vKipcbiAqIE51bWVyaWMgbW9kZSBlbmNvZGVzIGRhdGEgZnJvbSB0aGUgZGVjaW1hbCBkaWdpdCBzZXQgKDAgLSA5KVxuICogKGJ5dGUgdmFsdWVzIDMwSEVYIHRvIDM5SEVYKS5cbiAqIE5vcm1hbGx5LCAzIGRhdGEgY2hhcmFjdGVycyBhcmUgcmVwcmVzZW50ZWQgYnkgMTAgYml0cy5cbiAqXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5leHBvcnRzLk5VTUVSSUMgPSB7XG4gIGlkOiAnTnVtZXJpYycsXG4gIGJpdDogMSA8PCAwLFxuICBjY0JpdHM6IFsxMCwgMTIsIDE0XVxufVxuXG4vKipcbiAqIEFscGhhbnVtZXJpYyBtb2RlIGVuY29kZXMgZGF0YSBmcm9tIGEgc2V0IG9mIDQ1IGNoYXJhY3RlcnMsXG4gKiBpLmUuIDEwIG51bWVyaWMgZGlnaXRzICgwIC0gOSksXG4gKiAgICAgIDI2IGFscGhhYmV0aWMgY2hhcmFjdGVycyAoQSAtIFopLFxuICogICBhbmQgOSBzeW1ib2xzIChTUCwgJCwgJSwgKiwgKywgLSwgLiwgLywgOikuXG4gKiBOb3JtYWxseSwgdHdvIGlucHV0IGNoYXJhY3RlcnMgYXJlIHJlcHJlc2VudGVkIGJ5IDExIGJpdHMuXG4gKlxuICogQHR5cGUge09iamVjdH1cbiAqL1xuZXhwb3J0cy5BTFBIQU5VTUVSSUMgPSB7XG4gIGlkOiAnQWxwaGFudW1lcmljJyxcbiAgYml0OiAxIDw8IDEsXG4gIGNjQml0czogWzksIDExLCAxM11cbn1cblxuLyoqXG4gKiBJbiBieXRlIG1vZGUsIGRhdGEgaXMgZW5jb2RlZCBhdCA4IGJpdHMgcGVyIGNoYXJhY3Rlci5cbiAqXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5leHBvcnRzLkJZVEUgPSB7XG4gIGlkOiAnQnl0ZScsXG4gIGJpdDogMSA8PCAyLFxuICBjY0JpdHM6IFs4LCAxNiwgMTZdXG59XG5cbi8qKlxuICogVGhlIEthbmppIG1vZGUgZWZmaWNpZW50bHkgZW5jb2RlcyBLYW5qaSBjaGFyYWN0ZXJzIGluIGFjY29yZGFuY2Ugd2l0aFxuICogdGhlIFNoaWZ0IEpJUyBzeXN0ZW0gYmFzZWQgb24gSklTIFggMDIwOC5cbiAqIFRoZSBTaGlmdCBKSVMgdmFsdWVzIGFyZSBzaGlmdGVkIGZyb20gdGhlIEpJUyBYIDAyMDggdmFsdWVzLlxuICogSklTIFggMDIwOCBnaXZlcyBkZXRhaWxzIG9mIHRoZSBzaGlmdCBjb2RlZCByZXByZXNlbnRhdGlvbi5cbiAqIEVhY2ggdHdvLWJ5dGUgY2hhcmFjdGVyIHZhbHVlIGlzIGNvbXBhY3RlZCB0byBhIDEzLWJpdCBiaW5hcnkgY29kZXdvcmQuXG4gKlxuICogQHR5cGUge09iamVjdH1cbiAqL1xuZXhwb3J0cy5LQU5KSSA9IHtcbiAgaWQ6ICdLYW5qaScsXG4gIGJpdDogMSA8PCAzLFxuICBjY0JpdHM6IFs4LCAxMCwgMTJdXG59XG5cbi8qKlxuICogTWl4ZWQgbW9kZSB3aWxsIGNvbnRhaW4gYSBzZXF1ZW5jZXMgb2YgZGF0YSBpbiBhIGNvbWJpbmF0aW9uIG9mIGFueSBvZlxuICogdGhlIG1vZGVzIGRlc2NyaWJlZCBhYm92ZVxuICpcbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cbmV4cG9ydHMuTUlYRUQgPSB7XG4gIGJpdDogLTFcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgYml0cyBuZWVkZWQgdG8gc3RvcmUgdGhlIGRhdGEgbGVuZ3RoXG4gKiBhY2NvcmRpbmcgdG8gUVIgQ29kZSBzcGVjaWZpY2F0aW9ucy5cbiAqXG4gKiBAcGFyYW0gIHtNb2RlfSAgIG1vZGUgICAgRGF0YSBtb2RlXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IHZlcnNpb24gUVIgQ29kZSB2ZXJzaW9uXG4gKiBAcmV0dXJuIHtOdW1iZXJ9ICAgICAgICAgTnVtYmVyIG9mIGJpdHNcbiAqL1xuZXhwb3J0cy5nZXRDaGFyQ291bnRJbmRpY2F0b3IgPSBmdW5jdGlvbiBnZXRDaGFyQ291bnRJbmRpY2F0b3IgKG1vZGUsIHZlcnNpb24pIHtcbiAgaWYgKCFtb2RlLmNjQml0cykgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG1vZGU6ICcgKyBtb2RlKVxuXG4gIGlmICghVmVyc2lvbkNoZWNrLmlzVmFsaWQodmVyc2lvbikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgdmVyc2lvbjogJyArIHZlcnNpb24pXG4gIH1cblxuICBpZiAodmVyc2lvbiA+PSAxICYmIHZlcnNpb24gPCAxMCkgcmV0dXJuIG1vZGUuY2NCaXRzWzBdXG4gIGVsc2UgaWYgKHZlcnNpb24gPCAyNykgcmV0dXJuIG1vZGUuY2NCaXRzWzFdXG4gIHJldHVybiBtb2RlLmNjQml0c1syXVxufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIG1vc3QgZWZmaWNpZW50IG1vZGUgdG8gc3RvcmUgdGhlIHNwZWNpZmllZCBkYXRhXG4gKlxuICogQHBhcmFtICB7U3RyaW5nfSBkYXRhU3RyIElucHV0IGRhdGEgc3RyaW5nXG4gKiBAcmV0dXJuIHtNb2RlfSAgICAgICAgICAgQmVzdCBtb2RlXG4gKi9cbmV4cG9ydHMuZ2V0QmVzdE1vZGVGb3JEYXRhID0gZnVuY3Rpb24gZ2V0QmVzdE1vZGVGb3JEYXRhIChkYXRhU3RyKSB7XG4gIGlmIChSZWdleC50ZXN0TnVtZXJpYyhkYXRhU3RyKSkgcmV0dXJuIGV4cG9ydHMuTlVNRVJJQ1xuICBlbHNlIGlmIChSZWdleC50ZXN0QWxwaGFudW1lcmljKGRhdGFTdHIpKSByZXR1cm4gZXhwb3J0cy5BTFBIQU5VTUVSSUNcbiAgZWxzZSBpZiAoUmVnZXgudGVzdEthbmppKGRhdGFTdHIpKSByZXR1cm4gZXhwb3J0cy5LQU5KSVxuICBlbHNlIHJldHVybiBleHBvcnRzLkJZVEVcbn1cblxuLyoqXG4gKiBSZXR1cm4gbW9kZSBuYW1lIGFzIHN0cmluZ1xuICpcbiAqIEBwYXJhbSB7TW9kZX0gbW9kZSBNb2RlIG9iamVjdFxuICogQHJldHVybnMge1N0cmluZ30gIE1vZGUgbmFtZVxuICovXG5leHBvcnRzLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcgKG1vZGUpIHtcbiAgaWYgKG1vZGUgJiYgbW9kZS5pZCkgcmV0dXJuIG1vZGUuaWRcbiAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG1vZGUnKVxufVxuXG4vKipcbiAqIENoZWNrIGlmIGlucHV0IHBhcmFtIGlzIGEgdmFsaWQgbW9kZSBvYmplY3RcbiAqXG4gKiBAcGFyYW0gICB7TW9kZX0gICAgbW9kZSBNb2RlIG9iamVjdFxuICogQHJldHVybnMge0Jvb2xlYW59IFRydWUgaWYgdmFsaWQgbW9kZSwgZmFsc2Ugb3RoZXJ3aXNlXG4gKi9cbmV4cG9ydHMuaXNWYWxpZCA9IGZ1bmN0aW9uIGlzVmFsaWQgKG1vZGUpIHtcbiAgcmV0dXJuIG1vZGUgJiYgbW9kZS5iaXQgJiYgbW9kZS5jY0JpdHNcbn1cblxuLyoqXG4gKiBHZXQgbW9kZSBvYmplY3QgZnJvbSBpdHMgbmFtZVxuICpcbiAqIEBwYXJhbSAgIHtTdHJpbmd9IHN0cmluZyBNb2RlIG5hbWVcbiAqIEByZXR1cm5zIHtNb2RlfSAgICAgICAgICBNb2RlIG9iamVjdFxuICovXG5mdW5jdGlvbiBmcm9tU3RyaW5nIChzdHJpbmcpIHtcbiAgaWYgKHR5cGVvZiBzdHJpbmcgIT09ICdzdHJpbmcnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQYXJhbSBpcyBub3QgYSBzdHJpbmcnKVxuICB9XG5cbiAgdmFyIGxjU3RyID0gc3RyaW5nLnRvTG93ZXJDYXNlKClcblxuICBzd2l0Y2ggKGxjU3RyKSB7XG4gICAgY2FzZSAnbnVtZXJpYyc6XG4gICAgICByZXR1cm4gZXhwb3J0cy5OVU1FUklDXG4gICAgY2FzZSAnYWxwaGFudW1lcmljJzpcbiAgICAgIHJldHVybiBleHBvcnRzLkFMUEhBTlVNRVJJQ1xuICAgIGNhc2UgJ2thbmppJzpcbiAgICAgIHJldHVybiBleHBvcnRzLktBTkpJXG4gICAgY2FzZSAnYnl0ZSc6XG4gICAgICByZXR1cm4gZXhwb3J0cy5CWVRFXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5rbm93biBtb2RlOiAnICsgc3RyaW5nKVxuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyBtb2RlIGZyb20gYSB2YWx1ZS5cbiAqIElmIHZhbHVlIGlzIG5vdCBhIHZhbGlkIG1vZGUsIHJldHVybnMgZGVmYXVsdFZhbHVlXG4gKlxuICogQHBhcmFtICB7TW9kZXxTdHJpbmd9IHZhbHVlICAgICAgICBFbmNvZGluZyBtb2RlXG4gKiBAcGFyYW0gIHtNb2RlfSAgICAgICAgZGVmYXVsdFZhbHVlIEZhbGxiYWNrIHZhbHVlXG4gKiBAcmV0dXJuIHtNb2RlfSAgICAgICAgICAgICAgICAgICAgIEVuY29kaW5nIG1vZGVcbiAqL1xuZXhwb3J0cy5mcm9tID0gZnVuY3Rpb24gZnJvbSAodmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICBpZiAoZXhwb3J0cy5pc1ZhbGlkKHZhbHVlKSkge1xuICAgIHJldHVybiB2YWx1ZVxuICB9XG5cbiAgdHJ5IHtcbiAgICByZXR1cm4gZnJvbVN0cmluZyh2YWx1ZSlcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBkZWZhdWx0VmFsdWVcbiAgfVxufVxuIiwidmFyIE1vZGUgPSByZXF1aXJlKCcuL21vZGUnKVxuXG5mdW5jdGlvbiBOdW1lcmljRGF0YSAoZGF0YSkge1xuICB0aGlzLm1vZGUgPSBNb2RlLk5VTUVSSUNcbiAgdGhpcy5kYXRhID0gZGF0YS50b1N0cmluZygpXG59XG5cbk51bWVyaWNEYXRhLmdldEJpdHNMZW5ndGggPSBmdW5jdGlvbiBnZXRCaXRzTGVuZ3RoIChsZW5ndGgpIHtcbiAgcmV0dXJuIDEwICogTWF0aC5mbG9vcihsZW5ndGggLyAzKSArICgobGVuZ3RoICUgMykgPyAoKGxlbmd0aCAlIDMpICogMyArIDEpIDogMClcbn1cblxuTnVtZXJpY0RhdGEucHJvdG90eXBlLmdldExlbmd0aCA9IGZ1bmN0aW9uIGdldExlbmd0aCAoKSB7XG4gIHJldHVybiB0aGlzLmRhdGEubGVuZ3RoXG59XG5cbk51bWVyaWNEYXRhLnByb3RvdHlwZS5nZXRCaXRzTGVuZ3RoID0gZnVuY3Rpb24gZ2V0Qml0c0xlbmd0aCAoKSB7XG4gIHJldHVybiBOdW1lcmljRGF0YS5nZXRCaXRzTGVuZ3RoKHRoaXMuZGF0YS5sZW5ndGgpXG59XG5cbk51bWVyaWNEYXRhLnByb3RvdHlwZS53cml0ZSA9IGZ1bmN0aW9uIHdyaXRlIChiaXRCdWZmZXIpIHtcbiAgdmFyIGksIGdyb3VwLCB2YWx1ZVxuXG4gIC8vIFRoZSBpbnB1dCBkYXRhIHN0cmluZyBpcyBkaXZpZGVkIGludG8gZ3JvdXBzIG9mIHRocmVlIGRpZ2l0cyxcbiAgLy8gYW5kIGVhY2ggZ3JvdXAgaXMgY29udmVydGVkIHRvIGl0cyAxMC1iaXQgYmluYXJ5IGVxdWl2YWxlbnQuXG4gIGZvciAoaSA9IDA7IGkgKyAzIDw9IHRoaXMuZGF0YS5sZW5ndGg7IGkgKz0gMykge1xuICAgIGdyb3VwID0gdGhpcy5kYXRhLnN1YnN0cihpLCAzKVxuICAgIHZhbHVlID0gcGFyc2VJbnQoZ3JvdXAsIDEwKVxuXG4gICAgYml0QnVmZmVyLnB1dCh2YWx1ZSwgMTApXG4gIH1cblxuICAvLyBJZiB0aGUgbnVtYmVyIG9mIGlucHV0IGRpZ2l0cyBpcyBub3QgYW4gZXhhY3QgbXVsdGlwbGUgb2YgdGhyZWUsXG4gIC8vIHRoZSBmaW5hbCBvbmUgb3IgdHdvIGRpZ2l0cyBhcmUgY29udmVydGVkIHRvIDQgb3IgNyBiaXRzIHJlc3BlY3RpdmVseS5cbiAgdmFyIHJlbWFpbmluZ051bSA9IHRoaXMuZGF0YS5sZW5ndGggLSBpXG4gIGlmIChyZW1haW5pbmdOdW0gPiAwKSB7XG4gICAgZ3JvdXAgPSB0aGlzLmRhdGEuc3Vic3RyKGkpXG4gICAgdmFsdWUgPSBwYXJzZUludChncm91cCwgMTApXG5cbiAgICBiaXRCdWZmZXIucHV0KHZhbHVlLCByZW1haW5pbmdOdW0gKiAzICsgMSlcbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IE51bWVyaWNEYXRhXG4iLCJ2YXIgQnVmZmVyID0gcmVxdWlyZSgnLi4vdXRpbHMvYnVmZmVyJylcbnZhciBHRiA9IHJlcXVpcmUoJy4vZ2Fsb2lzLWZpZWxkJylcblxuLyoqXG4gKiBNdWx0aXBsaWVzIHR3byBwb2x5bm9taWFscyBpbnNpZGUgR2Fsb2lzIEZpZWxkXG4gKlxuICogQHBhcmFtICB7QnVmZmVyfSBwMSBQb2x5bm9taWFsXG4gKiBAcGFyYW0gIHtCdWZmZXJ9IHAyIFBvbHlub21pYWxcbiAqIEByZXR1cm4ge0J1ZmZlcn0gICAgUHJvZHVjdCBvZiBwMSBhbmQgcDJcbiAqL1xuZXhwb3J0cy5tdWwgPSBmdW5jdGlvbiBtdWwgKHAxLCBwMikge1xuICB2YXIgY29lZmYgPSBuZXcgQnVmZmVyKHAxLmxlbmd0aCArIHAyLmxlbmd0aCAtIDEpXG4gIGNvZWZmLmZpbGwoMClcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHAxLmxlbmd0aDsgaSsrKSB7XG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBwMi5sZW5ndGg7IGorKykge1xuICAgICAgY29lZmZbaSArIGpdIF49IEdGLm11bChwMVtpXSwgcDJbal0pXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGNvZWZmXG59XG5cbi8qKlxuICogQ2FsY3VsYXRlIHRoZSByZW1haW5kZXIgb2YgcG9seW5vbWlhbHMgZGl2aXNpb25cbiAqXG4gKiBAcGFyYW0gIHtCdWZmZXJ9IGRpdmlkZW50IFBvbHlub21pYWxcbiAqIEBwYXJhbSAge0J1ZmZlcn0gZGl2aXNvciAgUG9seW5vbWlhbFxuICogQHJldHVybiB7QnVmZmVyfSAgICAgICAgICBSZW1haW5kZXJcbiAqL1xuZXhwb3J0cy5tb2QgPSBmdW5jdGlvbiBtb2QgKGRpdmlkZW50LCBkaXZpc29yKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQnVmZmVyKGRpdmlkZW50KVxuXG4gIHdoaWxlICgocmVzdWx0Lmxlbmd0aCAtIGRpdmlzb3IubGVuZ3RoKSA+PSAwKSB7XG4gICAgdmFyIGNvZWZmID0gcmVzdWx0WzBdXG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRpdmlzb3IubGVuZ3RoOyBpKyspIHtcbiAgICAgIHJlc3VsdFtpXSBePSBHRi5tdWwoZGl2aXNvcltpXSwgY29lZmYpXG4gICAgfVxuXG4gICAgLy8gcmVtb3ZlIGFsbCB6ZXJvcyBmcm9tIGJ1ZmZlciBoZWFkXG4gICAgdmFyIG9mZnNldCA9IDBcbiAgICB3aGlsZSAob2Zmc2V0IDwgcmVzdWx0Lmxlbmd0aCAmJiByZXN1bHRbb2Zmc2V0XSA9PT0gMCkgb2Zmc2V0KytcbiAgICByZXN1bHQgPSByZXN1bHQuc2xpY2Uob2Zmc2V0KVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG4vKipcbiAqIEdlbmVyYXRlIGFuIGlycmVkdWNpYmxlIGdlbmVyYXRvciBwb2x5bm9taWFsIG9mIHNwZWNpZmllZCBkZWdyZWVcbiAqICh1c2VkIGJ5IFJlZWQtU29sb21vbiBlbmNvZGVyKVxuICpcbiAqIEBwYXJhbSAge051bWJlcn0gZGVncmVlIERlZ3JlZSBvZiB0aGUgZ2VuZXJhdG9yIHBvbHlub21pYWxcbiAqIEByZXR1cm4ge0J1ZmZlcn0gICAgICAgIEJ1ZmZlciBjb250YWluaW5nIHBvbHlub21pYWwgY29lZmZpY2llbnRzXG4gKi9cbmV4cG9ydHMuZ2VuZXJhdGVFQ1BvbHlub21pYWwgPSBmdW5jdGlvbiBnZW5lcmF0ZUVDUG9seW5vbWlhbCAoZGVncmVlKSB7XG4gIHZhciBwb2x5ID0gbmV3IEJ1ZmZlcihbMV0pXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgZGVncmVlOyBpKyspIHtcbiAgICBwb2x5ID0gZXhwb3J0cy5tdWwocG9seSwgWzEsIEdGLmV4cChpKV0pXG4gIH1cblxuICByZXR1cm4gcG9seVxufVxuIiwidmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4uL3V0aWxzL2J1ZmZlcicpXG52YXIgVXRpbHMgPSByZXF1aXJlKCcuL3V0aWxzJylcbnZhciBFQ0xldmVsID0gcmVxdWlyZSgnLi9lcnJvci1jb3JyZWN0aW9uLWxldmVsJylcbnZhciBCaXRCdWZmZXIgPSByZXF1aXJlKCcuL2JpdC1idWZmZXInKVxudmFyIEJpdE1hdHJpeCA9IHJlcXVpcmUoJy4vYml0LW1hdHJpeCcpXG52YXIgQWxpZ25tZW50UGF0dGVybiA9IHJlcXVpcmUoJy4vYWxpZ25tZW50LXBhdHRlcm4nKVxudmFyIEZpbmRlclBhdHRlcm4gPSByZXF1aXJlKCcuL2ZpbmRlci1wYXR0ZXJuJylcbnZhciBNYXNrUGF0dGVybiA9IHJlcXVpcmUoJy4vbWFzay1wYXR0ZXJuJylcbnZhciBFQ0NvZGUgPSByZXF1aXJlKCcuL2Vycm9yLWNvcnJlY3Rpb24tY29kZScpXG52YXIgUmVlZFNvbG9tb25FbmNvZGVyID0gcmVxdWlyZSgnLi9yZWVkLXNvbG9tb24tZW5jb2RlcicpXG52YXIgVmVyc2lvbiA9IHJlcXVpcmUoJy4vdmVyc2lvbicpXG52YXIgRm9ybWF0SW5mbyA9IHJlcXVpcmUoJy4vZm9ybWF0LWluZm8nKVxudmFyIE1vZGUgPSByZXF1aXJlKCcuL21vZGUnKVxudmFyIFNlZ21lbnRzID0gcmVxdWlyZSgnLi9zZWdtZW50cycpXG52YXIgaXNBcnJheSA9IHJlcXVpcmUoJ2lzYXJyYXknKVxuXG4vKipcbiAqIFFSQ29kZSBmb3IgSmF2YVNjcmlwdFxuICpcbiAqIG1vZGlmaWVkIGJ5IFJ5YW4gRGF5IGZvciBub2RlanMgc3VwcG9ydFxuICogQ29weXJpZ2h0IChjKSAyMDExIFJ5YW4gRGF5XG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlOlxuICogICBodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocFxuICpcbi8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBRUkNvZGUgZm9yIEphdmFTY3JpcHRcbi8vXG4vLyBDb3B5cmlnaHQgKGMpIDIwMDkgS2F6dWhpa28gQXJhc2Vcbi8vXG4vLyBVUkw6IGh0dHA6Ly93d3cuZC1wcm9qZWN0LmNvbS9cbi8vXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2U6XG4vLyAgIGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvbWl0LWxpY2Vuc2UucGhwXG4vL1xuLy8gVGhlIHdvcmQgXCJRUiBDb2RlXCIgaXMgcmVnaXN0ZXJlZCB0cmFkZW1hcmsgb2Zcbi8vIERFTlNPIFdBVkUgSU5DT1JQT1JBVEVEXG4vLyAgIGh0dHA6Ly93d3cuZGVuc28td2F2ZS5jb20vcXJjb2RlL2ZhcXBhdGVudC1lLmh0bWxcbi8vXG4vLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuKi9cblxuLyoqXG4gKiBBZGQgZmluZGVyIHBhdHRlcm5zIGJpdHMgdG8gbWF0cml4XG4gKlxuICogQHBhcmFtICB7Qml0TWF0cml4fSBtYXRyaXggIE1vZHVsZXMgbWF0cml4XG4gKiBAcGFyYW0gIHtOdW1iZXJ9ICAgIHZlcnNpb24gUVIgQ29kZSB2ZXJzaW9uXG4gKi9cbmZ1bmN0aW9uIHNldHVwRmluZGVyUGF0dGVybiAobWF0cml4LCB2ZXJzaW9uKSB7XG4gIHZhciBzaXplID0gbWF0cml4LnNpemVcbiAgdmFyIHBvcyA9IEZpbmRlclBhdHRlcm4uZ2V0UG9zaXRpb25zKHZlcnNpb24pXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBwb3MubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcm93ID0gcG9zW2ldWzBdXG4gICAgdmFyIGNvbCA9IHBvc1tpXVsxXVxuXG4gICAgZm9yICh2YXIgciA9IC0xOyByIDw9IDc7IHIrKykge1xuICAgICAgaWYgKHJvdyArIHIgPD0gLTEgfHwgc2l6ZSA8PSByb3cgKyByKSBjb250aW51ZVxuXG4gICAgICBmb3IgKHZhciBjID0gLTE7IGMgPD0gNzsgYysrKSB7XG4gICAgICAgIGlmIChjb2wgKyBjIDw9IC0xIHx8IHNpemUgPD0gY29sICsgYykgY29udGludWVcblxuICAgICAgICBpZiAoKHIgPj0gMCAmJiByIDw9IDYgJiYgKGMgPT09IDAgfHwgYyA9PT0gNikpIHx8XG4gICAgICAgICAgKGMgPj0gMCAmJiBjIDw9IDYgJiYgKHIgPT09IDAgfHwgciA9PT0gNikpIHx8XG4gICAgICAgICAgKHIgPj0gMiAmJiByIDw9IDQgJiYgYyA+PSAyICYmIGMgPD0gNCkpIHtcbiAgICAgICAgICBtYXRyaXguc2V0KHJvdyArIHIsIGNvbCArIGMsIHRydWUsIHRydWUpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbWF0cml4LnNldChyb3cgKyByLCBjb2wgKyBjLCBmYWxzZSwgdHJ1ZSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEFkZCB0aW1pbmcgcGF0dGVybiBiaXRzIHRvIG1hdHJpeFxuICpcbiAqIE5vdGU6IHRoaXMgZnVuY3Rpb24gbXVzdCBiZSBjYWxsZWQgYmVmb3JlIHtAbGluayBzZXR1cEFsaWdubWVudFBhdHRlcm59XG4gKlxuICogQHBhcmFtICB7Qml0TWF0cml4fSBtYXRyaXggTW9kdWxlcyBtYXRyaXhcbiAqL1xuZnVuY3Rpb24gc2V0dXBUaW1pbmdQYXR0ZXJuIChtYXRyaXgpIHtcbiAgdmFyIHNpemUgPSBtYXRyaXguc2l6ZVxuXG4gIGZvciAodmFyIHIgPSA4OyByIDwgc2l6ZSAtIDg7IHIrKykge1xuICAgIHZhciB2YWx1ZSA9IHIgJSAyID09PSAwXG4gICAgbWF0cml4LnNldChyLCA2LCB2YWx1ZSwgdHJ1ZSlcbiAgICBtYXRyaXguc2V0KDYsIHIsIHZhbHVlLCB0cnVlKVxuICB9XG59XG5cbi8qKlxuICogQWRkIGFsaWdubWVudCBwYXR0ZXJucyBiaXRzIHRvIG1hdHJpeFxuICpcbiAqIE5vdGU6IHRoaXMgZnVuY3Rpb24gbXVzdCBiZSBjYWxsZWQgYWZ0ZXIge0BsaW5rIHNldHVwVGltaW5nUGF0dGVybn1cbiAqXG4gKiBAcGFyYW0gIHtCaXRNYXRyaXh9IG1hdHJpeCAgTW9kdWxlcyBtYXRyaXhcbiAqIEBwYXJhbSAge051bWJlcn0gICAgdmVyc2lvbiBRUiBDb2RlIHZlcnNpb25cbiAqL1xuZnVuY3Rpb24gc2V0dXBBbGlnbm1lbnRQYXR0ZXJuIChtYXRyaXgsIHZlcnNpb24pIHtcbiAgdmFyIHBvcyA9IEFsaWdubWVudFBhdHRlcm4uZ2V0UG9zaXRpb25zKHZlcnNpb24pXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBwb3MubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcm93ID0gcG9zW2ldWzBdXG4gICAgdmFyIGNvbCA9IHBvc1tpXVsxXVxuXG4gICAgZm9yICh2YXIgciA9IC0yOyByIDw9IDI7IHIrKykge1xuICAgICAgZm9yICh2YXIgYyA9IC0yOyBjIDw9IDI7IGMrKykge1xuICAgICAgICBpZiAociA9PT0gLTIgfHwgciA9PT0gMiB8fCBjID09PSAtMiB8fCBjID09PSAyIHx8XG4gICAgICAgICAgKHIgPT09IDAgJiYgYyA9PT0gMCkpIHtcbiAgICAgICAgICBtYXRyaXguc2V0KHJvdyArIHIsIGNvbCArIGMsIHRydWUsIHRydWUpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbWF0cml4LnNldChyb3cgKyByLCBjb2wgKyBjLCBmYWxzZSwgdHJ1ZSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEFkZCB2ZXJzaW9uIGluZm8gYml0cyB0byBtYXRyaXhcbiAqXG4gKiBAcGFyYW0gIHtCaXRNYXRyaXh9IG1hdHJpeCAgTW9kdWxlcyBtYXRyaXhcbiAqIEBwYXJhbSAge051bWJlcn0gICAgdmVyc2lvbiBRUiBDb2RlIHZlcnNpb25cbiAqL1xuZnVuY3Rpb24gc2V0dXBWZXJzaW9uSW5mbyAobWF0cml4LCB2ZXJzaW9uKSB7XG4gIHZhciBzaXplID0gbWF0cml4LnNpemVcbiAgdmFyIGJpdHMgPSBWZXJzaW9uLmdldEVuY29kZWRCaXRzKHZlcnNpb24pXG4gIHZhciByb3csIGNvbCwgbW9kXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAxODsgaSsrKSB7XG4gICAgcm93ID0gTWF0aC5mbG9vcihpIC8gMylcbiAgICBjb2wgPSBpICUgMyArIHNpemUgLSA4IC0gM1xuICAgIG1vZCA9ICgoYml0cyA+PiBpKSAmIDEpID09PSAxXG5cbiAgICBtYXRyaXguc2V0KHJvdywgY29sLCBtb2QsIHRydWUpXG4gICAgbWF0cml4LnNldChjb2wsIHJvdywgbW9kLCB0cnVlKVxuICB9XG59XG5cbi8qKlxuICogQWRkIGZvcm1hdCBpbmZvIGJpdHMgdG8gbWF0cml4XG4gKlxuICogQHBhcmFtICB7Qml0TWF0cml4fSBtYXRyaXggICAgICAgICAgICAgICBNb2R1bGVzIG1hdHJpeFxuICogQHBhcmFtICB7RXJyb3JDb3JyZWN0aW9uTGV2ZWx9ICAgIGVycm9yQ29ycmVjdGlvbkxldmVsIEVycm9yIGNvcnJlY3Rpb24gbGV2ZWxcbiAqIEBwYXJhbSAge051bWJlcn0gICAgbWFza1BhdHRlcm4gICAgICAgICAgTWFzayBwYXR0ZXJuIHJlZmVyZW5jZSB2YWx1ZVxuICovXG5mdW5jdGlvbiBzZXR1cEZvcm1hdEluZm8gKG1hdHJpeCwgZXJyb3JDb3JyZWN0aW9uTGV2ZWwsIG1hc2tQYXR0ZXJuKSB7XG4gIHZhciBzaXplID0gbWF0cml4LnNpemVcbiAgdmFyIGJpdHMgPSBGb3JtYXRJbmZvLmdldEVuY29kZWRCaXRzKGVycm9yQ29ycmVjdGlvbkxldmVsLCBtYXNrUGF0dGVybilcbiAgdmFyIGksIG1vZFxuXG4gIGZvciAoaSA9IDA7IGkgPCAxNTsgaSsrKSB7XG4gICAgbW9kID0gKChiaXRzID4+IGkpICYgMSkgPT09IDFcblxuICAgIC8vIHZlcnRpY2FsXG4gICAgaWYgKGkgPCA2KSB7XG4gICAgICBtYXRyaXguc2V0KGksIDgsIG1vZCwgdHJ1ZSlcbiAgICB9IGVsc2UgaWYgKGkgPCA4KSB7XG4gICAgICBtYXRyaXguc2V0KGkgKyAxLCA4LCBtb2QsIHRydWUpXG4gICAgfSBlbHNlIHtcbiAgICAgIG1hdHJpeC5zZXQoc2l6ZSAtIDE1ICsgaSwgOCwgbW9kLCB0cnVlKVxuICAgIH1cblxuICAgIC8vIGhvcml6b250YWxcbiAgICBpZiAoaSA8IDgpIHtcbiAgICAgIG1hdHJpeC5zZXQoOCwgc2l6ZSAtIGkgLSAxLCBtb2QsIHRydWUpXG4gICAgfSBlbHNlIGlmIChpIDwgOSkge1xuICAgICAgbWF0cml4LnNldCg4LCAxNSAtIGkgLSAxICsgMSwgbW9kLCB0cnVlKVxuICAgIH0gZWxzZSB7XG4gICAgICBtYXRyaXguc2V0KDgsIDE1IC0gaSAtIDEsIG1vZCwgdHJ1ZSlcbiAgICB9XG4gIH1cblxuICAvLyBmaXhlZCBtb2R1bGVcbiAgbWF0cml4LnNldChzaXplIC0gOCwgOCwgMSwgdHJ1ZSlcbn1cblxuLyoqXG4gKiBBZGQgZW5jb2RlZCBkYXRhIGJpdHMgdG8gbWF0cml4XG4gKlxuICogQHBhcmFtICB7Qml0TWF0cml4fSBtYXRyaXggTW9kdWxlcyBtYXRyaXhcbiAqIEBwYXJhbSAge0J1ZmZlcn0gICAgZGF0YSAgIERhdGEgY29kZXdvcmRzXG4gKi9cbmZ1bmN0aW9uIHNldHVwRGF0YSAobWF0cml4LCBkYXRhKSB7XG4gIHZhciBzaXplID0gbWF0cml4LnNpemVcbiAgdmFyIGluYyA9IC0xXG4gIHZhciByb3cgPSBzaXplIC0gMVxuICB2YXIgYml0SW5kZXggPSA3XG4gIHZhciBieXRlSW5kZXggPSAwXG5cbiAgZm9yICh2YXIgY29sID0gc2l6ZSAtIDE7IGNvbCA+IDA7IGNvbCAtPSAyKSB7XG4gICAgaWYgKGNvbCA9PT0gNikgY29sLS1cblxuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBmb3IgKHZhciBjID0gMDsgYyA8IDI7IGMrKykge1xuICAgICAgICBpZiAoIW1hdHJpeC5pc1Jlc2VydmVkKHJvdywgY29sIC0gYykpIHtcbiAgICAgICAgICB2YXIgZGFyayA9IGZhbHNlXG5cbiAgICAgICAgICBpZiAoYnl0ZUluZGV4IDwgZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGRhcmsgPSAoKChkYXRhW2J5dGVJbmRleF0gPj4+IGJpdEluZGV4KSAmIDEpID09PSAxKVxuICAgICAgICAgIH1cblxuICAgICAgICAgIG1hdHJpeC5zZXQocm93LCBjb2wgLSBjLCBkYXJrKVxuICAgICAgICAgIGJpdEluZGV4LS1cblxuICAgICAgICAgIGlmIChiaXRJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICAgIGJ5dGVJbmRleCsrXG4gICAgICAgICAgICBiaXRJbmRleCA9IDdcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcm93ICs9IGluY1xuXG4gICAgICBpZiAocm93IDwgMCB8fCBzaXplIDw9IHJvdykge1xuICAgICAgICByb3cgLT0gaW5jXG4gICAgICAgIGluYyA9IC1pbmNcbiAgICAgICAgYnJlYWtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGUgZW5jb2RlZCBjb2Rld29yZHMgZnJvbSBkYXRhIGlucHV0XG4gKlxuICogQHBhcmFtICB7TnVtYmVyfSAgIHZlcnNpb24gICAgICAgICAgICAgIFFSIENvZGUgdmVyc2lvblxuICogQHBhcmFtICB7RXJyb3JDb3JyZWN0aW9uTGV2ZWx9ICAgZXJyb3JDb3JyZWN0aW9uTGV2ZWwgRXJyb3IgY29ycmVjdGlvbiBsZXZlbFxuICogQHBhcmFtICB7Qnl0ZURhdGF9IGRhdGEgICAgICAgICAgICAgICAgIERhdGEgaW5wdXRcbiAqIEByZXR1cm4ge0J1ZmZlcn0gICAgICAgICAgICAgICAgICAgICAgICBCdWZmZXIgY29udGFpbmluZyBlbmNvZGVkIGNvZGV3b3Jkc1xuICovXG5mdW5jdGlvbiBjcmVhdGVEYXRhICh2ZXJzaW9uLCBlcnJvckNvcnJlY3Rpb25MZXZlbCwgc2VnbWVudHMpIHtcbiAgLy8gUHJlcGFyZSBkYXRhIGJ1ZmZlclxuICB2YXIgYnVmZmVyID0gbmV3IEJpdEJ1ZmZlcigpXG5cbiAgc2VnbWVudHMuZm9yRWFjaChmdW5jdGlvbiAoZGF0YSkge1xuICAgIC8vIHByZWZpeCBkYXRhIHdpdGggbW9kZSBpbmRpY2F0b3IgKDQgYml0cylcbiAgICBidWZmZXIucHV0KGRhdGEubW9kZS5iaXQsIDQpXG5cbiAgICAvLyBQcmVmaXggZGF0YSB3aXRoIGNoYXJhY3RlciBjb3VudCBpbmRpY2F0b3IuXG4gICAgLy8gVGhlIGNoYXJhY3RlciBjb3VudCBpbmRpY2F0b3IgaXMgYSBzdHJpbmcgb2YgYml0cyB0aGF0IHJlcHJlc2VudHMgdGhlXG4gICAgLy8gbnVtYmVyIG9mIGNoYXJhY3RlcnMgdGhhdCBhcmUgYmVpbmcgZW5jb2RlZC5cbiAgICAvLyBUaGUgY2hhcmFjdGVyIGNvdW50IGluZGljYXRvciBtdXN0IGJlIHBsYWNlZCBhZnRlciB0aGUgbW9kZSBpbmRpY2F0b3JcbiAgICAvLyBhbmQgbXVzdCBiZSBhIGNlcnRhaW4gbnVtYmVyIG9mIGJpdHMgbG9uZywgZGVwZW5kaW5nIG9uIHRoZSBRUiB2ZXJzaW9uXG4gICAgLy8gYW5kIGRhdGEgbW9kZVxuICAgIC8vIEBzZWUge0BsaW5rIE1vZGUuZ2V0Q2hhckNvdW50SW5kaWNhdG9yfS5cbiAgICBidWZmZXIucHV0KGRhdGEuZ2V0TGVuZ3RoKCksIE1vZGUuZ2V0Q2hhckNvdW50SW5kaWNhdG9yKGRhdGEubW9kZSwgdmVyc2lvbikpXG5cbiAgICAvLyBhZGQgYmluYXJ5IGRhdGEgc2VxdWVuY2UgdG8gYnVmZmVyXG4gICAgZGF0YS53cml0ZShidWZmZXIpXG4gIH0pXG5cbiAgLy8gQ2FsY3VsYXRlIHJlcXVpcmVkIG51bWJlciBvZiBiaXRzXG4gIHZhciB0b3RhbENvZGV3b3JkcyA9IFV0aWxzLmdldFN5bWJvbFRvdGFsQ29kZXdvcmRzKHZlcnNpb24pXG4gIHZhciBlY1RvdGFsQ29kZXdvcmRzID0gRUNDb2RlLmdldFRvdGFsQ29kZXdvcmRzQ291bnQodmVyc2lvbiwgZXJyb3JDb3JyZWN0aW9uTGV2ZWwpXG4gIHZhciBkYXRhVG90YWxDb2Rld29yZHNCaXRzID0gKHRvdGFsQ29kZXdvcmRzIC0gZWNUb3RhbENvZGV3b3JkcykgKiA4XG5cbiAgLy8gQWRkIGEgdGVybWluYXRvci5cbiAgLy8gSWYgdGhlIGJpdCBzdHJpbmcgaXMgc2hvcnRlciB0aGFuIHRoZSB0b3RhbCBudW1iZXIgb2YgcmVxdWlyZWQgYml0cyxcbiAgLy8gYSB0ZXJtaW5hdG9yIG9mIHVwIHRvIGZvdXIgMHMgbXVzdCBiZSBhZGRlZCB0byB0aGUgcmlnaHQgc2lkZSBvZiB0aGUgc3RyaW5nLlxuICAvLyBJZiB0aGUgYml0IHN0cmluZyBpcyBtb3JlIHRoYW4gZm91ciBiaXRzIHNob3J0ZXIgdGhhbiB0aGUgcmVxdWlyZWQgbnVtYmVyIG9mIGJpdHMsXG4gIC8vIGFkZCBmb3VyIDBzIHRvIHRoZSBlbmQuXG4gIGlmIChidWZmZXIuZ2V0TGVuZ3RoSW5CaXRzKCkgKyA0IDw9IGRhdGFUb3RhbENvZGV3b3Jkc0JpdHMpIHtcbiAgICBidWZmZXIucHV0KDAsIDQpXG4gIH1cblxuICAvLyBJZiB0aGUgYml0IHN0cmluZyBpcyBmZXdlciB0aGFuIGZvdXIgYml0cyBzaG9ydGVyLCBhZGQgb25seSB0aGUgbnVtYmVyIG9mIDBzIHRoYXRcbiAgLy8gYXJlIG5lZWRlZCB0byByZWFjaCB0aGUgcmVxdWlyZWQgbnVtYmVyIG9mIGJpdHMuXG5cbiAgLy8gQWZ0ZXIgYWRkaW5nIHRoZSB0ZXJtaW5hdG9yLCBpZiB0aGUgbnVtYmVyIG9mIGJpdHMgaW4gdGhlIHN0cmluZyBpcyBub3QgYSBtdWx0aXBsZSBvZiA4LFxuICAvLyBwYWQgdGhlIHN0cmluZyBvbiB0aGUgcmlnaHQgd2l0aCAwcyB0byBtYWtlIHRoZSBzdHJpbmcncyBsZW5ndGggYSBtdWx0aXBsZSBvZiA4LlxuICB3aGlsZSAoYnVmZmVyLmdldExlbmd0aEluQml0cygpICUgOCAhPT0gMCkge1xuICAgIGJ1ZmZlci5wdXRCaXQoMClcbiAgfVxuXG4gIC8vIEFkZCBwYWQgYnl0ZXMgaWYgdGhlIHN0cmluZyBpcyBzdGlsbCBzaG9ydGVyIHRoYW4gdGhlIHRvdGFsIG51bWJlciBvZiByZXF1aXJlZCBiaXRzLlxuICAvLyBFeHRlbmQgdGhlIGJ1ZmZlciB0byBmaWxsIHRoZSBkYXRhIGNhcGFjaXR5IG9mIHRoZSBzeW1ib2wgY29ycmVzcG9uZGluZyB0b1xuICAvLyB0aGUgVmVyc2lvbiBhbmQgRXJyb3IgQ29ycmVjdGlvbiBMZXZlbCBieSBhZGRpbmcgdGhlIFBhZCBDb2Rld29yZHMgMTExMDExMDAgKDB4RUMpXG4gIC8vIGFuZCAwMDAxMDAwMSAoMHgxMSkgYWx0ZXJuYXRlbHkuXG4gIHZhciByZW1haW5pbmdCeXRlID0gKGRhdGFUb3RhbENvZGV3b3Jkc0JpdHMgLSBidWZmZXIuZ2V0TGVuZ3RoSW5CaXRzKCkpIC8gOFxuICBmb3IgKHZhciBpID0gMDsgaSA8IHJlbWFpbmluZ0J5dGU7IGkrKykge1xuICAgIGJ1ZmZlci5wdXQoaSAlIDIgPyAweDExIDogMHhFQywgOClcbiAgfVxuXG4gIHJldHVybiBjcmVhdGVDb2Rld29yZHMoYnVmZmVyLCB2ZXJzaW9uLCBlcnJvckNvcnJlY3Rpb25MZXZlbClcbn1cblxuLyoqXG4gKiBFbmNvZGUgaW5wdXQgZGF0YSB3aXRoIFJlZWQtU29sb21vbiBhbmQgcmV0dXJuIGNvZGV3b3JkcyB3aXRoXG4gKiByZWxhdGl2ZSBlcnJvciBjb3JyZWN0aW9uIGJpdHNcbiAqXG4gKiBAcGFyYW0gIHtCaXRCdWZmZXJ9IGJpdEJ1ZmZlciAgICAgICAgICAgIERhdGEgdG8gZW5jb2RlXG4gKiBAcGFyYW0gIHtOdW1iZXJ9ICAgIHZlcnNpb24gICAgICAgICAgICAgIFFSIENvZGUgdmVyc2lvblxuICogQHBhcmFtICB7RXJyb3JDb3JyZWN0aW9uTGV2ZWx9IGVycm9yQ29ycmVjdGlvbkxldmVsIEVycm9yIGNvcnJlY3Rpb24gbGV2ZWxcbiAqIEByZXR1cm4ge0J1ZmZlcn0gICAgICAgICAgICAgICAgICAgICAgICAgQnVmZmVyIGNvbnRhaW5pbmcgZW5jb2RlZCBjb2Rld29yZHNcbiAqL1xuZnVuY3Rpb24gY3JlYXRlQ29kZXdvcmRzIChiaXRCdWZmZXIsIHZlcnNpb24sIGVycm9yQ29ycmVjdGlvbkxldmVsKSB7XG4gIC8vIFRvdGFsIGNvZGV3b3JkcyBmb3IgdGhpcyBRUiBjb2RlIHZlcnNpb24gKERhdGEgKyBFcnJvciBjb3JyZWN0aW9uKVxuICB2YXIgdG90YWxDb2Rld29yZHMgPSBVdGlscy5nZXRTeW1ib2xUb3RhbENvZGV3b3Jkcyh2ZXJzaW9uKVxuXG4gIC8vIFRvdGFsIG51bWJlciBvZiBlcnJvciBjb3JyZWN0aW9uIGNvZGV3b3Jkc1xuICB2YXIgZWNUb3RhbENvZGV3b3JkcyA9IEVDQ29kZS5nZXRUb3RhbENvZGV3b3Jkc0NvdW50KHZlcnNpb24sIGVycm9yQ29ycmVjdGlvbkxldmVsKVxuXG4gIC8vIFRvdGFsIG51bWJlciBvZiBkYXRhIGNvZGV3b3Jkc1xuICB2YXIgZGF0YVRvdGFsQ29kZXdvcmRzID0gdG90YWxDb2Rld29yZHMgLSBlY1RvdGFsQ29kZXdvcmRzXG5cbiAgLy8gVG90YWwgbnVtYmVyIG9mIGJsb2Nrc1xuICB2YXIgZWNUb3RhbEJsb2NrcyA9IEVDQ29kZS5nZXRCbG9ja3NDb3VudCh2ZXJzaW9uLCBlcnJvckNvcnJlY3Rpb25MZXZlbClcblxuICAvLyBDYWxjdWxhdGUgaG93IG1hbnkgYmxvY2tzIGVhY2ggZ3JvdXAgc2hvdWxkIGNvbnRhaW5cbiAgdmFyIGJsb2Nrc0luR3JvdXAyID0gdG90YWxDb2Rld29yZHMgJSBlY1RvdGFsQmxvY2tzXG4gIHZhciBibG9ja3NJbkdyb3VwMSA9IGVjVG90YWxCbG9ja3MgLSBibG9ja3NJbkdyb3VwMlxuXG4gIHZhciB0b3RhbENvZGV3b3Jkc0luR3JvdXAxID0gTWF0aC5mbG9vcih0b3RhbENvZGV3b3JkcyAvIGVjVG90YWxCbG9ja3MpXG5cbiAgdmFyIGRhdGFDb2Rld29yZHNJbkdyb3VwMSA9IE1hdGguZmxvb3IoZGF0YVRvdGFsQ29kZXdvcmRzIC8gZWNUb3RhbEJsb2NrcylcbiAgdmFyIGRhdGFDb2Rld29yZHNJbkdyb3VwMiA9IGRhdGFDb2Rld29yZHNJbkdyb3VwMSArIDFcblxuICAvLyBOdW1iZXIgb2YgRUMgY29kZXdvcmRzIGlzIHRoZSBzYW1lIGZvciBib3RoIGdyb3Vwc1xuICB2YXIgZWNDb3VudCA9IHRvdGFsQ29kZXdvcmRzSW5Hcm91cDEgLSBkYXRhQ29kZXdvcmRzSW5Hcm91cDFcblxuICAvLyBJbml0aWFsaXplIGEgUmVlZC1Tb2xvbW9uIGVuY29kZXIgd2l0aCBhIGdlbmVyYXRvciBwb2x5bm9taWFsIG9mIGRlZ3JlZSBlY0NvdW50XG4gIHZhciBycyA9IG5ldyBSZWVkU29sb21vbkVuY29kZXIoZWNDb3VudClcblxuICB2YXIgb2Zmc2V0ID0gMFxuICB2YXIgZGNEYXRhID0gbmV3IEFycmF5KGVjVG90YWxCbG9ja3MpXG4gIHZhciBlY0RhdGEgPSBuZXcgQXJyYXkoZWNUb3RhbEJsb2NrcylcbiAgdmFyIG1heERhdGFTaXplID0gMFxuICB2YXIgYnVmZmVyID0gbmV3IEJ1ZmZlcihiaXRCdWZmZXIuYnVmZmVyKVxuXG4gIC8vIERpdmlkZSB0aGUgYnVmZmVyIGludG8gdGhlIHJlcXVpcmVkIG51bWJlciBvZiBibG9ja3NcbiAgZm9yICh2YXIgYiA9IDA7IGIgPCBlY1RvdGFsQmxvY2tzOyBiKyspIHtcbiAgICB2YXIgZGF0YVNpemUgPSBiIDwgYmxvY2tzSW5Hcm91cDEgPyBkYXRhQ29kZXdvcmRzSW5Hcm91cDEgOiBkYXRhQ29kZXdvcmRzSW5Hcm91cDJcblxuICAgIC8vIGV4dHJhY3QgYSBibG9jayBvZiBkYXRhIGZyb20gYnVmZmVyXG4gICAgZGNEYXRhW2JdID0gYnVmZmVyLnNsaWNlKG9mZnNldCwgb2Zmc2V0ICsgZGF0YVNpemUpXG5cbiAgICAvLyBDYWxjdWxhdGUgRUMgY29kZXdvcmRzIGZvciB0aGlzIGRhdGEgYmxvY2tcbiAgICBlY0RhdGFbYl0gPSBycy5lbmNvZGUoZGNEYXRhW2JdKVxuXG4gICAgb2Zmc2V0ICs9IGRhdGFTaXplXG4gICAgbWF4RGF0YVNpemUgPSBNYXRoLm1heChtYXhEYXRhU2l6ZSwgZGF0YVNpemUpXG4gIH1cblxuICAvLyBDcmVhdGUgZmluYWwgZGF0YVxuICAvLyBJbnRlcmxlYXZlIHRoZSBkYXRhIGFuZCBlcnJvciBjb3JyZWN0aW9uIGNvZGV3b3JkcyBmcm9tIGVhY2ggYmxvY2tcbiAgdmFyIGRhdGEgPSBuZXcgQnVmZmVyKHRvdGFsQ29kZXdvcmRzKVxuICB2YXIgaW5kZXggPSAwXG4gIHZhciBpLCByXG5cbiAgLy8gQWRkIGRhdGEgY29kZXdvcmRzXG4gIGZvciAoaSA9IDA7IGkgPCBtYXhEYXRhU2l6ZTsgaSsrKSB7XG4gICAgZm9yIChyID0gMDsgciA8IGVjVG90YWxCbG9ja3M7IHIrKykge1xuICAgICAgaWYgKGkgPCBkY0RhdGFbcl0ubGVuZ3RoKSB7XG4gICAgICAgIGRhdGFbaW5kZXgrK10gPSBkY0RhdGFbcl1baV1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBBcHBlZCBFQyBjb2Rld29yZHNcbiAgZm9yIChpID0gMDsgaSA8IGVjQ291bnQ7IGkrKykge1xuICAgIGZvciAociA9IDA7IHIgPCBlY1RvdGFsQmxvY2tzOyByKyspIHtcbiAgICAgIGRhdGFbaW5kZXgrK10gPSBlY0RhdGFbcl1baV1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gZGF0YVxufVxuXG4vKipcbiAqIEJ1aWxkIFFSIENvZGUgc3ltYm9sXG4gKlxuICogQHBhcmFtICB7U3RyaW5nfSBkYXRhICAgICAgICAgICAgICAgICBJbnB1dCBzdHJpbmdcbiAqIEBwYXJhbSAge051bWJlcn0gdmVyc2lvbiAgICAgICAgICAgICAgUVIgQ29kZSB2ZXJzaW9uXG4gKiBAcGFyYW0gIHtFcnJvckNvcnJldGlvbkxldmVsfSBlcnJvckNvcnJlY3Rpb25MZXZlbCBFcnJvciBsZXZlbFxuICogQHBhcmFtICB7TWFza1BhdHRlcm59IG1hc2tQYXR0ZXJuICAgICBNYXNrIHBhdHRlcm5cbiAqIEByZXR1cm4ge09iamVjdH0gICAgICAgICAgICAgICAgICAgICAgT2JqZWN0IGNvbnRhaW5pbmcgc3ltYm9sIGRhdGFcbiAqL1xuZnVuY3Rpb24gY3JlYXRlU3ltYm9sIChkYXRhLCB2ZXJzaW9uLCBlcnJvckNvcnJlY3Rpb25MZXZlbCwgbWFza1BhdHRlcm4pIHtcbiAgdmFyIHNlZ21lbnRzXG5cbiAgaWYgKGlzQXJyYXkoZGF0YSkpIHtcbiAgICBzZWdtZW50cyA9IFNlZ21lbnRzLmZyb21BcnJheShkYXRhKVxuICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJykge1xuICAgIHZhciBlc3RpbWF0ZWRWZXJzaW9uID0gdmVyc2lvblxuXG4gICAgaWYgKCFlc3RpbWF0ZWRWZXJzaW9uKSB7XG4gICAgICB2YXIgcmF3U2VnbWVudHMgPSBTZWdtZW50cy5yYXdTcGxpdChkYXRhKVxuXG4gICAgICAvLyBFc3RpbWF0ZSBiZXN0IHZlcnNpb24gdGhhdCBjYW4gY29udGFpbiByYXcgc3BsaXR0ZWQgc2VnbWVudHNcbiAgICAgIGVzdGltYXRlZFZlcnNpb24gPSBWZXJzaW9uLmdldEJlc3RWZXJzaW9uRm9yRGF0YShyYXdTZWdtZW50cyxcbiAgICAgICAgZXJyb3JDb3JyZWN0aW9uTGV2ZWwpXG4gICAgfVxuXG4gICAgLy8gQnVpbGQgb3B0aW1pemVkIHNlZ21lbnRzXG4gICAgLy8gSWYgZXN0aW1hdGVkIHZlcnNpb24gaXMgdW5kZWZpbmVkLCB0cnkgd2l0aCB0aGUgaGlnaGVzdCB2ZXJzaW9uXG4gICAgc2VnbWVudHMgPSBTZWdtZW50cy5mcm9tU3RyaW5nKGRhdGEsIGVzdGltYXRlZFZlcnNpb24gfHwgNDApXG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGRhdGEnKVxuICB9XG5cbiAgLy8gR2V0IHRoZSBtaW4gdmVyc2lvbiB0aGF0IGNhbiBjb250YWluIGRhdGFcbiAgdmFyIGJlc3RWZXJzaW9uID0gVmVyc2lvbi5nZXRCZXN0VmVyc2lvbkZvckRhdGEoc2VnbWVudHMsXG4gICAgICBlcnJvckNvcnJlY3Rpb25MZXZlbClcblxuICAvLyBJZiBubyB2ZXJzaW9uIGlzIGZvdW5kLCBkYXRhIGNhbm5vdCBiZSBzdG9yZWRcbiAgaWYgKCFiZXN0VmVyc2lvbikge1xuICAgIHRocm93IG5ldyBFcnJvcignVGhlIGFtb3VudCBvZiBkYXRhIGlzIHRvbyBiaWcgdG8gYmUgc3RvcmVkIGluIGEgUVIgQ29kZScpXG4gIH1cblxuICAvLyBJZiBub3Qgc3BlY2lmaWVkLCB1c2UgbWluIHZlcnNpb24gYXMgZGVmYXVsdFxuICBpZiAoIXZlcnNpb24pIHtcbiAgICB2ZXJzaW9uID0gYmVzdFZlcnNpb25cblxuICAvLyBDaGVjayBpZiB0aGUgc3BlY2lmaWVkIHZlcnNpb24gY2FuIGNvbnRhaW4gdGhlIGRhdGFcbiAgfSBlbHNlIGlmICh2ZXJzaW9uIDwgYmVzdFZlcnNpb24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1xcbicgK1xuICAgICAgJ1RoZSBjaG9zZW4gUVIgQ29kZSB2ZXJzaW9uIGNhbm5vdCBjb250YWluIHRoaXMgYW1vdW50IG9mIGRhdGEuXFxuJyArXG4gICAgICAnTWluaW11bSB2ZXJzaW9uIHJlcXVpcmVkIHRvIHN0b3JlIGN1cnJlbnQgZGF0YSBpczogJyArIGJlc3RWZXJzaW9uICsgJy5cXG4nXG4gICAgKVxuICB9XG5cbiAgdmFyIGRhdGFCaXRzID0gY3JlYXRlRGF0YSh2ZXJzaW9uLCBlcnJvckNvcnJlY3Rpb25MZXZlbCwgc2VnbWVudHMpXG5cbiAgLy8gQWxsb2NhdGUgbWF0cml4IGJ1ZmZlclxuICB2YXIgbW9kdWxlQ291bnQgPSBVdGlscy5nZXRTeW1ib2xTaXplKHZlcnNpb24pXG4gIHZhciBtb2R1bGVzID0gbmV3IEJpdE1hdHJpeChtb2R1bGVDb3VudClcblxuICAvLyBBZGQgZnVuY3Rpb24gbW9kdWxlc1xuICBzZXR1cEZpbmRlclBhdHRlcm4obW9kdWxlcywgdmVyc2lvbilcbiAgc2V0dXBUaW1pbmdQYXR0ZXJuKG1vZHVsZXMpXG4gIHNldHVwQWxpZ25tZW50UGF0dGVybihtb2R1bGVzLCB2ZXJzaW9uKVxuXG4gIC8vIEFkZCB0ZW1wb3JhcnkgZHVtbXkgYml0cyBmb3IgZm9ybWF0IGluZm8ganVzdCB0byBzZXQgdGhlbSBhcyByZXNlcnZlZC5cbiAgLy8gVGhpcyBpcyBuZWVkZWQgdG8gcHJldmVudCB0aGVzZSBiaXRzIGZyb20gYmVpbmcgbWFza2VkIGJ5IHtAbGluayBNYXNrUGF0dGVybi5hcHBseU1hc2t9XG4gIC8vIHNpbmNlIHRoZSBtYXNraW5nIG9wZXJhdGlvbiBtdXN0IGJlIHBlcmZvcm1lZCBvbmx5IG9uIHRoZSBlbmNvZGluZyByZWdpb24uXG4gIC8vIFRoZXNlIGJsb2NrcyB3aWxsIGJlIHJlcGxhY2VkIHdpdGggY29ycmVjdCB2YWx1ZXMgbGF0ZXIgaW4gY29kZS5cbiAgc2V0dXBGb3JtYXRJbmZvKG1vZHVsZXMsIGVycm9yQ29ycmVjdGlvbkxldmVsLCAwKVxuXG4gIGlmICh2ZXJzaW9uID49IDcpIHtcbiAgICBzZXR1cFZlcnNpb25JbmZvKG1vZHVsZXMsIHZlcnNpb24pXG4gIH1cblxuICAvLyBBZGQgZGF0YSBjb2Rld29yZHNcbiAgc2V0dXBEYXRhKG1vZHVsZXMsIGRhdGFCaXRzKVxuXG4gIGlmIChpc05hTihtYXNrUGF0dGVybikpIHtcbiAgICAvLyBGaW5kIGJlc3QgbWFzayBwYXR0ZXJuXG4gICAgbWFza1BhdHRlcm4gPSBNYXNrUGF0dGVybi5nZXRCZXN0TWFzayhtb2R1bGVzLFxuICAgICAgc2V0dXBGb3JtYXRJbmZvLmJpbmQobnVsbCwgbW9kdWxlcywgZXJyb3JDb3JyZWN0aW9uTGV2ZWwpKVxuICB9XG5cbiAgLy8gQXBwbHkgbWFzayBwYXR0ZXJuXG4gIE1hc2tQYXR0ZXJuLmFwcGx5TWFzayhtYXNrUGF0dGVybiwgbW9kdWxlcylcblxuICAvLyBSZXBsYWNlIGZvcm1hdCBpbmZvIGJpdHMgd2l0aCBjb3JyZWN0IHZhbHVlc1xuICBzZXR1cEZvcm1hdEluZm8obW9kdWxlcywgZXJyb3JDb3JyZWN0aW9uTGV2ZWwsIG1hc2tQYXR0ZXJuKVxuXG4gIHJldHVybiB7XG4gICAgbW9kdWxlczogbW9kdWxlcyxcbiAgICB2ZXJzaW9uOiB2ZXJzaW9uLFxuICAgIGVycm9yQ29ycmVjdGlvbkxldmVsOiBlcnJvckNvcnJlY3Rpb25MZXZlbCxcbiAgICBtYXNrUGF0dGVybjogbWFza1BhdHRlcm4sXG4gICAgc2VnbWVudHM6IHNlZ21lbnRzXG4gIH1cbn1cblxuLyoqXG4gKiBRUiBDb2RlXG4gKlxuICogQHBhcmFtIHtTdHJpbmcgfCBBcnJheX0gZGF0YSAgICAgICAgICAgICAgICAgSW5wdXQgZGF0YVxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgICAgICAgICAgICAgICAgICAgICAgT3B0aW9uYWwgY29uZmlndXJhdGlvbnNcbiAqIEBwYXJhbSB7TnVtYmVyfSBvcHRpb25zLnZlcnNpb24gICAgICAgICAgICAgIFFSIENvZGUgdmVyc2lvblxuICogQHBhcmFtIHtTdHJpbmd9IG9wdGlvbnMuZXJyb3JDb3JyZWN0aW9uTGV2ZWwgRXJyb3IgY29ycmVjdGlvbiBsZXZlbFxuICogQHBhcmFtIHtGdW5jdGlvbn0gb3B0aW9ucy50b1NKSVNGdW5jICAgICAgICAgSGVscGVyIGZ1bmMgdG8gY29udmVydCB1dGY4IHRvIHNqaXNcbiAqL1xuZXhwb3J0cy5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUgKGRhdGEsIG9wdGlvbnMpIHtcbiAgaWYgKHR5cGVvZiBkYXRhID09PSAndW5kZWZpbmVkJyB8fCBkYXRhID09PSAnJykge1xuICAgIHRocm93IG5ldyBFcnJvcignTm8gaW5wdXQgdGV4dCcpXG4gIH1cblxuICB2YXIgZXJyb3JDb3JyZWN0aW9uTGV2ZWwgPSBFQ0xldmVsLk1cbiAgdmFyIHZlcnNpb25cbiAgdmFyIG1hc2tcblxuICBpZiAodHlwZW9mIG9wdGlvbnMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgLy8gVXNlIGhpZ2hlciBlcnJvciBjb3JyZWN0aW9uIGxldmVsIGFzIGRlZmF1bHRcbiAgICBlcnJvckNvcnJlY3Rpb25MZXZlbCA9IEVDTGV2ZWwuZnJvbShvcHRpb25zLmVycm9yQ29ycmVjdGlvbkxldmVsLCBFQ0xldmVsLk0pXG4gICAgdmVyc2lvbiA9IFZlcnNpb24uZnJvbShvcHRpb25zLnZlcnNpb24pXG4gICAgbWFzayA9IE1hc2tQYXR0ZXJuLmZyb20ob3B0aW9ucy5tYXNrUGF0dGVybilcblxuICAgIGlmIChvcHRpb25zLnRvU0pJU0Z1bmMpIHtcbiAgICAgIFV0aWxzLnNldFRvU0pJU0Z1bmN0aW9uKG9wdGlvbnMudG9TSklTRnVuYylcbiAgICB9XG4gIH1cblxuICByZXR1cm4gY3JlYXRlU3ltYm9sKGRhdGEsIHZlcnNpb24sIGVycm9yQ29ycmVjdGlvbkxldmVsLCBtYXNrKVxufVxuIiwidmFyIEJ1ZmZlciA9IHJlcXVpcmUoJy4uL3V0aWxzL2J1ZmZlcicpXG52YXIgUG9seW5vbWlhbCA9IHJlcXVpcmUoJy4vcG9seW5vbWlhbCcpXG5cbmZ1bmN0aW9uIFJlZWRTb2xvbW9uRW5jb2RlciAoZGVncmVlKSB7XG4gIHRoaXMuZ2VuUG9seSA9IHVuZGVmaW5lZFxuICB0aGlzLmRlZ3JlZSA9IGRlZ3JlZVxuXG4gIGlmICh0aGlzLmRlZ3JlZSkgdGhpcy5pbml0aWFsaXplKHRoaXMuZGVncmVlKVxufVxuXG4vKipcbiAqIEluaXRpYWxpemUgdGhlIGVuY29kZXIuXG4gKiBUaGUgaW5wdXQgcGFyYW0gc2hvdWxkIGNvcnJlc3BvbmQgdG8gdGhlIG51bWJlciBvZiBlcnJvciBjb3JyZWN0aW9uIGNvZGV3b3Jkcy5cbiAqXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IGRlZ3JlZVxuICovXG5SZWVkU29sb21vbkVuY29kZXIucHJvdG90eXBlLmluaXRpYWxpemUgPSBmdW5jdGlvbiBpbml0aWFsaXplIChkZWdyZWUpIHtcbiAgLy8gY3JlYXRlIGFuIGlycmVkdWNpYmxlIGdlbmVyYXRvciBwb2x5bm9taWFsXG4gIHRoaXMuZGVncmVlID0gZGVncmVlXG4gIHRoaXMuZ2VuUG9seSA9IFBvbHlub21pYWwuZ2VuZXJhdGVFQ1BvbHlub21pYWwodGhpcy5kZWdyZWUpXG59XG5cbi8qKlxuICogRW5jb2RlcyBhIGNodW5rIG9mIGRhdGFcbiAqXG4gKiBAcGFyYW0gIHtCdWZmZXJ9IGRhdGEgQnVmZmVyIGNvbnRhaW5pbmcgaW5wdXQgZGF0YVxuICogQHJldHVybiB7QnVmZmVyfSAgICAgIEJ1ZmZlciBjb250YWluaW5nIGVuY29kZWQgZGF0YVxuICovXG5SZWVkU29sb21vbkVuY29kZXIucHJvdG90eXBlLmVuY29kZSA9IGZ1bmN0aW9uIGVuY29kZSAoZGF0YSkge1xuICBpZiAoIXRoaXMuZ2VuUG9seSkge1xuICAgIHRocm93IG5ldyBFcnJvcignRW5jb2RlciBub3QgaW5pdGlhbGl6ZWQnKVxuICB9XG5cbiAgLy8gQ2FsY3VsYXRlIEVDIGZvciB0aGlzIGRhdGEgYmxvY2tcbiAgLy8gZXh0ZW5kcyBkYXRhIHNpemUgdG8gZGF0YStnZW5Qb2x5IHNpemVcbiAgdmFyIHBhZCA9IG5ldyBCdWZmZXIodGhpcy5kZWdyZWUpXG4gIHBhZC5maWxsKDApXG4gIHZhciBwYWRkZWREYXRhID0gQnVmZmVyLmNvbmNhdChbZGF0YSwgcGFkXSwgZGF0YS5sZW5ndGggKyB0aGlzLmRlZ3JlZSlcblxuICAvLyBUaGUgZXJyb3IgY29ycmVjdGlvbiBjb2Rld29yZHMgYXJlIHRoZSByZW1haW5kZXIgYWZ0ZXIgZGl2aWRpbmcgdGhlIGRhdGEgY29kZXdvcmRzXG4gIC8vIGJ5IGEgZ2VuZXJhdG9yIHBvbHlub21pYWxcbiAgdmFyIHJlbWFpbmRlciA9IFBvbHlub21pYWwubW9kKHBhZGRlZERhdGEsIHRoaXMuZ2VuUG9seSlcblxuICAvLyByZXR1cm4gRUMgZGF0YSBibG9ja3MgKGxhc3QgbiBieXRlLCB3aGVyZSBuIGlzIHRoZSBkZWdyZWUgb2YgZ2VuUG9seSlcbiAgLy8gSWYgY29lZmZpY2llbnRzIG51bWJlciBpbiByZW1haW5kZXIgYXJlIGxlc3MgdGhhbiBnZW5Qb2x5IGRlZ3JlZSxcbiAgLy8gcGFkIHdpdGggMHMgdG8gdGhlIGxlZnQgdG8gcmVhY2ggdGhlIG5lZWRlZCBudW1iZXIgb2YgY29lZmZpY2llbnRzXG4gIHZhciBzdGFydCA9IHRoaXMuZGVncmVlIC0gcmVtYWluZGVyLmxlbmd0aFxuICBpZiAoc3RhcnQgPiAwKSB7XG4gICAgdmFyIGJ1ZmYgPSBuZXcgQnVmZmVyKHRoaXMuZGVncmVlKVxuICAgIGJ1ZmYuZmlsbCgwKVxuICAgIHJlbWFpbmRlci5jb3B5KGJ1ZmYsIHN0YXJ0KVxuXG4gICAgcmV0dXJuIGJ1ZmZcbiAgfVxuXG4gIHJldHVybiByZW1haW5kZXJcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBSZWVkU29sb21vbkVuY29kZXJcbiIsInZhciBudW1lcmljID0gJ1swLTldKydcbnZhciBhbHBoYW51bWVyaWMgPSAnW0EtWiAkJSorXFxcXC0uLzpdKydcbnZhciBrYW5qaSA9ICcoPzpbdTMwMDAtdTMwM0ZdfFt1MzA0MC11MzA5Rl18W3UzMEEwLXUzMEZGXXwnICtcbiAgJ1t1RkYwMC11RkZFRl18W3U0RTAwLXU5RkFGXXxbdTI2MDUtdTI2MDZdfFt1MjE5MC11MjE5NV18dTIwM0J8JyArXG4gICdbdTIwMTB1MjAxNXUyMDE4dTIwMTl1MjAyNXUyMDI2dTIwMUN1MjAxRHUyMjI1dTIyNjBdfCcgK1xuICAnW3UwMzkxLXUwNDUxXXxbdTAwQTd1MDBBOHUwMEIxdTAwQjR1MDBEN3UwMEY3XSkrJ1xua2FuamkgPSBrYW5qaS5yZXBsYWNlKC91L2csICdcXFxcdScpXG5cbnZhciBieXRlID0gJyg/Oig/IVtBLVowLTkgJCUqK1xcXFwtLi86XXwnICsga2FuamkgKyAnKSg/Oi58W1xcclxcbl0pKSsnXG5cbmV4cG9ydHMuS0FOSkkgPSBuZXcgUmVnRXhwKGthbmppLCAnZycpXG5leHBvcnRzLkJZVEVfS0FOSkkgPSBuZXcgUmVnRXhwKCdbXkEtWjAtOSAkJSorXFxcXC0uLzpdKycsICdnJylcbmV4cG9ydHMuQllURSA9IG5ldyBSZWdFeHAoYnl0ZSwgJ2cnKVxuZXhwb3J0cy5OVU1FUklDID0gbmV3IFJlZ0V4cChudW1lcmljLCAnZycpXG5leHBvcnRzLkFMUEhBTlVNRVJJQyA9IG5ldyBSZWdFeHAoYWxwaGFudW1lcmljLCAnZycpXG5cbnZhciBURVNUX0tBTkpJID0gbmV3IFJlZ0V4cCgnXicgKyBrYW5qaSArICckJylcbnZhciBURVNUX05VTUVSSUMgPSBuZXcgUmVnRXhwKCdeJyArIG51bWVyaWMgKyAnJCcpXG52YXIgVEVTVF9BTFBIQU5VTUVSSUMgPSBuZXcgUmVnRXhwKCdeW0EtWjAtOSAkJSorXFxcXC0uLzpdKyQnKVxuXG5leHBvcnRzLnRlc3RLYW5qaSA9IGZ1bmN0aW9uIHRlc3RLYW5qaSAoc3RyKSB7XG4gIHJldHVybiBURVNUX0tBTkpJLnRlc3Qoc3RyKVxufVxuXG5leHBvcnRzLnRlc3ROdW1lcmljID0gZnVuY3Rpb24gdGVzdE51bWVyaWMgKHN0cikge1xuICByZXR1cm4gVEVTVF9OVU1FUklDLnRlc3Qoc3RyKVxufVxuXG5leHBvcnRzLnRlc3RBbHBoYW51bWVyaWMgPSBmdW5jdGlvbiB0ZXN0QWxwaGFudW1lcmljIChzdHIpIHtcbiAgcmV0dXJuIFRFU1RfQUxQSEFOVU1FUklDLnRlc3Qoc3RyKVxufVxuIiwidmFyIE1vZGUgPSByZXF1aXJlKCcuL21vZGUnKVxudmFyIE51bWVyaWNEYXRhID0gcmVxdWlyZSgnLi9udW1lcmljLWRhdGEnKVxudmFyIEFscGhhbnVtZXJpY0RhdGEgPSByZXF1aXJlKCcuL2FscGhhbnVtZXJpYy1kYXRhJylcbnZhciBCeXRlRGF0YSA9IHJlcXVpcmUoJy4vYnl0ZS1kYXRhJylcbnZhciBLYW5qaURhdGEgPSByZXF1aXJlKCcuL2thbmppLWRhdGEnKVxudmFyIFJlZ2V4ID0gcmVxdWlyZSgnLi9yZWdleCcpXG52YXIgVXRpbHMgPSByZXF1aXJlKCcuL3V0aWxzJylcbnZhciBkaWprc3RyYSA9IHJlcXVpcmUoJ2RpamtzdHJhanMnKVxuXG4vKipcbiAqIFJldHVybnMgVVRGOCBieXRlIGxlbmd0aFxuICpcbiAqIEBwYXJhbSAge1N0cmluZ30gc3RyIElucHV0IHN0cmluZ1xuICogQHJldHVybiB7TnVtYmVyfSAgICAgTnVtYmVyIG9mIGJ5dGVcbiAqL1xuZnVuY3Rpb24gZ2V0U3RyaW5nQnl0ZUxlbmd0aCAoc3RyKSB7XG4gIHJldHVybiB1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQoc3RyKSkubGVuZ3RoXG59XG5cbi8qKlxuICogR2V0IGEgbGlzdCBvZiBzZWdtZW50cyBvZiB0aGUgc3BlY2lmaWVkIG1vZGVcbiAqIGZyb20gYSBzdHJpbmdcbiAqXG4gKiBAcGFyYW0gIHtNb2RlfSAgIG1vZGUgU2VnbWVudCBtb2RlXG4gKiBAcGFyYW0gIHtTdHJpbmd9IHN0ciAgU3RyaW5nIHRvIHByb2Nlc3NcbiAqIEByZXR1cm4ge0FycmF5fSAgICAgICBBcnJheSBvZiBvYmplY3Qgd2l0aCBzZWdtZW50cyBkYXRhXG4gKi9cbmZ1bmN0aW9uIGdldFNlZ21lbnRzIChyZWdleCwgbW9kZSwgc3RyKSB7XG4gIHZhciBzZWdtZW50cyA9IFtdXG4gIHZhciByZXN1bHRcblxuICB3aGlsZSAoKHJlc3VsdCA9IHJlZ2V4LmV4ZWMoc3RyKSkgIT09IG51bGwpIHtcbiAgICBzZWdtZW50cy5wdXNoKHtcbiAgICAgIGRhdGE6IHJlc3VsdFswXSxcbiAgICAgIGluZGV4OiByZXN1bHQuaW5kZXgsXG4gICAgICBtb2RlOiBtb2RlLFxuICAgICAgbGVuZ3RoOiByZXN1bHRbMF0ubGVuZ3RoXG4gICAgfSlcbiAgfVxuXG4gIHJldHVybiBzZWdtZW50c1xufVxuXG4vKipcbiAqIEV4dHJhY3RzIGEgc2VyaWVzIG9mIHNlZ21lbnRzIHdpdGggdGhlIGFwcHJvcHJpYXRlXG4gKiBtb2RlcyBmcm9tIGEgc3RyaW5nXG4gKlxuICogQHBhcmFtICB7U3RyaW5nfSBkYXRhU3RyIElucHV0IHN0cmluZ1xuICogQHJldHVybiB7QXJyYXl9ICAgICAgICAgIEFycmF5IG9mIG9iamVjdCB3aXRoIHNlZ21lbnRzIGRhdGFcbiAqL1xuZnVuY3Rpb24gZ2V0U2VnbWVudHNGcm9tU3RyaW5nIChkYXRhU3RyKSB7XG4gIHZhciBudW1TZWdzID0gZ2V0U2VnbWVudHMoUmVnZXguTlVNRVJJQywgTW9kZS5OVU1FUklDLCBkYXRhU3RyKVxuICB2YXIgYWxwaGFOdW1TZWdzID0gZ2V0U2VnbWVudHMoUmVnZXguQUxQSEFOVU1FUklDLCBNb2RlLkFMUEhBTlVNRVJJQywgZGF0YVN0cilcbiAgdmFyIGJ5dGVTZWdzXG4gIHZhciBrYW5qaVNlZ3NcblxuICBpZiAoVXRpbHMuaXNLYW5qaU1vZGVFbmFibGVkKCkpIHtcbiAgICBieXRlU2VncyA9IGdldFNlZ21lbnRzKFJlZ2V4LkJZVEUsIE1vZGUuQllURSwgZGF0YVN0cilcbiAgICBrYW5qaVNlZ3MgPSBnZXRTZWdtZW50cyhSZWdleC5LQU5KSSwgTW9kZS5LQU5KSSwgZGF0YVN0cilcbiAgfSBlbHNlIHtcbiAgICBieXRlU2VncyA9IGdldFNlZ21lbnRzKFJlZ2V4LkJZVEVfS0FOSkksIE1vZGUuQllURSwgZGF0YVN0cilcbiAgICBrYW5qaVNlZ3MgPSBbXVxuICB9XG5cbiAgdmFyIHNlZ3MgPSBudW1TZWdzLmNvbmNhdChhbHBoYU51bVNlZ3MsIGJ5dGVTZWdzLCBrYW5qaVNlZ3MpXG5cbiAgcmV0dXJuIHNlZ3NcbiAgICAuc29ydChmdW5jdGlvbiAoczEsIHMyKSB7XG4gICAgICByZXR1cm4gczEuaW5kZXggLSBzMi5pbmRleFxuICAgIH0pXG4gICAgLm1hcChmdW5jdGlvbiAob2JqKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBkYXRhOiBvYmouZGF0YSxcbiAgICAgICAgbW9kZTogb2JqLm1vZGUsXG4gICAgICAgIGxlbmd0aDogb2JqLmxlbmd0aFxuICAgICAgfVxuICAgIH0pXG59XG5cbi8qKlxuICogUmV0dXJucyBob3cgbWFueSBiaXRzIGFyZSBuZWVkZWQgdG8gZW5jb2RlIGEgc3RyaW5nIG9mXG4gKiBzcGVjaWZpZWQgbGVuZ3RoIHdpdGggdGhlIHNwZWNpZmllZCBtb2RlXG4gKlxuICogQHBhcmFtICB7TnVtYmVyfSBsZW5ndGggU3RyaW5nIGxlbmd0aFxuICogQHBhcmFtICB7TW9kZX0gbW9kZSAgICAgU2VnbWVudCBtb2RlXG4gKiBAcmV0dXJuIHtOdW1iZXJ9ICAgICAgICBCaXQgbGVuZ3RoXG4gKi9cbmZ1bmN0aW9uIGdldFNlZ21lbnRCaXRzTGVuZ3RoIChsZW5ndGgsIG1vZGUpIHtcbiAgc3dpdGNoIChtb2RlKSB7XG4gICAgY2FzZSBNb2RlLk5VTUVSSUM6XG4gICAgICByZXR1cm4gTnVtZXJpY0RhdGEuZ2V0Qml0c0xlbmd0aChsZW5ndGgpXG4gICAgY2FzZSBNb2RlLkFMUEhBTlVNRVJJQzpcbiAgICAgIHJldHVybiBBbHBoYW51bWVyaWNEYXRhLmdldEJpdHNMZW5ndGgobGVuZ3RoKVxuICAgIGNhc2UgTW9kZS5LQU5KSTpcbiAgICAgIHJldHVybiBLYW5qaURhdGEuZ2V0Qml0c0xlbmd0aChsZW5ndGgpXG4gICAgY2FzZSBNb2RlLkJZVEU6XG4gICAgICByZXR1cm4gQnl0ZURhdGEuZ2V0Qml0c0xlbmd0aChsZW5ndGgpXG4gIH1cbn1cblxuLyoqXG4gKiBNZXJnZXMgYWRqYWNlbnQgc2VnbWVudHMgd2hpY2ggaGF2ZSB0aGUgc2FtZSBtb2RlXG4gKlxuICogQHBhcmFtICB7QXJyYXl9IHNlZ3MgQXJyYXkgb2Ygb2JqZWN0IHdpdGggc2VnbWVudHMgZGF0YVxuICogQHJldHVybiB7QXJyYXl9ICAgICAgQXJyYXkgb2Ygb2JqZWN0IHdpdGggc2VnbWVudHMgZGF0YVxuICovXG5mdW5jdGlvbiBtZXJnZVNlZ21lbnRzIChzZWdzKSB7XG4gIHJldHVybiBzZWdzLnJlZHVjZShmdW5jdGlvbiAoYWNjLCBjdXJyKSB7XG4gICAgdmFyIHByZXZTZWcgPSBhY2MubGVuZ3RoIC0gMSA+PSAwID8gYWNjW2FjYy5sZW5ndGggLSAxXSA6IG51bGxcbiAgICBpZiAocHJldlNlZyAmJiBwcmV2U2VnLm1vZGUgPT09IGN1cnIubW9kZSkge1xuICAgICAgYWNjW2FjYy5sZW5ndGggLSAxXS5kYXRhICs9IGN1cnIuZGF0YVxuICAgICAgcmV0dXJuIGFjY1xuICAgIH1cblxuICAgIGFjYy5wdXNoKGN1cnIpXG4gICAgcmV0dXJuIGFjY1xuICB9LCBbXSlcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSBsaXN0IG9mIGFsbCBwb3NzaWJsZSBub2RlcyBjb21iaW5hdGlvbiB3aGljaFxuICogd2lsbCBiZSB1c2VkIHRvIGJ1aWxkIGEgc2VnbWVudHMgZ3JhcGguXG4gKlxuICogTm9kZXMgYXJlIGRpdmlkZWQgYnkgZ3JvdXBzLiBFYWNoIGdyb3VwIHdpbGwgY29udGFpbiBhIGxpc3Qgb2YgYWxsIHRoZSBtb2Rlc1xuICogaW4gd2hpY2ggaXMgcG9zc2libGUgdG8gZW5jb2RlIHRoZSBnaXZlbiB0ZXh0LlxuICpcbiAqIEZvciBleGFtcGxlIHRoZSB0ZXh0ICcxMjM0NScgY2FuIGJlIGVuY29kZWQgYXMgTnVtZXJpYywgQWxwaGFudW1lcmljIG9yIEJ5dGUuXG4gKiBUaGUgZ3JvdXAgZm9yICcxMjM0NScgd2lsbCBjb250YWluIHRoZW4gMyBvYmplY3RzLCBvbmUgZm9yIGVhY2hcbiAqIHBvc3NpYmxlIGVuY29kaW5nIG1vZGUuXG4gKlxuICogRWFjaCBub2RlIHJlcHJlc2VudHMgYSBwb3NzaWJsZSBzZWdtZW50LlxuICpcbiAqIEBwYXJhbSAge0FycmF5fSBzZWdzIEFycmF5IG9mIG9iamVjdCB3aXRoIHNlZ21lbnRzIGRhdGFcbiAqIEByZXR1cm4ge0FycmF5fSAgICAgIEFycmF5IG9mIG9iamVjdCB3aXRoIHNlZ21lbnRzIGRhdGFcbiAqL1xuZnVuY3Rpb24gYnVpbGROb2RlcyAoc2Vncykge1xuICB2YXIgbm9kZXMgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHNlZ3MubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgc2VnID0gc2Vnc1tpXVxuXG4gICAgc3dpdGNoIChzZWcubW9kZSkge1xuICAgICAgY2FzZSBNb2RlLk5VTUVSSUM6XG4gICAgICAgIG5vZGVzLnB1c2goW3NlZyxcbiAgICAgICAgICB7IGRhdGE6IHNlZy5kYXRhLCBtb2RlOiBNb2RlLkFMUEhBTlVNRVJJQywgbGVuZ3RoOiBzZWcubGVuZ3RoIH0sXG4gICAgICAgICAgeyBkYXRhOiBzZWcuZGF0YSwgbW9kZTogTW9kZS5CWVRFLCBsZW5ndGg6IHNlZy5sZW5ndGggfVxuICAgICAgICBdKVxuICAgICAgICBicmVha1xuICAgICAgY2FzZSBNb2RlLkFMUEhBTlVNRVJJQzpcbiAgICAgICAgbm9kZXMucHVzaChbc2VnLFxuICAgICAgICAgIHsgZGF0YTogc2VnLmRhdGEsIG1vZGU6IE1vZGUuQllURSwgbGVuZ3RoOiBzZWcubGVuZ3RoIH1cbiAgICAgICAgXSlcbiAgICAgICAgYnJlYWtcbiAgICAgIGNhc2UgTW9kZS5LQU5KSTpcbiAgICAgICAgbm9kZXMucHVzaChbc2VnLFxuICAgICAgICAgIHsgZGF0YTogc2VnLmRhdGEsIG1vZGU6IE1vZGUuQllURSwgbGVuZ3RoOiBnZXRTdHJpbmdCeXRlTGVuZ3RoKHNlZy5kYXRhKSB9XG4gICAgICAgIF0pXG4gICAgICAgIGJyZWFrXG4gICAgICBjYXNlIE1vZGUuQllURTpcbiAgICAgICAgbm9kZXMucHVzaChbXG4gICAgICAgICAgeyBkYXRhOiBzZWcuZGF0YSwgbW9kZTogTW9kZS5CWVRFLCBsZW5ndGg6IGdldFN0cmluZ0J5dGVMZW5ndGgoc2VnLmRhdGEpIH1cbiAgICAgICAgXSlcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbm9kZXNcbn1cblxuLyoqXG4gKiBCdWlsZHMgYSBncmFwaCBmcm9tIGEgbGlzdCBvZiBub2Rlcy5cbiAqIEFsbCBzZWdtZW50cyBpbiBlYWNoIG5vZGUgZ3JvdXAgd2lsbCBiZSBjb25uZWN0ZWQgd2l0aCBhbGwgdGhlIHNlZ21lbnRzIG9mXG4gKiB0aGUgbmV4dCBncm91cCBhbmQgc28gb24uXG4gKlxuICogQXQgZWFjaCBjb25uZWN0aW9uIHdpbGwgYmUgYXNzaWduZWQgYSB3ZWlnaHQgZGVwZW5kaW5nIG9uIHRoZVxuICogc2VnbWVudCdzIGJ5dGUgbGVuZ3RoLlxuICpcbiAqIEBwYXJhbSAge0FycmF5fSBub2RlcyAgICBBcnJheSBvZiBvYmplY3Qgd2l0aCBzZWdtZW50cyBkYXRhXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IHZlcnNpb24gUVIgQ29kZSB2ZXJzaW9uXG4gKiBAcmV0dXJuIHtPYmplY3R9ICAgICAgICAgR3JhcGggb2YgYWxsIHBvc3NpYmxlIHNlZ21lbnRzXG4gKi9cbmZ1bmN0aW9uIGJ1aWxkR3JhcGggKG5vZGVzLCB2ZXJzaW9uKSB7XG4gIHZhciB0YWJsZSA9IHt9XG4gIHZhciBncmFwaCA9IHsnc3RhcnQnOiB7fX1cbiAgdmFyIHByZXZOb2RlSWRzID0gWydzdGFydCddXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBub2RlR3JvdXAgPSBub2Rlc1tpXVxuICAgIHZhciBjdXJyZW50Tm9kZUlkcyA9IFtdXG5cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IG5vZGVHcm91cC5sZW5ndGg7IGorKykge1xuICAgICAgdmFyIG5vZGUgPSBub2RlR3JvdXBbal1cbiAgICAgIHZhciBrZXkgPSAnJyArIGkgKyBqXG5cbiAgICAgIGN1cnJlbnROb2RlSWRzLnB1c2goa2V5KVxuICAgICAgdGFibGVba2V5XSA9IHsgbm9kZTogbm9kZSwgbGFzdENvdW50OiAwIH1cbiAgICAgIGdyYXBoW2tleV0gPSB7fVxuXG4gICAgICBmb3IgKHZhciBuID0gMDsgbiA8IHByZXZOb2RlSWRzLmxlbmd0aDsgbisrKSB7XG4gICAgICAgIHZhciBwcmV2Tm9kZUlkID0gcHJldk5vZGVJZHNbbl1cblxuICAgICAgICBpZiAodGFibGVbcHJldk5vZGVJZF0gJiYgdGFibGVbcHJldk5vZGVJZF0ubm9kZS5tb2RlID09PSBub2RlLm1vZGUpIHtcbiAgICAgICAgICBncmFwaFtwcmV2Tm9kZUlkXVtrZXldID1cbiAgICAgICAgICAgIGdldFNlZ21lbnRCaXRzTGVuZ3RoKHRhYmxlW3ByZXZOb2RlSWRdLmxhc3RDb3VudCArIG5vZGUubGVuZ3RoLCBub2RlLm1vZGUpIC1cbiAgICAgICAgICAgIGdldFNlZ21lbnRCaXRzTGVuZ3RoKHRhYmxlW3ByZXZOb2RlSWRdLmxhc3RDb3VudCwgbm9kZS5tb2RlKVxuXG4gICAgICAgICAgdGFibGVbcHJldk5vZGVJZF0ubGFzdENvdW50ICs9IG5vZGUubGVuZ3RoXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKHRhYmxlW3ByZXZOb2RlSWRdKSB0YWJsZVtwcmV2Tm9kZUlkXS5sYXN0Q291bnQgPSBub2RlLmxlbmd0aFxuXG4gICAgICAgICAgZ3JhcGhbcHJldk5vZGVJZF1ba2V5XSA9IGdldFNlZ21lbnRCaXRzTGVuZ3RoKG5vZGUubGVuZ3RoLCBub2RlLm1vZGUpICtcbiAgICAgICAgICAgIDQgKyBNb2RlLmdldENoYXJDb3VudEluZGljYXRvcihub2RlLm1vZGUsIHZlcnNpb24pIC8vIHN3aXRjaCBjb3N0XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBwcmV2Tm9kZUlkcyA9IGN1cnJlbnROb2RlSWRzXG4gIH1cblxuICBmb3IgKG4gPSAwOyBuIDwgcHJldk5vZGVJZHMubGVuZ3RoOyBuKyspIHtcbiAgICBncmFwaFtwcmV2Tm9kZUlkc1tuXV1bJ2VuZCddID0gMFxuICB9XG5cbiAgcmV0dXJuIHsgbWFwOiBncmFwaCwgdGFibGU6IHRhYmxlIH1cbn1cblxuLyoqXG4gKiBCdWlsZHMgYSBzZWdtZW50IGZyb20gYSBzcGVjaWZpZWQgZGF0YSBhbmQgbW9kZS5cbiAqIElmIGEgbW9kZSBpcyBub3Qgc3BlY2lmaWVkLCB0aGUgbW9yZSBzdWl0YWJsZSB3aWxsIGJlIHVzZWQuXG4gKlxuICogQHBhcmFtICB7U3RyaW5nfSBkYXRhICAgICAgICAgICAgIElucHV0IGRhdGFcbiAqIEBwYXJhbSAge01vZGUgfCBTdHJpbmd9IG1vZGVzSGludCBEYXRhIG1vZGVcbiAqIEByZXR1cm4ge1NlZ21lbnR9ICAgICAgICAgICAgICAgICBTZWdtZW50XG4gKi9cbmZ1bmN0aW9uIGJ1aWxkU2luZ2xlU2VnbWVudCAoZGF0YSwgbW9kZXNIaW50KSB7XG4gIHZhciBtb2RlXG4gIHZhciBiZXN0TW9kZSA9IE1vZGUuZ2V0QmVzdE1vZGVGb3JEYXRhKGRhdGEpXG5cbiAgbW9kZSA9IE1vZGUuZnJvbShtb2Rlc0hpbnQsIGJlc3RNb2RlKVxuXG4gIC8vIE1ha2Ugc3VyZSBkYXRhIGNhbiBiZSBlbmNvZGVkXG4gIGlmIChtb2RlICE9PSBNb2RlLkJZVEUgJiYgbW9kZS5iaXQgPCBiZXN0TW9kZS5iaXQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1wiJyArIGRhdGEgKyAnXCInICtcbiAgICAgICcgY2Fubm90IGJlIGVuY29kZWQgd2l0aCBtb2RlICcgKyBNb2RlLnRvU3RyaW5nKG1vZGUpICtcbiAgICAgICcuXFxuIFN1Z2dlc3RlZCBtb2RlIGlzOiAnICsgTW9kZS50b1N0cmluZyhiZXN0TW9kZSkpXG4gIH1cblxuICAvLyBVc2UgTW9kZS5CWVRFIGlmIEthbmppIHN1cHBvcnQgaXMgZGlzYWJsZWRcbiAgaWYgKG1vZGUgPT09IE1vZGUuS0FOSkkgJiYgIVV0aWxzLmlzS2FuamlNb2RlRW5hYmxlZCgpKSB7XG4gICAgbW9kZSA9IE1vZGUuQllURVxuICB9XG5cbiAgc3dpdGNoIChtb2RlKSB7XG4gICAgY2FzZSBNb2RlLk5VTUVSSUM6XG4gICAgICByZXR1cm4gbmV3IE51bWVyaWNEYXRhKGRhdGEpXG5cbiAgICBjYXNlIE1vZGUuQUxQSEFOVU1FUklDOlxuICAgICAgcmV0dXJuIG5ldyBBbHBoYW51bWVyaWNEYXRhKGRhdGEpXG5cbiAgICBjYXNlIE1vZGUuS0FOSkk6XG4gICAgICByZXR1cm4gbmV3IEthbmppRGF0YShkYXRhKVxuXG4gICAgY2FzZSBNb2RlLkJZVEU6XG4gICAgICByZXR1cm4gbmV3IEJ5dGVEYXRhKGRhdGEpXG4gIH1cbn1cblxuLyoqXG4gKiBCdWlsZHMgYSBsaXN0IG9mIHNlZ21lbnRzIGZyb20gYW4gYXJyYXkuXG4gKiBBcnJheSBjYW4gY29udGFpbiBTdHJpbmdzIG9yIE9iamVjdHMgd2l0aCBzZWdtZW50J3MgaW5mby5cbiAqXG4gKiBGb3IgZWFjaCBpdGVtIHdoaWNoIGlzIGEgc3RyaW5nLCB3aWxsIGJlIGdlbmVyYXRlZCBhIHNlZ21lbnQgd2l0aCB0aGUgZ2l2ZW5cbiAqIHN0cmluZyBhbmQgdGhlIG1vcmUgYXBwcm9wcmlhdGUgZW5jb2RpbmcgbW9kZS5cbiAqXG4gKiBGb3IgZWFjaCBpdGVtIHdoaWNoIGlzIGFuIG9iamVjdCwgd2lsbCBiZSBnZW5lcmF0ZWQgYSBzZWdtZW50IHdpdGggdGhlIGdpdmVuXG4gKiBkYXRhIGFuZCBtb2RlLlxuICogT2JqZWN0cyBtdXN0IGNvbnRhaW4gYXQgbGVhc3QgdGhlIHByb3BlcnR5IFwiZGF0YVwiLlxuICogSWYgcHJvcGVydHkgXCJtb2RlXCIgaXMgbm90IHByZXNlbnQsIHRoZSBtb3JlIHN1aXRhYmxlIG1vZGUgd2lsbCBiZSB1c2VkLlxuICpcbiAqIEBwYXJhbSAge0FycmF5fSBhcnJheSBBcnJheSBvZiBvYmplY3RzIHdpdGggc2VnbWVudHMgZGF0YVxuICogQHJldHVybiB7QXJyYXl9ICAgICAgIEFycmF5IG9mIFNlZ21lbnRzXG4gKi9cbmV4cG9ydHMuZnJvbUFycmF5ID0gZnVuY3Rpb24gZnJvbUFycmF5IChhcnJheSkge1xuICByZXR1cm4gYXJyYXkucmVkdWNlKGZ1bmN0aW9uIChhY2MsIHNlZykge1xuICAgIGlmICh0eXBlb2Ygc2VnID09PSAnc3RyaW5nJykge1xuICAgICAgYWNjLnB1c2goYnVpbGRTaW5nbGVTZWdtZW50KHNlZywgbnVsbCkpXG4gICAgfSBlbHNlIGlmIChzZWcuZGF0YSkge1xuICAgICAgYWNjLnB1c2goYnVpbGRTaW5nbGVTZWdtZW50KHNlZy5kYXRhLCBzZWcubW9kZSkpXG4gICAgfVxuXG4gICAgcmV0dXJuIGFjY1xuICB9LCBbXSlcbn1cblxuLyoqXG4gKiBCdWlsZHMgYW4gb3B0aW1pemVkIHNlcXVlbmNlIG9mIHNlZ21lbnRzIGZyb20gYSBzdHJpbmcsXG4gKiB3aGljaCB3aWxsIHByb2R1Y2UgdGhlIHNob3J0ZXN0IHBvc3NpYmxlIGJpdHN0cmVhbS5cbiAqXG4gKiBAcGFyYW0gIHtTdHJpbmd9IGRhdGEgICAgSW5wdXQgc3RyaW5nXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IHZlcnNpb24gUVIgQ29kZSB2ZXJzaW9uXG4gKiBAcmV0dXJuIHtBcnJheX0gICAgICAgICAgQXJyYXkgb2Ygc2VnbWVudHNcbiAqL1xuZXhwb3J0cy5mcm9tU3RyaW5nID0gZnVuY3Rpb24gZnJvbVN0cmluZyAoZGF0YSwgdmVyc2lvbikge1xuICB2YXIgc2VncyA9IGdldFNlZ21lbnRzRnJvbVN0cmluZyhkYXRhLCBVdGlscy5pc0thbmppTW9kZUVuYWJsZWQoKSlcblxuICB2YXIgbm9kZXMgPSBidWlsZE5vZGVzKHNlZ3MpXG4gIHZhciBncmFwaCA9IGJ1aWxkR3JhcGgobm9kZXMsIHZlcnNpb24pXG4gIHZhciBwYXRoID0gZGlqa3N0cmEuZmluZF9wYXRoKGdyYXBoLm1hcCwgJ3N0YXJ0JywgJ2VuZCcpXG5cbiAgdmFyIG9wdGltaXplZFNlZ3MgPSBbXVxuICBmb3IgKHZhciBpID0gMTsgaSA8IHBhdGgubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgb3B0aW1pemVkU2Vncy5wdXNoKGdyYXBoLnRhYmxlW3BhdGhbaV1dLm5vZGUpXG4gIH1cblxuICByZXR1cm4gZXhwb3J0cy5mcm9tQXJyYXkobWVyZ2VTZWdtZW50cyhvcHRpbWl6ZWRTZWdzKSlcbn1cblxuLyoqXG4gKiBTcGxpdHMgYSBzdHJpbmcgaW4gdmFyaW91cyBzZWdtZW50cyB3aXRoIHRoZSBtb2RlcyB3aGljaFxuICogYmVzdCByZXByZXNlbnQgdGhlaXIgY29udGVudC5cbiAqIFRoZSBwcm9kdWNlZCBzZWdtZW50cyBhcmUgZmFyIGZyb20gYmVpbmcgb3B0aW1pemVkLlxuICogVGhlIG91dHB1dCBvZiB0aGlzIGZ1bmN0aW9uIGlzIG9ubHkgdXNlZCB0byBlc3RpbWF0ZSBhIFFSIENvZGUgdmVyc2lvblxuICogd2hpY2ggbWF5IGNvbnRhaW4gdGhlIGRhdGEuXG4gKlxuICogQHBhcmFtICB7c3RyaW5nfSBkYXRhIElucHV0IHN0cmluZ1xuICogQHJldHVybiB7QXJyYXl9ICAgICAgIEFycmF5IG9mIHNlZ21lbnRzXG4gKi9cbmV4cG9ydHMucmF3U3BsaXQgPSBmdW5jdGlvbiByYXdTcGxpdCAoZGF0YSkge1xuICByZXR1cm4gZXhwb3J0cy5mcm9tQXJyYXkoXG4gICAgZ2V0U2VnbWVudHNGcm9tU3RyaW5nKGRhdGEsIFV0aWxzLmlzS2FuamlNb2RlRW5hYmxlZCgpKVxuICApXG59XG4iLCJ2YXIgdG9TSklTRnVuY3Rpb25cbnZhciBDT0RFV09SRFNfQ09VTlQgPSBbXG4gIDAsIC8vIE5vdCB1c2VkXG4gIDI2LCA0NCwgNzAsIDEwMCwgMTM0LCAxNzIsIDE5NiwgMjQyLCAyOTIsIDM0NixcbiAgNDA0LCA0NjYsIDUzMiwgNTgxLCA2NTUsIDczMywgODE1LCA5MDEsIDk5MSwgMTA4NSxcbiAgMTE1NiwgMTI1OCwgMTM2NCwgMTQ3NCwgMTU4OCwgMTcwNiwgMTgyOCwgMTkyMSwgMjA1MSwgMjE4NSxcbiAgMjMyMywgMjQ2NSwgMjYxMSwgMjc2MSwgMjg3NiwgMzAzNCwgMzE5NiwgMzM2MiwgMzUzMiwgMzcwNlxuXVxuXG4vKipcbiAqIFJldHVybnMgdGhlIFFSIENvZGUgc2l6ZSBmb3IgdGhlIHNwZWNpZmllZCB2ZXJzaW9uXG4gKlxuICogQHBhcmFtICB7TnVtYmVyfSB2ZXJzaW9uIFFSIENvZGUgdmVyc2lvblxuICogQHJldHVybiB7TnVtYmVyfSAgICAgICAgIHNpemUgb2YgUVIgY29kZVxuICovXG5leHBvcnRzLmdldFN5bWJvbFNpemUgPSBmdW5jdGlvbiBnZXRTeW1ib2xTaXplICh2ZXJzaW9uKSB7XG4gIGlmICghdmVyc2lvbikgdGhyb3cgbmV3IEVycm9yKCdcInZlcnNpb25cIiBjYW5ub3QgYmUgbnVsbCBvciB1bmRlZmluZWQnKVxuICBpZiAodmVyc2lvbiA8IDEgfHwgdmVyc2lvbiA+IDQwKSB0aHJvdyBuZXcgRXJyb3IoJ1widmVyc2lvblwiIHNob3VsZCBiZSBpbiByYW5nZSBmcm9tIDEgdG8gNDAnKVxuICByZXR1cm4gdmVyc2lvbiAqIDQgKyAxN1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHRvdGFsIG51bWJlciBvZiBjb2Rld29yZHMgdXNlZCB0byBzdG9yZSBkYXRhIGFuZCBFQyBpbmZvcm1hdGlvbi5cbiAqXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IHZlcnNpb24gUVIgQ29kZSB2ZXJzaW9uXG4gKiBAcmV0dXJuIHtOdW1iZXJ9ICAgICAgICAgRGF0YSBsZW5ndGggaW4gYml0c1xuICovXG5leHBvcnRzLmdldFN5bWJvbFRvdGFsQ29kZXdvcmRzID0gZnVuY3Rpb24gZ2V0U3ltYm9sVG90YWxDb2Rld29yZHMgKHZlcnNpb24pIHtcbiAgcmV0dXJuIENPREVXT1JEU19DT1VOVFt2ZXJzaW9uXVxufVxuXG4vKipcbiAqIEVuY29kZSBkYXRhIHdpdGggQm9zZS1DaGF1ZGh1cmktSG9jcXVlbmdoZW1cbiAqXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IGRhdGEgVmFsdWUgdG8gZW5jb2RlXG4gKiBAcmV0dXJuIHtOdW1iZXJ9ICAgICAgRW5jb2RlZCB2YWx1ZVxuICovXG5leHBvcnRzLmdldEJDSERpZ2l0ID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgdmFyIGRpZ2l0ID0gMFxuXG4gIHdoaWxlIChkYXRhICE9PSAwKSB7XG4gICAgZGlnaXQrK1xuICAgIGRhdGEgPj4+PSAxXG4gIH1cblxuICByZXR1cm4gZGlnaXRcbn1cblxuZXhwb3J0cy5zZXRUb1NKSVNGdW5jdGlvbiA9IGZ1bmN0aW9uIHNldFRvU0pJU0Z1bmN0aW9uIChmKSB7XG4gIGlmICh0eXBlb2YgZiAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBFcnJvcignXCJ0b1NKSVNGdW5jXCIgaXMgbm90IGEgdmFsaWQgZnVuY3Rpb24uJylcbiAgfVxuXG4gIHRvU0pJU0Z1bmN0aW9uID0gZlxufVxuXG5leHBvcnRzLmlzS2FuamlNb2RlRW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHR5cGVvZiB0b1NKSVNGdW5jdGlvbiAhPT0gJ3VuZGVmaW5lZCdcbn1cblxuZXhwb3J0cy50b1NKSVMgPSBmdW5jdGlvbiB0b1NKSVMgKGthbmppKSB7XG4gIHJldHVybiB0b1NKSVNGdW5jdGlvbihrYW5qaSlcbn1cbiIsIi8qKlxuICogQ2hlY2sgaWYgUVIgQ29kZSB2ZXJzaW9uIGlzIHZhbGlkXG4gKlxuICogQHBhcmFtICB7TnVtYmVyfSAgdmVyc2lvbiBRUiBDb2RlIHZlcnNpb25cbiAqIEByZXR1cm4ge0Jvb2xlYW59ICAgICAgICAgdHJ1ZSBpZiB2YWxpZCB2ZXJzaW9uLCBmYWxzZSBvdGhlcndpc2VcbiAqL1xuZXhwb3J0cy5pc1ZhbGlkID0gZnVuY3Rpb24gaXNWYWxpZCAodmVyc2lvbikge1xuICByZXR1cm4gIWlzTmFOKHZlcnNpb24pICYmIHZlcnNpb24gPj0gMSAmJiB2ZXJzaW9uIDw9IDQwXG59XG4iLCJ2YXIgVXRpbHMgPSByZXF1aXJlKCcuL3V0aWxzJylcbnZhciBFQ0NvZGUgPSByZXF1aXJlKCcuL2Vycm9yLWNvcnJlY3Rpb24tY29kZScpXG52YXIgRUNMZXZlbCA9IHJlcXVpcmUoJy4vZXJyb3ItY29ycmVjdGlvbi1sZXZlbCcpXG52YXIgTW9kZSA9IHJlcXVpcmUoJy4vbW9kZScpXG52YXIgVmVyc2lvbkNoZWNrID0gcmVxdWlyZSgnLi92ZXJzaW9uLWNoZWNrJylcbnZhciBpc0FycmF5ID0gcmVxdWlyZSgnaXNhcnJheScpXG5cbi8vIEdlbmVyYXRvciBwb2x5bm9taWFsIHVzZWQgdG8gZW5jb2RlIHZlcnNpb24gaW5mb3JtYXRpb25cbnZhciBHMTggPSAoMSA8PCAxMikgfCAoMSA8PCAxMSkgfCAoMSA8PCAxMCkgfCAoMSA8PCA5KSB8ICgxIDw8IDgpIHwgKDEgPDwgNSkgfCAoMSA8PCAyKSB8ICgxIDw8IDApXG52YXIgRzE4X0JDSCA9IFV0aWxzLmdldEJDSERpZ2l0KEcxOClcblxuZnVuY3Rpb24gZ2V0QmVzdFZlcnNpb25Gb3JEYXRhTGVuZ3RoIChtb2RlLCBsZW5ndGgsIGVycm9yQ29ycmVjdGlvbkxldmVsKSB7XG4gIGZvciAodmFyIGN1cnJlbnRWZXJzaW9uID0gMTsgY3VycmVudFZlcnNpb24gPD0gNDA7IGN1cnJlbnRWZXJzaW9uKyspIHtcbiAgICBpZiAobGVuZ3RoIDw9IGV4cG9ydHMuZ2V0Q2FwYWNpdHkoY3VycmVudFZlcnNpb24sIGVycm9yQ29ycmVjdGlvbkxldmVsLCBtb2RlKSkge1xuICAgICAgcmV0dXJuIGN1cnJlbnRWZXJzaW9uXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHVuZGVmaW5lZFxufVxuXG5mdW5jdGlvbiBnZXRSZXNlcnZlZEJpdHNDb3VudCAobW9kZSwgdmVyc2lvbikge1xuICAvLyBDaGFyYWN0ZXIgY291bnQgaW5kaWNhdG9yICsgbW9kZSBpbmRpY2F0b3IgYml0c1xuICByZXR1cm4gTW9kZS5nZXRDaGFyQ291bnRJbmRpY2F0b3IobW9kZSwgdmVyc2lvbikgKyA0XG59XG5cbmZ1bmN0aW9uIGdldFRvdGFsQml0c0Zyb21EYXRhQXJyYXkgKHNlZ21lbnRzLCB2ZXJzaW9uKSB7XG4gIHZhciB0b3RhbEJpdHMgPSAwXG5cbiAgc2VnbWVudHMuZm9yRWFjaChmdW5jdGlvbiAoZGF0YSkge1xuICAgIHZhciByZXNlcnZlZEJpdHMgPSBnZXRSZXNlcnZlZEJpdHNDb3VudChkYXRhLm1vZGUsIHZlcnNpb24pXG4gICAgdG90YWxCaXRzICs9IHJlc2VydmVkQml0cyArIGRhdGEuZ2V0Qml0c0xlbmd0aCgpXG4gIH0pXG5cbiAgcmV0dXJuIHRvdGFsQml0c1xufVxuXG5mdW5jdGlvbiBnZXRCZXN0VmVyc2lvbkZvck1peGVkRGF0YSAoc2VnbWVudHMsIGVycm9yQ29ycmVjdGlvbkxldmVsKSB7XG4gIGZvciAodmFyIGN1cnJlbnRWZXJzaW9uID0gMTsgY3VycmVudFZlcnNpb24gPD0gNDA7IGN1cnJlbnRWZXJzaW9uKyspIHtcbiAgICB2YXIgbGVuZ3RoID0gZ2V0VG90YWxCaXRzRnJvbURhdGFBcnJheShzZWdtZW50cywgY3VycmVudFZlcnNpb24pXG4gICAgaWYgKGxlbmd0aCA8PSBleHBvcnRzLmdldENhcGFjaXR5KGN1cnJlbnRWZXJzaW9uLCBlcnJvckNvcnJlY3Rpb25MZXZlbCwgTW9kZS5NSVhFRCkpIHtcbiAgICAgIHJldHVybiBjdXJyZW50VmVyc2lvblxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB1bmRlZmluZWRcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHZlcnNpb24gbnVtYmVyIGZyb20gYSB2YWx1ZS5cbiAqIElmIHZhbHVlIGlzIG5vdCBhIHZhbGlkIHZlcnNpb24sIHJldHVybnMgZGVmYXVsdFZhbHVlXG4gKlxuICogQHBhcmFtICB7TnVtYmVyfFN0cmluZ30gdmFsdWUgICAgICAgIFFSIENvZGUgdmVyc2lvblxuICogQHBhcmFtICB7TnVtYmVyfSAgICAgICAgZGVmYXVsdFZhbHVlIEZhbGxiYWNrIHZhbHVlXG4gKiBAcmV0dXJuIHtOdW1iZXJ9ICAgICAgICAgICAgICAgICAgICAgUVIgQ29kZSB2ZXJzaW9uIG51bWJlclxuICovXG5leHBvcnRzLmZyb20gPSBmdW5jdGlvbiBmcm9tICh2YWx1ZSwgZGVmYXVsdFZhbHVlKSB7XG4gIGlmIChWZXJzaW9uQ2hlY2suaXNWYWxpZCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gcGFyc2VJbnQodmFsdWUsIDEwKVxuICB9XG5cbiAgcmV0dXJuIGRlZmF1bHRWYWx1ZVxufVxuXG4vKipcbiAqIFJldHVybnMgaG93IG11Y2ggZGF0YSBjYW4gYmUgc3RvcmVkIHdpdGggdGhlIHNwZWNpZmllZCBRUiBjb2RlIHZlcnNpb25cbiAqIGFuZCBlcnJvciBjb3JyZWN0aW9uIGxldmVsXG4gKlxuICogQHBhcmFtICB7TnVtYmVyfSB2ZXJzaW9uICAgICAgICAgICAgICBRUiBDb2RlIHZlcnNpb24gKDEtNDApXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IGVycm9yQ29ycmVjdGlvbkxldmVsIEVycm9yIGNvcnJlY3Rpb24gbGV2ZWxcbiAqIEBwYXJhbSAge01vZGV9ICAgbW9kZSAgICAgICAgICAgICAgICAgRGF0YSBtb2RlXG4gKiBAcmV0dXJuIHtOdW1iZXJ9ICAgICAgICAgICAgICAgICAgICAgIFF1YW50aXR5IG9mIHN0b3JhYmxlIGRhdGFcbiAqL1xuZXhwb3J0cy5nZXRDYXBhY2l0eSA9IGZ1bmN0aW9uIGdldENhcGFjaXR5ICh2ZXJzaW9uLCBlcnJvckNvcnJlY3Rpb25MZXZlbCwgbW9kZSkge1xuICBpZiAoIVZlcnNpb25DaGVjay5pc1ZhbGlkKHZlcnNpb24pKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIFFSIENvZGUgdmVyc2lvbicpXG4gIH1cblxuICAvLyBVc2UgQnl0ZSBtb2RlIGFzIGRlZmF1bHRcbiAgaWYgKHR5cGVvZiBtb2RlID09PSAndW5kZWZpbmVkJykgbW9kZSA9IE1vZGUuQllURVxuXG4gIC8vIFRvdGFsIGNvZGV3b3JkcyBmb3IgdGhpcyBRUiBjb2RlIHZlcnNpb24gKERhdGEgKyBFcnJvciBjb3JyZWN0aW9uKVxuICB2YXIgdG90YWxDb2Rld29yZHMgPSBVdGlscy5nZXRTeW1ib2xUb3RhbENvZGV3b3Jkcyh2ZXJzaW9uKVxuXG4gIC8vIFRvdGFsIG51bWJlciBvZiBlcnJvciBjb3JyZWN0aW9uIGNvZGV3b3Jkc1xuICB2YXIgZWNUb3RhbENvZGV3b3JkcyA9IEVDQ29kZS5nZXRUb3RhbENvZGV3b3Jkc0NvdW50KHZlcnNpb24sIGVycm9yQ29ycmVjdGlvbkxldmVsKVxuXG4gIC8vIFRvdGFsIG51bWJlciBvZiBkYXRhIGNvZGV3b3Jkc1xuICB2YXIgZGF0YVRvdGFsQ29kZXdvcmRzQml0cyA9ICh0b3RhbENvZGV3b3JkcyAtIGVjVG90YWxDb2Rld29yZHMpICogOFxuXG4gIGlmIChtb2RlID09PSBNb2RlLk1JWEVEKSByZXR1cm4gZGF0YVRvdGFsQ29kZXdvcmRzQml0c1xuXG4gIHZhciB1c2FibGVCaXRzID0gZGF0YVRvdGFsQ29kZXdvcmRzQml0cyAtIGdldFJlc2VydmVkQml0c0NvdW50KG1vZGUsIHZlcnNpb24pXG5cbiAgLy8gUmV0dXJuIG1heCBudW1iZXIgb2Ygc3RvcmFibGUgY29kZXdvcmRzXG4gIHN3aXRjaCAobW9kZSkge1xuICAgIGNhc2UgTW9kZS5OVU1FUklDOlxuICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKHVzYWJsZUJpdHMgLyAxMCkgKiAzKVxuXG4gICAgY2FzZSBNb2RlLkFMUEhBTlVNRVJJQzpcbiAgICAgIHJldHVybiBNYXRoLmZsb29yKCh1c2FibGVCaXRzIC8gMTEpICogMilcblxuICAgIGNhc2UgTW9kZS5LQU5KSTpcbiAgICAgIHJldHVybiBNYXRoLmZsb29yKHVzYWJsZUJpdHMgLyAxMylcblxuICAgIGNhc2UgTW9kZS5CWVRFOlxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gTWF0aC5mbG9vcih1c2FibGVCaXRzIC8gOClcbiAgfVxufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIG1pbmltdW0gdmVyc2lvbiBuZWVkZWQgdG8gY29udGFpbiB0aGUgYW1vdW50IG9mIGRhdGFcbiAqXG4gKiBAcGFyYW0gIHtTZWdtZW50fSBkYXRhICAgICAgICAgICAgICAgICAgICBTZWdtZW50IG9mIGRhdGFcbiAqIEBwYXJhbSAge051bWJlcn0gW2Vycm9yQ29ycmVjdGlvbkxldmVsPUhdIEVycm9yIGNvcnJlY3Rpb24gbGV2ZWxcbiAqIEBwYXJhbSAge01vZGV9IG1vZGUgICAgICAgICAgICAgICAgICAgICAgIERhdGEgbW9kZVxuICogQHJldHVybiB7TnVtYmVyfSAgICAgICAgICAgICAgICAgICAgICAgICAgUVIgQ29kZSB2ZXJzaW9uXG4gKi9cbmV4cG9ydHMuZ2V0QmVzdFZlcnNpb25Gb3JEYXRhID0gZnVuY3Rpb24gZ2V0QmVzdFZlcnNpb25Gb3JEYXRhIChkYXRhLCBlcnJvckNvcnJlY3Rpb25MZXZlbCkge1xuICB2YXIgc2VnXG5cbiAgdmFyIGVjbCA9IEVDTGV2ZWwuZnJvbShlcnJvckNvcnJlY3Rpb25MZXZlbCwgRUNMZXZlbC5NKVxuXG4gIGlmIChpc0FycmF5KGRhdGEpKSB7XG4gICAgaWYgKGRhdGEubGVuZ3RoID4gMSkge1xuICAgICAgcmV0dXJuIGdldEJlc3RWZXJzaW9uRm9yTWl4ZWREYXRhKGRhdGEsIGVjbClcbiAgICB9XG5cbiAgICBpZiAoZGF0YS5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiAxXG4gICAgfVxuXG4gICAgc2VnID0gZGF0YVswXVxuICB9IGVsc2Uge1xuICAgIHNlZyA9IGRhdGFcbiAgfVxuXG4gIHJldHVybiBnZXRCZXN0VmVyc2lvbkZvckRhdGFMZW5ndGgoc2VnLm1vZGUsIHNlZy5nZXRMZW5ndGgoKSwgZWNsKVxufVxuXG4vKipcbiAqIFJldHVybnMgdmVyc2lvbiBpbmZvcm1hdGlvbiB3aXRoIHJlbGF0aXZlIGVycm9yIGNvcnJlY3Rpb24gYml0c1xuICpcbiAqIFRoZSB2ZXJzaW9uIGluZm9ybWF0aW9uIGlzIGluY2x1ZGVkIGluIFFSIENvZGUgc3ltYm9scyBvZiB2ZXJzaW9uIDcgb3IgbGFyZ2VyLlxuICogSXQgY29uc2lzdHMgb2YgYW4gMTgtYml0IHNlcXVlbmNlIGNvbnRhaW5pbmcgNiBkYXRhIGJpdHMsXG4gKiB3aXRoIDEyIGVycm9yIGNvcnJlY3Rpb24gYml0cyBjYWxjdWxhdGVkIHVzaW5nIHRoZSAoMTgsIDYpIEdvbGF5IGNvZGUuXG4gKlxuICogQHBhcmFtICB7TnVtYmVyfSB2ZXJzaW9uIFFSIENvZGUgdmVyc2lvblxuICogQHJldHVybiB7TnVtYmVyfSAgICAgICAgIEVuY29kZWQgdmVyc2lvbiBpbmZvIGJpdHNcbiAqL1xuZXhwb3J0cy5nZXRFbmNvZGVkQml0cyA9IGZ1bmN0aW9uIGdldEVuY29kZWRCaXRzICh2ZXJzaW9uKSB7XG4gIGlmICghVmVyc2lvbkNoZWNrLmlzVmFsaWQodmVyc2lvbikgfHwgdmVyc2lvbiA8IDcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgUVIgQ29kZSB2ZXJzaW9uJylcbiAgfVxuXG4gIHZhciBkID0gdmVyc2lvbiA8PCAxMlxuXG4gIHdoaWxlIChVdGlscy5nZXRCQ0hEaWdpdChkKSAtIEcxOF9CQ0ggPj0gMCkge1xuICAgIGQgXj0gKEcxOCA8PCAoVXRpbHMuZ2V0QkNIRGlnaXQoZCkgLSBHMThfQkNIKSlcbiAgfVxuXG4gIHJldHVybiAodmVyc2lvbiA8PCAxMikgfCBkXG59XG4iLCJcbnZhciBjYW5Qcm9taXNlID0gcmVxdWlyZSgnLi9jYW4tcHJvbWlzZScpXG5cbnZhciBRUkNvZGUgPSByZXF1aXJlKCcuL2NvcmUvcXJjb2RlJylcbnZhciBDYW52YXNSZW5kZXJlciA9IHJlcXVpcmUoJy4vcmVuZGVyZXIvY2FudmFzJylcbnZhciBTdmdSZW5kZXJlciA9IHJlcXVpcmUoJy4vcmVuZGVyZXIvc3ZnLXRhZy5qcycpXG5cbmZ1bmN0aW9uIHJlbmRlckNhbnZhcyAocmVuZGVyRnVuYywgY2FudmFzLCB0ZXh0LCBvcHRzLCBjYikge1xuICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKVxuICB2YXIgYXJnc051bSA9IGFyZ3MubGVuZ3RoXG4gIHZhciBpc0xhc3RBcmdDYiA9IHR5cGVvZiBhcmdzW2FyZ3NOdW0gLSAxXSA9PT0gJ2Z1bmN0aW9uJ1xuXG4gIGlmICghaXNMYXN0QXJnQ2IgJiYgIWNhblByb21pc2UoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2FsbGJhY2sgcmVxdWlyZWQgYXMgbGFzdCBhcmd1bWVudCcpXG4gIH1cblxuICBpZiAoaXNMYXN0QXJnQ2IpIHtcbiAgICBpZiAoYXJnc051bSA8IDIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVG9vIGZldyBhcmd1bWVudHMgcHJvdmlkZWQnKVxuICAgIH1cblxuICAgIGlmIChhcmdzTnVtID09PSAyKSB7XG4gICAgICBjYiA9IHRleHRcbiAgICAgIHRleHQgPSBjYW52YXNcbiAgICAgIGNhbnZhcyA9IG9wdHMgPSB1bmRlZmluZWRcbiAgICB9IGVsc2UgaWYgKGFyZ3NOdW0gPT09IDMpIHtcbiAgICAgIGlmIChjYW52YXMuZ2V0Q29udGV4dCAmJiB0eXBlb2YgY2IgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGNiID0gb3B0c1xuICAgICAgICBvcHRzID0gdW5kZWZpbmVkXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjYiA9IG9wdHNcbiAgICAgICAgb3B0cyA9IHRleHRcbiAgICAgICAgdGV4dCA9IGNhbnZhc1xuICAgICAgICBjYW52YXMgPSB1bmRlZmluZWRcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKGFyZ3NOdW0gPCAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RvbyBmZXcgYXJndW1lbnRzIHByb3ZpZGVkJylcbiAgICB9XG5cbiAgICBpZiAoYXJnc051bSA9PT0gMSkge1xuICAgICAgdGV4dCA9IGNhbnZhc1xuICAgICAgY2FudmFzID0gb3B0cyA9IHVuZGVmaW5lZFxuICAgIH0gZWxzZSBpZiAoYXJnc051bSA9PT0gMiAmJiAhY2FudmFzLmdldENvbnRleHQpIHtcbiAgICAgIG9wdHMgPSB0ZXh0XG4gICAgICB0ZXh0ID0gY2FudmFzXG4gICAgICBjYW52YXMgPSB1bmRlZmluZWRcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdmFyIGRhdGEgPSBRUkNvZGUuY3JlYXRlKHRleHQsIG9wdHMpXG4gICAgICAgIHJlc29sdmUocmVuZGVyRnVuYyhkYXRhLCBjYW52YXMsIG9wdHMpKVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZWplY3QoZSlcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgdHJ5IHtcbiAgICB2YXIgZGF0YSA9IFFSQ29kZS5jcmVhdGUodGV4dCwgb3B0cylcbiAgICBjYihudWxsLCByZW5kZXJGdW5jKGRhdGEsIGNhbnZhcywgb3B0cykpXG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBjYihlKVxuICB9XG59XG5cbmV4cG9ydHMuY3JlYXRlID0gUVJDb2RlLmNyZWF0ZVxuZXhwb3J0cy50b0NhbnZhcyA9IHJlbmRlckNhbnZhcy5iaW5kKG51bGwsIENhbnZhc1JlbmRlcmVyLnJlbmRlcilcbmV4cG9ydHMudG9EYXRhVVJMID0gcmVuZGVyQ2FudmFzLmJpbmQobnVsbCwgQ2FudmFzUmVuZGVyZXIucmVuZGVyVG9EYXRhVVJMKVxuXG4vLyBvbmx5IHN2ZyBmb3Igbm93LlxuZXhwb3J0cy50b1N0cmluZyA9IHJlbmRlckNhbnZhcy5iaW5kKG51bGwsIGZ1bmN0aW9uIChkYXRhLCBfLCBvcHRzKSB7XG4gIHJldHVybiBTdmdSZW5kZXJlci5yZW5kZXIoZGF0YSwgb3B0cylcbn0pXG4iLCJ2YXIgVXRpbHMgPSByZXF1aXJlKCcuL3V0aWxzJylcblxuZnVuY3Rpb24gY2xlYXJDYW52YXMgKGN0eCwgY2FudmFzLCBzaXplKSB7XG4gIGN0eC5jbGVhclJlY3QoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KVxuXG4gIGlmICghY2FudmFzLnN0eWxlKSBjYW52YXMuc3R5bGUgPSB7fVxuICBjYW52YXMuaGVpZ2h0ID0gc2l6ZVxuICBjYW52YXMud2lkdGggPSBzaXplXG4gIGNhbnZhcy5zdHlsZS5oZWlnaHQgPSBzaXplICsgJ3B4J1xuICBjYW52YXMuc3R5bGUud2lkdGggPSBzaXplICsgJ3B4J1xufVxuXG5mdW5jdGlvbiBnZXRDYW52YXNFbGVtZW50ICgpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJylcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignWW91IG5lZWQgdG8gc3BlY2lmeSBhIGNhbnZhcyBlbGVtZW50JylcbiAgfVxufVxuXG5leHBvcnRzLnJlbmRlciA9IGZ1bmN0aW9uIHJlbmRlciAocXJEYXRhLCBjYW52YXMsIG9wdGlvbnMpIHtcbiAgdmFyIG9wdHMgPSBvcHRpb25zXG4gIHZhciBjYW52YXNFbCA9IGNhbnZhc1xuXG4gIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ3VuZGVmaW5lZCcgJiYgKCFjYW52YXMgfHwgIWNhbnZhcy5nZXRDb250ZXh0KSkge1xuICAgIG9wdHMgPSBjYW52YXNcbiAgICBjYW52YXMgPSB1bmRlZmluZWRcbiAgfVxuXG4gIGlmICghY2FudmFzKSB7XG4gICAgY2FudmFzRWwgPSBnZXRDYW52YXNFbGVtZW50KClcbiAgfVxuXG4gIG9wdHMgPSBVdGlscy5nZXRPcHRpb25zKG9wdHMpXG4gIHZhciBzaXplID0gVXRpbHMuZ2V0SW1hZ2VXaWR0aChxckRhdGEubW9kdWxlcy5zaXplLCBvcHRzKVxuXG4gIHZhciBjdHggPSBjYW52YXNFbC5nZXRDb250ZXh0KCcyZCcpXG4gIHZhciBpbWFnZSA9IGN0eC5jcmVhdGVJbWFnZURhdGEoc2l6ZSwgc2l6ZSlcbiAgVXRpbHMucXJUb0ltYWdlRGF0YShpbWFnZS5kYXRhLCBxckRhdGEsIG9wdHMpXG5cbiAgY2xlYXJDYW52YXMoY3R4LCBjYW52YXNFbCwgc2l6ZSlcbiAgY3R4LnB1dEltYWdlRGF0YShpbWFnZSwgMCwgMClcblxuICByZXR1cm4gY2FudmFzRWxcbn1cblxuZXhwb3J0cy5yZW5kZXJUb0RhdGFVUkwgPSBmdW5jdGlvbiByZW5kZXJUb0RhdGFVUkwgKHFyRGF0YSwgY2FudmFzLCBvcHRpb25zKSB7XG4gIHZhciBvcHRzID0gb3B0aW9uc1xuXG4gIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ3VuZGVmaW5lZCcgJiYgKCFjYW52YXMgfHwgIWNhbnZhcy5nZXRDb250ZXh0KSkge1xuICAgIG9wdHMgPSBjYW52YXNcbiAgICBjYW52YXMgPSB1bmRlZmluZWRcbiAgfVxuXG4gIGlmICghb3B0cykgb3B0cyA9IHt9XG5cbiAgdmFyIGNhbnZhc0VsID0gZXhwb3J0cy5yZW5kZXIocXJEYXRhLCBjYW52YXMsIG9wdHMpXG5cbiAgdmFyIHR5cGUgPSBvcHRzLnR5cGUgfHwgJ2ltYWdlL3BuZydcbiAgdmFyIHJlbmRlcmVyT3B0cyA9IG9wdHMucmVuZGVyZXJPcHRzIHx8IHt9XG5cbiAgcmV0dXJuIGNhbnZhc0VsLnRvRGF0YVVSTCh0eXBlLCByZW5kZXJlck9wdHMucXVhbGl0eSlcbn1cbiIsInZhciBVdGlscyA9IHJlcXVpcmUoJy4vdXRpbHMnKVxuXG5mdW5jdGlvbiBnZXRDb2xvckF0dHJpYiAoY29sb3IsIGF0dHJpYikge1xuICB2YXIgYWxwaGEgPSBjb2xvci5hIC8gMjU1XG4gIHZhciBzdHIgPSBhdHRyaWIgKyAnPVwiJyArIGNvbG9yLmhleCArICdcIidcblxuICByZXR1cm4gYWxwaGEgPCAxXG4gICAgPyBzdHIgKyAnICcgKyBhdHRyaWIgKyAnLW9wYWNpdHk9XCInICsgYWxwaGEudG9GaXhlZCgyKS5zbGljZSgxKSArICdcIidcbiAgICA6IHN0clxufVxuXG5mdW5jdGlvbiBzdmdDbWQgKGNtZCwgeCwgeSkge1xuICB2YXIgc3RyID0gY21kICsgeFxuICBpZiAodHlwZW9mIHkgIT09ICd1bmRlZmluZWQnKSBzdHIgKz0gJyAnICsgeVxuXG4gIHJldHVybiBzdHJcbn1cblxuZnVuY3Rpb24gcXJUb1BhdGggKGRhdGEsIHNpemUsIG1hcmdpbikge1xuICB2YXIgcGF0aCA9ICcnXG4gIHZhciBtb3ZlQnkgPSAwXG4gIHZhciBuZXdSb3cgPSBmYWxzZVxuICB2YXIgbGluZUxlbmd0aCA9IDBcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgY29sID0gTWF0aC5mbG9vcihpICUgc2l6ZSlcbiAgICB2YXIgcm93ID0gTWF0aC5mbG9vcihpIC8gc2l6ZSlcblxuICAgIGlmICghY29sICYmICFuZXdSb3cpIG5ld1JvdyA9IHRydWVcblxuICAgIGlmIChkYXRhW2ldKSB7XG4gICAgICBsaW5lTGVuZ3RoKytcblxuICAgICAgaWYgKCEoaSA+IDAgJiYgY29sID4gMCAmJiBkYXRhW2kgLSAxXSkpIHtcbiAgICAgICAgcGF0aCArPSBuZXdSb3dcbiAgICAgICAgICA/IHN2Z0NtZCgnTScsIGNvbCArIG1hcmdpbiwgMC41ICsgcm93ICsgbWFyZ2luKVxuICAgICAgICAgIDogc3ZnQ21kKCdtJywgbW92ZUJ5LCAwKVxuXG4gICAgICAgIG1vdmVCeSA9IDBcbiAgICAgICAgbmV3Um93ID0gZmFsc2VcbiAgICAgIH1cblxuICAgICAgaWYgKCEoY29sICsgMSA8IHNpemUgJiYgZGF0YVtpICsgMV0pKSB7XG4gICAgICAgIHBhdGggKz0gc3ZnQ21kKCdoJywgbGluZUxlbmd0aClcbiAgICAgICAgbGluZUxlbmd0aCA9IDBcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbW92ZUJ5KytcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcGF0aFxufVxuXG5leHBvcnRzLnJlbmRlciA9IGZ1bmN0aW9uIHJlbmRlciAocXJEYXRhLCBvcHRpb25zLCBjYikge1xuICB2YXIgb3B0cyA9IFV0aWxzLmdldE9wdGlvbnMob3B0aW9ucylcbiAgdmFyIHNpemUgPSBxckRhdGEubW9kdWxlcy5zaXplXG4gIHZhciBkYXRhID0gcXJEYXRhLm1vZHVsZXMuZGF0YVxuICB2YXIgcXJjb2Rlc2l6ZSA9IHNpemUgKyBvcHRzLm1hcmdpbiAqIDJcblxuICB2YXIgYmcgPSAhb3B0cy5jb2xvci5saWdodC5hXG4gICAgPyAnJ1xuICAgIDogJzxwYXRoICcgKyBnZXRDb2xvckF0dHJpYihvcHRzLmNvbG9yLmxpZ2h0LCAnZmlsbCcpICtcbiAgICAgICcgZD1cIk0wIDBoJyArIHFyY29kZXNpemUgKyAndicgKyBxcmNvZGVzaXplICsgJ0gwelwiLz4nXG5cbiAgdmFyIHBhdGggPVxuICAgICc8cGF0aCAnICsgZ2V0Q29sb3JBdHRyaWIob3B0cy5jb2xvci5kYXJrLCAnc3Ryb2tlJykgK1xuICAgICcgZD1cIicgKyBxclRvUGF0aChkYXRhLCBzaXplLCBvcHRzLm1hcmdpbikgKyAnXCIvPidcblxuICB2YXIgdmlld0JveCA9ICd2aWV3Qm94PVwiJyArICcwIDAgJyArIHFyY29kZXNpemUgKyAnICcgKyBxcmNvZGVzaXplICsgJ1wiJ1xuXG4gIHZhciB3aWR0aCA9ICFvcHRzLndpZHRoID8gJycgOiAnd2lkdGg9XCInICsgb3B0cy53aWR0aCArICdcIiBoZWlnaHQ9XCInICsgb3B0cy53aWR0aCArICdcIiAnXG5cbiAgdmFyIHN2Z1RhZyA9ICc8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiAnICsgd2lkdGggKyB2aWV3Qm94ICsgJyBzaGFwZS1yZW5kZXJpbmc9XCJjcmlzcEVkZ2VzXCI+JyArIGJnICsgcGF0aCArICc8L3N2Zz5cXG4nXG5cbiAgaWYgKHR5cGVvZiBjYiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGNiKG51bGwsIHN2Z1RhZylcbiAgfVxuXG4gIHJldHVybiBzdmdUYWdcbn1cbiIsImZ1bmN0aW9uIGhleDJyZ2JhIChoZXgpIHtcbiAgaWYgKHR5cGVvZiBoZXggPT09ICdudW1iZXInKSB7XG4gICAgaGV4ID0gaGV4LnRvU3RyaW5nKClcbiAgfVxuXG4gIGlmICh0eXBlb2YgaGV4ICE9PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBFcnJvcignQ29sb3Igc2hvdWxkIGJlIGRlZmluZWQgYXMgaGV4IHN0cmluZycpXG4gIH1cblxuICB2YXIgaGV4Q29kZSA9IGhleC5zbGljZSgpLnJlcGxhY2UoJyMnLCAnJykuc3BsaXQoJycpXG4gIGlmIChoZXhDb2RlLmxlbmd0aCA8IDMgfHwgaGV4Q29kZS5sZW5ndGggPT09IDUgfHwgaGV4Q29kZS5sZW5ndGggPiA4KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGhleCBjb2xvcjogJyArIGhleClcbiAgfVxuXG4gIC8vIENvbnZlcnQgZnJvbSBzaG9ydCB0byBsb25nIGZvcm0gKGZmZiAtPiBmZmZmZmYpXG4gIGlmIChoZXhDb2RlLmxlbmd0aCA9PT0gMyB8fCBoZXhDb2RlLmxlbmd0aCA9PT0gNCkge1xuICAgIGhleENvZGUgPSBBcnJheS5wcm90b3R5cGUuY29uY2F0LmFwcGx5KFtdLCBoZXhDb2RlLm1hcChmdW5jdGlvbiAoYykge1xuICAgICAgcmV0dXJuIFtjLCBjXVxuICAgIH0pKVxuICB9XG5cbiAgLy8gQWRkIGRlZmF1bHQgYWxwaGEgdmFsdWVcbiAgaWYgKGhleENvZGUubGVuZ3RoID09PSA2KSBoZXhDb2RlLnB1c2goJ0YnLCAnRicpXG5cbiAgdmFyIGhleFZhbHVlID0gcGFyc2VJbnQoaGV4Q29kZS5qb2luKCcnKSwgMTYpXG5cbiAgcmV0dXJuIHtcbiAgICByOiAoaGV4VmFsdWUgPj4gMjQpICYgMjU1LFxuICAgIGc6IChoZXhWYWx1ZSA+PiAxNikgJiAyNTUsXG4gICAgYjogKGhleFZhbHVlID4+IDgpICYgMjU1LFxuICAgIGE6IGhleFZhbHVlICYgMjU1LFxuICAgIGhleDogJyMnICsgaGV4Q29kZS5zbGljZSgwLCA2KS5qb2luKCcnKVxuICB9XG59XG5cbmV4cG9ydHMuZ2V0T3B0aW9ucyA9IGZ1bmN0aW9uIGdldE9wdGlvbnMgKG9wdGlvbnMpIHtcbiAgaWYgKCFvcHRpb25zKSBvcHRpb25zID0ge31cbiAgaWYgKCFvcHRpb25zLmNvbG9yKSBvcHRpb25zLmNvbG9yID0ge31cblxuICB2YXIgbWFyZ2luID0gdHlwZW9mIG9wdGlvbnMubWFyZ2luID09PSAndW5kZWZpbmVkJyB8fFxuICAgIG9wdGlvbnMubWFyZ2luID09PSBudWxsIHx8XG4gICAgb3B0aW9ucy5tYXJnaW4gPCAwID8gNCA6IG9wdGlvbnMubWFyZ2luXG5cbiAgdmFyIHdpZHRoID0gb3B0aW9ucy53aWR0aCAmJiBvcHRpb25zLndpZHRoID49IDIxID8gb3B0aW9ucy53aWR0aCA6IHVuZGVmaW5lZFxuICB2YXIgc2NhbGUgPSBvcHRpb25zLnNjYWxlIHx8IDRcblxuICByZXR1cm4ge1xuICAgIHdpZHRoOiB3aWR0aCxcbiAgICBzY2FsZTogd2lkdGggPyA0IDogc2NhbGUsXG4gICAgbWFyZ2luOiBtYXJnaW4sXG4gICAgY29sb3I6IHtcbiAgICAgIGRhcms6IGhleDJyZ2JhKG9wdGlvbnMuY29sb3IuZGFyayB8fCAnIzAwMDAwMGZmJyksXG4gICAgICBsaWdodDogaGV4MnJnYmEob3B0aW9ucy5jb2xvci5saWdodCB8fCAnI2ZmZmZmZmZmJylcbiAgICB9LFxuICAgIHR5cGU6IG9wdGlvbnMudHlwZSxcbiAgICByZW5kZXJlck9wdHM6IG9wdGlvbnMucmVuZGVyZXJPcHRzIHx8IHt9XG4gIH1cbn1cblxuZXhwb3J0cy5nZXRTY2FsZSA9IGZ1bmN0aW9uIGdldFNjYWxlIChxclNpemUsIG9wdHMpIHtcbiAgcmV0dXJuIG9wdHMud2lkdGggJiYgb3B0cy53aWR0aCA+PSBxclNpemUgKyBvcHRzLm1hcmdpbiAqIDJcbiAgICA/IG9wdHMud2lkdGggLyAocXJTaXplICsgb3B0cy5tYXJnaW4gKiAyKVxuICAgIDogb3B0cy5zY2FsZVxufVxuXG5leHBvcnRzLmdldEltYWdlV2lkdGggPSBmdW5jdGlvbiBnZXRJbWFnZVdpZHRoIChxclNpemUsIG9wdHMpIHtcbiAgdmFyIHNjYWxlID0gZXhwb3J0cy5nZXRTY2FsZShxclNpemUsIG9wdHMpXG4gIHJldHVybiBNYXRoLmZsb29yKChxclNpemUgKyBvcHRzLm1hcmdpbiAqIDIpICogc2NhbGUpXG59XG5cbmV4cG9ydHMucXJUb0ltYWdlRGF0YSA9IGZ1bmN0aW9uIHFyVG9JbWFnZURhdGEgKGltZ0RhdGEsIHFyLCBvcHRzKSB7XG4gIHZhciBzaXplID0gcXIubW9kdWxlcy5zaXplXG4gIHZhciBkYXRhID0gcXIubW9kdWxlcy5kYXRhXG4gIHZhciBzY2FsZSA9IGV4cG9ydHMuZ2V0U2NhbGUoc2l6ZSwgb3B0cylcbiAgdmFyIHN5bWJvbFNpemUgPSBNYXRoLmZsb29yKChzaXplICsgb3B0cy5tYXJnaW4gKiAyKSAqIHNjYWxlKVxuICB2YXIgc2NhbGVkTWFyZ2luID0gb3B0cy5tYXJnaW4gKiBzY2FsZVxuICB2YXIgcGFsZXR0ZSA9IFtvcHRzLmNvbG9yLmxpZ2h0LCBvcHRzLmNvbG9yLmRhcmtdXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzeW1ib2xTaXplOyBpKyspIHtcbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IHN5bWJvbFNpemU7IGorKykge1xuICAgICAgdmFyIHBvc0RzdCA9IChpICogc3ltYm9sU2l6ZSArIGopICogNFxuICAgICAgdmFyIHB4Q29sb3IgPSBvcHRzLmNvbG9yLmxpZ2h0XG5cbiAgICAgIGlmIChpID49IHNjYWxlZE1hcmdpbiAmJiBqID49IHNjYWxlZE1hcmdpbiAmJlxuICAgICAgICBpIDwgc3ltYm9sU2l6ZSAtIHNjYWxlZE1hcmdpbiAmJiBqIDwgc3ltYm9sU2l6ZSAtIHNjYWxlZE1hcmdpbikge1xuICAgICAgICB2YXIgaVNyYyA9IE1hdGguZmxvb3IoKGkgLSBzY2FsZWRNYXJnaW4pIC8gc2NhbGUpXG4gICAgICAgIHZhciBqU3JjID0gTWF0aC5mbG9vcigoaiAtIHNjYWxlZE1hcmdpbikgLyBzY2FsZSlcbiAgICAgICAgcHhDb2xvciA9IHBhbGV0dGVbZGF0YVtpU3JjICogc2l6ZSArIGpTcmNdID8gMSA6IDBdXG4gICAgICB9XG5cbiAgICAgIGltZ0RhdGFbcG9zRHN0KytdID0gcHhDb2xvci5yXG4gICAgICBpbWdEYXRhW3Bvc0RzdCsrXSA9IHB4Q29sb3IuZ1xuICAgICAgaW1nRGF0YVtwb3NEc3QrK10gPSBweENvbG9yLmJcbiAgICAgIGltZ0RhdGFbcG9zRHN0XSA9IHB4Q29sb3IuYVxuICAgIH1cbiAgfVxufVxuIiwiLyoqXG4gKiBJbXBsZW1lbnRhdGlvbiBvZiBhIHN1YnNldCBvZiBub2RlLmpzIEJ1ZmZlciBtZXRob2RzIGZvciB0aGUgYnJvd3Nlci5cbiAqIEJhc2VkIG9uIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyXG4gKi9cblxuLyogZXNsaW50LWRpc2FibGUgbm8tcHJvdG8gKi9cblxuJ3VzZSBzdHJpY3QnXG5cbnZhciBpc0FycmF5ID0gcmVxdWlyZSgnaXNhcnJheScpXG5cbmZ1bmN0aW9uIHR5cGVkQXJyYXlTdXBwb3J0ICgpIHtcbiAgLy8gQ2FuIHR5cGVkIGFycmF5IGluc3RhbmNlcyBiZSBhdWdtZW50ZWQ/XG4gIHRyeSB7XG4gICAgdmFyIGFyciA9IG5ldyBVaW50OEFycmF5KDEpXG4gICAgYXJyLl9fcHJvdG9fXyA9IHtfX3Byb3RvX186IFVpbnQ4QXJyYXkucHJvdG90eXBlLCBmb286IGZ1bmN0aW9uICgpIHsgcmV0dXJuIDQyIH19XG4gICAgcmV0dXJuIGFyci5mb28oKSA9PT0gNDJcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbkJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUID0gdHlwZWRBcnJheVN1cHBvcnQoKVxuXG52YXIgS19NQVhfTEVOR1RIID0gQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlRcbiAgICA/IDB4N2ZmZmZmZmZcbiAgICA6IDB4M2ZmZmZmZmZcblxuZnVuY3Rpb24gQnVmZmVyIChhcmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIGlmICghQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQgJiYgISh0aGlzIGluc3RhbmNlb2YgQnVmZmVyKSkge1xuICAgIHJldHVybiBuZXcgQnVmZmVyKGFyZywgb2Zmc2V0LCBsZW5ndGgpXG4gIH1cblxuICBpZiAodHlwZW9mIGFyZyA9PT0gJ251bWJlcicpIHtcbiAgICByZXR1cm4gYWxsb2NVbnNhZmUodGhpcywgYXJnKVxuICB9XG5cbiAgcmV0dXJuIGZyb20odGhpcywgYXJnLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gIEJ1ZmZlci5wcm90b3R5cGUuX19wcm90b19fID0gVWludDhBcnJheS5wcm90b3R5cGVcbiAgQnVmZmVyLl9fcHJvdG9fXyA9IFVpbnQ4QXJyYXlcblxuICAvLyBGaXggc3ViYXJyYXkoKSBpbiBFUzIwMTYuIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXIvcHVsbC85N1xuICBpZiAodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnNwZWNpZXMgJiZcbiAgICAgIEJ1ZmZlcltTeW1ib2wuc3BlY2llc10gPT09IEJ1ZmZlcikge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShCdWZmZXIsIFN5bWJvbC5zcGVjaWVzLCB7XG4gICAgICB2YWx1ZTogbnVsbCxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgd3JpdGFibGU6IGZhbHNlXG4gICAgfSlcbiAgfVxufVxuXG5mdW5jdGlvbiBjaGVja2VkIChsZW5ndGgpIHtcbiAgLy8gTm90ZTogY2Fubm90IHVzZSBgbGVuZ3RoIDwgS19NQVhfTEVOR1RIYCBoZXJlIGJlY2F1c2UgdGhhdCBmYWlscyB3aGVuXG4gIC8vIGxlbmd0aCBpcyBOYU4gKHdoaWNoIGlzIG90aGVyd2lzZSBjb2VyY2VkIHRvIHplcm8uKVxuICBpZiAobGVuZ3RoID49IEtfTUFYX0xFTkdUSCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdBdHRlbXB0IHRvIGFsbG9jYXRlIEJ1ZmZlciBsYXJnZXIgdGhhbiBtYXhpbXVtICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICdzaXplOiAweCcgKyBLX01BWF9MRU5HVEgudG9TdHJpbmcoMTYpICsgJyBieXRlcycpXG4gIH1cbiAgcmV0dXJuIGxlbmd0aCB8IDBcbn1cblxuZnVuY3Rpb24gaXNuYW4gKHZhbCkge1xuICByZXR1cm4gdmFsICE9PSB2YWwgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1zZWxmLWNvbXBhcmVcbn1cblxuZnVuY3Rpb24gY3JlYXRlQnVmZmVyICh0aGF0LCBsZW5ndGgpIHtcbiAgdmFyIGJ1ZlxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICBidWYgPSBuZXcgVWludDhBcnJheShsZW5ndGgpXG4gICAgYnVmLl9fcHJvdG9fXyA9IEJ1ZmZlci5wcm90b3R5cGVcbiAgfSBlbHNlIHtcbiAgICAvLyBGYWxsYmFjazogUmV0dXJuIGFuIG9iamVjdCBpbnN0YW5jZSBvZiB0aGUgQnVmZmVyIGNsYXNzXG4gICAgYnVmID0gdGhhdFxuICAgIGlmIChidWYgPT09IG51bGwpIHtcbiAgICAgIGJ1ZiA9IG5ldyBCdWZmZXIobGVuZ3RoKVxuICAgIH1cbiAgICBidWYubGVuZ3RoID0gbGVuZ3RoXG4gIH1cblxuICByZXR1cm4gYnVmXG59XG5cbmZ1bmN0aW9uIGFsbG9jVW5zYWZlICh0aGF0LCBzaXplKSB7XG4gIHZhciBidWYgPSBjcmVhdGVCdWZmZXIodGhhdCwgc2l6ZSA8IDAgPyAwIDogY2hlY2tlZChzaXplKSB8IDApXG5cbiAgaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2l6ZTsgKytpKSB7XG4gICAgICBidWZbaV0gPSAwXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ1ZlxufVxuXG5mdW5jdGlvbiBmcm9tU3RyaW5nICh0aGF0LCBzdHJpbmcpIHtcbiAgdmFyIGxlbmd0aCA9IGJ5dGVMZW5ndGgoc3RyaW5nKSB8IDBcbiAgdmFyIGJ1ZiA9IGNyZWF0ZUJ1ZmZlcih0aGF0LCBsZW5ndGgpXG5cbiAgdmFyIGFjdHVhbCA9IGJ1Zi53cml0ZShzdHJpbmcpXG5cbiAgaWYgKGFjdHVhbCAhPT0gbGVuZ3RoKSB7XG4gICAgLy8gV3JpdGluZyBhIGhleCBzdHJpbmcsIGZvciBleGFtcGxlLCB0aGF0IGNvbnRhaW5zIGludmFsaWQgY2hhcmFjdGVycyB3aWxsXG4gICAgLy8gY2F1c2UgZXZlcnl0aGluZyBhZnRlciB0aGUgZmlyc3QgaW52YWxpZCBjaGFyYWN0ZXIgdG8gYmUgaWdub3JlZC4gKGUuZy5cbiAgICAvLyAnYWJ4eGNkJyB3aWxsIGJlIHRyZWF0ZWQgYXMgJ2FiJylcbiAgICBidWYgPSBidWYuc2xpY2UoMCwgYWN0dWFsKVxuICB9XG5cbiAgcmV0dXJuIGJ1ZlxufVxuXG5mdW5jdGlvbiBmcm9tQXJyYXlMaWtlICh0aGF0LCBhcnJheSkge1xuICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoIDwgMCA/IDAgOiBjaGVja2VkKGFycmF5Lmxlbmd0aCkgfCAwXG4gIHZhciBidWYgPSBjcmVhdGVCdWZmZXIodGhhdCwgbGVuZ3RoKVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgYnVmW2ldID0gYXJyYXlbaV0gJiAyNTVcbiAgfVxuICByZXR1cm4gYnVmXG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheUJ1ZmZlciAodGhhdCwgYXJyYXksIGJ5dGVPZmZzZXQsIGxlbmd0aCkge1xuICBpZiAoYnl0ZU9mZnNldCA8IDAgfHwgYXJyYXkuYnl0ZUxlbmd0aCA8IGJ5dGVPZmZzZXQpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignXFwnb2Zmc2V0XFwnIGlzIG91dCBvZiBib3VuZHMnKVxuICB9XG5cbiAgaWYgKGFycmF5LmJ5dGVMZW5ndGggPCBieXRlT2Zmc2V0ICsgKGxlbmd0aCB8fCAwKSkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdcXCdsZW5ndGhcXCcgaXMgb3V0IG9mIGJvdW5kcycpXG4gIH1cblxuICB2YXIgYnVmXG4gIGlmIChieXRlT2Zmc2V0ID09PSB1bmRlZmluZWQgJiYgbGVuZ3RoID09PSB1bmRlZmluZWQpIHtcbiAgICBidWYgPSBuZXcgVWludDhBcnJheShhcnJheSlcbiAgfSBlbHNlIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCkge1xuICAgIGJ1ZiA9IG5ldyBVaW50OEFycmF5KGFycmF5LCBieXRlT2Zmc2V0KVxuICB9IGVsc2Uge1xuICAgIGJ1ZiA9IG5ldyBVaW50OEFycmF5KGFycmF5LCBieXRlT2Zmc2V0LCBsZW5ndGgpXG4gIH1cblxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICAvLyBSZXR1cm4gYW4gYXVnbWVudGVkIGBVaW50OEFycmF5YCBpbnN0YW5jZSwgZm9yIGJlc3QgcGVyZm9ybWFuY2VcbiAgICBidWYuX19wcm90b19fID0gQnVmZmVyLnByb3RvdHlwZVxuICB9IGVsc2Uge1xuICAgIC8vIEZhbGxiYWNrOiBSZXR1cm4gYW4gb2JqZWN0IGluc3RhbmNlIG9mIHRoZSBCdWZmZXIgY2xhc3NcbiAgICBidWYgPSBmcm9tQXJyYXlMaWtlKHRoYXQsIGJ1ZilcbiAgfVxuXG4gIHJldHVybiBidWZcbn1cblxuZnVuY3Rpb24gZnJvbU9iamVjdCAodGhhdCwgb2JqKSB7XG4gIGlmIChCdWZmZXIuaXNCdWZmZXIob2JqKSkge1xuICAgIHZhciBsZW4gPSBjaGVja2VkKG9iai5sZW5ndGgpIHwgMFxuICAgIHZhciBidWYgPSBjcmVhdGVCdWZmZXIodGhhdCwgbGVuKVxuXG4gICAgaWYgKGJ1Zi5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBidWZcbiAgICB9XG5cbiAgICBvYmouY29weShidWYsIDAsIDAsIGxlbilcbiAgICByZXR1cm4gYnVmXG4gIH1cblxuICBpZiAob2JqKSB7XG4gICAgaWYgKCh0eXBlb2YgQXJyYXlCdWZmZXIgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIG9iai5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgfHwgJ2xlbmd0aCcgaW4gb2JqKSB7XG4gICAgICBpZiAodHlwZW9mIG9iai5sZW5ndGggIT09ICdudW1iZXInIHx8IGlzbmFuKG9iai5sZW5ndGgpKSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVCdWZmZXIodGhhdCwgMClcbiAgICAgIH1cbiAgICAgIHJldHVybiBmcm9tQXJyYXlMaWtlKHRoYXQsIG9iailcbiAgICB9XG5cbiAgICBpZiAob2JqLnR5cGUgPT09ICdCdWZmZXInICYmIEFycmF5LmlzQXJyYXkob2JqLmRhdGEpKSB7XG4gICAgICByZXR1cm4gZnJvbUFycmF5TGlrZSh0aGF0LCBvYmouZGF0YSlcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZUVycm9yKCdGaXJzdCBhcmd1bWVudCBtdXN0IGJlIGEgc3RyaW5nLCBCdWZmZXIsIEFycmF5QnVmZmVyLCBBcnJheSwgb3IgYXJyYXktbGlrZSBvYmplY3QuJylcbn1cblxuZnVuY3Rpb24gdXRmOFRvQnl0ZXMgKHN0cmluZywgdW5pdHMpIHtcbiAgdW5pdHMgPSB1bml0cyB8fCBJbmZpbml0eVxuICB2YXIgY29kZVBvaW50XG4gIHZhciBsZW5ndGggPSBzdHJpbmcubGVuZ3RoXG4gIHZhciBsZWFkU3Vycm9nYXRlID0gbnVsbFxuICB2YXIgYnl0ZXMgPSBbXVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICBjb2RlUG9pbnQgPSBzdHJpbmcuY2hhckNvZGVBdChpKVxuXG4gICAgLy8gaXMgc3Vycm9nYXRlIGNvbXBvbmVudFxuICAgIGlmIChjb2RlUG9pbnQgPiAweEQ3RkYgJiYgY29kZVBvaW50IDwgMHhFMDAwKSB7XG4gICAgICAvLyBsYXN0IGNoYXIgd2FzIGEgbGVhZFxuICAgICAgaWYgKCFsZWFkU3Vycm9nYXRlKSB7XG4gICAgICAgIC8vIG5vIGxlYWQgeWV0XG4gICAgICAgIGlmIChjb2RlUG9pbnQgPiAweERCRkYpIHtcbiAgICAgICAgICAvLyB1bmV4cGVjdGVkIHRyYWlsXG4gICAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfSBlbHNlIGlmIChpICsgMSA9PT0gbGVuZ3RoKSB7XG4gICAgICAgICAgLy8gdW5wYWlyZWQgbGVhZFxuICAgICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cblxuICAgICAgICAvLyB2YWxpZCBsZWFkXG4gICAgICAgIGxlYWRTdXJyb2dhdGUgPSBjb2RlUG9pbnRcblxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICAvLyAyIGxlYWRzIGluIGEgcm93XG4gICAgICBpZiAoY29kZVBvaW50IDwgMHhEQzAwKSB7XG4gICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICBsZWFkU3Vycm9nYXRlID0gY29kZVBvaW50XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIC8vIHZhbGlkIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBjb2RlUG9pbnQgPSAobGVhZFN1cnJvZ2F0ZSAtIDB4RDgwMCA8PCAxMCB8IGNvZGVQb2ludCAtIDB4REMwMCkgKyAweDEwMDAwXG4gICAgfSBlbHNlIGlmIChsZWFkU3Vycm9nYXRlKSB7XG4gICAgICAvLyB2YWxpZCBibXAgY2hhciwgYnV0IGxhc3QgY2hhciB3YXMgYSBsZWFkXG4gICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICB9XG5cbiAgICBsZWFkU3Vycm9nYXRlID0gbnVsbFxuXG4gICAgLy8gZW5jb2RlIHV0ZjhcbiAgICBpZiAoY29kZVBvaW50IDwgMHg4MCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAxKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKGNvZGVQb2ludClcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA8IDB4ODAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDIpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgfCAweEMwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHgxMDAwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAzKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHhDIHwgMHhFMCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHgxMTAwMDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gNCkgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4MTIgfCAweEYwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHhDICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ICYgMHgzRiB8IDB4ODBcbiAgICAgIClcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvZGUgcG9pbnQnKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBieXRlc1xufVxuXG5mdW5jdGlvbiBieXRlTGVuZ3RoIChzdHJpbmcpIHtcbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihzdHJpbmcpKSB7XG4gICAgcmV0dXJuIHN0cmluZy5sZW5ndGhcbiAgfVxuICBpZiAodHlwZW9mIEFycmF5QnVmZmVyICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgQXJyYXlCdWZmZXIuaXNWaWV3ID09PSAnZnVuY3Rpb24nICYmXG4gICAgICAoQXJyYXlCdWZmZXIuaXNWaWV3KHN0cmluZykgfHwgc3RyaW5nIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpKSB7XG4gICAgcmV0dXJuIHN0cmluZy5ieXRlTGVuZ3RoXG4gIH1cbiAgaWYgKHR5cGVvZiBzdHJpbmcgIT09ICdzdHJpbmcnKSB7XG4gICAgc3RyaW5nID0gJycgKyBzdHJpbmdcbiAgfVxuXG4gIHZhciBsZW4gPSBzdHJpbmcubGVuZ3RoXG4gIGlmIChsZW4gPT09IDApIHJldHVybiAwXG5cbiAgcmV0dXJuIHV0ZjhUb0J5dGVzKHN0cmluZykubGVuZ3RoXG59XG5cbmZ1bmN0aW9uIGJsaXRCdWZmZXIgKHNyYywgZHN0LCBvZmZzZXQsIGxlbmd0aCkge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7XG4gICAgaWYgKChpICsgb2Zmc2V0ID49IGRzdC5sZW5ndGgpIHx8IChpID49IHNyYy5sZW5ndGgpKSBicmVha1xuICAgIGRzdFtpICsgb2Zmc2V0XSA9IHNyY1tpXVxuICB9XG4gIHJldHVybiBpXG59XG5cbmZ1bmN0aW9uIHV0ZjhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKHV0ZjhUb0J5dGVzKHN0cmluZywgYnVmLmxlbmd0aCAtIG9mZnNldCksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGZyb20gKHRoYXQsIHZhbHVlLCBvZmZzZXQsIGxlbmd0aCkge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1widmFsdWVcIiBhcmd1bWVudCBtdXN0IG5vdCBiZSBhIG51bWJlcicpXG4gIH1cblxuICBpZiAodHlwZW9mIEFycmF5QnVmZmVyICE9PSAndW5kZWZpbmVkJyAmJiB2YWx1ZSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7XG4gICAgcmV0dXJuIGZyb21BcnJheUJ1ZmZlcih0aGF0LCB2YWx1ZSwgb2Zmc2V0LCBsZW5ndGgpXG4gIH1cblxuICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBmcm9tU3RyaW5nKHRoYXQsIHZhbHVlLCBvZmZzZXQpXG4gIH1cblxuICByZXR1cm4gZnJvbU9iamVjdCh0aGF0LCB2YWx1ZSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZSA9IGZ1bmN0aW9uIHdyaXRlIChzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcpXG4gIGlmIChvZmZzZXQgPT09IHVuZGVmaW5lZCkge1xuICAgIGxlbmd0aCA9IHRoaXMubGVuZ3RoXG4gICAgb2Zmc2V0ID0gMFxuICAvLyBCdWZmZXIjd3JpdGUoc3RyaW5nLCBlbmNvZGluZylcbiAgfSBlbHNlIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCAmJiB0eXBlb2Ygb2Zmc2V0ID09PSAnc3RyaW5nJykge1xuICAgIGxlbmd0aCA9IHRoaXMubGVuZ3RoXG4gICAgb2Zmc2V0ID0gMFxuICAvLyBCdWZmZXIjd3JpdGUoc3RyaW5nLCBvZmZzZXRbLCBsZW5ndGhdKVxuICB9IGVsc2UgaWYgKGlzRmluaXRlKG9mZnNldCkpIHtcbiAgICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gICAgaWYgKGlzRmluaXRlKGxlbmd0aCkpIHtcbiAgICAgIGxlbmd0aCA9IGxlbmd0aCB8IDBcbiAgICB9IGVsc2Uge1xuICAgICAgbGVuZ3RoID0gdW5kZWZpbmVkXG4gICAgfVxuICB9XG5cbiAgdmFyIHJlbWFpbmluZyA9IHRoaXMubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCB8fCBsZW5ndGggPiByZW1haW5pbmcpIGxlbmd0aCA9IHJlbWFpbmluZ1xuXG4gIGlmICgoc3RyaW5nLmxlbmd0aCA+IDAgJiYgKGxlbmd0aCA8IDAgfHwgb2Zmc2V0IDwgMCkpIHx8IG9mZnNldCA+IHRoaXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0F0dGVtcHQgdG8gd3JpdGUgb3V0c2lkZSBidWZmZXIgYm91bmRzJylcbiAgfVxuXG4gIHJldHVybiB1dGY4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zbGljZSA9IGZ1bmN0aW9uIHNsaWNlIChzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBzdGFydCA9IH5+c3RhcnRcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyBsZW4gOiB+fmVuZFxuXG4gIGlmIChzdGFydCA8IDApIHtcbiAgICBzdGFydCArPSBsZW5cbiAgICBpZiAoc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgfSBlbHNlIGlmIChzdGFydCA+IGxlbikge1xuICAgIHN0YXJ0ID0gbGVuXG4gIH1cblxuICBpZiAoZW5kIDwgMCkge1xuICAgIGVuZCArPSBsZW5cbiAgICBpZiAoZW5kIDwgMCkgZW5kID0gMFxuICB9IGVsc2UgaWYgKGVuZCA+IGxlbikge1xuICAgIGVuZCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IHN0YXJ0KSBlbmQgPSBzdGFydFxuXG4gIHZhciBuZXdCdWZcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgbmV3QnVmID0gdGhpcy5zdWJhcnJheShzdGFydCwgZW5kKVxuICAgIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlXG4gICAgbmV3QnVmLl9fcHJvdG9fXyA9IEJ1ZmZlci5wcm90b3R5cGVcbiAgfSBlbHNlIHtcbiAgICB2YXIgc2xpY2VMZW4gPSBlbmQgLSBzdGFydFxuICAgIG5ld0J1ZiA9IG5ldyBCdWZmZXIoc2xpY2VMZW4sIHVuZGVmaW5lZClcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNsaWNlTGVuOyArK2kpIHtcbiAgICAgIG5ld0J1ZltpXSA9IHRoaXNbaSArIHN0YXJ0XVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdCdWZcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5jb3B5ID0gZnVuY3Rpb24gY29weSAodGFyZ2V0LCB0YXJnZXRTdGFydCwgc3RhcnQsIGVuZCkge1xuICBpZiAoIXN0YXJ0KSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgJiYgZW5kICE9PSAwKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAodGFyZ2V0U3RhcnQgPj0gdGFyZ2V0Lmxlbmd0aCkgdGFyZ2V0U3RhcnQgPSB0YXJnZXQubGVuZ3RoXG4gIGlmICghdGFyZ2V0U3RhcnQpIHRhcmdldFN0YXJ0ID0gMFxuICBpZiAoZW5kID4gMCAmJiBlbmQgPCBzdGFydCkgZW5kID0gc3RhcnRcblxuICAvLyBDb3B5IDAgYnl0ZXM7IHdlJ3JlIGRvbmVcbiAgaWYgKGVuZCA9PT0gc3RhcnQpIHJldHVybiAwXG4gIGlmICh0YXJnZXQubGVuZ3RoID09PSAwIHx8IHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm4gMFxuXG4gIC8vIEZhdGFsIGVycm9yIGNvbmRpdGlvbnNcbiAgaWYgKHRhcmdldFN0YXJ0IDwgMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCd0YXJnZXRTdGFydCBvdXQgb2YgYm91bmRzJylcbiAgfVxuICBpZiAoc3RhcnQgPCAwIHx8IHN0YXJ0ID49IHRoaXMubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignc291cmNlU3RhcnQgb3V0IG9mIGJvdW5kcycpXG4gIGlmIChlbmQgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignc291cmNlRW5kIG91dCBvZiBib3VuZHMnKVxuXG4gIC8vIEFyZSB3ZSBvb2I/XG4gIGlmIChlbmQgPiB0aGlzLmxlbmd0aCkgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKHRhcmdldC5sZW5ndGggLSB0YXJnZXRTdGFydCA8IGVuZCAtIHN0YXJ0KSB7XG4gICAgZW5kID0gdGFyZ2V0Lmxlbmd0aCAtIHRhcmdldFN0YXJ0ICsgc3RhcnRcbiAgfVxuXG4gIHZhciBsZW4gPSBlbmQgLSBzdGFydFxuICB2YXIgaVxuXG4gIGlmICh0aGlzID09PSB0YXJnZXQgJiYgc3RhcnQgPCB0YXJnZXRTdGFydCAmJiB0YXJnZXRTdGFydCA8IGVuZCkge1xuICAgIC8vIGRlc2NlbmRpbmcgY29weSBmcm9tIGVuZFxuICAgIGZvciAoaSA9IGxlbiAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICB0YXJnZXRbaSArIHRhcmdldFN0YXJ0XSA9IHRoaXNbaSArIHN0YXJ0XVxuICAgIH1cbiAgfSBlbHNlIGlmIChsZW4gPCAxMDAwIHx8ICFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIC8vIGFzY2VuZGluZyBjb3B5IGZyb20gc3RhcnRcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyArK2kpIHtcbiAgICAgIHRhcmdldFtpICsgdGFyZ2V0U3RhcnRdID0gdGhpc1tpICsgc3RhcnRdXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIFVpbnQ4QXJyYXkucHJvdG90eXBlLnNldC5jYWxsKFxuICAgICAgdGFyZ2V0LFxuICAgICAgdGhpcy5zdWJhcnJheShzdGFydCwgc3RhcnQgKyBsZW4pLFxuICAgICAgdGFyZ2V0U3RhcnRcbiAgICApXG4gIH1cblxuICByZXR1cm4gbGVuXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuZmlsbCA9IGZ1bmN0aW9uIGZpbGwgKHZhbCwgc3RhcnQsIGVuZCkge1xuICAvLyBIYW5kbGUgc3RyaW5nIGNhc2VzOlxuICBpZiAodHlwZW9mIHZhbCA9PT0gJ3N0cmluZycpIHtcbiAgICBpZiAodHlwZW9mIHN0YXJ0ID09PSAnc3RyaW5nJykge1xuICAgICAgc3RhcnQgPSAwXG4gICAgICBlbmQgPSB0aGlzLmxlbmd0aFxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGVuZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGVuZCA9IHRoaXMubGVuZ3RoXG4gICAgfVxuICAgIGlmICh2YWwubGVuZ3RoID09PSAxKSB7XG4gICAgICB2YXIgY29kZSA9IHZhbC5jaGFyQ29kZUF0KDApXG4gICAgICBpZiAoY29kZSA8IDI1Nikge1xuICAgICAgICB2YWwgPSBjb2RlXG4gICAgICB9XG4gICAgfVxuICB9IGVsc2UgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSB7XG4gICAgdmFsID0gdmFsICYgMjU1XG4gIH1cblxuICAvLyBJbnZhbGlkIHJhbmdlcyBhcmUgbm90IHNldCB0byBhIGRlZmF1bHQsIHNvIGNhbiByYW5nZSBjaGVjayBlYXJseS5cbiAgaWYgKHN0YXJ0IDwgMCB8fCB0aGlzLmxlbmd0aCA8IHN0YXJ0IHx8IHRoaXMubGVuZ3RoIDwgZW5kKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ091dCBvZiByYW5nZSBpbmRleCcpXG4gIH1cblxuICBpZiAoZW5kIDw9IHN0YXJ0KSB7XG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIHN0YXJ0ID0gc3RhcnQgPj4+IDBcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyB0aGlzLmxlbmd0aCA6IGVuZCA+Pj4gMFxuXG4gIGlmICghdmFsKSB2YWwgPSAwXG5cbiAgdmFyIGlcbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSB7XG4gICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkge1xuICAgICAgdGhpc1tpXSA9IHZhbFxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2YXIgYnl0ZXMgPSBCdWZmZXIuaXNCdWZmZXIodmFsKVxuICAgICAgPyB2YWxcbiAgICAgIDogbmV3IEJ1ZmZlcih2YWwpXG4gICAgdmFyIGxlbiA9IGJ5dGVzLmxlbmd0aFxuICAgIGZvciAoaSA9IDA7IGkgPCBlbmQgLSBzdGFydDsgKytpKSB7XG4gICAgICB0aGlzW2kgKyBzdGFydF0gPSBieXRlc1tpICUgbGVuXVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzXG59XG5cbkJ1ZmZlci5jb25jYXQgPSBmdW5jdGlvbiBjb25jYXQgKGxpc3QsIGxlbmd0aCkge1xuICBpZiAoIWlzQXJyYXkobGlzdCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RcIiBhcmd1bWVudCBtdXN0IGJlIGFuIEFycmF5IG9mIEJ1ZmZlcnMnKVxuICB9XG5cbiAgaWYgKGxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUJ1ZmZlcihudWxsLCAwKVxuICB9XG5cbiAgdmFyIGlcbiAgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgbGVuZ3RoID0gMFxuICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgKytpKSB7XG4gICAgICBsZW5ndGggKz0gbGlzdFtpXS5sZW5ndGhcbiAgICB9XG4gIH1cblxuICB2YXIgYnVmZmVyID0gYWxsb2NVbnNhZmUobnVsbCwgbGVuZ3RoKVxuICB2YXIgcG9zID0gMFxuICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7ICsraSkge1xuICAgIHZhciBidWYgPSBsaXN0W2ldXG4gICAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYnVmKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0XCIgYXJndW1lbnQgbXVzdCBiZSBhbiBBcnJheSBvZiBCdWZmZXJzJylcbiAgICB9XG4gICAgYnVmLmNvcHkoYnVmZmVyLCBwb3MpXG4gICAgcG9zICs9IGJ1Zi5sZW5ndGhcbiAgfVxuICByZXR1cm4gYnVmZmVyXG59XG5cbkJ1ZmZlci5ieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aFxuXG5CdWZmZXIucHJvdG90eXBlLl9pc0J1ZmZlciA9IHRydWVcbkJ1ZmZlci5pc0J1ZmZlciA9IGZ1bmN0aW9uIGlzQnVmZmVyIChiKSB7XG4gIHJldHVybiAhIShiICE9IG51bGwgJiYgYi5faXNCdWZmZXIpXG59XG5cbm1vZHVsZS5leHBvcnRzID0gQnVmZmVyXG4iLCIndXNlIHN0cmljdCc7XG5cbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAqIENyZWF0ZWQgMjAwOC0wOC0xOS5cbiAqXG4gKiBEaWprc3RyYSBwYXRoLWZpbmRpbmcgZnVuY3Rpb25zLiBBZGFwdGVkIGZyb20gdGhlIERpamtzdGFyIFB5dGhvbiBwcm9qZWN0LlxuICpcbiAqIENvcHlyaWdodCAoQykgMjAwOFxuICogICBXeWF0dCBCYWxkd2luIDxzZWxmQHd5YXR0YmFsZHdpbi5jb20+XG4gKiAgIEFsbCByaWdodHMgcmVzZXJ2ZWRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UuXG4gKlxuICogICBodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocFxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1JcbiAqIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuICogRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gKiBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4gKiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuICogT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuICogVEhFIFNPRlRXQVJFLlxuICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xudmFyIGRpamtzdHJhID0ge1xuICBzaW5nbGVfc291cmNlX3Nob3J0ZXN0X3BhdGhzOiBmdW5jdGlvbihncmFwaCwgcywgZCkge1xuICAgIC8vIFByZWRlY2Vzc29yIG1hcCBmb3IgZWFjaCBub2RlIHRoYXQgaGFzIGJlZW4gZW5jb3VudGVyZWQuXG4gICAgLy8gbm9kZSBJRCA9PiBwcmVkZWNlc3NvciBub2RlIElEXG4gICAgdmFyIHByZWRlY2Vzc29ycyA9IHt9O1xuXG4gICAgLy8gQ29zdHMgb2Ygc2hvcnRlc3QgcGF0aHMgZnJvbSBzIHRvIGFsbCBub2RlcyBlbmNvdW50ZXJlZC5cbiAgICAvLyBub2RlIElEID0+IGNvc3RcbiAgICB2YXIgY29zdHMgPSB7fTtcbiAgICBjb3N0c1tzXSA9IDA7XG5cbiAgICAvLyBDb3N0cyBvZiBzaG9ydGVzdCBwYXRocyBmcm9tIHMgdG8gYWxsIG5vZGVzIGVuY291bnRlcmVkOyBkaWZmZXJzIGZyb21cbiAgICAvLyBgY29zdHNgIGluIHRoYXQgaXQgcHJvdmlkZXMgZWFzeSBhY2Nlc3MgdG8gdGhlIG5vZGUgdGhhdCBjdXJyZW50bHkgaGFzXG4gICAgLy8gdGhlIGtub3duIHNob3J0ZXN0IHBhdGggZnJvbSBzLlxuICAgIC8vIFhYWDogRG8gd2UgYWN0dWFsbHkgbmVlZCBib3RoIGBjb3N0c2AgYW5kIGBvcGVuYD9cbiAgICB2YXIgb3BlbiA9IGRpamtzdHJhLlByaW9yaXR5UXVldWUubWFrZSgpO1xuICAgIG9wZW4ucHVzaChzLCAwKTtcblxuICAgIHZhciBjbG9zZXN0LFxuICAgICAgICB1LCB2LFxuICAgICAgICBjb3N0X29mX3NfdG9fdSxcbiAgICAgICAgYWRqYWNlbnRfbm9kZXMsXG4gICAgICAgIGNvc3Rfb2ZfZSxcbiAgICAgICAgY29zdF9vZl9zX3RvX3VfcGx1c19jb3N0X29mX2UsXG4gICAgICAgIGNvc3Rfb2Zfc190b192LFxuICAgICAgICBmaXJzdF92aXNpdDtcbiAgICB3aGlsZSAoIW9wZW4uZW1wdHkoKSkge1xuICAgICAgLy8gSW4gdGhlIG5vZGVzIHJlbWFpbmluZyBpbiBncmFwaCB0aGF0IGhhdmUgYSBrbm93biBjb3N0IGZyb20gcyxcbiAgICAgIC8vIGZpbmQgdGhlIG5vZGUsIHUsIHRoYXQgY3VycmVudGx5IGhhcyB0aGUgc2hvcnRlc3QgcGF0aCBmcm9tIHMuXG4gICAgICBjbG9zZXN0ID0gb3Blbi5wb3AoKTtcbiAgICAgIHUgPSBjbG9zZXN0LnZhbHVlO1xuICAgICAgY29zdF9vZl9zX3RvX3UgPSBjbG9zZXN0LmNvc3Q7XG5cbiAgICAgIC8vIEdldCBub2RlcyBhZGphY2VudCB0byB1Li4uXG4gICAgICBhZGphY2VudF9ub2RlcyA9IGdyYXBoW3VdIHx8IHt9O1xuXG4gICAgICAvLyAuLi5hbmQgZXhwbG9yZSB0aGUgZWRnZXMgdGhhdCBjb25uZWN0IHUgdG8gdGhvc2Ugbm9kZXMsIHVwZGF0aW5nXG4gICAgICAvLyB0aGUgY29zdCBvZiB0aGUgc2hvcnRlc3QgcGF0aHMgdG8gYW55IG9yIGFsbCBvZiB0aG9zZSBub2RlcyBhc1xuICAgICAgLy8gbmVjZXNzYXJ5LiB2IGlzIHRoZSBub2RlIGFjcm9zcyB0aGUgY3VycmVudCBlZGdlIGZyb20gdS5cbiAgICAgIGZvciAodiBpbiBhZGphY2VudF9ub2Rlcykge1xuICAgICAgICBpZiAoYWRqYWNlbnRfbm9kZXMuaGFzT3duUHJvcGVydHkodikpIHtcbiAgICAgICAgICAvLyBHZXQgdGhlIGNvc3Qgb2YgdGhlIGVkZ2UgcnVubmluZyBmcm9tIHUgdG8gdi5cbiAgICAgICAgICBjb3N0X29mX2UgPSBhZGphY2VudF9ub2Rlc1t2XTtcblxuICAgICAgICAgIC8vIENvc3Qgb2YgcyB0byB1IHBsdXMgdGhlIGNvc3Qgb2YgdSB0byB2IGFjcm9zcyBlLS10aGlzIGlzICphKlxuICAgICAgICAgIC8vIGNvc3QgZnJvbSBzIHRvIHYgdGhhdCBtYXkgb3IgbWF5IG5vdCBiZSBsZXNzIHRoYW4gdGhlIGN1cnJlbnRcbiAgICAgICAgICAvLyBrbm93biBjb3N0IHRvIHYuXG4gICAgICAgICAgY29zdF9vZl9zX3RvX3VfcGx1c19jb3N0X29mX2UgPSBjb3N0X29mX3NfdG9fdSArIGNvc3Rfb2ZfZTtcblxuICAgICAgICAgIC8vIElmIHdlIGhhdmVuJ3QgdmlzaXRlZCB2IHlldCBPUiBpZiB0aGUgY3VycmVudCBrbm93biBjb3N0IGZyb20gcyB0b1xuICAgICAgICAgIC8vIHYgaXMgZ3JlYXRlciB0aGFuIHRoZSBuZXcgY29zdCB3ZSBqdXN0IGZvdW5kIChjb3N0IG9mIHMgdG8gdSBwbHVzXG4gICAgICAgICAgLy8gY29zdCBvZiB1IHRvIHYgYWNyb3NzIGUpLCB1cGRhdGUgdidzIGNvc3QgaW4gdGhlIGNvc3QgbGlzdCBhbmRcbiAgICAgICAgICAvLyB1cGRhdGUgdidzIHByZWRlY2Vzc29yIGluIHRoZSBwcmVkZWNlc3NvciBsaXN0IChpdCdzIG5vdyB1KS5cbiAgICAgICAgICBjb3N0X29mX3NfdG9fdiA9IGNvc3RzW3ZdO1xuICAgICAgICAgIGZpcnN0X3Zpc2l0ID0gKHR5cGVvZiBjb3N0c1t2XSA9PT0gJ3VuZGVmaW5lZCcpO1xuICAgICAgICAgIGlmIChmaXJzdF92aXNpdCB8fCBjb3N0X29mX3NfdG9fdiA+IGNvc3Rfb2Zfc190b191X3BsdXNfY29zdF9vZl9lKSB7XG4gICAgICAgICAgICBjb3N0c1t2XSA9IGNvc3Rfb2Zfc190b191X3BsdXNfY29zdF9vZl9lO1xuICAgICAgICAgICAgb3Blbi5wdXNoKHYsIGNvc3Rfb2Zfc190b191X3BsdXNfY29zdF9vZl9lKTtcbiAgICAgICAgICAgIHByZWRlY2Vzc29yc1t2XSA9IHU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBkICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgY29zdHNbZF0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB2YXIgbXNnID0gWydDb3VsZCBub3QgZmluZCBhIHBhdGggZnJvbSAnLCBzLCAnIHRvICcsIGQsICcuJ10uam9pbignJyk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJlZGVjZXNzb3JzO1xuICB9LFxuXG4gIGV4dHJhY3Rfc2hvcnRlc3RfcGF0aF9mcm9tX3ByZWRlY2Vzc29yX2xpc3Q6IGZ1bmN0aW9uKHByZWRlY2Vzc29ycywgZCkge1xuICAgIHZhciBub2RlcyA9IFtdO1xuICAgIHZhciB1ID0gZDtcbiAgICB2YXIgcHJlZGVjZXNzb3I7XG4gICAgd2hpbGUgKHUpIHtcbiAgICAgIG5vZGVzLnB1c2godSk7XG4gICAgICBwcmVkZWNlc3NvciA9IHByZWRlY2Vzc29yc1t1XTtcbiAgICAgIHUgPSBwcmVkZWNlc3NvcnNbdV07XG4gICAgfVxuICAgIG5vZGVzLnJldmVyc2UoKTtcbiAgICByZXR1cm4gbm9kZXM7XG4gIH0sXG5cbiAgZmluZF9wYXRoOiBmdW5jdGlvbihncmFwaCwgcywgZCkge1xuICAgIHZhciBwcmVkZWNlc3NvcnMgPSBkaWprc3RyYS5zaW5nbGVfc291cmNlX3Nob3J0ZXN0X3BhdGhzKGdyYXBoLCBzLCBkKTtcbiAgICByZXR1cm4gZGlqa3N0cmEuZXh0cmFjdF9zaG9ydGVzdF9wYXRoX2Zyb21fcHJlZGVjZXNzb3JfbGlzdChcbiAgICAgIHByZWRlY2Vzc29ycywgZCk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEEgdmVyeSBuYWl2ZSBwcmlvcml0eSBxdWV1ZSBpbXBsZW1lbnRhdGlvbi5cbiAgICovXG4gIFByaW9yaXR5UXVldWU6IHtcbiAgICBtYWtlOiBmdW5jdGlvbiAob3B0cykge1xuICAgICAgdmFyIFQgPSBkaWprc3RyYS5Qcmlvcml0eVF1ZXVlLFxuICAgICAgICAgIHQgPSB7fSxcbiAgICAgICAgICBrZXk7XG4gICAgICBvcHRzID0gb3B0cyB8fCB7fTtcbiAgICAgIGZvciAoa2V5IGluIFQpIHtcbiAgICAgICAgaWYgKFQuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgIHRba2V5XSA9IFRba2V5XTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdC5xdWV1ZSA9IFtdO1xuICAgICAgdC5zb3J0ZXIgPSBvcHRzLnNvcnRlciB8fCBULmRlZmF1bHRfc29ydGVyO1xuICAgICAgcmV0dXJuIHQ7XG4gICAgfSxcblxuICAgIGRlZmF1bHRfc29ydGVyOiBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgcmV0dXJuIGEuY29zdCAtIGIuY29zdDtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQWRkIGEgbmV3IGl0ZW0gdG8gdGhlIHF1ZXVlIGFuZCBlbnN1cmUgdGhlIGhpZ2hlc3QgcHJpb3JpdHkgZWxlbWVudFxuICAgICAqIGlzIGF0IHRoZSBmcm9udCBvZiB0aGUgcXVldWUuXG4gICAgICovXG4gICAgcHVzaDogZnVuY3Rpb24gKHZhbHVlLCBjb3N0KSB7XG4gICAgICB2YXIgaXRlbSA9IHt2YWx1ZTogdmFsdWUsIGNvc3Q6IGNvc3R9O1xuICAgICAgdGhpcy5xdWV1ZS5wdXNoKGl0ZW0pO1xuICAgICAgdGhpcy5xdWV1ZS5zb3J0KHRoaXMuc29ydGVyKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBoaWdoZXN0IHByaW9yaXR5IGVsZW1lbnQgaW4gdGhlIHF1ZXVlLlxuICAgICAqL1xuICAgIHBvcDogZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXMucXVldWUuc2hpZnQoKTtcbiAgICB9LFxuXG4gICAgZW1wdHk6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0aGlzLnF1ZXVlLmxlbmd0aCA9PT0gMDtcbiAgICB9XG4gIH1cbn07XG5cblxuLy8gbm9kZS5qcyBtb2R1bGUgZXhwb3J0c1xuaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnKSB7XG4gIG1vZHVsZS5leHBvcnRzID0gZGlqa3N0cmE7XG59XG4iLCJ2YXIgdG9TdHJpbmcgPSB7fS50b1N0cmluZztcblxubW9kdWxlLmV4cG9ydHMgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uIChhcnIpIHtcbiAgcmV0dXJuIHRvU3RyaW5nLmNhbGwoYXJyKSA9PSAnW29iamVjdCBBcnJheV0nO1xufTtcbiJdfQ==
|