wiki 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/README.md +10 -2
  4. data/bin/wiki +4 -0
  5. data/default-data/pages/how-to-wiki +1069 -0
  6. data/default-data/pages/welcome-visitors +336 -0
  7. data/default-data/status/favicon.png +0 -0
  8. data/default-data/status/local-identity +7 -0
  9. data/lib/wiki/favicon.rb +0 -1
  10. data/lib/wiki/page.rb +3 -6
  11. data/lib/wiki/server.rb +7 -3
  12. data/lib/wiki/version.rb +1 -1
  13. data/package.json +70 -0
  14. data/wiki.gemspec +20 -13
  15. metadata +205 -58
  16. data/lib/wiki/views/client/Gruntfile.js +0 -50
  17. data/lib/wiki/views/client/ReadMe.md +0 -67
  18. data/lib/wiki/views/client/build-test.bat +0 -10
  19. data/lib/wiki/views/client/build.bat +0 -8
  20. data/lib/wiki/views/client/builder.pl +0 -41
  21. data/lib/wiki/views/client/client.coffee +0 -3
  22. data/lib/wiki/views/client/client.js +0 -3607
  23. data/lib/wiki/views/client/crosses.png +0 -0
  24. data/lib/wiki/views/client/images/external-link-ltr-icon.png +0 -0
  25. data/lib/wiki/views/client/images/noise.png +0 -0
  26. data/lib/wiki/views/client/images/oops.jpg +0 -0
  27. data/lib/wiki/views/client/js/d3/d3.behavior.js +0 -198
  28. data/lib/wiki/views/client/js/d3/d3.chart.js +0 -984
  29. data/lib/wiki/views/client/js/d3/d3.csv.js +0 -92
  30. data/lib/wiki/views/client/js/d3/d3.geo.js +0 -566
  31. data/lib/wiki/views/client/js/d3/d3.geom.js +0 -825
  32. data/lib/wiki/views/client/js/d3/d3.js +0 -3597
  33. data/lib/wiki/views/client/js/d3/d3.layout.js +0 -1923
  34. data/lib/wiki/views/client/js/d3/d3.time.js +0 -660
  35. data/lib/wiki/views/client/js/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  36. data/lib/wiki/views/client/js/images/ui-icons_222222_256x240.png +0 -0
  37. data/lib/wiki/views/client/js/jquery-1.6.2.min.js +0 -18
  38. data/lib/wiki/views/client/js/jquery-1.7.1.min.js +0 -4
  39. data/lib/wiki/views/client/js/jquery-1.9.1.min.js +0 -5
  40. data/lib/wiki/views/client/js/jquery-migrate-1.1.1.min.js +0 -3
  41. data/lib/wiki/views/client/js/jquery-ui-1.10.1.custom.min.css +0 -5
  42. data/lib/wiki/views/client/js/jquery-ui-1.10.1.custom.min.js +0 -6
  43. data/lib/wiki/views/client/js/jquery-ui-1.8.16.custom.css +0 -339
  44. data/lib/wiki/views/client/js/jquery-ui-1.8.16.custom.min.js +0 -315
  45. data/lib/wiki/views/client/js/jquery.ie.cors.js +0 -310
  46. data/lib/wiki/views/client/js/jquery.ui.touch-punch.min.js +0 -11
  47. data/lib/wiki/views/client/js/modernizr.custom.63710.js +0 -824
  48. data/lib/wiki/views/client/js/sockjs-0.3.min.js +0 -27
  49. data/lib/wiki/views/client/js/underscore-min.js +0 -30
  50. data/lib/wiki/views/client/mkplugin.sh +0 -97
  51. data/lib/wiki/views/client/package.json +0 -36
  52. data/lib/wiki/views/client/runtests.html +0 -26
  53. data/lib/wiki/views/client/style.css +0 -339
  54. data/lib/wiki/views/client/test/mocha.css +0 -231
  55. data/lib/wiki/views/client/test/mocha.js +0 -5340
  56. data/lib/wiki/views/client/test/testclient.js +0 -17133
  57. data/lib/wiki/views/client/testclient.coffee +0 -18
  58. data/lib/wiki/views/client/theme/granite.css +0 -59
  59. data/lib/wiki/views/client/theme/stoneSeamless.jpg +0 -0
  60. data/lib/wiki/views/client/twitter-maintainance.jpg +0 -0
@@ -1,10 +0,0 @@
1
- @ECHO OFF
2
- ::
3
- :: Used on Windows to build testclient.js as npm start and test don't work!
4
- ::
5
-
6
- :: Build testclient.js - need to expand .\plugins\*\test.coffee as wildcard does not work on Windows
7
-
8
- echo "Building test\testclient.js"
9
-
10
- .\node_modules\.bin\browserify.cmd testclient.coffee .\plugins\calendar\test.coffee .\plugins\changes\test.coffee .\plugins\efficiency\test.coffee .\plugins\report\test.coffee .\plugins\txtzyme\test.coffee -o test\testclient.js
@@ -1,8 +0,0 @@
1
- @ECHO OFF
2
- ::
3
- :: Used on Windows to build client.js as npm start and test don't work!
4
- ::
5
-
6
- echo "Building client.js"
7
-
8
- .\node_modules\.bin\browserify.cmd client.coffee -o client.js
@@ -1,41 +0,0 @@
1
- #!/usr/bin/perl
2
-
3
- #this script exists because the browserify -w option does not appear to work?
4
-
5
- my ($old, $new);
6
- my $OSXsay = ($^O eq 'darwin');
7
-
8
- sub say {
9
- my $msg = shift;
10
- if ($OSXsay) {
11
- `say $msg&`;
12
- }
13
- print $msg."\n";
14
- }
15
- sub run {
16
- $trouble = `($_[0] || echo 'failed to run') 2>&1`;
17
- return unless $trouble;
18
- if ($trouble =~ /( on line \d+)/) {
19
- say("having trouble $1.");
20
- print "\n$_[0]\n$trouble";
21
- }elsif ($trouble =~ /failed to run/) {
22
- say('failed to run');
23
- print("\n$_[0]\n$trouble");
24
- }
25
-
26
- }
27
-
28
- while (sleep 1) {
29
- $new = `ls -lt *.coffee lib/*.coffee test/*.coffee plugins/*/*.coffee`;
30
- next if $old eq $new;
31
- $old = $new;
32
- print `clear; date`;
33
- say('client.');
34
- run('./node_modules/.bin/browserify -t coffeeify client.coffee --debug > client.js');
35
- say('test.');
36
- run('./node_modules/.bin/browserify -t coffeeify testclient.coffee ./plugins/*/test.coffee --debug > test/testclient.js');
37
- say('plugins.');
38
- run('./node_modules/.bin/coffee -c ./plugins/*.coffee');
39
- run('./node_modules/.bin/coffee -c ./plugins/*/*.coffee');
40
- say('done.');
41
- }
@@ -1,3 +0,0 @@
1
- window.wiki = require('wiki-client/lib/wiki')
2
- require('wiki-client/lib/legacy')
3
-
@@ -1,3607 +0,0 @@
1
- ;(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
2
- window.wiki = require('wiki-client/lib/wiki');
3
-
4
- require('wiki-client/lib/legacy');
5
-
6
-
7
- },{"wiki-client/lib/legacy":3,"wiki-client/lib/wiki":2}],2:[function(require,module,exports){
8
- (function() {
9
- var createSynopsis, wiki,
10
- __slice = [].slice;
11
-
12
- createSynopsis = require('./synopsis');
13
-
14
- wiki = {
15
- createSynopsis: createSynopsis
16
- };
17
-
18
- wiki.persona = require('./persona');
19
-
20
- wiki.log = function() {
21
- var things;
22
- things = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
23
- if ((typeof console !== "undefined" && console !== null ? console.log : void 0) != null) {
24
- return console.log.apply(console, things);
25
- }
26
- };
27
-
28
- wiki.asSlug = function(name) {
29
- return name.replace(/\s/g, '-').replace(/[^A-Za-z0-9-]/g, '').toLowerCase();
30
- };
31
-
32
- wiki.useLocalStorage = function() {
33
- return $(".login").length > 0;
34
- };
35
-
36
- wiki.resolutionContext = [];
37
-
38
- wiki.resolveFrom = function(addition, callback) {
39
- wiki.resolutionContext.push(addition);
40
- try {
41
- return callback();
42
- } finally {
43
- wiki.resolutionContext.pop();
44
- }
45
- };
46
-
47
- wiki.getData = function(vis) {
48
- var idx, who;
49
- if (vis) {
50
- idx = $('.item').index(vis);
51
- who = $(".item:lt(" + idx + ")").filter('.chart,.data,.calculator').last();
52
- if (who != null) {
53
- return who.data('item').data;
54
- } else {
55
- return {};
56
- }
57
- } else {
58
- who = $('.chart,.data,.calculator').last();
59
- if (who != null) {
60
- return who.data('item').data;
61
- } else {
62
- return {};
63
- }
64
- }
65
- };
66
-
67
- wiki.getDataNodes = function(vis) {
68
- var idx, who;
69
- if (vis) {
70
- idx = $('.item').index(vis);
71
- who = $(".item:lt(" + idx + ")").filter('.chart,.data,.calculator').toArray().reverse();
72
- return $(who);
73
- } else {
74
- who = $('.chart,.data,.calculator').toArray().reverse();
75
- return $(who);
76
- }
77
- };
78
-
79
- wiki.createPage = function(name, loc) {
80
- var $page, site;
81
- if (loc && loc !== 'view') {
82
- site = loc;
83
- }
84
- $page = $("<div class=\"page\" id=\"" + name + "\">\n <div class=\"twins\"> <p> </p> </div>\n <div class=\"header\">\n <h1> <img class=\"favicon\" src=\"" + (site ? "//" + site : "") + "/favicon.png\" height=\"32px\"> " + name + " </h1>\n </div>\n</div>");
85
- if (site) {
86
- $page.data('site', site);
87
- }
88
- return $page;
89
- };
90
-
91
- wiki.getItem = function(element) {
92
- if ($(element).length > 0) {
93
- return $(element).data("item") || $(element).data('staticItem');
94
- }
95
- };
96
-
97
- wiki.resolveLinks = function(string) {
98
- var renderInternalLink;
99
- renderInternalLink = function(match, name) {
100
- var slug;
101
- slug = wiki.asSlug(name);
102
- return "<a class=\"internal\" href=\"/" + slug + ".html\" data-page-name=\"" + slug + "\" title=\"" + (wiki.resolutionContext.join(' => ')) + "\">" + name + "</a>";
103
- };
104
- return string.replace(/\[\[([^\]]+)\]\]/gi, renderInternalLink).replace(/\[(http.*?) (.*?)\]/gi, "<a class=\"external\" target=\"_blank\" href=\"$1\" title=\"$1\" rel=\"nofollow\">$2 <img src=\"/images/external-link-ltr-icon.png\"></a>");
105
- };
106
-
107
- module.exports = wiki;
108
-
109
- }).call(this);
110
-
111
- },{"./persona":5,"./synopsis":4}],3:[function(require,module,exports){
112
- (function() {
113
- var active, newPage, pageHandler, plugin, refresh, state, util, wiki;
114
-
115
- wiki = require('./wiki');
116
-
117
- util = require('./util');
118
-
119
- pageHandler = wiki.pageHandler = require('./pageHandler');
120
-
121
- plugin = require('./plugin');
122
-
123
- state = require('./state');
124
-
125
- active = require('./active');
126
-
127
- refresh = require('./refresh');
128
-
129
- newPage = require('./page').newPage;
130
-
131
- Array.prototype.last = function() {
132
- return this[this.length - 1];
133
- };
134
-
135
- $(function() {
136
- var LEFTARROW, RIGHTARROW, createTextElement, doInternalLink, finishClick, getTemplate, sleep, textEditor;
137
- window.dialog = $('<div></div>').html('This dialog will show every time!').dialog({
138
- autoOpen: false,
139
- title: 'Basic Dialog',
140
- height: 600,
141
- width: 800
142
- });
143
- wiki.dialog = function(title, html) {
144
- window.dialog.html(html);
145
- window.dialog.dialog("option", "title", wiki.resolveLinks(title));
146
- return window.dialog.dialog('open');
147
- };
148
- sleep = function(time, done) {
149
- return setTimeout(done, time);
150
- };
151
- wiki.removeItem = function($item, item) {
152
- pageHandler.put($item.parents('.page:first'), {
153
- type: 'remove',
154
- id: item.id
155
- });
156
- return $item.remove();
157
- };
158
- wiki.createItem = function($page, $before, item) {
159
- var $item, before;
160
- if ($page == null) {
161
- $page = $before.parents('.page');
162
- }
163
- item.id = util.randomBytes(8);
164
- $item = $("<div class=\"item " + item.type + "\" data-id=\"" + "\"</div>");
165
- $item.data('item', item).data('pageElement', $page);
166
- if ($before != null) {
167
- $before.after($item);
168
- } else {
169
- $page.find('.story').append($item);
170
- }
171
- plugin["do"]($item, item);
172
- before = wiki.getItem($before);
173
- sleep(500, function() {
174
- return pageHandler.put($page, {
175
- item: item,
176
- id: item.id,
177
- type: 'add',
178
- after: before != null ? before.id : void 0
179
- });
180
- });
181
- return $item;
182
- };
183
- createTextElement = function(pageElement, beforeElement, initialText) {
184
- var item, itemBefore, itemElement;
185
- item = {
186
- type: 'paragraph',
187
- id: util.randomBytes(8),
188
- text: initialText
189
- };
190
- itemElement = $("<div class=\"item paragraph\" data-id=" + item.id + "></div>");
191
- itemElement.data('item', item).data('pageElement', pageElement);
192
- beforeElement.after(itemElement);
193
- plugin["do"](itemElement, item);
194
- itemBefore = wiki.getItem(beforeElement);
195
- wiki.textEditor(itemElement, item);
196
- return sleep(500, function() {
197
- return pageHandler.put(pageElement, {
198
- item: item,
199
- id: item.id,
200
- type: 'add',
201
- after: itemBefore != null ? itemBefore.id : void 0
202
- });
203
- });
204
- };
205
- textEditor = wiki.textEditor = function(div, item, caretPos, doubleClicked) {
206
- var original, textarea, _ref;
207
- if (div.hasClass('textEditing')) {
208
- return;
209
- }
210
- div.addClass('textEditing');
211
- textarea = $("<textarea>" + (original = (_ref = item.text) != null ? _ref : '') + "</textarea>").focusout(function() {
212
- div.removeClass('textEditing');
213
- if (item.text = textarea.val()) {
214
- plugin["do"](div.empty(), item);
215
- if (item.text === original) {
216
- return;
217
- }
218
- pageHandler.put(div.parents('.page:first'), {
219
- type: 'edit',
220
- id: item.id,
221
- item: item
222
- });
223
- } else {
224
- pageHandler.put(div.parents('.page:first'), {
225
- type: 'remove',
226
- id: item.id
227
- });
228
- div.remove();
229
- }
230
- return null;
231
- }).bind('keydown', function(e) {
232
- var middle, page, pageElement, prefix, prevItem, prevTextLen, sel, suffix, text;
233
- if ((e.altKey || e.ctlKey || e.metaKey) && e.which === 83) {
234
- textarea.focusout();
235
- return false;
236
- }
237
- if ((e.altKey || e.ctlKey || e.metaKey) && e.which === 73) {
238
- e.preventDefault();
239
- if (!e.shiftKey) {
240
- page = $(e.target).parents('.page');
241
- }
242
- doInternalLink("about " + item.type + " plugin", page);
243
- return false;
244
- }
245
- if (item.type === 'paragraph') {
246
- sel = util.getSelectionPos(textarea);
247
- if (e.which === $.ui.keyCode.BACKSPACE && sel.start === 0 && sel.start === sel.end) {
248
- prevItem = wiki.getItem(div.prev());
249
- if (prevItem.type !== 'paragraph') {
250
- return false;
251
- }
252
- prevTextLen = prevItem.text.length;
253
- prevItem.text += textarea.val();
254
- textarea.val('');
255
- textEditor(div.prev(), prevItem, prevTextLen);
256
- return false;
257
- } else if (e.which === $.ui.keyCode.ENTER && item.type === 'paragraph') {
258
- if (!sel) {
259
- return false;
260
- }
261
- text = textarea.val();
262
- prefix = text.substring(0, sel.start);
263
- if (sel.start !== sel.end) {
264
- middle = text.substring(sel.start, sel.end);
265
- }
266
- suffix = text.substring(sel.end);
267
- if (prefix === '') {
268
- textarea.val(' ');
269
- } else {
270
- textarea.val(prefix);
271
- }
272
- textarea.focusout();
273
- pageElement = div.parent().parent();
274
- createTextElement(pageElement, div, suffix);
275
- if (middle != null) {
276
- createTextElement(pageElement, div, middle);
277
- }
278
- if (prefix === '') {
279
- createTextElement(pageElement, div, '');
280
- }
281
- return false;
282
- }
283
- }
284
- });
285
- div.html(textarea);
286
- if (caretPos != null) {
287
- return util.setCaretPosition(textarea, caretPos);
288
- } else if (doubleClicked) {
289
- util.setCaretPosition(textarea, textarea.val().length);
290
- return textarea.scrollTop(textarea[0].scrollHeight - textarea.height());
291
- } else {
292
- return textarea.focus();
293
- }
294
- };
295
- doInternalLink = wiki.doInternalLink = function(name, page, site) {
296
- if (site == null) {
297
- site = null;
298
- }
299
- name = wiki.asSlug(name);
300
- if (page != null) {
301
- $(page).nextAll().remove();
302
- }
303
- wiki.createPage(name, site).appendTo($('.main')).each(refresh);
304
- return active.set($('.page').last());
305
- };
306
- LEFTARROW = 37;
307
- RIGHTARROW = 39;
308
- $(document).keydown(function(event) {
309
- var direction, newIndex, pages;
310
- direction = (function() {
311
- switch (event.which) {
312
- case LEFTARROW:
313
- return -1;
314
- case RIGHTARROW:
315
- return +1;
316
- }
317
- })();
318
- if (direction && !(event.target.tagName === "TEXTAREA")) {
319
- pages = $('.page');
320
- newIndex = pages.index($('.active')) + direction;
321
- if ((0 <= newIndex && newIndex < pages.length)) {
322
- return active.set(pages.eq(newIndex));
323
- }
324
- }
325
- });
326
- $(window).on('popstate', state.show);
327
- $(document).ajaxError(function(event, request, settings) {
328
- if (request.status === 0 || request.status === 404) {
329
- return;
330
- }
331
- wiki.log('ajax error', event, request, settings);
332
- return $('.main').prepend("<li class='error'>\n Error on " + settings.url + ": " + request.responseText + "\n</li>");
333
- });
334
- getTemplate = function(slug, done) {
335
- if (!slug) {
336
- return done(null);
337
- }
338
- wiki.log('getTemplate', slug);
339
- return pageHandler.get({
340
- whenGotten: function(data, siteFound) {
341
- return done(data.story);
342
- },
343
- whenNotGotten: function() {
344
- return done(null);
345
- },
346
- pageInformation: {
347
- slug: slug
348
- }
349
- });
350
- };
351
- finishClick = function(e, name) {
352
- var page;
353
- e.preventDefault();
354
- if (!e.shiftKey) {
355
- page = $(e.target).parents('.page');
356
- }
357
- doInternalLink(name, page, $(e.target).data('site'));
358
- return false;
359
- };
360
- $('.main').delegate('.show-page-source', 'click', function(e) {
361
- var json, pageElement;
362
- e.preventDefault();
363
- pageElement = $(this).parent().parent();
364
- json = pageElement.data('data');
365
- return wiki.dialog("JSON for " + json.title, $('<pre/>').text(JSON.stringify(json, null, 2)));
366
- }).delegate('.page', 'click', function(e) {
367
- if (!$(e.target).is("a")) {
368
- return active.set(this);
369
- }
370
- }).delegate('.internal', 'click', function(e) {
371
- var name;
372
- name = $(e.target).data('pageName');
373
- pageHandler.context = $(e.target).attr('title').split(' => ');
374
- return finishClick(e, name);
375
- }).delegate('img.remote', 'click', function(e) {
376
- var name;
377
- name = $(e.target).data('slug');
378
- pageHandler.context = [$(e.target).data('site')];
379
- return finishClick(e, name);
380
- }).delegate('.revision', 'dblclick', function(e) {
381
- var $page, action, json, page, rev;
382
- e.preventDefault();
383
- $page = $(this).parents('.page');
384
- page = $page.data('data');
385
- rev = page.journal.length - 1;
386
- action = page.journal[rev];
387
- json = JSON.stringify(action, null, 2);
388
- return wiki.dialog("Revision " + rev + ", " + action.type + " action", $('<pre/>').text(json));
389
- }).delegate('.action', 'click', function(e) {
390
- var $action, $page, name, rev, slug;
391
- e.preventDefault();
392
- $action = $(e.target);
393
- if ($action.is('.fork') && ((name = $action.data('slug')) != null)) {
394
- pageHandler.context = [$action.data('site')];
395
- return finishClick(e, (name.split('_'))[0]);
396
- } else {
397
- $page = $(this).parents('.page');
398
- slug = wiki.asSlug($page.data('data').title);
399
- rev = $(this).parent().children().index($action);
400
- if (!e.shiftKey) {
401
- $page.nextAll().remove();
402
- }
403
- wiki.createPage("" + slug + "_rev" + rev, $page.data('site')).appendTo($('.main')).each(refresh);
404
- return active.set($('.page').last());
405
- }
406
- }).delegate('.fork-page', 'click', function(e) {
407
- var item, pageElement, remoteSite;
408
- pageElement = $(e.target).parents('.page');
409
- if (pageElement.hasClass('local')) {
410
- if (!wiki.useLocalStorage()) {
411
- item = pageElement.data('data');
412
- pageElement.removeClass('local');
413
- return pageHandler.put(pageElement, {
414
- type: 'fork',
415
- item: item
416
- });
417
- }
418
- } else {
419
- if ((remoteSite = pageElement.data('site')) != null) {
420
- return pageHandler.put(pageElement, {
421
- type: 'fork',
422
- site: remoteSite
423
- });
424
- }
425
- }
426
- }).delegate('.action', 'hover', function() {
427
- var id;
428
- id = $(this).attr('data-id');
429
- $("[data-id=" + id + "]").toggleClass('target');
430
- return $('.main').trigger('rev');
431
- }).delegate('.item', 'hover', function() {
432
- var id;
433
- id = $(this).attr('data-id');
434
- return $(".action[data-id=" + id + "]").toggleClass('target');
435
- }).delegate('button.create', 'click', function(e) {
436
- return getTemplate($(e.target).data('slug'), function(story) {
437
- var $page, page, pageObject;
438
- $page = $(e.target).parents('.page:first');
439
- $page.removeClass('ghost');
440
- page = $page.data('data');
441
- page.story = story || [];
442
- pageObject = newPage(page, null);
443
- page = pageObject.getRawPage();
444
- pageHandler.put($page, {
445
- type: 'create',
446
- id: page.id,
447
- item: {
448
- title: page.title,
449
- story: page.story
450
- }
451
- });
452
- return wiki.buildPage(pageObject, $page.empty());
453
- });
454
- }).delegate('.ghost', 'rev', function(e) {
455
- var $item, $page, position;
456
- wiki.log('rev', e);
457
- $page = $(e.target).parents('.page:first');
458
- $item = $page.find('.target');
459
- position = $item.offset().top + $page.scrollTop() - $page.height() / 2;
460
- wiki.log('scroll', $page, $item, position);
461
- return $page.stop().animate({
462
- scrollTop: postion
463
- }, 'slow');
464
- }).delegate('.score', 'hover', function(e) {
465
- return $('.main').trigger('thumb', $(e.target).data('thumb'));
466
- });
467
- $(".provider input").click(function() {
468
- $("footer input:first").val($(this).attr('data-provider'));
469
- return $("footer form").submit();
470
- });
471
- $('body').on('new-neighbor-done', function(e, neighbor) {
472
- return $('.page').each(function(index, element) {
473
- return wiki.emitTwins($(element));
474
- });
475
- });
476
- return $(function() {
477
- state.first();
478
- $('.page').each(refresh);
479
- return active.set($('.page').last());
480
- });
481
- });
482
-
483
- }).call(this);
484
-
485
- },{"./active":10,"./page":12,"./pageHandler":7,"./plugin":8,"./refresh":11,"./state":9,"./util":6,"./wiki":2}],4:[function(require,module,exports){
486
- (function() {
487
- module.exports = function(page) {
488
- var p1, p2, synopsis;
489
- synopsis = page.synopsis;
490
- if ((page != null) && (page.story != null)) {
491
- p1 = page.story[0];
492
- p2 = page.story[1];
493
- if (p1 && p1.type === 'paragraph') {
494
- synopsis || (synopsis = p1.text);
495
- }
496
- if (p2 && p2.type === 'paragraph') {
497
- synopsis || (synopsis = p2.text);
498
- }
499
- if (p1 && (p1.text != null)) {
500
- synopsis || (synopsis = p1.text);
501
- }
502
- if (p2 && (p2.text != null)) {
503
- synopsis || (synopsis = p2.text);
504
- }
505
- synopsis || (synopsis = (page.story != null) && ("A page with " + page.story.length + " items."));
506
- } else {
507
- synopsis = 'A page with no story.';
508
- }
509
- return synopsis;
510
- };
511
-
512
- }).call(this);
513
-
514
- },{}],5:[function(require,module,exports){
515
- (function() {
516
- module.exports = function(owner) {
517
- $("#user-email").hide();
518
- $("#persona-login-btn").hide();
519
- $("#persona-logout-btn").hide();
520
- navigator.id.watch({
521
- loggedInUser: owner,
522
- onlogin: function(assertion) {
523
- return $.post("/persona_login", {
524
- assertion: assertion
525
- }, function(verified) {
526
- verified = JSON.parse(verified);
527
- if ("okay" === verified.status) {
528
- return window.location = "/";
529
- } else {
530
- navigator.id.logout();
531
- if ("wrong-address" === verified.status) {
532
- return window.location = "/oops";
533
- }
534
- }
535
- });
536
- },
537
- onlogout: function() {
538
- return $.post("/persona_logout", function() {
539
- return window.location = "/";
540
- });
541
- },
542
- onready: function() {
543
- if (owner) {
544
- $("#persona-login-btn").hide();
545
- return $("#persona-logout-btn").show();
546
- } else {
547
- $("#persona-login-btn").show();
548
- return $("#persona-logout-btn").hide();
549
- }
550
- }
551
- });
552
- $("#persona-login-btn").click(function(e) {
553
- e.preventDefault();
554
- return navigator.id.request({});
555
- });
556
- return $("#persona-logout-btn").click(function(e) {
557
- e.preventDefault();
558
- return navigator.id.logout();
559
- });
560
- };
561
-
562
- }).call(this);
563
-
564
- },{}],10:[function(require,module,exports){
565
- (function() {
566
- var active, findScrollContainer, scrollTo;
567
-
568
- module.exports = active = {};
569
-
570
- active.scrollContainer = void 0;
571
-
572
- findScrollContainer = function() {
573
- var scrolled;
574
- scrolled = $("body, html").filter(function() {
575
- return $(this).scrollLeft() > 0;
576
- });
577
- if (scrolled.length > 0) {
578
- return scrolled;
579
- } else {
580
- return $("body, html").scrollLeft(12).filter(function() {
581
- return $(this).scrollLeft() > 0;
582
- }).scrollTop(0);
583
- }
584
- };
585
-
586
- scrollTo = function(el) {
587
- var bodyWidth, contentWidth, maxX, minX, target, width;
588
- if (active.scrollContainer == null) {
589
- active.scrollContainer = findScrollContainer();
590
- }
591
- bodyWidth = $("body").width();
592
- minX = active.scrollContainer.scrollLeft();
593
- maxX = minX + bodyWidth;
594
- target = el.position().left;
595
- width = el.outerWidth(true);
596
- contentWidth = $(".page").outerWidth(true) * $(".page").size();
597
- if (target < minX) {
598
- return active.scrollContainer.animate({
599
- scrollLeft: target
600
- });
601
- } else if (target + width > maxX) {
602
- return active.scrollContainer.animate({
603
- scrollLeft: target - (bodyWidth - width)
604
- });
605
- } else if (maxX > $(".pages").outerWidth()) {
606
- return active.scrollContainer.animate({
607
- scrollLeft: Math.min(target, contentWidth - bodyWidth)
608
- });
609
- }
610
- };
611
-
612
- active.set = function(el) {
613
- el = $(el);
614
- $(".active").removeClass("active");
615
- return scrollTo(el.addClass("active"));
616
- };
617
-
618
- }).call(this);
619
-
620
- },{}],6:[function(require,module,exports){
621
- (function() {
622
- var util, wiki;
623
-
624
- wiki = require('./wiki');
625
-
626
- module.exports = wiki.util = util = {};
627
-
628
- util.symbols = {
629
- create: '☼',
630
- add: '+',
631
- edit: '✎',
632
- fork: '⚑',
633
- move: '↕',
634
- remove: '✕'
635
- };
636
-
637
- util.randomByte = function() {
638
- return (((1 + Math.random()) * 0x100) | 0).toString(16).substring(1);
639
- };
640
-
641
- util.randomBytes = function(n) {
642
- return ((function() {
643
- var _i, _results;
644
- _results = [];
645
- for (_i = 1; 1 <= n ? _i <= n : _i >= n; 1 <= n ? _i++ : _i--) {
646
- _results.push(util.randomByte());
647
- }
648
- return _results;
649
- })()).join('');
650
- };
651
-
652
- util.formatTime = function(time) {
653
- var am, d, h, mi, mo;
654
- d = new Date((time > 10000000000 ? time : time * 1000));
655
- mo = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][d.getMonth()];
656
- h = d.getHours();
657
- am = h < 12 ? 'AM' : 'PM';
658
- h = h === 0 ? 12 : h > 12 ? h - 12 : h;
659
- mi = (d.getMinutes() < 10 ? "0" : "") + d.getMinutes();
660
- return "" + h + ":" + mi + " " + am + "<br>" + (d.getDate()) + " " + mo + " " + (d.getFullYear());
661
- };
662
-
663
- util.formatDate = function(msSinceEpoch) {
664
- var am, d, day, h, mi, mo, sec, wk, yr;
665
- d = new Date(msSinceEpoch);
666
- wk = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][d.getDay()];
667
- mo = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][d.getMonth()];
668
- day = d.getDate();
669
- yr = d.getFullYear();
670
- h = d.getHours();
671
- am = h < 12 ? 'AM' : 'PM';
672
- h = h === 0 ? 12 : h > 12 ? h - 12 : h;
673
- mi = (d.getMinutes() < 10 ? "0" : "") + d.getMinutes();
674
- sec = (d.getSeconds() < 10 ? "0" : "") + d.getSeconds();
675
- return "" + wk + " " + mo + " " + day + ", " + yr + "<br>" + h + ":" + mi + ":" + sec + " " + am;
676
- };
677
-
678
- util.formatElapsedTime = function(msSinceEpoch) {
679
- var days, hrs, mins, months, msecs, secs, weeks, years;
680
- msecs = new Date().getTime() - msSinceEpoch;
681
- if ((secs = msecs / 1000) < 2) {
682
- return "" + (Math.floor(msecs)) + " milliseconds ago";
683
- }
684
- if ((mins = secs / 60) < 2) {
685
- return "" + (Math.floor(secs)) + " seconds ago";
686
- }
687
- if ((hrs = mins / 60) < 2) {
688
- return "" + (Math.floor(mins)) + " minutes ago";
689
- }
690
- if ((days = hrs / 24) < 2) {
691
- return "" + (Math.floor(hrs)) + " hours ago";
692
- }
693
- if ((weeks = days / 7) < 2) {
694
- return "" + (Math.floor(days)) + " days ago";
695
- }
696
- if ((months = days / 31) < 2) {
697
- return "" + (Math.floor(weeks)) + " weeks ago";
698
- }
699
- if ((years = days / 365) < 2) {
700
- return "" + (Math.floor(months)) + " months ago";
701
- }
702
- return "" + (Math.floor(years)) + " years ago";
703
- };
704
-
705
- util.emptyPage = function() {
706
- return {
707
- title: 'empty',
708
- story: [],
709
- journal: []
710
- };
711
- };
712
-
713
- util.getSelectionPos = function(jQueryElement) {
714
- var el, iePos, sel;
715
- el = jQueryElement.get(0);
716
- if (document.selection) {
717
- el.focus();
718
- sel = document.selection.createRange();
719
- sel.moveStart('character', -el.value.length);
720
- iePos = sel.text.length;
721
- return {
722
- start: iePos,
723
- end: iePos
724
- };
725
- } else {
726
- return {
727
- start: el.selectionStart,
728
- end: el.selectionEnd
729
- };
730
- }
731
- };
732
-
733
- util.setCaretPosition = function(jQueryElement, caretPos) {
734
- var el, range;
735
- el = jQueryElement.get(0);
736
- if (el != null) {
737
- if (el.createTextRange) {
738
- range = el.createTextRange();
739
- range.move("character", caretPos);
740
- range.select();
741
- } else {
742
- el.setSelectionRange(caretPos, caretPos);
743
- }
744
- return el.focus();
745
- }
746
- };
747
-
748
- }).call(this);
749
-
750
- },{"./wiki":2}],8:[function(require,module,exports){
751
- (function() {
752
- var getScript, plugin, scripts, util, wiki;
753
-
754
- util = require('./util');
755
-
756
- wiki = require('./wiki');
757
-
758
- module.exports = plugin = {};
759
-
760
- scripts = {};
761
-
762
- getScript = wiki.getScript = function(url, callback) {
763
- if (callback == null) {
764
- callback = function() {};
765
- }
766
- if (scripts[url] != null) {
767
- return callback();
768
- } else {
769
- return $.getScript(url).done(function() {
770
- scripts[url] = true;
771
- return callback();
772
- }).fail(function() {
773
- return callback();
774
- });
775
- }
776
- };
777
-
778
- plugin.get = wiki.getPlugin = function(name, callback) {
779
- if (window.plugins[name]) {
780
- return callback(window.plugins[name]);
781
- }
782
- return getScript("/plugins/" + name + "/" + name + ".js", function() {
783
- if (window.plugins[name]) {
784
- return callback(window.plugins[name]);
785
- }
786
- return getScript("/plugins/" + name + ".js", function() {
787
- return callback(window.plugins[name]);
788
- });
789
- });
790
- };
791
-
792
- plugin["do"] = wiki.doPlugin = function(div, item, done) {
793
- var error;
794
- if (done == null) {
795
- done = function() {};
796
- }
797
- error = function(ex) {
798
- var errorElement;
799
- errorElement = $("<div />").addClass('error');
800
- errorElement.text(ex.toString());
801
- return div.append(errorElement);
802
- };
803
- div.data('pageElement', div.parents(".page"));
804
- div.data('item', item);
805
- return plugin.get(item.type, function(script) {
806
- var err;
807
- try {
808
- if (script == null) {
809
- throw TypeError("Can't find plugin for '" + item.type + "'");
810
- }
811
- if (script.emit.length > 2) {
812
- return script.emit(div, item, function() {
813
- script.bind(div, item);
814
- return done();
815
- });
816
- } else {
817
- script.emit(div, item);
818
- script.bind(div, item);
819
- return done();
820
- }
821
- } catch (_error) {
822
- err = _error;
823
- wiki.log('plugin error', err);
824
- error(err);
825
- return done();
826
- }
827
- });
828
- };
829
-
830
- wiki.registerPlugin = function(pluginName, pluginFn) {
831
- return window.plugins[pluginName] = pluginFn($);
832
- };
833
-
834
- window.plugins = {
835
- reference: require('./reference'),
836
- factory: require('./factory'),
837
- paragraph: {
838
- emit: function(div, item) {
839
- var text, _i, _len, _ref, _results;
840
- _ref = item.text.split(/\n\n+/);
841
- _results = [];
842
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
843
- text = _ref[_i];
844
- if (text.match(/\S/)) {
845
- _results.push(div.append("<p>" + (wiki.resolveLinks(text)) + "</p>"));
846
- } else {
847
- _results.push(void 0);
848
- }
849
- }
850
- return _results;
851
- },
852
- bind: function(div, item) {
853
- return div.dblclick(function() {
854
- return wiki.textEditor(div, item, null, true);
855
- });
856
- }
857
- },
858
- image: {
859
- emit: function(div, item) {
860
- item.text || (item.text = item.caption);
861
- return div.append("<img class=thumbnail src=\"" + item.url + "\"> <p>" + (wiki.resolveLinks(item.text)) + "</p>");
862
- },
863
- bind: function(div, item) {
864
- div.dblclick(function() {
865
- return wiki.textEditor(div, item);
866
- });
867
- return div.find('img').dblclick(function() {
868
- return wiki.dialog(item.text, this);
869
- });
870
- }
871
- },
872
- future: {
873
- emit: function(div, item) {
874
- var info, _i, _len, _ref, _results;
875
- div.append("" + item.text + "<br><br><button class=\"create\">create</button> new blank page");
876
- if (((info = wiki.neighborhood[location.host]) != null) && (info.sitemap != null)) {
877
- _ref = info.sitemap;
878
- _results = [];
879
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
880
- item = _ref[_i];
881
- if (item.slug.match(/-template$/)) {
882
- _results.push(div.append("<br><button class=\"create\" data-slug=" + item.slug + ">create</button> from " + (wiki.resolveLinks("[[" + item.title + "]]"))));
883
- } else {
884
- _results.push(void 0);
885
- }
886
- }
887
- return _results;
888
- }
889
- },
890
- bind: function(div, item) {}
891
- }
892
- };
893
-
894
- }).call(this);
895
-
896
- },{"./factory":14,"./reference":13,"./util":6,"./wiki":2}],9:[function(require,module,exports){
897
- (function() {
898
- var active, state, wiki,
899
- __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
900
-
901
- wiki = require('./wiki');
902
-
903
- active = require('./active');
904
-
905
- module.exports = state = {};
906
-
907
- state.pagesInDom = function() {
908
- return $.makeArray($(".page").map(function(_, el) {
909
- return el.id;
910
- }));
911
- };
912
-
913
- state.urlPages = function() {
914
- var i;
915
- return ((function() {
916
- var _i, _len, _ref, _results;
917
- _ref = $(location).attr('pathname').split('/');
918
- _results = [];
919
- for (_i = 0, _len = _ref.length; _i < _len; _i += 2) {
920
- i = _ref[_i];
921
- _results.push(i);
922
- }
923
- return _results;
924
- })()).slice(1);
925
- };
926
-
927
- state.locsInDom = function() {
928
- return $.makeArray($(".page").map(function(_, el) {
929
- return $(el).data('site') || 'view';
930
- }));
931
- };
932
-
933
- state.urlLocs = function() {
934
- var j, _i, _len, _ref, _results;
935
- _ref = $(location).attr('pathname').split('/').slice(1);
936
- _results = [];
937
- for (_i = 0, _len = _ref.length; _i < _len; _i += 2) {
938
- j = _ref[_i];
939
- _results.push(j);
940
- }
941
- return _results;
942
- };
943
-
944
- state.setUrl = function() {
945
- var idx, locs, page, pages, url, _ref;
946
- document.title = (_ref = $('.page:last').data('data')) != null ? _ref.title : void 0;
947
- if (history && history.pushState) {
948
- locs = state.locsInDom();
949
- pages = state.pagesInDom();
950
- url = ((function() {
951
- var _i, _len, _results;
952
- _results = [];
953
- for (idx = _i = 0, _len = pages.length; _i < _len; idx = ++_i) {
954
- page = pages[idx];
955
- _results.push("/" + ((locs != null ? locs[idx] : void 0) || 'view') + "/" + page);
956
- }
957
- return _results;
958
- })()).join('');
959
- if (url !== $(location).attr('pathname')) {
960
- return history.pushState(null, null, url);
961
- }
962
- }
963
- };
964
-
965
- state.show = function(e) {
966
- var idx, name, newLocs, newPages, old, oldLocs, oldPages, previous, _i, _len, _ref;
967
- oldPages = state.pagesInDom();
968
- newPages = state.urlPages();
969
- oldLocs = state.locsInDom();
970
- newLocs = state.urlLocs();
971
- if (!location.pathname || location.pathname === '/') {
972
- return;
973
- }
974
- previous = $('.page').eq(0);
975
- for (idx = _i = 0, _len = newPages.length; _i < _len; idx = ++_i) {
976
- name = newPages[idx];
977
- if (name !== oldPages[idx]) {
978
- old = $('.page').eq(idx);
979
- if (old) {
980
- old.remove();
981
- }
982
- wiki.createPage(name, newLocs[idx]).insertAfter(previous).each(wiki.refresh);
983
- }
984
- previous = $('.page').eq(idx);
985
- }
986
- previous.nextAll().remove();
987
- active.set($('.page').last());
988
- return document.title = (_ref = $('.page:last').data('data')) != null ? _ref.title : void 0;
989
- };
990
-
991
- state.first = function() {
992
- var firstUrlLocs, firstUrlPages, idx, oldPages, urlPage, _i, _len, _results;
993
- state.setUrl();
994
- firstUrlPages = state.urlPages();
995
- firstUrlLocs = state.urlLocs();
996
- oldPages = state.pagesInDom();
997
- _results = [];
998
- for (idx = _i = 0, _len = firstUrlPages.length; _i < _len; idx = ++_i) {
999
- urlPage = firstUrlPages[idx];
1000
- if (__indexOf.call(oldPages, urlPage) < 0) {
1001
- if (urlPage !== '') {
1002
- _results.push(wiki.createPage(urlPage, firstUrlLocs[idx]).appendTo('.main'));
1003
- } else {
1004
- _results.push(void 0);
1005
- }
1006
- }
1007
- }
1008
- return _results;
1009
- };
1010
-
1011
- }).call(this);
1012
-
1013
- },{"./active":10,"./wiki":2}],15:[function(require,module,exports){
1014
- (function() {
1015
- var create;
1016
-
1017
- create = function(revIndex, data) {
1018
- var afterIndex, editIndex, itemId, items, journal, journalEntry, removeIndex, revJournal, revStory, revStoryIds, revTitle, storyItem, _i, _j, _k, _len, _len1, _len2, _ref;
1019
- journal = data.journal;
1020
- revTitle = data.title;
1021
- revStory = [];
1022
- revJournal = journal.slice(0, +(+revIndex) + 1 || 9e9);
1023
- for (_i = 0, _len = revJournal.length; _i < _len; _i++) {
1024
- journalEntry = revJournal[_i];
1025
- revStoryIds = revStory.map(function(storyItem) {
1026
- return storyItem.id;
1027
- });
1028
- switch (journalEntry.type) {
1029
- case 'create':
1030
- if (journalEntry.item.title != null) {
1031
- revTitle = journalEntry.item.title;
1032
- revStory = journalEntry.item.story || [];
1033
- }
1034
- break;
1035
- case 'add':
1036
- if ((afterIndex = revStoryIds.indexOf(journalEntry.after)) !== -1) {
1037
- revStory.splice(afterIndex + 1, 0, journalEntry.item);
1038
- } else {
1039
- revStory.push(journalEntry.item);
1040
- }
1041
- break;
1042
- case 'edit':
1043
- if ((editIndex = revStoryIds.indexOf(journalEntry.id)) !== -1) {
1044
- revStory.splice(editIndex, 1, journalEntry.item);
1045
- } else {
1046
- revStory.push(journalEntry.item);
1047
- }
1048
- break;
1049
- case 'move':
1050
- items = {};
1051
- for (_j = 0, _len1 = revStory.length; _j < _len1; _j++) {
1052
- storyItem = revStory[_j];
1053
- items[storyItem.id] = storyItem;
1054
- }
1055
- revStory = [];
1056
- _ref = journalEntry.order;
1057
- for (_k = 0, _len2 = _ref.length; _k < _len2; _k++) {
1058
- itemId = _ref[_k];
1059
- if (items[itemId] != null) {
1060
- revStory.push(items[itemId]);
1061
- }
1062
- }
1063
- break;
1064
- case 'remove':
1065
- if ((removeIndex = revStoryIds.indexOf(journalEntry.id)) !== -1) {
1066
- revStory.splice(removeIndex, 1);
1067
- }
1068
- }
1069
- }
1070
- return {
1071
- story: revStory,
1072
- journal: revJournal,
1073
- title: revTitle
1074
- };
1075
- };
1076
-
1077
- exports.create = create;
1078
-
1079
- }).call(this);
1080
-
1081
- },{}],13:[function(require,module,exports){
1082
- (function() {
1083
- var bind, emit;
1084
-
1085
- emit = function($item, item) {
1086
- var site, slug;
1087
- slug = item.slug || 'welcome-visitors';
1088
- site = item.site;
1089
- return wiki.resolveFrom(site, function() {
1090
- return $item.append("<p style='margin-bottom:3px;'>\n <img class='remote'\n src='//" + site + "/favicon.png'\n title='" + site + "'\n data-site=\"" + site + "\"\n data-slug=\"" + slug + "\"\n >\n " + (wiki.resolveLinks("[[" + (item.title || slug) + "]]")) + "\n</p>\n<div>\n " + (wiki.resolveLinks(item.text)) + "\n</div>");
1091
- });
1092
- };
1093
-
1094
- bind = function($item, item) {
1095
- return $item.dblclick(function() {
1096
- return wiki.textEditor($item, item);
1097
- });
1098
- };
1099
-
1100
- module.exports = {
1101
- emit: emit,
1102
- bind: bind
1103
- };
1104
-
1105
- }).call(this);
1106
-
1107
- },{}],14:[function(require,module,exports){
1108
- (function() {
1109
- var arrayToJson, bind, csvToArray, emit,
1110
- __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
1111
-
1112
- emit = function(div, item) {
1113
- var showMenu, showPrompt;
1114
- div.append('<p>Double-Click to Edit<br>Drop Text or Image to Insert</p>');
1115
- showMenu = function() {
1116
- var info, menu, menuItem, name, _i, _len, _ref, _ref1;
1117
- menu = div.find('p').append("<br>Or Choose a Plugin");
1118
- menuItem = function(title, name) {
1119
- return menu.append("<li><a class=\"menu\" href=\"#\" title=\"" + title + "\">" + name + "</a></li>");
1120
- };
1121
- if (Array.isArray(window.catalog)) {
1122
- _ref = window.catalog;
1123
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1124
- info = _ref[_i];
1125
- menuItem(info.title, info.name);
1126
- }
1127
- } else {
1128
- _ref1 = window.catalog;
1129
- for (name in _ref1) {
1130
- info = _ref1[name];
1131
- menuItem(info.menu, name);
1132
- }
1133
- }
1134
- return menu.find('a.menu').click(function(evt) {
1135
- div.removeClass('factory').addClass(item.type = evt.target.text.toLowerCase());
1136
- div.unbind();
1137
- return wiki.textEditor(div, item);
1138
- });
1139
- };
1140
- showPrompt = function() {
1141
- return div.append("<p>" + (wiki.resolveLinks(item.prompt)) + "</b>");
1142
- };
1143
- if (item.prompt) {
1144
- return showPrompt();
1145
- } else if (window.catalog != null) {
1146
- return showMenu();
1147
- } else {
1148
- return $.getJSON('/system/factories.json', function(data) {
1149
- window.catalog = data;
1150
- return showMenu();
1151
- });
1152
- }
1153
- };
1154
-
1155
- bind = function(div, item) {
1156
- var syncEditAction;
1157
- syncEditAction = function() {
1158
- var err, pageElement;
1159
- wiki.log('factory item', item);
1160
- div.empty().unbind();
1161
- div.removeClass("factory").addClass(item.type);
1162
- pageElement = div.parents('.page:first');
1163
- try {
1164
- div.data('pageElement', pageElement);
1165
- div.data('item', item);
1166
- wiki.getPlugin(item.type, function(plugin) {
1167
- plugin.emit(div, item);
1168
- return plugin.bind(div, item);
1169
- });
1170
- } catch (_error) {
1171
- err = _error;
1172
- div.append("<p class='error'>" + err + "</p>");
1173
- }
1174
- return wiki.pageHandler.put(pageElement, {
1175
- type: 'edit',
1176
- id: item.id,
1177
- item: item
1178
- });
1179
- };
1180
- div.dblclick(function() {
1181
- div.removeClass('factory').addClass(item.type = 'paragraph');
1182
- div.unbind();
1183
- return wiki.textEditor(div, item);
1184
- });
1185
- div.bind('dragenter', function(evt) {
1186
- return evt.preventDefault();
1187
- });
1188
- div.bind('dragover', function(evt) {
1189
- return evt.preventDefault();
1190
- });
1191
- return div.bind("drop", function(dropEvent) {
1192
- var dt, found, ignore, origin, punt, readFile, url;
1193
- punt = function(data) {
1194
- item.prompt = "<b>Unexpected Item</b><br>We can't make sense of the drop.<br>" + (JSON.stringify(data)) + "<br>Try something else or see [[About Factory Plugin]].";
1195
- data.userAgent = navigator.userAgent;
1196
- item.punt = data;
1197
- wiki.log('factory punt', dropEvent);
1198
- return syncEditAction();
1199
- };
1200
- readFile = function(file) {
1201
- var majorType, minorType, reader, _ref;
1202
- if (file != null) {
1203
- _ref = file.type.split("/"), majorType = _ref[0], minorType = _ref[1];
1204
- reader = new FileReader();
1205
- if (majorType === "image") {
1206
- reader.onload = function(loadEvent) {
1207
- item.type = 'image';
1208
- item.url = loadEvent.target.result;
1209
- item.caption || (item.caption = "Uploaded image");
1210
- return syncEditAction();
1211
- };
1212
- return reader.readAsDataURL(file);
1213
- } else if (majorType === "text") {
1214
- reader.onload = function(loadEvent) {
1215
- var array, result;
1216
- result = loadEvent.target.result;
1217
- if (minorType === 'csv') {
1218
- item.type = 'data';
1219
- item.columns = (array = csvToArray(result))[0];
1220
- item.data = arrayToJson(array);
1221
- item.text = file.fileName;
1222
- } else {
1223
- item.type = 'paragraph';
1224
- item.text = result;
1225
- }
1226
- return syncEditAction();
1227
- };
1228
- return reader.readAsText(file);
1229
- } else {
1230
- return punt({
1231
- number: 1,
1232
- name: file.fileName,
1233
- type: file.type
1234
- });
1235
- }
1236
- } else {
1237
- return punt({
1238
- number: 2,
1239
- types: dropEvent.originalEvent.dataTransfer.types
1240
- });
1241
- }
1242
- };
1243
- dropEvent.preventDefault();
1244
- if ((dt = dropEvent.originalEvent.dataTransfer) != null) {
1245
- if ((dt.types != null) && (__indexOf.call(dt.types, 'text/uri-list') >= 0 || __indexOf.call(dt.types, 'text/x-moz-url') >= 0) && !(__indexOf.call(dt.types, 'Files') >= 0)) {
1246
- url = dt.getData('URL');
1247
- if (found = url.match(/^http:\/\/([a-zA-Z0-9:.-]+)(\/([a-zA-Z0-9:.-]+)\/([a-z0-9-]+(_rev\d+)?))+$/)) {
1248
- wiki.log('factory drop url', found);
1249
- ignore = found[0], origin = found[1], ignore = found[2], item.site = found[3], item.slug = found[4], ignore = found[5];
1250
- if ($.inArray(item.site, ['view', 'local', 'origin']) >= 0) {
1251
- item.site = origin;
1252
- }
1253
- return $.getJSON("http://" + item.site + "/" + item.slug + ".json", function(remote) {
1254
- wiki.log('factory remote', remote);
1255
- item.type = 'reference';
1256
- item.title = remote.title || item.slug;
1257
- item.text = wiki.createSynopsis(remote);
1258
- syncEditAction();
1259
- if (item.site != null) {
1260
- return wiki.registerNeighbor(item.site);
1261
- }
1262
- });
1263
- } else {
1264
- return punt({
1265
- number: 4,
1266
- url: url,
1267
- types: dt.types
1268
- });
1269
- }
1270
- } else if (__indexOf.call(dt.types, 'Files') >= 0) {
1271
- return readFile(dt.files[0]);
1272
- } else {
1273
- return punt({
1274
- number: 5,
1275
- types: dt.types
1276
- });
1277
- }
1278
- } else {
1279
- return punt({
1280
- number: 6,
1281
- trouble: "no data transfer object"
1282
- });
1283
- }
1284
- });
1285
- };
1286
-
1287
- csvToArray = function(strData, strDelimiter) {
1288
- var arrData, arrMatches, objPattern, strMatchedDelimiter, strMatchedValue;
1289
- strDelimiter = strDelimiter || ",";
1290
- objPattern = new RegExp("(\\" + strDelimiter + "|\\r?\\n|\\r|^)" + "(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" + "([^\"\\" + strDelimiter + "\\r\\n]*))", "gi");
1291
- arrData = [[]];
1292
- arrMatches = null;
1293
- while (arrMatches = objPattern.exec(strData)) {
1294
- strMatchedDelimiter = arrMatches[1];
1295
- if (strMatchedDelimiter.length && (strMatchedDelimiter !== strDelimiter)) {
1296
- arrData.push([]);
1297
- }
1298
- if (arrMatches[2]) {
1299
- strMatchedValue = arrMatches[2].replace(new RegExp("\"\"", "g"), "\"");
1300
- } else {
1301
- strMatchedValue = arrMatches[3];
1302
- }
1303
- arrData[arrData.length - 1].push(strMatchedValue);
1304
- }
1305
- return arrData;
1306
- };
1307
-
1308
- arrayToJson = function(array) {
1309
- var cols, row, rowToObject, _i, _len, _results;
1310
- cols = array.shift();
1311
- rowToObject = function(row) {
1312
- var k, obj, v, _i, _len, _ref, _ref1;
1313
- obj = {};
1314
- _ref = _.zip(cols, row);
1315
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1316
- _ref1 = _ref[_i], k = _ref1[0], v = _ref1[1];
1317
- if ((v != null) && (v.match(/\S/)) && v !== 'NULL') {
1318
- obj[k] = v;
1319
- }
1320
- }
1321
- return obj;
1322
- };
1323
- _results = [];
1324
- for (_i = 0, _len = array.length; _i < _len; _i++) {
1325
- row = array[_i];
1326
- _results.push(rowToObject(row));
1327
- }
1328
- return _results;
1329
- };
1330
-
1331
- module.exports = {
1332
- emit: emit,
1333
- bind: bind
1334
- };
1335
-
1336
- }).call(this);
1337
-
1338
- },{}],16:[function(require,module,exports){
1339
- (function() {
1340
- var util;
1341
-
1342
- util = require('./util');
1343
-
1344
- module.exports = function(journalElement, action) {
1345
- var actionElement, actionTitle, controls, pageElement;
1346
- pageElement = journalElement.parents('.page:first');
1347
- actionTitle = action.type || 'separator';
1348
- if (action.date != null) {
1349
- actionTitle += " " + (util.formatElapsedTime(action.date));
1350
- }
1351
- actionElement = $("<a href=\"#\" /> ").addClass("action").addClass(action.type || 'separator').text(action.symbol || util.symbols[action.type]).attr('title', actionTitle).attr('data-id', action.id || "0").data('action', action);
1352
- controls = journalElement.children('.control-buttons');
1353
- if (controls.length > 0) {
1354
- actionElement.insertBefore(controls);
1355
- } else {
1356
- actionElement.appendTo(journalElement);
1357
- }
1358
- if (action.type === 'fork' && (action.site != null)) {
1359
- return actionElement.css("background-image", "url(//" + action.site + "/favicon.png)").attr("href", "//" + action.site + "/" + (pageElement.attr('id')) + ".html").data("site", action.site).data("slug", pageElement.attr('id'));
1360
- }
1361
- };
1362
-
1363
- }).call(this);
1364
-
1365
- },{"./util":6}],7:[function(require,module,exports){
1366
- (function() {
1367
- var addToJournal, newPage, pageFromLocalStorage, pageHandler, pushToLocal, pushToServer, recursiveGet, revision, state, util, wiki, _;
1368
-
1369
- _ = require('underscore');
1370
-
1371
- wiki = require('./wiki');
1372
-
1373
- util = require('./util');
1374
-
1375
- state = require('./state');
1376
-
1377
- revision = require('./revision');
1378
-
1379
- addToJournal = require('./addToJournal');
1380
-
1381
- newPage = require('./page').newPage;
1382
-
1383
- module.exports = pageHandler = {};
1384
-
1385
- pageFromLocalStorage = function(slug) {
1386
- var json;
1387
- if (json = localStorage[slug]) {
1388
- return JSON.parse(json);
1389
- } else {
1390
- return void 0;
1391
- }
1392
- };
1393
-
1394
- recursiveGet = function(_arg) {
1395
- var localContext, localPage, pageInformation, rev, site, slug, url, whenGotten, whenNotGotten;
1396
- pageInformation = _arg.pageInformation, whenGotten = _arg.whenGotten, whenNotGotten = _arg.whenNotGotten, localContext = _arg.localContext;
1397
- slug = pageInformation.slug, rev = pageInformation.rev, site = pageInformation.site;
1398
- if (site) {
1399
- localContext = [];
1400
- } else {
1401
- site = localContext.shift();
1402
- }
1403
- if (site === window.location.host) {
1404
- site = 'origin';
1405
- }
1406
- if (site === 'view') {
1407
- site = null;
1408
- }
1409
- if (site != null) {
1410
- if (site === 'local') {
1411
- if (localPage = pageFromLocalStorage(pageInformation.slug)) {
1412
- return whenGotten(newPage(localPage, 'local'));
1413
- } else {
1414
- return whenNotGotten();
1415
- }
1416
- } else {
1417
- if (site === 'origin') {
1418
- url = "/" + slug + ".json";
1419
- } else {
1420
- url = "http://" + site + "/" + slug + ".json";
1421
- }
1422
- }
1423
- } else {
1424
- url = "/" + slug + ".json";
1425
- }
1426
- return $.ajax({
1427
- type: 'GET',
1428
- dataType: 'json',
1429
- url: url + ("?random=" + (util.randomBytes(4))),
1430
- success: function(page) {
1431
- if (rev) {
1432
- page = revision.create(rev, page);
1433
- }
1434
- return whenGotten(newPage(page, site));
1435
- },
1436
- error: function(xhr, type, msg) {
1437
- var report;
1438
- if ((xhr.status !== 404) && (xhr.status !== 0)) {
1439
- wiki.log('pageHandler.get error', xhr, xhr.status, type, msg);
1440
- report = {
1441
- 'title': "" + xhr.status + " " + msg,
1442
- 'story': [
1443
- {
1444
- 'type': 'paragraph',
1445
- 'id': '928739187243',
1446
- 'text': "<pre>" + xhr.responseText
1447
- }
1448
- ]
1449
- };
1450
- return whenGotten(report, 'local');
1451
- }
1452
- if (localContext.length > 0) {
1453
- return recursiveGet({
1454
- pageInformation: pageInformation,
1455
- whenGotten: whenGotten,
1456
- whenNotGotten: whenNotGotten,
1457
- localContext: localContext
1458
- });
1459
- } else {
1460
- return whenNotGotten();
1461
- }
1462
- }
1463
- });
1464
- };
1465
-
1466
- pageHandler.get = function(_arg) {
1467
- var localPage, pageInformation, whenGotten, whenNotGotten;
1468
- whenGotten = _arg.whenGotten, whenNotGotten = _arg.whenNotGotten, pageInformation = _arg.pageInformation;
1469
- if (!pageInformation.site) {
1470
- if (localPage = pageFromLocalStorage(pageInformation.slug)) {
1471
- if (pageInformation.rev) {
1472
- localPage = revision.create(pageInformation.rev, localPage);
1473
- }
1474
- return whenGotten(newPage(localPage, 'local'));
1475
- }
1476
- }
1477
- if (!pageHandler.context.length) {
1478
- pageHandler.context = ['view'];
1479
- }
1480
- return recursiveGet({
1481
- pageInformation: pageInformation,
1482
- whenGotten: whenGotten,
1483
- whenNotGotten: whenNotGotten,
1484
- localContext: _.clone(pageHandler.context)
1485
- });
1486
- };
1487
-
1488
- pageHandler.context = [];
1489
-
1490
- pushToLocal = function(pageElement, pagePutInfo, action) {
1491
- var page, site;
1492
- if (action.type === 'create') {
1493
- page = {
1494
- title: action.item.title,
1495
- story: [],
1496
- journal: []
1497
- };
1498
- } else {
1499
- page = pageFromLocalStorage(pagePutInfo.slug);
1500
- page || (page = pageElement.data("data"));
1501
- if (page.journal == null) {
1502
- page.journal = [];
1503
- }
1504
- if ((site = action['fork']) != null) {
1505
- page.journal = page.journal.concat({
1506
- 'type': 'fork',
1507
- 'site': site
1508
- });
1509
- delete action['fork'];
1510
- }
1511
- page.story = $(pageElement).find(".item").map(function() {
1512
- return $(this).data("item");
1513
- }).get();
1514
- }
1515
- page.journal = page.journal.concat(action);
1516
- localStorage[pagePutInfo.slug] = JSON.stringify(page);
1517
- return addToJournal(pageElement.find('.journal'), action);
1518
- };
1519
-
1520
- pushToServer = function(pageElement, pagePutInfo, action) {
1521
- return $.ajax({
1522
- type: 'PUT',
1523
- url: "/page/" + pagePutInfo.slug + "/action",
1524
- data: {
1525
- 'action': JSON.stringify(action)
1526
- },
1527
- success: function() {
1528
- addToJournal(pageElement.find('.journal'), action);
1529
- if (action.type === 'fork') {
1530
- localStorage.removeItem(pageElement.attr('id'));
1531
- return state.setUrl;
1532
- }
1533
- },
1534
- error: function(xhr, type, msg) {
1535
- return wiki.log("pageHandler.put ajax error callback", type, msg);
1536
- }
1537
- });
1538
- };
1539
-
1540
- pageHandler.put = function(pageElement, action) {
1541
- var checkedSite, forkFrom, pagePutInfo;
1542
- checkedSite = function() {
1543
- var site;
1544
- switch (site = pageElement.data('site')) {
1545
- case 'origin':
1546
- case 'local':
1547
- case 'view':
1548
- return null;
1549
- case location.host:
1550
- return null;
1551
- default:
1552
- return site;
1553
- }
1554
- };
1555
- pagePutInfo = {
1556
- slug: pageElement.attr('id').split('_rev')[0],
1557
- rev: pageElement.attr('id').split('_rev')[1],
1558
- site: checkedSite(),
1559
- local: pageElement.hasClass('local')
1560
- };
1561
- forkFrom = pagePutInfo.site;
1562
- wiki.log('pageHandler.put', action, pagePutInfo);
1563
- if (wiki.useLocalStorage()) {
1564
- if (pagePutInfo.site != null) {
1565
- wiki.log('remote => local');
1566
- } else if (!pagePutInfo.local) {
1567
- wiki.log('origin => local');
1568
- action.site = forkFrom = location.host;
1569
- }
1570
- }
1571
- action.date = (new Date()).getTime();
1572
- if (action.site === 'origin') {
1573
- delete action.site;
1574
- }
1575
- if (forkFrom) {
1576
- pageElement.find('h1 img').attr('src', '/favicon.png');
1577
- pageElement.find('h1 a').attr('href', '/');
1578
- pageElement.data('site', null);
1579
- pageElement.removeClass('remote');
1580
- state.setUrl();
1581
- if (action.type !== 'fork') {
1582
- action.fork = forkFrom;
1583
- addToJournal(pageElement.find('.journal'), {
1584
- type: 'fork',
1585
- site: forkFrom,
1586
- date: action.date
1587
- });
1588
- }
1589
- }
1590
- if (wiki.useLocalStorage() || pagePutInfo.site === 'local') {
1591
- pushToLocal(pageElement, pagePutInfo, action);
1592
- return pageElement.addClass("local");
1593
- } else {
1594
- return pushToServer(pageElement, pagePutInfo, action);
1595
- }
1596
- };
1597
-
1598
- }).call(this);
1599
-
1600
- },{"./addToJournal":16,"./page":12,"./revision":15,"./state":9,"./util":6,"./wiki":2,"underscore":17}],11:[function(require,module,exports){
1601
- (function() {
1602
- var addToJournal, buildPageHeader, createFactory, emitHeader, emitTwins, handleDragging, initAddButton, initDragging, neighborhood, pageHandler, plugin, refresh, renderPageIntoPageElement, state, util, wiki, _;
1603
-
1604
- _ = require('underscore');
1605
-
1606
- util = require('./util');
1607
-
1608
- pageHandler = require('./pageHandler');
1609
-
1610
- plugin = require('./plugin');
1611
-
1612
- state = require('./state');
1613
-
1614
- neighborhood = require('./neighborhood');
1615
-
1616
- addToJournal = require('./addToJournal');
1617
-
1618
- wiki = require('./wiki');
1619
-
1620
- handleDragging = function(evt, ui) {
1621
- var action, before, beforeElement, destinationPageElement, equals, item, itemElement, moveFromPage, moveToPage, moveWithinPage, order, sourcePageElement, sourceSite, thisPageElement;
1622
- itemElement = ui.item;
1623
- item = wiki.getItem(itemElement);
1624
- thisPageElement = $(this).parents('.page:first');
1625
- sourcePageElement = itemElement.data('pageElement');
1626
- sourceSite = sourcePageElement.data('site');
1627
- destinationPageElement = itemElement.parents('.page:first');
1628
- equals = function(a, b) {
1629
- return a && b && a.get(0) === b.get(0);
1630
- };
1631
- moveWithinPage = !sourcePageElement || equals(sourcePageElement, destinationPageElement);
1632
- moveFromPage = !moveWithinPage && equals(thisPageElement, sourcePageElement);
1633
- moveToPage = !moveWithinPage && equals(thisPageElement, destinationPageElement);
1634
- if (moveFromPage) {
1635
- if (sourcePageElement.hasClass('ghost') || sourcePageElement.attr('id') === destinationPageElement.attr('id')) {
1636
- return;
1637
- }
1638
- }
1639
- action = moveWithinPage ? (order = $(this).children().map(function(_, value) {
1640
- return $(value).attr('data-id');
1641
- }).get(), {
1642
- type: 'move',
1643
- order: order
1644
- }) : moveFromPage ? (wiki.log('drag from', sourcePageElement.find('h1').text()), {
1645
- type: 'remove'
1646
- }) : moveToPage ? (itemElement.data('pageElement', thisPageElement), beforeElement = itemElement.prev('.item'), before = wiki.getItem(beforeElement), {
1647
- type: 'add',
1648
- item: item,
1649
- after: before != null ? before.id : void 0
1650
- }) : void 0;
1651
- action.id = item.id;
1652
- return pageHandler.put(thisPageElement, action);
1653
- };
1654
-
1655
- initDragging = function($page) {
1656
- var $story;
1657
- $story = $page.find('.story');
1658
- return $story.sortable({
1659
- connectWith: '.page .story'
1660
- }).on("sortupdate", handleDragging);
1661
- };
1662
-
1663
- initAddButton = function($page) {
1664
- return $page.find(".add-factory").live("click", function(evt) {
1665
- if ($page.hasClass('ghost')) {
1666
- return;
1667
- }
1668
- evt.preventDefault();
1669
- return createFactory($page);
1670
- });
1671
- };
1672
-
1673
- createFactory = function($page) {
1674
- var before, beforeElement, item, itemElement;
1675
- item = {
1676
- type: "factory",
1677
- id: util.randomBytes(8)
1678
- };
1679
- itemElement = $("<div />", {
1680
- "class": "item factory"
1681
- }).data('item', item).attr('data-id', item.id);
1682
- itemElement.data('pageElement', $page);
1683
- $page.find(".story").append(itemElement);
1684
- plugin["do"](itemElement, item);
1685
- beforeElement = itemElement.prev('.item');
1686
- before = wiki.getItem(beforeElement);
1687
- return pageHandler.put($page, {
1688
- item: item,
1689
- id: item.id,
1690
- type: "add",
1691
- after: before != null ? before.id : void 0
1692
- });
1693
- };
1694
-
1695
- buildPageHeader = function(_arg) {
1696
- var favicon_src, header_href, page, tooltip;
1697
- page = _arg.page, tooltip = _arg.tooltip, header_href = _arg.header_href, favicon_src = _arg.favicon_src;
1698
- if (page.plugin) {
1699
- tooltip += "\n" + page.plugin + " plugin";
1700
- }
1701
- return "<h1 title=\"" + tooltip + "\"><a href=\"" + header_href + "\"><img src=\"" + favicon_src + "\" height=\"32px\" class=\"favicon\"></a> " + page.title + "</h1>";
1702
- };
1703
-
1704
- emitHeader = function($header, $page, pageObject) {
1705
- var date, header, isRemotePage, page, pageHeader, rev, viewHere;
1706
- page = pageObject.getRawPage();
1707
- isRemotePage = pageObject.isRemote();
1708
- header = '';
1709
- viewHere = wiki.asSlug(page.title) === 'welcome-visitors' ? "" : "/view/" + (pageObject.getSlug());
1710
- pageHeader = isRemotePage ? buildPageHeader({
1711
- tooltip: pageObject.getRemoteSite(),
1712
- header_href: "//" + (pageObject.getRemoteSite()) + "/view/welcome-visitors" + viewHere,
1713
- favicon_src: "http://" + (pageObject.getRemoteSite()) + "/favicon.png",
1714
- page: page
1715
- }) : buildPageHeader({
1716
- tooltip: location.host,
1717
- header_href: "/view/welcome-visitors" + viewHere,
1718
- favicon_src: "/favicon.png",
1719
- page: page
1720
- });
1721
- $header.append(pageHeader);
1722
- if (!isRemotePage) {
1723
- $('img.favicon', $page).error(function(e) {
1724
- return plugin.get('favicon', function(favicon) {
1725
- return favicon.create();
1726
- });
1727
- });
1728
- }
1729
- if ($page.attr('id').match(/_rev/)) {
1730
- rev = page.journal.length - 1;
1731
- date = page.journal[rev].date;
1732
- $page.addClass('ghost').data('rev', rev);
1733
- return $header.append($("<h2 class=\"revision\">\n <span>\n " + (date != null ? util.formatDate(date) : "Revision " + rev) + "\n </span>\n</h2>"));
1734
- }
1735
- };
1736
-
1737
- emitTwins = wiki.emitTwins = function($page) {
1738
- var actions, bin, bins, flags, i, info, item, legend, page, remoteSite, site, slug, twins, viewing, _i, _len, _ref, _ref1, _ref2, _ref3;
1739
- page = $page.data('data');
1740
- site = $page.data('site') || window.location.host;
1741
- if (site === 'view' || site === 'origin') {
1742
- site = window.location.host;
1743
- }
1744
- slug = wiki.asSlug(page.title);
1745
- if (((actions = (_ref = page.journal) != null ? _ref.length : void 0) != null) && ((viewing = (_ref1 = page.journal[actions - 1]) != null ? _ref1.date : void 0) != null)) {
1746
- viewing = Math.floor(viewing / 1000) * 1000;
1747
- bins = {
1748
- newer: [],
1749
- same: [],
1750
- older: []
1751
- };
1752
- _ref2 = wiki.neighborhood;
1753
- for (remoteSite in _ref2) {
1754
- info = _ref2[remoteSite];
1755
- if (remoteSite !== site && (info.sitemap != null)) {
1756
- _ref3 = info.sitemap;
1757
- for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
1758
- item = _ref3[_i];
1759
- if (item.slug === slug) {
1760
- bin = item.date > viewing ? bins.newer : item.date < viewing ? bins.older : bins.same;
1761
- bin.push({
1762
- remoteSite: remoteSite,
1763
- item: item
1764
- });
1765
- }
1766
- }
1767
- }
1768
- }
1769
- twins = [];
1770
- for (legend in bins) {
1771
- bin = bins[legend];
1772
- if (!bin.length) {
1773
- continue;
1774
- }
1775
- bin.sort(function(a, b) {
1776
- return a.item.date < b.item.date;
1777
- });
1778
- flags = (function() {
1779
- var _j, _len1, _ref4, _results;
1780
- _results = [];
1781
- for (i = _j = 0, _len1 = bin.length; _j < _len1; i = ++_j) {
1782
- _ref4 = bin[i], remoteSite = _ref4.remoteSite, item = _ref4.item;
1783
- if (i >= 8) {
1784
- break;
1785
- }
1786
- _results.push("<img class=\"remote\"\nsrc=\"http://" + remoteSite + "/favicon.png\"\ndata-slug=\"" + slug + "\"\ndata-site=\"" + remoteSite + "\"\ntitle=\"" + remoteSite + "\">");
1787
- }
1788
- return _results;
1789
- })();
1790
- twins.push("" + (flags.join('&nbsp;')) + " " + legend);
1791
- }
1792
- if (twins) {
1793
- return $page.find('.twins').html("<p>" + (twins.join(", ")) + "</p>");
1794
- }
1795
- }
1796
- };
1797
-
1798
- renderPageIntoPageElement = function(pageObject, $page) {
1799
- var $footer, $header, $journal, $story, $twins, host, slug, _ref;
1800
- $page.data("data", pageObject.getRawPage());
1801
- if (pageObject.isRemote()) {
1802
- $page.data("site", pageObject.getRemoteSite());
1803
- }
1804
- slug = $page.attr('id');
1805
- wiki.resolutionContext = pageObject.getContext();
1806
- $page.empty();
1807
- _ref = ['twins', 'header', 'story', 'journal', 'footer'].map(function(className) {
1808
- return $("<div />").addClass(className).appendTo($page);
1809
- }), $twins = _ref[0], $header = _ref[1], $story = _ref[2], $journal = _ref[3], $footer = _ref[4];
1810
- emitHeader($header, $page, pageObject);
1811
- pageObject.seqItems(function(item, done) {
1812
- var $item;
1813
- if ((item != null ? item.type : void 0) && (item != null ? item.id : void 0)) {
1814
- $item = $("<div class=\"item " + item.type + "\" data-id=\"" + item.id + "\">");
1815
- $story.append($item);
1816
- return plugin["do"]($item, item, done);
1817
- } else {
1818
- $story.append($("<div><p class=\"error\">Can't make sense of story[" + i + "]</p></div>"));
1819
- return done();
1820
- }
1821
- });
1822
- pageObject.seqActions(function(each, done) {
1823
- if (each.separator) {
1824
- addToJournal($journal, each.separator);
1825
- }
1826
- addToJournal($journal, each.action);
1827
- return done();
1828
- });
1829
- emitTwins($page);
1830
- $journal.append("<div class=\"control-buttons\">\n <a href=\"#\" class=\"button fork-page\" title=\"fork this page\">" + util.symbols['fork'] + "</a>\n <a href=\"#\" class=\"button add-factory\" title=\"add paragraph\">" + util.symbols['add'] + "</a>\n</div>");
1831
- host = pageObject.getRemoteSite() || location.host;
1832
- return $footer.append("<a id=\"license\" href=\"http://creativecommons.org/licenses/by-sa/3.0/\">CC BY-SA 3.0</a> .\n<a class=\"show-page-source\" href=\"/" + slug + ".json?random=" + (util.randomBytes(4)) + "\" title=\"source\">JSON</a> .\n<a href= \"//" + host + "/" + slug + ".html\">" + host + "</a>");
1833
- };
1834
-
1835
- wiki.buildPage = function(pageObject, $page) {
1836
- if (pageObject.isLocal()) {
1837
- $page.addClass('local');
1838
- }
1839
- if (pageObject.isRemote()) {
1840
- $page.addClass('remote');
1841
- }
1842
- if (pageObject.isPlugin()) {
1843
- $page.addClass('plugin');
1844
- }
1845
- renderPageIntoPageElement(pageObject, $page);
1846
- state.setUrl();
1847
- initDragging($page);
1848
- initAddButton($page);
1849
- return $page;
1850
- };
1851
-
1852
- module.exports = refresh = wiki.refresh = function() {
1853
- var $page, createGhostPage, emptyPage, pageInformation, rev, slug, whenGotten, _ref;
1854
- $page = $(this);
1855
- _ref = $page.attr('id').split('_rev'), slug = _ref[0], rev = _ref[1];
1856
- pageInformation = {
1857
- slug: slug,
1858
- rev: rev,
1859
- site: $page.data('site')
1860
- };
1861
- emptyPage = require('./page').emptyPage;
1862
- createGhostPage = function() {
1863
- var hit, hits, info, pageObject, result, site, title, _i, _len, _ref1;
1864
- title = $("a[href=\"/" + slug + ".html\"]:last").text() || slug;
1865
- pageObject = emptyPage();
1866
- pageObject.setTitle(title);
1867
- hits = [];
1868
- _ref1 = wiki.neighborhood;
1869
- for (site in _ref1) {
1870
- info = _ref1[site];
1871
- if (info.sitemap != null) {
1872
- result = _.find(info.sitemap, function(each) {
1873
- return each.slug === slug;
1874
- });
1875
- if (result != null) {
1876
- hits.push({
1877
- "type": "reference",
1878
- "site": site,
1879
- "slug": slug,
1880
- "title": result.title || slug,
1881
- "text": result.synopsis || ''
1882
- });
1883
- }
1884
- }
1885
- }
1886
- if (hits.length > 0) {
1887
- pageObject.addItem({
1888
- 'type': 'future',
1889
- 'text': 'We could not find this page in the expected context.',
1890
- 'title': title
1891
- });
1892
- pageObject.addItem({
1893
- 'type': 'paragraph',
1894
- 'text': "We did find the page in your current neighborhood."
1895
- });
1896
- for (_i = 0, _len = hits.length; _i < _len; _i++) {
1897
- hit = hits[_i];
1898
- pageObject.addItem(hit);
1899
- }
1900
- } else {
1901
- pageObject.addItem({
1902
- 'type': 'future',
1903
- 'text': 'We could not find this page.',
1904
- 'title': title
1905
- });
1906
- }
1907
- return wiki.buildPage(pageObject, $page).addClass('ghost');
1908
- };
1909
- whenGotten = function(pageObject) {
1910
- var site, _i, _len, _ref1, _results;
1911
- wiki.buildPage(pageObject, $page);
1912
- _ref1 = pageObject.getNeighbors(location.host);
1913
- _results = [];
1914
- for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
1915
- site = _ref1[_i];
1916
- _results.push(neighborhood.registerNeighbor(site));
1917
- }
1918
- return _results;
1919
- };
1920
- return pageHandler.get({
1921
- whenGotten: whenGotten,
1922
- whenNotGotten: createGhostPage,
1923
- pageInformation: pageInformation
1924
- });
1925
- };
1926
-
1927
- }).call(this);
1928
-
1929
- },{"./addToJournal":16,"./neighborhood":18,"./page":12,"./pageHandler":7,"./plugin":8,"./state":9,"./util":6,"./wiki":2,"underscore":17}],12:[function(require,module,exports){
1930
- (function() {
1931
- var asSlug, emptyPage, newPage, nowSections, util, _;
1932
-
1933
- util = require('./util');
1934
-
1935
- _ = require('underscore');
1936
-
1937
- asSlug = function(name) {
1938
- return name.replace(/\s/g, '-').replace(/[^A-Za-z0-9-]/g, '').toLowerCase();
1939
- };
1940
-
1941
- emptyPage = function() {
1942
- return newPage({}, null);
1943
- };
1944
-
1945
- nowSections = function(now) {
1946
- return [
1947
- {
1948
- symbol: '❄',
1949
- date: now - 1000 * 60 * 60 * 24 * 366,
1950
- period: 'a Year'
1951
- }, {
1952
- symbol: '⚘',
1953
- date: now - 1000 * 60 * 60 * 24 * 31 * 3,
1954
- period: 'a Season'
1955
- }, {
1956
- symbol: '⚪',
1957
- date: now - 1000 * 60 * 60 * 24 * 31,
1958
- period: 'a Month'
1959
- }, {
1960
- symbol: '☽',
1961
- date: now - 1000 * 60 * 60 * 24 * 7,
1962
- period: 'a Week'
1963
- }, {
1964
- symbol: '☀',
1965
- date: now - 1000 * 60 * 60 * 24,
1966
- period: 'a Day'
1967
- }, {
1968
- symbol: '⌚',
1969
- date: now - 1000 * 60 * 60,
1970
- period: 'an Hour'
1971
- }
1972
- ];
1973
- };
1974
-
1975
- newPage = function(json, site) {
1976
- var addItem, addParagraph, getContext, getNeighbors, getRawPage, getRemoteSite, getSlug, isLocal, isPlugin, isRemote, page, seqActions, seqItems, setTitle;
1977
- page = _.extend({}, util.emptyPage(), json);
1978
- page.story || (page.story = []);
1979
- page.journal || (page.journal = []);
1980
- getRawPage = function() {
1981
- return page;
1982
- };
1983
- getContext = function() {
1984
- var action, addContext, context, _i, _len, _ref;
1985
- context = ['view'];
1986
- if (isRemote()) {
1987
- context.push(site);
1988
- }
1989
- addContext = function(site) {
1990
- if ((site != null) && !_.include(context, site)) {
1991
- return context.push(site);
1992
- }
1993
- };
1994
- _ref = page.journal.slice(0).reverse();
1995
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1996
- action = _ref[_i];
1997
- addContext(action.site);
1998
- }
1999
- return context;
2000
- };
2001
- isPlugin = function() {
2002
- return page.plugin != null;
2003
- };
2004
- isRemote = function() {
2005
- return !(site === (void 0) || site === null || site === 'view' || site === 'origin' || site === 'local');
2006
- };
2007
- isLocal = function() {
2008
- return site === 'local';
2009
- };
2010
- getRemoteSite = function() {
2011
- if (isRemote()) {
2012
- return site;
2013
- }
2014
- return null;
2015
- };
2016
- getSlug = function() {
2017
- return asSlug(page.title);
2018
- };
2019
- getNeighbors = function(host) {
2020
- var action, item, neighbors, _i, _j, _len, _len1, _ref, _ref1;
2021
- neighbors = [];
2022
- if (isRemote()) {
2023
- neighbors.push(site);
2024
- } else {
2025
- if (host != null) {
2026
- neighbors.push(host);
2027
- }
2028
- }
2029
- _ref = page.story;
2030
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
2031
- item = _ref[_i];
2032
- if (item.site != null) {
2033
- neighbors.push(item.site);
2034
- }
2035
- }
2036
- _ref1 = page.journal;
2037
- for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
2038
- action = _ref1[_j];
2039
- if (action.site != null) {
2040
- neighbors.push(action.site);
2041
- }
2042
- }
2043
- return _.uniq(neighbors);
2044
- };
2045
- setTitle = function(title) {
2046
- return page.title = title;
2047
- };
2048
- addItem = function(item) {
2049
- item = _.extend({}, {
2050
- id: util.randomBytes(8)
2051
- }, item);
2052
- return page.story.push(item);
2053
- };
2054
- seqItems = function(each) {
2055
- var emitItem;
2056
- emitItem = function(i) {
2057
- if (i >= page.story.length) {
2058
- return;
2059
- }
2060
- return each(page.story[i], function() {
2061
- return emitItem(i + 1);
2062
- });
2063
- };
2064
- return emitItem(0);
2065
- };
2066
- addParagraph = function(text) {
2067
- var type;
2068
- type = "paragraph";
2069
- return addItem({
2070
- type: type,
2071
- text: text
2072
- });
2073
- };
2074
- seqActions = function(each) {
2075
- var emitAction, sections, smaller;
2076
- smaller = 0;
2077
- sections = nowSections((new Date).getTime());
2078
- emitAction = function(i) {
2079
- var action, bigger, section, separator, _i, _len;
2080
- if (i >= page.journal.length) {
2081
- return;
2082
- }
2083
- action = page.journal[i];
2084
- bigger = action.date || 0;
2085
- separator = null;
2086
- for (_i = 0, _len = sections.length; _i < _len; _i++) {
2087
- section = sections[_i];
2088
- if (section.date > smaller && section.date < bigger) {
2089
- separator = section;
2090
- }
2091
- }
2092
- smaller = bigger;
2093
- return each({
2094
- action: action,
2095
- separator: separator
2096
- }, function() {
2097
- return emitAction(i + 1);
2098
- });
2099
- };
2100
- return emitAction(0);
2101
- };
2102
- return {
2103
- getRawPage: getRawPage,
2104
- getContext: getContext,
2105
- isPlugin: isPlugin,
2106
- isRemote: isRemote,
2107
- isLocal: isLocal,
2108
- getRemoteSite: getRemoteSite,
2109
- getSlug: getSlug,
2110
- getNeighbors: getNeighbors,
2111
- setTitle: setTitle,
2112
- addItem: addItem,
2113
- addParagraph: addParagraph,
2114
- seqItems: seqItems,
2115
- seqActions: seqActions
2116
- };
2117
- };
2118
-
2119
- module.exports = {
2120
- newPage: newPage,
2121
- emptyPage: emptyPage
2122
- };
2123
-
2124
- }).call(this);
2125
-
2126
- },{"./util":6,"underscore":17}],17:[function(require,module,exports){
2127
- (function(){// Underscore.js 1.5.2
2128
- // http://underscorejs.org
2129
- // (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
2130
- // Underscore may be freely distributed under the MIT license.
2131
-
2132
- (function() {
2133
-
2134
- // Baseline setup
2135
- // --------------
2136
-
2137
- // Establish the root object, `window` in the browser, or `exports` on the server.
2138
- var root = this;
2139
-
2140
- // Save the previous value of the `_` variable.
2141
- var previousUnderscore = root._;
2142
-
2143
- // Establish the object that gets returned to break out of a loop iteration.
2144
- var breaker = {};
2145
-
2146
- // Save bytes in the minified (but not gzipped) version:
2147
- var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
2148
-
2149
- // Create quick reference variables for speed access to core prototypes.
2150
- var
2151
- push = ArrayProto.push,
2152
- slice = ArrayProto.slice,
2153
- concat = ArrayProto.concat,
2154
- toString = ObjProto.toString,
2155
- hasOwnProperty = ObjProto.hasOwnProperty;
2156
-
2157
- // All **ECMAScript 5** native function implementations that we hope to use
2158
- // are declared here.
2159
- var
2160
- nativeForEach = ArrayProto.forEach,
2161
- nativeMap = ArrayProto.map,
2162
- nativeReduce = ArrayProto.reduce,
2163
- nativeReduceRight = ArrayProto.reduceRight,
2164
- nativeFilter = ArrayProto.filter,
2165
- nativeEvery = ArrayProto.every,
2166
- nativeSome = ArrayProto.some,
2167
- nativeIndexOf = ArrayProto.indexOf,
2168
- nativeLastIndexOf = ArrayProto.lastIndexOf,
2169
- nativeIsArray = Array.isArray,
2170
- nativeKeys = Object.keys,
2171
- nativeBind = FuncProto.bind;
2172
-
2173
- // Create a safe reference to the Underscore object for use below.
2174
- var _ = function(obj) {
2175
- if (obj instanceof _) return obj;
2176
- if (!(this instanceof _)) return new _(obj);
2177
- this._wrapped = obj;
2178
- };
2179
-
2180
- // Export the Underscore object for **Node.js**, with
2181
- // backwards-compatibility for the old `require()` API. If we're in
2182
- // the browser, add `_` as a global object via a string identifier,
2183
- // for Closure Compiler "advanced" mode.
2184
- if (typeof exports !== 'undefined') {
2185
- if (typeof module !== 'undefined' && module.exports) {
2186
- exports = module.exports = _;
2187
- }
2188
- exports._ = _;
2189
- } else {
2190
- root._ = _;
2191
- }
2192
-
2193
- // Current version.
2194
- _.VERSION = '1.5.2';
2195
-
2196
- // Collection Functions
2197
- // --------------------
2198
-
2199
- // The cornerstone, an `each` implementation, aka `forEach`.
2200
- // Handles objects with the built-in `forEach`, arrays, and raw objects.
2201
- // Delegates to **ECMAScript 5**'s native `forEach` if available.
2202
- var each = _.each = _.forEach = function(obj, iterator, context) {
2203
- if (obj == null) return;
2204
- if (nativeForEach && obj.forEach === nativeForEach) {
2205
- obj.forEach(iterator, context);
2206
- } else if (obj.length === +obj.length) {
2207
- for (var i = 0, length = obj.length; i < length; i++) {
2208
- if (iterator.call(context, obj[i], i, obj) === breaker) return;
2209
- }
2210
- } else {
2211
- var keys = _.keys(obj);
2212
- for (var i = 0, length = keys.length; i < length; i++) {
2213
- if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
2214
- }
2215
- }
2216
- };
2217
-
2218
- // Return the results of applying the iterator to each element.
2219
- // Delegates to **ECMAScript 5**'s native `map` if available.
2220
- _.map = _.collect = function(obj, iterator, context) {
2221
- var results = [];
2222
- if (obj == null) return results;
2223
- if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
2224
- each(obj, function(value, index, list) {
2225
- results.push(iterator.call(context, value, index, list));
2226
- });
2227
- return results;
2228
- };
2229
-
2230
- var reduceError = 'Reduce of empty array with no initial value';
2231
-
2232
- // **Reduce** builds up a single result from a list of values, aka `inject`,
2233
- // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
2234
- _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
2235
- var initial = arguments.length > 2;
2236
- if (obj == null) obj = [];
2237
- if (nativeReduce && obj.reduce === nativeReduce) {
2238
- if (context) iterator = _.bind(iterator, context);
2239
- return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
2240
- }
2241
- each(obj, function(value, index, list) {
2242
- if (!initial) {
2243
- memo = value;
2244
- initial = true;
2245
- } else {
2246
- memo = iterator.call(context, memo, value, index, list);
2247
- }
2248
- });
2249
- if (!initial) throw new TypeError(reduceError);
2250
- return memo;
2251
- };
2252
-
2253
- // The right-associative version of reduce, also known as `foldr`.
2254
- // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
2255
- _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
2256
- var initial = arguments.length > 2;
2257
- if (obj == null) obj = [];
2258
- if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
2259
- if (context) iterator = _.bind(iterator, context);
2260
- return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
2261
- }
2262
- var length = obj.length;
2263
- if (length !== +length) {
2264
- var keys = _.keys(obj);
2265
- length = keys.length;
2266
- }
2267
- each(obj, function(value, index, list) {
2268
- index = keys ? keys[--length] : --length;
2269
- if (!initial) {
2270
- memo = obj[index];
2271
- initial = true;
2272
- } else {
2273
- memo = iterator.call(context, memo, obj[index], index, list);
2274
- }
2275
- });
2276
- if (!initial) throw new TypeError(reduceError);
2277
- return memo;
2278
- };
2279
-
2280
- // Return the first value which passes a truth test. Aliased as `detect`.
2281
- _.find = _.detect = function(obj, iterator, context) {
2282
- var result;
2283
- any(obj, function(value, index, list) {
2284
- if (iterator.call(context, value, index, list)) {
2285
- result = value;
2286
- return true;
2287
- }
2288
- });
2289
- return result;
2290
- };
2291
-
2292
- // Return all the elements that pass a truth test.
2293
- // Delegates to **ECMAScript 5**'s native `filter` if available.
2294
- // Aliased as `select`.
2295
- _.filter = _.select = function(obj, iterator, context) {
2296
- var results = [];
2297
- if (obj == null) return results;
2298
- if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
2299
- each(obj, function(value, index, list) {
2300
- if (iterator.call(context, value, index, list)) results.push(value);
2301
- });
2302
- return results;
2303
- };
2304
-
2305
- // Return all the elements for which a truth test fails.
2306
- _.reject = function(obj, iterator, context) {
2307
- return _.filter(obj, function(value, index, list) {
2308
- return !iterator.call(context, value, index, list);
2309
- }, context);
2310
- };
2311
-
2312
- // Determine whether all of the elements match a truth test.
2313
- // Delegates to **ECMAScript 5**'s native `every` if available.
2314
- // Aliased as `all`.
2315
- _.every = _.all = function(obj, iterator, context) {
2316
- iterator || (iterator = _.identity);
2317
- var result = true;
2318
- if (obj == null) return result;
2319
- if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
2320
- each(obj, function(value, index, list) {
2321
- if (!(result = result && iterator.call(context, value, index, list))) return breaker;
2322
- });
2323
- return !!result;
2324
- };
2325
-
2326
- // Determine if at least one element in the object matches a truth test.
2327
- // Delegates to **ECMAScript 5**'s native `some` if available.
2328
- // Aliased as `any`.
2329
- var any = _.some = _.any = function(obj, iterator, context) {
2330
- iterator || (iterator = _.identity);
2331
- var result = false;
2332
- if (obj == null) return result;
2333
- if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
2334
- each(obj, function(value, index, list) {
2335
- if (result || (result = iterator.call(context, value, index, list))) return breaker;
2336
- });
2337
- return !!result;
2338
- };
2339
-
2340
- // Determine if the array or object contains a given value (using `===`).
2341
- // Aliased as `include`.
2342
- _.contains = _.include = function(obj, target) {
2343
- if (obj == null) return false;
2344
- if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
2345
- return any(obj, function(value) {
2346
- return value === target;
2347
- });
2348
- };
2349
-
2350
- // Invoke a method (with arguments) on every item in a collection.
2351
- _.invoke = function(obj, method) {
2352
- var args = slice.call(arguments, 2);
2353
- var isFunc = _.isFunction(method);
2354
- return _.map(obj, function(value) {
2355
- return (isFunc ? method : value[method]).apply(value, args);
2356
- });
2357
- };
2358
-
2359
- // Convenience version of a common use case of `map`: fetching a property.
2360
- _.pluck = function(obj, key) {
2361
- return _.map(obj, function(value){ return value[key]; });
2362
- };
2363
-
2364
- // Convenience version of a common use case of `filter`: selecting only objects
2365
- // containing specific `key:value` pairs.
2366
- _.where = function(obj, attrs, first) {
2367
- if (_.isEmpty(attrs)) return first ? void 0 : [];
2368
- return _[first ? 'find' : 'filter'](obj, function(value) {
2369
- for (var key in attrs) {
2370
- if (attrs[key] !== value[key]) return false;
2371
- }
2372
- return true;
2373
- });
2374
- };
2375
-
2376
- // Convenience version of a common use case of `find`: getting the first object
2377
- // containing specific `key:value` pairs.
2378
- _.findWhere = function(obj, attrs) {
2379
- return _.where(obj, attrs, true);
2380
- };
2381
-
2382
- // Return the maximum element or (element-based computation).
2383
- // Can't optimize arrays of integers longer than 65,535 elements.
2384
- // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797)
2385
- _.max = function(obj, iterator, context) {
2386
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
2387
- return Math.max.apply(Math, obj);
2388
- }
2389
- if (!iterator && _.isEmpty(obj)) return -Infinity;
2390
- var result = {computed : -Infinity, value: -Infinity};
2391
- each(obj, function(value, index, list) {
2392
- var computed = iterator ? iterator.call(context, value, index, list) : value;
2393
- computed > result.computed && (result = {value : value, computed : computed});
2394
- });
2395
- return result.value;
2396
- };
2397
-
2398
- // Return the minimum element (or element-based computation).
2399
- _.min = function(obj, iterator, context) {
2400
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
2401
- return Math.min.apply(Math, obj);
2402
- }
2403
- if (!iterator && _.isEmpty(obj)) return Infinity;
2404
- var result = {computed : Infinity, value: Infinity};
2405
- each(obj, function(value, index, list) {
2406
- var computed = iterator ? iterator.call(context, value, index, list) : value;
2407
- computed < result.computed && (result = {value : value, computed : computed});
2408
- });
2409
- return result.value;
2410
- };
2411
-
2412
- // Shuffle an array, using the modern version of the
2413
- // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
2414
- _.shuffle = function(obj) {
2415
- var rand;
2416
- var index = 0;
2417
- var shuffled = [];
2418
- each(obj, function(value) {
2419
- rand = _.random(index++);
2420
- shuffled[index - 1] = shuffled[rand];
2421
- shuffled[rand] = value;
2422
- });
2423
- return shuffled;
2424
- };
2425
-
2426
- // Sample **n** random values from an array.
2427
- // If **n** is not specified, returns a single random element from the array.
2428
- // The internal `guard` argument allows it to work with `map`.
2429
- _.sample = function(obj, n, guard) {
2430
- if (arguments.length < 2 || guard) {
2431
- return obj[_.random(obj.length - 1)];
2432
- }
2433
- return _.shuffle(obj).slice(0, Math.max(0, n));
2434
- };
2435
-
2436
- // An internal function to generate lookup iterators.
2437
- var lookupIterator = function(value) {
2438
- return _.isFunction(value) ? value : function(obj){ return obj[value]; };
2439
- };
2440
-
2441
- // Sort the object's values by a criterion produced by an iterator.
2442
- _.sortBy = function(obj, value, context) {
2443
- var iterator = lookupIterator(value);
2444
- return _.pluck(_.map(obj, function(value, index, list) {
2445
- return {
2446
- value: value,
2447
- index: index,
2448
- criteria: iterator.call(context, value, index, list)
2449
- };
2450
- }).sort(function(left, right) {
2451
- var a = left.criteria;
2452
- var b = right.criteria;
2453
- if (a !== b) {
2454
- if (a > b || a === void 0) return 1;
2455
- if (a < b || b === void 0) return -1;
2456
- }
2457
- return left.index - right.index;
2458
- }), 'value');
2459
- };
2460
-
2461
- // An internal function used for aggregate "group by" operations.
2462
- var group = function(behavior) {
2463
- return function(obj, value, context) {
2464
- var result = {};
2465
- var iterator = value == null ? _.identity : lookupIterator(value);
2466
- each(obj, function(value, index) {
2467
- var key = iterator.call(context, value, index, obj);
2468
- behavior(result, key, value);
2469
- });
2470
- return result;
2471
- };
2472
- };
2473
-
2474
- // Groups the object's values by a criterion. Pass either a string attribute
2475
- // to group by, or a function that returns the criterion.
2476
- _.groupBy = group(function(result, key, value) {
2477
- (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
2478
- });
2479
-
2480
- // Indexes the object's values by a criterion, similar to `groupBy`, but for
2481
- // when you know that your index values will be unique.
2482
- _.indexBy = group(function(result, key, value) {
2483
- result[key] = value;
2484
- });
2485
-
2486
- // Counts instances of an object that group by a certain criterion. Pass
2487
- // either a string attribute to count by, or a function that returns the
2488
- // criterion.
2489
- _.countBy = group(function(result, key) {
2490
- _.has(result, key) ? result[key]++ : result[key] = 1;
2491
- });
2492
-
2493
- // Use a comparator function to figure out the smallest index at which
2494
- // an object should be inserted so as to maintain order. Uses binary search.
2495
- _.sortedIndex = function(array, obj, iterator, context) {
2496
- iterator = iterator == null ? _.identity : lookupIterator(iterator);
2497
- var value = iterator.call(context, obj);
2498
- var low = 0, high = array.length;
2499
- while (low < high) {
2500
- var mid = (low + high) >>> 1;
2501
- iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
2502
- }
2503
- return low;
2504
- };
2505
-
2506
- // Safely create a real, live array from anything iterable.
2507
- _.toArray = function(obj) {
2508
- if (!obj) return [];
2509
- if (_.isArray(obj)) return slice.call(obj);
2510
- if (obj.length === +obj.length) return _.map(obj, _.identity);
2511
- return _.values(obj);
2512
- };
2513
-
2514
- // Return the number of elements in an object.
2515
- _.size = function(obj) {
2516
- if (obj == null) return 0;
2517
- return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
2518
- };
2519
-
2520
- // Array Functions
2521
- // ---------------
2522
-
2523
- // Get the first element of an array. Passing **n** will return the first N
2524
- // values in the array. Aliased as `head` and `take`. The **guard** check
2525
- // allows it to work with `_.map`.
2526
- _.first = _.head = _.take = function(array, n, guard) {
2527
- if (array == null) return void 0;
2528
- return (n == null) || guard ? array[0] : slice.call(array, 0, n);
2529
- };
2530
-
2531
- // Returns everything but the last entry of the array. Especially useful on
2532
- // the arguments object. Passing **n** will return all the values in
2533
- // the array, excluding the last N. The **guard** check allows it to work with
2534
- // `_.map`.
2535
- _.initial = function(array, n, guard) {
2536
- return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
2537
- };
2538
-
2539
- // Get the last element of an array. Passing **n** will return the last N
2540
- // values in the array. The **guard** check allows it to work with `_.map`.
2541
- _.last = function(array, n, guard) {
2542
- if (array == null) return void 0;
2543
- if ((n == null) || guard) {
2544
- return array[array.length - 1];
2545
- } else {
2546
- return slice.call(array, Math.max(array.length - n, 0));
2547
- }
2548
- };
2549
-
2550
- // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
2551
- // Especially useful on the arguments object. Passing an **n** will return
2552
- // the rest N values in the array. The **guard**
2553
- // check allows it to work with `_.map`.
2554
- _.rest = _.tail = _.drop = function(array, n, guard) {
2555
- return slice.call(array, (n == null) || guard ? 1 : n);
2556
- };
2557
-
2558
- // Trim out all falsy values from an array.
2559
- _.compact = function(array) {
2560
- return _.filter(array, _.identity);
2561
- };
2562
-
2563
- // Internal implementation of a recursive `flatten` function.
2564
- var flatten = function(input, shallow, output) {
2565
- if (shallow && _.every(input, _.isArray)) {
2566
- return concat.apply(output, input);
2567
- }
2568
- each(input, function(value) {
2569
- if (_.isArray(value) || _.isArguments(value)) {
2570
- shallow ? push.apply(output, value) : flatten(value, shallow, output);
2571
- } else {
2572
- output.push(value);
2573
- }
2574
- });
2575
- return output;
2576
- };
2577
-
2578
- // Flatten out an array, either recursively (by default), or just one level.
2579
- _.flatten = function(array, shallow) {
2580
- return flatten(array, shallow, []);
2581
- };
2582
-
2583
- // Return a version of the array that does not contain the specified value(s).
2584
- _.without = function(array) {
2585
- return _.difference(array, slice.call(arguments, 1));
2586
- };
2587
-
2588
- // Produce a duplicate-free version of the array. If the array has already
2589
- // been sorted, you have the option of using a faster algorithm.
2590
- // Aliased as `unique`.
2591
- _.uniq = _.unique = function(array, isSorted, iterator, context) {
2592
- if (_.isFunction(isSorted)) {
2593
- context = iterator;
2594
- iterator = isSorted;
2595
- isSorted = false;
2596
- }
2597
- var initial = iterator ? _.map(array, iterator, context) : array;
2598
- var results = [];
2599
- var seen = [];
2600
- each(initial, function(value, index) {
2601
- if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
2602
- seen.push(value);
2603
- results.push(array[index]);
2604
- }
2605
- });
2606
- return results;
2607
- };
2608
-
2609
- // Produce an array that contains the union: each distinct element from all of
2610
- // the passed-in arrays.
2611
- _.union = function() {
2612
- return _.uniq(_.flatten(arguments, true));
2613
- };
2614
-
2615
- // Produce an array that contains every item shared between all the
2616
- // passed-in arrays.
2617
- _.intersection = function(array) {
2618
- var rest = slice.call(arguments, 1);
2619
- return _.filter(_.uniq(array), function(item) {
2620
- return _.every(rest, function(other) {
2621
- return _.indexOf(other, item) >= 0;
2622
- });
2623
- });
2624
- };
2625
-
2626
- // Take the difference between one array and a number of other arrays.
2627
- // Only the elements present in just the first array will remain.
2628
- _.difference = function(array) {
2629
- var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
2630
- return _.filter(array, function(value){ return !_.contains(rest, value); });
2631
- };
2632
-
2633
- // Zip together multiple lists into a single array -- elements that share
2634
- // an index go together.
2635
- _.zip = function() {
2636
- var length = _.max(_.pluck(arguments, "length").concat(0));
2637
- var results = new Array(length);
2638
- for (var i = 0; i < length; i++) {
2639
- results[i] = _.pluck(arguments, '' + i);
2640
- }
2641
- return results;
2642
- };
2643
-
2644
- // Converts lists into objects. Pass either a single array of `[key, value]`
2645
- // pairs, or two parallel arrays of the same length -- one of keys, and one of
2646
- // the corresponding values.
2647
- _.object = function(list, values) {
2648
- if (list == null) return {};
2649
- var result = {};
2650
- for (var i = 0, length = list.length; i < length; i++) {
2651
- if (values) {
2652
- result[list[i]] = values[i];
2653
- } else {
2654
- result[list[i][0]] = list[i][1];
2655
- }
2656
- }
2657
- return result;
2658
- };
2659
-
2660
- // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
2661
- // we need this function. Return the position of the first occurrence of an
2662
- // item in an array, or -1 if the item is not included in the array.
2663
- // Delegates to **ECMAScript 5**'s native `indexOf` if available.
2664
- // If the array is large and already in sort order, pass `true`
2665
- // for **isSorted** to use binary search.
2666
- _.indexOf = function(array, item, isSorted) {
2667
- if (array == null) return -1;
2668
- var i = 0, length = array.length;
2669
- if (isSorted) {
2670
- if (typeof isSorted == 'number') {
2671
- i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted);
2672
- } else {
2673
- i = _.sortedIndex(array, item);
2674
- return array[i] === item ? i : -1;
2675
- }
2676
- }
2677
- if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
2678
- for (; i < length; i++) if (array[i] === item) return i;
2679
- return -1;
2680
- };
2681
-
2682
- // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
2683
- _.lastIndexOf = function(array, item, from) {
2684
- if (array == null) return -1;
2685
- var hasIndex = from != null;
2686
- if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
2687
- return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
2688
- }
2689
- var i = (hasIndex ? from : array.length);
2690
- while (i--) if (array[i] === item) return i;
2691
- return -1;
2692
- };
2693
-
2694
- // Generate an integer Array containing an arithmetic progression. A port of
2695
- // the native Python `range()` function. See
2696
- // [the Python documentation](http://docs.python.org/library/functions.html#range).
2697
- _.range = function(start, stop, step) {
2698
- if (arguments.length <= 1) {
2699
- stop = start || 0;
2700
- start = 0;
2701
- }
2702
- step = arguments[2] || 1;
2703
-
2704
- var length = Math.max(Math.ceil((stop - start) / step), 0);
2705
- var idx = 0;
2706
- var range = new Array(length);
2707
-
2708
- while(idx < length) {
2709
- range[idx++] = start;
2710
- start += step;
2711
- }
2712
-
2713
- return range;
2714
- };
2715
-
2716
- // Function (ahem) Functions
2717
- // ------------------
2718
-
2719
- // Reusable constructor function for prototype setting.
2720
- var ctor = function(){};
2721
-
2722
- // Create a function bound to a given object (assigning `this`, and arguments,
2723
- // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
2724
- // available.
2725
- _.bind = function(func, context) {
2726
- var args, bound;
2727
- if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
2728
- if (!_.isFunction(func)) throw new TypeError;
2729
- args = slice.call(arguments, 2);
2730
- return bound = function() {
2731
- if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
2732
- ctor.prototype = func.prototype;
2733
- var self = new ctor;
2734
- ctor.prototype = null;
2735
- var result = func.apply(self, args.concat(slice.call(arguments)));
2736
- if (Object(result) === result) return result;
2737
- return self;
2738
- };
2739
- };
2740
-
2741
- // Partially apply a function by creating a version that has had some of its
2742
- // arguments pre-filled, without changing its dynamic `this` context.
2743
- _.partial = function(func) {
2744
- var args = slice.call(arguments, 1);
2745
- return function() {
2746
- return func.apply(this, args.concat(slice.call(arguments)));
2747
- };
2748
- };
2749
-
2750
- // Bind all of an object's methods to that object. Useful for ensuring that
2751
- // all callbacks defined on an object belong to it.
2752
- _.bindAll = function(obj) {
2753
- var funcs = slice.call(arguments, 1);
2754
- if (funcs.length === 0) throw new Error("bindAll must be passed function names");
2755
- each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
2756
- return obj;
2757
- };
2758
-
2759
- // Memoize an expensive function by storing its results.
2760
- _.memoize = function(func, hasher) {
2761
- var memo = {};
2762
- hasher || (hasher = _.identity);
2763
- return function() {
2764
- var key = hasher.apply(this, arguments);
2765
- return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
2766
- };
2767
- };
2768
-
2769
- // Delays a function for the given number of milliseconds, and then calls
2770
- // it with the arguments supplied.
2771
- _.delay = function(func, wait) {
2772
- var args = slice.call(arguments, 2);
2773
- return setTimeout(function(){ return func.apply(null, args); }, wait);
2774
- };
2775
-
2776
- // Defers a function, scheduling it to run after the current call stack has
2777
- // cleared.
2778
- _.defer = function(func) {
2779
- return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
2780
- };
2781
-
2782
- // Returns a function, that, when invoked, will only be triggered at most once
2783
- // during a given window of time. Normally, the throttled function will run
2784
- // as much as it can, without ever going more than once per `wait` duration;
2785
- // but if you'd like to disable the execution on the leading edge, pass
2786
- // `{leading: false}`. To disable execution on the trailing edge, ditto.
2787
- _.throttle = function(func, wait, options) {
2788
- var context, args, result;
2789
- var timeout = null;
2790
- var previous = 0;
2791
- options || (options = {});
2792
- var later = function() {
2793
- previous = options.leading === false ? 0 : new Date;
2794
- timeout = null;
2795
- result = func.apply(context, args);
2796
- };
2797
- return function() {
2798
- var now = new Date;
2799
- if (!previous && options.leading === false) previous = now;
2800
- var remaining = wait - (now - previous);
2801
- context = this;
2802
- args = arguments;
2803
- if (remaining <= 0) {
2804
- clearTimeout(timeout);
2805
- timeout = null;
2806
- previous = now;
2807
- result = func.apply(context, args);
2808
- } else if (!timeout && options.trailing !== false) {
2809
- timeout = setTimeout(later, remaining);
2810
- }
2811
- return result;
2812
- };
2813
- };
2814
-
2815
- // Returns a function, that, as long as it continues to be invoked, will not
2816
- // be triggered. The function will be called after it stops being called for
2817
- // N milliseconds. If `immediate` is passed, trigger the function on the
2818
- // leading edge, instead of the trailing.
2819
- _.debounce = function(func, wait, immediate) {
2820
- var timeout, args, context, timestamp, result;
2821
- return function() {
2822
- context = this;
2823
- args = arguments;
2824
- timestamp = new Date();
2825
- var later = function() {
2826
- var last = (new Date()) - timestamp;
2827
- if (last < wait) {
2828
- timeout = setTimeout(later, wait - last);
2829
- } else {
2830
- timeout = null;
2831
- if (!immediate) result = func.apply(context, args);
2832
- }
2833
- };
2834
- var callNow = immediate && !timeout;
2835
- if (!timeout) {
2836
- timeout = setTimeout(later, wait);
2837
- }
2838
- if (callNow) result = func.apply(context, args);
2839
- return result;
2840
- };
2841
- };
2842
-
2843
- // Returns a function that will be executed at most one time, no matter how
2844
- // often you call it. Useful for lazy initialization.
2845
- _.once = function(func) {
2846
- var ran = false, memo;
2847
- return function() {
2848
- if (ran) return memo;
2849
- ran = true;
2850
- memo = func.apply(this, arguments);
2851
- func = null;
2852
- return memo;
2853
- };
2854
- };
2855
-
2856
- // Returns the first function passed as an argument to the second,
2857
- // allowing you to adjust arguments, run code before and after, and
2858
- // conditionally execute the original function.
2859
- _.wrap = function(func, wrapper) {
2860
- return function() {
2861
- var args = [func];
2862
- push.apply(args, arguments);
2863
- return wrapper.apply(this, args);
2864
- };
2865
- };
2866
-
2867
- // Returns a function that is the composition of a list of functions, each
2868
- // consuming the return value of the function that follows.
2869
- _.compose = function() {
2870
- var funcs = arguments;
2871
- return function() {
2872
- var args = arguments;
2873
- for (var i = funcs.length - 1; i >= 0; i--) {
2874
- args = [funcs[i].apply(this, args)];
2875
- }
2876
- return args[0];
2877
- };
2878
- };
2879
-
2880
- // Returns a function that will only be executed after being called N times.
2881
- _.after = function(times, func) {
2882
- return function() {
2883
- if (--times < 1) {
2884
- return func.apply(this, arguments);
2885
- }
2886
- };
2887
- };
2888
-
2889
- // Object Functions
2890
- // ----------------
2891
-
2892
- // Retrieve the names of an object's properties.
2893
- // Delegates to **ECMAScript 5**'s native `Object.keys`
2894
- _.keys = nativeKeys || function(obj) {
2895
- if (obj !== Object(obj)) throw new TypeError('Invalid object');
2896
- var keys = [];
2897
- for (var key in obj) if (_.has(obj, key)) keys.push(key);
2898
- return keys;
2899
- };
2900
-
2901
- // Retrieve the values of an object's properties.
2902
- _.values = function(obj) {
2903
- var keys = _.keys(obj);
2904
- var length = keys.length;
2905
- var values = new Array(length);
2906
- for (var i = 0; i < length; i++) {
2907
- values[i] = obj[keys[i]];
2908
- }
2909
- return values;
2910
- };
2911
-
2912
- // Convert an object into a list of `[key, value]` pairs.
2913
- _.pairs = function(obj) {
2914
- var keys = _.keys(obj);
2915
- var length = keys.length;
2916
- var pairs = new Array(length);
2917
- for (var i = 0; i < length; i++) {
2918
- pairs[i] = [keys[i], obj[keys[i]]];
2919
- }
2920
- return pairs;
2921
- };
2922
-
2923
- // Invert the keys and values of an object. The values must be serializable.
2924
- _.invert = function(obj) {
2925
- var result = {};
2926
- var keys = _.keys(obj);
2927
- for (var i = 0, length = keys.length; i < length; i++) {
2928
- result[obj[keys[i]]] = keys[i];
2929
- }
2930
- return result;
2931
- };
2932
-
2933
- // Return a sorted list of the function names available on the object.
2934
- // Aliased as `methods`
2935
- _.functions = _.methods = function(obj) {
2936
- var names = [];
2937
- for (var key in obj) {
2938
- if (_.isFunction(obj[key])) names.push(key);
2939
- }
2940
- return names.sort();
2941
- };
2942
-
2943
- // Extend a given object with all the properties in passed-in object(s).
2944
- _.extend = function(obj) {
2945
- each(slice.call(arguments, 1), function(source) {
2946
- if (source) {
2947
- for (var prop in source) {
2948
- obj[prop] = source[prop];
2949
- }
2950
- }
2951
- });
2952
- return obj;
2953
- };
2954
-
2955
- // Return a copy of the object only containing the whitelisted properties.
2956
- _.pick = function(obj) {
2957
- var copy = {};
2958
- var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
2959
- each(keys, function(key) {
2960
- if (key in obj) copy[key] = obj[key];
2961
- });
2962
- return copy;
2963
- };
2964
-
2965
- // Return a copy of the object without the blacklisted properties.
2966
- _.omit = function(obj) {
2967
- var copy = {};
2968
- var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
2969
- for (var key in obj) {
2970
- if (!_.contains(keys, key)) copy[key] = obj[key];
2971
- }
2972
- return copy;
2973
- };
2974
-
2975
- // Fill in a given object with default properties.
2976
- _.defaults = function(obj) {
2977
- each(slice.call(arguments, 1), function(source) {
2978
- if (source) {
2979
- for (var prop in source) {
2980
- if (obj[prop] === void 0) obj[prop] = source[prop];
2981
- }
2982
- }
2983
- });
2984
- return obj;
2985
- };
2986
-
2987
- // Create a (shallow-cloned) duplicate of an object.
2988
- _.clone = function(obj) {
2989
- if (!_.isObject(obj)) return obj;
2990
- return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
2991
- };
2992
-
2993
- // Invokes interceptor with the obj, and then returns obj.
2994
- // The primary purpose of this method is to "tap into" a method chain, in
2995
- // order to perform operations on intermediate results within the chain.
2996
- _.tap = function(obj, interceptor) {
2997
- interceptor(obj);
2998
- return obj;
2999
- };
3000
-
3001
- // Internal recursive comparison function for `isEqual`.
3002
- var eq = function(a, b, aStack, bStack) {
3003
- // Identical objects are equal. `0 === -0`, but they aren't identical.
3004
- // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
3005
- if (a === b) return a !== 0 || 1 / a == 1 / b;
3006
- // A strict comparison is necessary because `null == undefined`.
3007
- if (a == null || b == null) return a === b;
3008
- // Unwrap any wrapped objects.
3009
- if (a instanceof _) a = a._wrapped;
3010
- if (b instanceof _) b = b._wrapped;
3011
- // Compare `[[Class]]` names.
3012
- var className = toString.call(a);
3013
- if (className != toString.call(b)) return false;
3014
- switch (className) {
3015
- // Strings, numbers, dates, and booleans are compared by value.
3016
- case '[object String]':
3017
- // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
3018
- // equivalent to `new String("5")`.
3019
- return a == String(b);
3020
- case '[object Number]':
3021
- // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
3022
- // other numeric values.
3023
- return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
3024
- case '[object Date]':
3025
- case '[object Boolean]':
3026
- // Coerce dates and booleans to numeric primitive values. Dates are compared by their
3027
- // millisecond representations. Note that invalid dates with millisecond representations
3028
- // of `NaN` are not equivalent.
3029
- return +a == +b;
3030
- // RegExps are compared by their source patterns and flags.
3031
- case '[object RegExp]':
3032
- return a.source == b.source &&
3033
- a.global == b.global &&
3034
- a.multiline == b.multiline &&
3035
- a.ignoreCase == b.ignoreCase;
3036
- }
3037
- if (typeof a != 'object' || typeof b != 'object') return false;
3038
- // Assume equality for cyclic structures. The algorithm for detecting cyclic
3039
- // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
3040
- var length = aStack.length;
3041
- while (length--) {
3042
- // Linear search. Performance is inversely proportional to the number of
3043
- // unique nested structures.
3044
- if (aStack[length] == a) return bStack[length] == b;
3045
- }
3046
- // Objects with different constructors are not equivalent, but `Object`s
3047
- // from different frames are.
3048
- var aCtor = a.constructor, bCtor = b.constructor;
3049
- if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
3050
- _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
3051
- return false;
3052
- }
3053
- // Add the first object to the stack of traversed objects.
3054
- aStack.push(a);
3055
- bStack.push(b);
3056
- var size = 0, result = true;
3057
- // Recursively compare objects and arrays.
3058
- if (className == '[object Array]') {
3059
- // Compare array lengths to determine if a deep comparison is necessary.
3060
- size = a.length;
3061
- result = size == b.length;
3062
- if (result) {
3063
- // Deep compare the contents, ignoring non-numeric properties.
3064
- while (size--) {
3065
- if (!(result = eq(a[size], b[size], aStack, bStack))) break;
3066
- }
3067
- }
3068
- } else {
3069
- // Deep compare objects.
3070
- for (var key in a) {
3071
- if (_.has(a, key)) {
3072
- // Count the expected number of properties.
3073
- size++;
3074
- // Deep compare each member.
3075
- if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
3076
- }
3077
- }
3078
- // Ensure that both objects contain the same number of properties.
3079
- if (result) {
3080
- for (key in b) {
3081
- if (_.has(b, key) && !(size--)) break;
3082
- }
3083
- result = !size;
3084
- }
3085
- }
3086
- // Remove the first object from the stack of traversed objects.
3087
- aStack.pop();
3088
- bStack.pop();
3089
- return result;
3090
- };
3091
-
3092
- // Perform a deep comparison to check if two objects are equal.
3093
- _.isEqual = function(a, b) {
3094
- return eq(a, b, [], []);
3095
- };
3096
-
3097
- // Is a given array, string, or object empty?
3098
- // An "empty" object has no enumerable own-properties.
3099
- _.isEmpty = function(obj) {
3100
- if (obj == null) return true;
3101
- if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
3102
- for (var key in obj) if (_.has(obj, key)) return false;
3103
- return true;
3104
- };
3105
-
3106
- // Is a given value a DOM element?
3107
- _.isElement = function(obj) {
3108
- return !!(obj && obj.nodeType === 1);
3109
- };
3110
-
3111
- // Is a given value an array?
3112
- // Delegates to ECMA5's native Array.isArray
3113
- _.isArray = nativeIsArray || function(obj) {
3114
- return toString.call(obj) == '[object Array]';
3115
- };
3116
-
3117
- // Is a given variable an object?
3118
- _.isObject = function(obj) {
3119
- return obj === Object(obj);
3120
- };
3121
-
3122
- // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
3123
- each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
3124
- _['is' + name] = function(obj) {
3125
- return toString.call(obj) == '[object ' + name + ']';
3126
- };
3127
- });
3128
-
3129
- // Define a fallback version of the method in browsers (ahem, IE), where
3130
- // there isn't any inspectable "Arguments" type.
3131
- if (!_.isArguments(arguments)) {
3132
- _.isArguments = function(obj) {
3133
- return !!(obj && _.has(obj, 'callee'));
3134
- };
3135
- }
3136
-
3137
- // Optimize `isFunction` if appropriate.
3138
- if (typeof (/./) !== 'function') {
3139
- _.isFunction = function(obj) {
3140
- return typeof obj === 'function';
3141
- };
3142
- }
3143
-
3144
- // Is a given object a finite number?
3145
- _.isFinite = function(obj) {
3146
- return isFinite(obj) && !isNaN(parseFloat(obj));
3147
- };
3148
-
3149
- // Is the given value `NaN`? (NaN is the only number which does not equal itself).
3150
- _.isNaN = function(obj) {
3151
- return _.isNumber(obj) && obj != +obj;
3152
- };
3153
-
3154
- // Is a given value a boolean?
3155
- _.isBoolean = function(obj) {
3156
- return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
3157
- };
3158
-
3159
- // Is a given value equal to null?
3160
- _.isNull = function(obj) {
3161
- return obj === null;
3162
- };
3163
-
3164
- // Is a given variable undefined?
3165
- _.isUndefined = function(obj) {
3166
- return obj === void 0;
3167
- };
3168
-
3169
- // Shortcut function for checking if an object has a given property directly
3170
- // on itself (in other words, not on a prototype).
3171
- _.has = function(obj, key) {
3172
- return hasOwnProperty.call(obj, key);
3173
- };
3174
-
3175
- // Utility Functions
3176
- // -----------------
3177
-
3178
- // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
3179
- // previous owner. Returns a reference to the Underscore object.
3180
- _.noConflict = function() {
3181
- root._ = previousUnderscore;
3182
- return this;
3183
- };
3184
-
3185
- // Keep the identity function around for default iterators.
3186
- _.identity = function(value) {
3187
- return value;
3188
- };
3189
-
3190
- // Run a function **n** times.
3191
- _.times = function(n, iterator, context) {
3192
- var accum = Array(Math.max(0, n));
3193
- for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
3194
- return accum;
3195
- };
3196
-
3197
- // Return a random integer between min and max (inclusive).
3198
- _.random = function(min, max) {
3199
- if (max == null) {
3200
- max = min;
3201
- min = 0;
3202
- }
3203
- return min + Math.floor(Math.random() * (max - min + 1));
3204
- };
3205
-
3206
- // List of HTML entities for escaping.
3207
- var entityMap = {
3208
- escape: {
3209
- '&': '&amp;',
3210
- '<': '&lt;',
3211
- '>': '&gt;',
3212
- '"': '&quot;',
3213
- "'": '&#x27;'
3214
- }
3215
- };
3216
- entityMap.unescape = _.invert(entityMap.escape);
3217
-
3218
- // Regexes containing the keys and values listed immediately above.
3219
- var entityRegexes = {
3220
- escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
3221
- unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
3222
- };
3223
-
3224
- // Functions for escaping and unescaping strings to/from HTML interpolation.
3225
- _.each(['escape', 'unescape'], function(method) {
3226
- _[method] = function(string) {
3227
- if (string == null) return '';
3228
- return ('' + string).replace(entityRegexes[method], function(match) {
3229
- return entityMap[method][match];
3230
- });
3231
- };
3232
- });
3233
-
3234
- // If the value of the named `property` is a function then invoke it with the
3235
- // `object` as context; otherwise, return it.
3236
- _.result = function(object, property) {
3237
- if (object == null) return void 0;
3238
- var value = object[property];
3239
- return _.isFunction(value) ? value.call(object) : value;
3240
- };
3241
-
3242
- // Add your own custom functions to the Underscore object.
3243
- _.mixin = function(obj) {
3244
- each(_.functions(obj), function(name) {
3245
- var func = _[name] = obj[name];
3246
- _.prototype[name] = function() {
3247
- var args = [this._wrapped];
3248
- push.apply(args, arguments);
3249
- return result.call(this, func.apply(_, args));
3250
- };
3251
- });
3252
- };
3253
-
3254
- // Generate a unique integer id (unique within the entire client session).
3255
- // Useful for temporary DOM ids.
3256
- var idCounter = 0;
3257
- _.uniqueId = function(prefix) {
3258
- var id = ++idCounter + '';
3259
- return prefix ? prefix + id : id;
3260
- };
3261
-
3262
- // By default, Underscore uses ERB-style template delimiters, change the
3263
- // following template settings to use alternative delimiters.
3264
- _.templateSettings = {
3265
- evaluate : /<%([\s\S]+?)%>/g,
3266
- interpolate : /<%=([\s\S]+?)%>/g,
3267
- escape : /<%-([\s\S]+?)%>/g
3268
- };
3269
-
3270
- // When customizing `templateSettings`, if you don't want to define an
3271
- // interpolation, evaluation or escaping regex, we need one that is
3272
- // guaranteed not to match.
3273
- var noMatch = /(.)^/;
3274
-
3275
- // Certain characters need to be escaped so that they can be put into a
3276
- // string literal.
3277
- var escapes = {
3278
- "'": "'",
3279
- '\\': '\\',
3280
- '\r': 'r',
3281
- '\n': 'n',
3282
- '\t': 't',
3283
- '\u2028': 'u2028',
3284
- '\u2029': 'u2029'
3285
- };
3286
-
3287
- var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
3288
-
3289
- // JavaScript micro-templating, similar to John Resig's implementation.
3290
- // Underscore templating handles arbitrary delimiters, preserves whitespace,
3291
- // and correctly escapes quotes within interpolated code.
3292
- _.template = function(text, data, settings) {
3293
- var render;
3294
- settings = _.defaults({}, settings, _.templateSettings);
3295
-
3296
- // Combine delimiters into one regular expression via alternation.
3297
- var matcher = new RegExp([
3298
- (settings.escape || noMatch).source,
3299
- (settings.interpolate || noMatch).source,
3300
- (settings.evaluate || noMatch).source
3301
- ].join('|') + '|$', 'g');
3302
-
3303
- // Compile the template source, escaping string literals appropriately.
3304
- var index = 0;
3305
- var source = "__p+='";
3306
- text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
3307
- source += text.slice(index, offset)
3308
- .replace(escaper, function(match) { return '\\' + escapes[match]; });
3309
-
3310
- if (escape) {
3311
- source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
3312
- }
3313
- if (interpolate) {
3314
- source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
3315
- }
3316
- if (evaluate) {
3317
- source += "';\n" + evaluate + "\n__p+='";
3318
- }
3319
- index = offset + match.length;
3320
- return match;
3321
- });
3322
- source += "';\n";
3323
-
3324
- // If a variable is not specified, place data values in local scope.
3325
- if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
3326
-
3327
- source = "var __t,__p='',__j=Array.prototype.join," +
3328
- "print=function(){__p+=__j.call(arguments,'');};\n" +
3329
- source + "return __p;\n";
3330
-
3331
- try {
3332
- render = new Function(settings.variable || 'obj', '_', source);
3333
- } catch (e) {
3334
- e.source = source;
3335
- throw e;
3336
- }
3337
-
3338
- if (data) return render(data, _);
3339
- var template = function(data) {
3340
- return render.call(this, data, _);
3341
- };
3342
-
3343
- // Provide the compiled function source as a convenience for precompilation.
3344
- template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
3345
-
3346
- return template;
3347
- };
3348
-
3349
- // Add a "chain" function, which will delegate to the wrapper.
3350
- _.chain = function(obj) {
3351
- return _(obj).chain();
3352
- };
3353
-
3354
- // OOP
3355
- // ---------------
3356
- // If Underscore is called as a function, it returns a wrapped object that
3357
- // can be used OO-style. This wrapper holds altered versions of all the
3358
- // underscore functions. Wrapped objects may be chained.
3359
-
3360
- // Helper function to continue chaining intermediate results.
3361
- var result = function(obj) {
3362
- return this._chain ? _(obj).chain() : obj;
3363
- };
3364
-
3365
- // Add all of the Underscore functions to the wrapper object.
3366
- _.mixin(_);
3367
-
3368
- // Add all mutator Array functions to the wrapper.
3369
- each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
3370
- var method = ArrayProto[name];
3371
- _.prototype[name] = function() {
3372
- var obj = this._wrapped;
3373
- method.apply(obj, arguments);
3374
- if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
3375
- return result.call(this, obj);
3376
- };
3377
- });
3378
-
3379
- // Add all accessor Array functions to the wrapper.
3380
- each(['concat', 'join', 'slice'], function(name) {
3381
- var method = ArrayProto[name];
3382
- _.prototype[name] = function() {
3383
- return result.call(this, method.apply(this._wrapped, arguments));
3384
- };
3385
- });
3386
-
3387
- _.extend(_.prototype, {
3388
-
3389
- // Start chaining a wrapped Underscore object.
3390
- chain: function() {
3391
- this._chain = true;
3392
- return this;
3393
- },
3394
-
3395
- // Extracts the result from a wrapped and chained object.
3396
- value: function() {
3397
- return this._wrapped;
3398
- }
3399
-
3400
- });
3401
-
3402
- }).call(this);
3403
-
3404
- })()
3405
- },{}],19:[function(require,module,exports){
3406
- (function() {
3407
- var active, createSearch, emptyPage, util, wiki;
3408
-
3409
- wiki = require('./wiki');
3410
-
3411
- util = require('./util');
3412
-
3413
- active = require('./active');
3414
-
3415
- emptyPage = require('./page').emptyPage;
3416
-
3417
- createSearch = function(_arg) {
3418
- var neighborhood, performSearch;
3419
- neighborhood = _arg.neighborhood;
3420
- performSearch = function(searchQuery) {
3421
- var $resultPage, result, resultPage, searchResults, tally, _i, _len, _ref;
3422
- searchResults = neighborhood.search(searchQuery);
3423
- tally = searchResults.tally;
3424
- resultPage = emptyPage();
3425
- resultPage.setTitle("Search for '" + searchQuery + "'");
3426
- resultPage.addParagraph("String '" + searchQuery + "' found on " + (tally.finds || 'none') + " of " + (tally.pages || 'no') + " pages from " + (tally.sites || 'no') + " sites.\nText matched on " + (tally.title || 'no') + " titles, " + (tally.text || 'no') + " paragraphs, and " + (tally.slug || 'no') + " slugs.\nElapsed time " + tally.msec + " milliseconds.");
3427
- _ref = searchResults.finds;
3428
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
3429
- result = _ref[_i];
3430
- resultPage.addItem({
3431
- "type": "reference",
3432
- "site": result.site,
3433
- "slug": result.page.slug,
3434
- "title": result.page.title,
3435
- "text": result.page.synopsis || ''
3436
- });
3437
- }
3438
- $resultPage = wiki.createPage(resultPage.getSlug()).addClass('ghost');
3439
- $resultPage.appendTo($('.main'));
3440
- wiki.buildPage(resultPage, $resultPage);
3441
- return active.set($('.page').last());
3442
- };
3443
- return {
3444
- performSearch: performSearch
3445
- };
3446
- };
3447
-
3448
- module.exports = createSearch;
3449
-
3450
- }).call(this);
3451
-
3452
- },{"./active":10,"./page":12,"./util":6,"./wiki":2}],18:[function(require,module,exports){
3453
- (function() {
3454
- var active, createSearch, neighborhood, nextAvailableFetch, nextFetchInterval, populateSiteInfoFor, util, wiki, _,
3455
- __hasProp = {}.hasOwnProperty;
3456
-
3457
- _ = require('underscore');
3458
-
3459
- wiki = require('./wiki');
3460
-
3461
- active = require('./active');
3462
-
3463
- util = require('./util');
3464
-
3465
- createSearch = require('./search');
3466
-
3467
- module.exports = neighborhood = {};
3468
-
3469
- if (wiki.neighborhood == null) {
3470
- wiki.neighborhood = {};
3471
- }
3472
-
3473
- nextAvailableFetch = 0;
3474
-
3475
- nextFetchInterval = 2000;
3476
-
3477
- populateSiteInfoFor = function(site, neighborInfo) {
3478
- var fetchMap, now, transition;
3479
- if (neighborInfo.sitemapRequestInflight) {
3480
- return;
3481
- }
3482
- neighborInfo.sitemapRequestInflight = true;
3483
- transition = function(site, from, to) {
3484
- return $(".neighbor[data-site=\"" + site + "\"]").find('div').removeClass(from).addClass(to);
3485
- };
3486
- fetchMap = function() {
3487
- var request, sitemapUrl;
3488
- sitemapUrl = "http://" + site + "/system/sitemap.json";
3489
- transition(site, 'wait', 'fetch');
3490
- request = $.ajax({
3491
- type: 'GET',
3492
- dataType: 'json',
3493
- url: sitemapUrl
3494
- });
3495
- return request.always(function() {
3496
- return neighborInfo.sitemapRequestInflight = false;
3497
- }).done(function(data) {
3498
- neighborInfo.sitemap = data;
3499
- transition(site, 'fetch', 'done');
3500
- return $('body').trigger('new-neighbor-done', site);
3501
- }).fail(function(data) {
3502
- return transition(site, 'fetch', 'fail');
3503
- });
3504
- };
3505
- now = Date.now();
3506
- if (now > nextAvailableFetch) {
3507
- nextAvailableFetch = now + nextFetchInterval;
3508
- return setTimeout(fetchMap, 100);
3509
- } else {
3510
- setTimeout(fetchMap, nextAvailableFetch - now);
3511
- return nextAvailableFetch += nextFetchInterval;
3512
- }
3513
- };
3514
-
3515
- wiki.registerNeighbor = neighborhood.registerNeighbor = function(site) {
3516
- var neighborInfo;
3517
- if (wiki.neighborhood[site] != null) {
3518
- return;
3519
- }
3520
- neighborInfo = {};
3521
- wiki.neighborhood[site] = neighborInfo;
3522
- populateSiteInfoFor(site, neighborInfo);
3523
- return $('body').trigger('new-neighbor', site);
3524
- };
3525
-
3526
- neighborhood.listNeighbors = function() {
3527
- return _.keys(wiki.neighborhood);
3528
- };
3529
-
3530
- neighborhood.search = function(searchQuery) {
3531
- var finds, match, matchingPages, neighborInfo, neighborSite, sitemap, start, tally, tick, _ref;
3532
- finds = [];
3533
- tally = {};
3534
- tick = function(key) {
3535
- if (tally[key] != null) {
3536
- return tally[key]++;
3537
- } else {
3538
- return tally[key] = 1;
3539
- }
3540
- };
3541
- match = function(key, text) {
3542
- var hit;
3543
- hit = (text != null) && text.toLowerCase().indexOf(searchQuery.toLowerCase()) >= 0;
3544
- if (hit) {
3545
- tick(key);
3546
- }
3547
- return hit;
3548
- };
3549
- start = Date.now();
3550
- _ref = wiki.neighborhood;
3551
- for (neighborSite in _ref) {
3552
- if (!__hasProp.call(_ref, neighborSite)) continue;
3553
- neighborInfo = _ref[neighborSite];
3554
- sitemap = neighborInfo.sitemap;
3555
- if (sitemap != null) {
3556
- tick('sites');
3557
- }
3558
- matchingPages = _.each(sitemap, function(page) {
3559
- tick('pages');
3560
- if (!(match('title', page.title) || match('text', page.synopsis) || match('slug', page.slug))) {
3561
- return;
3562
- }
3563
- tick('finds');
3564
- return finds.push({
3565
- page: page,
3566
- site: neighborSite,
3567
- rank: 1
3568
- });
3569
- });
3570
- }
3571
- tally['msec'] = Date.now() - start;
3572
- return {
3573
- finds: finds,
3574
- tally: tally
3575
- };
3576
- };
3577
-
3578
- $(function() {
3579
- var $neighborhood, flag, search;
3580
- $neighborhood = $('.neighborhood');
3581
- flag = function(site) {
3582
- return "<span class=\"neighbor\" data-site=\"" + site + "\">\n <div class=\"wait\">\n <img src=\"http://" + site + "/favicon.png\" title=\"" + site + "\">\n </div>\n</span>";
3583
- };
3584
- $('body').on('new-neighbor', function(e, site) {
3585
- return $neighborhood.append(flag(site));
3586
- }).delegate('.neighbor img', 'click', function(e) {
3587
- return wiki.doInternalLink('welcome-visitors', null, this.title);
3588
- });
3589
- search = createSearch({
3590
- neighborhood: neighborhood
3591
- });
3592
- return $('input.search').on('keypress', function(e) {
3593
- var searchQuery;
3594
- if (e.keyCode !== 13) {
3595
- return;
3596
- }
3597
- searchQuery = $(this).val();
3598
- search.performSearch(searchQuery);
3599
- return $(this).val("");
3600
- });
3601
- });
3602
-
3603
- }).call(this);
3604
-
3605
- },{"./active":10,"./search":19,"./util":6,"./wiki":2,"underscore":17}]},{},[1])
3606
- //@ sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlcyI6WyIvVXNlcnMvd2N1bm5pbmdoYW0vRmVkV2lraS9TbWFsbGVzdC1GZWRlcmF0ZWQtV2lraS9jbGllbnQvY2xpZW50LmNvZmZlZSIsIi9Vc2Vycy93Y3VubmluZ2hhbS9GZWRXaWtpL1NtYWxsZXN0LUZlZGVyYXRlZC1XaWtpL2NsaWVudC9ub2RlX21vZHVsZXMvd2lraS1jbGllbnQvbGliL3dpa2kuanMiLCIvVXNlcnMvd2N1bm5pbmdoYW0vRmVkV2lraS9TbWFsbGVzdC1GZWRlcmF0ZWQtV2lraS9jbGllbnQvbm9kZV9tb2R1bGVzL3dpa2ktY2xpZW50L2xpYi9sZWdhY3kuanMiLCIvVXNlcnMvd2N1bm5pbmdoYW0vRmVkV2lraS9TbWFsbGVzdC1GZWRlcmF0ZWQtV2lraS9jbGllbnQvbm9kZV9tb2R1bGVzL3dpa2ktY2xpZW50L2xpYi9zeW5vcHNpcy5qcyIsIi9Vc2Vycy93Y3VubmluZ2hhbS9GZWRXaWtpL1NtYWxsZXN0LUZlZGVyYXRlZC1XaWtpL2NsaWVudC9ub2RlX21vZHVsZXMvd2lraS1jbGllbnQvbGliL3BlcnNvbmEuanMiLCIvVXNlcnMvd2N1bm5pbmdoYW0vRmVkV2lraS9TbWFsbGVzdC1GZWRlcmF0ZWQtV2lraS9jbGllbnQvbm9kZV9tb2R1bGVzL3dpa2ktY2xpZW50L2xpYi9hY3RpdmUuanMiLCIvVXNlcnMvd2N1bm5pbmdoYW0vRmVkV2lraS9TbWFsbGVzdC1GZWRlcmF0ZWQtV2lraS9jbGllbnQvbm9kZV9tb2R1bGVzL3dpa2ktY2xpZW50L2xpYi91dGlsLmpzIiwiL1VzZXJzL3djdW5uaW5naGFtL0ZlZFdpa2kvU21hbGxlc3QtRmVkZXJhdGVkLVdpa2kvY2xpZW50L25vZGVfbW9kdWxlcy93aWtpLWNsaWVudC9saWIvcGx1Z2luLmpzIiwiL1VzZXJzL3djdW5uaW5naGFtL0ZlZFdpa2kvU21hbGxlc3QtRmVkZXJhdGVkLVdpa2kvY2xpZW50L25vZGVfbW9kdWxlcy93aWtpLWNsaWVudC9saWIvc3RhdGUuanMiLCIvVXNlcnMvd2N1bm5pbmdoYW0vRmVkV2lraS9TbWFsbGVzdC1GZWRlcmF0ZWQtV2lraS9jbGllbnQvbm9kZV9tb2R1bGVzL3dpa2ktY2xpZW50L2xpYi9yZXZpc2lvbi5qcyIsIi9Vc2Vycy93Y3VubmluZ2hhbS9GZWRXaWtpL1NtYWxsZXN0LUZlZGVyYXRlZC1XaWtpL2NsaWVudC9ub2RlX21vZHVsZXMvd2lraS1jbGllbnQvbGliL3JlZmVyZW5jZS5qcyIsIi9Vc2Vycy93Y3VubmluZ2hhbS9GZWRXaWtpL1NtYWxsZXN0LUZlZGVyYXRlZC1XaWtpL2NsaWVudC9ub2RlX21vZHVsZXMvd2lraS1jbGllbnQvbGliL2ZhY3RvcnkuanMiLCIvVXNlcnMvd2N1bm5pbmdoYW0vRmVkV2lraS9TbWFsbGVzdC1GZWRlcmF0ZWQtV2lraS9jbGllbnQvbm9kZV9tb2R1bGVzL3dpa2ktY2xpZW50L2xpYi9hZGRUb0pvdXJuYWwuanMiLCIvVXNlcnMvd2N1bm5pbmdoYW0vRmVkV2lraS9TbWFsbGVzdC1GZWRlcmF0ZWQtV2lraS9jbGllbnQvbm9kZV9tb2R1bGVzL3dpa2ktY2xpZW50L2xpYi9wYWdlSGFuZGxlci5qcyIsIi9Vc2Vycy93Y3VubmluZ2hhbS9GZWRXaWtpL1NtYWxsZXN0LUZlZGVyYXRlZC1XaWtpL2NsaWVudC9ub2RlX21vZHVsZXMvd2lraS1jbGllbnQvbGliL3JlZnJlc2guanMiLCIvVXNlcnMvd2N1bm5pbmdoYW0vRmVkV2lraS9TbWFsbGVzdC1GZWRlcmF0ZWQtV2lraS9jbGllbnQvbm9kZV9tb2R1bGVzL3dpa2ktY2xpZW50L2xpYi9wYWdlLmpzIiwiL1VzZXJzL3djdW5uaW5naGFtL0ZlZFdpa2kvU21hbGxlc3QtRmVkZXJhdGVkLVdpa2kvY2xpZW50L25vZGVfbW9kdWxlcy91bmRlcnNjb3JlL3VuZGVyc2NvcmUuanMiLCIvVXNlcnMvd2N1bm5pbmdoYW0vRmVkV2lraS9TbWFsbGVzdC1GZWRlcmF0ZWQtV2lraS9jbGllbnQvbm9kZV9tb2R1bGVzL3dpa2ktY2xpZW50L2xpYi9zZWFyY2guanMiLCIvVXNlcnMvd2N1bm5pbmdoYW0vRmVkV2lraS9TbWFsbGVzdC1GZWRlcmF0ZWQtV2lraS9jbGllbnQvbm9kZV9tb2R1bGVzL3dpa2ktY2xpZW50L2xpYi9uZWlnaGJvcmhvb2QuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLENBQU8sRUFBTyxDQUFkLEVBQU0sQ0FBUSxlQUFBOztBQUNkLENBREEsTUFDQSxpQkFBQTs7OztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDek9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzd2Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzQ29udGVudCI6WyJ3aW5kb3cud2lraSA9IHJlcXVpcmUoJ3dpa2ktY2xpZW50L2xpYi93aWtpJylcbnJlcXVpcmUoJ3dpa2ktY2xpZW50L2xpYi9sZWdhY3knKVxuXG4iLCIoZnVuY3Rpb24oKSB7XG4gIHZhciBjcmVhdGVTeW5vcHNpcywgd2lraSxcbiAgICBfX3NsaWNlID0gW10uc2xpY2U7XG5cbiAgY3JlYXRlU3lub3BzaXMgPSByZXF1aXJlKCcuL3N5bm9wc2lzJyk7XG5cbiAgd2lraSA9IHtcbiAgICBjcmVhdGVTeW5vcHNpczogY3JlYXRlU3lub3BzaXNcbiAgfTtcblxuICB3aWtpLnBlcnNvbmEgPSByZXF1aXJlKCcuL3BlcnNvbmEnKTtcblxuICB3aWtpLmxvZyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB0aGluZ3M7XG4gICAgdGhpbmdzID0gMSA8PSBhcmd1bWVudHMubGVuZ3RoID8gX19zbGljZS5jYWxsKGFyZ3VtZW50cywgMCkgOiBbXTtcbiAgICBpZiAoKHR5cGVvZiBjb25zb2xlICE9PSBcInVuZGVmaW5lZFwiICYmIGNvbnNvbGUgIT09IG51bGwgPyBjb25zb2xlLmxvZyA6IHZvaWQgMCkgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbnNvbGUubG9nLmFwcGx5KGNvbnNvbGUsIHRoaW5ncyk7XG4gICAgfVxuICB9O1xuXG4gIHdpa2kuYXNTbHVnID0gZnVuY3Rpb24obmFtZSkge1xuICAgIHJldHVybiBuYW1lLnJlcGxhY2UoL1xccy9nLCAnLScpLnJlcGxhY2UoL1teQS1aYS16MC05LV0vZywgJycpLnRvTG93ZXJDYXNlKCk7XG4gIH07XG5cbiAgd2lraS51c2VMb2NhbFN0b3JhZ2UgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gJChcIi5sb2dpblwiKS5sZW5ndGggPiAwO1xuICB9O1xuXG4gIHdpa2kucmVzb2x1dGlvbkNvbnRleHQgPSBbXTtcblxuICB3aWtpLnJlc29sdmVGcm9tID0gZnVuY3Rpb24oYWRkaXRpb24sIGNhbGxiYWNrKSB7XG4gICAgd2lraS5yZXNvbHV0aW9uQ29udGV4dC5wdXNoKGFkZGl0aW9uKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHdpa2kucmVzb2x1dGlvbkNvbnRleHQucG9wKCk7XG4gICAgfVxuICB9O1xuXG4gIHdpa2kuZ2V0RGF0YSA9IGZ1bmN0aW9uKHZpcykge1xuICAgIHZhciBpZHgsIHdobztcbiAgICBpZiAodmlzKSB7XG4gICAgICBpZHggPSAkKCcuaXRlbScpLmluZGV4KHZpcyk7XG4gICAgICB3aG8gPSAkKFwiLml0ZW06bHQoXCIgKyBpZHggKyBcIilcIikuZmlsdGVyKCcuY2hhcnQsLmRhdGEsLmNhbGN1bGF0b3InKS5sYXN0KCk7XG4gICAgICBpZiAod2hvICE9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHdoby5kYXRhKCdpdGVtJykuZGF0YTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB7fTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgd2hvID0gJCgnLmNoYXJ0LC5kYXRhLC5jYWxjdWxhdG9yJykubGFzdCgpO1xuICAgICAgaWYgKHdobyAhPSBudWxsKSB7XG4gICAgICAgIHJldHVybiB3aG8uZGF0YSgnaXRlbScpLmRhdGE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4ge307XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIHdpa2kuZ2V0RGF0YU5vZGVzID0gZnVuY3Rpb24odmlzKSB7XG4gICAgdmFyIGlkeCwgd2hvO1xuICAgIGlmICh2aXMpIHtcbiAgICAgIGlkeCA9ICQoJy5pdGVtJykuaW5kZXgodmlzKTtcbiAgICAgIHdobyA9ICQoXCIuaXRlbTpsdChcIiArIGlkeCArIFwiKVwiKS5maWx0ZXIoJy5jaGFydCwuZGF0YSwuY2FsY3VsYXRvcicpLnRvQXJyYXkoKS5yZXZlcnNlKCk7XG4gICAgICByZXR1cm4gJCh3aG8pO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aG8gPSAkKCcuY2hhcnQsLmRhdGEsLmNhbGN1bGF0b3InKS50b0FycmF5KCkucmV2ZXJzZSgpO1xuICAgICAgcmV0dXJuICQod2hvKTtcbiAgICB9XG4gIH07XG5cbiAgd2lraS5jcmVhdGVQYWdlID0gZnVuY3Rpb24obmFtZSwgbG9jKSB7XG4gICAgdmFyICRwYWdlLCBzaXRlO1xuICAgIGlmIChsb2MgJiYgbG9jICE9PSAndmlldycpIHtcbiAgICAgIHNpdGUgPSBsb2M7XG4gICAgfVxuICAgICRwYWdlID0gJChcIjxkaXYgY2xhc3M9XFxcInBhZ2VcXFwiIGlkPVxcXCJcIiArIG5hbWUgKyBcIlxcXCI+XFxuICA8ZGl2IGNsYXNzPVxcXCJ0d2luc1xcXCI+IDxwPiA8L3A+IDwvZGl2PlxcbiAgPGRpdiBjbGFzcz1cXFwiaGVhZGVyXFxcIj5cXG4gICAgPGgxPiA8aW1nIGNsYXNzPVxcXCJmYXZpY29uXFxcIiBzcmM9XFxcIlwiICsgKHNpdGUgPyBcIi8vXCIgKyBzaXRlIDogXCJcIikgKyBcIi9mYXZpY29uLnBuZ1xcXCIgaGVpZ2h0PVxcXCIzMnB4XFxcIj4gXCIgKyBuYW1lICsgXCIgPC9oMT5cXG4gIDwvZGl2PlxcbjwvZGl2PlwiKTtcbiAgICBpZiAoc2l0ZSkge1xuICAgICAgJHBhZ2UuZGF0YSgnc2l0ZScsIHNpdGUpO1xuICAgIH1cbiAgICByZXR1cm4gJHBhZ2U7XG4gIH07XG5cbiAgd2lraS5nZXRJdGVtID0gZnVuY3Rpb24oZWxlbWVudCkge1xuICAgIGlmICgkKGVsZW1lbnQpLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiAkKGVsZW1lbnQpLmRhdGEoXCJpdGVtXCIpIHx8ICQoZWxlbWVudCkuZGF0YSgnc3RhdGljSXRlbScpO1xuICAgIH1cbiAgfTtcblxuICB3aWtpLnJlc29sdmVMaW5rcyA9IGZ1bmN0aW9uKHN0cmluZykge1xuICAgIHZhciByZW5kZXJJbnRlcm5hbExpbms7XG4gICAgcmVuZGVySW50ZXJuYWxMaW5rID0gZnVuY3Rpb24obWF0Y2gsIG5hbWUpIHtcbiAgICAgIHZhciBzbHVnO1xuICAgICAgc2x1ZyA9IHdpa2kuYXNTbHVnKG5hbWUpO1xuICAgICAgcmV0dXJuIFwiPGEgY2xhc3M9XFxcImludGVybmFsXFxcIiBocmVmPVxcXCIvXCIgKyBzbHVnICsgXCIuaHRtbFxcXCIgZGF0YS1wYWdlLW5hbWU9XFxcIlwiICsgc2x1ZyArIFwiXFxcIiB0aXRsZT1cXFwiXCIgKyAod2lraS5yZXNvbHV0aW9uQ29udGV4dC5qb2luKCcgPT4gJykpICsgXCJcXFwiPlwiICsgbmFtZSArIFwiPC9hPlwiO1xuICAgIH07XG4gICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXFtcXFsoW15cXF1dKylcXF1cXF0vZ2ksIHJlbmRlckludGVybmFsTGluaykucmVwbGFjZSgvXFxbKGh0dHAuKj8pICguKj8pXFxdL2dpLCBcIjxhIGNsYXNzPVxcXCJleHRlcm5hbFxcXCIgdGFyZ2V0PVxcXCJfYmxhbmtcXFwiIGhyZWY9XFxcIiQxXFxcIiB0aXRsZT1cXFwiJDFcXFwiIHJlbD1cXFwibm9mb2xsb3dcXFwiPiQyIDxpbWcgc3JjPVxcXCIvaW1hZ2VzL2V4dGVybmFsLWxpbmstbHRyLWljb24ucG5nXFxcIj48L2E+XCIpO1xuICB9O1xuXG4gIG1vZHVsZS5leHBvcnRzID0gd2lraTtcblxufSkuY2FsbCh0aGlzKTtcbiIsIihmdW5jdGlvbigpIHtcbiAgdmFyIGFjdGl2ZSwgbmV3UGFnZSwgcGFnZUhhbmRsZXIsIHBsdWdpbiwgcmVmcmVzaCwgc3RhdGUsIHV0aWwsIHdpa2k7XG5cbiAgd2lraSA9IHJlcXVpcmUoJy4vd2lraScpO1xuXG4gIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxuICBwYWdlSGFuZGxlciA9IHdpa2kucGFnZUhhbmRsZXIgPSByZXF1aXJlKCcuL3BhZ2VIYW5kbGVyJyk7XG5cbiAgcGx1Z2luID0gcmVxdWlyZSgnLi9wbHVnaW4nKTtcblxuICBzdGF0ZSA9IHJlcXVpcmUoJy4vc3RhdGUnKTtcblxuICBhY3RpdmUgPSByZXF1aXJlKCcuL2FjdGl2ZScpO1xuXG4gIHJlZnJlc2ggPSByZXF1aXJlKCcuL3JlZnJlc2gnKTtcblxuICBuZXdQYWdlID0gcmVxdWlyZSgnLi9wYWdlJykubmV3UGFnZTtcblxuICBBcnJheS5wcm90b3R5cGUubGFzdCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzW3RoaXMubGVuZ3RoIC0gMV07XG4gIH07XG5cbiAgJChmdW5jdGlvbigpIHtcbiAgICB2YXIgTEVGVEFSUk9XLCBSSUdIVEFSUk9XLCBjcmVhdGVUZXh0RWxlbWVudCwgZG9JbnRlcm5hbExpbmssIGZpbmlzaENsaWNrLCBnZXRUZW1wbGF0ZSwgc2xlZXAsIHRleHRFZGl0b3I7XG4gICAgd2luZG93LmRpYWxvZyA9ICQoJzxkaXY+PC9kaXY+JykuaHRtbCgnVGhpcyBkaWFsb2cgd2lsbCBzaG93IGV2ZXJ5IHRpbWUhJykuZGlhbG9nKHtcbiAgICAgIGF1dG9PcGVuOiBmYWxzZSxcbiAgICAgIHRpdGxlOiAnQmFzaWMgRGlhbG9nJyxcbiAgICAgIGhlaWdodDogNjAwLFxuICAgICAgd2lkdGg6IDgwMFxuICAgIH0pO1xuICAgIHdpa2kuZGlhbG9nID0gZnVuY3Rpb24odGl0bGUsIGh0bWwpIHtcbiAgICAgIHdpbmRvdy5kaWFsb2cuaHRtbChodG1sKTtcbiAgICAgIHdpbmRvdy5kaWFsb2cuZGlhbG9nKFwib3B0aW9uXCIsIFwidGl0bGVcIiwgd2lraS5yZXNvbHZlTGlua3ModGl0bGUpKTtcbiAgICAgIHJldHVybiB3aW5kb3cuZGlhbG9nLmRpYWxvZygnb3BlbicpO1xuICAgIH07XG4gICAgc2xlZXAgPSBmdW5jdGlvbih0aW1lLCBkb25lKSB7XG4gICAgICByZXR1cm4gc2V0VGltZW91dChkb25lLCB0aW1lKTtcbiAgICB9O1xuICAgIHdpa2kucmVtb3ZlSXRlbSA9IGZ1bmN0aW9uKCRpdGVtLCBpdGVtKSB7XG4gICAgICBwYWdlSGFuZGxlci5wdXQoJGl0ZW0ucGFyZW50cygnLnBhZ2U6Zmlyc3QnKSwge1xuICAgICAgICB0eXBlOiAncmVtb3ZlJyxcbiAgICAgICAgaWQ6IGl0ZW0uaWRcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuICRpdGVtLnJlbW92ZSgpO1xuICAgIH07XG4gICAgd2lraS5jcmVhdGVJdGVtID0gZnVuY3Rpb24oJHBhZ2UsICRiZWZvcmUsIGl0ZW0pIHtcbiAgICAgIHZhciAkaXRlbSwgYmVmb3JlO1xuICAgICAgaWYgKCRwYWdlID09IG51bGwpIHtcbiAgICAgICAgJHBhZ2UgPSAkYmVmb3JlLnBhcmVudHMoJy5wYWdlJyk7XG4gICAgICB9XG4gICAgICBpdGVtLmlkID0gdXRpbC5yYW5kb21CeXRlcyg4KTtcbiAgICAgICRpdGVtID0gJChcIjxkaXYgY2xhc3M9XFxcIml0ZW0gXCIgKyBpdGVtLnR5cGUgKyBcIlxcXCIgZGF0YS1pZD1cXFwiXCIgKyBcIlxcXCI8L2Rpdj5cIik7XG4gICAgICAkaXRlbS5kYXRhKCdpdGVtJywgaXRlbSkuZGF0YSgncGFnZUVsZW1lbnQnLCAkcGFnZSk7XG4gICAgICBpZiAoJGJlZm9yZSAhPSBudWxsKSB7XG4gICAgICAgICRiZWZvcmUuYWZ0ZXIoJGl0ZW0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgJHBhZ2UuZmluZCgnLnN0b3J5JykuYXBwZW5kKCRpdGVtKTtcbiAgICAgIH1cbiAgICAgIHBsdWdpbltcImRvXCJdKCRpdGVtLCBpdGVtKTtcbiAgICAgIGJlZm9yZSA9IHdpa2kuZ2V0SXRlbSgkYmVmb3JlKTtcbiAgICAgIHNsZWVwKDUwMCwgZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBwYWdlSGFuZGxlci5wdXQoJHBhZ2UsIHtcbiAgICAgICAgICBpdGVtOiBpdGVtLFxuICAgICAgICAgIGlkOiBpdGVtLmlkLFxuICAgICAgICAgIHR5cGU6ICdhZGQnLFxuICAgICAgICAgIGFmdGVyOiBiZWZvcmUgIT0gbnVsbCA/IGJlZm9yZS5pZCA6IHZvaWQgMFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuICRpdGVtO1xuICAgIH07XG4gICAgY3JlYXRlVGV4dEVsZW1lbnQgPSBmdW5jdGlvbihwYWdlRWxlbWVudCwgYmVmb3JlRWxlbWVudCwgaW5pdGlhbFRleHQpIHtcbiAgICAgIHZhciBpdGVtLCBpdGVtQmVmb3JlLCBpdGVtRWxlbWVudDtcbiAgICAgIGl0ZW0gPSB7XG4gICAgICAgIHR5cGU6ICdwYXJhZ3JhcGgnLFxuICAgICAgICBpZDogdXRpbC5yYW5kb21CeXRlcyg4KSxcbiAgICAgICAgdGV4dDogaW5pdGlhbFRleHRcbiAgICAgIH07XG4gICAgICBpdGVtRWxlbWVudCA9ICQoXCI8ZGl2IGNsYXNzPVxcXCJpdGVtIHBhcmFncmFwaFxcXCIgZGF0YS1pZD1cIiArIGl0ZW0uaWQgKyBcIj48L2Rpdj5cIik7XG4gICAgICBpdGVtRWxlbWVudC5kYXRhKCdpdGVtJywgaXRlbSkuZGF0YSgncGFnZUVsZW1lbnQnLCBwYWdlRWxlbWVudCk7XG4gICAgICBiZWZvcmVFbGVtZW50LmFmdGVyKGl0ZW1FbGVtZW50KTtcbiAgICAgIHBsdWdpbltcImRvXCJdKGl0ZW1FbGVtZW50LCBpdGVtKTtcbiAgICAgIGl0ZW1CZWZvcmUgPSB3aWtpLmdldEl0ZW0oYmVmb3JlRWxlbWVudCk7XG4gICAgICB3aWtpLnRleHRFZGl0b3IoaXRlbUVsZW1lbnQsIGl0ZW0pO1xuICAgICAgcmV0dXJuIHNsZWVwKDUwMCwgZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBwYWdlSGFuZGxlci5wdXQocGFnZUVsZW1lbnQsIHtcbiAgICAgICAgICBpdGVtOiBpdGVtLFxuICAgICAgICAgIGlkOiBpdGVtLmlkLFxuICAgICAgICAgIHR5cGU6ICdhZGQnLFxuICAgICAgICAgIGFmdGVyOiBpdGVtQmVmb3JlICE9IG51bGwgPyBpdGVtQmVmb3JlLmlkIDogdm9pZCAwXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfTtcbiAgICB0ZXh0RWRpdG9yID0gd2lraS50ZXh0RWRpdG9yID0gZnVuY3Rpb24oZGl2LCBpdGVtLCBjYXJldFBvcywgZG91YmxlQ2xpY2tlZCkge1xuICAgICAgdmFyIG9yaWdpbmFsLCB0ZXh0YXJlYSwgX3JlZjtcbiAgICAgIGlmIChkaXYuaGFzQ2xhc3MoJ3RleHRFZGl0aW5nJykpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgZGl2LmFkZENsYXNzKCd0ZXh0RWRpdGluZycpO1xuICAgICAgdGV4dGFyZWEgPSAkKFwiPHRleHRhcmVhPlwiICsgKG9yaWdpbmFsID0gKF9yZWYgPSBpdGVtLnRleHQpICE9IG51bGwgPyBfcmVmIDogJycpICsgXCI8L3RleHRhcmVhPlwiKS5mb2N1c291dChmdW5jdGlvbigpIHtcbiAgICAgICAgZGl2LnJlbW92ZUNsYXNzKCd0ZXh0RWRpdGluZycpO1xuICAgICAgICBpZiAoaXRlbS50ZXh0ID0gdGV4dGFyZWEudmFsKCkpIHtcbiAgICAgICAgICBwbHVnaW5bXCJkb1wiXShkaXYuZW1wdHkoKSwgaXRlbSk7XG4gICAgICAgICAgaWYgKGl0ZW0udGV4dCA9PT0gb3JpZ2luYWwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgcGFnZUhhbmRsZXIucHV0KGRpdi5wYXJlbnRzKCcucGFnZTpmaXJzdCcpLCB7XG4gICAgICAgICAgICB0eXBlOiAnZWRpdCcsXG4gICAgICAgICAgICBpZDogaXRlbS5pZCxcbiAgICAgICAgICAgIGl0ZW06IGl0ZW1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwYWdlSGFuZGxlci5wdXQoZGl2LnBhcmVudHMoJy5wYWdlOmZpcnN0JyksIHtcbiAgICAgICAgICAgIHR5cGU6ICdyZW1vdmUnLFxuICAgICAgICAgICAgaWQ6IGl0ZW0uaWRcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBkaXYucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9KS5iaW5kKCdrZXlkb3duJywgZnVuY3Rpb24oZSkge1xuICAgICAgICB2YXIgbWlkZGxlLCBwYWdlLCBwYWdlRWxlbWVudCwgcHJlZml4LCBwcmV2SXRlbSwgcHJldlRleHRMZW4sIHNlbCwgc3VmZml4LCB0ZXh0O1xuICAgICAgICBpZiAoKGUuYWx0S2V5IHx8IGUuY3RsS2V5IHx8IGUubWV0YUtleSkgJiYgZS53aGljaCA9PT0gODMpIHtcbiAgICAgICAgICB0ZXh0YXJlYS5mb2N1c291dCgpO1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKGUuYWx0S2V5IHx8IGUuY3RsS2V5IHx8IGUubWV0YUtleSkgJiYgZS53aGljaCA9PT0gNzMpIHtcbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgaWYgKCFlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICBwYWdlID0gJChlLnRhcmdldCkucGFyZW50cygnLnBhZ2UnKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZG9JbnRlcm5hbExpbmsoXCJhYm91dCBcIiArIGl0ZW0udHlwZSArIFwiIHBsdWdpblwiLCBwYWdlKTtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGl0ZW0udHlwZSA9PT0gJ3BhcmFncmFwaCcpIHtcbiAgICAgICAgICBzZWwgPSB1dGlsLmdldFNlbGVjdGlvblBvcyh0ZXh0YXJlYSk7XG4gICAgICAgICAgaWYgKGUud2hpY2ggPT09ICQudWkua2V5Q29kZS5CQUNLU1BBQ0UgJiYgc2VsLnN0YXJ0ID09PSAwICYmIHNlbC5zdGFydCA9PT0gc2VsLmVuZCkge1xuICAgICAgICAgICAgcHJldkl0ZW0gPSB3aWtpLmdldEl0ZW0oZGl2LnByZXYoKSk7XG4gICAgICAgICAgICBpZiAocHJldkl0ZW0udHlwZSAhPT0gJ3BhcmFncmFwaCcpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcHJldlRleHRMZW4gPSBwcmV2SXRlbS50ZXh0Lmxlbmd0aDtcbiAgICAgICAgICAgIHByZXZJdGVtLnRleHQgKz0gdGV4dGFyZWEudmFsKCk7XG4gICAgICAgICAgICB0ZXh0YXJlYS52YWwoJycpO1xuICAgICAgICAgICAgdGV4dEVkaXRvcihkaXYucHJldigpLCBwcmV2SXRlbSwgcHJldlRleHRMZW4pO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH0gZWxzZSBpZiAoZS53aGljaCA9PT0gJC51aS5rZXlDb2RlLkVOVEVSICYmIGl0ZW0udHlwZSA9PT0gJ3BhcmFncmFwaCcpIHtcbiAgICAgICAgICAgIGlmICghc2VsKSB7XG4gICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRleHQgPSB0ZXh0YXJlYS52YWwoKTtcbiAgICAgICAgICAgIHByZWZpeCA9IHRleHQuc3Vic3RyaW5nKDAsIHNlbC5zdGFydCk7XG4gICAgICAgICAgICBpZiAoc2VsLnN0YXJ0ICE9PSBzZWwuZW5kKSB7XG4gICAgICAgICAgICAgIG1pZGRsZSA9IHRleHQuc3Vic3RyaW5nKHNlbC5zdGFydCwgc2VsLmVuZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdWZmaXggPSB0ZXh0LnN1YnN0cmluZyhzZWwuZW5kKTtcbiAgICAgICAgICAgIGlmIChwcmVmaXggPT09ICcnKSB7XG4gICAgICAgICAgICAgIHRleHRhcmVhLnZhbCgnICcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdGV4dGFyZWEudmFsKHByZWZpeCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0ZXh0YXJlYS5mb2N1c291dCgpO1xuICAgICAgICAgICAgcGFnZUVsZW1lbnQgPSBkaXYucGFyZW50KCkucGFyZW50KCk7XG4gICAgICAgICAgICBjcmVhdGVUZXh0RWxlbWVudChwYWdlRWxlbWVudCwgZGl2LCBzdWZmaXgpO1xuICAgICAgICAgICAgaWYgKG1pZGRsZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgIGNyZWF0ZVRleHRFbGVtZW50KHBhZ2VFbGVtZW50LCBkaXYsIG1pZGRsZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocHJlZml4ID09PSAnJykge1xuICAgICAgICAgICAgICBjcmVhdGVUZXh0RWxlbWVudChwYWdlRWxlbWVudCwgZGl2LCAnJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGRpdi5odG1sKHRleHRhcmVhKTtcbiAgICAgIGlmIChjYXJldFBvcyAhPSBudWxsKSB7XG4gICAgICAgIHJldHVybiB1dGlsLnNldENhcmV0UG9zaXRpb24odGV4dGFyZWEsIGNhcmV0UG9zKTtcbiAgICAgIH0gZWxzZSBpZiAoZG91YmxlQ2xpY2tlZCkge1xuICAgICAgICB1dGlsLnNldENhcmV0UG9zaXRpb24odGV4dGFyZWEsIHRleHRhcmVhLnZhbCgpLmxlbmd0aCk7XG4gICAgICAgIHJldHVybiB0ZXh0YXJlYS5zY3JvbGxUb3AodGV4dGFyZWFbMF0uc2Nyb2xsSGVpZ2h0IC0gdGV4dGFyZWEuaGVpZ2h0KCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRleHRhcmVhLmZvY3VzKCk7XG4gICAgICB9XG4gICAgfTtcbiAgICBkb0ludGVybmFsTGluayA9IHdpa2kuZG9JbnRlcm5hbExpbmsgPSBmdW5jdGlvbihuYW1lLCBwYWdlLCBzaXRlKSB7XG4gICAgICBpZiAoc2l0ZSA9PSBudWxsKSB7XG4gICAgICAgIHNpdGUgPSBudWxsO1xuICAgICAgfVxuICAgICAgbmFtZSA9IHdpa2kuYXNTbHVnKG5hbWUpO1xuICAgICAgaWYgKHBhZ2UgIT0gbnVsbCkge1xuICAgICAgICAkKHBhZ2UpLm5leHRBbGwoKS5yZW1vdmUoKTtcbiAgICAgIH1cbiAgICAgIHdpa2kuY3JlYXRlUGFnZShuYW1lLCBzaXRlKS5hcHBlbmRUbygkKCcubWFpbicpKS5lYWNoKHJlZnJlc2gpO1xuICAgICAgcmV0dXJuIGFjdGl2ZS5zZXQoJCgnLnBhZ2UnKS5sYXN0KCkpO1xuICAgIH07XG4gICAgTEVGVEFSUk9XID0gMzc7XG4gICAgUklHSFRBUlJPVyA9IDM5O1xuICAgICQoZG9jdW1lbnQpLmtleWRvd24oZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgIHZhciBkaXJlY3Rpb24sIG5ld0luZGV4LCBwYWdlcztcbiAgICAgIGRpcmVjdGlvbiA9IChmdW5jdGlvbigpIHtcbiAgICAgICAgc3dpdGNoIChldmVudC53aGljaCkge1xuICAgICAgICAgIGNhc2UgTEVGVEFSUk9XOlxuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICAgIGNhc2UgUklHSFRBUlJPVzpcbiAgICAgICAgICAgIHJldHVybiArMTtcbiAgICAgICAgfVxuICAgICAgfSkoKTtcbiAgICAgIGlmIChkaXJlY3Rpb24gJiYgIShldmVudC50YXJnZXQudGFnTmFtZSA9PT0gXCJURVhUQVJFQVwiKSkge1xuICAgICAgICBwYWdlcyA9ICQoJy5wYWdlJyk7XG4gICAgICAgIG5ld0luZGV4ID0gcGFnZXMuaW5kZXgoJCgnLmFjdGl2ZScpKSArIGRpcmVjdGlvbjtcbiAgICAgICAgaWYgKCgwIDw9IG5ld0luZGV4ICYmIG5ld0luZGV4IDwgcGFnZXMubGVuZ3RoKSkge1xuICAgICAgICAgIHJldHVybiBhY3RpdmUuc2V0KHBhZ2VzLmVxKG5ld0luZGV4KSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICAkKHdpbmRvdykub24oJ3BvcHN0YXRlJywgc3RhdGUuc2hvdyk7XG4gICAgJChkb2N1bWVudCkuYWpheEVycm9yKGZ1bmN0aW9uKGV2ZW50LCByZXF1ZXN0LCBzZXR0aW5ncykge1xuICAgICAgaWYgKHJlcXVlc3Quc3RhdHVzID09PSAwIHx8IHJlcXVlc3Quc3RhdHVzID09PSA0MDQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgd2lraS5sb2coJ2FqYXggZXJyb3InLCBldmVudCwgcmVxdWVzdCwgc2V0dGluZ3MpO1xuICAgICAgcmV0dXJuICQoJy5tYWluJykucHJlcGVuZChcIjxsaSBjbGFzcz0nZXJyb3InPlxcbiAgRXJyb3Igb24gXCIgKyBzZXR0aW5ncy51cmwgKyBcIjogXCIgKyByZXF1ZXN0LnJlc3BvbnNlVGV4dCArIFwiXFxuPC9saT5cIik7XG4gICAgfSk7XG4gICAgZ2V0VGVtcGxhdGUgPSBmdW5jdGlvbihzbHVnLCBkb25lKSB7XG4gICAgICBpZiAoIXNsdWcpIHtcbiAgICAgICAgcmV0dXJuIGRvbmUobnVsbCk7XG4gICAgICB9XG4gICAgICB3aWtpLmxvZygnZ2V0VGVtcGxhdGUnLCBzbHVnKTtcbiAgICAgIHJldHVybiBwYWdlSGFuZGxlci5nZXQoe1xuICAgICAgICB3aGVuR290dGVuOiBmdW5jdGlvbihkYXRhLCBzaXRlRm91bmQpIHtcbiAgICAgICAgICByZXR1cm4gZG9uZShkYXRhLnN0b3J5KTtcbiAgICAgICAgfSxcbiAgICAgICAgd2hlbk5vdEdvdHRlbjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIGRvbmUobnVsbCk7XG4gICAgICAgIH0sXG4gICAgICAgIHBhZ2VJbmZvcm1hdGlvbjoge1xuICAgICAgICAgIHNsdWc6IHNsdWdcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfTtcbiAgICBmaW5pc2hDbGljayA9IGZ1bmN0aW9uKGUsIG5hbWUpIHtcbiAgICAgIHZhciBwYWdlO1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgaWYgKCFlLnNoaWZ0S2V5KSB7XG4gICAgICAgIHBhZ2UgPSAkKGUudGFyZ2V0KS5wYXJlbnRzKCcucGFnZScpO1xuICAgICAgfVxuICAgICAgZG9JbnRlcm5hbExpbmsobmFtZSwgcGFnZSwgJChlLnRhcmdldCkuZGF0YSgnc2l0ZScpKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9O1xuICAgICQoJy5tYWluJykuZGVsZWdhdGUoJy5zaG93LXBhZ2Utc291cmNlJywgJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xuICAgICAgdmFyIGpzb24sIHBhZ2VFbGVtZW50O1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgcGFnZUVsZW1lbnQgPSAkKHRoaXMpLnBhcmVudCgpLnBhcmVudCgpO1xuICAgICAganNvbiA9IHBhZ2VFbGVtZW50LmRhdGEoJ2RhdGEnKTtcbiAgICAgIHJldHVybiB3aWtpLmRpYWxvZyhcIkpTT04gZm9yIFwiICsganNvbi50aXRsZSwgJCgnPHByZS8+JykudGV4dChKU09OLnN0cmluZ2lmeShqc29uLCBudWxsLCAyKSkpO1xuICAgIH0pLmRlbGVnYXRlKCcucGFnZScsICdjbGljaycsIGZ1bmN0aW9uKGUpIHtcbiAgICAgIGlmICghJChlLnRhcmdldCkuaXMoXCJhXCIpKSB7XG4gICAgICAgIHJldHVybiBhY3RpdmUuc2V0KHRoaXMpO1xuICAgICAgfVxuICAgIH0pLmRlbGVnYXRlKCcuaW50ZXJuYWwnLCAnY2xpY2snLCBmdW5jdGlvbihlKSB7XG4gICAgICB2YXIgbmFtZTtcbiAgICAgIG5hbWUgPSAkKGUudGFyZ2V0KS5kYXRhKCdwYWdlTmFtZScpO1xuICAgICAgcGFnZUhhbmRsZXIuY29udGV4dCA9ICQoZS50YXJnZXQpLmF0dHIoJ3RpdGxlJykuc3BsaXQoJyA9PiAnKTtcbiAgICAgIHJldHVybiBmaW5pc2hDbGljayhlLCBuYW1lKTtcbiAgICB9KS5kZWxlZ2F0ZSgnaW1nLnJlbW90ZScsICdjbGljaycsIGZ1bmN0aW9uKGUpIHtcbiAgICAgIHZhciBuYW1lO1xuICAgICAgbmFtZSA9ICQoZS50YXJnZXQpLmRhdGEoJ3NsdWcnKTtcbiAgICAgIHBhZ2VIYW5kbGVyLmNvbnRleHQgPSBbJChlLnRhcmdldCkuZGF0YSgnc2l0ZScpXTtcbiAgICAgIHJldHVybiBmaW5pc2hDbGljayhlLCBuYW1lKTtcbiAgICB9KS5kZWxlZ2F0ZSgnLnJldmlzaW9uJywgJ2RibGNsaWNrJywgZnVuY3Rpb24oZSkge1xuICAgICAgdmFyICRwYWdlLCBhY3Rpb24sIGpzb24sIHBhZ2UsIHJldjtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICRwYWdlID0gJCh0aGlzKS5wYXJlbnRzKCcucGFnZScpO1xuICAgICAgcGFnZSA9ICRwYWdlLmRhdGEoJ2RhdGEnKTtcbiAgICAgIHJldiA9IHBhZ2Uuam91cm5hbC5sZW5ndGggLSAxO1xuICAgICAgYWN0aW9uID0gcGFnZS5qb3VybmFsW3Jldl07XG4gICAgICBqc29uID0gSlNPTi5zdHJpbmdpZnkoYWN0aW9uLCBudWxsLCAyKTtcbiAgICAgIHJldHVybiB3aWtpLmRpYWxvZyhcIlJldmlzaW9uIFwiICsgcmV2ICsgXCIsIFwiICsgYWN0aW9uLnR5cGUgKyBcIiBhY3Rpb25cIiwgJCgnPHByZS8+JykudGV4dChqc29uKSk7XG4gICAgfSkuZGVsZWdhdGUoJy5hY3Rpb24nLCAnY2xpY2snLCBmdW5jdGlvbihlKSB7XG4gICAgICB2YXIgJGFjdGlvbiwgJHBhZ2UsIG5hbWUsIHJldiwgc2x1ZztcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICRhY3Rpb24gPSAkKGUudGFyZ2V0KTtcbiAgICAgIGlmICgkYWN0aW9uLmlzKCcuZm9yaycpICYmICgobmFtZSA9ICRhY3Rpb24uZGF0YSgnc2x1ZycpKSAhPSBudWxsKSkge1xuICAgICAgICBwYWdlSGFuZGxlci5jb250ZXh0ID0gWyRhY3Rpb24uZGF0YSgnc2l0ZScpXTtcbiAgICAgICAgcmV0dXJuIGZpbmlzaENsaWNrKGUsIChuYW1lLnNwbGl0KCdfJykpWzBdKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgICRwYWdlID0gJCh0aGlzKS5wYXJlbnRzKCcucGFnZScpO1xuICAgICAgICBzbHVnID0gd2lraS5hc1NsdWcoJHBhZ2UuZGF0YSgnZGF0YScpLnRpdGxlKTtcbiAgICAgICAgcmV2ID0gJCh0aGlzKS5wYXJlbnQoKS5jaGlsZHJlbigpLmluZGV4KCRhY3Rpb24pO1xuICAgICAgICBpZiAoIWUuc2hpZnRLZXkpIHtcbiAgICAgICAgICAkcGFnZS5uZXh0QWxsKCkucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICAgICAgd2lraS5jcmVhdGVQYWdlKFwiXCIgKyBzbHVnICsgXCJfcmV2XCIgKyByZXYsICRwYWdlLmRhdGEoJ3NpdGUnKSkuYXBwZW5kVG8oJCgnLm1haW4nKSkuZWFjaChyZWZyZXNoKTtcbiAgICAgICAgcmV0dXJuIGFjdGl2ZS5zZXQoJCgnLnBhZ2UnKS5sYXN0KCkpO1xuICAgICAgfVxuICAgIH0pLmRlbGVnYXRlKCcuZm9yay1wYWdlJywgJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xuICAgICAgdmFyIGl0ZW0sIHBhZ2VFbGVtZW50LCByZW1vdGVTaXRlO1xuICAgICAgcGFnZUVsZW1lbnQgPSAkKGUudGFyZ2V0KS5wYXJlbnRzKCcucGFnZScpO1xuICAgICAgaWYgKHBhZ2VFbGVtZW50Lmhhc0NsYXNzKCdsb2NhbCcpKSB7XG4gICAgICAgIGlmICghd2lraS51c2VMb2NhbFN0b3JhZ2UoKSkge1xuICAgICAgICAgIGl0ZW0gPSBwYWdlRWxlbWVudC5kYXRhKCdkYXRhJyk7XG4gICAgICAgICAgcGFnZUVsZW1lbnQucmVtb3ZlQ2xhc3MoJ2xvY2FsJyk7XG4gICAgICAgICAgcmV0dXJuIHBhZ2VIYW5kbGVyLnB1dChwYWdlRWxlbWVudCwge1xuICAgICAgICAgICAgdHlwZTogJ2ZvcmsnLFxuICAgICAgICAgICAgaXRlbTogaXRlbVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoKHJlbW90ZVNpdGUgPSBwYWdlRWxlbWVudC5kYXRhKCdzaXRlJykpICE9IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4gcGFnZUhhbmRsZXIucHV0KHBhZ2VFbGVtZW50LCB7XG4gICAgICAgICAgICB0eXBlOiAnZm9yaycsXG4gICAgICAgICAgICBzaXRlOiByZW1vdGVTaXRlXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KS5kZWxlZ2F0ZSgnLmFjdGlvbicsICdob3ZlcicsIGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGlkO1xuICAgICAgaWQgPSAkKHRoaXMpLmF0dHIoJ2RhdGEtaWQnKTtcbiAgICAgICQoXCJbZGF0YS1pZD1cIiArIGlkICsgXCJdXCIpLnRvZ2dsZUNsYXNzKCd0YXJnZXQnKTtcbiAgICAgIHJldHVybiAkKCcubWFpbicpLnRyaWdnZXIoJ3JldicpO1xuICAgIH0pLmRlbGVnYXRlKCcuaXRlbScsICdob3ZlcicsIGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGlkO1xuICAgICAgaWQgPSAkKHRoaXMpLmF0dHIoJ2RhdGEtaWQnKTtcbiAgICAgIHJldHVybiAkKFwiLmFjdGlvbltkYXRhLWlkPVwiICsgaWQgKyBcIl1cIikudG9nZ2xlQ2xhc3MoJ3RhcmdldCcpO1xuICAgIH0pLmRlbGVnYXRlKCdidXR0b24uY3JlYXRlJywgJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xuICAgICAgcmV0dXJuIGdldFRlbXBsYXRlKCQoZS50YXJnZXQpLmRhdGEoJ3NsdWcnKSwgZnVuY3Rpb24oc3RvcnkpIHtcbiAgICAgICAgdmFyICRwYWdlLCBwYWdlLCBwYWdlT2JqZWN0O1xuICAgICAgICAkcGFnZSA9ICQoZS50YXJnZXQpLnBhcmVudHMoJy5wYWdlOmZpcnN0Jyk7XG4gICAgICAgICRwYWdlLnJlbW92ZUNsYXNzKCdnaG9zdCcpO1xuICAgICAgICBwYWdlID0gJHBhZ2UuZGF0YSgnZGF0YScpO1xuICAgICAgICBwYWdlLnN0b3J5ID0gc3RvcnkgfHwgW107XG4gICAgICAgIHBhZ2VPYmplY3QgPSBuZXdQYWdlKHBhZ2UsIG51bGwpO1xuICAgICAgICBwYWdlID0gcGFnZU9iamVjdC5nZXRSYXdQYWdlKCk7XG4gICAgICAgIHBhZ2VIYW5kbGVyLnB1dCgkcGFnZSwge1xuICAgICAgICAgIHR5cGU6ICdjcmVhdGUnLFxuICAgICAgICAgIGlkOiBwYWdlLmlkLFxuICAgICAgICAgIGl0ZW06IHtcbiAgICAgICAgICAgIHRpdGxlOiBwYWdlLnRpdGxlLFxuICAgICAgICAgICAgc3Rvcnk6IHBhZ2Uuc3RvcnlcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gd2lraS5idWlsZFBhZ2UocGFnZU9iamVjdCwgJHBhZ2UuZW1wdHkoKSk7XG4gICAgICB9KTtcbiAgICB9KS5kZWxlZ2F0ZSgnLmdob3N0JywgJ3JldicsIGZ1bmN0aW9uKGUpIHtcbiAgICAgIHZhciAkaXRlbSwgJHBhZ2UsIHBvc2l0aW9uO1xuICAgICAgd2lraS5sb2coJ3JldicsIGUpO1xuICAgICAgJHBhZ2UgPSAkKGUudGFyZ2V0KS5wYXJlbnRzKCcucGFnZTpmaXJzdCcpO1xuICAgICAgJGl0ZW0gPSAkcGFnZS5maW5kKCcudGFyZ2V0Jyk7XG4gICAgICBwb3NpdGlvbiA9ICRpdGVtLm9mZnNldCgpLnRvcCArICRwYWdlLnNjcm9sbFRvcCgpIC0gJHBhZ2UuaGVpZ2h0KCkgLyAyO1xuICAgICAgd2lraS5sb2coJ3Njcm9sbCcsICRwYWdlLCAkaXRlbSwgcG9zaXRpb24pO1xuICAgICAgcmV0dXJuICRwYWdlLnN0b3AoKS5hbmltYXRlKHtcbiAgICAgICAgc2Nyb2xsVG9wOiBwb3N0aW9uXG4gICAgICB9LCAnc2xvdycpO1xuICAgIH0pLmRlbGVnYXRlKCcuc2NvcmUnLCAnaG92ZXInLCBmdW5jdGlvbihlKSB7XG4gICAgICByZXR1cm4gJCgnLm1haW4nKS50cmlnZ2VyKCd0aHVtYicsICQoZS50YXJnZXQpLmRhdGEoJ3RodW1iJykpO1xuICAgIH0pO1xuICAgICQoXCIucHJvdmlkZXIgaW5wdXRcIikuY2xpY2soZnVuY3Rpb24oKSB7XG4gICAgICAkKFwiZm9vdGVyIGlucHV0OmZpcnN0XCIpLnZhbCgkKHRoaXMpLmF0dHIoJ2RhdGEtcHJvdmlkZXInKSk7XG4gICAgICByZXR1cm4gJChcImZvb3RlciBmb3JtXCIpLnN1Ym1pdCgpO1xuICAgIH0pO1xuICAgICQoJ2JvZHknKS5vbignbmV3LW5laWdoYm9yLWRvbmUnLCBmdW5jdGlvbihlLCBuZWlnaGJvcikge1xuICAgICAgcmV0dXJuICQoJy5wYWdlJykuZWFjaChmdW5jdGlvbihpbmRleCwgZWxlbWVudCkge1xuICAgICAgICByZXR1cm4gd2lraS5lbWl0VHdpbnMoJChlbGVtZW50KSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gJChmdW5jdGlvbigpIHtcbiAgICAgIHN0YXRlLmZpcnN0KCk7XG4gICAgICAkKCcucGFnZScpLmVhY2gocmVmcmVzaCk7XG4gICAgICByZXR1cm4gYWN0aXZlLnNldCgkKCcucGFnZScpLmxhc3QoKSk7XG4gICAgfSk7XG4gIH0pO1xuXG59KS5jYWxsKHRoaXMpO1xuIiwiKGZ1bmN0aW9uKCkge1xuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHBhZ2UpIHtcbiAgICB2YXIgcDEsIHAyLCBzeW5vcHNpcztcbiAgICBzeW5vcHNpcyA9IHBhZ2Uuc3lub3BzaXM7XG4gICAgaWYgKChwYWdlICE9IG51bGwpICYmIChwYWdlLnN0b3J5ICE9IG51bGwpKSB7XG4gICAgICBwMSA9IHBhZ2Uuc3RvcnlbMF07XG4gICAgICBwMiA9IHBhZ2Uuc3RvcnlbMV07XG4gICAgICBpZiAocDEgJiYgcDEudHlwZSA9PT0gJ3BhcmFncmFwaCcpIHtcbiAgICAgICAgc3lub3BzaXMgfHwgKHN5bm9wc2lzID0gcDEudGV4dCk7XG4gICAgICB9XG4gICAgICBpZiAocDIgJiYgcDIudHlwZSA9PT0gJ3BhcmFncmFwaCcpIHtcbiAgICAgICAgc3lub3BzaXMgfHwgKHN5bm9wc2lzID0gcDIudGV4dCk7XG4gICAgICB9XG4gICAgICBpZiAocDEgJiYgKHAxLnRleHQgIT0gbnVsbCkpIHtcbiAgICAgICAgc3lub3BzaXMgfHwgKHN5bm9wc2lzID0gcDEudGV4dCk7XG4gICAgICB9XG4gICAgICBpZiAocDIgJiYgKHAyLnRleHQgIT0gbnVsbCkpIHtcbiAgICAgICAgc3lub3BzaXMgfHwgKHN5bm9wc2lzID0gcDIudGV4dCk7XG4gICAgICB9XG4gICAgICBzeW5vcHNpcyB8fCAoc3lub3BzaXMgPSAocGFnZS5zdG9yeSAhPSBudWxsKSAmJiAoXCJBIHBhZ2Ugd2l0aCBcIiArIHBhZ2Uuc3RvcnkubGVuZ3RoICsgXCIgaXRlbXMuXCIpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3lub3BzaXMgPSAnQSBwYWdlIHdpdGggbm8gc3RvcnkuJztcbiAgICB9XG4gICAgcmV0dXJuIHN5bm9wc2lzO1xuICB9O1xuXG59KS5jYWxsKHRoaXMpO1xuIiwiKGZ1bmN0aW9uKCkge1xuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG93bmVyKSB7XG4gICAgJChcIiN1c2VyLWVtYWlsXCIpLmhpZGUoKTtcbiAgICAkKFwiI3BlcnNvbmEtbG9naW4tYnRuXCIpLmhpZGUoKTtcbiAgICAkKFwiI3BlcnNvbmEtbG9nb3V0LWJ0blwiKS5oaWRlKCk7XG4gICAgbmF2aWdhdG9yLmlkLndhdGNoKHtcbiAgICAgIGxvZ2dlZEluVXNlcjogb3duZXIsXG4gICAgICBvbmxvZ2luOiBmdW5jdGlvbihhc3NlcnRpb24pIHtcbiAgICAgICAgcmV0dXJuICQucG9zdChcIi9wZXJzb25hX2xvZ2luXCIsIHtcbiAgICAgICAgICBhc3NlcnRpb246IGFzc2VydGlvblxuICAgICAgICB9LCBmdW5jdGlvbih2ZXJpZmllZCkge1xuICAgICAgICAgIHZlcmlmaWVkID0gSlNPTi5wYXJzZSh2ZXJpZmllZCk7XG4gICAgICAgICAgaWYgKFwib2theVwiID09PSB2ZXJpZmllZC5zdGF0dXMpIHtcbiAgICAgICAgICAgIHJldHVybiB3aW5kb3cubG9jYXRpb24gPSBcIi9cIjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmF2aWdhdG9yLmlkLmxvZ291dCgpO1xuICAgICAgICAgICAgaWYgKFwid3JvbmctYWRkcmVzc1wiID09PSB2ZXJpZmllZC5zdGF0dXMpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5sb2NhdGlvbiA9IFwiL29vcHNcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICAgIG9ubG9nb3V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuICQucG9zdChcIi9wZXJzb25hX2xvZ291dFwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gd2luZG93LmxvY2F0aW9uID0gXCIvXCI7XG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICAgIG9ucmVhZHk6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAob3duZXIpIHtcbiAgICAgICAgICAkKFwiI3BlcnNvbmEtbG9naW4tYnRuXCIpLmhpZGUoKTtcbiAgICAgICAgICByZXR1cm4gJChcIiNwZXJzb25hLWxvZ291dC1idG5cIikuc2hvdygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICQoXCIjcGVyc29uYS1sb2dpbi1idG5cIikuc2hvdygpO1xuICAgICAgICAgIHJldHVybiAkKFwiI3BlcnNvbmEtbG9nb3V0LWJ0blwiKS5oaWRlKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICAkKFwiI3BlcnNvbmEtbG9naW4tYnRuXCIpLmNsaWNrKGZ1bmN0aW9uKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHJldHVybiBuYXZpZ2F0b3IuaWQucmVxdWVzdCh7fSk7XG4gICAgfSk7XG4gICAgcmV0dXJuICQoXCIjcGVyc29uYS1sb2dvdXQtYnRuXCIpLmNsaWNrKGZ1bmN0aW9uKGUpIHtcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHJldHVybiBuYXZpZ2F0b3IuaWQubG9nb3V0KCk7XG4gICAgfSk7XG4gIH07XG5cbn0pLmNhbGwodGhpcyk7XG4iLCIoZnVuY3Rpb24oKSB7XG4gIHZhciBhY3RpdmUsIGZpbmRTY3JvbGxDb250YWluZXIsIHNjcm9sbFRvO1xuXG4gIG1vZHVsZS5leHBvcnRzID0gYWN0aXZlID0ge307XG5cbiAgYWN0aXZlLnNjcm9sbENvbnRhaW5lciA9IHZvaWQgMDtcblxuICBmaW5kU2Nyb2xsQ29udGFpbmVyID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHNjcm9sbGVkO1xuICAgIHNjcm9sbGVkID0gJChcImJvZHksIGh0bWxcIikuZmlsdGVyKGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuICQodGhpcykuc2Nyb2xsTGVmdCgpID4gMDtcbiAgICB9KTtcbiAgICBpZiAoc2Nyb2xsZWQubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIHNjcm9sbGVkO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gJChcImJvZHksIGh0bWxcIikuc2Nyb2xsTGVmdCgxMikuZmlsdGVyKGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gJCh0aGlzKS5zY3JvbGxMZWZ0KCkgPiAwO1xuICAgICAgfSkuc2Nyb2xsVG9wKDApO1xuICAgIH1cbiAgfTtcblxuICBzY3JvbGxUbyA9IGZ1bmN0aW9uKGVsKSB7XG4gICAgdmFyIGJvZHlXaWR0aCwgY29udGVudFdpZHRoLCBtYXhYLCBtaW5YLCB0YXJnZXQsIHdpZHRoO1xuICAgIGlmIChhY3RpdmUuc2Nyb2xsQ29udGFpbmVyID09IG51bGwpIHtcbiAgICAgIGFjdGl2ZS5zY3JvbGxDb250YWluZXIgPSBmaW5kU2Nyb2xsQ29udGFpbmVyKCk7XG4gICAgfVxuICAgIGJvZHlXaWR0aCA9ICQoXCJib2R5XCIpLndpZHRoKCk7XG4gICAgbWluWCA9IGFjdGl2ZS5zY3JvbGxDb250YWluZXIuc2Nyb2xsTGVmdCgpO1xuICAgIG1heFggPSBtaW5YICsgYm9keVdpZHRoO1xuICAgIHRhcmdldCA9IGVsLnBvc2l0aW9uKCkubGVmdDtcbiAgICB3aWR0aCA9IGVsLm91dGVyV2lkdGgodHJ1ZSk7XG4gICAgY29udGVudFdpZHRoID0gJChcIi5wYWdlXCIpLm91dGVyV2lkdGgodHJ1ZSkgKiAkKFwiLnBhZ2VcIikuc2l6ZSgpO1xuICAgIGlmICh0YXJnZXQgPCBtaW5YKSB7XG4gICAgICByZXR1cm4gYWN0aXZlLnNjcm9sbENvbnRhaW5lci5hbmltYXRlKHtcbiAgICAgICAgc2Nyb2xsTGVmdDogdGFyZ2V0XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKHRhcmdldCArIHdpZHRoID4gbWF4WCkge1xuICAgICAgcmV0dXJuIGFjdGl2ZS5zY3JvbGxDb250YWluZXIuYW5pbWF0ZSh7XG4gICAgICAgIHNjcm9sbExlZnQ6IHRhcmdldCAtIChib2R5V2lkdGggLSB3aWR0aClcbiAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAobWF4WCA+ICQoXCIucGFnZXNcIikub3V0ZXJXaWR0aCgpKSB7XG4gICAgICByZXR1cm4gYWN0aXZlLnNjcm9sbENvbnRhaW5lci5hbmltYXRlKHtcbiAgICAgICAgc2Nyb2xsTGVmdDogTWF0aC5taW4odGFyZ2V0LCBjb250ZW50V2lkdGggLSBib2R5V2lkdGgpXG4gICAgICB9KTtcbiAgICB9XG4gIH07XG5cbiAgYWN0aXZlLnNldCA9IGZ1bmN0aW9uKGVsKSB7XG4gICAgZWwgPSAkKGVsKTtcbiAgICAkKFwiLmFjdGl2ZVwiKS5yZW1vdmVDbGFzcyhcImFjdGl2ZVwiKTtcbiAgICByZXR1cm4gc2Nyb2xsVG8oZWwuYWRkQ2xhc3MoXCJhY3RpdmVcIikpO1xuICB9O1xuXG59KS5jYWxsKHRoaXMpO1xuIiwiKGZ1bmN0aW9uKCkge1xuICB2YXIgdXRpbCwgd2lraTtcblxuICB3aWtpID0gcmVxdWlyZSgnLi93aWtpJyk7XG5cbiAgbW9kdWxlLmV4cG9ydHMgPSB3aWtpLnV0aWwgPSB1dGlsID0ge307XG5cbiAgdXRpbC5zeW1ib2xzID0ge1xuICAgIGNyZWF0ZTogJ+KYvCcsXG4gICAgYWRkOiAnKycsXG4gICAgZWRpdDogJ+KcjicsXG4gICAgZm9yazogJ+KakScsXG4gICAgbW92ZTogJ+KGlScsXG4gICAgcmVtb3ZlOiAn4pyVJ1xuICB9O1xuXG4gIHV0aWwucmFuZG9tQnl0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiAoKCgxICsgTWF0aC5yYW5kb20oKSkgKiAweDEwMCkgfCAwKS50b1N0cmluZygxNikuc3Vic3RyaW5nKDEpO1xuICB9O1xuXG4gIHV0aWwucmFuZG9tQnl0ZXMgPSBmdW5jdGlvbihuKSB7XG4gICAgcmV0dXJuICgoZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgX2ksIF9yZXN1bHRzO1xuICAgICAgX3Jlc3VsdHMgPSBbXTtcbiAgICAgIGZvciAoX2kgPSAxOyAxIDw9IG4gPyBfaSA8PSBuIDogX2kgPj0gbjsgMSA8PSBuID8gX2krKyA6IF9pLS0pIHtcbiAgICAgICAgX3Jlc3VsdHMucHVzaCh1dGlsLnJhbmRvbUJ5dGUoKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gX3Jlc3VsdHM7XG4gICAgfSkoKSkuam9pbignJyk7XG4gIH07XG5cbiAgdXRpbC5mb3JtYXRUaW1lID0gZnVuY3Rpb24odGltZSkge1xuICAgIHZhciBhbSwgZCwgaCwgbWksIG1vO1xuICAgIGQgPSBuZXcgRGF0ZSgodGltZSA+IDEwMDAwMDAwMDAwID8gdGltZSA6IHRpbWUgKiAxMDAwKSk7XG4gICAgbW8gPSBbJ0phbicsICdGZWInLCAnTWFyJywgJ0FwcicsICdNYXknLCAnSnVuJywgJ0p1bCcsICdBdWcnLCAnU2VwJywgJ09jdCcsICdOb3YnLCAnRGVjJ11bZC5nZXRNb250aCgpXTtcbiAgICBoID0gZC5nZXRIb3VycygpO1xuICAgIGFtID0gaCA8IDEyID8gJ0FNJyA6ICdQTSc7XG4gICAgaCA9IGggPT09IDAgPyAxMiA6IGggPiAxMiA/IGggLSAxMiA6IGg7XG4gICAgbWkgPSAoZC5nZXRNaW51dGVzKCkgPCAxMCA/IFwiMFwiIDogXCJcIikgKyBkLmdldE1pbnV0ZXMoKTtcbiAgICByZXR1cm4gXCJcIiArIGggKyBcIjpcIiArIG1pICsgXCIgXCIgKyBhbSArIFwiPGJyPlwiICsgKGQuZ2V0RGF0ZSgpKSArIFwiIFwiICsgbW8gKyBcIiBcIiArIChkLmdldEZ1bGxZZWFyKCkpO1xuICB9O1xuXG4gIHV0aWwuZm9ybWF0RGF0ZSA9IGZ1bmN0aW9uKG1zU2luY2VFcG9jaCkge1xuICAgIHZhciBhbSwgZCwgZGF5LCBoLCBtaSwgbW8sIHNlYywgd2ssIHlyO1xuICAgIGQgPSBuZXcgRGF0ZShtc1NpbmNlRXBvY2gpO1xuICAgIHdrID0gWydTdW4nLCAnTW9uJywgJ1R1ZScsICdXZWQnLCAnVGh1JywgJ0ZyaScsICdTYXQnXVtkLmdldERheSgpXTtcbiAgICBtbyA9IFsnSmFuJywgJ0ZlYicsICdNYXInLCAnQXByJywgJ01heScsICdKdW4nLCAnSnVsJywgJ0F1ZycsICdTZXAnLCAnT2N0JywgJ05vdicsICdEZWMnXVtkLmdldE1vbnRoKCldO1xuICAgIGRheSA9IGQuZ2V0RGF0ZSgpO1xuICAgIHlyID0gZC5nZXRGdWxsWWVhcigpO1xuICAgIGggPSBkLmdldEhvdXJzKCk7XG4gICAgYW0gPSBoIDwgMTIgPyAnQU0nIDogJ1BNJztcbiAgICBoID0gaCA9PT0gMCA/IDEyIDogaCA+IDEyID8gaCAtIDEyIDogaDtcbiAgICBtaSA9IChkLmdldE1pbnV0ZXMoKSA8IDEwID8gXCIwXCIgOiBcIlwiKSArIGQuZ2V0TWludXRlcygpO1xuICAgIHNlYyA9IChkLmdldFNlY29uZHMoKSA8IDEwID8gXCIwXCIgOiBcIlwiKSArIGQuZ2V0U2Vjb25kcygpO1xuICAgIHJldHVybiBcIlwiICsgd2sgKyBcIiBcIiArIG1vICsgXCIgXCIgKyBkYXkgKyBcIiwgXCIgKyB5ciArIFwiPGJyPlwiICsgaCArIFwiOlwiICsgbWkgKyBcIjpcIiArIHNlYyArIFwiIFwiICsgYW07XG4gIH07XG5cbiAgdXRpbC5mb3JtYXRFbGFwc2VkVGltZSA9IGZ1bmN0aW9uKG1zU2luY2VFcG9jaCkge1xuICAgIHZhciBkYXlzLCBocnMsIG1pbnMsIG1vbnRocywgbXNlY3MsIHNlY3MsIHdlZWtzLCB5ZWFycztcbiAgICBtc2VjcyA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpIC0gbXNTaW5jZUVwb2NoO1xuICAgIGlmICgoc2VjcyA9IG1zZWNzIC8gMTAwMCkgPCAyKSB7XG4gICAgICByZXR1cm4gXCJcIiArIChNYXRoLmZsb29yKG1zZWNzKSkgKyBcIiBtaWxsaXNlY29uZHMgYWdvXCI7XG4gICAgfVxuICAgIGlmICgobWlucyA9IHNlY3MgLyA2MCkgPCAyKSB7XG4gICAgICByZXR1cm4gXCJcIiArIChNYXRoLmZsb29yKHNlY3MpKSArIFwiIHNlY29uZHMgYWdvXCI7XG4gICAgfVxuICAgIGlmICgoaHJzID0gbWlucyAvIDYwKSA8IDIpIHtcbiAgICAgIHJldHVybiBcIlwiICsgKE1hdGguZmxvb3IobWlucykpICsgXCIgbWludXRlcyBhZ29cIjtcbiAgICB9XG4gICAgaWYgKChkYXlzID0gaHJzIC8gMjQpIDwgMikge1xuICAgICAgcmV0dXJuIFwiXCIgKyAoTWF0aC5mbG9vcihocnMpKSArIFwiIGhvdXJzIGFnb1wiO1xuICAgIH1cbiAgICBpZiAoKHdlZWtzID0gZGF5cyAvIDcpIDwgMikge1xuICAgICAgcmV0dXJuIFwiXCIgKyAoTWF0aC5mbG9vcihkYXlzKSkgKyBcIiBkYXlzIGFnb1wiO1xuICAgIH1cbiAgICBpZiAoKG1vbnRocyA9IGRheXMgLyAzMSkgPCAyKSB7XG4gICAgICByZXR1cm4gXCJcIiArIChNYXRoLmZsb29yKHdlZWtzKSkgKyBcIiB3ZWVrcyBhZ29cIjtcbiAgICB9XG4gICAgaWYgKCh5ZWFycyA9IGRheXMgLyAzNjUpIDwgMikge1xuICAgICAgcmV0dXJuIFwiXCIgKyAoTWF0aC5mbG9vcihtb250aHMpKSArIFwiIG1vbnRocyBhZ29cIjtcbiAgICB9XG4gICAgcmV0dXJuIFwiXCIgKyAoTWF0aC5mbG9vcih5ZWFycykpICsgXCIgeWVhcnMgYWdvXCI7XG4gIH07XG5cbiAgdXRpbC5lbXB0eVBhZ2UgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdGl0bGU6ICdlbXB0eScsXG4gICAgICBzdG9yeTogW10sXG4gICAgICBqb3VybmFsOiBbXVxuICAgIH07XG4gIH07XG5cbiAgdXRpbC5nZXRTZWxlY3Rpb25Qb3MgPSBmdW5jdGlvbihqUXVlcnlFbGVtZW50KSB7XG4gICAgdmFyIGVsLCBpZVBvcywgc2VsO1xuICAgIGVsID0galF1ZXJ5RWxlbWVudC5nZXQoMCk7XG4gICAgaWYgKGRvY3VtZW50LnNlbGVjdGlvbikge1xuICAgICAgZWwuZm9jdXMoKTtcbiAgICAgIHNlbCA9IGRvY3VtZW50LnNlbGVjdGlvbi5jcmVhdGVSYW5nZSgpO1xuICAgICAgc2VsLm1vdmVTdGFydCgnY2hhcmFjdGVyJywgLWVsLnZhbHVlLmxlbmd0aCk7XG4gICAgICBpZVBvcyA9IHNlbC50ZXh0Lmxlbmd0aDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHN0YXJ0OiBpZVBvcyxcbiAgICAgICAgZW5kOiBpZVBvc1xuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQ6IGVsLnNlbGVjdGlvblN0YXJ0LFxuICAgICAgICBlbmQ6IGVsLnNlbGVjdGlvbkVuZFxuICAgICAgfTtcbiAgICB9XG4gIH07XG5cbiAgdXRpbC5zZXRDYXJldFBvc2l0aW9uID0gZnVuY3Rpb24oalF1ZXJ5RWxlbWVudCwgY2FyZXRQb3MpIHtcbiAgICB2YXIgZWwsIHJhbmdlO1xuICAgIGVsID0galF1ZXJ5RWxlbWVudC5nZXQoMCk7XG4gICAgaWYgKGVsICE9IG51bGwpIHtcbiAgICAgIGlmIChlbC5jcmVhdGVUZXh0UmFuZ2UpIHtcbiAgICAgICAgcmFuZ2UgPSBlbC5jcmVhdGVUZXh0UmFuZ2UoKTtcbiAgICAgICAgcmFuZ2UubW92ZShcImNoYXJhY3RlclwiLCBjYXJldFBvcyk7XG4gICAgICAgIHJhbmdlLnNlbGVjdCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZWwuc2V0U2VsZWN0aW9uUmFuZ2UoY2FyZXRQb3MsIGNhcmV0UG9zKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBlbC5mb2N1cygpO1xuICAgIH1cbiAgfTtcblxufSkuY2FsbCh0aGlzKTtcbiIsIihmdW5jdGlvbigpIHtcbiAgdmFyIGdldFNjcmlwdCwgcGx1Z2luLCBzY3JpcHRzLCB1dGlsLCB3aWtpO1xuXG4gIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxuICB3aWtpID0gcmVxdWlyZSgnLi93aWtpJyk7XG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBwbHVnaW4gPSB7fTtcblxuICBzY3JpcHRzID0ge307XG5cbiAgZ2V0U2NyaXB0ID0gd2lraS5nZXRTY3JpcHQgPSBmdW5jdGlvbih1cmwsIGNhbGxiYWNrKSB7XG4gICAgaWYgKGNhbGxiYWNrID09IG51bGwpIHtcbiAgICAgIGNhbGxiYWNrID0gZnVuY3Rpb24oKSB7fTtcbiAgICB9XG4gICAgaWYgKHNjcmlwdHNbdXJsXSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuICQuZ2V0U2NyaXB0KHVybCkuZG9uZShmdW5jdGlvbigpIHtcbiAgICAgICAgc2NyaXB0c1t1cmxdID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgICB9KS5mYWlsKGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfTtcblxuICBwbHVnaW4uZ2V0ID0gd2lraS5nZXRQbHVnaW4gPSBmdW5jdGlvbihuYW1lLCBjYWxsYmFjaykge1xuICAgIGlmICh3aW5kb3cucGx1Z2luc1tuYW1lXSkge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKHdpbmRvdy5wbHVnaW5zW25hbWVdKTtcbiAgICB9XG4gICAgcmV0dXJuIGdldFNjcmlwdChcIi9wbHVnaW5zL1wiICsgbmFtZSArIFwiL1wiICsgbmFtZSArIFwiLmpzXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKHdpbmRvdy5wbHVnaW5zW25hbWVdKSB7XG4gICAgICAgIHJldHVybiBjYWxsYmFjayh3aW5kb3cucGx1Z2luc1tuYW1lXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZ2V0U2NyaXB0KFwiL3BsdWdpbnMvXCIgKyBuYW1lICsgXCIuanNcIiwgZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBjYWxsYmFjayh3aW5kb3cucGx1Z2luc1tuYW1lXSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfTtcblxuICBwbHVnaW5bXCJkb1wiXSA9IHdpa2kuZG9QbHVnaW4gPSBmdW5jdGlvbihkaXYsIGl0ZW0sIGRvbmUpIHtcbiAgICB2YXIgZXJyb3I7XG4gICAgaWYgKGRvbmUgPT0gbnVsbCkge1xuICAgICAgZG9uZSA9IGZ1bmN0aW9uKCkge307XG4gICAgfVxuICAgIGVycm9yID0gZnVuY3Rpb24oZXgpIHtcbiAgICAgIHZhciBlcnJvckVsZW1lbnQ7XG4gICAgICBlcnJvckVsZW1lbnQgPSAkKFwiPGRpdiAvPlwiKS5hZGRDbGFzcygnZXJyb3InKTtcbiAgICAgIGVycm9yRWxlbWVudC50ZXh0KGV4LnRvU3RyaW5nKCkpO1xuICAgICAgcmV0dXJuIGRpdi5hcHBlbmQoZXJyb3JFbGVtZW50KTtcbiAgICB9O1xuICAgIGRpdi5kYXRhKCdwYWdlRWxlbWVudCcsIGRpdi5wYXJlbnRzKFwiLnBhZ2VcIikpO1xuICAgIGRpdi5kYXRhKCdpdGVtJywgaXRlbSk7XG4gICAgcmV0dXJuIHBsdWdpbi5nZXQoaXRlbS50eXBlLCBmdW5jdGlvbihzY3JpcHQpIHtcbiAgICAgIHZhciBlcnI7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoc2NyaXB0ID09IG51bGwpIHtcbiAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBmaW5kIHBsdWdpbiBmb3IgJ1wiICsgaXRlbS50eXBlICsgXCInXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzY3JpcHQuZW1pdC5sZW5ndGggPiAyKSB7XG4gICAgICAgICAgcmV0dXJuIHNjcmlwdC5lbWl0KGRpdiwgaXRlbSwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBzY3JpcHQuYmluZChkaXYsIGl0ZW0pO1xuICAgICAgICAgICAgcmV0dXJuIGRvbmUoKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzY3JpcHQuZW1pdChkaXYsIGl0ZW0pO1xuICAgICAgICAgIHNjcmlwdC5iaW5kKGRpdiwgaXRlbSk7XG4gICAgICAgICAgcmV0dXJuIGRvbmUoKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoX2Vycm9yKSB7XG4gICAgICAgIGVyciA9IF9lcnJvcjtcbiAgICAgICAgd2lraS5sb2coJ3BsdWdpbiBlcnJvcicsIGVycik7XG4gICAgICAgIGVycm9yKGVycik7XG4gICAgICAgIHJldHVybiBkb25lKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgd2lraS5yZWdpc3RlclBsdWdpbiA9IGZ1bmN0aW9uKHBsdWdpbk5hbWUsIHBsdWdpbkZuKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5wbHVnaW5zW3BsdWdpbk5hbWVdID0gcGx1Z2luRm4oJCk7XG4gIH07XG5cbiAgd2luZG93LnBsdWdpbnMgPSB7XG4gICAgcmVmZXJlbmNlOiByZXF1aXJlKCcuL3JlZmVyZW5jZScpLFxuICAgIGZhY3Rvcnk6IHJlcXVpcmUoJy4vZmFjdG9yeScpLFxuICAgIHBhcmFncmFwaDoge1xuICAgICAgZW1pdDogZnVuY3Rpb24oZGl2LCBpdGVtKSB7XG4gICAgICAgIHZhciB0ZXh0LCBfaSwgX2xlbiwgX3JlZiwgX3Jlc3VsdHM7XG4gICAgICAgIF9yZWYgPSBpdGVtLnRleHQuc3BsaXQoL1xcblxcbisvKTtcbiAgICAgICAgX3Jlc3VsdHMgPSBbXTtcbiAgICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgICAgdGV4dCA9IF9yZWZbX2ldO1xuICAgICAgICAgIGlmICh0ZXh0Lm1hdGNoKC9cXFMvKSkge1xuICAgICAgICAgICAgX3Jlc3VsdHMucHVzaChkaXYuYXBwZW5kKFwiPHA+XCIgKyAod2lraS5yZXNvbHZlTGlua3ModGV4dCkpICsgXCI8L3A+XCIpKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgX3Jlc3VsdHMucHVzaCh2b2lkIDApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX3Jlc3VsdHM7XG4gICAgICB9LFxuICAgICAgYmluZDogZnVuY3Rpb24oZGl2LCBpdGVtKSB7XG4gICAgICAgIHJldHVybiBkaXYuZGJsY2xpY2soZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIHdpa2kudGV4dEVkaXRvcihkaXYsIGl0ZW0sIG51bGwsIHRydWUpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGltYWdlOiB7XG4gICAgICBlbWl0OiBmdW5jdGlvbihkaXYsIGl0ZW0pIHtcbiAgICAgICAgaXRlbS50ZXh0IHx8IChpdGVtLnRleHQgPSBpdGVtLmNhcHRpb24pO1xuICAgICAgICByZXR1cm4gZGl2LmFwcGVuZChcIjxpbWcgY2xhc3M9dGh1bWJuYWlsIHNyYz1cXFwiXCIgKyBpdGVtLnVybCArIFwiXFxcIj4gPHA+XCIgKyAod2lraS5yZXNvbHZlTGlua3MoaXRlbS50ZXh0KSkgKyBcIjwvcD5cIik7XG4gICAgICB9LFxuICAgICAgYmluZDogZnVuY3Rpb24oZGl2LCBpdGVtKSB7XG4gICAgICAgIGRpdi5kYmxjbGljayhmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gd2lraS50ZXh0RWRpdG9yKGRpdiwgaXRlbSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZGl2LmZpbmQoJ2ltZycpLmRibGNsaWNrKGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHJldHVybiB3aWtpLmRpYWxvZyhpdGVtLnRleHQsIHRoaXMpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGZ1dHVyZToge1xuICAgICAgZW1pdDogZnVuY3Rpb24oZGl2LCBpdGVtKSB7XG4gICAgICAgIHZhciBpbmZvLCBfaSwgX2xlbiwgX3JlZiwgX3Jlc3VsdHM7XG4gICAgICAgIGRpdi5hcHBlbmQoXCJcIiArIGl0ZW0udGV4dCArIFwiPGJyPjxicj48YnV0dG9uIGNsYXNzPVxcXCJjcmVhdGVcXFwiPmNyZWF0ZTwvYnV0dG9uPiBuZXcgYmxhbmsgcGFnZVwiKTtcbiAgICAgICAgaWYgKCgoaW5mbyA9IHdpa2kubmVpZ2hib3Job29kW2xvY2F0aW9uLmhvc3RdKSAhPSBudWxsKSAmJiAoaW5mby5zaXRlbWFwICE9IG51bGwpKSB7XG4gICAgICAgICAgX3JlZiA9IGluZm8uc2l0ZW1hcDtcbiAgICAgICAgICBfcmVzdWx0cyA9IFtdO1xuICAgICAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZi5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICAgICAgaXRlbSA9IF9yZWZbX2ldO1xuICAgICAgICAgICAgaWYgKGl0ZW0uc2x1Zy5tYXRjaCgvLXRlbXBsYXRlJC8pKSB7XG4gICAgICAgICAgICAgIF9yZXN1bHRzLnB1c2goZGl2LmFwcGVuZChcIjxicj48YnV0dG9uIGNsYXNzPVxcXCJjcmVhdGVcXFwiIGRhdGEtc2x1Zz1cIiArIGl0ZW0uc2x1ZyArIFwiPmNyZWF0ZTwvYnV0dG9uPiBmcm9tIFwiICsgKHdpa2kucmVzb2x2ZUxpbmtzKFwiW1tcIiArIGl0ZW0udGl0bGUgKyBcIl1dXCIpKSkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgX3Jlc3VsdHMucHVzaCh2b2lkIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gX3Jlc3VsdHM7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBiaW5kOiBmdW5jdGlvbihkaXYsIGl0ZW0pIHt9XG4gICAgfVxuICB9O1xuXG59KS5jYWxsKHRoaXMpO1xuIiwiKGZ1bmN0aW9uKCkge1xuICB2YXIgYWN0aXZlLCBzdGF0ZSwgd2lraSxcbiAgICBfX2luZGV4T2YgPSBbXS5pbmRleE9mIHx8IGZ1bmN0aW9uKGl0ZW0pIHsgZm9yICh2YXIgaSA9IDAsIGwgPSB0aGlzLmxlbmd0aDsgaSA8IGw7IGkrKykgeyBpZiAoaSBpbiB0aGlzICYmIHRoaXNbaV0gPT09IGl0ZW0pIHJldHVybiBpOyB9IHJldHVybiAtMTsgfTtcblxuICB3aWtpID0gcmVxdWlyZSgnLi93aWtpJyk7XG5cbiAgYWN0aXZlID0gcmVxdWlyZSgnLi9hY3RpdmUnKTtcblxuICBtb2R1bGUuZXhwb3J0cyA9IHN0YXRlID0ge307XG5cbiAgc3RhdGUucGFnZXNJbkRvbSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiAkLm1ha2VBcnJheSgkKFwiLnBhZ2VcIikubWFwKGZ1bmN0aW9uKF8sIGVsKSB7XG4gICAgICByZXR1cm4gZWwuaWQ7XG4gICAgfSkpO1xuICB9O1xuXG4gIHN0YXRlLnVybFBhZ2VzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGk7XG4gICAgcmV0dXJuICgoZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgX2ksIF9sZW4sIF9yZWYsIF9yZXN1bHRzO1xuICAgICAgX3JlZiA9ICQobG9jYXRpb24pLmF0dHIoJ3BhdGhuYW1lJykuc3BsaXQoJy8nKTtcbiAgICAgIF9yZXN1bHRzID0gW107XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYubGVuZ3RoOyBfaSA8IF9sZW47IF9pICs9IDIpIHtcbiAgICAgICAgaSA9IF9yZWZbX2ldO1xuICAgICAgICBfcmVzdWx0cy5wdXNoKGkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIF9yZXN1bHRzO1xuICAgIH0pKCkpLnNsaWNlKDEpO1xuICB9O1xuXG4gIHN0YXRlLmxvY3NJbkRvbSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiAkLm1ha2VBcnJheSgkKFwiLnBhZ2VcIikubWFwKGZ1bmN0aW9uKF8sIGVsKSB7XG4gICAgICByZXR1cm4gJChlbCkuZGF0YSgnc2l0ZScpIHx8ICd2aWV3JztcbiAgICB9KSk7XG4gIH07XG5cbiAgc3RhdGUudXJsTG9jcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBqLCBfaSwgX2xlbiwgX3JlZiwgX3Jlc3VsdHM7XG4gICAgX3JlZiA9ICQobG9jYXRpb24pLmF0dHIoJ3BhdGhuYW1lJykuc3BsaXQoJy8nKS5zbGljZSgxKTtcbiAgICBfcmVzdWx0cyA9IFtdO1xuICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZi5sZW5ndGg7IF9pIDwgX2xlbjsgX2kgKz0gMikge1xuICAgICAgaiA9IF9yZWZbX2ldO1xuICAgICAgX3Jlc3VsdHMucHVzaChqKTtcbiAgICB9XG4gICAgcmV0dXJuIF9yZXN1bHRzO1xuICB9O1xuXG4gIHN0YXRlLnNldFVybCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBpZHgsIGxvY3MsIHBhZ2UsIHBhZ2VzLCB1cmwsIF9yZWY7XG4gICAgZG9jdW1lbnQudGl0bGUgPSAoX3JlZiA9ICQoJy5wYWdlOmxhc3QnKS5kYXRhKCdkYXRhJykpICE9IG51bGwgPyBfcmVmLnRpdGxlIDogdm9pZCAwO1xuICAgIGlmIChoaXN0b3J5ICYmIGhpc3RvcnkucHVzaFN0YXRlKSB7XG4gICAgICBsb2NzID0gc3RhdGUubG9jc0luRG9tKCk7XG4gICAgICBwYWdlcyA9IHN0YXRlLnBhZ2VzSW5Eb20oKTtcbiAgICAgIHVybCA9ICgoZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBfaSwgX2xlbiwgX3Jlc3VsdHM7XG4gICAgICAgIF9yZXN1bHRzID0gW107XG4gICAgICAgIGZvciAoaWR4ID0gX2kgPSAwLCBfbGVuID0gcGFnZXMubGVuZ3RoOyBfaSA8IF9sZW47IGlkeCA9ICsrX2kpIHtcbiAgICAgICAgICBwYWdlID0gcGFnZXNbaWR4XTtcbiAgICAgICAgICBfcmVzdWx0cy5wdXNoKFwiL1wiICsgKChsb2NzICE9IG51bGwgPyBsb2NzW2lkeF0gOiB2b2lkIDApIHx8ICd2aWV3JykgKyBcIi9cIiArIHBhZ2UpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfcmVzdWx0cztcbiAgICAgIH0pKCkpLmpvaW4oJycpO1xuICAgICAgaWYgKHVybCAhPT0gJChsb2NhdGlvbikuYXR0cigncGF0aG5hbWUnKSkge1xuICAgICAgICByZXR1cm4gaGlzdG9yeS5wdXNoU3RhdGUobnVsbCwgbnVsbCwgdXJsKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgc3RhdGUuc2hvdyA9IGZ1bmN0aW9uKGUpIHtcbiAgICB2YXIgaWR4LCBuYW1lLCBuZXdMb2NzLCBuZXdQYWdlcywgb2xkLCBvbGRMb2NzLCBvbGRQYWdlcywgcHJldmlvdXMsIF9pLCBfbGVuLCBfcmVmO1xuICAgIG9sZFBhZ2VzID0gc3RhdGUucGFnZXNJbkRvbSgpO1xuICAgIG5ld1BhZ2VzID0gc3RhdGUudXJsUGFnZXMoKTtcbiAgICBvbGRMb2NzID0gc3RhdGUubG9jc0luRG9tKCk7XG4gICAgbmV3TG9jcyA9IHN0YXRlLnVybExvY3MoKTtcbiAgICBpZiAoIWxvY2F0aW9uLnBhdGhuYW1lIHx8IGxvY2F0aW9uLnBhdGhuYW1lID09PSAnLycpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgcHJldmlvdXMgPSAkKCcucGFnZScpLmVxKDApO1xuICAgIGZvciAoaWR4ID0gX2kgPSAwLCBfbGVuID0gbmV3UGFnZXMubGVuZ3RoOyBfaSA8IF9sZW47IGlkeCA9ICsrX2kpIHtcbiAgICAgIG5hbWUgPSBuZXdQYWdlc1tpZHhdO1xuICAgICAgaWYgKG5hbWUgIT09IG9sZFBhZ2VzW2lkeF0pIHtcbiAgICAgICAgb2xkID0gJCgnLnBhZ2UnKS5lcShpZHgpO1xuICAgICAgICBpZiAob2xkKSB7XG4gICAgICAgICAgb2xkLnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHdpa2kuY3JlYXRlUGFnZShuYW1lLCBuZXdMb2NzW2lkeF0pLmluc2VydEFmdGVyKHByZXZpb3VzKS5lYWNoKHdpa2kucmVmcmVzaCk7XG4gICAgICB9XG4gICAgICBwcmV2aW91cyA9ICQoJy5wYWdlJykuZXEoaWR4KTtcbiAgICB9XG4gICAgcHJldmlvdXMubmV4dEFsbCgpLnJlbW92ZSgpO1xuICAgIGFjdGl2ZS5zZXQoJCgnLnBhZ2UnKS5sYXN0KCkpO1xuICAgIHJldHVybiBkb2N1bWVudC50aXRsZSA9IChfcmVmID0gJCgnLnBhZ2U6bGFzdCcpLmRhdGEoJ2RhdGEnKSkgIT0gbnVsbCA/IF9yZWYudGl0bGUgOiB2b2lkIDA7XG4gIH07XG5cbiAgc3RhdGUuZmlyc3QgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZmlyc3RVcmxMb2NzLCBmaXJzdFVybFBhZ2VzLCBpZHgsIG9sZFBhZ2VzLCB1cmxQYWdlLCBfaSwgX2xlbiwgX3Jlc3VsdHM7XG4gICAgc3RhdGUuc2V0VXJsKCk7XG4gICAgZmlyc3RVcmxQYWdlcyA9IHN0YXRlLnVybFBhZ2VzKCk7XG4gICAgZmlyc3RVcmxMb2NzID0gc3RhdGUudXJsTG9jcygpO1xuICAgIG9sZFBhZ2VzID0gc3RhdGUucGFnZXNJbkRvbSgpO1xuICAgIF9yZXN1bHRzID0gW107XG4gICAgZm9yIChpZHggPSBfaSA9IDAsIF9sZW4gPSBmaXJzdFVybFBhZ2VzLmxlbmd0aDsgX2kgPCBfbGVuOyBpZHggPSArK19pKSB7XG4gICAgICB1cmxQYWdlID0gZmlyc3RVcmxQYWdlc1tpZHhdO1xuICAgICAgaWYgKF9faW5kZXhPZi5jYWxsKG9sZFBhZ2VzLCB1cmxQYWdlKSA8IDApIHtcbiAgICAgICAgaWYgKHVybFBhZ2UgIT09ICcnKSB7XG4gICAgICAgICAgX3Jlc3VsdHMucHVzaCh3aWtpLmNyZWF0ZVBhZ2UodXJsUGFnZSwgZmlyc3RVcmxMb2NzW2lkeF0pLmFwcGVuZFRvKCcubWFpbicpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBfcmVzdWx0cy5wdXNoKHZvaWQgMCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIF9yZXN1bHRzO1xuICB9O1xuXG59KS5jYWxsKHRoaXMpO1xuIiwiKGZ1bmN0aW9uKCkge1xuICB2YXIgY3JlYXRlO1xuXG4gIGNyZWF0ZSA9IGZ1bmN0aW9uKHJldkluZGV4LCBkYXRhKSB7XG4gICAgdmFyIGFmdGVySW5kZXgsIGVkaXRJbmRleCwgaXRlbUlkLCBpdGVtcywgam91cm5hbCwgam91cm5hbEVudHJ5LCByZW1vdmVJbmRleCwgcmV2Sm91cm5hbCwgcmV2U3RvcnksIHJldlN0b3J5SWRzLCByZXZUaXRsZSwgc3RvcnlJdGVtLCBfaSwgX2osIF9rLCBfbGVuLCBfbGVuMSwgX2xlbjIsIF9yZWY7XG4gICAgam91cm5hbCA9IGRhdGEuam91cm5hbDtcbiAgICByZXZUaXRsZSA9IGRhdGEudGl0bGU7XG4gICAgcmV2U3RvcnkgPSBbXTtcbiAgICByZXZKb3VybmFsID0gam91cm5hbC5zbGljZSgwLCArKCtyZXZJbmRleCkgKyAxIHx8IDllOSk7XG4gICAgZm9yIChfaSA9IDAsIF9sZW4gPSByZXZKb3VybmFsLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICBqb3VybmFsRW50cnkgPSByZXZKb3VybmFsW19pXTtcbiAgICAgIHJldlN0b3J5SWRzID0gcmV2U3RvcnkubWFwKGZ1bmN0aW9uKHN0b3J5SXRlbSkge1xuICAgICAgICByZXR1cm4gc3RvcnlJdGVtLmlkO1xuICAgICAgfSk7XG4gICAgICBzd2l0Y2ggKGpvdXJuYWxFbnRyeS50eXBlKSB7XG4gICAgICAgIGNhc2UgJ2NyZWF0ZSc6XG4gICAgICAgICAgaWYgKGpvdXJuYWxFbnRyeS5pdGVtLnRpdGxlICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldlRpdGxlID0gam91cm5hbEVudHJ5Lml0ZW0udGl0bGU7XG4gICAgICAgICAgICByZXZTdG9yeSA9IGpvdXJuYWxFbnRyeS5pdGVtLnN0b3J5IHx8IFtdO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnYWRkJzpcbiAgICAgICAgICBpZiAoKGFmdGVySW5kZXggPSByZXZTdG9yeUlkcy5pbmRleE9mKGpvdXJuYWxFbnRyeS5hZnRlcikpICE9PSAtMSkge1xuICAgICAgICAgICAgcmV2U3Rvcnkuc3BsaWNlKGFmdGVySW5kZXggKyAxLCAwLCBqb3VybmFsRW50cnkuaXRlbSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldlN0b3J5LnB1c2goam91cm5hbEVudHJ5Lml0ZW0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZWRpdCc6XG4gICAgICAgICAgaWYgKChlZGl0SW5kZXggPSByZXZTdG9yeUlkcy5pbmRleE9mKGpvdXJuYWxFbnRyeS5pZCkpICE9PSAtMSkge1xuICAgICAgICAgICAgcmV2U3Rvcnkuc3BsaWNlKGVkaXRJbmRleCwgMSwgam91cm5hbEVudHJ5Lml0ZW0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXZTdG9yeS5wdXNoKGpvdXJuYWxFbnRyeS5pdGVtKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ21vdmUnOlxuICAgICAgICAgIGl0ZW1zID0ge307XG4gICAgICAgICAgZm9yIChfaiA9IDAsIF9sZW4xID0gcmV2U3RvcnkubGVuZ3RoOyBfaiA8IF9sZW4xOyBfaisrKSB7XG4gICAgICAgICAgICBzdG9yeUl0ZW0gPSByZXZTdG9yeVtfal07XG4gICAgICAgICAgICBpdGVtc1tzdG9yeUl0ZW0uaWRdID0gc3RvcnlJdGVtO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXZTdG9yeSA9IFtdO1xuICAgICAgICAgIF9yZWYgPSBqb3VybmFsRW50cnkub3JkZXI7XG4gICAgICAgICAgZm9yIChfayA9IDAsIF9sZW4yID0gX3JlZi5sZW5ndGg7IF9rIDwgX2xlbjI7IF9rKyspIHtcbiAgICAgICAgICAgIGl0ZW1JZCA9IF9yZWZbX2tdO1xuICAgICAgICAgICAgaWYgKGl0ZW1zW2l0ZW1JZF0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICByZXZTdG9yeS5wdXNoKGl0ZW1zW2l0ZW1JZF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAncmVtb3ZlJzpcbiAgICAgICAgICBpZiAoKHJlbW92ZUluZGV4ID0gcmV2U3RvcnlJZHMuaW5kZXhPZihqb3VybmFsRW50cnkuaWQpKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHJldlN0b3J5LnNwbGljZShyZW1vdmVJbmRleCwgMSk7XG4gICAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgc3Rvcnk6IHJldlN0b3J5LFxuICAgICAgam91cm5hbDogcmV2Sm91cm5hbCxcbiAgICAgIHRpdGxlOiByZXZUaXRsZVxuICAgIH07XG4gIH07XG5cbiAgZXhwb3J0cy5jcmVhdGUgPSBjcmVhdGU7XG5cbn0pLmNhbGwodGhpcyk7XG4iLCIoZnVuY3Rpb24oKSB7XG4gIHZhciBiaW5kLCBlbWl0O1xuXG4gIGVtaXQgPSBmdW5jdGlvbigkaXRlbSwgaXRlbSkge1xuICAgIHZhciBzaXRlLCBzbHVnO1xuICAgIHNsdWcgPSBpdGVtLnNsdWcgfHwgJ3dlbGNvbWUtdmlzaXRvcnMnO1xuICAgIHNpdGUgPSBpdGVtLnNpdGU7XG4gICAgcmV0dXJuIHdpa2kucmVzb2x2ZUZyb20oc2l0ZSwgZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gJGl0ZW0uYXBwZW5kKFwiPHAgc3R5bGU9J21hcmdpbi1ib3R0b206M3B4Oyc+XFxuICA8aW1nIGNsYXNzPSdyZW1vdGUnXFxuICAgIHNyYz0nLy9cIiArIHNpdGUgKyBcIi9mYXZpY29uLnBuZydcXG4gICAgdGl0bGU9J1wiICsgc2l0ZSArIFwiJ1xcbiAgICBkYXRhLXNpdGU9XFxcIlwiICsgc2l0ZSArIFwiXFxcIlxcbiAgICBkYXRhLXNsdWc9XFxcIlwiICsgc2x1ZyArIFwiXFxcIlxcbiAgPlxcbiAgXCIgKyAod2lraS5yZXNvbHZlTGlua3MoXCJbW1wiICsgKGl0ZW0udGl0bGUgfHwgc2x1ZykgKyBcIl1dXCIpKSArIFwiXFxuPC9wPlxcbjxkaXY+XFxuICBcIiArICh3aWtpLnJlc29sdmVMaW5rcyhpdGVtLnRleHQpKSArIFwiXFxuPC9kaXY+XCIpO1xuICAgIH0pO1xuICB9O1xuXG4gIGJpbmQgPSBmdW5jdGlvbigkaXRlbSwgaXRlbSkge1xuICAgIHJldHVybiAkaXRlbS5kYmxjbGljayhmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB3aWtpLnRleHRFZGl0b3IoJGl0ZW0sIGl0ZW0pO1xuICAgIH0pO1xuICB9O1xuXG4gIG1vZHVsZS5leHBvcnRzID0ge1xuICAgIGVtaXQ6IGVtaXQsXG4gICAgYmluZDogYmluZFxuICB9O1xuXG59KS5jYWxsKHRoaXMpO1xuIiwiKGZ1bmN0aW9uKCkge1xuICB2YXIgYXJyYXlUb0pzb24sIGJpbmQsIGNzdlRvQXJyYXksIGVtaXQsXG4gICAgX19pbmRleE9mID0gW10uaW5kZXhPZiB8fCBmdW5jdGlvbihpdGVtKSB7IGZvciAodmFyIGkgPSAwLCBsID0gdGhpcy5sZW5ndGg7IGkgPCBsOyBpKyspIHsgaWYgKGkgaW4gdGhpcyAmJiB0aGlzW2ldID09PSBpdGVtKSByZXR1cm4gaTsgfSByZXR1cm4gLTE7IH07XG5cbiAgZW1pdCA9IGZ1bmN0aW9uKGRpdiwgaXRlbSkge1xuICAgIHZhciBzaG93TWVudSwgc2hvd1Byb21wdDtcbiAgICBkaXYuYXBwZW5kKCc8cD5Eb3VibGUtQ2xpY2sgdG8gRWRpdDxicj5Ecm9wIFRleHQgb3IgSW1hZ2UgdG8gSW5zZXJ0PC9wPicpO1xuICAgIHNob3dNZW51ID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgaW5mbywgbWVudSwgbWVudUl0ZW0sIG5hbWUsIF9pLCBfbGVuLCBfcmVmLCBfcmVmMTtcbiAgICAgIG1lbnUgPSBkaXYuZmluZCgncCcpLmFwcGVuZChcIjxicj5PciBDaG9vc2UgYSBQbHVnaW5cIik7XG4gICAgICBtZW51SXRlbSA9IGZ1bmN0aW9uKHRpdGxlLCBuYW1lKSB7XG4gICAgICAgIHJldHVybiBtZW51LmFwcGVuZChcIjxsaT48YSBjbGFzcz1cXFwibWVudVxcXCIgaHJlZj1cXFwiI1xcXCIgdGl0bGU9XFxcIlwiICsgdGl0bGUgKyBcIlxcXCI+XCIgKyBuYW1lICsgXCI8L2E+PC9saT5cIik7XG4gICAgICB9O1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkod2luZG93LmNhdGFsb2cpKSB7XG4gICAgICAgIF9yZWYgPSB3aW5kb3cuY2F0YWxvZztcbiAgICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgICAgaW5mbyA9IF9yZWZbX2ldO1xuICAgICAgICAgIG1lbnVJdGVtKGluZm8udGl0bGUsIGluZm8ubmFtZSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIF9yZWYxID0gd2luZG93LmNhdGFsb2c7XG4gICAgICAgIGZvciAobmFtZSBpbiBfcmVmMSkge1xuICAgICAgICAgIGluZm8gPSBfcmVmMVtuYW1lXTtcbiAgICAgICAgICBtZW51SXRlbShpbmZvLm1lbnUsIG5hbWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gbWVudS5maW5kKCdhLm1lbnUnKS5jbGljayhmdW5jdGlvbihldnQpIHtcbiAgICAgICAgZGl2LnJlbW92ZUNsYXNzKCdmYWN0b3J5JykuYWRkQ2xhc3MoaXRlbS50eXBlID0gZXZ0LnRhcmdldC50ZXh0LnRvTG93ZXJDYXNlKCkpO1xuICAgICAgICBkaXYudW5iaW5kKCk7XG4gICAgICAgIHJldHVybiB3aWtpLnRleHRFZGl0b3IoZGl2LCBpdGVtKTtcbiAgICAgIH0pO1xuICAgIH07XG4gICAgc2hvd1Byb21wdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGRpdi5hcHBlbmQoXCI8cD5cIiArICh3aWtpLnJlc29sdmVMaW5rcyhpdGVtLnByb21wdCkpICsgXCI8L2I+XCIpO1xuICAgIH07XG4gICAgaWYgKGl0ZW0ucHJvbXB0KSB7XG4gICAgICByZXR1cm4gc2hvd1Byb21wdCgpO1xuICAgIH0gZWxzZSBpZiAod2luZG93LmNhdGFsb2cgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHNob3dNZW51KCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAkLmdldEpTT04oJy9zeXN0ZW0vZmFjdG9yaWVzLmpzb24nLCBmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgIHdpbmRvdy5jYXRhbG9nID0gZGF0YTtcbiAgICAgICAgcmV0dXJuIHNob3dNZW51KCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH07XG5cbiAgYmluZCA9IGZ1bmN0aW9uKGRpdiwgaXRlbSkge1xuICAgIHZhciBzeW5jRWRpdEFjdGlvbjtcbiAgICBzeW5jRWRpdEFjdGlvbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGVyciwgcGFnZUVsZW1lbnQ7XG4gICAgICB3aWtpLmxvZygnZmFjdG9yeSBpdGVtJywgaXRlbSk7XG4gICAgICBkaXYuZW1wdHkoKS51bmJpbmQoKTtcbiAgICAgIGRpdi5yZW1vdmVDbGFzcyhcImZhY3RvcnlcIikuYWRkQ2xhc3MoaXRlbS50eXBlKTtcbiAgICAgIHBhZ2VFbGVtZW50ID0gZGl2LnBhcmVudHMoJy5wYWdlOmZpcnN0Jyk7XG4gICAgICB0cnkge1xuICAgICAgICBkaXYuZGF0YSgncGFnZUVsZW1lbnQnLCBwYWdlRWxlbWVudCk7XG4gICAgICAgIGRpdi5kYXRhKCdpdGVtJywgaXRlbSk7XG4gICAgICAgIHdpa2kuZ2V0UGx1Z2luKGl0ZW0udHlwZSwgZnVuY3Rpb24ocGx1Z2luKSB7XG4gICAgICAgICAgcGx1Z2luLmVtaXQoZGl2LCBpdGVtKTtcbiAgICAgICAgICByZXR1cm4gcGx1Z2luLmJpbmQoZGl2LCBpdGVtKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChfZXJyb3IpIHtcbiAgICAgICAgZXJyID0gX2Vycm9yO1xuICAgICAgICBkaXYuYXBwZW5kKFwiPHAgY2xhc3M9J2Vycm9yJz5cIiArIGVyciArIFwiPC9wPlwiKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB3aWtpLnBhZ2VIYW5kbGVyLnB1dChwYWdlRWxlbWVudCwge1xuICAgICAgICB0eXBlOiAnZWRpdCcsXG4gICAgICAgIGlkOiBpdGVtLmlkLFxuICAgICAgICBpdGVtOiBpdGVtXG4gICAgICB9KTtcbiAgICB9O1xuICAgIGRpdi5kYmxjbGljayhmdW5jdGlvbigpIHtcbiAgICAgIGRpdi5yZW1vdmVDbGFzcygnZmFjdG9yeScpLmFkZENsYXNzKGl0ZW0udHlwZSA9ICdwYXJhZ3JhcGgnKTtcbiAgICAgIGRpdi51bmJpbmQoKTtcbiAgICAgIHJldHVybiB3aWtpLnRleHRFZGl0b3IoZGl2LCBpdGVtKTtcbiAgICB9KTtcbiAgICBkaXYuYmluZCgnZHJhZ2VudGVyJywgZnVuY3Rpb24oZXZ0KSB7XG4gICAgICByZXR1cm4gZXZ0LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSk7XG4gICAgZGl2LmJpbmQoJ2RyYWdvdmVyJywgZnVuY3Rpb24oZXZ0KSB7XG4gICAgICByZXR1cm4gZXZ0LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGRpdi5iaW5kKFwiZHJvcFwiLCBmdW5jdGlvbihkcm9wRXZlbnQpIHtcbiAgICAgIHZhciBkdCwgZm91bmQsIGlnbm9yZSwgb3JpZ2luLCBwdW50LCByZWFkRmlsZSwgdXJsO1xuICAgICAgcHVudCA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgaXRlbS5wcm9tcHQgPSBcIjxiPlVuZXhwZWN0ZWQgSXRlbTwvYj48YnI+V2UgY2FuJ3QgbWFrZSBzZW5zZSBvZiB0aGUgZHJvcC48YnI+XCIgKyAoSlNPTi5zdHJpbmdpZnkoZGF0YSkpICsgXCI8YnI+VHJ5IHNvbWV0aGluZyBlbHNlIG9yIHNlZSBbW0Fib3V0IEZhY3RvcnkgUGx1Z2luXV0uXCI7XG4gICAgICAgIGRhdGEudXNlckFnZW50ID0gbmF2aWdhdG9yLnVzZXJBZ2VudDtcbiAgICAgICAgaXRlbS5wdW50ID0gZGF0YTtcbiAgICAgICAgd2lraS5sb2coJ2ZhY3RvcnkgcHVudCcsIGRyb3BFdmVudCk7XG4gICAgICAgIHJldHVybiBzeW5jRWRpdEFjdGlvbigpO1xuICAgICAgfTtcbiAgICAgIHJlYWRGaWxlID0gZnVuY3Rpb24oZmlsZSkge1xuICAgICAgICB2YXIgbWFqb3JUeXBlLCBtaW5vclR5cGUsIHJlYWRlciwgX3JlZjtcbiAgICAgICAgaWYgKGZpbGUgIT0gbnVsbCkge1xuICAgICAgICAgIF9yZWYgPSBmaWxlLnR5cGUuc3BsaXQoXCIvXCIpLCBtYWpvclR5cGUgPSBfcmVmWzBdLCBtaW5vclR5cGUgPSBfcmVmWzFdO1xuICAgICAgICAgIHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XG4gICAgICAgICAgaWYgKG1ham9yVHlwZSA9PT0gXCJpbWFnZVwiKSB7XG4gICAgICAgICAgICByZWFkZXIub25sb2FkID0gZnVuY3Rpb24obG9hZEV2ZW50KSB7XG4gICAgICAgICAgICAgIGl0ZW0udHlwZSA9ICdpbWFnZSc7XG4gICAgICAgICAgICAgIGl0ZW0udXJsID0gbG9hZEV2ZW50LnRhcmdldC5yZXN1bHQ7XG4gICAgICAgICAgICAgIGl0ZW0uY2FwdGlvbiB8fCAoaXRlbS5jYXB0aW9uID0gXCJVcGxvYWRlZCBpbWFnZVwiKTtcbiAgICAgICAgICAgICAgcmV0dXJuIHN5bmNFZGl0QWN0aW9uKCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIHJlYWRlci5yZWFkQXNEYXRhVVJMKGZpbGUpO1xuICAgICAgICAgIH0gZWxzZSBpZiAobWFqb3JUeXBlID09PSBcInRleHRcIikge1xuICAgICAgICAgICAgcmVhZGVyLm9ubG9hZCA9IGZ1bmN0aW9uKGxvYWRFdmVudCkge1xuICAgICAgICAgICAgICB2YXIgYXJyYXksIHJlc3VsdDtcbiAgICAgICAgICAgICAgcmVzdWx0ID0gbG9hZEV2ZW50LnRhcmdldC5yZXN1bHQ7XG4gICAgICAgICAgICAgIGlmIChtaW5vclR5cGUgPT09ICdjc3YnKSB7XG4gICAgICAgICAgICAgICAgaXRlbS50eXBlID0gJ2RhdGEnO1xuICAgICAgICAgICAgICAgIGl0ZW0uY29sdW1ucyA9IChhcnJheSA9IGNzdlRvQXJyYXkocmVzdWx0KSlbMF07XG4gICAgICAgICAgICAgICAgaXRlbS5kYXRhID0gYXJyYXlUb0pzb24oYXJyYXkpO1xuICAgICAgICAgICAgICAgIGl0ZW0udGV4dCA9IGZpbGUuZmlsZU5hbWU7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaXRlbS50eXBlID0gJ3BhcmFncmFwaCc7XG4gICAgICAgICAgICAgICAgaXRlbS50ZXh0ID0gcmVzdWx0O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiBzeW5jRWRpdEFjdGlvbigpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJldHVybiByZWFkZXIucmVhZEFzVGV4dChmaWxlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHB1bnQoe1xuICAgICAgICAgICAgICBudW1iZXI6IDEsXG4gICAgICAgICAgICAgIG5hbWU6IGZpbGUuZmlsZU5hbWUsXG4gICAgICAgICAgICAgIHR5cGU6IGZpbGUudHlwZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBwdW50KHtcbiAgICAgICAgICAgIG51bWJlcjogMixcbiAgICAgICAgICAgIHR5cGVzOiBkcm9wRXZlbnQub3JpZ2luYWxFdmVudC5kYXRhVHJhbnNmZXIudHlwZXNcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGRyb3BFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgaWYgKChkdCA9IGRyb3BFdmVudC5vcmlnaW5hbEV2ZW50LmRhdGFUcmFuc2ZlcikgIT0gbnVsbCkge1xuICAgICAgICBpZiAoKGR0LnR5cGVzICE9IG51bGwpICYmIChfX2luZGV4T2YuY2FsbChkdC50eXBlcywgJ3RleHQvdXJpLWxpc3QnKSA+PSAwIHx8IF9faW5kZXhPZi5jYWxsKGR0LnR5cGVzLCAndGV4dC94LW1vei11cmwnKSA+PSAwKSAmJiAhKF9faW5kZXhPZi5jYWxsKGR0LnR5cGVzLCAnRmlsZXMnKSA+PSAwKSkge1xuICAgICAgICAgIHVybCA9IGR0LmdldERhdGEoJ1VSTCcpO1xuICAgICAgICAgIGlmIChmb3VuZCA9IHVybC5tYXRjaCgvXmh0dHA6XFwvXFwvKFthLXpBLVowLTk6Li1dKykoXFwvKFthLXpBLVowLTk6Li1dKylcXC8oW2EtejAtOS1dKyhfcmV2XFxkKyk/KSkrJC8pKSB7XG4gICAgICAgICAgICB3aWtpLmxvZygnZmFjdG9yeSBkcm9wIHVybCcsIGZvdW5kKTtcbiAgICAgICAgICAgIGlnbm9yZSA9IGZvdW5kWzBdLCBvcmlnaW4gPSBmb3VuZFsxXSwgaWdub3JlID0gZm91bmRbMl0sIGl0ZW0uc2l0ZSA9IGZvdW5kWzNdLCBpdGVtLnNsdWcgPSBmb3VuZFs0XSwgaWdub3JlID0gZm91bmRbNV07XG4gICAgICAgICAgICBpZiAoJC5pbkFycmF5KGl0ZW0uc2l0ZSwgWyd2aWV3JywgJ2xvY2FsJywgJ29yaWdpbiddKSA+PSAwKSB7XG4gICAgICAgICAgICAgIGl0ZW0uc2l0ZSA9IG9yaWdpbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAkLmdldEpTT04oXCJodHRwOi8vXCIgKyBpdGVtLnNpdGUgKyBcIi9cIiArIGl0ZW0uc2x1ZyArIFwiLmpzb25cIiwgZnVuY3Rpb24ocmVtb3RlKSB7XG4gICAgICAgICAgICAgIHdpa2kubG9nKCdmYWN0b3J5IHJlbW90ZScsIHJlbW90ZSk7XG4gICAgICAgICAgICAgIGl0ZW0udHlwZSA9ICdyZWZlcmVuY2UnO1xuICAgICAgICAgICAgICBpdGVtLnRpdGxlID0gcmVtb3RlLnRpdGxlIHx8IGl0ZW0uc2x1ZztcbiAgICAgICAgICAgICAgaXRlbS50ZXh0ID0gd2lraS5jcmVhdGVTeW5vcHNpcyhyZW1vdGUpO1xuICAgICAgICAgICAgICBzeW5jRWRpdEFjdGlvbigpO1xuICAgICAgICAgICAgICBpZiAoaXRlbS5zaXRlICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gd2lraS5yZWdpc3Rlck5laWdoYm9yKGl0ZW0uc2l0ZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gcHVudCh7XG4gICAgICAgICAgICAgIG51bWJlcjogNCxcbiAgICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICAgIHR5cGVzOiBkdC50eXBlc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKF9faW5kZXhPZi5jYWxsKGR0LnR5cGVzLCAnRmlsZXMnKSA+PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIHJlYWRGaWxlKGR0LmZpbGVzWzBdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gcHVudCh7XG4gICAgICAgICAgICBudW1iZXI6IDUsXG4gICAgICAgICAgICB0eXBlczogZHQudHlwZXNcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHB1bnQoe1xuICAgICAgICAgIG51bWJlcjogNixcbiAgICAgICAgICB0cm91YmxlOiBcIm5vIGRhdGEgdHJhbnNmZXIgb2JqZWN0XCJcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgY3N2VG9BcnJheSA9IGZ1bmN0aW9uKHN0ckRhdGEsIHN0ckRlbGltaXRlcikge1xuICAgIHZhciBhcnJEYXRhLCBhcnJNYXRjaGVzLCBvYmpQYXR0ZXJuLCBzdHJNYXRjaGVkRGVsaW1pdGVyLCBzdHJNYXRjaGVkVmFsdWU7XG4gICAgc3RyRGVsaW1pdGVyID0gc3RyRGVsaW1pdGVyIHx8IFwiLFwiO1xuICAgIG9ialBhdHRlcm4gPSBuZXcgUmVnRXhwKFwiKFxcXFxcIiArIHN0ckRlbGltaXRlciArIFwifFxcXFxyP1xcXFxufFxcXFxyfF4pXCIgKyBcIig/OlxcXCIoW15cXFwiXSooPzpcXFwiXFxcIlteXFxcIl0qKSopXFxcInxcIiArIFwiKFteXFxcIlxcXFxcIiArIHN0ckRlbGltaXRlciArIFwiXFxcXHJcXFxcbl0qKSlcIiwgXCJnaVwiKTtcbiAgICBhcnJEYXRhID0gW1tdXTtcbiAgICBhcnJNYXRjaGVzID0gbnVsbDtcbiAgICB3aGlsZSAoYXJyTWF0Y2hlcyA9IG9ialBhdHRlcm4uZXhlYyhzdHJEYXRhKSkge1xuICAgICAgc3RyTWF0Y2hlZERlbGltaXRlciA9IGFyck1hdGNoZXNbMV07XG4gICAgICBpZiAoc3RyTWF0Y2hlZERlbGltaXRlci5sZW5ndGggJiYgKHN0ck1hdGNoZWREZWxpbWl0ZXIgIT09IHN0ckRlbGltaXRlcikpIHtcbiAgICAgICAgYXJyRGF0YS5wdXNoKFtdKTtcbiAgICAgIH1cbiAgICAgIGlmIChhcnJNYXRjaGVzWzJdKSB7XG4gICAgICAgIHN0ck1hdGNoZWRWYWx1ZSA9IGFyck1hdGNoZXNbMl0ucmVwbGFjZShuZXcgUmVnRXhwKFwiXFxcIlxcXCJcIiwgXCJnXCIpLCBcIlxcXCJcIik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdHJNYXRjaGVkVmFsdWUgPSBhcnJNYXRjaGVzWzNdO1xuICAgICAgfVxuICAgICAgYXJyRGF0YVthcnJEYXRhLmxlbmd0aCAtIDFdLnB1c2goc3RyTWF0Y2hlZFZhbHVlKTtcbiAgICB9XG4gICAgcmV0dXJuIGFyckRhdGE7XG4gIH07XG5cbiAgYXJyYXlUb0pzb24gPSBmdW5jdGlvbihhcnJheSkge1xuICAgIHZhciBjb2xzLCByb3csIHJvd1RvT2JqZWN0LCBfaSwgX2xlbiwgX3Jlc3VsdHM7XG4gICAgY29scyA9IGFycmF5LnNoaWZ0KCk7XG4gICAgcm93VG9PYmplY3QgPSBmdW5jdGlvbihyb3cpIHtcbiAgICAgIHZhciBrLCBvYmosIHYsIF9pLCBfbGVuLCBfcmVmLCBfcmVmMTtcbiAgICAgIG9iaiA9IHt9O1xuICAgICAgX3JlZiA9IF8uemlwKGNvbHMsIHJvdyk7XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgX3JlZjEgPSBfcmVmW19pXSwgayA9IF9yZWYxWzBdLCB2ID0gX3JlZjFbMV07XG4gICAgICAgIGlmICgodiAhPSBudWxsKSAmJiAodi5tYXRjaCgvXFxTLykpICYmIHYgIT09ICdOVUxMJykge1xuICAgICAgICAgIG9ialtrXSA9IHY7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBvYmo7XG4gICAgfTtcbiAgICBfcmVzdWx0cyA9IFtdO1xuICAgIGZvciAoX2kgPSAwLCBfbGVuID0gYXJyYXkubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgIHJvdyA9IGFycmF5W19pXTtcbiAgICAgIF9yZXN1bHRzLnB1c2gocm93VG9PYmplY3Qocm93KSk7XG4gICAgfVxuICAgIHJldHVybiBfcmVzdWx0cztcbiAgfTtcblxuICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBlbWl0OiBlbWl0LFxuICAgIGJpbmQ6IGJpbmRcbiAgfTtcblxufSkuY2FsbCh0aGlzKTtcbiIsIihmdW5jdGlvbigpIHtcbiAgdmFyIHV0aWw7XG5cbiAgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xuXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oam91cm5hbEVsZW1lbnQsIGFjdGlvbikge1xuICAgIHZhciBhY3Rpb25FbGVtZW50LCBhY3Rpb25UaXRsZSwgY29udHJvbHMsIHBhZ2VFbGVtZW50O1xuICAgIHBhZ2VFbGVtZW50ID0gam91cm5hbEVsZW1lbnQucGFyZW50cygnLnBhZ2U6Zmlyc3QnKTtcbiAgICBhY3Rpb25UaXRsZSA9IGFjdGlvbi50eXBlIHx8ICdzZXBhcmF0b3InO1xuICAgIGlmIChhY3Rpb24uZGF0ZSAhPSBudWxsKSB7XG4gICAgICBhY3Rpb25UaXRsZSArPSBcIiBcIiArICh1dGlsLmZvcm1hdEVsYXBzZWRUaW1lKGFjdGlvbi5kYXRlKSk7XG4gICAgfVxuICAgIGFjdGlvbkVsZW1lbnQgPSAkKFwiPGEgaHJlZj1cXFwiI1xcXCIgLz4gXCIpLmFkZENsYXNzKFwiYWN0aW9uXCIpLmFkZENsYXNzKGFjdGlvbi50eXBlIHx8ICdzZXBhcmF0b3InKS50ZXh0KGFjdGlvbi5zeW1ib2wgfHwgdXRpbC5zeW1ib2xzW2FjdGlvbi50eXBlXSkuYXR0cigndGl0bGUnLCBhY3Rpb25UaXRsZSkuYXR0cignZGF0YS1pZCcsIGFjdGlvbi5pZCB8fCBcIjBcIikuZGF0YSgnYWN0aW9uJywgYWN0aW9uKTtcbiAgICBjb250cm9scyA9IGpvdXJuYWxFbGVtZW50LmNoaWxkcmVuKCcuY29udHJvbC1idXR0b25zJyk7XG4gICAgaWYgKGNvbnRyb2xzLmxlbmd0aCA+IDApIHtcbiAgICAgIGFjdGlvbkVsZW1lbnQuaW5zZXJ0QmVmb3JlKGNvbnRyb2xzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYWN0aW9uRWxlbWVudC5hcHBlbmRUbyhqb3VybmFsRWxlbWVudCk7XG4gICAgfVxuICAgIGlmIChhY3Rpb24udHlwZSA9PT0gJ2ZvcmsnICYmIChhY3Rpb24uc2l0ZSAhPSBudWxsKSkge1xuICAgICAgcmV0dXJuIGFjdGlvbkVsZW1lbnQuY3NzKFwiYmFja2dyb3VuZC1pbWFnZVwiLCBcInVybCgvL1wiICsgYWN0aW9uLnNpdGUgKyBcIi9mYXZpY29uLnBuZylcIikuYXR0cihcImhyZWZcIiwgXCIvL1wiICsgYWN0aW9uLnNpdGUgKyBcIi9cIiArIChwYWdlRWxlbWVudC5hdHRyKCdpZCcpKSArIFwiLmh0bWxcIikuZGF0YShcInNpdGVcIiwgYWN0aW9uLnNpdGUpLmRhdGEoXCJzbHVnXCIsIHBhZ2VFbGVtZW50LmF0dHIoJ2lkJykpO1xuICAgIH1cbiAgfTtcblxufSkuY2FsbCh0aGlzKTtcbiIsIihmdW5jdGlvbigpIHtcbiAgdmFyIGFkZFRvSm91cm5hbCwgbmV3UGFnZSwgcGFnZUZyb21Mb2NhbFN0b3JhZ2UsIHBhZ2VIYW5kbGVyLCBwdXNoVG9Mb2NhbCwgcHVzaFRvU2VydmVyLCByZWN1cnNpdmVHZXQsIHJldmlzaW9uLCBzdGF0ZSwgdXRpbCwgd2lraSwgXztcblxuICBfID0gcmVxdWlyZSgndW5kZXJzY29yZScpO1xuXG4gIHdpa2kgPSByZXF1aXJlKCcuL3dpa2knKTtcblxuICB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG5cbiAgc3RhdGUgPSByZXF1aXJlKCcuL3N0YXRlJyk7XG5cbiAgcmV2aXNpb24gPSByZXF1aXJlKCcuL3JldmlzaW9uJyk7XG5cbiAgYWRkVG9Kb3VybmFsID0gcmVxdWlyZSgnLi9hZGRUb0pvdXJuYWwnKTtcblxuICBuZXdQYWdlID0gcmVxdWlyZSgnLi9wYWdlJykubmV3UGFnZTtcblxuICBtb2R1bGUuZXhwb3J0cyA9IHBhZ2VIYW5kbGVyID0ge307XG5cbiAgcGFnZUZyb21Mb2NhbFN0b3JhZ2UgPSBmdW5jdGlvbihzbHVnKSB7XG4gICAgdmFyIGpzb247XG4gICAgaWYgKGpzb24gPSBsb2NhbFN0b3JhZ2Vbc2x1Z10pIHtcbiAgICAgIHJldHVybiBKU09OLnBhcnNlKGpzb24pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdm9pZCAwO1xuICAgIH1cbiAgfTtcblxuICByZWN1cnNpdmVHZXQgPSBmdW5jdGlvbihfYXJnKSB7XG4gICAgdmFyIGxvY2FsQ29udGV4dCwgbG9jYWxQYWdlLCBwYWdlSW5mb3JtYXRpb24sIHJldiwgc2l0ZSwgc2x1ZywgdXJsLCB3aGVuR290dGVuLCB3aGVuTm90R290dGVuO1xuICAgIHBhZ2VJbmZvcm1hdGlvbiA9IF9hcmcucGFnZUluZm9ybWF0aW9uLCB3aGVuR290dGVuID0gX2FyZy53aGVuR290dGVuLCB3aGVuTm90R290dGVuID0gX2FyZy53aGVuTm90R290dGVuLCBsb2NhbENvbnRleHQgPSBfYXJnLmxvY2FsQ29udGV4dDtcbiAgICBzbHVnID0gcGFnZUluZm9ybWF0aW9uLnNsdWcsIHJldiA9IHBhZ2VJbmZvcm1hdGlvbi5yZXYsIHNpdGUgPSBwYWdlSW5mb3JtYXRpb24uc2l0ZTtcbiAgICBpZiAoc2l0ZSkge1xuICAgICAgbG9jYWxDb250ZXh0ID0gW107XG4gICAgfSBlbHNlIHtcbiAgICAgIHNpdGUgPSBsb2NhbENvbnRleHQuc2hpZnQoKTtcbiAgICB9XG4gICAgaWYgKHNpdGUgPT09IHdpbmRvdy5sb2NhdGlvbi5ob3N0KSB7XG4gICAgICBzaXRlID0gJ29yaWdpbic7XG4gICAgfVxuICAgIGlmIChzaXRlID09PSAndmlldycpIHtcbiAgICAgIHNpdGUgPSBudWxsO1xuICAgIH1cbiAgICBpZiAoc2l0ZSAhPSBudWxsKSB7XG4gICAgICBpZiAoc2l0ZSA9PT0gJ2xvY2FsJykge1xuICAgICAgICBpZiAobG9jYWxQYWdlID0gcGFnZUZyb21Mb2NhbFN0b3JhZ2UocGFnZUluZm9ybWF0aW9uLnNsdWcpKSB7XG4gICAgICAgICAgcmV0dXJuIHdoZW5Hb3R0ZW4obmV3UGFnZShsb2NhbFBhZ2UsICdsb2NhbCcpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gd2hlbk5vdEdvdHRlbigpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoc2l0ZSA9PT0gJ29yaWdpbicpIHtcbiAgICAgICAgICB1cmwgPSBcIi9cIiArIHNsdWcgKyBcIi5qc29uXCI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdXJsID0gXCJodHRwOi8vXCIgKyBzaXRlICsgXCIvXCIgKyBzbHVnICsgXCIuanNvblwiO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHVybCA9IFwiL1wiICsgc2x1ZyArIFwiLmpzb25cIjtcbiAgICB9XG4gICAgcmV0dXJuICQuYWpheCh7XG4gICAgICB0eXBlOiAnR0VUJyxcbiAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICB1cmw6IHVybCArIChcIj9yYW5kb209XCIgKyAodXRpbC5yYW5kb21CeXRlcyg0KSkpLFxuICAgICAgc3VjY2VzczogZnVuY3Rpb24ocGFnZSkge1xuICAgICAgICBpZiAocmV2KSB7XG4gICAgICAgICAgcGFnZSA9IHJldmlzaW9uLmNyZWF0ZShyZXYsIHBhZ2UpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB3aGVuR290dGVuKG5ld1BhZ2UocGFnZSwgc2l0ZSkpO1xuICAgICAgfSxcbiAgICAgIGVycm9yOiBmdW5jdGlvbih4aHIsIHR5cGUsIG1zZykge1xuICAgICAgICB2YXIgcmVwb3J0O1xuICAgICAgICBpZiAoKHhoci5zdGF0dXMgIT09IDQwNCkgJiYgKHhoci5zdGF0dXMgIT09IDApKSB7XG4gICAgICAgICAgd2lraS5sb2coJ3BhZ2VIYW5kbGVyLmdldCBlcnJvcicsIHhociwgeGhyLnN0YXR1cywgdHlwZSwgbXNnKTtcbiAgICAgICAgICByZXBvcnQgPSB7XG4gICAgICAgICAgICAndGl0bGUnOiBcIlwiICsgeGhyLnN0YXR1cyArIFwiIFwiICsgbXNnLFxuICAgICAgICAgICAgJ3N0b3J5JzogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgJ3R5cGUnOiAncGFyYWdyYXBoJyxcbiAgICAgICAgICAgICAgICAnaWQnOiAnOTI4NzM5MTg3MjQzJyxcbiAgICAgICAgICAgICAgICAndGV4dCc6IFwiPHByZT5cIiArIHhoci5yZXNwb25zZVRleHRcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXVxuICAgICAgICAgIH07XG4gICAgICAgICAgcmV0dXJuIHdoZW5Hb3R0ZW4ocmVwb3J0LCAnbG9jYWwnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobG9jYWxDb250ZXh0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICByZXR1cm4gcmVjdXJzaXZlR2V0KHtcbiAgICAgICAgICAgIHBhZ2VJbmZvcm1hdGlvbjogcGFnZUluZm9ybWF0aW9uLFxuICAgICAgICAgICAgd2hlbkdvdHRlbjogd2hlbkdvdHRlbixcbiAgICAgICAgICAgIHdoZW5Ob3RHb3R0ZW46IHdoZW5Ob3RHb3R0ZW4sXG4gICAgICAgICAgICBsb2NhbENvbnRleHQ6IGxvY2FsQ29udGV4dFxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiB3aGVuTm90R290dGVuKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcblxuICBwYWdlSGFuZGxlci5nZXQgPSBmdW5jdGlvbihfYXJnKSB7XG4gICAgdmFyIGxvY2FsUGFnZSwgcGFnZUluZm9ybWF0aW9uLCB3aGVuR290dGVuLCB3aGVuTm90R290dGVuO1xuICAgIHdoZW5Hb3R0ZW4gPSBfYXJnLndoZW5Hb3R0ZW4sIHdoZW5Ob3RHb3R0ZW4gPSBfYXJnLndoZW5Ob3RHb3R0ZW4sIHBhZ2VJbmZvcm1hdGlvbiA9IF9hcmcucGFnZUluZm9ybWF0aW9uO1xuICAgIGlmICghcGFnZUluZm9ybWF0aW9uLnNpdGUpIHtcbiAgICAgIGlmIChsb2NhbFBhZ2UgPSBwYWdlRnJvbUxvY2FsU3RvcmFnZShwYWdlSW5mb3JtYXRpb24uc2x1ZykpIHtcbiAgICAgICAgaWYgKHBhZ2VJbmZvcm1hdGlvbi5yZXYpIHtcbiAgICAgICAgICBsb2NhbFBhZ2UgPSByZXZpc2lvbi5jcmVhdGUocGFnZUluZm9ybWF0aW9uLnJldiwgbG9jYWxQYWdlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gd2hlbkdvdHRlbihuZXdQYWdlKGxvY2FsUGFnZSwgJ2xvY2FsJykpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIXBhZ2VIYW5kbGVyLmNvbnRleHQubGVuZ3RoKSB7XG4gICAgICBwYWdlSGFuZGxlci5jb250ZXh0ID0gWyd2aWV3J107XG4gICAgfVxuICAgIHJldHVybiByZWN1cnNpdmVHZXQoe1xuICAgICAgcGFnZUluZm9ybWF0aW9uOiBwYWdlSW5mb3JtYXRpb24sXG4gICAgICB3aGVuR290dGVuOiB3aGVuR290dGVuLFxuICAgICAgd2hlbk5vdEdvdHRlbjogd2hlbk5vdEdvdHRlbixcbiAgICAgIGxvY2FsQ29udGV4dDogXy5jbG9uZShwYWdlSGFuZGxlci5jb250ZXh0KVxuICAgIH0pO1xuICB9O1xuXG4gIHBhZ2VIYW5kbGVyLmNvbnRleHQgPSBbXTtcblxuICBwdXNoVG9Mb2NhbCA9IGZ1bmN0aW9uKHBhZ2VFbGVtZW50LCBwYWdlUHV0SW5mbywgYWN0aW9uKSB7XG4gICAgdmFyIHBhZ2UsIHNpdGU7XG4gICAgaWYgKGFjdGlvbi50eXBlID09PSAnY3JlYXRlJykge1xuICAgICAgcGFnZSA9IHtcbiAgICAgICAgdGl0bGU6IGFjdGlvbi5pdGVtLnRpdGxlLFxuICAgICAgICBzdG9yeTogW10sXG4gICAgICAgIGpvdXJuYWw6IFtdXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBwYWdlID0gcGFnZUZyb21Mb2NhbFN0b3JhZ2UocGFnZVB1dEluZm8uc2x1Zyk7XG4gICAgICBwYWdlIHx8IChwYWdlID0gcGFnZUVsZW1lbnQuZGF0YShcImRhdGFcIikpO1xuICAgICAgaWYgKHBhZ2Uuam91cm5hbCA9PSBudWxsKSB7XG4gICAgICAgIHBhZ2Uuam91cm5hbCA9IFtdO1xuICAgICAgfVxuICAgICAgaWYgKChzaXRlID0gYWN0aW9uWydmb3JrJ10pICE9IG51bGwpIHtcbiAgICAgICAgcGFnZS5qb3VybmFsID0gcGFnZS5qb3VybmFsLmNvbmNhdCh7XG4gICAgICAgICAgJ3R5cGUnOiAnZm9yaycsXG4gICAgICAgICAgJ3NpdGUnOiBzaXRlXG4gICAgICAgIH0pO1xuICAgICAgICBkZWxldGUgYWN0aW9uWydmb3JrJ107XG4gICAgICB9XG4gICAgICBwYWdlLnN0b3J5ID0gJChwYWdlRWxlbWVudCkuZmluZChcIi5pdGVtXCIpLm1hcChmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuICQodGhpcykuZGF0YShcIml0ZW1cIik7XG4gICAgICB9KS5nZXQoKTtcbiAgICB9XG4gICAgcGFnZS5qb3VybmFsID0gcGFnZS5qb3VybmFsLmNvbmNhdChhY3Rpb24pO1xuICAgIGxvY2FsU3RvcmFnZVtwYWdlUHV0SW5mby5zbHVnXSA9IEpTT04uc3RyaW5naWZ5KHBhZ2UpO1xuICAgIHJldHVybiBhZGRUb0pvdXJuYWwocGFnZUVsZW1lbnQuZmluZCgnLmpvdXJuYWwnKSwgYWN0aW9uKTtcbiAgfTtcblxuICBwdXNoVG9TZXJ2ZXIgPSBmdW5jdGlvbihwYWdlRWxlbWVudCwgcGFnZVB1dEluZm8sIGFjdGlvbikge1xuICAgIHJldHVybiAkLmFqYXgoe1xuICAgICAgdHlwZTogJ1BVVCcsXG4gICAgICB1cmw6IFwiL3BhZ2UvXCIgKyBwYWdlUHV0SW5mby5zbHVnICsgXCIvYWN0aW9uXCIsXG4gICAgICBkYXRhOiB7XG4gICAgICAgICdhY3Rpb24nOiBKU09OLnN0cmluZ2lmeShhY3Rpb24pXG4gICAgICB9LFxuICAgICAgc3VjY2VzczogZnVuY3Rpb24oKSB7XG4gICAgICAgIGFkZFRvSm91cm5hbChwYWdlRWxlbWVudC5maW5kKCcuam91cm5hbCcpLCBhY3Rpb24pO1xuICAgICAgICBpZiAoYWN0aW9uLnR5cGUgPT09ICdmb3JrJykge1xuICAgICAgICAgIGxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKHBhZ2VFbGVtZW50LmF0dHIoJ2lkJykpO1xuICAgICAgICAgIHJldHVybiBzdGF0ZS5zZXRVcmw7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBlcnJvcjogZnVuY3Rpb24oeGhyLCB0eXBlLCBtc2cpIHtcbiAgICAgICAgcmV0dXJuIHdpa2kubG9nKFwicGFnZUhhbmRsZXIucHV0IGFqYXggZXJyb3IgY2FsbGJhY2tcIiwgdHlwZSwgbXNnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcblxuICBwYWdlSGFuZGxlci5wdXQgPSBmdW5jdGlvbihwYWdlRWxlbWVudCwgYWN0aW9uKSB7XG4gICAgdmFyIGNoZWNrZWRTaXRlLCBmb3JrRnJvbSwgcGFnZVB1dEluZm87XG4gICAgY2hlY2tlZFNpdGUgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBzaXRlO1xuICAgICAgc3dpdGNoIChzaXRlID0gcGFnZUVsZW1lbnQuZGF0YSgnc2l0ZScpKSB7XG4gICAgICAgIGNhc2UgJ29yaWdpbic6XG4gICAgICAgIGNhc2UgJ2xvY2FsJzpcbiAgICAgICAgY2FzZSAndmlldyc6XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIGNhc2UgbG9jYXRpb24uaG9zdDpcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICByZXR1cm4gc2l0ZTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHBhZ2VQdXRJbmZvID0ge1xuICAgICAgc2x1ZzogcGFnZUVsZW1lbnQuYXR0cignaWQnKS5zcGxpdCgnX3JldicpWzBdLFxuICAgICAgcmV2OiBwYWdlRWxlbWVudC5hdHRyKCdpZCcpLnNwbGl0KCdfcmV2JylbMV0sXG4gICAgICBzaXRlOiBjaGVja2VkU2l0ZSgpLFxuICAgICAgbG9jYWw6IHBhZ2VFbGVtZW50Lmhhc0NsYXNzKCdsb2NhbCcpXG4gICAgfTtcbiAgICBmb3JrRnJvbSA9IHBhZ2VQdXRJbmZvLnNpdGU7XG4gICAgd2lraS5sb2coJ3BhZ2VIYW5kbGVyLnB1dCcsIGFjdGlvbiwgcGFnZVB1dEluZm8pO1xuICAgIGlmICh3aWtpLnVzZUxvY2FsU3RvcmFnZSgpKSB7XG4gICAgICBpZiAocGFnZVB1dEluZm8uc2l0ZSAhPSBudWxsKSB7XG4gICAgICAgIHdpa2kubG9nKCdyZW1vdGUgPT4gbG9jYWwnKTtcbiAgICAgIH0gZWxzZSBpZiAoIXBhZ2VQdXRJbmZvLmxvY2FsKSB7XG4gICAgICAgIHdpa2kubG9nKCdvcmlnaW4gPT4gbG9jYWwnKTtcbiAgICAgICAgYWN0aW9uLnNpdGUgPSBmb3JrRnJvbSA9IGxvY2F0aW9uLmhvc3Q7XG4gICAgICB9XG4gICAgfVxuICAgIGFjdGlvbi5kYXRlID0gKG5ldyBEYXRlKCkpLmdldFRpbWUoKTtcbiAgICBpZiAoYWN0aW9uLnNpdGUgPT09ICdvcmlnaW4nKSB7XG4gICAgICBkZWxldGUgYWN0aW9uLnNpdGU7XG4gICAgfVxuICAgIGlmIChmb3JrRnJvbSkge1xuICAgICAgcGFnZUVsZW1lbnQuZmluZCgnaDEgaW1nJykuYXR0cignc3JjJywgJy9mYXZpY29uLnBuZycpO1xuICAgICAgcGFnZUVsZW1lbnQuZmluZCgnaDEgYScpLmF0dHIoJ2hyZWYnLCAnLycpO1xuICAgICAgcGFnZUVsZW1lbnQuZGF0YSgnc2l0ZScsIG51bGwpO1xuICAgICAgcGFnZUVsZW1lbnQucmVtb3ZlQ2xhc3MoJ3JlbW90ZScpO1xuICAgICAgc3RhdGUuc2V0VXJsKCk7XG4gICAgICBpZiAoYWN0aW9uLnR5cGUgIT09ICdmb3JrJykge1xuICAgICAgICBhY3Rpb24uZm9yayA9IGZvcmtGcm9tO1xuICAgICAgICBhZGRUb0pvdXJuYWwocGFnZUVsZW1lbnQuZmluZCgnLmpvdXJuYWwnKSwge1xuICAgICAgICAgIHR5cGU6ICdmb3JrJyxcbiAgICAgICAgICBzaXRlOiBmb3JrRnJvbSxcbiAgICAgICAgICBkYXRlOiBhY3Rpb24uZGF0ZVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHdpa2kudXNlTG9jYWxTdG9yYWdlKCkgfHwgcGFnZVB1dEluZm8uc2l0ZSA9PT0gJ2xvY2FsJykge1xuICAgICAgcHVzaFRvTG9jYWwocGFnZUVsZW1lbnQsIHBhZ2VQdXRJbmZvLCBhY3Rpb24pO1xuICAgICAgcmV0dXJuIHBhZ2VFbGVtZW50LmFkZENsYXNzKFwibG9jYWxcIik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBwdXNoVG9TZXJ2ZXIocGFnZUVsZW1lbnQsIHBhZ2VQdXRJbmZvLCBhY3Rpb24pO1xuICAgIH1cbiAgfTtcblxufSkuY2FsbCh0aGlzKTtcbiIsIihmdW5jdGlvbigpIHtcbiAgdmFyIGFkZFRvSm91cm5hbCwgYnVpbGRQYWdlSGVhZGVyLCBjcmVhdGVGYWN0b3J5LCBlbWl0SGVhZGVyLCBlbWl0VHdpbnMsIGhhbmRsZURyYWdnaW5nLCBpbml0QWRkQnV0dG9uLCBpbml0RHJhZ2dpbmcsIG5laWdoYm9yaG9vZCwgcGFnZUhhbmRsZXIsIHBsdWdpbiwgcmVmcmVzaCwgcmVuZGVyUGFnZUludG9QYWdlRWxlbWVudCwgc3RhdGUsIHV0aWwsIHdpa2ksIF87XG5cbiAgXyA9IHJlcXVpcmUoJ3VuZGVyc2NvcmUnKTtcblxuICB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG5cbiAgcGFnZUhhbmRsZXIgPSByZXF1aXJlKCcuL3BhZ2VIYW5kbGVyJyk7XG5cbiAgcGx1Z2luID0gcmVxdWlyZSgnLi9wbHVnaW4nKTtcblxuICBzdGF0ZSA9IHJlcXVpcmUoJy4vc3RhdGUnKTtcblxuICBuZWlnaGJvcmhvb2QgPSByZXF1aXJlKCcuL25laWdoYm9yaG9vZCcpO1xuXG4gIGFkZFRvSm91cm5hbCA9IHJlcXVpcmUoJy4vYWRkVG9Kb3VybmFsJyk7XG5cbiAgd2lraSA9IHJlcXVpcmUoJy4vd2lraScpO1xuXG4gIGhhbmRsZURyYWdnaW5nID0gZnVuY3Rpb24oZXZ0LCB1aSkge1xuICAgIHZhciBhY3Rpb24sIGJlZm9yZSwgYmVmb3JlRWxlbWVudCwgZGVzdGluYXRpb25QYWdlRWxlbWVudCwgZXF1YWxzLCBpdGVtLCBpdGVtRWxlbWVudCwgbW92ZUZyb21QYWdlLCBtb3ZlVG9QYWdlLCBtb3ZlV2l0aGluUGFnZSwgb3JkZXIsIHNvdXJjZVBhZ2VFbGVtZW50LCBzb3VyY2VTaXRlLCB0aGlzUGFnZUVsZW1lbnQ7XG4gICAgaXRlbUVsZW1lbnQgPSB1aS5pdGVtO1xuICAgIGl0ZW0gPSB3aWtpLmdldEl0ZW0oaXRlbUVsZW1lbnQpO1xuICAgIHRoaXNQYWdlRWxlbWVudCA9ICQodGhpcykucGFyZW50cygnLnBhZ2U6Zmlyc3QnKTtcbiAgICBzb3VyY2VQYWdlRWxlbWVudCA9IGl0ZW1FbGVtZW50LmRhdGEoJ3BhZ2VFbGVtZW50Jyk7XG4gICAgc291cmNlU2l0ZSA9IHNvdXJjZVBhZ2VFbGVtZW50LmRhdGEoJ3NpdGUnKTtcbiAgICBkZXN0aW5hdGlvblBhZ2VFbGVtZW50ID0gaXRlbUVsZW1lbnQucGFyZW50cygnLnBhZ2U6Zmlyc3QnKTtcbiAgICBlcXVhbHMgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgICByZXR1cm4gYSAmJiBiICYmIGEuZ2V0KDApID09PSBiLmdldCgwKTtcbiAgICB9O1xuICAgIG1vdmVXaXRoaW5QYWdlID0gIXNvdXJjZVBhZ2VFbGVtZW50IHx8IGVxdWFscyhzb3VyY2VQYWdlRWxlbWVudCwgZGVzdGluYXRpb25QYWdlRWxlbWVudCk7XG4gICAgbW92ZUZyb21QYWdlID0gIW1vdmVXaXRoaW5QYWdlICYmIGVxdWFscyh0aGlzUGFnZUVsZW1lbnQsIHNvdXJjZVBhZ2VFbGVtZW50KTtcbiAgICBtb3ZlVG9QYWdlID0gIW1vdmVXaXRoaW5QYWdlICYmIGVxdWFscyh0aGlzUGFnZUVsZW1lbnQsIGRlc3RpbmF0aW9uUGFnZUVsZW1lbnQpO1xuICAgIGlmIChtb3ZlRnJvbVBhZ2UpIHtcbiAgICAgIGlmIChzb3VyY2VQYWdlRWxlbWVudC5oYXNDbGFzcygnZ2hvc3QnKSB8fCBzb3VyY2VQYWdlRWxlbWVudC5hdHRyKCdpZCcpID09PSBkZXN0aW5hdGlvblBhZ2VFbGVtZW50LmF0dHIoJ2lkJykpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cbiAgICBhY3Rpb24gPSBtb3ZlV2l0aGluUGFnZSA/IChvcmRlciA9ICQodGhpcykuY2hpbGRyZW4oKS5tYXAoZnVuY3Rpb24oXywgdmFsdWUpIHtcbiAgICAgIHJldHVybiAkKHZhbHVlKS5hdHRyKCdkYXRhLWlkJyk7XG4gICAgfSkuZ2V0KCksIHtcbiAgICAgIHR5cGU6ICdtb3ZlJyxcbiAgICAgIG9yZGVyOiBvcmRlclxuICAgIH0pIDogbW92ZUZyb21QYWdlID8gKHdpa2kubG9nKCdkcmFnIGZyb20nLCBzb3VyY2VQYWdlRWxlbWVudC5maW5kKCdoMScpLnRleHQoKSksIHtcbiAgICAgIHR5cGU6ICdyZW1vdmUnXG4gICAgfSkgOiBtb3ZlVG9QYWdlID8gKGl0ZW1FbGVtZW50LmRhdGEoJ3BhZ2VFbGVtZW50JywgdGhpc1BhZ2VFbGVtZW50KSwgYmVmb3JlRWxlbWVudCA9IGl0ZW1FbGVtZW50LnByZXYoJy5pdGVtJyksIGJlZm9yZSA9IHdpa2kuZ2V0SXRlbShiZWZvcmVFbGVtZW50KSwge1xuICAgICAgdHlwZTogJ2FkZCcsXG4gICAgICBpdGVtOiBpdGVtLFxuICAgICAgYWZ0ZXI6IGJlZm9yZSAhPSBudWxsID8gYmVmb3JlLmlkIDogdm9pZCAwXG4gICAgfSkgOiB2b2lkIDA7XG4gICAgYWN0aW9uLmlkID0gaXRlbS5pZDtcbiAgICByZXR1cm4gcGFnZUhhbmRsZXIucHV0KHRoaXNQYWdlRWxlbWVudCwgYWN0aW9uKTtcbiAgfTtcblxuICBpbml0RHJhZ2dpbmcgPSBmdW5jdGlvbigkcGFnZSkge1xuICAgIHZhciAkc3Rvcnk7XG4gICAgJHN0b3J5ID0gJHBhZ2UuZmluZCgnLnN0b3J5Jyk7XG4gICAgcmV0dXJuICRzdG9yeS5zb3J0YWJsZSh7XG4gICAgICBjb25uZWN0V2l0aDogJy5wYWdlIC5zdG9yeSdcbiAgICB9KS5vbihcInNvcnR1cGRhdGVcIiwgaGFuZGxlRHJhZ2dpbmcpO1xuICB9O1xuXG4gIGluaXRBZGRCdXR0b24gPSBmdW5jdGlvbigkcGFnZSkge1xuICAgIHJldHVybiAkcGFnZS5maW5kKFwiLmFkZC1mYWN0b3J5XCIpLmxpdmUoXCJjbGlja1wiLCBmdW5jdGlvbihldnQpIHtcbiAgICAgIGlmICgkcGFnZS5oYXNDbGFzcygnZ2hvc3QnKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBldnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIHJldHVybiBjcmVhdGVGYWN0b3J5KCRwYWdlKTtcbiAgICB9KTtcbiAgfTtcblxuICBjcmVhdGVGYWN0b3J5ID0gZnVuY3Rpb24oJHBhZ2UpIHtcbiAgICB2YXIgYmVmb3JlLCBiZWZvcmVFbGVtZW50LCBpdGVtLCBpdGVtRWxlbWVudDtcbiAgICBpdGVtID0ge1xuICAgICAgdHlwZTogXCJmYWN0b3J5XCIsXG4gICAgICBpZDogdXRpbC5yYW5kb21CeXRlcyg4KVxuICAgIH07XG4gICAgaXRlbUVsZW1lbnQgPSAkKFwiPGRpdiAvPlwiLCB7XG4gICAgICBcImNsYXNzXCI6IFwiaXRlbSBmYWN0b3J5XCJcbiAgICB9KS5kYXRhKCdpdGVtJywgaXRlbSkuYXR0cignZGF0YS1pZCcsIGl0ZW0uaWQpO1xuICAgIGl0ZW1FbGVtZW50LmRhdGEoJ3BhZ2VFbGVtZW50JywgJHBhZ2UpO1xuICAgICRwYWdlLmZpbmQoXCIuc3RvcnlcIikuYXBwZW5kKGl0ZW1FbGVtZW50KTtcbiAgICBwbHVnaW5bXCJkb1wiXShpdGVtRWxlbWVudCwgaXRlbSk7XG4gICAgYmVmb3JlRWxlbWVudCA9IGl0ZW1FbGVtZW50LnByZXYoJy5pdGVtJyk7XG4gICAgYmVmb3JlID0gd2lraS5nZXRJdGVtKGJlZm9yZUVsZW1lbnQpO1xuICAgIHJldHVybiBwYWdlSGFuZGxlci5wdXQoJHBhZ2UsIHtcbiAgICAgIGl0ZW06IGl0ZW0sXG4gICAgICBpZDogaXRlbS5pZCxcbiAgICAgIHR5cGU6IFwiYWRkXCIsXG4gICAgICBhZnRlcjogYmVmb3JlICE9IG51bGwgPyBiZWZvcmUuaWQgOiB2b2lkIDBcbiAgICB9KTtcbiAgfTtcblxuICBidWlsZFBhZ2VIZWFkZXIgPSBmdW5jdGlvbihfYXJnKSB7XG4gICAgdmFyIGZhdmljb25fc3JjLCBoZWFkZXJfaHJlZiwgcGFnZSwgdG9vbHRpcDtcbiAgICBwYWdlID0gX2FyZy5wYWdlLCB0b29sdGlwID0gX2FyZy50b29sdGlwLCBoZWFkZXJfaHJlZiA9IF9hcmcuaGVhZGVyX2hyZWYsIGZhdmljb25fc3JjID0gX2FyZy5mYXZpY29uX3NyYztcbiAgICBpZiAocGFnZS5wbHVnaW4pIHtcbiAgICAgIHRvb2x0aXAgKz0gXCJcXG5cIiArIHBhZ2UucGx1Z2luICsgXCIgcGx1Z2luXCI7XG4gICAgfVxuICAgIHJldHVybiBcIjxoMSB0aXRsZT1cXFwiXCIgKyB0b29sdGlwICsgXCJcXFwiPjxhIGhyZWY9XFxcIlwiICsgaGVhZGVyX2hyZWYgKyBcIlxcXCI+PGltZyBzcmM9XFxcIlwiICsgZmF2aWNvbl9zcmMgKyBcIlxcXCIgaGVpZ2h0PVxcXCIzMnB4XFxcIiBjbGFzcz1cXFwiZmF2aWNvblxcXCI+PC9hPiBcIiArIHBhZ2UudGl0bGUgKyBcIjwvaDE+XCI7XG4gIH07XG5cbiAgZW1pdEhlYWRlciA9IGZ1bmN0aW9uKCRoZWFkZXIsICRwYWdlLCBwYWdlT2JqZWN0KSB7XG4gICAgdmFyIGRhdGUsIGhlYWRlciwgaXNSZW1vdGVQYWdlLCBwYWdlLCBwYWdlSGVhZGVyLCByZXYsIHZpZXdIZXJlO1xuICAgIHBhZ2UgPSBwYWdlT2JqZWN0LmdldFJhd1BhZ2UoKTtcbiAgICBpc1JlbW90ZVBhZ2UgPSBwYWdlT2JqZWN0LmlzUmVtb3RlKCk7XG4gICAgaGVhZGVyID0gJyc7XG4gICAgdmlld0hlcmUgPSB3aWtpLmFzU2x1ZyhwYWdlLnRpdGxlKSA9PT0gJ3dlbGNvbWUtdmlzaXRvcnMnID8gXCJcIiA6IFwiL3ZpZXcvXCIgKyAocGFnZU9iamVjdC5nZXRTbHVnKCkpO1xuICAgIHBhZ2VIZWFkZXIgPSBpc1JlbW90ZVBhZ2UgPyBidWlsZFBhZ2VIZWFkZXIoe1xuICAgICAgdG9vbHRpcDogcGFnZU9iamVjdC5nZXRSZW1vdGVTaXRlKCksXG4gICAgICBoZWFkZXJfaHJlZjogXCIvL1wiICsgKHBhZ2VPYmplY3QuZ2V0UmVtb3RlU2l0ZSgpKSArIFwiL3ZpZXcvd2VsY29tZS12aXNpdG9yc1wiICsgdmlld0hlcmUsXG4gICAgICBmYXZpY29uX3NyYzogXCJodHRwOi8vXCIgKyAocGFnZU9iamVjdC5nZXRSZW1vdGVTaXRlKCkpICsgXCIvZmF2aWNvbi5wbmdcIixcbiAgICAgIHBhZ2U6IHBhZ2VcbiAgICB9KSA6IGJ1aWxkUGFnZUhlYWRlcih7XG4gICAgICB0b29sdGlwOiBsb2NhdGlvbi5ob3N0LFxuICAgICAgaGVhZGVyX2hyZWY6IFwiL3ZpZXcvd2VsY29tZS12aXNpdG9yc1wiICsgdmlld0hlcmUsXG4gICAgICBmYXZpY29uX3NyYzogXCIvZmF2aWNvbi5wbmdcIixcbiAgICAgIHBhZ2U6IHBhZ2VcbiAgICB9KTtcbiAgICAkaGVhZGVyLmFwcGVuZChwYWdlSGVhZGVyKTtcbiAgICBpZiAoIWlzUmVtb3RlUGFnZSkge1xuICAgICAgJCgnaW1nLmZhdmljb24nLCAkcGFnZSkuZXJyb3IoZnVuY3Rpb24oZSkge1xuICAgICAgICByZXR1cm4gcGx1Z2luLmdldCgnZmF2aWNvbicsIGZ1bmN0aW9uKGZhdmljb24pIHtcbiAgICAgICAgICByZXR1cm4gZmF2aWNvbi5jcmVhdGUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKCRwYWdlLmF0dHIoJ2lkJykubWF0Y2goL19yZXYvKSkge1xuICAgICAgcmV2ID0gcGFnZS5qb3VybmFsLmxlbmd0aCAtIDE7XG4gICAgICBkYXRlID0gcGFnZS5qb3VybmFsW3Jldl0uZGF0ZTtcbiAgICAgICRwYWdlLmFkZENsYXNzKCdnaG9zdCcpLmRhdGEoJ3JldicsIHJldik7XG4gICAgICByZXR1cm4gJGhlYWRlci5hcHBlbmQoJChcIjxoMiBjbGFzcz1cXFwicmV2aXNpb25cXFwiPlxcbiAgPHNwYW4+XFxuICAgIFwiICsgKGRhdGUgIT0gbnVsbCA/IHV0aWwuZm9ybWF0RGF0ZShkYXRlKSA6IFwiUmV2aXNpb24gXCIgKyByZXYpICsgXCJcXG4gIDwvc3Bhbj5cXG48L2gyPlwiKSk7XG4gICAgfVxuICB9O1xuXG4gIGVtaXRUd2lucyA9IHdpa2kuZW1pdFR3aW5zID0gZnVuY3Rpb24oJHBhZ2UpIHtcbiAgICB2YXIgYWN0aW9ucywgYmluLCBiaW5zLCBmbGFncywgaSwgaW5mbywgaXRlbSwgbGVnZW5kLCBwYWdlLCByZW1vdGVTaXRlLCBzaXRlLCBzbHVnLCB0d2lucywgdmlld2luZywgX2ksIF9sZW4sIF9yZWYsIF9yZWYxLCBfcmVmMiwgX3JlZjM7XG4gICAgcGFnZSA9ICRwYWdlLmRhdGEoJ2RhdGEnKTtcbiAgICBzaXRlID0gJHBhZ2UuZGF0YSgnc2l0ZScpIHx8IHdpbmRvdy5sb2NhdGlvbi5ob3N0O1xuICAgIGlmIChzaXRlID09PSAndmlldycgfHwgc2l0ZSA9PT0gJ29yaWdpbicpIHtcbiAgICAgIHNpdGUgPSB3aW5kb3cubG9jYXRpb24uaG9zdDtcbiAgICB9XG4gICAgc2x1ZyA9IHdpa2kuYXNTbHVnKHBhZ2UudGl0bGUpO1xuICAgIGlmICgoKGFjdGlvbnMgPSAoX3JlZiA9IHBhZ2Uuam91cm5hbCkgIT0gbnVsbCA/IF9yZWYubGVuZ3RoIDogdm9pZCAwKSAhPSBudWxsKSAmJiAoKHZpZXdpbmcgPSAoX3JlZjEgPSBwYWdlLmpvdXJuYWxbYWN0aW9ucyAtIDFdKSAhPSBudWxsID8gX3JlZjEuZGF0ZSA6IHZvaWQgMCkgIT0gbnVsbCkpIHtcbiAgICAgIHZpZXdpbmcgPSBNYXRoLmZsb29yKHZpZXdpbmcgLyAxMDAwKSAqIDEwMDA7XG4gICAgICBiaW5zID0ge1xuICAgICAgICBuZXdlcjogW10sXG4gICAgICAgIHNhbWU6IFtdLFxuICAgICAgICBvbGRlcjogW11cbiAgICAgIH07XG4gICAgICBfcmVmMiA9IHdpa2kubmVpZ2hib3Job29kO1xuICAgICAgZm9yIChyZW1vdGVTaXRlIGluIF9yZWYyKSB7XG4gICAgICAgIGluZm8gPSBfcmVmMltyZW1vdGVTaXRlXTtcbiAgICAgICAgaWYgKHJlbW90ZVNpdGUgIT09IHNpdGUgJiYgKGluZm8uc2l0ZW1hcCAhPSBudWxsKSkge1xuICAgICAgICAgIF9yZWYzID0gaW5mby5zaXRlbWFwO1xuICAgICAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjMubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgICAgIGl0ZW0gPSBfcmVmM1tfaV07XG4gICAgICAgICAgICBpZiAoaXRlbS5zbHVnID09PSBzbHVnKSB7XG4gICAgICAgICAgICAgIGJpbiA9IGl0ZW0uZGF0ZSA+IHZpZXdpbmcgPyBiaW5zLm5ld2VyIDogaXRlbS5kYXRlIDwgdmlld2luZyA/IGJpbnMub2xkZXIgOiBiaW5zLnNhbWU7XG4gICAgICAgICAgICAgIGJpbi5wdXNoKHtcbiAgICAgICAgICAgICAgICByZW1vdGVTaXRlOiByZW1vdGVTaXRlLFxuICAgICAgICAgICAgICAgIGl0ZW06IGl0ZW1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0d2lucyA9IFtdO1xuICAgICAgZm9yIChsZWdlbmQgaW4gYmlucykge1xuICAgICAgICBiaW4gPSBiaW5zW2xlZ2VuZF07XG4gICAgICAgIGlmICghYmluLmxlbmd0aCkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGJpbi5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgICByZXR1cm4gYS5pdGVtLmRhdGUgPCBiLml0ZW0uZGF0ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGZsYWdzID0gKGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciBfaiwgX2xlbjEsIF9yZWY0LCBfcmVzdWx0cztcbiAgICAgICAgICBfcmVzdWx0cyA9IFtdO1xuICAgICAgICAgIGZvciAoaSA9IF9qID0gMCwgX2xlbjEgPSBiaW4ubGVuZ3RoOyBfaiA8IF9sZW4xOyBpID0gKytfaikge1xuICAgICAgICAgICAgX3JlZjQgPSBiaW5baV0sIHJlbW90ZVNpdGUgPSBfcmVmNC5yZW1vdGVTaXRlLCBpdGVtID0gX3JlZjQuaXRlbTtcbiAgICAgICAgICAgIGlmIChpID49IDgpIHtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfcmVzdWx0cy5wdXNoKFwiPGltZyBjbGFzcz1cXFwicmVtb3RlXFxcIlxcbnNyYz1cXFwiaHR0cDovL1wiICsgcmVtb3RlU2l0ZSArIFwiL2Zhdmljb24ucG5nXFxcIlxcbmRhdGEtc2x1Zz1cXFwiXCIgKyBzbHVnICsgXCJcXFwiXFxuZGF0YS1zaXRlPVxcXCJcIiArIHJlbW90ZVNpdGUgKyBcIlxcXCJcXG50aXRsZT1cXFwiXCIgKyByZW1vdGVTaXRlICsgXCJcXFwiPlwiKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIF9yZXN1bHRzO1xuICAgICAgICB9KSgpO1xuICAgICAgICB0d2lucy5wdXNoKFwiXCIgKyAoZmxhZ3Muam9pbignJm5ic3A7JykpICsgXCIgXCIgKyBsZWdlbmQpO1xuICAgICAgfVxuICAgICAgaWYgKHR3aW5zKSB7XG4gICAgICAgIHJldHVybiAkcGFnZS5maW5kKCcudHdpbnMnKS5odG1sKFwiPHA+XCIgKyAodHdpbnMuam9pbihcIiwgXCIpKSArIFwiPC9wPlwiKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgcmVuZGVyUGFnZUludG9QYWdlRWxlbWVudCA9IGZ1bmN0aW9uKHBhZ2VPYmplY3QsICRwYWdlKSB7XG4gICAgdmFyICRmb290ZXIsICRoZWFkZXIsICRqb3VybmFsLCAkc3RvcnksICR0d2lucywgaG9zdCwgc2x1ZywgX3JlZjtcbiAgICAkcGFnZS5kYXRhKFwiZGF0YVwiLCBwYWdlT2JqZWN0LmdldFJhd1BhZ2UoKSk7XG4gICAgaWYgKHBhZ2VPYmplY3QuaXNSZW1vdGUoKSkge1xuICAgICAgJHBhZ2UuZGF0YShcInNpdGVcIiwgcGFnZU9iamVjdC5nZXRSZW1vdGVTaXRlKCkpO1xuICAgIH1cbiAgICBzbHVnID0gJHBhZ2UuYXR0cignaWQnKTtcbiAgICB3aWtpLnJlc29sdXRpb25Db250ZXh0ID0gcGFnZU9iamVjdC5nZXRDb250ZXh0KCk7XG4gICAgJHBhZ2UuZW1wdHkoKTtcbiAgICBfcmVmID0gWyd0d2lucycsICdoZWFkZXInLCAnc3RvcnknLCAnam91cm5hbCcsICdmb290ZXInXS5tYXAoZnVuY3Rpb24oY2xhc3NOYW1lKSB7XG4gICAgICByZXR1cm4gJChcIjxkaXYgLz5cIikuYWRkQ2xhc3MoY2xhc3NOYW1lKS5hcHBlbmRUbygkcGFnZSk7XG4gICAgfSksICR0d2lucyA9IF9yZWZbMF0sICRoZWFkZXIgPSBfcmVmWzFdLCAkc3RvcnkgPSBfcmVmWzJdLCAkam91cm5hbCA9IF9yZWZbM10sICRmb290ZXIgPSBfcmVmWzRdO1xuICAgIGVtaXRIZWFkZXIoJGhlYWRlciwgJHBhZ2UsIHBhZ2VPYmplY3QpO1xuICAgIHBhZ2VPYmplY3Quc2VxSXRlbXMoZnVuY3Rpb24oaXRlbSwgZG9uZSkge1xuICAgICAgdmFyICRpdGVtO1xuICAgICAgaWYgKChpdGVtICE9IG51bGwgPyBpdGVtLnR5cGUgOiB2b2lkIDApICYmIChpdGVtICE9IG51bGwgPyBpdGVtLmlkIDogdm9pZCAwKSkge1xuICAgICAgICAkaXRlbSA9ICQoXCI8ZGl2IGNsYXNzPVxcXCJpdGVtIFwiICsgaXRlbS50eXBlICsgXCJcXFwiIGRhdGEtaWQ9XFxcIlwiICsgaXRlbS5pZCArIFwiXFxcIj5cIik7XG4gICAgICAgICRzdG9yeS5hcHBlbmQoJGl0ZW0pO1xuICAgICAgICByZXR1cm4gcGx1Z2luW1wiZG9cIl0oJGl0ZW0sIGl0ZW0sIGRvbmUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgJHN0b3J5LmFwcGVuZCgkKFwiPGRpdj48cCBjbGFzcz1cXFwiZXJyb3JcXFwiPkNhbid0IG1ha2Ugc2Vuc2Ugb2Ygc3RvcnlbXCIgKyBpICsgXCJdPC9wPjwvZGl2PlwiKSk7XG4gICAgICAgIHJldHVybiBkb25lKCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcGFnZU9iamVjdC5zZXFBY3Rpb25zKGZ1bmN0aW9uKGVhY2gsIGRvbmUpIHtcbiAgICAgIGlmIChlYWNoLnNlcGFyYXRvcikge1xuICAgICAgICBhZGRUb0pvdXJuYWwoJGpvdXJuYWwsIGVhY2guc2VwYXJhdG9yKTtcbiAgICAgIH1cbiAgICAgIGFkZFRvSm91cm5hbCgkam91cm5hbCwgZWFjaC5hY3Rpb24pO1xuICAgICAgcmV0dXJuIGRvbmUoKTtcbiAgICB9KTtcbiAgICBlbWl0VHdpbnMoJHBhZ2UpO1xuICAgICRqb3VybmFsLmFwcGVuZChcIjxkaXYgY2xhc3M9XFxcImNvbnRyb2wtYnV0dG9uc1xcXCI+XFxuICA8YSBocmVmPVxcXCIjXFxcIiBjbGFzcz1cXFwiYnV0dG9uIGZvcmstcGFnZVxcXCIgdGl0bGU9XFxcImZvcmsgdGhpcyBwYWdlXFxcIj5cIiArIHV0aWwuc3ltYm9sc1snZm9yayddICsgXCI8L2E+XFxuICA8YSBocmVmPVxcXCIjXFxcIiBjbGFzcz1cXFwiYnV0dG9uIGFkZC1mYWN0b3J5XFxcIiB0aXRsZT1cXFwiYWRkIHBhcmFncmFwaFxcXCI+XCIgKyB1dGlsLnN5bWJvbHNbJ2FkZCddICsgXCI8L2E+XFxuPC9kaXY+XCIpO1xuICAgIGhvc3QgPSBwYWdlT2JqZWN0LmdldFJlbW90ZVNpdGUoKSB8fCBsb2NhdGlvbi5ob3N0O1xuICAgIHJldHVybiAkZm9vdGVyLmFwcGVuZChcIjxhIGlkPVxcXCJsaWNlbnNlXFxcIiBocmVmPVxcXCJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8zLjAvXFxcIj5DQyBCWS1TQSAzLjA8L2E+IC5cXG48YSBjbGFzcz1cXFwic2hvdy1wYWdlLXNvdXJjZVxcXCIgaHJlZj1cXFwiL1wiICsgc2x1ZyArIFwiLmpzb24/cmFuZG9tPVwiICsgKHV0aWwucmFuZG9tQnl0ZXMoNCkpICsgXCJcXFwiIHRpdGxlPVxcXCJzb3VyY2VcXFwiPkpTT048L2E+IC5cXG48YSBocmVmPSBcXFwiLy9cIiArIGhvc3QgKyBcIi9cIiArIHNsdWcgKyBcIi5odG1sXFxcIj5cIiArIGhvc3QgKyBcIjwvYT5cIik7XG4gIH07XG5cbiAgd2lraS5idWlsZFBhZ2UgPSBmdW5jdGlvbihwYWdlT2JqZWN0LCAkcGFnZSkge1xuICAgIGlmIChwYWdlT2JqZWN0LmlzTG9jYWwoKSkge1xuICAgICAgJHBhZ2UuYWRkQ2xhc3MoJ2xvY2FsJyk7XG4gICAgfVxuICAgIGlmIChwYWdlT2JqZWN0LmlzUmVtb3RlKCkpIHtcbiAgICAgICRwYWdlLmFkZENsYXNzKCdyZW1vdGUnKTtcbiAgICB9XG4gICAgaWYgKHBhZ2VPYmplY3QuaXNQbHVnaW4oKSkge1xuICAgICAgJHBhZ2UuYWRkQ2xhc3MoJ3BsdWdpbicpO1xuICAgIH1cbiAgICByZW5kZXJQYWdlSW50b1BhZ2VFbGVtZW50KHBhZ2VPYmplY3QsICRwYWdlKTtcbiAgICBzdGF0ZS5zZXRVcmwoKTtcbiAgICBpbml0RHJhZ2dpbmcoJHBhZ2UpO1xuICAgIGluaXRBZGRCdXR0b24oJHBhZ2UpO1xuICAgIHJldHVybiAkcGFnZTtcbiAgfTtcblxuICBtb2R1bGUuZXhwb3J0cyA9IHJlZnJlc2ggPSB3aWtpLnJlZnJlc2ggPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgJHBhZ2UsIGNyZWF0ZUdob3N0UGFnZSwgZW1wdHlQYWdlLCBwYWdlSW5mb3JtYXRpb24sIHJldiwgc2x1Zywgd2hlbkdvdHRlbiwgX3JlZjtcbiAgICAkcGFnZSA9ICQodGhpcyk7XG4gICAgX3JlZiA9ICRwYWdlLmF0dHIoJ2lkJykuc3BsaXQoJ19yZXYnKSwgc2x1ZyA9IF9yZWZbMF0sIHJldiA9IF9yZWZbMV07XG4gICAgcGFnZUluZm9ybWF0aW9uID0ge1xuICAgICAgc2x1Zzogc2x1ZyxcbiAgICAgIHJldjogcmV2LFxuICAgICAgc2l0ZTogJHBhZ2UuZGF0YSgnc2l0ZScpXG4gICAgfTtcbiAgICBlbXB0eVBhZ2UgPSByZXF1aXJlKCcuL3BhZ2UnKS5lbXB0eVBhZ2U7XG4gICAgY3JlYXRlR2hvc3RQYWdlID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgaGl0LCBoaXRzLCBpbmZvLCBwYWdlT2JqZWN0LCByZXN1bHQsIHNpdGUsIHRpdGxlLCBfaSwgX2xlbiwgX3JlZjE7XG4gICAgICB0aXRsZSA9ICQoXCJhW2hyZWY9XFxcIi9cIiArIHNsdWcgKyBcIi5odG1sXFxcIl06bGFzdFwiKS50ZXh0KCkgfHwgc2x1ZztcbiAgICAgIHBhZ2VPYmplY3QgPSBlbXB0eVBhZ2UoKTtcbiAgICAgIHBhZ2VPYmplY3Quc2V0VGl0bGUodGl0bGUpO1xuICAgICAgaGl0cyA9IFtdO1xuICAgICAgX3JlZjEgPSB3aWtpLm5laWdoYm9yaG9vZDtcbiAgICAgIGZvciAoc2l0ZSBpbiBfcmVmMSkge1xuICAgICAgICBpbmZvID0gX3JlZjFbc2l0ZV07XG4gICAgICAgIGlmIChpbmZvLnNpdGVtYXAgIT0gbnVsbCkge1xuICAgICAgICAgIHJlc3VsdCA9IF8uZmluZChpbmZvLnNpdGVtYXAsIGZ1bmN0aW9uKGVhY2gpIHtcbiAgICAgICAgICAgIHJldHVybiBlYWNoLnNsdWcgPT09IHNsdWc7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgaWYgKHJlc3VsdCAhPSBudWxsKSB7XG4gICAgICAgICAgICBoaXRzLnB1c2goe1xuICAgICAgICAgICAgICBcInR5cGVcIjogXCJyZWZlcmVuY2VcIixcbiAgICAgICAgICAgICAgXCJzaXRlXCI6IHNpdGUsXG4gICAgICAgICAgICAgIFwic2x1Z1wiOiBzbHVnLFxuICAgICAgICAgICAgICBcInRpdGxlXCI6IHJlc3VsdC50aXRsZSB8fCBzbHVnLFxuICAgICAgICAgICAgICBcInRleHRcIjogcmVzdWx0LnN5bm9wc2lzIHx8ICcnXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChoaXRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcGFnZU9iamVjdC5hZGRJdGVtKHtcbiAgICAgICAgICAndHlwZSc6ICdmdXR1cmUnLFxuICAgICAgICAgICd0ZXh0JzogJ1dlIGNvdWxkIG5vdCBmaW5kIHRoaXMgcGFnZSBpbiB0aGUgZXhwZWN0ZWQgY29udGV4dC4nLFxuICAgICAgICAgICd0aXRsZSc6IHRpdGxlXG4gICAgICAgIH0pO1xuICAgICAgICBwYWdlT2JqZWN0LmFkZEl0ZW0oe1xuICAgICAgICAgICd0eXBlJzogJ3BhcmFncmFwaCcsXG4gICAgICAgICAgJ3RleHQnOiBcIldlIGRpZCBmaW5kIHRoZSBwYWdlIGluIHlvdXIgY3VycmVudCBuZWlnaGJvcmhvb2QuXCJcbiAgICAgICAgfSk7XG4gICAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gaGl0cy5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICAgIGhpdCA9IGhpdHNbX2ldO1xuICAgICAgICAgIHBhZ2VPYmplY3QuYWRkSXRlbShoaXQpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwYWdlT2JqZWN0LmFkZEl0ZW0oe1xuICAgICAgICAgICd0eXBlJzogJ2Z1dHVyZScsXG4gICAgICAgICAgJ3RleHQnOiAnV2UgY291bGQgbm90IGZpbmQgdGhpcyBwYWdlLicsXG4gICAgICAgICAgJ3RpdGxlJzogdGl0bGVcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gd2lraS5idWlsZFBhZ2UocGFnZU9iamVjdCwgJHBhZ2UpLmFkZENsYXNzKCdnaG9zdCcpO1xuICAgIH07XG4gICAgd2hlbkdvdHRlbiA9IGZ1bmN0aW9uKHBhZ2VPYmplY3QpIHtcbiAgICAgIHZhciBzaXRlLCBfaSwgX2xlbiwgX3JlZjEsIF9yZXN1bHRzO1xuICAgICAgd2lraS5idWlsZFBhZ2UocGFnZU9iamVjdCwgJHBhZ2UpO1xuICAgICAgX3JlZjEgPSBwYWdlT2JqZWN0LmdldE5laWdoYm9ycyhsb2NhdGlvbi5ob3N0KTtcbiAgICAgIF9yZXN1bHRzID0gW107XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIHNpdGUgPSBfcmVmMVtfaV07XG4gICAgICAgIF9yZXN1bHRzLnB1c2gobmVpZ2hib3Job29kLnJlZ2lzdGVyTmVpZ2hib3Ioc2l0ZSkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIF9yZXN1bHRzO1xuICAgIH07XG4gICAgcmV0dXJuIHBhZ2VIYW5kbGVyLmdldCh7XG4gICAgICB3aGVuR290dGVuOiB3aGVuR290dGVuLFxuICAgICAgd2hlbk5vdEdvdHRlbjogY3JlYXRlR2hvc3RQYWdlLFxuICAgICAgcGFnZUluZm9ybWF0aW9uOiBwYWdlSW5mb3JtYXRpb25cbiAgICB9KTtcbiAgfTtcblxufSkuY2FsbCh0aGlzKTtcbiIsIihmdW5jdGlvbigpIHtcbiAgdmFyIGFzU2x1ZywgZW1wdHlQYWdlLCBuZXdQYWdlLCBub3dTZWN0aW9ucywgdXRpbCwgXztcblxuICB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG5cbiAgXyA9IHJlcXVpcmUoJ3VuZGVyc2NvcmUnKTtcblxuICBhc1NsdWcgPSBmdW5jdGlvbihuYW1lKSB7XG4gICAgcmV0dXJuIG5hbWUucmVwbGFjZSgvXFxzL2csICctJykucmVwbGFjZSgvW15BLVphLXowLTktXS9nLCAnJykudG9Mb3dlckNhc2UoKTtcbiAgfTtcblxuICBlbXB0eVBhZ2UgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gbmV3UGFnZSh7fSwgbnVsbCk7XG4gIH07XG5cbiAgbm93U2VjdGlvbnMgPSBmdW5jdGlvbihub3cpIHtcbiAgICByZXR1cm4gW1xuICAgICAge1xuICAgICAgICBzeW1ib2w6ICfinYQnLFxuICAgICAgICBkYXRlOiBub3cgLSAxMDAwICogNjAgKiA2MCAqIDI0ICogMzY2LFxuICAgICAgICBwZXJpb2Q6ICdhIFllYXInXG4gICAgICB9LCB7XG4gICAgICAgIHN5bWJvbDogJ+KamCcsXG4gICAgICAgIGRhdGU6IG5vdyAtIDEwMDAgKiA2MCAqIDYwICogMjQgKiAzMSAqIDMsXG4gICAgICAgIHBlcmlvZDogJ2EgU2Vhc29uJ1xuICAgICAgfSwge1xuICAgICAgICBzeW1ib2w6ICfimqonLFxuICAgICAgICBkYXRlOiBub3cgLSAxMDAwICogNjAgKiA2MCAqIDI0ICogMzEsXG4gICAgICAgIHBlcmlvZDogJ2EgTW9udGgnXG4gICAgICB9LCB7XG4gICAgICAgIHN5bWJvbDogJ+KYvScsXG4gICAgICAgIGRhdGU6IG5vdyAtIDEwMDAgKiA2MCAqIDYwICogMjQgKiA3LFxuICAgICAgICBwZXJpb2Q6ICdhIFdlZWsnXG4gICAgICB9LCB7XG4gICAgICAgIHN5bWJvbDogJ+KYgCcsXG4gICAgICAgIGRhdGU6IG5vdyAtIDEwMDAgKiA2MCAqIDYwICogMjQsXG4gICAgICAgIHBlcmlvZDogJ2EgRGF5J1xuICAgICAgfSwge1xuICAgICAgICBzeW1ib2w6ICfijJonLFxuICAgICAgICBkYXRlOiBub3cgLSAxMDAwICogNjAgKiA2MCxcbiAgICAgICAgcGVyaW9kOiAnYW4gSG91cidcbiAgICAgIH1cbiAgICBdO1xuICB9O1xuXG4gIG5ld1BhZ2UgPSBmdW5jdGlvbihqc29uLCBzaXRlKSB7XG4gICAgdmFyIGFkZEl0ZW0sIGFkZFBhcmFncmFwaCwgZ2V0Q29udGV4dCwgZ2V0TmVpZ2hib3JzLCBnZXRSYXdQYWdlLCBnZXRSZW1vdGVTaXRlLCBnZXRTbHVnLCBpc0xvY2FsLCBpc1BsdWdpbiwgaXNSZW1vdGUsIHBhZ2UsIHNlcUFjdGlvbnMsIHNlcUl0ZW1zLCBzZXRUaXRsZTtcbiAgICBwYWdlID0gXy5leHRlbmQoe30sIHV0aWwuZW1wdHlQYWdlKCksIGpzb24pO1xuICAgIHBhZ2Uuc3RvcnkgfHwgKHBhZ2Uuc3RvcnkgPSBbXSk7XG4gICAgcGFnZS5qb3VybmFsIHx8IChwYWdlLmpvdXJuYWwgPSBbXSk7XG4gICAgZ2V0UmF3UGFnZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHBhZ2U7XG4gICAgfTtcbiAgICBnZXRDb250ZXh0ID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgYWN0aW9uLCBhZGRDb250ZXh0LCBjb250ZXh0LCBfaSwgX2xlbiwgX3JlZjtcbiAgICAgIGNvbnRleHQgPSBbJ3ZpZXcnXTtcbiAgICAgIGlmIChpc1JlbW90ZSgpKSB7XG4gICAgICAgIGNvbnRleHQucHVzaChzaXRlKTtcbiAgICAgIH1cbiAgICAgIGFkZENvbnRleHQgPSBmdW5jdGlvbihzaXRlKSB7XG4gICAgICAgIGlmICgoc2l0ZSAhPSBudWxsKSAmJiAhXy5pbmNsdWRlKGNvbnRleHQsIHNpdGUpKSB7XG4gICAgICAgICAgcmV0dXJuIGNvbnRleHQucHVzaChzaXRlKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIF9yZWYgPSBwYWdlLmpvdXJuYWwuc2xpY2UoMCkucmV2ZXJzZSgpO1xuICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIGFjdGlvbiA9IF9yZWZbX2ldO1xuICAgICAgICBhZGRDb250ZXh0KGFjdGlvbi5zaXRlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjb250ZXh0O1xuICAgIH07XG4gICAgaXNQbHVnaW4gPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBwYWdlLnBsdWdpbiAhPSBudWxsO1xuICAgIH07XG4gICAgaXNSZW1vdGUgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiAhKHNpdGUgPT09ICh2b2lkIDApIHx8IHNpdGUgPT09IG51bGwgfHwgc2l0ZSA9PT0gJ3ZpZXcnIHx8IHNpdGUgPT09ICdvcmlnaW4nIHx8IHNpdGUgPT09ICdsb2NhbCcpO1xuICAgIH07XG4gICAgaXNMb2NhbCA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHNpdGUgPT09ICdsb2NhbCc7XG4gICAgfTtcbiAgICBnZXRSZW1vdGVTaXRlID0gZnVuY3Rpb24oKSB7XG4gICAgICBpZiAoaXNSZW1vdGUoKSkge1xuICAgICAgICByZXR1cm4gc2l0ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgZ2V0U2x1ZyA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGFzU2x1ZyhwYWdlLnRpdGxlKTtcbiAgICB9O1xuICAgIGdldE5laWdoYm9ycyA9IGZ1bmN0aW9uKGhvc3QpIHtcbiAgICAgIHZhciBhY3Rpb24sIGl0ZW0sIG5laWdoYm9ycywgX2ksIF9qLCBfbGVuLCBfbGVuMSwgX3JlZiwgX3JlZjE7XG4gICAgICBuZWlnaGJvcnMgPSBbXTtcbiAgICAgIGlmIChpc1JlbW90ZSgpKSB7XG4gICAgICAgIG5laWdoYm9ycy5wdXNoKHNpdGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGhvc3QgIT0gbnVsbCkge1xuICAgICAgICAgIG5laWdoYm9ycy5wdXNoKGhvc3QpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBfcmVmID0gcGFnZS5zdG9yeTtcbiAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZi5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICBpdGVtID0gX3JlZltfaV07XG4gICAgICAgIGlmIChpdGVtLnNpdGUgIT0gbnVsbCkge1xuICAgICAgICAgIG5laWdoYm9ycy5wdXNoKGl0ZW0uc2l0ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIF9yZWYxID0gcGFnZS5qb3VybmFsO1xuICAgICAgZm9yIChfaiA9IDAsIF9sZW4xID0gX3JlZjEubGVuZ3RoOyBfaiA8IF9sZW4xOyBfaisrKSB7XG4gICAgICAgIGFjdGlvbiA9IF9yZWYxW19qXTtcbiAgICAgICAgaWYgKGFjdGlvbi5zaXRlICE9IG51bGwpIHtcbiAgICAgICAgICBuZWlnaGJvcnMucHVzaChhY3Rpb24uc2l0ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBfLnVuaXEobmVpZ2hib3JzKTtcbiAgICB9O1xuICAgIHNldFRpdGxlID0gZnVuY3Rpb24odGl0bGUpIHtcbiAgICAgIHJldHVybiBwYWdlLnRpdGxlID0gdGl0bGU7XG4gICAgfTtcbiAgICBhZGRJdGVtID0gZnVuY3Rpb24oaXRlbSkge1xuICAgICAgaXRlbSA9IF8uZXh0ZW5kKHt9LCB7XG4gICAgICAgIGlkOiB1dGlsLnJhbmRvbUJ5dGVzKDgpXG4gICAgICB9LCBpdGVtKTtcbiAgICAgIHJldHVybiBwYWdlLnN0b3J5LnB1c2goaXRlbSk7XG4gICAgfTtcbiAgICBzZXFJdGVtcyA9IGZ1bmN0aW9uKGVhY2gpIHtcbiAgICAgIHZhciBlbWl0SXRlbTtcbiAgICAgIGVtaXRJdGVtID0gZnVuY3Rpb24oaSkge1xuICAgICAgICBpZiAoaSA+PSBwYWdlLnN0b3J5Lmxlbmd0aCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWFjaChwYWdlLnN0b3J5W2ldLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gZW1pdEl0ZW0oaSArIDEpO1xuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgICByZXR1cm4gZW1pdEl0ZW0oMCk7XG4gICAgfTtcbiAgICBhZGRQYXJhZ3JhcGggPSBmdW5jdGlvbih0ZXh0KSB7XG4gICAgICB2YXIgdHlwZTtcbiAgICAgIHR5cGUgPSBcInBhcmFncmFwaFwiO1xuICAgICAgcmV0dXJuIGFkZEl0ZW0oe1xuICAgICAgICB0eXBlOiB0eXBlLFxuICAgICAgICB0ZXh0OiB0ZXh0XG4gICAgICB9KTtcbiAgICB9O1xuICAgIHNlcUFjdGlvbnMgPSBmdW5jdGlvbihlYWNoKSB7XG4gICAgICB2YXIgZW1pdEFjdGlvbiwgc2VjdGlvbnMsIHNtYWxsZXI7XG4gICAgICBzbWFsbGVyID0gMDtcbiAgICAgIHNlY3Rpb25zID0gbm93U2VjdGlvbnMoKG5ldyBEYXRlKS5nZXRUaW1lKCkpO1xuICAgICAgZW1pdEFjdGlvbiA9IGZ1bmN0aW9uKGkpIHtcbiAgICAgICAgdmFyIGFjdGlvbiwgYmlnZ2VyLCBzZWN0aW9uLCBzZXBhcmF0b3IsIF9pLCBfbGVuO1xuICAgICAgICBpZiAoaSA+PSBwYWdlLmpvdXJuYWwubGVuZ3RoKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGFjdGlvbiA9IHBhZ2Uuam91cm5hbFtpXTtcbiAgICAgICAgYmlnZ2VyID0gYWN0aW9uLmRhdGUgfHwgMDtcbiAgICAgICAgc2VwYXJhdG9yID0gbnVsbDtcbiAgICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBzZWN0aW9ucy5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICAgIHNlY3Rpb24gPSBzZWN0aW9uc1tfaV07XG4gICAgICAgICAgaWYgKHNlY3Rpb24uZGF0ZSA+IHNtYWxsZXIgJiYgc2VjdGlvbi5kYXRlIDwgYmlnZ2VyKSB7XG4gICAgICAgICAgICBzZXBhcmF0b3IgPSBzZWN0aW9uO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzbWFsbGVyID0gYmlnZ2VyO1xuICAgICAgICByZXR1cm4gZWFjaCh7XG4gICAgICAgICAgYWN0aW9uOiBhY3Rpb24sXG4gICAgICAgICAgc2VwYXJhdG9yOiBzZXBhcmF0b3JcbiAgICAgICAgfSwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIGVtaXRBY3Rpb24oaSArIDEpO1xuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgICByZXR1cm4gZW1pdEFjdGlvbigwKTtcbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICBnZXRSYXdQYWdlOiBnZXRSYXdQYWdlLFxuICAgICAgZ2V0Q29udGV4dDogZ2V0Q29udGV4dCxcbiAgICAgIGlzUGx1Z2luOiBpc1BsdWdpbixcbiAgICAgIGlzUmVtb3RlOiBpc1JlbW90ZSxcbiAgICAgIGlzTG9jYWw6IGlzTG9jYWwsXG4gICAgICBnZXRSZW1vdGVTaXRlOiBnZXRSZW1vdGVTaXRlLFxuICAgICAgZ2V0U2x1ZzogZ2V0U2x1ZyxcbiAgICAgIGdldE5laWdoYm9yczogZ2V0TmVpZ2hib3JzLFxuICAgICAgc2V0VGl0bGU6IHNldFRpdGxlLFxuICAgICAgYWRkSXRlbTogYWRkSXRlbSxcbiAgICAgIGFkZFBhcmFncmFwaDogYWRkUGFyYWdyYXBoLFxuICAgICAgc2VxSXRlbXM6IHNlcUl0ZW1zLFxuICAgICAgc2VxQWN0aW9uczogc2VxQWN0aW9uc1xuICAgIH07XG4gIH07XG5cbiAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbmV3UGFnZTogbmV3UGFnZSxcbiAgICBlbXB0eVBhZ2U6IGVtcHR5UGFnZVxuICB9O1xuXG59KS5jYWxsKHRoaXMpO1xuIiwiKGZ1bmN0aW9uKCl7Ly8gICAgIFVuZGVyc2NvcmUuanMgMS41LjJcbi8vICAgICBodHRwOi8vdW5kZXJzY29yZWpzLm9yZ1xuLy8gICAgIChjKSAyMDA5LTIwMTMgSmVyZW15IEFzaGtlbmFzLCBEb2N1bWVudENsb3VkIGFuZCBJbnZlc3RpZ2F0aXZlIFJlcG9ydGVycyAmIEVkaXRvcnNcbi8vICAgICBVbmRlcnNjb3JlIG1heSBiZSBmcmVlbHkgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlLlxuXG4oZnVuY3Rpb24oKSB7XG5cbiAgLy8gQmFzZWxpbmUgc2V0dXBcbiAgLy8gLS0tLS0tLS0tLS0tLS1cblxuICAvLyBFc3RhYmxpc2ggdGhlIHJvb3Qgb2JqZWN0LCBgd2luZG93YCBpbiB0aGUgYnJvd3Nlciwgb3IgYGV4cG9ydHNgIG9uIHRoZSBzZXJ2ZXIuXG4gIHZhciByb290ID0gdGhpcztcblxuICAvLyBTYXZlIHRoZSBwcmV2aW91cyB2YWx1ZSBvZiB0aGUgYF9gIHZhcmlhYmxlLlxuICB2YXIgcHJldmlvdXNVbmRlcnNjb3JlID0gcm9vdC5fO1xuXG4gIC8vIEVzdGFibGlzaCB0aGUgb2JqZWN0IHRoYXQgZ2V0cyByZXR1cm5lZCB0byBicmVhayBvdXQgb2YgYSBsb29wIGl0ZXJhdGlvbi5cbiAgdmFyIGJyZWFrZXIgPSB7fTtcblxuICAvLyBTYXZlIGJ5dGVzIGluIHRoZSBtaW5pZmllZCAoYnV0IG5vdCBnemlwcGVkKSB2ZXJzaW9uOlxuICB2YXIgQXJyYXlQcm90byA9IEFycmF5LnByb3RvdHlwZSwgT2JqUHJvdG8gPSBPYmplY3QucHJvdG90eXBlLCBGdW5jUHJvdG8gPSBGdW5jdGlvbi5wcm90b3R5cGU7XG5cbiAgLy8gQ3JlYXRlIHF1aWNrIHJlZmVyZW5jZSB2YXJpYWJsZXMgZm9yIHNwZWVkIGFjY2VzcyB0byBjb3JlIHByb3RvdHlwZXMuXG4gIHZhclxuICAgIHB1c2ggICAgICAgICAgICAgPSBBcnJheVByb3RvLnB1c2gsXG4gICAgc2xpY2UgICAgICAgICAgICA9IEFycmF5UHJvdG8uc2xpY2UsXG4gICAgY29uY2F0ICAgICAgICAgICA9IEFycmF5UHJvdG8uY29uY2F0LFxuICAgIHRvU3RyaW5nICAgICAgICAgPSBPYmpQcm90by50b1N0cmluZyxcbiAgICBoYXNPd25Qcm9wZXJ0eSAgID0gT2JqUHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbiAgLy8gQWxsICoqRUNNQVNjcmlwdCA1KiogbmF0aXZlIGZ1bmN0aW9uIGltcGxlbWVudGF0aW9ucyB0aGF0IHdlIGhvcGUgdG8gdXNlXG4gIC8vIGFyZSBkZWNsYXJlZCBoZXJlLlxuICB2YXJcbiAgICBuYXRpdmVGb3JFYWNoICAgICAgPSBBcnJheVByb3RvLmZvckVhY2gsXG4gICAgbmF0aXZlTWFwICAgICAgICAgID0gQXJyYXlQcm90by5tYXAsXG4gICAgbmF0aXZlUmVkdWNlICAgICAgID0gQXJyYXlQcm90by5yZWR1Y2UsXG4gICAgbmF0aXZlUmVkdWNlUmlnaHQgID0gQXJyYXlQcm90by5yZWR1Y2VSaWdodCxcbiAgICBuYXRpdmVGaWx0ZXIgICAgICAgPSBBcnJheVByb3RvLmZpbHRlcixcbiAgICBuYXRpdmVFdmVyeSAgICAgICAgPSBBcnJheVByb3RvLmV2ZXJ5LFxuICAgIG5hdGl2ZVNvbWUgICAgICAgICA9IEFycmF5UHJvdG8uc29tZSxcbiAgICBuYXRpdmVJbmRleE9mICAgICAgPSBBcnJheVByb3RvLmluZGV4T2YsXG4gICAgbmF0aXZlTGFzdEluZGV4T2YgID0gQXJyYXlQcm90by5sYXN0SW5kZXhPZixcbiAgICBuYXRpdmVJc0FycmF5ICAgICAgPSBBcnJheS5pc0FycmF5LFxuICAgIG5hdGl2ZUtleXMgICAgICAgICA9IE9iamVjdC5rZXlzLFxuICAgIG5hdGl2ZUJpbmQgICAgICAgICA9IEZ1bmNQcm90by5iaW5kO1xuXG4gIC8vIENyZWF0ZSBhIHNhZmUgcmVmZXJlbmNlIHRvIHRoZSBVbmRlcnNjb3JlIG9iamVjdCBmb3IgdXNlIGJlbG93LlxuICB2YXIgXyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmIChvYmogaW5zdGFuY2VvZiBfKSByZXR1cm4gb2JqO1xuICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBfKSkgcmV0dXJuIG5ldyBfKG9iaik7XG4gICAgdGhpcy5fd3JhcHBlZCA9IG9iajtcbiAgfTtcblxuICAvLyBFeHBvcnQgdGhlIFVuZGVyc2NvcmUgb2JqZWN0IGZvciAqKk5vZGUuanMqKiwgd2l0aFxuICAvLyBiYWNrd2FyZHMtY29tcGF0aWJpbGl0eSBmb3IgdGhlIG9sZCBgcmVxdWlyZSgpYCBBUEkuIElmIHdlJ3JlIGluXG4gIC8vIHRoZSBicm93c2VyLCBhZGQgYF9gIGFzIGEgZ2xvYmFsIG9iamVjdCB2aWEgYSBzdHJpbmcgaWRlbnRpZmllcixcbiAgLy8gZm9yIENsb3N1cmUgQ29tcGlsZXIgXCJhZHZhbmNlZFwiIG1vZGUuXG4gIGlmICh0eXBlb2YgZXhwb3J0cyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgJiYgbW9kdWxlLmV4cG9ydHMpIHtcbiAgICAgIGV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IF87XG4gICAgfVxuICAgIGV4cG9ydHMuXyA9IF87XG4gIH0gZWxzZSB7XG4gICAgcm9vdC5fID0gXztcbiAgfVxuXG4gIC8vIEN1cnJlbnQgdmVyc2lvbi5cbiAgXy5WRVJTSU9OID0gJzEuNS4yJztcblxuICAvLyBDb2xsZWN0aW9uIEZ1bmN0aW9uc1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8vIFRoZSBjb3JuZXJzdG9uZSwgYW4gYGVhY2hgIGltcGxlbWVudGF0aW9uLCBha2EgYGZvckVhY2hgLlxuICAvLyBIYW5kbGVzIG9iamVjdHMgd2l0aCB0aGUgYnVpbHQtaW4gYGZvckVhY2hgLCBhcnJheXMsIGFuZCByYXcgb2JqZWN0cy5cbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYGZvckVhY2hgIGlmIGF2YWlsYWJsZS5cbiAgdmFyIGVhY2ggPSBfLmVhY2ggPSBfLmZvckVhY2ggPSBmdW5jdGlvbihvYmosIGl0ZXJhdG9yLCBjb250ZXh0KSB7XG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm47XG4gICAgaWYgKG5hdGl2ZUZvckVhY2ggJiYgb2JqLmZvckVhY2ggPT09IG5hdGl2ZUZvckVhY2gpIHtcbiAgICAgIG9iai5mb3JFYWNoKGl0ZXJhdG9yLCBjb250ZXh0KTtcbiAgICB9IGVsc2UgaWYgKG9iai5sZW5ndGggPT09ICtvYmoubGVuZ3RoKSB7XG4gICAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gb2JqLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChpdGVyYXRvci5jYWxsKGNvbnRleHQsIG9ialtpXSwgaSwgb2JqKSA9PT0gYnJlYWtlcikgcmV0dXJuO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopO1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGtleXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgb2JqW2tleXNbaV1dLCBrZXlzW2ldLCBvYmopID09PSBicmVha2VyKSByZXR1cm47XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIC8vIFJldHVybiB0aGUgcmVzdWx0cyBvZiBhcHBseWluZyB0aGUgaXRlcmF0b3IgdG8gZWFjaCBlbGVtZW50LlxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgbWFwYCBpZiBhdmFpbGFibGUuXG4gIF8ubWFwID0gXy5jb2xsZWN0ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIHZhciByZXN1bHRzID0gW107XG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gcmVzdWx0cztcbiAgICBpZiAobmF0aXZlTWFwICYmIG9iai5tYXAgPT09IG5hdGl2ZU1hcCkgcmV0dXJuIG9iai5tYXAoaXRlcmF0b3IsIGNvbnRleHQpO1xuICAgIGVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIHJlc3VsdHMucHVzaChpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgbGlzdCkpO1xuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9O1xuXG4gIHZhciByZWR1Y2VFcnJvciA9ICdSZWR1Y2Ugb2YgZW1wdHkgYXJyYXkgd2l0aCBubyBpbml0aWFsIHZhbHVlJztcblxuICAvLyAqKlJlZHVjZSoqIGJ1aWxkcyB1cCBhIHNpbmdsZSByZXN1bHQgZnJvbSBhIGxpc3Qgb2YgdmFsdWVzLCBha2EgYGluamVjdGAsXG4gIC8vIG9yIGBmb2xkbGAuIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGByZWR1Y2VgIGlmIGF2YWlsYWJsZS5cbiAgXy5yZWR1Y2UgPSBfLmZvbGRsID0gXy5pbmplY3QgPSBmdW5jdGlvbihvYmosIGl0ZXJhdG9yLCBtZW1vLCBjb250ZXh0KSB7XG4gICAgdmFyIGluaXRpYWwgPSBhcmd1bWVudHMubGVuZ3RoID4gMjtcbiAgICBpZiAob2JqID09IG51bGwpIG9iaiA9IFtdO1xuICAgIGlmIChuYXRpdmVSZWR1Y2UgJiYgb2JqLnJlZHVjZSA9PT0gbmF0aXZlUmVkdWNlKSB7XG4gICAgICBpZiAoY29udGV4dCkgaXRlcmF0b3IgPSBfLmJpbmQoaXRlcmF0b3IsIGNvbnRleHQpO1xuICAgICAgcmV0dXJuIGluaXRpYWwgPyBvYmoucmVkdWNlKGl0ZXJhdG9yLCBtZW1vKSA6IG9iai5yZWR1Y2UoaXRlcmF0b3IpO1xuICAgIH1cbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICBpZiAoIWluaXRpYWwpIHtcbiAgICAgICAgbWVtbyA9IHZhbHVlO1xuICAgICAgICBpbml0aWFsID0gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1lbW8gPSBpdGVyYXRvci5jYWxsKGNvbnRleHQsIG1lbW8sIHZhbHVlLCBpbmRleCwgbGlzdCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKCFpbml0aWFsKSB0aHJvdyBuZXcgVHlwZUVycm9yKHJlZHVjZUVycm9yKTtcbiAgICByZXR1cm4gbWVtbztcbiAgfTtcblxuICAvLyBUaGUgcmlnaHQtYXNzb2NpYXRpdmUgdmVyc2lvbiBvZiByZWR1Y2UsIGFsc28ga25vd24gYXMgYGZvbGRyYC5cbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYHJlZHVjZVJpZ2h0YCBpZiBhdmFpbGFibGUuXG4gIF8ucmVkdWNlUmlnaHQgPSBfLmZvbGRyID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgbWVtbywgY29udGV4dCkge1xuICAgIHZhciBpbml0aWFsID0gYXJndW1lbnRzLmxlbmd0aCA+IDI7XG4gICAgaWYgKG9iaiA9PSBudWxsKSBvYmogPSBbXTtcbiAgICBpZiAobmF0aXZlUmVkdWNlUmlnaHQgJiYgb2JqLnJlZHVjZVJpZ2h0ID09PSBuYXRpdmVSZWR1Y2VSaWdodCkge1xuICAgICAgaWYgKGNvbnRleHQpIGl0ZXJhdG9yID0gXy5iaW5kKGl0ZXJhdG9yLCBjb250ZXh0KTtcbiAgICAgIHJldHVybiBpbml0aWFsID8gb2JqLnJlZHVjZVJpZ2h0KGl0ZXJhdG9yLCBtZW1vKSA6IG9iai5yZWR1Y2VSaWdodChpdGVyYXRvcik7XG4gICAgfVxuICAgIHZhciBsZW5ndGggPSBvYmoubGVuZ3RoO1xuICAgIGlmIChsZW5ndGggIT09ICtsZW5ndGgpIHtcbiAgICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XG4gICAgICBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgICB9XG4gICAgZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xuICAgICAgaW5kZXggPSBrZXlzID8ga2V5c1stLWxlbmd0aF0gOiAtLWxlbmd0aDtcbiAgICAgIGlmICghaW5pdGlhbCkge1xuICAgICAgICBtZW1vID0gb2JqW2luZGV4XTtcbiAgICAgICAgaW5pdGlhbCA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtZW1vID0gaXRlcmF0b3IuY2FsbChjb250ZXh0LCBtZW1vLCBvYmpbaW5kZXhdLCBpbmRleCwgbGlzdCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKCFpbml0aWFsKSB0aHJvdyBuZXcgVHlwZUVycm9yKHJlZHVjZUVycm9yKTtcbiAgICByZXR1cm4gbWVtbztcbiAgfTtcblxuICAvLyBSZXR1cm4gdGhlIGZpcnN0IHZhbHVlIHdoaWNoIHBhc3NlcyBhIHRydXRoIHRlc3QuIEFsaWFzZWQgYXMgYGRldGVjdGAuXG4gIF8uZmluZCA9IF8uZGV0ZWN0ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIHZhciByZXN1bHQ7XG4gICAgYW55KG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICBpZiAoaXRlcmF0b3IuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpKSB7XG4gICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFJldHVybiBhbGwgdGhlIGVsZW1lbnRzIHRoYXQgcGFzcyBhIHRydXRoIHRlc3QuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBmaWx0ZXJgIGlmIGF2YWlsYWJsZS5cbiAgLy8gQWxpYXNlZCBhcyBgc2VsZWN0YC5cbiAgXy5maWx0ZXIgPSBfLnNlbGVjdCA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIHJlc3VsdHM7XG4gICAgaWYgKG5hdGl2ZUZpbHRlciAmJiBvYmouZmlsdGVyID09PSBuYXRpdmVGaWx0ZXIpIHJldHVybiBvYmouZmlsdGVyKGl0ZXJhdG9yLCBjb250ZXh0KTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICBpZiAoaXRlcmF0b3IuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpKSByZXN1bHRzLnB1c2godmFsdWUpO1xuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9O1xuXG4gIC8vIFJldHVybiBhbGwgdGhlIGVsZW1lbnRzIGZvciB3aGljaCBhIHRydXRoIHRlc3QgZmFpbHMuXG4gIF8ucmVqZWN0ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIHJldHVybiBfLmZpbHRlcihvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xuICAgICAgcmV0dXJuICFpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgbGlzdCk7XG4gICAgfSwgY29udGV4dCk7XG4gIH07XG5cbiAgLy8gRGV0ZXJtaW5lIHdoZXRoZXIgYWxsIG9mIHRoZSBlbGVtZW50cyBtYXRjaCBhIHRydXRoIHRlc3QuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBldmVyeWAgaWYgYXZhaWxhYmxlLlxuICAvLyBBbGlhc2VkIGFzIGBhbGxgLlxuICBfLmV2ZXJ5ID0gXy5hbGwgPSBmdW5jdGlvbihvYmosIGl0ZXJhdG9yLCBjb250ZXh0KSB7XG4gICAgaXRlcmF0b3IgfHwgKGl0ZXJhdG9yID0gXy5pZGVudGl0eSk7XG4gICAgdmFyIHJlc3VsdCA9IHRydWU7XG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gcmVzdWx0O1xuICAgIGlmIChuYXRpdmVFdmVyeSAmJiBvYmouZXZlcnkgPT09IG5hdGl2ZUV2ZXJ5KSByZXR1cm4gb2JqLmV2ZXJ5KGl0ZXJhdG9yLCBjb250ZXh0KTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICBpZiAoIShyZXN1bHQgPSByZXN1bHQgJiYgaXRlcmF0b3IuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpKSkgcmV0dXJuIGJyZWFrZXI7XG4gICAgfSk7XG4gICAgcmV0dXJuICEhcmVzdWx0O1xuICB9O1xuXG4gIC8vIERldGVybWluZSBpZiBhdCBsZWFzdCBvbmUgZWxlbWVudCBpbiB0aGUgb2JqZWN0IG1hdGNoZXMgYSB0cnV0aCB0ZXN0LlxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgc29tZWAgaWYgYXZhaWxhYmxlLlxuICAvLyBBbGlhc2VkIGFzIGBhbnlgLlxuICB2YXIgYW55ID0gXy5zb21lID0gXy5hbnkgPSBmdW5jdGlvbihvYmosIGl0ZXJhdG9yLCBjb250ZXh0KSB7XG4gICAgaXRlcmF0b3IgfHwgKGl0ZXJhdG9yID0gXy5pZGVudGl0eSk7XG4gICAgdmFyIHJlc3VsdCA9IGZhbHNlO1xuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIHJlc3VsdDtcbiAgICBpZiAobmF0aXZlU29tZSAmJiBvYmouc29tZSA9PT0gbmF0aXZlU29tZSkgcmV0dXJuIG9iai5zb21lKGl0ZXJhdG9yLCBjb250ZXh0KTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICBpZiAocmVzdWx0IHx8IChyZXN1bHQgPSBpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgbGlzdCkpKSByZXR1cm4gYnJlYWtlcjtcbiAgICB9KTtcbiAgICByZXR1cm4gISFyZXN1bHQ7XG4gIH07XG5cbiAgLy8gRGV0ZXJtaW5lIGlmIHRoZSBhcnJheSBvciBvYmplY3QgY29udGFpbnMgYSBnaXZlbiB2YWx1ZSAodXNpbmcgYD09PWApLlxuICAvLyBBbGlhc2VkIGFzIGBpbmNsdWRlYC5cbiAgXy5jb250YWlucyA9IF8uaW5jbHVkZSA9IGZ1bmN0aW9uKG9iaiwgdGFyZ2V0KSB7XG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKG5hdGl2ZUluZGV4T2YgJiYgb2JqLmluZGV4T2YgPT09IG5hdGl2ZUluZGV4T2YpIHJldHVybiBvYmouaW5kZXhPZih0YXJnZXQpICE9IC0xO1xuICAgIHJldHVybiBhbnkob2JqLCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSB0YXJnZXQ7XG4gICAgfSk7XG4gIH07XG5cbiAgLy8gSW52b2tlIGEgbWV0aG9kICh3aXRoIGFyZ3VtZW50cykgb24gZXZlcnkgaXRlbSBpbiBhIGNvbGxlY3Rpb24uXG4gIF8uaW52b2tlID0gZnVuY3Rpb24ob2JqLCBtZXRob2QpIHtcbiAgICB2YXIgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcbiAgICB2YXIgaXNGdW5jID0gXy5pc0Z1bmN0aW9uKG1ldGhvZCk7XG4gICAgcmV0dXJuIF8ubWFwKG9iaiwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHJldHVybiAoaXNGdW5jID8gbWV0aG9kIDogdmFsdWVbbWV0aG9kXSkuYXBwbHkodmFsdWUsIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIENvbnZlbmllbmNlIHZlcnNpb24gb2YgYSBjb21tb24gdXNlIGNhc2Ugb2YgYG1hcGA6IGZldGNoaW5nIGEgcHJvcGVydHkuXG4gIF8ucGx1Y2sgPSBmdW5jdGlvbihvYmosIGtleSkge1xuICAgIHJldHVybiBfLm1hcChvYmosIGZ1bmN0aW9uKHZhbHVlKXsgcmV0dXJuIHZhbHVlW2tleV07IH0pO1xuICB9O1xuXG4gIC8vIENvbnZlbmllbmNlIHZlcnNpb24gb2YgYSBjb21tb24gdXNlIGNhc2Ugb2YgYGZpbHRlcmA6IHNlbGVjdGluZyBvbmx5IG9iamVjdHNcbiAgLy8gY29udGFpbmluZyBzcGVjaWZpYyBga2V5OnZhbHVlYCBwYWlycy5cbiAgXy53aGVyZSA9IGZ1bmN0aW9uKG9iaiwgYXR0cnMsIGZpcnN0KSB7XG4gICAgaWYgKF8uaXNFbXB0eShhdHRycykpIHJldHVybiBmaXJzdCA/IHZvaWQgMCA6IFtdO1xuICAgIHJldHVybiBfW2ZpcnN0ID8gJ2ZpbmQnIDogJ2ZpbHRlciddKG9iaiwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIGZvciAodmFyIGtleSBpbiBhdHRycykge1xuICAgICAgICBpZiAoYXR0cnNba2V5XSAhPT0gdmFsdWVba2V5XSkgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSk7XG4gIH07XG5cbiAgLy8gQ29udmVuaWVuY2UgdmVyc2lvbiBvZiBhIGNvbW1vbiB1c2UgY2FzZSBvZiBgZmluZGA6IGdldHRpbmcgdGhlIGZpcnN0IG9iamVjdFxuICAvLyBjb250YWluaW5nIHNwZWNpZmljIGBrZXk6dmFsdWVgIHBhaXJzLlxuICBfLmZpbmRXaGVyZSA9IGZ1bmN0aW9uKG9iaiwgYXR0cnMpIHtcbiAgICByZXR1cm4gXy53aGVyZShvYmosIGF0dHJzLCB0cnVlKTtcbiAgfTtcblxuICAvLyBSZXR1cm4gdGhlIG1heGltdW0gZWxlbWVudCBvciAoZWxlbWVudC1iYXNlZCBjb21wdXRhdGlvbikuXG4gIC8vIENhbid0IG9wdGltaXplIGFycmF5cyBvZiBpbnRlZ2VycyBsb25nZXIgdGhhbiA2NSw1MzUgZWxlbWVudHMuXG4gIC8vIFNlZSBbV2ViS2l0IEJ1ZyA4MDc5N10oaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTgwNzk3KVxuICBfLm1heCA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICBpZiAoIWl0ZXJhdG9yICYmIF8uaXNBcnJheShvYmopICYmIG9ialswXSA9PT0gK29ialswXSAmJiBvYmoubGVuZ3RoIDwgNjU1MzUpIHtcbiAgICAgIHJldHVybiBNYXRoLm1heC5hcHBseShNYXRoLCBvYmopO1xuICAgIH1cbiAgICBpZiAoIWl0ZXJhdG9yICYmIF8uaXNFbXB0eShvYmopKSByZXR1cm4gLUluZmluaXR5O1xuICAgIHZhciByZXN1bHQgPSB7Y29tcHV0ZWQgOiAtSW5maW5pdHksIHZhbHVlOiAtSW5maW5pdHl9O1xuICAgIGVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIHZhciBjb21wdXRlZCA9IGl0ZXJhdG9yID8gaXRlcmF0b3IuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpIDogdmFsdWU7XG4gICAgICBjb21wdXRlZCA+IHJlc3VsdC5jb21wdXRlZCAmJiAocmVzdWx0ID0ge3ZhbHVlIDogdmFsdWUsIGNvbXB1dGVkIDogY29tcHV0ZWR9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0LnZhbHVlO1xuICB9O1xuXG4gIC8vIFJldHVybiB0aGUgbWluaW11bSBlbGVtZW50IChvciBlbGVtZW50LWJhc2VkIGNvbXB1dGF0aW9uKS5cbiAgXy5taW4gPSBmdW5jdGlvbihvYmosIGl0ZXJhdG9yLCBjb250ZXh0KSB7XG4gICAgaWYgKCFpdGVyYXRvciAmJiBfLmlzQXJyYXkob2JqKSAmJiBvYmpbMF0gPT09ICtvYmpbMF0gJiYgb2JqLmxlbmd0aCA8IDY1NTM1KSB7XG4gICAgICByZXR1cm4gTWF0aC5taW4uYXBwbHkoTWF0aCwgb2JqKTtcbiAgICB9XG4gICAgaWYgKCFpdGVyYXRvciAmJiBfLmlzRW1wdHkob2JqKSkgcmV0dXJuIEluZmluaXR5O1xuICAgIHZhciByZXN1bHQgPSB7Y29tcHV0ZWQgOiBJbmZpbml0eSwgdmFsdWU6IEluZmluaXR5fTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICB2YXIgY29tcHV0ZWQgPSBpdGVyYXRvciA/IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KSA6IHZhbHVlO1xuICAgICAgY29tcHV0ZWQgPCByZXN1bHQuY29tcHV0ZWQgJiYgKHJlc3VsdCA9IHt2YWx1ZSA6IHZhbHVlLCBjb21wdXRlZCA6IGNvbXB1dGVkfSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdC52YWx1ZTtcbiAgfTtcblxuICAvLyBTaHVmZmxlIGFuIGFycmF5LCB1c2luZyB0aGUgbW9kZXJuIHZlcnNpb24gb2YgdGhlIFxuICAvLyBbRmlzaGVyLVlhdGVzIHNodWZmbGVdKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRmlzaGVy4oCTWWF0ZXNfc2h1ZmZsZSkuXG4gIF8uc2h1ZmZsZSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciByYW5kO1xuICAgIHZhciBpbmRleCA9IDA7XG4gICAgdmFyIHNodWZmbGVkID0gW107XG4gICAgZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByYW5kID0gXy5yYW5kb20oaW5kZXgrKyk7XG4gICAgICBzaHVmZmxlZFtpbmRleCAtIDFdID0gc2h1ZmZsZWRbcmFuZF07XG4gICAgICBzaHVmZmxlZFtyYW5kXSA9IHZhbHVlO1xuICAgIH0pO1xuICAgIHJldHVybiBzaHVmZmxlZDtcbiAgfTtcblxuICAvLyBTYW1wbGUgKipuKiogcmFuZG9tIHZhbHVlcyBmcm9tIGFuIGFycmF5LlxuICAvLyBJZiAqKm4qKiBpcyBub3Qgc3BlY2lmaWVkLCByZXR1cm5zIGEgc2luZ2xlIHJhbmRvbSBlbGVtZW50IGZyb20gdGhlIGFycmF5LlxuICAvLyBUaGUgaW50ZXJuYWwgYGd1YXJkYCBhcmd1bWVudCBhbGxvd3MgaXQgdG8gd29yayB3aXRoIGBtYXBgLlxuICBfLnNhbXBsZSA9IGZ1bmN0aW9uKG9iaiwgbiwgZ3VhcmQpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIgfHwgZ3VhcmQpIHtcbiAgICAgIHJldHVybiBvYmpbXy5yYW5kb20ob2JqLmxlbmd0aCAtIDEpXTtcbiAgICB9XG4gICAgcmV0dXJuIF8uc2h1ZmZsZShvYmopLnNsaWNlKDAsIE1hdGgubWF4KDAsIG4pKTtcbiAgfTtcblxuICAvLyBBbiBpbnRlcm5hbCBmdW5jdGlvbiB0byBnZW5lcmF0ZSBsb29rdXAgaXRlcmF0b3JzLlxuICB2YXIgbG9va3VwSXRlcmF0b3IgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiBfLmlzRnVuY3Rpb24odmFsdWUpID8gdmFsdWUgOiBmdW5jdGlvbihvYmopeyByZXR1cm4gb2JqW3ZhbHVlXTsgfTtcbiAgfTtcblxuICAvLyBTb3J0IHRoZSBvYmplY3QncyB2YWx1ZXMgYnkgYSBjcml0ZXJpb24gcHJvZHVjZWQgYnkgYW4gaXRlcmF0b3IuXG4gIF8uc29ydEJ5ID0gZnVuY3Rpb24ob2JqLCB2YWx1ZSwgY29udGV4dCkge1xuICAgIHZhciBpdGVyYXRvciA9IGxvb2t1cEl0ZXJhdG9yKHZhbHVlKTtcbiAgICByZXR1cm4gXy5wbHVjayhfLm1hcChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgICBpbmRleDogaW5kZXgsXG4gICAgICAgIGNyaXRlcmlhOiBpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgbGlzdClcbiAgICAgIH07XG4gICAgfSkuc29ydChmdW5jdGlvbihsZWZ0LCByaWdodCkge1xuICAgICAgdmFyIGEgPSBsZWZ0LmNyaXRlcmlhO1xuICAgICAgdmFyIGIgPSByaWdodC5jcml0ZXJpYTtcbiAgICAgIGlmIChhICE9PSBiKSB7XG4gICAgICAgIGlmIChhID4gYiB8fCBhID09PSB2b2lkIDApIHJldHVybiAxO1xuICAgICAgICBpZiAoYSA8IGIgfHwgYiA9PT0gdm9pZCAwKSByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgICByZXR1cm4gbGVmdC5pbmRleCAtIHJpZ2h0LmluZGV4O1xuICAgIH0pLCAndmFsdWUnKTtcbiAgfTtcblxuICAvLyBBbiBpbnRlcm5hbCBmdW5jdGlvbiB1c2VkIGZvciBhZ2dyZWdhdGUgXCJncm91cCBieVwiIG9wZXJhdGlvbnMuXG4gIHZhciBncm91cCA9IGZ1bmN0aW9uKGJlaGF2aW9yKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKG9iaiwgdmFsdWUsIGNvbnRleHQpIHtcbiAgICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICAgIHZhciBpdGVyYXRvciA9IHZhbHVlID09IG51bGwgPyBfLmlkZW50aXR5IDogbG9va3VwSXRlcmF0b3IodmFsdWUpO1xuICAgICAgZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgICB2YXIga2V5ID0gaXRlcmF0b3IuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIG9iaik7XG4gICAgICAgIGJlaGF2aW9yKHJlc3VsdCwga2V5LCB2YWx1ZSk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgfTtcblxuICAvLyBHcm91cHMgdGhlIG9iamVjdCdzIHZhbHVlcyBieSBhIGNyaXRlcmlvbi4gUGFzcyBlaXRoZXIgYSBzdHJpbmcgYXR0cmlidXRlXG4gIC8vIHRvIGdyb3VwIGJ5LCBvciBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgY3JpdGVyaW9uLlxuICBfLmdyb3VwQnkgPSBncm91cChmdW5jdGlvbihyZXN1bHQsIGtleSwgdmFsdWUpIHtcbiAgICAoXy5oYXMocmVzdWx0LCBrZXkpID8gcmVzdWx0W2tleV0gOiAocmVzdWx0W2tleV0gPSBbXSkpLnB1c2godmFsdWUpO1xuICB9KTtcblxuICAvLyBJbmRleGVzIHRoZSBvYmplY3QncyB2YWx1ZXMgYnkgYSBjcml0ZXJpb24sIHNpbWlsYXIgdG8gYGdyb3VwQnlgLCBidXQgZm9yXG4gIC8vIHdoZW4geW91IGtub3cgdGhhdCB5b3VyIGluZGV4IHZhbHVlcyB3aWxsIGJlIHVuaXF1ZS5cbiAgXy5pbmRleEJ5ID0gZ3JvdXAoZnVuY3Rpb24ocmVzdWx0LCBrZXksIHZhbHVlKSB7XG4gICAgcmVzdWx0W2tleV0gPSB2YWx1ZTtcbiAgfSk7XG5cbiAgLy8gQ291bnRzIGluc3RhbmNlcyBvZiBhbiBvYmplY3QgdGhhdCBncm91cCBieSBhIGNlcnRhaW4gY3JpdGVyaW9uLiBQYXNzXG4gIC8vIGVpdGhlciBhIHN0cmluZyBhdHRyaWJ1dGUgdG8gY291bnQgYnksIG9yIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZVxuICAvLyBjcml0ZXJpb24uXG4gIF8uY291bnRCeSA9IGdyb3VwKGZ1bmN0aW9uKHJlc3VsdCwga2V5KSB7XG4gICAgXy5oYXMocmVzdWx0LCBrZXkpID8gcmVzdWx0W2tleV0rKyA6IHJlc3VsdFtrZXldID0gMTtcbiAgfSk7XG5cbiAgLy8gVXNlIGEgY29tcGFyYXRvciBmdW5jdGlvbiB0byBmaWd1cmUgb3V0IHRoZSBzbWFsbGVzdCBpbmRleCBhdCB3aGljaFxuICAvLyBhbiBvYmplY3Qgc2hvdWxkIGJlIGluc2VydGVkIHNvIGFzIHRvIG1haW50YWluIG9yZGVyLiBVc2VzIGJpbmFyeSBzZWFyY2guXG4gIF8uc29ydGVkSW5kZXggPSBmdW5jdGlvbihhcnJheSwgb2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGl0ZXJhdG9yID0gaXRlcmF0b3IgPT0gbnVsbCA/IF8uaWRlbnRpdHkgOiBsb29rdXBJdGVyYXRvcihpdGVyYXRvcik7XG4gICAgdmFyIHZhbHVlID0gaXRlcmF0b3IuY2FsbChjb250ZXh0LCBvYmopO1xuICAgIHZhciBsb3cgPSAwLCBoaWdoID0gYXJyYXkubGVuZ3RoO1xuICAgIHdoaWxlIChsb3cgPCBoaWdoKSB7XG4gICAgICB2YXIgbWlkID0gKGxvdyArIGhpZ2gpID4+PiAxO1xuICAgICAgaXRlcmF0b3IuY2FsbChjb250ZXh0LCBhcnJheVttaWRdKSA8IHZhbHVlID8gbG93ID0gbWlkICsgMSA6IGhpZ2ggPSBtaWQ7XG4gICAgfVxuICAgIHJldHVybiBsb3c7XG4gIH07XG5cbiAgLy8gU2FmZWx5IGNyZWF0ZSBhIHJlYWwsIGxpdmUgYXJyYXkgZnJvbSBhbnl0aGluZyBpdGVyYWJsZS5cbiAgXy50b0FycmF5ID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgaWYgKCFvYmopIHJldHVybiBbXTtcbiAgICBpZiAoXy5pc0FycmF5KG9iaikpIHJldHVybiBzbGljZS5jYWxsKG9iaik7XG4gICAgaWYgKG9iai5sZW5ndGggPT09ICtvYmoubGVuZ3RoKSByZXR1cm4gXy5tYXAob2JqLCBfLmlkZW50aXR5KTtcbiAgICByZXR1cm4gXy52YWx1ZXMob2JqKTtcbiAgfTtcblxuICAvLyBSZXR1cm4gdGhlIG51bWJlciBvZiBlbGVtZW50cyBpbiBhbiBvYmplY3QuXG4gIF8uc2l6ZSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIDA7XG4gICAgcmV0dXJuIChvYmoubGVuZ3RoID09PSArb2JqLmxlbmd0aCkgPyBvYmoubGVuZ3RoIDogXy5rZXlzKG9iaikubGVuZ3RoO1xuICB9O1xuXG4gIC8vIEFycmF5IEZ1bmN0aW9uc1xuICAvLyAtLS0tLS0tLS0tLS0tLS1cblxuICAvLyBHZXQgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYW4gYXJyYXkuIFBhc3NpbmcgKipuKiogd2lsbCByZXR1cm4gdGhlIGZpcnN0IE5cbiAgLy8gdmFsdWVzIGluIHRoZSBhcnJheS4gQWxpYXNlZCBhcyBgaGVhZGAgYW5kIGB0YWtlYC4gVGhlICoqZ3VhcmQqKiBjaGVja1xuICAvLyBhbGxvd3MgaXQgdG8gd29yayB3aXRoIGBfLm1hcGAuXG4gIF8uZmlyc3QgPSBfLmhlYWQgPSBfLnRha2UgPSBmdW5jdGlvbihhcnJheSwgbiwgZ3VhcmQpIHtcbiAgICBpZiAoYXJyYXkgPT0gbnVsbCkgcmV0dXJuIHZvaWQgMDtcbiAgICByZXR1cm4gKG4gPT0gbnVsbCkgfHwgZ3VhcmQgPyBhcnJheVswXSA6IHNsaWNlLmNhbGwoYXJyYXksIDAsIG4pO1xuICB9O1xuXG4gIC8vIFJldHVybnMgZXZlcnl0aGluZyBidXQgdGhlIGxhc3QgZW50cnkgb2YgdGhlIGFycmF5LiBFc3BlY2lhbGx5IHVzZWZ1bCBvblxuICAvLyB0aGUgYXJndW1lbnRzIG9iamVjdC4gUGFzc2luZyAqKm4qKiB3aWxsIHJldHVybiBhbGwgdGhlIHZhbHVlcyBpblxuICAvLyB0aGUgYXJyYXksIGV4Y2x1ZGluZyB0aGUgbGFzdCBOLiBUaGUgKipndWFyZCoqIGNoZWNrIGFsbG93cyBpdCB0byB3b3JrIHdpdGhcbiAgLy8gYF8ubWFwYC5cbiAgXy5pbml0aWFsID0gZnVuY3Rpb24oYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgcmV0dXJuIHNsaWNlLmNhbGwoYXJyYXksIDAsIGFycmF5Lmxlbmd0aCAtICgobiA9PSBudWxsKSB8fCBndWFyZCA/IDEgOiBuKSk7XG4gIH07XG5cbiAgLy8gR2V0IHRoZSBsYXN0IGVsZW1lbnQgb2YgYW4gYXJyYXkuIFBhc3NpbmcgKipuKiogd2lsbCByZXR1cm4gdGhlIGxhc3QgTlxuICAvLyB2YWx1ZXMgaW4gdGhlIGFycmF5LiBUaGUgKipndWFyZCoqIGNoZWNrIGFsbG93cyBpdCB0byB3b3JrIHdpdGggYF8ubWFwYC5cbiAgXy5sYXN0ID0gZnVuY3Rpb24oYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgaWYgKGFycmF5ID09IG51bGwpIHJldHVybiB2b2lkIDA7XG4gICAgaWYgKChuID09IG51bGwpIHx8IGd1YXJkKSB7XG4gICAgICByZXR1cm4gYXJyYXlbYXJyYXkubGVuZ3RoIC0gMV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBzbGljZS5jYWxsKGFycmF5LCBNYXRoLm1heChhcnJheS5sZW5ndGggLSBuLCAwKSk7XG4gICAgfVxuICB9O1xuXG4gIC8vIFJldHVybnMgZXZlcnl0aGluZyBidXQgdGhlIGZpcnN0IGVudHJ5IG9mIHRoZSBhcnJheS4gQWxpYXNlZCBhcyBgdGFpbGAgYW5kIGBkcm9wYC5cbiAgLy8gRXNwZWNpYWxseSB1c2VmdWwgb24gdGhlIGFyZ3VtZW50cyBvYmplY3QuIFBhc3NpbmcgYW4gKipuKiogd2lsbCByZXR1cm5cbiAgLy8gdGhlIHJlc3QgTiB2YWx1ZXMgaW4gdGhlIGFycmF5LiBUaGUgKipndWFyZCoqXG4gIC8vIGNoZWNrIGFsbG93cyBpdCB0byB3b3JrIHdpdGggYF8ubWFwYC5cbiAgXy5yZXN0ID0gXy50YWlsID0gXy5kcm9wID0gZnVuY3Rpb24oYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgcmV0dXJuIHNsaWNlLmNhbGwoYXJyYXksIChuID09IG51bGwpIHx8IGd1YXJkID8gMSA6IG4pO1xuICB9O1xuXG4gIC8vIFRyaW0gb3V0IGFsbCBmYWxzeSB2YWx1ZXMgZnJvbSBhbiBhcnJheS5cbiAgXy5jb21wYWN0ID0gZnVuY3Rpb24oYXJyYXkpIHtcbiAgICByZXR1cm4gXy5maWx0ZXIoYXJyYXksIF8uaWRlbnRpdHkpO1xuICB9O1xuXG4gIC8vIEludGVybmFsIGltcGxlbWVudGF0aW9uIG9mIGEgcmVjdXJzaXZlIGBmbGF0dGVuYCBmdW5jdGlvbi5cbiAgdmFyIGZsYXR0ZW4gPSBmdW5jdGlvbihpbnB1dCwgc2hhbGxvdywgb3V0cHV0KSB7XG4gICAgaWYgKHNoYWxsb3cgJiYgXy5ldmVyeShpbnB1dCwgXy5pc0FycmF5KSkge1xuICAgICAgcmV0dXJuIGNvbmNhdC5hcHBseShvdXRwdXQsIGlucHV0KTtcbiAgICB9XG4gICAgZWFjaChpbnB1dCwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIGlmIChfLmlzQXJyYXkodmFsdWUpIHx8IF8uaXNBcmd1bWVudHModmFsdWUpKSB7XG4gICAgICAgIHNoYWxsb3cgPyBwdXNoLmFwcGx5KG91dHB1dCwgdmFsdWUpIDogZmxhdHRlbih2YWx1ZSwgc2hhbGxvdywgb3V0cHV0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG91dHB1dC5wdXNoKHZhbHVlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gb3V0cHV0O1xuICB9O1xuXG4gIC8vIEZsYXR0ZW4gb3V0IGFuIGFycmF5LCBlaXRoZXIgcmVjdXJzaXZlbHkgKGJ5IGRlZmF1bHQpLCBvciBqdXN0IG9uZSBsZXZlbC5cbiAgXy5mbGF0dGVuID0gZnVuY3Rpb24oYXJyYXksIHNoYWxsb3cpIHtcbiAgICByZXR1cm4gZmxhdHRlbihhcnJheSwgc2hhbGxvdywgW10pO1xuICB9O1xuXG4gIC8vIFJldHVybiBhIHZlcnNpb24gb2YgdGhlIGFycmF5IHRoYXQgZG9lcyBub3QgY29udGFpbiB0aGUgc3BlY2lmaWVkIHZhbHVlKHMpLlxuICBfLndpdGhvdXQgPSBmdW5jdGlvbihhcnJheSkge1xuICAgIHJldHVybiBfLmRpZmZlcmVuY2UoYXJyYXksIHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gIH07XG5cbiAgLy8gUHJvZHVjZSBhIGR1cGxpY2F0ZS1mcmVlIHZlcnNpb24gb2YgdGhlIGFycmF5LiBJZiB0aGUgYXJyYXkgaGFzIGFscmVhZHlcbiAgLy8gYmVlbiBzb3J0ZWQsIHlvdSBoYXZlIHRoZSBvcHRpb24gb2YgdXNpbmcgYSBmYXN0ZXIgYWxnb3JpdGhtLlxuICAvLyBBbGlhc2VkIGFzIGB1bmlxdWVgLlxuICBfLnVuaXEgPSBfLnVuaXF1ZSA9IGZ1bmN0aW9uKGFycmF5LCBpc1NvcnRlZCwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICBpZiAoXy5pc0Z1bmN0aW9uKGlzU29ydGVkKSkge1xuICAgICAgY29udGV4dCA9IGl0ZXJhdG9yO1xuICAgICAgaXRlcmF0b3IgPSBpc1NvcnRlZDtcbiAgICAgIGlzU29ydGVkID0gZmFsc2U7XG4gICAgfVxuICAgIHZhciBpbml0aWFsID0gaXRlcmF0b3IgPyBfLm1hcChhcnJheSwgaXRlcmF0b3IsIGNvbnRleHQpIDogYXJyYXk7XG4gICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICB2YXIgc2VlbiA9IFtdO1xuICAgIGVhY2goaW5pdGlhbCwgZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7XG4gICAgICBpZiAoaXNTb3J0ZWQgPyAoIWluZGV4IHx8IHNlZW5bc2Vlbi5sZW5ndGggLSAxXSAhPT0gdmFsdWUpIDogIV8uY29udGFpbnMoc2VlbiwgdmFsdWUpKSB7XG4gICAgICAgIHNlZW4ucHVzaCh2YWx1ZSk7XG4gICAgICAgIHJlc3VsdHMucHVzaChhcnJheVtpbmRleF0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9O1xuXG4gIC8vIFByb2R1Y2UgYW4gYXJyYXkgdGhhdCBjb250YWlucyB0aGUgdW5pb246IGVhY2ggZGlzdGluY3QgZWxlbWVudCBmcm9tIGFsbCBvZlxuICAvLyB0aGUgcGFzc2VkLWluIGFycmF5cy5cbiAgXy51bmlvbiA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBfLnVuaXEoXy5mbGF0dGVuKGFyZ3VtZW50cywgdHJ1ZSkpO1xuICB9O1xuXG4gIC8vIFByb2R1Y2UgYW4gYXJyYXkgdGhhdCBjb250YWlucyBldmVyeSBpdGVtIHNoYXJlZCBiZXR3ZWVuIGFsbCB0aGVcbiAgLy8gcGFzc2VkLWluIGFycmF5cy5cbiAgXy5pbnRlcnNlY3Rpb24gPSBmdW5jdGlvbihhcnJheSkge1xuICAgIHZhciByZXN0ID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgIHJldHVybiBfLmZpbHRlcihfLnVuaXEoYXJyYXkpLCBmdW5jdGlvbihpdGVtKSB7XG4gICAgICByZXR1cm4gXy5ldmVyeShyZXN0LCBmdW5jdGlvbihvdGhlcikge1xuICAgICAgICByZXR1cm4gXy5pbmRleE9mKG90aGVyLCBpdGVtKSA+PSAwO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgLy8gVGFrZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIG9uZSBhcnJheSBhbmQgYSBudW1iZXIgb2Ygb3RoZXIgYXJyYXlzLlxuICAvLyBPbmx5IHRoZSBlbGVtZW50cyBwcmVzZW50IGluIGp1c3QgdGhlIGZpcnN0IGFycmF5IHdpbGwgcmVtYWluLlxuICBfLmRpZmZlcmVuY2UgPSBmdW5jdGlvbihhcnJheSkge1xuICAgIHZhciByZXN0ID0gY29uY2F0LmFwcGx5KEFycmF5UHJvdG8sIHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gICAgcmV0dXJuIF8uZmlsdGVyKGFycmF5LCBmdW5jdGlvbih2YWx1ZSl7IHJldHVybiAhXy5jb250YWlucyhyZXN0LCB2YWx1ZSk7IH0pO1xuICB9O1xuXG4gIC8vIFppcCB0b2dldGhlciBtdWx0aXBsZSBsaXN0cyBpbnRvIGEgc2luZ2xlIGFycmF5IC0tIGVsZW1lbnRzIHRoYXQgc2hhcmVcbiAgLy8gYW4gaW5kZXggZ28gdG9nZXRoZXIuXG4gIF8uemlwID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGxlbmd0aCA9IF8ubWF4KF8ucGx1Y2soYXJndW1lbnRzLCBcImxlbmd0aFwiKS5jb25jYXQoMCkpO1xuICAgIHZhciByZXN1bHRzID0gbmV3IEFycmF5KGxlbmd0aCk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgcmVzdWx0c1tpXSA9IF8ucGx1Y2soYXJndW1lbnRzLCAnJyArIGkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfTtcblxuICAvLyBDb252ZXJ0cyBsaXN0cyBpbnRvIG9iamVjdHMuIFBhc3MgZWl0aGVyIGEgc2luZ2xlIGFycmF5IG9mIGBba2V5LCB2YWx1ZV1gXG4gIC8vIHBhaXJzLCBvciB0d28gcGFyYWxsZWwgYXJyYXlzIG9mIHRoZSBzYW1lIGxlbmd0aCAtLSBvbmUgb2Yga2V5cywgYW5kIG9uZSBvZlxuICAvLyB0aGUgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gIF8ub2JqZWN0ID0gZnVuY3Rpb24obGlzdCwgdmFsdWVzKSB7XG4gICAgaWYgKGxpc3QgPT0gbnVsbCkgcmV0dXJuIHt9O1xuICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gbGlzdC5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHZhbHVlcykge1xuICAgICAgICByZXN1bHRbbGlzdFtpXV0gPSB2YWx1ZXNbaV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHRbbGlzdFtpXVswXV0gPSBsaXN0W2ldWzFdO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIElmIHRoZSBicm93c2VyIGRvZXNuJ3Qgc3VwcGx5IHVzIHdpdGggaW5kZXhPZiAoSSdtIGxvb2tpbmcgYXQgeW91LCAqKk1TSUUqKiksXG4gIC8vIHdlIG5lZWQgdGhpcyBmdW5jdGlvbi4gUmV0dXJuIHRoZSBwb3NpdGlvbiBvZiB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiBhblxuICAvLyBpdGVtIGluIGFuIGFycmF5LCBvciAtMSBpZiB0aGUgaXRlbSBpcyBub3QgaW5jbHVkZWQgaW4gdGhlIGFycmF5LlxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgaW5kZXhPZmAgaWYgYXZhaWxhYmxlLlxuICAvLyBJZiB0aGUgYXJyYXkgaXMgbGFyZ2UgYW5kIGFscmVhZHkgaW4gc29ydCBvcmRlciwgcGFzcyBgdHJ1ZWBcbiAgLy8gZm9yICoqaXNTb3J0ZWQqKiB0byB1c2UgYmluYXJ5IHNlYXJjaC5cbiAgXy5pbmRleE9mID0gZnVuY3Rpb24oYXJyYXksIGl0ZW0sIGlzU29ydGVkKSB7XG4gICAgaWYgKGFycmF5ID09IG51bGwpIHJldHVybiAtMTtcbiAgICB2YXIgaSA9IDAsIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcbiAgICBpZiAoaXNTb3J0ZWQpIHtcbiAgICAgIGlmICh0eXBlb2YgaXNTb3J0ZWQgPT0gJ251bWJlcicpIHtcbiAgICAgICAgaSA9IChpc1NvcnRlZCA8IDAgPyBNYXRoLm1heCgwLCBsZW5ndGggKyBpc1NvcnRlZCkgOiBpc1NvcnRlZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpID0gXy5zb3J0ZWRJbmRleChhcnJheSwgaXRlbSk7XG4gICAgICAgIHJldHVybiBhcnJheVtpXSA9PT0gaXRlbSA/IGkgOiAtMTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG5hdGl2ZUluZGV4T2YgJiYgYXJyYXkuaW5kZXhPZiA9PT0gbmF0aXZlSW5kZXhPZikgcmV0dXJuIGFycmF5LmluZGV4T2YoaXRlbSwgaXNTb3J0ZWQpO1xuICAgIGZvciAoOyBpIDwgbGVuZ3RoOyBpKyspIGlmIChhcnJheVtpXSA9PT0gaXRlbSkgcmV0dXJuIGk7XG4gICAgcmV0dXJuIC0xO1xuICB9O1xuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBsYXN0SW5kZXhPZmAgaWYgYXZhaWxhYmxlLlxuICBfLmxhc3RJbmRleE9mID0gZnVuY3Rpb24oYXJyYXksIGl0ZW0sIGZyb20pIHtcbiAgICBpZiAoYXJyYXkgPT0gbnVsbCkgcmV0dXJuIC0xO1xuICAgIHZhciBoYXNJbmRleCA9IGZyb20gIT0gbnVsbDtcbiAgICBpZiAobmF0aXZlTGFzdEluZGV4T2YgJiYgYXJyYXkubGFzdEluZGV4T2YgPT09IG5hdGl2ZUxhc3RJbmRleE9mKSB7XG4gICAgICByZXR1cm4gaGFzSW5kZXggPyBhcnJheS5sYXN0SW5kZXhPZihpdGVtLCBmcm9tKSA6IGFycmF5Lmxhc3RJbmRleE9mKGl0ZW0pO1xuICAgIH1cbiAgICB2YXIgaSA9IChoYXNJbmRleCA/IGZyb20gOiBhcnJheS5sZW5ndGgpO1xuICAgIHdoaWxlIChpLS0pIGlmIChhcnJheVtpXSA9PT0gaXRlbSkgcmV0dXJuIGk7XG4gICAgcmV0dXJuIC0xO1xuICB9O1xuXG4gIC8vIEdlbmVyYXRlIGFuIGludGVnZXIgQXJyYXkgY29udGFpbmluZyBhbiBhcml0aG1ldGljIHByb2dyZXNzaW9uLiBBIHBvcnQgb2ZcbiAgLy8gdGhlIG5hdGl2ZSBQeXRob24gYHJhbmdlKClgIGZ1bmN0aW9uLiBTZWVcbiAgLy8gW3RoZSBQeXRob24gZG9jdW1lbnRhdGlvbl0oaHR0cDovL2RvY3MucHl0aG9uLm9yZy9saWJyYXJ5L2Z1bmN0aW9ucy5odG1sI3JhbmdlKS5cbiAgXy5yYW5nZSA9IGZ1bmN0aW9uKHN0YXJ0LCBzdG9wLCBzdGVwKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPD0gMSkge1xuICAgICAgc3RvcCA9IHN0YXJ0IHx8IDA7XG4gICAgICBzdGFydCA9IDA7XG4gICAgfVxuICAgIHN0ZXAgPSBhcmd1bWVudHNbMl0gfHwgMTtcblxuICAgIHZhciBsZW5ndGggPSBNYXRoLm1heChNYXRoLmNlaWwoKHN0b3AgLSBzdGFydCkgLyBzdGVwKSwgMCk7XG4gICAgdmFyIGlkeCA9IDA7XG4gICAgdmFyIHJhbmdlID0gbmV3IEFycmF5KGxlbmd0aCk7XG5cbiAgICB3aGlsZShpZHggPCBsZW5ndGgpIHtcbiAgICAgIHJhbmdlW2lkeCsrXSA9IHN0YXJ0O1xuICAgICAgc3RhcnQgKz0gc3RlcDtcbiAgICB9XG5cbiAgICByZXR1cm4gcmFuZ2U7XG4gIH07XG5cbiAgLy8gRnVuY3Rpb24gKGFoZW0pIEZ1bmN0aW9uc1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvLyBSZXVzYWJsZSBjb25zdHJ1Y3RvciBmdW5jdGlvbiBmb3IgcHJvdG90eXBlIHNldHRpbmcuXG4gIHZhciBjdG9yID0gZnVuY3Rpb24oKXt9O1xuXG4gIC8vIENyZWF0ZSBhIGZ1bmN0aW9uIGJvdW5kIHRvIGEgZ2l2ZW4gb2JqZWN0IChhc3NpZ25pbmcgYHRoaXNgLCBhbmQgYXJndW1lbnRzLFxuICAvLyBvcHRpb25hbGx5KS4gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYEZ1bmN0aW9uLmJpbmRgIGlmXG4gIC8vIGF2YWlsYWJsZS5cbiAgXy5iaW5kID0gZnVuY3Rpb24oZnVuYywgY29udGV4dCkge1xuICAgIHZhciBhcmdzLCBib3VuZDtcbiAgICBpZiAobmF0aXZlQmluZCAmJiBmdW5jLmJpbmQgPT09IG5hdGl2ZUJpbmQpIHJldHVybiBuYXRpdmVCaW5kLmFwcGx5KGZ1bmMsIHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gICAgaWYgKCFfLmlzRnVuY3Rpb24oZnVuYykpIHRocm93IG5ldyBUeXBlRXJyb3I7XG4gICAgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcbiAgICByZXR1cm4gYm91bmQgPSBmdW5jdGlvbigpIHtcbiAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBib3VuZCkpIHJldHVybiBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MuY29uY2F0KHNsaWNlLmNhbGwoYXJndW1lbnRzKSkpO1xuICAgICAgY3Rvci5wcm90b3R5cGUgPSBmdW5jLnByb3RvdHlwZTtcbiAgICAgIHZhciBzZWxmID0gbmV3IGN0b3I7XG4gICAgICBjdG9yLnByb3RvdHlwZSA9IG51bGw7XG4gICAgICB2YXIgcmVzdWx0ID0gZnVuYy5hcHBseShzZWxmLCBhcmdzLmNvbmNhdChzbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgIGlmIChPYmplY3QocmVzdWx0KSA9PT0gcmVzdWx0KSByZXR1cm4gcmVzdWx0O1xuICAgICAgcmV0dXJuIHNlbGY7XG4gICAgfTtcbiAgfTtcblxuICAvLyBQYXJ0aWFsbHkgYXBwbHkgYSBmdW5jdGlvbiBieSBjcmVhdGluZyBhIHZlcnNpb24gdGhhdCBoYXMgaGFkIHNvbWUgb2YgaXRzXG4gIC8vIGFyZ3VtZW50cyBwcmUtZmlsbGVkLCB3aXRob3V0IGNoYW5naW5nIGl0cyBkeW5hbWljIGB0aGlzYCBjb250ZXh0LlxuICBfLnBhcnRpYWwgPSBmdW5jdGlvbihmdW5jKSB7XG4gICAgdmFyIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkodGhpcywgYXJncy5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMpKSk7XG4gICAgfTtcbiAgfTtcblxuICAvLyBCaW5kIGFsbCBvZiBhbiBvYmplY3QncyBtZXRob2RzIHRvIHRoYXQgb2JqZWN0LiBVc2VmdWwgZm9yIGVuc3VyaW5nIHRoYXRcbiAgLy8gYWxsIGNhbGxiYWNrcyBkZWZpbmVkIG9uIGFuIG9iamVjdCBiZWxvbmcgdG8gaXQuXG4gIF8uYmluZEFsbCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBmdW5jcyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICBpZiAoZnVuY3MubGVuZ3RoID09PSAwKSB0aHJvdyBuZXcgRXJyb3IoXCJiaW5kQWxsIG11c3QgYmUgcGFzc2VkIGZ1bmN0aW9uIG5hbWVzXCIpO1xuICAgIGVhY2goZnVuY3MsIGZ1bmN0aW9uKGYpIHsgb2JqW2ZdID0gXy5iaW5kKG9ialtmXSwgb2JqKTsgfSk7XG4gICAgcmV0dXJuIG9iajtcbiAgfTtcblxuICAvLyBNZW1vaXplIGFuIGV4cGVuc2l2ZSBmdW5jdGlvbiBieSBzdG9yaW5nIGl0cyByZXN1bHRzLlxuICBfLm1lbW9pemUgPSBmdW5jdGlvbihmdW5jLCBoYXNoZXIpIHtcbiAgICB2YXIgbWVtbyA9IHt9O1xuICAgIGhhc2hlciB8fCAoaGFzaGVyID0gXy5pZGVudGl0eSk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGtleSA9IGhhc2hlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgcmV0dXJuIF8uaGFzKG1lbW8sIGtleSkgPyBtZW1vW2tleV0gOiAobWVtb1trZXldID0gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpKTtcbiAgICB9O1xuICB9O1xuXG4gIC8vIERlbGF5cyBhIGZ1bmN0aW9uIGZvciB0aGUgZ2l2ZW4gbnVtYmVyIG9mIG1pbGxpc2Vjb25kcywgYW5kIHRoZW4gY2FsbHNcbiAgLy8gaXQgd2l0aCB0aGUgYXJndW1lbnRzIHN1cHBsaWVkLlxuICBfLmRlbGF5ID0gZnVuY3Rpb24oZnVuYywgd2FpdCkge1xuICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICAgIHJldHVybiBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7IHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGFyZ3MpOyB9LCB3YWl0KTtcbiAgfTtcblxuICAvLyBEZWZlcnMgYSBmdW5jdGlvbiwgc2NoZWR1bGluZyBpdCB0byBydW4gYWZ0ZXIgdGhlIGN1cnJlbnQgY2FsbCBzdGFjayBoYXNcbiAgLy8gY2xlYXJlZC5cbiAgXy5kZWZlciA9IGZ1bmN0aW9uKGZ1bmMpIHtcbiAgICByZXR1cm4gXy5kZWxheS5hcHBseShfLCBbZnVuYywgMV0uY29uY2F0KHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSkpO1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiwgdGhhdCwgd2hlbiBpbnZva2VkLCB3aWxsIG9ubHkgYmUgdHJpZ2dlcmVkIGF0IG1vc3Qgb25jZVxuICAvLyBkdXJpbmcgYSBnaXZlbiB3aW5kb3cgb2YgdGltZS4gTm9ybWFsbHksIHRoZSB0aHJvdHRsZWQgZnVuY3Rpb24gd2lsbCBydW5cbiAgLy8gYXMgbXVjaCBhcyBpdCBjYW4sIHdpdGhvdXQgZXZlciBnb2luZyBtb3JlIHRoYW4gb25jZSBwZXIgYHdhaXRgIGR1cmF0aW9uO1xuICAvLyBidXQgaWYgeW91J2QgbGlrZSB0byBkaXNhYmxlIHRoZSBleGVjdXRpb24gb24gdGhlIGxlYWRpbmcgZWRnZSwgcGFzc1xuICAvLyBge2xlYWRpbmc6IGZhbHNlfWAuIFRvIGRpc2FibGUgZXhlY3V0aW9uIG9uIHRoZSB0cmFpbGluZyBlZGdlLCBkaXR0by5cbiAgXy50aHJvdHRsZSA9IGZ1bmN0aW9uKGZ1bmMsIHdhaXQsIG9wdGlvbnMpIHtcbiAgICB2YXIgY29udGV4dCwgYXJncywgcmVzdWx0O1xuICAgIHZhciB0aW1lb3V0ID0gbnVsbDtcbiAgICB2YXIgcHJldmlvdXMgPSAwO1xuICAgIG9wdGlvbnMgfHwgKG9wdGlvbnMgPSB7fSk7XG4gICAgdmFyIGxhdGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICBwcmV2aW91cyA9IG9wdGlvbnMubGVhZGluZyA9PT0gZmFsc2UgPyAwIDogbmV3IERhdGU7XG4gICAgICB0aW1lb3V0ID0gbnVsbDtcbiAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbm93ID0gbmV3IERhdGU7XG4gICAgICBpZiAoIXByZXZpb3VzICYmIG9wdGlvbnMubGVhZGluZyA9PT0gZmFsc2UpIHByZXZpb3VzID0gbm93O1xuICAgICAgdmFyIHJlbWFpbmluZyA9IHdhaXQgLSAobm93IC0gcHJldmlvdXMpO1xuICAgICAgY29udGV4dCA9IHRoaXM7XG4gICAgICBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgaWYgKHJlbWFpbmluZyA8PSAwKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgdGltZW91dCA9IG51bGw7XG4gICAgICAgIHByZXZpb3VzID0gbm93O1xuICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgfSBlbHNlIGlmICghdGltZW91dCAmJiBvcHRpb25zLnRyYWlsaW5nICE9PSBmYWxzZSkge1xuICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgcmVtYWluaW5nKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24sIHRoYXQsIGFzIGxvbmcgYXMgaXQgY29udGludWVzIHRvIGJlIGludm9rZWQsIHdpbGwgbm90XG4gIC8vIGJlIHRyaWdnZXJlZC4gVGhlIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIGFmdGVyIGl0IHN0b3BzIGJlaW5nIGNhbGxlZCBmb3JcbiAgLy8gTiBtaWxsaXNlY29uZHMuIElmIGBpbW1lZGlhdGVgIGlzIHBhc3NlZCwgdHJpZ2dlciB0aGUgZnVuY3Rpb24gb24gdGhlXG4gIC8vIGxlYWRpbmcgZWRnZSwgaW5zdGVhZCBvZiB0aGUgdHJhaWxpbmcuXG4gIF8uZGVib3VuY2UgPSBmdW5jdGlvbihmdW5jLCB3YWl0LCBpbW1lZGlhdGUpIHtcbiAgICB2YXIgdGltZW91dCwgYXJncywgY29udGV4dCwgdGltZXN0YW1wLCByZXN1bHQ7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgY29udGV4dCA9IHRoaXM7XG4gICAgICBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgdGltZXN0YW1wID0gbmV3IERhdGUoKTtcbiAgICAgIHZhciBsYXRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgbGFzdCA9IChuZXcgRGF0ZSgpKSAtIHRpbWVzdGFtcDtcbiAgICAgICAgaWYgKGxhc3QgPCB3YWl0KSB7XG4gICAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHdhaXQgLSBsYXN0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aW1lb3V0ID0gbnVsbDtcbiAgICAgICAgICBpZiAoIWltbWVkaWF0ZSkgcmVzdWx0ID0gZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIHZhciBjYWxsTm93ID0gaW1tZWRpYXRlICYmICF0aW1lb3V0O1xuICAgICAgaWYgKCF0aW1lb3V0KSB7XG4gICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGxhdGVyLCB3YWl0KTtcbiAgICAgIH1cbiAgICAgIGlmIChjYWxsTm93KSByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgZXhlY3V0ZWQgYXQgbW9zdCBvbmUgdGltZSwgbm8gbWF0dGVyIGhvd1xuICAvLyBvZnRlbiB5b3UgY2FsbCBpdC4gVXNlZnVsIGZvciBsYXp5IGluaXRpYWxpemF0aW9uLlxuICBfLm9uY2UgPSBmdW5jdGlvbihmdW5jKSB7XG4gICAgdmFyIHJhbiA9IGZhbHNlLCBtZW1vO1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIGlmIChyYW4pIHJldHVybiBtZW1vO1xuICAgICAgcmFuID0gdHJ1ZTtcbiAgICAgIG1lbW8gPSBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICBmdW5jID0gbnVsbDtcbiAgICAgIHJldHVybiBtZW1vO1xuICAgIH07XG4gIH07XG5cbiAgLy8gUmV0dXJucyB0aGUgZmlyc3QgZnVuY3Rpb24gcGFzc2VkIGFzIGFuIGFyZ3VtZW50IHRvIHRoZSBzZWNvbmQsXG4gIC8vIGFsbG93aW5nIHlvdSB0byBhZGp1c3QgYXJndW1lbnRzLCBydW4gY29kZSBiZWZvcmUgYW5kIGFmdGVyLCBhbmRcbiAgLy8gY29uZGl0aW9uYWxseSBleGVjdXRlIHRoZSBvcmlnaW5hbCBmdW5jdGlvbi5cbiAgXy53cmFwID0gZnVuY3Rpb24oZnVuYywgd3JhcHBlcikge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBhcmdzID0gW2Z1bmNdO1xuICAgICAgcHVzaC5hcHBseShhcmdzLCBhcmd1bWVudHMpO1xuICAgICAgcmV0dXJuIHdyYXBwZXIuYXBwbHkodGhpcywgYXJncyk7XG4gICAgfTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCBpcyB0aGUgY29tcG9zaXRpb24gb2YgYSBsaXN0IG9mIGZ1bmN0aW9ucywgZWFjaFxuICAvLyBjb25zdW1pbmcgdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgZnVuY3Rpb24gdGhhdCBmb2xsb3dzLlxuICBfLmNvbXBvc2UgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZnVuY3MgPSBhcmd1bWVudHM7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICBmb3IgKHZhciBpID0gZnVuY3MubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYXJncyA9IFtmdW5jc1tpXS5hcHBseSh0aGlzLCBhcmdzKV07XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJnc1swXTtcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiB0aGF0IHdpbGwgb25seSBiZSBleGVjdXRlZCBhZnRlciBiZWluZyBjYWxsZWQgTiB0aW1lcy5cbiAgXy5hZnRlciA9IGZ1bmN0aW9uKHRpbWVzLCBmdW5jKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKC0tdGltZXMgPCAxKSB7XG4gICAgICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB9XG4gICAgfTtcbiAgfTtcblxuICAvLyBPYmplY3QgRnVuY3Rpb25zXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS1cblxuICAvLyBSZXRyaWV2ZSB0aGUgbmFtZXMgb2YgYW4gb2JqZWN0J3MgcHJvcGVydGllcy5cbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYE9iamVjdC5rZXlzYFxuICBfLmtleXMgPSBuYXRpdmVLZXlzIHx8IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmIChvYmogIT09IE9iamVjdChvYmopKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdJbnZhbGlkIG9iamVjdCcpO1xuICAgIHZhciBrZXlzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikgaWYgKF8uaGFzKG9iaiwga2V5KSkga2V5cy5wdXNoKGtleSk7XG4gICAgcmV0dXJuIGtleXM7XG4gIH07XG5cbiAgLy8gUmV0cmlldmUgdGhlIHZhbHVlcyBvZiBhbiBvYmplY3QncyBwcm9wZXJ0aWVzLlxuICBfLnZhbHVlcyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XG4gICAgdmFyIGxlbmd0aCA9IGtleXMubGVuZ3RoO1xuICAgIHZhciB2YWx1ZXMgPSBuZXcgQXJyYXkobGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICB2YWx1ZXNbaV0gPSBvYmpba2V5c1tpXV07XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZXM7XG4gIH07XG5cbiAgLy8gQ29udmVydCBhbiBvYmplY3QgaW50byBhIGxpc3Qgb2YgYFtrZXksIHZhbHVlXWAgcGFpcnMuXG4gIF8ucGFpcnMgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopO1xuICAgIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgICB2YXIgcGFpcnMgPSBuZXcgQXJyYXkobGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBwYWlyc1tpXSA9IFtrZXlzW2ldLCBvYmpba2V5c1tpXV1dO1xuICAgIH1cbiAgICByZXR1cm4gcGFpcnM7XG4gIH07XG5cbiAgLy8gSW52ZXJ0IHRoZSBrZXlzIGFuZCB2YWx1ZXMgb2YgYW4gb2JqZWN0LiBUaGUgdmFsdWVzIG11c3QgYmUgc2VyaWFsaXphYmxlLlxuICBfLmludmVydCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopO1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBrZXlzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICByZXN1bHRbb2JqW2tleXNbaV1dXSA9IGtleXNbaV07XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gUmV0dXJuIGEgc29ydGVkIGxpc3Qgb2YgdGhlIGZ1bmN0aW9uIG5hbWVzIGF2YWlsYWJsZSBvbiB0aGUgb2JqZWN0LlxuICAvLyBBbGlhc2VkIGFzIGBtZXRob2RzYFxuICBfLmZ1bmN0aW9ucyA9IF8ubWV0aG9kcyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBuYW1lcyA9IFtdO1xuICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgIGlmIChfLmlzRnVuY3Rpb24ob2JqW2tleV0pKSBuYW1lcy5wdXNoKGtleSk7XG4gICAgfVxuICAgIHJldHVybiBuYW1lcy5zb3J0KCk7XG4gIH07XG5cbiAgLy8gRXh0ZW5kIGEgZ2l2ZW4gb2JqZWN0IHdpdGggYWxsIHRoZSBwcm9wZXJ0aWVzIGluIHBhc3NlZC1pbiBvYmplY3QocykuXG4gIF8uZXh0ZW5kID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgZWFjaChzbGljZS5jYWxsKGFyZ3VtZW50cywgMSksIGZ1bmN0aW9uKHNvdXJjZSkge1xuICAgICAgaWYgKHNvdXJjZSkge1xuICAgICAgICBmb3IgKHZhciBwcm9wIGluIHNvdXJjZSkge1xuICAgICAgICAgIG9ialtwcm9wXSA9IHNvdXJjZVtwcm9wXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBvYmo7XG4gIH07XG5cbiAgLy8gUmV0dXJuIGEgY29weSBvZiB0aGUgb2JqZWN0IG9ubHkgY29udGFpbmluZyB0aGUgd2hpdGVsaXN0ZWQgcHJvcGVydGllcy5cbiAgXy5waWNrID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIGNvcHkgPSB7fTtcbiAgICB2YXIga2V5cyA9IGNvbmNhdC5hcHBseShBcnJheVByb3RvLCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICAgIGVhY2goa2V5cywgZnVuY3Rpb24oa2V5KSB7XG4gICAgICBpZiAoa2V5IGluIG9iaikgY29weVtrZXldID0gb2JqW2tleV07XG4gICAgfSk7XG4gICAgcmV0dXJuIGNvcHk7XG4gIH07XG5cbiAgIC8vIFJldHVybiBhIGNvcHkgb2YgdGhlIG9iamVjdCB3aXRob3V0IHRoZSBibGFja2xpc3RlZCBwcm9wZXJ0aWVzLlxuICBfLm9taXQgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgY29weSA9IHt9O1xuICAgIHZhciBrZXlzID0gY29uY2F0LmFwcGx5KEFycmF5UHJvdG8sIHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgaWYgKCFfLmNvbnRhaW5zKGtleXMsIGtleSkpIGNvcHlba2V5XSA9IG9ialtrZXldO1xuICAgIH1cbiAgICByZXR1cm4gY29weTtcbiAgfTtcblxuICAvLyBGaWxsIGluIGEgZ2l2ZW4gb2JqZWN0IHdpdGggZGVmYXVsdCBwcm9wZXJ0aWVzLlxuICBfLmRlZmF1bHRzID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgZWFjaChzbGljZS5jYWxsKGFyZ3VtZW50cywgMSksIGZ1bmN0aW9uKHNvdXJjZSkge1xuICAgICAgaWYgKHNvdXJjZSkge1xuICAgICAgICBmb3IgKHZhciBwcm9wIGluIHNvdXJjZSkge1xuICAgICAgICAgIGlmIChvYmpbcHJvcF0gPT09IHZvaWQgMCkgb2JqW3Byb3BdID0gc291cmNlW3Byb3BdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIG9iajtcbiAgfTtcblxuICAvLyBDcmVhdGUgYSAoc2hhbGxvdy1jbG9uZWQpIGR1cGxpY2F0ZSBvZiBhbiBvYmplY3QuXG4gIF8uY2xvbmUgPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAoIV8uaXNPYmplY3Qob2JqKSkgcmV0dXJuIG9iajtcbiAgICByZXR1cm4gXy5pc0FycmF5KG9iaikgPyBvYmouc2xpY2UoKSA6IF8uZXh0ZW5kKHt9LCBvYmopO1xuICB9O1xuXG4gIC8vIEludm9rZXMgaW50ZXJjZXB0b3Igd2l0aCB0aGUgb2JqLCBhbmQgdGhlbiByZXR1cm5zIG9iai5cbiAgLy8gVGhlIHByaW1hcnkgcHVycG9zZSBvZiB0aGlzIG1ldGhvZCBpcyB0byBcInRhcCBpbnRvXCIgYSBtZXRob2QgY2hhaW4sIGluXG4gIC8vIG9yZGVyIHRvIHBlcmZvcm0gb3BlcmF0aW9ucyBvbiBpbnRlcm1lZGlhdGUgcmVzdWx0cyB3aXRoaW4gdGhlIGNoYWluLlxuICBfLnRhcCA9IGZ1bmN0aW9uKG9iaiwgaW50ZXJjZXB0b3IpIHtcbiAgICBpbnRlcmNlcHRvcihvYmopO1xuICAgIHJldHVybiBvYmo7XG4gIH07XG5cbiAgLy8gSW50ZXJuYWwgcmVjdXJzaXZlIGNvbXBhcmlzb24gZnVuY3Rpb24gZm9yIGBpc0VxdWFsYC5cbiAgdmFyIGVxID0gZnVuY3Rpb24oYSwgYiwgYVN0YWNrLCBiU3RhY2spIHtcbiAgICAvLyBJZGVudGljYWwgb2JqZWN0cyBhcmUgZXF1YWwuIGAwID09PSAtMGAsIGJ1dCB0aGV5IGFyZW4ndCBpZGVudGljYWwuXG4gICAgLy8gU2VlIHRoZSBbSGFybW9ueSBgZWdhbGAgcHJvcG9zYWxdKGh0dHA6Ly93aWtpLmVjbWFzY3JpcHQub3JnL2Rva3UucGhwP2lkPWhhcm1vbnk6ZWdhbCkuXG4gICAgaWYgKGEgPT09IGIpIHJldHVybiBhICE9PSAwIHx8IDEgLyBhID09IDEgLyBiO1xuICAgIC8vIEEgc3RyaWN0IGNvbXBhcmlzb24gaXMgbmVjZXNzYXJ5IGJlY2F1c2UgYG51bGwgPT0gdW5kZWZpbmVkYC5cbiAgICBpZiAoYSA9PSBudWxsIHx8IGIgPT0gbnVsbCkgcmV0dXJuIGEgPT09IGI7XG4gICAgLy8gVW53cmFwIGFueSB3cmFwcGVkIG9iamVjdHMuXG4gICAgaWYgKGEgaW5zdGFuY2VvZiBfKSBhID0gYS5fd3JhcHBlZDtcbiAgICBpZiAoYiBpbnN0YW5jZW9mIF8pIGIgPSBiLl93cmFwcGVkO1xuICAgIC8vIENvbXBhcmUgYFtbQ2xhc3NdXWAgbmFtZXMuXG4gICAgdmFyIGNsYXNzTmFtZSA9IHRvU3RyaW5nLmNhbGwoYSk7XG4gICAgaWYgKGNsYXNzTmFtZSAhPSB0b1N0cmluZy5jYWxsKGIpKSByZXR1cm4gZmFsc2U7XG4gICAgc3dpdGNoIChjbGFzc05hbWUpIHtcbiAgICAgIC8vIFN0cmluZ3MsIG51bWJlcnMsIGRhdGVzLCBhbmQgYm9vbGVhbnMgYXJlIGNvbXBhcmVkIGJ5IHZhbHVlLlxuICAgICAgY2FzZSAnW29iamVjdCBTdHJpbmddJzpcbiAgICAgICAgLy8gUHJpbWl0aXZlcyBhbmQgdGhlaXIgY29ycmVzcG9uZGluZyBvYmplY3Qgd3JhcHBlcnMgYXJlIGVxdWl2YWxlbnQ7IHRodXMsIGBcIjVcImAgaXNcbiAgICAgICAgLy8gZXF1aXZhbGVudCB0byBgbmV3IFN0cmluZyhcIjVcIilgLlxuICAgICAgICByZXR1cm4gYSA9PSBTdHJpbmcoYik7XG4gICAgICBjYXNlICdbb2JqZWN0IE51bWJlcl0nOlxuICAgICAgICAvLyBgTmFOYHMgYXJlIGVxdWl2YWxlbnQsIGJ1dCBub24tcmVmbGV4aXZlLiBBbiBgZWdhbGAgY29tcGFyaXNvbiBpcyBwZXJmb3JtZWQgZm9yXG4gICAgICAgIC8vIG90aGVyIG51bWVyaWMgdmFsdWVzLlxuICAgICAgICByZXR1cm4gYSAhPSArYSA/IGIgIT0gK2IgOiAoYSA9PSAwID8gMSAvIGEgPT0gMSAvIGIgOiBhID09ICtiKTtcbiAgICAgIGNhc2UgJ1tvYmplY3QgRGF0ZV0nOlxuICAgICAgY2FzZSAnW29iamVjdCBCb29sZWFuXSc6XG4gICAgICAgIC8vIENvZXJjZSBkYXRlcyBhbmQgYm9vbGVhbnMgdG8gbnVtZXJpYyBwcmltaXRpdmUgdmFsdWVzLiBEYXRlcyBhcmUgY29tcGFyZWQgYnkgdGhlaXJcbiAgICAgICAgLy8gbWlsbGlzZWNvbmQgcmVwcmVzZW50YXRpb25zLiBOb3RlIHRoYXQgaW52YWxpZCBkYXRlcyB3aXRoIG1pbGxpc2Vjb25kIHJlcHJlc2VudGF0aW9uc1xuICAgICAgICAvLyBvZiBgTmFOYCBhcmUgbm90IGVxdWl2YWxlbnQuXG4gICAgICAgIHJldHVybiArYSA9PSArYjtcbiAgICAgIC8vIFJlZ0V4cHMgYXJlIGNvbXBhcmVkIGJ5IHRoZWlyIHNvdXJjZSBwYXR0ZXJucyBhbmQgZmxhZ3MuXG4gICAgICBjYXNlICdbb2JqZWN0IFJlZ0V4cF0nOlxuICAgICAgICByZXR1cm4gYS5zb3VyY2UgPT0gYi5zb3VyY2UgJiZcbiAgICAgICAgICAgICAgIGEuZ2xvYmFsID09IGIuZ2xvYmFsICYmXG4gICAgICAgICAgICAgICBhLm11bHRpbGluZSA9PSBiLm11bHRpbGluZSAmJlxuICAgICAgICAgICAgICAgYS5pZ25vcmVDYXNlID09IGIuaWdub3JlQ2FzZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBhICE9ICdvYmplY3QnIHx8IHR5cGVvZiBiICE9ICdvYmplY3QnKSByZXR1cm4gZmFsc2U7XG4gICAgLy8gQXNzdW1lIGVxdWFsaXR5IGZvciBjeWNsaWMgc3RydWN0dXJlcy4gVGhlIGFsZ29yaXRobSBmb3IgZGV0ZWN0aW5nIGN5Y2xpY1xuICAgIC8vIHN0cnVjdHVyZXMgaXMgYWRhcHRlZCBmcm9tIEVTIDUuMSBzZWN0aW9uIDE1LjEyLjMsIGFic3RyYWN0IG9wZXJhdGlvbiBgSk9gLlxuICAgIHZhciBsZW5ndGggPSBhU3RhY2subGVuZ3RoO1xuICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgLy8gTGluZWFyIHNlYXJjaC4gUGVyZm9ybWFuY2UgaXMgaW52ZXJzZWx5IHByb3BvcnRpb25hbCB0byB0aGUgbnVtYmVyIG9mXG4gICAgICAvLyB1bmlxdWUgbmVzdGVkIHN0cnVjdHVyZXMuXG4gICAgICBpZiAoYVN0YWNrW2xlbmd0aF0gPT0gYSkgcmV0dXJuIGJTdGFja1tsZW5ndGhdID09IGI7XG4gICAgfVxuICAgIC8vIE9iamVjdHMgd2l0aCBkaWZmZXJlbnQgY29uc3RydWN0b3JzIGFyZSBub3QgZXF1aXZhbGVudCwgYnV0IGBPYmplY3Rgc1xuICAgIC8vIGZyb20gZGlmZmVyZW50IGZyYW1lcyBhcmUuXG4gICAgdmFyIGFDdG9yID0gYS5jb25zdHJ1Y3RvciwgYkN0b3IgPSBiLmNvbnN0cnVjdG9yO1xuICAgIGlmIChhQ3RvciAhPT0gYkN0b3IgJiYgIShfLmlzRnVuY3Rpb24oYUN0b3IpICYmIChhQ3RvciBpbnN0YW5jZW9mIGFDdG9yKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfLmlzRnVuY3Rpb24oYkN0b3IpICYmIChiQ3RvciBpbnN0YW5jZW9mIGJDdG9yKSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgLy8gQWRkIHRoZSBmaXJzdCBvYmplY3QgdG8gdGhlIHN0YWNrIG9mIHRyYXZlcnNlZCBvYmplY3RzLlxuICAgIGFTdGFjay5wdXNoKGEpO1xuICAgIGJTdGFjay5wdXNoKGIpO1xuICAgIHZhciBzaXplID0gMCwgcmVzdWx0ID0gdHJ1ZTtcbiAgICAvLyBSZWN1cnNpdmVseSBjb21wYXJlIG9iamVjdHMgYW5kIGFycmF5cy5cbiAgICBpZiAoY2xhc3NOYW1lID09ICdbb2JqZWN0IEFycmF5XScpIHtcbiAgICAgIC8vIENvbXBhcmUgYXJyYXkgbGVuZ3RocyB0byBkZXRlcm1pbmUgaWYgYSBkZWVwIGNvbXBhcmlzb24gaXMgbmVjZXNzYXJ5LlxuICAgICAgc2l6ZSA9IGEubGVuZ3RoO1xuICAgICAgcmVzdWx0ID0gc2l6ZSA9PSBiLmxlbmd0aDtcbiAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgLy8gRGVlcCBjb21wYXJlIHRoZSBjb250ZW50cywgaWdub3Jpbmcgbm9uLW51bWVyaWMgcHJvcGVydGllcy5cbiAgICAgICAgd2hpbGUgKHNpemUtLSkge1xuICAgICAgICAgIGlmICghKHJlc3VsdCA9IGVxKGFbc2l6ZV0sIGJbc2l6ZV0sIGFTdGFjaywgYlN0YWNrKSkpIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIERlZXAgY29tcGFyZSBvYmplY3RzLlxuICAgICAgZm9yICh2YXIga2V5IGluIGEpIHtcbiAgICAgICAgaWYgKF8uaGFzKGEsIGtleSkpIHtcbiAgICAgICAgICAvLyBDb3VudCB0aGUgZXhwZWN0ZWQgbnVtYmVyIG9mIHByb3BlcnRpZXMuXG4gICAgICAgICAgc2l6ZSsrO1xuICAgICAgICAgIC8vIERlZXAgY29tcGFyZSBlYWNoIG1lbWJlci5cbiAgICAgICAgICBpZiAoIShyZXN1bHQgPSBfLmhhcyhiLCBrZXkpICYmIGVxKGFba2V5XSwgYltrZXldLCBhU3RhY2ssIGJTdGFjaykpKSBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gRW5zdXJlIHRoYXQgYm90aCBvYmplY3RzIGNvbnRhaW4gdGhlIHNhbWUgbnVtYmVyIG9mIHByb3BlcnRpZXMuXG4gICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgIGZvciAoa2V5IGluIGIpIHtcbiAgICAgICAgICBpZiAoXy5oYXMoYiwga2V5KSAmJiAhKHNpemUtLSkpIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdCA9ICFzaXplO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBSZW1vdmUgdGhlIGZpcnN0IG9iamVjdCBmcm9tIHRoZSBzdGFjayBvZiB0cmF2ZXJzZWQgb2JqZWN0cy5cbiAgICBhU3RhY2sucG9wKCk7XG4gICAgYlN0YWNrLnBvcCgpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gUGVyZm9ybSBhIGRlZXAgY29tcGFyaXNvbiB0byBjaGVjayBpZiB0d28gb2JqZWN0cyBhcmUgZXF1YWwuXG4gIF8uaXNFcXVhbCA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgICByZXR1cm4gZXEoYSwgYiwgW10sIFtdKTtcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIGFycmF5LCBzdHJpbmcsIG9yIG9iamVjdCBlbXB0eT9cbiAgLy8gQW4gXCJlbXB0eVwiIG9iamVjdCBoYXMgbm8gZW51bWVyYWJsZSBvd24tcHJvcGVydGllcy5cbiAgXy5pc0VtcHR5ID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gdHJ1ZTtcbiAgICBpZiAoXy5pc0FycmF5KG9iaikgfHwgXy5pc1N0cmluZyhvYmopKSByZXR1cm4gb2JqLmxlbmd0aCA9PT0gMDtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSBpZiAoXy5oYXMob2JqLCBrZXkpKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiB2YWx1ZSBhIERPTSBlbGVtZW50P1xuICBfLmlzRWxlbWVudCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiAhIShvYmogJiYgb2JqLm5vZGVUeXBlID09PSAxKTtcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhbHVlIGFuIGFycmF5P1xuICAvLyBEZWxlZ2F0ZXMgdG8gRUNNQTUncyBuYXRpdmUgQXJyYXkuaXNBcnJheVxuICBfLmlzQXJyYXkgPSBuYXRpdmVJc0FycmF5IHx8IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT0gJ1tvYmplY3QgQXJyYXldJztcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhcmlhYmxlIGFuIG9iamVjdD9cbiAgXy5pc09iamVjdCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBvYmogPT09IE9iamVjdChvYmopO1xuICB9O1xuXG4gIC8vIEFkZCBzb21lIGlzVHlwZSBtZXRob2RzOiBpc0FyZ3VtZW50cywgaXNGdW5jdGlvbiwgaXNTdHJpbmcsIGlzTnVtYmVyLCBpc0RhdGUsIGlzUmVnRXhwLlxuICBlYWNoKFsnQXJndW1lbnRzJywgJ0Z1bmN0aW9uJywgJ1N0cmluZycsICdOdW1iZXInLCAnRGF0ZScsICdSZWdFeHAnXSwgZnVuY3Rpb24obmFtZSkge1xuICAgIF9bJ2lzJyArIG5hbWVdID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09ICdbb2JqZWN0ICcgKyBuYW1lICsgJ10nO1xuICAgIH07XG4gIH0pO1xuXG4gIC8vIERlZmluZSBhIGZhbGxiYWNrIHZlcnNpb24gb2YgdGhlIG1ldGhvZCBpbiBicm93c2VycyAoYWhlbSwgSUUpLCB3aGVyZVxuICAvLyB0aGVyZSBpc24ndCBhbnkgaW5zcGVjdGFibGUgXCJBcmd1bWVudHNcIiB0eXBlLlxuICBpZiAoIV8uaXNBcmd1bWVudHMoYXJndW1lbnRzKSkge1xuICAgIF8uaXNBcmd1bWVudHMgPSBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiAhIShvYmogJiYgXy5oYXMob2JqLCAnY2FsbGVlJykpO1xuICAgIH07XG4gIH1cblxuICAvLyBPcHRpbWl6ZSBgaXNGdW5jdGlvbmAgaWYgYXBwcm9wcmlhdGUuXG4gIGlmICh0eXBlb2YgKC8uLykgIT09ICdmdW5jdGlvbicpIHtcbiAgICBfLmlzRnVuY3Rpb24gPSBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiB0eXBlb2Ygb2JqID09PSAnZnVuY3Rpb24nO1xuICAgIH07XG4gIH1cblxuICAvLyBJcyBhIGdpdmVuIG9iamVjdCBhIGZpbml0ZSBudW1iZXI/XG4gIF8uaXNGaW5pdGUgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gaXNGaW5pdGUob2JqKSAmJiAhaXNOYU4ocGFyc2VGbG9hdChvYmopKTtcbiAgfTtcblxuICAvLyBJcyB0aGUgZ2l2ZW4gdmFsdWUgYE5hTmA/IChOYU4gaXMgdGhlIG9ubHkgbnVtYmVyIHdoaWNoIGRvZXMgbm90IGVxdWFsIGl0c2VsZikuXG4gIF8uaXNOYU4gPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gXy5pc051bWJlcihvYmopICYmIG9iaiAhPSArb2JqO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gdmFsdWUgYSBib29sZWFuP1xuICBfLmlzQm9vbGVhbiA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBvYmogPT09IHRydWUgfHwgb2JqID09PSBmYWxzZSB8fCB0b1N0cmluZy5jYWxsKG9iaikgPT0gJ1tvYmplY3QgQm9vbGVhbl0nO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gdmFsdWUgZXF1YWwgdG8gbnVsbD9cbiAgXy5pc051bGwgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gb2JqID09PSBudWxsO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gdmFyaWFibGUgdW5kZWZpbmVkP1xuICBfLmlzVW5kZWZpbmVkID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIG9iaiA9PT0gdm9pZCAwO1xuICB9O1xuXG4gIC8vIFNob3J0Y3V0IGZ1bmN0aW9uIGZvciBjaGVja2luZyBpZiBhbiBvYmplY3QgaGFzIGEgZ2l2ZW4gcHJvcGVydHkgZGlyZWN0bHlcbiAgLy8gb24gaXRzZWxmIChpbiBvdGhlciB3b3Jkcywgbm90IG9uIGEgcHJvdG90eXBlKS5cbiAgXy5oYXMgPSBmdW5jdGlvbihvYmosIGtleSkge1xuICAgIHJldHVybiBoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KTtcbiAgfTtcblxuICAvLyBVdGlsaXR5IEZ1bmN0aW9uc1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8vIFJ1biBVbmRlcnNjb3JlLmpzIGluICpub0NvbmZsaWN0KiBtb2RlLCByZXR1cm5pbmcgdGhlIGBfYCB2YXJpYWJsZSB0byBpdHNcbiAgLy8gcHJldmlvdXMgb3duZXIuIFJldHVybnMgYSByZWZlcmVuY2UgdG8gdGhlIFVuZGVyc2NvcmUgb2JqZWN0LlxuICBfLm5vQ29uZmxpY3QgPSBmdW5jdGlvbigpIHtcbiAgICByb290Ll8gPSBwcmV2aW91c1VuZGVyc2NvcmU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgLy8gS2VlcCB0aGUgaWRlbnRpdHkgZnVuY3Rpb24gYXJvdW5kIGZvciBkZWZhdWx0IGl0ZXJhdG9ycy5cbiAgXy5pZGVudGl0eSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9O1xuXG4gIC8vIFJ1biBhIGZ1bmN0aW9uICoqbioqIHRpbWVzLlxuICBfLnRpbWVzID0gZnVuY3Rpb24obiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICB2YXIgYWNjdW0gPSBBcnJheShNYXRoLm1heCgwLCBuKSk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyBpKyspIGFjY3VtW2ldID0gaXRlcmF0b3IuY2FsbChjb250ZXh0LCBpKTtcbiAgICByZXR1cm4gYWNjdW07XG4gIH07XG5cbiAgLy8gUmV0dXJuIGEgcmFuZG9tIGludGVnZXIgYmV0d2VlbiBtaW4gYW5kIG1heCAoaW5jbHVzaXZlKS5cbiAgXy5yYW5kb20gPSBmdW5jdGlvbihtaW4sIG1heCkge1xuICAgIGlmIChtYXggPT0gbnVsbCkge1xuICAgICAgbWF4ID0gbWluO1xuICAgICAgbWluID0gMDtcbiAgICB9XG4gICAgcmV0dXJuIG1pbiArIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIChtYXggLSBtaW4gKyAxKSk7XG4gIH07XG5cbiAgLy8gTGlzdCBvZiBIVE1MIGVudGl0aWVzIGZvciBlc2NhcGluZy5cbiAgdmFyIGVudGl0eU1hcCA9IHtcbiAgICBlc2NhcGU6IHtcbiAgICAgICcmJzogJyZhbXA7JyxcbiAgICAgICc8JzogJyZsdDsnLFxuICAgICAgJz4nOiAnJmd0OycsXG4gICAgICAnXCInOiAnJnF1b3Q7JyxcbiAgICAgIFwiJ1wiOiAnJiN4Mjc7J1xuICAgIH1cbiAgfTtcbiAgZW50aXR5TWFwLnVuZXNjYXBlID0gXy5pbnZlcnQoZW50aXR5TWFwLmVzY2FwZSk7XG5cbiAgLy8gUmVnZXhlcyBjb250YWluaW5nIHRoZSBrZXlzIGFuZCB2YWx1ZXMgbGlzdGVkIGltbWVkaWF0ZWx5IGFib3ZlLlxuICB2YXIgZW50aXR5UmVnZXhlcyA9IHtcbiAgICBlc2NhcGU6ICAgbmV3IFJlZ0V4cCgnWycgKyBfLmtleXMoZW50aXR5TWFwLmVzY2FwZSkuam9pbignJykgKyAnXScsICdnJyksXG4gICAgdW5lc2NhcGU6IG5ldyBSZWdFeHAoJygnICsgXy5rZXlzKGVudGl0eU1hcC51bmVzY2FwZSkuam9pbignfCcpICsgJyknLCAnZycpXG4gIH07XG5cbiAgLy8gRnVuY3Rpb25zIGZvciBlc2NhcGluZyBhbmQgdW5lc2NhcGluZyBzdHJpbmdzIHRvL2Zyb20gSFRNTCBpbnRlcnBvbGF0aW9uLlxuICBfLmVhY2goWydlc2NhcGUnLCAndW5lc2NhcGUnXSwgZnVuY3Rpb24obWV0aG9kKSB7XG4gICAgX1ttZXRob2RdID0gZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgICBpZiAoc3RyaW5nID09IG51bGwpIHJldHVybiAnJztcbiAgICAgIHJldHVybiAoJycgKyBzdHJpbmcpLnJlcGxhY2UoZW50aXR5UmVnZXhlc1ttZXRob2RdLCBmdW5jdGlvbihtYXRjaCkge1xuICAgICAgICByZXR1cm4gZW50aXR5TWFwW21ldGhvZF1bbWF0Y2hdO1xuICAgICAgfSk7XG4gICAgfTtcbiAgfSk7XG5cbiAgLy8gSWYgdGhlIHZhbHVlIG9mIHRoZSBuYW1lZCBgcHJvcGVydHlgIGlzIGEgZnVuY3Rpb24gdGhlbiBpbnZva2UgaXQgd2l0aCB0aGVcbiAgLy8gYG9iamVjdGAgYXMgY29udGV4dDsgb3RoZXJ3aXNlLCByZXR1cm4gaXQuXG4gIF8ucmVzdWx0ID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkge1xuICAgIGlmIChvYmplY3QgPT0gbnVsbCkgcmV0dXJuIHZvaWQgMDtcbiAgICB2YXIgdmFsdWUgPSBvYmplY3RbcHJvcGVydHldO1xuICAgIHJldHVybiBfLmlzRnVuY3Rpb24odmFsdWUpID8gdmFsdWUuY2FsbChvYmplY3QpIDogdmFsdWU7XG4gIH07XG5cbiAgLy8gQWRkIHlvdXIgb3duIGN1c3RvbSBmdW5jdGlvbnMgdG8gdGhlIFVuZGVyc2NvcmUgb2JqZWN0LlxuICBfLm1peGluID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgZWFjaChfLmZ1bmN0aW9ucyhvYmopLCBmdW5jdGlvbihuYW1lKSB7XG4gICAgICB2YXIgZnVuYyA9IF9bbmFtZV0gPSBvYmpbbmFtZV07XG4gICAgICBfLnByb3RvdHlwZVtuYW1lXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgYXJncyA9IFt0aGlzLl93cmFwcGVkXTtcbiAgICAgICAgcHVzaC5hcHBseShhcmdzLCBhcmd1bWVudHMpO1xuICAgICAgICByZXR1cm4gcmVzdWx0LmNhbGwodGhpcywgZnVuYy5hcHBseShfLCBhcmdzKSk7XG4gICAgICB9O1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIEdlbmVyYXRlIGEgdW5pcXVlIGludGVnZXIgaWQgKHVuaXF1ZSB3aXRoaW4gdGhlIGVudGlyZSBjbGllbnQgc2Vzc2lvbikuXG4gIC8vIFVzZWZ1bCBmb3IgdGVtcG9yYXJ5IERPTSBpZHMuXG4gIHZhciBpZENvdW50ZXIgPSAwO1xuICBfLnVuaXF1ZUlkID0gZnVuY3Rpb24ocHJlZml4KSB7XG4gICAgdmFyIGlkID0gKytpZENvdW50ZXIgKyAnJztcbiAgICByZXR1cm4gcHJlZml4ID8gcHJlZml4ICsgaWQgOiBpZDtcbiAgfTtcblxuICAvLyBCeSBkZWZhdWx0LCBVbmRlcnNjb3JlIHVzZXMgRVJCLXN0eWxlIHRlbXBsYXRlIGRlbGltaXRlcnMsIGNoYW5nZSB0aGVcbiAgLy8gZm9sbG93aW5nIHRlbXBsYXRlIHNldHRpbmdzIHRvIHVzZSBhbHRlcm5hdGl2ZSBkZWxpbWl0ZXJzLlxuICBfLnRlbXBsYXRlU2V0dGluZ3MgPSB7XG4gICAgZXZhbHVhdGUgICAgOiAvPCUoW1xcc1xcU10rPyklPi9nLFxuICAgIGludGVycG9sYXRlIDogLzwlPShbXFxzXFxTXSs/KSU+L2csXG4gICAgZXNjYXBlICAgICAgOiAvPCUtKFtcXHNcXFNdKz8pJT4vZ1xuICB9O1xuXG4gIC8vIFdoZW4gY3VzdG9taXppbmcgYHRlbXBsYXRlU2V0dGluZ3NgLCBpZiB5b3UgZG9uJ3Qgd2FudCB0byBkZWZpbmUgYW5cbiAgLy8gaW50ZXJwb2xhdGlvbiwgZXZhbHVhdGlvbiBvciBlc2NhcGluZyByZWdleCwgd2UgbmVlZCBvbmUgdGhhdCBpc1xuICAvLyBndWFyYW50ZWVkIG5vdCB0byBtYXRjaC5cbiAgdmFyIG5vTWF0Y2ggPSAvKC4pXi87XG5cbiAgLy8gQ2VydGFpbiBjaGFyYWN0ZXJzIG5lZWQgdG8gYmUgZXNjYXBlZCBzbyB0aGF0IHRoZXkgY2FuIGJlIHB1dCBpbnRvIGFcbiAgLy8gc3RyaW5nIGxpdGVyYWwuXG4gIHZhciBlc2NhcGVzID0ge1xuICAgIFwiJ1wiOiAgICAgIFwiJ1wiLFxuICAgICdcXFxcJzogICAgICdcXFxcJyxcbiAgICAnXFxyJzogICAgICdyJyxcbiAgICAnXFxuJzogICAgICduJyxcbiAgICAnXFx0JzogICAgICd0JyxcbiAgICAnXFx1MjAyOCc6ICd1MjAyOCcsXG4gICAgJ1xcdTIwMjknOiAndTIwMjknXG4gIH07XG5cbiAgdmFyIGVzY2FwZXIgPSAvXFxcXHwnfFxccnxcXG58XFx0fFxcdTIwMjh8XFx1MjAyOS9nO1xuXG4gIC8vIEphdmFTY3JpcHQgbWljcm8tdGVtcGxhdGluZywgc2ltaWxhciB0byBKb2huIFJlc2lnJ3MgaW1wbGVtZW50YXRpb24uXG4gIC8vIFVuZGVyc2NvcmUgdGVtcGxhdGluZyBoYW5kbGVzIGFyYml0cmFyeSBkZWxpbWl0ZXJzLCBwcmVzZXJ2ZXMgd2hpdGVzcGFjZSxcbiAgLy8gYW5kIGNvcnJlY3RseSBlc2NhcGVzIHF1b3RlcyB3aXRoaW4gaW50ZXJwb2xhdGVkIGNvZGUuXG4gIF8udGVtcGxhdGUgPSBmdW5jdGlvbih0ZXh0LCBkYXRhLCBzZXR0aW5ncykge1xuICAgIHZhciByZW5kZXI7XG4gICAgc2V0dGluZ3MgPSBfLmRlZmF1bHRzKHt9LCBzZXR0aW5ncywgXy50ZW1wbGF0ZVNldHRpbmdzKTtcblxuICAgIC8vIENvbWJpbmUgZGVsaW1pdGVycyBpbnRvIG9uZSByZWd1bGFyIGV4cHJlc3Npb24gdmlhIGFsdGVybmF0aW9uLlxuICAgIHZhciBtYXRjaGVyID0gbmV3IFJlZ0V4cChbXG4gICAgICAoc2V0dGluZ3MuZXNjYXBlIHx8IG5vTWF0Y2gpLnNvdXJjZSxcbiAgICAgIChzZXR0aW5ncy5pbnRlcnBvbGF0ZSB8fCBub01hdGNoKS5zb3VyY2UsXG4gICAgICAoc2V0dGluZ3MuZXZhbHVhdGUgfHwgbm9NYXRjaCkuc291cmNlXG4gICAgXS5qb2luKCd8JykgKyAnfCQnLCAnZycpO1xuXG4gICAgLy8gQ29tcGlsZSB0aGUgdGVtcGxhdGUgc291cmNlLCBlc2NhcGluZyBzdHJpbmcgbGl0ZXJhbHMgYXBwcm9wcmlhdGVseS5cbiAgICB2YXIgaW5kZXggPSAwO1xuICAgIHZhciBzb3VyY2UgPSBcIl9fcCs9J1wiO1xuICAgIHRleHQucmVwbGFjZShtYXRjaGVyLCBmdW5jdGlvbihtYXRjaCwgZXNjYXBlLCBpbnRlcnBvbGF0ZSwgZXZhbHVhdGUsIG9mZnNldCkge1xuICAgICAgc291cmNlICs9IHRleHQuc2xpY2UoaW5kZXgsIG9mZnNldClcbiAgICAgICAgLnJlcGxhY2UoZXNjYXBlciwgZnVuY3Rpb24obWF0Y2gpIHsgcmV0dXJuICdcXFxcJyArIGVzY2FwZXNbbWF0Y2hdOyB9KTtcblxuICAgICAgaWYgKGVzY2FwZSkge1xuICAgICAgICBzb3VyY2UgKz0gXCInK1xcbigoX190PShcIiArIGVzY2FwZSArIFwiKSk9PW51bGw/Jyc6Xy5lc2NhcGUoX190KSkrXFxuJ1wiO1xuICAgICAgfVxuICAgICAgaWYgKGludGVycG9sYXRlKSB7XG4gICAgICAgIHNvdXJjZSArPSBcIicrXFxuKChfX3Q9KFwiICsgaW50ZXJwb2xhdGUgKyBcIikpPT1udWxsPycnOl9fdCkrXFxuJ1wiO1xuICAgICAgfVxuICAgICAgaWYgKGV2YWx1YXRlKSB7XG4gICAgICAgIHNvdXJjZSArPSBcIic7XFxuXCIgKyBldmFsdWF0ZSArIFwiXFxuX19wKz0nXCI7XG4gICAgICB9XG4gICAgICBpbmRleCA9IG9mZnNldCArIG1hdGNoLmxlbmd0aDtcbiAgICAgIHJldHVybiBtYXRjaDtcbiAgICB9KTtcbiAgICBzb3VyY2UgKz0gXCInO1xcblwiO1xuXG4gICAgLy8gSWYgYSB2YXJpYWJsZSBpcyBub3Qgc3BlY2lmaWVkLCBwbGFjZSBkYXRhIHZhbHVlcyBpbiBsb2NhbCBzY29wZS5cbiAgICBpZiAoIXNldHRpbmdzLnZhcmlhYmxlKSBzb3VyY2UgPSAnd2l0aChvYmp8fHt9KXtcXG4nICsgc291cmNlICsgJ31cXG4nO1xuXG4gICAgc291cmNlID0gXCJ2YXIgX190LF9fcD0nJyxfX2o9QXJyYXkucHJvdG90eXBlLmpvaW4sXCIgK1xuICAgICAgXCJwcmludD1mdW5jdGlvbigpe19fcCs9X19qLmNhbGwoYXJndW1lbnRzLCcnKTt9O1xcblwiICtcbiAgICAgIHNvdXJjZSArIFwicmV0dXJuIF9fcDtcXG5cIjtcblxuICAgIHRyeSB7XG4gICAgICByZW5kZXIgPSBuZXcgRnVuY3Rpb24oc2V0dGluZ3MudmFyaWFibGUgfHwgJ29iaicsICdfJywgc291cmNlKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBlLnNvdXJjZSA9IHNvdXJjZTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgaWYgKGRhdGEpIHJldHVybiByZW5kZXIoZGF0YSwgXyk7XG4gICAgdmFyIHRlbXBsYXRlID0gZnVuY3Rpb24oZGF0YSkge1xuICAgICAgcmV0dXJuIHJlbmRlci5jYWxsKHRoaXMsIGRhdGEsIF8pO1xuICAgIH07XG5cbiAgICAvLyBQcm92aWRlIHRoZSBjb21waWxlZCBmdW5jdGlvbiBzb3VyY2UgYXMgYSBjb252ZW5pZW5jZSBmb3IgcHJlY29tcGlsYXRpb24uXG4gICAgdGVtcGxhdGUuc291cmNlID0gJ2Z1bmN0aW9uKCcgKyAoc2V0dGluZ3MudmFyaWFibGUgfHwgJ29iaicpICsgJyl7XFxuJyArIHNvdXJjZSArICd9JztcblxuICAgIHJldHVybiB0ZW1wbGF0ZTtcbiAgfTtcblxuICAvLyBBZGQgYSBcImNoYWluXCIgZnVuY3Rpb24sIHdoaWNoIHdpbGwgZGVsZWdhdGUgdG8gdGhlIHdyYXBwZXIuXG4gIF8uY2hhaW4gPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gXyhvYmopLmNoYWluKCk7XG4gIH07XG5cbiAgLy8gT09QXG4gIC8vIC0tLS0tLS0tLS0tLS0tLVxuICAvLyBJZiBVbmRlcnNjb3JlIGlzIGNhbGxlZCBhcyBhIGZ1bmN0aW9uLCBpdCByZXR1cm5zIGEgd3JhcHBlZCBvYmplY3QgdGhhdFxuICAvLyBjYW4gYmUgdXNlZCBPTy1zdHlsZS4gVGhpcyB3cmFwcGVyIGhvbGRzIGFsdGVyZWQgdmVyc2lvbnMgb2YgYWxsIHRoZVxuICAvLyB1bmRlcnNjb3JlIGZ1bmN0aW9ucy4gV3JhcHBlZCBvYmplY3RzIG1heSBiZSBjaGFpbmVkLlxuXG4gIC8vIEhlbHBlciBmdW5jdGlvbiB0byBjb250aW51ZSBjaGFpbmluZyBpbnRlcm1lZGlhdGUgcmVzdWx0cy5cbiAgdmFyIHJlc3VsdCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiB0aGlzLl9jaGFpbiA/IF8ob2JqKS5jaGFpbigpIDogb2JqO1xuICB9O1xuXG4gIC8vIEFkZCBhbGwgb2YgdGhlIFVuZGVyc2NvcmUgZnVuY3Rpb25zIHRvIHRoZSB3cmFwcGVyIG9iamVjdC5cbiAgXy5taXhpbihfKTtcblxuICAvLyBBZGQgYWxsIG11dGF0b3IgQXJyYXkgZnVuY3Rpb25zIHRvIHRoZSB3cmFwcGVyLlxuICBlYWNoKFsncG9wJywgJ3B1c2gnLCAncmV2ZXJzZScsICdzaGlmdCcsICdzb3J0JywgJ3NwbGljZScsICd1bnNoaWZ0J10sIGZ1bmN0aW9uKG5hbWUpIHtcbiAgICB2YXIgbWV0aG9kID0gQXJyYXlQcm90b1tuYW1lXTtcbiAgICBfLnByb3RvdHlwZVtuYW1lXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIG9iaiA9IHRoaXMuX3dyYXBwZWQ7XG4gICAgICBtZXRob2QuYXBwbHkob2JqLCBhcmd1bWVudHMpO1xuICAgICAgaWYgKChuYW1lID09ICdzaGlmdCcgfHwgbmFtZSA9PSAnc3BsaWNlJykgJiYgb2JqLmxlbmd0aCA9PT0gMCkgZGVsZXRlIG9ialswXTtcbiAgICAgIHJldHVybiByZXN1bHQuY2FsbCh0aGlzLCBvYmopO1xuICAgIH07XG4gIH0pO1xuXG4gIC8vIEFkZCBhbGwgYWNjZXNzb3IgQXJyYXkgZnVuY3Rpb25zIHRvIHRoZSB3cmFwcGVyLlxuICBlYWNoKFsnY29uY2F0JywgJ2pvaW4nLCAnc2xpY2UnXSwgZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciBtZXRob2QgPSBBcnJheVByb3RvW25hbWVdO1xuICAgIF8ucHJvdG90eXBlW25hbWVdID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gcmVzdWx0LmNhbGwodGhpcywgbWV0aG9kLmFwcGx5KHRoaXMuX3dyYXBwZWQsIGFyZ3VtZW50cykpO1xuICAgIH07XG4gIH0pO1xuXG4gIF8uZXh0ZW5kKF8ucHJvdG90eXBlLCB7XG5cbiAgICAvLyBTdGFydCBjaGFpbmluZyBhIHdyYXBwZWQgVW5kZXJzY29yZSBvYmplY3QuXG4gICAgY2hhaW46IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5fY2hhaW4gPSB0cnVlO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIC8vIEV4dHJhY3RzIHRoZSByZXN1bHQgZnJvbSBhIHdyYXBwZWQgYW5kIGNoYWluZWQgb2JqZWN0LlxuICAgIHZhbHVlOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLl93cmFwcGVkO1xuICAgIH1cblxuICB9KTtcblxufSkuY2FsbCh0aGlzKTtcblxufSkoKSIsIihmdW5jdGlvbigpIHtcbiAgdmFyIGFjdGl2ZSwgY3JlYXRlU2VhcmNoLCBlbXB0eVBhZ2UsIHV0aWwsIHdpa2k7XG5cbiAgd2lraSA9IHJlcXVpcmUoJy4vd2lraScpO1xuXG4gIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxuICBhY3RpdmUgPSByZXF1aXJlKCcuL2FjdGl2ZScpO1xuXG4gIGVtcHR5UGFnZSA9IHJlcXVpcmUoJy4vcGFnZScpLmVtcHR5UGFnZTtcblxuICBjcmVhdGVTZWFyY2ggPSBmdW5jdGlvbihfYXJnKSB7XG4gICAgdmFyIG5laWdoYm9yaG9vZCwgcGVyZm9ybVNlYXJjaDtcbiAgICBuZWlnaGJvcmhvb2QgPSBfYXJnLm5laWdoYm9yaG9vZDtcbiAgICBwZXJmb3JtU2VhcmNoID0gZnVuY3Rpb24oc2VhcmNoUXVlcnkpIHtcbiAgICAgIHZhciAkcmVzdWx0UGFnZSwgcmVzdWx0LCByZXN1bHRQYWdlLCBzZWFyY2hSZXN1bHRzLCB0YWxseSwgX2ksIF9sZW4sIF9yZWY7XG4gICAgICBzZWFyY2hSZXN1bHRzID0gbmVpZ2hib3Job29kLnNlYXJjaChzZWFyY2hRdWVyeSk7XG4gICAgICB0YWxseSA9IHNlYXJjaFJlc3VsdHMudGFsbHk7XG4gICAgICByZXN1bHRQYWdlID0gZW1wdHlQYWdlKCk7XG4gICAgICByZXN1bHRQYWdlLnNldFRpdGxlKFwiU2VhcmNoIGZvciAnXCIgKyBzZWFyY2hRdWVyeSArIFwiJ1wiKTtcbiAgICAgIHJlc3VsdFBhZ2UuYWRkUGFyYWdyYXBoKFwiU3RyaW5nICdcIiArIHNlYXJjaFF1ZXJ5ICsgXCInIGZvdW5kIG9uIFwiICsgKHRhbGx5LmZpbmRzIHx8ICdub25lJykgKyBcIiBvZiBcIiArICh0YWxseS5wYWdlcyB8fCAnbm8nKSArIFwiIHBhZ2VzIGZyb20gXCIgKyAodGFsbHkuc2l0ZXMgfHwgJ25vJykgKyBcIiBzaXRlcy5cXG5UZXh0IG1hdGNoZWQgb24gXCIgKyAodGFsbHkudGl0bGUgfHwgJ25vJykgKyBcIiB0aXRsZXMsIFwiICsgKHRhbGx5LnRleHQgfHwgJ25vJykgKyBcIiBwYXJhZ3JhcGhzLCBhbmQgXCIgKyAodGFsbHkuc2x1ZyB8fCAnbm8nKSArIFwiIHNsdWdzLlxcbkVsYXBzZWQgdGltZSBcIiArIHRhbGx5Lm1zZWMgKyBcIiBtaWxsaXNlY29uZHMuXCIpO1xuICAgICAgX3JlZiA9IHNlYXJjaFJlc3VsdHMuZmluZHM7XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgcmVzdWx0ID0gX3JlZltfaV07XG4gICAgICAgIHJlc3VsdFBhZ2UuYWRkSXRlbSh7XG4gICAgICAgICAgXCJ0eXBlXCI6IFwicmVmZXJlbmNlXCIsXG4gICAgICAgICAgXCJzaXRlXCI6IHJlc3VsdC5zaXRlLFxuICAgICAgICAgIFwic2x1Z1wiOiByZXN1bHQucGFnZS5zbHVnLFxuICAgICAgICAgIFwidGl0bGVcIjogcmVzdWx0LnBhZ2UudGl0bGUsXG4gICAgICAgICAgXCJ0ZXh0XCI6IHJlc3VsdC5wYWdlLnN5bm9wc2lzIHx8ICcnXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgJHJlc3VsdFBhZ2UgPSB3aWtpLmNyZWF0ZVBhZ2UocmVzdWx0UGFnZS5nZXRTbHVnKCkpLmFkZENsYXNzKCdnaG9zdCcpO1xuICAgICAgJHJlc3VsdFBhZ2UuYXBwZW5kVG8oJCgnLm1haW4nKSk7XG4gICAgICB3aWtpLmJ1aWxkUGFnZShyZXN1bHRQYWdlLCAkcmVzdWx0UGFnZSk7XG4gICAgICByZXR1cm4gYWN0aXZlLnNldCgkKCcucGFnZScpLmxhc3QoKSk7XG4gICAgfTtcbiAgICByZXR1cm4ge1xuICAgICAgcGVyZm9ybVNlYXJjaDogcGVyZm9ybVNlYXJjaFxuICAgIH07XG4gIH07XG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVTZWFyY2g7XG5cbn0pLmNhbGwodGhpcyk7XG4iLCIoZnVuY3Rpb24oKSB7XG4gIHZhciBhY3RpdmUsIGNyZWF0ZVNlYXJjaCwgbmVpZ2hib3Job29kLCBuZXh0QXZhaWxhYmxlRmV0Y2gsIG5leHRGZXRjaEludGVydmFsLCBwb3B1bGF0ZVNpdGVJbmZvRm9yLCB1dGlsLCB3aWtpLCBfLFxuICAgIF9faGFzUHJvcCA9IHt9Lmhhc093blByb3BlcnR5O1xuXG4gIF8gPSByZXF1aXJlKCd1bmRlcnNjb3JlJyk7XG5cbiAgd2lraSA9IHJlcXVpcmUoJy4vd2lraScpO1xuXG4gIGFjdGl2ZSA9IHJlcXVpcmUoJy4vYWN0aXZlJyk7XG5cbiAgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xuXG4gIGNyZWF0ZVNlYXJjaCA9IHJlcXVpcmUoJy4vc2VhcmNoJyk7XG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBuZWlnaGJvcmhvb2QgPSB7fTtcblxuICBpZiAod2lraS5uZWlnaGJvcmhvb2QgPT0gbnVsbCkge1xuICAgIHdpa2kubmVpZ2hib3Job29kID0ge307XG4gIH1cblxuICBuZXh0QXZhaWxhYmxlRmV0Y2ggPSAwO1xuXG4gIG5leHRGZXRjaEludGVydmFsID0gMjAwMDtcblxuICBwb3B1bGF0ZVNpdGVJbmZvRm9yID0gZnVuY3Rpb24oc2l0ZSwgbmVpZ2hib3JJbmZvKSB7XG4gICAgdmFyIGZldGNoTWFwLCBub3csIHRyYW5zaXRpb247XG4gICAgaWYgKG5laWdoYm9ySW5mby5zaXRlbWFwUmVxdWVzdEluZmxpZ2h0KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIG5laWdoYm9ySW5mby5zaXRlbWFwUmVxdWVzdEluZmxpZ2h0ID0gdHJ1ZTtcbiAgICB0cmFuc2l0aW9uID0gZnVuY3Rpb24oc2l0ZSwgZnJvbSwgdG8pIHtcbiAgICAgIHJldHVybiAkKFwiLm5laWdoYm9yW2RhdGEtc2l0ZT1cXFwiXCIgKyBzaXRlICsgXCJcXFwiXVwiKS5maW5kKCdkaXYnKS5yZW1vdmVDbGFzcyhmcm9tKS5hZGRDbGFzcyh0byk7XG4gICAgfTtcbiAgICBmZXRjaE1hcCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHJlcXVlc3QsIHNpdGVtYXBVcmw7XG4gICAgICBzaXRlbWFwVXJsID0gXCJodHRwOi8vXCIgKyBzaXRlICsgXCIvc3lzdGVtL3NpdGVtYXAuanNvblwiO1xuICAgICAgdHJhbnNpdGlvbihzaXRlLCAnd2FpdCcsICdmZXRjaCcpO1xuICAgICAgcmVxdWVzdCA9ICQuYWpheCh7XG4gICAgICAgIHR5cGU6ICdHRVQnLFxuICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICB1cmw6IHNpdGVtYXBVcmxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlcXVlc3QuYWx3YXlzKGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gbmVpZ2hib3JJbmZvLnNpdGVtYXBSZXF1ZXN0SW5mbGlnaHQgPSBmYWxzZTtcbiAgICAgIH0pLmRvbmUoZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICBuZWlnaGJvckluZm8uc2l0ZW1hcCA9IGRhdGE7XG4gICAgICAgIHRyYW5zaXRpb24oc2l0ZSwgJ2ZldGNoJywgJ2RvbmUnKTtcbiAgICAgICAgcmV0dXJuICQoJ2JvZHknKS50cmlnZ2VyKCduZXctbmVpZ2hib3ItZG9uZScsIHNpdGUpO1xuICAgICAgfSkuZmFpbChmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgIHJldHVybiB0cmFuc2l0aW9uKHNpdGUsICdmZXRjaCcsICdmYWlsJyk7XG4gICAgICB9KTtcbiAgICB9O1xuICAgIG5vdyA9IERhdGUubm93KCk7XG4gICAgaWYgKG5vdyA+IG5leHRBdmFpbGFibGVGZXRjaCkge1xuICAgICAgbmV4dEF2YWlsYWJsZUZldGNoID0gbm93ICsgbmV4dEZldGNoSW50ZXJ2YWw7XG4gICAgICByZXR1cm4gc2V0VGltZW91dChmZXRjaE1hcCwgMTAwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2V0VGltZW91dChmZXRjaE1hcCwgbmV4dEF2YWlsYWJsZUZldGNoIC0gbm93KTtcbiAgICAgIHJldHVybiBuZXh0QXZhaWxhYmxlRmV0Y2ggKz0gbmV4dEZldGNoSW50ZXJ2YWw7XG4gICAgfVxuICB9O1xuXG4gIHdpa2kucmVnaXN0ZXJOZWlnaGJvciA9IG5laWdoYm9yaG9vZC5yZWdpc3Rlck5laWdoYm9yID0gZnVuY3Rpb24oc2l0ZSkge1xuICAgIHZhciBuZWlnaGJvckluZm87XG4gICAgaWYgKHdpa2kubmVpZ2hib3Job29kW3NpdGVdICE9IG51bGwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbmVpZ2hib3JJbmZvID0ge307XG4gICAgd2lraS5uZWlnaGJvcmhvb2Rbc2l0ZV0gPSBuZWlnaGJvckluZm87XG4gICAgcG9wdWxhdGVTaXRlSW5mb0ZvcihzaXRlLCBuZWlnaGJvckluZm8pO1xuICAgIHJldHVybiAkKCdib2R5JykudHJpZ2dlcignbmV3LW5laWdoYm9yJywgc2l0ZSk7XG4gIH07XG5cbiAgbmVpZ2hib3Job29kLmxpc3ROZWlnaGJvcnMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gXy5rZXlzKHdpa2kubmVpZ2hib3Job29kKTtcbiAgfTtcblxuICBuZWlnaGJvcmhvb2Quc2VhcmNoID0gZnVuY3Rpb24oc2VhcmNoUXVlcnkpIHtcbiAgICB2YXIgZmluZHMsIG1hdGNoLCBtYXRjaGluZ1BhZ2VzLCBuZWlnaGJvckluZm8sIG5laWdoYm9yU2l0ZSwgc2l0ZW1hcCwgc3RhcnQsIHRhbGx5LCB0aWNrLCBfcmVmO1xuICAgIGZpbmRzID0gW107XG4gICAgdGFsbHkgPSB7fTtcbiAgICB0aWNrID0gZnVuY3Rpb24oa2V5KSB7XG4gICAgICBpZiAodGFsbHlba2V5XSAhPSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0YWxseVtrZXldKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdGFsbHlba2V5XSA9IDE7XG4gICAgICB9XG4gICAgfTtcbiAgICBtYXRjaCA9IGZ1bmN0aW9uKGtleSwgdGV4dCkge1xuICAgICAgdmFyIGhpdDtcbiAgICAgIGhpdCA9ICh0ZXh0ICE9IG51bGwpICYmIHRleHQudG9Mb3dlckNhc2UoKS5pbmRleE9mKHNlYXJjaFF1ZXJ5LnRvTG93ZXJDYXNlKCkpID49IDA7XG4gICAgICBpZiAoaGl0KSB7XG4gICAgICAgIHRpY2soa2V5KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBoaXQ7XG4gICAgfTtcbiAgICBzdGFydCA9IERhdGUubm93KCk7XG4gICAgX3JlZiA9IHdpa2kubmVpZ2hib3Job29kO1xuICAgIGZvciAobmVpZ2hib3JTaXRlIGluIF9yZWYpIHtcbiAgICAgIGlmICghX19oYXNQcm9wLmNhbGwoX3JlZiwgbmVpZ2hib3JTaXRlKSkgY29udGludWU7XG4gICAgICBuZWlnaGJvckluZm8gPSBfcmVmW25laWdoYm9yU2l0ZV07XG4gICAgICBzaXRlbWFwID0gbmVpZ2hib3JJbmZvLnNpdGVtYXA7XG4gICAgICBpZiAoc2l0ZW1hcCAhPSBudWxsKSB7XG4gICAgICAgIHRpY2soJ3NpdGVzJyk7XG4gICAgICB9XG4gICAgICBtYXRjaGluZ1BhZ2VzID0gXy5lYWNoKHNpdGVtYXAsIGZ1bmN0aW9uKHBhZ2UpIHtcbiAgICAgICAgdGljaygncGFnZXMnKTtcbiAgICAgICAgaWYgKCEobWF0Y2goJ3RpdGxlJywgcGFnZS50aXRsZSkgfHwgbWF0Y2goJ3RleHQnLCBwYWdlLnN5bm9wc2lzKSB8fCBtYXRjaCgnc2x1ZycsIHBhZ2Uuc2x1ZykpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRpY2soJ2ZpbmRzJyk7XG4gICAgICAgIHJldHVybiBmaW5kcy5wdXNoKHtcbiAgICAgICAgICBwYWdlOiBwYWdlLFxuICAgICAgICAgIHNpdGU6IG5laWdoYm9yU2l0ZSxcbiAgICAgICAgICByYW5rOiAxXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHRhbGx5Wydtc2VjJ10gPSBEYXRlLm5vdygpIC0gc3RhcnQ7XG4gICAgcmV0dXJuIHtcbiAgICAgIGZpbmRzOiBmaW5kcyxcbiAgICAgIHRhbGx5OiB0YWxseVxuICAgIH07XG4gIH07XG5cbiAgJChmdW5jdGlvbigpIHtcbiAgICB2YXIgJG5laWdoYm9yaG9vZCwgZmxhZywgc2VhcmNoO1xuICAgICRuZWlnaGJvcmhvb2QgPSAkKCcubmVpZ2hib3Job29kJyk7XG4gICAgZmxhZyA9IGZ1bmN0aW9uKHNpdGUpIHtcbiAgICAgIHJldHVybiBcIjxzcGFuIGNsYXNzPVxcXCJuZWlnaGJvclxcXCIgZGF0YS1zaXRlPVxcXCJcIiArIHNpdGUgKyBcIlxcXCI+XFxuICA8ZGl2IGNsYXNzPVxcXCJ3YWl0XFxcIj5cXG4gICAgPGltZyBzcmM9XFxcImh0dHA6Ly9cIiArIHNpdGUgKyBcIi9mYXZpY29uLnBuZ1xcXCIgdGl0bGU9XFxcIlwiICsgc2l0ZSArIFwiXFxcIj5cXG4gIDwvZGl2Plxcbjwvc3Bhbj5cIjtcbiAgICB9O1xuICAgICQoJ2JvZHknKS5vbignbmV3LW5laWdoYm9yJywgZnVuY3Rpb24oZSwgc2l0ZSkge1xuICAgICAgcmV0dXJuICRuZWlnaGJvcmhvb2QuYXBwZW5kKGZsYWcoc2l0ZSkpO1xuICAgIH0pLmRlbGVnYXRlKCcubmVpZ2hib3IgaW1nJywgJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xuICAgICAgcmV0dXJuIHdpa2kuZG9JbnRlcm5hbExpbmsoJ3dlbGNvbWUtdmlzaXRvcnMnLCBudWxsLCB0aGlzLnRpdGxlKTtcbiAgICB9KTtcbiAgICBzZWFyY2ggPSBjcmVhdGVTZWFyY2goe1xuICAgICAgbmVpZ2hib3Job29kOiBuZWlnaGJvcmhvb2RcbiAgICB9KTtcbiAgICByZXR1cm4gJCgnaW5wdXQuc2VhcmNoJykub24oJ2tleXByZXNzJywgZnVuY3Rpb24oZSkge1xuICAgICAgdmFyIHNlYXJjaFF1ZXJ5O1xuICAgICAgaWYgKGUua2V5Q29kZSAhPT0gMTMpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgc2VhcmNoUXVlcnkgPSAkKHRoaXMpLnZhbCgpO1xuICAgICAgc2VhcmNoLnBlcmZvcm1TZWFyY2goc2VhcmNoUXVlcnkpO1xuICAgICAgcmV0dXJuICQodGhpcykudmFsKFwiXCIpO1xuICAgIH0pO1xuICB9KTtcblxufSkuY2FsbCh0aGlzKTtcbiJdfQ==
3607
- ;