UNPKG

@hsaadawy/ngx-chat

Version:
411 lines 73.5 kB
import { __awaiter } from "tslib"; import { jid as parseJid, xml } from '@xmpp/client'; import { BehaviorSubject, Subject } from 'rxjs'; import { dummyAvatarRoom } from '../../../../core/contact-avatar'; import { Direction } from '../../../../core/message'; import { MessageStore } from '../../../../core/message-store'; import { isJid } from '../../../../core/recipient'; import { AbstractStanzaBuilder } from '../abstract-stanza-builder'; import { StanzaBuilder } from '../stanza-builder'; import { AbstractXmppPlugin } from './abstract-xmpp-plugin'; import { MessageReceivedEvent } from './message.plugin'; import { ServiceDiscoveryPlugin } from './service-discovery.plugin'; export class Room { constructor(occupantJid, logService, name) { this.recipientType = 'room'; this.avatar = dummyAvatarRoom; this.metadata = {}; this.roomJid = occupantJid.bare(); this.name = name !== null && name !== void 0 ? name : occupantJid.bare().toString(); this.nick = name !== null && name !== void 0 ? name : occupantJid.bare().toString(); this.occupantJid = occupantJid; this.messageStore = new MessageStore(logService); } get jidBare() { return this.roomJid; } get messages$() { return this.messageStore.messages$; } get messages() { return this.messageStore.messages; } get dateMessagesGroups() { return this.messageStore.dateMessageGroups; } get oldestMessage() { return this.messageStore.oldestMessage; } get mostRecentMessage() { return this.messageStore.mostRecentMessage; } get mostRecentMessageReceived() { return this.messageStore.mostRecentMessageReceived; } get mostRecentMessageSent() { return this.messageStore.mostRecentMessageSent; } addMessage(message) { this.messageStore.addMessage(message); } equalsBareJid(other) { if (other instanceof Room || isJid(other)) { const otherJid = other instanceof Room ? other.roomJid : other.bare(); return this.roomJid.bare().equals(otherJid); } return false; } } export var Affiliation; (function (Affiliation) { Affiliation[Affiliation["none"] = 0] = "none"; Affiliation[Affiliation["member"] = 1] = "member"; Affiliation[Affiliation["admin"] = 2] = "admin"; Affiliation[Affiliation["owner"] = 3] = "owner"; Affiliation[Affiliation["outcast"] = 4] = "outcast"; })(Affiliation || (Affiliation = {})); class QueryMemberListStanzaBuilder extends AbstractStanzaBuilder { constructor(roomJid, affiliation) { super(); this.roomJid = roomJid; this.affiliation = affiliation; } static build(roomJid, affiliation) { return new QueryMemberListStanzaBuilder(roomJid, affiliation).toStanza(); } toStanza() { return xml('iq', { type: 'get', to: this.roomJid }, xml('query', { xmlns: 'http://jabber.org/protocol/muc#admin' }, xml('item', { affiliation: this.affiliation }))); } } class ModifyMemberListStanzaBuilder extends AbstractStanzaBuilder { constructor(roomJid, modifications) { super(); this.roomJid = roomJid; this.modifications = modifications; } static build(roomJid, modifications) { return new ModifyMemberListStanzaBuilder(roomJid, modifications).toStanza(); } toStanza() { return xml('iq', { to: this.roomJid, type: 'set' }, xml('query', { xmlns: 'http://jabber.org/protocol/muc#admin' }, ...this.modifications.map(modification => this.buildItem(modification)))); } buildItem({ nick, jid, affiliation }) { const item = xml('item', { jid, affiliation: Affiliation[affiliation] }); if (nick) { item.attrs.nick = nick; } return item; } } /** * The MultiUserChatPlugin tries to provide the necessary functionality for a multi-user text chat, * whereby multiple XMPP users can exchange messages in the context of a room or channel, similar to Internet Relay Chat (IRC). * For more details see: * @see https://xmpp.org/extensions/xep-0045.html */ export class MultiUserChatPlugin extends AbstractXmppPlugin { constructor(xmppChatAdapter, logService, serviceDiscoveryPlugin) { super(); this.xmppChatAdapter = xmppChatAdapter; this.logService = logService; this.serviceDiscoveryPlugin = serviceDiscoveryPlugin; this.rooms$ = new BehaviorSubject([]); this.message$ = new Subject(); this.roomJoinResponseHandlers = new Map(); } onOffline() { this.roomJoinResponseHandlers.clear(); this.rooms$.next([]); } handleStanza(stanza, archiveDelayElement) { if (this.isRoomPresenceStanza(stanza)) { return this.handleRoomPresenceStanza(stanza); } else if (this.isRoomMessageStanza(stanza)) { return this.handleRoomMessageStanza(stanza, archiveDelayElement); } return false; } isRoomPresenceStanza(stanza) { return stanza.name === 'presence' && (stanza.getChild('x', 'http://jabber.org/protocol/muc') || stanza.getChild('x', 'http://jabber.org/protocol/muc#user')) != null; } handleRoomPresenceStanza(stanza) { const handleStanza = this.roomJoinResponseHandlers.get(stanza.attrs.from); if (handleStanza) { this.roomJoinResponseHandlers.delete(stanza.attrs.from); handleStanza(stanza); return true; } return false; } /** * Resolves if room could be configured as requested, rejects if room did exist or server did not accept configuration. */ createRoom(request) { return __awaiter(this, void 0, void 0, function* () { const { roomId, nick, name } = request; const service = yield this.serviceDiscoveryPlugin.findService('conference', 'text'); const occupantJid = parseJid(roomId, service.jid, nick); const { presenceResponse, room } = yield this.joinRoomInternal(occupantJid, name); const itemElement = presenceResponse.getChild('x').getChild('item'); if (itemElement.attrs.affiliation !== 'owner') { throw new Error('error creating room, user is not owner: ' + presenceResponse.toString()); } /** * requests a configuration form for a room which returns with the default values * for an example see: * https://xmpp.org/extensions/xep-0045.html#registrar-formtype-owner */ const configurationForm = yield this.xmppChatAdapter.chatConnectionService.sendIq(xml('iq', { type: 'get', to: room.roomJid.toString() }, xml('query', { xmlns: 'http://jabber.org/protocol/muc#owner' }))); const configurationListElement = configurationForm.getChild('query').getChild('x'); if (!configurationListElement) { throw new Error('room not configurable'); } const roomConfigurationOptions = this.applyRoomCreationRequestOptions(this.extractDefaultConfiguration(configurationListElement.getChildren('field')), request); try { yield this.xmppChatAdapter.chatConnectionService.sendIq(xml('iq', { type: 'set', to: room.roomJid.toString() }, xml('query', { xmlns: 'http://jabber.org/protocol/muc#owner' }, xml('x', { xmlns: 'jabber:x:data', type: 'submit' }, xml('field', { var: 'FORM_TYPE' }, xml('value', {}, 'http://jabber.org/protocol/muc#roomconfig')), ...this.configurationToElements(roomConfigurationOptions))))); return room; } catch (e) { this.logService.error('room configuration rejected', e); throw e; } }); } destroyRoom(roomJid) { return __awaiter(this, void 0, void 0, function* () { let roomDestroyedResponse; try { roomDestroyedResponse = yield this.xmppChatAdapter.chatConnectionService.sendIq(xml('iq', { type: 'set', to: roomJid.toString() }, xml('query', { xmlns: 'http://jabber.org/protocol/muc#owner' }, xml('destroy')))); } catch (e) { this.logService.error('error destroying room'); throw e; } // TODO: refactor so that we instead listen to the presence destroy stanza const allRoomsWithoutDestroyedRoom = this.rooms$.getValue().filter(room => !room.roomJid.equals(roomJid)); this.rooms$.next(allRoomsWithoutDestroyedRoom); return roomDestroyedResponse; }); } joinRoomInternal(roomJid, name) { return __awaiter(this, void 0, void 0, function* () { if (this.getRoomByJid(roomJid.bare())) { throw new Error('can not join room more than once: ' + roomJid.bare().toString()); } const userJid = this.xmppChatAdapter.chatConnectionService.userJid; const occupantJid = parseJid(roomJid.local, roomJid.domain, roomJid.resource || userJid.local); const roomJoinedPromise = new Promise(resolve => this.roomJoinResponseHandlers.set(occupantJid.toString(), resolve)); try { yield this.xmppChatAdapter.chatConnectionService.send(xml('presence', { from: userJid.toString(), to: occupantJid.toString() }, xml('x', { xmlns: 'http://jabber.org/protocol/muc' }))); } catch (e) { this.logService.error('error sending presence stanza to join a room', e); this.roomJoinResponseHandlers.delete(occupantJid.toString()); throw e; } const presenceResponse = yield roomJoinedPromise; if (presenceResponse.getChild('error')) { throw new Error('error joining room: ' + presenceResponse.toString()); } let room = this.getRoomByJid(roomJid); if (!room) { room = new Room(occupantJid, this.logService, name); this.rooms$.next([room].concat(this.rooms$.getValue())); } return { presenceResponse, room }; }); } joinRoom(occupantJid) { return __awaiter(this, void 0, void 0, function* () { return (yield this.joinRoomInternal(occupantJid)).room; }); } queryAllRooms() { return __awaiter(this, void 0, void 0, function* () { const conferenceServer = yield this.serviceDiscoveryPlugin.findService('conference', 'text'); const to = conferenceServer.jid.toString(); const result = []; let roomQueryResponse = yield this.xmppChatAdapter.chatConnectionService.sendIq(xml('iq', { type: 'get', to: conferenceServer.jid.toString() }, xml('query', { xmlns: ServiceDiscoveryPlugin.DISCO_ITEMS }))); result.push(...this.extractRoomSummariesFromResponse(roomQueryResponse)); let resultSet = this.extractResultSetFromResponse(roomQueryResponse); while (resultSet && resultSet.getChild('last')) { const lastReceivedRoom = resultSet.getChildText('last'); roomQueryResponse = yield this.xmppChatAdapter.chatConnectionService.sendIq(xml('iq', { type: 'get', to: conferenceServer.jid.toString() }, xml('query', { xmlns: ServiceDiscoveryPlugin.DISCO_ITEMS }, xml('set', { xmlns: 'http://jabber.org/protocol/rsm' }, xml('max', {}, 250), xml('after', {}, lastReceivedRoom))))); result.push(...this.extractRoomSummariesFromResponse(roomQueryResponse)); resultSet = this.extractResultSetFromResponse(roomQueryResponse); } return result; }); } extractRoomSummariesFromResponse(iq) { var _a, _b; return ((_b = (_a = iq .getChild('query', ServiceDiscoveryPlugin.DISCO_ITEMS)) === null || _a === void 0 ? void 0 : _a.getChildren('item')) === null || _b === void 0 ? void 0 : _b.map(room => room.attrs)) || []; } extractResultSetFromResponse(iq) { var _a; return (_a = iq .getChild('query', ServiceDiscoveryPlugin.DISCO_ITEMS)) === null || _a === void 0 ? void 0 : _a.getChild('set', 'http://jabber.org/protocol/rsm'); } /** * Get all members of a MUC-Room with their affiliation to the room using the rooms fullJid * @param fullRoomJid fullJid of the room as string */ queryMemberList(fullRoomJid) { return __awaiter(this, void 0, void 0, function* () { const memberQueryResponses = yield Promise.all([ this.xmppChatAdapter.chatConnectionService.sendIq(QueryMemberListStanzaBuilder.build(fullRoomJid, 'admin')), this.xmppChatAdapter.chatConnectionService.sendIq(QueryMemberListStanzaBuilder.build(fullRoomJid, 'member')), this.xmppChatAdapter.chatConnectionService.sendIq(QueryMemberListStanzaBuilder.build(fullRoomJid, 'owner')), this.xmppChatAdapter.chatConnectionService.sendIq(QueryMemberListStanzaBuilder.build(fullRoomJid, 'outcast')), ]); let members = []; for (const memberQueryResponse of memberQueryResponses) { const membersFromQueryResponse = memberQueryResponse.getChild('query').getChildren('item') .map((memberItem) => ({ jid: memberItem.attrs.jid, nick: memberItem.attrs.nick, affiliation: this.reverseMapAffiliation(memberItem.attrs.affiliation), })); members = members.concat(membersFromQueryResponse); } return members; }); } reverseMapAffiliation(value) { if (!value || value === 'none') { return Affiliation.none; } else if (value === 'member') { return Affiliation.member; } else if (value === 'admin') { return Affiliation.admin; } else if (value === 'owner') { return Affiliation.owner; } else if (value === 'outcast') { return Affiliation.outcast; } else { const message = 'unexpected affilation: ' + value; this.logService.error(message); throw new Error(message); } } modifyMemberList(roomJid, jid, affiliation, nick) { return __awaiter(this, void 0, void 0, function* () { return yield this.xmppChatAdapter.chatConnectionService.sendIq(ModifyMemberListStanzaBuilder.build(roomJid, [{ jid, affiliation, nick }])); }); } sendMessage(room, body, thread) { return __awaiter(this, void 0, void 0, function* () { const from = this.xmppChatAdapter.chatConnectionService.userJid.toString(); const roomJid = room.roomJid.toString(); const roomMessageStanza = thread ? StanzaBuilder.buildRoomMessageWithThread(from, roomJid, body, thread) : StanzaBuilder.buildRoomMessageWithBody(from, roomJid, body); for (const plugin of this.xmppChatAdapter.plugins) { plugin.beforeSendMessage(roomMessageStanza); } return yield this.xmppChatAdapter.chatConnectionService.send(roomMessageStanza); }); } configurationToElements(configurationOptions) { return [...configurationOptions.entries()] .map(([configurationKey, configurationValues]) => xml('field', { var: configurationKey }, ...configurationValues.map(value => xml('value', {}, value)))); } extractDefaultConfiguration(fields) { const entries = fields .filter(field => field.attrs.type !== 'hidden') .map((field) => [ field.attrs.var, field.getChildren('value').map(value => value.getText()) ]); return new Map(entries); } applyRoomCreationRequestOptions(defaultOptions, request) { const options = new Map(defaultOptions); options .set('muc#roomconfig_whois', [request.nonAnonymous ? 'anyone' : 'moderators']) .set('muc#roomconfig_publicroom', [request.public ? '1' : '0']) .set('muc#roomconfig_membersonly', [request.membersOnly ? '1' : '0']) .set('muc#roomconfig_persistentroom', [request.persistentRoom ? '1' : '0']); if (request.allowSubscription !== undefined) { options.set('allow_subscription', [request.allowSubscription === true ? '1' : '0']); } return options; } isRoomMessageStanza(stanza) { var _a; return stanza.name === 'message' && stanza.attrs.type === 'groupchat' && !!((_a = stanza.getChildText('body')) === null || _a === void 0 ? void 0 : _a.trim()); } handleRoomMessageStanza(messageStanza, archiveDelayElement) { const delayElement = archiveDelayElement !== null && archiveDelayElement !== void 0 ? archiveDelayElement : messageStanza.getChild('delay'); const datetime = (delayElement === null || delayElement === void 0 ? void 0 : delayElement.attrs.stamp) ? new Date(delayElement.attrs.stamp) : new Date() /* TODO: replace with entity time plugin */; const from = parseJid(messageStanza.attrs.from); const room = this.getRoomByJid(from.bare()); if (!room) { // there are several reasons why we can receive a message for an unknown room: // - this is a message delivered via MAM/MUCSub but the room it was stored for // - is gone (was destroyed) // - user was banned from room // - room wasn't joined yet // - this is some kind of error on developer's side this.logService.warn(`received stanza for unknown room: ${from.bare().toString()}`); return false; } const message = { body: messageStanza.getChildText('body').trim(), datetime, id: messageStanza.attrs.id, from, direction: from.equals(room.occupantJid) ? Direction.out : Direction.in, delayed: !!delayElement, fromArchive: archiveDelayElement != null }; const messageReceivedEvent = new MessageReceivedEvent(); for (const plugin of this.xmppChatAdapter.plugins) { plugin.afterReceiveMessage(message, messageStanza, messageReceivedEvent); } if (!messageReceivedEvent.discard) { room.addMessage(message); } if (!message.delayed) { this.message$.next(room); } return true; } getRoomByJid(jid) { return this.rooms$.getValue().find(room => room.roomJid.equals(jid)); } ban() { throw new Error('moderation not implemented'); } invite() { throw new Error('moderation not implemented'); } join() { throw new Error('moderation not implemented'); } kick() { throw new Error('moderation not implemented'); } nick() { throw new Error('moderation not implemented'); } part() { this.leave(); } leave() { throw new Error('moderation not implemented'); } topic() { throw new Error('moderation not implemented'); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXVsdGktdXNlci1jaGF0LnBsdWdpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3BhenpuZXR3b3JrL25neC1jaGF0L3NyYy9saWIvc2VydmljZXMvYWRhcHRlcnMveG1wcC9wbHVnaW5zL211bHRpLXVzZXItY2hhdC5wbHVnaW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxHQUFHLElBQUksUUFBUSxFQUFFLEdBQUcsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUdwRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUVoRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbEUsT0FBTyxFQUFFLFNBQVMsRUFBVyxNQUFNLDBCQUEwQixDQUFDO0FBQzlELE9BQU8sRUFBcUIsWUFBWSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDakYsT0FBTyxFQUFFLEtBQUssRUFBYSxNQUFNLDRCQUE0QixDQUFDO0FBRzlELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ25FLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUVsRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM1RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQTREcEUsTUFBTSxPQUFPLElBQUk7SUFlYixZQUFZLFdBQWdCLEVBQUUsVUFBc0IsRUFBRSxJQUF5QjtRQWJ0RSxrQkFBYSxHQUFHLE1BQU0sQ0FBQztRQUtoQyxXQUFNLEdBQUcsZUFBZSxDQUFDO1FBQ3pCLGFBQVEsR0FBaUIsRUFBRSxDQUFDO1FBUXhCLElBQUksQ0FBQyxPQUFPLEdBQUcsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2xDLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxhQUFKLElBQUksY0FBSixJQUFJLEdBQUksV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2xELElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxhQUFKLElBQUksY0FBSixJQUFJLEdBQUksV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2xELElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBQy9CLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxZQUFZLENBQWMsVUFBVSxDQUFDLENBQUM7SUFDbEUsQ0FBQztJQVZELElBQUksT0FBTztRQUNQLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQztJQUN4QixDQUFDO0lBVUQsSUFBSSxTQUFTO1FBQ1QsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQztJQUN2QyxDQUFDO0lBRUQsSUFBSSxRQUFRO1FBQ1IsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQztJQUN0QyxDQUFDO0lBRUQsSUFBSSxrQkFBa0I7UUFDbEIsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLGlCQUFpQixDQUFDO0lBQy9DLENBQUM7SUFFRCxJQUFJLGFBQWE7UUFDYixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsYUFBYSxDQUFDO0lBQzNDLENBQUM7SUFFRCxJQUFJLGlCQUFpQjtRQUNqQixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsaUJBQWlCLENBQUM7SUFDL0MsQ0FBQztJQUVELElBQUkseUJBQXlCO1FBQ3pCLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyx5QkFBeUIsQ0FBQztJQUN2RCxDQUFDO0lBRUQsSUFBSSxxQkFBcUI7UUFDckIsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLHFCQUFxQixDQUFDO0lBQ25ELENBQUM7SUFFRCxVQUFVLENBQUMsT0FBb0I7UUFDM0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVELGFBQWEsQ0FBQyxLQUFzQjtRQUNoQyxJQUFJLEtBQUssWUFBWSxJQUFJLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQ3ZDLE1BQU0sUUFBUSxHQUFHLEtBQUssWUFBWSxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUN0RSxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQy9DO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztDQUVKO0FBRUQsTUFBTSxDQUFOLElBQVksV0FNWDtBQU5ELFdBQVksV0FBVztJQUNuQiw2Q0FBSSxDQUFBO0lBQ0osaURBQU0sQ0FBQTtJQUNOLCtDQUFLLENBQUE7SUFDTCwrQ0FBSyxDQUFBO0lBQ0wsbURBQU8sQ0FBQTtBQUNYLENBQUMsRUFOVyxXQUFXLEtBQVgsV0FBVyxRQU10QjtBQUVELE1BQU0sNEJBQTZCLFNBQVEscUJBQXFCO0lBRTVELFlBQTZCLE9BQWUsRUFBbUIsV0FBbUI7UUFDOUUsS0FBSyxFQUFFLENBQUM7UUFEaUIsWUFBTyxHQUFQLE9BQU8sQ0FBUTtRQUFtQixnQkFBVyxHQUFYLFdBQVcsQ0FBUTtJQUVsRixDQUFDO0lBRUQsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFlLEVBQUUsV0FBbUI7UUFDN0MsT0FBTyxJQUFJLDRCQUE0QixDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUM3RSxDQUFDO0lBRUQsUUFBUTtRQUNKLE9BQU8sR0FBRyxDQUFDLElBQUksRUFBRSxFQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUMsRUFDNUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxFQUFDLEtBQUssRUFBRSxzQ0FBc0MsRUFBQyxFQUN4RCxHQUFHLENBQUMsTUFBTSxFQUFFLEVBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUMsQ0FBQyxDQUMvQyxDQUNKLENBQUM7SUFDTixDQUFDO0NBRUo7QUFhRCxNQUFNLDZCQUE4QixTQUFRLHFCQUFxQjtJQUU3RCxZQUE2QixPQUFlLEVBQW1CLGFBQXdDO1FBQ25HLEtBQUssRUFBRSxDQUFDO1FBRGlCLFlBQU8sR0FBUCxPQUFPLENBQVE7UUFBbUIsa0JBQWEsR0FBYixhQUFhLENBQTJCO0lBRXZHLENBQUM7SUFFRCxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQWUsRUFBRSxhQUF3QztRQUNsRSxPQUFPLElBQUksNkJBQTZCLENBQUMsT0FBTyxFQUFFLGFBQWEsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ2hGLENBQUM7SUFFRCxRQUFRO1FBQ0osT0FBTyxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBQyxFQUM1QyxHQUFHLENBQUMsT0FBTyxFQUFFLEVBQUMsS0FBSyxFQUFFLHNDQUFzQyxFQUFDLEVBQ3hELEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQzFFLENBQ0osQ0FBQztJQUNOLENBQUM7SUFFTyxTQUFTLENBQUMsRUFBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLFdBQVcsRUFBaUI7UUFDdEQsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxFQUFDLEdBQUcsRUFBRSxXQUFXLEVBQUUsV0FBVyxDQUFDLFdBQVcsQ0FBQyxFQUFDLENBQUMsQ0FBQztRQUN2RSxJQUFJLElBQUksRUFBRTtZQUNOLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztTQUMxQjtRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7Q0FDSjtBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLG1CQUFvQixTQUFRLGtCQUFrQjtJQU12RCxZQUNxQixlQUFnQyxFQUNoQyxVQUFzQixFQUN0QixzQkFBOEM7UUFFL0QsS0FBSyxFQUFFLENBQUM7UUFKUyxvQkFBZSxHQUFmLGVBQWUsQ0FBaUI7UUFDaEMsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQUN0QiwyQkFBc0IsR0FBdEIsc0JBQXNCLENBQXdCO1FBUDFELFdBQU0sR0FBRyxJQUFJLGVBQWUsQ0FBUyxFQUFFLENBQUMsQ0FBQztRQUN6QyxhQUFRLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztRQUN2Qiw2QkFBd0IsR0FBRyxJQUFJLEdBQUcsRUFBb0MsQ0FBQztJQVF4RixDQUFDO0lBRUQsU0FBUztRQUNMLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN0QyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN6QixDQUFDO0lBRUQsWUFBWSxDQUFDLE1BQWMsRUFBRSxtQkFBNEI7UUFDckQsSUFBSSxJQUFJLENBQUMsb0JBQW9CLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDbkMsT0FBTyxJQUFJLENBQUMsd0JBQXdCLENBQUMsTUFBTSxDQUFDLENBQUM7U0FDaEQ7YUFBTSxJQUFJLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsRUFBRTtZQUN6QyxPQUFPLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxNQUFNLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztTQUNwRTtRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUM7SUFFTyxvQkFBb0IsQ0FBQyxNQUFjO1FBQ3ZDLE9BQU8sTUFBTSxDQUFDLElBQUksS0FBSyxVQUFVLElBQUksQ0FDakMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsZ0NBQWdDLENBQUM7ZUFDbkQsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUscUNBQXFDLENBQUMsQ0FDakUsSUFBSSxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU8sd0JBQXdCLENBQUMsTUFBYztRQUMzQyxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsd0JBQXdCLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDMUUsSUFBSSxZQUFZLEVBQUU7WUFDZCxJQUFJLENBQUMsd0JBQXdCLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDeEQsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3JCLE9BQU8sSUFBSSxDQUFDO1NBQ2Y7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0lBRUQ7O09BRUc7SUFDRyxVQUFVLENBQUMsT0FBNEI7O1lBQ3pDLE1BQU0sRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBQyxHQUFHLE9BQU8sQ0FBQztZQUNyQyxNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxXQUFXLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ3BGLE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUN4RCxNQUFNLEVBQUMsZ0JBQWdCLEVBQUUsSUFBSSxFQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBRWhGLE1BQU0sV0FBVyxHQUFHLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDcEUsSUFBSSxXQUFXLENBQUMsS0FBSyxDQUFDLFdBQVcsS0FBSyxPQUFPLEVBQUU7Z0JBQzNDLE1BQU0sSUFBSSxLQUFLLENBQUMsMENBQTBDLEdBQUcsZ0JBQWdCLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQzthQUM3RjtZQUVEOzs7O2VBSUc7WUFDSCxNQUFNLGlCQUFpQixHQUFHLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQzdFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxFQUFDLEVBQ2hELEdBQUcsQ0FBQyxPQUFPLEVBQUUsRUFBQyxLQUFLLEVBQUUsc0NBQXNDLEVBQUMsQ0FBQyxDQUNoRSxDQUNKLENBQUM7WUFFRixNQUFNLHdCQUF3QixHQUFHLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDbkYsSUFBSSxDQUFDLHdCQUF3QixFQUFFO2dCQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixDQUFDLENBQUM7YUFDNUM7WUFFRCxNQUFNLHdCQUF3QixHQUMxQixJQUFJLENBQUMsK0JBQStCLENBQ2hDLElBQUksQ0FBQywyQkFBMkIsQ0FBQyx3QkFBd0IsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsRUFDL0UsT0FBTyxDQUNWLENBQUM7WUFFTixJQUFJO2dCQUNBLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQ25ELEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxFQUFDLEVBQ2hELEdBQUcsQ0FBQyxPQUFPLEVBQUUsRUFBQyxLQUFLLEVBQUUsc0NBQXNDLEVBQUMsRUFDeEQsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFDLEtBQUssRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBQyxFQUM3QyxHQUFHLENBQUMsT0FBTyxFQUFFLEVBQUMsR0FBRyxFQUFFLFdBQVcsRUFBQyxFQUMzQixHQUFHLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSwyQ0FBMkMsQ0FBQyxDQUNoRSxFQUNELEdBQUcsSUFBSSxDQUFDLHVCQUF1QixDQUFDLHdCQUF3QixDQUFDLENBQzVELENBQ0osQ0FDSixDQUNKLENBQUM7Z0JBQ0YsT0FBTyxJQUFJLENBQUM7YUFDZjtZQUFDLE9BQU8sQ0FBVSxFQUFFO2dCQUNqQixJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyw2QkFBNkIsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDeEQsTUFBTSxDQUFDLENBQUM7YUFDWDtRQUNMLENBQUM7S0FBQTtJQUVLLFdBQVcsQ0FBQyxPQUFZOztZQUMxQixJQUFJLHFCQUFpRCxDQUFDO1lBQ3RELElBQUk7Z0JBQ0EscUJBQXFCLEdBQUcsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLHFCQUFxQixDQUFDLE1BQU0sQ0FDM0UsR0FBRyxDQUFDLElBQUksRUFBRSxFQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLE9BQU8sQ0FBQyxRQUFRLEVBQUUsRUFBQyxFQUMzQyxHQUFHLENBQUMsT0FBTyxFQUFFLEVBQUMsS0FBSyxFQUFFLHNDQUFzQyxFQUFDLEVBQ3hELEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUNqQztZQUFDLE9BQU8sQ0FBVSxFQUFFO2dCQUNqQixJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO2dCQUMvQyxNQUFNLENBQUMsQ0FBQzthQUNYO1lBRUQsMEVBQTBFO1lBQzFFLE1BQU0sNEJBQTRCLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQzlELElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FDeEMsQ0FBQztZQUVGLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLDRCQUE0QixDQUFDLENBQUM7WUFFL0MsT0FBTyxxQkFBcUIsQ0FBQztRQUNqQyxDQUFDO0tBQUE7SUFFYSxnQkFBZ0IsQ0FBQyxPQUFZLEVBQUUsSUFBeUI7O1lBQ2xFLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRTtnQkFDbkMsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQ0FBb0MsR0FBRyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQzthQUNyRjtZQUNELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMscUJBQXFCLENBQUMsT0FBTyxDQUFDO1lBQ25FLE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLFFBQVEsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDL0YsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLE9BQU8sQ0FDakMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FDaEYsQ0FBQztZQUVGLElBQUk7Z0JBQ0EsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FDakQsR0FBRyxDQUFDLFVBQVUsRUFBRSxFQUFDLElBQUksRUFBRSxPQUFPLENBQUMsUUFBUSxFQUFFLEVBQUUsRUFBRSxFQUFFLFdBQVcsQ0FBQyxRQUFRLEVBQUUsRUFBQyxFQUNsRSxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUMsS0FBSyxFQUFFLGdDQUFnQyxFQUFDLENBQUMsQ0FDdEQsQ0FDSixDQUFDO2FBQ0w7WUFBQyxPQUFPLENBQVUsRUFBRTtnQkFDakIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsOENBQThDLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ3pFLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7Z0JBQzdELE1BQU0sQ0FBQyxDQUFDO2FBQ1g7WUFFRCxNQUFNLGdCQUFnQixHQUFHLE1BQU0saUJBQWlCLENBQUM7WUFDakQsSUFBSSxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ3BDLE1BQU0sSUFBSSxLQUFLLENBQUMsc0JBQXNCLEdBQUcsZ0JBQWdCLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQzthQUN6RTtZQUVELElBQUksSUFBSSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDdEMsSUFBSSxDQUFDLElBQUksRUFBRTtnQkFDUCxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ3BELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO2FBQzNEO1lBRUQsT0FBTyxFQUFDLGdCQUFnQixFQUFFLElBQUksRUFBQyxDQUFDO1FBQ3BDLENBQUM7S0FBQTtJQUVLLFFBQVEsQ0FBQyxXQUFnQjs7WUFDM0IsT0FBTyxDQUFDLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQzNELENBQUM7S0FBQTtJQUVLLGFBQWE7O1lBQ2YsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxXQUFXLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzdGLE1BQU0sRUFBRSxHQUFHLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUUzQyxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUM7WUFFbEIsSUFBSSxpQkFBaUIsR0FBRyxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMscUJBQXFCLENBQUMsTUFBTSxDQUMzRSxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxFQUFDLEVBQ3hELEdBQUcsQ0FBQyxPQUFPLEVBQUUsRUFBQyxLQUFLLEVBQUUsc0JBQXNCLENBQUMsV0FBVyxFQUFDLENBQUMsQ0FDNUQsQ0FDSixDQUFDO1lBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxnQ0FBZ0MsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7WUFHekUsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLDRCQUE0QixDQUFDLGlCQUFpQixDQUFDLENBQUM7WUFDckUsT0FBTyxTQUFTLElBQUksU0FBUyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRTtnQkFDNUMsTUFBTSxnQkFBZ0IsR0FBRyxTQUFTLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUN4RCxpQkFBaUIsR0FBRyxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMscUJBQXFCLENBQUMsTUFBTSxDQUN2RSxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxFQUFDLEVBQ3hELEdBQUcsQ0FBQyxPQUFPLEVBQUUsRUFBQyxLQUFLLEVBQUUsc0JBQXNCLENBQUMsV0FBVyxFQUFDLEVBQ3BELEdBQUcsQ0FBQyxLQUFLLEVBQUUsRUFBQyxLQUFLLEVBQUUsZ0NBQWdDLEVBQUMsRUFDaEQsR0FBRyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxDQUFDLEVBQ25CLEdBQUcsQ0FBQyxPQUFPLEVBQUUsRUFBRSxFQUFFLGdCQUFnQixDQUFDLENBQ3JDLENBQ0osQ0FDSixDQUNKLENBQUM7Z0JBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxnQ0FBZ0MsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7Z0JBQ3pFLFNBQVMsR0FBRyxJQUFJLENBQUMsNEJBQTRCLENBQUMsaUJBQWlCLENBQUMsQ0FBQzthQUNwRTtZQUNELE9BQU8sTUFBTSxDQUFDO1FBQ2xCLENBQUM7S0FBQTtJQUVPLGdDQUFnQyxDQUFDLEVBQW9COztRQUN6RCxPQUFPLENBQUEsTUFBQSxNQUFBLEVBQUU7YUFDSixRQUFRLENBQUMsT0FBTyxFQUFFLHNCQUFzQixDQUFDLFdBQVcsQ0FBQywwQ0FDcEQsV0FBVyxDQUFDLE1BQU0sQ0FBQywwQ0FDbkIsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFJLEVBQUUsQ0FBQztJQUN4QyxDQUFDO0lBRU8sNEJBQTRCLENBQUMsRUFBb0I7O1FBQ3JELE9BQU8sTUFBQSxFQUFFO2FBQ0osUUFBUSxDQUFDLE9BQU8sRUFBRSxzQkFBc0IsQ0FBQyxXQUFXLENBQUMsMENBQ3BELFFBQVEsQ0FBQyxLQUFLLEVBQUUsZ0NBQWdDLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0csZUFBZSxDQUFDLFdBQW1COztZQUNyQyxNQUFNLG9CQUFvQixHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztnQkFDM0MsSUFBSSxDQUFDLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsNEJBQTRCLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUMsQ0FBQztnQkFDM0csSUFBSSxDQUFDLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsNEJBQTRCLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQztnQkFDNUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsNEJBQTRCLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUMsQ0FBQztnQkFDM0csSUFBSSxDQUFDLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsNEJBQTRCLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQzthQUNoSCxDQUFDLENBQUM7WUFDSCxJQUFJLE9BQU8sR0FBcUIsRUFBRSxDQUFDO1lBQ25DLEtBQUssTUFBTSxtQkFBbUIsSUFBSSxvQkFBb0IsRUFBRTtnQkFDcEQsTUFBTSx3QkFBd0IsR0FBRyxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQztxQkFDckYsR0FBRyxDQUFDLENBQUMsVUFBbUIsRUFBRSxFQUFFLENBQUMsQ0FBQztvQkFDM0IsR0FBRyxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsR0FBRztvQkFDekIsSUFBSSxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsSUFBSTtvQkFDM0IsV0FBVyxFQUFFLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQztpQkFDeEUsQ0FBQyxDQUFDLENBQUM7Z0JBQ1IsT0FBTyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsd0JBQXdCLENBQUMsQ0FBQzthQUN0RDtZQUVELE9BQU8sT0FBTyxDQUFDO1FBQ25CLENBQUM7S0FBQTtJQUVPLHFCQUFxQixDQUFDLEtBQWE7UUFDdkMsSUFBSSxDQUFDLEtBQUssSUFBSSxLQUFLLEtBQUssTUFBTSxFQUFFO1lBQzVCLE9BQU8sV0FBVyxDQUFDLElBQUksQ0FBQztTQUMzQjthQUFNLElBQUksS0FBSyxLQUFLLFFBQVEsRUFBRTtZQUMzQixPQUFPLFdBQVcsQ0FBQyxNQUFNLENBQUM7U0FDN0I7YUFBTSxJQUFJLEtBQUssS0FBSyxPQUFPLEVBQUU7WUFDMUIsT0FBTyxXQUFXLENBQUMsS0FBSyxDQUFDO1NBQzVCO2FBQU0sSUFBSSxLQUFLLEtBQUssT0FBTyxFQUFFO1lBQzFCLE9BQU8sV0FBVyxDQUFDLEtBQUssQ0FBQztTQUM1QjthQUFNLElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRTtZQUM1QixPQUFPLFdBQVcsQ0FBQyxPQUFPLENBQUM7U0FDOUI7YUFBTTtZQUNILE1BQU0sT0FBTyxHQUFHLHlCQUF5QixHQUFHLEtBQUssQ0FBQztZQUNsRCxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUMvQixNQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQzVCO0lBQ0wsQ0FBQztJQUVLLGdCQUFnQixDQUFDLE9BQWUsRUFBRSxHQUFXLEVBQUUsV0FBd0IsRUFBRSxJQUFhOztZQUN4RixPQUFPLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQzFELDZCQUE2QixDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFDLEdBQUcsRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQyxDQUMzRSxDQUFDO1FBQ04sQ0FBQztLQUFBO0lBRUssV0FBVyxDQUFDLElBQVUsRUFBRSxJQUFZLEVBQUUsTUFBZTs7WUFDdkQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDM0UsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN4QyxNQUFNLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLDBCQUEwQixDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQztnQkFDcEcsQ0FBQyxDQUFDLGFBQWEsQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBRWxFLEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLEVBQUU7Z0JBQy9DLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO2FBQy9DO1lBRUQsT0FBTyxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDcEYsQ0FBQztLQUFBO0lBRU8sdUJBQXVCLENBQUMsb0JBQTJDO1FBQ3ZFLE9BQU8sQ0FBQyxHQUFHLG9CQUFvQixDQUFDLE9BQU8sRUFBRSxDQUFDO2FBQ3JDLEdBQUcsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLEVBQUUsbUJBQW1CLENBQUMsRUFBRSxFQUFFLENBQzdDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsRUFBQyxHQUFHLEVBQUUsZ0JBQWdCLEVBQUMsRUFDaEMsR0FBRyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvRSxDQUFDO0lBRU8sMkJBQTJCLENBQUMsTUFBaUI7UUFDakQsTUFBTSxPQUFPLEdBQUcsTUFBTTthQUNqQixNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxRQUFRLENBQUM7YUFDOUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBRTtZQUNiLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBYTtZQUN6QixLQUFLLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUNqRCxDQUFDLENBQUM7UUFFakIsT0FBTyxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRU8sK0JBQStCLENBQ25DLGNBQTZDLEVBQzdDLE9BQTRCO1FBRTVCLE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3hDLE9BQU87YUFDRixHQUFHLENBQUMsc0JBQXNCLEVBQUUsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDO2FBQzdFLEdBQUcsQ0FBQywyQkFBMkIsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7YUFDOUQsR0FBRyxDQUFDLDRCQUE0QixFQUFFLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQzthQUNwRSxHQUFHLENBQUMsK0JBQStCLEVBQUUsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFaEYsSUFBSSxPQUFPLENBQUMsaUJBQWlCLEtBQUssU0FBUyxFQUFFO1lBQ3pDLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7U0FDdkY7UUFFRCxPQUFPLE9BQU8sQ0FBQztJQUNuQixDQUFDO0lBRU8sbUJBQW1CLENBQUMsTUFBYzs7UUFDdEMsT0FBTyxNQUFNLENBQUMsSUFBSSxLQUFLLFNBQVMsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxXQUFXLElBQUksQ0FBQyxDQUFDLENBQUEsTUFBQSxNQUFNLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQywwQ0FBRSxJQUFJLEVBQUUsQ0FBQSxDQUFDO0lBQ25ILENBQUM7SUFFTyx1QkFBdUIsQ0FBQyxhQUFxQixFQUFFLG1CQUE0QjtRQUMvRSxNQUFNLFlBQVksR0FBRyxtQkFBbUIsYUFBbkIsbUJBQW1CLGNBQW5CLG1CQUFtQixHQUFJLGFBQWEsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDNUUsTUFBTSxRQUFRLEdBQUcsQ0FBQSxZQUFZLGFBQVosWUFBWSx1QkFBWixZQUFZLENBQUUsS0FBSyxDQUFDLEtBQUs7WUFDdEMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDO1lBQ3BDLENBQUMsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLDJDQUEyQyxDQUFDO1FBRTdELE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7UUFDNUMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNQLDhFQUE4RTtZQUM5RSw4RUFBOEU7WUFDOUUsOEJBQThCO1lBQzlCLGdDQUFnQztZQUNoQyw2QkFBNkI7WUFDN0IsbURBQW1EO1lBQ25ELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLHFDQUFxQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ3BGLE9BQU8sS0FBSyxDQUFDO1NBQ2hCO1FBRUQsTUFBTSxPQUFPLEdBQWdCO1lBQ3pCLElBQUksRUFBRSxhQUFhLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRTtZQUMvQyxRQUFRO1lBQ1IsRUFBRSxFQUFFLGFBQWEsQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUMxQixJQUFJO1lBQ0osU0FBUyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRTtZQUN2RSxPQUFPLEVBQUUsQ0FBQyxDQUFDLFlBQVk7WUFDdkIsV0FBVyxFQUFFLG1CQUFtQixJQUFJLElBQUk7U0FDM0MsQ0FBQztRQUVGLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxvQkFBb0IsRUFBRSxDQUFDO1FBQ3hELEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLEVBQUU7WUFDL0MsTUFBTSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxhQUFhLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztTQUM1RTtRQUNELElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLEVBQUU7WUFDL0IsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUM1QjtRQUVELElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFO1lBQ2xCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQzVCO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVELFlBQVksQ0FBQyxHQUFRO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3pFLENBQUM7SUFFRCxHQUFHO1FBQ0MsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRCxNQUFNO1FBQ0YsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRCxJQUFJO1FBQ0EsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRCxJQUFJO1FBQ0EsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRCxJQUFJO1FBQ0EsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRCxJQUFJO1FBQ0EsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ2pCLENBQUM7SUFFRCxLQUFLO1FBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRCxLQUFLO1FBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO0lBQ2xELENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGppZCBhcyBwYXJzZUppZCwgeG1sIH0gZnJvbSAnQHhtcHAvY2xpZW50JztcclxuaW1wb3J0IHsgSklEIH0gZnJvbSAnQHhtcHAvamlkJztcclxuaW1wb3J0IHsgRWxlbWVudCB9IGZyb20gJ2x0eCc7XHJcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBDb250YWN0TWV0YWRhdGEgfSBmcm9tICcuLi8uLi8uLi8uLi9jb3JlL2NvbnRhY3QnO1xyXG5pbXBvcnQgeyBkdW1teUF2YXRhclJvb20gfSBmcm9tICcuLi8uLi8uLi8uLi9jb3JlL2NvbnRhY3QtYXZhdGFyJztcclxuaW1wb3J0IHsgRGlyZWN0aW9uLCBNZXNzYWdlIH0gZnJvbSAnLi4vLi4vLi4vLi4vY29yZS9tZXNzYWdlJztcclxuaW1wb3J0IHsgRGF0ZU1lc3NhZ2VzR3JvdXAsIE1lc3NhZ2VTdG9yZSB9IGZyb20gJy4uLy4uLy4uLy4uL2NvcmUvbWVzc2FnZS1zdG9yZSc7XHJcbmltcG9ydCB7IGlzSmlkLCBSZWNpcGllbnQgfSBmcm9tICcuLi8uLi8uLi8uLi9jb3JlL3JlY2lwaWVudCc7XHJcbmltcG9ydCB7IElxUmVzcG9uc2VTdGFuemEsIFN0YW56YSB9IGZyb20gJy4uLy4uLy4uLy4uL2NvcmUvc3RhbnphJztcclxuaW1wb3J0IHsgTG9nU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL2xvZy5zZXJ2aWNlJztcclxuaW1wb3J0IHsgQWJzdHJhY3RTdGFuemFCdWlsZGVyIH0gZnJvbSAnLi4vYWJzdHJhY3Qtc3RhbnphLWJ1aWxkZXInO1xyXG5pbXBvcnQgeyBTdGFuemFCdWlsZGVyIH0gZnJvbSAnLi4vc3RhbnphLWJ1aWxkZXInO1xyXG5pbXBvcnQgeyBYbXBwQ2hhdEFkYXB0ZXIgfSBmcm9tICcuLi94bXBwLWNoYXQtYWRhcHRlci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgQWJzdHJhY3RYbXBwUGx1Z2luIH0gZnJvbSAnLi9hYnN0cmFjdC14bXBwLXBsdWdpbic7XHJcbmltcG9ydCB7IE1lc3NhZ2VSZWNlaXZlZEV2ZW50IH0gZnJvbSAnLi9tZXNzYWdlLnBsdWdpbic7XHJcbmltcG9ydCB7IFNlcnZpY2VEaXNjb3ZlcnlQbHVnaW4gfSBmcm9tICcuL3NlcnZpY2UtZGlzY292ZXJ5LnBsdWdpbic7XHJcblxyXG4vKipcclxuICogc2VlOlxyXG4gKiBodHRwczovL3htcHAub3JnL2V4dGVuc2lvbnMveGVwLTAwNDUuaHRtbCN0ZXJtcy1yb29tc1xyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBSb29tQ3JlYXRpb25PcHRpb25zIHtcclxuICAgIG5hbWU/OiBzdHJpbmc7XHJcbiAgICByb29tSWQ6IHN0cmluZztcclxuICAgIC8qKlxyXG4gICAgICogQSByb29tIHRoYXQgY2FuIGJlIGZvdW5kIGJ5IGFueSB1c2VyIHRocm91Z2ggbm9ybWFsIG1lYW5zIHN1Y2ggYXMgc2VhcmNoaW5nIGFuZCBzZXJ2aWNlIGRpc2NvdmVyeVxyXG4gICAgICovXHJcbiAgICBwdWJsaWM6IGJvb2xlYW47XHJcbiAgICAvKipcclxuICAgICAqIGZvciB0cnVlOlxyXG4gICAgICogQSByb29tIHRoYXQgYSB1c2VyIGNhbm5vdCBlbnRlciB3aXRob3V0IGJlaW5nIG9uIHRoZSBtZW1iZXIgbGlzdC5cclxuICAgICAqIGZvciBmYWxzZTpcclxuICAgICAqIEEgcm9vbSB0aGF0IG5vbi1iYW5uZWQgZW50aXRpZXMgYXJlIGFsbG93ZWQgdG8gZW50ZXIgd2l0aG91dCBiZWluZyBvbiB0aGUgbWVtYmVyIGxpc3QuXHJcbiAgICAgKi9cclxuICAgIG1lbWJlcnNPbmx5OiBib29sZWFuO1xyXG4gICAgLyoqXHJcbiAgICAgKiBmb3IgdHJ1ZTpcclxuICAgICAqIEEgcm9vbSBpbiB3aGljaCBhbiBvY2N1cGFudCdzIGZ1bGwgSklEIGlzIGV4cG9zZWQgdG8gYWxsIG90aGVyIG9jY3VwYW50cyxcclxuICAgICAqIGFsdGhvdWdoIHRoZSBvY2N1cGFudCBjYW4gcmVxdWVzdCBhbnkgZGVzaXJlZCByb29tIG5pY2tuYW1lLlxyXG4gICAgICogZm9yIGZhbHNlOlxyXG4gICAgICogQSByb29tIGluIHdoaWNoIGFuIG9jY3VwYW50J3MgZnVsbCBKSUQgY2FuIGJlIGRpc2NvdmVyZWQgYnkgcm9vbSBhZG1pbnMgb25seS5cclxuICAgICAqL1xyXG4gICAgbm9uQW5vbnltb3VzOiBib29sZWFuO1xyXG4gICAgLyoqXHJcbiAgICAgKiBmb3IgdHJ1ZTpcclxuICAgICAqIEEgcm9vbSB0aGF0IGlzIG5vdCBkZXN0cm95ZWQgaWYgdGhlIGxhc3Qgb2NjdXBhbnQgZXhpdHMuXHJcbiAgICAgKiBmb3IgZmFsc2U6XHJcbiAgICAgKiBBIHJvb20gdGhhdCBpcyBkZXN0cm95ZWQgaWYgdGhlIGxhc3Qgb2NjdXBhbnQgZXhpdHMuXHJcbiAgICAgKi9cclxuICAgIHBlcnNpc3RlbnRSb29tOiBib29sZWFuO1xyXG4gICAgLyoqXHJcbiAgICAgKiBPcHRpb25hbCBuYW1lIGZvciB0aGUgcm9vbSwgaWYgbm8gcHJvdmlkZWQgcm9vbSB3aWxsIGJlIG9ubHkgaWRlbnRpZmllZCBieSBpdHMgamlkXHJcbiAgICAgKi9cclxuICAgIG5pY2s/OiBzdHJpbmc7XHJcbiAgICAvKipcclxuICAgICAqIGFsbG93IGVqYWJiZXJkIE11Y1N1YiBzdWJzY3JpcHRpb25zLlxyXG4gICAgICogUm9vbSBvY2N1cGFudHMgYXJlIGFsbG93ZWQgdG8gc3Vic2NyaWJlIHRvIG1lc3NhZ2Ugbm90aWZpY2F0aW9ucyBiZWluZyBhcmNoaXZlZCB3aGlsZSB0aGV5IHdlcmUgb2ZmbGluZVxyXG4gICAgICovXHJcbiAgICBhbGxvd1N1YnNjcmlwdGlvbj86IGJvb2xlYW47XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgUm9vbU1lc3NhZ2UgZXh0ZW5kcyBNZXNzYWdlIHtcclxuICAgIGZyb206IEpJRDtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBPY2N1cGFudCB7XHJcbiAgICByb29tSmlkOiBKSUQ7XHJcbiAgICByZWFsSmlkPzogSklEO1xyXG4gICAgbWV0YWRhdGE6IENvbnRhY3RNZXRhZGF0YTtcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBSb29tTWV0YWRhdGEge1xyXG4gICAgW2tleTogc3RyaW5nXTogYW55O1xyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgUm9vbSB7XHJcblxyXG4gICAgcmVhZG9ubHkgcmVjaXBpZW50VHlwZSA9ICdyb29tJztcclxuICAgIHJlYWRvbmx5IHJvb21KaWQ6IEpJRDtcclxuICAgIG9jY3VwYW50SmlkOiBKSUQ7XHJcbiAgICBuYW1lOiBzdHJpbmc7XHJcbiAgICBuaWNrOnN0cmluZztcclxuICAgIGF2YXRhciA9IGR1bW15QXZhdGFyUm9vbTtcclxuICAgIG1ldGFkYXRhOiBSb29tTWV0YWRhdGEgPSB7fTtcclxuICAgIHByaXZhdGUgbWVzc2FnZVN0b3JlOiBNZXNzYWdlU3RvcmU8Um9vbU1lc3NhZ2U+O1xyXG5cclxuICAgIGdldCBqaWRCYXJlKCk6IEpJRCB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMucm9vbUppZDtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdHJ1Y3RvcihvY2N1cGFudEppZDogSklELCBsb2dTZXJ2aWNlOiBMb2dTZXJ2aWNlLCBuYW1lPzogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgdGhpcy5yb29tSmlkID0gb2NjdXBhbnRKaWQuYmFyZSgpO1xyXG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWUgPz8gb2NjdXBhbnRKaWQuYmFyZSgpLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgdGhpcy5uaWNrID0gbmFtZSA/PyBvY2N1cGFudEppZC5iYXJlKCkudG9TdHJpbmcoKTtcclxuICAgICAgICB0aGlzLm9jY3VwYW50SmlkID0gb2NjdXBhbnRKaWQ7XHJcbiAgICAgICAgdGhpcy5tZXNzYWdlU3RvcmUgPSBuZXcgTWVzc2FnZVN0b3JlPFJvb21NZXNzYWdlPihsb2dTZXJ2aWNlKTtcclxuICAgIH1cclxuXHJcbiAgICBnZXQgbWVzc2FnZXMkKCk6IFN1YmplY3Q8Um9vbU1lc3NhZ2U+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlU3RvcmUubWVzc2FnZXMkO1xyXG4gICAgfVxyXG5cclxuICAgIGdldCBtZXNzYWdlcygpOiBSb29tTWVzc2FnZVtdIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlU3RvcmUubWVzc2FnZXM7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IGRhdGVNZXNzYWdlc0dyb3VwcygpOiBEYXRlTWVzc2FnZXNHcm91cDxSb29tTWVzc2FnZT5bXSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZVN0b3JlLmRhdGVNZXNzYWdlR3JvdXBzO1xyXG4gICAgfVxyXG5cclxuICAgIGdldCBvbGRlc3RNZXNzYWdlKCk6IFJvb21NZXNzYWdlIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlU3RvcmUub2xkZXN0TWVzc2FnZTtcclxuICAgIH1cclxuXHJcbiAgICBnZXQgbW9zdFJlY2VudE1lc3NhZ2UoKTogUm9vbU1lc3NhZ2Uge1xyXG4gICAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2VTdG9yZS5tb3N0UmVjZW50TWVzc2FnZTtcclxuICAgIH1cclxuXHJcbiAgICBnZXQgbW9zdFJlY2VudE1lc3NhZ2VSZWNlaXZlZCgpOiBSb29tTWVzc2FnZSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZVN0b3JlLm1vc3RSZWNlbnRNZXNzYWdlUmVjZWl2ZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IG1vc3RSZWNlbnRNZXNzYWdlU2VudCgpOiBSb29tTWVzc2FnZSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZVN0b3JlLm1vc3RSZWNlbnRNZXNzYWdlU2VudDtcclxuICAgIH1cclxuXHJcbiAgICBhZGRNZXNzYWdlKG1lc3NhZ2U6IFJvb21NZXNzYWdlKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5tZXNzYWdlU3RvcmUuYWRkTWVzc2FnZShtZXNzYWdlKTtcclxuICAgIH1cclxuXHJcbiAgICBlcXVhbHNCYXJlSmlkKG90aGVyOiBSZWNpcGllbnQgfCBKSUQpOiBib29sZWFuIHtcclxuICAgICAgICBpZiAob3RoZXIgaW5zdGFuY2VvZiBSb29tIHx8IGlzSmlkKG90aGVyKSkge1xyXG4gICAgICAgICAgICBjb25zdCBvdGhlckppZCA9IG90aGVyIGluc3RhbmNlb2YgUm9vbSA/IG90aGVyLnJvb21KaWQgOiBvdGhlci5iYXJlKCk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJvb21KaWQuYmFyZSgpLmVxdWFscyhvdGhlckppZCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbn1cclxuXHJcbmV4cG9ydCBlbnVtIEFmZmlsaWF0aW9uIHtcclxuICAgIG5vbmUsXHJcbiAgICBtZW1iZXIsXHJcbiAgICBhZG1pbixcclxuICAgIG93bmVyLFxyXG4gICAgb3V0Y2FzdFxyXG59XHJcblxyXG5jbGFzcyBRdWVyeU1lbWJlckxpc3RTdGFuemFCdWlsZGVyIGV4dGVuZHMgQWJzdHJhY3RTdGFuemFCdWlsZGVyIHtcclxuXHJcbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHJvb21KaWQ6IHN0cmluZywgcHJpdmF0ZSByZWFkb25seSBhZmZpbGlhdGlvbjogc3RyaW5nKSB7XHJcbiAgICAgICAgc3VwZXIoKTtcclxuICAgIH1cclxuXHJcbiAgICBzdGF0aWMgYnVpbGQocm9vbUppZDogc3RyaW5nLCBhZmZpbGlhdGlvbjogc3RyaW5nKTogU3RhbnphIHtcclxuICAgICAgICByZXR1cm4gbmV3IFF1ZXJ5TWVtYmVyTGlzdFN0YW56YUJ1aWxkZXIocm9vbUppZCwgYWZmaWxpYXRpb24pLnRvU3RhbnphKCk7XHJcbiAgICB9XHJcblxyXG4gICAgdG9TdGFuemEoKTogU3RhbnphIHtcclxuICAgICAgICByZXR1cm4geG1sKCdpcScsIHt0eXBlOiAnZ2V0JywgdG86IHRoaXMucm9vbUppZH0sXHJcbiAgICAgICAgICAgIHhtbCgncXVlcnknLCB7eG1sbnM6ICdodHRwOi8vamFiYmVyLm9yZy9wcm90b2NvbC9tdWMjYWRtaW4nfSxcclxuICAgICAgICAgICAgICAgIHhtbCgnaXRlbScsIHthZmZpbGlhdGlvbjogdGhpcy5hZmZpbGlhdGlvbn0pLFxyXG4gICAgICAgICAgICApLFxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIE1lbWJlckxpc3RJdGVtIHtcclxuICAgIGppZDogc3RyaW5nO1xyXG4gICAgYWZmaWxpYXRpb246IEFmZmlsaWF0aW9uO1xyXG4gICAgbmljaz86IHN0cmluZztcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBSb29tU3VtbWFyeSB7XHJcbiAgICBqaWQ6IHN0cmluZztcclxuICAgIG5hbWU6IHN0cmluZztcclxufVxyXG5cclxuY2xhc3MgTW9kaWZ5TWVtYmVyTGlzdFN0YW56YUJ1aWxkZXIgZXh0ZW5kcyBBYnN0cmFjdFN0YW56YUJ1aWxkZXIge1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgcm9vbUppZDogc3RyaW5nLCBwcml2YXRlIHJlYWRvbmx5IG1vZGlmaWNhdGlvbnM6IHJlYWRvbmx5IE1lbWJlckxpc3RJdGVtW10pIHtcclxuICAgICAgICBzdXBlcigpO1xyXG4gICAgfVxyXG5cclxuICAgIHN0YXRpYyBidWlsZChyb29tSmlkOiBzdHJpbmcsIG1vZGlmaWNhdGlvbnM6IHJlYWRvbmx5IE1lbWJlckxpc3RJdGVtW10pOiBTdGFuemEge1xyXG4gICAgICAgIHJldHVybiBuZXcgTW9kaWZ5TWVtYmVyTGlzdFN0YW56YUJ1aWxkZXIocm9vbUppZCwgbW9kaWZpY2F0aW9ucykudG9TdGFuemEoKTtcclxuICAgIH1cclxuXHJcbiAgICB0b1N0YW56YSgpOiBTdGFuemEge1xyXG4gICAgICAgIHJldHVybiB4bWwoJ2lxJywge3RvOiB0aGlzLnJvb21KaWQsIHR5cGU6ICdzZXQnfSxcclxuICAgICAgICAgICAgeG1sKCdxdWVyeScsIHt4bWxuczogJ2h0dHA6Ly9qYWJiZXIub3JnL3Byb3RvY29sL211YyNhZG1pbid9LFxyXG4gICAgICAgICAgICAgICAgLi4udGhpcy5tb2RpZmljYXRpb25zLm1hcChtb2RpZmljYXRpb24gPT4gdGhpcy5idWlsZEl0ZW0obW9kaWZpY2F0aW9uK