UNPKG

gamelet-cli

Version:

Download project from code.gamelet.com, edit/test in vscode and sync back to server.

276 lines 21.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GameroomBase = void 0; const Message_1 = require("../messages/Message"); const ArrayUtil_1 = require("./../utils/ArrayUtil"); const events_1 = require("events"); const MonitorManager_1 = require("../managers/MonitorManager"); class GameroomBase extends events_1.EventEmitter { constructor(roomType, code, server, client, stateJson) { super(); this.roomType = roomType; this.code = code; this.server = server; this.client = client; this.stateJson = stateJson; this.players = []; // private states for each player, playerCode: object this.playerStates = {}; this.createTime = Math.floor(Date.now() / 1000); this.stateJson = this.stateJson || {}; } setFpsDirty() { this.ping = null; } getPing() { if (!this.ping) { if (this.players.length) { let min = 9999; let max = 0; let total = 0; for (let p of this.players) { min = Math.min(min, p.networkDelay); max = Math.max(max, p.networkDelay); total += p.networkDelay; } this.ping = { min: min, max: max, avg: Math.round(total / this.players.length), }; } else { this.ping = { min: 0, max: 0, avg: 0, }; } } return this.ping; } get monitorChannel() { return this.code; } dispose() { this.listPlayers().forEach(player => this.removePlayer(player)); this.emit(GameroomBase.EVENT.DISPOSED); MonitorManager_1.monitorManager.log(this.client.project.code, this.monitorChannel, this.roomType + ' disposed', this.code); } setPlayerSynced(player, value, updateBrainer) { let promise; if (this.setPlayerState(player, 'synced', value, false)) { if (updateBrainer) { promise = this.updateBrainer(true); } } return (promise || Promise.resolve()).then(() => { this.emit(GameroomBase.EVENT.PLAYER_SYNCED_CHANGED, player, value, this.brainer.code); }); } isPlayerSynced(player) { return !!this.getPlayerState(player, 'synced'); } setPlayerState(player, key, value, emitEvent = true) { if (this.players.includes(player)) { let states = this.playerStates[player.code]; if (!states) { this.playerStates[player.code] = states = {}; } if (this._setPlayerState(states, key, value)) { emitEvent && this.emit(GameroomBase.EVENT.PLAYER_STATE_CHANGED, player, key, value); return true; } } else { throw new Error('Tried to set player state of a player who is not in this ' + this.roomType); } return false; } _setPlayerState(states, key, value) { if (states[key] !== value) { if (value === undefined || value === null) { value = null; delete states[key]; } else { states[key] = value; } return true; } return false; } setPlayerStates(player, newStates) { if (this.players.includes(player)) { let result = false; if (newStates) { let states = this.playerStates[player.code]; if (!states) { this.playerStates[player.code] = states = {}; } for (let key in newStates) { if (this._setPlayerState(states, key, newStates[key])) { result = true; } } } else if (this.playerStates[player.code]) { result = true; this.deletePlayerState(player); } if (result) { this.emit(GameroomBase.EVENT.PLAYER_STATES_CHANGED, player, newStates); } } else { throw new Error('Tried to set player state of a player who is not in this ' + this.roomType); } return false; } getPlayer(code) { return this.players.find(p => p.code == code); } includesPlayer(player) { return this.players.includes(player); } getPlayerState(player, key) { let state = this.playerStates[player.code]; return state && state[key]; } getPlayerStates(player) { return this.playerStates[player.code]; } deletePlayerState(player) { if (this.playerStates[player.code]) { delete this.playerStates[player.code]; return true; } else { return false; } } listPlayers() { return this.players.slice(); } getPlayersStates() { return this.playerStates; } get playersCount() { return this.players.length; } get socketChannel() { return this.code; } addPlayer(player) { if (ArrayUtil_1.ArrayUtil.addUniqueElement(this.players, player)) { this.setFpsDirty(); if (!this.brainer) { this.updateBrainer(false); } player.socket.join(this.socketChannel); this.emit(GameroomBase.EVENT.PLAYER_ADDED, player); this.emit(GameroomBase.EVENT.STATUS_CHANGED); return true; } return false; } removePlayer(player) { if (ArrayUtil_1.ArrayUtil.removeElement(this.players, player)) { this.setFpsDirty(); player.socket.leave(this.socketChannel); if (this.deletePlayerState(player)) { this.emit(GameroomBase.EVENT.PLAYER_STATES_CHANGED, player, null); } if (player == this.brainer) { // must do this before we send playerLeft event this.updateBrainer(false); } this.emit(GameroomBase.EVENT.STATUS_CHANGED); this.emit(GameroomBase.EVENT.PLAYER_REMOVED, player); return true; } return false; } setBrainerByPlayer(playerCode, needPreset) { let brainer = this.players.find(p => p.code == playerCode); if (!brainer) { throw new Error('The player is not in room.'); } return this._setBrainer(brainer, needPreset); } updateBrainer(needPreset) { return this._setBrainer(this.chooseBrainer(), needPreset); } _setBrainer(brainer, needPreset) { if (brainer != this.brainer) { if (needPreset) { return brainer.send(Message_1.Message.forRoomBrainerSet(this.code)) .then(() => { this.brainer = brainer; this.emit(GameroomBase.EVENT.BRAINER_CHANGED); return this.brainer; }); } else { this.brainer = brainer; this.emit(GameroomBase.EVENT.BRAINER_CHANGED); } } return Promise.resolve(this.brainer); } chooseBrainer() { if (this.players.length) { let idleStart = Date.now() - 10000; let brainer = this.players[0]; let bestDelay = this.calcNetworkDelayValue(brainer, idleStart); for (let i = this.players.length - 1; i > 0; --i) { let player = this.players[i]; if (this.isPlayerSynced(player)) { let delay = this.calcNetworkDelayValue(player, idleStart); if (player.cheats) { delay += 500; } if (delay < bestDelay) { brainer = player; bestDelay = delay; } } } return brainer; } return null; } /** * network delay + idle factor */ calcNetworkDelayValue(player, idleStart) { let value = player.networkDelay; if (idleStart > player.lastMsgTime) { value += (idleStart - player.lastMsgTime) / 100; } return value; } getBrainer() { return this.brainer; } broadcast(msg) { MonitorManager_1.monitorManager.logOutgoing(this.client.project.code, this.monitorChannel, this.roomType + '.broadcast', [this.code, msg.type, msg.params]); msg.send(this.server.to(this.socketChannel)); } broadcastByPlayer(msg, sender) { MonitorManager_1.monitorManager.logIncoming(this.client.project.code, this.monitorChannel, this.roomType + '.broadcast', [this.code, msg.type, msg.params], sender); msg.send(this.server.to(this.socketChannel)); } } exports.GameroomBase = GameroomBase; GameroomBase.EVENT = { DISPOSED: 'disposed', PLAYER_ADDED: 'playerAdded', PLAYER_REMOVED: 'playerRemoved', BRAINER_CHANGED: 'brainerChanged', STATUS_CHANGED: 'statusChanged', PLAYER_STATE_CHANGED: 'playerStateChanged', PLAYER_STATES_CHANGED: 'playerStatesChanged', PLAYER_SYNCED_CHANGED: 'playerSyncedChanged', }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiR2FtZXJvb21CYXNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3NlcnZlci9lbnRpdGllcy9HYW1lcm9vbUJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsaURBQThDO0FBQzlDLG9EQUFpRDtBQUVqRCxtQ0FBc0M7QUFDdEMsK0RBQTREO0FBRTVELE1BQWEsWUFBYSxTQUFRLHFCQUFZO0lBd0IxQyxZQUFtQixRQUFnQixFQUN4QixJQUFZLEVBQ1gsTUFBMEIsRUFDM0IsTUFBYyxFQUNkLFNBQWtDO1FBRXpDLEtBQUssRUFBRSxDQUFDO1FBTk8sYUFBUSxHQUFSLFFBQVEsQ0FBUTtRQUN4QixTQUFJLEdBQUosSUFBSSxDQUFRO1FBQ1gsV0FBTSxHQUFOLE1BQU0sQ0FBb0I7UUFDM0IsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLGNBQVMsR0FBVCxTQUFTLENBQXlCO1FBYm5DLFlBQU8sR0FBYSxFQUFFLENBQUM7UUFJakMscURBQXFEO1FBQzNDLGlCQUFZLEdBQThDLEVBQUUsQ0FBQztRQUVoRSxlQUFVLEdBQVcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFTdEQsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxJQUFJLEVBQUUsQ0FBQztJQUMxQyxDQUFDO0lBRUQsV0FBVztRQUNQLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQ3JCLENBQUM7SUFFRCxPQUFPO1FBQ0gsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDWixJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFO2dCQUNyQixJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUM7Z0JBQ2YsSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDO2dCQUNaLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztnQkFDZCxLQUFLLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7b0JBQ3hCLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUM7b0JBQ3BDLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUM7b0JBQ3BDLEtBQUssSUFBSSxDQUFDLENBQUMsWUFBWSxDQUFDO2lCQUMzQjtnQkFDRCxJQUFJLENBQUMsSUFBSSxHQUFHO29CQUNSLEdBQUcsRUFBRSxHQUFHO29CQUNSLEdBQUcsRUFBRSxHQUFHO29CQUNSLEdBQUcsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztpQkFDL0MsQ0FBQzthQUNMO2lCQUFNO2dCQUNILElBQUksQ0FBQyxJQUFJLEdBQUc7b0JBQ1IsR0FBRyxFQUFFLENBQUM7b0JBQ04sR0FBRyxFQUFFLENBQUM7b0JBQ04sR0FBRyxFQUFFLENBQUM7aUJBQ1QsQ0FBQzthQUNMO1NBQ0o7UUFDRCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDckIsQ0FBQztJQUVELElBQUksY0FBYztRQUNkLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQztJQUNyQixDQUFDO0lBRUQsT0FBTztRQUNILElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDaEUsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZDLCtCQUFjLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQyxRQUFRLEdBQUcsV0FBVyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM5RyxDQUFDO0lBRUQsZUFBZSxDQUFDLE1BQWMsRUFBRSxLQUFjLEVBQUUsYUFBc0I7UUFDbEUsSUFBSSxPQUFxQixDQUFDO1FBQzFCLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsRUFBRTtZQUNyRCxJQUFJLGFBQWEsRUFBRTtnQkFDZixPQUFPLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQzthQUN0QztTQUNKO1FBQ0QsT0FBTyxDQUFDLE9BQU8sSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQzVDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxxQkFBcUIsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDMUYsQ0FBQyxDQUFDLENBQUE7SUFDTixDQUFDO0lBQ0QsY0FBYyxDQUFDLE1BQWM7UUFDekIsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUdELGNBQWMsQ0FBQyxNQUFjLEVBQUUsR0FBVyxFQUFFLEtBQVUsRUFBRSxZQUFxQixJQUFJO1FBQzdFLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDL0IsSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDNUMsSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFDVCxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxNQUFNLEdBQUcsRUFBRSxDQUFDO2FBQ2hEO1lBQ0QsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsS0FBSyxDQUFDLEVBQUU7Z0JBQzFDLFNBQVMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsb0JBQW9CLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDcEYsT0FBTyxJQUFJLENBQUM7YUFDZjtTQUNKO2FBQU07WUFDSCxNQUFNLElBQUksS0FBSyxDQUFDLDJEQUEyRCxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUNoRztRQUVELE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUM7SUFFTyxlQUFlLENBQUMsTUFBOEIsRUFBRSxHQUFXLEVBQUUsS0FBVTtRQUMzRSxJQUFJLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxLQUFLLEVBQUU7WUFDdkIsSUFBSSxLQUFLLEtBQUssU0FBUyxJQUFJLEtBQUssS0FBSyxJQUFJLEVBQUU7Z0JBQ3ZDLEtBQUssR0FBRyxJQUFJLENBQUM7Z0JBQ2IsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7YUFDdEI7aUJBQU07Z0JBQ0gsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQzthQUN2QjtZQUNELE9BQU8sSUFBSSxDQUFDO1NBQ2Y7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0lBRUQsZUFBZSxDQUFDLE1BQWMsRUFBRSxTQUFpQztRQUM3RCxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQy9CLElBQUksTUFBTSxHQUFZLEtBQUssQ0FBQztZQUM1QixJQUFJLFNBQVMsRUFBRTtnQkFDWCxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDNUMsSUFBSSxDQUFDLE1BQU0sRUFBRTtvQkFDVCxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxNQUFNLEdBQUcsRUFBRSxDQUFDO2lCQUNoRDtnQkFDRCxLQUFLLElBQUksR0FBRyxJQUFJLFNBQVMsRUFBRTtvQkFDdkIsSUFBSSxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUU7d0JBQ25ELE1BQU0sR0FBRyxJQUFJLENBQUM7cUJBQ2pCO2lCQUNKO2FBQ0o7aUJBQU0sSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRTtnQkFDdkMsTUFBTSxHQUFHLElBQUksQ0FBQztnQkFDZCxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDbEM7WUFDRCxJQUFJLE1BQU0sRUFBRTtnQkFDUixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMscUJBQXFCLEVBQUUsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDO2FBQzFFO1NBQ0o7YUFBTTtZQUNILE1BQU0sSUFBSSxLQUFLLENBQUMsMkRBQTJELEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQ2hHO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztJQUVELFNBQVMsQ0FBQyxJQUFZO1FBQ2xCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRCxjQUFjLENBQUMsTUFBYztRQUN6QixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFRCxjQUFjLENBQUMsTUFBYyxFQUFFLEdBQVc7UUFDdEMsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDMUMsT0FBTyxLQUFLLElBQUksS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFRCxlQUFlLENBQUMsTUFBYztRQUMxQixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFRCxpQkFBaUIsQ0FBQyxNQUFjO1FBQzVCLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDaEMsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN0QyxPQUFPLElBQUksQ0FBQztTQUNmO2FBQU07WUFDSCxPQUFPLEtBQUssQ0FBQztTQUNoQjtJQUNMLENBQUM7SUFFRCxXQUFXO1FBQ1AsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ2hDLENBQUM7SUFFRCxnQkFBZ0I7UUFDWixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDN0IsQ0FBQztJQUVELElBQUksWUFBWTtRQUNaLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7SUFDL0IsQ0FBQztJQUVELElBQUksYUFBYTtRQUNiLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQztJQUNyQixDQUFDO0lBRUQsU0FBUyxDQUFDLE1BQWM7UUFDcEIsSUFBSSxxQkFBUyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLEVBQUU7WUFDbEQsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ25CLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFO2dCQUNmLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7YUFDN0I7WUFDRCxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDdkMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLFlBQVksRUFBRSxNQUFNLENBQUMsQ0FBQztZQUNuRCxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDN0MsT0FBTyxJQUFJLENBQUM7U0FDZjtRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUM7SUFFRCxZQUFZLENBQUMsTUFBYztRQUN2QixJQUFJLHFCQUFTLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLEVBQUU7WUFDL0MsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ25CLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUN4QyxJQUFJLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsRUFBRTtnQkFDaEMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLHFCQUFxQixFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQzthQUNyRTtZQUVELElBQUksTUFBTSxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7Z0JBQ3hCLCtDQUErQztnQkFDL0MsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUM3QjtZQUVELElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUM3QyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsY0FBYyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ3JELE9BQU8sSUFBSSxDQUFDO1NBQ2Y7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0lBRUQsa0JBQWtCLENBQUMsVUFBa0IsRUFBRSxVQUFtQjtRQUN0RCxJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksVUFBVSxDQUFDLENBQUM7UUFDM0QsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNWLE1BQU0sSUFBSSxLQUFLLENBQUMsNEJBQTRCLENBQUMsQ0FBQztTQUNqRDtRQUNELE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDakQsQ0FBQztJQUVELGFBQWEsQ0FBQyxVQUFtQjtRQUM3QixPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQzlELENBQUM7SUFDTyxXQUFXLENBQUMsT0FBZSxFQUFFLFVBQW1CO1FBQ3BELElBQUksT0FBTyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDekIsSUFBSSxVQUFVLEVBQUU7Z0JBQ1osT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDLGlCQUFPLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO3FCQUNwRCxJQUFJLENBQUMsR0FBRyxFQUFFO29CQUNQLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO29CQUN2QixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7b0JBQzlDLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQztnQkFDeEIsQ0FBQyxDQUFDLENBQUM7YUFDVjtpQkFBTTtnQkFDSCxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztnQkFDdkIsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO2FBQ2pEO1NBQ0o7UUFDRCxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFTyxhQUFhO1FBQ2pCLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUU7WUFDckIsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLEtBQUssQ0FBQztZQUNuQyxJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzlCLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFFL0QsS0FBSyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRTtnQkFDOUMsSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDN0IsSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxFQUFFO29CQUM3QixJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQUMsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDO29CQUMxRCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUU7d0JBQ2YsS0FBSyxJQUFJLEdBQUcsQ0FBQztxQkFDaEI7b0JBQ0QsSUFBSSxLQUFLLEdBQUcsU0FBUyxFQUFFO3dCQUNuQixPQUFPLEdBQUcsTUFBTSxDQUFDO3dCQUNqQixTQUFTLEdBQUcsS0FBSyxDQUFDO3FCQUNyQjtpQkFDSjthQUNKO1lBQ0QsT0FBTyxPQUFPLENBQUM7U0FDbEI7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRUQ7O09BRUc7SUFDSyxxQkFBcUIsQ0FBQyxNQUFjLEVBQUUsU0FBaUI7UUFDM0QsSUFBSSxLQUFLLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQztRQUNoQyxJQUFJLFNBQVMsR0FBRyxNQUFNLENBQUMsV0FBVyxFQUFFO1lBQ2hDLEtBQUssSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsR0FBRyxDQUFDO1NBQ25EO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztJQUVELFVBQVU7UUFDTixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDeEIsQ0FBQztJQUVELFNBQVMsQ0FBQyxHQUFZO1FBQ2xCLCtCQUFjLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQyxRQUFRLEdBQUcsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQzNJLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDakQsQ0FBQztJQUVELGlCQUFpQixDQUFDLEdBQVksRUFBRSxNQUFjO1FBQzFDLCtCQUFjLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQyxRQUFRLEdBQUcsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNuSixHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO0lBQ2pELENBQUM7O0FBM1NMLG9DQTZTQztBQTNTVSxrQkFBSyxHQUFHO0lBQ1gsUUFBUSxFQUFFLFVBQVU7SUFDcEIsWUFBWSxFQUFFLGFBQWE7SUFDM0IsY0FBYyxFQUFFLGVBQWU7SUFDL0IsZUFBZSxFQUFFLGdCQUFnQjtJQUNqQyxjQUFjLEVBQUUsZUFBZTtJQUMvQixvQkFBb0IsRUFBRSxvQkFBb0I7SUFDMUMscUJBQXFCLEVBQUUscUJBQXFCO0lBQzVDLHFCQUFxQixFQUFFLHFCQUFxQjtDQUMvQyxDQUFBIn0=