@discordeno/rest 19.0.0-next.b2f65c2 → 19.0.0-next.b567c13
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.
- package/dist/cjs/index.cjs +23 -0
- package/dist/cjs/invalidBucket.cjs +84 -0
- package/dist/cjs/manager.cjs +1325 -0
- package/dist/cjs/queue.cjs +165 -0
- package/dist/cjs/routes.cjs +533 -0
- package/dist/cjs/types.cjs +6 -0
- package/dist/cjs/typings/routes.cjs +6 -0
- package/dist/esm/index.js +8 -0
- package/dist/esm/invalidBucket.js +82 -0
- package/dist/esm/manager.js +1303 -0
- package/dist/esm/queue.js +157 -0
- package/dist/esm/routes.js +525 -0
- package/dist/esm/types.js +3 -0
- package/dist/esm/typings/routes.js +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/invalidBucket.d.ts.map +1 -0
- package/dist/types/manager.d.ts.map +1 -0
- package/dist/{queue.d.ts → types/queue.d.ts} +5 -0
- package/dist/types/queue.d.ts.map +1 -0
- package/dist/types/routes.d.ts.map +1 -0
- package/dist/{types.d.ts → types/types.d.ts} +212 -13
- package/dist/types/types.d.ts.map +1 -0
- package/dist/{typings → types/typings}/routes.d.ts +24 -4
- package/dist/types/typings/routes.d.ts.map +1 -0
- package/package.json +13 -7
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -8
- package/dist/index.js.map +0 -1
- package/dist/invalidBucket.d.ts.map +0 -1
- package/dist/invalidBucket.js +0 -82
- package/dist/invalidBucket.js.map +0 -1
- package/dist/manager.d.ts.map +0 -1
- package/dist/manager.js +0 -1139
- package/dist/manager.js.map +0 -1
- package/dist/queue.d.ts.map +0 -1
- package/dist/queue.js +0 -153
- package/dist/queue.js.map +0 -1
- package/dist/routes.d.ts.map +0 -1
- package/dist/routes.js +0 -487
- package/dist/routes.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +0 -1
- package/dist/typings/routes.d.ts.map +0 -1
- package/dist/typings/routes.js +0 -3
- package/dist/typings/routes.js.map +0 -1
- /package/dist/{index.d.ts → types/index.d.ts} +0 -0
- /package/dist/{invalidBucket.d.ts → types/invalidBucket.d.ts} +0 -0
- /package/dist/{manager.d.ts → types/manager.d.ts} +0 -0
- /package/dist/{routes.d.ts → types/routes.d.ts} +0 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "Queue", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: ()=>Queue
|
|
8
|
+
});
|
|
9
|
+
const _utils = require("@discordeno/utils");
|
|
10
|
+
let Queue = class Queue {
|
|
11
|
+
constructor(rest, options){
|
|
12
|
+
/** Amount of requests that have are remaining. Defaults to 1. */ this.remaining = 1;
|
|
13
|
+
/** Max requests for this this. Defaults to 1. */ this.max = 1;
|
|
14
|
+
/** The time that discord allows to make the max number of requests. Defaults to 0 */ this.interval = 0;
|
|
15
|
+
/** The requests that are currently pending. */ this.waiting = [];
|
|
16
|
+
/** The requests that are currently pending. */ this.pending = [];
|
|
17
|
+
/** Whether or not the waiting queue is already processing. */ this.processing = false;
|
|
18
|
+
/** Whether or not the pending queue is already processing. */ this.processingPending = false;
|
|
19
|
+
/** Whether the first request is pending. */ this.firstRequest = false;
|
|
20
|
+
/** When requests started being made to determine when the interval will reset it. */ this.frozenAt = 0;
|
|
21
|
+
/** The time in milliseconds to wait before deleting this queue if it is empty. Defaults to 60000(one minute). */ this.deleteQueueDelay = 60000;
|
|
22
|
+
/** The authentication header used for the OAuth2 request. Defaults to an empty string for non-OAuth2 requests */ this.authentication = '';
|
|
23
|
+
this.rest = rest;
|
|
24
|
+
this.url = options.url;
|
|
25
|
+
if (options.interval) this.interval = options.interval;
|
|
26
|
+
if (options.max) this.max = options.max;
|
|
27
|
+
if (options.remaining) this.remaining = options.remaining;
|
|
28
|
+
if (options.timeoutId) this.timeoutId = options.timeoutId;
|
|
29
|
+
if (options.deleteQueueDelay) this.deleteQueueDelay = options.deleteQueueDelay;
|
|
30
|
+
if (options.authentication) this.authentication = options.authentication;
|
|
31
|
+
}
|
|
32
|
+
/** Check if there is any remaining requests that are allowed. */ isRequestAllowed() {
|
|
33
|
+
return this.remaining > 0;
|
|
34
|
+
}
|
|
35
|
+
/** Pauses the execution until a request is allowed to be made. */ async waitUntilRequestAvailable() {
|
|
36
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
37
|
+
return await new Promise(async (resolve)=>{
|
|
38
|
+
// If whatever amount of requests is left is more than the safety margin, allow the request
|
|
39
|
+
if (this.isRequestAllowed()) {
|
|
40
|
+
// this.remaining++;
|
|
41
|
+
resolve();
|
|
42
|
+
} else {
|
|
43
|
+
this.waiting.push(resolve);
|
|
44
|
+
await this.processWaiting();
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/** Process the queue of requests waiting to be handled. */ async processWaiting() {
|
|
49
|
+
// If already processing, that loop will handle all waiting requests.
|
|
50
|
+
if (this.processing) return;
|
|
51
|
+
// Mark as processing so other loops don't start
|
|
52
|
+
this.processing = true;
|
|
53
|
+
while(this.waiting.length > 0){
|
|
54
|
+
_utils.logger.debug(`[Queue] ${this.isOauth2Queue() ? '' : 'Bearer '}${this.url} process waiting while loop ran.`);
|
|
55
|
+
if (this.isRequestAllowed()) {
|
|
56
|
+
// Resolve the next item in the queue
|
|
57
|
+
this.waiting.shift()?.();
|
|
58
|
+
} else {
|
|
59
|
+
await (0, _utils.delay)(1000);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Mark as false so next pending request can be triggered by new loop.
|
|
63
|
+
this.processing = false;
|
|
64
|
+
}
|
|
65
|
+
/** Process the queue of all requests pending to be sent. */ async processPending() {
|
|
66
|
+
// If already processing, that loop will handle all pending requests.
|
|
67
|
+
if (this.processingPending || !this.pending.length) return;
|
|
68
|
+
// Mark as processing so other loops don't start
|
|
69
|
+
this.processingPending = true;
|
|
70
|
+
while(this.pending.length > 0){
|
|
71
|
+
_utils.logger.debug(`Queue ${this.isOauth2Queue() ? '' : 'Bearer '}${this.url} process pending while loop ran with ${this.pending.length}.`);
|
|
72
|
+
if (!this.firstRequest && !this.isRequestAllowed()) {
|
|
73
|
+
const now = Date.now();
|
|
74
|
+
const future = this.frozenAt + this.interval;
|
|
75
|
+
await (0, _utils.delay)(future > now ? future - now : 1000);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const request = this.pending[0];
|
|
79
|
+
if (request) {
|
|
80
|
+
const basicURL = this.rest.simplifyUrl(request.route, request.method);
|
|
81
|
+
// If this url is still rate limited, try again
|
|
82
|
+
const urlResetIn = this.rest.checkRateLimits(basicURL, request.requestBodyOptions?.headers);
|
|
83
|
+
if (urlResetIn) await (0, _utils.delay)(urlResetIn);
|
|
84
|
+
// IF A BUCKET EXISTS, CHECK THE BUCKET'S RATE LIMITS
|
|
85
|
+
const bucketResetIn = request.bucketId ? this.rest.checkRateLimits(request.bucketId, request.requestBodyOptions?.headers) : false;
|
|
86
|
+
if (bucketResetIn) await (0, _utils.delay)(bucketResetIn);
|
|
87
|
+
this.firstRequest = false;
|
|
88
|
+
this.remaining--;
|
|
89
|
+
if (this.timeoutId && this.remaining === 0 && this.interval !== 0) {
|
|
90
|
+
this.timeoutId = setTimeout(()=>{
|
|
91
|
+
this.remaining = this.max;
|
|
92
|
+
this.timeoutId = undefined;
|
|
93
|
+
}, this.interval);
|
|
94
|
+
}
|
|
95
|
+
// Remove from queue, we are executing it.
|
|
96
|
+
this.pending.shift();
|
|
97
|
+
// Check if this request is able to be made globally
|
|
98
|
+
await this.rest.invalidBucket.waitUntilRequestAvailable();
|
|
99
|
+
await this.rest.sendRequest(request)// Should be handled in sendRequest, this catch just prevents bots from dying
|
|
100
|
+
.catch(()=>null);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
_utils.logger.debug(`Queue ${this.isOauth2Queue() ? '' : 'Bearer '}${this.url} process pending while loop exited with ${this.pending.length}.`);
|
|
104
|
+
// Mark as false so next pending request can be triggered by new loop.
|
|
105
|
+
this.processingPending = false;
|
|
106
|
+
this.cleanup();
|
|
107
|
+
}
|
|
108
|
+
handleCompletedRequest(headers) {
|
|
109
|
+
if (headers.max === 0) {
|
|
110
|
+
this.remaining++;
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (!this.frozenAt) this.frozenAt = Date.now();
|
|
114
|
+
if (headers.interval !== undefined) this.interval = headers.interval;
|
|
115
|
+
if (headers.remaining !== undefined) this.remaining = headers.remaining;
|
|
116
|
+
if (this.remaining <= 1) {
|
|
117
|
+
this.timeoutId = setTimeout(()=>{
|
|
118
|
+
this.remaining = this.max;
|
|
119
|
+
this.timeoutId = undefined;
|
|
120
|
+
}, headers.interval);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/** Checks if a request is available and adds it to the queue. Also triggers queue processing if not already processing. */ async makeRequest(options) {
|
|
124
|
+
await this.waitUntilRequestAvailable();
|
|
125
|
+
this.pending.push(options);
|
|
126
|
+
this.processPending();
|
|
127
|
+
}
|
|
128
|
+
/** Cleans up the queue by checking if there is nothing left and removing it. */ cleanup() {
|
|
129
|
+
if (!this.isQueueClearable()) {
|
|
130
|
+
this.processPending();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
_utils.logger.debug(`[Queue] ${this.isOauth2Queue() ? '' : 'Bearer '}${this.url}. Delaying delete for ${this.deleteQueueDelay}ms`);
|
|
134
|
+
// Delete in a minute giving a bit of time to allow new requests that may reuse this queue
|
|
135
|
+
setTimeout(async ()=>{
|
|
136
|
+
if (!this.isQueueClearable()) {
|
|
137
|
+
_utils.logger.debug(`[Queue] ${this.isOauth2Queue() ? '' : 'Bearer '}${this.url}. is not clearable. Restarting processing of queue.`);
|
|
138
|
+
this.processPending();
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
_utils.logger.debug(`[Queue] ${this.url}. Deleting`);
|
|
142
|
+
if (this.timeoutId) clearTimeout(this.timeoutId);
|
|
143
|
+
// No requests have been requested for this queue so we nuke this queue
|
|
144
|
+
this.rest.queues.delete(`${this.authentication}${this.url}`);
|
|
145
|
+
_utils.logger.debug(`[Queue] ${this.url}. Deleted! Remaining: (${this.rest.queues.size})`, [
|
|
146
|
+
...this.rest.queues.values()
|
|
147
|
+
].map((queue)=>`${queue.isOauth2Queue() ? '' : 'Bearer '}${queue.url}`));
|
|
148
|
+
if (this.rest.queues.size) this.processPending();
|
|
149
|
+
}, this.deleteQueueDelay);
|
|
150
|
+
}
|
|
151
|
+
/** Simply checks if the queue is able to be cleared or it has requests pending. */ isQueueClearable() {
|
|
152
|
+
if (this.firstRequest) return false;
|
|
153
|
+
if (this.waiting.length > 0) return false;
|
|
154
|
+
if (this.pending.length > 0) return false;
|
|
155
|
+
if (this.interval === 0) return false;
|
|
156
|
+
if (this.processing) return false;
|
|
157
|
+
if (this.processingPending) return false;
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
isOauth2Queue() {
|
|
161
|
+
return this.authentication === '';
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9xdWV1ZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBkZWxheSwgbG9nZ2VyIH0gZnJvbSAnQGRpc2NvcmRlbm8vdXRpbHMnXG5pbXBvcnQgdHlwZSB7IFJlc3RNYW5hZ2VyLCBTZW5kUmVxdWVzdE9wdGlvbnMgfSBmcm9tICcuL3R5cGVzLmpzJ1xuXG5leHBvcnQgY2xhc3MgUXVldWUge1xuICAvKiogVGhlIHJlc3QgbWFuYWdlciAqL1xuICByZXN0OiBSZXN0TWFuYWdlclxuICAvKiogQW1vdW50IG9mIHJlcXVlc3RzIHRoYXQgaGF2ZSBhcmUgcmVtYWluaW5nLiBEZWZhdWx0cyB0byAxLiAqL1xuICByZW1haW5pbmc6IG51bWJlciA9IDFcbiAgLyoqIE1heCByZXF1ZXN0cyBmb3IgdGhpcyB0aGlzLiBEZWZhdWx0cyB0byAxLiAqL1xuICBtYXg6IG51bWJlciA9IDFcbiAgLyoqIFRoZSB0aW1lIHRoYXQgZGlzY29yZCBhbGxvd3MgdG8gbWFrZSB0aGUgbWF4IG51bWJlciBvZiByZXF1ZXN0cy4gRGVmYXVsdHMgdG8gMCAqL1xuICBpbnRlcnZhbDogbnVtYmVyID0gMFxuICAvKiogdGltZXIgdG8gcmVzZXQgdG8gMCAqL1xuICB0aW1lb3V0SWQ6IE5vZGVKUy5UaW1lb3V0IHwgdW5kZWZpbmVkXG4gIC8qKiBUaGUgcmVxdWVzdHMgdGhhdCBhcmUgY3VycmVudGx5IHBlbmRpbmcuICovXG4gIHdhaXRpbmc6IEFycmF5PCh2YWx1ZTogdm9pZCB8IFByb21pc2VMaWtlPHZvaWQ+KSA9PiB2b2lkPiA9IFtdXG4gIC8qKiBUaGUgcmVxdWVzdHMgdGhhdCBhcmUgY3VycmVudGx5IHBlbmRpbmcuICovXG4gIHBlbmRpbmc6IFNlbmRSZXF1ZXN0T3B0aW9uc1tdID0gW11cbiAgLyoqIFdoZXRoZXIgb3Igbm90IHRoZSB3YWl0aW5nIHF1ZXVlIGlzIGFscmVhZHkgcHJvY2Vzc2luZy4gKi9cbiAgcHJvY2Vzc2luZzogYm9vbGVhbiA9IGZhbHNlXG4gIC8qKiBXaGV0aGVyIG9yIG5vdCB0aGUgcGVuZGluZyBxdWV1ZSBpcyBhbHJlYWR5IHByb2Nlc3NpbmcuICovXG4gIHByb2Nlc3NpbmdQZW5kaW5nOiBib29sZWFuID0gZmFsc2VcbiAgLyoqIFdoZXRoZXIgdGhlIGZpcnN0IHJlcXVlc3QgaXMgcGVuZGluZy4gKi9cbiAgZmlyc3RSZXF1ZXN0OiBib29sZWFuID0gZmFsc2VcbiAgLyoqIFRoZSB1cmwgdGhhdCBhbGwgdGhlIHJlcXVlc3RzIGluIHRoaXMgcXVldWUgYXJlIHNlbnQgdG8uICovXG4gIHVybDogc3RyaW5nXG4gIC8qKiBXaGVuIHJlcXVlc3RzIHN0YXJ0ZWQgYmVpbmcgbWFkZSB0byBkZXRlcm1pbmUgd2hlbiB0aGUgaW50ZXJ2YWwgd2lsbCByZXNldCBpdC4gKi9cbiAgZnJvemVuQXQ6IG51bWJlciA9IDBcbiAgLyoqIFRoZSB0aW1lIGluIG1pbGxpc2Vjb25kcyB0byB3YWl0IGJlZm9yZSBkZWxldGluZyB0aGlzIHF1ZXVlIGlmIGl0IGlzIGVtcHR5LiBEZWZhdWx0cyB0byA2MDAwMChvbmUgbWludXRlKS4gKi9cbiAgZGVsZXRlUXVldWVEZWxheTogbnVtYmVyID0gNjAwMDBcbiAgLyoqIFRoZSBhdXRoZW50aWNhdGlvbiBoZWFkZXIgdXNlZCBmb3IgdGhlIE9BdXRoMiByZXF1ZXN0LiBEZWZhdWx0cyB0byBhbiBlbXB0eSBzdHJpbmcgZm9yIG5vbi1PQXV0aDIgcmVxdWVzdHMgKi9cbiAgYXV0aGVudGljYXRpb246IHN0cmluZyA9ICcnXG5cbiAgY29uc3RydWN0b3IocmVzdDogUmVzdE1hbmFnZXIsIG9wdGlvbnM6IFF1ZXVlT3B0aW9ucykge1xuICAgIHRoaXMucmVzdCA9IHJlc3RcbiAgICB0aGlzLnVybCA9IG9wdGlvbnMudXJsXG5cbiAgICBpZiAob3B0aW9ucy5pbnRlcnZhbCkgdGhpcy5pbnRlcnZhbCA9IG9wdGlvbnMuaW50ZXJ2YWxcbiAgICBpZiAob3B0aW9ucy5tYXgpIHRoaXMubWF4ID0gb3B0aW9ucy5tYXhcbiAgICBpZiAob3B0aW9ucy5yZW1haW5pbmcpIHRoaXMucmVtYWluaW5nID0gb3B0aW9ucy5yZW1haW5pbmdcbiAgICBpZiAob3B0aW9ucy50aW1lb3V0SWQpIHRoaXMudGltZW91dElkID0gb3B0aW9ucy50aW1lb3V0SWRcbiAgICBpZiAob3B0aW9ucy5kZWxldGVRdWV1ZURlbGF5KSB0aGlzLmRlbGV0ZVF1ZXVlRGVsYXkgPSBvcHRpb25zLmRlbGV0ZVF1ZXVlRGVsYXlcbiAgICBpZiAob3B0aW9ucy5hdXRoZW50aWNhdGlvbikgdGhpcy5hdXRoZW50aWNhdGlvbiA9IG9wdGlvbnMuYXV0aGVudGljYXRpb25cbiAgfVxuXG4gIC8qKiBDaGVjayBpZiB0aGVyZSBpcyBhbnkgcmVtYWluaW5nIHJlcXVlc3RzIHRoYXQgYXJlIGFsbG93ZWQuICovXG4gIGlzUmVxdWVzdEFsbG93ZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucmVtYWluaW5nID4gMFxuICB9XG5cbiAgLyoqIFBhdXNlcyB0aGUgZXhlY3V0aW9uIHVudGlsIGEgcmVxdWVzdCBpcyBhbGxvd2VkIHRvIGJlIG1hZGUuICovXG4gIGFzeW5jIHdhaXRVbnRpbFJlcXVlc3RBdmFpbGFibGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWFzeW5jLXByb21pc2UtZXhlY3V0b3JcbiAgICByZXR1cm4gYXdhaXQgbmV3IFByb21pc2UoYXN5bmMgKHJlc29sdmUpID0+IHtcbiAgICAgIC8vIElmIHdoYXRldmVyIGFtb3VudCBvZiByZXF1ZXN0cyBpcyBsZWZ0IGlzIG1vcmUgdGhhbiB0aGUgc2FmZXR5IG1hcmdpbiwgYWxsb3cgdGhlIHJlcXVlc3RcbiAgICAgIGlmICh0aGlzLmlzUmVxdWVzdEFsbG93ZWQoKSkge1xuICAgICAgICAvLyB0aGlzLnJlbWFpbmluZysrO1xuICAgICAgICByZXNvbHZlKClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMud2FpdGluZy5wdXNoKHJlc29sdmUpXG4gICAgICAgIGF3YWl0IHRoaXMucHJvY2Vzc1dhaXRpbmcoKVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICAvKiogUHJvY2VzcyB0aGUgcXVldWUgb2YgcmVxdWVzdHMgd2FpdGluZyB0byBiZSBoYW5kbGVkLiAqL1xuICBhc3luYyBwcm9jZXNzV2FpdGluZygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBJZiBhbHJlYWR5IHByb2Nlc3NpbmcsIHRoYXQgbG9vcCB3aWxsIGhhbmRsZSBhbGwgd2FpdGluZyByZXF1ZXN0cy5cbiAgICBpZiAodGhpcy5wcm9jZXNzaW5nKSByZXR1cm5cbiAgICAvLyBNYXJrIGFzIHByb2Nlc3Npbmcgc28gb3RoZXIgbG9vcHMgZG9uJ3Qgc3RhcnRcbiAgICB0aGlzLnByb2Nlc3NpbmcgPSB0cnVlXG5cbiAgICB3aGlsZSAodGhpcy53YWl0aW5nLmxlbmd0aCA+IDApIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgW1F1ZXVlXSAke3RoaXMuaXNPYXV0aDJRdWV1ZSgpID8gJycgOiAnQmVhcmVyICd9JHt0aGlzLnVybH0gcHJvY2VzcyB3YWl0aW5nIHdoaWxlIGxvb3AgcmFuLmApXG4gICAgICBpZiAodGhpcy5pc1JlcXVlc3RBbGxvd2VkKCkpIHtcbiAgICAgICAgLy8gUmVzb2x2ZSB0aGUgbmV4dCBpdGVtIGluIHRoZSBxdWV1ZVxuICAgICAgICB0aGlzLndhaXRpbmcuc2hpZnQoKT8uKClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IGRlbGF5KDEwMDApXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gTWFyayBhcyBmYWxzZSBzbyBuZXh0IHBlbmRpbmcgcmVxdWVzdCBjYW4gYmUgdHJpZ2dlcmVkIGJ5IG5ldyBsb29wLlxuICAgIHRoaXMucHJvY2Vzc2luZyA9IGZhbHNlXG4gIH1cblxuICAvKiogUHJvY2VzcyB0aGUgcXVldWUgb2YgYWxsIHJlcXVlc3RzIHBlbmRpbmcgdG8gYmUgc2VudC4gKi9cbiAgYXN5bmMgcHJvY2Vzc1BlbmRpbmcoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gSWYgYWxyZWFkeSBwcm9jZXNzaW5nLCB0aGF0IGxvb3Agd2lsbCBoYW5kbGUgYWxsIHBlbmRpbmcgcmVxdWVzdHMuXG4gICAgaWYgKHRoaXMucHJvY2Vzc2luZ1BlbmRpbmcgfHwgIXRoaXMucGVuZGluZy5sZW5ndGgpIHJldHVyblxuXG4gICAgLy8gTWFyayBhcyBwcm9jZXNzaW5nIHNvIG90aGVyIGxvb3BzIGRvbid0IHN0YXJ0XG4gICAgdGhpcy5wcm9jZXNzaW5nUGVuZGluZyA9IHRydWVcblxuICAgIHdoaWxlICh0aGlzLnBlbmRpbmcubGVuZ3RoID4gMCkge1xuICAgICAgbG9nZ2VyLmRlYnVnKGBRdWV1ZSAke3RoaXMuaXNPYXV0aDJRdWV1ZSgpID8gJycgOiAnQmVhcmVyICd9JHt0aGlzLnVybH0gcHJvY2VzcyBwZW5kaW5nIHdoaWxlIGxvb3AgcmFuIHdpdGggJHt0aGlzLnBlbmRpbmcubGVuZ3RofS5gKVxuICAgICAgaWYgKCF0aGlzLmZpcnN0UmVxdWVzdCAmJiAhdGhpcy5pc1JlcXVlc3RBbGxvd2VkKCkpIHtcbiAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKVxuICAgICAgICBjb25zdCBmdXR1cmUgPSB0aGlzLmZyb3plbkF0ICsgdGhpcy5pbnRlcnZhbFxuICAgICAgICBhd2FpdCBkZWxheShmdXR1cmUgPiBub3cgPyBmdXR1cmUgLSBub3cgOiAxMDAwKVxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5wZW5kaW5nWzBdXG4gICAgICBpZiAocmVxdWVzdCkge1xuICAgICAgICBjb25zdCBiYXNpY1VSTCA9IHRoaXMucmVzdC5zaW1wbGlmeVVybChyZXF1ZXN0LnJvdXRlLCByZXF1ZXN0Lm1ldGhvZClcblxuICAgICAgICAvLyBJZiB0aGlzIHVybCBpcyBzdGlsbCByYXRlIGxpbWl0ZWQsIHRyeSBhZ2FpblxuICAgICAgICBjb25zdCB1cmxSZXNldEluID0gdGhpcy5yZXN0LmNoZWNrUmF0ZUxpbWl0cyhiYXNpY1VSTCwgcmVxdWVzdC5yZXF1ZXN0Qm9keU9wdGlvbnM/LmhlYWRlcnMpXG4gICAgICAgIGlmICh1cmxSZXNldEluKSBhd2FpdCBkZWxheSh1cmxSZXNldEluKVxuXG4gICAgICAgIC8vIElGIEEgQlVDS0VUIEVYSVNUUywgQ0hFQ0sgVEhFIEJVQ0tFVCdTIFJBVEUgTElNSVRTXG4gICAgICAgIGNvbnN0IGJ1Y2tldFJlc2V0SW4gPSByZXF1ZXN0LmJ1Y2tldElkID8gdGhpcy5yZXN0LmNoZWNrUmF0ZUxpbWl0cyhyZXF1ZXN0LmJ1Y2tldElkLCByZXF1ZXN0LnJlcXVlc3RCb2R5T3B0aW9ucz8uaGVhZGVycykgOiBmYWxzZVxuICAgICAgICBpZiAoYnVja2V0UmVzZXRJbikgYXdhaXQgZGVsYXkoYnVja2V0UmVzZXRJbilcblxuICAgICAgICB0aGlzLmZpcnN0UmVxdWVzdCA9IGZhbHNlXG4gICAgICAgIHRoaXMucmVtYWluaW5nLS1cblxuICAgICAgICBpZiAodGhpcy50aW1lb3V0SWQgJiYgdGhpcy5yZW1haW5pbmcgPT09IDAgJiYgdGhpcy5pbnRlcnZhbCAhPT0gMCkge1xuICAgICAgICAgIHRoaXMudGltZW91dElkID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnJlbWFpbmluZyA9IHRoaXMubWF4XG4gICAgICAgICAgICB0aGlzLnRpbWVvdXRJZCA9IHVuZGVmaW5lZFxuICAgICAgICAgIH0sIHRoaXMuaW50ZXJ2YWwpXG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZW1vdmUgZnJvbSBxdWV1ZSwgd2UgYXJlIGV4ZWN1dGluZyBpdC5cbiAgICAgICAgdGhpcy5wZW5kaW5nLnNoaWZ0KClcbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhpcyByZXF1ZXN0IGlzIGFibGUgdG8gYmUgbWFkZSBnbG9iYWxseVxuICAgICAgICBhd2FpdCB0aGlzLnJlc3QuaW52YWxpZEJ1Y2tldC53YWl0VW50aWxSZXF1ZXN0QXZhaWxhYmxlKClcblxuICAgICAgICBhd2FpdCB0aGlzLnJlc3RcbiAgICAgICAgICAuc2VuZFJlcXVlc3QocmVxdWVzdClcbiAgICAgICAgICAvLyBTaG91bGQgYmUgaGFuZGxlZCBpbiBzZW5kUmVxdWVzdCwgdGhpcyBjYXRjaCBqdXN0IHByZXZlbnRzIGJvdHMgZnJvbSBkeWluZ1xuICAgICAgICAgIC5jYXRjaCgoKSA9PiBudWxsKVxuICAgICAgfVxuICAgIH1cblxuICAgIGxvZ2dlci5kZWJ1ZyhgUXVldWUgJHt0aGlzLmlzT2F1dGgyUXVldWUoKSA/ICcnIDogJ0JlYXJlciAnfSR7dGhpcy51cmx9IHByb2Nlc3MgcGVuZGluZyB3aGlsZSBsb29wIGV4aXRlZCB3aXRoICR7dGhpcy5wZW5kaW5nLmxlbmd0aH0uYClcblxuICAgIC8vIE1hcmsgYXMgZmFsc2Ugc28gbmV4dCBwZW5kaW5nIHJlcXVlc3QgY2FuIGJlIHRyaWdnZXJlZCBieSBuZXcgbG9vcC5cbiAgICB0aGlzLnByb2Nlc3NpbmdQZW5kaW5nID0gZmFsc2VcbiAgICB0aGlzLmNsZWFudXAoKVxuICB9XG5cbiAgaGFuZGxlQ29tcGxldGVkUmVxdWVzdChoZWFkZXJzOiB7IG1heD86IG51bWJlcjsgaW50ZXJ2YWw/OiBudW1iZXI7IHJlbWFpbmluZz86IG51bWJlciB9KTogdm9pZCB7XG4gICAgaWYgKGhlYWRlcnMubWF4ID09PSAwKSB7XG4gICAgICB0aGlzLnJlbWFpbmluZysrXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuZnJvemVuQXQpIHRoaXMuZnJvemVuQXQgPSBEYXRlLm5vdygpXG4gICAgaWYgKGhlYWRlcnMuaW50ZXJ2YWwgIT09IHVuZGVmaW5lZCkgdGhpcy5pbnRlcnZhbCA9IGhlYWRlcnMuaW50ZXJ2YWxcbiAgICBpZiAoaGVhZGVycy5yZW1haW5pbmcgIT09IHVuZGVmaW5lZCkgdGhpcy5yZW1haW5pbmcgPSBoZWFkZXJzLnJlbWFpbmluZ1xuXG4gICAgaWYgKHRoaXMucmVtYWluaW5nIDw9IDEpIHtcbiAgICAgIHRoaXMudGltZW91dElkID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHRoaXMucmVtYWluaW5nID0gdGhpcy5tYXhcbiAgICAgICAgdGhpcy50aW1lb3V0SWQgPSB1bmRlZmluZWRcbiAgICAgIH0sIGhlYWRlcnMuaW50ZXJ2YWwpXG4gICAgfVxuICB9XG5cbiAgLyoqIENoZWNrcyBpZiBhIHJlcXVlc3QgaXMgYXZhaWxhYmxlIGFuZCBhZGRzIGl0IHRvIHRoZSBxdWV1ZS4gQWxzbyB0cmlnZ2VycyBxdWV1ZSBwcm9jZXNzaW5nIGlmIG5vdCBhbHJlYWR5IHByb2Nlc3NpbmcuICovXG4gIGFzeW5jIG1ha2VSZXF1ZXN0KG9wdGlvbnM6IFNlbmRSZXF1ZXN0T3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMud2FpdFVudGlsUmVxdWVzdEF2YWlsYWJsZSgpXG4gICAgdGhpcy5wZW5kaW5nLnB1c2gob3B0aW9ucylcbiAgICB0aGlzLnByb2Nlc3NQZW5kaW5nKClcbiAgfVxuXG4gIC8qKiBDbGVhbnMgdXAgdGhlIHF1ZXVlIGJ5IGNoZWNraW5nIGlmIHRoZXJlIGlzIG5vdGhpbmcgbGVmdCBhbmQgcmVtb3ZpbmcgaXQuICovXG4gIGNsZWFudXAoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlzUXVldWVDbGVhcmFibGUoKSkge1xuICAgICAgdGhpcy5wcm9jZXNzUGVuZGluZygpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoYFtRdWV1ZV0gJHt0aGlzLmlzT2F1dGgyUXVldWUoKSA/ICcnIDogJ0JlYXJlciAnfSR7dGhpcy51cmx9LiBEZWxheWluZyBkZWxldGUgZm9yICR7dGhpcy5kZWxldGVRdWV1ZURlbGF5fW1zYClcbiAgICAvLyBEZWxldGUgaW4gYSBtaW51dGUgZ2l2aW5nIGEgYml0IG9mIHRpbWUgdG8gYWxsb3cgbmV3IHJlcXVlc3RzIHRoYXQgbWF5IHJldXNlIHRoaXMgcXVldWVcbiAgICBzZXRUaW1lb3V0KGFzeW5jICgpID0+IHtcbiAgICAgIGlmICghdGhpcy5pc1F1ZXVlQ2xlYXJhYmxlKCkpIHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKGBbUXVldWVdICR7dGhpcy5pc09hdXRoMlF1ZXVlKCkgPyAnJyA6ICdCZWFyZXIgJ30ke3RoaXMudXJsfS4gaXMgbm90IGNsZWFyYWJsZS4gUmVzdGFydGluZyBwcm9jZXNzaW5nIG9mIHF1ZXVlLmApXG4gICAgICAgIHRoaXMucHJvY2Vzc1BlbmRpbmcoKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgbG9nZ2VyLmRlYnVnKGBbUXVldWVdICR7dGhpcy51cmx9LiBEZWxldGluZ2ApXG4gICAgICBpZiAodGhpcy50aW1lb3V0SWQpIGNsZWFyVGltZW91dCh0aGlzLnRpbWVvdXRJZClcbiAgICAgIC8vIE5vIHJlcXVlc3RzIGhhdmUgYmVlbiByZXF1ZXN0ZWQgZm9yIHRoaXMgcXVldWUgc28gd2UgbnVrZSB0aGlzIHF1ZXVlXG4gICAgICB0aGlzLnJlc3QucXVldWVzLmRlbGV0ZShgJHt0aGlzLmF1dGhlbnRpY2F0aW9ufSR7dGhpcy51cmx9YClcbiAgICAgIGxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgYFtRdWV1ZV0gJHt0aGlzLnVybH0uIERlbGV0ZWQhIFJlbWFpbmluZzogKCR7dGhpcy5yZXN0LnF1ZXVlcy5zaXplfSlgLFxuICAgICAgICBbLi4udGhpcy5yZXN0LnF1ZXVlcy52YWx1ZXMoKV0ubWFwKChxdWV1ZSkgPT4gYCR7cXVldWUuaXNPYXV0aDJRdWV1ZSgpID8gJycgOiAnQmVhcmVyICd9JHtxdWV1ZS51cmx9YCksXG4gICAgICApXG4gICAgICBpZiAodGhpcy5yZXN0LnF1ZXVlcy5zaXplKSB0aGlzLnByb2Nlc3NQZW5kaW5nKClcbiAgICB9LCB0aGlzLmRlbGV0ZVF1ZXVlRGVsYXkpXG4gIH1cblxuICAvKiogU2ltcGx5IGNoZWNrcyBpZiB0aGUgcXVldWUgaXMgYWJsZSB0byBiZSBjbGVhcmVkIG9yIGl0IGhhcyByZXF1ZXN0cyBwZW5kaW5nLiAqL1xuICBpc1F1ZXVlQ2xlYXJhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmZpcnN0UmVxdWVzdCkgcmV0dXJuIGZhbHNlXG4gICAgaWYgKHRoaXMud2FpdGluZy5sZW5ndGggPiAwKSByZXR1cm4gZmFsc2VcbiAgICBpZiAodGhpcy5wZW5kaW5nLmxlbmd0aCA+IDApIHJldHVybiBmYWxzZVxuICAgIGlmICh0aGlzLmludGVydmFsID09PSAwKSByZXR1cm4gZmFsc2VcbiAgICBpZiAodGhpcy5wcm9jZXNzaW5nKSByZXR1cm4gZmFsc2VcbiAgICBpZiAodGhpcy5wcm9jZXNzaW5nUGVuZGluZykgcmV0dXJuIGZhbHNlXG5cbiAgICByZXR1cm4gdHJ1ZVxuICB9XG5cbiAgaXNPYXV0aDJRdWV1ZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5hdXRoZW50aWNhdGlvbiA9PT0gJydcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFF1ZXVlT3B0aW9ucyB7XG4gIC8qKiBIb3cgbWFueSByZXF1ZXN0cyBhcmUgcmVtYWluaW5nLiBEZWZhdWx0cyB0byAxICovXG4gIHJlbWFpbmluZz86IG51bWJlclxuICAvKiogTWF4IG51bWJlciBvZiByZXF1ZXN0cyBhbGxvd2VkIGluIHRoaXMgdGhpcy4gRGVmYXVsdHMgdG8gMS4gKi9cbiAgbWF4PzogbnVtYmVyXG4gIC8qKiBUaGUgdGltZSBpbiBtaWxsaXNlY29uZHMgdGhhdCBkaXNjb3JkIGFsbG93cyB0byBtYWtlIHRoZSBtYXggbnVtYmVyIG9mIGludmFsaWQgcmVxdWVzdHMuIERlZmF1bHRzIHRvIDAgKi9cbiAgaW50ZXJ2YWw/OiBudW1iZXJcbiAgLyoqIHRpbWVyIHRvIHJlc2V0IHRvIDAgKi9cbiAgdGltZW91dElkPzogTm9kZUpTLlRpbWVvdXRcbiAgLyoqIFRoZSB1cmwgdGhpcyBxdWV1ZSB3aWxsIGJlIGhhbmRsaW5nLiAqL1xuICB1cmw6IHN0cmluZ1xuICAvKiogVGhlIHRpbWUgaW4gbWlsbGlzZWNvbmRzIHRvIHdhaXQgYmVmb3JlIGRlbGV0aW5nIHRoaXMgcXVldWUgaWYgaXQgaXMgZW1wdHkuIERlZmF1bHRzIHRvIDYwMDAwKG9uZSBtaW51dGUpLiAqL1xuICBkZWxldGVRdWV1ZURlbGF5PzogbnVtYmVyXG4gIC8qKiBBdXRoZW50aWNhdGlvbiB1c2VkIGZvciB0aGUgcmVxdWVzdC4gSW4gbm9uLU9BdXRoMiBzaXR1YXRpb25zIHNob3VsZCBiZSBhbiBlbXB0eSBzdHJpbmcuIERlZmF1bHRzIHRvIGFuIGVtcHR5IHN0cmluZyAqL1xuICBhdXRoZW50aWNhdGlvbj86IHN0cmluZ1xufVxuIl0sIm5hbWVzIjpbIlF1ZXVlIiwiY29uc3RydWN0b3IiLCJyZXN0Iiwib3B0aW9ucyIsInJlbWFpbmluZyIsIm1heCIsImludGVydmFsIiwid2FpdGluZyIsInBlbmRpbmciLCJwcm9jZXNzaW5nIiwicHJvY2Vzc2luZ1BlbmRpbmciLCJmaXJzdFJlcXVlc3QiLCJmcm96ZW5BdCIsImRlbGV0ZVF1ZXVlRGVsYXkiLCJhdXRoZW50aWNhdGlvbiIsInVybCIsInRpbWVvdXRJZCIsImlzUmVxdWVzdEFsbG93ZWQiLCJ3YWl0VW50aWxSZXF1ZXN0QXZhaWxhYmxlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJwdXNoIiwicHJvY2Vzc1dhaXRpbmciLCJsZW5ndGgiLCJsb2dnZXIiLCJkZWJ1ZyIsImlzT2F1dGgyUXVldWUiLCJzaGlmdCIsImRlbGF5IiwicHJvY2Vzc1BlbmRpbmciLCJub3ciLCJEYXRlIiwiZnV0dXJlIiwicmVxdWVzdCIsImJhc2ljVVJMIiwic2ltcGxpZnlVcmwiLCJyb3V0ZSIsIm1ldGhvZCIsInVybFJlc2V0SW4iLCJjaGVja1JhdGVMaW1pdHMiLCJyZXF1ZXN0Qm9keU9wdGlvbnMiLCJoZWFkZXJzIiwiYnVja2V0UmVzZXRJbiIsImJ1Y2tldElkIiwic2V0VGltZW91dCIsInVuZGVmaW5lZCIsImludmFsaWRCdWNrZXQiLCJzZW5kUmVxdWVzdCIsImNhdGNoIiwiY2xlYW51cCIsImhhbmRsZUNvbXBsZXRlZFJlcXVlc3QiLCJtYWtlUmVxdWVzdCIsImlzUXVldWVDbGVhcmFibGUiLCJjbGVhclRpbWVvdXQiLCJxdWV1ZXMiLCJkZWxldGUiLCJzaXplIiwidmFsdWVzIiwibWFwIiwicXVldWUiXSwibWFwcGluZ3MiOiI7Ozs7K0JBR2FBOzthQUFBQTs7dUJBSGlCO0FBR3ZCLElBQUEsQUFBTUEsUUFBTixNQUFNQTtJQThCWEMsWUFBWUMsSUFBaUIsRUFBRUMsT0FBcUIsQ0FBRTtRQTNCdEQsK0RBQStELFFBQy9EQyxZQUFvQjtRQUNwQiwrQ0FBK0MsUUFDL0NDLE1BQWM7UUFDZCxtRkFBbUYsUUFDbkZDLFdBQW1CO1FBR25CLDZDQUE2QyxRQUM3Q0MsVUFBNEQsRUFBRTtRQUM5RCw2Q0FBNkMsUUFDN0NDLFVBQWdDLEVBQUU7UUFDbEMsNERBQTRELFFBQzVEQyxhQUFzQixLQUFLO1FBQzNCLDREQUE0RCxRQUM1REMsb0JBQTZCLEtBQUs7UUFDbEMsMENBQTBDLFFBQzFDQyxlQUF3QixLQUFLO1FBRzdCLG1GQUFtRixRQUNuRkMsV0FBbUI7UUFDbkIsK0dBQStHLFFBQy9HQyxtQkFBMkI7UUFDM0IsK0dBQStHLFFBQy9HQyxpQkFBeUI7UUFHdkIsSUFBSSxDQUFDWixJQUFJLEdBQUdBO1FBQ1osSUFBSSxDQUFDYSxHQUFHLEdBQUdaLFFBQVFZLEdBQUc7UUFFdEIsSUFBSVosUUFBUUcsUUFBUSxFQUFFLElBQUksQ0FBQ0EsUUFBUSxHQUFHSCxRQUFRRyxRQUFRO1FBQ3RELElBQUlILFFBQVFFLEdBQUcsRUFBRSxJQUFJLENBQUNBLEdBQUcsR0FBR0YsUUFBUUUsR0FBRztRQUN2QyxJQUFJRixRQUFRQyxTQUFTLEVBQUUsSUFBSSxDQUFDQSxTQUFTLEdBQUdELFFBQVFDLFNBQVM7UUFDekQsSUFBSUQsUUFBUWEsU0FBUyxFQUFFLElBQUksQ0FBQ0EsU0FBUyxHQUFHYixRQUFRYSxTQUFTO1FBQ3pELElBQUliLFFBQVFVLGdCQUFnQixFQUFFLElBQUksQ0FBQ0EsZ0JBQWdCLEdBQUdWLFFBQVFVLGdCQUFnQjtRQUM5RSxJQUFJVixRQUFRVyxjQUFjLEVBQUUsSUFBSSxDQUFDQSxjQUFjLEdBQUdYLFFBQVFXLGNBQWM7SUFDMUU7SUFFQSwrREFBK0QsR0FDL0RHLG1CQUE0QjtRQUMxQixPQUFPLElBQUksQ0FBQ2IsU0FBUyxHQUFHO0lBQzFCO0lBRUEsZ0VBQWdFLEdBQ2hFLE1BQU1jLDRCQUEyQztRQUMvQyxxREFBcUQ7UUFDckQsT0FBTyxNQUFNLElBQUlDLFFBQVEsT0FBT0MsVUFBWTtZQUMxQywyRkFBMkY7WUFDM0YsSUFBSSxJQUFJLENBQUNILGdCQUFnQixJQUFJO2dCQUMzQixvQkFBb0I7Z0JBQ3BCRztZQUNGLE9BQU87Z0JBQ0wsSUFBSSxDQUFDYixPQUFPLENBQUNjLElBQUksQ0FBQ0Q7Z0JBQ2xCLE1BQU0sSUFBSSxDQUFDRSxjQUFjO1lBQzNCLENBQUM7UUFDSDtJQUNGO0lBRUEseURBQXlELEdBQ3pELE1BQU1BLGlCQUFnQztRQUNwQyxxRUFBcUU7UUFDckUsSUFBSSxJQUFJLENBQUNiLFVBQVUsRUFBRTtRQUNyQixnREFBZ0Q7UUFDaEQsSUFBSSxDQUFDQSxVQUFVLEdBQUcsSUFBSTtRQUV0QixNQUFPLElBQUksQ0FBQ0YsT0FBTyxDQUFDZ0IsTUFBTSxHQUFHLEVBQUc7WUFDOUJDLGFBQU0sQ0FBQ0MsS0FBSyxDQUFDLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQ0MsYUFBYSxLQUFLLEtBQUssU0FBUyxDQUFDLEVBQUUsSUFBSSxDQUFDWCxHQUFHLENBQUMsZ0NBQWdDLENBQUM7WUFDMUcsSUFBSSxJQUFJLENBQUNFLGdCQUFnQixJQUFJO2dCQUMzQixxQ0FBcUM7Z0JBQ3JDLElBQUksQ0FBQ1YsT0FBTyxDQUFDb0IsS0FBSztZQUNwQixPQUFPO2dCQUNMLE1BQU1DLElBQUFBLFlBQUssRUFBQztZQUNkLENBQUM7UUFDSDtRQUVBLHNFQUFzRTtRQUN0RSxJQUFJLENBQUNuQixVQUFVLEdBQUcsS0FBSztJQUN6QjtJQUVBLDBEQUEwRCxHQUMxRCxNQUFNb0IsaUJBQWdDO1FBQ3BDLHFFQUFxRTtRQUNyRSxJQUFJLElBQUksQ0FBQ25CLGlCQUFpQixJQUFJLENBQUMsSUFBSSxDQUFDRixPQUFPLENBQUNlLE1BQU0sRUFBRTtRQUVwRCxnREFBZ0Q7UUFDaEQsSUFBSSxDQUFDYixpQkFBaUIsR0FBRyxJQUFJO1FBRTdCLE1BQU8sSUFBSSxDQUFDRixPQUFPLENBQUNlLE1BQU0sR0FBRyxFQUFHO1lBQzlCQyxhQUFNLENBQUNDLEtBQUssQ0FBQyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUNDLGFBQWEsS0FBSyxLQUFLLFNBQVMsQ0FBQyxFQUFFLElBQUksQ0FBQ1gsR0FBRyxDQUFDLHFDQUFxQyxFQUFFLElBQUksQ0FBQ1AsT0FBTyxDQUFDZSxNQUFNLENBQUMsQ0FBQyxDQUFDO1lBQ3BJLElBQUksQ0FBQyxJQUFJLENBQUNaLFlBQVksSUFBSSxDQUFDLElBQUksQ0FBQ00sZ0JBQWdCLElBQUk7Z0JBQ2xELE1BQU1hLE1BQU1DLEtBQUtELEdBQUc7Z0JBQ3BCLE1BQU1FLFNBQVMsSUFBSSxDQUFDcEIsUUFBUSxHQUFHLElBQUksQ0FBQ04sUUFBUTtnQkFDNUMsTUFBTXNCLElBQUFBLFlBQUssRUFBQ0ksU0FBU0YsTUFBTUUsU0FBU0YsTUFBTSxJQUFJO2dCQUM5QyxRQUFRO1lBQ1YsQ0FBQztZQUVELE1BQU1HLFVBQVUsSUFBSSxDQUFDekIsT0FBTyxDQUFDLEVBQUU7WUFDL0IsSUFBSXlCLFNBQVM7Z0JBQ1gsTUFBTUMsV0FBVyxJQUFJLENBQUNoQyxJQUFJLENBQUNpQyxXQUFXLENBQUNGLFFBQVFHLEtBQUssRUFBRUgsUUFBUUksTUFBTTtnQkFFcEUsK0NBQStDO2dCQUMvQyxNQUFNQyxhQUFhLElBQUksQ0FBQ3BDLElBQUksQ0FBQ3FDLGVBQWUsQ0FBQ0wsVUFBVUQsUUFBUU8sa0JBQWtCLEVBQUVDO2dCQUNuRixJQUFJSCxZQUFZLE1BQU1WLElBQUFBLFlBQUssRUFBQ1U7Z0JBRTVCLHFEQUFxRDtnQkFDckQsTUFBTUksZ0JBQWdCVCxRQUFRVSxRQUFRLEdBQUcsSUFBSSxDQUFDekMsSUFBSSxDQUFDcUMsZUFBZSxDQUFDTixRQUFRVSxRQUFRLEVBQUVWLFFBQVFPLGtCQUFrQixFQUFFQyxXQUFXLEtBQUs7Z0JBQ2pJLElBQUlDLGVBQWUsTUFBTWQsSUFBQUEsWUFBSyxFQUFDYztnQkFFL0IsSUFBSSxDQUFDL0IsWUFBWSxHQUFHLEtBQUs7Z0JBQ3pCLElBQUksQ0FBQ1AsU0FBUztnQkFFZCxJQUFJLElBQUksQ0FBQ1ksU0FBUyxJQUFJLElBQUksQ0FBQ1osU0FBUyxLQUFLLEtBQUssSUFBSSxDQUFDRSxRQUFRLEtBQUssR0FBRztvQkFDakUsSUFBSSxDQUFDVSxTQUFTLEdBQUc0QixXQUFXLElBQU07d0JBQ2hDLElBQUksQ0FBQ3hDLFNBQVMsR0FBRyxJQUFJLENBQUNDLEdBQUc7d0JBQ3pCLElBQUksQ0FBQ1csU0FBUyxHQUFHNkI7b0JBQ25CLEdBQUcsSUFBSSxDQUFDdkMsUUFBUTtnQkFDbEIsQ0FBQztnQkFFRCwwQ0FBMEM7Z0JBQzFDLElBQUksQ0FBQ0UsT0FBTyxDQUFDbUIsS0FBSztnQkFDbEIsb0RBQW9EO2dCQUNwRCxNQUFNLElBQUksQ0FBQ3pCLElBQUksQ0FBQzRDLGFBQWEsQ0FBQzVCLHlCQUF5QjtnQkFFdkQsTUFBTSxJQUFJLENBQUNoQixJQUFJLENBQ1o2QyxXQUFXLENBQUNkLFFBQ2IsNkVBQTZFO2lCQUM1RWUsS0FBSyxDQUFDLElBQU0sSUFBSTtZQUNyQixDQUFDO1FBQ0g7UUFFQXhCLGFBQU0sQ0FBQ0MsS0FBSyxDQUFDLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQ0MsYUFBYSxLQUFLLEtBQUssU0FBUyxDQUFDLEVBQUUsSUFBSSxDQUFDWCxHQUFHLENBQUMsd0NBQXdDLEVBQUUsSUFBSSxDQUFDUCxPQUFPLENBQUNlLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFFdkksc0VBQXNFO1FBQ3RFLElBQUksQ0FBQ2IsaUJBQWlCLEdBQUcsS0FBSztRQUM5QixJQUFJLENBQUN1QyxPQUFPO0lBQ2Q7SUFFQUMsdUJBQXVCVCxPQUFnRSxFQUFRO1FBQzdGLElBQUlBLFFBQVFwQyxHQUFHLEtBQUssR0FBRztZQUNyQixJQUFJLENBQUNELFNBQVM7WUFDZDtRQUNGLENBQUM7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDUSxRQUFRLEVBQUUsSUFBSSxDQUFDQSxRQUFRLEdBQUdtQixLQUFLRCxHQUFHO1FBQzVDLElBQUlXLFFBQVFuQyxRQUFRLEtBQUt1QyxXQUFXLElBQUksQ0FBQ3ZDLFFBQVEsR0FBR21DLFFBQVFuQyxRQUFRO1FBQ3BFLElBQUltQyxRQUFRckMsU0FBUyxLQUFLeUMsV0FBVyxJQUFJLENBQUN6QyxTQUFTLEdBQUdxQyxRQUFRckMsU0FBUztRQUV2RSxJQUFJLElBQUksQ0FBQ0EsU0FBUyxJQUFJLEdBQUc7WUFDdkIsSUFBSSxDQUFDWSxTQUFTLEdBQUc0QixXQUFXLElBQU07Z0JBQ2hDLElBQUksQ0FBQ3hDLFNBQVMsR0FBRyxJQUFJLENBQUNDLEdBQUc7Z0JBQ3pCLElBQUksQ0FBQ1csU0FBUyxHQUFHNkI7WUFDbkIsR0FBR0osUUFBUW5DLFFBQVE7UUFDckIsQ0FBQztJQUNIO0lBRUEseUhBQXlILEdBQ3pILE1BQU02QyxZQUFZaEQsT0FBMkIsRUFBaUI7UUFDNUQsTUFBTSxJQUFJLENBQUNlLHlCQUF5QjtRQUNwQyxJQUFJLENBQUNWLE9BQU8sQ0FBQ2EsSUFBSSxDQUFDbEI7UUFDbEIsSUFBSSxDQUFDMEIsY0FBYztJQUNyQjtJQUVBLDhFQUE4RSxHQUM5RW9CLFVBQWdCO1FBQ2QsSUFBSSxDQUFDLElBQUksQ0FBQ0csZ0JBQWdCLElBQUk7WUFDNUIsSUFBSSxDQUFDdkIsY0FBYztZQUNuQjtRQUNGLENBQUM7UUFFREwsYUFBTSxDQUFDQyxLQUFLLENBQUMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDQyxhQUFhLEtBQUssS0FBSyxTQUFTLENBQUMsRUFBRSxJQUFJLENBQUNYLEdBQUcsQ0FBQyxzQkFBc0IsRUFBRSxJQUFJLENBQUNGLGdCQUFnQixDQUFDLEVBQUUsQ0FBQztRQUMxSCwwRkFBMEY7UUFDMUYrQixXQUFXLFVBQVk7WUFDckIsSUFBSSxDQUFDLElBQUksQ0FBQ1EsZ0JBQWdCLElBQUk7Z0JBQzVCNUIsYUFBTSxDQUFDQyxLQUFLLENBQUMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDQyxhQUFhLEtBQUssS0FBSyxTQUFTLENBQUMsRUFBRSxJQUFJLENBQUNYLEdBQUcsQ0FBQyxtREFBbUQsQ0FBQztnQkFDN0gsSUFBSSxDQUFDYyxjQUFjO2dCQUNuQjtZQUNGLENBQUM7WUFFREwsYUFBTSxDQUFDQyxLQUFLLENBQUMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDVixHQUFHLENBQUMsVUFBVSxDQUFDO1lBQzVDLElBQUksSUFBSSxDQUFDQyxTQUFTLEVBQUVxQyxhQUFhLElBQUksQ0FBQ3JDLFNBQVM7WUFDL0MsdUVBQXVFO1lBQ3ZFLElBQUksQ0FBQ2QsSUFBSSxDQUFDb0QsTUFBTSxDQUFDQyxNQUFNLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQ3pDLGNBQWMsQ0FBQyxFQUFFLElBQUksQ0FBQ0MsR0FBRyxDQUFDLENBQUM7WUFDM0RTLGFBQU0sQ0FBQ0MsS0FBSyxDQUNWLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQ1YsR0FBRyxDQUFDLHVCQUF1QixFQUFFLElBQUksQ0FBQ2IsSUFBSSxDQUFDb0QsTUFBTSxDQUFDRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQ3JFO21CQUFJLElBQUksQ0FBQ3RELElBQUksQ0FBQ29ELE1BQU0sQ0FBQ0csTUFBTTthQUFHLENBQUNDLEdBQUcsQ0FBQyxDQUFDQyxRQUFVLENBQUMsRUFBRUEsTUFBTWpDLGFBQWEsS0FBSyxLQUFLLFNBQVMsQ0FBQyxFQUFFaUMsTUFBTTVDLEdBQUcsQ0FBQyxDQUFDO1lBRXZHLElBQUksSUFBSSxDQUFDYixJQUFJLENBQUNvRCxNQUFNLENBQUNFLElBQUksRUFBRSxJQUFJLENBQUMzQixjQUFjO1FBQ2hELEdBQUcsSUFBSSxDQUFDaEIsZ0JBQWdCO0lBQzFCO0lBRUEsaUZBQWlGLEdBQ2pGdUMsbUJBQTRCO1FBQzFCLElBQUksSUFBSSxDQUFDekMsWUFBWSxFQUFFLE9BQU8sS0FBSztRQUNuQyxJQUFJLElBQUksQ0FBQ0osT0FBTyxDQUFDZ0IsTUFBTSxHQUFHLEdBQUcsT0FBTyxLQUFLO1FBQ3pDLElBQUksSUFBSSxDQUFDZixPQUFPLENBQUNlLE1BQU0sR0FBRyxHQUFHLE9BQU8sS0FBSztRQUN6QyxJQUFJLElBQUksQ0FBQ2pCLFFBQVEsS0FBSyxHQUFHLE9BQU8sS0FBSztRQUNyQyxJQUFJLElBQUksQ0FBQ0csVUFBVSxFQUFFLE9BQU8sS0FBSztRQUNqQyxJQUFJLElBQUksQ0FBQ0MsaUJBQWlCLEVBQUUsT0FBTyxLQUFLO1FBRXhDLE9BQU8sSUFBSTtJQUNiO0lBRUFnQixnQkFBeUI7UUFDdkIsT0FBTyxJQUFJLENBQUNaLGNBQWMsS0FBSztJQUNqQztBQUNGIn0=
|