sliftutils 1.7.65 → 1.7.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/CLAUDE.md +1 -0
  2. package/dist/test.ts.cache +187 -36
  3. package/dist/treeSummary.ts.cache +359 -0
  4. package/index.d.ts +56 -18
  5. package/package.json +1 -1
  6. package/storage/ArchivesDisk.d.ts +2 -2
  7. package/storage/ArchivesDisk.ts +3 -2
  8. package/storage/IArchives.d.ts +19 -2
  9. package/storage/IArchives.ts +23 -5
  10. package/storage/backblaze.d.ts +2 -2
  11. package/storage/backblaze.ts +5 -4
  12. package/storage/dist/ArchivesDisk.ts.cache +6 -4
  13. package/storage/dist/IArchives.ts.cache +6 -6
  14. package/storage/dist/backblaze.ts.cache +7 -6
  15. package/storage/remoteStorage/ArchivesRemote.d.ts +2 -2
  16. package/storage/remoteStorage/ArchivesRemote.ts +5 -5
  17. package/storage/remoteStorage/ArchivesUrl.d.ts +2 -2
  18. package/storage/remoteStorage/ArchivesUrl.ts +8 -6
  19. package/storage/remoteStorage/blobStore.d.ts +21 -3
  20. package/storage/remoteStorage/blobStore.ts +43 -12
  21. package/storage/remoteStorage/createArchives.d.ts +2 -2
  22. package/storage/remoteStorage/createArchives.ts +5 -6
  23. package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +7 -7
  24. package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +12 -8
  25. package/storage/remoteStorage/dist/blobStore.ts.cache +43 -13
  26. package/storage/remoteStorage/dist/createArchives.ts.cache +6 -7
  27. package/storage/remoteStorage/dist/sourceWrapper.ts.cache +3 -4
  28. package/storage/remoteStorage/dist/storageController.ts.cache +11 -8
  29. package/storage/remoteStorage/dist/storageServerState.ts.cache +38 -9
  30. package/storage/remoteStorage/sourceWrapper.ts +2 -3
  31. package/storage/remoteStorage/storageController.d.ts +3 -3
  32. package/storage/remoteStorage/storageController.ts +8 -5
  33. package/storage/remoteStorage/storageServerState.d.ts +3 -0
  34. package/storage/remoteStorage/storageServerState.ts +34 -7
  35. package/test-files-cache.json +1 -0
  36. package/test.ts +127 -10
  37. package/treeSummary.ts +331 -54
package/CLAUDE.md CHANGED
@@ -45,6 +45,7 @@ from `.cursor/rules/*.mdc` so Claude reads them automatically.
45
45
  - Avoid callback hell with `import { PromiseObj } from "socket-function/src/misc";` — wrap event callbacks in a `PromiseObj` and await it.
46
46
  - `import { keyBy, keyByArray } from "socket-function/src/misc";` for building lookups.
47
47
  - Never use `alert`. Throw instead.
48
+ - Always use the helper functions for potentially large numbers (> 1000), and time spans. For time spans, it takes the time in terms of milliseconds. For example, 5,000 would be formatted as 5 seconds. `import { formatNumber, formatTime } from "socket-function/src/formatting/format";`
48
49
 
49
50
  ## MobX state
50
51
 
@@ -1,48 +1,199 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
4
24
  };
5
25
  Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
