@pie-lib/mask-markup 3.1.5 → 3.1.6-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +0 -105
  2. package/lib/__tests__/drag-in-the-blank.test.js +129 -0
  3. package/lib/__tests__/index.test.js +39 -0
  4. package/lib/__tests__/keyboard-coordinates.test.js +449 -0
  5. package/lib/__tests__/mask.test.js +344 -0
  6. package/lib/__tests__/serialization.test.js +44 -0
  7. package/lib/__tests__/utils.js +14 -0
  8. package/lib/__tests__/with-mask.test.js +110 -0
  9. package/lib/choices/__tests__/index.test.js +139 -0
  10. package/lib/choices/choice.js +6 -24
  11. package/lib/choices/choice.js.map +1 -1
  12. package/lib/choices/index.js +9 -32
  13. package/lib/choices/index.js.map +1 -1
  14. package/lib/components/__tests__/blank.test.js +293 -0
  15. package/lib/components/__tests__/correct-input.test.js +132 -0
  16. package/lib/components/__tests__/dropdown.test.js +202 -0
  17. package/lib/components/__tests__/input.test.js +129 -0
  18. package/lib/components/blank.js +29 -106
  19. package/lib/components/blank.js.map +1 -1
  20. package/lib/components/dropdown.js +9 -6
  21. package/lib/components/dropdown.js.map +1 -1
  22. package/lib/drag-in-the-blank.js +30 -139
  23. package/lib/drag-in-the-blank.js.map +1 -1
  24. package/lib/keyboard-coordinates.js +1 -1
  25. package/lib/mask.js +15 -20
  26. package/lib/mask.js.map +1 -1
  27. package/package.json +6 -6
  28. package/src/__tests__/drag-in-the-blank.test.js +2 -147
  29. package/src/__tests__/mask.test.js +0 -98
  30. package/src/choices/__tests__/index.test.js +1 -104
  31. package/src/choices/choice.jsx +3 -16
  32. package/src/choices/index.jsx +3 -27
  33. package/src/components/__tests__/blank.test.js +5 -186
  34. package/src/components/blank.jsx +35 -108
  35. package/src/components/dropdown.jsx +9 -7
  36. package/src/drag-in-the-blank.jsx +22 -132
  37. package/src/mask.jsx +11 -13
  38. package/LICENSE.md +0 -5
  39. package/lib/keyboard-coordinates.js.map +0 -1
  40. package/src/__tests__/keyboard-coordinates.test.js +0 -202
  41. package/src/keyboard-coordinates.js +0 -147
