sliftutils 1.7.10 → 1.7.11

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 (83) hide show
  1. package/examplestorage/exampleserver.ts +0 -2
  2. package/index.d.ts +290 -54
  3. package/misc/dist/environment.ts.cache +3 -3
  4. package/misc/dist/getSecret.ts.cache +139 -0
  5. package/misc/dist/strings.ts.cache +13 -0
  6. package/misc/dist/zip.ts.cache +9 -0
  7. package/misc/getSecret.ts +38 -16
  8. package/misc/https/cloudflareHelpers.d.ts +19 -0
  9. package/misc/https/cloudflareHelpers.ts +69 -0
  10. package/misc/https/dist/certs.ts.cache +115 -179
  11. package/misc/https/dist/cloudflareHelpers.ts.cache +68 -0
  12. package/misc/https/dist/dns.ts.cache +112 -100
  13. package/misc/https/dist/hostServer.ts.cache +130 -0
  14. package/misc/https/dist/httpsCerts.ts.cache +24 -5
  15. package/misc/https/dist/persistentLocalStorage.ts.cache +3 -2
  16. package/misc/https/dns.d.ts +41 -12
  17. package/misc/https/dns.ts +104 -101
  18. package/misc/https/hostServer.d.ts +0 -6
  19. package/misc/https/hostServer.ts +9 -5
  20. package/package.json +2 -2
  21. package/render-utils/dist/observer.tsx.cache +3 -2
  22. package/spec.txt +0 -90
  23. package/storage/ArchivesDisk.d.ts +2 -0
  24. package/storage/ArchivesDisk.ts +7 -3
  25. package/storage/BulkDatabase2/dist/BulkDatabaseBase.ts.cache +1242 -0
  26. package/storage/BulkDatabase2/dist/BulkDatabaseFormat.ts.cache +513 -0
  27. package/storage/BulkDatabase2/dist/BulkDatabaseMerge.ts.cache +352 -0
  28. package/storage/BulkDatabase2/dist/BulkDatabaseReader.ts.cache +306 -0
  29. package/storage/BulkDatabase2/dist/LoadedIndex.ts.cache +435 -0
  30. package/storage/BulkDatabase2/dist/WriteOverlay.ts.cache +58 -0
  31. package/storage/BulkDatabase2/dist/blockCache.ts.cache +179 -0
  32. package/storage/BulkDatabase2/dist/mergeLock.ts.cache +149 -0
  33. package/storage/BulkDatabase2/dist/mergeMarkers.ts.cache +101 -0
  34. package/storage/BulkDatabase2/dist/streamLog.ts.cache +227 -0
  35. package/storage/BulkDatabase2/dist/syncClient.ts.cache +104 -0
  36. package/storage/IArchives.d.ts +47 -15
  37. package/storage/IArchives.ts +86 -31
  38. package/storage/backblaze.d.ts +15 -0
  39. package/storage/backblaze.ts +199 -79
  40. package/storage/dist/ArchivesDisk.ts.cache +373 -0
  41. package/storage/dist/FileFolderAPI.tsx.cache +508 -65
  42. package/storage/dist/IArchives.ts.cache +44 -0
  43. package/storage/dist/IndexedDBFileFolderAPI.ts.cache +8 -2
  44. package/storage/dist/JSONStorage.ts.cache +6 -2
  45. package/storage/dist/PendingManager.tsx.cache +1 -1
  46. package/storage/dist/TransactionStorage.ts.cache +231 -92
  47. package/storage/dist/backblaze.ts.cache +797 -0
  48. package/storage/dist/fileSystemPointer.ts.cache +36 -3
  49. package/storage/dist/remoteFileStorage.ts.cache +495 -0
  50. package/storage/remoteStorage/ArchivesRemote.d.ts +5 -1
  51. package/storage/remoteStorage/ArchivesRemote.ts +28 -8
  52. package/storage/remoteStorage/ArchivesUrl.d.ts +2 -0
  53. package/storage/remoteStorage/ArchivesUrl.ts +16 -4
  54. package/storage/remoteStorage/blobStore.d.ts +52 -3
  55. package/storage/remoteStorage/blobStore.ts +414 -101
  56. package/storage/remoteStorage/createArchives.d.ts +31 -10
  57. package/storage/remoteStorage/createArchives.ts +470 -253
  58. package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +197 -0
  59. package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +85 -0
  60. package/storage/remoteStorage/dist/accessPage.tsx.cache +222 -0
  61. package/storage/remoteStorage/dist/blobStore.ts.cache +837 -0
  62. package/storage/remoteStorage/dist/cliArgs.ts.cache +16 -0
  63. package/storage/remoteStorage/dist/createArchives.ts.cache +610 -0
  64. package/storage/remoteStorage/dist/remoteConfig.ts.cache +206 -0
  65. package/storage/remoteStorage/dist/sourceWrapper.ts.cache +223 -0
  66. package/storage/remoteStorage/dist/storageController.ts.cache +500 -0
  67. package/storage/remoteStorage/dist/storageServer.ts.cache +106 -0
  68. package/storage/remoteStorage/dist/storageServerCli.ts.cache +39 -0
  69. package/storage/remoteStorage/dist/storageServerState.ts.cache +518 -0
  70. package/storage/remoteStorage/remoteConfig.d.ts +8 -0
  71. package/storage/remoteStorage/remoteConfig.ts +105 -5
  72. package/storage/remoteStorage/sourceWrapper.d.ts +41 -0
  73. package/storage/remoteStorage/sourceWrapper.ts +223 -0
  74. package/storage/remoteStorage/spec.md +31 -0
  75. package/storage/remoteStorage/storageController.d.ts +11 -0
  76. package/storage/remoteStorage/storageController.ts +109 -40
  77. package/storage/remoteStorage/storageServer.d.ts +0 -5
  78. package/storage/remoteStorage/storageServer.ts +17 -10
  79. package/storage/remoteStorage/storageServerCli.ts +0 -3
  80. package/storage/remoteStorage/storageServerState.d.ts +7 -1
  81. package/storage/remoteStorage/storageServerState.ts +230 -48
  82. package/testsite/server.ts +0 -2
  83. package/yarn.lock +11 -6