6
- const net_1 = __importDefault(require("net"));
7
- const forwardPort_1 = require("socket-function/src/forwardPort");
8
- const TEST_PORT = 5299;
9
- const EXTERNAL_IP = "99.250.124.91";
10
- function testConnect(host, port) {
11
- return new Promise(resolve => {
12
- let socket = net_1.default.connect({ host, port, timeout: 8000 });
13
- socket.on("connect", () => {
14
- socket.destroy();
15
- resolve("CONNECTED");
16
- });
17
- socket.on("timeout", () => {
18
- socket.destroy();
19
- resolve("TIMEOUT");
20
- });
21
- socket.on("error", e => resolve(e.code || String(e)));
26
+ const fs = __importStar(require("fs"));
27
+ const path = __importStar(require("path"));
28
+ const format_1 = require("socket-function/src/formatting/format");
29
+ const misc_1 = require("socket-function/src/misc");
30
+ const treeSummary_1 = require("./treeSummary");
31
+ const SUMMARY_COUNT = 30;
32
+ const TIMING_RUNS = 20;
33
+ const SCAN_DIRS = [
34
+ "D:/repos/qs-cyoa",
35
+ "D:/repos/querysub",
36
+ "D:/repos/socket-function",
37
+ "D:/repos/sliftutils",
38
+ "D:/repos/inference-weights",
39
+ ];
40
+ // Matches the gitignored "test*.json" pattern, so the cache never gets tracked.
41
+ const CACHE_FILE = "D:/repos/sliftutils/test-files-cache.json";
42
+ async function collectFiles(dirs, output) {
43
+ for (let dir of dirs) {
44
+ let basePath = dir.endsWith("/") && dir || dir + "/";
45
+ await collectDir(dir, basePath, output);
46
+ }
47
+ }
48
+ async function collectDir(dir, basePath, output) {
49
+ let entries = await fs.promises.readdir(dir, { withFileTypes: true });
50
+ for (let entry of entries) {
51
+ let fullPath = path.join(dir, entry.name);
52
+ let entryPath = basePath + entry.name;
53
+ if (entry.isDirectory()) {
54
+ await collectDir(fullPath, entryPath + "/", output);
55
+ }
56
+ else if (entry.isFile()) {
57
+ let stats = await fs.promises.stat(fullPath);
58
+ output.push({ path: entryPath, size: stats.size });
59
+ }
60
+ }
61
+ }
62
+ function summarize(files, weightBySize) {
63
+ let tree = new treeSummary_1.TreeSummary({
64
+ getPath: file => file.path,
65
+ createSummary: () => ({ count: 0, totalSize: 0 }),
66
+ addToSummary: (file, summary) => {
67
+ summary.count++;
68
+ summary.totalSize += file.size;
69
+ },
70
+ mergeSummaries: (target, source) => {
71
+ target.count += source.count;
72
+ target.totalSize += source.totalSize;
73
+ },
74
+ getWeight: summary => {
75
+ if (weightBySize)
76
+ return summary.totalSize;
77
+ return summary.count;
78
+ },
79
+ expectedOutputCount: SUMMARY_COUNT,
22
80
  });
81
+ let addStart = performance.now();
82
+ for (let file of files) {
83
+ tree.add(file);
84
+ }
85
+ let addTime = performance.now() - addStart;
86
+ let queryStart = performance.now();
87
+ let summaries = tree.getSummaries(SUMMARY_COUNT);
88
+ for (let i = 1; i < TIMING_RUNS; i++) {
89
+ summaries = tree.getSummaries(SUMMARY_COUNT);
90
+ }
91
+ let queryTime = (performance.now() - queryStart) / TIMING_RUNS;
92
+ let label = weightBySize && "size" || "count";
93
+ console.log(`\n=== weighted by ${label}, ${SUMMARY_COUNT} entries ===`);
94
+ console.log(`add: ${(0, format_1.formatTime)(addTime)} total for ${(0, format_1.formatNumber)(files.length)} files, tracking ${(0, format_1.formatNumber)(tree.getTrackedNodeCount())} nodes, getSummaries: ${(0, format_1.formatTime)(queryTime)} avg over ${TIMING_RUNS} runs`);
95
+ let totalWeight = 0;
96
+ for (let entry of summaries) {
97
+ totalWeight += entry.weight;
98
+ }
99
+ (0, misc_1.sort)(summaries, entry => -entry.weight);
100
+ // Verify each entry against the raw file list: assign every file to its most specific displayed entry (exact paths beat prefixes, longer prefixes beat shorter), which is the partition the entries claim to represent.
101
+ let actuals = summaries.map(() => ({ count: 0, totalSize: 0 }));
102
+ let unmatchedCount = 0;
103
+ let unmatchedSize = 0;
104
+ for (let file of files) {
105
+ let bestIndex = -1;
106
+ let bestLen = -1;
107
+ for (let i = 0; i < summaries.length; i++) {
108
+ let entryPath = summaries[i].path;
109
+ if (entryPath.endsWith("*")) {
110
+ let prefix = entryPath.slice(0, -1);
111
+ if (prefix.length > bestLen && file.path.startsWith(prefix)) {
112
+ bestIndex = i;
113
+ bestLen = prefix.length;
114
+ }
115
+ }
116
+ else if (file.path === entryPath && entryPath.length + 1 > bestLen) {
117
+ bestIndex = i;
118
+ bestLen = entryPath.length + 1;
119
+ }
120
+ }
121
+ if (bestIndex === -1) {
122
+ unmatchedCount++;
123
+ unmatchedSize += file.size;
124
+ continue;
125
+ }
126
+ actuals[bestIndex].count++;
127
+ actuals[bestIndex].totalSize += file.size;
128
+ }
129
+ let shownPercent = 0;
130
+ let specificPercent = 0;
131
+ for (let i = 0; i < summaries.length; i++) {
132
+ let entry = summaries[i];
133
+ let percent = entry.weight / totalWeight * 100;
134
+ shownPercent += percent;
135
+ if (entry.kind === "self" || entry.kind === "subtree") {
136
+ specificPercent += percent;
137
+ }
138
+ let actual = actuals[i];
139
+ let diff = "";
140
+ if (actual.count !== entry.summary.count || actual.totalSize !== entry.summary.totalSize) {
141
+ diff = ` DIFF actual files=${(0, format_1.formatNumber)(actual.count)} size=${(0, format_1.formatNumber)(actual.totalSize)}B`;
142
+ }
143
+ console.log(`${percent.toFixed(1).padStart(5)}% ${entry.path.padEnd(60)} files=${(0, format_1.formatNumber)(entry.summary.count).padStart(6)} size=${((0, format_1.formatNumber)(entry.summary.totalSize) + "B").padStart(8)}${diff}`);
144
+ }
145
+ if (unmatchedCount > 0) {
146
+ console.log(`UNMATCHED: ${(0, format_1.formatNumber)(unmatchedCount)} files (${(0, format_1.formatNumber)(unmatchedSize)}B) matched no displayed entry`);
147
+ }
148
+ console.log(`top ${summaries.length} entries cover ${shownPercent.toFixed(1)}% (specific paths ${specificPercent.toFixed(1)}%, combined leftovers ${(shownPercent - specificPercent).toFixed(1)}%)`);
149
+ // Entries are a strict partition (each file in exactly one entry), so these must match the real totals exactly.
150
+ let entryCount = 0;
151
+ let entrySize = 0;
152
+ for (let entry of summaries) {
153
+ entryCount += entry.summary.count;
154
+ entrySize += entry.summary.totalSize;
155
+ }
156
+ let actualSize = 0;
157
+ for (let file of files) {
158
+ actualSize += file.size;
159
+ }
160
+ console.log(`entry totals: files=${(0, format_1.formatNumber)(entryCount)} (actual ${(0, format_1.formatNumber)(files.length)}), size=${(0, format_1.formatNumber)(entrySize)}B (actual ${(0, format_1.formatNumber)(actualSize)}B)`);
161
+ }
162
+ async function getFiles() {
163
+ var _a;
164
+ try {
165
+ let cached = JSON.parse(await fs.promises.readFile(CACHE_FILE, "utf8"));
166
+ if (JSON.stringify(cached.dirs) === JSON.stringify(SCAN_DIRS)) {
167
+ console.log(`loaded ${(0, format_1.formatNumber)(cached.files.length)} files from cache ${CACHE_FILE}`);
168
+ return cached.files;
169
+ }
170
+ console.log(`cache dirs changed (cached ${JSON.stringify(cached.dirs)}, now ${JSON.stringify(SCAN_DIRS)}), rescanning`);
171
+ }
172
+ catch (err) {
173
+ if (err.code === "ENOENT") {
174
+ console.log(`no cache file at ${CACHE_FILE}, scanning`);
175
+ }
176
+ else {
177
+ console.log(`cache read failed, rescanning:`, (_a = err.stack) !== null && _a !== void 0 ? _a : err);
178
+ }
179
+ }
180
+ let files = [];
181
+ let scanStart = performance.now();
182
+ await collectFiles(SCAN_DIRS, files);
183
+ await fs.promises.writeFile(CACHE_FILE, JSON.stringify({ dirs: SCAN_DIRS, files }));
184
+ console.log(`scanned ${(0, format_1.formatNumber)(files.length)} files in ${(0, format_1.formatTime)(performance.now() - scanStart)}, cached to ${CACHE_FILE}`);
185
+ return files;
23
186
  }
24
187
  async function main() {
25
- let lanIP = await (0, forwardPort_1.getLocalInternalIP)();
26
- console.log("our LAN IP:", lanIP);
27
- let listener = net_1.default.createServer(socket => {
28
- socket.on("error", () => socket.destroy());
29
- socket.end("hello");
30
- });
31
- await new Promise(resolve => listener.listen(TEST_PORT, "0.0.0.0", () => resolve()));
32
- console.log(`listening on 0.0.0.0:${TEST_PORT}`);
33
- await (0, forwardPort_1.forwardPort)({ externalPort: TEST_PORT, internalPort: TEST_PORT });
34
- let mappings = await (0, forwardPort_1.listPortMappings)();
35
- let ours = mappings.find(x => x.externalPort === TEST_PORT);
36
- console.log(`mapping for ${TEST_PORT} after create:`, JSON.stringify(ours) || "MISSING");
37
- console.log(`LAN direct (${lanIP}:${TEST_PORT}):`, await testConnect(lanIP || "127.0.0.1", TEST_PORT));
38
- console.log(`hairpin (${EXTERNAL_IP}:${TEST_PORT}):`, await testConnect(EXTERNAL_IP, TEST_PORT));
39
- listener.close();
40
- process.exit(0);
188
+ let files = await getFiles();
189
+ console.log(`collected ${(0, format_1.formatNumber)(files.length)} files from ${SCAN_DIRS.join(", ")}`);
190
+ summarize(files, true);
191
+ summarize(files, false);
41
192
  }
42
193
  main().catch(e => {
43
194
  var _a;
44
195
  console.error((_a = e.stack) !== null && _a !== void 0 ? _a : e);
45
196
  process.exit(1);
46
197
  });
47
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw4Q0FBc0I7QUFDdEIsaUVBQW9HO0FBRXBHLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQztBQUN2QixNQUFNLFdBQVcsR0FBRyxlQUFlLENBQUM7QUFFcEMsU0FBUyxXQUFXLENBQUMsSUFBWSxFQUFFLElBQVk7SUFDM0MsT0FBTyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRTtRQUN6QixJQUFJLE1BQU0sR0FBRyxhQUFHLENBQUMsT0FBTyxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUN4RCxNQUFNLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxHQUFHLEVBQUU7WUFDdEIsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2pCLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUN6QixDQUFDLENBQUMsQ0FBQztRQUNILE1BQU0sQ0FBQyxFQUFFLENBQUMsU0FBUyxFQUFFLEdBQUcsRUFBRTtZQUN0QixNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDakIsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3ZCLENBQUMsQ0FBQyxDQUFDO1FBQ0gsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUUsQ0FBdUIsQ0FBQyxJQUFJLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNqRixDQUFDLENBQUMsQ0FBQztBQUNQLENBQUM7QUFFRCxLQUFLLFVBQVUsSUFBSTtJQUNmLElBQUksS0FBSyxHQUFHLE1BQU0sSUFBQSxnQ0FBa0IsR0FBRSxDQUFDO0lBQ3ZDLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBRWxDLElBQUksUUFBUSxHQUFHLGFBQUcsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUU7UUFDckMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDM0MsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN4QixDQUFDLENBQUMsQ0FBQztJQUNILE1BQU0sSUFBSSxPQUFPLENBQU8sT0FBTyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzNGLE9BQU8sQ0FBQyxHQUFHLENBQUMsd0JBQXdCLFNBQVMsRUFBRSxDQUFDLENBQUM7SUFFakQsTUFBTSxJQUFBLHlCQUFXLEVBQUMsRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO0lBRXhFLElBQUksUUFBUSxHQUFHLE1BQU0sSUFBQSw4QkFBZ0IsR0FBRSxDQUFDO0lBQ3hDLElBQUksSUFBSSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsWUFBWSxLQUFLLFNBQVMsQ0FBQyxDQUFDO0lBQzVELE9BQU8sQ0FBQyxHQUFHLENBQUMsZUFBZSxTQUFTLGdCQUFnQixFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksU0FBUyxDQUFDLENBQUM7SUFFekYsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLEtBQUssSUFBSSxTQUFTLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQyxLQUFLLElBQUksV0FBVyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDdkcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLFdBQVcsSUFBSSxTQUFTLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQyxXQUFXLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUVqRyxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDakIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNwQixDQUFDO0FBRUQsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFOztJQUNiLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBQyxDQUFXLENBQUMsS0FBSyxtQ0FBSSxDQUFDLENBQUMsQ0FBQztJQUN2QyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3BCLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IG5ldCBmcm9tIFwibmV0XCI7XG5pbXBvcnQgeyBsaXN0UG9ydE1hcHBpbmdzLCBmb3J3YXJkUG9ydCwgZ2V0TG9jYWxJbnRlcm5hbElQIH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvZm9yd2FyZFBvcnRcIjtcblxuY29uc3QgVEVTVF9QT1JUID0gNTI5OTtcbmNvbnN0IEVYVEVSTkFMX0lQID0gXCI5OS4yNTAuMTI0LjkxXCI7XG5cbmZ1bmN0aW9uIHRlc3RDb25uZWN0KGhvc3Q6IHN0cmluZywgcG9ydDogbnVtYmVyKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgIGxldCBzb2NrZXQgPSBuZXQuY29ubmVjdCh7IGhvc3QsIHBvcnQsIHRpbWVvdXQ6IDgwMDAgfSk7XG4gICAgICAgIHNvY2tldC5vbihcImNvbm5lY3RcIiwgKCkgPT4ge1xuICAgICAgICAgICAgc29ja2V0LmRlc3Ryb3koKTtcbiAgICAgICAgICAgIHJlc29sdmUoXCJDT05ORUNURURcIik7XG4gICAgICAgIH0pO1xuICAgICAgICBzb2NrZXQub24oXCJ0aW1lb3V0XCIsICgpID0+IHtcbiAgICAgICAgICAgIHNvY2tldC5kZXN0cm95KCk7XG4gICAgICAgICAgICByZXNvbHZlKFwiVElNRU9VVFwiKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHNvY2tldC5vbihcImVycm9yXCIsIGUgPT4gcmVzb2x2ZSgoZSBhcyB7IGNvZGU/OiBzdHJpbmcgfSkuY29kZSB8fCBTdHJpbmcoZSkpKTtcbiAgICB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbWFpbigpIHtcbiAgICBsZXQgbGFuSVAgPSBhd2FpdCBnZXRMb2NhbEludGVybmFsSVAoKTtcbiAgICBjb25zb2xlLmxvZyhcIm91ciBMQU4gSVA6XCIsIGxhbklQKTtcblxuICAgIGxldCBsaXN0ZW5lciA9IG5ldC5jcmVhdGVTZXJ2ZXIoc29ja2V0ID0+IHtcbiAgICAgICAgc29ja2V0Lm9uKFwiZXJyb3JcIiwgKCkgPT4gc29ja2V0LmRlc3Ryb3koKSk7XG4gICAgICAgIHNvY2tldC5lbmQoXCJoZWxsb1wiKTtcbiAgICB9KTtcbiAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPihyZXNvbHZlID0+IGxpc3RlbmVyLmxpc3RlbihURVNUX1BPUlQsIFwiMC4wLjAuMFwiLCAoKSA9PiByZXNvbHZlKCkpKTtcbiAgICBjb25zb2xlLmxvZyhgbGlzdGVuaW5nIG9uIDAuMC4wLjA6JHtURVNUX1BPUlR9YCk7XG5cbiAgICBhd2FpdCBmb3J3YXJkUG9ydCh7IGV4dGVybmFsUG9ydDogVEVTVF9QT1JULCBpbnRlcm5hbFBvcnQ6IFRFU1RfUE9SVCB9KTtcblxuICAgIGxldCBtYXBwaW5ncyA9IGF3YWl0IGxpc3RQb3J0TWFwcGluZ3MoKTtcbiAgICBsZXQgb3VycyA9IG1hcHBpbmdzLmZpbmQoeCA9PiB4LmV4dGVybmFsUG9ydCA9PT0gVEVTVF9QT1JUKTtcbiAgICBjb25zb2xlLmxvZyhgbWFwcGluZyBmb3IgJHtURVNUX1BPUlR9IGFmdGVyIGNyZWF0ZTpgLCBKU09OLnN0cmluZ2lmeShvdXJzKSB8fCBcIk1JU1NJTkdcIik7XG5cbiAgICBjb25zb2xlLmxvZyhgTEFOIGRpcmVjdCAoJHtsYW5JUH06JHtURVNUX1BPUlR9KTpgLCBhd2FpdCB0ZXN0Q29ubmVjdChsYW5JUCB8fCBcIjEyNy4wLjAuMVwiLCBURVNUX1BPUlQpKTtcbiAgICBjb25zb2xlLmxvZyhgaGFpcnBpbiAoJHtFWFRFUk5BTF9JUH06JHtURVNUX1BPUlR9KTpgLCBhd2FpdCB0ZXN0Q29ubmVjdChFWFRFUk5BTF9JUCwgVEVTVF9QT1JUKSk7XG5cbiAgICBsaXN0ZW5lci5jbG9zZSgpO1xuICAgIHByb2Nlc3MuZXhpdCgwKTtcbn1cblxubWFpbigpLmNhdGNoKGUgPT4ge1xuICAgIGNvbnNvbGUuZXJyb3IoKGUgYXMgRXJyb3IpLnN0YWNrID8/IGUpO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbn0pO1xuIl1//9
48
- /* _JS_SOURCE_HASH = "ff635e41519c7464cb3b055e6fe334893caa4fa66ebb080597c5fd80309af3da"; */
198
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLHVDQUF5QjtBQUN6QiwyQ0FBNkI7QUFDN0Isa0VBQWlGO0FBQ2pGLG1EQUFnRDtBQUNoRCwrQ0FBNEM7QUFFNUMsTUFBTSxhQUFhLEdBQUcsRUFBRSxDQUFDO0FBQ3pCLE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQztBQUN2QixNQUFNLFNBQVMsR0FBRztJQUNkLGtCQUFrQjtJQUNsQixtQkFBbUI7SUFDbkIsMEJBQTBCO0lBQzFCLHFCQUFxQjtJQUNyQiw0QkFBNEI7Q0FDL0IsQ0FBQztBQUVGLGdGQUFnRjtBQUNoRixNQUFNLFVBQVUsR0FBRywyQ0FBMkMsQ0FBQztBQUsvRCxLQUFLLFVBQVUsWUFBWSxDQUFDLElBQWMsRUFBRSxNQUFrQjtJQUMxRCxLQUFLLElBQUksR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ25CLElBQUksUUFBUSxHQUFHLEdBQUcsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksR0FBRyxJQUFJLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFDckQsTUFBTSxVQUFVLENBQUMsR0FBRyxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUM1QyxDQUFDO0FBQ0wsQ0FBQztBQUVELEtBQUssVUFBVSxVQUFVLENBQUMsR0FBVyxFQUFFLFFBQWdCLEVBQUUsTUFBa0I7SUFDdkUsSUFBSSxPQUFPLEdBQUcsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN0RSxLQUFLLElBQUksS0FBSyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQ3hCLElBQUksUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMxQyxJQUFJLFNBQVMsR0FBRyxRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQztRQUN0QyxJQUFJLEtBQUssQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDO1lBQ3RCLE1BQU0sVUFBVSxDQUFDLFFBQVEsRUFBRSxTQUFTLEdBQUcsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3hELENBQUM7YUFBTSxJQUFJLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1lBQ3hCLElBQUksS0FBSyxHQUFHLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDN0MsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZELENBQUM7SUFDTCxDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQVMsU0FBUyxDQUFDLEtBQWlCLEVBQUUsWUFBcUI7SUFDdkQsSUFBSSxJQUFJLEdBQUcsSUFBSSx5QkFBVyxDQUF3QjtRQUM5QyxPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSTtRQUMxQixhQUFhLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxDQUFDO1FBQ2pELFlBQVksRUFBRSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsRUFBRTtZQUM1QixPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDaEIsT0FBTyxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQ25DLENBQUM7UUFDRCxjQUFjLEVBQUUsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDL0IsTUFBTSxDQUFDLEtBQUssSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDO1lBQzdCLE1BQU0sQ0FBQyxTQUFTLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQztRQUN6QyxDQUFDO1FBQ0QsU0FBUyxFQUFFLE9BQU8sQ0FBQyxFQUFFO1lBQ2pCLElBQUksWUFBWTtnQkFBRSxPQUFPLE9BQU8sQ0FBQyxTQUFTLENBQUM7WUFDM0MsT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQ3pCLENBQUM7UUFDRCxtQkFBbUIsRUFBRSxhQUFhO0tBQ3JDLENBQUMsQ0FBQztJQUNILElBQUksUUFBUSxHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUNqQyxLQUFLLElBQUksSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkIsQ0FBQztJQUNELElBQUksT0FBTyxHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxRQUFRLENBQUM7SUFDM0MsSUFBSSxVQUFVLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ25DLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDakQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFdBQVcsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ25DLFNBQVMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFDRCxJQUFJLFNBQVMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxVQUFVLENBQUMsR0FBRyxXQUFXLENBQUM7SUFDL0QsSUFBSSxLQUFLLEdBQUcsWUFBWSxJQUFJLE1BQU0sSUFBSSxPQUFPLENBQUM7SUFDOUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxxQkFBcUIsS0FBSyxLQUFLLGFBQWEsY0FBYyxDQUFDLENBQUM7SUFDeEUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLElBQUEsbUJBQVUsRUFBQyxPQUFPLENBQUMsY0FBYyxJQUFBLHFCQUFZLEVBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxvQkFBb0IsSUFBQSxxQkFBWSxFQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLHlCQUF5QixJQUFBLG1CQUFVLEVBQUMsU0FBUyxDQUFDLGFBQWEsV0FBVyxPQUFPLENBQUMsQ0FBQztJQUMxTixJQUFJLFdBQVcsR0FBRyxDQUFDLENBQUM7SUFDcEIsS0FBSyxJQUFJLEtBQUssSUFBSSxTQUFTLEVBQUUsQ0FBQztRQUMxQixXQUFXLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQztJQUNoQyxDQUFDO0lBQ0QsSUFBQSxXQUFJLEVBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDeEMsd05BQXdOO0lBQ3hOLElBQUksT0FBTyxHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoRSxJQUFJLGNBQWMsR0FBRyxDQUFDLENBQUM7SUFDdkIsSUFBSSxhQUFhLEdBQUcsQ0FBQyxDQUFDO0lBQ3RCLEtBQUssSUFBSSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7UUFDckIsSUFBSSxTQUFTLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDbkIsSUFBSSxPQUFPLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDakIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUN4QyxJQUFJLFNBQVMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ2xDLElBQUksU0FBUyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUMxQixJQUFJLE1BQU0sR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNwQyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEdBQUcsT0FBTyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7b0JBQzFELFNBQVMsR0FBRyxDQUFDLENBQUM7b0JBQ2QsT0FBTyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7Z0JBQzVCLENBQUM7WUFDTCxDQUFDO2lCQUFNLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxTQUFTLElBQUksU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLEdBQUcsT0FBTyxFQUFFLENBQUM7Z0JBQ25FLFNBQVMsR0FBRyxDQUFDLENBQUM7Z0JBQ2QsT0FBTyxHQUFHLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1lBQ25DLENBQUM7UUFDTCxDQUFDO1FBQ0QsSUFBSSxTQUFTLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNuQixjQUFjLEVBQUUsQ0FBQztZQUNqQixhQUFhLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQztZQUMzQixTQUFTO1FBQ2IsQ0FBQztRQUNELE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUMzQixPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDOUMsQ0FBQztJQUNELElBQUksWUFBWSxHQUFHLENBQUMsQ0FBQztJQUNyQixJQUFJLGVBQWUsR0FBRyxDQUFDLENBQUM7SUFDeEIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUN4QyxJQUFJLEtBQUssR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDekIsSUFBSSxPQUFPLEdBQUcsS0FBSyxDQUFDLE1BQU0sR0FBRyxXQUFXLEdBQUcsR0FBRyxDQUFDO1FBQy9DLFlBQVksSUFBSSxPQUFPLENBQUM7UUFDeEIsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLE1BQU0sSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3BELGVBQWUsSUFBSSxPQUFPLENBQUM7UUFDL0IsQ0FBQztRQUNELElBQUksTUFBTSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4QixJQUFJLElBQUksR0FBRyxFQUFFLENBQUM7UUFDZCxJQUFJLE1BQU0sQ0FBQyxLQUFLLEtBQUssS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQUksTUFBTSxDQUFDLFNBQVMsS0FBSyxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3ZGLElBQUksR0FBRyx1QkFBdUIsSUFBQSxxQkFBWSxFQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxJQUFBLHFCQUFZLEVBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUM7UUFDdkcsQ0FBQztRQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxJQUFBLHFCQUFZLEVBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFBLHFCQUFZLEVBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMvTSxDQUFDO0lBQ0QsSUFBSSxjQUFjLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDckIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLElBQUEscUJBQVksRUFBQyxjQUFjLENBQUMsV0FBVyxJQUFBLHFCQUFZLEVBQUMsYUFBYSxDQUFDLCtCQUErQixDQUFDLENBQUM7SUFDakksQ0FBQztJQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxTQUFTLENBQUMsTUFBTSxrQkFBa0IsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMscUJBQXFCLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLHlCQUF5QixDQUFDLFlBQVksR0FBRyxlQUFlLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3JNLGdIQUFnSDtJQUNoSCxJQUFJLFVBQVUsR0FBRyxDQUFDLENBQUM7SUFDbkIsSUFBSSxTQUFTLEdBQUcsQ0FBQyxDQUFDO0lBQ2xCLEtBQUssSUFBSSxLQUFLLElBQUksU0FBUyxFQUFFLENBQUM7UUFDMUIsVUFBVSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBQ2xDLFNBQVMsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQztJQUN6QyxDQUFDO0lBQ0QsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0lBQ25CLEtBQUssSUFBSSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7UUFDckIsVUFBVSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDNUIsQ0FBQztJQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsdUJBQXVCLElBQUEscUJBQVksRUFBQyxVQUFVLENBQUMsWUFBWSxJQUFBLHFCQUFZLEVBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxXQUFXLElBQUEscUJBQVksRUFBQyxTQUFTLENBQUMsYUFBYSxJQUFBLHFCQUFZLEVBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ2xMLENBQUM7QUFFRCxLQUFLLFVBQVUsUUFBUTs7SUFDbkIsSUFBSSxDQUFDO1FBQ0QsSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBMEMsQ0FBQztRQUNqSCxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUM1RCxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBQSxxQkFBWSxFQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLHFCQUFxQixVQUFVLEVBQUUsQ0FBQyxDQUFDO1lBQzFGLE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQztRQUN4QixDQUFDO1FBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyw4QkFBOEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDNUgsQ0FBQztJQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDWCxJQUFLLEdBQXlCLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQy9DLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLFVBQVUsWUFBWSxDQUFDLENBQUM7UUFDNUQsQ0FBQzthQUFNLENBQUM7WUFDSixPQUFPLENBQUMsR0FBRyxDQUFDLGdDQUFnQyxFQUFFLE1BQUMsR0FBYSxDQUFDLEtBQUssbUNBQUksR0FBRyxDQUFDLENBQUM7UUFDL0UsQ0FBQztJQUNMLENBQUM7SUFDRCxJQUFJLEtBQUssR0FBZSxFQUFFLENBQUM7SUFDM0IsSUFBSSxTQUFTLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ2xDLE1BQU0sWUFBWSxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNyQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDcEYsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLElBQUEscUJBQVksRUFBQyxLQUFLLENBQUMsTUFBTSxDQUFDLGFBQWEsSUFBQSxtQkFBVSxFQUFDLFdBQVcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUMsZUFBZSxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQ3BJLE9BQU8sS0FBSyxDQUFDO0FBQ2pCLENBQUM7QUFFRCxLQUFLLFVBQVUsSUFBSTtJQUNmLElBQUksS0FBSyxHQUFHLE1BQU0sUUFBUSxFQUFFLENBQUM7SUFDN0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLElBQUEscUJBQVksRUFBQyxLQUFLLENBQUMsTUFBTSxDQUFDLGVBQWUsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDMUYsU0FBUyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztJQUN2QixTQUFTLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQzVCLENBQUM7QUFFRCxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUU7O0lBQ2IsT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFDLENBQVcsQ0FBQyxLQUFLLG1DQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDcEIsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCAqIGFzIHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IGZvcm1hdE51bWJlciwgZm9ybWF0VGltZSB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL2Zvcm1hdHRpbmcvZm9ybWF0XCI7XG5pbXBvcnQgeyBzb3J0IH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvbWlzY1wiO1xuaW1wb3J0IHsgVHJlZVN1bW1hcnkgfSBmcm9tIFwiLi90cmVlU3VtbWFyeVwiO1xuXG5jb25zdCBTVU1NQVJZX0NPVU5UID0gMzA7XG5jb25zdCBUSU1JTkdfUlVOUyA9IDIwO1xuY29uc3QgU0NBTl9ESVJTID0gW1xuICAgIFwiRDovcmVwb3MvcXMtY3lvYVwiLFxuICAgIFwiRDovcmVwb3MvcXVlcnlzdWJcIixcbiAgICBcIkQ6L3JlcG9zL3NvY2tldC1mdW5jdGlvblwiLFxuICAgIFwiRDovcmVwb3Mvc2xpZnR1dGlsc1wiLFxuICAgIFwiRDovcmVwb3MvaW5mZXJlbmNlLXdlaWdodHNcIixcbl07XG5cbi8vIE1hdGNoZXMgdGhlIGdpdGlnbm9yZWQgXCJ0ZXN0Ki5qc29uXCIgcGF0dGVybiwgc28gdGhlIGNhY2hlIG5ldmVyIGdldHMgdHJhY2tlZC5cbmNvbnN0IENBQ0hFX0ZJTEUgPSBcIkQ6L3JlcG9zL3NsaWZ0dXRpbHMvdGVzdC1maWxlcy1jYWNoZS5qc29uXCI7XG5cbnR5cGUgRmlsZUluZm8gPSB7IHBhdGg6IHN0cmluZzsgc2l6ZTogbnVtYmVyIH07XG50eXBlIEZpbGVTdW1tYXJ5ID0geyBjb3VudDogbnVtYmVyOyB0b3RhbFNpemU6IG51bWJlciB9O1xuXG5hc3luYyBmdW5jdGlvbiBjb2xsZWN0RmlsZXMoZGlyczogc3RyaW5nW10sIG91dHB1dDogRmlsZUluZm9bXSkge1xuICAgIGZvciAobGV0IGRpciBvZiBkaXJzKSB7XG4gICAgICAgIGxldCBiYXNlUGF0aCA9IGRpci5lbmRzV2l0aChcIi9cIikgJiYgZGlyIHx8IGRpciArIFwiL1wiO1xuICAgICAgICBhd2FpdCBjb2xsZWN0RGlyKGRpciwgYmFzZVBhdGgsIG91dHB1dCk7XG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBjb2xsZWN0RGlyKGRpcjogc3RyaW5nLCBiYXNlUGF0aDogc3RyaW5nLCBvdXRwdXQ6IEZpbGVJbmZvW10pIHtcbiAgICBsZXQgZW50cmllcyA9IGF3YWl0IGZzLnByb21pc2VzLnJlYWRkaXIoZGlyLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gICAgZm9yIChsZXQgZW50cnkgb2YgZW50cmllcykge1xuICAgICAgICBsZXQgZnVsbFBhdGggPSBwYXRoLmpvaW4oZGlyLCBlbnRyeS5uYW1lKTtcbiAgICAgICAgbGV0IGVudHJ5UGF0aCA9IGJhc2VQYXRoICsgZW50cnkubmFtZTtcbiAgICAgICAgaWYgKGVudHJ5LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgICAgIGF3YWl0IGNvbGxlY3REaXIoZnVsbFBhdGgsIGVudHJ5UGF0aCArIFwiL1wiLCBvdXRwdXQpO1xuICAgICAgICB9IGVsc2UgaWYgKGVudHJ5LmlzRmlsZSgpKSB7XG4gICAgICAgICAgICBsZXQgc3RhdHMgPSBhd2FpdCBmcy5wcm9taXNlcy5zdGF0KGZ1bGxQYXRoKTtcbiAgICAgICAgICAgIG91dHB1dC5wdXNoKHsgcGF0aDogZW50cnlQYXRoLCBzaXplOiBzdGF0cy5zaXplIH0pO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzdW1tYXJpemUoZmlsZXM6IEZpbGVJbmZvW10sIHdlaWdodEJ5U2l6ZTogYm9vbGVhbikge1xuICAgIGxldCB0cmVlID0gbmV3IFRyZWVTdW1tYXJ5PEZpbGVJbmZvLCBGaWxlU3VtbWFyeT4oe1xuICAgICAgICBnZXRQYXRoOiBmaWxlID0+IGZpbGUucGF0aCxcbiAgICAgICAgY3JlYXRlU3VtbWFyeTogKCkgPT4gKHsgY291bnQ6IDAsIHRvdGFsU2l6ZTogMCB9KSxcbiAgICAgICAgYWRkVG9TdW1tYXJ5OiAoZmlsZSwgc3VtbWFyeSkgPT4ge1xuICAgICAgICAgICAgc3VtbWFyeS5jb3VudCsrO1xuICAgICAgICAgICAgc3VtbWFyeS50b3RhbFNpemUgKz0gZmlsZS5zaXplO1xuICAgICAgICB9LFxuICAgICAgICBtZXJnZVN1bW1hcmllczogKHRhcmdldCwgc291cmNlKSA9PiB7XG4gICAgICAgICAgICB0YXJnZXQuY291bnQgKz0gc291cmNlLmNvdW50O1xuICAgICAgICAgICAgdGFyZ2V0LnRvdGFsU2l6ZSArPSBzb3VyY2UudG90YWxTaXplO1xuICAgICAgICB9LFxuICAgICAgICBnZXRXZWlnaHQ6IHN1bW1hcnkgPT4ge1xuICAgICAgICAgICAgaWYgKHdlaWdodEJ5U2l6ZSkgcmV0dXJuIHN1bW1hcnkudG90YWxTaXplO1xuICAgICAgICAgICAgcmV0dXJuIHN1bW1hcnkuY291bnQ7XG4gICAgICAgIH0sXG4gICAgICAgIGV4cGVjdGVkT3V0cHV0Q291bnQ6IFNVTU1BUllfQ09VTlQsXG4gICAgfSk7XG4gICAgbGV0IGFkZFN0YXJ0ID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgZm9yIChsZXQgZmlsZSBvZiBmaWxlcykge1xuICAgICAgICB0cmVlLmFkZChmaWxlKTtcbiAgICB9XG4gICAgbGV0IGFkZFRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKSAtIGFkZFN0YXJ0O1xuICAgIGxldCBxdWVyeVN0YXJ0ID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgbGV0IHN1bW1hcmllcyA9IHRyZWUuZ2V0U3VtbWFyaWVzKFNVTU1BUllfQ09VTlQpO1xuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgVElNSU5HX1JVTlM7IGkrKykge1xuICAgICAgICBzdW1tYXJpZXMgPSB0cmVlLmdldFN1bW1hcmllcyhTVU1NQVJZX0NPVU5UKTtcbiAgICB9XG4gICAgbGV0IHF1ZXJ5VGltZSA9IChwZXJmb3JtYW5jZS5ub3coKSAtIHF1ZXJ5U3RhcnQpIC8gVElNSU5HX1JVTlM7XG4gICAgbGV0IGxhYmVsID0gd2VpZ2h0QnlTaXplICYmIFwic2l6ZVwiIHx8IFwiY291bnRcIjtcbiAgICBjb25zb2xlLmxvZyhgXFxuPT09IHdlaWdodGVkIGJ5ICR7bGFiZWx9LCAke1NVTU1BUllfQ09VTlR9IGVudHJpZXMgPT09YCk7XG4gICAgY29uc29sZS5sb2coYGFkZDogJHtmb3JtYXRUaW1lKGFkZFRpbWUpfSB0b3RhbCBmb3IgJHtmb3JtYXROdW1iZXIoZmlsZXMubGVuZ3RoKX0gZmlsZXMsIHRyYWNraW5nICR7Zm9ybWF0TnVtYmVyKHRyZWUuZ2V0VHJhY2tlZE5vZGVDb3VudCgpKX0gbm9kZXMsIGdldFN1bW1hcmllczogJHtmb3JtYXRUaW1lKHF1ZXJ5VGltZSl9IGF2ZyBvdmVyICR7VElNSU5HX1JVTlN9IHJ1bnNgKTtcbiAgICBsZXQgdG90YWxXZWlnaHQgPSAwO1xuICAgIGZvciAobGV0IGVudHJ5IG9mIHN1bW1hcmllcykge1xuICAgICAgICB0b3RhbFdlaWdodCArPSBlbnRyeS53ZWlnaHQ7XG4gICAgfVxuICAgIHNvcnQoc3VtbWFyaWVzLCBlbnRyeSA9PiAtZW50cnkud2VpZ2h0KTtcbiAgICAvLyBWZXJpZnkgZWFjaCBlbnRyeSBhZ2FpbnN0IHRoZSByYXcgZmlsZSBsaXN0OiBhc3NpZ24gZXZlcnkgZmlsZSB0byBpdHMgbW9zdCBzcGVjaWZpYyBkaXNwbGF5ZWQgZW50cnkgKGV4YWN0IHBhdGhzIGJlYXQgcHJlZml4ZXMsIGxvbmdlciBwcmVmaXhlcyBiZWF0IHNob3J0ZXIpLCB3aGljaCBpcyB0aGUgcGFydGl0aW9uIHRoZSBlbnRyaWVzIGNsYWltIHRvIHJlcHJlc2VudC5cbiAgICBsZXQgYWN0dWFscyA9IHN1bW1hcmllcy5tYXAoKCkgPT4gKHsgY291bnQ6IDAsIHRvdGFsU2l6ZTogMCB9KSk7XG4gICAgbGV0IHVubWF0Y2hlZENvdW50ID0gMDtcbiAgICBsZXQgdW5tYXRjaGVkU2l6ZSA9IDA7XG4gICAgZm9yIChsZXQgZmlsZSBvZiBmaWxlcykge1xuICAgICAgICBsZXQgYmVzdEluZGV4ID0gLTE7XG4gICAgICAgIGxldCBiZXN0TGVuID0gLTE7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3VtbWFyaWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgZW50cnlQYXRoID0gc3VtbWFyaWVzW2ldLnBhdGg7XG4gICAgICAgICAgICBpZiAoZW50cnlQYXRoLmVuZHNXaXRoKFwiKlwiKSkge1xuICAgICAgICAgICAgICAgIGxldCBwcmVmaXggPSBlbnRyeVBhdGguc2xpY2UoMCwgLTEpO1xuICAgICAgICAgICAgICAgIGlmIChwcmVmaXgubGVuZ3RoID4gYmVzdExlbiAmJiBmaWxlLnBhdGguc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RJbmRleCA9IGk7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RMZW4gPSBwcmVmaXgubGVuZ3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZmlsZS5wYXRoID09PSBlbnRyeVBhdGggJiYgZW50cnlQYXRoLmxlbmd0aCArIDEgPiBiZXN0TGVuKSB7XG4gICAgICAgICAgICAgICAgYmVzdEluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICBiZXN0TGVuID0gZW50cnlQYXRoLmxlbmd0aCArIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJlc3RJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICAgIHVubWF0Y2hlZENvdW50Kys7XG4gICAgICAgICAgICB1bm1hdGNoZWRTaXplICs9IGZpbGUuc2l6ZTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGFjdHVhbHNbYmVzdEluZGV4XS5jb3VudCsrO1xuICAgICAgICBhY3R1YWxzW2Jlc3RJbmRleF0udG90YWxTaXplICs9IGZpbGUuc2l6ZTtcbiAgICB9XG4gICAgbGV0IHNob3duUGVyY2VudCA9IDA7XG4gICAgbGV0IHNwZWNpZmljUGVyY2VudCA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdW1tYXJpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbGV0IGVudHJ5ID0gc3VtbWFyaWVzW2ldO1xuICAgICAgICBsZXQgcGVyY2VudCA9IGVudHJ5LndlaWdodCAvIHRvdGFsV2VpZ2h0ICogMTAwO1xuICAgICAgICBzaG93blBlcmNlbnQgKz0gcGVyY2VudDtcbiAgICAgICAgaWYgKGVudHJ5LmtpbmQgPT09IFwic2VsZlwiIHx8IGVudHJ5LmtpbmQgPT09IFwic3VidHJlZVwiKSB7XG4gICAgICAgICAgICBzcGVjaWZpY1BlcmNlbnQgKz0gcGVyY2VudDtcbiAgICAgICAgfVxuICAgICAgICBsZXQgYWN0dWFsID0gYWN0dWFsc1tpXTtcbiAgICAgICAgbGV0IGRpZmYgPSBcIlwiO1xuICAgICAgICBpZiAoYWN0dWFsLmNvdW50ICE9PSBlbnRyeS5zdW1tYXJ5LmNvdW50IHx8IGFjdHVhbC50b3RhbFNpemUgIT09IGVudHJ5LnN1bW1hcnkudG90YWxTaXplKSB7XG4gICAgICAgICAgICBkaWZmID0gYCAgRElGRiBhY3R1YWwgZmlsZXM9JHtmb3JtYXROdW1iZXIoYWN0dWFsLmNvdW50KX0gc2l6ZT0ke2Zvcm1hdE51bWJlcihhY3R1YWwudG90YWxTaXplKX1CYDtcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmxvZyhgJHtwZXJjZW50LnRvRml4ZWQoMSkucGFkU3RhcnQoNSl9JSAke2VudHJ5LnBhdGgucGFkRW5kKDYwKX0gZmlsZXM9JHtmb3JtYXROdW1iZXIoZW50cnkuc3VtbWFyeS5jb3VudCkucGFkU3RhcnQoNil9IHNpemU9JHsoZm9ybWF0TnVtYmVyKGVudHJ5LnN1bW1hcnkudG90YWxTaXplKSArIFwiQlwiKS5wYWRTdGFydCg4KX0ke2RpZmZ9YCk7XG4gICAgfVxuICAgIGlmICh1bm1hdGNoZWRDb3VudCA+IDApIHtcbiAgICAgICAgY29uc29sZS5sb2coYFVOTUFUQ0hFRDogJHtmb3JtYXROdW1iZXIodW5tYXRjaGVkQ291bnQpfSBmaWxlcyAoJHtmb3JtYXROdW1iZXIodW5tYXRjaGVkU2l6ZSl9QikgbWF0Y2hlZCBubyBkaXNwbGF5ZWQgZW50cnlgKTtcbiAgICB9XG4gICAgY29uc29sZS5sb2coYHRvcCAke3N1bW1hcmllcy5sZW5ndGh9IGVudHJpZXMgY292ZXIgJHtzaG93blBlcmNlbnQudG9GaXhlZCgxKX0lIChzcGVjaWZpYyBwYXRocyAke3NwZWNpZmljUGVyY2VudC50b0ZpeGVkKDEpfSUsIGNvbWJpbmVkIGxlZnRvdmVycyAkeyhzaG93blBlcmNlbnQgLSBzcGVjaWZpY1BlcmNlbnQpLnRvRml4ZWQoMSl9JSlgKTtcbiAgICAvLyBFbnRyaWVzIGFyZSBhIHN0cmljdCBwYXJ0aXRpb24gKGVhY2ggZmlsZSBpbiBleGFjdGx5IG9uZSBlbnRyeSksIHNvIHRoZXNlIG11c3QgbWF0Y2ggdGhlIHJlYWwgdG90YWxzIGV4YWN0bHkuXG4gICAgbGV0IGVudHJ5Q291bnQgPSAwO1xuICAgIGxldCBlbnRyeVNpemUgPSAwO1xuICAgIGZvciAobGV0IGVudHJ5IG9mIHN1bW1hcmllcykge1xuICAgICAgICBlbnRyeUNvdW50ICs9IGVudHJ5LnN1bW1hcnkuY291bnQ7XG4gICAgICAgIGVudHJ5U2l6ZSArPSBlbnRyeS5zdW1tYXJ5LnRvdGFsU2l6ZTtcbiAgICB9XG4gICAgbGV0IGFjdHVhbFNpemUgPSAwO1xuICAgIGZvciAobGV0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgICAgYWN0dWFsU2l6ZSArPSBmaWxlLnNpemU7XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKGBlbnRyeSB0b3RhbHM6IGZpbGVzPSR7Zm9ybWF0TnVtYmVyKGVudHJ5Q291bnQpfSAoYWN0dWFsICR7Zm9ybWF0TnVtYmVyKGZpbGVzLmxlbmd0aCl9KSwgc2l6ZT0ke2Zvcm1hdE51bWJlcihlbnRyeVNpemUpfUIgKGFjdHVhbCAke2Zvcm1hdE51bWJlcihhY3R1YWxTaXplKX1CKWApO1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRGaWxlcygpOiBQcm9taXNlPEZpbGVJbmZvW10+IHtcbiAgICB0cnkge1xuICAgICAgICBsZXQgY2FjaGVkID0gSlNPTi5wYXJzZShhd2FpdCBmcy5wcm9taXNlcy5yZWFkRmlsZShDQUNIRV9GSUxFLCBcInV0ZjhcIikpIGFzIHsgZGlyczogc3RyaW5nW107IGZpbGVzOiBGaWxlSW5mb1tdIH07XG4gICAgICAgIGlmIChKU09OLnN0cmluZ2lmeShjYWNoZWQuZGlycykgPT09IEpTT04uc3RyaW5naWZ5KFNDQU5fRElSUykpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBsb2FkZWQgJHtmb3JtYXROdW1iZXIoY2FjaGVkLmZpbGVzLmxlbmd0aCl9IGZpbGVzIGZyb20gY2FjaGUgJHtDQUNIRV9GSUxFfWApO1xuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZC5maWxlcztcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmxvZyhgY2FjaGUgZGlycyBjaGFuZ2VkIChjYWNoZWQgJHtKU09OLnN0cmluZ2lmeShjYWNoZWQuZGlycyl9LCBub3cgJHtKU09OLnN0cmluZ2lmeShTQ0FOX0RJUlMpfSksIHJlc2Nhbm5pbmdgKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgaWYgKChlcnIgYXMgeyBjb2RlPzogc3RyaW5nIH0pLmNvZGUgPT09IFwiRU5PRU5UXCIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBubyBjYWNoZSBmaWxlIGF0ICR7Q0FDSEVfRklMRX0sIHNjYW5uaW5nYCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgY2FjaGUgcmVhZCBmYWlsZWQsIHJlc2Nhbm5pbmc6YCwgKGVyciBhcyBFcnJvcikuc3RhY2sgPz8gZXJyKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBsZXQgZmlsZXM6IEZpbGVJbmZvW10gPSBbXTtcbiAgICBsZXQgc2NhblN0YXJ0ID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgYXdhaXQgY29sbGVjdEZpbGVzKFNDQU5fRElSUywgZmlsZXMpO1xuICAgIGF3YWl0IGZzLnByb21pc2VzLndyaXRlRmlsZShDQUNIRV9GSUxFLCBKU09OLnN0cmluZ2lmeSh7IGRpcnM6IFNDQU5fRElSUywgZmlsZXMgfSkpO1xuICAgIGNvbnNvbGUubG9nKGBzY2FubmVkICR7Zm9ybWF0TnVtYmVyKGZpbGVzLmxlbmd0aCl9IGZpbGVzIGluICR7Zm9ybWF0VGltZShwZXJmb3JtYW5jZS5ub3coKSAtIHNjYW5TdGFydCl9LCBjYWNoZWQgdG8gJHtDQUNIRV9GSUxFfWApO1xuICAgIHJldHVybiBmaWxlcztcbn1cblxuYXN5bmMgZnVuY3Rpb24gbWFpbigpIHtcbiAgICBsZXQgZmlsZXMgPSBhd2FpdCBnZXRGaWxlcygpO1xuICAgIGNvbnNvbGUubG9nKGBjb2xsZWN0ZWQgJHtmb3JtYXROdW1iZXIoZmlsZXMubGVuZ3RoKX0gZmlsZXMgZnJvbSAke1NDQU5fRElSUy5qb2luKFwiLCBcIil9YCk7XG4gICAgc3VtbWFyaXplKGZpbGVzLCB0cnVlKTtcbiAgICBzdW1tYXJpemUoZmlsZXMsIGZhbHNlKTtcbn1cblxubWFpbigpLmNhdGNoKGUgPT4ge1xuICAgIGNvbnNvbGUuZXJyb3IoKGUgYXMgRXJyb3IpLnN0YWNrID8/IGUpO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbn0pO1xuIl19
199
+ /* _JS_SOURCE_HASH = "656b9eea92595d2b1164fb0d91cdd090fdb580dd665e47749657855c28eb87f8"; */