@push.rocks/smartpuppeteer 2.0.7 → 2.1.0
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_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/index.d.ts +2 -0
- package/dist_ts/index.js +3 -1
- package/dist_ts/smartpuppeteer.classes.livebrowsersession.d.ts +97 -0
- package/dist_ts/smartpuppeteer.classes.livebrowsersession.js +1906 -0
- package/dist_ts/smartpuppeteer.classes.smartpuppeteer.d.ts +1 -0
- package/dist_ts/smartpuppeteer.classes.smartpuppeteer.js +19 -7
- package/dist_ts/smartpuppeteer.interfaces.livebrowser.d.ts +191 -0
- package/dist_ts/smartpuppeteer.interfaces.livebrowser.js +2 -0
- package/dist_ts/smartpuppeteer.plugins.d.ts +3 -2
- package/dist_ts/smartpuppeteer.plugins.js +4 -3
- package/package.json +8 -6
- package/readme.hints.md +15 -1
- package/readme.md +92 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/index.ts +2 -0
- package/ts/smartpuppeteer.classes.livebrowsersession.ts +2298 -0
- package/ts/smartpuppeteer.classes.smartpuppeteer.ts +19 -6
- package/ts/smartpuppeteer.interfaces.livebrowser.ts +235 -0
- package/ts/smartpuppeteer.plugins.ts +3 -2
- package/dist/index.d.ts +0 -3
- package/dist/index.js +0 -18
|
@@ -0,0 +1,1906 @@
|
|
|
1
|
+
import { getEnvAwareBrowserInstance } from './smartpuppeteer.classes.smartpuppeteer.js';
|
|
2
|
+
import * as plugins from './smartpuppeteer.plugins.js';
|
|
3
|
+
const defaultViewport = {
|
|
4
|
+
width: 800,
|
|
5
|
+
height: 600,
|
|
6
|
+
deviceScaleFactor: 1,
|
|
7
|
+
};
|
|
8
|
+
const maxViewportWidth = 4096;
|
|
9
|
+
const maxViewportHeight = 4096;
|
|
10
|
+
const maxDeviceScaleFactor = 3;
|
|
11
|
+
const maxViewportPixelArea = 8294400;
|
|
12
|
+
const maxSelectorLength = 4096;
|
|
13
|
+
const maxTextLength = 32768;
|
|
14
|
+
const maxUrlLength = 16384;
|
|
15
|
+
const maxTimeoutMs = 60000;
|
|
16
|
+
const maxOutstandingFrames = 3;
|
|
17
|
+
const maxQueuedPublicOperations = 64;
|
|
18
|
+
const maxQueuedInternalOperations = 128;
|
|
19
|
+
const validateBoundedString = (value, name, minLength, maxLength) => {
|
|
20
|
+
if (typeof value !== 'string'
|
|
21
|
+
|| value.length < minLength
|
|
22
|
+
|| value.length > maxLength) {
|
|
23
|
+
throw new Error(`${name} must contain between ${minLength} and ${maxLength} characters`);
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
};
|
|
27
|
+
const validateFiniteNumber = (value, name, minimum, maximum) => {
|
|
28
|
+
if (typeof value !== 'number'
|
|
29
|
+
|| !Number.isFinite(value)
|
|
30
|
+
|| value < minimum
|
|
31
|
+
|| value > maximum) {
|
|
32
|
+
throw new Error(`${name} must be a finite number between ${minimum} and ${maximum}`);
|
|
33
|
+
}
|
|
34
|
+
return value;
|
|
35
|
+
};
|
|
36
|
+
const validateInteger = (value, name, minimum, maximum) => {
|
|
37
|
+
const validatedValue = validateFiniteNumber(value, name, minimum, maximum);
|
|
38
|
+
if (!Number.isInteger(validatedValue)) {
|
|
39
|
+
throw new Error(`${name} must be an integer`);
|
|
40
|
+
}
|
|
41
|
+
return validatedValue;
|
|
42
|
+
};
|
|
43
|
+
const validateOptionalBoolean = (value, name) => {
|
|
44
|
+
if (value !== undefined && typeof value !== 'boolean') {
|
|
45
|
+
throw new Error(`${name} must be a boolean`);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const truncate = (value, maxLength) => {
|
|
49
|
+
if (value.length <= maxLength) {
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
return `${value.slice(0, Math.max(0, maxLength - 3))}...`;
|
|
53
|
+
};
|
|
54
|
+
const normalizeErrorMessage = (error) => {
|
|
55
|
+
if (error instanceof Error) {
|
|
56
|
+
return truncate(error.message, 2048);
|
|
57
|
+
}
|
|
58
|
+
return truncate(String(error), 2048);
|
|
59
|
+
};
|
|
60
|
+
const readUint32 = (data, offset) => {
|
|
61
|
+
return (data[offset] * 0x1000000
|
|
62
|
+
+ data[offset + 1] * 0x10000
|
|
63
|
+
+ data[offset + 2] * 0x100
|
|
64
|
+
+ data[offset + 3]);
|
|
65
|
+
};
|
|
66
|
+
const readImageDimensions = (data, format, fallback) => {
|
|
67
|
+
if (format === 'png'
|
|
68
|
+
&& data.length >= 24
|
|
69
|
+
&& data[0] === 0x89
|
|
70
|
+
&& data[1] === 0x50
|
|
71
|
+
&& data[2] === 0x4e
|
|
72
|
+
&& data[3] === 0x47) {
|
|
73
|
+
return {
|
|
74
|
+
width: readUint32(data, 16),
|
|
75
|
+
height: readUint32(data, 20),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (format === 'jpeg' && data.length >= 4 && data[0] === 0xff && data[1] === 0xd8) {
|
|
79
|
+
let offset = 2;
|
|
80
|
+
while (offset + 8 < data.length) {
|
|
81
|
+
if (data[offset] !== 0xff) {
|
|
82
|
+
offset += 1;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const marker = data[offset + 1];
|
|
86
|
+
if (marker === 0xd8 || marker === 0xd9) {
|
|
87
|
+
offset += 2;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const segmentLength = (data[offset + 2] << 8) + data[offset + 3];
|
|
91
|
+
if (segmentLength < 2 || offset + segmentLength + 2 > data.length) {
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
if (marker === 0xc0
|
|
95
|
+
|| marker === 0xc1
|
|
96
|
+
|| marker === 0xc2
|
|
97
|
+
|| marker === 0xc3
|
|
98
|
+
|| marker === 0xc5
|
|
99
|
+
|| marker === 0xc6
|
|
100
|
+
|| marker === 0xc7
|
|
101
|
+
|| marker === 0xc9
|
|
102
|
+
|| marker === 0xca
|
|
103
|
+
|| marker === 0xcb
|
|
104
|
+
|| marker === 0xcd
|
|
105
|
+
|| marker === 0xce
|
|
106
|
+
|| marker === 0xcf) {
|
|
107
|
+
return {
|
|
108
|
+
height: (data[offset + 5] << 8) + data[offset + 6],
|
|
109
|
+
width: (data[offset + 7] << 8) + data[offset + 8],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
offset += segmentLength + 2;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return fallback;
|
|
116
|
+
};
|
|
117
|
+
const normalizeViewport = (viewport) => {
|
|
118
|
+
const normalizedViewport = {
|
|
119
|
+
width: validateInteger(viewport.width, 'viewport.width', 1, maxViewportWidth),
|
|
120
|
+
height: validateInteger(viewport.height, 'viewport.height', 1, maxViewportHeight),
|
|
121
|
+
deviceScaleFactor: validateFiniteNumber(viewport.deviceScaleFactor, 'viewport.deviceScaleFactor', 0.25, maxDeviceScaleFactor),
|
|
122
|
+
};
|
|
123
|
+
const physicalWidth = Math.ceil(normalizedViewport.width * normalizedViewport.deviceScaleFactor);
|
|
124
|
+
const physicalHeight = Math.ceil(normalizedViewport.height * normalizedViewport.deviceScaleFactor);
|
|
125
|
+
if (physicalWidth * physicalHeight > maxViewportPixelArea) {
|
|
126
|
+
throw new Error(`viewport pixel area must not exceed ${maxViewportPixelArea} physical pixels`);
|
|
127
|
+
}
|
|
128
|
+
return normalizedViewport;
|
|
129
|
+
};
|
|
130
|
+
const createPuppeteerViewport = (viewport) => ({
|
|
131
|
+
...viewport,
|
|
132
|
+
isMobile: false,
|
|
133
|
+
isLandscape: false,
|
|
134
|
+
hasTouch: false,
|
|
135
|
+
});
|
|
136
|
+
export class LiveBrowserSession {
|
|
137
|
+
constructor(optionsArg = {}) {
|
|
138
|
+
this.eventListeners = new Set();
|
|
139
|
+
this.tabs = new Map();
|
|
140
|
+
this.tabIdsByPage = new WeakMap();
|
|
141
|
+
this.outstandingFrames = new Map();
|
|
142
|
+
this.operationQueue = [];
|
|
143
|
+
this.operationRunning = false;
|
|
144
|
+
this.admittedPublicOperations = 0;
|
|
145
|
+
this.admittedInternalOperations = 0;
|
|
146
|
+
this.status = 'stopped';
|
|
147
|
+
this.activeTabId = null;
|
|
148
|
+
this.viewport = { ...defaultViewport };
|
|
149
|
+
this.viewportRevision = 1;
|
|
150
|
+
this.tabSequence = 0;
|
|
151
|
+
this.frameSequence = 0;
|
|
152
|
+
this.normalStopRequested = false;
|
|
153
|
+
if (optionsArg.launchOptions?.protocol
|
|
154
|
+
&& optionsArg.launchOptions.protocol !== 'cdp') {
|
|
155
|
+
throw new Error('LiveBrowserSession only supports Puppeteer CDP transport');
|
|
156
|
+
}
|
|
157
|
+
if (optionsArg.launchOptions?.browser
|
|
158
|
+
&& optionsArg.launchOptions.browser !== 'chrome') {
|
|
159
|
+
throw new Error('LiveBrowserSession requires Chromium');
|
|
160
|
+
}
|
|
161
|
+
if (optionsArg.launchOptions && 'signal' in optionsArg.launchOptions) {
|
|
162
|
+
throw new Error('LiveBrowserSession owns launch cancellation; launchOptions.signal is unsupported');
|
|
163
|
+
}
|
|
164
|
+
const launchViewport = optionsArg.launchOptions?.defaultViewport;
|
|
165
|
+
const viewport = normalizeViewport(optionsArg.viewport
|
|
166
|
+
?? (launchViewport
|
|
167
|
+
? {
|
|
168
|
+
width: launchViewport.width,
|
|
169
|
+
height: launchViewport.height,
|
|
170
|
+
deviceScaleFactor: launchViewport.deviceScaleFactor ?? 1,
|
|
171
|
+
}
|
|
172
|
+
: defaultViewport));
|
|
173
|
+
this.options = {
|
|
174
|
+
...optionsArg,
|
|
175
|
+
launchOptions: {
|
|
176
|
+
...optionsArg.launchOptions,
|
|
177
|
+
args: [...(optionsArg.launchOptions?.args ?? [])],
|
|
178
|
+
defaultViewport: createPuppeteerViewport(viewport),
|
|
179
|
+
},
|
|
180
|
+
viewport,
|
|
181
|
+
screencast: optionsArg.screencast ? { ...optionsArg.screencast } : undefined,
|
|
182
|
+
};
|
|
183
|
+
this.viewport = { ...viewport };
|
|
184
|
+
this.validateScreencastOptions();
|
|
185
|
+
}
|
|
186
|
+
onEvent(listener) {
|
|
187
|
+
if (typeof listener !== 'function') {
|
|
188
|
+
throw new Error('listener must be a function');
|
|
189
|
+
}
|
|
190
|
+
this.eventListeners.add(listener);
|
|
191
|
+
return () => {
|
|
192
|
+
this.eventListeners.delete(listener);
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
getState() {
|
|
196
|
+
return {
|
|
197
|
+
status: this.status,
|
|
198
|
+
activeTabId: this.activeTabId,
|
|
199
|
+
viewportRevision: this.viewportRevision,
|
|
200
|
+
viewport: { ...this.viewport },
|
|
201
|
+
tabs: [...this.tabs.values()].map((tab) => this.createTabState(tab)),
|
|
202
|
+
...(this.lastError ? { lastError: { ...this.lastError } } : {}),
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
async start() {
|
|
206
|
+
return this.enqueuePublicOperation(async (signal) => {
|
|
207
|
+
if (this.status === 'running' || this.status === 'starting') {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
this.normalStopRequested = false;
|
|
211
|
+
this.lastError = undefined;
|
|
212
|
+
this.viewportRevision = 1;
|
|
213
|
+
const browserLifetimeController = new AbortController();
|
|
214
|
+
this.browserLifetimeController = browserLifetimeController;
|
|
215
|
+
this.status = 'starting';
|
|
216
|
+
this.emitState();
|
|
217
|
+
try {
|
|
218
|
+
if (signal.aborted) {
|
|
219
|
+
throw signal.reason;
|
|
220
|
+
}
|
|
221
|
+
if (browserLifetimeController.signal.aborted) {
|
|
222
|
+
throw browserLifetimeController.signal.reason;
|
|
223
|
+
}
|
|
224
|
+
this.browser = await getEnvAwareBrowserInstance({
|
|
225
|
+
forceNoSandbox: this.options.forceNoSandbox,
|
|
226
|
+
usePipe: this.options.usePipe,
|
|
227
|
+
launchOptions: {
|
|
228
|
+
...this.options.launchOptions,
|
|
229
|
+
protocol: 'cdp',
|
|
230
|
+
signal: browserLifetimeController.signal,
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
if (signal.aborted) {
|
|
234
|
+
throw signal.reason;
|
|
235
|
+
}
|
|
236
|
+
this.browserContext = this.browser.defaultBrowserContext();
|
|
237
|
+
this.browserDisconnectedListener = () => {
|
|
238
|
+
if (this.normalStopRequested || this.status === 'stopped' || this.status === 'stopping') {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const error = {
|
|
242
|
+
code: 'browser_disconnected',
|
|
243
|
+
message: 'The Chromium process disconnected',
|
|
244
|
+
fatal: true,
|
|
245
|
+
};
|
|
246
|
+
this.emitError(error);
|
|
247
|
+
void this.requestShutdown(error).catch((cleanupError) => {
|
|
248
|
+
this.emitError({
|
|
249
|
+
code: 'browser_disconnect_cleanup_failed',
|
|
250
|
+
message: normalizeErrorMessage(cleanupError),
|
|
251
|
+
fatal: true,
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
};
|
|
255
|
+
this.browser.on('disconnected', this.browserDisconnectedListener);
|
|
256
|
+
const initialPages = await this.browserContext.pages();
|
|
257
|
+
if (initialPages.length === 0) {
|
|
258
|
+
initialPages.push(await this.browserContext.newPage());
|
|
259
|
+
}
|
|
260
|
+
const initialPage = initialPages[0];
|
|
261
|
+
if (initialPage.url() !== 'about:blank') {
|
|
262
|
+
await initialPage.goto('about:blank');
|
|
263
|
+
}
|
|
264
|
+
for (const page of initialPages) {
|
|
265
|
+
await this.registerPage(page);
|
|
266
|
+
}
|
|
267
|
+
const firstTab = this.tabs.values().next().value;
|
|
268
|
+
if (!firstTab) {
|
|
269
|
+
throw new Error('Chromium did not provide an initial page');
|
|
270
|
+
}
|
|
271
|
+
this.activeTabId = firstTab.id;
|
|
272
|
+
await firstTab.page.bringToFront();
|
|
273
|
+
this.status = 'running';
|
|
274
|
+
this.emitState();
|
|
275
|
+
await this.startScreencast(firstTab);
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
if (signal.aborted || this.normalStopRequested) {
|
|
279
|
+
await this.stopInternal();
|
|
280
|
+
throw error;
|
|
281
|
+
}
|
|
282
|
+
const startError = {
|
|
283
|
+
code: 'start_failed',
|
|
284
|
+
message: normalizeErrorMessage(error),
|
|
285
|
+
fatal: true,
|
|
286
|
+
};
|
|
287
|
+
this.emitError(startError);
|
|
288
|
+
await this.stopInternal(startError);
|
|
289
|
+
throw error;
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
async stop() {
|
|
294
|
+
this.normalStopRequested = true;
|
|
295
|
+
return this.requestShutdown();
|
|
296
|
+
}
|
|
297
|
+
async acknowledgeFrame(acknowledgement) {
|
|
298
|
+
if (!acknowledgement || typeof acknowledgement !== 'object') {
|
|
299
|
+
return { accepted: false };
|
|
300
|
+
}
|
|
301
|
+
const { tabId, sequence, generation, viewportRevision } = acknowledgement;
|
|
302
|
+
if (typeof tabId !== 'string'
|
|
303
|
+
|| tabId.length < 1
|
|
304
|
+
|| tabId.length > 128
|
|
305
|
+
|| !Number.isInteger(sequence)
|
|
306
|
+
|| sequence < 1
|
|
307
|
+
|| !Number.isInteger(generation)
|
|
308
|
+
|| generation < 0
|
|
309
|
+
|| !Number.isInteger(viewportRevision)
|
|
310
|
+
|| viewportRevision < 1) {
|
|
311
|
+
return { accepted: false };
|
|
312
|
+
}
|
|
313
|
+
const outstandingFrame = this.outstandingFrames.get(sequence);
|
|
314
|
+
if (!outstandingFrame) {
|
|
315
|
+
return { accepted: false };
|
|
316
|
+
}
|
|
317
|
+
if (outstandingFrame.tabId !== tabId
|
|
318
|
+
|| outstandingFrame.generation !== generation
|
|
319
|
+
|| outstandingFrame.viewportRevision !== viewportRevision) {
|
|
320
|
+
return { accepted: false };
|
|
321
|
+
}
|
|
322
|
+
const tab = this.tabs.get(outstandingFrame.tabId);
|
|
323
|
+
if (!tab
|
|
324
|
+
|| this.activeTabId !== tab.id
|
|
325
|
+
|| tab.generation !== outstandingFrame.generation
|
|
326
|
+
|| this.viewportRevision !== outstandingFrame.viewportRevision
|
|
327
|
+
|| tab.cdpSession !== outstandingFrame.cdpSession
|
|
328
|
+
|| outstandingFrame.cdpSession.detached) {
|
|
329
|
+
this.outstandingFrames.delete(sequence);
|
|
330
|
+
await this.acknowledgeCdpFrame(outstandingFrame);
|
|
331
|
+
return { accepted: false };
|
|
332
|
+
}
|
|
333
|
+
this.outstandingFrames.delete(sequence);
|
|
334
|
+
return {
|
|
335
|
+
accepted: await this.acknowledgeCdpFrame(outstandingFrame),
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
async createTab(optionsArg = {}) {
|
|
339
|
+
const url = optionsArg.url === undefined ? undefined : this.validateUrl(optionsArg.url);
|
|
340
|
+
const activate = optionsArg.activate ?? true;
|
|
341
|
+
validateOptionalBoolean(optionsArg.activate, 'activate');
|
|
342
|
+
const timeout = this.validateTimeout(optionsArg.timeoutMs, 30000);
|
|
343
|
+
const waitUntil = this.validateWaitUntil(optionsArg.waitUntil);
|
|
344
|
+
return this.enqueuePublicOperation(async (signal) => {
|
|
345
|
+
const context = this.requireBrowserContext();
|
|
346
|
+
const previousActiveTabId = this.activeTabId;
|
|
347
|
+
let page;
|
|
348
|
+
let tab;
|
|
349
|
+
try {
|
|
350
|
+
page = await context.newPage();
|
|
351
|
+
if (signal.aborted) {
|
|
352
|
+
throw signal.reason;
|
|
353
|
+
}
|
|
354
|
+
tab = await this.registerPage(page);
|
|
355
|
+
if (url !== undefined) {
|
|
356
|
+
await this.navigateTab(tab, async () => {
|
|
357
|
+
await tab.page.goto(url, { timeout, waitUntil, signal });
|
|
358
|
+
}, signal);
|
|
359
|
+
}
|
|
360
|
+
if (activate) {
|
|
361
|
+
await this.activateTabInternal(tab.id);
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
const previousActiveTab = previousActiveTabId
|
|
365
|
+
? this.tabs.get(previousActiveTabId)
|
|
366
|
+
: undefined;
|
|
367
|
+
if (previousActiveTab && !previousActiveTab.page.isClosed()) {
|
|
368
|
+
await previousActiveTab.page.bringToFront();
|
|
369
|
+
}
|
|
370
|
+
this.emitState();
|
|
371
|
+
}
|
|
372
|
+
return this.createTabState(tab);
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
if (page) {
|
|
376
|
+
const rollbackError = await this.rollbackCreatedPage(page, tab, previousActiveTabId);
|
|
377
|
+
if (rollbackError) {
|
|
378
|
+
throw new AggregateError([error, rollbackError], 'Tab creation failed and its page could not be closed cleanly');
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
throw error;
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
async activateTab(tabId) {
|
|
386
|
+
return this.enqueuePublicOperation(async () => {
|
|
387
|
+
await this.activateTabInternal(tabId);
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
async closeTab(tabId) {
|
|
391
|
+
return this.enqueuePublicOperation(async () => {
|
|
392
|
+
const tab = this.requireTab(tabId);
|
|
393
|
+
const wasActive = this.activeTabId === tab.id;
|
|
394
|
+
if (wasActive) {
|
|
395
|
+
await this.stopScreencast(tab);
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
await this.retireOutstandingFrames((frame) => frame.tabId === tab.id);
|
|
399
|
+
}
|
|
400
|
+
try {
|
|
401
|
+
if (!tab.page.isClosed()) {
|
|
402
|
+
await tab.page.close();
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
if (wasActive
|
|
407
|
+
&& this.status === 'running'
|
|
408
|
+
&& this.activeTabId === tab.id
|
|
409
|
+
&& tab.status === 'open') {
|
|
410
|
+
await this.startScreencast(tab);
|
|
411
|
+
}
|
|
412
|
+
this.emitState();
|
|
413
|
+
throw error;
|
|
414
|
+
}
|
|
415
|
+
tab.closing = true;
|
|
416
|
+
this.removePageListeners(tab);
|
|
417
|
+
this.tabs.delete(tab.id);
|
|
418
|
+
this.tabIdsByPage.delete(tab.page);
|
|
419
|
+
if (wasActive) {
|
|
420
|
+
this.activeTabId = null;
|
|
421
|
+
await this.activateReplacementTab();
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
this.emitState();
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
async navigate(optionsArg) {
|
|
429
|
+
const url = this.validateUrl(optionsArg.url);
|
|
430
|
+
return this.enqueuePublicOperation(async (signal) => {
|
|
431
|
+
const tab = this.resolveNavigationTab(optionsArg.tabId);
|
|
432
|
+
await this.navigateTab(tab, async () => {
|
|
433
|
+
await tab.page.goto(url, this.createPuppeteerNavigationOptions(optionsArg, signal));
|
|
434
|
+
}, signal);
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
async back(optionsArg = {}) {
|
|
438
|
+
return this.enqueuePublicOperation(async (signal) => {
|
|
439
|
+
const tab = this.resolveNavigationTab(optionsArg.tabId);
|
|
440
|
+
await this.navigateTab(tab, async () => {
|
|
441
|
+
await tab.page.goBack(this.createPuppeteerNavigationOptions(optionsArg, signal));
|
|
442
|
+
}, signal);
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
async forward(optionsArg = {}) {
|
|
446
|
+
return this.enqueuePublicOperation(async (signal) => {
|
|
447
|
+
const tab = this.resolveNavigationTab(optionsArg.tabId);
|
|
448
|
+
await this.navigateTab(tab, async () => {
|
|
449
|
+
await tab.page.goForward(this.createPuppeteerNavigationOptions(optionsArg, signal));
|
|
450
|
+
}, signal);
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
async reload(optionsArg = {}) {
|
|
454
|
+
return this.enqueuePublicOperation(async (signal) => {
|
|
455
|
+
const tab = this.resolveNavigationTab(optionsArg.tabId);
|
|
456
|
+
await this.navigateTab(tab, async () => {
|
|
457
|
+
await tab.page.reload(this.createPuppeteerNavigationOptions(optionsArg, signal));
|
|
458
|
+
}, signal);
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
async setViewport(viewportArg) {
|
|
462
|
+
const viewport = normalizeViewport(viewportArg);
|
|
463
|
+
return this.enqueuePublicOperation(async (signal) => {
|
|
464
|
+
const tab = this.requireActiveTab();
|
|
465
|
+
await this.stopScreencast(tab);
|
|
466
|
+
try {
|
|
467
|
+
if (signal.aborted) {
|
|
468
|
+
throw signal.reason;
|
|
469
|
+
}
|
|
470
|
+
await tab.page.setViewport(createPuppeteerViewport(viewport));
|
|
471
|
+
this.viewport = { ...viewport };
|
|
472
|
+
this.viewportRevision += 1;
|
|
473
|
+
tab.appliedViewportRevision = this.viewportRevision;
|
|
474
|
+
this.emitState();
|
|
475
|
+
}
|
|
476
|
+
finally {
|
|
477
|
+
if (this.status === 'running' && this.activeTabId === tab.id && tab.status === 'open') {
|
|
478
|
+
await this.startScreencast(tab);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
async dispatchMouse(input) {
|
|
484
|
+
const { tab, cdpSession } = this.requireRawInputTarget(input);
|
|
485
|
+
this.validateCoordinates(input.x, input.y);
|
|
486
|
+
const type = input.type === 'move'
|
|
487
|
+
? 'mouseMoved'
|
|
488
|
+
: input.type === 'down'
|
|
489
|
+
? 'mousePressed'
|
|
490
|
+
: input.type === 'up'
|
|
491
|
+
? 'mouseReleased'
|
|
492
|
+
: undefined;
|
|
493
|
+
if (!type) {
|
|
494
|
+
throw new Error('mouse input type must be move, down, or up');
|
|
495
|
+
}
|
|
496
|
+
const allowedButtons = ['none', 'left', 'middle', 'right', 'back', 'forward'];
|
|
497
|
+
const button = input.button ?? (type === 'mouseMoved' ? 'none' : 'left');
|
|
498
|
+
if (!allowedButtons.includes(button)) {
|
|
499
|
+
throw new Error('mouse button is invalid');
|
|
500
|
+
}
|
|
501
|
+
const buttons = input.buttons === undefined
|
|
502
|
+
? undefined
|
|
503
|
+
: validateInteger(input.buttons, 'buttons', 0, 31);
|
|
504
|
+
const clickCount = input.clickCount === undefined
|
|
505
|
+
? undefined
|
|
506
|
+
: validateInteger(input.clickCount, 'clickCount', 0, 3);
|
|
507
|
+
try {
|
|
508
|
+
await cdpSession.send('Input.dispatchMouseEvent', {
|
|
509
|
+
type,
|
|
510
|
+
x: input.x,
|
|
511
|
+
y: input.y,
|
|
512
|
+
button,
|
|
513
|
+
buttons,
|
|
514
|
+
clickCount,
|
|
515
|
+
modifiers: this.createModifierMask(input.modifiers),
|
|
516
|
+
pointerType: 'mouse',
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
catch (error) {
|
|
520
|
+
this.handlePossibleCdpDisconnection(tab, cdpSession, error);
|
|
521
|
+
throw error;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
async dispatchWheel(input) {
|
|
525
|
+
const { tab, cdpSession } = this.requireRawInputTarget(input);
|
|
526
|
+
this.validateCoordinates(input.x, input.y);
|
|
527
|
+
validateFiniteNumber(input.deltaX, 'deltaX', -1000000, 1000000);
|
|
528
|
+
validateFiniteNumber(input.deltaY, 'deltaY', -1000000, 1000000);
|
|
529
|
+
try {
|
|
530
|
+
await cdpSession.send('Input.dispatchMouseEvent', {
|
|
531
|
+
type: 'mouseWheel',
|
|
532
|
+
x: input.x,
|
|
533
|
+
y: input.y,
|
|
534
|
+
deltaX: input.deltaX,
|
|
535
|
+
deltaY: input.deltaY,
|
|
536
|
+
modifiers: this.createModifierMask(input.modifiers),
|
|
537
|
+
pointerType: 'mouse',
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
catch (error) {
|
|
541
|
+
this.handlePossibleCdpDisconnection(tab, cdpSession, error);
|
|
542
|
+
throw error;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
async dispatchKey(input) {
|
|
546
|
+
const { tab, cdpSession } = this.requireRawInputTarget(input);
|
|
547
|
+
const type = input.type === 'down'
|
|
548
|
+
? 'keyDown'
|
|
549
|
+
: input.type === 'up'
|
|
550
|
+
? 'keyUp'
|
|
551
|
+
: undefined;
|
|
552
|
+
if (!type) {
|
|
553
|
+
throw new Error('key input type must be down or up');
|
|
554
|
+
}
|
|
555
|
+
const key = validateBoundedString(input.key, 'key', 1, 64);
|
|
556
|
+
const code = input.code === undefined
|
|
557
|
+
? undefined
|
|
558
|
+
: validateBoundedString(input.code, 'code', 1, 64);
|
|
559
|
+
const text = input.text === undefined
|
|
560
|
+
? undefined
|
|
561
|
+
: validateBoundedString(input.text, 'text', 0, 1024);
|
|
562
|
+
const unmodifiedText = input.unmodifiedText === undefined
|
|
563
|
+
? undefined
|
|
564
|
+
: validateBoundedString(input.unmodifiedText, 'unmodifiedText', 0, 1024);
|
|
565
|
+
const windowsVirtualKeyCode = input.windowsVirtualKeyCode === undefined
|
|
566
|
+
? undefined
|
|
567
|
+
: validateInteger(input.windowsVirtualKeyCode, 'windowsVirtualKeyCode', 0, 65535);
|
|
568
|
+
const nativeVirtualKeyCode = input.nativeVirtualKeyCode === undefined
|
|
569
|
+
? undefined
|
|
570
|
+
: validateInteger(input.nativeVirtualKeyCode, 'nativeVirtualKeyCode', 0, 65535);
|
|
571
|
+
const location = input.location === undefined
|
|
572
|
+
? undefined
|
|
573
|
+
: validateInteger(input.location, 'location', 0, 3);
|
|
574
|
+
validateOptionalBoolean(input.autoRepeat, 'autoRepeat');
|
|
575
|
+
validateOptionalBoolean(input.isKeypad, 'isKeypad');
|
|
576
|
+
try {
|
|
577
|
+
await cdpSession.send('Input.dispatchKeyEvent', {
|
|
578
|
+
type,
|
|
579
|
+
key,
|
|
580
|
+
code,
|
|
581
|
+
text,
|
|
582
|
+
unmodifiedText,
|
|
583
|
+
windowsVirtualKeyCode,
|
|
584
|
+
nativeVirtualKeyCode,
|
|
585
|
+
autoRepeat: input.autoRepeat,
|
|
586
|
+
isKeypad: input.isKeypad,
|
|
587
|
+
location,
|
|
588
|
+
modifiers: this.createModifierMask(input.modifiers),
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
catch (error) {
|
|
592
|
+
this.handlePossibleCdpDisconnection(tab, cdpSession, error);
|
|
593
|
+
throw error;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
async insertText(input) {
|
|
597
|
+
const { tab, cdpSession } = this.requireRawInputTarget(input);
|
|
598
|
+
const text = validateBoundedString(input.text, 'text', 0, maxTextLength);
|
|
599
|
+
try {
|
|
600
|
+
await cdpSession.send('Input.insertText', { text });
|
|
601
|
+
}
|
|
602
|
+
catch (error) {
|
|
603
|
+
this.handlePossibleCdpDisconnection(tab, cdpSession, error);
|
|
604
|
+
throw error;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
async captureSnapshot(optionsArg = {}) {
|
|
608
|
+
const format = optionsArg.format ?? 'jpeg';
|
|
609
|
+
if (format !== 'jpeg' && format !== 'png') {
|
|
610
|
+
throw new Error('snapshot format must be jpeg or png');
|
|
611
|
+
}
|
|
612
|
+
const quality = optionsArg.quality === undefined
|
|
613
|
+
? undefined
|
|
614
|
+
: validateInteger(optionsArg.quality, 'quality', 0, 100);
|
|
615
|
+
if (format === 'png' && quality !== undefined) {
|
|
616
|
+
throw new Error('quality is only supported for jpeg snapshots');
|
|
617
|
+
}
|
|
618
|
+
if ('fullPage' in optionsArg) {
|
|
619
|
+
throw new Error('fullPage snapshots are not supported by LiveBrowserSession');
|
|
620
|
+
}
|
|
621
|
+
return this.enqueuePublicOperation(async (signal) => {
|
|
622
|
+
const tab = this.resolveActionTab(optionsArg.tabId);
|
|
623
|
+
await this.ensureTabViewport(tab);
|
|
624
|
+
const capturedTab = this.resolveActionTab(tab.id);
|
|
625
|
+
if (signal.aborted) {
|
|
626
|
+
throw signal.reason;
|
|
627
|
+
}
|
|
628
|
+
const viewport = { ...this.viewport };
|
|
629
|
+
const viewportRevision = this.viewportRevision;
|
|
630
|
+
const data = await capturedTab.page.screenshot({
|
|
631
|
+
type: format,
|
|
632
|
+
...(format === 'jpeg' && quality !== undefined ? { quality } : {}),
|
|
633
|
+
});
|
|
634
|
+
if (signal.aborted) {
|
|
635
|
+
throw signal.reason;
|
|
636
|
+
}
|
|
637
|
+
const dimensions = readImageDimensions(data, format, {
|
|
638
|
+
width: Math.round(viewport.width * viewport.deviceScaleFactor),
|
|
639
|
+
height: Math.round(viewport.height * viewport.deviceScaleFactor),
|
|
640
|
+
});
|
|
641
|
+
return {
|
|
642
|
+
tabId: capturedTab.id,
|
|
643
|
+
viewportRevision,
|
|
644
|
+
viewport,
|
|
645
|
+
format,
|
|
646
|
+
mimeType: format === 'jpeg' ? 'image/jpeg' : 'image/png',
|
|
647
|
+
...dimensions,
|
|
648
|
+
data,
|
|
649
|
+
};
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
async observe(optionsArg = {}) {
|
|
653
|
+
const maxCharacters = optionsArg.maxCharacters === undefined
|
|
654
|
+
? 12000
|
|
655
|
+
: validateInteger(optionsArg.maxCharacters, 'maxCharacters', 256, 50000);
|
|
656
|
+
return this.enqueuePublicOperation(async (signal) => {
|
|
657
|
+
const tab = this.resolveActionTab(optionsArg.tabId);
|
|
658
|
+
await this.ensureTabViewport(tab);
|
|
659
|
+
const observedTab = this.resolveActionTab(tab.id);
|
|
660
|
+
if (signal.aborted) {
|
|
661
|
+
throw signal.reason;
|
|
662
|
+
}
|
|
663
|
+
await this.refreshTab(observedTab);
|
|
664
|
+
const accessibilitySnapshot = await observedTab.page.accessibility.snapshot({
|
|
665
|
+
interestingOnly: true,
|
|
666
|
+
});
|
|
667
|
+
if (signal.aborted) {
|
|
668
|
+
throw signal.reason;
|
|
669
|
+
}
|
|
670
|
+
const header = [
|
|
671
|
+
`Tab: ${observedTab.id}`,
|
|
672
|
+
`Status: ${observedTab.status}`,
|
|
673
|
+
`Title: ${observedTab.title}`,
|
|
674
|
+
`URL: ${observedTab.url}`,
|
|
675
|
+
'Accessibility:',
|
|
676
|
+
];
|
|
677
|
+
const lines = [...header];
|
|
678
|
+
let reachedTraversalLimit = false;
|
|
679
|
+
const appendNode = (node, depth) => {
|
|
680
|
+
if (lines.join('\n').length >= maxCharacters) {
|
|
681
|
+
reachedTraversalLimit = true;
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
const details = [node.role];
|
|
685
|
+
if (node.name) {
|
|
686
|
+
details.push(`"${truncate(node.name, 512)}"`);
|
|
687
|
+
}
|
|
688
|
+
if (node.value !== undefined) {
|
|
689
|
+
details.push(`value="${truncate(String(node.value), 512)}"`);
|
|
690
|
+
}
|
|
691
|
+
for (const property of [
|
|
692
|
+
'disabled',
|
|
693
|
+
'expanded',
|
|
694
|
+
'focused',
|
|
695
|
+
'readonly',
|
|
696
|
+
'required',
|
|
697
|
+
'selected',
|
|
698
|
+
'checked',
|
|
699
|
+
'pressed',
|
|
700
|
+
]) {
|
|
701
|
+
const value = node[property];
|
|
702
|
+
if (value !== undefined && value !== false) {
|
|
703
|
+
details.push(`${property}=${String(value)}`);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
lines.push(`${' '.repeat(Math.min(depth, 20))}- ${details.join(' ')}`);
|
|
707
|
+
for (const child of node.children ?? []) {
|
|
708
|
+
appendNode(child, depth + 1);
|
|
709
|
+
if (reachedTraversalLimit) {
|
|
710
|
+
break;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
if (accessibilitySnapshot) {
|
|
715
|
+
appendNode(accessibilitySnapshot, 0);
|
|
716
|
+
}
|
|
717
|
+
else {
|
|
718
|
+
lines.push('- No accessibility nodes');
|
|
719
|
+
}
|
|
720
|
+
const unboundedText = lines.join('\n');
|
|
721
|
+
const truncatedText = unboundedText.length > maxCharacters
|
|
722
|
+
? unboundedText.slice(0, maxCharacters)
|
|
723
|
+
: unboundedText;
|
|
724
|
+
const state = this.getState();
|
|
725
|
+
return {
|
|
726
|
+
tabId: observedTab.id,
|
|
727
|
+
url: observedTab.url,
|
|
728
|
+
title: observedTab.title,
|
|
729
|
+
tab: this.createTabState(observedTab),
|
|
730
|
+
state,
|
|
731
|
+
text: truncatedText,
|
|
732
|
+
truncated: reachedTraversalLimit || unboundedText.length > maxCharacters,
|
|
733
|
+
};
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
async click(optionsArg) {
|
|
737
|
+
const selector = validateBoundedString(optionsArg.selector, 'selector', 1, maxSelectorLength);
|
|
738
|
+
const timeout = this.validateTimeout(optionsArg.timeoutMs);
|
|
739
|
+
const allowedButtons = ['left', 'middle', 'right'];
|
|
740
|
+
if (optionsArg.button !== undefined && !allowedButtons.includes(optionsArg.button)) {
|
|
741
|
+
throw new Error('click button is invalid');
|
|
742
|
+
}
|
|
743
|
+
const clickCount = optionsArg.clickCount === undefined
|
|
744
|
+
? undefined
|
|
745
|
+
: validateInteger(optionsArg.clickCount, 'clickCount', 1, 3);
|
|
746
|
+
return this.enqueuePublicOperation(async (signal) => {
|
|
747
|
+
const tab = this.requireSemanticActionTarget(optionsArg);
|
|
748
|
+
await this.ensureTabViewport(tab);
|
|
749
|
+
const actionTab = this.requireSemanticActionTarget(optionsArg);
|
|
750
|
+
await actionTab.page.locator(selector).setTimeout(timeout).click({
|
|
751
|
+
button: optionsArg.button,
|
|
752
|
+
count: clickCount,
|
|
753
|
+
signal,
|
|
754
|
+
});
|
|
755
|
+
await this.refreshTab(actionTab);
|
|
756
|
+
this.emitState();
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
async fill(optionsArg) {
|
|
760
|
+
const selector = validateBoundedString(optionsArg.selector, 'selector', 1, maxSelectorLength);
|
|
761
|
+
const text = validateBoundedString(optionsArg.text, 'text', 0, maxTextLength);
|
|
762
|
+
const timeout = this.validateTimeout(optionsArg.timeoutMs);
|
|
763
|
+
return this.enqueuePublicOperation(async (signal) => {
|
|
764
|
+
const tab = this.requireSemanticActionTarget(optionsArg);
|
|
765
|
+
await this.ensureTabViewport(tab);
|
|
766
|
+
const actionTab = this.requireSemanticActionTarget(optionsArg);
|
|
767
|
+
await actionTab.page.locator(selector).setTimeout(timeout).fill(text, { signal });
|
|
768
|
+
await this.refreshTab(actionTab);
|
|
769
|
+
this.emitState();
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
async press(optionsArg) {
|
|
773
|
+
const selector = validateBoundedString(optionsArg.selector, 'selector', 1, maxSelectorLength);
|
|
774
|
+
const key = validateBoundedString(optionsArg.key, 'key', 1, 64);
|
|
775
|
+
const timeout = this.validateTimeout(optionsArg.timeoutMs);
|
|
776
|
+
return this.enqueuePublicOperation(async (signal) => {
|
|
777
|
+
const tab = this.requireSemanticActionTarget(optionsArg);
|
|
778
|
+
await this.ensureTabViewport(tab);
|
|
779
|
+
const actionTab = this.requireSemanticActionTarget(optionsArg);
|
|
780
|
+
const element = await actionTab.page.waitForSelector(selector, {
|
|
781
|
+
visible: true,
|
|
782
|
+
timeout,
|
|
783
|
+
signal,
|
|
784
|
+
});
|
|
785
|
+
if (!element) {
|
|
786
|
+
throw new Error(`No visible element matched selector: ${selector}`);
|
|
787
|
+
}
|
|
788
|
+
try {
|
|
789
|
+
await element.press(key);
|
|
790
|
+
}
|
|
791
|
+
finally {
|
|
792
|
+
await element.dispose();
|
|
793
|
+
}
|
|
794
|
+
await this.refreshTab(actionTab);
|
|
795
|
+
this.emitState();
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
enqueuePublicOperation(operation) {
|
|
799
|
+
if (this.status === 'stopping'
|
|
800
|
+
|| this.normalStopRequested
|
|
801
|
+
|| (this.status === 'stopped' && this.operationRunning)) {
|
|
802
|
+
return Promise.reject(new Error('LiveBrowserSession is stopping'));
|
|
803
|
+
}
|
|
804
|
+
if (this.admittedPublicOperations >= maxQueuedPublicOperations) {
|
|
805
|
+
return Promise.reject(new Error('LiveBrowserSession operation queue is full'));
|
|
806
|
+
}
|
|
807
|
+
this.admittedPublicOperations += 1;
|
|
808
|
+
return this.enqueueQueuedOperation('public', operation);
|
|
809
|
+
}
|
|
810
|
+
enqueueInternalOperation(operation, priority = false) {
|
|
811
|
+
if (this.status === 'stopped' || this.status === 'stopping') {
|
|
812
|
+
return Promise.reject(new Error('LiveBrowserSession is stopping'));
|
|
813
|
+
}
|
|
814
|
+
this.admittedInternalOperations += 1;
|
|
815
|
+
return this.enqueueQueuedOperation('internal', operation, priority);
|
|
816
|
+
}
|
|
817
|
+
enqueueQueuedOperation(kind, operation, priority = false) {
|
|
818
|
+
return new Promise((resolve, reject) => {
|
|
819
|
+
const queuedOperation = {
|
|
820
|
+
kind,
|
|
821
|
+
controller: new AbortController(),
|
|
822
|
+
run: operation,
|
|
823
|
+
resolve: (value) => resolve(value),
|
|
824
|
+
reject,
|
|
825
|
+
};
|
|
826
|
+
if (priority) {
|
|
827
|
+
this.operationQueue.unshift(queuedOperation);
|
|
828
|
+
}
|
|
829
|
+
else {
|
|
830
|
+
this.operationQueue.push(queuedOperation);
|
|
831
|
+
}
|
|
832
|
+
this.drainOperationQueue();
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
drainOperationQueue() {
|
|
836
|
+
if (this.operationRunning) {
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
const queuedOperation = this.operationQueue.shift();
|
|
840
|
+
if (!queuedOperation) {
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
this.operationRunning = true;
|
|
844
|
+
this.activeOperation = queuedOperation;
|
|
845
|
+
void this.executeQueuedOperation(queuedOperation).catch((error) => {
|
|
846
|
+
this.operationRunning = false;
|
|
847
|
+
this.activeOperation = undefined;
|
|
848
|
+
this.emitError({
|
|
849
|
+
code: 'operation_scheduler_failed',
|
|
850
|
+
message: normalizeErrorMessage(error),
|
|
851
|
+
fatal: true,
|
|
852
|
+
});
|
|
853
|
+
this.drainOperationQueue();
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
async executeQueuedOperation(queuedOperation) {
|
|
857
|
+
try {
|
|
858
|
+
if (queuedOperation.controller.signal.aborted) {
|
|
859
|
+
throw queuedOperation.controller.signal.reason;
|
|
860
|
+
}
|
|
861
|
+
queuedOperation.resolve(await queuedOperation.run(queuedOperation.controller.signal));
|
|
862
|
+
}
|
|
863
|
+
catch (error) {
|
|
864
|
+
queuedOperation.reject(error);
|
|
865
|
+
}
|
|
866
|
+
finally {
|
|
867
|
+
if (queuedOperation.kind === 'public') {
|
|
868
|
+
this.admittedPublicOperations -= 1;
|
|
869
|
+
}
|
|
870
|
+
else if (queuedOperation.kind === 'internal') {
|
|
871
|
+
this.admittedInternalOperations -= 1;
|
|
872
|
+
}
|
|
873
|
+
if (this.activeOperation === queuedOperation) {
|
|
874
|
+
this.activeOperation = undefined;
|
|
875
|
+
}
|
|
876
|
+
this.operationRunning = false;
|
|
877
|
+
if (this.status === 'stopped'
|
|
878
|
+
&& !this.operationQueue.some((operation) => operation.kind === 'shutdown')) {
|
|
879
|
+
this.normalStopRequested = false;
|
|
880
|
+
}
|
|
881
|
+
this.drainOperationQueue();
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
cancelQueuedOperations(error) {
|
|
885
|
+
for (const queuedOperation of this.operationQueue.splice(0)) {
|
|
886
|
+
queuedOperation.controller.abort(error);
|
|
887
|
+
if (queuedOperation.kind === 'public') {
|
|
888
|
+
this.admittedPublicOperations -= 1;
|
|
889
|
+
}
|
|
890
|
+
else if (queuedOperation.kind === 'internal') {
|
|
891
|
+
this.admittedInternalOperations -= 1;
|
|
892
|
+
}
|
|
893
|
+
queuedOperation.reject(error);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
beginShutdown(abortActiveOperation) {
|
|
897
|
+
if (this.status !== 'stopped' && this.status !== 'stopping') {
|
|
898
|
+
this.status = 'stopping';
|
|
899
|
+
this.emitState();
|
|
900
|
+
}
|
|
901
|
+
const shutdownError = new Error('LiveBrowserSession is stopping');
|
|
902
|
+
if (abortActiveOperation
|
|
903
|
+
&& this.activeOperation
|
|
904
|
+
&& this.activeOperation.kind !== 'shutdown') {
|
|
905
|
+
this.activeOperation.controller.abort(shutdownError);
|
|
906
|
+
}
|
|
907
|
+
if (this.browserLifetimeController && !this.browserLifetimeController.signal.aborted) {
|
|
908
|
+
this.browserLifetimeController.abort(shutdownError);
|
|
909
|
+
}
|
|
910
|
+
this.cancelQueuedOperations(shutdownError);
|
|
911
|
+
}
|
|
912
|
+
requestShutdown(error) {
|
|
913
|
+
if (this.status === 'stopped') {
|
|
914
|
+
return Promise.resolve();
|
|
915
|
+
}
|
|
916
|
+
if (this.shutdownPromise) {
|
|
917
|
+
return this.shutdownPromise;
|
|
918
|
+
}
|
|
919
|
+
this.beginShutdown(true);
|
|
920
|
+
const shutdownPromise = this.enqueueQueuedOperation('shutdown', async () => this.stopInternal(error), true);
|
|
921
|
+
this.shutdownPromise = shutdownPromise;
|
|
922
|
+
void shutdownPromise.then(() => {
|
|
923
|
+
if (this.shutdownPromise === shutdownPromise) {
|
|
924
|
+
this.shutdownPromise = undefined;
|
|
925
|
+
}
|
|
926
|
+
}, () => {
|
|
927
|
+
if (this.shutdownPromise === shutdownPromise) {
|
|
928
|
+
this.shutdownPromise = undefined;
|
|
929
|
+
}
|
|
930
|
+
});
|
|
931
|
+
return shutdownPromise;
|
|
932
|
+
}
|
|
933
|
+
scheduleOperation(operation, errorCode, tabId, priority = false) {
|
|
934
|
+
if (this.admittedInternalOperations >= maxQueuedInternalOperations) {
|
|
935
|
+
const queueError = new Error('LiveBrowserSession internal operation queue is full');
|
|
936
|
+
const liveBrowserError = {
|
|
937
|
+
code: 'internal_operation_queue_full',
|
|
938
|
+
message: queueError.message,
|
|
939
|
+
fatal: priority,
|
|
940
|
+
...(tabId ? { tabId } : {}),
|
|
941
|
+
};
|
|
942
|
+
this.emitError(liveBrowserError);
|
|
943
|
+
if (priority) {
|
|
944
|
+
void this.requestShutdown(liveBrowserError).catch((error) => {
|
|
945
|
+
this.emitError({
|
|
946
|
+
code: 'queue_overflow_shutdown_failed',
|
|
947
|
+
message: normalizeErrorMessage(error),
|
|
948
|
+
fatal: true,
|
|
949
|
+
});
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
return false;
|
|
953
|
+
}
|
|
954
|
+
void this.enqueueInternalOperation(operation, priority).catch((error) => {
|
|
955
|
+
if (this.status === 'stopped'
|
|
956
|
+
|| this.status === 'stopping'
|
|
957
|
+
|| this.normalStopRequested) {
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
this.emitError({
|
|
961
|
+
code: errorCode,
|
|
962
|
+
message: normalizeErrorMessage(error),
|
|
963
|
+
fatal: false,
|
|
964
|
+
...(tabId ? { tabId } : {}),
|
|
965
|
+
});
|
|
966
|
+
});
|
|
967
|
+
return true;
|
|
968
|
+
}
|
|
969
|
+
emitEvent(event) {
|
|
970
|
+
for (const listener of [...this.eventListeners]) {
|
|
971
|
+
try {
|
|
972
|
+
listener(event);
|
|
973
|
+
}
|
|
974
|
+
catch {
|
|
975
|
+
// A consumer listener must not interrupt browser lifecycle cleanup.
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
emitState() {
|
|
980
|
+
this.emitEvent({
|
|
981
|
+
type: 'state',
|
|
982
|
+
state: this.getState(),
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
emitError(error) {
|
|
986
|
+
if (error.fatal) {
|
|
987
|
+
this.lastError = { ...error };
|
|
988
|
+
}
|
|
989
|
+
this.emitEvent({
|
|
990
|
+
type: 'error',
|
|
991
|
+
error: { ...error },
|
|
992
|
+
});
|
|
993
|
+
this.emitState();
|
|
994
|
+
}
|
|
995
|
+
createTabState(tab) {
|
|
996
|
+
return {
|
|
997
|
+
id: tab.id,
|
|
998
|
+
url: tab.url,
|
|
999
|
+
title: tab.title,
|
|
1000
|
+
active: this.activeTabId === tab.id,
|
|
1001
|
+
status: tab.status,
|
|
1002
|
+
generation: tab.generation,
|
|
1003
|
+
appliedViewportRevision: tab.appliedViewportRevision,
|
|
1004
|
+
streaming: tab.streaming,
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
async stopInternal(error) {
|
|
1008
|
+
if (this.status === 'stopped') {
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
1011
|
+
this.status = 'stopping';
|
|
1012
|
+
if (error) {
|
|
1013
|
+
this.lastError = { ...error };
|
|
1014
|
+
}
|
|
1015
|
+
this.emitState();
|
|
1016
|
+
if (this.browserLifetimeController && !this.browserLifetimeController.signal.aborted) {
|
|
1017
|
+
this.browserLifetimeController.abort(new Error('LiveBrowserSession is stopping'));
|
|
1018
|
+
}
|
|
1019
|
+
const browser = this.browser;
|
|
1020
|
+
if (browser && this.browserDisconnectedListener) {
|
|
1021
|
+
browser.off('disconnected', this.browserDisconnectedListener);
|
|
1022
|
+
}
|
|
1023
|
+
this.browserDisconnectedListener = undefined;
|
|
1024
|
+
const shutdownErrors = [];
|
|
1025
|
+
for (const tab of [...this.tabs.values()]) {
|
|
1026
|
+
tab.closing = true;
|
|
1027
|
+
try {
|
|
1028
|
+
await this.stopScreencast(tab);
|
|
1029
|
+
}
|
|
1030
|
+
catch (cleanupError) {
|
|
1031
|
+
shutdownErrors.push(cleanupError);
|
|
1032
|
+
}
|
|
1033
|
+
try {
|
|
1034
|
+
this.removePageListeners(tab);
|
|
1035
|
+
}
|
|
1036
|
+
catch (cleanupError) {
|
|
1037
|
+
shutdownErrors.push(cleanupError);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
try {
|
|
1041
|
+
await this.retireOutstandingFrames(() => true);
|
|
1042
|
+
}
|
|
1043
|
+
catch (cleanupError) {
|
|
1044
|
+
shutdownErrors.push(cleanupError);
|
|
1045
|
+
}
|
|
1046
|
+
if (browser) {
|
|
1047
|
+
try {
|
|
1048
|
+
await browser.close();
|
|
1049
|
+
}
|
|
1050
|
+
catch (closeError) {
|
|
1051
|
+
shutdownErrors.push(closeError);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
for (const tab of this.tabs.values()) {
|
|
1055
|
+
this.tabIdsByPage.delete(tab.page);
|
|
1056
|
+
}
|
|
1057
|
+
this.tabs.clear();
|
|
1058
|
+
this.outstandingFrames.clear();
|
|
1059
|
+
this.browser = undefined;
|
|
1060
|
+
this.browserContext = undefined;
|
|
1061
|
+
this.browserLifetimeController = undefined;
|
|
1062
|
+
this.activeTabId = null;
|
|
1063
|
+
this.status = 'stopped';
|
|
1064
|
+
this.emitState();
|
|
1065
|
+
if (shutdownErrors.length > 0 && !error) {
|
|
1066
|
+
throw new AggregateError(shutdownErrors, 'LiveBrowserSession shutdown was incomplete');
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
requireBrowserContext() {
|
|
1070
|
+
if (this.status !== 'running' || !this.browserContext) {
|
|
1071
|
+
throw new Error('LiveBrowserSession is not running');
|
|
1072
|
+
}
|
|
1073
|
+
return this.browserContext;
|
|
1074
|
+
}
|
|
1075
|
+
requireTab(tabId) {
|
|
1076
|
+
validateBoundedString(tabId, 'tabId', 1, 128);
|
|
1077
|
+
const tab = this.tabs.get(tabId);
|
|
1078
|
+
if (!tab) {
|
|
1079
|
+
throw new Error(`Unknown tab: ${tabId}`);
|
|
1080
|
+
}
|
|
1081
|
+
return tab;
|
|
1082
|
+
}
|
|
1083
|
+
requireActiveTab() {
|
|
1084
|
+
if (this.status !== 'running' || !this.activeTabId) {
|
|
1085
|
+
throw new Error('LiveBrowserSession has no active tab');
|
|
1086
|
+
}
|
|
1087
|
+
const tab = this.requireTab(this.activeTabId);
|
|
1088
|
+
if (tab.status !== 'open' || tab.page.isClosed()) {
|
|
1089
|
+
throw new Error(`Active tab is not available: ${tab.id}`);
|
|
1090
|
+
}
|
|
1091
|
+
return tab;
|
|
1092
|
+
}
|
|
1093
|
+
resolveActionTab(tabId) {
|
|
1094
|
+
if (this.status !== 'running') {
|
|
1095
|
+
throw new Error('LiveBrowserSession is not running');
|
|
1096
|
+
}
|
|
1097
|
+
const tab = tabId ? this.requireTab(tabId) : this.requireActiveTab();
|
|
1098
|
+
if (tab.status !== 'open' || tab.page.isClosed()) {
|
|
1099
|
+
throw new Error(`Tab is not available: ${tab.id}`);
|
|
1100
|
+
}
|
|
1101
|
+
return tab;
|
|
1102
|
+
}
|
|
1103
|
+
resolveNavigationTab(tabId) {
|
|
1104
|
+
return this.resolveActionTab(tabId);
|
|
1105
|
+
}
|
|
1106
|
+
async ensureTabViewport(tab) {
|
|
1107
|
+
if (tab.appliedViewportRevision === this.viewportRevision) {
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1110
|
+
const shouldRestartScreencast = this.activeTabId === tab.id && tab.streaming;
|
|
1111
|
+
if (shouldRestartScreencast) {
|
|
1112
|
+
await this.stopScreencast(tab);
|
|
1113
|
+
}
|
|
1114
|
+
try {
|
|
1115
|
+
await tab.page.setViewport(createPuppeteerViewport(this.viewport));
|
|
1116
|
+
tab.appliedViewportRevision = this.viewportRevision;
|
|
1117
|
+
}
|
|
1118
|
+
finally {
|
|
1119
|
+
if (shouldRestartScreencast
|
|
1120
|
+
&& this.status === 'running'
|
|
1121
|
+
&& this.activeTabId === tab.id
|
|
1122
|
+
&& tab.status === 'open'
|
|
1123
|
+
&& !tab.page.isClosed()) {
|
|
1124
|
+
await this.startScreencast(tab);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
async registerPage(page) {
|
|
1129
|
+
const existingTabId = this.tabIdsByPage.get(page);
|
|
1130
|
+
if (existingTabId) {
|
|
1131
|
+
return this.requireTab(existingTabId);
|
|
1132
|
+
}
|
|
1133
|
+
if (page.isClosed()) {
|
|
1134
|
+
throw new Error('Cannot register a closed page');
|
|
1135
|
+
}
|
|
1136
|
+
const tab = {
|
|
1137
|
+
id: `tab-${++this.tabSequence}`,
|
|
1138
|
+
page,
|
|
1139
|
+
url: truncate(page.url(), 4096),
|
|
1140
|
+
title: '',
|
|
1141
|
+
status: 'open',
|
|
1142
|
+
generation: 0,
|
|
1143
|
+
appliedViewportRevision: 0,
|
|
1144
|
+
streaming: false,
|
|
1145
|
+
streamInvalidated: true,
|
|
1146
|
+
navigationInProgress: false,
|
|
1147
|
+
closing: false,
|
|
1148
|
+
stateUpdateQueued: false,
|
|
1149
|
+
stateUpdatePending: false,
|
|
1150
|
+
navigationResetPending: false,
|
|
1151
|
+
removeListeners: [],
|
|
1152
|
+
};
|
|
1153
|
+
this.tabs.set(tab.id, tab);
|
|
1154
|
+
this.tabIdsByPage.set(page, tab.id);
|
|
1155
|
+
try {
|
|
1156
|
+
await this.ensureTabViewport(tab);
|
|
1157
|
+
await this.refreshTab(tab);
|
|
1158
|
+
const onPopup = (popup) => {
|
|
1159
|
+
if (!popup
|
|
1160
|
+
|| this.normalStopRequested
|
|
1161
|
+
|| this.status === 'stopped'
|
|
1162
|
+
|| this.status === 'stopping') {
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
const popupWasScheduled = this.scheduleOperation(async () => {
|
|
1166
|
+
if (popup.isClosed()) {
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
const previousActiveTabId = this.activeTabId;
|
|
1170
|
+
let popupTab;
|
|
1171
|
+
try {
|
|
1172
|
+
popupTab = await this.registerPage(popup);
|
|
1173
|
+
await this.activateTabInternal(popupTab.id);
|
|
1174
|
+
}
|
|
1175
|
+
catch (error) {
|
|
1176
|
+
const rollbackError = await this.rollbackCreatedPage(popup, popupTab, previousActiveTabId);
|
|
1177
|
+
if (rollbackError) {
|
|
1178
|
+
throw new AggregateError([error, rollbackError], 'Popup registration rollback failed');
|
|
1179
|
+
}
|
|
1180
|
+
throw error;
|
|
1181
|
+
}
|
|
1182
|
+
}, 'popup_registration_failed', tab.id);
|
|
1183
|
+
if (!popupWasScheduled) {
|
|
1184
|
+
const popupError = {
|
|
1185
|
+
code: 'popup_registration_capacity_exceeded',
|
|
1186
|
+
message: 'A popup could not be admitted to the internal operation queue',
|
|
1187
|
+
fatal: true,
|
|
1188
|
+
tabId: tab.id,
|
|
1189
|
+
};
|
|
1190
|
+
this.emitError(popupError);
|
|
1191
|
+
void this.requestShutdown(popupError).catch((shutdownError) => {
|
|
1192
|
+
this.emitError({
|
|
1193
|
+
code: 'untracked_popup_shutdown_failed',
|
|
1194
|
+
message: normalizeErrorMessage(shutdownError),
|
|
1195
|
+
fatal: true,
|
|
1196
|
+
tabId: tab.id,
|
|
1197
|
+
});
|
|
1198
|
+
});
|
|
1199
|
+
}
|
|
1200
|
+
};
|
|
1201
|
+
const onFrameNavigated = (frame) => {
|
|
1202
|
+
if (frame !== page.mainFrame() || tab.closing) {
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
const navigationReset = !tab.navigationInProgress;
|
|
1206
|
+
if (navigationReset) {
|
|
1207
|
+
tab.streamInvalidated = true;
|
|
1208
|
+
this.retireFramesForTabInBackground(tab.id);
|
|
1209
|
+
}
|
|
1210
|
+
this.requestTabStateUpdate(tab, navigationReset);
|
|
1211
|
+
};
|
|
1212
|
+
const onLoad = () => {
|
|
1213
|
+
this.requestTabStateUpdate(tab, false);
|
|
1214
|
+
};
|
|
1215
|
+
const onClose = () => {
|
|
1216
|
+
tab.streamInvalidated = true;
|
|
1217
|
+
this.retireFramesForTabInBackground(tab.id);
|
|
1218
|
+
if (tab.closing || this.normalStopRequested) {
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
this.scheduleOperation(async () => {
|
|
1222
|
+
await this.handleUnexpectedPageClose(tab);
|
|
1223
|
+
}, 'page_close_cleanup_failed', tab.id, true);
|
|
1224
|
+
};
|
|
1225
|
+
const onCrash = (error) => {
|
|
1226
|
+
tab.streamInvalidated = true;
|
|
1227
|
+
this.retireFramesForTabInBackground(tab.id);
|
|
1228
|
+
if (tab.closing || this.normalStopRequested) {
|
|
1229
|
+
return;
|
|
1230
|
+
}
|
|
1231
|
+
this.scheduleOperation(async () => {
|
|
1232
|
+
if (!this.tabs.has(tab.id) || tab.status === 'crashed') {
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
await this.stopScreencast(tab);
|
|
1236
|
+
tab.status = 'crashed';
|
|
1237
|
+
const wasActive = this.activeTabId === tab.id;
|
|
1238
|
+
if (wasActive) {
|
|
1239
|
+
this.activeTabId = null;
|
|
1240
|
+
}
|
|
1241
|
+
this.emitError({
|
|
1242
|
+
code: 'page_crashed',
|
|
1243
|
+
message: normalizeErrorMessage(error),
|
|
1244
|
+
fatal: false,
|
|
1245
|
+
tabId: tab.id,
|
|
1246
|
+
});
|
|
1247
|
+
if (wasActive) {
|
|
1248
|
+
await this.activateReplacementTab();
|
|
1249
|
+
}
|
|
1250
|
+
}, 'page_crash_cleanup_failed', tab.id, true);
|
|
1251
|
+
};
|
|
1252
|
+
const onPageError = (error) => {
|
|
1253
|
+
if (tab.closing || this.normalStopRequested) {
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
this.emitError({
|
|
1257
|
+
code: 'page_error',
|
|
1258
|
+
message: normalizeErrorMessage(error),
|
|
1259
|
+
fatal: false,
|
|
1260
|
+
tabId: tab.id,
|
|
1261
|
+
});
|
|
1262
|
+
};
|
|
1263
|
+
page.on('popup', onPopup);
|
|
1264
|
+
page.on('framenavigated', onFrameNavigated);
|
|
1265
|
+
page.on('load', onLoad);
|
|
1266
|
+
page.on('close', onClose);
|
|
1267
|
+
page.on('error', onCrash);
|
|
1268
|
+
page.on('pageerror', onPageError);
|
|
1269
|
+
tab.removeListeners.push(() => page.off('popup', onPopup), () => page.off('framenavigated', onFrameNavigated), () => page.off('load', onLoad), () => page.off('close', onClose), () => page.off('error', onCrash), () => page.off('pageerror', onPageError));
|
|
1270
|
+
return tab;
|
|
1271
|
+
}
|
|
1272
|
+
catch (error) {
|
|
1273
|
+
this.removePageListeners(tab);
|
|
1274
|
+
this.tabs.delete(tab.id);
|
|
1275
|
+
this.tabIdsByPage.delete(page);
|
|
1276
|
+
throw error;
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
removePageListeners(tab) {
|
|
1280
|
+
for (const removeListener of tab.removeListeners.splice(0)) {
|
|
1281
|
+
removeListener();
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
retireFramesForTabInBackground(tabId) {
|
|
1285
|
+
void this.retireOutstandingFrames((frame) => frame.tabId === tabId).catch((error) => {
|
|
1286
|
+
if (this.status === 'running' && !this.normalStopRequested) {
|
|
1287
|
+
this.emitError({
|
|
1288
|
+
code: 'frame_retirement_failed',
|
|
1289
|
+
message: normalizeErrorMessage(error),
|
|
1290
|
+
fatal: false,
|
|
1291
|
+
tabId,
|
|
1292
|
+
});
|
|
1293
|
+
}
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
requestTabStateUpdate(tab, navigationReset) {
|
|
1297
|
+
if (!this.tabs.has(tab.id) || tab.closing) {
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
tab.stateUpdatePending = true;
|
|
1301
|
+
tab.navigationResetPending ||= navigationReset;
|
|
1302
|
+
if (tab.stateUpdateQueued) {
|
|
1303
|
+
return;
|
|
1304
|
+
}
|
|
1305
|
+
tab.stateUpdateQueued = true;
|
|
1306
|
+
const wasScheduled = this.scheduleOperation(async () => {
|
|
1307
|
+
try {
|
|
1308
|
+
const shouldResetNavigation = tab.navigationResetPending;
|
|
1309
|
+
tab.stateUpdatePending = false;
|
|
1310
|
+
tab.navigationResetPending = false;
|
|
1311
|
+
if (!this.tabs.has(tab.id) || tab.closing) {
|
|
1312
|
+
return;
|
|
1313
|
+
}
|
|
1314
|
+
if (shouldResetNavigation && this.activeTabId === tab.id) {
|
|
1315
|
+
await this.stopScreencast(tab);
|
|
1316
|
+
}
|
|
1317
|
+
await this.refreshTab(tab);
|
|
1318
|
+
this.emitState();
|
|
1319
|
+
if (shouldResetNavigation
|
|
1320
|
+
&& this.activeTabId === tab.id
|
|
1321
|
+
&& this.status === 'running'
|
|
1322
|
+
&& tab.status === 'open') {
|
|
1323
|
+
await this.startScreencast(tab);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
finally {
|
|
1327
|
+
tab.stateUpdateQueued = false;
|
|
1328
|
+
if (tab.stateUpdatePending
|
|
1329
|
+
&& this.tabs.has(tab.id)
|
|
1330
|
+
&& this.status === 'running'
|
|
1331
|
+
&& !tab.closing) {
|
|
1332
|
+
this.requestTabStateUpdate(tab, false);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
}, 'page_state_update_failed', tab.id);
|
|
1336
|
+
if (!wasScheduled) {
|
|
1337
|
+
tab.stateUpdateQueued = false;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
async rollbackCreatedPage(page, tab, previousActiveTabId) {
|
|
1341
|
+
const rollbackErrors = [];
|
|
1342
|
+
if (tab) {
|
|
1343
|
+
try {
|
|
1344
|
+
await this.stopScreencast(tab);
|
|
1345
|
+
}
|
|
1346
|
+
catch (error) {
|
|
1347
|
+
rollbackErrors.push(error);
|
|
1348
|
+
}
|
|
1349
|
+
tab.closing = true;
|
|
1350
|
+
}
|
|
1351
|
+
try {
|
|
1352
|
+
if (!page.isClosed()) {
|
|
1353
|
+
await page.close();
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
catch (error) {
|
|
1357
|
+
rollbackErrors.push(error);
|
|
1358
|
+
}
|
|
1359
|
+
const pageClosed = page.isClosed();
|
|
1360
|
+
if (tab) {
|
|
1361
|
+
if (pageClosed) {
|
|
1362
|
+
this.removePageListeners(tab);
|
|
1363
|
+
this.tabs.delete(tab.id);
|
|
1364
|
+
this.tabIdsByPage.delete(tab.page);
|
|
1365
|
+
}
|
|
1366
|
+
else {
|
|
1367
|
+
tab.closing = false;
|
|
1368
|
+
try {
|
|
1369
|
+
await this.refreshTab(tab);
|
|
1370
|
+
}
|
|
1371
|
+
catch (error) {
|
|
1372
|
+
rollbackErrors.push(error);
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
else {
|
|
1377
|
+
this.tabIdsByPage.delete(page);
|
|
1378
|
+
if (!pageClosed) {
|
|
1379
|
+
const rollbackError = {
|
|
1380
|
+
code: 'untracked_page_rollback_failed',
|
|
1381
|
+
message: 'A failed page registration could not close its Chromium page',
|
|
1382
|
+
fatal: true,
|
|
1383
|
+
};
|
|
1384
|
+
if (!this.normalStopRequested && this.status === 'running') {
|
|
1385
|
+
this.emitError(rollbackError);
|
|
1386
|
+
}
|
|
1387
|
+
this.normalStopRequested = true;
|
|
1388
|
+
this.beginShutdown(false);
|
|
1389
|
+
try {
|
|
1390
|
+
await this.stopInternal();
|
|
1391
|
+
}
|
|
1392
|
+
catch (error) {
|
|
1393
|
+
rollbackErrors.push(error);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
const previousActiveTab = previousActiveTabId
|
|
1398
|
+
? this.tabs.get(previousActiveTabId)
|
|
1399
|
+
: undefined;
|
|
1400
|
+
this.activeTabId = previousActiveTab?.id ?? null;
|
|
1401
|
+
if (previousActiveTab
|
|
1402
|
+
&& previousActiveTab.status === 'open'
|
|
1403
|
+
&& !previousActiveTab.page.isClosed()) {
|
|
1404
|
+
try {
|
|
1405
|
+
await this.ensureTabViewport(previousActiveTab);
|
|
1406
|
+
await previousActiveTab.page.bringToFront();
|
|
1407
|
+
if (this.status === 'running' && !previousActiveTab.streaming) {
|
|
1408
|
+
await this.startScreencast(previousActiveTab);
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
catch (error) {
|
|
1412
|
+
rollbackErrors.push(error);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
this.emitState();
|
|
1416
|
+
if (rollbackErrors.length === 0) {
|
|
1417
|
+
return undefined;
|
|
1418
|
+
}
|
|
1419
|
+
return new AggregateError(rollbackErrors, 'Failed to roll back a new tab');
|
|
1420
|
+
}
|
|
1421
|
+
async handleUnexpectedPageClose(tab) {
|
|
1422
|
+
if (!this.tabs.has(tab.id)) {
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1425
|
+
await this.stopScreencast(tab);
|
|
1426
|
+
this.removePageListeners(tab);
|
|
1427
|
+
this.tabs.delete(tab.id);
|
|
1428
|
+
this.tabIdsByPage.delete(tab.page);
|
|
1429
|
+
if (this.activeTabId === tab.id) {
|
|
1430
|
+
this.activeTabId = null;
|
|
1431
|
+
await this.activateReplacementTab();
|
|
1432
|
+
}
|
|
1433
|
+
else {
|
|
1434
|
+
this.emitState();
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
async activateTabInternal(tabId) {
|
|
1438
|
+
const tab = this.requireTab(tabId);
|
|
1439
|
+
if (tab.status !== 'open' || tab.page.isClosed()) {
|
|
1440
|
+
throw new Error(`Tab is not available: ${tab.id}`);
|
|
1441
|
+
}
|
|
1442
|
+
if (this.activeTabId === tab.id && tab.streaming) {
|
|
1443
|
+
await tab.page.bringToFront();
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
const currentTab = this.activeTabId ? this.tabs.get(this.activeTabId) : undefined;
|
|
1447
|
+
if (currentTab) {
|
|
1448
|
+
await this.stopScreencast(currentTab);
|
|
1449
|
+
}
|
|
1450
|
+
try {
|
|
1451
|
+
await this.ensureTabViewport(tab);
|
|
1452
|
+
await tab.page.bringToFront();
|
|
1453
|
+
this.activeTabId = tab.id;
|
|
1454
|
+
this.emitState();
|
|
1455
|
+
if (this.status === 'running') {
|
|
1456
|
+
await this.startScreencast(tab);
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
catch (error) {
|
|
1460
|
+
if (currentTab && this.tabs.has(currentTab.id) && !currentTab.page.isClosed()) {
|
|
1461
|
+
this.activeTabId = currentTab.id;
|
|
1462
|
+
await this.ensureTabViewport(currentTab);
|
|
1463
|
+
await currentTab.page.bringToFront();
|
|
1464
|
+
if (this.status === 'running' && !currentTab.streaming) {
|
|
1465
|
+
await this.startScreencast(currentTab);
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
this.emitState();
|
|
1469
|
+
throw error;
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
async activateReplacementTab() {
|
|
1473
|
+
const attemptedTabIds = new Set();
|
|
1474
|
+
while (true) {
|
|
1475
|
+
const replacementTab = [...this.tabs.values()].find((tab) => (!attemptedTabIds.has(tab.id)
|
|
1476
|
+
&& tab.status === 'open'
|
|
1477
|
+
&& !tab.page.isClosed()));
|
|
1478
|
+
if (!replacementTab) {
|
|
1479
|
+
this.activeTabId = null;
|
|
1480
|
+
this.normalStopRequested = true;
|
|
1481
|
+
this.beginShutdown(false);
|
|
1482
|
+
await this.stopInternal();
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
attemptedTabIds.add(replacementTab.id);
|
|
1486
|
+
try {
|
|
1487
|
+
await this.activateTabInternal(replacementTab.id);
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1490
|
+
catch (error) {
|
|
1491
|
+
this.activeTabId = null;
|
|
1492
|
+
this.emitError({
|
|
1493
|
+
code: 'replacement_tab_activation_failed',
|
|
1494
|
+
message: normalizeErrorMessage(error),
|
|
1495
|
+
fatal: false,
|
|
1496
|
+
tabId: replacementTab.id,
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
async navigateTab(tab, navigation, signal) {
|
|
1502
|
+
const isActive = this.activeTabId === tab.id;
|
|
1503
|
+
tab.navigationInProgress = true;
|
|
1504
|
+
if (isActive) {
|
|
1505
|
+
await this.stopScreencast(tab);
|
|
1506
|
+
}
|
|
1507
|
+
try {
|
|
1508
|
+
if (signal.aborted) {
|
|
1509
|
+
throw signal.reason;
|
|
1510
|
+
}
|
|
1511
|
+
await navigation();
|
|
1512
|
+
}
|
|
1513
|
+
finally {
|
|
1514
|
+
tab.navigationInProgress = false;
|
|
1515
|
+
if (this.tabs.has(tab.id) && !tab.page.isClosed()) {
|
|
1516
|
+
await this.refreshTab(tab);
|
|
1517
|
+
this.emitState();
|
|
1518
|
+
if (isActive
|
|
1519
|
+
&& this.activeTabId === tab.id
|
|
1520
|
+
&& this.status === 'running'
|
|
1521
|
+
&& tab.status === 'open'
|
|
1522
|
+
&& !signal.aborted) {
|
|
1523
|
+
await this.startScreencast(tab);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
createPuppeteerNavigationOptions(options, signal) {
|
|
1529
|
+
return {
|
|
1530
|
+
timeout: this.validateTimeout(options.timeoutMs, 30000),
|
|
1531
|
+
waitUntil: this.validateWaitUntil(options.waitUntil),
|
|
1532
|
+
signal,
|
|
1533
|
+
};
|
|
1534
|
+
}
|
|
1535
|
+
async refreshTab(tab) {
|
|
1536
|
+
if (tab.page.isClosed()) {
|
|
1537
|
+
return;
|
|
1538
|
+
}
|
|
1539
|
+
tab.url = truncate(tab.page.url(), 4096);
|
|
1540
|
+
try {
|
|
1541
|
+
tab.title = truncate(await tab.page.title(), 1024);
|
|
1542
|
+
}
|
|
1543
|
+
catch (error) {
|
|
1544
|
+
if (!tab.page.isClosed() && !tab.closing) {
|
|
1545
|
+
throw error;
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
async startScreencast(tab) {
|
|
1550
|
+
if (this.status !== 'running'
|
|
1551
|
+
|| this.activeTabId !== tab.id
|
|
1552
|
+
|| tab.status !== 'open'
|
|
1553
|
+
|| tab.page.isClosed()
|
|
1554
|
+
|| tab.streaming) {
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1557
|
+
await this.ensureTabViewport(tab);
|
|
1558
|
+
const cdpSession = await tab.page.createCDPSession();
|
|
1559
|
+
const generation = tab.generation + 1;
|
|
1560
|
+
const frameListener = (event) => {
|
|
1561
|
+
this.handleScreencastFrame(tab, cdpSession, generation, event);
|
|
1562
|
+
};
|
|
1563
|
+
const cdpConnection = cdpSession.connection();
|
|
1564
|
+
const cdpSessionDetachedListener = (detachedSession) => {
|
|
1565
|
+
if (detachedSession !== cdpSession) {
|
|
1566
|
+
return;
|
|
1567
|
+
}
|
|
1568
|
+
this.handlePossibleCdpDisconnection(tab, cdpSession, new Error('The tab CDP session disconnected'));
|
|
1569
|
+
};
|
|
1570
|
+
tab.cdpSession = cdpSession;
|
|
1571
|
+
tab.cdpConnection = cdpConnection;
|
|
1572
|
+
tab.screencastFrameListener = frameListener;
|
|
1573
|
+
tab.cdpSessionDetachedListener = cdpSessionDetachedListener;
|
|
1574
|
+
tab.generation = generation;
|
|
1575
|
+
tab.streaming = true;
|
|
1576
|
+
tab.streamInvalidated = false;
|
|
1577
|
+
cdpSession.on('Page.screencastFrame', frameListener);
|
|
1578
|
+
cdpConnection?.on(plugins.puppeteer.CDPSessionEvent.SessionDetached, cdpSessionDetachedListener);
|
|
1579
|
+
const format = this.options.screencast?.format ?? 'jpeg';
|
|
1580
|
+
try {
|
|
1581
|
+
await cdpSession.send('Page.startScreencast', {
|
|
1582
|
+
format,
|
|
1583
|
+
quality: this.options.screencast?.quality ?? 80,
|
|
1584
|
+
maxWidth: this.options.screencast?.maxWidth,
|
|
1585
|
+
maxHeight: this.options.screencast?.maxHeight,
|
|
1586
|
+
everyNthFrame: this.options.screencast?.everyNthFrame ?? 1,
|
|
1587
|
+
});
|
|
1588
|
+
this.emitState();
|
|
1589
|
+
}
|
|
1590
|
+
catch (error) {
|
|
1591
|
+
tab.streaming = false;
|
|
1592
|
+
tab.streamInvalidated = true;
|
|
1593
|
+
tab.cdpSession = undefined;
|
|
1594
|
+
tab.cdpConnection = undefined;
|
|
1595
|
+
tab.screencastFrameListener = undefined;
|
|
1596
|
+
tab.cdpSessionDetachedListener = undefined;
|
|
1597
|
+
cdpSession.off('Page.screencastFrame', frameListener);
|
|
1598
|
+
cdpConnection?.off(plugins.puppeteer.CDPSessionEvent.SessionDetached, cdpSessionDetachedListener);
|
|
1599
|
+
if (!cdpSession.detached) {
|
|
1600
|
+
try {
|
|
1601
|
+
await cdpSession.detach();
|
|
1602
|
+
}
|
|
1603
|
+
catch {
|
|
1604
|
+
// The target may have closed while screencast startup was failing.
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
throw error;
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
async stopScreencast(tab) {
|
|
1611
|
+
const cdpSession = tab.cdpSession;
|
|
1612
|
+
const cdpConnection = tab.cdpConnection;
|
|
1613
|
+
const frameListener = tab.screencastFrameListener;
|
|
1614
|
+
const cdpSessionDetachedListener = tab.cdpSessionDetachedListener;
|
|
1615
|
+
tab.streaming = false;
|
|
1616
|
+
tab.streamInvalidated = true;
|
|
1617
|
+
tab.cdpSession = undefined;
|
|
1618
|
+
tab.cdpConnection = undefined;
|
|
1619
|
+
tab.screencastFrameListener = undefined;
|
|
1620
|
+
tab.cdpSessionDetachedListener = undefined;
|
|
1621
|
+
await this.retireOutstandingFrames((frame) => frame.tabId === tab.id);
|
|
1622
|
+
if (!cdpSession) {
|
|
1623
|
+
return;
|
|
1624
|
+
}
|
|
1625
|
+
if (!cdpSession.detached) {
|
|
1626
|
+
try {
|
|
1627
|
+
await cdpSession.send('Page.stopScreencast');
|
|
1628
|
+
}
|
|
1629
|
+
catch {
|
|
1630
|
+
// Page close and browser disconnect detach the target before cleanup runs.
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
await this.retireOutstandingFrames((frame) => frame.tabId === tab.id);
|
|
1634
|
+
if (frameListener) {
|
|
1635
|
+
cdpSession.off('Page.screencastFrame', frameListener);
|
|
1636
|
+
}
|
|
1637
|
+
if (cdpConnection && cdpSessionDetachedListener) {
|
|
1638
|
+
cdpConnection.off(plugins.puppeteer.CDPSessionEvent.SessionDetached, cdpSessionDetachedListener);
|
|
1639
|
+
}
|
|
1640
|
+
if (!cdpSession.detached) {
|
|
1641
|
+
try {
|
|
1642
|
+
await cdpSession.detach();
|
|
1643
|
+
}
|
|
1644
|
+
catch {
|
|
1645
|
+
// A concurrent page close can detach the session first.
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
handleScreencastFrame(tab, cdpSession, generation, event) {
|
|
1650
|
+
if (this.status !== 'running'
|
|
1651
|
+
|| this.activeTabId !== tab.id
|
|
1652
|
+
|| tab.status !== 'open'
|
|
1653
|
+
|| tab.streamInvalidated
|
|
1654
|
+
|| !tab.streaming
|
|
1655
|
+
|| tab.generation !== generation
|
|
1656
|
+
|| tab.appliedViewportRevision !== this.viewportRevision
|
|
1657
|
+
|| tab.cdpSession !== cdpSession) {
|
|
1658
|
+
this.acknowledgeCdpFrameInBackground({
|
|
1659
|
+
tabId: tab.id,
|
|
1660
|
+
generation,
|
|
1661
|
+
viewportRevision: this.viewportRevision,
|
|
1662
|
+
cdpSessionId: event.sessionId,
|
|
1663
|
+
cdpSession,
|
|
1664
|
+
});
|
|
1665
|
+
return;
|
|
1666
|
+
}
|
|
1667
|
+
const format = this.options.screencast?.format ?? 'jpeg';
|
|
1668
|
+
const data = new Uint8Array(plugins.Buffer.from(event.data, 'base64'));
|
|
1669
|
+
const dimensions = readImageDimensions(data, format, {
|
|
1670
|
+
width: Math.max(1, Math.round(event.metadata.deviceWidth)),
|
|
1671
|
+
height: Math.max(1, Math.round(event.metadata.deviceHeight)),
|
|
1672
|
+
});
|
|
1673
|
+
const sequence = ++this.frameSequence;
|
|
1674
|
+
const outstandingFrame = {
|
|
1675
|
+
tabId: tab.id,
|
|
1676
|
+
generation,
|
|
1677
|
+
viewportRevision: this.viewportRevision,
|
|
1678
|
+
cdpSessionId: event.sessionId,
|
|
1679
|
+
cdpSession,
|
|
1680
|
+
};
|
|
1681
|
+
while (this.outstandingFrames.size >= maxOutstandingFrames) {
|
|
1682
|
+
const oldestFrameEntry = this.outstandingFrames.entries().next().value;
|
|
1683
|
+
if (!oldestFrameEntry) {
|
|
1684
|
+
break;
|
|
1685
|
+
}
|
|
1686
|
+
this.outstandingFrames.delete(oldestFrameEntry[0]);
|
|
1687
|
+
this.acknowledgeCdpFrameInBackground(oldestFrameEntry[1]);
|
|
1688
|
+
}
|
|
1689
|
+
this.outstandingFrames.set(sequence, outstandingFrame);
|
|
1690
|
+
const frame = {
|
|
1691
|
+
tabId: tab.id,
|
|
1692
|
+
sequence,
|
|
1693
|
+
generation,
|
|
1694
|
+
viewportRevision: this.viewportRevision,
|
|
1695
|
+
viewport: { ...this.viewport },
|
|
1696
|
+
format,
|
|
1697
|
+
mimeType: format === 'jpeg' ? 'image/jpeg' : 'image/png',
|
|
1698
|
+
...dimensions,
|
|
1699
|
+
metadata: {
|
|
1700
|
+
offsetTop: event.metadata.offsetTop,
|
|
1701
|
+
pageScaleFactor: event.metadata.pageScaleFactor,
|
|
1702
|
+
deviceWidth: event.metadata.deviceWidth,
|
|
1703
|
+
deviceHeight: event.metadata.deviceHeight,
|
|
1704
|
+
scrollOffsetX: event.metadata.scrollOffsetX,
|
|
1705
|
+
scrollOffsetY: event.metadata.scrollOffsetY,
|
|
1706
|
+
...(event.metadata.timestamp !== undefined
|
|
1707
|
+
? { timestamp: event.metadata.timestamp }
|
|
1708
|
+
: {}),
|
|
1709
|
+
},
|
|
1710
|
+
data,
|
|
1711
|
+
};
|
|
1712
|
+
this.emitEvent({ type: 'frame', frame });
|
|
1713
|
+
}
|
|
1714
|
+
async acknowledgeCdpFrame(frame) {
|
|
1715
|
+
if (frame.cdpSession.detached) {
|
|
1716
|
+
this.handleFrameAcknowledgementFailure(frame, new Error('CDP session detached before frame acknowledgement'));
|
|
1717
|
+
return false;
|
|
1718
|
+
}
|
|
1719
|
+
try {
|
|
1720
|
+
await frame.cdpSession.send('Page.screencastFrameAck', {
|
|
1721
|
+
sessionId: frame.cdpSessionId,
|
|
1722
|
+
});
|
|
1723
|
+
return true;
|
|
1724
|
+
}
|
|
1725
|
+
catch (error) {
|
|
1726
|
+
this.handleFrameAcknowledgementFailure(frame, error);
|
|
1727
|
+
return false;
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
acknowledgeCdpFrameInBackground(frame) {
|
|
1731
|
+
void this.acknowledgeCdpFrame(frame);
|
|
1732
|
+
}
|
|
1733
|
+
handleFrameAcknowledgementFailure(frame, error) {
|
|
1734
|
+
const tab = this.tabs.get(frame.tabId);
|
|
1735
|
+
const isCurrentStream = Boolean(tab
|
|
1736
|
+
&& tab.cdpSession === frame.cdpSession
|
|
1737
|
+
&& !tab.streamInvalidated);
|
|
1738
|
+
if (isCurrentStream
|
|
1739
|
+
&& this.status === 'running'
|
|
1740
|
+
&& !this.normalStopRequested) {
|
|
1741
|
+
this.emitError({
|
|
1742
|
+
code: 'frame_acknowledgement_failed',
|
|
1743
|
+
message: normalizeErrorMessage(error),
|
|
1744
|
+
fatal: false,
|
|
1745
|
+
tabId: frame.tabId,
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1748
|
+
if (tab) {
|
|
1749
|
+
this.handlePossibleCdpDisconnection(tab, frame.cdpSession, error);
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
async retireOutstandingFrames(predicate) {
|
|
1753
|
+
const acknowledgements = [];
|
|
1754
|
+
for (const [sequence, frame] of this.outstandingFrames) {
|
|
1755
|
+
if (!predicate(frame)) {
|
|
1756
|
+
continue;
|
|
1757
|
+
}
|
|
1758
|
+
this.outstandingFrames.delete(sequence);
|
|
1759
|
+
acknowledgements.push(this.acknowledgeCdpFrame(frame));
|
|
1760
|
+
}
|
|
1761
|
+
await Promise.all(acknowledgements);
|
|
1762
|
+
}
|
|
1763
|
+
handlePossibleCdpDisconnection(tab, cdpSession, error) {
|
|
1764
|
+
if (this.normalStopRequested
|
|
1765
|
+
|| this.status !== 'running'
|
|
1766
|
+
|| tab.cdpSession !== cdpSession
|
|
1767
|
+
|| tab.streamInvalidated
|
|
1768
|
+
|| !cdpSession.detached) {
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
tab.streamInvalidated = true;
|
|
1772
|
+
this.retireFramesForTabInBackground(tab.id);
|
|
1773
|
+
this.scheduleOperation(async () => {
|
|
1774
|
+
if (!this.tabs.has(tab.id) || tab.cdpSession !== cdpSession) {
|
|
1775
|
+
return;
|
|
1776
|
+
}
|
|
1777
|
+
await this.stopScreencast(tab);
|
|
1778
|
+
tab.status = 'crashed';
|
|
1779
|
+
const wasActive = this.activeTabId === tab.id;
|
|
1780
|
+
if (wasActive) {
|
|
1781
|
+
this.activeTabId = null;
|
|
1782
|
+
}
|
|
1783
|
+
this.emitError({
|
|
1784
|
+
code: 'cdp_disconnected',
|
|
1785
|
+
message: normalizeErrorMessage(error),
|
|
1786
|
+
fatal: false,
|
|
1787
|
+
tabId: tab.id,
|
|
1788
|
+
});
|
|
1789
|
+
if (wasActive) {
|
|
1790
|
+
await this.activateReplacementTab();
|
|
1791
|
+
}
|
|
1792
|
+
}, 'cdp_disconnect_cleanup_failed', tab.id, true);
|
|
1793
|
+
}
|
|
1794
|
+
requireRawInputTarget(input) {
|
|
1795
|
+
const tab = this.requireInputTarget(input, true);
|
|
1796
|
+
const cdpSession = tab.cdpSession;
|
|
1797
|
+
if (!tab.streaming || tab.streamInvalidated || !cdpSession || cdpSession.detached) {
|
|
1798
|
+
throw new Error(`Tab input transport is not available: ${tab.id}`);
|
|
1799
|
+
}
|
|
1800
|
+
return { tab, cdpSession };
|
|
1801
|
+
}
|
|
1802
|
+
requireSemanticActionTarget(input) {
|
|
1803
|
+
return this.requireInputTarget(input, false);
|
|
1804
|
+
}
|
|
1805
|
+
requireInputTarget(input, requireActive) {
|
|
1806
|
+
if (this.status !== 'running') {
|
|
1807
|
+
throw new Error('LiveBrowserSession is not running');
|
|
1808
|
+
}
|
|
1809
|
+
const tab = this.requireTab(input.tabId);
|
|
1810
|
+
if (requireActive && this.activeTabId !== tab.id) {
|
|
1811
|
+
throw new Error(`Tab is not active: ${tab.id}`);
|
|
1812
|
+
}
|
|
1813
|
+
if (!Number.isInteger(input.generation) || input.generation !== tab.generation) {
|
|
1814
|
+
throw new Error(`Stale tab generation ${input.generation}; current generation is ${tab.generation}`);
|
|
1815
|
+
}
|
|
1816
|
+
if (input.viewportRevision !== this.viewportRevision) {
|
|
1817
|
+
throw new Error(`Stale viewport revision ${input.viewportRevision}; current revision is ${this.viewportRevision}`);
|
|
1818
|
+
}
|
|
1819
|
+
if (tab.status !== 'open' || tab.page.isClosed()) {
|
|
1820
|
+
throw new Error(`Tab is not available: ${tab.id}`);
|
|
1821
|
+
}
|
|
1822
|
+
return tab;
|
|
1823
|
+
}
|
|
1824
|
+
validateCoordinates(x, y) {
|
|
1825
|
+
validateFiniteNumber(x, 'x', 0, this.viewport.width);
|
|
1826
|
+
validateFiniteNumber(y, 'y', 0, this.viewport.height);
|
|
1827
|
+
if (x >= this.viewport.width) {
|
|
1828
|
+
throw new Error(`x must be less than viewport width ${this.viewport.width}`);
|
|
1829
|
+
}
|
|
1830
|
+
if (y >= this.viewport.height) {
|
|
1831
|
+
throw new Error(`y must be less than viewport height ${this.viewport.height}`);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
createModifierMask(modifiers) {
|
|
1835
|
+
if (modifiers === undefined) {
|
|
1836
|
+
return 0;
|
|
1837
|
+
}
|
|
1838
|
+
if (!modifiers || typeof modifiers !== 'object' || Array.isArray(modifiers)) {
|
|
1839
|
+
throw new Error('modifiers must be an object');
|
|
1840
|
+
}
|
|
1841
|
+
const allowedKeys = new Set(['alt', 'control', 'meta', 'shift']);
|
|
1842
|
+
for (const key of Object.keys(modifiers)) {
|
|
1843
|
+
if (!allowedKeys.has(key)) {
|
|
1844
|
+
throw new Error(`Unknown modifier: ${key}`);
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
validateOptionalBoolean(modifiers.alt, 'modifiers.alt');
|
|
1848
|
+
validateOptionalBoolean(modifiers.control, 'modifiers.control');
|
|
1849
|
+
validateOptionalBoolean(modifiers.meta, 'modifiers.meta');
|
|
1850
|
+
validateOptionalBoolean(modifiers.shift, 'modifiers.shift');
|
|
1851
|
+
return ((modifiers.alt ? 1 : 0)
|
|
1852
|
+
| (modifiers.control ? 2 : 0)
|
|
1853
|
+
| (modifiers.meta ? 4 : 0)
|
|
1854
|
+
| (modifiers.shift ? 8 : 0));
|
|
1855
|
+
}
|
|
1856
|
+
validateUrl(url) {
|
|
1857
|
+
const validatedUrl = validateBoundedString(url, 'url', 1, maxUrlLength);
|
|
1858
|
+
try {
|
|
1859
|
+
new URL(validatedUrl);
|
|
1860
|
+
}
|
|
1861
|
+
catch {
|
|
1862
|
+
throw new Error('url must be absolute');
|
|
1863
|
+
}
|
|
1864
|
+
return validatedUrl;
|
|
1865
|
+
}
|
|
1866
|
+
validateTimeout(timeoutMs, defaultValue = 5000) {
|
|
1867
|
+
if (timeoutMs === undefined) {
|
|
1868
|
+
return defaultValue;
|
|
1869
|
+
}
|
|
1870
|
+
return validateInteger(timeoutMs, 'timeoutMs', 1, maxTimeoutMs);
|
|
1871
|
+
}
|
|
1872
|
+
validateWaitUntil(waitUntil) {
|
|
1873
|
+
const validatedWaitUntil = waitUntil ?? 'load';
|
|
1874
|
+
if (!['load', 'domcontentloaded', 'networkidle0', 'networkidle2'].includes(validatedWaitUntil)) {
|
|
1875
|
+
throw new Error('waitUntil must be load, domcontentloaded, networkidle0, or networkidle2');
|
|
1876
|
+
}
|
|
1877
|
+
return validatedWaitUntil;
|
|
1878
|
+
}
|
|
1879
|
+
validateScreencastOptions() {
|
|
1880
|
+
const options = this.options.screencast;
|
|
1881
|
+
if (!options) {
|
|
1882
|
+
return;
|
|
1883
|
+
}
|
|
1884
|
+
if (options.format !== undefined && options.format !== 'jpeg' && options.format !== 'png') {
|
|
1885
|
+
throw new Error('screencast.format must be jpeg or png');
|
|
1886
|
+
}
|
|
1887
|
+
if (options.quality !== undefined) {
|
|
1888
|
+
validateInteger(options.quality, 'screencast.quality', 0, 100);
|
|
1889
|
+
}
|
|
1890
|
+
if (options.maxWidth !== undefined) {
|
|
1891
|
+
validateInteger(options.maxWidth, 'screencast.maxWidth', 1, maxViewportWidth);
|
|
1892
|
+
}
|
|
1893
|
+
if (options.maxHeight !== undefined) {
|
|
1894
|
+
validateInteger(options.maxHeight, 'screencast.maxHeight', 1, maxViewportHeight);
|
|
1895
|
+
}
|
|
1896
|
+
if (options.maxWidth !== undefined
|
|
1897
|
+
&& options.maxHeight !== undefined
|
|
1898
|
+
&& options.maxWidth * options.maxHeight > maxViewportPixelArea) {
|
|
1899
|
+
throw new Error(`screencast pixel area must not exceed ${maxViewportPixelArea} pixels`);
|
|
1900
|
+
}
|
|
1901
|
+
if (options.everyNthFrame !== undefined) {
|
|
1902
|
+
validateInteger(options.everyNthFrame, 'screencast.everyNthFrame', 1, 100);
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRwdXBwZXRlZXIuY2xhc3Nlcy5saXZlYnJvd3NlcnNlc3Npb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHB1cHBldGVlci5jbGFzc2VzLmxpdmVicm93c2Vyc2Vzc2lvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQztBQThCeEYsT0FBTyxLQUFLLE9BQU8sTUFBTSw2QkFBNkIsQ0FBQztBQUV2RCxNQUFNLGVBQWUsR0FBeUI7SUFDNUMsS0FBSyxFQUFFLEdBQUc7SUFDVixNQUFNLEVBQUUsR0FBRztJQUNYLGlCQUFpQixFQUFFLENBQUM7Q0FDckIsQ0FBQztBQUVGLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO0FBQzlCLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDO0FBQy9CLE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxDQUFDO0FBQy9CLE1BQU0sb0JBQW9CLEdBQUcsT0FBTyxDQUFDO0FBQ3JDLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDO0FBQy9CLE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQztBQUM1QixNQUFNLFlBQVksR0FBRyxLQUFLLENBQUM7QUFDM0IsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDO0FBQzNCLE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxDQUFDO0FBQy9CLE1BQU0seUJBQXlCLEdBQUcsRUFBRSxDQUFDO0FBQ3JDLE1BQU0sMkJBQTJCLEdBQUcsR0FBRyxDQUFDO0FBbUR4QyxNQUFNLHFCQUFxQixHQUFHLENBQzVCLEtBQWMsRUFDZCxJQUFZLEVBQ1osU0FBaUIsRUFDakIsU0FBaUIsRUFDVCxFQUFFO0lBQ1YsSUFDRSxPQUFPLEtBQUssS0FBSyxRQUFRO1dBQ3RCLEtBQUssQ0FBQyxNQUFNLEdBQUcsU0FBUztXQUN4QixLQUFLLENBQUMsTUFBTSxHQUFHLFNBQVMsRUFDM0IsQ0FBQztRQUNELE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxJQUFJLHlCQUF5QixTQUFTLFFBQVEsU0FBUyxhQUFhLENBQUMsQ0FBQztJQUMzRixDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDLENBQUM7QUFFRixNQUFNLG9CQUFvQixHQUFHLENBQzNCLEtBQWMsRUFDZCxJQUFZLEVBQ1osT0FBZSxFQUNmLE9BQWUsRUFDUCxFQUFFO0lBQ1YsSUFDRSxPQUFPLEtBQUssS0FBSyxRQUFRO1dBQ3RCLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUM7V0FDdkIsS0FBSyxHQUFHLE9BQU87V0FDZixLQUFLLEdBQUcsT0FBTyxFQUNsQixDQUFDO1FBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLElBQUksb0NBQW9DLE9BQU8sUUFBUSxPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZGLENBQUM7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMsQ0FBQztBQUVGLE1BQU0sZUFBZSxHQUFHLENBQ3RCLEtBQWMsRUFDZCxJQUFZLEVBQ1osT0FBZSxFQUNmLE9BQWUsRUFDUCxFQUFFO0lBQ1YsTUFBTSxjQUFjLEdBQUcsb0JBQW9CLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDM0UsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQztRQUN0QyxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsSUFBSSxxQkFBcUIsQ0FBQyxDQUFDO0lBQ2hELENBQUM7SUFDRCxPQUFPLGNBQWMsQ0FBQztBQUN4QixDQUFDLENBQUM7QUFFRixNQUFNLHVCQUF1QixHQUFHLENBQUMsS0FBYyxFQUFFLElBQVksRUFBUSxFQUFFO0lBQ3JFLElBQUksS0FBSyxLQUFLLFNBQVMsSUFBSSxPQUFPLEtBQUssS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUN0RCxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsSUFBSSxvQkFBb0IsQ0FBQyxDQUFDO0lBQy9DLENBQUM7QUFDSCxDQUFDLENBQUM7QUFFRixNQUFNLFFBQVEsR0FBRyxDQUFDLEtBQWEsRUFBRSxTQUFpQixFQUFVLEVBQUU7SUFDNUQsSUFBSSxLQUFLLENBQUMsTUFBTSxJQUFJLFNBQVMsRUFBRSxDQUFDO1FBQzlCLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUNELE9BQU8sR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxTQUFTLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO0FBQzVELENBQUMsQ0FBQztBQUVGLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxLQUFjLEVBQVUsRUFBRTtJQUN2RCxJQUFJLEtBQUssWUFBWSxLQUFLLEVBQUUsQ0FBQztRQUMzQixPQUFPLFFBQVEsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFDRCxPQUFPLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDdkMsQ0FBQyxDQUFDO0FBRUYsTUFBTSxVQUFVLEdBQUcsQ0FBQyxJQUFnQixFQUFFLE1BQWMsRUFBVSxFQUFFO0lBQzlELE9BQU8sQ0FDTCxJQUFJLENBQUMsTUFBTSxDQUFFLEdBQUcsU0FBUztVQUN2QixJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBRSxHQUFHLE9BQU87VUFDM0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUUsR0FBRyxLQUFLO1VBQ3pCLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFFLENBQ3BCLENBQUM7QUFDSixDQUFDLENBQUM7QUFFRixNQUFNLG1CQUFtQixHQUFHLENBQzFCLElBQWdCLEVBQ2hCLE1BQStCLEVBQy9CLFFBQTBCLEVBQ1IsRUFBRTtJQUNwQixJQUNFLE1BQU0sS0FBSyxLQUFLO1dBQ2IsSUFBSSxDQUFDLE1BQU0sSUFBSSxFQUFFO1dBQ2pCLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1dBQ2hCLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1dBQ2hCLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1dBQ2hCLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLEVBQ25CLENBQUM7UUFDRCxPQUFPO1lBQ0wsS0FBSyxFQUFFLFVBQVUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQzNCLE1BQU0sRUFBRSxVQUFVLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQztTQUM3QixDQUFDO0lBQ0osQ0FBQztJQUVELElBQUksTUFBTSxLQUFLLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUNsRixJQUFJLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDZixPQUFPLE1BQU0sR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2hDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUMxQixNQUFNLElBQUksQ0FBQyxDQUFDO2dCQUNaLFNBQVM7WUFDWCxDQUFDO1lBQ0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUUsQ0FBQztZQUNqQyxJQUFJLE1BQU0sS0FBSyxJQUFJLElBQUksTUFBTSxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUN2QyxNQUFNLElBQUksQ0FBQyxDQUFDO2dCQUNaLFNBQVM7WUFDWCxDQUFDO1lBQ0QsTUFBTSxhQUFhLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBRSxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFFLENBQUM7WUFDbkUsSUFBSSxhQUFhLEdBQUcsQ0FBQyxJQUFJLE1BQU0sR0FBRyxhQUFhLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDbEUsTUFBTTtZQUNSLENBQUM7WUFDRCxJQUNFLE1BQU0sS0FBSyxJQUFJO21CQUNaLE1BQU0sS0FBSyxJQUFJO21CQUNmLE1BQU0sS0FBSyxJQUFJO21CQUNmLE1BQU0sS0FBSyxJQUFJO21CQUNmLE1BQU0sS0FBSyxJQUFJO21CQUNmLE1BQU0sS0FBSyxJQUFJO21CQUNmLE1BQU0sS0FBSyxJQUFJO21CQUNmLE1BQU0sS0FBSyxJQUFJO21CQUNmLE1BQU0sS0FBSyxJQUFJO21CQUNmLE1BQU0sS0FBSyxJQUFJO21CQUNmLE1BQU0sS0FBSyxJQUFJO21CQUNmLE1BQU0sS0FBSyxJQUFJO21CQUNmLE1BQU0sS0FBSyxJQUFJLEVBQ2xCLENBQUM7Z0JBQ0QsT0FBTztvQkFDTCxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBRSxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFFO29CQUNwRCxLQUFLLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBRSxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFFO2lCQUNwRCxDQUFDO1lBQ0osQ0FBQztZQUNELE1BQU0sSUFBSSxhQUFhLEdBQUcsQ0FBQyxDQUFDO1FBQzlCLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxRQUFRLENBQUM7QUFDbEIsQ0FBQyxDQUFDO0FBRUYsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLFFBQThCLEVBQXdCLEVBQUU7SUFDakYsTUFBTSxrQkFBa0IsR0FBRztRQUN6QixLQUFLLEVBQUUsZUFBZSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQyxFQUFFLGdCQUFnQixDQUFDO1FBQzdFLE1BQU0sRUFBRSxlQUFlLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxpQkFBaUIsRUFBRSxDQUFDLEVBQUUsaUJBQWlCLENBQUM7UUFDakYsaUJBQWlCLEVBQUUsb0JBQW9CLENBQ3JDLFFBQVEsQ0FBQyxpQkFBaUIsRUFDMUIsNEJBQTRCLEVBQzVCLElBQUksRUFDSixvQkFBb0IsQ0FDckI7S0FDRixDQUFDO0lBQ0YsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FDN0Isa0JBQWtCLENBQUMsS0FBSyxHQUFHLGtCQUFrQixDQUFDLGlCQUFpQixDQUNoRSxDQUFDO0lBQ0YsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FDOUIsa0JBQWtCLENBQUMsTUFBTSxHQUFHLGtCQUFrQixDQUFDLGlCQUFpQixDQUNqRSxDQUFDO0lBQ0YsSUFBSSxhQUFhLEdBQUcsY0FBYyxHQUFHLG9CQUFvQixFQUFFLENBQUM7UUFDMUQsTUFBTSxJQUFJLEtBQUssQ0FDYix1Q0FBdUMsb0JBQW9CLGtCQUFrQixDQUM5RSxDQUFDO0lBQ0osQ0FBQztJQUNELE9BQU8sa0JBQWtCLENBQUM7QUFDNUIsQ0FBQyxDQUFDO0FBRUYsTUFBTSx1QkFBdUIsR0FBRyxDQUM5QixRQUE4QixFQUNGLEVBQUUsQ0FBQyxDQUFDO0lBQ2hDLEdBQUcsUUFBUTtJQUNYLFFBQVEsRUFBRSxLQUFLO0lBQ2YsV0FBVyxFQUFFLEtBQUs7SUFDbEIsUUFBUSxFQUFFLEtBQUs7Q0FDaEIsQ0FBQyxDQUFDO0FBRUgsTUFBTSxPQUFPLGtCQUFrQjtJQTBCN0IsWUFBWSxhQUF5QyxFQUFFO1FBeEJ0QyxtQkFBYyxHQUFHLElBQUksR0FBRyxFQUE2QixDQUFDO1FBQ3RELFNBQUksR0FBRyxJQUFJLEdBQUcsRUFBa0MsQ0FBQztRQUNqRCxpQkFBWSxHQUFHLElBQUksT0FBTyxFQUFrQyxDQUFDO1FBQzdELHNCQUFpQixHQUFHLElBQUksR0FBRyxFQUE2QixDQUFDO1FBTXpELG1CQUFjLEdBQXVCLEVBQUUsQ0FBQztRQUVqRCxxQkFBZ0IsR0FBRyxLQUFLLENBQUM7UUFDekIsNkJBQXdCLEdBQUcsQ0FBQyxDQUFDO1FBQzdCLCtCQUEwQixHQUFHLENBQUMsQ0FBQztRQUUvQixXQUFNLEdBQW9ELFNBQVMsQ0FBQztRQUNwRSxnQkFBVyxHQUFrQixJQUFJLENBQUM7UUFDbEMsYUFBUSxHQUF5QixFQUFFLEdBQUcsZUFBZSxFQUFFLENBQUM7UUFDeEQscUJBQWdCLEdBQUcsQ0FBQyxDQUFDO1FBQ3JCLGdCQUFXLEdBQUcsQ0FBQyxDQUFDO1FBQ2hCLGtCQUFhLEdBQUcsQ0FBQyxDQUFDO1FBQ2xCLHdCQUFtQixHQUFHLEtBQUssQ0FBQztRQUlsQyxJQUNFLFVBQVUsQ0FBQyxhQUFhLEVBQUUsUUFBUTtlQUMvQixVQUFVLENBQUMsYUFBYSxDQUFDLFFBQVEsS0FBSyxLQUFLLEVBQzlDLENBQUM7WUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLDBEQUEwRCxDQUFDLENBQUM7UUFDOUUsQ0FBQztRQUNELElBQ0UsVUFBVSxDQUFDLGFBQWEsRUFBRSxPQUFPO2VBQzlCLFVBQVUsQ0FBQyxhQUFhLENBQUMsT0FBTyxLQUFLLFFBQVEsRUFDaEQsQ0FBQztZQUNELE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQztRQUMxRCxDQUFDO1FBQ0QsSUFBSSxVQUFVLENBQUMsYUFBYSxJQUFJLFFBQVEsSUFBSSxVQUFVLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDckUsTUFBTSxJQUFJLEtBQUssQ0FBQyxrRkFBa0YsQ0FBQyxDQUFDO1FBQ3RHLENBQUM7UUFDRCxNQUFNLGNBQWMsR0FBRyxVQUFVLENBQUMsYUFBYSxFQUFFLGVBQWUsQ0FBQztRQUNqRSxNQUFNLFFBQVEsR0FBRyxpQkFBaUIsQ0FDaEMsVUFBVSxDQUFDLFFBQVE7ZUFDaEIsQ0FBQyxjQUFjO2dCQUNoQixDQUFDLENBQUM7b0JBQ0UsS0FBSyxFQUFFLGNBQWMsQ0FBQyxLQUFLO29CQUMzQixNQUFNLEVBQUUsY0FBYyxDQUFDLE1BQU07b0JBQzdCLGlCQUFpQixFQUFFLGNBQWMsQ0FBQyxpQkFBaUIsSUFBSSxDQUFDO2lCQUN6RDtnQkFDSCxDQUFDLENBQUMsZUFBZSxDQUFDLENBQ3JCLENBQUM7UUFDRixJQUFJLENBQUMsT0FBTyxHQUFHO1lBQ2IsR0FBRyxVQUFVO1lBQ2IsYUFBYSxFQUFFO2dCQUNiLEdBQUcsVUFBVSxDQUFDLGFBQWE7Z0JBQzNCLElBQUksRUFBRSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsYUFBYSxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQztnQkFDakQsZUFBZSxFQUFFLHVCQUF1QixDQUFDLFFBQVEsQ0FBQzthQUNuRDtZQUNELFFBQVE7WUFDUixVQUFVLEVBQUUsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLFVBQVUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUztTQUM3RSxDQUFDO1FBQ0YsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLEdBQUcsUUFBUSxFQUFFLENBQUM7UUFDaEMsSUFBSSxDQUFDLHlCQUF5QixFQUFFLENBQUM7SUFDbkMsQ0FBQztJQUVNLE9BQU8sQ0FBQyxRQUFtQztRQUNoRCxJQUFJLE9BQU8sUUFBUSxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQ25DLE1BQU0sSUFBSSxLQUFLLENBQUMsNkJBQTZCLENBQUMsQ0FBQztRQUNqRCxDQUFDO1FBQ0QsSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDbEMsT0FBTyxHQUFHLEVBQUU7WUFDVixJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN2QyxDQUFDLENBQUM7SUFDSixDQUFDO0lBRU0sUUFBUTtRQUNiLE9BQU87WUFDTCxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07WUFDbkIsV0FBVyxFQUFFLElBQUksQ0FBQyxXQUFXO1lBQzdCLGdCQUFnQixFQUFFLElBQUksQ0FBQyxnQkFBZ0I7WUFDdkMsUUFBUSxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQzlCLElBQUksRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNwRSxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7U0FDaEUsQ0FBQztJQUNKLENBQUM7SUFFTSxLQUFLLENBQUMsS0FBSztRQUNoQixPQUFPLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDbEQsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFVBQVUsRUFBRSxDQUFDO2dCQUM1RCxPQUFPO1lBQ1QsQ0FBQztZQUVELElBQUksQ0FBQyxtQkFBbUIsR0FBRyxLQUFLLENBQUM7WUFDakMsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7WUFDM0IsSUFBSSxDQUFDLGdCQUFnQixHQUFHLENBQUMsQ0FBQztZQUMxQixNQUFNLHlCQUF5QixHQUFHLElBQUksZUFBZSxFQUFFLENBQUM7WUFDeEQsSUFBSSxDQUFDLHlCQUF5QixHQUFHLHlCQUF5QixDQUFDO1lBQzNELElBQUksQ0FBQyxNQUFNLEdBQUcsVUFBVSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUVqQixJQUFJLENBQUM7Z0JBQ0gsSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7b0JBQ25CLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQztnQkFDdEIsQ0FBQztnQkFDRCxJQUFJLHlCQUF5QixDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztvQkFDN0MsTUFBTSx5QkFBeUIsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO2dCQUNoRCxDQUFDO2dCQUNELElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSwwQkFBMEIsQ0FBQztvQkFDOUMsY0FBYyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYztvQkFDM0MsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTztvQkFDN0IsYUFBYSxFQUFFO3dCQUNiLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhO3dCQUM3QixRQUFRLEVBQUUsS0FBSzt3QkFDZixNQUFNLEVBQUUseUJBQXlCLENBQUMsTUFBTTtxQkFDekM7aUJBQ0YsQ0FBQyxDQUFDO2dCQUNILElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO29CQUNuQixNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUM7Z0JBQ3RCLENBQUM7Z0JBQ0QsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLHFCQUFxQixFQUFFLENBQUM7Z0JBQzNELElBQUksQ0FBQywyQkFBMkIsR0FBRyxHQUFHLEVBQUU7b0JBQ3RDLElBQUksSUFBSSxDQUFDLG1CQUFtQixJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssVUFBVSxFQUFFLENBQUM7d0JBQ3hGLE9BQU87b0JBQ1QsQ0FBQztvQkFDRCxNQUFNLEtBQUssR0FBc0I7d0JBQy9CLElBQUksRUFBRSxzQkFBc0I7d0JBQzVCLE9BQU8sRUFBRSxtQ0FBbUM7d0JBQzVDLEtBQUssRUFBRSxJQUFJO3FCQUNaLENBQUM7b0JBQ0YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDdEIsS0FBSyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFO3dCQUN0RCxJQUFJLENBQUMsU0FBUyxDQUFDOzRCQUNiLElBQUksRUFBRSxtQ0FBbUM7NEJBQ3pDLE9BQU8sRUFBRSxxQkFBcUIsQ0FBQyxZQUFZLENBQUM7NEJBQzVDLEtBQUssRUFBRSxJQUFJO3lCQUNaLENBQUMsQ0FBQztvQkFDTCxDQUFDLENBQUMsQ0FBQztnQkFDTCxDQUFDLENBQUM7Z0JBQ0YsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO2dCQUVsRSxNQUFNLFlBQVksR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ3ZELElBQUksWUFBWSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztvQkFDOUIsWUFBWSxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztnQkFDekQsQ0FBQztnQkFDRCxNQUFNLFdBQVcsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFFLENBQUM7Z0JBQ3JDLElBQUksV0FBVyxDQUFDLEdBQUcsRUFBRSxLQUFLLGFBQWEsRUFBRSxDQUFDO29CQUN4QyxNQUFNLFdBQVcsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7Z0JBQ3hDLENBQUM7Z0JBRUQsS0FBSyxNQUFNLElBQUksSUFBSSxZQUFZLEVBQUUsQ0FBQztvQkFDaEMsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNoQyxDQUFDO2dCQUVELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBMkMsQ0FBQztnQkFDdkYsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO29CQUNkLE1BQU0sSUFBSSxLQUFLLENBQUMsMENBQTBDLENBQUMsQ0FBQztnQkFDOUQsQ0FBQztnQkFDRCxJQUFJLENBQUMsV0FBVyxHQUFHLFFBQVEsQ0FBQyxFQUFFLENBQUM7Z0JBQy9CLE1BQU0sUUFBUSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDbkMsSUFBSSxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUM7Z0JBQ3hCLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDakIsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3ZDLENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLElBQUksTUFBTSxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztvQkFDL0MsTUFBTSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7b0JBQzFCLE1BQU0sS0FBSyxDQUFDO2dCQUNkLENBQUM7Z0JBQ0QsTUFBTSxVQUFVLEdBQXNCO29CQUNwQyxJQUFJLEVBQUUsY0FBYztvQkFDcEIsT0FBTyxFQUFFLHFCQUFxQixDQUFDLEtBQUssQ0FBQztvQkFDckMsS0FBSyxFQUFFLElBQUk7aUJBQ1osQ0FBQztnQkFDRixJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUMzQixNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQ3BDLE1BQU0sS0FBSyxDQUFDO1lBQ2QsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLEtBQUssQ0FBQyxJQUFJO1FBQ2YsSUFBSSxDQUFDLG1CQUFtQixHQUFHLElBQUksQ0FBQztRQUNoQyxPQUFPLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUNoQyxDQUFDO0lBRU0sS0FBSyxDQUFDLGdCQUFnQixDQUMzQixlQUF3RDtRQUV4RCxJQUFJLENBQUMsZUFBZSxJQUFJLE9BQU8sZUFBZSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzVELE9BQU8sRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDN0IsQ0FBQztRQUNELE1BQU0sRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsRUFBRSxHQUFHLGVBQWUsQ0FBQztRQUMxRSxJQUNFLE9BQU8sS0FBSyxLQUFLLFFBQVE7ZUFDdEIsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDO2VBQ2hCLEtBQUssQ0FBQyxNQUFNLEdBQUcsR0FBRztlQUNsQixDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDO2VBQzNCLFFBQVEsR0FBRyxDQUFDO2VBQ1osQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQztlQUM3QixVQUFVLEdBQUcsQ0FBQztlQUNkLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQztlQUNuQyxnQkFBZ0IsR0FBRyxDQUFDLEVBQ3ZCLENBQUM7WUFDRCxPQUFPLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDO1FBQzdCLENBQUM7UUFDRCxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDOUQsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDdEIsT0FBTyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUM3QixDQUFDO1FBQ0QsSUFDRSxnQkFBZ0IsQ0FBQyxLQUFLLEtBQUssS0FBSztlQUM3QixnQkFBZ0IsQ0FBQyxVQUFVLEtBQUssVUFBVTtlQUMxQyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsS0FBSyxnQkFBZ0IsRUFDekQsQ0FBQztZQUNELE9BQU8sRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDN0IsQ0FBQztRQUVELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2xELElBQ0UsQ0FBQyxHQUFHO2VBQ0QsSUFBSSxDQUFDLFdBQVcsS0FBSyxHQUFHLENBQUMsRUFBRTtlQUMzQixHQUFHLENBQUMsVUFBVSxLQUFLLGdCQUFnQixDQUFDLFVBQVU7ZUFDOUMsSUFBSSxDQUFDLGdCQUFnQixLQUFLLGdCQUFnQixDQUFDLGdCQUFnQjtlQUMzRCxHQUFHLENBQUMsVUFBVSxLQUFLLGdCQUFnQixDQUFDLFVBQVU7ZUFDOUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFDdkMsQ0FBQztZQUNELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDeEMsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUNqRCxPQUFPLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDO1FBQzdCLENBQUM7UUFFRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3hDLE9BQU87WUFDTCxRQUFRLEVBQUUsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQUMsZ0JBQWdCLENBQUM7U0FDM0QsQ0FBQztJQUNKLENBQUM7SUFFTSxLQUFLLENBQUMsU0FBUyxDQUNwQixhQUEyQyxFQUFFO1FBRTdDLE1BQU0sR0FBRyxHQUFHLFVBQVUsQ0FBQyxHQUFHLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3hGLE1BQU0sUUFBUSxHQUFHLFVBQVUsQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDO1FBQzdDLHVCQUF1QixDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDekQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxVQUFVLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ2xFLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDL0QsT0FBTyxJQUFJLENBQUMsc0JBQXNCLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ2xELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQzdDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQztZQUM3QyxJQUFJLElBQXdDLENBQUM7WUFDN0MsSUFBSSxHQUF1QyxDQUFDO1lBQzVDLElBQUksQ0FBQztnQkFDSCxJQUFJLEdBQUcsTUFBTSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQy9CLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO29CQUNuQixNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUM7Z0JBQ3RCLENBQUM7Z0JBQ0QsR0FBRyxHQUFHLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDcEMsSUFBSSxHQUFHLEtBQUssU0FBUyxFQUFFLENBQUM7b0JBQ3RCLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FDcEIsR0FBRyxFQUNILEtBQUssSUFBSSxFQUFFO3dCQUNULE1BQU0sR0FBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO29CQUM1RCxDQUFDLEVBQ0QsTUFBTSxDQUNQLENBQUM7Z0JBQ0osQ0FBQztnQkFFRCxJQUFJLFFBQVEsRUFBRSxDQUFDO29CQUNiLE1BQU0sSUFBSSxDQUFDLG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDekMsQ0FBQztxQkFBTSxDQUFDO29CQUNOLE1BQU0saUJBQWlCLEdBQUcsbUJBQW1CO3dCQUMzQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUM7d0JBQ3BDLENBQUMsQ0FBQyxTQUFTLENBQUM7b0JBQ2QsSUFBSSxpQkFBaUIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO3dCQUM1RCxNQUFNLGlCQUFpQixDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztvQkFDOUMsQ0FBQztvQkFDRCxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ25CLENBQUM7Z0JBQ0QsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2xDLENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLElBQUksSUFBSSxFQUFFLENBQUM7b0JBQ1QsTUFBTSxhQUFhLEdBQUcsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQ2xELElBQUksRUFDSixHQUFHLEVBQ0gsbUJBQW1CLENBQ3BCLENBQUM7b0JBQ0YsSUFBSSxhQUFhLEVBQUUsQ0FBQzt3QkFDbEIsTUFBTSxJQUFJLGNBQWMsQ0FDdEIsQ0FBQyxLQUFLLEVBQUUsYUFBYSxDQUFDLEVBQ3RCLDhEQUE4RCxDQUMvRCxDQUFDO29CQUNKLENBQUM7Z0JBQ0gsQ0FBQztnQkFDRCxNQUFNLEtBQUssQ0FBQztZQUNkLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxLQUFLLENBQUMsV0FBVyxDQUFDLEtBQWE7UUFDcEMsT0FBTyxJQUFJLENBQUMsc0JBQXNCLENBQUMsS0FBSyxJQUFJLEVBQUU7WUFDNUMsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDeEMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU0sS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFhO1FBQ2pDLE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssSUFBSSxFQUFFO1lBQzVDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbkMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFdBQVcsS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzlDLElBQUksU0FBUyxFQUFFLENBQUM7Z0JBQ2QsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2pDLENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFNLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDeEUsQ0FBQztZQUNELElBQUksQ0FBQztnQkFDSCxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO29CQUN6QixNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ3pCLENBQUM7WUFDSCxDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZixJQUNFLFNBQVM7dUJBQ04sSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTO3VCQUN6QixJQUFJLENBQUMsV0FBVyxLQUFLLEdBQUcsQ0FBQyxFQUFFO3VCQUMzQixHQUFHLENBQUMsTUFBTSxLQUFLLE1BQU0sRUFDeEIsQ0FBQztvQkFDRCxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ2xDLENBQUM7Z0JBQ0QsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUNqQixNQUFNLEtBQUssQ0FBQztZQUNkLENBQUM7WUFFRCxHQUFHLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztZQUNuQixJQUFJLENBQUMsbUJBQW1CLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3pCLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUVuQyxJQUFJLFNBQVMsRUFBRSxDQUFDO2dCQUNkLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO2dCQUN4QixNQUFNLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1lBQ3RDLENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDbkIsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLEtBQUssQ0FBQyxRQUFRLENBQUMsVUFBdUM7UUFDM0QsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDN0MsT0FBTyxJQUFJLENBQUMsc0JBQXNCLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ2xELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDeEQsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUNwQixHQUFHLEVBQ0gsS0FBSyxJQUFJLEVBQUU7Z0JBQ1QsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLGdDQUFnQyxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO1lBQ3RGLENBQUMsRUFDRCxNQUFNLENBQ1AsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLEtBQUssQ0FBQyxJQUFJLENBQUMsYUFBNEMsRUFBRTtRQUM5RCxPQUFPLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDbEQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN4RCxNQUFNLElBQUksQ0FBQyxXQUFXLENBQ3BCLEdBQUcsRUFDSCxLQUFLLElBQUksRUFBRTtnQkFDVCxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxnQ0FBZ0MsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztZQUNuRixDQUFDLEVBQ0QsTUFBTSxDQUNQLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxLQUFLLENBQUMsT0FBTyxDQUFDLGFBQTRDLEVBQUU7UUFDakUsT0FBTyxJQUFJLENBQUMsc0JBQXNCLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ2xELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDeEQsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUNwQixHQUFHLEVBQ0gsS0FBSyxJQUFJLEVBQUU7Z0JBQ1QsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsZ0NBQWdDLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFDdEYsQ0FBQyxFQUNELE1BQU0sQ0FDUCxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU0sS0FBSyxDQUFDLE1BQU0sQ0FBQyxhQUE0QyxFQUFFO1FBQ2hFLE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNsRCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3hELE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FDcEIsR0FBRyxFQUNILEtBQUssSUFBSSxFQUFFO2dCQUNULE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGdDQUFnQyxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO1lBQ25GLENBQUMsRUFDRCxNQUFNLENBQ1AsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLEtBQUssQ0FBQyxXQUFXLENBQUMsV0FBaUM7UUFDeEQsTUFBTSxRQUFRLEdBQUcsaUJBQWlCLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDaEQsT0FBTyxJQUFJLENBQUMsc0JBQXNCLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ2xELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3BDLE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUMvQixJQUFJLENBQUM7Z0JBQ0gsSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7b0JBQ25CLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQztnQkFDdEIsQ0FBQztnQkFDRCxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLHVCQUF1QixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7Z0JBQzlELElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxHQUFHLFFBQVEsRUFBRSxDQUFDO2dCQUNoQyxJQUFJLENBQUMsZ0JBQWdCLElBQUksQ0FBQyxDQUFDO2dCQUMzQixHQUFHLENBQUMsdUJBQXVCLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDO2dCQUNwRCxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDbkIsQ0FBQztvQkFBUyxDQUFDO2dCQUNULElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLElBQUksSUFBSSxDQUFDLFdBQVcsS0FBSyxHQUFHLENBQUMsRUFBRSxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssTUFBTSxFQUFFLENBQUM7b0JBQ3RGLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDbEMsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxLQUFLLENBQUMsYUFBYSxDQUFDLEtBQTZCO1FBQ3RELE1BQU0sRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzlELElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzQyxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxLQUFLLE1BQU07WUFDaEMsQ0FBQyxDQUFDLFlBQVk7WUFDZCxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxNQUFNO2dCQUNyQixDQUFDLENBQUMsY0FBYztnQkFDaEIsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssSUFBSTtvQkFDbkIsQ0FBQyxDQUFDLGVBQWU7b0JBQ2pCLENBQUMsQ0FBQyxTQUFTLENBQUM7UUFDbEIsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1YsTUFBTSxJQUFJLEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO1FBQ2hFLENBQUM7UUFDRCxNQUFNLGNBQWMsR0FBRyxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDOUUsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sSUFBSSxDQUFDLElBQUksS0FBSyxZQUFZLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDekUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUNyQyxNQUFNLElBQUksS0FBSyxDQUFDLHlCQUF5QixDQUFDLENBQUM7UUFDN0MsQ0FBQztRQUNELE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLEtBQUssU0FBUztZQUN6QyxDQUFDLENBQUMsU0FBUztZQUNYLENBQUMsQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3JELE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxVQUFVLEtBQUssU0FBUztZQUMvQyxDQUFDLENBQUMsU0FBUztZQUNYLENBQUMsQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxZQUFZLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRTFELElBQUksQ0FBQztZQUNILE1BQU0sVUFBVSxDQUFDLElBQUksQ0FBQywwQkFBMEIsRUFBRTtnQkFDaEQsSUFBSTtnQkFDSixDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7Z0JBQ1YsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUNWLE1BQU07Z0JBQ04sT0FBTztnQkFDUCxVQUFVO2dCQUNWLFNBQVMsRUFBRSxJQUFJLENBQUMsa0JBQWtCLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQztnQkFDbkQsV0FBVyxFQUFFLE9BQU87YUFDckIsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixJQUFJLENBQUMsOEJBQThCLENBQUMsR0FBRyxFQUFFLFVBQVUsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUM1RCxNQUFNLEtBQUssQ0FBQztRQUNkLENBQUM7SUFDSCxDQUFDO0lBRU0sS0FBSyxDQUFDLGFBQWEsQ0FBQyxLQUE2QjtRQUN0RCxNQUFNLEVBQUUsR0FBRyxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM5RCxJQUFJLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0Msb0JBQW9CLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDaEUsb0JBQW9CLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDaEUsSUFBSSxDQUFDO1lBQ0gsTUFBTSxVQUFVLENBQUMsSUFBSSxDQUFDLDBCQUEwQixFQUFFO2dCQUNoRCxJQUFJLEVBQUUsWUFBWTtnQkFDbEIsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUNWLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDVixNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07Z0JBQ3BCLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTTtnQkFDcEIsU0FBUyxFQUFFLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDO2dCQUNuRCxXQUFXLEVBQUUsT0FBTzthQUNyQixDQUFDLENBQUM7UUFDTCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxHQUFHLEVBQUUsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQzVELE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUM7SUFFTSxLQUFLLENBQUMsV0FBVyxDQUFDLEtBQTJCO1FBQ2xELE1BQU0sRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzlELE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTTtZQUNoQyxDQUFDLENBQUMsU0FBUztZQUNYLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLElBQUk7Z0JBQ25CLENBQUMsQ0FBQyxPQUFPO2dCQUNULENBQUMsQ0FBQyxTQUFTLENBQUM7UUFDaEIsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1YsTUFBTSxJQUFJLEtBQUssQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO1FBQ3ZELENBQUM7UUFDRCxNQUFNLEdBQUcsR0FBRyxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDM0QsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksS0FBSyxTQUFTO1lBQ25DLENBQUMsQ0FBQyxTQUFTO1lBQ1gsQ0FBQyxDQUFDLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNyRCxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxLQUFLLFNBQVM7WUFDbkMsQ0FBQyxDQUFDLFNBQVM7WUFDWCxDQUFDLENBQUMscUJBQXFCLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3ZELE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQyxjQUFjLEtBQUssU0FBUztZQUN2RCxDQUFDLENBQUMsU0FBUztZQUNYLENBQUMsQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsY0FBYyxFQUFFLGdCQUFnQixFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMzRSxNQUFNLHFCQUFxQixHQUFHLEtBQUssQ0FBQyxxQkFBcUIsS0FBSyxTQUFTO1lBQ3JFLENBQUMsQ0FBQyxTQUFTO1lBQ1gsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLEVBQUUsdUJBQXVCLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3BGLE1BQU0sb0JBQW9CLEdBQUcsS0FBSyxDQUFDLG9CQUFvQixLQUFLLFNBQVM7WUFDbkUsQ0FBQyxDQUFDLFNBQVM7WUFDWCxDQUFDLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsRUFBRSxzQkFBc0IsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDbEYsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLFFBQVEsS0FBSyxTQUFTO1lBQzNDLENBQUMsQ0FBQyxTQUFTO1lBQ1gsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDdEQsdUJBQXVCLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUN4RCx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBRXBELElBQUksQ0FBQztZQUNILE1BQU0sVUFBVSxDQUFDLElBQUksQ0FBQyx3QkFBd0IsRUFBRTtnQkFDOUMsSUFBSTtnQkFDSixHQUFHO2dCQUNILElBQUk7Z0JBQ0osSUFBSTtnQkFDSixjQUFjO2dCQUNkLHFCQUFxQjtnQkFDckIsb0JBQW9CO2dCQUNwQixVQUFVLEVBQUUsS0FBSyxDQUFDLFVBQVU7Z0JBQzVCLFFBQVEsRUFBRSxLQUFLLENBQUMsUUFBUTtnQkFDeEIsUUFBUTtnQkFDUixTQUFTLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUM7YUFDcEQsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixJQUFJLENBQUMsOEJBQThCLENBQUMsR0FBRyxFQUFFLFVBQVUsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUM1RCxNQUFNLEtBQUssQ0FBQztRQUNkLENBQUM7SUFDSCxDQUFDO0lBRU0sS0FBSyxDQUFDLFVBQVUsQ0FBQyxLQUFrQztRQUN4RCxNQUFNLEVBQUUsR0FBRyxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM5RCxNQUFNLElBQUksR0FBRyxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDekUsSUFBSSxDQUFDO1lBQ0gsTUFBTSxVQUFVLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUN0RCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxHQUFHLEVBQUUsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQzVELE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUM7SUFFTSxLQUFLLENBQUMsZUFBZSxDQUMxQixhQUEwQyxFQUFFO1FBRTVDLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDO1FBQzNDLElBQUksTUFBTSxLQUFLLE1BQU0sSUFBSSxNQUFNLEtBQUssS0FBSyxFQUFFLENBQUM7WUFDMUMsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQ0FBcUMsQ0FBQyxDQUFDO1FBQ3pELENBQUM7UUFDRCxNQUFNLE9BQU8sR0FBRyxVQUFVLENBQUMsT0FBTyxLQUFLLFNBQVM7WUFDOUMsQ0FBQyxDQUFDLFNBQVM7WUFDWCxDQUFDLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUMzRCxJQUFJLE1BQU0sS0FBSyxLQUFLLElBQUksT0FBTyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzlDLE1BQU0sSUFBSSxLQUFLLENBQUMsOENBQThDLENBQUMsQ0FBQztRQUNsRSxDQUFDO1FBQ0QsSUFBSSxVQUFVLElBQUksVUFBVSxFQUFFLENBQUM7WUFDN0IsTUFBTSxJQUFJLEtBQUssQ0FBQyw0REFBNEQsQ0FBQyxDQUFDO1FBQ2hGLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDbEQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNwRCxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNsQyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2xELElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNuQixNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUM7WUFDdEIsQ0FBQztZQUNELE1BQU0sUUFBUSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDdEMsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7WUFDL0MsTUFBTSxJQUFJLEdBQUcsTUFBTSxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQztnQkFDN0MsSUFBSSxFQUFFLE1BQU07Z0JBQ1osR0FBRyxDQUFDLE1BQU0sS0FBSyxNQUFNLElBQUksT0FBTyxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2FBQ25FLENBQUMsQ0FBQztZQUNILElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNuQixNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUM7WUFDdEIsQ0FBQztZQUNELE1BQU0sVUFBVSxHQUFHLG1CQUFtQixDQUFDLElBQUksRUFBRSxNQUFNLEVBQUU7Z0JBQ25ELEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFDLGlCQUFpQixDQUFDO2dCQUM5RCxNQUFNLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQzthQUNqRSxDQUFDLENBQUM7WUFDSCxPQUFPO2dCQUNMLEtBQUssRUFBRSxXQUFXLENBQUMsRUFBRTtnQkFDckIsZ0JBQWdCO2dCQUNoQixRQUFRO2dCQUNSLE1BQU07Z0JBQ04sUUFBUSxFQUFFLE1BQU0sS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsV0FBVztnQkFDeEQsR0FBRyxVQUFVO2dCQUNiLElBQUk7YUFDTCxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU0sS0FBSyxDQUFDLE9BQU8sQ0FBQyxhQUF5QyxFQUFFO1FBQzlELE1BQU0sYUFBYSxHQUFHLFVBQVUsQ0FBQyxhQUFhLEtBQUssU0FBUztZQUMxRCxDQUFDLENBQUMsS0FBSztZQUNQLENBQUMsQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLGFBQWEsRUFBRSxlQUFlLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzNFLE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNsRCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3BELE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2xDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDbEQsSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ25CLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQztZQUN0QixDQUFDO1lBQ0QsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ25DLE1BQU0scUJBQXFCLEdBQUcsTUFBTSxXQUFXLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUM7Z0JBQzFFLGVBQWUsRUFBRSxJQUFJO2FBQ3RCLENBQUMsQ0FBQztZQUNILElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNuQixNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUM7WUFDdEIsQ0FBQztZQUNELE1BQU0sTUFBTSxHQUFHO2dCQUNiLFFBQVEsV0FBVyxDQUFDLEVBQUUsRUFBRTtnQkFDeEIsV0FBVyxXQUFXLENBQUMsTUFBTSxFQUFFO2dCQUMvQixVQUFVLFdBQVcsQ0FBQyxLQUFLLEVBQUU7Z0JBQzdCLFFBQVEsV0FBVyxDQUFDLEdBQUcsRUFBRTtnQkFDekIsZ0JBQWdCO2FBQ2pCLENBQUM7WUFDRixNQUFNLEtBQUssR0FBRyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUM7WUFDMUIsSUFBSSxxQkFBcUIsR0FBRyxLQUFLLENBQUM7WUFFbEMsTUFBTSxVQUFVLEdBQUcsQ0FDakIsSUFBd0MsRUFDeEMsS0FBYSxFQUNQLEVBQUU7Z0JBQ1IsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sSUFBSSxhQUFhLEVBQUUsQ0FBQztvQkFDN0MscUJBQXFCLEdBQUcsSUFBSSxDQUFDO29CQUM3QixPQUFPO2dCQUNULENBQUM7Z0JBQ0QsTUFBTSxPQUFPLEdBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3RDLElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO29CQUNkLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ2hELENBQUM7Z0JBQ0QsSUFBSSxJQUFJLENBQUMsS0FBSyxLQUFLLFNBQVMsRUFBRSxDQUFDO29CQUM3QixPQUFPLENBQUMsSUFBSSxDQUFDLFVBQVUsUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUMvRCxDQUFDO2dCQUNELEtBQUssTUFBTSxRQUFRLElBQUk7b0JBQ3JCLFVBQVU7b0JBQ1YsVUFBVTtvQkFDVixTQUFTO29CQUNULFVBQVU7b0JBQ1YsVUFBVTtvQkFDVixVQUFVO29CQUNWLFNBQVM7b0JBQ1QsU0FBUztpQkFDRCxFQUFFLENBQUM7b0JBQ1gsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO29CQUM3QixJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxLQUFLLEtBQUssRUFBRSxDQUFDO3dCQUMzQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsUUFBUSxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7b0JBQy9DLENBQUM7Z0JBQ0gsQ0FBQztnQkFDRCxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUN4RSxLQUFLLE1BQU0sS0FBSyxJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksRUFBRSxFQUFFLENBQUM7b0JBQ3hDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDO29CQUM3QixJQUFJLHFCQUFxQixFQUFFLENBQUM7d0JBQzFCLE1BQU07b0JBQ1IsQ0FBQztnQkFDSCxDQUFDO1lBQ0gsQ0FBQyxDQUFDO1lBRUYsSUFBSSxxQkFBcUIsRUFBRSxDQUFDO2dCQUMxQixVQUFVLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDdkMsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLEtBQUssQ0FBQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsQ0FBQztZQUN6QyxDQUFDO1lBRUQsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN2QyxNQUFNLGFBQWEsR0FBRyxhQUFhLENBQUMsTUFBTSxHQUFHLGFBQWE7Z0JBQ3hELENBQUMsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxhQUFhLENBQUM7Z0JBQ3ZDLENBQUMsQ0FBQyxhQUFhLENBQUM7WUFDbEIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzlCLE9BQU87Z0JBQ0wsS0FBSyxFQUFFLFdBQVcsQ0FBQyxFQUFFO2dCQUNyQixHQUFHLEVBQUUsV0FBVyxDQUFDLEdBQUc7Z0JBQ3BCLEtBQUssRUFBRSxXQUFXLENBQUMsS0FBSztnQkFDeEIsR0FBRyxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDO2dCQUNyQyxLQUFLO2dCQUNMLElBQUksRUFBRSxhQUFhO2dCQUNuQixTQUFTLEVBQUUscUJBQXFCLElBQUksYUFBYSxDQUFDLE1BQU0sR0FBRyxhQUFhO2FBQ3pFLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxLQUFLLENBQUMsS0FBSyxDQUFDLFVBQW9DO1FBQ3JELE1BQU0sUUFBUSxHQUFHLHFCQUFxQixDQUNwQyxVQUFVLENBQUMsUUFBUSxFQUNuQixVQUFVLEVBQ1YsQ0FBQyxFQUNELGlCQUFpQixDQUNsQixDQUFDO1FBQ0YsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDM0QsTUFBTSxjQUFjLEdBQUcsQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ25ELElBQUksVUFBVSxDQUFDLE1BQU0sS0FBSyxTQUFTLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQ25GLE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUM3QyxDQUFDO1FBQ0QsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLFVBQVUsS0FBSyxTQUFTO1lBQ3BELENBQUMsQ0FBQyxTQUFTO1lBQ1gsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLFlBQVksRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDL0QsT0FBTyxJQUFJLENBQUMsc0JBQXNCLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ2xELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUN6RCxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNsQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsMkJBQTJCLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDL0QsTUFBTSxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxDQUFDO2dCQUMvRCxNQUFNLEVBQUUsVUFBVSxDQUFDLE1BQU07Z0JBQ3pCLEtBQUssRUFBRSxVQUFVO2dCQUNqQixNQUFNO2FBQ1AsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ2pDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNuQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQW1DO1FBQ25ELE1BQU0sUUFBUSxHQUFHLHFCQUFxQixDQUNwQyxVQUFVLENBQUMsUUFBUSxFQUNuQixVQUFVLEVBQ1YsQ0FBQyxFQUNELGlCQUFpQixDQUNsQixDQUFDO1FBQ0YsTUFBTSxJQUFJLEdBQUcscUJBQXFCLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQzlFLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzNELE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNsRCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsMkJBQTJCLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDekQsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDbEMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLDJCQUEyQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQy9ELE1BQU0sU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQ2xGLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUNqQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDbkIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxVQUFvQztRQUNyRCxNQUFNLFFBQVEsR0FBRyxxQkFBcUIsQ0FDcEMsVUFBVSxDQUFDLFFBQVEsRUFDbkIsVUFBVSxFQUNWLENBQUMsRUFDRCxpQkFBaUIsQ0FDbEIsQ0FBQztRQUNGLE1BQU0sR0FBRyxHQUFHLHFCQUFxQixDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNoRSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMzRCxPQUFPLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDbEQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLDJCQUEyQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3pELE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2xDLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUMvRCxNQUFNLE9BQU8sR0FBRyxNQUFNLFNBQVMsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsRUFBRTtnQkFDN0QsT0FBTyxFQUFFLElBQUk7Z0JBQ2IsT0FBTztnQkFDUCxNQUFNO2FBQ1AsQ0FBQyxDQUFDO1lBQ0gsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNiLE1BQU0sSUFBSSxLQUFLLENBQUMsd0NBQXdDLFFBQVEsRUFBRSxDQUFDLENBQUM7WUFDdEUsQ0FBQztZQUNELElBQUksQ0FBQztnQkFDSCxNQUFNLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBaUMsQ0FBQyxDQUFDO1lBQ3pELENBQUM7b0JBQVMsQ0FBQztnQkFDVCxNQUFNLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUMxQixDQUFDO1lBQ0QsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ2pDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNuQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxzQkFBc0IsQ0FDNUIsU0FBOEM7UUFFOUMsSUFDRSxJQUFJLENBQUMsTUFBTSxLQUFLLFVBQVU7ZUFDdkIsSUFBSSxDQUFDLG1CQUFtQjtlQUN4QixDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxFQUN2RCxDQUFDO1lBQ0QsT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLGdDQUFnQyxDQUFDLENBQUMsQ0FBQztRQUNyRSxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsd0JBQXdCLElBQUkseUJBQXlCLEVBQUUsQ0FBQztZQUMvRCxPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsNENBQTRDLENBQUMsQ0FBQyxDQUFDO1FBQ2pGLENBQUM7UUFDRCxJQUFJLENBQUMsd0JBQXdCLElBQUksQ0FBQyxDQUFDO1FBQ25DLE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBRU8sd0JBQXdCLENBQzlCLFNBQWlELEVBQ2pELFFBQVEsR0FBRyxLQUFLO1FBRWhCLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxVQUFVLEVBQUUsQ0FBQztZQUM1RCxPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsZ0NBQWdDLENBQUMsQ0FBQyxDQUFDO1FBQ3JFLENBQUM7UUFDRCxJQUFJLENBQUMsMEJBQTBCLElBQUksQ0FBQyxDQUFDO1FBQ3JDLE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUFDLFVBQVUsRUFBRSxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUVPLHNCQUFzQixDQUM1QixJQUEwQixFQUMxQixTQUE4QyxFQUM5QyxRQUFRLEdBQUcsS0FBSztRQUVoQixPQUFPLElBQUksT0FBTyxDQUFJLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3hDLE1BQU0sZUFBZSxHQUFxQjtnQkFDeEMsSUFBSTtnQkFDSixVQUFVLEVBQUUsSUFBSSxlQUFlLEVBQUU7Z0JBQ2pDLEdBQUcsRUFBRSxTQUFTO2dCQUNkLE9BQU8sRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQVUsQ0FBQztnQkFDdkMsTUFBTTthQUNQLENBQUM7WUFDRixJQUFJLFFBQVEsRUFBRSxDQUFDO2dCQUNiLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQy9DLENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUM1QyxDQUFDO1lBQ0QsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDN0IsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sbUJBQW1CO1FBQ3pCLElBQUksSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDMUIsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3BELElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUNyQixPQUFPO1FBQ1QsQ0FBQztRQUNELElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7UUFDN0IsSUFBSSxDQUFDLGVBQWUsR0FBRyxlQUFlLENBQUM7UUFDdkMsS0FBSyxJQUFJLENBQUMsc0JBQXNCLENBQUMsZUFBZSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDaEUsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEtBQUssQ0FBQztZQUM5QixJQUFJLENBQUMsZUFBZSxHQUFHLFNBQVMsQ0FBQztZQUNqQyxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUNiLElBQUksRUFBRSw0QkFBNEI7Z0JBQ2xDLE9BQU8sRUFBRSxxQkFBcUIsQ0FBQyxLQUFLLENBQUM7Z0JBQ3JDLEtBQUssRUFBRSxJQUFJO2FBQ1osQ0FBQyxDQUFDO1lBQ0gsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDN0IsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sS0FBSyxDQUFDLHNCQUFzQixDQUFDLGVBQWlDO1FBQ3BFLElBQUksQ0FBQztZQUNILElBQUksZUFBZSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQzlDLE1BQU0sZUFBZSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO1lBQ2pELENBQUM7WUFDRCxlQUFlLENBQUMsT0FBTyxDQUFDLE1BQU0sZUFBZSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDeEYsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixlQUFlLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2hDLENBQUM7Z0JBQVMsQ0FBQztZQUNULElBQUksZUFBZSxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDdEMsSUFBSSxDQUFDLHdCQUF3QixJQUFJLENBQUMsQ0FBQztZQUNyQyxDQUFDO2lCQUFNLElBQUksZUFBZSxDQUFDLElBQUksS0FBSyxVQUFVLEVBQUUsQ0FBQztnQkFDL0MsSUFBSSxDQUFDLDBCQUEwQixJQUFJLENBQUMsQ0FBQztZQUN2QyxDQUFDO1lBQ0QsSUFBSSxJQUFJLENBQUMsZUFBZSxLQUFLLGVBQWUsRUFBRSxDQUFDO2dCQUM3QyxJQUFJLENBQUMsZUFBZSxHQUFHLFNBQVMsQ0FBQztZQUNuQyxDQUFDO1lBQ0QsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEtBQUssQ0FBQztZQUM5QixJQUNFLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUzttQkFDdEIsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksS0FBSyxVQUFVLENBQUMsRUFDMUUsQ0FBQztnQkFDRCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsS0FBSyxDQUFDO1lBQ25DLENBQUM7WUFDRCxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQUM3QixDQUFDO0lBQ0gsQ0FBQztJQUVPLHNCQUFzQixDQUFDLEtBQVk7UUFDekMsS0FBSyxNQUFNLGVBQWUsSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQzVELGVBQWUsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3hDLElBQUksZUFBZSxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDdEMsSUFBSSxDQUFDLHdCQUF3QixJQUFJLENBQUMsQ0FBQztZQUNyQyxDQUFDO2lCQUFNLElBQUksZUFBZSxDQUFDLElBQUksS0FBSyxVQUFVLEVBQUUsQ0FBQztnQkFDL0MsSUFBSSxDQUFDLDBCQUEwQixJQUFJLENBQUMsQ0FBQztZQUN2QyxDQUFDO1lBQ0QsZUFBZSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNoQyxDQUFDO0lBQ0gsQ0FBQztJQUVPLGFBQWEsQ0FBQyxvQkFBNkI7UUFDakQsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQzVELElBQUksQ0FBQyxNQUFNLEdBQUcsVUFBVSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNuQixDQUFDO1FBQ0QsTUFBTSxhQUFhLEdBQUcsSUFBSSxLQUFLLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztRQUNsRSxJQUNFLG9CQUFvQjtlQUNqQixJQUFJLENBQUMsZUFBZTtlQUNwQixJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksS0FBSyxVQUFVLEVBQzNDLENBQUM7WUFDRCxJQUFJLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDdkQsQ0FBQztRQUNELElBQUksSUFBSSxDQUFDLHlCQUF5QixJQUFJLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNyRixJQUFJLENBQUMseUJBQXlCLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ3RELENBQUM7UUFDRCxJQUFJLENBQUMsc0JBQXNCLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUVPLGVBQWUsQ0FBQyxLQUF5QjtRQUMvQyxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDOUIsT0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDM0IsQ0FBQztRQUNELElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3pCLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQztRQUM5QixDQUFDO1FBQ0QsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN6QixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsc0JBQXNCLENBQ2pELFVBQVUsRUFDVixLQUFLLElBQUksRUFBRSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLEVBQ3BDLElBQUksQ0FDTCxDQUFDO1FBQ0YsSUFBSSxDQUFDLGVBQWUsR0FBRyxlQUFlLENBQUM7UUFDdkMsS0FBSyxlQUFlLENBQUMsSUFBSSxDQUN2QixHQUFHLEVBQUU7WUFDSCxJQUFJLElBQUksQ0FBQyxlQUFlLEtBQUssZUFBZSxFQUFFLENBQUM7Z0JBQzdDLElBQUksQ0FBQyxlQUFlLEdBQUcsU0FBUyxDQUFDO1lBQ25DLENBQUM7UUFDSCxDQUFDLEVBQ0QsR0FBRyxFQUFFO1lBQ0gsSUFBSSxJQUFJLENBQUMsZUFBZSxLQUFLLGVBQWUsRUFBRSxDQUFDO2dCQUM3QyxJQUFJLENBQUMsZUFBZSxHQUFHLFNBQVMsQ0FBQztZQUNuQyxDQUFDO1FBQ0gsQ0FBQyxDQUNGLENBQUM7UUFDRixPQUFPLGVBQWUsQ0FBQztJQUN6QixDQUFDO0lBRU8saUJBQWlCLENBQ3ZCLFNBQWlELEVBQ2pELFNBQWlCLEVBQ2pCLEtBQWMsRUFDZCxRQUFRLEdBQUcsS0FBSztRQUVoQixJQUFJLElBQUksQ0FBQywwQkFBMEIsSUFBSSwyQkFBMkIsRUFBRSxDQUFDO1lBQ25FLE1BQU0sVUFBVSxHQUFHLElBQUksS0FBSyxDQUFDLHFEQUFxRCxDQUFDLENBQUM7WUFDcEYsTUFBTSxnQkFBZ0IsR0FBc0I7Z0JBQzFDLElBQUksRUFBRSwrQkFBK0I7Z0JBQ3JDLE9BQU8sRUFBRSxVQUFVLENBQUMsT0FBTztnQkFDM0IsS0FBSyxFQUFFLFFBQVE7Z0JBQ2YsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2FBQzVCLENBQUM7WUFDRixJQUFJLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLENBQUM7WUFDakMsSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDYixLQUFLLElBQUksQ0FBQyxlQUFlLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtvQkFDMUQsSUFBSSxDQUFDLFNBQVMsQ0FBQzt3QkFDYixJQUFJLEVBQUUsZ0NBQWdDO3dCQUN0QyxPQUFPLEVBQUUscUJBQXFCLENBQUMsS0FBSyxDQUFDO3dCQUNyQyxLQUFLLEVBQUUsSUFBSTtxQkFDWixDQUFDLENBQUM7Z0JBQ0wsQ0FBQyxDQUFDLENBQUM7WUFDTCxDQUFDO1lBQ0QsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBQ0QsS0FBSyxJQUFJLENBQUMsd0JBQXdCLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ3RFLElBQ0UsSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTO21CQUN0QixJQUFJLENBQUMsTUFBTSxLQUFLLFVBQVU7bUJBQzFCLElBQUksQ0FBQyxtQkFBbUIsRUFDM0IsQ0FBQztnQkFDRCxPQUFPO1lBQ1QsQ0FBQztZQUNELElBQUksQ0FBQyxTQUFTLENBQUM7Z0JBQ2IsSUFBSSxFQUFFLFNBQVM7Z0JBQ2YsT0FBTyxFQUFFLHFCQUFxQixDQUFDLEtBQUssQ0FBQztnQkFDckMsS0FBSyxFQUFFLEtBQUs7Z0JBQ1osR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2FBQzVCLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU8sU0FBUyxDQUFDLEtBQXdCO1FBQ3hDLEtBQUssTUFBTSxRQUFRLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDO1lBQ2hELElBQUksQ0FBQztnQkFDSCxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbEIsQ0FBQztZQUFDLE1BQU0sQ0FBQztnQkFDUCxvRUFBb0U7WUFDdEUsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRU8sU0FBUztRQUNmLElBQUksQ0FBQyxTQUFTLENBQUM7WUFDYixJQUFJLEVBQUUsT0FBTztZQUNiLEtBQUssRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFO1NBQ3ZCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxTQUFTLENBQUMsS0FBd0I7UUFDeEMsSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDaEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxFQUFFLEdBQUcsS0FBSyxFQUFFLENBQUM7UUFDaEMsQ0FBQztRQUNELElBQUksQ0FBQyxTQUFTLENBQUM7WUFDYixJQUFJLEVBQUUsT0FBTztZQUNiLEtBQUssRUFBRSxFQUFFLEdBQUcsS0FBSyxFQUFFO1NBQ3BCLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUNuQixDQUFDO0lBRU8sY0FBYyxDQUFDLEdBQTJCO1FBQ2hELE9BQU87WUFDTCxFQUFFLEVBQUUsR0FBRyxDQUFDLEVBQUU7WUFDVixHQUFHLEVBQUUsR0FBRyxDQUFDLEdBQUc7WUFDWixLQUFLLEVBQUUsR0FBRyxDQUFDLEtBQUs7WUFDaEIsTUFBTSxFQUFFLElBQUksQ0FBQyxXQUFXLEtBQUssR0FBRyxDQUFDLEVBQUU7WUFDbkMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNO1lBQ2xCLFVBQVUsRUFBRSxHQUFHLENBQUMsVUFBVTtZQUMxQix1QkFBdUIsRUFBRSxHQUFHLENBQUMsdUJBQXVCO1lBQ3BELFNBQVMsRUFBRSxHQUFHLENBQUMsU0FBUztTQUN6QixDQUFDO0lBQ0osQ0FBQztJQUVPLEtBQUssQ0FBQyxZQUFZLENBQUMsS0FBeUI7UUFDbEQsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzlCLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUM7UUFDekIsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUNWLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxDQUFDO1FBQ2hDLENBQUM7UUFDRCxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDakIsSUFBSSxJQUFJLENBQUMseUJBQXlCLElBQUksQ0FBQyxJQUFJLENBQUMseUJBQXlCLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3JGLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsZ0NBQWdDLENBQUMsQ0FBQyxDQUFDO1FBQ3BGLENBQUM7UUFFRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBQzdCLElBQUksT0FBTyxJQUFJLElBQUksQ0FBQywyQkFBMkIsRUFBRSxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1FBQ2hFLENBQUM7UUFDRCxJQUFJLENBQUMsMkJBQTJCLEdBQUcsU0FBUyxDQUFDO1FBRTdDLE1BQU0sY0FBYyxHQUFjLEVBQUUsQ0FBQztRQUNyQyxLQUFLLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUMxQyxHQUFHLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztZQUNuQixJQUFJLENBQUM7Z0JBQ0gsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2pDLENBQUM7WUFBQyxPQUFPLFlBQVksRUFBRSxDQUFDO2dCQUN0QixjQUFjLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3BDLENBQUM7WUFDRCxJQUFJLENBQUM7Z0JBQ0gsSUFBSSxDQUFDLG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2hDLENBQUM7WUFBQyxPQUFPLFlBQVksRUFBRSxDQUFDO2dCQUN0QixjQUFjLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3BDLENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLENBQUMsdUJBQXVCLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDakQsQ0FBQztRQUFDLE9BQU8sWUFBWSxFQUFFLENBQUM7WUFDdEIsY0FBYyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNwQyxDQUFDO1FBRUQsSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUNaLElBQUksQ0FBQztnQkFDSCxNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUN4QixDQUFDO1lBQUMsT0FBTyxVQUFVLEVBQUUsQ0FBQztnQkFDcEIsY0FBYyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNsQyxDQUFDO1FBQ0gsQ0FBQztRQUVELEtBQUssTUFBTSxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1lBQ3JDLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNyQyxDQUFDO1FBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNsQixJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDL0IsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUM7UUFDekIsSUFBSSxDQUFDLGNBQWMsR0FBRyxTQUFTLENBQUM7UUFDaEMsSUFBSSxDQUFDLHlCQUF5QixHQUFHLFNBQVMsQ0FBQztRQUMzQyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztRQUN4QixJQUFJLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQztRQUN4QixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDakIsSUFBSSxjQUFjLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3hDLE1BQU0sSUFBSSxjQUFjLENBQUMsY0FBYyxFQUFFLDRDQUE0QyxDQUFDLENBQUM7UUFDekYsQ0FBQztJQUNILENBQUM7SUFFTyxxQkFBcUI7UUFDM0IsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN0RCxNQUFNLElBQUksS0FBSyxDQUFDLG1DQUFtQyxDQUFDLENBQUM7UUFDdkQsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQztJQUM3QixDQUFDO0lBRU8sVUFBVSxDQUFDLEtBQWE7UUFDOUIscUJBQXFCLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDOUMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDakMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ1QsTUFBTSxJQUFJLEtBQUssQ0FBQyxnQkFBZ0IsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUMzQyxDQUFDO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0lBRU8sZ0JBQWdCO1FBQ3RCLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDbkQsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDO1FBQzFELENBQUM7UUFDRCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM5QyxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssTUFBTSxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztZQUNqRCxNQUFNLElBQUksS0FBSyxDQUFDLGdDQUFnQyxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUM1RCxDQUFDO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0lBRU8sZ0JBQWdCLENBQUMsS0FBYztRQUNyQyxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDOUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO1FBQ3ZELENBQUM7UUFDRCxNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3JFLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxNQUFNLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO1lBQ2pELE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3JELENBQUM7UUFDRCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFTyxvQkFBb0IsQ0FBQyxLQUFjO1FBQ3pDLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFTyxLQUFLLENBQUMsaUJBQWlCLENBQUMsR0FBMkI7UUFDekQsSUFBSSxHQUFHLENBQUMsdUJBQXVCLEtBQUssSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDMUQsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLHVCQUF1QixHQUFHLElBQUksQ0FBQyxXQUFXLEtBQUssR0FBRyxDQUFDLEVBQUUsSUFBSSxHQUFHLENBQUMsU0FBUyxDQUFDO1FBQzdFLElBQUksdUJBQXVCLEVBQUUsQ0FBQztZQUM1QixNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDakMsQ0FBQztRQUNELElBQUksQ0FBQztZQUNILE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDbkUsR0FBRyxDQUFDLHVCQUF1QixHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztRQUN0RCxDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUNFLHVCQUF1QjttQkFDcEIsSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTO21CQUN6QixJQUFJLENBQUMsV0FBVyxLQUFLLEdBQUcsQ0FBQyxFQUFFO21CQUMzQixHQUFHLENBQUMsTUFBTSxLQUFLLE1BQU07bUJBQ3JCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFDdkIsQ0FBQztnQkFDRCxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDbEMsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRU8sS0FBSyxDQUFDLFlBQVksQ0FBQyxJQUE0QjtRQUNyRCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNsRCxJQUFJLGFBQWEsRUFBRSxDQUFDO1lBQ2xCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUN4QyxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztZQUNwQixNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixDQUFDLENBQUM7UUFDbkQsQ0FBQztRQUVELE1BQU0sR0FBRyxHQUEyQjtZQUNsQyxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDL0IsSUFBSTtZQUNKLEdBQUcsRUFBRSxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFLElBQUksQ0FBQztZQUMvQixLQUFLLEVBQUUsRUFBRTtZQUNULE1BQU0sRUFBRSxNQUFNO1lBQ2QsVUFBVSxFQUFFLENBQUM7WUFDYix1QkFBdUIsRUFBRSxDQUFDO1lBQzFCLFNBQVMsRUFBRSxLQUFLO1lBQ2hCLGlCQUFpQixFQUFFLElBQUk7WUFDdkIsb0JBQW9CLEVBQUUsS0FBSztZQUMzQixPQUFPLEVBQUUsS0FBSztZQUNkLGlCQUFpQixFQUFFLEtBQUs7WUFDeEIsa0JBQWtCLEVBQUUsS0FBSztZQUN6QixzQkFBc0IsRUFBRSxLQUFLO1lBQzdCLGVBQWUsRUFBRSxFQUFFO1NBQ3BCLENBQUM7UUFDRixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQzNCLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDcEMsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDbEMsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBRTNCLE1BQU0sT0FBTyxHQUFHLENBQUMsS0FBb0MsRUFBUSxFQUFFO2dCQUM3RCxJQUNFLENBQUMsS0FBSzt1QkFDSCxJQUFJLENBQUMsbUJBQW1CO3VCQUN4QixJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVM7dUJBQ3pCLElBQUksQ0FBQyxNQUFNLEtBQUssVUFBVSxFQUM3QixDQUFDO29CQUNELE9BQU87Z0JBQ1QsQ0FBQztnQkFDRCxNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLElBQUksRUFBRTtvQkFDMUQsSUFBSSxLQUFLLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQzt3QkFDckIsT0FBTztvQkFDVCxDQUFDO29CQUNELE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQztvQkFDN0MsSUFBSSxRQUE0QyxDQUFDO29CQUNqRCxJQUFJLENBQUM7d0JBQ0gsUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQzt3QkFDMUMsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO29CQUM5QyxDQUFDO29CQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7d0JBQ2YsTUFBTSxhQUFhLEdBQUcsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQ2xELEtBQUssRUFDTCxRQUFRLEVBQ1IsbUJBQW1CLENBQ3BCLENBQUM7d0JBQ0YsSUFBSSxhQUFhLEVBQUUsQ0FBQzs0QkFDbEIsTUFBTSxJQUFJLGNBQWMsQ0FBQyxDQUFDLEtBQUssRUFBRSxhQUFhLENBQUMsRUFBRSxvQ0FBb0MsQ0FBQyxDQUFDO3dCQUN6RixDQUFDO3dCQUNELE1BQU0sS0FBSyxDQUFDO29CQUNkLENBQUM7Z0JBQ0gsQ0FBQyxFQUFFLDJCQUEyQixFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDeEMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7b0JBQ3ZCLE1BQU0sVUFBVSxHQUFzQjt3QkFDcEMsSUFBSSxFQUFFLHNDQUFzQzt3QkFDNUMsT0FBTyxFQUFFLCtEQUErRDt3QkFDeEUsS0FBSyxFQUFFLElBQUk7d0JBQ1gsS0FBSyxFQUFFLEdBQUcsQ0FBQyxFQUFFO3FCQUNkLENBQUM7b0JBQ0YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsQ0FBQztvQkFDM0IsS0FBSyxJQUFJLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLGFBQWEsRUFBRSxFQUFFO3dCQUM1RCxJQUFJLENBQUMsU0FBUyxDQUFDOzRCQUNiLElBQUksRUFBRSxpQ0FBaUM7NEJBQ3ZDLE9BQU8sRUFBRSxxQkFBcUIsQ0FBQyxhQUFhLENBQUM7NEJBQzdDLEtBQUssRUFBRSxJQUFJOzRCQUNYLEtBQUssRUFBRSxHQUFHLENBQUMsRUFBRTt5QkFDZCxDQUFDLENBQUM7b0JBQ0wsQ0FBQyxDQUFDLENBQUM7Z0JBQ0wsQ0FBQztZQUNILENBQUMsQ0FBQztZQUNGLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxLQUE4QixFQUFRLEVBQUU7Z0JBQ2hFLElBQUksS0FBSyxLQUFLLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUM7b0JBQzlDLE9BQU87Z0JBQ1QsQ0FBQztnQkFDRCxNQUFNLGVBQWUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQztnQkFDbEQsSUFBSSxlQUFlLEVBQUUsQ0FBQztvQkFDcEIsR0FBRyxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztvQkFDN0IsSUFBSSxDQUFDLDhCQUE4QixDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDOUMsQ0FBQztnQkFDRCxJQUFJLENBQUMscUJBQXFCLENBQUMsR0FBRyxFQUFFLGVBQWUsQ0FBQyxDQUFDO1lBQ25ELENBQUMsQ0FBQztZQUNGLE1BQU0sTUFBTSxHQUFHLEdBQVMsRUFBRTtnQkFDeEIsSUFBSSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN6QyxDQUFDLENBQUM7WUFDRixNQUFNLE9BQU8sR0FBRyxHQUFTLEVBQUU7Z0JBQ3pCLEdBQUcsQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUM7Z0JBQzdCLElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQzVDLElBQUksR0FBRyxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztvQkFDNUMsT0FBTztnQkFDVCxDQUFDO2dCQUNELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLElBQUksRUFBRTtvQkFDaEMsTUFBTSxJQUFJLENBQUMseUJBQXlCLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzVDLENBQUMsRUFBRSwyQkFBMkIsRUFBRSxHQUFHLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ2hELENBQUMsQ0FBQztZQUNGLE1BQU0sT0FBTyxHQUFHLENBQUMsS0FBWSxFQUFRLEVBQUU7Z0JBQ3JDLEdBQUcsQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUM7Z0JBQzdCLElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQzVDLElBQUksR0FBRyxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztvQkFDNUMsT0FBTztnQkFDVCxDQUFDO2dCQUNELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLElBQUksRUFBRTtvQkFDaEMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO3dCQUN2RCxPQUFPO29CQUNULENBQUM7b0JBQ0QsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUMvQixHQUFHLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQztvQkFDdkIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFdBQVcsS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUM5QyxJQUFJLFNBQVMsRUFBRSxDQUFDO3dCQUNkLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO29CQUMxQixDQUFDO29CQUNELElBQUksQ0FBQyxTQUFTLENBQUM7d0JBQ2IsSUFBSSxFQUFFLGNBQWM7d0JBQ3BCLE9BQU8sRUFBRSxxQkFBcUIsQ0FBQyxLQUFLLENBQUM7d0JBQ3JDLEtBQUssRUFBRSxLQUFLO3dCQUNaLEtBQUssRUFBRSxHQUFHLENBQUMsRUFBRTtxQkFDZCxDQUFDLENBQUM7b0JBQ0gsSUFBSSxTQUFTLEVBQUUsQ0FBQzt3QkFDZCxNQUFNLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO29CQUN0QyxDQUFDO2dCQUNILENBQUMsRUFBRSwyQkFBMkIsRUFBRSxHQUFHLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ2hELENBQUMsQ0FBQztZQUNGLE1BQU0sV0FBVyxHQUFHLENBQUMsS0FBYyxFQUFRLEVBQUU7Z0JBQzNDLElBQUksR0FBRyxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztvQkFDNUMsT0FBTztnQkFDVCxDQUFDO2dCQUNELElBQUksQ0FBQyxTQUFTLENBQUM7b0JBQ2IsSUFBSSxFQUFFLFlBQVk7b0JBQ2xCLE9BQU8sRUFBRSxxQkFBcUIsQ0FBQyxLQUFLLENBQUM7b0JBQ3JDLEtBQUssRUFBRSxLQUFLO29CQUNaLEtBQUssRUFBRSxHQUFHLENBQUMsRUFBRTtpQkFDZCxDQUFDLENBQUM7WUFDTCxDQUFDLENBQUM7WUFFRixJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUMxQixJQUFJLENBQUMsRUFBRSxDQUFDLGdCQUFnQixFQUFFLGdCQUFnQixDQUFDLENBQUM7WUFDNUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDeEIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDMUIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDMUIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxXQUFXLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFDbEMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQ3RCLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxFQUNoQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLGdCQUFnQixDQUFDLEVBQ2xELEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxFQUM5QixHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsRUFDaEMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLEVBQ2hDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLFdBQVcsQ0FBQyxDQUN6QyxDQUFDO1lBQ0YsT0FBTyxHQUFHLENBQUM7UUFDYixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUM5QixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDekIsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDL0IsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUVPLG1CQUFtQixDQUFDLEdBQTJCO1FBQ3JELEtBQUssTUFBTSxjQUFjLElBQUksR0FBRyxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUMzRCxjQUFjLEVBQUUsQ0FBQztRQUNuQixDQUFDO0lBQ0gsQ0FBQztJQUVPLDhCQUE4QixDQUFDLEtBQWE7UUFDbEQsS0FBSyxJQUFJLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLEtBQUssS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDbEYsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO2dCQUMzRCxJQUFJLENBQUMsU0FBUyxDQUFDO29CQUNiLElBQUksRUFBRSx5QkFBeUI7b0JBQy9CLE9BQU8sRUFBRSxxQkFBcUIsQ0FBQyxLQUFLLENBQUM7b0JBQ3JDLEtBQUssRUFBRSxLQUFLO29CQUNaLEtBQUs7aUJBQ04sQ0FBQyxDQUFDO1lBQ0wsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLHFCQUFxQixDQUMzQixHQUEyQixFQUMzQixlQUF3QjtRQUV4QixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUMxQyxPQUFPO1FBQ1QsQ0FBQztRQUNELEdBQUcsQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUM7UUFDOUIsR0FBRyxDQUFDLHNCQUFzQixLQUFLLGVBQWUsQ0FBQztRQUMvQyxJQUFJLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQzFCLE9BQU87UUFDVCxDQUFDO1FBQ0QsR0FBRyxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztRQUM3QixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxJQUFJLEVBQUU7WUFDckQsSUFBSSxDQUFDO2dCQUNILE1BQU0scUJBQXFCLEdBQUcsR0FBRyxDQUFDLHNCQUFzQixDQUFDO2dCQUN6RCxHQUFHLENBQUMsa0JBQWtCLEdBQUcsS0FBSyxDQUFDO2dCQUMvQixHQUFHLENBQUMsc0JBQXNCLEdBQUcsS0FBSyxDQUFDO2dCQUNuQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztvQkFDMUMsT0FBTztnQkFDVCxDQUFDO2dCQUNELElBQUkscUJBQXFCLElBQUksSUFBSSxDQUFDLFdBQVcsS0FBSyxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUM7b0JBQ3pELE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDakMsQ0FBQztnQkFDRCxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDakIsSUFDRSxxQkFBcUI7dUJBQ2xCLElBQUksQ0FBQyxXQUFXLEtBQUssR0FBRyxDQUFDLEVBQUU7dUJBQzNCLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUzt1QkFDekIsR0FBRyxDQUFDLE1BQU0sS0FBSyxNQUFNLEVBQ3hCLENBQUM7b0JBQ0QsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNsQyxDQUFDO1lBQ0gsQ0FBQztvQkFBUyxDQUFDO2dCQUNULEdBQUcsQ0FBQyxpQkFBaUIsR0FBRyxLQUFLLENBQUM7Z0JBQzlCLElBQ0UsR0FBRyxDQUFDLGtCQUFrQjt1QkFDbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQzt1QkFDckIsSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTO3VCQUN6QixDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQ2YsQ0FBQztvQkFDRCxJQUFJLENBQUMscUJBQXFCLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUN6QyxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUMsRUFBRSwwQkFBMEIsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdkMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ2xCLEdBQUcsQ0FBQyxpQkFBaUIsR0FBRyxLQUFLLENBQUM7UUFDaEMsQ0FBQztJQUNILENBQUM7SUFFTyxLQUFLLENBQUMsbUJBQW1CLENBQy9CLElBQTRCLEVBQzVCLEdBQXVDLEVBQ3ZDLG1CQUFrQztRQUVsQyxNQUFNLGNBQWMsR0FBYyxFQUFFLENBQUM7UUFDckMsSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNSLElBQUksQ0FBQztnQkFDSCxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDakMsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM3QixDQUFDO1lBQ0QsR0FBRyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFDckIsQ0FBQztRQUNELElBQUksQ0FBQztZQUNILElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztnQkFDckIsTUFBTSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDckIsQ0FBQztRQUNILENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3QixDQUFDO1FBQ0QsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ25DLElBQUksR0FBRyxFQUFFLENBQUM7WUFDUixJQUFJLFVBQVUsRUFBRSxDQUFDO2dCQUNmLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUN6QixJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDckMsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLEdBQUcsQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO2dCQUNwQixJQUFJLENBQUM7b0JBQ0gsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUM3QixDQUFDO2dCQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7b0JBQ2YsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDN0IsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQy9CLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDaEIsTUFBTSxhQUFhLEdBQXNCO29CQUN2QyxJQUFJLEVBQUUsZ0NBQWdDO29CQUN0QyxPQUFPLEVBQUUsOERBQThEO29CQUN2RSxLQUFLLEVBQUUsSUFBSTtpQkFDWixDQUFDO2dCQUNGLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztvQkFDM0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsQ0FBQztnQkFDaEMsQ0FBQztnQkFDRCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsSUFBSSxDQUFDO2dCQUNoQyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUMxQixJQUFJLENBQUM7b0JBQ0gsTUFBTSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQzVCLENBQUM7Z0JBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztvQkFDZixjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUM3QixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFFRCxNQUFNLGlCQUFpQixHQUFHLG1CQUFtQjtZQUMzQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUM7WUFDcEMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztRQUNkLElBQUksQ0FBQyxXQUFXLEdBQUcsaUJBQWlCLEVBQUUsRUFBRSxJQUFJLElBQUksQ0FBQztRQUNqRCxJQUNFLGlCQUFpQjtlQUNkLGlCQUFpQixDQUFDLE1BQU0sS0FBSyxNQUFNO2VBQ25DLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUNyQyxDQUFDO1lBQ0QsSUFBSSxDQUFDO2dCQUNILE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLGlCQUFpQixDQUFDLENBQUM7Z0JBQ2hELE1BQU0saUJBQWlCLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUM1QyxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxJQUFJLENBQUMsaUJBQWlCLENBQUMsU0FBUyxFQUFFLENBQUM7b0JBQzlELE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO2dCQUNoRCxDQUFDO1lBQ0gsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM3QixDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNqQixJQUFJLGNBQWMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDaEMsT0FBTyxTQUFTLENBQUM7UUFDbkIsQ0FBQztRQUNELE9BQU8sSUFBSSxjQUFjLENBQUMsY0FBYyxFQUFFLCtCQUErQixDQUFDLENBQUM7SUFDN0UsQ0FBQztJQUVPLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxHQUEyQjtRQUNqRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFDM0IsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzlCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFbkMsSUFBSSxJQUFJLENBQUMsV0FBVyxLQUFLLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNoQyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztZQUN4QixNQUFNLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1FBQ3RDLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ25CLENBQUM7SUFDSCxDQUFDO0lBRU8sS0FBSyxDQUFDLG1CQUFtQixDQUFDLEtBQWE7UUFDN0MsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuQyxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssTUFBTSxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztZQUNqRCxNQUFNLElBQUksS0FBSyxDQUFDLHlCQUF5QixHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNyRCxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsV0FBVyxLQUFLLEdBQUcsQ0FBQyxFQUFFLElBQUksR0FBRyxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ2pELE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUM5QixPQUFPO1FBQ1QsQ0FBQztRQUVELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQ2xGLElBQUksVUFBVSxFQUFFLENBQUM7WUFDZixNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDeEMsQ0FBQztRQUNELElBQUksQ0FBQztZQUNILE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2xDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUM5QixJQUFJLENBQUMsV0FBVyxHQUFHLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDMUIsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ2pCLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDOUIsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2xDLENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLElBQUksVUFBVSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztnQkFDOUUsSUFBSSxDQUFDLFdBQVcsR0FBRyxVQUFVLENBQUMsRUFBRSxDQUFDO2dCQUNqQyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDekMsTUFBTSxVQUFVLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUNyQyxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxDQUFDO29CQUN2RCxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQ3pDLENBQUM7WUFDSCxDQUFDO1lBQ0QsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ2pCLE1BQU0sS0FBSyxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUM7SUFFTyxLQUFLLENBQUMsc0JBQXNCO1FBQ2xDLE1BQU0sZUFBZSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDMUMsT0FBTyxJQUFJLEVBQUUsQ0FBQztZQUNaLE1BQU0sY0FBYyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUMzRCxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQzttQkFDekIsR0FBRyxDQUFDLE1BQU0sS0FBSyxNQUFNO21CQUNyQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQ3hCLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztnQkFDcEIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7Z0JBQ3hCLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJLENBQUM7Z0JBQ2hDLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQzFCLE1BQU0sSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUMxQixPQUFPO1lBQ1QsQ0FBQztZQUVELGVBQWUsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZDLElBQUksQ0FBQztnQkFDSCxNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ2xELE9BQU87WUFDVCxDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztnQkFDeEIsSUFBSSxDQUFDLFNBQVMsQ0FBQztvQkFDYixJQUFJLEVBQUUsbUNBQW1DO29CQUN6QyxPQUFPLEVBQUUscUJBQXFCLENBQUMsS0FBSyxDQUFDO29CQUNyQyxLQUFLLEVBQUUsS0FBSztvQkFDWixLQUFLLEVBQUUsY0FBYyxDQUFDLEVBQUU7aUJBQ3pCLENBQUMsQ0FBQztZQUNMLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxXQUFXLENBQ3ZCLEdBQTJCLEVBQzNCLFVBQStCLEVBQy9CLE1BQW1CO1FBRW5CLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxXQUFXLEtBQUssR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM3QyxHQUFHLENBQUMsb0JBQW9CLEdBQUcsSUFBSSxDQUFDO1FBQ2hDLElBQUksUUFBUSxFQUFFLENBQUM7WUFDYixNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDakMsQ0FBQztRQUNELElBQUksQ0FBQztZQUNILElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNuQixNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUM7WUFDdEIsQ0FBQztZQUNELE1BQU0sVUFBVSxFQUFFLENBQUM7UUFDckIsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsR0FBRyxDQUFDLG9CQUFvQixHQUFHLEtBQUssQ0FBQztZQUNqQyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztnQkFDbEQsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUMzQixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ2pCLElBQ0UsUUFBUTt1QkFDTCxJQUFJLENBQUMsV0FBVyxLQUFLLEdBQUcsQ0FBQyxFQUFFO3VCQUMzQixJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVM7dUJBQ3pCLEdBQUcsQ0FBQyxNQUFNLEtBQUssTUFBTTt1QkFDckIsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUNsQixDQUFDO29CQUNELE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDbEMsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVPLGdDQUFnQyxDQUN0QyxPQUFzQyxFQUN0QyxNQUFtQjtRQUVuQixPQUFPO1lBQ0wsT0FBTyxFQUFFLElBQUksQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUM7WUFDdkQsU0FBUyxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDO1lBQ3BELE1BQU07U0FDUCxDQUFDO0lBQ0osQ0FBQztJQUVPLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBMkI7UUFDbEQsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUM7WUFDeEIsT0FBTztRQUNULENBQUM7UUFDRCxHQUFHLENBQUMsR0FBRyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3pDLElBQUksQ0FBQztZQUNILEdBQUcsQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNyRCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUN6QyxNQUFNLEtBQUssQ0FBQztZQUNkLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxlQUFlLENBQUMsR0FBMkI7UUFDdkQsSUFDRSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVM7ZUFDdEIsSUFBSSxDQUFDLFdBQVcsS0FBSyxHQUFHLENBQUMsRUFBRTtlQUMzQixHQUFHLENBQUMsTUFBTSxLQUFLLE1BQU07ZUFDckIsR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUU7ZUFDbkIsR0FBRyxDQUFDLFNBQVMsRUFDaEIsQ0FBQztZQUNELE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFbEMsTUFBTSxVQUFVLEdBQUcsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDckQsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUM7UUFDdEMsTUFBTSxhQUFhLEdBQTZCLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDeEQsSUFBSSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ2pFLENBQUMsQ0FBQztRQUNGLE1BQU0sYUFBYSxHQUFHLFVBQVUsQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUM5QyxNQUFNLDBCQUEwQixHQUFnQyxDQUFDLGVBQWUsRUFBRSxFQUFFO1lBQ2xGLElBQUksZUFBZSxLQUFLLFVBQVUsRUFBRSxDQUFDO2dCQUNuQyxPQUFPO1lBQ1QsQ0FBQztZQUNELElBQUksQ0FBQyw4QkFBOEIsQ0FDakMsR0FBRyxFQUNILFVBQVUsRUFDVixJQUFJLEtBQUssQ0FBQyxrQ0FBa0MsQ0FBQyxDQUM5QyxDQUFDO1FBQ0osQ0FBQyxDQUFDO1FBQ0YsR0FBRyxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFDNUIsR0FBRyxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUM7UUFDbEMsR0FBRyxDQUFDLHVCQUF1QixHQUFHLGFBQWEsQ0FBQztRQUM1QyxHQUFHLENBQUMsMEJBQTBCLEdBQUcsMEJBQTBCLENBQUM7UUFDNUQsR0FBRyxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFDNUIsR0FBRyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7UUFDckIsR0FBRyxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQztRQUM5QixVQUFVLENBQUMsRUFBRSxDQUFDLHNCQUFzQixFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQ3JELGFBQWEsRUFBRSxFQUFFLENBQ2YsT0FBTyxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsZUFBZSxFQUNqRCwwQkFBMEIsQ0FDM0IsQ0FBQztRQUVGLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLE1BQU0sSUFBSSxNQUFNLENBQUM7UUFDekQsSUFBSSxDQUFDO1lBQ0gsTUFBTSxVQUFVLENBQUMsSUFBSSxDQUFDLHNCQUFzQixFQUFFO2dCQUM1QyxNQUFNO2dCQUNOLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxPQUFPLElBQUksRUFBRTtnQkFDL0MsUUFBUSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLFFBQVE7Z0JBQzNDLFNBQVMsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxTQUFTO2dCQUM3QyxhQUFhLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsYUFBYSxJQUFJLENBQUM7YUFDM0QsQ0FBQyxDQUFDO1lBQ0gsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ25CLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsR0FBRyxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7WUFDdEIsR0FBRyxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztZQUM3QixHQUFHLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQztZQUMzQixHQUFHLENBQUMsYUFBYSxHQUFHLFNBQVMsQ0FBQztZQUM5QixHQUFHLENBQUMsdUJBQXVCLEdBQUcsU0FBUyxDQUFDO1lBQ3hDLEdBQUcsQ0FBQywwQkFBMEIsR0FBRyxTQUFTLENBQUM7WUFDM0MsVUFBVSxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsRUFBRSxhQUFhLENBQUMsQ0FBQztZQUN0RCxhQUFhLEVBQUUsR0FBRyxDQUNoQixPQUFPLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxlQUFlLEVBQ2pELDBCQUEwQixDQUMzQixDQUFDO1lBQ0YsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDekIsSUFBSSxDQUFDO29CQUNILE1BQU0sVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUM1QixDQUFDO2dCQUFDLE1BQU0sQ0FBQztvQkFDUCxtRUFBbUU7Z0JBQ3JFLENBQUM7WUFDSCxDQUFDO1lBQ0QsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxjQUFjLENBQUMsR0FBMkI7UUFDdEQsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLFVBQVUsQ0FBQztRQUNsQyxNQUFNLGFBQWEsR0FBRyxHQUFHLENBQUMsYUFBYSxDQUFDO1FBQ3hDLE1BQU0sYUFBYSxHQUFHLEdBQUcsQ0FBQyx1QkFBdUIsQ0FBQztRQUNsRCxNQUFNLDBCQUEwQixHQUFHLEdBQUcsQ0FBQywwQkFBMEIsQ0FBQztRQUNsRSxHQUFHLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN0QixHQUFHLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDO1FBQzdCLEdBQUcsQ0FBQyxVQUFVLEdBQUcsU0FBUyxDQUFDO1FBQzNCLEdBQUcsQ0FBQyxhQUFhLEdBQUcsU0FBUyxDQUFDO1FBQzlCLEdBQUcsQ0FBQyx1QkFBdUIsR0FBRyxTQUFTLENBQUM7UUFDeEMsR0FBRyxDQUFDLDBCQUEwQixHQUFHLFNBQVMsQ0FBQztRQUMzQyxNQUFNLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEUsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ2hCLE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUM7Z0JBQ0gsTUFBTSxVQUFVLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUM7WUFDL0MsQ0FBQztZQUFDLE1BQU0sQ0FBQztnQkFDUCwyRUFBMkU7WUFDN0UsQ0FBQztRQUNILENBQUM7UUFDRCxNQUFNLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDdEUsSUFBSSxhQUFhLEVBQUUsQ0FBQztZQUNsQixVQUFVLENBQUMsR0FBRyxDQUFDLHNCQUFzQixFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQ3hELENBQUM7UUFDRCxJQUFJLGFBQWEsSUFBSSwwQkFBMEIsRUFBRSxDQUFDO1lBQ2hELGFBQWEsQ0FBQyxHQUFHLENBQ2YsT0FBTyxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsZUFBZSxFQUNqRCwwQkFBMEIsQ0FDM0IsQ0FBQztRQUNKLENBQUM7UUFDRCxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3pCLElBQUksQ0FBQztnQkFDSCxNQUFNLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUM1QixDQUFDO1lBQUMsTUFBTSxDQUFDO2dCQUNQLHdEQUF3RDtZQUMxRCxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFTyxxQkFBcUIsQ0FDM0IsR0FBMkIsRUFDM0IsVUFBd0MsRUFDeEMsVUFBa0IsRUFDbEIsS0FBNEI7UUFFNUIsSUFDRSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVM7ZUFDdEIsSUFBSSxDQUFDLFdBQVcsS0FBSyxHQUFHLENBQUMsRUFBRTtlQUMzQixHQUFHLENBQUMsTUFBTSxLQUFLLE1BQU07ZUFDckIsR0FBRyxDQUFDLGlCQUFpQjtlQUNyQixDQUFDLEdBQUcsQ0FBQyxTQUFTO2VBQ2QsR0FBRyxDQUFDLFVBQVUsS0FBSyxVQUFVO2VBQzdCLEdBQUcsQ0FBQyx1QkFBdUIsS0FBSyxJQUFJLENBQUMsZ0JBQWdCO2VBQ3JELEdBQUcsQ0FBQyxVQUFVLEtBQUssVUFBVSxFQUNoQyxDQUFDO1lBQ0QsSUFBSSxDQUFDLCtCQUErQixDQUFDO2dCQUNuQyxLQUFLLEVBQUUsR0FBRyxDQUFDLEVBQUU7Z0JBQ2IsVUFBVTtnQkFDVixnQkFBZ0IsRUFBRSxJQUFJLENBQUMsZ0JBQWdCO2dCQUN2QyxZQUFZLEVBQUUsS0FBSyxDQUFDLFNBQVM7Z0JBQzdCLFVBQVU7YUFDWCxDQUFDLENBQUM7WUFDSCxPQUFPO1FBQ1QsQ0FBQztRQUVELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLE1BQU0sSUFBSSxNQUFNLENBQUM7UUFDekQsTUFBTSxJQUFJLEdBQUcsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ3ZFLE1BQU0sVUFBVSxHQUFHLG1CQUFtQixDQUFDLElBQUksRUFBRSxNQUFNLEVBQUU7WUFDbkQsS0FBSyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUMxRCxNQUFNLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxDQUFDO1NBQzdELENBQUMsQ0FBQztRQUNILE1BQU0sUUFBUSxHQUFHLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQztRQUN0QyxNQUFNLGdCQUFnQixHQUFzQjtZQUMxQyxLQUFLLEVBQUUsR0FBRyxDQUFDLEVBQUU7WUFDYixVQUFVO1lBQ1YsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLGdCQUFnQjtZQUN2QyxZQUFZLEVBQUUsS0FBSyxDQUFDLFNBQVM7WUFDN0IsVUFBVTtTQUNYLENBQUM7UUFDRixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLElBQUksb0JBQW9CLEVBQUUsQ0FBQztZQUMzRCxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUVwRCxDQUFDO1lBQ2QsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7Z0JBQ3RCLE1BQU07WUFDUixDQUFDO1lBQ0QsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ25ELElBQUksQ0FBQywrQkFBK0IsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzVELENBQUM7UUFDRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ3ZELE1BQU0sS0FBSyxHQUFzQjtZQUMvQixLQUFLLEVBQUUsR0FBRyxDQUFDLEVBQUU7WUFDYixRQUFRO1lBQ1IsVUFBVTtZQUNWLGdCQUFnQixFQUFFLElBQUksQ0FBQyxnQkFBZ0I7WUFDdkMsUUFBUSxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQzlCLE1BQU07WUFDTixRQUFRLEVBQUUsTUFBTSxLQUFLLE1BQU0sQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxXQUFXO1lBQ3hELEdBQUcsVUFBVTtZQUNiLFFBQVEsRUFBRTtnQkFDUixTQUFTLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxTQUFTO2dCQUNuQyxlQUFlLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxlQUFlO2dCQUMvQyxXQUFXLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxXQUFXO2dCQUN2QyxZQUFZLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxZQUFZO2dCQUN6QyxhQUFhLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxhQUFhO2dCQUMzQyxhQUFhLEVBQUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxhQUFhO2dCQUMzQyxHQUFHLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxTQUFTLEtBQUssU0FBUztvQkFDeEMsQ0FBQyxDQUFDLEVBQUUsU0FBUyxFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFO29CQUN6QyxDQUFDLENBQUMsRUFBRSxDQUFDO2FBQ1I7WUFDRCxJQUFJO1NBQ0wsQ0FBQztRQUNGLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVPLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxLQUF3QjtRQUN4RCxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDOUIsSUFBSSxDQUFDLGlDQUFpQyxDQUNwQyxLQUFLLEVBQ0wsSUFBSSxLQUFLLENBQUMsbURBQW1ELENBQUMsQ0FDL0QsQ0FBQztZQUNGLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUNELElBQUksQ0FBQztZQUNILE1BQU0sS0FBSyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMseUJBQXlCLEVBQUU7Z0JBQ3JELFNBQVMsRUFBRSxLQUFLLENBQUMsWUFBWTthQUM5QixDQUFDLENBQUM7WUFDSCxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsSUFBSSxDQUFDLGlDQUFpQyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNyRCxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7SUFDSCxDQUFDO0lBRU8sK0JBQStCLENBQUMsS0FBd0I7UUFDOUQsS0FBSyxJQUFJLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVPLGlDQUFpQyxDQUN2QyxLQUF3QixFQUN4QixLQUFjO1FBRWQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FDN0IsR0FBRztlQUNBLEdBQUcsQ0FBQyxVQUFVLEtBQUssS0FBSyxDQUFDLFVBQVU7ZUFDbkMsQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQzFCLENBQUM7UUFDRixJQUNFLGVBQWU7ZUFDWixJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVM7ZUFDekIsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQzVCLENBQUM7WUFDRCxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUNiLElBQUksRUFBRSw4QkFBOEI7Z0JBQ3BDLE9BQU8sRUFBRSxxQkFBcUIsQ0FBQyxLQUFLLENBQUM7Z0JBQ3JDLEtBQUssRUFBRSxLQUFLO2dCQUNaLEtBQUssRUFBRSxLQUFLLENBQUMsS0FBSzthQUNuQixDQUFDLENBQUM7UUFDTCxDQUFDO1FBQ0QsSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNSLElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNwRSxDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyx1QkFBdUIsQ0FDbkMsU0FBZ0Q7UUFFaEQsTUFBTSxnQkFBZ0IsR0FBNEIsRUFBRSxDQUFDO1FBQ3JELEtBQUssTUFBTSxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsSUFBSSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUN2RCxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQ3RCLFNBQVM7WUFDWCxDQUFDO1lBQ0QsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUN4QyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDekQsQ0FBQztRQUNELE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFTyw4QkFBOEIsQ0FDcEMsR0FBMkIsRUFDM0IsVUFBd0MsRUFDeEMsS0FBYztRQUVkLElBQ0UsSUFBSSxDQUFDLG1CQUFtQjtlQUNyQixJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVM7ZUFDekIsR0FBRyxDQUFDLFVBQVUsS0FBSyxVQUFVO2VBQzdCLEdBQUcsQ0FBQyxpQkFBaUI7ZUFDckIsQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUN2QixDQUFDO1lBQ0QsT0FBTztRQUNULENBQUM7UUFDRCxHQUFHLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDO1FBQzdCLElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDNUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssSUFBSSxFQUFFO1lBQ2hDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksR0FBRyxDQUFDLFVBQVUsS0FBSyxVQUFVLEVBQUUsQ0FBQztnQkFDNUQsT0FBTztZQUNULENBQUM7WUFDRCxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDL0IsR0FBRyxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUM7WUFDdkIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFdBQVcsS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzlDLElBQUksU0FBUyxFQUFFLENBQUM7Z0JBQ2QsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7WUFDMUIsQ0FBQztZQUNELElBQUksQ0FBQyxTQUFTLENBQUM7Z0JBQ2IsSUFBSSxFQUFFLGtCQUFrQjtnQkFDeEIsT0FBTyxFQUFFLHFCQUFxQixDQUFDLEtBQUssQ0FBQztnQkFDckMsS0FBSyxFQUFFLEtBQUs7Z0JBQ1osS0FBSyxFQUFFLEdBQUcsQ0FBQyxFQUFFO2FBQ2QsQ0FBQyxDQUFDO1lBQ0gsSUFBSSxTQUFTLEVBQUUsQ0FBQztnQkFDZCxNQUFNLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1lBQ3RDLENBQUM7UUFDSCxDQUFDLEVBQUUsK0JBQStCLEVBQUUsR0FBRyxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRU8scUJBQXFCLENBQzNCLEtBQXNFO1FBRXRFLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDakQsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLFVBQVUsQ0FBQztRQUNsQyxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsSUFBSSxHQUFHLENBQUMsaUJBQWlCLElBQUksQ0FBQyxVQUFVLElBQUksVUFBVSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2xGLE1BQU0sSUFBSSxLQUFLLENBQUMseUNBQXlDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3JFLENBQUM7UUFDRCxPQUFPLEVBQUUsR0FBRyxFQUFFLFVBQVUsRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFFTywyQkFBMkIsQ0FDakMsS0FBc0U7UUFFdEUsT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFFTyxrQkFBa0IsQ0FDeEIsS0FBc0UsRUFDdEUsYUFBc0I7UUFFdEIsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzlCLE1BQU0sSUFBSSxLQUFLLENBQUMsbUNBQW1DLENBQUMsQ0FBQztRQUN2RCxDQUFDO1FBQ0QsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekMsSUFBSSxhQUFhLElBQUksSUFBSSxDQUFDLFdBQVcsS0FBSyxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDakQsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQkFBc0IsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDbEQsQ0FBQztRQUNELElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsSUFBSSxLQUFLLENBQUMsVUFBVSxLQUFLLEdBQUcsQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUMvRSxNQUFNLElBQUksS0FBSyxDQUNiLHdCQUF3QixLQUFLLENBQUMsVUFBVSwyQkFBMkIsR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUNwRixDQUFDO1FBQ0osQ0FBQztRQUNELElBQUksS0FBSyxDQUFDLGdCQUFnQixLQUFLLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3JELE1BQU0sSUFBSSxLQUFLLENBQ2IsMkJBQTJCLEtBQUssQ0FBQyxnQkFBZ0IseUJBQXlCLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUNsRyxDQUFDO1FBQ0osQ0FBQztRQUNELElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxNQUFNLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO1lBQ2pELE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3JELENBQUM7UUFDRCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFTyxtQkFBbUIsQ0FBQyxDQUFTLEVBQUUsQ0FBUztRQUM5QyxvQkFBb0IsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3JELG9CQUFvQixDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEQsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDL0UsQ0FBQztRQUNELElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDOUIsTUFBTSxJQUFJLEtBQUssQ0FBQyx1Q0FBdUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ2pGLENBQUM7SUFDSCxDQUFDO0lBRU8sa0JBQWtCLENBQUMsU0FBcUM7UUFDOUQsSUFBSSxTQUFTLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDNUIsT0FBTyxDQUFDLENBQUM7UUFDWCxDQUFDO1FBQ0QsSUFBSSxDQUFDLFNBQVMsSUFBSSxPQUFPLFNBQVMsS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQzVFLE1BQU0sSUFBSSxLQUFLLENBQUMsNkJBQTZCLENBQUMsQ0FBQztRQUNqRCxDQUFDO1FBQ0QsTUFBTSxXQUFXLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQ2pFLEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQ3pDLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMscUJBQXFCLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDOUMsQ0FBQztRQUNILENBQUM7UUFDRCx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQ3hELHVCQUF1QixDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztRQUNoRSx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFDMUQsdUJBQXVCLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1FBQzVELE9BQU8sQ0FDTCxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2NBQ3JCLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Y0FDM0IsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztjQUN4QixDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQzVCLENBQUM7SUFDSixDQUFDO0lBRU8sV0FBVyxDQUFDLEdBQVk7UUFDOUIsTUFBTSxZQUFZLEdBQUcscUJBQXFCLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDeEUsSUFBSSxDQUFDO1lBQ0gsSUFBSSxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDeEIsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLE1BQU0sSUFBSSxLQUFLLENBQUMsc0JBQXNCLENBQUMsQ0FBQztRQUMxQyxDQUFDO1FBQ0QsT0FBTyxZQUFZLENBQUM7SUFDdEIsQ0FBQztJQUVPLGVBQWUsQ0FBQyxTQUFrQixFQUFFLFlBQVksR0FBRyxJQUFJO1FBQzdELElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzVCLE9BQU8sWUFBWSxDQUFDO1FBQ3RCLENBQUM7UUFDRCxPQUFPLGVBQWUsQ0FBQyxTQUFTLEVBQUUsV0FBVyxFQUFFLENBQUMsRUFBRSxZQUFZLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBRU8saUJBQWlCLENBQUMsU0FBaUM7UUFDekQsTUFBTSxrQkFBa0IsR0FBRyxTQUFTLElBQUksTUFBTSxDQUFDO1FBQy9DLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxrQkFBa0IsRUFBRSxjQUFjLEVBQUUsY0FBYyxDQUFDLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQztZQUMvRixNQUFNLElBQUksS0FBSyxDQUFDLHlFQUF5RSxDQUFDLENBQUM7UUFDN0YsQ0FBQztRQUNELE9BQU8sa0JBQWtCLENBQUM7SUFDNUIsQ0FBQztJQUVPLHlCQUF5QjtRQUMvQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQztRQUN4QyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixPQUFPO1FBQ1QsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxTQUFTLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxNQUFNLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUMxRixNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxDQUFDLENBQUM7UUFDM0QsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLE9BQU8sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNsQyxlQUFlLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDakUsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNuQyxlQUFlLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxxQkFBcUIsRUFBRSxDQUFDLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUNoRixDQUFDO1FBQ0QsSUFBSSxPQUFPLENBQUMsU0FBUyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3BDLGVBQWUsQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLHNCQUFzQixFQUFFLENBQUMsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1FBQ25GLENBQUM7UUFDRCxJQUNFLE9BQU8sQ0FBQyxRQUFRLEtBQUssU0FBUztlQUMzQixPQUFPLENBQUMsU0FBUyxLQUFLLFNBQVM7ZUFDL0IsT0FBTyxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsU0FBUyxHQUFHLG9CQUFvQixFQUM5RCxDQUFDO1lBQ0QsTUFBTSxJQUFJLEtBQUssQ0FDYix5Q0FBeUMsb0JBQW9CLFNBQVMsQ0FDdkUsQ0FBQztRQUNKLENBQUM7UUFDRCxJQUFJLE9BQU8sQ0FBQyxhQUFhLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDeEMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEVBQUUsMEJBQTBCLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQzdFLENBQUM7SUFDSCxDQUFDO0NBQ0YifQ==
|