@discordeno/rest 19.0.0-next.85ea2d9 → 19.0.0-next.87f62d2

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 (51) hide show
  1. package/README.md +15 -1
  2. package/dist/cjs/index.cjs +25 -0
  3. package/dist/cjs/invalidBucket.cjs +86 -0
  4. package/dist/cjs/manager.cjs +1445 -0
  5. package/dist/cjs/queue.cjs +165 -0
  6. package/dist/cjs/routes.cjs +550 -0
  7. package/dist/cjs/types.cjs +6 -0
  8. package/dist/cjs/typings/routes.cjs +6 -0
  9. package/dist/esm/index.js +8 -0
  10. package/dist/esm/invalidBucket.js +82 -0
  11. package/dist/esm/manager.js +1403 -0
  12. package/dist/esm/queue.js +155 -0
  13. package/dist/esm/routes.js +540 -0
  14. package/dist/esm/types.js +3 -0
  15. package/dist/esm/typings/routes.js +3 -0
  16. package/dist/types/index.d.ts.map +1 -0
  17. package/dist/{invalidBucket.d.ts → types/invalidBucket.d.ts} +5 -0
  18. package/dist/types/invalidBucket.d.ts.map +1 -0
  19. package/dist/types/manager.d.ts.map +1 -0
  20. package/dist/{queue.d.ts → types/queue.d.ts} +12 -1
  21. package/dist/types/queue.d.ts.map +1 -0
  22. package/dist/types/routes.d.ts.map +1 -0
  23. package/dist/{types.d.ts → types/types.d.ts} +449 -110
  24. package/dist/types/types.d.ts.map +1 -0
  25. package/dist/{typings → types/typings}/routes.d.ts +46 -5
  26. package/dist/types/typings/routes.d.ts.map +1 -0
  27. package/package.json +32 -28
  28. package/dist/index.d.ts.map +0 -1
  29. package/dist/index.js +0 -8
  30. package/dist/index.js.map +0 -1
  31. package/dist/invalidBucket.d.ts.map +0 -1
  32. package/dist/invalidBucket.js +0 -82
  33. package/dist/invalidBucket.js.map +0 -1
  34. package/dist/manager.d.ts.map +0 -1
  35. package/dist/manager.js +0 -1102
  36. package/dist/manager.js.map +0 -1
  37. package/dist/queue.d.ts.map +0 -1
  38. package/dist/queue.js +0 -153
  39. package/dist/queue.js.map +0 -1
  40. package/dist/routes.d.ts.map +0 -1
  41. package/dist/routes.js +0 -487
  42. package/dist/routes.js.map +0 -1
  43. package/dist/types.d.ts.map +0 -1
  44. package/dist/types.js +0 -3
  45. package/dist/types.js.map +0 -1
  46. package/dist/typings/routes.d.ts.map +0 -1
  47. package/dist/typings/routes.js +0 -3
  48. package/dist/typings/routes.js.map +0 -1
  49. /package/dist/{index.d.ts → types/index.d.ts} +0 -0
  50. /package/dist/{manager.d.ts → types/manager.d.ts} +0 -0
  51. /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: function() {
8
+ return Queue;
9
+ }
10
+ });
11
+ const _utils = require("@discordeno/utils");
12
+ let Queue = class Queue {
13
+ constructor(rest, options){
14
+ /** Amount of requests that have are remaining. Defaults to 1. */ this.remaining = 1;
15
+ /** Max requests for this this. Defaults to 1. */ this.max = 1;
16
+ /** The time that discord allows to make the max number of requests. Defaults to 0 */ this.interval = 0;
17
+ /** The requests that are currently pending. */ this.waiting = [];
18
+ /** The requests that are currently pending. */ this.pending = [];
19
+ /** Whether or not the waiting queue is already processing. */ this.processing = false;
20
+ /** Whether or not the pending queue is already processing. */ this.processingPending = false;
21
+ /** Whether the first request is pending. */ this.firstRequest = false;
22
+ /** When requests started being made to determine when the interval will reset it. */ this.frozenAt = 0;
23
+ /** The time in milliseconds to wait before deleting this queue if it is empty. Defaults to 60000(one minute). */ this.deleteQueueDelay = 60000;
24
+ this.rest = rest;
25
+ this.url = options.url;
26
+ this.requestAuthorization = options.requestAuthorization;
27
+ if (options.interval) this.interval = options.interval;
28
+ if (options.max) this.max = options.max;
29
+ if (options.remaining) this.remaining = options.remaining;
30
+ if (options.timeoutId) this.timeoutId = options.timeoutId;
31
+ if (options.deleteQueueDelay) this.deleteQueueDelay = options.deleteQueueDelay;
32
+ }
33
+ /** Check if there is any remaining requests that are allowed. */ isRequestAllowed() {
34
+ return this.remaining > 0;
35
+ }
36
+ /** Pauses the execution until a request is allowed to be made. */ async waitUntilRequestAvailable() {
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
+ this.rest.logger.debug(`[Queue] ${this.getQueueType()} ${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
+ this.rest.logger.debug(`Queue ${this.getQueueType()} ${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, this.requestAuthorization);
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, this.requestAuthorization) : false;
86
+ if (bucketResetIn) await (0, _utils.delay)(bucketResetIn);
87
+ this.firstRequest = false;
88
+ this.remaining--;
89
+ if (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
+ if (request.requestBodyOptions?.headers?.authorization) request.requestBodyOptions.headers.authorization = this.requestAuthorization;
100
+ await this.rest.sendRequest(request)// Should be handled in sendRequest, this catch just prevents bots from dying
101
+ .catch(()=>null);
102
+ }
103
+ }
104
+ this.rest.logger.debug(`Queue ${this.getQueueType()} ${this.url} process pending while loop exited with ${this.pending.length}.`);
105
+ // Mark as false so next pending request can be triggered by new loop.
106
+ this.processingPending = false;
107
+ this.cleanup();
108
+ }
109
+ handleCompletedRequest(headers) {
110
+ if (headers.max === 0) {
111
+ this.remaining++;
112
+ return;
113
+ }
114
+ if (!this.frozenAt) this.frozenAt = Date.now();
115
+ if (headers.interval !== undefined) this.interval = headers.interval;
116
+ if (headers.remaining !== undefined) this.remaining = headers.remaining;
117
+ if (this.remaining <= 1) {
118
+ this.timeoutId ??= setTimeout(()=>{
119
+ this.remaining = this.max;
120
+ this.timeoutId = undefined;
121
+ }, headers.interval);
122
+ }
123
+ }
124
+ /** Checks if a request is available and adds it to the queue. Also triggers queue processing if not already processing. */ async makeRequest(options) {
125
+ await this.waitUntilRequestAvailable();
126
+ this.pending.push(options);
127
+ this.processPending();
128
+ }
129
+ /** Cleans up the queue by checking if there is nothing left and removing it. */ cleanup() {
130
+ if (!this.isQueueClearable()) {
131
+ this.processPending();
132
+ return;
133
+ }
134
+ this.rest.logger.debug(`[Queue] ${this.getQueueType()} ${this.url}. Delaying delete for ${this.deleteQueueDelay}ms`);
135
+ // Delete in a minute giving a bit of time to allow new requests that may reuse this queue
136
+ clearTimeout(this.deleteQueueTimeout);
137
+ this.deleteQueueTimeout = setTimeout(()=>{
138
+ if (!this.isQueueClearable()) {
139
+ this.rest.logger.debug(`[Queue] ${this.getQueueType()} ${this.url}. is not clearable. Restarting processing of queue.`);
140
+ this.processPending();
141
+ return;
142
+ }
143
+ this.rest.logger.debug(`[Queue] ${this.getQueueType()} ${this.url}. Deleting`);
144
+ if (this.timeoutId) clearTimeout(this.timeoutId);
145
+ // No requests have been requested for this queue so we nuke this queue
146
+ this.rest.queues.delete(`${this.requestAuthorization}${this.url}`);
147
+ this.rest.logger.debug(`[Queue] ${this.getQueueType()} ${this.url}. Deleted! Remaining: (${this.rest.queues.size})`, [
148
+ ...this.rest.queues.values()
149
+ ].map((queue)=>`${queue.getQueueType()}${queue.url}`));
150
+ }, this.deleteQueueDelay);
151
+ }
152
+ /** Simply checks if the queue is able to be cleared or it has requests pending. */ isQueueClearable() {
153
+ if (this.firstRequest) return false;
154
+ if (this.waiting.length > 0) return false;
155
+ if (this.pending.length > 0) return false;
156
+ if (this.processing) return false;
157
+ if (this.processingPending) return false;
158
+ return true;
159
+ }
160
+ getQueueType() {
161
+ return this.requestAuthorization.split(' ')[0];
162
+ }
163
+ };
164
+
165
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9xdWV1ZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBkZWxheSB9IGZyb20gJ0BkaXNjb3JkZW5vL3V0aWxzJ1xuaW1wb3J0IHR5cGUgeyBSZXN0TWFuYWdlciwgU2VuZFJlcXVlc3RPcHRpb25zIH0gZnJvbSAnLi90eXBlcy5qcydcblxuZXhwb3J0IGNsYXNzIFF1ZXVlIHtcbiAgLyoqIFRoZSByZXN0IG1hbmFnZXIgKi9cbiAgcmVzdDogUmVzdE1hbmFnZXJcbiAgLyoqIEFtb3VudCBvZiByZXF1ZXN0cyB0aGF0IGhhdmUgYXJlIHJlbWFpbmluZy4gRGVmYXVsdHMgdG8gMS4gKi9cbiAgcmVtYWluaW5nOiBudW1iZXIgPSAxXG4gIC8qKiBNYXggcmVxdWVzdHMgZm9yIHRoaXMgdGhpcy4gRGVmYXVsdHMgdG8gMS4gKi9cbiAgbWF4OiBudW1iZXIgPSAxXG4gIC8qKiBUaGUgdGltZSB0aGF0IGRpc2NvcmQgYWxsb3dzIHRvIG1ha2UgdGhlIG1heCBudW1iZXIgb2YgcmVxdWVzdHMuIERlZmF1bHRzIHRvIDAgKi9cbiAgaW50ZXJ2YWw6IG51bWJlciA9IDBcbiAgLyoqIHRpbWVyIHRvIHJlc2V0IHRvIDAgKi9cbiAgdGltZW91dElkOiBOb2RlSlMuVGltZW91dCB8IHVuZGVmaW5lZFxuICAvKiogVGhlIHJlcXVlc3RzIHRoYXQgYXJlIGN1cnJlbnRseSBwZW5kaW5nLiAqL1xuICB3YWl0aW5nOiBBcnJheTwodmFsdWU6IHZvaWQgfCBQcm9taXNlTGlrZTx2b2lkPikgPT4gdm9pZD4gPSBbXVxuICAvKiogVGhlIHJlcXVlc3RzIHRoYXQgYXJlIGN1cnJlbnRseSBwZW5kaW5nLiAqL1xuICBwZW5kaW5nOiBTZW5kUmVxdWVzdE9wdGlvbnNbXSA9IFtdXG4gIC8qKiBXaGV0aGVyIG9yIG5vdCB0aGUgd2FpdGluZyBxdWV1ZSBpcyBhbHJlYWR5IHByb2Nlc3NpbmcuICovXG4gIHByb2Nlc3Npbmc6IGJvb2xlYW4gPSBmYWxzZVxuICAvKiogV2hldGhlciBvciBub3QgdGhlIHBlbmRpbmcgcXVldWUgaXMgYWxyZWFkeSBwcm9jZXNzaW5nLiAqL1xuICBwcm9jZXNzaW5nUGVuZGluZzogYm9vbGVhbiA9IGZhbHNlXG4gIC8qKiBXaGV0aGVyIHRoZSBmaXJzdCByZXF1ZXN0IGlzIHBlbmRpbmcuICovXG4gIGZpcnN0UmVxdWVzdDogYm9vbGVhbiA9IGZhbHNlXG4gIC8qKiBUaGUgdXJsIHRoYXQgYWxsIHRoZSByZXF1ZXN0cyBpbiB0aGlzIHF1ZXVlIGFyZSBzZW50IHRvLiAqL1xuICB1cmw6IHN0cmluZ1xuICAvKiogV2hlbiByZXF1ZXN0cyBzdGFydGVkIGJlaW5nIG1hZGUgdG8gZGV0ZXJtaW5lIHdoZW4gdGhlIGludGVydmFsIHdpbGwgcmVzZXQgaXQuICovXG4gIGZyb3plbkF0OiBudW1iZXIgPSAwXG4gIC8qKiBUaGUgdGltZSBpbiBtaWxsaXNlY29uZHMgdG8gd2FpdCBiZWZvcmUgZGVsZXRpbmcgdGhpcyBxdWV1ZSBpZiBpdCBpcyBlbXB0eS4gRGVmYXVsdHMgdG8gNjAwMDAob25lIG1pbnV0ZSkuICovXG4gIGRlbGV0ZVF1ZXVlRGVsYXk6IG51bWJlciA9IDYwMDAwXG4gIC8qKiBUaGUgdGltZW91dCBmb3IgdGhlIGRlbGV0aW9uIG9mIHRoaXMgcXVldWUgKi9cbiAgZGVsZXRlUXVldWVUaW1lb3V0PzogTm9kZUpTLlRpbWVvdXRcbiAgLyoqXG4gICAqIFRoZSBhdXRob3JpemF0aW9uIGJlaW5nIHVzZWQgZm9yIHRoZSByZXF1ZXN0cyBpbiB0aGlzIHF1ZXVlXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIFRoaXMgaXMgYWxzbyB1c2VkIHRvIGdldCB0aGUga2V5IHRoaXMgcXVldWUgaXMgc3RvcmVkIGFzIGluIHRoZSBxdWV1ZSBtYXBwaW5nIG9mIHRoZSByZXN0IG1hbmFnZXJcbiAgICovXG4gIHJlcXVlc3RBdXRob3JpemF0aW9uOiBzdHJpbmdcblxuICBjb25zdHJ1Y3RvcihyZXN0OiBSZXN0TWFuYWdlciwgb3B0aW9uczogUXVldWVPcHRpb25zKSB7XG4gICAgdGhpcy5yZXN0ID0gcmVzdFxuICAgIHRoaXMudXJsID0gb3B0aW9ucy51cmxcbiAgICB0aGlzLnJlcXVlc3RBdXRob3JpemF0aW9uID0gb3B0aW9ucy5yZXF1ZXN0QXV0aG9yaXphdGlvblxuXG4gICAgaWYgKG9wdGlvbnMuaW50ZXJ2YWwpIHRoaXMuaW50ZXJ2YWwgPSBvcHRpb25zLmludGVydmFsXG4gICAgaWYgKG9wdGlvbnMubWF4KSB0aGlzLm1heCA9IG9wdGlvbnMubWF4XG4gICAgaWYgKG9wdGlvbnMucmVtYWluaW5nKSB0aGlzLnJlbWFpbmluZyA9IG9wdGlvbnMucmVtYWluaW5nXG4gICAgaWYgKG9wdGlvbnMudGltZW91dElkKSB0aGlzLnRpbWVvdXRJZCA9IG9wdGlvbnMudGltZW91dElkXG4gICAgaWYgKG9wdGlvbnMuZGVsZXRlUXVldWVEZWxheSkgdGhpcy5kZWxldGVRdWV1ZURlbGF5ID0gb3B0aW9ucy5kZWxldGVRdWV1ZURlbGF5XG4gIH1cblxuICAvKiogQ2hlY2sgaWYgdGhlcmUgaXMgYW55IHJlbWFpbmluZyByZXF1ZXN0cyB0aGF0IGFyZSBhbGxvd2VkLiAqL1xuICBpc1JlcXVlc3RBbGxvd2VkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnJlbWFpbmluZyA+IDBcbiAgfVxuXG4gIC8qKiBQYXVzZXMgdGhlIGV4ZWN1dGlvbiB1bnRpbCBhIHJlcXVlc3QgaXMgYWxsb3dlZCB0byBiZSBtYWRlLiAqL1xuICBhc3luYyB3YWl0VW50aWxSZXF1ZXN0QXZhaWxhYmxlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBhd2FpdCBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSkgPT4ge1xuICAgICAgLy8gSWYgd2hhdGV2ZXIgYW1vdW50IG9mIHJlcXVlc3RzIGlzIGxlZnQgaXMgbW9yZSB0aGFuIHRoZSBzYWZldHkgbWFyZ2luLCBhbGxvdyB0aGUgcmVxdWVzdFxuICAgICAgaWYgKHRoaXMuaXNSZXF1ZXN0QWxsb3dlZCgpKSB7XG4gICAgICAgIC8vIHRoaXMucmVtYWluaW5nKys7XG4gICAgICAgIHJlc29sdmUoKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy53YWl0aW5nLnB1c2gocmVzb2x2ZSlcbiAgICAgICAgYXdhaXQgdGhpcy5wcm9jZXNzV2FpdGluZygpXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIC8qKiBQcm9jZXNzIHRoZSBxdWV1ZSBvZiByZXF1ZXN0cyB3YWl0aW5nIHRvIGJlIGhhbmRsZWQuICovXG4gIGFzeW5jIHByb2Nlc3NXYWl0aW5nKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIElmIGFscmVhZHkgcHJvY2Vzc2luZywgdGhhdCBsb29wIHdpbGwgaGFuZGxlIGFsbCB3YWl0aW5nIHJlcXVlc3RzLlxuICAgIGlmICh0aGlzLnByb2Nlc3NpbmcpIHJldHVyblxuICAgIC8vIE1hcmsgYXMgcHJvY2Vzc2luZyBzbyBvdGhlciBsb29wcyBkb24ndCBzdGFydFxuICAgIHRoaXMucHJvY2Vzc2luZyA9IHRydWVcblxuICAgIHdoaWxlICh0aGlzLndhaXRpbmcubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5yZXN0LmxvZ2dlci5kZWJ1ZyhgW1F1ZXVlXSAke3RoaXMuZ2V0UXVldWVUeXBlKCl9ICR7dGhpcy51cmx9IHByb2Nlc3Mgd2FpdGluZyB3aGlsZSBsb29wIHJhbi5gKVxuICAgICAgaWYgKHRoaXMuaXNSZXF1ZXN0QWxsb3dlZCgpKSB7XG4gICAgICAgIC8vIFJlc29sdmUgdGhlIG5leHQgaXRlbSBpbiB0aGUgcXVldWVcbiAgICAgICAgdGhpcy53YWl0aW5nLnNoaWZ0KCk/LigpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhd2FpdCBkZWxheSgxMDAwKVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE1hcmsgYXMgZmFsc2Ugc28gbmV4dCBwZW5kaW5nIHJlcXVlc3QgY2FuIGJlIHRyaWdnZXJlZCBieSBuZXcgbG9vcC5cbiAgICB0aGlzLnByb2Nlc3NpbmcgPSBmYWxzZVxuICB9XG5cbiAgLyoqIFByb2Nlc3MgdGhlIHF1ZXVlIG9mIGFsbCByZXF1ZXN0cyBwZW5kaW5nIHRvIGJlIHNlbnQuICovXG4gIGFzeW5jIHByb2Nlc3NQZW5kaW5nKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIElmIGFscmVhZHkgcHJvY2Vzc2luZywgdGhhdCBsb29wIHdpbGwgaGFuZGxlIGFsbCBwZW5kaW5nIHJlcXVlc3RzLlxuICAgIGlmICh0aGlzLnByb2Nlc3NpbmdQZW5kaW5nIHx8ICF0aGlzLnBlbmRpbmcubGVuZ3RoKSByZXR1cm5cblxuICAgIC8vIE1hcmsgYXMgcHJvY2Vzc2luZyBzbyBvdGhlciBsb29wcyBkb24ndCBzdGFydFxuICAgIHRoaXMucHJvY2Vzc2luZ1BlbmRpbmcgPSB0cnVlXG5cbiAgICB3aGlsZSAodGhpcy5wZW5kaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMucmVzdC5sb2dnZXIuZGVidWcoYFF1ZXVlICR7dGhpcy5nZXRRdWV1ZVR5cGUoKX0gJHt0aGlzLnVybH0gcHJvY2VzcyBwZW5kaW5nIHdoaWxlIGxvb3AgcmFuIHdpdGggJHt0aGlzLnBlbmRpbmcubGVuZ3RofS5gKVxuICAgICAgaWYgKCF0aGlzLmZpcnN0UmVxdWVzdCAmJiAhdGhpcy5pc1JlcXVlc3RBbGxvd2VkKCkpIHtcbiAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKVxuICAgICAgICBjb25zdCBmdXR1cmUgPSB0aGlzLmZyb3plbkF0ICsgdGhpcy5pbnRlcnZhbFxuICAgICAgICBhd2FpdCBkZWxheShmdXR1cmUgPiBub3cgPyBmdXR1cmUgLSBub3cgOiAxMDAwKVxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5wZW5kaW5nWzBdXG4gICAgICBpZiAocmVxdWVzdCkge1xuICAgICAgICBjb25zdCBiYXNpY1VSTCA9IHRoaXMucmVzdC5zaW1wbGlmeVVybChyZXF1ZXN0LnJvdXRlLCByZXF1ZXN0Lm1ldGhvZClcblxuICAgICAgICAvLyBJZiB0aGlzIHVybCBpcyBzdGlsbCByYXRlIGxpbWl0ZWQsIHRyeSBhZ2FpblxuICAgICAgICBjb25zdCB1cmxSZXNldEluID0gdGhpcy5yZXN0LmNoZWNrUmF0ZUxpbWl0cyhiYXNpY1VSTCwgdGhpcy5yZXF1ZXN0QXV0aG9yaXphdGlvbilcbiAgICAgICAgaWYgKHVybFJlc2V0SW4pIGF3YWl0IGRlbGF5KHVybFJlc2V0SW4pXG5cbiAgICAgICAgLy8gSUYgQSBCVUNLRVQgRVhJU1RTLCBDSEVDSyBUSEUgQlVDS0VUJ1MgUkFURSBMSU1JVFNcbiAgICAgICAgY29uc3QgYnVja2V0UmVzZXRJbiA9IHJlcXVlc3QuYnVja2V0SWQgPyB0aGlzLnJlc3QuY2hlY2tSYXRlTGltaXRzKHJlcXVlc3QuYnVja2V0SWQsIHRoaXMucmVxdWVzdEF1dGhvcml6YXRpb24pIDogZmFsc2VcbiAgICAgICAgaWYgKGJ1Y2tldFJlc2V0SW4pIGF3YWl0IGRlbGF5KGJ1Y2tldFJlc2V0SW4pXG5cbiAgICAgICAgdGhpcy5maXJzdFJlcXVlc3QgPSBmYWxzZVxuICAgICAgICB0aGlzLnJlbWFpbmluZy0tXG5cbiAgICAgICAgaWYgKHRoaXMucmVtYWluaW5nID09PSAwICYmIHRoaXMuaW50ZXJ2YWwgIT09IDApIHtcbiAgICAgICAgICB0aGlzLnRpbWVvdXRJZCA/Pz0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnJlbWFpbmluZyA9IHRoaXMubWF4XG4gICAgICAgICAgICB0aGlzLnRpbWVvdXRJZCA9IHVuZGVmaW5lZFxuICAgICAgICAgIH0sIHRoaXMuaW50ZXJ2YWwpXG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZW1vdmUgZnJvbSBxdWV1ZSwgd2UgYXJlIGV4ZWN1dGluZyBpdC5cbiAgICAgICAgdGhpcy5wZW5kaW5nLnNoaWZ0KClcbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhpcyByZXF1ZXN0IGlzIGFibGUgdG8gYmUgbWFkZSBnbG9iYWxseVxuICAgICAgICBhd2FpdCB0aGlzLnJlc3QuaW52YWxpZEJ1Y2tldC53YWl0VW50aWxSZXF1ZXN0QXZhaWxhYmxlKClcblxuICAgICAgICBpZiAocmVxdWVzdC5yZXF1ZXN0Qm9keU9wdGlvbnM/LmhlYWRlcnM/LmF1dGhvcml6YXRpb24pIHJlcXVlc3QucmVxdWVzdEJvZHlPcHRpb25zLmhlYWRlcnMuYXV0aG9yaXphdGlvbiA9IHRoaXMucmVxdWVzdEF1dGhvcml6YXRpb25cblxuICAgICAgICBhd2FpdCB0aGlzLnJlc3RcbiAgICAgICAgICAuc2VuZFJlcXVlc3QocmVxdWVzdClcbiAgICAgICAgICAvLyBTaG91bGQgYmUgaGFuZGxlZCBpbiBzZW5kUmVxdWVzdCwgdGhpcyBjYXRjaCBqdXN0IHByZXZlbnRzIGJvdHMgZnJvbSBkeWluZ1xuICAgICAgICAgIC5jYXRjaCgoKSA9PiBudWxsKVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMucmVzdC5sb2dnZXIuZGVidWcoYFF1ZXVlICR7dGhpcy5nZXRRdWV1ZVR5cGUoKX0gJHt0aGlzLnVybH0gcHJvY2VzcyBwZW5kaW5nIHdoaWxlIGxvb3AgZXhpdGVkIHdpdGggJHt0aGlzLnBlbmRpbmcubGVuZ3RofS5gKVxuXG4gICAgLy8gTWFyayBhcyBmYWxzZSBzbyBuZXh0IHBlbmRpbmcgcmVxdWVzdCBjYW4gYmUgdHJpZ2dlcmVkIGJ5IG5ldyBsb29wLlxuICAgIHRoaXMucHJvY2Vzc2luZ1BlbmRpbmcgPSBmYWxzZVxuICAgIHRoaXMuY2xlYW51cCgpXG4gIH1cblxuICBoYW5kbGVDb21wbGV0ZWRSZXF1ZXN0KGhlYWRlcnM6IHsgbWF4PzogbnVtYmVyOyBpbnRlcnZhbD86IG51bWJlcjsgcmVtYWluaW5nPzogbnVtYmVyIH0pOiB2b2lkIHtcbiAgICBpZiAoaGVhZGVycy5tYXggPT09IDApIHtcbiAgICAgIHRoaXMucmVtYWluaW5nKytcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGlmICghdGhpcy5mcm96ZW5BdCkgdGhpcy5mcm96ZW5BdCA9IERhdGUubm93KClcbiAgICBpZiAoaGVhZGVycy5pbnRlcnZhbCAhPT0gdW5kZWZpbmVkKSB0aGlzLmludGVydmFsID0gaGVhZGVycy5pbnRlcnZhbFxuICAgIGlmIChoZWFkZXJzLnJlbWFpbmluZyAhPT0gdW5kZWZpbmVkKSB0aGlzLnJlbWFpbmluZyA9IGhlYWRlcnMucmVtYWluaW5nXG5cbiAgICBpZiAodGhpcy5yZW1haW5pbmcgPD0gMSkge1xuICAgICAgdGhpcy50aW1lb3V0SWQgPz89IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLnJlbWFpbmluZyA9IHRoaXMubWF4XG4gICAgICAgIHRoaXMudGltZW91dElkID0gdW5kZWZpbmVkXG4gICAgICB9LCBoZWFkZXJzLmludGVydmFsKVxuICAgIH1cbiAgfVxuXG4gIC8qKiBDaGVja3MgaWYgYSByZXF1ZXN0IGlzIGF2YWlsYWJsZSBhbmQgYWRkcyBpdCB0byB0aGUgcXVldWUuIEFsc28gdHJpZ2dlcnMgcXVldWUgcHJvY2Vzc2luZyBpZiBub3QgYWxyZWFkeSBwcm9jZXNzaW5nLiAqL1xuICBhc3luYyBtYWtlUmVxdWVzdChvcHRpb25zOiBTZW5kUmVxdWVzdE9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLndhaXRVbnRpbFJlcXVlc3RBdmFpbGFibGUoKVxuICAgIHRoaXMucGVuZGluZy5wdXNoKG9wdGlvbnMpXG4gICAgdGhpcy5wcm9jZXNzUGVuZGluZygpXG4gIH1cblxuICAvKiogQ2xlYW5zIHVwIHRoZSBxdWV1ZSBieSBjaGVja2luZyBpZiB0aGVyZSBpcyBub3RoaW5nIGxlZnQgYW5kIHJlbW92aW5nIGl0LiAqL1xuICBjbGVhbnVwKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5pc1F1ZXVlQ2xlYXJhYmxlKCkpIHtcbiAgICAgIHRoaXMucHJvY2Vzc1BlbmRpbmcoKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgdGhpcy5yZXN0LmxvZ2dlci5kZWJ1ZyhgW1F1ZXVlXSAke3RoaXMuZ2V0UXVldWVUeXBlKCl9ICR7dGhpcy51cmx9LiBEZWxheWluZyBkZWxldGUgZm9yICR7dGhpcy5kZWxldGVRdWV1ZURlbGF5fW1zYClcblxuICAgIC8vIERlbGV0ZSBpbiBhIG1pbnV0ZSBnaXZpbmcgYSBiaXQgb2YgdGltZSB0byBhbGxvdyBuZXcgcmVxdWVzdHMgdGhhdCBtYXkgcmV1c2UgdGhpcyBxdWV1ZVxuICAgIGNsZWFyVGltZW91dCh0aGlzLmRlbGV0ZVF1ZXVlVGltZW91dClcbiAgICB0aGlzLmRlbGV0ZVF1ZXVlVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgaWYgKCF0aGlzLmlzUXVldWVDbGVhcmFibGUoKSkge1xuICAgICAgICB0aGlzLnJlc3QubG9nZ2VyLmRlYnVnKGBbUXVldWVdICR7dGhpcy5nZXRRdWV1ZVR5cGUoKX0gJHt0aGlzLnVybH0uIGlzIG5vdCBjbGVhcmFibGUuIFJlc3RhcnRpbmcgcHJvY2Vzc2luZyBvZiBxdWV1ZS5gKVxuICAgICAgICB0aGlzLnByb2Nlc3NQZW5kaW5nKClcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIHRoaXMucmVzdC5sb2dnZXIuZGVidWcoYFtRdWV1ZV0gJHt0aGlzLmdldFF1ZXVlVHlwZSgpfSAke3RoaXMudXJsfS4gRGVsZXRpbmdgKVxuXG4gICAgICBpZiAodGhpcy50aW1lb3V0SWQpIGNsZWFyVGltZW91dCh0aGlzLnRpbWVvdXRJZClcblxuICAgICAgLy8gTm8gcmVxdWVzdHMgaGF2ZSBiZWVuIHJlcXVlc3RlZCBmb3IgdGhpcyBxdWV1ZSBzbyB3ZSBudWtlIHRoaXMgcXVldWVcbiAgICAgIHRoaXMucmVzdC5xdWV1ZXMuZGVsZXRlKGAke3RoaXMucmVxdWVzdEF1dGhvcml6YXRpb259JHt0aGlzLnVybH1gKVxuICAgICAgdGhpcy5yZXN0LmxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgYFtRdWV1ZV0gJHt0aGlzLmdldFF1ZXVlVHlwZSgpfSAke3RoaXMudXJsfS4gRGVsZXRlZCEgUmVtYWluaW5nOiAoJHt0aGlzLnJlc3QucXVldWVzLnNpemV9KWAsXG4gICAgICAgIFsuLi50aGlzLnJlc3QucXVldWVzLnZhbHVlcygpXS5tYXAoKHF1ZXVlKSA9PiBgJHtxdWV1ZS5nZXRRdWV1ZVR5cGUoKX0ke3F1ZXVlLnVybH1gKSxcbiAgICAgIClcbiAgICB9LCB0aGlzLmRlbGV0ZVF1ZXVlRGVsYXkpXG4gIH1cblxuICAvKiogU2ltcGx5IGNoZWNrcyBpZiB0aGUgcXVldWUgaXMgYWJsZSB0byBiZSBjbGVhcmVkIG9yIGl0IGhhcyByZXF1ZXN0cyBwZW5kaW5nLiAqL1xuICBpc1F1ZXVlQ2xlYXJhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmZpcnN0UmVxdWVzdCkgcmV0dXJuIGZhbHNlXG4gICAgaWYgKHRoaXMud2FpdGluZy5sZW5ndGggPiAwKSByZXR1cm4gZmFsc2VcbiAgICBpZiAodGhpcy5wZW5kaW5nLmxlbmd0aCA+IDApIHJldHVybiBmYWxzZVxuICAgIGlmICh0aGlzLnByb2Nlc3NpbmcpIHJldHVybiBmYWxzZVxuICAgIGlmICh0aGlzLnByb2Nlc3NpbmdQZW5kaW5nKSByZXR1cm4gZmFsc2VcblxuICAgIHJldHVybiB0cnVlXG4gIH1cblxuICBnZXRRdWV1ZVR5cGUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0QXV0aG9yaXphdGlvbi5zcGxpdCgnICcpWzBdXG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBRdWV1ZU9wdGlvbnMge1xuICAvKiogSG93IG1hbnkgcmVxdWVzdHMgYXJlIHJlbWFpbmluZy4gRGVmYXVsdHMgdG8gMSAqL1xuICByZW1haW5pbmc/OiBudW1iZXJcbiAgLyoqIE1heCBudW1iZXIgb2YgcmVxdWVzdHMgYWxsb3dlZCBpbiB0aGlzIHRoaXMuIERlZmF1bHRzIHRvIDEuICovXG4gIG1heD86IG51bWJlclxuICAvKiogVGhlIHRpbWUgaW4gbWlsbGlzZWNvbmRzIHRoYXQgZGlzY29yZCBhbGxvd3MgdG8gbWFrZSB0aGUgbWF4IG51bWJlciBvZiBpbnZhbGlkIHJlcXVlc3RzLiBEZWZhdWx0cyB0byAwICovXG4gIGludGVydmFsPzogbnVtYmVyXG4gIC8qKiB0aW1lciB0byByZXNldCB0byAwICovXG4gIHRpbWVvdXRJZD86IE5vZGVKUy5UaW1lb3V0XG4gIC8qKiBUaGUgdXJsIHRoaXMgcXVldWUgd2lsbCBiZSBoYW5kbGluZy4gKi9cbiAgdXJsOiBzdHJpbmdcbiAgLyoqIFRoZSB0aW1lIGluIG1pbGxpc2Vjb25kcyB0byB3YWl0IGJlZm9yZSBkZWxldGluZyB0aGlzIHF1ZXVlIGlmIGl0IGlzIGVtcHR5LiBEZWZhdWx0cyB0byA2MDAwMChvbmUgbWludXRlKS4gKi9cbiAgZGVsZXRlUXVldWVEZWxheT86IG51bWJlclxuICAvKiogVGhlIGJhc2Uga2V5IHRoYXQgaWRlbnRpZmllcyB0aGlzIHF1ZXVlIGluIHRoZSByZXN0IG1hbmFnZXIgKi9cbiAgcmVxdWVzdEF1dGhvcml6YXRpb246IHN0cmluZ1xufVxuIl0sIm5hbWVzIjpbIlF1ZXVlIiwiY29uc3RydWN0b3IiLCJyZXN0Iiwib3B0aW9ucyIsInJlbWFpbmluZyIsIm1heCIsImludGVydmFsIiwid2FpdGluZyIsInBlbmRpbmciLCJwcm9jZXNzaW5nIiwicHJvY2Vzc2luZ1BlbmRpbmciLCJmaXJzdFJlcXVlc3QiLCJmcm96ZW5BdCIsImRlbGV0ZVF1ZXVlRGVsYXkiLCJ1cmwiLCJyZXF1ZXN0QXV0aG9yaXphdGlvbiIsInRpbWVvdXRJZCIsImlzUmVxdWVzdEFsbG93ZWQiLCJ3YWl0VW50aWxSZXF1ZXN0QXZhaWxhYmxlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJwdXNoIiwicHJvY2Vzc1dhaXRpbmciLCJsZW5ndGgiLCJsb2dnZXIiLCJkZWJ1ZyIsImdldFF1ZXVlVHlwZSIsInNoaWZ0IiwiZGVsYXkiLCJwcm9jZXNzUGVuZGluZyIsIm5vdyIsIkRhdGUiLCJmdXR1cmUiLCJyZXF1ZXN0IiwiYmFzaWNVUkwiLCJzaW1wbGlmeVVybCIsInJvdXRlIiwibWV0aG9kIiwidXJsUmVzZXRJbiIsImNoZWNrUmF0ZUxpbWl0cyIsImJ1Y2tldFJlc2V0SW4iLCJidWNrZXRJZCIsInNldFRpbWVvdXQiLCJ1bmRlZmluZWQiLCJpbnZhbGlkQnVja2V0IiwicmVxdWVzdEJvZHlPcHRpb25zIiwiaGVhZGVycyIsImF1dGhvcml6YXRpb24iLCJzZW5kUmVxdWVzdCIsImNhdGNoIiwiY2xlYW51cCIsImhhbmRsZUNvbXBsZXRlZFJlcXVlc3QiLCJtYWtlUmVxdWVzdCIsImlzUXVldWVDbGVhcmFibGUiLCJjbGVhclRpbWVvdXQiLCJkZWxldGVRdWV1ZVRpbWVvdXQiLCJxdWV1ZXMiLCJkZWxldGUiLCJzaXplIiwidmFsdWVzIiwibWFwIiwicXVldWUiLCJzcGxpdCJdLCJtYXBwaW5ncyI6Ijs7OzsrQkFHYUE7OztlQUFBQTs7O3VCQUhTO0FBR2YsSUFBQSxBQUFNQSxRQUFOLE1BQU1BO0lBcUNYQyxZQUFZQyxJQUFpQixFQUFFQyxPQUFxQixDQUFFO1FBbEN0RCwrREFBK0QsUUFDL0RDLFlBQW9CO1FBQ3BCLCtDQUErQyxRQUMvQ0MsTUFBYztRQUNkLG1GQUFtRixRQUNuRkMsV0FBbUI7UUFHbkIsNkNBQTZDLFFBQzdDQyxVQUE0RCxFQUFFO1FBQzlELDZDQUE2QyxRQUM3Q0MsVUFBZ0MsRUFBRTtRQUNsQyw0REFBNEQsUUFDNURDLGFBQXNCO1FBQ3RCLDREQUE0RCxRQUM1REMsb0JBQTZCO1FBQzdCLDBDQUEwQyxRQUMxQ0MsZUFBd0I7UUFHeEIsbUZBQW1GLFFBQ25GQyxXQUFtQjtRQUNuQiwrR0FBK0csUUFDL0dDLG1CQUEyQjtRQVl6QixJQUFJLENBQUNYLElBQUksR0FBR0E7UUFDWixJQUFJLENBQUNZLEdBQUcsR0FBR1gsUUFBUVcsR0FBRztRQUN0QixJQUFJLENBQUNDLG9CQUFvQixHQUFHWixRQUFRWSxvQkFBb0I7UUFFeEQsSUFBSVosUUFBUUcsUUFBUSxFQUFFLElBQUksQ0FBQ0EsUUFBUSxHQUFHSCxRQUFRRyxRQUFRO1FBQ3RELElBQUlILFFBQVFFLEdBQUcsRUFBRSxJQUFJLENBQUNBLEdBQUcsR0FBR0YsUUFBUUUsR0FBRztRQUN2QyxJQUFJRixRQUFRQyxTQUFTLEVBQUUsSUFBSSxDQUFDQSxTQUFTLEdBQUdELFFBQVFDLFNBQVM7UUFDekQsSUFBSUQsUUFBUWEsU0FBUyxFQUFFLElBQUksQ0FBQ0EsU0FBUyxHQUFHYixRQUFRYSxTQUFTO1FBQ3pELElBQUliLFFBQVFVLGdCQUFnQixFQUFFLElBQUksQ0FBQ0EsZ0JBQWdCLEdBQUdWLFFBQVFVLGdCQUFnQjtJQUNoRjtJQUVBLCtEQUErRCxHQUMvREksbUJBQTRCO1FBQzFCLE9BQU8sSUFBSSxDQUFDYixTQUFTLEdBQUc7SUFDMUI7SUFFQSxnRUFBZ0UsR0FDaEUsTUFBTWMsNEJBQTJDO1FBQy9DLE9BQU8sTUFBTSxJQUFJQyxRQUFRLE9BQU9DO1lBQzlCLDJGQUEyRjtZQUMzRixJQUFJLElBQUksQ0FBQ0gsZ0JBQWdCLElBQUk7Z0JBQzNCLG9CQUFvQjtnQkFDcEJHO1lBQ0YsT0FBTztnQkFDTCxJQUFJLENBQUNiLE9BQU8sQ0FBQ2MsSUFBSSxDQUFDRDtnQkFDbEIsTUFBTSxJQUFJLENBQUNFLGNBQWM7WUFDM0I7UUFDRjtJQUNGO0lBRUEseURBQXlELEdBQ3pELE1BQU1BLGlCQUFnQztRQUNwQyxxRUFBcUU7UUFDckUsSUFBSSxJQUFJLENBQUNiLFVBQVUsRUFBRTtRQUNyQixnREFBZ0Q7UUFDaEQsSUFBSSxDQUFDQSxVQUFVLEdBQUc7UUFFbEIsTUFBTyxJQUFJLENBQUNGLE9BQU8sQ0FBQ2dCLE1BQU0sR0FBRyxFQUFHO1lBQzlCLElBQUksQ0FBQ3JCLElBQUksQ0FBQ3NCLE1BQU0sQ0FBQ0MsS0FBSyxDQUFDLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQ0MsWUFBWSxHQUFHLENBQUMsRUFBRSxJQUFJLENBQUNaLEdBQUcsQ0FBQyxnQ0FBZ0MsQ0FBQztZQUNuRyxJQUFJLElBQUksQ0FBQ0csZ0JBQWdCLElBQUk7Z0JBQzNCLHFDQUFxQztnQkFDckMsSUFBSSxDQUFDVixPQUFPLENBQUNvQixLQUFLO1lBQ3BCLE9BQU87Z0JBQ0wsTUFBTUMsSUFBQUEsWUFBSyxFQUFDO1lBQ2Q7UUFDRjtRQUVBLHNFQUFzRTtRQUN0RSxJQUFJLENBQUNuQixVQUFVLEdBQUc7SUFDcEI7SUFFQSwwREFBMEQsR0FDMUQsTUFBTW9CLGlCQUFnQztRQUNwQyxxRUFBcUU7UUFDckUsSUFBSSxJQUFJLENBQUNuQixpQkFBaUIsSUFBSSxDQUFDLElBQUksQ0FBQ0YsT0FBTyxDQUFDZSxNQUFNLEVBQUU7UUFFcEQsZ0RBQWdEO1FBQ2hELElBQUksQ0FBQ2IsaUJBQWlCLEdBQUc7UUFFekIsTUFBTyxJQUFJLENBQUNGLE9BQU8sQ0FBQ2UsTUFBTSxHQUFHLEVBQUc7WUFDOUIsSUFBSSxDQUFDckIsSUFBSSxDQUFDc0IsTUFBTSxDQUFDQyxLQUFLLENBQUMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDQyxZQUFZLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQ1osR0FBRyxDQUFDLHFDQUFxQyxFQUFFLElBQUksQ0FBQ04sT0FBTyxDQUFDZSxNQUFNLENBQUMsQ0FBQyxDQUFDO1lBQzdILElBQUksQ0FBQyxJQUFJLENBQUNaLFlBQVksSUFBSSxDQUFDLElBQUksQ0FBQ00sZ0JBQWdCLElBQUk7Z0JBQ2xELE1BQU1hLE1BQU1DLEtBQUtELEdBQUc7Z0JBQ3BCLE1BQU1FLFNBQVMsSUFBSSxDQUFDcEIsUUFBUSxHQUFHLElBQUksQ0FBQ04sUUFBUTtnQkFDNUMsTUFBTXNCLElBQUFBLFlBQUssRUFBQ0ksU0FBU0YsTUFBTUUsU0FBU0YsTUFBTTtnQkFDMUM7WUFDRjtZQUVBLE1BQU1HLFVBQVUsSUFBSSxDQUFDekIsT0FBTyxDQUFDLEVBQUU7WUFDL0IsSUFBSXlCLFNBQVM7Z0JBQ1gsTUFBTUMsV0FBVyxJQUFJLENBQUNoQyxJQUFJLENBQUNpQyxXQUFXLENBQUNGLFFBQVFHLEtBQUssRUFBRUgsUUFBUUksTUFBTTtnQkFFcEUsK0NBQStDO2dCQUMvQyxNQUFNQyxhQUFhLElBQUksQ0FBQ3BDLElBQUksQ0FBQ3FDLGVBQWUsQ0FBQ0wsVUFBVSxJQUFJLENBQUNuQixvQkFBb0I7Z0JBQ2hGLElBQUl1QixZQUFZLE1BQU1WLElBQUFBLFlBQUssRUFBQ1U7Z0JBRTVCLHFEQUFxRDtnQkFDckQsTUFBTUUsZ0JBQWdCUCxRQUFRUSxRQUFRLEdBQUcsSUFBSSxDQUFDdkMsSUFBSSxDQUFDcUMsZUFBZSxDQUFDTixRQUFRUSxRQUFRLEVBQUUsSUFBSSxDQUFDMUIsb0JBQW9CLElBQUk7Z0JBQ2xILElBQUl5QixlQUFlLE1BQU1aLElBQUFBLFlBQUssRUFBQ1k7Z0JBRS9CLElBQUksQ0FBQzdCLFlBQVksR0FBRztnQkFDcEIsSUFBSSxDQUFDUCxTQUFTO2dCQUVkLElBQUksSUFBSSxDQUFDQSxTQUFTLEtBQUssS0FBSyxJQUFJLENBQUNFLFFBQVEsS0FBSyxHQUFHO29CQUMvQyxJQUFJLENBQUNVLFNBQVMsS0FBSzBCLFdBQVc7d0JBQzVCLElBQUksQ0FBQ3RDLFNBQVMsR0FBRyxJQUFJLENBQUNDLEdBQUc7d0JBQ3pCLElBQUksQ0FBQ1csU0FBUyxHQUFHMkI7b0JBQ25CLEdBQUcsSUFBSSxDQUFDckMsUUFBUTtnQkFDbEI7Z0JBRUEsMENBQTBDO2dCQUMxQyxJQUFJLENBQUNFLE9BQU8sQ0FBQ21CLEtBQUs7Z0JBQ2xCLG9EQUFvRDtnQkFDcEQsTUFBTSxJQUFJLENBQUN6QixJQUFJLENBQUMwQyxhQUFhLENBQUMxQix5QkFBeUI7Z0JBRXZELElBQUllLFFBQVFZLGtCQUFrQixFQUFFQyxTQUFTQyxlQUFlZCxRQUFRWSxrQkFBa0IsQ0FBQ0MsT0FBTyxDQUFDQyxhQUFhLEdBQUcsSUFBSSxDQUFDaEMsb0JBQW9CO2dCQUVwSSxNQUFNLElBQUksQ0FBQ2IsSUFBSSxDQUNaOEMsV0FBVyxDQUFDZixRQUNiLDZFQUE2RTtpQkFDNUVnQixLQUFLLENBQUMsSUFBTTtZQUNqQjtRQUNGO1FBRUEsSUFBSSxDQUFDL0MsSUFBSSxDQUFDc0IsTUFBTSxDQUFDQyxLQUFLLENBQUMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDQyxZQUFZLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQ1osR0FBRyxDQUFDLHdDQUF3QyxFQUFFLElBQUksQ0FBQ04sT0FBTyxDQUFDZSxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBRWhJLHNFQUFzRTtRQUN0RSxJQUFJLENBQUNiLGlCQUFpQixHQUFHO1FBQ3pCLElBQUksQ0FBQ3dDLE9BQU87SUFDZDtJQUVBQyx1QkFBdUJMLE9BQWdFLEVBQVE7UUFDN0YsSUFBSUEsUUFBUXpDLEdBQUcsS0FBSyxHQUFHO1lBQ3JCLElBQUksQ0FBQ0QsU0FBUztZQUNkO1FBQ0Y7UUFFQSxJQUFJLENBQUMsSUFBSSxDQUFDUSxRQUFRLEVBQUUsSUFBSSxDQUFDQSxRQUFRLEdBQUdtQixLQUFLRCxHQUFHO1FBQzVDLElBQUlnQixRQUFReEMsUUFBUSxLQUFLcUMsV0FBVyxJQUFJLENBQUNyQyxRQUFRLEdBQUd3QyxRQUFReEMsUUFBUTtRQUNwRSxJQUFJd0MsUUFBUTFDLFNBQVMsS0FBS3VDLFdBQVcsSUFBSSxDQUFDdkMsU0FBUyxHQUFHMEMsUUFBUTFDLFNBQVM7UUFFdkUsSUFBSSxJQUFJLENBQUNBLFNBQVMsSUFBSSxHQUFHO1lBQ3ZCLElBQUksQ0FBQ1ksU0FBUyxLQUFLMEIsV0FBVztnQkFDNUIsSUFBSSxDQUFDdEMsU0FBUyxHQUFHLElBQUksQ0FBQ0MsR0FBRztnQkFDekIsSUFBSSxDQUFDVyxTQUFTLEdBQUcyQjtZQUNuQixHQUFHRyxRQUFReEMsUUFBUTtRQUNyQjtJQUNGO0lBRUEseUhBQXlILEdBQ3pILE1BQU04QyxZQUFZakQsT0FBMkIsRUFBaUI7UUFDNUQsTUFBTSxJQUFJLENBQUNlLHlCQUF5QjtRQUNwQyxJQUFJLENBQUNWLE9BQU8sQ0FBQ2EsSUFBSSxDQUFDbEI7UUFDbEIsSUFBSSxDQUFDMEIsY0FBYztJQUNyQjtJQUVBLDhFQUE4RSxHQUM5RXFCLFVBQWdCO1FBQ2QsSUFBSSxDQUFDLElBQUksQ0FBQ0csZ0JBQWdCLElBQUk7WUFDNUIsSUFBSSxDQUFDeEIsY0FBYztZQUNuQjtRQUNGO1FBRUEsSUFBSSxDQUFDM0IsSUFBSSxDQUFDc0IsTUFBTSxDQUFDQyxLQUFLLENBQUMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDQyxZQUFZLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQ1osR0FBRyxDQUFDLHNCQUFzQixFQUFFLElBQUksQ0FBQ0QsZ0JBQWdCLENBQUMsRUFBRSxDQUFDO1FBRW5ILDBGQUEwRjtRQUMxRnlDLGFBQWEsSUFBSSxDQUFDQyxrQkFBa0I7UUFDcEMsSUFBSSxDQUFDQSxrQkFBa0IsR0FBR2IsV0FBVztZQUNuQyxJQUFJLENBQUMsSUFBSSxDQUFDVyxnQkFBZ0IsSUFBSTtnQkFDNUIsSUFBSSxDQUFDbkQsSUFBSSxDQUFDc0IsTUFBTSxDQUFDQyxLQUFLLENBQUMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDQyxZQUFZLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQ1osR0FBRyxDQUFDLG1EQUFtRCxDQUFDO2dCQUN0SCxJQUFJLENBQUNlLGNBQWM7Z0JBQ25CO1lBQ0Y7WUFFQSxJQUFJLENBQUMzQixJQUFJLENBQUNzQixNQUFNLENBQUNDLEtBQUssQ0FBQyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUNDLFlBQVksR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDWixHQUFHLENBQUMsVUFBVSxDQUFDO1lBRTdFLElBQUksSUFBSSxDQUFDRSxTQUFTLEVBQUVzQyxhQUFhLElBQUksQ0FBQ3RDLFNBQVM7WUFFL0MsdUVBQXVFO1lBQ3ZFLElBQUksQ0FBQ2QsSUFBSSxDQUFDc0QsTUFBTSxDQUFDQyxNQUFNLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQzFDLG9CQUFvQixDQUFDLEVBQUUsSUFBSSxDQUFDRCxHQUFHLENBQUMsQ0FBQztZQUNqRSxJQUFJLENBQUNaLElBQUksQ0FBQ3NCLE1BQU0sQ0FBQ0MsS0FBSyxDQUNwQixDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUNDLFlBQVksR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDWixHQUFHLENBQUMsdUJBQXVCLEVBQUUsSUFBSSxDQUFDWixJQUFJLENBQUNzRCxNQUFNLENBQUNFLElBQUksQ0FBQyxDQUFDLENBQUMsRUFDNUY7bUJBQUksSUFBSSxDQUFDeEQsSUFBSSxDQUFDc0QsTUFBTSxDQUFDRyxNQUFNO2FBQUcsQ0FBQ0MsR0FBRyxDQUFDLENBQUNDLFFBQVUsQ0FBQyxFQUFFQSxNQUFNbkMsWUFBWSxHQUFHLEVBQUVtQyxNQUFNL0MsR0FBRyxDQUFDLENBQUM7UUFFdkYsR0FBRyxJQUFJLENBQUNELGdCQUFnQjtJQUMxQjtJQUVBLGlGQUFpRixHQUNqRndDLG1CQUE0QjtRQUMxQixJQUFJLElBQUksQ0FBQzFDLFlBQVksRUFBRSxPQUFPO1FBQzlCLElBQUksSUFBSSxDQUFDSixPQUFPLENBQUNnQixNQUFNLEdBQUcsR0FBRyxPQUFPO1FBQ3BDLElBQUksSUFBSSxDQUFDZixPQUFPLENBQUNlLE1BQU0sR0FBRyxHQUFHLE9BQU87UUFDcEMsSUFBSSxJQUFJLENBQUNkLFVBQVUsRUFBRSxPQUFPO1FBQzVCLElBQUksSUFBSSxDQUFDQyxpQkFBaUIsRUFBRSxPQUFPO1FBRW5DLE9BQU87SUFDVDtJQUVBZ0IsZUFBdUI7UUFDckIsT0FBTyxJQUFJLENBQUNYLG9CQUFvQixDQUFDK0MsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFO0lBQ2hEO0FBQ0YifQ==