UNPKG

@persian-caesar/discord-player

Version:

Type definitions and helpers for a Discord music player (MusicPlayer) without external dependencies

643 lines 45.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MusicPlayer = void 0; const voice_1 = require("@discordjs/voice"); const types_1 = require("./types"); const html_to_text_1 = require("html-to-text"); const ytdl_core_discord_1 = __importDefault(require("ytdl-core-discord")); const events_1 = __importDefault(require("events")); const ytdl_core_1 = __importDefault(require("ytdl-core")); const play_dl_1 = __importDefault(require("play-dl")); const ytdl_core_2 = __importDefault(require("@distube/ytdl-core")); const soundcloud_downloader_1 = __importDefault(require("soundcloud-downloader")); /** * Manages voice connection, playback, queue, history, and loop modes. * Emits events defined in MusicPlayerEvent. */ class MusicPlayer extends events_1.default { channel; // Player main data previousQueueOrder = []; connection = null; player; volume; queue = []; history = []; loopQueue = false; loopTrack = false; playing = false; autoLeaveOnEmptyQueue; autoLeaveOnIdleMs; idleTimer = null; shuffield = false; // Radio radioMode = false; radioUrls = []; // Connection connectionData = null; /** * Initializes a new MusicPlayer instance. * @param channel - Discord voice channel to connect to. * @param initialVolume - Initial volume (0–100), defaults to 100. * @param options - Options for auto-leave and idle timeout. */ constructor(channel, initialVolume = 100, options = {}) { super(); this.channel = channel; this.player = (0, voice_1.createAudioPlayer)(); // Creates a new audio player for streaming music this.volume = Math.round(initialVolume / 100); // Converts volume from percentage (0–100) to decimal (0–1) this.autoLeaveOnEmptyQueue = options.autoLeaveOnEmptyQueue ?? true; // Default: leave voice channel when queue is empty this.autoLeaveOnIdleMs = options.autoLeaveOnIdleMs ?? 5 * 60_000; // Default: 5-minute idle timeout before disconnecting this.connectionData = { channelId: channel.id, guildId: channel.guild.id, adapterCreator: channel.guild.voiceAdapterCreator, selfDeaf: true, selfMute: false, debug: false }; // Set up event listeners for error handling, idle state, and playback start this.player.on("error", err => { this.emit(types_1.MusicPlayerEvent.Error, this.createError("Player have error => " + err.message)); }); this.player.on(voice_1.AudioPlayerStatus.Idle, () => this.onIdle()); // Triggers when no audio is playing this.player.on(voice_1.AudioPlayerStatus.Playing, () => this.clearIdleTimer()); // Clears idle timer when music starts } /** * Sets the connection data for the voice channel. * @param data - Connection settings. * @returns The current MusicPlayer instance. */ setData(data) { this.connectionData = { ...data, selfDeaf: data.selfDeaf ?? true, selfMute: data.selfMute ?? false, debug: data.debug ?? false }; return this; } /** * Joins the voice channel using provided or stored connection data. * @param data - Optional connection settings; uses stored data if not provided. * @returns The VoiceConnection instance. */ join(data) { if (!data && !this.connectionData) { throw this.createError("No connection data available to join voice channel."); } const connectionData = data || this.connectionData; this.connection = (0, voice_1.joinVoiceChannel)({ channelId: connectionData.channelId, guildId: connectionData.guildId, adapterCreator: connectionData.adapterCreator, selfDeaf: connectionData.selfDeaf ?? true, selfMute: connectionData.selfMute ?? false, group: connectionData.group, debug: connectionData.debug }); this.connection.subscribe(this.player); return this.connection; } /** * Establishes a connection to the voice channel if not already connected. */ async ensureConnection() { if (!this.connection) { this.connection = this.join(); try { await (0, voice_1.entersState)(this.connection, voice_1.VoiceConnectionStatus.Ready, 20_000); } catch (e) { this.connection.destroy(); this.connection = null; this.emit(types_1.MusicPlayerEvent.Error, this.createError("Can't connect to the voice channel. => " + e.message)); } } return; } /** * Starts a timer to disconnect after inactivity. */ startIdleTimer() { if (this.autoLeaveOnIdleMs > 0 && !this.idleTimer && !this.playing) { this.idleTimer = setTimeout(() => { this.emit(types_1.MusicPlayerEvent.Disconnect); this.disconnect(); }, this.autoLeaveOnIdleMs); } } /** * Clears the idle timer if it exists. */ clearIdleTimer() { if (this.idleTimer) { clearTimeout(this.idleTimer); this.idleTimer = null; } } /** * Randomly shuffles an array. * @param array - Array to shuffle. * @returns New shuffled array. */ shuffleArray(array) { const shuffled = [...array]; for (let i = shuffled.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; } return shuffled; } /** * Searches Google for song lyrics and returns them, or null if not found. * @param title - Song title. * @param artist - Optional artist name for better accuracy. */ async searchLyrics(title, artist) { const delim1 = '</div></div></div></div><div class="hwc"><div class="BNeawe tAd8D AP7Wnd"><div><div class="BNeawe tAd8D AP7Wnd">'; const delim2 = '</div></div></div></div></div><div><span class="hwc"><div class="BNeawe uEec3 AP7Wnd">'; const GOOGLE = "https://www.google.com/search?q="; let html = ""; const query = encodeURIComponent(`${artist ? artist + " " : ""}${title}`); const attempts = [ `${GOOGLE}${query}+lyrics`, `${GOOGLE}${query}+song+lyrics`, `${GOOGLE}${query}+song`, `${GOOGLE}${query}` ]; for (const url of attempts) { try { const res = await fetch(url, { headers: { "User-Agent": "Mozilla/5.0" } }); html = await res.text(); break; } catch { continue; } } if (!html) return null; let snippet; try { [, snippet] = html.split(delim1); [snippet] = snippet.split(delim2); } catch { return null; } const rawLines = snippet.split("\n"); let lyrics = ""; for (const line of rawLines) { lyrics += (0, html_to_text_1.htmlToText)(line).trim() + "\n"; } lyrics = lyrics.trim(); return lyrics || null; } /** * Resolves a query to a track URL or returns the URL if provided. * @param query - Search query or URL. * @returns Resolved URL. */ async search(query) { if (/^https?:\/\//.test(query)) return query; const sc_results = await soundcloud_downloader_1.default.search({ query, resourceType: "tracks", limit: 1 }); let url = sc_results.collection?.[0]?.permalink_url; if (!url) { const playdl_results = await play_dl_1.default.search(query, { limit: 1, source: { spotify: "track", soundcloud: "tracks", youtube: "video", deezer: "track" } }); url = playdl_results[0]?.url; } return url; } /** * Starts radio mode with a list of URLs. * @param urls - Array of URLs to play. */ async startRadio(urls) { this.radioMode = true; this.radioUrls = urls; const shuffledUrls = this.shuffleArray([...urls]); this.queue = await Promise.all(shuffledUrls.map(async (url) => await this.fetchMetadata(url))); if (this.queue.length > 0) { const first = this.queue.shift(); await this.playUrl(first.url, first); } } /** * Creates a stream from a SoundCloud URL. * @param url - SoundCloud URL. * @returns Readable stream. */ async createStreamFromScdl(url) { return await soundcloud_downloader_1.default.download(url); } /** * Creates a stream from a YouTube URL using various ytdl libraries. * @param url - YouTube URL. * @returns Readable stream or null if failed. */ async createStreamFromYtdl(url) { const options = { filter: "audioonly", highWaterMark: 1 << 25 }; let stream = null; try { stream = (0, ytdl_core_2.default)(url, options); } catch { } if (!stream) try { stream = (0, ytdl_core_1.default)(url, options); } catch { } if (!stream) try { stream = await (0, ytdl_core_discord_1.default)(url, options); } catch { } return stream; } /** * Creates a stream from a URL using play-dl. * @param url - URL to stream. * @returns Readable stream or null if failed. */ async createStreamFromPlayDl(url) { const yt = await play_dl_1.default.stream(url, { quality: 2 }); if (!yt) return null; return yt.stream; } /** * Fetches metadata for a track URL. * @param url - Track URL. * @returns Track metadata. */ async fetchMetadata(url) { const empity_resualt = { title: undefined, author: undefined, duration: undefined, thumbnail: undefined, source: "unknown", url }; try { if (/^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\//.test(url)) { let info; try { info = await ytdl_core_2.default.getBasicInfo(url); } catch { } if (!info) try { info = await ytdl_core_1.default.getBasicInfo(url); } catch { } if (!info) try { info = await ytdl_core_discord_1.default.getBasicInfo(url); } catch { } if (!info) return empity_resualt; const details = info.videoDetails; return { title: details.title, author: details.author.name, duration: parseInt(details.lengthSeconds, 10), thumbnail: details.thumbnails[details.thumbnails.length - 1].url, source: "youtube", url }; } if (/^https?:\/\/(soundcloud\.com|snd\.sc)\//.test(url)) { const info = await soundcloud_downloader_1.default.getInfo(url); return { title: info.title, author: info.user?.username, duration: Math.floor(info.duration / 1000), thumbnail: info.artwork_url || info.user?.avatar_url, source: "soundcloud", url }; } const result = await play_dl_1.default.video_basic_info(url); const vid = result.video_details; return { title: vid.title, author: vid.channel?.name, duration: vid.durationInSec, thumbnail: vid.thumbnails?.[0]?.url, source: "unknown", url }; } catch { return empity_resualt; } } /** * Plays a track URL with its metadata. * @param url - Track URL. * @param metadata - Track metadata. */ async playUrl(url, metadata) { this.playing = true; this.history.push(url); let stream = null; if (/^https?:\/\/(soundcloud\.com|snd\.sc)\//.test(url)) try { stream = await this.createStreamFromScdl(url); } catch { } if (/^https?:\/\/open\.spotify\.com\/(track|album|playlist)\//.test(url)) if (!stream) try { stream = await this.createStreamFromPlayDl(url); } catch { } if (/^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\//.test(url)) if (!stream) try { stream = await this.createStreamFromYtdl(url); } catch { } const resource = (0, voice_1.createAudioResource)(stream, { inlineVolume: true }); resource.volume?.setVolume(this.volume); this.player.play(resource); if (!this.player.state.resource) this.player.state.resource = resource; this.emit(types_1.MusicPlayerEvent.Start, { metadata, queue: [...this.queue] }); return; } /** * Plays a song by query or URL, adding to queue if already playing. * @param input - Search query or URL. */ async play(input) { await this.ensureConnection(); const url = await this.search(input); const metadata = await this.fetchMetadata(url); if (this.playing) { this.queue.push(metadata); this.emit(types_1.MusicPlayerEvent.QueueAdd, { metadata, queue: [...this.queue] }); } else { await this.playUrl(url, metadata); } return; } /** * Pauses the current playback. */ pause() { this.player.pause(); this.emit(types_1.MusicPlayerEvent.Pause); return; } /** * Resumes the current playback. */ resume() { this.player.unpause(); this.emit(types_1.MusicPlayerEvent.Resume); return; } /** * Sets the playback volume. * @param percent - Volume percentage (0–200). */ setVolume(percent) { percent /= 100; if (percent < 0 || percent > 2) this.volume = 2; else this.volume = percent; const resource = this.player.state.resource; try { resource.volume.setVolume(this.volume); } catch { } this.emit(types_1.MusicPlayerEvent.VolumeChange, { volume: Math.round(this.volume * 100) }); return this.volume; } /** * Handles idle state, looping or playing next track as needed. */ async onIdle() { if (this.loopTrack) { const url = this.history[this.history.length - 1]; const metadata = await this.fetchMetadata(url); return await this.playUrl(url, metadata); } if (this.queue.length) { const next = this.queue.shift(); if (this.loopQueue) this.queue.push(next); return await this.playUrl(next.url, next); } if (this.radioMode && this.radioUrls.length > 0) { const shuffledUrls = this.shuffleArray([...this.radioUrls]); this.queue = await Promise.all(shuffledUrls.map(async (url) => await this.fetchMetadata(url))); if (this.queue.length > 0) { const next = this.queue.shift(); return await this.playUrl(next.url, next); } } this.playing = false; this.emit(types_1.MusicPlayerEvent.Finish, { queue: [...this.queue], history: [...this.history] }); if (this.autoLeaveOnEmptyQueue) { this.emit(types_1.MusicPlayerEvent.Disconnect); this.disconnect(); } else { this.startIdleTimer(); } return; } /** * Skips the current track and moves to the next. */ skip() { this.emit(types_1.MusicPlayerEvent.Skip, { queue: [...this.queue], history: [...this.history] }); this.player.stop(); return; } /** * Plays the previous track from history. */ async previous() { if (this.history.length < 2) { this.emit(types_1.MusicPlayerEvent.Error, this.createError("No track to previous.")); return; } this.history.pop(); const prevUrl = this.history.pop(); const metadata = await this.fetchMetadata(prevUrl); this.queue.unshift(metadata); this.emit(types_1.MusicPlayerEvent.Previous, { metadata, queue: [...this.queue], history: [...this.history, prevUrl] }); await this.playUrl(prevUrl, metadata); return; } /** * Shuffles the queue and saves the previous order. */ shuffle() { this.previousQueueOrder = [...this.queue]; for (let i = this.queue.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [this.queue[i], this.queue[j]] = [this.queue[j], this.queue[i]]; } this.shuffield = true; this.emit(types_1.MusicPlayerEvent.Shuffle, { queue: [...this.queue] }); return; } /** * Restores the queue to its pre-shuffle order, excluding played tracks. */ undoShuffle() { this.queue = this.previousQueueOrder.filter(meta => !this.history.includes(meta.url)); this.shuffield = false; this.emit(types_1.MusicPlayerEvent.Shuffle, { queue: [...this.queue] }); return; } /** * Toggles queue looping on or off. */ toggleLoopQueue() { return this.loopQueue = !this.loopQueue; } /** * Checks if queue looping is enabled. * @returns True if enabled, false otherwise. */ isLoopQueue() { return this.loopQueue; } /** * Toggles track looping on or off. */ toggleLoopTrack() { return this.loopTrack = !this.loopTrack; } /** * Checks if track looping is enabled. * @returns True if enabled, false otherwise. */ isLoopTrack() { return this.loopTrack; } /** * Disconnects from the voice channel and cleans up resources. */ disconnect() { this.clearIdleTimer(); this.player?.stop(); if (this.connection) { this.connection.destroy(); this.connection = null; } this.playing = false; this.queue = []; this.history = []; this.emit(types_1.MusicPlayerEvent.Disconnect); return; } /** * Stops playback and optionally disconnects. * @param noLeave - If true, stays connected to the channel. */ stop(noLeave = true) { this.radioMode = false; this.radioUrls = []; this.player.stop(); this.playing = false; this.queue = []; this.history = []; this.clearIdleTimer(); if (!noLeave) this.disconnect(); this.emit(types_1.MusicPlayerEvent.Stop); return; } /** * Returns a copy of the current queue. * @returns Array of track metadata. */ getQueue() { return [...this.queue]; } /** * Gets the current volume percentage. * @returns Volume (0–200). */ getVolume() { const resource = this.player.state.resource; if (resource && resource.volume && resource.volume.volume) return Math.round(resource.volume.volume * 100); return Math.round(this.volume * 100); } /** * Checks if the player is currently playing. * @returns True if playing, false otherwise. */ isPlaying() { return this.playing; } /** * Checks if the player is paused. * @returns True if paused, false otherwise. */ isPaused() { return this.player && this.player.state.status === voice_1.AudioPlayerStatus.Paused; } /** * Checks if the queue is shuffled. * @returns True if shuffled, false otherwise. */ isShuffiled() { return this.shuffield; } /** * Checks if the bot is actively connected to a voice channel. * @param guildId - Optional guild ID; uses stored guild ID if not provided. * @returns True if actively connected, false otherwise. */ isConnected(guildId) { const targetGuildId = guildId || this.connectionData?.guildId; if (!targetGuildId) return false; const connection = this.connection || (0, voice_1.getVoiceConnection)(targetGuildId); if (!connection) return false; return [ voice_1.VoiceConnectionStatus.Ready, voice_1.VoiceConnectionStatus.Connecting, voice_1.VoiceConnectionStatus.Signalling ].includes(connection.state.status); } /** * Creates a custom error for the music player. * @param message - Error message. * @returns Custom error instance. */ createError(message) { class discordPlayerError extends Error { constructor() { super(); this.name = "Discord-Player"; this.message = message; } } return new discordPlayerError(); } } exports.MusicPlayer = MusicPlayer; /** * @copyright * Code by Sobhan-SRZA (mr.sinre) | https://github.com/Sobhan-SRZA * Developed for Persian Caesar | https://github.com/Persian-Caesar | https://dsc.gg/persian-caesar * * If you encounter any issues or need assistance with this code, * please make sure to credit "Persian Caesar" in your documentation or communications. */ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTXVzaWNQbGF5ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvTXVzaWNQbGF5ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsNENBVzBCO0FBQzFCLG1DQU1pQjtBQUNqQiwrQ0FBMEM7QUFFMUMsMEVBQWtEO0FBQ2xELG9EQUFrQztBQUNsQywwREFBa0M7QUFDbEMsc0RBQTZCO0FBQzdCLG1FQUFzQztBQUN0QyxrRkFBeUM7QUFFekM7OztHQUdHO0FBQ0gsTUFBYSxXQUFZLFNBQVEsZ0JBQTBCO0lBc0M1QztJQXJDWCxtQkFBbUI7SUFDWCxrQkFBa0IsR0FBb0IsRUFBRSxDQUFDO0lBQ3pDLFVBQVUsR0FBMkIsSUFBSSxDQUFDO0lBQzFDLE1BQU0sQ0FBYztJQUNwQixNQUFNLENBQVM7SUFDZixLQUFLLEdBQW9CLEVBQUUsQ0FBQztJQUM1QixPQUFPLEdBQWEsRUFBRSxDQUFDO0lBQ3ZCLFNBQVMsR0FBRyxLQUFLLENBQUM7SUFDbEIsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUNsQixPQUFPLEdBQUcsS0FBSyxDQUFDO0lBQ2hCLHFCQUFxQixDQUFVO0lBQy9CLGlCQUFpQixDQUFTO0lBQzFCLFNBQVMsR0FBMEIsSUFBSSxDQUFDO0lBQ3hDLFNBQVMsR0FBWSxLQUFLLENBQUM7SUFFbkMsUUFBUTtJQUNBLFNBQVMsR0FBWSxLQUFLLENBQUM7SUFDM0IsU0FBUyxHQUFhLEVBQUUsQ0FBQztJQUVqQyxhQUFhO0lBQ0wsY0FBYyxHQVFYLElBQUksQ0FBQztJQUVoQjs7Ozs7T0FLRztJQUNILFlBQ1csT0FBcUIsRUFDNUIsYUFBYSxHQUFHLEdBQUcsRUFDbkIsVUFBOEIsRUFBRTtRQUVoQyxLQUFLLEVBQUUsQ0FBQztRQUpELFlBQU8sR0FBUCxPQUFPLENBQWM7UUFLNUIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFBLHlCQUFpQixHQUFFLENBQUMsQ0FBQyxpREFBaUQ7UUFDcEYsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLDJEQUEyRDtRQUMxRyxJQUFJLENBQUMscUJBQXFCLEdBQUcsT0FBTyxDQUFDLHFCQUFxQixJQUFJLElBQUksQ0FBQyxDQUFDLG1EQUFtRDtRQUN2SCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsT0FBTyxDQUFDLGlCQUFpQixJQUFJLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxzREFBc0Q7UUFFeEgsSUFBSSxDQUFDLGNBQWMsR0FBRztZQUNsQixTQUFTLEVBQUUsT0FBTyxDQUFDLEVBQUU7WUFDckIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUN6QixjQUFjLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxtQkFBbUI7WUFDakQsUUFBUSxFQUFFLElBQUk7WUFDZCxRQUFRLEVBQUUsS0FBSztZQUNmLEtBQUssRUFBRSxLQUFLO1NBQ2YsQ0FBQztRQUVGLDRFQUE0RTtRQUM1RSxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLEVBQUU7WUFDMUIsSUFBSSxDQUFDLElBQUksQ0FBQyx3QkFBZ0IsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyx1QkFBdUIsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUMvRixDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLHlCQUFpQixDQUFDLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLG9DQUFvQztRQUNqRyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyx5QkFBaUIsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQyxzQ0FBc0M7SUFDbEgsQ0FBQztJQUdEOzs7O09BSUc7SUFDSSxPQUFPLENBQUMsSUFRZDtRQUNHLElBQUksQ0FBQyxjQUFjLEdBQUc7WUFDbEIsR0FBRyxJQUFJO1lBQ1AsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSTtZQUMvQixRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVEsSUFBSSxLQUFLO1lBQ2hDLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxJQUFJLEtBQUs7U0FDN0IsQ0FBQztRQUVGLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFHRDs7OztPQUlHO0lBQ0ksSUFBSSxDQUFDLElBUVg7UUFDRyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ2hDLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxxREFBcUQsQ0FBQyxDQUFDO1FBQ2xGLENBQUM7UUFDRCxNQUFNLGNBQWMsR0FBRyxJQUFJLElBQUksSUFBSSxDQUFDLGNBQWUsQ0FBQztRQUNwRCxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUEsd0JBQWdCLEVBQUM7WUFDL0IsU0FBUyxFQUFFLGNBQWMsQ0FBQyxTQUFTO1lBQ25DLE9BQU8sRUFBRSxjQUFjLENBQUMsT0FBTztZQUMvQixjQUFjLEVBQUUsY0FBYyxDQUFDLGNBQWM7WUFDN0MsUUFBUSxFQUFFLGNBQWMsQ0FBQyxRQUFRLElBQUksSUFBSTtZQUN6QyxRQUFRLEVBQUUsY0FBYyxDQUFDLFFBQVEsSUFBSSxLQUFLO1lBQzFDLEtBQUssRUFBRSxjQUFjLENBQUMsS0FBSztZQUMzQixLQUFLLEVBQUUsY0FBYyxDQUFDLEtBQUs7U0FDOUIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRXZDLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUMzQixDQUFDO0lBRUQ7O09BRUc7SUFDSyxLQUFLLENBQUMsZ0JBQWdCO1FBRTFCLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDbkIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFFOUIsSUFBSSxDQUFDO2dCQUNELE1BQU0sSUFBQSxtQkFBVyxFQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsNkJBQXFCLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVFLENBQUM7WUFBQyxPQUFPLENBQU0sRUFBRSxDQUFDO2dCQUNkLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQzFCLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDO2dCQUN2QixJQUFJLENBQUMsSUFBSSxDQUFDLHdCQUFnQixDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLHlDQUF5QyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQy9HLENBQUM7UUFDTCxDQUFDO1FBRUQsT0FBTztJQUNYLENBQUM7SUFFRDs7T0FFRztJQUNLLGNBQWM7UUFDbEIsSUFBSSxJQUFJLENBQUMsaUJBQWlCLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNqRSxJQUFJLENBQUMsU0FBUyxHQUFHLFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQzdCLElBQUksQ0FBQyxJQUFJLENBQUMsd0JBQWdCLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQ3ZDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUN0QixDQUFDLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDL0IsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNLLGNBQWM7UUFDbEIsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDakIsWUFBWSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUM3QixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUMxQixDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxZQUFZLENBQUksS0FBVTtRQUM5QixNQUFNLFFBQVEsR0FBRyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUM7UUFDNUIsS0FBSyxJQUFJLENBQUMsR0FBRyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDM0MsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM5QyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM1RCxDQUFDO1FBRUQsT0FBTyxRQUFRLENBQUM7SUFDcEIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxLQUFLLENBQUMsWUFBWSxDQUFDLEtBQWEsRUFBRSxNQUFlO1FBQ3BELE1BQU0sTUFBTSxHQUFHLGtIQUFrSCxDQUFDO1FBQ2xJLE1BQU0sTUFBTSxHQUFHLHdGQUF3RixDQUFDO1FBQ3hHLE1BQU0sTUFBTSxHQUFHLGtDQUFrQyxDQUFDO1FBQ2xELElBQUksSUFBSSxHQUFXLEVBQUUsQ0FBQztRQUN0QixNQUFNLEtBQUssR0FBRyxrQkFBa0IsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDMUUsTUFBTSxRQUFRLEdBQUc7WUFDYixHQUFHLE1BQU0sR0FBRyxLQUFLLFNBQVM7WUFDMUIsR0FBRyxNQUFNLEdBQUcsS0FBSyxjQUFjO1lBQy9CLEdBQUcsTUFBTSxHQUFHLEtBQUssT0FBTztZQUN4QixHQUFHLE1BQU0sR0FBRyxLQUFLLEVBQUU7U0FDdEIsQ0FBQztRQUNGLEtBQUssTUFBTSxHQUFHLElBQUksUUFBUSxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDO2dCQUNELE1BQU0sR0FBRyxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsRUFBRSxFQUFFLE9BQU8sRUFBRSxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQzNFLElBQUksR0FBRyxNQUFNLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFFeEIsTUFBTTtZQUNWLENBQUM7WUFFRCxNQUFNLENBQUM7Z0JBQ0gsU0FBUztZQUNiLENBQUM7UUFDTCxDQUFDO1FBRUQsSUFBSSxDQUFDLElBQUk7WUFBRSxPQUFPLElBQUksQ0FBQztRQUV2QixJQUFJLE9BQWUsQ0FBQztRQUNwQixJQUFJLENBQUM7WUFDRCxDQUFDLEVBQUUsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNqQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEMsQ0FBQztRQUVELE1BQU0sQ0FBQztZQUNILE9BQU8sSUFBSSxDQUFDO1FBQ2hCLENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JDLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQztRQUNoQixLQUFLLE1BQU0sSUFBSSxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQzFCLE1BQU0sSUFBSSxJQUFBLHlCQUFVLEVBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDO1FBQzdDLENBQUM7UUFFRCxNQUFNLEdBQUcsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO1FBRXZCLE9BQU8sTUFBTSxJQUFJLElBQUksQ0FBQztJQUMxQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBYTtRQUM3QixJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFDN0MsTUFBTSxVQUFVLEdBQUcsTUFBTSwrQkFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ2xGLElBQUksR0FBRyxHQUFHLFVBQVUsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxhQUFhLENBQUM7UUFDcEQsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ1AsTUFBTSxjQUFjLEdBQUcsTUFBTSxpQkFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUU7Z0JBQzlDLEtBQUssRUFBRSxDQUFDO2dCQUNSLE1BQU0sRUFBRSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7YUFDeEYsQ0FBQyxDQUFDO1lBQ0gsR0FBRyxHQUFHLGNBQWMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUM7UUFDakMsQ0FBQztRQUVELE9BQU8sR0FBRyxDQUFDO0lBQ2YsQ0FBQztJQUVEOzs7T0FHRztJQUNJLEtBQUssQ0FBQyxVQUFVLENBQUMsSUFBYztRQUNsQyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN0QixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN0QixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ2xELElBQUksQ0FBQyxLQUFLLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFDLEdBQUcsRUFBQyxFQUFFLENBQUMsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3RixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3hCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFHLENBQUM7WUFDbEMsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDekMsQ0FBQztJQUNMLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssS0FBSyxDQUFDLG9CQUFvQixDQUFDLEdBQVc7UUFDMUMsT0FBTyxNQUFNLCtCQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssS0FBSyxDQUFDLG9CQUFvQixDQUFDLEdBQVc7UUFDMUMsTUFBTSxPQUFPLEdBQVEsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLGFBQWEsRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7UUFDckUsSUFBSSxNQUFNLEdBQTJCLElBQUksQ0FBQztRQUMxQyxJQUFJLENBQUM7WUFBQyxNQUFNLEdBQUcsSUFBQSxtQkFBSSxFQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUFDLENBQUM7UUFBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBRTlDLElBQUksQ0FBQyxNQUFNO1lBQUUsSUFBSSxDQUFDO2dCQUFDLE1BQU0sR0FBRyxJQUFBLG1CQUFTLEVBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQUMsQ0FBQztZQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFFaEUsSUFBSSxDQUFDLE1BQU07WUFBRSxJQUFJLENBQUM7Z0JBQUMsTUFBTSxHQUFHLE1BQU0sSUFBQSwyQkFBaUIsRUFBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFBQyxDQUFDO1lBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUU5RSxPQUFPLE1BQU0sQ0FBQztJQUNsQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxHQUFXO1FBQzVDLE1BQU0sRUFBRSxHQUFHLE1BQU0saUJBQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDcEQsSUFBSSxDQUFDLEVBQUU7WUFBRSxPQUFPLElBQUksQ0FBQztRQUVyQixPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUM7SUFDckIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQVc7UUFDbkMsTUFBTSxjQUFjLEdBQWtCLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxDQUFDO1FBRWpKLElBQUksQ0FBQztZQUNELElBQUksbURBQW1ELENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ2hFLElBQUksSUFBc0QsQ0FBQztnQkFDM0QsSUFBSSxDQUFDO29CQUFDLElBQUksR0FBRyxNQUFNLG1CQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUFDLENBQUM7Z0JBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFFdEQsSUFBSSxDQUFDLElBQUk7b0JBQ0wsSUFBSSxDQUFDO3dCQUFDLElBQUksR0FBRyxNQUFNLG1CQUFTLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUFDLENBQUM7b0JBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFFL0QsSUFBSSxDQUFDLElBQUk7b0JBQ0wsSUFBSSxDQUFDO3dCQUFDLElBQUksR0FBRyxNQUFNLDJCQUFpQixDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFBQyxDQUFDO29CQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0JBRXZFLElBQUksQ0FBQyxJQUFJO29CQUNMLE9BQU8sY0FBYyxDQUFDO2dCQUUxQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO2dCQUNsQyxPQUFPO29CQUNILEtBQUssRUFBRSxPQUFPLENBQUMsS0FBSztvQkFDcEIsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSTtvQkFDM0IsUUFBUSxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQztvQkFDN0MsU0FBUyxFQUFFLE9BQU8sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRztvQkFDaEUsTUFBTSxFQUFFLFNBQVM7b0JBQ2pCLEdBQUc7aUJBQ04sQ0FBQztZQUNOLENBQUM7WUFFRCxJQUFJLHlDQUF5QyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUN0RCxNQUFNLElBQUksR0FBRyxNQUFNLCtCQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNyQyxPQUFPO29CQUNILEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztvQkFDakIsTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsUUFBUTtvQkFDM0IsUUFBUSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVMsR0FBRyxJQUFJLENBQUM7b0JBQzNDLFNBQVMsRUFBRSxJQUFJLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsVUFBVTtvQkFDcEQsTUFBTSxFQUFFLFlBQVk7b0JBQ3BCLEdBQUc7aUJBQ04sQ0FBQztZQUNOLENBQUM7WUFFRCxNQUFNLE1BQU0sR0FBRyxNQUFNLGlCQUFNLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDbEQsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQztZQUVqQyxPQUFPO2dCQUNILEtBQUssRUFBRSxHQUFHLENBQUMsS0FBSztnQkFDaEIsTUFBTSxFQUFFLEdBQUcsQ0FBQyxPQUFPLEVBQUUsSUFBSTtnQkFDekIsUUFBUSxFQUFFLEdBQUcsQ0FBQyxhQUFhO2dCQUMzQixTQUFTLEVBQUUsR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUc7Z0JBQ25DLE1BQU0sRUFBRSxTQUFTO2dCQUNqQixHQUFHO2FBQ04sQ0FBQztRQUNOLENBQUM7UUFFRCxNQUFNLENBQUM7WUFDSCxPQUFPLGNBQWMsQ0FBQztRQUMxQixDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQVcsRUFBRSxRQUF1QjtRQUN0RCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztRQUNwQixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN2QixJQUFJLE1BQU0sR0FBMkIsSUFBSSxDQUFDO1FBQzFDLElBQUkseUNBQXlDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztZQUNuRCxJQUFJLENBQUM7Z0JBQUMsTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQUMsQ0FBQztZQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFFcEUsSUFBSSwwREFBMEQsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO1lBQ3BFLElBQUksQ0FBQyxNQUFNO2dCQUFFLElBQUksQ0FBQztvQkFBQyxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsc0JBQXNCLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQUMsQ0FBQztnQkFBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBRW5GLElBQUksbURBQW1ELENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztZQUM3RCxJQUFJLENBQUMsTUFBTTtnQkFBRSxJQUFJLENBQUM7b0JBQUMsTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUFDLENBQUM7Z0JBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUVqRixNQUFNLFFBQVEsR0FBRyxJQUFBLDJCQUFtQixFQUFDLE1BQU8sRUFBRSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3RFLFFBQVEsQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN4QyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMzQixJQUFJLENBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFpQyxDQUFDLFFBQVE7WUFDdkQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFpQyxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7UUFFdkUsSUFBSSxDQUFDLElBQUksQ0FBQyx3QkFBZ0IsQ0FBQyxLQUFLLEVBQUUsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRXhFLE9BQU87SUFDWCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFhO1FBQzNCLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDOUIsTUFBTSxHQUFHLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMvQyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNmLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQzFCLElBQUksQ0FBQyxJQUFJLENBQUMsd0JBQWdCLENBQUMsUUFBUSxFQUFFLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMvRSxDQUFDO2FBRUksQ0FBQztZQUNGLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDdEMsQ0FBQztRQUVELE9BQU87SUFDWCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLO1FBQ1IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLHdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRWxDLE9BQU87SUFDWCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxNQUFNO1FBQ1QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUN0QixJQUFJLENBQUMsSUFBSSxDQUFDLHdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRW5DLE9BQU87SUFDWCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksU0FBUyxDQUFDLE9BQWU7UUFDNUIsT0FBTyxJQUFJLEdBQUcsQ0FBQztRQUNmLElBQUksT0FBTyxHQUFHLENBQUMsSUFBSSxPQUFPLEdBQUcsQ0FBQztZQUFFLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDOztZQUUzQyxJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQztRQUUzQixNQUFNLFFBQVEsR0FBSSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQWlDLENBQUMsUUFBUSxDQUFDO1FBQ3pFLElBQUksQ0FBQztZQUFDLFFBQVEsQ0FBQyxNQUFPLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUFDLENBQUM7UUFBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBRTFELElBQUksQ0FBQyxJQUFJLENBQUMsd0JBQWdCLENBQUMsWUFBWSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFcEYsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3ZCLENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyxNQUFNO1FBQ2hCLElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ2pCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDbEQsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBRS9DLE9BQU8sTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUM3QyxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3BCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFHLENBQUM7WUFDakMsSUFBSSxJQUFJLENBQUMsU0FBUztnQkFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUUxQyxPQUFPLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzlDLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDOUMsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7WUFDNUQsSUFBSSxDQUFDLEtBQUssR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUMsR0FBRyxFQUFDLEVBQUUsQ0FBQyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzdGLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3hCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFHLENBQUM7Z0JBRWpDLE9BQU8sTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDOUMsQ0FBQztRQUNMLENBQUM7UUFFRCxJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztRQUNyQixJQUFJLENBQUMsSUFBSSxDQUFDLHdCQUFnQixDQUFDLE1BQU0sRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMzRixJQUFJLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQzdCLElBQUksQ0FBQyxJQUFJLENBQUMsd0JBQWdCLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDdkMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ3RCLENBQUM7YUFFSSxDQUFDO1lBQ0YsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQzFCLENBQUM7UUFFRCxPQUFPO0lBQ1gsQ0FBQztJQUVEOztPQUVHO0lBQ0ksSUFBSTtRQUNQLElBQUksQ0FBQyxJQUFJLENBQUMsd0JBQWdCLENBQUMsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3pGLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7UUFFbkIsT0FBTztJQUNYLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxRQUFRO1FBQ2pCLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDMUIsSUFBSSxDQUFDLElBQUksQ0FBQyx3QkFBZ0IsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLENBQUM7WUFFN0UsT0FBTztRQUNYLENBQUM7UUFFRCxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ25CLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFHLENBQUM7UUFDcEMsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxJQUFJLENBQUMsd0JBQWdCLENBQUMsUUFBUSxFQUFFLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDaEgsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztRQUV0QyxPQUFPO0lBQ1gsQ0FBQztJQUVEOztPQUVHO0lBQ0ksT0FBTztRQUNWLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzFDLEtBQUssSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUM3QyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzlDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwRSxDQUFDO1FBRUQsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7UUFDdEIsSUFBSSxDQUFDLElBQUksQ0FBQyx3QkFBZ0IsQ0FBQyxPQUFPLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFaEUsT0FBTztJQUNYLENBQUM7SUFFRDs7T0FFRztJQUNJLFdBQVc7UUFDZCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3RGLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxJQUFJLENBQUMsd0JBQWdCLENBQUMsT0FBTyxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRWhFLE9BQU87SUFDWCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxlQUFlO1FBQ2xCLE9BQU8sSUFBSSxDQUFDLFNBQVMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7SUFDNUMsQ0FBQztJQUVEOzs7T0FHRztJQUNJLFdBQVc7UUFDZCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUM7SUFDMUIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksZUFBZTtRQUNsQixPQUFPLElBQUksQ0FBQyxTQUFTLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQzVDLENBQUM7SUFFRDs7O09BR0c7SUFDSSxXQUFXO1FBQ2QsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQzFCLENBQUM7SUFFRDs7T0FFRztJQUNJLFVBQVU7UUFDYixJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQztRQUNwQixJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNsQixJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQzFCLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDO1FBQzNCLENBQUM7UUFFRCxJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztRQUNyQixJQUFJLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUNoQixJQUFJLENBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDLHdCQUFnQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRXZDLE9BQU87SUFDWCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJO1FBQ3RCLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDckIsSUFBSSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDaEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDbEIsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxPQUFPO1lBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBRWhDLElBQUksQ0FBQyxJQUFJLENBQUMsd0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFakMsT0FBTztJQUNYLENBQUM7SUFFRDs7O09BR0c7SUFDSSxRQUFRO1FBQ1gsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzNCLENBQUM7SUFFRDs7O09BR0c7SUFDSSxTQUFTO1FBQ1osTUFBTSxRQUFRLEdBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFpQyxDQUFDLFFBQVEsQ0FBQztRQUN6RSxJQUFJLFFBQVEsSUFBSSxRQUFRLENBQUMsTUFBTSxJQUFJLFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTTtZQUNyRCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFFcEQsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVEOzs7T0FHRztJQUNJLFNBQVM7UUFDWixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDeEIsQ0FBQztJQUVEOzs7T0FHRztJQUNJLFFBQVE7UUFDWCxPQUFPLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLHlCQUFpQixDQUFDLE1BQU0sQ0FBQztJQUNoRixDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksV0FBVztRQUNkLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUMxQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLFdBQVcsQ0FBQyxPQUFnQjtRQUMvQixNQUFNLGFBQWEsR0FBRyxPQUFPLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRSxPQUFPLENBQUM7UUFDOUQsSUFBSSxDQUFDLGFBQWE7WUFDZCxPQUFPLEtBQUssQ0FBQztRQUVqQixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxJQUFJLElBQUEsMEJBQWtCLEVBQUMsYUFBYSxDQUFDLENBQUM7UUFDeEUsSUFBSSxDQUFDLFVBQVU7WUFDWCxPQUFPLEtBQUssQ0FBQztRQUVqQixPQUFPO1lBQ0gsNkJBQXFCLENBQUMsS0FBSztZQUMzQiw2QkFBcUIsQ0FBQyxVQUFVO1lBQ2hDLDZCQUFxQixDQUFDLFVBQVU7U0FDbkMsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLFdBQVcsQ0FBQyxPQUFlO1FBQy9CLE1BQU0sa0JBQW1CLFNBQVEsS0FBSztZQUNsQztnQkFDSSxLQUFLLEVBQUUsQ0FBQztnQkFDUixJQUFJLENBQUMsSUFBSSxHQUFHLGdCQUFnQixDQUFDO2dCQUM3QixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztZQUMzQixDQUFDO1NBQ0o7UUFFRCxPQUFPLElBQUksa0JBQWtCLEVBQUUsQ0FBQztJQUNwQyxDQUFDO0NBQ0o7QUFqc0JELGtDQWlzQkM7QUFFRDs7Ozs7OztHQU9HIn0=