wiki 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/README.md +10 -2
- data/bin/wiki +4 -0
- data/default-data/pages/how-to-wiki +1069 -0
- data/default-data/pages/welcome-visitors +336 -0
- data/default-data/status/favicon.png +0 -0
- data/default-data/status/local-identity +7 -0
- data/lib/wiki/favicon.rb +0 -1
- data/lib/wiki/page.rb +3 -6
- data/lib/wiki/server.rb +7 -3
- data/lib/wiki/version.rb +1 -1
- data/package.json +70 -0
- data/wiki.gemspec +20 -13
- metadata +205 -58
- data/lib/wiki/views/client/Gruntfile.js +0 -50
- data/lib/wiki/views/client/ReadMe.md +0 -67
- data/lib/wiki/views/client/build-test.bat +0 -10
- data/lib/wiki/views/client/build.bat +0 -8
- data/lib/wiki/views/client/builder.pl +0 -41
- data/lib/wiki/views/client/client.coffee +0 -3
- data/lib/wiki/views/client/client.js +0 -3607
- data/lib/wiki/views/client/crosses.png +0 -0
- data/lib/wiki/views/client/images/external-link-ltr-icon.png +0 -0
- data/lib/wiki/views/client/images/noise.png +0 -0
- data/lib/wiki/views/client/images/oops.jpg +0 -0
- data/lib/wiki/views/client/js/d3/d3.behavior.js +0 -198
- data/lib/wiki/views/client/js/d3/d3.chart.js +0 -984
- data/lib/wiki/views/client/js/d3/d3.csv.js +0 -92
- data/lib/wiki/views/client/js/d3/d3.geo.js +0 -566
- data/lib/wiki/views/client/js/d3/d3.geom.js +0 -825
- data/lib/wiki/views/client/js/d3/d3.js +0 -3597
- data/lib/wiki/views/client/js/d3/d3.layout.js +0 -1923
- data/lib/wiki/views/client/js/d3/d3.time.js +0 -660
- data/lib/wiki/views/client/js/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/lib/wiki/views/client/js/images/ui-icons_222222_256x240.png +0 -0
- data/lib/wiki/views/client/js/jquery-1.6.2.min.js +0 -18
- data/lib/wiki/views/client/js/jquery-1.7.1.min.js +0 -4
- data/lib/wiki/views/client/js/jquery-1.9.1.min.js +0 -5
- data/lib/wiki/views/client/js/jquery-migrate-1.1.1.min.js +0 -3
- data/lib/wiki/views/client/js/jquery-ui-1.10.1.custom.min.css +0 -5
- data/lib/wiki/views/client/js/jquery-ui-1.10.1.custom.min.js +0 -6
- data/lib/wiki/views/client/js/jquery-ui-1.8.16.custom.css +0 -339
- data/lib/wiki/views/client/js/jquery-ui-1.8.16.custom.min.js +0 -315
- data/lib/wiki/views/client/js/jquery.ie.cors.js +0 -310
- data/lib/wiki/views/client/js/jquery.ui.touch-punch.min.js +0 -11
- data/lib/wiki/views/client/js/modernizr.custom.63710.js +0 -824
- data/lib/wiki/views/client/js/sockjs-0.3.min.js +0 -27
- data/lib/wiki/views/client/js/underscore-min.js +0 -30
- data/lib/wiki/views/client/mkplugin.sh +0 -97
- data/lib/wiki/views/client/package.json +0 -36
- data/lib/wiki/views/client/runtests.html +0 -26
- data/lib/wiki/views/client/style.css +0 -339
- data/lib/wiki/views/client/test/mocha.css +0 -231
- data/lib/wiki/views/client/test/mocha.js +0 -5340
- data/lib/wiki/views/client/test/testclient.js +0 -17133
- data/lib/wiki/views/client/testclient.coffee +0 -18
- data/lib/wiki/views/client/theme/granite.css +0 -59
- data/lib/wiki/views/client/theme/stoneSeamless.jpg +0 -0
- 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,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,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(' ')) + " " + 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
|
-
'&': '&',
|
3210
|
-
'<': '<',
|
3211
|
-
'>': '>',
|
3212
|
-
'"': '"',
|
3213
|
-
"'": '''
|
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
|
-
;
|