[
  {
    "path": ".github/workflows/cross-build.yml",
    "content": "name: Cross-Platform Build\n\non:\n  push:\n    branches:\n      - dev\n\njobs:\n  pyinstaller-build-windows:\n    runs-on: windows-latest\n    steps:\n      - name: Build executable\n        uses: PrajwalVandana/pyinstaller@c7c491de8409921df7045f681695d4d5ab71a4e0\n        id: pyinstaller\n        with:\n          python_ver: '3.12'\n          spec: specs/maestro-windows.spec\n          requirements: requirements.txt\n      - name: Install NSIS\n        uses: repolevedavaj/install-nsis@v1.0.2\n        with:\n          nsis-version: '3.10'\n      - name: Run NSIS and zip dist\n        run: |\n          makensis install-scripts/windows.nsi\n          Compress-Archive -Path \"${{ steps.pyinstaller.outputs.executable_path }}/maestro/*\" -Destination \"${{ steps.pyinstaller.outputs.executable_path }}/maestro-windows.zip\"\n      - name: Upload to release\n        uses: softprops/action-gh-release@v2\n        with:\n          files: |\n            install-scripts/maestro-installer.exe\n            ${{ steps.pyinstaller.outputs.executable_path }}/maestro-windows.zip\n          token: ${{ secrets.GITHUB_TOKEN }}\n          draft: true\n          prerelease: true\n  pyinstaller-build-mac:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os: [macos-12, macos-latest]\n    steps:\n      - name: Build executable\n        uses: PrajwalVandana/pyinstaller@c7c491de8409921df7045f681695d4d5ab71a4e0\n        id: pyinstaller\n        with:\n          python_ver: '3.12'\n          spec: specs/maestro-mac.spec\n          requirements: requirements.txt\n      - name: Read version from __version__.py\n        id: version\n        # read VERSION = \"a.b.c\" from __version__.py\n        run: |\n          VERSION=$(sed -n 's/VERSION = \"\\([^\"]*\\)\"/\\1/p' maestro/__version__.py)\n          echo \"version=$VERSION\" >> \"$GITHUB_OUTPUT\"\n      - name: Add install script\n        run: |\n          mkdir -p \"${{ steps.pyinstaller.outputs.executable_path }}/Scripts\"\n          mv install-scripts/mac \"${{ steps.pyinstaller.outputs.executable_path }}/Scripts/postinstall\"\n      - name: Create .pkg\n        id: pkgbuild\n        # main branch\n        # uses: PrajwalVandana/generate-mac-installer-github-action@fd5c2a03cfc2be65e32095573392ed03423a4208\n        # dev branch\n        uses: PrajwalVandana/generate-mac-installer-github-action@9d0c29930827283cce48688cb2154b47c92a4042\n        with:\n          root-directory:  \"${{ steps.pyinstaller.outputs.executable_path }}/maestro\"\n          scripts-directory:  \"${{ steps.pyinstaller.outputs.executable_path }}/Scripts\"\n          identifier: com.maestro.maestro-cli\n          version: ${{ steps.version.outputs.version }}\n          install-location: /usr/local/bin/maestro-bundle/\n      - name: Rename .pkg, compress dist\n        run: |\n          mv \"${{ steps.pkgbuild.outputs.output-path }}\" \"${{ steps.pyinstaller.outputs.executable_path }}/${{ matrix.os == 'macos-latest' && 'maestro-apple-silicon' || 'maestro-mac-intel' }}.pkg\"\n          tar -czf \"${{ steps.pyinstaller.outputs.executable_path }}/${{ matrix.os == 'macos-latest' && 'maestro-apple-silicon' || 'maestro-mac-intel' }}.tar.gz\" \"${{ steps.pyinstaller.outputs.executable_path }}/maestro\"\n      - name: Upload to release\n        uses: softprops/action-gh-release@v2\n        with:\n          files: |\n            ${{ steps.pyinstaller.outputs.executable_path }}/${{ matrix.os == 'macos-latest' && 'maestro-apple-silicon' || 'maestro-mac-intel' }}.pkg\n            ${{ steps.pyinstaller.outputs.executable_path }}/${{ matrix.os == 'macos-latest' && 'maestro-apple-silicon' || 'maestro-mac-intel' }}.tar.gz\n          token: ${{ secrets.GITHUB_TOKEN }}\n          draft: true\n          prerelease: true\n  pyinstaller-build-linux:\n    runs-on: ubuntu-20.04\n    steps:\n      - name: Build executable\n        uses: PrajwalVandana/pyinstaller@c7c491de8409921df7045f681695d4d5ab71a4e0\n        id: pyinstaller\n        with:\n          python_ver: '3.12'\n          spec: specs/maestro-ubuntu.spec\n          requirements: requirements.txt\n      - name: Add install script and compress\n        run: |\n          mv install-scripts/ubuntu \"${{ steps.pyinstaller.outputs.executable_path }}/maestro/install-maestro\"\n          tar -czf \"${{ steps.pyinstaller.outputs.executable_path }}/maestro-ubuntu.tar.gz\" \"${{ steps.pyinstaller.outputs.executable_path }}/maestro\"\n      - name: Upload to release\n        uses: softprops/action-gh-release@v2\n        with:\n          files: |\n            ${{ steps.pyinstaller.outputs.executable_path }}/maestro-ubuntu.tar.gz\n          token: ${{ secrets.GITHUB_TOKEN }}\n          draft: true\n          prerelease: true\n"
  },
  {
    "path": ".gitignore",
    "content": ".vscode\nbuild\n*.egg-info\n**/*.log\n*.egg\n__pycache__\n*.code-workspace\n**/*.env\n.pylintrc\n\ntodo.md\ntest_songs/\nsong_info.txt\n*_test.py\n*_ref.*\nsound_vis_cache/\ngui_helper.py\n**/*.spotdl\nprofile.*"
  },
  {
    "path": "LICENSE",
    "content": "Copyright © 2022 Prajwal Vandana\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n"
  },
  {
    "path": "install-scripts/mac",
    "content": "#!/bin/sh\n\nMAESTRO_BUNDLE_LOC=/usr/local/bin/maestro-bundle\nMAESTRO_SYMLINK_LOC=/usr/local/bin/maestro\n\n# Make maestro executable\nchmod +x $MAESTRO_BUNDLE_LOC/maestro\n\n# Recursively find and disable quarantine\nxattr -d -r com.apple.quarantine $MAESTRO_BUNDLE_LOC\n\n# Remove existing symlink\nrm -rf $MAESTRO_SYMLINK_LOC\n\n# Create a symlink to the maestro executable\nln -s $MAESTRO_BUNDLE_LOC/maestro $MAESTRO_SYMLINK_LOC\n"
  },
  {
    "path": "install-scripts/ubuntu",
    "content": "#!/bin/sh\n\nPREINSTALL_LOC=.\nMAESTRO_BUNDLE_LOC=/usr/local/bin/maestro-bundle\nMAESTRO_SYMLINK_LOC=/usr/local/bin/maestro\n\n# Make maestro executable\necho Changing permissions for maestro executable\nchmod +x $PREINSTALL_LOC/maestro || echo Failed to change permissions for maestro executable, try running with sudo\n\n# Remove existing bundle files\necho Removing any existing maestro bundle files at $MAESTRO_BUNDLE_LOC\nrm -rf $MAESTRO_BUNDLE_LOC || echo Failed to remove any existing maestro bundle files at $MAESTRO_BUNDLE_LOC, try running with sudo\n\n# Move files to $MAESTRO_BUNDLE_LOC\necho Creating maestro bundle at $MAESTRO_BUNDLE_LOC\nmkdir -p $MAESTRO_BUNDLE_LOC || echo Failed to create maestro bundle directory at $MAESTRO_BUNDLE_LOC, try running with sudo\necho Moving files to $MAESTRO_BUNDLE_LOC\nmv $PREINSTALL_LOC/maestro $MAESTRO_BUNDLE_LOC/maestro || echo Failed to move maestro executable to $MAESTRO_BUNDLE_LOC, try running with sudo\nmv $PREINSTALL_LOC/_internal $MAESTRO_BUNDLE_LOC/_internal || echo Failed to move dependency files to $MAESTRO_BUNDLE_LOC, try running with sudo\n\n# Remove existing symlink\necho Removing any existing symlink at $MAESTRO_SYMLINK_LOC\nrm -rf $MAESTRO_SYMLINK_LOC || echo Failed to remove any existing maestro symlink at $MAESTRO_SYMLINK_LOC, try running with sudo\n\n# Create a symlink to the maestro executable\necho Creating symlink to maestro executable\nln -s $MAESTRO_BUNDLE_LOC/maestro $MAESTRO_SYMLINK_LOC || echo Failed to create symlink to maestro executable, try running with sudo\n"
  },
  {
    "path": "install-scripts/windows.nsi",
    "content": "!define PRODUCT_NAME \"maestro-cli\"\n\nOutFile \"maestro-installer.exe\"\n\nSection\n    ; Set installation directory\n    SetOutPath $PROGRAMFILES64\\maestro-bundle\n\n    ; Add files to installation directory\n    File ..\\dist\\maestro\\maestro.exe\n    File /r ..\\dist\\maestro\\_internal\n\n    ; Add $PROGRAMFILES64\\maestro-bundle to PATH\n    EnVar::SetHKCU\n    EnVar::AddValue \"Path\" \"$PROGRAMFILES64\\maestro-bundle\"\n\n    ; Add uninstaller registry key\n    WriteRegStr HKCU \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${PRODUCT_NAME}\" \"DisplayName\" \"${PRODUCT_NAME}\"\n    WriteRegStr HKCU \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${PRODUCT_NAME}\" \"UninstallString\" \"$PROGRAMFILES64\\maestro-uninstall.exe\"\nSectionEnd\n\nSection -Post\n    WriteUninstaller \"$PROGRAMFILES64\\maestro-uninstall.exe\"\nSectionEnd\n\nSection \"Uninstall\"\n    ; Remove $PROGRAMFILES64\\maestro-bundle\n    RMDir /r \"$PROGRAMFILES64\\maestro-bundle\"\n\n    ; Remove $PROGRAMFILES64\\maestro-bundle from PATH\n    EnVar::SetHKCU\n    EnVar::DeleteValue \"Path\" \"$PROGRAMFILES64\\maestro-bundle\"\n\n    ; Remove uninstaller registry key\n    DeleteRegKey HKCU \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${PRODUCT_NAME}\"\n\n    ; Remove uninstaller\n    Delete \"$PROGRAMFILES64\\maestro-uninstall.exe\"\nSectionEnd"
  },
  {
    "path": "maestro/__init__.py",
    "content": ""
  },
  {
    "path": "maestro/__main__.py",
    "content": "import sys\n\nfrom multiprocessing import freeze_support\n\nfrom maestro.main import cli\n\n\nif __name__ == \"__main__\":\n    # check if frozen\n    if getattr(sys, \"frozen\", False):\n        freeze_support()\n\n    # click passes ctx, no param needed\n    cli()  # pylint: disable=no-value-for-parameter\n"
  },
  {
    "path": "maestro/__version__.py",
    "content": "VERSION = \"2.0.6\""
  },
  {
    "path": "maestro/config.py",
    "content": "import os\n\nfrom datetime import date, datetime\nfrom urllib.parse import urljoin\n\n\n# region constants\n\nDISCORD_ID = 1039038199881810040\n\nPROMPT_MODES_LIST = [\"insert\", \"append\", \"tag\", \"find\"]\nPROMPT_MODES = {mode: i for i, mode in enumerate(PROMPT_MODES_LIST)}\nLOOP_MODES = {\n    \"none\": 0,\n    \"one\": 1,\n    \"inf\": 2,\n}\n\nEXTS = (\".mp3\", \".wav\", \".flac\", \".ogg\")\nMETADATA_KEYS = (\n    \"album\",\n    \"albumartist\",\n    \"artist\",\n    \"artwork\",\n    \"comment\",\n    \"compilation\",\n    \"composer\",\n    \"discnumber\",\n    \"genre\",\n    \"lyrics\",\n    \"totaldiscs\",\n    \"totaltracks\",\n    \"tracknumber\",\n    \"tracktitle\",\n    \"year\",\n    \"isrc\",\n    \"#bitrate\",\n    \"#codec\",\n    \"#length\",\n    \"#channels\",\n    \"#bitspersample\",\n    \"#samplerate\",\n)\nINDIC_SCRIPTS = (\n    \"bengali\",\n    \"assamese\",\n    \"modi\",\n    \"malayalam\",\n    \"devanagari\",\n    \"sinhala\",\n    \"tibetan\",\n    \"gurmukhi\",\n    \"tamil\",\n    \"balinese\",\n    \"thai\",\n    \"burmese\",\n    \"telugu\",\n    \"kannada\",\n    \"gujarati\",\n    \"urdu\",\n    \"lao\",\n    \"javanese\",\n    \"manipuri\",\n    \"oriya\",\n    \"khmer\",\n)\n\nCUR_YEAR = date.today().year\n\n\n# region paths\nMAESTRO_DIR = os.path.join(os.path.expanduser(\"~\"), \".maestro-files/\")\n\nSETTINGS_FILE = os.path.join(MAESTRO_DIR, \"settings.json\")\nLOGFILE = os.path.join(MAESTRO_DIR, \"maestro.log\")\nOLD_LOG_DIR = os.path.join(MAESTRO_DIR, \"old-logs/\")\nDEFAULT_SETTINGS = {\n    \"song_directory\": os.path.join(MAESTRO_DIR, \"songs/\"),\n    \"last_version_sync\": 0,\n}\n\nOLD_SONGS_INFO_PATH = os.path.join(MAESTRO_DIR, \"songs.txt\")\nSONGS_INFO_PATH = os.path.join(MAESTRO_DIR, \"songs.json\")\nOLD_STATS_DIR = os.path.join(MAESTRO_DIR, \"stats/\")\nOVERRIDE_LYRICS_DIR = os.path.join(MAESTRO_DIR, \"override-lyrics/\")\nTRANSLATED_LYRICS_DIR = os.path.join(MAESTRO_DIR, \"translated-lyrics/\")\n# endregion\n\n# region player\nHORIZONTAL_BLOCKS = {\n    1: \"▏\",\n    2: \"▎\",\n    3: \"▍\",\n    4: \"▌\",\n    5: \"▋\",\n    6: \"▊\",\n    7: \"▉\",\n    8: \"█\",\n}\nSCRUB_TIME = 5  # in seconds\nVOLUME_STEP = 1\nMIN_PROGRESS_BAR_WIDTH = 20\nMIN_VOLUME_BAR_WIDTH, MAX_VOLUME_BAR_WIDTH = 10, 40\nLYRIC_PADDING = 3\n\n_FARTHEST_RIGHT_CONTROL_DESC = 5\nINDENT_CONTROL_DESC = 0\nPLAY_CONTROLS = [\n    (\"SPACE\", \"pause/play\"),\n    (\"b\", \"go [b]ack to previous song\"),\n    (\"r\", \"[r]eplay song\"),\n    (\"n\", \"skip to [n]ext song\"),\n    (\n        \"l\",\n        \"[l]oop the current song once ('l' in status bar). press again to loop infinitely ('L' in status bar). press once again to turn off looping\",\n    ),\n    (\"c\", \"toggle [c]lip mode\"),\n    (\"v\", \"toggle [v]isualization\"),\n    (\"LEFT\", \"rewind 5s\"),\n    (\"RIGHT\", \"fast forward 5s\"),\n    (\"[/-\", \"decrease volume\"),\n    (\"]/=\", \"increase volume (] has issues on Windows)\"),\n    (\"m\", \"[m]ute/unmute\"),\n    (\n        \"e\",\n        \"[e]nd the song player after the current song finishes (indicator in status bar, 'e' to cancel)\",\n    ),\n    (\"q\", \"[q]uit the song player immediately\"),\n    (\n        \"UP/DOWN\",\n        \"to scroll through the queue/lyrics (mouse scrolling should also work)\",\n    ),\n    (\n        \"SHIFT+UP/DOWN\",\n        \"move the selected song up/down in the queue\",\n    ),\n    (\"ENTER\", \"play the selected song/seek to selected lyric\"),\n    (\"p\", \"sna[p] back to the currently playing song/lyric\"),\n    (\n        \"g\",\n        \"go to the next pa[g]e/loop of the queue (ignored if not repeating queue)\",\n    ),\n    (\n        \"BACKSPACE/DELETE\",\n        \"delete the selected (not necessarily currently playing!) song from the queue\",\n    ),\n    (\"d\", \"toggle [D]iscord rich presence\"),\n    (\n        \"a\",\n        \"[a]dd a song to the end of the queue (opens a prompt to enter the song name or ID: ENTER to confirm, ESC to cancel)\",\n    ),\n    (\n        \"i\",\n        \"[i]nsert a song in the queue after the selected song (opens a prompt like 'a')\",\n    ),\n    (\n        \",\",\n        \"add (comma-separated) tag(s) to all songs in the queue (opens a prompt like 'a')\",\n    ),\n    (\n        \"s\",\n        \"toggle [s]tream (streams to maestro-music.vercel.app/listen-along/[USERNAME]), requires login\",\n    ),\n    (\"y\", \"toggle l[y]rics\"),\n    (\n        \"t\",\n        \"toggle [t]ranslated lyrics (if available, ignored if lyrics mode is off)\",\n    ),\n    (\"{/_\", \"focus queue\"),\n    (\"}/+\", \"focus lyrics (} has issues on Windows)\"),\n    (\n        \"o\",\n        \"rel[o]ad song data (useful if you've changed e.g lyrics, tags, metadata, etc. while playing)\",\n    ),\n    (\"h\", \"toggle this [h]elp message\"),\n    (\"f\", \"[f]ind a song in the queue (opens a prompt like 'a')\"),\n]\nfor key, desc in PLAY_CONTROLS:\n    if INDENT_CONTROL_DESC < len(key) <= _FARTHEST_RIGHT_CONTROL_DESC:\n        INDENT_CONTROL_DESC = len(key)\n# endregion\n\n# region visualizer\nFPS = 60\n\nSTEP_SIZE = 512  # librosa default\nVIS_SAMPLE_RATE = STEP_SIZE * FPS\n\nVERTICAL_BLOCKS = {\n    0: \" \",\n    1: \"▁\",\n    2: \"▂\",\n    3: \"▃\",\n    4: \"▄\",\n    5: \"▅\",\n    6: \"▆\",\n    7: \"▇\",\n    8: \"█\",\n}\nVISUALIZER_HEIGHT = 8  # should divide 80\nWAVEFORM_HEIGHT = 6  # should also divide 80\n\nVIS_FLATTEN_FACTOR = 3  # higher = more flattening; 1 = no flattening\nWAVEFORM_FLATTEN_FACTOR = 20\n# endregion\n\n# region stream\nSTREAM_SAMPLE_RATE = 44100\nSTREAM_CHUNK_SIZE = 256\n\nICECAST_SERVER = (\n    \"maestro-icecast.eastus2.cloudapp.azure.com\"  # Azure-hosted Icecast server\n)\n\nMAESTRO_SITE = \"https://maestro-music.vercel.app\"\n# MAESTRO_SITE = \"http://localhost:3000\"  # DEBUG\n\nIMAGE_URL = f\"{MAESTRO_SITE}/api/get_artwork/\"\n# endregion\n\n# region auth\nAUTH_SERVER = f\"{MAESTRO_SITE}/api/\"\n# AUTH_SERVER = \"http://localhost:5001/api/\"  # DEBUG\nUSER_EXISTS_URL = urljoin(AUTH_SERVER, \"user_exists\")\nSIGNUP_URL = urljoin(AUTH_SERVER, \"signup\")\nLOGIN_URL = urljoin(AUTH_SERVER, \"login\")\nUPDATE_METADATA_URL = urljoin(AUTH_SERVER, \"update_metadata\")\nUPDATE_ARTWORK_URL = urljoin(AUTH_SERVER, \"update_artwork\")\nUPDATE_TIMESTAMP_URL = urljoin(AUTH_SERVER, \"update_timestamp\")\n# endregion\n\n# endregion\n\n\nsettings = {}\n\n\ndef print_to_logfile(*args, **kwargs):\n    if \"file\" in kwargs:\n        raise ValueError(\"file kwargs not allowed for 'print_to_logfile'\")\n    print(\n        datetime.now().strftime(\"[%Y-%m-%d %H:%M:%S]\"),\n        *args,\n        **kwargs,\n        file=open(LOGFILE, \"a\", encoding=\"utf-8\"),\n    )\n"
  },
  {
    "path": "maestro/helpers.py",
    "content": "# region imports\n\nimport atexit\nimport curses\nimport logging\nimport os\nimport subprocess\nimport threading\n\nlogging.disable(logging.CRITICAL)\n\nimport click\nimport msgspec\n\nfrom getpass import getpass\nfrom random import randint\nfrom time import sleep, time\nfrom typing import Iterable\nfrom urllib.parse import quote, quote_plus\n\nfrom maestro import config\nfrom maestro.config import print_to_logfile\n\n# endregion\n\n\nclass Song:\n    def __init__(self, song_id: int):\n        if song_id < 1:\n            raise ValueError(\"Song ID must be greater than 0.\")\n        self._song_id = song_id\n\n        self._metadata = None\n        self._metadata_changed = False\n\n        self._parsed_lyrics = False\n        self._parsed_override_lyrics = False\n        self._parsed_translated_lyrics = False\n\n        atexit.register(self._save)\n\n    def reset(self):\n        self._metadata = None\n        self._metadata_changed = False\n\n        self._parsed_lyrics = False\n        self._parsed_override_lyrics = False\n        self._parsed_translated_lyrics = False\n\n    def __eq__(self, value):\n        if not isinstance(value, type(self)):\n            return False\n        return value.song_id == self.song_id\n\n    def __hash__(self):\n        return hash(self.song_id)\n\n    def __repr__(self):\n        return f\"Song(ID={self.song_id})\"\n\n    @property\n    def override_lyrics_path(self):\n        return os.path.join(\n            config.OVERRIDE_LYRICS_DIR, f\"{self.song_title}.lrc\"\n        )\n\n    @property\n    def translated_lyrics_path(self):\n        return os.path.join(\n            config.TRANSLATED_LYRICS_DIR, f\"{self.song_title}.lrc\"\n        )\n\n    @property\n    def song_id(self):\n        return self._song_id\n\n    @property\n    def song_file(self):\n        \"\"\"e.g. song.mp3\"\"\"\n        return SONG_DATA[self._song_id][\"filename\"]\n\n    @property\n    def song_path(self):\n        \"\"\"e.g. /path/to/song.mp3\"\"\"\n        return os.path.join(config.settings[\"song_directory\"], self.song_file)\n\n    @property\n    def song_title(self):\n        \"\"\"e.g. 'song'\"\"\"\n        return os.path.splitext(self.song_file)[0]\n\n    @song_title.setter\n    def song_title(self, v):\n        old_path = self.song_path\n        old_override_lyrics_path = self.override_lyrics_path\n        old_translated_lyrics_path = self.translated_lyrics_path\n\n        SONG_DATA[self._song_id][\"filename\"] = (\n            v + os.path.splitext(self.song_file)[1]\n        )\n\n        if os.path.exists(old_path):\n            os.rename(old_path, self.song_path)\n        if os.path.exists(old_override_lyrics_path):\n            os.rename(old_override_lyrics_path, self.override_lyrics_path)\n        if os.path.exists(old_translated_lyrics_path):\n            os.rename(old_translated_lyrics_path, self.translated_lyrics_path)\n\n        self._load_metadata()\n        self._metadata[\"tracktitle\"] = v\n        self._metadata_changed = True\n\n    @property\n    def tags(self) -> set[str]:\n        return SONG_DATA[self._song_id][\"tags\"]\n\n    @tags.setter\n    def tags(self, v: set[str]):\n        SONG_DATA[self._song_id][\"tags\"] = v\n\n    @property\n    def clips(self) -> dict[str, list[int, int]]:\n        return SONG_DATA[self._song_id][\"clips\"]\n\n    @property\n    def set_clip(self) -> str:\n        return SONG_DATA[self._song_id][\"set-clip\"]\n\n    @set_clip.setter\n    def set_clip(self, v: str):\n        SONG_DATA[self._song_id][\"set-clip\"] = v\n\n    @property\n    def listen_times(self) -> dict[int | str, float]:\n        return SONG_DATA[self._song_id][\"stats\"]\n\n    def _load_metadata(self):\n        import music_tag\n\n        self._metadata = music_tag.load_file(self.song_path)\n\n    @property\n    def artist(self):\n        return self.get_metadata(\"artist\") or \"No Artist\"\n\n    @artist.setter\n    def artist(self, v):\n        self.set_metadata(\"artist\", v)\n\n    @property\n    def album(self):\n        return self.get_metadata(\"album\") or \"No Album\"\n\n    @album.setter\n    def album(self, v):\n        self.set_metadata(\"album\", v)\n\n    @property\n    def album_artist(self):\n        return self.get_metadata(\"albumartist\") or \"No Album Artist\"\n\n    @album_artist.setter\n    def album_artist(self, v):\n        self.set_metadata(\"albumartist\", v)\n\n    @property\n    def duration(self):\n        return self.get_metadata(\"#length\")\n\n    @property\n    def artwork(self):\n        if self._metadata is None:\n            self._load_metadata()\n        return (\n            self._metadata[\"artwork\"].first\n            if \"artwork\" in self._metadata\n            else None\n        )\n\n    @property\n    def raw_lyrics(self) -> str | None:\n        return self.get_metadata(\"lyrics\")\n\n    @raw_lyrics.setter\n    def raw_lyrics(self, v):\n        if self._metadata is None:\n            self._load_metadata()\n\n        if v is None and \"lyrics\" in self._metadata:\n            del self._metadata[\"lyrics\"]\n        else:\n            self._metadata[\"lyrics\"] = v\n        self._parsed_lyrics = False\n        self._metadata_changed = True\n\n    @property\n    def raw_override_lyrics(self) -> str | None:\n        if not os.path.exists(self.override_lyrics_path):\n            return None\n        with open(self.override_lyrics_path, \"r\", encoding=\"utf-8\") as f:\n            return f.read()\n\n    @raw_override_lyrics.setter\n    def raw_override_lyrics(self, v):\n        import safer\n\n        if v is None:\n            if os.path.exists(self.override_lyrics_path):\n                os.remove(self.override_lyrics_path)\n        else:\n            os.makedirs(config.OVERRIDE_LYRICS_DIR, exist_ok=True)\n            with safer.open(\n                self.override_lyrics_path, \"w\", encoding=\"utf-8\"\n            ) as f:\n                f.write(v)\n\n        self._parsed_override_lyrics = False\n\n    @property\n    def raw_translated_lyrics(self) -> str | None:\n        if not os.path.exists(self.translated_lyrics_path):\n            return None\n        with open(self.translated_lyrics_path, \"r\", encoding=\"utf-8\") as f:\n            return f.read()\n\n    @raw_translated_lyrics.setter\n    def raw_translated_lyrics(self, v):\n        import safer\n\n        if v is None:\n            if os.path.exists(self.translated_lyrics_path):\n                os.remove(self.translated_lyrics_path)\n        else:\n            os.makedirs(config.TRANSLATED_LYRICS_DIR, exist_ok=True)\n            with safer.open(\n                self.translated_lyrics_path, \"w\", encoding=\"utf-8\"\n            ) as f:\n                f.write(v)\n\n    def _parse_lyrics(self, raw_lyrics):\n        if raw_lyrics is None:\n            return None\n\n        raw_lyrics_list = raw_lyrics.splitlines()\n        for line in raw_lyrics_list:\n            if line and not line.strip().startswith(\"[\"):  # not LRC format\n                return raw_lyrics_list\n\n        import pylrc\n\n        return pylrc.parse(raw_lyrics) if raw_lyrics else None\n\n    @property\n    def parsed_lyrics(self):\n        if self._parsed_lyrics is False:\n            self._parsed_lyrics = self._parse_lyrics(self.raw_lyrics)\n        return self._parsed_lyrics\n\n    @property\n    def parsed_override_lyrics(self):\n        if self._parsed_override_lyrics is False:\n            self._parsed_override_lyrics = self._parse_lyrics(\n                self.raw_override_lyrics\n            )\n        return self._parsed_override_lyrics\n\n    @property\n    def parsed_translated_lyrics(self):\n        if self._parsed_translated_lyrics is False:\n            self._parsed_translated_lyrics = self._parse_lyrics(\n                self.raw_translated_lyrics\n            )\n        return self._parsed_translated_lyrics\n\n    def get_metadata(self, key, resolve=True):\n        \"\"\"\n        Get metadata value for `key`.\n\n        If 'resolve' is False, then a MetadataItem is returned instead of the\n        resolved value.\n        \"\"\"\n        if self._metadata is None:\n            self._load_metadata()\n\n        if key not in self._metadata:\n            return None\n        if resolve:\n            return self._metadata[key].first\n        return self._metadata[key]\n\n    def set_metadata(self, key, value):\n        if self._metadata is None:\n            self._load_metadata()\n\n        if key not in config.METADATA_KEYS:\n            raise ValueError(f\"{key} is not a valid metadata key.\")\n        if key.startswith(\"#\"):\n            raise ValueError(f\"{key} is not editable.\")\n\n        if key == \"tracktitle\":\n            self.song_title = value  # also change file names\n        elif key == \"lyrics\":\n            self.raw_lyrics = value  # unset self._parsed_lyrics\n        elif value is None:\n            if key in self._metadata:\n                del self._metadata[key]\n        else:\n            self._metadata[key] = value\n\n        self._metadata_changed = True\n\n    def remove_from_data(self):\n        del SONG_DATA[self.song_id]\n\n    def _save(self):\n        if self._metadata_changed:\n            self._metadata.save()\n\n\nclass SongData:\n    def __init__(self):\n        self.songs = None\n        atexit.register(self._save)\n\n    def load(self):\n        self.songs = {}\n        with open(config.SONGS_INFO_PATH, \"r\", encoding=\"utf-8\") as f:\n            s = f.read()\n            if not s:\n                return\n            d = msgspec.json.decode(s)\n            for k, v in d.items():\n                self.songs[int(k)] = v\n\n                if \"tags\" not in v:\n                    v[\"tags\"] = set()\n                else:\n                    v[\"tags\"] = set(v[\"tags\"])\n\n                v[\"stats_\"] = {}\n                for year in v[\"stats\"]:\n                    if year.isdigit():\n                        v[\"stats_\"][int(year)] = v[\"stats\"][year]\n                    else:\n                        v[\"stats_\"][year] = v[\"stats\"][year]\n                v[\"stats\"] = v.pop(\"stats_\")\n                if \"set-clip\" not in v:\n                    v[\"set-clip\"] = \"default\"\n\n    def __getitem__(self, key):\n        if self.songs is None:\n            self.load()\n        return self.songs[key]\n\n    def __setitem__(self, key, value):\n        if self.songs is None:\n            self.load()\n        self.songs[key] = value\n\n    def __delitem__(self, key):\n        if self.songs is None:\n            self.load()\n        del self.songs[key]\n\n    def __iter__(self):\n        if self.songs is None:\n            self.load()\n        return iter(self.songs)\n\n    def items(self):\n        if self.songs is None:\n            self.load()\n        return self.songs.items()\n\n    def values(self):\n        if self.songs is None:\n            self.load()\n        return self.songs.values()\n\n    def _save(self):\n        import safer\n\n        if self.songs is not None:\n            with safer.open(config.SONGS_INFO_PATH, \"wb\") as f:\n                f.write(msgspec.json.encode(self.songs))\n\n    def add_song(self, filename, tags=None):\n        if tags is None:\n            tags = set()\n\n        if self.songs is None:\n            self.load()\n        if not self.songs:\n            song_id = 1\n        else:\n            song_id = max(self) + 1\n        self.songs[song_id] = {\n            \"filename\": os.path.split(filename)[1],\n            \"tags\": set(tags),\n            \"clips\": {},\n            \"stats\": {\n                config.CUR_YEAR: 0.0,\n                \"total\": 0.0,\n            },\n            \"set-clip\": \"default\",\n        }\n\n        song = Song(song_id)\n        song.set_metadata(\"tracktitle\", song.song_title)\n\n        return song\n\n\nSONG_DATA = SongData()\n\n\nclass Songs:\n    \"\"\"\n    Wrapper around dict of all `Song` objects.\n    \"\"\"\n\n    def __init__(self):\n        self._songs = None\n        self._song_data = SONG_DATA\n\n    def load(self):\n        self._songs = {Song(k) for k in self._song_data}\n\n    def __contains__(self, value: Song):\n        if self._songs is None:\n            self.load()\n        return value in self._songs\n\n    def __iter__(self) -> Iterable[Song]:\n        if self._songs is None:\n            self.load()\n        return iter(self._songs)\n\n    def __len__(self):\n        if self._songs is None:\n            self.load()\n        return len(self._songs)\n\n\nSONGS = Songs()\n\n\ndef is_safe_username(url):\n    return quote(url, safe=\"\") == url if url else False\n\n\ndef bounded_shuffle(lst, radius=-1):\n    \"\"\"\n    Randomly shuffle `lst`, but with the constraint that each element can only\n    move at most `radius` positions away from its original position.\n\n    To shuffle with no bounds, set `radius = -1`.\n    \"\"\"\n    n = len(lst)\n    if radius == -1:\n        radius = n\n    elif radius == 0:\n        return\n\n    index_at = list(range(n))\n    for i in range(n - 1, 0, -1):\n        j = randint(max(0, index_at[i] - radius), i)\n        index_at[j], index_at[i] = index_at[i], index_at[j]\n        lst[j], lst[i] = lst[i], lst[j]\n\n\ndef set_timeout(func, timeout, *args, **kwargs):\n    def wrapper():\n        sleep(timeout)\n        func()\n\n    threading.Thread(\n        target=wrapper, daemon=True, args=args, kwargs=kwargs\n    ).start()\n\n\nclass Scroller:\n    def __init__(self, num_lines, win_size):\n        self.num_lines = num_lines\n        self.win_size = win_size\n        self.pos = 0\n        self.top = 0\n\n    def scroll_forward(self):\n        if self.pos < self.num_lines - 1:\n            if (\n                self.pos == self.halfway\n                and self.top < self.num_lines - self.win_size\n            ):\n                self.top += 1\n            self.pos += 1\n\n    def scroll_backward(self):\n        if self.pos > 0:\n            if self.pos == self.halfway and self.top > 0:\n                self.top -= 1\n            self.pos -= 1\n\n    @property\n    def halfway(self):\n        return self.top + (self.win_size - 1) // 2\n\n    def resize(self, win_size=None):\n        if win_size is not None:\n            self.win_size = win_size\n        self.top = max(0, self.pos - (self.win_size - 1) // 2)\n        self.top = max(0, min(self.num_lines - self.win_size, self.top))\n\n    def refresh(self):\n        self.resize()\n\n\ndef fit_string_to_width(s, width, length_so_far):\n    if length_so_far + len(s) > width:\n        remaining_width = width - length_so_far\n        if remaining_width >= 3:\n            s = s[: (remaining_width - 3)] + \"...\"\n        else:\n            s = \".\" * remaining_width\n    length_so_far += len(s)\n    return s, length_so_far\n\n\ndef addstr_fit_to_width(stdscr, s, width, length_so_far, *args, **kwargs):\n    s, length_so_far = fit_string_to_width(s, width, length_so_far)\n    if s:\n        if length_so_far <= width:\n            stdscr.addstr(s, *args, **kwargs)\n        else:\n            stdscr.addstr(s[:-1], *args, **kwargs)\n            stdscr.insstr(s[-1], *args, **kwargs)\n    return length_so_far\n\n\nclass FFmpegProcessHandler:\n    def __init__(self, username, password):\n        self.process = None\n        self.username = username\n        self.password = password\n\n    def start(self):\n        threading.Thread(target=self._start, daemon=True).start()\n\n    def _start(self):\n        from spotdl.utils.ffmpeg import get_ffmpeg_path\n\n        self.process = subprocess.Popen(\n            # fmt: off\n            [\n                str(get_ffmpeg_path()),\n                \"-re\",  # Read input at native frame rate\n                \"-f\", \"s16le\",  # Raw PCM 16-bit little-endian audio\n                \"-ar\", str(config.STREAM_SAMPLE_RATE),  # Set the audio sample rate\n                \"-ac\", \"2\",  # Set the number of audio channels to 2 (stereo)\n                '-i', 'pipe:',  # Input from stdin\n                \"-f\", \"mp3\",  # Output format\n                # \"-report\",  # DEBUG\n                f\"icecast://{self.username}:{self.password}@{config.ICECAST_SERVER}:8000/{self.username}\",  # Azure-hosted maestro Icecast URL\n            ],\n            # fmt: on\n            stdin=subprocess.PIPE,\n            stdout=subprocess.DEVNULL,\n            stderr=subprocess.DEVNULL,\n        )\n\n    def terminate(self):\n        if self.process is not None:\n            self.process.terminate()\n            self.process = None\n\n    def restart(self):\n        self.terminate()\n        self.start()\n\n    def write(self, chunk):\n        if self.process is not None:\n            try:\n                self.process.stdin.write(chunk)\n            except BrokenPipeError as e:  # pylint: disable=unused-variable\n                print_to_logfile(\"FFmpeg processs error:\", e)\n\n\nclass PlaybackHandler:\n    def __init__(\n        self,\n        stdscr: \"curses._CursesWindow\",\n        playlist: list[Song],\n        clip_mode,\n        visualize,\n        stream,\n        creds,\n        want_lyrics,\n        want_translated_lyrics,\n    ):\n        from just_playback import Playback\n\n        self.stdscr = stdscr\n        self.scroller = Scroller(\n            len(playlist), stdscr.getmaxyx()[0] - 2  # -2 for status bar\n        )\n        self.playlist = playlist\n        self.i = 0\n        self._volume = 0\n        self.clip_mode = clip_mode\n        self.want_discord = False\n        self.want_vis = visualize  # want to visualize\n        self._want_stream = stream  # want to stream\n        self.username, self.password = creds\n        self.want_lyrics = want_lyrics\n        self.want_translated_lyrics = want_translated_lyrics and want_lyrics\n\n        self.playback = Playback()\n        self._paused = False\n        self.last_timestamp = 0\n        self.looping_current_song = config.LOOP_MODES[\"none\"]\n        self.duration = 0\n        self.restarting = False\n        self.ending = False\n        self.prompting: None | tuple = None\n        self.clip = (0, 0)\n\n        self.italic = True\n\n        self.can_mac_now_playing = False\n        self.mac_now_playing = None\n        self.update_now_playing = False\n\n        self.discord_connected = 2\n        self.discord_rpc = None\n        self.discord_last_update = 0\n        self.can_update_discord = True  # pypresence installed\n        self.discord_updating = False  # lock\n\n        self._librosa = None\n        self.can_visualize = True\n        self.can_show_visualization = (\n            self.want_vis\n            # space to show visualization\n            and self.screen_height > config.VISUALIZER_HEIGHT + 5\n        )\n\n        self.audio_data = None\n        self.audio_data = {}  # dict(song_id: (vis data, stream data))\n        self.audio_processing_thread = threading.Thread(\n            target=self._audio_processing_loop,\n            daemon=True,\n        )\n        self.audio_processing_thread.start()\n        self.compiled = None\n\n        self.ffmpeg_process = FFmpegProcessHandler(self.username, self.password)\n        if self.want_stream:\n            self.ffmpeg_process.start()\n        self.break_stream_loop = False\n        self.streaming_thread = threading.Thread(\n            target=self._streaming_loop,\n            daemon=True,\n        )\n        self.streaming_thread.start()\n\n        self.lyrics: list | None = None\n        self.translated_lyrics: list | None = None\n        self.lyrics_scroller = Scroller(0, 0)\n        self.lyrics_width = 50\n        self.lyric_pos = None\n\n        self.show_help = False\n        self.help_pos = 0\n\n        self._focus = 0  # 0: queue, 1: lyrics\n\n    def _load_audio(self, path, sr):\n        import numpy as np\n\n        # shape = (# channels, # frames)\n        audio_data = self._librosa.load(path, mono=False, sr=sr)[0]\n\n        if len(audio_data.shape) == 1:  # mono -> stereo\n            audio_data = np.repeat([audio_data], 2, axis=0)\n        elif audio_data.shape[0] == 1:  # mono -> stereo\n            audio_data = np.repeat(audio_data, 2, axis=0)\n        elif audio_data.shape[0] == 6:  # 5.1 -> stereo\n            audio_data = np.delete(audio_data, (1, 3, 4, 5), axis=0)\n\n        return audio_data\n\n    def _audio_processing_loop(self):\n        import numpy as np\n\n        try:\n            from librosa import load, stft, amplitude_to_db\n\n            self._librosa = type(\n                \"librosa\",\n                (),\n                {\n                    \"load\": staticmethod(load),\n                    \"stft\": staticmethod(stft),\n                    \"amplitude_to_db\": staticmethod(amplitude_to_db),\n                },\n            )\n        except ImportError:\n            self.can_visualize = False\n            self.can_show_visualization = False\n            print_to_logfile(\n                \"Librosa not installed. Visualization will be disabled.\"\n            )\n\n        while True:\n            try:\n                keys_to_delete = []\n                for k in self.audio_data:\n                    if k not in self.playlist[self.i : self.i + 5]:\n                        keys_to_delete.append(k)\n                for k in keys_to_delete:\n                    del self.audio_data[k]\n\n                for i in range(self.i, min(self.i + 5, len(self.playlist))):\n                    processing_song = self.playlist[i]\n\n                    if self.song != processing_song and (\n                        self.song not in self.audio_data\n                        or (\n                            self.want_vis\n                            and self.audio_data[self.song][0] is None\n                        )\n                        or (\n                            self.want_stream\n                            and self.audio_data[self.song][1] is None\n                        )\n                    ):\n                        break\n                    if processing_song in self.audio_data and (\n                        (\n                            self.audio_data[processing_song][0] is not None\n                            or not self.want_vis\n                        )\n                        and (\n                            self.audio_data[processing_song][1] is not None\n                            or not self.want_stream\n                        )\n                        or self._librosa is None\n                    ):\n                        continue\n\n                    processing_song_path = (\n                        os.path.join(  # NOTE: NOT SAME AS self.song_path\n                            config.settings[\"song_directory\"],\n                            self.playlist[i].song_file,\n                        )\n                    )\n\n                    if processing_song not in self.audio_data:\n                        self.audio_data[processing_song] = [\n                            (\n                                self._librosa.amplitude_to_db(\n                                    np.abs(\n                                        self._librosa.stft(\n                                            self._load_audio(\n                                                processing_song_path,\n                                                sr=config.VIS_SAMPLE_RATE,\n                                            )\n                                        )\n                                    ),\n                                    ref=np.max,\n                                )\n                                + 80\n                                if self.want_vis and self.can_visualize\n                                else None\n                            ),\n                            (\n                                np.int16(\n                                    self._load_audio(\n                                        processing_song_path,\n                                        sr=config.STREAM_SAMPLE_RATE,\n                                    )\n                                    * (2**15 - 1)\n                                    * 0.5  # reduce volume (avoid clipping)\n                                )  # convert to 16-bit PCM\n                                if self.want_stream\n                                else None\n                            ),\n                        ]\n                    else:\n                        if (\n                            self.audio_data[processing_song][0] is None\n                            and self.want_vis\n                            and self.can_visualize\n                        ):\n                            self.audio_data[processing_song][0] = (\n                                self._librosa.amplitude_to_db(\n                                    np.abs(\n                                        self._librosa.stft(\n                                            self._load_audio(\n                                                processing_song_path,\n                                                sr=config.VIS_SAMPLE_RATE,\n                                            )\n                                        )\n                                    ),\n                                    ref=np.max,\n                                )\n                                + 80\n                            )\n                        if (\n                            self.audio_data[processing_song][1] is None\n                            and self.want_stream\n                        ):\n                            self.audio_data[processing_song][1] = np.int16(\n                                self._load_audio(\n                                    processing_song_path,\n                                    sr=config.STREAM_SAMPLE_RATE,\n                                )\n                                * (2**15 - 1)\n                                * 0.5  # reduce volume (avoid clipping)\n                            )  # convert to 16-bit PCM\n            except:  # hacky fix  # pylint: disable=bare-except\n                pass\n\n            sleep(1)\n\n    def _streaming_loop(self):\n        while True:\n            if (\n                self.want_stream\n                and self.username is not None\n                and self.audio_data is not None\n                and self.song in self.audio_data\n                and self.audio_data[self.song][1] is not None\n                and self.playback is not None\n                # is 0 for a while after resuming, and is -1 if playback is\n                # inactive or file is not loaded\n                and self.playback.curr_pos > 0\n            ):\n                for fpos in range(\n                    int(self.playback.curr_pos * config.STREAM_SAMPLE_RATE),\n                    self.audio_data[self.song][1].shape[1],\n                    config.STREAM_CHUNK_SIZE,\n                ):\n                    try:\n                        # print_to_logfile(\n                        #     self.song_id,\n                        #     fpos / config.STREAM_SAMPLE_RATE,\n                        #     self.playback.curr_pos,\n                        # )  # DEBUG\n                        self.ffmpeg_process.write(\n                            self.audio_data[self.song][1][\n                                :,\n                                fpos : fpos + config.STREAM_CHUNK_SIZE,\n                            ]\n                            .reshape((-1,), order=\"F\")\n                            .tobytes()\n                            if not self.paused\n                            else b\"\\x00\" * 4 * config.STREAM_CHUNK_SIZE\n                        )\n                    except KeyError as e:\n                        print_to_logfile(\"KeyError in streaming loop:\", e)\n                        self.update_stream_metadata()\n\n                    if self.break_stream_loop:\n                        self.break_stream_loop = False\n                        break\n\n            sleep(0.01)\n\n    # region properties\n\n    @property\n    def paused(self):\n        return self._paused\n\n    @paused.setter\n    def paused(self, value):\n        self._paused = value\n        if self.want_stream:\n            self.threaded_update_icecast_metadata()\n\n    @property\n    def volume(self):\n        return self._volume\n\n    @volume.setter\n    def volume(self, v):\n        self._volume = v\n        if self.playback is not None:\n            self.playback.set_volume(v / 100)\n\n    @property\n    def want_stream(self):\n        return self._want_stream\n\n    @want_stream.setter\n    def want_stream(self, value):\n        if self._librosa is None:\n            value = False\n        self._want_stream = value\n\n    @property\n    def song(self):\n        return self.playlist[self.i]\n\n    @property\n    def song_id(self):\n        return self.song.song_id\n\n    @property\n    def song_file(self):\n        return self.song.song_file\n\n    @property\n    def song_path(self):\n        return self.song.song_path\n\n    @property\n    def song_title(self):\n        return self.song.song_title\n\n    @property\n    def song_artist(self):\n        return self.song.artist\n\n    @property\n    def song_album(self):\n        return self.song.album\n\n    @property\n    def album_artist(self):\n        return self.song.album_artist\n\n    @property\n    def artwork(self):\n        return (\n            self.song.artwork.raw_thumbnail([1024, 1024])\n            if self.song.artwork\n            else None\n        )\n\n    @property\n    def screen_height(self):\n        return self.stdscr.getmaxyx()[0]\n\n    @property\n    def screen_width(self):\n        return self.stdscr.getmaxyx()[1]\n\n    @property\n    def can_show_lyrics(self):\n        return self.want_lyrics and self.lyrics is not None\n\n    @property\n    def can_show_translated_lyrics(self):\n        return (\n            self.want_translated_lyrics and self.translated_lyrics is not None\n        )\n\n    @property\n    def focus(self):\n        return self._focus if self.can_show_lyrics else 0\n\n    @focus.setter\n    def focus(self, value):\n        self._focus = value if self.can_show_lyrics else 0\n\n    # endregion\n\n    def seek(self, pos):\n        if self.playback is not None:\n            pos = max(self.clip[0] if self.clip_mode else 0, pos)\n            self.playback.seek(pos)\n            self.break_stream_loop = True\n            if self.can_mac_now_playing and self.mac_now_playing is not None:\n                self.mac_now_playing.pos = round(pos)\n                self.update_now_playing = True\n            self.last_timestamp = pos\n\n    def scroll_forward(self):\n        if self.show_help:\n            self.help_pos += 1\n        elif self.focus == 1:\n            if self.lyric_pos is None:\n                self.lyric_pos = self.lyrics_scroller.pos\n            self.lyric_pos = min(self.lyric_pos + 1, len(self.lyrics) - 1)\n        elif self.focus == 0:\n            self.scroller.scroll_forward()\n\n    def scroll_backward(self):\n        if self.show_help:\n            self.help_pos -= 1\n        elif self.focus == 1:\n            if self.lyric_pos is None:\n                self.lyric_pos = self.lyrics_scroller.pos\n            self.lyric_pos = max(self.lyric_pos - 1, 0)\n        elif self.focus == 0:\n            self.scroller.scroll_backward()\n\n    def snap_back(self):\n        if self.focus == 1:\n            self.lyric_pos = None\n        elif self.focus == 0:\n            self.scroller.pos = self.i\n            self.scroller.refresh()\n\n    def set_volume(self, v):\n        \"\"\"Set volume w/o changing self.volume.\"\"\"\n        self.playback.set_volume(v / 100)\n\n    def quit(self):\n        self.playback.stop()\n        if self.ffmpeg_process is not None:\n            self.ffmpeg_process.terminate()\n        if self.discord_rpc is not None:\n            self.discord_rpc.close()\n\n    def prompting_delete_char(self):\n        if self.prompting[1] > 0:\n            self.prompting = (\n                self.prompting[0][: self.prompting[1] - 1]\n                + self.prompting[0][self.prompting[1] :],\n                self.prompting[1] - 1,\n                self.prompting[2],\n            )\n\n    def update_screen(self):\n        self.output(self.playback.curr_pos)\n\n    def connect_to_discord(self):\n        try:\n            from pypresence import Client as DiscordRPCClient\n        except ImportError:\n            print_to_logfile(\n                \"pypresence not installed. Discord presence will be disabled.\"\n            )\n            self.can_update_discord = False\n        discord_rpc = DiscordRPCClient(client_id=config.DISCORD_ID)\n        discord_rpc.start()\n        return discord_rpc\n\n    def update_discord_metadata(self):\n        if self.discord_updating:\n            return\n        if self.can_update_discord and self.want_discord:\n            self.discord_updating = True\n\n            t = time()\n            if self.discord_last_update + 15 > t:\n                sleep(15 - (t - self.discord_last_update))\n            song_name, artist_name, album_name = \"\", \"\", \"\"\n\n            # minimum 2 characters (Discord requirement)\n            new_song_name = self.song_title.ljust(2)\n            new_artist_name = \"by \" + self.song_artist\n            new_album_name = self.song_album.ljust(2)\n\n            if (\n                new_song_name != song_name\n                or new_artist_name != artist_name\n                or new_album_name != album_name\n            ):\n                song_name = new_song_name\n                artist_name = new_artist_name\n                album_name = new_album_name\n\n                d = dict(\n                    details=song_name,\n                    state=artist_name,\n                    large_image=(\n                        f\"{config.IMAGE_URL}/{self.username}?_={time()}\"\n                        if self.username\n                        else \"maestro-icon\"\n                    ),\n                    small_image=\"maestro-icon-small\",\n                    large_text=album_name,\n                    buttons=(\n                        [\n                            {\n                                \"label\": \"Listen Along\",\n                                \"url\": f\"{config.MAESTRO_SITE}/listen-along/{self.username}\",\n                            }\n                        ]\n                        if self.username and self.want_stream\n                        else None\n                    ),\n                )\n                d = {k: v for k, v in d.items() if v is not None}\n\n                try:\n                    self.discord_rpc.set_activity(**d)\n                    self.discord_last_update = time()\n                except Exception as e:  # pylint: disable=bare-except\n                    print_to_logfile(\"Discord update error:\", e)\n                    song_name, artist_name, album_name = \"\", \"\", \"\"\n                    self.discord_connected = 2\n                    try:\n                        self.discord_rpc = self.connect_to_discord()\n                        self.discord_connected = 1\n                        self.discord_updating = False\n                        self.update_discord_metadata()\n                    except Exception as err:\n                        print_to_logfile(\"Discord connection error:\", err)\n                        self.discord_connected = 0\n                finally:\n                    self.discord_updating = False\n\n    def update_mac_now_playing_metadata(self):\n        from maestro.icon import img as default_artwork\n\n        if self.can_mac_now_playing:\n            self.mac_now_playing.paused = False\n            self.mac_now_playing.pos = 0\n            self.mac_now_playing.length = self.duration\n            self.mac_now_playing.cover = (\n                self.artwork if self.artwork else default_artwork\n            )\n\n            multiprocessing_put_word(\n                self.mac_now_playing.title_queue,\n                self.song_title,\n            )\n            multiprocessing_put_word(\n                self.mac_now_playing.artist_queue,\n                self.song_artist,\n            )\n\n            self.update_now_playing = True\n\n    def update_icecast_metadata(self):\n        import requests\n\n        return requests.post(\n            config.UPDATE_METADATA_URL,\n            data={\n                \"mount\": self.username,\n                \"song\": quote_plus(self.song_title),\n                \"artist\": quote_plus(self.song_artist),\n                \"album\": quote_plus(self.song_album),\n                \"albumartist\": quote_plus(self.album_artist),\n                \"paused\": int(self.paused),\n            },\n            auth=(self.username, self.password),\n            timeout=5,\n        )\n\n    def icecast_metadata_update_loop(self):\n        success = False\n        last_metadata_update_attempt = 0\n        while not success:\n            t = time()\n            if t - last_metadata_update_attempt > 5:\n                try:\n                    response = self.update_icecast_metadata()\n                    if response.ok:\n                        last_metadata_update_attempt = 0\n                        success = True\n                    else:\n                        raise Exception(\n                            f\"Icecast Server error {response.status_code}: {response.text}\"\n                        )\n                except Exception as e:  # retry in 5 seconds\n                    print_to_logfile(\"Update metadata failed:\", e)\n                    last_metadata_update_attempt = t\n            sleep(0.01)\n\n    def threaded_update_icecast_metadata(self):\n        threading.Thread(\n            target=self.icecast_metadata_update_loop, daemon=True\n        ).start()\n\n    def update_stream_metadata(self):  # artwork + icecast metadata\n        import requests\n\n        self.break_stream_loop = True\n        if (\n            self.discord_connected\n            or self.want_stream\n            and self.username is not None\n        ):\n            if not requests.post(\n                config.UPDATE_ARTWORK_URL,\n                params={\"mount\": self.username},\n                files={\"artwork\": self.artwork},\n                auth=(self.username, self.password),\n                timeout=5,\n            ).ok:\n                print_to_logfile(\"Failed to update artwork.\")\n\n        if self.want_stream:\n            self.threaded_update_icecast_metadata()\n\n    def update_metadata(self):\n        def f():\n            self.update_mac_now_playing_metadata()\n            self.update_stream_metadata()\n            self.update_discord_metadata()\n\n        threading.Thread(target=f, daemon=True).start()\n\n    def initialize_discord(self):\n        self.want_discord = True\n        try:\n            self.discord_rpc = self.connect_to_discord()\n            self.discord_connected = 1\n        except Exception as e:  # pylint: disable=broad-except,unused-variable\n            self.discord_connected = 0\n            print_to_logfile(\"Discord connection error:\", e)\n\n    def threaded_initialize_discord(self):\n        threading.Thread(target=self.initialize_discord, daemon=True).start()\n\n    def output(self, pos):\n        from maestro.jit_funcs import render\n\n        screen_height = self.screen_height\n        if self.want_lyrics:\n            screen_width = self.screen_width - self.lyrics_width\n        else:\n            screen_width = self.screen_width\n\n        self.can_show_visualization = (\n            self.want_vis\n            and self.can_visualize\n            and screen_height > config.VISUALIZER_HEIGHT + 5\n        )\n        self.scroller.resize(\n            screen_height\n            - 3  # -3 for status bar\n            - 1  # -1 for header\n            - (self.prompting != None)  # - add mode\n            # - visualizer\n            - (config.VISUALIZER_HEIGHT if self.can_show_visualization else 0)\n        )\n\n        if self.clip_mode:\n            pos -= self.clip[0]\n\n        self.stdscr.erase()\n\n        length_so_far = 0\n        if self.want_discord:\n            if self.discord_connected == 2:\n                length_so_far = addstr_fit_to_width(\n                    self.stdscr,\n                    \"Connecting to Discord ... \",\n                    screen_width,\n                    length_so_far,\n                    curses.color_pair(12),\n                )\n            elif self.discord_connected == 1:\n                length_so_far = addstr_fit_to_width(\n                    self.stdscr,\n                    \"Discord connected! \",\n                    screen_width,\n                    length_so_far,\n                    curses.color_pair(17),\n                )\n            else:\n                length_so_far = addstr_fit_to_width(\n                    self.stdscr,\n                    \"Failed to connect to Discord. \",\n                    screen_width,\n                    length_so_far,\n                    curses.color_pair(14),\n                )\n\n        visualize_message = \"\"\n        visualize_color = 12\n        if self.want_vis:\n            if self.audio_data is None and self.can_visualize:\n                self.audio_processing_thread = threading.Thread(\n                    target=self._audio_processing_loop,\n                    daemon=True,\n                )\n                self.audio_data = {}\n                self.audio_processing_thread.start()\n\n            if not self.can_visualize:\n                visualize_message = \"Librosa is required for visualization.\"\n                visualize_color = 14\n            elif not self.can_show_visualization:\n                visualize_message = \"Window too small for visualization.\"\n                visualize_color = 14\n            elif self.song not in self.audio_data:\n                visualize_message = \"Loading visualization...\"\n                visualize_color = 12\n            elif not self.compiled:\n                visualize_message = \"Compiling renderer...\"\n                visualize_color = 12\n\n        if self.want_stream:\n            prefix = \"  \" if self.want_discord else \"\"\n            if self.username:\n                long_stream_message = (\n                    prefix\n                    + f\"Streaming at {config.MAESTRO_SITE}/listen-along/{self.username}\"\n                )\n                short_stream_message = prefix + f\"Streaming as {self.username}!\"\n                if (\n                    length_so_far\n                    + len(long_stream_message)\n                    + 2\n                    + (len(visualize_message) if visualize_message else -2)\n                    < screen_width\n                ):\n                    length_so_far = addstr_fit_to_width(\n                        self.stdscr,\n                        long_stream_message,\n                        screen_width,\n                        length_so_far,\n                        curses.color_pair(16),\n                    )\n                else:\n                    length_so_far = addstr_fit_to_width(\n                        self.stdscr,\n                        short_stream_message,\n                        screen_width,\n                        length_so_far,\n                        curses.color_pair(16),\n                    )\n            else:\n                length_so_far = addstr_fit_to_width(\n                    self.stdscr,\n                    prefix + \"Please log in to stream.\",\n                    screen_width,\n                    length_so_far,\n                    curses.color_pair(14),\n                )\n\n        length_so_far = addstr_fit_to_width(\n            self.stdscr,\n            \" \" * (screen_width - length_so_far - len(visualize_message))\n            + visualize_message,\n            screen_width,\n            length_so_far,\n            curses.color_pair(visualize_color),\n        )\n        self.stdscr.move(1, 0)\n\n        song_display_color = 5 if self.looping_current_song else 3\n        progress_bar_display_color = (\n            17 if (self.clip_mode and self.clip != (0, self.duration)) else 15\n        )\n\n        # for aligning song names\n        longest_song_id_length = max(\n            len(str(song.song_id)) for song in self.playlist\n        )\n\n        for j in range(\n            self.scroller.top, self.scroller.top + self.scroller.win_size\n        ):\n            if j <= len(self.playlist) - 1:\n                length_so_far = 0\n\n                length_so_far = addstr_fit_to_width(\n                    self.stdscr,\n                    \" \"\n                    * (\n                        longest_song_id_length\n                        - len(str(self.playlist[j].song_id))\n                    )\n                    + f\"{self.playlist[j].song_id} \",\n                    screen_width,\n                    length_so_far,\n                    curses.color_pair(2),\n                )\n                if j == self.i:\n                    length_so_far = addstr_fit_to_width(\n                        self.stdscr,\n                        f\"{self.playlist[j].song_title} \",\n                        screen_width,\n                        length_so_far,\n                        curses.color_pair(song_display_color) | curses.A_BOLD,\n                    )\n                else:\n                    length_so_far = addstr_fit_to_width(\n                        self.stdscr,\n                        f\"{self.playlist[j].song_title} \",\n                        screen_width,\n                        length_so_far,\n                        (\n                            curses.color_pair(4)\n                            if (j == self.scroller.pos)\n                            else curses.A_NORMAL\n                        ),\n                    )\n                length_so_far = addstr_fit_to_width(\n                    self.stdscr,\n                    f\"{', '.join(self.playlist[j].tags)}\",\n                    screen_width,\n                    length_so_far,\n                    curses.color_pair(2),\n                )\n            self.stdscr.move((j - self.scroller.top) + 2, 0)\n\n        if self.prompting is not None:\n            # pylint: disable=unsubscriptable-object\n            if self.prompting[2] == config.PROMPT_MODES[\"tag\"]:\n                adding_song_length = addstr_fit_to_width(\n                    self.stdscr,\n                    \"Add tag(s) to songs: \" + self.prompting[0],\n                    screen_width,\n                    0,\n                )\n            else:\n                adding_song_length = addstr_fit_to_width(\n                    self.stdscr,\n                    config.PROMPT_MODES_LIST[self.prompting[2]].capitalize()\n                    + \" song: \"\n                    + self.prompting[0],\n                    screen_width,\n                    0,\n                )\n            self.stdscr.move(self.stdscr.getyx()[0] + 1, 0)\n\n        length_so_far = 0\n        length_so_far = addstr_fit_to_width(\n            self.stdscr,\n            (\"| \" if self.paused else \"> \") + f\"({self.song_id}) \",\n            screen_width,\n            length_so_far,\n            curses.color_pair(song_display_color + 10),\n        )\n        length_so_far = addstr_fit_to_width(\n            self.stdscr,\n            f\"{self.song_title} \",\n            screen_width,\n            length_so_far,\n            curses.color_pair(song_display_color + 10) | curses.A_BOLD,\n        )\n        length_so_far = addstr_fit_to_width(\n            self.stdscr,\n            \"%d/%d  \" % (self.i + 1, len(self.playlist)),\n            screen_width,\n            length_so_far,\n            curses.color_pair(12),\n        )\n        length_so_far = addstr_fit_to_width(\n            self.stdscr,\n            f\"{'c' if self.clip_mode else ' '}\",\n            screen_width,\n            length_so_far,\n            curses.color_pair(17) | curses.A_BOLD,\n        )\n\n        loop_char = \" \"\n        if self.looping_current_song == config.LOOP_MODES[\"one\"]:\n            loop_char = \"l\"\n        elif self.looping_current_song == config.LOOP_MODES[\"inf\"]:\n            loop_char = \"L\"\n        length_so_far = addstr_fit_to_width(\n            self.stdscr,\n            loop_char,\n            screen_width,\n            length_so_far,\n            curses.color_pair(15) | curses.A_BOLD,\n        )\n\n        volume_line_length_so_far = addstr_fit_to_width(\n            self.stdscr,\n            f\"{'e' if self.ending else ' '}  \",\n            screen_width,\n            length_so_far,\n            curses.color_pair(14) | curses.A_BOLD,\n        )\n        addstr_fit_to_width(\n            self.stdscr,\n            \" \" * (screen_width - volume_line_length_so_far - 1),\n            screen_width,\n            volume_line_length_so_far,\n            curses.color_pair(16),\n        )\n        self.stdscr.insstr(  # hacky fix for curses bug\n            \" \",\n            curses.color_pair(16),\n        )\n        self.stdscr.move(\n            screen_height\n            - 2\n            - (config.VISUALIZER_HEIGHT if self.can_show_visualization else 0),\n            0,\n        )\n\n        addstr_fit_to_width(\n            self.stdscr,\n            \" \" * (screen_width - 1),\n            screen_width,\n            0,\n            curses.color_pair(16),\n        )\n        self.stdscr.insstr(  # hacky fix for curses bug\n            \" \",\n            curses.color_pair(16),\n        )\n        self.stdscr.move(\n            self.stdscr.getyx()[0],\n            0,\n        )\n\n        song_data_length_so_far = addstr_fit_to_width(\n            self.stdscr,\n            self.song_artist + \" - \",\n            screen_width,\n            0,\n            curses.color_pair(12),\n        )\n\n        if self.italic:\n            try:\n                song_data_length_so_far = addstr_fit_to_width(\n                    self.stdscr,\n                    self.song_album,\n                    screen_width,\n                    song_data_length_so_far,\n                    curses.color_pair(12) | curses.A_ITALIC,\n                )\n            except:  # pylint: disable=bare-except\n                self.italic = False\n                print_to_logfile(\"Failed to italicize text in curses.\")\n        if not self.italic:\n            song_data_length_so_far = addstr_fit_to_width(\n                self.stdscr,\n                self.song_album,\n                screen_width,\n                song_data_length_so_far,\n                curses.color_pair(12),\n            )\n\n        addstr_fit_to_width(\n            self.stdscr,\n            f\" ({self.album_artist})\",\n            screen_width,\n            song_data_length_so_far,\n            curses.color_pair(12),\n        )\n\n        self.stdscr.move(\n            screen_height\n            - (config.VISUALIZER_HEIGHT if self.can_show_visualization else 0)\n            - 1,\n            0,\n        )\n\n        length_so_far = 0\n        secs = int(pos)\n        length_so_far = addstr_fit_to_width(\n            self.stdscr,\n            f\"{format_seconds(secs)} / {format_seconds(self.duration)}  \",\n            screen_width,\n            length_so_far,\n            curses.color_pair(progress_bar_display_color),\n        )\n        if not length_so_far >= screen_width:\n            if (\n                screen_width - length_so_far\n                >= config.MIN_PROGRESS_BAR_WIDTH + 2\n            ):\n                progress_bar_width = screen_width - length_so_far - 2\n                bar = \"|\"\n                progress_block_width = (\n                    progress_bar_width * 8 * pos\n                ) // self.duration\n                for _ in range(progress_bar_width):\n                    if progress_block_width > 8:\n                        bar += config.HORIZONTAL_BLOCKS[8]\n                        progress_block_width -= 8\n                    elif progress_block_width > 0:\n                        bar += config.HORIZONTAL_BLOCKS[progress_block_width]\n                        progress_block_width = 0\n                    else:\n                        bar += \" \"\n\n                self.stdscr.addstr(\n                    bar, curses.color_pair(progress_bar_display_color)\n                )\n                self.stdscr.insstr(  # hacky fix for curses bug\n                    \"|\", curses.color_pair(progress_bar_display_color)\n                )\n            else:\n                self.stdscr.addstr(\n                    \" \" * (screen_width - length_so_far - 1),\n                    curses.color_pair(16),\n                )\n                self.stdscr.insstr(  # hacky fix for curses bug\n                    \" \", curses.color_pair(16)\n                )\n\n        # right align volume bar\n        if not volume_line_length_so_far >= screen_width:\n            self.stdscr.move(\n                screen_height\n                - 3\n                - (\n                    config.VISUALIZER_HEIGHT\n                    if self.can_show_visualization\n                    else 0\n                ),\n                volume_line_length_so_far,\n            )\n            if (\n                screen_width - volume_line_length_so_far\n                >= config.MIN_VOLUME_BAR_WIDTH + 10\n            ):\n                bar = f\"{str(int(self.volume)).rjust(3)}/100 |\"\n                volume_bar_width = min(\n                    screen_width - volume_line_length_so_far - (len(bar) + 1),\n                    config.MAX_VOLUME_BAR_WIDTH,\n                )\n                block_width = int(volume_bar_width * 8 * self.volume / 100)\n                for _ in range(volume_bar_width):\n                    if block_width > 8:\n                        bar += config.HORIZONTAL_BLOCKS[8]\n                        block_width -= 8\n                    elif block_width > 0:\n                        bar += config.HORIZONTAL_BLOCKS[block_width]\n                        block_width = 0\n                    else:\n                        bar += \" \"\n                bar += \"|\"\n                bar = bar.rjust(screen_width - volume_line_length_so_far)\n\n                self.stdscr.addstr(bar, curses.color_pair(16))\n            elif screen_width - volume_line_length_so_far >= 7:\n                self.stdscr.addstr(\n                    f\"{str(int(self.volume)).rjust(3)}/100\".rjust(\n                        screen_width - volume_line_length_so_far\n                    ),\n                    curses.color_pair(16),\n                )\n\n        if self.can_show_visualization:\n            if self.clip_mode:\n                pos += self.clip[0]\n\n            self.stdscr.move(\n                screen_height\n                - (\n                    config.VISUALIZER_HEIGHT\n                    if self.can_show_visualization\n                    else 0\n                ),\n                0,\n            )\n            if (\n                self.song not in self.audio_data\n                or self.audio_data[self.song][0] is None\n            ):\n                self.stdscr.addstr(\n                    (\n                        (\" \" * (screen_width - 1) + \"\\n\")\n                        * config.VISUALIZER_HEIGHT\n                    ).rstrip()\n                )\n            elif not self.compiled:\n                if self.compiled is None:\n                    self.compiled = False\n\n                    def thread_func():\n                        vdata = self.audio_data[self.song][0]\n                        render(\n                            screen_width,\n                            vdata,\n                            min(round(pos * config.FPS), vdata.shape[2] - 1),\n                            config.VISUALIZER_HEIGHT,\n                        )\n                        self.compiled = True\n\n                    threading.Thread(target=thread_func, daemon=True).start()\n                self.stdscr.addstr(\n                    (\n                        (\" \" * (screen_width - 1) + \"\\n\")\n                        * config.VISUALIZER_HEIGHT\n                    ).rstrip()\n                )\n            elif self.compiled:\n                vdata = self.audio_data[self.song][0]\n                rendered_lines = render(\n                    screen_width,\n                    vdata,\n                    min(\n                        round(pos * config.FPS),\n                        # fmt: off\n                        vdata.shape[2] - 1,\n                    ),\n                    config.VISUALIZER_HEIGHT,\n                )\n                for i in range(len(rendered_lines)):\n                    self.stdscr.addstr(rendered_lines[i][:-1])\n                    self.stdscr.insstr(rendered_lines[i][-1])\n                    if i < len(rendered_lines) - 1:\n                        self.stdscr.move(self.stdscr.getyx()[0] + 1, 0)\n\n        if self.can_show_lyrics:\n            from grapheme import graphemes\n\n            # self.stdscr.redrawwin()  # workaround for foreign characters\n\n            num_lines = min(\n                len(self.lyrics),\n                (\n                    screen_height // 2\n                    if self.can_show_translated_lyrics\n                    else screen_height - 1\n                ),\n            )\n\n            cur_lyric_i = None\n            is_timed = is_timed_lyrics(self.lyrics)\n            if is_timed:\n                for i, lyric in enumerate(self.lyrics):\n                    if lyric.time > pos:\n                        cur_lyric_i = i - 1\n                        break\n                if cur_lyric_i is None:\n                    cur_lyric_i = len(self.lyrics) - 1\n            self.lyrics_scroller.pos = (\n                self.lyric_pos or cur_lyric_i or self.lyrics_scroller.pos\n            )\n            self.lyrics_scroller.resize(num_lines)\n            if not is_timed:\n                self.lyrics_scroller.pos = min(\n                    max(\n                        self.lyrics_scroller.win_size // 2,\n                        self.lyrics_scroller.pos,\n                    ),\n                    self.lyrics_scroller.num_lines\n                    - self.lyrics_scroller.win_size // 2,\n                )\n\n            self.stdscr.move(0, screen_width)\n            lyric_focus_msg = (\n                f\"Focus: {'lyrics' if self.focus == 1 else 'queue'}\"\n            )\n            addstr_fit_to_width(\n                self.stdscr,\n                \" \" * (self.lyrics_width - len(lyric_focus_msg))\n                + lyric_focus_msg,\n                self.lyrics_width,\n                0,\n                curses.color_pair(19),\n            )\n\n            for i in range(\n                self.lyrics_scroller.top, self.lyrics_scroller.top + num_lines\n            ):\n                vertical_pos = (i - self.lyrics_scroller.top) * (\n                    2 if self.can_show_translated_lyrics else 1\n                ) + 1\n\n                style = curses.color_pair(9)\n                # pylint: disable=unsubscriptable-object\n                lyric_text = get_lyric(self.lyrics[i]).strip()\n                if cur_lyric_i is not None:\n                    if i == cur_lyric_i:\n                        style = curses.color_pair(9) | curses.A_BOLD\n\n                        self.stdscr.move(\n                            vertical_pos,\n                            screen_width + config.LYRIC_PADDING - 2,\n                        )\n                        self.stdscr.addstr(\"> \", style)\n                    elif i == self.lyric_pos:\n                        style = curses.color_pair(4)\n\n                        self.stdscr.move(\n                            vertical_pos,\n                            screen_width + config.LYRIC_PADDING - 2,\n                        )\n                        self.stdscr.addstr(\"> \", style)\n                    elif i < cur_lyric_i:\n                        style = curses.color_pair(9) | curses.A_DIM\n\n                try:\n                    width = 0\n                    for g in graphemes(lyric_text):\n                        width += 1\n                        # NOTE: why -1? No one knows.\n                        if width < self.lyrics_width - config.LYRIC_PADDING:\n                            self.stdscr.move(\n                                vertical_pos,\n                                screen_width + config.LYRIC_PADDING + width - 1,\n                            )\n                            self.stdscr.addstr(g, style)\n                        else:\n                            break\n                except curses.error:  # bottom right corner errors\n                    break\n\n                if (\n                    self.can_show_translated_lyrics\n                    and i < len(self.translated_lyrics)\n                    and self.stdscr.getyx()[0] < screen_height\n                ):\n                    style = curses.A_DIM\n                    if i == cur_lyric_i:\n                        style |= curses.A_BOLD\n                    elif i == self.lyric_pos and is_timed:\n                        style |= curses.color_pair(4)\n\n                    try:\n                        width = 0\n                        for g in graphemes(\n                            get_lyric(self.translated_lyrics[i]).strip()\n                        ):\n                            width += 1\n                            if (\n                                width\n                                < self.lyrics_width - config.LYRIC_PADDING - 1\n                            ):\n                                self.stdscr.move(\n                                    vertical_pos + 1,\n                                    screen_width\n                                    + config.LYRIC_PADDING\n                                    + 1\n                                    + width\n                                    - 1,\n                                )\n                                self.stdscr.addstr(g, style)\n                            else:\n                                break\n                    except curses.error:  # bottom right corner errors\n                        break\n        elif self.want_lyrics:\n            self.stdscr.move(0, screen_width + config.LYRIC_PADDING)\n            addstr_fit_to_width(\n                self.stdscr,\n                \"No lyrics found.\",\n                self.lyrics_width - config.LYRIC_PADDING,\n                0,\n                curses.color_pair(4),\n            )\n\n        if self.show_help:\n            l = 15\n            r = self.screen_width - l\n            t = 5\n            b = self.screen_height - t\n\n            if l < r and t < b:\n                # draw border\n                self.stdscr.addch(t, l, curses.ACS_ULCORNER)\n                self.stdscr.addch(t, r, curses.ACS_URCORNER)\n                self.stdscr.addch(b, l, curses.ACS_LLCORNER)\n                self.stdscr.addch(b, r, curses.ACS_LRCORNER)\n                for x in range(l + 1, r):\n                    self.stdscr.addch(t, x, curses.ACS_HLINE)\n                    self.stdscr.addch(b, x, curses.ACS_HLINE)\n                for y in range(t + 1, b):\n                    self.stdscr.addch(y, l, curses.ACS_VLINE)\n                    self.stdscr.addch(y, r, curses.ACS_VLINE)\n\n                # draw text\n                self.stdscr.move(t + 1, l + 1)\n                i = max(\n                    0,\n                    min(self.help_pos, len(config.PLAY_CONTROLS) - (b - t - 1)),\n                )\n                while self.stdscr.getyx()[0] < b:\n                    if i < len(config.PLAY_CONTROLS):\n                        key, desc = config.PLAY_CONTROLS[i]\n                        length_so_far = addstr_fit_to_width(\n                            self.stdscr,\n                            key\n                            + \" \" * (config.INDENT_CONTROL_DESC - len(key))\n                            + \" \",\n                            r - l - 1,\n                            0,\n                            curses.color_pair(18) | curses.A_BOLD,\n                        )\n                        length_so_far = addstr_fit_to_width(\n                            self.stdscr,\n                            desc\n                            + \" \" * (r - l - 1 - length_so_far - len(desc)),\n                            r - l - 1,\n                            length_so_far,\n                            curses.color_pair(18),\n                        )\n                        i += 1\n                        self.stdscr.move(self.stdscr.getyx()[0] + 1, l + 1)\n                    else:\n                        self.stdscr.addstr(\" \" * (r - l - 1))\n\n        if self.prompting is not None:\n            # pylint: disable=unsubscriptable-object\n            self.stdscr.move(\n                screen_height\n                - (\n                    config.VISUALIZER_HEIGHT\n                    if self.can_show_visualization\n                    else 0\n                )\n                - 4,  # 4 lines for status bar + adding entry\n                adding_song_length\n                + (self.prompting[1] - len(self.prompting[0])),\n            )\n\n        self.stdscr.refresh()\n\n\ndef init_curses(stdscr):\n    curses.start_color()\n    curses.use_default_colors()\n\n    # region colors\n\n    curses.init_pair(1, curses.COLOR_WHITE, -1)\n    curses.init_pair(2, curses.COLOR_BLACK + 8, -1)  # bright black\n    curses.init_pair(3, curses.COLOR_BLUE, -1)\n    curses.init_pair(4, curses.COLOR_RED, -1)\n    curses.init_pair(5, curses.COLOR_YELLOW, -1)\n    curses.init_pair(6, curses.COLOR_GREEN, -1)\n    curses.init_pair(7, curses.COLOR_MAGENTA, -1)\n    curses.init_pair(9, curses.COLOR_CYAN, -1)\n\n    curses.init_pair(11, curses.COLOR_WHITE, curses.COLOR_BLACK)\n    curses.init_pair(12, curses.COLOR_BLACK + 8, curses.COLOR_BLACK)\n    curses.init_pair(13, curses.COLOR_BLUE, curses.COLOR_BLACK)\n    curses.init_pair(14, curses.COLOR_RED, curses.COLOR_BLACK)\n    curses.init_pair(15, curses.COLOR_YELLOW, curses.COLOR_BLACK)\n    curses.init_pair(16, curses.COLOR_GREEN, curses.COLOR_BLACK)\n    curses.init_pair(17, curses.COLOR_MAGENTA, curses.COLOR_BLACK)\n    curses.init_pair(18, -1, curses.COLOR_BLACK)\n    curses.init_pair(19, curses.COLOR_CYAN, curses.COLOR_BLACK)\n    # endregion\n\n    curses.curs_set(False)\n    stdscr.nodelay(True)\n    try:\n        curses.set_escdelay(25)  # 25 ms\n    except:  # pylint: disable=bare-except\n        pass\n\n\nclass SongParamType(click.ParamType):\n    name = \"song\"\n\n    def convert(self, value, param, ctx) -> Song:\n        if value.isdecimal():\n            value = int(value)\n\n        if type(value) == int:\n            song = Song(value)\n            if song in SONGS:\n                return song\n            self.fail(f\"No song found with ID {value}.\", param, ctx)\n\n        if not value.isdecimal():\n            results = search_song(value)\n            if not any(results):\n                self.fail(f\"No song found matching '{value}'.\", param, ctx)\n\n            for result in results:\n                if len(result) == 1:\n                    return result[0]\n                if len(result) > 1:\n                    break\n\n            if param is not None:  # called by click\n                for song in sum(results, []):\n                    print_entry(song, value)\n            self.fail(\"Multiple songs found\", param, ctx)\n\n        self.fail(\"Invalid song argument\", param, ctx)\n\n\nCLICK_SONG = SongParamType()\n\n\ndef yt_embed_artwork(yt_dlp_info, crop):\n    import music_tag\n    import requests\n\n    yt_dlp_info[\"thumbnails\"].sort(key=lambda d: d[\"preference\"])\n    best_thumbnail = yt_dlp_info[\"thumbnails\"][-1]  # default thumbnail\n\n    if \"width\" not in best_thumbnail:\n        # different so that any square thumbnail is chosen\n        best_thumbnail[\"width\"] = 0\n        best_thumbnail[\"height\"] = -1\n\n    for thumbnail in yt_dlp_info[\"thumbnails\"][:-1]:\n        # print(thumbnail)\n        if \"height\" in thumbnail and (\n            (\n                thumbnail[\"height\"] == thumbnail[\"width\"]\n                and (\n                    (best_thumbnail[\"width\"] != best_thumbnail[\"height\"])\n                    or (\n                        thumbnail[\"height\"] >= best_thumbnail[\"height\"]\n                        and thumbnail[\"width\"] >= best_thumbnail[\"width\"]\n                    )\n                )\n            )\n            or (\n                thumbnail[\"height\"] >= best_thumbnail[\"height\"]\n                and (thumbnail[\"width\"] >= best_thumbnail[\"width\"])\n                and (best_thumbnail[\"width\"] != best_thumbnail[\"height\"])\n            )\n        ):\n            best_thumbnail = thumbnail\n\n    response = requests.get(best_thumbnail[\"url\"], timeout=5)\n    image_data = response.content\n    if best_thumbnail[\"width\"] != best_thumbnail[\"height\"] and crop:\n        from io import BytesIO\n        from PIL import Image\n\n        image = Image.open(BytesIO(image_data))\n        width, height = image.size\n        if width > height:\n            image = image.crop(\n                (\n                    (width - height) // 2,\n                    0,\n                    (width + height) // 2,\n                    height,\n                )\n            )\n        elif height > width:\n            image = image.crop(\n                (\n                    0,\n                    (height - width) // 2,\n                    width,\n                    (height + width) // 2,\n                )\n            )\n\n        image_data = BytesIO()\n        image.save(image_data, format=\"JPEG\")\n        image_data = image_data.getvalue()\n\n    m = music_tag.load_file(yt_dlp_info[\"requested_downloads\"][0][\"filepath\"])\n    m[\"artwork\"] = image_data\n    m.save()\n\n\ndef clip_editor(stdscr, song: Song, name, start=None, end=None):\n    from just_playback import Playback\n\n    playback = Playback()\n    playback.load_file(song.song_path)\n\n    init_curses(stdscr)\n\n    if name in song.clips:\n        clip_start, clip_end = song.clips[name]\n    else:\n        clip_start, clip_end = 0, playback.duration\n\n    if start is not None:\n        clip_start = start\n    if end is not None:\n        clip_end = end\n\n    editing_start = True\n    change_output = True\n    playback.play()\n    playback.pause()\n    playback.seek(clip_start)\n    last_timestamp = playback.curr_pos\n    while True:\n        if playback.curr_pos >= clip_end:\n            playback.pause()\n\n        change_output = change_output or (\n            (playback.curr_pos - last_timestamp)\n            >= (playback.duration / (8 * (stdscr.getmaxyx()[1] - 2)))\n        )\n\n        if change_output:\n            clip_editor_output(\n                stdscr,\n                song,\n                playback.curr_pos,\n                playback.paused,\n                playback.duration,\n                clip_start,\n                clip_end,\n                editing_start,\n            )\n\n        c = stdscr.getch()\n        next_c = stdscr.getch()\n        while next_c != -1:\n            c, next_c = next_c, stdscr.getch()\n\n        if c == -1:\n            continue\n\n        change_output = False\n        if editing_start:\n            if c == curses.KEY_LEFT:\n                change_output = True\n                playback.pause()\n                clip_start = max(0, clip_start - 0.1)\n                playback.seek(clip_start)\n            elif c == curses.KEY_SLEFT:\n                change_output = True\n                playback.pause()\n                clip_start = max(0, clip_start - 1)\n                playback.seek(clip_start)\n            elif c == curses.KEY_RIGHT:\n                change_output = True\n                playback.pause()\n                clip_start = min(clip_start + 0.1, clip_end)\n                playback.seek(clip_start)\n            elif c == curses.KEY_SRIGHT:\n                change_output = True\n                playback.pause()\n                clip_start = min(clip_start + 1, clip_end)\n                playback.seek(clip_start)\n            elif c == curses.KEY_ENTER:\n                break\n            else:\n                c = chr(c)\n                if c == \" \":  # space\n                    change_output = True\n                    if playback.playing:\n                        playback.pause()\n                    else:\n                        playback.resume()\n                elif c in \"tT\":\n                    change_output = True\n                    playback.pause()\n                    playback.seek(clip_end - 1)\n                    editing_start = False\n                elif c in \"qQ\":\n                    return (None, None)\n                elif c in \"\\r\\n\":\n                    break\n        else:\n            if c == curses.KEY_LEFT:\n                change_output = True\n                playback.pause()\n                clip_end = max(clip_end - 0.1, clip_start)\n                playback.seek(clip_end - 1)\n            elif c == curses.KEY_SLEFT:\n                change_output = True\n                playback.pause()\n                clip_end = max(clip_end - 1, clip_start)\n                playback.seek(clip_end - 1)\n            elif c == curses.KEY_RIGHT:\n                change_output = True\n                playback.pause()\n                clip_end = min(clip_end + 0.1, playback.duration)\n                playback.seek(clip_end - 1)\n            elif c == curses.KEY_SRIGHT:\n                change_output = True\n                playback.pause()\n                clip_end = min(clip_end + 1, playback.duration)\n                playback.seek(clip_end - 1)\n            elif c == curses.KEY_ENTER:\n                break\n            else:\n                c = chr(c)\n                if c == \" \":\n                    change_output = True\n                    if playback.playing:\n                        playback.pause()\n                    else:\n                        playback.resume()\n                elif c in \"tT\":\n                    change_output = True\n                    playback.pause()\n                    playback.seek(clip_start)\n                    editing_start = True\n                elif c in \"qQ\":\n                    return (None, None)\n                elif c in \"\\r\\n\":\n                    break\n\n    return clip_start, clip_end\n\n\ndef clip_editor_output(\n    stdscr,\n    song: Song,\n    pos,\n    paused,\n    duration,\n    clip_start,\n    clip_end,\n    editing_start,\n):\n    stdscr.erase()\n\n    if stdscr.getmaxyx()[0] < 3:\n        stdscr.addstr(\"Window too small.\", curses.color_pair(4))\n        stdscr.refresh()\n        return\n\n    screen_width = stdscr.getmaxyx()[1]\n\n    stdscr.insstr(\n        f\"{format_seconds(clip_start, show_decimal=True)}\"\n        + (\" <\" if editing_start else \"\"),\n        curses.color_pair(7),\n    )\n\n    end_str = (\n        \"> \" if not editing_start else \"\"\n    ) + f\"{format_seconds(clip_end, show_decimal=True)}\"\n    stdscr.move(0, screen_width - len(end_str))\n    stdscr.insstr(end_str, curses.color_pair(7))\n\n    stdscr.move(1, 0)\n\n    clip_bar_width = screen_width - 2\n    if clip_bar_width > 0:\n        bar = \"|\"\n        before_clip_block_width = round(\n            (clip_bar_width * 8 * clip_start) / duration\n        )\n        clip_block_width = round(\n            clip_bar_width * 8 * (clip_end - clip_start) / duration\n        )\n        num_chars_added = 0\n        stdscr.addstr(\"|\", curses.color_pair(7))\n        while before_clip_block_width:\n            if before_clip_block_width >= 8:\n                stdscr.addstr(\" \", curses.color_pair(7))\n                before_clip_block_width -= 8\n            else:\n                stdscr.addstr(\n                    config.HORIZONTAL_BLOCKS[before_clip_block_width],\n                    curses.color_pair(7) | curses.A_REVERSE,\n                )\n                clip_block_width -= 8 - before_clip_block_width\n                before_clip_block_width = 0\n            num_chars_added += 1\n\n        while num_chars_added < clip_bar_width:\n            if clip_block_width >= 8:\n                stdscr.addstr(config.HORIZONTAL_BLOCKS[8], curses.color_pair(7))\n                clip_block_width -= 8\n            elif clip_block_width > 0:\n                stdscr.addstr(\n                    config.HORIZONTAL_BLOCKS[clip_block_width],\n                    curses.color_pair(7),\n                )\n                clip_block_width = 0\n            else:\n                stdscr.addstr(\" \", curses.color_pair(7))\n            num_chars_added += 1\n        stdscr.insstr(\"|\", curses.color_pair(7))\n        stdscr.move(stdscr.getyx()[0] + 1, 0)\n\n    progress_bar_width = screen_width - 2\n    if progress_bar_width > 0:\n        bar = \"|\"\n        progress_block_width = (progress_bar_width * 8 * pos) // duration\n        for _ in range(progress_bar_width):\n            if progress_block_width > 8:\n                bar += config.HORIZONTAL_BLOCKS[8]\n                progress_block_width -= 8\n            elif progress_block_width > 0:\n                bar += config.HORIZONTAL_BLOCKS[progress_block_width]\n                progress_block_width = 0\n            else:\n                bar += \" \"\n\n        stdscr.addstr(bar, curses.color_pair(5))\n        stdscr.insstr(\"|\", curses.color_pair(5))  # hacky fix for curses bug\n        stdscr.move(stdscr.getyx()[0] + 1, 0)\n\n    stdscr.move(stdscr.getyx()[0] + 1, 0)  # 1-line spacing\n\n    # region pause indicator, song ID+title, tags\n    length_so_far = 0\n    length_so_far = addstr_fit_to_width(\n        stdscr,\n        (\"| \" if paused else \"> \") + f\"({song.song_id}) \",\n        screen_width,\n        length_so_far,\n        curses.color_pair(3),\n    )\n    length_so_far = addstr_fit_to_width(\n        stdscr,\n        f\"{song.song_title} \",\n        screen_width,\n        length_so_far,\n        curses.color_pair(3) | curses.A_BOLD,\n    )\n    length_so_far = addstr_fit_to_width(\n        stdscr,\n        f\"{', '.join(song.tags)} \",\n        screen_width,\n        length_so_far,\n        curses.color_pair(2),\n    )\n    stdscr.move(stdscr.getyx()[0] + 1, 0)\n    # endregion\n\n    # region credits\n    length_so_far = 0\n    length_so_far = addstr_fit_to_width(\n        stdscr,\n        f\"{song.artist} - \",\n        screen_width,\n        length_so_far,\n        curses.color_pair(2),\n    )\n    try:\n        length_so_far = addstr_fit_to_width(\n            stdscr,\n            song.album,\n            screen_width,\n            length_so_far,\n            curses.color_pair(2) | curses.A_ITALIC,\n        )\n    except:  # pylint: disable=bare-except\n        print_to_logfile(\"Failed to italicize text in curses.\")\n        length_so_far = addstr_fit_to_width(\n            stdscr,\n            song.album,\n            screen_width,\n            length_so_far,\n            curses.color_pair(2),\n        )\n    addstr_fit_to_width(\n        stdscr,\n        f\" ({song.album_artist})\",\n        screen_width,\n        length_so_far,\n        curses.color_pair(2),\n    )\n    stdscr.move(stdscr.getyx()[0] + 1, 0)\n    # endregion\n\n    stdscr.move(stdscr.getyx()[0] + 1, 0)  # 1-line spacing\n\n    # region controls\n    controls = [\n        (\"t\", \"toggle between editing the start and end of the clip\"),\n        (\n            \"LEFT/RIGHT\",\n            \"move whichever clip end you are editing by 0.1 seconds\",\n        ),\n        (\n            \"SHIFT+LEFT/RIGHT\",\n            \"move whichever clip end you are editing by 1 second\",\n        ),\n        (\"SPACE\", \"play/pause\"),\n        (\"ENTER\", \"exit the editor and save the clip\"),\n        (\"q\", \"exit the editor without saving the clip\"),\n    ]\n    for control in controls:\n        length_so_far = 0\n        length_so_far = addstr_fit_to_width(\n            stdscr,\n            f\"{control[0]}: \",\n            screen_width,\n            length_so_far,\n            curses.A_BOLD,\n        )\n        length_so_far = addstr_fit_to_width(\n            stdscr,\n            f\"{control[1]}\",\n            screen_width,\n            length_so_far,\n        )\n        stdscr.move(stdscr.getyx()[0] + 1, 0)\n    # endregion\n\n    stdscr.refresh()\n\n\ndef get_username():\n    import keyring\n\n    return keyring.get_password(\"maestro-music\", \"username\")\n\n\ndef get_password():\n    import keyring\n\n    return keyring.get_password(\"maestro-music\", \"password\")\n\n\ndef signup(username=None, password=None, login_=True):\n    if username is None:\n        username = input(\"Username: \")\n\n    if not username:\n        click.secho(\"Username cannot be empty.\", fg=\"red\")\n        return\n    if not is_safe_username(username):\n        click.secho(\n            \"Username must be URL-safe (no spaces or special characters).\",\n            fg=\"red\",\n        )\n        return\n\n    import requests\n\n    response = requests.get(\n        config.USER_EXISTS_URL, params={\"user\": username}, timeout=5\n    )\n    if response.status_code == 200:\n        click.secho(f\"Username {username} already exists.\", fg=\"red\")\n        return\n\n    if password is None:\n        password = getpass(\"Password (8-1024 characters):\")\n        if len(password) < 8 or len(password) > 1024:\n            click.secho(\"Passwords should be 8-1024 characters long.\", fg=\"red\")\n            return\n    confirm_password = getpass(\"Confirm password:\")\n    if password != confirm_password:\n        click.secho(\"Passwords do not match.\", fg=\"red\")\n        return\n\n    response = requests.post(\n        config.SIGNUP_URL, auth=(username, password), timeout=5\n    )\n    if response.status_code == 201:\n        click.secho(f\"Successfully signed up user '{username}'!\", fg=\"green\")\n        if login_:\n            login(username, password)\n    else:\n        click.secho(\n            f\"Signup failed with status code {response.status_code}: {response.text}\",\n            fg=\"red\",\n        )\n\n\ndef login(username=None, password=None):\n    if username is None:\n        username = input(\"Username: \")\n\n    if not username:\n        click.secho(\"Username cannot be empty.\", fg=\"red\")\n        return\n    if not is_safe_username(username):\n        click.secho(\n            \"Username must be URL-safe (no spaces or special characters).\",\n            fg=\"red\",\n        )\n        return\n\n    import keyring\n\n    current_username = keyring.get_password(\"maestro-music\", \"username\")\n    if current_username == username:\n        click.secho(f\"User '{username}' is already logged in.\", fg=\"yellow\")\n        return\n    if current_username is not None:\n        click.secho(\n            f\"Logging in as user '{username}' will log out current user '{current_username}'.\",\n            fg=\"yellow\",\n        )\n\n    import requests\n\n    if password is None:\n        password = getpass(\"Password:\")\n\n    response = requests.post(\n        config.LOGIN_URL, auth=(username, password), timeout=5\n    )\n    if response.status_code == 200:\n        click.secho(f\"Successfully logged in user '{username}'!\", fg=\"green\")\n        keyring.set_password(\"maestro-music\", \"username\", username)\n        keyring.set_password(\"maestro-music\", \"password\", password)\n    else:\n        click.secho(\n            f\"Login failed with status code {response.status_code}: {response.text}\",\n            fg=\"red\",\n        )\n\n\ndef format_seconds(secs, show_decimal=False, digital=True, include_hours=None):\n    \"\"\"Format seconds into a string.\n\n    show_decimal: whether to show the decimal part of the seconds\n    digital: whether to use digital format ([HH]:MM:SS) or words (e.g. 1h 2m 3s)\n    include_hours: whether to include hours in the output (e.g. 71:05 vs 1:11:05)\n    \"\"\"\n    h = int(secs // 3600)\n    if include_hours is None:\n        include_hours = h > 0\n    m = int(secs // 60)\n    if include_hours:\n        m %= 60\n    s = int(secs % 60)\n    if digital:\n        return (\n            (f\"{h}:\" if include_hours else \"\")\n            + f\"{m}:{s:02}\"\n            + (f\".{secs%1:0.2f}\"[2:] if show_decimal else \"\")\n        )\n    return (\n        (f\"{h}h \" if include_hours else \"\")\n        + f\"{m}m {s}\"\n        + (f\".{secs%1:0.2f}\"[2:] if show_decimal else \"\")\n        + \"s\"\n    )\n\n\ndef search_song(phrase):\n    \"\"\"\n    CASE INSENSITIVE. Returns a tuple of three lists:\n    0: songs that match the phrase exactly\n    1: songs that start with the phrase\n    1: songs that contain the phrase but do not start with it\n    \"\"\"\n    phrase = phrase.lower()\n\n    results = [], [], []  # is, starts, contains but does not start\n    for song in SONGS:\n        song_title = song.song_title.lower()\n        if song_title == phrase:\n            results[0].append(song)\n        elif song_title.startswith(phrase):\n            results[1].append(song)\n        elif phrase in song_title:\n            results[2].append(song)\n\n    return results\n\n\ndef print_entry(\n    song: Song, highlight: str | None = None, year: int | str | None = None\n):\n    \"\"\"\n    Pretty prints ([] means optional)\n        <song ID> <song name> <total duration> <seconds listened> <times listened> <clip> <tags>\n            [<artist> - <album> (<album artist>)]\n\n    highlight: a string to highlight (the first occurrence of) in the song name\n    \"\"\"\n    click.secho(f\"{song.song_id} \", fg=\"bright_black\", nl=False)\n    if highlight is None:\n        click.secho(song.song_title + \" \", fg=\"blue\", nl=False, bold=True)\n    else:\n        highlight_loc = song.song_title.lower().find(highlight.lower())\n        click.secho(\n            song.song_title[:highlight_loc],\n            fg=\"blue\",\n            nl=False,\n            bold=True,\n        )\n        click.secho(\n            song.song_title[highlight_loc : highlight_loc + len(highlight)],\n            fg=\"yellow\",\n            nl=False,\n            bold=True,\n        )\n        click.secho(\n            song.song_title[highlight_loc + len(highlight) :] + \" \",\n            fg=\"blue\",\n            nl=False,\n            bold=True,\n        )\n\n    click.secho(\n        format_seconds(\n            song.duration,\n            show_decimal=True,\n            digital=False,\n        )\n        + \" \",\n        nl=False,\n    )\n    if year is not None:\n        click.secho(\n            format_seconds(\n                song.listen_times.get(year, 0),\n                show_decimal=True,\n                digital=False,\n            )\n            + \" \",\n            fg=\"yellow\",\n            nl=False,\n        )\n        click.secho(\n            f\"{song.listen_times.get(year, 0) / song.duration:0.2f} \",\n            fg=\"green\",\n            nl=False,\n        )\n\n    if song.set_clip in song.clips:\n        start, end = map(\n            lambda f: format_seconds(f, show_decimal=True),\n            song.clips[song.set_clip],\n        )\n        click.secho(\n            f\"[{start}, {end}] \",\n            fg=\"magenta\",\n            nl=False,\n        )\n\n    click.secho(\", \".join(song.tags), fg=\"bright_black\")\n\n    click.secho(\n        f\"{(len(str(song.song_id))+1)*' '}{song.artist if song.artist else 'No Artist'} - \",\n        fg=\"bright_black\",\n        nl=False,\n    )\n    click.secho(\n        (song.album if song.album else \"No Album\"),\n        italic=True,\n        fg=\"bright_black\",\n        nl=False,\n    )\n    click.secho(\n        f\" ({song.album_artist if song.album_artist else 'No Album Artist'})\",\n        fg=\"bright_black\",\n    )\n\n\ndef multiprocessing_put_word(q, word):\n    for c in word:\n        q.put(c)\n    q.put(\"\\n\")\n\n\ndef versiontuple(v):\n    return tuple(map(int, v.split(\".\")))\n\n\ndef pluralize(count, word, include_count=True):\n    return f\"{count} \" * include_count + word + (\"s\" if count != 1 else \"\")\n\n\ndef is_timed_lyrics(lyrics):\n    from pylrc.classes import Lyrics\n\n    return isinstance(lyrics, Lyrics)\n\n\ndef get_lyric(lyric_obj):\n    if isinstance(lyric_obj, str):\n        return lyric_obj\n    return lyric_obj.text  # pylrc.classes.LyricLine\n\n\ndef set_lyric(lyrics, i, val):\n    if isinstance(lyrics[i], str):\n        lyrics[i] = val\n    else:\n        lyrics[i].text = val\n\n\ndef display_lyrics(lyrics, song, prefix: str = \"\"):\n    if prefix:\n        prefix += \" \"\n\n    if lyrics is None:\n        click.secho(\n            f'No {prefix}lyrics found for \"{song.song_title}\" (ID: {song.song_id}).',\n            fg=\"red\",\n        )\n        return\n\n    if prefix:\n        prefix = prefix.capitalize() + \"l\"\n    else:\n        prefix = \"L\"\n\n    click.echo(f\"{prefix.capitalize()}yrics for \", nl=False)\n    click.secho(song.song_title, fg=\"blue\", bold=True, nl=False)\n    click.echo(f\" (ID {song.song_id}):\")\n\n    if is_timed_lyrics(lyrics):\n        for lyric in lyrics:\n            click.echo(\n                f\"\\t[{format_seconds(lyric.time, show_decimal=True)}] {lyric.text}\"\n            )\n    else:\n        click.echo(\"\\n\".join([f\"\\t{lyric}\" for lyric in lyrics]))\n\n\ndef filter_songs(\n    tags: set[str],\n    exclude_tags,\n    artists,\n    albums,\n    album_artists,\n    match_all,\n    combine_artists,\n):\n    songs = []\n    for song in SONGS:\n        search_criteria = (\n            (\n                (\n                    any(\n                        artist.lower()\n                        in song.artist.lower()\n                        + (\n                            f\", {song.album_artist.lower()}\"\n                            if combine_artists\n                            else \"\"\n                        )\n                        for artist in artists\n                    )\n                ),\n                artists,\n            ),\n            (\n                (any(album.lower() in song.album.lower() for album in albums)),\n                albums,\n            ),\n            (\n                (\n                    any(\n                        album_artist.lower()\n                        in song.album_artist.lower()\n                        + (\n                            f\", {song.artist.lower()}\"\n                            if combine_artists\n                            else \"\"\n                        )\n                        for album_artist in album_artists\n                    )\n                ),\n                album_artists,\n            ),\n        )\n        search_criteria = tuple(\n            c[0] for c in filter(lambda t: t[1], search_criteria)\n        )\n\n        if match_all:\n            if not search_criteria:\n                search_criteria = (True,)\n\n            search_criteria = all(search_criteria) and (\n                not tags or (tags <= song.tags)  # subset\n            )\n        elif any(search_criteria):\n            search_criteria = True\n        elif tags:\n            search_criteria = tags & song.tags\n        else:\n            search_criteria = not search_criteria\n\n        if search_criteria and not exclude_tags & song.tags:\n            songs.append(song)\n\n    return songs\n"
  },
  {
    "path": "maestro/icon.py",
    "content": "img = b'\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00\\x04\\x00\\x00\\x00\\x04\\x00\\x08\\x06\\x00\\x00\\x00\\x7f\\x1d+\\x83\\x00\\x00\\x00\\x01sRGB\\x00\\xae\\xce\\x1c\\xe9\\x00\\x00\\x00DeXIfMM\\x00*\\x00\\x00\\x00\\x08\\x00\\x01\\x87i\\x00\\x04\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x1a\\x00\\x00\\x00\\x00\\x00\\x03\\xa0\\x01\\x00\\x03\\x00\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\xa0\\x02\\x00\\x04\\x00\\x00\\x00\\x01\\x00\\x00\\x04\\x00\\xa0\\x03\\x00\\x04\\x00\\x00\\x00\\x01\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\xd3\\xdd\\xea\\x1d\\x00\\x00\\x00\\x1ciDOT\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00(\\x00\\x00\\x02\\x00\\x00\\x00\\x02\\x00\\x00\\x00m.{a\\xb5\\x85\\x00\\x00@\\x00IDATx\\x01\\xec\\xdd\\t\\x94]U\\x99\\xb7q\\x036\\xd8*\\x1f*4\\xcb\\x01m\\xdan\\xc4V\\xcc\\x00$L\"S\\x18\\xc2\\x1cl\\x8d@\\x83\\x11\\x88\\x04ADTh%B\\xa2\\x08\\x01T\\x94\\xb4H0i\\x08H0D\\x8cH\\x18\\x12\\xc2\\x10P\\xa2L\\x8d\\x88\\xb4\\xda6\\xa2\\x80\\xa8 4C\\x90\\x0cd\\x7fgWSB\\x92\\xaaJ\\x9d[w8g\\xef_\\xadU+P\\xb9u\\xef9\\xef~\\xf6\\xde\\xef\\xff\\xc9\\xb9\\xe7\\xbe\\xe2\\x15\\xbeT\\xa0\\xa8\\xc0\\xad\\xb7\\xde\\xfa\\xfa\\x85\\x0b\\x17\\x0e+\\xbe\\x0f\\xbc\\xe5\\x96[\\x8e-\\xfe\\xff\\xd4\\xe2\\xcf)\\xc5\\xf7\\xcc\\xe2\\xbf\\xe7\\x17\\x7f\\xdeU\\xfc\\xf9\\xdb\\xe2\\xcfg\\x8a\\xefe\\xc5\\x7f\\x07\\xdfj\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xce0\\x10{\\xf2\\xd8\\x9b\\x17\\xf5\\x8f=z\\xec\\xd5c\\xcf>\\xb3\\xf8\\x9eR\\xfcw\\xec\\xe5\\x8f\\x8d\\xbd}\\xec\\xf1\\x8b\\xff\\x7f\\xbd\\xd0\\xa3\\x02*\\x90Y\\x05\\xae\\xbb\\xee\\xba7\\xdct\\xd3M;\\xc5\\xc5\\xa0\\xf8>\\xa7\\xf8\\x9eS,\\x06\\xf7\\x14\\xdfO\\x15\\xdf\\x02\\xbd\\x1a`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` Q\\x06\\x8a\\xde\\xff\\x7fc\\xef\\x1f3\\xc0\\x8bY\\xe0\\xd8\\x98\\rbF\\xc8,\\x169]\\x15H\\xab\\x02\\x97_~\\xf9\\xda\\x85\\xe9{O\\xf1}H1\\xb9\\xcf,\\xbe\\xaf-&\\xfb\\xc3B>\\xc9\\x81\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c\\xf4\\xc0\\xc0\\xc313\\xc4\\xec\\x103D\\xcc\\x121S\\xa4\\x95\\x92\\x9c\\x8d\\n$R\\x81+\\xaf\\xbcr\\xbdb\\x12\\x8f,\\xbeO-\\xbe\\xe7\\x17\\xdfO\\x17\\xdf\\xec\\xad\\x1a`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x8d2\\x103E\\xcc\\x16\\xa7\\x16\\xdf#c\\xe6H$>9\\r\\x15\\xa8W\\x05\\xe2\\xe4+\\xec\\xdc\\x01\\xc5w|\\x8f\\xfe\\xdd\\xc5\\xf7r\\x81\\x9f\\xf0\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06Z\\xc5@\\xcc\\x1c/f\\x8f\\x98A\\x0e \\x04\\xea\\x95!\\x1dm\\xcd*\\x10/\\xc3)&\\xda\\x89\\xc5\\x84\\xbe\\xa9\\xf8^\\xda\\xaa\\x89\\xedym\\x1a\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@?\\x18\\x88\\x99\\xe4\\xa6\\x98QbV\\xa9Y\\xbcr\\xb8*P\\xad\\n\\x14\\xef\\xb9Y\\xa7\\x98L{\\x17\\x93jZ\\xf1\\xed\\xfd\\xfb.\\xddj\\xf4\\xd2-\\xbf\\x87\\x1d\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81v0\\x103\\xcb\\xb4\\x98ab\\x96\\xa9V\\xbar4*P\\xc1\\n\\x14w\\xe1|e1i\\xf6,&\\xcd\\x7f\\x14\\xdfO\\x16\\xff\\xdd\\x8e\\x89\\xea5\\xd4\\x19\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18h\\x1a\\x031\\xcb\\xc4L\\x13\\xb3M\\xcc8\\x15\\x8c^\\x0eI\\x05:S\\x81\\x89\\x13\\'\\xaeUL\\x8c\\x91\\xc5\\x04\\xb9\\xa0\\xf8~\\\\\\xe8\\'=0\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81T\\x18\\x88\\x19\\xe7\\xc5\\xac\\xb3k\\xcc>\\x9dI]^U\\x05:\\\\\\x81\\xe2}2o-&\\xf5\\xa9\\xc5\\xf7oS\\x99\\xdc\\xce\\xc3F\\x85\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c\\xf4\\xc1@\\xcc>\\xa7\\xc6,\\xd4\\xe18\\xe6\\xe5U\\xa0\\xf5\\x15\\x88\\x97\\xbf\\x14\\xf6+\\xde\\xbd\\xff\\xea\\x02\\xfc\\x17\\xfa\\x98\\x18M\\xbb\\xfc\\xc6kX\\x801\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x8a1\\xf0B\\xccD1\\x1by\\x8b@\\xebs\\xa8Whs\\x05\\xe6\\xcf\\x9f\\xff\\xe6\\x02\\xee/\\x15\\xdf\\xbf\\xaf\\xd8\\xc4#\\x1a\\xbc\\xd7\\x0b\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xe8\\x18\\x031#\\xc5\\xac\\x143S\\x9bc\\x9a\\x97S\\x81\\xe6V\\xe0\\xc5\\x8f\\xee\\xbb\\xa8\\x08\\xfdK\\x04\\x7f\\xd6\\x15\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\xaf\\x0c,)D\\xc0E>R\\xb0\\xb9\\x99\\xd4\\xb3\\xb5\\xa1\\x02\\xc5\\xa4\\x8e7\\xf5\\xbb\\xce\\xe4\\xeeurw\\xcc0\\x1a\\x13c\\x82\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81j3\\xf0b\\x96\\x1a\\xd9\\x86\\xe8\\xe6%T\\xa0\\xe1\\n\\x0c*l\\xd5\\x98b1\\xb9\\xc7\\x82R\\xed\\x05\\xc5\\xf8\\x18\\x1f\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c\\xd4\\x82\\x81{b\\xc6*\\x12\\xda\\xa0\\x86S\\x9a_T\\x81fW\\xe0\\xe6\\x9bo\\x1e]X\\xaa{-\"\\xb5XD\\\\}\\xe0=n\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xa8\\x11\\x031k\\xc5\\xcc\\xd5\\xec\\x1c\\xe7\\xf9T\\xa0T\\x05\\n\\x10\\xf7.\\xbe\\xef\\x12\\xfc\\x05\\x7f\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\xade f\\xaf\\x98\\xc1J\\x856\\x0fV\\x81\\x81V\\xa0\\x80n\\xd7br/2\\xc1[;\\xc1\\xd5W}1\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x1e\\x18X\\x143\\xd9@s\\x9d\\xdfW\\x81>+P\\xbc\\xffd\\xd3\\x02\\xbe\\x1f\\xf4\\x00\\xa0K\\x88jt\\t\\x91\\xf1\\xb3\\x89`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` \\t\\x06~\\x103Z\\x9f!\\xce_\\xaa@\\xd9\\n\\\\s\\xcd5\\xff\\xaf0Lg\\x17\\x8b\\x84\\x8f\\xf3\\x13\\xf4\\xc9\\x1e\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0:\\x0c\\xc4\\x8f\\x0f<;f\\xb6\\xb29\\xcf\\xe3U`\\xa5\\nL\\x9c8q\\xad\\x02\\xa6qE\\xf0\\xff#C\\x98\\x84!\\xb4PWg\\xa16\\x16\\xc6\\x02\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0\\x99\\x0c\\xfc1f\\xb7\\x98\\xe1V\\nu\\xfeG\\x05\\xfaS\\x81\\xe2.\\x93\\xc3\\x8b\\xd0\\xff\\x9f\\x82\\xbf\\xe0\\x8f\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa06\\x0c\\xfcg\\xccr\\xfd\\xc9|\\x1e\\xa3\\x02\\xaf\\x987o\\xdek\\ns\\xf4\\xd5\\xe2{\\xb9I^\\x9bI\\xdeLs\\xe8\\xb9\\x98h\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c\\xd4\\x98\\x81\\x98\\xe5b\\xa6\\x8b\\xd9N\\xc4U\\x81^+P\\xdc@b\\xf7\\x02\\x94\\xdf\\x08\\xfe\\x82?\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81z3\\x10\\xb3]\\xccx\\xbd\\x06@\\x7f\\x91g\\x05\\x16,X\\xb0A1\\xb9g\\x98\\xe0\\xf5\\x9e\\xe0\\xc6\\xcf\\xf8a\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03=00#f\\xbe<\\xd3\\xae\\xb3^\\xa9\\x02\\xc5\\xfbC\\xf6-\\x00q\\x93\\xbf\\x1a_\\xe2\\xd3\\xc3\\x04w\\xc9\\x96\\xf1\\xc4\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06^\\xce\\xc0\\x1fc\\xf6[)\\x0c\\xfa\\x9f|*p\\xf9\\xe5\\x97\\xffmqI\\xc8y\\xc2#C\\x88\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` \\x0f\\x06b\\x06\\x8cY0\\x9f\\xe4\\xebL_q\\xd3M7\\r-\\x06\\xfe~\\x93<\\x8fIn\\x9c\\x8d3\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\xd0\\xcd@\\xcc\\x821\\x13\\x8a\\xc6\\xe9W`Pq\\x13\\x88O\\x17\\x03\\xbf\\xa4{\\xf0\\xfdi!\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x90\\x1d\\x03Kb6,\"\\xf0\\xa0\\xf4cp\\x86gX\\x18\\x9e\\r\\x8bI=\\xdf\\xc4\\xcenb\\xbf\\xfc}?\\xfe\\xdb\\xfb\\xc00\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x9730?f\\xc5\\x0c#r\\xba\\xa7\\\\\\x0c\\xe8VE\\xf0\\xff\\xad\\xf0/\\xfcc\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\xc0*\\x0c\\xfc6f\\xc6t\\x13qFgV\\xbc\\xbf\\xe3\\xc8\\xe2\\xfb\\xf9U\\x06\\xf8\\xe5\\xc6\\xc7\\x7f3\\x80\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x062f f\\xc6\\x98\\x1d3\\x8a\\xcai\\x9d\\xea5\\xd7\\\\\\xb3n1\\x80\\x17\\x08\\xfe\\xec\\x1e\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c\\xf4\\x87\\x81\\x98!c\\x96L+\\x1d\\'~6\\xc5\\xe5\\x1b\\x1b\\x17\\x03w{\\x7f\\x06\\xd8c,\\x04\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\xd0\\xcd@\\xcc\\x921S&\\x1e\\x9b\\xd38\\xbdb\\xa0\\x86\\x16\\x03\\xf7H\\xf7\\xe0\\xf9\\xd3D\\xc6\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x92\\x0c<\\x12\\xb3e\\x1a)9\\xd1\\xb3(>\\xc6a\\xaf\\xc2\\xd6<Sr`\\xbd\\xd7\\xa7\\x03\\xef\\xf5\\x997o^\\x981cF8\\xfb\\xec\\xb3\\xc3\\x84\\t\\x13\\xc2q\\xc7\\x1d\\x17\\x0e;\\xec\\xb0p\\xc0\\x01\\x07\\x84\\x9dw\\xde9l\\xb1\\xc5\\x16\\xe1\\x1d\\xefxG\\xd8d\\x93M\\xc2\\xc6\\x1bo\\x1c6\\xdah\\xa3\\xf0\\x867\\xbc!\\xac\\xb7\\xdez\\xe1U\\xafzUX{\\xed\\xb5}\\xab\\x01\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\xc7\\x18\\x88=i\\xecMc\\x8f\\x1a{\\xd5\\xd8\\xb3\\xc6\\xde5\\xf6\\xb0\\xb1\\x97\\x8d=m\\xecmc\\x8f\\x1b{\\xdd\\xd8\\xf3\\xc6\\xde7\\xf6\\xc0\\xb1\\x17\\x96Y\\xaa/$b\\xb6\\x8c\\x193\\xd1\\xf8\\\\\\xef\\xd3*\\x06g|\\xf1\\xbd\\xdcD\\xaa\\xceD\\xba\\xfa\\xea\\xab\\xc3\\xb9\\xe7\\x9e\\x1bN8\\xe1\\x84p\\xd0A\\x07u-\\x82\\x9bm\\xb6YX\\x7f\\xfd\\xf5CA\\x9bo5\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc8\\x96\\x81\\xd8\\x13\\xc7\\xde8\\x8a\\x82\\xd8+\\xc7\\x9e9\\xf6\\xce\\xb1\\x87\\x96i\\xaa\\x93ib\\xc6\\x8cY\\xb3\\xdei9\\xad\\xa3\\x1fT\\x0c\\xc8Y&I\\xe7&Ia\\xc5\\xbaL\\xe6\\xe7?\\xff\\xf9p\\xf0\\xc1\\x07\\x87\\xad\\xb7\\xde:l\\xb8\\xe1\\x86\\xd9.\\xe6\\xe4\\x06\\xb9\\x83\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x0600\\x10\\x06b/\\x1d{\\xea\\xd8[\\xc7\\x1e;^5\\x10{n\\x99\\xa7s\\x99\\'f\\xcebL\\x07\\x15\\xdf\\xbe:U\\x81\\xa9S\\xa7\\xfeM1\\tf\\x99\\x08\\xed\\x9d\\x08\\xf1\\x92\\xa5s\\xce9\\'\\x1c~\\xf8\\xe1a\\xf8\\xf0\\xe1\\xe1o\\xff\\xf6o\\x85}\\xf6\\x1e\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03-d \\xf6\\xdc\\xb1\\xf7\\x8e=x\\xec\\xc5\\xbd\\x8d\\xa0\\xbd\\x19\\xe8\\xc5\\xcc9+f\\xd0N\\xe5\\xdf\\xac_\\xb7\\xb8!\\xc3\\xab\\n\\x0b3W\\xf8o=\\xf8\\x0b\\x16,\\xe8z\\xbf\\xd2\\xbf\\xfc\\xcb\\xbft\\xbd\\xa7i\\xad\\xb5\\xd6\\xb2\\xb8\\xb7pq/&\\xb6\\xfa\\xaa\\x01\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\x9f\\x0c\\xc4\\x9e<\\xdeo \\xf6\\xe8\\xf1\\xde\\x02\\xb1g\\x97\\x8dZ\\x9f\\x8db\\x06\\x8dY4\\xeb0\\xde\\xee\\x93/l\\xd7k\\x8a\\xc2\\xdf\\x00\\xf0\\xd6\\x01>s\\xe6\\xcc\\xae\\x9b\\x95\\xc4K\\x8f\\xd6Yg\\x9d>\\x17\\x1f\\x81U`\\xc7\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@g\\x19\\x88={\\xec\\xdd\\xe3\\r\\x07c//+\\xb5.+\\xc5,\\x1a3i\\xc1\\xbc\\xafVW\\xe0\\xfa\\xeb\\xaf_\\xbf(\\xf8m\\x80n>\\xd0\\xe7\\x9f\\x7f~\\x183fLx\\xf3\\x9b\\xdf,\\xf03\\xce\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xa81\\x03\\xb1\\xa7\\x8f\\xbd}\\xec\\xf1e\\xa7\\xe6g\\xa7\\x98Ic6mu\\xfe\\xcd\\xfa\\xf9\\x8bK-6,\\n}7\\x80\\x9b\\x07\\xf0\\xb4i\\xd3\\xba\\xee:\\xfa\\xc67\\xbe\\xd1\\x02_\\xe3\\x05\\xbeX\\x18\\x8c\\x9f\\x1a`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c\\xf4\\xc8@\\xec\\xf5\\xe3\\'\\r\\xc4\\xde_\\x96j^\\x96\\x8a\\xd94f\\xd4\\xacCz\\xabN>\\x16\\xb6\\x80\\xf5>\\xc0\\x0e\\x1c\\xd8Y\\xb3fu}\\x1e\\xa9\\x7f\\xe9\\x17\\x9a\\x89\\x03\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xbc\\x18\\x88\\x19\\xe0\\xb0\\xc3\\x0e\\x0b1\\x13\\xc8V\\x03\\xcfV1\\xa3\\x92\\x00\\xc5*\\xd2\\xcc\\xaf\\x17/\\xfb\\xf7/\\xff\\xb76\\x0e\\xe8\\x8d7\\xde\\x18&N\\x9c\\x18\\xb6\\xdcr\\xcb\\x1e\\xad`1^~\\xae\\x06\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc8\\x88\\x81\\x98\\rbF\\x88Y\\x81\\x0ch<k\\xc5+\\x01\\xbc\\x1d\\xa0I\\x06\\xe0\\xc5\\x1b\\xfey\\xcf\\x7f\\x83\\xe1\\xff\\x92K.\\xe9z\\xef\\xcf\\xfa\\xeb\\xafo1\\xcfh1\\'t\\x08-\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xfe2\\x10\\xb3B\\xbc_@\\xcc\\x0eD@c\" \\xde\\x13\\xc0\\x8d\\x01\\x0b\\xe2\\x06\\xf2U\\\\J\\x11?\\xea\\xcf\\xdd\\xfe\\x1b\\x08\\xff_\\xf9\\xcaW\\xc2V[m%\\xf4\\x0b\\xfd\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\xbf\\x19\\x88\\x19\"f\\t\"\\xa0\\xbc\\x08\\x88\\xd95f\\xd8\\x81d\\xe0l\\x7fw\\xea\\xd4\\xa9\\x7fS\\x14p.\\xf0\\xfa\\x0f^\\x01[8\\xf9\\xe4\\x93\\xc3?\\xfe\\xe3?\\xf6{\\x82\\x17\\x80y\\xac\\x1a`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03+1\\x103E\\xcc\\x161c\\xc8d\\xfd\\xcfd1\\xc3\\xc6,\\x9bm\\x90o\\xf0\\xc4\\x07\\x15\\x90\\xcd\\x02Z\\xff@\\xbb\\xee\\xba\\xeb\\xc2\\xf8\\xf1\\xe3\\xc3\\x06\\x1bl\\xb0\\xd2\\xa4\\x15\\xee\\xc9\\r\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`` \\x0c\\xc4\\x8c\\x11\\xb3F\\xcc\\x1c\\xf2Y\\xff\\xf2Y\\xcc\\xb2E\\xcd\\x07\\x15\\xdf\\xbe\\xfaS\\x81\\xc2\\x9a\\x9c\\r\\xae5\\xc35\\x7f\\xfe\\xfcp\\xd4QG\\x85\\xf5\\xd6[O\\xf0gl1\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x961\\x103G\\xcc\\x1e1\\x83\\xc8jk\\xcejE\\xa6=\\xab?\\xd97\\xfb\\xc7\\x14\\x85\\x1a\\x0f\\xa8\\xbe\\x81Z\\xb0`A8\\xe6\\x98c\\xc2\\xeb^\\xf7\\xba\\x96M\\xf0\\x02D\\xcf\\xad\\x06\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\xc0J\\x0c\\xc4\\x0c\\x12\\xb3H\\xcc$r[\\xdf\\xb9-f\\xdb\\xec\\x03~_\\x05X\\xb8p\\xe1^E\\x91\\x96\\x03\\xa9g\\x90\\xe2\\xc7s\\x1c\\x7f\\xfc\\xf1.\\xf5\\xb7\\x08\\xaf\\xb4\\x08\\x935d\\x15\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\xbb\\x19\\x88o\\r\\x88\\xd9\\xc4G\\x08\\xf6\\x9c\\xddb\\xa6\\x8d\\xd9\\xf6\\xe6\\x9bo\\x1eU\\x8c\\x8d\\xafU+P\\xdc\\\\bhQ\\xa0g\\x84\\xff\\x9e\\x01:\\xe3\\x8c3\\xc2[\\xde\\xf2\\x16\\xc1O\\xf8\\xc7\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06*\\xc3@\\xcc(1\\xab\\xc8q=\\xe7\\xb8\\x98qc\\xd6]5\\xfff\\xfd\\xffEA6.\\x80y\\x044\\xabCs\\xf1\\xc5\\x17\\xfb8?\\x0b|e\\x16\\xf8b\\xa1r,j\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\xb0\\x1a\\x03\\xf1\\xe3\\x03cv\\x91\\xe9V\\xcft1\\xeb\\xc6\\xcc\\x9bu\\xe8\\xef>\\xf9k\\xae\\xb9f\\xdd\\xc2\\x8a\\xdc\\x0e\\x94\\x95A\\x99;wn\\x18=ztXk\\xad\\xb5V\\x9b\\\\B\\x98\\x10\\x8a\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0cT\\x8d\\x81\\x98]b\\x86\\x89YF\\xbe[9\\xdf\\xc5\\xcc\\x1b\\xb3o1fy\\x7f\\x15\\x85\\xb8\\x00\\x1c+\\xc3q\\xd2I\\'\\xb9\\xb3?\\xabJ\\xfc`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0\\x96\\x0c\\xc4O\\x0c\\x88\\x99F\\xce[9\\xe7\\xc5\\xec\\x9bu\\xfa/n\\xfaw\\x04(^\\x82\\xe2\\xb2\\xcb.\\x0b\\xc3\\x86\\r\\xab\\xe5$/@v\\xdcj\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c\\xfc\\x95\\x81\\x98mb\\xc6\\x91\\xf9^\\xca|1\\x03g)\\x01\\x8a\\xf7@lU\\x18\\x90\\xe7\\xc1pk(j\\x11\\xc6\\x8f\\x1f\\x1f\\xd6Yg\\x9d\\xbfN\\x16\\x81\\x9aP\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06\\xea\\xce@\\xcc81\\xeb\\xc4\\xcc#\\xfbu}2\\xc0\\xf3E-\\xb6*\\xc65\\x9f\\xaf\\xe2\\x847,\\x06\\xff\\xb7\\x00\\xb85L\\x9b6-\\xfc\\xd3?\\xfd\\x93\\xe0\\xcf\\x94b\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\xc92\\xb0\\xe9\\xa6\\x9bve\\x1f\\x19\\xb0\\xebj\\x80\\xdf\\xc6L\\x9c\\x8b\\x01\\x18T\\x0c\\xfa\\xfc\\xdc\\x07\\xbe\\xb8\\xf4#|\\xf4\\xa3\\x1f\\rk\\xaf\\xbdv\\xb2\\x93\\xbc\\x00\\xda\\xb9\\xa9\\x01\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\xd0\\xc5@\\xcc>1\\x03\\xc5,\\x94{\\x1e\\x8c\\x99\\xb8\\xc8K\\x83\\x92\\x97\\x00\\xc5`\\x7f:\\xf7\\xc1\\xfe\\xeew\\xbf\\x1b\\x86\\x0e\\x1dj!\\xb4\\x10b\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\xd91\\x10\\xb3P\\xccD\\xb9\\xe7\\xc2\"\\x1b\\x7f*i\\x01P\\\\\\xe60\\xb4\\x18\\xe4%9\\x0f\\xf4\\xc4\\x89\\x13\\xc3k_\\xfb\\xda\\xec&\\xb9\\xab\\x01\\\\\\r\\x81\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0ct3\\x103Q\\xccF9g\\xc3\\x98\\x8dcF.j\\x92\\xde\\xd7\\xe5\\x97_\\xfe\\xb7\\xc5M\\xff\\xee\\xcfu\\x80\\xe7\\xcd\\x9b\\x17\\xf6\\xd8c\\x0f\\xc1\\x9f\\xe1\\xc5\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\xf0\"\\x031#\\xc5\\xac\\x94kN\\x8c\\x199f\\xe5\\xe4\\x0c@qb\\xe7\\xe5:\\xa8\\x97^zi\\xd8d\\x93MLr\\x0b=\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81U\\x18\\x88Y)f\\xa6\\\\\\xf3b\\xf1V\\x80o$%\\x00\\x8a\\x81\\xdc\\'\\xd7\\xc1\\xfc\\xd2\\x97\\xbe\\x14^\\xfd\\xeaW\\x9b\\xe4\\xabL\\xf2\\x02p5Q\\x03\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0\\x8b\\x81\\x98\\x99bv\\xca57\\xc6\\xcc\\x9c\\x84\\x04X\\xb0`\\xc1\\x06\\xc5\\xc9\\xfc1\\xb7\\x81\\x8cw\\xb6<\\xf4\\xd0C-h\\x164\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\xfdd f\\xa8\\x98\\xa5r\\xcb\\x8f13\\xc7\\xec\\\\{\\tP\\x9c\\xc8\\x8c\\xdc\\x06\\xef\\xea\\xab\\xaf\\x0e\\xc3\\x87\\x0f7\\xc9\\xfb9\\xc9]\\r\\xe0j\\x08\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0\\x9b\\x81\\x98\\xa5b\\xa6\\xca-G\\xc6\\xec\\\\\\xd4\\xa0\\xbe_\\x85\\xb9\\xd9=\\xb7A\\xbb\\xec\\xb2\\xcb\\xc2\\xc6\\x1bo,\\xfc\\x0b\\xff\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06\\x1ad f\\xaa\\x98\\xadr\\xcb\\x931C\\xd7\\xd2\\x00\\\\u\\xd5U\\xaf.n\\xfc\\xf7@N\\x03v\\xdey\\xe7\\x85\\xf5\\xd7_\\xdf$op\\x92\\x17\\xa0\\xab\\x9d\\x1a`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03]\\x0c\\xc4l\\x153VN\\x992f\\xe8\\x98\\xa5k\\'\\x01\\x8a\\x03\\xffJN\\x035i\\xd2\\xa4\\xb0\\xce:\\xebX\\xac,V\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06\\x9a\\xc4@\\xccX1k\\xe5\\x94-c\\x96\\xae\\x95\\x00\\xb8\\xe9\\xa6\\x9b\\xb6*\\x0ezy.\\x834~\\xfcx\\x13\\xbcI\\x13\\xdcU\\x00\\xae\\x82\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06Ve f\\xae\\\\\\xf2e\\xcc\\xd21S\\x175\\xa8\\xfe\\xd7\\xc4\\x89\\x13\\xd7*\\x0e\\xf8\\xee\\x1c\\x06\\xa78\\xcfp\\xe0\\x81\\x07\\n\\xff\\xc2?\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x163\\x10\\xb3W\\xcc`\\x99d\\xcd\\xbbc\\xb6\\xae\\xbc\\x01(\\x06d\\\\\\x0e\\x03r\\xf3\\xcd7\\x87Q\\xa3F\\x99\\xe4-\\x9e\\xe4\\x05\\xf0j\\xac\\x06\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\x17\\x031\\x83\\xc5,\\x96C\\xe6\\x8c\\xd9\\xba\\xd2\\x02\\xe0\\x9ak\\xae\\xf9\\x7f\\xc5@\\xfc1\\xf5\\xc1(.\\xc7\\x08;\\xef\\xbc\\xb3E\\xc8\"\\x84\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0\\xcd\\x0c\\xc4,\\x163Y\\xea\\xb93f\\xeb\\x98\\xb1++\\x01\\nCqv\\xea\\x83\\xb0`\\xc1\\x82\\xb0\\xddv\\xdb\\x99\\xe4m\\x9e\\xe4\\xae\\x04p%\\x04\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\xd0\\xcd@\\xccd1\\x9b\\xa5\\x9e?c\\xc6.\\xce\\xb9z_\\x85\\x81\\xf9\\xa7\\xa2\\xf8KR\\x1e\\x80\\xf9\\xf3\\xe7\\x87-\\xb7\\xdcR\\xf8\\x17\\xfe1\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0ct\\x98\\x81\\x98\\xcdbFK9\\x83\\xc6\\x8c\\x1d\\xb3v\\xe5\\x0c@a&\\xaeL\\xb9\\xf0\\xd1.\\t\\xff\\x8cc1\\xf1,\\xf4j\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x8a0\\x103Z\\xeaW\\x02\\xc4\\xac])\\x01\\xb0p\\xe1\\xc2]R\\x0e\\xff\\xf1\\xfd%.\\xfb\\x17|\\x85\\x7f\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0z\\x0c\\xc4\\xac\\x163[\\xca\\x994f\\xee\\x82\\xbdj|\\x15\\x85^\\x94j\\xb1\\xe3\\x1d&\\xdd\\xf0\\xafz\\x93\\xbc \\x9fuU\\x03\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0\\x8b\\x81\\x98\\xd9\\x12\\xfft\\x80E\\x95H\\xff\\x85\\x89\\xd8+\\xd5\\xf0_\\\\j\\xe1\\xa3\\xfe,(6\\x15\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0\\x06\\x0c\\xc4\\x8f\\x08\\x8c\\x19.\\xd5|\\x1a\\xb3w\\xc7%@Q\\xdc;S-\\xf0\\x81\\x07\\x1eh\\xa2\\xd7`\\xa2\\xbb\\x1a\\xc0\\xd5\\x10\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@d f\\xb8T\\xf3i\\xcc\\xde\\xc59v\\xee\\xab\\xb0+\\x07\\xa4Z\\xdc\\xf1\\xe3\\xc7\\x0b\\xff\\xc2?\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x9a1\\x10\\xb3\\\\\\xaa95f\\xf0N\\x19\\x80A\\xc5\\x8b\\xdf\\x9bba\\'M\\x9ad\\x92\\xd7l\\x92\\x17\\x93\\xc0\\x98\\xa9\\x01\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\xd0\\xc5@\\xcct)f\\xd5\\x98\\xc1\\x8b\\xec3\\xa8\\xed\\x12\\xa0x\\xff\\xc1\\x07S,\\xe8y\\xe7\\x9d\\x17\\xd6Yg\\x1d\\x0b\\x87\\x85\\x03\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@M\\x19\\x88\\x99.f\\xbb\\x143k\\xcc\\xe2m\\x17\\x00E!\\xff3\\xb5b^v\\xd9ea\\xfd\\xf5\\xd77\\xc9k:\\xc9]\\x05\\xe0*\\x08\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0\\x9b\\x81\\x98\\xedb\\xc6K-\\xb7\\xc6,^\\x9cc\\xfb\\xbe\\x8a\\x17\\x1c\\x99Z\\x11\\xaf\\xbe\\xfa\\xea\\xb0\\xf1\\xc6\\x1b\\x0b\\xff\\x1d\\x08\\xff\\x83\\x06\\r\\n\\xeb\\xae\\xbbnXo\\xbd\\xf5\\xc2\\x1b\\xde\\xf0\\x86\\xf0\\xc67\\xbe1\\xbc\\xe5-o\\to{\\xdb\\xdb\\xc2\\xdb\\xdf\\xfe\\xf6\\xb0\\xe9\\xa6\\x9b\\x86\\xcd6\\xdb,\\xbc\\xf3\\x9d\\xef\\x0c\\xefz\\xd7\\xbb\\xc2\\xbb\\xdf\\xfd\\xee\\xb0\\xf9\\xe6\\x9b\\xfbV\\x03\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x8e1\\x10{\\xd2\\xd8\\x9b\\xc6\\x1e5\\xf6\\xaa\\xb1g\\x8d\\xbdk\\xecac/\\x1b{\\xda\\xd8\\xdb\\xc6\\x1e7\\xf6\\xba\\xb1\\xe7-\\x12\\x9b\\xef6\\xd7 f\\xbc\\x98\\xf5R\\xcb\\xaf1\\x93\\xb7\\xcd\\x00\\x14\\xef;\\xb86\\xa5\\x02\\x16\\x97P\\x84\\xe1\\xc3\\x87\\x9b\\x8cm\\x98\\x8cq\\xf1{\\xdd\\xeb^\\xd7\\xb5 n\\xb2\\xc9&]\\x0b\\xe6{\\xde\\xf3\\x9e\\xe0[\\r0\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06Rg \\xca\\x82\\xd8\\x03G9\\x10{\\xe2\\xd8\\x1b\\x93\\x02\\xad\\x97\"1\\xeb\\xc5\\xcc\\x97R\\x86\\x8d\\x99\\xbc-\\x02\\xe0\\xa6\\x9bn\\xda<\\xa5\\xc2\\xc5s9\\xf4\\xd0CM\\xbc\\x16\\x84\\xffh9_\\xf3\\x9a\\xd7\\x84\\x8d6\\xda\\xa8k\\xa1\\x8b\\x864\\xf5E\\xdd\\xf9i\\\\0\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06\\xca0\\x10{\\xe4(\\x05b\\xcf\\x1c{gW\\n\\xb4F\\x08\\xc4\\xcc\\x97Z\\x8e\\x8d\\xd9\\xbc\\xe5\\x12\\xa00\\r\\x17\\xa6T\\xb8\\xd3O?]\\xf8ob\\xf8\\x8f7\\xdb\\xd8`\\x83\\r\\xba\\x16\\xb1xYT\\x99\\xc5\\xcfcm\\x96\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\xb93\\x10{\\xe8(\\x04bO\\xed\\xe6\\xe4\\xcd\\x95\\x011\\xfb\\xa5\\x94ec6o\\xa9\\x00(^\\xe0ME\\xc1\\x96\\xa4R\\xb4K/\\xbd4\\xbc\\xfa\\xd5\\xaf&\\x00\\x06(\\x00\\xe2\\xa5K\\xd1X\\xbe\\xe3\\x1d\\xef\\x10\\xf8\\xbd\\x9d\\x01\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03Md \\xf6\\xd8\\xb1\\xd7\\xf6v\\x81\\x81\\xcb\\x80\\x98\\xfdb\\x06L%\\xcf\\xc6l\\x1e3z\\xcb$@\\xf1\\xbe\\x89\\xd3R)\\xd6\\xfc\\xf9\\xf3\\xbb\\xccZQ,\\x02\\xa0\\x81\\x1a\\xbc\\xf2\\x95\\xaf\\x0c\\x7f\\xf7w\\x7f\\xd7u\\xb3\\x93\\xdc-\\xad\\xf3\\xf7/\\x15\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\xed` \\xdeh0\\xf6\\xe0\\xb1\\x17\\x97c\\x1a\\xcbq\\xf1\\xea\\x8a\\x98\\x05S\\xc9\\xb51\\xa3\\xb7D\\x00\\x14\\xef/xea\\x17~\\x9fJ\\xa1\\xf6\\xdcsO\\x93\\xa6\\x81\\xe0\\x1f\\xefb\\xfa\\xf7\\x7f\\xff\\xf7]w[m\\xc7\"\\xe75l\\xa6\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18X\\x99\\x81\\xf8\\x89X\\xb1\\'\\x8f\\xbd9\\x11P^\\x04\\xc4,\\x98J\\xae\\x8d\\x19=f\\xf5\\xa6K\\x80\\xe2\\x89\\xf7O\\xa5H\\x13\\'N4QJ\\x84\\xff\\xb5\\xd6Z+l\\xb8\\xe1\\x86]\\x1fob\\xf1]y\\xf1U\\x0f\\xf5\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xe8$\\x03\\xf1#\\x08c\\xaf\\x1e{v2\\xa0\\xff2`\\xd2\\xa4I)I\\x80\\xfd[!\\x00\\xe6\\xa6 \\x00\\xbe\\xfb\\xdd\\xef\\x86\\xd7\\xbe\\xf6\\xb5&G?\\x04@\\xbc\\xb4(~D\\x89\\xbb\\xf7\\xdb\\xd4:\\xb9\\xa9ym\\xfca\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x8153\\x10{\\xf6\\xd8\\xbb{{@\\xff$@\\xcc\\x841\\x1b\\xa6\\x90q\\x8b\\x7f\\xac\\x9f\\xdbT\\x01P\\\\R\\xb0q\\xf1\\xa4\\xcb\\xeb^\\x9c\\xf8\\xd9\\x8fC\\x87\\x0e\\x15\\xfe\\xd7\\x10\\xfe\\xe3\\xa2\\xf1\\xa67\\xbd)\\xb8\\x8b\\xff\\x9a\\x17Z\\x9b\\x91\\x1aa\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0cT\\x89\\x81\\xd8\\xc3\\xc7^\\x9e\\x08X\\xb3\\x08\\x88\\xd90f\\xc4\\xba\\xe7\\xdc\\x98\\xd5cfo\\x9a\\x04(\\x9e\\xf0\\x94\\xba\\x17%\\x1e\\xffQG\\x1d%\\xfc\\xf7\\x11\\xfe\\xd7^{\\xed.k(\\xf8\\xdb\\xc4\\xaa\\xb4\\x899\\x16<b\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xf2\\x0c\\xc4\\x9e>^\\x11\\x10{|o\\r\\xe8]\\x06\\xc4\\x8c\\x98B\\xd6\\x8d\\x99\\xbd)\\x02\\xa0x\\xbf\\xfcZEA\\x1e\\xac{Q\\xa6M\\x9b\\x06\\xfe>\\xc2\\x7f\\xfc\\x9cQ\\x97\\xfa\\x97_XmFj\\x86\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060Pe\\x06b\\x8f\\x1f{}\\x12\\xa0g\\t\\x10\\x05\\xc9\\xf4\\xe9\\xd3S\\x90\\x00\\x0f\\xc6\\xec>`\\tP\\x98\\x84]\\xeb\\x1e\\xfe\\x8b\\xcb!\\xba>\\xae\\x0e\\xf4\\xabC\\x1f\\xdf\\xfb\\x12?N\\xa4\\xca\\x8b\\x96c\\xb3\\xa9b\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c```\\x0c\\xc4\\x9e\\xdf\\xbd\\xd0V\\xcfC1#\\xc6\\xda\\xc4\\xccX\\xf7\\xdc\\x1b\\xb3{3\\x04\\xc0\\x05u/\\xc4\\xf8\\xf1\\xe3\\x19\\xafU\\xfe\\xf5?\\xbe\\'\\xe8mo{\\x9b\\xe0\\xff\\x9e\\x81-\\xa46\"\\xf5\\xc3\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xa8\\x13\\x031\\x03\\xb8?\\xc0\\xea\" f\\xc6\\xba\\xe7\\xdeB\\x00\\\\0 \\x01PX\\x90W\\x16O\\xf2x\\x9d\\x0bq\\xd9e\\x97\\x85u\\xd6Y\\x87\\x00x\\x99\\x00x\\xfd\\xeb_\\xefr\\x7f\\xc1\\x9f\\xfc\\xc1\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc8\\x94\\x81\\xf8\\xb6\\x80\\x98\\t\\\\!\\xfd\\x92\\x08\\x88\\x991f\\xc7:g\\xdf\\x98\\xddc\\x86oX\\x02\\x14O\\xb0G\\x9d\\x0b\\x10\\x8f}\\xd8\\xb0a\\xc0~1\\xfcG\\xd3\\xf7\\x0f\\xff\\xf0\\x0f\\x16\\xfaL\\x17\\xfa:\\x99i\\xc7\\xea_R0\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\xeb\\x19\\x88\\xd9\\xc0\\xd5\\x00/I\\x80\\x98\\x1d\\xeb\\x9e\\x7fc\\x86\\x1f\\x88\\x00\\xf8\\x8f:\\x17\\xe0\\xa4\\x93N\\x12\\xfe_\\x0c\\xff\\xeb\\xaf\\xbf\\xbe\\x7f\\xf5\\x17\\xfc\\xc9\\x1f\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c\\xac\\xc4@\\xbc\\x1a f\\x05W\\x03\\xfc\\x9f\\x08\\x88\\x19\\xb2\\xce\\x19\\xb88\\xf6\\xe9\\r\\t\\x80\\xa9S\\xa7\\xfeM\\xf1\\xcbO\\xd4\\xf5\\xe4\\xe7\\xce\\x9d\\x1b\\xd6[o\\xbd\\xecA^k\\xad\\xb5\\xc2\\xc6\\x1bo\\xbc\\xd2$gS[oS\\xd5X\\x8d1\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06\\xea\\xc4@\\xcc\\x0c\\x83\\x06\\r\\xca>?\\xc5\\x0c\\x19\\xb3d]sp\\xcc\\xf01\\xcb\\x97\\x96\\x00\\xc5\\xa5\\x03{\\xd7\\xf8\\xa4\\xc3\\xe8\\xd1\\xa3\\xb3\\x877\\xbe\\x8f\\xc5\\x1d\\xfem<u\\xdax\\x1c+^1\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\xe7\\x18\\x88\\xd9\\xc1\\xfd\\xd3^\\xd1\\x95%\\xeb\\x9c\\x85c\\x96/-\\x00\\x8a\\x13\\x9eV\\xd7\\x93\\xbe\\xf8\\xe2\\x8bC\\xfc\\x97\\xef\\x9c/c\\x89\\xe6*^\\xcec\\x01\\xed\\xdc\\x02\\xaa\\xf6j\\x8f\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060P7\\x06b\\x86\\xc8\\xfdJ\\xea\\x98%c\\xa6\\xack\\x1e.\\x04\\xc0\\xb7\\x1a\\x11\\x00\\x0f\\xd7\\xf5\\x84\\xb7\\xdaj\\xab\\xac\\xc3\\xffF\\x1bm\\x146\\xdf|s\\xe1\\xdf\\xfb\\xbb0\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xd2\\x0c\\xc4,\\x113E\\xce\\xff\\xa0\\x1a3e]\\xf3p!\\x00\\x1e*%\\x00\\x16.\\\\\\xf8\\x9e\\xba\\x9e\\xec\\x19g\\x9c\\x91-\\xa8\\xf1=;o}\\xeb[KO\\xf0\\xbaYI\\xc7\\xcb\\xa4c\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0\\xf5\\x0c\\xc4l\\x91\\xf3}\\x01&O\\x9e\\\\[\\t\\x103}\\xbf%@a\\x0c>SG\\x01p\\xe3\\x8d7v\\xdd\\xf0.GS\\xb5\\xf6\\xdak\\x87\\xb7\\xbf\\xfd\\xed\\xc2?\\xc3\\x8b\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c4\\x8d\\x81\\x981b\\xd6\\xc81c\\xc5\\x1b#\\xc6\\x8cY\\xc7l\\x1c3}\\xbf\\x05@q\\x827\\xd6\\xf1$\\x8f?\\xfe\\xf8,\\xc1\\x8c\\x9f\\xdd\\xe9f\\x7f\\xad7\\xa0,\\xb3\\x1ac\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c\\xe4\\xc8@\\xcc\\x1a1s\\xe4(\\x01b\\xc6\\xacc6\\x8e\\x99\\xbe_\\x02\\xe0\\xa6\\x9bnzm\\xf1\\xe0\\xa5u;\\xc9\\x05\\x0b\\x16\\x84\\r6\\xd8 ;(\\xe3]:7\\xdbl\\xb3\\xa6\\x19\\xbe\\x1c\\x174\\xe7l#\\xc7\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\xdf\\x0c\\xc4\\xcc\\x91\\xe3\\'\\x04\\xc4\\x8c\\x19\\xb3f\\xdd\\xf2q\\xcc\\xf41\\xdb\\xafQ\\x02\\x14\\x97\\n\\xec_\\xc3\\x93\\x0b\\xc7\\x1csLv\\xe1\\x7f\\xddu\\xd7\\r\\xef|\\xe7;\\x85\\x7f\\x97xa\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03-g f\\x8f\\x98Ar\\xbb\\x12 f\\xcd:f\\xe4\\x98\\xed\\xfb#\\x00\\xa6\\xd4\\xed\\xe4\\xe6\\xcf\\x9f\\x1f^\\xf7\\xba\\xd7e\\x05b\\x9cx\\xff\\xfc\\xcf\\xff\\xdc\\xf2I\\xce\\x84\\xf6mB\\xd5G}0\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06rb f\\x90\\xdc$@\\xcc\\x9a1s\\xd6-\\'\\x17\\x02\\xe0\\xdc\\xfe\\x08\\x80\\xbb\\xebvbG\\x1duTV\\xe1?^z\\xe3_\\xfem49m4\\xce\\x15\\xef\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0:\\x0c\\xc4,\\x92\\xdb\\xdb\\x01b\\xe6\\xac[N.\\x04\\xc0\\xdd}\\n\\x80\\xf8\\x1e\\x81\\xe2A\\xcb\\xebtb\\xd7]w]Xo\\xbd\\xf5\\xb2\\x11\\x00\\xf1\\xe6\\x1b\\xde\\xf3_\\x9d\\xc5\\xcfFd,0\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06rd f\\x92\\x9cn\\x0c\\x183g\\xcc\\x9eu\\xca\\xca1\\xdb\\xf7y\\x1f\\x80\\xe2dF\\xd6\\xe9\\x84\\xe2\\xb1\\x8e\\x1f?>\\x9b\\xf0\\x1f?~\\xc3\\xdd\\xfem09n0\\xce\\x19\\xf7\\x18\\xc0@]\\x19\\x18<xp\\xd8v\\xdbm\\xbde\\xcf{\\xb31\\x80\\x81$\\x19\\x88\\xd9$\\xa7\\x8f\\x08\\x8c\\xd9\\xb3ny9f\\xfc^\\xaf\\x02(\\xfe\\xf2\\xd4:\\x9dPa3\\xc2\\x86\\x1bn\\x98\\x85\\x00\\x184hP\\x88\\x9f\\xc1Y\\xd7\\x06\\xc8qk\\xde1\\x80\\x01\\x0c` \\x07\\x06\\xf6\\xdak\\xaf\\xf0\\x99\\xcf|&\\\\t\\xd1E\\xe1\\x8e;\\xee\\x08\\x8b\\x17/\\x0e\\x17\\\\p\\x81\\xfd[\\xf8\\xc3\\x00\\x06\\x92e f\\x94\\x98U\\x8a\\x90\\x99\\xfcw\\xcc\\x9e1\\x83\\xd6)3\\xc7\\x8c\\xdf\\x97\\x00\\x98_\\xa7\\x939\\xf9\\xe4\\x93\\x93\\x87\\xac{\"\\xbd\\xf5\\xadoMv\\xd1\\xc8\\xa1!t\\x8e\\x82\\x0f\\x060\\x80\\x81\\xf4\\x18\\xd8}\\xf7\\xdd\\xc3\\'?\\xf9\\xc90m\\xda\\xb4\\xb0h\\xd1\\xa2\\xf0\\xf4\\xd3O\\x87\\x9e\\xbe\\x08\\x80\\xf4\\xc6\\xde|6\\xa6\\x18X\\x99\\x81\\x98U\\xbasK\\xea\\x7f\\xc6\\x0cZ\\xa7\\xcc\\\\\\x1c\\xeb\\xfc\\x1e\\x05\\xc0\\xe5\\x97_\\xbev\\xf1\\x97O\\xd7\\xe9d\\xfe\\xf1\\x1f\\xff1\\x0b\\xd06\\xdah#\\xe1\\x9f5\\xc6\\x00\\x060\\x80\\x01\\x0ct\\x90\\x81]v\\xd9%|\\xfc\\xe3\\x1f\\x0f\\xe7\\x9f\\x7f~W\\xe3\\xf7\\xe4\\x93O\\xf6\\x94\\xf5{\\xfc\\x19\\x01\\xb0rP\\x10\\x9c\\xd4\\x03\\x03i2\\x103K\\xea\\xe1?\\x9e_\\xcc\\xa0u\\xca\\xcc1\\xe3\\xc7\\xac\\xbf\\x9a\\x04X\\xb8p\\xe1{\\xeat\"_\\xfd\\xeaW\\xb3\\x00,\\xdelb\\xf3\\xcd7\\xd7\\xf4u\\xb0\\xe9\\xb3I\\xa5\\xb9I\\x19W\\xe3\\x8a\\x01\\x0c\\xf4\\xc6\\xc0\\x8e;\\xee\\x18\\x8e>\\xfa\\xe80e\\xca\\x94\\xaeK=\\x1f\\x7f\\xfc\\xf1\\x1e\\x83}\\x7f\\x7fH\\x00`\\xad7\\xd6\\xfc\\x1c\\x1b)1\\x103K.7g\\x8fY\\xb4N\\xd99f\\xfd\\x9e\\x04\\xc0!u:\\x89\\xe1\\xc3\\x87\\'/\\x00\\xe2Gk\\xbc\\xeb]\\xef\\x12\\xfe\\x85\\x7f\\x0c`\\x00\\x03\\x18\\xc0@\\x8b\\x18\\xd8~\\xfb\\xed\\xc3\\xb8q\\xe3\\xc2\\xd7\\xbe\\xf6\\xb5p\\xfd\\xf5\\xd7\\x87\\xdf\\xff\\xfe\\xf7\\xfd\\xcd\\xf5\\xfd~\\x1c\\x01 \\xe4\\xa5\\x14\\xf2\\x9c\\x0b\\x9e\\xfbb f\\x97\\x1c>\\x1e0f\\xd1:e\\xe7B\\x00\\x1c\\xb2\\x9a\\x00(>\"\\xe0\\xcc\\xba\\x9c\\xc4\\xb7\\xbf\\xfd\\xed\\xe4\\xc3\\x7f\\xbc\\x91\\x86;\\xfe[`\\xfbZ`\\xfd\\x1d>0\\x80\\x01\\x0c\\x94c`\\x9bm\\xb6\\tc\\xc7\\x8e\\r_\\xfe\\xf2\\x97\\xc3\\xb5\\xd7^\\x1b~\\xf7\\xbb\\xdf\\xf5;\\xc4\\x0f\\xe4\\x81\\x04@\\xb9q\\xc2\\xb5za\\xa0\\xde\\x0c\\xc4\\x0c\\x93\\xc3M\\x01c&\\xadK~.\\x8es\\xf2j\\x02\\xa0\\xf8\\xe15u9\\x811c\\xc6$/\\x006\\xdexc\\xff\\xda\\xd3\\xa2\\x7f\\xed\\xb1\\xa9\\xd4{S1~\\xc6\\x0f\\x03\\x18\\xe8\\x0f\\x03#F\\x8c\\x08\\xff\\xfa\\xaf\\xff\\x1a&O\\x9e\\x1c\\xae\\xba\\xea\\xaa\\xf0\\xc0\\x03\\x0f\\x84\\x15+V\\x0c$\\xc77\\xfc\\xbb?\\xf9\\xc9O\\xec\\xe9\\xf6t\\x0c` +\\x06b\\x96)\\x02g\\xd2\\xdf1\\x93\\xd6%?\\xc7\\xac\\xdf\\x93\\x00x\\xb8\\x0e\\'p\\xe3\\x8d7\\x86\\xf5\\xd7_?i\\x98\\xe2\\xf9\\xf5\\xa7\\xb9\\xf1\\x18M0\\x060\\x80\\x01\\x0c`\\xe0=a\\xcb-\\xb7\\x0c\\x07\\x1dtP8\\xed\\xb4\\xd3\\xc2\\x9c9s\\xc2/\\x7f\\xf9\\xcb\\xb0|\\xf9\\xf2\\x86\\x03{\\xb3\\x7f\\xf1\\xee\\xbb\\xef\\xb6\\xaf\\x0b\\x7f\\x18\\xc0@v\\x0c\\xe4\\x90\\xd9b6\\xadC\\x86.\\x8e\\xf1\\xe1\\x95\\x04\\xc0u\\xd7]\\xf7\\x86\\x9a\\x1cx\\x988qb\\xd2\\xe1\\xff\\x95\\xaf|\\xa5\\xf7\\xfd\\xdb \\xb2\\xdb \\x04\\x18!\\x16\\x03\\x18\\xe8/\\x03\\xc3\\x86\\r\\x0b\\x1f\\xf8\\xc0\\x07\\xba\\xfa\\x81\\xd9\\xb3g\\x87\\x9f\\xff\\xfc\\xe7a\\xd9\\xb2e\\xcd\\xce\\xecM}>\\x02\\x00\\xdf\\xfd\\xe5\\xdb\\xe3\\xb0\\x92\\x12\\x03\\xf1~\\x001\\xdb\\xa4|%@\\xcc\\xa6u\\xc9\\xd11\\xf3\\xffU\\x02\\x14\\xef\\xff\\xdf\\xb1.\\x07\\x1e-\\x7f\\xca\\x10\\xfd\\xc3?\\xfc\\x83\\xf0G\\x00`\\x00\\x03\\x18\\xc0\\x00\\x06\\n\\x06\\x86\\x0c\\x19\\x12F\\x8f\\x1e\\x1d&L\\x98\\x10f\\xce\\x9c\\x19~\\xfa\\xd3\\x9f\\x86%K\\x9645\\x9c\\xb7\\xe3\\xc9\\x08\\x00\\xa1.\\xa5P\\xe7\\\\\\xf0\\\\\\x86\\x81\\x98mR\\xcen[m\\xb5Um\\x04@\\xcc\\xfc/\\x17\\x00\\xc7\\xd6A\\x00\\xcc\\x9a5+i\\x80^\\xff\\xfa\\xd7k\\xf84\\xfd\\x18\\xc0\\x00\\x060\\x90-\\x03\\xfb\\xee\\xbbo8\\xe9\\xa4\\x93\\xc2\\xc5\\x17_\\x1c\\xee\\xba\\xeb\\xae\\xf0\\xdcs\\xcf\\xb5#\\x9f\\xb7\\xfc5\\x08\\x00\\x81\\xa9L`\\xf2X\\xbc\\xa4\\xc6@\\xcc8)K\\x80\\x98Q\\xeb\\x90\\xa5\\x0b\\x01p\\xec\\xcb\\x05\\xc09u8\\xe8\\xc3\\x0e;,Yx\\\\\\xfao\\xb1Om\\xb1w>\\x98\\xc6\\x00\\x06\\xfab`\\xd4\\xa8Q\\xe1S\\x9f\\xfaT\\xf8\\x8f\\xff\\xf8\\x8f\\x10o\\x92\\xf7\\xec\\xb3\\xcf\\xb6<\\x88w\\xea\\x05\\x08\\x00s\\xa1\\xaf\\xb9\\xe0\\xef\\xf0\\x91:\\x03\\xa9\\xbf\\x15 f\\xd4:d\\xe9B\\x00\\x9c\\xf3r\\x010\\xa7\\x0e\\x07\\xfd\\xe67\\xbf9Y\\x01\\xf0\\xb6\\xb7\\xbd-\\xdb\\x7f\\xf1I}\\xd1s~6v\\x0c` w\\x06F\\x8e\\x1c\\x19>\\xf1\\x89O\\x84\\xf8qx?\\xfa\\xd1\\x8f\\xc2SO=\\xd5\\xa9,\\xde\\x91\\xd7%\\x00\\xac\\x01\\xb9\\xaf\\x01\\xce\\xdf\\x1c\\x88Y\\'\\xd5\\xab\\x00bF\\xadC\\x96.\\x04\\xc0\\x9c\\xbf\\n\\x80\\xe2\\x80\\xef\\xa9\\xfaAO\\x9b6-Yh^\\xfb\\xda\\xd7\\n\\xff.\\xf9\\xc5\\x00\\x060\\x80\\x81$\\x18\\xd8i\\xa7\\x9d\\xc21\\xc7\\x1c\\x13\\xce;\\xef\\xbc\\xb0p\\xe1\\xc2\\xf0\\xe7?\\xff\\xb9#\\xa1\\xbbJ/J\\x00\\x08?\\x020\\x060\\xf0\\x9e\\x103O\\xaa\\x12 f\\xd5\\xaa\\xe7\\xe9\\x98\\xf9\\xff*\\x00\\n\\x1b\\xf0\\xbfU?\\xe0\\x83\\x0f>8Y`6\\xddt\\xd3$\\x9a>\\x0b\\x9b\\xcd\\r\\x03\\x18\\xc0@^\\x0c\\xec\\xb0\\xc3\\x0e\\xe1\\xa8\\xa3\\x8e\\n\\xe7\\x9e{n\\xb8\\xe1\\x86\\x1b\\xc2\\x1f\\xff\\xf8\\xc7*\\xe5\\xee\\xca\\x1c\\x0b\\x01\\x90\\xd7\\xbc\\xb0\\x0e\\x1ao\\x0c\\xf4\\xcc@\\xcc<\\xa9\\n\\x80\\x98U\\xab\\x9e\\xa7c\\xe6\\xef\\x12\\x00\\xc5\\x81\\xbe\\xbe\\xea\\x07\\x1b\\x8f\\xef\\x8do|c\\x92\\xc0l\\xb0\\xc1\\x06\\xc2\\xbf\\x7f\\xf5\\xc3\\x00\\x060\\x80\\x81\\xca3\\xb0\\xddv\\xdb\\x85#\\x8e8\"|\\xf5\\xab_\\r\\xf3\\xe6\\xcd\\x0b\\x0f?\\xfcpe\\x02v\\xd5\\x0f\\x84\\x00\\xe89\\x0c\\x08I\\xea\\x82\\x81\\xfc\\x18\\x88\\xd9\\'E\\t\\x10\\xb3j\\x1d2u\\xcc\\xfe\\xaf(.\\xcf\\x1bV\\xf5\\x83\\x9d:uj\\x92\\xa0\\xac\\xbd\\xf6\\xda!\\xde\\x14\\xc3\\xe2\\x97\\xdf\\xe2g\\xcc\\x8d9\\x060Pe\\x06F\\x8c\\x18\\x11>\\xfc\\xe1\\x0f\\x87\\xb3\\xce:+\\\\}\\xf5\\xd5\\xe1\\xc1\\x07\\x1f\\x0c+V\\xac\\xa8z\\xce\\xae\\xec\\xf1\\x11\\x00\\xe6{\\x95\\xe7\\xbbc\\xc3g;\\x19\\x88\\xd9\\'f\\xa0\\x14%@\\xcc\\xacU\\xcf\\xd51\\xfbG\\x01p`\\xd5\\x0ft\\xcc\\x981IB\\x12MQ;\\'\\x9c\\xd7\\xb2\\xc0c\\x00\\x03\\x18\\xc0\\xc0\\xaa\\x0c\\xc4\\xcf0>\\xe4\\x90C\\xc2\\xe9\\xa7\\x9f\\x1e\\xae\\xbc\\xf2\\xca\\xf0\\xeb_\\xff:\\xbc\\xf0\\xc2\\x0b\\x95\\r\\xd3u<0\\x02\\xc0\\xbc[u\\xde\\xf9\\x7fL\\xe4\\xcc@\\xaaWv\\xc7\\xccZ\\xf5\\\\\\x1d\\xb3\\xff+\\x8a\\xf7\\x02\\x1c[\\xf5\\x03M\\xf1\\xee\\xff\\xf1c\\xff\\xde\\xfd\\xeew\\x13\\x00.\\xfb\\xc5\\x00\\x060\\x80\\x81\\xb610l\\xd8\\xb0\\x10\\x1b\\x94/|\\xe1\\x0b\\xe1\\x8a+\\xae\\x08\\xbf\\xf8\\xc5/\\xc2\\xb2e\\xcb\\xea\\x98\\xa9ku\\xcc\\x04\\x80\\xb0\\x97s\\xd8s\\xee\\xf8_\\x95\\x81\\x98\\x81b\\x16J\\xed*\\x80:|\\x1a@\\xcc\\xfe\\xaf(\\xc2\\xff\\xa9U\\x16\\x003g\\xceL\\x0e\\x8e\\x08\\xfb\\x9b\\xde\\xf4\\xa6\\xb65|\\xabN:\\xffo!\\xc6\\x00\\x060\\x90>\\x03C\\x87\\x0e\\r\\x07\\x1ex`8\\xe5\\x94S\\xc2\\xacY\\xb3\\xc2}\\xf7\\xdd\\x17\\x96.]Z\\xab\\xe0\\x9c\\xca\\xc1\\x12\\x00\\xe9\\xcf7k\\xaa1\\xc6@9\\x06b\\x16JM\\x00\\xc4\\xf3\\x89\\xd9\\xb5\\xca\\xd9:f\\xffx\\x05\\xc0\\x94*\\x1f\\xe4q\\xc7\\x1d\\x97\\x1c\\x1c\\xfe\\xf5\\xbf\\xdc\\x02aAU/\\x0c`\\x00\\x03}30x\\xf0\\xe0\\xb0\\xff\\xfe\\xfb\\x87\\xcf}\\xees\\xe1\\xd2K/\\r\\xf7\\xdcsOx\\xfe\\xf9\\xe7S\\xc9\\xcf\\xb5?\\x0f\\x02\\xa0o~\\xcdo\\xf5\\xc1@~\\x0c\\xa4z\\x15@\\xcc\\xaeU\\xce\\xd61\\xfbG\\x010\\xb3\\xca\\x07\\xb9\\xf5\\xd6[\\'\\'\\x00\\xbc\\xf7?\\xbfE\\xce\\xc6f\\xcc1\\x80\\x81f2\\xb0\\xf7\\xde{\\x87\\x13O<1\\xcc\\x981#\\xdcq\\xc7\\x1da\\xf1\\xe2\\xc5\\xb5\\x0f\\xc9)\\x9f\\x00\\x01`\\xfe7s\\xfe{.<\\xa5\\xc2@\\x8a\\xf7\\x02\\x88\\xd9\\xb5\\xca\\xd9:f\\xff\\xf8\\x16\\x80\\xf9U=\\xc8\\x05\\x0b\\x16\\x84u\\xd6Y\\')\\x01\\xb0\\xd6Zk\\xb9\\xf3\\xbf\\xf7\\xfbz\\xfb\\x07\\x060\\x80\\x81~3\\xb0\\xc7\\x1e{\\x84\\x13N8!L\\x9f>=,Z\\xb4(<\\xfd\\xf4\\xd3)g\\xe5$\\xcf\\x8d\\x00\\x10\\xd8R\\tl\\xce\\x03\\xcb\\xcdd ~\"@\\xccF)\\xbd\\x15 f\\xd7\\x98a\\xab\\x9a\\xafc\\xf6\\x8fW\\x00\\xdcU\\xd5\\x03<\\xfb\\xec\\xb3\\x93\\x02\"\\xc2\\x1d?\\xfb\\xb2\\x99\\x13\\xc7sY\\x881\\x80\\x01\\x0c\\xa4\\xc3\\xc0\\xae\\xbb\\xee\\x1a\\xe2\\xe5\\x83\\xe7\\x9f\\x7f~W\\xf3\\xf0\\xe4\\x93O&\\x19\\x88s;)\\x02 \\x9d9j\\xbd5\\x96\\x18h.\\x031\\x1b\\xa5$\\x00\\xe2\\xb9\\xc4\\x0c[\\xd5|\\x1d\\xb3\\x7f\\xbc\\x02\\xe0\\xc1\\xaa\\x1e\\xe0\\x07>\\xf0\\x81\\xe4\\x80\\xd8l\\xb3\\xcd\\x08\\x00\\xff\\xf2\\x87\\x01\\x0c`\\x00\\x03a\\xc7\\x1dw\\x0cG\\x1f}t\\xf8\\xf7\\x7f\\xff\\xf7p\\xd3M7\\x85\\xc7\\x1e{,\\xb7\\\\\\x9c\\xcd\\xf9\\x12\\x00\\xcd\\r\\x0c\\x02\\x98zb \\x1d\\x06b6JM\\x00\\xc4\\x0c[\\xd5|\\x1d\\xb3\\x7f\\xbc\\x02\\xe0\\x99\\xaa\\x1e\\xe0;\\xde\\xf1\\x8e\\xa4\\x80Xo\\xbd\\xf54\\xfd\\x9a~\\x0c`\\x00\\x03\\x192\\xb0\\xfd\\xf6\\xdb\\x87q\\xe3\\xc6\\x85\\xaf}\\xedk\\xe1\\xfa\\xeb\\xaf\\x0f\\x8f>\\xfah6\\xe1\\xd7\\x89\\x86@\\x00\\xa4\\x13V\\x04Oc\\x89\\x81\\xe63\\x103RJ\\x12 f\\xd8\\xaa\\xe6\\xeb\\xe2\\xb8\\x9e\\x8e\\x02`Y\\x15\\x0fp\\xde\\xbcy\\xc9\\xbd\\'\\xe4\\xef\\xff\\xfe\\xef5\\xfe\\x196\\xfe6\\x8a\\xe6o\\x14j\\xaa\\xa6Uf`\\x9bm\\xb6\\t\\x1f\\xf9\\xc8G\\xc2\\x97\\xbf\\xfc\\xe5p\\xed\\xb5\\xd7\\x86\\x87\\x1ezH\\x06\\xce\\xbc\\x02\\x04\\x805\\xab\\xcak\\x96c\\xc3g\\xa7\\x19\\x88\\x19)%\\x01\\x10\\xefk\\x10\\xb3l\\x153v\\xcc\\xfe\\xf1-\\x00\\x95<\\xb8s\\xce9\\')\\x10\\xe2G\\xffm\\xbe\\xf9\\xe6\\x04\\x00\\x01\\x80\\x01\\x0c` !\\x06F\\x8c\\x18\\x11\\x0e=\\xf4\\xd00y\\xf2\\xe40w\\xee\\xdc\\xf0\\xc0\\x03\\x0f\\x84\\x15+Vd\\x1ew\\x9d\\xfe\\xaa\\x15 \\x00\\x04\\xacN\\x07,\\xaf\\x8f\\xc1*3\\x103R\\xccJ)I\\x80\\x98e\\xab\\x9a\\xb3++\\x00\\x0e?\\xfc\\xf0\\xa4 \\xf8\\xbb\\xbf\\xfb;M\\x7fBM\\x7f\\x95\\x17Q\\xc7f\\x93\\xc7@k\\x18\\xd8r\\xcb-\\xc3A\\x07\\x1d\\x14N;\\xed\\xb40g\\xce\\x9c\\xf0\\xab_\\xfd*,_\\xbe|\\xd5\\xac\\xe7\\xffU`\\xb5\\n\\x10\\x00\\xad\\x99\\x93\\xd6:u\\xc5@:\\x0c\\xc4\\xac\\x94\\x92\\x00\\x88Y\\x96\\x00(y\\xa5\\xc1\\xf0\\xe1\\xc3\\x93\\x82`\\xd3M7%\\x00\\x08\\x00\\x0c`\\x00\\x035a`\\xd8\\xb0a!\\xde\\xc4g\\xe2\\xc4\\x89a\\xf6\\xec\\xd9\\xe1\\xfe\\xfb\\xef\\x0fK\\x97.]-\\xd8\\xf9\\x81\\n\\xf4\\xa7\\x02\\x04@:!E\\xe04\\x96\\x18h\\r\\x031+\\xa5$\\x00b\\x96%\\x00J\\x08\\x80\\x85\\x0b\\x17\\x86W\\xbf\\xfa\\xd5\\xc9@\\xb0\\xee\\xba\\xebj\\xfak\\xd2\\xf4[\\xd4[\\xb3\\xa8\\xab\\xab\\xbaV\\x99\\x81!C\\x86\\x84\\xd1\\xa3G\\x87\\t\\x13&\\x84\\xcb.\\xbb,\\xdc{\\xef\\xbda\\xc9\\x92%\\xfd\\xc9u\\x1e\\xa3\\x02\\xfd\\xaa\\x00\\x01`\\r\\xac\\xf2\\x1a\\xe8\\xd8\\xf0Y\\x15\\x06bfJE\\x02\\xc4,\\x1b3m\\x15%@%\\xdf\\x020c\\xc6\\x8cd\\x06?B\\xbc\\xd1F\\x1b\\x11\\x00\\x04\\x00\\x060\\x80\\x81\\x8a0\\xb0\\xef\\xbe\\xfb\\x86\\x7f\\xfb\\xb7\\x7f\\x0b\\x97\\\\rI\\xd7\\xdd\\xd9\\x9f{\\xee\\xb9~\\x858\\x0fR\\x81F+@\\x00\\x08XU\\tX\\x8e\\x03\\x8bUf f\\xa6T\\x04@<\\x8f\\x98i\\t\\x80~^\\x05\\xf0\\xf9\\xcf\\x7f>\\xa9\\xc1\\x8f\\x1f\\x05Q\\xe5\\xc9\\xe6\\xd8l\\x06\\x18\\xc0@\\xaa\\x0c\\x8c\\x1a5*|\\xfa\\xd3\\x9f\\x0e\\x17^xa\\xb8\\xfd\\xf6\\xdb\\xc3\\xb3\\xcf>\\xdbh\\x86\\xf3{*\\xd0p\\x05\\x08\\x00kl\\xaak\\xac\\xf3\\xc2v3\\x19H\\xedm\\x001\\xd3\\x12\\x00\\xfd\\x14\\x00\\x87\\x1crH2\\x02`\\x9du\\xd6\\x11\\xfe+\\xf2\\xaf~\\xcd\\\\\\xa0<\\x97\\r\\x0f\\x03\\xd5c`\\xb7\\xddv\\x0b\\xc7\\x1f\\x7f|\\xf8\\xd6\\xb7\\xbe\\x15n\\xbb\\xed\\xb6\\xf0\\xd4SO5\\x1c\\xd8\\xfc\\xa2\\n4\\xb3\\x02\\x04@\\xf5\\xd6\\x0bk\\xb81\\xc1@5\\x19\\x88\\xd9)\\x95\\xab\\x00b\\xa6%\\x00\\xfa)\\x00\\xb6\\xdez\\xebd\\x06~\\x83\\r6 \\x00\\x08\\x00\\x0c`\\x00\\x03Mf`\\xe7\\x9dw\\x0e\\xc7\\x1e{l\\xf8\\xe67\\xbf\\x19\\x8a\\xcf\\xb4\\r\\x8f?\\xfex3\\xf3\\x9a\\xe7R\\x81\\xa6V\\x80\\x00\\xa8f\\xd0\\x10\\x00\\x8d\\x0b\\x06\\xaa\\xc7@\\xccN\\xa9\\x08\\x80\\x98i\\t\\x80~\\n\\x80\\r7\\xdc0\\x99\\x81\\xdfd\\x93M4\\xfeMn\\xfc-\\xd6\\xd5[\\xac\\x8d\\x891i%\\x03;\\xec\\xb0C\\x18?~|\\x982eJ\\xb8\\xe1\\x86\\x1b\\xc2\\x1f\\xfe\\xf0\\x87\\xa6\\x863O\\xa6\\x02\\xad\\xae\\x00\\x01`\\x8dl\\xe5\\x1a\\xe9\\xb9\\xf1\\x95\\x12\\x031;\\xa5\"\\x00b\\xa6%\\x00\\xfa!\\x00\\xae\\xbe\\xfa\\xead\\x06}\\xd0\\xa0A\\xe1\\xdd\\xef~7\\x01@\\x00`\\x00\\x03\\x18\\xe8\\'\\x03\\xdbm\\xb7]8\\xf2\\xc8#\\xc39\\xe7\\x9c\\x13\\xe6\\xcd\\x9b\\x17\\x1e~\\xf8\\xe1Vg3\\xcf\\xaf\\x02-\\xaf\\x00\\x01 \\xa0\\xa5\\x14\\xd0\\x9c\\x0b\\x9e[\\xc9@\\xccN1C\\xa5\"\\x01b\\xb6\\xad\\x9a\\x04\\xa8\\xdc\\xa7\\x00\\x9c{\\xee\\xb9\\xc9\\x0c\\xf8k^\\xf3\\x1aM\\x7f?\\x9b\\xfeV.$\\x9e\\xdbF\\x85\\x81j20b\\xc4\\x880v\\xec\\xd8p\\xd6Yg\\x85\\xb8A\\xfe\\xf6\\xb7\\xbf\\r+V\\xachy\\x18\\xf3\\x02*\\xd0\\xee\\n\\x10\\x00\\xd5\\\\\\x83\\xec\\r\\xc6\\x05\\x03\\xd5d f\\xa8T\\x04@\\xcc\\xb6\\x04\\xc0\\x1a\\xae\\x028\\xe1\\x84\\x13\\x92\\x19p\\x1f\\xffW\\xcdE\\xc5bo\\\\0\\xd0y\\x06.\\xbf\\xfcra\\xbf\\xdd)\\xd4\\xebu\\xac\\x02\\x04@\\xe7\\xd7\\x1c\\xeb\\xbe1\\xc0@}\\x18H\\xe9\\xe3\\x00c\\xb6%\\x00\\xd6 \\x00\\x0e:\\xe8\\xa0d\\x04\\x80\\xf7\\xff\\xd7g\\xa1\\xb1)\\x18+\\x0c\\xb4\\x97\\x81\\xf8/\\xfe\\xbeT \\x97\\n\\x10\\x00\\xed]_\\xac\\xe7\\xea\\x8d\\x81z3\\x90\\xd2}\\x00b\\xb6%\\x00\\xd6 \\x00\\xe2\\x9d\\x9dS\\xb9\\xe4\\xe3]\\xefz\\x97\\xb7\\x00x\\x0b\\x00\\x060\\x80\\x81\\x1e\\x18 \\x00r\\x89\\xbe\\xce3V\\x80\\x00\\xa8w\\x18\\x11&\\x8d\\x1f\\x06\\xda\\xcb@\\xccP\\xa9\\xe4\\xc1\\x98m\\t\\x805\\x08\\x80\\xcd6\\xdb,\\x89\\x01_w\\xddu5\\xfd=4\\xfd\\x16\\xd0\\xf6.\\xa0\\xea\\xad\\xdeUe\\x80\\x00\\x10\\x8cs\\xaa\\x00\\x01`-\\xae\\xeaZ\\xec\\xb8\\xb0YU\\x06b\\x96JA\\x02\\xc4lK\\x00\\xacA\\x00\\xac\\xbf\\xfe\\xfaI\\x0c\\xf6\\xeb^\\xf7:\\x02\\x80\\x00\\xc0\\x00\\x060\\xd0\\x0b\\x03\\x04@N\\xf1\\xd7\\xb9\\x12\\x00BVUC\\x96\\xe3\\xc2fU\\x19\\x88Y*\\x05\\x01\\x10\\xb3-\\x01\\xd0\\x87\\x00\\x88\\x1f\\xf9\\x94\\xc2@\\xc7sx\\xe3\\x1b\\xdf\\xa8\\xf1\\xef\\xa5\\xf1\\xaf\\xeaB\\xe3\\xb8l\\x82\\x18h\\x1f\\x03\\x04\\x80P\\x9cS\\x05\\x08\\x80\\xf6\\xad-\\xd6q\\xb5\\xc6@\\x1a\\x0c\\xc4,\\x95J.\\x8c\\x19\\xb7J\\x12\\xa0R\\x1f\\x038c\\xc6\\x8cd\\x06\\xda\\r\\x00\\xd3X|l\"\\xc6\\x11\\x03\\xada\\x80\\x00\\xc8)\\xfe:W\\x02\\xa05\\xeb\\x88\\xf5Y]1\\x90.\\x03)\\xdd\\x080f\\\\\\x02\\xa0\\x97\\xab\\x00\\xce>\\xfb\\xecd\\x04\\xc0;\\xdf\\xf9NW\\x00\\xb8\\x02\\x00\\x03\\x18\\xc0@/\\x0c\\x10\\x00BqN\\x15 \\x00\\xd2\\r)\\x02\\xa8\\xb1\\xc5@k\\x18\\x88Y*\\x95+\\x00b\\xc6%\\x00z\\x11\\x00\\x13&LHb\\xa0\\x07\\r\\x1a\\xa4\\xe9\\xef\\xa5\\xe9\\xb7H\\xb6f\\x91TWu\\xad\\x1b\\x03\\x04@N\\xf1\\xd7\\xb9\\x12\\x00\\xd6\\xe8\\xba\\xad\\xd1\\x8e\\x17\\xb3U` f\\xaa\\x14$@\\xcc\\xb8\\x04@/\\x02\\xe0\\xb8\\xe3\\x8eKb\\x90}\\x02\\x80E\\xb3\\n\\x8b\\xa6c\\xc0a\\x95\\x19 \\x00\\x84\\xe2\\x9c*@\\x00X\\x8f\\xab\\xbc\\x1e;6|V\\x95\\x81T>\\t f\\\\\\x02\\xa0\\x17\\x01p\\xd8a\\x87%!\\x00\\xd6[o=W\\x00\\xb8\\x02\\x00\\x03\\x18\\xc0@\\x1f\\x0c\\x10\\x009\\xc5_\\xe7J\\x00\\x08XU\\rX\\x8e\\x0b\\x9bUf f\\xaa\\x14\\xae\\x00\\x88\\x19\\x97\\x00\\xe8E\\x00\\x1cp\\xc0\\x01I\\x0c\\xf2\\x1b\\xde\\xf0\\x06\\x8d\\x7f\\x1f\\x8d\\x7f\\x95\\x17\\x1a\\xc7f#\\xc4@{\\x18 \\x00\\x84\\xe2\\x9c*@\\x00\\xb4g]\\xb1~\\xab3\\x06\\xd2b f\\xaa\\x14\\x04@\\xcc\\xb8\\x04@/\\x02`\\xe7\\x9dwNb\\x90}\\x04`Z\\x8b\\x8f\\xcd\\xc4xb\\xa0\\xf9\\x0c\\x10\\x009\\xc5_\\xe7J\\x004\\x7f\\r\\xb1.\\xab)\\x06\\xd2g \\x95\\x8f\\x02\\x8c\\x19\\x97\\x00\\xe8E\\x00l\\xb1\\xc5\\x16I\\x08\\x80\\xb7\\xbc\\xe5-\\xae\\x00p\\x05\\x00\\x060\\x80\\x81>\\x18 \\x00\\x84\\xe2\\x9c*@\\x00\\xa4\\x1fT\\x84Qc\\x8c\\x81\\xe63\\x103U\\nW\\x00\\xc4\\x8cK\\x00\\xf4\"\\x00\\xde\\xf1\\x8ew$1\\xc8o{\\xdb\\xdb4\\xfe}4\\xfe\\x16\\xc8\\xe6/\\x90j\\xaa\\xa6uc\\x80\\x00\\xc8)\\xfe:\\xd7Y\\xb3f\\xe9\\x0b\\xf4\\x05\\x18\\xc0\\x00\\x06J2\\x103U\\n\\x02 f\\\\\\x02\\xa0\\x17\\x01\\xb0\\xc9&\\x9b$1\\xc8o\\x7f\\xfb\\xdbM\\xf0\\x92\\x13\\xbcn\\xe1\\xc5\\xf1\\n\\xdc\\x18\\x18\\x18\\x03\\x04\\x80P\\x9cS\\x05.\\xb8\\xe0\\x02}\\x81\\xbe\\x00\\x03\\x18\\xc0@I\\x06b\\xa6JA\\x00\\xc4\\x8cK\\x00\\xf4\"\\x00R\\xb9\\xccc\\xd3M75\\xc1KNpaj`aJ\\xfd\\xd4\\xafn\\x0c\\x10\\x009\\xc5_\\xe7J\\x00X\\xa3\\xeb\\xb6F;^\\xccV\\x81\\x81\\x98\\xa9R\\x10\\x001\\xe3\\x12\\x00\\xbd\\x08\\x80\\x8d6\\xda(\\x89A\\xdel\\xb3\\xcd\\x08\\x00\\x02\\x00\\x03\\x18\\xc0@\\x1f\\x0c\\x10\\x00BqN\\x15 \\x00\\x84\\xa9*\\x84)\\xc7\\x80\\xc3\\xba1\\x103U\\n\\x02 f\\\\\\x02\\xa0\\x17\\x01\\xf0\\xfa\\xd7\\xbf>\\x89A~\\xe7;\\xdf\\xa9\\xf1\\xef\\xa3\\xf1\\xaf\\xdb\\xe2\\xe3xm\\x98\\x18h>\\x03\\x04@N\\xf1\\xd7\\xb9\\x12\\x00\\xcd_C\\xac\\xcbj\\x8a\\x81\\xf4\\x19\\x88\\x99*\\x05\\x01\\x10?\\xce\\x90\\x00\\xe8E\\x00\\xac\\xb7\\xdezI\\x0c\\xf2\\xbb\\xde\\xf5.\\x02\\x80\\x00\\xc0\\x00\\x060\\xd0\\x07\\x03\\x04\\x80P\\x9cS\\x05\\x08\\x80\\xf4\\x83\\x8a0j\\x8c1\\xd0|\\x06b\\xa6JA\\x00\\xc4\\x8cK\\x00\\xf4\"\\x00^\\xf5\\xaaW%1\\xc8\\xef~\\xf7\\xbb5\\xfe}4\\xfe\\x16\\xc8\\xe6/\\x90j\\xaa\\xa6uc\\x80\\x00\\xc8)\\xfev\\xf6\\\\\\x17/^\\x1c\\xe2\\xc7\\xf0]r\\xc9%\\xe1\\xbf\\xff\\xfb\\xbf;r0\\x04\\x805\\xbank\\xb4\\xe3\\xc5l\\x15\\x18\\x88\\x99*\\x05\\x01\\x103.\\x01\\xd0\\x8b\\x00X{\\xed\\xb5\\x93\\x18\\xe4\\xcd7\\xdf\\x9c\\x00 \\x000\\x80\\x01\\x0c\\xf4\\xc1\\x00\\x01\\xd0\\x91\\x1c\\x9a\\xfc\\x8b>\\xff\\xfc\\xf3\\xe1\\xde{\\xef\\r\\x97]vY8\\xf9\\xe4\\x93\\xc3\\x81\\x07\\x1e\\x18\\x06\\x0f\\x1e\\xfc\\xd7\\xb9\\xb8h\\xd1\\xa2\\x8e\\xd4\\x80\\x00\\x10\\xa6\\xaa\\x10\\xa6\\x1c\\x03\\x0e\\xeb\\xc6@\\xccT)\\x08\\x80\\x98q\\t\\x00\\x02\\xe0\\xaf\\xcdH\\xdd&\\xa2\\xe3\\xb5y`\\x00\\x03\\xcd`\\x80\\x00\\xe8H\\x0eM\\xeaE\\x97.]\\x1a\\xee\\xbf\\xff\\xfe0{\\xf6\\xec0i\\xd2\\xa4\\xf0\\xc1\\x0f~0\\x0c\\x1d:\\xb4\\xcf\\xfd\\x95\\x00\\xb0~5c\\xfd\\xf2\\x1c8\\xc2@{\\x18 \\x00nm\\x898xE\\x95l\\x84+\\x00\\xda3\\x99,Z\\xea\\x8c\\x01\\x0ct\\x9a\\x01\\x02 \\xa9,\\xde\\xf2\\x93Y\\xbe|y\\xf8\\xd5\\xaf~\\x15\\xe6\\xcc\\x99\\x13\\xbe\\xf4\\xa5/\\x85\\x83\\x0f>8l\\xb1\\xc5\\x16}\\x86\\xfd\\x9e\\x18\\'\\x00\\xac}=q\\xe1g\\xb8\\xc0@5\\x19 \\x00\\x08\\x80\\xda\\\\\\x02\\xe2-\\x00\\xd5\\\\D,\\xee\\xc6\\x05\\x03\\xd5a\\x80\\x00hyf\\xae\\xed\\x0b\\xbc\\xf0\\xc2\\x0b\\xe1\\x81\\x07\\x1e\\x08s\\xe7\\xce\\rg\\x9eyf8\\xec\\xb0\\xc3\\xc2\\xf0\\xe1\\xc3K\\x87\\xfd\\x9e\\xe6;\\x01P\\x9d5\\xa0\\xa7\\xf1\\xf13\\xe3\\x83\\x01\\x0c\\xbc\\x9c\\x01\\x02\\x80\\x00 \\x00\\xfax?\\xed\\xcb\\'\\x8b\\xff\\xb6xb\\x00\\x03Ug\\x80\\x00\\xa8m>o\\xfa\\x81?\\xf4\\xd0C\\xe1\\xba\\xeb\\xae\\x0b_\\xf9\\xcaW\\xc2\\xe1\\x87\\x1f\\x1e\\xb6\\xdez\\xeb\\xa6\\x84\\xfd\\x9e\\xe6\\x00\\x01`m\\xec\\x89\\x0b?\\xc3\\x05\\x06\\xaa\\xc9\\x00\\x01@\\x00\\x10\\x00\\x04@\\xcb\\x9aB\\x0b\\x7f5\\x17~\\xe3\\x92\\xee\\xb8\\x10\\x00M\\xcf\\xd1\\xb5x\\xc2G\\x1f}4,X\\xb0 |\\xfd\\xeb_\\x0f\\xe3\\xc6\\x8d\\x0b\\xdbo\\xbf}[\\xd7u\\x02 \\xdd5\\xc5~al1\\x90\\x1e\\x03\\x04\\x00\\x01@\\x00\\x10\\x00mm\\x14m$\\xe9m$\\xc6\\xb4:cJ\\x00\\xd4\"\\xaf\\x0f\\xe8 \\x1f{\\xec\\xb1p\\xf3\\xcd7\\x87o|\\xe3\\x1b\\xe1\\xe8\\xa3\\x8f\\x0e\\xef{\\xdf\\xfb:\\xbe\\x86\\x13\\x00\\xd5Y\\x03\\xac\\xc7\\xc6\\x02\\x03\\x18X\\x13\\x03\\x04\\x00\\x01@\\x00\\x10\\x00\\x1do\\x1e\\xd7\\xb4P\\xf9{\\x9b\\x19\\x06\\xfa\\xc7\\x00\\x010\\xa0l]\\xb9_~\\xe2\\x89\\'\\xc2\\x0f\\x7f\\xf8\\xc30u\\xea\\xd4p\\xdcq\\xc7\\x85]v\\xd9\\xa5\\x92\\xeb5\\x01\\xd0\\xbf\\xf9i\\x1dS\\'\\x0c`\\xa0\\n\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00T\\xb2\\xa1\\xac\\xc2\\x02\\xe9\\x18l\\xd4uc\\x80\\x00\\xa8\\\\\\x86\\xef\\xf7\\x01=\\xf5\\xd4S\\xe1\\xc7?\\xfeq\\x98>}z8\\xe1\\x84\\x13\\xc2\\x1e{\\xecQ\\x9b\\xb5\\x99\\x00\\xb0V\\xd6m\\xadt\\xbc\\x98\\xcd\\x99\\x01\\x02\\x80\\x00 \\x00\\x08\\x80\\xda4\\x999/\\xd6\\xce]\\xb3\\xd2\\x1f\\x06\\x08\\x80~\\xe7\\xed\\x8e>\\xf0\\xd9g\\x9f\\rw\\xdeyg\\x981cF8\\xf1\\xc4\\x13\\xc3\\xde{\\xef]\\xebu\\x98\\x00\\xb0>\\xf5g}\\xf2\\x18\\x9c`\\xa0\\x1a\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00\\xd4\\xba\\xf1\\xb4\\x99Tc31\\x0e\\xd5\\x18\\x07\\x02\\xa0\\xa3\\xb9\\xbe\\xc7\\x17\\xff\\xcb_\\xfe\\x12\\xee\\xb9\\xe7\\x9ep\\xe9\\xa5\\x97\\x86\\xcf}\\xeesa\\xbf\\xfd\\xf6\\x0b\\x83\\x07\\x0fNj\\xdd%\\x00\\xaa1\\xff\\xad\\xc3\\xc6\\x01\\x03\\x18\\xe8\\x0f\\x03\\x04\\x00\\x01@\\x00\\x10\\x00I5\\xa2\\xfdY\\xf8<\\xc6\\x06\\x99*\\x03\\x04@\\x8f\\x19\\xbcm?\\\\\\xbati\\xb8\\xef\\xbe\\xfb\\xc2\\xacY\\xb3\\xc2)\\xa7\\x9c\\x12\\xde\\xff\\xfe\\xf7\\x87!C\\x86$\\xbf\\xc6\\x12\\x00\\xd6\\xd4T\\xd7T\\xe7\\x85\\xed\\x14\\x19 \\x00\\x08\\x00\\x02\\x80\\x00H\\xbe9Mq\\xf1vN\\x9a\\x92\\x9e\\x18 \\x00\\xda\\x96\\xf5\\xc3\\xb2e\\xcb\\xc2/~\\xf1\\x8bp\\xc5\\x15W\\x84/|\\xe1\\x0ba\\xcc\\x981a\\xd8\\xb0aY\\xae\\xa7\\x04\\x80\\xf5\\xa8\\xa7\\xf5\\xc8\\xcfp\\x81\\x81j2@\\x00\\x10\\x00\\x04\\x00\\x01\\x90e\\xc3jS\\xaa\\xe6\\xa6d\\\\\\x066.\\x04@k\\x04\\xc0\\x0b/\\xbc\\x10~\\xfd\\xeb_\\x87+\\xaf\\xbc2\\x9c~\\xfa\\xe9\\xe1\\x90C\\x0e\\t[n\\xb9\\xa5\\xb5\\xf3\\xc5\\xfd\\x93\\x00\\x18\\xd8\\xbc\\xb5\\xee\\xa9\\x1f\\x060\\xd0N\\x06\\x08\\x00\\x02\\x80\\x00 \\x004\\xb1\\x18\\xc0@\"\\x0c\\x10\\x00\\x03\\x17\\x00+V\\xac\\x08\\x0f>\\xf8`\\x88\\xb5<\\xeb\\xac\\xb3\\xc2\\xd8\\xb1c\\xc3\\x88\\x11#\\xcc\\x91>\\xe6\\x08\\x01 \\xbc\\xb43\\xbcx-\\xbca``\\x0c\\x10\\x00\\x04\\x00\\x01\\xd0GSc\\x81\\x19\\xd8\\x02\\xa3~\\xea\\x87\\x81\\xf62@\\x00\\x94\\x17\\x00\\x0f?\\xfcp\\x987o^8\\xe7\\x9cs\\xc2\\x91G\\x1e\\x19\\xb6\\xddv[a\\xbf\\xe4\\xbeH\\x00\\xb4w\\x9e[W\\xd5\\x1b\\x03\\x18\\x18\\x08\\x03\\x04\\x00\\x01@\\x00\\x94lt\\x062\\xe1\\xfc\\xae\\x05\\x1b\\x03\\x18h%\\x03\\x04@\\xdf\\x02\\xe0\\x0f\\x7f\\xf8C\\xb8\\xe1\\x86\\x1b\\xc2\\x94)S\\xc2\\xf8\\xf1\\xe3\\xc3{\\xdf\\xfb^a\\xbf\\t{ \\x01`]k\\xe5\\xba\\xe6\\xb9\\xf1\\x85\\x81\\xe62@\\x00\\x10\\x00\\x04@\\x13\\x9a\\x1f\\x0bSs\\x17&\\xf5TO\\x0c4\\xc6\\x00\\x01\\xf0\\x92\\x00x\\xfc\\xf1\\xc7\\xc3-\\xb7\\xdc\\x12\\xbe\\xf9\\xcdo\\x86c\\x8e9&\\xec\\xb4\\xd3N\\xc2~\\x8b\\xf6;\\x02\\xa0\\xb1\\xf9j\\x9dS7\\x0c`\\xa0\\x13\\x0c\\x10\\x00\\x04\\x00\\x01\\xd0\\xa2\\x86\\xa8\\x13\\x13\\xdak\\xdaH0\\x907\\x03\\xb9\\n\\x80\\xff\\xfd\\xdf\\xff\\r\\xb7\\xddv[\\xf8\\xd6\\xb7\\xbe\\x15>\\xf1\\x89O\\x84\\x91#G\\n\\xfbm\\xdc\\xdb\\x08\\x80\\xbc\\xd7\\x1d\\xfb\\x8e\\xf1\\xc7@\\xbd\\x18 \\x00\\x08\\x00\\x02\\xa0\\x8dM\\x92\\x05\\xb2^\\x0b\\xa4\\xf12^uc \\x07\\x01\\xf0\\xcc3\\xcf\\x84\\xdbo\\xbf=\\\\x\\xe1\\x85\\xe1S\\x9f\\xfaT\\x185j\\x94\\xb0\\xdf\\xe1}\\x8c\\x00\\xb0V\\xd6m\\xadt\\xbc\\x98\\xcd\\x99\\x01\\x02\\x80\\x00 \\x00:\\xdc8\\xe5\\xbc\\x009w\\x1b0\\x06\\x9a\\xcb@j\\x02`\\xf1\\xe2\\xc5\\xe1\\xee\\xbb\\xef\\x0e\\x97\\\\rI8\\xe9\\xa4\\x93\\xc2\\xbe\\xfb\\xee+\\xecWp\\xcf\"\\x00\\x9a;\\x8f\\xad\\x8b\\xea\\x89\\x01\\x0c\\xb4\\x92\\x01\\x02\\x80\\x00 \\x00*\\xd8L\\xb5r\\xd2{n\\x9b\\n\\x06\\xd2e\\xa0\\xce\\x02\\xe0\\xf9\\xe7\\x9f\\x0f\\xf7\\xde{o\\x989sf\\x980aB\\x18=zt\\x182d\\x88\\xc0_\\x83=\\x8a\\x00HwM\\xb1_\\x18[\\x0c\\xa4\\xc7\\x00\\x01@\\x00\\x10\\x005h\\xae,\\xbe\\xe9-\\xbe\\xc6\\xd4\\x98\\xb6\\x82\\x81\\xba\\x08\\x80\\xa5K\\x97\\x86\\xfb\\xef\\xbf?\\xcc\\x9e=;L\\x9c81|\\xe0\\x03\\x1f\\x08\\xc3\\x86\\r\\x13\\xf6k\\xba\\x1f\\x11\\x00\\xd6\\xb3V\\xacg\\x9e\\x13W\\x18h\\r\\x03\\x04\\x00\\x01@\\x00\\xd4\\xb4\\xe1\\xb2(\\xb6fQTWu\\xad3\\x03U\\x14\\x00\\xcb\\x97/\\x0f\\xbf\\xfa\\xd5\\xaf\\xc2\\x9c9s\\xc2i\\xa7\\x9d\\x16\\x0e:\\xe8\\xa0\\xb0\\xc5\\x16[\\x08\\xfb\\t\\xed=\\x04\\x80u\\xb3\\xce\\xeb\\xa6c\\xc7on\\x0c\\x10\\x00\\x04\\x00\\x01\\x90P\\x13\\x96\\xdb\\x02\\xe6|m\\xda\\x18X\\x99\\x81N\\x0b\\x80\\x15+V\\x84\\x07\\x1ex \\\\u\\xd5Ua\\xf2\\xe4\\xc9\\xe1\\xd0C\\x0f\\r\\xc3\\x87\\x0f\\x17\\xf6\\x13\\xdfg\\x08\\x80\\x95\\xe7\\xa1uI=0\\x80\\x81*3@\\x00\\x10\\x00\\x04@\\xe2\\x8dY\\x95\\x17 \\xc7f\\x83\\xc4@s\\x19\\xe8\\x94\\x00\\xf8\\xf3\\x9f\\xff\\x1c>\\xf2\\x91\\x8f\\x84\\xad\\xb7\\xdeZ\\xd8\\xcfpO!\\x00\\x9a;\\x8f\\xad\\x8b\\xea\\x89\\x01\\x0c\\xb4\\x92\\x01\\x02\\x80\\x00 \\x002l\\xd6Z\\xb9\\xa8xn\\x9b\\x16\\x06:\\xc7@\\xa7\\x04@\\xfcW\\x7f\\xe3\\xde\\xb9q\\xeft\\xed\\t\\x80|\\xc7\\xbe\\xd3\\xecy}\\xeca\\xa0<\\x03\\x04\\x00\\x01@\\x00$&\\x00\\xf6\\xdcs\\xcf\\xf0\\xcdo~3\\xdcy\\xe7\\x9d\\xe1\\xd1G\\x1f\\r\\x7f\\xf8\\xc3\\x1f\\xc2=\\xf7\\xdc\\x13\\xa6O\\x9f\\x1e\\xf6\\xdf\\x7f\\x7fMzb\\xe3m\\xe3+\\xbf\\xf1\\xa5\\\\3\\x02\\x00\\x0f\\x9d\\xe0\\x9b\\x00\\xc0]\\'\\xb8\\xf3\\x9a\\xb8\\xc3@c\\x0c\\x10\\x00\\x04\\x00\\x01\\x90H \\xdcj\\xab\\xad\\xba>+{\\xd9\\xb2e\\xa1\\xaf\\xaf\\x1bn\\xb8\\xa1\\xeb\\x8e\\xdb\\x16\\xcd\\xc6\\x16MuS\\xb7*3@\\x00\\xe0\\xb3\\x13|\\x12\\x00\\xb8\\xeb\\x04w^\\x13w\\x18h\\x8c\\x01\\x02\\x80\\x00 \\x00\\x12\\x10\\x00\\xdbm\\xb7]\\xf8\\xe9O\\x7f\\xdaW\\xee_\\xed\\xef\\x88\\x80\\xc6\\x16M\\x9b\\x8d\\xbaU\\x99\\x01\\x02\\x00\\x9f\\x9d\\xe0\\x93\\x00\\xc0]\\'\\xb8\\xf3\\x9a\\xb8\\xc3@c\\x0c\\x10\\x00\\x04\\x00\\x01\\x90\\x80\\x00\\x18H\\xf3E\\x044\\xb6x\\xdat\\xd4\\xad\\x8a\\x0c\\x10\\x00\\xb8\\xec\\x04\\x97\\x03\\xd9\\x83V\\xb3\\xd3%~p\\xc1\\x05\\x17x[[\\x02=L\\'\\x98\\xf5\\x9a\\xd6\\xca\\x9c\\x19 \\x00\\x08\\x00\\x02\\xa0\\xe6\\x9b\\xe7)\\xa7\\x9cR\\xa2]\\xea\\xfd\\xa1D\\x80\\xcd0\\xe7\\xcd0\\x95s\\x9f6mZ\\xef\\x93\\xbc\\x85\\x7f\\xe3&\\x80y\\xaf\\x1f\\x04@\\xde\\xe3\\x9f\\xca\\xfa\\xe9<p\\x9c\\x0b\\x03\\x04\\x00\\x01@\\x00\\xd4\\\\\\x00<\\xf8\\xe0\\x83Mm\\xeb\\x89\\x00\\x1b`.\\x1b`\\x8a\\xe7\\xf9\\x85/|\\xa1\\xa9\\xebA\\x7f\\x9f\\x8c\\x00\\xc8{\\xdd \\x00\\xf2\\x1e\\xff\\x14\\xd7R\\xe7\\x84\\xe9\\x94\\x19 \\x00\\x08\\x00\\x02\\xa0\\xc6\\x02`\\xf4\\xe8\\xd1\\xfd\\xed\\xcfK?\\x8e\\x08\\xb0\\xf9\\xa5\\xbc\\xf9\\xa5zn\\x04\\x80y\\xdb\\t\\xb6\\t\\x00\\xdcu\\x82;\\xaf\\x89;\\x0c4\\xc6\\x00\\x01@\\x00\\x10\\x005\\x16\\x00\\xff\\xf6o\\xffV:\\xd8\\x97\\xfd\\x05\"\\xa0\\xb1\\xc5\\xd5\\xa6\\xa4n\\x9d`\\x80\\x00\\xc0]\\'\\xb8#\\x00p\\xd7\\t\\xee\\xbc&\\xee0\\xd0\\x18\\x03\\x04\\x00\\x01@\\x00\\xd4X\\x00L\\x9e<\\xb9l\\x9eo\\xf8\\xf1D@c\\x8b\\xac\\xcdI\\xdd\\xda\\xc9\\x00\\x01\\x80\\xb7v\\xf2\\xd6\\xfdZ\\x04\\x00\\xee\\xbaY\\xf0\\'\\x160P}\\x06\\x08\\x00\\x02\\x80\\x00\\xa8\\xb1\\x008\\xeb\\xac\\xb3\\x1a\\x0e\\xf4\\x8d\\xfe\"\\x11P\\xfd\\x85\\xdd\\xe6\\x9b\\xef\\x18\\x11\\x00\\xf9\\x8e}\\'\\xe7=\\x01\\x80\\xbbN\\xf2\\xe7\\xb5\\xf1\\x87\\x81r\\x0c\\x10\\x00\\x04\\x00\\x01@\\x004\\xe4\\x02\\x88\\x80r\\x8b\\xad\\xcdI\\xbd\\xda\\xc1\\x00\\x01\\x80\\xb3vp\\xb6\\xeak\\x10\\x00\\xb8[\\x95\\t\\xff\\x8f\\t\\x0cT\\x97\\x01\\x02\\x80\\x00 \\x00\\x08\\x80\\x86\\x04@\\xf7/\\x11\\x01\\xd5]\\xe0m\\xbe\\xf9\\x8d\\r\\x01\\x90\\xdf\\x98Wa\\x9e\\x13\\x00\\xb8\\xab\\x02\\x87\\x8e\\x01\\x87\\x18\\xe8\\x1f\\x03\\x04\\x00\\x01@\\x00\\x10\\x00\\xddY~@\\x7f\\x12\\x01\\xfd[tmN\\xea\\xd4J\\x06\\x08\\x00|\\xb5\\x92\\xaf\\xde\\x9e\\x9b\\x00\\xc0]ol\\xf8960P=\\x06\\x08\\x00\\x02\\x80\\x00 \\x00\\x06\\x14\\xfcW\\xfde\"\\xa0z\\x0b\\xbd\\xcd7\\x9f1!\\x00\\xf2\\x19\\xeb*\\xcdk\\x02\\x00wU\\xe2\\xd1\\xb1\\xe0\\x11\\x03}3@\\x00\\x10\\x00\\x04\\x00\\x01\\xb0j\\x86o\\xca\\xff\\x13\\x01}/\\xbe6\\'\\xf5i\\x05\\x03\\x04\\x00\\xaeZ\\xc1\\xd5\\x9a\\x9e\\x93\\x00\\xc0\\xdd\\x9a\\x18\\xf1\\xf7\\x18\\xc1@u\\x18 \\x00\\x08\\x00\\x02\\x80\\x00hJ\\xe0\\xef\\xedI\\x88\\x80\\xea,\\xf86\\xdf\\xf4\\xc7\\x82\\x00H\\x7f\\x8c\\xab8\\x8f\\t\\x00\\xdcU\\x91K\\xc7\\x84K\\x0c\\xf4\\xcc\\x00\\x01@\\x00\\x10\\x00\\x04@o\\xd9\\xbd\\xa9?\\'\\x02z^\\x84mN\\xea\\xd2L\\x06\\x08\\x00<5\\x93\\xa7\\xfe>\\x17\\x01\\x80\\xbb\\xfe\\xb2\\xe2qX\\xc1@\\xe7\\x19 \\x00\\x08\\x00\\x02\\x80\\x00hj\\xd0_\\xd3\\x93\\x11\\x01\\x9d_\\xf8m\\xbe\\xe9\\x8e\\x01\\x01\\x90\\xee\\xd8Vy\\xde\\x12\\x00\\xb8\\xab2\\x9f\\x8e\\r\\x9f\\x18X\\x99\\x01\\x02\\x80\\x00 \\x00\\x08\\x805e\\xf6\\x96\\xfc=\\x11\\xb0\\xf2blsR\\x8ff0@\\x00\\xe0\\xa8\\x19\\x1c\\x95}\\x0e\\x02\\x00we\\x99\\xf1x\\xcc`\\xa0s\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00\\xb4$\\xe0\\xf7\\xf7I\\x89\\x80\\xcem\\x006\\xdf\\xf4jO\\x00\\xa47\\xa6u\\x98\\xa7\\x04\\x00\\xee\\xea\\xc0\\xa9c\\xc4)\\x06\\xfe\\x8f\\x01\\x02\\x80\\x00 \\x00\\x08\\x80\\xfef\\xf5\\x96>\\x8e\\x08\\xb01\\xdb\\x98\\x07\\xce\\x00\\x010\\xf0\\x1a\\xe2\\xb0|\\r\\t\\x80\\xf25\\xc3\\x99\\x9aa\\x00\\x03\\x9db\\x80\\x00 \\x00\\x08\\x00\\x02\\xa0\\xa5\\xc1\\xbe\\xec\\x93\\x13\\x016\\xc4Nm\\x88)\\xbc.\\x01`\\xfet\\x82c\\x02\\x00w\\x9d\\xe0\\xcek\\xe2\\x0e\\x03\\x8d1@\\x00\\x10\\x00\\x04\\x00\\x01P6\\xa3\\xb7\\xe5\\xf1D@c\\x8b\\xba\\xcd0\\xef\\xba\\x11\\x00y\\x8f\\x7f\\xa7\\xe6?\\x01\\x80\\xbbN\\xb1\\xe7u\\xb1\\x87\\x81\\xf2\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00\\xb4%\\xd07\\xfa\"D@\\xf9\\x85\\xddf\\x98o\\xcd\\x08\\x80|\\xc7\\xbe\\x93\\xf3\\x9e\\x00\\xc0]\\'\\xf9\\xf3\\xda\\xf8\\xc3@9\\x06\\x08\\x00\\x02\\x80\\x00 \\x00\\x1a\\xcd\\xe6m\\xfd=\"\\xa0\\xdc\\xe2n3\\xcc\\xb3^\\x04@\\x9e\\xe3\\xde\\xe9\\xf9N\\x00\\xe0\\xae\\xd3\\x0cz}\\x0cb\\xa0\\xff\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00\\xb45\\xc8\\x0f\\xf4\\xc5\\x88\\x80\\xfe/\\xf06\\xc3\\xfcjE\\x00\\xe47\\xe6U\\x98\\xe7\\x04\\x00\\xee\\xaa\\xc0\\xa1c\\xc0!\\x06\\xfa\\xc7\\x00\\x01@\\x00\\x10\\x00\\x04\\xc0@3yG~\\x9f\\x08\\xe8\\xdf\"o3\\xcc\\xabN\\x04@^\\xe3]\\x95\\xf9M\\x00\\xe0\\xae*,:\\x0e,b`\\xcd\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00t$\\xc07\\xebE\\x89\\x805/\\xf46\\xc3|jD\\x00\\xe43\\xd6U\\x9a\\xd7\\x04\\x00\\xee\\xaa\\xc4\\xa3c\\xc1#\\x06\\xfaf\\x80\\x00 \\x00\\x08\\x80\\x1a\\x0b\\x80\\xd3O?\\xbdY9\\xba\\xf6\\xcfC\\x04\\xf4\\xbd\\xd8\\xdb\\x0c\\xf3\\xa8\\x0f\\x01\\x90\\xc78Wm>\\x13\\x00\\xb8\\xab\\x1a\\x93\\x8e\\x07\\x93\\x18\\xe8\\x9d\\x01\\x02\\x80\\x00 \\x00j,\\x00>\\xf3\\x99\\xcf\\xd4>\\xb87\\xfb\\x04\\x88\\x80\\xde\\x17|\\x9ba\\xfa\\xb5!\\x00\\xd2\\x1f\\xe3*\\xcec\\x02\\x00wU\\xe4\\xd21\\xe1\\x12\\x03=3@\\x00\\x10\\x00\\x04@\\x8d\\x05\\xc0^{\\xed\\xd5\\xec\\xfc\\x9c\\xcc\\xf3\\x11\\x01=/\\xfa6\\xc3\\xb4\\xebB\\x00\\xa4=\\xbeU\\x9d\\xbf\\x04\\x00\\xee\\xaa\\xca\\xa6\\xe3\\xc2&\\x06Vg\\x80\\x00 \\x00\\x08\\x80\\x1a\\x0b\\x80\\xb8\\xa8\\xdd\\x7f\\xff\\xfd\\xc9\\x84\\xf6V\\x9c\\x08\\x11\\xb0\\xfa\\xc2o3L\\xb7&\\x04@\\xbac[\\xe5yK\\x00\\xe0\\xae\\xca|:6|b`e\\x06\\x08\\x00\\x02\\x80\\x00\\xa8\\xb9\\x008\\xfe\\xf8\\xe3[\\x91\\x9b\\x93{N\"`\\xe5\\xc5\\xdff\\x98f=\\x08\\x804\\xc7\\xb5\\xea\\xf3\\x95\\x00\\xc0]\\xd5\\x19u|\\x18\\xc5\\xc0K\\x0c\\x10\\x00\\x04\\x00\\x01Ps\\x01\\x10\\x17\\xb4k\\xae\\xb9&\\xb9\\xc0\\xde\\xaa\\x13\"\\x02^\\xda\\x00l\\x86\\xe9\\xd5\\x82\\x00HoL\\xeb0O\\t\\x00\\xdc\\xd5\\x81S\\xc7\\x88S\\x0c\\xfc\\x1f\\x03\\x04\\x00\\x01@\\x00$ \\x00\\xb6\\xd8b\\x8bp\\xcb-\\xb7\\xb4*3\\'\\xf9\\xbcD\\x80F \\xc5F\\x80\\x00\\xc0u\\'\\xb8&\\x00p\\xd7\\t\\xee\\xbc&\\xee0\\xd0\\x18\\x03\\x04\\x00\\x01@\\x00$ \\x00\\xe2\\x028x\\xf0\\xe0p\\xce9\\xe7\\x84\\xc5\\x8b\\x17\\'\\x19\\xd8[uRD@c\\x9b\\x87M\\xb7\\x9au#\\x00\\xaa9.\\xa9\\xcf\\x17\\x02\\x00w\\xa93\\xee\\xfc0\\x9e\\x12\\x03\\x04\\x00\\x01@\\x00$\"\\x00\\xba\\x17\\xa6\\x1dw\\xdc1\\\\t\\xd1E\\xe1\\xb9\\xe7\\x9ekUfN\\xf2y\\x89\\x00\\x9b{\\xf7\\x1c\\xaa\\xf3\\x9f\\x04\\x00\\x8e;\\xc1/\\x01\\x80\\xbbNp\\xe75q\\x87\\x81\\xc6\\x18 \\x00\\x08\\x00\\x02 1\\x01\\xd0\\xbd\\x18F\\x110c\\xc6\\x0c\"\\xa0\\xa4\\xae \\x02\\x1a\\xdbL\\xba\\xb9\\xf3gg\\xebG\\x00t\\xb6\\xfe\\xb9\\xf2O\\x00\\xe0.W\\xf6\\x9d7\\xf6\\xeb\\xc8\\x00\\x01@\\x00\\x10\\x00\\x89\\n\\x80\\xee\\x05\\xa9[\\x04\\xfc\\xe5/\\x7f)\\x19\\x85\\xf3~8\\x11`S\\xef\\x9eCu\\xfa\\x93\\x00\\xc0m\\'x%\\x00p\\xd7\\t\\xee\\xbc&\\xee0\\xd0\\x18\\x03\\x04\\x00\\x01@\\x00$.\\x00\\xba\\x17\\xc7(\\x02.\\xbe\\xf8\\xe2@\\x04\\x94\\x13\\x1bD@c\\x9bK7w\\xfelo\\xfd\\x08\\x80\\xf6\\xd6\\x1b\\xdf\\xffWo\\x02\\x00w\\xe6\\x02\\x060P\\x1f\\x06\\x08\\x00\\x02\\x80\\x00\\xc8D\\x00t/\\xcc;\\xed\\xb4S\\xb8\\xe4\\x92K\\xc2\\xf3\\xcf?_.\\tg\\xfeh\"\\xa0>\\x1b[7\\xeb9\\xfeI\\x00\\xe0\\xb4\\x13\\xdc\\x13\\x00\\xb8\\xeb\\x04w^\\x13w\\x18h\\x8c\\x01\\x02\\x80\\x00 \\x002\\x13\\x00\\xdd\\x8b\\xe5\\xce;\\xef\\x1c\\xbe\\xfd\\xedo\\x13\\x01%\\xc5\\x06\\x11\\xd0\\xd8f\\xd3\\xcd\\x9d?[[?\\x02\\xa0\\xb5\\xf5\\xc5o\\xcf\\xf5%\\x00z\\xae\\x0b^\\xd4\\x05\\x03\\x18\\xa8\"\\x03\\x04\\x00\\x01@\\x00d*\\x00\\xba\\x17\\xa4]v\\xd9%\\\\z\\xe9\\xa5D\\x00\\x11\\x10\\xba\\x99\\xf0g}\\x1b\\x16\\x02\\xa0\\xbecW\\xe7yG\\x00\\xe0\\xae\\xce\\xfc:v\\xfc\\xe6\\xc6\\x00\\x01@\\x00\\x10\\x00\\x99\\x0b\\x80\\xeeE/\\x8a\\x80\\x993g\\x86%K\\x96\\x94\\x8c\\xc2y?\\xdc\\x15\\x01\\x1a\\x87\\xee9T\\x85?\\t\\x00<v\\x82C\\x02\\x00w\\x9d\\xe0\\xcek\\xe2\\x0e\\x03\\x8d1@\\x00\\x10\\x00\\x04\\x00\\x01\\xb0\\xd2\\xbf\\xfc\\xee\\xba\\xeb\\xaeD@\\x03N\\x83\\x08hl\\x13\\xb2y7\\xb7n\\x04@s\\xeb\\x89\\xcf\\xfe\\xd5\\x93\\x00\\xe8_\\x9d\\xf0\\xa4N\\x18\\xc0@\\x15\\x18 \\x00\\x08\\x00\\x02\\x80\\x00XI\\x00t/L#G\\x8e$\\x02\\x88\\x80\\x1e\\xd9\\xe8f\\xc4\\x9f\\xd5kd\\x08\\x80\\xea\\x8dI\\x0e\\xf3\\x84\\x00\\xc0]\\x0e\\x9c;G\\x9c\\xa7\\xc2\\x00\\x01@\\x00\\x10\\x00\\x04@\\x9f!/\\x8a\\x80\\xef|\\xe7;a\\xe9\\xd2\\xa5\\r\\xc4\\xe1|\\x7f\\xc5\\x15\\x01\\x1a\\x85N4\\n\\x04\\x00\\xee:\\xc1\\x1d\\x01\\x80\\xbbNp\\xe75q\\x87\\x81\\xc6\\x18 \\x00\\x08\\x00\\x02\\x80\\x00\\xe8S\\x00t/\\xaeQ\\x04\\xcc\\x9a5\\x8b\\x08(\\xe94\\x88\\x80\\xc66\\xa7n\\xee\\xfcY\\xae~\\x04@\\xb9z\\xe1\\xab9\\xf5\"\\x00\\x9aSG<\\xaa#\\x060\\xd0\\x0e\\x06\\x08\\x00\\x02\\x80\\x00 \\x00\\xfa%\\x00\\xba\\x17\\xa4\\xddv\\xdb-\\\\~\\xf9\\xe5D\\x00\\x11P\\x8a\\x9bn~\\xfc\\xd9\\xda\\xe6\\x86\\x00hm}\\xf1\\xdbs}\\t\\x80\\x9e\\xeb\\x82\\x17u\\xc1\\x00\\x06\\xaa\\xc8\\x00\\x01@\\x00\\x10\\x00\\x04@CA.\\x8a\\x80\\xd9\\xb3g\\x13\\x01D@C\\xfcTqCL\\xe1\\x98\\x08\\x00\\xcdf\\'8&\\x00p\\xd7\\t\\xee\\xbc&\\xee0\\xd0\\x18\\x03\\x04\\x00\\x01@\\x00\\x10\\x00\\x03\\np\\xbb\\xef\\xbe;\\x11PR\\x02\\xc4\\x87{k@c\\x9b\\x96\\xcd\\xbe\\xef\\xba\\x11\\x00}\\xd7\\x07?\\xad\\xa9\\x0f\\x01\\xd0\\x9a\\xba\\xe2U]1\\x80\\x81V0@\\x00\\x10\\x00\\x04\\x00\\x010 \\x01\\xd0\\xbd0\\xed\\xb1\\xc7\\x1e\\xe1\\xbb\\xdf\\xfd\\xae+\\x02J\\xca\\x00\"\\xc0\\xe6\\xde=\\x87\\x9a\\xf1\\'\\x01\\x80\\xa7fpT\\xf69\\x08\\x00\\xdc\\x95e\\xc6\\xe31\\x83\\x81\\xce1@\\x00\\x10\\x00\\x04\\x00\\x01\\xd0\\x14\\x01\\xd0\\xbd\\x90G\\x11p\\xc5\\x15W\\x84e\\xcb\\x96\\x95\\x8c\\xc2y?\\x9c\\x08\\xe8\\xdcF\\xd8\\xcdn\\n\\x7f\\x12\\x008\\xea\\x04\\xc7\\x04\\x00\\xee:\\xc1\\x9d\\xd7\\xc4\\x1d\\x06\\x1ac\\x80\\x00 \\x00\\x08\\x00\\x02\\xa0\\xa9\\x02\\xa0{1\\xdes\\xcf=\\xc3\\xf7\\xbe\\xf7=\"\\xa0\\xa4\\xd7 \\x02\\x1a\\xdb\\xcc\\xba\\xb9\\xcb\\xfdO\\x02\\x00?\\x9d\\x98\\x03\\x04\\x00\\xee:\\xc1\\x9d\\xd7\\xc4\\x1d\\x06\\x1ac\\x80\\x00 \\x00\\x08\\x00\\x02\\xa0%\\x02\\xa0{Q\\x1e5jT\\x983g\\x0e\\x11@\\x04\\xb4\\x94\\xb3n\\xder\\xff\\x93\\x00h\\xac\\x19\\xca\\x9d\\x9b\\x81\\x9e?\\x01\\x80\\xbb\\x812\\xe4\\xf71\\x84\\x81\\xf61@\\x00\\x10\\x00\\x04\\x00\\x01\\xd0\\x96`F\\x04\\x944\\x00/>\\xdc\\x15\\x01\\xed\\xdb\\x10Sh>\\x08\\x00\\xbct\\x82c\\x02\\x00w\\x9d\\xe0\\xcek\\xe2\\x0e\\x03\\x8d1@\\x00\\x10\\x00\\x04\\x00\\x01\\xd0\\x16\\x01\\xd0\\xbdHG\\x11\\xf0\\xfd\\xef\\x7f?,_\\xbe\\xbc\\xb1D\\x9c\\xe9o\\x11\\x01\\x8dmr\\xdd\\xdc\\xe5\\xf2\\'\\x01\\x80\\x93N\\xb0N\\x00\\xe0\\xae\\x13\\xdcyM\\xdca\\xa01\\x06\\x08\\x00\\x02\\x80\\x00 \\x00\\xda*\\x00\\xba\\x17\\xeb\\xbd\\xf6\\xda+\\\\y\\xe5\\x95D@I\\xa1A\\x044\\xb6\\xd9us\\x97\\xfa\\x9f\\x04\\x00>:\\xc18\\x01\\x80\\xbbNp\\xe75q\\x87\\x81\\xc6\\x18 \\x00\\x08\\x00\\x02\\x80\\x00\\xe8\\x88\\x00\\xe8^\\xb4\\xf7\\xde{\\xef\\xf0\\x83\\x1f\\xfc\\x80\\x08 \\x02:\\xcaa7\\x8fu\\xff\\x93\\x00h\\xac\\x19\\xaa\\xfb\\xb8w\\xfa\\xf8\\t\\x00\\xdcu\\x9aA\\xaf\\x8fA\\x0c\\xf4\\x9f\\x01\\x02\\x80\\x00 \\x00\\x08\\x80J\\x04\\xaf}\\xf6\\xd9\\'\\\\u\\xd5UD\\x00\\x11P\\t\\x1e\\xeb\\xdaH\\x10\\x00\\xfdo\\x80\\xea:\\xc6U<n\\x02\\x00wU\\xe4\\xd21\\xe1\\x12\\x03=3@\\x00\\x10\\x00\\x04\\x00\\x01P\\xa9\\xc0\\xb5\\xef\\xbe\\xfb\\x86\\xb9s\\xe7\\x86\\x17^x\\xa1d\\x14\\xce\\xfb\\xe1\\xde\\x1a\\xd0\\xf3&\\x97\\xdb\\xe6O\\x00\\xe0\\xa0\\x13\\xcc\\x13\\x00\\xb8\\xeb\\x04w^\\x13w\\x18h\\x8c\\x01\\x02\\x80\\x00 \\x00\\x08\\x80J\\t\\x80\\xee\\xc5\\x9c\\x08hLh\\x10\\x01\\x8dm\\x86\\xdd\\xdc\\xd5\\xfdO\\x02 \\xef\\xf1\\xef\\x14\\xbf\\x04\\x00\\xee:\\xc5\\x9e\\xd7\\xc5\\x1e\\x06\\xca3@\\x00\\x10\\x00\\x04\\x00\\x01PI\\x01\\xd0\\xbd\\xa0G\\x11p\\xf5\\xd5W\\xbb\"\\xa0\\xa4\\x0f \\x02\\xcao\\x88\\xdd\\xcc\\xd5\\xf9O\\x02 \\xcfq\\xef4\\xb3\\x04\\x00\\xee:\\xcd\\xa0\\xd7\\xc7 \\x06\\xfa\\xcf\\x00\\x01@\\x00\\x10\\x00\\x04@\\xa5\\x05@\\xf7\\x82\\xbe\\xdf~\\xfb\\x85k\\xae\\xb9\\x86\\x08h@\\x04\\x8c\\x1e=\\xba\\x16c\\xdc=\\xd6\\xfe\\xec\\xff&\\xbej\\xad\\x08\\x80\\xc6k\\xb7j-\\xfd\\x7f\\xffkI\\x00\\xf4\\xbfV\\xb8R+\\x0c`\\xa0\\xd3\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00\\xd4*\\x1c\\xee\\xbf\\xff\\xfe\\xe1\\xdak\\xaf%\\x02J\\x88\\x80e\\xcb\\x96\\x85\\xf3\\xce;\\xafV\\xe3\\xdc\\xe9\\xcd\\xb1\\xae\\xafO\\x00h,;\\xc1.\\x01\\x80\\xbbNp\\xe75q\\x87\\x81\\xc6\\x18 \\x00\\x08\\x00\\x02\\x80\\x00\\xa8\\xd5\\x03\\xa6\\xa3\\x00\\x00,\\xeeIDATe0<\\xe0\\x80\\x03\\xc2u\\xd7]\\x17V\\xacXQ\"\\n\\xe7\\xfd\\xd0\\xd9\\xb3g\\xd7r\\xacm\\xf0\\xfd\\xdf\\xe0\\t\\x80\\xfe\\xd7\\nW\\xcd\\xab\\x15\\x01\\xd0\\xbcZ\\xe2R-1\\x80\\x81V3@\\x00\\x10\\x00\\x04\\x00\\x01P\\xebP\\x18/o\\x9f7o\\x1e\\x11\\xd0O\\xb71q\\xe2\\xc4Z\\x8fw\\xab7\\xc5\\xba??\\x01\\xa0q\\xec\\x04\\xc3\\x04\\x00\\xee:\\xc1\\x9d\\xd7\\xc4\\x1d\\x06\\x1ac\\x80\\x00 \\x00\\x08\\x00\\x02 \\x89@H\\x04\\xf4\\xcf\\x00<\\xf1\\xc4\\x13a\\xc4\\x88\\x11I\\x8c\\xb9\\x8d\\x7f\\xf5\\x8d\\x9f\\x00X\\xbd&8i}M\\x08\\x80\\xd6\\xd7\\x18\\xc7j\\x8c\\x01\\x0c4\\x8b\\x01\\x02\\x80\\x00 \\x00\\x08\\x80\\xa4\\xc2\\xe0\\x81\\x07\\x1e\\x18\\xe6\\xcf\\x9f\\xef\\x8a\\x80>|\\xc0\\x84\\t\\x13\\x92\\x1a\\xf3fm\\x88)<\\x0f\\x01\\xa0A\\xec\\x04\\xc7\\x04\\x00\\xee:\\xc1\\x9d\\xd7\\xc4\\x1d\\x06\\x1ac\\x80\\x00 \\x00\\x08\\x00\\x02 \\xc90\\x18E\\xc0\\xf5\\xd7_O\\x04\\xf4 \\x02\\xe6\\xce\\x9d\\x9b\\xe4\\x98k\\x04\\xde\\x13\\x08\\x80\\xc6\\x9a!\\xec\\x0c\\xacn\\x04\\xc0\\xc0\\xea\\x87?\\xf5\\xc3\\x00\\x06\\xda\\xc9\\x00\\x01@\\x00\\x10\\x00\\x04@\\xd2a\\xf0\\xfd\\xef\\x7f\\x7fX\\xb0`\\x01\\x11\\xf02\\x11p\\xef\\xbd\\xf7&=\\xe6\\xed\\xdcD\\xab\\xf6Z\\x04\\x80&\\xb2\\x13L\\x12\\x00\\xb8\\xeb\\x04w^\\x13w\\x18h\\x8c\\x01\\x02\\x80\\x00 \\x00\\x08\\x80\\xe4\\xc3\\xe0\\xae\\xbb\\xee\\x1a:\\xd5\\xa0\\xbe,wW\\xe6?\\x7f\\xf1\\x8b_$?\\xe6\\xb96\\x05\\x04@c\\xcdP\\xae\\xbc4\\xeb\\xbc;\\xb5\\xbe^p\\xc1\\x05\\xd62=\\x0c\\x060\\x80\\x81\\x92\\x0c\\x10\\x00\\x04\\x00\\x01Pr\\xd24\\xaba\\xf2<\\xado\\xd4G\\x8e\\x1c\\x19.\\xbb\\xec\\xb2\\xb0d\\xc9\\x92\\xca\\x84\\xef*\\x1c\\xc8\\x8f~\\xf4#\\x9be\\xa2\\xf3\\x9e\\x00h\\xfd\\xbab\\xed^\\xbd\\xc6\\x04\\xc0\\xea5\\xc1\\x89\\x9a`\\x00\\x03Ue\\x80\\x00 \\x00\\x08\\x80D\\x83@U\\x17\\x9dv\\x1c\\xd7n\\xbb\\xed\\x16\\xbe\\xf3\\x9d\\xef\\x84\\xa5K\\x97V!oW\\xee\\x18\\xa6N\\x9dJ\\x00$:\\xef\\t\\x00\\rg;\\xd6\\xd8U_\\x83\\x00\\xc0\\xdd\\xaaL\\xf8\\x7fL`\\xa0\\xba\\x0c\\x10\\x00\\x04\\x00\\x01\\x90h\\x10\\xc8q\\xe1\\xdd}\\xf7\\xdd\\xc3\\xe5\\x97_.\\xf8\\xafA9\\xc4\\x1b$\\xe6\\xc8G\\x0e\\xe7L\\x00T\\xb7\\xe1J\\x99?\\x02\\x00w)\\xf3\\xed\\xdc\\xf0\\x9d\\x1a\\x03\\x04\\x00\\x01@\\x00\\x10\\x00\\xb5\\x0f\\x83{\\xec\\xb1G\\x98={\\xb6\\xe0\\xbf\\x86\\xe0\\x1f\\xff:\\xde\\x101\\xb5\\x8d\\xcc\\xf9\\xbc\\xd4\\x9c\\x11\\x00/\\xd5\\x02\\x17\\xed\\xab\\x05\\x01\\xd0\\xbeZ\\xe3Z\\xad1\\x80\\x81\\x812@\\x00\\x10\\x00\\x04\\x00\\x01P\\xdb@\\xb8\\xe7\\x9e{\\x86+\\xae\\xb8B\\xf0\\xefG\\xf0\\x8f\\x0f\\xf9\\xd3\\x9f\\xfe\\x14v\\xdey\\xe7\\xda\\x8e\\xf7@7\\xbc\\x1c~\\x9f\\x00\\xd0\\x18v\\x82s\\x02\\x00w\\x9d\\xe0\\xcek\\xe2\\x0e\\x03\\x8d1@\\x00\\x10\\x00\\x04\\x00\\x01P\\xbb@8j\\xd4\\xa8\\xf0\\xbd\\xef}/,[\\xb6\\xac\\x9f\\xd1\\xd7\\xc3\\x1e}\\xf4\\xd1p\\xc0\\x01\\x07\\xd4n\\xacm\\xee\\xe56w\\x02\\xa0\\\\\\xbd\\xf0\\xd5\\x9cz\\x11\\x00\\xcd\\xa9#\\x1e\\xd5\\x11\\x03\\x18h\\x07\\x03\\x04\\x00\\x01@\\x00\\x10\\x00\\xb5\\t\\x85{\\xed\\xb5W\\x983g\\x8e\\xe0_\\xc2g\\xbc\\xf0\\xc2\\x0b]\\xb2d\\x87\\x1dv\\xa8\\xcd8\\xb7c\\xf3K\\xf55\\x08\\x00\\xcdc\\'\\xd8&\\x00p\\xd7\\t\\xee\\xbc&\\xee0\\xd0\\x18\\x03\\x04\\x00\\x01@\\x00\\x10\\x00\\x95\\x0f\\x86{\\xef\\xbdw\\xf8\\xfe\\xf7\\xbf\\x1f\\x96/_^\"\\xfa\\xe6\\xfd\\xd0\\x18\\xfc\\xaf\\xbe\\xfa\\xea\\xb0\\xef\\xbe\\xfbV~|m\\xe0\\x8dm\\xe0=\\xd5\\x8d\\x00h^-{\\xaa\\xaf\\x9f\\xf5\\\\_\\x02\\xa0\\xe7\\xba\\xe0E]0\\x80\\x81*2@\\x00\\x10\\x00\\x04\\x00\\x01P\\xd9\\x80\\xb8\\xcf>\\xfb\\x84\\x1f\\xfc\\xe0\\x07\\x82\\x7f\\t\\x97!\\xf8\\xe7\\xddl\\x10\\x00y\\x8f\\x7f\\xa7\\x1aM\\x02\\x00w\\x9db\\xcf\\xebb\\x0f\\x03\\xe5\\x19 \\x00\\x08\\x00\\x02\\x80\\x00\\xa8\\x9c\\x00\\x88\\xffj}\\xd5UW\\t\\xfe\\x82\\x7f\\xe5\\xd8\\xacz\\xa3A\\x00\\x94o\\x84\\xaa>\\xa6u8>\\x02\\x00wu\\xe0\\xd41\\xe2\\x14\\x03\\xff\\xc7\\x00\\x01@\\x00\\x10\\x00\\x04@eB\\xd6~\\xfb\\xed\\x17\\xe6\\xce\\x9d\\x1b\\xe2\\xbfb\\xfb\\xea_\\x05\\xfc\\x8b\\xbf\\x86\\xe6\\xe5\\r\\r\\x01\\x80\\x87\\x97\\xf3\\xd0\\xdb\\x7fo\\xb5\\xd5V!\\xdeL\\xf5C\\x1f\\xfaP8\\xea\\xa8\\xa3\\xc2I\\'\\x9d\\x14\\xbe\\xf4\\xa5/\\x85\\xb3\\xcf>;\\x9cu\\xd6Y\\xe1\\xcc3\\xcf\\x0c\\x93\\'O\\x0e\\xa7\\x9f~z\\xf8\\xecg?\\xdb\\xf5\\x98\\x0f|\\xe0\\x03a\\xe4\\xc8\\x91a\\xd8\\xb0a\\xab\\xed\\x19\\x04\\x00\\xeezc\\xcd\\xcf\\xb1\\x81\\x81\\xea1@\\x00\\x10\\x00\\x04\\x00\\x01\\xb0Z3\\xd7\\xee\\xc5z\\xff\\xfd\\xf7\\x0f\\xd7\\\\s\\x8d\\xe0\\xdf\\xbf\\xcc\\xdf\\xf5(\\xc1\\xbfz\\x1bj\\xbb\\xe7MO\\xafG\\x00\\xe0\\xe2\\xe5\\\\\\x8c\\x181\"\\x8c\\x1d;\\xb6+\\xcc\\xcf\\x9e=;\\xdc}\\xf7\\xdd\\xe1\\xb1\\xc7\\x1e+\\xb1\\xd2\\xac\\xfe\\xd0x/\\x96\\x07\\x1f|0\\xdcp\\xc3\\ra\\xea\\xd4\\xa9\\xe1\\xc4\\x13O\\xecz\\xde\\xd5\\x1f\\xd9\\xfa\\x9f\\\\p\\xc1\\x05\\x1d\\xdf\\xbf^^o\\xffm\\xfea\\x00\\x03u`\\x80\\x00 \\x00\\x08\\x00\\x02\\xa0c\\r\\xd4\\xe8\\xd1\\xa3\\xc3u\\xd7]\\'\\xf8\\x97\\xe8\\x93\\x05\\x7f\\xcdE_\\xcd\\x05\\x01\\x907\\x1f\\xdbo\\xbf}8\\xe1\\x84\\x13\\xc2\\xcc\\x993\\xc3/\\x7f\\xf9\\xcb\\xe4\\xd7V\\x02 o\\xde\\xfbZ\\x0b\\xfd\\x1d60\\xd0;\\x03\\x04\\x00\\x01@\\x00\\x10\\x00m\\x17\\x00\\x07\\x1ex`\\x987o^X\\xb1bE\\x89\\xe8\\x9b\\xf7C\\x05\\xff\\xde72\\x9b\\xfcK\\xb5!\\x00^\\xaaE.\\\\\\xec\\xb1\\xc7\\x1e\\xe1\\x8c3\\xce\\x08?\\xfe\\xf1\\x8f\\xb3\\xfb\\x88T\\x02 ?\\xdes\\x99\\xd7\\xce\\x13\\xdb\\xadd\\x80\\x00 \\x00\\x08\\x00\\x02\\xa0m\\x02\\xe0\\xfd\\xef\\x7f\\x7f\\x98?\\x7f\\xbe\\xe0_\\xc2e\\x08\\xfe\\x9a\\x802M\\x00\\x01\\x90\\x07/\\xef{\\xdf\\xfb\\xc2\\x97\\xbf\\xfc\\xe5\\xf0\\x8b_\\xfc\\xa2\\xc4j\\x92\\xdeC\\t\\x80<x/\\xb3\\x06z,&0\\xb0f\\x06\\x08\\x00\\x02\\x80\\x00 \\x00Z.\\x00\\xfe\\xe5_\\xfe%,X\\xb0@\\xf0/\\xd1\\x7f\\x0b\\xfek\\xde\\xc0l\\xf2\\xab\\xd7\\x88\\x00X\\xbd&)q2n\\xdc\\xb8\\xae\\xab\\xa7\\x96.]Zb5I\\xf7\\xa1\\x04@\\xda\\xbc\\xa74w\\x9d\\x0bV\\xab\\xc4\\x00\\x01@\\x00\\x10\\x00\\x04@\\xcb\\x04\\xc0\\x07?\\xf8\\xc1\\xae\\x1bE\\xa5\\xdb~6\\xff\\xcc\\x04\\x7fM\\xc2@\\x9a\\x04\\x02 =~\\xe2]\\xf7\\'N\\x9c\\x18~\\xf7\\xbb\\xdf5\\x7f\\xc1\\xa9\\xf93\\x12\\x00\\xe9\\xf1>\\x90\\xf5\\xcf\\xef\\xe2\\x01\\x03\\xfdc\\x80\\x00 \\x00\\x08\\x00\\x02\\xa0\\xe9\\x02`\\xcc\\x981\\xe1\\xc6\\x1bo\\xacyk\\xd9\\xde\\xc3\\x17\\xfc\\xfb\\xb7i\\xd9\\xdc\\xfb\\xae\\x13\\x01\\xd0w}\\xea\\xc4\\xcf\\x96[n\\xd9\\xf5\\xd1|\\x8f>\\xfah{\\x17\\xa3\\x1a\\xbd\\x1a\\x01\\x90\\x0e\\xefu\\x9a\\x9b\\x8e\\x15wug\\x80\\x00 \\x00\\x08\\x00\\x02\\xa0i\\x02 ~\\xa6\\xf4\\xcd7\\xdf\\\\\\xa3\\xf6\\xb1\\xf3\\x87*\\xf8k$\\x9a\\xd9H\\x10\\x00\\xf5\\xe7i\\xf0\\xe0\\xc1a\\xd2\\xa4I\\x03\\xfe\\xb8\\xbe\\xce\\xafn\\xad?\\x02\\x02\\xa0\\xfe\\xbc7s\\xfd\\xf3\\\\x\\xc0@\\xff\\x18 \\x00\\x08\\x00\\x02\\x80\\x00\\x18\\xb0\\x008\\xe8\\xa0\\x83\\xc2-\\xb7\\xdc\\xd2\\xfan/\\xa1W\\x10\\xfc\\xfb\\xb7I\\xd9\\xcc\\xcb\\xd5\\x89\\x00(W\\xaf\\xaa\\xf1u\\xd8a\\x87\\x85\\xfb\\xef\\xbf?\\xa1\\x95\\xae\\xb5\\xa7B\\x00\\xd4\\x9b\\xf7\\xaa\\xcd?\\xc7\\x83\\xa7\\\\\\x18 \\x00\\x08\\x00\\x02\\x80\\x00hX\\x00\\x1cr\\xc8!\\xe1\\xd6[omm\\x87\\x97\\xd8\\xb3\\x0b\\xfe\\x1a\\x8cV6\\x18\\x04@=\\xf9\\xday\\xe7\\x9d\\xc3\\xdc\\xb9s\\x13[\\xedZ\\x7f:\\x04@=yo\\xe5\\x1a\\xe8\\xb91\\x81\\x8153@\\x00\\x10\\x00\\x04\\x00\\x01PZ\\x00\\xfc\\xeb\\xbf\\xfek\\xf8\\xe1\\x0f\\x7f\\xd8\\xfa\\xee.\\xa1W\\x10\\xfc\\xd7\\xbc!\\xd9\\xb4\\x07^#\\x02`\\xe05l7\\x87\\x9f\\xfc\\xe4\\'\\xc3\\x93O>\\x99\\xd0j\\xd7\\xbeS!\\x00\\xea\\xc7{\\xbb\\xe7\\x97\\xd7\\xc3\\x08\\x06Vg\\x80\\x00 \\x00\\x08\\x00\\x02\\xa0\\xdf\\x02\\xe0\\xd0C\\x0f\\r\\xb7\\xddv[\\xfb\\xba\\xbb\\x04^I\\xf0_}\\xe3\\xb1\\x19\\xb7\\xae&\\x04@\\xebj\\xdbln\\xb7\\xd9f\\x9bp\\xe5\\x95W&\\xb0\\xcau\\xee\\x14\\x08\\x80\\xfa\\xf0\\xde\\xec\\xf9\\xe3\\xf9\\x8c=\\x06\\x1ag\\x80\\x00 \\x00\\x08\\x00\\x02`\\x8d\\x02\\xe0\\xc3\\x1f\\xfepX\\xb4hQ\\xe7\\xba\\xbc\\x1a\\xbe\\xb2\\xe0\\xdf\\xf8\\xc6dSo\\xbcv\\x04@\\xe3\\xb5k\\'w\\xf1\\x93R\\x1ey\\xe4\\x91\\x1a\\xael\\xd5:d\\x02\\xa0\\x1e\\xbc\\xb7sny-L``\\xcd\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00\\xf4*\\x00\\xc6\\x8e\\x1d\\x1b~\\xf2\\x93\\x9fT\\xab\\xe3\\xab\\xf8\\xd1\\x08\\xfek\\xdexl\\xce\\xad\\xab\\x11\\x01\\xd0\\xba\\xda6\\x8b\\xdb\\x13O<1<\\xff\\xfc\\xf3\\x15_\\xc9\\xeaqx\\x04@\\xf5yo\\xd6\\xbc\\xf1<\\xc6\\x1a\\x03\\xcdc\\x80\\x00 \\x00\\x08\\x00\\x02`5\\x01\\xf0\\x91\\x8f|$\\xdc~\\xfb\\xed\\xf5\\xe8\\x00+r\\x94\\x82\\x7f\\xf36&\\x9b|\\xe3\\xb5$\\x00\\x1a\\xaf];\\xb8\\x8b\\x81\\xd5W\\xf3*@\\x00T\\x9b\\xf7v\\xcc)\\xaf\\x81\\x01\\x0c\\x94g\\x80\\x00 \\x00\\x08\\x00\\x02\\xe0\\xaf\\x02\\xe0\\x88#\\x8e\\x08w\\xdcqG\\xf3\\xba\\xb3\\x0c\\x9eI\\xf0/\\xbf\\xf1\\xd8\\xac[W3\\x02\\xa0u\\xb5\\x1d\\x08\\xb7\\xc3\\x86\\r\\x0b\\xf3\\xe7\\xcf\\xcf`El\\xef)\\x12\\x00\\xd5\\xe4} s\\xc5\\xef\\x1aS\\x0c\\xb4\\x9e\\x01\\x02\\x80\\x00 \\x00\\x08\\x800n\\xdc\\xb8p\\xd7]w\\xb5\\xb7s\\xab\\xf9\\xab\\t\\xfe\\xad\\xdf\\xa04\\x01\\xe5kL\\x00\\x94\\xafY\\xab9\\xdbb\\x8b-\\xc2\\xc2\\x85\\x0bk\\xbe\\xe2U\\xf3\\xf0\\t\\x80\\xea\\xf1\\xde\\xea\\xf9\\xe4\\xf9\\x8d9\\x06\\x06\\xce\\x00\\x01@\\x00\\x10\\x00\\x19\\x0b\\x80\\x8f~\\xf4\\xa3\\xe1?\\xff\\xf3?\\xab\\xd9\\xd9U\\xf4\\xa8\\x04\\xff\\x81o<6\\xef\\xd6\\xd5\\x90\\x00h]m\\x1b\\xe1v\\xab\\xad\\xb6\\xf2\\x91\\xa9-\\\\\\xcb\\t\\x80j\\xf1\\xde\\xc8\\x1c\\xf1;\\xc6\\x10\\x03\\xedg\\x80\\x00 \\x00\\x08\\x80\\x0c\\x05\\xc0QG\\x1d\\x15\\xee\\xb9\\xe7\\x9e\\x16\\xb6e\\xe9=\\xb5\\xe0\\xdf\\xfe\\rJSP\\xbe\\xe6\\x04@\\xf9\\x9a\\xb5\\x8a\\xb3x\\xd9\\xbfOOi\\xed^@\\x00T\\x87\\xf7V\\xcd#\\xcfk\\x8c1\\xd0|\\x06\\x08\\x00\\x02\\x80\\x00\\xc8H\\x00\\x1c}\\xf4\\xd1\\xe1\\xa7?\\xfdik;\\xb2\\xc4\\x9e]\\xf0o\\xfe\\xc6c3o]M\\t\\x80\\xd6\\xd5\\xb6,\\xb7W^yeb\\xaba\\xf5N\\x87\\x00\\xa8\\x0e\\xefe\\xe7\\x87\\xc7\\x1b;\\x0ct\\x8e\\x01\\x02\\x80\\x00 \\x002\\x10\\x00\\x1f\\xfb\\xd8\\xc7\\xc2\\xcf~\\xf6\\xb3\\xeauo\\x15>\"\\xc1\\xbfs\\x1b\\x93\\xa6\\xa0\\xf1\\xda\\x13\\x00\\x8d\\xd7\\xae\\x99\\xdc\\xfd\\xfb\\xbf\\xff{\\x85W\\xb7t\\x0e\\x8d\\x00\\xa8\\x06\\xef\\xcd\\x9c;\\x9e\\xcb\\x98b\\xa0\\xf5\\x0c\\x10\\x00\\x04\\x00\\x01\\x90\\xb0\\x008\\xf6\\xd8c\\xc3}\\xf7\\xdd\\x97N\\xb7\\xd7\\x863\\x11\\xfc[\\xbf\\xf1\\xd8\\xdc[Wc\\x02\\xa0u\\xb5\\xed/\\xb7\\'\\x9exb\\x1bV*/\\x11+@\\x00t\\x9e\\xf7\\xfe\\xce\\x0b\\x8f3V\\x18\\xa8\\x0e\\x03\\x04\\x00\\x01@\\x00$(\\x00>\\xfe\\xf1\\x8f\\x87\\x9f\\xff\\xfc\\xe7:\\xc4\\x12\\x15\\x10\\xfc\\xab\\xb31i\\x12\\x1a\\x1f\\x0b\\x02\\xa0\\xf1\\xda5\\x83\\xbb\\xbd\\xf6\\xda+,^\\xbc\\xb8\\xc4\\xca\\xe3\\xa1\\x03\\xa9\\x00\\x01\\xd0Y\\xde\\x9b1g<\\x871\\xc4@\\xfb\\x19 \\x00\\x08\\x00\\x02 !\\x010v\\xecX\\xc1\\xbfd7)\\xf8\\xb7\\x7f\\xe3\\xb1\\xd9\\xb7\\xae\\xe6\\x04@\\xebj\\xbb&n\\x87\\x0e\\x1d\\xea\\xadV%\\xd7\\xdf\\x81>\\x9c\\x00\\xe8\\x1c\\xefk\\x9a\\x0f\\xfe\\xde\\xd8`\\xa0\\xba\\x0c\\x10\\x00\\x04\\x00\\x01\\x90\\x88\\x00\\x982eJX\\xb1b\\xc5@\\xfb\\xa9l~_\\xf0\\xaf\\xee\\xc6\\xa4ih|l\\x08\\x80\\xc6k7P\\xeeb\\x18\\xf5\\xd5\\xde\\n\\x10\\x00\\x9d\\xe3}\\xa0\\xf3\\xc5\\xef\\x1b;\\x0ct\\x8e\\x01\\x02\\x80\\x00 \\x00\\x12\\x10\\x00\\xe7\\x9csN{\\xbb\\xae\\x1a\\xbf\\x9a\\xe0\\xdf\\xb9\\r\\xc7f\\xdf\\xfa\\xda\\x13\\x00\\xad\\xafqO\\x1c\\x7f\\xe8C\\x1f\\nqm\\xf1\\xd5\\xde\\n\\x10\\x00\\x9d\\xe1\\xbd\\xa79\\xe0g\\xc6\\x02\\x03\\xf5a\\x80\\x00 \\x00\\x08\\x80\\x9a\\x0b\\x801c\\xc6\\x84\\xe5\\xcb\\x97\\xb7\\xb7\\xeb\\xaa\\xe1\\xab\\t\\xfe\\xf5\\xd9\\x984\\x11\\x8d\\x8f\\x15\\x01\\xd0x\\xed\\x1a\\xe5n\\xf0\\xe0\\xc1n\\xb6\\xda\\xa1=\\x81\\x00h?\\xef\\x8d\\xce\\x13\\xbfg\\xac0P\\x1d\\x06\\x08\\x00\\x02\\x80\\x00\\xa8\\xb9\\x00\\xb8\\xe5\\x96[:\\xd4z\\xd5\\xe3e\\x05\\xff\\xeal86\\xff\\xd6\\x8f\\x05\\x01\\xd0\\xfa\\x1a\\xaf\\xca\\xf1\\x84\\t\\x13\\xea\\xb1\\x18&x\\x94\\xd3\\xa7O\\x0f\\xab\\x8e\\x87\\xffo\\xff\\x1cPs5\\xc7@\\xbd\\x18 \\x00\\x08\\x00\\x02\\xa0\\xc6\\x02`\\xc7\\x1dwt\\xd9i/M\\xad\\xe0_\\xaf\\xcdH\\xf3\\xd0\\x9c\\xf1\"\\x00\\x9aS\\xc7\\xfe\\xf2\\xb8\\xc5\\x16[\\x84G\\x1f}\\xb4\\x97U\\xc8\\x8f[]\\x81+\\xae\\xb8\\x82\\x00\\xa8q\\x0f\\xd3\\xdfy\\xe6q\\xed]\\xd7\\xd4;\\xfdz\\x13\\x00\\x04\\x00\\x01P\\xe3\\xcd3~\\xdc\\x9f\\xaf\\x95+\\xd0\\x1d\\xfc\\xf7\\xdbo?\\x8da\\x8d\\xd9\\xd6\\x804\\xd6\\x80\\x10\\x00\\x8d\\xd5\\xadQ\\xde\\xbe\\xf8\\xc5/\\xae\\xbc\\x00\\xf9\\xbf\\xb6V`\\xfe\\xfc\\xf9\\xd6y\\xeb<\\x060\\x80\\x81\\x92\\x0c\\x10\\x00\\x04\\x00\\x01Pr\\xd24\\xda(\\xb6\\xe2\\xf7N;\\xed\\xb4\\xb66[U~1\\xc1\\xbf\\xbd\\xc1\\xa7\\x15<{\\xce\\x81\\x8f!\\x010\\xf0\\x1a\\xf6\\x97\\xc3\\xf8\\xde\\xff\\x87\\x1ez\\xa8\\xca\\xcbb\\xf2\\xc7\\xf6\\xc3\\x1f\\xfeP\\xe3_\\xe3\\x1e\\xa6\\xbfs\\xcd\\xe3\\xda\\xb7\\xae\\xa9u\\x1e\\xb5&\\x00\\x08\\x00\\x02\\xa0\\xc6\\x9b\\xe7Yg\\x9d\\x95|\\x83\\xb7\\xa6\\x13\\x14\\xfc\\xf3\\xd8\\xacRmJb\\x88\\xdcu\\xd7]\\xc3\\x81\\x07\\x1e\\x18\\x0e?\\xfc\\xf0\\xf0\\xc9O~2L\\x9c81\\xc4\\xb9\\x1d\\xbf\\xcf<\\xf3\\xcc0y\\xf2\\xe4p\\xfa\\xe9\\xa7\\x87SN9%\\x1c{\\xec\\xb1\\xe1\\x90C\\x0e\\t\\xa3F\\x8d\\n#F\\x8cX-\\xfc\\x10\\x00\\xed\\x9b\\x0fq,|u\\xb6\\x02\\xb7\\xdf~\\xfbjs \\xd5\\xb5\\xc2y\\xb5on\\xab\\xb5Z\\xa7\\xce\\x00\\x01@\\x00\\x10\\x00\\x04@g;\\xb8\\x06_]\\xf0\\xb7A\\xd7i\\x83\\x1e2dH\\x18=zt\\x887\\x8c\\xbb\\xf0\\xc2\\x0b\\xc3\\xad\\xb7\\xde\\x1a~\\xf7\\xbb\\xdf\\x85\\xa5K\\x9768\\x03\\xfe\\xef\\xd7\\x1e{\\xec\\xb1\\xb0h\\xd1\\xa2\\xf0\\xedo\\x7f;L\\x9a4)L\\x9b6m@\\xcf\\xd7\\xe8/?\\xf0\\xc0\\x03\\xd9\\x05\\xb1\\x85\\x0b\\x176Z.\\xbf\\xd7\\xa4\\n\\xdcu\\xd7]\\xd9qW\\xa7u\\xcf\\xb1\\xda\\xa71PM\\x06\\x08\\x00\\x02\\x80\\x00 \\x00\\x9a\\xd4\\x8a\\xb5\\xe7i\\x04\\xffjn&6\\xf9\\x95\\xc7e\\xe8\\xd0\\xa1a\\xec\\xd8\\xb1\\xe1\\x1b\\xdf\\xf8F\\xf8\\xc9O~\\x12\\x16/^\\xdc\\x9e\\t\\xd2\\xa1W\\xc9M\\x00\\xec\\xb0\\xc3\\x0ea\\xd9\\xb2e\\x1d\\xaa\\xb6\\x97\\xed\\xae@\\x9c_\\xd6\\x9e\\x95\\xd7\\x1e\\xf5P\\x0f\\x0c``M\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00t\\xf7R\\x95\\xfeS\\xf0\\xb7\\xa1\\xadiC\\xeb\\xf4\\xdf\\xc7K\\xf2O8\\xe1\\x84p\\xd5UW\\x85\\xa7\\x9ez\\xaa\\xd2\\xf3\\xa9\\xd9\\x07\\x97\\x9b\\x008\\xf5\\xd4S\\x9b]B\\xcf\\xd7@\\x05\\xbe\\xf2\\x95\\xaf\\x10\\x005\\xeea:\\xbdf{}}E\\xae\\x0c\\x10\\x00\\x04\\x00\\x01P\\xe3\\xcd3\\x87{\\x00\\x08\\xfe6\\xe8*o\\xd0\\xc3\\x86\\r\\x0b\\xc7\\x1f\\x7f|\\x88\\x97\\x83/Y\\xb2\\xa4\\x81\\x08\\x93\\xc6\\xaf\\xe4&\\x00\\x16,X\\x90\\xc6\\xc0\\xd5\\xfc,\\xe2[j\\xaa\\xbc>86\\xfb\\x17\\x060PE\\x06\\x08\\x00\\x02\\x80\\x00 \\x00*\\xd9\\x02v\\x07\\xff}\\xf7\\xddW\\x83WcF\\xab\\xb8\\xf15\\xe3\\x98\\xf6\\xdak\\xaf0}\\xfa\\xf4\\xf0\\xf8\\xe3\\x8fWr\\xfe\\xb4\\xfb\\xa0r\\x12\\x00\\xf1\\xc6\\x8dO?\\xfdt\\xbbK\\xec\\xf5z\\xa8\\xc0G?\\xfaQ\\xfb\\x83\\xfd\\x01\\x03\\x18\\xc0@I\\x06\\x08\\x00\\x02\\x80\\x00(9i\\x9a\\x11\\x1e\\x9a\\xf5\\x1c)^\\x01\\xd0\\x1d\\xfc\\xf7\\xdbo?\\x0bz\\x8d\\xd9l\\x16\\xe3U{\\x9e\\xc3\\x0e;,\\xc4\\x8f\\x1e\\xf3\\xb5r\\x05r\\x12\\x00\\xf1f\\x8e\\xbe\\xaaQ\\x81=\\xf6\\xd8\\xc3>a\\x9f\\xc0\\x00\\x060P\\x92\\x01\\x02\\x80\\x00 \\x00JN\\x9a*\\x05\\x92\\x94\\x04\\x80\\xe0\\xef2\\xb9*\\xcd\\xadU\\x8f\\xe5\\xc8#\\x8f\\x0cw\\xdcqG5RO\\x05\\x8f\"\\'\\x01\\xf0\\xb9\\xcf}\\xae\\x82#\\x90\\xdf!\\xc5\\x1bk\\xae:O\\xfd\\xbf}\\x04\\x03\\x18\\xc0\\xc0\\x9a\\x19 \\x00\\x08\\x00\\x02\\x80\\x00\\xe8h\\xe7(\\xf8\\xafy\\xa1\\xb6\\x99u\\xaeF\\x07\\x1f|p\\xb8\\xe7\\x9e{::G\\xea\\xf0\\xe29\\t\\x80\\xf8\\xd6\\x0f_\\x9d\\xaf\\xc0\\xed\\xb7\\xdfN\\x00\\xd4\\xb8\\x7f\\xb1\\xafun_S{\\xb5\\'\\x00\\x08\\x00\\x02\\xa0\\xc6\\x1bh\\x9d\\xaf\\x00\\x10\\xfcm@UnBv\\xdai\\xa7\\xf0\\xfd\\xef\\x7f?\\xacX\\xb1\\xa2\\xf3I\\xa7\\x06G\\x90\\x93\\x00\\xb8\\xf6\\xdakk0\"\\xe9\\x1f\\xe2\\xf9\\xe7\\x9fO\\x00\\xd4\\xb8\\x7f\\xa9\\xf2\\xfa\\xef\\xd8\\xf4\\'\\xa93@\\x00\\x10\\x00\\x04@\\x8d7\\xd0:\\n\\x00\\xc1\\xdf\\xc6Z\\xe5\\x8du\\xc8\\x90!\\xe1\\xec\\xb3\\xcf\\x0e\\xcf>\\xfbl\\xfa\\t\\xaa\\x89g\\x98\\x93\\x00\\xb8\\xf3\\xce;\\x9bX9O\\xd5h\\x05\\x0e=\\xf4P\\x02\\xa0\\xc6\\xfdK\\x95\\xf7\\x01\\xc7\\xa6OI\\x9d\\x01\\x02\\x80\\x00 \\x00j\\xbc\\x81\\xd6I\\x00\\x08\\xfe6\\xd4\\xaao\\xa8\\xf1\\xce\\xfe.\\xf7o,\\x8e\\xe5$\\x00~\\xf9\\xcb_6V$\\xbf\\xd5\\xb4\\n<\\xf1\\xc4\\x13!\\xca\\xba\\xaa\\xaf)\\x8e\\xcf\\xbe\\x87\\x01\\x0cT\\x91\\x01\\x02\\x80\\x00 \\x00\\x08\\x80\\xa65e==\\x91\\xe0o\\xf3\\xab\\xe2\\xe6\\xb7\\xea1M\\x9a4)\\xc4\\x9b\\x8a\\xf9j\\xac\\x029\\t\\x80\\x07\\x1f|\\xb0\\xb1\"\\xf9\\xad\\xa6U\\xe0;\\xdf\\xf9\\x8e\\xf0_\\xe3\\xdee\\xd5\\xf5\\xd7\\xff\\xeb\\x130\\xd0^\\x06\\x08\\x00\\x02\\x80\\x00\\xa8\\xf1&Z\\xe5+\\x00\\x04\\xff\\xf6.\\xe66\\xcf\\xc6\\xea\\xbd\\xed\\xb6\\xdb\\x86\\x1bo\\xbc\\xb1i\\xc1$\\xd7\\'\\xcaI\\x00\\xc4s\\xf5\\xd5\\xd9\\n\\xc4\\x9bsZ\\xf3\\x1a[\\xf3\\xd4M\\xdd0\\x80\\x01\\x02\\x80\\x00 \\x00\\x08\\x80\\xa6vr\\x82\\xbf\\x8d\\xa5.\\xcd\\xc5\\xde{\\xef\\x1d\\x84\\xb9\\xe6L\\xff\\x9c\\x04\\xc0\\x7f\\xfd\\xd7\\x7f5\\xa7h\\x9e\\xa5\\xa1\\n\\xdc\\x7f\\xff\\xfd\\xc2\\x7f\\x8d\\xfb\\x96\\xba\\xec\\x0f\\x8eS/\\x932\\x03\\x04\\x00\\x01@\\x00\\xd4x#\\xad\\xd2\\x15\\x00\\x82\\xbf\\xcd\\xb2N\\x9b\\xe5\\xb8q\\xe3\\xc2SO=\\xd5P\\x00\\xf1K\\xabW \\'\\x01p\\xdbm\\xb7\\xad^\\x00?i[\\x05>\\xfb\\xd9\\xcf\\x12\\x005\\xee[\\xea\\xb4O8V}M\\xaa\\x0c\\x10\\x00\\x04\\x00\\x01P\\xe3\\x8d\\xb4\\n\\x02@\\xf0\\xb7A\\xd6m\\x83\\xfc\\xfc\\xe7?\\x1f\\x96/_\\xde\\xb6\\xc0\\x92\\xc3\\x0b\\xe5$\\x00\\xe2\\xc7C\\xfa\\xeaL\\x05\\x1e~\\xf8\\xe10t\\xe8P\\x02\\xa0\\xc6}K\\xdd\\xf6\\x0b\\xc7\\xab\\xc7I\\x91\\x01\\x02\\x80\\x00 \\x00j\\xbc\\x91vR\\x00\\x08\\xfe6\\xc5:n\\x8a_\\xfc\\xe2\\x17\\xc3\\x8a\\x15+:\\x93^\\x12~\\xd5\\x9c\\x04\\xc0\\xd7\\xbe\\xf6\\xb5\\x84G\\xb2\\xda\\xa7v\\xf2\\xc9\\'\\x0b\\xff5\\xeeY\\xea\\xb8g8f\\xbdN\\x8a\\x0c\\x10\\x00\\x04\\x00\\x01P\\xe3\\xcd\\xb4\\x13\\x02@\\xf0\\xb7\\x19\\xd6u3<\\xe3\\x8c3\\xaa\\x9dnj|t9\\t\\x80c\\x8f=\\xb6\\xc6#U\\xdfC\\x8f\\x1f\\xbf8x\\xf0`\\x02\\xa0\\xc6=K]\\xf7\\x0e\\xc7\\xad\\xefI\\x8d\\x01\\x02\\x80\\x00 \\x00j\\xbc\\x99\\xb6S\\x00\\x08\\xfe6\\xc0:o\\x80\\xc2\\x7fk\\x83_N\\x02\\xe0}\\xef{_k\\x8b\\xe9\\xd9{\\xac\\xc0\\x87?\\xfca\\xe1\\xbf\\xc6\\xfdJ\\x9d\\xf7\\x0f\\xc7\\xae\\xffI\\x8d\\x01\\x02\\x80\\x00 \\x00j\\xbc\\xa1\\xc6\\xcf.o\\xf5\\x97\\xe0o\\xe3\\xab\\xfb\\xc6w\\xdcq\\xc7\\x85\\xc8\\xb1\\xaf\\xd6U \\'\\x01\\x10\\xe7\\xc3\\xaf\\x7f\\xfd\\xeb\\xd6\\x15\\xd33\\xafV\\x81\\xef}\\xef{\\xc2\\x7f\\x8d{\\x95\\xba\\xef!\\x8e_\\x1f\\x94\\x1a\\x03\\x04\\x00\\x01@\\x00\\xd4xS\\xfd\\xe8G?\\xbaZ\\xa3\\xd4\\xac\\x1f\\x08\\xfe6\\xbc\\x146\\xbc1c\\xc6\\x84\\xe7\\x9e{\\xaeY\\xd3\\xc2\\xf3\\xf4R\\x81\\xdc\\x04\\xc0\\xf4\\xe9\\xd3{\\xa9\\x84\\x1f7\\xbb\\x02\\xbf\\xfb\\xdd\\xef\\xc2\\xd6[oM\\x00\\xd4\\xb8WIa/q\\x0ez\\xa2\\x94\\x18 \\x00\\x08\\x00\\x02\\xa0\\xc6\\x9bjl\\x8a\\x9e\\x7f\\xfe\\xf9\\xa6\\xf6[\\x82\\xbfM.\\x95Mn\\xe4\\xc8\\x91\\xe1\\xb1\\xc7\\x1ek\\xea\\xfc\\xf0d=W 7\\x01\\x10\\xc5\\x92\\xaf\\xd6W`\\xd9\\xb2e\\xe1\\xe0\\x83\\x0f\\x16\\xfek\\xdc\\xa7\\xa4\\xb2\\x9f8\\x0f\\xbdQJ\\x0c\\x10\\x00\\x04\\x00\\x01P\\xf3\\x8du\\xce\\x9c9M\\xe9\\xc2\\x04\\x7f\\x9b[J\\x9b[\\xbcY\\xd8\\x9dw\\xde\\xd9\\x94\\xb9\\xe1I\\xd6\\\\\\x81\\xdc\\x04@\\x9c+\\xff\\xfd\\xdf\\xff\\xbd\\xe6\\xc2x\\xc4\\x80*0e\\xca\\x14\\xe1\\xbf\\xe6=JJ\\xfb\\x8as\\xd1\\'\\xa5\\xc2\\x00\\x01@\\x00\\x10\\x005\\xdf\\\\w\\xdbm\\xb7\\xf0\\xec\\xb3\\xcf6\\xdcd\\t\\xfe6\\xb4T6\\xb4\\x97\\x9f\\xc7\\xb9\\xe7\\x9e\\xdb\\xf0\\x9c\\xf0\\x8b\\xe5+\\x90\\xa3\\x00\\x88\\x1f)\\xe9\\xabu\\x15X\\xb0`\\x81\\xbb\\xfe\\xd7\\xbc?y\\xf9\\x9a\\xec\\xbf\\xf5\\x1a\\x18\\xa8\\x0e\\x03\\x04\\x00\\x01@\\x00$\\xb0\\xc1\\xc6\\x9b\\x9c-_\\xbe\\xbcT\\'&\\xf8Wg!\\xb6)6w,\\x0e:\\xe8\\xa0\\x10/\\x1d\\xf6\\xd5\\xbe\\n\\xe4(\\x00\\xb6\\xdaj\\xab\\xf0\\xe7?\\xff\\xb9}E\\xce\\xe8\\x95~\\xf6\\xb3\\x9f\\x85X_kcs\\xd7F\\xf5TO\\x0c` 2@\\x00\\x10\\x00\\x04@\\x02\\x02 N\\xe6\\x8f}\\xecc\\xe1\\xa9\\xa7\\x9eZc\\x8b(\\xf8[\\xfcSn\\x00\\x86\\r\\x1b\\x16b\\x18\\xf5\\xd5\\xde\\n\\xe4(\\x00\\xe2<\\x9a<yr{\\x0b\\x9d\\xc1\\xab=\\xf2\\xc8#a\\xc7\\x1dw\\x14\\xfe\\x13\\xe9MR\\xdeo\\x9c\\x9b~\\xaa\\xae\\x0c\\x10\\x00\\x04\\x00\\x01\\x90\\xd0&\\xbb\\xd3N;\\x85\\x993g\\x86g\\x9eyf\\xb56\\xf1/\\x7f\\xf9K\\x88\\xf7\\x0b\\xd8o\\xbf\\xfd4V\\t\\x8dy]7\\x9fV\\x1d\\xf7\\xd7\\xbf\\xfe\\xf5\\xd5\\xd8\\xf7\\x83\\xd6W \\xde\\xa9\\xbdUcZ\\xe5\\xe7\\x8d\\xc2\\xe9\\xb7\\xbf\\xfdm\\xeb\\x0b\\x9c\\xc9+\\xfc\\xe9O\\x7f\\n\\xfb\\xee\\xbbo\\x96,U\\x99s\\xc7&\\xe8b -\\x06\\x08\\x00\\x02\\x80\\x00H0\\x0c\\xc6\\xa6\\xf4\\x90C\\x0e\\t\\x9f\\xf9\\xccg\\xc2I\\'\\x9d\\x14>\\xfc\\xe1\\x0f\\x87-\\xb7\\xdcRS\\x95\\xe0X\\xdb\\x94_\\xda\\x94\\xa3\\x00[\\xbcxq&Q\\xa9Z\\xa7\\xf9\\xc7?\\xfe1\\xdb\\xf5e\\xdc\\xb8q\\xd5\\x1a\\x8c\\x9a\\x1e\\xcd\\xa3\\x8f>\\x1a\\xf6\\xde{\\xefl9\\xb2\\x96\\xbf\\xb4\\x96\\xab\\x85Z`\\xa0\\xb5\\x0c\\x10\\x00\\x04\\x00\\x01 \\x14j\\xb80\\x90\\x04\\x03\\xb3f\\xcd\\xaai\\xf4\\xa9\\xffa?\\xf9\\xe4\\x93I0\\xd4h\\xd39{\\xf6\\xec\\xfa\\x0fb\\x07\\xcf ^\\xf6\\xbf\\xe7\\x9e{f\\xcdP\\xa3\\xec\\xf9\\xbd\\xd6\\x06%\\xf5U\\xdf\\x14\\x19 \\x00\\x08\\x00\\x02@\\xf8\\xd3ta\\xa0\\xf6\\x0c\\xec\\xba\\xeb\\xaea\\xe9\\xd2\\xa5\\x1d\\x8c0y\\xbft|\\xdbQ\\x8aMR\\x7f\\xcfi\\xf8\\xf0\\xe1>\\x16\\xb0\\xc1)\\xf0\\xcb_\\xfe2\\x8c\\x1c92k~\\xfa\\xcb\\x99\\xc7\\t\\xa3\\x18\\xc0@3\\x18 \\x00\\x08\\x00\\x02@\\xf8\\xd3xa\\xa0\\xf6\\x0c\\xcc\\x981\\xa3\\xc1\\xf8\\xe1\\xd7\\x9aQ\\x81\\xe7\\x9e{\\xae\\xf6\\x0c\\r\\xb4\\xa9\\xda}\\xf7\\xdd\\xc3\\xe3\\x8f?\\xde\\x8crf\\xf3\\x1c7\\xdcpC\\x181bD\\xf6\\xec\\x0c\\x94=\\xbf/\\x14b\\x00\\x03e\\x18 \\x00\\x08\\x00\\x02@\\xf8\\xd3|a\\xa0\\xd6\\x0c\\xc4\\x7f}\\xed\\xcf\\'`d\\x93\\xaa:p\\xa2\\xcf?\\xff|\\xad\\x19*\\xd38\\xf5\\xf5\\xd81c\\xc6\\x84(C|\\xad\\xb9\\x02S\\xa7N\\xc5\\x8c\\xbd\\x07\\x03\\x18\\xc0@\\x07\\x18 \\x00\\x08\\x00\\x02\\xa0\\x03\\x13\\xaf\\xaf\\x06\\xd2\\xdf\\xb1\\xb8\\x18(\\xc7\\xc0\\x84\\t\\x13\\xd6\\x9c6<\\xa2\\xa5\\x15X\\xb2d\\x89&\\xee\\xc5\\xbd\\xe4\\x98c\\x8e\\xf1v\\x94>h{\\xe2\\x89\\'\\xc2q\\xc7\\x1d\\x87\\x17\\xbd\\x07\\x060\\x80\\x81\\x0e1@\\x00\\x10\\x00\\x04@\\x87&\\x9f\\x90W.\\xe4\\xa9\\x97z\\xf5\\xc6\\xc0\\xa2E\\x8b\\xfa\\x88\\x1b\\xfe\\xaa\\x1d\\x15\\x88\\xef\\xe3\\xeem|r\\xfc\\xf9\\x11G\\x1c\\x11\\x9e}\\xf6\\xd9v\\x94\\xbeV\\xafq\\xcb-\\xb7\\x84\\xf8i\\x1d92\\xe1\\x9c\\xeda\\x18\\xc0@U\\x18 \\x00\\x08\\x00\\x02\\x80\\x00\\xd0\\x8ca\\xa0\\xb6\\x0c\\xec\\xb0\\xc3\\x0e\\xe1\\x85\\x17^\\xa8U\\x08J\\xf1`\\x7f\\xfa\\xd3\\x9f\\xd6\\x96\\xa1V5d\\x1f\\xfc\\xe0\\x07\\xdd\\x13\\xe0E\\xd8\\xe3\\xc7s~\\xf1\\x8b_\\xc4\\x88\\xbd\\x06\\x03\\x18\\xc0@\\x05\\x18 \\x00\\x08\\x00\\x02\\xa0\\x02\\x13\\xb1U\\r\\xa8\\xe7e\\x9bSg\\xe0\\xa4\\x93NJ1O\\xd7\\xee\\x9c\\x16.\\\\\\xa8\\xa9\\xeba/\\x89\\x1fmw\\xef\\xbd\\xf7\\xd6n<\\x9by\\xc0\\xd7^{\\xad\\xbb\\xfc\\xf7\\xc0F\\xeak\\xb3\\xf3\\xd3\\x7f`\\xa0\\xba\\x0c\\x10\\x00\\x04\\x00\\x01`c\\xd6\\xb8c\\xa0\\xb6\\x0c\\xcc\\x993\\xa7\\x99Y\\xc5s5X\\x81\\xd9\\xb3g\\xd7\\x96\\xa1V7\\xa9\\xc3\\x86\\r\\x0b\\xd3\\xa7O\\x0f+V\\xach\\xb0\\xba\\xf5\\xfc\\xb5\\xf8\\xb6\\x90\\xb1c\\xc7\\xe2\\xc2\\xfe\\x82\\x01\\x0c`\\xa0b\\x0c\\x10\\x00\\x04\\x00\\x01P\\xb1I\\xd9\\xeaf\\xd4\\xf3W\\xd7\\xc8\\x1a\\x9b\\xf2c\\xf3\\x9b\\xdf\\xfc\\xa6\\x9e\\xe9(\\xb1\\xa3\\xfe\\xf2\\x97\\xbf\\xac\\xc1[\\xc3^2n\\xdc\\xb8\\xf0\\xd0C\\x0f%6\\xf2\\xab\\x9fN<\\xc7SO=5\\x0c\\x192\\x04\\x13k`\\xc2\\x9a_~\\xcdW35\\xc3\\xc0\\xc0\\x19 \\x00\\x08\\x00\\x02\\xc0\\x06\\xadI\\xc3@-\\x19\\x88\\x9f\\x1f\\x9e\\xdb\\xbf\\xaa\\xae\\x1e\\xb7\\xaa\\xf1\\x93\\xa3\\x8f>\\xba\\x96\\x0c\\xb5\\xbb\\x91\\xdcb\\x8b-\\xc2\\xd7\\xbf\\xfe\\xf5\\x10\\xdf\\x13\\x9f\\xda\\xd7\\x03\\x0f<\\x10N>\\xf9\\xe40t\\xe8P,\\xd8S0\\x80\\x01\\x0cT\\x98\\x01\\x02\\x80\\x00 \\x00*<A\\xdb\\xdd\\x9cz\\xbd\\x81[U5l_\\r\\xe3g\\xae\\xfb\\xaaF\\x05\\xde\\xfb\\xde\\xf7j\\xf6J\\xec%\\xbb\\xec\\xb2K\\x88o_Y\\xbati5\\x06p\\x00Gq\\xd7]w\\x85O\\x7f\\xfa\\xd3a\\xf0\\xe0\\xc1\\x18(\\xc1\\x80\\xbd\\xa2}{\\x85Z\\xab5\\x06Vf\\x80\\x00 \\x00\\x08\\x00\\x1b\\xb6\\xa6\\r\\x03\\xb5d\\xe0S\\x9f\\xfa\\xd4\\x00b\\x8b_mV\\x05\\xfe\\xe7\\x7f\\xfe\\xa7\\x96\\xfcT\\xa1!\\x1c9rd\\xb8\\xe8\\xa2\\x8b\\xc23\\xcf<\\xd3\\xac\\xe1h\\xcb\\xf3<\\xf1\\xc4\\x13a\\xc6\\x8c\\x19a\\xdf}\\xf75\\xf6\\xf6\\x0f\\x0c`\\x00\\x035c\\x80\\x00 \\x00\\x08\\x80\\x9aM\\xda*4\\xad\\x8eae\\x93\\xaa\\x1e\\x9d\\xa9\\xc7\\x19g\\x9c\\xd1\\x96\\xb0\\xe3E\\xfa\\xae\\xc0\\xc5\\x17_\\xac\\xf9\\x1b\\xe0>\\xb2\\xed\\xb6\\xdb\\x86\\xc9\\x93\\'\\x87\\x9f\\xfd\\xecg}\\x17\\xbb\\x83\\x7f\\xfb\\xd4SO\\x85\\xb9s\\xe7\\x86O~\\xf2\\x93!\\xde\\xd8\\xd0\\xba\\xd7\\x99uO\\xdd\\xd5\\x1d\\x03\\x18\\x18(\\x03\\x04\\x00\\x01@\\x00\\x0c\\xb0q\\x1b\\xe8$\\xf4\\xfb\\x16r\\x0c4\\xc6\\xc0\\x94)S:\\x18\\x87\\xbctw\\x05\\x8e8\\xe2\\x08a\\xb0\\x89\\xfb\\xc8^{\\xed\\x15\"\\xdb\\xf1.\\xfa\\x9d\\xfe\\x8a7\\xf4\\xbb\\xf4\\xd2K\\xc3\\x91G\\x1e\\xe9\\xbd\\xfdM\\x1cck~ck\\xbe\\xba\\xa9\\x1b\\x06\\x9a\\xc3\\x00\\x01@\\x00\\x10\\x006u\\xcd;\\x06j\\xc9\\xc0\\xb7\\xbe\\xf5\\xadN\\xe7\\xa3\\xec_\\xffO\\x7f\\xfa\\x93\\xf7~\\xb7p\\xfd\\xd8q\\xc7\\x1dC|\\xab\\xcb\\xacY\\xb3B\\xbc\\xc9^+oz\\x19\\xefG\\xf0\\xf3\\x9f\\xff\\xbc\\xeb\\xb5>\\xf7\\xb9\\xcf\\x85\\xddv\\xdb\\xad\\x96\\xeb\\x82\\x80\\xd0\\x9c\\x80\\xa0\\x8e\\xea\\x88\\x81t\\x19 \\x00\\x08\\x00\\x02\\xa0\\x85\\xcd\\x9b\\xc53\\xdd\\xc5\\xd3\\xd8v~l\\xa7N\\x9d\\x9a}\\x00\\xeft\\x01.\\xbc\\xf0B!\\xb1\\x8d{\\xc8\\xf0\\xe1\\xc3C\\xbc\\xf9e\\x0c\\xe8\\xd3\\xa7O\\x0f\\xd7_\\x7f}\\x887\\xe1\\x8b\\x1f\\x87\\x19/\\xd1\\xef\\xeb+~\\xf2\\xc0\\xef\\x7f\\xff\\xfb\\xf0_\\xff\\xf5_a\\xd1\\xa2E\\xe1{\\xdf\\xfb^\\xd7\\x95\\x06\\xf1\\x06~\\xa3G\\x8fvY\\x7f\\x1b\\xc7\\xd1\\xfe\\xd1\\xf9\\xfd\\xc3\\x18\\x18\\x83\\x9c\\x19 \\x00\\x08\\x00\\x02\\xc0\\xa6\\xaf\\x81\\xc7@-\\x198\\xf7\\xdcs\\xfb\\xca;\\xfe\\xae\\xc5\\x15\\x88\\xff\\x1a=j\\xd4\\xa8Z\\xb2\\x93j\\xe3\\x17\\xdf\\x9b\\xbf\\xcd6\\xdb\\x84\\xed\\xb6\\xdb.l\\xbf\\xfd\\xf6!~:C\\xfc\\xf6\\x9e}a\\'U\\xe6\\x9d\\x17\\xb61P\\x9e\\x01\\x02\\x80\\x00 \\x00\\x84?\\r<\\x06j\\xc9\\xc0\\xa4I\\x93Z\\x1cq=}_\\x15\\xb8\\xf1\\xc6\\x1bk\\xc9\\x8df\\xb1|\\xb3\\xa8fj\\x86\\x01\\x0c` \\x1d\\x06\\x08\\x00\\x02\\x80\\x00\\x10\\xfe4\\xf1\\x18\\xa8%\\x03\\xc7\\x1e{l_\\xf9\\xd4\\xdf\\xb5\\xb8\\x02\\x07\\x1f|p-\\xb9\\xd1\\xc4\\xa6\\xd3\\xc4\\x1aKc\\x89\\x01\\x0c`\\xa0<\\x03\\x04\\x00\\x01@\\x00\\x08\\x7f\\x9ax\\x0c\\xd4\\x92\\x81}\\xf6\\xd9\\xa7\\xc5\\x11\\xd7\\xd3\\xf7V\\x81\\x9bo\\xbe\\xb9\\x96\\xcch\\x14\\xcb7\\x8aj\\xa6f\\x18\\xc0\\x00\\x06\\xd2b\\x80\\x00 \\x00\\x08\\x00\\xe1O#\\x8f\\x81Z20d\\xc8\\x90\\xf0\\x97\\xbf\\xfc\\xa5\\xb7\\x8c\\xea\\xe7-\\xaa\\xc0\\xf2\\xe5\\xcb\\xc3\\x01\\x07\\x1cPKf4\\xb1i5\\xb1\\xc6\\xd3xb\\x00\\x03\\x18(\\xcf\\x00\\x01@\\x00\\x10\\x00\\xc2\\x9fF\\x1e\\x03\\xb5e\\xe0\\x8e;\\xeehQ\\xcc\\xf5\\xb4\\xbdU\\xe0\\x92K.\\xa9-/\\x1a\\xc5\\xf2\\x8d\\xa2\\x9a\\xa9\\x19\\x060\\x80\\x81\\xb4\\x18 \\x00\\x08\\x00\\x02@\\xf8\\xd3\\xccc\\xa0\\xb6\\x0c\\x9c\\x7f\\xfe\\xf9\\xbd\\xe5T?oA\\x05\\x1e}\\xf4\\xd1\\xae\\xbb\\xcck\\x06\\xd3j\\x06\\x8d\\xa7\\xf1\\xc4\\x00\\x060\\x90\\x0f\\x03\\x04\\x00\\x01@\\x00\\x08\\x7f\\xb5\\r\\x7f6\\xab|6\\xab\\xde\\xc6\\xfaC\\x1f\\xfaP\\x0bb\\xae\\xa7\\xec\\xa9\\x02/\\xbc\\xf0B\\x18;v\\xac\\xf5\\xc2\\x9e\\x81\\x01\\x0c`\\x00\\x03\\x18\\xa81\\x03\\x04\\x00\\x01@\\x00\\xd4x\\x02\\xf7\\x16\\x8a\\xfc\\\\0\\xce\\x89\\x81G\\x1ey\\xa4\\xa7\\xbc\\xeagM\\xae\\xc0\\xb4i\\xd34|\\xf6\\x0b\\x0c`\\x00\\x03\\x18\\xc0@\\xcd\\x19 \\x00\\x08\\x00\\x02\\xa0\\xe6\\x938\\xa7\\xa0\\xe7\\\\\\x89\\x8d\\x9e\\x18\\xf8\\xe67\\xbf\\xd9\\xe4\\xa8\\xeb\\xe9V\\xad\\xc0}\\xf7\\xdd\\x17\\x86\\r\\x1b\\xa6\\xe9\\xb3_`\\x00\\x03\\x18\\xc0\\x00\\x06j\\xce\\x00\\x01@\\x00\\x10\\x005\\x9f\\xc4=\\x05\"?\\x13\\x94sb`\\xe4\\xc8\\x91a\\xe9\\xd2\\xa5\\xabfV\\xff\\xdf\\xa4\\n\\xfc\\xe9O\\x7f\\n\\xb1\\xc691\\xe5\\\\\\xad\\xa1\\x18\\xc0\\x00\\x060\\x90*\\x03\\x04\\x00\\x01@\\x00\\x10\\x00\\x1a{\\x0c\\xd4\\x9e\\x81\\xef\\x7f\\xff\\xfbM\\x8a\\xbb\\x9e\\xe6\\xe5\\x15X\\xbcxq\\x183fL\\xed\\xf9H\\xb5\\x89s^\\x02\\n\\x060\\x80\\x01\\x0c\\x94e\\x80\\x00 \\x00\\x08\\x00\\xe1Os\\x8f\\x81\\xda30j\\xd4(W\\x01\\xbc<\\xb97\\xe1\\xbf\\xe3M\\xff>\\xfe\\xf1\\x8f\\xd7\\x9e\\x8d\\xb2\\x8d\\x91\\xc7k\\xa61\\x80\\x01\\x0c` e\\x06\\x08\\x00\\x02\\x80\\x00\\x10\\xfe4\\xf8\\x18H\\x82\\x81\\x8b/\\xbe\\xb8\\t\\xb1\\xd7S\\xc4\\n\\xc4\\xf0\\x7f\\xca)\\xa7$\\xc1E\\xcaM\\x9cs\\x13R0\\x80\\x01\\x0c`\\xa0,\\x03\\x04\\x00\\x01@\\x00\\x08\\x7f\\x9a|\\x0c$\\xc1\\xc0\\xd6[o\\x1d\\xe2\\xe7\\xd4\\xfb\\x1aX\\x05b\\xf8?\\xf9\\xe4\\x93\\x93`\\xa2lS\\xe4\\xf1\\x1ai\\x0c`\\x00\\x03\\x18H\\x9d\\x01\\x02\\x80\\x00 \\x00\\x84?\\x8d>\\x06\\x92a\\xe0\\xa8\\xa3\\x8e\\n+V\\xac\\x18X\\x02\\xce\\xf8\\xb7\\x97/_\\x1eN<\\xf1\\xc4dxH\\xbd\\x89s~\\x82\\n\\x060\\x80\\x01\\x0c\\x94e\\x80\\x00 \\x00\\x08\\x00\\xe1O\\xb3\\x8f\\x81\\xa4\\x18\\xb8\\xe8\\xa2\\x8b2\\x8e\\xf0\\x8d\\x9fz\\xbc\\xe1\\xdfq\\xc7\\x1d\\x97\\x14\\x0be\\x9b\"\\x8f\\xd7Hc\\x00\\x03\\x18\\xc0@\\xea\\x0c\\x10\\x00\\x04\\x00\\x01 \\xfci\\xf81\\x90\\x14\\x03C\\x86\\x0c\\t7\\xddtS\\xe3I8\\xc3\\xdf|\\xe4\\x91G\\xc2\\xfb\\xdf\\xff\\xfe\\xa48H\\xbd\\x81s~B\\n\\x060\\x80\\x01\\x0c4\\xc2\\x00\\x01@\\x00\\x10\\x00\\xc2\\x9f\\xa6\\x1f\\x03\\xc910b\\xc4\\x88p\\xdf}\\xf7e\\x18\\xe5\\xcb\\x9f\\xf2]w\\xdd\\x15\\xde\\xf7\\xbe\\xf7%\\xc7@#M\\x91\\xdf\\xd1Lc\\x00\\x03\\x18\\xc0@\\xea\\x0c\\x10\\x00\\x04\\x00\\x01 \\xfci\\xfc1\\x90$\\x03;\\xed\\xb4Sx\\xf0\\xc1\\x07\\xcb\\'\\xe2L~#\\xde+!\\xbe]b\\xd8\\xb0aI\\x8e\\x7f\\xea\\r\\x9c\\xf3\\x13R0\\x80\\x01\\x0c`\\xa0\\x11\\x06\\x08\\x00\\x02\\x80\\x00\\x10\\xfe4\\xff\\x18H\\x96\\x81\\xf8/\\xdb?\\xff\\xf9\\xcf3\\x89\\xf4\\xfd?\\xcd\\xdf\\xff\\xfe\\xf7\\xe1\\xf0\\xc3\\x0fOv\\xdc\\x1bi\\x88\\xfc\\x8eF\\x1a\\x03\\x18\\xc0\\x00\\x06r`\\x80\\x00 \\x00\\x08\\x00\\xe1O\\x08\\xc0@\\xd2\\x0c\\xc4\\x8f\\x07\\\\\\xb4hQ\\xff\\xd3q\\xe2\\x8f\\xbc\\xea\\xaa\\xab\\xc2\\xb6\\xdbn\\x9b\\xf4\\x98\\xe7\\xd0\\xc09GA\\x05\\x03\\x18\\xc0\\x00\\x06\\x1aa\\x80\\x00 \\x00\\x08\\x00\\xe1O\\x10\\xc0@\\xf2\\x0c\\xc4\\xcb\\xdcg\\xce\\x9c\\x99x\\xb4\\xef\\xfb\\xf4~\\xfd\\xeb_\\x87q\\xe3\\xc6%?\\xd6\\x8d4C~G\\x13\\x8d\\x01\\x0c`\\x00\\x03\\xb90@\\x00\\x10\\x00\\x04\\x80\\xf0\\'\\x10` \\x1b\\x06\\x8e=\\xf6\\xd8\\xf0\\xe4\\x93O\\xf6\\x9d\\x94\\x13\\xfb\\xdb\\xa7\\x9f~:\\x9cy\\xe6\\x99a\\xe8\\xd0\\xa1\\xd9\\x8cs.M\\x9c\\xf3\\x14X0\\x80\\x01\\x0c`\\xa0,\\x03\\x04\\x00\\x01@\\x00\\x08\\x7fB\\x01\\x06\\xb2b`\\x97]v\\t\\xb7\\xdcrKb1\\x7f\\xf5\\xd3y\\xee\\xb9\\xe7\\xc2\\xc5\\x17_\\xec\\x0e\\xff\\xe6wV\\xf3\\xbbl#\\xec\\xf1\\xc2\\x13\\x060\\x90\\x1b\\x03\\x04\\x00\\x01@\\x00h\\x0e5\\x87\\x18\\xc8\\x92\\x81\\x8f}\\xecc\\xe17\\xbf\\xf9\\xcd\\xea\\xc9\\xb9\\xe6?y\\xf6\\xd9g\\xc3\\xf4\\xe9\\xd3\\x05\\x7f\\xf3:\\xcby\\x9d[#\\xef|\\x85W\\x0c`\\xa0,\\x03\\x04\\x00\\x01@\\x00h\\x125\\x89\\x18\\xc8\\x96\\x81xo\\x80\\xb3\\xcf>;<\\xfe\\xf8\\xe35\\x8f\\xfd!\\xc4;\\xfbO\\x992%l\\xbf\\xfd\\xf6\\xd9\\x8eg\\xd9&\\xc8\\xe35\\xce\\x18\\xc0\\x00\\x060\\x90\\x1b\\x03\\x04\\x00\\x01@\\x00\\x08\\x7f\\xc2\\x02\\x06\\xb2g`\\xcb-\\xb7\\x0c\\x93&M\\xaa\\xdd\\x15\\x01\\xcb\\x96-\\x0b\\x0b\\x16,\\x08G\\x1f}t\\x18<xp\\xf6\\xe3\\x98[\\x13\\xe7|\\x05\\x17\\x0c`\\x00\\x03\\x18(\\xcb\\x00\\x01@\\x00\\x10\\x00\\xc2\\x9f\\xd0\\x80\\x01\\x0c\\xbc\\xc8@\\x0c\\xd1\\x1f\\xff\\xf8\\xc7\\xc3\\xf5\\xd7_\\x1f\\x96,YR\\xc9\\xab\\x02\\x96/_\\x1en\\xbf\\xfd\\xf6\\xae\\x1b\\xfb\\xed\\xb4\\xd3N\\xc6\\xce\\xfc\\xc5\\x00\\x060\\x80\\x01\\x0c`\\xa0\\xdf\\x0c\\x10\\x00\\x04\\x00\\x01`\\xc1\\xe8\\xf7\\x82Q\\xd60z<+]g\\x06\\xb6\\xddv\\xdb0a\\xc2\\x84\\xf0\\xa3\\x1f\\xfd\\xa8\\xe32\\xe0\\x99g\\x9e\\t\\xf3\\xe7\\xcf\\x0f\\x9f\\xfd\\xecg]\\xe2o\\xcd\\xb6fc\\x00\\x03\\x18\\xc0\\x00\\x06\\x1af\\x80\\x00 \\x00\\x08\\x00\\x0bH\\xc3\\x0bH\\x9d\\xc3\\x9dc\\'\\'\\xca0\\x10\\xdf\"p\\xc4\\x11G\\x84\\xf3\\xcf??\\xdc}\\xf7\\xdd-\\x17\\x02\\x0f=\\xf4P\\xb8\\xee\\xba\\xeb\\xc2Yg\\x9d\\x15\\xc6\\x8c\\x19\\x13\\x86\\x0c\\x19b\\x9eZ\\xab1\\x80\\x01\\x0c`\\x00\\x03\\x18\\x180\\x03\\x04\\x00\\x01@\\x00XH\\x06\\xbc\\x90\\x94\\tR\\x1e+x\\xa7\\xc0@\\x0c\\xe4\\xfb\\xec\\xb3O\\xf8\\xc4\\'>\\x11\\xce=\\xf7\\xdc0w\\xee\\xdc\\xf0\\xe3\\x1f\\xff8\\xfc\\xeaW\\xbf\\xea\\xba\\xa1`\\xbcL\\xbf\\xb7\\xaf\\xa5K\\x97v=\\xe6\\x7f\\xfe\\xe7\\x7f\\xc2]w\\xdd\\xd5\\x15\\xf4\\xe3]\\xfb\\'N\\x9c\\x18\\x0e=\\xf4\\xd0\\xb0\\xddv\\xdb\\x99\\x93\\xd6e\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06Z\\xc2\\x00\\x01@\\x00\\x10\\x00\\x16\\x97\\x96,.)\\x84<\\xe7@V4\\xca@\\xbc\\x97\\xc06\\xdbl\\xd3\\x15\\xe6\\xe3]\\xf9\\xdf\\xfb\\xde\\xf7v},\\xdf\\xd6[om\\xbeYs1\\x80\\x01\\x0c`\\x00\\x03\\x18\\xe8\\x18\\x03\\x04\\x00\\x01@\\x00X\\x80:\\xb6\\x005\\x1a\\xae\\xfc\\x9e`\\x8e\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xf2\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00\\x10\\x00\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\x06\\x0c\\x10\\x00\\x04\\x00\\x01\\x90\\xc1DgG\\xcb\\xdbQ5S3\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xd4\\x18 \\x00\\x08\\x00\\x02\\x80\\x00`{1\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x0c\\x18 \\x00\\x08\\x00\\x02 \\x83\\x89\\x9e\\x9a\\xb9t>l<\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06\\xca3@\\x00\\x10\\x00\\x04\\x00\\x01\\xc0\\xf6b\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x190@\\x00\\x10\\x00\\x04@\\x06\\x13\\x9d\\x1d-oG\\xd5L\\xcd0\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06Rc\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xed\\xc5\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x062`\\x80\\x00 \\x00\\x08\\x80\\x0c&zj\\xe6\\xd2\\xf9\\xb0\\xf1\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18(\\xcf\\x00\\x01@\\x00\\x10\\x00\\x04\\x00\\xdb\\x8b\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0cd\\xc0\\x00\\x01@\\x00\\x10\\x00\\x19Ltv\\xb4\\xbc\\x1dU35\\xc3\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18H\\x8d\\x01\\x02\\x80\\x00 \\x00\\x08\\x00\\xb6\\x17\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc8\\x80\\x01\\x02\\x80\\x00 \\x002\\x98\\xe8\\xa9\\x99K\\xe7\\xc3\\xc6c\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0<\\x03\\x04\\x00\\x01@\\x00\\x10\\x00l/\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x90\\x01\\x03\\x04\\x00\\x01@\\x00d0\\xd1\\xd9\\xd1\\xf2vT\\xcd\\xd4\\x0c\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` 5\\x06\\x08\\x00\\x02\\x80\\x00 \\x00\\xd8^\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` \\x03\\x06\\x08\\x00\\x02\\x80\\x00\\xc8`\\xa2\\xa7f.\\x9d\\x0f\\x1b\\x8f\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xf2\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00\\xb0\\xbd\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\x06\\x0c\\x10\\x00\\x04\\x00\\x01\\x90\\xc1DgG\\xcb\\xdbQ5S3\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xd4\\x18 \\x00\\x08\\x00\\x02\\x80\\x00`{1\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x0c\\x18 \\x00\\x08\\x00\\x02 \\x83\\x89\\x9e\\x9a\\xb9t>l<\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06\\xca3@\\x00\\x10\\x00\\x04\\x00\\x01\\xc0\\xf6b\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x190@\\x00\\x10\\x00\\x04@\\x06\\x13\\x9d\\x1d-oG\\xd5L\\xcd0\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06Rc\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xed\\xc5\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x062`\\x80\\x00 \\x00\\x08\\x80\\x0c&zj\\xe6\\xd2\\xf9\\xb0\\xf1\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18(\\xcf\\x00\\x01@\\x00\\x10\\x00\\x04\\x00\\xdb\\x8b\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0cd\\xc0\\x00\\x01@\\x00\\x10\\x00\\x19Ltv\\xb4\\xbc\\x1dU35\\xc3\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18H\\x8d\\x01\\x02\\x80\\x00 \\x00\\x08\\x00\\xb6\\x17\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc8\\x80\\x01\\x02\\x80\\x00 \\x002\\x98\\xe8\\xa9\\x99K\\xe7\\xc3\\xc6c\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0<\\x03\\x04\\x00\\x01@\\x00\\x10\\x00l/\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x90\\x01\\x03\\x04\\x00\\x01@\\x00d0\\xd1\\xd9\\xd1\\xf2vT\\xcd\\xd4\\x0c\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` 5\\x06\\x08\\x00\\x02\\x80\\x00 \\x00\\xd8^\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` \\x03\\x06\\x08\\x00\\x02\\x80\\x00\\xc8`\\xa2\\xa7f.\\x9d\\x0f\\x1b\\x8f\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xf2\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00\\xb0\\xbd\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\x06\\x0c\\x10\\x00\\x04\\x00\\x01\\x90\\xc1DgG\\xcb\\xdbQ5S3\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xd4\\x18 \\x00\\x08\\x00\\x02\\x80\\x00`{1\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x0c\\x18 \\x00\\x08\\x00\\x02 \\x83\\x89\\x9e\\x9a\\xb9t>l<\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06\\xca3@\\x00\\x10\\x00\\x04\\x00\\x01\\xc0\\xf6b\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x190@\\x00\\x10\\x00\\x04@\\x06\\x13\\x9d\\x1d-oG\\xd5L\\xcd0\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06Rc\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xed\\xc5\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x062`\\x80\\x00 \\x00\\x08\\x80\\x0c&zj\\xe6\\xd2\\xf9\\xb0\\xf1\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18(\\xcf\\x00\\x01@\\x00\\x10\\x00\\x04\\x00\\xdb\\x8b\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0cd\\xc0\\x00\\x01@\\x00\\x10\\x00\\x19Ltv\\xb4\\xbc\\x1dU35\\xc3\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18H\\x8d\\x01\\x02\\x80\\x00 \\x00\\x08\\x00\\xb6\\x17\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc8\\x80\\x01\\x02\\x80\\x00 \\x002\\x98\\xe8\\xa9\\x99K\\xe7\\xc3\\xc6c\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0<\\x03\\x04\\x00\\x01@\\x00\\x10\\x00l/\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x90\\x01\\x03\\x04\\x00\\x01@\\x00d0\\xd1\\xd9\\xd1\\xf2vT\\xcd\\xd4\\x0c\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` 5\\x06\\x08\\x00\\x02\\x80\\x00 \\x00\\xd8^\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` \\x03\\x06\\x08\\x00\\x02\\x80\\x00\\xc8`\\xa2\\xa7f.\\x9d\\x0f\\x1b\\x8f\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xf2\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00\\xb0\\xbd\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\x06\\x0c\\x10\\x00\\x04\\x00\\x01\\x90\\xc1DgG\\xcb\\xdbQ5S3\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xd4\\x18 \\x00\\x08\\x00\\x02\\x80\\x00`{1\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x0c\\x18 \\x00\\x08\\x00\\x02 \\x83\\x89\\x9e\\x9a\\xb9t>l<\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06\\xca3@\\x00\\x10\\x00\\x04\\x00\\x01\\xc0\\xf6b\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x190@\\x00\\x10\\x00\\x04@\\x06\\x13\\x9d\\x1d-oG\\xd5L\\xcd0\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06Rc\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xed\\xc5\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x062`\\x80\\x00 \\x00\\x08\\x80\\x0c&zj\\xe6\\xd2\\xf9\\xb0\\xf1\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18(\\xcf\\x00\\x01@\\x00\\x10\\x00\\x04\\x00\\xdb\\x8b\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0cd\\xc0\\x00\\x01@\\x00\\x10\\x00\\x19Ltv\\xb4\\xbc\\x1dU35\\xc3\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18H\\x8d\\x01\\x02\\x80\\x00 \\x00\\x08\\x00\\xb6\\x17\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc8\\x80\\x01\\x02\\x80\\x00 \\x002\\x98\\xe8\\xa9\\x99K\\xe7\\xc3\\xc6c\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0<\\x03\\x04\\x00\\x01@\\x00\\x10\\x00l/\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x90\\x01\\x03\\x04\\x00\\x01@\\x00d0\\xd1\\xd9\\xd1\\xf2vT\\xcd\\xd4\\x0c\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` 5\\x06\\x08\\x00\\x02\\x80\\x00 \\x00\\xd8^\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` \\x03\\x06\\x08\\x00\\x02\\x80\\x00\\xc8`\\xa2\\xa7f.\\x9d\\x0f\\x1b\\x8f\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xf2\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00\\xb0\\xbd\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\x06\\x0c\\x10\\x00\\x04\\x00\\x01\\x90\\xc1DgG\\xcb\\xdbQ5S3\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xd4\\x18 \\x00\\x08\\x00\\x02\\x80\\x00`{1\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x0c\\x18 \\x00\\x08\\x00\\x02 \\x83\\x89\\x9e\\x9a\\xb9t>l<\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06\\xca3@\\x00\\x10\\x00\\x04\\x00\\x01\\xc0\\xf6b\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x190@\\x00\\x10\\x00\\x04@\\x06\\x13\\x9d\\x1d-oG\\xd5L\\xcd0\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06Rc\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xed\\xc5\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x062`\\x80\\x00 \\x00\\x08\\x80\\x0c&zj\\xe6\\xd2\\xf9\\xb0\\xf1\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18(\\xcf\\x00\\x01@\\x00\\x10\\x00\\x04\\x00\\xdb\\x8b\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0cd\\xc0\\x00\\x01@\\x00\\x10\\x00\\x19Ltv\\xb4\\xbc\\x1dU35\\xc3\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18H\\x8d\\x01\\x02\\x80\\x00 \\x00\\x08\\x00\\xb6\\x17\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc8\\x80\\x01\\x02\\x80\\x00 \\x002\\x98\\xe8\\xa9\\x99K\\xe7\\xc3\\xc6c\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0<\\x03\\x04\\x00\\x01@\\x00\\x10\\x00l/\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x90\\x01\\x03\\x04\\x00\\x01@\\x00d0\\xd1\\xd9\\xd1\\xf2vT\\xcd\\xd4\\x0c\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` 5\\x06\\x08\\x00\\x02\\x80\\x00 \\x00\\xd8^\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` \\x03\\x06\\x08\\x00\\x02\\x80\\x00\\xc8`\\xa2\\xa7f.\\x9d\\x0f\\x1b\\x8f\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xf2\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00\\xb0\\xbd\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\x06\\x0c\\x10\\x00\\x04\\x00\\x01\\x90\\xc1DgG\\xcb\\xdbQ5S3\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xd4\\x18 \\x00\\x08\\x00\\x02\\x80\\x00`{1\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x0c\\x18 \\x00\\x08\\x00\\x02 \\x83\\x89\\x9e\\x9a\\xb9t>l<\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06\\xca3@\\x00\\x10\\x00\\x04\\x00\\x01\\xc0\\xf6b\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x190@\\x00\\x10\\x00\\x04@\\x06\\x13\\x9d\\x1d-oG\\xd5L\\xcd0\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06Rc\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xed\\xc5\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x062`\\x80\\x00 \\x00\\x08\\x80\\x0c&zj\\xe6\\xd2\\xf9\\xb0\\xf1\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18(\\xcf\\x00\\x01@\\x00\\x10\\x00\\x04\\x00\\xdb\\x8b\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0cd\\xc0\\x00\\x01@\\x00\\x10\\x00\\x19Ltv\\xb4\\xbc\\x1dU35\\xc3\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18H\\x8d\\x01\\x02\\x80\\x00 \\x00\\x08\\x00\\xb6\\x17\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc8\\x80\\x01\\x02\\x80\\x00 \\x002\\x98\\xe8\\xa9\\x99K\\xe7\\xc3\\xc6c\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0<\\x03\\x04\\x00\\x01@\\x00\\x10\\x00l/\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x90\\x01\\x03\\x04\\x00\\x01@\\x00d0\\xd1\\xd9\\xd1\\xf2vT\\xcd\\xd4\\x0c\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` 5\\x06\\x08\\x00\\x02\\x80\\x00 \\x00\\xd8^\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` \\x03\\x06\\x08\\x00\\x02\\x80\\x00\\xc8`\\xa2\\xa7f.\\x9d\\x0f\\x1b\\x8f\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xf2\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00\\xb0\\xbd\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\x06\\x0c\\x10\\x00\\x04\\x00\\x01\\x90\\xc1DgG\\xcb\\xdbQ5S3\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xd4\\x18 \\x00\\x08\\x00\\x02\\x80\\x00`{1\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x0c\\x18 \\x00\\x08\\x00\\x02 \\x83\\x89\\x9e\\x9a\\xb9t>l<\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06\\xca3@\\x00\\x10\\x00\\x04\\x00\\x01\\xc0\\xf6b\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x190@\\x00\\x10\\x00\\x04@\\x06\\x13\\x9d\\x1d-oG\\xd5L\\xcd0\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06Rc\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xed\\xc5\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x062`\\x80\\x00 \\x00\\x08\\x80\\x0c&zj\\xe6\\xd2\\xf9\\xb0\\xf1\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18(\\xcf\\x00\\x01@\\x00\\x10\\x00\\x04\\x00\\xdb\\x8b\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0cd\\xc0\\x00\\x01@\\x00\\x10\\x00\\x19Ltv\\xb4\\xbc\\x1dU35\\xc3\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18H\\x8d\\x01\\x02\\x80\\x00 \\x00\\x08\\x00\\xb6\\x17\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc8\\x80\\x01\\x02\\x80\\x00 \\x002\\x98\\xe8\\xa9\\x99K\\xe7\\xc3\\xc6c\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\xa0<\\x03\\x04\\x00\\x01@\\x00\\x10\\x00l/\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x90\\x01\\x03\\x04\\x00\\x01@\\x00d0\\xd1\\xd9\\xd1\\xf2vT\\xcd\\xd4\\x0c\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` 5\\x06\\x08\\x00\\x02\\x80\\x00 \\x00\\xd8^\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c` \\x03\\x06\\x08\\x00\\x02\\x80\\x00\\xc8`\\xa2\\xa7f.\\x9d\\x0f\\x1b\\x8f\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xf2\\x0c\\x10\\x00\\x04\\x00\\x01@\\x00\\xb0\\xbd\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0@\\x06\\x0c\\x10\\x00\\x04\\x00\\x01\\x90\\xc1DgG\\xcb\\xdbQ5S3\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\xd4\\x18 \\x00\\x08\\x00\\x02\\x80\\x00`{1\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x81\\x0c\\x18 \\x00\\x08\\x00\\x02 \\x83\\x89\\x9e\\x9a\\xb9t>l<\\x060\\x80\\x01\\x0c`\\x00\\x03\\x18\\xc0\\x00\\x06\\xca3@\\x00\\x10\\x00\\x04\\x00\\x01\\xc0\\xf6b\\x00\\x03\\x18\\xc0\\x00\\x060\\x80\\x01\\x0c`\\x00\\x03\\x190@\\x00\\xb4F\\x00\\xfc\\x7f\\x00\\x00\\x00\\xff\\xffT\\xaenr\\x00\\x00@\\x00IDAT\\xed\\xddm\\x8c\\x9d\\xe5y\\xe0q\\x8fMl\\x02\\xcc\\xda\\xc6\\xc62\\xd8\\x18\\x03\\xf1KlG\\xe2\\xc5\\x16R\\xbet\\xd9\\xa4\\x9b\\x97f\\x15@IPH\\xf1\\x07\\xb6\\x0b\\x96 $awK$`c\\xa4\\r\\xc9.I\\x90\\xa8\\x16\\xc5-\\xe9\\x06\\x12ba!\\xed\\xa6\\xc1\\xd46.\\xb6Aj\\xa4j\\xf3\\xa2\\xaa\\xea\\xc7\\xdd\\xa2m*E\\xaa\\xba\\xbb\\xc9\\x97\\xd2R={_f\\x06\\xc6\\x83=\\x1e\\x1f\\xdf\\xc7~\\xee\\xe7\\xfa\\x8d4\\x19;\\xf3\\xc2s\\xee\\xe7w?>\\xd7\\x7f\\xce\\x9cY\\xf0\\xdak\\xafu}y]\\xb4hQ\\xb7`\\xc1\\x82\\xe6_\\xb7m\\xdb\\xd6}\\xe0\\x03\\x1f\\xf0j\\r\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x11\\x0c\\xc4L5\\x84\\xd90f\\xdc\\xbe\\xcc\\xdbq\\x1c\\x0b\\xfat0\\x02\\x80h \\x9c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x02\\xc0x\\xbeQ/\\x00\\x8c\\xe1\\x11\\x07\\x1e\\x01\\xe0\\x82\\xe5\\x1f-\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\x18\\xdd\\x80\\x00 \\x004\\xf3\\x10\\x10\\x01`\\xf4\\x8d\\xee\"i\\xed\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`@\\x00\\x10\\x00\\x04\\x80\\x11~v\\xc6\\xc5\\xd3\\xc5\\x93\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06Z3 \\x00\\x08\\x00\\x02\\x80\\x00\\xe0\\tT\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12l\\xf4\\xd6\\xca\\xa4\\xe3U\\xd3\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xa8o@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1\\xd5\\xd3\\xfa\\xf5\\xd4\\x9aZS\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xd6\\x0c\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6zke\\xd2\\xf1\\xaa\\xe9\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xd47 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xeai\\xfdzjM\\xad)\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@k\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b\\xbd\\xb52\\xe9x\\xd5t\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xea\\x1b\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12lt\\xf5\\xb4~=\\xb5\\xa6\\xd6\\x94\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa05\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xdeZ\\x99t\\xbcj:\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xf5\\r\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6\\xbazZ\\xbf\\x9eZSk\\xca\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xd0\\x9a\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1Fo\\xadL:^5\\x9d\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xfa\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b]=\\xad_O\\xad\\xa95e\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18h\\xcd\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xb7V&\\x1d\\xaf\\x9a\\xce\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@}\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xae\\x9e\\xd6\\xaf\\xa7\\xd6\\xd4\\x9a2\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xb4f@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1[+\\x93\\x8eWMg\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xbe\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1FWO\\xeb\\xd7SkjM\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06Z3 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xad\\x95I\\xc7\\xab\\xa63\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0P\\xdf\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xab\\xa7\\xf5\\xeb\\xa95\\xb5\\xa6\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xad\\x19\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12l\\xf4\\xd6\\xca\\xa4\\xe3U\\xd3\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xa8o@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1\\xd5\\xd3\\xfa\\xf5\\xd4\\x9aZS\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xd6\\x0c\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6zke\\xd2\\xf1\\xaa\\xe9\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xd47 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xeai\\xfdzjM\\xad)\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@k\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b\\xbd\\xb52\\xe9x\\xd5t\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xea\\x1b\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12lt\\xf5\\xb4~=\\xb5\\xa6\\xd6\\x94\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa05\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xdeZ\\x99t\\xbcj:\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xf5\\r\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6\\xbazZ\\xbf\\x9eZSk\\xca\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xd0\\x9a\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1Fo\\xadL:^5\\x9d\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xfa\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b]=\\xad_O\\xad\\xa95e\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18h\\xcd\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xb7V&\\x1d\\xaf\\x9a\\xce\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@}\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xae\\x9e\\xd6\\xaf\\xa7\\xd6\\xd4\\x9a2\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xb4f@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1[+\\x93\\x8eWMg\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xbe\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1FWO\\xeb\\xd7SkjM\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06Z3 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xad\\x95I\\xc7\\xab\\xa63\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0P\\xdf\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xab\\xa7\\xf5\\xeb\\xa95\\xb5\\xa6\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xad\\x19\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12l\\xf4\\xd6\\xca\\xa4\\xe3U\\xd3\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xa8o@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1\\xd5\\xd3\\xfa\\xf5\\xd4\\x9aZS\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xd6\\x0c\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6zke\\xd2\\xf1\\xaa\\xe9\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xd47 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xeai\\xfdzjM\\xad)\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@k\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b\\xbd\\xb52\\xe9x\\xd5t\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xea\\x1b\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12lt\\xf5\\xb4~=\\xb5\\xa6\\xd6\\x94\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa05\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xdeZ\\x99t\\xbcj:\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xf5\\r\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6\\xbazZ\\xbf\\x9eZSk\\xca\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xd0\\x9a\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1Fo\\xadL:^5\\x9d\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xfa\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b]=\\xad_O\\xad\\xa95e\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18h\\xcd\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xb7V&\\x1d\\xaf\\x9a\\xce\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@}\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xae\\x9e\\xd6\\xaf\\xa7\\xd6\\xd4\\x9a2\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xb4f@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1[+\\x93\\x8eWMg\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xbe\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1FWO\\xeb\\xd7SkjM\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06Z3 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xad\\x95I\\xc7\\xab\\xa63\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0P\\xdf\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xab\\xa7\\xf5\\xeb\\xa95\\xb5\\xa6\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xad\\x19\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12l\\xf4\\xd6\\xca\\xa4\\xe3U\\xd3\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xa8o@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1\\xd5\\xd3\\xfa\\xf5\\xd4\\x9aZS\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xd6\\x0c\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6zke\\xd2\\xf1\\xaa\\xe9\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xd47 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xeai\\xfdzjM\\xad)\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@k\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b\\xbd\\xb52\\xe9x\\xd5t\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xea\\x1b\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12lt\\xf5\\xb4~=\\xb5\\xa6\\xd6\\x94\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa05\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xdeZ\\x99t\\xbcj:\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xf5\\r\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6\\xbazZ\\xbf\\x9eZSk\\xca\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xd0\\x9a\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1Fo\\xadL:^5\\x9d\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xfa\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b]=\\xad_O\\xad\\xa95e\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18h\\xcd\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xb7V&\\x1d\\xaf\\x9a\\xce\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@}\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xae\\x9e\\xd6\\xaf\\xa7\\xd6\\xd4\\x9a2\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xb4f@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1[+\\x93\\x8eWMg\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xbe\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1FWO\\xeb\\xd7SkjM\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06Z3 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xad\\x95I\\xc7\\xab\\xa63\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0P\\xdf\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xab\\xa7\\xf5\\xeb\\xa95\\xb5\\xa6\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xad\\x19\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12l\\xf4\\xd6\\xca\\xa4\\xe3U\\xd3\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xa8o@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1\\xd5\\xd3\\xfa\\xf5\\xd4\\x9aZS\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xd6\\x0c\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6zke\\xd2\\xf1\\xaa\\xe9\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xd47 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xeai\\xfdzjM\\xad)\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@k\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b\\xbd\\xb52\\xe9x\\xd5t\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xea\\x1b\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12lt\\xf5\\xb4~=\\xb5\\xa6\\xd6\\x94\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa05\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xdeZ\\x99t\\xbcj:\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xf5\\r\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6\\xbazZ\\xbf\\x9eZSk\\xca\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xd0\\x9a\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1Fo\\xadL:^5\\x9d\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xfa\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b]=\\xad_O\\xad\\xa95e\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18h\\xcd\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xb7V&\\x1d\\xaf\\x9a\\xce\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@}\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xae\\x9e\\xd6\\xaf\\xa7\\xd6\\xd4\\x9a2\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xb4f@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1[+\\x93\\x8eWMg\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xbe\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1FWO\\xeb\\xd7SkjM\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06Z3 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xad\\x95I\\xc7\\xab\\xa63\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0P\\xdf\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xab\\xa7\\xf5\\xeb\\xa95\\xb5\\xa6\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xad\\x19\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12l\\xf4\\xd6\\xca\\xa4\\xe3U\\xd3\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xa8o@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1\\xd5\\xd3\\xfa\\xf5\\xd4\\x9aZS\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xd6\\x0c\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6zke\\xd2\\xf1\\xaa\\xe9\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xd47 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xeai\\xfdzjM\\xad)\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@k\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b\\xbd\\xb52\\xe9x\\xd5t\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xea\\x1b\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12lt\\xf5\\xb4~=\\xb5\\xa6\\xd6\\x94\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa05\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xdeZ\\x99t\\xbcj:\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xf5\\r\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6\\xbazZ\\xbf\\x9eZSk\\xca\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xd0\\x9a\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1Fo\\xadL:^5\\x9d\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xfa\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b]=\\xad_O\\xad\\xa95e\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18h\\xcd\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xb7V&\\x1d\\xaf\\x9a\\xce\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@}\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xae\\x9e\\xd6\\xaf\\xa7\\xd6\\xd4\\x9a2\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xb4f@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1[+\\x93\\x8eWMg\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xbe\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1FWO\\xeb\\xd7SkjM\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06Z3 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xad\\x95I\\xc7\\xab\\xa63\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0P\\xdf\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xab\\xa7\\xf5\\xeb\\xa95\\xb5\\xa6\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xad\\x19\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12l\\xf4\\xd6\\xca\\xa4\\xe3U\\xd3\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xa8o@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1\\xd5\\xd3\\xfa\\xf5\\xd4\\x9aZS\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xd6\\x0c\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6zke\\xd2\\xf1\\xaa\\xe9\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xd47 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xeai\\xfdzjM\\xad)\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@k\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b\\xbd\\xb52\\xe9x\\xd5t\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xea\\x1b\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12lt\\xf5\\xb4~=\\xb5\\xa6\\xd6\\x94\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa05\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xdeZ\\x99t\\xbcj:\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xf5\\r\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6\\xbazZ\\xbf\\x9eZSk\\xca\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xd0\\x9a\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1Fo\\xadL:^5\\x9d\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xfa\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b]=\\xad_O\\xad\\xa95e\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18h\\xcd\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xb7V&\\x1d\\xaf\\x9a\\xce\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@}\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xae\\x9e\\xd6\\xaf\\xa7\\xd6\\xd4\\x9a2\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xb4f@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1[+\\x93\\x8eWMg\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xbe\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1FWO\\xeb\\xd7SkjM\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06Z3 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xad\\x95I\\xc7\\xab\\xa63\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0P\\xdf\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xab\\xa7\\xf5\\xeb\\xa95\\xb5\\xa6\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xad\\x19\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12l\\xf4\\xd6\\xca\\xa4\\xe3U\\xd3\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xa8o@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1\\xd5\\xd3\\xfa\\xf5\\xd4\\x9aZS\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xd6\\x0c\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6zke\\xd2\\xf1\\xaa\\xe9\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xd47 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xeai\\xfdzjM\\xad)\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@k\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b\\xbd\\xb52\\xe9x\\xd5t\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xea\\x1b\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12lt\\xf5\\xb4~=\\xb5\\xa6\\xd6\\x94\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa05\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xdeZ\\x99t\\xbcj:\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xf5\\r\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6\\xbazZ\\xbf\\x9eZSk\\xca\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xd0\\x9a\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1Fo\\xadL:^5\\x9d\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xfa\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b]=\\xad_O\\xad\\xa95e\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18h\\xcd\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xb7V&\\x1d\\xaf\\x9a\\xce\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@}\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xae\\x9e\\xd6\\xaf\\xa7\\xd6\\xd4\\x9a2\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xb4f@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1[+\\x93\\x8eWMg\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xbe\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1FWO\\xeb\\xd7SkjM\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06Z3 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xad\\x95I\\xc7\\xab\\xa63\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0P\\xdf\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xab\\xa7\\xf5\\xeb\\xa95\\xb5\\xa6\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xad\\x19\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12l\\xf4\\xd6\\xca\\xa4\\xe3U\\xd3\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xa8o@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1\\xd5\\xd3\\xfa\\xf5\\xd4\\x9aZS\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xd6\\x0c\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6zke\\xd2\\xf1\\xaa\\xe9\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xd47 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xeai\\xfdzjM\\xad)\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@k\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b\\xbd\\xb52\\xe9x\\xd5t\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xea\\x1b\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12lt\\xf5\\xb4~=\\xb5\\xa6\\xd6\\x94\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa05\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xdeZ\\x99t\\xbcj:\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xf5\\r\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6\\xbazZ\\xbf\\x9eZSk\\xca\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xd0\\x9a\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1Fo\\xadL:^5\\x9d\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xfa\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b]=\\xad_O\\xad\\xa95e\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18h\\xcd\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xb7V&\\x1d\\xaf\\x9a\\xce\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@}\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xae\\x9e\\xd6\\xaf\\xa7\\xd6\\xd4\\x9a2\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xb4f@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1[+\\x93\\x8eWMg\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xbe\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1FWO\\xeb\\xd7SkjM\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06Z3 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xad\\x95I\\xc7\\xab\\xa63\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0P\\xdf\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xab\\xa7\\xf5\\xeb\\xa95\\xb5\\xa6\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xad\\x19\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12l\\xf4\\xd6\\xca\\xa4\\xe3U\\xd3\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xa8o@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1\\xd5\\xd3\\xfa\\xf5\\xd4\\x9aZS\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xd6\\x0c\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6zke\\xd2\\xf1\\xaa\\xe9\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xd47 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xeai\\xfdzjM\\xad)\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@k\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b\\xbd\\xb52\\xe9x\\xd5t\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xea\\x1b\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12lt\\xf5\\xb4~=\\xb5\\xa6\\xd6\\x94\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa05\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xdeZ\\x99t\\xbcj:\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xf5\\r\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6\\xbazZ\\xbf\\x9eZSk\\xca\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xd0\\x9a\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1Fo\\xadL:^5\\x9d\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xfa\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b]=\\xad_O\\xad\\xa95e\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18h\\xcd\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xb7V&\\x1d\\xaf\\x9a\\xce\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@}\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00\\x08\\x00\\x02@\\x82\\x8d\\xae\\x9e\\xd6\\xaf\\xa7\\xd6\\xd4\\x9a2\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xb4f@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1[+\\x93\\x8eWMg\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xbe\\x01\\x01@\\x00\\x10\\x00\\x04\\x00\\xb5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x18\\x10\\x00\\x04\\x00\\x01 \\xc1FWO\\xeb\\xd7SkjM\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06Z3 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xad\\x95I\\xc7\\xab\\xa63\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0P\\xdf\\x80\\x00 \\x00\\x08\\x00\\x02\\x80\\xda\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\t\\x0c\\x08\\x00\\x02\\x80\\x00\\x90`\\xa3\\xab\\xa7\\xf5\\xeb\\xa95\\xb5\\xa6\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xad\\x19\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12l\\xf4\\xd6\\xca\\xa4\\xe3U\\xd3\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xa8o@\\x00\\x10\\x00\\x04\\x00\\x01@\\xede\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x04\\x06\\x04\\x00\\x01@\\x00H\\xb0\\xd1\\xd5\\xd3\\xfa\\xf5\\xd4\\x9aZS\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xd6\\x0c\\x08\\x00\\x02\\x80\\x00 \\x00\\xa8\\xbd\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc0\\x80\\x00 \\x00\\x08\\x00\\t6zke\\xd2\\xf1\\xaa\\xe9\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xd47 \\x00\\x08\\x00\\x02\\x80\\x00\\xa0\\xf62\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x02\\x03\\x02\\x80\\x00 \\x00$\\xd8\\xe8\\xeai\\xfdzjM\\xad)\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@k\\x06\\x04\\x00\\x01@\\x00\\x10\\x00\\xd4^\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18H`@\\x00\\x10\\x00\\x04\\x80\\x04\\x1b\\xbd\\xb52\\xe9x\\xd5t\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xea\\x1b\\x10\\x00\\x04\\x00\\x01@\\x00P{\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\x81\\x01\\x01@\\x00\\x10\\x00\\x12lt\\xf5\\xb4~=\\xb5\\xa6\\xd6\\x94\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa05\\x03\\x02\\x80\\x00 \\x00\\x08\\x00j/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$0 \\x00$\\x08\\x00\\x17^xa3C\\xfe\\x82\\x05\\x0bNy\\xac[\\xb7nuQJpQj\\xad\\xa2:^\\xe5\\x9f\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\x15\\x031S\\xcd5s\\xb5\\xf2\\xbe\\x98q_{m<\\xc3\\xfc(_w\\xc1(\\x9f4\\xae\\xcf\\x99\\x9c\\x9c\\x1c\\xc4I\\xde\\xb2e\\x8b\\x00 \\x000\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03#\\x1a\\x88\\x99\\xaa\\x95!\\x7f\\xae\\xe3\\x8c\\x19w\\\\\\xf3\\xf3(_\\xb7W\\x01\\xe0\\xd2K/\\x1d\\xc4I\\xde\\xbcy\\xb3\\x8d>\\xe2Fo\\xa5H:N\\xf5\\x9c\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xf1\\x19\\x88\\x99j\\xae\\xc1\\xba\\x95\\xf7\\xc5\\x8c;\\xca\\xa0>\\xae\\xcf\\xe9U\\x00X\\xb5j\\xd5 N\\xf2\\xa6M\\x9b\\x04\\x00\\x01\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\x18\\xd1@\\xccT\\xad\\x0c\\xf9s\\x1dg\\xcc\\xb8\\xe3\\x1a\\xe6G\\xf9\\xba\\xbd\\n\\x00k\\xd7\\xae\\x1d\\xc4I\\xde\\xb0a\\x83\\x8d>\\xe2FWQ\\xc7WQ\\xad\\xad\\xb5e\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18h\\xc5@\\xccTs\\r\\xd6\\xad\\xbc/f\\xdcQ\\x06\\xf5q}N\\xaf\\x02\\xc0\\xfa\\xf5\\xeb\\x07q\\x92\\xaf\\xb9\\xe6\\x1a\\x01@\\x00`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06F4\\x103U+C\\xfe\\\\\\xc7\\x193\\xee\\xb8\\x86\\xf9Q\\xben\\xaf\\x02\\xc0\\xc6\\x8d\\x1b\\x07q\\x92\\xd7\\xad[g\\xa3\\x8f\\xb8\\xd1[)\\x92\\x8eS=g\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18``|\\x06b\\xa6\\x9ak\\xb0n\\xe5}1\\xe3\\x8e2\\xa8\\x8f\\xebsz\\x15\\x00n\\xb8\\xe1\\x86A\\x9c\\xe45k\\xd6\\x08\\x00\\x02\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c00\\xa2\\x81\\x98\\xa9Z\\x19\\xf2\\xe7:\\xce\\x98q\\xc75\\xcc\\x8f\\xf2u{\\x15\\x00n\\xbe\\xf9\\xe6A\\x9c\\xe4\\xd5\\xabW\\xdb\\xe8#nt\\x15u|\\x15\\xd5\\xdaZ[\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81V\\x0c\\xc4L5\\xd7`\\xdd\\xca\\xfbb\\xc6\\x1deP\\x1f\\xd7\\xe7\\xf4*\\x00\\xdcr\\xcb-\\x838\\xc9\\xf1\\xab\\x1eZ\\xd9X\\x8e\\xd3?\\x02\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xd07\\x03C\\xf9\\x15\\xf11\\xe3\\x8ek\\x98\\x1f\\xe5\\xeb\\xf6*\\x00\\xec\\xdc\\xb9s\\x10\\x01`rrR\\x00\\xf0\\x08\\x00\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18``D\\x031S\\xb5\\xf2]\\xfe\\xb9\\x8e3f\\xdcQ\\x06\\xf5q}N\\xaf\\x02\\xc0\\xfd\\xf7\\xdf?\\x88\\x93\\xbcd\\xc9\\x12\\x1b}\\xc4\\x8d\\xde\\xb7\\xf2\\xe8x\\xd4p\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xce\\xbd\\x81\\x98\\xa9\\xe6\\x1a\\xac[y_\\xcc\\xb8\\xe3\\x1a\\xe6G\\xf9\\xba\\xbd\\n\\x00\\x0f?\\xfc\\xf0 N\\xf2\\xc4\\xc4\\x84\\x00 \\x000\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03#\\x1a\\x88\\x99\\xaa\\x95!\\x7f\\xae\\xe3\\x8c\\x19w\\x94A}\\\\\\x9f\\xd3\\xab\\x00\\xf0\\xf8\\xe3\\x8f\\x0f\\xe2$\\x07\\x80\\xcd\\x9b7\\xdb\\xec#nv\\x85\\xf5\\xdc\\x17Vkn\\xcd\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xfab f\\xa9\\xb9\\x86\\xea\\x96\\xde\\x173\\xee\\xb8\\x86\\xf9Q\\xben\\xaf\\x02\\xc03\\xcf<3\\x98\\x13\\xbd~\\xfdz\\x01@\\x00`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xce\\xd0@\\xccR-\\r\\xf9s\\x1dk\\xcc\\xb8\\xa3\\x0c\\xea\\xe3\\xfa\\x9c^\\x05\\x80\\x83\\x07\\x0f\\x0e\\xe6D\\xfbU\\x80\\nj_\\n\\xaa\\xe3`\\x91\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0%\\x03C\\xf9\\x15\\x80\\x11\\x06b\\xc6\\x1d\\xd70?\\xca\\xd7\\xedU\\x00\\x88\\x1b\\xb0t\\xe9\\xd2AD\\x80e\\xcb\\x96)}gX\\xfaZ\\xba(9V\\xff\\x882\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c00\\x1e\\x031K\\xcd\\xf5]\\xf5V\\xde\\x17\\xb3\\xed(C\\xfa8?\\xa7w\\x01`(?\\xef\\xe17\\x01\\x8c\\xe7b\\xe0\"k]\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\x18\\xb6\\x81\\xa1\\xfc\\x06\\x80\\x98m\\xc79\\xcc\\x8f\\xf2\\xb5{\\x17\\x00n\\xbe\\xf9\\xe6A\\xd4\\x9e\\xa8R[\\xb6l\\xf1(\\x00\\x8f\\x02`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xe6i f\\xa8V\\xbe\\xc3\\x7f\\xba\\xe3\\x8c\\xd9v\\x94!}\\x9c\\x9f\\xd3\\xbb\\x00p\\xc7\\x1dw\\x0c\\xe6\\x84{\"\\xc0a\\x97I\\xe5\\xd9\\xf9e\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xae\\x81!=\\x01`\\xcc\\xb6\\xe3\\x1c\\xe6G\\xf9\\xda\\xbd\\x0b\\x00\\x0f<\\xf0\\xc0`\\x02\\xc0\\xaaU\\xab\\x94\\xbey\\x96>\\x17\\xce\\xba\\x17N\\xebi=\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06Z4\\x103\\xd4\\xe9\\xbe\\xb3\\xde\\xca\\xfbc\\xb6\\x1deH\\x1f\\xe7\\xe7\\xf4.\\x00<\\xf9\\xe4\\x93\\x839\\xe1\\x17_|\\xb1\\x00 \\x000\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xf34\\x103T+\\x03\\xfe\\xe9\\x8e3f\\xdbq\\x0e\\xf3\\xa3|\\xed\\xde\\x05\\x80\\xfd\\xfb\\xf7\\x0f\\xe6\\x84OLLt[\\xb7n\\xb5\\xd9\\xe7\\xb9\\xd9[,\\x94\\x8eYYg\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\x8e\\x81\\x98\\x9db\\x86:\\xdd`\\xdd\\xca\\xfbc\\xb6\\x1deH\\x1f\\xe7\\xe7\\xf4.\\x00\\xc4\\x8d]\\xb9r\\xe5`N\\xba\\xe7\\x01\\xa8s1pQ\\xb5\\x8e\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\x0c\\xdb\\xc0\\x90~\\xfe?f\\xdaq\\x0e\\xf2\\xa3~\\xed^\\x06\\x80\\x9bn\\xbai0\\x01`\\xc5\\x8a\\x15\\x1e\\x01\\xe0\\x11\\x00\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\xc0i\\x0c\\xc4\\xec\\xd4\\xcaw\\xf7Ow\\x9c1\\xd3\\x8e:\\xa4\\x8f\\xf3\\xf3z\\x19\\x00>\\xf7\\xb9\\xcf\\r\\xe6\\xc4/^\\xbc\\xd8F?\\xcdFWr\\x87]r\\x9d_\\xe7\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18``>\\x06bv:\\xdd`\\xdd\\xca\\xfbc\\xa6\\x1d\\xe7 ?\\xea\\xd7\\xeee\\x00x\\xe4\\x91G\\x06s\\xe2\\x03\\xe8\\x86\\r\\x1bD\\x00\\x11\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x188\\x85\\x81\\x98\\x99Z\\x19\\xee\\xe7s\\x9c1\\xd3\\x8e:\\xa4\\x8f\\xf3\\xf3z\\x19\\x00\\x9ey\\xe6\\x99A\\x9d|\\xbf\\x0eP\\xf1\\x9cO\\xf1\\xf41\\x9c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0cd50\\xa4_\\xff\\x17\\x81 f\\xdaq\\x0e\\xf2\\xa3~\\xed^\\x06\\x80c\\xc7\\x8eu\\x17]t\\xd1`\"\\xc0\\x92%K\\x94\\xbeS\\x94\\xbe\\xac\\x178\\xb7\\xdb?\\xee\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xbcc f\\xa6\\xf9|g\\xbd\\x85\\x8f\\x89Y6f\\xdaQ\\x87\\xf4q~^/\\x03@\\xdc\\xe0\\x1d;v\\x0c\\x06@ \\xf5c\\x00\\xefln\\x17:k\\xc1\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xd3\\x06\\x86\\xf6\\xf0\\xff\\x98e\\xc79\\xc4\\x9f\\xcd\\xd7\\xeem\\x00\\xb8\\xeb\\xae\\xbb\\x06\\x15\\x00.\\xbb\\xec2\\x8f\\x02\\xf0(\\x00\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18``\\x96\\x81\\x98\\x95Z\\xf8\\xce\\xfe|\\x8f1f\\xd9\\xb3\\x19\\xd2\\xc7\\xf9\\xb9\\xbd\\r\\x00O<\\xf1\\xc4\\xa0\\x10\\\\p\\xc1\\x05\\xdd\\xb6m\\xdbl\\xf6Y\\x9b}\\xba\\xfay\\xab\\x003\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xcf@\\xccH1+\\xcdw\\xb8n\\xe1\\xe3b\\x96\\x1d\\xe7\\x10\\x7f6_{\\xc1\\xab\\xaf\\xbe\\xfa\\x8fg\\xf3\\x05\\xc6\\xf5\\xb9\\x07\\x0f\\x1e\\xec\\x16.\\\\8(\\x08W]u\\x95\\x00 \\x000\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03S\\x06bFja\\xa8\\x9f\\xef1\\xc6\\x0c\\x1b\\xb3\\xec\\xb8\\xe6\\xe4\\xb3\\xf9\\xba1\\xfb\\xc7#\\x00~u6_d\\x9c\\x9f\\xbbq\\xe3\\xc6Aa\\x98\\x9c\\x9c\\xb4\\xd1]\\xec\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81)\\x031#\\xcdw\\xb8n\\xe1\\xe3b\\x86\\x1d\\xe7\\x8c|\\x96_\\xfbW\\x11\\x00\\xfe\\xea,\\xbf\\xc8\\xd8n\\xe0\\xa7?\\xfd\\xe9Aa\\x08\\xb0\\x9b6m\\xb2\\xd9]\\xf0\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\xbd\\x81\\x98\\x8dZ\\x18\\xea\\xcf\\xe4\\x18c\\x86\\xed\\xeb|\\x1d\\xb3\\x7f\\xfc\\x08\\xc0O\\xfaz\\x80\\xdf\\xf8\\xc67\\x06\\x07b\\xc5\\x8a\\x15\\xe97\\xba\\x9f\\xed\\xca\\xf7\\xb3]\\xce\\xb9s\\xce\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c00\\xdb@\\xccFg2\\\\\\xb7\\xf0\\xb11\\xc3\\xf6u\\xbe\\x8e\\xd9?\\x02\\xc0\\xc1\\xbe\\x1e\\xe0\\xe1\\xc3\\x87\\xbb\\xc5\\x8b\\x17\\x0f\\nE\\xfcL\\xc8\\x96-[D\\x00\\xc5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xd2\\x1a\\x88\\x99hh\\xcf\\xf9\\x16\\xb3k\\xcc\\xb0}\\x9d\\xafc\\xf6\\x8f\\x00\\xf0\\x83\\xbe\\x1e`\\x1c\\xd7M7\\xdd4\\xa8\\x00\\x10\\xd5j\\xf5\\xea\\xd5i7\\xfa\\xec\\xea\\xe7\\xefJ0\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xf9\\x0c\\xc4L\\xd4\\xc2w\\xf4\\xcf\\xe4\\x18cv\\xed\\xf3l\\x1d\\xb3\\x7f\\x04\\x80\\'\\xfb|\\x90_\\xf8\\xc2\\x17\\x06\\x07#~\\xcd\\xc5\\xd6\\xad[E\\x00\\xc5\\x97\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xd2\\x19\\x88Yhh\\xbf\\xfa/BA\\xcc\\xae}\\x9e\\xadc\\xf6\\x8f\\'\\x01\\xfcJ\\x9f\\x0f\\xf2\\x07?\\xf8\\xc1\\xe0\\x02@\\xe0\\xb8\\xfc\\xf2\\xcb\\xd3mte7_\\xd9u\\xce\\x9ds\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xd9\\x06b\\x16:\\x93\\xef\\xac\\xb7\\xf2\\xb11\\xbb\\xf6y\\xb6\\x8e\\xd9?\\x1e\\x01p_\\xcf\\x0f\\xb2\\xbb\\xe2\\x8a+\\x06\\x07\\xc4\\xa3\\x00\\\\\\x08g_\\x08\\xfd\\x9d\\t\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xa1\\x1b\\x18\\xeaw\\xffcf\\xed\\xfb\\\\\\x1d\\xb3\\xff\\x82c\\xc7\\x8e\\xdd\\xd6\\xf7\\x03\\xbd\\xfd\\xf6\\xdb\\x07\\x17\\x00\\xa2by.\\x00\\x17\\xf8\\xa1_\\xe0\\xdd>\\xc6\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06f\\x1a\\x18\\xe2\\xcf\\xfe\\xc7l\\x173k\\xdf\\xe7\\xea\\xa3G\\x8f\\xde\\x1a\\x01\\xe0\\xfa\\xbe\\x1f\\xe8\\x9e={\\x06\\x19\\x00\\x16-Z\\xe47\\x02\\xf8\\x99/?\\n\\xc2\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\n\\x03\\xf1\\xcc\\xff1\\x03\\xb5\\xf2\\x90\\xfe39\\xce\\x98Y\\xfb>W\\xc7\\xec\\x1f\\xcf\\x01\\xb0\\xbc\\xef\\x07\\x1a\\xc77\\xd4R\\x14\\xbf\\xfbrf\\x11\\xf3g\\x85\\x94\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x86h f\\x9f3\\x19\\xaa[\\xf9\\xd8\\x98U[\\x98\\xa9\\x8f\\x1c9\\xb2\\xac\\xac\\xe9\\x82x\\x1e\\x80\\xff\\xdb\\xf7\\x03\\xbe\\xe3\\x8e;\\x06\\x89%Po\\xd8\\xb0A\\x04P}\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18``\\xb0\\x06b\\xe6\\x89\\xd9g\\x88\\xaf1\\xab\\xf6}\\x9e\\x8e\\x99\\xbf\\xac\\xfd[/\\xe5`\\x7f\\xde\\xf7\\x03~\\xfa\\xe9\\xa7\\x07\\x89\\xa5\\x9c\\x81\\xee\\x92K.\\x19\\xecF\\x1fb\\xb9t\\x9b\\x14y\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xce\\xcc@\\xcc<1\\xfb\\x0c\\xf15f\\xd5\\xbe\\xcf\\xd3\\xe5\\xf8~\\xf6\\xd6\\xf4_\\xfe\\xb7\\xd4\\x80\\xff\\xd6\\xc0\\x01wk\\xd6\\xac\\x19$\\x98\\xd8\\x04\\xeb\\xd6\\xad\\x13\\x01\\x14_\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\x18\\x9c\\x81\\x98u\\x868\\xf8\\xc7m\\x8a\\x19\\xb5\\x85Y:f\\xfer\\xbco\\xbd\\x94\\xbf<\\xd1\\xc2A\\xef\\xdc\\xb9s\\xb0p\\xe2\\xd7\\x02\\xc6\\x93b(\\x89gV\\x12\\xad\\x97\\xf5b\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xbf\\x06b\\xc6\\x89Y\\xa7L\\x9e\\x83|\\x8d\\x19\\xb5\\x85Y\\xba\\xcc\\xfc\\xdf\\x9a\\x9e\\xff\\xe3\\x11\\x00\\xf7\\xb5p\\xd0\\xcf?\\xff\\xfc \\xd1Lo\\x86\\xe5\\xcb\\x97\\x0b\\x00\\x8a/\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\x0c\\xc6@\\xcc8\\xd3\\xf3\\xce\\x10\\xdf\\xc6\\x8c\\xda\\xc2,\\x1d3\\xff\\xcc\\x00\\xf0\\x1b-\\x1ct\\x1c\\xe3\\xf6\\xed\\xdb\\x07\\r\\xe8\\xea\\xab\\xaf\\x1e\\xccfWb\\xfb[b\\x9d\\x1b\\xe7\\x86\\x01\\x06\\x18`\\x80\\x01\\x06\\x18``\\xdc\\x06b\\xb6\\x19\\xe2\\xd0?}\\x9bb6me\\x8e.\\x01\\xe07\\xde\\x0e\\x00\\x07\\x0e\\x1c\\xb8\\xb4\\x95\\x03\\x7f\\xf4\\xd1G\\x07\\x8d\\xc8\\x8f\\x02\\xb8\\x10\\x8f\\xfbB\\xec\\xeb3\\xc6\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c00n\\x03C\\x7f\\xe8\\x7fD\\x80\\x98M[\\x99\\xa3c\\xe6\\x7f;\\x00\\xc4\\x1f\\xca\\x81\\xffu\\x0b\\x07\\xff\\xca+\\xaftK\\x97.\\x1dt\\x04\\x88\\xdb7\\xee\\r\\xe9\\xeb\\xbb\\xe83\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\xc0\\xb8\\x0cd\\x98\\xd9b6ma\\x86\\x8eY\\xff\\x84\\xe1\\x7f*\\x00\\xbc\\xd4\\xc8\\xc1w\\xb7\\xdf~\\xfb\\xa0\\x03@9\\x1f\\xdd\\xda\\xb5kE\\x00?\\xfb\\xc5\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xcd\\x19\\x18\\xf2oo\\x8bY-^c&me~.\\xc7\\xf9R\\xcc\\xfc\\'\\xbc\\x94\\xff\\xf3\\xeb\\xad\\xdc\\x80\\xef\\x7f\\xff\\xfb\\x83\\x0f\\x00\\x13\\x13\\x13\\xdd\\x86\\r\\x1b\\x9a\\xdb\\xec\\xe3*\\x88\\xbe\\xae:\\xcd\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\xff\\r\\xc4\\x0c\\x13\\xb3L\\x196\\x07\\xfd\\x1a3i+\\xf3s\\xcc\\xfa\\'\\x0c\\xff\\xf1\\x97c\\xc7\\x8e}\\xae\\xa1\\x1b\\xd0\\xed\\xd8\\xb1c\\xd0\\xa0b\\xc3,^\\xbc\\xd8\\xaf\\x06T|E \\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x9a0\\x10?\\xf7\\x1f3L\\xcc2C~\\x8dY\\xb4\\xa5\\xd99f\\xfdr>N|9r\\xe4\\xc8\\xb6\\x96n\\xc4\\xb7\\xbe\\xf5\\xadA\\xa3*g\\xe7\\xf8\\xed\\x9b\\x9c\\x9c\\xec\\xb6m\\xdb\\xd6\\xc4\\x86Wd\\xfb_d\\x9d#\\xe7\\x88\\x01\\x06\\x18`\\x80\\x01\\x06\\x18``\\x1c\\x06bf\\x89\\xd9ez\\x8e\\x19\\xf2\\xdb\\x98E[\\x9a\\x9dc\\xd6?q\\xfa/\\x7f\\xdb\\xb7o\\xdf\\xa2r#~\\xd5\\xd2\\r\\xb9\\xf6\\xdakS\\x00[\\xb5j\\x95\\x00\\xa0\\xfa2\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@o\\r\\xc4\\xcc2\\xe4\\xa1\\x7f\\xfa\\xb6\\xc5\\x0c\\xda\\xd2\\xcc\\x1c3~\\xcc\\xfa\\xef\\n\\x00\\xf1\\x7f\\x94w\\x1ej\\xe9\\xc6<\\xf4\\xd0C)\\x90\\x05\\xb6+\\xaf\\xbc\\xb2\\xb7\\x9b}\\x1c\\x05\\xd1\\xd7T\\xa6\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18h\\xc3@\\xcc*1\\xb3dx\\x8d\\x19\\xb4\\xa5\\x999f\\xfcr^N\\xfeR\\xde\\xf9\\x95\\x96nLy(C\\xb7r\\xe5\\xca\\x14\\xd0\\xe2\\x894\\xae\\xb9\\xe6\\x1a\\x11@\\xf5e\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xde\\x18\\x88\\x19%\\xc3\\x93\\xfe\\x95\\t\\xfa\\xf8\\xec\\x193hK3s\\xcc\\xf8\\'\\x9f\\xfe\\xcb\\xff[\\xde\\xf9\\xe1\\xc6nL\\xb7k\\xd7\\xae\\x14\\x01 \\xc0-Z\\xb4\\xc8o\\x06p\\xb1\\xef\\xcd\\xc5^\\x91o\\xa3\\xc8;O\\xce\\x13\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\x8c\\xcb@<\\xe3\\x7f\\xcc(1\\xabdx\\x8d\\xd9\\xb3\\xb5y9f\\xfcrnN\\xfeRj\\xc6%\\xaf\\xbe\\xfa\\xea\\x9b-\\xdd\\xa8\\x03\\x07\\x0e\\xa4y\\xb2\\x89r\\xd6\\xba\\x0b.\\xb8\\xa0\\xdb\\xb4i\\x93!P\\x08`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xf3f f\\x92\\x98MbF\\xc9\\xf0\\x1aOp\\x18\\xb3gK\\xb3r\\xcc\\xf61\\xe3\\x9f|\\xfa\\x9f\\xfa\\x7f\\xcb\\x07\\xfd\\xa4\\xa5\\x1b\\x15\\xc7z\\xcf=\\xf7\\xa4@7\\xbd\\xb1\\xe2Wkl\\xde\\xbc\\xf9\\xbcm\\xf6q\\x15D_W\\x9df\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xff\\x06b\\x16\\xc9\\xf0\\xeb\\xfe\\xa6\\xe7\\xafx\\x1b3gksr\\xcc\\xf6Sc\\xfe\\xa9\\xdf\\x94\\x0fz\\xb2\\xb5\\x1bv\\xe8\\xd0\\xa1n\\xd9\\xb2e\\xa9\"\\xc0\\x92%K\\xba\\xf7\\xbf\\xff\\xfd\"\\x80\\xea\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xe7\\xcc@\\xcc 1\\x8b\\xcc\\x1c\\x8e\\x87\\xfe\\xe7\\x985c\\xe6lmN\\x8e\\xd9\\xfe\\xd4\\x93\\xff\\xd4{\\xca\\x07}\\xb2\\xb5\\x1b\\x16\\xc7{\\xef\\xbd\\xf7\\xa6B\\x18\\x9b,6\\x9eG\\x02\\xf4\\xbf\\x90\\xaa\\xd8\\xce\\x11\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\xc0\\x10\\x0c\\xc4\\xec\\x91m\\xf8\\x8f\\xb9\\xeb\\xbe\\xfb\\xeekn\\xf8\\x8f\\x199f\\xfb\\xd3\\x06\\x80\\xf8\\x19\\x81\\xf2\\xc1\\xff\\xd0Z\\x048|\\xf8p\\xb7b\\xc5\\x8at\\x11 \\x1ez\\xe39\\x01\\xfc\\x832\\x84\\x7fP\\xdc\\x06\\x8e\\x19`\\x80\\x01\\x06\\x18`\\x80\\x81\\xfe\\x1a\\x88\\x99#\\xdb\\xc3\\xfec\\xf8\\x8f\\x193f\\xcd\\xd6\\xe6\\xe3\\x98\\xe9O\\xfb\\xf3\\xff\\xd3u\\xa0|\\xf0+\\r\\xde\\xc0\\xeeK_\\xfaR\\xba\\x00\\x10(\\xe3\\xc97\\xe2\\x198]0\\xfb{\\xc1tn\\x9c\\x1b\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81V\\r\\xc4\\xac\\x91\\xe9\\t\\xffb\\xc6\\x9a~\\x8d\\x19\\xb3\\xc5\\xd98f\\xfa\\xe9\\xf9\\xfe\\xb4o\\xcbC\\x05\\xfe}\\x8b7\\xf2\\x95W^\\xe9\\xd6\\xae]\\xfb\\xf6\\xc9\\x9a>i\\x19\\xde\\xc6\\xaf\\xdf\\x88\\xdf\\xc1\\xd9\\xeaE\\xc5q\\xfb\\x07\\x91\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xfe\\x19\\x88\\x19#\\xd3\\xaf\\xfa\\x9b9;\\xc6l\\x193f\\x8b\\xb3q\\xcc\\xf4\\xa7\\x1d\\xfc\\xa7?\\xa0<T`[\\x8b72\\x8e\\xf9\\xeb_\\xffz\\xca\\x00\\x10P\\'&&\\xba+\\xaf\\xbcR\\x04\\xf0$0\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0p\\xd6\\x06b\\xb6\\x88\\x19c\\xe6P\\x9c\\xe9\\xcf1[\\xb6:\\x17\\xc7L?=\\xdf\\xcf\\xebm)\\x06\\xff\\xbb\\xd5\\x1b\\xbb}\\xfb\\xf6\\xb4HcC\\xaeZ\\xb5\\xaa\\xdb\\xb6m\\xdbYox\\x05\\xb6\\x7f\\x05\\xd69qN\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xc6m f\\x89\\x98)2\\r\\xfb\\xb3ok\\xcc\\x94\\xad\\xce\\xc31\\xcb\\xcfk\\xe8\\x9f\\xf9A\\xe5\\x93\\xfe\\xa0\\xd5\\x1b\\xfc\\xec\\xb3\\xcfv\\x0b\\x17.L\\rvrr\\xb2\\xdb\\xb2e\\x8b\\x08\\xa0\\xfc2\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\xc0\\xbc\\r\\xc4\\x0c\\x11\\xb3\\xc4\\xec\\x818\\xd3\\xdfc\\x96\\x8c\\x99\\xb2\\xd5y8f\\xf9\\x99\\xb3\\xfd\\xbc\\xfe|\\xec\\xd8\\xb1\\x8f\\xb7z\\x83\\xe3\\xb8o\\xbd\\xf5\\xd6\\xd4hc\\x83\\xc6\\xb3tzr@\\x85x\\xdc\\x85\\xd8\\xd7g\\x8c\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\x18\\x86\\x81\\x98\\x1d2>\\xd3\\xff\\xec\\xb8\\x11\\xb3d\\xcb\\xb3p\\xcc\\xf2\\xf3\\x1a\\xfag~\\xd0\\x9e={\\xdeSn\\xf4\\xdf\\xb5z\\xc3_|\\xf1\\xc5\\xf4\\xe5* G\\xbd\\x8a\\'\\xafpQ\\x1e\\xc6E\\xd9yt\\x1e\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xc6a f\\x86\\xcc?\\xef?\\x1d\\x01\\xe2\\xd1\\x0f\\xfb\\xf7\\xefo9\\x00\\xfc]\\xcc\\xf23g\\xfby\\xff\\xb9\\x0c\\xff\\xdfi5\\x00\\xc4q?\\xf8\\xe0\\x83\\xe9\\x1f\\x050\\ry\\xe9\\xd2\\xa5~$\\xc0C\\xbf\\x84 \\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06N0\\x10\\x0f\\xf9\\x8fYazn\\xc8\\xfe\\xf6\\xcb_\\xfer\\xcb\\xc3\\x7f\\x1c\\xfbw\\xe6=\\xf0\\xcf\\xfe\\xc0\\xf2\\xb3\\x03\\x1fi9\\x00\\xc4\\xb1_\\x7f\\xfd\\xf50\\x97G\\x02\\xc4F\\x8e\\xdf\\xddy\\xf5\\xd5W\\x9f\\xb0\\xe1\\xc7Q\\x0f}MU\\x9a\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xfe\\x1b\\x88\\xd9 f\\x84\\xecC\\xff\\xf4\\xed\\x8f\\xd9\\xb1\\xf5\\xf97f\\xf8\\xd9s\\xfd\\xbc\\xff^~u\\xc0\\x05\\xe5\\x0b\\xfcm\\xcb\\x8b\\xb0w\\xef^?\\xc72\\x15\\x00\\xa6a/_\\xbe\\xdc\\xa3\\x01\\x94_!\\x88\\x01\\x06\\x18`\\x80\\x01\\x06\\x18` \\xa9\\x81\\xf8\\xae\\x7f\\xcc\\x04\\xd3\\xf3\\x81\\xb7o=\\x7fZ\\xcc\\x8e-\\xcf\\xbe1\\xbb\\xc7\\x0c?\\xef\\x81\\xffd\\x1fX\\x16`O\\xcb\\x8b\\x10\\xc7\\xbek\\xd7.\\xb8gE\\x80(}\\xeb\\xd6\\xads\\xd1Oz\\xd1W\\xe4\\xfb_\\xe4\\x9d#\\xe7\\x88\\x01\\x06\\x18`\\x80\\x01\\x06\\xc6a f\\x00\\xdf\\xf5\\x7f\\xeb\\x11\\xd23\\xc3G\\xcc\\x8c\\xad\\xcf\\xbd1\\xbb\\x9fl\\xa6?\\xa3\\xff\\xafT\\x84\\x0f\\xb5\\xbe\\x10\\xa5\\x82\\x1c\\x7f6\\xfc\\x99\\'\\xd8\\x9f\\xdfB\\x7f\\xc9%\\x97\\xf8M\\x01\"\\x80\\x10\\xc4\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c00p\\x03\\xf1\\x0c\\xffq\\xdf\\xdf\\x1c\\xf4\\xee\\xe1?\\xd6&f\\xc6\\xd6\\xe7\\xde\\x98\\xdd\\xcfh\\xd8?\\xd9\\x07\\xef\\xde\\xbd{aY\\x88\\xbfj}1\\xbe\\xf3\\x9d\\xeft\\x8b\\x16-\\x02~\\xd6#\\x01\\xa6/\\x00+V\\xac\\xf0c\\x01\\x03\\xbf\\xe8\\x8f\\xa3 \\xfb\\x9a\\xbe3\\xc1\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xf4\\xdb@<\\xdc?\\xee\\xebO\\xdf\\xef\\xf7\\xf6\\xc4\\x00\\x103b\\xcc\\x8a\\xad\\xcf\\xbb1\\xb3\\xc7\\xec~\\xb2\\x99\\xfe\\x8c\\xff\\xbfR\\x12\\xfe\\xc3\\x00\\x16\\xa4\\xbb\\xe7\\x9e{\\xc0?E\\x00\\x88\\x0bA\\xe0_\\xbdzu\\xb7u\\xebV\\x05X\\x0c`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0a\\x03q\\x9f>\\xee\\xdb\\xfb&\\xe8\\x89\\x03\\xff\\xec\\x00\\x123\\xe2\\x10f\\xdd2\\xb3?r\\xc6\\x83\\xfe\\xa9>\\xa1<\\x1cbm\\xf9\\x82o\\xb6\\xbe0\\xc7\\x8e\\x1d\\xeb\\xae\\xbb\\xee:\\x11`\\x8e\\x08\\x10\\x1b\"~&\\xe8\\xf2\\xcb/\\x17\\x02\\x1a\\xbe\\xe0+\\xf1\\xfd.\\xf1\\xce\\x8f\\xf3\\xc3\\x00\\x03\\x0c0\\xc0\\x00\\x03\\xe32\\x10\\x83\\x7f\\xdc\\x97\\xf7s\\xfes\\x0f\\xfe1\\xf7\\xc4l\\x183b\\xebsn\\xcc\\xea1\\xb3\\x9fj\\x9e\\x1f\\xe9\\xff/_\\xf4\\xc5\\xd6\\x17&\\x8e\\xff\\x85\\x17^\\xf0\\xb3/\\xa7\\t\\x00\\xb1\\x19\\xe25.\\x1aQ\\r\\xe3aC\\xe3\\xba@\\xf9\\xba\\xfe\\xf1c\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xe0\\xec\\r\\xc4}\\xf6\\xb8\\xefn\\xf0?\\xfd\\xe0\\x1f\\xb3N<\\x1fB\\xcc\\x86C\\x98qcV\\x1fi\\xc8\\x9f\\xeb\\x93\\xca\\x17\\xfd\\xe4\\x10\\x16\\'n\\xc3\\xa3\\x8f>\\xeaQ\\x00\\xf3\\x8c\\x00\\xb19\\x16.\\\\\\xd8\\xad\\\\\\xb9\\xb2\\xdb\\xb4i\\x93\\x10\\xe0Q\\x01\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xf4\\xc8@\\xdcG\\x8f\\xfb\\xeaq\\x9f=\\xee\\xbb{\\x9d\\xdf\\x1a\\xc4L8\\x94\\xf96f\\xf5\\xb9f\\xf9\\x91\\xdeW\\x1eRpA\\xf9\\xc2\\x7f3\\x94E\\xfa\\xe8G?js\\x8cp\\x81\\x98\\x9c\\x9c\\xec\\xae\\xba\\xea\\xaan\\xdb\\xb6m.\\xfc=\\xba\\xf0\\xab\\xe6g_\\xcd\\xad\\xa15d\\x80\\x01\\x06\\x18`\\x80\\x81V\\x0c\\xc4}\\xf1\\xb8O\\x1e\\xf7\\xcd\\r\\xfc\\xf3\\x1b\\xf8g\\xaeS\\xcc\\x82C\\x99kcF\\x8fY}\\xa4!\\xfft\\x9fT~>\\xe2?\\x0ee\\xa1\\x0e\\x1d:\\xd4\\xad_\\xbf\\xde\\x86\\x19!\\x02\\xc4\\xe6\\x89\\x87\\x16]v\\xd9e~\\x85\\xa0\\x08 \\x041\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\x9c#\\x03\\xf1\\xeb\\xea\\xe2>\\xb8\\x87\\xf9\\x9f\\xf9\\xd0?\\x1d\\x00b\\x06\\x8cYp(sm\\xcc\\xe8\\xa7\\x9b\\xe3G~\\x7f\\xa9\\x0b\\x97\\x97\\x85zc(\\x8b\\xf5\\xdcs\\xcfu\\x17]t\\x91\\x080b\\x04\\x98\\xdeDK\\x96,\\xe9V\\xadZ\\xd5m\\xdc\\xb8\\xd1\\xc5\\xff\\x1c]\\xfc[\\xa9\\xd3\\x8e\\xd3wR\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\xb33\\x10\\xf7\\xb1\\xe3\\xbev\\xdc\\xe7\\x9e\\xbe\\xff\\xed\\xedh\\x01 f\\xbf\\x98\\x01\\x872\\xcf\\xc6l\\x1e3\\xfa\\xc8\\x03\\xfe|>\\xb1\\xfc\\x07\\xfe\\xeb\\x80\\x16\\xac{\\xec\\xb1\\xc7l\\xa4\\xb3\\x0c\\x003/@\\x8b\\x17/>\\xfe{F\\xa3\\xac\\xf9u\\x82gw\\xb1\\xf7\\x8f\\xa5\\xf5c\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xf2\\x19\\x88\\xfb\\xd0q_z\\xc5\\x8a\\x15]\\xdc\\xb7\\x9ey_\\xdb\\x9fG\\x1b\\xfc\\xa7\\xd7-f\\xbf!\\xcd\\xb2e6\\xff\\xc3r\\xdb\\xc6\\xfbR~\\xbe`\\xdb\\x90\\x16-n\\xcb\\x9dw\\xdeicU\\x8c\\x00E\\xe0\\xf1\\xf5\\x9c\\x98\\x98\\xe8.\\xbe\\xf8\\xe2\\xe3\\xc52.b~\\x9b@\\xbe\\x7f\\xc0\\xdciq\\xce\\x19`\\x80\\x01\\x06\\x18`\\x80\\x81\\xb9\\r\\xc4}\\xe4\\xb8\\xaf\\x1c\\xdf\\xe5\\x8f\\xfb\\xceq\\x1fz\\xfa\\xfe\\xb4\\xb7g7\\xf0\\xcf\\\\\\xbf\\x98\\xf9\\x866\\xc7\\xc6l^n\\xe3\\xf8_Ji\\xf8\\xe3!-^\\xfc\\xee\\xc7\\x1d;v\\xd8hc\\x88\\x00E\\xe3\\t\\xeb\\x1a\\x0f]Z\\xb6l\\xd9\\xf1_Q\\x12\\x17\\xba\\xcd\\x9b7\\xfb\\xb1\\x01?6\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc2@\\xdc\\xf7\\x8d\\xfb\\xc0\\xf1\\xeb\\xfa\\xe2>\\xb1\\x87\\xf5\\x9f8+\\xcc\\x9e\\x1dj\\xfd=f\\xbd\\x98\\xf9\\x864\\xc3\\xc6L>\\xfe\\xc9\\x7f\\xea\\xbfP\\x16\\xee\\xc3CZ\\xbc\\xb8-\\xfb\\xf7\\xef\\xef\\xd6\\xae]{\\xc2\\xb0Z\\x0b\\x9c\\xaf3\\xf7\\xc6\\x8e\\xca\\x19\\x17\\xbfx\\x16\\xd3K/\\xbd\\xf4\\xf8\\x05q\\xcd\\x9a5\\xdd\\xbau\\xeb\\xbak\\xae\\xb9\\xe6\\xf8\\x13\\r\\xc6\\xaf7\\x89\\x0bf\\x14\\xd2xXT<\\xf3\\xa9Wk\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0p\\xbe\\x0c\\xc4}\\xd2\\xb8o\\x1a\\xf7Q\\xe3\\xbej<A_\\xdcw\\x8d\\xfb\\xb0q_6\\x86\\xfc\\xb8o\\x1b\\xf7q\\xe3\\xbe\\xae\\xef\\xec\\xcf=\\x13\\x8ckf\\x8a\\x19/f\\xbd\\xa1\\xcd\\xaf%\\x00|hj<?7o\\xca\\x02\\xfelh\\x8b\\xb8w\\xef\\xden\\xe9\\xd2\\xa5\"\\xc0\\xac\\xef\\xda\\x8fk3\\xfa\\xba\\xe7\\xe7\"h\\xdd\\xad;\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\\x06\\x031\\xdb\\xc5\\x8c7\\xb4\\xb95f\\xf1r\\xfe\\xce\\xedKy\\x08\\xc5g\\x06\\xb8\\x90\\xddSO=\\xe5\\xc96\\x04\\x00\\x11\\x88\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x1a6\\x10O\\xa0\\x18\\xb3\\xdd\\x10g\\xd6\\x98\\xc5\\xcf\\xed\\xf4\\xff\\xd6\\x7fm\\xa2<\\xec\\xe0\\xcf\\x87\\xb8\\xa0\\x8f>\\xfa\\xa8\\xcd\\xde\\xf0f/<\\x9d?k\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@b\\x031\\xd3\\rqV\\x8d\\x19\\xbc\\xcc;\\x13\\xe7#\\x00,(\\xff\\xf1[\\x86\\xb8\\xa8q\\x9bv\\xed\\xda\\xe5\\x82\\x91\\xf8\\x82!\"\\x88(\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xb4i f\\xb9\\xa1\\xce\\xa91\\x83\\x17\\x97\\xe7\\xef\\xa5,\\xec\\xff\\x18\\xea\\xe2\\xdev\\xdbm\"\\x80\\x08\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c4b f\\xb8\\xa1\\xce\\xa71{\\x9f\\xbf\\xc9\\x7f\\xea\\xbf\\\\~\\xfe\\xe0\\xe3C]\\xe0RW\\xba\\x8f}\\xecc6{#\\x9b\\xbd\\x90t\\xae\\xac\\x01\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03I\\r\\xc4\\xec\\x163\\xdcP\\xe7\\xd3\\x98\\xbd\\xcf{\\x00\\x88\\x03(\\x0b\\xfc\\xe3\\xa1.\\xf2\\xd1\\xa3G\\xbb\\x9bo\\xbe\\xd9E$\\xe9EDT\\x10U\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xe8\\xbf\\x81\\x98\\xd9bv\\x1b\\xea\\\\\\x1a3wq\\xd8\\x8f\\x97R\"\\xfe\\xc5\\x80\\x17\\xba;r\\xe4H\\xf7\\xc1\\x0f~P\\x04\\x10\\x01\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x9e\\x19\\x88Y-f\\xb6!\\xcf\\xa41s\\xf7c\\xfa\\x9f:\\x8a\\xf2P\\x8b\\x1f\\x0ey\\xc1\\x0f\\x1f>\\xdc\\xddx\\xe3\\x8d6{\\xcf6{\\xe1\\xe7\\x9cX\\x03\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x92\\x1a\\x88\\x19-f\\xb5!\\xcf\\xa21k\\xf7j\\xf8\\x8f\\x83)\\xc5\\xe5}e\\xd1\\xdf\\x18\\xf2\\xc2\\x1f:tH\\x04Hza\\x11\\x1a\\x84\\x16\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xfae \\x86\\xff\\x98\\xd1\\x86<\\x83\\xc6\\x8c\\x1d\\xb3v\\xb1\\xd7\\xbf\\x97R&\\x1e\\x1f\\xf8\\xe2\\x1f\\xafK~\\x1c\\xa0_\\x1b\\xbf\\xec\\x04\\xc5\\xd7\\x1a0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xc8@\\xccdC\\xff\\xce\\x7f\\xcc\\xd61c\\xf7o\\xf2\\x9f:\\xa2\\x97^z\\xe9\\x9f\\x95\\x83\\xfc\\xe5\\xd0#@\\xfc|\\x89\\'\\x064t\\x0b\\x0f\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0p\\xee\\r\\xc4,\\x163\\xd9\\xd0\\xe7\\xce\\x98\\xadc\\xc6.\\xc6\\xfa\\xfbR\\n\\xc5\\xef$8\\x11\\xc7\\x9fa\\xd2\\xaf\\x08<\\xf7\\x9b\\xbd\\xc8Wv\\xad\\x01\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03I\\r\\xc4\\x0c6\\xf0g\\xfb\\x7f;l\\xc4l\\xdd\\xdf\\xc9\\x7f\\xea\\xc8v\\xef\\xde\\xbd\\xb0\\x1c\\xe8O3D\\x80r;\\xbb\\xdbn\\xbb\\xcd\\xc5\\'\\xe9\\xc5G\\x8c\\x10c\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x188w\\x06b\\xf6\\x8a\\x19,\\xc9\\xac\\xf9\\xd3\\x98\\xad\\x8b\\xaf\\xfe\\xbf\\x94\\x87cl/\\'\\xe6\\xcd\\x0c\\'&n\\xe3\\xae]\\xbbD\\x00\\x11\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\x18\\x93\\x81\\x98\\xb9\\xb2\\xcc\\x971K\\xc7L\\xdd\\xff\\xc9\\x7f\\xc6\\x11\\x96\\x83\\xfef\\x96\\x13\\x14\\xb7\\xf3\\xd1G\\x1f\\xed\\x16/^l\\xc3\\x8fi\\xc3\\x17Z\\xd6\\xd6\\x1a0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xcc@\\xccX1ke\\x9a-c\\x96\\x9e1Z\\xb7\\xf1\\xc7\\x1f\\xfd\\xe8G\\x17\\x95\\x03\\xff\\x9f\\x99N\\xd4SO=\\xd5-]\\xba\\xd4E)\\xd9EI\\x9c\\x10g\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xa8o f\\xab\\x98\\xb12\\xcd\\x941C\\xc7,]<\\xb5\\xf7R\\x9e\\x9c\\xe173\\x9d\\xac\\xb8\\xad{\\xf7\\xee\\xed\\xd6\\xae]+\\x02\\x88\\x00\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\xc0\\x88\\x06b\\xa6\\x8a\\xd9*\\xdb<\\x193t{\\x93\\xff\\x8c#.\\'\\xec\\x99l\\'m\\xff\\xfe\\xfd\\xdd\\x8e\\x1d;l\\xf6\\x117{\\xe1c\\xed\\xac\\x01\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03I\\r\\xc4,\\x153U\\xb692f\\xe7\\x19\\xa3t\\x9b\\x7f<|\\xf8\\xf0\\x8arC~\\x99\\xed\\xe4\\x1d;v\\xac\\xbb\\xf3\\xce;]\\xb4\\x92^\\xb4D\\x0c\\x11\\x87\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x8137\\x103T\\xccR\\xd9\\xe6\\xc7\\x98\\x99cv.f\\xda\\x7f)7\\xe6\\x13\\tO\\xe0q\\xb4_\\xfd\\xeaW\\xbb\\x8b.\\xbaH\\x08\\x10\\x02\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81S\\x18\\x88\\x99\\xe9\\xb1\\xc7\\x1e\\xcb8\\xf8O\\xdf\\xe6O\\xb4?\\xf9\\xcf\\xb8\\x05\\xa5\\xe2\\xfc\\x97\\xac\\x11\\xe0\\xb9\\xe7\\x9e\\xeb\\xd6\\xaf_o\\xb3\\x9fb\\xb3\\x17&\\xd6\\xc6\\x1a0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xd4@\\xccJ13e\\x9d\\x17cV\\x9e1:\\x0f\\xe3\\x8f\\xfb\\xf6\\xed{oyF\\xc3\\xbf\\xcczR\\x0f\\x1e<\\xd8}\\xe4#\\x1fqQKzQ\\x139D\\x1e\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xdem f\\xa4\\x98\\x95\\xb2\\xce\\x891#\\xc7\\xac\\\\l\\x0c\\xef\\xe5\\xc8\\x91#\\xd7\\x95\\x13\\xfbF\\xd6\\x93\\x1b\\xb7{\\xf7\\xee\\xdd\\xdd%\\x97\\\\\"\\x04\\x08\\x01\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xd6@\\xccD1\\x1be\\x9e\\rc6\\x8e\\x19yx\\x93\\xff\\x8c[T\\x1e\\xde\\xf0o\\x93\\x9f\\xe4\\xee\\x85\\x17^\\xe8\\xae\\xbb\\xee\\xba\\xb4\\x9b\\xbdpp\\xdb\\xad\\x01\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03I\\r\\xc4,\\x143Q\\xf6\\xb90f\\xe3\\x19\\xa3\\xf2`\\xff8QN\\xf4!\\'\\xfbXw\\xf7\\xddww\\x8b\\x16-r\\xe1Kz\\xe1\\x13B\\x84 \\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81L\\x06b\\xf6\\x89\\x19\\xa8\\x0c\\xbe\\xe9\\x87\\xff\\x98\\x89\\xcb\\xb9\\x9f(\\xaf\\xc3\\x7f)\\x0fsXYn\\xf0\\xeb\\xd9#@\\xdc\\xfe\\xa7\\x9f~\\xba{\\xdf\\xfb\\xde\\'\\x02\\x88\\x00\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c00X\\x03\\x1b6l8>\\xfb\\x98\\x01_\\x8b\\xf8\\xf1z\\xcc\\xc4\\xc3\\x9f\\xfcg\\xdc\\xc2r\\x83\\xb7\\x97\\'<\\xf8{\\x00^\\xeb\\xcaZt\\xbbv\\xed\\xea\\x16/^<\\xd8\\r_N\\xbd\\xdbf\\r\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18Hf f\\x9c\\x98ub\\xe61\\xfb\\xbd\\xd6\\xc5\\x0c\\\\\\xd6b\\xfb\\x8c\\xd18\\xcf\\x1f\\xcbC?\\xfe5\\x04\\xc7\\x0b\\xd0\\xf1\\xcd\\xb0w\\xef\\xde\\xee\\xfa\\xeb\\xafwQLvQ\\x14G\\xc4!\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81!\\x1a\\x88\\xd9&f\\x1c3\\xdf;3_\\xcc\\xc0\\xe5\\\\\\xe7})\\x05\\xe4\\xf7\\x81x\\x07D\\xac\\xc5\\x83\\x0f>\\xd8MNN\\n\\x01B\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c4g f\\x99\\x98i\\xccy\\'\\xcey1\\xfb\\xe6\\x9d\\xfc\\xa7n\\xf9K/\\xbd\\xb4\\xa4,\\xc4\\x9f\\xc1q\"\\x8e\\x17_|\\xb1\\xbb\\xf5\\xd6[\\xbb\\x85\\x0b\\x176\\xb7\\xe1\\xcb\\xa9u\\xcc\\xd6\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81d\\x06bv\\x89\\x19&f\\x19\\xf3\\xdd\\x89\\xf3]\\xcc\\xbc1\\xfb\\xa6\\x0f\\x00\\xb1\\x00\\xe5g \\xd6\\x16 \\xbf\\x80\\xe4D$\\xb1\\x1e\\xcf>\\xfbl\\xb7}\\xfbv\\x17\\xcfd\\x17O\\x11EDb\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18h\\xc9@\\xcc,1\\xbb\\x98\\xe9\\xde=\\xd3\\xc5\\xac\\x1b3o9\\x9f^\\xa6W\\xa0,\\xc8u\\xa5\\x8a\\xfc\\x1a\\x98\\x93\\x82\\xe9\\xbe\\xf6\\xb5\\xafuk\\xd6\\xac\\x11\\x02\\x84\\x00\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xe8\\x8d\\x81\\x98QbV1\\xc7\\x9d|\\x8e\\x8b\\x197f\\xdd\\xe9\\xb9\\xd7\\xdb\\x19+p\\xf4\\xe8\\xd1\\x8f\\x95\\x05z\\x13\\x9e\\x93\\xe3y\\xe5\\x95W\\xba/~\\xf1\\x8b\\xdd\\x8a\\x15+z\\xb3\\xe1\\xcb\\xe9s,\\xd6\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81d\\x06b&\\x89\\xd9$f\\x14\\xf3\\xdb\\xc9\\xe7\\xb7\\x98mc\\xc6\\x9d1\\xf2\\xfa\\xe3\\xec\\x15(\\x8b\\xb4\\x0b\\xa0\\x93\\x03\\x9a^\\x97\\xc3\\x87\\x0fw\\xf7\\xde{o\\xb7l\\xd92\\x17\\xdad\\x17Z\\xc1Epb\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x188\\x9f\\x06b\\x06\\x89Y$f\\x92\\xe9\\xf9\\xc4\\xdb\\x93\\xcfo1\\xdb\\x96s\\xe5\\xe5t+P\\x16\\xea?CtrD3\\xd7\\xe5\\xd0\\xa1C\\xdd\\xddw\\xdf\\xed7\\x06\\x88\\x00\\xf9\\x84\\xf1\\xcc\\x00\\x00\\x0blIDATB\\x10\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03c5\\x10\\xcf\\xec\\x1f\\xb3G\\xcc 3g\\x12\\x7f>\\xf9\\xdc\\x163\\xed\\xe9\\xe6^\\xef\\x7fg\\x05&\\n\\xa4\\xe7a:9\\xa6\\xd9\\xebr\\xe0\\xc0\\x81n\\xd7\\xae]~4\\xc0E\\x7f\\xac\\x17\\xfd\\xb2=}}k\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c$3\\x10\\x0f\\xf5\\x8fY#f\\x8e\\xd9s\\x88\\xbf\\x9fr^{\\xbe\\xdcw\\x9exg\\xbc\\xf5\\xa7\\xd3\\xae\\xc0\\x9e={\\xdeS\\xaa\\xc9\\x8bP\\x9d\\x12\\xd5\\xbb6`yr\\x89\\xee\\xa1\\x87\\x1e\\xea\\xae\\xbd\\xf6Z\\x17\\xe6d\\x17\\xe6\\xb2\\xa1\\x9csk\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0P\\xcd@\\xcc\\x141[\\xc4\\x8ca&\\x9b\\xffL\\x163l\\xcc\\xb2\\xa7\\x1dx}\\xc0\\xbbW\\xa0`\\xbb\\xb0,\\xe0\\x9f\\x007\\x7fp\\xd3k\\xf5\\xcdo~\\xd3\\xaf\\x0f\\xf4\\x0f@\\xb5\\x7f\\x00\\x04\\x06\\x81\\x85\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xc8a ~\\x9d_\\xcc\\x12\\xd3s\\x85\\xb7\\xf3\\x9f\\xc5bv\\x8d\\x19\\xb6\\xec\\x15/\\xa3\\xae\\xc0\\xc1\\x83\\x07/.\\x0b\\xf9\\xa7\\xe0\\xcd\\x1f\\xde\\xcc\\xb5\\xfa\\xde\\xf7\\xbe\\xd7\\xdd~\\xfb\\xed\\xdd\\xd2\\xa5K\\r\\x83\\x82\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xbc\\xcb@\\xcc\\n13\\xc4\\xec0s\\x96\\xf0\\xe7\\xf9\\xcf`1\\xb3\\xc6\\xec:\\xea\\xdc\\xeb\\xf3f\\xac\\xc0\\xcb/\\xbf\\xbc\\xb4,\\xe8O\\x01\\x9c?\\xc0\\xd9k\\x15\\xbf\\x9ec\\xf7\\xee\\xdd\\xdd\\x8d7\\xde\\xf8\\xae\\r_\\x96\\xda\\xffg\\r\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18Hf f\\x83\\x98\\x11\\xfc*\\xbf\\xd1\\xe7\\xac\\x98\\xbbbV\\x8d\\x99u\\xc6\\x08\\xeb\\x8fg\\xbb\\x02\\xe5\\xa1\\x14+\\xcb\\xe2\\xfe\\xc5\\xec\\xc1\\xd6\\xdf\\xcf\\x1c\\xeb\\xf3\\xcf?\\xdf\\xed\\xdc\\xb9\\xb3\\xbb\\xe2\\x8a+\\\\\\xe4\\x93]\\xe4\\xc5\\x1e\\xb1\\x8b\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xc8m f\\x80\\x98\\x05b&0K\\x9d\\xf9,u\\x925\\xfb\\x8b\\x98U\\xcb\\xbe\\xf2R{\\x05ba=\\x12\\xa0\\n\\xd2\\xb77\\xfb\\xd3O?\\xdd}\\xf6\\xb3\\x9f\\xedV\\xaf^-\\x06\\x88\\x01\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\x0c\\xd0@\\xdc\\xd7\\x8f\\xfb\\xfcq\\xdf\\xff$\\x03\\xac\\xff\\xaf|\\x17\\x7f\\x94u\\x89\\xd9\\xd4\\xf0_{\\xea\\x9f\\xf5\\xf5\\xa6~\\x1c\\xc0s\\x02\\x8c\\x88t.\\xd8\\xdf\\xfe\\xf6\\xb7\\xbb\\xcf|\\xe63\\x1e\\x190\\xc0\\x8b~\\xd9F\\xfe1\\xb7\\x06\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@\"\\x03\\xf1\\x9d\\xfe\\xb8o\\x1f\\xf7\\xf1\\xe7\\x9a\\x01\\xbco\\xe4\\xe1\\xffO=\\xec\\x7f\\xd6\\xb0>\\xae\\xbfN=1\\xa0\\xdf\\x0e0\\x86\\x080}\\x01x\\xee\\xb9\\xe7\\xba\\xfb\\xef\\xbf\\xbf\\xbb\\xe9\\xa6\\x9b\\xba\\xc5\\x8b\\x17\\xfb\\xc7\"\\xd1?\\x16b\\x81X\\xc2\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\xb4g \\xee\\xb3\\xc7}\\xf7\\xb8\\x0f\\x1f\\xf7\\xe5\\xa7\\xef\\xd7{;\\xda\\x80?\\xd7\\xba\\x95\\xef\\xfc\\xff\\x89\\'\\xfc+W\\x89s\\xf9R\\x1ej\\x11\\xbf\"\\xf0\\xc5\\xb9N\\x8c\\xf7\\xd5\\xc1~\\xf8\\xf0\\xe1\\xee\\xf1\\xc7\\x1f\\xef>\\xf5\\xa9Ou\\x1b7n\\xec\\x16.\\\\(\\x08\\x08\\x02\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\x9cG\\x03q\\x9f<\\xee\\x9b\\xc7}\\xf4\\xb8\\xaf\\x1e\\xf7\\xd9\\xcd?u\\xe6\\x9f\\xb9\\xd61f\\xd0\\x98E\\xcf\\xe5\\xec\\xeb\\xbf5\\xb5\\x02{\\xf6\\xecyO99\\xcf\\xcfu\\x82\\xbc\\xaf\\xfe&(\\xb5\\xab{\\xe2\\x89\\'\\xba\\xbb\\xee\\xba\\xab\\xdb\\xb1cG\\xf7\\xde\\xf7\\xbe\\xd7\\xc5\\xff<^\\xfc\\xcbv\\xb0\\xfe\\xd6\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\x18\\xb8\\x81\\xb8\\xcf\\x1d\\xf7\\xbd\\xe3>x\\xdc\\x17\\x8f\\xfb\\xe4f\\x9d\\xfa\\xb3\\xcei\\xd6\\xf4\\xf9\\x98A\\r\\xe4\\xe7w\\x05&J\\x85y\\xfc4\\'\\xca\\xe6\\x18\\xe3\\x8f\\x0b\\x1c;v\\xac\\xfb\\xeew\\xbf\\xdb=\\xf2\\xc8#\\xdd\\x1dw\\xdcq\\xfc\\xa1G+W\\xae\\xf4\\x8f\\xd0\\xc0\\xff\\x11\\x12\\x1e\\x84\\x17\\x06\\x18`\\x80\\x01\\x06\\x18``<\\x06\\xe2\\xbet<\\x9c?\\xee[\\xc7}\\xec\\xb8\\xaf\\x1d\\xf7\\xb9\\xcd<\\xe7|\\xe0\\x7f{\\xcdc\\xe6,\\xde\\'\\xca\\xab\\x97>\\xac@9!\\xbb\\xca\\xeb\\x9b6\\xc5\\xf9\\xdb\\x14\\xb3\\xd7~\\xff\\xfe\\xfd\\xdd\\x93O>\\xd9=\\xf0\\xc0\\x03\\xc7\\x9fu\\xf4\\xe6\\x9bo\\xee6m\\xda\\xd4-]\\xbaT\\x1c\\x10\\x07\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06R\\x1b\\x88\\xfb\\xc4q\\xdf8\\xee#\\xc73\\xf4\\xc7}\\xe6\\xb8\\xef\\x1c\\xf7\\xa1g\\xdf\\xaf\\xf6\\xf7\\xf37\\xe3\\xc4\\x8c\\x19\\xb3f\\x1ff^\\xc70k\\x05J\\x15\\xfbx99\\xbf\\xb6A\\xce\\xdf\\x06\\x99\\xef\\xda\\xc7C\\x96\\x9ey\\xe6\\x99\\xe3?\\xaf\\xf4\\xf0\\xc3\\x0fw\\x9f\\xff\\xfc\\xe7\\x8f\\xff>\\xd2O~\\xf2\\x93\\xc7/\\x827\\xdcp\\xc3\\xf1\\x9fiZ\\xbf~}\\xb7f\\xcd\\x9an\\xd5\\xaaU\\xdd\\xf2\\xe5\\xcb\\xbb\\xc9\\xc9\\xc9\\xee\\xc2\\x0b/\\xec\\x16-Z\\xe4\\xd5\\x1a0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\x9c7\\x03q\\x9f4\\xee\\x9b\\xc6}\\xd4\\xb8\\xaf\\x1a\\xf7Y\\xe3\\xbek\\xfc\\\\~\\xdc\\x97\\x8d\\xc1>\\xee\\xdb\\xee\\xdc\\xb9\\xf3\\xf8}\\xdd\\xb8\\xcf\\x1b?\\xab\\x1f\\xf7\\x81=|\\xbf\\xff\\xf3J\\xcc51[\\xc6\\x8c9k\\xec\\xf4\\xd7>\\xad@yB\\x86\\xeb\\xca\\xc9\\xfa\\xc5|\\x07Q\\x1f\\xd7\\xc6\\xe6s\\x9e\\x9c\\'\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x188\\x87\\x06~\\x11\\xb3e\\x9ff]\\xc7r\\x8a\\x15(\\'jm\\xa95\\x7fv\\x0eqx\\x98\\xce\\x18\\x9fc\\xc0yt\\xa1g\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81se f\\xc9\\x98)O1n\\xfa\\xbf\\xfb\\xb8\\x02/\\xbd\\xf4\\xd2\\x92r\\xe2\\xfe\\xe0\\\\!\\xf1\\xdfqAb\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xda6\\x103d\\xcc\\x92}\\x9cq\\x1d\\xd3<V\\xa0\\x9c\\xc0\\xdf)\\xaf\\x7fo#\\xb6\\xbd\\x11\\x9d?\\xe7\\x8f\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xc6e f\\xc6\\x98\\x1d\\xe71b\\xfa\\x90\\xbe\\xaf@y\\xf8\\xc6\\xf6\\x02\\xe5\\xf5qa\\xf1u]\\x88\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81f\\r\\xbc\\x1e3c\\xdf\\xe7Z\\xc7w\\x06+PN\\xe8\\xca\\xb2!\\x0f\\xd9\\x94\\xcdnJ\\xcf\\xb3\\xe0y\\x16\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xb6\\x81C1+\\x9e\\xc1h\\xe9C\\x1bZ\\x81\\x89\\xf2k\\x1c\\xfe]\\x89\\x00o\\x08\\x01B\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\x90\\xd6\\xc0\\x1b1\\x1b\\x96Yv\\xa2\\xa1y\\xd6\\xa1\\x8e\\xb2\\x02\\xa5\\xf0\\\\W~\\xbe\\xe3/m\\xf6\\xb4\\x9b\\xbdv5\\xf4\\xf5\\x94h\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x1a1\\x10\\xb3`\\xcc\\x84\\xa3\\xcc\\x92>\\xa7\\xd1\\x15\\xd8\\xb7o\\xdf{\\xcb\\x89\\x7fJ\\x04\\x10\\x01\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81\\x1c\\x06b\\x06\\x8cY\\xb0\\xd11\\xd6a\\x9f\\xed\\n\\x1c=z\\xf4_\\x95\\xcd\\xfeK\\x1b>\\xc7\\x86w\\x9e\\x9dg\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06R\\x1a\\xf8e\\xcc~g;?\\xfa\\xfc\\x01\\xac\\xc0\\xe1\\xc3\\x87W\\x94\\x12\\xf4\\xac\\x0bA\\xca\\x0b\\x81\\x87j5\\xf2P-\\xfb\\xd3\\xfed\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\x18\\xc5@\\xccz1\\xf3\\r`tu\\x13j\\xae@y\\x12\\x88\\x7fYp\\xfc\\xafQP\\xf9\\x1c\\x17#\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0?\\x06b\\xb6\\x8b\\x19\\xaf\\xe6\\xcc\\xe8k\\rl\\x05\\x0e\\x1e<xq\\x81\\xf2\\xad\\xf2\\xfa\\xa6\\xcd\\xdb\\x9f\\xcd\\xeb\\\\8\\x17\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c00\\x1f\\x031\\xcb\\xc5L\\x17\\xb3\\xdd\\xc0\\xc6U7g\\\\+P~>dG\\xc1\\xf5\\xb3\\xf9\\x00\\xf31.D\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@/\\x0c\\xfc,f\\xb9q\\xcd\\x89\\xbe\\xee\\x80W`\\xf7\\xee\\xdd\\x0bK9\\xfa7e#{\\x92@?\\'\\xee\\xb9\\x02\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\xbf\\x06~\\x19\\xb3[\\xccp\\x03\\x1eQ\\xdd\\xb4s\\xb1\\x02/\\xbf\\xfc\\xf2\\xd2\\x12\\x01\\xbeQ^\\xdfP\\xf5zQ\\xf5\\\\x\\xfb{\\xe1un\\x9c\\x1b\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x81si f\\xb4o\\xc4\\xccv.fC\\xff\\x8dD+P\\x9e@bC\\xc1\\xf5G\"\\x80\\x08\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\x9cw\\x03\\x7f\\x143Z\\xa2\\x91\\xd4M=\\x1f+P\\x1eZ\\xf2\\xa1\\xb2\\xd9\\x7fl\\xc3\\x9f\\xf7\\r\\x7f.\\xcb\\xa2\\xff\\x96\\x92\\xcd\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@?\\x0c\\xfc8f\\xb2\\xf31\\x0b\\xfao&^\\x81\\x82\\xee\\xb7\\xca\\xebO\\x84\\x00!\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\x18\\xaf\\x81\\x98\\xbdb\\x06K<\\x82\\xba\\xe9}X\\x81\\xf2,\\x93\\xb7\\x16\\x88\\x7fn\\xc3\\x8fw\\xc3[_\\xeb\\xcb\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0@>\\x031k\\xc5\\xcc\\xd5\\x87\\xd9\\xcf1X\\x81\\xe9\\x15\\x98(?\\x7fr{\\xb9 \\xfd\\xdcE)\\xdfE\\xc99w\\xce\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xa8n\\xe0\\xe71c\\x95\\x81kbz\\xe8\\xf2\\xd6\\n\\xf4n\\x05\\xca\\xc6\\xffp\\xa9T\\x07\\\\\\x00\\xaa_\\x00\\xfc\\xccU?~\\xe6\\xcayp\\x1e\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\xc6f`j\\x96\\xfap\\xef\\x06=\\x07d\\x05\\xe6Z\\x81R\\xab>P\\xf0~\\xb7\\x84\\x00\\xbf>\\xd0\\x05rl\\x17H\\xa1Ihb\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\x18\\x80\\x817bv\\x8a\\x19j\\xae\\x19\\xcb\\xfb\\xac@\\xefW\\xe0\\xd0\\xa1CW\\x14\\xcc_-\\xaf\\x7f3\\x80\\x8di\\x90\\x153\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\xa0\\x8a\\x81\\x98\\x91bV\\x8a\\x99\\xa9\\xf7\\x83\\x9d\\x03\\xb4\\x02g\\xb2\\x02G\\x8e\\x1c\\xb9\\xa0\\xe0\\xbe\\xa5\\xbc\\xee/!\\xe0\\x9f\\xc4\\x00\\xa5\\x96\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x12\\x1a\\xf8\\xa7\\x98\\x89b6\\x8a\\x19\\xe9Lf*\\x1fk\\x05\\x9a\\\\\\x81\\xf2\\xd0\\x96+\\xcbF\\xffJy}=\\xe1\\x86\\xafR\\x0b\\xad\\x9b\\x7f,\\x19`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18h\\xca@\\xcc>_\\x89Y\\xa8\\xc9!\\xceA[\\x81\\xb3]\\x81\\xdd\\xbbw/,\\x9b \\x9e4\\xf0\\xf7\\xcb\\xeb\\xdf\\xba\\x805u\\x01\\x132<\\xf4\\x8d\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x819\\x0c\\xc4\\x8c\\x13\\xb3N\\xcc<1\\xfb\\x9c\\xed\\xfc\\xe4\\xf3\\xad\\xc0`V \\x1e\\xfeR6\\xc6G\\xcb\\x06\\xf9\\xc3\\xf2\\xfa\\x7f\\xc4\\x001\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06Z3\\x10\\xb3L\\xcc4\\xe5\\xb8?\\xea!\\xfe\\x83\\x19W\\xdd\\x90q\\xae\\xc0\\xbe}\\xfb\\x16\\x97\\r\\xf3\\x89\\xf2\\xfaty\\xfd\\xeb\\xf2\\xaa,Z\\x03\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18\\xe8\\xab\\x81\\x98Ybv\\xf9D\\xcc2\\xe3\\x9c\\x95|m+0\\xf8\\x15\\x98\\xfa\\x95\\x82\\xbf[6\\xd4\\x91\\xf2\\xfa\\x0f\\xe5\\xb5\\xaf\\x1b\\xdfq97\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\x0c\\xdf@\\xcc$G\\xcaw\\xfa\\x7f\\xd7\\xaf\\xee\\x1b\\xfc8\\xea\\x06\\x9e\\xcf\\x15\\xf8\\xe1\\x0f\\x7f8Y6Z\\xfc6\\x81\\xdf+\\xaf?-\\xafo\\n\\x02\\x82\\x08\\x03\\x0c0\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c\\x8c\\xcb@\\xcc\\x1cS\\xb3G\\xcc \\xb7\\xc4Lr>g\"\\xffm+\\x90v\\x05b\\xf3\\x1d=z\\xf47Ky\\xdb]6\\xfc\\xcb\\xe5\\xf5W\\xe3\\xda\\xf8\\xbe\\xae\\x7fT\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x18Ha f\\x8a\\x97c\\xc6\\x88Y\\xc3\\xc0\\x9fv\\xdct\\xc3\\xfb\\xbe\\x02\\xe5gn\\x16M\\xfd\\xc8\\xc0o\\x97:\\xf7\\x9f\\xca\\xeb\\x1f\\x97\\xcd\\xfb\\x0b\\x17\\xea\\x14\\x17j\\x0f\\xb7\\x1b\\xfe\\xc3\\xed\\x9cc\\xe7\\x98\\x01\\x06\\x18`\\x80\\x01\\x06j\\x1b\\xf8E\\xcc\\x0cS\\xb3\\xc3o\\xc7,\\x113E\\xdf\\xe7\\x1e\\xc7g\\x05\\xac\\xc0\\x1c+p\\xe0\\xc0\\x81K\\xcb\\xb3p\\xfe\\xf3\\xb2\\xb1\\xef+\\xafO\\x94\\xd7\\xff^\\xa2\\xc0\\xcf\\xcb\\xeb\\xff\\x13\\x07\\xc4\\x01\\x06\\x18`\\x80\\x01\\x06\\x18`\\x80\\x01\\x06\\x06m \\xee\\xf3\\xff<f\\x80\\xa9Y\\xe0\\xbe\\x98\\rbF\\x98c\\x84\\xf0.+`\\x05\\x86\\xb8\\x02\\xe5b\\xb0\\xbc\\\\\\x08n(\\xb5\\xef\\xb6\\xf2\\xf6\\xbex\\xa8Oy\\x1b?\\xdf\\xb3\\xb7\\xbc\\xefPy\\xfb\\x93\\xf2\\xf6\\xf5\\xf2\\xf6\\xd7\\xe5\\xf5\\x1f\\xcb\\x9fkWG_\\xcf\\x9a2\\xc0\\x00\\x03\\x0c0\\xc0\\x00\\x03\\x0c00O\\x03q\\x9f<\\xee\\x9bO\\xddG\\x8f\\xfb\\xeaq\\x9f}oy\\xfd\\xbd\\xa9\\xfb\\xf2q\\x9f>\\xee\\xdb\\xdfP\\xde\\xb7|\\x883\\x8c\\xdbt\\xe6+\\xf0\\xff\\x01\\xdb\\xc4Fz~\\xbf&2\\x00\\x00\\x00\\x00IEND\\xaeB`\\x82'\n"
  },
  {
    "path": "maestro/jit_funcs.py",
    "content": "import warnings\n\nimport numpy as np\n\nfrom maestro import config\nfrom maestro.config import print_to_logfile\n\ntry:\n    from numba import jit\nexcept:  # pylint: disable=bare-except\n    jit = lambda x: x\n    print_to_logfile(\"Numba not installed. Visualization will be slower.\")\ntry:\n    from numba.core.errors import NumbaWarning\n\n    warnings.simplefilter(\"ignore\", category=NumbaWarning)\nexcept:  # pylint: disable=bare-except\n    pass\n\n\n@jit\ndef lerp(start, stop, t):\n    return start + t * (stop - start)\n\n\n@jit(forceobj=True)\ndef bin_average(arr: np.ndarray, n, include_remainder=False, func=None):\n    if func is None:\n        func = np.max\n\n    remainder = arr.shape[1] % n\n    if remainder == 0:\n        return func(arr.reshape(arr.shape[0], -1, n), axis=1)\n\n    avg_head = func(arr[:, :-remainder].reshape(arr.shape[0], -1, n), axis=1)\n    if include_remainder:\n        avg_tail = func(\n            arr[:, -remainder:].reshape(arr.shape[0], -1, remainder), axis=1\n        )\n        return np.concatenate((avg_head, avg_tail), axis=1)\n\n    return avg_head\n\n\n@jit(forceobj=True)\ndef render(\n    num_bins,\n    freqs: np.ndarray,\n    frame,\n    visualizer_height,\n    mono=None,\n    include_remainder=None,\n    func=None,\n):\n    \"\"\"\n    mono:\n        True:  forces one-channel visualization\n        False: forces two-channel visualization\n        None:  if freqs[0] == freqs[1], one-channel, else two\n    \"\"\"\n    if func is None:\n        func = np.max\n\n    if mono is None:\n        mono = np.array_equal(freqs[0], freqs[1])\n\n    if not mono:\n        gap_bins = 1 if num_bins % 2 else 2\n        num_bins = (num_bins - 1) // 2\n    else:\n        gap_bins = 0\n        freqs[0, :, frame] = (freqs[0, :, frame] + freqs[1, :, frame]) / 2\n\n    num_vertical_block_sizes = len(config.VERTICAL_BLOCKS) - 1\n    freqs = np.round(\n        bin_average(\n            freqs[:, :, frame],\n            num_bins,\n            (\n                (freqs.shape[-2] % num_bins) > num_bins / 2\n                if include_remainder is None\n                else include_remainder\n            ),\n            func=func,\n        )\n        / 80\n        * visualizer_height\n        * num_vertical_block_sizes\n    )\n\n    arr = np.zeros((int(not mono) + 1, visualizer_height, num_bins))\n    for b in range(num_bins):\n        bin_height = freqs[0, b]\n        h = 0\n        while bin_height > num_vertical_block_sizes:\n            arr[0, h, b] = num_vertical_block_sizes\n            bin_height -= num_vertical_block_sizes\n            h += 1\n        arr[0, h, b] = bin_height\n        if not mono:\n            bin_height = freqs[1, b]\n            h = 0\n            while bin_height > num_vertical_block_sizes:\n                arr[1, h, b] = num_vertical_block_sizes\n                bin_height -= num_vertical_block_sizes\n                h += 1\n            arr[1, h, b] = bin_height\n\n    res = []\n    for h in range(visualizer_height - 1, -1, -1):\n        s = \"\"\n        for b in range(num_bins):\n            if mono:\n                s += config.VERTICAL_BLOCKS[arr[0, h, b]]\n            else:\n                s += config.VERTICAL_BLOCKS[arr[0, h, num_bins - b - 1]]\n        if not mono:\n            s += \" \" * gap_bins\n            for b in range(num_bins):\n                s += config.VERTICAL_BLOCKS[arr[1, h, b]]\n        res.append(s)\n\n    return res"
  },
  {
    "path": "maestro/mac_presence.py",
    "content": "# BIG thanks to @othalan on StackOverflow for this\n# adapted from https://stackoverflow.com/questions/69965175/pyobjc-accessing-mpnowplayinginfocenter\n\nfrom maestro.helpers import print_to_logfile  # pylint: disable=unused-import\n\n# pylint: disable=no-name-in-module,import-error\nfrom AppKit import (\n    NSImage,\n    NSObject,\n    # NSMakeRect,\n    # NSCompositingOperationSourceOver,\n    # NSCompositingOperationCopy,\n)\nfrom Foundation import NSMutableDictionary\nfrom MediaPlayer import (\n    MPNowPlayingInfoCenter,\n    MPNowPlayingInfoPropertyElapsedPlaybackTime,\n    MPRemoteCommandCenter,\n    MPMediaItemArtwork,\n    MPMediaItemPropertyTitle,\n    MPMediaItemPropertyArtist,\n    MPMediaItemPropertyPlaybackDuration,\n    MPMediaItemPropertyArtwork,\n    # MPMusicPlaybackState,\n    MPMusicPlaybackStatePlaying,\n    MPMusicPlaybackStatePaused,\n    # MPMusicPlaybackStateStopped,\n)\nfrom PyObjCTools import AppHelper\n\n\nclass AppDelegate(NSObject):  # so Python doesn't bounce in the dock\n    def applicationDidFinishLaunching_(self, _aNotification):\n        pass\n\n    def sayHello_(self, _sender):\n        pass\n\ndef app_helper_loop():\n    # ns_application = NSApplication.sharedApplication()\n    # logo_ns_image = NSImage.alloc().initByReferencingFile_(\n    #     \"./maestro_icon.png\"\n    # )\n    # ns_application.setApplicationIconImage_(logo_ns_image)\n\n    # # we must keep a reference to the delegate object ourselves,\n    # # NSApp.setDelegate_() doesn't retain it. A local variable is\n    # # enough here.\n    # delegate = AppDelegate.alloc().init()\n    # NSApp().setDelegate_(delegate)\n\n    AppHelper.runEventLoop()\n\n# pylint: enable\n\n\nclass MockQueue:  # enable testing this file\n    def put(self, *args, **kwargs):\n        pass\n\n    def empty(self):\n        return True\n\n\nclass MockInt:\n    def __init__(self) -> None:\n        self._value = 0\n\n    @property\n    def value(self):\n        return self._value\n\n    @value.setter\n    def value(self, value):\n        self._value = value\n\n\nclass MacNowPlaying:\n    def __init__(self):\n        # get the remote command center\n        # ... which is how the OS sends commands to the application\n        self.cmd_center = MPRemoteCommandCenter.sharedCommandCenter()\n\n        # get the now playing info center\n        # ... which is how this application notifies MacOS of what is playing\n        self.info_center = MPNowPlayingInfoCenter.defaultCenter()\n\n        # enable command handlers\n        self.cmd_center.playCommand().addTargetWithHandler_(self.play_handler)\n        self.cmd_center.pauseCommand().addTargetWithHandler_(self.pause_handler)\n        self.cmd_center.togglePlayPauseCommand().addTargetWithHandler_(\n            self.toggle_handler\n        )\n        self.cmd_center.nextTrackCommand().addTargetWithHandler_(\n            self.next_handler\n        )\n        self.cmd_center.previousTrackCommand().addTargetWithHandler_(\n            self.prev_handler\n        )\n        self.cmd_center.seekBackwardCommand().addTargetWithHandler_(\n            self.seek_backward_handler\n        )\n        self.cmd_center.seekForwardCommand().addTargetWithHandler_(\n            self.seek_forward_handler\n        )\n        self.cmd_center.changePlaybackPositionCommand().addTargetWithHandler_(\n            self.change_position_handler\n        )\n        # NOTE: disabling these handlers shows prev/next track buttons instead\n        # NOTE:  in the control center and touch bar\n        self.cmd_center.skipForwardCommand().addTargetWithHandler_(\n            self.seek_forward_handler\n        )\n        self.cmd_center.skipBackwardCommand().addTargetWithHandler_(\n            self.seek_backward_handler\n        )\n        # self.cmd_center.stopCommand().addTargetWithHandler_(self.stop)\n\n        self.title_queue = MockQueue()\n        self.artist_queue = MockQueue()\n        self.paused = False\n        self.pos = 0\n        self.length = 0\n        self.q = MockQueue()\n        self.cover = None\n\n        self.title = \"\"\n        self.artist = \"\"\n        self._cover = None\n\n    def play_handler(self, _event):\n        \"\"\"\n        Handle an external 'playCommand' event.\n        \"\"\"\n        if self.info_center.playbackState() == MPMusicPlaybackStatePaused:\n            self.q.put(\" \")\n\n        return 0\n\n    def pause_handler(self, _event):\n        \"\"\"\n        Handle an external 'pauseCommand' event.\n        \"\"\"\n        if self.info_center.playbackState() == MPMusicPlaybackStatePlaying:\n            self.q.put(\" \")\n\n        return 0\n\n    def toggle_handler(self, _event):\n        \"\"\"\n        Handle an external 'togglePlayPauseCommand' event.\n        \"\"\"\n        self.q.put(\" \")\n\n        return 0\n\n    def next_handler(self, _event):\n        \"\"\"\n        Handle an external 'nextTrackCommand' event.\n        \"\"\"\n        self.q.put(\"n\")\n        return 0\n\n    def prev_handler(self, _event):\n        \"\"\"\n        Handle an external 'previousTrackCommand' event.\n        \"\"\"\n        self.q.put(\"b\")\n        return 0\n\n    def seek_backward_handler(self, _event):\n        \"\"\"\n        Handle an external 'seekBackwardCommand' event.\n        \"\"\"\n        self.pos -= 10\n        return 0\n\n    def seek_forward_handler(self, _event):\n        \"\"\"\n        Handle an external 'seekForwardCommand' event.\n        \"\"\"\n        self.pos += 10\n        return 0\n\n    def change_position_handler(self, event):\n        # get time from event\n        time = round(event.positionTime())\n        self.pos = time\n        return 0\n\n    def stop(self):\n        \"\"\"\n        Call this method to update 'Now Playing' state to stopped\n        \"\"\"\n        self.q.put(\"q\")\n        return 0\n\n    def pause(self):\n        \"\"\"\n        Call this method to update 'Now Playing' state to paused\n        \"\"\"\n        self.info_center.setPlaybackState_(MPMusicPlaybackStatePaused)\n        return 0\n\n    def resume(self):\n        \"\"\"\n        Call this method to update 'Now Playing' state to playing\n        \"\"\"\n        self.info_center.setPlaybackState_(MPMusicPlaybackStatePlaying)\n        return 0\n\n    def update(self):\n        \"\"\"\n        Call this method to update the 'Now Playing' info\n        \"\"\"\n\n        nowplaying_info = NSMutableDictionary.dictionary()\n\n        if not self.artist_queue.empty():\n            while not self.artist_queue.empty():\n                self.artist = \"\"\n                c = self.artist_queue.get()\n                while c != \"\\n\":\n                    self.artist += c\n                    c = self.artist_queue.get()\n\n        if not self.title_queue.empty():\n            while not self.title_queue.empty():\n                self.title = \"\"\n                c = self.title_queue.get()\n                while c != \"\\n\":\n                    self.title += c\n                    c = self.title_queue.get()\n\n        # Set basic track information\n        nowplaying_info[MPMediaItemPropertyTitle] = self.title\n        nowplaying_info[MPMediaItemPropertyArtist] = self.artist\n        nowplaying_info[MPMediaItemPropertyPlaybackDuration] = self.length\n        nowplaying_info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = self.pos\n\n        if self.cover is not None:\n            # print_to_logfile(\"cover len: {}\".format(len(self.cover)))\n            img = NSImage.alloc().initWithData_(self.cover)\n\n            # def resize(size):\n            #     new = NSImage.alloc().initWithSize_(size)\n            #     new.lockFocus()\n            #     img.drawInRect_fromRect_operation_fraction_(\n            #         NSMakeRect(0, 0, size.width, size.height),\n            #         NSMakeRect(0, 0, img.size().width, img.size().height),\n            #         NSCompositingOperationCopy,\n            #         1.0,\n            #     )\n            #     new.unlockFocus()\n            #     return new\n\n            art = MPMediaItemArtwork.alloc().initWithBoundsSize_requestHandler_(\n                img.size(), lambda size: img\n            )\n\n            # print_to_logfile(\"artwork size: {}\".format(img.size()))\n            nowplaying_info[MPMediaItemPropertyArtwork] = self._cover = art\n            self.cover = None\n        else:\n            if self._cover is not None:\n                nowplaying_info[MPMediaItemPropertyArtwork] = self._cover\n\n        # Set the metadata information for the 'Now Playing' service\n        self.info_center.setNowPlayingInfo_(nowplaying_info)\n\n        if self.paused:\n            self.pause()\n        else:\n            self.resume()\n\n        # self.info_center.setObject_for_key_(self.artist, \"artist\")\n        # self.info_center.setObject_for_key_(self.length, \"length\")\n        # self.info_center.setObject_for_key_(self.pos, \"pos\")\n\n        # # self.info_center.title = title\n        # # self.info_center.artist = artist\n        # # self.info_center.length = length\n        # # self.info_center.pos = pos\n\n        # nowplaying_info = NSMutableDictionary.dictionary()\n\n        # nowplaying_info[MPMediaItemPropertyTitle] = title\n        # nowplaying_info[MPMediaItemPropertyArtist] = artist\n        # nowplaying_info[MPMediaItemPropertyPlaybackDuration] = length\n        # nowplaying_info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = pos\n\n        # # self.info_center.setNowPlayingInfo_(nowplaying_info)\n\n        # if paused:\n        #     self.info_center.setPlaybackState_(MPMusicPlaybackStatePaused)\n        # else:\n        #     self.info_center.setPlaybackState_(MPMusicPlaybackStatePlaying)\n\n        return 0\n"
  },
  {
    "path": "maestro/main.py",
    "content": "# pylint: disable=possibly-used-before-assignment\n\n# region imports\nimport curses\nimport multiprocessing\nimport os\nimport sys\nimport threading\n\nimport click\nimport msgspec\n\nfrom collections import defaultdict\nfrom queue import Queue\nfrom random import randint\nfrom shutil import move, copy, rmtree\nfrom time import sleep, time\n\nfrom maestro import config\nfrom maestro import helpers\nfrom maestro.__version__ import VERSION\nfrom maestro.config import print_to_logfile  # pylint: disable=unused-import\n\n# endregion\n\n# region utility functions/classes\n\n\ndef _play(\n    stdscr,\n    playlist,\n    volume,\n    loop,\n    clip_mode,\n    reshuffle,\n    update_discord,\n    visualize,\n    stream,\n    username,\n    password,\n    lyrics,\n    translated_lyrics,\n):\n    helpers.init_curses(stdscr)\n\n    can_mac_now_playing = False\n    if sys.platform == \"darwin\":\n        try:\n            from maestro.mac_presence import (\n                MacNowPlaying,\n                AppDelegate,\n                app_helper_loop,\n            )\n\n            # pylint: disable=no-name-in-module,import-error\n            from AppKit import (\n                NSApp,\n                NSApplication,\n                # NSApplicationDelegate,\n                NSApplicationActivationPolicyProhibited,\n                NSDate,\n                NSRunLoop,\n            )\n\n            # pylint: enable\n\n            mac_now_playing = MacNowPlaying()\n            can_mac_now_playing = True\n        except (\n            Exception  # pylint: disable=bare-except,broad-except\n        ) as mac_import_err:\n            print_to_logfile(\"macOS PyObjC import error:\", mac_import_err)\n\n    if loop:\n        next_playlist = playlist[:]\n        helpers.bounded_shuffle(next_playlist, reshuffle)\n    else:\n        next_playlist = None\n\n    player = helpers.PlaybackHandler(\n        stdscr,\n        playlist,\n        clip_mode,\n        visualize,\n        stream,\n        (username, password) if username and password else (None, None),\n        lyrics,\n        translated_lyrics,\n    )\n    player.volume = volume\n    if can_mac_now_playing:\n        player.can_mac_now_playing = True\n        player.mac_now_playing = mac_now_playing\n\n        player.mac_now_playing.title_queue = Queue()\n        player.mac_now_playing.artist_queue = Queue()\n        player.mac_now_playing.q = Queue()\n\n        ns_application = NSApplication.sharedApplication()\n        ns_application.setActivationPolicy_(\n            NSApplicationActivationPolicyProhibited\n        )\n\n        # NOTE: keep ref to delegate object, setDelegate_ doesn't retain\n        delegate = AppDelegate.alloc().init()\n        NSApp().setDelegate_(delegate)\n\n        app_helper_process = multiprocessing.Process(\n            daemon=True,\n            target=app_helper_loop,\n        )\n        app_helper_process.start()\n    if update_discord:\n        player.threaded_initialize_discord()\n\n    prev_volume = volume\n    while player.i in range(len(player.playlist)):\n        player.playback.load_file(player.song_path)\n\n        if player.song.set_clip in player.song.clips:\n            player.clip = player.song.clips[player.song.set_clip]\n        else:\n            player.clip = (0, player.playback.duration)\n        player.paused = False\n\n        player.lyrics = (\n            player.song.parsed_override_lyrics or player.song.parsed_lyrics\n        )\n        player.lyric_pos = None\n        if player.lyrics is not None:\n            player.lyrics_scroller = helpers.Scroller(\n                len(player.lyrics), player.screen_height - 1\n            )\n        player.translated_lyrics = player.song.parsed_translated_lyrics\n\n        player.playback.play()\n        player.set_volume(volume)\n        player.update_metadata()\n\n        # latter is clip-agnostic, former is clip-aware\n        player.duration = player.playback.duration\n        if player.clip_mode:\n            clip_start, clip_end = player.clip\n            player.duration = clip_end - clip_start\n            player.seek(clip_start)\n\n        start_time = pause_start = time()\n\n        player.last_timestamp = player.playback.curr_pos\n        next_song = 1  # -1 if going back, 0 if restarting, +1 if next song\n        player.restarting = False\n        while True:\n            if not player.playback.active or (\n                player.clip_mode and player.playback.curr_pos > player.clip[1]\n            ):\n                next_song = not player.looping_current_song\n                break\n\n            # fade in first 2 seconds of clip\n            if (\n                player.clip_mode\n                and clip_start > 0.01  # if clip doesn't start at beginning\n                and clip_end - clip_start > 5  # if clip is longer than 5 secs\n                and player.playback.curr_pos < clip_start + 2\n            ):\n                player.set_volume(\n                    player.volume * (player.playback.curr_pos - clip_start) / 2\n                )\n            else:\n                player.set_volume(player.volume)\n\n            if player.can_mac_now_playing:  # macOS Now Playing event loop\n                try:\n                    if player.update_now_playing:\n                        player.mac_now_playing.update()\n                        player.update_now_playing = False\n                    NSRunLoop.currentRunLoop().runUntilDate_(\n                        NSDate.dateWithTimeIntervalSinceNow_(0.05)\n                    )\n                except Exception as e:\n                    print_to_logfile(\"macOS Now Playing error:\", e)\n                    player.can_mac_now_playing = False\n\n            if (\n                player.can_mac_now_playing\n                and not player.mac_now_playing.q.empty()\n            ):\n                c = player.mac_now_playing.q.get()\n                if c in \"nN\":\n                    if player.i == len(player.playlist) - 1 and not loop:\n                        pass\n                    else:\n                        next_song = 1\n                        player.playback.stop()\n                        break\n                elif c in \"bB\":\n                    if player.i == 0:\n                        pass\n                    else:\n                        next_song = -1\n                        player.playback.stop()\n                        break\n                elif c in \"rR\":\n                    player.playback.stop()\n                    next_song = 0\n                    break\n                elif c in \"qQ\":\n                    player.ending = True\n                    break\n                elif c == \" \":\n                    player.paused = not player.paused\n\n                    if player.paused:\n                        player.playback.pause()\n                        pause_start = time()\n                    else:\n                        player.playback.resume()\n                        start_time += time() - pause_start\n\n                    if player.can_mac_now_playing:\n                        player.mac_now_playing.paused = player.paused\n                        if player.paused:\n                            player.mac_now_playing.pause()\n                        else:\n                            player.mac_now_playing.resume()\n                        player.update_now_playing = True\n\n                    player.update_screen()\n            else:\n                c = player.stdscr.getch()  # int\n                next_c = player.stdscr.getch()\n                while next_c != -1:\n                    c, next_c = next_c, player.stdscr.getch()\n\n                if c != -1:\n                    try:\n                        ch = chr(c)\n                        if ch in \"\\b\\x7f\":\n                            c = curses.KEY_DC\n                        elif ch in \"\\r\\n\":\n                            c = curses.KEY_ENTER\n                    except (ValueError, OverflowError):\n                        ch = None\n\n                    if c == curses.KEY_UP:\n                        player.scroll_backward()\n                        player.update_screen()\n                    elif c == curses.KEY_DOWN:\n                        player.scroll_forward()\n                        player.update_screen()\n                    elif c == curses.KEY_SLEFT:\n                        if player.want_lyrics:\n                            player.lyrics_width += 1\n                            player.update_screen()\n                    elif c == curses.KEY_SRIGHT:\n                        if player.want_lyrics:\n                            player.lyrics_width -= 1\n                            player.update_screen()\n                    elif c == 337:  # SHIFT + UP\n                        if player.scroller.pos > 0:\n                            if player.scroller.pos == player.i:\n                                player.i -= 1\n                            elif player.scroller.pos == player.i + 1:\n                                player.i += 1\n                            (\n                                player.playlist[player.scroller.pos],\n                                player.playlist[player.scroller.pos - 1],\n                            ) = (\n                                player.playlist[player.scroller.pos - 1],\n                                player.playlist[player.scroller.pos],\n                            )\n                            player.scroller.scroll_backward()\n                    elif c == 336:  # SHIFT + DOWN\n                        if player.scroller.pos < player.scroller.num_lines - 1:\n                            if player.scroller.pos == player.i:\n                                player.i += 1\n                            elif player.scroller.pos == player.i - 1:\n                                player.i -= 1\n                            (\n                                player.playlist[player.scroller.pos],\n                                player.playlist[player.scroller.pos + 1],\n                            ) = (\n                                player.playlist[player.scroller.pos + 1],\n                                player.playlist[player.scroller.pos],\n                            )\n                            player.scroller.scroll_forward()\n                    else:\n                        if player.prompting is None:\n                            if c == curses.KEY_LEFT:\n                                player.seek(\n                                    player.playback.curr_pos - config.SCRUB_TIME\n                                )\n                                player.update_screen()\n                            elif c == curses.KEY_RIGHT:\n                                player.seek(\n                                    player.playback.curr_pos + config.SCRUB_TIME\n                                )\n                                player.update_screen()\n                            elif c == curses.KEY_ENTER:\n                                if player.focus == 0:\n                                    # pylint: disable=invalid-unary-operand-type\n                                    # -2 because pos can be 0\n                                    next_song = -(player.scroller.pos) - 2\n                                    player.playback.stop()\n                                    break\n                                elif player.focus == 1:\n                                    if (\n                                        helpers.is_timed_lyrics(player.lyrics)\n                                        and player.lyric_pos is not None\n                                    ):\n                                        player.seek(\n                                            player.lyrics[player.lyric_pos].time\n                                        )\n                                        player.snap_back()\n                                        player.update_screen()\n                            elif c == curses.KEY_DC:\n                                if len(player.playlist) > 1:\n                                    player.scroller.num_lines -= 1\n                                    if (\n                                        player.scroller.pos == player.i\n                                    ):  # deleted current song\n                                        next_song = 3\n                                        player.playback.stop()\n                                        break\n\n                                    deleted_song = player.playlist[\n                                        player.scroller.pos\n                                    ]\n                                    del player.playlist[player.scroller.pos]\n\n                                    if loop:\n                                        for i in range(len(next_playlist)):\n                                            if next_playlist[i] == deleted_song:\n                                                del next_playlist[i]\n                                                break\n\n                                    # deleted song before current\n                                    if player.scroller.pos < player.i:\n                                        player.i -= 1\n                                    # deleted last song\n                                    if (\n                                        player.scroller.pos\n                                        == player.scroller.num_lines\n                                    ):\n                                        player.scroller.pos -= 1\n\n                                    player.scroller.refresh()\n                            elif c == 27:  # ESC key\n                                if player.show_help:\n                                    player.show_help = False\n                                    player.update_screen()\n                            elif ch is not None:\n                                if ch in \"nN\":\n                                    if (\n                                        not player.i == len(player.playlist) - 1\n                                        or loop\n                                    ):\n                                        next_song = 1\n                                        player.playback.stop()\n                                        break\n                                elif ch in \"bB\":\n                                    if player.i != 0:\n                                        next_song = -1\n                                        player.playback.stop()\n                                        break\n                                elif ch in \"rR\":\n                                    player.restarting = True\n                                    player.playback.stop()\n                                    next_song = 0\n                                    break\n                                elif ch in \"lL\":\n                                    player.looping_current_song = (\n                                        player.looping_current_song + 1\n                                    ) % len(config.LOOP_MODES)\n                                    player.update_screen()\n                                elif ch in \"cC\":\n                                    player.clip_mode = not player.clip_mode\n                                    if player.clip_mode:\n                                        clip_start, clip_end = player.clip\n                                        player.duration = clip_end - clip_start\n                                        if (\n                                            player.playback.curr_pos\n                                            < clip_start\n                                            or player.playback.curr_pos\n                                            > clip_end\n                                        ):\n                                            player.seek(clip_start)\n                                    else:\n                                        player.duration = (\n                                            player.playback.duration\n                                        )\n                                    player.update_screen()\n                                elif ch in \"pP\":\n                                    player.snap_back()\n                                    player.update_screen()\n                                elif ch in \"gG\":\n                                    if loop:\n                                        player.playback.stop()\n                                        next_song = 2\n                                        break\n                                elif ch in \"eE\":\n                                    player.ending = not player.ending\n                                    player.update_screen()\n                                elif ch in \"qQ\":\n                                    player.ending = True\n                                    break\n                                elif ch in \"dD\":\n                                    if player.want_discord:\n                                        player.want_discord = False\n                                        if player.discord_rpc is not None:\n                                            player.discord_rpc.close()\n                                        player.discord_connected = 0\n                                    else:\n\n                                        def f():\n                                            player.initialize_discord()\n                                            player.update_discord_metadata()\n                                            player.update_stream_metadata()\n\n                                        threading.Thread(\n                                            target=f,\n                                            daemon=True,\n                                        ).start()\n                                elif ch in \"iI\":\n                                    player.prompting = (\n                                        \"\",\n                                        0,\n                                        config.PROMPT_MODES[\"insert\"],\n                                    )\n                                    curses.curs_set(True)\n                                    screen_size = player.stdscr.getmaxyx()\n                                    player.scroller.resize(screen_size[0] - 3)\n                                    player.update_screen()\n                                elif ch in \"aA\":\n                                    player.prompting = (\n                                        \"\",\n                                        0,\n                                        config.PROMPT_MODES[\"append\"],\n                                    )\n                                    curses.curs_set(True)\n                                    screen_size = player.stdscr.getmaxyx()\n                                    player.scroller.resize(screen_size[0] - 3)\n                                    player.update_screen()\n                                elif ch == \",\":\n                                    player.prompting = (\n                                        \"\",\n                                        0,\n                                        config.PROMPT_MODES[\"tag\"],\n                                    )\n                                    curses.curs_set(True)\n                                    screen_size = player.stdscr.getmaxyx()\n                                    player.scroller.resize(screen_size[0] - 3)\n                                    player.update_screen()\n                                elif ch in \"mM\":\n                                    if player.volume == 0:\n                                        player.volume = prev_volume\n                                    else:\n                                        player.volume = 0\n\n                                    player.update_screen()\n                                elif ch in \"vV\":\n                                    player.want_vis = not player.want_vis\n                                    player.update_screen()\n                                elif ch in \"sS\":\n                                    player.want_stream = not player.want_stream\n                                    if player.want_stream:\n                                        if player.username is not None:\n                                            threading.Thread(\n                                                target=player.update_stream_metadata,\n                                                daemon=True,\n                                            ).start()\n                                            player.ffmpeg_process.start()\n                                    else:\n                                        player.ffmpeg_process.terminate()\n                                    player.update_discord_metadata()\n                                    player.update_screen()\n                                elif ch == \" \":\n                                    player.paused = not player.paused\n\n                                    if player.paused:\n                                        player.playback.pause()\n                                        pause_start = time()\n                                    else:\n                                        player.playback.resume()\n                                        start_time += time() - pause_start\n\n                                    if player.can_mac_now_playing:\n                                        player.mac_now_playing.paused = (\n                                            player.paused\n                                        )\n                                        if player.paused:\n                                            player.mac_now_playing.pause()\n                                        else:\n                                            player.mac_now_playing.resume()\n                                        player.update_now_playing = True\n\n                                    player.update_screen()\n                                elif ch in \"[-\":\n                                    player.volume = max(\n                                        0, player.volume - config.VOLUME_STEP\n                                    )\n                                    player.update_screen()\n                                    prev_volume = player.volume\n                                elif ch in \"]=\":\n                                    player.volume = min(\n                                        100, player.volume + config.VOLUME_STEP\n                                    )\n                                    player.update_screen()\n                                    prev_volume = player.volume\n                                elif ch in \"yY\":\n                                    player.want_lyrics = not player.want_lyrics\n                                elif ch in \"oO\":\n                                    helpers.SONG_DATA.load()\n                                    helpers.SONGS.load()\n                                    for song in player.playlist:\n                                        song.reset()\n\n                                    if (\n                                        player.song.set_clip\n                                        in player.song.clips\n                                    ):\n                                        player.clip = player.song.clips[\n                                            player.song.set_clip\n                                        ]\n                                    else:\n                                        player.clip = (\n                                            0,\n                                            player.playback.duration,\n                                        )\n                                    player.duration = (\n                                        player.clip[1] - player.clip[0]\n                                    )\n\n                                    player.lyrics = (\n                                        player.song.parsed_override_lyrics\n                                        or player.song.parsed_lyrics\n                                    )\n                                    if player.lyrics is not None:\n                                        player.lyrics_scroller = (\n                                            helpers.Scroller(\n                                                len(player.lyrics),\n                                                player.screen_height - 1,\n                                            )\n                                        )\n                                    player.translated_lyrics = (\n                                        player.song.parsed_translated_lyrics\n                                    )\n\n                                    from keyring.errors import NoKeyringError\n\n                                    try:\n                                        player.username = helpers.get_username()\n                                        player.password = helpers.get_password()\n                                    except NoKeyringError:\n                                        pass\n\n                                    player.update_screen()\n                                elif ch in \"hH\":\n                                    player.show_help = not player.show_help\n                                elif ch in \"tT\":\n                                    player.want_translated_lyrics = (\n                                        not player.want_translated_lyrics\n                                        and player.want_lyrics\n                                    )\n                                elif ch in \"fF\":\n                                    player.prompting = (\n                                        \"\",\n                                        0,\n                                        config.PROMPT_MODES[\"find\"],\n                                    )\n                                    curses.curs_set(True)\n                                    screen_size = player.stdscr.getmaxyx()\n                                    player.scroller.resize(screen_size[0] - 3)\n                                    player.update_screen()\n                                elif ch in \"{_\":\n                                    player.snap_back()\n                                    player.focus = 0\n                                elif ch in \"}+\":\n                                    player.snap_back()\n                                    player.focus = 1\n                        else:\n                            if c == curses.KEY_LEFT:\n                                # pylint: disable=unsubscriptable-object\n                                player.prompting = (\n                                    player.prompting[0],\n                                    max(player.prompting[1] - 1, 0),\n                                    player.prompting[2],\n                                )\n                                player.update_screen()\n                            elif c == curses.KEY_RIGHT:\n                                # pylint: disable=unsubscriptable-object\n                                player.prompting = (\n                                    player.prompting[0],\n                                    min(\n                                        player.prompting[1] + 1,\n                                        len(player.prompting[0]),\n                                    ),\n                                    player.prompting[2],\n                                )\n                                player.update_screen()\n                            elif c == curses.KEY_DC:\n                                # pylint: disable=unsubscriptable-object\n                                player.prompting_delete_char()\n                                player.update_screen()\n                            elif c == curses.KEY_ENTER:\n                                # pylint: disable=unsubscriptable-object\n                                # fmt: off\n                                if (\n                                    player.prompting[2] == config.PROMPT_MODES[\"tag\"]\n                                ):\n                                    tags = set(player.prompting[0].split(\",\"))\n\n                                    for song in player.playlist:\n                                        song.tags |= tags\n\n                                    player.prompting = None\n                                    curses.curs_set(False)\n                                    player.scroller.resize(screen_size[0] - 2)\n\n                                    player.update_screen()\n                                elif player.prompting[2] == config.PROMPT_MODES[\"find\"]:\n                                    try:\n                                        song = helpers.CLICK_SONG(player.prompting[0])\n                                        i = player.playlist.index(song)\n                                        if i != -1:\n                                            player.scroller.pos = i\n\n                                        player.prompting = None\n                                        curses.curs_set(False)\n                                        player.scroller.resize(screen_size[0] - 2)\n\n                                        player.update_screen()\n                                    except click.BadParameter:\n                                        pass\n                                else:\n                                    try:\n                                        song = helpers.CLICK_SONG(player.prompting[0])\n                                        if player.prompting[2] == config.PROMPT_MODES[\"insert\"]:\n                                            player.playlist.insert(\n                                                player.scroller.pos + 1,\n                                                song,\n                                            )\n                                            inserted_pos = player.scroller.pos + 1\n                                            if player.i > player.scroller.pos:\n                                                player.i += 1\n                                        else:\n                                            player.playlist.append(song)\n                                            inserted_pos = len(player.playlist) - 1\n\n                                        if loop:\n                                            if reshuffle >= 0:\n                                                next_playlist.insert(randint(max(0, inserted_pos-reshuffle), min(len(playlist)-1, inserted_pos+reshuffle)), song)\n                                            elif reshuffle == -1:\n                                                next_playlist.insert(randint(0, len(playlist) - 1), song)\n\n                                        player.scroller.num_lines += 1\n\n                                        player.prompting = None\n                                        curses.curs_set(False)\n                                        player.scroller.resize(screen_size[0] - 2)\n\n                                        player.update_screen()\n                                    except click.BadParameter:\n                                        pass\n                            elif c == 27:  # ESC key\n                                player.prompting = None\n                                curses.curs_set(False)\n                                player.scroller.resize(screen_size[0] - 2)\n                                player.update_screen()\n                            elif ch is not None:\n                                player.prompting = (\n                                    # pylint: disable=unsubscriptable-object\n                                    player.prompting[0][: player.prompting[1]]\n                                    + ch\n                                    + player.prompting[0][\n                                        player.prompting[1] :\n                                    ],\n                                    player.prompting[1] + 1,\n                                    player.prompting[2],\n                                )\n                                player.update_screen()\n\n            if (\n                player.can_mac_now_playing\n            ):  # sync macOS Now Playing pos with playback pos\n                if (\n                    abs(player.mac_now_playing.pos - player.playback.curr_pos)\n                    > 1\n                ):\n                    player.seek(player.mac_now_playing.pos)\n                    player.update_screen()\n                else:\n                    player.mac_now_playing.pos = round(player.playback.curr_pos)\n\n            progress_bar_width = player.stdscr.getmaxyx()[1] - 18\n            frame_duration = min(\n                (\n                    1\n                    if progress_bar_width < config.MIN_PROGRESS_BAR_WIDTH\n                    else player.duration / (progress_bar_width * 8)\n                ),\n                1 / config.FPS if player.want_vis else 1,\n            )\n            if (\n                abs(player.playback.curr_pos - player.last_timestamp)\n                > frame_duration\n            ):\n                player.last_timestamp = player.playback.curr_pos\n                player.update_screen()\n\n            sleep(0.01)  # NOTE: so CPU usage doesn't fly through the roof\n\n        if player.paused:\n            time_listened = pause_start - start_time\n        else:\n            time_listened = time() - start_time\n\n        # region update stats\n        def stats_update(s: helpers.Song, t: float):\n            s.listen_times[config.CUR_YEAR] += t\n            s.listen_times[\"total\"] += t\n\n        threading.Thread(\n            target=stats_update, args=(player.song, time_listened), daemon=True\n        ).start()\n        # endregion\n\n        if player.ending and not player.restarting:\n            player.quit()\n            if player.can_mac_now_playing:\n                app_helper_process.terminate()\n            return\n\n        if next_song == -1:\n            if player.i == player.scroller.pos:\n                player.scroller.scroll_backward()\n            player.i -= 1\n        elif next_song == 1:\n            if player.i == len(player.playlist) - 1:\n                if loop:\n                    next_next_playlist = next_playlist[:]\n                    if reshuffle:\n                        helpers.bounded_shuffle(next_next_playlist, reshuffle)\n                    player.playlist, next_playlist = (\n                        next_playlist,\n                        next_next_playlist,\n                    )\n                    player.i = -1\n                    player.scroller.pos = 0\n                else:\n                    return\n            else:\n                if player.i == player.scroller.pos:\n                    player.scroller.scroll_forward()\n            player.i += 1\n        elif next_song == 0:\n            if player.looping_current_song == config.LOOP_MODES[\"one\"]:\n                player.looping_current_song = config.LOOP_MODES[\"none\"]\n        elif next_song <= -2:  # user pos -> -(pos + 2)\n            player.i = -next_song - 2\n        elif next_song == 2:  # next page\n            next_next_playlist = next_playlist[:]\n            if reshuffle:\n                helpers.bounded_shuffle(next_next_playlist, reshuffle)\n            player.playlist, next_playlist = (\n                next_playlist,\n                next_next_playlist,\n            )\n            player.i = 0\n            player.scroller.pos = 0\n        elif next_song == 3:  # deleted current song\n            deleted_song = player.playlist[player.i]\n            del player.playlist[player.i]\n            if loop:\n                for i in range(len(next_playlist)):\n                    if next_playlist[i] == deleted_song:\n                        del next_playlist[i]\n                        break\n\n\n# endregion\n\n\n@click.group(context_settings={\"help_option_names\": [\"-h\", \"--help\"]})\n@click.pass_context\ndef cli(ctx: click.Context):\n    \"\"\"A command line interface for playing music.\"\"\"\n\n    # ~/.maestro-files\n    if not os.path.exists(config.MAESTRO_DIR):\n        os.makedirs(config.MAESTRO_DIR)\n\n    # ensure config.SETTINGS has all settings\n    update_settings_file = False\n    if not os.path.exists(config.SETTINGS_FILE):\n        config.settings = config.DEFAULT_SETTINGS\n        update_settings_file = True\n    else:\n        with open(config.SETTINGS_FILE, \"r\", encoding=\"utf-8\") as f:\n            s = f.read()\n            if s:\n                config.settings = msgspec.json.decode(s)\n                for key in config.DEFAULT_SETTINGS:\n                    if key not in config.settings:\n                        config.settings[key] = config.DEFAULT_SETTINGS[key]\n                        update_settings_file = True\n            else:\n                config.settings = config.DEFAULT_SETTINGS\n                update_settings_file = True\n\n    # ~/.maestro-files/songs.json\n    if not os.path.exists(config.SONGS_INFO_PATH):\n        if os.path.exists(config.OLD_SONGS_INFO_PATH):\n            if ctx.invoked_subcommand == \"migrate\":\n                return\n            ctx.fail(\n                \"Legacy song data detected. Please run 'maestro migrate' to convert the old songs file to the new format.\"\n            )\n\n        with open(config.SONGS_INFO_PATH, \"x\", encoding=\"utf-8\") as _:\n            pass\n\n    # ~/.maestro-files/songs/\n    if not os.path.exists(config.settings[\"song_directory\"]):\n        os.makedirs(config.settings[\"song_directory\"])\n\n    t = time()\n    if t - config.settings[\"last_version_sync\"] > 24 * 60 * 60:  # 1 day\n        config.settings[\"last_version_sync\"] = t\n        update_settings_file = True\n        try:\n            import requests\n\n            response = requests.get(\n                \"https://pypi.org/pypi/maestro-music/json\", timeout=5\n            )\n            latest_version = response.json()[\"info\"][\"version\"]\n            if helpers.versiontuple(latest_version) > helpers.versiontuple(\n                VERSION\n            ):\n                click.secho(\n                    f\"A new version of maestro is available. Run 'pip install --upgrade maestro-music' to update to version {latest_version}.\",\n                    fg=\"yellow\",\n                )\n        except Exception as e:\n            print_to_logfile(\"Failed to check for updates:\", e)\n\n    # ensure config.SETTINGS_FILE is up to date\n    if update_settings_file:\n        import safer\n\n        with safer.open(config.SETTINGS_FILE, \"wb\") as g:\n            g.write(msgspec.json.encode(config.settings))\n\n    # ensure config.LOGFILE is not too large (1 MB)\n    t = time()\n    if os.path.exists(config.LOGFILE) and os.path.getsize(config.LOGFILE) > 1e6:\n        # move to backup\n        backup_path = os.path.join(config.OLD_LOG_DIR, f\"maestro-{int(t)}.log\")\n        os.makedirs(os.path.dirname(backup_path), exist_ok=True)\n        move(config.LOGFILE, backup_path)\n\n    # delete old log files\n    if os.path.exists(config.OLD_LOG_DIR):\n        for file in os.listdir(config.OLD_LOG_DIR):\n            if file.endswith(\".log\"):\n                if t - int(file.split(\".\")[0].split(\"-\")[1]) > 24 * 60 * 60:\n                    os.remove(os.path.join(config.OLD_LOG_DIR, file))\n\n\n@cli.command()\n@click.argument(\"path_\", metavar=\"PATH_OR_URL\")\n@click.argument(\"tags\", nargs=-1)\n@click.option(\n    \"-M/-nM\",\n    \"--move/--no-move\",\n    \"move_\",\n    default=False,\n    help=\"Move file from PATH to maestro's internal song database instead of copying.\",\n)\n@click.option(\n    \"-n\",\n    \"--name\",\n    type=str,\n    help=\"What to name the song, if you don't want to use the title from Youtube/Spotify/filename. Do not include an extension (e.g. '.wav'). Ignored if adding multiple songs.\",\n)\n@click.option(\n    \"-R/-nR\",\n    \"--recursive/--no-recursive\",\n    \"recurse\",\n    default=False,\n    help=\"If PATH is a folder, add songs in subfolders.\",\n)\n@click.option(\n    \"-Y/-nY\",\n    \"--youtube/--no-youtube\",\n    default=False,\n    help=\"Add a song from a YouTube or YouTube Music URL.\",\n)\n@click.option(\n    \"-S/-nS\",\n    \"--spotify/--no-spotify\",\n    default=False,\n    help=\"Add a song from Spotify (track URL, album URL, playlist URL, artist URL, or search query).\",\n)\n@click.option(\n    \"-f\",\n    \"--format\",\n    \"format_\",\n    type=click.Choice((\"wav\", \"mp3\", \"flac\", \"vorbis\")),\n    help=\"Specify the format of the song if downloading from YouTube, YouTube Music, or Spotify URL.\",\n    default=\"mp3\",\n    show_default=True,\n)\n@click.option(\n    \"-P/-nP\",\n    \"--playlist/--no-playlist\",\n    \"playlist_\",\n    default=False,\n    help=\"If song URL passed is from a YouTube playlist, download all the songs. If the URL points directly to a playlist, this flag is unncessary.\",\n)\n@click.option(\n    \"-m\",\n    \"--metadata\",\n    \"metadata_pairs\",\n    default=None,\n    help=\"Add metadata to the song. If adding multiple songs, the metadata is added to each song. The format is 'key1:value1|key2:value2|...'.\",\n)\n@click.option(\n    \"-a\",\n    \"--artist\",\n    help=\"Specify the artist. If also specified in '-m/--metadata', this takes precedence.\",\n)\n@click.option(\n    \"-b\",\n    \"--album\",\n    help=\"Specify the album. If also specified in '-m/--metadata', this takes precedence.\",\n)\n@click.option(\n    \"-c\",\n    \"--album-artist\",\n    help=\"Specify the album artist. If also specified in '-m/--metadata', this takes precedence.\",\n)\n@click.option(\n    \"-nD/-D\",\n    \"--skip-dupes/--no-skip-dupes\",\n    default=False,\n    help=\"Skip adding song names that are already in the database. If not passed, 'copy' is appended to any duplicate names.\",\n)\n@click.option(\n    \"-L/-nL\",\n    \"--lyrics/--no-lyrics\",\n    default=True,\n    help=\"Search for and download lyrics for the song.\",\n)\n@click.option(\n    \"-q\",\n    \"--audio-quality\",\n    type=click.Choice(\n        (\n            \"auto\",\n            # \"disable\",\n            \"8k\",\n            \"16k\",\n            \"24k\",\n            \"32k\",\n            \"40k\",\n            \"48k\",\n            \"64k\",\n            \"80k\",\n            \"96k\",\n            \"112k\",\n            \"128k\",\n            \"160k\",\n            \"192k\",\n            \"224k\",\n            \"256k\",\n            \"320k\",\n            \"0\",\n            \"1\",\n            \"2\",\n            \"3\",\n            \"4\",\n            \"5\",\n            \"6\",\n            \"7\",\n            \"8\",\n            \"9\",\n        ),\n        case_sensitive=False,\n    ),\n    default=\"auto\",\n    help=\"Specify the audio quality to download. 0 is the best quality, 9 is the worst. 'auto' is the default (5). You can also specify a bitrate (e.g. '128k').\",\n)\n@click.option(\n    \"--crop/--no-crop\",\n    default=True,\n    help=\"Crop the album art to a square if no square art is found (YouTube/YT Music only).\",\n)\n@click.option(\n    \"--cookies-browser\",\n    help=\"Browser to extract cookies from for downloading from YouTube/YouTube Music. \",\n)\ndef add(\n    path_,\n    tags,\n    move_,\n    name,\n    recurse,\n    youtube,\n    spotify,\n    format_,\n    playlist_,\n    metadata_pairs,\n    artist,\n    album,\n    album_artist,\n    skip_dupes,\n    lyrics,\n    audio_quality,\n    crop,\n    cookies_browser,\n):\n    \"\"\"\n    Add a new song.\n\n    Adds the audio file located at PATH. If PATH is a folder, adds all files\n    in PATH (including files in subfolders if '-R/--recursive' is passed). If\n    '-M/--move' is passed, the file is moved from PATH to maestro's internal\n    song database instead of copied.\n\n    If the '-Y/--youtube' flag is passed, PATH is treated as a YouTube or\n    YouTube Music URL instead of a file path.\n\n    If the '-S/--spotify' flag is passed, PATH is treated as a Spotify\n    track URL, album URL, playlist URL, artist URL, or search query instead of\n    a file path.\n\n    The default format for downloading from YouTube, YouTube Music, or Spotify\n    is 'mp3'. The '-f/--format' option can be used to specify the format: 'wav',\n    'mp3', 'flac', or 'vorbis' (.ogg container).\n\n    If adding only one song, the '-n/--name' option can be used to specify the\n    name of the song. Do not include an extension (e.g. '.wav').\n\n    The '-m/--metadata' option can be used to add metadata to the song. It takes\n    a string of the format 'key1:value1|key2:value2|...'. If adding multiple\n    songs, the metadata is added to each song.\n\n    Possible editable metadata keys are: album, albumartist, artist, artwork,\n    comment, compilation, composer, discnumber, genre, lyrics, totaldiscs,\n    totaltracks, tracknumber, tracktitle, year, isrc\n\n    If the '-nD/--skip-dupes' flag is passed, song names that are already in\n    the database are skipped. If not passed, 'copy' is appended to any duplicate\n    names.\n    \"\"\"\n\n    paths = None\n    if not (youtube or spotify or os.path.exists(path_)):\n        click.secho(\n            f\"The path '{path_}' does not exist. To download from a YouTube or YouTube Music URl, pass the '-Y/--youtube' flag. To download from a Spotify URl, pass the '-S/--spotify' flag.\",\n            fg=\"red\",\n        )\n        return\n\n    if youtube or spotify:\n        if youtube and spotify:\n            click.secho(\n                \"Cannot pass both '-Y/--youtube' and '-S/--spotify' flags.\",\n                fg=\"red\",\n            )\n            return\n\n        if youtube:\n            from spotdl.utils.ffmpeg import get_ffmpeg_path\n            from yt_dlp import YoutubeDL\n\n            if get_ffmpeg_path() is None:\n                click.secho(\n                    \"FFmpeg is not installed: you can install it globally or run 'maestro download-ffmpeg' to download it internally.\",\n                    fg=\"red\",\n                )\n                return\n\n            ytdl_settings = {\n                \"noplaylist\": not playlist_,\n                \"postprocessors\": [\n                    {\n                        \"key\": \"FFmpegMetadata\",\n                        \"add_metadata\": True,\n                    },\n                    {\n                        \"key\": \"FFmpegExtractAudio\",\n                        \"preferredcodec\": format_,\n                        \"preferredquality\": (\n                            audio_quality\n                            if not audio_quality.lower().endswith(\"k\")\n                            else audio_quality[:-1]\n                        ),\n                    },\n                ],\n                \"outtmpl\": {\n                    \"default\": os.path.join(\n                        config.MAESTRO_DIR, \"%(title)s.%(ext)s\"\n                    )\n                },\n                \"ffmpeg_location\": str(get_ffmpeg_path()),\n            }\n            if cookies_browser:\n                ytdl_settings[\"cookiefile\"] = os.path.join(config.MAESTRO_DIR, \"cookies.txt\")\n                ytdl_settings[\"cookiesfrombrowser\"] = (cookies_browser,)\n            with YoutubeDL(ytdl_settings) as ydl:\n                info = ydl.extract_info(path_, download=True)\n                if \"entries\" in info:\n                    for e in info[\"entries\"]:\n                        helpers.yt_embed_artwork(e, crop)\n                else:\n                    helpers.yt_embed_artwork(info, crop)\n        else:\n            from spotdl import (\n                console_entry_point as original_spotdl_entry_point,\n            )\n            from spotdl.utils.ffmpeg import FFmpegError\n\n            if format_ == \"vorbis\":  # for spotdl only\n                format_ = \"ogg\"\n\n            cwd = os.getcwd()\n            os.chdir(config.MAESTRO_DIR)\n\n            def spotdl_entry_point(args):\n                original_argv = sys.argv\n                sys.argv = args\n                try:\n                    original_spotdl_entry_point()\n                except Exception as e:\n                    os.chdir(cwd)\n                    raise e\n                finally:\n                    sys.argv = original_argv\n\n            try:\n                spotdl_entry_point(\n                    [\n                        \"download\",\n                        path_,\n                        \"--output\",\n                        \"{title}.{output-ext}\",\n                        \"--format\",\n                        format_,\n                        \"--headless\",\n                        \"--bitrate\",\n                        audio_quality,\n                    ],\n                )\n            except FFmpegError:\n                click.secho(\n                    \"FFmpeg is not installed: you can install it globally or run 'maestro download-ffmpeg' to download it internally.\",\n                    fg=\"red\",\n                )\n                return\n\n        paths = []\n        for fname in os.listdir(config.MAESTRO_DIR):\n            for f in config.EXTS:\n                if fname.endswith(f):\n                    raw_path = os.path.join(config.MAESTRO_DIR, fname)\n                    sanitized_path = raw_path.replace(\"|\", \"-\")\n\n                    os.rename(raw_path, sanitized_path)\n\n                    paths.append(sanitized_path)\n            if fname.endswith(\".part\"):  # delete incomplete downloads\n                os.remove(os.path.join(config.MAESTRO_DIR, fname))\n\n        move_ = True\n\n    if paths is None:  # not downloading from YouTube or Spotify\n        if os.path.isdir(path_):  # get all songs to be added\n            paths = []\n            if recurse:\n                for dirpath, _, fnames in os.walk(path_):\n                    for fname in fnames:\n                        if os.path.splitext(fname)[1].lower() in config.EXTS:\n                            paths.append(os.path.join(dirpath, fname))\n            else:\n                for fname in os.listdir(path_):\n                    if os.path.splitext(fname)[1].lower() in config.EXTS:\n                        full_path = os.path.join(path_, fname)\n                        if os.path.isfile(full_path):\n                            paths.append(full_path)\n            if len(paths) == 0:\n                click.secho(\n                    f\"No songs found in '{path_}'.\",\n                    fg=\"red\",\n                )\n                return\n        else:\n            paths = [path_]\n\n    if not paths:\n        click.secho(\"No songs to add.\", fg=\"red\")\n        return\n\n    if name is not None:  # renaming\n        if len(paths) > 1:\n            click.secho(\n                \"Cannot pass '-n/--name' option when adding multiple songs.\",\n                fg=\"yellow\",\n            )\n\n        ext = os.path.splitext(paths[0])[1].lower()\n        if not os.path.isdir(paths[0]) and ext not in config.EXTS:\n            click.secho(f\"'{ext}' is not supported.\", fg=\"red\")\n            return\n\n        new_path = os.path.join(config.MAESTRO_DIR, name + ext)\n        # move/copy to config.MAESTRO_DIR (avoid name conflicts)\n        if move_:\n            move(paths[0], new_path)\n        else:\n            copy(paths[0], new_path)\n        paths = [new_path]\n        move_ = True  # always move (from temp loc in config.MAESTRO_DIR) if renaming\n\n    if metadata_pairs is not None:\n        # convert from \"key:value|key:value\" to [(\"key\", \"value\")]\n        metadata_pairs = [\n            tuple(pair.strip().split(\":\")) for pair in metadata_pairs.split(\"|\")\n        ]\n        keys_to_ignore = set()\n        for key, value in metadata_pairs:\n            if key not in config.METADATA_KEYS or key.startswith(\"#\"):\n                click.secho(\n                    f\"'{key}' is not a valid editable metadata key.\", fg=\"red\"\n                )\n                keys_to_ignore.add(key)\n            elif key == \"artist\" and artist is not None:\n                keys_to_ignore.add(key)\n            elif key == \"album\" and album is not None:\n                keys_to_ignore.add(key)\n            elif key == \"albumartist\" and album_artist is not None:\n                keys_to_ignore.add(key)\n        metadata_pairs = list(\n            filter(lambda t: t[0] not in keys_to_ignore, metadata_pairs)\n        )\n\n    abc_opts = list(\n        filter(\n            lambda t: t[1] is not None,\n            [\n                (\"artist\", artist),\n                (\"album\", album),\n                (\"albumartist\", album_artist),\n            ],\n        )\n    )\n    if abc_opts:\n        metadata_pairs = metadata_pairs or []\n        metadata_pairs.extend(abc_opts)\n\n    for path in paths:\n        ext = os.path.splitext(path)[1].lower()\n        if not os.path.isdir(path) and ext not in config.EXTS:\n            click.secho(f\"'{ext}' is not supported.\", fg=\"red\")\n            continue\n\n        song_fname = os.path.split(path)[1]\n        song_title = os.path.splitext(song_fname)[0]\n        dest_path = os.path.join(config.settings[\"song_directory\"], song_fname)\n\n        for song in helpers.SONGS:\n            if song.song_title == song_title:\n                if skip_dupes:\n                    click.secho(\n                        f\"Song with name '{song_title}' already exists, skipping.\",\n                        fg=\"yellow\",\n                    )\n                    os.remove(path)\n                else:\n                    click.secho(\n                        f\"Song with name '{song_title}' already exists, 'copy' will be appended to the song name.\",\n                        fg=\"yellow\",\n                    )\n                    song_fname = song_title + \" copy\" + ext\n\n                    dest_path = os.path.join(\n                        config.settings[\"song_directory\"], song_fname\n                    )\n                break\n\n        if move_:\n            move(path, dest_path)\n        else:\n            copy(path, dest_path)\n\n        song = helpers.SONG_DATA.add_song(dest_path, tags)\n\n        if metadata_pairs is not None:\n            for path in paths:\n                for key, value in metadata_pairs:\n                    song.set_metadata(key, value)\n\n        if lyrics:\n            import syncedlyrics\n\n            try:\n                # pylint: disable=unexpected-keyword-arg\n                lyrics = syncedlyrics.search(\n                    f\"{song.artist} - {song_title}\", allow_plain_format=True\n                )\n            except TypeError as e:\n                print_to_logfile(\n                    f\"TypeError with allow_plain_format=True in syncedlyrics.search: {e}\"\n                )\n                try:\n                    lyrics = syncedlyrics.search(song_title)\n                except Exception as e:  # pylint: disable=redefined-outer-name\n                    click.secho(\n                        f'Failed to download lyrics for \"{song_title}\": {e}',\n                        fg=\"red\",\n                    )\n            except Exception as e:\n                click.secho(\n                    f'Failed to download lyrics for \"{song_title}\": {e}',\n                    fg=\"red\",\n                )\n            else:\n                if lyrics:\n                    click.secho(\n                        f'Downloaded lyrics for \"{song_title}\".', fg=\"green\"\n                    )\n                    song.raw_lyrics = lyrics\n                else:\n                    click.secho(\n                        f'No lyrics found for \"{song_title}\".', fg=\"yellow\"\n                    )\n\n        if not tags:\n            tags_string = \"\"\n        elif len(tags) == 1:\n            tags_string = f\" and tag '{tags[0]}'\"\n        else:\n            tags_string = f\" and tags {', '.join([repr(tag) for tag in tags])}\"\n\n        click.secho(\n            f\"Added song '{song.song_file}' with ID {song.song_id}\"\n            + tags_string\n            + f\" and metadata (artist: {song.artist}, album: {song.album}, albumartist: {song.album_artist}).\",\n            fg=\"green\",\n        )\n\n\n@cli.command()\n@click.argument(\"args\", required=True, nargs=-1)\n@click.option(\n    \"-F/-nF\",\n    \"--force/--no-force\",\n    default=False,\n    help=\"Skip confirmation prompt(s).\",\n)\n@click.option(\n    \"-T/-nT\",\n    \"--tag/--no-tag\",\n    default=False,\n    help=\"If passed, treat all arguments as tags, deleting every ocurrence of each tag.\",\n)\ndef remove(args, force, tag):\n    \"\"\"Remove tag(s) or song(s).\"\"\"\n    if not tag:\n        songs: set[helpers.Song] = {helpers.CLICK_SONG(v) for v in args}\n\n        if not force:\n            char = input(\n                f\"Are you sure you want to delete {helpers.pluralize(len(songs), 'song')}? [y/n] \"\n            )\n\n            if char.lower() != \"y\":\n                print(\"Did not delete.\")\n                return\n\n        for song in songs:\n            if os.path.exists(song.song_path):\n                os.remove(song.song_path)\n            elif not force:\n                click.secho(\n                    f\"Warning: Song file '{song.song_path}' (ID {song.song_id}) not found. Would you still like to delete the song from the database? [y/n] \",\n                    fg=\"yellow\",\n                    nl=False,\n                )\n                if input().lower() != \"y\":\n                    click.echo(\n                        f'Skipping song \"{song.song_title}\" (ID {song.song_id}).'\n                    )\n                    continue\n            click.secho(\n                f'Removed song \"{song.song_title}\" (ID {song.song_id}).',\n                fg=\"green\",\n            )\n            song.remove_from_data()\n    else:\n        tags_to_remove = set(args)\n        if not force:\n            char = input(\n                f\"Are you sure you want to delete {helpers.pluralize(len(tags_to_remove), 'tag')}? [y/n] \"\n            )\n\n            if char.lower() != \"y\":\n                print(\"Did not delete.\")\n                return\n\n        for song in helpers.SONGS:\n            song.tags -= tags_to_remove\n\n        click.secho(\n            f\"Deleted all occurrences of {helpers.pluralize(len(tags_to_remove), 'tag')}.\",\n            fg=\"green\",\n        )\n\n\n@cli.command(name=\"tag\")\n@click.argument(\"songs\", type=helpers.CLICK_SONG, required=True, nargs=-1)\n@click.option(\n    \"-t\",\n    \"--tag\",\n    \"tags\",\n    help=\"Tags to add.\",\n    multiple=True,\n)\ndef tag_(songs, tags):\n    \"\"\"Add tags to songs.\"\"\"\n    if tags:\n        tags = set(tags)\n        for song in songs:\n            song.tags |= tags\n        click.secho(\n            f\"Added {helpers.pluralize(len(tags), 'tag')} to {helpers.pluralize(len(songs), 'song')}.\",\n            fg=\"green\",\n        )\n    else:\n        click.secho(\"No tags passed.\", fg=\"red\")\n\n\n@cli.command()\n@click.argument(\"songs\", type=helpers.CLICK_SONG, required=True, nargs=-1)\n@click.option(\n    \"-t\",\n    \"--tag\",\n    \"tags\",\n    help=\"Tags to remove.\",\n    multiple=True,\n)\n@click.option(\"-A/-nA\", \"--all/--no-all\", \"all_\", default=False)\n@click.option(\"-F/-nF\", \"--force/--no-force\", default=False)\ndef untag(songs, tags, all_, force):\n    \"\"\"Remove tags from songs. Tags that a song doesn't have will be ignored.\n\n    Passing the '-A/--all' flag will remove all tags from each song, unless TAGS\n    is passed (in which case the flag is ignored). Prompts for confirmation\n    unless the '-F/--force' flag is passed.\"\"\"\n    if tags:\n        tags = set(tags)\n        for song in songs:\n            song.tags -= tags\n        click.secho(\n            f\"Removed any occurrences of {helpers.pluralize(len(tags), 'tag')} from {helpers.pluralize(len(songs), 'song')}.\",\n            fg=\"green\",\n        )\n    else:\n        if not all_:\n            click.secho(\n                \"No tags passed—to remove all tags, pass the '-A/--all' flag.\",\n                fg=\"red\",\n            )\n        else:\n            if (\n                force\n                or input(\n                    f\"Are you sure you want to remove all tags from all {helpers.pluralize(len(songs), 'song')}? [y/n] \"\n                ).lower()\n                == \"y\"\n            ):\n                for song in songs:\n                    song.tags.clear()\n\n                click.secho(\n                    f\"Removed all tags from all {helpers.pluralize(len(songs), 'song')}.\",\n                    fg=\"green\",\n                )\n\n\n@cli.command()\n@click.argument(\"tags\", nargs=-1)\n@click.option(\n    \"-e\",\n    \"--exclude-tags\",\n    \"exclude_tags\",\n    help=\"Exclude songs with these tags.\",\n    multiple=True,\n)\n@click.option(\n    \"-a\",\n    \"--artist\",\n    \"artists\",\n    help=\"Filter by artist.\",\n    multiple=True,\n)\n@click.option(\n    \"-b\",\n    \"--album\",\n    \"albums\",\n    help=\"Filter by album.\",\n    multiple=True,\n)\n@click.option(\n    \"-c\",\n    \"--album-artist\",\n    \"album_artists\",\n    help=\"Filter by album artist.\",\n    multiple=True,\n)\n@click.option(\n    \"-s\",\n    \"--shuffle\",\n    \"shuffle_\",\n    type=click.IntRange(-1, None),\n    default=0,\n    help=\"How to shuffle the queue on the first run. -1: random shuffle, 0: no shuffle, any other integer N: random shuffle with the constraint that each song is no farther than N spots away from its starting position.\",\n)\n@click.option(\n    \"-r\",\n    \"--reshuffle\",\n    \"reshuffle\",\n    type=click.IntRange(-1, None),\n    default=0,\n    help=\"How to shuffle the queue on every run after the first. -1: random reshuffle, 0: no reshuffle, any other integer N: random reshuffle with the constraint that each song is no farther than N spots away from its previous position.\",\n)\n@click.option(\n    \"-R/-nR\",\n    \"--reverse/--no-reverse\",\n    \"reverse\",\n    default=False,\n    help=\"Play songs in reverse (most recently added first).\",\n)\n@click.option(\n    \"-o\",\n    \"--only\",\n    \"only\",\n    type=helpers.CLICK_SONG,\n    multiple=True,\n    help=\"Play only this/these song(s) (can be passed multiple times, e.g. 'maestro play -o 1 -o 17'). TAGS arguments are ignored\",\n)\n@click.option(\n    \"-v\",\n    \"--volume\",\n    \"volume\",\n    type=click.IntRange(0, 100),\n    default=100,\n    show_default=True,\n)\n@click.option(\n    \"-L/-nL\",\n    \"--loop/--no-loop\",\n    \"loop\",\n    default=False,\n    help=\"Loop the queue.\",\n)\n@click.option(\n    \"-C/-nC\",\n    \"--clips/--no-clips\",\n    \"clips\",\n    default=False,\n    help=\"Start in clip mode. Can be toggled with 'c'.\",\n)\n@click.option(\n    \"-D/-nD\",\n    \"--discord/--no-discord\",\n    \"discord\",\n    default=False,\n    help=\"Discord rich presence. Ignored if required dependencies are not installed. Will fail silently and retry every time the song changes if Discord connection fails (e.g. Discord not open).\",\n)\n@click.option(\n    \"-M/-nM\",\n    \"--match-all/--no-match-all\",\n    \"match_all\",\n    default=False,\n    help=\"Play songs that match all tags, not any.\",\n)\n@click.option(\n    \"-V/-nV\",\n    \"--visualize/--no-visualize\",\n    \"visualize\",\n    default=False,\n    help=\"Visualize the song being played. Ignored if required dependencies are not installed.\",\n)\n@click.option(\n    \"-S/-nS\",\n    \"--stream/--no-stream\",\n    \"stream\",\n    default=False,\n    help=\"Stream to maestro-music.vercel.app/listen-along/[USERNAME].\",\n)\n@click.option(\n    \"-Y/-nY\",\n    \"--lyrics/--no-lyrics\",\n    \"lyrics\",\n    default=False,\n    help=\"Show lyrics.\",\n)\n@click.option(\n    \"-T/-nT\",\n    \"--translated-lyrics/--no-translated-lyrics\",\n    \"translated_lyrics\",\n    default=False,\n    help=\"Show translated lyrics (ignored if '-Y/--lyrics' is not passed).\",\n)\n@click.option(\n    \"-X/-nX\",\n    \"--combine-artists/--no-combine-artists\",\n    \"combine_artists\",\n    default=True,\n    is_flag=True,\n    help=\"Count artists as album artists and vice versa.\",\n)\ndef play(\n    tags,\n    exclude_tags,\n    artists,\n    albums,\n    album_artists,\n    shuffle_,\n    reshuffle,\n    reverse,\n    only,\n    volume,\n    loop,\n    clips,\n    discord,\n    match_all,\n    visualize,\n    stream,\n    lyrics,\n    translated_lyrics,\n    combine_artists,\n):\n    \"\"\"Play your songs. If tags are passed, any song matching any tag will be in\n    your queue, unless the '-M/--match-all' flag is passed, in which case\n    every tag must be matched.\n\n    \\b\n    \\x1b[1mSPACE\\x1b[0m\\tpause/play\n    \\x1b[1mb\\x1b[0m\\t\\tgo [b]ack to previous song\n    \\x1b[1mr\\x1b[0m\\t\\t[r]eplay song\n    \\x1b[1mn\\x1b[0m\\t\\tskip to [n]ext song\n    \\x1b[1ml\\x1b[0m\\t\\t[l]oop the current song once ('l' in status bar). press again to loop infinitely ('L' in status bar). press once again to turn off looping\n    \\x1b[1mc\\x1b[0m\\t\\ttoggle [c]lip mode\n    \\x1b[1mv\\x1b[0m\\t\\ttoggle [v]isualization\n    \\x1b[1mLEFT\\x1b[0m\\trewind 5s\n    \\x1b[1mRIGHT\\x1b[0m\\tfast forward 5s\n    \\x1b[1m[/-\\x1b[0m\\t\\tdecrease volume\n    \\x1b[1m]/=\\x1b[0m\\t\\tincrease volume (] has issues on Windows)\n    \\x1b[1mm\\x1b[0m\\t\\t[m]ute/unmute\n    \\x1b[1me\\x1b[0m\\t\\t[e]nd the song player after the current song finishes (indicator in status bar, 'e' to cancel)\n    \\x1b[1mq\\x1b[0m\\t\\t[q]uit the song player immediately\n    \\x1b[1mUP/DOWN\\x1b[0m\\tto scroll through the queue/lyrics (mouse scrolling should also work)\n    \\x1b[1mSHIFT+UP/DOWN\\x1b[0m\\tmove the selected song up/down in the queue\n    \\x1b[1mENTER\\x1b[0m\\tplay the selected song/seek to selected lyric\n    \\x1b[1mp\\x1b[0m\\t\\tsna[p] back to the currently [p]laying song/lyric\n    \\x1b[1mg\\x1b[0m\\t\\tgo to the next pa[g]e/loop of the queue (ignored if not repeating queue)\n    \\x1b[1mBACKSPACE/DELETE\\x1b[0m\\tdelete the selected (not necessarily currently playing!) song from the queue\n    \\x1b[1md\\x1b[0m\\t\\ttoggle [D]iscord rich presence\n    \\x1b[1ma\\x1b[0m\\t\\t[a]dd a song to the end of the queue (opens a prompt to enter the song name or ID: ENTER to confirm, ESC to cancel)\n    \\x1b[1mi\\x1b[0m\\t\\t[i]nsert a song in the queue after the selected song (opens a prompt like 'a')\n    \\x1b[1m,\\x1b[0m\\t\\tadd ([comma]-separated) tag(s) to all songs in the queue. (opens a prompt like 'a')\n    \\x1b[1ms\\x1b[0m\\t\\ttoggle [s]tream (streams to maestro-music.vercel.app/listen-along/[USERNAME]), requires login\n    \\x1b[1my\\x1b[0m\\t\\ttoggle l[y]rics\n    \\x1b[1mt\\x1b[0m\\t\\ttoggle [t]ranslated lyrics (if available, ignored if lyrics mode is off)\n    \\x1b[1m{/_\\x1b[0m\\t\\tfocus playlist\n    \\x1b[1m}/+\\x1b[0m\\t\\tfocus lyrics (} has issues on Windows)\n    \\x1b[1mSHIFT+LEFT/RIGHT[0m\\tincrease/decrease width of lyrics window\n    \\x1b[1mo\\x1b[0m\\t\\trel[o]ad song data (useful if you've changed e.g lyrics, tags, or metadata while playing)\n    \\x1b[1m?\\x1b[0m\\t\\ttoggle this help message\n    \\x1b[1mf\\x1b[0m\\t\\t[f]ind a song in the queue (opens a prompt like 'a')\n\n    \\b\n    song color indicates mode:\n        \\x1b[1;34mblue\\x1b[0m\\t\\tnormal\n        \\x1b[1;33myellow\\x1b[0m\\tlooping current song (once or repeatedly)\n\n    \\b\n    progress bar color indicates status:\n        \\x1b[1;33myellow\\x1b[0m\\tnormal (or current song doesn't have a clip)\n        \\x1b[1;35mmagenta\\x1b[0m\\tplaying clip\n\n    For the color vision deficient, both modes also have indicators in the status bar.\n    \"\"\"\n    playlist = []\n    exclude_tags = set(exclude_tags)\n\n    if only:\n        playlist = list(only)\n    else:\n        playlist.extend(\n            helpers.filter_songs(\n                set(tags),\n                exclude_tags,\n                artists,\n                albums,\n                album_artists,\n                match_all,\n                combine_artists,\n            )\n        )\n\n    # song files not found\n    songs_not_found: list[helpers.Song] = []\n    for i in range(len(playlist)):\n        if not os.path.exists(playlist[i].song_path):\n            songs_not_found.append(playlist[i])\n            playlist[i] = None\n\n    playlist: list[helpers.Song] = sorted(\n        list(filter(lambda song: song is not None, playlist)),\n        key=lambda song: song.song_id,\n    )\n\n    helpers.bounded_shuffle(playlist, shuffle_)\n    if reverse:\n        playlist.reverse()\n\n    if not playlist:\n        click.secho(\"No songs found matching criteria.\", fg=\"red\")\n    else:\n        from keyring.errors import NoKeyringError\n\n        try:\n            username = helpers.get_username()\n            password = helpers.get_password()\n            if stream:\n                if username is None or password is None:\n                    if username is None:\n                        click.secho(\"Username not found.\", fg=\"red\")\n                    if password is None:\n                        click.secho(\"Password not found.\", fg=\"red\")\n                    click.secho(\n                        \"Please log in using 'maestro login' to stream.\",\n                        fg=\"red\",\n                    )\n                    return\n            elif discord:\n                if username is None or password is None:\n                    if username is None:\n                        click.secho(\"Username not found.\", fg=\"yellow\")\n                    if password is None:\n                        click.secho(\"Password not found.\", fg=\"yellow\")\n                    click.secho(\n                        \"Log in using 'maestro login' to enable album art in the Discord rich presence.\",\n                        fg=\"yellow\",\n                    )\n                    username = None\n                    password = None\n        except NoKeyringError as e:\n            if stream:\n                click.secho(\n                    f\"No keyring available. Cannot stream without login.\\n{e}\",\n                    fg=\"red\",\n                )\n            if discord:\n                click.secho(\n                    f\"No keyring available. Cannot show album art in Discord rich presence without login.\\n{e}\",\n                    fg=\"yellow\",\n                )\n            username = None\n            password = None\n\n        curses.wrapper(\n            _play,\n            playlist,\n            volume,\n            loop,\n            clips,\n            reshuffle,\n            discord,\n            visualize,\n            stream,\n            username,\n            password,\n            lyrics,\n            translated_lyrics and lyrics,\n        )\n\n    if songs_not_found:\n        click.secho(\"Song files not found:\", fg=\"red\")\n        for song in songs_not_found:\n            click.secho(f\"\\t{song.song_path} (ID {song.song_id})\", fg=\"red\")\n\n\n@cli.command()\n@click.option(\n    \"-T/-nT\",\n    \"--tag/--no-tag\",\n    \"renaming_tag\",\n    default=False,\n    help=\"If passed, rename tag instead of song (treat the arguments as tags).\",\n)\n# NOTE: original is not forced to be a int so that tags can be renamed\n@click.argument(\"original\")\n@click.argument(\"new_name\")\ndef rename(original, new_name, renaming_tag):\n    \"\"\"\n    Rename a song or tag.\n\n    Renames the song with the ID ORIGINAL to NEW_NAME. The extension of the\n    song (e.g. '.wav', '.mp3') is preserved—do not include it in the name.\n\n    If the '-T/--tag' flag is passed, treats ORIGINAL as a tag, renaming all\n    ocurrences of it to NEW_NAME—doesn't check if the tag NEW_NAME already\n    exists, so be careful!\n    \"\"\"\n    if not renaming_tag:\n        original = helpers.CLICK_SONG(original)\n        original_song_title = original.song_title\n        original.song_title = new_name\n        click.secho(\n            f'Renamed song \"{original_song_title}\" (ID: {original.song_id}) to \"{new_name}\".',\n            fg=\"green\",\n        )\n    else:\n        for song in helpers.SONGS:\n            if original in song.tags:\n                song.tags.remove(original)\n                song.tags.add(new_name)\n\n        click.secho(\n            f\"Renamed all ocurrences of tag '{original}' to '{new_name}'.\",\n            fg=\"green\",\n        )\n\n\n@cli.command()\n@click.argument(\"phrase\")\n@click.option(\n    \"-T/-nT\",\n    \"--tag/--no-tag\",\n    \"searching_for_tags\",\n    default=False,\n    help=\"Searches for matching tags instead of song names.\",\n)\ndef search(phrase, searching_for_tags):\n    \"\"\"Search for song names (or tags with '-T/--tag' flag). All songs/tags\n    starting with PHRASE will appear before songs/tags containing but not\n    starting with PHRASE. This search is case-insensitive.\"\"\"\n    if not searching_for_tags:\n        results = helpers.search_song(phrase)\n        if not any(results):\n            click.secho(\"No results found.\", fg=\"red\")\n            return\n\n        for song in sum(results, []):\n            helpers.print_entry(song, highlight=phrase)\n\n        num_results = len(results[0]) + len(results[1]) + len(results[2])\n        click.secho(\n            f\"Found {helpers.pluralize(num_results, 'song')}.\",\n            fg=\"green\",\n        )\n    else:\n        phrase = phrase.lower()\n        results = (\n            set(),\n            set(),\n            set(),\n        )  # is, starts, contains but does not start\n        for song in helpers.SONGS:\n            for tag in song.tags:\n                tag_lower = tag.lower()\n                if tag_lower == phrase:\n                    results[0].add(tag)\n                elif tag_lower.startswith(phrase):\n                    results[1].add(tag)\n                elif phrase in tag_lower:\n                    results[2].add(tag)\n\n        if not any(results):\n            click.secho(\"No results found.\", fg=\"red\")\n            return\n\n        for tag in sum(map(list, results), []):\n            tag = tag.replace(phrase, click.style(phrase, fg=\"yellow\"), 1)\n            click.echo(tag)\n\n        num_results = len(results[0]) + len(results[1]) + len(results[2])\n        click.secho(\n            f\"Found {helpers.pluralize(num_results, 'tag')}.\", fg=\"green\"\n        )\n\n\n@cli.command(name=\"list\")\n@click.argument(\"search_tags\", metavar=\"TAGS\", nargs=-1)\n@click.option(\n    \"-e\",\n    \"--exclude-tags\",\n    \"exclude_tags\",\n    multiple=True,\n    help=\"Exclude songs/tags matching these tags.\",\n)\n@click.option(\n    \"-s\",\n    \"--sort\",\n    \"sort_\",\n    type=click.Choice(\n        (\n            \"none\",\n            \"name\",\n            \"n\",\n            \"secs-listened\",\n            \"s\",\n            \"duration\",\n            \"d\",\n            \"times-listened\",\n            \"t\",\n            \"artist\",\n            \"a\",\n            \"album\",\n            \"b\",\n            \"album-artist\",\n            \"c\",\n        )\n    ),\n    help=\"Sort by song name, seconds listened, duration or times listened (seconds listened divided by song duration). Increasing order, default is by ID for songs and no order for tags.\",\n    default=\"none\",\n    show_default=True,\n)\n@click.option(\n    \"-R/-nR\",\n    \"--reverse/--no-reverse\",\n    \"reverse_\",\n    default=False,\n    help=\"Reverse the sorting order (decreasing instead of increasing). For example, 'maestro list -s s -R -t 5' will show the top 5 most-listened songs by seconds listened.\",\n)\n@click.option(\n    \"-T/-nT\",\n    \"--list-tags/--no-list-tags\",\n    \"listing_tags\",\n    default=False,\n    help=\"List tags matching TAGS instead of songs.\",\n)\n@click.option(\n    \"-y\",\n    \"--year\",\n    \"year\",\n    help=\"Show time listened for a specific year, instead of the total. Passing 'cur' will show the time listened for the current year.\",\n)\n@click.option(\"-t\", \"--top\", \"top\", type=int, help=\"Show the top n songs/tags.\")\n@click.option(\n    \"-M/-nM\",\n    \"--match-all/--no-match-all\",\n    \"match_all\",\n    default=False,\n    help=\"Shows songs that match all criteria instead of any criteria. Ignored if '-t/--tag' is passed.\",\n)\n@click.option(\n    \"-a\",\n    \"--artist\",\n    \"artists\",\n    multiple=True,\n    help=\"Filter by artist(s) (fuzzy search); can pass multiple.\",\n)\n@click.option(\n    \"-b\",\n    \"--album\",\n    \"albums\",\n    multiple=True,\n    help=\"Filter by album (fuzzy search); can pass multiple.\",\n)\n@click.option(\n    \"-c\",\n    \"--album-artist\",\n    \"album_artists\",\n    multiple=True,\n    help=\"Filter by album artist (fuzzy search); can pass multiple.\",\n)\n@click.option(\n    \"-A/-nA\",\n    \"--list-artists/--no-list-artists\",\n    \"listing_artists\",\n    is_flag=True,\n    help=\"Show artists instead of songs.\",\n)\n@click.option(\n    \"-B/-nB\",\n    \"--list-albums/--no-list-albums\",\n    \"listing_albums\",\n    is_flag=True,\n    help=\"Show albums instead of songs.\",\n)\n@click.option(\n    \"-C/-nC\",\n    \"--list-album-artist/--no-list-album-artist\",\n    \"listing_album_artists\",\n    is_flag=True,\n    help=\"Show album artists instead of songs.\",\n)\n@click.option(\n    \"-X/-nX\",\n    \"--combine-artists/--no-combine-artists\",\n    \"combine_artists\",\n    is_flag=True,\n    default=True,\n    help=\"Count artists as album artists and vice versa. Ignored if neither '-A/--list-artists' nor '-C/--list-album-artists' is passed.\",\n)\ndef list_(\n    search_tags,\n    exclude_tags,\n    listing_tags,\n    year,\n    sort_,\n    top,\n    reverse_,\n    match_all,\n    artists,\n    albums,\n    album_artists,\n    listing_artists,\n    listing_albums,\n    listing_album_artists,\n    combine_artists,\n):\n    \"\"\"List songs or tags.\n    Output format: ID, name, duration, listen time, times listened, [clip-start, clip-end] if clip exists, comma-separated tags if any\n\n    If the '-T/--list-tags' flag is passed, tags will be listed instead of songs.\n\n    If any of the '-A/--list-artists', '-B/--list-albums', or\n    '-C/--list-album-artists' flags are passed, the respective fields will be\n    listed instead of songs.\n\n    Output format: tag/artist/album/album artist, duration, listen time, times listened\n    \"\"\"\n    if top is not None:\n        if top < 1:\n            click.secho(\n                \"The option '-t/--top' must be a positive number.\", fg=\"red\"\n            )\n            return\n\n    if (\n        sum(\n            [\n                listing_artists,\n                listing_albums,\n                listing_album_artists,\n                listing_tags,\n            ]\n        )\n        > 1\n    ):\n        click.secho(\n            \"Only one of '-A/--show-artist', '-B/--show-album', '-C/--show-album-artist', or '-T/--tag' can be passed.\",\n            fg=\"red\",\n        )\n        return\n\n    if year is None:\n        year = \"total\"\n    elif year == \"cur\":\n        year = config.CUR_YEAR\n    else:\n        if not year.isdigit():\n            click.secho(\"Year must be a number or 'cur'.\", fg=\"red\")\n            return\n        year = int(year)\n\n    search_tags = set(search_tags)\n    exclude_tags = set(exclude_tags)\n\n    num_lines = 0\n\n    if listing_tags:\n        search_tags -= exclude_tags\n\n        tags = defaultdict(lambda: [0, 0])\n        for song in helpers.SONGS:\n            search_criteria = (\n                (\n                    (\n                        any(\n                            artist.lower()\n                            in song.artist.lower()\n                            + (\n                                f\", {song.album_artist.lower()}\"\n                                if combine_artists\n                                else \"\"\n                            )\n                            for artist in artists\n                        )\n                    ),\n                    artists,\n                ),\n                (\n                    (\n                        any(\n                            album.lower() in song.album.lower()\n                            for album in albums\n                        )\n                    ),\n                    albums,\n                ),\n                (\n                    (\n                        any(\n                            album_artist.lower()\n                            in song.album_artist.lower()\n                            + (\n                                \", \" + song.artist.lower()\n                                if combine_artists\n                                else \"\"\n                            )\n                            for album_artist in album_artists\n                        )\n                    ),\n                    album_artists,\n                ),\n            )\n            search_criteria = tuple(\n                c[0] for c in filter(lambda t: t[1], search_criteria)\n            )\n\n            if match_all:\n                search_criteria = not search_criteria or all(search_criteria)\n            else:\n                search_criteria = not search_criteria or any(search_criteria)\n\n            for tag in song.tags:\n                if (not search_tags or tag in search_tags) and search_criteria:\n                    tags[tag][0] += song.listen_times.get(year, 0)\n                    tags[tag][1] += song.duration\n\n        tags = list(tags.items())\n\n        if sort_ != \"none\":\n            if sort_ in (\"name\", \"n\"):\n                sort_key = lambda t: t[0].lower()\n            elif sort_ in (\"secs-listened\", \"s\"):\n                sort_key = lambda t: t[1][0]\n            elif sort_ in (\"duration\", \"d\"):\n                sort_key = lambda t: t[1][1]\n            elif sort_ in (\"times-listened\", \"t\"):\n                sort_key = lambda t: t[1][0] / t[1][1]\n\n            tags.sort(key=sort_key)  # pylint: disable=used-before-assignment\n            if reverse_:\n                tags.reverse()\n\n        for tag, (listen_time, total_duration) in tags:\n            click.echo(\n                f\"{tag} {click.style(helpers.format_seconds(total_duration, show_decimal=True, digital=False), fg='bright_black')} {click.style(helpers.format_seconds(listen_time, show_decimal=True, digital=False), fg='yellow')} {click.style('%.2f'%(listen_time/total_duration), fg='green')}\"\n            )\n            num_lines += 1\n            if top is not None and num_lines == top:\n                break\n        return\n\n    if listing_artists or listing_albums or listing_album_artists:\n        abcs = defaultdict(lambda: [0, 0])\n        if combine_artists:\n            artists += album_artists\n            album_artists = artists\n        for song in helpers.filter_songs(\n            search_tags,\n            exclude_tags,\n            artists,\n            albums,\n            album_artists,\n            match_all,\n            combine_artists,\n        ):\n            if listing_artists or (combine_artists and listing_album_artists):\n                for artist in song.artist.split(\", \"):\n                    if artists:\n                        for search_artist in artists:\n                            if search_artist.lower() in artist.lower():\n                                abcs[artist][0] += song.listen_times.get(\n                                    year, 0\n                                )\n                                abcs[artist][1] += song.duration\n                                break\n                    else:\n                        abcs[artist][0] += song.listen_times.get(year, 0)\n                        abcs[artist][1] += song.duration\n            if listing_albums:\n                if albums:\n                    for album in albums:\n                        if album.lower() in song.album.lower():\n                            abcs[album][0] += song.listen_times.get(year, 0)\n                            abcs[album][1] += song.duration\n                else:\n                    abcs[song.album][0] += song.listen_times.get(year, 0)\n                    abcs[song.album][1] += song.duration\n            if listing_album_artists or (combine_artists and listing_artists):\n                for album_artist in song.album_artist.split(\", \"):\n                    if album_artists:\n                        for search_album_artist in album_artists:\n                            if (\n                                search_album_artist.lower()\n                                in album_artist.lower()\n                            ):\n                                abcs[album_artist][0] += song.listen_times.get(\n                                    year, 0\n                                )\n                                abcs[album_artist][1] += song.duration\n                                break\n                    else:\n                        abcs[album_artist][0] += song.listen_times.get(year, 0)\n                        abcs[album_artist][1] += song.duration\n\n        abcs = list(abcs.items())\n\n        if sort_ != \"none\":\n            if sort_ in (\"name\", \"n\"):\n                sort_key = lambda t: t[0].lower()\n            elif sort_ in (\"secs-listened\", \"s\"):\n                sort_key = lambda t: t[1][0]\n            elif sort_ in (\"duration\", \"d\"):\n                sort_key = lambda t: t[1][1]\n            elif sort_ in (\"times-listened\", \"t\"):\n                sort_key = lambda t: t[1][0] / t[1][1]\n            abcs.sort(key=sort_key)\n            if reverse_:\n                abcs.reverse()\n\n        for abc, (listen_time, total_duration) in abcs:\n            click.echo(\n                f\"{abc} {click.style(helpers.format_seconds(total_duration, show_decimal=True, digital=False), fg='bright_black')} {click.style(helpers.format_seconds(listen_time, show_decimal=True, digital=False), fg='yellow')} {click.style('%.2f'%(listen_time/total_duration), fg='green')}\"\n            )\n            num_lines += 1\n            if top is not None and num_lines == top:\n                break\n        return\n\n    songs = helpers.filter_songs(\n        search_tags,\n        exclude_tags,\n        artists,\n        albums,\n        album_artists,\n        match_all,\n        combine_artists,\n    )\n\n    if sort_ == \"none\":\n        sort_key = lambda song: song.song_id\n    if sort_ in (\"name\", \"n\"):\n        sort_key = lambda song: song.song_title.lower()\n    elif sort_ in (\"secs-listened\", \"s\"):\n        sort_key = lambda song: song.listen_times.get(year, 0)\n    elif sort_ in (\"duration\", \"d\"):\n        sort_key = lambda song: song.duration\n    elif sort_ in (\"times-listened\", \"t\"):\n        sort_key = lambda song: song.listen_times.get(year, 0) / song.duration\n    songs.sort(key=sort_key, reverse=reverse_)\n\n    no_results = True\n    for song in songs:\n        helpers.print_entry(song, year=year)\n        num_lines += 1\n        no_results = False\n        if top is not None and num_lines == top:\n            break\n\n    if no_results and not any([search_tags, artists, albums, album_artists]):\n        click.secho(\n            \"No songs found. Use 'maestro add' to add a song.\", fg=\"red\"\n        )\n    elif no_results:\n        click.secho(\"No songs found matching criteria.\", fg=\"red\")\n\n\n@cli.command()\n@click.option(\n    \"-y\",\n    \"--year\",\n    \"year\",\n    help=\"Show time listened for a specific year, instead of the total. Passing 'cur' will show the time listened for the current year.\",\n)\n@click.argument(\"songs\", type=helpers.CLICK_SONG, nargs=-1, required=True)\ndef entry(songs, year):\n    \"\"\"\n    View the details for specific song(s).\n\n    \\b\n    Output format:\n        ID, name, duration, listen time, times listened, [clip-start, clip-end] if clip exists, comma-separated tags if any\n            artist - album (album artist)\n    \"\"\"\n    if year is None:\n        year = \"total\"\n    elif year == \"cur\":\n        year = config.CUR_YEAR\n    else:\n        if not year.isdigit():\n            click.secho(\"Year must be a number.\", fg=\"red\")\n            return\n        year = int(year)\n\n    for song in songs:\n        helpers.print_entry(song, year=year)\n\n\n@cli.command()\n@click.argument(\"song\", required=True)\n@click.option(\n    \"-T/-nT\",\n    \"--title/--no-title\",\n    \"title\",\n    default=False,\n    help=\"Treat SONG as a song title to search on YT Music instead of an existing maestro song.\",\n)\ndef recommend(song, title):\n    \"\"\"\n    Get recommendations from YT Music based on song titles.\n\n    Recommends songs (possibly explicit) using the YouTube Music API that are\n    similar to SONG to listen to.\n\n    If the '-T/--title' flag is passed, maestro directly searches up SONG on\n    YouTube Music, rather than trying to find a matching entry in your maestro\n    songs.\"\"\"\n    try:\n        from ytmusicapi import YTMusic\n    except ImportError:\n        click.secho(\n            \"The 'recommend' command requires the 'ytmusicapi' package to be installed. Run 'pip install ytmusicapi' to install it.\",\n            fg=\"red\",\n        )\n        return\n\n    ytmusic = YTMusic()\n\n    if title:\n        results = ytmusic.search(song, filter=\"songs\")\n    else:\n        song = helpers.CLICK_SONG(song)\n        results = ytmusic.search(\n            os.path.splitext(song.song_title)[0], filter=\"songs\"\n        )\n\n    yt_music_playlist = ytmusic.get_watch_playlist(results[0][\"videoId\"])\n\n    click.echo(\"Recommendations for \", nl=False)\n    click.secho(\n        yt_music_playlist[\"tracks\"][0][\"title\"] + \" \",\n        fg=\"blue\",\n        nl=False,\n    )\n    click.secho(\n        f\"(https://music.youtube.com/watch?v={yt_music_playlist['tracks'][0]['videoId']})\",\n        fg=\"bright_black\",\n        nl=False,\n    )\n    click.echo(\":\")\n    for track in yt_music_playlist[\"tracks\"][1:]:\n        click.secho(track[\"title\"] + \" \", fg=\"blue\", bold=True, nl=False)\n        click.secho(\n            f\"https://music.youtube.com/watch?v={track['videoId']}\",\n            fg=\"bright_black\",\n        )\n\n\n@cli.command(name=\"clips\")\n@click.argument(\"songs\", required=True, type=helpers.CLICK_SONG, nargs=-1)\ndef clips_(songs: tuple[helpers.Song]):\n    \"\"\"\n    List the clips for song(s).\n\n    Output format: clip name: start time, end time\n\n    The set clip for the song is bolded and highlighted in magenta.\n    \"\"\"\n    for song in songs:\n        if not song.clips:\n            click.secho(\n                f'No clips for \"{song.song_title}\" (ID {song.song_id}).',\n            )\n            continue\n        click.echo(\"Clips for \", nl=False)\n        click.secho(song.song_title, fg=\"blue\", bold=True, nl=False)\n        click.echo(f\" (ID {song.song_id}):\")\n\n        def style_clip_name(clip_name, song):\n            if clip_name == song.set_clip:\n                return click.style(clip_name, bold=True, fg=\"magenta\")\n            else:\n                return click.style(clip_name)\n\n        if \"default\" in song.clips:\n            click.echo(\n                f\"\\t{style_clip_name('default', song)}: {song.clips['default'][0]}, {song.clips['default'][1]}\"\n            )\n        for clip_name, (start, end) in song.clips.items():\n            if clip_name == \"default\":\n                continue\n            click.echo(f\"\\t{style_clip_name(clip_name, song)}: {start}, {end}\")\n\n\n@cli.command(name=\"clip\")\n@click.argument(\"song\", required=True, type=helpers.CLICK_SONG)\n@click.argument(\"start\", required=False, type=float, default=None)\n@click.argument(\"end\", required=False, type=float, default=None)\n@click.option(\n    \"-n\",\n    \"--name\",\n    \"name\",\n    help=\"Name of the clip.\",\n    default=\"default\",\n)\n@click.option(\n    \"-E/-nE\",\n    \"--editor/--no-editor\",\n    \"editor\",\n    default=True,\n    help=\"Open the clip editor, even if START and END are passed. Ignored if neither START nor END are passed.\",\n)\ndef clip_(song: helpers.Song, name, start, end, editor):\n    \"\"\"\n    Create or edit a clip for a song.\n\n    Sets the clip (with name passed to '-n/--name' or 'default' if not passed)\n    for SONG to the time range START to END (in seconds).\n\n    If END is not passed, the clip will be from START to the end of the song.\n\n    If neither START nor END are passed, a clip editor will be opened, in which\n    you can move the start and end of the clip around using the arrow keys while\n    listening to the song.\n\n    If the '-E/--editor' flag is passed, the clip editor will be opened even if\n    START and END are passed; this is useful if you want to fine-tune the clip.\n\n    \\b\n    The editor starts out editing the start of the clip.\n    \\x1b[1mt\\x1b[0m to toggle between editing the start and end of the clip.\n    \\x1b[1mLEFT/RIGHT\\x1b[0m will move whichever clip end you are editing\n        by 0.1 seconds, snap the current playback to that clip end (to exactly\n        the clip start if editing start, end-1 if editing end), and pause.\n    \\x1b[1mSHIFT+LEFT/RIGHT\\x1b[0m will move whichever clip end you are editing\n        by 1 second, snap the current playback to that clip end, and pause.\n    \\x1b[1mSPACE\\x1b[0m will play/pause.\n    \\x1b[1mENTER\\x1b[0m will exit the editor and save the clip.\n    \\x1b[1mq\\x1b[0m will exit the editor without saving the clip.\n    \"\"\"\n    if start is not None:\n        if start < 0:\n            click.secho(\"START must be a positive number.\", fg=\"red\")\n            return\n        if end is not None and end < 0:\n            click.secho(\"END must be a positive number.\", fg=\"red\")\n            return\n\n    if start is None:  # clip editor\n        start, end = curses.wrapper(helpers.clip_editor, song, name)\n        if start is None:\n            click.secho(\n                f\"No change in clip '{name}' for \\\"{song.song_title}\\\" (ID {song.song_id}).\",\n                fg=\"green\",\n            )\n            return\n        editor = False\n\n        # hacky fix for end being past end of song sometimes\n        end = min(end, song.duration)\n\n    if end is None:\n        end = song.duration\n    if start > song.duration:\n        click.secho(\"START must not be more than the song duration.\", fg=\"red\")\n        return\n    if end > song.duration:\n        click.secho(\"END must not be more than the song duration.\", fg=\"red\")\n        return\n    if start > end:\n        click.secho(\"START must not be more than END.\", fg=\"red\")\n        return\n\n    if editor:\n        start, end = curses.wrapper(helpers.clip_editor, song, name, start, end)\n        if start is None:\n            click.secho(\n                f\"No change in clip '{name}' for \\\"{song.song_title}\\\" (ID {song.song_id}).\",\n                fg=\"green\",\n            )\n            return\n\n    if name in song.clips:\n        click.secho(\n            \"Modified \",\n            nl=False,\n            fg=\"green\",\n        )\n    else:\n        click.secho(\n            \"Created \",\n            nl=False,\n            fg=\"green\",\n        )\n    click.secho(\n        f'clip \"{name}\" for \"{song.song_title}\" (ID {song.song_id}): {start} to {end}.',\n        fg=\"green\",\n    )\n    song.clips[name] = (start, end)\n\n\n@cli.command()\n@click.argument(\"songs\", type=helpers.CLICK_SONG, nargs=-1, required=False)\n@click.option(\n    \"-n\",\n    \"--name\",\n    \"names\",\n    help=\"Name(s) of the clip(s) to remove.\",\n    multiple=True,\n)\n@click.option(\n    \"-A/-nA\",\n    \"--all/--no-all\",\n    \"all_\",\n    default=False,\n    help=\"Remove clips for all songs. Ignores SONG_IDS.\",\n)\n@click.option(\n    \"-F/-nF\",\n    \"--force/--no-force\",\n    \"force\",\n    default=False,\n    help=\"Skip confirmation prompt.\",\n)\ndef unclip(songs: tuple[helpers.Song], names, all_, force):\n    \"\"\"\n    Remove clips from song(s).\n\n    Removes any clips with names passed to '-n/--name' from each song in SONGS.\n    If no names are passed, removes the clip 'default' from each song.\n\n    If the '-A/--all' flag is passed, at most one of SONGS or '-n/--name' must\n    be passed. If name(s) are passed, all clips with those names will be\n    removed. If SONGS are passed, all clips for each song will be removed.\n    Prompts for confirmation unless '-F/--force' is passed.\n    \"\"\"\n    if all_:\n        if songs and names:\n            click.secho(\n                \"The '-A/--all' flag cannot be passed with both SONGS and '-n/--name'.\",\n                fg=\"red\",\n            )\n            return\n\n        if songs:\n            if not force:\n                click.echo(\n                    f'Are you sure you want to remove all clips from {helpers.pluralize(len(songs), \"song\")}? This cannot be undone. [y/n] ',\n                    nl=False,\n                )\n                if input().lower() != \"y\":\n                    return\n        elif names:\n            if not force:\n                click.echo(\n                    f\"Are you sure you want to remove all clips with names {', '.join(names)} for all songs? This cannot be undone. [y/n] \",\n                    nl=False,\n                )\n                if input().lower() != \"y\":\n                    return\n            songs = helpers.SONGS\n        else:\n            click.secho(\n                \"The '-A/--all' flag must be passed with either SONGS or '-n/--name'.\",\n                fg=\"red\",\n            )\n            return\n\n    if not (songs or names):\n        click.secho(\n            \"No songs or clip names passed—to remove all clips from all songs, pass the '-A/--all' flag.\",\n            fg=\"red\",\n        )\n        return\n\n    if not (names or all_):\n        names = (\"default\",)\n\n    for song in songs:\n        if not names:\n            song.clips.clear()\n        else:\n            for name in names:\n                if name in song.clips:\n                    del song.clips[name]\n\n    if not names:\n        click.secho(\n            f\"Removed all clips from {helpers.pluralize(len(songs), 'song')}.\",\n            fg=\"green\",\n        )\n    else:\n        click.secho(\n            f\"Removed {helpers.pluralize(len(names), 'clip', False)} {', '.join(map(repr, names))} from {helpers.pluralize(len(songs), 'song')}.\",\n            fg=\"green\",\n        )\n\n\n@cli.command(name=\"set-clip\")\n@click.argument(\"songs\", type=helpers.CLICK_SONG, nargs=-1, required=False)\n@click.argument(\"name\", required=True)\n@click.option(\n    \"-F/-nF\",\n    \"--force/--no-force\",\n    \"force\",\n    default=False,\n    help=\"Skip confirmation prompt.\",\n)\ndef set_clip(songs: tuple[helpers.Song], name, force):\n    \"\"\"\n    Set the clip for song(s).\n\n    Sets the clip for each song in SONGS to NAME; 'maestro play' will play this\n    clip in clip mode.\n\n    If no SONGS are passed, sets the clip for all songs. This prompts for\n    confirmation unless '-F/--force' is passed.\n    \"\"\"\n    if not songs:\n        songs = helpers.SONGS\n        if not force:\n            click.echo(\n                f\"Are you sure you want to set the clip for all {helpers.pluralize(len(songs), 'song')} to '{name}'? This cannot be undone. [y/n] \",\n                nl=False,\n            )\n            if input().lower() != \"y\":\n                return\n\n    for song in songs:\n        song.set_clip = name\n\n    click.secho(\n        f\"Set clip for {helpers.pluralize(len(songs), 'song')} to '{name}'.\",\n        fg=\"green\",\n    )\n\n\n@cli.command()\n@click.argument(\"songs\", type=helpers.CLICK_SONG, required=True, nargs=-1)\n@click.option(\"-m\", \"--metadata\", \"pairs\", type=str, required=False)\n@click.option(\n    \"-a\",\n    \"--artist\",\n    help=\"Artist of the song. Overrides '-m/--metadata'.\",\n)\n@click.option(\n    \"-b\",\n    \"--album\",\n    help=\"Album of the song. Overrides '-m/--metadata'.\",\n)\n@click.option(\n    \"-c\",\n    \"--album-artist\",\n    help=\"Album artist of the song. Overrides '-m/--metadata'.\",\n)\ndef metadata(songs: tuple[helpers.Song], pairs, artist, album, album_artist):\n    \"\"\"\n    View or edit the metadata for songs.\n\n    If no options are passed, prints the metadata for each song in SONGS.\n\n    If '-m/--metadata' is passed, sets the metadata for the each song in SONGS\n    to the key-value pairs in -m/--metadata. The option should be passed as a\n    string of the form 'key1:value1|key2:value2|...'.\n\n    Possible editable metadata keys are: album, albumartist, artist, comment,\n    compilation, composer, discnumber, genre, lyrics, totaldiscs, totaltracks,\n    tracknumber, tracktitle, year, isrc\n    \"\"\"\n    valid_pairs = None\n    if any([artist, album, album_artist, pairs]):\n        if pairs:\n            pairs = [\n                tuple(pair.strip().split(\":\", 1)) for pair in pairs.split(\"|\")\n            ]\n        else:\n            pairs = []\n\n        valid_pairs = set(pairs[:])\n        for key, value in pairs:\n            if (\n                key not in config.METADATA_KEYS\n                or key.startswith(\"#\")\n                or key == \"artwork\"\n            ):\n                click.secho(\n                    f\"'{key}' is not a valid editable metadata key.\",\n                    fg=\"yellow\",\n                )\n                valid_pairs.remove((key, value))\n            elif key == \"artist\" and artist is not None:\n                valid_pairs.remove((key, value))\n            elif key == \"album\" and album is not None:\n                valid_pairs.remove((key, value))\n            elif key == \"albumartist\" and album_artist is not None:\n                valid_pairs.remove((key, value))\n\n        if artist is not None:\n            valid_pairs.add((\"artist\", artist))\n        if album is not None:\n            valid_pairs.add((\"album\", album))\n        if album_artist is not None:\n            valid_pairs.add((\"albumartist\", album_artist))\n\n        if not valid_pairs:\n            click.secho(\"No valid metadata keys passed.\", fg=\"red\")\n            return\n\n        click.secho(f\"Valid pairs: {valid_pairs}\", fg=\"green\")\n\n    for song in songs:\n        if not os.path.exists(song.song_path):\n            click.secho(\n                f'Song file \"{song.song_title}\" (ID {song.song_id}) not found.',\n                fg=\"red\",\n            )\n            continue\n\n        if valid_pairs:\n            for key, value in valid_pairs:\n                song.set_metadata(key, value)\n        else:\n            click.echo(\"Metadata for \", nl=False)\n            click.secho(song.song_title, fg=\"blue\", bold=True, nl=False)\n            click.echo(f\" (ID {song.song_id}):\")\n\n            for key in config.METADATA_KEYS:\n                try:\n                    click.echo(\n                        f\"\\t{key if not key.startswith('#') else key[1:]}: {song.get_metadata(key)}\"\n                    )\n                except KeyError:\n                    pass\n\n\n@cli.command(name=\"dir\")\n@click.argument(\"directory\", type=click.Path(file_okay=False), required=False)\ndef dir_(directory):\n    \"\"\"\n    Change the directory where maestro looks for songs. NOTE: This does not move\n    any songs. It only changes where maestro looks for songs. You will have to\n    move the songs yourself.\n\n    If no argument is passed, prints the current directory.\n    \"\"\"\n    if directory is None:\n        click.echo(config.settings[\"song_directory\"])\n        return\n\n    if not os.path.exists(directory):\n        os.makedirs(directory)\n\n    with open(config.SETTINGS_FILE, \"rb+\") as settings_file:\n        settings = msgspec.json.decode(settings_file.read())\n        settings[\"song_directory\"] = directory\n\n        settings_file.seek(0)\n        settings_file.write(msgspec.json.encode(settings))\n        settings_file.truncate()\n\n    click.secho(f\"Changed song directory to {directory}.\", fg=\"green\")\n\n\n@cli.command(name=\"version\")\ndef version():\n    \"\"\"\n    Currently installed maestro version (PyPI version of the `maestro-music`\n    package).\n    \"\"\"\n    click.echo(f\"{VERSION}\")\n\n\n@cli.command(name=\"login\")\n@click.argument(\"username\", required=False, default=None, type=str)\ndef login(username):\n    \"\"\"\n    Log in to maestro. Required for listen-along streaming and album covers in\n    the Discord rich presence. The USERNAME argument is optional; if not passed,\n    you will be prompted for your username.\n\n    Will log out from existing username if a new one is passed.\n    \"\"\"\n    helpers.login(username)\n\n\n@cli.command(name=\"logout\")\n@click.option(\n    \"-f/-nF\",\n    \"--force/--no-force\",\n    \"force\",\n    default=False,\n    help=\"Skip confirmation prompt.\",\n)\ndef logout(force):\n    \"\"\"\n    Log out of maestro.\n    \"\"\"\n    if not force:\n        click.echo(\"Are you sure you want to log out? [y/n] \", nl=False)\n        if input().lower() != \"y\":\n            return\n\n    import keyring\n\n    try:\n        username = keyring.get_password(\"maestro-music\", \"username\")\n        keyring.delete_password(\"maestro-music\", \"username\")\n        click.secho(f\"Logged out user '{username}'.\", fg=\"green\")\n    except keyring.errors.PasswordDeleteError:\n        click.secho(\"No user logged in.\", fg=\"red\")\n\n    try:\n        keyring.delete_password(\"maestro-music\", \"password\")\n        click.secho(\"Deleted password.\", fg=\"green\")\n    except keyring.errors.PasswordDeleteError:\n        click.secho(\"No password saved.\", fg=\"red\")\n\n\n@cli.command(name=\"signup\")\n@click.argument(\"username\", required=False, default=None, type=str)\n@click.option(\"-l/-nL\", \"--login/--no-login\", \"login_\", default=True)\ndef signup(username, login_):\n    \"\"\"\n    Create a new maestro account. Required for listen-along streaming and\n    album covers in the Discord rich presence.\n\n    The USERNAME argument is optional; if not passed, you will be prompted for\n    a username.\n\n    If the '-nL/--no-login' flag is passed, you will not be logged in after\n    creating the account. You can still log in later using 'maestro login'.\n    \"\"\"\n    helpers.signup(username, None, login_)\n\n\n@cli.command(name=\"clear-logs\")\ndef clear_logs():\n    \"\"\"\n    Clear all logs stored by maestro.\n    \"\"\"\n    try:\n        os.remove(config.LOGFILE)\n        try:\n            rmtree(config.OLD_LOG_DIR)\n        except FileNotFoundError:\n            pass\n        click.secho(\"Cleared logs.\", fg=\"green\")\n    except FileNotFoundError:\n        click.secho(\"No logs found.\", fg=\"yellow\")\n\n\n@cli.command(name=\"download-ffmpeg\")\ndef download_ffmpeg():\n    \"\"\"\n    Download ffmpeg locally. A global or local FFmpeg install is required for\n    clip editing.\n    \"\"\"\n    from spotdl.utils.ffmpeg import download_ffmpeg as spotdl_download_ffmpeg\n\n    spotdl_download_ffmpeg()\n\n\n@cli.command()\ndef migrate():\n    \"\"\"\n    Migrate the maestro database to the latest version.\n    \"\"\"\n    if not os.path.exists(config.OLD_SONGS_INFO_PATH):\n        click.secho(\n            \"Legacy files not found, no migration necessary.\", fg=\"yellow\"\n        )\n        return\n\n    d = {}\n    with open(config.OLD_SONGS_INFO_PATH, \"r\", encoding=\"utf-8\") as f:\n        for line in f.readlines():\n            if not line.strip():\n                continue\n            details = line.split(\"|\")\n\n            song_id = details[0]\n            song_file = details[1]\n            tags = details[2].split(\",\")\n            clip = list(map(float, details[3].split())) if details[3] else None\n            d[song_id] = {\n                \"filename\": song_file,\n                \"tags\": tags,\n                \"clips\": (\n                    {\n                        \"default\": clip,\n                    }\n                    if clip\n                    else {}\n                ),\n                \"stats\": {},\n            }\n\n    for path in os.listdir(config.OLD_STATS_DIR):\n        if not path.endswith(\".txt\"):\n            continue\n\n        with open(\n            os.path.join(config.OLD_STATS_DIR, path), \"r\", encoding=\"utf-8\"\n        ) as f:\n            year = os.path.splitext(path)[0]\n            if year.isdigit():\n                year = int(year)\n\n            for line in f.readlines():\n                if not line.strip():\n                    continue\n                details = line.split(\"|\")\n\n                song_id = details[0]\n                stats = float(details[1])\n                d[song_id][\"stats\"][year] = stats\n\n    import safer\n\n    with safer.open(config.SONGS_INFO_PATH, \"wb\") as f:\n        f.write(msgspec.json.encode(d))\n\n    # move old files to old-data\n    old_data_dir = os.path.join(config.MAESTRO_DIR, \"old-data/\")\n    os.makedirs(old_data_dir, exist_ok=True)\n    move(config.OLD_SONGS_INFO_PATH, old_data_dir)\n    move(config.OLD_STATS_DIR, old_data_dir)\n\n    click.secho(\n        f\"Legacy files '{config.OLD_SONGS_INFO_PATH}' and '{config.OLD_STATS_DIR}' were moved to '{old_data_dir}', which can be safely deleted after confirming that all song data was moved to '{config.SONGS_INFO_PATH}'.\",\n        fg=\"green\",\n    )\n\n\n@cli.command(name=\"format-data\")\n@click.argument(\"indent\", type=int, default=4)\ndef format_data(indent: int):\n    \"\"\"\n    Format the song data file to be more human-readable. The INDENT argument\n    specifies the number of spaces to indent each level of the JSON file.\n    \"\"\"\n    import safer\n\n    with open(config.SONGS_INFO_PATH, \"r\", encoding=\"utf-8\") as f:\n        data = msgspec.json.decode(f.read())\n\n    with safer.open(config.SONGS_INFO_PATH, \"wb\") as f:\n        f.write(msgspec.json.format(msgspec.json.encode(data), indent=indent))\n\n    click.secho(\n        f\"Formatted '{config.SONGS_INFO_PATH}' with an indent of {indent}.\",\n        fg=\"green\",\n    )\n\n\n@cli.command(name=\"lyrics\")\n@click.argument(\"songs\", required=False, type=helpers.CLICK_SONG, nargs=-1)\n@click.option(\n    \"-U/-nU\",\n    \"--update/--no-update\",\n    \"updating\",\n    default=False,\n    help=\"Update lyrics for song(s).\",\n)\n@click.option(\n    \"-R/-nR\",\n    \"--remove/--no-remove\",\n    \"removing\",\n    default=False,\n    help=\"Remove lyrics for song(s).\",\n)\n@click.option(\n    \"-O/-nO\",\n    \"--override/--no-override\",\n    \"override\",\n    default=True,\n)\n@click.option(\n    \"-T/-nT\",\n    \"--translated/--no-translated\",\n    \"translated\",\n    default=True,\n)\n@click.option(\n    \"-n\", \"--name\", \"name\", help=\"Name to use instead of the song title.\"\n)\n@click.option(\n    \"-o\",\n    \"--offset\",\n    \"offset\",\n    type=float,\n    default=0,\n    help=\"Offset lyrics (secs); positive means later, negative means earlier.\",\n)\n@click.option(\n    \"-F/-nF\",\n    \"--force/--no-force\",\n    \"force\",\n    default=False,\n    help=\"Skip confirmation prompt.\",\n)\n@click.option(\n    \"-A/-nA\",\n    \"--all/--no-all\",\n    \"all_\",\n    default=False,\n    help=\"Update lyrics for all songs.\",\n)\ndef lyrics_(\n    songs: tuple[helpers.Song],\n    updating,\n    removing,\n    override,\n    translated,\n    name,\n    offset,\n    force,\n    all_,\n):\n    \"\"\"\n    Display or update the lyrics for song(s). Shows the overridden lyrics if\n    they exist instead of the embedded metadata lyrics. To view the embedded\n    lyrics, you can use 'maestro metadata'. Any translated lyrics are also\n    shown by default if available; turn them off with '-nT/--no-translated'.\n\n    Updates (embedded metadata, not any overridden) lyrics if '-U/--update' is\n    passed, downloading synced lyrics if available. If the song has lyrics,\n    prompts for confirmation before updating unless '-F/--force' is passed.\n\n    If '-R/--remove' is passed, removes the override lyrics for each song\n    (prompts for confirmation). '-R/--remove' can only remove the overridden\n    lyrics, not the embedded lyrics. Use 'maestro metadata -m \"lyrics:\"' to\n    remove embedded lyrics.\n\n    If '-A/--all' is passed, update/remove/view lyrics for all songs. Errors if\n    SONGS are passed with '-A/--all'. Prompts for confirmation unless\n    '-F/--force' is passed. Ignored if not updating.\n\n    If the '-n/--name' flag is passed, uses NAME as the song title to search for\n    lyrics instead of the actual song title. Ignored if not updating.\n\n    If the '-o/--offset' flag is passed, offsets the lyrics by OFFSET seconds.\n    Updates override lyrics if they exist by default; pass '-O/--no-override' to\n    update only the embedded lyrics instead. Ignored if not updating.\n    \"\"\"\n    if updating and removing:\n        click.secho(\n            \"Cannot pass both '-U/--update' and '-R/--remove'.\",\n            fg=\"red\",\n        )\n        return\n\n    if len(songs) > 1 and name:\n        click.secho(\n            \"Cannot pass a name when updating lyrics for multiple songs.\",\n            fg=\"red\",\n        )\n        return\n    if not (songs or all_):\n        click.secho(\n            \"No songs passed. Use '-A/--all' to update lyrics for all songs.\",\n            fg=\"red\",\n        )\n        return\n    if songs and all_:\n        click.secho(\n            \"Cannot pass songs with '-A/--all'.\",\n            fg=\"red\",\n        )\n        return\n\n    if all_:\n        if not force:\n            click.echo(\n                f\"Are you sure you want to {'update override' if updating else ('remove override' if removing else ('show' if not offset else 'offset the'))} lyrics for all songs? [y/n] \",\n                nl=False,\n            )\n            if input().lower() != \"y\":\n                return\n        songs = helpers.SONGS\n        force = True\n\n    if not (updating or removing):  # viewing\n        if offset:\n            songs_valid = set(songs)\n            for song in songs:\n                parsed_lyrics = song.parsed_lyrics\n                parsed_override_lyrics = song.parsed_override_lyrics\n                embedded_is_timed = helpers.is_timed_lyrics(parsed_lyrics)\n                override_is_timed = helpers.is_timed_lyrics(\n                    parsed_override_lyrics\n                )\n                if not (embedded_is_timed or override_is_timed):\n                    click.secho(\n                        f'No timed lyrics found for \"{song.song_title}\" (ID: {song.song_id}).',\n                        fg=\"yellow\",\n                    )\n                    songs_valid.remove(song)\n                    continue\n\n                if embedded_is_timed:\n                    parsed_lyrics.offset += int(offset * 1000)\n                    song.raw_lyrics = parsed_lyrics.toLRC()\n                if override_is_timed:\n                    parsed_override_lyrics.offset += int(offset * 1000)\n                    song.raw_override_lyrics = parsed_override_lyrics.toLRC()\n            click.secho(\n                f\"Offset the lyrics for {helpers.pluralize(len(songs_valid), 'song')} by {offset} seconds.\",\n                fg=\"green\",\n            )\n            return\n\n        for song in songs:\n            show_lyrics = True\n            lyrics = song.parsed_override_lyrics or song.parsed_lyrics\n            translated_lyrics = song.parsed_translated_lyrics\n            if lyrics is None and translated_lyrics is None:\n                click.secho(\n                    f'No lyrics found for \"{song.song_title}\" (ID: {song.song_id}).',\n                    fg=\"yellow\",\n                )\n                show_lyrics = False\n            show_translated = translated and translated_lyrics is not None\n\n            if show_lyrics and show_translated:\n                click.echo(\"Lyrics for \", nl=False)\n                click.secho(song.song_title, fg=\"blue\", bold=True, nl=False)\n                click.echo(f\" (ID {song.song_id}):\")\n\n                is_timed = helpers.is_timed_lyrics(lyrics)\n                for i in range(len(lyrics)):\n                    time_str = \"\"\n                    if is_timed:\n                        time_str = f\"\\t[{helpers.format_seconds(lyrics[i].time, show_decimal=True)}] \"\n                        click.secho(\n                            f\"{time_str}{lyrics[i].text}\",\n                            fg=\"cyan\",\n                        )\n                    else:\n                        click.secho(\n                            \"\\t\" + lyrics[i],\n                            fg=\"cyan\",\n                        )\n                    if i < len(translated_lyrics):\n                        click.echo(\n                            \"\\t\"\n                            + \" \" * len(time_str)\n                            + helpers.get_lyric(translated_lyrics[i]),\n                        )\n            elif show_lyrics:\n                helpers.display_lyrics(lyrics, song)\n            elif show_translated:\n                helpers.display_lyrics(\n                    translated_lyrics,\n                    song,\n                    \"translated\",\n                )\n        return\n\n    import syncedlyrics\n\n    for song in songs:\n        if removing:\n            if override:\n                if not force:\n                    click.echo(\n                        f'Are you sure you want to remove override lyrics for \"{song.song_title}\" (ID {song.song_id})? This cannot be undone. [y/n] ',\n                        nl=False,\n                    )\n                if force or input().lower() == \"y\":\n                    song.raw_override_lyrics = None\n                    click.secho(\n                        f'Removed override lyrics for \"{song.song_title}\" (ID {song.song_id}).',\n                        fg=\"green\",\n                    )\n            if translated:\n                if not force:\n                    click.echo(\n                        f'Are you sure you want to remove translated lyrics for \"{song.song_title}\" (ID {song.song_id})? This cannot be undone. [y/n] ',\n                        nl=False,\n                    )\n                if force or input().lower() == \"y\":\n                    song.raw_translated_lyrics = None\n                    click.secho(\n                        f'Removed translated lyrics for \"{song.song_title}\" (ID {song.song_id}).',\n                        fg=\"green\",\n                    )\n            continue\n\n        song_title = name or f\"{song.artist} - {song.song_title}\"\n\n        if song.raw_lyrics:\n            if not force:\n                click.echo(\n                    f'Lyrics already exist for \"{song.song_title}\" (ID {song.song_id}). Overwrite? [y/n] ',\n                    nl=False,\n                )\n                if input().lower() != \"y\":\n                    continue\n\n        try:\n            # pylint: disable=unexpected-keyword-arg\n            lyrics = syncedlyrics.search(song_title, allow_plain_format=True)\n        except TypeError as e:\n            print_to_logfile(\n                f\"TypeError with allow_plain_format=True in syncedlyrics.search: {e}\"\n            )\n            try:\n                lyrics = syncedlyrics.search(song_title)\n            except Exception as f:\n                click.secho(\n                    f'Failed to download lyrics for \"{song_title}\": {f}',\n                    fg=\"red\",\n                )\n        except Exception as e:\n            click.secho(\n                f'Failed to download lyrics for \"{song_title}\": {e}',\n                fg=\"red\",\n            )\n        else:\n            if lyrics:\n                click.secho(\n                    f'Downloaded lyrics for \"{song.song_title}\" (ID {song.song_id})'\n                    + (f' using name \"{name}\"' if name else \"\")\n                    + \".\",\n                    fg=\"green\",\n                )\n                song.raw_lyrics = lyrics\n            else:\n                click.secho(f'No lyrics found for \"{song_title}\".', fg=\"yellow\")\n\n\n@cli.command(name=\"translit\")\n@click.argument(\"songs\", required=True, type=helpers.CLICK_SONG, nargs=-1)\n@click.option(\n    \"-l\",\n    \"--lang\",\n    type=click.Choice(\n        (\"japanese\", \"german\") + config.INDIC_SCRIPTS, case_sensitive=False\n    ),\n    help=\"Language-specific transliteration support.\",\n)\n@click.option(\n    \"-S/-nS\",\n    \"--save-override/--no-save-override\",\n    \"override\",\n    default=False,\n    help=\"Add override lyrics.\",\n)\n@click.option(\n    \"-F/-nF\",\n    \"--force/--no-force\",\n    \"force\",\n    default=False,\n    help=\"Skip confirmation prompt.\",\n)\ndef transliterate(songs, lang, override, force):\n    \"\"\"\n    Romanize foreign-script song lyrics. This is NOT translation, but rather\n    converting the script to a more readable form using the 'unidecode' package.\n    For example, \"తెలుగు\" would be transliterated to \"telugu\".\n\n    If '-S/--save-override' is passed, adds the transliterated lyrics as an\n    override for each song to maestro's internal data (prompts for confirmation\n    if override already exists unless '-F/--force' is passed). This retains the\n    original lyric metadata while allowing maestro to display the transliterated\n    lyrics instead in 'maestro play'.\n\n    Unidecode is not perfect and may not work well with all languages; for\n    example, 'ä' becomes 'a' instead of 'ae', and Japanese characters are\n    treated as Chinese characters (although maestro uses 'pykakasi' as a\n    workaround for Japanese).\n\n    If you're having issues, you can try explicitly passing the \"-l/--lang\"\n    option with either \"japanese\" or \"german\" to improve transliteration. The\n    former will skip unidecode and use pykakasi only, while the latter will\n    replace 'ä', 'ö', 'ü' with 'ae', 'oe', 'ue' before running unidecode.\n\n    Indic scripts are also supported using the 'indic_transliteration' package:\n    bengali, assamese, modi (i.e. Marathi), malayalam, devanagari, sinhala,\n    tibetan, gurmukhi (i.e. Punjabi), tamil, balinese, thai, burmese, telugu,\n    kannada, gujarati, urdu, lao, javanese, manipuri, oriya, khmer\n    \"\"\"\n    if not songs:\n        click.secho(\"No songs passed.\", fg=\"red\")\n        return\n\n    import re\n\n    from unidecode import unidecode\n\n    ja_regex = re.compile(\n        \"[\\u3000-\\u303f\\u3040-\\u309f\\u30a0-\\u30ff\\uff00-\\uff9f\\u4e00-\\u9faf\\u3400-\\u4dbf]\"\n    )\n\n    for song in songs:\n        lyrics = song.parsed_lyrics\n        if lyrics is None:\n            click.secho(\n                f'No lyrics found for \"{song.song_title}\" (ID: {song.song_id}).',\n                fg=\"red\",\n            )\n            return\n\n        if lang == \"de\":\n            for i in range(len(lyrics)):\n                helpers.set_lyric(\n                    lyrics,\n                    i,\n                    helpers.get_lyric(lyrics[i])\n                    .replace(\"ä\", \"ae\")\n                    .replace(\"ö\", \"oe\")\n                    .replace(\"ü\", \"ue\"),\n                )\n\n        if lang == \"ja\" or ja_regex.search(song.raw_lyrics):\n            from pykakasi import kakasi\n\n            kks = kakasi()\n            for i in range(len(lyrics)):\n                helpers.set_lyric(\n                    lyrics,\n                    i,\n                    \" \".join(\n                        [\n                            t[\"hepburn\"]\n                            for t in kks.convert(helpers.get_lyric(lyrics[i]))\n                        ]\n                    ),\n                )\n\n        if lang in config.INDIC_SCRIPTS:\n            from itertools import groupby\n\n            from indic_transliteration import sanscript\n\n            for i in range(len(lyrics)):\n                transliterated = \"\"\n                for is_indic, word in groupby(\n                    helpers.get_lyric(lyrics[i]).split(),\n                    lambda w: all(\n                        c not in \"abcdefghijklmnopqrstuvwxyz\" for c in w.lower()\n                    ),\n                ):\n                    word = \" \".join(word)\n                    if is_indic:\n                        word = (\n                            sanscript.transliterate(word, lang, \"iast\")\n                            .replace(\"c\", \"ch\")\n                            .replace(\"ā\", \"aa\")\n                            .replace(\"t\", \"th\")\n                            .replace(\"ṭ\", \"t\")\n                            .replace(\"ī\", \"ee\")\n                            .replace(\"ū\", \"oo\")\n                            .replace(\"è\", \"e\")\n                            .replace(\"ò\", \"o\")\n                            .replace(\"ṣ\", \"sh\")\n                            .replace(\"ś\", \"sh\")\n                            .replace(\"ḍ\", \"d\")\n                            .replace(\"ṇ\", \"n\")\n                        )\n                        word = re.sub(r\"ṃ(?=\\w)\", \"n\", word)\n                        word = word.replace(\"ṃ\", \"m\")\n                    transliterated += word + \" \"\n                helpers.set_lyric(lyrics, i, transliterated)\n\n        if lang != \"ja\" and lang not in config.INDIC_SCRIPTS:\n            for i in range(len(lyrics)):\n                helpers.set_lyric(\n                    lyrics, i, unidecode(helpers.get_lyric(lyrics[i]))\n                )\n\n        if override:\n            if song.raw_override_lyrics is not None:\n                if not force:\n                    click.echo(\n                        f'Override lyrics already exist for \"{song.song_title}\" (ID {song.song_id}), do you want to replace them? This action cannot be undone. [y/n] ',\n                        nl=False,\n                    )\n                    if input().lower() != \"y\":\n                        continue\n            if helpers.is_timed_lyrics(lyrics):\n                song.raw_override_lyrics = lyrics.toLRC()\n            else:\n                song.raw_override_lyrics = \"\\n\".join(lyrics)\n            click.secho(\n                f'Added override lyrics for \"{song.song_title}\" (ID {song.song_id}).',\n                fg=\"green\",\n            )\n        else:\n            helpers.display_lyrics(lyrics, song, \"transliterated\")\n\n\n@cli.command()\n@click.argument(\"songs\", required=True, type=helpers.CLICK_SONG, nargs=-1)\n@click.option(\n    \"-S/-nS\",\n    \"--save/--no-save\",\n    \"save_\",\n    default=False,\n    help=\"Save translated lyrics.\",\n)\n@click.option(\n    \"-f\",\n    \"--from\",\n    \"from_langs\",\n    help=\"Language(s) to translate from.\",\n    multiple=True,\n    default=(\"auto\",),\n)\n@click.option(\n    \"-t\",\n    \"--to\",\n    \"to_lang\",\n    help=\"Language to translate to.\",\n    default=\"English\",\n)\n@click.option(\n    \"-F/-nF\",\n    \"--force/--no-force\",\n    \"force\",\n    default=False,\n    help=\"Skip confirmation prompt.\",\n)\n@click.option(\n    \"-R/-nR\",\n    \"--remove/--no-remove\",\n    \"remove_\",\n    default=False,\n    help=\"Remove translated lyrics.\",\n)\ndef translate(songs, save_, from_langs, to_lang, force, remove_):\n    \"\"\"\n    Translate song lyrics using the 'translatepy' package.\n\n    If '-S/--save' is passed, saves the translated lyrics to be used by 'maestro\n    play' (displayed with original lyrics). If a translated lyric file already\n    exists, prompts for confirmation before overwriting unless '-F/--force' is\n    passed.\n\n    If '-R/--remove' is passed, removes the translated lyrics for each song\n    (prompts for confirmation unless '-F/--force' is passed).\n\n    Default translation is from 'auto' to 'English', but you can specify the\n    languages using the '-f/--from' and '-t/--to' options. Multiple '-f/--from'\n    options can be passed, and 'maestro translate' will attempt to detect the\n    language of each word/phrase. The first language in '-f/--from' is used as\n    the default language if a word/phrase is detected as a language that was not\n    passed.\n    \"\"\"\n    if not songs:\n        click.secho(\"No songs passed.\", fg=\"red\")\n        return\n\n    if remove_ and save_:\n        click.secho(\n            \"Cannot pass both '-R/--remove' and '-S/--save'.\",\n            fg=\"red\",\n        )\n        return\n\n    import translatepy.translators\n\n    from itertools import groupby\n\n    from translatepy import Translator, Language\n    from translatepy.exceptions import TranslatepyException\n\n    translator = Translator(\n        [\n            translatepy.translators.GoogleTranslateV2,\n            translatepy.translators.GoogleTranslateV1,\n            translatepy.translators.YandexTranslate,\n            translatepy.translators.ReversoTranslate,\n            translatepy.translators.DeeplTranslate,\n            translatepy.translators.LibreTranslate,\n            translatepy.translators.TranslateComTranslate,\n            translatepy.translators.MyMemoryTranslate,\n        ]\n    )\n    for i, service in enumerate(translator.services):\n        # pylint: disable=protected-access\n        translator._instantiate_translator(service, translator.services, i)\n\n    AUTO_LANG = Language(\"auto\")\n\n    from_langs = list(from_langs)\n    for i in range(len(from_langs)):\n        from_langs[i] = Language(from_langs[i])\n\n    to_lang = Language(to_lang)\n\n    if len(from_langs) > 1:\n        for lang in from_langs:\n            if lang.id == AUTO_LANG.id:\n                click.secho(\n                    \"Cannot pass 'auto' with other languages in '-f/--from'.\",\n                )\n                return\n\n    for song in songs:\n        if remove_:\n            song.raw_translated_lyrics = None\n            click.secho(\n                f'Removed translated lyrics for \"{song.song_title}\" (ID {song.song_id}).',\n                fg=\"green\",\n            )\n            continue\n\n        lyrics = song.parsed_lyrics\n        if lyrics is None:\n            click.secho(\n                f'No lyrics found for \"{song.song_title}\" (ID: {song.song_id}).',\n                fg=\"red\",\n            )\n            return\n\n        translated_lyrics = [helpers.get_lyric(lyric) for lyric in lyrics]\n        for i in range(len(lyrics)):\n            lyric = helpers.get_lyric(lyrics[i])\n            if not lyric:\n                continue\n\n            if len(from_langs) == 1 and from_langs[0].id != AUTO_LANG.id:\n                try:\n                    translated_lyrics[i] = translator.translate(\n                        lyric, to_lang, from_langs[0]\n                    ).result\n                except TranslatepyException as e:\n                    print_to_logfile(f\"TranslatepyException on {lyric}: {e}\")\n            else:\n                words = [[w, \"auto\"] for w in lyric.split()]\n                for word in words:\n                    try:\n                        word[1] = translator.language(word[0]).result\n                        if from_langs[0].id != AUTO_LANG.id:\n                            for lang in from_langs:\n                                if lang.id == word[1].id:\n                                    break\n                            else:\n                                word[1] = from_langs[0]\n                    except TranslatepyException as e:\n                        print_to_logfile(\n                            f\"TranslatepyException on {word[0]}: {e}\"\n                        )\n\n                translated_lyrics[i] = \"\"\n                for lang, phrase in groupby(words, lambda x: x[1].id):\n                    phrase = \" \".join([w[0] for w in phrase])\n                    if lang != to_lang.id:\n                        try:\n                            click.secho(phrase, fg=\"blue\", nl=False)\n                            phrase = translator.translate(\n                                phrase, to_lang, lang\n                            ).result\n                            print(\" ->\", phrase)\n                        except TranslatepyException as e:\n                            print_to_logfile(\n                                f\"TranslatepyException on {phrase}: {e}\"\n                            )\n                        for service in translator.services:\n                            service.clean_cache()\n                    translated_lyrics[i] += phrase + \" \"\n\n        if save_:\n            if song.raw_translated_lyrics is not None:\n                if not force:\n                    click.echo(\n                        f'Translated lyrics already exist for \"{song.song_title}\" (ID {song.song_id}), do you want to replace them? This action cannot be undone. [y/n] ',\n                        nl=False,\n                    )\n                    if input().lower() != \"y\":\n                        continue\n            song.raw_translated_lyrics = \"\\n\".join(translated_lyrics).strip()\n            click.secho(\n                f'Added translated lyrics for \"{song.song_title}\" (ID {song.song_id}).',\n                fg=\"green\",\n            )\n        else:\n            helpers.display_lyrics(translated_lyrics, song, \"translated\")\n\n\n@cli.command()\ndef user():\n    \"\"\"\n    Display the currently logged-in user.\n    \"\"\"\n    import keyring\n\n    try:\n        click.echo(keyring.get_password(\"maestro-music\", \"username\"))\n        try:\n            keyring.get_password(\"maestro-music\", \"password\")\n        except keyring.errors.KeyringError:\n            click.secho(\"No password saved.\", fg=\"red\")\n    except keyring.errors.KeyringError:\n        click.secho(\"No user logged in.\", fg=\"yellow\")\n\n\nif __name__ == \"__main__\":\n    # check if frozen\n    if getattr(sys, \"frozen\", False):\n        multiprocessing.freeze_support()\n\n    # click passes ctx, no param needed\n    cli()  # pylint: disable=no-value-for-parameter\n"
  },
  {
    "path": "readme.md",
    "content": "# maestro\n[![PyPI downloads](https://static.pepy.tech/badge/maestro-music)](https://pepy.tech/project/maestro-music) [![PyPI version](https://badge.fury.io/py/maestro-music.svg)](https://badge.fury.io/py/maestro-music) [![Support server](https://img.shields.io/discord/1117677384846544896.svg?color=7289da&label=maestro-cli&logo=discord)](https://discord.gg/AW8fh2QEav)\n\n`maestro` is a command-line tool to play songs (or any audio, really) in the terminal.\n![](https://github.com/PrajwalVandana/maestro-cli/raw/master/data/player.png)\n\nCheck out the [Discord server](https://discord.gg/AW8fh2QEav)!\n## Features\n- [cross-platform](#platforms)\n- [add songs](#adding-songs) from YouTube, YouTube Music, or Spotify\n- [stream your music](#streaming)\n- [lyrics](#lyrics)\n    - romanize foreign-language lyrics\n    - translate lyrics\n- [clips](#clips)\n- filter by [tags](#tags)\n- [listen statistics](#listen-statistics)\n- [shuffle](#shuffling) (along with precise control over the behavior of shuffling when repeating)\n- [audio visualization](#visualization) directly in the terminal\n- [Discord integration](#discord-status)\n- Now Playing Center integration on macOS (allows headphone controls)\n![](https://github.com/PrajwalVandana/maestro-cli/raw/master/data/now_playing.png)\n- [music discovery](#music-discovery)\n## Technical Details\n[Visualization Breakdown](https://github.com/PrajwalVandana/maestro-cli/blob/master/data/maestro_vis.pdf)\n[Listen-along Streaming Breakdown](https://github.com/PrajwalVandana/maestro-cli/blob/master/data/maestro_listen_along.pdf)\n## Installation\n### Using `pip`\nMake sure you have Python 3 and `pip` installed.\n\nFirst, run\n```\npip install maestro-music\n```\n**NOTE**: `pip install maestro` and `pip install maestro-cli` will NOT work, they are totally unrelated PyPI packages.\n\nNow, if you want to be able to directly download songs from YouTube or Spotify, you'll need to install [FFmpeg](https://ffmpeg.org/download.html). You can download FFmpeg yourself globally, or locally with `maestro download-ffmpeg`.\n### Download executable\nUsing Python and `pip` is the preferred way; executables may be slower/have bugs, and `pip` makes updating way easier. However, the releases page does have executables/installers for macOS, Windows, and Linux.\n#### macOS\nDownload the `.pkg` file corresponding to your Mac's architecture; Apple Silicon (M1, M2, M3, etc.) or Intel. Right click on the file in Finder and click \"Open\" (double clicking won't work). The installation may be a bit slow, and the first run of `maestro` will probably be slow as well.\n#### Windows\nDownload and install using `maestro-installer.exe`.\n#### Linux\nBuilt on Ubuntu; should work on other Linux distros too. Download and unzip `maestro-ubuntu.tar.gz`. This should unzip a folder named `dist`, which contains a single folder named `maestro`. Inside `maestro` will be another folder, `_internal`, and two scripts: `maestro` and `install-maestro`. Assuming you unzipped inside `Downloads`, run\n```bash\ncd Downloads/dist/maestro\nsudo ./install-maestro\n```\nYou can then safely delete `dist`.\n## Known Issues\nIf you get a segmentation fault when running `maestro play` on macOS, it may be caused by an issue with the Python installation that comes bundled with macOS, as Apple uses an old version of `ncurses` for the `curses` module. To fix this, you can install Python directly from the [Python website](python.org/downloads), which should fix the issue.\n\nIf you have issues on Linux, try `sudo apt-get install python3-dev python3-dbus`.\n## Platforms\nTested heavily on macOS, lightly on Windows and (Ubuntu) Linux. `maestro` was coded to be cross-platform, but if there are any problems, please open an issue (or PR if you know how to fix it!). You can also join the [Discord server](https://discord.gg/AW8fh2QEav) and ask for help there.\n\n`maestro` *should* work on any 3.x version of Python, but I coded it on 3.12 and don't test on earlier versions.\n\nSupports `.mp3`, `.wav`, `.flac`, and `.ogg` (Ogg Vorbis).\n## Usage\nRun `maestro -h` to get a list of commands. Run `maestro <some command> -h` to get comprehensive help for that command—the below is just an overview. Click `h` in the player session to get a list of commands (scrollable).\n\n`maestro` uses the concept of a positive integer **song ID** to uniquely refer to each song; any place where `maestro` expects a song ID should also allow a search phrase—if only one song matches, `maestro` will infer the song ID.\n### Adding Songs\nYou can add a song from a file or folder with `maestro add <PATH>`. To add songs in subfolders as well, pass the `-R`/`--recursive` flag.\n\nPass the `-Y`/`--youtube` flag to download from a YouTube or YouTube Music URL instead of a file path. This requires FFmpeg. Passing a YouTube Music **song** URL (not \"Video\") is recommended, as passing \"Video\"s (i.e. just normal YouTube videos) can sometimes mess up the artist/album data (this can always be fixed manually with the `maestro metadata` command, though).\n\nPass the `-S`/`--spotify` flag to download from a Spotify URL instead of a file path. This also requires installing FFmpeg.\n\nPass the `-P` or `--playlist` flag to download an entire YouTube playlist from a song URL with a playlist component, e.g. https://www.youtube.com/watch?v=V1Z586zoeeE&list=PLfSdF_HSSu55q-5p-maISZyr19erpZsTo. The `-P` flag is unnecessary if the URL points directly to a playlist, e.g. https://www.youtube.com/playlist?list=PLfSdF_HSSu55q-5p-maISZyr19erpZsTo.\n\nBy default, `maestro add` copies the file to its internal database (`~/.maestro-files`), but you can pass the `-M` or `--move` flag to move the file instead. You can also change the folder where the songs are stored with `maestro dir`.\n### Tags\nPlaylists don't exist—`maestro` uses **tags**. For example, let's say you want to be able to listen to all your rap songs together. Instead of adding them all to a playlist, run `maestro tag <space-separated song IDs for each rap song> -t rap`. Then `maestro play rap` will play all the songs you've added the `rap` tag to. Basically, if song `s` has tag `t`, then you can think of song `s` as belonging to the playlist defined by tag `t`. The advantage of tags over playlists is that you can combine tags; `maestro play A B` will play only songs tagged `A` or `B` (add the `-M/--match-all` flag to play only songs tagged `A` *and* `B`).\n### Listen Statistics\n`maestro` also tracks your listen time—total and by year. You can see this with `maestro list` and/or `maestro entry`. For example, to see your top 10 listened songs this year (by average number of times listened; note that this is NOT the number of times the song was played, but rather the total listen time for that song divided by the duration), run `maestro list --reverse --sort times-listened --top 10 --year cur`—replace 'cur' with e.g. '2020' to get the listen times for 2020 instead.\n![](https://github.com/PrajwalVandana/maestro-cli/raw/master/data/list.png)\n### Clips\nEver been listening to music, and you're skipping every song because you keep getting bored of them? You like the songs, you're just not in the mood to listen to all of them entirely.\n\nIntroducing clips, something I've always wished the big companies like Spotify and YouTube Music would do. Use `maestro clip <song ID> <START> <END>` to define a clip for any song with a start and end timestamp (or use the clip editor for fine-grained control with `maestro clip <song ID>`), then `maestro play -C` to play in \"clip mode\" (can also be toggled in the player session with the `c` key)—this will play the clips for each song (or the entire song if there's no clip). Now you can listen to only the best parts of your music!\n\nBy default, `maestro clip` creates a clip named 'default'; you can add additional clips with the `--name` option:\n```bash\nmaestro clip <song ID> --name clip1\nmaestro set-clip <song ID> clip1\n```\nThe `maestro set-clip` command will set 'clip1' as the clip to be played in clip mode instead of 'default'.\n### Lyrics\n`maestro add` will automatically attempt to download lyrics (synced if possible) for the song. You can romanize foreign-language lyrics with `maestro translit <song ID> --save`, which will save the romanization as an override `.lrc` file (the original lyrics will still be preserved in the metadata of the song's file, but the override will be used). You can add a translation for a song with `maestro translate <song ID> --save`, which can then be shown with the lyrics using `maestro play --lyrics --translated-lyrics`. Not passing `--save` to either command will print the lyrics instead of saving them.\n\nPress `y` in the player session to toggle lyrics, `t` to toggle translated lyrics. To scroll through lyrics, change focus to the lyrics window with `}` (you can change focus back to the queue with `{`).\n### Shuffling\n`maestro play` accepts two shuffle options, `-s`/`--shuffle` and `-r`/`--reshuffle`. The first is for shuffling the song before the player session starts, and the second is for reshuffling the queue when it loops (the `-r` option is ignored if you don't also pass the `-L`/`--loop` flag to loop the queue). The default for both is `0`, i.e. no shuffling. To shuffle completely randomly, pass `-1`; otherwise, passing any positive integer `n` will ensure that each song is no more than `n` positions away in the queue from its previous position.\n### Visualization\nRun `maestro play --visualize` or click `v` in the player session to show the visualizer.\n### Discord Status\nRun `maestro play --discord` or click `d` in the player session to show the currently playing song in your Discord status (requires the Discord app to be open). Hovering over the image will show the album name. To show album art, requires signing up/logging in with `maestro signup`/`maestro login`.\n\n<img src=\"https://github.com/PrajwalVandana/maestro-cli/raw/master/data/discord.png\" width=\"300\"/>\n\n### Streaming\nIf you're logged in as `user123`, run `maestro play --stream` (or click `s` in the player session) to stream your music to `maestro-music.vercel.app/listen-along/user123`. This will show up as a \"Listen Along\" button on your Discord status too, if the Discord status is enabled (some versions of the Discord app don't show buttons on your own status, but it should show for everyone else).\n![](https://github.com/PrajwalVandana/maestro-cli/raw/master/data/stream.png)\n### Music Discovery\nUse `maestro recommend <song ID>` to recommend similar songs (searches up the song name on YouTube Music).\n"
  },
  {
    "path": "requirements.txt",
    "content": "click  # CLI handling\njust_playback  # Audio playback\nmusic-tag  # Metadata handling\npillow  # Image processing (required by music-tag for album art)\npypresence >= 4.3.0  # Discord Rich Presence\nyt-dlp  # YouTube downloads\nspotdl  # Spotify downloads\nytmusicapi  # Song recommendation (experimental)\nlibrosa  # Audio processing\nnumba  # JIT compilation\nnumpy ~= 1.26  # 2.0.0 breaks librosa\nwindows-curses; sys_platform == 'win32'  # Windows curses support\nkeyring  # Credential storage\nrequests  # HTTP requests\nmsgspec  # Faster JSON serialization\nsyncedlyrics  # Search for synced lyrics\npylrc  # LRC file parsing\nsafer  # safe file writing\ngrapheme  # Unicode grapheme clusters\nunidecode  # transliteration  # NOTE: GPL v3\npykakasi  # Japanese transliteration  # NOTE: GPL v3\ntranslatepy  # Translation  # NOTE: GPL v3\nindic_transliteration  # Indic transliteration\n\n# PyObjC dependencies for macOS\npyobjc-core; sys_platform == 'darwin'\npyobjc-framework-ApplicationServices; sys_platform == 'darwin'\npyobjc-framework-AVFoundation; sys_platform == 'darwin'\npyobjc-framework-Cocoa; sys_platform == 'darwin'\npyobjc-framework-CoreAudio; sys_platform == 'darwin'\npyobjc-framework-CoreMedia; sys_platform == 'darwin'\npyobjc-framework-MediaPlayer; sys_platform == 'darwin'\npyobjc-framework-Quartz; sys_platform == 'darwin'"
  },
  {
    "path": "scripts/add_album_art.py",
    "content": "\"\"\"\nAdd album art to songs that don't have it, using the title of the song to search\nSpotify for the album art. Can fail sometimes; the 'custom_album_art.py' script\noffers more control over the process, but requires manual non-CLI input.\n\nUsage: python add_album_art.py <path_to_songs_directory>\n\"\"\"\n\nimport json\nimport os\nimport sys\nimport subprocess\n\nimport music_tag\nimport requests\n\n\nDIR = sys.argv[1]  # REPLACE WITH THE PATH TO YOUR SONGS DIRECTORY\n\nfor path in os.listdir(DIR):\n    fname, ext = os.path.splitext(path)\n    if ext not in (\".mp3\", \".flac\", \".ogg\", \".wav\"):\n        continue\n\n    m = music_tag.load_file(os.path.join(DIR, path))\n    if m[\"artwork\"]:\n        continue\n\n    subprocess.run(\n        [\n            \"spotdl\",\n            \"save\",\n            fname,\n            \"--save-file\",\n            \"temp.spotdl\",\n        ],\n        check=True,\n    )\n\n    with open(\"temp.spotdl\", \"r\") as f:  # pylint: disable=unspecified-encoding\n        m[\"artwork\"] = requests.get(\n            json.load(f)[0][\"cover_url\"], timeout=5\n        ).content\n        m.save()\n"
  },
  {
    "path": "scripts/custom_album_art.py",
    "content": "\"\"\"\nUsage: python custom_album_art.py <path_to_songs_directory>\n\"\"\"\n\nimport json\nimport os\nimport subprocess\nimport sys\n\nimport music_tag\nimport requests\n\nfrom yt_dlp import YoutubeDL\n\n\nremove_paths = []  # song paths to remove artwork from\nyoutubeURLs = {}  # {filename: YouTube/YT Music URL to download artwork from}\nspotifyURLs = {}  # {filename: Spotify URL to download artwork from}\nDIR = sys.argv[1]  # REPLACE WITH THE PATH TO YOUR SONGS DIRECTORY\n\n\ndef yt_embed_artwork(path_, yt_dlp_info):\n    yt_dlp_info[\"thumbnails\"].sort(key=lambda d: d[\"preference\"])\n    best_thumbnail = yt_dlp_info[\"thumbnails\"][-1]  # default thumbnail\n\n    if \"width\" not in best_thumbnail:\n        # diff so that any square thumbnail is chosen\n        best_thumbnail[\"width\"] = 0\n        best_thumbnail[\"height\"] = -1\n\n    for thumbnail in yt_dlp_info[\"thumbnails\"][:-1]:\n        if \"height\" in thumbnail and (\n            thumbnail[\"height\"] == thumbnail[\"width\"]\n            and (best_thumbnail[\"width\"] != best_thumbnail[\"height\"])\n            or (\n                thumbnail[\"height\"] >= best_thumbnail[\"height\"]\n                and (thumbnail[\"width\"] >= best_thumbnail[\"width\"])\n                and (\n                    (best_thumbnail[\"width\"] != best_thumbnail[\"height\"])\n                    or thumbnail[\"width\"] == thumbnail[\"height\"]\n                )\n            )\n        ):\n            best_thumbnail = thumbnail\n\n    image_url = best_thumbnail[\"url\"]\n    response = requests.get(image_url, timeout=5)\n    image_data = response.content\n\n    m_ = music_tag.load_file(path_)\n    m_[\"artwork\"] = image_data\n    m_.save()\n\n\nfor path, url in spotifyURLs.items():\n    subprocess.run(\n        [\n            \"spotdl\",\n            \"save\",\n            url,\n            \"--save-file\",\n            \"temp.spotdl\",\n        ],\n        check=True,\n    )\n\n    with open(\"temp.spotdl\", \"r\") as f:  # pylint: disable=unspecified-encoding\n        m = music_tag.load_file(os.path.join(DIR, path))\n        m[\"artwork\"] = requests.get(\n            json.load(f)[0][\"cover_url\"], timeout=5\n        ).content\n        m.save()\n\nfor path, url in youtubeURLs.items():\n    with YoutubeDL() as ydl:\n        info = ydl.extract_info(url, download=False)\n        yt_embed_artwork(os.path.join(DIR, path), info)\n\nfor path in remove_paths:\n    m = music_tag.load_file(os.path.join(DIR, path))\n    m[\"artwork\"] = None\n    m.save()\n"
  },
  {
    "path": "scripts/rename_tracktitles.py",
    "content": "\"\"\"\nRename the 'tracktitle' metadata property of all songs to the name of the song\nfile. Sufficiently new versions of maestro will automatically do this when\nadding and renaming songs.\n\nUsage: python rename_tracktitles.py <path_to_songs_directory>\n\"\"\"\n\nimport os\nimport sys\n\nimport music_tag\n\n\nDIR = sys.argv[1]\n\nfor path in os.listdir(DIR):\n    fname, ext = os.path.splitext(path)\n    if ext not in (\".mp3\", \".flac\", \".ogg\", \".wav\"):\n        continue\n\n    m = music_tag.load_file(os.path.join(DIR, path))\n    m[\"tracktitle\"] = fname\n    m.save()\n"
  },
  {
    "path": "setup.py",
    "content": "from os.path import normpath\nimport re\n\nfrom setuptools import setup, find_packages\n\n\nd = {}\nwith open(normpath(\"maestro/__version__.py\"), encoding=\"utf-8\") as version_file:\n    exec(version_file.read(), d)  # pylint: disable=exec-used\nVERSION = d[\"VERSION\"]\n\n_INLINE_COMMENT_RE = re.compile(r\"\\s+#\")\n\n\ndef read_requirements(path: str) -> list[str]:\n    requirements: list[str] = []\n    with open(path, encoding=\"utf-8\") as f:\n        for raw_line in f:\n            line = raw_line.strip()\n            if not line or line.startswith(\"#\"):\n                continue\n\n            if line.startswith((\"-r \", \"--requirement \")):\n                _, included_path = line.split(maxsplit=1)\n                requirements.extend(read_requirements(included_path))\n                continue\n\n            if line.startswith((\"-c \", \"--constraint \")):\n                continue\n\n            match = _INLINE_COMMENT_RE.search(line)\n            if match:\n                line = line[: match.start()].rstrip()\n\n            if line:\n                requirements.append(line)\n\n    return requirements\n\n\ninstall_requires = read_requirements(\"requirements.txt\")\n\n\ndef main() -> None:\n    setup(\n        name=\"maestro-music\",\n        version=VERSION,\n        author=\"Prajwal Vandana\",\n        url=\"https://github.com/PrajwalVandana/maestro-cli\",\n        description=\"A simple command line tool to play songs (or any audio files, really).\",\n        long_description=open(\"readme.md\", encoding=\"utf-8\").read(),\n        license=\"MIT\",\n        license_files=[\"LICENSE\"],\n        long_description_content_type=\"text/markdown\",\n        keywords=[\n            \"music\",\n            \"sound\",\n            \"audio\",\n            \"music-player\",\n            \"cli\",\n            \"ogg\",\n            \"vorbis\",\n            \"ogg vorbis\",\n            \"flac\",\n            \"mp3\",\n            \"wav\",\n            \"spotify\",\n            \"youtube\",\n            \"audio-visualization\",\n            \"audio-visualizer\",\n        ],\n        packages=find_packages(include=[\"maestro\"]),\n        install_requires=install_requires,\n        entry_points={\n            \"console_scripts\": [\n                \"maestro = maestro.main:cli\",\n            ],\n        },\n    )\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "specs/maestro-mac.spec",
    "content": "# -*- mode: python ; coding: utf-8 -*-\nfrom PyInstaller.utils.hooks import collect_all\n\ndatas = []\nbinaries = []\nhiddenimports = []\ntmp_ret = collect_all('ytmusicapi')\ndatas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]\ntmp_ret = collect_all('pykakasi')\ndatas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]\ntmp_ret = collect_all('indic_transliteration')\ndatas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]\ntmp_ret = collect_all('grapheme')\ndatas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]\n\n\nblock_cipher = None\n\n\na = Analysis(\n    ['../maestro/main.py'],\n    pathex=[],\n    binaries=binaries,\n    datas=datas,\n    hiddenimports=hiddenimports,\n    hookspath=[],\n    hooksconfig={},\n    runtime_hooks=[],\n    excludes=[],\n    win_no_prefer_redirects=False,\n    win_private_assemblies=False,\n    cipher=block_cipher,\n    noarchive=False,\n)\npyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)\n\nexe = EXE(\n    pyz,\n    a.scripts,\n    [],\n    exclude_binaries=True,\n    name='maestro',\n    debug=False,\n    bootloader_ignore_signals=False,\n    strip=False,\n    upx=True,\n    console=True,\n    disable_windowed_traceback=False,\n    argv_emulation=False,\n    target_arch=None,\n    codesign_identity=None,\n    entitlements_file=None,\n)\ncoll = COLLECT(\n    exe,\n    a.binaries,\n    a.zipfiles,\n    a.datas,\n    strip=False,\n    upx=True,\n    upx_exclude=[],\n    name='maestro',\n)\n"
  },
  {
    "path": "specs/maestro-ubuntu.spec",
    "content": "# -*- mode: python ; coding: utf-8 -*-\nfrom PyInstaller.utils.hooks import collect_all\n\ndatas = []\nbinaries = []\nhiddenimports = []\ntmp_ret = collect_all('ytmusicapi')\ndatas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]\ntmp_ret = collect_all('pykakasi')\ndatas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]\ntmp_ret = collect_all('indic_transliteration')\ndatas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]\ntmp_ret = collect_all('grapheme')\ndatas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]\ntmp_ret = collect_all('indic_transliteration')\ndatas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]\ntmp_ret = collect_all('grapheme')\ndatas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]\n\n\nblock_cipher = None\n\n\na = Analysis(\n    ['../maestro/main.py'],\n    pathex=[],\n    binaries=binaries,\n    datas=datas,\n    hiddenimports=hiddenimports,\n    hookspath=[],\n    hooksconfig={},\n    runtime_hooks=[],\n    excludes=[],\n    win_no_prefer_redirects=False,\n    win_private_assemblies=False,\n    cipher=block_cipher,\n    noarchive=False,\n)\npyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)\n\nexe = EXE(\n    pyz,\n    a.scripts,\n    [],\n    exclude_binaries=True,\n    name='maestro',\n    debug=False,\n    bootloader_ignore_signals=False,\n    strip=False,\n    upx=True,\n    console=True,\n    disable_windowed_traceback=False,\n    argv_emulation=False,\n    target_arch=None,\n    codesign_identity=None,\n    entitlements_file=None,\n)\ncoll = COLLECT(\n    exe,\n    a.binaries,\n    a.zipfiles,\n    a.datas,\n    strip=False,\n    upx=True,\n    upx_exclude=[],\n    name='maestro',\n)\n"
  },
  {
    "path": "specs/maestro-windows.spec",
    "content": "# -*- mode: python ; coding: utf-8 -*-\nfrom PyInstaller.utils.hooks import collect_all\n\ndatas = []\nbinaries = []\nhiddenimports = []\ntmp_ret = collect_all('ytmusicapi')\ndatas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]\ntmp_ret = collect_all('pykakasi')\ndatas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]\ntmp_ret = collect_all('indic_transliteration')\ndatas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]\ntmp_ret = collect_all('grapheme')\ndatas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]\n\n\nblock_cipher = None\n\n\na = Analysis(\n    ['../maestro/main.py'],\n    pathex=[],\n    binaries=binaries,\n    datas=datas,\n    hiddenimports=hiddenimports,\n    hookspath=[],\n    hooksconfig={},\n    runtime_hooks=[],\n    excludes=[],\n    win_no_prefer_redirects=False,\n    win_private_assemblies=False,\n    cipher=block_cipher,\n    noarchive=False,\n)\npyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)\n\nexe = EXE(\n    pyz,\n    a.scripts,\n    [],\n    exclude_binaries=True,\n    name='maestro',\n    debug=False,\n    bootloader_ignore_signals=False,\n    strip=False,\n    upx=True,\n    console=True,\n    disable_windowed_traceback=False,\n    argv_emulation=False,\n    target_arch=None,\n    codesign_identity=None,\n    entitlements_file=None,\n)\ncoll = COLLECT(\n    exe,\n    a.binaries,\n    a.zipfiles,\n    a.datas,\n    strip=False,\n    upx=True,\n    upx_exclude=[],\n    name='maestro',\n)\n"
  },
  {
    "path": "uninstall-scripts/unix",
    "content": "#!/bin/sh\n\nMAESTRO_BUNDLE_LOC=/usr/local/bin/maestro-bundle\nMAESTRO_SYMLINK_LOC=/usr/local/bin/maestro\n\n# Remove bundle files\necho Removing maestro bundle files at $MAESTRO_BUNDLE_LOC\nrm -rf $MAESTRO_BUNDLE_LOC  || echo Failed to remove maestro bundle files at $MAESTRO_BUNDLE_LOC, try running with sudo\n\n# Remove symlink\necho Removing symlink at $MAESTRO_SYMLINK_LOC\nrm -rf $MAESTRO_SYMLINK_LOC || echo Failed to remove maestro symlink at $MAESTRO_SYMLINK_LOC, try running with sudo\n\necho \"Uninstall complete; maestro data at ~/.maestro-files has not been deleted\""
  }
]