@jsprismarine/prismarine
Version:
Dedicated Minecraft Bedrock Edition server written in TypeScript
319 lines (316 loc) • 37.6 kB
JavaScript
import { CommandDispatcher, CommandSyntaxException } from '@jsprismarine/brigadier';
import { CommandRegisterClassMalformedOrMissingError, GenericNamespaceInvalidError, CommandUnknownCommandError, Error } from '@jsprismarine/errors';
import 'node:fs';
import 'confbox';
import '@jsprismarine/jsbinaryutils';
import 'node:assert';
import 'node:path';
import 'node:process';
import '../block/BlockToolType.es.js';
import '@jsprismarine/bedrock-data';
import Timer from '../utils/Timer.es.js';
import '@jsprismarine/nbt';
import 'zlib';
import '@jsprismarine/math';
import '@jsprismarine/minecraft';
import '../network/packet/AddActorPacket.es.js';
import '../network/packet/MoveActorAbsolutePacket.es.js';
import '../network/packet/RemoveActorPacket.es.js';
import 'node:crypto';
import '../network/packet/ActorFallPacket.es.js';
import '../network/packet/AddItemActorPacket.es.js';
import '../network/packet/AddPlayerPacket.es.js';
import '../network/packet/AnimatePacket.es.js';
import '../network/packet/AvailableActorIdentifiersPacket.es.js';
import '../network/packet/AvailableCommandsPacket.es.js';
import '../network/CompressionProvider.es.js';
import '../network/packet/NetworkSettingsPacket.es.js';
import '../network/packet/BiomeDefinitionListPacket.es.js';
import '../network/packet/ChangeDimensionPacket.es.js';
import '../network/packet/ChunkRadiusUpdatedPacket.es.js';
import '../network/packet/CommandRequestPacket.es.js';
import '../network/packet/ContainerClosePacket.es.js';
import '../network/packet/ContainerOpenPacket.es.js';
import '../network/packet/CreativeContentPacket.es.js';
import '../network/packet/DisconnectPacket.es.js';
import '../network/packet/EmoteListPacket.es.js';
import '../network/packet/InteractPacket.es.js';
import '../network/packet/InventoryContentPacket.es.js';
import '../network/packet/InventoryTransactionPacket.es.js';
import '../network/packet/ItemComponentPacket.es.js';
import '../network/packet/ItemStackRequestPacket.es.js';
import '../network/packet/ItemStackResponsePacket.es.js';
import '../network/packet/LevelChunkPacket.es.js';
import '../network/packet/LevelSoundEventPacket.es.js';
import '../network/packet/LoginPacket.es.js';
import '../network/packet/MobEquipmentPacket.es.js';
import '../network/packet/MovePlayerPacket.es.js';
import '../network/packet/NetworkChunkPublisherUpdatePacket.es.js';
import '../network/packet/OnScreenTextureAnimationPacket.es.js';
import '../network/packet/PacketViolationWarningPacket.es.js';
import '../network/packet/PlaySoundPacket.es.js';
import '../network/packet/PlayStatusPacket.es.js';
import '../network/packet/PlayerActionPacket.es.js';
import '../network/packet/PlayerListPacket.es.js';
import '../network/packet/PlayerSkinPacket.es.js';
import '../network/packet/RequestChunkRadiusPacket.es.js';
import '../network/packet/RequestNetworkSettingsPacket.es.js';
import '../network/packet/ResourcePackResponsePacket.es.js';
import '../network/packet/ResourcePackStackPacket.es.js';
import '../network/packet/ResourcePacksInfoPacket.es.js';
import '../network/packet/ServerSettingsRequestPacket.es.js';
import '../network/packet/SetActorDataPacket.es.js';
import '../network/packet/SetDefaultGametypePacket.es.js';
import '../network/packet/SetHealthPacket.es.js';
import '../network/packet/SetLocalPlayerAsInitializedPacket.es.js';
import '../network/packet/SetPlayerGametypePacket.es.js';
import '../network/packet/SetTimePacket.es.js';
import '../network/packet/ShowProfilePacket.es.js';
import '../network/packet/StartGamePacket.es.js';
import '../network/packet/TextPacket.es.js';
import '../network/packet/TickSyncPacket.es.js';
import '../network/packet/TransferPacket.es.js';
import '../network/packet/UpdateAdventureSettingsPacket.es.js';
import '../network/packet/UpdateAttributesPacket.es.js';
import '../network/packet/UpdateBlockPacket.es.js';
import '../network/packet/WorldEventPacket.es.js';
import * as command_Commands from './Commands.es.js';
import '../config/Config.es.js';
import CommandRegisterEvent from '../events/command/CommandRegisterEvent.es.js';
import '../network/handler/AnimateHandler.es.js';
import '../network/handler/CommandRequestHandler.es.js';
import '../network/handler/ContainerCloseHandler.es.js';
import '../network/handler/EmoteListHandler.es.js';
import '../network/handler/InteractHandler.es.js';
import '../network/handler/InventoryTransactionHandler.es.js';
import '../network/handler/LevelSoundEventHandler.es.js';
import '../network/handler/LoginHandler.es.js';
import '../network/handler/MobEquipmentHandler.es.js';
import '../network/handler/MovePlayerHandler.es.js';
import '../network/handler/PacketViolationWarningHandler.es.js';
import '../network/handler/PlayerActionHandler.es.js';
import '../network/handler/RequestChunkRadiusHandler.es.js';
import '../network/handler/RequestNetworkSettingsHandler.es.js';
import '../network/handler/ResourcePackResponseHandler.es.js';
import '../network/handler/ServerSettingsRequestHandler.es.js';
import '../network/handler/SetDefaultGametypeHandler.es.js';
import '../network/handler/SetLocalPlayerAsInitializedHandler.es.js';
import '../network/handler/SetPlayerGametypeHandler.es.js';
import '../network/handler/TextHandler.es.js';
import '../network/handler/TickSyncHandler.es.js';
import 'node:readline';
import { Chat } from '../chat/Chat.es.js';
import 'heap';
import '../network/packet/UpdateAbilitiesPacket.es.js';
import '@jsprismarine/raknet';
import 'evt';
import 'assert';
class CommandManager {
commands = /* @__PURE__ */ new Map();
server;
dispatcher;
constructor(server) {
this.server = server;
this.dispatcher = new CommandDispatcher();
}
/**
* On enable hook.
* @group Lifecycle
*/
async enable() {
const timer = new Timer();
const commands = Object.keys(command_Commands).map((key) => command_Commands[key]);
await Promise.all(
commands.map(async (Command) => {
const command = new Command({});
const event = new CommandRegisterEvent(command);
await this.server.emit("commandRegister", event);
if (event.isCancelled()) return;
try {
await this.registerCommand(command);
} catch (error) {
this.server.getLogger().error(error);
this.server.getLogger().warn(`Failed to register command ${command.id}`);
}
})
);
this.server.getLogger().verbose(`Registered §b${this.commands.size}§r commands(s) (took §e${timer.stop()} ms§r)!`);
}
/**
* On disable hook.
* @group Lifecycle
*/
async disable() {
this.commands.clear();
}
/**
* Register a command into command manager by class.
* @param {Command} [command] - The command class to register
*/
async registerCommand(command) {
if (!command || !command.id) throw new CommandRegisterClassMalformedOrMissingError();
if (command.id.split(":").length !== 2) throw new GenericNamespaceInvalidError();
if (!command.register)
this.server.getLogger().warn(`Command is missing "register" member. This is unsupported!`);
else await command.register(this.dispatcher);
this.commands.set(command.id, command);
await Promise.all(
this.server.getSessionManager().getAllPlayers().map(async (player) => player.getNetworkSession().sendAvailableCommands())
);
this.server.getLogger().debug(`Command with id §b${command.id}§r registered`);
}
/**
* Get a registered command by ID.
* @remarks This is case-insensitive, works with or without namespace, and also with aliases.
* @param {string} id - The command ID.
* @returns {Command} The command if found, otherwise undefined.
*/
getCommand(id) {
const command = Array.from(this.commands.values()).find(
(command2) => (
// Check if it matches ID without namespace.
command2.name === id || // Check if it's an alias.
command2.aliases?.includes(id) || // Last check if it's the whole ID (this is uncommon so,
// it's last to avoid the most checks).
command2.id === id
)
);
if (!command) throw new CommandUnknownCommandError();
return command;
}
/**
* Get all enabled commands.
*/
getCommands() {
return this.commands;
}
/**
* Get a list of all command variants.
*
* @remarks
* This is EXCLUDING legacy commands.
*/
getCommandsList() {
const parseNode = (node) => {
if (node.getChildrenCount() <= 0) {
return [
{
item: node.getType(),
children: []
}
];
}
const res2 = Array.from(node.getChildren()).map((node2) => parseNode(node2)).reverse();
return [
node.getCommand() ? {
item: node.getType(),
children: []
} : void 0,
...res2.map((children) => ({
item: node.getType(),
children: [...children]
}))
].filter((a) => a);
};
const traverse = (node, path = [], result = []) => {
if (!node.children.length) result.push(path.concat(node.item));
for (const child of node.children) traverse(child, path.concat(node.item), result);
return result;
};
const res = Array.from(this.server.getCommandManager().getDispatcher().getRoot().getChildren()).flatMap((command) => {
const branches = [];
if (command.getCommand()) branches.push([]);
Array.from(command.getChildren()).forEach((node) => {
const parsed = parseNode(node);
parsed.forEach((branch) => {
branches.push(traverse(branch));
});
});
return branches.map((branch) => [command.getName(), command, branch]);
}).filter((a) => a);
res.toString = () => {
return `${this.getCommandsList().map((item) => {
if (!item[2].length) return `/${item[0]}`;
return item[2].map(
(entries) => `/${item[0]} ${entries.flat(Number.POSITIVE_INFINITY).map((argument) => argument.getReadableType?.() ?? argument.constructor.name).join(" ")}`
).join(`
`);
}).join("\n")}`;
};
return res;
}
/**
* Get dispatcher
*/
getDispatcher() {
return this.dispatcher;
}
/**
* Dispatches a command and executes them.
*
* @param sender - the player/console who executed the command
* @param target - the Player/entity/console who should execute the command
* @param input - the command input including arguments
*/
async dispatchCommand(sender, target, input = "") {
try {
if (input.startsWith("/")) input = input.slice(1);
const parsed = this.dispatcher.parse(input.trim(), target);
const id = parsed.getReader().getString().split(" ")[0];
if (!sender.isConsole()) {
this.server.getLogger().debug(
`Entity with §b${sender.getRuntimeId()}§r is dispatching command: ${input} (id: ${id})`,
"CommandManager/dispatchCommand"
);
}
const command = this.getCommand(id);
if (!this.server.getPermissionManager().can(sender).execute(command.permission)) {
await sender.sendMessage(
"§cI'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error."
);
return;
}
let res = [];
if (command.name !== id) {
await this.dispatchCommand(sender, target, input.replace(id, command.name));
return;
}
res = await Promise.all(this.dispatcher.execute(parsed));
const feedback = sender.getWorld().getGameruleManager().getGamerule("sendCommandFeedback");
if (!feedback) return;
await Promise.all(
res.map(async (res2) => {
const chat = new Chat({
sender: this.server.getConsole(),
message: `§o§7[${target.getName()}: ${res2 ?? `issued server command: /${input}`}]§r`,
channel: "*.ops"
});
await this.server.getChatManager().send(chat);
})
);
} catch (error) {
switch (true) {
case error instanceof CommandSyntaxException:
await sender.sendMessage(`§c${error.getMessage()}`);
return;
case error instanceof CommandUnknownCommandError:
await sender.sendMessage(`§cUnknown command. Type "/help" for help.`);
return;
case error instanceof Error:
await sender.sendMessage(`§c${error.message}`);
return;
default:
this.server.getLogger().error(error);
break;
}
await sender.sendMessage(`§c${error}`);
this.server.getLogger().debug(
`Player ${target.getFormattedUsername()} tried to execute ${input}, but it failed with the error: ${error}`,
"CommandManager/dispatchCommand"
);
this.server.getLogger().error(error);
}
}
}
export { CommandManager };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tbWFuZE1hbmFnZXIuZXMuanMiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21tYW5kL0NvbW1hbmRNYW5hZ2VyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgQXJndW1lbnRDb21tYW5kTm9kZSB9IGZyb20gJ0Bqc3ByaXNtYXJpbmUvYnJpZ2FkaWVyJztcbmltcG9ydCB7IENvbW1hbmREaXNwYXRjaGVyLCBDb21tYW5kU3ludGF4RXhjZXB0aW9uIH0gZnJvbSAnQGpzcHJpc21hcmluZS9icmlnYWRpZXInO1xuaW1wb3J0IHtcbiAgICBDb21tYW5kUmVnaXN0ZXJDbGFzc01hbGZvcm1lZE9yTWlzc2luZ0Vycm9yLFxuICAgIENvbW1hbmRVbmtub3duQ29tbWFuZEVycm9yLFxuICAgIEVycm9yLFxuICAgIEdlbmVyaWNOYW1lc3BhY2VJbnZhbGlkRXJyb3Jcbn0gZnJvbSAnQGpzcHJpc21hcmluZS9lcnJvcnMnO1xuXG5pbXBvcnQgdHlwZSB7IENvbW1hbmQsIENvbW1hbmRBcmd1bWVudCwgRW50aXR5LCBQbGF5ZXIsIFNlcnZlciwgU2VydmljZSB9IGZyb20gJy4uLyc7XG5pbXBvcnQgeyBDaGF0IH0gZnJvbSAnLi4vJztcbmltcG9ydCBDb21tYW5kUmVnaXN0ZXJFdmVudCBmcm9tICcuLi9ldmVudHMvY29tbWFuZC9Db21tYW5kUmVnaXN0ZXJFdmVudCc7XG5pbXBvcnQgVGltZXIgZnJvbSAnLi4vdXRpbHMvVGltZXInO1xuaW1wb3J0IHsgQ29tbWFuZHMgfSBmcm9tICcuLyc7XG5cbmV4cG9ydCBjbGFzcyBDb21tYW5kTWFuYWdlciBpbXBsZW1lbnRzIFNlcnZpY2Uge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgY29tbWFuZHM6IE1hcDxzdHJpbmcsIENvbW1hbmQ+ID0gbmV3IE1hcCgpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgc2VydmVyOiBTZXJ2ZXI7XG4gICAgcHJpdmF0ZSBkaXNwYXRjaGVyITogQ29tbWFuZERpc3BhdGNoZXI8UGxheWVyPjtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcihzZXJ2ZXI6IFNlcnZlcikge1xuICAgICAgICB0aGlzLnNlcnZlciA9IHNlcnZlcjtcbiAgICAgICAgdGhpcy5kaXNwYXRjaGVyID0gbmV3IENvbW1hbmREaXNwYXRjaGVyKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT24gZW5hYmxlIGhvb2suXG4gICAgICogQGdyb3VwIExpZmVjeWNsZVxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBlbmFibGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHRpbWVyID0gbmV3IFRpbWVyKCk7XG5cbiAgICAgICAgY29uc3QgY29tbWFuZHMgPSBPYmplY3Qua2V5cyhDb21tYW5kcykubWFwKChrZXkpID0+IChDb21tYW5kcyBhcyBhbnkpW2tleV0gYXMgdHlwZW9mIENvbW1hbmQpO1xuXG4gICAgICAgIC8vIFJlZ2lzdGVyIGpzcHJpc21hcmluZSBjb21tYW5kc1xuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgIGNvbW1hbmRzLm1hcChhc3luYyAoQ29tbWFuZCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbW1hbmQ6IENvbW1hbmQgPSBuZXcgQ29tbWFuZCh7fSBhcyBhbnkpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgZXZlbnQgPSBuZXcgQ29tbWFuZFJlZ2lzdGVyRXZlbnQoY29tbWFuZCk7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zZXJ2ZXIuZW1pdCgnY29tbWFuZFJlZ2lzdGVyJywgZXZlbnQpO1xuICAgICAgICAgICAgICAgIGlmIChldmVudC5pc0NhbmNlbGxlZCgpKSByZXR1cm47XG5cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyQ29tbWFuZChjb21tYW5kKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlcnZlci5nZXRMb2dnZXIoKS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VydmVyLmdldExvZ2dlcigpLndhcm4oYEZhaWxlZCB0byByZWdpc3RlciBjb21tYW5kICR7Y29tbWFuZC5pZH1gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuc2VydmVyXG4gICAgICAgICAgICAuZ2V0TG9nZ2VyKClcbiAgICAgICAgICAgIC52ZXJib3NlKGBSZWdpc3RlcmVkIMKnYiR7dGhpcy5jb21tYW5kcy5zaXplfcKnciBjb21tYW5kcyhzKSAodG9vayDCp2Uke3RpbWVyLnN0b3AoKX0gbXPCp3IpIWApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE9uIGRpc2FibGUgaG9vay5cbiAgICAgKiBAZ3JvdXAgTGlmZWN5Y2xlXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGRpc2FibGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRoaXMuY29tbWFuZHMuY2xlYXIoKTtcbiAgICAgICAgLy8gVE9ETzogY2xlYXIgY29tbWFuZHMgaW4gZGlzcGF0Y2hlclxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVyIGEgY29tbWFuZCBpbnRvIGNvbW1hbmQgbWFuYWdlciBieSBjbGFzcy5cbiAgICAgKiBAcGFyYW0ge0NvbW1hbmR9IFtjb21tYW5kXSAtIFRoZSBjb21tYW5kIGNsYXNzIHRvIHJlZ2lzdGVyXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIHJlZ2lzdGVyQ29tbWFuZChjb21tYW5kPzogQ29tbWFuZCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAoIWNvbW1hbmQgfHwgIWNvbW1hbmQuaWQpIHRocm93IG5ldyBDb21tYW5kUmVnaXN0ZXJDbGFzc01hbGZvcm1lZE9yTWlzc2luZ0Vycm9yKCk7XG4gICAgICAgIGlmIChjb21tYW5kLmlkLnNwbGl0KCc6JykubGVuZ3RoICE9PSAyKSB0aHJvdyBuZXcgR2VuZXJpY05hbWVzcGFjZUludmFsaWRFcnJvcigpO1xuXG4gICAgICAgIGlmICghKGNvbW1hbmQgYXMgYW55KS5yZWdpc3RlcilcbiAgICAgICAgICAgIHRoaXMuc2VydmVyLmdldExvZ2dlcigpLndhcm4oYENvbW1hbmQgaXMgbWlzc2luZyBcInJlZ2lzdGVyXCIgbWVtYmVyLiBUaGlzIGlzIHVuc3VwcG9ydGVkIWApO1xuICAgICAgICBlbHNlIGF3YWl0IGNvbW1hbmQucmVnaXN0ZXIodGhpcy5kaXNwYXRjaGVyKTtcbiAgICAgICAgdGhpcy5jb21tYW5kcy5zZXQoY29tbWFuZC5pZCwgY29tbWFuZCk7XG5cbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICB0aGlzLnNlcnZlclxuICAgICAgICAgICAgICAgIC5nZXRTZXNzaW9uTWFuYWdlcigpXG4gICAgICAgICAgICAgICAgLmdldEFsbFBsYXllcnMoKVxuICAgICAgICAgICAgICAgIC5tYXAoYXN5bmMgKHBsYXllcikgPT4gcGxheWVyLmdldE5ldHdvcmtTZXNzaW9uKCkuc2VuZEF2YWlsYWJsZUNvbW1hbmRzKCkpXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5zZXJ2ZXIuZ2V0TG9nZ2VyKCkuZGVidWcoYENvbW1hbmQgd2l0aCBpZCDCp2Ike2NvbW1hbmQuaWR9wqdyIHJlZ2lzdGVyZWRgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSByZWdpc3RlcmVkIGNvbW1hbmQgYnkgSUQuXG4gICAgICogQHJlbWFya3MgVGhpcyBpcyBjYXNlLWluc2Vuc2l0aXZlLCB3b3JrcyB3aXRoIG9yIHdpdGhvdXQgbmFtZXNwYWNlLCBhbmQgYWxzbyB3aXRoIGFsaWFzZXMuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGNvbW1hbmQgSUQuXG4gICAgICogQHJldHVybnMge0NvbW1hbmR9IFRoZSBjb21tYW5kIGlmIGZvdW5kLCBvdGhlcndpc2UgdW5kZWZpbmVkLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRDb21tYW5kKGlkOiBzdHJpbmcpOiBDb21tYW5kIHtcbiAgICAgICAgY29uc3QgY29tbWFuZCA9IEFycmF5LmZyb20odGhpcy5jb21tYW5kcy52YWx1ZXMoKSkuZmluZChcbiAgICAgICAgICAgIChjb21tYW5kKSA9PlxuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIGl0IG1hdGNoZXMgSUQgd2l0aG91dCBuYW1lc3BhY2UuXG4gICAgICAgICAgICAgICAgY29tbWFuZC5uYW1lID09PSBpZCB8fFxuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIGl0J3MgYW4gYWxpYXMuXG4gICAgICAgICAgICAgICAgY29tbWFuZC5hbGlhc2VzPy5pbmNsdWRlcyhpZCkgfHxcbiAgICAgICAgICAgICAgICAvLyBMYXN0IGNoZWNrIGlmIGl0J3MgdGhlIHdob2xlIElEICh0aGlzIGlzIHVuY29tbW9uIHNvLFxuICAgICAgICAgICAgICAgIC8vICBpdCdzIGxhc3QgdG8gYXZvaWQgdGhlIG1vc3QgY2hlY2tzKS5cbiAgICAgICAgICAgICAgICBjb21tYW5kLmlkID09PSBpZFxuICAgICAgICApO1xuXG4gICAgICAgIGlmICghY29tbWFuZCkgdGhyb3cgbmV3IENvbW1hbmRVbmtub3duQ29tbWFuZEVycm9yKCk7XG4gICAgICAgIHJldHVybiBjb21tYW5kO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgZW5hYmxlZCBjb21tYW5kcy5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0Q29tbWFuZHMoKTogTWFwPHN0cmluZywgQ29tbWFuZD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5jb21tYW5kcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBsaXN0IG9mIGFsbCBjb21tYW5kIHZhcmlhbnRzLlxuICAgICAqXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBUaGlzIGlzIEVYQ0xVRElORyBsZWdhY3kgY29tbWFuZHMuXG4gICAgICovXG4gICAgcHVibGljIGdldENvbW1hbmRzTGlzdCgpOiBBcnJheTxbc3RyaW5nLCAvKiBDb21tYW5kTm9kZTxQbGF5ZXI+ICovIGFueSwgQ29tbWFuZEFyZ3VtZW50W11bXV0+IHtcbiAgICAgICAgY29uc3QgcGFyc2VOb2RlID0gKG5vZGU6IC8qIENvbW1hbmROb2RlPFBsYXllcj4gKi8gYW55KTogYW55W10gPT4ge1xuICAgICAgICAgICAgaWYgKG5vZGUuZ2V0Q2hpbGRyZW5Db3VudCgpIDw9IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpdGVtOiAobm9kZSBhcyBBcmd1bWVudENvbW1hbmROb2RlPGFueSwgYW55PikuZ2V0VHlwZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IFtdXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCByZXMgPSBBcnJheS5mcm9tKG5vZGUuZ2V0Q2hpbGRyZW4oKSlcbiAgICAgICAgICAgICAgICAubWFwKChub2RlKSA9PiBwYXJzZU5vZGUobm9kZSkpXG4gICAgICAgICAgICAgICAgLnJldmVyc2UoKTtcblxuICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICBub2RlLmdldENvbW1hbmQoKVxuICAgICAgICAgICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbTogKG5vZGUgYXMgQXJndW1lbnRDb21tYW5kTm9kZTxhbnksIGFueT4pLmdldFR5cGUoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IFtdXG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAuLi5yZXMubWFwKChjaGlsZHJlbjogYW55KSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICBpdGVtOiAobm9kZSBhcyBBcmd1bWVudENvbW1hbmROb2RlPGFueSwgYW55PikuZ2V0VHlwZSgpLFxuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogWy4uLmNoaWxkcmVuXVxuICAgICAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgXS5maWx0ZXIoKGEpID0+IGEpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHRyYXZlcnNlID0gKG5vZGU6IGFueSwgcGF0aDogYW55W10gPSBbXSwgcmVzdWx0OiBhbnlbXSA9IFtdKSA9PiB7XG4gICAgICAgICAgICBpZiAoIW5vZGUuY2hpbGRyZW4ubGVuZ3RoKSByZXN1bHQucHVzaChwYXRoLmNvbmNhdChub2RlLml0ZW0pKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgY2hpbGQgb2Ygbm9kZS5jaGlsZHJlbikgdHJhdmVyc2UoY2hpbGQsIHBhdGguY29uY2F0KG5vZGUuaXRlbSksIHJlc3VsdCk7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHJlcyA9IEFycmF5LmZyb20odGhpcy5zZXJ2ZXIuZ2V0Q29tbWFuZE1hbmFnZXIoKS5nZXREaXNwYXRjaGVyKCkuZ2V0Um9vdCgpLmdldENoaWxkcmVuKCkpXG4gICAgICAgICAgICAuZmxhdE1hcCgoY29tbWFuZCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGJyYW5jaGVzOiBhbnlbXSA9IFtdO1xuICAgICAgICAgICAgICAgIGlmIChjb21tYW5kLmdldENvbW1hbmQoKSkgYnJhbmNoZXMucHVzaChbXSk7XG5cbiAgICAgICAgICAgICAgICBBcnJheS5mcm9tKGNvbW1hbmQuZ2V0Q2hpbGRyZW4oKSkuZm9yRWFjaCgobm9kZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZU5vZGUobm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIHBhcnNlZC5mb3JFYWNoKChicmFuY2gpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyYW5jaGVzLnB1c2godHJhdmVyc2UoYnJhbmNoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGJyYW5jaGVzLm1hcCgoYnJhbmNoKSA9PiBbY29tbWFuZC5nZXROYW1lKCksIGNvbW1hbmQsIGJyYW5jaF0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5maWx0ZXIoKGEpID0+IGEgYXMgYW55KTtcblxuICAgICAgICByZXMudG9TdHJpbmcgPSAoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gYCR7dGhpcy5nZXRDb21tYW5kc0xpc3QoKVxuICAgICAgICAgICAgICAgIC5tYXAoKGl0ZW0pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpdGVtWzJdLmxlbmd0aCkgcmV0dXJuIGAvJHtpdGVtWzBdfWA7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpdGVtWzJdXG4gICAgICAgICAgICAgICAgICAgICAgICAubWFwKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChlbnRyaWVzKSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgLyR7aXRlbVswXX0gJHtlbnRyaWVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZmxhdChOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAubWFwKChhcmd1bWVudDogYW55KSA9PiBhcmd1bWVudC5nZXRSZWFkYWJsZVR5cGU/LigpID8/IGFyZ3VtZW50LmNvbnN0cnVjdG9yLm5hbWUpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuam9pbignICcpfWBcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgIC5qb2luKGBcXG5gKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5qb2luKCdcXG4nKX1gO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gcmVzIGFzIGFueTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgZGlzcGF0Y2hlclxuICAgICAqL1xuICAgIHB1YmxpYyBnZXREaXNwYXRjaGVyKCk6IENvbW1hbmREaXNwYXRjaGVyPFBsYXllcj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5kaXNwYXRjaGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERpc3BhdGNoZXMgYSBjb21tYW5kIGFuZCBleGVjdXRlcyB0aGVtLlxuICAgICAqXG4gICAgICogQHBhcmFtIHNlbmRlciAtIHRoZSBwbGF5ZXIvY29uc29sZSB3aG8gZXhlY3V0ZWQgdGhlIGNvbW1hbmRcbiAgICAgKiBAcGFyYW0gdGFyZ2V0IC0gdGhlIFBsYXllci9lbnRpdHkvY29uc29sZSB3aG8gc2hvdWxkIGV4ZWN1dGUgdGhlIGNvbW1hbmRcbiAgICAgKiBAcGFyYW0gaW5wdXQgLSB0aGUgY29tbWFuZCBpbnB1dCBpbmNsdWRpbmcgYXJndW1lbnRzXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGRpc3BhdGNoQ29tbWFuZChzZW5kZXI6IFBsYXllciwgdGFyZ2V0OiBFbnRpdHkgfCBQbGF5ZXIsIGlucHV0ID0gJycpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChpbnB1dC5zdGFydHNXaXRoKCcvJykpIGlucHV0ID0gaW5wdXQuc2xpY2UoMSk7XG5cbiAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IHRoaXMuZGlzcGF0Y2hlci5wYXJzZShpbnB1dC50cmltKCksIHRhcmdldCBhcyBQbGF5ZXIpO1xuICAgICAgICAgICAgY29uc3QgaWQgPSBwYXJzZWQuZ2V0UmVhZGVyKCkuZ2V0U3RyaW5nKCkuc3BsaXQoJyAnKVswXSE7XG5cbiAgICAgICAgICAgIGlmICghc2VuZGVyLmlzQ29uc29sZSgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXJ2ZXJcbiAgICAgICAgICAgICAgICAgICAgLmdldExvZ2dlcigpXG4gICAgICAgICAgICAgICAgICAgIC5kZWJ1ZyhcbiAgICAgICAgICAgICAgICAgICAgICAgIGBFbnRpdHkgd2l0aCDCp2Ike3NlbmRlci5nZXRSdW50aW1lSWQoKX3Cp3IgaXMgZGlzcGF0Y2hpbmcgY29tbWFuZDogJHtpbnB1dH0gKGlkOiAke2lkfSlgLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ0NvbW1hbmRNYW5hZ2VyL2Rpc3BhdGNoQ29tbWFuZCdcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gR2V0IGNvbW1hbmQgZnJvbSBwYXJzZWQgc3RyaW5nLlxuICAgICAgICAgICAgY29uc3QgY29tbWFuZCA9IHRoaXMuZ2V0Q29tbWFuZChpZCk7XG5cbiAgICAgICAgICAgIC8vIFZhbGlkYXRlIHBlcm1pc3Npb25zLlxuICAgICAgICAgICAgaWYgKCF0aGlzLnNlcnZlci5nZXRQZXJtaXNzaW9uTWFuYWdlcigpLmNhbihzZW5kZXIpLmV4ZWN1dGUoY29tbWFuZC5wZXJtaXNzaW9uKSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHNlbmRlci5zZW5kTWVzc2FnZShcbiAgICAgICAgICAgICAgICAgICAgXCLCp2NJJ20gc29ycnksIGJ1dCB5b3UgZG8gbm90IGhhdmUgcGVybWlzc2lvbiB0byBwZXJmb3JtIHRoaXMgY29tbWFuZC4gXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJ1BsZWFzZSBjb250YWN0IHRoZSBzZXJ2ZXIgYWRtaW5pc3RyYXRvcnMgaWYgeW91IGJlbGlldmUgdGhhdCB0aGlzIGlzIGluIGVycm9yLidcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IHJlczogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgICAgIC8vIEhhbmRsZSBhbGlhc2VzIGFuZCBJRHMuXG4gICAgICAgICAgICBpZiAoY29tbWFuZC5uYW1lICE9PSBpZCkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZGlzcGF0Y2hDb21tYW5kKHNlbmRlciwgdGFyZ2V0LCBpbnB1dC5yZXBsYWNlKGlkLCBjb21tYW5kLm5hbWUpKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJlcyA9IGF3YWl0IFByb21pc2UuYWxsKHRoaXMuZGlzcGF0Y2hlci5leGVjdXRlKHBhcnNlZCkpO1xuXG4gICAgICAgICAgICBjb25zdCBmZWVkYmFjayA9IChzZW5kZXIgYXMgYW55IGFzIEVudGl0eSlcbiAgICAgICAgICAgICAgICAuZ2V0V29ybGQoKVxuICAgICAgICAgICAgICAgIC5nZXRHYW1lcnVsZU1hbmFnZXIoKVxuICAgICAgICAgICAgICAgIC5nZXRHYW1lcnVsZSgnc2VuZENvbW1hbmRGZWVkYmFjaycpO1xuXG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgd2UgZG9uJ3Qgc2VuZCBmZWVkYmFjayBpZiBzZW5kQ29tbWFuZEZlZWRiYWNrIGlzIHNldCB0byBmYWxzZVxuICAgICAgICAgICAgaWYgKCFmZWVkYmFjaykgcmV0dXJuO1xuXG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgICAgICByZXMubWFwKGFzeW5jIChyZXM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGF0ID0gbmV3IENoYXQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VuZGVyOiB0aGlzLnNlcnZlci5nZXRDb25zb2xlKCkhLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogYMKnb8KnN1ske3RhcmdldC5nZXROYW1lKCl9OiAke3JlcyA/PyBgaXNzdWVkIHNlcnZlciBjb21tYW5kOiAvJHtpbnB1dH1gfV3Cp3JgLFxuICAgICAgICAgICAgICAgICAgICAgICAgY2hhbm5lbDogJyoub3BzJ1xuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBzaG91bGQgdGhpcyBiZSBicm9hZGNhc3RlZCB0byB0aGUgZXhlY3V0ZXI/XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2VydmVyLmdldENoYXRNYW5hZ2VyKCkuc2VuZChjaGF0KTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgICAgICAgIHN3aXRjaCAodHJ1ZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgZXJyb3IgaW5zdGFuY2VvZiBDb21tYW5kU3ludGF4RXhjZXB0aW9uOlxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBzZW5kZXIuc2VuZE1lc3NhZ2UoYMKnYyR7ZXJyb3IuZ2V0TWVzc2FnZSgpfWApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgY2FzZSBlcnJvciBpbnN0YW5jZW9mIENvbW1hbmRVbmtub3duQ29tbWFuZEVycm9yOlxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBzZW5kZXIuc2VuZE1lc3NhZ2UoYMKnY1Vua25vd24gY29tbWFuZC4gVHlwZSBcIi9oZWxwXCIgZm9yIGhlbHAuYCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICBjYXNlIGVycm9yIGluc3RhbmNlb2YgRXJyb3I6XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHNlbmRlci5zZW5kTWVzc2FnZShgwqdjJHtlcnJvci5tZXNzYWdlfWApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXJ2ZXIuZ2V0TG9nZ2VyKCkuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYXdhaXQgc2VuZGVyLnNlbmRNZXNzYWdlKGDCp2Mke2Vycm9yfWApO1xuICAgICAgICAgICAgdGhpcy5zZXJ2ZXJcbiAgICAgICAgICAgICAgICAuZ2V0TG9nZ2VyKClcbiAgICAgICAgICAgICAgICAuZGVidWcoXG4gICAgICAgICAgICAgICAgICAgIGBQbGF5ZXIgJHt0YXJnZXQuZ2V0Rm9ybWF0dGVkVXNlcm5hbWUoKX0gdHJpZWQgdG8gZXhlY3V0ZSAke2lucHV0fSwgYnV0IGl0IGZhaWxlZCB3aXRoIHRoZSBlcnJvcjogJHtlcnJvcn1gLFxuICAgICAgICAgICAgICAgICAgICAnQ29tbWFuZE1hbmFnZXIvZGlzcGF0Y2hDb21tYW5kJ1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLnNlcnZlci5nZXRMb2dnZXIoKS5lcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG59XG4iXSwibmFtZXMiOlsiQ29tbWFuZHMiLCJjb21tYW5kIiwicmVzIiwibm9kZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZU8sTUFBTSxjQUFrQyxDQUFBO0FBQUEsRUFDMUIsUUFBQSx1QkFBcUMsR0FBSSxFQUFBO0FBQUEsRUFDekMsTUFBQTtBQUFBLEVBQ1QsVUFBQTtBQUFBLEVBRUQsWUFBWSxNQUFnQixFQUFBO0FBQy9CLElBQUEsSUFBQSxDQUFLLE1BQVMsR0FBQSxNQUFBO0FBQ2QsSUFBSyxJQUFBLENBQUEsVUFBQSxHQUFhLElBQUksaUJBQWtCLEVBQUE7QUFBQTtBQUM1QztBQUFBO0FBQUE7QUFBQTtBQUFBLEVBTUEsTUFBYSxNQUF3QixHQUFBO0FBQ2pDLElBQU0sTUFBQSxLQUFBLEdBQVEsSUFBSSxLQUFNLEVBQUE7QUFFeEIsSUFBTSxNQUFBLFFBQUEsR0FBVyxNQUFPLENBQUEsSUFBQSxDQUFLQSxnQkFBUSxDQUFBLENBQUUsSUFBSSxDQUFDLEdBQUEsS0FBU0EsZ0JBQWlCLENBQUEsR0FBRyxDQUFtQixDQUFBO0FBRzVGLElBQUEsTUFBTSxPQUFRLENBQUEsR0FBQTtBQUFBLE1BQ1YsUUFBQSxDQUFTLEdBQUksQ0FBQSxPQUFPLE9BQVksS0FBQTtBQUM1QixRQUFBLE1BQU0sT0FBbUIsR0FBQSxJQUFJLE9BQVEsQ0FBQSxFQUFTLENBQUE7QUFFOUMsUUFBTSxNQUFBLEtBQUEsR0FBUSxJQUFJLG9CQUFBLENBQXFCLE9BQU8sQ0FBQTtBQUM5QyxRQUFBLE1BQU0sSUFBSyxDQUFBLE1BQUEsQ0FBTyxJQUFLLENBQUEsaUJBQUEsRUFBbUIsS0FBSyxDQUFBO0FBQy9DLFFBQUksSUFBQSxLQUFBLENBQU0sYUFBZSxFQUFBO0FBRXpCLFFBQUksSUFBQTtBQUNBLFVBQU0sTUFBQSxJQUFBLENBQUssZ0JBQWdCLE9BQU8sQ0FBQTtBQUFBLGlCQUM3QixLQUFnQixFQUFBO0FBQ3JCLFVBQUEsSUFBQSxDQUFLLE1BQU8sQ0FBQSxTQUFBLEVBQVksQ0FBQSxLQUFBLENBQU0sS0FBSyxDQUFBO0FBQ25DLFVBQUEsSUFBQSxDQUFLLE9BQU8sU0FBVSxFQUFBLENBQUUsS0FBSyxDQUE4QiwyQkFBQSxFQUFBLE9BQUEsQ0FBUSxFQUFFLENBQUUsQ0FBQSxDQUFBO0FBQUE7QUFDM0UsT0FDSDtBQUFBLEtBQ0w7QUFFQSxJQUFBLElBQUEsQ0FBSyxNQUNBLENBQUEsU0FBQSxFQUNBLENBQUEsT0FBQSxDQUFRLENBQWdCLGFBQUEsRUFBQSxJQUFBLENBQUssUUFBUyxDQUFBLElBQUksQ0FBMEIsdUJBQUEsRUFBQSxLQUFBLENBQU0sSUFBSyxFQUFDLENBQVMsT0FBQSxDQUFBLENBQUE7QUFBQTtBQUNsRztBQUFBO0FBQUE7QUFBQTtBQUFBLEVBTUEsTUFBYSxPQUF5QixHQUFBO0FBQ2xDLElBQUEsSUFBQSxDQUFLLFNBQVMsS0FBTSxFQUFBO0FBQUE7QUFFeEI7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQU1BLE1BQWEsZ0JBQWdCLE9BQWtDLEVBQUE7QUFDM0QsSUFBQSxJQUFJLENBQUMsT0FBVyxJQUFBLENBQUMsUUFBUSxFQUFJLEVBQUEsTUFBTSxJQUFJLDJDQUE0QyxFQUFBO0FBQ25GLElBQUksSUFBQSxPQUFBLENBQVEsR0FBRyxLQUFNLENBQUEsR0FBRyxFQUFFLE1BQVcsS0FBQSxDQUFBLEVBQVMsTUFBQSxJQUFJLDRCQUE2QixFQUFBO0FBRS9FLElBQUEsSUFBSSxDQUFFLE9BQWdCLENBQUEsUUFBQTtBQUNsQixNQUFBLElBQUEsQ0FBSyxNQUFPLENBQUEsU0FBQSxFQUFZLENBQUEsSUFBQSxDQUFLLENBQTRELDBEQUFBLENBQUEsQ0FBQTtBQUFBLFNBQ2xGLE1BQUEsT0FBQSxDQUFRLFFBQVMsQ0FBQSxJQUFBLENBQUssVUFBVSxDQUFBO0FBQzNDLElBQUEsSUFBQSxDQUFLLFFBQVMsQ0FBQSxHQUFBLENBQUksT0FBUSxDQUFBLEVBQUEsRUFBSSxPQUFPLENBQUE7QUFFckMsSUFBQSxNQUFNLE9BQVEsQ0FBQSxHQUFBO0FBQUEsTUFDVixJQUFLLENBQUEsTUFBQSxDQUNBLGlCQUFrQixFQUFBLENBQ2xCLGFBQWMsRUFBQSxDQUNkLEdBQUksQ0FBQSxPQUFPLE1BQVcsS0FBQSxNQUFBLENBQU8saUJBQWtCLEVBQUEsQ0FBRSx1QkFBdUI7QUFBQSxLQUNqRjtBQUVBLElBQUEsSUFBQSxDQUFLLE9BQU8sU0FBVSxFQUFBLENBQUUsTUFBTSxDQUFxQixrQkFBQSxFQUFBLE9BQUEsQ0FBUSxFQUFFLENBQWUsYUFBQSxDQUFBLENBQUE7QUFBQTtBQUNoRjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQVFPLFdBQVcsRUFBcUIsRUFBQTtBQUNuQyxJQUFBLE1BQU0sVUFBVSxLQUFNLENBQUEsSUFBQSxDQUFLLEtBQUssUUFBUyxDQUFBLE1BQUEsRUFBUSxDQUFFLENBQUEsSUFBQTtBQUFBLE1BQy9DLENBQUNDLFFBQUFBO0FBQUE7QUFBQSxRQUVHQSxTQUFRLElBQVMsS0FBQSxFQUFBO0FBQUEsUUFFakJBLFFBQUFBLENBQVEsT0FBUyxFQUFBLFFBQUEsQ0FBUyxFQUFFLENBQUE7QUFBQTtBQUFBLFFBRzVCQSxTQUFRLEVBQU8sS0FBQTtBQUFBO0FBQUEsS0FDdkI7QUFFQSxJQUFBLElBQUksQ0FBQyxPQUFBLEVBQWUsTUFBQSxJQUFJLDBCQUEyQixFQUFBO0FBQ25ELElBQU8sT0FBQSxPQUFBO0FBQUE7QUFDWDtBQUFBO0FBQUE7QUFBQSxFQUtPLFdBQW9DLEdBQUE7QUFDdkMsSUFBQSxPQUFPLElBQUssQ0FBQSxRQUFBO0FBQUE7QUFDaEI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFRTyxlQUF1RixHQUFBO0FBQzFGLElBQU0sTUFBQSxTQUFBLEdBQVksQ0FBQyxJQUErQyxLQUFBO0FBQzlELE1BQUksSUFBQSxJQUFBLENBQUssZ0JBQWlCLEVBQUEsSUFBSyxDQUFHLEVBQUE7QUFDOUIsUUFBTyxPQUFBO0FBQUEsVUFDSDtBQUFBLFlBQ0ksSUFBQSxFQUFPLEtBQXVDLE9BQVEsRUFBQTtBQUFBLFlBQ3RELFVBQVU7QUFBQztBQUNmLFNBQ0o7QUFBQTtBQUdKLE1BQUEsTUFBTUMsSUFBTSxHQUFBLEtBQUEsQ0FBTSxJQUFLLENBQUEsSUFBQSxDQUFLLGFBQWEsQ0FBQSxDQUNwQyxHQUFJLENBQUEsQ0FBQ0MsS0FBUyxLQUFBLFNBQUEsQ0FBVUEsS0FBSSxDQUFDLEVBQzdCLE9BQVEsRUFBQTtBQUViLE1BQU8sT0FBQTtBQUFBLFFBQ0gsSUFBQSxDQUFLLFlBQ0MsR0FBQTtBQUFBLFVBQ0ksSUFBQSxFQUFPLEtBQXVDLE9BQVEsRUFBQTtBQUFBLFVBQ3RELFVBQVU7QUFBQyxTQUVmLEdBQUEsS0FBQSxDQUFBO0FBQUEsUUFDTixHQUFHRCxJQUFBQSxDQUFJLEdBQUksQ0FBQSxDQUFDLFFBQW1CLE1BQUE7QUFBQSxVQUMzQixJQUFBLEVBQU8sS0FBdUMsT0FBUSxFQUFBO0FBQUEsVUFDdEQsUUFBQSxFQUFVLENBQUMsR0FBRyxRQUFRO0FBQUEsU0FDeEIsQ0FBQTtBQUFBLE9BQ0osQ0FBQSxNQUFBLENBQU8sQ0FBQyxDQUFBLEtBQU0sQ0FBQyxDQUFBO0FBQUEsS0FDckI7QUFFQSxJQUFNLE1BQUEsUUFBQSxHQUFXLENBQUMsSUFBVyxFQUFBLElBQUEsR0FBYyxFQUFJLEVBQUEsTUFBQSxHQUFnQixFQUFPLEtBQUE7QUFDbEUsTUFBSSxJQUFBLENBQUMsSUFBSyxDQUFBLFFBQUEsQ0FBUyxNQUFRLEVBQUEsTUFBQSxDQUFPLEtBQUssSUFBSyxDQUFBLE1BQUEsQ0FBTyxJQUFLLENBQUEsSUFBSSxDQUFDLENBQUE7QUFDN0QsTUFBVyxLQUFBLE1BQUEsS0FBQSxJQUFTLElBQUssQ0FBQSxRQUFBLEVBQW1CLFFBQUEsQ0FBQSxLQUFBLEVBQU8sS0FBSyxNQUFPLENBQUEsSUFBQSxDQUFLLElBQUksQ0FBQSxFQUFHLE1BQU0sQ0FBQTtBQUNqRixNQUFPLE9BQUEsTUFBQTtBQUFBLEtBQ1g7QUFFQSxJQUFBLE1BQU0sTUFBTSxLQUFNLENBQUEsSUFBQSxDQUFLLElBQUssQ0FBQSxNQUFBLENBQU8sbUJBQW9CLENBQUEsYUFBQSxFQUFnQixDQUFBLE9BQUEsR0FBVSxXQUFZLEVBQUMsQ0FDekYsQ0FBQSxPQUFBLENBQVEsQ0FBQyxPQUFZLEtBQUE7QUFDbEIsTUFBQSxNQUFNLFdBQWtCLEVBQUM7QUFDekIsTUFBQSxJQUFJLFFBQVEsVUFBVyxFQUFBLEVBQVksUUFBQSxDQUFBLElBQUEsQ0FBSyxFQUFFLENBQUE7QUFFMUMsTUFBQSxLQUFBLENBQU0sS0FBSyxPQUFRLENBQUEsV0FBQSxFQUFhLENBQUUsQ0FBQSxPQUFBLENBQVEsQ0FBQyxJQUFTLEtBQUE7QUFDaEQsUUFBTSxNQUFBLE1BQUEsR0FBUyxVQUFVLElBQUksQ0FBQTtBQUM3QixRQUFPLE1BQUEsQ0FBQSxPQUFBLENBQVEsQ0FBQyxNQUFXLEtBQUE7QUFDdkIsVUFBUyxRQUFBLENBQUEsSUFBQSxDQUFLLFFBQVMsQ0FBQSxNQUFNLENBQUMsQ0FBQTtBQUFBLFNBQ2pDLENBQUE7QUFBQSxPQUNKLENBQUE7QUFFRCxNQUFPLE9BQUEsUUFBQSxDQUFTLEdBQUksQ0FBQSxDQUFDLE1BQVcsS0FBQSxDQUFDLFFBQVEsT0FBUSxFQUFBLEVBQUcsT0FBUyxFQUFBLE1BQU0sQ0FBQyxDQUFBO0FBQUEsS0FDdkUsQ0FBQSxDQUNBLE1BQU8sQ0FBQSxDQUFDLE1BQU0sQ0FBUSxDQUFBO0FBRTNCLElBQUEsR0FBQSxDQUFJLFdBQVcsTUFBTTtBQUNqQixNQUFBLE9BQU8sR0FBRyxJQUFLLENBQUEsZUFBQSxFQUNWLENBQUEsR0FBQSxDQUFJLENBQUMsSUFBUyxLQUFBO0FBQ1gsUUFBSSxJQUFBLENBQUMsS0FBSyxDQUFDLENBQUEsQ0FBRSxRQUFlLE9BQUEsQ0FBQSxDQUFBLEVBQUksSUFBSyxDQUFBLENBQUMsQ0FBQyxDQUFBLENBQUE7QUFDdkMsUUFBTyxPQUFBLElBQUEsQ0FBSyxDQUFDLENBQ1IsQ0FBQSxHQUFBO0FBQUEsVUFDRyxDQUFDLE9BQ0csS0FBQSxDQUFBLENBQUEsRUFBSSxJQUFLLENBQUEsQ0FBQyxDQUFDLENBQUksQ0FBQSxFQUFBLE9BQUEsQ0FDVixJQUFLLENBQUEsTUFBQSxDQUFPLGlCQUFpQixDQUFBLENBQzdCLElBQUksQ0FBQyxRQUFBLEtBQWtCLFFBQVMsQ0FBQSxlQUFBLElBQXVCLElBQUEsUUFBQSxDQUFTLFlBQVksSUFBSSxDQUFBLENBQ2hGLElBQUssQ0FBQSxHQUFHLENBQUMsQ0FBQTtBQUFBLFVBRXJCLElBQUssQ0FBQTtBQUFBLENBQUksQ0FBQTtBQUFBLE9BQ2pCLENBQUEsQ0FDQSxJQUFLLENBQUEsSUFBSSxDQUFDLENBQUEsQ0FBQTtBQUFBLEtBQ25CO0FBQ0EsSUFBTyxPQUFBLEdBQUE7QUFBQTtBQUNYO0FBQUE7QUFBQTtBQUFBLEVBS08sYUFBMkMsR0FBQTtBQUM5QyxJQUFBLE9BQU8sSUFBSyxDQUFBLFVBQUE7QUFBQTtBQUNoQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBU0EsTUFBYSxlQUFBLENBQWdCLE1BQWdCLEVBQUEsTUFBQSxFQUF5QixRQUFRLEVBQUksRUFBQTtBQUM5RSxJQUFJLElBQUE7QUFDQSxNQUFBLElBQUksTUFBTSxVQUFXLENBQUEsR0FBRyxHQUFXLEtBQUEsR0FBQSxLQUFBLENBQU0sTUFBTSxDQUFDLENBQUE7QUFFaEQsTUFBQSxNQUFNLFNBQVMsSUFBSyxDQUFBLFVBQUEsQ0FBVyxNQUFNLEtBQU0sQ0FBQSxJQUFBLElBQVEsTUFBZ0IsQ0FBQTtBQUNuRSxNQUFNLE1BQUEsRUFBQSxHQUFLLE9BQU8sU0FBVSxFQUFBLENBQUUsV0FBWSxDQUFBLEtBQUEsQ0FBTSxHQUFHLENBQUEsQ0FBRSxDQUFDLENBQUE7QUFFdEQsTUFBSSxJQUFBLENBQUMsTUFBTyxDQUFBLFNBQUEsRUFBYSxFQUFBO0FBQ3JCLFFBQUssSUFBQSxDQUFBLE1BQUEsQ0FDQSxXQUNBLENBQUEsS0FBQTtBQUFBLFVBQ0csaUJBQWlCLE1BQU8sQ0FBQSxZQUFBLEVBQWMsQ0FBOEIsMkJBQUEsRUFBQSxLQUFLLFNBQVMsRUFBRSxDQUFBLENBQUEsQ0FBQTtBQUFBLFVBQ3BGO0FBQUEsU0FDSjtBQUFBO0FBSVIsTUFBTSxNQUFBLE9BQUEsR0FBVSxJQUFLLENBQUEsVUFBQSxDQUFXLEVBQUUsQ0FBQTtBQUdsQyxNQUFJLElBQUEsQ0FBQyxJQUFLLENBQUEsTUFBQSxDQUFPLG9CQUFxQixFQUFBLENBQUUsR0FBSSxDQUFBLE1BQU0sQ0FBRSxDQUFBLE9BQUEsQ0FBUSxPQUFRLENBQUEsVUFBVSxDQUFHLEVBQUE7QUFDN0UsUUFBQSxNQUFNLE1BQU8sQ0FBQSxXQUFBO0FBQUEsVUFDVDtBQUFBLFNBRUo7QUFDQSxRQUFBO0FBQUE7QUFHSixNQUFBLElBQUksTUFBZ0IsRUFBQztBQUVyQixNQUFJLElBQUEsT0FBQSxDQUFRLFNBQVMsRUFBSSxFQUFBO0FBQ3JCLFFBQU0sTUFBQSxJQUFBLENBQUssZ0JBQWdCLE1BQVEsRUFBQSxNQUFBLEVBQVEsTUFBTSxPQUFRLENBQUEsRUFBQSxFQUFJLE9BQVEsQ0FBQSxJQUFJLENBQUMsQ0FBQTtBQUMxRSxRQUFBO0FBQUE7QUFHSixNQUFBLEdBQUEsR0FBTSxNQUFNLE9BQVEsQ0FBQSxHQUFBLENBQUksS0FBSyxVQUFXLENBQUEsT0FBQSxDQUFRLE1BQU0sQ0FBQyxDQUFBO0FBRXZELE1BQUEsTUFBTSxXQUFZLE1BQ2IsQ0FBQSxRQUFBLEdBQ0Esa0JBQW1CLEVBQUEsQ0FDbkIsWUFBWSxxQkFBcUIsQ0FBQTtBQUd0QyxNQUFBLElBQUksQ0FBQyxRQUFVLEVBQUE7QUFFZixNQUFBLE1BQU0sT0FBUSxDQUFBLEdBQUE7QUFBQSxRQUNWLEdBQUEsQ0FBSSxHQUFJLENBQUEsT0FBT0EsSUFBYSxLQUFBO0FBQ3hCLFVBQU0sTUFBQSxJQUFBLEdBQU8sSUFBSSxJQUFLLENBQUE7QUFBQSxZQUNsQixNQUFBLEVBQVEsSUFBSyxDQUFBLE1BQUEsQ0FBTyxVQUFXLEVBQUE7QUFBQSxZQUMvQixPQUFBLEVBQVMsUUFBUSxNQUFPLENBQUEsT0FBQSxFQUFTLENBQUtBLEVBQUFBLEVBQUFBLElBQUFBLElBQU8sQ0FBMkIsd0JBQUEsRUFBQSxLQUFLLENBQUUsQ0FBQSxDQUFBLEdBQUEsQ0FBQTtBQUFBLFlBQy9FLE9BQVMsRUFBQTtBQUFBLFdBQ1osQ0FBQTtBQUdELFVBQUEsTUFBTSxJQUFLLENBQUEsTUFBQSxDQUFPLGNBQWUsRUFBQSxDQUFFLEtBQUssSUFBSSxDQUFBO0FBQUEsU0FDL0M7QUFBQSxPQUNMO0FBQUEsYUFDSyxLQUFnQixFQUFBO0FBQ3JCLE1BQUEsUUFBUSxJQUFNO0FBQUEsUUFDVixLQUFLLEtBQWlCLFlBQUEsc0JBQUE7QUFDbEIsVUFBQSxNQUFNLE9BQU8sV0FBWSxDQUFBLENBQUEsRUFBQSxFQUFLLEtBQU0sQ0FBQSxVQUFBLEVBQVksQ0FBRSxDQUFBLENBQUE7QUFDbEQsVUFBQTtBQUFBLFFBQ0osS0FBSyxLQUFpQixZQUFBLDBCQUFBO0FBQ2xCLFVBQU0sTUFBQSxNQUFBLENBQU8sWUFBWSxDQUEyQyx5Q0FBQSxDQUFBLENBQUE7QUFDcEUsVUFBQTtBQUFBLFFBQ0osS0FBSyxLQUFpQixZQUFBLEtBQUE7QUFDbEIsVUFBQSxNQUFNLE1BQU8sQ0FBQSxXQUFBLENBQVksQ0FBSyxFQUFBLEVBQUEsS0FBQSxDQUFNLE9BQU8sQ0FBRSxDQUFBLENBQUE7QUFDN0MsVUFBQTtBQUFBLFFBQ0o7QUFDSSxVQUFBLElBQUEsQ0FBSyxNQUFPLENBQUEsU0FBQSxFQUFZLENBQUEsS0FBQSxDQUFNLEtBQUssQ0FBQTtBQUNuQyxVQUFBO0FBQUE7QUFHUixNQUFBLE1BQU0sTUFBTyxDQUFBLFdBQUEsQ0FBWSxDQUFLLEVBQUEsRUFBQSxLQUFLLENBQUUsQ0FBQSxDQUFBO0FBQ3JDLE1BQUssSUFBQSxDQUFBLE1BQUEsQ0FDQSxXQUNBLENBQUEsS0FBQTtBQUFBLFFBQ0csVUFBVSxNQUFPLENBQUEsb0JBQUEsRUFBc0IsQ0FBcUIsa0JBQUEsRUFBQSxLQUFLLG1DQUFtQyxLQUFLLENBQUEsQ0FBQTtBQUFBLFFBQ3pHO0FBQUEsT0FDSjtBQUNKLE1BQUEsSUFBQSxDQUFLLE1BQU8sQ0FBQSxTQUFBLEVBQVksQ0FBQSxLQUFBLENBQU0sS0FBSyxDQUFBO0FBQUE7QUFDdkM7QUFFUjs7OzsifQ==