agl 1.0.17 → 21.0.2
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/.smartconfig.json +55 -0
- package/changelog.md +1026 -0
- package/cli.js +14 -0
- package/dist_serve/bundle.js +44778 -0
- package/dist_serve/index.html +13 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.authmodels.d.ts +126 -0
- package/dist_ts/classes.authmodels.js +1422 -0
- package/dist_ts/classes.authstore.d.ts +160 -0
- package/dist_ts/classes.authstore.js +2483 -0
- package/dist_ts/classes.browserresourcehost.d.ts +85 -0
- package/dist_ts/classes.browserresourcehost.js +912 -0
- package/dist_ts/classes.cli.d.ts +21 -0
- package/dist_ts/classes.cli.js +1082 -0
- package/dist_ts/classes.config.d.ts +23 -0
- package/dist_ts/classes.config.js +267 -0
- package/dist_ts/classes.controller.d.ts +523 -0
- package/dist_ts/classes.controller.js +10611 -0
- package/dist_ts/classes.controllermanagement.d.ts +32 -0
- package/dist_ts/classes.controllermanagement.js +222 -0
- package/dist_ts/classes.draftmanager.d.ts +30 -0
- package/dist_ts/classes.draftmanager.js +179 -0
- package/dist_ts/classes.embeddeddb.d.ts +30 -0
- package/dist_ts/classes.embeddeddb.js +159 -0
- package/dist_ts/classes.flexframedtransport.d.ts +56 -0
- package/dist_ts/classes.flexframedtransport.js +275 -0
- package/dist_ts/classes.flexmodels.private.d.ts +231 -0
- package/dist_ts/classes.flexmodels.private.js +985 -0
- package/dist_ts/classes.flexmodels.public.d.ts +207 -0
- package/dist_ts/classes.flexmodels.public.js +885 -0
- package/dist_ts/classes.flexprojectionreader.d.ts +89 -0
- package/dist_ts/classes.flexprojectionreader.js +580 -0
- package/dist_ts/classes.flexservice.d.ts +196 -0
- package/dist_ts/classes.flexservice.js +3704 -0
- package/dist_ts/classes.flexstore.d.ts +174 -0
- package/dist_ts/classes.flexstore.js +3400 -0
- package/dist_ts/classes.flexsupervisor.d.ts +105 -0
- package/dist_ts/classes.flexsupervisor.js +1191 -0
- package/dist_ts/classes.gitreversion.d.ts +431 -0
- package/dist_ts/classes.gitreversion.js +10592 -0
- package/dist_ts/classes.harnessoperationmanager.d.ts +113 -0
- package/dist_ts/classes.harnessoperationmanager.js +602 -0
- package/dist_ts/classes.opencodeclient.d.ts +146 -0
- package/dist_ts/classes.opencodeclient.js +3003 -0
- package/dist_ts/classes.opencodesupervisor.d.ts +60 -0
- package/dist_ts/classes.opencodesupervisor.js +1003 -0
- package/dist_ts/classes.passkeymanager.d.ts +34 -0
- package/dist_ts/classes.passkeymanager.js +456 -0
- package/dist_ts/classes.processinspection.d.ts +50 -0
- package/dist_ts/classes.processinspection.js +484 -0
- package/dist_ts/classes.resourcecoordinator.d.ts +64 -0
- package/dist_ts/classes.resourcecoordinator.js +294 -0
- package/dist_ts/classes.sessionintelligencereader.d.ts +13 -0
- package/dist_ts/classes.sessionintelligencereader.js +40 -0
- package/dist_ts/classes.systemmetricssampler.d.ts +53 -0
- package/dist_ts/classes.systemmetricssampler.js +168 -0
- package/dist_ts/classes.terminalmanager.d.ts +95 -0
- package/dist_ts/classes.terminalmanager.js +981 -0
- package/dist_ts/classes.terminalresourcehost.d.ts +20 -0
- package/dist_ts/classes.terminalresourcehost.js +84 -0
- package/dist_ts/classes.upgradecoordinator.d.ts +244 -0
- package/dist_ts/classes.upgradecoordinator.js +2155 -0
- package/dist_ts/classes.upgradetransaction.d.ts +92 -0
- package/dist_ts/classes.upgradetransaction.js +2125 -0
- package/dist_ts/classes.uploadmanager.d.ts +24 -0
- package/dist_ts/classes.uploadmanager.js +210 -0
- package/dist_ts/classes.validation.d.ts +91 -0
- package/dist_ts/classes.validation.js +1087 -0
- package/dist_ts/flexharness.child.d.ts +1 -0
- package/dist_ts/flexharness.child.js +28 -0
- package/dist_ts/functions.canonicaldirectory.d.ts +21 -0
- package/dist_ts/functions.canonicaldirectory.js +144 -0
- package/dist_ts/functions.controllerdataroot.d.ts +15 -0
- package/dist_ts/functions.controllerdataroot.js +76 -0
- package/dist_ts/functions.embeddeddb.d.ts +2 -0
- package/dist_ts/functions.embeddeddb.js +21 -0
- package/dist_ts/functions.flexcredentialstore.d.ts +16 -0
- package/dist_ts/functions.flexcredentialstore.js +93 -0
- package/dist_ts/functions.opencodeauth.d.ts +3 -0
- package/dist_ts/functions.opencodeauth.js +31 -0
- package/dist_ts/functions.runtimeenvironment.d.ts +2 -0
- package/dist_ts/functions.runtimeenvironment.js +79 -0
- package/dist_ts/functions.upgradefollower.d.ts +3 -0
- package/dist_ts/functions.upgradefollower.js +95 -0
- package/dist_ts/index.d.ts +24 -0
- package/dist_ts/index.js +25 -0
- package/dist_ts/interfaces.auth.d.ts +181 -0
- package/dist_ts/interfaces.auth.js +82 -0
- package/dist_ts/interfaces.config.d.ts +34 -0
- package/dist_ts/interfaces.config.js +2 -0
- package/dist_ts/interfaces.flexipc.d.ts +939 -0
- package/dist_ts/interfaces.flexipc.js +1492 -0
- package/dist_ts/interfaces.gitreversion.d.ts +246 -0
- package/dist_ts/interfaces.gitreversion.js +2 -0
- package/dist_ts/interfaces.lifecycle.d.ts +37 -0
- package/dist_ts/interfaces.lifecycle.js +2 -0
- package/dist_ts/interfaces.opencode.d.ts +101 -0
- package/dist_ts/interfaces.opencode.js +3 -0
- package/dist_ts/interfaces.projects.d.ts +156 -0
- package/dist_ts/interfaces.projects.js +5 -0
- package/dist_ts/plugins.d.ts +36 -0
- package/dist_ts/plugins.js +40 -0
- package/dist_ts_interfaces/index.d.ts +2 -0
- package/dist_ts_interfaces/index.js +3 -0
- package/dist_ts_interfaces/interfaces.d.ts +747 -0
- package/dist_ts_interfaces/interfaces.js +47 -0
- package/dist_ts_interfaces/plugins.d.ts +4 -0
- package/dist_ts_interfaces/plugins.js +3 -0
- package/dist_ts_interfaces/requests.d.ts +806 -0
- package/dist_ts_interfaces/requests.js +2 -0
- package/dist_ts_migration/classes.documentmigrationrunner.d.ts +8 -0
- package/dist_ts_migration/classes.documentmigrationrunner.js +24 -0
- package/dist_ts_migration/classes.flexmigrationrunner.d.ts +11 -0
- package/dist_ts_migration/classes.flexmigrationrunner.js +25 -0
- package/dist_ts_migration/classes.flexpostharnessmigrationrunner.d.ts +10 -0
- package/dist_ts_migration/classes.flexpostharnessmigrationrunner.js +15 -0
- package/dist_ts_migration/classes.migrationrunner.d.ts +8 -0
- package/dist_ts_migration/classes.migrationrunner.js +34 -0
- package/dist_ts_migration/index.d.ts +12 -0
- package/dist_ts_migration/index.js +13 -0
- package/dist_ts_migration/v10_flexharnessv3migration.d.ts +11 -0
- package/dist_ts_migration/v10_flexharnessv3migration.js +23 -0
- package/dist_ts_migration/v13_flexprojectionorder.d.ts +11 -0
- package/dist_ts_migration/v13_flexprojectionorder.js +23 -0
- package/dist_ts_migration/v16_flexprovidercredentials.d.ts +22 -0
- package/dist_ts_migration/v16_flexprovidercredentials.js +149 -0
- package/dist_ts_migration/v18_resourcelayout.d.ts +22 -0
- package/dist_ts_migration/v18_resourcelayout.js +23 -0
- package/dist_ts_migration/v18_resourcelayoutmigration.d.ts +6 -0
- package/dist_ts_migration/v18_resourcelayoutmigration.js +61 -0
- package/dist_ts_migration/v19_flexprojectmanagement.d.ts +11 -0
- package/dist_ts_migration/v19_flexprojectmanagement.js +21 -0
- package/dist_ts_migration/v1_embeddeddatabaselocation.d.ts +28 -0
- package/dist_ts_migration/v1_embeddeddatabaselocation.js +415 -0
- package/dist_ts_migration/v22_projectfilesystemidentitymigration.d.ts +7 -0
- package/dist_ts_migration/v22_projectfilesystemidentitymigration.js +105 -0
- package/dist_ts_migration/v2_controllerdataroot.d.ts +130 -0
- package/dist_ts_migration/v2_controllerdataroot.js +1887 -0
- package/dist_ts_migration/v6_protocoldocumentmigration.d.ts +7 -0
- package/dist_ts_migration/v6_protocoldocumentmigration.js +100 -0
- package/dist_ts_migration/v6_protocoldocuments.d.ts +7 -0
- package/dist_ts_migration/v6_protocoldocuments.js +138 -0
- package/html/index.html +13 -0
- package/{LICENSE → license.md} +2 -2
- package/package.json +86 -48
- package/readme.md +480 -0
- package/readme.plan.md +188 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.authmodels.ts +1245 -0
- package/ts/classes.authstore.ts +3274 -0
- package/ts/classes.browserresourcehost.ts +1205 -0
- package/ts/classes.cli.ts +1254 -0
- package/ts/classes.config.ts +351 -0
- package/ts/classes.controller.ts +14426 -0
- package/ts/classes.controllermanagement.ts +330 -0
- package/ts/classes.draftmanager.ts +232 -0
- package/ts/classes.embeddeddb.ts +166 -0
- package/ts/classes.flexframedtransport.ts +283 -0
- package/ts/classes.flexmodels.private.ts +823 -0
- package/ts/classes.flexmodels.public.ts +732 -0
- package/ts/classes.flexprojectionreader.ts +816 -0
- package/ts/classes.flexservice.ts +4302 -0
- package/ts/classes.flexstore.ts +4565 -0
- package/ts/classes.flexsupervisor.ts +1453 -0
- package/ts/classes.gitreversion.ts +13353 -0
- package/ts/classes.harnessoperationmanager.ts +870 -0
- package/ts/classes.opencodeclient.ts +4110 -0
- package/ts/classes.opencodesupervisor.ts +1280 -0
- package/ts/classes.passkeymanager.ts +570 -0
- package/ts/classes.processinspection.ts +623 -0
- package/ts/classes.resourcecoordinator.ts +436 -0
- package/ts/classes.sessionintelligencereader.ts +52 -0
- package/ts/classes.systemmetricssampler.ts +215 -0
- package/ts/classes.terminalmanager.ts +1207 -0
- package/ts/classes.terminalresourcehost.ts +122 -0
- package/ts/classes.upgradecoordinator.ts +2675 -0
- package/ts/classes.upgradetransaction.ts +2900 -0
- package/ts/classes.uploadmanager.ts +240 -0
- package/ts/classes.validation.ts +1409 -0
- package/ts/flexharness.child.ts +35 -0
- package/ts/functions.canonicaldirectory.ts +213 -0
- package/ts/functions.controllerdataroot.ts +107 -0
- package/ts/functions.embeddeddb.ts +22 -0
- package/ts/functions.flexcredentialstore.ts +128 -0
- package/ts/functions.opencodeauth.ts +34 -0
- package/ts/functions.runtimeenvironment.ts +90 -0
- package/ts/functions.upgradefollower.ts +115 -0
- package/ts/index.ts +36 -6
- package/ts/interfaces.auth.ts +316 -0
- package/ts/interfaces.config.ts +37 -0
- package/ts/interfaces.flexipc.ts +2586 -0
- package/ts/interfaces.gitreversion.ts +336 -0
- package/ts/interfaces.lifecycle.ts +46 -0
- package/ts/interfaces.opencode.ts +153 -0
- package/ts/interfaces.projects.ts +182 -0
- package/ts/plugins.ts +64 -0
- package/ts_interfaces/index.ts +2 -0
- package/ts_interfaces/interfaces.ts +827 -0
- package/ts_interfaces/plugins.ts +15 -0
- package/ts_interfaces/requests.ts +1186 -0
- package/ts_migration/classes.documentmigrationrunner.ts +32 -0
- package/ts_migration/classes.flexmigrationrunner.ts +33 -0
- package/ts_migration/classes.flexpostharnessmigrationrunner.ts +22 -0
- package/ts_migration/classes.migrationrunner.ts +40 -0
- package/ts_migration/index.ts +12 -0
- package/ts_migration/v10_flexharnessv3migration.ts +35 -0
- package/ts_migration/v13_flexprojectionorder.ts +33 -0
- package/ts_migration/v16_flexprovidercredentials.ts +196 -0
- package/ts_migration/v18_resourcelayout.ts +55 -0
- package/ts_migration/v18_resourcelayoutmigration.ts +68 -0
- package/ts_migration/v19_flexprojectmanagement.ts +28 -0
- package/ts_migration/v1_embeddeddatabaselocation.ts +560 -0
- package/ts_migration/v22_projectfilesystemidentitymigration.ts +121 -0
- package/ts_migration/v2_controllerdataroot.ts +2349 -0
- package/ts_migration/v6_protocoldocumentmigration.ts +144 -0
- package/ts_migration/v6_protocoldocuments.ts +198 -0
- package/ts_web/00_commitinfo_data.ts +8 -0
- package/ts_web/classes.controllersocketclient.ts +517 -0
- package/ts_web/classes.sessiondraftsync.ts +390 -0
- package/ts_web/elements.harnesscontrollerapp.ts +11494 -0
- package/ts_web/index.ts +2 -0
- package/ts_web/plugins.ts +31 -0
- package/.gitlab-ci.yml +0 -71
- package/.npmignore +0 -5
- package/README.md +0 -40
- package/dist/cli.js +0 -2
- package/dist/index.d.ts +0 -0
- package/dist/index.js +0 -9
- package/dist/mod_bundle/index.d.ts +0 -1
- package/dist/mod_bundle/index.js +0 -18
- package/dist/mod_bundle/mod.plugins.d.ts +0 -4
- package/dist/mod_bundle/mod.plugins.js +0 -11
- package/dist/mod_install/index.d.ts +0 -4
- package/dist/mod_install/index.js +0 -21
- package/dist/mod_install/mod.plugins.d.ts +0 -1
- package/dist/mod_install/mod.plugins.js +0 -7
- package/dist/mod_standard/index.d.ts +0 -4
- package/dist/mod_standard/index.js +0 -21
- package/dist/mod_standard/mod.browser.d.ts +0 -6
- package/dist/mod_standard/mod.browser.js +0 -14
- package/dist/mod_standard/mod.clean.d.ts +0 -4
- package/dist/mod_standard/mod.clean.js +0 -12
- package/dist/mod_standard/mod.compile.d.ts +0 -4
- package/dist/mod_standard/mod.compile.js +0 -21
- package/dist/mod_standard/mod.plugins.d.ts +0 -8
- package/dist/mod_standard/mod.plugins.js +0 -19
- package/dist/mod_standard/mod.test.d.ts +0 -4
- package/dist/mod_standard/mod.test.js +0 -12
- package/dist/plr.cli.d.ts +0 -3
- package/dist/plr.cli.js +0 -57
- package/dist/plr.config.d.ts +0 -11
- package/dist/plr.config.js +0 -26
- package/dist/plr.mods.d.ts +0 -17
- package/dist/plr.mods.js +0 -17
- package/dist/plr.paths.d.ts +0 -19
- package/dist/plr.paths.js +0 -26
- package/dist/plr.plugins.d.ts +0 -8
- package/dist/plr.plugins.js +0 -16
- package/npmextra.json +0 -10
- package/ts/mod_bundle/index.ts +0 -20
- package/ts/mod_bundle/mod.plugins.ts +0 -9
- package/ts/mod_install/index.ts +0 -20
- package/ts/mod_install/mod.plugins.ts +0 -1
- package/ts/mod_standard/index.ts +0 -23
- package/ts/mod_standard/mod.browser.ts +0 -17
- package/ts/mod_standard/mod.clean.ts +0 -13
- package/ts/mod_standard/mod.compile.ts +0 -23
- package/ts/mod_standard/mod.plugins.ts +0 -17
- package/ts/mod_standard/mod.test.ts +0 -13
- package/ts/plr.cli.ts +0 -60
- package/ts/plr.config.ts +0 -36
- package/ts/plr.mods.ts +0 -25
- package/ts/plr.paths.ts +0 -29
- package/ts/plr.plugins.ts +0 -17
- package/tslint.json +0 -3
- package/yarn.lock +0 -3464
|
@@ -0,0 +1,1191 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { commitinfo } from './00_commitinfo_data.js';
|
|
3
|
+
import { FlexFramedTransport } from './classes.flexframedtransport.js';
|
|
4
|
+
import { GitReversionConflictError, GitReversionDirtyWorktreeError, GitReversionFencedError, } from './classes.gitreversion.js';
|
|
5
|
+
import { createSanitizedRuntimeEnvironment } from './functions.runtimeenvironment.js';
|
|
6
|
+
import { FlexServiceError, flexIpcCancellationGraceTimeoutMs, flexIpcControlTimeoutMs, flexIpcDisposeTimeoutMs, flexIpcMaximumBrowserChannels, flexIpcMaximumPendingBrowserFrameBytes, flexIpcMaximumPendingBrowserFrames, flexIpcMaximumPendingRequests, flexIpcProtocolVersion, flexIpcSlashTimeoutMs, flexIpcStartupTimeoutMs, hasFlexExactKeys, isFlexPlainObject, isFlexHostResponseResult, isFlexResponseResult, parseFlexChildMessage, parseFlexParentMessage, } from './interfaces.flexipc.js';
|
|
7
|
+
const supervisorLogEntries = 200;
|
|
8
|
+
const supervisorLogLineBytes = 8 * 1024;
|
|
9
|
+
const supervisorTermTimeoutMs = 5_000;
|
|
10
|
+
const supervisorKillTimeoutMs = 2_000;
|
|
11
|
+
const logSuffix = '... [truncated]';
|
|
12
|
+
const supervisorExitMessageBytes = 1024;
|
|
13
|
+
const readOnlyFlexRequestMethods = new Set([
|
|
14
|
+
'service.status',
|
|
15
|
+
'intelligence.get',
|
|
16
|
+
'session.list',
|
|
17
|
+
'session.get',
|
|
18
|
+
'session.reversion.info',
|
|
19
|
+
'slash.list',
|
|
20
|
+
'message.page',
|
|
21
|
+
'message.get',
|
|
22
|
+
'prompt.get',
|
|
23
|
+
'prompt.list',
|
|
24
|
+
'permission.list',
|
|
25
|
+
'provider.list',
|
|
26
|
+
'provider.login.status',
|
|
27
|
+
'provider.connection.list',
|
|
28
|
+
'provider.connection.opencode-auth.get',
|
|
29
|
+
'provider.connection.ratelimits.get',
|
|
30
|
+
'model.choice.get',
|
|
31
|
+
'model.choice.validate',
|
|
32
|
+
]);
|
|
33
|
+
const outcomeMayBeUnknown = (methodArg) => methodArg !== undefined
|
|
34
|
+
&& !readOnlyFlexRequestMethods.has(methodArg);
|
|
35
|
+
const isReadyOnlyHostRequest = (methodArg) => (methodArg === 'crossharness.chats.list'
|
|
36
|
+
|| methodArg === 'crossharness.chat.read'
|
|
37
|
+
|| methodArg === 'browser.resources.resolve'
|
|
38
|
+
|| methodArg === 'browser.channel.open'
|
|
39
|
+
|| methodArg === 'browser.channel.close');
|
|
40
|
+
const sanitizeExitMessage = (messageArg) => {
|
|
41
|
+
const sanitized = messageArg.replace(/[\u0000-\u001f\u007f]/gu, ' ').trim();
|
|
42
|
+
if (Buffer.byteLength(sanitized, 'utf8') <= supervisorExitMessageBytes)
|
|
43
|
+
return sanitized;
|
|
44
|
+
return Buffer.from(sanitized, 'utf8')
|
|
45
|
+
.subarray(0, supervisorExitMessageBytes)
|
|
46
|
+
.toString('utf8')
|
|
47
|
+
.replace(/\uFFFD$/u, '');
|
|
48
|
+
};
|
|
49
|
+
const isMissingProcess = (errorArg) => typeof errorArg === 'object'
|
|
50
|
+
&& errorArg !== null
|
|
51
|
+
&& 'code' in errorArg
|
|
52
|
+
&& errorArg.code === 'ESRCH';
|
|
53
|
+
const isProcessGroupAlive = (processGroupIdArg) => {
|
|
54
|
+
try {
|
|
55
|
+
process.kill(-processGroupIdArg, 0);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
catch (errorArg) {
|
|
59
|
+
if (isMissingProcess(errorArg))
|
|
60
|
+
return false;
|
|
61
|
+
throw errorArg;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const signalProcessGroup = (processGroupIdArg, signalArg) => {
|
|
65
|
+
try {
|
|
66
|
+
process.kill(-processGroupIdArg, signalArg);
|
|
67
|
+
}
|
|
68
|
+
catch (errorArg) {
|
|
69
|
+
if (!isMissingProcess(errorArg))
|
|
70
|
+
throw errorArg;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const waitFor = async (predicateArg, timeoutMsArg) => {
|
|
74
|
+
const deadline = Date.now() + timeoutMsArg;
|
|
75
|
+
while (predicateArg()) {
|
|
76
|
+
const remaining = deadline - Date.now();
|
|
77
|
+
if (remaining <= 0)
|
|
78
|
+
return false;
|
|
79
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(20, remaining)));
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
};
|
|
83
|
+
const waitBounded = async (promiseArg, timeoutMsArg) => {
|
|
84
|
+
let timer;
|
|
85
|
+
try {
|
|
86
|
+
return await Promise.race([
|
|
87
|
+
promiseArg,
|
|
88
|
+
new Promise((resolve) => {
|
|
89
|
+
timer = setTimeout(() => resolve(undefined), timeoutMsArg);
|
|
90
|
+
}),
|
|
91
|
+
]);
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
if (timer)
|
|
95
|
+
clearTimeout(timer);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
const truncateLog = (lineArg) => {
|
|
99
|
+
if (Buffer.byteLength(lineArg, 'utf8') <= supervisorLogLineBytes) {
|
|
100
|
+
return { line: lineArg, truncated: false };
|
|
101
|
+
}
|
|
102
|
+
const contentBytes = supervisorLogLineBytes - Buffer.byteLength(logSuffix, 'utf8');
|
|
103
|
+
const content = Buffer.from(lineArg, 'utf8')
|
|
104
|
+
.subarray(0, contentBytes)
|
|
105
|
+
.toString('utf8')
|
|
106
|
+
.replace(/\uFFFD$/u, '');
|
|
107
|
+
return { line: `${content}${logSuffix}`, truncated: true };
|
|
108
|
+
};
|
|
109
|
+
export const resolveFlexChildEntryPath = () => {
|
|
110
|
+
const modulePath = plugins.url.fileURLToPath(import.meta.url);
|
|
111
|
+
const sourceDirectory = plugins.path.dirname(modulePath);
|
|
112
|
+
const packageDirectory = plugins.fs.realpathSync.native(plugins.path.dirname(sourceDirectory));
|
|
113
|
+
const packageJsonPath = plugins.fs.realpathSync.native(plugins.path.join(packageDirectory, 'package.json'));
|
|
114
|
+
const packageJson = JSON.parse(plugins.fs.readFileSync(packageJsonPath, 'utf8'));
|
|
115
|
+
if (!packageJson
|
|
116
|
+
|| typeof packageJson !== 'object'
|
|
117
|
+
|| !('name' in packageJson)
|
|
118
|
+
|| packageJson.name !== commitinfo.name)
|
|
119
|
+
throw new Error('The Flex child package identity is invalid.');
|
|
120
|
+
const childPath = plugins.fs.realpathSync.native(plugins.path.join(packageDirectory, 'dist_ts', 'flexharness.child.js'));
|
|
121
|
+
const relative = plugins.path.relative(packageDirectory, childPath);
|
|
122
|
+
if (relative === '..'
|
|
123
|
+
|| relative.startsWith(`..${plugins.path.sep}`)
|
|
124
|
+
|| plugins.path.isAbsolute(relative)
|
|
125
|
+
|| relative !== plugins.path.join('dist_ts', 'flexharness.child.js'))
|
|
126
|
+
throw new Error('The Flex child entry escaped its package.');
|
|
127
|
+
if (!plugins.fs.statSync(childPath).isFile()) {
|
|
128
|
+
throw new Error('The package-owned Flex child entry is not a file.');
|
|
129
|
+
}
|
|
130
|
+
return childPath;
|
|
131
|
+
};
|
|
132
|
+
export class FlexSupervisor {
|
|
133
|
+
options;
|
|
134
|
+
status = { state: 'stopped', ready: false };
|
|
135
|
+
child;
|
|
136
|
+
lifecycle;
|
|
137
|
+
transport;
|
|
138
|
+
ownedProcessGroupId;
|
|
139
|
+
orphanReapTask;
|
|
140
|
+
childTaskDrainTask;
|
|
141
|
+
childExitCleanupPending = false;
|
|
142
|
+
pendingChildExit;
|
|
143
|
+
lastExit;
|
|
144
|
+
browserPeerId = '';
|
|
145
|
+
startPromise;
|
|
146
|
+
stopPromise;
|
|
147
|
+
startupResolve;
|
|
148
|
+
startupReject;
|
|
149
|
+
pendingRequests = new Map();
|
|
150
|
+
activeHostRequests = new Map();
|
|
151
|
+
hostRequestTasks = new Set();
|
|
152
|
+
pendingHostSuccessAcknowledgements = new Map();
|
|
153
|
+
activeReadyHostRequests = new Set();
|
|
154
|
+
browserFrameTasks = new Set();
|
|
155
|
+
browserFrameTaskBytes = 0;
|
|
156
|
+
settledHostRequestIds = new Set();
|
|
157
|
+
eventListeners = new Set();
|
|
158
|
+
logs = [];
|
|
159
|
+
stdoutAccumulator = {
|
|
160
|
+
decoder: new TextDecoder(), partial: '', dropping: false,
|
|
161
|
+
};
|
|
162
|
+
stderrAccumulator = {
|
|
163
|
+
decoder: new TextDecoder(), partial: '', dropping: false,
|
|
164
|
+
};
|
|
165
|
+
cancellationGraceTimeoutMs;
|
|
166
|
+
childTaskDrainTimeoutMs;
|
|
167
|
+
constructor(options = {}) {
|
|
168
|
+
this.options = options;
|
|
169
|
+
this.cancellationGraceTimeoutMs = this.normalizeDeadline(options.cancellationGraceTimeoutMs, flexIpcCancellationGraceTimeoutMs, 'cancellationGraceTimeoutMs');
|
|
170
|
+
this.childTaskDrainTimeoutMs = this.normalizeDeadline(options.childTaskDrainTimeoutMs, flexIpcControlTimeoutMs, 'childTaskDrainTimeoutMs');
|
|
171
|
+
}
|
|
172
|
+
getStatus() {
|
|
173
|
+
return {
|
|
174
|
+
...this.status,
|
|
175
|
+
...(this.child?.pid ? { pid: this.child.pid } : {}),
|
|
176
|
+
...(this.lastExit ? { lastExit: { ...this.lastExit } } : {}),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
getLogSnapshot() {
|
|
180
|
+
return this.logs.map((entry) => ({ ...entry }));
|
|
181
|
+
}
|
|
182
|
+
ownsChildPeer(peerIdArg) {
|
|
183
|
+
return this.browserPeerId !== ''
|
|
184
|
+
&& this.browserPeerId === peerIdArg
|
|
185
|
+
&& this.child?.exitCode === null
|
|
186
|
+
&& this.child.signalCode === null;
|
|
187
|
+
}
|
|
188
|
+
ownsBrowserPeer(peerIdArg) {
|
|
189
|
+
return this.status.ready && this.ownsChildPeer(peerIdArg);
|
|
190
|
+
}
|
|
191
|
+
ownsHostPeer(peerIdArg) {
|
|
192
|
+
return this.ownsChildPeer(peerIdArg)
|
|
193
|
+
&& (this.status.state === 'starting' || this.status.state === 'ready');
|
|
194
|
+
}
|
|
195
|
+
subscribe(listenerArg) {
|
|
196
|
+
this.eventListeners.add(listenerArg);
|
|
197
|
+
return () => this.eventListeners.delete(listenerArg);
|
|
198
|
+
}
|
|
199
|
+
async settleReadyHostRequests() {
|
|
200
|
+
while (this.activeReadyHostRequests.size > 0) {
|
|
201
|
+
const settled = await waitBounded(Promise.allSettled([...this.activeReadyHostRequests]).then(() => true), flexIpcDisposeTimeoutMs);
|
|
202
|
+
if (settled !== true) {
|
|
203
|
+
throw new Error('Prior ready-only Flex host requests did not settle after cleanup.');
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async start(initArg, signalArg) {
|
|
208
|
+
if (this.startPromise)
|
|
209
|
+
return this.startPromise;
|
|
210
|
+
if (this.hostRequestTasks.size > 0) {
|
|
211
|
+
throw new Error('Prior Flex child host requests must settle before another child can start.');
|
|
212
|
+
}
|
|
213
|
+
if (this.child || this.stopPromise || this.status.state === 'stopping') {
|
|
214
|
+
throw new Error('A prior Flex child must stop before another can start.');
|
|
215
|
+
}
|
|
216
|
+
const startPromise = this.performStart(initArg, signalArg);
|
|
217
|
+
this.startPromise = startPromise;
|
|
218
|
+
try {
|
|
219
|
+
return await startPromise;
|
|
220
|
+
}
|
|
221
|
+
finally {
|
|
222
|
+
if (this.startPromise === startPromise)
|
|
223
|
+
this.startPromise = undefined;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
async request(methodArg, payloadArg, signalArg) {
|
|
227
|
+
if (methodArg !== 'service.status' && !this.status.ready) {
|
|
228
|
+
throw new FlexServiceError(this.status.state === 'unsupported' ? 'UNSUPPORTED_RUNTIME' : 'NOT_READY');
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
return await this.sendRequest(methodArg, payloadArg, methodArg === 'slash.execute' ? flexIpcSlashTimeoutMs : flexIpcControlTimeoutMs, signalArg);
|
|
232
|
+
}
|
|
233
|
+
catch (errorArg) {
|
|
234
|
+
if (errorArg instanceof FlexServiceError
|
|
235
|
+
&& errorArg.code === 'OUTCOME_UNKNOWN') {
|
|
236
|
+
try {
|
|
237
|
+
await this.stop();
|
|
238
|
+
}
|
|
239
|
+
catch (stopErrorArg) {
|
|
240
|
+
throw new AggregateError([errorArg, stopErrorArg], 'The timed-out Flex request could not stop its child.');
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
throw errorArg;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
async requestToCompletion(methodArg, payloadArg) {
|
|
247
|
+
if (methodArg !== 'service.status' && !this.status.ready) {
|
|
248
|
+
throw new FlexServiceError(this.status.state === 'unsupported' ? 'UNSUPPORTED_RUNTIME' : 'NOT_READY');
|
|
249
|
+
}
|
|
250
|
+
return await this.sendRequest(methodArg, payloadArg, undefined);
|
|
251
|
+
}
|
|
252
|
+
async stop() {
|
|
253
|
+
if (this.stopPromise)
|
|
254
|
+
return this.stopPromise;
|
|
255
|
+
const stopPromise = this.performStop();
|
|
256
|
+
this.stopPromise = stopPromise;
|
|
257
|
+
try {
|
|
258
|
+
await stopPromise;
|
|
259
|
+
}
|
|
260
|
+
finally {
|
|
261
|
+
if (this.stopPromise === stopPromise)
|
|
262
|
+
this.stopPromise = undefined;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
async performStart(initArg, signalArg) {
|
|
266
|
+
this.status = { state: 'starting', ready: false };
|
|
267
|
+
this.settledHostRequestIds.clear();
|
|
268
|
+
signalArg?.throwIfAborted();
|
|
269
|
+
const childEntry = resolveFlexChildEntryPath();
|
|
270
|
+
const child = plugins.childProcess.spawn(process.execPath, [childEntry], {
|
|
271
|
+
cwd: plugins.path.dirname(plugins.path.dirname(childEntry)),
|
|
272
|
+
detached: process.platform !== 'win32',
|
|
273
|
+
shell: false,
|
|
274
|
+
windowsHide: true,
|
|
275
|
+
env: createSanitizedRuntimeEnvironment(),
|
|
276
|
+
stdio: ['ignore', 'pipe', 'pipe', 'pipe', 'pipe'],
|
|
277
|
+
});
|
|
278
|
+
this.child = child;
|
|
279
|
+
this.lifecycle = this.observeChild(child);
|
|
280
|
+
if (!child.pid) {
|
|
281
|
+
await this.stop().catch(() => undefined);
|
|
282
|
+
throw new Error('The Flex child did not provide a process ID.');
|
|
283
|
+
}
|
|
284
|
+
this.browserPeerId = `flex-child:${child.pid}:${plugins.crypto.randomBytes(12).toString('base64url')}`;
|
|
285
|
+
if (process.platform !== 'win32')
|
|
286
|
+
this.ownedProcessGroupId = child.pid;
|
|
287
|
+
const parentWriter = child.stdio[3];
|
|
288
|
+
const parentReader = child.stdio[4];
|
|
289
|
+
if (!(parentWriter instanceof plugins.stream.Writable)
|
|
290
|
+
|| !(parentReader instanceof plugins.stream.Readable)) {
|
|
291
|
+
await this.stop().catch(() => undefined);
|
|
292
|
+
throw new Error('The Flex child control pipes were not created.');
|
|
293
|
+
}
|
|
294
|
+
const transport = new FlexFramedTransport({
|
|
295
|
+
readable: parentReader,
|
|
296
|
+
writable: parentWriter,
|
|
297
|
+
parseIncoming: parseFlexChildMessage,
|
|
298
|
+
validateOutgoing: parseFlexParentMessage,
|
|
299
|
+
});
|
|
300
|
+
this.transport = transport;
|
|
301
|
+
const browserPeerId = this.browserPeerId;
|
|
302
|
+
transport.onMessage((message) => this.handleChildMessage(message, browserPeerId));
|
|
303
|
+
transport.onError(() => {
|
|
304
|
+
if (this.transport === transport && this.ownsChildPeer(browserPeerId)) {
|
|
305
|
+
this.handleProtocolFailure();
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
transport.onClose(() => {
|
|
309
|
+
if (this.transport === transport
|
|
310
|
+
&& this.status.state !== 'stopping'
|
|
311
|
+
&& this.status.state !== 'stopped')
|
|
312
|
+
this.handleProtocolFailure();
|
|
313
|
+
});
|
|
314
|
+
const startup = new Promise((resolve, reject) => {
|
|
315
|
+
this.startupResolve = resolve;
|
|
316
|
+
this.startupReject = reject;
|
|
317
|
+
});
|
|
318
|
+
try {
|
|
319
|
+
await transport.send({
|
|
320
|
+
version: flexIpcProtocolVersion,
|
|
321
|
+
type: 'init',
|
|
322
|
+
init: initArg,
|
|
323
|
+
});
|
|
324
|
+
const result = await this.waitForStartup(startup, this.lifecycle, signalArg);
|
|
325
|
+
if (result.state === 'failed')
|
|
326
|
+
throw new Error('The Flex child failed during initialization.');
|
|
327
|
+
if (result.state === 'unsupported') {
|
|
328
|
+
await this.stop();
|
|
329
|
+
this.status = { ...result };
|
|
330
|
+
return this.getStatus();
|
|
331
|
+
}
|
|
332
|
+
this.status = { ...result, pid: child.pid };
|
|
333
|
+
return this.getStatus();
|
|
334
|
+
}
|
|
335
|
+
catch (errorArg) {
|
|
336
|
+
await this.stop().catch(() => undefined);
|
|
337
|
+
this.status = { state: 'failed', ready: false };
|
|
338
|
+
throw new Error('Flex child startup failed.', { cause: errorArg });
|
|
339
|
+
}
|
|
340
|
+
finally {
|
|
341
|
+
this.startupResolve = undefined;
|
|
342
|
+
this.startupReject = undefined;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
async waitForStartup(startupArg, lifecycleArg, signalArg) {
|
|
346
|
+
let timeout;
|
|
347
|
+
let abortListener;
|
|
348
|
+
try {
|
|
349
|
+
const outcomes = [
|
|
350
|
+
startupArg,
|
|
351
|
+
lifecycleArg.then(() => {
|
|
352
|
+
throw new Error('The Flex child exited during startup.');
|
|
353
|
+
}),
|
|
354
|
+
new Promise((_, reject) => {
|
|
355
|
+
timeout = setTimeout(() => reject(new Error('The Flex child exceeded its startup deadline.')), flexIpcStartupTimeoutMs);
|
|
356
|
+
}),
|
|
357
|
+
];
|
|
358
|
+
if (signalArg) {
|
|
359
|
+
outcomes.push(new Promise((_, reject) => {
|
|
360
|
+
if (signalArg.aborted) {
|
|
361
|
+
reject(signalArg.reason);
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
abortListener = () => reject(signalArg.reason);
|
|
365
|
+
signalArg.addEventListener('abort', abortListener, { once: true });
|
|
366
|
+
}));
|
|
367
|
+
}
|
|
368
|
+
return await Promise.race(outcomes);
|
|
369
|
+
}
|
|
370
|
+
finally {
|
|
371
|
+
if (timeout)
|
|
372
|
+
clearTimeout(timeout);
|
|
373
|
+
if (abortListener)
|
|
374
|
+
signalArg?.removeEventListener('abort', abortListener);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
handleChildMessage(messageArg, peerIdArg) {
|
|
378
|
+
if (!this.ownsChildPeer(peerIdArg))
|
|
379
|
+
return;
|
|
380
|
+
if (messageArg.type === 'status') {
|
|
381
|
+
this.status = {
|
|
382
|
+
...messageArg.status,
|
|
383
|
+
...(this.child?.pid ? { pid: this.child.pid } : {}),
|
|
384
|
+
};
|
|
385
|
+
if (messageArg.status.state === 'ready'
|
|
386
|
+
|| messageArg.status.state === 'unsupported'
|
|
387
|
+
|| messageArg.status.state === 'failed')
|
|
388
|
+
this.startupResolve?.(messageArg.status);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if (messageArg.type === 'event') {
|
|
392
|
+
for (const listener of [...this.eventListeners]) {
|
|
393
|
+
try {
|
|
394
|
+
listener(messageArg.event);
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
// Event listeners are isolated from the child transport.
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
if (messageArg.type === 'host.request') {
|
|
403
|
+
if (!this.ownsHostPeer(peerIdArg)
|
|
404
|
+
|| this.activeHostRequests.has(messageArg.requestId)
|
|
405
|
+
|| this.settledHostRequestIds.has(messageArg.requestId)
|
|
406
|
+
|| this.hostRequestTasks.size >= flexIpcMaximumBrowserChannels) {
|
|
407
|
+
this.handleProtocolFailure();
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
const operation = this.handleHostRequest(messageArg, peerIdArg);
|
|
411
|
+
this.hostRequestTasks.add(operation);
|
|
412
|
+
if (isReadyOnlyHostRequest(messageArg.method)) {
|
|
413
|
+
this.activeReadyHostRequests.add(operation);
|
|
414
|
+
}
|
|
415
|
+
void operation.finally(() => {
|
|
416
|
+
this.hostRequestTasks.delete(operation);
|
|
417
|
+
this.activeReadyHostRequests.delete(operation);
|
|
418
|
+
this.notifyChildExitCleanup();
|
|
419
|
+
}).catch(() => undefined);
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
if (messageArg.type === 'host.response.acknowledge') {
|
|
423
|
+
const pending = this.pendingHostSuccessAcknowledgements.get(messageArg.requestId);
|
|
424
|
+
if (!pending || pending.peerId !== peerIdArg) {
|
|
425
|
+
this.handleProtocolFailure();
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
this.pendingHostSuccessAcknowledgements.delete(messageArg.requestId);
|
|
429
|
+
if (!pending.acknowledge())
|
|
430
|
+
this.handleProtocolFailure();
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
if (messageArg.type === 'host.cancel') {
|
|
434
|
+
const active = this.activeHostRequests.get(messageArg.requestId);
|
|
435
|
+
if (active) {
|
|
436
|
+
active.abort(new FlexServiceError('ABORTED'));
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
if (!this.settledHostRequestIds.has(messageArg.requestId)) {
|
|
440
|
+
this.handleProtocolFailure();
|
|
441
|
+
}
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
if (messageArg.type === 'browser.channel.frame') {
|
|
445
|
+
const handleBrowserFrame = this.options.handleBrowserFrame;
|
|
446
|
+
if (!this.ownsBrowserPeer(peerIdArg) || !handleBrowserFrame) {
|
|
447
|
+
this.handleProtocolFailure();
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
const transport = this.transport;
|
|
451
|
+
if (!transport) {
|
|
452
|
+
this.handleProtocolFailure();
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
const bytes = Buffer.from(messageArg.dataBase64, 'base64');
|
|
456
|
+
if (this.browserFrameTasks.size >= flexIpcMaximumPendingBrowserFrames
|
|
457
|
+
|| this.browserFrameTaskBytes + bytes.byteLength > flexIpcMaximumPendingBrowserFrameBytes) {
|
|
458
|
+
this.handleProtocolFailure();
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
this.browserFrameTaskBytes += bytes.byteLength;
|
|
462
|
+
let operation;
|
|
463
|
+
operation = Promise.resolve()
|
|
464
|
+
.then(() => handleBrowserFrame(messageArg.channelId, bytes, peerIdArg))
|
|
465
|
+
.finally(() => {
|
|
466
|
+
this.browserFrameTaskBytes -= bytes.byteLength;
|
|
467
|
+
this.browserFrameTasks.delete(operation);
|
|
468
|
+
this.notifyChildExitCleanup();
|
|
469
|
+
});
|
|
470
|
+
this.browserFrameTasks.add(operation);
|
|
471
|
+
void operation.catch(() => {
|
|
472
|
+
if (this.transport === transport && this.ownsBrowserPeer(peerIdArg)) {
|
|
473
|
+
this.handleProtocolFailure();
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
const pending = this.pendingRequests.get(messageArg.requestId);
|
|
479
|
+
if (!pending) {
|
|
480
|
+
this.handleProtocolFailure();
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
this.clearPendingRequest(messageArg.requestId, pending);
|
|
484
|
+
if (pending.cancelled)
|
|
485
|
+
return;
|
|
486
|
+
if (!messageArg.ok) {
|
|
487
|
+
pending.reject(new FlexServiceError(messageArg.error.code));
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
if (pending.kind === 'request'
|
|
491
|
+
&& pending.method
|
|
492
|
+
&& !isFlexResponseResult(pending.method, messageArg.result)) {
|
|
493
|
+
pending.reject(new Error('The Flex child returned an invalid method result.'));
|
|
494
|
+
this.handleProtocolFailure();
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
if (pending.kind === 'dispose'
|
|
498
|
+
&& (!isFlexPlainObject(messageArg.result)
|
|
499
|
+
|| !hasFlexExactKeys(messageArg.result, ['disposed'])
|
|
500
|
+
|| messageArg.result.disposed !== true)) {
|
|
501
|
+
pending.reject(new Error('The Flex child returned an invalid dispose result.'));
|
|
502
|
+
this.handleProtocolFailure();
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
pending.resolve(messageArg.result);
|
|
506
|
+
}
|
|
507
|
+
async sendBrowserFrame(channelIdArg, bytesArg, peerIdArg) {
|
|
508
|
+
if (!this.ownsBrowserPeer(peerIdArg))
|
|
509
|
+
throw new Error('The Flex child generation is unavailable.');
|
|
510
|
+
const transport = this.transport;
|
|
511
|
+
if (!transport)
|
|
512
|
+
throw new Error('The Flex child transport is unavailable.');
|
|
513
|
+
await transport.send({
|
|
514
|
+
version: flexIpcProtocolVersion,
|
|
515
|
+
type: 'browser.channel.frame',
|
|
516
|
+
channelId: channelIdArg,
|
|
517
|
+
dataBase64: bytesArg.toString('base64'),
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
async notifyBrowserChannelClosed(channelIdArg, peerIdArg) {
|
|
521
|
+
if (!this.ownsBrowserPeer(peerIdArg))
|
|
522
|
+
throw new Error('The Flex child generation is unavailable.');
|
|
523
|
+
const transport = this.transport;
|
|
524
|
+
if (!transport)
|
|
525
|
+
throw new Error('The Flex child transport is unavailable.');
|
|
526
|
+
await transport.send({
|
|
527
|
+
version: flexIpcProtocolVersion,
|
|
528
|
+
type: 'browser.channel.closed',
|
|
529
|
+
channelId: channelIdArg,
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
async handleHostRequest(messageArg, peerIdArg) {
|
|
533
|
+
const transport = this.transport;
|
|
534
|
+
const child = this.child;
|
|
535
|
+
if (!transport || !this.options.handleHostRequest || !this.ownsHostPeer(peerIdArg)) {
|
|
536
|
+
this.handleProtocolFailure();
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
if (messageArg.method === 'git.worktree.create' && !this.options.handleUndeliveredHostSuccess) {
|
|
540
|
+
this.handleProtocolFailure();
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
const controller = new AbortController();
|
|
544
|
+
this.activeHostRequests.set(messageArg.requestId, controller);
|
|
545
|
+
const timeout = setTimeout(() => controller.abort(new FlexServiceError('TIMEOUT')), messageArg.timeoutMs);
|
|
546
|
+
timeout.unref();
|
|
547
|
+
let completedResult;
|
|
548
|
+
let deliveryState;
|
|
549
|
+
let compensationTask;
|
|
550
|
+
let responseSendAttempted = false;
|
|
551
|
+
let compensationFailed = false;
|
|
552
|
+
let acknowledgementTimeout;
|
|
553
|
+
let acknowledgementAbortListener;
|
|
554
|
+
let acknowledgementResolve;
|
|
555
|
+
let acknowledgementReject;
|
|
556
|
+
let pendingAcknowledgement;
|
|
557
|
+
let acknowledgementPromise;
|
|
558
|
+
const compensateUndeliveredSuccess = () => {
|
|
559
|
+
if (deliveryState === 'acknowledged')
|
|
560
|
+
return Promise.resolve();
|
|
561
|
+
if (compensationTask)
|
|
562
|
+
return compensationTask;
|
|
563
|
+
const result = completedResult;
|
|
564
|
+
if (!result)
|
|
565
|
+
return Promise.resolve();
|
|
566
|
+
deliveryState = 'compensating';
|
|
567
|
+
if (pendingAcknowledgement
|
|
568
|
+
&& this.pendingHostSuccessAcknowledgements.get(messageArg.requestId)
|
|
569
|
+
=== pendingAcknowledgement) {
|
|
570
|
+
this.pendingHostSuccessAcknowledgements.delete(messageArg.requestId);
|
|
571
|
+
}
|
|
572
|
+
compensationTask = (async () => {
|
|
573
|
+
try {
|
|
574
|
+
await this.options.handleUndeliveredHostSuccess?.(messageArg.method, messageArg.payload, result, peerIdArg);
|
|
575
|
+
deliveryState = 'compensated';
|
|
576
|
+
completedResult = undefined;
|
|
577
|
+
}
|
|
578
|
+
catch (errorArg) {
|
|
579
|
+
compensationFailed = true;
|
|
580
|
+
deliveryState = 'compensated';
|
|
581
|
+
completedResult = undefined;
|
|
582
|
+
throw new GitReversionFencedError('Undelivered Flex host success compensation failed.', { cause: errorArg });
|
|
583
|
+
}
|
|
584
|
+
})();
|
|
585
|
+
return compensationTask;
|
|
586
|
+
};
|
|
587
|
+
const rejectAcknowledgementAfterCompensation = (errorArg) => {
|
|
588
|
+
if (!acknowledgementReject || deliveryState !== 'retained')
|
|
589
|
+
return;
|
|
590
|
+
const task = compensateUndeliveredSuccess();
|
|
591
|
+
void task.then(() => acknowledgementReject?.(errorArg), (compensationError) => acknowledgementReject?.(compensationError));
|
|
592
|
+
};
|
|
593
|
+
try {
|
|
594
|
+
const result = await this.options.handleHostRequest(messageArg.method, messageArg.payload, peerIdArg, controller.signal);
|
|
595
|
+
if (!isFlexHostResponseResult(messageArg.method, result)) {
|
|
596
|
+
throw new Error('The Flex host returned an invalid resource result.');
|
|
597
|
+
}
|
|
598
|
+
completedResult = result;
|
|
599
|
+
deliveryState = 'retained';
|
|
600
|
+
if (controller.signal.aborted) {
|
|
601
|
+
await compensateUndeliveredSuccess();
|
|
602
|
+
controller.signal.throwIfAborted();
|
|
603
|
+
}
|
|
604
|
+
if (!this.ownsChildPeer(peerIdArg) || this.transport !== transport) {
|
|
605
|
+
await compensateUndeliveredSuccess();
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
if (messageArg.method === 'git.worktree.create') {
|
|
609
|
+
acknowledgementPromise = new Promise((resolve, reject) => {
|
|
610
|
+
acknowledgementResolve = resolve;
|
|
611
|
+
acknowledgementReject = reject;
|
|
612
|
+
});
|
|
613
|
+
void acknowledgementPromise.catch(() => undefined);
|
|
614
|
+
pendingAcknowledgement = {
|
|
615
|
+
peerId: peerIdArg,
|
|
616
|
+
acknowledge: () => {
|
|
617
|
+
if (deliveryState !== 'retained')
|
|
618
|
+
return false;
|
|
619
|
+
deliveryState = 'acknowledged';
|
|
620
|
+
completedResult = undefined;
|
|
621
|
+
acknowledgementResolve?.();
|
|
622
|
+
return true;
|
|
623
|
+
},
|
|
624
|
+
};
|
|
625
|
+
this.pendingHostSuccessAcknowledgements.set(messageArg.requestId, pendingAcknowledgement);
|
|
626
|
+
acknowledgementAbortListener = () => {
|
|
627
|
+
rejectAcknowledgementAfterCompensation(controller.signal.reason ?? new FlexServiceError('ABORTED'));
|
|
628
|
+
};
|
|
629
|
+
controller.signal.addEventListener('abort', acknowledgementAbortListener, { once: true });
|
|
630
|
+
if (controller.signal.aborted)
|
|
631
|
+
acknowledgementAbortListener();
|
|
632
|
+
if (!this.ownsChildPeer(peerIdArg) || this.transport !== transport) {
|
|
633
|
+
await compensateUndeliveredSuccess();
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
responseSendAttempted = true;
|
|
638
|
+
try {
|
|
639
|
+
await transport.send({
|
|
640
|
+
version: flexIpcProtocolVersion,
|
|
641
|
+
type: 'host.response',
|
|
642
|
+
requestId: messageArg.requestId,
|
|
643
|
+
ok: true,
|
|
644
|
+
result,
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
catch (errorArg) {
|
|
648
|
+
await compensateUndeliveredSuccess();
|
|
649
|
+
throw errorArg;
|
|
650
|
+
}
|
|
651
|
+
clearTimeout(timeout);
|
|
652
|
+
if (acknowledgementPromise) {
|
|
653
|
+
if (deliveryState === 'retained') {
|
|
654
|
+
acknowledgementTimeout = setTimeout(() => {
|
|
655
|
+
rejectAcknowledgementAfterCompensation(new FlexServiceError('TIMEOUT'));
|
|
656
|
+
}, this.cancellationGraceTimeoutMs);
|
|
657
|
+
acknowledgementTimeout.unref();
|
|
658
|
+
}
|
|
659
|
+
await acknowledgementPromise;
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
deliveryState = 'acknowledged';
|
|
663
|
+
completedResult = undefined;
|
|
664
|
+
}
|
|
665
|
+
this.rememberSettledHostRequest(messageArg.requestId);
|
|
666
|
+
}
|
|
667
|
+
catch (caughtError) {
|
|
668
|
+
let errorArg = caughtError;
|
|
669
|
+
if (completedResult) {
|
|
670
|
+
try {
|
|
671
|
+
await compensateUndeliveredSuccess();
|
|
672
|
+
}
|
|
673
|
+
catch (compensationError) {
|
|
674
|
+
errorArg = compensationError;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
if (responseSendAttempted) {
|
|
678
|
+
if (deliveryState === 'acknowledged') {
|
|
679
|
+
this.rememberSettledHostRequest(messageArg.requestId);
|
|
680
|
+
}
|
|
681
|
+
else {
|
|
682
|
+
this.failClosedChildGeneration(errorArg instanceof Error
|
|
683
|
+
? errorArg
|
|
684
|
+
: new Error('Flex host success delivery failed.'), transport, child);
|
|
685
|
+
}
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
if (!this.ownsChildPeer(peerIdArg) || this.transport !== transport)
|
|
689
|
+
return;
|
|
690
|
+
const authoritativeError = errorArg instanceof GitReversionFencedError
|
|
691
|
+
? errorArg
|
|
692
|
+
: controller.signal.aborted
|
|
693
|
+
? controller.signal.reason
|
|
694
|
+
: errorArg;
|
|
695
|
+
const code = authoritativeError instanceof FlexServiceError
|
|
696
|
+
? authoritativeError.code
|
|
697
|
+
: authoritativeError instanceof GitReversionFencedError
|
|
698
|
+
? 'OUTCOME_UNKNOWN'
|
|
699
|
+
: authoritativeError instanceof GitReversionConflictError
|
|
700
|
+
|| authoritativeError instanceof GitReversionDirtyWorktreeError
|
|
701
|
+
? 'CONFLICT'
|
|
702
|
+
: 'INTERNAL';
|
|
703
|
+
await transport.send({
|
|
704
|
+
version: flexIpcProtocolVersion,
|
|
705
|
+
type: 'host.response',
|
|
706
|
+
requestId: messageArg.requestId,
|
|
707
|
+
ok: false,
|
|
708
|
+
error: {
|
|
709
|
+
name: 'FlexServiceError',
|
|
710
|
+
code,
|
|
711
|
+
message: code === 'OUTCOME_UNKNOWN'
|
|
712
|
+
? 'The Flex operation outcome is unknown.'
|
|
713
|
+
: code === 'CONFLICT'
|
|
714
|
+
? 'The Flex operation conflicted with a concurrent change.'
|
|
715
|
+
: authoritativeError instanceof FlexServiceError
|
|
716
|
+
? authoritativeError.message
|
|
717
|
+
: 'The Flex operation failed.',
|
|
718
|
+
},
|
|
719
|
+
}).then(() => {
|
|
720
|
+
this.rememberSettledHostRequest(messageArg.requestId);
|
|
721
|
+
if (compensationFailed)
|
|
722
|
+
this.handleProtocolFailure();
|
|
723
|
+
}, () => {
|
|
724
|
+
if (this.ownsChildPeer(peerIdArg) && this.transport === transport) {
|
|
725
|
+
this.handleProtocolFailure();
|
|
726
|
+
}
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
finally {
|
|
730
|
+
clearTimeout(timeout);
|
|
731
|
+
if (acknowledgementTimeout)
|
|
732
|
+
clearTimeout(acknowledgementTimeout);
|
|
733
|
+
if (acknowledgementAbortListener) {
|
|
734
|
+
controller.signal.removeEventListener('abort', acknowledgementAbortListener);
|
|
735
|
+
}
|
|
736
|
+
if (pendingAcknowledgement
|
|
737
|
+
&& this.pendingHostSuccessAcknowledgements.get(messageArg.requestId)
|
|
738
|
+
=== pendingAcknowledgement) {
|
|
739
|
+
this.pendingHostSuccessAcknowledgements.delete(messageArg.requestId);
|
|
740
|
+
}
|
|
741
|
+
if (this.activeHostRequests.get(messageArg.requestId) === controller) {
|
|
742
|
+
this.activeHostRequests.delete(messageArg.requestId);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
sendRequest(methodArg, payloadArg, timeoutMsArg, signalArg) {
|
|
747
|
+
return this.sendPending('request', timeoutMsArg, (requestId) => ({
|
|
748
|
+
version: flexIpcProtocolVersion,
|
|
749
|
+
type: 'request',
|
|
750
|
+
requestId,
|
|
751
|
+
method: methodArg,
|
|
752
|
+
payload: payloadArg,
|
|
753
|
+
}), methodArg, signalArg);
|
|
754
|
+
}
|
|
755
|
+
sendDispose(timeoutMsArg) {
|
|
756
|
+
return this.sendPending('dispose', timeoutMsArg, (requestId) => ({
|
|
757
|
+
version: flexIpcProtocolVersion,
|
|
758
|
+
type: 'dispose',
|
|
759
|
+
requestId,
|
|
760
|
+
}));
|
|
761
|
+
}
|
|
762
|
+
sendPending(kindArg, timeoutMsArg, createMessageArg, methodArg, signalArg) {
|
|
763
|
+
const transport = this.transport;
|
|
764
|
+
if (!transport)
|
|
765
|
+
return Promise.reject(new Error('The Flex child transport is unavailable.'));
|
|
766
|
+
if (this.pendingRequests.size >= flexIpcMaximumPendingRequests) {
|
|
767
|
+
return Promise.reject(new FlexServiceError('LIMIT_EXCEEDED'));
|
|
768
|
+
}
|
|
769
|
+
const child = this.child;
|
|
770
|
+
const requestId = plugins.crypto.randomBytes(16).toString('base64url');
|
|
771
|
+
return new Promise((resolve, reject) => {
|
|
772
|
+
if (signalArg?.aborted) {
|
|
773
|
+
reject(signalArg.reason ?? new DOMException('The operation was aborted.', 'AbortError'));
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
const timeout = timeoutMsArg === undefined
|
|
777
|
+
? undefined
|
|
778
|
+
: setTimeout(() => {
|
|
779
|
+
const pending = this.pendingRequests.get(requestId);
|
|
780
|
+
if (!pending || pending.cancelled)
|
|
781
|
+
return;
|
|
782
|
+
this.cancelPendingRequest(requestId, pending, new FlexServiceError(pending.dispatched && outcomeMayBeUnknown(pending.method)
|
|
783
|
+
? 'OUTCOME_UNKNOWN'
|
|
784
|
+
: 'TIMEOUT'), transport, child);
|
|
785
|
+
}, timeoutMsArg);
|
|
786
|
+
timeout?.unref();
|
|
787
|
+
const pending = {
|
|
788
|
+
kind: kindArg,
|
|
789
|
+
...(methodArg ? { method: methodArg } : {}),
|
|
790
|
+
resolve,
|
|
791
|
+
reject,
|
|
792
|
+
...(timeout ? { timeout } : {}),
|
|
793
|
+
...(signalArg === undefined ? {} : { signal: signalArg }),
|
|
794
|
+
};
|
|
795
|
+
this.pendingRequests.set(requestId, pending);
|
|
796
|
+
if (signalArg) {
|
|
797
|
+
const abortListener = () => {
|
|
798
|
+
if (this.pendingRequests.get(requestId) !== pending)
|
|
799
|
+
return;
|
|
800
|
+
this.cancelPendingRequest(requestId, pending, pending.dispatched && outcomeMayBeUnknown(pending.method)
|
|
801
|
+
? new FlexServiceError('OUTCOME_UNKNOWN')
|
|
802
|
+
: signalArg.reason ?? new DOMException('The operation was aborted.', 'AbortError'), transport, child);
|
|
803
|
+
};
|
|
804
|
+
pending.abortListener = abortListener;
|
|
805
|
+
signalArg.addEventListener('abort', abortListener, { once: true });
|
|
806
|
+
if (signalArg.aborted)
|
|
807
|
+
abortListener();
|
|
808
|
+
}
|
|
809
|
+
if (this.pendingRequests.get(requestId) !== pending || pending.cancelled)
|
|
810
|
+
return;
|
|
811
|
+
pending.dispatched = true;
|
|
812
|
+
void transport.send(createMessageArg(requestId)).catch(() => {
|
|
813
|
+
const pending = this.pendingRequests.get(requestId);
|
|
814
|
+
if (!pending)
|
|
815
|
+
return;
|
|
816
|
+
this.clearPendingRequest(requestId, pending);
|
|
817
|
+
if (!pending.cancelled) {
|
|
818
|
+
pending.reject(new Error('The Flex child request could not be sent.'));
|
|
819
|
+
}
|
|
820
|
+
this.failClosedChildGeneration(new Error('The Flex child request could not be sent.'), transport, child);
|
|
821
|
+
});
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
cancelPendingRequest(requestIdArg, pendingArg, rejectionArg, transportArg, childArg) {
|
|
825
|
+
if (this.pendingRequests.get(requestIdArg) !== pendingArg || pendingArg.cancelled)
|
|
826
|
+
return;
|
|
827
|
+
if (pendingArg.timeout)
|
|
828
|
+
clearTimeout(pendingArg.timeout);
|
|
829
|
+
if (pendingArg.signal && pendingArg.abortListener) {
|
|
830
|
+
pendingArg.signal.removeEventListener('abort', pendingArg.abortListener);
|
|
831
|
+
pendingArg.signal = undefined;
|
|
832
|
+
pendingArg.abortListener = undefined;
|
|
833
|
+
}
|
|
834
|
+
pendingArg.cancelled = true;
|
|
835
|
+
pendingArg.reject(rejectionArg);
|
|
836
|
+
if (!pendingArg.dispatched) {
|
|
837
|
+
this.clearPendingRequest(requestIdArg, pendingArg);
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
pendingArg.cancellationGraceTimeout = setTimeout(() => {
|
|
841
|
+
if (this.pendingRequests.get(requestIdArg) !== pendingArg)
|
|
842
|
+
return;
|
|
843
|
+
this.clearPendingRequest(requestIdArg, pendingArg);
|
|
844
|
+
this.failClosedChildGeneration(new Error('The Flex child did not settle a cancelled request.'), transportArg, childArg);
|
|
845
|
+
}, this.cancellationGraceTimeoutMs);
|
|
846
|
+
pendingArg.cancellationGraceTimeout.unref();
|
|
847
|
+
void transportArg.send({
|
|
848
|
+
version: flexIpcProtocolVersion,
|
|
849
|
+
type: 'request.cancel',
|
|
850
|
+
requestId: requestIdArg,
|
|
851
|
+
}).catch(() => {
|
|
852
|
+
if (this.pendingRequests.get(requestIdArg) !== pendingArg)
|
|
853
|
+
return;
|
|
854
|
+
this.clearPendingRequest(requestIdArg, pendingArg);
|
|
855
|
+
this.failClosedChildGeneration(new Error('The Flex request cancellation could not be sent.'), transportArg, childArg);
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
clearPendingRequest(requestIdArg, pendingArg) {
|
|
859
|
+
if (this.pendingRequests.get(requestIdArg) === pendingArg) {
|
|
860
|
+
this.pendingRequests.delete(requestIdArg);
|
|
861
|
+
}
|
|
862
|
+
if (pendingArg.timeout)
|
|
863
|
+
clearTimeout(pendingArg.timeout);
|
|
864
|
+
if (pendingArg.cancellationGraceTimeout) {
|
|
865
|
+
clearTimeout(pendingArg.cancellationGraceTimeout);
|
|
866
|
+
pendingArg.cancellationGraceTimeout = undefined;
|
|
867
|
+
}
|
|
868
|
+
if (pendingArg.signal && pendingArg.abortListener) {
|
|
869
|
+
pendingArg.signal.removeEventListener('abort', pendingArg.abortListener);
|
|
870
|
+
pendingArg.signal = undefined;
|
|
871
|
+
pendingArg.abortListener = undefined;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
async performStop() {
|
|
875
|
+
const child = this.child;
|
|
876
|
+
const lifecycle = this.lifecycle;
|
|
877
|
+
if (!child || !lifecycle) {
|
|
878
|
+
this.rejectPending(new Error('The Flex child stopped.'));
|
|
879
|
+
await this.awaitChildTaskDrain();
|
|
880
|
+
await this.reapRetainedProcessGroup();
|
|
881
|
+
this.notifyChildExitCleanup();
|
|
882
|
+
this.status = { state: 'stopped', ready: false };
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
this.status = { state: 'stopping', ready: false, pid: child.pid };
|
|
886
|
+
this.clearCancellationGraceTimeouts();
|
|
887
|
+
const deadline = Date.now() + flexIpcDisposeTimeoutMs;
|
|
888
|
+
if (this.transport && child.exitCode === null && child.signalCode === null) {
|
|
889
|
+
await this.sendDispose(flexIpcDisposeTimeoutMs).catch(() => undefined);
|
|
890
|
+
const remaining = Math.max(1, deadline - Date.now());
|
|
891
|
+
await waitBounded(lifecycle, remaining);
|
|
892
|
+
}
|
|
893
|
+
if (child.exitCode === null && child.signalCode === null) {
|
|
894
|
+
await this.terminateOwnedChild(child, lifecycle);
|
|
895
|
+
}
|
|
896
|
+
const orphanTask = this.orphanReapTask;
|
|
897
|
+
if (orphanTask)
|
|
898
|
+
await orphanTask;
|
|
899
|
+
await this.reapRetainedProcessGroup();
|
|
900
|
+
const confirmed = await waitBounded(lifecycle, supervisorKillTimeoutMs);
|
|
901
|
+
if (!confirmed && child.exitCode === null && child.signalCode === null) {
|
|
902
|
+
this.status = { state: 'failed', ready: false };
|
|
903
|
+
throw new Error('The Flex child exit was not confirmed.');
|
|
904
|
+
}
|
|
905
|
+
await this.transport?.close().catch(() => undefined);
|
|
906
|
+
this.transport = undefined;
|
|
907
|
+
this.rejectPending(new Error('The Flex child stopped.'));
|
|
908
|
+
await this.awaitChildTaskDrain();
|
|
909
|
+
this.notifyChildExitCleanup();
|
|
910
|
+
if (this.child === child)
|
|
911
|
+
this.child = undefined;
|
|
912
|
+
if (this.lifecycle === lifecycle)
|
|
913
|
+
this.lifecycle = undefined;
|
|
914
|
+
this.browserPeerId = '';
|
|
915
|
+
this.status = { state: 'stopped', ready: false };
|
|
916
|
+
}
|
|
917
|
+
async terminateOwnedChild(childArg, lifecycleArg) {
|
|
918
|
+
const processGroupId = this.ownedProcessGroupId;
|
|
919
|
+
if (processGroupId !== undefined && process.platform !== 'win32') {
|
|
920
|
+
if (isProcessGroupAlive(processGroupId))
|
|
921
|
+
signalProcessGroup(processGroupId, 'SIGTERM');
|
|
922
|
+
let exited = await waitFor(() => isProcessGroupAlive(processGroupId), supervisorTermTimeoutMs);
|
|
923
|
+
if (!exited) {
|
|
924
|
+
signalProcessGroup(processGroupId, 'SIGKILL');
|
|
925
|
+
exited = await waitFor(() => isProcessGroupAlive(processGroupId), supervisorKillTimeoutMs);
|
|
926
|
+
}
|
|
927
|
+
if (!exited)
|
|
928
|
+
throw new Error('The owned Flex process group survived SIGKILL.');
|
|
929
|
+
this.ownedProcessGroupId = undefined;
|
|
930
|
+
}
|
|
931
|
+
else {
|
|
932
|
+
childArg.kill('SIGTERM');
|
|
933
|
+
let exited = await waitBounded(lifecycleArg, supervisorTermTimeoutMs);
|
|
934
|
+
if (!exited && childArg.exitCode === null && childArg.signalCode === null) {
|
|
935
|
+
childArg.kill('SIGKILL');
|
|
936
|
+
exited = await waitBounded(lifecycleArg, supervisorKillTimeoutMs);
|
|
937
|
+
}
|
|
938
|
+
if (!exited && childArg.exitCode === null && childArg.signalCode === null) {
|
|
939
|
+
throw new Error('The owned Flex child survived SIGKILL.');
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
observeChild(childArg) {
|
|
944
|
+
childArg.stdout?.on('data', (chunk) => this.consumeLog('stdout', chunk, this.stdoutAccumulator));
|
|
945
|
+
childArg.stderr?.on('data', (chunk) => this.consumeLog('stderr', chunk, this.stderrAccumulator));
|
|
946
|
+
return new Promise((resolve) => {
|
|
947
|
+
let settled = false;
|
|
948
|
+
const finish = (outcomeArg) => {
|
|
949
|
+
if (settled)
|
|
950
|
+
return;
|
|
951
|
+
settled = true;
|
|
952
|
+
this.flushLog('stdout', this.stdoutAccumulator);
|
|
953
|
+
this.flushLog('stderr', this.stderrAccumulator);
|
|
954
|
+
this.status = { state: this.status.state === 'stopping' ? 'stopped' : 'failed', ready: false };
|
|
955
|
+
this.browserPeerId = '';
|
|
956
|
+
this.startupReject?.(new Error('The Flex child exited during startup.'));
|
|
957
|
+
this.rejectPending(new Error('The Flex child exited.'));
|
|
958
|
+
const processGroupId = this.ownedProcessGroupId;
|
|
959
|
+
const terminal = {
|
|
960
|
+
type: outcomeArg.type,
|
|
961
|
+
timestamp: Date.now(),
|
|
962
|
+
...(outcomeArg.code === undefined ? {} : { code: outcomeArg.code }),
|
|
963
|
+
...(outcomeArg.signal === undefined ? {} : { signal: outcomeArg.signal }),
|
|
964
|
+
...(outcomeArg.error?.message
|
|
965
|
+
? { errorMessage: sanitizeExitMessage(outcomeArg.error.message) }
|
|
966
|
+
: {}),
|
|
967
|
+
};
|
|
968
|
+
this.lastExit = terminal;
|
|
969
|
+
try {
|
|
970
|
+
this.options.onChildExitObserved?.({ ...terminal });
|
|
971
|
+
}
|
|
972
|
+
catch {
|
|
973
|
+
// Immediate authority fencing must not prevent lifecycle settlement.
|
|
974
|
+
}
|
|
975
|
+
this.pendingChildExit = terminal;
|
|
976
|
+
this.childExitCleanupPending = true;
|
|
977
|
+
this.startChildTaskDrain();
|
|
978
|
+
if (processGroupId !== undefined && process.platform !== 'win32') {
|
|
979
|
+
const reap = this.reapOrphanedGroup(processGroupId).then(() => {
|
|
980
|
+
if (this.ownedProcessGroupId === processGroupId) {
|
|
981
|
+
this.ownedProcessGroupId = undefined;
|
|
982
|
+
}
|
|
983
|
+
}).finally(() => {
|
|
984
|
+
if (this.orphanReapTask === reap)
|
|
985
|
+
this.orphanReapTask = undefined;
|
|
986
|
+
this.notifyChildExitCleanup();
|
|
987
|
+
});
|
|
988
|
+
this.orphanReapTask = reap;
|
|
989
|
+
void reap.catch(() => undefined);
|
|
990
|
+
}
|
|
991
|
+
else {
|
|
992
|
+
this.notifyChildExitCleanup();
|
|
993
|
+
}
|
|
994
|
+
resolve(outcomeArg);
|
|
995
|
+
};
|
|
996
|
+
childArg.once('exit', (code, signal) => finish({ type: 'exit', code, signal }));
|
|
997
|
+
childArg.once('error', (error) => {
|
|
998
|
+
if (!childArg.pid)
|
|
999
|
+
finish({ type: 'error', error });
|
|
1000
|
+
});
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
async reapOrphanedGroup(processGroupIdArg) {
|
|
1004
|
+
if (!isProcessGroupAlive(processGroupIdArg))
|
|
1005
|
+
return;
|
|
1006
|
+
signalProcessGroup(processGroupIdArg, 'SIGTERM');
|
|
1007
|
+
let exited = await waitFor(() => isProcessGroupAlive(processGroupIdArg), supervisorTermTimeoutMs);
|
|
1008
|
+
if (!exited) {
|
|
1009
|
+
signalProcessGroup(processGroupIdArg, 'SIGKILL');
|
|
1010
|
+
exited = await waitFor(() => isProcessGroupAlive(processGroupIdArg), supervisorKillTimeoutMs);
|
|
1011
|
+
}
|
|
1012
|
+
if (!exited)
|
|
1013
|
+
throw new Error('An owned Flex process-group member survived SIGKILL.');
|
|
1014
|
+
}
|
|
1015
|
+
async reapRetainedProcessGroup() {
|
|
1016
|
+
const processGroupId = this.ownedProcessGroupId;
|
|
1017
|
+
if (processGroupId === undefined || process.platform === 'win32')
|
|
1018
|
+
return;
|
|
1019
|
+
await this.reapOrphanedGroup(processGroupId);
|
|
1020
|
+
if (this.ownedProcessGroupId === processGroupId)
|
|
1021
|
+
this.ownedProcessGroupId = undefined;
|
|
1022
|
+
}
|
|
1023
|
+
notifyChildExitCleanup() {
|
|
1024
|
+
if (!this.childExitCleanupPending)
|
|
1025
|
+
return;
|
|
1026
|
+
if (this.orphanReapTask)
|
|
1027
|
+
return;
|
|
1028
|
+
if (this.childTaskDrainTask)
|
|
1029
|
+
return;
|
|
1030
|
+
if (this.hostRequestTasks.size > 0
|
|
1031
|
+
|| this.browserFrameTasks.size > 0
|
|
1032
|
+
|| this.activeHostRequests.size > 0)
|
|
1033
|
+
return;
|
|
1034
|
+
this.childExitCleanupPending = false;
|
|
1035
|
+
const terminal = this.pendingChildExit;
|
|
1036
|
+
this.pendingChildExit = undefined;
|
|
1037
|
+
if (!terminal)
|
|
1038
|
+
return;
|
|
1039
|
+
try {
|
|
1040
|
+
this.options.onChildExit?.({ ...terminal });
|
|
1041
|
+
}
|
|
1042
|
+
catch {
|
|
1043
|
+
// Child lifecycle cleanup must not prevent lifecycle settlement.
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
handleProtocolFailure() {
|
|
1047
|
+
this.rejectPending(new Error('The Flex child protocol failed.'));
|
|
1048
|
+
this.startupReject?.(new Error('The Flex child protocol failed.'));
|
|
1049
|
+
void this.stop().catch(() => undefined);
|
|
1050
|
+
}
|
|
1051
|
+
rejectPending(errorArg) {
|
|
1052
|
+
for (const [requestId, pending] of this.pendingRequests) {
|
|
1053
|
+
this.clearPendingRequest(requestId, pending);
|
|
1054
|
+
pending.reject(pending.dispatched && outcomeMayBeUnknown(pending.method)
|
|
1055
|
+
? new FlexServiceError('OUTCOME_UNKNOWN')
|
|
1056
|
+
: errorArg);
|
|
1057
|
+
}
|
|
1058
|
+
for (const controller of this.activeHostRequests.values())
|
|
1059
|
+
controller.abort(errorArg);
|
|
1060
|
+
this.settledHostRequestIds.clear();
|
|
1061
|
+
}
|
|
1062
|
+
clearCancellationGraceTimeouts() {
|
|
1063
|
+
for (const pending of this.pendingRequests.values()) {
|
|
1064
|
+
if (!pending.cancellationGraceTimeout)
|
|
1065
|
+
continue;
|
|
1066
|
+
clearTimeout(pending.cancellationGraceTimeout);
|
|
1067
|
+
pending.cancellationGraceTimeout = undefined;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
failClosedChildGeneration(errorArg, transportArg, childArg) {
|
|
1071
|
+
if (!childArg
|
|
1072
|
+
|| this.child !== childArg
|
|
1073
|
+
|| this.transport !== transportArg
|
|
1074
|
+
|| childArg.exitCode !== null
|
|
1075
|
+
|| childArg.signalCode !== null)
|
|
1076
|
+
return;
|
|
1077
|
+
this.status = { state: 'failed', ready: false };
|
|
1078
|
+
this.browserPeerId = '';
|
|
1079
|
+
this.transport = undefined;
|
|
1080
|
+
this.startupReject?.(errorArg);
|
|
1081
|
+
this.rejectPending(errorArg);
|
|
1082
|
+
void transportArg.close().catch(() => undefined);
|
|
1083
|
+
void this.stop().catch(() => undefined);
|
|
1084
|
+
}
|
|
1085
|
+
startChildTaskDrain() {
|
|
1086
|
+
if (this.childTaskDrainTask)
|
|
1087
|
+
return;
|
|
1088
|
+
let task;
|
|
1089
|
+
task = this.drainChildTasks().finally(() => {
|
|
1090
|
+
if (this.childTaskDrainTask === task)
|
|
1091
|
+
this.childTaskDrainTask = undefined;
|
|
1092
|
+
this.notifyChildExitCleanup();
|
|
1093
|
+
});
|
|
1094
|
+
this.childTaskDrainTask = task;
|
|
1095
|
+
void task.catch(() => undefined);
|
|
1096
|
+
}
|
|
1097
|
+
async awaitChildTaskDrain() {
|
|
1098
|
+
const task = this.childTaskDrainTask ?? this.drainChildTasks();
|
|
1099
|
+
await task;
|
|
1100
|
+
}
|
|
1101
|
+
async drainChildTasks() {
|
|
1102
|
+
if (this.hostRequestTasks.size === 0 && this.browserFrameTasks.size === 0)
|
|
1103
|
+
return;
|
|
1104
|
+
const settled = await waitBounded(Promise.allSettled([...this.hostRequestTasks, ...this.browserFrameTasks]), this.childTaskDrainTimeoutMs);
|
|
1105
|
+
if (!settled
|
|
1106
|
+
|| this.hostRequestTasks.size > 0
|
|
1107
|
+
|| this.browserFrameTasks.size > 0
|
|
1108
|
+
|| this.activeHostRequests.size > 0) {
|
|
1109
|
+
this.status = { state: 'failed', ready: false };
|
|
1110
|
+
throw new Error('Flex child tasks did not settle after child shutdown.');
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
rememberSettledHostRequest(requestIdArg) {
|
|
1114
|
+
this.settledHostRequestIds.delete(requestIdArg);
|
|
1115
|
+
this.settledHostRequestIds.add(requestIdArg);
|
|
1116
|
+
while (this.settledHostRequestIds.size > flexIpcMaximumPendingRequests * 4) {
|
|
1117
|
+
const oldest = this.settledHostRequestIds.values().next().value;
|
|
1118
|
+
if (oldest === undefined)
|
|
1119
|
+
break;
|
|
1120
|
+
this.settledHostRequestIds.delete(oldest);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
normalizeDeadline(selectedArg, defaultArg, nameArg) {
|
|
1124
|
+
const selected = selectedArg ?? defaultArg;
|
|
1125
|
+
if (!Number.isSafeInteger(selected) || selected < 1 || selected > defaultArg) {
|
|
1126
|
+
throw new Error(`${nameArg} must be a safe integer between 1 and ${defaultArg}.`);
|
|
1127
|
+
}
|
|
1128
|
+
return selected;
|
|
1129
|
+
}
|
|
1130
|
+
consumeLog(streamArg, chunkArg, accumulatorArg) {
|
|
1131
|
+
const bytes = typeof chunkArg === 'string'
|
|
1132
|
+
? Buffer.from(chunkArg, 'utf8')
|
|
1133
|
+
: chunkArg instanceof Uint8Array
|
|
1134
|
+
? chunkArg
|
|
1135
|
+
: undefined;
|
|
1136
|
+
if (!bytes)
|
|
1137
|
+
return;
|
|
1138
|
+
let text = accumulatorArg.decoder.decode(bytes, { stream: true });
|
|
1139
|
+
while (text.length > 0) {
|
|
1140
|
+
if (accumulatorArg.dropping) {
|
|
1141
|
+
const newline = text.indexOf('\n');
|
|
1142
|
+
if (newline < 0)
|
|
1143
|
+
return;
|
|
1144
|
+
accumulatorArg.dropping = false;
|
|
1145
|
+
text = text.slice(newline + 1);
|
|
1146
|
+
continue;
|
|
1147
|
+
}
|
|
1148
|
+
const newline = text.indexOf('\n');
|
|
1149
|
+
if (newline >= 0) {
|
|
1150
|
+
const complete = `${accumulatorArg.partial}${text.slice(0, newline)}`.replace(/\r$/u, '');
|
|
1151
|
+
accumulatorArg.partial = '';
|
|
1152
|
+
this.addLog(streamArg, complete);
|
|
1153
|
+
text = text.slice(newline + 1);
|
|
1154
|
+
continue;
|
|
1155
|
+
}
|
|
1156
|
+
const complete = `${accumulatorArg.partial}${text}`;
|
|
1157
|
+
if (Buffer.byteLength(complete, 'utf8') > supervisorLogLineBytes) {
|
|
1158
|
+
this.addLog(streamArg, complete);
|
|
1159
|
+
accumulatorArg.partial = '';
|
|
1160
|
+
accumulatorArg.dropping = true;
|
|
1161
|
+
}
|
|
1162
|
+
else {
|
|
1163
|
+
accumulatorArg.partial = complete;
|
|
1164
|
+
}
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
flushLog(streamArg, accumulatorArg) {
|
|
1169
|
+
const final = accumulatorArg.decoder.decode();
|
|
1170
|
+
if (final)
|
|
1171
|
+
this.consumeLog(streamArg, final, accumulatorArg);
|
|
1172
|
+
if (accumulatorArg.partial && !accumulatorArg.dropping) {
|
|
1173
|
+
this.addLog(streamArg, accumulatorArg.partial);
|
|
1174
|
+
}
|
|
1175
|
+
accumulatorArg.partial = '';
|
|
1176
|
+
accumulatorArg.dropping = false;
|
|
1177
|
+
}
|
|
1178
|
+
addLog(streamArg, lineArg) {
|
|
1179
|
+
const bounded = truncateLog(lineArg);
|
|
1180
|
+
this.logs.push({
|
|
1181
|
+
timestamp: Date.now(),
|
|
1182
|
+
stream: streamArg,
|
|
1183
|
+
line: bounded.line,
|
|
1184
|
+
truncated: bounded.truncated,
|
|
1185
|
+
});
|
|
1186
|
+
if (this.logs.length > supervisorLogEntries) {
|
|
1187
|
+
this.logs.splice(0, this.logs.length - supervisorLogEntries);
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5mbGV4c3VwZXJ2aXNvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NsYXNzZXMuZmxleHN1cGVydmlzb3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3ZFLE9BQU8sRUFDTCx5QkFBeUIsRUFDekIsOEJBQThCLEVBQzlCLHVCQUF1QixHQUN4QixNQUFNLDJCQUEyQixDQUFDO0FBQ25DLE9BQU8sRUFBRSxpQ0FBaUMsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3RGLE9BQU8sRUFDTCxnQkFBZ0IsRUFhaEIsaUNBQWlDLEVBQ2pDLHVCQUF1QixFQUN2Qix1QkFBdUIsRUFDdkIsNkJBQTZCLEVBQzdCLHNDQUFzQyxFQUN0QyxrQ0FBa0MsRUFDbEMsNkJBQTZCLEVBQzdCLHNCQUFzQixFQUN0QixxQkFBcUIsRUFDckIsdUJBQXVCLEVBQ3ZCLGdCQUFnQixFQUNoQixpQkFBaUIsRUFDakIsd0JBQXdCLEVBQ3hCLG9CQUFvQixFQUNwQixxQkFBcUIsRUFDckIsc0JBQXNCLEdBQ3ZCLE1BQU0seUJBQXlCLENBQUM7QUFtRmpDLE1BQU0sb0JBQW9CLEdBQUcsR0FBRyxDQUFDO0FBQ2pDLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztBQUN4QyxNQUFNLHVCQUF1QixHQUFHLEtBQUssQ0FBQztBQUN0QyxNQUFNLHVCQUF1QixHQUFHLEtBQUssQ0FBQztBQUN0QyxNQUFNLFNBQVMsR0FBRyxpQkFBaUIsQ0FBQztBQUNwQyxNQUFNLDBCQUEwQixHQUFHLElBQUksQ0FBQztBQUV4QyxNQUFNLDBCQUEwQixHQUFvQyxJQUFJLEdBQUcsQ0FBQztJQUN4RSxnQkFBZ0I7SUFDaEIsa0JBQWtCO0lBQ2xCLGNBQWM7SUFDZCxhQUFhO0lBQ2Isd0JBQXdCO0lBQ3hCLFlBQVk7SUFDWixjQUFjO0lBQ2QsYUFBYTtJQUNiLFlBQVk7SUFDWixhQUFhO0lBQ2IsaUJBQWlCO0lBQ2pCLGVBQWU7SUFDZix1QkFBdUI7SUFDdkIsMEJBQTBCO0lBQzFCLHVDQUF1QztJQUN2QyxvQ0FBb0M7SUFDcEMsa0JBQWtCO0lBQ2xCLHVCQUF1QjtDQUMxQixDQUFDLENBQUM7QUFFSCxNQUFNLG1CQUFtQixHQUFHLENBQUMsU0FBOEIsRUFBVyxFQUFFLENBQUMsU0FBUyxLQUFLLFNBQVM7T0FDM0YsQ0FBQywwQkFBMEIsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7QUFFaEQsTUFBTSxzQkFBc0IsR0FBRyxDQUFDLFNBQWlDLEVBQVcsRUFBRSxDQUFDLENBQzdFLFNBQVMsS0FBSyx5QkFBeUI7T0FDcEMsU0FBUyxLQUFLLHdCQUF3QjtPQUN0QyxTQUFTLEtBQUssMkJBQTJCO09BQ3pDLFNBQVMsS0FBSyxzQkFBc0I7T0FDcEMsU0FBUyxLQUFLLHVCQUF1QixDQUN6QyxDQUFDO0FBRUYsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLFVBQWtCLEVBQVUsRUFBRTtJQUN6RCxNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLHlCQUF5QixFQUFFLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzVFLElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLElBQUksMEJBQTBCO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFDekYsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUM7U0FDbEMsUUFBUSxDQUFDLENBQUMsRUFBRSwwQkFBMEIsQ0FBQztTQUN2QyxRQUFRLENBQUMsTUFBTSxDQUFDO1NBQ2hCLE9BQU8sQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDN0IsQ0FBQyxDQUFDO0FBRUYsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLFFBQWlCLEVBQVcsRUFBRSxDQUN0RCxPQUFPLFFBQVEsS0FBSyxRQUFRO09BQ3pCLFFBQVEsS0FBSyxJQUFJO09BQ2pCLE1BQU0sSUFBSSxRQUFRO09BQ2xCLFFBQVEsQ0FBQyxJQUFJLEtBQUssT0FBTyxDQUFDO0FBRS9CLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxpQkFBeUIsRUFBVyxFQUFFO0lBQ2pFLElBQUksQ0FBQztRQUNILE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNwQyxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFBQyxPQUFPLFFBQVEsRUFBRSxDQUFDO1FBQ2xCLElBQUksZ0JBQWdCLENBQUMsUUFBUSxDQUFDO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFDN0MsTUFBTSxRQUFRLENBQUM7SUFDakIsQ0FBQztBQUNILENBQUMsQ0FBQztBQUVGLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxpQkFBeUIsRUFBRSxTQUF5QixFQUFRLEVBQUU7SUFDeEYsSUFBSSxDQUFDO1FBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLGlCQUFpQixFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFBQyxPQUFPLFFBQVEsRUFBRSxDQUFDO1FBQ2xCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUM7WUFBRSxNQUFNLFFBQVEsQ0FBQztJQUNsRCxDQUFDO0FBQ0gsQ0FBQyxDQUFDO0FBRUYsTUFBTSxPQUFPLEdBQUcsS0FBSyxFQUFFLFlBQTJCLEVBQUUsWUFBb0IsRUFBb0IsRUFBRTtJQUM1RixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsWUFBWSxDQUFDO0lBQzNDLE9BQU8sWUFBWSxFQUFFLEVBQUUsQ0FBQztRQUN0QixNQUFNLFNBQVMsR0FBRyxRQUFRLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3hDLElBQUksU0FBUyxJQUFJLENBQUM7WUFBRSxPQUFPLEtBQUssQ0FBQztRQUNqQyxNQUFNLElBQUksT0FBTyxDQUFPLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyRixDQUFDO0lBQ0QsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDLENBQUM7QUFFRixNQUFNLFdBQVcsR0FBRyxLQUFLLEVBQUssVUFBc0IsRUFBRSxZQUFvQixFQUEwQixFQUFFO0lBQ3BHLElBQUksS0FBaUMsQ0FBQztJQUN0QyxJQUFJLENBQUM7UUFDSCxPQUFPLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQztZQUN4QixVQUFVO1lBQ1YsSUFBSSxPQUFPLENBQVksQ0FBQyxPQUFPLEVBQUUsRUFBRTtnQkFDakMsS0FBSyxHQUFHLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFDN0QsQ0FBQyxDQUFDO1NBQ0gsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztZQUFTLENBQUM7UUFDVCxJQUFJLEtBQUs7WUFBRSxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakMsQ0FBQztBQUNILENBQUMsQ0FBQztBQUVGLE1BQU0sV0FBVyxHQUFHLENBQUMsT0FBZSxFQUF3QyxFQUFFO0lBQzVFLElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLElBQUksc0JBQXNCLEVBQUUsQ0FBQztRQUNqRSxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDN0MsQ0FBQztJQUNELE1BQU0sWUFBWSxHQUFHLHNCQUFzQixHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ25GLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQztTQUN6QyxRQUFRLENBQUMsQ0FBQyxFQUFFLFlBQVksQ0FBQztTQUN6QixRQUFRLENBQUMsTUFBTSxDQUFDO1NBQ2hCLE9BQU8sQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDM0IsT0FBTyxFQUFFLElBQUksRUFBRSxHQUFHLE9BQU8sR0FBRyxTQUFTLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUM7QUFDN0QsQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUcsR0FBVyxFQUFFO0lBQ3BELE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDOUQsTUFBTSxlQUFlLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDekQsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQztJQUMvRixNQUFNLGVBQWUsR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQ3BELE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLGNBQWMsQ0FBQyxDQUNwRCxDQUFDO0lBQ0YsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxlQUFlLEVBQUUsTUFBTSxDQUFDLENBQVksQ0FBQztJQUM1RixJQUNFLENBQUMsV0FBVztXQUNULE9BQU8sV0FBVyxLQUFLLFFBQVE7V0FDL0IsQ0FBQyxDQUFDLE1BQU0sSUFBSSxXQUFXLENBQUM7V0FDeEIsV0FBVyxDQUFDLElBQUksS0FBSyxVQUFVLENBQUMsSUFBSTtRQUN2QyxNQUFNLElBQUksS0FBSyxDQUFDLDZDQUE2QyxDQUFDLENBQUM7SUFDakUsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUM5QyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxTQUFTLEVBQUUsc0JBQXNCLENBQUMsQ0FDdkUsQ0FBQztJQUNGLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGdCQUFnQixFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQ3BFLElBQ0UsUUFBUSxLQUFLLElBQUk7V0FDZCxRQUFRLENBQUMsVUFBVSxDQUFDLEtBQUssT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztXQUM1QyxPQUFPLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUM7V0FDakMsUUFBUSxLQUFLLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxzQkFBc0IsQ0FBQztRQUNwRSxNQUFNLElBQUksS0FBSyxDQUFDLDJDQUEyQyxDQUFDLENBQUM7SUFDL0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7UUFDN0MsTUFBTSxJQUFJLEtBQUssQ0FBQyxtREFBbUQsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7SUFDRCxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDLENBQUM7QUFFRixNQUFNLE9BQU8sY0FBYztJQXNDSTtJQXJDckIsTUFBTSxHQUEwQixFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDO0lBQ25FLEtBQUssQ0FBcUM7SUFDMUMsU0FBUyxDQUFnQztJQUN6QyxTQUFTLENBQThEO0lBQ3ZFLG1CQUFtQixDQUFVO0lBQzdCLGNBQWMsQ0FBaUI7SUFDL0Isa0JBQWtCLENBQWlCO0lBQ25DLHVCQUF1QixHQUFHLEtBQUssQ0FBQztJQUNoQyxnQkFBZ0IsQ0FBdUI7SUFDdkMsUUFBUSxDQUF1QjtJQUMvQixhQUFhLEdBQUcsRUFBRSxDQUFDO0lBQ25CLFlBQVksQ0FBa0M7SUFDOUMsV0FBVyxDQUFpQjtJQUM1QixjQUFjLENBQTJDO0lBQ3pELGFBQWEsQ0FBNkI7SUFDakMsZUFBZSxHQUFHLElBQUksR0FBRyxFQUErQixDQUFDO0lBQ3pELGtCQUFrQixHQUFHLElBQUksR0FBRyxFQUEyQixDQUFDO0lBQ3hELGdCQUFnQixHQUFHLElBQUksR0FBRyxFQUFpQixDQUFDO0lBQzVDLGtDQUFrQyxHQUFHLElBQUksR0FBRyxFQUcxRCxDQUFDO0lBQ2EsdUJBQXVCLEdBQUcsSUFBSSxHQUFHLEVBQWlCLENBQUM7SUFDbkQsaUJBQWlCLEdBQUcsSUFBSSxHQUFHLEVBQWlCLENBQUM7SUFDdEQscUJBQXFCLEdBQUcsQ0FBQyxDQUFDO0lBQ2pCLHFCQUFxQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFDMUMsY0FBYyxHQUFHLElBQUksR0FBRyxFQUF1QyxDQUFDO0lBQ2hFLElBQUksR0FBOEIsRUFBRSxDQUFDO0lBQ3JDLGlCQUFpQixHQUFvQjtRQUNwRCxPQUFPLEVBQUUsSUFBSSxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxLQUFLO0tBQ3pELENBQUM7SUFDZSxpQkFBaUIsR0FBb0I7UUFDcEQsT0FBTyxFQUFFLElBQUksV0FBVyxFQUFFLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsS0FBSztLQUN6RCxDQUFDO0lBQ2UsMEJBQTBCLENBQVM7SUFDbkMsdUJBQXVCLENBQVM7SUFFakQsWUFBNkIsVUFBa0MsRUFBRTtRQUFwQyxZQUFPLEdBQVAsT0FBTyxDQUE2QjtRQUMvRCxJQUFJLENBQUMsMEJBQTBCLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUN0RCxPQUFPLENBQUMsMEJBQTBCLEVBQ2xDLGlDQUFpQyxFQUNqQyw0QkFBNEIsQ0FDN0IsQ0FBQztRQUNGLElBQUksQ0FBQyx1QkFBdUIsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQ25ELE9BQU8sQ0FBQyx1QkFBdUIsRUFDL0IsdUJBQXVCLEVBQ3ZCLHlCQUF5QixDQUMxQixDQUFDO0lBQ0osQ0FBQztJQUVNLFNBQVM7UUFDZCxPQUFPO1lBQ0wsR0FBRyxJQUFJLENBQUMsTUFBTTtZQUNkLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ25ELEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztTQUM3RCxDQUFDO0lBQ0osQ0FBQztJQUVNLGNBQWM7UUFDbkIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFTSxhQUFhLENBQUMsU0FBaUI7UUFDcEMsT0FBTyxJQUFJLENBQUMsYUFBYSxLQUFLLEVBQUU7ZUFDM0IsSUFBSSxDQUFDLGFBQWEsS0FBSyxTQUFTO2VBQ2hDLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxLQUFLLElBQUk7ZUFDN0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEtBQUssSUFBSSxDQUFDO0lBQ3RDLENBQUM7SUFFTSxlQUFlLENBQUMsU0FBaUI7UUFDdEMsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzVELENBQUM7SUFFTSxZQUFZLENBQUMsU0FBaUI7UUFDbkMsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQztlQUMvQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxLQUFLLFVBQVUsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssS0FBSyxPQUFPLENBQUMsQ0FBQztJQUMzRSxDQUFDO0lBRU0sU0FBUyxDQUFDLFdBQWdEO1FBQy9ELElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3JDLE9BQU8sR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDdkQsQ0FBQztJQUVNLEtBQUssQ0FBQyx1QkFBdUI7UUFDbEMsT0FBTyxJQUFJLENBQUMsdUJBQXVCLENBQUMsSUFBSSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzdDLE1BQU0sT0FBTyxHQUFHLE1BQU0sV0FBVyxDQUMvQixPQUFPLENBQUMsVUFBVSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFDdEUsdUJBQXVCLENBQ3hCLENBQUM7WUFDRixJQUFJLE9BQU8sS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDckIsTUFBTSxJQUFJLEtBQUssQ0FBQyxtRUFBbUUsQ0FBQyxDQUFDO1lBQ3ZGLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVNLEtBQUssQ0FBQyxLQUFLLENBQ2hCLE9BQXlCLEVBQ3pCLFNBQXVCO1FBRXZCLElBQUksSUFBSSxDQUFDLFlBQVk7WUFBRSxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7UUFDaEQsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ25DLE1BQU0sSUFBSSxLQUFLLENBQUMsNEVBQTRFLENBQUMsQ0FBQztRQUNoRyxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxXQUFXLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDdkUsTUFBTSxJQUFJLEtBQUssQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO1FBQzVFLENBQUM7UUFDRCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQztRQUMzRCxJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQztRQUNqQyxJQUFJLENBQUM7WUFDSCxPQUFPLE1BQU0sWUFBWSxDQUFDO1FBQzVCLENBQUM7Z0JBQVMsQ0FBQztZQUNULElBQUksSUFBSSxDQUFDLFlBQVksS0FBSyxZQUFZO2dCQUFFLElBQUksQ0FBQyxZQUFZLEdBQUcsU0FBUyxDQUFDO1FBQ3hFLENBQUM7SUFDSCxDQUFDO0lBRU0sS0FBSyxDQUFDLE9BQU8sQ0FDbEIsU0FBa0IsRUFDbEIsVUFBaUMsRUFDakMsU0FBdUI7UUFFdkIsSUFBSSxTQUFTLEtBQUssZ0JBQWdCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3pELE1BQU0sSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssS0FBSyxhQUFhLENBQUMsQ0FBQyxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUN4RyxDQUFDO1FBQ0QsSUFBSSxDQUFDO1lBQ0gsT0FBTyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQzNCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsU0FBUyxLQUFLLGVBQWUsQ0FBQyxDQUFDLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLHVCQUF1QixFQUMvRSxTQUFTLENBRWEsQ0FBQztRQUMzQixDQUFDO1FBQUMsT0FBTyxRQUFRLEVBQUUsQ0FBQztZQUNsQixJQUNFLFFBQVEsWUFBWSxnQkFBZ0I7bUJBQ2pDLFFBQVEsQ0FBQyxJQUFJLEtBQUssaUJBQWlCLEVBQ3RDLENBQUM7Z0JBQ0QsSUFBSSxDQUFDO29CQUNILE1BQU0sSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNwQixDQUFDO2dCQUFDLE9BQU8sWUFBWSxFQUFFLENBQUM7b0JBQ3RCLE1BQU0sSUFBSSxjQUFjLENBQ3RCLENBQUMsUUFBUSxFQUFFLFlBQVksQ0FBQyxFQUN4QixzREFBc0QsQ0FDdkQsQ0FBQztnQkFDSixDQUFDO1lBQ0gsQ0FBQztZQUNELE1BQU0sUUFBUSxDQUFDO1FBQ2pCLENBQUM7SUFDSCxDQUFDO0lBRU0sS0FBSyxDQUFDLG1CQUFtQixDQUM5QixTQUFrQixFQUNsQixVQUFpQztRQUVqQyxJQUFJLFNBQVMsS0FBSyxnQkFBZ0IsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDekQsTUFBTSxJQUFJLGdCQUFnQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxLQUFLLGFBQWEsQ0FBQyxDQUFDLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3hHLENBQUM7UUFDRCxPQUFPLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsVUFBVSxFQUFFLFNBQVMsQ0FBMkIsQ0FBQztJQUM1RixDQUFDO0lBRU0sS0FBSyxDQUFDLElBQUk7UUFDZixJQUFJLElBQUksQ0FBQyxXQUFXO1lBQUUsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDO1FBQzlDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN2QyxJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztRQUMvQixJQUFJLENBQUM7WUFDSCxNQUFNLFdBQVcsQ0FBQztRQUNwQixDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUFJLElBQUksQ0FBQyxXQUFXLEtBQUssV0FBVztnQkFBRSxJQUFJLENBQUMsV0FBVyxHQUFHLFNBQVMsQ0FBQztRQUNyRSxDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxZQUFZLENBQ3hCLE9BQXlCLEVBQ3pCLFNBQXVCO1FBRXZCLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUNsRCxJQUFJLENBQUMscUJBQXFCLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDbkMsU0FBUyxFQUFFLGNBQWMsRUFBRSxDQUFDO1FBQzVCLE1BQU0sVUFBVSxHQUFHLHlCQUF5QixFQUFFLENBQUM7UUFDL0MsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1lBQ3ZFLEdBQUcsRUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUMzRCxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVEsS0FBSyxPQUFPO1lBQ3RDLEtBQUssRUFBRSxLQUFLO1lBQ1osV0FBVyxFQUFFLElBQUk7WUFDakIsR0FBRyxFQUFFLGlDQUFpQyxFQUFFO1lBQ3hDLEtBQUssRUFBRSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUM7U0FDbEQsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDbkIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzFDLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDZixNQUFNLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDekMsTUFBTSxJQUFJLEtBQUssQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO1FBQ2xFLENBQUM7UUFDRCxJQUFJLENBQUMsYUFBYSxHQUFHLGNBQWMsS0FBSyxDQUFDLEdBQUcsSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztRQUN2RyxJQUFJLE9BQU8sQ0FBQyxRQUFRLEtBQUssT0FBTztZQUFFLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDO1FBQ3ZFLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEMsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwQyxJQUFJLENBQUMsQ0FBQyxZQUFZLFlBQVksT0FBTyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUM7ZUFDakQsQ0FBQyxDQUFDLFlBQVksWUFBWSxPQUFPLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDeEQsTUFBTSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3pDLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQztRQUNwRSxDQUFDO1FBQ0QsTUFBTSxTQUFTLEdBQUcsSUFBSSxtQkFBbUIsQ0FBd0M7WUFDL0UsUUFBUSxFQUFFLFlBQVk7WUFDdEIsUUFBUSxFQUFFLFlBQVk7WUFDdEIsYUFBYSxFQUFFLHFCQUFxQjtZQUNwQyxnQkFBZ0IsRUFBRSxzQkFBc0I7U0FDekMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFDM0IsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQztRQUN6QyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsT0FBTyxFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUM7UUFDbEYsU0FBUyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUU7WUFDckIsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLFNBQVMsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUM7Z0JBQ3RFLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQy9CLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILFNBQVMsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFO1lBQ3JCLElBQ0UsSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTO21CQUN6QixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssS0FBSyxVQUFVO21CQUNoQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssS0FBSyxTQUFTO2dCQUNsQyxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUNqQyxDQUFDLENBQUMsQ0FBQztRQUVILE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxDQUFxQixDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNsRSxJQUFJLENBQUMsY0FBYyxHQUFHLE9BQU8sQ0FBQztZQUM5QixJQUFJLENBQUMsYUFBYSxHQUFHLE1BQU0sQ0FBQztRQUM5QixDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQztZQUNILE1BQU0sU0FBUyxDQUFDLElBQUksQ0FBQztnQkFDbkIsT0FBTyxFQUFFLHNCQUFzQjtnQkFDL0IsSUFBSSxFQUFFLE1BQU07Z0JBQ1osSUFBSSxFQUFFLE9BQU87YUFDZCxDQUFDLENBQUM7WUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFDN0UsSUFBSSxNQUFNLENBQUMsS0FBSyxLQUFLLFFBQVE7Z0JBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO1lBQy9GLElBQUksTUFBTSxDQUFDLEtBQUssS0FBSyxhQUFhLEVBQUUsQ0FBQztnQkFDbkMsTUFBTSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ2xCLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDO2dCQUM1QixPQUFPLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUMxQixDQUFDO1lBQ0QsSUFBSSxDQUFDLE1BQU0sR0FBRyxFQUFFLEdBQUcsTUFBTSxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDNUMsT0FBTyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDMUIsQ0FBQztRQUFDLE9BQU8sUUFBUSxFQUFFLENBQUM7WUFDbEIsTUFBTSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3pDLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQztZQUNoRCxNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixFQUFFLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDckUsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsSUFBSSxDQUFDLGNBQWMsR0FBRyxTQUFTLENBQUM7WUFDaEMsSUFBSSxDQUFDLGFBQWEsR0FBRyxTQUFTLENBQUM7UUFDakMsQ0FBQztJQUNILENBQUM7SUFFTyxLQUFLLENBQUMsY0FBYyxDQUMxQixVQUF1QyxFQUN2QyxZQUEwQyxFQUMxQyxTQUF1QjtRQUV2QixJQUFJLE9BQW1DLENBQUM7UUFDeEMsSUFBSSxhQUF1QyxDQUFDO1FBQzVDLElBQUksQ0FBQztZQUNILE1BQU0sUUFBUSxHQUF1QztnQkFDbkQsVUFBVTtnQkFDVixZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtvQkFDckIsTUFBTSxJQUFJLEtBQUssQ0FBQyx1Q0FBdUMsQ0FBQyxDQUFDO2dCQUMzRCxDQUFDLENBQUM7Z0JBQ0YsSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUU7b0JBQ3hCLE9BQU8sR0FBRyxVQUFVLENBQ2xCLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQywrQ0FBK0MsQ0FBQyxDQUFDLEVBQ3hFLHVCQUF1QixDQUN4QixDQUFDO2dCQUNKLENBQUMsQ0FBQzthQUNILENBQUM7WUFDRixJQUFJLFNBQVMsRUFBRSxDQUFDO2dCQUNkLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUU7b0JBQ3RDLElBQUksU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDO3dCQUN0QixNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO3dCQUN6QixPQUFPO29CQUNULENBQUM7b0JBQ0QsYUFBYSxHQUFHLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7b0JBQy9DLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsYUFBYSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7Z0JBQ3JFLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDTixDQUFDO1lBQ0QsT0FBTyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdEMsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsSUFBSSxPQUFPO2dCQUFFLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNuQyxJQUFJLGFBQWE7Z0JBQUUsU0FBUyxFQUFFLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUMsQ0FBQztRQUM1RSxDQUFDO0lBQ0gsQ0FBQztJQUVPLGtCQUFrQixDQUFDLFVBQTZCLEVBQUUsU0FBaUI7UUFDekUsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDO1lBQUUsT0FBTztRQUMzQyxJQUFJLFVBQVUsQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDakMsSUFBSSxDQUFDLE1BQU0sR0FBRztnQkFDWixHQUFHLFVBQVUsQ0FBQyxNQUFNO2dCQUNwQixHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQzthQUNwRCxDQUFDO1lBQ0YsSUFDRSxVQUFVLENBQUMsTUFBTSxDQUFDLEtBQUssS0FBSyxPQUFPO21CQUNoQyxVQUFVLENBQUMsTUFBTSxDQUFDLEtBQUssS0FBSyxhQUFhO21CQUN6QyxVQUFVLENBQUMsTUFBTSxDQUFDLEtBQUssS0FBSyxRQUFRO2dCQUN2QyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzNDLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxVQUFVLENBQUMsSUFBSSxLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQ2hDLEtBQUssTUFBTSxRQUFRLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDO2dCQUNoRCxJQUFJLENBQUM7b0JBQ0gsUUFBUSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDN0IsQ0FBQztnQkFBQyxNQUFNLENBQUM7b0JBQ1AseURBQXlEO2dCQUMzRCxDQUFDO1lBQ0gsQ0FBQztZQUNELE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxVQUFVLENBQUMsSUFBSSxLQUFLLGNBQWMsRUFBRSxDQUFDO1lBQ3ZDLElBQ0UsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQzttQkFDMUIsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDO21CQUNqRCxJQUFJLENBQUMscUJBQXFCLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUM7bUJBQ3BELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLElBQUksNkJBQTZCLEVBQzlELENBQUM7Z0JBQ0QsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7Z0JBQzdCLE9BQU87WUFDVCxDQUFDO1lBQ0QsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsRUFBRSxTQUFTLENBQUMsQ0FBQztZQUNoRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3JDLElBQUksc0JBQXNCLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7Z0JBQzlDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDOUMsQ0FBQztZQUNELEtBQUssU0FBUyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUU7Z0JBQzFCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ3hDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQy9DLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1lBQ2hDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUMxQixPQUFPO1FBQ1QsQ0FBQztRQUNELElBQUksVUFBVSxDQUFDLElBQUksS0FBSywyQkFBMkIsRUFBRSxDQUFDO1lBQ3BELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxrQ0FBa0MsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ2xGLElBQUksQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDN0MsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7Z0JBQzdCLE9BQU87WUFDVCxDQUFDO1lBQ0QsSUFBSSxDQUFDLGtDQUFrQyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDckUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUU7Z0JBQUUsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDekQsT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLFVBQVUsQ0FBQyxJQUFJLEtBQUssYUFBYSxFQUFFLENBQUM7WUFDdEMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDakUsSUFBSSxNQUFNLEVBQUUsQ0FBQztnQkFDWCxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztnQkFDOUMsT0FBTztZQUNULENBQUM7WUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztnQkFDMUQsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDL0IsQ0FBQztZQUNELE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxVQUFVLENBQUMsSUFBSSxLQUFLLHVCQUF1QixFQUFFLENBQUM7WUFDaEQsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDO1lBQzNELElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztnQkFDNUQsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7Z0JBQzdCLE9BQU87WUFDVCxDQUFDO1lBQ0QsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUNqQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ2YsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7Z0JBQzdCLE9BQU87WUFDVCxDQUFDO1lBQ0QsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQzNELElBQ0UsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksSUFBSSxrQ0FBa0M7bUJBQzlELElBQUksQ0FBQyxxQkFBcUIsR0FBRyxLQUFLLENBQUMsVUFBVSxHQUFHLHNDQUFzQyxFQUN6RixDQUFDO2dCQUNELElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO2dCQUM3QixPQUFPO1lBQ1QsQ0FBQztZQUNELElBQUksQ0FBQyxxQkFBcUIsSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDO1lBQy9DLElBQUksU0FBeUIsQ0FBQztZQUM5QixTQUFTLEdBQUcsT0FBTyxDQUFDLE9BQU8sRUFBRTtpQkFDMUIsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsQ0FBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO2lCQUN0RSxPQUFPLENBQUMsR0FBRyxFQUFFO2dCQUNaLElBQUksQ0FBQyxxQkFBcUIsSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDO2dCQUMvQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUN6QyxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztZQUNoQyxDQUFDLENBQUMsQ0FBQztZQUNMLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDdEMsS0FBSyxTQUFTLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRTtnQkFDeEIsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLFNBQVMsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7b0JBQ3BFLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO2dCQUMvQixDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUM7WUFDSCxPQUFPO1FBQ1QsQ0FBQztRQUNELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMvRCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztZQUM3QixPQUFPO1FBQ1QsQ0FBQztRQUNELElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3hELElBQUksT0FBTyxDQUFDLFNBQVM7WUFBRSxPQUFPO1FBQzlCLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDbkIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUM1RCxPQUFPO1FBQ1QsQ0FBQztRQUNELElBQ0UsT0FBTyxDQUFDLElBQUksS0FBSyxTQUFTO2VBQ3ZCLE9BQU8sQ0FBQyxNQUFNO2VBQ2QsQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFDM0QsQ0FBQztZQUNELE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsbURBQW1ELENBQUMsQ0FBQyxDQUFDO1lBQy9FLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQzdCLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFDRSxPQUFPLENBQUMsSUFBSSxLQUFLLFNBQVM7ZUFDdkIsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7bUJBQ3BDLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLFVBQVUsQ0FBQyxDQUFDO21CQUNsRCxVQUFVLENBQUMsTUFBTSxDQUFDLFFBQVEsS0FBSyxJQUFJLENBQUMsRUFDekMsQ0FBQztZQUNELE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsb0RBQW9ELENBQUMsQ0FBQyxDQUFDO1lBQ2hGLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQzdCLE9BQU87UUFDVCxDQUFDO1FBQ0QsT0FBTyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVNLEtBQUssQ0FBQyxnQkFBZ0IsQ0FDM0IsWUFBb0IsRUFDcEIsUUFBZ0IsRUFDaEIsU0FBaUI7UUFFakIsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDO1FBQ25HLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7UUFDakMsSUFBSSxDQUFDLFNBQVM7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLDBDQUEwQyxDQUFDLENBQUM7UUFDNUUsTUFBTSxTQUFTLENBQUMsSUFBSSxDQUFDO1lBQ25CLE9BQU8sRUFBRSxzQkFBc0I7WUFDL0IsSUFBSSxFQUFFLHVCQUF1QjtZQUM3QixTQUFTLEVBQUUsWUFBWTtZQUN2QixVQUFVLEVBQUUsUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7U0FDeEMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxZQUFvQixFQUFFLFNBQWlCO1FBQzdFLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQztZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsMkNBQTJDLENBQUMsQ0FBQztRQUNuRyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO1FBQ2pDLElBQUksQ0FBQyxTQUFTO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDO1FBQzVFLE1BQU0sU0FBUyxDQUFDLElBQUksQ0FBQztZQUNuQixPQUFPLEVBQUUsc0JBQXNCO1lBQy9CLElBQUksRUFBRSx3QkFBd0I7WUFDOUIsU0FBUyxFQUFFLFlBQVk7U0FDeEIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLEtBQUssQ0FBQyxpQkFBaUIsQ0FDN0IsVUFBc0MsRUFDdEMsU0FBaUI7UUFFakIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztRQUNqQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGlCQUFpQixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQ25GLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQzdCLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxVQUFVLENBQUMsTUFBTSxLQUFLLHFCQUFxQixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyw0QkFBNEIsRUFBRSxDQUFDO1lBQzlGLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQzdCLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxVQUFVLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUN6QyxJQUFJLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxTQUFTLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDOUQsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUN4QixHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLElBQUksZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUMsRUFDdkQsVUFBVSxDQUFDLFNBQVMsQ0FDckIsQ0FBQztRQUNGLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNoQixJQUFJLGVBQXdFLENBQUM7UUFDN0UsSUFBSSxhQUF3RCxDQUFDO1FBQzdELElBQUksZ0JBQTJDLENBQUM7UUFDaEQsSUFBSSxxQkFBcUIsR0FBRyxLQUFLLENBQUM7UUFDbEMsSUFBSSxrQkFBa0IsR0FBRyxLQUFLLENBQUM7UUFDL0IsSUFBSSxzQkFBa0QsQ0FBQztRQUN2RCxJQUFJLDRCQUFzRCxDQUFDO1FBQzNELElBQUksc0JBQWdELENBQUM7UUFDckQsSUFBSSxxQkFBZ0UsQ0FBQztRQUNyRSxJQUFJLHNCQUEwRSxDQUFDO1FBQy9FLElBQUksc0JBQWlELENBQUM7UUFDdEQsTUFBTSw0QkFBNEIsR0FBRyxHQUFrQixFQUFFO1lBQ3ZELElBQUksYUFBYSxLQUFLLGNBQWM7Z0JBQUUsT0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDL0QsSUFBSSxnQkFBZ0I7Z0JBQUUsT0FBTyxnQkFBZ0IsQ0FBQztZQUM5QyxNQUFNLE1BQU0sR0FBRyxlQUFlLENBQUM7WUFDL0IsSUFBSSxDQUFDLE1BQU07Z0JBQUUsT0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDdEMsYUFBYSxHQUFHLGNBQWMsQ0FBQztZQUMvQixJQUNFLHNCQUFzQjttQkFDbkIsSUFBSSxDQUFDLGtDQUFrQyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDO3dCQUM5RCxzQkFBc0IsRUFDNUIsQ0FBQztnQkFDRCxJQUFJLENBQUMsa0NBQWtDLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUN2RSxDQUFDO1lBQ0QsZ0JBQWdCLEdBQUcsQ0FBQyxLQUFLLElBQUksRUFBRTtnQkFDN0IsSUFBSSxDQUFDO29CQUNILE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyw0QkFBNEIsRUFBRSxDQUMvQyxVQUFVLENBQUMsTUFBTSxFQUNqQixVQUFVLENBQUMsT0FBcUQsRUFDaEUsTUFBTSxFQUNOLFNBQVMsQ0FDVixDQUFDO29CQUNGLGFBQWEsR0FBRyxhQUFhLENBQUM7b0JBQzlCLGVBQWUsR0FBRyxTQUFTLENBQUM7Z0JBQzlCLENBQUM7Z0JBQUMsT0FBTyxRQUFRLEVBQUUsQ0FBQztvQkFDbEIsa0JBQWtCLEdBQUcsSUFBSSxDQUFDO29CQUMxQixhQUFhLEdBQUcsYUFBYSxDQUFDO29CQUM5QixlQUFlLEdBQUcsU0FBUyxDQUFDO29CQUM1QixNQUFNLElBQUksdUJBQXVCLENBQy9CLG9EQUFvRCxFQUNwRCxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsQ0FDcEIsQ0FBQztnQkFDSixDQUFDO1lBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNMLE9BQU8sZ0JBQWdCLENBQUM7UUFDMUIsQ0FBQyxDQUFDO1FBQ0YsTUFBTSxzQ0FBc0MsR0FBRyxDQUFDLFFBQWlCLEVBQVEsRUFBRTtZQUN6RSxJQUFJLENBQUMscUJBQXFCLElBQUksYUFBYSxLQUFLLFVBQVU7Z0JBQUUsT0FBTztZQUNuRSxNQUFNLElBQUksR0FBRyw0QkFBNEIsRUFBRSxDQUFDO1lBQzVDLEtBQUssSUFBSSxDQUFDLElBQUksQ0FDWixHQUFHLEVBQUUsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUN2QyxDQUFDLGlCQUFpQixFQUFFLEVBQUUsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLGlCQUFpQixDQUFDLENBQ2xFLENBQUM7UUFDSixDQUFDLENBQUM7UUFDRixJQUFJLENBQUM7WUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQ2pELFVBQVUsQ0FBQyxNQUFNLEVBQ2pCLFVBQVUsQ0FBQyxPQUFxRCxFQUNoRSxTQUFTLEVBQ1QsVUFBVSxDQUFDLE1BQU0sQ0FDbEIsQ0FBQztZQUNGLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxFQUFFLENBQUM7Z0JBQ3pELE1BQU0sSUFBSSxLQUFLLENBQUMsb0RBQW9ELENBQUMsQ0FBQztZQUN4RSxDQUFDO1lBQ0QsZUFBZSxHQUFHLE1BQU0sQ0FBQztZQUN6QixhQUFhLEdBQUcsVUFBVSxDQUFDO1lBQzNCLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDOUIsTUFBTSw0QkFBNEIsRUFBRSxDQUFDO2dCQUNyQyxVQUFVLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3JDLENBQUM7WUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUNuRSxNQUFNLDRCQUE0QixFQUFFLENBQUM7Z0JBQ3JDLE9BQU87WUFDVCxDQUFDO1lBQ0QsSUFBSSxVQUFVLENBQUMsTUFBTSxLQUFLLHFCQUFxQixFQUFFLENBQUM7Z0JBQ2hELHNCQUFzQixHQUFHLElBQUksT0FBTyxDQUFPLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO29CQUM3RCxzQkFBc0IsR0FBRyxPQUFPLENBQUM7b0JBQ2pDLHFCQUFxQixHQUFHLE1BQU0sQ0FBQztnQkFDakMsQ0FBQyxDQUFDLENBQUM7Z0JBQ0gsS0FBSyxzQkFBc0IsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ25ELHNCQUFzQixHQUFHO29CQUN2QixNQUFNLEVBQUUsU0FBUztvQkFDakIsV0FBVyxFQUFFLEdBQUcsRUFBRTt3QkFDaEIsSUFBSSxhQUFhLEtBQUssVUFBVTs0QkFBRSxPQUFPLEtBQUssQ0FBQzt3QkFDL0MsYUFBYSxHQUFHLGNBQWMsQ0FBQzt3QkFDL0IsZUFBZSxHQUFHLFNBQVMsQ0FBQzt3QkFDNUIsc0JBQXNCLEVBQUUsRUFBRSxDQUFDO3dCQUMzQixPQUFPLElBQUksQ0FBQztvQkFDZCxDQUFDO2lCQUNGLENBQUM7Z0JBQ0YsSUFBSSxDQUFDLGtDQUFrQyxDQUFDLEdBQUcsQ0FDekMsVUFBVSxDQUFDLFNBQVMsRUFDcEIsc0JBQXNCLENBQ3ZCLENBQUM7Z0JBQ0YsNEJBQTRCLEdBQUcsR0FBRyxFQUFFO29CQUNsQyxzQ0FBc0MsQ0FDcEMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxNQUFNLElBQUksSUFBSSxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsQ0FDNUQsQ0FBQztnQkFDSixDQUFDLENBQUM7Z0JBQ0YsVUFBVSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztnQkFDMUYsSUFBSSxVQUFVLENBQUMsTUFBTSxDQUFDLE9BQU87b0JBQUUsNEJBQTRCLEVBQUUsQ0FBQztnQkFDOUQsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTLEVBQUUsQ0FBQztvQkFDbkUsTUFBTSw0QkFBNEIsRUFBRSxDQUFDO29CQUNyQyxPQUFPO2dCQUNULENBQUM7WUFDSCxDQUFDO1lBQ0QscUJBQXFCLEdBQUcsSUFBSSxDQUFDO1lBQzdCLElBQUksQ0FBQztnQkFDSCxNQUFNLFNBQVMsQ0FBQyxJQUFJLENBQUM7b0JBQ25CLE9BQU8sRUFBRSxzQkFBc0I7b0JBQy9CLElBQUksRUFBRSxlQUFlO29CQUNyQixTQUFTLEVBQUUsVUFBVSxDQUFDLFNBQVM7b0JBQy9CLEVBQUUsRUFBRSxJQUFJO29CQUNSLE1BQU07aUJBQ1AsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztZQUFDLE9BQU8sUUFBUSxFQUFFLENBQUM7Z0JBQ2xCLE1BQU0sNEJBQTRCLEVBQUUsQ0FBQztnQkFDckMsTUFBTSxRQUFRLENBQUM7WUFDakIsQ0FBQztZQUNELFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN0QixJQUFJLHNCQUFzQixFQUFFLENBQUM7Z0JBQzNCLElBQUksYUFBYSxLQUFLLFVBQVUsRUFBRSxDQUFDO29CQUNqQyxzQkFBc0IsR0FBRyxVQUFVLENBQUMsR0FBRyxFQUFFO3dCQUN2QyxzQ0FBc0MsQ0FBQyxJQUFJLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7b0JBQzFFLENBQUMsRUFBRSxJQUFJLENBQUMsMEJBQTBCLENBQUMsQ0FBQztvQkFDcEMsc0JBQXNCLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ2pDLENBQUM7Z0JBQ0QsTUFBTSxzQkFBc0IsQ0FBQztZQUMvQixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sYUFBYSxHQUFHLGNBQWMsQ0FBQztnQkFDL0IsZUFBZSxHQUFHLFNBQVMsQ0FBQztZQUM5QixDQUFDO1lBQ0QsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBQUMsT0FBTyxXQUFXLEVBQUUsQ0FBQztZQUNyQixJQUFJLFFBQVEsR0FBRyxXQUFXLENBQUM7WUFDM0IsSUFBSSxlQUFlLEVBQUUsQ0FBQztnQkFDcEIsSUFBSSxDQUFDO29CQUNILE1BQU0sNEJBQTRCLEVBQUUsQ0FBQztnQkFDdkMsQ0FBQztnQkFBQyxPQUFPLGlCQUFpQixFQUFFLENBQUM7b0JBQzNCLFFBQVEsR0FBRyxpQkFBaUIsQ0FBQztnQkFDL0IsQ0FBQztZQUNILENBQUM7WUFDRCxJQUFJLHFCQUFxQixFQUFFLENBQUM7Z0JBQzFCLElBQUksYUFBYSxLQUFLLGNBQWMsRUFBRSxDQUFDO29CQUNyQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUN4RCxDQUFDO3FCQUFNLENBQUM7b0JBQ04sSUFBSSxDQUFDLHlCQUF5QixDQUM1QixRQUFRLFlBQVksS0FBSzt3QkFDdkIsQ0FBQyxDQUFDLFFBQVE7d0JBQ1YsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLG9DQUFvQyxDQUFDLEVBQ25ELFNBQVMsRUFDVCxLQUFLLENBQ04sQ0FBQztnQkFDSixDQUFDO2dCQUNELE9BQU87WUFDVCxDQUFDO1lBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTO2dCQUFFLE9BQU87WUFDM0UsTUFBTSxrQkFBa0IsR0FBRyxRQUFRLFlBQVksdUJBQXVCO2dCQUNwRSxDQUFDLENBQUMsUUFBUTtnQkFDVixDQUFDLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxPQUFPO29CQUN6QixDQUFDLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxNQUFNO29CQUMxQixDQUFDLENBQUMsUUFBUSxDQUFDO1lBQ2YsTUFBTSxJQUFJLEdBQUcsa0JBQWtCLFlBQVksZ0JBQWdCO2dCQUN6RCxDQUFDLENBQUMsa0JBQWtCLENBQUMsSUFBSTtnQkFDekIsQ0FBQyxDQUFDLGtCQUFrQixZQUFZLHVCQUF1QjtvQkFDckQsQ0FBQyxDQUFDLGlCQUFpQjtvQkFDbkIsQ0FBQyxDQUFDLGtCQUFrQixZQUFZLHlCQUF5QjsyQkFDcEQsa0JBQWtCLFlBQVksOEJBQThCO3dCQUMvRCxDQUFDLENBQUMsVUFBVTt3QkFDWixDQUFDLENBQUMsVUFBVSxDQUFDO1lBQ25CLE1BQU0sU0FBUyxDQUFDLElBQUksQ0FBQztnQkFDbkIsT0FBTyxFQUFFLHNCQUFzQjtnQkFDL0IsSUFBSSxFQUFFLGVBQWU7Z0JBQ3JCLFNBQVMsRUFBRSxVQUFVLENBQUMsU0FBUztnQkFDL0IsRUFBRSxFQUFFLEtBQUs7Z0JBQ1QsS0FBSyxFQUFFO29CQUNMLElBQUksRUFBRSxrQkFBa0I7b0JBQ3hCLElBQUk7b0JBQ0osT0FBTyxFQUFFLElBQUksS0FBSyxpQkFBaUI7d0JBQ2pDLENBQUMsQ0FBQyx3Q0FBd0M7d0JBQzFDLENBQUMsQ0FBQyxJQUFJLEtBQUssVUFBVTs0QkFDbkIsQ0FBQyxDQUFDLHlEQUF5RDs0QkFDM0QsQ0FBQyxDQUFDLGtCQUFrQixZQUFZLGdCQUFnQjtnQ0FDOUMsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLE9BQU87Z0NBQzVCLENBQUMsQ0FBQyw0QkFBNEI7aUJBQ3JDO2FBQ0YsQ0FBQyxDQUFDLElBQUksQ0FDTCxHQUFHLEVBQUU7Z0JBQ0gsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDdEQsSUFBSSxrQkFBa0I7b0JBQUUsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDdkQsQ0FBQyxFQUNELEdBQUcsRUFBRTtnQkFDSCxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTLEVBQUUsQ0FBQztvQkFDbEUsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7Z0JBQy9CLENBQUM7WUFDSCxDQUFDLENBQ0YsQ0FBQztRQUNKLENBQUM7Z0JBQVMsQ0FBQztZQUNULFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN0QixJQUFJLHNCQUFzQjtnQkFBRSxZQUFZLENBQUMsc0JBQXNCLENBQUMsQ0FBQztZQUNqRSxJQUFJLDRCQUE0QixFQUFFLENBQUM7Z0JBQ2pDLFVBQVUsQ0FBQyxNQUFNLENBQUMsbUJBQW1CLENBQUMsT0FBTyxFQUFFLDRCQUE0QixDQUFDLENBQUM7WUFDL0UsQ0FBQztZQUNELElBQ0Usc0JBQXNCO21CQUNuQixJQUFJLENBQUMsa0NBQWtDLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUM7d0JBQzlELHNCQUFzQixFQUM1QixDQUFDO2dCQUNELElBQUksQ0FBQyxrQ0FBa0MsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ3ZFLENBQUM7WUFDRCxJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxLQUFLLFVBQVUsRUFBRSxDQUFDO2dCQUNyRSxJQUFJLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUN2RCxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFTyxXQUFXLENBQ2pCLFNBQTZCLEVBQzdCLFVBQW1CLEVBQ25CLFlBQWdDLEVBQ2hDLFNBQXVCO1FBRXZCLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsWUFBWSxFQUFFLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQy9ELE9BQU8sRUFBRSxzQkFBc0I7WUFDL0IsSUFBSSxFQUFFLFNBQVM7WUFDZixTQUFTO1lBQ1QsTUFBTSxFQUFFLFNBQVM7WUFDakIsT0FBTyxFQUFFLFVBQVU7U0FDcEIsQ0FBQyxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRU8sV0FBVyxDQUFDLFlBQW9CO1FBQ3RDLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsWUFBWSxFQUFFLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQy9ELE9BQU8sRUFBRSxzQkFBc0I7WUFDL0IsSUFBSSxFQUFFLFNBQVM7WUFDZixTQUFTO1NBQ1YsQ0FBQyxDQUFDLENBQUM7SUFDTixDQUFDO0lBRU8sV0FBVyxDQUNqQixPQUFvQyxFQUNwQyxZQUFnQyxFQUNoQyxnQkFBOEQsRUFDOUQsU0FBOEIsRUFDOUIsU0FBdUI7UUFFdkIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztRQUNqQyxJQUFJLENBQUMsU0FBUztZQUFFLE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDLENBQUM7UUFDN0YsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksSUFBSSw2QkFBNkIsRUFBRSxDQUFDO1lBQy9ELE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLGdCQUFnQixDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQztRQUNoRSxDQUFDO1FBQ0QsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUN6QixNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDdkUsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxJQUFJLFNBQVMsRUFBRSxPQUFPLEVBQUUsQ0FBQztnQkFDdkIsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLElBQUksSUFBSSxZQUFZLENBQUMsNEJBQTRCLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQztnQkFDekYsT0FBTztZQUNULENBQUM7WUFDRCxNQUFNLE9BQU8sR0FBRyxZQUFZLEtBQUssU0FBUztnQkFDeEMsQ0FBQyxDQUFDLFNBQVM7Z0JBQ1gsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7b0JBQ2QsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7b0JBQ3BELElBQUksQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLFNBQVM7d0JBQUUsT0FBTztvQkFDMUMsSUFBSSxDQUFDLG9CQUFvQixDQUN2QixTQUFTLEVBQ1QsT0FBTyxFQUNQLElBQUksZ0JBQWdCLENBQ2xCLE9BQU8sQ0FBQyxVQUFVLElBQUksbUJBQW1CLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQzt3QkFDdkQsQ0FBQyxDQUFDLGlCQUFpQjt3QkFDbkIsQ0FBQyxDQUFDLFNBQVMsQ0FDZCxFQUNELFNBQVMsRUFDVCxLQUFLLENBQ04sQ0FBQztnQkFDSixDQUFDLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFDckIsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUFDO1lBQ2pCLE1BQU0sT0FBTyxHQUF3QjtnQkFDbkMsSUFBSSxFQUFFLE9BQU87Z0JBQ2IsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDM0MsT0FBTztnQkFDUCxNQUFNO2dCQUNOLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDL0IsR0FBRyxDQUFDLFNBQVMsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLENBQUM7YUFDMUQsQ0FBQztZQUNGLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUM3QyxJQUFJLFNBQVMsRUFBRSxDQUFDO2dCQUNkLE1BQU0sYUFBYSxHQUFHLEdBQVMsRUFBRTtvQkFDL0IsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsS0FBSyxPQUFPO3dCQUFFLE9BQU87b0JBQzVELElBQUksQ0FBQyxvQkFBb0IsQ0FDdkIsU0FBUyxFQUNULE9BQU8sRUFDUCxPQUFPLENBQUMsVUFBVSxJQUFJLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7d0JBQ3ZELENBQUMsQ0FBQyxJQUFJLGdCQUFnQixDQUFDLGlCQUFpQixDQUFDO3dCQUN6QyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sSUFBSSxJQUFJLFlBQVksQ0FBQyw0QkFBNEIsRUFBRSxZQUFZLENBQUMsRUFDcEYsU0FBUyxFQUNULEtBQUssQ0FDTixDQUFDO2dCQUNKLENBQUMsQ0FBQztnQkFDRixPQUFPLENBQUMsYUFBYSxHQUFHLGFBQWEsQ0FBQztnQkFDdEMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxhQUFhLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztnQkFDbkUsSUFBSSxTQUFTLENBQUMsT0FBTztvQkFBRSxhQUFhLEVBQUUsQ0FBQztZQUN6QyxDQUFDO1lBQ0QsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsS0FBSyxPQUFPLElBQUksT0FBTyxDQUFDLFNBQVM7Z0JBQUUsT0FBTztZQUNqRixPQUFPLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztZQUMxQixLQUFLLFNBQVMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFO2dCQUMxRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDcEQsSUFBSSxDQUFDLE9BQU87b0JBQUUsT0FBTztnQkFDckIsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztnQkFDN0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQztvQkFDdkIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3pFLENBQUM7Z0JBQ0QsSUFBSSxDQUFDLHlCQUF5QixDQUM1QixJQUFJLEtBQUssQ0FBQywyQ0FBMkMsQ0FBQyxFQUN0RCxTQUFTLEVBQ1QsS0FBSyxDQUNOLENBQUM7WUFDSixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLG9CQUFvQixDQUMxQixZQUFvQixFQUNwQixVQUErQixFQUMvQixZQUFxQixFQUNyQixZQUF3RSxFQUN4RSxRQUE0QztRQUU1QyxJQUFJLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxLQUFLLFVBQVUsSUFBSSxVQUFVLENBQUMsU0FBUztZQUFFLE9BQU87UUFDMUYsSUFBSSxVQUFVLENBQUMsT0FBTztZQUFFLFlBQVksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDekQsSUFBSSxVQUFVLENBQUMsTUFBTSxJQUFJLFVBQVUsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNsRCxVQUFVLENBQUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDekUsVUFBVSxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUM7WUFDOUIsVUFBVSxDQUFDLGFBQWEsR0FBRyxTQUFTLENBQUM7UUFDdkMsQ0FBQztRQUNELFVBQVUsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1FBQzVCLFVBQVUsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDaEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUMzQixJQUFJLENBQUMsbUJBQW1CLENBQUMsWUFBWSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBQ25ELE9BQU87UUFDVCxDQUFDO1FBQ0QsVUFBVSxDQUFDLHdCQUF3QixHQUFHLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDcEQsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsS0FBSyxVQUFVO2dCQUFFLE9BQU87WUFDbEUsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFlBQVksRUFBRSxVQUFVLENBQUMsQ0FBQztZQUNuRCxJQUFJLENBQUMseUJBQXlCLENBQzVCLElBQUksS0FBSyxDQUFDLG9EQUFvRCxDQUFDLEVBQy9ELFlBQVksRUFDWixRQUFRLENBQ1QsQ0FBQztRQUNKLENBQUMsRUFBRSxJQUFJLENBQUMsMEJBQTBCLENBQUMsQ0FBQztRQUNwQyxVQUFVLENBQUMsd0JBQXdCLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDNUMsS0FBSyxZQUFZLENBQUMsSUFBSSxDQUFDO1lBQ3JCLE9BQU8sRUFBRSxzQkFBc0I7WUFDL0IsSUFBSSxFQUFFLGdCQUFnQjtZQUN0QixTQUFTLEVBQUUsWUFBWTtTQUN4QixDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRTtZQUNaLElBQUksSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEtBQUssVUFBVTtnQkFBRSxPQUFPO1lBQ2xFLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDbkQsSUFBSSxDQUFDLHlCQUF5QixDQUM1QixJQUFJLEtBQUssQ0FBQyxrREFBa0QsQ0FBQyxFQUM3RCxZQUFZLEVBQ1osUUFBUSxDQUNULENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxtQkFBbUIsQ0FBQyxZQUFvQixFQUFFLFVBQStCO1FBQy9FLElBQUksSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDMUQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDNUMsQ0FBQztRQUNELElBQUksVUFBVSxDQUFDLE9BQU87WUFBRSxZQUFZLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3pELElBQUksVUFBVSxDQUFDLHdCQUF3QixFQUFFLENBQUM7WUFDeEMsWUFBWSxDQUFDLFVBQVUsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1lBQ2xELFVBQVUsQ0FBQyx3QkFBd0IsR0FBRyxTQUFTLENBQUM7UUFDbEQsQ0FBQztRQUNELElBQUksVUFBVSxDQUFDLE1BQU0sSUFBSSxVQUFVLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDbEQsVUFBVSxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ3pFLFVBQVUsQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDO1lBQzlCLFVBQVUsQ0FBQyxhQUFhLEdBQUcsU0FBUyxDQUFDO1FBQ3ZDLENBQUM7SUFDSCxDQUFDO0lBRU8sS0FBSyxDQUFDLFdBQVc7UUFDdkIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUN6QixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO1FBQ2pDLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksS0FBSyxDQUFDLHlCQUF5QixDQUFDLENBQUMsQ0FBQztZQUN6RCxNQUFNLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBQ2pDLE1BQU0sSUFBSSxDQUFDLHdCQUF3QixFQUFFLENBQUM7WUFDdEMsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7WUFDOUIsSUFBSSxDQUFDLE1BQU0sR0FBRyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDO1lBQ2pELE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDLE1BQU0sR0FBRyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ2xFLElBQUksQ0FBQyw4QkFBOEIsRUFBRSxDQUFDO1FBQ3RDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyx1QkFBdUIsQ0FBQztRQUN0RCxJQUFJLElBQUksQ0FBQyxTQUFTLElBQUksS0FBSyxDQUFDLFFBQVEsS0FBSyxJQUFJLElBQUksS0FBSyxDQUFDLFVBQVUsS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUMzRSxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDdkUsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQ3JELE1BQU0sV0FBVyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUMxQyxDQUFDO1FBRUQsSUFBSSxLQUFLLENBQUMsUUFBUSxLQUFLLElBQUksSUFBSSxLQUFLLENBQUMsVUFBVSxLQUFLLElBQUksRUFBRSxDQUFDO1lBQ3pELE1BQU0sSUFBSSxDQUFDLG1CQUFtQixDQUFDLEtBQUssRUFBRSxTQUFTLENBQUMsQ0FBQztRQUNuRCxDQUFDO1FBQ0QsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQztRQUN2QyxJQUFJLFVBQVU7WUFBRSxNQUFNLFVBQVUsQ0FBQztRQUNqQyxNQUFNLElBQUksQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO1FBQ3RDLE1BQU0sU0FBUyxHQUFHLE1BQU0sV0FBVyxDQUFDLFNBQVMsRUFBRSx1QkFBdUIsQ0FBQyxDQUFDO1FBQ3hFLElBQUksQ0FBQyxTQUFTLElBQUksS0FBSyxDQUFDLFFBQVEsS0FBSyxJQUFJLElBQUksS0FBSyxDQUFDLFVBQVUsS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUN2RSxJQUFJLENBQUMsTUFBTSxHQUFHLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUM7WUFDaEQsTUFBTSxJQUFJLEtBQUssQ0FBQyx3Q0FBd0MsQ0FBQyxDQUFDO1FBQzVELENBQUM7UUFDRCxNQUFNLElBQUksQ0FBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3JELElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBQzNCLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQyxDQUFDO1FBQ3pELE1BQU0sSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDakMsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7UUFDOUIsSUFBSSxJQUFJLENBQUMsS0FBSyxLQUFLLEtBQUs7WUFBRSxJQUFJLENBQUMsS0FBSyxHQUFHLFNBQVMsQ0FBQztRQUNqRCxJQUFJLElBQUksQ0FBQyxTQUFTLEtBQUssU0FBUztZQUFFLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBQzdELElBQUksQ0FBQyxhQUFhLEdBQUcsRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQztJQUNuRCxDQUFDO0lBRU8sS0FBSyxDQUFDLG1CQUFtQixDQUMvQixRQUEyQyxFQUMzQyxZQUEwQztRQUUxQyxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUM7UUFDaEQsSUFBSSxjQUFjLEtBQUssU0FBUyxJQUFJLE9BQU8sQ0FBQyxRQUFRLEtBQUssT0FBTyxFQUFFLENBQUM7WUFDakUsSUFBSSxtQkFBbUIsQ0FBQyxjQUFjLENBQUM7Z0JBQUUsa0JBQWtCLENBQUMsY0FBYyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ3ZGLElBQUksTUFBTSxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLG1CQUFtQixDQUFDLGNBQWMsQ0FBQyxFQUFFLHVCQUF1QixDQUFDLENBQUM7WUFDL0YsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUNaLGtCQUFrQixDQUFDLGNBQWMsRUFBRSxTQUFTLENBQUMsQ0FBQztnQkFDOUMsTUFBTSxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLG1CQUFtQixDQUFDLGNBQWMsQ0FBQyxFQUFFLHVCQUF1QixDQUFDLENBQUM7WUFDN0YsQ0FBQztZQUNELElBQUksQ0FBQyxNQUFNO2dCQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQztZQUMvRSxJQUFJLENBQUMsbUJBQW1CLEdBQUcsU0FBUyxDQUFDO1FBQ3ZDLENBQUM7YUFBTSxDQUFDO1lBQ04sUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUN6QixJQUFJLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxZQUFZLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztZQUN0RSxJQUFJLENBQUMsTUFBTSxJQUFJLFFBQVEsQ0FBQyxRQUFRLEtBQUssSUFBSSxJQUFJLFFBQVEsQ0FBQyxVQUFVLEtBQUssSUFBSSxFQUFFLENBQUM7Z0JBQzFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ3pCLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxZQUFZLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztZQUNwRSxDQUFDO1lBQ0QsSUFBSSxDQUFDLE1BQU0sSUFBSSxRQUFRLENBQUMsUUFBUSxLQUFLLElBQUksSUFBSSxRQUFRLENBQUMsVUFBVSxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUMxRSxNQUFNLElBQUksS0FBSyxDQUFDLHdDQUF3QyxDQUFDLENBQUM7WUFDNUQsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRU8sWUFBWSxDQUFDLFFBQTJDO1FBQzlELFFBQVEsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7UUFDakcsUUFBUSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQztRQUNqRyxPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDN0IsSUFBSSxPQUFPLEdBQUcsS0FBSyxDQUFDO1lBQ3BCLE1BQU0sTUFBTSxHQUFHLENBQUMsVUFBK0IsRUFBUSxFQUFFO2dCQUN2RCxJQUFJLE9BQU87b0JBQUUsT0FBTztnQkFDcEIsT0FBTyxHQUFHLElBQUksQ0FBQztnQkFDZixJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztnQkFDaEQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7Z0JBQ2hELElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUM7Z0JBQy9GLElBQUksQ0FBQyxhQUFhLEdBQUcsRUFBRSxDQUFDO2dCQUN4QixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUMsSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQyxDQUFDO2dCQUN6RSxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksS0FBSyxDQUFDLHdCQUF3QixDQUFDLENBQUMsQ0FBQztnQkFDeEQsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDO2dCQUNoRCxNQUFNLFFBQVEsR0FBd0I7b0JBQ3BDLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTtvQkFDckIsU0FBUyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7b0JBQ3JCLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUM7b0JBQ25FLEdBQUcsQ0FBQyxVQUFVLENBQUMsTUFBTSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUM7b0JBQ3pFLEdBQUcsQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLE9BQU87d0JBQzNCLENBQUMsQ0FBQyxFQUFFLFlBQVksRUFBRSxtQkFBbUIsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFO3dCQUNqRSxDQUFDLENBQUMsRUFBRSxDQUFDO2lCQUNSLENBQUM7Z0JBQ0YsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7Z0JBQ3pCLElBQUksQ0FBQztvQkFDSCxJQUFJLENBQUMsT0FBTyxDQUFDLG1CQUFtQixFQUFFLENBQUMsRUFBRSxHQUFHLFFBQVEsRUFBRSxDQUFDLENBQUM7Z0JBQ3RELENBQUM7Z0JBQUMsTUFBTSxDQUFDO29CQUNQLHFFQUFxRTtnQkFDdkUsQ0FBQztnQkFDRCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsUUFBUSxDQUFDO2dCQUNqQyxJQUFJLENBQUMsdUJBQXVCLEdBQUcsSUFBSSxDQUFDO2dCQUNwQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztnQkFDM0IsSUFBSSxjQUFjLEtBQUssU0FBUyxJQUFJLE9BQU8sQ0FBQyxRQUFRLEtBQUssT0FBTyxFQUFFLENBQUM7b0JBQ2pFLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxjQUFjLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFO3dCQUM1RCxJQUFJLElBQUksQ0FBQyxtQkFBbUIsS0FBSyxjQUFjLEVBQUUsQ0FBQzs0QkFDaEQsSUFBSSxDQUFDLG1CQUFtQixHQUFHLFNBQVMsQ0FBQzt3QkFDdkMsQ0FBQztvQkFDSCxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFO3dCQUNkLElBQUksSUFBSSxDQUFDLGNBQWMsS0FBSyxJQUFJOzRCQUFFLElBQUksQ0FBQyxjQUFjLEdBQUcsU0FBUyxDQUFDO3dCQUNsRSxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztvQkFDaEMsQ0FBQyxDQUFDLENBQUM7b0JBQ0gsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUM7b0JBQzNCLEtBQUssSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDbkMsQ0FBQztxQkFBTSxDQUFDO29CQUNOLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO2dCQUNoQyxDQUFDO2dCQUNELE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUN0QixDQUFDLENBQUM7WUFDRixRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNoRixRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFO2dCQUMvQixJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUc7b0JBQUUsTUFBTSxDQUFDLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1lBQ3RELENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sS0FBSyxDQUFDLGlCQUFpQixDQUFDLGlCQUF5QjtRQUN2RCxJQUFJLENBQUMsbUJBQW1CLENBQUMsaUJBQWlCLENBQUM7WUFBRSxPQUFPO1FBQ3BELGtCQUFrQixDQUFDLGlCQUFpQixFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ2pELElBQUksTUFBTSxHQUFHLE1BQU0sT0FBTyxDQUN4QixHQUFHLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxpQkFBaUIsQ0FBQyxFQUM1Qyx1QkFBdUIsQ0FDeEIsQ0FBQztRQUNGLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNaLGtCQUFrQixDQUFDLGlCQUFpQixFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ2pELE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FDcEIsR0FBRyxFQUFFLENBQUMsbUJBQW1CLENBQUMsaUJBQWlCLENBQUMsRUFDNUMsdUJBQXVCLENBQ3hCLENBQUM7UUFDSixDQUFDO1FBQ0QsSUFBSSxDQUFDLE1BQU07WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLHNEQUFzRCxDQUFDLENBQUM7SUFDdkYsQ0FBQztJQUVPLEtBQUssQ0FBQyx3QkFBd0I7UUFDcEMsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDO1FBQ2hELElBQUksY0FBYyxLQUFLLFNBQVMsSUFBSSxPQUFPLENBQUMsUUFBUSxLQUFLLE9BQU87WUFBRSxPQUFPO1FBQ3pFLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQzdDLElBQUksSUFBSSxDQUFDLG1CQUFtQixLQUFLLGNBQWM7WUFBRSxJQUFJLENBQUMsbUJBQW1CLEdBQUcsU0FBUyxDQUFDO0lBQ3hGLENBQUM7SUFFTyxzQkFBc0I7UUFDNUIsSUFBSSxDQUFDLElBQUksQ0FBQyx1QkFBdUI7WUFBRSxPQUFPO1FBQzFDLElBQUksSUFBSSxDQUFDLGNBQWM7WUFBRSxPQUFPO1FBQ2hDLElBQUksSUFBSSxDQUFDLGtCQUFrQjtZQUFFLE9BQU87UUFDcEMsSUFDRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxHQUFHLENBQUM7ZUFDM0IsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksR0FBRyxDQUFDO2VBQy9CLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLEdBQUcsQ0FBQztZQUNuQyxPQUFPO1FBQ1QsSUFBSSxDQUFDLHVCQUF1QixHQUFHLEtBQUssQ0FBQztRQUNyQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7UUFDdkMsSUFBSSxDQUFDLGdCQUFnQixHQUFHLFNBQVMsQ0FBQztRQUNsQyxJQUFJLENBQUMsUUFBUTtZQUFFLE9BQU87UUFDdEIsSUFBSSxDQUFDO1lBQ0gsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxFQUFFLEdBQUcsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUM5QyxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsaUVBQWlFO1FBQ25FLENBQUM7SUFDSCxDQUFDO0lBRU8scUJBQXFCO1FBQzNCLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxLQUFLLENBQUMsaUNBQWlDLENBQUMsQ0FBQyxDQUFDO1FBQ2pFLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDLENBQUM7UUFDbkUsS0FBSyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFTyxhQUFhLENBQUMsUUFBZTtRQUNuQyxLQUFLLE1BQU0sQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3hELElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDN0MsT0FBTyxDQUFDLE1BQU0sQ0FDWixPQUFPLENBQUMsVUFBVSxJQUFJLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7Z0JBQ3ZELENBQUMsQ0FBQyxJQUFJLGdCQUFnQixDQUFDLGlCQUFpQixDQUFDO2dCQUN6QyxDQUFDLENBQUMsUUFBUSxDQUNiLENBQUM7UUFDSixDQUFDO1FBQ0QsS0FBSyxNQUFNLFVBQVUsSUFBSSxJQUFJLENBQUMsa0JBQWtCLENBQUMsTUFBTSxFQUFFO1lBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN0RixJQUFJLENBQUMscUJBQXFCLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDckMsQ0FBQztJQUVPLDhCQUE4QjtRQUNwQyxLQUFLLE1BQU0sT0FBTyxJQUFJLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztZQUNwRCxJQUFJLENBQUMsT0FBTyxDQUFDLHdCQUF3QjtnQkFBRSxTQUFTO1lBQ2hELFlBQVksQ0FBQyxPQUFPLENBQUMsd0JBQXdCLENBQUMsQ0FBQztZQUMvQyxPQUFPLENBQUMsd0JBQXdCLEdBQUcsU0FBUyxDQUFDO1FBQy9DLENBQUM7SUFDSCxDQUFDO0lBRU8seUJBQXlCLENBQy9CLFFBQWUsRUFDZixZQUF3RSxFQUN4RSxRQUE0QztRQUU1QyxJQUNFLENBQUMsUUFBUTtlQUNOLElBQUksQ0FBQyxLQUFLLEtBQUssUUFBUTtlQUN2QixJQUFJLENBQUMsU0FBUyxLQUFLLFlBQVk7ZUFDL0IsUUFBUSxDQUFDLFFBQVEsS0FBSyxJQUFJO2VBQzFCLFFBQVEsQ0FBQyxVQUFVLEtBQUssSUFBSTtZQUMvQixPQUFPO1FBQ1QsSUFBSSxDQUFDLE1BQU0sR0FBRyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDO1FBQ2hELElBQUksQ0FBQyxhQUFhLEdBQUcsRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBQzNCLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzdCLEtBQUssWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNqRCxLQUFLLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVPLG1CQUFtQjtRQUN6QixJQUFJLElBQUksQ0FBQyxrQkFBa0I7WUFBRSxPQUFPO1FBQ3BDLElBQUksSUFBb0IsQ0FBQztRQUN6QixJQUFJLEdBQUcsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUU7WUFDekMsSUFBSSxJQUFJLENBQUMsa0JBQWtCLEtBQUssSUFBSTtnQkFBRSxJQUFJLENBQUMsa0JBQWtCLEdBQUcsU0FBUyxDQUFDO1lBQzFFLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1FBQ2hDLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQztRQUMvQixLQUFLLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVPLEtBQUssQ0FBQyxtQkFBbUI7UUFDL0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUMvRCxNQUFNLElBQUksQ0FBQztJQUNiLENBQUM7SUFFTyxLQUFLLENBQUMsZUFBZTtRQUMzQixJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEtBQUssQ0FBQyxJQUFJLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEtBQUssQ0FBQztZQUFFLE9BQU87UUFDbEYsTUFBTSxPQUFPLEdBQUcsTUFBTSxXQUFXLENBQy9CLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLEVBQ3pFLElBQUksQ0FBQyx1QkFBdUIsQ0FDN0IsQ0FBQztRQUNGLElBQ0UsQ0FBQyxPQUFPO2VBQ0wsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksR0FBRyxDQUFDO2VBQzlCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEdBQUcsQ0FBQztlQUMvQixJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxHQUFHLENBQUMsRUFDbkMsQ0FBQztZQUNELElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQztZQUNoRCxNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7UUFDM0UsQ0FBQztJQUNILENBQUM7SUFFTywwQkFBMEIsQ0FBQyxZQUFvQjtRQUNyRCxJQUFJLENBQUMscUJBQXFCLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ2hELElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDN0MsT0FBTyxJQUFJLENBQUMscUJBQXFCLENBQUMsSUFBSSxHQUFHLDZCQUE2QixHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzNFLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUM7WUFDaEUsSUFBSSxNQUFNLEtBQUssU0FBUztnQkFBRSxNQUFNO1lBQ2hDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDNUMsQ0FBQztJQUNILENBQUM7SUFFTyxpQkFBaUIsQ0FDdkIsV0FBK0IsRUFDL0IsVUFBa0IsRUFDbEIsT0FBZTtRQUVmLE1BQU0sUUFBUSxHQUFHLFdBQVcsSUFBSSxVQUFVLENBQUM7UUFDM0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLElBQUksUUFBUSxHQUFHLENBQUMsSUFBSSxRQUFRLEdBQUcsVUFBVSxFQUFFLENBQUM7WUFDN0UsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLE9BQU8seUNBQXlDLFVBQVUsR0FBRyxDQUFDLENBQUM7UUFDcEYsQ0FBQztRQUNELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFTyxVQUFVLENBQ2hCLFNBQTRDLEVBQzVDLFFBQWlCLEVBQ2pCLGNBQStCO1FBRS9CLE1BQU0sS0FBSyxHQUFHLE9BQU8sUUFBUSxLQUFLLFFBQVE7WUFDeEMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQztZQUMvQixDQUFDLENBQUMsUUFBUSxZQUFZLFVBQVU7Z0JBQzlCLENBQUMsQ0FBQyxRQUFRO2dCQUNWLENBQUMsQ0FBQyxTQUFTLENBQUM7UUFDaEIsSUFBSSxDQUFDLEtBQUs7WUFBRSxPQUFPO1FBQ25CLElBQUksSUFBSSxHQUFHLGNBQWMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ2xFLE9BQU8sSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN2QixJQUFJLGNBQWMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDNUIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDbkMsSUFBSSxPQUFPLEdBQUcsQ0FBQztvQkFBRSxPQUFPO2dCQUN4QixjQUFjLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztnQkFDaEMsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUMvQixTQUFTO1lBQ1gsQ0FBQztZQUNELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbkMsSUFBSSxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQ2pCLE1BQU0sUUFBUSxHQUFHLEdBQUcsY0FBYyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQzFGLGNBQWMsQ0FBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUM1QixJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztnQkFDakMsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUMvQixTQUFTO1lBQ1gsQ0FBQztZQUNELE1BQU0sUUFBUSxHQUFHLEdBQUcsY0FBYyxDQUFDLE9BQU8sR0FBRyxJQUFJLEVBQUUsQ0FBQztZQUNwRCxJQUFJLE1BQU0sQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxHQUFHLHNCQUFzQixFQUFFLENBQUM7Z0JBQ2pFLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDO2dCQUNqQyxjQUFjLENBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztnQkFDNUIsY0FBYyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7WUFDakMsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLGNBQWMsQ0FBQyxPQUFPLEdBQUcsUUFBUSxDQUFDO1lBQ3BDLENBQUM7WUFDRCxPQUFPO1FBQ1QsQ0FBQztJQUNILENBQUM7SUFFTyxRQUFRLENBQ2QsU0FBNEMsRUFDNUMsY0FBK0I7UUFFL0IsTUFBTSxLQUFLLEdBQUcsY0FBYyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUM5QyxJQUFJLEtBQUs7WUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsRUFBRSxLQUFLLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDN0QsSUFBSSxjQUFjLENBQUMsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3ZELElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNqRCxDQUFDO1FBQ0QsY0FBYyxDQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDNUIsY0FBYyxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDbEMsQ0FBQztJQUVPLE1BQU0sQ0FBQyxTQUE0QyxFQUFFLE9BQWU7UUFDMUUsTUFBTSxPQUFPLEdBQUcsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQ2IsU0FBUyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7WUFDckIsTUFBTSxFQUFFLFNBQVM7WUFDakIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO1lBQ2xCLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztTQUM3QixDQUFDLENBQUM7UUFDSCxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLG9CQUFvQixFQUFFLENBQUM7WUFDNUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLG9CQUFvQixDQUFDLENBQUM7UUFDL0QsQ0FBQztJQUNILENBQUM7Q0FDRiJ9
|