@@ -0,0 +1,513 @@
1
+ "use strict";
2
+ // File format (all integers little-endian):
3
+ // u32 headerLength, then headerLength bytes of JSON: { rowCount, columns: [{ name, offset, length }] }, where offset is relative to the end of the header.
4
+ // Each column blob is: u32 offsets[rowCount + 1] (byte offsets into the column's data section), u8 types[rowCount], then the data section (each value's bytes, concatenated).
5
+ // Values are encoded with an explicit type tag per value (see the TYPE_ constants). Reads only fetch the byte ranges they need.
6
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
7
+ //exports.loadBulkDatabase = exports.loadBulkHeader = exports.buildFileBufferRaw = exports.buildFileBuffer = exports.assemblePlannedFile = exports.columnIndexByteLength = exports.TARGET_FILE_BYTES = exports.encodeValue = exports.TYPE_ABSENT_TAG = exports.ABSENT = exports.EMPTY_BUFFER = exports.KEY_COLUMN = void 0;
8
+ exports.KEY_COLUMN = "key";
9
+ // Every tag is an explicit constant baked into files on disk. NEVER renumber an existing tag — only add new ones — or every previously written file silently decodes wrong.
10
+ const TYPE_UNDEFINED = 0;
11
+ const TYPE_STRING = 1;
12
+ const TYPE_NUMBER = 2;
13
+ const TYPE_BOOLEAN = 3;
14
+ const TYPE_OBJECT = 4;
15
+ const TYPE_INT8_ARRAY = 5;
16
+ const TYPE_UINT8_ARRAY = 6;
17
+ const TYPE_UINT8_CLAMPED_ARRAY = 7;
18
+ const TYPE_INT16_ARRAY = 8;
19
+ const TYPE_UINT16_ARRAY = 9;
20
+ const TYPE_INT32_ARRAY = 10;
21
+ const TYPE_UINT32_ARRAY = 11;
22
+ const TYPE_FLOAT32_ARRAY = 12;
23
+ const TYPE_FLOAT64_ARRAY = 13;
24
+ // A cell whose row never set this column at all — as opposed to TYPE_UNDEFINED, an explicitly stored
25
+ // undefined. On read, ABSENT falls through to older readers for that column; a stored undefined stops
26
+ // the fall-through (it's a real value that clears the column).
27
+ const TYPE_ABSENT = 14;
28
+ const TYPED_ARRAY_TYPES = [
29
+ { type: TYPE_INT8_ARRAY, ctor: Int8Array },
30
+ { type: TYPE_UINT8_ARRAY, ctor: Uint8Array },
31
+ { type: TYPE_UINT8_CLAMPED_ARRAY, ctor: Uint8ClampedArray },
32
+ { type: TYPE_INT16_ARRAY, ctor: Int16Array },
33
+ { type: TYPE_UINT16_ARRAY, ctor: Uint16Array },
34
+ { type: TYPE_INT32_ARRAY, ctor: Int32Array },
35
+ { type: TYPE_UINT32_ARRAY, ctor: Uint32Array },
36
+ { type: TYPE_FLOAT32_ARRAY, ctor: Float32Array },
37
+ { type: TYPE_FLOAT64_ARRAY, ctor: Float64Array },
38
+ ];
39
+ exports.EMPTY_BUFFER = Buffer.alloc(0);
40
+ // Sentinel a reader returns for a cell whose row never set this column, so the join can fall through
41
+ // to an older reader for that column. Distinct from a stored undefined, which is a real clearing value.
42
+ exports.ABSENT = Symbol("absent");
43
+ // The type tag a cell carries when its row never set this column — read it from the column's `types`
44
+ // array to detect ABSENT without decoding. Re-exported so the merge planner (which works at the
45
+ // column-index level, no value materialization) can check it.
46
+ exports.TYPE_ABSENT_TAG = TYPE_ABSENT;
47
+ // Hidden per-row column holding each row's write-time (so reads can resolve a key to its latest value
48
+ // by actual time). NUL-prefixed so it can't collide with a user column; excluded from `columns`.
49
+ const TIME_COLUMN = String.fromCharCode(0) + "t";
50
+ function encodeValue(value) {
51
+ if (value === exports.ABSENT) {
52
+ return { type: TYPE_ABSENT, bytes: exports.EMPTY_BUFFER };
53
+ }
54
+ if (value === undefined || value === null) {
55
+ return { type: TYPE_UNDEFINED, bytes: exports.EMPTY_BUFFER };
56
+ }
57
+ if (typeof value === "string") {
58
+ return { type: TYPE_STRING, bytes: Buffer.from(value, "utf8") };
59
+ }
60
+ if (typeof value === "number") {
61
+ const bytes = Buffer.alloc(8);
62
+ bytes.writeDoubleLE(value, 0);
63
+ return { type: TYPE_NUMBER, bytes };
64
+ }
65
+ if (typeof value === "boolean") {
66
+ return { type: TYPE_BOOLEAN, bytes: Buffer.from([value && 1 || 0]) };
67
+ }
68
+ if (ArrayBuffer.isView(value)) {
69
+ if (value instanceof DataView) {
70
+ throw new Error(`DataView values are not supported, store a typed array instead`);
71
+ }
72
+ const entry = TYPED_ARRAY_TYPES.find(t => value instanceof t.ctor);
73
+ if (!entry) {
74
+ throw new Error(`Unsupported typed array type ${value.constructor.name}`);
75
+ }
76
+ return {
77
+ type: entry.type,
78
+ bytes: Buffer.from(value.buffer, value.byteOffset, value.byteLength),
79
+ };
80
+ }
81
+ if (typeof value !== "object") {
82
+ throw new Error(`Unsupported value type ${typeof value}`);
83
+ }
84
+ return { type: TYPE_OBJECT, bytes: Buffer.from(JSON.stringify(value), "utf8") };
85
+ }
86
+ exports.encodeValue = encodeValue;
87
+ function decodeValue(type, bytes) {
88
+ if (type === TYPE_UNDEFINED)
89
+ return undefined;
90
+ if (type === TYPE_STRING)
91
+ return bytes.toString("utf8");
92
+ if (type === TYPE_NUMBER) {
93
+ if (bytes.length !== 8) {
94
+ throw new Error(`Expected 8 bytes for a number, was ${bytes.length}`);
95
+ }
96
+ return bytes.readDoubleLE(0);
97
+ }
98
+ if (type === TYPE_BOOLEAN) {
99
+ if (bytes.length !== 1) {
100
+ throw new Error(`Expected 1 byte for a boolean, was ${bytes.length}`);
101
+ }
102
+ return bytes[0] === 1;
103
+ }
104
+ if (type === TYPE_OBJECT)
105
+ return JSON.parse(bytes.toString("utf8"));
106
+ if (type === TYPE_ABSENT)
107
+ return exports.ABSENT;
108
+ const entry = TYPED_ARRAY_TYPES.find(t => t.type === type);
109
+ if (!entry) {
110
+ throw new Error(`Expected a valid type tag, was ${type}`);
111
+ }
112
+ const ctor = entry.ctor;
113
+ if (type === TYPE_UINT8_ARRAY)
114
+ return Buffer.from(bytes);
115
+ if (bytes.length % ctor.BYTES_PER_ELEMENT !== 0) {
116
+ throw new Error(`Expected byte length divisible by ${ctor.BYTES_PER_ELEMENT} for ${ctor.name}, was ${bytes.length}`);
117
+ }
118
+ // Copy to a fresh ArrayBuffer so the typed array view is aligned regardless of where the bytes landed in the source buffer.
119
+ const aligned = new ArrayBuffer(bytes.length);
120
+ new Uint8Array(aligned).set(bytes);
121
+ return new ctor(aligned);
122
+ }
123
+ function encodeBulkData(data) {
124
+ const n = data.length;
125
+ const offsets = Buffer.alloc(4 * (n + 1));
126
+ const types = Buffer.alloc(n);
127
+ const parts = [];
128
+ let pos = 0;
129
+ for (let i = 0; i < n; i++) {
130
+ const { type, bytes } = encodeValue(data[i]);
131
+ offsets.writeUInt32LE(pos, 4 * i);
132
+ types[i] = type;
133
+ parts.push(bytes);
134
+ pos += bytes.length;
135
+ }
136
+ offsets.writeUInt32LE(pos, 4 * n);
137
+ return Buffer.concat([offsets, types, ...parts]);
138
+ }
139
+ // Like encodeBulkData but the values are already encoded (a merge supplies the winning cells' raw bytes
140
+ // straight from the input files). Lays out the same offsets / types / data section without touching the
141
+ // values themselves.
142
+ function encodeBulkDataRaw(cells) {
143
+ const n = cells.length;
144
+ const offsets = Buffer.alloc(4 * (n + 1));
145
+ const types = Buffer.alloc(n);
146
+ const parts = [];
147
+ let pos = 0;
148
+ for (let i = 0; i < n; i++) {
149
+ const { type, bytes } = cells[i];
150
+ offsets.writeUInt32LE(pos, 4 * i);
151
+ types[i] = type;
152
+ parts.push(bytes);
153
+ pos += bytes.length;
154
+ }
155
+ offsets.writeUInt32LE(pos, 4 * n);
156
+ return Buffer.concat([offsets, types, ...parts]);
157
+ }
158
+ function decodeBulkData(blob, rowCount) {
159
+ const indexSize = 4 * (rowCount + 1) + rowCount;
160
+ const values = [];
161
+ for (let i = 0; i < rowCount; i++) {
162
+ const start = blob.readUInt32LE(4 * i);
163
+ const end = blob.readUInt32LE(4 * (i + 1));
164
+ const type = blob[4 * (rowCount + 1) + i];
165
+ values.push(decodeValue(type, blob.subarray(indexSize + start, indexSize + end)));
166
+ }
167
+ return values;
168
+ }
169
+ // Target logical (uncompressed) size of one bulk file. A rows array bigger than this is split across
170
+ // multiple key-contiguous files, so files stay around this size (the merge policy's target) and no
171
+ // single column blob / Buffer.concat ever approaches the ~2GB Buffer length limit. The estimate is
172
+ // rough on purpose — it only needs to keep each chunk near the target, not be exact. A single row
173
+ // bigger than the target still becomes its own (oversized) file, since we never split within a key.
174
+ exports.TARGET_FILE_BYTES = 256 * 1024 * 1024;
175
+ // Per-value on-disk overhead: a 4-byte offset entry plus a 1-byte type tag.
176
+ const PER_VALUE_OVERHEAD = 5;
177
+ function estimateValueBytes(value) {
178
+ if (value === undefined || value === null)
179
+ return 0;
180
+ if (typeof value === "string")
181
+ return value.length * 2;
182
+ if (typeof value === "number")
183
+ return 8;
184
+ if (typeof value === "boolean")
185
+ return 1;
186
+ if (ArrayBuffer.isView(value))
187
+ return value.byteLength;
188
+ if (typeof value === "object")
189
+ return JSON.stringify(value).length;
190
+ return 0;
191
+ }
192
+ function estimateRowBytes(row) {
193
+ let total = 0;
194
+ for (const value of Object.values(row)) {
195
+ total += estimateValueBytes(value) + PER_VALUE_OVERHEAD;
196
+ }
197
+ return total;
198
+ }
199
+ // Concatenates already-encoded column blobs into a complete file (4-byte header length + header JSON +
200
+ // blobs), computing the header's time + key bounds from the per-row times and keys. Shared by the
201
+ // object-based builder (buildOneFile) and the raw-splice builder (buildOneFileRaw).
202
+ function assembleFile(columnNames, blobs, rowCount, times, keys) {
203
+ let offset = 0;
204
+ const columns = columnNames.map((name, i) => {
205
+ const entry = { name, offset, length: blobs[i].length };
206
+ offset += blobs[i].length;
207
+ return entry;
208
+ });
209
+ let minTime = times.length ? times[0] : 0;
210
+ let maxTime = minTime;
211
+ for (const t of times) {
212
+ if (t < minTime)
213
+ minTime = t;
214
+ if (t > maxTime)
215
+ maxTime = t;
216
+ }
217
+ let minKey;
218
+ let maxKey;
219
+ for (const key of keys) {
220
+ if (minKey === undefined || key < minKey)
221
+ minKey = key;
222
+ if (maxKey === undefined || key > maxKey)
223
+ maxKey = key;
224
+ }
225
+ const header = { rowCount, columns, minTime, maxTime, minKey, maxKey };
226
+ const headerBuf = Buffer.from(JSON.stringify(header), "utf8");
227
+ const lengthPrefix = Buffer.alloc(4);
228
+ lengthPrefix.writeUInt32LE(headerBuf.length, 0);
229
+ return Buffer.concat([lengthPrefix, headerBuf, ...blobs]);
230
+ }
231
+ function buildOneFile(rows, times) {
232
+ const columnNames = [];
233
+ const columnSet = new Set();
234
+ for (const row of rows) {
235
+ for (const field of Object.keys(row)) {
236
+ if (columnSet.has(field))
237
+ continue;
238
+ columnSet.add(field);
239
+ columnNames.push(field);
240
+ }
241
+ }
242
+ // A row that doesn't include a column stores ABSENT (fall-through), not undefined (a real value).
243
+ const blobs = columnNames.map(col => encodeBulkData(rows.map(row => col in row ? row[col] : exports.ABSENT)));
244
+ // The hidden per-row time column.
245
+ columnNames.push(TIME_COLUMN);
246
+ blobs.push(encodeBulkData(times));
247
+ return assembleFile(columnNames, blobs, rows.length, times, rows.map(r => r[exports.KEY_COLUMN]));
248
+ }
249
+ // Size of a column blob's INDEX section (offsets array + types array) for a column of N rows. The data
250
+ // section follows immediately after. The planned merge uses this to size output buffers exactly.
251
+ function columnIndexByteLength(rowCount) {
252
+ return 4 * (rowCount + 1) + rowCount;
253
+ }
254
+ exports.columnIndexByteLength = columnIndexByteLength;
255
+ // Assembles a complete bulk file from a set of pre-built value column blobs plus the keys + times. Auto-
256
+ // adds the KEY_COLUMN (keys) and hidden TIME_COLUMN (times) — they're small enough to encode in one shot
257
+ // here. Used by the planned merge: it builds each value column's blob by-hand (offsets/types + raw bytes
258
+ // copied directly from inputs, no value materialization) and hands the result here for header + bounds.
259
+ function assemblePlannedFile(config) {
260
+ const columnNames = [exports.KEY_COLUMN, ...config.valueColumns.map(c => c.name), TIME_COLUMN];
261
+ const blobs = [
262
+ encodeBulkData(config.keys),
263
+ ...config.valueColumns.map(c => c.blob),
264
+ encodeBulkData(config.times),
265
+ ];
266
+ return assembleFile(columnNames, blobs, config.keys.length, config.times, config.keys);
267
+ }
268
+ exports.assemblePlannedFile = assemblePlannedFile;
269
+ const ABSENT_CELL = { type: TYPE_ABSENT, bytes: exports.EMPTY_BUFFER };
270
+ function buildOneFileRaw(rows) {
271
+ // Columns present in this chunk, in first-seen order (matches buildOneFile, which only emits columns
272
+ // some row actually has).
273
+ const valueColumns = [];
274
+ const seen = new Set();
275
+ for (const row of rows)
276
+ for (const col of row.cells.keys()) {
277
+ if (seen.has(col))
278
+ continue;
279
+ seen.add(col);
280
+ valueColumns.push(col);
281
+ }
282
+ const columnNames = [exports.KEY_COLUMN, ...valueColumns, TIME_COLUMN];
283
+ const times = rows.map(r => r.time);
284
+ const blobs = [
285
+ encodeBulkData(rows.map(r => r.key)),
286
+ ...valueColumns.map(col => encodeBulkDataRaw(rows.map(r => { var _a; return (_a = r.cells.get(col)) !== null && _a !== void 0 ? _a : ABSENT_CELL; }))),
287
+ encodeBulkData(times),
288
+ ];
289
+ return assembleFile(columnNames, blobs, rows.length, times, rows.map(r => r.key));
290
+ }
291
+ function estimateRawRowBytes(row) {
292
+ let total = row.key.length * 2 + PER_VALUE_OVERHEAD;
293
+ for (const cell of row.cells.values())
294
+ total += cell.bytes.length + PER_VALUE_OVERHEAD;
295
+ return total;
296
+ }
297
+ // Returns one complete, independent file per chunk of rows. Rows are first sorted by key, then
298
+ // partitioned into key-contiguous chunks of ~targetBytes each — so every returned file is key-sorted
299
+ // (tight minKey/maxKey for the read-skip + merge planner) and stays near the target size, and no
300
+ // single column blob / Buffer.concat approaches the ~2GB limit. The chunks have disjoint key ranges,
301
+ // so the caller just writes each as its own file. A normal-sized write returns a single file.
302
+ // `times[i]` is row i's write-time, stored per row so reads resolve a key to its latest value by time.
303
+ function buildFileBuffer(rows, times, targetBytes = exports.TARGET_FILE_BYTES) {
304
+ // A chunk is already key-sorted, so its first/last row are its min/max key.
305
+ const make = (rs, ts) => ({
306
+ buffer: buildOneFile(rs, ts),
307
+ minKey: rs.length ? rs[0][exports.KEY_COLUMN] : "",
308
+ maxKey: rs.length ? rs[rs.length - 1][exports.KEY_COLUMN] : "",
309
+ rowCount: rs.length,
310
+ });
311
+ if (rows.length === 0)
312
+ return [make([], [])];
313
+ // Sort rows + their times together by key so each output file is key-contiguous.
314
+ const order = rows.map((_, i) => i).sort((a, b) => {
315
+ const ka = rows[a][exports.KEY_COLUMN];
316
+ const kb = rows[b][exports.KEY_COLUMN];
317
+ return ka < kb ? -1 : ka > kb ? 1 : 0;
318
+ });
319
+ const sortedRows = order.map(i => rows[i]);
320
+ const sortedTimes = order.map(i => times[i]);
321
+ const result = [];
322
+ let chunkStart = 0;
323
+ let chunkBytes = 0;
324
+ for (let i = 0; i < sortedRows.length; i++) {
325
+ const rowBytes = estimateRowBytes(sortedRows[i]);
326
+ if (i > chunkStart && chunkBytes + rowBytes > targetBytes) {
327
+ result.push(make(sortedRows.slice(chunkStart, i), sortedTimes.slice(chunkStart, i)));
328
+ chunkStart = i;
329
+ chunkBytes = 0;
330
+ }
331
+ chunkBytes += rowBytes;
332
+ }
333
+ result.push(make(sortedRows.slice(chunkStart), sortedTimes.slice(chunkStart)));
334
+ return result;
335
+ }
336
+ exports.buildFileBuffer = buildFileBuffer;
337
+ // The raw-splice counterpart of buildFileBuffer, used by merges: the rows already carry their winning
338
+ // cells as raw on-disk bytes (no JS values), so this just sorts by key, chunks to ~targetBytes, and
339
+ // concatenates the bytes. Same output guarantees: key-contiguous, disjoint, ascending files.
340
+ function buildFileBufferRaw(rows, targetBytes = exports.TARGET_FILE_BYTES) {
341
+ const make = (rs) => ({
342
+ buffer: buildOneFileRaw(rs),
343
+ minKey: rs.length ? rs[0].key : "",
344
+ maxKey: rs.length ? rs[rs.length - 1].key : "",
345
+ rowCount: rs.length,
346
+ });
347
+ if (rows.length === 0)
348
+ return [make([])];
349
+ const sorted = rows.slice().sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);
350
+ const result = [];
351
+ let chunkStart = 0;
352
+ let chunkBytes = 0;
353
+ for (let i = 0; i < sorted.length; i++) {
354
+ const rowBytes = estimateRawRowBytes(sorted[i]);
355
+ if (i > chunkStart && chunkBytes + rowBytes > targetBytes) {
356
+ result.push(make(sorted.slice(chunkStart, i)));
357
+ chunkStart = i;
358
+ chunkBytes = 0;
359
+ }
360
+ chunkBytes += rowBytes;
361
+ }
362
+ result.push(make(sorted.slice(chunkStart)));
363
+ return result;
364
+ }
365
+ exports.buildFileBufferRaw = buildFileBufferRaw;
366
+ async function loadBulkHeader(getRange, totalBytes) {
367
+ const headerLength = (await getRange(0, 4)).readUInt32LE(0);
368
+ if (headerLength <= 0 || headerLength > totalBytes) {
369
+ throw new Error(`Expected header length in (0, ${totalBytes}], was ${headerLength}`);
370
+ }
371
+ const header = JSON.parse((await getRange(4, 4 + headerLength)).toString("utf8"));
372
+ return {
373
+ rowCount: header.rowCount,
374
+ minTime: header.minTime || 0,
375
+ maxTime: header.maxTime || 0,
376
+ minKey: header.minKey,
377
+ maxKey: header.maxKey,
378
+ columns: header.columns.filter(c => c.name !== TIME_COLUMN).map(c => ({ column: c.name, byteSize: c.length })),
379
+ };
380
+ }
381
+ exports.loadBulkHeader = loadBulkHeader;
382
+ async function loadBulkDatabase(config) {
383
+ const headerLength = (await config.getRange(0, 4)).readUInt32LE(0);
384
+ if (headerLength <= 0 || headerLength > config.totalBytes) {
385
+ throw new Error(`Expected header length in (0, ${config.totalBytes}], was ${headerLength}`);
386
+ }
387
+ const header = JSON.parse((await config.getRange(4, 4 + headerLength)).toString("utf8"));
388
+ const dataBase = 4 + headerLength;
389
+ const rowCount = header.rowCount;
390
+ const colByName = new Map(header.columns.map(c => [c.name, c]));
391
+ async function readWholeColumn(column) {
392
+ const col = colByName.get(column);
393
+ if (!col) {
394
+ throw new Error(`Expected column ${column}, file only has: ${header.columns.map(c => c.name).join(", ")}`);
395
+ }
396
+ const blob = await config.getRange(dataBase + col.offset, dataBase + col.offset + col.length);
397
+ return decodeBulkData(blob, rowCount);
398
+ }
399
+ const keys = (await readWholeColumn(exports.KEY_COLUMN)).map(v => {
400
+ var _a;
401
+ if (typeof v !== "string") {
402
+ throw new Error(`Expected string key, was ${typeof v}: ${(_a = JSON.stringify(v)) === null || _a === void 0 ? void 0 : _a.slice(0, 500)}`);
403
+ }
404
+ return v;
405
+ });
406
+ const keyIndex = new Map(keys.map((key, i) => [key, i]));
407
+ // Per-row write-times. Old files (written before this column existed) fall back to the file's header
408
+ // time (or 0) for every row — fine, since such files predate concurrent-time resolution.
409
+ const times = colByName.has(TIME_COLUMN)
410
+ ? (await readWholeColumn(TIME_COLUMN)).map(v => typeof v === "number" ? v : 0)
411
+ : keys.map(() => header.maxTime || 0);
412
+ return {
413
+ name: config.name,
414
+ rowCount,
415
+ totalBytes: config.totalBytes,
416
+ minTime: header.minTime || 0,
417
+ maxTime: header.maxTime || 0,
418
+ minKey: header.minKey,
419
+ maxKey: header.maxKey,
420
+ keys,
421
+ keyTimes: new Map(keys.map((key, i) => [key, times[i]])),
422
+ columns: header.columns.filter(c => c.name !== TIME_COLUMN).map(c => ({ column: c.name, byteSize: c.length })),
423
+ async getColumn(column) {
424
+ const values = await readWholeColumn(column);
425
+ return keys.map((key, i) => ({ key, value: values[i], time: times[i] }));
426
+ },
427
+ async getRawColumn(column) {
428
+ const map = new Map();
429
+ const col = colByName.get(column);
430
+ if (!col)
431
+ return map; // file lacks this column → every cell ABSENT (fall through)
432
+ const blob = await config.getRange(dataBase + col.offset, dataBase + col.offset + col.length);
433
+ const indexSize = 4 * (rowCount + 1) + rowCount;
434
+ for (let i = 0; i < rowCount; i++) {
435
+ const type = blob[4 * (rowCount + 1) + i];
436
+ if (type === TYPE_ABSENT)
437
+ continue; // omit ABSENT so the join falls through
438
+ const start = blob.readUInt32LE(4 * i);
439
+ const end = blob.readUInt32LE(4 * (i + 1));
440
+ map.set(keys[i], { type, bytes: blob.subarray(indexSize + start, indexSize + end) });
441
+ }
442
+ return map;
443
+ },
444
+ async getColumnIndex(column) {
445
+ const col = colByName.get(column);
446
+ if (!col) {
447
+ // File lacks this column — present an all-ABSENT index so the planner can treat it
448
+ // uniformly with files that have the column.
449
+ const offsets = new Uint32Array(rowCount + 1);
450
+ const types = new Uint8Array(rowCount).fill(TYPE_ABSENT);
451
+ return {
452
+ offsets,
453
+ types,
454
+ async readValueBytes() { return exports.EMPTY_BUFFER; },
455
+ };
456
+ }
457
+ const colBase = dataBase + col.offset;
458
+ const indexSize = 4 * (rowCount + 1) + rowCount;
459
+ // One read pulls offsets + types (small — ~5 B/row). Block cache makes subsequent value reads
460
+ // of nearby rows cheap. Decoded into aligned typed arrays so the executor can do O(1) lookups.
461
+ const indexBuf = await config.getRange(colBase, colBase + indexSize);
462
+ const offsets = new Uint32Array(rowCount + 1);
463
+ for (let i = 0; i <= rowCount; i++)
464
+ offsets[i] = indexBuf.readUInt32LE(4 * i);
465
+ const types = new Uint8Array(rowCount);
466
+ for (let i = 0; i < rowCount; i++)
467
+ types[i] = indexBuf[4 * (rowCount + 1) + i];
468
+ const dataStart = colBase + indexSize;
469
+ return {
470
+ offsets,
471
+ types,
472
+ async readValueBytes(startRow, endRow) {
473
+ if (endRow <= startRow)
474
+ return exports.EMPTY_BUFFER;
475
+ const start = offsets[startRow];
476
+ const end = offsets[endRow];
477
+ if (end <= start)
478
+ return exports.EMPTY_BUFFER;
479
+ return config.getRange(dataStart + start, dataStart + end);
480
+ },
481
+ };
482
+ },
483
+ rowOfKey(key) {
484
+ return keyIndex.get(key);
485
+ },
486
+ async getSingleField(key, column) {
487
+ const row = keyIndex.get(key);
488
+ if (row === undefined)
489
+ return exports.ABSENT;
490
+ const col = colByName.get(column);
491
+ if (!col)
492
+ return exports.ABSENT;
493
+ const colBase = dataBase + col.offset;
494
+ const offsetsBuf = await config.getRange(colBase + 4 * row, colBase + 4 * row + 8);
495
+ const start = offsetsBuf.readUInt32LE(0);
496
+ const end = offsetsBuf.readUInt32LE(4);
497
+ const typePos = colBase + 4 * (rowCount + 1) + row;
498
+ const typeBuf = await config.getRange(typePos, typePos + 1);
499
+ const dataStart = colBase + 4 * (rowCount + 1) + rowCount;
500
+ let bytes = exports.EMPTY_BUFFER;
501
+ if (end > start) {
502
+ bytes = await config.getRange(dataStart + start, dataStart + end);
503
+ }
504
+ const value = decodeValue(typeBuf[0], bytes);
505
+ if (value === exports.ABSENT)
506
+ return exports.ABSENT;
507
+ return { value, time: times[row] };
508
+ },
509
+ };
510
+ }
511
+ exports.loadBulkDatabase = loadBulkDatabase;
512
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQnVsa0RhdGFiYXNlRm9ybWF0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiQnVsa0RhdGFiYXNlRm9ybWF0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSw0Q0FBNEM7QUFDNUMsNkpBQTZKO0FBQzdKLGdMQUFnTDtBQUNoTCxnSUFBZ0k7OztBQUVuSCxRQUFBLFVBQVUsR0FBRyxLQUFLLENBQUM7QUFFaEMsNEtBQTRLO0FBQzVLLE1BQU0sY0FBYyxHQUFHLENBQUMsQ0FBQztBQUN6QixNQUFNLFdBQVcsR0FBRyxDQUFDLENBQUM7QUFDdEIsTUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFDO0FBQ3RCLE1BQU0sWUFBWSxHQUFHLENBQUMsQ0FBQztBQUN2QixNQUFNLFdBQVcsR0FBRyxDQUFDLENBQUM7QUFDdEIsTUFBTSxlQUFlLEdBQUcsQ0FBQyxDQUFDO0FBQzFCLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDO0FBQzNCLE1BQU0sd0JBQXdCLEdBQUcsQ0FBQyxDQUFDO0FBQ25DLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDO0FBQzNCLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxDQUFDO0FBQzVCLE1BQU0sZ0JBQWdCLEdBQUcsRUFBRSxDQUFDO0FBQzVCLE1BQU0saUJBQWlCLEdBQUcsRUFBRSxDQUFDO0FBQzdCLE1BQU0sa0JBQWtCLEdBQUcsRUFBRSxDQUFDO0FBQzlCLE1BQU0sa0JBQWtCLEdBQUcsRUFBRSxDQUFDO0FBQzlCLHFHQUFxRztBQUNyRyxzR0FBc0c7QUFDdEcsK0RBQStEO0FBQy9ELE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQztBQUV2QixNQUFNLGlCQUFpQixHQUFxSDtJQUN4SSxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRTtJQUMxQyxFQUFFLElBQUksRUFBRSxnQkFBZ0IsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFO0lBQzVDLEVBQUUsSUFBSSxFQUFFLHdCQUF3QixFQUFFLElBQUksRUFBRSxpQkFBaUIsRUFBRTtJQUMzRCxFQUFFLElBQUksRUFBRSxnQkFBZ0IsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFO0lBQzVDLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFLElBQUksRUFBRSxXQUFXLEVBQUU7SUFDOUMsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRTtJQUM1QyxFQUFFLElBQUksRUFBRSxpQkFBaUIsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFO0lBQzlDLEVBQUUsSUFBSSxFQUFFLGtCQUFrQixFQUFFLElBQUksRUFBRSxZQUFZLEVBQUU7SUFDaEQsRUFBRSxJQUFJLEVBQUUsa0JBQWtCLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRTtDQUNuRCxDQUFDO0FBRVcsUUFBQSxZQUFZLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQVcsQ0FBQztBQUV0RCxxR0FBcUc7QUFDckcsd0dBQXdHO0FBQzNGLFFBQUEsTUFBTSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQVN2QyxxR0FBcUc7QUFDckcsZ0dBQWdHO0FBQ2hHLDhEQUE4RDtBQUNqRCxRQUFBLGVBQWUsR0FBRyxXQUFXLENBQUM7QUFtQjNDLHNHQUFzRztBQUN0RyxpR0FBaUc7QUFDakcsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUM7QUFpQmpELFNBQWdCLFdBQVcsQ0FBQyxLQUFjO0lBQ3RDLElBQUksS0FBSyxLQUFLLGNBQU0sRUFBRSxDQUFDO1FBQ25CLE9BQU8sRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEtBQUssRUFBRSxvQkFBWSxFQUFFLENBQUM7SUFDdEQsQ0FBQztJQUNELElBQUksS0FBSyxLQUFLLFNBQVMsSUFBSSxLQUFLLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDeEMsT0FBTyxFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsS0FBSyxFQUFFLG9CQUFZLEVBQUUsQ0FBQztJQUN6RCxDQUFDO0lBQ0QsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUM1QixPQUFPLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLEVBQUUsQ0FBQztJQUNwRSxDQUFDO0lBQ0QsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUM1QixNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzlCLEtBQUssQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzlCLE9BQU8sRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLEtBQUssRUFBRSxDQUFDO0lBQ3hDLENBQUM7SUFDRCxJQUFJLE9BQU8sS0FBSyxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQzdCLE9BQU8sRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDekUsQ0FBQztJQUNELElBQUksV0FBVyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQzVCLElBQUksS0FBSyxZQUFZLFFBQVEsRUFBRSxDQUFDO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0VBQWdFLENBQUMsQ0FBQztRQUN0RixDQUFDO1FBQ0QsTUFBTSxLQUFLLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNuRSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDVCxNQUFNLElBQUksS0FBSyxDQUFDLGdDQUFnQyxLQUFLLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7UUFDOUUsQ0FBQztRQUNELE9BQU87WUFDSCxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUk7WUFDaEIsS0FBSyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVLENBQUM7U0FDdkUsQ0FBQztJQUNOLENBQUM7SUFDRCxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsMEJBQTBCLE9BQU8sS0FBSyxFQUFFLENBQUMsQ0FBQztJQUM5RCxDQUFDO0lBQ0QsT0FBTyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxNQUFNLENBQUMsRUFBRSxDQUFDO0FBQ3BGLENBQUM7QUFuQ0Qsa0NBbUNDO0FBRUQsU0FBUyxXQUFXLENBQUMsSUFBWSxFQUFFLEtBQWE7SUFDNUMsSUFBSSxJQUFJLEtBQUssY0FBYztRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQzlDLElBQUksSUFBSSxLQUFLLFdBQVc7UUFBRSxPQUFPLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDeEQsSUFBSSxJQUFJLEtBQUssV0FBVyxFQUFFLENBQUM7UUFDdkIsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3JCLE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQzFFLENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDakMsQ0FBQztJQUNELElBQUksSUFBSSxLQUFLLFlBQVksRUFBRSxDQUFDO1FBQ3hCLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNyQixNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUMxRSxDQUFDO1FBQ0QsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzFCLENBQUM7SUFDRCxJQUFJLElBQUksS0FBSyxXQUFXO1FBQUUsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNwRSxJQUFJLElBQUksS0FBSyxXQUFXO1FBQUUsT0FBTyxjQUFNLENBQUM7SUFDeEMsTUFBTSxLQUFLLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQztJQUMzRCxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDVCxNQUFNLElBQUksS0FBSyxDQUFDLGtDQUFrQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzlELENBQUM7SUFDRCxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDO0lBQ3hCLElBQUksSUFBSSxLQUFLLGdCQUFnQjtRQUFFLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN6RCxJQUFJLEtBQUssQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixLQUFLLENBQUMsRUFBRSxDQUFDO1FBQzlDLE1BQU0sSUFBSSxLQUFLLENBQUMscUNBQXFDLElBQUksQ0FBQyxpQkFBaUIsUUFBUSxJQUFJLENBQUMsSUFBSSxTQUFTLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQ3pILENBQUM7SUFDRCw0SEFBNEg7SUFDNUgsTUFBTSxPQUFPLEdBQUcsSUFBSSxXQUFXLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzlDLElBQUksVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNuQyxPQUFPLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQzdCLENBQUM7QUFFRCxTQUFTLGNBQWMsQ0FBQyxJQUFlO0lBQ25DLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDdEIsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxQyxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlCLE1BQU0sS0FBSyxHQUFhLEVBQUUsQ0FBQztJQUMzQixJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDWixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDekIsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0MsT0FBTyxDQUFDLGFBQWEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ2xDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUM7UUFDaEIsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNsQixHQUFHLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQztJQUN4QixDQUFDO0lBQ0QsT0FBTyxDQUFDLGFBQWEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQ3JELENBQUM7QUFFRCx3R0FBd0c7QUFDeEcsd0dBQXdHO0FBQ3hHLHFCQUFxQjtBQUNyQixTQUFTLGlCQUFpQixDQUFDLEtBQWdCO0lBQ3ZDLE1BQU0sQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7SUFDdkIsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxQyxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlCLE1BQU0sS0FBSyxHQUFhLEVBQUUsQ0FBQztJQUMzQixJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDWixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDekIsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ2xDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUM7UUFDaEIsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNsQixHQUFHLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQztJQUN4QixDQUFDO0lBQ0QsT0FBTyxDQUFDLGFBQWEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQ3JELENBQUM7QUFFRCxTQUFTLGNBQWMsQ0FBQyxJQUFZLEVBQUUsUUFBZ0I7SUFDbEQsTUFBTSxTQUFTLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxHQUFHLFFBQVEsQ0FBQztJQUNoRCxNQUFNLE1BQU0sR0FBYyxFQUFFLENBQUM7SUFDN0IsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFFBQVEsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ2hDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0MsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUMxQyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEdBQUcsS0FBSyxFQUFFLFNBQVMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEYsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2xCLENBQUM7QUFFRCxxR0FBcUc7QUFDckcsbUdBQW1HO0FBQ25HLG1HQUFtRztBQUNuRyxrR0FBa0c7QUFDbEcsb0dBQW9HO0FBQ3ZGLFFBQUEsaUJBQWlCLEdBQUcsR0FBRyxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFFbkQsNEVBQTRFO0FBQzVFLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxDQUFDO0FBRTdCLFNBQVMsa0JBQWtCLENBQUMsS0FBYztJQUN0QyxJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxLQUFLLElBQUk7UUFBRSxPQUFPLENBQUMsQ0FBQztJQUNwRCxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVE7UUFBRSxPQUFPLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZELElBQUksT0FBTyxLQUFLLEtBQUssUUFBUTtRQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3hDLElBQUksT0FBTyxLQUFLLEtBQUssU0FBUztRQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3pDLElBQUksV0FBVyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUM7UUFBRSxPQUFPLEtBQUssQ0FBQyxVQUFVLENBQUM7SUFDdkQsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRO1FBQUUsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQztJQUNuRSxPQUFPLENBQUMsQ0FBQztBQUNiLENBQUM7QUFFRCxTQUFTLGdCQUFnQixDQUFDLEdBQTRCO0lBQ2xELElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztJQUNkLEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3JDLEtBQUssSUFBSSxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsR0FBRyxrQkFBa0IsQ0FBQztJQUM1RCxDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDakIsQ0FBQztBQUVELHVHQUF1RztBQUN2RyxrR0FBa0c7QUFDbEcsb0ZBQW9GO0FBQ3BGLFNBQVMsWUFBWSxDQUFDLFdBQXFCLEVBQUUsS0FBZSxFQUFFLFFBQWdCLEVBQUUsS0FBZSxFQUFFLElBQWM7SUFDM0csSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ2YsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUN4QyxNQUFNLEtBQUssR0FBRyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUN4RCxNQUFNLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztRQUMxQixPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDLENBQUMsQ0FBQztJQUNILElBQUksT0FBTyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFDLElBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQztJQUN0QixLQUFLLE1BQU0sQ0FBQyxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQUMsSUFBSSxDQUFDLEdBQUcsT0FBTztZQUFFLE9BQU8sR0FBRyxDQUFDLENBQUM7UUFBQyxJQUFJLENBQUMsR0FBRyxPQUFPO1lBQUUsT0FBTyxHQUFHLENBQUMsQ0FBQztJQUFDLENBQUM7SUFDdEYsSUFBSSxNQUEwQixDQUFDO0lBQy9CLElBQUksTUFBMEIsQ0FBQztJQUMvQixLQUFLLE1BQU0sR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ3JCLElBQUksTUFBTSxLQUFLLFNBQVMsSUFBSSxHQUFHLEdBQUcsTUFBTTtZQUFFLE1BQU0sR0FBRyxHQUFHLENBQUM7UUFDdkQsSUFBSSxNQUFNLEtBQUssU0FBUyxJQUFJLEdBQUcsR0FBRyxNQUFNO1lBQUUsTUFBTSxHQUFHLEdBQUcsQ0FBQztJQUMzRCxDQUFDO0lBQ0QsTUFBTSxNQUFNLEdBQWUsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxDQUFDO0lBQ25GLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUM5RCxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JDLFlBQVksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxZQUFZLEVBQUUsU0FBUyxFQUFFLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUM5RCxDQUFDO0FBRUQsU0FBUyxZQUFZLENBQUMsSUFBK0IsRUFBRSxLQUFlO0lBQ2xFLE1BQU0sV0FBVyxHQUFhLEVBQUUsQ0FBQztJQUNqQyxNQUFNLFNBQVMsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO0lBQ3BDLEtBQUssTUFBTSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFDckIsS0FBSyxNQUFNLEtBQUssSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDbkMsSUFBSSxTQUFTLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQztnQkFBRSxTQUFTO1lBQ25DLFNBQVMsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDckIsV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM1QixDQUFDO0lBQ0wsQ0FBQztJQUNELGtHQUFrRztJQUNsRyxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLGNBQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0RyxrQ0FBa0M7SUFDbEMsV0FBVyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUM5QixLQUFLLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLE9BQU8sWUFBWSxDQUFDLFdBQVcsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxrQkFBVSxDQUFXLENBQUMsQ0FBQyxDQUFDO0FBQ3hHLENBQUM7QUFPRCx1R0FBdUc7QUFDdkcsaUdBQWlHO0FBQ2pHLFNBQWdCLHFCQUFxQixDQUFDLFFBQWdCO0lBQ2xELE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxHQUFHLFFBQVEsQ0FBQztBQUN6QyxDQUFDO0FBRkQsc0RBRUM7QUFFRCx5R0FBeUc7QUFDekcseUdBQXlHO0FBQ3pHLHlHQUF5RztBQUN6Ryx3R0FBd0c7QUFDeEcsU0FBZ0IsbUJBQW1CLENBQUMsTUFJbkM7SUFDRyxNQUFNLFdBQVcsR0FBRyxDQUFDLGtCQUFVLEVBQUUsR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUN2RixNQUFNLEtBQUssR0FBRztRQUNWLGNBQWMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDO1FBQzNCLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ3ZDLGNBQWMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDO0tBQy9CLENBQUM7SUFDRixPQUFPLFlBQVksQ0FBQyxXQUFXLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzNGLENBQUM7QUFaRCxrREFZQztBQUVELE1BQU0sV0FBVyxHQUFZLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsb0JBQVksRUFBRSxDQUFDO0FBRXhFLFNBQVMsZUFBZSxDQUFDLElBQWM7SUFDbkMscUdBQXFHO0lBQ3JHLDBCQUEwQjtJQUMxQixNQUFNLFlBQVksR0FBYSxFQUFFLENBQUM7SUFDbEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUMvQixLQUFLLE1BQU0sR0FBRyxJQUFJLElBQUk7UUFBRSxLQUFLLE1BQU0sR0FBRyxJQUFJLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUN6RCxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDO2dCQUFFLFNBQVM7WUFDNUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNkLFlBQVksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDM0IsQ0FBQztJQUNELE1BQU0sV0FBVyxHQUFHLENBQUMsa0JBQVUsRUFBRSxHQUFHLFlBQVksRUFBRSxXQUFXLENBQUMsQ0FBQztJQUMvRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BDLE1BQU0sS0FBSyxHQUFHO1FBQ1YsY0FBYyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEMsR0FBRyxZQUFZLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxXQUFDLE9BQUEsTUFBQSxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsbUNBQUksV0FBVyxDQUFBLEVBQUEsQ0FBQyxDQUFDLENBQUM7UUFDN0YsY0FBYyxDQUFDLEtBQUssQ0FBQztLQUN4QixDQUFDO0lBQ0YsT0FBTyxZQUFZLENBQUMsV0FBVyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQztBQUVELFNBQVMsbUJBQW1CLENBQUMsR0FBVztJQUNwQyxJQUFJLEtBQUssR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLEdBQUcsa0JBQWtCLENBQUM7SUFDcEQsS0FBSyxNQUFNLElBQUksSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRTtRQUFFLEtBQUssSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxrQkFBa0IsQ0FBQztJQUN2RixPQUFPLEtBQUssQ0FBQztBQUNqQixDQUFDO0FBTUQsK0ZBQStGO0FBQy9GLHFHQUFxRztBQUNyRyxpR0FBaUc7QUFDakcscUdBQXFHO0FBQ3JHLDhGQUE4RjtBQUM5Rix1R0FBdUc7QUFDdkcsU0FBZ0IsZUFBZSxDQUFDLElBQStCLEVBQUUsS0FBZSxFQUFFLFdBQVcsR0FBRyx5QkFBaUI7SUFDN0csNEVBQTRFO0lBQzVFLE1BQU0sSUFBSSxHQUFHLENBQUMsRUFBNkIsRUFBRSxFQUFZLEVBQWEsRUFBRSxDQUFDLENBQUM7UUFDdEUsTUFBTSxFQUFFLFlBQVksQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDO1FBQzVCLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsa0JBQVUsQ0FBWSxDQUFDLENBQUMsQ0FBQyxFQUFFO1FBQ3RELE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBRSxFQUFFLENBQUMsRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxrQkFBVSxDQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUU7UUFDbEUsUUFBUSxFQUFFLEVBQUUsQ0FBQyxNQUFNO0tBQ3RCLENBQUMsQ0FBQztJQUNILElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM3QyxpRkFBaUY7SUFDakYsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUM5QyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsa0JBQVUsQ0FBVyxDQUFDO1FBQ3pDLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxrQkFBVSxDQUFXLENBQUM7UUFDekMsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDMUMsQ0FBQyxDQUFDLENBQUM7SUFDSCxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0MsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzdDLE1BQU0sTUFBTSxHQUFnQixFQUFFLENBQUM7SUFDL0IsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0lBQ25CLElBQUksVUFBVSxHQUFHLENBQUMsQ0FBQztJQUNuQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3pDLE1BQU0sUUFBUSxHQUFHLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pELElBQUksQ0FBQyxHQUFHLFVBQVUsSUFBSSxVQUFVLEdBQUcsUUFBUSxHQUFHLFdBQVcsRUFBRSxDQUFDO1lBQ3hELE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxFQUFFLFdBQVcsQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNyRixVQUFVLEdBQUcsQ0FBQyxDQUFDO1lBQ2YsVUFBVSxHQUFHLENBQUMsQ0FBQztRQUNuQixDQUFDO1FBQ0QsVUFBVSxJQUFJLFFBQVEsQ0FBQztJQUMzQixDQUFDO0lBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsRUFBRSxXQUFXLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvRSxPQUFPLE1BQU0sQ0FBQztBQUNsQixDQUFDO0FBL0JELDBDQStCQztBQUVELHNHQUFzRztBQUN0RyxvR0FBb0c7QUFDcEcsNkZBQTZGO0FBQzdGLFNBQWdCLGtCQUFrQixDQUFDLElBQWMsRUFBRSxXQUFXLEdBQUcseUJBQWlCO0lBQzlFLE1BQU0sSUFBSSxHQUFHLENBQUMsRUFBWSxFQUFhLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0sRUFBRSxlQUFlLENBQUMsRUFBRSxDQUFDO1FBQzNCLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFO1FBQ2xDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUU7UUFDOUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxNQUFNO0tBQ3RCLENBQUMsQ0FBQztJQUNILElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3pDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkYsTUFBTSxNQUFNLEdBQWdCLEVBQUUsQ0FBQztJQUMvQixJQUFJLFVBQVUsR0FBRyxDQUFDLENBQUM7SUFDbkIsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0lBQ25CLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDckMsTUFBTSxRQUFRLEdBQUcsbUJBQW1CLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLEdBQUcsVUFBVSxJQUFJLFVBQVUsR0FBRyxRQUFRLEdBQUcsV0FBVyxFQUFFLENBQUM7WUFDeEQsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQy9DLFVBQVUsR0FBRyxDQUFDLENBQUM7WUFDZixVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ25CLENBQUM7UUFDRCxVQUFVLElBQUksUUFBUSxDQUFDO0lBQzNCLENBQUM7SUFDRCxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM1QyxPQUFPLE1BQU0sQ0FBQztBQUNsQixDQUFDO0FBdkJELGdEQXVCQztBQTZDTSxLQUFLLFVBQVUsY0FBYyxDQUFDLFFBQXlELEVBQUUsVUFBa0I7SUFDOUcsTUFBTSxZQUFZLEdBQUcsQ0FBQyxNQUFNLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUQsSUFBSSxZQUFZLElBQUksQ0FBQyxJQUFJLFlBQVksR0FBRyxVQUFVLEVBQUUsQ0FBQztRQUNqRCxNQUFNLElBQUksS0FBSyxDQUFDLGlDQUFpQyxVQUFVLFVBQVUsWUFBWSxFQUFFLENBQUMsQ0FBQztJQUN6RixDQUFDO0lBQ0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQWUsQ0FBQztJQUNoRyxPQUFPO1FBQ0gsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRO1FBQ3pCLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxJQUFJLENBQUM7UUFDNUIsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLElBQUksQ0FBQztRQUM1QixNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU07UUFDckIsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNO1FBQ3JCLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssV0FBVyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztLQUNqSCxDQUFDO0FBQ04sQ0FBQztBQWRELHdDQWNDO0FBRU0sS0FBSyxVQUFVLGdCQUFnQixDQUFDLE1BSXRDO0lBQ0csTUFBTSxZQUFZLEdBQUcsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ25FLElBQUksWUFBWSxJQUFJLENBQUMsSUFBSSxZQUFZLEdBQUcsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ3hELE1BQU0sSUFBSSxLQUFLLENBQUMsaUNBQWlDLE1BQU0sQ0FBQyxVQUFVLFVBQVUsWUFBWSxFQUFFLENBQUMsQ0FBQztJQUNoRyxDQUFDO0lBQ0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFlLENBQUM7SUFDdkcsTUFBTSxRQUFRLEdBQUcsQ0FBQyxHQUFHLFlBQVksQ0FBQztJQUNsQyxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDO0lBQ2pDLE1BQU0sU0FBUyxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVoRSxLQUFLLFVBQVUsZUFBZSxDQUFDLE1BQWM7UUFDekMsTUFBTSxHQUFHLEdBQUcsU0FBUyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDUCxNQUFNLElBQUksS0FBSyxDQUFDLG1CQUFtQixNQUFNLG9CQUFvQixNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQy9HLENBQUM7UUFDRCxNQUFNLElBQUksR0FBRyxNQUFNLE1BQU0sQ0FBQyxRQUFRLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUUsUUFBUSxHQUFHLEdBQUcsQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzlGLE9BQU8sY0FBYyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRUQsTUFBTSxJQUFJLEdBQUcsQ0FBQyxNQUFNLGVBQWUsQ0FBQyxrQkFBVSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUU7O1FBQ3JELElBQUksT0FBTyxDQUFDLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDeEIsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsT0FBTyxDQUFDLEtBQUssTUFBQSxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQywwQ0FBRSxLQUFLLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNqRyxDQUFDO1FBQ0QsT0FBTyxDQUFDLENBQUM7SUFDYixDQUFDLENBQUMsQ0FBQztJQUNILE1BQU0sUUFBUSxHQUFHLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFekQscUdBQXFHO0lBQ3JHLHlGQUF5RjtJQUN6RixNQUFNLEtBQUssR0FBYSxTQUFTLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQztRQUM5QyxDQUFDLENBQUMsQ0FBQyxNQUFNLGVBQWUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDOUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQztJQUUxQyxPQUFPO1FBQ0gsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJO1FBQ2pCLFFBQVE7UUFDUixVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQVU7UUFDN0IsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLElBQUksQ0FBQztRQUM1QixPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sSUFBSSxDQUFDO1FBQzVCLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTTtRQUNyQixNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU07UUFDckIsSUFBSTtRQUNKLFFBQVEsRUFBRSxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4RCxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFdBQVcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDOUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxNQUFNO1lBQ2xCLE1BQU0sTUFBTSxHQUFHLE1BQU0sZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzdDLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzdFLENBQUM7UUFDRCxLQUFLLENBQUMsWUFBWSxDQUFDLE1BQU07WUFDckIsTUFBTSxHQUFHLEdBQUcsSUFBSSxHQUFHLEVBQW1CLENBQUM7WUFDdkMsTUFBTSxHQUFHLEdBQUcsU0FBUyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNsQyxJQUFJLENBQUMsR0FBRztnQkFBRSxPQUFPLEdBQUcsQ0FBQyxDQUFDLDREQUE0RDtZQUNsRixNQUFNLElBQUksR0FBRyxNQUFNLE1BQU0sQ0FBQyxRQUFRLENBQUMsUUFBUSxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUUsUUFBUSxHQUFHLEdBQUcsQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzlGLE1BQU0sU0FBUyxHQUFHLENBQUMsR0FBRyxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUM7WUFDaEQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFFBQVEsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUNoQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUMxQyxJQUFJLElBQUksS0FBSyxXQUFXO29CQUFFLFNBQVMsQ0FBQyx3Q0FBd0M7Z0JBQzVFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUN2QyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUMzQyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEdBQUcsS0FBSyxFQUFFLFNBQVMsR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDekYsQ0FBQztZQUNELE9BQU8sR0FBRyxDQUFDO1FBQ2YsQ0FBQztRQUNELEtBQUssQ0FBQyxjQUFjLENBQUMsTUFBTTtZQUN2QixNQUFNLEdBQUcsR0FBRyxTQUFTLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2xDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDUCxtRkFBbUY7Z0JBQ25GLDZDQUE2QztnQkFDN0MsTUFBTSxPQUFPLEdBQUcsSUFBSSxXQUFXLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUM5QyxNQUFNLEtBQUssR0FBRyxJQUFJLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQ3pELE9BQU87b0JBQ0gsT0FBTztvQkFDUCxLQUFLO29CQUNMLEtBQUssQ0FBQyxjQUFjLEtBQUssT0FBTyxvQkFBWSxDQUFDLENBQUMsQ0FBQztpQkFDbEQsQ0FBQztZQUNOLENBQUM7WUFDRCxNQUFNLE9BQU8sR0FBRyxRQUFRLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQztZQUN0QyxNQUFNLFNBQVMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDLEdBQUcsUUFBUSxDQUFDO1lBQ2hELDhGQUE4RjtZQUM5RiwrRkFBK0Y7WUFDL0YsTUFBTSxRQUFRLEdBQUcsTUFBTSxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxPQUFPLEdBQUcsU0FBUyxDQUFDLENBQUM7WUFDckUsTUFBTSxPQUFPLEdBQUcsSUFBSSxXQUFXLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQzlDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxRQUFRLEVBQUUsQ0FBQyxFQUFFO2dCQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUM5RSxNQUFNLEtBQUssR0FBRyxJQUFJLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUN2QyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxFQUFFLENBQUMsRUFBRTtnQkFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUMvRSxNQUFNLFNBQVMsR0FBRyxPQUFPLEdBQUcsU0FBUyxDQUFDO1lBQ3RDLE9BQU87Z0JBQ0gsT0FBTztnQkFDUCxLQUFLO2dCQUNMLEtBQUssQ0FBQyxjQUFjLENBQUMsUUFBUSxFQUFFLE1BQU07b0JBQ2pDLElBQUksTUFBTSxJQUFJLFFBQVE7d0JBQUUsT0FBTyxvQkFBWSxDQUFDO29CQUM1QyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7b0JBQ2hDLE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztvQkFDNUIsSUFBSSxHQUFHLElBQUksS0FBSzt3QkFBRSxPQUFPLG9CQUFZLENBQUM7b0JBQ3RDLE9BQU8sTUFBTSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEdBQUcsS0FBSyxFQUFFLFNBQVMsR0FBRyxHQUFHLENBQUMsQ0FBQztnQkFDL0QsQ0FBQzthQUNKLENBQUM7UUFDTixDQUFDO1FBQ0QsUUFBUSxDQUFDLEdBQUc7WUFDUixPQUFPLFFBQVEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDN0IsQ0FBQztRQUNELEtBQUssQ0FBQyxjQUFjLENBQUMsR0FBRyxFQUFFLE1BQU07WUFDNUIsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUM5QixJQUFJLEdBQUcsS0FBSyxTQUFTO2dCQUFFLE9BQU8sY0FBTSxDQUFDO1lBQ3JDLE1BQU0sR0FBRyxHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDbEMsSUFBSSxDQUFDLEdBQUc7Z0JBQUUsT0FBTyxjQUFNLENBQUM7WUFDeEIsTUFBTSxPQUFPLEdBQUcsUUFBUSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUM7WUFDdEMsTUFBTSxVQUFVLEdBQUcsTUFBTSxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sR0FBRyxDQUFDLEdBQUcsR0FBRyxFQUFFLE9BQU8sR0FBRyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ25GLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDekMsTUFBTSxHQUFHLEdBQUcsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN2QyxNQUFNLE9BQU8sR0FBRyxPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQztZQUNuRCxNQUFNLE9BQU8sR0FBRyxNQUFNLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQztZQUM1RCxNQUFNLFNBQVMsR0FBRyxPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxHQUFHLFFBQVEsQ0FBQztZQUMxRCxJQUFJLEtBQUssR0FBRyxvQkFBWSxDQUFDO1lBQ3pCLElBQUksR0FBRyxHQUFHLEtBQUssRUFBRSxDQUFDO2dCQUNkLEtBQUssR0FBRyxNQUFNLE1BQU0sQ0FBQyxRQUFRLENBQUMsU0FBUyxHQUFHLEtBQUssRUFBRSxTQUFTLEdBQUcsR0FBRyxDQUFDLENBQUM7WUFDdEUsQ0FBQztZQUNELE1BQU0sS0FBSyxHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDN0MsSUFBSSxLQUFLLEtBQUssY0FBTTtnQkFBRSxPQUFPLGNBQU0sQ0FBQztZQUNwQyxPQUFPLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUN2QyxDQUFDO0tBQ0osQ0FBQztBQUNOLENBQUM7QUE5SEQsNENBOEhDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gRmlsZSBmb3JtYXQgKGFsbCBpbnRlZ2VycyBsaXR0bGUtZW5kaWFuKTpcbi8vICAgdTMyIGhlYWRlckxlbmd0aCwgdGhlbiBoZWFkZXJMZW5ndGggYnl0ZXMgb2YgSlNPTjogeyByb3dDb3VudCwgY29sdW1uczogW3sgbmFtZSwgb2Zmc2V0LCBsZW5ndGggfV0gfSwgd2hlcmUgb2Zmc2V0IGlzIHJlbGF0aXZlIHRvIHRoZSBlbmQgb2YgdGhlIGhlYWRlci5cbi8vICAgRWFjaCBjb2x1bW4gYmxvYiBpczogdTMyIG9mZnNldHNbcm93Q291bnQgKyAxXSAoYnl0ZSBvZmZzZXRzIGludG8gdGhlIGNvbHVtbidzIGRhdGEgc2VjdGlvbiksIHU4IHR5cGVzW3Jvd0NvdW50XSwgdGhlbiB0aGUgZGF0YSBzZWN0aW9uIChlYWNoIHZhbHVlJ3MgYnl0ZXMsIGNvbmNhdGVuYXRlZCkuXG4vLyBWYWx1ZXMgYXJlIGVuY29kZWQgd2l0aCBhbiBleHBsaWNpdCB0eXBlIHRhZyBwZXIgdmFsdWUgKHNlZSB0aGUgVFlQRV8gY29uc3RhbnRzKS4gUmVhZHMgb25seSBmZXRjaCB0aGUgYnl0ZSByYW5nZXMgdGhleSBuZWVkLlxuXG5leHBvcnQgY29uc3QgS0VZX0NPTFVNTiA9IFwia2V5XCI7XG5cbi8vIEV2ZXJ5IHRhZyBpcyBhbiBleHBsaWNpdCBjb25zdGFudCBiYWtlZCBpbnRvIGZpbGVzIG9uIGRpc2suIE5FVkVSIHJlbnVtYmVyIGFuIGV4aXN0aW5nIHRhZyDigJQgb25seSBhZGQgbmV3IG9uZXMg4oCUIG9yIGV2ZXJ5IHByZXZpb3VzbHkgd3JpdHRlbiBmaWxlIHNpbGVudGx5IGRlY29kZXMgd3JvbmcuXG5jb25zdCBUWVBFX1VOREVGSU5FRCA9IDA7XG5jb25zdCBUWVBFX1NUUklORyA9IDE7XG5jb25zdCBUWVBFX05VTUJFUiA9IDI7XG5jb25zdCBUWVBFX0JPT0xFQU4gPSAzO1xuY29uc3QgVFlQRV9PQkpFQ1QgPSA0O1xuY29uc3QgVFlQRV9JTlQ4X0FSUkFZID0gNTtcbmNvbnN0IFRZUEVfVUlOVDhfQVJSQVkgPSA2O1xuY29uc3QgVFlQRV9VSU5UOF9DTEFNUEVEX0FSUkFZID0gNztcbmNvbnN0IFRZUEVfSU5UMTZfQVJSQVkgPSA4O1xuY29uc3QgVFlQRV9VSU5UMTZfQVJSQVkgPSA5O1xuY29uc3QgVFlQRV9JTlQzMl9BUlJBWSA9IDEwO1xuY29uc3QgVFlQRV9VSU5UMzJfQVJSQVkgPSAxMTtcbmNvbnN0IFRZUEVfRkxPQVQzMl9BUlJBWSA9IDEyO1xuY29uc3QgVFlQRV9GTE9BVDY0X0FSUkFZID0gMTM7XG4vLyBBIGNlbGwgd2hvc2Ugcm93IG5ldmVyIHNldCB0aGlzIGNvbHVtbiBhdCBhbGwg4oCUIGFzIG9wcG9zZWQgdG8gVFlQRV9VTkRFRklORUQsIGFuIGV4cGxpY2l0bHkgc3RvcmVkXG4vLyB1bmRlZmluZWQuIE9uIHJlYWQsIEFCU0VOVCBmYWxscyB0aHJvdWdoIHRvIG9sZGVyIHJlYWRlcnMgZm9yIHRoYXQgY29sdW1uOyBhIHN0b3JlZCB1bmRlZmluZWQgc3RvcHNcbi8vIHRoZSBmYWxsLXRocm91Z2ggKGl0J3MgYSByZWFsIHZhbHVlIHRoYXQgY2xlYXJzIHRoZSBjb2x1bW4pLlxuY29uc3QgVFlQRV9BQlNFTlQgPSAxNDtcblxuY29uc3QgVFlQRURfQVJSQVlfVFlQRVM6IHsgdHlwZTogbnVtYmVyOyBjdG9yOiB7IG5ldyhidWZmZXI6IEFycmF5QnVmZmVyKTogQXJyYXlCdWZmZXJWaWV3OyBCWVRFU19QRVJfRUxFTUVOVDogbnVtYmVyOyBuYW1lOiBzdHJpbmcgfSB9W10gPSBbXG4gICAgeyB0eXBlOiBUWVBFX0lOVDhfQVJSQVksIGN0b3I6IEludDhBcnJheSB9LFxuICAgIHsgdHlwZTogVFlQRV9VSU5UOF9BUlJBWSwgY3RvcjogVWludDhBcnJheSB9LFxuICAgIHsgdHlwZTogVFlQRV9VSU5UOF9DTEFNUEVEX0FSUkFZLCBjdG9yOiBVaW50OENsYW1wZWRBcnJheSB9LFxuICAgIHsgdHlwZTogVFlQRV9JTlQxNl9BUlJBWSwgY3RvcjogSW50MTZBcnJheSB9LFxuICAgIHsgdHlwZTogVFlQRV9VSU5UMTZfQVJSQVksIGN0b3I6IFVpbnQxNkFycmF5IH0sXG4gICAgeyB0eXBlOiBUWVBFX0lOVDMyX0FSUkFZLCBjdG9yOiBJbnQzMkFycmF5IH0sXG4gICAgeyB0eXBlOiBUWVBFX1VJTlQzMl9BUlJBWSwgY3RvcjogVWludDMyQXJyYXkgfSxcbiAgICB7IHR5cGU6IFRZUEVfRkxPQVQzMl9BUlJBWSwgY3RvcjogRmxvYXQzMkFycmF5IH0sXG4gICAgeyB0eXBlOiBUWVBFX0ZMT0FUNjRfQVJSQVksIGN0b3I6IEZsb2F0NjRBcnJheSB9LFxuXTtcblxuZXhwb3J0IGNvbnN0IEVNUFRZX0JVRkZFUiA9IEJ1ZmZlci5hbGxvYygwKSBhcyBCdWZmZXI7XG5cbi8vIFNlbnRpbmVsIGEgcmVhZGVyIHJldHVybnMgZm9yIGEgY2VsbCB3aG9zZSByb3cgbmV2ZXIgc2V0IHRoaXMgY29sdW1uLCBzbyB0aGUgam9pbiBjYW4gZmFsbCB0aHJvdWdoXG4vLyB0byBhbiBvbGRlciByZWFkZXIgZm9yIHRoYXQgY29sdW1uLiBEaXN0aW5jdCBmcm9tIGEgc3RvcmVkIHVuZGVmaW5lZCwgd2hpY2ggaXMgYSByZWFsIGNsZWFyaW5nIHZhbHVlLlxuZXhwb3J0IGNvbnN0IEFCU0VOVCA9IFN5bWJvbChcImFic2VudFwiKTtcblxuLy8gT25lIHZhbHVlIGV4YWN0bHkgYXMgaXQgc2l0cyBvbiBkaXNrOiBpdHMgdHlwZSB0YWcgKyByYXcgYnl0ZXMuIEEgY2VsbCdzIGVuY29kaW5nIGlzIHBvc2l0aW9uLVxuLy8gaW5kZXBlbmRlbnQgKG5vdGhpbmcgYWJvdXQgaXQgZGVwZW5kcyBvbiB3aGljaCByb3cvZmlsZSBpdCBsaXZlcyBpbiksIHNvIGEgbWVyZ2UgY29waWVzIHRoZSB3aW5uaW5nXG4vLyBSYXdDZWxsIHN0cmFpZ2h0IGZyb20gYW4gaW5wdXQgY29sdW1uIGludG8gdGhlIG91dHB1dCDigJQgbmV2ZXIgZGVjb2RpbmcgaXQgdG8gYSBKUyB2YWx1ZSBhbmRcbi8vIHJlLWVuY29kaW5nLiBUaGF0J3MgZmFyIGxlc3MgbWVtb3J5IChubyBvYmplY3QgbWF0ZXJpYWxpemF0aW9uKSBhbmQgbXVjaCBmYXN0ZXIgKGEgYnl0ZSBjb3B5LCBub3QgYVxuLy8gSlBFRy90eXBlZC1hcnJheSBkZWNvZGUgKyByZS1lbmNvZGUpLlxuZXhwb3J0IHR5cGUgUmF3Q2VsbCA9IHsgdHlwZTogbnVtYmVyOyBieXRlczogQnVmZmVyIH07XG5cbi8vIFRoZSB0eXBlIHRhZyBhIGNlbGwgY2FycmllcyB3aGVuIGl0cyByb3cgbmV2ZXIgc2V0IHRoaXMgY29sdW1uIOKAlCByZWFkIGl0IGZyb20gdGhlIGNvbHVtbidzIGB0eXBlc2Bcbi8vIGFycmF5IHRvIGRldGVjdCBBQlNFTlQgd2l0aG91dCBkZWNvZGluZy4gUmUtZXhwb3J0ZWQgc28gdGhlIG1lcmdlIHBsYW5uZXIgKHdoaWNoIHdvcmtzIGF0IHRoZVxuLy8gY29sdW1uLWluZGV4IGxldmVsLCBubyB2YWx1ZSBtYXRlcmlhbGl6YXRpb24pIGNhbiBjaGVjayBpdC5cbmV4cG9ydCBjb25zdCBUWVBFX0FCU0VOVF9UQUcgPSBUWVBFX0FCU0VOVDtcblxuLy8gQSBjb2x1bW4ncyBpbmRleCBhbG9uZSAob2Zmc2V0cyArIHR5cGVzIOKAlCBzbWFsbCwgfjUgYnl0ZXMvcm93KSBwbHVzIGEgcHJpbWl0aXZlIHRvIHJlYWQgYSBDT05USUdVT1VTXG4vLyByb3cgcmFuZ2UncyByYXcgdmFsdWUgYnl0ZXMuIFVzZWQgYnkgdGhlIHBsYW5uZWQgbWVyZ2U6IGl0IGxvYWRzIHRoZSBpbmRleCBhY3Jvc3MgZXZlcnkgKHNvdXJjZSxcbi8vIGNvbHVtbikgb25jZSAoY2hlYXApLCB1c2VzIHR5cGVzIHRvIGRldGVjdCBBQlNFTlQgYW5kIG9mZnNldHMgdG8gc2l6ZSBlYWNoIGNlbGwsIHBsYW5zIHRoZSBieXRlXG4vLyBsYXlvdXQgb2YgZXZlcnkgb3V0cHV0IGZpbGUgZnJvbSB0aG9zZSDigJQgdGhlbiBpbiB0aGUgZXhlY3V0ZSBwaGFzZSByZWFkcyBvbmx5IHRoZSBydW5zIG9mIGJ5dGVzIGl0XG4vLyBhY3R1YWxseSBuZWVkcywgY29weWluZyB0aGVtIHN0cmFpZ2h0IGludG8gcHJlLWxhaWQtb3V0IG91dHB1dCBidWZmZXJzLiBObyBjZWxsIHZhbHVlIGlzIGV2ZXJcbi8vIG1hdGVyaWFsaXplZCBhcyBhIEpTIG9iamVjdC5cbmV4cG9ydCB0eXBlIENvbHVtbkluZGV4ID0ge1xuICAgIC8vIG9mZnNldHNbaV0uLm9mZnNldHNbaSsxXSBpcyByb3cgaSdzIHZhbHVlIGJ5dGUgcmFuZ2Ugd2l0aGluIHRoZSBjb2x1bW4ncyBkYXRhIHNlY3Rpb24uXG4gICAgb2Zmc2V0czogVWludDMyQXJyYXk7XG4gICAgLy8gUGVyLXJvdyB0eXBlIHRhZzsgVFlQRV9BQlNFTlRfVEFHIG1hcmtzIFwidGhpcyByb3cgbmV2ZXIgc2V0IHRoaXMgY29sdW1uXCIgKGZhbGwtdGhyb3VnaCkuXG4gICAgdHlwZXM6IFVpbnQ4QXJyYXk7XG4gICAgLy8gUmVhZCB0aGUgY29udGlndW91cyBieXRlcyBvZiB2YWx1ZShzKSBmb3Igcm93cyBbc3RhcnRSb3csIGVuZFJvdykuIExlbmd0aCBpcyBleGFjdGx5XG4gICAgLy8gb2Zmc2V0c1tlbmRSb3ddIC0gb2Zmc2V0c1tzdGFydFJvd10g4oCUIHRoZSBjZWxscyBpbiB0aGF0IHJhbmdlIGNvbmNhdGVuYXRlZC4gVGhlIGNhbGxlciBjb21wb3Nlc1xuICAgIC8vIGxhcmdlciByZWFkcyBmcm9tIGNvbnNlY3V0aXZlIHJvd3MgKG9uZSBzb3VyY2Utc2lkZSBnZXRSYW5nZSBwZXIgcnVuKS5cbiAgICByZWFkVmFsdWVCeXRlczogKHN0YXJ0Um93OiBudW1iZXIsIGVuZFJvdzogbnVtYmVyKSA9PiBQcm9taXNlPEJ1ZmZlcj47XG59O1xuXG4vLyBIaWRkZW4gcGVyLXJvdyBjb2x1bW4gaG9sZGluZyBlYWNoIHJvdydzIHdyaXRlLXRpbWUgKHNvIHJlYWRzIGNhbiByZXNvbHZlIGEga2V5IHRvIGl0cyBsYXRlc3QgdmFsdWVcbi8vIGJ5IGFjdHVhbCB0aW1lKS4gTlVMLXByZWZpeGVkIHNvIGl0IGNhbid0IGNvbGxpZGUgd2l0aCBhIHVzZXIgY29sdW1uOyBleGNsdWRlZCBmcm9tIGBjb2x1bW5zYC5cbmNvbnN0IFRJTUVfQ09MVU1OID0gU3RyaW5nLmZyb21DaGFyQ29kZSgwKSArIFwidFwiO1xuXG50eXBlIEZpbGVIZWFkZXIgPSB7XG4gICAgcm93Q291bnQ6IG51bWJlcjtcbiAgICBjb2x1bW5zOiB7IG5hbWU6IHN0cmluZzsgb2Zmc2V0OiBudW1iZXI7IGxlbmd0aDogbnVtYmVyIH1bXTtcbiAgICAvLyBPbGRlc3QvbmV3ZXN0IHdyaXRlLXRpbWUgb2YgdGhlIGRhdGEgaW4gdGhpcyBmaWxlIChmcm9tIHRoZSBzdHJlYW0gZW50cmllcyBpdCB3YXMgZm9sZGVkIGZyb20sXG4gICAgLy8gY2FycmllZCB0aHJvdWdoIG1lcmdlcykuIExldHMgdGhlIG1lcmdlIHBsYW5uZXIgcGljayBmaWxlcyBvdmVybGFwcGluZyBhIHRpbWUgcmFuZ2UuIEFic2VudCAoMClcbiAgICAvLyBpbiBmaWxlcyB3cml0dGVuIGJlZm9yZSB0aGlzIGV4aXN0ZWQuXG4gICAgbWluVGltZT86IG51bWJlcjtcbiAgICBtYXhUaW1lPzogbnVtYmVyO1xuICAgIC8vIExleGljb2dyYXBoaWNhbGx5IHNtYWxsZXN0L2xhcmdlc3Qga2V5IGluIHRoaXMgZmlsZSAocm93cyBhcmUgc3RvcmVkIGtleS1zb3J0ZWQpLiBMZXRzIHRoZSBtZXJnZVxuICAgIC8vIHBsYW5uZXIgZ3JvdXAvZGVkdXAgYnkga2V5IHJhbmdlIGFuZCBsZXRzIGEgc2luZ2xlLWtleSByZWFkIHNraXAgZmlsZXMgd2hvc2UgcmFuZ2UgZXhjbHVkZXMgdGhlXG4gICAgLy8ga2V5LiBBYnNlbnQgKHVuZGVmaW5lZCkgaW4gZmlsZXMgd3JpdHRlbiBiZWZvcmUgdGhpcyBleGlzdGVkIOKAlCB0cmVhdGVkIGFzIFwic3BhbnMgYWxsIGtleXNcIi5cbiAgICBtaW5LZXk/OiBzdHJpbmc7XG4gICAgbWF4S2V5Pzogc3RyaW5nO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZVZhbHVlKHZhbHVlOiB1bmtub3duKTogeyB0eXBlOiBudW1iZXI7IGJ5dGVzOiBCdWZmZXIgfSB7XG4gICAgaWYgKHZhbHVlID09PSBBQlNFTlQpIHtcbiAgICAgICAgcmV0dXJuIHsgdHlwZTogVFlQRV9BQlNFTlQsIGJ5dGVzOiBFTVBUWV9CVUZGRVIgfTtcbiAgICB9XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHsgdHlwZTogVFlQRV9VTkRFRklORUQsIGJ5dGVzOiBFTVBUWV9CVUZGRVIgfTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICByZXR1cm4geyB0eXBlOiBUWVBFX1NUUklORywgYnl0ZXM6IEJ1ZmZlci5mcm9tKHZhbHVlLCBcInV0ZjhcIikgfTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICBjb25zdCBieXRlcyA9IEJ1ZmZlci5hbGxvYyg4KTtcbiAgICAgICAgYnl0ZXMud3JpdGVEb3VibGVMRSh2YWx1ZSwgMCk7XG4gICAgICAgIHJldHVybiB7IHR5cGU6IFRZUEVfTlVNQkVSLCBieXRlcyB9O1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcImJvb2xlYW5cIikge1xuICAgICAgICByZXR1cm4geyB0eXBlOiBUWVBFX0JPT0xFQU4sIGJ5dGVzOiBCdWZmZXIuZnJvbShbdmFsdWUgJiYgMSB8fCAwXSkgfTtcbiAgICB9XG4gICAgaWYgKEFycmF5QnVmZmVyLmlzVmlldyh2YWx1ZSkpIHtcbiAgICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgRGF0YVZpZXcpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRGF0YVZpZXcgdmFsdWVzIGFyZSBub3Qgc3VwcG9ydGVkLCBzdG9yZSBhIHR5cGVkIGFycmF5IGluc3RlYWRgKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBlbnRyeSA9IFRZUEVEX0FSUkFZX1RZUEVTLmZpbmQodCA9PiB2YWx1ZSBpbnN0YW5jZW9mIHQuY3Rvcik7XG4gICAgICAgIGlmICghZW50cnkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgdHlwZWQgYXJyYXkgdHlwZSAke3ZhbHVlLmNvbnN0cnVjdG9yLm5hbWV9YCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHR5cGU6IGVudHJ5LnR5cGUsXG4gICAgICAgICAgICBieXRlczogQnVmZmVyLmZyb20odmFsdWUuYnVmZmVyLCB2YWx1ZS5ieXRlT2Zmc2V0LCB2YWx1ZS5ieXRlTGVuZ3RoKSxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJvYmplY3RcIikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIHZhbHVlIHR5cGUgJHt0eXBlb2YgdmFsdWV9YCk7XG4gICAgfVxuICAgIHJldHVybiB7IHR5cGU6IFRZUEVfT0JKRUNULCBieXRlczogQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkodmFsdWUpLCBcInV0ZjhcIikgfTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlVmFsdWUodHlwZTogbnVtYmVyLCBieXRlczogQnVmZmVyKTogdW5rbm93biB7XG4gICAgaWYgKHR5cGUgPT09IFRZUEVfVU5ERUZJTkVEKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmICh0eXBlID09PSBUWVBFX1NUUklORykgcmV0dXJuIGJ5dGVzLnRvU3RyaW5nKFwidXRmOFwiKTtcbiAgICBpZiAodHlwZSA9PT0gVFlQRV9OVU1CRVIpIHtcbiAgICAgICAgaWYgKGJ5dGVzLmxlbmd0aCAhPT0gOCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCA4IGJ5dGVzIGZvciBhIG51bWJlciwgd2FzICR7Ynl0ZXMubGVuZ3RofWApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBieXRlcy5yZWFkRG91YmxlTEUoMCk7XG4gICAgfVxuICAgIGlmICh0eXBlID09PSBUWVBFX0JPT0xFQU4pIHtcbiAgICAgICAgaWYgKGJ5dGVzLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCAxIGJ5dGUgZm9yIGEgYm9vbGVhbiwgd2FzICR7Ynl0ZXMubGVuZ3RofWApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBieXRlc1swXSA9PT0gMTtcbiAgICB9XG4gICAgaWYgKHR5cGUgPT09IFRZUEVfT0JKRUNUKSByZXR1cm4gSlNPTi5wYXJzZShieXRlcy50b1N0cmluZyhcInV0ZjhcIikpO1xuICAgIGlmICh0eXBlID09PSBUWVBFX0FCU0VOVCkgcmV0dXJuIEFCU0VOVDtcbiAgICBjb25zdCBlbnRyeSA9IFRZUEVEX0FSUkFZX1RZUEVTLmZpbmQodCA9PiB0LnR5cGUgPT09IHR5cGUpO1xuICAgIGlmICghZW50cnkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBhIHZhbGlkIHR5cGUgdGFnLCB3YXMgJHt0eXBlfWApO1xuICAgIH1cbiAgICBjb25zdCBjdG9yID0gZW50cnkuY3RvcjtcbiAgICBpZiAodHlwZSA9PT0gVFlQRV9VSU5UOF9BUlJBWSkgcmV0dXJuIEJ1ZmZlci5mcm9tKGJ5dGVzKTtcbiAgICBpZiAoYnl0ZXMubGVuZ3RoICUgY3Rvci5CWVRFU19QRVJfRUxFTUVOVCAhPT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGJ5dGUgbGVuZ3RoIGRpdmlzaWJsZSBieSAke2N0b3IuQllURVNfUEVSX0VMRU1FTlR9IGZvciAke2N0b3IubmFtZX0sIHdhcyAke2J5dGVzLmxlbmd0aH1gKTtcbiAgICB9XG4gICAgLy8gQ29weSB0byBhIGZyZXNoIEFycmF5QnVmZmVyIHNvIHRoZSB0eXBlZCBhcnJheSB2aWV3IGlzIGFsaWduZWQgcmVnYXJkbGVzcyBvZiB3aGVyZSB0aGUgYnl0ZXMgbGFuZGVkIGluIHRoZSBzb3VyY2UgYnVmZmVyLlxuICAgIGNvbnN0IGFsaWduZWQgPSBuZXcgQXJyYXlCdWZmZXIoYnl0ZXMubGVuZ3RoKTtcbiAgICBuZXcgVWludDhBcnJheShhbGlnbmVkKS5zZXQoYnl0ZXMpO1xuICAgIHJldHVybiBuZXcgY3RvcihhbGlnbmVkKTtcbn1cblxuZnVuY3Rpb24gZW5jb2RlQnVsa0RhdGEoZGF0YTogdW5rbm93bltdKTogQnVmZmVyIHtcbiAgICBjb25zdCBuID0gZGF0YS5sZW5ndGg7XG4gICAgY29uc3Qgb2Zmc2V0cyA9IEJ1ZmZlci5hbGxvYyg0ICogKG4gKyAxKSk7XG4gICAgY29uc3QgdHlwZXMgPSBCdWZmZXIuYWxsb2Mobik7XG4gICAgY29uc3QgcGFydHM6IEJ1ZmZlcltdID0gW107XG4gICAgbGV0IHBvcyA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgY29uc3QgeyB0eXBlLCBieXRlcyB9ID0gZW5jb2RlVmFsdWUoZGF0YVtpXSk7XG4gICAgICAgIG9mZnNldHMud3JpdGVVSW50MzJMRShwb3MsIDQgKiBpKTtcbiAgICAgICAgdHlwZXNbaV0gPSB0eXBlO1xuICAgICAgICBwYXJ0cy5wdXNoKGJ5dGVzKTtcbiAgICAgICAgcG9zICs9IGJ5dGVzLmxlbmd0aDtcbiAgICB9XG4gICAgb2Zmc2V0cy53cml0ZVVJbnQzMkxFKHBvcywgNCAqIG4pO1xuICAgIHJldHVybiBCdWZmZXIuY29uY2F0KFtvZmZzZXRzLCB0eXBlcywgLi4ucGFydHNdKTtcbn1cblxuLy8gTGlrZSBlbmNvZGVCdWxrRGF0YSBidXQgdGhlIHZhbHVlcyBhcmUgYWxyZWFkeSBlbmNvZGVkIChhIG1lcmdlIHN1cHBsaWVzIHRoZSB3aW5uaW5nIGNlbGxzJyByYXcgYnl0ZXNcbi8vIHN0cmFpZ2h0IGZyb20gdGhlIGlucHV0IGZpbGVzKS4gTGF5cyBvdXQgdGhlIHNhbWUgb2Zmc2V0cyAvIHR5cGVzIC8gZGF0YSBzZWN0aW9uIHdpdGhvdXQgdG91Y2hpbmcgdGhlXG4vLyB2YWx1ZXMgdGhlbXNlbHZlcy5cbmZ1bmN0aW9uIGVuY29kZUJ1bGtEYXRhUmF3KGNlbGxzOiBSYXdDZWxsW10pOiBCdWZmZXIge1xuICAgIGNvbnN0IG4gPSBjZWxscy5sZW5ndGg7XG4gICAgY29uc3Qgb2Zmc2V0cyA9IEJ1ZmZlci5hbGxvYyg0ICogKG4gKyAxKSk7XG4gICAgY29uc3QgdHlwZXMgPSBCdWZmZXIuYWxsb2Mobik7XG4gICAgY29uc3QgcGFydHM6IEJ1ZmZlcltdID0gW107XG4gICAgbGV0IHBvcyA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICAgICAgY29uc3QgeyB0eXBlLCBieXRlcyB9ID0gY2VsbHNbaV07XG4gICAgICAgIG9mZnNldHMud3JpdGVVSW50MzJMRShwb3MsIDQgKiBpKTtcbiAgICAgICAgdHlwZXNbaV0gPSB0eXBlO1xuICAgICAgICBwYXJ0cy5wdXNoKGJ5dGVzKTtcbiAgICAgICAgcG9zICs9IGJ5dGVzLmxlbmd0aDtcbiAgICB9XG4gICAgb2Zmc2V0cy53cml0ZVVJbnQzMkxFKHBvcywgNCAqIG4pO1xuICAgIHJldHVybiBCdWZmZXIuY29uY2F0KFtvZmZzZXRzLCB0eXBlcywgLi4ucGFydHNdKTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlQnVsa0RhdGEoYmxvYjogQnVmZmVyLCByb3dDb3VudDogbnVtYmVyKTogdW5rbm93bltdIHtcbiAgICBjb25zdCBpbmRleFNpemUgPSA0ICogKHJvd0NvdW50ICsgMSkgKyByb3dDb3VudDtcbiAgICBjb25zdCB2YWx1ZXM6IHVua25vd25bXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcm93Q291bnQ7IGkrKykge1xuICAgICAgICBjb25zdCBzdGFydCA9IGJsb2IucmVhZFVJbnQzMkxFKDQgKiBpKTtcbiAgICAgICAgY29uc3QgZW5kID0gYmxvYi5yZWFkVUludDMyTEUoNCAqIChpICsgMSkpO1xuICAgICAgICBjb25zdCB0eXBlID0gYmxvYls0ICogKHJvd0NvdW50ICsgMSkgKyBpXTtcbiAgICAgICAgdmFsdWVzLnB1c2goZGVjb2RlVmFsdWUodHlwZSwgYmxvYi5zdWJhcnJheShpbmRleFNpemUgKyBzdGFydCwgaW5kZXhTaXplICsgZW5kKSkpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWVzO1xufVxuXG4vLyBUYXJnZXQgbG9naWNhbCAodW5jb21wcmVzc2VkKSBzaXplIG9mIG9uZSBidWxrIGZpbGUuIEEgcm93cyBhcnJheSBiaWdnZXIgdGhhbiB0aGlzIGlzIHNwbGl0IGFjcm9zc1xuLy8gbXVsdGlwbGUga2V5LWNvbnRpZ3VvdXMgZmlsZXMsIHNvIGZpbGVzIHN0YXkgYXJvdW5kIHRoaXMgc2l6ZSAodGhlIG1lcmdlIHBvbGljeSdzIHRhcmdldCkgYW5kIG5vXG4vLyBzaW5nbGUgY29sdW1uIGJsb2IgLyBCdWZmZXIuY29uY2F0IGV2ZXIgYXBwcm9hY2hlcyB0aGUgfjJHQiBCdWZmZXIgbGVuZ3RoIGxpbWl0LiBUaGUgZXN0aW1hdGUgaXNcbi8vIHJvdWdoIG9uIHB1cnBvc2Ug4oCUIGl0IG9ubHkgbmVlZHMgdG8ga2VlcCBlYWNoIGNodW5rIG5lYXIgdGhlIHRhcmdldCwgbm90IGJlIGV4YWN0LiBBIHNpbmdsZSByb3dcbi8vIGJpZ2dlciB0aGFuIHRoZSB0YXJnZXQgc3RpbGwgYmVjb21lcyBpdHMgb3duIChvdmVyc2l6ZWQpIGZpbGUsIHNpbmNlIHdlIG5ldmVyIHNwbGl0IHdpdGhpbiBhIGtleS5cbmV4cG9ydCBjb25zdCBUQVJHRVRfRklMRV9CWVRFUyA9IDI1NiAqIDEwMjQgKiAxMDI0O1xuXG4vLyBQZXItdmFsdWUgb24tZGlzayBvdmVyaGVhZDogYSA0LWJ5dGUgb2Zmc2V0IGVudHJ5IHBsdXMgYSAxLWJ5dGUgdHlwZSB0YWcuXG5jb25zdCBQRVJfVkFMVUVfT1ZFUkhFQUQgPSA1O1xuXG5mdW5jdGlvbiBlc3RpbWF0ZVZhbHVlQnl0ZXModmFsdWU6IHVua25vd24pOiBudW1iZXIge1xuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSBudWxsKSByZXR1cm4gMDtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiKSByZXR1cm4gdmFsdWUubGVuZ3RoICogMjtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiKSByZXR1cm4gODtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcImJvb2xlYW5cIikgcmV0dXJuIDE7XG4gICAgaWYgKEFycmF5QnVmZmVyLmlzVmlldyh2YWx1ZSkpIHJldHVybiB2YWx1ZS5ieXRlTGVuZ3RoO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIpIHJldHVybiBKU09OLnN0cmluZ2lmeSh2YWx1ZSkubGVuZ3RoO1xuICAgIHJldHVybiAwO1xufVxuXG5mdW5jdGlvbiBlc3RpbWF0ZVJvd0J5dGVzKHJvdzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBudW1iZXIge1xuICAgIGxldCB0b3RhbCA9IDA7XG4gICAgZm9yIChjb25zdCB2YWx1ZSBvZiBPYmplY3QudmFsdWVzKHJvdykpIHtcbiAgICAgICAgdG90YWwgKz0gZXN0aW1hdGVWYWx1ZUJ5dGVzKHZhbHVlKSArIFBFUl9WQUxVRV9PVkVSSEVBRDtcbiAgICB9XG4gICAgcmV0dXJuIHRvdGFsO1xufVxuXG4vLyBDb25jYXRlbmF0ZXMgYWxyZWFkeS1lbmNvZGVkIGNvbHVtbiBibG9icyBpbnRvIGEgY29tcGxldGUgZmlsZSAoNC1ieXRlIGhlYWRlciBsZW5ndGggKyBoZWFkZXIgSlNPTiArXG4vLyBibG9icyksIGNvbXB1dGluZyB0aGUgaGVhZGVyJ3MgdGltZSArIGtleSBib3VuZHMgZnJvbSB0aGUgcGVyLXJvdyB0aW1lcyBhbmQga2V5cy4gU2hhcmVkIGJ5IHRoZVxuLy8gb2JqZWN0LWJhc2VkIGJ1aWxkZXIgKGJ1aWxkT25lRmlsZSkgYW5kIHRoZSByYXctc3BsaWNlIGJ1aWxkZXIgKGJ1aWxkT25lRmlsZVJhdykuXG5mdW5jdGlvbiBhc3NlbWJsZUZpbGUoY29sdW1uTmFtZXM6IHN0cmluZ1tdLCBibG9iczogQnVmZmVyW10sIHJvd0NvdW50OiBudW1iZXIsIHRpbWVzOiBudW1iZXJbXSwga2V5czogc3RyaW5nW10pOiBCdWZmZXIge1xuICAgIGxldCBvZmZzZXQgPSAwO1xuICAgIGNvbnN0IGNvbHVtbnMgPSBjb2x1bW5OYW1lcy5tYXAoKG5hbWUsIGkpID0+IHtcbiAgICAgICAgY29uc3QgZW50cnkgPSB7IG5hbWUsIG9mZnNldCwgbGVuZ3RoOiBibG9ic1tpXS5sZW5ndGggfTtcbiAgICAgICAgb2Zmc2V0ICs9IGJsb2JzW2ldLmxlbmd0aDtcbiAgICAgICAgcmV0dXJuIGVudHJ5O1xuICAgIH0pO1xuICAgIGxldCBtaW5UaW1lID0gdGltZXMubGVuZ3RoID8gdGltZXNbMF0gOiAwO1xuICAgIGxldCBtYXhUaW1lID0gbWluVGltZTtcbiAgICBmb3IgKGNvbnN0IHQgb2YgdGltZXMpIHsgaWYgKHQgPCBtaW5UaW1lKSBtaW5UaW1lID0gdDsgaWYgKHQgPiBtYXhUaW1lKSBtYXhUaW1lID0gdDsgfVxuICAgIGxldCBtaW5LZXk6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBsZXQgbWF4S2V5OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgZm9yIChjb25zdCBrZXkgb2Yga2V5cykge1xuICAgICAgICBpZiAobWluS2V5ID09PSB1bmRlZmluZWQgfHwga2V5IDwgbWluS2V5KSBtaW5LZXkgPSBrZXk7XG4gICAgICAgIGlmIChtYXhLZXkgPT09IHVuZGVmaW5lZCB8fCBrZXkgPiBtYXhLZXkpIG1heEtleSA9IGtleTtcbiAgICB9XG4gICAgY29uc3QgaGVhZGVyOiBGaWxlSGVhZGVyID0geyByb3dDb3VudCwgY29sdW1ucywgbWluVGltZSwgbWF4VGltZSwgbWluS2V5LCBtYXhLZXkgfTtcbiAgICBjb25zdCBoZWFkZXJCdWYgPSBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeShoZWFkZXIpLCBcInV0ZjhcIik7XG4gICAgY29uc3QgbGVuZ3RoUHJlZml4ID0gQnVmZmVyLmFsbG9jKDQpO1xuICAgIGxlbmd0aFByZWZpeC53cml0ZVVJbnQzMkxFKGhlYWRlckJ1Zi5sZW5ndGgsIDApO1xuICAgIHJldHVybiBCdWZmZXIuY29uY2F0KFtsZW5ndGhQcmVmaXgsIGhlYWRlckJ1ZiwgLi4uYmxvYnNdKTtcbn1cblxuZnVuY3Rpb24gYnVpbGRPbmVGaWxlKHJvd3M6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W10sIHRpbWVzOiBudW1iZXJbXSk6IEJ1ZmZlciB7XG4gICAgY29uc3QgY29sdW1uTmFtZXM6IHN0cmluZ1tdID0gW107XG4gICAgY29uc3QgY29sdW1uU2V0ID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgZm9yIChjb25zdCByb3cgb2Ygcm93cykge1xuICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIE9iamVjdC5rZXlzKHJvdykpIHtcbiAgICAgICAgICAgIGlmIChjb2x1bW5TZXQuaGFzKGZpZWxkKSkgY29udGludWU7XG4gICAgICAgICAgICBjb2x1bW5TZXQuYWRkKGZpZWxkKTtcbiAgICAgICAgICAgIGNvbHVtbk5hbWVzLnB1c2goZmllbGQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIEEgcm93IHRoYXQgZG9lc24ndCBpbmNsdWRlIGEgY29sdW1uIHN0b3JlcyBBQlNFTlQgKGZhbGwtdGhyb3VnaCksIG5vdCB1bmRlZmluZWQgKGEgcmVhbCB2YWx1ZSkuXG4gICAgY29uc3QgYmxvYnMgPSBjb2x1bW5OYW1lcy5tYXAoY29sID0+IGVuY29kZUJ1bGtEYXRhKHJvd3MubWFwKHJvdyA9PiBjb2wgaW4gcm93ID8gcm93W2NvbF0gOiBBQlNFTlQpKSk7XG4gICAgLy8gVGhlIGhpZGRlbiBwZXItcm93IHRpbWUgY29sdW1uLlxuICAgIGNvbHVtbk5hbWVzLnB1c2goVElNRV9DT0xVTU4pO1xuICAgIGJsb2JzLnB1c2goZW5jb2RlQnVsa0RhdGEodGltZXMpKTtcbiAgICByZXR1cm4gYXNzZW1ibGVGaWxlKGNvbHVtbk5hbWVzLCBibG9icywgcm93cy5sZW5ndGgsIHRpbWVzLCByb3dzLm1hcChyID0+IHJbS0VZX0NPTFVNTl0gYXMgc3RyaW5nKSk7XG59XG5cbi8vIEEgcmVzb2x2ZWQgb3V0cHV0IHJvdyBmb3IgdGhlIHJhdy1zcGxpY2UgbWVyZ2U6IGl0cyBrZXksIHdyaXRlLXRpbWUsIGFuZCB0aGUgd2lubmluZyByYXcgY2VsbCBmb3IgZWFjaFxuLy8gY29sdW1uIGl0IGhhcyAoYSBjb2x1bW4gaXQgbGFja3MgaXMgd3JpdHRlbiBBQlNFTlQg4oCUIGZhbGwtdGhyb3VnaCkuIFRoZSBjZWxsIGJ5dGVzIGFyZSBjb3BpZWQgc3RyYWlnaHRcbi8vIGZyb20gdGhlIGlucHV0IGZpbGVzOyBubyB2YWx1ZSBpcyBldmVyIGRlY29kZWQuXG5leHBvcnQgdHlwZSBSYXdSb3cgPSB7IGtleTogc3RyaW5nOyB0aW1lOiBudW1iZXI7IGNlbGxzOiBNYXA8c3RyaW5nLCBSYXdDZWxsPiB9O1xuXG4vLyBTaXplIG9mIGEgY29sdW1uIGJsb2IncyBJTkRFWCBzZWN0aW9uIChvZmZzZXRzIGFycmF5ICsgdHlwZXMgYXJyYXkpIGZvciBhIGNvbHVtbiBvZiBOIHJvd3MuIFRoZSBkYXRhXG4vLyBzZWN0aW9uIGZvbGxvd3MgaW1tZWRpYXRlbHkgYWZ0ZXIuIFRoZSBwbGFubmVkIG1lcmdlIHVzZXMgdGhpcyB0byBzaXplIG91dHB1dCBidWZmZXJzIGV4YWN0bHkuXG5leHBvcnQgZnVuY3Rpb24gY29sdW1uSW5kZXhCeXRlTGVuZ3RoKHJvd0NvdW50OiBudW1iZXIpOiBudW1iZXIge1xuICAgIHJldHVybiA0ICogKHJvd0NvdW50ICsgMSkgKyByb3dDb3VudDtcbn1cblxuLy8gQXNzZW1ibGVzIGEgY29tcGxldGUgYnVsayBmaWxlIGZyb20gYSBzZXQgb2YgcHJlLWJ1aWx0IHZhbHVlIGNvbHVtbiBibG9icyBwbHVzIHRoZSBrZXlzICsgdGltZXMuIEF1dG8tXG4vLyBhZGRzIHRoZSBLRVlfQ09MVU1OIChrZXlzKSBhbmQgaGlkZGVuIFRJTUVfQ09MVU1OICh0aW1lcykg4oCUIHRoZXkncmUgc21hbGwgZW5vdWdoIHRvIGVuY29kZSBpbiBvbmUgc2hvdFxuLy8gaGVyZS4gVXNlZCBieSB0aGUgcGxhbm5lZCBtZXJnZTogaXQgYnVpbGRzIGVhY2ggdmFsdWUgY29sdW1uJ3MgYmxvYiBieS1oYW5kIChvZmZzZXRzL3R5cGVzICsgcmF3IGJ5dGVzXG4vLyBjb3BpZWQgZGlyZWN0bHkgZnJvbSBpbnB1dHMsIG5vIHZhbHVlIG1hdGVyaWFsaXphdGlvbikgYW5kIGhhbmRzIHRoZSByZXN1bHQgaGVyZSBmb3IgaGVhZGVyICsgYm91bmRzLlxuZXhwb3J0IGZ1bmN0aW9uIGFzc2VtYmxlUGxhbm5lZEZpbGUoY29uZmlnOiB7XG4gICAgdmFsdWVDb2x1bW5zOiB7IG5hbWU6IHN0cmluZzsgYmxvYjogQnVmZmVyIH1bXTtcbiAgICBrZXlzOiBzdHJpbmdbXTtcbiAgICB0aW1lczogbnVtYmVyW107XG59KTogQnVmZmVyIHtcbiAgICBjb25zdCBjb2x1bW5OYW1lcyA9IFtLRVlfQ09MVU1OLCAuLi5jb25maWcudmFsdWVDb2x1bW5zLm1hcChjID0+IGMubmFtZSksIFRJTUVfQ09MVU1OXTtcbiAgICBjb25zdCBibG9icyA9IFtcbiAgICAgICAgZW5jb2RlQnVsa0RhdGEoY29uZmlnLmtleXMpLFxuICAgICAgICAuLi5jb25maWcudmFsdWVDb2x1bW5zLm1hcChjID0+IGMuYmxvYiksXG4gICAgICAgIGVuY29kZUJ1bGtEYXRhKGNvbmZpZy50aW1lcyksXG4gICAgXTtcbiAgICByZXR1cm4gYXNzZW1ibGVGaWxlKGNvbHVtbk5hbWVzLCBibG9icywgY29uZmlnLmtleXMubGVuZ3RoLCBjb25maWcudGltZXMsIGNvbmZpZy5rZXlzKTtcbn1cblxuY29uc3QgQUJTRU5UX0NFTEw6IFJhd0NlbGwgPSB7IHR5cGU6IFRZUEVfQUJTRU5ULCBieXRlczogRU1QVFlfQlVGRkVSIH07XG5cbmZ1bmN0aW9uIGJ1aWxkT25lRmlsZVJhdyhyb3dzOiBSYXdSb3dbXSk6IEJ1ZmZlciB7XG4gICAgLy8gQ29sdW1ucyBwcmVzZW50IGluIHRoaXMgY2h1bmssIGluIGZpcnN0LXNlZW4gb3JkZXIgKG1hdGNoZXMgYnVpbGRPbmVGaWxlLCB3aGljaCBvbmx5IGVtaXRzIGNvbHVtbnNcbiAgICAvLyBzb21lIHJvdyBhY3R1YWxseSBoYXMpLlxuICAgIGNvbnN0IHZhbHVlQ29sdW1uczogc3RyaW5nW10gPSBbXTtcbiAgICBjb25zdCBzZWVuID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgZm9yIChjb25zdCByb3cgb2Ygcm93cykgZm9yIChjb25zdCBjb2wgb2Ygcm93LmNlbGxzLmtleXMoKSkge1xuICAgICAgICBpZiAoc2Vlbi5oYXMoY29sKSkgY29udGludWU7XG4gICAgICAgIHNlZW4uYWRkKGNvbCk7XG4gICAgICAgIHZhbHVlQ29sdW1ucy5wdXNoKGNvbCk7XG4gICAgfVxuICAgIGNvbnN0IGNvbHVtbk5hbWVzID0gW0tFWV9DT0xVTU4sIC4uLnZhbHVlQ29sdW1ucywgVElNRV9DT0xVTU5dO1xuICAgIGNvbnN0IHRpbWVzID0gcm93cy5tYXAociA9PiByLnRpbWUpO1xuICAgIGNvbnN0IGJsb2JzID0gW1xuICAgICAgICBlbmNvZGVCdWxrRGF0YShyb3dzLm1hcChyID0+IHIua2V5KSksXG4gICAgICAgIC4uLnZhbHVlQ29sdW1ucy5tYXAoY29sID0+IGVuY29kZUJ1bGtEYXRhUmF3KHJvd3MubWFwKHIgPT4gci5jZWxscy5nZXQoY29sKSA/PyBBQlNFTlRfQ0VMTCkpKSxcbiAgICAgICAgZW5jb2RlQnVsa0RhdGEodGltZXMpLFxuICAgIF07XG4gICAgcmV0dXJuIGFzc2VtYmxlRmlsZShjb2x1bW5OYW1lcywgYmxvYnMsIHJvd3MubGVuZ3RoLCB0aW1lcywgcm93cy5tYXAociA9PiByLmtleSkpO1xufVxuXG5mdW5jdGlvbiBlc3RpbWF0ZVJhd1Jvd0J5dGVzKHJvdzogUmF3Um93KTogbnVtYmVyIHtcbiAgICBsZXQgdG90YWwgPSByb3cua2V5Lmxlbmd0aCAqIDIgKyBQRVJfVkFMVUVfT1ZFUkhFQUQ7XG4gICAgZm9yIChjb25zdCBjZWxsIG9mIHJvdy5jZWxscy52YWx1ZXMoKSkgdG90YWwgKz0gY2VsbC5ieXRlcy5sZW5ndGggKyBQRVJfVkFMVUVfT1ZFUkhFQUQ7XG4gICAgcmV0dXJuIHRvdGFsO1xufVxuXG4vLyBPbmUgY29tcGxldGUsIGluZGVwZW5kZW50IGZpbGU6IHRoZSBlbmNvZGVkIGJ1ZmZlciBwbHVzIGl0cyBrZXkgcmFuZ2UgKyByb3cgY291bnQgKHRoZSBjYWxsZXIgbG9ncyB0aGVcbi8vIHJhbmdlIHdoZW4gYSBtZXJnZSBzcGxpdHMgYWNyb3NzIHNldmVyYWwgZmlsZXMpLlxuZXhwb3J0IGludGVyZmFjZSBCdWlsdEZpbGUgeyBidWZmZXI6IEJ1ZmZlcjsgbWluS2V5OiBzdHJpbmc7IG1heEtleTogc3RyaW5nOyByb3dDb3VudDogbnVtYmVyOyB9XG5cbi8vIFJldHVybnMgb25lIGNvbXBsZXRlLCBpbmRlcGVuZGVudCBmaWxlIHBlciBjaHVuayBvZiByb3dzLiBSb3dzIGFyZSBmaXJzdCBzb3J0ZWQgYnkga2V5LCB0aGVuXG4vLyBwYXJ0aXRpb25lZCBpbnRvIGtleS1jb250aWd1b3VzIGNodW5rcyBvZiB+dGFyZ2V0Qnl0ZXMgZWFjaCDigJQgc28gZXZlcnkgcmV0dXJuZWQgZmlsZSBpcyBrZXktc29ydGVkXG4vLyAodGlnaHQgbWluS2V5L21heEtleSBmb3IgdGhlIHJlYWQtc2tpcCArIG1lcmdlIHBsYW5uZXIpIGFuZCBzdGF5cyBuZWFyIHRoZSB0YXJnZXQgc2l6ZSwgYW5kIG5vXG4vLyBzaW5nbGUgY29sdW1uIGJsb2IgLyBCdWZmZXIuY29uY2F0IGFwcHJvYWNoZXMgdGhlIH4yR0IgbGltaXQuIFRoZSBjaHVua3MgaGF2ZSBkaXNqb2ludCBrZXkgcmFuZ2VzLFxuLy8gc28gdGhlIGNhbGxlciBqdXN0IHdyaXRlcyBlYWNoIGFzIGl0cyBvd24gZmlsZS4gQSBub3JtYWwtc2l6ZWQgd3JpdGUgcmV0dXJucyBhIHNpbmdsZSBmaWxlLlxuLy8gYHRpbWVzW2ldYCBpcyByb3cgaSdzIHdyaXRlLXRpbWUsIHN0b3JlZCBwZXIgcm93IHNvIHJlYWRzIHJlc29sdmUgYSBrZXkgdG8gaXRzIGxhdGVzdCB2YWx1ZSBieSB0aW1lLlxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkRmlsZUJ1ZmZlcihyb3dzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPltdLCB0aW1lczogbnVtYmVyW10sIHRhcmdldEJ5dGVzID0gVEFSR0VUX0ZJTEVfQllURVMpOiBCdWlsdEZpbGVbXSB7XG4gICAgLy8gQSBjaHVuayBpcyBhbHJlYWR5IGtleS1zb3J0ZWQsIHNvIGl0cyBmaXJzdC9sYXN0IHJvdyBhcmUgaXRzIG1pbi9tYXgga2V5LlxuICAgIGNvbnN0IG1ha2UgPSAocnM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W10sIHRzOiBudW1iZXJbXSk6IEJ1aWx0RmlsZSA9PiAoe1xuICAgICAgICBidWZmZXI6IGJ1aWxkT25lRmlsZShycywgdHMpLFxuICAgICAgICBtaW5LZXk6IHJzLmxlbmd0aCA/IChyc1swXVtLRVlfQ09MVU1OXSBhcyBzdHJpbmcpIDogXCJcIixcbiAgICAgICAgbWF4S2V5OiBycy5sZW5ndGggPyAocnNbcnMubGVuZ3RoIC0gMV1bS0VZX0NPTFVNTl0gYXMgc3RyaW5nKSA6IFwiXCIsXG4gICAgICAgIHJvd0NvdW50OiBycy5sZW5ndGgsXG4gICAgfSk7XG4gICAgaWYgKHJvd3MubGVuZ3RoID09PSAwKSByZXR1cm4gW21ha2UoW10sIFtdKV07XG4gICAgLy8gU29ydCByb3dzICsgdGhlaXIgdGltZXMgdG9nZXRoZXIgYnkga2V5IHNvIGVhY2ggb3V0cHV0IGZpbGUgaXMga2V5LWNvbnRpZ3VvdXMuXG4gICAgY29uc3Qgb3JkZXIgPSByb3dzLm1hcCgoXywgaSkgPT4gaSkuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICBjb25zdCBrYSA9IHJvd3NbYV1bS0VZX0NPTFVNTl0gYXMgc3RyaW5nO1xuICAgICAgICBjb25zdCBrYiA9IHJvd3NbYl1bS0VZX0NPTFVNTl0gYXMgc3RyaW5nO1xuICAgICAgICByZXR1cm4ga2EgPCBrYiA/IC0xIDoga2EgPiBrYiA/IDEgOiAwO1xuICAgIH0pO1xuICAgIGNvbnN0IHNvcnRlZFJvd3MgPSBvcmRlci5tYXAoaSA9PiByb3dzW2ldKTtcbiAgICBjb25zdCBzb3J0ZWRUaW1lcyA9IG9yZGVyLm1hcChpID0+IHRpbWVzW2ldKTtcbiAgICBjb25zdCByZXN1bHQ6IEJ1aWx0RmlsZVtdID0gW107XG4gICAgbGV0IGNodW5rU3RhcnQgPSAwO1xuICAgIGxldCBjaHVua0J5dGVzID0gMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNvcnRlZFJvd3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3Qgcm93Qnl0ZXMgPSBlc3RpbWF0ZVJvd0J5dGVzKHNvcnRlZFJvd3NbaV0pO1xuICAgICAgICBpZiAoaSA+IGNodW5rU3RhcnQgJiYgY2h1bmtCeXRlcyArIHJvd0J5dGVzID4gdGFyZ2V0Qnl0ZXMpIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKG1ha2Uoc29ydGVkUm93cy5zbGljZShjaHVua1N0YXJ0LCBpKSwgc29ydGVkVGltZXMuc2xpY2UoY2h1bmtTdGFydCwgaSkpKTtcbiAgICAgICAgICAgIGNodW5rU3RhcnQgPSBpO1xuICAgICAgICAgICAgY2h1bmtCeXRlcyA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgY2h1bmtCeXRlcyArPSByb3dCeXRlcztcbiAgICB9XG4gICAgcmVzdWx0LnB1c2gobWFrZShzb3J0ZWRSb3dzLnNsaWNlKGNodW5rU3RhcnQpLCBzb3J0ZWRUaW1lcy5zbGljZShjaHVua1N0YXJ0KSkpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbi8vIFRoZSByYXctc3BsaWNlIGNvdW50ZXJwYXJ0IG9mIGJ1aWxkRmlsZUJ1ZmZlciwgdXNlZCBieSBtZXJnZXM6IHRoZSByb3dzIGFscmVhZHkgY2FycnkgdGhlaXIgd2lubmluZ1xuLy8gY2VsbHMgYXMgcmF3IG9uLWRpc2sgYnl0ZXMgKG5vIEpTIHZhbHVlcyksIHNvIHRoaXMganVzdCBzb3J0cyBieSBrZXksIGNodW5rcyB0byB+dGFyZ2V0Qnl0ZXMsIGFuZFxuLy8gY29uY2F0ZW5hdGVzIHRoZSBieXRlcy4gU2FtZSBvdXRwdXQgZ3VhcmFudGVlczoga2V5LWNvbnRpZ3VvdXMsIGRpc2pvaW50LCBhc2NlbmRpbmcgZmlsZXMuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRGaWxlQnVmZmVyUmF3KHJvd3M6IFJhd1Jvd1tdLCB0YXJnZXRCeXRlcyA9IFRBUkdFVF9GSUxFX0JZVEVTKTogQnVpbHRGaWxlW10ge1xuICAgIGNvbnN0IG1ha2UgPSAocnM6IFJhd1Jvd1tdKTogQnVpbHRGaWxlID0+ICh7XG4gICAgICAgIGJ1ZmZlcjogYnVpbGRPbmVGaWxlUmF3KHJzKSxcbiAgICAgICAgbWluS2V5OiBycy5sZW5ndGggPyByc1swXS5rZXkgOiBcIlwiLFxuICAgICAgICBtYXhLZXk6IHJzLmxlbmd0aCA/IHJzW3JzLmxlbmd0aCAtIDFdLmtleSA6IFwiXCIsXG4gICAgICAgIHJvd0NvdW50OiBycy5sZW5ndGgsXG4gICAgfSk7XG4gICAgaWYgKHJvd3MubGVuZ3RoID09PSAwKSByZXR1cm4gW21ha2UoW10pXTtcbiAgICBjb25zdCBzb3J0ZWQgPSByb3dzLnNsaWNlKCkuc29ydCgoYSwgYikgPT4gYS5rZXkgPCBiLmtleSA/IC0xIDogYS5rZXkgPiBiLmtleSA/IDEgOiAwKTtcbiAgICBjb25zdCByZXN1bHQ6IEJ1aWx0RmlsZVtdID0gW107XG4gICAgbGV0IGNodW5rU3RhcnQgPSAwO1xuICAgIGxldCBjaHVua0J5dGVzID0gMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNvcnRlZC5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCByb3dCeXRlcyA9IGVzdGltYXRlUmF3Um93Qnl0ZXMoc29ydGVkW2ldKTtcbiAgICAgICAgaWYgKGkgPiBjaHVua1N0YXJ0ICYmIGNodW5rQnl0ZXMgKyByb3dCeXRlcyA+IHRhcmdldEJ5dGVzKSB7XG4gICAgICAgICAgICByZXN1bHQucHVzaChtYWtlKHNvcnRlZC5zbGljZShjaHVua1N0YXJ0LCBpKSkpO1xuICAgICAgICAgICAgY2h1bmtTdGFydCA9IGk7XG4gICAgICAgICAgICBjaHVua0J5dGVzID0gMDtcbiAgICAgICAgfVxuICAgICAgICBjaHVua0J5dGVzICs9IHJvd0J5dGVzO1xuICAgIH1cbiAgICByZXN1bHQucHVzaChtYWtlKHNvcnRlZC5zbGljZShjaHVua1N0YXJ0KSkpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbmV4cG9ydCB0eXBlIEJhc2VCdWxrRGF0YWJhc2VSZWFkZXIgPSB7XG4gICAgLy8gSWRlbnRpZmllcyB0aGUgc291cmNlIHRoaXMgcmVhZGVyIGNhbWUgZnJvbSAodGhlIGJ1bGsgZmlsZSBuYW1lLCBvciBcIihzdHJlYW1zKVwiKSBzbyB0aGUgam9pbiBjYW5cbiAgICAvLyBuYW1lIHRoZSBvZmZlbmRpbmcgZmlsZSB3aGVuIG9uZSBvZiBpdHMgcmVhZHMgZmFpbHMuIFVuZGVmaW5lZCBmb3IgcmVhZGVycyBidWlsdCB3aXRob3V0IG9uZS5cbiAgICBuYW1lPzogc3RyaW5nO1xuICAgIHJvd0NvdW50OiBudW1iZXI7XG4gICAgdG90YWxCeXRlczogbnVtYmVyO1xuICAgIC8vIFdyaXRlLXRpbWUgYm91bmRzIG9mIHRoaXMgcmVhZGVyJ3MgZGF0YSAoMCBpZiB1bmtub3duIOKAlCBvbGQgYnVsayBmaWxlcykuXG4gICAgbWluVGltZTogbnVtYmVyO1xuICAgIG1heFRpbWU6IG51bWJlcjtcbiAgICAvLyBLZXktcmFuZ2UgYm91bmRzICh1bmRlZmluZWQgZm9yIG9sZCBmaWxlcyAvIHRoZSBzdHJlYW0gcmVhZGVyIOKAlCB0cmVhdCBhcyBcInNwYW5zIGFsbCBrZXlzXCIpLlxuICAgIG1pbktleT86IHN0cmluZztcbiAgICBtYXhLZXk/OiBzdHJpbmc7XG4gICAgLy8gS2V5cyBpcyBzcGVjaWFsLCBpdCdzIGFsd2F5cyBhdXRvbWF0aWNhbGx5IGRlY29kZWQsIGV2ZW4gdGhvdWdoIGl0IGlzIHN0b3JlZCBhcyBhIG5vcm1hbCBjb2x1bW5cbiAgICBrZXlzOiBzdHJpbmdbXTtcbiAgICBjb2x1bW5zOiB7IGNvbHVtbjogc3RyaW5nOyBieXRlU2l6ZTogbnVtYmVyIH1bXTtcbiAgICAvLyBFYWNoIGtleSdzIHJvdyB3cml0ZS10aW1lICh0aGUgdGltZSBvZiBpdHMgbmV3ZXN0IHdyaXRlIGluIHRoaXMgcmVhZGVyKS4gVGhlIGpvaW4gY29tcGFyZXMgdGhlc2VcbiAgICAvLyBhY3Jvc3MgcmVhZGVycyB0byByZXNvbHZlIGEga2V5IHRvIGl0cyBsYXRlc3QgdmFsdWUuXG4gICAga2V5VGltZXM6IE1hcDxzdHJpbmcsIG51bWJlcj47XG4gICAgLy8gUGVyLWtleSB0b21ic3RvbmUgdGltZTogdGhlIGtleSB3YXMgZGVsZXRlZCBhdCB0aGlzIHRpbWUuIFRoZSBqb2luIHRyZWF0cyBhIGRlbGV0ZSBsaWtlIGFueSBvdGhlclxuICAgIC8vIGV2ZW50IOKAlCBhIGRlbGV0ZSBvbmx5IHdpbnMgaWYgaXQncyBuZXdlciB0aGFuIGV2ZXJ5IHNldCBmb3IgdGhlIGtleS4gT25seSB0aGUgc3RyZWFtIHJlYWRlciBzZXRzIGl0LlxuICAgIGRlbGV0ZVRpbWVzPzogTWFwPHN0cmluZywgbnVtYmVyPjtcbiAgICAvLyBFYWNoIGtleSdzIHZhbHVlIGZvciB0aGUgY29sdW1uIHBsdXMgdGhlIHJvdydzIHdyaXRlLXRpbWUuIHZhbHVlIG1heSBiZSBBQlNFTlQgKHRoZSByb3cgbmV2ZXIgc2V0XG4gICAgLy8gdGhpcyBjb2x1bW4g4oCUIHRoZSBqb2luIHRoZW4gZmFsbHMgdGhyb3VnaCB0byBhbiBvbGRlciByZWFkZXIgZm9yIHRoYXQga2V5L2NvbHVtbikuXG4gICAgZ2V0Q29sdW1uOiAoY29sdW1uOiBzdHJpbmcpID0+IFByb21pc2U8eyBrZXk6IHN0cmluZzsgdmFsdWU6IHVua25vd247IHRpbWU6IG51bWJlciB9W10+O1xuICAgIC8vIExpa2UgZ2V0Q29sdW1uIGJ1dCByZXR1cm5zIGVhY2ggY2VsbCdzIHJhdyBvbi1kaXNrIGVuY29kaW5nICh0eXBlIHRhZyArIGJ5dGVzKSBrZXllZCBieSBrZXksIFdJVEhPVVRcbiAgICAvLyBkZWNvZGluZyB0aGUgdmFsdWUg4oCUIGZvciBtZXJnZXMsIHdoaWNoIHNwbGljZSB0aGUgd2lubmluZyBieXRlcyBzdHJhaWdodCBpbnRvIHRoZSBvdXRwdXQuIEFCU0VOVFxuICAgIC8vIGNlbGxzIGFyZSBvbWl0dGVkIChhIG1pc3Npbmcga2V5IG1lYW5zIHRoaXMgcmVhZGVyIGRpZG4ndCBzZXQgdGhpcyBjb2x1bW4sIHNvIHRoZSBtZXJnZSBmYWxsc1xuICAgIC8vIHRocm91Z2ggdG8gYW4gb2xkZXIgcmVhZGVyKS4gRWFjaCBjZWxsJ3Mgd3JpdGUtdGltZSBpcyB0aGUgcmVhZGVyJ3Mga2V5VGltZXMgdmFsdWUgZm9yIHRoYXQga2V5LlxuICAgIGdldFJhd0NvbHVtbjogKGNvbHVtbjogc3RyaW5nKSA9PiBQcm9taXNlPE1hcDxzdHJpbmcsIFJhd0NlbGw+PjtcbiAgICAvLyBSZXR1cm5zIHRoZSBjb2x1bW4ncyBJTkRFWCAob2Zmc2V0cyArIHR5cGVzKSBwbHVzIGEgY29udGlndW91cyByb3ctcmFuZ2UgYnl0ZSByZWFkZXIuIFRoZSBwbGFubmVkXG4gICAgLy8gbWVyZ2UgbG9hZHMgdGhpcyBmb3IgZXZlcnkgKHNvdXJjZSwgY29sdW1uKSBvbmNlIOKAlCBzbWFsbCAofjVCL3JvdyksIG5vIHZhbHVlIGJ5dGVzIHB1bGxlZCDigJQgYW5kXG4gICAgLy8gdXNlcyB0eXBlcy9vZmZzZXRzIHRvIHBsYW4gdGhlIG91dHB1dCdzIGJ5dGUgbGF5b3V0LiBFeGVjdXRlIHRoZW4gcmVhZHMgb25seSB0aGUgbmVlZGVkIHJ1bnMuXG4gICAgZ2V0Q29sdW1uSW5kZXg6IChjb2x1bW46IHN0cmluZykgPT4gUHJvbWlzZTxDb2x1bW5JbmRleD47XG4gICAgLy8gTWFwcyBhIGtleSB0byBpdHMgcm93IGluZGV4IGluIHRoaXMgcmVhZGVyIChhbmQgdW5kZWZpbmVkIGlmIGFic2VudCkuIFRoZSBwbGFubmVkIG1lcmdlIHVzZXMgdGhpc1xuICAgIC8vIHRvIGxvb2sgdXAgYSB3aW5uaW5nIGNlbGwncyBzb3VyY2Ugcm93IHdpdGhvdXQgZ29pbmcgdGhyb3VnaCBhIGNvbHVtbiByZWFkLlxuICAgIHJvd09mS2V5OiAoa2V5OiBzdHJpbmcpID0+IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICAvLyBUaGUgdmFsdWUgKyB3cml0ZS10aW1lIGZvciAoa2V5LCBjb2x1bW4pLCBvciBBQlNFTlQgaWYgdGhpcyByZWFkZXIgaGFzIG5vIHN1Y2ggY2VsbC5cbiAgICBnZXRTaW5nbGVGaWVsZDogKGtleTogc3RyaW5nLCBjb2x1bW46IHN0cmluZykgPT4gUHJvbWlzZTx7IHZhbHVlOiB1bmtub3duOyB0aW1lOiBudW1iZXIgfSB8IHR5cGVvZiBBQlNFTlQ+O1xufTtcblxuLy8gUmVhZHMganVzdCB0aGUgZmlsZSBoZWFkZXIgKHRoZSA0LWJ5dGUgbGVuZ3RoICsgaGVhZGVyIEpTT04pIOKAlCBubyBjb2x1bW4gZGF0YS4gVXNlZCBieSB0aGUgbWVyZ2Vcbi8vIHBsYW5uZXIgdG8gZ2V0IGVhY2ggZmlsZSdzIHJvdyBjb3VudCwgdGltZSByYW5nZSwgYW5kIGtleSByYW5nZSBjaGVhcGx5IGFjcm9zcyBtYW55IGZpbGVzLlxuZXhwb3J0IHR5cGUgQnVsa0hlYWRlckluZm8gPSB7IHJvd0NvdW50OiBudW1iZXI7IG1pblRpbWU6IG51bWJlcjsgbWF4VGltZTogbnVtYmVyOyBtaW5LZXk/OiBzdHJpbmc7IG1heEtleT86IHN0cmluZzsgY29sdW1uczogeyBjb2x1bW46IHN0cmluZzsgYnl0ZVNpemU6IG51bWJlciB9W10gfTtcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsb2FkQnVsa0hlYWRlcihnZXRSYW5nZTogKHN0YXJ0OiBudW1iZXIsIGVuZDogbnVtYmVyKSA9PiBQcm9taXNlPEJ1ZmZlcj4sIHRvdGFsQnl0ZXM6IG51bWJlcik6IFByb21pc2U8QnVsa0hlYWRlckluZm8+IHtcbiAgICBjb25zdCBoZWFkZXJMZW5ndGggPSAoYXdhaXQgZ2V0UmFuZ2UoMCwgNCkpLnJlYWRVSW50MzJMRSgwKTtcbiAgICBpZiAoaGVhZGVyTGVuZ3RoIDw9IDAgfHwgaGVhZGVyTGVuZ3RoID4gdG90YWxCeXRlcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGhlYWRlciBsZW5ndGggaW4gKDAsICR7dG90YWxCeXRlc31dLCB3YXMgJHtoZWFkZXJMZW5ndGh9YCk7XG4gICAgfVxuICAgIGNvbnN0IGhlYWRlciA9IEpTT04ucGFyc2UoKGF3YWl0IGdldFJhbmdlKDQsIDQgKyBoZWFkZXJMZW5ndGgpKS50b1N0cmluZyhcInV0ZjhcIikpIGFzIEZpbGVIZWFkZXI7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgcm93Q291bnQ6IGhlYWRlci5yb3dDb3VudCxcbiAgICAgICAgbWluVGltZTogaGVhZGVyLm1pblRpbWUgfHwgMCxcbiAgICAgICAgbWF4VGltZTogaGVhZGVyLm1heFRpbWUgfHwgMCxcbiAgICAgICAgbWluS2V5OiBoZWFkZXIubWluS2V5LFxuICAgICAgICBtYXhLZXk6IGhlYWRlci5tYXhLZXksXG4gICAgICAgIGNvbHVtbnM6IGhlYWRlci5jb2x1bW5zLmZpbHRlcihjID0+IGMubmFtZSAhPT0gVElNRV9DT0xVTU4pLm1hcChjID0+ICh7IGNvbHVtbjogYy5uYW1lLCBieXRlU2l6ZTogYy5sZW5ndGggfSkpLFxuICAgIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsb2FkQnVsa0RhdGFiYXNlKGNvbmZpZzoge1xuICAgIHRvdGFsQnl0ZXM6IG51bWJlcjtcbiAgICBnZXRSYW5nZTogKHN0YXJ0OiBudW1iZXIsIGVuZDogbnVtYmVyKSA9PiBQcm9taXNlPEJ1ZmZlcj47XG4gICAgbmFtZT86IHN0cmluZztcbn0pOiBQcm9taXNlPEJhc2VCdWxrRGF0YWJhc2VSZWFkZXI+IHtcbiAgICBjb25zdCBoZWFkZXJMZW5ndGggPSAoYXdhaXQgY29uZmlnLmdldFJhbmdlKDAsIDQpKS5yZWFkVUludDMyTEUoMCk7XG4gICAgaWYgKGhlYWRlckxlbmd0aCA8PSAwIHx8IGhlYWRlckxlbmd0aCA+IGNvbmZpZy50b3RhbEJ5dGVzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgaGVhZGVyIGxlbmd0aCBpbiAoMCwgJHtjb25maWcudG90YWxCeXRlc31dLCB3YXMgJHtoZWFkZXJMZW5ndGh9YCk7XG4gICAgfVxuICAgIGNvbnN0IGhlYWRlciA9IEpTT04ucGFyc2UoKGF3YWl0IGNvbmZpZy5nZXRSYW5nZSg0LCA0ICsgaGVhZGVyTGVuZ3RoKSkudG9TdHJpbmcoXCJ1dGY4XCIpKSBhcyBGaWxlSGVhZGVyO1xuICAgIGNvbnN0IGRhdGFCYXNlID0gNCArIGhlYWRlckxlbmd0aDtcbiAgICBjb25zdCByb3dDb3VudCA9IGhlYWRlci5yb3dDb3VudDtcbiAgICBjb25zdCBjb2xCeU5hbWUgPSBuZXcgTWFwKGhlYWRlci5jb2x1bW5zLm1hcChjID0+IFtjLm5hbWUsIGNdKSk7XG5cbiAgICBhc3luYyBmdW5jdGlvbiByZWFkV2hvbGVDb2x1bW4oY29sdW1uOiBzdHJpbmcpOiBQcm9taXNlPHVua25vd25bXT4ge1xuICAgICAgICBjb25zdCBjb2wgPSBjb2xCeU5hbWUuZ2V0KGNvbHVtbik7XG4gICAgICAgIGlmICghY29sKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGNvbHVtbiAke2NvbHVtbn0sIGZpbGUgb25seSBoYXM6ICR7aGVhZGVyLmNvbHVtbnMubWFwKGMgPT4gYy5uYW1lKS5qb2luKFwiLCBcIil9YCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYmxvYiA9IGF3YWl0IGNvbmZpZy5nZXRSYW5nZShkYXRhQmFzZSArIGNvbC5vZmZzZXQsIGRhdGFCYXNlICsgY29sLm9mZnNldCArIGNvbC5sZW5ndGgpO1xuICAgICAgICByZXR1cm4gZGVjb2RlQnVsa0RhdGEoYmxvYiwgcm93Q291bnQpO1xuICAgIH1cblxuICAgIGNvbnN0IGtleXMgPSAoYXdhaXQgcmVhZFdob2xlQ29sdW1uKEtFWV9DT0xVTU4pKS5tYXAodiA9PiB7XG4gICAgICAgIGlmICh0eXBlb2YgdiAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBzdHJpbmcga2V5LCB3YXMgJHt0eXBlb2Ygdn06ICR7SlNPTi5zdHJpbmdpZnkodik/LnNsaWNlKDAsIDUwMCl9YCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHY7XG4gICAgfSk7XG4gICAgY29uc3Qga2V5SW5kZXggPSBuZXcgTWFwKGtleXMubWFwKChrZXksIGkpID0+IFtrZXksIGldKSk7XG5cbiAgICAvLyBQZXItcm93IHdyaXRlLXRpbWVzLiBPbGQgZmlsZXMgKHdyaXR0ZW4gYmVmb3JlIHRoaXMgY29sdW1uIGV4aXN0ZWQpIGZhbGwgYmFjayB0byB0aGUgZmlsZSdzIGhlYWRlclxuICAgIC8vIHRpbWUgKG9yIDApIGZvciBldmVyeSByb3cg4oCUIGZpbmUsIHNpbmNlIHN1Y2ggZmlsZXMgcHJlZGF0ZSBjb25jdXJyZW50LXRpbWUgcmVzb2x1dGlvbi5cbiAgICBjb25zdCB0aW1lczogbnVtYmVyW10gPSBjb2xCeU5hbWUuaGFzKFRJTUVfQ09MVU1OKVxuICAgICAgICA/IChhd2FpdCByZWFkV2hvbGVDb2x1bW4oVElNRV9DT0xVTU4pKS5tYXAodiA9PiB0eXBlb2YgdiA9PT0gXCJudW1iZXJcIiA/IHYgOiAwKVxuICAgICAgICA6IGtleXMubWFwKCgpID0+IGhlYWRlci5tYXhUaW1lIHx8IDApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgbmFtZTogY29uZmlnLm5hbWUsXG4gICAgICAgIHJvd0NvdW50LFxuICAgICAgICB0b3RhbEJ5dGVzOiBjb25maWcudG90YWxCeXRlcyxcbiAgICAgICAgbWluVGltZTogaGVhZGVyLm1pblRpbWUgfHwgMCxcbiAgICAgICAgbWF4VGltZTogaGVhZGVyLm1heFRpbWUgfHwgMCxcbiAgICAgICAgbWluS2V5OiBoZWFkZXIubWluS2V5LFxuICAgICAgICBtYXhLZXk6IGhlYWRlci5tYXhLZXksXG4gICAgICAgIGtleXMsXG4gICAgICAgIGtleVRpbWVzOiBuZXcgTWFwKGtleXMubWFwKChrZXksIGkpID0+IFtrZXksIHRpbWVzW2ldXSkpLFxuICAgICAgICBjb2x1bW5zOiBoZWFkZXIuY29sdW1ucy5maWx0ZXIoYyA9PiBjLm5hbWUgIT09IFRJTUVfQ09MVU1OKS5tYXAoYyA9PiAoeyBjb2x1bW46IGMubmFtZSwgYnl0ZVNpemU6IGMubGVuZ3RoIH0pKSxcbiAgICAgICAgYXN5bmMgZ2V0Q29sdW1uKGNvbHVtbikge1xuICAgICAgICAgICAgY29uc3QgdmFsdWVzID0gYXdhaXQgcmVhZFdob2xlQ29sdW1uKGNvbHVtbik7XG4gICAgICAgICAgICByZXR1cm4ga2V5cy5tYXAoKGtleSwgaSkgPT4gKHsga2V5LCB2YWx1ZTogdmFsdWVzW2ldLCB0aW1lOiB0aW1lc1tpXSB9KSk7XG4gICAgICAgIH0sXG4gICAgICAgIGFzeW5jIGdldFJhd0NvbHVtbihjb2x1bW4pIHtcbiAgICAgICAgICAgIGNvbnN0IG1hcCA9IG5ldyBNYXA8c3RyaW5nLCBSYXdDZWxsPigpO1xuICAgICAgICAgICAgY29uc3QgY29sID0gY29sQnlOYW1lLmdldChjb2x1bW4pO1xuICAgICAgICAgICAgaWYgKCFjb2wpIHJldHVybiBtYXA7IC8vIGZpbGUgbGFja3MgdGhpcyBjb2x1bW4g4oaSIGV2ZXJ5IGNlbGwgQUJTRU5UIChmYWxsIHRocm91Z2gpXG4gICAgICAgICAgICBjb25zdCBibG9iID0gYXdhaXQgY29uZmlnLmdldFJhbmdlKGRhdGFCYXNlICsgY29sLm9mZnNldCwgZGF0YUJhc2UgKyBjb2wub2Zmc2V0ICsgY29sLmxlbmd0aCk7XG4gICAgICAgICAgICBjb25zdCBpbmRleFNpemUgPSA0ICogKHJvd0NvdW50ICsgMSkgKyByb3dDb3VudDtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcm93Q291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHR5cGUgPSBibG9iWzQgKiAocm93Q291bnQgKyAxKSArIGldO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlID09PSBUWVBFX0FCU0VOVCkgY29udGludWU7IC8vIG9taXQgQUJTRU5UIHNvIHRoZSBqb2luIGZhbGxzIHRocm91Z2hcbiAgICAgICAgICAgICAgICBjb25zdCBzdGFydCA9IGJsb2IucmVhZFVJbnQzMkxFKDQgKiBpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBlbmQgPSBibG9iLnJlYWRVSW50MzJMRSg0ICogKGkgKyAxKSk7XG4gICAgICAgICAgICAgICAgbWFwLnNldChrZXlzW2ldLCB7IHR5cGUsIGJ5dGVzOiBibG9iLnN1YmFycmF5KGluZGV4U2l6ZSArIHN0YXJ0LCBpbmRleFNpemUgKyBlbmQpIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1hcDtcbiAgICAgICAgfSxcbiAgICAgICAgYXN5bmMgZ2V0Q29sdW1uSW5kZXgoY29sdW1uKSB7XG4gICAgICAgICAgICBjb25zdCBjb2wgPSBjb2xCeU5hbWUuZ2V0KGNvbHVtbik7XG4gICAgICAgICAgICBpZiAoIWNvbCkge1xuICAgICAgICAgICAgICAgIC8vIEZpbGUgbGFja3MgdGhpcyBjb2x1bW4g4oCUIHByZXNlbnQgYW4gYWxsLUFCU0VOVCBpbmRleCBzbyB0aGUgcGxhbm5lciBjYW4gdHJlYXQgaXRcbiAgICAgICAgICAgICAgICAvLyB1bmlmb3JtbHkgd2l0aCBmaWxlcyB0aGF0IGhhdmUgdGhlIGNvbHVtbi5cbiAgICAgICAgICAgICAgICBjb25zdCBvZmZzZXRzID0gbmV3IFVpbnQzMkFycmF5KHJvd0NvdW50ICsgMSk7XG4gICAgICAgICAgICAgICAgY29uc3QgdHlwZXMgPSBuZXcgVWludDhBcnJheShyb3dDb3VudCkuZmlsbChUWVBFX0FCU0VOVCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0cyxcbiAgICAgICAgICAgICAgICAgICAgdHlwZXMsXG4gICAgICAgICAgICAgICAgICAgIGFzeW5jIHJlYWRWYWx1ZUJ5dGVzKCkgeyByZXR1cm4gRU1QVFlfQlVGRkVSOyB9LFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBjb2xCYXNlID0gZGF0YUJhc2UgKyBjb2wub2Zmc2V0O1xuICAgICAgICAgICAgY29uc3QgaW5kZXhTaXplID0gNCAqIChyb3dDb3VudCArIDEpICsgcm93Q291bnQ7XG4gICAgICAgICAgICAvLyBPbmUgcmVhZCBwdWxscyBvZmZzZXRzICsgdHlwZXMgKHNtYWxsIOKAlCB+NSBCL3JvdykuIEJsb2NrIGNhY2hlIG1ha2VzIHN1YnNlcXVlbnQgdmFsdWUgcmVhZHNcbiAgICAgICAgICAgIC8vIG9mIG5lYXJieSByb3dzIGNoZWFwLiBEZWNvZGVkIGludG8gYWxpZ25lZCB0eXBlZCBhcnJheXMgc28gdGhlIGV4ZWN1dG9yIGNhbiBkbyBPKDEpIGxvb2t1cHMuXG4gICAgICAgICAgICBjb25zdCBpbmRleEJ1ZiA9IGF3YWl0IGNvbmZpZy5nZXRSYW5nZShjb2xCYXNlLCBjb2xCYXNlICsgaW5kZXhTaXplKTtcbiAgICAgICAgICAgIGNvbnN0IG9mZnNldHMgPSBuZXcgVWludDMyQXJyYXkocm93Q291bnQgKyAxKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IHJvd0NvdW50OyBpKyspIG9mZnNldHNbaV0gPSBpbmRleEJ1Zi5yZWFkVUludDMyTEUoNCAqIGkpO1xuICAgICAgICAgICAgY29uc3QgdHlwZXMgPSBuZXcgVWludDhBcnJheShyb3dDb3VudCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJvd0NvdW50OyBpKyspIHR5cGVzW2ldID0gaW5kZXhCdWZbNCAqIChyb3dDb3VudCArIDEpICsgaV07XG4gICAgICAgICAgICBjb25zdCBkYXRhU3RhcnQgPSBjb2xCYXNlICsgaW5kZXhTaXplO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBvZmZzZXRzLFxuICAgICAgICAgICAgICAgIHR5cGVzLFxuICAgICAgICAgICAgICAgIGFzeW5jIHJlYWRWYWx1ZUJ5dGVzKHN0YXJ0Um93LCBlbmRSb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVuZFJvdyA8PSBzdGFydFJvdykgcmV0dXJuIEVNUFRZX0JVRkZFUjtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhcnQgPSBvZmZzZXRzW3N0YXJ0Um93XTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZW5kID0gb2Zmc2V0c1tlbmRSb3ddO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZW5kIDw9IHN0YXJ0KSByZXR1cm4gRU1QVFlfQlVGRkVSO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29uZmlnLmdldFJhbmdlKGRhdGFTdGFydCArIHN0YXJ0LCBkYXRhU3RhcnQgKyBlbmQpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICAgICByb3dPZktleShrZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBrZXlJbmRleC5nZXQoa2V5KTtcbiAgICAgICAgfSxcbiAgICAgICAgYXN5bmMgZ2V0U2luZ2xlRmllbGQoa2V5LCBjb2x1bW4pIHtcbiAgICAgICAgICAgIGNvbnN0IHJvdyA9IGtleUluZGV4LmdldChrZXkpO1xuICAgICAgICAgICAgaWYgKHJvdyA9PT0gdW5kZWZpbmVkKSByZXR1cm4gQUJTRU5UO1xuICAgICAgICAgICAgY29uc3QgY29sID0gY29sQnlOYW1lLmdldChjb2x1bW4pO1xuICAgICAgICAgICAgaWYgKCFjb2wpIHJldHVybiBBQlNFTlQ7XG4gICAgICAgICAgICBjb25zdCBjb2xCYXNlID0gZGF0YUJhc2UgKyBjb2wub2Zmc2V0O1xuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0c0J1ZiA9IGF3YWl0IGNvbmZpZy5nZXRSYW5nZShjb2xCYXNlICsgNCAqIHJvdywgY29sQmFzZSArIDQgKiByb3cgKyA4KTtcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0ID0gb2Zmc2V0c0J1Zi5yZWFkVUludDMyTEUoMCk7XG4gICAgICAgICAgICBjb25zdCBlbmQgPSBvZmZzZXRzQnVmLnJlYWRVSW50MzJMRSg0KTtcbiAgICAgICAgICAgIGNvbnN0IHR5cGVQb3MgPSBjb2xCYXNlICsgNCAqIChyb3dDb3VudCArIDEpICsgcm93O1xuICAgICAgICAgICAgY29uc3QgdHlwZUJ1ZiA9IGF3YWl0IGNvbmZpZy5nZXRSYW5nZSh0eXBlUG9zLCB0eXBlUG9zICsgMSk7XG4gICAgICAgICAgICBjb25zdCBkYXRhU3RhcnQgPSBjb2xCYXNlICsgNCAqIChyb3dDb3VudCArIDEpICsgcm93Q291bnQ7XG4gICAgICAgICAgICBsZXQgYnl0ZXMgPSBFTVBUWV9CVUZGRVI7XG4gICAgICAgICAgICBpZiAoZW5kID4gc3RhcnQpIHtcbiAgICAgICAgICAgICAgICBieXRlcyA9IGF3YWl0IGNvbmZpZy5nZXRSYW5nZShkYXRhU3RhcnQgKyBzdGFydCwgZGF0YVN0YXJ0ICsgZW5kKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gZGVjb2RlVmFsdWUodHlwZUJ1ZlswXSwgYnl0ZXMpO1xuICAgICAgICAgICAgaWYgKHZhbHVlID09PSBBQlNFTlQpIHJldHVybiBBQlNFTlQ7XG4gICAgICAgICAgICByZXR1cm4geyB2YWx1ZSwgdGltZTogdGltZXNbcm93XSB9O1xuICAgICAgICB9LFxuICAgIH07XG59XG4iXX0=
513
+ /* _JS_SOURCE_HASH = "9a6ef16155eeef797edef47467ace2aa8a3c9b5493e6be9fbb76a7c57b83b8b5"; */