@@ -0,0 +1,449 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
5
+ var _core = require("@dnd-kit/core");
6
+ var _keyboardCoordinates = require("../keyboard-coordinates");
7
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
8
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
9
+ function rectsToContext(rects) {
10
+ var droppableRects = new Map(Object.entries(rects));
11
+ var droppableContainers = new Map(Object.keys(rects).map(function (id) {
12
+ return [id, {
13
+ disabled: false
14
+ }];
15
+ }));
16
+ return {
17
+ droppableRects: droppableRects,
18
+ droppableContainers: droppableContainers
19
+ };
20
+ }
21
+ function makeEvent(code) {
22
+ var shiftKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
23
+ return {
24
+ code: code,
25
+ preventDefault: function preventDefault() {},
26
+ shiftKey: shiftKey
27
+ };
28
+ }
29
+
30
+ // Mirrors dnd-kit's own KeyboardSensor, which always derives collisionRect's top-left
31
+ // from the dragged item's current on-screen position on every keydown — so a test's
32
+ // collisionRect must track currentCoordinates the same way on every simulated press,
33
+ // not stay fixed while currentCoordinates changes across multiple presses.
34
+ function press(rects, currentCoordinates, itemSize, event, active) {
35
+ var context = _objectSpread(_objectSpread({}, rectsToContext(rects)), {}, {
36
+ collisionRect: _objectSpread({
37
+ left: currentCoordinates.x,
38
+ top: currentCoordinates.y
39
+ }, itemSize)
40
+ });
41
+ return (0, _keyboardCoordinates.closestDroppableKeyboardCoordinates)(event, {
42
+ active: active,
43
+ context: context,
44
+ currentCoordinates: currentCoordinates
45
+ });
46
+ }
47
+ describe('closestDroppableKeyboardCoordinates', function () {
48
+ describe('arrow keys', function () {
49
+ it("nudges the dragged item by dnd-kit's own default step (25px), unchanged", function () {
50
+ var context = _objectSpread(_objectSpread({}, rectsToContext({})), {}, {
51
+ collisionRect: {
52
+ left: 0,
53
+ top: 0,
54
+ width: 100,
55
+ height: 40
56
+ }
57
+ });
58
+ var currentCoordinates = {
59
+ x: 10,
60
+ y: 20
61
+ };
62
+ expect((0, _keyboardCoordinates.closestDroppableKeyboardCoordinates)(makeEvent(_core.KeyboardCode.Down), {
63
+ context: context,
64
+ currentCoordinates: currentCoordinates
65
+ })).toEqual({
66
+ x: 10,
67
+ y: 45
68
+ });
69
+ expect((0, _keyboardCoordinates.closestDroppableKeyboardCoordinates)(makeEvent(_core.KeyboardCode.Up), {
70
+ context: context,
71
+ currentCoordinates: currentCoordinates
72
+ })).toEqual({
73
+ x: 10,
74
+ y: -5
75
+ });
76
+ expect((0, _keyboardCoordinates.closestDroppableKeyboardCoordinates)(makeEvent(_core.KeyboardCode.Right), {
77
+ context: context,
78
+ currentCoordinates: currentCoordinates
79
+ })).toEqual({
80
+ x: 35,
81
+ y: 20
82
+ });
83
+ expect((0, _keyboardCoordinates.closestDroppableKeyboardCoordinates)(makeEvent(_core.KeyboardCode.Left), {
84
+ context: context,
85
+ currentCoordinates: currentCoordinates
86
+ })).toEqual({
87
+ x: -15,
88
+ y: 20
89
+ });
90
+ });
91
+ });
92
+ describe('Tab / Shift+Tab', function () {
93
+ var blank0Rect = {
94
+ left: 0,
95
+ top: 0,
96
+ width: 120,
97
+ height: 40,
98
+ right: 120,
99
+ bottom: 40
100
+ };
101
+ var blank1Rect = {
102
+ left: 0,
103
+ top: 60,
104
+ width: 120,
105
+ height: 40,
106
+ right: 120,
107
+ bottom: 100
108
+ };
109
+ var boardRect = {
110
+ left: 0,
111
+ top: 120,
112
+ width: 400,
113
+ height: 300,
114
+ right: 400,
115
+ bottom: 420
116
+ };
117
+ var baseRects = {
118
+ 'mask-blank-drop-0': blank0Rect,
119
+ 'mask-blank-drop-1': blank1Rect,
120
+ 'drag-in-the-blank-droppable': boardRect
121
+ };
122
+ it('jumps to the next droppable in top-to-bottom order, landing at its center-left point', function () {
123
+ var currentCoordinates = {
124
+ x: blank0Rect.left,
125
+ y: blank0Rect.top
126
+ };
127
+ var next = press(baseRects, currentCoordinates, {
128
+ width: 120,
129
+ height: 40
130
+ }, makeEvent('Tab'));
131
+ expect(next).toEqual({
132
+ x: blank1Rect.left,
133
+ y: blank1Rect.top + blank1Rect.height / 2
134
+ });
135
+ });
136
+ it('cycles backwards with Shift+Tab, wrapping to the choice board', function () {
137
+ var currentCoordinates = {
138
+ x: blank0Rect.left,
139
+ y: blank0Rect.top
140
+ };
141
+ var next = press(baseRects, currentCoordinates, {
142
+ width: 120,
143
+ height: 40
144
+ }, makeEvent('Tab', true));
145
+ expect(next).toEqual({
146
+ x: boardRect.left,
147
+ y: boardRect.top + boardRect.height / 2
148
+ });
149
+ });
150
+ it("excludes a dragged blank's own drop-zone from the cycle", function () {
151
+ // A blank is simultaneously draggable and droppable for its own slot (the same
152
+ // shape as match-list's placed "target" tiles). Without excluding it, containment
153
+ // would match the blank to itself and cycle relative to itself instead of its
154
+ // real neighbors — this test is constructed so the two behaviors give different,
155
+ // distinguishable results (not just coincidentally the same answer).
156
+ var blankARect = {
157
+ left: 0,
158
+ top: 0,
159
+ width: 120,
160
+ height: 40,
161
+ right: 120,
162
+ bottom: 40
163
+ };
164
+ var blankBRect = {
165
+ left: 0,
166
+ top: 60,
167
+ width: 120,
168
+ height: 40,
169
+ right: 120,
170
+ bottom: 100
171
+ };
172
+ var blankCRect = {
173
+ left: 0,
174
+ top: 120,
175
+ width: 120,
176
+ height: 40,
177
+ right: 120,
178
+ bottom: 160
179
+ };
180
+ var rects = {
181
+ 'mask-blank-drop-a': blankARect,
182
+ 'mask-blank-drop-b': blankBRect,
183
+ 'mask-blank-drop-c': blankCRect
184
+ };
185
+ var active = {
186
+ data: {
187
+ current: {
188
+ id: 'b',
189
+ fromChoice: false,
190
+ type: 'MaskBlank'
191
+ }
192
+ }
193
+ };
194
+ // Sitting exactly at blank B's own position.
195
+ var currentCoordinates = {
196
+ x: blankBRect.left,
197
+ y: blankBRect.top
198
+ };
199
+ var next = press(rects, currentCoordinates, {
200
+ width: 120,
201
+ height: 40
202
+ }, makeEvent('Tab', true), active);
203
+
204
+ // With B's own slot excluded, Shift+Tab from B's position falls back to
205
+ // nearest-by-dropPosition among the remaining targets (A and C) — A is closer to
206
+ // B's actual position, making A the resolved "current", so reverse from there
207
+ // lands on C. Without the exclusion, containment would match B to itself
208
+ // directly (index 1 of [A, B, C] sorted by position), landing on A instead.
209
+ expect(next).toEqual({
210
+ x: blankCRect.left,
211
+ y: blankCRect.top + blankCRect.height / 2
212
+ });
213
+ });
214
+ it('keeps advancing on repeated Shift+Tab when the choice board is much wider than the dragged item', function () {
215
+ // Regression case for the bug already found and fixed in match-list/image-cloze-
216
+ // association: matching the "current" target by reconstructing a center from the
217
+ // dragged item's own small size (instead of checking which target's rect actually
218
+ // contains it) makes the *next* press re-match a completely different droppable
219
+ // once the item is actually sitting on a wide target, so it looks like the press
220
+ // does nothing.
221
+ var wideBlankRect = {
222
+ left: 0,
223
+ top: 0,
224
+ width: 900,
225
+ height: 40,
226
+ right: 900,
227
+ bottom: 40
228
+ };
229
+ var rects = {
230
+ 'mask-blank-drop-0': wideBlankRect,
231
+ 'drag-in-the-blank-droppable': boardRect
232
+ };
233
+ var itemSize = {
234
+ width: 100,
235
+ height: 40
236
+ };
237
+ var afterFirst = press(rects, {
238
+ x: boardRect.left,
239
+ y: boardRect.top
240
+ }, itemSize, makeEvent('Tab', true));
241
+ expect(afterFirst).toEqual({
242
+ x: 0,
243
+ y: 20
244
+ }); // wide blank's center-left point
245
+
246
+ var afterSecond = press(rects, afterFirst, itemSize, makeEvent('Tab', true));
247
+ expect(afterSecond).toEqual({
248
+ x: boardRect.left,
249
+ y: boardRect.top + boardRect.height / 2
250
+ });
251
+ });
252
+ it('correctly identifies the choice board as the current target when picking up an item positioned near its edge, close to a small neighboring blank', function () {
253
+ // Regression case for the OTHER failure mode: matching "current target" purely by
254
+ // nearest-dropPosition (instead of containment first) can misidentify a large
255
+ // droppable as some small, unrelated nearby one, because a large droppable's
256
+ // dropPosition is anchored at its own vertical middle.
257
+ var tallBoardRect = {
258
+ left: 0,
259
+ top: 0,
260
+ width: 400,
261
+ height: 600,
262
+ right: 400,
263
+ bottom: 600
264
+ };
265
+ var smallBlankRect = {
266
+ left: 0,
267
+ top: -60,
268
+ width: 100,
269
+ height: 40,
270
+ right: 100,
271
+ bottom: -20
272
+ };
273
+ var rects = {
274
+ 'mask-blank-drop-0': smallBlankRect,
275
+ 'drag-in-the-blank-droppable': tallBoardRect
276
+ };
277
+ var itemSize = {
278
+ width: 100,
279
+ height: 40
280
+ };
281
+ var currentCoordinates = {
282
+ x: 0,
283
+ y: 10
284
+ };
285
+ var next = press(rects, currentCoordinates, itemSize, makeEvent('Tab'));
286
+ expect(next).toEqual({
287
+ x: smallBlankRect.left,
288
+ y: smallBlankRect.top + smallBlankRect.height / 2
289
+ });
290
+ });
291
+ it('keeps the choice board as a fixed last stop instead of sorting it in by its own center, when the board spans multiple blank rows', function () {
292
+ // Regression case for a real bug found via manual browser testing: with 3
293
+ // choices stacked beside wrapped inline text (`choicePosition: 'right'`), the
294
+ // tall choice board's own center fell numerically BETWEEN blank 2 and blank 3's
295
+ // rows. Sorting it by position the same way as a blank interleaved it into the
296
+ // middle of the cycle, so the very first Tab press after picking up a pool
297
+ // choice jumped straight to blank 3, skipping blanks 1 and 2 entirely.
298
+ var blank0Rect = {
299
+ left: 0,
300
+ top: 200,
301
+ width: 50,
302
+ height: 50,
303
+ right: 50,
304
+ bottom: 250
305
+ };
306
+ var blank1Rect = {
307
+ left: 0,
308
+ top: 250,
309
+ width: 50,
310
+ height: 50,
311
+ right: 50,
312
+ bottom: 300
313
+ };
314
+ var blank2Rect = {
315
+ left: 0,
316
+ top: 285,
317
+ width: 50,
318
+ height: 50,
319
+ right: 50,
320
+ bottom: 335
321
+ };
322
+ // Spans all three choices stacked beside the text — its center (287.5) falls
323
+ // between blank1's (275) and blank2's (310), more than 10px from either, so the
324
+ // old position-based sort placed it between them.
325
+ var tallBoardRect = {
326
+ left: 400,
327
+ top: 195,
328
+ width: 80,
329
+ height: 185,
330
+ right: 480,
331
+ bottom: 380
332
+ };
333
+ var rects = {
334
+ 'mask-blank-drop-0': blank0Rect,
335
+ 'mask-blank-drop-1': blank1Rect,
336
+ 'mask-blank-drop-2': blank2Rect,
337
+ 'drag-in-the-blank-droppable': tallBoardRect
338
+ };
339
+ var active = {
340
+ data: {
341
+ current: {
342
+ fromChoice: true,
343
+ choice: {
344
+ id: 'x'
345
+ },
346
+ type: 'MaskBlank'
347
+ }
348
+ }
349
+ };
350
+ var itemSize = {
351
+ width: 48,
352
+ height: 50
353
+ };
354
+ // Picking up a choice from within the board — its own current position, before
355
+ // any movement, sits inside the board's rect.
356
+ var currentCoordinates = {
357
+ x: 415,
358
+ y: 205
359
+ };
360
+ var next = press(rects, currentCoordinates, itemSize, makeEvent('Tab'), active);
361
+ expect(next).toEqual({
362
+ x: blank0Rect.left,
363
+ y: blank0Rect.top + blank0Rect.height / 2
364
+ });
365
+ });
366
+ it('cycles through every blank in position order, then the board, then wraps — even when the board would otherwise sort into the middle', function () {
367
+ var blank0Rect = {
368
+ left: 0,
369
+ top: 200,
370
+ width: 50,
371
+ height: 50,
372
+ right: 50,
373
+ bottom: 250
374
+ };
375
+ var blank1Rect = {
376
+ left: 0,
377
+ top: 250,
378
+ width: 50,
379
+ height: 50,
380
+ right: 50,
381
+ bottom: 300
382
+ };
383
+ var blank2Rect = {
384
+ left: 0,
385
+ top: 285,
386
+ width: 50,
387
+ height: 50,
388
+ right: 50,
389
+ bottom: 335
390
+ };
391
+ var tallBoardRect = {
392
+ left: 400,
393
+ top: 195,
394
+ width: 80,
395
+ height: 185,
396
+ right: 480,
397
+ bottom: 380
398
+ };
399
+ var rects = {
400
+ 'mask-blank-drop-0': blank0Rect,
401
+ 'mask-blank-drop-1': blank1Rect,
402
+ 'mask-blank-drop-2': blank2Rect,
403
+ 'drag-in-the-blank-droppable': tallBoardRect
404
+ };
405
+ var active = {
406
+ data: {
407
+ current: {
408
+ fromChoice: true,
409
+ choice: {
410
+ id: 'x'
411
+ },
412
+ type: 'MaskBlank'
413
+ }
414
+ }
415
+ };
416
+ var itemSize = {
417
+ width: 48,
418
+ height: 50
419
+ };
420
+ var coords = {
421
+ x: 415,
422
+ y: 205
423
+ };
424
+ var visited = [];
425
+ for (var i = 0; i < 5; i++) {
426
+ coords = press(rects, coords, itemSize, makeEvent('Tab'), active);
427
+ visited.push(coords);
428
+ }
429
+ expect(visited).toEqual([{
430
+ x: blank0Rect.left,
431
+ y: blank0Rect.top + blank0Rect.height / 2
432
+ }, {
433
+ x: blank1Rect.left,
434
+ y: blank1Rect.top + blank1Rect.height / 2
435
+ }, {
436
+ x: blank2Rect.left,
437
+ y: blank2Rect.top + blank2Rect.height / 2
438
+ }, {
439
+ x: tallBoardRect.left,
440
+ y: tallBoardRect.top + tallBoardRect.height / 2
441
+ }, {
442
+ x: blank0Rect.left,
443
+ y: blank0Rect.top + blank0Rect.height / 2
444
+ } // wraps
445
+ ]);
446
+ });
447
+ });
448
+ });
449
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfY29yZSIsInJlcXVpcmUiLCJfa2V5Ym9hcmRDb29yZGluYXRlcyIsIm93bktleXMiLCJlIiwiciIsInQiLCJPYmplY3QiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwibyIsImZpbHRlciIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsImVudW1lcmFibGUiLCJwdXNoIiwiYXBwbHkiLCJfb2JqZWN0U3ByZWFkIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwiZm9yRWFjaCIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzIiwiZGVmaW5lUHJvcGVydGllcyIsImRlZmluZVByb3BlcnR5IiwicmVjdHNUb0NvbnRleHQiLCJyZWN0cyIsImRyb3BwYWJsZVJlY3RzIiwiTWFwIiwiZW50cmllcyIsImRyb3BwYWJsZUNvbnRhaW5lcnMiLCJtYXAiLCJpZCIsImRpc2FibGVkIiwibWFrZUV2ZW50IiwiY29kZSIsInNoaWZ0S2V5IiwidW5kZWZpbmVkIiwicHJldmVudERlZmF1bHQiLCJwcmVzcyIsImN1cnJlbnRDb29yZGluYXRlcyIsIml0ZW1TaXplIiwiZXZlbnQiLCJhY3RpdmUiLCJjb250ZXh0IiwiY29sbGlzaW9uUmVjdCIsImxlZnQiLCJ4IiwidG9wIiwieSIsImNsb3Nlc3REcm9wcGFibGVLZXlib2FyZENvb3JkaW5hdGVzIiwiZGVzY3JpYmUiLCJpdCIsIndpZHRoIiwiaGVpZ2h0IiwiZXhwZWN0IiwiS2V5Ym9hcmRDb2RlIiwiRG93biIsInRvRXF1YWwiLCJVcCIsIlJpZ2h0IiwiTGVmdCIsImJsYW5rMFJlY3QiLCJyaWdodCIsImJvdHRvbSIsImJsYW5rMVJlY3QiLCJib2FyZFJlY3QiLCJiYXNlUmVjdHMiLCJuZXh0IiwiYmxhbmtBUmVjdCIsImJsYW5rQlJlY3QiLCJibGFua0NSZWN0IiwiZGF0YSIsImN1cnJlbnQiLCJmcm9tQ2hvaWNlIiwidHlwZSIsIndpZGVCbGFua1JlY3QiLCJhZnRlckZpcnN0IiwiYWZ0ZXJTZWNvbmQiLCJ0YWxsQm9hcmRSZWN0Iiwic21hbGxCbGFua1JlY3QiLCJibGFuazJSZWN0IiwiY2hvaWNlIiwiY29vcmRzIiwidmlzaXRlZCIsImkiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvX190ZXN0c19fL2tleWJvYXJkLWNvb3JkaW5hdGVzLnRlc3QuanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgS2V5Ym9hcmRDb2RlIH0gZnJvbSAnQGRuZC1raXQvY29yZSc7XG5pbXBvcnQgeyBjbG9zZXN0RHJvcHBhYmxlS2V5Ym9hcmRDb29yZGluYXRlcyB9IGZyb20gJy4uL2tleWJvYXJkLWNvb3JkaW5hdGVzJztcblxuZnVuY3Rpb24gcmVjdHNUb0NvbnRleHQocmVjdHMpIHtcbiAgY29uc3QgZHJvcHBhYmxlUmVjdHMgPSBuZXcgTWFwKE9iamVjdC5lbnRyaWVzKHJlY3RzKSk7XG4gIGNvbnN0IGRyb3BwYWJsZUNvbnRhaW5lcnMgPSBuZXcgTWFwKE9iamVjdC5rZXlzKHJlY3RzKS5tYXAoKGlkKSA9PiBbaWQsIHsgZGlzYWJsZWQ6IGZhbHNlIH1dKSk7XG5cbiAgcmV0dXJuIHsgZHJvcHBhYmxlUmVjdHMsIGRyb3BwYWJsZUNvbnRhaW5lcnMgfTtcbn1cblxuZnVuY3Rpb24gbWFrZUV2ZW50KGNvZGUsIHNoaWZ0S2V5ID0gZmFsc2UpIHtcbiAgcmV0dXJuIHsgY29kZSwgcHJldmVudERlZmF1bHQ6ICgpID0+IHt9LCBzaGlmdEtleSB9O1xufVxuXG4vLyBNaXJyb3JzIGRuZC1raXQncyBvd24gS2V5Ym9hcmRTZW5zb3IsIHdoaWNoIGFsd2F5cyBkZXJpdmVzIGNvbGxpc2lvblJlY3QncyB0b3AtbGVmdFxuLy8gZnJvbSB0aGUgZHJhZ2dlZCBpdGVtJ3MgY3VycmVudCBvbi1zY3JlZW4gcG9zaXRpb24gb24gZXZlcnkga2V5ZG93biDigJQgc28gYSB0ZXN0J3Ncbi8vIGNvbGxpc2lvblJlY3QgbXVzdCB0cmFjayBjdXJyZW50Q29vcmRpbmF0ZXMgdGhlIHNhbWUgd2F5IG9uIGV2ZXJ5IHNpbXVsYXRlZCBwcmVzcyxcbi8vIG5vdCBzdGF5IGZpeGVkIHdoaWxlIGN1cnJlbnRDb29yZGluYXRlcyBjaGFuZ2VzIGFjcm9zcyBtdWx0aXBsZSBwcmVzc2VzLlxuZnVuY3Rpb24gcHJlc3MocmVjdHMsIGN1cnJlbnRDb29yZGluYXRlcywgaXRlbVNpemUsIGV2ZW50LCBhY3RpdmUpIHtcbiAgY29uc3QgY29udGV4dCA9IHtcbiAgICAuLi5yZWN0c1RvQ29udGV4dChyZWN0cyksXG4gICAgY29sbGlzaW9uUmVjdDogeyBsZWZ0OiBjdXJyZW50Q29vcmRpbmF0ZXMueCwgdG9wOiBjdXJyZW50Q29vcmRpbmF0ZXMueSwgLi4uaXRlbVNpemUgfSxcbiAgfTtcblxuICByZXR1cm4gY2xvc2VzdERyb3BwYWJsZUtleWJvYXJkQ29vcmRpbmF0ZXMoZXZlbnQsIHsgYWN0aXZlLCBjb250ZXh0LCBjdXJyZW50Q29vcmRpbmF0ZXMgfSk7XG59XG5cbmRlc2NyaWJlKCdjbG9zZXN0RHJvcHBhYmxlS2V5Ym9hcmRDb29yZGluYXRlcycsICgpID0+IHtcbiAgZGVzY3JpYmUoJ2Fycm93IGtleXMnLCAoKSA9PiB7XG4gICAgaXQoXCJudWRnZXMgdGhlIGRyYWdnZWQgaXRlbSBieSBkbmQta2l0J3Mgb3duIGRlZmF1bHQgc3RlcCAoMjVweCksIHVuY2hhbmdlZFwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBjb250ZXh0ID0geyAuLi5yZWN0c1RvQ29udGV4dCh7fSksIGNvbGxpc2lvblJlY3Q6IHsgbGVmdDogMCwgdG9wOiAwLCB3aWR0aDogMTAwLCBoZWlnaHQ6IDQwIH0gfTtcbiAgICAgIGNvbnN0IGN1cnJlbnRDb29yZGluYXRlcyA9IHsgeDogMTAsIHk6IDIwIH07XG5cbiAgICAgIGV4cGVjdChcbiAgICAgICAgY2xvc2VzdERyb3BwYWJsZUtleWJvYXJkQ29vcmRpbmF0ZXMobWFrZUV2ZW50KEtleWJvYXJkQ29kZS5Eb3duKSwgeyBjb250ZXh0LCBjdXJyZW50Q29vcmRpbmF0ZXMgfSksXG4gICAgICApLnRvRXF1YWwoeyB4OiAxMCwgeTogNDUgfSk7XG4gICAgICBleHBlY3QoXG4gICAgICAgIGNsb3Nlc3REcm9wcGFibGVLZXlib2FyZENvb3JkaW5hdGVzKG1ha2VFdmVudChLZXlib2FyZENvZGUuVXApLCB7IGNvbnRleHQsIGN1cnJlbnRDb29yZGluYXRlcyB9KSxcbiAgICAgICkudG9FcXVhbCh7IHg6IDEwLCB5OiAtNSB9KTtcbiAgICAgIGV4cGVjdChcbiAgICAgICAgY2xvc2VzdERyb3BwYWJsZUtleWJvYXJkQ29vcmRpbmF0ZXMobWFrZUV2ZW50KEtleWJvYXJkQ29kZS5SaWdodCksIHsgY29udGV4dCwgY3VycmVudENvb3JkaW5hdGVzIH0pLFxuICAgICAgKS50b0VxdWFsKHsgeDogMzUsIHk6IDIwIH0pO1xuICAgICAgZXhwZWN0KFxuICAgICAgICBjbG9zZXN0RHJvcHBhYmxlS2V5Ym9hcmRDb29yZGluYXRlcyhtYWtlRXZlbnQoS2V5Ym9hcmRDb2RlLkxlZnQpLCB7IGNvbnRleHQsIGN1cnJlbnRDb29yZGluYXRlcyB9KSxcbiAgICAgICkudG9FcXVhbCh7IHg6IC0xNSwgeTogMjAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUYWIgLyBTaGlmdCtUYWInLCAoKSA9PiB7XG4gICAgY29uc3QgYmxhbmswUmVjdCA9IHsgbGVmdDogMCwgdG9wOiAwLCB3aWR0aDogMTIwLCBoZWlnaHQ6IDQwLCByaWdodDogMTIwLCBib3R0b206IDQwIH07XG4gICAgY29uc3QgYmxhbmsxUmVjdCA9IHsgbGVmdDogMCwgdG9wOiA2MCwgd2lkdGg6IDEyMCwgaGVpZ2h0OiA0MCwgcmlnaHQ6IDEyMCwgYm90dG9tOiAxMDAgfTtcbiAgICBjb25zdCBib2FyZFJlY3QgPSB7IGxlZnQ6IDAsIHRvcDogMTIwLCB3aWR0aDogNDAwLCBoZWlnaHQ6IDMwMCwgcmlnaHQ6IDQwMCwgYm90dG9tOiA0MjAgfTtcbiAgICBjb25zdCBiYXNlUmVjdHMgPSB7XG4gICAgICAnbWFzay1ibGFuay1kcm9wLTAnOiBibGFuazBSZWN0LFxuICAgICAgJ21hc2stYmxhbmstZHJvcC0xJzogYmxhbmsxUmVjdCxcbiAgICAgICdkcmFnLWluLXRoZS1ibGFuay1kcm9wcGFibGUnOiBib2FyZFJlY3QsXG4gICAgfTtcblxuICAgIGl0KCdqdW1wcyB0byB0aGUgbmV4dCBkcm9wcGFibGUgaW4gdG9wLXRvLWJvdHRvbSBvcmRlciwgbGFuZGluZyBhdCBpdHMgY2VudGVyLWxlZnQgcG9pbnQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBjdXJyZW50Q29vcmRpbmF0ZXMgPSB7IHg6IGJsYW5rMFJlY3QubGVmdCwgeTogYmxhbmswUmVjdC50b3AgfTtcblxuICAgICAgY29uc3QgbmV4dCA9IHByZXNzKGJhc2VSZWN0cywgY3VycmVudENvb3JkaW5hdGVzLCB7IHdpZHRoOiAxMjAsIGhlaWdodDogNDAgfSwgbWFrZUV2ZW50KCdUYWInKSk7XG5cbiAgICAgIGV4cGVjdChuZXh0KS50b0VxdWFsKHsgeDogYmxhbmsxUmVjdC5sZWZ0LCB5OiBibGFuazFSZWN0LnRvcCArIGJsYW5rMVJlY3QuaGVpZ2h0IC8gMiB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdjeWNsZXMgYmFja3dhcmRzIHdpdGggU2hpZnQrVGFiLCB3cmFwcGluZyB0byB0aGUgY2hvaWNlIGJvYXJkJywgKCkgPT4ge1xuICAgICAgY29uc3QgY3VycmVudENvb3JkaW5hdGVzID0geyB4OiBibGFuazBSZWN0LmxlZnQsIHk6IGJsYW5rMFJlY3QudG9wIH07XG5cbiAgICAgIGNvbnN0IG5leHQgPSBwcmVzcyhiYXNlUmVjdHMsIGN1cnJlbnRDb29yZGluYXRlcywgeyB3aWR0aDogMTIwLCBoZWlnaHQ6IDQwIH0sIG1ha2VFdmVudCgnVGFiJywgdHJ1ZSkpO1xuXG4gICAgICBleHBlY3QobmV4dCkudG9FcXVhbCh7IHg6IGJvYXJkUmVjdC5sZWZ0LCB5OiBib2FyZFJlY3QudG9wICsgYm9hcmRSZWN0LmhlaWdodCAvIDIgfSk7XG4gICAgfSk7XG5cbiAgICBpdChcImV4Y2x1ZGVzIGEgZHJhZ2dlZCBibGFuaydzIG93biBkcm9wLXpvbmUgZnJvbSB0aGUgY3ljbGVcIiwgKCkgPT4ge1xuICAgICAgLy8gQSBibGFuayBpcyBzaW11bHRhbmVvdXNseSBkcmFnZ2FibGUgYW5kIGRyb3BwYWJsZSBmb3IgaXRzIG93biBzbG90ICh0aGUgc2FtZVxuICAgICAgLy8gc2hhcGUgYXMgbWF0Y2gtbGlzdCdzIHBsYWNlZCBcInRhcmdldFwiIHRpbGVzKS4gV2l0aG91dCBleGNsdWRpbmcgaXQsIGNvbnRhaW5tZW50XG4gICAgICAvLyB3b3VsZCBtYXRjaCB0aGUgYmxhbmsgdG8gaXRzZWxmIGFuZCBjeWNsZSByZWxhdGl2ZSB0byBpdHNlbGYgaW5zdGVhZCBvZiBpdHNcbiAgICAgIC8vIHJlYWwgbmVpZ2hib3JzIOKAlCB0aGlzIHRlc3QgaXMgY29uc3RydWN0ZWQgc28gdGhlIHR3byBiZWhhdmlvcnMgZ2l2ZSBkaWZmZXJlbnQsXG4gICAgICAvLyBkaXN0aW5ndWlzaGFibGUgcmVzdWx0cyAobm90IGp1c3QgY29pbmNpZGVudGFsbHkgdGhlIHNhbWUgYW5zd2VyKS5cbiAgICAgIGNvbnN0IGJsYW5rQVJlY3QgPSB7IGxlZnQ6IDAsIHRvcDogMCwgd2lkdGg6IDEyMCwgaGVpZ2h0OiA0MCwgcmlnaHQ6IDEyMCwgYm90dG9tOiA0MCB9O1xuICAgICAgY29uc3QgYmxhbmtCUmVjdCA9IHsgbGVmdDogMCwgdG9wOiA2MCwgd2lkdGg6IDEyMCwgaGVpZ2h0OiA0MCwgcmlnaHQ6IDEyMCwgYm90dG9tOiAxMDAgfTtcbiAgICAgIGNvbnN0IGJsYW5rQ1JlY3QgPSB7IGxlZnQ6IDAsIHRvcDogMTIwLCB3aWR0aDogMTIwLCBoZWlnaHQ6IDQwLCByaWdodDogMTIwLCBib3R0b206IDE2MCB9O1xuICAgICAgY29uc3QgcmVjdHMgPSB7XG4gICAgICAgICdtYXNrLWJsYW5rLWRyb3AtYSc6IGJsYW5rQVJlY3QsXG4gICAgICAgICdtYXNrLWJsYW5rLWRyb3AtYic6IGJsYW5rQlJlY3QsXG4gICAgICAgICdtYXNrLWJsYW5rLWRyb3AtYyc6IGJsYW5rQ1JlY3QsXG4gICAgICB9O1xuICAgICAgY29uc3QgYWN0aXZlID0geyBkYXRhOiB7IGN1cnJlbnQ6IHsgaWQ6ICdiJywgZnJvbUNob2ljZTogZmFsc2UsIHR5cGU6ICdNYXNrQmxhbmsnIH0gfSB9O1xuICAgICAgLy8gU2l0dGluZyBleGFjdGx5IGF0IGJsYW5rIEIncyBvd24gcG9zaXRpb24uXG4gICAgICBjb25zdCBjdXJyZW50Q29vcmRpbmF0ZXMgPSB7IHg6IGJsYW5rQlJlY3QubGVmdCwgeTogYmxhbmtCUmVjdC50b3AgfTtcblxuICAgICAgY29uc3QgbmV4dCA9IHByZXNzKHJlY3RzLCBjdXJyZW50Q29vcmRpbmF0ZXMsIHsgd2lkdGg6IDEyMCwgaGVpZ2h0OiA0MCB9LCBtYWtlRXZlbnQoJ1RhYicsIHRydWUpLCBhY3RpdmUpO1xuXG4gICAgICAvLyBXaXRoIEIncyBvd24gc2xvdCBleGNsdWRlZCwgU2hpZnQrVGFiIGZyb20gQidzIHBvc2l0aW9uIGZhbGxzIGJhY2sgdG9cbiAgICAgIC8vIG5lYXJlc3QtYnktZHJvcFBvc2l0aW9uIGFtb25nIHRoZSByZW1haW5pbmcgdGFyZ2V0cyAoQSBhbmQgQykg4oCUIEEgaXMgY2xvc2VyIHRvXG4gICAgICAvLyBCJ3MgYWN0dWFsIHBvc2l0aW9uLCBtYWtpbmcgQSB0aGUgcmVzb2x2ZWQgXCJjdXJyZW50XCIsIHNvIHJldmVyc2UgZnJvbSB0aGVyZVxuICAgICAgLy8gbGFuZHMgb24gQy4gV2l0aG91dCB0aGUgZXhjbHVzaW9uLCBjb250YWlubWVudCB3b3VsZCBtYXRjaCBCIHRvIGl0c2VsZlxuICAgICAgLy8gZGlyZWN0bHkgKGluZGV4IDEgb2YgW0EsIEIsIENdIHNvcnRlZCBieSBwb3NpdGlvbiksIGxhbmRpbmcgb24gQSBpbnN0ZWFkLlxuICAgICAgZXhwZWN0KG5leHQpLnRvRXF1YWwoeyB4OiBibGFua0NSZWN0LmxlZnQsIHk6IGJsYW5rQ1JlY3QudG9wICsgYmxhbmtDUmVjdC5oZWlnaHQgLyAyIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ2tlZXBzIGFkdmFuY2luZyBvbiByZXBlYXRlZCBTaGlmdCtUYWIgd2hlbiB0aGUgY2hvaWNlIGJvYXJkIGlzIG11Y2ggd2lkZXIgdGhhbiB0aGUgZHJhZ2dlZCBpdGVtJywgKCkgPT4ge1xuICAgICAgLy8gUmVncmVzc2lvbiBjYXNlIGZvciB0aGUgYnVnIGFscmVhZHkgZm91bmQgYW5kIGZpeGVkIGluIG1hdGNoLWxpc3QvaW1hZ2UtY2xvemUtXG4gICAgICAvLyBhc3NvY2lhdGlvbjogbWF0Y2hpbmcgdGhlIFwiY3VycmVudFwiIHRhcmdldCBieSByZWNvbnN0cnVjdGluZyBhIGNlbnRlciBmcm9tIHRoZVxuICAgICAgLy8gZHJhZ2dlZCBpdGVtJ3Mgb3duIHNtYWxsIHNpemUgKGluc3RlYWQgb2YgY2hlY2tpbmcgd2hpY2ggdGFyZ2V0J3MgcmVjdCBhY3R1YWxseVxuICAgICAgLy8gY29udGFpbnMgaXQpIG1ha2VzIHRoZSAqbmV4dCogcHJlc3MgcmUtbWF0Y2ggYSBjb21wbGV0ZWx5IGRpZmZlcmVudCBkcm9wcGFibGVcbiAgICAgIC8vIG9uY2UgdGhlIGl0ZW0gaXMgYWN0dWFsbHkgc2l0dGluZyBvbiBhIHdpZGUgdGFyZ2V0LCBzbyBpdCBsb29rcyBsaWtlIHRoZSBwcmVzc1xuICAgICAgLy8gZG9lcyBub3RoaW5nLlxuICAgICAgY29uc3Qgd2lkZUJsYW5rUmVjdCA9IHsgbGVmdDogMCwgdG9wOiAwLCB3aWR0aDogOTAwLCBoZWlnaHQ6IDQwLCByaWdodDogOTAwLCBib3R0b206IDQwIH07XG4gICAgICBjb25zdCByZWN0cyA9IHsgJ21hc2stYmxhbmstZHJvcC0wJzogd2lkZUJsYW5rUmVjdCwgJ2RyYWctaW4tdGhlLWJsYW5rLWRyb3BwYWJsZSc6IGJvYXJkUmVjdCB9O1xuICAgICAgY29uc3QgaXRlbVNpemUgPSB7IHdpZHRoOiAxMDAsIGhlaWdodDogNDAgfTtcblxuICAgICAgY29uc3QgYWZ0ZXJGaXJzdCA9IHByZXNzKHJlY3RzLCB7IHg6IGJvYXJkUmVjdC5sZWZ0LCB5OiBib2FyZFJlY3QudG9wIH0sIGl0ZW1TaXplLCBtYWtlRXZlbnQoJ1RhYicsIHRydWUpKTtcblxuICAgICAgZXhwZWN0KGFmdGVyRmlyc3QpLnRvRXF1YWwoeyB4OiAwLCB5OiAyMCB9KTsgLy8gd2lkZSBibGFuaydzIGNlbnRlci1sZWZ0IHBvaW50XG5cbiAgICAgIGNvbnN0IGFmdGVyU2Vjb25kID0gcHJlc3MocmVjdHMsIGFmdGVyRmlyc3QsIGl0ZW1TaXplLCBtYWtlRXZlbnQoJ1RhYicsIHRydWUpKTtcblxuICAgICAgZXhwZWN0KGFmdGVyU2Vjb25kKS50b0VxdWFsKHsgeDogYm9hcmRSZWN0LmxlZnQsIHk6IGJvYXJkUmVjdC50b3AgKyBib2FyZFJlY3QuaGVpZ2h0IC8gMiB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdjb3JyZWN0bHkgaWRlbnRpZmllcyB0aGUgY2hvaWNlIGJvYXJkIGFzIHRoZSBjdXJyZW50IHRhcmdldCB3aGVuIHBpY2tpbmcgdXAgYW4gaXRlbSBwb3NpdGlvbmVkIG5lYXIgaXRzIGVkZ2UsIGNsb3NlIHRvIGEgc21hbGwgbmVpZ2hib3JpbmcgYmxhbmsnLCAoKSA9PiB7XG4gICAgICAvLyBSZWdyZXNzaW9uIGNhc2UgZm9yIHRoZSBPVEhFUiBmYWlsdXJlIG1vZGU6IG1hdGNoaW5nIFwiY3VycmVudCB0YXJnZXRcIiBwdXJlbHkgYnlcbiAgICAgIC8vIG5lYXJlc3QtZHJvcFBvc2l0aW9uIChpbnN0ZWFkIG9mIGNvbnRhaW5tZW50IGZpcnN0KSBjYW4gbWlzaWRlbnRpZnkgYSBsYXJnZVxuICAgICAgLy8gZHJvcHBhYmxlIGFzIHNvbWUgc21hbGwsIHVucmVsYXRlZCBuZWFyYnkgb25lLCBiZWNhdXNlIGEgbGFyZ2UgZHJvcHBhYmxlJ3NcbiAgICAgIC8vIGRyb3BQb3NpdGlvbiBpcyBhbmNob3JlZCBhdCBpdHMgb3duIHZlcnRpY2FsIG1pZGRsZS5cbiAgICAgIGNvbnN0IHRhbGxCb2FyZFJlY3QgPSB7IGxlZnQ6IDAsIHRvcDogMCwgd2lkdGg6IDQwMCwgaGVpZ2h0OiA2MDAsIHJpZ2h0OiA0MDAsIGJvdHRvbTogNjAwIH07XG4gICAgICBjb25zdCBzbWFsbEJsYW5rUmVjdCA9IHsgbGVmdDogMCwgdG9wOiAtNjAsIHdpZHRoOiAxMDAsIGhlaWdodDogNDAsIHJpZ2h0OiAxMDAsIGJvdHRvbTogLTIwIH07XG4gICAgICBjb25zdCByZWN0cyA9IHsgJ21hc2stYmxhbmstZHJvcC0wJzogc21hbGxCbGFua1JlY3QsICdkcmFnLWluLXRoZS1ibGFuay1kcm9wcGFibGUnOiB0YWxsQm9hcmRSZWN0IH07XG4gICAgICBjb25zdCBpdGVtU2l6ZSA9IHsgd2lkdGg6IDEwMCwgaGVpZ2h0OiA0MCB9O1xuXG4gICAgICBjb25zdCBjdXJyZW50Q29vcmRpbmF0ZXMgPSB7IHg6IDAsIHk6IDEwIH07XG5cbiAgICAgIGNvbnN0IG5leHQgPSBwcmVzcyhyZWN0cywgY3VycmVudENvb3JkaW5hdGVzLCBpdGVtU2l6ZSwgbWFrZUV2ZW50KCdUYWInKSk7XG5cbiAgICAgIGV4cGVjdChuZXh0KS50b0VxdWFsKHsgeDogc21hbGxCbGFua1JlY3QubGVmdCwgeTogc21hbGxCbGFua1JlY3QudG9wICsgc21hbGxCbGFua1JlY3QuaGVpZ2h0IC8gMiB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdrZWVwcyB0aGUgY2hvaWNlIGJvYXJkIGFzIGEgZml4ZWQgbGFzdCBzdG9wIGluc3RlYWQgb2Ygc29ydGluZyBpdCBpbiBieSBpdHMgb3duIGNlbnRlciwgd2hlbiB0aGUgYm9hcmQgc3BhbnMgbXVsdGlwbGUgYmxhbmsgcm93cycsICgpID0+IHtcbiAgICAgIC8vIFJlZ3Jlc3Npb24gY2FzZSBmb3IgYSByZWFsIGJ1ZyBmb3VuZCB2aWEgbWFudWFsIGJyb3dzZXIgdGVzdGluZzogd2l0aCAzXG4gICAgICAvLyBjaG9pY2VzIHN0YWNrZWQgYmVzaWRlIHdyYXBwZWQgaW5saW5lIHRleHQgKGBjaG9pY2VQb3NpdGlvbjogJ3JpZ2h0J2ApLCB0aGVcbiAgICAgIC8vIHRhbGwgY2hvaWNlIGJvYXJkJ3Mgb3duIGNlbnRlciBmZWxsIG51bWVyaWNhbGx5IEJFVFdFRU4gYmxhbmsgMiBhbmQgYmxhbmsgMydzXG4gICAgICAvLyByb3dzLiBTb3J0aW5nIGl0IGJ5IHBvc2l0aW9uIHRoZSBzYW1lIHdheSBhcyBhIGJsYW5rIGludGVybGVhdmVkIGl0IGludG8gdGhlXG4gICAgICAvLyBtaWRkbGUgb2YgdGhlIGN5Y2xlLCBzbyB0aGUgdmVyeSBmaXJzdCBUYWIgcHJlc3MgYWZ0ZXIgcGlja2luZyB1cCBhIHBvb2xcbiAgICAgIC8vIGNob2ljZSBqdW1wZWQgc3RyYWlnaHQgdG8gYmxhbmsgMywgc2tpcHBpbmcgYmxhbmtzIDEgYW5kIDIgZW50aXJlbHkuXG4gICAgICBjb25zdCBibGFuazBSZWN0ID0geyBsZWZ0OiAwLCB0b3A6IDIwMCwgd2lkdGg6IDUwLCBoZWlnaHQ6IDUwLCByaWdodDogNTAsIGJvdHRvbTogMjUwIH07XG4gICAgICBjb25zdCBibGFuazFSZWN0ID0geyBsZWZ0OiAwLCB0b3A6IDI1MCwgd2lkdGg6IDUwLCBoZWlnaHQ6IDUwLCByaWdodDogNTAsIGJvdHRvbTogMzAwIH07XG4gICAgICBjb25zdCBibGFuazJSZWN0ID0geyBsZWZ0OiAwLCB0b3A6IDI4NSwgd2lkdGg6IDUwLCBoZWlnaHQ6IDUwLCByaWdodDogNTAsIGJvdHRvbTogMzM1IH07XG4gICAgICAvLyBTcGFucyBhbGwgdGhyZWUgY2hvaWNlcyBzdGFja2VkIGJlc2lkZSB0aGUgdGV4dCDigJQgaXRzIGNlbnRlciAoMjg3LjUpIGZhbGxzXG4gICAgICAvLyBiZXR3ZWVuIGJsYW5rMSdzICgyNzUpIGFuZCBibGFuazIncyAoMzEwKSwgbW9yZSB0aGFuIDEwcHggZnJvbSBlaXRoZXIsIHNvIHRoZVxuICAgICAgLy8gb2xkIHBvc2l0aW9uLWJhc2VkIHNvcnQgcGxhY2VkIGl0IGJldHdlZW4gdGhlbS5cbiAgICAgIGNvbnN0IHRhbGxCb2FyZFJlY3QgPSB7IGxlZnQ6IDQwMCwgdG9wOiAxOTUsIHdpZHRoOiA4MCwgaGVpZ2h0OiAxODUsIHJpZ2h0OiA0ODAsIGJvdHRvbTogMzgwIH07XG4gICAgICBjb25zdCByZWN0cyA9IHtcbiAgICAgICAgJ21hc2stYmxhbmstZHJvcC0wJzogYmxhbmswUmVjdCxcbiAgICAgICAgJ21hc2stYmxhbmstZHJvcC0xJzogYmxhbmsxUmVjdCxcbiAgICAgICAgJ21hc2stYmxhbmstZHJvcC0yJzogYmxhbmsyUmVjdCxcbiAgICAgICAgJ2RyYWctaW4tdGhlLWJsYW5rLWRyb3BwYWJsZSc6IHRhbGxCb2FyZFJlY3QsXG4gICAgICB9O1xuICAgICAgY29uc3QgYWN0aXZlID0geyBkYXRhOiB7IGN1cnJlbnQ6IHsgZnJvbUNob2ljZTogdHJ1ZSwgY2hvaWNlOiB7IGlkOiAneCcgfSwgdHlwZTogJ01hc2tCbGFuaycgfSB9IH07XG4gICAgICBjb25zdCBpdGVtU2l6ZSA9IHsgd2lkdGg6IDQ4LCBoZWlnaHQ6IDUwIH07XG4gICAgICAvLyBQaWNraW5nIHVwIGEgY2hvaWNlIGZyb20gd2l0aGluIHRoZSBib2FyZCDigJQgaXRzIG93biBjdXJyZW50IHBvc2l0aW9uLCBiZWZvcmVcbiAgICAgIC8vIGFueSBtb3ZlbWVudCwgc2l0cyBpbnNpZGUgdGhlIGJvYXJkJ3MgcmVjdC5cbiAgICAgIGNvbnN0IGN1cnJlbnRDb29yZGluYXRlcyA9IHsgeDogNDE1LCB5OiAyMDUgfTtcblxuICAgICAgY29uc3QgbmV4dCA9IHByZXNzKHJlY3RzLCBjdXJyZW50Q29vcmRpbmF0ZXMsIGl0ZW1TaXplLCBtYWtlRXZlbnQoJ1RhYicpLCBhY3RpdmUpO1xuXG4gICAgICBleHBlY3QobmV4dCkudG9FcXVhbCh7IHg6IGJsYW5rMFJlY3QubGVmdCwgeTogYmxhbmswUmVjdC50b3AgKyBibGFuazBSZWN0LmhlaWdodCAvIDIgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnY3ljbGVzIHRocm91Z2ggZXZlcnkgYmxhbmsgaW4gcG9zaXRpb24gb3JkZXIsIHRoZW4gdGhlIGJvYXJkLCB0aGVuIHdyYXBzIOKAlCBldmVuIHdoZW4gdGhlIGJvYXJkIHdvdWxkIG90aGVyd2lzZSBzb3J0IGludG8gdGhlIG1pZGRsZScsICgpID0+IHtcbiAgICAgIGNvbnN0IGJsYW5rMFJlY3QgPSB7IGxlZnQ6IDAsIHRvcDogMjAwLCB3aWR0aDogNTAsIGhlaWdodDogNTAsIHJpZ2h0OiA1MCwgYm90dG9tOiAyNTAgfTtcbiAgICAgIGNvbnN0IGJsYW5rMVJlY3QgPSB7IGxlZnQ6IDAsIHRvcDogMjUwLCB3aWR0aDogNTAsIGhlaWdodDogNTAsIHJpZ2h0OiA1MCwgYm90dG9tOiAzMDAgfTtcbiAgICAgIGNvbnN0IGJsYW5rMlJlY3QgPSB7IGxlZnQ6IDAsIHRvcDogMjg1LCB3aWR0aDogNTAsIGhlaWdodDogNTAsIHJpZ2h0OiA1MCwgYm90dG9tOiAzMzUgfTtcbiAgICAgIGNvbnN0IHRhbGxCb2FyZFJlY3QgPSB7IGxlZnQ6IDQwMCwgdG9wOiAxOTUsIHdpZHRoOiA4MCwgaGVpZ2h0OiAxODUsIHJpZ2h0OiA0ODAsIGJvdHRvbTogMzgwIH07XG4gICAgICBjb25zdCByZWN0cyA9IHtcbiAgICAgICAgJ21hc2stYmxhbmstZHJvcC0wJzogYmxhbmswUmVjdCxcbiAgICAgICAgJ21hc2stYmxhbmstZHJvcC0xJzogYmxhbmsxUmVjdCxcbiAgICAgICAgJ21hc2stYmxhbmstZHJvcC0yJzogYmxhbmsyUmVjdCxcbiAgICAgICAgJ2RyYWctaW4tdGhlLWJsYW5rLWRyb3BwYWJsZSc6IHRhbGxCb2FyZFJlY3QsXG4gICAgICB9O1xuICAgICAgY29uc3QgYWN0aXZlID0geyBkYXRhOiB7IGN1cnJlbnQ6IHsgZnJvbUNob2ljZTogdHJ1ZSwgY2hvaWNlOiB7IGlkOiAneCcgfSwgdHlwZTogJ01hc2tCbGFuaycgfSB9IH07XG4gICAgICBjb25zdCBpdGVtU2l6ZSA9IHsgd2lkdGg6IDQ4LCBoZWlnaHQ6IDUwIH07XG5cbiAgICAgIGxldCBjb29yZHMgPSB7IHg6IDQxNSwgeTogMjA1IH07XG4gICAgICBjb25zdCB2aXNpdGVkID0gW107XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNTsgaSsrKSB7XG4gICAgICAgIGNvb3JkcyA9IHByZXNzKHJlY3RzLCBjb29yZHMsIGl0ZW1TaXplLCBtYWtlRXZlbnQoJ1RhYicpLCBhY3RpdmUpO1xuICAgICAgICB2aXNpdGVkLnB1c2goY29vcmRzKTtcbiAgICAgIH1cblxuICAgICAgZXhwZWN0KHZpc2l0ZWQpLnRvRXF1YWwoW1xuICAgICAgICB7IHg6IGJsYW5rMFJlY3QubGVmdCwgeTogYmxhbmswUmVjdC50b3AgKyBibGFuazBSZWN0LmhlaWdodCAvIDIgfSxcbiAgICAgICAgeyB4OiBibGFuazFSZWN0LmxlZnQsIHk6IGJsYW5rMVJlY3QudG9wICsgYmxhbmsxUmVjdC5oZWlnaHQgLyAyIH0sXG4gICAgICAgIHsgeDogYmxhbmsyUmVjdC5sZWZ0LCB5OiBibGFuazJSZWN0LnRvcCArIGJsYW5rMlJlY3QuaGVpZ2h0IC8gMiB9LFxuICAgICAgICB7IHg6IHRhbGxCb2FyZFJlY3QubGVmdCwgeTogdGFsbEJvYXJkUmVjdC50b3AgKyB0YWxsQm9hcmRSZWN0LmhlaWdodCAvIDIgfSxcbiAgICAgICAgeyB4OiBibGFuazBSZWN0LmxlZnQsIHk6IGJsYW5rMFJlY3QudG9wICsgYmxhbmswUmVjdC5oZWlnaHQgLyAyIH0sIC8vIHdyYXBzXG4gICAgICBdKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLElBQUFBLEtBQUEsR0FBQUMsT0FBQTtBQUNBLElBQUFDLG9CQUFBLEdBQUFELE9BQUE7QUFBOEUsU0FBQUUsUUFBQUMsQ0FBQSxFQUFBQyxDQUFBLFFBQUFDLENBQUEsR0FBQUMsTUFBQSxDQUFBQyxJQUFBLENBQUFKLENBQUEsT0FBQUcsTUFBQSxDQUFBRSxxQkFBQSxRQUFBQyxDQUFBLEdBQUFILE1BQUEsQ0FBQUUscUJBQUEsQ0FBQUwsQ0FBQSxHQUFBQyxDQUFBLEtBQUFLLENBQUEsR0FBQUEsQ0FBQSxDQUFBQyxNQUFBLFdBQUFOLENB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