diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..e4cdc56 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,21 @@ +name: macOS + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build: + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - name: Test + run: make test + - name: Build (release, universal) + run: make release + - uses: actions/upload-artifact@v4 + with: + name: SonyNotch-macOS + path: build/SonyNotch.zip diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml deleted file mode 100644 index 37a3a53..0000000 --- a/.github/workflows/cmake.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Linux & Windows - -on: - push: - branches: - - main - - master - - 'feature/**' - pull_request: - branches: - - main - - master - workflow_dispatch: - -env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) - BUILD_TYPE: Release - -jobs: - build: - strategy: - matrix: - os: ["ubuntu-latest", "windows-latest"] - include: - - os: ubuntu-latest - binary_path: Client/build/SonyHeadphonesClient - artifact_name: "SonyHeadphonesClient-linux-x64" - script: "sudo apt-get update && sudo apt-get install libbluetooth-dev libglew-dev libglfw3-dev libdbus-1-dev" - - os: windows-latest - binary_path: Client/build/Release/SonyHeadphonesClient.exe - artifact_name: "SonyHeadphonesClient-win-x64.exe" - script: "" - runs-on: ${{ matrix.os }} - - steps: - - uses: actions/checkout@v4 - with: - submodules: true - - - name: Download Packages - run: ${{ matrix.script }} - - - name: Create Build Environment - # Some projects don't allow in-source building, so create a separate build directory - # We'll use this as our working directory for all subsequent commands - run: cmake -E make_directory ${{github.workspace}}/Client/build - - - name: Configure CMake - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash - working-directory: ${{github.workspace}}/Client/build - # Note the current convention is to use the -S and -B options here to specify source - # and build directories, but this is only available with CMake 3.13 and higher. - # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 - run: cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE - - - name: Build - working-directory: ${{github.workspace}}/Client/build - shell: bash - # Execute the build. You can specify a specific target with "--target " - run: cmake --build . --config $BUILD_TYPE - - name: Upload a Build Artifact - uses: actions/upload-artifact@v4 - with: - # Artifact name - name: ${{ matrix.artifact_name }} - # A file, directory or wildcard pattern that describes what to upload - path: ${{github.workspace}}/${{matrix.binary_path}} - # The desired behavior if no files are found using the provided path. - - diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..b2f31a2 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,50 @@ +name: Release + +# Push a version tag to publish a release: +# git tag v1.0.0 && git push origin v1.0.0 +# The app gets its version from the tag, is tested and built for Apple Silicon and Intel, and the zip is attached +# to a GitHub release with its SHA-256 (used by the Homebrew cask). + +on: + push: + tags: ["v*.*.*"] + +permissions: + contents: write + +jobs: + release: + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + + - name: Set the app version from the tag + run: | + VERSION="${GITHUB_REF_NAME#v}" + echo "VERSION=$VERSION" >> "$GITHUB_ENV" + /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $VERSION" Client/macos/info.plist + /usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${{ github.run_number }}" Client/macos/info.plist + + - name: Test + run: make test + + - name: Build (release, universal) + run: make release + + - name: Checksum + run: | + cd build + shasum -a 256 SonyNotch.zip | tee SonyNotch.zip.sha256 + + # A release already made by hand for this tag (title and notes written on GitHub) only gets the files. + - name: Publish the release + env: + GH_TOKEN: ${{ github.token }} + run: | + if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then + gh release upload "$GITHUB_REF_NAME" build/SonyNotch.zip build/SonyNotch.zip.sha256 --clobber + else + gh release create "$GITHUB_REF_NAME" build/SonyNotch.zip build/SonyNotch.zip.sha256 \ + --title "SonyNotch $VERSION" \ + --generate-notes + fi diff --git a/.github/workflows/xcodebuild.yml b/.github/workflows/xcodebuild.yml deleted file mode 100644 index 2d3193e..0000000 --- a/.github/workflows/xcodebuild.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: macOS - -on: - push: - branches: - - master - pull_request: - branches: - - master - -jobs: - build: - strategy: - matrix: - os: ["macos-latest"] - include: - - os: macos-latest - binary_path: Client/build/SonyHeadphonesClient.zip - artifact_name: "SonyHeadphonesClient-macOS.zip" - runs-on: ${{ matrix.os }} - - steps: - - uses: actions/checkout@v3 - with: - submodules: true - - - name: Create build directory - working-directory: ${{github.workspace}}/Client - run: mkdir build - - - name: Build - working-directory: ${{github.workspace}}/Client/build - # Execute the build. - run: xcodebuild -project '../macos/SonyHeadphonesClient.xcodeproj' -config Release -scheme 'SonyHeadphonesClient' -archivePath ./archive archive | xcpretty - - - name: Export archive to .app - working-directory: ${{github.workspace}}/Client/build - # Exports the archive to a .app file - run: xcodebuild -exportArchive -archivePath ./archive.xcarchive -exportPath ./ -exportOptionsPlist ../macos/exportOptions.plist | xcpretty - - - name: Zip the exported file - working-directory: ${{github.workspace}}/Client/build - # Zip the application for easier downloading - run: zip -r SonyHeadphonesClient.zip SonyHeadphonesClient.app - - - name: Upload the zipped application - uses: actions/upload-artifact@v3 - with: - # Artifact name - name: ${{ matrix.artifact_name }} - # A file, directory or wildcard pattern that describes what to upload - path: ${{github.workspace}}/${{matrix.binary_path}} - # The desired behavior if no files are found using the provided path. - - diff --git a/.gitignore b/.gitignore index 32ccd08..4cb044e 100644 --- a/.gitignore +++ b/.gitignore @@ -523,10 +523,9 @@ MigrationBackup/ .ionide/ # End of https://www.toptal.com/developers/gitignore/api/c++,visualstudio,python -Client/imgui.ini # vscode .vscode/ -# linux build -Client/linux/sonyheadphonesclient.build/ +# brainstorming mockups (superpowers visual companion) +.superpowers/ diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index a739d31..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "Client/imgui"] - path = Client/imgui - url = https://github.com/ocornut/imgui.git diff --git a/Client/BluetoothWrapper.cpp b/Client/BluetoothWrapper.cpp index cd3cb74..f5d5435 100644 --- a/Client/BluetoothWrapper.cpp +++ b/Client/BluetoothWrapper.cpp @@ -27,7 +27,9 @@ BluetoothWrapper& BluetoothWrapper::operator=(BluetoothWrapper&& other) noexcept int BluetoothWrapper::sendCommand(const std::vector& bytes) { std::lock_guard guard(this->_connectorMtx); - auto data = CommandSerializer::packageDataForBt(bytes, DATA_TYPE::DATA_MDR, this->_seqNumber++); + // Use the current seq, don't advance it here: the next seq comes from the device's ACK + // (_waitForAck), so if this frame goes unanswered its seq is simply reused on the next call. + auto data = CommandSerializer::packageDataForBt(bytes, DATA_TYPE::DATA_MDR, this->_seqNumber); auto bytesSent = this->_connector->send(data.data(), data.size()); this->_waitForAck(); @@ -68,7 +70,9 @@ SonyProtocolVersion BluetoothWrapper::getProtocolVersion() noexcept Buffer BluetoothWrapper::sendCommandAndReadResponse(const std::vector& bytes, unsigned char retCommandId, int retSubType) { std::lock_guard guard(this->_connectorMtx); - auto data = CommandSerializer::packageDataForBt(bytes, DATA_TYPE::DATA_MDR, this->_seqNumber++); + // Use the current seq, don't advance it here: the next seq comes from the device's ACK + // (handled below), so if this frame goes unanswered its seq is simply reused on the next call. + auto data = CommandSerializer::packageDataForBt(bytes, DATA_TYPE::DATA_MDR, this->_seqNumber); this->_connector->send(data.data(), data.size()); // The device replies with an ACK and then the RET frame; unrelated notifications may interleave. @@ -92,8 +96,19 @@ Buffer BluetoothWrapper::sendCommandAndReadResponse(const std::vector& byt void BluetoothWrapper::_waitForAck() { - auto msg = this->_readMessage(); - this->_seqNumber = msg.seqNumber; + // The device may send its own DATA_MDR notifications (already ACKed inside _readMessage) before + // the ACK for our frame arrives; skip those and keep reading until we see the actual ACK, so + // _seqNumber never gets set from an unrelated message's seq. + for (int i = 0; i < 16; i++) + { + auto msg = this->_readMessage(); + if (msg.dataType == DATA_TYPE::ACK) + { + this->_seqNumber = msg.seqNumber; + return; + } + } + throw RecoverableException("No ACK received from device", true); } CommandSerializer::Message BluetoothWrapper::_readMessage() @@ -150,9 +165,10 @@ CommandSerializer::Message BluetoothWrapper::_readMessage() auto msg = CommandSerializer::unpackBtMessage(msgBytes); - // The device retransmits any DATA_MDR frame it sends until the host ACKs it. The ack carries the - // toggled 1-bit sequence number (1 - deviceSeq), matching the device's own ack-to-us behaviour. - if (msg.dataType == DATA_TYPE::DATA_MDR) + // The device retransmits any DATA_MDR or DATA_MDR_NO2 frame it sends until the host ACKs it (e.g. + // slider drags are echoed as DATA_MDR_NO2). The ack carries the toggled 1-bit sequence number + // (1 - deviceSeq), matching the device's own ack-to-us behaviour. + if (msg.dataType == DATA_TYPE::DATA_MDR || msg.dataType == DATA_TYPE::DATA_MDR_NO2) { auto ack = CommandSerializer::packageDataForBt({}, DATA_TYPE::ACK, (unsigned char)(1 - msg.seqNumber)); this->_connector->send(ack.data(), ack.size()); diff --git a/Client/CMakeLists.txt b/Client/CMakeLists.txt deleted file mode 100644 index 9695cef..0000000 --- a/Client/CMakeLists.txt +++ /dev/null @@ -1,112 +0,0 @@ -cmake_minimum_required(VERSION 3.5) -project(SonyHeadphonesClient) - -set(CMAKE_CXX_STANDARD 20) - -find_package(Threads REQUIRED) - -add_executable(SonyHeadphonesClient) - -add_definitions(-D__HEADPHONES_APP_VERSION__="0.4.0-beta2") - -target_sources(SonyHeadphonesClient - PRIVATE BluetoothWrapper.cpp - ByteMagic.cpp - CommandSerializer.cpp - TimedMessageQueue.cpp - CrossPlatformGUI.cpp "Headphones.cpp") - -target_include_directories (SonyHeadphonesClient - PRIVATE ${CMAKE_SOURCE_DIR} -) - -if(UNIX AND NOT APPLE) - set(LINUX TRUE) -endif() - -if (WIN32 OR LINUX) - set (DEAR_IMGUI TRUE) -endif() - -if (DEAR_IMGUI) - target_sources(SonyHeadphonesClient - PRIVATE CrossPlatformGUI.cpp - imgui/imgui.cpp - imgui/imgui_draw.cpp - imgui/imgui_tables.cpp - imgui/imgui_widgets.cpp - CascadiaCodeFont.cpp - ) - - target_include_directories (SonyHeadphonesClient - PRIVATE ${CMAKE_SOURCE_DIR}/imgui - ) -endif () - -if (LINUX) - target_sources(SonyHeadphonesClient - PRIVATE linux/DBusHelper.cpp - linux/LinuxBluetoothConnector.cpp - linux/LinuxGUI.cpp - linux/main.cpp - imgui/backends/imgui_impl_glfw.cpp - imgui/backends/imgui_impl_opengl3.cpp - ) - - set (CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/linux) - - set (OpenGL_GL_PREFERENCE GLVND) - - find_package(DBus REQUIRED) - - find_package(glfw3 REQUIRED) - - find_package(OpenGL REQUIRED) - - if ((NOT DBUS_FOUND) OR (NOT glfw3_FOUND) OR (NOT OPENGL_FOUND)) - message ( FATAL_ERROR - "Didn't find one of the packages. For Debian based systems, use:" - "sudo apt install libbluetooth-dev libglfw3-dev libdbus-1-dev" ) - endif () - - target_include_directories(SonyHeadphonesClient - PRIVATE ${DBUS_INCLUDE_DIRS} - ${OPENGL_INCLUDE_DIRS} - ) - - target_link_libraries(SonyHeadphonesClient - PRIVATE ${DBUS_LIBRARIES} - glfw - bluetooth - OpenGL::GL - ) - -endif () - -if (WIN32) - ADD_DEFINITIONS(-DUNICODE) - - target_sources(SonyHeadphonesClient - PRIVATE windows/WindowsGUI.cpp - windows/main.cpp - windows/WindowsBluetoothConnector.cpp - imgui/backends/imgui_impl_dx11.cpp - imgui/backends/imgui_impl_win32.cpp - ) - - target_link_libraries(SonyHeadphonesClient - PRIVATE d3d11 - ) -endif () - -target_link_libraries(SonyHeadphonesClient - PRIVATE Threads::Threads -) - -if (WIN32 OR LINUX) - add_custom_command(TARGET SonyHeadphonesClient POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory - "${CMAKE_CURRENT_SOURCE_DIR}/resources/devices" - "$/resources/devices" - COMMENT "Copying device hero images next to the binary") -endif() diff --git a/Client/CMakeSettings.json b/Client/CMakeSettings.json deleted file mode 100644 index 4c88030..0000000 --- a/Client/CMakeSettings.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "configurations": [ - { - "name": "x64-Debug", - "generator": "Ninja", - "configurationType": "Debug", - "inheritEnvironments": [ "msvc_x64_x64" ], - "buildRoot": "${projectDir}\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "" - }, - { - "name": "x64-Release", - "generator": "Ninja", - "configurationType": "Release", - "buildRoot": "${projectDir}\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "", - "inheritEnvironments": [ "msvc_x64_x64" ] - } - ] -} \ No newline at end of file diff --git a/Client/CascadiaCodeFont.cpp b/Client/CascadiaCodeFont.cpp deleted file mode 100644 index 621453a..0000000 --- a/Client/CascadiaCodeFont.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "CascadiaCodeFont.h" - -/* -Copyright (c) 2019 - Present, Microsoft Corporation, -with Reserved Font Name Cascadia Code. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. -*/ - -unsigned char CascadiaCodeTTF[358448] = {0,1,0,0,0,23,1,0,0,4,0,112,71,68,69,70,81,102,150,3,0,0,1,124,0,0,2,64,71,80,79,83,159,158,209,172,0,0,3,188,0,0,24,82,71,83,85,66,109,248,194,236,0,0,28,16,0,0,84,90,72,86,65,82,6,104,0,51,0,0,112,108,0,0,0,54,79,83,47,50,107,254,128,250,0,0,112,164,0,0,0,96,83,84,65,84,133,190,111,53,0,0,113,4,0,0,0,116,97,118,97,114,224,9,250,172,0,0,113,120,0,0,0,34,99,109,97,112,255,232,237,9,0,0,113,156,0,0,13,236,99,118,97,114,98,64,72,163,0,0,127,136,0,0,0,38,99,118,116,32,91,102,60,18,0,0,127,176,0,0,1,54,102,112,103,109,87,139,15,16,0,0,128,232,0,0,15,131,102,118,97,114,140,158,105,146,0,0,144,108,0,0,0,84,103,97,115,112,0,59,0,38,0,0,144,192,0,0,0,16,103,108,121,102,20,79,161,34,0,0,144,208,0,2,44,240,103,118,97,114,150,216,133,215,0,2,189,192,0,1,229,40,104,101,97,100,19,45,98,193,0,4,162,232,0,0,0,54,104,104,101,97,255,183,4,214,0,4,163,32,0,0,0,36,104,109,116,120,235,186,84,243,0,4,163,68,0,0,25,84,108,111,99,97,6,51,105,60,0,4,188,152,0,0,25,100,109,97,120,112,10,65,16,163,0,4,213,252,0,0,0,32,110,97,109,101,208,92,112,138,0,4,214,28,0,0,27,9,112,111,115,116,0,27,136,175,0,4,241,40,0,0,132,7,112,114,101,112,95,40,173,248,0,5,117,48,0,0,3,0,0,1,0,3,0,18,0,0,0,0,0,0,1,216,0,0,1,252,0,2,0,75,0,1,0,54,0,1,0,57,0,57,0,1,0,59,0,70,0,1,0,72,0,122,0,1,0,124,0,140,0,1,0,143,0,167,0,1,0,169,0,187,0,1,0,189,0,193,0,1,0,195,0,228,0,1,0,231,0,249,0,1,0,251,0,252,0,1,0,254,1,17,0,1,1,19,1,21,0,1,1,23,1,26,0,1,1,28,1,39,0,1,1,42,1,64,0,1,1,66,1,70,0,1,1,72,1,82,0,1,1,84,1,89,0,1,1,91,1,110,0,1,1,112,1,130,0,1,1,133,1,137,0,1,1,141,1,141,0,1,1,143,1,143,0,1,1,145,1,145,0,1,1,150,1,152,0,1,1,155,1,157,0,1,1,161,1,163,0,1,1,165,1,169,0,1,1,171,1,171,0,1,1,182,1,187,0,1,1,195,1,198,0,1,1,201,1,201,0,1,1,203,1,205,0,1,1,209,1,209,0,1,1,212,1,213,0,1,1,216,1,218,0,1,1,221,1,225,0,1,1,229,1,229,0,1,1,231,1,232,0,1,1,234,1,235,0,1,1,237,1,237,0,1,1,248,1,252,0,1,2,2,2,2,0,1,2,4,2,4,0,1,2,8,2,8,0,1,2,10,2,15,0,1,2,18,2,18,0,1,2,21,2,23,0,1,2,26,2,27,0,1,2,35,2,36,0,1,2,39,2,44,0,1,2,46,2,47,0,1,2,49,2,49,0,1,2,51,2,51,0,1,2,53,2,54,0,1,2,56,2,56,0,1,2,59,2,59,0,1,2,66,2,67,0,1,2,73,2,73,0,1,2,75,2,75,0,1,2,77,2,77,0,1,2,83,2,83,0,1,2,89,2,89,0,1,2,93,2,101,0,1,2,103,2,104,0,1,3,29,3,32,0,1,3,34,3,35,0,1,3,39,3,40,0,1,3,42,3,42,0,1,3,47,3,50,0,1,3,56,3,58,0,1,6,27,6,46,0,3,6,60,6,75,0,3,6,79,6,80,0,3,0,1,0,1,0,0,0,8,0,2,0,4,6,27,6,39,0,0,6,45,6,46,0,13,6,60,6,71,0,15,6,73,6,75,0,27,0,1,0,0,0,16,0,2,0,0,0,32,0,0,0,50,0,1,0,2,192,0,192,0,0,0,0,0,64,0,64,0,0,10,0,0,0,1,0,0,158,215,221,230,233,246,3,5,20,35,0,4,0,0,0,2,0,0,0,1,0,236,0,20,4,248,10,60,0,1,0,0,0,10,0,94,0,120,0,3,68,70,76,84,0,20,99,121,114,108,0,24,108,97,116,110,0,40,0,54,0,0,0,50,0,2,66,71,82,32,0,50,83,82,66,32,0,50,0,34,0,5,67,65,84,32,0,34,77,79,76,32,0,34,78,76,68,32,0,34,80,76,75,32,0,34,82,79,77,32,0,34,0,0,255,255,0,2,0,0,0,1,0,2,109,97,114,107,0,14,109,107,109,107,0,20,0,0,0,1,0,0,0,0,0,1,0,1,0,2,0,6,21,218,0,4,0,0,0,1,0,8,0,1,0,12,0,28,0,4,1,208,2,110,0,2,0,2,6,27,6,46,0,0,6,60,6,75,0,20,0,2,0,72,0,1,0,54,0,0,0,57,0,57,0,54,0,59,0,70,0,55,0,72,0,122,0,67,0,124,0,140,0,118,0,143,0,167,0,135,0,169,0,187,0,160,0,189,0,193,0,179,0,195,0,228,0,184,0,231,0,249,0,218,0,251,0,252,0,237,0,254,1,17,0,239,1,19,1,21,1,3,1,23,1,26,1,6,1,28,1,39,1,10,1,42,1,64,1,22,1,66,1,70,1,45,1,72,1,82,1,50,1,84,1,89,1,61,1,91,1,110,1,67,1,112,1,130,1,87,1,133,1,137,1,106,1,141,1,141,1,111,1,143,1,143,1,112,1,145,1,145,1,113,1,150,1,152,1,114,1,155,1,157,1,117,1,161,1,163,1,120,1,165,1,168,1,123,1,171,1,171,1,127,1,182,1,187,1,128,1,195,1,198,1,134,1,201,1,201,1,138,1,203,1,205,1,139,1,209,1,209,1,142,1,212,1,213,1,143,1,216,1,218,1,145,1,221,1,225,1,148,1,229,1,229,1,153,1,231,1,232,1,154,1,234,1,235,1,156,1,237,1,237,1,158,1,248,1,252,1,159,2,2,2,2,1,164,2,4,2,4,1,165,2,8,2,8,1,166,2,10,2,15,1,167,2,18,2,18,1,173,2,21,2,23,1,174,2,26,2,27,1,177,2,35,2,36,1,179,2,39,2,44,1,181,2,46,2,47,1,187,2,49,2,49,1,189,2,51,2,51,1,190,2,53,2,54,1,191,2,56,2,56,1,193,2,59,2,59,1,194,2,66,2,67,1,195,2,73,2,73,1,197,2,75,2,75,1,198,2,77,2,77,1,199,2,83,2,83,1,200,2,89,2,89,1,201,2,93,2,101,1,202,2,103,2,104,1,211,3,29,3,32,1,213,3,34,3,35,1,217,3,39,3,40,1,219,3,42,3,42,1,221,3,47,3,50,1,222,3,56,3,58,1,226,0,36,0,0,20,202,0,0,20,208,0,0,20,242,0,0,21,8,0,0,20,214,0,0,20,230,0,0,20,230,0,0,20,230,0,0,20,230,0,0,20,220,0,0,20,230,0,0,20,236,0,0,21,20,0,1,0,146,0,2,19,246,0,2,19,246,0,2,19,168,0,3,0,152,0,0,20,242,0,0,21,8,0,0,21,14,0,0,21,14,0,0,21,14,0,0,21,14,0,0,21,14,0,0,20,248,0,0,21,14,0,0,21,14,0,0,21,14,0,0,21,2,0,0,21,14,0,0,21,14,0,1,18,208,0,0,21,8,0,0,21,14,0,0,21,20,0,1,2,228,4,36,0,1,2,203,0,10,1,229,20,112,0,0,19,88,18,206,20,112,0,0,19,88,18,206,21,52,0,0,19,88,18,206,21,52,0,0,19,88,18,206,21,52,0,0,19,88,18,206,21,52,0,0,19,88,18,206,21,52,0,0,19,88,18,206,21,52,0,0,19,88,18,206,21,46,0,0,19,88,18,206,15,212,0,0,19,88,18,206,15,212,0,0,19,88,18,206,15,212,0,0,19,88,18,206,15,212,0,0,19,88,18,206,15,212,0,0,19,88,18,206,15,212,0,0,19,88,18,206,20,112,0,0,19,88,18,206,20,112,0,0,19,88,18,206,20,112,0,0,19,88,18,206,20,112,0,0,19,88,18,206,20,112,0,0,19,88,18,206,20,112,0,0,19,88,18,206,21,58,0,0,19,88,18,206,21,58,0,0,19,88,18,206,20,112,0,0,19,88,18,206,15,184,0,0,19,64,15,42,15,184,0,0,19,64,18,206,19,70,0,0,19,76,0,0,19,4,0,0,19,10,0,0,19,4,0,0,19,10,0,0,15,58,0,0,19,10,0,0,19,4,0,0,19,10,0,0,15,64,0,0,19,10,0,0,15,70,0,0,19,10,0,0,15,82,0,0,18,116,0,0,15,82,0,0,18,116,0,0,15,76,0,0,18,116,0,0,15,82,0,0,18,116,0,0,18,188,0,0,18,194,18,206,18,188,0,0,18,194,18,206,15,88,0,0,18,194,18,206,15,94,0,0,18,194,18,206,15,100,0,0,18,194,18,206,15,100,0,0,18,194,18,206,15,100,0,0,18,194,18,206,15,100,0,0,18,194,18,206,15,100,0,0,18,194,18,206,15,100,0,0,18,194,18,206,18,188,0,0,18,194,18,206,15,106,0,0,18,194,18,206,18,188,0,0,18,194,18,206,18,188,0,0,18,194,18,206,18,188,0,0,18,194,18,206,18,188,0,0,18,194,18,206,18,188,0,0,18,194,18,206,18,188,0,0,18,194,18,206,19,40,0,0,19,46,0,0,19,52,0,0,19,58,0,0,15,112,0,0,19,58,0,0,15,118,0,0,19,58,0,0,15,124,0,0,19,58,0,0,19,52,0,0,19,58,0,0,15,130,0,0,19,58,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,21,46,0,0,19,88,0,0,15,212,0,0,19,88,0,0,20,112,0,0,19,88,18,206,20,112,0,0,19,88,18,206,21,52,0,0,19,88,18,206,15,212,0,0,19,88,18,206,20,112,0,0,19,88,18,206,21,18,0,0,19,88,18,206,20,112,0,0,19,88,18,206,20,112,0,0,19,88,18,206,20,112,0,0,19,88,18,206,20,112,0,0,19,88,18,206,20,112,0,0,19,88,18,206,20,112,0,0,19,88,18,206,15,136,0,0,19,88,0,0,15,146,0,0,19,88,0,0,20,112,0,0,19,64,0,0,20,112,0,0,19,64,0,0,15,162,18,200,15,168,0,0,15,162,18,200,15,168,0,0,15,162,18,200,15,168,0,0,15,162,18,200,15,168,0,0,15,162,18,200,15,168,0,0,15,162,18,200,15,168,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,21,46,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,18,200,15,174,18,206,20,112,18,200,19,88,18,206,21,52,18,200,19,88,18,206,15,212,18,200,19,88,18,206,15,212,18,200,19,88,18,206,15,212,18,200,19,88,18,206,15,212,18,200,19,88,18,206,15,212,18,200,19,88,18,206,15,212,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,15,184,0,0,19,64,0,0,19,70,0,0,19,76,0,0,19,70,0,0,19,76,0,0,20,112,18,200,19,88,18,206,19,70,0,0,19,16,0,0,19,70,0,0,19,16,0,0,15,190,0,0,19,16,0,0,19,70,0,0,19,16,0,0,15,196,0,0,19,16,0,0,20,112,0,0,19,16,0,0,21,46,0,0,19,16,0,0,20,112,0,0,19,16,0,0,15,212,0,0,19,16,0,0,20,112,0,0,19,16,0,0,20,112,0,0,19,82,0,0,20,112,0,0,19,82,0,0,21,46,0,0,19,82,0,0,20,112,0,0,19,82,0,0,20,112,0,0,19,82,0,0,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,21,52,18,200,19,88,18,206,15,212,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,18,200,19,88,18,206,21,58,18,200,19,88,18,206,20,112,18,200,19,88,18,206,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,15,212,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,15,212,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,15,218,0,0,15,228,0,0,20,112,0,0,19,88,0,0,21,46,0,0,19,88,0,0,21,18,0,0,19,88,0,0,19,4,0,0,19,10,0,0,20,112,0,0,19,88,0,0,20,112,18,200,19,88,18,206,20,112,0,0,19,16,0,0,20,112,0,0,19,88,0,0,20,78,0,0,19,88,16,74,15,244,0,0,19,88,18,206,16,148,0,0,19,88,18,206,15,250,0,0,19,88,18,206,16,148,0,0,19,88,18,206,16,0,0,0,19,88,18,206,16,148,0,0,19,88,18,206,16,148,0,0,19,88,18,206,16,154,0,0,19,88,18,206,16,160,0,0,19,88,18,206,16,6,0,0,19,88,18,206,16,160,0,0,19,88,18,206,16,12,0,0,19,88,18,206,16,160,0,0,19,88,18,206,16,160,0,0,19,88,18,206,16,18,0,0,19,88,18,206,20,78,0,0,19,88,18,206,16,154,0,0,19,88,18,206,20,78,0,0,19,88,18,206,16,24,0,0,19,88,18,206,20,78,0,0,19,88,18,206,16,30,0,0,19,88,18,206,16,36,0,0,19,88,18,206,20,78,0,0,19,88,18,206,20,72,0,0,19,88,0,0,18,2,0,0,19,88,0,0,16,42,0,0,19,64,0,0,18,248,0,0,18,254,0,0,16,210,0,0,18,254,0,0,16,228,0,0,18,254,0,0,18,248,0,0,18,254,0,0,16,222,0,0,18,254,0,0,16,48,0,0,18,254,0,0,16,54,16,64,19,34,0,0,19,22,19,28,19,34,0,0,17,90,0,0,18,194,16,74,16,84,0,0,18,194,18,206,16,90,0,0,18,194,18,206,18,80,0,0,18,194,18,206,16,108,0,0,18,194,18,206,16,96,0,0,18,194,18,206,16,108,0,0,18,194,18,206,16,102,0,0,18,194,18,206,16,108,0,0,18,194,18,206,16,108,0,0,18,194,18,206,18,86,0,0,18,194,18,206,16,114,0,0,18,194,18,206,18,74,0,0,18,194,18,206,18,80,0,0,18,194,18,206,18,74,0,0,18,194,18,206,16,120,0,0,18,194,18,206,18,74,0,0,18,194,18,206,18,242,0,0,0,0,0,0,18,74,0,0,18,194,18,206,20,106,0,0,16,126,0,0,17,146,0,0,16,142,0,0,20,78,0,0,18,164,0,0,16,148,0,0,18,164,0,0,16,154,0,0,18,164,0,0,16,160,0,0,18,164,0,0,20,78,0,0,18,164,0,0,16,166,0,0,18,164,0,0,16,172,0,0,19,88,0,0,18,128,0,0,19,88,0,0,16,182,0,0,19,88,0,0,16,188,0,0,19,88,0,0,0,0,0,0,18,134,0,0,18,248,0,0,18,134,16,204,16,210,0,0,18,134,18,206,16,216,0,0,18,134,18,206,16,222,0,0,18,134,18,206,18,122,0,0,18,134,18,206,0,0,0,0,18,134,0,0,16,228,0,0,18,134,18,206,18,248,0,0,18,134,18,206,16,234,0,0,18,134,18,206,0,0,0,0,18,134,0,0,18,248,0,0,18,134,18,206,16,240,0,0,17,10,0,0,16,250,0,0,17,10,0,0,17,16,0,0,17,38,0,0,17,32,0,0,17,38,0,0,17,44,17,50,18,134,0,0,17,44,17,50,18,134,0,0,17,44,17,50,18,134,0,0,17,44,17,50,18,134,0,0,17,44,17,50,18,134,0,0,17,44,17,50,18,134,0,0,20,72,0,0,19,88,0,0,20,118,0,0,19,88,0,0,18,92,0,0,19,88,0,0,20,118,0,0,19,88,0,0,18,170,0,0,19,88,0,0,20,118,0,0,19,88,0,0,20,118,0,0,19,88,0,0,20,72,17,56,19,88,18,236,18,2,18,230,19,88,18,236,20,206,18,230,19,88,18,236,20,194,18,230,19,88,18,236,17,72,18,230,19,88,18,236,20,194,18,230,19,88,18,236,17,78,18,230,19,88,18,236,20,194,18,230,19,88,18,236,20,194,18,230,19,88,18,236,18,224,18,230,19,88,18,236,20,72,18,230,19,88,18,236,20,200,18,230,19,88,18,236,20,72,18,230,19,88,18,236,20,72,18,230,19,88,18,236,18,2,18,230,19,88,18,236,20,72,18,230,19,88,18,236,20,200,18,230,19,88,18,236,20,72,18,230,19,88,18,236,20,72,18,230,19,88,18,236,17,84,18,230,19,88,18,236,18,146,18,230,19,88,18,236,20,72,18,230,19,88,18,236,20,72,18,230,19,88,18,236,18,2,18,230,19,88,18,236,20,72,18,230,19,88,18,236,17,90,0,0,19,16,0,0,18,248,0,0,18,254,0,0,17,96,0,0,17,106,0,0,20,72,0,0,17,122,0,0,18,2,0,0,17,122,0,0,20,200,0,0,17,122,0,0,20,72,0,0,17,122,0,0,18,104,0,0,19,16,0,0,17,128,0,0,19,16,0,0,17,134,0,0,19,16,0,0,18,104,0,0,19,16,0,0,17,140,0,0,19,16,0,0,18,104,0,0,19,16,0,0,17,146,0,0,17,152,0,0,17,168,17,174,17,180,0,0,17,168,17,174,17,180,0,0,17,168,17,174,17,180,0,0,17,168,17,174,17,180,0,0,17,168,17,174,17,180,0,0,20,118,18,176,18,182,18,206,18,92,18,176,18,182,18,206,17,186,18,176,18,182,18,206,17,222,18,176,18,182,18,206,17,228,18,176,18,182,18,206,20,118,18,176,18,182,18,206,18,170,18,176,18,182,18,206,20,118,18,176,18,182,18,206,20,118,18,176,18,182,18,206,18,92,18,176,18,182,18,206,20,118,18,176,18,182,18,206,18,170,18,176,18,182,18,206,20,118,18,176,18,182,18,206,20,118,18,176,18,182,18,206,17,192,18,176,18,182,18,206,17,198,18,176,18,182,18,206,20,118,18,176,18,182,18,206,17,204,18,176,18,182,18,206,20,118,18,176,18,182,18,206,17,210,0,0,17,216,0,0,20,118,0,0,18,140,0,0,18,92,0,0,18,140,0,0,17,222,0,0,18,140,0,0,17,228,0,0,18,140,0,0,18,170,0,0,18,140,0,0,20,72,0,0,19,88,0,0,18,98,0,0,18,158,0,0,17,234,0,0,18,158,0,0,17,240,0,0,18,158,0,0,17,246,0,0,18,158,0,0,18,98,0,0,18,158,0,0,17,252,0,0,18,158,0,0,18,98,0,0,18,158,0,0,18,152,0,0,18,158,0,0,18,98,0,0,18,158,0,0,20,72,0,0,19,88,0,0,18,2,0,0,19,88,0,0,20,200,0,0,19,88,0,0,18,8,0,0,19,88,0,0,18,14,0,0,18,254,0,0,18,20,0,0,19,88,0,0,18,32,18,230,19,88,18,236,18,26,0,0,19,16,0,0,18,32,0,0,19,88,0,0,0,0,0,0,0,0,18,38,20,112,0,0,19,88,18,206,19,70,0,0,19,76,0,0,18,188,0,0,18,194,18,206,18,188,0,0,18,194,18,206,18,188,0,0,18,194,18,206,20,112,0,0,19,88,0,0,0,0,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,18,200,19,88,18,206,19,70,0,0,19,76,0,0,19,4,0,0,19,10,0,0,20,112,0,0,19,82,0,0,18,56,0,0,0,0,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,16,0,0,19,4,0,0,19,10,0,0,18,44,0,0,19,76,0,0,20,112,0,0,19,88,18,206,20,112,0,0,19,88,18,206,18,50,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,18,206,20,112,0,0,19,88,0,0,20,112,18,200,19,88,18,206,18,56,0,0,0,0,0,0,20,78,0,0,19,88,18,206,18,62,0,0,0,0,0,0,18,68,0,0,0,0,0,0,18,74,0,0,18,194,18,206,18,80,0,0,18,194,18,206,18,86,0,0,18,194,18,206,20,72,0,0,0,0,0,0,20,72,0,0,0,0,0,0,20,200,0,0,0,0,0,0,20,118,0,0,0,0,0,0,18,92,0,0,0,0,0,0,20,72,18,230,19,88,18,236,18,248,0,0,18,254,0,0,18,248,0,0,18,254,0,0,18,98,0,0,18,158,0,0,18,98,0,0,18,158,0,0,20,72,0,0,19,88,0,0,18,104,0,0,19,16,0,0,18,248,0,0,18,254,0,0,18,110,0,0,18,116,0,0,0,0,0,0,18,134,0,0,18,122,0,0,18,134,18,206,18,242,0,0,0,0,0,0,20,118,0,0,0,0,0,0,20,72,0,0,19,88,0,0,18,128,0,0,19,88,0,0,18,248,0,0,18,134,18,206,20,106,0,0,18,140,0,0,18,146,0,0,0,0,0,0,20,72,18,230,19,88,18,236,18,152,0,0,18,158,0,0,20,78,0,0,18,164,0,0,20,118,18,176,18,182,18,206,20,118,18,176,18,182,18,206,18,170,18,176,18,182,18,206,20,118,0,0,19,88,0,0,20,72,0,0,19,88,0,0,20,112,0,0,19,88,18,206,19,70,0,0,19,76,0,0,18,188,0,0,18,194,18,206,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,18,200,19,88,18,206,20,112,0,0,19,88,18,206,20,112,0,0,19,64,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,18,200,19,88,18,206,19,70,0,0,19,76,0,0,20,112,0,0,19,82,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,20,112,0,0,0,0,0,0,20,112,0,0,19,88,18,206,20,112,0,0,19,88,0,0,18,242,0,0,0,0,0,0,20,118,0,0,0,0,0,0,18,218,0,0,0,0,0,0,20,72,18,230,19,88,18,236,20,72,0,0,0,0,0,0,20,72,0,0,19,88,0,0,18,218,0,0,0,0,0,0,18,212,0,0,0,0,0,0,18,218,0,0,0,0,0,0,20,72,0,0,0,0,0,0,18,224,0,0,0,0,0,0,20,72,0,0,0,0,0,0,20,72,18,230,19,88,18,236,20,72,0,0,19,88,0,0,18,242,0,0,0,0,0,0,20,118,0,0,0,0,0,0,19,70,0,0,19,76,0,0,19,4,0,0,19,10,0,0,18,248,0,0,18,254,0,0,19,4,0,0,19,10,0,0,20,112,0,0,19,16,0,0,19,22,19,28,19,34,0,0,19,40,0,0,19,46,0,0,19,52,0,0,19,58,0,0,20,112,0,0,19,64,0,0,20,112,0,0,19,88,0,0,19,70,0,0,19,76,0,0,19,70,0,0,19,76,0,0,19,70,0,0,19,76,0,0,20,112,0,0,19,82,0,0,20,112,0,0,19,88,0,0,20,112,0,0,19,88,0,0,0,3,4,56,0,10,0,10,0,0,0,0,0,3,128,0,0,1,2,193,7,48,0,1,2,193,6,212,0,1,2,193,7,56,0,1,2,38,7,48,0,1,2,38,5,140,0,1,2,118,6,206,0,1,2,118,7,48,0,1,2,118,6,212,0,1,2,118,7,56,0,1,2,183,6,206,0,1,2,183,7,48,0,1,2,183,6,212,0,1,2,183,7,56,0,3,3,12,5,140,0,20,0,0,0,3,3,12,6,212,0,10,0,0,0,1,0,3,128,0,0,1,1,4,5,140,0,1,2,108,0,0,0,3,2,88,0,0,0,0,0,32,0,1,2,128,5,140,0,1,2,48,7,48,0,3,2,108,5,140,0,10,0,0,0,1,0,0,128,0,0,1,2,88,6,212,0,3,2,88,5,140,0,20,0,0,0,3,2,88,0,0,0,10,0,0,0,0,0,8,128,0,0,1,2,68,6,82,0,1,2,68,7,219,0,1,2,68,7,229,0,1,3,169,7,166,0,1,3,168,7,176,0,1,2,70,5,226,0,1,2,68,5,156,0,1,2,68,6,94,0,1,2,68,7,106,0,1,1,24,6,32,0,1,2,136,5,226,0,3,3,158,6,32,1,12,0,0,0,3,4,156,4,36,1,2,0,0,0,3,4,56,0,10,0,248,0,0,0,1,2,108,6,82,0,1,2,108,5,173,0,1,3,209,7,166,0,1,3,208,7,176,0,1,2,108,5,238,0,1,2,106,5,226,0,1,2,108,5,156,0,3,2,78,0,0,0,10,0,0,0,0,0,5,128,0,0,1,1,252,0,0,0,1,2,68,5,173,0,1,2,68,6,92,0,1,2,68,5,238,0,1,2,66,5,226,0,3,1,18,5,220,0,26,0,0,0,1,1,18,7,128,0,3,1,18,7,36,0,10,0,0,0,0,0,2,128,0,0,1,2,219,0,10,0,1,2,138,6,82,0,1,2,138,5,173,0,1,2,138,5,238,0,1,2,138,6,92,0,1,2,138,5,156,0,3,3,14,4,36,0,20,0,0,0,3,3,14,5,238,0,10,0,0,0,0,0,9,128,0,0,1,3,12,254,32,0,3,1,10,6,32,0,10,0,0,0,0,0,1,128,0,0,1,1,10,6,32,0,1,2,68,0,0,0,1,1,250,5,220,0,1,3,192,5,220,0,3,4,16,4,36,0,10,0,0,0,0,0,4,128,0,0,1,3,189,7,166,0,1,3,188,7,176,0,1,2,168,6,92,0,1,2,98,4,36,0,3,2,36,4,36,0,20,0,0,0,3,2,36,0,0,0,10,0,0,0,1,0,2,128,0,0,1,1,174,0,0,0,1,2,118,6,82,0,1,2,118,6,92,0,1,2,118,5,238,0,1,2,228,6,32,0,3,1,252,0,0,0,10,0,0,0,1,0,1,128,0,0,1,2,88,5,100,0,1,4,46,4,36,0,1,2,143,0,0,0,1,2,78,5,173,0,1,2,158,6,92,0,1,2,78,5,156,0,1,2,78,6,94,0,1,2,93,4,36,0,1,2,93,0,0,0,1,2,78,5,238,0,1,2,80,5,226,0,1,2,103,6,82,0,1,2,103,5,238,0,1,2,105,5,226,0,1,2,103,6,92,0,1,2,88,6,82,0,1,2,86,5,226,0,1,2,138,6,112,0,1,2,78,6,112,0,1,2,118,6,112,0,1,2,88,6,112,0,1,1,44,0,5,0,1,2,18,5,140,0,1,3,12,5,140,0,1,2,138,5,140,0,1,2,178,4,36,0,1,2,128,6,82,0,1,2,108,4,36,0,1,2,108,6,92,0,1,2,110,5,226,0,1,2,78,6,82,0,1,2,103,4,36,0,1,2,118,4,36,0,1,2,38,4,36,0,1,2,38,0,0,0,1,2,140,5,226,0,1,1,18,5,220,0,1,2,158,0,0,0,1,2,78,0,0,0,1,2,88,5,156,0,1,2,103,5,156,0,1,3,177,0,0,0,1,2,28,254,32,0,1,2,78,6,92,0,1,4,96,4,36,0,1,2,58,0,0,0,1,2,118,5,140,0,1,2,118,0,0,0,1,4,156,5,140,0,1,4,56,0,10,0,1,2,26,5,226,0,1,2,24,4,36,0,1,2,90,5,226,0,1,4,16,4,36,0,1,2,88,0,10,0,1,2,128,4,36,0,1,2,138,4,36,0,1,2,138,0,0,0,1,2,193,5,140,0,1,2,163,0,0,0,1,2,98,0,0,0,1,3,158,6,32,0,1,4,156,4,36,0,1,2,28,0,0,0,1,2,148,5,140,0,1,2,148,0,0,0,1,2,183,5,140,0,1,2,203,0,0,0,1,2,128,0,0,0,1,2,48,5,140,0,1,2,48,0,0,0,1,2,83,0,0,0,1,2,88,0,0,0,6,0,16,0,1,0,10,0,0,0,1,0,12,0,40,0,1,0,74,1,20,0,2,0,4,6,27,6,39,0,0,6,45,6,46,0,13,6,60,6,71,0,15,6,73,6,75,0,27,0,2,0,5,6,27,6,39,0,0,6,45,6,46,0,13,6,61,6,71,0,15,6,73,6,73,0,26,6,75,6,75,0,27,0,30,0,0,0,122,0,0,0,128,0,0,0,162,0,0,0,184,0,0,0,134,0,0,0,150,0,0,0,150,0,0,0,150,0,0,0,150,0,0,0,140,0,0,0,150,0,0,0,156,0,0,0,196,0,0,0,162,0,0,0,184,0,0,0,190,0,0,0,190,0,0,0,190,0,0,0,190,0,0,0,190,0,0,0,168,0,0,0,190,0,0,0,190,0,0,0,190,0,0,0,178,0,0,0,190,0,0,0,190,0,0,0,184,0,0,0,190,0,0,0,196,0,1,2,86,4,36,0,1,2,90,4,36,0,1,2,18,4,36,0,3,2,78,4,36,0,166,0,0,0,1,2,88,4,36,0,1,2,68,4,36,0,1,2,43,4,36,0,3,2,88,5,140,0,206,0,0,0,1,2,78,5,140,0,1,2,58,4,36,0,1,2,88,5,140,0,1,2,78,4,36,0,28,0,58,0,58,0,138,0,144,0,64,0,70,0,76,0,82,0,88,0,94,0,110,0,126,0,132,0,138,0,144,0,150,0,156,0,156,0,156,0,162,0,178,0,184,0,190,0,196,0,202,0,208,0,214,0,220,0,1,2,88,5,226,0,1,2,98,6,92,0,1,2,88,5,238,0,1,2,88,6,92,0,1,2,88,5,173,0,1,2,88,6,94,0,3,2,78,5,226,0,10,0,0,0,0,0,6,128,0,0,3,2,88,5,156,0,0,0,10,0,0,0,0,128,0,0,1,2,78,6,62,0,1,2,78,5,218,0,1,2,43,6,92,0,1,2,58,6,82,0,1,2,88,7,56,0,1,2,88,6,231,0,3,2,88,6,212,0,10,0,0,0,0,0,7,128,0,0,1,2,88,7,48,0,1,2,88,6,206,0,1,2,88,7,108,0,1,2,88,6,241,0,1,2,88,6,201,0,1,2,88,6,251,0,1,2,58,6,112,0,1,2,78,6,70,0,0,0,1,0,1,0,14,1,110,3,138,0,0,84,42,0,3,68,70,76,84,0,20,99,121,114,108,0,24,108,97,116,110,0,120,1,38,0,0,1,34,0,2,66,71,82,32,0,16,83,82,66,32,0,56,0,0,255,255,0,17,0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,12,0,13,0,14,0,16,0,17,0,18,0,19,0,20,0,21,0,15,0,0,255,255,0,17,0,0,0,1,0,2,0,3,0,4,0,5,0,11,0,12,0,13,0,14,0,16,0,17,0,18,0,19,0,20,0,21,0,15,0,194,0,5,67,65,84,32,0,34,77,79,76,32,0,74,78,76,68,32,0,114,80,76,75,32,0,154,82,79,77,32,0,194,0,0,255,255,0,17,0,0,0,1,0,2,0,3,0,4,0,5,0,7,0,12,0,13,0,14,0,16,0,17,0,18,0,19,0,20,0,21,0,15,0,0,255,255,0,17,0,0,0,1,0,2,0,3,0,4,0,5,0,8,0,12,0,13,0,14,0,16,0,17,0,18,0,19,0,20,0,21,0,15,0,0,255,255,0,17,0,0,0,1,0,2,0,3,0,4,0,5,0,9,0,12,0,13,0,14,0,16,0,17,0,18,0,19,0,20,0,21,0,15,0,0,255,255,0,17,0,0,0,1,0,2,0,3,0,4,0,5,0,10,0,12,0,13,0,14,0,16,0,17,0,18,0,19,0,20,0,21,0,15,0,0,255,255,0,16,0,0,0,1,0,2,0,3,0,4,0,5,0,12,0,13,0,14,0,16,0,17,0,18,0,19,0,20,0,21,0,15,0,22,97,97,108,116,0,134,99,97,108,116,0,142,99,97,115,101,1,158,99,99,109,112,1,164,100,110,111,109,1,172,102,114,97,99,1,178,108,111,99,108,1,188,108,111,99,108,1,194,108,111,99,108,1,200,108,111,99,108,1,206,108,111,99,108,1,212,108,111,99,108,1,218,110,117,109,114,1,224,111,114,100,110,1,230,114,99,108,116,1,238,114,118,114,110,1,244,115,105,110,102,1,248,115,115,48,50,1,254,115,115,49,57,2,4,115,117,98,115,2,10,115,117,112,115,2,16,122,101,114,111,2,22,0,0,0,2,0,0,0,1,0,0,0,134,0,2,0,6,0,10,0,13,0,16,0,21,0,24,0,28,0,31,0,34,0,38,0,41,0,44,0,47,0,51,0,54,0,57,0,60,0,63,0,66,0,69,0,72,0,75,0,78,0,82,0,85,0,88,0,91,0,94,0,98,0,101,0,104,0,106,0,108,0,111,0,113,0,115,0,118,0,120,0,123,0,125,0,128,0,131,0,134,0,137,0,141,0,143,0,145,0,149,0,151,0,154,0,158,0,162,0,165,0,169,0,172,0,176,0,179,0,181,0,184,0,186,0,188,0,190,0,192,0,195,0,197,0,199,0,202,0,204,0,206,0,208,0,210,0,212,0,214,0,216,0,218,0,221,0,223,0,225,0,227,0,229,0,232,0,234,0,236,0,239,0,241,0,243,0,246,0,248,0,250,0,252,0,254,1,1,1,3,1,5,1,7,1,9,1,11,1,13,1,15,1,17,1,19,1,22,1,24,1,26,1,28,1,30,1,32,1,34,1,36,1,39,1,41,1,43,1,45,1,48,1,50,1,52,1,55,1,57,1,59,1,62,1,64,1,66,1,68,1,71,1,74,1,76,1,78,1,80,1,83,1,86,1,88,1,90,1,93,0,0,0,1,1,124,0,0,0,2,1,96,1,100,0,0,0,1,1,115,0,0,0,3,1,116,1,117,1,118,0,0,0,1,1,109,0,0,0,1,1,106,0,0,0,1,1,103,0,0,0,1,1,105,0,0,0,1,1,104,0,0,0,1,1,110,0,0,0,1,1,114,0,0,0,2,1,121,1,123,0,0,0,1,1,128,0,0,0,0,0,0,0,1,1,112,0,0,0,1,1,125,0,0,0,1,1,127,0,0,0,1,1,111,0,0,0,1,1,113,0,0,0,1,1,126,1,130,3,6,4,180,7,44,7,190,44,56,44,56,7,208,8,98,44,56,44,56,8,116,9,30,50,254,9,50,9,220,56,112,9,250,10,140,64,108,64,108,64,108,10,154,11,10,40,150,11,28,11,180,42,214,42,214,11,194,12,50,44,56,12,68,12,200,44,56,12,218,13,96,48,120,48,120,13,110,13,244,48,120,14,6,14,118,72,242,14,144,15,46,50,254,15,64,15,222,50,254,50,254,15,236,16,138,50,254,16,156,17,58,50,254,17,76,17,234,54,72,17,252,18,154,60,248,18,172,19,74,50,254,19,92,19,250,50,254,20,12,20,170,52,186,20,196,21,52,54,72,21,70,21,182,54,72,21,200,22,116,54,72,54,72,22,130,22,242,54,72,23,4,23,116,54,72,23,134,23,246,54,72,24,8,24,120,56,112,24,138,24,250,56,112,56,112,25,8,25,120,60,248,25,138,25,250,40,150,26,12,26,124,26,154,26,226,27,0,27,132,44,56,27,150,28,6,28,36,28,108,28,138,29,16,50,254,29,34,29,168,29,198,30,76,60,248,30,94,30,206,30,236,31,92,56,112,31,110,31,222,60,248,31,240,32,96,60,248,32,114,32,226,60,248,32,244,33,160,60,248,60,248,33,174,33,246,34,20,34,132,34,162,35,18,64,108,64,108,35,32,35,144,35,174,36,30,67,118,36,56,36,168,67,118,67,118,36,182,37,38,68,180,68,180,37,52,37,164,50,254,37,182,38,38,72,242,72,242,38,52,38,164,73,96,38,190,39,46,39,60,39,60,39,80,39,162,39,176,39,196,40,28,40,54,40,136,40,150,40,164,40,252,41,22,41,104,41,130,41,212,41,238,42,64,42,82,42,200,42,214,42,228,43,54,43,80,43,198,43,216,44,42,44,56,44,70,44,170,44,196,45,40,45,66,45,148,45,174,46,0,46,26,46,126,46,144,46,250,47,20,47,120,47,146,47,234,48,4,48,106,48,120,48,134,48,236,49,6,49,126,49,144,49,246,50,8,50,90,50,116,50,240,50,254,51,12,51,136,51,154,52,22,52,48,52,172,52,186,52,200,53,26,53,52,53,152,53,178,54,58,54,72,54,86,54,168,54,186,55,12,55,38,55,138,55,164,55,246,56,16,56,98,56,112,56,126,56,208,56,226,57,52,57,78,57,160,57,186,58,18,58,44,58,126,58,152,58,234,59,4,59,106,59,132,59,214,59,240,60,66,60,92,60,234,60,248,61,6,61,88,61,114,61,196,61,222,62,54,62,80,62,168,62,194,63,20,63,46,63,128,63,154,63,242,64,12,64,94,64,108,64,122,64,204,64,230,65,56,65,82,65,170,65,196,66,22,66,36,66,56,66,138,66,164,66,252,67,22,67,104,67,118,67,132,67,214,67,232,68,58,68,84,68,166,68,180,68,200,69,50,69,76,69,176,69,202,70,34,70,60,70,142,70,156,70,176,71,2,71,16,71,36,71,154,71,180,72,12,72,38,72,120,72,146,72,228,72,242,73,0,73,82,73,96,73,116,73,204,73,230,74,68,74,94,74,182,74,196,74,216,75,176,75,206,75,226,76,170,76,142,76,170,77,0,79,242,79,242,77,68,77,102,77,164,77,210,78,10,78,42,78,74,78,176,78,196,78,196,78,210,79,2,78,224,78,238,79,2,79,16,79,78,79,78,79,102,79,174,79,208,79,242,80,58,80,78,80,78,80,98,80,122,0,1,0,0,0,1,0,8,0,2,0,212,0,103,1,140,0,189,0,190,1,141,0,191,0,192,0,140,0,147,0,193,1,140,1,133,1,131,1,134,1,141,1,135,1,136,1,82,1,89,1,138,1,137,1,206,1,207,1,208,2,34,2,16,2,17,2,18,2,19,2,20,2,21,2,22,2,23,2,24,2,25,2,26,2,27,2,28,2,29,2,30,2,31,2,32,2,33,2,127,2,128,2,129,2,130,2,131,2,132,2,133,2,134,2,135,2,136,2,252,4,207,6,82,4,111,4,112,4,113,4,114,4,115,4,116,4,117,4,118,4,119,4,120,4,121,4,122,4,123,4,124,4,125,4,126,4,127,4,128,4,129,4,130,4,131,4,132,4,133,4,134,4,135,4,136,4,137,4,138,4,139,4,140,4,141,4,142,5,13,2,246,6,60,6,61,6,62,6,64,6,65,6,66,6,67,6,68,6,69,6,70,6,71,6,72,6,77,6,80,0,1,0,103,0,1,0,29,0,95,0,101,0,102,0,136,0,138,0,146,0,185,0,195,0,223,0,230,1,36,1,43,1,44,1,78,1,80,1,88,1,117,1,128,1,149,1,160,1,170,1,210,1,211,1,212,1,215,1,219,1,220,1,221,1,222,1,223,1,224,1,226,1,230,1,233,1,239,1,240,1,241,1,243,1,244,1,255,2,137,2,138,2,139,2,140,2,141,2,142,2,143,2,144,2,145,2,146,2,184,2,186,3,81,3,106,3,107,3,108,3,109,3,110,3,111,3,112,3,113,3,114,3,115,3,116,3,117,3,118,3,119,3,120,3,121,3,122,3,123,3,124,3,125,3,126,3,127,3,128,3,129,3,130,3,131,3,132,3,133,3,134,3,135,3,136,3,137,4,155,5,14,6,27,6,28,6,29,6,31,6,32,6,33,6,34,6,35,6,36,6,37,6,38,6,40,6,76,6,79,0,3,0,0,0,1,0,8,0,1,2,36,0,36,0,78,0,84,0,96,0,106,0,116,0,126,0,136,0,146,0,156,0,166,0,176,0,186,0,198,0,214,0,220,0,228,0,238,0,252,1,8,1,24,1,30,1,38,1,44,1,50,1,56,1,82,1,92,1,98,1,108,1,158,1,222,1,244,2,0,2,6,2,12,2,30,0,2,1,139,6,82,0,5,2,116,2,117,2,127,2,137,2,147,0,4,2,118,2,128,2,138,2,148,0,4,2,119,2,129,2,139,2,149,0,4,2,120,2,130,2,140,2,150,0,4,2,121,2,131,2,141,2,151,0,4,2,122,2,132,2,142,2,152,0,4,2,123,2,133,2,143,2,153,0,4,2,124,2,134,2,144,2,154,0,4,2,125,2,135,2,145,2,155,0,4,2,126,2,136,2,146,2,156,0,5,2,230,2,231,2,245,2,248,6,82,0,7,2,236,2,237,2,249,3,4,4,230,4,241,6,82,0,2,2,243,6,82,0,3,2,244,3,5,6,82,0,4,2,234,2,250,3,6,6,82,0,6,2,224,2,253,2,254,3,13,4,243,6,82,0,5,2,228,3,7,3,8,3,9,6,82,0,7,2,157,2,242,3,0,3,17,3,18,5,10,6,82,0,2,3,19,6,82,0,3,3,1,3,12,6,82,0,2,3,2,6,82,0,2,3,3,6,82,0,2,4,208,6,82,0,12,2,215,2,216,2,229,4,206,4,228,4,234,4,237,4,238,4,242,5,4,5,12,6,82,0,4,3,11,3,20,3,21,6,82,0,2,4,249,6,82,0,4,4,216,4,217,4,251,6,82,0,24,2,235,2,238,2,239,2,246,2,247,2,251,3,10,3,14,3,15,4,211,4,213,4,219,4,220,4,221,4,222,4,227,4,231,4,235,4,253,4,254,5,5,5,14,5,18,6,82,0,31,2,217,2,219,2,220,2,240,2,255,3,16,4,210,4,212,4,214,4,215,4,218,4,223,4,224,4,225,4,229,4,232,4,233,4,236,4,239,4,244,4,248,4,250,4,252,4,255,5,0,5,2,5,8,5,11,5,15,5,17,6,82,0,10,2,221,2,222,2,233,2,241,4,226,4,240,5,1,5,3,5,6,6,82,0,5,2,223,5,7,5,9,5,16,6,82,0,2,5,19,6,82,0,2,4,205,6,82,0,8,2,218,2,225,2,227,4,209,4,245,4,246,4,247,6,82,0,2,6,63,6,73,0,1,0,36,1,112,2,106,2,107,2,108,2,109,2,110,2,111,2,112,2,113,2,114,2,115,2,165,2,167,2,168,2,170,2,172,2,176,2,178,2,181,2,182,2,183,2,185,2,187,2,188,2,193,2,200,3,34,3,67,3,71,3,73,3,74,3,79,3,93,4,156,4,167,6,30,0,6,0,0,0,6,0,18,0,38,0,58,0,80,0,102,0,124,0,3,0,1,50,206,0,1,50,206,0,3,50,206,50,206,67,200,0,0,0,3,0,0,0,1,50,186,0,4,50,186,50,186,67,180,67,180,0,0,0,3,0,3,67,56,67,56,67,56,0,1,67,160,0,0,0,1,0,0,0,3,0,3,0,2,67,34,67,34,0,1,50,144,0,1,67,138,0,1,0,0,0,3,0,3,0,1,67,12,0,1,50,122,0,2,50,122,67,116,0,1,0,0,0,4,0,3,0,0,0,1,50,100,0,3,50,100,50,100,67,94,0,1,0,0,0,5,0,1,0,0,0,1,0,8,0,2,38,76,0,2,4,210,6,82,0,6,0,0,0,6,0,18,0,38,0,58,0,80,0,102,0,124,0,3,0,1,67,24,0,1,67,24,0,3,50,42,50,42,50,42,0,0,0,3,0,0,0,1,67,4,0,4,50,22,50,22,50,22,50,22,0,0,0,3,0,3,66,148,66,148,66,148,0,1,50,2,0,0,0,1,0,0,0,7,0,3,0,2,66,126,66,126,0,1,49,236,0,1,49,236,0,1,0,0,0,8,0,3,0,1,66,104,0,1,49,214,0,2,49,214,49,214,0,1,0,0,0,9,0,3,0,0,0,1,66,174,0,3,49,192,49,192,49,192,0,1,0,0,0,7,0,1,0,0,0,1,0,8,0,2,49,186,0,2,6,82,4,247,0,6,0,0,0,7,0,20,0,40,0,60,0,82,0,104,0,126,0,148,0,3,0,1,66,114,0,1,66,114,0,3,63,126,63,126,66,126,0,0,0,3,0,0,0,1,66,94,0,4,63,106,63,106,66,106,66,106,0,0,0,3,0,2,61,250,65,22,0,1,66,74,0,3,63,86,63,86,66,86,0,0,0,3,0,3,65,216,65,216,65,216,0,1,66,64,0,0,0,1,0,0,0,11,0,3,0,2,65,194,65,194,0,1,63,42,0,1,66,42,0,1,0,0,0,11,0,3,0,1,65,172,0,1,63,20,0,2,63,20,66,20,0,1,0,0,0,12,0,3,0,0,0,1,65,242,0,3,62,254,62,254,65,254,0,1,0,0,0,11,0,1,0,0,0,1,0,8,0,2,20,150,0,3,6,82,4,255,6,82,0,6,0,0,0,7,0,20,0,40,0,60,0,82,0,104,0,126,0,148,0,3,0,1,65,180,0,1,65,180,0,3,54,166,57,176,57,176,0,0,0,3,0,0,0,1,65,160,0,4,54,146,57,156,57,156,57,156,0,0,0,3,0,2,61,60,64,88,0,1,65,140,0,3,54,126,57,136,57,136,0,0,0,3,0,3,65,26,65,26,65,26,0,1,57,114,0,0,0,1,0,0,0,14,0,3,0,2,65,4,65,4,0,1,57,92,0,1,57,92,0,1,0,0,0,15,0,3,0,1,64,238,0,1,54,60,0,2,57,70,57,70,0,1,0,0,0,14,0,3,0,0,0,1,65,52,0,3,54,38,57,48,57,48,0,1,0,0,0,14,0,1,0,0,0,1,0,8,0,2,0,12,0,3,6,82,4,242,6,82,0,1,0,3,2,170,2,193,3,74,0,6,0,0,0,6,0,18,0,38,0,58,0,80,0,102,0,124,0,3,0,1,55,152,0,1,55,152,0,3,55,152,55,152,55,152,0,0,0,3,0,0,0,1,55,132,0,4,55,132,55,132,55,132,55,132,0,0,0,3,0,3,64,106,64,106,64,106,0,1,55,112,0,0,0,1,0,0,0,17,0,3,0,2,64,84,64,84,0,1,55,90,0,1,55,90,0,1,0,0,0,18,0,3,0,1,64,62,0,1,55,68,0,2,55,68,55,68,0,1,0,0,0,19,0,3,0,0,0,1,55,46,0,3,55,46,55,46,55,46,0,1,0,0,0,20,0,1,0,0,0,1,0,8,0,1,55,16,0,87,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,64,86,0,1,64,86,0,2,64,86,64,92,0,0,0,3,0,0,0,1,64,68,0,3,64,68,64,74,64,74,0,0,0,3,0,2,63,208,63,208,0,1,64,56,0,0,0,1,0,0,0,22,0,3,0,1,63,188,0,1,64,30,0,1,64,36,0,1,0,0,0,22,0,3,0,0,0,1,64,10,0,2,64,10,64,16,0,1,0,0,0,23,0,1,0,0,0,1,0,8,0,2,30,212,0,2,5,17,6,82,0,6,0,0,0,7,0,20,0,38,0,56,0,74,0,92,0,112,0,132,0,3,0,1,63,8,0,1,63,8,0,2,63,8,63,8,0,0,0,3,0,0,0,1,62,246,0,3,62,246,62,246,62,246,0,0,0,3,0,1,67,168,0,1,62,228,0,2,62,228,62,228,0,0,0,3,0,0,0,1,62,210,0,3,62,210,62,210,67,150,0,0,0,3,0,2,63,38,63,38,0,1,62,192,0,0,0,1,0,0,0,25,0,3,0,1,63,18,0,1,62,172,0,1,62,172,0,1,0,0,0,26,0,3,0,0,0,1,62,152,0,2,62,152,62,152,0,1,0,0,0,27,0,1,0,0,0,1,0,8,0,1,62,124,0,78,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,46,58,0,1,46,58,0,2,46,58,60,52,0,0,0,3,0,0,0,1,46,40,0,3,46,40,60,34,60,34,0,0,0,3,0,2,62,168,62,168,0,1,60,16,0,0,0,1,0,0,0,29,0,3,0,1,62,148,0,1,46,2,0,1,59,252,0,1,0,0,0,29,0,3,0,0,0,1,45,238,0,2,45,238,59,232,0,1,0,0,0,30,0,1,0,0,0,1,0,8,0,2,33,108,0,2,4,211,6,82,0,6,0,0,0,6,0,18,0,36,0,54,0,72,0,92,0,112,0,3,0,1,45,182,0,1,45,182,0,2,45,182,62,176,0,0,0,3,0,0,0,1,45,164,0,3,45,164,62,158,62,158,0,0,0,3,0,1,62,128,0,1,45,146,0,2,45,146,62,140,0,0,0,3,0,2,62,18,62,18,0,1,62,122,0,0,0,1,0,0,0,32,0,3,0,1,61,254,0,1,45,108,0,1,62,102,0,1,0,0,0,32,0,3,0,0,0,1,45,88,0,2,45,88,62,82,0,1,0,0,0,33,0,1,0,0,0,1,0,8,0,2,33,66,0,2,4,212,6,82,0,6,0,0,0,6,0,18,0,36,0,54,0,74,0,94,0,114,0,3,0,1,56,64,0,1,56,64,0,2,56,64,56,64,0,0,0,3,0,0,0,1,56,46,0,3,56,46,56,46,56,46,0,0,0,3,0,2,57,154,60,182,0,1,56,28,0,2,56,28,56,28,0,0,0,3,0,2,61,122,61,122,0,1,56,8,0,0,0,1,0,0,0,35,0,3,0,1,61,102,0,1,55,244,0,1,55,244,0,1,0,0,0,36,0,3,0,0,0,1,55,224,0,2,55,224,55,224,0,1,0,0,0,37,0,1,0,0,0,1,0,8,0,1,55,196,0,70,0,6,0,0,0,6,0,18,0,36,0,54,0,74,0,94,0,114,0,3,0,1,55,172,0,1,55,172,0,2,55,172,58,134,0,0,0,3,0,0,0,1,55,154,0,3,55,154,58,116,58,116,0,0,0,3,0,2,57,6,60,34,0,1,55,136,0,2,55,136,58,98,0,0,0,3,0,2,60,230,60,230,0,1,58,78,0,0,0,1,0,0,0,39,0,3,0,1,60,210,0,1,55,96,0,1,58,58,0,1,0,0,0,39,0,3,0,0,0,1,55,76,0,2,55,76,58,38,0,1,0,0,0,40,0,1,0,0,0,1,0,8,0,2,35,2,0,2,6,82,2,238,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,55,22,0,1,55,22,0,2,64,230,64,230,0,0,0,3,0,0,0,1,55,4,0,3,64,212,64,212,64,212,0,0,0,3,0,2,60,100,60,100,0,1,64,194,0,0,0,1,0,0,0,42,0,3,0,1,60,80,0,1,64,174,0,1,64,174,0,1,0,0,0,43,0,3,0,0,0,1,54,202,0,2,64,154,64,154,0,1,0,0,0,42,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,2,242,0,1,0,2,2,167,2,181,0,6,0,0,0,7,0,20,0,38,0,56,0,76,0,98,0,118,0,138,0,3,0,1,57,98,0,1,57,98,0,2,54,136,57,98,0,0,0,3,0,0,0,1,57,80,0,3,54,118,57,80,57,80,0,0,0,3,0,2,55,226,58,254,0,1,57,62,0,2,54,100,57,62,0,0,0,3,0,3,60,30,55,206,58,234,0,1,57,42,0,2,54,80,57,42,0,0,0,3,0,2,59,172,59,172,0,1,57,20,0,0,0,1,0,0,0,45,0,3,0,1,59,152,0,1,54,38,0,1,57,0,0,1,0,0,0,45,0,3,0,0,0,1,56,236,0,2,54,18,56,236,0,1,0,0,0,46,0,1,0,0,0,1,0,8,0,2,33,200,0,2,6,82,4,219,0,6,0,0,0,7,0,20,0,38,0,56,0,76,0,98,0,118,0,138,0,3,0,1,56,178,0,1,56,178,0,2,56,178,56,178,0,0,0,3,0,0,0,1,56,160,0,3,56,160,56,160,56,160,0,0,0,3,0,2,55,50,58,78,0,1,56,142,0,2,56,142,56,142,0,0,0,3,0,3,59,110,55,30,58,58,0,1,56,122,0,2,56,122,56,122,0,0,0,3,0,2,58,252,58,252,0,1,56,100,0,0,0,1,0,0,0,48,0,3,0,1,58,232,0,1,56,80,0,1,56,80,0,1,0,0,0,49,0,3,0,0,0,1,56,60,0,2,56,60,56,60,0,1,0,0,0,50,0,1,0,0,0,1,0,8,0,1,56,32,1,151,0,6,0,0,0,7,0,20,0,38,0,56,0,76,0,98,0,118,0,138,0,3,0,1,56,6,0,1,56,6,0,2,56,6,59,6,0,0,0,3,0,0,0,1,55,244,0,3,55,244,58,244,58,244,0,0,0,3,0,2,54,134,57,162,0,1,55,226,0,2,55,226,58,226,0,0,0,3,0,3,58,194,54,114,57,142,0,1,55,206,0,2,55,206,58,206,0,0,0,3,0,2,58,80,58,80,0,1,58,184,0,0,0,1,0,0,0,52,0,3,0,1,58,60,0,1,55,164,0,1,58,164,0,1,0,0,0,52,0,3,0,0,0,1,55,144,0,2,55,144,58,144,0,1,0,0,0,53,0,1,0,0,0,1,0,8,0,2,37,24,0,2,6,82,4,223,0,6,0,0,0,7,0,20,0,38,0,56,0,76,0,98,0,118,0,138,0,3,0,1,55,86,0,1,55,86,0,2,47,60,55,86,0,0,0,3,0,0,0,1,55,68,0,3,47,42,55,68,55,68,0,0,0,3,0,2,53,214,56,242,0,1,55,50,0,2,47,24,55,50,0,0,0,3,0,3,58,18,53,194,56,222,0,1,55,30,0,2,47,4,55,30,0,0,0,3,0,2,57,160,57,160,0,1,55,8,0,0,0,1,0,0,0,55,0,3,0,1,57,140,0,1,46,218,0,1,54,244,0,1,0,0,0,55,0,3,0,0,0,1,54,224,0,2,46,198,54,224,0,1,0,0,0,56,0,1,0,0,0,1,0,8,0,2,34,230,0,2,6,82,4,220,0,6,0,0,0,7,0,20,0,38,0,56,0,76,0,98,0,118,0,138,0,3,0,1,54,166,0,1,54,166,0,2,57,166,57,166,0,0,0,3,0,0,0,1,54,148,0,3,57,148,57,148,57,148,0,0,0,3,0,2,53,38,56,66,0,1,54,130,0,2,57,130,57,130,0,0,0,3,0,3,57,98,53,18,56,46,0,1,54,110,0,2,57,110,57,110,0,0,0,3,0,2,56,240,56,240,0,1,57,88,0,0,0,1,0,0,0,58,0,3,0,1,56,220,0,1,57,68,0,1,57,68,0,1,0,0,0,59,0,3,0,0,0,1,54,48,0,2,57,48,57,48,0,1,0,0,0,58,0,1,0,0,0,1,0,8,0,2,35,184,0,2,6,82,4,225,0,6,0,0,0,7,0,20,0,38,0,56,0,76,0,98,0,118,0,138,0,3,0,1,53,246,0,1,53,246,0,2,56,234,56,234,0,0,0,3,0,0,0,1,53,228,0,3,56,216,56,216,56,216,0,0,0,3,0,2,52,118,55,146,0,1,53,210,0,2,56,198,56,198,0,0,0,3,0,3,56,178,52,98,55,126,0,1,53,190,0,2,56,178,56,178,0,0,0,3,0,2,56,64,56,64,0,1,56,156,0,0,0,1,0,0,0,61,0,3,0,1,56,44,0,1,56,136,0,1,56,136,0,1,0,0,0,62,0,3,0,0,0,1,53,128,0,2,56,116,56,116,0,1,0,0,0,61,0,1,0,0,0,1,0,8,0,2,40,218,0,2,6,82,4,226,0,6,0,0,0,7,0,20,0,38,0,56,0,76,0,98,0,118,0,138,0,3,0,1,53,70,0,1,53,70,0,2,60,60,53,70,0,0,0,3,0,0,0,1,53,52,0,3,60,42,53,52,53,52,0,0,0,3,0,2,51,198,54,226,0,1,53,34,0,2,60,24,53,34,0,0,0,3,0,3,56,2,51,178,54,206,0,1,53,14,0,2,60,4,53,14,0,0,0,3,0,2,55,144,55,144,0,1,52,248,0,0,0,1,0,0,0,64,0,3,0,1,55,124,0,1,59,218,0,1,52,228,0,1,0,0,0,64,0,3,0,0,0,1,52,208,0,2,59,198,52,208,0,1,0,0,0,65,0,1,0,0,0,1,0,8,0,2,52,204,0,2,6,82,4,227,0,6,0,0,0,7,0,20,0,38,0,56,0,76,0,98,0,118,0,138,0,3,0,1,44,124,0,1,44,124,0,2,52,150,52,150,0,0,0,3,0,0,0,1,44,106,0,3,52,132,52,132,52,132,0,0,0,3,0,2,51,22,54,50,0,1,44,88,0,2,52,114,52,114,0,0,0,3,0,3,55,82,51,2,54,30,0,1,44,68,0,2,52,94,52,94,0,0,0,3,0,2,54,224,54,224,0,1,52,72,0,0,0,1,0,0,0,67,0,3,0,1,54,204,0,1,52,52,0,1,52,52,0,1,0,0,0,68,0,3,0,0,0,1,44,6,0,2,52,32,52,32,0,1,0,0,0,67,0,1,0,0,0,1,0,8,0,2,32,38,0,2,6,82,2,247,0,6,0,0,0,7,0,20,0,38,0,56,0,76,0,98,0,118,0,138,0,3,0,1,43,204,0,1,43,204,0,2,43,204,49,252,0,0,0,3,0,0,0,1,43,186,0,3,43,186,49,234,49,234,0,0,0,3,0,2,50,102,53,130,0,1,43,168,0,2,43,168,49,216,0,0,0,3,0,3,54,162,50,82,53,110,0,1,43,148,0,2,43,148,49,196,0,0,0,3,0,2,54,48,54,48,0,1,49,174,0,0,0,1,0,0,0,70,0,3,0,1,54,28,0,1,43,106,0,1,49,154,0,1,0,0,0,70,0,3,0,0,0,1,43,86,0,2,43,86,49,134,0,1,0,0,0,71,0,1,0,0,0,1,0,8,0,2,0,10,0,2,2,245,6,82,0,1,0,2,2,165,2,170,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,54,50,0,1,54,50,0,2,51,50,54,50,0,0,0,3,0,0,0,1,54,32,0,3,51,32,54,32,54,32,0,0,0,3,0,2,53,166,53,166,0,1,54,14,0,0,0,1,0,0,0,73,0,3,0,1,53,146,0,1,50,250,0,1,53,250,0,1,0,0,0,73,0,3,0,0,0,1,53,230,0,2,50,230,53,230,0,1,0,0,0,74,0,1,0,0,0,1,0,8,0,2,32,110,0,2,6,82,4,232,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,53,176,0,1,53,176,0,2,53,176,50,176,0,0,0,3,0,0,0,1,53,158,0,3,53,158,50,158,50,158,0,0,0,3,0,2,53,36,53,36,0,1,50,140,0,0,0,1,0,0,0,76,0,3,0,1,53,16,0,1,53,120,0,1,50,120,0,1,0,0,0,76,0,3,0,0,0,1,53,100,0,2,53,100,50,100,0,1,0,0,0,77,0,1,0,0,0,1,0,8,0,2,31,236,0,2,4,235,6,82,0,6,0,0,0,8,0,22,0,40,0,58,0,76,0,94,0,112,0,132,0,152,0,3,0,1,53,40,0,1,53,40,0,2,53,40,53,40,0,0,0,3,0,0,0,1,53,22,0,3,53,22,53,22,53,22,0,0,0,3,0,1,52,54,0,1,53,4,0,2,53,4,53,4,0,0,0,3,0,1,46,174,0,1,52,242,0,2,52,242,52,242,0,0,0,3,0,1,38,154,0,1,52,224,0,2,52,224,52,224,0,0,0,3,0,2,52,102,52,102,0,1,52,206,0,0,0,1,0,0,0,79,0,3,0,1,52,82,0,1,52,186,0,1,52,186,0,1,0,0,0,80,0,3,0,0,0,1,52,166,0,2,52,166,52,166,0,1,0,0,0,81,0,1,0,0,0,1,0,8,0,1,52,138,1,163,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,52,116,0,1,52,116,0,2,52,116,44,100,0,0,0,3,0,0,0,1,52,98,0,3,52,98,44,82,44,82,0,0,0,3,0,2,51,232,51,232,0,1,44,64,0,0,0,1,0,0,0,83,0,3,0,1,51,212,0,1,52,60,0,1,44,44,0,1,0,0,0,83,0,3,0,0,0,1,52,40,0,2,52,40,44,24,0,1,0,0,0,84,0,1,0,0,0,1,0,8,0,2,33,14,0,2,4,234,6,82,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,51,242,0,1,51,242,0,2,43,226,51,242,0,0,0,3,0,0,0,1,51,224,0,3,43,208,51,224,51,224,0,0,0,3,0,2,51,102,51,102,0,1,51,206,0,0,0,1,0,0,0,86,0,3,0,1,51,82,0,1,43,170,0,1,51,186,0,1,0,0,0,86,0,3,0,0,0,1,51,166,0,2,43,150,51,166,0,1,0,0,0,87,0,1,0,0,0,1,0,8,0,2,32,140,0,2,6,82,4,229,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,43,96,0,1,43,96,0,2,51,112,51,112,0,0,0,3,0,0,0,1,43,78,0,3,51,94,51,94,51,94,0,0,0,3,0,2,50,228,50,228,0,1,51,76,0,0,0,1,0,0,0,89,0,3,0,1,50,208,0,1,51,56,0,1,51,56,0,1,0,0,0,90,0,3,0,0,0,1,43,20,0,2,51,36,51,36,0,1,0,0,0,89,0,1,0,0,0,1,0,8,0,2,32,10,0,2,6,82,2,220,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,42,222,0,1,42,222,0,2,42,222,50,238,0,0,0,3,0,0,0,1,42,204,0,3,42,204,50,220,50,220,0,0,0,3,0,2,50,98,50,98,0,1,50,202,0,0,0,1,0,0,0,92,0,3,0,1,50,78,0,1,42,166,0,1,50,182,0,1,0,0,0,92,0,3,0,0,0,1,42,146,0,2,42,146,50,162,0,1,0,0,0,93,0,1,0,0,0,1,0,8,0,2,31,136,0,2,6,82,2,217,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,42,92,0,1,42,92,0,2,42,92,42,92,0,0,0,3,0,0,0,1,42,74,0,3,42,74,42,74,42,74,0,0,0,3,0,2,49,224,49,224,0,1,42,56,0,0,0,1,0,0,0,95,0,3,0,1,49,204,0,1,42,36,0,1,42,36,0,1,0,0,0,96,0,3,0,0,0,1,42,16,0,2,42,16,42,16,0,1,0,0,0,97,0,1,0,0,0,1,0,8,0,1,41,244,0,23,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,41,222,0,1,41,222,0,2,49,226,49,226,0,0,0,3,0,0,0,1,41,204,0,3,49,208,49,208,49,208,0,0,0,3,0,2,49,98,49,98,0,1,49,190,0,0,0,1,0,0,0,99,0,3,0,1,49,78,0,1,49,170,0,1,49,170,0,1,0,0,0,100,0,3,0,0,0,1,41,146,0,2,49,150,49,150,0,1,0,0,0,99,0,1,0,0,0,1,0,8,0,2,34,212,0,2,6,82,2,222,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,49,96,0,1,49,96,0,2,49,102,49,102,0,0,0,3,0,0,0,1,49,78,0,3,49,84,49,84,49,84,0,0,0,3,0,2,48,224,48,224,0,1,49,66,0,0,0,1,0,0,0,102,0,3,0,1,48,204,0,1,49,46,0,1,49,46,0,1,0,0,0,103,0,3,0,0,0,1,49,20,0,2,49,26,49,26,0,1,0,0,0,102,0,1,0,0,0,1,0,8,0,2,31,68,0,2,6,82,5,9,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,48,222,0,1,48,222,0,2,48,228,48,234,0,0,0,3,0,0,0,1,48,204,0,3,48,210,48,216,48,216,0,0,0,3,0,2,48,94,48,94,0,1,48,198,0,0,0,1,0,0,0,105,0,3,0,1,48,74,0,1,48,172,0,1,48,178,0,1,0,0,0,105,0,3,0,0,0,1,48,146,0,2,48,152,48,158,0,1,0,0,0,105,0,1,0,0,0,1,0,8,0,2,0,12,0,3,5,8,6,82,6,82,0,1,0,3,3,73,3,74,3,79,0,6,0,0,0,3,0,12,0,32,0,52,0,3,0,2,47,248,47,248,0,1,48,96,0,0,0,1,0,0,0,107,0,3,0,1,47,228,0,1,47,126,0,1,48,76,0,1,0,0,0,107,0,3,0,0,0,1,48,44,0,2,47,106,48,56,0,1,0,0,0,107,0,1,0,0,0,1,0,8,0,2,0,12,0,3,6,82,4,244,6,82,0,1,0,3,2,176,3,73,3,74,0,6,0,0,0,6,0,18,0,36,0,54,0,72,0,92,0,112,0,3,0,1,47,232,0,1,47,232,0,2,30,250,30,250,0,0,0,3,0,0,0,1,47,214,0,3,30,232,30,232,30,232,0,0,0,3,0,0,0,1,47,196,0,3,30,214,30,214,47,208,0,0,0,3,0,2,47,86,47,86,0,1,30,196,0,0,0,1,0,0,0,109,0,3,0,1,47,66,0,1,30,176,0,1,30,176,0,1,0,0,0,110,0,3,0,0,0,1,47,138,0,2,30,156,30,156,0,1,0,0,0,109,0,1,0,0,0,1,0,8,0,2,30,152,0,2,6,82,4,246,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,47,84,0,1,47,84,0,2,30,102,47,96,0,0,0,3,0,0,0,1,47,66,0,3,30,84,47,78,47,78,0,0,0,3,0,2,46,212,46,212,0,1,47,60,0,0,0,1,0,0,0,112,0,3,0,1,46,192,0,1,30,46,0,1,47,40,0,1,0,0,0,112,0,3,0,0,0,1,47,8,0,2,30,26,47,20,0,1,0,0,0,112,0,1,0,0,0,1,0,8,0,2,0,12,0,3,4,248,6,82,6,82,0,1,0,3,3,73,3,74,4,167,0,6,0,0,0,3,0,12,0,32,0,52,0,3,0,2,46,110,46,110,0,1,46,214,0,0,0,1,0,0,0,114,0,3,0,1,46,90,0,1,32,124,0,1,46,194,0,1,0,0,0,114,0,3,0,0,0,1,46,162,0,2,32,104,46,174,0,1,0,0,0,114,0,1,0,0,0,1,0,8,0,2,0,12,0,3,6,82,4,250,6,82,0,1,0,3,3,34,3,73,3,74,0,6,0,0,0,6,0,18,0,36,0,54,0,74,0,94,0,114,0,3,0,1,46,94,0,1,46,94,0,2,43,106,43,106,0,0,0,3,0,0,0,1,46,76,0,3,43,88,43,88,43,88,0,0,0,3,0,2,41,234,45,6,0,1,46,58,0,2,43,70,43,70,0,0,0,3,0,2,45,202,45,202,0,1,43,50,0,0,0,1,0,0,0,116,0,3,0,1,45,182,0,1,43,30,0,1,43,30,0,1,0,0,0,117,0,3,0,0,0,1,45,254,0,2,43,10,43,10,0,1,0,0,0,116,0,1,0,0,0,1,0,8,0,2,30,100,0,2,4,254,6,82,0,6,0,0,0,6,0,18,0,36,0,54,0,74,0,94,0,114,0,3,0,1,45,198,0,1,45,198,0,2,42,210,45,210,0,0,0,3,0,0,0,1,45,180,0,3,42,192,45,192,45,192,0,0,0,3,0,2,41,82,44,110,0,1,45,162,0,2,42,174,45,174,0,0,0,3,0,2,45,50,45,50,0,1,45,154,0,0,0,1,0,0,0,119,0,3,0,1,45,30,0,1,42,134,0,1,45,134,0,1,0,0,0,119,0,3,0,0,0,1,45,102,0,2,42,114,45,114,0,1,0,0,0,119,0,1,0,0,0,1,0,8,0,2,0,12,0,3,6,82,5,0,6,82,0,1,0,3,3,71,3,73,3,74,0,6,0,0,0,6,0,18,0,36,0,54,0,74,0,94,0,114,0,3,0,1,45,34,0,1,45,34,0,2,42,46,45,34,0,0,0,3,0,0,0,1,45,16,0,3,42,28,45,16,45,16,0,0,0,3,0,2,40,174,43,202,0,1,44,254,0,2,42,10,44,254,0,0,0,3,0,2,44,142,44,142,0,1,44,234,0,0,0,1,0,0,0,121,0,3,0,1,44,122,0,1,41,226,0,1,44,214,0,1,0,0,0,121,0,3,0,0,0,1,44,194,0,2,41,206,44,194,0,1,0,0,0,122,0,1,0,0,0,1,0,8,0,2,29,40,0,2,6,82,5,1,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,44,140,0,1,44,140,0,2,36,136,44,152,0,0,0,3,0,0,0,1,44,122,0,3,36,118,44,134,44,134,0,0,0,3,0,2,44,12,44,12,0,1,44,116,0,0,0,1,0,0,0,124,0,3,0,1,43,248,0,1,36,80,0,1,44,96,0,1,0,0,0,124,0,3,0,0,0,1,44,64,0,2,36,60,44,76,0,1,0,0,0,124,0,1,0,0,0,1,0,8,0,2,0,12,0,3,6,82,4,239,6,82,0,1,0,3,2,193,3,73,3,74,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,43,254,0,1,43,254,0,2,35,250,35,250,0,0,0,3,0,0,0,1,43,236,0,3,35,232,35,232,35,232,0,0,0,3,0,2,43,126,43,126,0,1,35,214,0,0,0,1,0,0,0,126,0,3,0,1,43,106,0,1,35,194,0,1,35,194,0,1,0,0,0,127,0,3,0,0,0,1,43,178,0,2,35,174,35,174,0,1,0,0,0,126,0,1,0,0,0,1,0,8,0,2,28,240,0,2,4,238,6,82,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,43,124,0,1,43,124,0,2,35,120,43,124,0,0,0,3,0,0,0,1,43,106,0,3,35,102,43,106,43,106,0,0,0,3,0,2,42,252,42,252,0,1,43,88,0,0,0,1,0,0,0,129,0,3,0,1,42,232,0,1,35,64,0,1,43,68,0,1,0,0,0,129,0,3,0,0,0,1,43,48,0,2,35,44,43,48,0,1,0,0,0,130,0,1,0,0,0,1,0,8,0,2,28,110,0,2,6,82,4,240,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,42,250,0,1,42,250,0,2,42,250,40,6,0,0,0,3,0,0,0,1,42,232,0,3,42,232,39,244,39,244,0,0,0,3,0,2,42,122,42,122,0,1,39,226,0,0,0,1,0,0,0,132,0,3,0,1,42,102,0,1,42,194,0,1,39,206,0,1,0,0,0,132,0,3,0,0,0,1,42,174,0,2,42,174,39,186,0,1,0,0,0,133,0,1,0,0,0,1,0,8,0,2,27,20,0,2,5,5,6,82,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,42,120,0,1,42,120,0,2,42,120,34,116,0,0,0,3,0,0,0,1,42,102,0,3,42,102,34,98,34,98,0,0,0,3,0,2,41,248,41,248,0,1,34,80,0,0,0,1,0,0,0,135,0,3,0,1,41,228,0,1,42,64,0,1,34,60,0,1,0,0,0,135,0,3,0,0,0,1,42,44,0,2,42,44,34,40,0,1,0,0,0,136,0,1,0,0,0,1,0,8,0,2,27,106,0,2,5,4,6,82,0,6,0,0,0,8,0,22,0,40,0,58,0,76,0,94,0,112,0,132,0,152,0,3,0,1,41,240,0,1,41,240,0,2,41,240,41,240,0,0,0,3,0,0,0,1,41,222,0,3,41,222,41,222,41,222,0,0,0,3,0,0,0,1,41,204,0,3,41,204,41,204,41,10,0,0,0,3,0,0,0,1,41,186,0,3,41,186,41,186,35,130,0,0,0,3,0,0,0,1,41,168,0,3,41,168,41,168,27,110,0,0,0,3,0,2,41,58,41,58,0,1,41,150,0,0,0,1,0,0,0,138,0,3,0,1,41,38,0,1,41,130,0,1,41,130,0,1,0,0,0,139,0,3,0,0,0,1,41,110,0,2,41,110,41,110,0,1,0,0,0,140,0,1,0,0,0,1,0,8,0,1,41,82,1,188,0,6,0,0,0,3,0,12,0,32,0,52,0,3,0,2,40,228,40,228,0,1,41,76,0,0,0,1,0,0,0,142,0,3,0,1,40,208,0,1,34,244,0,1,41,56,0,1,0,0,0,142,0,3,0,0,0,1,41,24,0,2,34,224,41,36,0,1,0,0,0,142,0,1,0,0,0,1,0,8,0,2,0,12,0,3,6,82,4,252,6,82,0,1,0,3,3,67,3,73,3,74,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,40,214,0,1,40,214,0,2,44,216,40,226,0,0,0,3,0,0,0,1,40,196,0,3,44,198,40,208,40,208,0,0,0,3,0,2,40,86,40,86,0,1,40,190,0,0,0,1,0,0,0,144,0,3,0,1,40,66,0,1,44,160,0,1,40,170,0,1,0,0,0,144,0,3,0,0,0,1,40,138,0,2,44,140,40,150,0,1,0,0,0,144,0,1,0,0,0,1,0,8,0,2,0,12,0,3,6,82,5,11,6,82,0,1,0,3,2,181,3,73,3,74,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,30,242,0,1,30,242,0,2,30,242,30,242,0,0,0,3,0,0,0,1,30,224,0,3,30,224,30,224,30,224,0,0,0,3,0,2,39,200,39,200,0,1,30,206,0,0,0,1,0,0,0,146,0,3,0,1,39,180,0,1,30,186,0,1,30,186,0,1,0,0,0,147,0,3,0,0,0,1,30,166,0,2,30,166,30,166,0,1,0,0,0,148,0,1,0,0,0,1,0,8,0,1,30,138,0,86,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,30,116,0,1,30,116,0,2,38,62,38,150,0,0,0,3,0,0,0,1,30,98,0,3,38,44,38,132,38,132,0,0,0,3,0,2,39,74,39,74,0,1,38,114,0,0,0,1,0,0,0,150,0,3,0,1,39,54,0,1,38,6,0,1,38,94,0,1,0,0,0,150,0,3,0,0,0,1,30,40,0,2,37,242,38,74,0,1,0,0,0,150,0,1,0,0,0,1,0,8,0,2,0,12,0,3,6,82,3,12,6,82,0,1,0,3,2,178,2,183,2,200,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,34,94,0,1,34,94,0,2,34,94,39,60,0,0,0,3,0,0,0,1,34,76,0,3,34,76,39,42,39,42,0,0,0,3,0,2,38,188,38,188,0,1,39,24,0,0,0,1,0,0,0,152,0,3,0,1,38,168,0,1,34,38,0,1,39,4,0,1,0,0,0,152,0,3,0,0,0,1,34,18,0,2,34,18,38,240,0,1,0,0,0,153,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,2,233,0,1,0,2,2,165,3,74,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,33,212,0,1,33,212,0,2,33,212,33,212,0,0,0,3,0,0,0,1,33,194,0,3,33,194,33,194,33,194,0,0,0,3,0,2,38,50,38,50,0,1,33,176,0,0,0,1,0,0,0,155,0,3,0,1,38,30,0,1,33,156,0,1,33,156,0,1,0,0,0,156,0,3,0,0,0,1,33,136,0,2,33,136,33,136,0,1,0,0,0,157,0,1,0,0,0,1,0,8,0,1,33,108,0,66,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,31,252,0,1,31,252,0,2,31,252,31,252,0,0,0,3,0,0,0,1,31,234,0,3,31,234,31,234,31,234,0,0,0,3,0,2,37,180,37,180,0,1,31,216,0,0,0,1,0,0,0,159,0,3,0,1,37,160,0,1,31,196,0,1,31,196,0,1,0,0,0,160,0,3,0,0,0,1,31,176,0,2,31,176,31,176,0,1,0,0,0,161,0,1,0,0,0,1,0,8,0,1,31,148,1,150,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,41,184,0,1,41,184,0,2,34,194,34,194,0,0,0,3,0,0,0,1,41,166,0,3,34,176,34,176,34,176,0,0,0,3,0,2,37,54,37,54,0,1,34,158,0,0,0,1,0,0,0,163,0,3,0,1,37,34,0,1,34,138,0,1,34,138,0,1,0,0,0,164,0,3,0,0,0,1,41,108,0,2,34,118,34,118,0,1,0,0,0,163,0,1,0,0,0,1,0,8,0,2,34,114,0,2,6,82,3,15,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,41,54,0,1,41,54,0,2,41,54,41,54,0,0,0,3,0,0,0,1,41,36,0,3,41,36,41,36,41,36,0,0,0,3,0,2,36,180,36,180,0,1,41,18,0,0,0,1,0,0,0,166,0,3,0,1,36,160,0,1,40,254,0,1,40,254,0,1,0,0,0,167,0,3,0,0,0,1,40,234,0,2,40,234,40,234,0,1,0,0,0,168,0,1,0,0,0,1,0,8,0,1,40,206,0,93,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,35,42,0,1,35,42,0,2,19,200,35,42,0,0,0,3,0,0,0,1,35,24,0,3,19,182,35,24,35,24,0,0,0,3,0,2,36,54,36,54,0,1,35,6,0,0,0,1,0,0,0,170,0,3,0,1,36,34,0,1,19,144,0,1,34,242,0,1,0,0,0,170,0,3,0,0,0,1,34,222,0,2,19,124,34,222,0,1,0,0,0,171,0,1,0,0,0,1,0,8,0,2,0,10,0,2,3,20,6,82,0,1,0,2,2,200,4,167,0,6,0,0,0,5,0,16,0,34,0,52,0,72,0,92,0,3,0,1,0,124,0,1,0,124,0,2,0,124,0,124,0,0,0,3,0,0,0,1,0,106,0,3,0,106,0,106,0,106,0,0,0,3,0,2,35,172,35,172,0,1,0,88,0,0,0,1,0,0,0,173,0,3,0,1,35,152,0,1,0,68,0,1,0,68,0,1,0,0,0,174,0,3,0,0,0,1,0,48,0,2,0,48,0,48,0,1,0,0,0,175,0,1,0,0,0,1,0,8,0,1,0,20,0,27,0,1,0,0,0,1,0,8,0,1,0,6,4,226,0,1,0,1,1,112,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,0,96,0,1,0,96,0,1,0,96,0,0,0,3,0,0,0,1,0,80,0,2,0,80,0,80,0,0,0,3,0,1,35,32,0,1,0,64,0,0,0,1,0,0,0,177,0,3,0,0,0,1,0,46,0,1,0,46,0,1,0,0,0,178,0,1,0,0,0,1,0,8,0,1,0,20,0,49,0,1,0,0,0,1,0,8,0,1,0,6,1,182,0,1,0,1,4,156,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,0,68,0,1,0,68,0,1,32,52,0,0,0,3,0,0,0,1,0,52,0,2,32,36,32,36,0,0,0,3,0,1,34,172,0,1,32,20,0,0,0,1,0,0,0,180,0,3,0,0,0,1,0,18,0,1,32,2,0,1,0,0,0,180,0,1,0,1,3,81,0,1,0,0,0,1,0,8,0,2,0,10,0,2,5,18,6,82,0,1,0,2,3,71,3,81,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,34,188,0,1,34,188,0,1,34,188,0,0,0,3,0,0,0,1,34,172,0,2,34,172,34,172,0,0,0,3,0,1,34,58,0,1,34,156,0,0,0,1,0,0,0,182,0,3,0,0,0,1,34,138,0,1,34,138,0,1,0,0,0,183,0,1,0,0,0,1,0,8,0,1,34,112,1,193,0,1,0,0,0,1,0,8,0,1,34,98,3,3,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,34,78,0,1,34,78,0,1,0,68,0,0,0,3,0,0,0,1,34,62,0,2,0,52,0,52,0,0,0,3,0,1,33,204,0,1,0,36,0,0,0,1,0,0,0,185,0,3,0,0,0,1,34,28,0,1,0,18,0,1,0,0,0,185,0,1,0,1,4,155,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,5,13,0,1,0,2,3,79,4,155,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,33,220,0,1,33,220,0,1,30,226,0,0,0,3,0,0,0,1,33,204,0,2,30,210,30,210,0,0,0,3,0,1,33,90,0,1,30,194,0,0,0,1,0,0,0,187,0,3,0,0,0,1,33,170,0,1,30,176,0,1,0,0,0,187,0,1,0,0,0,1,0,8,0,2,0,10,0,2,5,14,6,82,0,1,0,2,3,71,3,79,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,33,112,0,1,33,112,0,1,33,118,0,0,0,3,0,0,0,1,33,96,0,2,33,102,33,102,0,0,0,3,0,1,32,238,0,1,33,86,0,0,0,1,0,0,0,189,0,3,0,0,0,1,33,62,0,1,33,68,0,1,0,0,0,189,0,1,0,0,0,1,0,8,0,2,0,10,0,2,5,15,6,82,0,1,0,2,3,73,3,79,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,33,4,0,1,33,4,0,1,24,250,0,0,0,3,0,0,0,1,32,244,0,2,24,234,24,234,0,0,0,3,0,1,32,130,0,1,24,218,0,0,0,1,0,0,0,191,0,3,0,0,0,1,32,210,0,1,24,200,0,1,0,0,0,191,0,1,0,0,0,1,0,8,0,2,12,214,0,2,5,12,6,82,0,6,0,0,0,6,0,18,0,34,0,50,0,66,0,82,0,100,0,3,0,1,31,212,0,1,31,212,0,1,31,212,0,0,0,3,0,0,0,1,31,196,0,2,31,196,31,196,0,0,0,3,0,1,36,120,0,1,31,180,0,1,31,180,0,0,0,3,0,0,0,1,31,164,0,2,31,164,36,104,0,0,0,3,0,1,31,250,0,1,31,148,0,0,0,1,0,0,0,193,0,3,0,0,0,1,31,130,0,1,31,130,0,1,0,0,0,194,0,1,0,0,0,1,0,8,0,1,31,104,0,77,0,1,0,0,0,1,0,8,0,1,31,90,3,162,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,31,70,0,1,31,70,0,1,32,20,0,0,0,3,0,0,0,1,31,54,0,2,32,4,32,4,0,0,0,3,0,1,31,140,0,1,31,244,0,0,0,1,0,0,0,196,0,3,0,0,0,1,31,20,0,1,31,226,0,1,0,0,0,196,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,2,255,0,1,0,2,2,176,3,73,0,6,0,0,0,6,0,18,0,34,0,50,0,66,0,82,0,100,0,3,0,1,30,214,0,1,30,214,0,1,35,154,0,0,0,3,0,0,0,1,30,198,0,2,35,138,35,138,0,0,0,3,0,1,35,122,0,1,30,182,0,1,35,122,0,0,0,3,0,0,0,1,30,166,0,2,35,106,30,166,0,0,0,3,0,1,30,252,0,1,35,90,0,0,0,1,0,0,0,198,0,3,0,0,0,1,30,132,0,1,35,72,0,1,0,0,0,198,0,1,0,0,0,1,0,8,0,2,27,222,0,2,6,82,3,0,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,14,38,0,1,14,38,0,1,14,38,0,0,0,3,0,0,0,1,14,22,0,2,14,22,14,22,0,0,0,3,0,1,30,152,0,1,14,6,0,0,0,1,0,0,0,200,0,3,0,0,0,1,13,244,0,1,13,244,0,1,0,0,0,201,0,1,0,0,0,1,0,8,0,1,13,218,0,42,0,1,0,0,0,1,0,8,0,1,13,204,1,171,0,6,0,0,0,5,0,16,0,32,0,48,0,64,0,82,0,3,0,1,13,182,0,1,13,182,0,1,2,122,0,0,0,3,0,0,0,1,13,166,0,2,2,106,2,106,0,0,0,3,0,1,17,186,0,1,13,150,0,1,2,90,0,0,0,3,0,1,30,24,0,1,2,74,0,0,0,1,0,0,0,203,0,3,0,0,0,1,13,116,0,1,2,56,0,1,0,0,0,203,0,1,0,0,0,1,0,8,0,2,0,10,0,2,4,207,6,82,0,1,0,2,2,186,4,167,0,6,0,0,0,5,0,16,0,32,0,48,0,64,0,82,0,3,0,1,13,56,0,1,13,56,0,1,3,16,0,0,0,3,0,0,0,1,13,40,0,2,3,0,3,0,0,0,0,3,0,1,17,174,0,1,13,24,0,1,2,240,0,0,0,3,0,1,29,154,0,1,2,224,0,0,0,1,0,0,0,205,0,3,0,0,0,1,12,246,0,1,2,206,0,1,0,0,0,205,0,1,0,0,0,1,0,8,0,2,0,10,0,2,4,208,6,82,0,1,0,2,2,188,4,167,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,12,188,0,1,12,188,0,1,26,182,0,0,0,3,0,0,0,1,12,172,0,2,26,166,26,166,0,0,0,3,0,1,29,46,0,1,26,150,0,0,0,1,0,0,0,207,0,3,0,0,0,1,12,138,0,1,26,132,0,1,0,0,0,207,0,1,0,0,0,1,0,8,0,2,0,10,0,2,4,213,6,82,0,1,0,2,3,71,4,167,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,12,80,0,1,12,80,0,1,29,74,0,0,0,3,0,0,0,1,12,64,0,2,29,58,29,58,0,0,0,3,0,1,28,194,0,1,29,42,0,0,0,1,0,0,0,209,0,3,0,0,0,1,12,30,0,1,29,24,0,1,0,0,0,209,0,1,0,0,0,1,0,8,0,2,0,10,0,2,4,214,6,82,0,1,0,2,3,73,4,167,0,6,0,0,0,5,0,16,0,32,0,48,0,64,0,82,0,3,0,1,11,226,0,1,11,226,0,1,20,204,0,0,0,3,0,0,0,1,11,210,0,2,20,188,20,188,0,0,0,3,0,0,0,1,11,194,0,2,20,172,11,194,0,0,0,3,0,1,28,68,0,1,20,156,0,0,0,1,0,0,0,211,0,3,0,0,0,1,11,160,0,1,20,138,0,1,0,0,0,211,0,1,0,0,0,1,0,8,0,2,9,22,0,2,4,206,6,82,0,6,0,0,0,5,0,16,0,32,0,48,0,70,0,88,0,3,0,1,15,144,0,1,15,144,0,1,11,108,0,0,0,3,0,0,0,1,15,128,0,2,11,92,11,92,0,0,0,3,0,0,0,1,15,112,0,2,11,76,0,16,0,0,0,1,0,1,2,186,0,3,0,1,27,200,0,1,11,54,0,0,0,1,0,0,0,213,0,3,0,0,0,1,15,72,0,1,11,36,0,1,0,0,0,213,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,2,225,0,1,0,2,2,185,4,167,0,6,0,0,0,5,0,16,0,32,0,48,0,64,0,82,0,3,0,1,15,126,0,1,15,126,0,1,10,232,0,0,0,3,0,0,0,1,15,110,0,2,10,216,10,216,0,0,0,3,0,0,0,1,15,94,0,2,10,200,0,160,0,0,0,3,0,1,27,74,0,1,10,184,0,0,0,1,0,0,0,215,0,3,0,0,0,1,15,60,0,1,10,166,0,1,0,0,0,215,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,2,227,0,1,0,2,2,187,4,167,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,0,68,0,1,0,68,0,1,18,4,0,0,0,3,0,0,0,1,0,52,0,2,17,244,17,244,0,0,0,3,0,1,26,222,0,1,17,228,0,0,0,1,0,0,0,217,0,3,0,0,0,1,0,18,0,1,17,210,0,1,0,0,0,217,0,1,0,1,2,188,0,1,0,0,0,1,0,8,0,2,0,10,0,2,2,228,6,82,0,1,0,2,2,178,2,188,0,6,0,0,0,5,0,16,0,32,0,48,0,66,0,84,0,3,0,1,21,24,0,1,21,24,0,1,21,24,0,0,0,3,0,0,0,1,21,8,0,2,21,8,21,8,0,0,0,3,0,2,22,118,25,146,0,1,20,248,0,1,20,248,0,0,0,3,0,1,26,88,0,1,20,230,0,0,0,1,0,0,0,219,0,3,0,0,0,1,20,212,0,1,20,212,0,1,0,0,0,220,0,1,0,0,0,1,0,8,0,1,20,186,0,69,0,1,0,0,0,1,0,8,0,1,20,172,3,171,0,6,0,0,0,5,0,16,0,32,0,48,0,66,0,84,0,3,0,1,20,150,0,1,20,150,0,1,23,112,0,0,0,3,0,0,0,1,20,134,0,2,23,96,23,96,0,0,0,3,0,2,21,244,25,16,0,1,20,118,0,1,23,80,0,0,0,3,0,1,25,214,0,1,23,62,0,0,0,1,0,0,0,222,0,3,0,0,0,1,20,82,0,1,23,44,0,1,0,0,0,222,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,2,239,0,1,0,2,2,167,3,71,0,6,0,0,0,6,0,18,0,34,0,50,0,68,0,84,0,102,0,3,0,1,20,20,0,1,20,20,0,1,25,238,0,0,0,3,0,0,0,1,20,4,0,2,25,222,25,222,0,0,0,3,0,2,21,114,24,142,0,1,19,244,0,1,25,206,0,0,0,3,0,0,0,1,19,226,0,2,25,188,22,188,0,0,0,3,0,1,25,68,0,1,25,172,0,0,0,1,0,0,0,224,0,3,0,0,0,1,19,192,0,1,25,154,0,1,0,0,0,224,0,1,0,0,0,1,0,8,0,2,3,166,0,2,6,82,2,240,0,6,0,0,0,5,0,16,0,32,0,48,0,66,0,84,0,3,0,1,19,140,0,1,19,140,0,1,25,90,0,0,0,3,0,0,0,1,19,124,0,2,25,74,25,74,0,0,0,3,0,2,20,234,24,6,0,1,19,108,0,1,25,58,0,0,0,3,0,1,24,204,0,1,25,40,0,0,0,1,0,0,0,226,0,3,0,0,0,1,19,72,0,1,25,22,0,1,0,0,0,226,0,1,0,0,0,1,0,8,0,2,8,146,0,2,6,82,2,241,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,10,170,0,1,10,170,0,1,24,240,0,0,0,3,0,0,0,1,10,154,0,2,24,224,24,224,0,0,0,3,0,1,24,104,0,1,24,208,0,0,0,1,0,0,0,228,0,3,0,0,0,1,10,120,0,1,24,190,0,1,0,0,0,228,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,4,215,0,1,0,2,3,34,3,73,0,6,0,0,0,6,0,18,0,34,0,50,0,68,0,88,0,106,0,3,0,1,21,128,0,1,21,128,0,1,21,128,0,0,0,3,0,0,0,1,21,112,0,2,21,112,21,112,0,0,0,3,0,2,20,4,23,32,0,1,21,96,0,1,21,96,0,0,0,3,0,3,24,66,19,242,23,14,0,1,21,78,0,1,21,78,0,0,0,3,0,1,23,210,0,1,21,58,0,0,0,1,0,0,0,230,0,3,0,0,0,1,21,40,0,1,21,40,0,1,0,0,0,231,0,1,0,0,0,1,0,8,0,1,21,14,1,150,0,1,0,0,0,1,0,8,0,1,21,0,3,11,0,6,0,0,0,6,0,18,0,34,0,50,0,68,0,88,0,106,0,3,0,1,20,232,0,1,20,232,0,1,23,232,0,0,0,3,0,0,0,1,20,216,0,2,23,216,23,216,0,0,0,3,0,2,19,108,22,136,0,1,20,200,0,1,23,200,0,0,0,3,0,3,23,170,19,90,22,118,0,1,20,182,0,1,23,182,0,0,0,3,0,1,23,58,0,1,23,162,0,0,0,1,0,0,0,233,0,3,0,0,0,1,20,144,0,1,23,144,0,1,0,0,0,233,0,1,0,0,0,1,0,8,0,2,2,26,0,2,6,82,4,224,0,6,0,0,0,6,0,18,0,34,0,50,0,68,0,88,0,106,0,3,0,1,12,64,0,1,12,64,0,1,20,90,0,0,0,3,0,0,0,1,12,48,0,2,20,74,20,74,0,0,0,3,0,2,18,222,21,250,0,1,12,32,0,1,20,58,0,0,0,3,0,3,23,28,18,204,21,232,0,1,12,14,0,1,20,40,0,0,0,3,0,1,22,172,0,1,20,20,0,0,0,1,0,0,0,235,0,3,0,0,0,1,11,232,0,1,20,2,0,1,0,0,0,235,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,2,246,0,1,0,2,2,170,3,71,0,6,0,0,0,6,0,18,0,34,0,50,0,68,0,88,0,106,0,3,0,1,11,170,0,1,11,170,0,1,11,170,0,0,0,3,0,0,0,1,11,154,0,2,11,154,11,154,0,0,0,3,0,2,18,72,21,100,0,1,11,138,0,1,11,138,0,0,0,3,0,3,22,134,18,54,21,82,0,1,11,120,0,1,11,120,0,0,0,3,0,1,22,22,0,1,11,100,0,0,0,1,0,0,0,237,0,3,0,0,0,1,11,82,0,1,11,82,0,1,0,0,0,238,0,1,0,0,0,1,0,8,0,1,11,56,0,74,0,1,0,0,0,1,0,8,0,1,11,42,3,168,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,22,48,0,1,22,48,0,1,16,86,0,0,0,3,0,0,0,1,22,32,0,2,16,70,16,70,0,0,0,3,0,1,21,168,0,1,16,54,0,0,0,1,0,0,0,240,0,3,0,0,0,1,21,254,0,1,16,36,0,1,0,0,0,240,0,1,0,0,0,1,0,8,0,2,0,10,0,2,4,230,6,82,0,1,0,2,2,167,3,73,0,6,0,0,0,5,0,16,0,32,0,48,0,64,0,82,0,3,0,1,21,194,0,1,21,194,0,1,18,194,0,0,0,3,0,0,0,1,21,178,0,2,18,178,18,178,0,0,0,3,0,0,0,1,21,162,0,2,18,162,21,150,0,0,0,3,0,1,21,42,0,1,18,146,0,0,0,1,0,0,0,242,0,3,0,0,0,1,21,128,0,1,18,128,0,1,0,0,0,242,0,1,0,0,0,1,0,8,0,2,0,10,0,2,4,231,6,82,0,1,0,2,3,71,3,73,0,6,0,0,0,7,0,20,0,36,0,52,0,68,0,84,0,100,0,118,0,3,0,1,21,64,0,1,21,64,0,1,21,64,0,0,0,3,0,0,0,1,21,48,0,2,21,48,21,48,0,0,0,3,0,1,20,82,0,1,21,32,0,1,21,32,0,0,0,3,0,1,14,204,0,1,21,16,0,1,21,16,0,0,0,3,0,1,6,186,0,1,21,0,0,1,21,0,0,0,0,3,0,1,20,136,0,1,20,240,0,0,0,1,0,0,0,244,0,3,0,0,0,1,20,222,0,1,20,222,0,1,0,0,0,245,0,1,0,0,0,1,0,8,0,1,20,196,1,160,0,1,0,0,0,1,0,8,0,1,20,182,3,9,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,20,162,0,1,20,162,0,1,12,146,0,0,0,3,0,0,0,1,20,146,0,2,12,130,12,130,0,0,0,3,0,1,20,26,0,1,12,114,0,0,0,1,0,0,0,247,0,3,0,0,0,1,20,112,0,1,12,96,0,1,0,0,0,247,0,1,0,0,0,1,0,8,0,2,1,88,0,2,4,228,6,82,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,12,46,0,1,12,46,0,1,20,56,0,0,0,3,0,0,0,1,12,30,0,2,20,40,20,40,0,0,0,3,0,1,19,182,0,1,20,24,0,0,0,1,0,0,0,249,0,3,0,0,0,1,11,252,0,1,20,6,0,1,0,0,0,249,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,2,223,0,1,0,2,2,193,3,79,0,6,0,0,0,5,0,16,0,32,0,48,0,64,0,82,0,3,0,1,11,192,0,1,11,192,0,1,2,214,0,0,0,3,0,0,0,1,11,176,0,2,2,198,2,198,0,0,0,3,0,1,2,182,0,1,11,160,0,1,2,182,0,0,0,3,0,1,19,56,0,1,2,166,0,0,0,1,0,0,0,251,0,3,0,0,0,1,11,126,0,1,2,148,0,1,0,0,0,251,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,2,218,0,1,0,2,2,193,4,167,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,11,68,0,1,11,68,0,1,19,84,0,0,0,3,0,0,0,1,11,52,0,2,19,68,19,68,0,0,0,3,0,1,18,204,0,1,19,52,0,0,0,1,0,0,0,253,0,3,0,0,0,1,11,18,0,1,19,34,0,1,0,0,0,253,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,2,219,0,1,0,2,2,193,3,73,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,10,216,0,1,10,216,0,1,10,216,0,0,0,3,0,0,0,1,10,200,0,2,10,200,10,200,0,0,0,3,0,1,18,96,0,1,10,184,0,0,0,1,0,0,0,255,0,3,0,0,0,1,10,166,0,1,10,166,0,1,0,0,1,0,0,1,0,0,0,1,0,8,0,1,10,140,0,22,0,1,0,0,0,1,0,8,0,1,10,126,3,145,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,10,106,0,1,10,106,0,1,18,110,0,0,0,3,0,0,0,1,10,90,0,2,18,94,18,94,0,0,0,3,0,1,17,242,0,1,18,78,0,0,0,1,0,0,1,2,0,3,0,0,0,1,10,56,0,1,18,60,0,1,0,0,1,2,0,1,0,0,0,1,0,8,0,2,3,124,0,2,6,82,2,221,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,18,10,0,1,18,10,0,1,18,16,0,0,0,3,0,0,0,1,17,250,0,2,18,0,18,0,0,0,0,3,0,1,17,142,0,1,17,240,0,0,0,1,0,0,1,4,0,3,0,0,0,1,17,216,0,1,17,222,0,1,0,0,1,4,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,5,7,0,1,0,2,3,74,3,79,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,17,158,0,1,17,158,0,1,16,220,0,0,0,3,0,0,0,1,17,142,0,2,16,204,16,204,0,0,0,3,0,1,17,34,0,1,16,188,0,0,0,1,0,0,1,6,0,3,0,0,0,1,17,108,0,1,16,170,0,1,0,0,1,6,0,1,0,0,0,1,0,8,0,2,0,10,0,2,4,243,6,82,0,1,0,2,2,176,3,74,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,17,50,0,1,17,50,0,1,0,68,0,0,0,3,0,0,0,1,17,34,0,2,0,52,0,52,0,0,0,3,0,1,16,182,0,1,0,36,0,0,0,1,0,0,1,8,0,3,0,0,0,1,17,0,0,1,0,18,0,1,0,0,1,8,0,1,0,1,4,167,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,4,245,0,1,0,2,3,74,4,167,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,16,192,0,1,16,192,0,1,10,242,0,0,0,3,0,0,0,1,16,176,0,2,10,226,10,226,0,0,0,3,0,1,16,68,0,1,10,210,0,0,0,1,0,0,1,10,0,3,0,0,0,1,16,142,0,1,10,192,0,1,0,0,1,10,0,1,0,0,0,1,0,8,0,2,0,10,0,2,4,241,6,82,0,1,0,2,2,167,3,74,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,16,84,0,1,16,84,0,1,2,26,0,0,0,3,0,0,0,1,16,68,0,2,2,10,2,10,0,0,0,3,0,1,15,216,0,1,1,250,0,0,0,1,0,0,1,12,0,3,0,0,0,1,16,34,0,1,1,232,0,1,0,0,1,12,0,1,0,0,0,1,0,8,0,2,0,10,0,2,4,249,6,82,0,1,0,2,3,34,3,74,0,6,0,0,0,5,0,16,0,32,0,48,0,66,0,84,0,3,0,1,15,230,0,1,15,230,0,1,12,242,0,0,0,3,0,0,0,1,15,214,0,2,12,226,12,226,0,0,0,3,0,2,11,118,14,146,0,1,15,198,0,1,12,210,0,0,0,3,0,1,15,88,0,1,12,192,0,0,0,1,0,0,1,14,0,3,0,0,0,1,15,162,0,1,12,174,0,1,0,0,1,14,0,1,0,0,0,1,0,8,0,2,0,10,0,2,4,253,6,82,0,1,0,2,3,71,3,74,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,15,104,0,1,15,104,0,1,15,116,0,0,0,3,0,0,0,1,15,88,0,2,15,100,15,100,0,0,0,3,0,1,14,236,0,1,15,84,0,0,0,1,0,0,1,16,0,3,0,0,0,1,15,54,0,1,15,66,0,1,0,0,1,16,0,1,0,0,0,1,0,8,0,2,0,10,0,2,5,2,6,82,0,1,0,2,3,73,3,74,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,14,252,0,1,14,252,0,1,6,248,0,0,0,3,0,0,0,1,14,236,0,2,6,232,6,232,0,0,0,3,0,1,14,128,0,1,6,216,0,0,0,1,0,0,1,18,0,3,0,0,0,1,14,202,0,1,6,198,0,1,0,0,1,18,0,1,0,0,0,1,0,8,0,2,0,10,0,2,4,237,6,82,0,1,0,2,2,193,3,74,0,6,0,0,0,7,0,20,0,36,0,52,0,68,0,84,0,106,0,124,0,3,0,1,14,138,0,1,14,138,0,1,14,138,0,0,0,3,0,0,0,1,14,122,0,2,14,122,14,122,0,0,0,3,0,0,0,1,14,106,0,2,14,106,13,168,0,0,0,3,0,0,0,1,14,90,0,2,14,90,8,34,0,0,0,3,0,0,0,1,14,74,0,2,14,74,0,16,0,0,0,1,0,1,3,34,0,3,0,1,13,216,0,1,14,52,0,0,0,1,0,0,1,20,0,3,0,0,0,1,14,34,0,1,14,34,0,1,0,0,1,21,0,1,0,0,0,1,0,8,0,1,14,8,1,185,0,1,0,0,0,1,0,8,0,1,13,250,3,8,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,13,230,0,1,13,230,0,1,7,174,0,0,0,3,0,0,0,1,13,214,0,2,7,158,7,158,0,0,0,3,0,1,13,106,0,1,7,142,0,0,0,1,0,0,1,23,0,3,0,0,0,1,13,180,0,1,7,124,0,1,0,0,1,23,0,1,0,0,0,1,0,8,0,2,0,10,0,2,4,251,6,82,0,1,0,2,3,67,3,74,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,13,122,0,1,13,122,0,1,17,124,0,0,0,3,0,0,0,1,13,106,0,2,17,108,17,108,0,0,0,3,0,1,12,254,0,1,17,92,0,0,0,1,0,0,1,25,0,3,0,0,0,1,13,72,0,1,17,74,0,1,0,0,1,25,0,1,0,0,0,1,0,8,0,2,0,10,0,2,5,10,6,82,0,1,0,2,2,181,3,74,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,3,184,0,1,3,184,0,1,0,68,0,0,0,3,0,0,0,1,3,168,0,2,0,52,0,52,0,0,0,3,0,1,12,146,0,1,0,36,0,0,0,1,0,0,1,27,0,3,0,0,0,1,3,134,0,1,0,18,0,1,0,0,1,27,0,1,0,1,2,185,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,3,2,0,1,0,2,2,178,2,185,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,3,70,0,1,3,70,0,1,0,68,0,0,0,3,0,0,0,1,3,54,0,2,0,52,0,52,0,0,0,3,0,1,12,32,0,1,0,36,0,0,0,1,0,0,1,29,0,3,0,0,0,1,3,20,0,1,0,18,0,1,0,0,1,29,0,1,0,1,2,187,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,3,3,0,1,0,2,2,178,2,187,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,2,212,0,1,2,212,0,1,6,92,0,0,0,3,0,0,0,1,2,196,0,2,6,76,6,76,0,0,0,3,0,1,11,174,0,1,6,60,0,0,0,1,0,0,1,31,0,3,0,0,0,1,2,162,0,1,6,42,0,1,0,0,1,31,0,1,0,0,0,1,0,8,0,2,0,10,0,2,3,4,6,82,0,1,0,2,2,167,2,178,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,2,104,0,1,2,104,0,1,8,202,0,0,0,3,0,0,0,1,2,88,0,2,8,186,8,186,0,0,0,3,0,1,11,66,0,1,8,170,0,0,0,1,0,0,1,33,0,3,0,0,0,1,2,54,0,1,8,152,0,1,0,0,1,33,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,3,10,0,1,0,2,2,178,3,71,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,1,252,0,1,1,252,0,1,0,68,0,0,0,3,0,0,0,1,1,236,0,2,0,52,0,52,0,0,0,3,0,1,10,214,0,1,0,36,0,0,0,1,0,0,1,35,0,3,0,0,0,1,1,202,0,1,0,18,0,1,0,0,1,35,0,1,0,1,2,170,0,1,0,0,0,1,0,8,0,2,0,10,0,2,3,5,6,82,0,1,0,2,2,170,2,178,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,1,138,0,1,1,138,0,1,1,138,0,0,0,3,0,0,0,1,1,122,0,2,1,122,1,122,0,0,0,3,0,1,10,100,0,1,1,106,0,0,0,1,0,0,1,37,0,3,0,0,0,1,1,88,0,1,1,88,0,1,0,0,1,38,0,1,0,0,0,1,0,8,0,1,1,62,0,85,0,1,0,0,0,1,0,8,0,1,1,48,3,160,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,1,28,0,1,1,28,0,1,9,62,0,0,0,3,0,0,0,1,1,12,0,2,9,46,9,46,0,0,0,3,0,1,9,246,0,1,9,30,0,0,0,1,0,0,1,40,0,3,0,0,0,1,0,234,0,1,9,12,0,1,0,0,1,40,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,3,1,0,1,0,2,2,178,2,183,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,0,176,0,1,0,176,0,1,5,182,0,0,0,3,0,0,0,1,0,160,0,2,5,166,5,166,0,0,0,3,0,1,9,138,0,1,5,150,0,0,0,1,0,0,1,42,0,3,0,0,0,1,0,126,0,1,5,132,0,1,0,0,1,42,0,1,0,0,0,1,0,8,0,2,0,10,0,2,3,6,6,82,0,1,0,2,2,172,2,178,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,0,68,0,1,0,68,0,1,8,14,0,0,0,3,0,0,0,1,0,52,0,2,7,254,7,254,0,0,0,3,0,1,9,30,0,1,7,238,0,0,0,1,0,0,1,44,0,3,0,0,0,1,0,18,0,1,7,220,0,1,0,0,1,44,0,1,0,1,2,178,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,3,11,0,1,0,2,2,178,2,200,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,0,96,0,1,0,96,0,1,0,96,0,0,0,3,0,0,0,1,0,80,0,2,0,80,0,80,0,0,0,3,0,1,8,172,0,1,0,64,0,0,0,1,0,0,1,46,0,3,0,0,0,1,0,46,0,1,0,46,0,1,0,0,1,47,0,1,0,0,0,1,0,8,0,1,0,20,1,182,0,1,0,0,0,1,0,8,0,1,0,6,2,245,0,1,0,1,3,93,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,3,214,0,1,3,214,0,1,5,192,0,0,0,3,0,0,0,1,3,198,0,2,5,176,5,176,0,0,0,3,0,1,8,56,0,1,5,160,0,0,0,1,0,0,1,49,0,3,0,0,0,1,3,164,0,1,5,142,0,1,0,0,1,49,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,2,235,0,1,0,2,2,165,3,71,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,3,106,0,1,3,106,0,1,0,68,0,0,0,3,0,0,0,1,3,90,0,2,0,52,0,52,0,0,0,3,0,1,7,204,0,1,0,36,0,0,0,1,0,0,1,51,0,3,0,0,0,1,3,56,0,1,0,18,0,1,0,0,1,51,0,1,0,1,2,193,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,2,229,0,1,0,2,2,165,2,193,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,2,248,0,1,2,248,0,1,2,248,0,0,0,3,0,0,0,1,2,232,0,2,2,232,2,232,0,0,0,3,0,1,7,90,0,1,2,216,0,0,0,1,0,0,1,53,0,3,0,0,0,1,2,198,0,1,2,198,0,1,0,0,1,54,0,1,0,0,0,1,0,8,0,1,2,172,0,65,0,1,0,0,0,1,0,8,0,1,2,158,3,173,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,2,138,0,1,2,138,0,1,3,24,0,0,0,3,0,0,0,1,2,122,0,2,3,8,3,8,0,0,0,3,0,1,6,236,0,1,2,248,0,0,0,1,0,0,1,56,0,3,0,0,0,1,2,88,0,1,2,230,0,1,0,0,1,56,0,1,0,0,0,1,0,8,0,2,2,86,0,2,6,82,2,234,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,0,204,0,1,0,204,0,1,7,16,0,0,0,3,0,0,0,1,0,188,0,2,7,0,7,0,0,0,0,3,0,1,6,136,0,1,6,240,0,0,0,1,0,0,1,58,0,3,0,0,0,1,0,154,0,1,6,222,0,1,0,0,1,58,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,4,218,0,1,0,2,3,67,3,73,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,0,96,0,1,0,96,0,1,0,96,0,0,0,3,0,0,0,1,0,80,0,2,0,80,0,80,0,0,0,3,0,1,6,28,0,1,0,64,0,0,0,1,0,0,1,60,0,3,0,0,0,1,0,46,0,1,0,46,0,1,0,0,1,61,0,1,0,0,0,1,0,8,0,1,0,20,1,149,0,1,0,0,0,1,0,8,0,1,0,6,3,15,0,1,0,1,3,67,0,6,0,0,0,5,0,16,0,32,0,48,0,64,0,82,0,3,0,1,1,210,0,1,1,210,0,1,0,84,0,0,0,3,0,0,0,1,1,194,0,2,0,68,0,68,0,0,0,3,0,1,4,206,0,1,1,178,0,1,0,52,0,0,0,3,0,1,5,150,0,1,0,36,0,0,0,1,0,0,1,63,0,3,0,0,0,1,1,144,0,1,0,18,0,1,0,0,1,63,0,1,0,1,2,167,0,1,0,0,0,1,0,8,0,2,0,10,0,2,2,249,6,82,0,1,0,2,2,167,2,172,0,6,0,0,0,5,0,16,0,32,0,48,0,64,0,82,0,3,0,1,1,78,0,1,1,78,0,1,2,170,0,0,0,3,0,0,0,1,1,62,0,2,2,154,2,154,0,0,0,3,0,1,4,74,0,1,1,46,0,1,2,138,0,0,0,3,0,1,5,18,0,1,2,122,0,0,0,1,0,0,1,65,0,3,0,0,0,1,1,12,0,1,2,104,0,1,0,0,1,65,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,2,251,0,1,0,2,2,172,3,71,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,0,210,0,1,0,210,0,1,0,68,0,0,0,3,0,0,0,1,0,194,0,2,0,52,0,52,0,0,0,3,0,1,4,166,0,1,0,36,0,0,0,1,0,0,1,67,0,3,0,0,0,1,0,160,0,1,0,18,0,1,0,0,1,67,0,1,0,1,2,165,0,1,0,0,0,1,0,8,0,2,0,10,0,2,2,248,6,82,0,1,0,2,2,165,2,172,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,0,96,0,1,0,96,0,1,0,96,0,0,0,3,0,0,0,1,0,80,0,2,0,80,0,80,0,0,0,3,0,1,4,52,0,1,0,64,0,0,0,1,0,0,1,69,0,3,0,0,0,1,0,46,0,1,0,46,0,1,0,0,1,70,0,1,0,0,0,1,0,8,0,1,0,20,0,78,0,1,0,0,0,1,0,8,0,1,0,6,3,166,0,1,0,1,2,172,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,0,96,0,1,0,96,0,1,0,96,0,0,0,3,0,0,0,1,0,80,0,2,0,80,0,80,0,0,0,3,0,1,3,192,0,1,0,64,0,0,0,1,0,0,1,72,0,3,0,0,0,1,0,46,0,1,0,46,0,1,0,0,1,73,0,1,0,0,0,1,0,8,0,1,0,20,0,75,0,1,0,0,0,1,0,8,0,1,0,6,3,170,0,1,0,1,2,168,0,6,0,0,0,6,0,18,0,34,0,50,0,66,0,82,0,100,0,3,0,1,7,198,0,1,7,198,0,1,3,2,0,0,0,3,0,0,0,1,7,182,0,2,2,242,2,242,0,0,0,3,0,0,0,1,7,166,0,2,2,226,7,166,0,0,0,3,0,1,2,210,0,1,7,150,0,1,2,210,0,0,0,3,0,1,3,40,0,1,2,194,0,0,0,1,0,0,1,75,0,3,0,0,0,1,7,116,0,1,2,176,0,1,0,0,1,75,0,1,0,0,0,1,0,8,0,2,0,10,0,2,3,13,6,82,0,1,0,2,2,176,2,181,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,7,58,0,1,7,58,0,1,0,68,0,0,0,3,0,0,0,1,7,42,0,2,0,52,0,52,0,0,0,3,0,1,2,188,0,1,0,36,0,0,0,1,0,0,1,77,0,3,0,0,0,1,7,8,0,1,0,18,0,1,0,0,1,77,0,1,0,1,3,71,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,3,14,0,1,0,2,2,181,3,71,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,6,200,0,1,6,200,0,1,2,210,0,0,0,3,0,0,0,1,6,184,0,2,2,194,2,194,0,0,0,3,0,1,2,74,0,1,2,178,0,0,0,1,0,0,1,79,0,3,0,0,0,1,6,150,0,1,2,160,0,1,0,0,1,79,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,3,16,0,1,0,2,2,181,3,73,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,6,92,0,1,6,92,0,1,6,92,0,0,0,3,0,0,0,1,6,76,0,2,6,76,6,76,0,0,0,3,0,1,1,222,0,1,6,60,0,0,0,1,0,0,1,81,0,3,0,0,0,1,6,42,0,1,6,42,0,1,0,0,1,82,0,1,0,0,0,1,0,8,0,1,6,16,0,92,0,1,0,0,0,1,0,8,0,1,6,2,3,157,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,0,96,0,1,0,96,0,1,0,96,0,0,0,3,0,0,0,1,0,80,0,2,0,80,0,80,0,0,0,3,0,1,1,112,0,1,0,64,0,0,0,1,0,0,1,84,0,3,0,0,0,1,0,46,0,1,0,46,0,1,0,0,1,85,0,1,0,0,0,1,0,8,0,1,0,20,0,77,0,1,0,0,0,1,0,8,0,1,0,6,3,138,0,1,0,1,2,200,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,0,68,0,1,0,68,0,1,0,182,0,0,0,3,0,0,0,1,0,52,0,2,0,166,0,166,0,0,0,3,0,1,0,252,0,1,0,150,0,0,0,1,0,0,1,87,0,3,0,0,0,1,0,18,0,1,0,132,0,1,0,0,1,87,0,1,0,1,2,183,0,1,0,0,0,1,0,8,0,2,0,10,0,2,2,224,6,82,0,1,0,2,2,176,2,183,0,6,0,0,0,4,0,14,0,30,0,46,0,64,0,3,0,1,0,68,0,1,0,68,0,1,0,74,0,0,0,3,0,0,0,1,0,52,0,2,0,58,0,58,0,0,0,3,0,1,0,138,0,1,0,42,0,0,0,1,0,0,1,89,0,3,0,0,0,1,0,18,0,1,0,24,0,1,0,0,1,89,0,1,0,1,2,176,0,1,0,1,2,184,0,1,0,0,0,1,0,8,0,2,0,10,0,2,6,82,2,252,0,1,0,2,2,176,2,184,0,6,0,0,0,4,0,14,0,30,0,46,0,70,0,3,0,1,0,102,0,1,0,102,0,1,0,102,0,0,0,3,0,0,0,1,0,86,0,2,0,86,0,86,0,0,0,3,0,1,0,18,0,1,0,70,0,0,0,1,0,0,1,91,0,1,0,1,6,82,0,3,0,0,0,1,0,46,0,1,0,46,0,1,0,0,1,92,0,1,0,0,0,1,0,8,0,1,0,20,0,93,0,1,0,0,0,1,0,8,0,1,0,6,3,156,0,1,0,1,2,182,0,6,0,0,0,4,0,14,0,52,0,128,0,196,0,3,0,1,0,20,0,1,0,26,0,1,0,32,0,1,0,0,1,94,0,1,0,1,3,74,0,1,0,1,3,79,0,1,0,1,3,73,0,3,0,0,0,1,0,18,0,1,0,24,0,1,0,0,1,94,0,1,0,1,0,230,0,2,0,8,0,1,0,193,0,0,0,221,0,221,0,193,1,5,1,6,0,194,1,8,1,8,0,196,1,25,1,26,0,197,1,28,1,33,0,199,1,143,1,208,0,205,2,35,2,68,1,15,0,3,0,1,5,4,0,1,0,132,0,1,0,20,0,1,0,0,1,94,0,1,0,22,0,1,0,27,0,28,0,34,0,38,0,59,0,195,0,221,0,222,0,228,0,232,0,254,2,106,2,107,2,108,2,109,2,110,2,111,2,112,2,113,2,114,2,115,0,3,0,1,4,0,0,1,0,64,0,1,4,0,0,1,0,0,1,95,0,1,0,0,0,1,0,8,0,2,0,12,0,3,1,131,1,138,5,16,0,1,0,3,0,230,1,117,3,79,0,1,0,0,0,1,0,8,0,1,0,6,0,21,0,1,0,1,1,117,0,6,0,0,0,5,0,16,0,34,0,52,0,114,0,132,0,3,0,0,0,1,0,56,0,1,0,76,0,1,0,0,1,97,0,3,0,0,0,1,0,154,0,1,0,58,0,1,0,0,1,98,0,3,0,0,0,1,0,20,0,2,0,28,0,40,0,1,0,0,1,99,0,1,0,2,1,9,1,22,0,1,0,4,6,40,6,41,6,43,6,44,0,2,0,3,6,27,6,39,0,0,6,45,6,46,0,13,6,75,6,75,0,15,0,3,0,1,3,202,0,1,3,202,0,0,0,1,0,0,1,97,0,3,0,1,0,18,0,1,3,184,0,0,0,1,0,0,1,99,0,2,0,3,0,1,0,193,0,0,1,143,1,208,0,193,2,35,2,68,1,3,0,2,0,0,0,1,0,8,0,1,0,8,0,1,0,14,0,1,0,1,1,20,0,2,1,10,6,44,0,1,0,0,0,1,0,8,0,2,0,40,0,17,1,10,1,23,6,60,6,61,6,62,6,63,6,64,6,65,6,66,6,67,6,68,6,69,6,70,6,71,6,72,6,77,6,80,0,1,0,17,1,9,1,22,6,27,6,28,6,29,6,30,6,31,6,32,6,33,6,34,6,35,6,36,6,37,6,38,6,40,6,76,6,79,0,6,0,0,0,2,0,10,0,28,0,3,0,0,0,1,3,20,0,1,0,36,0,1,0,0,1,101,0,3,0,1,0,18,0,1,3,2,0,0,0,1,0,0,1,102,0,2,0,3,6,60,6,72,0,0,6,77,6,77,0,13,6,80,6,80,0,14,0,1,0,0,0,1,0,8,0,2,0,14,0,4,0,140,0,147,1,82,1,89,0,1,0,4,0,138,0,146,1,80,1,88,0,1,0,0,0,1,0,8,0,2,0,28,0,11,0,189,0,190,0,191,0,192,0,193,1,133,1,134,1,135,1,136,1,137,6,73,0,1,0,11,0,29,0,95,0,102,0,136,0,185,0,223,1,36,1,44,1,78,1,128,6,30,0,4,0,0,0,1,0,8,0,1,0,30,0,2,0,10,0,20,0,1,0,4,0,188,0,2,0,83,0,1,0,4,1,132,0,2,1,22,0,1,0,2,0,72,1,11,0,6,0,0,0,2,0,10,0,30,0,3,0,0,0,2,0,62,0,40,0,1,0,62,0,1,0,0,1,107,0,3,0,0,0,2,0,74,0,20,0,1,0,74,0,1,0,0,1,108,0,1,0,1,2,174,0,4,0,0,0,1,0,8,0,1,0,8,0,1,0,14,0,1,0,1,1,28,0,1,0,4,1,32,0,2,2,174,0,4,0,0,0,1,0,8,0,1,0,8,0,1,0,14,0,1,0,1,0,87,0,1,0,4,0,91,0,2,2,174,0,1,0,0,0,1,0,8,0,2,0,48,0,21,1,206,1,207,1,208,2,16,2,17,2,18,2,19,2,20,2,21,2,22,2,23,2,24,2,25,2,26,2,27,2,28,2,29,2,30,2,31,2,32,2,33,0,1,0,21,1,149,1,160,1,170,1,211,1,212,1,215,1,219,1,220,1,221,1,222,1,223,1,224,1,226,1,230,1,233,1,239,1,240,1,241,1,243,1,244,1,255,0,1,0,0,0,1,0,8,0,1,0,6,0,80,0,1,0,1,1,210,0,1,0,0,0,1,0,8,0,1,0,208,0,11,0,1,0,0,0,1,0,8,0,1,0,194,0,41,0,1,0,0,0,1,0,8,0,1,0,180,0,21,0,1,0,0,0,1,0,8,0,1,0,6,255,232,0,1,0,1,2,181,0,1,0,0,0,1,0,8,0,1,0,146,0,31,0,6,0,0,0,2,0,10,0,34,0,3,0,1,0,18,0,1,0,66,0,0,0,1,0,0,1,119,0,1,0,1,2,157,0,3,0,1,0,18,0,1,0,42,0,0,0,1,0,0,1,120,0,2,0,1,2,127,2,136,0,0,0,1,0,0,0,1,0,8,0,1,0,6,255,246,0,2,0,1,2,137,2,146,0,0,0,6,0,0,0,2,0,10,0,36,0,3,0,1,0,44,0,1,0,18,0,0,0,1,0,0,1,122,0,1,0,2,0,1,0,195,0,3,0,1,0,18,0,1,0,28,0,0,0,1,0,0,1,122,0,2,0,1,2,106,2,115,0,0,0,1,0,2,0,101,1,43,0,1,0,0,0,1,0,8,0,2,0,14,0,4,1,140,1,141,1,140,1,141,0,1,0,4,0,1,0,101,0,195,1,43,0,4,0,0,0,1,0,8,0,1,0,20,0,1,0,8,0,1,0,4,4,172,0,3,1,43,2,165,0,1,0,1,0,94,0,1,0,0,0,1,0,8,0,2,0,36,0,15,6,60,6,61,6,62,6,63,6,64,6,65,6,66,6,67,6,68,6,69,6,70,6,71,6,72,6,77,6,80,0,2,0,4,6,27,6,38,0,0,6,40,6,40,0,12,6,76,6,76,0,13,6,79,6,79,0,14,0,1,0,0,0,1,0,8,0,1,0,6,253,232,0,1,0,1,5,14,0,1,0,0,0,1,0,8,0,1,0,6,0,10,0,1,0,1,2,106,0,1,0,0,0,1,0,8,0,1,0,6,1,5,0,2,0,1,3,106,3,137,0,0,0,1,0,0,0,1,0,8,0,2,0,16,0,5,6,83,6,84,6,85,6,86,6,87,0,1,0,5,3,29,3,34,4,215,4,249,4,250,0,1,0,0,0,0,0,1,0,0,0,16,0,0,0,30,0,1,0,0,0,6,0,1,0,0,32,0,64,0,0,1,0,0,0,1,0,15,0,0,0,12,0,0,0,1,1,129,0,0,0,1,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,12,0,1,0,0,0,28,0,1,0,2,192,0,192,0,0,0,0,0,64,0,64,0,6,88,0,0,0,0,0,0,0,4,4,176,1,144,0,5,0,0,5,51,4,205,0,0,0,154,5,51,4,205,0,0,2,205,0,50,2,124,0,0,2,11,6,9,2,0,0,2,0,4,161,0,2,255,0,0,248,251,0,4,0,0,0,0,0,0,83,65,74,65,0,192,0,9,43,203,7,108,254,32,0,0,8,178,1,224,96,0,1,159,223,215,0,0,4,36,5,140,0,0,0,32,0,5,0,1,0,1,0,8,0,1,0,0,0,20,0,6,0,0,0,28,0,2,119,103,104,116,1,0,0,0,0,12,0,24,0,36,0,48,0,64,0,76,0,1,0,0,0,0,1,1,0,200,0,0,0,1,0,0,0,0,1,2,1,44,0,0,0,1,0,0,0,0,1,3,1,94,0,0,0,3,0,0,0,2,1,4,1,144,0,0,2,188,0,0,0,1,0,0,0,0,1,5,2,88,0,0,0,1,0,0,0,0,1,6,2,188,0,0,0,1,0,0,0,0,0,1,0,6,192,0,192,0,224,0,213,85,240,0,234,171,0,0,0,0,42,171,32,0,64,0,64,0,0,0,0,0,0,2,0,0,0,3,0,0,0,20,0,3,0,1,0,0,0,20,0,4,13,216,0,0,1,36,1,0,0,7,0,36,0,9,0,13,0,47,0,57,0,126,1,127,1,134,1,144,1,146,1,157,1,161,1,169,1,176,1,183,1,206,1,231,1,235,1,255,2,27,2,31,2,51,2,55,2,69,2,84,2,89,2,91,2,106,2,114,2,131,2,140,2,146,2,167,2,188,2,199,2,201,2,221,3,4,3,12,3,18,3,27,3,35,3,40,3,66,3,117,3,126,3,138,3,140,3,144,3,161,3,169,3,176,3,201,3,207,3,215,4,26,4,35,4,58,4,67,4,95,4,147,4,151,4,155,4,163,4,179,4,183,4,187,4,192,4,207,4,217,4,227,4,233,4,239,14,63,30,133,30,158,30,249,32,8,32,17,32,21,32,30,32,34,32,36,32,38,32,40,32,48,32,51,32,58,32,60,32,62,32,68,32,112,32,121,32,127,32,137,32,161,32,164,32,174,32,178,32,181,32,186,32,190,33,5,33,19,33,23,33,34,33,38,33,46,33,94,33,149,33,168,33,225,33,227,34,2,34,6,34,15,34,18,34,21,34,26,34,31,34,41,34,43,34,72,34,101,35,16,35,33,35,175,37,148,37,159,37,255,38,25,38,60,38,64,38,66,38,96,38,99,38,102,38,107,39,19,39,103,39,111,40,255,42,47,43,47,43,200,43,203,255,255,0,0,0,9,0,13,0,32,0,48,0,58,0,160,1,134,1,143,1,146,1,157,1,160,1,169,1,175,1,183,1,205,1,230,1,234,1,250,2,24,2,30,2,50,2,55,2,69,2,84,2,89,2,91,2,106,2,114,2,131,2,140,2,146,2,167,2,187,2,198,2,201,2,216,3,0,3,6,3,18,3,27,3,35,3,38,3,64,3,116,3,126,3,132,3,140,3,142,3,145,3,163,3,170,3,177,3,202,3,215,4,0,4,27,4,36,4,59,4,68,4,144,4,150,4,154,4,162,4,174,4,182,4,186,4,192,4,207,4,216,4,226,4,232,4,238,14,63,30,128,30,158,30,160,32,8,32,16,32,19,32,23,32,32,32,36,32,38,32,40,32,48,32,50,32,57,32,60,32,62,32,68,32,112,32,116,32,127,32,128,32,160,32,163,32,166,32,177,32,180,32,184,32,188,33,5,33,19,33,22,33,34,33,38,33,46,33,91,33,144,33,168,33,225,33,227,34,2,34,6,34,15,34,17,34,21,34,25,34,30,34,41,34,43,34,72,34,96,35,16,35,32,35,175,37,0,37,149,37,160,38,25,38,58,38,64,38,66,38,96,38,99,38,101,38,106,39,19,39,103,39,108,40,0,42,47,43,18,43,197,43,202,255,255,6,72,3,14,0,0,2,58,0,0,0,0,254,245,0,0,1,148,254,198,0,0,254,143,0,0,254,131,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,224,254,99,254,237,254,163,254,158,254,88,254,183,254,119,254,227,254,107,254,179,0,0,3,110,3,81,0,0,0,0,0,0,3,21,3,13,3,6,3,4,0,0,2,162,255,153,0,0,254,179,0,0,254,146,254,145,0,0,254,148,0,0,254,146,0,0,253,133,0,0,253,167,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,253,9,253,60,0,0,0,0,0,0,0,0,244,222,0,0,225,239,0,0,227,16,226,182,226,176,0,0,0,0,226,143,226,131,226,244,227,46,228,115,226,154,226,117,226,118,226,89,226,35,226,35,225,15,225,245,0,0,0,0,0,0,0,0,0,0,0,0,0,0,227,158,227,151,0,0,227,128,226,47,227,127,225,70,0,0,225,191,225,135,225,134,225,89,225,80,225,72,0,0,225,39,0,0,0,0,225,42,225,41,225,6,0,0,224,49,0,0,223,143,0,0,221,231,0,0,222,118,222,86,222,83,222,82,222,53,222,51,222,50,222,170,221,134,221,51,0,0,0,0,217,49,0,0,0,0,0,0,0,1,0,0,0,0,1,32,0,0,1,60,1,196,0,0,3,128,0,0,0,0,3,126,0,0,3,126,0,0,3,126,3,128,3,130,3,132,3,142,3,148,3,150,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,130,0,0,0,0,3,128,3,138,3,146,0,0,0,0,0,0,0,0,3,150,0,0,0,0,3,150,0,0,3,160,0,0,0,0,3,160,0,0,3,170,0,0,3,178,0,0,3,228,0,0,4,14,4,68,4,74,4,76,4,78,4,80,4,90,4,92,0,0,0,0,4,90,4,92,4,94,4,96,0,0,4,96,0,0,4,104,0,0,0,0,0,0,5,20,5,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,12,5,14,5,16,5,32,5,34,5,36,5,40,0,0,0,0,5,40,0,0,0,0,0,0,0,0,5,34,0,0,0,0,0,0,0,0,0,0,0,0,5,32,0,0,5,32,5,34,0,0,0,0,0,0,5,30,0,0,5,38,0,0,5,38,0,0,6,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,246,6,252,0,0,8,248,9,50,9,56,0,0,3,25,2,170,2,213,2,178,3,34,3,93,4,156,2,214,2,183,2,184,2,176,3,67,2,166,2,193,2,165,2,181,2,167,2,168,3,74,3,71,3,73,2,172,4,155,0,1,0,27,0,28,0,34,0,38,0,59,0,60,0,66,0,70,0,83,0,85,0,87,0,93,0,94,0,101,0,128,0,130,0,131,0,135,0,143,0,148,0,167,0,169,0,174,0,175,0,184,2,187,2,182,2,188,3,81,2,200,6,49,0,195,0,221,0,222,0,228,0,232,0,254,0,255,1,5,1,9,1,22,1,25,1,28,1,34,1,35,1,43,1,70,1,72,1,73,1,77,1,85,1,91,1,110,1,112,1,117,1,118,1,127,2,185,4,167,2,186,3,79,3,26,2,171,3,31,3,54,3,33,3,58,4,168,4,158,6,47,4,159,1,140,2,209,3,80,2,194,4,160,6,57,4,164,3,77,2,149,2,150,6,50,3,90,4,157,2,174,6,58,2,148,1,141,2,210,2,159,2,158,2,160,2,173,0,18,0,2,0,10,0,24,0,16,0,22,0,25,0,31,0,51,0,39,0,42,0,48,0,78,0,72,0,74,0,75,0,35,0,100,0,112,0,102,0,104,0,126,0,110,3,69,0,124,0,154,0,149,0,151,0,152,0,176,0,129,1,83,0,212,0,196,0,204,0,218,0,210,0,216,0,219,0,225,0,245,0,233,0,236,0,242,1,16,1,11,1,13,1,14,0,229,1,42,1,54,1,44,1,46,1,68,1,52,3,70,1,66,1,97,1,92,1,94,1,95,1,119,1,71,1,121,0,20,0,214,0,3,0,197,0,21,0,215,0,29,0,223,0,32,0,226,0,33,0,227,0,30,0,224,0,36,0,230,0,37,0,231,0,53,0,247,0,40,0,234,0,49,0,243,0,54,0,248,0,41,0,235,0,63,1,2,0,61,1,0,0,65,1,4,0,64,1,3,0,69,1,8,0,67,1,6,0,82,1,21,0,80,1,19,0,73,1,12,0,81,1,20,0,76,1,10,0,71,1,18,0,84,1,24,0,86,1,26,1,27,0,88,1,29,0,90,1,31,0,89,1,30,0,91,1,32,0,92,1,33,0,95,1,36,0,97,1,39,0,96,1,38,1,37,0,98,1,40,0,121,1,63,0,103,1,45,0,120,1,62,0,127,1,69,0,132,1,74,0,134,1,76,0,133,1,75,0,136,1,78,0,139,1,81,0,138,1,80,0,137,1,79,0,146,1,88,0,145,1,87,0,144,1,86,0,166,1,109,0,163,1,106,0,150,1,93,0,165,1,108,0,162,1,105,0,164,1,107,0,171,1,114,0,177,1,120,0,178,0,185,1,128,0,187,1,130,0,186,1,129,1,84,0,142,0,55,0,114,1,56,0,156,1,99,0,9,0,203,0,62,1,1,0,122,1,64,0,23,0,217,0,26,0,220,0,125,1,67,0,140,1,82,0,147,1,89,0,68,1,7,0,182,1,125,6,25,6,24,6,54,6,48,6,55,6,59,6,56,6,51,6,29,6,30,6,32,6,36,6,37,6,34,6,28,6,27,6,38,6,35,6,31,6,33,6,45,6,46,6,75,6,76,6,78,2,59,3,22,2,60,2,61,2,62,2,64,2,65,2,96,2,66,2,67,2,102,2,103,2,104,2,94,2,99,2,95,2,98,2,100,2,97,2,101,2,68,1,151,1,152,1,191,1,147,1,183,1,182,1,185,1,186,1,187,1,180,1,181,1,188,1,159,1,157,1,169,1,176,1,143,1,144,1,145,1,146,1,149,1,150,1,153,1,154,1,155,1,156,1,158,1,170,1,171,1,173,1,172,1,174,1,175,1,178,1,179,1,177,1,184,1,189,1,190,1,209,1,210,1,211,1,212,1,215,1,216,1,219,1,220,1,221,1,222,1,224,1,236,1,237,1,239,1,238,1,240,1,241,1,244,1,245,1,243,1,250,1,255,2,0,1,217,1,218,2,1,1,213,1,249,1,248,1,251,1,252,1,253,1,246,1,247,1,254,1,225,1,223,1,235,1,242,1,148,1,214,1,192,2,2,1,193,2,3,1,194,2,4,1,195,2,5,1,196,2,6,1,197,2,7,1,198,2,8,1,199,2,9,1,200,2,10,1,202,2,12,1,203,2,13,1,204,2,14,1,205,2,15,0,173,1,116,0,170,1,113,0,172,1,115,0,17,0,211,0,19,0,213,0,11,0,205,0,13,0,207,0,14,0,208,0,15,0,209,0,12,0,206,0,4,0,198,0,6,0,200,0,7,0,201,0,8,0,202,0,5,0,199,0,50,0,244,0,52,0,246,0,57,0,251,0,43,0,237,0,45,0,239,0,46,0,240,0,47,0,241,0,44,0,238,0,79,1,17,0,77,1,15,0,111,1,53,0,113,1,55,0,105,1,47,0,107,1,49,0,108,1,50,0,109,1,51,0,106,1,48,0,115,1,57,0,117,1,59,0,118,1,60,0,119,1,61,0,116,1,58,0,153,1,96,0,155,1,98,0,157,1,100,0,159,1,102,0,160,1,103,0,161,1,104,0,158,1,101,0,180,1,123,0,179,1,122,0,181,1,124,0,183,1,126,2,201,2,206,2,207,2,202,2,208,2,204,2,205,2,203,4,169,4,171,2,175,3,37,3,32,3,39,3,44,3,47,3,48,3,51,3,57,3,53,3,35,3,36,3,42,3,56,3,49,3,40,3,41,3,30,3,55,3,52,3,45,3,46,3,50,3,43,4,172,4,161,3,100,3,97,3,98,3,99,3,101,3,102,3,88,3,68,3,59,3,89,3,82,3,92,3,72,3,61,3,66,3,95,3,76,3,75,3,64,3,63,4,56,4,18,4,69,4,31,4,62,4,24,4,63,4,25,4,59,4,21,4,60,4,22,4,55,4,6,4,0,4,17,4,54,4,4,3,254,4,16,4,68,4,95,4,89,4,30,4,67,4,93,4,87,4,28,4,72,4,107,4,88,4,1,4,104,4,7,4,94,4,34,4,71,4,106,4,86,3,255,4,103,4,5,4,92,4,33,4,53,4,36,4,74,4,3,3,253,4,77,4,39,4,15,4,66,4,37,4,75,4,91,4,85,4,78,4,40,4,27,4,70,4,38,4,76,4,105,4,84,4,2,4,102,4,42,4,80,4,35,4,73,4,8,4,90,4,79,4,41,4,32,4,50,4,12,4,51,4,13,3,242,3,246,4,11,3,252,3,241,4,10,3,251,3,240,4,98,4,83,3,245,4,97,4,82,3,244,4,110,4,101,3,249,4,109,4,100,3,248,4,9,3,250,3,239,4,96,4,81,3,243,4,108,4,99,3,247,4,44,4,43,4,45,4,46,4,49,4,48,4,47,4,57,4,64,4,61,4,52,4,19,4,26,4,23,4,14,4,58,4,65,4,20,4,29,3,114,3,106,3,107,3,108,3,109,3,110,3,111,3,112,3,113,3,122,3,121,3,120,3,119,3,118,3,117,3,116,3,123,3,135,3,136,3,137,3,115,3,182,3,183,3,184,3,185,3,187,3,188,3,189,3,190,3,191,3,192,3,193,3,194,3,179,3,180,3,178,3,181,3,176,3,177,3,208,3,212,3,223,3,227,3,209,3,213,3,224,3,228,3,219,3,221,3,210,3,214,3,225,3,229,3,211,3,215,3,226,3,230,3,220,3,222,3,168,3,169,3,174,3,155,3,175,3,139,3,154,3,153,3,156,3,138,3,141,3,142,3,143,3,144,3,147,3,148,3,145,3,146,3,158,3,159,3,160,3,161,3,164,3,165,3,166,3,167,3,162,3,163,3,232,3,233,3,234,3,231,3,157,3,195,3,196,3,197,3,198,3,199,3,216,3,217,3,218,3,140,3,200,3,201,3,202,3,203,3,149,3,150,3,151,3,152,3,238,3,235,3,237,3,204,3,205,3,206,3,207,3,236,2,191,2,192,2,189,2,190,5,22,5,23,5,151,5,24,5,215,5,88,5,152,5,25,5,247,5,120,5,184,5,57,5,216,5,89,5,153,5,26,6,7,5,136,5,200,5,73,5,232,5,105,5,169,5,42,5,248,5,121,5,185,5,58,5,217,5,90,5,154,5,27,6,15,5,144,5,208,5,81,5,240,5,113,5,177,5,50,6,0,5,129,5,193,5,66,5,225,5,98,5,162,5,35,6,8,5,137,5,201,5,74,5,233,5,106,5,170,5,43,5,249,5,122,5,186,5,59,5,218,5,91,5,155,5,28,6,19,5,148,5,212,5,85,5,244,5,117,5,181,5,54,6,4,5,133,5,197,5,70,5,229,5,102,5,166,5,39,6,12,5,141,5,205,5,78,5,237,5,110,5,174,5,47,5,253,5,126,5,190,5,63,5,222,5,95,5,159,5,32,6,16,5,145,5,209,5,82,5,241,5,114,5,178,5,51,6,1,5,130,5,194,5,67,5,226,5,99,5,163,5,36,6,9,5,138,5,202,5,75,5,234,5,107,5,171,5,44,5,250,5,123,5,187,5,60,5,219,5,92,5,156,5,29,6,21,5,150,5,214,5,87,5,246,5,119,5,183,5,56,6,6,5,135,5,199,5,72,5,231,5,104,5,168,5,41,6,14,5,143,5,207,5,80,5,239,5,112,5,176,5,49,5,255,5,128,5,192,5,65,5,224,5,97,5,161,5,34,6,18,5,147,5,211,5,84,5,243,5,116,5,180,5,53,6,3,5,132,5,196,5,69,5,228,5,101,5,165,5,38,6,11,5,140,5,204,5,77,5,236,5,109,5,173,5,46,5,252,5,125,5,189,5,62,5,221,5,94,5,158,5,31,6,20,5,149,5,213,5,86,5,245,5,118,5,182,5,55,6,5,5,134,5,198,5,71,5,230,5,103,5,167,5,40,6,13,5,142,5,206,5,79,5,238,5,111,5,175,5,48,5,254,5,127,5,191,5,64,5,223,5,96,5,160,5,33,6,17,5,146,5,210,5,83,5,242,5,115,5,179,5,52,6,2,5,131,5,195,5,68,5,227,5,100,5,164,5,37,6,10,5,139,5,203,5,76,5,235,5,108,5,172,5,45,5,251,5,124,5,188,5,61,5,220,5,93,5,157,5,30,4,191,4,194,4,192,4,195,3,170,3,171,3,172,3,173,3,186,4,177,4,198,4,188,4,204,4,184,4,201,4,196,4,174,4,190,4,176,4,178,4,199,4,181,4,200,4,185,4,186,4,202,4,175,4,197,4,187,4,203,4,183,4,179,4,180,4,182,4,193,4,189,0,1,0,0,0,2,0,20,0,9,160,0,192,0,0,9,160,0,64,0,3,2,147,1,3,2,208,208,211,3,2,147,1,3,2,34,40,40,0,0,5,220,0,20,5,140,0,20,5,140,0,20,4,36,0,20,0,0,255,236,0,0,255,236,0,0,255,236,254,52,255,238,5,140,0,20,0,0,255,236,0,0,0,206,0,199,0,190,0,190,0,212,0,176,0,176,0,13,0,200,0,10,0,188,0,95,255,252,1,84,0,142,0,204,0,192,0,195,0,12,0,213,0,176,0,80,0,182,255,248,0,190,0,117,0,190,0,177,0,213,0,213,0,149,1,78,0,18,0,184,0,154,0,205,0,192,0,3,0,214,0,197,0,181,0,172,0,183,0,163,0,189,1,124,0,184,0,168,0,192,0,203,0,230,0,12,0,30,0,192,0,200,0,211,0,95,0,183,0,190,1,84,0,122,0,142,0,165,0,176,0,187,0,196,0,208,0,216,0,12,0,160,0,176,0,192,0,200,0,212,0,220,0,80,0,140,0,161,0,173,0,180,0,191,0,226,0,117,0,171,0,177,0,185,0,190,0,199,0,204,0,208,0,213,0,138,0,154,0,172,0,202,0,206,0,214,0,220,0,252,1,78,0,18,0,176,0,184,0,190,0,149,0,158,0,192,0,207,0,3,0,171,0,181,0,192,0,201,0,216,0,163,0,170,0,180,0,188,0,201,1,124,0,159,0,168,0,182,0,193,0,204,0,230,3,34,4,28,6,194,4,152,3,42,6,74,6,98,6,84,0,0,64,74,153,152,151,150,135,134,133,132,131,130,129,128,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,81,80,79,78,77,76,75,74,73,72,71,70,40,31,16,10,9,44,1,177,11,10,67,35,67,101,10,45,44,0,177,10,11,67,35,67,11,45,44,1,176,6,67,176,7,67,101,10,45,44,176,79,43,32,176,64,81,88,33,75,82,88,69,68,27,33,33,89,27,35,33,176,64,176,4,37,69,176,4,37,69,97,100,138,99,82,88,69,68,27,33,33,89,89,45,44,0,176,7,67,176,6,67,11,45,44,75,83,35,75,81,90,88,32,69,138,96,68,27,33,33,89,45,44,75,84,88,32,69,138,96,68,27,33,33,89,45,44,75,83,35,75,81,90,88,56,27,33,33,89,45,44,75,84,88,56,27,33,33,89,45,44,176,2,67,84,88,176,70,43,27,33,33,33,33,89,45,44,176,2,67,84,88,176,71,43,27,33,33,33,89,45,44,176,2,67,84,88,176,72,43,27,33,33,33,33,89,45,44,176,2,67,84,88,176,73,43,27,33,33,33,89,45,44,35,32,176,0,80,138,138,100,177,0,3,37,84,88,176,64,27,177,1,3,37,84,88,176,5,67,139,89,176,79,43,89,35,176,98,43,35,33,35,88,101,89,45,44,177,8,0,12,33,84,96,67,45,44,177,12,0,12,33,84,96,67,45,44,1,32,71,176,2,67,32,184,16,0,98,184,16,0,99,87,35,184,1,0,98,184,16,0,99,87,90,88,176,32,96,102,89,72,45,44,177,0,2,37,176,2,37,176,2,37,83,184,0,53,35,120,176,2,37,176,2,37,96,176,32,99,32,32,176,6,37,35,98,80,88,138,33,176,1,96,35,27,32,32,176,6,37,35,98,82,88,35,33,176,1,97,27,138,33,35,33,32,89,89,184,255,193,28,96,176,32,99,35,33,45,44,177,2,0,66,177,35,1,136,81,177,64,1,136,83,90,88,185,16,0,0,32,136,84,88,178,2,1,2,67,96,66,89,177,36,1,136,81,88,185,32,0,0,64,136,84,88,178,2,2,2,67,96,66,177,36,1,136,84,88,178,2,32,2,67,96,66,0,75,1,75,82,88,178,2,8,2,67,96,66,89,27,185,64,0,0,128,136,84,88,178,2,4,2,67,96,66,89,185,64,0,0,128,99,184,1,0,136,84,88,178,2,8,2,67,96,66,89,185,64,0,1,0,99,184,2,0,136,84,88,178,2,16,2,67,96,66,89,177,38,1,136,81,88,185,64,0,2,0,99,184,4,0,136,84,88,178,2,64,2,67,96,66,89,185,64,0,4,0,99,184,8,0,136,84,88,178,2,128,2,67,96,66,89,177,40,1,136,81,88,185,64,0,8,0,99,184,16,0,136,84,88,186,0,2,1,0,0,2,67,96,66,89,89,89,89,89,89,89,177,0,2,67,84,88,64,10,5,64,8,64,9,64,12,2,13,2,27,177,1,2,67,84,88,178,5,64,8,186,1,0,0,9,1,0,179,12,1,13,1,27,177,128,2,67,82,88,178,5,64,8,184,1,128,177,9,64,27,185,1,0,0,2,67,82,88,178,5,64,8,186,1,128,0,9,1,64,27,185,1,128,0,2,67,82,88,178,5,64,8,184,2,0,177,9,64,27,178,5,64,8,186,1,0,0,9,1,0,89,89,89,185,64,0,0,128,136,85,185,64,0,2,0,99,184,4,0,136,85,90,88,179,12,0,13,1,27,179,12,0,13,1,89,89,89,66,66,66,66,66,45,44,69,177,2,78,43,35,176,79,43,32,176,64,81,88,33,75,81,88,176,2,37,69,177,1,78,43,96,89,27,35,75,81,88,176,3,37,69,32,100,138,99,176,64,83,88,177,2,78,43,96,27,33,89,27,33,89,89,68,45,44,32,176,0,80,32,88,35,101,27,35,89,177,20,20,138,112,69,177,16,16,67,75,138,67,81,90,88,176,64,27,176,79,43,89,35,177,97,6,38,96,43,138,88,176,5,67,139,89,35,88,101,89,35,16,58,45,44,176,3,37,73,99,35,70,96,176,79,43,35,176,4,37,176,4,37,73,176,3,37,99,86,32,96,176,98,96,43,176,3,37,32,16,70,138,70,96,176,32,99,97,58,45,44,176,0,22,177,2,3,37,177,1,4,37,1,62,0,62,177,1,2,6,12,176,10,35,101,66,176,11,35,66,177,2,3,37,177,1,4,37,1,63,0,63,177,1,2,6,12,176,6,35,101,66,176,7,35,66,176,1,22,177,0,2,67,84,88,69,35,69,32,24,105,138,99,35,98,32,32,176,64,80,88,103,27,102,89,97,176,32,99,176,64,35,97,176,4,35,66,27,177,4,0,66,33,33,89,24,1,45,44,32,69,177,0,78,43,68,45,44,75,81,177,64,79,43,80,91,88,32,69,177,1,78,43,32,138,138,68,32,177,64,4,38,97,99,97,177,1,78,43,68,33,27,35,33,138,69,177,1,78,43,32,138,35,68,68,89,45,44,75,81,177,64,79,43,80,91,88,69,32,138,176,64,97,99,96,27,35,33,69,89,177,1,78,43,68,45,44,35,69,32,138,69,35,97,32,100,176,64,81,176,4,37,32,176,0,83,35,176,64,81,90,90,177,64,79,43,84,90,88,138,12,100,35,100,35,83,88,177,64,64,138,97,32,99,97,27,32,99,89,27,138,89,99,177,2,78,43,96,68,45,44,1,45,44,0,45,44,5,177,11,10,67,35,67,101,10,45,44,177,10,11,67,35,67,11,2,45,44,176,2,37,99,102,176,2,37,184,32,0,98,96,35,98,45,44,176,2,37,99,176,32,96,102,176,2,37,184,32,0,98,96,35,98,45,44,176,2,37,99,103,176,2,37,184,32,0,98,96,35,98,45,44,176,2,37,99,102,176,32,96,176,2,37,184,32,0,98,96,35,98,45,44,35,74,177,2,78,43,45,44,35,74,177,1,78,43,45,44,35,138,74,35,69,100,176,2,37,100,176,2,37,97,100,176,3,67,82,88,33,32,100,89,177,2,78,43,35,176,0,80,88,101,89,45,44,35,138,74,35,69,100,176,2,37,100,176,2,37,97,100,176,3,67,82,88,33,32,100,89,177,1,78,43,35,176,0,80,88,101,89,45,44,32,176,3,37,74,177,2,78,43,138,16,59,45,44,32,176,3,37,74,177,1,78,43,138,16,59,45,44,176,3,37,176,3,37,138,176,103,43,138,16,59,45,44,176,3,37,176,3,37,138,176,104,43,138,16,59,45,44,176,3,37,70,176,3,37,70,96,176,4,37,46,176,4,37,176,4,37,176,4,38,32,176,0,80,88,33,176,106,27,176,108,89,43,176,3,37,70,176,3,37,70,96,97,176,128,98,32,138,32,16,35,58,35,32,16,35,58,45,44,176,3,37,71,176,3,37,71,96,176,5,37,71,176,128,99,97,176,2,37,176,6,37,73,99,35,176,5,37,74,176,128,99,32,88,98,27,33,89,176,4,38,70,96,138,70,138,70,96,176,32,99,97,45,44,176,4,38,176,4,37,176,4,37,176,4,38,176,110,43,32,138,32,16,35,58,35,32,16,35,58,45,44,35,32,176,1,84,88,33,176,2,37,177,2,78,43,176,128,80,32,96,89,32,96,96,32,176,1,81,88,33,33,27,32,176,5,81,88,33,32,102,97,176,64,35,97,177,0,3,37,80,176,3,37,176,3,37,80,90,88,32,176,3,37,97,138,83,88,33,176,0,89,27,33,89,27,176,7,84,88,32,102,97,101,35,33,27,33,33,176,0,89,89,89,177,2,78,43,45,44,176,2,37,176,4,37,74,176,0,83,88,176,0,27,138,138,35,138,176,1,89,176,4,37,70,32,102,97,32,176,5,38,176,6,38,73,176,5,38,176,5,38,176,112,43,35,97,101,176,32,96,32,102,97,176,32,97,101,45,44,176,2,37,70,32,138,32,176,0,80,88,33,177,2,78,43,27,69,35,33,89,97,101,176,2,37,16,59,45,44,176,4,38,32,184,2,0,98,32,184,2,0,99,138,35,97,32,176,93,96,43,176,5,37,17,138,18,138,32,57,138,88,186,0,93,16,0,0,4,38,99,86,96,43,35,33,32,16,32,70,32,177,2,78,43,35,97,27,35,33,32,138,32,16,73,177,2,78,43,89,59,45,44,186,0,93,16,0,0,9,37,99,86,96,43,176,5,37,176,5,37,176,5,38,176,109,43,177,93,7,37,96,43,176,5,37,176,5,37,176,5,37,176,5,37,176,111,43,186,0,93,16,0,0,8,38,99,86,96,43,32,176,0,82,88,176,80,43,176,5,37,176,5,37,176,7,37,176,7,37,176,5,37,176,113,43,176,2,23,56,176,0,82,176,2,37,176,1,82,90,88,176,4,37,176,6,37,73,176,3,37,176,5,37,73,96,32,176,64,82,88,33,27,176,0,82,88,32,176,2,84,88,176,4,37,176,4,37,176,7,37,176,7,37,73,176,2,23,56,27,176,4,37,176,4,37,176,4,37,176,6,37,73,176,2,23,56,89,89,89,89,89,33,33,33,33,33,45,44,186,0,93,16,0,0,11,37,99,86,96,43,176,7,37,176,7,37,176,6,37,176,6,37,176,12,37,176,12,37,176,9,37,176,8,37,176,110,43,176,4,23,56,176,7,37,176,7,37,176,7,38,176,109,43,176,4,37,176,4,37,176,4,38,176,109,43,176,80,43,176,6,37,176,6,37,176,3,37,176,113,43,176,5,37,176,5,37,176,3,37,176,2,23,56,32,176,6,37,176,6,37,176,5,37,176,113,43,96,176,6,37,176,6,37,176,4,37,101,176,2,23,56,176,2,37,176,2,37,96,32,176,64,83,88,33,176,64,97,35,176,64,97,35,27,184,255,192,80,88,176,64,96,35,176,64,96,35,89,89,176,8,37,176,8,37,176,4,38,176,2,23,56,176,5,37,176,5,37,138,176,2,23,56,32,176,0,82,88,176,6,37,176,8,37,73,176,3,37,176,5,37,73,96,32,176,64,82,88,33,27,176,0,82,88,176,6,37,176,6,37,176,6,37,176,6,37,176,11,37,176,11,37,73,176,4,23,56,176,6,37,176,6,37,176,6,37,176,6,37,176,10,37,176,10,37,176,7,37,176,113,43,176,4,23,56,176,4,37,176,4,37,176,5,37,176,7,37,176,5,37,176,113,43,176,2,23,56,27,176,4,37,176,4,37,185,255,192,0,2,23,56,89,89,89,33,33,33,33,33,33,33,33,45,44,176,4,37,176,3,37,135,176,3,37,176,3,37,138,32,176,0,80,88,33,176,101,27,176,104,89,43,100,176,4,37,176,4,37,6,176,4,37,176,4,37,73,32,32,99,176,3,37,32,99,81,177,0,3,37,84,91,88,33,33,35,33,7,27,32,99,176,2,37,32,99,97,32,176,83,43,138,99,176,5,37,176,5,37,135,176,4,37,176,4,38,74,176,0,80,88,101,89,176,4,38,32,1,70,35,0,70,176,5,38,32,1,70,35,0,70,176,0,22,0,176,0,35,72,1,176,0,35,72,0,32,176,1,35,72,176,2,35,72,1,32,176,1,35,72,176,2,35,72,35,178,2,0,1,8,35,56,178,2,0,1,9,35,56,177,2,1,7,176,1,22,89,45,44,35,16,13,12,138,99,35,138,99,96,100,185,64,0,4,0,99,80,88,176,0,56,27,60,89,45,44,176,6,37,176,9,37,176,9,37,176,7,38,176,118,43,35,176,0,84,88,5,27,4,89,176,4,37,176,6,38,176,119,43,176,5,37,176,5,38,176,5,37,176,5,38,176,118,43,176,0,84,88,5,27,4,89,176,119,43,45,44,176,7,37,176,10,37,176,10,37,176,8,38,176,118,43,138,176,0,84,88,5,27,4,89,176,5,37,176,7,38,176,119,43,176,6,37,176,6,38,176,6,37,176,6,38,176,118,43,8,176,119,43,45,44,176,7,37,176,10,37,176,10,37,176,8,38,176,118,43,138,138,8,176,4,37,176,6,38,176,119,43,176,5,37,176,5,38,176,5,37,176,5,38,176,118,43,176,0,84,88,5,27,4,89,176,119,43,45,44,176,8,37,176,11,37,176,11,37,176,9,38,176,118,43,176,4,38,176,4,38,8,176,5,37,176,7,38,176,119,43,176,6,37,176,6,38,176,6,37,176,6,38,176,118,43,8,176,119,43,45,44,3,176,3,37,176,3,37,74,176,4,37,176,3,37,74,2,176,5,37,176,5,38,74,176,5,38,176,5,38,74,176,4,38,99,138,138,99,97,45,44,177,93,14,37,96,43,176,12,38,17,176,5,38,18,176,10,37,57,176,7,37,57,176,10,37,176,10,37,176,9,37,176,124,43,176,0,80,176,11,37,176,8,37,176,10,37,176,124,43,176,0,80,84,88,176,7,37,176,11,37,135,176,4,37,176,4,37,11,176,10,37,16,176,9,37,193,176,2,37,176,2,37,11,176,7,37,16,176,6,37,193,27,176,7,37,176,11,37,176,11,37,185,255,255,0,118,43,176,4,37,176,4,37,11,176,7,37,176,10,37,176,119,43,176,10,37,176,8,37,176,8,37,185,255,255,0,118,43,176,2,37,176,2,37,11,176,10,37,176,7,37,176,119,43,89,176,10,37,70,176,10,37,70,96,176,8,37,70,176,8,37,70,96,176,6,37,176,6,37,11,176,12,37,176,12,37,176,12,38,32,176,0,80,88,33,176,106,27,176,108,89,43,176,4,37,176,4,37,11,176,9,37,176,9,37,176,9,38,32,176,0,80,88,33,176,106,27,176,108,89,43,35,176,10,37,70,176,10,37,70,96,97,176,32,99,35,176,8,37,70,176,8,37,70,96,97,176,32,99,177,1,12,37,84,88,4,27,5,89,176,10,38,32,16,176,3,37,58,176,6,38,176,6,38,11,176,7,38,32,16,138,58,177,1,7,38,84,88,4,27,5,89,176,5,38,32,16,176,2,37,58,138,138,11,35,32,16,35,58,45,44,35,176,1,84,88,185,0,0,64,0,27,185,64,0,0,0,89,138,176,1,84,88,185,0,0,64,0,27,185,64,0,0,0,89,176,125,43,45,44,138,138,8,13,138,176,1,84,88,185,0,0,64,0,27,185,64,0,0,0,89,176,125,43,45,44,8,176,1,84,88,185,0,0,64,0,27,185,64,0,0,0,89,13,176,125,43,45,44,176,4,38,176,4,38,8,13,176,4,38,176,4,38,8,13,176,125,43,45,44,32,1,70,35,0,70,176,10,67,176,11,67,138,99,35,98,97,45,44,176,9,43,176,6,37,46,176,5,37,125,197,176,6,37,176,5,37,176,4,37,32,176,0,80,88,33,176,106,27,176,108,89,43,176,5,37,176,4,37,176,3,37,32,176,0,80,88,33,176,106,27,176,108,89,43,24,176,8,37,176,7,37,176,6,37,176,10,37,176,111,43,176,6,37,176,5,37,176,4,38,32,176,0,80,88,33,176,102,27,176,104,89,43,176,5,37,176,4,37,176,4,38,32,176,0,80,88,33,176,102,27,176,104,89,43,84,88,125,176,4,37,16,176,3,37,197,176,2,37,16,176,1,37,197,176,5,38,33,176,5,38,33,27,176,6,38,176,4,37,176,3,37,176,8,38,176,111,43,89,177,0,2,67,84,88,125,176,2,37,176,130,43,176,5,37,176,130,43,32,32,105,97,176,4,67,1,35,97,176,96,96,32,105,97,176,32,97,32,176,8,38,176,8,38,138,176,2,23,56,138,138,97,32,105,97,97,176,2,23,56,27,33,33,33,33,89,24,45,44,75,82,177,1,2,67,83,90,88,35,16,32,1,60,0,60,27,33,33,89,45,44,35,176,2,37,176,2,37,83,88,32,176,4,37,88,60,27,57,89,176,1,96,184,255,233,28,89,33,33,33,45,44,176,2,37,71,176,2,37,71,84,138,32,32,16,17,176,1,96,138,32,18,176,1,97,176,133,43,45,44,176,4,37,71,176,2,37,71,84,35,32,18,176,1,97,35,32,176,6,38,32,32,16,17,176,1,96,176,6,38,176,133,43,138,138,176,133,43,45,44,176,2,67,84,88,12,2,138,75,83,176,4,38,75,81,90,88,10,56,27,10,33,33,89,27,33,33,33,33,89,45,44,176,152,43,88,12,2,138,75,83,176,4,38,75,81,90,88,10,56,27,10,33,33,89,27,33,33,33,33,89,45,44,32,176,2,67,84,176,1,35,176,95,35,120,33,177,0,2,67,176,86,35,121,33,176,2,67,35,176,32,32,92,88,33,33,33,177,0,71,28,89,138,138,32,138,32,138,35,184,16,0,99,86,88,184,16,0,99,86,88,33,33,33,177,1,44,28,89,27,33,89,176,128,98,32,92,88,33,33,33,177,0,27,28,89,35,176,128,98,32,92,88,33,33,33,177,0,12,28,89,138,176,1,97,184,255,179,28,35,33,45,44,32,176,2,67,84,176,1,35,176,123,35,120,33,177,0,2,67,176,114,35,121,33,177,0,2,67,138,176,32,32,92,88,33,33,33,176,99,28,89,138,138,32,138,32,138,35,184,16,0,99,86,88,184,16,0,99,86,88,176,4,38,176,1,91,176,4,38,176,4,38,176,4,38,27,33,33,33,33,177,54,0,35,28,89,27,33,89,176,4,38,35,176,128,98,32,92,88,138,92,138,90,35,33,35,33,176,29,28,89,138,176,128,98,32,92,88,33,33,35,33,176,14,28,89,176,4,38,176,1,97,184,255,152,28,35,33,45,0,0,1,0,0,0,16,0,2,0,1,0,20,0,6,0,8,119,103,104,116,0,200,0,0,1,144,0,0,2,188,0,0,0,0,1,0,1,1,0,0,0,200,0,0,1,2,0,0,1,44,0,0,1,3,0,0,1,94,0,0,1,4,0,0,1,144,0,0,1,5,0,0,2,88,0,0,1,6,0,0,2,188,0,0,0,1,0,3,0,9,0,10,0,50,0,15,255,255,0,10,0,4,0,128,0,0,4,48,5,140,0,3,0,7,0,11,0,15,0,29,64,16,13,12,106,13,4,5,106,4,9,1,2,114,8,0,8,114,0,43,50,43,50,47,43,47,43,48,49,33,17,51,17,33,53,33,21,33,17,51,17,3,53,33,21,3,92,212,252,80,3,176,252,80,212,212,3,176,5,140,250,116,190,190,5,140,250,116,4,206,190,190,0,2,0,45,0,0,4,131,5,140,0,7,0,11,0,29,64,15,8,9,106,8,8,0,5,4,1,2,114,4,0,8,114,0,43,50,43,18,57,18,57,47,43,48,49,51,1,33,1,35,1,35,1,3,53,33,21,45,1,154,1,34,1,154,210,254,176,18,254,176,20,2,208,5,140,250,116,4,224,251,32,1,90,190,190,0,255,255,0,45,0,0,4,131,7,38,2,38,0,1,0,0,1,6,6,63,0,0,0,11,182,2,12,1,1,1,160,86,0,43,52,0,255,255,0,45,0,0,4,131,7,68,2,38,0,1,0,0,1,6,6,67,0,0,0,11,182,2,12,1,1,1,150,86,0,43,52,0,255,255,0,45,0,0,4,131,8,104,2,38,0,1,0,0,0,38,6,67,0,0,1,7,6,63,0,0,1,66,0,21,64,14,3,26,15,1,1,42,86,2,12,1,1,1,150,86,0,43,52,43,52,0,255,255,0,45,254,92,4,131,7,68,2,38,0,1,0,0,0,38,6,41,0,0,1,6,6,67,0,0,0,24,64,12,3,24,1,1,1,150,86,2,18,4,1,1,185,255,104,0,86,0,43,52,43,52,255,255,0,45,0,0,4,131,8,104,2,38,0,1,0,0,0,38,6,67,0,0,1,7,6,62,0,0,1,66,0,21,64,14,3,26,15,1,1,42,86,2,12,1,1,1,150,86,0,43,52,43,52,0,255,255,0,45,0,0,4,131,8,178,2,38,0,1,0,0,0,38,6,67,0,0,1,7,6,71,0,0,1,66,0,23,180,3,26,22,1,0,184,255,247,183,86,2,12,1,1,1,150,86,0,43,52,43,52,0,255,255,0,45,0,0,4,131,8,164,2,38,0,1,0,0,0,38,6,67,0,0,1,7,6,69,0,10,1,66,0,21,64,14,3,26,15,1,0,28,86,2,12,1,1,1,150,86,0,43,52,43,52,0,255,255,0,45,0,0,4,131,7,48,2,38,0,1,0,0,1,6,6,66,0,0,0,11,182,2,12,1,1,1,160,86,0,43,52,0,255,255,0,45,0,0,4,131,7,48,2,38,0,1,0,0,1,6,6,65,0,0,0,11,182,2,16,1,1,1,160,86,0,43,52,0,255,255,0,45,0,0,5,42,8,30,2,38,0,1,0,0,0,38,6,65,0,0,1,7,6,63,1,95,0,248,0,21,64,14,3,20,17,1,0,43,86,2,16,1,1,1,160,86,0,43,52,43,52,0,255,255,0,45,254,92,4,131,7,48,2,38,0,1,0,0,0,38,6,41,0,0,1,6,6,65,0,0,0,24,64,12,3,28,1,1,1,160,86,2,18,4,1,1,185,255,104,0,86,0,43,52,43,52,255,255,0,45,0,0,4,131,8,30,2,38,0,1,0,0,0,38,6,65,0,0,1,7,6,62,1,95,0,248,0,21,64,14,3,20,17,1,0,43,86,2,16,1,1,1,160,86,0,43,52,43,52,0,255,255,0,45,0,0,4,162,8,104,2,38,0,1,0,0,0,38,6,65,0,0,1,7,6,71,1,95,0,248,0,23,180,3,20,17,1,0,184,255,248,183,86,2,16,1,1,1,160,86,0,43,52,43,52,0,255,255,0,45,0,0,4,131,8,170,2,38,0,1,0,0,0,38,6,65,0,0,1,7,6,69,0,10,1,72,0,21,64,14,3,20,13,1,1,54,86,2,16,1,1,1,160,86,0,43,52,43,52,0,255,255,0,45,0,0,4,131,7,56,2,38,0,1,0,0,1,6,6,60,0,0,0,13,183,3,2,12,1,1,1,160,86,0,43,52,52,0,255,255,0,45,254,92,4,131,5,140,2,38,0,1,0,0,1,6,6,41,0,0,0,14,180,2,18,4,1,1,185,255,104,0,86,0,43,52,255,255,0,45,0,0,4,131,7,38,2,38,0,1,0,0,1,6,6,62,0,0,0,11,182,2,12,1,1,1,160,86,0,43,52,0,255,255,0,45,0,0,4,131,7,112,2,38,0,1,0,0,1,6,6,71,0,0,0,11,182,2,12,1,1,1,109,86,0,43,52,0,255,255,0,45,0,0,4,131,6,232,2,38,0,1,0,0,1,6,6,70,0,0,0,11,182,2,12,1,1,1,160,86,0,43,52,0,0,3,0,45,254,88,4,131,5,140,0,19,0,27,0,31,0,47,64,26,9,6,28,29,106,28,28,24,26,20,21,2,114,24,6,6,20,0,14,106,20,0,105,20,8,114,0,43,43,43,17,51,17,51,43,17,57,17,57,47,43,17,51,48,49,1,34,38,53,52,54,55,55,23,23,34,6,21,20,51,50,55,7,6,6,1,1,33,1,35,1,35,1,3,53,33,21,3,250,115,125,88,79,17,170,20,106,118,116,35,47,18,23,47,252,31,1,154,1,34,1,154,210,254,176,18,254,176,20,2,208,254,88,111,101,81,111,20,50,18,32,82,76,98,11,170,4,5,1,168,5,140,250,116,4,224,251,32,1,90,190,190,255,255,0,45,0,0,4,131,7,108,2,38,0,1,0,0,1,6,6,68,0,0,0,13,183,3,2,12,1,1,1,68,86,0,43,52,52,0,255,255,0,45,0,0,4,131,8,22,0,39,6,63,0,0,0,240,3,6,0,22,0,0,0,14,180,0,0,22,0,0,185,255,176,0,86,0,43,52,255,255,0,45,0,0,4,131,7,98,2,38,0,1,0,0,1,6,6,69,10,0,0,11,182,2,12,1,1,1,146,86,0,43,52,0,0,6,0,42,0,0,4,76,5,140,0,5,0,9,0,13,0,17,0,21,0,25,0,53,64,31,23,22,105,23,4,106,23,1,7,6,106,18,19,106,7,18,7,18,0,15,1,2,114,10,11,106,10,14,0,8,114,0,43,50,50,43,43,50,17,57,57,47,47,43,43,17,51,43,43,48,49,51,1,33,21,35,1,53,53,33,21,7,53,33,21,33,17,51,17,3,53,33,21,1,53,33,21,42,1,144,1,19,134,254,161,1,214,102,1,244,254,12,180,180,1,184,254,72,1,244,5,140,172,251,32,246,165,165,246,180,180,5,140,250,116,2,109,180,180,2,107,180,180,0,255,255,0,42,0,0,4,76,7,38,2,38,0,25,0,0,1,6,6,63,40,0,0,11,182,6,26,1,1,1,160,86,0,43,52,0,0,4,0,160,0,0,4,110,5,140,0,17,0,21,0,25,0,43,0,45,64,26,36,35,106,36,19,26,10,22,3,9,27,105,23,9,9,18,19,2,114,0,1,106,0,18,8,114,0,43,50,43,43,17,57,47,57,43,23,57,17,51,43,48,49,33,53,33,50,54,53,52,38,35,33,39,33,50,22,21,20,6,35,33,17,51,17,3,53,33,21,37,53,51,50,54,53,52,38,35,35,39,33,50,22,21,20,6,35,1,90,1,44,132,146,152,140,254,230,24,1,100,216,236,224,206,253,224,200,82,1,160,254,164,240,113,125,131,121,222,24,1,0,216,236,224,206,190,121,109,112,123,91,186,170,186,204,5,140,250,116,2,186,98,98,56,91,101,94,92,98,190,187,173,147,159,0,1,0,96,255,236,4,125,5,160,0,21,0,27,64,15,8,9,0,5,12,106,5,3,114,0,17,106,0,9,114,0,43,43,43,43,18,57,57,48,49,5,32,17,16,0,33,50,22,23,7,38,38,35,34,2,17,16,33,50,55,23,6,2,246,253,106,1,78,1,48,147,218,50,148,45,139,81,193,233,1,226,145,141,46,174,20,2,220,1,91,1,125,93,86,147,68,74,254,234,255,0,253,210,60,176,68,0,255,255,0,96,255,236,4,125,7,38,2,38,0,28,0,0,1,6,6,63,105,0,0,11,182,1,22,5,1,1,140,86,0,43,52,0,255,255,0,96,255,236,4,125,7,48,2,38,0,28,0,0,1,6,6,66,105,0,0,11,182,1,22,5,1,1,140,86,0,43,52,0,255,255,0,96,254,32,4,125,5,160,2,38,0,28,0,0,1,6,6,43,0,0,0,11,182,1,31,0,0,0,15,86,0,43,52,0,255,255,0,96,255,236,4,125,7,48,2,38,0,28,0,0,1,6,6,65,105,0,0,11,182,1,26,5,1,1,140,86,0,43,52,0,255,255,0,96,255,236,4,125,7,56,2,38,0,28,0,0,1,6,6,61,105,0,0,11,182,1,22,5,1,1,140,86,0,43,52,0,0,2,0,160,0,0,4,130,5,140,0,15,0,19,0,27,64,15,0,1,106,0,16,10,9,106,10,17,2,114,16,8,114,0,43,43,50,43,17,51,43,48,49,33,53,51,50,54,53,16,2,35,35,39,51,32,17,16,33,33,17,51,17,1,90,158,219,221,221,219,154,24,178,2,138,253,118,254,168,200,190,250,250,1,15,1,13,190,253,38,253,78,5,140,250,116,0,3,0,42,0,0,4,130,5,140,0,3,0,19,0,23,0,39,64,22,4,5,106,4,20,0,1,106,0,0,20,21,14,13,106,14,21,2,114,20,8,114,0,43,43,50,43,17,18,57,47,43,17,51,43,48,49,19,53,33,21,1,53,51,50,54,53,16,2,35,35,39,51,32,17,16,33,33,17,51,17,42,2,127,254,177,158,219,221,221,219,154,24,178,2,138,253,118,254,168,200,2,100,190,190,253,156,190,250,250,1,15,1,13,190,253,38,253,78,5,140,250,116,0,255,255,0,160,0,0,4,130,7,48,2,38,0,34,0,0,1,6,6,66,206,0,0,11,182,2,20,10,1,1,160,86,0,43,52,0,255,255,0,42,0,0,4,130,5,140,2,6,0,35,0,0,0,4,0,160,0,0,4,76,5,140,0,3,0,7,0,11,0,15,0,39,64,22,4,5,106,4,0,8,9,106,8,8,0,1,13,12,106,13,1,2,114,0,8,114,0,43,43,50,43,17,18,57,47,43,17,51,43,48,49,51,17,51,17,35,53,33,21,1,53,33,21,1,53,33,21,160,200,200,3,172,252,84,2,248,253,8,3,172,5,140,250,116,190,190,2,104,190,190,2,102,190,190,255,255,0,160,0,0,4,76,7,38,2,38,0,38,0,0,1,6,6,63,30,0,0,11,182,4,16,1,1,1,160,86,0,43,52,0,255,255,0,160,0,0,4,76,7,68,2,38,0,38,0,0,1,6,6,67,30,0,0,11,182,4,16,1,1,1,150,86,0,43,52,0,255,255,0,160,0,0,4,76,7,48,2,38,0,38,0,0,1,6,6,66,30,0,0,11,182,4,16,1,1,1,160,86,0,43,52,0,255,255,0,160,0,0,4,76,7,48,2,38,0,38,0,0,1,6,6,65,30,0,0,11,182,4,20,1,1,1,160,86,0,43,52,0,255,255,0,160,0,0,5,72,8,30,2,38,0,38,0,0,0,38,6,65,30,0,1,7,6,63,1,125,0,248,0,21,64,14,5,24,21,1,0,43,86,4,20,1,1,1,160,86,0,43,52,43,52,0,255,255,0,160,254,92,4,76,7,48,2,38,0,38,0,0,0,38,6,41,30,0,1,6,6,65,30,0,0,24,64,12,5,32,1,1,1,160,86,4,22,4,1,1,185,255,104,0,86,0,43,52,43,52,255,255,0,160,0,0,4,98,8,30,2,38,0,38,0,0,0,38,6,65,30,0,1,7,6,62,1,125,0,248,0,21,64,14,5,24,21,1,0,43,86,4,20,1,1,1,160,86,0,43,52,43,52,0,255,255,0,160,0,0,4,192,8,104,2,38,0,38,0,0,0,38,6,65,30,0,1,7,6,71,1,125,0,248,0,23,180,5,24,21,1,0,184,255,248,183,86,4,20,1,1,1,160,86,0,43,52,43,52,0,255,255,0,160,0,0,4,76,8,170,2,38,0,38,0,0,0,38,6,65,30,0,1,7,6,69,0,40,1,72,0,21,64,14,5,24,17,1,1,54,86,4,20,1,1,1,160,86,0,43,52,43,52,0,255,255,0,160,0,0,4,76,7,56,2,38,0,38,0,0,1,6,6,60,30,0,0,13,183,5,4,16,1,1,1,160,86,0,43,52,52,0,255,255,0,160,0,0,4,76,7,56,2,38,0,38,0,0,1,6,6,61,30,0,0,11,182,4,16,1,1,1,160,86,0,43,52,0,255,255,0,160,254,92,4,76,5,140,2,38,0,38,0,0,1,6,6,41,30,0,0,14,180,4,22,4,1,1,185,255,104,0,86,0,43,52,255,255,0,160,0,0,4,76,7,38,2,38,0,38,0,0,1,6,6,62,30,0,0,11,182,4,16,1,1,1,160,86,0,43,52,0,255,255,0,160,0,0,4,76,7,112,2,38,0,38,0,0,1,6,6,71,30,0,0,11,182,4,16,1,1,1,109,86,0,43,52,0,255,255,0,160,0,0,4,76,6,232,2,38,0,38,0,0,1,6,6,70,30,0,0,11,182,4,16,1,1,1,160,86,0,43,52,0,0,5,0,160,254,88,4,76,5,140,0,20,0,24,0,28,0,32,0,36,0,53,64,31,30,30,22,7,26,9,21,30,29,106,34,33,106,34,22,2,114,25,26,106,25,21,0,15,106,21,0,105,21,8,114,0,43,43,43,17,51,43,43,50,43,43,17,51,18,57,18,57,47,48,49,1,34,38,53,52,54,55,53,55,23,34,6,21,20,22,51,50,55,7,6,6,1,17,51,17,35,53,33,21,1,53,33,21,1,53,33,21,3,198,115,125,59,55,240,20,106,118,61,55,35,47,18,23,47,252,198,200,200,3,172,252,84,2,248,253,8,3,172,254,88,111,101,74,100,18,50,2,32,88,80,42,46,11,170,4,5,1,168,5,140,250,116,190,190,2,104,190,190,2,102,190,190,0,0,1,0,128,255,236,4,101,5,160,0,46,0,39,64,22,41,38,15,13,106,4,3,15,15,0,30,21,106,30,9,114,0,7,106,0,3,114,0,43,43,43,43,18,57,47,57,57,43,57,57,48,49,1,50,22,23,7,38,38,35,34,6,21,20,22,23,7,35,34,6,21,20,22,51,50,54,54,55,23,14,2,35,34,38,38,53,52,54,54,55,7,53,23,38,38,53,52,54,2,178,163,220,52,148,44,148,94,162,141,208,242,22,150,148,182,177,156,82,118,113,72,46,64,120,143,99,168,245,133,118,191,109,17,17,193,169,238,5,160,93,86,147,70,72,114,84,106,104,8,188,123,114,118,133,10,25,23,174,26,30,12,102,187,125,117,160,83,2,54,117,56,27,176,127,155,192,0,255,255,0,150,0,0,4,46,5,140,2,6,2,52,0,0,255,255,0,160,0,0,4,76,7,98,2,38,0,38,0,0,1,6,6,69,40,0,0,11,182,4,16,1,1,1,146,86,0,43,52,0,0,1,0,64,255,236,4,48,5,140,0,29,0,37,64,21,16,21,19,18,106,15,22,14,23,106,14,0,19,3,114,0,7,106,0,9,114,0,43,43,43,18,57,43,57,57,43,50,57,48,49,5,32,39,55,30,2,51,50,54,53,52,38,35,35,39,1,7,33,53,33,21,1,53,22,4,21,20,6,6,2,34,254,216,186,144,59,103,110,71,147,166,209,191,135,20,2,10,1,253,91,3,85,254,50,252,1,20,128,236,20,171,141,46,56,26,128,113,128,139,124,1,243,61,186,201,254,76,43,4,218,195,130,193,106,0,0,3,0,160,0,0,4,76,5,140,0,3,0,7,0,11,0,31,64,17,4,5,106,4,4,0,1,9,8,106,9,1,2,114,0,8,114,0,43,43,50,43,17,18,57,47,43,48,49,51,17,51,17,3,53,33,21,1,53,33,21,160,200,200,2,248,253,8,3,172,5,140,250,116,2,44,190,190,2,162,190,190,0,3,0,96,255,236,4,126,5,160,0,25,0,29,0,33,0,39,64,22,27,30,31,106,10,6,30,30,0,6,13,106,6,3,114,26,0,19,106,0,9,114,0,43,43,57,43,43,18,57,47,18,57,43,50,48,49,5,32,0,17,16,0,33,50,22,23,7,38,38,35,34,2,21,16,18,51,50,54,55,23,6,6,55,17,51,17,1,53,33,21,2,220,254,194,254,194,1,74,1,42,149,224,53,149,46,139,80,202,224,224,222,95,145,46,78,42,211,63,190,254,32,1,218,20,1,110,1,110,1,91,1,125,93,85,148,68,74,254,233,255,254,233,254,233,37,13,174,13,47,60,2,158,253,98,1,224,190,190,0,255,255,0,96,255,236,4,126,7,68,2,38,0,60,0,0,1,6,6,67,95,0,0,11,182,3,34,6,1,1,130,86,0,43,52,0,255,255,0,96,255,236,4,126,7,48,2,38,0,60,0,0,1,6,6,66,95,0,0,11,182,3,34,6,1,1,140,86,0,43,52,0,255,255,0,96,255,236,4,126,7,48,2,38,0,60,0,0,1,6,6,65,95,0,0,11,182,3,38,6,1,1,140,86,0,43,52,0,255,255,0,96,254,32,4,126,5,160,2,38,0,60,0,0,1,6,6,42,115,0,0,14,180,3,35,0,1,1,185,255,136,0,86,0,43,52,255,255,0,96,255,236,4,126,7,56,2,38,0,60,0,0,1,6,6,61,95,0,0,11,182,3,34,6,1,1,140,86,0,43,52,0,0,3,0,140,0,0,4,36,5,140,0,3,0,7,0,11,0,31,64,16,0,4,1,5,8,9,106,8,8,4,5,2,114,4,8,114,0,43,43,17,57,47,43,17,51,17,51,48,49,33,17,51,17,33,17,51,17,3,53,33,21,3,92,200,252,104,200,158,3,73,5,140,250,116,5,140,250,116,2,100,190,190,0,4,0,62,0,0,4,114,5,140,0,3,0,7,0,11,0,15,0,35,64,20,0,1,106,13,0,105,12,13,106,12,12,8,5,9,2,114,4,8,8,114,0,43,50,43,50,17,57,47,43,43,43,48,49,19,53,33,21,1,17,51,17,33,17,51,17,3,53,33,21,62,4,52,254,234,200,252,104,200,158,3,73,3,234,190,190,252,22,5,140,250,116,5,140,250,116,2,100,190,190,0,255,255,0,140,0,0,4,36,7,48,2,38,0,66,0,0,1,6,6,66,0,0,0,11,182,3,12,1,1,1,160,86,0,43,52,0,255,255,0,140,0,0,4,36,7,48,2,38,0,66,0,0,1,6,6,65,0,0,0,11,182,3,16,1,1,1,160,86,0,43,52,0,0,3,0,168,0,0,4,8,5,140,0,3,0,7,0,11,0,29,64,16,0,4,1,9,4,5,106,9,8,106,9,2,114,4,8,114,0,43,43,43,43,17,51,17,51,48,49,33,17,51,17,33,53,33,21,1,53,33,21,1,243,200,253,237,3,96,252,160,3,96,5,140,250,116,190,190,4,206,190,190,0,5,0,45,0,0,4,48,5,140,0,15,0,19,0,23,0,27,0,31,0,47,64,27,11,29,29,25,20,16,17,106,3,16,105,3,3,0,25,24,106,21,25,2,114,0,7,106,0,8,114,0,43,43,43,50,43,18,57,47,43,43,51,17,51,17,51,48,49,33,34,38,53,51,20,22,51,50,54,53,17,51,17,20,6,1,53,33,21,33,17,51,17,1,53,33,21,51,53,33,21,2,112,205,203,200,107,106,122,121,200,223,252,220,2,32,254,144,190,254,146,2,12,111,1,30,188,188,98,98,137,139,3,196,252,60,229,227,2,5,190,190,3,135,252,121,2,201,190,190,190,190,255,255,0,168,0,0,4,8,7,38,2,38,0,70,0,0,1,6,6,63,0,0,0,11,182,3,12,1,1,1,160,86,0,43,52,0,255,255,0,168,0,0,4,8,7,68,2,38,0,70,0,0,1,6,6,67,0,0,0,11,182,3,12,1,1,1,150,86,0,43,52,0,255,255,0,168,0,0,4,8,7,48,2,38,0,70,0,0,1,6,6,65,0,0,0,11,182,3,16,1,1,1,160,86,0,43,52,0,255,255,0,168,0,0,4,8,7,56,2,38,0,70,0,0,1,6,6,60,0,0,0,13,183,4,3,12,1,1,1,160,86,0,43,52,52,0,255,255,0,168,0,0,4,8,7,56,2,38,0,70,0,0,1,6,6,61,0,0,0,11,182,3,12,1,1,1,160,86,0,43,52,0,255,255,0,168,254,92,4,8,5,140,2,38,0,70,0,0,1,6,6,41,0,0,0,14,180,3,18,0,1,1,185,255,104,0,86,0,43,52,255,255,0,168,0,0,4,8,7,38,2,38,0,70,0,0,1,6,6,62,0,0,0,11,182,3,12,1,1,1,160,86,0,43,52,0,255,255,0,168,0,0,4,8,7,112,2,38,0,70,0,0,1,6,6,71,0,0,0,11,182,3,12,1,1,1,109,86,0,43,52,0,255,255,0,168,0,0,4,8,6,232,2,38,0,70,0,0,1,6,6,70,0,0,0,11,182,3,12,9,1,1,160,86,0,43,52,0,0,4,0,168,254,88,4,8,5,140,0,20,0,24,0,28,0,32,0,41,64,24,30,29,106,22,30,2,114,7,25,26,106,6,25,0,15,106,25,0,105,21,9,25,8,114,0,43,50,50,43,43,18,57,43,57,43,50,43,48,49,1,34,38,53,52,54,55,53,55,23,34,6,21,20,22,51,50,55,7,6,6,3,17,51,17,33,53,33,21,1,53,33,21,2,124,115,125,59,55,240,20,106,118,61,55,35,47,18,23,47,157,200,253,237,3,96,252,160,3,96,254,88,111,101,74,100,18,50,2,32,88,80,42,46,11,170,4,5,1,168,5,140,250,116,190,190,4,206,190,190,0,255,255,0,168,0,0,4,8,7,98,2,38,0,70,0,0,1,6,6,69,10,0,0,11,182,3,12,9,1,1,146,86,0,43,52,0,0,2,0,96,255,236,4,48,5,140,0,15,0,19,0,29,64,16,4,4,0,17,16,106,12,17,2,114,0,7,106,0,9,114,0,43,43,43,50,43,18,57,47,48,49,5,34,2,53,51,20,22,51,50,54,53,17,51,17,20,0,1,53,33,21,2,72,234,254,200,153,140,136,147,200,254,254,254,198,1,210,20,1,5,235,150,166,165,151,3,176,252,80,236,254,252,4,226,190,190,255,255,0,96,255,236,4,107,7,48,2,38,0,83,0,0,1,7,6,65,0,180,0,0,0,11,182,2,24,11,1,1,160,86,0,43,52,0,0,3,0,160,0,0,4,148,5,140,0,11,0,15,0,19,0,33,64,17,0,1,106,18,17,13,0,0,12,6,13,2,114,16,12,8,114,0,43,50,43,50,18,57,47,18,57,57,43,48,49,1,55,50,54,54,18,53,51,20,2,2,4,1,17,51,17,33,1,55,1,1,30,18,154,224,145,71,206,110,210,254,208,254,192,200,2,58,254,152,180,1,166,1,196,198,129,219,1,19,147,189,254,164,254,239,158,254,60,5,140,250,116,2,180,102,252,230,255,255,0,160,254,32,4,148,5,140,2,38,0,85,0,0,1,6,6,42,40,0,0,14,180,3,21,12,1,1,185,255,116,0,86,0,43,52,0,2,0,160,0,0,4,76,5,140,0,3,0,7,0,21,64,11,4,5,106,4,0,1,2,114,0,8,114,0,43,43,17,51,43,48,49,51,17,51,17,35,53,33,21,160,200,200,3,172,5,140,250,116,190,190,255,255,0,129,0,0,4,76,7,38,2,38,0,87,0,0,1,7,6,63,254,172,0,0,0,11,182,2,8,1,1,1,160,86,0,43,52,0,0,3,0,160,0,0,4,76,6,32,0,3,0,7,0,11,0,27,64,16,1,0,106,5,1,105,5,2,114,8,9,106,8,4,8,114,0,43,50,43,43,43,43,48,49,1,19,51,3,1,17,51,17,35,53,33,21,2,250,50,212,90,252,250,200,200,3,172,4,164,1,124,254,132,251,92,5,140,250,116,190,190,255,255,0,160,254,32,4,76,5,140,2,38,0,87,0,0,1,6,6,42,20,0,0,14,180,2,9,4,1,1,185,255,116,0,86,0,43,52,255,255,0,160,0,0,4,76,5,140,2,38,0,87,0,0,1,7,2,174,0,200,1,64,0,14,180,2,14,1,2,0,185,255,14,0,86,0,43,52,0,3,0,58,0,0,4,76,5,140,0,3,0,7,0,11,0,33,64,19,0,1,106,2,3,106,0,2,11,9,2,114,11,4,5,106,4,8,114,0,43,43,51,43,17,57,57,43,43,48,49,19,53,1,21,1,53,33,21,33,17,51,17,58,3,38,253,164,3,72,252,184,200,1,199,185,1,164,185,252,149,190,190,5,140,250,116,0,0,4,0,128,0,0,4,48,5,140,0,7,0,11,0,19,0,23,0,41,64,22,5,9,14,106,17,12,1,106,0,12,12,20,21,15,3,9,2,114,20,8,8,114,0,43,50,43,50,50,50,17,57,47,51,43,50,43,50,48,49,1,55,51,19,51,21,35,3,1,17,51,17,19,3,35,53,51,19,51,23,1,17,51,17,2,54,30,12,162,142,58,162,253,204,192,188,162,58,142,162,8,20,1,4,192,2,68,230,2,98,252,253,180,253,188,5,140,250,116,2,68,2,76,252,253,158,230,253,188,5,140,250,116,0,3,0,148,0,0,4,28,5,140,0,7,0,11,0,15,0,27,64,13,2,5,8,13,4,9,2,114,12,7,8,8,114,0,43,50,50,43,50,50,18,57,57,48,49,33,1,35,17,51,1,51,17,33,17,51,17,33,17,51,17,3,32,254,72,92,132,1,184,50,253,26,192,2,8,192,4,56,1,84,251,200,254,172,5,140,250,116,5,140,250,116,255,255,0,148,0,0,4,28,7,38,2,38,0,94,0,0,1,6,6,63,0,0,0,11,182,3,16,9,1,1,160,86,0,43,52,0,255,255,0,148,0,0,4,28,7,48,2,38,0,94,0,0,1,6,6,66,0,0,0,11,182,3,16,13,1,1,160,86,0,43,52,0,255,255,0,148,254,32,4,28,5,140,2,38,0,94,0,0,1,6,6,42,0,0,0,14,180,3,17,8,1,1,185,255,116,0,86,0,43,52,0,4,0,148,254,32,4,28,5,140,0,12,0,20,0,24,0,28,0,47,64,27,6,21,18,26,17,22,15,106,22,2,114,25,13,13,21,0,1,106,21,0,105,21,18,105,21,8,114,0,43,43,43,43,17,51,17,51,43,43,51,51,17,18,57,48,49,1,39,55,54,54,53,17,51,17,20,6,6,7,19,1,35,17,51,1,51,17,33,17,51,17,33,17,51,17,2,81,10,120,78,78,193,77,147,105,77,254,72,92,132,1,184,50,253,26,192,2,8,192,254,32,168,18,12,100,94,1,16,254,232,108,160,94,10,1,212,4,56,1,84,251,200,254,172,5,140,250,116,5,140,250,116,0,0,4,255,128,254,32,4,28,5,140,0,12,0,20,0,24,0,28,0,37,64,22,7,28,18,105,0,1,106,28,0,105,24,13,28,8,114,22,15,106,22,26,2,114,0,43,50,43,43,50,50,43,43,43,57,48,49,3,39,55,54,54,53,17,51,17,20,6,6,7,1,1,35,17,51,1,51,17,33,17,51,17,33,17,51,17,118,10,120,78,78,193,77,147,105,3,20,254,72,92,132,1,184,50,253,26,192,2,8,192,254,32,168,18,9,103,94,1,16,254,232,110,161,93,8,1,212,4,56,1,84,251,200,254,172,5,140,250,116,5,140,250,116,0,255,255,0,148,0,0,4,28,7,98,2,38,0,94,0,0,1,6,6,69,10,0,0,11,182,3,16,9,1,1,146,86,0,43,52,0,0,2,0,76,255,236,4,100,5,160,0,7,0,15,0,21,64,12,0,8,106,4,12,106,4,3,114,0,9,114,0,43,43,43,43,48,49,5,32,17,16,33,32,17,16,37,32,17,16,33,32,17,16,2,88,253,244,2,12,2,12,253,244,1,58,254,198,254,198,20,2,208,2,228,253,28,253,48,184,2,24,2,44,253,212,253,232,0,255,255,0,76,255,236,4,100,7,38,2,38,0,101,0,0,1,6,6,63,0,0,0,11,182,2,16,4,1,1,140,86,0,43,52,0,255,255,0,76,255,236,4,100,7,68,2,38,0,101,0,0,1,6,6,67,0,0,0,11,182,2,16,4,1,1,130,86,0,43,52,0,255,255,0,76,255,236,4,100,7,48,2,38,0,101,0,0,1,6,6,65,0,0,0,11,182,2,20,4,1,1,140,86,0,43,52,0,255,255,0,76,255,236,5,42,8,30,2,38,0,101,0,0,0,38,6,65,0,0,1,7,6,63,1,95,0,248,0,21,64,14,3,24,21,1,0,43,86,2,20,4,1,1,140,86,0,43,52,43,52,0,255,255,0,76,254,92,4,100,7,48,2,38,0,101,0,0,0,38,6,41,0,0,1,6,6,65,0,0,0,24,64,12,3,32,4,1,1,140,86,2,22,0,1,1,185,255,124,0,86,0,43,52,43,52,255,255,0,76,255,236,4,100,8,30,2,38,0,101,0,0,0,38,6,65,0,0,1,7,6,62,1,95,0,248,0,21,64,14,3,24,21,1,0,43,86,2,20,4,1,1,140,86,0,43,52,43,52,0,255,255,0,76,255,236,4,162,8,104,2,38,0,101,0,0,0,38,6,65,0,0,1,7,6,71,1,95,0,248,0,23,180,3,24,21,1,0,184,255,248,183,86,2,20,4,1,1,140,86,0,43,52,43,52,0,255,255,0,76,255,236,4,100,8,170,2,38,0,101,0,0,0,38,6,65,0,0,1,7,6,69,0,10,1,72,0,21,64,14,3,24,17,1,1,54,86,2,20,4,1,1,140,86,0,43,52,43,52,0,255,255,0,76,255,236,4,100,7,56,2,38,0,101,0,0,1,6,6,60,0,0,0,13,183,3,2,16,4,1,1,140,86,0,43,52,52,0,255,255,0,76,254,92,4,100,5,160,2,38,0,101,0,0,1,6,6,41,0,0,0,14,180,2,22,0,1,1,185,255,124,0,86,0,43,52,255,255,0,76,255,236,4,100,7,38,2,38,0,101,0,0,1,6,6,62,0,0,0,11,182,2,16,4,1,1,140,86,0,43,52,0,255,255,0,76,255,236,4,100,7,112,2,38,0,101,0,0,1,6,6,71,0,0,0,11,182,2,16,4,1,1,89,86,0,43,52,0,255,255,0,76,255,236,4,224,6,117,2,38,0,101,0,0,1,7,6,72,1,144,0,0,0,11,182,2,21,4,0,0,213,86,0,43,52,0,255,255,0,76,255,236,4,224,7,38,2,38,0,114,0,0,1,6,6,63,0,0,0,11,182,3,26,4,1,1,140,86,0,43,52,0,255,255,0,76,254,92,4,224,6,117,2,38,0,114,0,0,1,6,6,41,0,0,0,14,180,3,32,0,1,1,185,255,124,0,86,0,43,52,255,255,0,76,255,236,4,224,7,38,2,38,0,114,0,0,1,6,6,62,0,0,0,11,182,3,26,4,1,1,140,86,0,43,52,0,255,255,0,76,255,236,4,224,7,112,2,38,0,114,0,0,1,6,6,71,0,0,0,11,182,3,26,4,1,1,89,86,0,43,52,0,255,255,0,76,255,236,4,224,7,98,2,38,0,114,0,0,1,6,6,69,10,0,0,11,182,3,26,4,1,1,126,86,0,43,52,0,255,255,0,76,255,236,4,100,7,38,2,38,0,101,0,0,1,6,6,64,0,0,0,13,183,3,2,16,4,1,1,140,86,0,43,52,52,0,255,255,0,76,255,236,4,100,6,232,2,38,0,101,0,0,1,6,6,70,0,0,0,11,182,2,16,4,1,1,140,86,0,43,52,0,0,3,0,76,254,88,4,100,5,160,0,20,0,28,0,36,0,39,64,24,25,33,106,25,3,114,7,6,8,3,21,29,105,5,21,0,15,106,21,0,105,21,9,114,0,43,43,43,18,57,43,23,57,43,43,48,49,1,34,38,53,52,55,53,55,23,14,2,21,20,22,51,50,55,7,6,6,3,32,17,16,33,32,17,16,37,32,17,16,33,32,17,16,2,146,115,125,114,210,44,49,101,68,46,70,37,45,18,25,45,78,253,244,2,12,2,12,253,244,1,58,254,198,254,198,254,88,101,91,154,38,70,10,32,17,38,65,56,26,62,11,170,4,5,1,148,2,208,2,228,253,28,253,48,184,2,24,2,44,253,212,253,232,0,0,1,0,17,255,236,4,80,5,160,0,24,0,27,64,15,4,3,0,19,14,106,19,3,114,0,8,106,0,9,114,0,43,43,43,43,18,57,57,48,49,5,34,38,39,55,30,2,51,50,18,53,16,2,35,34,7,39,54,51,32,0,17,16,0,1,220,135,235,89,144,59,99,103,65,194,216,240,236,148,141,46,174,195,1,64,1,73,254,198,20,86,85,141,49,56,23,1,32,253,1,7,1,32,60,176,68,254,138,254,159,254,169,254,122,0,0,3,0,66,255,122,4,100,5,252,0,3,0,11,0,19,0,35,64,19,3,1,0,2,8,8,16,106,8,3,114,0,4,4,12,106,4,9,114,0,43,43,16,206,43,43,16,206,17,57,57,48,49,23,39,1,23,1,32,17,16,33,32,17,16,37,32,17,16,33,32,17,16,201,135,3,145,135,253,254,253,244,2,12,2,12,253,244,1,58,254,198,254,198,134,75,6,55,75,250,59,2,208,2,228,253,28,253,48,184,2,24,2,44,253,212,253,232,255,255,0,66,255,122,4,100,7,38,2,38,0,124,0,0,1,6,6,63,0,0,0,11,182,3,20,8,1,1,140,86,0,43,52,0,255,255,0,76,255,236,4,100,7,98,2,38,0,101,0,0,1,6,6,69,10,0,0,11,182,2,16,4,1,1,126,86,0,43,52,0,0,5,0,76,255,236,4,76,5,160,0,14,0,18,0,29,0,33,0,37,0,51,64,32,35,34,106,10,35,2,114,15,16,106,12,15,8,114,30,31,106,30,30,0,6,24,106,6,3,114,0,19,106,0,9,114,0,43,43,43,43,18,57,47,43,43,50,43,43,50,43,48,49,5,34,2,17,16,18,51,50,22,51,51,17,35,34,6,55,53,33,21,37,50,55,17,38,35,34,2,17,16,18,1,53,33,21,1,53,33,21,2,8,211,233,233,211,54,80,46,80,80,35,89,74,1,194,253,198,40,30,35,45,112,122,128,1,0,1,114,254,112,1,204,20,1,121,1,87,1,97,1,131,20,250,116,20,20,180,180,164,6,4,40,22,254,221,254,247,255,0,254,232,1,201,180,180,2,107,180,180,0,0,2,0,160,0,0,4,96,5,140,0,17,0,21,0,31,64,17,0,1,106,0,0,18,19,10,9,106,10,19,2,114,18,8,114,0,43,43,50,43,17,18,57,47,43,48,49,1,53,51,50,54,53,52,38,35,35,53,51,32,0,21,20,0,33,1,17,51,17,1,80,242,158,174,174,158,238,238,1,3,1,27,254,229,254,253,254,94,200,1,184,190,158,142,143,157,190,254,255,233,234,255,0,254,72,5,140,250,116,0,0,2,0,160,0,0,4,96,5,140,0,17,0,21,0,35,64,19,0,1,106,0,0,18,19,10,9,106,10,10,18,19,2,114,18,8,114,0,43,43,17,57,47,43,17,18,57,47,43,48,49,37,53,51,50,54,53,52,38,35,35,53,51,32,0,21,20,0,33,5,17,51,17,1,80,242,158,174,174,158,238,238,1,2,1,28,254,228,254,254,254,94,200,220,190,158,142,144,156,190,255,0,234,234,255,0,220,5,140,250,116,0,0,3,0,76,254,52,4,100,5,160,0,11,0,19,0,27,0,31,64,19,16,24,106,16,3,114,5,12,20,105,0,9,106,12,0,105,12,9,114,0,43,43,43,43,57,43,43,48,49,1,34,38,53,53,51,21,20,22,51,51,7,1,32,17,16,33,32,17,16,37,32,17,16,33,32,17,16,3,162,216,218,198,118,118,102,20,254,100,253,244,2,12,2,12,253,244,1,58,254,198,254,198,254,52,220,220,82,84,129,129,180,1,184,2,208,2,228,253,28,253,48,184,2,24,2,44,253,212,253,232,0,3,0,140,0,0,4,118,5,140,0,17,0,21,0,25,0,35,64,19,10,9,106,10,19,23,0,1,106,0,0,18,19,2,114,22,18,8,114,0,43,50,43,17,57,47,43,57,17,51,43,48,49,1,53,33,50,54,53,52,38,35,33,39,33,50,22,21,20,6,35,1,17,51,17,33,1,51,1,1,70,1,46,119,133,133,119,254,214,24,1,66,221,241,241,221,254,24,200,2,50,254,194,220,1,82,2,28,190,126,114,125,135,190,224,206,214,236,253,228,5,140,250,116,2,156,253,100,255,255,0,140,0,0,4,118,7,38,2,38,0,131,0,0,1,6,6,63,216,0,0,11,182,3,26,10,1,1,160,86,0,43,52,0,255,255,0,140,0,0,4,118,7,48,2,38,0,131,0,0,1,6,6,66,216,0,0,11,182,3,26,10,1,1,160,86,0,43,52,0,255,255,0,140,254,32,4,118,5,140,2,38,0,131,0,0,1,6,6,42,10,0,0,14,180,3,27,18,1,1,185,255,116,0,86,0,43,52,0,1,0,129,255,236,4,37,5,160,0,39,0,36,64,24,10,37,13,14,34,33,17,30,24,23,10,0,20,27,106,20,3,114,0,7,106,0,9,114,0,43,43,43,43,18,23,57,48,49,5,34,38,39,55,22,22,51,50,54,53,52,38,39,39,38,38,53,52,54,51,50,22,23,7,38,38,35,34,6,21,20,22,23,23,22,22,21,20,6,2,39,121,211,90,26,110,205,97,140,136,67,63,246,145,155,224,205,143,220,102,140,88,153,83,103,113,74,72,208,158,164,251,20,39,39,202,47,49,98,100,66,92,28,112,66,186,138,186,204,84,95,142,72,65,99,97,69,87,34,98,74,186,146,193,193,255,255,0,129,255,236,4,37,7,38,2,38,0,135,0,0,1,6,6,63,20,0,0,11,182,1,40,20,1,1,140,86,0,43,52,0,255,255,0,129,255,236,4,37,7,48,2,38,0,135,0,0,1,6,6,66,20,0,0,11,182,1,40,20,1,1,140,86,0,43,52,0,255,255,0,129,254,32,4,37,5,160,2,38,0,135,0,0,1,6,6,43,191,0,0,11,182,1,49,0,0,0,15,86,0,43,52,0,255,255,0,129,255,236,4,37,7,48,2,38,0,135,0,0,1,6,6,65,20,0,0,11,182,1,44,20,1,1,140,86,0,43,52,0,255,255,0,129,254,32,4,37,5,160,2,38,0,135,0,0,1,6,6,42,10,0,0,14,180,1,41,0,1,1,185,255,136,0,86,0,43,52,0,2,0,140,255,236,4,133,5,160,0,15,0,38,0,40,64,25,32,33,29,106,33,8,31,7,4,4,16,22,106,16,9,114,15,8,114,4,11,106,4,3,114,0,43,43,43,43,43,18,23,57,43,57,48,49,51,17,16,54,33,50,22,23,7,38,38,35,38,6,21,17,5,34,39,55,22,22,51,50,54,53,52,38,39,39,1,51,1,39,22,22,21,20,4,140,245,1,15,128,223,97,171,70,137,70,166,150,1,65,120,82,26,45,101,46,127,139,116,106,175,1,77,226,254,218,28,179,195,254,252,3,162,1,13,241,84,86,140,60,60,1,153,168,252,94,20,23,187,8,10,136,124,96,142,34,50,2,4,254,89,29,31,225,174,222,244,0,0,2,0,76,255,236,4,100,5,160,0,22,0,26,0,31,64,18,0,10,106,23,24,106,23,23,0,19,14,106,19,3,114,0,9,114,0,43,43,43,18,57,47,43,43,48,49,5,32,17,52,54,55,23,6,21,16,33,32,17,16,33,34,7,39,54,51,32,17,16,1,53,33,21,2,88,253,244,2,2,209,3,1,58,1,58,254,98,163,141,28,156,176,2,112,251,236,3,173,20,2,188,31,59,28,16,49,53,253,252,2,24,2,44,39,177,46,253,28,253,48,2,116,190,190,0,0,2,0,80,0,0,4,96,5,140,0,3,0,7,0,19,64,10,2,5,4,106,5,2,114,0,8,114,0,43,43,43,51,48,49,33,17,51,17,1,53,33,21,1,244,200,253,148,4,16,5,140,250,116,4,206,190,190,0,3,0,80,0,0,4,96,5,140,0,3,0,7,0,11,0,31,64,17,6,9,0,1,106,0,0,4,9,8,106,9,2,114,4,8,114,0,43,43,43,18,57,47,43,17,51,48,49,19,53,33,21,1,17,51,17,1,53,33,21,192,3,48,254,4,200,253,148,4,16,2,75,190,190,253,181,5,140,250,116,4,206,190,190,0,255,255,0,80,0,0,4,96,7,48,2,38,0,143,0,0,1,6,6,66,0,0,0,11,182,2,8,1,1,1,160,86,0,43,52,0,255,255,0,80,254,32,4,96,5,140,2,38,0,143,0,0,1,6,6,43,176,0,0,14,180,2,17,0,1,0,185,255,251,0,86,0,43,52,255,255,0,80,254,32,4,96,5,140,2,38,0,143,0,0,1,6,6,42,251,0,0,14,180,2,9,0,1,1,185,255,116,0,86,0,43,52,0,1,0,140,255,236,4,36,5,140,0,15,0,21,64,11,12,3,0,8,106,3,2,114,0,9,114,0,43,43,43,17,51,48,49,5,32,17,17,51,17,20,22,51,32,17,17,51,17,20,6,2,84,254,56,200,125,135,1,4,200,236,20,1,220,3,196,252,60,142,144,1,30,3,196,252,60,238,238,0,255,255,0,140,255,236,4,36,7,38,2,38,0,148,0,0,1,6,6,63,0,0,0,11,182,1,16,3,1,1,160,86,0,43,52,0,255,255,0,140,255,236,4,36,7,68,2,38,0,148,0,0,1,6,6,67,0,0,0,11,182,1,16,11,1,1,150,86,0,43,52,0,255,255,0,140,255,236,4,36,7,48,2,38,0,148,0,0,1,6,6,65,0,0,0,11,182,1,20,11,1,1,160,86,0,43,52,0,255,255,0,140,255,236,4,36,7,56,2,38,0,148,0,0,1,6,6,60,0,0,0,13,183,2,1,16,11,1,1,160,86,0,43,52,52,0,255,255,0,140,254,92,4,36,5,140,2,38,0,148,0,0,1,6,6,41,0,0,0,14,180,1,22,0,1,1,185,255,124,0,86,0,43,52,255,255,0,140,255,236,4,36,7,38,2,38,0,148,0,0,1,6,6,62,0,0,0,11,182,1,16,3,1,1,160,86,0,43,52,0,255,255,0,140,255,236,4,36,7,112,2,38,0,148,0,0,1,6,6,71,0,0,0,11,182,1,16,11,1,1,109,86,0,43,52,0,0,2,0,140,255,236,5,18,6,117,0,9,0,25,0,29,64,17,1,22,0,105,22,13,5,105,13,2,114,10,18,106,10,9,114,0,43,43,43,43,51,43,51,48,49,1,39,55,54,54,53,51,20,6,7,1,32,17,17,51,17,20,22,51,32,17,17,51,17,20,6,3,143,51,61,93,92,192,163,164,254,137,254,56,200,125,135,1,4,200,236,4,231,165,10,15,111,97,169,192,27,250,251,1,220,3,196,252,60,142,144,1,30,3,196,252,60,238,238,0,255,255,0,140,255,236,5,18,7,38,2,38,0,156,0,0,1,6,6,63,0,0,0,11,182,2,26,13,1,1,160,86,0,43,52,0,255,255,0,140,254,92,5,18,6,117,2,38,0,156,0,0,1,6,6,41,0,0,0,14,180,2,32,10,1,1,185,255,124,0,86,0,43,52,255,255,0,140,255,236,5,18,7,38,2,38,0,156,0,0,1,6,6,62,0,0,0,11,182,2,26,13,1,1,160,86,0,43,52,0,255,255,0,140,255,236,5,18,7,112,2,38,0,156,0,0,1,6,6,71,0,0,0,11,182,2,26,21,1,1,109,86,0,43,52,0,255,255,0,140,255,236,5,18,7,98,2,38,0,156,0,0,1,6,6,69,10,0,0,11,182,2,26,13,1,1,146,86,0,43,52,0,255,255,0,140,255,236,4,77,7,38,2,38,0,148,0,0,1,6,6,64,0,0,0,13,183,2,1,16,11,1,1,160,86,0,43,52,52,0,255,255,0,140,255,236,4,36,6,232,2,38,0,148,0,0,1,6,6,70,0,0,0,11,182,1,16,3,1,1,160,86,0,43,52,0,0,2,0,140,254,88,4,36,5,140,0,20,0,36,0,37,64,22,33,24,2,114,7,6,8,3,21,29,105,5,21,0,15,106,21,0,105,21,9,114,0,43,43,43,18,57,43,23,57,43,50,48,49,1,34,38,53,52,55,53,55,23,14,2,21,20,22,51,50,55,7,6,6,3,32,17,17,51,17,20,22,51,32,17,17,51,17,20,6,2,156,115,125,114,220,44,52,105,71,46,70,37,45,18,25,45,92,254,56,200,125,135,1,4,200,236,254,88,101,91,154,38,70,10,27,17,39,67,58,26,62,11,170,4,5,1,148,1,220,3,196,252,60,142,144,1,30,3,196,252,60,238,238,0,255,255,0,140,255,236,4,36,7,108,2,38,0,148,0,0,1,6,6,68,0,0,0,13,183,2,1,16,11,1,1,68,86,0,43,52,52,0,255,255,0,140,255,236,4,36,7,98,2,38,0,148,0,0,1,6,6,69,10,0,0,11,182,1,16,3,1,1,146,86,0,43,52,0,0,1,0,44,0,0,4,130,5,140,0,7,0,19,64,9,3,0,6,1,2,114,0,8,114,0,43,43,50,18,57,48,49,33,1,51,1,51,1,51,1,1,188,254,112,214,1,76,18,1,76,214,254,112,5,140,251,30,4,226,250,116,255,255,0,45,0,0,4,131,5,140,2,6,1,207,0,0,0,2,0,20,0,0,4,156,5,140,0,9,0,19,0,37,64,20,5,12,13,106,8,12,12,10,17,1,2,114,10,15,0,3,106,0,8,114,0,43,43,50,51,43,50,17,57,17,51,43,50,48,49,51,3,51,19,51,19,51,7,35,3,51,3,35,39,51,19,51,19,51,3,180,160,210,120,20,131,200,67,40,105,222,105,40,65,200,129,20,120,210,160,5,140,251,20,3,132,198,252,162,3,94,198,252,124,4,236,250,116,0,255,255,0,20,0,0,4,156,7,38,2,38,0,169,0,0,1,6,6,63,0,0,0,11,182,2,20,1,1,1,160,86,0,43,52,0,255,255,0,20,0,0,4,156,7,48,2,38,0,169,0,0,1,6,6,65,0,0,0,11,182,2,24,17,1,1,160,86,0,43,52,0,255,255,0,20,0,0,4,156,7,56,2,38,0,169,0,0,1,6,6,60,0,0,0,13,183,3,2,20,17,1,1,160,86,0,43,52,52,0,255,255,0,20,0,0,4,156,7,38,2,38,0,169,0,0,1,6,6,62,0,0,0,11,182,2,20,17,1,1,160,86,0,43,52,0,0,2,0,66,0,0,4,112,5,140,0,5,0,11,0,28,64,15,1,10,4,7,4,2,5,5,6,8,114,9,2,2,114,0,43,50,43,50,17,18,23,57,48,49,33,1,1,51,1,1,33,1,1,51,1,1,3,138,254,148,254,36,230,1,122,1,206,251,210,1,206,1,122,230,254,36,254,148,2,124,3,16,253,94,253,22,2,234,2,162,252,240,253,132,0,2,0,25,0,0,4,151,5,140,0,7,0,11,0,23,64,12,0,9,3,3,1,8,8,114,6,1,2,114,0,43,50,43,17,23,57,48,49,1,1,51,1,51,1,51,1,3,17,51,17,2,3,254,22,220,1,90,18,1,90,220,254,22,185,200,1,218,3,178,253,58,2,198,252,78,254,38,2,188,253,68,255,255,0,25,0,0,4,151,7,38,2,38,0,175,0,0,1,6,6,63,0,0,0,11,182,2,12,1,1,1,160,86,0,43,52,0,255,255,0,25,0,0,4,151,7,48,2,38,0,175,0,0,1,6,6,65,0,0,0,11,182,2,16,5,1,1,160,86,0,43,52,0,255,255,0,25,0,0,4,151,7,56,2,38,0,175,0,0,1,6,6,60,0,0,0,13,183,3,2,12,5,1,1,160,86,0,43,52,52,0,255,255,0,25,254,92,4,151,5,140,2,38,0,175,0,0,1,6,6,41,0,0,0,14,180,2,18,8,1,1,185,255,104,0,86,0,43,52,255,255,0,25,0,0,4,151,7,38,2,38,0,175,0,0,1,6,6,62,0,0,0,11,182,2,12,5,1,1,160,86,0,43,52,0,255,255,0,25,0,0,4,151,7,112,2,38,0,175,0,0,1,6,6,71,0,0,0,11,182,2,12,5,1,1,109,86,0,43,52,0,255,255,0,25,0,0,4,151,6,232,2,38,0,175,0,0,1,6,6,70,0,0,0,11,182,2,12,1,1,1,160,86,0,43,52,0,255,255,0,25,0,0,4,151,7,98,2,38,0,175,0,0,1,6,6,69,10,0,0,11,182,2,12,1,1,1,146,86,0,43,52,0,0,3,0,150,0,0,4,46,5,140,0,3,0,7,0,11,0,29,64,16,2,3,9,8,106,9,2,114,0,1,4,6,106,4,8,114,0,43,43,50,57,43,43,50,57,48,49,37,39,1,23,1,53,33,21,1,53,33,21,1,46,152,2,236,152,252,124,3,152,252,104,3,132,68,122,4,148,132,251,50,190,190,4,206,190,190,255,255,0,150,0,0,4,46,7,38,2,38,0,184,0,0,1,6,6,63,0,0,0,11,182,3,12,9,1,1,160,86,0,43,52,0,255,255,0,150,0,0,4,46,7,48,2,38,0,184,0,0,1,6,6,66,0,0,0,11,182,3,12,9,1,1,160,86,0,43,52,0,255,255,0,150,0,0,4,46,7,56,2,38,0,184,0,0,1,6,6,61,0,0,0,11,182,3,12,9,1,1,160,86,0,43,52,0,255,255,0,45,0,0,5,51,7,38,2,38,0,71,0,0,0,39,6,63,254,232,0,0,1,7,6,63,1,104,0,0,0,21,64,14,6,36,11,1,1,160,86,5,32,21,1,1,160,86,0,43,52,43,52,0,255,255,0,96,255,236,4,125,7,48,2,38,0,28,0,0,1,6,6,74,105,0,0,11,182,1,22,5,1,1,100,86,0,43,52,0,255,255,0,148,0,0,4,28,7,48,2,38,0,94,0,0,1,6,6,74,0,0,0,11,182,3,16,13,1,1,120,86,0,43,52,0,255,255,0,76,255,236,4,100,7,48,2,38,0,101,0,0,1,6,6,74,0,0,0,11,182,2,16,4,1,1,100,86,0,43,52,0,255,255,0,129,255,236,4,37,7,48,2,38,0,135,0,0,1,6,6,74,20,0,0,11,182,1,40,20,1,1,100,86,0,43,52,0,255,255,0,150,0,0,4,46,7,48,2,38,0,184,0,0,1,6,6,74,0,0,0,11,182,3,12,9,1,1,120,86,0,43,52,0,0,3,0,168,0,0,4,8,4,36,0,3,0,7,0,11,0,25,64,14,9,8,106,1,9,6,114,4,5,106,0,4,10,114,0,43,50,43,43,50,43,48,49,33,17,51,17,33,53,33,21,1,53,33,21,1,244,200,253,236,3,96,252,160,3,96,4,36,251,220,190,190,3,102,190,190,0,2,0,96,255,236,4,134,4,46,0,15,0,45,0,42,64,27,22,29,106,41,42,1,39,22,5,8,16,34,106,16,11,114,15,13,106,15,10,8,7,106,8,7,114,0,43,43,63,43,43,43,18,23,57,43,48,49,5,3,39,17,52,38,39,39,55,23,4,22,21,17,23,21,5,34,38,53,52,54,51,50,22,23,7,38,38,35,32,21,20,22,51,50,54,54,53,53,19,35,55,20,6,6,3,50,14,28,149,147,254,20,214,1,7,255,180,253,54,166,182,251,229,95,149,58,44,67,128,67,254,236,95,87,99,133,66,62,84,34,85,154,10,1,58,88,1,18,106,99,4,7,188,3,4,219,210,254,70,22,170,20,160,146,168,180,23,23,144,15,5,158,74,82,68,106,56,116,254,240,32,92,123,61,255,255,0,96,255,236,4,134,6,92,2,38,0,195,0,0,1,6,6,30,10,0,0,11,182,2,46,8,1,1,178,86,0,43,52,0,255,255,0,96,255,236,4,134,6,67,2,38,0,195,0,0,1,6,6,34,236,0,0,11,182,2,46,8,1,1,168,86,0,43,52,0,255,255,0,96,255,236,4,134,7,229,2,38,0,195,0,0,0,38,6,34,236,0,1,7,6,30,0,10,1,137,0,21,64,14,3,64,50,1,1,38,86,2,46,8,1,1,168,86,0,43,52,43,52,0,255,255,0,96,254,92,4,134,6,67,2,38,0,195,0,0,0,38,6,41,0,0,1,6,6,34,236,0,0,24,64,12,3,58,8,1,1,168,86,2,52,16,1,1,185,255,124,0,86,0,43,52,43,52,255,255,0,96,255,236,4,134,7,229,2,38,0,195,0,0,0,38,6,34,236,0,1,7,6,29,0,25,1,137,0,21,64,14,3,64,59,1,1,38,86,2,46,8,1,1,168,86,0,43,52,43,52,0,255,255,0,96,255,236,4,134,8,37,2,38,0,195,0,0,0,38,6,34,236,0,1,7,6,38,0,0,1,137,0,23,64,15,4,3,64,59,1,1,38,86,2,46,8,1,1,168,86,0,43,52,43,52,52,0,255,255,0,96,255,236,4,134,7,201,2,38,0,195,0,0,0,38,6,34,236,0,1,7,6,36,255,246,1,137,0,21,64,14,3,64,50,1,1,46,86,2,46,8,1,1,168,86,0,43,52,43,52,0,255,255,0,96,255,236,4,134,6,92,2,38,0,195,0,0,1,6,6,33,236,0,0,11,182,2,46,8,1,1,178,86,0,43,52,0,255,255,0,96,255,236,4,134,6,92,2,38,0,195,0,0,1,6,6,32,236,0,0,11,182,2,50,8,1,1,178,86,0,43,52,0,255,255,0,96,255,236,4,194,7,176,2,38,0,195,0,0,0,38,6,32,236,0,1,7,6,30,1,111,1,84,0,23,180,3,54,47,1,0,184,255,216,183,86,2,50,8,1,1,178,86,0,43,52,43,52,0,255,255,0,96,254,92,4,134,6,92,2,38,0,195,0,0,0,38,6,41,0,0,1,6,6,32,236,0,0,24,64,12,3,62,8,1,1,178,86,2,52,16,1,1,185,255,124,0,86,0,43,52,43,52,255,255,0,96,255,236,4,134,7,176,2,38,0,195,0,0,0,38,6,32,236,0,1,7,6,29,1,125,1,84,0,23,180,3,54,47,1,0,184,255,216,183,86,2,50,8,1,1,178,86,0,43,52,43,52,0,255,255,0,96,255,236,4,134,7,240,2,38,0,195,0,0,0,38,6,32,236,0,1,7,6,38,1,101,1,84,0,25,181,4,3,54,47,1,0,184,255,216,183,86,2,50,8,1,1,178,86,0,43,52,43,52,52,0,255,255,0,96,255,236,4,134,8,10,2,38,0,195,0,0,0,38,6,32,236,0,1,7,6,36,255,246,1,202,0,21,64,14,3,54,47,1,1,86,86,2,50,8,1,1,178,86,0,43,52,43,52,0,255,255,0,96,255,236,4,134,5,226,2,38,0,195,0,0,1,6,6,27,238,0,0,13,183,3,2,46,8,1,1,168,86,0,43,52,52,0,255,255,0,96,254,92,4,134,4,46,2,38,0,195,0,0,1,6,6,41,0,0,0,14,180,2,52,16,1,1,185,255,124,0,86,0,43,52,255,255,0,96,255,236,4,134,6,92,2,38,0,195,0,0,1,6,6,29,25,0,0,11,182,2,46,8,1,1,178,86,0,43,52,0,255,255,0,96,255,236,4,134,6,156,2,38,0,195,0,0,1,6,6,38,0,0,0,13,183,3,2,46,8,1,1,178,86,0,43,52,52,0,255,255,0,96,255,236,4,134,5,156,2,38,0,195,0,0,1,6,6,37,236,0,0,11,182,2,46,8,1,1,178,86,0,43,52,0,0,3,0,96,254,88,4,134,4,46,0,20,0,36,0,66,0,57,64,37,43,50,106,62,63,22,60,43,5,29,37,0,15,106,37,0,105,37,55,106,37,11,114,7,8,36,34,105,36,10,114,29,28,106,29,7,114,0,43,43,43,43,57,57,43,43,43,43,17,18,23,57,43,48,49,1,34,38,53,52,54,55,53,55,23,34,6,21,20,22,51,50,55,7,6,6,3,3,39,17,52,38,39,39,55,23,4,22,21,17,23,21,5,34,38,53,52,54,51,50,22,23,7,38,38,35,32,21,20,22,51,50,54,54,53,53,19,35,55,20,6,6,3,252,115,125,59,55,240,20,106,118,61,55,35,47,18,23,47,222,14,28,149,147,254,20,214,1,7,255,180,253,54,166,182,251,229,95,149,58,44,67,128,67,254,236,95,87,99,133,66,62,84,34,85,154,254,88,111,101,68,93,16,65,2,32,88,80,42,46,11,170,4,5,1,158,1,58,88,1,18,106,99,4,7,188,3,4,219,210,254,70,22,170,20,160,146,168,180,23,23,144,15,5,158,74,82,68,106,56,116,254,240,32,92,123,61,0,255,255,0,96,255,236,4,134,6,94,2,38,0,195,0,0,1,6,6,35,236,0,0,13,183,3,2,46,8,1,1,128,86,0,43,52,52,0,255,255,0,96,255,236,4,134,7,116,2,38,0,195,0,0,0,38,6,35,236,0,1,7,6,30,0,10,1,24,0,26,180,4,66,52,0,0,184,255,154,64,9,86,3,2,46,8,1,1,128,86,0,43,52,52,43,52,255,255,0,96,255,236,4,134,6,64,2,38,0,195,0,0,1,6,6,36,246,0,0,11,182,2,46,8,1,1,186,86,0,43,52,0,0,3,0,21,255,236,4,151,4,56,0,28,0,41,0,71,0,60,64,39,56,55,106,56,56,42,48,60,106,48,7,114,42,66,106,42,11,114,6,13,106,24,29,10,6,4,0,36,35,106,36,7,114,0,19,106,0,11,114,0,43,43,43,43,18,23,57,43,43,43,43,43,18,57,47,43,48,49,5,34,38,53,52,54,51,50,22,23,7,38,38,35,34,6,21,20,22,51,50,54,53,53,19,35,55,6,6,19,53,17,52,38,39,39,55,23,22,22,21,17,1,34,2,17,16,18,51,50,18,21,20,6,7,33,53,33,52,38,35,34,6,21,20,22,51,50,55,23,6,6,1,43,133,145,194,176,65,110,37,44,26,90,56,84,92,75,67,80,88,152,164,84,16,138,82,156,140,94,20,94,204,224,1,34,193,213,165,148,146,159,3,3,254,28,1,52,69,77,75,69,149,135,57,63,26,40,89,20,160,146,166,182,19,17,154,23,7,88,80,74,82,121,109,176,254,180,22,127,139,1,74,82,1,18,99,116,4,3,182,3,7,225,201,254,188,254,182,1,25,1,15,1,5,1,31,254,246,242,34,72,30,152,161,145,167,185,184,202,13,171,8,10,255,255,0,21,255,236,4,151,6,92,2,38,0,219,0,0,1,6,6,30,30,0,0,11,182,3,72,36,1,1,178,86,0,43,52,0,0,2,0,168,255,236,4,80,5,220,0,24,0,28,0,37,64,22,26,0,114,17,15,0,19,13,106,19,7,114,28,3,25,3,0,7,106,0,11,114,0,43,43,23,57,43,43,18,57,57,43,48,49,5,34,38,39,55,22,22,51,50,54,53,52,38,35,32,17,3,51,54,51,50,22,21,16,0,37,17,51,17,1,196,72,140,72,82,53,128,63,191,209,127,117,254,242,62,82,15,245,212,232,254,171,253,173,212,20,11,9,194,25,9,230,210,144,156,254,208,1,16,212,250,230,254,217,254,187,20,5,220,250,54,0,1,0,136,255,236,4,73,4,56,0,25,0,27,64,15,9,10,0,6,13,106,6,7,114,0,19,106,0,11,114,0,43,43,43,43,18,57,57,48,49,5,32,0,17,16,0,33,50,22,23,7,38,38,35,34,6,21,20,22,51,50,54,55,23,6,6,2,170,254,251,254,227,1,23,1,3,155,221,47,163,45,140,83,147,163,182,168,80,157,75,24,87,184,20,1,29,1,11,1,4,1,32,115,105,123,73,80,181,167,181,191,14,12,186,18,12,0,255,255,0,136,255,236,4,73,6,92,2,38,0,222,0,0,1,6,6,30,80,0,0,11,182,1,26,6,1,1,168,86,0,43,52,0,255,255,0,136,255,236,4,73,6,92,2,38,0,222,0,0,1,6,6,33,50,0,0,11,182,1,26,6,1,1,168,86,0,43,52,0,255,255,0,136,254,32,4,73,4,56,2,38,0,222,0,0,1,6,6,43,231,0,0,11,182,1,35,0,0,0,15,86,0,43,52,0,255,255,0,136,255,236,4,73,6,92,2,38,0,222,0,0,1,6,6,32,50,0,0,11,182,1,30,6,1,1,168,86,0,43,52,0,255,255,0,136,255,236,4,73,5,226,2,38,0,222,0,0,1,6,6,28,48,0,0,11,182,1,26,6,1,1,158,86,0,43,52,0,0,2,0,96,255,236,4,8,5,220,0,25,0,30,0,37,64,23,30,10,28,0,114,9,11,21,23,4,0,6,13,106,6,7,114,0,18,106,0,11,114,0,43,43,43,43,18,23,57,43,63,48,49,5,34,2,17,16,18,51,50,22,23,51,3,16,33,34,6,21,16,51,32,53,53,19,35,6,6,55,39,17,51,17,2,6,201,221,222,202,128,139,13,82,62,254,242,117,127,246,1,12,72,92,10,152,204,22,212,20,1,23,1,5,1,11,1,37,105,107,254,240,1,48,198,182,254,152,180,116,254,220,91,93,10,208,5,22,250,36,0,4,0,118,255,236,4,80,5,236,0,10,0,21,0,36,0,40,0,49,64,33,37,38,106,28,37,105,28,16,106,0,33,10,34,31,28,4,7,5,22,11,106,22,11,114,39,40,106,5,39,105,5,1,114,0,43,43,43,43,43,18,23,57,43,43,43,48,49,1,17,16,2,37,55,22,4,18,17,21,1,32,17,52,38,35,34,6,21,20,22,23,34,2,53,52,54,51,50,22,23,51,17,55,16,0,1,39,37,23,3,94,248,254,236,50,244,1,51,145,254,10,1,24,138,128,127,137,130,122,223,243,202,186,129,179,30,74,166,254,252,253,222,40,3,58,40,1,16,1,138,1,37,1,100,101,100,74,245,254,146,254,255,48,254,150,1,20,142,154,133,123,151,165,184,1,6,238,210,230,111,101,254,212,118,254,251,254,227,3,249,175,240,175,0,3,0,96,255,236,5,104,6,32,0,3,0,29,0,34,0,44,64,28,34,10,1,3,106,32,1,105,32,0,27,25,15,13,4,4,10,17,106,10,7,114,4,22,106,4,11,114,0,43,43,43,43,18,23,57,63,43,43,63,48,49,1,19,51,3,1,34,2,17,16,18,51,50,22,23,51,3,16,33,34,6,21,16,51,32,53,53,19,35,6,6,55,39,17,51,17,4,98,50,212,90,252,248,201,221,222,202,128,139,13,82,62,254,242,117,127,246,1,12,72,92,10,152,204,22,212,4,164,1,124,254,132,251,72,1,23,1,5,1,11,1,37,105,107,254,240,1,48,198,182,254,152,180,116,254,220,91,93,10,208,5,22,250,36,0,0,3,0,96,255,236,4,114,5,220,0,3,0,29,0,34,0,44,64,27,34,10,0,1,106,0,10,32,0,27,25,15,13,4,4,10,17,106,10,7,114,4,22,106,4,11,114,0,43,43,43,43,18,23,57,63,18,57,43,63,48,49,1,53,33,21,1,34,2,17,16,18,51,50,22,23,51,3,16,33,34,6,21,16,51,32,53,53,19,35,6,6,55,39,17,51,17,1,206,2,164,253,148,201,221,222,202,128,139,13,82,62,254,242,117,127,246,1,12,72,92,10,152,204,22,212,4,194,174,174,251,42,1,23,1,5,1,11,1,37,105,107,254,240,1,48,198,182,254,152,180,116,254,220,91,93,10,208,5,22,250,36,0,1,0,136,255,236,4,40,4,56,0,29,0,33,64,19,27,0,23,106,12,13,106,12,12,0,6,17,106,6,7,114,0,11,114,0,43,43,43,18,57,47,43,43,51,48,49,5,32,0,17,16,18,51,50,18,21,20,7,33,53,33,52,38,35,34,6,21,20,22,51,50,54,55,23,6,6,2,190,254,241,254,217,250,228,215,235,6,253,24,2,46,136,120,135,149,205,189,66,128,66,26,94,156,20,1,29,1,11,1,4,1,32,254,252,248,73,63,162,143,153,184,168,184,192,15,13,186,18,10,255,255,0,136,255,236,4,40,6,92,2,38,0,232,0,0,1,6,6,30,40,0,0,11,182,1,30,6,1,1,168,86,0,43,52,0,255,255,0,136,255,236,4,40,6,67,2,38,0,232,0,0,1,6,6,34,10,0,0,11,182,1,30,6,1,1,158,86,0,43,52,0,255,255,0,136,255,236,4,40,6,92,2,38,0,232,0,0,1,6,6,33,10,0,0,11,182,1,30,6,1,1,168,86,0,43,52,0,255,255,0,136,255,236,4,40,6,92,2,38,0,232,0,0,1,6,6,32,10,0,0,11,182,1,34,6,1,1,168,86,0,43,52,0,255,255,0,136,255,236,4,224,7,176,2,38,0,232,0,0,0,38,6,32,10,0,1,7,6,30,1,141,1,84,0,23,180,2,38,31,1,0,184,255,216,183,86,1,34,6,1,1,168,86,0,43,52,43,52,0,255,255,0,136,254,92,4,40,6,92,2,38,0,232,0,0,0,38,6,41,30,0,1,6,6,32,10,0,0,24,64,12,2,46,6,1,1,168,86,1,36,0,1,1,185,255,124,0,86,0,43,52,43,52,255,255,0,136,255,236,4,58,7,176,2,38,0,232,0,0,0,38,6,32,10,0,1,7,6,29,1,155,1,84,0,23,180,2,38,31,1,0,184,255,216,183,86,1,34,6,1,1,168,86,0,43,52,43,52,0,255,255,0,136,255,236,4,138,7,240,2,38,0,232,0,0,0,38,6,32,10,0,1,7,6,38,1,131,1,84,0,25,181,3,2,38,31,1,0,184,255,216,183,86,1,34,6,1,1,168,86,0,43,52,43,52,52,0,255,255,0,136,255,236,4,40,8,10,2,38,0,232,0,0,0,38,6,32,10,0,1,7,6,36,0,20,1,202,0,21,64,14,2,38,31,1,1,86,86,1,34,6,1,1,168,86,0,43,52,43,52,0,255,255,0,136,255,236,4,40,5,226,2,38,0,232,0,0,1,6,6,27,12,0,0,13,183,2,1,30,6,1,1,158,86,0,43,52,52,0,255,255,0,136,255,236,4,40,5,226,2,38,0,232,0,0,1,6,6,28,8,0,0,11,182,1,30,6,1,1,158,86,0,43,52,0,255,255,0,136,254,92,4,40,4,56,2,38,0,232,0,0,1,6,6,41,30,0,0,14,180,1,36,0,1,1,185,255,124,0,86,0,43,52,255,255,0,136,255,236,4,40,6,92,2,38,0,232,0,0,1,6,6,29,55,0,0,11,182,1,30,6,1,1,168,86,0,43,52,0,255,255,0,136,255,236,4,40,6,156,2,38,0,232,0,0,1,6,6,38,30,0,0,13,183,2,1,30,6,1,1,168,86,0,43,52,52,0,255,255,0,136,255,236,4,40,5,156,2,38,0,232,0,0,1,6,6,37,10,0,0,11,182,1,30,6,1,1,168,86,0,43,52,0,0,2,0,136,254,88,4,40,4,56,0,21,0,51,0,49,64,30,35,34,106,35,35,22,28,39,106,28,7,114,7,9,49,3,22,45,106,6,22,0,16,106,22,0,105,22,11,114,0,43,43,43,18,57,43,23,57,43,43,18,57,47,43,48,49,1,34,38,53,52,54,55,53,55,23,14,2,21,20,22,51,50,55,7,6,6,3,32,0,17,16,18,51,50,18,21,20,7,33,53,33,52,38,35,34,6,21,20,22,51,50,54,55,23,6,6,3,110,115,125,60,54,240,20,51,103,70,46,70,37,45,18,25,45,196,254,241,254,217,250,228,215,235,6,253,24,2,46,136,120,135,149,205,189,66,128,66,26,94,156,254,88,101,91,74,100,18,70,10,32,12,39,69,56,26,62,11,170,4,5,1,148,1,29,1,11,1,4,1,32,254,252,248,73,63,162,143,153,184,168,184,192,15,13,186,18,10,0,255,255,0,166,255,236,4,26,4,56,2,6,2,73,0,0,255,255,0,68,254,35,4,100,5,160,2,6,3,84,0,0,255,255,0,136,255,236,4,40,6,64,2,38,0,232,0,0,1,6,6,36,20,0,0,11,182,1,30,6,1,1,176,86,0,43,52,0,0,1,0,136,255,236,4,40,4,56,0,29,0,31,64,18,0,11,106,8,5,106,8,8,0,24,17,106,24,7,114,0,11,114,0,43,43,43,18,57,47,43,43,48,49,5,34,2,53,52,55,33,21,33,20,22,51,50,54,53,52,38,35,34,6,7,39,54,54,51,32,0,17,16,2,2,74,214,236,6,2,232,253,210,136,120,135,149,205,189,66,128,66,26,95,155,60,1,16,1,38,250,20,1,5,247,73,63,162,142,154,184,168,185,191,20,18,176,31,17,254,227,254,245,254,253,254,223,0,2,0,79,254,52,4,37,4,27,0,21,0,31,0,45,64,25,25,28,27,106,24,23,14,106,13,30,28,3,0,23,23,28,0,6,106,28,0,105,28,6,114,0,43,43,43,18,57,47,18,57,18,57,51,43,57,43,57,48,49,1,32,39,55,22,22,51,50,54,53,52,38,35,35,39,51,22,4,21,20,6,6,3,35,39,1,23,33,53,33,21,1,2,29,254,223,173,140,80,148,105,138,153,174,158,111,8,180,233,1,0,122,232,240,128,20,1,241,24,253,101,3,55,254,75,254,52,179,148,72,65,152,129,125,137,153,4,225,200,134,206,117,2,221,124,2,17,49,174,201,254,46,0,0,2,0,68,0,0,4,100,5,240,0,12,0,16,0,27,64,15,13,14,106,13,13,0,3,9,106,3,1,114,0,10,114,0,43,43,43,18,57,47,43,48,49,33,17,16,33,50,23,7,38,38,35,32,17,17,1,53,33,21,1,146,1,246,114,106,22,63,96,45,254,228,253,222,3,212,3,202,2,38,20,184,8,6,254,162,252,44,2,134,174,174,0,3,0,96,254,34,4,8,4,56,0,28,0,40,0,45,0,48,64,30,44,6,29,30,106,29,15,114,45,36,23,11,9,5,6,26,26,0,6,14,106,6,7,114,0,20,106,0,11,114,0,43,43,43,43,18,57,47,18,23,57,43,43,63,48,49,5,34,2,17,16,18,51,50,22,23,51,7,52,38,35,34,6,21,20,22,51,50,54,53,53,19,35,6,6,1,39,37,54,54,53,53,51,21,16,0,5,1,17,55,51,17,2,6,201,221,222,202,128,139,13,82,62,120,120,131,143,140,136,120,118,72,92,10,152,254,56,10,1,84,161,145,214,254,254,254,230,1,72,20,192,20,1,23,1,5,1,11,1,37,105,107,232,133,131,198,182,178,182,90,90,116,254,220,91,93,254,54,194,10,5,168,163,242,210,254,229,254,242,9,2,216,2,64,224,252,224,0,255,255,0,96,254,34,4,8,6,67,2,38,0,255,0,0,1,6,6,34,236,0,0,11,182,3,46,6,1,1,158,86,0,43,52,0,255,255,0,96,254,34,4,8,6,92,2,38,0,255,0,0,1,6,6,33,236,0,0,11,182,3,46,6,1,1,168,86,0,43,52,0,255,255,0,96,254,34,4,8,6,92,2,38,0,255,0,0,1,6,6,32,236,0,0,11,182,3,50,6,1,1,168,86,0,43,52,0,255,255,0,96,254,34,4,8,6,52,2,38,0,255,0,0,1,6,6,39,246,0,0,11,182,3,46,6,1,1,128,86,0,43,52,0,255,255,0,96,254,34,4,8,5,226,2,38,0,255,0,0,1,6,6,28,234,0,0,11,182,3,46,6,1,1,158,86,0,43,52,0,0,2,0,168,0,0,4,8,5,220,0,15,0,19,0,29,64,16,17,0,114,7,6,11,15,16,10,114,11,4,106,11,7,114,0,43,43,43,50,17,57,57,43,48,49,33,17,52,38,35,34,17,3,51,54,54,51,50,22,21,17,33,17,51,17,3,52,100,90,250,62,82,9,138,133,168,184,252,160,212,2,178,101,109,254,208,1,16,107,105,204,186,253,78,5,220,250,36,0,3,0,62,0,0,4,8,5,220,0,3,0,19,0,23,0,39,64,22,0,1,106,0,0,15,21,0,114,11,10,15,19,20,10,114,15,8,106,15,7,114,0,43,43,43,50,17,57,57,43,17,57,47,43,48,49,19,53,33,21,19,17,52,38,35,34,17,3,51,54,54,51,50,22,21,17,33,17,51,17,62,2,164,82,100,90,250,62,82,9,138,133,168,184,252,160,212,4,194,174,174,251,62,2,178,101,109,254,208,1,16,107,105,204,186,253,78,5,220,250,36,255,255,255,184,0,0,4,8,7,128,2,38,1,5,0,0,1,7,6,66,254,186,0,80,0,11,182,2,20,17,1,1,160,86,0,43,52,0,255,255,255,189,0,0,4,8,7,128,2,38,1,5,0,0,1,7,6,65,254,186,0,80,0,11,182,2,24,17,1,1,160,86,0,43,52,0,0,5,0,160,0,0,4,78,5,244,0,3,0,7,0,11,0,15,0,27,0,37,64,22,16,22,106,13,16,105,1,13,12,106,13,6,114,9,4,5,106,8,0,4,10,114,0,43,50,50,43,50,43,43,57,43,43,48,49,33,17,51,17,33,53,33,21,51,53,33,21,1,53,33,21,3,34,38,53,52,54,51,50,22,21,20,6,2,52,212,253,152,1,168,172,1,90,252,142,2,44,118,61,87,87,61,62,86,86,3,232,252,24,174,174,174,174,3,116,176,176,1,88,87,61,62,86,86,62,61,87,0,0,4,0,160,0,0,4,78,4,36,0,3,0,7,0,11,0,15,0,33,64,18,0,4,1,13,9,8,4,5,106,13,12,106,13,6,114,4,10,114,0,43,43,43,43,51,50,17,51,17,51,48,49,33,17,51,17,33,53,33,21,51,53,33,21,1,53,33,21,2,52,212,253,152,1,168,172,1,90,252,142,2,44,4,36,251,220,174,174,174,174,3,118,174,174,0,255,255,0,160,0,0,4,78,6,92,2,38,1,10,0,0,1,6,6,30,80,0,0,11,182,4,16,1,1,1,188,86,0,43,52,0,255,255,0,160,0,0,4,78,6,67,2,38,1,10,0,0,1,6,6,34,50,0,0,11,182,4,16,1,1,1,178,86,0,43,52,0,255,255,0,160,0,0,4,78,6,92,2,38,1,10,0,0,1,6,6,32,50,0,0,11,182,4,20,1,1,1,188,86,0,43,52,0,255,255,0,160,0,0,4,78,5,226,2,38,1,10,0,0,1,6,6,27,52,0,0,13,183,5,4,16,1,1,1,178,86,0,43,52,52,0,255,255,0,160,254,92,4,78,5,244,2,38,1,9,0,0,1,6,6,41,70,0,0,14,180,5,34,8,1,1,185,255,104,0,86,0,43,52,255,255,0,160,0,0,4,78,6,92,2,38,1,10,0,0,1,6,6,29,95,0,0,11,182,4,16,1,1,1,188,86,0,43,52,0,255,255,0,160,0,0,4,78,6,156,2,38,1,10,0,0,1,6,6,38,70,0,0,13,183,5,4,16,1,1,1,188,86,0,43,52,52,0,0,5,0,200,254,32,3,232,5,244,0,11,0,15,0,19,0,31,0,43,0,41,64,24,38,20,26,106,32,13,20,105,6,19,12,17,13,6,114,12,10,114,0,1,106,0,15,114,0,43,43,43,43,50,18,57,57,43,50,43,50,48,49,19,39,55,54,54,53,17,51,17,16,0,5,3,17,51,17,1,17,51,17,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,252,10,200,161,145,212,255,0,254,230,178,212,1,36,212,253,156,61,87,87,61,62,86,86,1,186,61,87,87,61,62,86,86,254,32,188,18,14,159,163,1,66,254,222,254,229,254,253,20,1,212,4,36,251,220,1,94,2,198,253,58,3,110,87,61,62,86,86,62,61,87,87,61,62,86,86,62,61,87,255,255,0,160,0,0,4,78,5,156,2,38,1,10,0,0,1,6,6,37,50,0,0,11,182,4,16,13,1,1,188,86,0,43,52,0,0,6,0,160,254,88,4,78,5,244,0,20,0,24,0,28,0,32,0,36,0,48,0,53,64,32,37,43,106,34,37,105,22,34,33,106,34,6,114,7,31,25,26,106,6,25,0,15,106,25,0,105,32,21,9,25,10,114,0,43,50,50,50,43,43,18,57,43,50,57,43,43,57,43,43,48,49,1,34,38,53,52,54,55,53,55,23,34,6,21,20,22,51,50,55,7,6,6,3,17,51,17,33,53,33,21,51,53,33,21,1,53,33,21,3,34,38,53,52,54,51,50,22,21,20,6,2,158,115,125,59,55,240,20,106,118,61,55,35,47,18,23,47,126,212,253,152,1,168,172,1,90,252,142,2,44,118,61,87,87,61,62,86,86,254,88,111,101,74,100,18,50,2,32,88,80,42,46,11,170,4,5,1,168,3,232,252,24,174,174,174,174,3,116,176,176,1,88,87,61,62,86,86,62,61,87,255,255,0,160,0,0,4,78,6,64,2,38,1,10,0,0,1,6,6,36,60,0,0,11,182,4,16,13,1,1,196,86,0,43,52,0,0,4,0,170,254,32,3,140,5,244,0,12,0,16,0,20,0,32,0,37,64,22,21,27,106,14,21,105,7,20,0,18,14,13,106,14,6,114,0,1,106,0,15,114,0,43,43,43,43,51,18,57,57,43,43,48,49,19,39,55,54,54,53,17,51,17,20,6,6,7,3,53,33,21,3,17,51,17,3,34,38,53,52,54,51,50,22,21,20,6,180,10,200,161,145,212,112,238,188,86,1,172,16,212,128,61,87,87,61,62,86,86,254,32,188,18,15,158,163,1,66,254,222,189,237,121,15,5,74,174,174,253,232,2,198,253,58,3,110,87,61,62,86,86,62,61,87,0,0,3,0,170,254,32,3,120,4,36,0,12,0,16,0,20,0,25,64,13,6,20,0,18,14,13,106,14,6,114,0,15,114,0,43,43,43,51,18,57,57,48,49,19,39,55,54,54,53,17,51,17,20,6,6,7,3,53,33,21,3,17,51,17,180,10,200,161,145,212,112,238,188,86,1,172,16,212,254,32,188,18,15,158,163,1,66,254,222,189,237,121,15,5,74,174,174,253,232,2,198,253,58,0,255,255,0,170,254,32,4,84,6,92,2,38,1,23,0,0,1,7,6,32,0,182,0,0,0,11,182,3,25,14,1,1,188,86,0,43,52,0,0,3,0,160,0,0,4,116,5,220,0,10,0,14,0,18,0,34,64,18,17,16,0,1,106,0,0,11,6,12,0,114,15,11,10,114,6,6,0,63,43,50,43,17,18,57,47,43,57,57,48,49,1,53,51,50,54,54,55,51,2,0,33,1,17,51,17,33,1,55,1,1,54,120,132,170,97,23,220,42,254,219,254,255,254,192,212,1,250,254,210,200,1,108,1,146,190,91,206,171,254,181,254,185,254,110,5,220,250,36,2,4,82,253,170,0,255,255,0,160,254,32,4,116,5,220,2,38,1,25,0,0,1,6,6,42,236,0,0,14,180,3,20,11,1,1,185,255,116,0,86,0,43,52,0,3,0,160,0,0,4,116,4,36,0,10,0,14,0,18,0,31,64,16,17,16,0,1,106,0,0,11,7,12,6,114,15,11,10,114,0,43,50,43,50,17,57,47,43,57,57,48,49,1,53,51,50,54,54,55,51,2,0,33,1,17,51,17,33,1,55,1,1,54,120,132,170,97,23,220,42,254,219,254,255,254,192,212,1,250,254,210,200,1,108,1,146,190,91,206,171,254,181,254,185,254,110,4,36,251,220,2,4,82,253,170,0,2,0,88,255,236,4,40,5,220,0,15,0,19,0,25,64,14,5,17,0,10,106,17,16,106,17,0,114,0,11,114,0,43,43,43,43,17,51,48,49,5,34,38,53,17,51,17,20,22,22,51,50,55,23,6,6,1,53,33,21,2,236,184,164,212,32,93,91,83,129,24,81,149,253,22,1,74,20,200,220,4,76,251,190,84,106,50,38,186,22,20,5,66,174,174,255,255,0,88,255,236,4,40,7,118,2,38,1,28,0,0,1,6,6,63,162,80,0,11,182,2,20,4,1,1,160,86,0,43,52,0,0,3,0,88,255,236,4,40,6,32,0,3,0,19,0,23,0,31,64,19,1,3,106,21,1,105,21,20,106,9,21,0,114,4,14,106,4,11,114,0,43,43,43,50,43,43,43,48,49,1,19,51,3,3,34,38,53,17,51,17,20,22,22,51,50,55,23,6,6,1,53,33,21,2,250,50,212,90,186,184,164,212,32,93,91,83,129,24,81,149,253,22,1,74,4,164,1,124,254,132,251,72,200,220,4,76,251,190,84,106,50,38,186,22,20,5,66,174,174,0,255,255,0,88,254,32,4,40,5,220,2,38,1,28,0,0,1,6,6,42,70,0,0,14,180,2,21,0,1,1,185,255,136,0,86,0,43,52,255,255,0,88,255,236,4,40,5,220,2,38,1,28,0,0,1,7,2,174,1,60,1,44,0,14,180,2,20,12,1,1,185,2,142,0,86,0,43,52,0,3,0,88,255,236,4,40,5,220,0,3,0,19,0,23,0,37,64,22,2,3,106,0,1,106,2,0,4,21,20,106,9,21,0,114,4,14,106,4,11,114,0,43,43,43,50,43,18,57,57,43,43,48,49,19,53,1,21,3,34,38,53,17,51,17,20,22,22,51,50,55,23,6,6,1,53,33,21,118,3,38,176,184,164,212,32,93,91,83,129,24,81,149,253,22,1,74,1,199,185,1,164,185,252,129,200,220,4,76,251,190,84,106,50,38,186,22,20,5,66,174,174,0,0,3,0,112,0,0,4,64,4,56,0,14,0,19,0,34,0,41,64,23,10,3,106,10,30,7,114,6,26,5,25,26,3,15,16,6,114,14,34,34,15,10,114,0,43,50,17,51,43,18,23,57,17,51,43,50,43,48,49,33,17,52,35,34,21,39,51,54,54,51,50,22,21,17,33,17,51,23,17,51,17,52,35,34,21,39,51,54,54,51,50,22,21,17,3,108,82,104,72,82,5,89,84,110,100,252,48,188,24,186,84,102,62,68,6,89,87,83,95,3,42,110,144,152,62,90,118,132,252,194,4,36,224,252,188,3,62,90,144,152,77,75,114,116,252,174,0,2,0,168,0,0,4,8,4,56,0,15,0,20,0,29,64,16,7,6,16,17,6,114,15,16,10,114,11,4,106,11,7,114,0,43,43,43,50,43,18,57,57,48,49,33,17,52,38,35,34,17,3,51,54,54,51,50,22,21,17,33,17,51,23,17,3,52,100,90,250,62,82,9,138,133,168,184,252,160,192,20,2,178,96,104,254,218,1,16,107,105,204,186,253,78,4,36,224,252,188,0,255,255,0,168,0,0,4,8,6,92,2,38,1,35,0,0,1,6,6,30,20,0,0,11,182,2,21,17,1,1,188,86,0,43,52,0,0,3,0,0,0,0,4,8,6,92,0,3,0,19,0,24,0,39,64,23,10,11,20,21,0,1,106,21,0,105,21,6,114,19,20,10,114,15,8,106,15,7,114,0,43,43,43,50,43,43,43,17,18,57,57,48,49,17,19,51,3,1,17,52,38,35,34,17,3,51,54,54,51,50,22,21,17,33,17,51,23,17,70,232,140,2,146,100,90,250,62,82,9,138,133,168,184,252,160,192,20,4,224,1,124,254,132,251,32,2,178,96,104,254,218,1,16,107,105,204,186,253,78,4,36,224,252,188,255,255,0,168,0,0,4,8,6,92,2,38,1,35,0,0,1,6,6,33,246,0,0,11,182,2,21,17,1,1,188,86,0,43,52,0,255,255,0,168,254,32,4,8,4,56,2,38,1,35,0,0,1,6,6,42,0,0,0,14,180,2,22,16,1,1,185,255,116,0,86,0,43,52,0,3,0,168,254,32,4,8,4,56,0,15,0,28,0,33,0,34,64,21,7,6,22,15,4,29,30,6,114,29,10,114,16,17,106,16,15,114,11,7,114,0,43,43,43,43,43,17,23,57,48,49,1,17,52,38,35,34,17,3,51,54,54,51,50,22,21,17,1,39,55,54,54,53,17,51,17,20,6,6,7,1,17,51,23,17,3,52,100,90,250,62,82,9,138,133,168,184,253,200,10,130,124,112,212,98,206,164,254,116,192,20,1,133,1,45,101,109,254,208,1,16,107,105,204,186,254,211,252,155,188,18,15,158,163,1,126,254,162,189,237,121,15,1,212,4,36,224,252,188,0,3,255,58,254,32,4,8,4,56,0,15,0,28,0,33,0,38,64,24,33,23,6,7,4,0,30,6,114,16,17,106,16,15,114,11,4,106,11,7,114,0,10,114,0,43,43,43,43,43,43,18,23,57,48,49,33,17,52,38,35,34,17,3,51,54,54,51,50,22,21,17,1,39,55,54,54,53,17,51,17,20,6,6,7,1,17,51,23,17,3,52,100,90,250,62,82,9,138,133,168,184,251,60,10,130,124,112,212,98,207,163,1,0,192,20,2,178,101,109,254,208,1,16,107,105,204,186,253,78,254,32,188,18,17,156,163,1,126,254,162,189,233,120,20,2,186,3,62,224,253,162,255,255,0,168,0,0,4,8,6,64,2,38,1,35,0,0,1,6,6,36,0,0,0,11,182,2,21,17,1,1,196,86,0,43,52,0,0,2,0,136,255,236,4,40,4,56,0,11,0,23,0,21,64,12,0,12,106,6,18,106,6,7,114,0,11,114,0,43,43,43,43,48,49,5,34,2,17,16,18,51,50,18,17,16,2,39,50,54,53,52,38,35,34,6,21,20,22,2,88,220,244,244,220,221,243,243,221,117,127,127,117,117,127,127,20,1,32,1,6,1,7,1,31,254,225,254,249,254,250,254,224,190,188,172,173,187,187,173,172,188,255,255,0,136,255,236,4,40,6,92,2,38,1,43,0,0,1,6,6,30,30,0,0,11,182,2,24,6,1,1,168,86,0,43,52,0,255,255,0,136,255,236,4,40,6,67,2,38,1,43,0,0,1,6,6,34,0,0,0,11,182,2,24,6,1,1,158,86,0,43,52,0,255,255,0,136,255,236,4,40,6,92,2,38,1,43,0,0,1,6,6,32,0,0,0,11,182,2,28,6,1,1,168,86,0,43,52,0,255,255,0,136,255,236,4,214,7,176,2,38,1,43,0,0,0,38,6,32,0,0,1,7,6,30,1,131,1,84,0,23,180,3,32,25,1,0,184,255,216,183,86,2,28,6,1,1,168,86,0,43,52,43,52,0,255,255,0,136,254,92,4,40,6,92,2,38,1,43,0,0,0,38,6,41,0,0,1,6,6,32,0,0,0,24,64,12,3,40,6,1,1,168,86,2,30,0,1,1,185,255,124,0,86,0,43,52,43,52,255,255,0,136,255,236,4,48,7,176,2,38,1,43,0,0,0,38,6,32,0,0,1,7,6,29,1,145,1,84,0,23,180,3,32,25,1,0,184,255,216,183,86,2,28,6,1,1,168,86,0,43,52,43,52,0,255,255,0,136,255,236,4,128,7,240,2,38,1,43,0,0,0,38,6,32,0,0,1,7,6,38,1,121,1,84,0,25,181,4,3,32,25,1,0,184,255,216,183,86,2,28,6,1,1,168,86,0,43,52,43,52,52,0,255,255,0,136,255,236,4,40,8,10,2,38,1,43,0,0,0,38,6,32,0,0,1,7,6,36,0,10,1,202,0,21,64,14,3,32,25,1,1,86,86,2,28,6,1,1,168,86,0,43,52,43,52,0,255,255,0,136,255,236,4,40,5,226,2,38,1,43,0,0,1,6,6,27,2,0,0,13,183,3,2,24,6,1,1,158,86,0,43,52,52,0,255,255,0,136,254,92,4,40,4,56,2,38,1,43,0,0,1,6,6,41,0,0,0,14,180,2,30,0,1,1,185,255,124,0,86,0,43,52,255,255,0,136,255,236,4,40,6,92,2,38,1,43,0,0,1,6,6,29,45,0,0,11,182,2,24,6,1,1,168,86,0,43,52,0,255,255,0,136,255,236,4,40,6,156,2,38,1,43,0,0,1,6,6,38,20,0,0,13,183,3,2,24,6,1,1,168,86,0,43,52,52,0,255,255,0,136,255,236,4,184,5,63,2,38,1,43,0,0,1,7,6,40,1,44,0,0,0,14,180,2,24,6,0,0,185,255,71,0,86,0,43,52,255,255,0,136,255,236,4,184,6,92,2,38,1,56,0,0,1,6,6,30,30,0,0,11,182,3,34,6,1,1,168,86,0,43,52,0,255,255,0,136,254,92,4,184,5,63,2,38,1,56,0,0,1,6,6,41,0,0,0,14,180,3,40,0,1,1,185,255,124,0,86,0,43,52,255,255,0,136,255,236,4,184,6,92,2,38,1,56,0,0,1,6,6,29,45,0,0,11,182,3,34,6,1,1,168,86,0,43,52,0,255,255,0,136,255,236,4,184,6,156,2,38,1,56,0,0,1,6,6,38,20,0,0,13,183,4,3,34,6,1,1,168,86,0,43,52,52,0,255,255,0,136,255,236,4,184,6,64,2,38,1,56,0,0,1,6,6,36,10,0,0,11,182,3,34,6,1,1,176,86,0,43,52,0,255,255,0,136,255,236,4,40,6,92,2,38,1,43,0,0,1,6,6,31,70,0,0,13,183,3,2,24,6,1,1,168,86,0,43,52,52,0,255,255,0,136,255,236,4,40,5,156,2,38,1,43,0,0,1,6,6,37,0,0,0,11,182,2,24,6,1,1,168,86,0,43,52,0,0,3,0,136,254,88,4,40,4,56,0,21,0,33,0,45,0,39,64,24,28,40,106,28,7,114,9,7,8,3,22,34,105,6,22,0,16,106,22,0,105,22,11,114,0,43,43,43,18,57,43,23,57,43,43,48,49,1,34,38,53,52,54,55,53,55,23,14,2,21,20,22,51,50,55,7,6,6,3,34,2,17,16,18,51,50,18,17,16,2,39,50,54,53,52,38,35,34,6,21,20,22,2,157,115,125,60,54,220,19,41,95,67,46,70,37,45,18,25,45,89,220,244,244,220,221,243,243,221,117,127,127,117,117,127,127,254,88,101,91,74,100,18,70,6,25,16,39,66,58,26,62,11,170,4,5,1,148,1,32,1,6,1,7,1,31,254,225,254,249,254,250,254,224,190,188,172,173,187,187,173,172,188,0,0,1,0,132,255,236,4,40,4,56,0,25,0,27,64,15,3,4,0,20,13,106,20,7,114,0,7,106,0,11,114,0,43,43,43,43,18,57,57,48,49,5,34,38,39,55,22,22,51,50,54,53,52,38,35,34,6,7,39,54,54,51,32,0,17,16,0,2,14,129,206,59,104,50,156,92,152,168,198,182,67,118,77,32,77,143,98,1,15,1,39,254,233,20,71,52,160,37,56,182,166,182,190,18,23,184,26,21,254,227,254,245,254,253,254,223,0,3,0,136,255,122,4,40,4,174,0,3,0,15,0,27,0,35,64,19,3,1,0,2,10,10,22,106,10,7,114,0,4,4,16,106,4,11,114,0,43,43,16,206,43,43,16,206,17,57,57,48,49,5,39,1,23,1,34,2,17,16,18,51,50,18,17,16,2,39,50,54,53,52,38,35,34,6,21,20,22,1,45,105,2,188,115,254,101,220,244,244,220,221,243,243,221,117,127,127,117,117,127,127,134,75,4,233,65,251,127,1,32,1,6,1,7,1,31,254,225,254,249,254,250,254,224,190,188,172,173,187,187,173,172,188,255,255,0,136,255,122,4,40,6,92,2,38,1,66,0,0,1,6,6,30,30,0,0,11,182,3,28,10,1,1,168,86,0,43,52,0,255,255,0,136,255,236,4,40,6,64,2,38,1,43,0,0,1,6,6,36,10,0,0,11,182,2,24,6,1,1,176,86,0,43,52,0,0,3,0,20,255,236,4,150,4,56,0,7,0,17,0,47,0,45,64,27,31,32,106,31,31,0,4,24,36,106,24,4,13,106,4,7,114,18,42,106,18,0,8,106,0,11,114,0,43,43,51,43,43,43,51,43,17,18,57,47,43,48,49,5,32,17,16,33,32,17,16,37,50,17,52,38,35,34,6,21,16,5,34,2,17,16,18,51,50,18,21,20,6,7,33,53,33,52,38,35,34,6,21,20,22,51,50,55,23,6,6,1,108,254,168,1,88,1,48,254,208,144,71,73,82,80,2,248,193,213,165,148,146,159,3,3,254,28,1,52,69,77,75,69,149,135,57,63,26,40,89,20,2,38,2,38,253,218,253,218,190,1,104,181,179,179,181,254,152,190,1,33,1,7,1,5,1,31,254,246,242,34,72,30,152,161,145,167,185,184,202,13,171,8,10,0,0,2,0,168,254,52,4,80,4,56,0,28,0,33,0,38,64,24,30,6,114,29,14,114,3,5,18,20,4,0,23,15,106,23,7,114,0,9,106,0,11,114,0,43,43,43,43,18,23,57,43,43,48,49,5,34,38,39,35,19,21,20,22,51,50,54,53,52,38,35,34,6,21,39,51,54,54,51,50,18,17,16,2,1,17,51,23,17,2,170,120,151,11,92,72,118,120,137,139,143,131,120,120,62,82,14,139,127,203,221,221,253,53,192,20,20,93,91,1,36,116,90,90,182,178,182,198,131,133,232,107,105,254,219,254,245,254,251,254,233,254,72,5,240,224,250,240,0,0,2,0,168,254,52,4,80,5,220,0,28,0,32,0,38,64,24,30,0,114,29,14,114,3,5,18,20,4,0,23,15,106,23,7,114,0,9,106,0,11,114,0,43,43,43,43,18,23,57,43,43,48,49,5,34,38,39,35,19,21,20,22,51,50,54,53,52,38,35,34,6,21,3,51,54,54,51,50,18,17,16,2,1,17,51,17,2,170,120,151,11,92,72,133,135,122,124,127,117,135,135,62,82,14,139,127,203,221,221,253,53,212,20,93,91,1,36,116,90,90,182,178,182,198,151,153,1,16,107,105,254,219,254,245,254,251,254,233,254,72,7,168,248,88,0,0,2,0,96,254,52,4,8,4,56,0,28,0,33,0,38,64,24,33,14,114,32,6,114,25,24,11,10,4,0,6,14,106,6,7,114,0,20,106,0,11,114,0,43,43,43,43,18,23,57,43,43,48,49,5,34,2,17,16,18,51,50,22,23,51,7,52,38,35,34,6,21,20,22,51,50,54,53,53,19,35,6,6,19,17,55,51,17,2,6,201,221,222,202,128,139,13,82,62,120,120,131,143,140,136,120,118,72,92,10,152,182,20,192,20,1,23,1,5,1,11,1,37,105,107,232,133,131,198,182,178,182,90,90,116,254,220,91,93,254,72,5,16,224,250,16,0,4,0,80,0,0,4,128,4,56,0,13,0,17,0,22,0,26,0,45,64,26,0,1,14,24,23,106,19,24,6,114,8,8,4,18,14,15,106,14,10,114,4,11,106,4,7,114,0,43,43,43,43,51,18,57,47,43,50,43,18,57,57,48,49,1,3,51,18,33,50,22,21,35,52,38,35,34,6,1,53,33,21,33,17,51,19,17,1,53,33,23,2,16,62,82,18,1,18,164,148,210,69,77,135,133,254,64,2,196,254,40,172,40,254,104,1,98,20,1,200,1,76,1,36,188,210,116,102,231,253,99,174,174,4,36,254,208,253,12,3,118,174,174,255,255,0,80,0,0,4,128,6,92,2,38,1,73,0,0,1,6,6,30,30,0,0,11,182,4,27,19,1,1,188,86,0,43,52,0,255,255,0,80,0,0,4,128,6,92,2,38,1,73,0,0,1,6,6,33,0,0,0,11,182,4,27,19,1,1,188,86,0,43,52,0,255,255,0,80,254,32,4,128,4,56,2,38,1,73,0,0,1,7,6,42,255,86,0,0,0,14,180,4,28,18,1,1,185,255,116,0,86,0,43,52,0,1,0,156,255,236,4,20,4,56,0,39,0,34,64,22,10,37,13,14,34,33,17,30,8,0,20,27,106,20,7,114,0,7,106,0,11,114,0,43,43,43,43,18,23,57,48,49,5,34,38,39,55,22,22,51,50,54,53,52,38,39,39,38,38,53,52,36,33,50,22,23,7,38,38,35,34,6,21,20,22,23,23,22,22,21,20,6,2,6,120,171,71,24,105,161,72,161,145,51,53,244,157,147,1,11,1,41,77,133,70,22,81,124,59,178,160,66,68,196,167,155,250,20,14,16,192,16,16,63,69,48,47,13,62,40,118,120,174,156,9,11,184,8,6,61,69,46,41,17,48,40,134,128,171,155,255,255,0,156,255,236,4,20,6,92,2,38,1,77,0,0,1,6,6,30,60,0,0,11,182,1,40,20,1,1,168,86,0,43,52,0,255,255,0,156,255,236,4,20,6,92,2,38,1,77,0,0,1,6,6,33,30,0,0,11,182,1,40,20,1,1,168,86,0,43,52,0,255,255,0,156,254,32,4,20,4,56,2,38,1,77,0,0,1,6,6,43,191,0,0,11,182,1,49,0,0,0,15,86,0,43,52,0,255,255,0,156,255,236,4,20,6,92,2,38,1,77,0,0,1,6,6,32,30,0,0,11,182,1,44,20,1,1,168,86,0,43,52,0,255,255,0,156,254,32,4,20,4,56,2,38,1,77,0,0,1,6,6,42,10,0,0,14,180,1,41,0,1,1,185,255,136,0,86,0,43,52,0,2,0,68,255,236,4,140,5,240,0,54,0,58,0,50,64,33,55,56,106,55,55,31,10,52,13,48,17,45,42,20,38,23,10,0,35,26,106,35,1,114,31,10,114,0,7,106,0,11,114,0,43,43,43,43,43,18,23,57,18,57,47,43,48,49,5,34,38,39,55,22,22,51,50,54,53,52,38,39,46,2,53,52,54,55,54,54,53,52,38,39,34,6,21,17,35,17,52,54,51,50,22,21,20,6,6,7,6,6,21,20,22,23,30,2,21,20,6,1,53,33,21,3,50,79,124,49,24,73,112,43,60,66,73,50,40,78,51,50,25,29,53,73,68,112,122,212,237,215,170,185,31,47,23,19,37,65,43,43,85,56,181,252,109,1,44,20,16,14,192,15,17,59,53,73,95,39,35,75,99,72,70,105,46,44,102,73,56,63,1,131,119,251,200,4,46,215,235,162,148,70,92,67,35,36,73,57,49,85,47,40,91,111,71,146,160,2,152,176,176,0,0,2,0,68,0,0,4,100,5,240,0,12,0,16,0,27,64,15,13,14,106,13,13,0,3,9,106,3,1,114,0,10,114,0,43,43,43,18,57,47,43,48,49,33,17,16,33,50,23,7,38,38,35,34,17,17,1,53,33,21,1,166,1,216,120,110,22,66,101,47,254,253,202,1,244,3,202,2,38,20,184,8,6,254,162,252,44,2,132,176,176,0,0,3,0,60,255,236,4,36,5,100,0,15,0,19,0,23,0,35,64,20,4,21,16,16,0,21,20,106,21,17,105,21,6,114,0,9,106,0,11,114,0,43,43,43,43,43,18,57,47,18,57,48,49,5,34,38,53,53,51,21,20,22,51,50,54,55,23,6,6,1,17,51,17,1,53,33,21,3,14,241,215,212,123,141,50,112,72,24,70,133,253,237,212,254,34,3,192,20,200,220,180,170,126,114,11,9,186,12,12,2,8,3,112,252,144,1,130,174,174,0,0,4,0,60,255,236,4,36,5,100,0,3,0,19,0,23,0,27,0,37,64,23,1,0,106,20,8,1,3,4,25,24,106,25,21,105,25,6,114,4,13,106,4,11,114,0,43,43,43,43,43,18,23,57,43,48,49,19,53,33,21,3,34,38,53,53,51,21,20,22,51,50,54,55,23,6,6,1,17,51,17,1,53,33,21,60,3,192,238,241,215,212,123,141,50,112,72,24,70,133,253,237,212,254,34,3,192,1,240,174,174,253,252,200,220,180,170,126,114,11,9,186,12,12,2,8,3,112,252,144,1,130,174,174,0,4,0,60,255,236,4,36,6,32,0,3,0,19,0,23,0,27,0,41,64,24,20,8,4,25,0,1,106,0,25,25,24,106,25,21,105,25,6,114,4,13,106,4,11,114,0,43,43,43,43,43,16,204,43,17,18,57,57,48,49,1,19,51,3,3,34,38,53,53,51,21,20,22,51,50,54,55,23,6,6,1,17,51,17,1,53,33,21,2,170,50,212,90,72,241,215,212,123,141,50,112,72,24,70,133,253,237,212,254,34,3,192,4,164,1,124,254,132,251,72,200,220,180,170,126,114,11,9,186,12,12,2,8,3,112,252,144,1,130,174,174,255,255,0,60,254,32,4,36,5,100,2,38,1,85,0,0,1,6,6,43,236,0,0,11,182,3,33,0,0,0,15,86,0,43,52,0,255,255,0,60,254,32,4,36,5,100,2,38,1,85,0,0,1,6,6,42,55,0,0,14,180,3,25,0,1,1,185,255,136,0,86,0,43,52,0,5,0,0,254,35,4,200,5,160,0,15,0,19,0,23,0,38,0,50,0,50,64,33,39,40,106,39,15,114,28,34,106,21,28,105,24,45,19,5,4,0,21,20,106,21,17,105,21,6,114,0,9,106,0,11,114,0,43,43,43,43,43,18,23,57,43,43,43,43,48,49,5,34,38,53,53,51,21,20,22,51,50,54,55,23,6,6,1,17,51,17,1,53,33,21,3,17,52,54,51,50,22,23,7,38,35,34,6,21,17,1,39,55,54,54,53,17,51,17,20,6,5,1,246,166,150,212,59,65,18,41,25,24,32,61,254,161,212,254,114,3,102,118,166,166,36,73,31,22,39,45,73,81,253,182,10,118,140,126,212,236,254,250,20,143,157,220,210,63,57,6,4,186,7,7,1,184,3,192,252,64,1,210,174,174,253,242,2,188,191,189,7,8,184,9,94,86,253,58,252,187,188,12,14,123,122,1,146,254,142,237,230,18,0,3,0,156,255,236,4,134,4,36,0,16,0,23,0,27,0,39,64,23,23,21,106,23,10,114,12,20,24,3,14,14,0,25,4,6,114,0,9,106,0,11,114,0,43,43,43,50,17,57,47,23,57,43,43,48,49,5,34,38,53,17,51,17,20,22,51,50,54,53,19,35,6,6,55,39,53,51,21,23,21,1,17,51,17,1,250,167,183,212,104,94,116,118,54,70,25,146,205,18,212,146,254,154,212,20,199,181,2,188,253,68,91,99,147,173,254,226,108,116,10,254,186,238,22,170,1,44,2,248,253,68,255,255,0,156,255,236,4,134,6,92,2,38,1,91,0,0,1,6,6,30,20,0,0,11,182,3,28,4,1,1,188,86,0,43,52,0,255,255,0,156,255,236,4,134,6,67,2,38,1,91,0,0,1,6,6,34,246,0,0,11,182,3,28,4,1,1,178,86,0,43,52,0,255,255,0,156,255,236,4,134,6,92,2,38,1,91,0,0,1,6,6,32,246,0,0,11,182,3,32,4,1,1,188,86,0,43,52,0,255,255,0,156,255,236,4,134,5,226,2,38,1,91,0,0,1,6,6,27,248,0,0,13,183,4,3,28,4,1,1,178,86,0,43,52,52,0,255,255,0,156,254,92,4,134,4,36,2,38,1,91,0,0,1,6,6,41,226,0,0,14,180,3,34,0,1,1,185,255,124,0,86,0,43,52,255,255,0,156,255,236,4,134,6,92,2,38,1,91,0,0,1,6,6,29,35,0,0,11,182,3,28,4,1,1,188,86,0,43,52,0,255,255,0,156,255,236,4,134,6,156,2,38,1,91,0,0,1,6,6,38,10,0,0,13,183,4,3,28,4,1,1,188,86,0,43,52,52,0,0,4,0,156,255,236,4,214,5,63,0,9,0,26,0,33,0,37,0,47,64,30,33,31,106,33,10,114,24,34,37,30,22,5,10,35,14,5,105,1,14,0,105,14,6,114,10,19,106,10,11,114,0,43,43,43,43,51,43,51,18,23,57,43,43,48,49,1,39,55,54,54,53,51,20,6,7,1,34,38,53,17,51,17,20,22,51,50,54,53,19,35,6,6,55,39,53,51,21,23,21,1,17,51,17,3,83,50,40,93,84,220,165,182,254,127,167,183,212,104,94,116,118,54,70,25,146,205,18,212,146,254,154,212,3,127,165,10,23,130,120,184,208,46,252,99,199,181,2,188,253,68,91,99,147,173,254,226,108,116,10,254,186,238,22,170,1,44,2,248,253,68,255,255,0,156,255,236,4,214,6,92,2,38,1,99,0,0,1,6,6,30,20,0,0,11,182,4,38,14,1,1,188,86,0,43,52,0,255,255,0,156,254,92,4,214,5,63,2,38,1,99,0,0,1,6,6,41,226,0,0,14,180,4,44,10,1,1,185,255,124,0,86,0,43,52,255,255,0,156,255,236,4,214,6,92,2,38,1,99,0,0,1,6,6,29,35,0,0,14,180,4,38,5,1,0,185,255,161,0,86,0,43,52,255,255,0,156,255,236,4,214,6,156,2,38,1,99,0,0,1,6,6,38,10,0,0,16,181,5,4,38,5,1,0,185,255,161,0,86,0,43,52,52,255,255,0,156,255,236,4,214,6,64,2,38,1,99,0,0,1,6,6,36,0,0,0,11,182,4,38,14,1,1,196,86,0,43,52,0,255,255,0,156,255,236,4,134,6,92,2,38,1,91,0,0,1,6,6,31,60,0,0,13,183,4,3,28,4,1,1,188,86,0,43,52,52,0,255,255,0,156,255,236,4,134,5,156,2,38,1,91,0,0,1,6,6,37,246,0,0,11,182,3,28,4,1,1,188,86,0,43,52,0,0,4,0,156,254,88,4,134,4,36,0,20,0,37,0,44,0,48,0,54,64,33,8,7,44,42,105,6,15,9,44,10,33,41,48,45,35,5,21,46,25,6,114,15,0,106,21,15,105,21,30,106,21,11,114,0,43,43,43,43,43,50,17,23,57,63,51,18,57,43,57,57,48,49,1,34,38,53,52,54,55,53,55,23,34,6,21,20,22,51,50,55,7,6,6,1,34,38,53,17,51,17,20,22,51,50,54,53,19,35,6,6,55,39,53,51,21,23,21,1,17,51,17,3,252,115,125,59,55,240,20,106,118,61,55,35,47,18,23,47,253,234,167,183,212,104,94,116,118,54,70,25,146,205,18,212,146,254,154,212,254,88,111,101,68,93,16,65,2,32,88,80,42,46,11,170,4,5,1,148,199,181,2,188,253,68,91,99,147,173,254,226,108,116,10,254,186,238,22,170,1,44,2,248,253,68,255,255,0,156,255,236,4,134,6,94,2,38,1,91,0,0,1,6,6,35,246,0,0,13,183,4,3,28,4,1,1,138,86,0,43,52,52,0,255,255,0,156,255,236,4,134,6,64,2,38,1,91,0,0,1,6,6,36,0,0,0,11,182,3,28,4,1,1,196,86,0,43,52,0,0,1,0,80,0,0,4,96,4,36,0,7,0,19,64,10,6,1,6,114,0,3,106,0,10,114,0,43,43,43,50,48,49,33,1,51,1,51,1,51,1,1,208,254,128,226,1,34,18,1,24,226,254,138,4,36,252,144,3,112,251,220,255,255,0,95,0,0,4,81,4,36,2,6,2,25,0,0,0,2,0,70,0,0,4,106,4,36,0,9,0,19,0,33,64,18,18,11,2,105,16,8,3,11,6,114,5,10,13,106,0,10,10,114,0,43,50,43,50,43,50,50,50,43,50,48,49,33,3,35,39,51,19,51,19,51,3,33,3,51,19,51,19,51,7,35,3,2,208,124,16,87,194,125,18,90,210,150,252,234,120,200,80,18,125,194,89,14,124,3,74,218,252,124,3,132,251,220,4,36,252,124,3,132,218,252,182,0,255,255,0,70,0,0,4,106,6,92,2,38,1,112,0,0,1,6,6,30,20,0,0,11,182,2,20,3,1,1,188,86,0,43,52,0,255,255,0,70,0,0,4,106,6,92,2,38,1,112,0,0,1,6,6,32,246,0,0,11,182,2,24,3,1,1,188,86,0,43,52,0,255,255,0,70,0,0,4,106,5,226,2,38,1,112,0,0,1,6,6,27,248,0,0,13,183,3,2,20,7,1,1,178,86,0,43,52,52,0,255,255,0,70,0,0,4,106,6,92,2,38,1,112,0,0,1,6,6,29,35,0,0,11,182,2,20,3,1,1,188,86,0,43,52,0,0,2,0,106,0,0,4,70,4,36,0,5,0,11,0,26,64,14,7,4,1,10,4,11,3,8,6,114,11,0,10,114,0,43,50,43,50,18,23,57,48,49,51,1,1,51,1,1,33,1,1,51,1,1,106,1,166,1,70,240,254,74,254,202,1,252,254,190,254,86,240,1,70,1,166,2,72,1,220,253,166,254,54,1,202,2,90,254,36,253,184,0,0,2,0,55,254,32,4,91,4,36,0,13,0,19,0,27,64,16,8,15,6,114,14,17,106,14,10,114,0,1,106,0,15,114,0,43,43,43,43,43,50,48,49,19,39,55,62,2,55,1,51,1,14,2,7,19,1,51,1,51,21,75,10,166,105,149,106,40,1,8,220,254,206,60,149,203,142,222,254,90,220,1,90,32,254,32,190,20,13,88,173,140,3,148,252,58,190,232,116,16,1,204,4,36,252,124,160,0,255,255,0,55,254,32,4,91,6,92,2,38,1,118,0,0,1,6,6,30,45,0,0,11,182,2,20,7,1,1,188,86,0,43,52,0,255,255,0,55,254,32,4,91,6,92,2,38,1,118,0,0,1,6,6,32,15,0,0,11,182,2,24,7,1,1,188,86,0,43,52,0,255,255,0,55,254,32,4,91,5,226,2,38,1,118,0,0,1,6,6,27,17,0,0,13,183,3,2,20,7,1,1,178,86,0,43,52,52,0,255,255,0,55,254,32,4,91,4,36,2,38,1,118,0,0,1,7,6,41,1,89,0,0,0,11,182,2,20,0,2,0,60,86,0,43,52,0,255,255,0,55,254,32,4,91,6,92,2,38,1,118,0,0,1,6,6,29,60,0,0,11,182,2,20,7,1,1,188,86,0,43,52,0,255,255,0,55,254,32,4,91,6,156,2,38,1,118,0,0,1,6,6,38,35,0,0,13,183,3,2,20,7,1,1,188,86,0,43,52,52,0,255,255,0,55,254,32,4,91,5,156,2,38,1,118,0,0,1,6,6,37,15,0,0,11,182,2,20,15,1,1,188,86,0,43,52,0,255,255,0,55,254,32,4,91,6,64,2,38,1,118,0,0,1,6,6,36,25,0,0,11,182,2,20,15,1,1,196,86,0,43,52,0,0,3,0,160,0,0,4,12,4,36,0,3,0,7,0,11,0,33,64,18,0,5,4,2,3,9,8,106,9,6,114,1,4,5,106,4,10,114,0,43,43,50,43,43,50,57,17,18,57,48,49,37,39,1,23,1,53,33,21,1,53,33,21,1,50,146,2,198,146,252,168,3,108,252,148,3,88,54,122,3,58,118,252,140,176,176,3,116,176,176,255,255,0,160,0,0,4,12,6,92,2,38,1,127,0,0,1,6,6,30,30,0,0,11,182,3,12,9,1,1,188,86,0,43,52,0,255,255,0,160,0,0,4,12,6,92,2,38,1,127,0,0,1,6,6,33,0,0,0,11,182,3,12,9,1,1,188,86,0,43,52,0,255,255,0,160,0,0,4,12,5,226,2,38,1,127,0,0,1,6,6,28,254,0,0,11,182,3,12,9,1,1,178,86,0,43,52,0,0,3,0,96,255,236,5,4,6,32,0,25,0,30,0,34,0,46,64,30,30,10,114,32,34,106,28,32,105,28,0,114,23,21,11,9,4,0,6,13,106,6,7,114,0,18,106,0,11,114,0,43,43,43,43,18,23,57,43,43,43,43,48,49,5,34,2,17,16,18,51,50,22,23,51,3,16,35,34,6,21,16,51,50,53,53,19,35,6,6,55,39,17,51,17,19,19,51,3,1,222,192,190,191,193,110,118,12,82,62,210,112,112,226,208,72,92,10,129,181,22,212,90,50,192,90,20,1,13,1,15,1,25,1,23,105,107,254,240,1,48,189,191,254,152,180,116,254,220,91,93,10,208,5,22,250,36,4,164,1,124,254,132,0,0,5,0,242,254,32,4,117,6,92,0,12,0,16,0,20,0,24,0,28,0,39,64,22,26,21,22,106,25,21,6,17,13,18,14,6,114,13,10,114,0,1,106,0,15,114,0,43,43,43,43,50,18,57,57,206,50,43,50,48,49,19,39,55,54,54,53,17,51,17,20,6,6,7,3,17,51,17,1,17,51,17,1,19,51,3,33,19,51,3,252,10,200,161,145,212,112,238,188,178,212,1,36,212,253,67,170,212,190,1,52,170,212,190,254,32,188,18,14,159,163,1,66,254,222,189,238,121,14,1,212,4,36,251,220,1,94,2,198,253,58,3,130,1,124,254,132,1,124,254,132,0,255,255,0,136,255,236,4,73,6,112,2,38,0,222,0,0,1,6,6,73,80,0,0,11,182,1,26,6,1,1,168,86,0,43,52,0,255,255,0,168,0,0,4,8,6,112,2,38,1,35,0,0,1,6,6,73,20,0,0,11,182,2,21,17,1,1,188,86,0,43,52,0,255,255,0,136,255,236,4,40,6,112,2,38,1,43,0,0,1,6,6,73,30,0,0,11,182,2,24,6,1,1,168,86,0,43,52,0,255,255,0,156,255,236,4,20,6,112,2,38,1,77,0,0,1,6,6,73,60,0,0,11,182,1,40,20,1,1,168,86,0,43,52,0,255,255,0,160,0,0,4,12,6,112,2,38,1,127,0,0,1,6,6,73,30,0,0,11,182,3,12,9,1,1,188,86,0,43,52,0,255,255,0,121,0,188,4,55,4,164,2,6,3,69,0,0,0,10,246,230,0,0,4,106,4,36,0,9,0,19,0,27,0,35,0,43,0,51,0,59,0,67,0,75,0,83,0,137,64,76,19,20,20,35,35,36,36,51,51,52,52,67,67,68,68,83,83,9,26,14,30,30,42,46,46,58,62,62,74,78,78,9,6,106,80,3,2,106,38,31,34,105,40,31,70,63,66,105,72,63,54,47,50,105,56,47,22,15,18,105,24,15,15,47,63,31,3,5,8,9,10,114,11,8,6,114,0,43,50,43,17,23,57,17,51,43,50,17,51,43,50,17,51,43,50,17,51,43,50,43,51,43,50,17,51,51,17,51,51,17,51,51,17,51,51,17,51,17,51,17,51,17,51,17,51,17,51,17,51,17,51,17,51,48,49,33,3,35,39,51,19,51,19,51,3,33,3,51,19,51,19,51,7,35,3,33,3,35,39,51,19,51,21,35,53,51,19,51,7,35,3,33,3,35,39,51,19,51,21,35,53,51,19,51,7,35,3,33,3,35,39,51,19,51,21,35,53,51,19,51,7,35,3,33,3,35,39,51,19,51,21,35,53,51,19,51,7,35,3,2,218,158,50,66,220,154,20,80,200,110,243,88,110,200,80,20,154,220,86,30,158,1,62,148,50,66,220,164,20,20,20,174,220,86,30,158,1,62,148,50,66,220,164,20,20,20,184,220,86,30,168,1,92,168,50,66,220,184,20,20,20,164,220,86,30,148,1,62,158,50,66,220,174,20,20,20,164,220,86,30,148,2,230,198,252,244,3,132,251,220,4,36,252,124,3,12,198,253,26,2,230,198,252,244,160,160,3,12,198,253,26,2,230,198,252,244,160,160,3,12,198,253,26,2,230,198,252,244,160,160,3,12,198,253,26,2,230,198,252,244,160,160,3,12,198,253,26,0,0,2,1,28,3,5,3,226,5,160,0,15,0,42,0,35,64,21,33,39,36,29,22,5,8,16,15,13,106,15,8,16,105,8,7,106,8,17,114,0,43,43,43,50,43,17,18,23,57,48,49,1,39,7,53,52,38,35,35,55,23,22,22,21,21,23,21,5,34,38,53,52,54,51,50,22,23,7,38,38,35,34,21,20,51,50,54,53,53,23,35,55,6,6,2,233,8,16,88,87,185,11,162,180,173,107,254,19,103,114,149,136,67,105,40,26,46,90,46,114,86,88,88,36,61,20,25,92,3,11,185,1,215,56,60,146,1,1,143,136,249,13,112,12,101,92,104,113,12,14,108,8,2,76,74,84,46,39,164,7,73,75,0,2,1,2,3,2,3,174,5,160,0,11,0,23,0,21,64,12,0,12,106,6,0,105,6,18,106,6,17,114,0,43,43,43,43,48,49,1,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,2,88,154,188,188,154,155,187,187,155,71,86,86,71,71,86,86,3,2,184,151,152,183,183,152,151,184,150,102,83,83,102,102,83,83,102,0,0,2,1,33,3,22,3,130,5,160,0,15,0,20,0,27,64,15,17,16,114,8,6,20,11,0,105,11,3,106,11,17,114,0,43,43,43,50,57,57,43,48,49,1,17,52,35,34,6,21,39,51,54,54,51,50,22,21,17,33,17,51,23,17,2,200,115,60,60,37,48,5,84,71,119,131,253,159,176,12,3,22,1,135,125,71,71,149,61,66,123,111,254,96,2,126,135,254,9,0,255,255,0,45,0,0,4,131,5,140,2,6,0,1,0,0,0,3,0,160,0,0,4,96,5,140,0,17,0,21,0,25,0,35,64,20,9,10,106,9,9,18,23,19,22,106,19,2,114,0,1,106,0,18,8,114,0,43,50,43,43,43,51,18,57,47,43,48,49,33,53,33,50,54,53,52,38,35,33,39,33,50,22,21,20,6,35,33,17,51,17,3,53,33,21,1,90,1,30,133,145,145,133,254,230,24,1,108,205,225,225,205,253,238,200,158,3,46,190,132,121,111,122,190,221,202,211,232,5,140,250,116,4,206,190,190,255,255,0,160,0,0,4,110,5,140,2,6,0,27,0,0,0,2,0,180,0,0,4,66,5,140,0,3,0,7,0,19,64,10,5,4,106,5,1,2,114,0,8,114,0,43,43,50,43,48,49,51,17,51,17,3,53,33,21,180,200,200,3,142,5,140,250,116,4,206,190,190,255,255,0,180,0,0,4,66,7,38,2,38,1,146,0,0,1,6,6,63,20,0,0,11,182,2,8,1,1,1,160,86,0,43,52,0,0,3,0,180,0,0,4,86,6,194,0,3,0,7,0,11,0,23,64,13,8,5,4,106,5,9,105,5,2,114,0,8,114,0,43,43,43,43,57,48,49,51,17,51,17,3,53,33,21,39,17,51,17,180,200,200,3,162,200,200,5,140,250,116,4,206,190,190,40,1,204,254,52,0,0,6,0,30,254,222,4,146,5,140,0,13,0,17,0,21,0,25,0,29,0,33,0,40,64,23,1,0,19,15,4,32,33,106,18,14,96,22,32,8,114,27,7,26,106,23,7,2,114,0,43,50,43,51,43,50,26,206,50,43,23,57,48,49,37,39,62,3,53,17,51,17,20,14,2,1,17,51,17,33,17,51,17,1,17,51,17,1,53,33,21,19,21,33,53,1,40,180,30,45,30,16,185,15,31,47,254,213,200,2,228,200,254,186,200,253,65,2,108,209,251,140,155,25,43,161,198,203,84,2,39,253,223,87,208,206,171,254,19,1,164,254,92,1,164,254,92,1,34,5,140,250,116,4,206,190,190,251,240,190,190,0,255,255,0,160,0,0,4,76,5,140,2,6,0,38,0,0,255,255,0,160,0,0,4,76,7,38,2,38,1,150,0,0,1,6,6,62,30,0,0,11,182,4,16,1,1,1,160,86,0,43,52,0,255,255,0,160,0,0,4,76,7,56,2,38,1,150,0,0,1,6,6,60,30,0,0,13,183,5,4,16,1,1,1,160,86,0,43,52,52,0,0,7,0,27,255,251,4,149,5,145,0,19,0,39,0,43,0,63,0,67,0,87,0,91,0,80,64,46,54,53,106,54,65,77,30,44,0,4,89,76,88,88,43,1,89,89,63,43,42,106,31,43,43,65,64,10,11,106,10,65,2,114,87,86,106,87,64,20,21,106,20,64,8,114,0,43,50,43,17,51,43,43,50,43,17,18,57,47,51,43,50,50,17,51,17,51,17,51,18,23,57,17,51,43,48,49,1,55,50,54,54,53,17,52,54,51,51,21,35,34,6,21,17,20,6,7,1,53,51,50,54,53,17,52,54,55,55,7,34,6,6,21,17,20,6,35,19,53,51,21,39,39,38,38,53,17,52,38,35,35,53,51,50,22,21,17,20,22,22,51,19,17,51,17,5,34,38,53,17,52,38,38,35,39,23,22,22,21,17,20,22,51,51,21,1,53,51,21,3,15,48,39,33,6,89,85,90,23,19,30,85,69,252,104,23,19,30,85,69,164,48,39,32,7,88,86,162,236,98,164,69,85,30,19,23,90,86,88,7,32,39,146,170,1,142,85,89,6,33,39,48,164,69,85,30,19,23,254,24,226,2,212,81,15,40,36,1,76,104,93,190,30,34,254,216,64,72,5,253,29,190,30,34,1,40,65,72,4,10,81,15,39,37,254,180,103,94,2,108,190,190,109,10,5,72,64,1,40,34,30,190,93,104,254,180,36,40,15,252,219,5,140,250,116,5,94,103,1,76,37,39,15,81,10,4,72,65,254,216,34,30,190,2,108,190,190,0,1,0,64,255,236,4,48,5,160,0,46,0,37,64,20,36,39,15,2,3,14,14,0,30,21,106,30,3,114,0,7,106,0,9,114,0,43,43,43,43,18,57,47,57,57,205,57,57,48,49,5,32,39,55,30,2,51,50,54,53,52,38,35,35,39,54,54,53,52,38,35,34,6,6,7,39,62,2,51,32,4,21,20,6,7,55,21,39,30,2,21,20,6,6,2,54,254,204,194,144,63,108,116,76,137,156,182,148,150,22,242,208,159,183,40,86,88,43,25,31,89,108,57,1,31,1,0,168,194,17,17,109,191,118,123,227,20,171,141,46,56,26,133,118,114,123,188,8,104,106,83,114,12,18,10,184,10,18,13,192,155,127,161,42,56,117,54,2,83,160,117,125,187,102,0,0,3,0,148,0,0,4,28,5,140,0,7,0,11,0,15,0,29,64,14,14,4,4,1,6,12,9,2,114,12,7,8,8,114,0,43,50,50,43,17,57,57,50,17,51,48,49,33,17,51,1,51,17,35,1,35,17,51,17,33,17,51,17,1,2,102,1,224,60,60,254,32,212,192,2,8,192,1,94,4,46,254,162,251,210,5,140,250,116,5,140,250,116,0,255,255,0,148,0,0,4,28,7,68,2,38,1,155,0,0,1,6,6,80,0,0,0,11,182,3,16,13,1,1,150,86,0,43,52,0,255,255,0,148,0,0,4,28,7,38,2,38,1,155,0,0,1,6,6,62,0,0,0,11,182,3,16,9,1,1,160,86,0,43,52,0,0,4,0,140,255,251,4,106,5,145,0,19,0,23,0,27,0,47,0,49,64,27,19,38,1,36,36,1,24,25,106,24,24,20,21,10,11,106,10,21,2,114,47,46,106,47,20,8,114,0,43,50,43,43,50,43,17,18,57,47,43,50,51,17,18,57,57,48,49,1,55,50,54,55,55,62,2,51,51,21,35,34,6,7,7,6,6,35,1,17,51,17,3,53,33,21,1,34,38,38,39,39,38,38,35,39,51,50,22,23,23,22,22,51,51,21,2,23,11,98,74,19,38,21,58,102,87,68,48,46,36,14,53,22,93,121,253,230,200,45,1,77,1,169,87,102,58,21,38,18,78,105,11,143,128,105,22,53,14,36,46,48,2,212,81,79,90,184,101,116,50,190,48,56,213,88,106,253,44,5,140,250,116,2,103,190,190,253,148,50,117,100,184,89,80,81,106,88,213,56,48,190,255,255,0,140,255,251,4,106,7,38,2,38,1,158,0,0,1,6,6,63,0,0,0,11,182,4,48,21,1,1,160,86,0,43,52,0,0,3,0,37,0,0,4,36,5,140,0,12,0,16,0,20,0,27,64,15,0,1,106,0,16,8,114,18,17,106,18,15,6,2,114,0,43,50,50,43,43,50,43,48,49,55,53,50,54,54,53,17,51,17,20,14,2,5,17,51,17,1,53,33,21,37,104,91,22,185,23,78,162,2,172,200,253,50,2,169,1,190,103,190,130,3,38,252,225,144,229,161,86,1,5,140,250,116,4,206,190,190,255,255,0,128,0,0,4,48,5,140,2,6,0,93,0,0,255,255,0,140,0,0,4,36,5,140,2,6,0,66,0,0,255,255,0,76,255,236,4,100,5,160,2,6,0,101,0,0,0,3,0,140,0,0,4,36,5,140,0,3,0,7,0,11,0,27,64,14,0,4,1,5,9,8,106,9,5,2,114,4,8,114,0,43,43,50,43,17,51,17,51,48,49,33,17,51,17,33,17,51,17,3,53,33,21,3,92,200,252,104,200,158,3,73,5,140,250,116,5,140,250,116,4,206,190,190,255,255,0,160,0,0,4,96,5,140,2,6,0,128,0,0,255,255,0,96,255,236,4,125,5,160,2,6,0,28,0,0,255,255,0,80,0,0,4,96,5,140,2,6,0,143,0,0,0,2,0,96,0,0,4,152,5,140,0,11,0,16,0,27,64,14,16,12,7,0,7,13,2,114,0,1,106,0,8,114,0,43,43,43,50,17,18,57,57,48,49,51,53,50,54,54,55,1,51,1,14,2,55,1,51,1,51,203,140,179,111,38,1,29,220,254,163,52,149,237,189,254,30,220,1,95,34,190,50,122,108,3,182,251,220,138,157,65,200,4,196,252,114,0,255,255,0,96,0,0,4,152,7,68,2,38,1,168,0,0,1,6,6,80,50,0,0,11,182,2,17,6,1,1,150,86,0,43,52,0,0,3,0,66,255,236,4,110,5,180,0,7,0,19,0,27,0,41,64,25,11,16,15,12,4,4,24,105,9,18,17,10,4,0,20,105,4,0,8,13,3,114,8,9,114,0,43,43,18,57,57,43,23,57,43,23,57,48,49,37,32,17,16,33,32,17,16,5,53,55,17,39,53,51,21,7,17,23,21,3,32,17,16,33,32,17,16,2,88,253,234,2,22,2,22,253,148,10,10,170,10,10,84,1,78,254,178,254,178,140,2,58,2,78,253,178,253,198,160,228,63,3,150,59,212,212,59,252,106,63,228,1,68,1,150,1,170,254,86,254,106,0,255,255,0,66,0,0,4,112,5,140,2,6,0,174,0,0,0,2,0,140,0,0,4,36,5,140,0,11,0,15,0,27,64,14,14,4,0,9,106,0,0,15,4,2,114,15,8,114,0,43,43,17,57,47,43,17,51,48,49,1,34,38,53,17,51,17,20,22,51,33,21,3,17,51,17,2,68,232,208,200,114,126,1,42,18,200,2,33,227,253,1,139,254,117,152,138,190,253,223,5,140,250,116,0,0,4,0,140,254,222,4,136,5,140,0,3,0,7,0,11,0,15,0,31,64,16,1,9,2,114,13,4,5,106,0,4,4,12,96,8,8,114,0,43,26,206,51,17,51,43,50,43,50,48,49,33,17,51,17,33,53,33,21,33,17,51,17,1,17,51,17,3,82,200,252,156,3,208,252,6,200,2,108,200,5,140,250,116,190,190,5,140,250,116,254,222,1,224,254,32,0,4,0,128,0,0,4,48,5,140,0,3,0,7,0,11,0,15,0,37,64,19,12,8,13,9,0,8,1,9,4,5,106,4,8,9,2,114,8,8,114,0,43,43,17,51,43,17,51,17,51,17,51,17,51,48,49,33,17,51,17,33,53,33,21,33,17,51,17,51,17,51,17,3,104,200,252,122,3,97,252,117,200,187,170,5,140,250,116,180,180,5,140,250,116,5,140,250,116,0,0,5,0,128,254,222,4,136,5,140,0,3,0,7,0,11,0,15,0,19,0,39,64,20,1,17,17,9,2,114,0,16,16,8,14,4,5,106,4,12,96,8,8,114,0,43,26,206,51,43,50,17,51,17,51,43,50,17,51,48,49,33,17,51,17,33,53,33,21,33,17,51,17,1,17,51,17,1,17,51,17,3,104,200,252,122,3,97,252,117,200,2,120,200,253,123,170,5,140,250,116,180,180,5,140,250,116,254,222,1,214,254,42,1,34,5,140,250,116,0,0,4,0,140,254,222,4,36,5,140,0,3,0,7,0,11,0,15,0,33,64,18,1,13,2,114,4,96,12,8,114,6,0,8,9,106,0,8,8,114,0,43,50,43,17,57,43,26,206,43,50,48,49,33,17,51,17,1,17,51,17,1,53,33,21,33,17,51,17,3,92,200,253,208,200,253,208,3,152,252,104,200,5,140,250,116,254,222,1,164,254,92,1,34,190,190,5,140,250,116,0,2,0,160,0,0,4,110,5,140,0,19,0,23,0,31,64,17,0,1,106,0,20,10,9,106,10,10,20,21,2,114,20,8,114,0,43,43,17,57,47,43,17,51,43,48,49,33,53,33,50,54,53,52,38,35,33,53,33,50,22,22,21,20,6,6,35,33,17,51,17,1,90,1,44,126,152,152,126,254,192,1,122,130,193,107,107,193,130,253,224,200,190,147,121,122,146,190,114,206,138,138,206,114,5,140,250,116,0,3,0,0,0,0,4,110,5,140,0,19,0,23,0,27,0,39,64,22,22,25,0,1,106,0,20,10,9,106,10,10,20,25,24,106,25,2,114,20,8,114,0,43,43,43,18,57,47,43,17,51,43,17,51,48,49,33,53,51,50,54,53,52,38,35,35,53,33,50,22,22,21,20,6,6,35,33,17,51,17,1,53,33,21,1,180,210,126,152,152,126,230,1,32,130,193,107,107,193,130,254,58,200,254,62,1,68,190,147,121,122,146,190,114,206,138,138,206,114,5,140,250,116,4,206,190,190,0,3,0,128,0,0,4,48,5,140,0,19,0,23,0,27,0,39,64,21,24,20,25,21,0,1,106,0,20,10,9,106,10,10,20,21,2,114,20,8,114,0,43,43,17,57,47,43,17,51,43,17,51,17,51,48,49,33,53,51,50,54,53,52,38,35,35,53,51,50,22,22,21,20,6,6,35,33,17,51,17,33,17,51,17,1,58,82,76,92,92,76,102,160,91,134,75,75,134,91,254,186,200,2,42,190,190,147,121,122,146,190,114,206,138,138,206,114,5,140,250,116,5,140,250,116,0,4,0,53,0,0,4,100,5,140,0,10,0,14,0,34,0,38,0,45,64,26,36,35,106,36,5,25,24,106,25,25,0,12,5,2,114,15,16,106,15,11,0,1,106,0,8,114,0,43,43,51,51,43,43,50,17,57,47,43,17,51,43,48,49,51,53,50,54,53,17,51,17,20,6,6,33,17,51,17,35,53,51,50,54,53,52,38,35,35,53,51,50,22,22,21,20,6,6,35,1,53,33,21,53,96,71,160,60,142,1,131,180,24,85,58,70,70,58,105,163,79,116,65,65,116,79,253,166,1,179,190,109,146,3,207,252,56,173,198,81,5,140,250,116,190,147,121,122,146,190,114,206,138,138,206,114,4,206,190,190,0,0,4,0,128,0,0,4,100,5,140,0,19,0,23,0,27,0,33,0,51,64,28,28,20,29,21,0,1,106,0,20,24,25,106,24,24,20,21,10,9,106,10,10,20,21,2,114,20,8,114,0,43,43,17,57,47,43,17,18,57,47,43,17,51,43,17,51,17,51,48,49,33,53,51,50,54,53,52,38,35,35,53,51,50,22,22,21,20,6,6,35,33,17,51,17,3,53,33,21,3,17,51,17,21,17,2,208,76,62,76,76,62,76,134,82,121,67,67,121,82,253,42,200,158,2,19,157,200,190,147,121,122,146,190,114,206,138,138,206,114,5,140,250,116,2,100,190,190,253,156,5,140,253,175,20,252,217,0,255,255,0,129,255,236,4,37,5,160,2,6,0,135,0,0,0,2,0,96,255,236,4,125,5,160,0,21,0,25,0,37,64,21,22,23,106,9,8,5,22,22,0,5,12,106,5,3,114,0,17,106,0,9,114,0,43,43,43,43,18,57,47,18,57,57,43,48,49,5,32,17,16,0,33,50,22,23,7,38,38,35,34,2,17,16,33,50,55,23,6,1,53,33,21,2,246,253,106,1,78,1,48,147,218,50,148,45,139,81,198,238,1,236,145,141,46,174,253,0,2,168,20,2,220,1,91,1,125,93,86,147,68,74,254,234,255,0,253,210,60,176,68,2,140,190,190,0,0,2,0,17,255,236,4,80,5,160,0,25,0,29,0,35,64,20,26,27,106,3,4,26,26,0,20,14,106,20,3,114,0,8,106,0,9,114,0,43,43,43,43,18,57,47,57,57,43,48,49,5,34,38,39,55,30,2,51,50,18,53,16,2,35,34,6,7,39,54,51,32,0,17,16,0,1,53,33,21,1,220,135,235,89,144,59,99,103,65,194,216,240,236,76,142,71,46,175,194,1,64,1,73,254,198,254,55,2,173,20,86,85,141,49,56,23,1,32,253,1,7,1,32,25,25,176,58,254,138,254,159,254,169,254,122,2,140,190,190,255,255,0,168,0,0,4,8,5,140,2,6,0,70,0,0,255,255,0,168,0,0,4,8,7,56,2,38,0,70,0,0,1,6,6,60,0,0,0,13,183,4,3,12,1,1,1,160,86,0,43,52,52,0,255,255,0,96,255,236,4,48,5,140,2,6,0,83,0,0,0,3,0,20,0,0,4,38,5,140,0,11,0,15,0,19,0,35,64,19,14,17,11,12,5,6,106,5,5,12,17,16,106,17,2,114,12,8,114,0,43,43,43,18,57,47,43,17,51,17,51,48,49,33,17,52,38,35,35,53,51,50,22,21,17,33,17,51,17,1,53,33,21,3,94,100,112,228,228,217,195,252,202,200,254,92,3,52,1,134,152,138,190,227,253,254,122,5,140,250,116,4,206,190,190,0,0,4,0,80,255,236,4,100,5,160,0,11,0,15,0,19,0,31,0,39,64,24,0,20,106,16,17,106,16,16,0,6,26,106,13,2,114,12,8,114,6,3,114,0,9,114,0,43,43,43,43,43,18,57,47,43,43,48,49,5,34,2,17,16,18,51,50,18,17,16,2,37,17,51,17,3,53,33,21,1,50,54,17,16,2,35,34,2,17,16,22,3,7,184,165,165,184,184,165,165,252,145,190,108,1,75,1,16,84,75,75,84,84,75,75,20,1,85,1,123,1,133,1,95,254,161,254,123,254,133,254,171,20,5,140,250,116,2,100,190,190,254,64,254,1,26,1,37,1,7,254,249,254,219,254,230,254,0,0,4,0,72,255,251,4,38,5,140,0,20,0,41,0,45,0,49,0,45,64,25,0,31,18,42,43,105,33,42,42,49,9,21,22,106,21,49,8,114,48,9,12,106,9,2,114,0,43,43,51,43,50,43,17,18,57,47,51,43,50,57,57,48,49,1,34,46,3,53,52,54,51,33,7,33,34,6,21,20,22,51,33,21,1,53,51,50,54,55,55,62,2,51,51,21,34,6,6,7,7,6,6,35,1,53,33,21,3,17,51,17,2,52,39,115,123,108,67,252,220,1,56,24,254,224,119,143,143,119,1,36,252,220,33,39,62,19,36,21,63,81,49,191,83,88,40,12,51,23,115,139,1,124,1,147,36,200,2,116,7,33,78,140,110,203,221,190,125,125,121,139,92,253,135,190,39,71,130,75,77,27,74,27,57,45,204,93,109,2,23,190,190,253,238,5,140,250,116,0,0,3,0,20,0,0,4,88,5,140,0,15,0,19,0,23,0,35,64,20,8,9,106,8,8,16,21,20,106,18,21,2,114,0,1,106,0,16,8,114,0,43,50,43,43,50,43,18,57,47,43,48,49,33,53,50,54,53,52,38,35,33,53,33,50,22,21,20,6,33,17,51,17,1,53,33,21,2,130,136,134,126,126,254,225,1,31,227,225,234,253,160,200,254,62,3,52,190,128,127,125,124,190,218,221,223,222,5,130,250,126,4,206,190,190,0,0,3,255,252,0,0,4,66,5,140,0,3,0,7,0,11,0,31,64,17,0,1,106,0,0,4,5,9,8,106,9,5,2,114,4,8,114,0,43,43,50,43,17,18,57,47,43,48,49,3,53,33,21,1,17,51,17,3,53,33,21,4,2,200,253,240,200,200,3,142,2,73,190,190,253,183,5,140,250,116,4,206,190,190,0,8,0,27,254,222,4,176,5,145,0,19,0,39,0,43,0,47,0,67,0,71,0,91,0,95,0,82,64,46,58,57,106,58,69,80,92,92,44,1,93,93,48,0,81,30,4,67,44,45,105,31,44,44,68,69,10,11,106,10,69,2,114,22,41,41,72,89,105,72,40,96,39,68,8,114,0,43,50,26,206,51,43,50,17,51,43,50,43,17,18,57,47,51,43,50,23,57,50,17,51,17,51,17,51,17,51,43,48,49,1,55,50,54,54,53,17,52,54,51,51,21,35,34,6,21,17,20,6,7,1,53,51,50,54,53,17,52,54,55,55,7,34,6,6,21,17,20,6,35,1,17,51,17,1,53,51,21,39,39,38,38,53,17,52,38,35,35,53,51,50,22,21,17,20,22,22,51,19,17,51,17,5,34,38,53,17,52,38,38,35,39,23,22,22,21,17,20,22,51,51,21,1,53,51,21,2,191,68,29,24,5,89,85,90,23,19,30,85,69,252,184,23,19,30,85,69,164,68,29,24,5,88,86,3,125,190,252,111,188,58,164,69,85,30,19,23,90,86,88,5,24,29,126,170,1,102,85,89,5,24,29,68,164,69,85,30,19,23,254,64,178,2,212,81,15,40,36,1,76,104,93,190,30,34,254,216,64,72,5,253,29,190,30,34,1,40,65,72,4,10,81,15,39,37,254,180,103,94,254,227,1,224,254,32,3,137,190,190,109,10,5,72,64,1,40,34,30,190,93,104,254,180,36,40,15,252,219,5,140,250,116,5,94,103,1,76,37,39,15,81,10,4,72,65,254,221,34,30,195,2,108,190,190,0,5,0,140,254,222,4,136,5,145,0,19,0,23,0,27,0,31,0,51,0,45,64,24,0,41,40,29,28,106,1,29,29,20,10,21,2,114,25,32,49,105,32,24,96,20,8,114,0,43,26,206,51,43,50,43,50,17,57,47,51,43,50,57,57,48,49,1,55,50,54,55,55,62,2,51,51,21,35,34,6,7,7,6,6,35,1,17,51,17,1,17,51,17,1,53,33,21,1,34,38,38,39,39,38,38,35,39,51,50,22,23,23,22,22,51,51,21,2,23,11,98,74,19,38,21,58,102,87,68,48,46,36,14,53,22,93,121,253,230,200,2,118,190,252,159,1,77,1,169,87,102,58,21,38,18,78,105,11,143,128,105,22,53,14,36,46,48,2,212,81,79,90,184,101,116,50,190,48,56,213,88,106,253,44,5,140,250,116,254,222,1,219,254,37,3,137,190,190,253,148,50,117,100,184,89,80,81,106,88,213,56,48,190,0,4,0,140,254,222,4,136,5,140,0,3,0,7,0,11,0,15,0,35,64,19,13,12,106,13,13,8,6,9,2,114,4,1,106,4,0,96,8,8,114,0,43,26,206,51,43,43,50,17,57,47,43,48,49,1,17,51,17,1,17,51,17,33,17,51,17,3,53,33,21,3,202,190,254,212,200,252,104,200,158,3,73,254,222,1,224,254,32,1,34,5,140,250,116,5,140,250,116,2,100,190,190,0,255,255,0,25,0,0,4,151,5,140,2,6,0,175,0,0,0,3,0,25,0,0,4,151,5,140,0,3,0,11,0,15,0,31,64,17,0,1,106,7,13,4,3,0,0,5,12,8,114,10,5,2,114,0,43,50,43,18,57,47,23,57,43,48,49,1,53,33,21,37,1,51,1,51,1,51,1,3,17,51,17,1,1,2,177,254,81,254,22,220,1,90,18,1,90,220,254,22,185,200,1,39,190,190,179,3,178,253,58,2,198,252,78,254,38,2,188,253,68,0,0,3,0,66,254,222,4,136,5,140,0,3,0,9,0,15,0,38,64,21,11,8,14,5,4,10,13,4,1,106,0,4,96,4,10,8,114,13,6,2,114,0,43,50,43,50,26,16,206,43,17,18,23,57,48,49,1,17,51,17,3,1,1,51,1,1,33,1,1,51,1,1,3,202,190,254,254,148,254,36,230,1,122,1,206,251,210,1,206,1,122,230,254,36,254,148,254,222,1,224,254,32,1,34,2,124,3,16,253,94,253,22,2,234,2,162,252,240,253,132,0,3,0,140,254,222,4,136,5,140,0,3,0,15,0,19,0,35,64,19,4,13,106,4,4,8,0,16,96,16,1,106,16,8,114,18,8,2,114,0,43,50,43,43,26,16,206,18,57,47,43,48,49,1,17,51,17,1,34,38,53,17,51,17,20,22,51,33,21,3,17,51,17,3,202,190,253,188,232,208,200,114,126,1,42,18,200,254,222,1,224,254,32,3,67,227,253,1,139,254,117,152,138,190,253,223,5,140,250,116,0,2,0,140,0,0,4,36,5,140,0,11,0,15,0,27,64,14,11,12,5,6,106,5,5,12,13,2,114,12,8,114,0,43,43,17,57,47,43,17,51,48,49,33,17,52,38,35,33,53,33,50,22,21,17,33,17,51,17,3,92,114,126,254,214,1,42,232,208,252,104,200,1,139,152,138,190,227,253,254,117,5,140,250,116,0,255,255,0,168,0,0,4,8,5,140,2,6,0,70,0,0,255,255,0,76,255,236,4,100,5,160,2,6,0,142,0,0,255,255,0,148,0,0,4,28,6,232,2,38,1,155,0,0,1,6,6,70,0,0,0,11,182,3,16,9,1,1,160,86,0,43,52,0,0,3,0,76,255,236,4,100,5,160,0,3,0,11,0,19,0,31,64,18,4,12,106,0,1,106,0,0,4,8,16,106,8,3,114,4,9,114,0,43,43,43,18,57,47,43,43,48,49,19,53,33,21,1,32,17,16,33,32,17,16,37,32,17,16,33,32,17,16,182,3,73,254,89,253,244,2,12,2,12,253,244,1,58,254,198,254,198,2,100,190,190,253,136,2,208,2,228,253,28,253,48,184,2,24,2,44,253,212,253,232,0,255,255,0,96,0,0,4,152,6,232,2,38,1,168,0,0,1,6,6,70,50,0,0,11,182,2,17,13,1,1,160,86,0,43,52,0,0,4,0,30,254,222,4,146,5,140,0,7,0,11,0,15,0,19,0,33,64,17,6,0,1,2,114,9,17,0,13,105,16,11,96,4,0,8,114,0,43,50,26,205,50,43,57,57,43,18,57,48,49,51,1,33,1,35,1,35,1,1,17,51,17,3,53,33,21,3,17,51,17,102,1,94,1,34,1,94,210,254,236,18,254,236,254,230,200,200,4,116,200,200,5,140,250,116,4,224,251,32,254,222,1,164,254,92,1,34,190,190,254,222,1,164,254,92,0,1,0,45,0,0,4,131,5,140,0,7,0,19,64,9,6,4,1,2,114,4,0,8,114,0,43,50,43,17,57,48,49,51,1,33,1,35,1,35,1,45,1,154,1,34,1,154,220,254,186,18,254,186,5,140,250,116,4,224,251,32,0,3,0,66,255,106,4,110,6,34,0,11,0,23,0,35,0,41,64,25,15,20,19,16,4,6,30,105,17,6,3,114,14,21,13,22,4,0,24,105,12,96,0,9,114,0,43,26,205,43,23,57,43,205,43,23,57,48,49,5,32,2,17,16,18,33,32,18,17,16,2,5,53,55,17,39,53,51,21,7,17,23,21,3,50,18,17,16,2,35,34,2,17,16,18,2,88,254,231,253,253,1,25,1,25,253,253,254,135,10,10,190,10,10,94,170,154,154,170,170,154,154,20,1,85,1,123,1,133,1,95,254,161,254,123,254,133,254,171,130,184,70,4,211,65,166,166,65,251,45,70,184,1,38,1,8,1,36,1,47,1,17,254,239,254,209,254,220,254,248,255,255,0,96,255,236,4,134,4,46,2,6,0,195,0,0,0,2,0,122,255,236,4,60,5,145,0,25,0,36,0,33,64,19,20,32,106,16,20,20,0,9,10,106,9,3,114,0,26,106,0,11,114,0,43,43,43,43,18,57,47,57,43,48,49,5,34,0,17,53,52,18,54,55,37,23,5,14,2,21,21,51,54,54,51,50,22,21,20,2,39,50,54,53,52,38,35,34,6,21,16,2,106,239,254,255,113,240,188,1,113,10,254,188,145,167,71,23,31,184,133,180,198,244,220,119,131,133,121,132,144,20,1,61,1,33,118,200,1,13,157,32,63,190,55,24,87,147,116,98,111,121,246,224,233,254,255,184,160,146,137,149,138,128,254,186,0,4,0,168,0,0,4,60,4,36,0,17,0,21,0,25,0,43,0,44,64,26,36,35,106,36,19,22,10,26,23,4,9,27,105,9,9,18,19,6,114,0,1,106,0,18,10,114,0,43,50,43,43,17,57,47,43,23,57,17,51,43,48,49,33,53,33,50,54,53,52,38,35,33,53,33,50,22,21,20,6,35,33,17,51,17,3,53,33,21,37,53,33,50,54,53,52,38,35,33,53,33,50,22,21,20,6,35,1,110,1,84,74,82,89,81,254,166,1,140,163,179,168,152,253,172,212,82,1,200,254,104,1,64,74,82,89,81,254,226,1,80,163,179,168,152,190,73,67,67,73,71,136,125,133,147,4,36,251,220,1,242,98,98,61,71,63,57,57,63,190,146,134,106,115,0,0,2,1,60,0,0,4,46,4,36,0,3,0,7,0,19,64,10,5,4,106,5,1,6,114,0,10,114,0,43,43,50,43,48,49,33,17,51,17,3,53,33,21,1,60,212,150,2,180,4,36,251,220,3,102,190,190,0,255,255,1,60,0,0,4,46,6,92,2,38,1,212,0,0,1,6,6,30,120,0,0,11,182,2,8,1,1,1,188,86,0,43,52,0,0,3,1,60,0,0,4,66,5,40,0,3,0,7,0,11,0,25,64,13,8,5,4,106,5,9,96,1,6,114,0,10,114,0,43,43,26,206,51,43,50,48,49,33,17,51,17,3,53,33,21,35,17,51,17,1,60,212,150,2,180,180,200,4,36,251,220,3,102,190,190,1,194,254,62,0,0,6,0,40,254,242,4,106,4,36,0,9,0,13,0,17,0,21,0,25,0,29,0,40,64,23,11,15,0,1,4,28,29,106,14,10,96,18,28,10,114,23,22,106,23,20,5,6,114,0,43,50,50,43,43,50,26,206,50,43,23,57,48,49,37,39,54,54,53,17,51,17,20,2,1,17,51,17,33,17,51,17,1,17,51,17,1,53,33,21,19,21,33,53,1,62,190,59,52,185,48,254,176,200,2,178,200,254,174,212,253,105,2,68,209,251,190,145,25,86,249,169,1,130,254,133,173,254,246,254,0,1,144,254,112,1,144,254,112,1,14,4,36,251,220,3,102,190,190,253,88,190,190,0,255,255,0,136,255,236,4,40,4,56,2,6,0,232,0,0,255,255,0,136,255,236,4,40,6,92,2,38,1,216,0,0,1,6,6,29,65,0,0,11,182,1,30,6,1,1,168,86,0,43,52,0,255,255,0,136,255,236,4,40,5,226,2,38,1,216,0,0,1,6,6,27,22,0,0,13,183,2,1,30,6,1,1,158,86,0,43,52,52,0,0,7,0,37,255,246,4,139,4,46,0,18,0,37,0,41,0,60,0,64,0,83,0,87,0,78,64,45,52,51,106,52,62,72,84,84,41,1,85,85,29,73,0,42,4,60,41,40,106,30,41,41,62,61,9,10,106,9,62,6,114,83,82,106,83,61,19,20,106,19,61,10,114,0,43,50,43,17,51,43,43,50,43,17,18,57,47,51,43,50,23,57,50,17,51,17,51,17,51,17,51,43,48,49,1,53,50,54,53,53,52,54,51,51,21,35,34,6,21,21,20,6,7,1,53,51,50,54,53,53,52,54,55,55,21,34,6,21,21,20,6,35,19,53,51,21,39,39,38,38,53,53,52,38,35,35,53,51,50,22,21,21,20,22,51,19,17,51,17,5,34,38,53,53,52,38,35,53,23,22,22,21,21,20,22,51,51,21,1,53,51,21,3,38,54,17,110,103,73,43,22,37,84,61,252,145,43,23,36,84,61,110,54,17,109,104,212,203,131,110,61,84,36,23,43,73,104,109,17,54,115,180,1,145,103,110,17,54,110,61,84,37,22,43,254,18,209,2,24,81,36,55,170,101,91,190,27,32,134,64,72,5,253,212,190,28,31,134,65,71,5,10,81,36,55,170,101,91,1,197,174,174,93,10,5,72,64,134,32,27,190,91,101,170,55,36,253,151,4,36,251,220,10,91,101,170,55,36,81,10,5,71,65,134,31,28,190,1,197,174,174,0,0,1,0,115,255,236,4,12,4,56,0,44,0,39,64,22,37,38,14,15,106,3,4,14,14,0,30,23,106,30,7,114,0,7,106,0,11,114,0,43,43,43,43,18,57,47,57,57,43,57,57,48,49,5,34,38,39,55,22,22,51,50,54,53,52,38,35,35,39,51,50,54,54,53,52,38,35,34,6,7,39,54,54,51,50,4,21,20,6,6,7,21,30,2,21,20,4,2,44,122,235,84,102,72,185,74,125,143,161,201,42,11,56,138,136,44,163,124,69,108,86,25,74,131,105,223,1,6,60,118,87,103,135,68,254,252,20,52,78,148,52,42,77,64,83,81,164,32,63,44,62,62,13,9,180,10,16,131,142,54,100,71,12,20,15,68,105,72,140,170,0,3,0,168,0,0,4,8,4,36,0,7,0,11,0,15,0,27,64,13,6,1,8,13,4,9,6,114,15,7,8,10,114,0,43,50,50,43,50,50,18,57,57,48,49,33,17,51,1,51,17,35,1,35,17,51,17,33,17,51,17,1,52,92,1,159,70,85,254,97,217,212,1,184,212,1,34,3,2,254,222,252,254,4,36,251,220,4,36,251,220,0,255,255,0,168,0,0,4,8,6,67,2,38,1,221,0,0,1,6,6,79,0,0,0,11,182,3,16,3,1,1,178,86,0,43,52,0,255,255,0,168,0,0,4,8,6,92,2,38,1,221,0,0,1,6,6,29,45,0,0,11,182,3,16,3,1,1,188,86,0,43,52,0,0,4,0,168,255,251,4,49,4,41,0,19,0,23,0,27,0,47,0,45,64,25,37,0,1,24,25,106,36,24,24,20,21,10,11,106,10,21,6,114,28,45,106,28,20,10,114,0,43,50,43,43,50,43,17,18,57,47,51,43,50,57,57,48,49,1,53,50,54,55,55,62,2,51,51,21,35,34,6,7,7,6,6,35,1,17,51,17,3,53,33,21,1,34,38,38,39,39,38,38,35,53,51,50,22,23,23,22,22,51,51,21,2,34,64,51,17,69,31,66,98,78,43,43,37,38,14,70,25,95,81,254,20,212,15,1,53,1,100,78,103,71,31,69,17,51,64,124,81,105,25,70,14,38,37,33,2,32,81,39,43,171,77,81,29,190,20,34,164,57,56,253,224,4,36,251,220,1,179,190,190,254,72,29,81,77,171,43,39,81,56,57,164,34,20,190,255,255,0,168,255,251,4,49,6,92,2,38,1,224,0,0,1,6,6,30,20,0,0,11,182,4,48,21,1,1,188,86,0,43,52,0,0,3,0,63,0,0,4,14,4,36,0,11,0,15,0,19,0,27,64,15,17,16,106,17,13,6,6,114,12,0,1,106,0,10,114,0,43,43,51,43,50,50,43,48,49,51,53,50,54,54,53,17,51,17,20,6,6,33,17,51,17,1,53,33,21,63,80,91,38,185,71,172,2,100,212,253,54,2,165,190,55,132,117,2,54,253,209,193,218,90,4,36,251,220,3,102,190,190,0,4,0,128,0,0,4,48,4,36,0,7,0,11,0,19,0,23,0,41,64,21,6,14,2,17,19,0,0,17,14,3,8,21,15,3,9,6,114,20,8,10,114,0,43,50,43,50,50,50,18,23,57,17,51,17,51,17,51,48,49,37,55,51,19,51,21,35,3,5,17,51,17,55,3,35,53,51,19,51,23,23,17,51,17,2,54,30,12,172,122,58,162,253,214,202,188,162,58,122,172,8,20,250,202,220,230,2,98,252,253,180,220,4,36,251,220,220,2,76,252,253,158,230,220,4,36,251,220,0,0,3,0,168,0,0,4,8,4,36,0,3,0,7,0,11,0,31,64,16,0,4,1,5,8,9,106,8,8,4,5,6,114,4,10,114,0,43,43,17,57,47,43,17,51,17,51,48,49,33,17,51,17,33,17,51,17,3,53,33,21,3,52,212,252,160,212,150,3,3,4,36,251,220,4,36,251,220,1,187,174,174,255,255,0,136,255,236,4,40,4,56,2,6,1,43,0,0,0,3,0,168,0,0,4,8,4,36,0,3,0,7,0,11,0,27,64,14,0,4,1,5,9,8,106,9,5,6,114,4,10,114,0,43,43,50,43,17,51,17,51,48,49,33,17,51,17,33,17,51,17,3,53,33,21,3,52,212,252,160,212,150,3,3,4,36,251,220,4,36,251,220,3,102,190,190,255,255,0,168,254,52,4,80,4,56,2,6,1,70,0,0,255,255,0,136,255,236,4,73,4,56,2,6,0,222,0,0,0,2,0,90,0,0,4,86,4,36,0,3,0,7,0,19,64,10,2,5,4,106,5,6,114,0,10,114,0,43,43,43,51,48,49,33,17,51,17,1,53,33,21,1,238,212,253,152,3,252,4,36,251,220,3,102,190,190,255,255,0,55,254,32,4,91,4,36,2,6,1,118,0,0,255,255,0,55,254,32,4,91,6,67,2,38,1,234,0,0,1,6,6,79,251,0,0,11,182,2,20,7,1,1,178,86,0,43,52,0,0,3,0,45,254,72,4,131,5,220,0,27,0,55,0,67,0,50,64,32,61,0,114,56,14,114,15,34,41,106,3,53,5,51,17,39,19,37,8,28,22,34,7,114,9,28,47,106,0,28,11,114,0,43,50,43,50,43,50,18,23,57,43,50,43,43,48,49,5,34,38,39,35,19,21,20,22,51,50,54,53,52,38,35,34,17,3,51,54,54,51,50,18,17,16,2,33,34,2,17,16,18,51,50,22,23,51,3,16,35,34,6,21,20,22,51,50,54,53,53,19,35,6,6,19,17,55,17,39,17,51,17,7,17,23,17,3,140,79,101,7,92,57,63,65,69,62,61,68,130,47,82,9,92,84,131,118,117,253,22,130,117,118,131,84,92,9,82,47,130,67,62,62,69,65,63,57,92,7,100,127,15,15,202,15,15,20,88,86,1,46,116,90,90,170,190,200,180,254,208,1,26,101,101,254,247,254,217,254,228,255,0,1,0,1,28,1,39,1,9,101,101,254,230,1,48,180,200,190,170,90,90,116,254,210,86,88,254,92,2,125,57,2,41,33,2,148,253,108,33,253,215,57,253,131,0,255,255,0,106,0,0,4,70,4,36,2,6,1,117,0,0,0,2,0,128,0,0,4,8,4,36,0,11,0,15,0,27,64,14,14,4,0,9,106,0,0,15,4,6,114,15,10,114,0,43,43,17,57,47,43,17,51,48,49,1,34,38,53,53,51,21,20,22,51,33,21,3,17,51,17,2,48,217,215,212,110,110,1,62,58,212,1,124,215,215,250,250,128,128,174,254,132,4,36,251,220,0,0,4,0,140,254,242,4,106,4,36,0,3,0,7,0,11,0,15,0,29,64,15,1,9,6,114,13,4,5,106,4,12,96,0,8,10,114,0,43,50,26,206,51,43,50,43,50,48,49,33,17,51,17,33,53,33,21,33,17,51,17,1,17,51,17,3,14,212,252,232,3,107,252,87,212,2,66,200,4,36,251,220,190,190,4,36,251,220,254,242,1,204,254,52,0,4,0,112,0,0,4,64,4,36,0,3,0,7,0,11,0,15,0,37,64,19,12,8,13,9,0,8,1,9,4,5,106,4,8,9,6,114,8,10,114,0,43,43,17,51,43,17,51,17,51,17,51,17,51,48,49,33,17,51,17,33,53,33,21,33,17,51,17,51,17,51,17,3,108,212,252,90,3,129,252,85,212,185,180,4,36,251,220,180,180,4,36,251,220,4,36,251,220,0,0,5,0,112,254,242,4,134,4,36,0,3,0,7,0,11,0,15,0,19,0,35,64,18,17,1,9,6,114,0,16,16,13,4,5,106,4,12,96,8,10,114,0,43,26,206,51,43,50,51,17,51,43,50,50,48,49,33,17,51,17,33,53,33,21,33,17,51,17,1,17,51,17,1,17,51,17,3,88,212,252,110,3,129,252,85,212,2,122,200,253,114,170,4,36,251,220,180,180,4,36,251,220,254,242,1,194,254,62,1,14,4,36,251,220,0,0,4,0,173,254,242,4,3,4,36,0,3,0,7,0,11,0,15,0,33,64,17,1,13,6,114,5,0,0,15,15,8,9,106,4,96,8,10,114,0,43,26,206,43,51,17,51,17,57,43,50,48,49,33,17,51,17,1,17,51,17,1,53,33,21,33,17,51,17,3,47,212,253,247,200,253,235,3,86,252,170,212,4,36,251,220,254,242,1,144,254,112,1,14,174,174,4,36,251,220,0,2,0,188,0,0,4,80,4,36,0,17,0,21,0,31,64,17,0,1,106,0,18,9,10,106,9,9,18,19,6,114,18,10,114,0,43,43,17,57,47,43,17,51,43,48,49,33,53,33,50,54,53,52,38,35,33,53,33,50,22,21,20,6,35,33,17,51,17,1,130,1,74,80,88,88,80,254,162,1,122,172,188,188,172,253,212,212,190,88,80,80,88,190,187,171,171,187,4,36,251,220,0,3,0,0,0,0,4,80,4,36,0,17,0,21,0,25,0,39,64,22,20,23,0,1,106,0,18,9,10,106,9,9,18,23,22,106,23,6,114,18,10,114,0,43,43,43,18,57,47,43,17,51,43,17,51,48,49,33,53,51,50,54,53,52,38,35,33,53,33,50,22,21,20,6,35,33,17,51,17,1,53,33,21,1,190,250,90,98,98,90,254,242,1,42,182,198,198,182,254,36,212,254,52,1,97,190,88,80,80,88,190,187,171,171,187,4,36,251,220,3,102,190,190,0,0,3,0,112,0,0,4,64,4,36,0,17,0,21,0,25,0,39,64,21,22,18,23,19,0,1,106,0,18,10,9,106,10,10,18,19,6,114,18,10,114,0,43,43,17,57,47,43,17,51,43,17,51,17,51,48,49,33,53,51,50,54,53,52,38,35,35,53,51,50,22,21,20,6,35,33,17,51,17,33,17,51,17,1,54,79,80,88,88,80,99,127,158,172,172,158,254,207,212,2,40,212,170,98,90,90,98,170,187,171,171,187,4,36,251,220,4,36,251,220,0,4,0,63,0,0,4,147,4,36,0,10,0,14,0,32,0,36,0,45,64,26,34,33,106,34,5,24,25,106,24,24,0,12,5,6,114,15,16,106,15,11,0,1,106,0,10,114,0,43,43,51,51,43,43,50,17,57,47,43,17,51,43,48,49,51,53,50,54,53,17,51,17,20,6,6,33,17,51,17,35,53,51,50,54,53,52,38,35,35,53,51,50,22,21,20,6,35,1,53,33,21,63,79,58,185,58,140,1,128,192,14,74,71,77,77,71,94,112,158,172,172,158,253,169,1,228,190,65,89,2,204,253,59,135,153,63,4,36,251,220,190,88,80,80,88,190,187,171,171,187,3,118,174,174,0,0,4,0,88,0,0,4,147,4,36,0,17,0,21,0,25,0,31,0,43,64,23,26,18,27,19,0,1,106,0,18,10,9,22,23,106,22,22,18,19,6,114,18,10,114,0,43,43,17,57,47,43,51,50,17,51,43,17,51,17,51,48,49,33,53,51,50,54,53,52,38,35,35,53,51,50,22,21,20,6,35,33,17,51,17,3,53,33,21,3,17,51,17,21,17,2,207,104,71,77,77,71,124,142,158,172,172,158,253,15,212,150,1,195,60,192,190,88,80,74,80,174,171,157,171,187,4,36,251,220,2,0,174,174,254,0,4,36,254,69,50,253,201,0,255,255,0,156,255,236,4,20,4,56,2,6,1,77,0,0,0,2,0,136,255,236,4,73,4,56,0,25,0,29,0,39,64,22,26,27,106,10,9,6,26,26,0,6,13,106,6,7,114,23,0,19,106,0,11,114,0,43,43,51,43,43,18,57,47,18,57,57,43,48,49,5,32,0,17,16,0,33,50,22,23,7,38,38,35,34,6,21,20,22,51,50,54,55,23,6,6,1,53,33,21,2,170,254,251,254,227,1,23,1,3,155,221,47,163,45,140,83,151,169,188,172,80,157,75,24,87,184,253,212,2,57,20,1,29,1,11,1,4,1,32,115,105,123,73,80,181,167,181,191,14,12,186,18,12,1,210,174,174,0,0,2,0,132,255,236,4,40,4,56,0,25,0,29,0,37,64,21,26,27,106,3,4,26,26,0,17,20,13,106,20,7,114,0,7,106,0,11,114,0,43,43,43,43,51,18,57,47,57,57,43,48,49,5,34,38,39,55,22,22,51,50,54,53,52,38,35,34,6,7,55,54,54,51,32,0,17,16,0,1,53,33,21,2,14,129,206,59,104,50,156,92,152,168,208,192,61,125,66,18,55,129,74,1,25,1,49,254,233,254,143,2,22,20,71,52,160,37,56,182,166,182,190,10,11,194,8,9,254,227,254,245,254,253,254,223,1,210,174,174,255,255,0,160,0,0,4,78,5,244,2,6,1,9,0,0,255,255,0,160,0,0,4,78,5,226,2,38,1,10,0,0,1,6,6,27,52,0,0,13,183,5,4,16,1,1,1,178,86,0,43,52,52,0,255,255,0,170,254,32,3,140,5,244,2,6,1,22,0,0,0,3,0,0,0,0,4,8,5,220,0,14,0,18,0,22,0,39,64,21,10,4,106,20,19,106,6,8,15,10,20,10,20,15,16,0,114,14,15,10,114,0,43,50,43,17,57,57,47,47,18,57,57,43,43,48,49,33,17,52,38,35,34,17,3,51,54,51,50,22,21,17,33,17,51,17,1,53,33,21,3,52,90,80,230,62,82,16,244,158,174,252,200,212,254,92,3,2,2,58,101,109,254,208,1,16,212,204,186,253,198,5,220,250,36,4,122,174,174,0,0,4,0,110,255,236,4,100,4,56,0,11,0,15,0,19,0,31,0,39,64,24,0,20,106,16,17,106,16,16,0,6,26,106,13,6,114,12,10,114,6,7,114,0,11,114,0,43,43,43,43,43,18,57,47,43,43,48,49,5,34,2,17,16,18,51,50,18,17,16,2,37,17,51,17,3,53,33,21,19,50,54,53,52,38,35,34,6,21,20,22,3,7,173,156,156,173,184,165,165,252,175,197,125,1,75,252,78,71,71,78,78,71,71,20,1,0,1,28,1,39,1,9,254,247,254,217,254,228,255,0,20,4,36,251,220,1,184,174,174,254,236,169,187,198,178,178,198,187,169,0,4,0,126,255,251,4,3,4,36,0,17,0,38,0,42,0,46,0,45,64,25,0,27,15,39,40,105,29,39,39,46,6,18,19,106,18,46,10,114,45,6,9,106,6,6,114,0,43,43,51,43,50,43,17,18,57,47,51,43,50,57,57,48,49,1,34,38,53,52,54,51,33,21,33,34,6,21,20,22,51,33,7,1,53,51,50,54,55,55,54,54,51,51,7,34,6,6,7,7,14,2,35,1,53,33,21,3,17,51,17,1,221,154,168,210,192,1,36,254,220,87,95,95,87,1,16,10,253,75,33,41,45,23,50,32,87,73,190,8,65,68,34,15,43,36,73,104,85,1,85,1,97,48,212,1,194,152,139,152,167,190,86,79,74,81,100,254,57,190,35,34,74,47,46,61,18,36,28,81,69,89,44,1,109,190,190,254,152,4,36,251,220,0,0,4,0,0,254,32,4,8,5,220,0,14,0,18,0,22,0,35,0,44,64,27,23,24,106,23,15,114,10,4,106,20,19,106,10,7,29,0,4,15,20,20,15,16,0,114,15,10,114,0,43,43,17,57,47,18,23,57,43,43,43,43,48,49,37,17,52,38,35,34,17,3,51,54,51,50,22,21,17,5,17,51,17,1,53,33,21,1,39,55,54,54,53,17,51,17,20,6,6,7,3,52,90,80,230,62,82,16,244,158,174,252,200,212,254,92,3,2,255,0,10,140,92,84,212,85,180,143,140,1,174,101,109,254,208,1,16,212,204,186,254,82,140,5,220,250,36,4,122,174,174,249,166,188,18,8,128,130,1,136,254,152,165,211,106,10,0,3,0,106,0,0,4,46,4,36,0,3,0,7,0,11,0,31,64,17,0,1,106,0,0,4,5,9,8,106,9,5,6,114,4,10,114,0,43,43,50,43,17,18,57,47,43,48,49,19,53,33,21,1,17,51,17,3,53,33,21,106,2,170,254,40,212,150,2,180,1,167,174,174,254,89,4,36,251,220,3,102,190,190,0,8,0,47,254,242,4,142,4,41,0,19,0,39,0,43,0,63,0,67,0,87,0,91,0,95,0,78,64,45,54,53,106,54,65,77,30,44,0,4,90,63,1,40,41,105,91,76,31,40,40,65,64,10,11,106,10,65,6,114,94,87,86,106,87,64,20,21,106,20,92,96,64,10,114,0,43,26,206,51,43,17,51,43,50,43,50,43,17,18,57,47,51,51,51,43,50,50,50,23,57,17,51,43,48,49,1,39,50,54,54,53,53,52,54,51,51,21,35,34,6,21,21,20,6,7,1,53,51,50,54,53,53,52,54,55,55,23,34,6,6,21,21,20,6,35,19,53,51,21,39,39,38,38,53,53,52,38,35,35,53,51,50,22,21,21,20,22,22,51,3,17,51,17,5,34,38,53,53,52,38,38,35,55,23,22,22,21,21,20,22,51,51,21,1,53,51,21,19,17,51,17,2,156,32,71,58,11,116,108,73,63,19,30,96,69,253,19,63,19,30,96,69,138,22,70,59,11,116,108,242,128,28,138,69,96,30,19,63,73,108,116,11,59,70,4,160,1,104,108,116,11,58,71,32,128,69,96,30,19,63,254,69,128,208,200,2,24,81,15,40,36,160,104,93,190,30,34,124,64,72,5,253,217,190,30,34,124,65,71,5,10,81,15,39,37,160,103,94,1,192,174,174,93,10,5,72,64,124,34,30,190,93,104,160,36,40,15,253,151,4,36,251,220,5,94,103,160,37,39,15,81,10,5,71,65,119,34,30,195,1,192,174,174,253,55,1,204,254,52,0,5,0,168,254,242,4,142,4,41,0,19,0,23,0,27,0,31,0,51,0,51,64,29,0,41,1,24,25,106,40,24,24,21,20,10,11,106,10,21,6,114,30,51,50,106,51,20,28,105,20,10,114,0,43,43,51,43,50,43,50,43,17,18,57,47,51,43,50,57,57,48,49,1,55,50,54,55,55,62,2,51,51,21,35,34,6,7,7,6,6,35,1,17,51,17,3,53,33,21,1,17,51,17,3,34,38,38,39,39,38,38,35,39,51,50,22,23,23,22,22,51,51,21,2,26,8,64,51,17,69,31,66,98,78,43,43,37,38,14,70,25,95,81,254,20,212,15,1,53,1,36,200,136,78,103,71,31,69,17,51,64,8,132,81,105,25,70,14,38,37,33,2,32,81,39,43,171,77,81,29,190,20,34,164,57,56,253,224,4,36,251,220,1,179,190,190,253,63,1,199,254,57,1,9,29,81,77,171,43,39,81,56,57,164,34,20,190,0,4,0,168,254,242,4,142,4,36,0,3,0,7,0,11,0,15,0,35,64,19,13,12,106,13,13,8,6,9,6,114,4,1,106,4,0,96,8,10,114,0,43,26,206,51,43,43,50,17,57,47,43,48,49,1,17,51,17,1,17,51,17,33,17,51,17,3,53,33,21,3,198,200,254,166,212,252,160,212,150,3,3,254,242,1,204,254,52,1,14,4,36,251,220,4,36,251,220,1,187,174,174,0,0,2,0,80,254,52,4,96,4,36,0,7,0,11,0,25,64,13,8,14,114,4,9,0,6,1,6,114,0,10,114,0,43,43,50,18,57,57,43,48,49,33,1,51,1,35,1,51,1,3,17,51,17,1,243,254,93,226,1,69,62,1,69,226,254,93,207,212,4,36,252,124,3,132,251,220,254,52,2,44,253,212,0,3,0,80,254,52,4,96,4,36,0,3,0,11,0,15,0,31,64,17,12,14,114,8,13,4,10,5,6,114,1,0,106,1,4,10,114,0,43,50,43,43,50,18,57,57,43,48,49,23,53,33,21,37,1,51,1,35,1,51,1,3,17,51,17,215,3,3,254,25,254,93,226,1,69,62,1,69,226,254,93,207,212,174,174,174,174,4,36,252,124,3,132,251,220,254,52,2,44,253,212,0,0,3,0,106,254,242,4,132,4,36,0,3,0,9,0,15,0,38,64,21,8,11,5,14,4,7,4,7,12,6,114,10,1,106,0,10,96,10,4,10,114,0,43,50,26,16,206,43,43,50,17,18,23,57,48,49,1,17,51,17,9,2,51,1,1,33,1,1,51,1,1,3,188,200,251,230,1,166,1,70,240,254,74,254,202,1,252,254,190,254,86,240,1,70,1,166,254,242,1,204,254,52,1,14,2,72,1,220,253,166,254,54,1,202,2,90,254,36,253,184,0,3,0,128,254,242,4,142,4,36,0,3,0,15,0,19,0,35,64,19,4,13,106,4,4,8,0,16,96,16,1,106,16,10,114,18,8,6,114,0,43,50,43,43,26,16,206,18,57,47,43,48,49,1,17,51,17,1,34,38,53,53,51,21,20,22,51,33,21,3,17,51,17,3,198,200,253,162,217,215,212,110,110,1,62,58,212,254,242,1,204,254,52,2,138,215,215,250,250,128,128,174,254,132,4,36,251,220,255,255,0,168,0,0,4,8,5,220,2,6,1,5,0,0,255,255,0,160,0,0,4,78,4,36,2,6,1,10,0,0,255,255,0,136,255,236,4,40,4,56,2,6,0,252,0,0,255,255,0,168,0,0,4,8,5,156,2,38,1,221,0,0,1,6,6,37,0,0,0,11,182,3,16,9,1,1,188,86,0,43,52,0,0,3,0,136,255,236,4,40,4,56,0,3,0,15,0,27,0,31,64,18,4,16,106,0,1,106,0,0,4,10,22,106,10,7,114,4,11,114,0,43,43,43,18,57,47,43,43,48,49,19,53,33,21,1,34,2,17,16,18,51,50,18,17,16,2,39,50,54,53,52,38,35,34,6,21,20,22,230,3,3,254,111,220,244,244,220,221,243,243,221,117,127,127,117,117,127,127,1,193,162,162,254,43,1,32,1,6,1,7,1,31,254,225,254,249,254,250,254,224,190,188,172,173,187,187,173,172,188,255,255,0,55,254,32,4,91,5,156,2,38,1,234,0,0,1,6,6,37,15,0,0,11,182,2,20,15,1,1,188,86,0,43,52,0,0,2,0,160,255,236,4,50,5,160,0,18,0,38,0,35,64,20,12,13,26,27,106,26,26,0,6,34,106,6,3,114,0,19,106,0,11,114,0,43,43,43,43,18,57,47,43,57,57,48,49,5,34,38,17,17,16,33,50,22,21,20,6,7,21,22,22,21,20,6,39,50,54,53,52,38,35,35,53,51,50,54,53,52,38,35,34,17,17,16,2,102,239,215,1,196,201,221,146,134,153,167,241,217,113,125,126,116,104,98,99,109,106,96,240,20,232,1,2,1,217,1,241,189,171,126,154,20,14,4,190,172,200,220,190,131,119,122,133,190,108,97,86,94,254,202,254,42,254,212,0,1,0,156,255,236,4,20,4,56,0,43,0,34,64,22,3,34,31,30,8,9,12,25,8,0,22,15,106,22,7,114,0,37,106,0,11,114,0,43,43,43,43,18,23,57,48,49,5,34,38,53,52,62,2,55,55,54,54,53,52,38,35,34,6,7,55,54,54,51,32,4,21,20,14,2,7,5,6,6,21,20,22,51,50,54,55,23,6,6,2,140,253,243,70,105,108,39,216,53,61,147,178,70,120,77,14,57,115,70,1,29,1,15,57,89,98,40,254,248,55,49,139,148,92,160,105,24,83,205,20,157,144,85,112,68,36,9,51,13,44,52,68,71,1,5,188,5,3,159,155,79,100,58,31,11,68,14,64,39,73,59,25,27,183,31,28,0,255,255,0,96,254,34,4,8,4,56,2,6,0,255,0,0,0,7,0,37,255,246,4,139,5,220,0,19,0,39,0,43,0,63,0,69,0,89,0,93,0,78,64,46,66,0,114,89,88,106,89,64,78,93,93,40,1,92,92,79,30,44,0,4,63,40,41,105,31,40,40,54,64,20,21,106,20,64,8,114,10,11,106,10,54,53,106,54,6,114,0,43,43,51,43,43,50,43,17,18,57,47,51,43,50,23,57,50,17,51,17,51,17,51,17,51,43,43,48,49,1,39,50,54,54,53,53,52,54,51,51,21,35,34,6,21,21,20,6,7,1,53,51,50,54,53,53,52,54,55,55,23,34,6,6,21,21,20,6,35,19,53,51,21,39,39,38,38,53,53,52,38,35,35,53,51,50,22,21,21,20,22,22,51,19,17,3,51,3,17,5,34,38,53,53,52,38,38,35,55,23,22,22,21,21,20,22,51,51,21,1,53,51,21,3,10,32,66,54,11,110,103,73,43,22,37,84,61,252,145,43,23,36,84,61,138,32,66,54,11,109,104,212,188,88,138,61,84,36,23,43,73,104,109,11,54,66,56,5,190,5,1,144,103,110,11,54,66,32,138,61,84,37,22,43,254,39,188,2,24,81,15,40,36,170,101,91,190,27,32,134,64,72,5,253,212,190,28,31,134,65,72,4,10,81,15,39,37,170,101,91,1,197,174,174,93,10,5,72,64,134,32,27,190,91,101,170,36,40,15,253,151,2,63,3,157,252,99,253,193,10,91,101,170,37,39,15,81,10,4,72,65,134,31,28,190,1,197,174,174,0,1,0,79,254,52,4,37,4,56,0,47,0,41,64,23,37,40,14,15,106,3,2,0,14,14,30,0,6,106,30,0,105,30,22,106,30,7,114,0,43,43,43,43,18,57,47,18,57,57,43,57,57,48,49,1,32,39,55,22,22,51,50,54,53,52,38,38,35,35,39,54,54,53,52,38,38,35,34,6,7,39,62,2,51,32,22,21,20,6,7,7,55,21,39,30,2,21,20,6,6,2,29,254,223,173,140,80,148,105,138,153,95,156,91,111,24,221,193,61,131,106,56,161,52,25,22,100,121,55,1,10,242,166,133,53,24,14,108,186,115,122,232,254,52,179,148,72,65,141,120,92,121,60,191,8,108,108,58,96,57,16,11,189,7,13,8,201,163,145,151,30,12,55,123,57,2,88,172,128,128,197,112,0,255,255,0,156,255,236,4,134,4,36,2,6,1,91,0,0,255,255,0,156,255,236,4,134,6,67,2,38,2,21,0,0,0,6,6,79,246,0,255,255,0,156,255,236,4,134,6,92,2,38,2,21,0,0,0,6,6,29,35,0,0,4,0,168,255,251,4,49,5,220,0,19,0,23,0,27,0,47,0,47,64,27,21,0,114,28,45,106,28,20,0,37,1,24,25,106,36,24,24,10,20,10,114,10,11,106,10,6,114,0,43,43,43,17,57,47,51,43,50,57,57,17,51,43,43,48,49,1,55,50,54,55,55,62,2,51,51,21,35,34,6,7,7,6,6,35,1,17,51,17,3,53,33,21,1,34,38,38,39,39,38,38,35,39,51,50,22,23,23,22,22,51,51,21,2,26,8,64,51,17,69,31,66,98,78,43,43,37,38,14,70,25,95,81,254,20,212,15,1,53,1,100,78,103,71,31,69,17,51,64,8,132,81,105,25,70,14,38,37,33,2,32,81,39,43,171,77,81,29,190,20,34,164,57,56,253,224,5,220,250,36,1,179,190,190,254,72,29,81,77,171,43,39,81,56,57,164,34,20,190,0,1,0,95,0,0,4,81,4,36,0,7,0,19,64,9,6,4,1,6,114,4,0,10,114,0,43,50,43,18,57,48,49,51,1,33,1,35,1,35,1,95,1,104,1,34,1,104,220,254,236,18,254,236,4,36,251,220,3,120,252,136,255,255,0,168,0,0,4,8,4,56,2,6,1,35,0,0,255,255,0,112,0,0,4,64,4,56,2,6,1,34,0,0,0,4,0,156,254,242,4,134,4,36,0,3,0,20,0,27,0,31,0,44,64,27,25,27,2,105,27,10,114,18,28,31,23,24,16,6,4,29,8,6,114,4,13,106,0,96,4,11,114,0,43,26,206,43,43,50,18,23,57,43,43,57,48,49,1,17,51,17,37,34,38,53,17,51,17,20,22,51,50,54,53,19,35,6,6,55,39,53,51,21,23,21,1,17,51,17,3,190,200,253,116,167,183,212,104,94,116,118,54,70,25,146,205,18,212,146,254,154,212,254,242,1,204,254,52,250,199,181,2,188,253,68,91,99,147,173,254,226,108,116,10,254,186,248,12,170,1,44,2,248,253,68,0,1,0,112,255,236,4,64,4,36,0,34,0,35,64,19,22,10,114,20,13,13,4,6,114,25,31,17,0,9,106,28,0,11,114,0,43,50,43,50,57,57,43,50,17,51,43,48,49,5,34,38,53,17,51,17,20,22,51,50,54,53,17,51,17,20,51,50,53,17,51,17,7,39,35,6,6,35,34,38,39,35,6,6,1,77,107,114,212,47,46,46,47,180,94,92,212,194,11,18,16,87,65,61,85,21,16,16,96,20,177,163,2,228,253,28,76,84,78,92,2,218,253,28,160,160,2,228,251,216,6,154,79,85,85,79,79,85,0,2,0,82,254,242,4,166,4,36,0,3,0,38,0,45,64,25,3,26,96,26,2,106,26,11,114,24,17,17,8,6,114,36,29,21,4,13,106,32,4,11,114,0,43,50,43,50,57,57,43,50,17,51,43,43,26,16,205,48,49,1,17,51,17,37,34,38,53,17,51,17,20,22,51,50,54,53,17,51,17,20,51,50,53,17,51,17,7,39,35,6,6,35,34,38,39,35,6,6,3,222,200,252,137,107,114,212,47,46,46,47,180,94,92,212,194,11,18,16,87,65,61,85,21,16,16,96,254,242,1,204,254,52,250,177,163,2,228,253,28,76,84,78,92,2,218,253,28,160,160,2,228,251,216,6,154,79,85,85,79,79,85,0,0,2,0,168,255,236,4,100,4,36,0,15,0,26,0,31,64,17,10,22,106,6,0,10,10,0,4,6,114,0,16,106,0,11,114,0,43,43,43,17,57,47,18,57,43,48,49,5,34,38,39,17,51,17,51,54,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,2,126,225,243,2,212,18,30,179,129,185,203,254,230,126,138,135,123,127,139,20,220,202,2,146,254,20,104,113,207,188,196,214,184,118,108,101,110,115,106,216,0,0,2,0,0,255,236,4,100,4,36,0,17,0,28,0,33,64,19,12,24,106,8,12,12,0,6,5,106,6,6,114,0,18,106,0,11,114,0,43,43,43,43,18,57,47,57,43,48,49,5,34,38,39,17,35,53,33,17,51,54,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,2,161,203,220,2,248,1,204,18,26,155,112,169,184,236,213,110,119,116,107,106,115,20,220,202,1,212,190,254,20,104,113,207,188,196,214,184,118,108,101,110,115,106,216,0,4,0,110,255,236,4,100,5,220,0,11,0,15,0,19,0,31,0,38,64,23,15,10,114,13,0,114,16,17,106,16,16,0,6,26,106,6,7,114,0,20,106,0,11,0,63,43,43,43,18,57,47,43,43,43,48,49,5,34,2,17,16,18,51,50,18,17,16,2,37,17,51,17,3,53,33,21,19,50,54,53,52,38,35,34,6,21,20,22,3,7,173,156,156,173,184,165,165,252,175,197,125,1,75,252,78,71,71,78,78,71,71,20,1,0,1,28,1,39,1,9,254,247,254,217,254,228,255,0,20,5,220,250,36,1,184,174,174,254,236,169,187,198,178,178,198,187,169,0,0,2,0,126,255,236,4,60,5,141,0,36,0,48,0,33,64,19,8,7,28,43,106,28,0,18,19,106,0,37,106,18,2,114,0,11,114,0,43,43,43,43,18,57,43,57,57,48,49,5,34,38,38,53,52,54,55,53,46,2,53,52,62,2,55,37,23,5,14,2,21,20,22,22,23,30,3,21,20,6,6,39,50,54,53,52,38,35,34,6,21,20,22,2,88,142,214,118,184,147,111,110,36,102,153,159,56,1,74,10,254,153,66,109,64,55,85,44,89,173,142,84,120,217,142,128,137,148,118,122,142,145,20,110,206,143,182,204,28,23,25,79,93,45,102,117,54,16,2,12,189,17,3,13,45,51,47,54,30,12,24,61,103,169,133,154,220,116,184,172,129,139,152,160,135,137,160,0,255,255,0,45,0,0,4,131,5,140,2,6,0,1,0,0,255,255,0,160,0,0,4,110,5,140,2,6,0,27,0,0,255,255,0,180,0,0,4,66,5,140,2,6,1,146,0,0,0,2,0,45,0,0,4,131,5,140,0,7,0,11,0,25,64,13,6,4,1,2,114,8,9,106,8,4,0,8,114,0,43,50,50,43,43,18,57,48,49,51,1,33,1,35,1,35,1,35,53,33,21,45,1,154,1,34,1,154,210,254,176,18,254,176,80,3,72,5,140,250,116,4,224,251,32,190,190,0,255,255,0,160,0,0,4,76,5,140,2,6,0,38,0,0,255,255,0,150,0,0,4,46,5,140,2,6,0,184,0,0,255,255,0,140,0,0,4,36,5,140,2,6,0,66,0,0,0,3,0,76,255,236,4,100,5,160,0,3,0,11,0,19,0,31,64,18,4,12,106,0,1,106,0,0,4,8,16,106,8,3,114,4,9,114,0,43,43,43,18,57,47,43,43,48,49,19,53,33,21,1,32,17,16,33,32,17,16,37,32,17,16,33,32,17,16,213,3,6,254,125,253,244,2,12,2,12,253,244,1,58,254,198,254,198,2,104,188,188,253,132,2,208,2,228,253,28,253,48,184,2,24,2,44,253,212,253,232,0,255,255,0,168,0,0,4,8,5,140,2,6,0,70,0,0,255,255,0,160,0,0,4,148,5,140,2,6,0,85,0,0,255,255,0,45,0,0,4,131,5,140,2,6,1,207,0,0,255,255,0,128,0,0,4,48,5,140,2,6,0,93,0,0,255,255,0,148,0,0,4,28,5,140,2,6,0,94,0,0,0,3,0,100,0,0,4,76,5,140,0,3,0,7,0,11,0,31,64,18,4,5,106,8,9,106,8,8,4,1,0,106,1,2,114,4,8,114,0,43,43,43,18,57,47,43,43,48,49,19,53,33,21,1,53,33,21,1,53,33,21,100,3,232,252,24,3,232,252,114,3,52,4,206,190,190,251,50,190,190,2,104,190,190,255,255,0,76,255,236,4,100,5,160,2,6,0,101,0,0,255,255,0,140,0,0,4,36,5,140,2,6,1,164,0,0,255,255,0,160,0,0,4,96,5,140,2,6,0,128,0,0,0,3,0,150,0,0,4,46,5,140,0,5,0,9,0,13,0,35,64,19,4,3,11,10,106,2,5,6,11,2,114,0,1,6,7,106,6,8,114,0,43,43,50,57,43,18,57,57,43,50,57,48,49,37,39,1,1,55,1,1,53,33,21,1,53,33,21,1,40,146,1,185,254,71,162,2,23,253,71,3,152,252,104,3,132,54,122,2,25,2,5,132,253,119,253,55,176,176,4,206,190,190,255,255,0,80,0,0,4,96,5,140,2,6,0,143,0,0,255,255,0,25,0,0,4,151,5,140,2,6,0,175,0,0,255,255,0,66,255,236,4,110,5,180,2,6,1,170,0,0,255,255,0,66,0,0,4,112,5,140,2,6,0,174,0,0,0,3,0,76,0,0,4,100,5,140,0,13,0,17,0,21,0,26,64,14,14,15,19,18,4,3,17,8,114,20,11,3,2,114,0,43,50,50,43,18,23,57,48,49,1,32,17,17,51,17,16,33,32,17,17,51,17,16,37,51,17,35,19,35,17,51,2,88,253,244,200,1,68,1,68,200,253,143,200,200,200,200,200,1,54,2,28,2,58,253,198,254,156,1,100,2,58,253,198,253,228,100,254,102,1,154,3,242,0,3,0,76,0,0,4,100,5,160,0,25,0,29,0,33,0,45,64,25,15,30,31,106,14,0,30,30,26,13,1,1,25,26,27,106,26,8,114,7,20,106,7,3,114,0,43,43,43,43,50,50,17,51,17,51,17,57,57,43,50,48,49,37,53,46,2,53,16,33,32,17,20,6,6,7,21,39,54,18,53,16,33,32,17,20,18,23,5,53,33,21,51,53,33,21,1,94,91,122,61,2,12,2,12,55,111,84,180,110,110,254,198,254,198,122,122,254,86,1,170,164,1,146,127,76,20,136,235,166,2,168,253,88,169,236,133,16,71,51,40,1,31,247,1,240,254,16,243,254,225,44,186,186,186,186,186,0,0,3,255,255,0,0,4,131,5,140,0,7,0,11,0,15,0,35,64,19,8,9,106,8,8,0,5,4,13,15,106,2,13,2,114,4,0,8,114,0,43,50,43,50,43,18,57,18,57,47,43,48,49,51,1,33,1,35,3,35,3,3,53,33,21,1,19,51,3,245,1,54,1,34,1,54,210,236,18,236,20,2,8,252,68,90,212,110,5,140,250,116,4,224,251,32,1,90,190,190,2,182,1,124,254,132,0,5,255,255,0,0,4,76,5,140,0,3,0,7,0,11,0,15,0,19,0,43,64,25,17,16,106,17,13,8,9,106,8,8,0,13,15,106,2,13,2,114,4,5,106,4,0,8,114,0,43,50,43,43,50,43,18,57,47,43,17,51,43,48,49,33,17,51,17,35,53,33,21,1,53,33,21,1,19,51,3,55,53,33,21,1,104,200,200,2,228,253,28,2,48,252,103,90,212,110,169,2,228,5,140,250,116,190,190,2,104,190,190,1,168,1,124,254,132,190,190,190,0,4,255,255,0,0,4,36,5,140,0,3,0,7,0,11,0,15,0,33,64,18,12,13,106,12,12,4,9,11,106,6,1,9,2,114,0,4,8,114,0,43,50,43,50,50,43,18,57,47,43,48,49,33,17,51,17,33,17,51,17,1,19,51,3,19,53,33,21,3,92,200,253,48,200,253,227,90,212,110,191,2,129,5,140,250,116,5,140,250,116,4,16,1,124,254,132,254,84,190,190,0,0,4,255,255,0,0,4,8,5,140,0,3,0,7,0,11,0,15,0,31,64,18,13,12,106,13,9,11,106,1,9,2,114,4,5,106,0,4,8,114,0,43,50,43,43,50,43,51,43,48,49,33,17,51,17,33,53,33,21,1,19,51,3,55,53,33,21,2,87,200,254,81,2,152,251,247,90,212,110,177,2,152,5,140,250,116,190,190,4,16,1,124,254,132,190,190,190,0,0,3,255,255,255,236,4,100,5,160,0,7,0,11,0,19,0,29,64,18,9,11,106,9,2,114,4,16,106,4,3,114,0,12,106,0,9,114,0,43,43,43,43,43,43,48,49,5,32,17,16,33,32,17,16,1,19,51,3,1,50,17,16,35,34,17,16,2,188,254,88,1,168,1,168,251,155,90,212,110,1,253,214,214,214,20,2,208,2,228,253,28,253,48,4,36,1,124,254,132,252,148,2,24,2,44,253,212,253,232,0,3,255,255,0,0,4,152,5,140,0,7,0,11,0,15,0,31,64,17,0,9,3,3,1,11,1,13,15,106,6,13,2,114,11,8,114,0,43,43,50,43,51,17,18,23,57,48,49,1,1,51,19,51,19,51,1,3,17,51,17,1,19,51,3,2,156,254,180,220,186,18,196,220,254,174,185,200,252,170,90,212,110,1,214,3,182,253,58,2,198,252,74,254,42,2,188,253,68,4,16,1,124,254,132,0,0,4,255,255,0,0,4,100,5,160,0,19,0,23,0,27,0,31,0,45,64,25,29,31,106,29,2,114,11,9,26,24,24,10,0,19,1,21,20,8,114,5,15,106,5,3,114,0,43,43,43,205,50,50,57,57,51,16,205,50,50,43,43,48,49,37,53,36,17,16,33,32,17,16,7,21,39,54,17,16,35,34,17,16,23,5,53,33,21,51,53,33,21,1,19,51,3,2,28,254,248,1,168,1,168,240,130,160,214,214,184,254,146,1,110,84,1,86,251,183,90,212,110,127,76,59,1,242,2,168,253,88,254,6,48,71,51,79,1,239,1,240,254,16,254,26,88,186,186,186,186,186,4,16,1,124,254,132,255,255,0,168,0,0,4,8,7,56,2,38,2,43,0,0,1,6,6,60,0,0,0,13,183,4,3,12,1,1,1,160,86,0,43,52,52,0,255,255,0,25,0,0,4,151,7,56,2,38,2,54,0,0,1,6,6,60,0,0,0,13,183,3,2,12,5,1,1,160,86,0,43,52,52,0,0,3,0,160,254,117,4,148,5,140,0,11,0,15,0,27,0,43,64,22,0,1,106,22,21,6,26,17,12,0,0,6,12,6,13,2,114,16,96,12,8,114,0,43,26,206,43,50,17,18,57,47,18,57,57,18,57,57,43,48,49,1,55,50,54,54,18,53,51,20,2,2,4,1,17,51,17,1,17,52,38,39,1,55,1,22,22,21,17,1,30,18,154,224,145,71,206,110,210,254,208,254,192,200,2,100,24,32,254,166,180,1,110,32,24,1,196,198,129,219,1,19,147,189,254,164,254,239,158,254,60,5,140,250,116,254,117,1,166,36,62,48,2,7,102,253,207,49,79,58,254,70,0,3,0,76,255,236,4,134,4,56,0,26,0,33,0,37,0,44,64,29,35,6,114,33,31,106,33,10,114,9,11,22,30,37,24,6,0,6,13,106,6,7,114,0,18,106,0,11,114,0,43,43,43,43,18,23,57,43,43,43,48,49,5,34,2,17,16,18,51,50,22,23,51,3,16,33,34,6,21,16,51,50,54,53,53,19,35,6,6,55,39,53,51,21,23,21,1,17,51,17,2,16,215,237,237,217,114,124,12,82,62,254,242,117,127,246,135,133,72,92,10,135,183,18,212,146,254,154,212,20,1,23,1,5,1,11,1,37,105,107,254,240,1,48,198,182,254,152,90,90,116,254,220,91,93,10,254,186,238,22,170,1,44,2,248,253,68,0,0,3,0,160,254,52,4,50,5,160,0,44,0,48,0,52,0,52,64,32,48,14,114,52,39,16,51,4,37,18,105,47,10,5,3,28,3,37,37,0,10,25,106,10,3,114,0,30,106,0,11,114,0,43,43,43,43,18,57,47,23,57,18,57,43,23,57,43,48,49,5,34,38,53,23,35,38,53,17,16,33,50,22,21,20,6,35,35,53,51,50,54,53,52,38,35,34,17,17,16,51,50,54,53,52,38,35,35,53,51,50,22,21,20,6,1,17,51,17,19,53,51,21,2,142,126,138,34,93,171,1,196,201,221,194,176,156,98,99,109,106,96,240,244,113,125,126,116,104,234,158,174,220,253,74,212,136,246,20,124,112,40,110,184,1,217,1,241,189,171,145,161,91,108,97,86,94,254,202,254,42,254,212,131,119,122,133,91,191,175,200,220,254,72,4,144,251,112,4,154,98,98,0,2,0,36,254,52,4,116,4,76,0,5,0,23,0,29,64,17,14,6,15,7,114,6,14,114,3,6,114,0,1,106,0,11,114,0,43,43,43,43,43,17,57,48,49,5,53,32,17,51,16,1,54,54,53,52,2,38,38,39,55,30,2,18,21,20,6,7,1,108,2,52,212,252,170,5,5,23,58,101,78,122,105,136,78,31,5,5,20,190,3,122,251,200,254,72,98,235,137,213,1,40,202,143,61,175,76,175,240,254,164,251,137,235,98,0,0,2,0,126,255,236,4,60,5,160,0,34,0,46,0,39,64,24,7,9,8,3,27,41,106,27,19,18,3,0,16,21,106,16,3,114,0,35,106,0,11,114,0,43,43,43,43,18,23,57,43,23,57,48,49,5,34,38,38,53,52,54,55,53,23,46,2,53,52,54,51,50,23,7,38,35,34,6,21,20,22,23,30,2,21,20,6,6,39,50,54,53,52,38,35,34,6,21,20,22,2,91,144,215,118,177,163,41,107,136,64,227,207,220,180,102,127,171,117,105,92,112,149,209,110,120,216,143,120,145,150,124,115,141,145,20,111,201,134,167,194,9,66,56,31,81,110,73,162,177,107,163,80,61,68,58,72,31,41,112,191,160,143,215,118,184,171,141,122,148,159,131,132,160,0,2,0,166,255,236,4,26,4,56,0,17,0,33,0,39,64,22,5,19,4,33,32,106,6,33,33,0,23,28,106,23,7,114,0,11,106,0,11,114,0,43,43,43,43,18,57,47,51,43,57,57,50,48,49,5,32,17,52,37,37,7,35,32,21,20,51,50,54,55,23,6,6,1,53,36,53,16,33,32,23,7,38,35,34,21,20,5,7,2,114,254,52,1,106,1,50,24,32,254,121,247,124,163,64,55,80,209,254,233,254,236,1,190,1,27,125,65,138,183,247,1,161,24,20,1,44,226,30,80,181,145,126,38,17,191,22,26,1,199,115,70,202,1,2,58,181,55,124,140,16,181,0,2,0,176,254,32,4,58,5,220,0,25,0,29,0,31,64,18,13,14,12,27,26,106,27,0,114,7,20,106,7,10,114,0,15,114,0,43,43,43,43,43,50,50,57,48,49,1,39,54,54,53,52,38,35,32,0,53,16,1,53,5,4,0,21,20,22,51,50,22,21,20,6,1,53,33,21,2,255,95,101,99,73,67,254,247,254,221,2,114,1,18,254,149,254,185,209,191,141,155,157,253,75,3,76,254,32,180,29,87,58,50,56,1,14,252,1,209,1,64,74,47,231,254,132,191,167,175,155,141,137,176,6,217,186,186,0,2,0,168,254,52,4,8,4,56,0,15,0,20,0,30,64,17,17,6,114,7,6,11,16,10,114,11,4,106,11,7,114,0,14,0,63,43,43,43,17,57,57,43,48,49,1,17,52,38,35,34,17,3,51,54,54,51,50,22,21,17,1,17,51,23,17,3,52,100,90,250,62,82,9,138,133,168,184,252,160,192,20,254,52,4,126,101,109,254,208,1,16,107,105,204,186,251,130,1,204,4,36,224,252,188,0,3,0,136,255,236,4,40,5,160,0,11,0,23,0,27,0,31,64,18,0,12,106,24,25,106,24,24,0,6,18,106,6,3,114,0,11,114,0,43,43,43,18,57,47,43,43,48,49,5,34,2,17,16,18,51,50,18,17,16,2,39,50,18,17,16,2,35,34,2,17,16,18,1,53,33,21,2,88,244,220,220,244,244,220,220,244,134,120,120,134,133,121,121,254,237,3,73,20,1,90,1,128,1,128,1,90,254,166,254,128,254,128,254,166,184,1,3,1,31,1,31,1,3,254,253,254,225,254,225,254,253,1,198,190,190,0,2,0,130,255,236,4,40,4,36,0,15,0,19,0,25,64,14,5,17,0,10,106,17,16,106,17,6,114,0,11,114,0,43,43,43,43,17,51,48,49,5,34,38,53,17,51,17,20,22,22,51,50,55,23,6,6,1,53,33,21,2,252,177,157,212,30,87,85,78,118,24,77,142,253,53,1,62,20,200,220,2,148,253,118,84,106,50,38,186,22,20,3,136,176,176,0,3,0,168,0,0,4,136,4,56,0,7,0,12,0,16,0,30,64,17,1,14,5,15,4,8,9,6,114,13,0,8,10,114,6,7,114,0,43,43,50,50,43,18,23,57,48,49,33,39,51,54,54,55,1,23,1,17,51,17,7,33,1,55,1,1,104,38,80,15,79,72,1,150,153,252,65,212,20,2,51,254,206,149,1,138,171,110,200,90,1,253,119,252,63,4,36,252,71,107,1,212,140,253,160,0,0,2,0,67,255,236,4,150,5,220,0,23,0,31,0,34,64,21,24,10,114,25,26,27,30,4,0,12,7,106,12,0,114,0,19,106,0,11,114,0,43,43,43,43,18,23,57,43,48,49,5,34,38,39,3,38,38,35,34,7,39,54,51,50,22,23,1,22,22,51,50,55,23,6,37,1,23,7,22,6,7,3,4,44,130,160,44,255,27,81,58,27,35,24,51,55,128,156,42,1,2,27,83,61,27,35,24,51,251,224,1,203,136,135,16,5,20,224,20,117,154,3,121,95,75,8,186,12,112,148,252,124,95,75,8,186,12,20,4,84,191,41,66,122,57,253,137,0,0,4,0,156,254,52,4,134,4,36,0,17,0,21,0,28,0,32,0,47,64,30,28,26,106,28,10,114,18,14,114,13,19,24,4,29,20,2,7,15,15,0,30,5,6,114,0,10,106,0,11,114,0,43,43,43,50,17,57,47,23,57,43,43,43,48,49,5,34,39,35,39,17,51,17,20,22,51,50,54,53,19,35,6,6,1,17,23,19,1,39,53,51,21,23,21,1,17,51,17,2,54,162,43,57,148,212,104,94,116,118,54,70,21,109,254,14,184,38,1,184,18,212,146,254,154,212,20,224,156,2,188,253,138,115,125,138,162,254,226,112,112,254,72,3,122,193,253,71,1,194,254,186,238,22,170,1,44,2,248,253,68,0,2,0,6,0,0,4,96,4,56,0,5,0,17,0,27,64,15,12,7,114,17,2,11,3,3,6,5,10,114,3,6,114,0,43,43,50,17,23,57,43,48,49,33,55,51,1,51,1,33,3,46,2,39,55,30,2,23,19,1,188,142,18,1,34,226,254,128,254,220,113,39,81,115,90,122,103,138,93,34,122,180,3,112,251,220,1,134,134,207,140,34,175,38,142,206,134,254,31,0,0,4,0,142,254,32,4,48,5,220,0,14,0,28,0,43,0,47,0,61,64,35,30,5,42,29,37,38,36,45,44,106,6,29,42,105,8,29,29,0,45,0,114,15,16,106,15,15,114,23,0,12,106,22,0,11,114,0,43,50,43,50,43,43,43,18,57,47,51,43,50,43,50,50,57,17,18,57,57,48,49,5,32,17,52,54,55,37,7,35,32,17,20,33,51,7,19,39,54,54,53,52,38,35,55,50,22,21,20,6,1,53,38,38,53,52,54,55,53,5,32,21,16,33,7,1,53,33,21,2,102,254,54,198,234,1,150,14,32,253,186,1,59,95,54,35,75,85,95,73,67,54,141,155,157,254,159,206,170,128,128,1,186,254,24,2,86,14,252,186,3,136,20,1,84,161,190,30,94,190,254,247,170,190,254,52,180,29,87,58,50,56,190,155,141,137,176,4,20,110,15,153,139,116,131,24,72,50,253,254,245,190,2,197,186,186,255,255,0,136,255,236,4,40,4,56,2,6,1,43,0,0,0,3,0,90,255,236,4,120,4,36,0,15,0,19,0,23,0,29,64,17,21,20,106,18,5,21,6,114,16,10,114,0,9,106,0,11,114,0,43,43,43,43,50,50,43,48,49,5,34,38,53,17,51,17,20,22,51,50,54,55,23,6,6,37,17,51,17,1,53,33,21,3,230,147,131,212,47,79,14,29,19,24,37,62,252,237,212,254,132,4,16,20,157,173,2,238,253,28,79,71,4,4,186,7,5,20,4,36,251,220,3,102,190,190,0,2,0,168,254,52,4,80,4,56,0,27,0,31,0,36,64,23,28,14,114,3,6,5,18,19,29,6,0,22,15,106,22,7,114,0,9,106,0,11,114,0,43,43,43,43,18,23,57,43,48,49,5,34,38,39,35,19,21,20,22,51,50,54,53,52,38,35,34,6,21,39,52,54,51,50,18,17,16,2,1,17,51,17,2,150,112,140,10,92,72,133,135,122,124,129,129,122,134,212,245,223,235,233,231,253,63,212,20,93,91,1,36,116,90,90,182,178,191,189,159,145,9,227,248,254,233,254,231,254,251,254,233,254,72,4,41,251,215,0,0,1,0,136,254,32,4,73,4,56,0,34,0,35,64,21,18,17,7,14,21,106,14,7,114,7,28,106,7,11,114,0,1,106,0,15,114,0,43,43,43,43,43,43,18,57,57,48,49,1,39,54,54,53,52,39,35,34,2,17,52,54,54,51,50,22,23,7,38,38,35,34,6,6,21,20,22,51,51,22,22,21,20,6,2,185,95,98,108,117,89,223,243,125,241,172,155,221,47,163,45,140,83,98,139,73,156,144,90,130,142,168,254,32,180,28,91,55,103,3,1,29,1,11,173,245,130,115,105,123,73,80,81,156,111,181,191,2,155,139,130,185,0,3,0,136,255,236,4,176,4,36,0,15,0,27,0,31,0,31,64,18,7,8,29,28,106,29,6,22,106,6,6,114,0,16,106,0,11,114,0,43,43,43,43,51,43,50,57,48,49,5,34,2,17,52,18,51,23,21,30,2,21,20,6,6,39,50,54,53,52,38,35,34,6,21,20,22,19,53,33,21,2,83,218,241,241,218,224,65,101,59,112,201,136,110,119,119,110,115,124,124,115,2,93,20,1,32,1,6,253,1,21,63,151,10,106,163,97,147,221,122,190,188,172,163,177,177,163,172,188,2,188,190,190,0,0,2,0,130,255,236,4,46,4,36,0,15,0,19,0,25,64,14,5,17,0,9,106,17,16,106,17,6,114,0,11,114,0,43,43,43,43,17,51,48,49,5,34,38,53,17,51,17,20,22,51,50,54,55,23,6,6,1,53,33,21,2,252,177,157,212,75,127,41,94,61,24,77,142,253,53,3,172,20,200,220,2,148,253,118,126,114,19,19,186,22,20,3,122,190,190,0,1,0,5,255,236,4,20,4,36,0,21,0,25,64,14,19,8,0,15,106,8,7,106,8,6,114,0,11,114,0,43,43,43,43,17,51,48,49,5,32,17,3,52,38,35,35,53,51,50,22,21,19,20,51,50,53,17,51,17,16,2,128,254,108,1,50,62,118,158,157,127,1,192,192,212,20,1,174,1,64,77,63,190,125,155,254,142,240,240,2,138,253,118,254,82,0,5,0,86,254,72,4,90,5,220,0,11,0,15,0,27,0,31,0,35,0,37,64,22,33,0,114,12,14,114,35,29,6,22,105,6,7,114,31,14,0,16,105,0,11,114,0,43,43,57,57,43,43,57,57,43,43,48,49,5,32,0,17,16,0,33,32,0,17,16,0,1,19,51,19,3,50,54,53,52,38,35,34,6,21,20,22,23,17,51,17,3,3,51,3,2,88,254,254,255,0,1,0,1,2,1,2,1,0,255,0,254,148,25,162,25,106,158,156,156,158,157,157,157,76,162,162,25,212,25,20,1,18,1,20,1,20,1,18,254,238,254,236,254,236,254,238,254,92,1,215,254,41,2,68,194,196,196,194,194,196,196,194,38,3,103,252,153,3,148,1,226,254,30,0,2,0,57,254,72,4,105,4,56,0,25,0,31,0,40,64,26,3,16,30,27,4,15,6,28,31,14,114,28,6,114,12,7,106,12,7,114,0,19,106,0,15,114,0,43,43,43,43,43,43,17,23,57,48,49,1,34,38,39,1,38,38,35,34,7,39,54,51,50,22,23,1,22,22,51,50,54,55,23,6,6,37,1,1,51,1,1,3,255,134,154,57,254,168,36,90,65,27,35,24,51,55,132,149,55,1,92,37,92,67,14,29,19,24,28,48,252,57,1,206,1,70,240,254,44,254,192,254,72,123,148,3,121,93,77,8,186,12,118,142,252,124,94,76,4,4,186,7,5,20,3,46,2,154,252,212,253,100,0,0,2,0,106,254,72,4,70,5,220,0,13,0,19,0,31,64,18,16,0,114,14,14,114,10,3,6,114,18,15,0,7,105,0,11,114,0,43,43,57,57,43,50,43,43,48,49,5,32,17,17,51,17,16,33,32,17,17,51,17,16,1,19,3,51,3,19,2,88,254,18,202,1,36,1,36,202,253,173,20,15,192,15,20,20,2,38,2,18,253,238,254,142,1,114,2,18,253,238,253,218,254,92,2,69,5,79,250,177,253,187,0,0,3,0,106,255,236,4,58,4,36,0,16,0,33,0,37,0,39,64,23,34,30,3,5,29,5,35,35,0,13,21,6,114,0,8,106,0,17,26,106,17,11,114,0,43,43,51,43,43,50,18,57,47,23,57,48,49,5,34,38,39,51,55,20,22,51,50,54,53,17,51,17,20,6,33,34,38,53,17,51,17,20,22,51,50,54,53,23,51,6,6,19,17,51,17,3,59,106,109,16,1,87,47,46,46,47,212,130,253,167,119,126,212,47,46,46,47,87,1,16,114,42,180,20,173,191,16,109,91,84,76,2,228,253,28,163,177,177,163,2,228,253,28,76,84,91,109,16,191,173,1,88,2,24,253,232,255,255,0,130,255,236,4,40,6,92,2,38,2,77,0,0,1,6,6,76,222,0,0,11,182,2,20,4,1,1,188,86,0,43,52,0,255,255,0,130,255,236,4,40,5,226,2,38,2,77,0,0,1,6,6,27,194,0,0,13,183,3,2,20,4,1,1,178,86,0,43,52,52,0,255,255,0,94,255,236,4,40,6,92,2,38,2,77,0,0,1,6,6,78,214,0,0,16,64,9,4,3,2,24,17,1,1,178,86,0,43,52,52,52,255,255,0,5,255,236,4,20,6,92,2,38,2,89,0,0,1,6,6,76,30,0,0,11,182,1,22,18,1,1,188,86,0,43,52,0,255,255,0,5,255,236,4,20,5,226,2,38,2,89,0,0,1,6,6,27,2,0,0,13,183,2,1,22,18,1,1,178,86,0,43,52,52,0,255,255,0,5,255,236,4,72,6,92,2,38,2,89,0,0,1,6,6,78,22,0,0,16,64,9,3,2,1,26,8,1,1,178,86,0,43,52,52,52,255,255,0,136,255,236,4,40,6,92,2,38,2,83,0,0,1,6,6,76,30,0,0,11,182,2,24,6,1,1,168,86,0,43,52,0,255,255,0,106,255,236,4,58,6,92,2,38,2,93,0,0,1,6,6,76,30,0,0,11,182,3,38,21,1,1,188,86,0,43,52,0,255,255,0,76,255,236,4,134,6,92,2,38,2,69,0,0,1,6,6,76,0,0,0,11,182,3,38,6,1,1,168,86,0,43,52,0,255,255,0,166,255,236,4,26,6,92,2,38,2,73,0,0,1,6,6,76,70,0,0,11,182,2,34,23,1,1,168,86,0,43,52,0,255,255,0,168,254,52,4,8,6,92,2,38,2,75,0,0,1,6,6,76,20,0,0,11,182,2,21,17,1,1,188,86,0,43,52,0,0,3,0,168,254,117,4,103,4,56,0,7,0,12,0,24,0,38,64,24,13,14,114,14,23,1,18,5,19,6,8,9,6,114,0,8,10,114,6,7,106,6,7,114,0,43,43,43,50,43,18,23,57,43,48,49,33,39,51,54,54,55,1,23,1,17,51,17,7,1,17,52,38,39,3,55,1,22,22,21,17,1,104,38,80,15,79,72,1,150,153,252,65,212,20,2,31,18,22,246,149,1,32,34,27,171,110,200,90,1,253,119,252,63,4,36,252,71,107,254,117,1,151,51,63,28,1,58,140,254,139,42,83,60,254,67,0,3,0,116,255,236,4,60,5,160,0,7,0,19,0,27,0,29,64,17,8,14,106,8,0,4,24,106,4,5,114,0,20,106,0,13,114,0,43,43,43,43,18,57,43,48,49,5,32,17,16,33,32,17,16,1,34,38,53,52,54,51,50,22,21,20,6,3,32,17,16,33,32,17,16,2,88,254,28,1,228,1,228,254,28,67,83,83,67,68,82,82,68,1,14,254,242,254,242,20,2,208,2,228,253,28,253,48,2,58,83,67,68,82,82,68,67,83,254,126,2,24,2,44,253,212,253,232,0,4,0,170,0,0,4,28,5,140,0,3,0,7,0,11,0,15,0,37,64,21,13,12,106,13,4,14,15,106,1,14,4,114,9,4,5,106,8,0,4,12,114,0,43,50,50,43,50,43,50,43,18,57,43,48,49,33,17,51,17,33,53,33,21,51,53,33,21,1,53,37,21,2,12,212,253,202,1,118,172,1,80,252,162,1,78,5,140,250,116,186,186,186,186,4,74,202,120,206,0,2,0,126,0,0,4,72,5,160,0,21,0,25,0,35,64,20,11,10,0,14,7,106,14,5,114,22,23,106,22,20,0,1,106,0,12,114,0,43,43,50,51,43,43,43,18,57,57,48,49,51,53,36,0,53,52,38,35,34,6,7,39,54,54,51,50,22,21,20,0,5,21,35,53,33,21,172,1,73,1,69,120,122,81,176,63,138,69,254,139,225,223,254,239,254,233,252,3,96,224,182,1,140,210,122,122,94,78,137,99,120,213,215,216,254,115,183,216,186,186,0,0,2,0,125,255,236,4,20,5,160,0,22,0,45,0,45,64,25,17,44,16,45,24,105,15,35,34,38,45,45,0,38,31,106,38,5,114,0,7,106,0,13,114,0,43,43,43,43,18,57,47,18,57,57,51,43,50,57,57,48,49,5,34,38,39,55,22,22,51,50,54,53,52,38,38,35,35,39,5,22,22,21,20,4,1,39,62,2,53,52,38,35,34,6,7,39,54,54,51,50,22,21,20,6,7,21,2,2,110,183,71,25,61,153,117,154,170,98,187,133,32,24,1,50,170,212,254,235,254,125,24,156,196,92,111,103,76,171,76,138,92,242,149,194,212,164,132,20,26,22,191,17,38,124,112,80,112,58,130,24,13,195,168,190,210,2,158,130,21,82,117,72,87,97,76,76,137,104,95,165,153,128,189,35,120,0,0,4,0,72,0,0,4,96,5,140,0,3,0,7,0,11,0,15,0,33,64,17,5,8,9,106,7,3,8,2,8,2,14,15,12,114,14,4,114,0,43,43,18,57,57,47,47,51,51,43,50,48,49,19,19,51,3,35,55,33,21,51,53,51,21,1,17,51,17,74,200,206,202,206,142,2,78,162,154,254,176,202,1,62,3,254,252,2,176,176,176,176,254,194,5,140,250,116,0,3,0,132,255,236,4,70,5,140,0,26,0,31,0,35,0,51,64,30,33,32,106,33,28,27,16,106,15,27,19,13,106,4,27,19,19,27,4,3,0,28,4,114,0,7,106,0,13,114,0,43,43,43,17,23,57,47,47,47,43,17,51,43,17,51,43,48,49,5,34,38,53,51,20,22,51,50,54,53,52,38,35,34,7,55,54,54,51,50,22,22,21,20,6,6,1,19,51,3,7,19,39,33,21,2,102,230,252,214,140,130,126,138,151,137,140,122,18,79,156,79,138,193,101,113,214,253,219,20,210,34,84,4,18,2,176,20,219,199,111,123,154,140,137,151,66,170,45,31,110,209,149,152,214,112,2,188,2,228,253,152,124,2,42,186,186,0,0,3,0,118,255,236,4,60,5,146,0,8,0,23,0,35,0,42,64,26,18,30,106,15,8,1,12,13,0,6,9,18,18,5,9,24,106,9,13,114,5,6,106,5,4,114,0,43,43,43,43,18,57,47,18,23,57,43,48,49,1,39,53,16,0,37,23,4,17,1,34,0,17,23,17,51,54,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,1,37,175,1,157,1,167,20,253,134,1,22,240,254,252,166,74,30,179,129,186,202,242,222,117,127,133,125,128,140,142,1,69,201,88,1,132,1,148,20,190,27,253,225,253,82,1,29,1,5,118,1,4,111,121,230,210,228,252,184,155,141,123,133,144,132,138,138,0,3,0,112,0,0,4,130,5,140,0,3,0,7,0,11,0,27,64,14,5,9,4,96,9,8,106,1,9,4,114,0,12,114,0,43,43,50,43,26,206,18,57,48,49,33,1,51,1,1,17,51,17,3,53,33,7,1,191,1,232,219,254,24,253,214,206,206,4,18,142,5,140,250,116,3,154,1,212,254,44,1,52,190,190,0,0,5,0,116,255,236,4,60,5,160,0,11,0,23,0,27,0,39,0,51,0,43,64,26,26,27,18,28,40,105,18,28,105,18,6,105,18,0,46,34,106,46,5,114,0,12,106,0,13,114,0,43,43,43,43,18,57,43,43,43,18,57,57,48,49,5,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,3,53,33,21,39,50,54,53,52,38,35,34,6,21,20,22,23,34,38,53,52,54,51,50,22,21,20,6,2,88,231,253,253,231,231,253,253,231,129,141,141,129,129,141,141,37,1,78,168,110,120,120,110,109,121,121,109,211,233,233,211,212,232,232,20,215,195,179,195,195,179,195,215,184,124,112,120,134,134,120,112,124,2,30,102,102,140,103,91,104,112,112,104,91,103,100,175,159,171,189,189,171,159,175,0,0,3,0,118,255,250,4,60,5,160,0,8,0,20,0,35,0,42,64,26,21,9,106,4,31,5,30,3,32,6,27,21,21,0,27,15,106,27,5,114,0,1,106,0,12,114,0,43,43,43,43,18,57,47,18,23,57,43,48,49,23,39,36,17,17,23,21,16,0,3,50,54,53,52,38,35,34,6,21,20,22,23,34,38,53,52,54,51,50,0,17,39,17,35,6,6,248,20,2,122,222,254,99,75,128,138,140,140,120,130,137,37,186,202,243,223,240,1,4,166,74,30,179,6,190,27,2,31,1,138,254,48,254,106,254,87,2,177,144,132,138,138,155,141,123,133,184,230,210,228,252,254,227,254,251,118,254,252,111,121,0,3,0,116,255,236,4,60,5,160,0,7,0,11,0,19,0,30,64,18,8,9,11,10,4,0,4,16,106,4,5,114,0,12,106,0,13,114,0,43,43,43,43,18,23,57,48,49,5,32,17,16,33,32,17,16,37,39,1,23,1,32,17,16,33,32,17,16,2,88,254,28,1,228,1,228,252,252,82,2,130,98,254,142,1,14,254,242,254,242,20,2,208,2,228,253,28,253,48,252,106,3,14,80,252,148,2,24,2,44,253,212,253,232,255,255,1,8,255,236,3,122,2,116,2,7,2,147,0,0,252,212,255,255,1,86,255,254,3,92,2,106,2,7,2,148,0,0,252,222,255,255,1,61,255,255,3,90,2,125,2,7,2,149,0,0,252,221,255,255,1,80,255,235,3,79,2,115,2,7,2,150,0,0,252,211,255,255,1,64,0,0,3,98,2,106,2,7,2,151,0,0,252,222,255,255,1,80,255,236,3,106,2,95,2,7,2,152,0,0,252,211,255,255,1,68,255,236,3,112,2,115,2,7,2,153,0,0,252,211,255,255,1,98,0,0,3,131,2,106,2,7,2,154,0,0,252,222,255,255,1,68,255,237,3,107,2,115,2,7,2,155,0,0,252,211,255,255,1,68,255,240,3,112,2,114,2,7,2,156,0,0,252,210,255,255,1,8,255,236,3,122,2,116,2,7,2,147,0,0,252,212,255,255,1,86,255,254,3,92,2,106,2,7,2,148,0,0,252,222,255,255,1,61,255,255,3,90,2,125,2,7,2,149,0,0,252,221,255,255,1,80,255,235,3,79,2,115,2,7,2,150,0,0,252,211,255,255,1,64,0,0,3,98,2,106,2,7,2,151,0,0,252,222,255,255,1,80,255,236,3,106,2,95,2,7,2,152,0,0,252,211,255,255,1,68,255,236,3,112,2,115,2,7,2,153,0,0,252,211,255,255,1,98,0,0,3,131,2,106,2,7,2,154,0,0,252,222,255,255,1,68,255,237,3,107,2,115,2,7,2,155,0,0,252,211,255,255,1,68,255,240,3,112,2,114,2,7,2,156,0,0,252,210,255,255,1,8,3,24,3,122,5,160,2,6,2,147,0,0,255,255,1,86,3,32,3,92,5,140,2,6,2,148,0,0,255,255,1,61,3,34,3,90,5,160,2,6,2,149,0,0,255,255,1,80,3,24,3,79,5,160,2,6,2,150,0,0,255,255,1,64,3,34,3,98,5,140,2,6,2,151,0,0,255,255,1,80,3,25,3,106,5,140,2,6,2,152,0,0,255,255,1,68,3,25,3,112,5,160,2,6,2,153,0,0,255,255,1,98,3,34,3,131,5,140,2,6,2,154,0,0,255,255,1,68,3,26,3,107,5,160,2,6,2,155,0,0,255,255,1,68,3,30,3,112,5,160,2,6,2,156,0,0,0,2,1,8,3,24,3,122,5,160,0,11,0,23,0,21,64,12,0,12,106,6,0,105,6,18,106,6,3,114,0,43,43,43,43,48,49,1,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,2,66,142,172,172,142,141,171,171,141,59,72,72,59,61,72,72,3,24,179,148,146,175,172,149,148,179,163,91,73,72,86,86,72,73,91,0,0,4,1,86,3,32,3,92,5,140,0,3,0,7,0,11,0,15,0,35,64,19,13,12,2,6,11,10,106,7,3,2,11,105,2,15,106,14,2,2,114,0,43,50,43,43,50,50,43,50,18,57,57,48,49,1,17,51,17,33,53,51,21,51,53,51,21,1,53,55,21,2,29,156,254,157,207,139,172,254,3,190,3,32,2,108,253,148,141,141,141,141,1,153,158,53,160,0,0,2,1,61,3,34,3,90,5,160,0,19,0,23,0,33,64,18,9,8,12,21,18,0,1,106,20,12,0,105,12,6,106,12,3,114,0,43,43,43,50,43,50,57,18,57,57,48,49,1,53,54,54,53,52,35,34,7,39,54,54,51,50,22,21,20,6,7,21,35,53,33,21,1,86,149,148,102,74,80,66,44,134,79,117,141,121,123,220,1,234,3,34,157,53,115,60,93,46,138,33,35,109,89,78,143,66,153,140,140,0,2,1,80,3,24,3,79,5,160,0,21,0,41,0,32,64,20,23,40,15,16,14,22,6,34,0,7,106,34,0,105,34,28,106,34,3,114,0,43,43,43,43,18,23,57,48,49,1,6,38,39,55,22,22,51,50,54,53,52,38,35,35,53,23,22,22,21,20,6,3,39,54,54,53,52,35,34,7,39,54,54,51,50,22,21,20,6,7,21,2,42,65,110,43,41,31,81,51,64,70,66,61,64,173,86,105,153,211,10,97,86,112,97,78,21,50,113,63,123,133,82,67,3,25,1,14,13,146,6,15,33,30,25,27,96,15,7,77,68,93,100,1,8,116,7,35,24,49,29,149,16,14,71,67,52,75,14,72,0,0,4,1,64,3,34,3,98,5,140,0,3,0,7,0,11,0,15,0,31,64,16,6,11,10,106,4,3,2,14,11,11,14,15,105,14,2,114,0,43,43,57,47,18,57,51,51,43,50,48,49,1,19,51,3,35,55,33,21,51,53,51,21,7,17,51,17,1,65,78,164,78,165,62,1,12,138,78,225,156,3,140,1,223,254,33,140,140,140,140,106,2,106,253,150,0,0,3,1,80,3,25,3,106,5,140,0,23,0,28,0,32,0,27,64,17,6,4,24,14,12,27,15,18,32,9,25,0,105,30,25,2,114,0,43,50,43,23,57,48,49,1,34,38,53,51,20,51,50,54,53,52,38,35,34,7,55,54,54,51,50,22,21,20,6,37,19,51,3,7,39,39,33,21,2,90,127,139,191,76,41,44,50,46,56,46,8,29,73,37,113,124,142,254,142,9,184,14,51,8,8,1,106,3,25,102,92,50,37,33,32,35,28,112,15,17,93,85,104,115,253,1,118,254,231,93,234,140,140,0,0,3,1,68,3,25,3,112,5,160,0,9,0,24,0,33,0,35,64,20,13,1,14,0,25,5,10,6,19,16,3,5,29,29,5,10,105,5,3,114,0,43,43,57,47,18,23,57,18,23,57,48,49,1,39,53,52,54,55,23,6,6,21,19,34,38,53,23,55,51,54,54,51,50,22,21,20,6,39,50,53,52,35,34,6,21,20,1,195,127,227,251,8,163,146,108,136,149,124,30,31,15,92,66,95,103,141,135,100,100,49,55,3,191,80,21,191,180,9,141,4,93,98,254,201,128,118,70,136,42,46,98,89,101,112,130,78,74,40,37,75,0,0,3,1,98,3,34,3,131,5,140,0,3,0,7,0,11,0,27,64,15,6,9,8,4,105,9,8,106,9,3,105,1,9,2,114,0,43,50,43,43,43,18,57,48,49,1,19,51,3,1,17,51,17,39,53,33,7,2,35,175,177,176,254,143,156,156,2,33,63,3,34,2,106,253,150,1,67,1,25,254,231,156,139,139,0,5,1,68,3,26,3,107,5,160,0,11,0,20,0,24,0,32,0,44,0,24,64,15,12,16,24,33,6,23,25,29,8,39,0,105,39,3,114,0,43,43,23,57,48,49,1,34,38,53,52,54,51,50,22,21,20,6,39,50,53,52,35,34,6,21,20,55,53,51,21,39,50,53,52,35,34,21,20,23,34,38,53,52,54,51,50,22,21,20,6,2,87,130,145,145,130,131,145,145,131,100,100,47,52,29,142,72,83,83,82,82,122,136,136,122,123,136,136,3,26,97,88,79,85,85,79,88,97,118,84,81,43,38,84,206,44,44,77,64,63,63,64,60,80,72,73,80,80,73,72,80,0,3,1,68,3,30,3,112,5,160,0,9,0,24,0,33,0,25,64,16,10,21,4,25,6,19,20,5,30,9,16,0,105,16,3,114,0,43,43,23,57,48,49,1,39,54,54,53,55,23,21,20,6,39,34,38,53,52,54,51,50,22,21,39,7,35,6,6,55,50,54,53,52,35,34,21,20,1,146,8,163,146,50,127,227,131,95,103,141,130,137,148,124,30,31,15,92,12,50,54,104,100,3,30,141,5,89,96,145,80,21,188,178,233,98,89,101,112,128,118,70,136,42,46,118,40,37,75,78,74,0,1,0,94,1,50,4,92,4,82,0,3,0,10,179,2,0,106,2,0,47,43,48,49,19,39,1,23,186,92,3,162,92,1,50,136,2,152,130,0,0,7,0,82,255,255,4,104,5,140,0,3,0,7,0,11,0,15,0,19,0,39,0,43,0,68,64,42,38,43,42,106,32,26,106,43,32,105,20,21,106,20,0,1,3,2,4,6,43,8,114,17,16,6,9,15,14,106,8,7,6,15,105,6,19,106,18,6,2,114,0,43,50,43,43,50,50,43,50,18,57,57,43,17,23,57,50,43,43,43,43,50,48,49,19,39,1,23,5,17,51,17,33,53,51,21,51,53,51,21,1,53,55,21,1,53,54,54,53,52,35,34,7,39,54,54,51,50,22,21,20,6,7,21,35,53,33,21,186,92,3,162,92,252,189,156,254,157,207,139,172,254,3,190,1,75,149,148,102,74,80,66,44,134,79,117,141,121,123,220,1,234,1,40,136,2,152,130,166,2,108,253,148,141,141,141,141,1,153,158,53,160,251,19,157,53,115,60,93,46,138,33,35,109,89,78,143,66,153,140,140,0,0,9,0,82,0,0,4,92,5,140,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,35,0,68,64,40,25,31,30,106,33,32,24,24,23,22,31,105,0,1,3,2,4,19,22,35,106,34,22,2,114,10,15,14,106,11,7,6,15,15,19,17,106,19,8,114,0,43,43,57,47,57,51,51,43,50,43,50,43,18,23,57,43,50,50,18,57,57,43,50,48,49,19,39,1,23,1,19,51,3,35,55,33,21,51,53,51,21,7,17,51,17,1,17,51,17,33,53,51,21,51,53,51,21,1,53,55,21,186,92,3,162,92,253,213,78,164,78,165,62,1,12,138,78,225,156,253,12,156,254,157,207,139,172,254,3,190,1,30,136,2,152,130,252,174,1,223,254,33,140,140,140,140,106,2,106,253,150,3,32,2,108,253,148,141,141,141,141,1,153,158,53,160,0,0,7,0,94,0,0,4,92,5,160,0,3,0,7,0,11,0,15,0,19,0,41,0,61,0,58,64,37,27,42,34,61,36,35,60,43,48,9,54,20,105,0,1,3,2,4,19,54,3,114,10,15,14,106,11,7,6,15,15,19,18,105,19,8,114,0,43,43,57,47,57,51,51,43,50,43,18,23,57,43,23,57,48,49,19,39,1,23,1,19,51,3,35,55,33,21,51,53,51,21,7,17,51,17,1,6,38,39,55,22,22,51,50,54,53,52,38,35,35,53,23,22,22,21,20,6,3,39,54,54,53,52,35,34,7,39,54,54,51,50,22,21,20,6,7,21,186,92,3,162,92,253,213,78,164,78,165,62,1,12,138,78,225,156,253,45,65,110,43,41,31,81,51,64,70,66,61,64,173,86,105,153,211,10,97,86,112,97,78,21,50,113,63,123,133,82,67,1,50,136,2,152,130,252,154,1,223,254,33,140,140,140,140,106,2,106,253,150,3,25,1,14,13,146,6,15,33,30,25,27,96,15,7,77,68,93,100,1,8,116,7,35,24,49,29,149,16,14,71,67,52,75,14,72,0,10,0,82,255,237,4,121,5,140,0,3,0,7,0,11,0,15,0,19,0,31,0,40,0,44,0,52,0,64,0,63,64,40,32,36,44,53,26,43,45,49,8,20,59,105,0,1,3,2,4,6,20,9,114,17,16,6,10,15,14,106,11,7,6,15,105,6,19,106,18,6,2,114,0,43,50,43,43,50,50,43,50,18,57,57,43,17,23,57,43,23,57,48,49,19,39,1,23,5,17,51,17,33,53,51,21,51,53,51,21,1,53,55,21,1,34,38,53,52,54,51,50,22,21,20,6,39,50,53,52,35,34,6,21,20,55,53,51,21,39,50,53,52,35,34,21,20,23,34,38,53,52,54,51,50,22,21,20,6,186,92,3,162,92,252,189,156,254,157,207,139,172,254,3,190,2,76,130,145,145,130,131,145,145,131,100,100,47,52,29,142,72,83,83,82,82,122,136,136,122,123,136,136,1,40,136,2,152,130,166,2,108,253,148,141,141,141,141,1,153,158,53,160,251,1,97,88,79,85,85,79,88,97,118,84,81,43,38,84,206,44,44,77,64,63,63,64,60,80,72,73,80,80,73,72,80,0,0,8,0,76,255,237,4,121,5,160,0,3,0,25,0,45,0,57,0,66,0,70,0,78,0,90,0,52,64,36,58,62,67,79,52,68,71,75,8,46,85,105,0,1,3,2,4,38,46,9,114,26,18,45,20,19,44,27,32,8,38,4,105,38,3,114,0,43,43,23,57,43,17,23,57,43,23,57,48,49,19,39,1,23,5,6,38,39,55,22,22,51,50,54,53,52,38,35,35,53,23,22,22,21,20,6,3,39,54,54,53,52,35,34,7,39,54,54,51,50,22,21,20,6,7,21,1,34,38,53,52,54,51,50,22,21,20,6,39,50,53,52,35,34,6,21,20,55,53,51,21,39,50,53,52,35,34,21,20,23,34,38,53,52,54,51,50,22,21,20,6,186,92,3,162,92,252,202,65,110,43,41,31,81,51,64,70,66,61,64,173,86,105,153,211,10,97,86,112,97,78,21,50,113,63,123,133,82,67,1,192,130,145,145,130,131,145,145,131,100,100,47,52,29,142,72,83,83,82,82,122,136,136,122,123,136,136,1,40,136,2,152,130,173,1,14,13,146,6,15,33,30,25,27,96,15,7,77,68,93,100,1,8,116,7,35,24,49,29,149,16,14,71,67,52,75,14,72,251,172,97,88,79,85,85,79,88,97,118,84,81,43,38,84,206,44,44,77,64,63,63,64,60,80,72,73,80,80,73,72,80,0,0,9,0,76,255,237,4,121,5,140,0,3,0,27,0,32,0,36,0,48,0,57,0,61,0,69,0,81,0,52,64,35,49,53,61,70,43,60,62,66,8,37,76,105,0,1,3,2,4,35,37,9,114,10,8,32,16,31,22,6,35,4,105,30,35,2,114,0,43,50,43,23,57,43,17,23,57,43,23,57,48,49,19,39,1,23,5,34,38,53,51,20,51,50,54,53,52,38,35,34,7,55,54,54,51,50,22,21,20,6,37,19,51,3,7,39,39,33,21,1,34,38,53,52,54,51,50,22,21,20,6,39,50,53,52,35,34,6,21,20,55,53,51,21,39,50,53,52,35,34,21,20,23,34,38,53,52,54,51,50,22,21,20,6,186,92,3,162,92,252,250,127,139,191,76,41,44,50,46,56,46,8,29,73,37,113,124,142,254,142,9,184,14,51,8,8,1,106,1,37,130,145,145,130,131,145,145,131,100,100,47,52,29,142,72,83,83,82,82,122,136,136,122,123,136,136,1,40,136,2,152,130,173,102,92,50,37,33,32,35,28,112,15,17,93,85,104,115,253,1,118,254,231,93,234,140,140,250,237,97,88,79,85,85,79,88,97,118,84,81,43,38,84,206,44,44,77,64,63,63,64,60,80,72,73,80,80,73,72,80,0,9,0,94,255,237,4,121,5,140,0,3,0,7,0,11,0,15,0,27,0,36,0,40,0,48,0,60,0,46,64,30,28,32,40,49,22,39,41,45,8,16,55,105,16,9,114,10,13,12,8,105,13,12,106,13,7,105,5,13,2,114,0,43,50,43,43,43,18,57,43,43,23,57,48,49,19,39,1,23,5,19,51,3,1,17,51,17,39,53,33,7,1,34,38,53,52,54,51,50,22,21,20,6,39,50,53,52,35,34,6,21,20,55,53,51,21,39,50,53,52,35,34,21,20,23,34,38,53,52,54,51,50,22,21,20,6,186,92,3,162,92,252,195,175,177,176,254,143,156,156,2,33,63,1,37,130,145,145,130,131,145,145,131,100,100,47,52,29,142,72,83,83,82,82,122,136,136,122,123,136,136,1,40,136,2,152,130,164,2,106,253,150,1,67,1,25,254,231,156,139,139,250,236,97,88,79,85,85,79,88,97,118,84,81,43,38,84,206,44,44,77,64,63,63,64,60,80,72,73,80,80,73,72,80,0,0,1,1,196,255,236,2,236,1,20,0,11,0,12,181,0,6,106,0,19,114,0,43,43,48,49,5,34,38,53,52,54,51,50,22,21,20,6,2,88,61,87,87,61,62,86,86,20,87,61,62,86,86,62,61,87,0,1,1,146,254,76,2,202,0,254,0,3,0,10,179,1,0,106,1,0,47,43,48,49,1,19,51,3,1,146,80,232,120,254,76,2,178,253,78,0,0,2,1,196,255,236,2,236,4,56,0,11,0,23,0,21,64,12,12,18,106,12,19,114,6,0,106,6,7,114,0,43,43,43,43,48,49,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,2,88,61,87,87,61,62,86,86,62,61,87,87,61,62,86,86,3,16,87,61,62,86,86,62,61,87,252,220,87,61,62,86,86,62,61,87,0,2,1,146,254,76,2,236,4,56,0,11,0,15,0,19,64,10,14,12,106,14,6,0,106,6,7,114,0,43,43,47,43,48,49,1,34,38,53,52,54,51,50,22,21,20,6,1,19,51,3,2,88,61,87,87,61,62,86,86,254,252,80,232,120,3,16,87,61,62,86,86,62,61,87,251,60,2,178,253,78,0,255,255,0,54,255,236,4,122,1,20,2,39,2,165,254,114,0,0,2,39,2,165,1,142,0,0,2,6,2,165,0,0,0,2,1,196,255,236,2,236,5,150,0,3,0,15,0,21,64,12,10,3,105,4,10,106,4,19,114,1,16,114,0,43,43,43,43,48,49,1,3,51,3,3,34,38,53,52,54,51,50,22,21,20,6,1,246,6,208,10,94,61,87,87,61,62,86,86,1,200,3,206,252,50,254,36,87,61,62,86,86,62,61,87,0,2,1,196,254,142,2,236,4,56,0,3,0,15,0,21,64,12,10,1,105,4,10,106,4,0,105,4,7,114,0,43,43,43,43,48,49,1,19,51,19,3,50,22,21,20,6,35,34,38,53,52,54,1,240,6,192,10,104,62,86,86,62,61,87,87,254,142,3,206,252,50,5,170,86,62,61,87,87,61,62,86,0,3,0,156,255,236,4,22,5,160,0,21,0,29,0,41,0,44,64,28,23,22,7,14,4,17,6,0,11,27,106,11,10,106,36,0,105,30,36,106,22,30,19,114,26,11,3,114,0,43,50,43,50,43,43,43,43,18,23,57,48,49,1,53,52,54,55,54,54,53,52,38,35,55,50,22,21,20,6,7,6,6,21,21,1,39,54,36,51,7,34,6,19,34,38,53,52,54,51,50,22,21,20,6,1,244,82,82,81,81,100,92,2,195,215,111,111,64,64,254,110,138,70,1,3,151,2,94,182,244,61,87,87,61,62,86,86,1,200,96,99,151,52,50,119,69,75,83,190,177,161,111,182,71,42,99,59,82,2,110,143,99,120,190,94,251,104,87,61,62,86,86,62,61,87,0,0,3,0,154,254,132,4,20,4,56,0,21,0,29,0,41,0,42,64,27,27,26,3,18,15,6,6,30,36,10,105,30,36,106,22,30,0,105,30,23,105,30,21,105,30,7,114,0,43,43,43,43,50,43,43,17,23,57,48,49,1,34,38,53,52,54,55,54,54,53,53,51,21,20,6,7,6,6,21,20,22,51,7,55,50,54,55,23,6,4,3,50,22,21,20,6,35,34,38,53,52,54,2,52,195,215,111,111,65,63,196,81,83,81,81,101,91,2,2,94,182,64,138,70,254,253,117,62,86,86,62,61,87,87,254,132,178,160,111,182,71,42,100,58,82,96,99,150,53,50,119,69,75,83,190,190,94,78,143,99,120,5,180,86,62,61,87,87,61,62,86,0,255,255,1,196,2,50,2,236,3,90,2,7,2,165,0,0,2,70,0,1,1,48,1,158,3,128,3,238,0,15,0,10,179,8,0,106,8,0,47,43,48,49,1,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,2,88,82,134,80,80,134,82,82,134,80,80,134,1,158,80,134,82,82,134,80,80,134,82,82,134,80,0,0,5,0,110,1,2,4,62,4,152,0,3,0,7,0,11,0,15,0,19,0,49,64,32,16,8,1,7,15,12,6,2,11,17,10,13,4,4,0,10,9,106,18,19,106,3,5,18,10,4,13,0,105,13,150,114,0,43,43,23,57,43,43,17,51,17,18,23,57,48,49,1,1,55,1,5,39,1,23,7,37,55,5,7,3,51,3,7,39,37,23,3,56,254,230,112,1,80,253,150,166,1,80,112,82,254,50,74,1,184,100,34,216,34,48,52,1,184,74,1,2,1,134,96,254,166,140,140,1,90,96,22,132,204,196,70,1,224,254,32,70,140,196,204,255,255,0,182,255,236,3,250,5,150,0,39,2,170,254,242,0,0,0,7,2,170,1,14,0,0,0,4,0,120,0,0,4,96,5,140,0,3,0,7,0,11,0,15,0,35,64,19,5,4,106,12,13,106,5,12,5,12,8,1,9,16,114,0,8,18,114,0,43,50,43,50,17,57,57,47,47,43,43,48,49,33,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,2,178,120,176,120,253,22,3,232,252,158,120,176,120,254,202,3,232,5,140,250,116,1,104,170,170,254,152,5,140,250,116,3,122,170,170,0,255,255,1,196,255,236,2,236,1,20,2,6,2,165,0,0,0,1,0,100,6,32,4,76,6,208,0,3,0,10,179,0,1,106,0,0,47,43,48,49,19,53,33,21,100,3,232,6,32,176,176,0,0,1,0,104,255,66,4,96,6,74,0,3,0,12,181,1,0,106,1,152,114,0,43,43,48,49,23,1,51,1,104,3,36,212,252,220,190,7,8,248,248,0,0,1,0,104,255,66,4,96,6,74,0,3,0,12,181,1,0,106,1,152,114,0,43,43,48,49,5,1,51,1,3,140,252,220,212,3,36,190,7,8,248,248,0,1,1,10,255,56,3,230,6,84,0,17,0,21,64,12,0,15,106,6,0,105,6,9,106,6,154,114,0,43,43,43,43,48,49,5,32,0,17,16,0,33,51,7,35,34,0,17,16,0,51,51,23,3,182,254,187,254,153,1,103,1,69,48,20,8,237,254,255,1,1,237,8,20,200,1,223,1,181,1,175,1,217,180,254,132,254,168,254,162,254,126,180,0,0,1,0,202,255,56,3,166,6,84,0,17,0,21,64,12,0,1,106,10,0,105,10,9,106,10,154,114,0,43,43,43,43,48,49,23,55,51,50,0,17,16,0,35,35,39,51,32,0,17,16,0,33,202,20,8,237,1,1,254,255,237,8,20,48,1,70,1,102,254,154,254,186,200,180,1,130,1,94,1,88,1,124,180,254,39,254,81,254,75,254,33,0,1,1,0,255,42,3,228,6,90,0,54,0,33,64,19,38,39,10,11,106,10,22,0,48,106,22,0,105,22,29,106,22,154,114,0,43,43,43,43,18,57,43,57,57,48,49,5,34,38,53,52,54,53,52,38,38,35,53,50,62,2,53,52,38,53,52,54,51,50,22,23,7,38,38,35,34,6,21,20,22,21,20,6,7,21,22,22,21,20,6,21,20,22,51,50,54,55,23,6,6,3,58,163,179,42,95,127,48,35,91,87,57,42,179,163,59,78,33,24,35,65,28,71,75,46,138,124,124,138,46,75,71,28,65,35,24,33,78,214,195,175,84,164,88,56,63,25,158,19,37,54,34,92,160,84,169,183,11,9,170,5,5,90,82,87,158,87,99,109,2,34,2,113,95,91,158,83,91,99,6,4,170,9,11,0,0,1,0,206,255,42,3,178,6,90,0,54,0,33,64,19,17,16,45,44,106,45,33,0,7,106,33,0,105,33,26,106,33,154,114,0,43,43,43,43,18,57,43,57,57,48,49,5,34,38,39,55,22,22,51,50,54,53,52,38,53,52,54,55,53,38,38,53,52,54,53,52,38,35,34,6,7,39,54,54,51,50,22,21,20,6,21,20,30,2,51,21,34,6,6,21,20,22,21,20,6,1,120,58,79,33,24,35,65,28,71,75,46,138,124,124,138,46,75,71,28,65,35,24,33,79,58,163,179,42,57,87,92,34,48,127,95,42,179,214,11,9,170,4,6,99,91,83,158,91,95,113,2,34,2,109,99,87,158,87,82,90,5,5,170,9,11,183,169,84,160,92,34,54,37,19,158,25,63,56,88,164,84,175,195,0,0,3,1,116,255,42,3,230,6,98,0,3,0,7,0,11,0,27,64,15,9,8,106,9,1,4,5,106,4,1,0,106,1,153,114,0,43,43,50,43,17,51,43,48,49,5,17,51,17,35,53,33,21,1,53,33,21,1,116,200,20,1,190,254,66,1,190,214,7,56,248,200,190,190,6,122,190,190,0,3,0,202,255,42,3,60,6,98,0,3,0,7,0,11,0,27,64,15,9,8,106,9,10,4,5,106,4,10,0,105,10,153,114,0,43,43,50,43,17,51,43,48,49,5,17,51,17,33,53,33,21,1,53,33,21,2,104,212,253,142,1,178,254,78,1,178,214,7,56,248,200,190,190,6,122,190,190,0,0,1,0,152,0,0,3,252,5,140,0,7,0,22,64,12,1,6,5,2,4,0,3,2,114,0,8,114,0,43,43,18,23,57,48,49,33,1,53,1,33,1,21,1,2,173,253,235,2,21,1,79,253,235,2,21,2,189,18,2,189,253,67,18,253,67,0,1,0,180,0,0,4,24,5,140,0,7,0,22,64,12,1,6,5,2,4,0,3,2,114,0,8,114,0,43,43,18,23,57,48,49,51,1,53,1,33,1,21,1,180,2,21,253,235,1,79,2,21,253,235,2,189,18,2,189,253,67,18,253,67,0,0,1,0,221,0,0,3,221,5,140,0,7,0,22,64,12,1,6,5,2,4,0,3,2,114,0,8,114,0,43,43,18,23,57,48,49,33,1,53,1,51,1,21,1,2,242,253,235,2,21,235,253,235,2,21,2,189,18,2,189,253,67,18,253,67,0,0,1,0,211,0,0,3,211,5,140,0,7,0,22,64,12,2,1,5,6,4,0,3,2,114,0,8,114,0,43,43,18,23,57,48,49,51,1,53,1,51,1,21,1,211,2,21,253,235,235,2,21,253,235,2,189,18,2,189,253,67,18,253,67,255,255,0,100,2,104,4,76,3,34,2,6,3,68,0,0,255,255,0,100,2,104,4,76,3,34,2,6,2,193,0,0,0,1,0,70,2,104,4,106,3,34,0,3,0,12,181,1,0,106,1,147,114,0,43,43,48,49,19,53,33,21,70,4,36,2,104,186,186,0,0,1,0,40,2,104,4,136,3,34,0,3,0,12,181,1,0,106,1,147,114,0,43,43,48,49,19,53,33,21,40,4,96,2,104,186,186,0,255,255,0,40,2,104,4,136,3,34,2,6,2,196,0,0,255,255,0,100,2,104,4,76,3,34,2,6,2,193,0,0,255,255,0,100,2,104,4,76,3,34,2,6,2,198,0,0,0,1,0,100,255,80,4,76,0,0,0,3,0,12,181,1,0,106,1,8,114,0,43,43,48,49,23,53,33,21,100,3,232,176,176,176,255,255,0,100,254,32,4,76,0,0,2,38,2,200,0,0,2,7,2,200,0,0,254,208,255,255,1,116,254,76,3,76,0,254,2,7,2,207,0,0,251,114,255,255,0,150,254,76,4,38,0,254,0,39,2,207,0,218,251,114,0,7,2,207,255,34,251,114,255,255,0,200,2,218,4,88,5,140,0,39,2,206,255,34,0,0,0,7,2,206,0,218,0,0,255,255,0,150,2,218,4,38,5,140,0,39,2,207,0,218,0,0,0,7,2,207,255,34,0,0,0,1,1,166,2,218,3,126,5,140,0,3,0,12,181,1,0,106,1,16,114,0,43,43,48,49,1,1,51,3,1,166,1,54,162,190,2,218,2,178,253,78,0,1,1,116,2,218,3,76,5,140,0,3,0,12,181,1,0,106,1,16,114,0,43,43,48,49,1,19,33,1,1,116,190,1,26,254,202,2,218,2,178,253,78,0,255,255,1,140,2,218,3,100,5,140,0,71,2,207,4,216,0,0,192,0,64,0,0,2,0,76,0,74,4,60,3,216,0,7,0,15,0,38,64,23,12,3,4,106,15,0,7,106,1,6,5,2,14,13,9,10,8,8,3,0,105,11,3,0,47,51,43,50,23,57,43,50,43,50,48,49,37,1,53,1,21,5,21,5,5,1,53,1,21,5,21,5,4,60,254,24,1,232,254,212,1,44,253,248,254,24,1,232,254,212,1,44,74,1,128,142,1,128,230,216,18,216,230,1,128,142,1,128,230,216,18,216,0,2,0,116,0,74,4,100,3,216,0,7,0,15,0,46,64,29,13,12,106,13,5,8,9,106,8,6,7,3,4,15,14,10,11,8,5,0,1,106,5,0,105,5,4,106,5,0,47,43,43,43,18,23,57,51,43,17,51,43,48,49,37,53,37,53,37,53,1,21,1,53,37,53,37,53,1,21,2,124,1,44,254,212,1,232,252,16,1,44,254,212,1,232,74,230,216,18,216,230,254,128,142,254,128,230,216,18,216,230,254,128,142,0,0,1,0,236,0,74,3,166,3,216,0,7,0,28,64,16,5,6,2,1,4,3,0,7,106,3,0,105,3,4,106,3,0,47,43,43,43,18,23,57,48,49,37,1,53,1,21,5,21,5,3,166,253,70,2,186,254,42,1,214,74,1,128,142,1,128,220,226,18,226,0,1,1,10,0,74,3,196,3,216,0,7,0,28,64,16,6,3,2,7,4,5,0,1,106,5,0,105,5,4,106,5,0,47,43,43,43,18,23,57,48,49,37,53,37,53,37,53,1,21,1,10,1,214,254,42,2,186,74,220,226,18,226,220,254,128,142,0,255,255,1,26,3,12,3,150,5,140,0,39,2,214,255,56,0,0,0,7,2,214,0,204,0,0,0,1,1,226,3,12,2,202,5,140,0,3,0,12,181,1,0,106,1,16,114,0,43,43,48,49,1,3,51,3,1,246,20,232,20,3,12,2,128,253,128,0,0,2,252,104,2,104,3,152,3,34,0,3,0,7,0,16,183,0,5,4,106,1,5,147,114,0,43,50,43,50,48,49,19,53,33,21,33,53,33,21,120,3,32,248,208,3,12,2,104,186,186,186,186,0,0,3,247,184,2,104,3,152,3,34,0,3,0,7,0,11,0,27,64,13,1,9,9,5,0,8,8,5,4,106,5,147,114,0,43,43,50,17,51,17,51,17,51,48,49,19,53,33,21,33,53,33,21,33,53,33,21,120,3,32,244,32,3,12,1,74,3,32,2,104,186,186,186,186,186,186,0,2,247,184,0,112,3,192,5,24,0,15,0,19,0,38,64,24,6,15,14,7,4,13,1,0,106,16,1,105,17,16,106,12,13,106,17,12,105,17,147,114,0,43,43,43,43,43,43,17,23,57,48,49,55,53,62,3,55,17,46,3,39,53,1,21,5,53,33,21,6,167,211,122,63,19,20,67,124,209,162,3,186,243,248,10,202,112,240,71,85,44,17,1,1,20,2,14,43,86,73,240,253,234,122,34,188,188,0,2,252,104,254,202,3,12,6,194,0,3,0,7,0,21,64,12,5,4,105,5,149,114,1,0,106,1,147,114,0,43,43,43,43,48,49,1,53,33,21,3,17,51,17,252,104,6,24,60,200,2,104,186,186,252,98,7,248,248,8,0,0,2,252,104,0,112,3,192,5,24,0,15,0,19,0,38,64,24,6,15,14,7,4,13,1,0,106,16,1,105,17,16,106,12,13,106,17,12,105,17,147,114,0,43,43,43,43,43,43,17,23,57,48,49,55,53,62,3,55,17,46,3,39,53,1,21,5,53,33,21,6,167,211,123,63,18,20,67,124,209,162,3,186,248,168,6,26,112,230,74,90,46,17,1,1,20,2,14,43,86,73,240,253,234,122,34,188,188,0,3,247,184,0,112,3,192,5,24,0,7,0,11,0,27,0,52,64,33,7,2,3,18,19,27,26,6,8,5,0,5,24,25,106,4,9,24,105,0,13,12,106,1,8,13,105,9,8,106,9,147,114,0,43,43,43,50,43,50,43,50,43,50,17,18,23,57,48,49,55,53,1,53,1,53,1,21,5,53,33,21,1,53,62,3,55,17,46,3,39,53,1,21,6,2,138,253,118,3,186,243,248,7,88,253,132,167,211,122,63,19,20,67,124,209,162,3,186,112,240,1,92,18,1,90,240,253,234,122,34,188,188,254,10,240,68,84,46,19,1,1,20,2,14,42,87,73,240,253,234,122,0,2,252,104,0,112,3,152,5,24,0,7,0,11,0,36,64,23,7,0,106,8,7,105,1,2,5,6,4,9,8,106,4,3,106,9,4,105,9,147,114,0,43,43,43,43,23,57,43,43,48,49,37,1,53,1,21,1,21,1,1,53,33,21,3,152,252,70,3,186,253,118,2,138,248,208,3,184,112,2,24,122,2,22,240,254,166,18,254,164,1,16,168,168,0,3,247,184,0,112,3,152,5,24,0,3,0,11,0,19,0,48,64,31,7,16,15,106,8,1,16,105,4,19,12,106,11,0,19,105,13,14,18,17,5,6,9,10,8,1,0,106,1,147,114,0,43,43,23,57,43,50,43,50,43,50,43,50,48,49,1,53,33,21,1,1,53,1,21,1,21,1,5,1,53,1,21,1,21,1,247,184,5,52,6,172,252,70,3,186,253,118,2,138,252,204,252,70,3,186,253,118,2,138,2,102,188,188,254,10,2,24,122,2,22,240,254,166,18,254,164,240,2,24,122,2,22,240,254,166,18,254,164,0,0,2,252,104,2,35,3,232,3,209,0,29,0,33,0,35,64,20,6,15,106,21,0,106,6,30,21,21,30,25,105,11,31,30,106,31,147,114,0,43,43,50,43,57,47,18,57,43,43,48,49,1,34,38,39,38,38,35,34,6,21,21,35,53,52,54,51,50,22,23,22,22,51,50,54,53,53,51,21,20,6,37,53,33,21,2,228,74,129,62,57,113,60,55,50,204,138,152,77,138,60,58,99,55,45,40,202,123,248,251,4,36,2,35,62,37,35,61,42,47,27,17,158,142,62,37,35,61,57,62,110,100,173,157,79,186,186,0,0,6,252,120,255,56,3,218,6,84,0,27,0,31,0,35,0,39,0,43,0,47,0,65,64,44,45,39,30,34,43,40,29,35,44,36,10,32,41,32,28,38,37,106,46,47,106,31,33,46,38,4,41,28,105,41,150,114,0,21,106,8,0,105,8,15,106,8,154,114,0,43,43,43,43,43,43,23,57,43,43,17,51,17,18,23,57,48,49,7,34,36,2,17,16,18,36,51,50,22,23,7,38,38,35,32,0,17,16,0,33,50,54,55,23,6,6,1,1,55,1,5,39,1,23,7,37,55,5,7,3,51,3,7,39,37,23,140,242,254,170,180,180,1,86,242,27,54,27,20,17,34,17,254,236,254,214,1,42,1,20,20,39,19,20,29,60,3,67,254,230,112,1,80,253,150,166,1,80,112,82,254,50,74,1,184,100,34,216,34,48,52,1,184,74,200,215,1,153,1,36,1,32,1,148,212,1,4,180,4,1,254,132,254,168,254,162,254,126,2,5,180,5,2,1,202,1,134,96,254,166,140,140,1,90,96,22,132,204,196,70,1,224,254,32,70,140,196,204,0,0,2,252,64,254,202,2,188,6,194,0,53,0,57,0,41,64,25,55,54,106,55,149,114,37,38,11,10,106,11,21,0,47,106,21,0,105,21,28,106,21,154,114,0,43,43,43,43,18,57,43,57,57,43,43,48,49,5,34,38,53,52,54,53,52,38,38,35,53,50,54,54,53,52,38,53,52,54,51,50,22,23,7,38,38,35,34,6,21,20,22,21,20,6,7,21,22,22,21,20,6,21,20,22,51,50,54,55,23,6,6,5,17,51,17,254,222,210,232,2,81,108,41,39,109,82,2,232,210,93,144,33,24,63,115,50,120,126,6,117,105,105,117,6,126,120,50,115,63,24,52,125,2,185,200,214,226,204,69,135,72,56,63,25,158,34,64,46,75,132,69,197,215,11,9,170,5,5,122,110,71,130,71,99,109,2,34,2,113,95,74,130,68,119,131,6,4,170,9,11,96,7,248,248,8,0,0,5,252,67,255,42,3,152,6,90,0,54,0,58,0,62,0,66,0,70,0,62,64,38,66,65,106,57,58,106,45,16,17,44,4,57,66,57,66,57,68,67,68,60,2,114,67,59,8,114,0,7,106,33,0,105,33,26,106,33,154,114,0,43,43,43,43,43,50,43,50,17,18,57,57,47,47,18,23,57,43,43,48,49,5,34,38,39,55,22,22,51,50,54,53,52,38,53,52,54,55,53,38,38,53,52,54,53,52,38,35,34,6,7,39,54,54,51,50,22,21,20,6,21,20,30,2,51,21,34,6,6,21,20,22,21,20,6,19,53,33,21,1,19,51,3,1,53,33,21,1,19,51,3,252,237,58,79,33,24,35,65,28,71,75,46,138,124,124,138,46,75,71,28,65,35,24,33,79,58,163,179,42,57,87,92,34,48,127,95,42,179,125,5,139,252,158,120,176,120,253,46,5,132,254,82,120,176,120,214,11,9,170,4,6,99,91,83,158,91,95,113,2,34,2,109,99,87,158,87,82,90,5,5,170,9,11,183,169,84,160,92,42,64,45,23,98,31,75,68,88,164,84,175,195,2,62,170,170,254,152,5,140,250,116,3,122,170,170,252,134,5,140,250,116,0,0,4,253,108,254,202,2,142,6,194,0,3,0,7,0,11,0,15,0,35,64,21,13,15,106,13,149,114,10,11,106,10,1,7,6,106,7,1,3,105,1,153,114,0,43,43,50,43,17,51,43,43,43,48,49,5,17,51,17,35,53,33,21,1,53,33,21,1,17,51,17,253,108,202,20,2,154,253,102,2,154,1,10,200,200,7,28,248,228,176,176,6,108,176,176,249,38,7,248,248,8,0,0,7,252,63,255,42,3,152,6,98,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,55,64,33,21,22,106,16,26,21,105,26,25,106,19,26,153,114,15,14,106,6,7,106,15,6,15,6,2,11,3,8,114,10,2,2,114,0,43,50,43,50,17,57,57,47,47,43,43,43,50,43,43,50,43,48,49,33,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,1,35,17,51,3,33,53,33,17,33,53,33,1,234,120,176,120,251,194,5,60,252,158,120,176,120,253,118,5,60,251,25,200,200,180,254,66,1,190,254,66,1,190,5,140,250,116,1,104,170,170,254,152,5,140,250,116,3,122,170,170,251,176,7,56,248,200,190,5,188,190,0,2,252,216,2,48,3,152,3,88,0,3,0,15,0,21,64,12,10,4,106,1,10,105,1,0,106,1,147,114,0,43,43,43,43,48,49,3,53,33,21,5,34,38,53,52,54,51,50,22,21,20,6,180,4,76,249,212,61,87,87,61,62,86,86,2,102,186,186,54,87,61,62,86,86,62,61,87,255,255,253,160,255,236,2,96,1,20,0,39,2,165,251,220,0,0,0,7,2,165,255,116,0,0,255,255,249,244,255,236,1,92,1,20,0,39,2,165,248,48,0,0,0,39,2,165,251,80,0,0,0,7,2,165,254,112,0,0,0,4,247,236,1,110,3,152,4,28,0,3,0,7,0,19,0,31,0,35,64,21,26,20,106,14,8,106,26,14,1,4,5,106,1,4,105,1,0,106,1,148,114,0,43,43,43,43,18,57,57,43,43,48,49,1,53,33,21,1,53,33,21,37,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,254,12,5,140,250,116,5,140,244,232,61,87,87,61,62,86,86,2,196,61,87,87,61,62,86,86,3,98,186,186,254,12,186,186,194,87,61,62,86,86,62,61,87,87,61,62,86,86,62,61,87,0,3,248,40,0,214,3,152,4,180,0,7,0,19,0,31,0,47,64,29,14,8,106,26,20,106,14,26,0,4,3,106,2,4,106,7,0,106,1,7,106,6,5,2,1,106,2,151,114,0,43,43,57,57,43,43,43,43,17,57,57,43,43,48,49,37,1,53,1,21,1,21,1,37,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,152,251,142,4,114,252,164,3,92,245,36,61,87,87,61,62,86,86,3,168,61,87,87,61,62,86,86,214,1,138,202,1,138,220,254,246,18,254,246,108,87,61,62,86,86,62,61,87,87,61,62,86,86,62,61,87,255,255,253,120,255,236,3,38,5,160,0,39,2,165,251,180,0,0,0,7,2,172,255,16,0,0,0,3,252,216,1,110,3,152,4,28,0,3,0,7,0,19,0,29,64,17,14,8,106,14,1,4,5,106,1,4,105,1,0,106,1,148,114,0,43,43,43,43,18,57,43,48,49,3,53,33,21,1,53,33,21,37,34,38,53,52,54,51,50,22,21,20,6,100,3,252,252,4,3,252,249,212,61,87,87,61,62,86,86,3,98,186,186,254,12,186,186,194,87,61,62,86,86,62,61,87,255,255,253,160,255,236,2,96,4,56,0,39,2,167,251,220,0,0,0,7,2,167,255,116,0,0,255,255,249,244,255,236,1,92,4,56,0,39,2,167,248,48,0,0,0,39,2,167,251,80,0,0,0,7,2,167,254,112,0,0,0,6,247,236,0,160,3,152,4,236,0,3,0,7,0,19,0,31,0,43,0,55,0,45,64,28,32,14,8,106,38,1,14,105,50,20,26,106,44,4,20,105,4,5,106,1,4,105,1,0,106,1,148,114,0,43,43,43,43,43,50,43,50,43,50,43,50,48,49,1,53,33,21,1,53,33,21,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,254,12,5,140,250,116,5,140,247,234,61,87,87,61,62,86,86,62,61,87,87,61,62,86,86,252,192,61,87,87,61,62,86,86,62,61,87,87,61,62,86,86,3,98,186,186,254,12,186,186,2,86,87,61,62,86,86,62,61,87,252,220,87,61,62,86,86,62,61,87,3,36,87,61,62,86,86,62,61,87,252,220,87,61,62,86,86,62,61,87,0,0,4,252,216,0,160,3,152,4,236,0,3,0,7,0,19,0,31,0,37,64,24,14,8,106,1,14,105,20,26,106,4,20,105,4,5,106,1,4,105,1,0,106,1,148,114,0,43,43,43,43,43,43,43,43,48,49,3,53,33,21,1,53,33,21,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,200,4,96,251,160,4,96,249,212,61,87,87,61,62,86,86,62,61,87,87,61,62,86,86,3,58,186,186,254,12,186,186,2,126,87,61,62,86,86,62,61,87,252,220,87,61,62,86,86,62,61,87,0,0,3,252,216,0,160,3,194,4,236,0,7,0,19,0,31,0,53,64,34,2,3,7,6,20,26,106,0,20,105,1,0,106,7,1,106,6,7,106,14,8,106,5,14,105,4,5,106,6,4,106,6,151,114,0,43,43,43,43,43,43,43,43,43,43,17,18,57,57,48,49,39,53,1,53,1,53,1,21,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,156,3,52,252,204,4,94,249,170,61,87,87,61,62,86,86,62,61,87,87,61,62,86,86,214,220,1,10,18,1,10,220,254,118,202,1,100,87,61,62,86,86,62,61,87,252,220,87,61,62,86,86,62,61,87,0,3,252,224,0,160,3,152,4,236,0,7,0,19,0,31,0,53,64,34,6,5,1,2,14,8,106,3,14,105,4,3,106,2,4,106,20,26,106,0,20,105,7,0,106,1,7,106,2,1,106,2,151,114,0,43,43,43,43,43,43,43,43,43,43,17,18,57,57,48,49,37,1,53,1,21,1,21,1,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,152,251,162,4,94,252,204,3,52,249,220,61,87,87,61,62,86,86,62,61,87,87,61,62,86,86,214,1,138,202,1,138,220,254,246,18,254,246,2,18,87,61,62,86,86,62,61,87,252,220,87,61,62,86,86,62,61,87,255,255,248,210,255,66,3,32,6,74,0,39,2,167,247,14,0,0,0,39,2,181,254,192,0,0,0,7,2,181,251,0,0,0,255,255,253,136,254,76,2,120,4,56,0,39,2,168,251,246,0,0,0,6,2,168,140,0,255,255,253,160,255,236,2,96,5,150,0,39,2,170,251,220,0,0,0,7,2,170,255,116,0,0,255,255,248,200,255,236,2,136,5,150,0,39,2,170,247,4,0,0,0,39,2,170,251,100,0,0,0,6,2,165,156,0,0,3,252,4,255,156,3,252,5,240,0,3,0,7,0,11,0,29,64,18,4,5,106,4,0,105,9,4,105,9,8,106,9,1,105,9,148,114,0,43,43,43,43,43,43,48,49,5,1,51,1,1,53,33,21,1,53,33,21,253,252,3,46,202,252,210,253,62,7,248,248,8,7,248,100,6,84,249,172,1,210,186,186,1,244,186,186,0,0,4,247,84,255,156,3,252,5,240,0,3,0,7,0,11,0,15,0,37,64,24,13,1,105,12,13,106,9,12,105,4,0,105,5,4,106,8,5,105,9,8,106,9,147,114,0,43,43,43,43,43,43,43,43,48,49,5,1,51,1,1,53,33,21,1,53,33,21,1,53,33,21,251,204,3,46,202,252,210,250,190,12,168,243,88,12,168,243,88,12,168,100,6,84,249,172,1,50,186,186,1,154,186,186,1,154,186,186,0,255,255,252,220,255,236,2,136,5,160,0,39,2,172,252,64,0,0,0,6,2,165,156,0,255,255,252,220,255,236,2,136,5,160,0,39,2,172,252,64,0,0,0,6,2,167,156,0,255,255,252,66,255,236,3,108,5,160,0,39,2,172,251,166,0,0,0,7,2,172,255,86,0,0,0,5,252,22,255,236,3,152,5,160,0,3,0,9,0,31,0,39,0,51,0,54,64,36,33,24,17,32,14,27,6,36,46,10,105,40,46,106,40,9,114,37,36,20,106,36,3,114,3,2,106,8,3,105,8,9,106,8,148,114,0,43,43,43,43,43,43,50,43,43,43,17,23,57,48,49,3,53,33,21,1,54,54,55,33,21,1,53,52,54,55,54,54,53,52,38,35,55,50,22,21,20,6,7,6,6,21,21,1,39,54,36,51,7,34,6,19,34,38,53,52,54,51,50,22,21,20,6,98,3,250,252,60,23,34,7,3,132,249,214,82,82,81,81,100,92,2,195,215,111,111,64,64,254,110,138,70,1,3,151,2,94,182,244,61,87,87,61,62,86,86,1,110,186,186,1,244,41,102,43,186,254,102,96,99,151,52,50,119,69,75,83,190,177,161,111,182,71,42,99,59,82,2,110,143,99,120,190,94,251,104,87,61,62,86,86,62,61,87,0,0,6,252,139,255,56,3,218,6,84,0,25,0,29,0,33,0,37,0,41,0,45,0,65,64,44,34,42,33,27,41,38,32,28,43,37,10,39,30,36,35,106,44,45,106,31,29,44,36,4,26,26,39,30,105,39,150,114,0,7,106,20,0,105,20,13,106,20,154,114,0,43,43,43,43,43,43,50,18,23,57,43,43,17,18,23,57,48,49,23,34,38,39,55,22,22,51,32,0,17,16,0,33,34,6,7,39,54,54,51,32,0,17,16,0,1,1,55,1,5,39,1,23,7,37,55,5,7,3,51,3,7,39,37,23,222,29,60,29,20,20,39,19,1,19,1,43,254,213,254,237,17,34,17,20,27,54,27,1,108,1,144,254,112,253,11,254,230,112,1,80,253,150,166,1,80,112,82,254,50,74,1,184,100,34,216,34,48,52,1,184,74,200,2,5,180,5,2,1,130,1,94,1,88,1,124,1,4,180,4,1,254,39,254,81,254,75,254,33,1,202,1,134,96,254,166,140,140,1,90,96,22,132,204,196,70,1,224,254,32,70,140,196,204,255,255,251,252,1,2,4,4,4,152,0,39,2,176,251,142,0,0,0,6,2,176,198,0,255,255,247,76,1,2,4,4,5,196,0,38,2,176,198,0,0,39,2,176,246,222,0,0,0,7,2,176,251,90,1,44,255,255,251,252,0,214,3,238,4,180,0,39,2,176,251,142,0,0,0,6,3,73,158,0,255,255,251,252,255,66,4,38,6,74,0,39,2,176,251,142,0,0,0,6,2,181,198,0,0,5,252,104,255,56,3,210,6,84,0,3,0,7,0,11,0,15,0,33,0,51,64,31,16,31,106,22,16,105,22,24,106,22,154,114,12,13,106,9,8,106,12,9,12,9,4,1,5,2,114,0,4,8,114,0,43,50,43,50,18,57,57,47,47,43,43,43,43,43,43,48,49,33,19,51,3,33,19,51,3,1,53,33,21,1,53,33,21,1,32,0,17,16,0,33,51,7,35,34,0,17,16,0,51,51,23,254,162,120,176,120,253,156,120,176,120,254,202,5,60,250,196,5,60,1,254,254,187,254,153,1,103,1,69,48,20,8,237,254,255,1,1,237,8,20,5,140,250,116,5,140,250,116,1,104,170,170,2,18,170,170,251,190,1,223,1,181,1,175,1,217,180,254,132,254,168,254,162,254,126,180,0,5,252,84,255,42,3,228,6,90,0,54,0,58,0,62,0,66,0,70,0,60,64,37,67,68,106,60,59,106,10,39,38,11,4,60,67,60,67,60,55,64,56,2,114,63,55,8,114,0,48,106,22,0,105,22,29,106,22,154,114,0,43,43,43,43,43,50,43,50,18,57,57,47,47,18,23,57,43,43,48,49,5,34,38,53,52,54,53,52,38,38,35,53,50,62,2,53,52,38,53,52,54,51,50,22,23,7,38,38,35,34,6,21,20,22,21,20,6,7,21,22,22,21,20,6,21,20,22,51,50,54,55,23,6,6,37,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,3,58,163,179,42,95,127,48,35,91,87,57,42,179,163,59,78,33,24,35,65,28,71,75,46,138,124,124,138,46,75,71,28,65,35,24,33,78,249,101,120,176,120,254,202,5,220,252,94,120,176,120,253,22,5,220,214,195,175,92,179,95,56,63,25,98,19,37,54,34,100,175,91,169,183,11,9,170,5,5,90,82,87,158,87,99,109,2,34,2,113,95,91,158,83,91,99,6,4,170,9,11,214,5,140,250,116,1,104,170,170,254,152,5,140,250,116,3,122,170,170,0,0,7,252,104,255,42,3,194,6,98,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,57,64,34,23,16,23,22,106,17,16,105,26,27,106,26,17,153,114,12,13,106,9,8,106,12,9,12,9,4,1,5,2,114,0,4,8,114,0,43,50,43,50,18,57,57,47,47,43,43,43,50,43,43,43,17,51,48,49,33,19,51,3,33,19,51,3,1,53,33,21,1,53,33,21,3,17,51,17,35,53,33,21,1,53,33,21,254,162,120,176,120,253,156,120,176,120,254,202,5,80,250,176,5,80,104,200,20,1,190,254,66,1,190,5,140,250,116,5,140,250,116,1,104,170,170,2,18,170,170,251,176,7,56,248,200,190,190,6,122,190,190,255,255,252,104,0,0,3,2,5,140,0,39,2,178,251,240,0,0,0,7,2,167,0,22,0,180,255,255,252,104,255,236,3,2,5,150,0,39,2,178,251,240,0,0,0,6,2,170,22,0,0,6,252,104,255,236,3,194,5,160,0,30,0,34,0,38,0,42,0,46,0,58,0,66,64,41,26,4,7,23,4,20,53,30,105,47,53,106,47,9,114,14,43,44,106,32,31,106,43,32,43,32,35,40,36,2,114,39,35,8,114,20,10,106,20,3,114,0,43,43,43,50,43,50,18,57,57,47,47,43,43,57,43,43,43,17,23,57,48,49,1,53,52,54,55,54,54,53,52,38,35,34,6,6,21,35,52,62,2,51,50,22,21,20,6,7,6,6,21,21,5,53,33,21,1,19,51,3,33,19,51,3,1,53,33,21,19,34,38,53,52,54,51,50,22,21,20,6,1,160,82,82,81,81,106,96,77,109,58,202,60,115,167,106,200,220,111,111,64,64,250,4,3,232,252,158,120,176,120,1,4,120,176,120,253,22,4,192,222,61,87,87,61,62,86,86,1,200,96,99,151,52,53,123,72,71,77,53,102,73,100,155,107,56,172,156,114,188,72,42,99,59,82,96,170,170,254,152,5,140,250,116,5,140,250,116,3,122,170,170,252,114,87,61,62,86,86,62,61,87,255,255,252,104,0,0,3,152,5,140,0,39,2,178,251,240,0,0,0,7,2,178,255,56,0,0,0,14,247,184,0,0,3,152,5,140,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,35,0,39,0,43,0,47,0,51,0,55,0,119,64,61,54,38,38,22,5,5,20,21,106,55,39,39,23,4,4,20,47,31,31,15,0,0,13,12,106,46,30,30,14,1,1,13,20,13,20,13,16,41,49,49,25,25,33,33,9,9,17,2,114,40,48,48,24,24,32,32,8,8,16,8,114,0,43,50,17,51,17,51,17,51,17,51,43,50,17,51,17,51,17,51,17,51,17,57,57,47,47,17,51,17,51,51,17,51,43,50,17,51,51,17,51,17,51,17,51,51,17,51,43,50,17,51,51,17,51,48,49,1,53,33,21,1,53,33,21,1,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,251,38,5,50,250,206,5,50,249,154,120,176,120,253,22,3,232,252,158,120,176,120,254,202,3,232,2,78,120,176,120,253,22,3,232,252,158,120,176,120,254,202,3,232,2,78,120,176,120,253,22,3,232,252,158,120,176,120,254,202,3,232,1,104,170,170,2,18,170,170,252,134,5,140,250,116,1,104,170,170,254,152,5,140,250,116,3,122,170,170,252,134,5,140,250,116,1,104,170,170,254,152,5,140,250,116,3,122,170,170,252,134,5,140,250,116,1,104,170,170,254,152,5,140,250,116,3,122,170,170,0,0,18,243,8,0,0,3,152,5,140,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,35,0,39,0,43,0,47,0,51,0,55,0,59,0,63,0,67,0,71,0,143,64,73,60,44,44,28,28,4,4,13,12,106,61,45,45,29,29,5,5,13,69,53,53,37,37,1,1,20,21,106,68,52,52,36,36,0,0,20,13,20,13,20,16,57,65,65,41,41,49,49,25,25,33,33,9,9,17,2,114,56,64,64,40,40,48,48,24,24,32,32,8,8,16,8,114,0,43,50,17,51,17,51,17,51,17,51,17,51,17,51,43,50,17,51,17,51,17,51,17,51,17,51,17,51,17,57,57,47,47,17,51,17,51,17,51,17,51,43,50,17,51,17,51,17,51,17,51,17,51,17,51,17,51,43,50,17,51,17,51,17,51,48,49,1,53,33,21,1,53,33,21,1,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,246,118,9,226,246,30,9,226,244,234,120,176,120,253,22,3,232,252,158,120,176,120,254,202,3,232,2,138,120,176,120,253,22,3,232,252,158,120,176,120,254,202,3,232,2,138,120,176,120,253,22,3,232,252,158,120,176,120,254,202,3,232,2,138,120,176,120,253,22,3,232,252,158,120,176,120,254,202,3,232,3,122,170,170,253,238,170,170,254,152,5,140,250,116,1,104,170,170,254,152,5,140,250,116,3,122,170,170,252,134,5,140,250,116,1,104,170,170,254,152,5,140,250,116,3,122,170,170,252,134,5,140,250,116,1,104,170,170,254,152,5,140,250,116,3,122,170,170,252,134,5,140,250,116,1,104,170,170,254,152,5,140,250,116,3,122,170,170,0,0,6,252,104,0,0,3,152,5,140,0,3,0,7,0,11,0,15,0,19,0,23,0,47,64,25,1,20,21,106,0,20,4,13,12,106,5,13,20,13,20,13,16,9,17,2,114,8,16,8,114,0,43,50,43,50,18,57,57,47,47,17,51,43,50,17,51,43,50,48,49,19,53,33,21,1,53,33,21,1,19,51,3,1,53,33,21,1,19,51,3,1,53,33,21,160,2,248,253,8,2,248,251,10,120,176,120,253,22,3,232,252,158,120,176,120,254,202,3,232,3,116,176,176,253,242,176,176,254,154,5,140,250,116,1,104,170,170,254,152,5,140,250,116,3,122,170,170,0,5,252,104,255,80,3,192,5,140,0,3,0,7,0,11,0,15,0,19,0,41,64,23,16,17,106,5,4,106,16,5,16,5,8,1,9,2,114,12,8,0,105,13,8,8,114,0,43,50,43,50,43,50,18,57,57,47,47,43,43,48,49,5,19,51,3,1,53,33,21,1,19,51,3,5,55,33,21,1,53,33,21,254,148,134,176,134,253,36,3,232,252,158,120,176,120,1,54,2,4,234,248,168,3,232,176,6,60,249,196,2,24,170,170,254,152,5,140,250,116,176,176,176,4,42,170,170,0,6,247,184,255,80,3,212,6,84,0,19,0,23,0,27,0,31,0,35,0,39,0,59,64,34,32,33,106,21,20,106,32,21,32,21,24,29,25,2,114,18,1,2,37,37,28,0,24,36,105,24,8,114,9,11,106,9,154,114,0,43,43,43,43,50,50,51,17,51,57,57,43,50,18,57,57,47,47,43,43,48,49,5,37,53,34,38,2,53,16,0,33,51,7,35,34,0,17,16,0,51,51,1,53,33,21,1,19,51,3,23,19,51,3,1,53,33,21,1,53,33,23,3,206,254,150,86,168,110,1,103,1,69,48,20,8,237,254,255,1,1,237,8,243,248,3,232,252,158,120,176,120,246,134,176,134,253,36,3,232,254,132,8,192,234,176,130,66,163,1,55,222,1,175,1,217,180,254,132,254,168,254,157,254,121,1,134,170,170,254,152,5,140,250,116,176,6,60,249,196,4,42,170,170,251,214,176,176,0,255,255,252,48,255,66,4,4,6,74,0,39,2,181,251,200,0,0,0,6,2,176,198,0,0,3,252,48,255,66,3,154,6,74,0,3,0,7,0,11,0,29,64,18,9,11,106,9,152,114,3,2,106,6,3,105,6,7,106,6,148,114,0,43,43,43,43,43,43,48,49,1,55,33,21,1,55,33,21,1,1,51,1,254,204,90,4,116,252,24,90,3,142,248,150,3,36,212,252,220,1,110,186,186,1,244,186,186,251,224,7,8,248,248,0,5,247,128,255,66,3,152,6,74,0,3,0,7,0,11,0,15,0,19,0,37,64,22,17,19,106,17,152,114,7,14,15,106,2,11,10,106,3,14,11,105,6,14,148,114,0,43,50,43,50,43,50,43,50,43,43,48,49,1,55,33,21,1,55,33,21,19,53,33,21,1,53,33,21,1,1,51,1,250,28,90,4,116,252,24,90,3,142,158,4,16,251,240,4,16,243,232,3,36,212,252,220,1,110,186,186,1,244,186,186,254,12,186,186,1,244,186,186,251,224,7,8,248,248,0,0,2,252,48,255,66,3,238,6,74,0,7,0,11,0,45,64,28,2,3,7,6,9,11,106,9,152,114,1,0,106,7,1,106,6,7,106,4,5,106,6,4,105,6,151,114,0,43,43,43,43,43,43,43,43,17,18,57,57,48,49,55,53,1,53,1,53,1,21,1,1,51,1,48,2,188,252,50,4,208,248,66,3,36,212,252,220,214,220,1,10,18,1,128,215,254,5,202,252,226,7,8,248,248,255,255,252,98,255,66,3,204,6,74,0,39,2,181,251,250,0,0,0,7,2,181,255,108,0,0,255,255,247,218,255,66,3,172,6,74,0,39,2,181,255,76,0,0,0,39,2,181,247,114,0,0,0,7,2,181,251,110,0,0,255,255,252,98,255,66,3,204,6,74,0,39,2,182,251,250,0,0,0,7,2,182,255,108,0,0,0,2,247,184,255,80,3,152,6,224,0,3,0,7,0,19,64,10,5,149,114,7,2,3,106,2,8,114,0,43,43,57,43,48,49,5,53,33,21,37,17,51,17,247,184,11,224,249,172,200,176,176,176,56,7,88,248,168,0,1,252,104,255,80,3,152,0,0,0,3,0,12,181,1,0,106,1,8,114,0,43,43,48,49,5,53,33,21,252,104,7,48,176,176,176,0,255,255,1,196,3,16,2,236,4,56,2,7,2,165,0,0,3,36,255,255,1,146,254,76,2,236,4,56,2,6,2,168,0,0,0,5,0,160,254,192,4,110,6,204,0,3,0,21,0,25,0,29,0,47,0,48,64,28,26,27,14,30,4,13,31,105,13,13,22,40,23,39,106,1,23,2,114,22,5,106,4,0,96,22,8,114,0,43,26,206,51,43,43,206,43,51,18,57,47,43,23,57,48,49,1,17,51,17,1,53,33,50,54,53,52,38,35,33,39,33,50,22,21,20,6,35,33,17,51,17,3,53,33,21,37,53,51,50,54,53,52,38,35,35,39,33,50,22,21,20,6,35,2,2,138,254,206,1,44,132,146,152,140,254,230,24,1,100,216,236,224,206,253,224,200,82,1,160,254,164,240,113,125,131,121,222,24,1,0,216,236,224,206,254,192,8,12,247,244,1,64,190,121,109,112,123,91,186,170,186,204,5,140,250,116,2,186,98,98,56,91,101,94,92,98,190,187,173,147,159,0,2,0,96,254,192,4,125,6,204,0,3,0,25,0,33,64,18,12,13,4,9,16,105,1,9,3,114,4,21,105,0,96,4,9,114,0,43,26,205,43,43,205,43,18,57,57,48,49,1,17,51,17,3,32,17,16,0,33,50,22,23,7,38,38,35,34,2,17,16,33,50,55,23,6,2,122,138,14,253,106,1,78,1,48,147,218,50,148,45,139,81,193,233,1,226,145,141,46,174,254,192,8,12,247,244,1,44,2,220,1,91,1,125,93,86,147,68,74,254,234,255,0,253,210,60,176,68,0,2,0,136,254,178,4,73,5,114,0,3,0,29,0,27,64,15,10,17,105,1,10,7,114,4,23,105,3,96,4,11,114,0,43,26,205,43,43,205,43,48,49,1,17,51,17,3,32,0,17,16,0,33,50,22,23,7,38,38,35,34,6,21,20,22,51,50,54,55,23,6,6,2,82,138,50,254,251,254,227,1,23,1,3,155,221,47,163,45,140,83,147,163,182,168,80,157,75,24,87,184,254,178,6,192,249,64,1,58,1,29,1,11,1,4,1,32,115,105,123,73,80,181,167,181,191,14,12,186,18,12,0,3,0,96,254,182,4,125,6,180,0,3,0,7,0,29,0,51,64,31,16,17,8,3,13,7,105,2,13,6,105,13,20,106,13,3,114,5,8,1,105,4,8,0,105,8,25,106,8,9,114,0,43,43,43,50,43,50,43,43,43,50,43,50,18,57,57,48,49,1,39,1,23,1,39,1,23,19,32,17,16,0,33,50,22,23,7,38,38,35,34,2,17,16,33,50,55,23,6,2,161,136,1,100,136,253,132,136,1,100,136,9,253,106,1,78,1,48,147,218,50,148,45,139,81,193,233,1,226,145,141,46,174,254,182,24,7,230,24,248,26,24,7,230,24,249,80,2,220,1,91,1,125,93,86,147,68,74,254,234,255,0,253,210,60,176,68,0,0,6,0,72,0,131,4,104,4,235,0,15,0,19,0,23,0,35,0,39,0,43,0,57,64,36,43,37,8,42,105,41,39,40,26,4,8,30,106,19,21,18,22,4,0,24,106,23,17,0,20,105,0,16,105,8,0,105,8,38,105,8,0,47,43,43,43,43,57,57,43,23,57,43,23,57,43,57,57,48,49,1,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,5,39,55,23,5,3,55,23,37,50,54,53,52,38,35,34,6,21,20,22,3,39,55,23,5,39,55,23,2,91,128,191,105,105,191,128,128,191,105,105,191,253,225,116,197,143,2,88,228,128,216,253,243,92,112,112,92,92,112,112,239,200,127,220,1,254,143,215,127,1,44,100,180,120,121,179,100,100,179,121,120,180,100,169,132,207,86,253,1,3,101,228,227,115,95,95,115,115,95,95,115,1,180,209,124,251,82,88,245,124,0,0,2,0,129,254,192,4,37,6,204,0,3,0,43,0,42,64,27,34,21,37,38,18,17,14,41,28,27,10,4,24,31,105,1,24,3,114,4,11,105,3,96,4,9,114,0,43,26,205,43,43,205,43,18,23,57,48,49,1,17,51,17,3,34,38,39,55,22,22,51,50,54,53,52,38,39,39,38,38,53,52,54,51,50,22,23,7,38,38,35,34,6,21,20,22,23,23,22,22,21,20,6,2,32,138,131,121,211,90,26,110,205,97,140,136,67,63,246,145,155,224,205,143,220,102,140,88,153,83,103,113,74,72,208,158,164,251,254,192,8,12,247,244,1,44,39,39,202,47,49,98,100,66,92,28,112,66,186,138,186,204,84,95,142,72,65,99,97,69,87,34,98,74,186,146,193,193,0,0,4,0,96,254,182,4,114,5,220,0,3,0,7,0,33,0,38,0,57,64,37,17,19,29,30,35,5,8,14,2,3,106,38,2,105,38,11,114,4,5,106,4,14,36,0,114,14,21,106,14,7,114,8,26,106,8,11,114,0,43,43,43,43,43,18,57,43,43,43,43,17,18,23,57,48,49,19,53,33,21,1,53,33,21,1,34,2,17,16,18,51,50,22,23,51,3,16,33,34,6,21,16,51,32,53,53,19,35,6,6,55,39,17,51,17,166,3,98,253,198,2,164,253,148,201,221,222,202,128,139,13,82,62,254,242,117,127,246,1,12,72,92,10,152,204,22,212,254,182,176,176,6,12,174,174,251,42,1,23,1,5,1,11,1,37,105,107,254,240,1,48,198,182,254,152,180,116,254,220,91,93,10,208,5,22,250,36,0,3,0,79,255,236,4,125,5,160,0,21,0,25,0,29,0,38,64,24,26,27,106,23,22,106,23,26,9,8,4,0,5,12,106,5,3,114,0,17,106,0,11,114,0,43,43,43,43,18,23,57,43,43,48,49,5,32,17,16,0,33,50,22,23,7,38,38,35,34,2,17,16,33,50,55,23,6,1,53,33,21,1,53,33,21,3,10,253,186,1,30,1,6,144,212,49,168,40,123,72,153,183,1,146,136,130,46,166,252,145,3,50,252,206,3,50,20,2,220,1,91,1,125,115,104,127,77,85,254,234,255,0,253,210,60,176,68,1,255,138,138,1,34,138,138,0,5,0,62,0,0,4,55,5,159,0,21,0,25,0,29,0,33,0,37,0,53,64,32,32,33,25,36,37,106,28,25,36,105,29,25,24,106,25,8,114,9,10,6,0,19,105,6,0,105,6,13,106,6,3,114,0,43,43,43,43,18,57,57,43,43,51,43,50,43,18,57,57,48,49,1,34,38,53,52,54,51,50,22,23,7,38,38,35,34,6,21,20,22,51,51,21,3,53,33,21,33,17,51,17,3,53,33,21,1,53,33,21,1,252,213,233,230,208,116,140,57,133,29,93,56,105,115,131,119,96,109,2,48,253,208,185,185,1,204,254,52,2,48,2,43,228,208,214,234,74,66,143,44,49,135,123,117,129,190,253,213,186,186,3,112,252,144,1,92,186,186,1,90,186,186,0,3,0,78,254,35,4,110,5,160,0,12,0,25,0,29,0,37,64,21,28,29,106,12,20,13,28,28,3,13,14,106,13,15,114,3,9,106,3,3,114,0,43,43,43,43,18,57,47,18,57,57,43,48,49,1,17,16,33,50,23,7,38,38,35,32,17,17,1,39,55,54,54,53,17,51,17,20,6,6,7,3,53,33,21,1,156,1,246,114,106,22,63,96,45,254,228,253,232,10,108,118,108,212,96,202,160,88,3,212,1,104,2,18,2,38,20,184,8,6,254,162,253,228,252,187,188,15,17,156,163,1,66,254,222,189,234,120,19,4,8,174,174,0,0,4,0,30,0,0,4,76,5,140,0,3,0,7,0,11,0,15,0,33,64,18,11,10,106,2,3,11,11,7,14,15,106,6,14,2,114,7,8,114,0,43,43,50,43,18,57,47,57,57,43,48,49,55,53,33,21,5,17,51,17,3,53,33,21,1,53,33,21,30,2,136,253,250,200,200,2,248,253,8,3,172,231,138,138,231,5,140,250,116,2,44,190,190,2,162,190,190,0,4,0,96,254,192,4,126,6,204,0,7,0,33,0,37,0,41,0,49,64,27,39,38,106,35,17,18,14,39,39,8,14,21,105,1,14,3,114,31,37,8,27,105,0,96,8,9,114,0,43,26,205,43,57,57,43,205,43,18,57,47,18,57,57,51,43,48,49,1,17,51,17,21,17,21,17,3,32,0,17,16,0,33,50,22,23,7,38,38,35,34,2,21,16,18,51,50,54,55,23,6,6,55,17,51,17,1,53,33,21,2,112,138,30,254,194,254,194,1,74,1,42,149,224,53,149,46,139,80,202,224,224,222,95,145,46,78,42,211,63,190,254,32,1,218,254,192,8,12,251,205,62,254,2,78,254,177,1,44,1,110,1,110,1,91,1,125,93,85,148,68,74,254,233,255,254,233,254,233,37,13,174,13,47,60,2,158,253,98,1,224,190,190,0,5,0,70,255,236,4,106,5,160,0,19,0,40,0,44,0,48,0,52,0,59,64,35,47,46,19,3,18,49,50,106,28,48,27,3,26,42,41,106,10,9,49,42,49,42,13,20,34,106,20,9,114,13,6,106,13,3,114,0,43,43,43,43,18,57,57,47,47,57,57,43,50,23,57,43,50,23,57,48,49,1,54,54,53,52,38,35,34,6,7,39,54,36,51,50,22,21,20,7,21,1,34,38,53,52,54,55,53,23,6,6,21,20,22,51,50,54,55,23,6,6,1,53,33,21,37,1,51,1,1,53,33,21,2,181,63,63,97,89,82,186,86,140,100,1,8,141,185,204,149,254,237,222,244,79,79,151,48,47,134,122,95,225,112,26,94,242,253,103,4,36,252,216,1,129,126,254,127,254,134,4,36,3,72,47,110,63,94,102,72,65,142,86,93,141,129,124,97,48,252,103,139,127,55,106,34,84,45,34,73,41,80,88,50,46,202,37,41,1,225,148,148,54,1,74,254,182,1,10,148,148,0,5,0,0,0,0,4,176,5,140,0,3,0,7,0,19,0,23,0,27,0,39,64,20,1,5,9,8,106,26,21,25,9,5,5,20,14,21,2,114,24,20,8,114,0,43,50,43,50,18,57,47,57,57,18,57,43,17,51,48,49,1,53,33,21,33,53,33,21,7,55,50,54,54,18,53,51,20,2,2,4,1,17,51,17,33,1,55,1,2,188,1,244,251,80,1,41,11,18,154,224,145,71,206,110,210,254,208,254,192,200,2,58,254,152,180,1,166,2,89,138,138,138,138,149,198,129,219,1,19,147,189,254,164,254,239,158,254,60,5,140,250,116,2,180,102,252,230,0,4,0,76,0,0,4,100,6,32,0,23,0,27,0,31,0,35,0,43,64,23,0,23,1,24,25,106,31,32,12,12,7,24,8,114,30,33,7,7,16,106,7,3,114,0,43,43,16,206,50,43,17,57,47,57,57,43,50,50,57,48,49,37,53,38,2,53,16,0,33,50,0,17,21,35,53,52,38,35,34,2,21,20,22,22,51,5,53,33,21,1,17,51,17,51,17,51,17,1,124,137,167,1,27,1,0,243,1,10,200,161,148,162,177,120,218,146,253,94,3,252,253,96,108,122,108,143,69,31,1,16,235,1,73,1,105,254,219,254,245,172,172,189,207,254,237,251,170,254,140,186,186,186,2,196,3,92,252,164,3,92,252,164,0,4,0,109,0,0,4,91,5,160,0,23,0,27,0,31,0,35,0,51,64,29,22,1,27,26,106,32,33,106,29,28,106,11,12,8,32,29,32,29,8,0,27,8,114,8,15,106,8,3,114,0,43,43,43,50,17,57,57,47,47,18,57,57,43,43,43,50,50,48,49,51,53,54,54,53,17,52,54,51,50,22,23,7,38,38,35,34,6,21,17,20,6,7,23,35,53,33,21,1,53,33,21,1,53,33,21,132,81,79,222,196,144,212,49,168,42,128,75,87,109,80,82,100,252,3,136,252,37,3,20,252,236,3,20,186,116,210,115,1,153,194,210,115,104,127,74,80,109,104,254,104,115,212,114,186,186,186,1,215,138,138,1,4,138,138,0,3,0,120,255,236,4,100,5,140,0,16,0,20,0,24,0,43,64,24,23,21,22,106,24,21,20,18,17,106,19,18,21,18,0,4,2,114,0,10,106,0,9,114,0,43,43,43,18,57,57,17,51,43,50,17,51,43,50,48,49,5,34,38,53,17,51,17,20,22,22,51,50,54,55,23,6,6,1,53,37,21,37,53,37,21,2,176,195,173,200,32,94,92,68,151,83,84,109,206,253,79,3,110,252,146,3,110,20,200,220,3,252,252,14,84,106,50,54,54,166,70,62,1,225,148,150,148,180,148,150,148,0,2,0,76,0,0,4,100,5,140,0,13,0,17,0,25,64,13,3,10,105,3,14,15,2,114,13,7,14,8,114,0,43,50,50,43,18,57,43,48,49,51,17,16,33,32,17,17,35,17,16,33,32,17,17,51,17,51,17,76,2,12,2,12,210,254,198,254,198,245,138,2,28,2,88,253,168,253,228,2,28,1,160,254,96,253,228,5,140,250,116,0,0,4,0,0,0,0,4,176,5,140,0,3,0,11,0,15,0,19,0,43,64,22,17,8,8,13,1,0,106,6,13,10,1,1,19,13,2,114,19,4,4,12,8,114,0,43,50,17,51,43,18,57,47,57,18,57,43,17,51,17,51,48,49,17,53,33,21,1,1,35,17,51,1,51,17,33,17,51,17,33,17,51,17,4,176,254,112,254,72,92,132,1,184,50,253,26,192,2,8,192,2,129,138,138,253,127,4,56,1,84,251,200,254,172,5,140,250,116,5,140,250,116,0,3,0,0,0,0,4,176,5,140,0,3,0,21,0,25,0,37,64,20,5,4,106,0,5,1,5,1,5,22,14,23,13,106,23,2,114,22,8,114,0,43,43,43,51,18,57,57,47,47,18,57,43,48,49,17,53,33,21,1,53,51,50,54,53,52,38,35,35,53,51,32,0,21,20,0,33,1,17,51,17,4,176,252,160,242,158,174,174,158,238,238,1,3,1,27,254,229,254,253,254,94,200,3,83,138,138,254,101,190,158,142,143,157,190,254,255,233,234,255,0,254,72,5,140,250,116,0,0,4,0,0,0,0,4,176,5,140,0,3,0,7,0,25,0,29,0,38,64,22,9,8,106,4,5,0,1,4,27,9,9,26,19,27,17,106,27,2,114,26,8,114,0,43,43,43,51,18,57,47,18,23,57,43,48,49,17,53,33,21,5,53,33,21,1,53,51,50,54,53,52,38,35,35,53,51,32,0,21,20,0,33,1,17,51,17,4,176,251,80,4,176,252,160,242,158,174,174,158,238,238,1,3,1,27,254,229,254,253,254,94,200,3,213,138,138,245,138,138,254,216,190,158,142,143,157,190,254,255,233,234,255,0,254,72,5,140,250,116,0,0,4,0,0,0,0,4,96,5,140,0,3,0,7,0,25,0,29,0,43,64,23,4,9,8,106,5,9,0,1,9,1,9,1,26,18,27,17,106,27,2,114,26,8,114,0,43,43,43,51,18,57,57,47,47,17,57,17,51,43,50,48,49,53,53,33,21,1,53,33,21,35,53,51,50,54,53,52,38,35,35,53,51,32,0,21,20,0,33,1,17,51,17,3,20,252,236,1,181,101,242,158,174,174,158,238,238,1,3,1,27,254,229,254,253,254,94,200,161,138,138,1,23,190,190,190,158,142,143,157,190,254,255,233,234,255,0,254,72,5,140,250,116,0,0,4,0,80,255,236,4,150,5,140,0,34,0,38,0,42,0,60,0,60,64,38,36,44,43,106,44,44,39,53,40,52,106,40,2,114,35,39,8,114,9,32,12,29,15,26,6,0,18,23,106,18,7,114,0,6,106,0,11,114,0,43,43,43,43,18,23,57,43,50,43,43,51,18,57,47,43,57,48,49,5,34,39,55,22,22,51,50,54,53,52,38,39,38,38,53,52,54,51,50,23,7,38,35,34,6,21,20,22,23,22,22,21,20,6,37,3,51,19,33,17,51,17,3,53,51,50,54,53,52,38,35,35,53,51,50,22,21,20,6,35,3,110,117,85,24,65,88,25,48,48,68,68,70,76,131,133,93,77,22,68,36,54,54,70,64,74,74,147,253,178,138,175,158,253,216,185,14,57,80,82,82,80,77,77,161,171,171,161,20,20,196,13,13,46,46,33,107,75,77,154,82,146,144,20,184,14,50,50,35,102,74,85,151,67,148,148,20,2,156,253,100,5,140,250,116,2,28,174,135,121,132,144,174,224,206,214,236,0,4,0,164,0,0,4,76,5,140,0,17,0,21,0,25,0,29,0,44,64,24,10,28,16,11,9,27,29,106,19,1,0,106,23,22,27,1,1,21,27,2,114,21,8,114,0,43,43,18,57,47,18,57,57,43,57,43,50,50,63,57,48,49,19,53,33,50,54,53,52,38,35,33,37,21,22,22,21,20,6,35,1,1,51,1,1,53,33,21,1,53,33,21,164,1,108,119,133,133,119,254,148,2,142,82,90,241,221,1,18,254,154,220,1,122,252,146,3,168,252,88,3,160,2,28,190,126,114,125,135,38,58,15,135,110,196,214,253,228,2,156,253,100,3,143,138,138,1,63,190,190,0,6,0,80,0,0,4,96,4,36,0,3,0,7,0,11,0,15,0,19,0,23,0,34,64,18,10,19,14,23,4,2,15,11,0,4,8,114,22,17,6,2,6,114,0,43,50,50,50,43,50,50,50,17,23,57,48,49,33,17,51,17,33,17,51,17,51,53,33,21,33,17,51,17,19,17,51,17,1,53,33,21,3,162,190,251,240,190,109,2,229,253,27,160,122,160,253,27,2,229,4,36,251,220,4,36,251,220,170,170,3,12,252,244,1,24,3,12,252,244,2,98,170,170,0,3,0,109,0,0,4,91,5,160,0,23,0,27,0,31,0,45,64,25,1,22,22,27,26,106,30,31,106,11,12,8,30,30,8,23,27,8,114,8,15,106,8,3,114,0,43,43,43,50,17,57,47,18,57,57,43,43,50,17,51,48,49,51,53,54,54,53,17,52,54,51,50,22,23,7,38,38,35,34,6,21,17,20,6,7,21,35,53,33,21,1,53,33,21,132,81,79,222,196,144,212,49,168,42,128,75,87,109,80,82,152,3,136,252,37,3,20,186,116,210,115,1,153,194,210,115,104,127,74,80,109,104,254,104,115,212,114,186,186,186,2,69,138,138,0,0,3,0,80,0,0,4,96,5,140,0,3,0,7,0,11,0,27,64,16,5,4,106,1,8,5,105,9,8,106,9,2,114,0,8,114,0,43,43,43,43,50,43,48,49,33,17,51,17,1,53,33,21,1,53,33,21,1,244,200,253,148,4,16,251,240,4,16,4,36,251,220,3,102,190,190,1,104,190,190,0,4,0,80,0,0,4,96,5,140,0,3,0,7,0,11,0,15,0,32,64,20,4,5,7,6,0,1,3,2,8,8,13,12,106,9,13,2,114,8,8,114,0,43,43,50,43,18,23,57,48,49,19,53,37,21,1,53,37,21,1,17,51,17,1,53,33,21,161,3,110,252,146,3,110,253,229,200,253,148,4,16,2,159,148,150,148,254,32,148,150,148,254,21,5,140,250,116,4,206,190,190,0,3,0,0,0,0,4,176,5,140,0,3,0,13,0,23,0,51,64,25,10,17,17,9,2,3,106,12,9,19,7,2,4,9,2,9,2,21,4,21,5,4,14,4,12,0,63,51,63,51,17,18,57,57,47,47,17,18,57,57,17,57,43,17,51,17,51,48,49,17,53,33,21,1,3,51,19,51,19,51,7,35,3,51,3,35,39,51,19,51,19,51,3,4,176,252,4,160,210,120,20,131,200,67,40,105,222,105,40,65,200,129,20,120,210,160,2,69,138,138,253,187,5,140,251,20,3,132,198,252,162,3,94,198,252,124,4,236,250,116,0,4,0,25,0,0,4,151,5,140,0,3,0,7,0,15,0,19,0,27,64,16,4,5,8,0,1,17,11,7,9,16,8,114,13,9,2,114,0,43,50,43,17,23,57,48,49,19,53,33,21,1,53,33,21,1,1,51,1,51,1,51,1,3,17,51,17,162,3,110,252,146,3,110,253,243,254,22,220,1,90,18,1,90,220,254,22,185,200,1,245,138,138,254,202,138,138,1,27,3,178,253,58,2,198,252,78,254,38,2,188,253,68,0,255,255,1,48,1,158,3,128,3,238,2,6,2,175,0,0,255,255,0,106,255,66,4,98,6,74,0,6,2,181,2,0,0,3,0,100,0,226,4,76,4,168,0,3,0,7,0,11,0,18,64,9,5,8,9,0,4,1,4,105,1,0,47,43,23,57,48,49,19,53,33,21,1,53,33,21,1,53,33,21,100,3,232,252,24,3,232,252,24,3,232,3,238,186,186,252,244,186,186,1,134,186,186,0,255,255,255,150,1,168,5,26,2,124,2,6,4,56,0,0,0,1,0,68,254,35,2,102,7,16,0,12,0,15,183,0,6,105,0,1,106,0,15,0,63,43,43,48,49,19,39,55,54,54,53,17,51,17,20,6,6,7,78,10,108,118,108,212,96,202,160,254,35,188,15,17,156,163,6,210,249,78,189,234,120,19,0,1,1,146,253,18,4,100,5,160,0,12,0,15,183,3,9,106,3,0,105,3,3,0,63,43,43,48,49,1,17,16,33,50,23,7,38,38,35,32,17,17,1,146,1,246,114,106,22,63,96,45,254,228,253,18,6,104,2,38,20,184,8,6,254,162,249,142,0,2,0,100,1,94,4,76,3,135,0,3,0,7,0,16,183,6,1,3,106,1,7,105,1,0,47,43,43,57,48,49,19,53,33,21,1,17,51,17,100,3,232,252,24,192,2,205,186,186,254,145,1,211,254,45,0,5,0,100,0,0,4,76,5,140,0,3,0,7,0,11,0,15,0,19,0,26,64,16,8,9,12,13,16,17,4,5,8,1,3,8,114,1,2,114,0,43,43,17,23,57,48,49,51,1,51,1,3,53,33,21,1,53,33,21,1,53,33,21,1,53,33,21,142,2,202,202,253,54,244,3,232,252,24,3,232,252,24,3,232,252,24,3,232,5,140,250,116,4,72,166,166,252,94,166,166,1,54,166,166,1,54,166,166,0,0,2,0,100,0,190,4,76,4,204,0,3,0,7,0,21,64,12,4,0,105,5,4,106,5,1,105,5,147,114,0,43,43,43,43,48,49,37,17,51,17,1,53,33,21,1,248,192,253,172,3,232,190,4,14,251,242,1,171,186,186,0,0,1,0,100,2,104,4,76,3,34,0,3,0,12,181,1,0,106,1,147,114,0,43,43,48,49,19,53,33,21,100,3,232,2,104,186,186,0,0,2,0,121,0,188,4,55,4,164,0,3,0,7,0,22,64,11,5,3,7,1,4,4,2,0,105,6,2,0,47,51,43,50,23,57,48,49,55,1,39,1,5,55,1,7,249,3,62,128,252,194,3,62,128,252,194,128,188,3,109,123,252,145,121,121,3,111,123,0,0,3,0,100,0,151,4,76,4,241,0,3,0,15,0,27,0,29,64,18,16,22,106,1,16,105,10,4,106,0,10,105,1,0,106,1,147,114,0,43,43,43,43,43,43,48,49,19,53,33,21,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,100,3,232,254,12,58,83,83,58,59,82,82,59,58,83,83,58,59,82,83,2,104,186,186,254,47,82,58,59,82,82,59,58,82,3,65,83,58,58,82,82,58,58,83,0,0,2,0,100,1,110,4,76,4,28,0,3,0,7,0,21,64,12,4,5,106,1,4,105,1,0,106,1,148,114,0,43,43,43,43,48,49,19,53,33,21,1,53,33,21,100,3,232,252,24,3,232,3,98,186,186,254,12,186,186,0,3,0,100,0,0,4,76,5,140,0,3,0,7,0,11,0,29,64,18,4,5,106,9,4,105,9,8,106,9,148,114,3,8,114,1,2,114,0,43,43,43,43,43,43,48,49,51,1,51,1,3,53,33,21,1,53,33,21,142,2,202,202,253,54,244,3,232,252,24,3,232,5,140,250,116,1,110,186,186,1,244,186,186,0,1,0,146,0,214,4,80,4,180,0,7,0,37,64,22,3,2,6,7,1,0,106,7,1,106,6,7,106,4,5,106,6,4,106,6,151,114,0,43,43,43,43,43,43,17,18,57,57,48,49,55,53,1,53,1,53,1,21,146,2,188,253,68,3,190,214,220,1,10,18,1,10,220,254,118,202,0,0,1,0,96,0,214,4,30,4,180,0,7,0,33,64,20,4,3,106,2,4,106,7,0,106,1,7,106,5,6,2,1,106,2,151,114,0,43,43,57,57,43,43,43,43,48,49,37,1,53,1,21,1,21,1,4,30,252,66,3,190,253,28,2,228,214,1,138,202,1,138,220,254,246,18,254,246,0,0,2,0,126,0,103,4,60,4,180,0,7,0,11,0,40,64,22,9,8,106,0,9,105,1,0,106,7,1,106,6,7,106,4,5,106,6,4,106,6,185,255,255,0,114,0,43,43,43,43,43,43,43,43,48,49,19,53,37,53,37,53,1,21,1,53,33,21,126,2,228,253,28,3,190,252,67,3,185,1,58,220,216,18,216,220,254,168,202,253,213,186,186,0,0,2,0,116,0,103,4,50,4,180,0,7,0,11,0,39,64,24,4,3,106,2,4,106,10,11,106,0,10,105,7,0,106,1,7,106,5,6,2,1,106,2,0,47,43,57,57,43,43,43,43,43,43,48,49,1,1,53,1,21,5,21,5,1,53,33,21,4,50,252,66,3,190,253,28,2,228,252,70,3,185,1,58,1,88,202,1,88,220,216,18,216,254,81,186,186,0,3,0,100,0,186,4,76,4,200,0,3,0,7,0,11,0,25,64,13,0,8,9,106,4,5,106,4,4,1,8,105,1,0,47,43,57,47,43,43,57,48,49,37,17,51,17,1,53,33,21,1,53,33,21,1,248,192,253,172,3,232,252,24,3,232,246,3,210,252,46,1,181,186,186,254,15,186,186,0,255,255,0,100,0,196,4,76,4,196,2,39,3,79,0,0,1,34,2,7,3,79,0,0,254,222,0,1,0,100,1,230,4,76,3,162,0,29,0,23,64,12,10,19,106,25,4,106,10,25,14,29,105,14,0,47,43,57,57,43,43,48,49,19,53,52,54,51,50,22,23,22,22,51,50,54,53,53,51,21,20,6,35,34,38,39,38,38,35,34,6,21,21,100,128,142,73,129,58,49,87,47,45,40,202,114,126,71,128,57,51,93,51,56,51,1,230,80,173,157,54,35,29,57,57,62,90,80,173,157,55,34,31,55,57,62,90,0,0,2,0,100,1,94,4,76,3,135,0,3,0,7,0,16,183,5,1,0,106,1,7,105,1,0,47,43,43,57,48,49,19,53,33,21,3,17,51,17,100,3,232,192,192,2,205,186,186,254,145,1,211,254,45,0,0,1,0,204,3,52,3,226,5,140,0,7,0,16,183,6,4,1,0,106,1,2,114,0,43,43,50,57,48,49,19,1,33,1,35,3,35,3,204,1,4,1,14,1,4,220,166,18,166,3,52,2,88,253,168,1,184,254,72,0,0,3,0,100,1,88,4,122,4,46,0,25,0,38,0,51,0,37,64,19,45,6,33,106,9,23,13,19,13,6,39,0,26,106,19,6,0,105,6,0,47,43,50,43,50,17,51,17,18,57,57,43,50,48,49,1,34,38,53,52,54,51,50,22,23,35,54,54,51,50,22,21,20,6,35,34,38,39,51,6,6,39,50,54,55,21,38,38,35,34,6,21,20,22,33,50,54,53,52,38,35,34,6,7,53,22,22,1,116,123,149,149,123,102,132,47,60,47,132,102,123,149,149,123,102,132,47,60,47,132,53,63,67,15,15,68,62,61,75,75,1,208,62,74,74,62,63,67,15,15,67,1,88,199,163,169,195,123,134,134,123,195,169,163,199,123,133,133,123,168,129,100,71,105,129,107,91,87,107,107,87,91,107,129,105,71,100,129,0,1,0,136,0,0,4,40,4,56,0,13,0,19,64,10,3,10,106,3,7,114,7,0,8,114,0,43,50,43,43,48,49,51,17,16,33,32,17,17,35,17,16,35,34,17,17,136,1,208,1,208,220,244,244,2,78,1,234,254,22,253,178,2,78,1,44,254,212,253,178,0,0,2,0,68,254,35,4,100,5,160,0,12,0,25,0,27,64,15,20,12,3,13,14,106,13,15,114,3,9,106,3,3,114,0,43,43,43,43,18,57,57,48,49,1,17,16,33,50,23,7,38,38,35,32,17,17,1,39,55,54,54,53,17,51,17,20,6,6,7,1,146,1,246,114,106,22,63,96,45,254,228,253,232,10,108,118,108,212,96,202,160,1,104,2,18,2,38,20,184,8,6,254,162,253,228,252,187,188,15,17,156,163,1,66,254,222,189,234,120,19,255,255,0,76,0,0,4,100,5,160,2,6,2,58,0,0,255,255,0,45,0,0,4,131,5,140,2,6,2,38,0,0,0,3,0,80,255,56,4,96,5,140,0,3,0,7,0,11,0,25,64,13,1,5,5,0,9,4,105,9,8,106,9,2,114,0,43,43,43,50,51,17,51,48,49,5,17,51,17,33,17,51,17,1,53,33,21,3,12,212,252,240,212,254,172,4,16,200,6,84,249,172,6,84,249,172,5,150,190,190,0,3,0,150,255,56,4,46,5,140,0,5,0,9,0,13,0,33,64,18,4,3,12,13,106,0,1,9,8,106,5,2,12,9,105,12,2,114,0,43,43,57,57,43,50,57,43,50,57,48,49,5,39,1,1,55,1,1,53,33,21,1,53,33,21,1,40,146,1,195,254,61,162,2,23,253,71,3,152,252,104,3,132,146,122,2,126,2,104,132,253,18,252,212,176,176,5,150,190,190,0,2,0,86,255,56,4,106,5,140,0,7,0,11,0,25,64,13,3,2,2,10,7,105,10,11,106,6,10,2,114,0,43,50,43,43,57,47,57,48,49,5,3,51,19,51,1,51,1,19,53,33,21,1,18,188,206,109,18,1,5,196,254,192,124,1,194,200,2,89,254,91,5,160,249,172,5,150,190,190,255,255,0,156,254,52,4,134,4,36,2,6,2,80,0,0,255,255,0,118,255,236,4,60,5,146,0,71,2,112,4,178,0,0,192,0,64,0,0,2,0,100,0,0,4,76,4,36,0,3,0,7,0,19,64,10,7,6,106,3,7,8,114,1,6,114,0,43,43,50,43,48,49,51,17,51,17,35,53,33,21,100,192,192,3,232,4,36,251,220,186,186,0,5,0,54,255,236,4,142,5,160,0,3,0,15,0,27,0,39,0,51,0,44,64,28,28,40,106,34,28,105,0,1,3,2,4,4,34,46,106,34,17,10,22,106,4,10,105,4,16,106,4,19,0,63,43,43,43,63,43,18,23,57,43,43,48,49,19,39,1,23,1,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,1,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,186,92,3,162,92,254,250,142,172,172,142,141,171,171,141,59,72,72,59,61,72,72,254,87,142,172,172,142,141,171,171,141,59,72,72,59,61,72,72,1,50,136,2,152,130,252,28,177,145,147,177,177,147,145,177,163,88,71,73,88,88,73,71,88,2,139,177,145,147,177,174,150,145,177,163,88,71,74,89,89,74,71,88,0,0,7,0,32,255,236,4,173,5,160,0,3,0,15,0,27,0,39,0,51,0,63,0,75,0,47,64,31,28,40,106,34,28,105,0,1,3,2,4,4,34,46,106,34,3,114,16,52,22,64,10,70,6,4,58,105,4,9,114,0,43,43,23,57,43,43,18,23,57,43,43,48,49,19,39,1,23,1,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,3,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,1,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,136,92,3,162,92,253,244,107,130,130,107,107,129,129,107,38,45,45,38,38,46,46,158,142,172,172,142,141,171,171,141,59,72,72,59,61,72,72,2,164,107,130,130,107,107,129,129,107,38,45,45,38,38,46,46,1,50,136,2,152,130,252,28,138,113,114,138,138,114,113,138,144,59,48,49,59,59,49,48,59,2,158,177,145,147,177,174,150,145,177,163,88,71,74,89,89,74,71,88,253,97,138,113,114,138,138,114,113,138,144,59,48,49,59,59,49,48,59,0,0,4,0,100,0,166,4,76,4,238,0,3,0,7,0,11,0,15,0,20,64,11,6,11,10,15,14,3,6,1,4,105,1,0,47,43,23,57,48,49,19,53,33,21,1,53,33,21,1,53,33,21,1,53,33,21,100,3,232,252,24,3,232,252,24,3,232,252,24,3,232,4,72,166,166,252,94,166,166,1,54,166,166,1,54,166,166,0,255,255,0,121,0,188,4,55,4,164,2,6,3,69,0,0,0,2,0,194,0,0,3,238,5,160,0,7,0,11,0,23,64,12,4,7,7,6,9,3,8,1,105,8,8,114,0,43,43,23,57,17,51,48,49,19,1,51,1,35,3,33,3,19,17,51,17,194,1,139,22,1,139,222,50,254,244,50,90,188,3,8,2,152,253,104,1,70,254,186,252,248,4,168,251,88,0,2,0,100,1,46,4,106,4,90,0,7,0,11,0,33,64,18,6,7,9,8,1,0,106,1,9,8,106,4,5,106,4,9,147,114,0,43,206,43,43,206,43,17,18,57,57,48,49,1,53,37,17,37,53,1,21,5,53,33,21,1,210,1,29,254,227,2,152,251,250,3,14,1,46,222,50,1,12,50,222,254,118,22,84,188,188,0,0,2,0,194,255,236,3,238,5,140,0,7,0,11,0,23,64,11,5,3,8,2,2,9,0,105,9,2,114,0,43,43,57,47,57,57,51,48,49,5,1,51,19,33,19,51,1,39,17,51,17,2,77,254,117,222,50,1,12,50,222,254,117,105,188,20,2,152,254,186,1,70,253,104,248,4,168,251,88,0,0,2,0,70,1,46,4,76,4,90,0,7,0,11,0,29,64,16,7,0,106,7,2,1,10,11,106,4,3,106,4,10,147,114,0,43,206,43,43,57,57,206,43,48,49,1,1,53,1,21,5,17,5,37,53,33,21,2,222,253,104,2,152,254,227,1,29,254,96,3,14,1,46,1,140,22,1,138,222,50,254,244,50,90,188,188,0,3,0,65,1,46,4,111,4,90,0,7,0,15,0,19,0,44,64,25,7,9,10,6,4,18,19,8,1,0,106,15,1,18,19,106,11,4,5,106,12,4,18,147,114,0,43,204,50,43,50,43,204,50,43,50,17,18,23,57,48,49,1,53,55,17,39,53,1,21,1,1,53,1,21,7,17,23,37,53,33,21,2,189,195,195,1,178,253,132,254,78,1,178,195,195,254,236,2,242,1,46,222,50,1,12,50,222,254,118,22,254,116,1,140,22,1,138,222,50,254,244,50,90,188,188,0,3,0,194,255,236,3,238,5,160,0,7,0,15,0,19,0,37,64,17,17,6,1,4,13,7,11,16,10,7,10,7,10,1,8,105,1,0,47,43,57,57,47,47,17,57,57,18,57,57,17,57,57,48,49,19,1,51,1,35,39,33,7,19,1,51,23,33,55,51,1,39,17,51,17,194,1,139,22,1,139,222,50,254,244,50,173,254,117,222,50,1,12,50,222,254,117,105,188,3,118,2,42,253,214,246,246,252,118,2,42,246,246,253,214,218,4,0,252,0,0,4,0,194,255,70,3,238,5,160,0,3,0,11,0,19,0,23,0,42,64,22,21,10,6,11,15,20,14,11,14,11,14,6,12,105,6,17,2,3,106,2,8,114,0,43,43,63,43,57,57,47,47,17,57,57,17,18,57,57,48,49,23,53,33,21,1,1,51,1,35,39,33,7,19,1,51,23,33,55,51,1,39,17,51,17,200,3,22,252,228,1,139,22,1,139,222,50,254,244,50,173,254,117,222,50,1,12,50,222,254,117,105,188,186,186,186,4,48,2,42,253,214,246,246,252,118,2,42,246,246,253,214,218,4,0,252,0,0,5,0,194,0,0,3,238,5,160,0,7,0,11,0,15,0,19,0,23,0,40,64,21,22,23,1,3,10,15,14,19,4,7,8,3,7,3,7,8,1,105,8,8,114,0,43,43,57,57,47,47,17,18,23,57,17,18,57,57,48,49,19,1,51,1,35,3,33,3,19,53,51,21,3,53,51,21,3,53,51,21,3,17,51,17,194,1,139,22,1,139,222,50,254,244,50,90,188,188,188,188,188,188,188,3,8,2,152,253,104,1,70,254,186,252,248,194,194,1,48,182,182,1,36,182,182,1,36,1,48,254,208,0,0,5,0,194,255,236,3,238,5,140,0,7,0,11,0,15,0,19,0,23,0,41,64,23,13,16,17,20,4,21,2,8,3,9,12,4,5,2,5,2,5,21,0,105,21,2,114,0,43,43,57,57,47,47,17,23,57,17,18,23,57,48,49,5,1,51,19,33,19,51,1,39,17,51,17,3,53,51,21,3,53,51,21,3,53,51,21,2,77,254,117,222,50,1,12,50,222,254,117,105,188,188,188,188,188,188,188,20,2,152,254,186,1,70,253,104,248,1,48,254,208,1,158,182,182,1,36,182,182,1,36,194,194,0,0,1,0,0,254,32,4,176,255,83,0,3,0,0,17,17,33,17,4,176,254,32,1,51,254,205,0,1,0,0,254,32,4,176,0,135,0,3,0,0,17,17,33,17,4,176,254,32,2,103,253,153,0,1,0,0,254,32,4,176,1,186,0,3,0,0,17,17,33,17,4,176,254,32,3,154,252,102,0,1,0,0,254,32,4,176,2,238,0,3,0,0,17,17,33,17,4,176,254,32,4,206,251,50,0,1,0,0,254,32,4,176,4,33,0,3,0,0,17,17,33,17,4,176,254,32,6,1,249,255,0,1,0,0,254,32,4,176,5,85,0,3,0,0,17,17,33,17,4,176,254,32,7,53,248,203,0,1,0,0,254,32,4,176,6,136,0,3,0,0,17,17,33,17,4,176,254,32,8,104,247,152,0,1,0,0,254,32,4,176,7,188,0,3,0,0,17,17,33,17,4,176,254,32,9,156,246,100,0,1,0,0,2,18,4,176,7,188,0,3,0,0,17,17,33,17,4,176,2,18,5,170,250,86,0,1,0,0,6,136,4,176,7,188,0,3,0,0,17,17,33,17,4,176,6,136,1,52,254,204,0,1,0,0,254,32,0,150,7,188,0,3,0,0,17,17,51,17,150,254,32,9,156,246,100,0,0,1,0,0,254,32,1,44,7,188,0,3,0,0,17,17,33,17,1,44,254,32,9,156,246,100,0,1,0,0,254,32,1,194,7,188,0,3,0,0,17,17,33,17,1,194,254,32,9,156,246,100,0,1,0,0,254,32,2,88,7,188,0,3,0,0,17,17,33,17,2,88,254,32,9,156,246,100,0,1,0,0,254,32,2,238,7,188,0,3,0,0,17,17,33,17,2,238,254,32,9,156,246,100,0,1,0,0,254,32,3,132,7,188,0,3,0,0,17,17,33,17,3,132,254,32,9,156,246,100,0,1,0,0,254,32,4,26,7,188,0,3,0,0,17,17,33,17,4,26,254,32,9,156,246,100,0,1,2,88,254,32,4,176,7,188,0,3,0,0,1,17,33,17,2,88,2,88,254,32,9,156,246,100,0,1,4,26,254,32,4,176,7,188,0,3,0,0,1,17,51,17,4,26,150,254,32,9,156,246,100,0,0,1,0,0,254,32,2,88,2,238,0,3,0,0,17,17,33,17,2,88,254,32,4,206,251,50,0,1,2,88,254,32,4,176,2,18,0,3,0,0,1,17,33,17,2,88,2,88,254,32,3,242,252,14,0,1,0,0,2,18,2,88,7,188,0,3,0,0,17,17,33,17,2,88,2,18,5,170,250,86,0,1,0,0,254,32,4,176,7,188,0,5,0,0,17,17,33,17,33,17,2,88,2,88,254,32,9,156,251,50,251,50,0,2,0,0,254,32,4,176,7,188,0,3,0,7,0,0,17,17,33,25,2,33,17,2,88,2,88,2,18,5,170,250,86,252,14,3,242,252,14,0,0,1,0,0,254,32,4,176,7,188,0,5,0,0,17,17,33,17,33,17,4,176,253,168,254,32,9,156,250,86,252,14,0,1,0,0,254,32,4,176,7,188,0,5,0,0,1,17,33,17,33,17,2,88,253,168,4,176,254,32,3,242,5,170,246,100,0,1,2,88,2,18,4,176,7,188,0,3,0,0,1,17,33,17,2,88,2,88,2,18,5,170,250,86,0,1,0,0,254,32,4,176,7,188,0,7,0,0,17,17,33,17,33,17,33,17,2,88,2,88,253,168,254,32,4,206,4,206,250,86,252,14,0,1,0,0,254,32,4,176,7,188,0,5,0,0,17,17,33,17,33,17,2,88,2,88,254,32,4,206,4,206,246,100,0,9,0,0,254,32,4,176,7,188,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,35,0,0,17,53,1,21,1,1,21,1,33,1,21,1,33,55,21,7,37,53,1,21,1,53,1,21,1,53,1,51,1,53,1,51,1,53,1,51,4,176,252,124,3,132,252,164,1,104,1,244,254,52,1,104,100,60,251,140,4,176,251,80,4,176,251,80,1,104,40,254,112,2,248,40,252,224,4,136,40,1,124,40,4,176,40,247,244,3,132,40,252,164,1,244,40,254,52,100,40,60,60,40,4,176,40,252,224,40,4,176,40,1,144,40,1,104,252,224,40,2,248,251,80,40,4,136,0,18,0,0,254,32,4,176,7,188,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,35,0,39,0,43,0,47,0,51,0,55,0,59,0,63,0,67,0,71,0,0,17,53,1,21,1,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,55,21,7,37,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,37,53,55,51,3,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,4,176,251,180,4,76,251,220,160,3,132,252,164,160,2,188,253,108,160,1,244,254,52,160,1,44,254,252,160,100,60,251,140,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,160,40,200,1,104,40,254,112,2,48,40,253,168,2,248,40,252,224,3,192,40,252,24,4,136,40,2,68,40,4,176,40,247,44,4,76,40,251,220,3,132,40,252,164,2,188,40,253,108,1,244,40,254,52,1,44,40,254,252,100,40,60,60,40,4,176,40,252,24,40,4,176,40,252,24,40,4,176,40,252,24,40,4,176,40,252,24,40,4,176,40,200,40,160,254,112,40,1,104,253,168,40,2,48,252,224,40,2,248,252,24,40,3,192,251,80,40,4,136,0,36,0,0,254,32,4,176,7,188,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,35,0,39,0,43,0,47,0,51,0,55,0,59,0,63,0,67,0,71,0,75,0,79,0,83,0,87,0,91,0,95,0,99,0,103,0,107,0,111,0,115,0,119,0,123,0,127,0,131,0,135,0,139,0,143,0,0,17,53,1,21,1,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,55,21,7,51,55,21,7,37,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,37,53,55,51,7,53,55,51,3,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,4,176,251,80,4,176,251,120,60,4,76,251,220,60,3,232,252,64,60,3,132,252,164,60,3,32,253,8,60,2,188,253,108,60,2,88,253,208,60,1,244,254,52,60,1,144,254,152,60,1,44,254,252,60,200,160,60,100,60,251,140,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,60,40,100,160,40,200,1,4,40,254,212,1,104,40,254,112,1,204,40,254,12,2,48,40,253,168,2,148,40,253,68,2,248,40,252,224,3,92,40,252,124,3,192,40,252,24,4,36,40,251,180,4,136,40,2,168,40,4,176,40,246,200,4,176,40,251,120,4,76,40,251,220,3,232,40,252,64,3,132,40,252,164,3,32,40,253,8,2,188,40,253,108,2,88,40,253,208,1,244,40,254,52,1,144,40,254,152,1,44,40,254,252,200,40,160,100,40,60,60,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,100,40,60,200,40,160,254,212,40,1,4,254,112,40,1,104,254,12,40,1,204,253,168,40,2,48,253,68,40,2,148,252,224,40,2,248,252,124,40,3,92,252,24,40,3,192,251,180,40,4,36,251,80,40,4,136,0,1,0,75,0,185,4,101,4,211,0,15,0,0,37,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,2,88,158,236,131,131,236,158,158,236,131,131,236,185,131,236,158,158,236,131,131,236,158,158,236,131,0,2,0,75,0,185,4,101,4,211,0,15,0,31,0,0,37,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,39,50,54,54,53,52,38,38,35,34,6,6,21,20,22,22,2,88,158,236,131,131,236,158,158,236,131,131,236,158,113,169,93,93,169,113,113,169,93,93,169,185,131,236,158,158,236,131,131,236,158,158,236,131,150,93,169,113,113,169,93,93,169,113,113,169,93,0,0,2,0,0,0,110,4,176,5,30,0,15,0,31,0,0,37,34,36,2,53,52,18,36,51,50,4,18,21,20,2,4,39,50,54,54,53,52,38,38,35,34,6,6,21,20,22,22,2,88,181,254,242,149,149,1,14,181,181,1,14,149,149,254,242,181,136,202,112,112,202,136,135,203,112,112,203,110,149,1,14,181,181,1,14,149,149,254,242,181,181,254,242,149,150,112,203,135,136,202,112,112,202,136,135,203,112,0,0,3,0,75,0,185,4,101,4,211,0,4,0,20,0,36,0,0,1,3,19,33,17,21,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,39,50,54,54,53,52,38,38,35,34,6,6,21,20,22,22,1,93,207,160,1,42,158,236,131,131,236,158,158,236,131,131,236,158,113,169,93,93,169,113,113,169,93,93,169,1,35,1,157,1,154,252,201,106,131,236,158,158,236,131,131,236,158,158,236,131,150,93,169,113,113,169,93,93,169,113,113,169,93,0,3,0,75,0,185,4,101,4,211,0,4,0,20,0,36,0,0,1,17,33,19,3,7,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,39,50,54,54,53,52,38,38,35,34,6,6,21,20,22,22,2,88,1,42,160,207,251,158,236,131,131,236,158,158,236,131,131,236,158,113,169,93,93,169,113,113,169,93,93,169,1,35,3,66,254,91,254,99,106,131,236,158,158,236,131,131,236,158,158,236,131,150,93,169,113,113,169,93,93,169,113,113,169,93,0,0,3,0,75,0,185,4,101,4,211,0,4,0,20,0,36,0,0,37,37,53,33,17,5,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,39,50,54,54,53,52,38,38,35,34,6,6,21,20,22,22,2,82,254,99,3,66,254,97,158,236,131,131,236,158,158,236,131,131,236,158,113,169,93,93,169,113,113,169,93,93,169,252,207,251,254,214,227,131,236,158,158,236,131,131,236,158,158,236,131,150,93,169,113,113,169,93,93,169,113,113,169,93,0,0,3,0,75,0,185,4,101,4,211,0,4,0,20,0,36,0,0,19,53,37,5,17,1,50,22,22,21,20,6,6,35,34,38,38,53,52,54,54,23,34,6,6,21,20,22,22,51,50,54,54,53,52,38,38,181,1,157,1,165,254,97,158,236,131,131,236,158,158,236,131,131,236,158,113,169,93,93,169,113,113,169,93,93,169,2,198,251,207,160,254,214,2,13,131,236,158,158,236,131,131,236,158,158,236,131,150,93,169,113,113,169,93,93,169,113,113,169,93,0,0,1,0,75,0,185,2,88,4,211,0,8,0,0,37,34,38,38,53,52,54,54,51,2,88,158,236,131,131,236,158,185,131,236,158,158,236,131,0,1,2,88,0,185,4,101,4,211,0,8,0,0,37,17,50,22,22,21,20,6,6,2,88,158,236,131,131,236,185,4,26,131,236,158,158,236,131,0,0,3,0,75,0,185,4,101,4,211,0,3,0,19,0,35,0,0,1,17,5,19,1,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,39,50,54,54,53,52,38,38,35,34,6,6,21,20,22,22,2,88,1,103,116,254,37,158,236,131,131,236,158,158,236,131,131,236,158,113,169,93,93,169,113,113,169,93,93,169,2,198,1,219,105,254,142,253,243,131,236,158,158,236,131,131,236,158,158,236,131,150,93,169,113,113,169,93,93,169,113,113,169,93,0,3,0,75,0,185,4,101,4,211,0,8,0,24,0,40,0,0,37,1,53,33,17,51,1,17,3,5,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,39,50,54,54,53,52,38,38,35,34,6,6,21,20,22,22,1,175,254,206,1,219,180,1,36,197,254,237,158,236,131,131,236,158,158,236,131,131,236,158,113,169,93,93,169,113,113,169,93,93,169,225,1,53,176,1,219,254,228,254,172,254,227,91,131,236,158,158,236,131,131,236,158,158,236,131,150,93,169,113,113,169,93,93,169,113,113,169,93,0,3,0,75,0,185,4,101,4,211,0,5,0,21,0,37,0,0,19,53,33,17,51,17,3,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,39,50,54,54,53,52,38,38,35,34,6,6,21,20,22,22,153,1,116,150,75,158,236,131,131,236,158,158,236,131,131,236,158,113,169,93,93,169,113,113,169,93,93,169,2,123,150,1,107,253,255,254,62,131,236,158,158,236,131,131,236,158,158,236,131,150,93,169,113,113,169,93,93,169,113,113,169,93,0,3,0,75,0,185,4,101,4,211,0,5,0,21,0,37,0,0,1,17,33,53,33,17,7,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,39,50,54,54,53,52,38,38,35,34,6,6,21,20,22,22,2,13,254,149,2,1,75,158,236,131,131,236,158,158,236,131,131,236,158,113,169,93,93,169,113,113,169,93,93,169,1,7,1,116,150,253,246,78,131,236,158,158,236,131,131,236,158,158,236,131,150,93,169,113,113,169,93,93,169,113,113,169,93,0,0,3,0,75,0,185,4,101,4,211,0,5,0,21,0,37,0,0,1,17,33,21,33,17,7,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,39,50,54,54,53,52,38,38,35,34,6,6,21,20,22,22,2,13,2,21,254,129,75,158,236,131,131,236,158,158,236,131,131,236,158,113,169,93,93,169,113,113,169,93,93,169,1,7,2,10,150,254,140,78,131,236,158,158,236,131,131,236,158,158,236,131,150,93,169,113,113,169,93,93,169,113,113,169,93,0,0,3,0,75,0,185,4,101,4,211,0,5,0,21,0,37,0,0,1,17,51,17,33,21,1,50,22,22,21,20,6,6,35,34,38,38,53,52,54,54,23,34,6,6,21,20,22,22,51,50,54,54,53,52,38,38,2,13,150,1,127,254,54,158,236,131,131,236,158,158,236,131,131,236,158,113,169,93,93,169,113,113,169,93,93,169,2,123,2,10,254,140,150,2,88,131,236,158,158,236,131,131,236,158,158,236,131,150,93,169,113,113,169,93,93,169,113,113,169,93,0,4,0,75,0,185,4,101,4,211,0,3,0,7,0,23,0,39,0,0,1,17,23,17,51,17,23,17,3,50,22,22,21,20,6,6,35,34,38,38,53,52,54,54,23,34,6,6,21,20,22,22,51,50,54,54,53,52,38,38,1,119,150,150,150,225,158,236,131,131,236,158,158,236,131,131,236,158,113,169,93,93,169,113,113,169,93,93,169,1,18,3,127,1,252,130,3,127,1,252,130,3,193,131,236,158,158,236,131,131,236,158,158,236,131,150,93,169,113,113,169,93,93,169,113,113,169,93,0,12,0,75,0,185,4,101,4,211,0,11,0,23,0,35,0,47,0,59,0,71,0,83,0,95,0,107,0,119,0,131,0,143,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,39,34,38,53,52,54,51,50,22,21,20,6,5,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,55,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,55,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,5,34,38,53,52,54,51,50,22,21,20,6,3,58,34,41,41,34,34,41,41,254,27,34,41,41,34,34,41,41,197,34,41,41,34,34,41,41,1,98,34,41,41,34,34,41,41,254,28,34,41,41,34,34,41,41,28,34,41,41,34,34,41,41,2,68,34,41,41,34,34,41,41,254,27,34,41,41,34,34,41,41,2,68,34,41,41,34,34,41,41,27,34,41,41,34,34,41,41,254,28,34,41,41,34,34,41,41,1,99,34,41,41,34,34,41,41,4,0,41,34,34,41,41,34,34,41,252,246,41,34,34,41,41,34,34,41,165,41,34,34,41,41,34,34,41,226,41,34,34,41,41,34,34,41,1,194,41,34,34,41,41,34,34,41,225,41,34,34,41,41,34,34,41,253,154,41,34,34,41,41,34,34,41,3,10,41,34,34,41,41,34,34,41,253,155,41,34,34,41,41,34,34,41,224,41,34,34,41,41,34,34,41,1,194,41,34,34,41,41,34,34,41,225,41,34,34,41,41,34,34,41,0,3,0,75,0,185,4,101,4,211,0,11,0,27,0,43,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,50,22,22,21,20,6,6,35,34,38,38,53,52,54,54,23,34,6,6,21,20,22,22,51,50,54,54,53,52,38,38,2,88,102,123,123,102,102,123,123,102,158,236,131,131,236,158,158,236,131,131,236,158,113,169,93,93,169,113,113,169,93,93,169,1,229,123,102,102,123,123,102,102,123,2,238,131,236,158,158,236,131,131,236,158,158,236,131,150,93,169,113,113,169,93,93,169,113,113,169,93,255,255,0,0,0,110,4,176,5,30,2,38,3,140,0,0,0,6,3,157,0,0,0,2,1,48,1,158,3,128,3,238,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,2,88,133,163,163,133,134,162,162,134,66,80,80,66,66,80,80,1,158,163,133,134,162,162,134,133,163,150,80,66,66,80,80,66,66,80,0,2,0,75,0,185,4,101,4,211,0,3,0,15,0,0,55,17,33,17,37,50,54,53,52,38,35,34,6,21,20,22,75,4,26,253,243,134,162,162,134,133,163,163,185,4,26,251,230,215,163,133,134,162,162,134,133,163,0,3,0,0,0,110,4,176,5,30,0,3,0,19,0,35,0,0,53,17,33,17,37,50,54,54,53,52,38,38,35,34,6,6,21,20,22,22,55,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,4,176,253,168,158,236,131,131,236,158,158,236,131,131,236,158,113,169,93,93,169,113,113,169,93,93,169,110,4,176,251,80,75,131,236,158,158,236,131,131,236,158,158,236,131,150,93,169,113,113,169,93,93,169,113,113,169,93,0,2,0,0,2,198,4,176,5,30,0,12,0,21,0,0,17,17,33,17,35,52,38,38,35,34,6,6,21,51,52,54,54,51,50,22,22,21,4,176,75,131,236,158,158,236,131,150,93,169,113,113,169,93,2,198,2,88,253,168,158,236,131,131,236,158,113,169,93,93,169,113,0,2,0,0,0,110,4,176,2,198,0,12,0,21,0,0,53,17,51,20,22,22,51,50,54,54,53,51,17,37,34,38,38,53,33,20,6,6,75,131,236,158,158,236,131,75,253,168,113,169,93,2,238,93,169,110,2,88,158,236,131,131,236,158,253,168,225,93,169,113,113,169,93,0,0,1,0,75,2,198,4,101,4,211,0,17,0,0,19,52,54,54,51,50,22,22,21,35,52,38,38,35,34,6,6,21,75,131,236,158,158,236,131,150,93,169,113,113,169,93,2,198,158,236,131,131,236,158,113,169,93,93,169,113,0,1,0,75,0,185,4,101,2,198,0,17,0,0,37,34,38,38,53,51,20,22,22,51,50,54,54,53,51,20,6,6,2,88,158,236,131,150,93,169,113,113,169,93,150,131,236,185,131,236,158,113,169,93,93,169,113,158,236,131,0,1,0,75,2,198,2,88,4,211,0,9,0,0,19,52,54,54,51,21,34,6,6,21,75,131,236,158,113,169,93,2,198,158,236,131,150,93,169,113,0,1,2,88,2,198,4,101,4,211,0,9,0,0,1,52,38,38,35,53,50,22,22,21,3,207,93,169,113,158,236,131,2,198,113,169,93,150,131,236,158,0,0,1,2,88,0,185,4,101,2,198,0,9,0,0,37,53,50,54,54,53,51,20,6,6,2,88,113,169,93,150,131,236,185,150,93,169,113,158,236,131,0,1,0,75,0,185,2,88,2,198,0,9,0,0,37,34,38,38,53,51,20,22,22,51,2,88,158,236,131,150,93,169,113,185,131,236,158,113,169,93,0,1,0,0,0,110,4,176,5,30,0,3,0,0,37,9,2,2,88,253,168,2,88,2,88,110,2,88,2,88,253,168,0,2,0,0,0,110,4,176,5,30,0,3,0,7,0,0,37,9,6,2,88,253,168,2,88,2,88,253,168,1,132,254,124,254,124,110,2,88,2,88,253,168,254,124,1,132,1,132,254,124,0,3,0,0,0,110,4,176,5,30,0,2,0,6,0,10,0,0,37,1,1,17,9,6,2,88,253,235,2,21,253,168,2,88,2,88,253,168,1,132,254,124,254,124,192,2,6,2,6,251,162,2,88,2,88,253,168,254,124,1,132,1,132,254,124,0,0,3,0,0,0,110,4,176,5,30,0,2,0,6,0,10,0,0,37,17,9,8,2,88,2,21,253,235,253,168,2,88,2,88,253,168,1,132,254,124,254,124,192,4,12,253,250,253,168,2,88,2,88,253,168,254,124,1,132,1,132,254,124,0,0,3,0,0,0,110,4,176,5,30,0,2,0,6,0,10,0,0,19,9,9,67,2,21,2,21,253,235,253,168,2,88,2,88,253,168,1,132,254,124,254,124,2,198,2,6,253,250,253,168,2,88,2,88,253,168,254,124,1,132,1,132,254,124,0,3,0,0,0,110,4,176,5,30,0,2,0,6,0,10,0,0,19,33,1,17,9,6,67,4,42,253,235,2,88,253,168,253,168,2,88,254,124,1,132,1,132,2,198,253,250,4,94,253,168,253,168,2,88,1,132,254,124,254,124,1,132,0,0,3,0,0,0,110,4,176,5,30,0,3,0,7,0,11,0,0,1,39,55,23,3,9,6,2,88,176,176,176,176,2,88,253,168,253,168,2,88,254,124,1,132,1,132,2,22,176,176,176,2,88,253,168,253,168,2,88,1,132,254,124,254,124,1,132,0,2,0,80,0,0,4,96,5,140,0,5,0,9,0,0,33,1,1,51,1,1,39,9,2,1,223,254,113,1,143,232,1,153,254,103,116,1,54,254,202,254,212,2,198,2,198,253,58,253,58,172,2,26,2,26,253,230,0,1,0,0,1,154,4,176,3,242,0,3,0,0,17,19,33,3,170,4,6,170,1,154,2,88,253,168,0,2,0,0,1,154,4,176,3,242,0,3,0,11,0,0,17,19,33,3,37,39,33,7,19,23,33,55,170,4,6,170,252,170,59,3,113,103,129,59,252,143,103,1,154,2,88,253,168,72,78,78,1,200,78,78,0,1,1,44,0,110,3,132,5,30,0,3,0,0,37,17,33,17,1,44,2,88,110,4,176,251,80,0,0,1,0,0,1,154,4,176,3,242,0,3,0,0,17,17,33,17,4,176,1,154,2,88,253,168,0,2,0,0,1,154,4,176,3,242,0,3,0,7,0,0,17,17,33,17,37,33,17,33,4,176,251,230,3,132,252,124,1,154,2,88,253,168,150,1,44,0,0,2,1,44,0,110,3,132,5,30,0,3,0,7,0,0,37,17,33,17,37,33,17,33,1,44,2,88,254,62,1,44,254,212,110,4,176,251,80,150,3,132,0,1,0,75,0,185,4,101,4,211,0,3,0,0,55,17,33,17,75,4,26,185,4,26,251,230,0,2,0,75,0,185,4,101,4,211,0,3,0,7,0,0,55,17,33,17,37,33,17,33,75,4,26,252,124,2,238,253,18,185,4,26,251,230,150,2,238,0,0,2,0,75,0,185,4,101,4,211,0,15,0,31,0,0,37,34,38,53,17,52,54,51,33,50,22,21,17,20,6,35,37,33,50,54,53,17,52,38,35,33,34,6,21,17,20,22,1,75,115,141,141,115,2,26,115,141,141,115,253,229,2,28,48,57,57,48,253,228,48,57,57,185,141,115,2,26,115,141,141,115,253,230,115,141,150,57,48,2,28,48,57,57,48,253,228,48,57,0,0,3,0,75,0,185,4,101,4,211,0,3,0,7,0,11,0,0,1,17,33,17,1,17,33,17,37,33,17,33,1,119,1,194,253,18,4,26,252,124,2,238,253,18,1,229,1,194,254,62,254,212,4,26,251,230,150,2,238,0,0,12,0,75,0,185,4,101,4,211,0,11,0,23,0,35,0,47,0,59,0,71,0,83,0,95,0,107,0,119,0,131,0,143,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,4,26,31,44,44,31,31,44,44,252,93,31,44,44,31,31,44,44,31,31,44,44,31,31,44,44,1,13,31,44,44,31,31,44,44,254,181,31,44,44,31,31,44,44,2,57,31,44,44,31,31,44,44,253,137,31,44,44,31,31,44,44,3,101,31,44,44,31,31,44,44,253,137,31,44,44,31,31,44,44,2,57,31,44,44,31,31,44,44,31,31,44,44,31,31,44,44,254,181,31,44,44,31,31,44,44,4,61,44,31,31,44,44,31,31,44,252,124,44,31,31,44,44,31,31,44,1,44,44,31,31,44,44,31,31,44,254,212,44,31,31,44,44,31,31,44,2,88,44,31,31,44,44,31,31,44,253,168,44,31,31,44,44,31,31,44,3,132,44,31,31,44,44,31,31,44,252,124,44,31,31,44,44,31,31,44,3,132,44,31,31,44,44,31,31,44,253,168,44,31,31,44,44,31,31,44,1,44,44,31,31,44,44,31,31,44,1,44,44,31,31,44,44,31,31,44,0,4,0,75,0,185,4,101,4,211,0,3,0,7,0,11,0,15,0,0,19,53,33,21,1,53,33,21,1,17,33,17,37,33,17,33,149,3,134,252,122,3,134,252,48,4,26,252,124,2,238,253,18,3,17,150,150,254,212,150,150,254,212,4,26,251,230,150,2,238,0,4,0,75,0,185,4,101,4,211,0,3,0,7,0,11,0,15,0,0,1,35,17,51,1,35,17,51,1,33,17,33,3,17,33,17,2,13,150,150,1,44,150,150,1,44,251,230,4,26,150,253,18,1,3,3,134,252,122,3,134,252,48,4,26,252,124,2,238,253,18,0,0,6,0,75,0,185,4,101,4,211,0,3,0,7,0,11,0,15,0,19,0,23,0,0,19,53,33,21,1,17,51,17,37,53,33,21,5,17,51,17,5,17,33,17,37,33,17,33,149,3,134,253,92,150,254,136,3,134,254,136,150,253,18,4,26,252,124,2,238,253,18,3,17,150,150,253,242,3,134,252,122,226,150,150,226,3,134,252,122,74,4,26,251,230,150,2,238,0,0,5,0,75,0,185,4,101,4,211,0,3,0,7,0,11,0,15,0,19,0,0,19,55,1,7,1,53,1,35,3,51,1,21,1,17,33,17,37,33,17,33,129,111,3,79,101,252,188,2,103,212,111,212,1,170,252,19,4,26,252,124,2,238,253,18,4,56,101,252,177,111,1,170,212,253,153,3,163,254,86,212,254,158,4,26,251,230,150,2,238,0,0,5,0,75,0,185,4,101,4,211,0,3,0,7,0,11,0,15,0,19,0,0,1,1,39,1,19,1,35,9,2,53,1,1,33,17,33,3,17,33,17,4,47,252,167,101,3,79,90,254,109,212,2,103,254,220,253,130,1,170,2,67,251,230,4,26,150,253,18,4,56,252,167,111,3,79,253,236,254,109,2,103,1,60,253,130,212,1,170,252,32,4,26,252,124,2,238,253,18,0,0,8,0,75,0,185,4,101,4,211,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,0,37,1,55,1,5,1,53,1,5,39,1,23,1,1,21,1,1,53,1,51,1,1,51,1,1,17,33,17,37,33,17,33,3,218,252,167,111,3,79,253,234,254,109,2,103,253,217,101,3,79,111,253,132,2,103,254,109,253,241,1,170,212,1,66,253,130,212,1,170,252,19,4,26,252,124,2,238,253,18,223,3,89,101,252,177,88,1,147,212,253,153,23,111,3,79,101,252,190,2,103,212,254,109,1,37,212,1,170,253,130,2,126,254,86,253,202,4,26,251,230,150,2,238,0,0,1,1,44,1,154,3,132,3,242,0,3,0,0,1,17,33,17,1,44,2,88,1,154,2,88,253,168,0,2,1,44,1,154,3,132,3,242,0,3,0,7,0,0,1,17,33,17,37,33,17,33,1,44,2,88,254,62,1,44,254,212,1,154,2,88,253,168,150,1,44,0,0,3,0,75,0,185,4,101,4,211,0,3,0,7,0,11,0,0,37,33,17,33,1,17,33,17,37,33,17,33,2,88,254,27,1,229,253,243,4,26,252,124,2,238,253,18,235,3,182,252,24,4,26,251,230,150,2,238,0,3,0,75,0,185,4,101,4,211,0,3,0,7,0,11,0,0,37,17,33,17,23,33,17,33,3,17,33,17,2,88,1,229,40,251,230,4,26,150,253,18,235,3,182,252,74,50,4,26,252,124,2,238,253,18,0,3,0,75,0,185,4,101,4,211,0,2,0,6,0,10,0,0,55,17,33,19,33,17,33,3,17,33,17,101,3,220,36,251,230,4,26,150,253,18,221,3,211,252,9,4,26,252,124,2,238,253,18,0,0,3,0,75,0,185,4,101,4,211,0,2,0,6,0,10,0,0,1,17,33,3,33,17,33,19,17,33,17,4,75,252,36,36,4,26,251,230,150,2,238,4,175,252,45,3,247,251,230,3,132,253,18,2,238,0,0,3,0,75,0,185,4,101,4,211,0,3,0,7,0,11,0,0,37,35,17,51,37,33,17,33,19,17,33,17,2,163,150,150,253,168,4,26,251,230,150,2,238,219,3,214,34,251,230,3,132,253,18,2,238,0,0,3,0,75,0,185,4,101,4,211,0,5,0,9,0,13,0,0,19,53,33,17,51,17,1,33,17,33,19,17,33,17,130,1,140,150,253,167,4,26,251,230,150,2,238,2,123,150,1,140,253,222,2,88,251,230,3,132,253,18,2,238,0,3,0,75,0,185,4,101,4,211,0,5,0,9,0,13,0,0,19,33,17,35,17,33,3,17,33,17,37,33,17,33,130,2,34,150,254,116,55,4,26,252,124,2,238,253,18,3,17,253,222,1,140,254,62,4,26,251,230,150,2,238,0,3,0,75,0,185,4,101,4,211,0,5,0,9,0,13,0,0,1,21,33,17,35,17,1,33,17,33,3,17,33,17,4,46,254,116,150,2,89,251,230,4,26,150,253,18,3,17,150,254,116,2,34,253,168,4,26,252,124,2,238,253,18,0,0,3,0,75,0,185,4,101,4,211,0,5,0,9,0,13,0,0,1,33,17,51,17,33,19,17,33,17,5,33,17,33,4,46,253,222,150,1,140,55,251,230,3,132,253,18,2,238,2,123,2,34,254,116,1,194,251,230,4,26,150,253,18,0,0,2,0,150,1,4,4,26,4,136,0,3,0,7,0,0,19,17,33,17,37,33,17,33,150,3,132,253,18,2,88,253,168,1,4,3,132,252,124,150,2,88,0,1,0,150,1,4,4,26,4,136,0,3,0,0,19,17,33,17,150,3,132,1,4,3,132,252,124,0,0,2,0,225,1,79,3,207,4,61,0,3,0,7,0,0,19,17,33,17,37,33,17,33,225,2,238,253,168,1,194,254,62,1,79,2,238,253,18,150,1,194,0,1,0,225,1,79,3,207,4,61,0,3,0,0,19,17,33,17,225,2,238,1,79,2,238,253,18,0,0,1,0,0,0,230,4,176,4,226,0,2,0,0,53,1,1,2,88,2,88,230,3,252,252,4,0,1,0,120,0,110,4,116,5,30,0,2,0,0,55,17,1,120,3,252,110,4,176,253,168,0,0,1,0,0,0,170,4,176,4,166,0,2,0,0,37,1,33,2,88,253,168,4,176,170,3,252,0,1,0,60,0,110,4,56,5,30,0,2,0,0,37,1,1,4,56,252,4,3,252,110,2,88,2,88,0,2,0,0,0,230,4,176,4,226,0,2,0,8,0,0,53,1,1,37,39,33,7,1,51,2,88,2,88,252,10,67,3,202,78,254,27,148,230,3,252,252,4,20,130,124,3,56,0,2,0,120,0,110,4,116,5,30,0,2,0,8,0,0,55,17,1,1,39,1,21,1,55,120,3,252,252,154,124,3,56,252,194,130,110,4,176,253,168,254,23,78,1,229,148,1,232,67,0,2,0,0,0,170,4,176,4,166,0,2,0,8,0,0,37,1,33,1,1,23,33,55,1,2,88,253,168,4,176,253,94,1,229,78,252,54,67,1,232,170,3,252,252,174,3,56,124,130,252,194,0,2,0,60,0,110,4,56,5,30,0,2,0,8,0,0,37,1,1,3,17,23,1,53,1,4,56,252,4,3,252,150,130,252,194,3,56,110,2,88,2,88,251,191,3,202,67,254,24,148,254,27,0,3,0,0,0,230,4,176,4,226,0,11,0,14,0,20,0,0,1,34,38,53,52,54,51,50,22,21,20,6,9,2,37,39,33,7,1,51,2,88,31,44,44,31,31,44,44,253,137,2,88,2,88,252,10,67,3,202,78,254,27,148,2,3,44,31,31,44,44,31,31,44,254,227,3,252,252,4,20,130,124,3,56,0,0,3,0,0,0,230,4,176,4,226,0,2,0,5,0,11,0,0,1,33,9,3,37,39,33,7,1,51,2,88,254,22,1,234,253,168,2,88,2,88,252,10,67,3,202,78,254,27,148,1,24,3,56,252,150,3,252,252,4,20,130,124,3,56,0,3,0,0,0,230,4,176,4,226,0,2,0,5,0,11,0,0,1,17,1,23,33,9,2,51,1,39,33,2,88,1,234,110,251,80,2,88,1,158,254,24,148,254,27,78,3,202,1,24,3,56,252,200,50,3,252,252,24,3,62,252,200,124,0,1,0,120,1,94,4,116,4,46,0,2,0,0,19,17,1,120,3,252,1,94,2,208,254,152,0,1,0,60,1,94,4,56,4,46,0,2,0,0,9,2,4,56,252,4,3,252,1,94,1,104,1,104,0,2,0,120,1,94,4,116,4,46,0,2,0,8,0,0,19,17,1,5,39,37,21,37,55,120,3,252,252,154,78,2,143,253,113,78,1,94,2,208,254,152,229,48,214,66,214,48,0,2,0,60,1,94,4,56,4,46,0,2,0,8,0,0,9,2,3,17,23,5,53,5,4,56,252,4,3,252,150,78,253,66,2,190,1,94,1,104,1,104,253,159,1,242,68,229,96,229,0,1,0,131,1,49,4,45,4,78,0,2,0,0,19,1,1,131,1,213,1,213,1,49,3,29,252,227,0,1,0,195,0,241,3,224,4,155,0,2,0,0,55,17,1,195,3,29,241,3,170,254,43,0,0,1,0,131,1,62,4,45,4,91,0,2,0,0,1,1,33,2,88,254,43,3,170,1,62,3,29,0,0,1,0,208,0,241,3,237,4,155,0,2,0,0,37,1,1,3,237,252,227,3,29,241,1,213,1,213,0,2,0,131,1,49,4,45,4,78,0,2,0,8,0,0,19,1,1,37,39,33,7,1,51,131,1,213,1,213,253,51,40,2,64,40,254,223,82,1,49,3,29,252,227,80,70,70,1,235,0,2,0,195,0,241,3,224,4,155,0,2,0,8,0,0,55,17,1,1,39,1,21,1,55,195,3,29,253,121,70,1,235,254,21,70,241,3,170,254,43,254,224,40,1,33,82,1,33,40,0,2,0,131,1,62,4,45,4,91,0,2,0,8,0,0,1,1,33,1,1,23,33,55,1,2,88,254,43,3,170,254,2,1,33,40,253,192,40,1,33,1,62,3,29,253,197,1,235,70,70,254,21,0,0,2,0,208,0,241,3,237,4,155,0,2,0,8,0,0,37,1,1,3,17,23,1,53,1,3,237,252,227,3,29,150,70,254,21,1,235,241,1,213,1,213,253,11,2,64,40,254,223,82,254,223,0,1,0,75,0,185,4,101,4,211,0,2,0,0,37,1,33,4,101,251,230,4,26,185,4,26,0,1,0,75,0,185,4,101,4,211,0,2,0,0,55,1,17,75,4,26,185,4,26,251,230,0,0,1,0,75,0,185,4,101,4,211,0,2,0,0,55,17,1,75,4,26,185,4,26,251,230,0,0,1,0,75,0,185,4,101,4,211,0,2,0,0,55,17,33,75,4,26,185,4,26,0,0,2,0,75,0,185,4,101,4,211,0,2,0,8,0,0,37,1,33,3,7,17,23,33,55,4,101,251,230,4,26,93,57,81,253,68,24,185,4,26,253,23,24,2,188,81,57,0,0,2,0,75,0,185,4,101,4,211,0,2,0,8,0,0,1,17,33,1,1,39,33,7,17,4,101,251,230,3,189,253,116,24,2,188,81,4,211,251,230,2,233,253,116,57,81,2,188,0,0,2,0,75,0,185,4,101,4,211,0,2,0,8,0,0,19,1,33,19,55,17,39,33,7,75,4,26,251,230,93,57,81,2,188,24,4,211,251,230,2,233,24,253,68,81,57,0,0,2,0,75,0,185,4,101,4,211,0,2,0,8,0,0,55,17,33,1,1,23,33,55,17,75,4,26,252,67,2,140,24,253,68,81,185,4,26,253,23,2,140,57,81,253,68,0,0,3,255,150,251,60,5,26,3,80,0,5,0,11,0,15,0,0,1,17,33,21,33,17,33,17,33,53,33,17,1,53,33,21,2,194,2,88,254,124,253,132,254,124,2,88,253,168,5,132,251,60,6,108,212,250,104,5,152,212,249,148,7,64,212,212,0,2,255,150,251,60,3,150,3,80,0,5,0,11,0,0,1,17,33,53,33,17,33,17,33,53,33,17,2,194,252,212,4,0,253,132,254,124,2,88,251,60,7,64,212,247,236,5,152,212,249,148,0,2,1,26,251,60,5,26,3,80,0,5,0,11,0,0,1,17,33,21,33,17,51,17,33,21,33,17,1,26,4,0,252,212,212,2,88,254,124,251,60,8,20,212,248,192,6,108,212,250,104,0,0,2,255,150,0,212,5,26,3,80,0,3,0,7,0,0,3,53,33,21,1,53,33,21,106,5,132,250,124,5,132,2,124,212,212,254,88,212,212,0,0,3,255,150,0,212,5,26,8,232,0,5,0,9,0,15,0,0,1,17,51,17,33,21,1,53,33,21,1,53,33,17,51,17,2,194,212,1,132,250,124,5,132,250,124,1,132,212,2,124,6,108,250,104,212,254,88,212,212,1,168,212,5,152,249,148,0,2,255,150,0,212,3,150,8,232,0,5,0,11,0,0,39,53,33,17,51,17,1,53,33,17,51,17,106,3,44,212,252,0,1,132,212,212,212,7,64,247,236,1,168,212,5,152,249,148,0,2,1,26,0,212,5,26,8,232,0,5,0,11,0,0,37,17,51,17,33,21,1,17,51,17,33,21,1,26,212,3,44,253,168,212,1,132,212,8,20,248,192,212,1,168,6,108,250,104,212,0,0,2,1,26,251,60,3,150,8,232,0,3,0,7,0,0,1,17,51,17,33,17,51,17,2,194,212,253,132,212,251,60,13,172,242,84,13,172,242,84,0,4,255,150,251,60,5,26,8,232,0,5,0,11,0,17,0,23,0,0,1,17,51,17,33,21,1,17,33,53,33,17,51,17,33,21,33,17,1,53,33,17,51,17,2,194,212,1,132,252,0,254,124,2,88,212,2,88,254,124,252,0,1,132,212,2,124,6,108,250,104,212,248,192,5,152,212,249,148,6,108,212,250,104,7,64,212,5,152,249,148,0,0,3,255,150,251,60,3,150,8,232,0,5,0,11,0,15,0,0,3,53,33,17,51,17,3,17,33,53,33,17,51,17,51,17,106,1,132,212,212,254,124,2,88,212,212,2,124,212,5,152,249,148,248,192,5,152,212,249,148,13,172,242,84,0,0,3,1,26,251,60,5,26,8,232,0,5,0,11,0,15,0,0,1,17,51,17,33,21,1,17,33,21,33,17,33,17,51,17,2,194,212,1,132,253,168,2,88,254,124,253,132,212,2,124,6,108,250,104,212,248,192,6,108,212,250,104,13,172,242,84,0,1,255,150,251,60,5,26,2,124,0,11,0,0,1,17,33,53,33,21,33,17,35,17,35,17,1,26,254,124,5,132,254,124,212,212,251,60,6,108,212,212,249,148,6,108,249,148,0,1,255,150,251,60,3,150,2,124,0,9,0,0,1,17,33,53,33,17,35,17,35,17,1,26,254,124,4,0,212,212,251,60,6,108,212,248,192,6,108,249,148,0,0,1,1,26,251,60,5,26,2,124,0,9,0,0,1,17,33,21,33,17,35,17,35,17,1,26,4,0,254,124,212,212,251,60,7,64,212,249,148,6,108,249,148,0,0,1,255,150,251,60,5,26,2,124,0,7,0,0,1,17,33,53,33,21,33,17,1,132,254,18,5,132,254,18,251,60,6,108,212,212,249,148,0,1,255,150,251,60,3,44,2,124,0,5,0,0,1,17,33,53,33,17,1,132,254,18,3,150,251,60,6,108,212,248,192,0,0,1,255,150,251,60,3,44,8,232,0,9,0,0,1,17,33,53,33,17,51,17,51,17,1,132,254,18,2,88,212,106,251,60,6,108,212,6,108,249,148,248,192,0,0,1,1,132,251,60,5,26,2,124,0,5,0,0,1,17,33,21,33,17,1,132,3,150,254,18,251,60,7,64,212,249,148,0,0,1,1,132,251,60,5,26,8,232,0,9,0,0,1,17,51,17,51,17,33,21,33,17,1,132,106,212,2,88,254,18,251,60,7,64,6,108,249,148,212,249,148,0,0,1,255,150,251,60,5,26,8,232,0,11,0,0,1,17,33,53,33,17,51,17,33,21,33,17,1,132,254,18,2,88,212,2,88,254,18,251,60,6,108,212,6,108,249,148,212,249,148,0,0,1,255,150,251,60,5,26,2,230,0,7,0,0,1,17,33,17,33,17,33,17,1,238,253,168,5,132,253,168,251,60,6,2,1,168,254,88,249,254,0,1,255,150,251,60,2,194,2,230,0,5,0,0,1,17,33,17,33,17,1,238,253,168,3,44,251,60,6,2,1,168,248,86,0,1,255,150,251,60,3,44,8,232,0,9,0,0,1,17,33,17,33,17,33,17,35,17,1,238,253,168,1,238,1,168,106,251,60,6,2,1,168,6,2,248,86,249,254,0,0,1,1,238,251,60,5,26,2,230,0,5,0,0,1,17,33,17,33,17,1,238,3,44,253,168,251,60,7,170,254,88,249,254,0,1,1,132,251,60,5,26,8,232,0,9,0,0,1,17,35,17,33,17,33,17,33,17,1,238,106,1,168,1,238,253,168,251,60,6,2,7,170,249,254,254,88,249,254,0,0,1,255,150,251,60,5,26,8,232,0,11,0,0,1,17,33,17,33,17,33,17,33,17,33,17,1,238,253,168,1,238,1,168,1,238,253,168,251,60,6,2,1,168,6,2,249,254,254,88,249,254,0,2,255,150,251,60,5,26,3,80,0,7,0,11,0,0,1,17,33,53,33,21,33,17,1,53,33,21,1,238,253,168,5,132,253,168,252,212,5,132,251,60,5,152,212,212,250,104,7,64,212,212,0,1,255,150,251,60,2,194,3,80,0,9,0,0,1,17,33,53,33,53,33,53,33,17,1,238,253,168,2,88,253,168,3,44,251,60,5,152,212,212,212,247,236,0,0,1,1,238,251,60,5,26,3,80,0,9,0,0,1,17,33,21,33,21,33,21,33,17,1,238,3,44,253,168,2,88,253,168,251,60,8,20,212,212,212,250,104,0,0,2,0,150,1,62,4,26,2,230,0,3,0,7,0,0,1,17,33,17,33,17,33,17,2,238,1,44,252,124,1,44,1,62,1,168,254,88,1,168,254,88,0,2,1,132,255,58,3,44,4,233,0,3,0,7,0,0,1,17,33,17,1,17,33,17,1,132,1,168,254,88,1,168,3,4,1,229,254,27,252,54,1,229,254,27,0,1,1,132,251,60,3,44,2,124,0,3,0,0,1,17,33,17,1,132,1,168,251,60,7,64,248,192,0,1,255,150,251,60,5,26,2,230,0,7,0,0,1,17,33,17,33,17,33,17,1,132,254,18,5,132,254,18,251,60,6,2,1,168,254,88,249,254,0,1,255,150,251,60,3,44,2,230,0,5,0,0,1,17,33,17,33,17,1,132,254,18,3,150,251,60,6,2,1,168,248,86,0,1,1,132,251,60,5,26,2,230,0,5,0,0,1,17,33,17,33,17,1,132,3,150,254,18,251,60,7,170,254,88,249,254,0,1,255,150,1,62,5,26,2,230,0,3,0,0,3,17,33,17,106,5,132,1,62,1,168,254,88,0,0,1,255,150,1,62,2,194,2,230,0,3,0,0,3,17,33,17,106,3,44,1,62,1,168,254,88,0,0,1,255,150,1,62,5,26,2,230,0,7,0,0,3,17,33,21,33,21,33,21,106,3,44,2,88,253,168,1,62,1,168,106,212,106,0,4,0,37,1,62,4,138,2,230,0,3,0,7,0,11,0,15,0,0,1,17,51,17,33,17,51,17,51,17,51,17,51,17,51,17,3,169,225,251,155,225,75,225,75,225,1,62,1,168,254,88,1,168,254,88,1,168,254,88,1,168,254,88,0,4,1,132,254,132,3,44,5,159,0,3,0,7,0,11,0,15,0,0,1,17,33,17,1,17,33,17,1,17,33,17,1,17,33,17,1,132,1,168,254,88,1,168,254,88,1,168,254,88,1,168,4,51,1,108,254,148,250,81,1,108,254,148,1,229,1,108,254,148,1,229,1,108,254,148,0,1,1,238,1,62,5,26,2,230,0,3,0,0,1,17,33,17,1,238,3,44,1,62,1,168,254,88,0,3,0,66,1,62,4,109,2,230,0,3,0,7,0,11,0,0,1,17,33,17,33,17,33,17,51,17,33,17,3,98,1,11,251,213,1,11,133,1,11,1,62,1,168,254,88,1,168,254,88,1,168,254,88,0,0,3,1,132,254,179,3,44,5,110,0,3,0,7,0,11,0,0,1,17,33,17,1,17,33,17,1,17,33,17,1,132,1,168,254,88,1,168,254,88,1,168,3,191,1,175,254,81,250,244,1,175,254,81,2,134,1,175,254,81,0,1,1,132,1,168,3,44,8,232,0,3,0,0,1,17,33,17,1,132,1,168,1,168,7,64,248,192,0,1,255,150,1,62,5,26,8,232,0,7,0,0,3,17,33,17,33,17,33,17,106,1,238,1,168,1,238,1,62,1,168,6,2,249,254,254,88,0,0,1,255,150,1,62,3,44,8,232,0,5,0,0,3,17,33,17,33,17,106,1,238,1,168,1,62,1,168,6,2,248,86,0,0,1,1,132,251,60,3,44,8,232,0,7,0,0,1,17,35,17,33,17,35,17,1,238,106,1,168,106,251,60,6,108,7,64,248,192,249,148,0,1,1,132,1,62,5,26,8,232,0,5,0,0,1,17,33,17,33,17,1,132,1,168,1,238,1,62,7,170,249,254,254,88,0,1,1,132,251,60,3,44,8,232,0,3,0,0,1,17,33,17,1,132,1,168,251,60,13,172,242,84,0,1,255,150,251,60,5,26,8,232,0,11,0,0,1,17,33,17,33,17,33,17,33,17,33,17,1,132,254,18,1,238,1,168,1,238,254,18,251,60,6,2,1,168,6,2,249,254,254,88,249,254,0,1,255,150,251,60,3,44,8,232,0,7,0,0,1,17,33,17,33,17,33,17,1,132,254,18,1,238,1,168,251,60,6,2,1,168,6,2,242,84,0,1,1,132,251,60,5,26,8,232,0,7,0,0,1,17,33,17,33,17,33,17,1,132,1,168,1,238,254,18,251,60,13,172,249,254,254,88,249,254,0,1,255,150,251,60,5,26,8,232,0,13,0,0,1,17,33,17,33,17,51,17,51,21,33,21,33,17,1,132,254,18,2,88,212,106,1,238,254,18,251,60,6,2,1,168,6,2,249,254,106,212,249,148,0,1,255,150,251,60,5,26,2,230,0,9,0,0,1,17,33,17,33,21,33,21,33,17,1,238,253,168,3,44,2,88,253,168,251,60,6,2,1,168,106,212,249,148,0,1,255,150,1,62,5,26,8,232,0,9,0,0,3,17,33,17,51,17,33,21,33,21,106,2,88,212,2,88,253,168,1,62,1,168,6,2,249,148,212,106,0,1,255,150,251,60,5,26,8,232,0,11,0,0,1,17,33,17,33,17,51,17,33,21,33,17,1,238,253,168,2,88,212,2,88,253,168,251,60,6,2,1,168,6,2,249,148,212,249,148,0,1,255,150,251,60,5,26,2,230,0,9,0,0,1,17,33,53,33,53,33,17,33,17,1,132,254,18,1,238,3,150,254,18,251,60,6,108,212,106,254,88,249,254,0,1,255,150,1,62,5,26,8,232,0,9,0,0,1,53,33,53,33,17,33,17,33,17,1,132,254,18,1,238,1,168,1,238,1,62,106,212,6,108,249,254,254,88,0,1,255,150,251,60,5,26,8,232,0,11,0,0,1,17,33,53,33,17,33,17,33,17,33,17,1,132,254,18,1,238,1,168,1,238,254,18,251,60,6,108,212,6,108,249,254,254,88,249,254,0,0,1,255,150,251,60,5,26,8,232,0,13,0,0,1,17,33,17,33,17,33,17,33,21,33,21,35,17,1,238,253,168,1,238,1,168,1,238,254,18,106,251,60,6,2,1,168,6,2,249,148,212,106,249,254,0,0,1,255,150,251,60,2,194,2,124,0,15,0,0,1,17,52,46,2,35,35,53,51,50,4,22,18,21,17,1,238,77,136,179,102,106,106,146,1,0,194,110,251,60,4,126,102,179,136,77,212,110,194,255,0,146,251,130,0,1,1,238,251,60,5,26,2,124,0,15,0,0,1,17,52,18,54,36,51,51,21,35,34,14,2,21,17,1,238,110,194,1,0,146,106,106,102,179,136,77,251,60,4,126,146,1,0,194,110,212,77,136,179,102,251,130,0,1,255,150,1,168,2,194,8,232,0,15,0,0,3,53,51,50,62,2,53,17,51,17,20,2,6,4,35,106,106,102,179,136,77,212,110,194,255,0,146,1,168,212,77,136,179,102,4,126,251,130,146,255,0,194,110,0,0,1,1,238,1,168,5,26,8,232,0,15,0,0,1,34,36,38,2,53,17,51,17,20,30,2,51,51,21,4,176,146,255,0,194,110,212,77,136,179,102,106,1,168,110,194,1,0,146,4,126,251,130,102,179,136,77,212,0,1,0,0,254,72,4,176,5,220,0,15,0,0,17,53,1,1,53,51,1,1,51,21,1,1,21,35,1,1,1,219,254,37,125,1,219,1,219,125,254,37,1,219,125,254,37,254,37,254,72,202,3,0,3,0,202,253,0,3,0,202,253,0,253,0,202,3,0,253,0,0,0,1,0,0,254,72,4,176,5,220,0,5,0,0,1,1,53,51,1,21,4,51,251,205,125,4,51,254,72,6,202,202,249,54,202,0,0,1,0,0,254,72,4,176,5,220,0,5,0,0,17,53,1,51,21,1,4,51,125,251,205,254,72,202,6,202,202,249,54,0,0,2,0,150,1,168,4,26,2,124,0,3,0,7,0,0,1,53,33,21,33,53,33,21,2,238,1,44,252,124,1,44,1,168,212,212,212,212,0,2,1,238,255,58,2,194,4,233,0,3,0,7,0,0,1,17,51,17,3,17,51,17,1,238,212,212,212,3,4,1,229,254,27,252,54,1,229,254,27,0,0,1,1,238,251,60,2,194,2,124,0,3,0,0,1,17,51,17,1,238,212,251,60,7,64,248,192,0,0,1,255,150,251,60,5,26,2,124,0,7,0,0,1,17,33,53,33,21,33,17,1,238,253,168,5,132,253,168,251,60,6,108,212,212,249,148,0,1,255,150,251,60,2,194,2,124,0,5,0,0,1,17,33,53,33,17,1,238,253,168,3,44,251,60,6,108,212,248,192,0,0,1,1,238,251,60,5,26,2,124,0,5,0,0,1,17,33,21,33,17,1,238,3,44,253,168,251,60,7,64,212,249,148,0,0,1,255,150,1,168,5,26,2,124,0,3,0,0,3,53,33,21,106,5,132,1,168,212,212,0,0,1,255,150,1,168,2,194,2,124,0,3,0,0,3,53,33,21,106,3,44,1,168,212,212,0,0,1,255,150,1,62,5,26,2,230,0,7,0,0,1,53,33,53,33,53,33,17,1,238,253,168,2,88,3,44,1,62,106,212,106,254,88,0,0,4,0,37,1,168,4,138,2,124,0,3,0,7,0,11,0,15,0,0,1,53,51,21,33,53,51,21,51,53,51,21,51,53,51,21,3,169,225,251,155,225,75,225,75,225,1,168,212,212,212,212,212,212,212,212,0,4,1,238,254,132,2,194,5,159,0,3,0,7,0,11,0,15,0,0,1,17,51,17,3,17,51,17,3,17,51,17,3,17,51,17,1,238,212,212,212,212,212,212,212,4,51,1,108,254,148,250,81,1,108,254,148,1,229,1,108,254,148,1,229,1,108,254,148,0,0,1,1,238,1,168,5,26,2,124,0,3,0,0,1,53,33,21,1,238,3,44,1,168,212,212,0,3,0,66,1,168,4,109,2,124,0,3,0,7,0,11,0,0,1,53,33,21,33,53,33,21,51,53,33,21,3,98,1,11,251,213,1,11,133,1,11,1,168,212,212,212,212,212,212,0,0,3,1,238,254,179,2,194,5,110,0,3,0,7,0,11,0,0,1,17,51,17,3,17,51,17,3,17,51,17,1,238,212,212,212,212,212,3,191,1,175,254,81,250,244,1,175,254,81,2,134,1,175,254,81,0,0,1,1,238,1,168,2,194,8,232,0,3,0,0,1,17,51,17,1,238,212,1,168,7,64,248,192,0,0,1,1,132,251,60,3,44,8,232,0,7,0,0,1,17,51,17,51,17,51,17,1,132,106,212,106,251,60,7,64,6,108,249,148,248,192,0,0,1,255,150,1,168,5,26,8,232,0,7,0,0,3,53,33,17,51,17,33,21,106,2,88,212,2,88,1,168,212,6,108,249,148,212,0,1,255,150,1,168,2,194,8,232,0,5,0,0,3,53,33,17,51,17,106,2,88,212,1,168,212,6,108,248,192,0,0,1,1,238,1,168,5,26,8,232,0,5,0,0,1,17,51,17,33,21,1,238,212,2,88,1,168,7,64,249,148,212,0,1,1,238,251,60,2,194,8,232,0,3,0,0,1,17,51,17,1,238,212,251,60,13,172,242,84,0,0,1,255,150,251,60,5,26,8,232,0,11,0,0,1,17,33,53,33,17,51,17,33,21,33,17,1,238,253,168,2,88,212,2,88,253,168,251,60,6,108,212,6,108,249,148,212,249,148,0,0,1,255,150,251,60,2,194,8,232,0,7,0,0,1,17,33,53,33,17,51,17,1,238,253,168,2,88,212,251,60,6,108,212,6,108,242,84,0,1,1,238,251,60,5,26,8,232,0,7,0,0,1,17,51,17,33,21,33,17,1,238,212,2,88,253,168,251,60,13,172,249,148,212,249,148,0,1,255,150,251,60,5,26,8,232,0,13,0,0,1,17,33,53,33,53,51,17,51,17,33,17,33,17,1,132,254,18,1,238,106,212,2,88,254,18,251,60,6,108,212,106,6,2,249,254,254,88,249,254,0,1,255,150,251,60,5,26,2,230,0,9,0,0,1,17,33,53,33,53,33,17,33,17,1,238,253,168,2,88,3,44,253,168,251,60,6,108,212,106,254,88,249,254,0,1,255,150,1,62,5,26,8,232,0,9,0,0,1,53,33,53,33,17,51,17,33,17,1,238,253,168,2,88,212,2,88,1,62,106,212,6,108,249,254,254,88,0,0,1,255,150,251,60,5,26,8,232,0,11,0,0,1,17,33,53,33,17,51,17,33,17,33,17,1,238,253,168,2,88,212,2,88,253,168,251,60,6,108,212,6,108,249,254,254,88,249,254,0,1,255,150,251,60,5,26,2,230,0,9,0,0,1,17,33,17,33,21,33,21,33,17,1,132,254,18,3,150,1,238,254,18,251,60,6,2,1,168,106,212,249,148,0,1,255,150,1,62,5,26,8,232,0,9,0,0,3,17,33,17,33,17,33,21,33,21,106,1,238,1,168,1,238,254,18,1,62,1,168,6,2,249,148,212,106,0,0,1,255,150,251,60,5,26,8,232,0,11,0,0,1,17,33,17,33,17,33,17,33,21,33,17,1,132,254,18,1,238,1,168,1,238,254,18,251,60,6,2,1,168,6,2,249,148,212,249,148,0,0,1,255,150,251,60,5,26,8,232,0,13,0,0,1,17,35,53,33,53,33,17,33,17,33,17,33,17,1,238,106,254,18,1,238,1,168,1,238,253,168,251,60,6,2,106,212,6,108,249,254,254,88,249,254,0,0,1,255,150,1,168,5,26,8,232,0,11,0,0,3,53,33,17,51,17,51,17,51,17,33,21,106,1,132,212,212,212,1,132,1,168,212,6,108,249,148,6,108,249,148,212,0,1,255,150,1,168,3,150,8,232,0,9,0,0,3,53,33,17,51,17,51,17,51,17,106,1,132,212,212,212,1,168,212,6,108,249,148,6,108,248,192,0,0,1,1,26,1,168,5,26,8,232,0,9,0,0,1,17,51,17,51,17,51,17,33,21,1,26,212,212,212,1,132,1,168,7,64,249,148,6,108,249,148,212,0,1,255,150,251,60,5,26,8,232,0,11,0,0,1,17,33,53,33,17,33,17,33,21,33,17,1,238,253,168,1,238,1,168,1,238,253,168,251,60,6,108,212,6,108,249,148,212,249,148,0,1,255,150,1,168,5,26,8,232,0,7,0,0,3,53,33,17,33,17,33,21,106,1,238,1,168,1,238,1,168,212,6,108,249,148,212,0,0,1,255,150,251,60,3,44,8,232,0,9,0,0,1,17,33,53,33,17,33,17,35,17,1,238,253,168,1,238,1,168,106,251,60,6,108,212,6,108,248,192,249,148,0,1,255,150,1,168,3,44,8,232,0,5,0,0,3,53,33,17,33,17,106,1,238,1,168,1,168,212,6,108,248,192,0,1,1,132,251,60,5,26,8,232,0,9,0,0,1,17,35,17,33,17,33,21,33,17,1,238,106,1,168,1,238,253,168,251,60,6,108,7,64,249,148,212,249,148,0,1,1,132,1,168,5,26,8,232,0,5,0,0,1,17,33,17,33,21,1,132,1,168,1,238,1,168,7,64,249,148,212,0,0,1,255,150,251,60,5,26,8,232,0,11,0,0,1,17,33,17,33,17,51,17,33,17,33,17,1,132,254,18,2,88,212,2,88,254,18,251,60,6,2,1,168,6,2,249,254,254,88,249,254,0,0,1,255,150,1,62,5,26,8,232,0,7,0,0,3,17,33,17,51,17,33,17,106,2,88,212,2,88,1,62,1,168,6,2,249,254,254,88,0,1,255,150,251,60,3,44,8,232,0,9,0,0,1,17,33,17,33,17,51,17,51,17,1,132,254,18,2,88,212,106,251,60,6,2,1,168,6,2,249,254,248,86,0,1,255,150,1,62,2,194,8,232,0,5,0,0,3,17,33,17,51,17,106,2,88,212,1,62,1,168,6,2,248,86,0,1,1,132,251,60,5,26,8,232,0,9,0,0,1,17,51,17,51,17,33,17,33,17,1,132,106,212,2,88,254,18,251,60,7,170,6,2,249,254,254,88,249,254,0,1,1,238,1,62,5,26,8,232,0,5,0,0,1,17,51,17,33,17,1,238,212,2,88,1,62,7,170,249,254,254,88,0,0,2,255,150,0,212,5,26,8,232,0,7,0,11,0,0,3,53,33,17,51,17,33,21,1,53,33,21,106,2,88,212,2,88,250,124,5,132,2,124,212,5,152,250,104,212,254,88,212,212,0,1,255,150,0,212,2,194,8,232,0,9,0,0,39,53,33,53,33,53,33,17,51,17,106,2,88,253,168,2,88,212,212,212,212,212,5,152,247,236,0,1,1,238,0,212,5,26,8,232,0,9,0,0,37,17,51,17,33,21,33,21,33,21,1,238,212,2,88,253,168,2,88,212,8,20,250,104,212,212,212,0,0,1,255,150,251,60,5,26,8,232,0,19,0,0,1,17,33,53,33,17,51,17,51,17,51,17,33,21,33,17,35,17,35,17,1,26,254,124,1,132,212,212,212,1,132,254,124,212,212,251,60,6,108,212,6,108,249,148,6,108,249,148,212,249,148,6,108,249,148,0,0,2,255,150,251,60,3,150,8,232,0,7,0,11,0,0,1,17,33,53,33,17,51,17,51,17,51,17,1,26,254,124,1,132,212,212,212,251,60,6,108,212,6,108,242,84,13,172,242,84,0,2,1,26,251,60,5,26,8,232,0,7,0,11,0,0,1,17,51,17,33,21,33,17,33,17,51,17,2,194,212,1,132,254,124,253,132,212,251,60,13,172,249,148,212,249,148,13,172,242,84,0,0,1,255,150,251,60,5,26,8,232,0,11,0,0,1,17,33,53,33,17,33,17,33,21,33,17,1,132,254,18,1,238,1,168,1,238,254,18,251,60,6,108,212,6,108,249,148,212,249,148,0,1,255,150,251,60,3,44,8,232,0,7,0,0,1,17,33,53,33,17,33,17,1,132,254,18,1,238,1,168,251,60,6,108,212,6,108,242,84,0,0,1,1,132,251,60,5,26,8,232,0,7,0,0,1,17,33,17,33,21,33,17,1,132,1,168,1,238,254,18,251,60,13,172,249,148,212,249,148,0,0,1,255,150,251,60,5,26,8,232,0,11,0,0,1,17,33,17,33,17,51,17,33,17,33,17,1,238,253,168,2,88,212,2,88,253,168,251,60,6,2,1,168,6,2,249,254,254,88,249,254,0,0,1,255,150,251,60,2,194,8,232,0,7,0,0,1,17,33,17,33,17,51,17,1,238,253,168,2,88,212,251,60,6,2,1,168,6,2,242,84,0,0,1,1,238,251,60,5,26,8,232,0,7,0,0,1,17,51,17,33,17,33,17,1,238,212,2,88,253,168,251,60,13,172,249,254,254,88,249,254,0,0,1,255,150,251,60,5,26,8,232,0,19,0,0,1,17,33,53,33,53,33,53,33,17,51,17,33,21,33,21,33,21,33,17,1,238,253,168,2,88,253,168,2,88,212,2,88,253,168,2,88,253,168,251,60,5,152,212,212,212,5,152,250,104,212,212,212,250,104,0,0,1,255,150,251,60,2,194,8,232,0,11,0,0,1,17,33,53,33,53,33,53,33,17,51,17,1,238,253,168,2,88,253,168,2,88,212,251,60,5,152,212,212,212,5,152,242,84,0,1,1,238,251,60,5,26,8,232,0,11,0,0,1,17,51,17,33,21,33,21,33,21,33,17,1,238,212,2,88,253,168,2,88,253,168,251,60,13,172,250,104,212,212,212,250,104,0,1,0,0,254,32,4,176,255,73,0,3,0,0,17,17,33,17,4,176,254,32,1,41,254,215,0,1,0,0,254,32,4,176,0,115,0,3,0,0,17,17,33,17,4,176,254,32,2,83,253,173,0,1,0,0,254,32,4,176,1,156,0,3,0,0,17,17,33,17,4,176,254,32,3,124,252,132,0,1,0,0,254,32,4,176,2,198,0,3,0,0,17,17,33,17,4,176,254,32,4,166,251,90,0,1,0,0,254,32,4,176,3,239,0,3,0,0,17,17,33,17,4,176,254,32,5,207,250,49,0,1,0,0,254,32,4,176,5,25,0,3,0,0,17,17,33,17,4,176,254,32,6,249,249,7,0,1,0,0,254,32,4,176,6,66,0,3,0,0,17,17,33,17,4,176,254,32,8,34,247,222,0,1,0,0,254,32,4,176,7,108,0,3,0,0,17,17,33,17,4,176,254,32,9,76,246,180,0,1,0,0,2,18,4,176,7,108,0,3,0,0,17,17,33,17,4,176,2,18,5,90,250,166,0,1,0,0,6,66,4,176,7,108,0,3,0,0,17,17,33,17,4,176,6,66,1,42,254,214,0,1,0,0,254,32,0,150,7,108,0,3,0,0,17,17,51,17,150,254,32,9,76,246,180,0,0,1,0,0,254,32,1,44,7,108,0,3,0,0,17,17,33,17,1,44,254,32,9,76,246,180,0,1,0,0,254,32,1,194,7,108,0,3,0,0,17,17,33,17,1,194,254,32,9,76,246,180,0,1,0,0,254,32,2,88,7,108,0,3,0,0,17,17,33,17,2,88,254,32,9,76,246,180,0,1,0,0,254,32,2,238,7,108,0,3,0,0,17,17,33,17,2,238,254,32,9,76,246,180,0,1,0,0,254,32,3,132,7,108,0,3,0,0,17,17,33,17,3,132,254,32,9,76,246,180,0,1,0,0,254,32,4,26,7,108,0,3,0,0,17,17,33,17,4,26,254,32,9,76,246,180,0,1,2,88,254,32,4,176,7,108,0,3,0,0,1,17,33,17,2,88,2,88,254,32,9,76,246,180,0,1,4,26,254,32,4,176,7,108,0,3,0,0,1,17,51,17,4,26,150,254,32,9,76,246,180,0,0,1,0,0,254,32,2,88,2,198,0,3,0,0,17,17,33,17,2,88,254,32,4,166,251,90,0,1,2,88,254,32,4,176,2,18,0,3,0,0,1,17,33,17,2,88,2,88,254,32,3,242,252,14,0,1,0,0,2,18,2,88,7,108,0,3,0,0,17,17,33,17,2,88,2,18,5,90,250,166,0,1,0,0,254,32,4,176,7,108,0,5,0,0,17,17,33,17,33,17,2,88,2,88,254,32,9,76,251,90,251,90,0,2,0,0,254,32,4,176,7,108,0,3,0,7,0,0,17,17,33,25,2,33,17,2,88,2,88,2,18,5,90,250,166,252,14,3,242,252,14,0,0,1,0,0,254,32,4,176,7,108,0,5,0,0,17,17,33,17,33,17,4,176,253,168,254,32,9,76,250,166,252,14,0,1,0,0,254,32,4,176,7,108,0,5,0,0,1,17,33,17,33,17,2,88,253,168,4,176,254,32,3,242,5,90,246,180,0,1,2,88,2,18,4,176,7,108,0,3,0,0,1,17,33,17,2,88,2,88,2,18,5,90,250,166,0,1,0,0,254,32,4,176,7,108,0,7,0,0,17,17,33,17,33,17,33,17,2,88,2,88,253,168,254,32,4,166,4,166,250,166,252,14,0,1,0,0,254,32,4,176,7,108,0,5,0,0,17,17,33,17,33,17,2,88,2,88,254,32,4,166,4,166,246,180,0,9,0,0,254,32,4,176,7,108,0,3,0,7,0,11,0,14,0,18,0,22,0,26,0,30,0,34,0,0,17,53,1,21,1,1,21,1,33,1,21,1,33,55,21,33,39,1,21,1,53,1,21,1,53,1,51,1,53,1,51,1,53,1,51,4,176,252,204,3,52,252,244,1,104,1,164,254,132,1,104,20,251,100,20,4,176,251,80,4,176,251,80,1,104,40,254,112,2,248,40,252,224,4,136,40,1,44,40,4,176,40,248,68,3,52,40,252,244,1,164,40,254,132,20,20,20,4,176,40,252,224,40,4,176,40,1,144,40,1,104,252,224,40,2,248,251,80,40,4,136,0,0,18,0,0,254,32,4,176,7,108,0,3,0,7,0,11,0,15,0,19,0,23,0,26,0,30,0,34,0,38,0,42,0,46,0,50,0,54,0,58,0,62,0,66,0,70,0,0,17,53,1,21,1,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,55,21,7,51,55,21,33,39,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,37,53,55,51,3,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,4,176,252,4,3,252,252,44,160,3,52,252,244,160,2,108,253,188,160,1,164,254,132,160,220,180,160,20,251,100,20,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,160,40,200,1,104,40,254,112,2,48,40,253,168,2,248,40,252,224,3,192,40,252,24,4,136,40,1,244,40,4,176,40,247,124,3,252,40,252,44,3,52,40,252,244,2,108,40,253,188,1,164,40,254,132,220,40,180,20,20,20,4,176,40,252,24,40,4,176,40,252,24,40,4,176,40,252,24,40,4,176,40,252,24,40,4,176,40,200,40,160,254,112,40,1,104,253,168,40,2,48,252,224,40,2,248,252,24,40,3,192,251,80,40,4,136,0,0,36,0,0,254,32,4,176,7,108,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,35,0,39,0,43,0,47,0,50,0,54,0,58,0,62,0,66,0,70,0,74,0,78,0,82,0,86,0,90,0,94,0,98,0,102,0,106,0,110,0,114,0,118,0,122,0,126,0,130,0,134,0,138,0,142,0,0,17,53,1,21,1,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,1,21,1,51,55,21,7,51,55,21,7,51,55,21,33,39,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,1,53,1,21,37,53,55,51,7,53,55,51,3,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,1,53,1,51,4,176,251,160,4,96,251,200,60,3,252,252,44,60,3,152,252,144,60,3,52,252,244,60,2,208,253,88,60,2,108,253,188,60,2,8,254,32,60,1,164,254,132,60,1,64,254,232,60,220,180,60,120,80,60,20,251,100,20,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,4,176,251,80,60,40,100,160,40,200,1,4,40,254,212,1,104,40,254,112,1,204,40,254,12,2,48,40,253,168,2,148,40,253,68,2,248,40,252,224,3,92,40,252,124,3,192,40,252,24,4,36,40,251,180,4,136,40,2,88,40,4,176,40,247,24,4,96,40,251,200,3,252,40,252,44,3,152,40,252,144,3,52,40,252,244,2,208,40,253,88,2,108,40,253,188,2,8,40,254,32,1,164,40,254,132,1,64,40,254,232,220,40,180,120,40,80,20,20,20,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,251,180,40,4,176,40,100,40,60,200,40,160,254,212,40,1,4,254,112,40,1,104,254,12,40,1,204,253,168,40,2,48,253,68,40,2,148,252,224,40,2,248,252,124,40,3,92,252,24,40,3,192,251,180,40,4,36,251,80,40,4,136,0,0,3,0,0,0,8,4,176,4,248,0,20,0,56,0,68,0,30,64,20,24,28,25,46,45,0,20,50,39,57,58,64,63,9,14,60,21,105,10,60,0,47,51,43,23,57,48,49,1,46,2,39,46,3,39,55,30,3,23,30,3,23,1,34,38,39,55,22,22,51,50,54,53,52,46,2,53,52,54,51,50,22,21,20,6,7,23,62,2,51,50,22,21,20,6,6,19,39,18,33,50,22,23,7,38,38,35,34,3,252,16,74,155,137,135,186,122,74,23,180,33,76,99,134,90,120,164,108,71,27,252,236,147,192,73,86,53,63,30,29,36,58,77,58,105,94,84,102,38,7,35,21,43,68,58,95,114,116,209,137,180,138,1,2,89,147,52,104,38,95,47,151,1,190,86,111,83,44,43,84,100,135,95,40,86,109,69,49,27,36,70,91,129,95,254,14,76,69,138,41,37,34,34,44,58,58,81,65,95,104,102,84,52,90,20,14,55,91,55,113,94,123,185,102,3,55,68,1,117,66,66,144,44,42,0,5,0,0,0,110,4,176,5,30,0,15,0,30,0,42,0,58,0,70,0,30,64,18,16,21,58,30,36,64,6,42,8,50,106,0,42,105,8,0,105,8,0,47,43,43,43,17,23,57,48,49,37,34,36,2,53,52,18,36,51,50,4,18,21,20,2,4,39,34,38,53,52,51,58,2,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,19,50,54,54,53,52,38,38,35,34,6,6,21,20,22,22,1,34,38,53,52,54,51,50,22,21,20,6,2,88,181,254,242,149,149,1,14,181,181,1,14,149,149,254,242,186,139,169,66,67,181,186,72,35,31,181,254,158,59,72,72,59,59,72,72,151,141,209,116,116,209,141,140,210,116,116,210,1,94,59,72,72,59,59,72,72,110,149,1,14,181,181,1,14,149,149,254,242,181,181,254,242,149,219,136,112,66,29,37,112,136,1,174,72,59,59,72,72,59,59,72,253,253,116,210,140,141,209,116,116,209,141,140,210,116,2,3,72,59,59,72,72,59,59,72,0,0,4,0,0,0,110,4,176,5,30,0,15,0,30,0,42,0,54,0,20,64,11,16,21,30,42,48,36,6,8,0,105,8,0,47,43,23,57,48,49,37,34,36,2,53,52,18,36,51,50,4,18,21,20,2,4,39,50,54,53,52,38,35,42,2,35,34,21,20,22,3,50,54,53,52,38,35,34,6,21,20,22,33,50,54,53,52,38,35,34,6,21,20,22,2,88,181,254,242,149,149,1,14,181,181,1,14,149,149,254,242,186,149,181,31,35,72,186,181,67,66,169,66,59,72,72,59,59,72,72,1,223,59,72,72,59,59,72,72,110,149,1,14,181,181,1,14,149,149,254,242,181,181,254,242,149,219,136,112,37,29,66,112,136,1,174,72,59,59,72,72,59,59,72,72,59,59,72,72,59,59,72,0,10,0,31,0,139,4,148,5,0,0,11,0,15,0,19,0,23,0,35,0,39,0,43,0,47,0,51,0,55,0,54,64,39,12,40,43,13,15,41,14,42,44,23,22,45,52,36,53,39,37,55,54,38,20,49,19,0,24,105,19,0,106,49,19,105,6,30,105,49,6,106,49,0,47,43,43,43,43,43,17,18,23,57,48,49,1,34,38,53,52,54,51,50,22,21,20,6,5,39,55,23,19,17,51,17,1,39,33,21,5,50,54,53,52,38,35,34,6,21,20,22,3,39,55,23,1,39,55,23,3,53,33,21,1,17,51,17,23,39,55,23,2,88,160,195,195,160,161,194,194,253,249,87,198,86,102,122,253,137,1,1,23,1,34,93,112,112,93,93,112,112,155,197,86,197,2,11,199,86,199,157,1,26,253,137,122,186,86,199,86,1,99,195,160,161,194,194,161,160,195,92,86,197,86,254,191,1,23,254,234,1,252,122,122,143,112,93,93,112,112,93,93,112,1,111,197,87,197,253,72,199,86,199,1,43,122,122,1,94,1,26,254,230,128,86,199,86,0,4,0,136,0,0,4,40,5,160,0,15,0,19,0,23,0,35,0,35,64,19,22,0,24,105,0,8,19,18,18,8,23,8,114,8,30,106,8,3,114,0,43,43,43,17,57,47,57,18,57,43,57,48,49,1,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,1,53,33,21,5,17,51,17,3,50,54,53,52,38,35,34,6,21,20,22,2,88,147,207,110,110,207,147,147,208,109,109,208,253,203,3,73,253,245,200,100,117,127,127,117,117,127,127,2,8,110,211,149,143,201,106,106,201,143,149,211,110,254,174,190,190,182,2,68,253,188,2,198,146,134,125,135,135,125,134,146,0,5,0,36,255,236,4,146,5,130,0,11,0,23,0,27,0,36,0,45,0,49,64,30,24,25,6,18,106,6,32,33,27,40,42,26,7,38,36,36,0,38,37,106,34,38,2,114,0,12,106,0,9,114,0,43,43,43,50,43,18,57,47,18,23,57,43,57,57,48,49,5,34,2,53,52,54,51,50,22,21,20,2,39,50,54,53,52,38,35,34,6,21,20,22,1,39,1,23,3,53,52,54,55,39,39,51,17,1,53,33,21,39,39,6,6,35,1,214,206,228,228,206,206,228,228,206,103,111,111,103,103,111,111,1,64,133,1,138,154,112,44,49,57,36,180,253,188,2,68,226,55,46,78,39,20,1,6,238,229,251,251,229,238,254,250,190,162,148,139,151,151,139,148,162,2,85,134,1,158,90,254,117,136,34,84,61,48,217,253,188,1,144,180,180,29,47,40,36,0,0,2,0,89,0,60,4,87,5,0,0,18,0,22,0,18,64,9,12,0,15,21,4,19,6,105,19,0,47,43,23,57,48,49,37,34,38,53,16,0,55,22,0,17,20,6,35,34,38,53,35,20,6,23,17,51,17,1,54,105,116,1,19,246,242,1,3,110,101,87,97,212,105,124,174,162,148,134,1,8,1,168,148,150,254,88,254,250,134,148,106,95,95,106,102,3,232,252,24,0,0,6,0,49,0,60,4,127,5,0,0,11,0,27,0,32,0,36,0,41,0,57,0,28,64,19,35,30,39,18,52,0,40,29,49,21,25,45,42,12,14,33,6,105,33,0,47,43,23,57,48,49,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,39,23,21,35,20,6,3,53,55,51,21,3,17,51,17,3,53,51,23,21,19,34,38,53,35,53,55,7,52,54,51,50,22,21,20,6,2,88,169,206,206,169,170,205,205,254,22,104,127,129,106,100,120,129,232,93,128,42,92,211,114,134,114,211,92,64,106,128,93,232,129,120,100,107,128,127,2,58,181,149,172,208,208,172,149,181,254,74,130,106,112,135,138,114,118,35,83,104,127,1,31,52,150,202,254,153,3,232,252,24,1,103,202,150,52,254,225,127,104,83,35,118,114,138,135,112,106,130,0,1,0,69,0,60,4,107,4,236,0,20,0,14,181,10,7,0,106,14,7,0,47,51,43,57,48,49,37,38,2,2,53,52,54,51,50,22,23,51,54,54,51,50,22,21,20,2,2,2,88,160,239,132,146,120,101,142,16,12,16,142,101,120,146,132,239,60,90,1,9,1,57,160,168,204,160,131,131,160,204,168,160,254,198,254,247,0,0,1,0,109,0,40,4,67,5,20,0,3,0,10,179,2,0,106,2,0,47,43,48,49,37,9,2,2,92,254,17,1,239,1,231,40,2,118,2,118,253,138,0,1,0,126,0,0,4,102,5,140,0,7,0,21,64,10,4,2,2,0,6,2,114,0,8,114,0,43,43,18,57,47,57,48,49,33,3,51,19,51,1,51,1,1,68,198,206,119,18,1,195,206,253,242,2,89,254,91,4,216,250,116,0,3,0,0,0,8,4,176,4,248,0,20,0,56,0,68,0,29,64,19,54,50,53,32,33,0,1,28,39,57,68,62,63,13,66,21,105,11,66,0,47,51,43,23,57,48,49,19,39,62,3,55,62,3,55,23,14,3,7,14,2,1,34,38,38,53,52,54,51,50,22,22,23,55,38,38,53,52,54,51,50,22,21,20,14,2,21,20,22,51,50,54,55,23,6,6,1,38,35,34,6,7,39,54,54,51,32,19,180,180,27,71,108,164,120,90,134,99,76,33,180,23,74,122,186,135,137,155,74,2,80,140,210,116,115,94,59,67,43,21,35,7,38,102,84,95,104,58,77,58,36,29,30,63,53,86,73,192,254,87,69,151,47,95,38,104,52,148,88,1,2,138,1,190,60,95,129,91,70,36,27,49,69,109,86,40,95,135,100,84,43,44,83,111,253,244,102,185,123,94,113,55,91,55,14,20,90,52,84,102,104,95,65,81,58,58,44,34,34,37,41,138,69,76,3,55,251,42,44,144,66,66,254,139,0,4,0,108,255,13,4,48,5,159,0,26,0,41,0,53,0,57,0,42,64,28,33,48,106,27,42,106,27,54,38,11,45,56,36,33,8,6,0,22,106,6,0,105,6,17,106,6,3,114,0,43,43,43,43,18,23,57,43,43,48,49,5,34,36,2,17,16,33,32,17,20,20,21,35,52,52,53,16,33,32,17,16,18,51,50,55,21,6,3,34,38,53,52,54,51,50,22,23,51,17,35,6,6,39,50,54,53,52,38,35,34,6,21,20,22,23,17,51,17,2,198,211,254,246,125,2,0,1,196,172,254,232,254,168,206,228,125,72,79,152,133,147,147,135,77,111,22,74,74,18,111,25,80,86,78,74,82,90,83,241,172,243,175,1,115,1,39,3,73,253,222,90,170,109,107,168,88,1,126,253,97,254,164,254,199,25,180,25,1,135,247,224,237,233,121,111,254,35,111,121,190,121,111,172,157,134,146,134,147,170,2,89,253,167,0,0,3,0,56,255,236,4,200,5,160,0,15,0,35,0,43,0,45,64,25,22,23,32,36,32,36,32,16,39,40,8,106,7,40,3,114,16,29,106,16,9,114,0,8,114,0,43,43,43,43,50,43,50,18,57,57,47,47,17,57,57,48,49,33,1,38,38,53,52,54,51,23,34,6,21,20,22,23,1,5,34,38,53,52,54,55,23,6,6,21,20,22,51,50,18,17,51,16,0,19,52,38,35,39,50,22,21,3,194,253,252,130,114,213,195,4,91,101,77,67,2,146,253,6,183,223,199,181,110,138,150,125,103,198,216,192,254,182,14,85,77,4,181,199,2,54,143,227,106,191,207,184,112,104,73,140,77,253,18,20,199,165,161,206,27,122,27,137,98,85,105,1,58,1,32,254,137,254,101,4,118,65,69,184,166,152,0,4,0,36,0,0,4,136,5,140,0,6,0,10,0,14,0,18,0,27,64,14,9,17,18,106,0,7,13,6,17,2,114,7,8,114,0,43,43,50,50,17,57,43,57,48,49,1,34,38,53,52,54,51,3,17,51,17,51,17,51,17,1,55,33,21,2,0,227,249,253,235,102,200,170,200,254,24,20,2,124,2,128,197,185,188,210,250,116,5,6,250,250,5,140,250,116,4,206,190,190,0,0,2,0,69,255,36,4,107,6,32,0,54,0,67,0,41,64,23,31,30,65,51,106,3,4,59,24,106,65,59,38,10,17,106,38,10,105,38,44,106,38,0,47,43,43,43,18,57,57,43,57,57,43,57,57,48,49,1,20,6,7,21,22,22,21,20,6,33,34,38,39,55,22,22,51,50,54,53,52,38,39,37,38,38,53,52,54,23,53,46,2,53,52,54,33,50,23,7,38,38,35,34,6,21,20,22,23,5,30,2,5,20,22,22,51,50,54,53,52,38,35,34,6,4,107,147,162,107,102,240,254,246,120,171,71,24,105,161,72,150,136,40,44,254,158,157,147,187,208,115,129,51,248,1,20,146,134,22,81,124,59,157,141,45,49,1,70,110,142,70,252,182,88,152,96,150,136,164,140,168,150,2,162,140,129,2,28,43,119,107,171,155,14,16,192,16,16,63,69,48,47,13,110,49,143,146,134,136,1,23,39,73,99,77,174,156,20,184,8,6,61,69,46,40,18,120,40,86,125,105,75,83,32,92,100,118,80,94,0,3,0,26,0,15,4,150,5,125,0,11,0,36,0,48,0,36,64,22,18,24,106,12,30,106,12,22,21,18,4,6,0,37,106,6,0,105,6,43,106,6,0,47,43,43,43,18,23,57,43,43,48,49,37,32,0,17,16,0,33,32,0,17,16,0,3,34,38,53,52,54,51,50,22,23,7,38,35,34,6,21,20,22,51,50,54,55,23,6,6,7,50,18,53,16,2,35,34,2,17,20,18,2,88,254,238,254,212,1,44,1,18,1,18,1,44,254,212,222,175,191,186,172,89,127,27,123,44,84,76,84,103,97,44,87,41,24,52,113,107,193,211,211,193,193,211,211,15,1,100,1,68,1,82,1,116,254,140,254,174,254,188,254,156,1,109,172,160,155,173,63,57,113,73,82,76,88,94,14,12,156,18,12,211,1,20,250,1,9,1,35,254,221,254,247,250,254,236,0,0,5,0,26,0,15,4,150,5,125,0,11,0,15,0,19,0,31,0,49,0,39,64,23,43,13,16,12,12,32,17,18,33,41,13,7,20,6,26,106,0,20,106,6,0,105,6,0,47,43,43,43,17,23,57,17,51,17,51,48,49,37,32,0,17,16,0,33,32,0,17,16,0,1,17,51,17,51,39,55,23,5,50,18,53,16,2,35,34,2,17,20,18,19,53,51,50,54,53,52,38,35,35,53,51,50,22,21,20,6,35,2,88,254,238,254,212,1,44,1,18,1,18,1,44,254,212,253,242,160,209,114,154,147,254,208,193,211,211,193,193,211,211,87,154,44,48,48,44,174,174,116,126,126,116,15,1,100,1,68,1,82,1,116,254,140,254,174,254,188,254,156,1,125,2,122,253,134,212,27,239,227,1,20,250,1,9,1,35,254,221,254,247,250,254,236,1,175,130,45,40,41,44,130,107,98,107,118,0,4,0,26,0,15,4,150,5,125,0,11,0,15,0,27,0,45,0,33,64,19,39,13,12,28,29,37,13,5,6,0,16,106,6,0,105,6,22,106,6,0,47,43,43,43,18,23,57,17,51,48,49,37,32,0,17,16,0,33,32,0,17,16,0,1,17,51,17,23,50,18,53,16,2,35,34,2,17,20,18,19,53,51,50,54,53,52,38,35,35,53,51,50,22,21,20,6,35,2,88,254,238,254,212,1,44,1,18,1,18,1,44,254,212,253,242,160,92,193,211,211,193,193,211,211,87,144,44,48,48,44,164,174,116,126,126,116,15,1,100,1,68,1,82,1,116,254,140,254,174,254,188,254,156,1,125,2,122,253,134,227,1,20,250,1,9,1,35,254,221,254,247,250,254,236,1,135,130,55,50,50,55,130,118,107,117,128,0,6,0,29,3,6,4,119,5,140,0,3,0,7,0,15,0,19,0,27,0,31,0,57,64,30,13,22,22,5,4,106,30,11,11,24,24,17,17,1,1,15,20,25,9,4,5,28,28,16,16,5,0,105,5,2,0,63,43,50,17,51,17,18,23,57,50,17,51,17,51,17,51,17,51,43,50,17,51,48,49,19,17,51,17,1,53,33,21,1,55,51,19,51,21,35,3,5,17,51,17,55,3,35,53,51,19,51,23,23,17,51,17,192,151,254,198,1,224,1,62,16,6,85,80,31,79,254,145,146,103,89,31,90,85,4,10,142,146,3,6,2,134,253,122,2,2,132,132,254,206,161,1,21,172,254,246,208,2,134,253,122,208,1,10,172,254,235,161,208,2,134,253,122,0,4,0,52,255,236,4,142,5,159,0,3,0,15,0,27,0,51,0,46,64,30,28,47,106,34,28,105,0,1,3,2,4,4,34,41,106,34,3,114,10,22,106,4,10,105,4,16,106,4,9,114,0,43,43,43,43,43,43,18,23,57,43,43,48,49,19,39,1,23,1,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,1,34,38,53,52,54,51,50,22,23,7,38,38,35,34,6,21,20,22,51,50,55,23,6,186,92,3,162,92,254,250,142,172,172,142,141,171,171,141,57,69,69,57,58,70,70,254,104,160,176,182,166,93,132,28,123,21,67,40,76,84,89,81,83,89,24,90,1,50,136,2,152,130,252,28,177,145,147,177,177,147,145,177,168,85,69,71,85,85,71,69,85,2,155,165,151,147,161,63,57,113,35,38,77,71,74,82,36,156,40,0,2,1,2,3,2,3,174,5,160,0,11,0,23,0,21,64,12,0,12,106,6,0,105,6,18,106,6,3,114,0,43,43,43,43,48,49,1,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,2,88,154,188,188,154,155,187,187,155,76,91,91,76,76,91,91,3,2,184,151,152,183,183,152,151,184,150,102,83,83,102,102,83,83,102,0,0,1,1,206,3,12,3,36,5,140,0,3,0,12,181,1,0,106,1,2,114,0,43,43,48,49,1,19,33,3,1,206,80,1,6,190,3,12,2,128,253,128,0,2,0,242,3,12,3,216,5,140,0,3,0,7,0,16,183,7,5,0,105,2,5,2,114,0,43,50,43,50,48,49,1,19,33,3,33,19,33,3,2,130,80,1,6,190,253,216,80,1,6,190,3,12,2,128,253,128,2,128,253,128,0,1,1,244,254,202,2,188,6,194,0,3,0,12,181,1,0,106,1,149,114,0,43,43,48,49,1,17,51,17,1,244,200,254,202,7,248,248,8,0,0,2,1,244,254,202,2,188,6,194,0,3,0,7,0,21,64,12,0,5,105,1,0,106,1,4,105,1,149,114,0,43,43,43,43,48,49,1,17,51,17,3,17,51,17,1,244,200,200,200,3,102,3,92,252,164,251,100,3,92,252,164,0,2,0,220,1,16,3,212,5,160,0,3,0,9,0,21,64,11,5,4,106,5,5,1,0,106,1,3,114,0,43,43,57,47,43,48,49,1,3,51,3,1,53,33,33,21,33,1,255,10,192,10,254,49,1,126,1,122,254,134,1,16,4,144,251,112,2,180,168,168,0,1,0,0,0,0,4,40,5,160,0,28,0,29,64,17,15,14,106,15,0,7,21,106,7,3,114,0,28,106,0,9,114,0,43,43,43,43,18,57,43,48,49,33,34,36,2,53,16,18,51,50,22,21,20,2,4,33,53,32,0,17,52,38,35,34,2,21,20,22,22,51,3,192,212,254,195,175,237,217,169,185,250,254,36,254,174,1,151,1,191,75,69,116,128,130,236,158,187,1,81,226,1,73,1,105,209,191,232,254,186,172,184,1,30,1,4,103,113,254,248,242,170,255,141,0,0,5,0,220,1,16,3,212,5,160,0,5,0,9,0,15,0,19,0,23,0,55,64,29,3,0,1,106,4,0,14,11,10,106,13,11,18,23,21,0,19,8,11,0,11,0,11,21,6,105,21,3,114,0,43,43,57,57,47,47,17,57,57,17,18,57,57,17,51,43,50,17,51,43,50,48,49,19,53,33,33,21,33,3,19,51,19,1,53,33,33,21,33,39,17,51,17,3,3,51,3,220,1,126,1,122,254,134,101,10,172,10,254,39,1,126,1,122,254,134,91,172,172,10,192,10,4,0,158,158,253,16,1,92,254,164,1,22,158,158,110,1,188,254,68,1,166,1,102,254,154,0,0,6,0,58,0,0,4,132,5,140,0,11,0,15,0,19,0,31,0,39,0,43,0,57,64,34,41,36,36,37,33,43,17,43,32,32,17,16,106,17,2,114,6,26,106,0,6,105,0,20,106,14,0,105,15,14,106,15,8,114,0,43,43,43,43,43,43,43,43,50,17,51,17,18,57,57,51,17,51,48,49,37,34,38,53,52,54,51,50,22,21,20,6,5,53,33,21,1,17,51,17,1,50,54,53,52,38,35,34,6,21,20,22,1,3,35,53,51,19,51,21,35,17,51,17,3,86,138,166,166,138,137,165,165,254,71,2,94,251,182,172,2,112,53,63,63,53,54,64,64,254,102,140,92,132,140,50,30,172,220,171,141,143,171,171,143,141,171,220,138,138,3,72,2,68,253,188,254,60,80,64,66,80,80,66,64,80,1,196,1,124,200,254,132,200,2,68,253,188,0,0,4,0,76,255,236,4,100,4,156,0,30,0,34,0,38,0,42,0,50,64,31,35,36,106,12,13,42,33,41,40,34,6,6,31,27,32,3,35,35,0,6,18,106,0,6,105,0,24,106,0,9,114,0,43,43,43,43,18,57,47,23,57,18,23,57,51,43,48,49,5,34,0,17,16,0,51,50,0,17,20,6,7,39,54,53,52,38,35,34,2,21,20,22,51,50,54,55,51,6,4,37,3,19,55,3,53,33,21,37,17,23,19,2,98,254,254,232,1,24,254,245,1,13,2,2,159,3,185,169,173,191,191,173,125,179,38,151,45,254,254,254,97,240,12,228,206,3,173,254,207,251,12,20,1,43,1,15,1,44,1,74,254,203,254,231,39,62,17,16,36,66,227,249,254,242,246,217,239,139,126,181,198,117,1,71,1,191,237,253,132,154,154,66,2,58,237,254,179,0,0,1,0,80,0,110,4,96,5,30,0,5,0,0,37,1,17,1,1,17,2,88,253,248,2,8,2,8,110,1,44,2,88,1,44,254,212,253,168,0,0,1,0,75,1,139,4,101,4,1,0,15,0,0,1,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,2,88,158,236,131,131,236,158,158,236,131,131,236,1,139,78,142,95,95,142,78,78,142,95,95,142,78,0,0,1,0,0,0,110,4,176,5,30,0,15,0,0,37,34,36,2,53,52,18,36,51,50,4,18,21,20,2,4,2,88,181,254,242,149,149,1,14,181,181,1,14,149,149,254,242,110,149,1,14,181,181,1,14,149,149,254,242,181,181,254,242,149,0,1,0,0,0,110,4,176,5,30,0,3,0,0,53,17,33,17,4,176,110,4,176,251,80,0,0,1,0,212,1,66,3,220,4,74,0,3,0,0,9,3,2,88,254,124,1,132,1,132,1,66,1,132,1,132,254,124,0,1,1,6,1,210,3,170,4,16,0,2,0,0,1,1,33,2,88,254,174,2,164,1,210,2,62,0,0,1,1,10,1,116,3,72,4,24,0,2,0,0,9,2,3,72,253,194,2,62,1,116,1,82,1,82,0,1,1,72,1,0,3,105,4,140,0,3,0,0,9,3,2,88,254,240,1,16,1,17,1,0,1,198,1,198,254,58,0,1,1,104,1,116,3,166,4,24,0,2,0,0,1,17,1,1,104,2,62,1,116,2,164,254,174,0,0,1,1,6,1,124,3,170,3,186,0,2,0,0,9,2,1,6,1,82,1,82,1,124,2,62,253,194,0,1,0,0,0,168,4,176,5,30,0,4,0,0,55,3,1,1,3,230,230,2,88,2,88,230,168,2,194,1,180,254,76,253,62,0,0,1,1,168,2,22,3,8,3,118,0,3,0,0,1,39,55,23,2,88,176,176,176,2,22,176,176,176,0,1,1,159,1,146,3,17,3,251,0,3,0,0,1,3,19,19,2,88,185,185,185,1,146,1,52,1,53,254,203,0,0,1,1,29,0,185,3,147,4,211,0,15,0,0,37,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,2,88,95,142,78,78,142,95,95,142,78,78,142,185,131,236,158,158,236,131,131,236,158,158,236,131,0,1,1,119,1,229,3,57,3,167,0,3,0,0,1,17,33,17,1,119,1,194,1,229,1,194,254,62,0,1,0,75,0,185,4,101,2,198,0,8,0,0,37,34,38,38,53,33,20,6,6,2,88,158,236,131,4,26,131,236,185,131,236,158,158,236,131,0,0,1,0,0,0,190,4,176,4,206,0,5,0,0,37,1,1,33,1,1,1,44,254,212,1,44,2,88,1,44,254,212,190,2,8,2,8,253,248,253,248,0,0,3,0,75,0,185,4,101,4,211,0,3,0,7,0,11,0,0,19,17,33,17,1,33,17,33,19,17,33,17,125,3,182,252,24,4,26,251,230,150,2,238,2,198,1,229,254,27,2,13,251,230,3,132,253,18,2,238,0,3,0,75,0,185,4,101,4,211,0,2,0,6,0,10,0,0,19,33,17,5,17,33,17,37,33,17,33,111,3,211,252,9,4,26,252,124,2,238,253,18,4,185,252,36,36,4,26,251,230,150,2,238,0,1,0,75,2,198,4,101,4,211,0,8,0,0,19,52,54,54,51,50,22,22,21,75,131,236,158,158,236,131,2,198,158,236,131,131,236,158,0,3,0,75,0,185,4,101,4,211,0,3,0,7,0,11,0,0,19,33,17,33,7,17,33,17,37,33,17,33,125,3,182,252,74,50,4,26,252,124,2,238,253,18,2,198,254,27,40,4,26,251,230,150,2,238,0,3,0,75,0,185,4,101,4,211,0,2,0,6,0,10,0,0,37,33,17,37,17,33,17,5,33,17,33,4,65,252,45,3,247,251,230,3,132,253,18,2,238,211,3,220,36,251,230,4,26,150,253,18,0,2,0,80,0,110,4,96,5,30,0,5,0,17,0,0,37,1,17,1,1,17,5,35,1,7,17,23,1,51,1,55,17,39,2,88,253,248,2,8,2,8,254,62,140,1,254,70,70,254,2,140,254,2,70,70,110,1,44,2,88,1,44,254,212,253,168,168,1,40,122,2,76,122,1,40,254,216,122,253,180,122,0,2,0,75,1,139,4,101,4,1,0,15,0,27,0,0,1,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,39,50,54,53,52,38,35,34,6,21,20,22,2,88,158,236,131,131,236,158,158,236,131,131,236,158,170,205,205,170,169,206,206,1,139,78,142,95,95,142,78,78,142,95,95,142,78,150,91,74,74,91,91,74,74,91,0,2,0,0,0,110,4,176,5,30,0,3,0,7,0,0,53,17,33,17,37,33,17,33,4,176,251,230,3,132,252,124,110,4,176,251,80,150,3,132,0,2,0,212,1,66,3,220,4,74,0,3,0,11,0,0,9,3,5,35,1,21,1,51,1,53,2,88,254,124,1,132,1,132,254,181,114,1,34,254,222,114,254,222,1,66,1,132,1,132,254,124,233,1,34,114,1,34,254,222,114,0,0,2,1,72,1,0,3,105,4,140,0,3,0,11,0,0,9,3,7,35,19,21,3,51,3,53,2,88,254,240,1,16,1,17,231,84,182,182,84,182,1,0,1,198,1,198,254,58,232,1,45,138,1,45,254,211,138,0,0,2,0,0,0,168,4,176,5,30,0,4,0,9,0,0,55,3,1,1,3,37,33,19,1,1,230,230,2,88,2,88,230,253,137,2,10,163,254,88,254,88,168,2,194,1,180,254,76,253,62,150,1,243,1,52,254,204,0,2,1,159,1,146,3,17,3,251,0,3,0,7,0,0,1,3,19,19,7,55,39,7,2,88,185,185,185,185,69,69,68,1,146,1,52,1,53,254,203,114,114,114,114,0,0,2,1,29,0,185,3,147,4,211,0,15,0,27,0,0,37,34,38,38,53,52,54,54,51,50,22,22,21,20,6,6,39,50,54,53,52,38,35,34,6,21,20,22,2,88,95,142,78,78,142,95,95,142,78,78,142,95,74,91,91,74,74,91,91,185,131,236,158,158,236,131,131,236,158,158,236,131,150,206,169,170,205,205,170,169,206,0,0,2,1,119,1,229,3,57,3,167,0,3,0,7,0,0,1,17,33,17,37,51,53,35,1,119,1,194,254,212,150,150,1,229,1,194,254,62,150,150,0,6,252,10,255,236,3,226,5,160,0,15,0,36,0,52,0,73,0,81,0,89,0,77,64,41,85,8,77,77,78,45,106,60,23,59,22,69,32,82,74,23,22,16,32,74,32,74,16,86,44,7,78,3,114,0,37,8,114,66,16,29,106,53,16,9,114,0,43,50,43,50,43,50,43,50,50,50,17,57,57,47,47,18,57,57,17,51,17,51,17,51,17,51,43,50,17,51,51,48,49,33,1,38,38,53,52,54,51,23,34,6,21,20,22,23,1,5,34,38,53,52,54,55,23,6,6,21,20,22,51,50,18,17,51,16,2,6,55,1,38,38,53,52,54,51,23,34,6,21,20,22,23,1,5,34,38,53,52,54,55,23,6,6,21,20,22,51,50,18,17,51,16,2,6,1,52,38,35,39,50,22,21,33,52,38,35,39,50,22,21,2,250,254,48,67,97,187,169,4,66,74,54,34,2,40,249,150,183,183,150,150,110,105,103,94,94,162,162,182,117,236,213,254,48,69,95,187,169,4,66,74,52,36,2,40,1,142,183,183,150,150,110,105,103,94,94,162,162,182,113,235,252,86,74,68,4,171,189,3,38,74,68,4,180,180,2,214,107,187,82,161,177,184,81,75,57,119,54,252,154,20,181,183,170,196,28,122,28,130,104,100,100,1,49,1,51,254,249,254,163,174,20,2,214,108,192,76,161,177,184,81,75,55,118,57,252,154,20,181,183,170,196,28,122,28,130,104,100,100,1,50,1,50,254,249,254,163,174,4,118,65,69,184,166,152,65,69,184,159,159,0,0,2,253,22,254,202,3,152,6,194,0,3,0,7,0,21,64,11,1,0,106,1,1,6,4,105,6,149,114,0,43,43,57,47,43,48,49,1,53,33,21,1,35,17,51,253,48,6,104,250,70,200,200,2,104,186,186,252,98,7,248,0,0,2,253,68,254,202,3,192,6,194,0,54,0,58,0,41,64,25,57,55,106,57,149,114,17,16,44,45,106,44,33,0,7,106,33,0,105,33,26,106,33,154,114,0,43,43,43,43,18,57,43,57,57,43,43,48,49,5,34,38,39,55,22,22,51,50,54,53,52,38,53,52,54,55,53,38,38,53,52,54,53,52,38,35,34,6,7,39,54,54,51,50,22,21,20,6,21,20,30,2,51,21,34,6,6,21,20,22,21,20,6,5,35,17,51,1,34,93,124,53,24,63,116,49,120,126,46,138,124,124,138,46,126,120,49,116,63,24,33,144,93,210,232,42,57,87,92,34,48,127,95,42,232,252,24,200,200,214,11,9,170,4,6,131,119,68,130,74,95,113,2,34,2,109,99,71,130,71,110,122,5,5,170,9,11,215,197,69,132,75,34,54,37,19,158,25,63,56,72,135,69,204,226,96,7,248,0,4,253,114,254,202,2,142,6,194,0,3,0,7,0,11,0,15,0,33,64,20,13,15,106,13,149,114,3,6,106,4,2,3,106,2,11,106,9,2,153,114,0,43,50,43,43,50,43,43,43,48,49,5,17,51,17,33,53,33,21,1,53,33,21,1,17,51,17,1,196,202,253,0,2,74,253,182,2,74,251,154,200,200,7,28,248,228,176,176,6,108,176,176,249,38,7,248,248,8,255,255,253,198,254,202,2,58,6,194,0,39,4,167,255,126,0,0,0,7,4,167,251,210,0,0,0,4,245,72,254,202,2,188,6,194,0,7,0,11,0,15,0,19,0,63,64,37,19,13,15,106,17,13,149,114,3,2,6,7,0,8,10,5,4,11,1,8,106,7,1,105,6,7,106,9,4,5,106,6,4,105,6,151,114,0,43,43,43,50,43,43,43,57,17,18,57,17,51,17,18,57,57,43,50,43,50,48,49,5,53,1,53,1,53,1,21,1,17,23,17,1,17,51,17,33,17,51,17,252,220,4,222,251,34,5,224,250,32,200,247,164,200,3,32,200,10,240,1,214,18,1,216,240,253,148,202,253,150,5,160,100,251,40,254,112,7,248,248,8,7,248,248,8,0,4,249,112,254,202,3,152,6,194,0,3,0,7,0,11,0,15,0,33,64,20,9,13,15,106,10,13,149,114,7,6,106,2,7,105,2,3,106,2,148,114,0,43,43,43,43,43,50,43,50,48,49,1,53,33,21,1,53,33,21,1,35,17,51,1,17,51,17,253,8,6,144,249,112,6,144,249,172,200,200,252,44,200,3,98,186,186,254,12,186,186,253,92,7,248,248,8,7,248,248,8,0,3,249,152,254,202,2,143,6,194,0,7,0,11,0,15,0,59,64,35,2,3,6,11,7,1,10,5,4,14,12,106,14,149,114,8,1,0,106,7,1,105,6,7,106,9,4,5,106,6,4,105,6,151,114,0,43,43,43,50,43,43,43,50,43,43,17,18,57,17,18,57,17,57,57,48,49,5,53,1,53,1,53,1,21,1,17,23,17,1,35,17,51,252,175,4,222,251,34,5,224,250,32,200,252,233,200,200,10,240,1,214,18,1,216,240,253,148,202,253,150,5,160,100,251,40,254,112,7,248,0,3,253,22,254,202,3,152,6,194,0,3,0,7,0,11,0,29,64,18,10,8,105,10,149,114,7,6,106,2,7,105,2,3,106,2,148,114,0,43,43,43,43,43,43,48,49,1,53,33,21,1,53,33,21,1,35,17,51,253,88,6,64,249,192,6,64,250,70,200,200,3,98,186,186,254,12,186,186,253,92,7,248,0,0,2,253,109,255,246,3,77,5,150,0,7,0,11,0,45,64,26,3,2,6,7,11,0,1,8,106,7,1,105,6,7,106,10,5,4,9,106,6,4,105,6,151,114,0,43,43,43,50,57,43,43,43,50,57,17,18,57,57,48,49,5,53,1,53,1,53,1,21,1,17,23,17,253,109,4,222,251,34,5,224,250,32,200,10,240,1,214,18,1,216,240,253,148,202,253,150,5,160,100,251,40,0,3,252,10,254,192,3,197,6,204,0,7,0,41,0,45,0,76,64,49,18,39,21,22,36,35,25,32,8,8,43,28,28,29,106,28,3,114,45,8,96,8,15,105,8,9,114,3,2,6,7,1,0,106,7,1,106,6,7,106,4,5,106,6,4,105,6,151,114,0,43,43,43,43,43,43,17,18,57,57,43,43,26,16,205,43,43,16,205,18,23,57,48,49,55,53,1,53,1,53,1,21,1,34,38,39,55,22,22,51,50,54,53,52,38,39,39,38,38,53,52,54,51,21,34,6,21,20,22,23,23,22,22,21,20,6,1,17,51,17,7,2,188,251,71,5,187,249,235,121,211,90,26,110,205,97,140,136,67,63,246,145,155,236,214,112,124,74,72,208,158,164,251,254,253,138,214,220,1,10,18,1,248,215,253,141,202,253,140,39,39,194,43,45,98,100,66,92,28,112,66,186,138,186,204,184,103,93,69,86,35,98,73,187,146,193,193,254,212,8,12,247,244,0,255,255,252,64,0,190,3,192,4,204,0,39,3,67,251,220,0,0,0,7,3,67,255,116,0,0,0,8,247,184,0,190,3,152,4,204,0,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,61,64,32,8,24,24,23,16,105,15,7,7,31,31,3,3,22,23,106,9,25,25,22,17,105,14,6,6,30,30,2,2,22,147,114,0,43,50,17,51,17,51,17,51,43,50,17,51,43,50,17,51,17,51,17,51,43,50,17,51,48,49,1,53,33,21,33,53,33,21,1,17,51,17,1,53,33,21,1,17,51,17,1,53,33,21,1,17,51,17,1,53,33,21,253,229,3,117,248,163,3,117,251,218,192,253,172,3,232,5,164,192,253,172,3,232,249,176,192,253,172,3,232,2,105,186,186,186,186,254,85,4,14,251,242,1,171,186,186,254,85,4,14,251,242,1,171,186,186,254,85,4,14,251,242,1,171,186,186,255,255,252,104,0,190,3,196,4,204,0,39,3,67,252,4,0,0,0,7,3,73,255,116,0,0,255,255,247,184,0,160,3,152,4,236,0,39,3,71,247,84,0,0,0,39,3,71,255,76,0,0,0,7,2,167,251,80,0,180,255,255,247,184,255,236,3,152,5,150,0,39,3,71,247,84,0,0,0,39,3,71,255,76,0,0,0,7,2,170,251,80,0,0,0,4,252,4,1,110,3,252,4,28,0,3,0,7,0,11,0,15,0,29,64,16,6,15,14,106,7,2,15,105,11,2,3,106,10,2,148,114,0,43,50,43,50,43,50,43,50,48,49,19,53,33,21,1,53,33,21,1,53,33,21,19,53,33,21,80,3,172,248,8,3,152,252,104,3,152,180,3,172,3,98,186,186,254,12,186,186,1,244,186,186,254,12,186,186,0,0,3,247,84,0,206,3,252,4,188,0,3,0,7,0,11,0,29,64,18,5,4,106,8,5,105,9,8,106,0,1,106,9,0,105,9,147,114,0,43,43,43,43,43,43,48,49,1,53,33,21,1,53,33,21,1,53,33,21,247,84,12,168,243,88,12,168,243,88,12,168,4,2,186,186,252,204,186,186,1,154,186,186,0,0,3,247,184,0,112,3,192,5,24,0,11,0,15,0,19,0,50,64,30,10,5,4,11,4,17,3,13,12,1,0,106,1,13,12,106,16,13,105,6,17,16,106,8,9,106,8,17,148,114,0,43,206,43,43,57,43,43,206,43,17,18,57,18,23,57,48,49,55,53,55,53,1,53,1,53,39,53,1,21,1,53,33,5,1,53,33,5,6,200,1,204,254,56,204,3,186,243,248,10,240,254,252,246,20,9,96,1,4,112,220,30,82,1,0,18,1,8,70,32,220,253,234,122,254,250,186,186,1,204,186,186,0,3,252,104,0,112,3,192,5,24,0,11,0,15,0,19,0,47,64,28,6,17,16,106,3,12,13,106,11,4,5,10,4,17,12,1,0,106,1,17,12,105,8,9,106,8,17,148,0,63,206,43,43,206,43,17,18,23,57,43,57,43,57,48,49,55,53,55,53,1,53,1,53,39,53,1,21,1,53,33,5,1,53,33,5,6,200,1,204,254,56,204,3,186,248,168,6,64,254,252,250,196,4,176,1,4,112,220,30,82,1,0,18,1,8,70,32,220,253,234,122,254,250,186,186,1,204,186,186,0,0,4,247,184,0,112,3,192,5,24,0,7,0,11,0,15,0,27,0,59,64,36,5,24,25,106,4,24,13,22,13,12,106,0,17,16,106,1,17,8,19,8,9,106,7,27,20,2,3,21,26,6,8,13,8,105,13,148,0,63,43,23,57,43,57,16,206,50,43,50,43,57,16,206,50,43,50,48,49,55,53,1,53,1,53,1,21,1,53,33,5,1,53,33,5,1,53,55,53,1,53,1,53,39,53,1,21,6,2,148,253,108,3,186,243,248,8,32,254,252,248,228,6,144,1,4,253,234,200,1,204,254,56,204,3,186,112,220,1,112,18,1,110,220,253,234,122,254,250,186,186,1,204,186,186,253,34,220,30,82,1,0,18,1,8,70,32,220,253,234,122,0,0,5,247,184,0,112,3,152,5,24,0,7,0,11,0,15,0,19,0,23,0,64,64,39,3,23,22,106,4,13,23,105,21,13,1,6,5,2,4,9,20,13,12,106,0,19,16,106,7,8,19,105,17,18,8,9,106,13,8,105,13,148,114,0,43,43,43,50,57,43,50,43,50,43,50,17,23,57,17,57,43,50,43,50,48,49,37,1,53,1,21,1,21,1,37,53,33,21,1,53,33,21,1,1,55,5,1,39,1,21,3,152,252,70,3,186,253,108,2,148,244,32,7,36,248,220,7,36,1,136,253,244,132,1,136,254,120,132,2,12,112,2,24,122,2,22,220,254,146,18,254,144,34,186,186,1,244,186,186,253,14,1,40,144,220,2,22,142,1,40,220,0,0,3,247,84,255,156,3,252,5,240,0,3,0,7,0,11,0,28,64,17,4,5,106,4,0,105,9,4,105,9,8,106,9,1,105,9,148,0,63,43,43,43,43,43,48,49,5,1,51,1,1,53,33,21,1,53,33,21,251,164,3,46,202,252,210,250,230,12,168,243,88,12,168,100,6,84,249,172,1,210,186,186,1,244,186,186,0,2,252,104,0,112,3,152,5,24,0,7,0,11,0,40,64,25,7,2,3,6,4,10,11,1,0,106,11,1,105,10,11,106,4,5,106,10,4,105,10,147,114,0,43,43,43,43,43,43,17,18,23,57,48,49,37,53,1,53,1,53,1,21,7,53,33,21,252,104,2,148,253,108,3,186,96,3,214,112,220,1,112,18,1,110,220,253,234,122,34,188,188,0,0,3,247,184,0,112,3,192,5,24,0,15,0,23,0,27,0,50,64,31,22,23,19,18,15,14,6,25,24,0,17,16,106,1,24,17,106,25,24,106,13,20,21,106,12,25,20,106,25,147,114,0,43,43,50,43,50,43,43,50,43,50,17,18,23,57,48,49,55,53,62,3,55,17,46,3,39,53,1,21,1,53,1,53,1,53,1,21,7,53,33,21,6,167,211,122,63,19,20,67,124,209,162,3,186,243,248,2,148,253,108,3,186,106,7,122,112,240,65,84,47,21,1,1,20,2,16,44,86,70,240,253,234,122,253,232,220,1,112,18,1,110,220,253,234,122,34,188,188,0,255,255,252,216,0,160,3,34,4,236,0,39,3,73,252,70,0,0,0,7,2,167,0,54,0,180,0,2,253,74,0,144,2,238,5,154,0,7,0,11,0,43,64,26,2,3,7,6,9,8,106,0,9,105,1,0,106,7,1,106,6,7,106,4,5,106,6,4,106,6,0,47,43,43,43,43,43,43,43,17,18,57,57,48,49,1,53,37,53,37,53,1,21,1,53,33,21,253,74,4,112,251,144,5,164,250,92,5,164,1,228,220,246,18,246,220,254,148,222,253,64,190,190,0,0,5,247,184,0,112,3,192,5,24,0,11,0,15,0,19,0,23,0,27,0,64,64,37,6,19,26,11,4,5,10,4,22,16,26,27,106,3,15,14,23,22,106,12,1,0,106,13,1,26,23,105,18,8,9,106,17,8,26,148,114,0,43,204,50,43,50,43,205,50,43,50,43,50,57,57,43,50,17,23,57,17,57,57,48,49,55,53,55,53,1,53,1,53,39,53,1,21,1,53,37,23,3,37,53,1,3,53,33,5,1,53,33,5,6,200,1,204,254,56,204,3,186,243,248,1,136,132,132,254,120,2,12,132,9,104,254,252,247,156,7,216,1,4,112,220,30,82,1,0,18,1,8,70,32,220,253,234,122,253,232,220,230,154,1,192,228,220,254,216,253,146,176,176,1,214,176,176,0,2,252,104,0,174,3,192,4,220,0,7,0,15,0,58,64,34,3,2,11,10,4,7,6,8,9,1,12,4,13,5,1,0,106,7,1,106,15,6,7,106,4,5,106,6,4,106,14,6,151,114,0,43,50,43,43,43,50,43,43,17,51,17,51,17,51,50,17,18,23,57,48,49,55,53,1,53,1,53,1,21,1,53,1,53,1,53,1,21,2,2,188,253,68,3,190,248,168,2,188,253,68,3,190,174,220,1,50,18,1,50,220,254,78,202,254,78,220,1,50,18,1,50,220,254,78,202,0,3,247,184,0,112,3,152,5,24,0,7,0,15,0,19,0,54,64,34,8,9,1,12,4,13,5,1,0,106,19,1,105,4,5,106,18,4,105,6,7,14,15,11,10,3,2,8,18,19,106,18,147,114,0,43,43,23,57,43,43,43,43,17,51,17,51,17,51,50,48,49,37,53,1,53,1,53,1,21,1,53,1,53,1,53,1,21,5,53,33,21,250,236,2,148,253,108,3,206,248,254,2,148,253,108,3,186,2,242,5,52,112,220,1,112,18,1,110,220,253,234,122,253,232,220,1,112,18,1,110,220,253,234,122,34,188,188,0,5,247,184,0,112,3,152,5,24,0,7,0,11,0,15,0,19,0,23,0,78,64,44,15,23,22,11,19,12,6,7,3,2,4,18,23,0,8,1,9,4,5,13,14,106,9,8,106,9,19,13,22,10,14,23,19,18,106,22,19,105,22,23,106,22,148,114,0,43,43,43,43,17,51,50,16,204,16,204,43,43,50,51,17,51,17,51,17,18,23,57,51,17,57,17,18,57,48,49,37,53,1,53,1,53,1,21,3,53,37,23,3,37,53,1,3,53,33,21,1,53,33,21,247,184,2,148,253,108,3,186,134,1,136,132,132,254,120,2,12,132,7,36,248,220,7,36,112,220,1,112,18,1,110,220,253,234,122,253,232,220,220,144,1,202,218,220,254,216,253,126,186,186,1,244,186,186,255,255,247,184,0,214,3,192,4,180,0,39,3,73,255,112,0,0,0,39,3,73,247,38,0,0,0,7,3,73,251,80,0,0,0,2,252,64,0,112,3,152,5,24,0,15,0,19,0,37,64,22,1,2,19,18,15,0,106,19,15,105,4,3,106,18,4,105,18,19,106,18,147,114,0,43,43,43,43,43,43,17,18,57,57,48,49,39,1,53,1,21,14,3,7,17,30,3,23,1,53,33,21,6,252,70,3,186,162,209,124,67,20,19,63,122,212,166,253,132,6,26,112,2,24,122,2,22,240,70,86,44,16,2,254,236,1,21,47,84,65,1,6,188,188,0,0,2,247,144,0,112,3,152,5,24,0,15,0,19,0,37,64,22,1,2,19,18,15,0,106,19,15,105,4,3,106,18,4,105,18,19,106,18,147,114,0,43,43,43,43,43,43,17,18,57,57,48,49,37,1,53,1,21,14,3,7,17,30,3,23,1,53,33,21,251,74,252,70,3,186,162,209,124,67,20,19,63,122,212,166,253,132,10,202,112,2,24,122,2,22,240,70,86,44,16,2,254,236,1,21,47,84,65,1,6,188,188,0,3,247,144,0,112,3,192,5,24,0,15,0,31,0,35,0,56,64,33,16,0,31,1,20,12,19,13,14,15,18,17,4,35,34,1,0,106,35,1,105,12,13,106,34,12,105,34,35,106,34,147,114,0,43,43,43,43,43,43,17,18,23,57,17,51,17,51,17,51,17,51,48,49,55,53,62,3,55,17,46,3,39,53,1,21,1,1,53,1,21,14,3,7,17,30,3,23,1,53,33,21,6,167,211,122,63,19,20,67,124,209,162,3,186,247,138,252,70,3,186,162,209,124,67,20,19,63,122,212,166,253,132,9,180,112,240,65,84,47,21,1,1,20,2,16,44,86,70,240,253,234,122,253,232,2,24,122,2,22,240,70,86,44,16,2,254,236,1,21,47,84,65,1,6,188,188,0,0,3,247,144,0,112,3,152,5,24,0,7,0,23,0,27,0,52,64,32,8,23,7,12,4,11,3,7,0,106,27,7,106,4,3,106,26,4,106,2,1,5,6,10,9,6,26,27,106,26,147,114,0,43,43,23,57,43,43,43,43,17,51,17,51,17,51,50,48,49,37,1,53,1,21,1,21,1,5,1,53,1,21,14,3,7,17,30,3,23,1,53,33,21,3,152,252,70,3,186,253,128,2,128,247,178,252,70,3,186,162,209,124,67,20,19,63,122,212,166,253,132,7,82,112,2,24,122,2,22,240,254,166,18,254,164,240,2,24,122,2,22,240,70,86,44,16,2,254,236,1,21,47,84,65,1,6,188,188,0,255,255,252,238,0,160,3,38,4,236,0,39,3,74,252,142,0,0,0,7,2,167,0,58,0,180,0,5,242,224,255,236,3,152,5,150,0,15,0,19,0,23,0,27,0,39,0,57,64,36,1,2,19,18,15,0,106,19,15,105,4,3,106,18,4,105,34,24,105,28,34,106,28,9,114,25,2,114,20,18,19,106,21,18,147,114,0,43,50,43,50,43,43,43,43,43,43,43,43,17,18,57,57,48,49,37,1,53,1,21,14,3,7,17,30,3,23,1,53,33,21,33,53,33,21,5,3,51,3,3,34,38,53,52,54,51,50,22,21,20,6,246,154,252,70,3,186,162,209,124,67,20,19,63,122,212,166,253,132,4,16,2,208,8,154,245,158,6,208,10,94,61,87,87,61,62,86,86,112,2,24,122,2,22,240,70,86,44,16,2,254,236,1,21,47,84,65,1,6,188,188,188,188,158,3,206,252,50,254,36,87,61,62,86,86,62,61,87,255,255,252,84,0,214,3,218,4,180,0,39,3,74,251,244,0,0,0,6,2,176,156,0,255,255,247,164,0,214,3,192,4,180,0,39,3,73,255,112,0,0,0,39,3,74,247,68,0,0,0,7,2,176,251,90,0,0,0,2,252,179,255,246,2,147,5,150,0,7,0,11,0,45,64,26,10,3,4,9,8,7,0,106,1,7,105,11,4,3,106,2,4,105,6,5,2,1,106,2,151,114,0,43,43,57,57,43,43,50,43,43,50,57,17,18,57,48,49,5,1,53,1,21,1,21,1,21,39,17,55,2,147,250,32,5,224,251,34,4,222,200,200,10,2,106,202,2,108,240,254,40,18,254,42,240,100,4,216,100,0,3,248,144,254,202,2,28,6,194,0,7,0,11,0,15,0,49,64,30,13,15,106,13,149,114,10,11,4,3,106,2,4,105,9,8,7,0,106,1,7,105,6,5,2,1,106,2,151,114,0,43,43,57,57,43,43,50,57,43,43,50,57,43,43,48,49,5,1,53,1,21,1,21,1,21,39,17,55,1,17,51,17,254,112,250,32,5,224,251,34,4,222,200,200,2,228,200,10,2,106,202,2,108,240,254,40,18,254,42,240,100,4,216,100,249,52,7,248,248,8,0,0,4,243,224,254,202,1,88,6,194,0,7,0,11,0,15,0,19,0,53,64,32,16,13,15,106,17,13,149,114,10,11,4,3,106,2,4,105,9,8,7,0,106,1,7,105,6,5,2,1,106,2,151,114,0,43,43,57,57,43,43,50,57,43,43,50,57,43,50,43,50,48,49,5,1,53,1,21,1,21,1,21,39,17,55,1,17,51,17,33,17,51,17,249,192,250,32,5,224,251,34,4,222,200,200,2,232,200,3,32,200,10,2,106,202,2,108,240,254,40,18,254,42,240,100,4,216,100,249,52,7,248,248,8,7,248,248,8,255,255,247,164,254,202,3,192,6,194,0,39,3,73,255,112,0,0,0,39,3,74,247,68,0,0,0,7,4,167,251,90,0,0,0,3,252,24,254,192,3,206,6,204,0,7,0,41,0,45,0,74,64,49,25,26,32,19,35,36,16,15,39,12,10,8,43,22,22,29,105,22,3,114,42,8,96,8,9,106,8,9,114,4,3,106,2,4,106,7,0,106,1,7,105,6,5,2,1,106,2,151,114,0,43,43,57,57,43,43,43,43,43,43,26,16,204,43,43,16,205,18,23,57,48,49,5,1,53,1,21,1,21,1,7,55,50,54,53,52,38,39,39,38,38,53,52,54,51,50,22,23,7,38,38,35,34,6,21,20,22,23,23,22,22,21,20,6,1,17,51,17,1,242,250,38,3,210,253,38,4,226,30,16,140,136,67,63,246,145,155,236,214,147,218,50,168,42,129,75,113,124,74,72,208,158,164,251,254,253,138,42,2,138,202,1,144,216,254,236,18,253,246,198,194,94,94,66,92,28,112,66,186,138,186,204,115,104,127,73,79,97,89,69,87,34,98,74,186,146,193,193,254,212,8,12,247,244,0,4,247,104,254,192,3,192,6,204,0,7,0,35,0,39,0,47,0,104,64,67,43,42,46,47,41,40,106,47,41,106,7,0,106,1,7,105,5,6,2,1,1,46,47,106,44,45,106,46,44,105,4,3,106,2,4,106,2,46,151,114,12,33,15,16,30,29,19,26,8,8,37,22,22,23,106,22,3,114,36,8,96,8,9,106,8,9,114,0,43,43,26,16,204,43,43,16,205,18,23,57,43,50,43,43,43,43,43,50,17,18,57,57,43,43,43,43,17,18,57,57,48,49,5,1,53,1,21,1,21,1,7,55,50,54,53,52,38,39,39,38,38,53,52,54,51,21,34,6,21,20,22,23,23,22,22,21,20,6,1,17,51,17,1,53,1,53,1,53,1,21,253,164,249,196,3,210,253,38,5,68,60,16,140,136,67,63,246,145,155,236,214,112,124,74,72,208,158,164,251,254,253,138,2,20,2,188,251,31,5,227,63,2,159,202,1,144,216,254,236,18,253,215,177,184,103,105,66,92,28,112,66,186,138,186,204,184,103,93,69,87,34,98,74,186,146,198,198,254,222,8,12,247,244,2,22,220,1,10,18,2,2,215,253,131,202,0,255,255,252,84,0,190,3,152,4,204,0,39,3,74,251,244,0,0,0,7,3,67,255,76,0,0,255,255,247,164,0,190,3,192,4,204,0,39,3,73,255,112,0,0,0,39,3,74,247,68,0,0,0,7,3,67,251,90,0,0,0,2,253,74,0,144,2,238,5,154,0,7,0,11,0,43,64,26,6,5,1,2,4,3,106,2,4,106,10,11,106,0,10,105,7,0,106,1,7,106,2,1,106,2,0,47,43,43,43,43,43,43,43,17,18,57,57,48,49,1,1,53,1,21,5,21,5,1,53,33,21,2,238,250,92,5,164,251,144,4,112,250,92,5,164,1,228,1,108,222,1,108,220,246,18,246,253,208,190,190,0,3,247,144,0,92,3,152,5,44,0,11,0,15,0,19,0,58,64,34,2,1,7,8,4,19,9,15,14,6,19,18,11,0,106,11,15,15,14,106,18,15,105,4,3,106,4,18,18,19,106,18,148,114,0,43,43,16,206,43,43,43,16,206,43,17,18,57,17,18,57,18,23,57,48,49,37,1,53,1,21,7,21,1,21,1,21,23,37,37,33,21,1,37,33,21,251,74,252,70,3,186,204,254,56,1,204,200,254,98,254,252,10,240,245,156,1,4,9,96,92,2,44,122,2,42,240,32,70,254,248,18,255,0,82,30,54,186,186,1,204,186,186,0,0,4,242,224,0,112,3,192,5,24,0,11,0,23,0,27,0,31,0,72,64,43,0,12,1,23,8,16,9,15,6,18,29,13,20,19,14,5,4,10,11,8,25,29,28,106,3,21,24,25,106,23,12,106,23,29,24,105,16,15,106,16,29,148,114,0,43,204,43,43,205,43,43,57,57,43,17,23,57,17,57,57,17,51,17,51,17,51,17,51,48,49,55,53,55,53,1,53,1,53,39,53,1,21,1,1,53,1,21,7,21,1,21,1,21,23,37,37,33,5,1,37,33,5,6,200,1,204,254,56,204,3,186,242,218,252,70,3,186,204,254,56,1,204,200,254,98,254,252,14,176,254,252,242,224,1,4,11,144,1,4,112,220,30,82,1,0,18,1,8,70,32,220,253,234,122,253,232,2,24,122,2,22,220,32,70,254,248,18,255,0,82,30,54,166,166,1,224,166,166,0,4,247,144,0,92,3,192,5,44,0,11,0,23,0,27,0,31,0,82,64,48,0,12,1,23,8,16,9,15,20,19,14,13,5,4,10,11,8,28,3,21,24,25,6,18,29,28,23,12,106,23,24,24,25,106,29,24,105,16,15,106,16,29,29,28,106,29,148,114,0,43,43,16,204,43,43,43,16,205,43,17,18,57,57,17,18,57,57,18,23,57,17,51,17,51,17,51,17,51,48,49,55,53,55,53,1,53,1,53,39,53,1,21,1,1,53,1,21,7,21,1,21,1,21,23,37,37,33,5,1,37,33,5,6,200,1,204,254,56,204,3,186,247,138,252,70,3,186,204,254,56,1,204,200,254,98,254,252,10,0,254,252,247,144,1,4,6,224,1,4,92,240,30,82,1,0,18,1,8,70,32,240,253,214,122,253,212,2,44,122,2,42,240,32,70,254,248,18,255,0,82,30,54,186,186,1,204,186,186,0,5,247,144,0,92,3,152,5,44,0,11,0,15,0,19,0,23,0,27,0,72,64,41,20,0,23,11,27,4,26,3,6,25,17,2,7,8,1,4,13,24,17,16,106,21,9,22,12,13,106,11,0,106,11,17,12,105,4,3,106,4,17,148,114,0,43,204,43,43,205,43,43,50,57,57,43,50,17,23,57,17,57,57,17,51,17,51,17,51,17,51,48,49,37,1,53,1,21,7,21,1,21,1,21,23,37,37,33,21,1,37,33,21,1,1,55,1,1,39,1,21,251,74,252,70,3,186,204,254,56,1,204,200,254,98,254,252,9,104,247,36,1,4,7,216,1,136,253,244,132,1,136,254,120,132,2,12,92,2,44,122,2,42,240,32,70,254,248,18,255,0,82,30,54,206,206,1,184,206,206,253,54,1,60,164,254,252,1,238,162,1,60,220,255,255,252,76,0,214,3,200,4,180,0,39,3,74,251,236,0,0,0,7,3,73,255,120,0,0,0,2,252,64,0,164,3,152,4,230,0,7,0,15,0,58,64,34,5,6,13,14,4,2,9,1,10,2,8,0,15,7,12,11,4,3,106,2,4,106,7,0,106,1,7,106,2,1,106,2,151,114,0,43,43,43,43,43,43,50,51,17,51,17,51,17,51,17,51,18,23,57,48,49,55,1,53,1,21,1,21,1,5,1,53,1,21,1,21,1,18,252,46,3,210,253,48,2,208,3,134,252,66,3,190,253,68,2,188,164,1,188,202,1,188,220,254,196,18,254,196,220,1,188,202,1,188,220,254,196,18,254,196,0,0,3,247,144,0,112,3,152,5,24,0,15,0,23,0,27,0,58,64,35,16,0,23,15,20,4,19,3,2,1,18,17,21,22,6,24,25,15,0,106,24,15,105,4,3,106,25,4,105,25,24,106,25,147,114,0,43,43,43,43,43,43,17,18,23,57,17,51,17,51,17,51,17,51,48,49,37,1,53,1,21,14,3,7,17,30,3,23,5,1,53,1,21,1,21,1,19,53,33,21,254,188,252,70,3,186,162,209,124,67,20,19,63,122,212,166,252,142,252,70,3,186,253,108,2,148,246,7,88,112,2,24,122,2,22,240,70,86,44,16,2,254,236,1,21,47,84,65,240,2,24,122,2,22,240,254,166,18,254,164,1,6,188,188,0,4,247,144,0,92,3,152,5,44,0,11,0,19,0,23,0,27,0,80,64,47,7,8,2,1,17,18,14,13,8,22,27,12,0,19,11,16,4,15,3,9,23,22,6,27,26,11,0,106,11,23,23,22,106,26,23,105,4,3,106,4,26,26,27,106,26,148,114,0,43,43,16,206,43,43,43,16,206,43,17,18,57,17,18,57,17,51,17,51,17,51,17,51,17,18,23,57,48,49,37,1,53,1,21,7,21,1,21,1,21,23,5,1,53,1,21,1,21,1,37,37,33,21,1,37,33,21,254,26,252,70,3,186,204,254,56,1,204,200,253,48,252,70,3,186,253,108,2,148,1,50,254,252,8,32,248,108,1,4,6,144,92,2,44,122,2,42,240,32,70,254,248,18,255,0,82,30,240,2,44,122,2,42,240,254,146,18,254,144,54,186,186,1,204,186,186,0,255,255,247,164,0,214,3,152,4,180,0,39,3,74,255,122,0,0,0,39,3,74,247,68,0,0,0,7,3,74,251,100,0,0,0,2,252,64,0,112,3,232,5,24,0,15,0,53,0,57,64,37,36,27,106,47,16,106,22,41,106,22,47,36,3,3,15,0,106,31,15,105,1,2,32,31,106,4,3,106,32,4,105,32,50,105,32,147,114,0,43,43,43,43,43,57,57,43,43,17,23,57,43,43,43,48,49,39,1,53,1,21,14,3,7,17,30,3,23,37,34,38,39,38,38,35,34,14,2,35,34,38,38,35,53,50,22,22,51,50,62,2,51,50,22,23,22,22,51,50,53,53,51,21,16,6,252,70,3,186,162,209,124,67,20,19,63,122,212,166,2,174,81,139,65,53,107,61,57,98,98,110,69,65,123,123,66,71,122,119,65,69,111,99,100,59,75,130,63,53,112,65,120,202,112,2,24,122,2,22,240,70,86,44,16,2,254,236,1,21,47,84,65,138,65,38,31,51,35,45,35,31,31,180,20,21,35,45,35,62,38,31,54,189,70,90,254,142,255,255,247,164,0,214,3,192,4,180,0,39,3,73,255,112,0,0,0,39,3,74,247,68,0,0,0,7,3,79,251,90,0,0,0,2,247,144,0,112,3,232,5,24,0,63,0,79,0,67,64,45,22,11,106,45,52,106,33,0,106,58,39,106,6,27,106,6,58,33,45,22,5,64,68,67,106,17,68,105,79,64,106,16,79,105,66,65,17,16,106,17,48,105,17,147,114,0,43,43,43,57,57,43,43,43,43,17,23,57,43,43,43,43,43,48,49,1,34,38,39,38,38,35,34,14,2,35,34,46,2,35,53,50,30,2,51,50,62,2,51,50,22,23,22,22,51,50,54,55,54,54,51,50,22,23,22,22,51,50,53,53,51,21,16,33,34,38,39,38,38,35,34,6,7,6,6,1,1,53,1,21,14,3,7,17,30,3,23,254,112,90,136,60,58,116,74,74,113,104,116,77,81,116,97,104,69,69,104,97,114,81,78,118,104,116,76,100,147,68,47,101,63,56,120,61,79,163,73,83,149,67,58,110,61,120,202,254,192,88,155,74,55,107,57,55,120,60,79,159,252,147,252,70,3,186,162,209,124,67,20,19,63,122,212,166,1,234,52,33,31,49,23,29,23,10,12,10,196,8,11,8,23,29,23,62,37,26,40,51,32,41,61,68,34,29,54,189,70,90,254,142,70,37,28,50,41,32,41,71,254,134,2,24,122,2,22,240,70,86,44,16,2,254,236,1,21,47,84,65,0,2,252,64,255,66,4,40,6,74,0,7,0,11,0,41,64,26,9,11,106,9,152,114,4,3,106,2,4,106,7,0,106,1,7,105,5,6,2,1,106,2,151,114,0,43,43,57,57,43,43,43,43,43,43,48,49,37,1,53,1,21,1,21,9,2,51,1,1,80,250,240,3,210,253,38,4,54,254,194,3,36,212,252,220,46,2,50,202,1,148,220,254,236,18,254,58,254,76,7,8,248,248,0,0,3,247,144,255,66,3,192,6,74,0,7,0,15,0,19,0,68,64,45,15,8,106,9,15,105,12,11,106,10,12,106,1,0,106,7,1,106,4,5,106,6,4,105,3,2,13,14,4,7,6,17,19,106,17,152,114,9,6,7,106,10,6,151,114,0,43,50,43,50,43,43,17,18,23,57,43,43,43,43,43,43,43,43,48,49,55,53,1,53,1,53,1,21,1,1,53,1,21,1,21,1,3,1,51,1,2,2,188,251,237,5,21,248,224,250,240,3,210,253,38,4,54,252,3,36,212,252,220,214,220,1,10,18,1,173,215,253,216,202,253,206,2,50,202,1,148,220,254,236,18,254,58,254,76,7,8,248,248,0,0,2,252,24,1,182,3,152,3,100,0,29,0,33,0,35,64,22,33,29,105,32,33,106,10,19,106,4,10,105,4,25,106,32,4,105,15,32,147,114,0,43,50,43,43,43,43,43,43,48,49,1,53,52,54,51,50,22,23,22,22,51,50,54,53,53,51,21,20,6,35,34,38,39,38,38,35,34,6,21,21,37,53,33,21,252,24,128,142,77,134,64,58,113,59,45,40,202,114,126,84,154,65,57,98,55,55,50,2,144,4,36,1,182,80,184,166,71,38,34,52,47,52,20,10,163,147,50,39,35,71,66,73,90,168,186,186,0,0,5,252,24,255,13,3,152,5,159,0,44,0,58,0,73,0,85,0,89,0,64,64,42,59,74,106,40,4,106,10,34,106,65,80,106,48,71,86,59,4,54,65,68,10,40,77,51,23,7,27,44,44,27,45,54,106,17,45,105,17,27,106,17,3,114,0,43,43,43,43,17,57,47,18,23,57,18,23,57,43,43,43,43,48,49,1,53,52,54,51,50,22,23,22,22,51,50,54,54,55,54,36,51,50,22,22,21,17,35,17,52,38,35,34,6,7,14,2,35,34,38,39,38,38,35,34,6,21,21,1,32,0,3,54,54,55,18,18,51,50,55,21,6,3,34,38,53,52,54,51,50,22,23,51,17,35,6,6,39,50,54,53,52,38,35,34,6,21,20,22,23,17,51,17,252,24,128,142,77,137,61,50,78,59,52,48,30,24,78,1,23,223,153,201,100,172,142,138,172,215,64,29,71,101,74,61,110,52,57,98,55,55,50,5,74,254,231,254,225,27,44,81,37,7,207,219,125,72,79,152,133,147,147,135,77,111,22,74,74,18,111,25,80,86,78,74,82,90,83,241,172,1,182,80,184,166,67,42,34,52,87,137,73,236,233,132,245,169,254,143,1,107,191,191,215,254,115,145,68,58,31,35,71,66,73,90,253,87,1,61,1,90,20,67,46,254,188,254,220,25,180,25,1,135,247,224,237,233,121,111,254,35,111,121,190,121,111,172,157,134,146,134,147,170,2,89,253,167,0,0,2,253,68,1,110,2,188,4,106,0,27,0,31,0,31,64,17,29,28,106,29,27,24,4,106,10,18,106,24,10,13,27,105,13,0,47,43,57,57,43,43,16,198,43,48,49,1,53,52,54,51,50,30,3,51,50,53,53,51,21,20,6,35,34,46,3,35,34,21,21,3,53,33,21,253,68,179,181,79,143,137,137,143,79,120,202,157,163,79,145,139,139,145,79,150,204,5,120,2,174,70,181,179,43,64,65,43,159,70,90,171,169,43,64,65,43,179,50,254,192,186,186,0,0,2,252,25,0,112,3,192,5,24,0,15,0,53,0,63,64,40,25,44,106,50,19,106,39,30,106,39,50,25,3,13,0,35,53,105,15,14,35,34,1,0,106,35,1,105,34,35,106,12,13,106,34,12,105,34,147,114,0,43,43,43,43,43,43,17,18,57,57,43,17,18,23,57,43,43,43,48,49,55,53,62,3,55,17,46,3,39,53,1,21,5,53,16,33,50,22,23,22,22,51,50,62,2,51,50,22,22,51,21,34,38,38,35,34,14,2,35,34,38,39,38,38,35,34,21,21,6,167,211,122,63,19,20,67,124,209,162,3,186,248,89,1,64,81,139,65,53,107,61,57,98,98,110,69,66,123,123,65,70,123,118,66,69,111,99,100,59,75,130,63,53,112,65,120,112,240,65,84,47,21,1,1,20,2,16,44,86,70,240,253,234,122,182,90,1,114,65,38,31,51,35,45,35,31,31,180,21,20,35,45,35,63,37,32,53,189,70,0,1,252,104,1,190,3,152,4,36,0,53,0,34,64,21,22,30,106,36,16,106,10,44,106,50,4,106,50,10,36,22,4,25,53,105,25,0,47,43,23,57,43,43,43,43,48,49,1,53,52,54,51,50,22,23,22,22,51,50,54,55,54,54,51,50,22,23,22,22,51,50,53,53,51,21,20,6,35,34,38,39,38,38,35,34,6,6,7,14,2,35,34,38,39,38,38,35,34,21,21,252,104,128,142,89,107,54,35,82,56,69,83,48,41,130,106,51,111,65,52,75,29,85,202,114,126,77,92,46,56,83,77,52,63,42,22,31,72,101,76,60,117,53,46,85,40,105,1,190,80,173,157,60,31,19,25,71,62,54,78,41,33,26,35,119,90,80,173,157,45,22,27,41,34,51,25,36,71,48,39,28,25,43,119,90,0,2,247,104,0,112,3,192,5,24,0,63,0,79,0,71,64,47,21,42,106,9,54,106,48,15,106,60,3,106,37,26,106,37,60,48,9,21,5,64,76,77,106,31,76,105,78,79,31,32,65,64,106,32,65,105,32,63,105,31,32,106,31,147,114,0,43,43,43,43,43,17,18,57,57,43,43,17,23,57,43,43,43,43,43,48,49,1,53,16,33,50,22,23,22,22,51,50,54,55,54,54,51,50,22,23,22,22,51,50,62,2,51,50,30,2,51,21,34,46,2,35,34,14,2,35,34,38,39,38,38,35,34,6,7,6,6,35,34,38,39,38,38,35,34,21,21,1,53,62,3,55,17,46,3,39,53,1,21,247,104,1,64,88,155,74,56,106,57,55,120,60,79,159,71,90,136,60,58,117,73,74,113,104,116,77,81,116,97,104,69,69,104,97,114,81,78,118,104,115,77,100,147,68,47,101,63,55,120,62,79,162,74,82,149,68,58,110,61,120,7,212,167,211,122,63,19,20,67,124,209,162,3,186,1,210,90,1,114,70,37,28,50,42,31,41,71,52,33,31,49,23,29,23,10,12,10,196,8,11,8,23,29,23,62,37,26,40,51,32,41,61,68,34,29,54,189,70,254,158,240,65,84,47,21,1,1,20,2,16,44,86,70,240,253,234,122,0,0,3,252,44,1,110,3,152,5,140,0,7,0,11,0,15,0,35,64,20,3,14,15,106,6,7,7,1,11,10,106,14,11,105,14,148,114,1,2,114,0,43,43,43,43,18,57,47,57,43,50,48,49,1,1,33,19,35,3,35,3,1,53,33,21,1,53,33,21,252,44,1,64,1,14,246,220,152,18,226,2,184,3,216,250,252,5,4,2,146,2,250,253,214,1,138,253,166,254,220,186,186,1,244,186,186,0,10,251,220,255,236,4,72,5,160,0,3,0,15,0,27,0,39,0,51,0,63,0,75,0,79,0,91,0,103,0,66,64,42,98,34,46,106,92,28,40,106,80,34,28,105,76,0,77,1,79,78,3,2,8,4,86,34,3,114,64,4,16,106,70,10,22,106,58,4,10,105,52,4,9,114,0,43,50,43,50,43,50,43,50,43,50,18,23,57,43,50,43,50,43,50,48,49,1,39,1,23,1,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,1,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,1,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,37,39,1,23,5,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,252,96,92,4,70,92,254,86,142,172,172,142,141,171,171,141,57,69,69,57,58,70,70,254,84,142,172,172,142,141,171,171,141,57,69,69,57,58,70,70,6,52,142,172,172,142,141,171,171,141,57,69,69,57,58,70,70,253,26,92,4,38,92,253,20,142,172,172,142,141,171,171,141,57,69,69,57,58,70,70,1,50,126,3,26,120,251,154,177,145,147,177,177,147,145,177,168,85,69,71,85,85,71,69,85,2,134,177,145,147,177,174,150,145,177,168,85,69,72,86,86,72,69,85,252,42,177,145,147,177,177,147,145,177,168,85,69,71,85,85,71,69,85,62,126,3,2,120,192,177,145,147,177,174,150,145,177,168,85,69,72,86,86,72,69,85,0,3,0,156,255,239,4,81,5,140,0,11,0,23,0,27,0,35,64,20,0,1,12,25,7,106,8,25,2,114,24,27,21,3,12,18,106,12,9,114,0,43,43,23,57,43,50,43,18,57,57,48,49,1,39,54,54,53,52,38,35,17,32,17,20,1,34,38,53,52,54,51,50,22,21,20,6,55,17,23,17,3,146,84,44,44,197,199,2,71,253,53,117,117,127,127,107,127,138,16,122,2,102,62,49,117,68,107,107,1,40,254,103,205,252,201,96,96,97,96,89,74,100,122,202,4,211,50,251,115,0,5,0,5,255,236,4,79,5,180,0,3,0,15,0,19,0,31,0,35,0,44,64,26,13,19,4,10,106,29,35,20,26,106,20,4,33,18,1,34,4,2,3,106,4,2,105,4,9,114,0,43,43,43,23,57,18,57,43,57,57,43,57,57,48,49,1,3,37,17,1,34,38,53,52,54,51,50,22,21,20,6,55,17,23,17,5,34,38,53,52,54,51,50,22,21,20,6,55,17,55,17,1,94,9,2,250,252,150,101,123,134,110,97,117,128,6,122,1,150,101,123,134,110,97,117,128,6,122,4,60,1,40,80,254,216,251,96,116,96,96,117,111,92,100,122,222,4,154,50,251,152,79,116,96,96,117,111,92,100,122,222,3,172,125,251,215,0,0,1,0,200,4,116,1,244,5,160,0,11,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,0,0,2,0,200,2,191,1,244,5,160,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,3,0,200,1,11,1,244,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,4,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,5,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,6,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,7,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,83,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,8,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,83,0,95,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,7,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,83,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,7,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,83,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,5,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,7,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,83,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,4,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,5,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,7,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,83,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,4,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,4,0,200,255,86,1,244,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,0,3,0,200,2,191,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,4,0,200,2,191,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,5,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,7,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,83,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,4,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,3,0,200,2,191,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,4,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,3,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,3,0,200,255,86,1,244,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,0,2,0,200,1,11,1,244,5,160,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,0,0,3,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,5,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,7,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,83,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,4,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,0,3,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,0,3,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,3,0,200,255,86,1,244,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,2,0,200,4,116,3,232,5,160,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,3,0,200,2,191,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,4,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,3,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,0,2,0,200,2,191,3,232,5,160,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,3,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,5,30,88,62,62,88,88,62,62,88,0,2,0,200,1,11,3,232,5,160,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,2,0,200,255,86,1,244,5,160,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,0,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,2,0,200,255,86,3,232,5,160,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,0,1,0,200,2,191,1,244,3,235,0,11,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,0,0,2,0,200,1,11,1,244,3,235,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,3,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,4,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,5,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,7,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,83,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,4,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,3,0,200,1,11,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,4,0,200,1,11,3,232,3,235,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,3,0,200,1,11,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,5,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,3,0,200,255,86,1,244,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,2,0,200,2,191,3,232,5,160,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,3,0,200,2,191,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,4,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,3,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,2,0,200,2,191,3,232,3,235,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,3,0,200,1,11,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,3,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,2,0,200,1,11,3,232,3,235,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,2,0,200,255,86,1,244,3,235,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,0,0,3,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,2,0,200,255,86,3,232,3,235,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,0,1,0,200,1,11,1,244,2,55,0,11,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,0,0,2,0,200,1,11,3,232,5,160,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,0,3,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,4,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,6,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,71,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,0,3,0,200,1,11,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,2,0,200,1,11,3,232,3,235,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,3,0,200,1,11,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,0,3,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,3,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,2,0,200,1,11,3,232,2,55,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,2,55,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,4,0,200,255,86,3,232,2,55,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,3,0,200,255,86,3,232,2,55,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,2,0,200,255,86,1,244,2,55,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,3,0,200,255,86,3,232,2,55,0,11,0,23,0,35,0,0,5,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,170,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,0,2,0,200,255,86,3,232,2,55,0,11,0,23,0,0,5,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,170,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,0,1,2,188,4,116,3,232,5,160,0,11,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,0,0,2,2,188,2,191,3,232,5,160,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,3,2,188,1,11,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,5,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,59,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,4,2,188,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,1,180,88,62,62,88,88,62,62,88,0,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,0,3,2,188,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,3,105,88,62,62,88,88,62,62,88,0,0,2,2,188,1,11,3,232,5,160,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,0,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,0,3,2,188,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,0,2,0,200,255,86,3,232,5,160,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,5,160,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,2,2,188,255,86,3,232,5,160,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,4,116,88,62,62,88,88,62,62,88,250,226,88,62,62,88,88,62,62,88,0,0,1,2,188,2,191,3,232,3,235,0,11,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,0,0,2,2,188,1,11,3,232,3,235,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,254,76,88,62,62,88,88,62,62,88,0,0,3,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,0,4,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,47,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,0,3,2,188,255,86,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,1,181,88,62,62,88,88,62,62,88,0,0,2,0,200,255,86,3,232,3,235,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,3,235,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,2,2,188,255,86,3,232,3,235,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,2,191,88,62,62,88,88,62,62,88,252,151,88,62,62,88,88,62,62,88,0,0,1,2,188,1,11,3,232,2,55,0,11,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,0,0,2,0,200,255,86,3,232,2,55,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,3,0,200,255,86,3,232,2,55,0,11,0,23,0,35,0,0,1,34,38,53,52,54,51,50,22,21,20,6,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,1,182,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,2,2,188,255,86,3,232,2,55,0,11,0,23,0,0,1,34,38,53,52,54,51,50,22,21,20,6,3,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,62,62,88,88,62,62,88,88,1,11,88,62,62,88,88,62,62,88,254,75,88,62,62,88,88,62,62,88,0,0,1,0,200,255,86,1,244,0,130,0,11,0,0,5,34,38,53,52,54,51,50,22,21,20,6,1,94,62,88,88,62,62,88,88,170,88,62,62,88,88,62,62,88,0,2,0,200,255,86,3,232,0,130,0,11,0,23,0,0,5,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,253,206,62,88,88,62,62,88,88,170,88,62,62,88,88,62,62,88,88,62,62,88,88,62,62,88,0,0,1,2,188,255,86,3,232,0,130,0,11,0,0,5,34,38,53,52,54,51,50,22,21,20,6,3,82,62,88,88,62,62,88,88,170,88,62,62,88,88,62,62,88,255,255,1,116,2,218,3,76,5,140,2,6,2,207,0,0,255,255,1,146,254,76,2,202,0,254,2,6,2,166,0,0,255,255,1,116,2,218,3,76,5,140,2,6,2,207,0,0,0,1,1,176,3,12,3,96,5,190,0,3,0,10,179,0,1,106,0,0,47,43,48,49,1,1,51,3,1,176,1,14,162,150,3,12,2,178,253,78,255,255,0,170,4,224,4,6,5,156,2,6,6,57,0,0,0,2,1,0,4,214,3,176,5,226,0,11,0,23,0,14,181,18,0,6,106,12,0,0,47,50,43,50,48,49,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,42,55,79,79,55,56,78,78,254,36,55,79,79,55,56,78,78,4,214,79,55,56,78,78,56,55,79,79,55,56,78,78,56,55,79,0,1,1,210,4,214,2,222,5,226,0,11,0,10,179,0,6,106,0,0,47,43,48,49,1,34,38,53,52,54,51,50,22,21,20,6,2,88,55,79,79,55,56,78,78,4,214,79,55,56,78,78,56,55,79,0,0,1,1,33,4,224,2,159,6,92,0,3,0,10,179,0,1,106,0,0,47,43,48,49,1,3,51,19,1,223,190,212,170,4,224,1,124,254,132,0,0,1,1,213,4,224,3,83,6,92,0,3,0,10,179,0,1,106,0,0,47,43,48,49,1,19,51,3,1,213,170,212,190,4,224,1,124,254,132,0,0,2,0,219,4,224,3,203,6,92,0,3,0,7,0,14,181,5,0,1,106,4,0,0,47,50,43,50,48,49,1,19,51,3,33,19,51,3,2,87,150,222,170,253,186,150,222,170,4,224,1,124,254,132,1,124,254,132,0,1,1,18,4,224,3,158,6,92,0,7,0,14,181,5,0,1,106,4,0,0,47,50,43,57,48,49,1,19,51,19,35,39,51,7,1,18,240,172,240,212,124,20,124,4,224,1,124,254,132,246,246,0,0,1,1,18,4,224,3,158,6,92,0,7,0,16,182,3,6,6,0,1,106,0,0,47,43,50,18,57,48,49,1,3,51,23,35,55,51,3,2,2,240,212,124,20,124,212,240,4,224,1,124,246,246,254,132,0,0,1,0,251,4,214,3,181,6,67,0,17,0,16,183,14,0,4,106,0,9,106,0,0,47,43,43,50,48,49,1,34,38,53,53,51,21,20,22,51,50,54,53,53,51,21,20,6,2,88,166,183,175,90,84,84,90,175,182,4,214,168,154,43,43,89,97,97,89,43,43,154,168,0,0,2,1,106,4,174,3,70,6,94,0,11,0,19,0,19,64,10,6,16,106,0,6,105,0,12,106,0,0,47,43,43,43,48,49,1,34,38,53,52,54,51,50,22,21,20,6,39,50,53,52,35,34,21,20,2,88,113,125,125,113,113,125,125,113,96,96,96,4,174,113,103,103,113,113,103,103,113,116,100,100,100,100,0,0,1,0,240,4,232,3,202,6,64,0,27,0,23,64,12,9,17,106,23,3,106,9,23,27,12,105,27,0,47,43,57,57,43,43,48,49,19,53,52,51,50,22,23,22,22,51,50,53,53,51,21,20,6,35,34,38,39,38,38,35,34,6,21,21,240,210,40,70,38,50,71,25,54,172,94,94,28,82,53,33,66,32,37,37,4,232,40,250,25,19,25,31,64,90,80,120,120,24,26,17,33,36,38,50,0,0,1,0,170,4,224,4,6,5,156,0,3,0,10,179,0,1,106,0,0,47,43,48,49,19,53,33,21,170,3,92,4,224,188,188,0,0,2,1,100,4,224,3,7,6,156,0,19,0,26,0,20,64,10,25,10,9,106,24,0,10,105,0,16,0,63,43,50,43,50,48,49,1,53,52,62,2,53,52,38,35,55,50,22,21,20,14,2,21,21,39,39,54,54,51,7,34,1,246,32,43,32,34,28,21,94,113,36,46,36,234,67,31,116,65,21,73,4,224,36,39,55,42,40,25,26,30,151,106,87,48,59,45,51,39,9,250,119,34,41,151,0,0,1,1,236,4,184,2,242,6,52,0,3,0,10,179,0,1,106,0,0,47,43,48,49,1,19,51,3,1,236,90,172,50,4,184,1,124,254,132,0,0,1,1,195,3,127,3,140,5,63,0,9,0,17,64,9,1,5,105,1,0,106,1,6,114,0,43,43,43,48,49,1,39,55,54,54,53,51,20,6,7,1,245,50,60,94,93,210,173,174,3,127,165,10,16,138,119,190,219,29,0,1,1,210,254,92,2,222,255,104,0,11,0,10,179,6,0,106,6,0,47,43,48,49,1,34,38,53,52,54,51,50,22,21,20,6,2,88,55,79,79,55,56,78,78,254,92,79,55,56,78,78,56,55,79,0,0,1,1,159,254,32,2,202,255,116,0,3,0,10,179,1,0,106,1,0,47,43,48,49,1,19,51,3,1,159,77,222,117,254,32,1,84,254,172,0,0,1,2,2,254,32,3,124,0,6,0,15,0,25,64,15,1,0,106,7,1,105,10,7,106,9,10,106,9,8,114,0,43,43,43,43,43,48,49,1,53,50,54,53,52,38,35,55,23,7,22,22,21,20,6,2,2,95,93,80,82,69,136,25,86,86,188,254,32,150,36,36,35,33,196,11,95,18,83,66,106,107,0,1,1,156,254,88,3,18,0,32,0,20,0,21,64,11,15,0,106,9,15,105,7,6,9,8,114,0,43,50,50,43,43,48,49,1,34,38,53,52,54,55,53,55,21,34,6,21,20,22,51,50,55,7,6,6,2,140,115,125,70,64,240,106,118,61,55,35,47,18,22,48,254,88,101,91,74,100,18,70,2,32,88,80,42,46,11,170,4,5,255,255,1,33,4,224,2,159,6,92,2,6,6,29,0,0,255,255,1,213,4,224,3,83,6,92,2,6,6,30,0,0,255,255,1,0,4,214,3,176,5,226,0,6,6,27,0,0,255,255,1,210,4,214,2,222,5,226,0,6,6,28,0,0,255,255,1,33,4,224,2,159,6,92,0,6,6,29,0,0,255,255,1,213,4,224,3,83,6,92,0,6,6,30,0,0,255,255,0,219,4,224,3,203,6,92,0,6,6,31,0,0,255,255,1,18,4,224,3,158,6,92,0,6,6,32,0,0,255,255,1,18,4,224,3,158,6,92,0,6,6,33,0,0,255,255,0,251,4,214,3,181,6,67,0,6,6,34,0,0,255,255,1,106,4,174,3,70,6,94,0,6,6,35,0,0,255,255,0,240,4,232,3,202,6,64,0,6,6,36,0,0,255,255,0,170,4,224,4,6,5,156,0,6,6,37,0,0,255,255,2,2,254,32,3,124,0,6,0,6,6,43,0,0,255,255,1,156,254,88,3,18,0,32,0,6,6,44,0,0,0,2,1,2,6,44,3,174,7,56,0,11,0,23,0,14,181,18,0,6,106,12,0,0,47,50,43,50,48,49,1,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,3,40,55,79,79,55,56,78,78,254,40,55,79,79,55,56,78,78,6,44,79,55,56,78,78,56,55,79,79,55,56,78,78,56,55,79,0,1,1,210,6,44,2,222,7,56,0,11,0,10,179,0,6,106,0,0,47,43,48,49,1,34,38,53,52,54,51,50,22,21,20,6,2,88,55,79,79,55,56,78,78,6,44,79,55,56,78,78,56,55,79,0,0,1,0,239,6,44,2,229,7,38,0,3,0,10,179,0,1,106,0,0,47,43,48,49,1,37,33,23,1,243,254,252,1,26,220,6,44,250,250,0,0,1,1,213,6,44,3,203,7,38,0,3,0,10,179,0,1,106,0,0,47,43,48,49,1,55,33,5,1,213,220,1,26,254,252,6,44,250,250,0,0,2,0,249,6,44,4,77,7,38,0,3,0,7,0,14,181,5,0,1,106,4,0,0,47,50,43,50,48,49,1,55,33,7,33,55,33,7,2,147,160,1,26,200,253,116,160,1,26,200,6,44,250,250,250,250,0,1,1,3,6,44,3,183,7,48,0,7,0,14,181,5,0,1,106,4,0,0,47,50,43,57,48,49,1,1,51,1,35,39,51,7,1,3,1,4,172,1,4,222,177,106,177,6,44,1,4,254,252,205,205,0,0,1,0,254,6,44,3,178,7,48,0,7,0,14,181,4,6,0,1,106,0,0,47,43,50,57,48,49,1,1,51,23,35,55,51,1,2,2,254,252,222,134,20,134,222,254,252,6,44,1,4,156,156,254,252,0,0,1,0,226,6,34,3,206,7,68,0,13,0,16,183,11,0,3,106,0,7,106,0,0,47,43,43,50,48,49,1,34,38,53,51,20,22,51,50,54,53,51,20,6,2,88,178,196,175,105,94,95,104,175,196,6,34,152,138,73,81,81,73,138,152,0,0,2,1,106,5,208,3,70,7,108,0,11,0,23,0,19,64,10,6,18,106,0,6,105,0,12,106,0,0,47,43,43,43,48,49,1,34,38,53,52,54,51,50,22,21,20,6,39,50,54,53,52,38,35,34,6,21,20,22,2,88,113,125,125,113,113,125,125,113,47,49,49,47,46,50,50,5,208,108,98,98,108,108,98,98,108,116,47,43,44,47,47,44,43,47,0,0,1,0,215,6,30,3,217,7,98,0,27,0,23,64,12,10,18,106,24,4,106,10,24,27,13,105,27,0,47,43,57,57,43,43,48,49,19,53,52,54,51,50,22,23,22,22,51,50,53,53,51,21,20,6,35,34,38,39,38,38,35,34,21,21,215,105,105,41,89,58,59,62,25,54,172,94,94,34,94,65,43,72,26,74,6,30,50,125,125,25,24,24,27,64,60,50,120,120,28,27,18,27,74,60,0,0,1,0,213,6,44,3,219,6,232,0,3,0,10,179,0,1,106,0,0,47,43,48,49,19,53,33,21,213,3,6,6,44,188,188,0,0,1,1,100,5,249,3,67,7,112,0,22,0,16,183,14,9,106,22,14,105,22,0,0,47,47,43,43,48,49,1,53,52,54,55,54,54,53,52,35,34,7,39,54,51,50,21,20,6,7,6,6,21,2,20,30,36,39,32,82,96,68,67,81,171,227,54,65,16,13,5,249,21,18,35,25,25,33,16,51,43,119,75,163,60,79,38,9,16,10,0,1,1,135,4,181,3,80,6,117,0,9,0,14,182,1,5,105,1,0,106,1,0,47,43,43,48,49,1,39,55,54,54,53,51,20,6,7,1,185,50,60,103,102,192,173,174,4,181,165,10,17,137,119,190,219,29,0,0,1,1,223,4,224,3,13,6,112,0,3,0,10,179,0,1,106,0,0,47,43,48,49,1,19,51,3,1,223,90,212,110,4,224,1,144,254,112,0,0,1,2,7,6,4,3,23,7,48,0,3,0,10,179,0,1,106,0,0,47,43,48,49,1,19,51,3,2,7,30,242,90,6,4,1,44,254,212,0,255,255,0,240,4,232,3,202,6,64,2,6,6,36,0,0,255,255,1,213,4,224,3,83,6,92,0,6,6,30,0,0,255,255,1,213,4,224,3,83,6,92,2,6,6,76,0,0,0,3,0,136,4,214,4,50,6,92,0,3,0,15,0,27,0,23,64,11,10,16,22,106,16,16,4,3,1,106,3,0,47,43,51,51,47,43,50,48,49,1,19,51,3,5,34,38,53,52,54,51,50,22,21,20,6,33,34,38,53,52,54,51,50,22,21,20,6,1,202,130,212,150,254,132,55,79,79,55,56,78,78,2,102,55,79,79,55,56,78,78,4,224,1,124,254,132,10,79,55,56,78,78,56,55,79,79,55,56,78,78,56,55,79,0,0,1,0,253,4,214,3,179,6,67,0,13,0,16,183,11,0,3,106,0,7,106,0,0,47,43,43,50,48,49,1,34,38,53,51,20,22,51,50,54,53,51,20,6,2,88,179,168,188,72,87,89,70,188,169,4,214,181,184,120,109,111,118,185,180,0,0,1,1,0,6,34,3,176,7,68,0,13,0,16,183,11,0,3,106,0,7,106,0,0,47,43,43,50,48,49,1,34,38,53,51,20,22,51,50,54,53,51,20,6,2,88,163,181,195,78,71,71,78,195,180,6,34,152,138,88,66,66,88,138,152,0,0,6,0,160,254,192,4,110,6,204,0,3,0,7,0,25,0,29,0,33,0,51,0,56,64,32,0,45,45,27,43,106,33,19,51,32,4,17,35,105,17,17,26,1,27,2,114,5,25,25,26,9,106,4,96,26,8,114,0,43,26,206,43,51,17,57,43,206,18,57,47,43,23,57,43,51,17,57,48,49,1,17,51,17,3,17,51,17,1,53,33,50,54,53,52,38,35,33,39,33,50,22,21,20,6,35,33,17,51,17,3,53,33,21,37,53,51,50,54,53,52,38,35,35,39,33,50,22,21,20,6,35,2,2,138,138,138,254,206,1,44,132,146,152,140,254,230,24,1,100,216,236,224,206,253,224,200,82,1,160,254,164,240,113,125,131,121,222,24,1,0,216,236,224,206,5,44,1,160,254,96,249,148,1,133,254,123,1,64,190,121,109,112,123,91,186,170,186,204,5,140,250,116,2,186,98,98,56,91,101,94,92,98,190,187,173,147,159,0,3,0,129,254,192,4,37,6,204,0,3,0,7,0,47,0,46,64,29,3,28,35,105,18,45,21,22,42,41,25,38,32,31,10,8,2,96,28,3,114,6,8,15,105,7,8,9,114,0,43,205,43,57,43,26,205,18,23,57,43,57,48,49,1,17,51,17,3,17,51,17,3,34,38,39,55,22,22,51,50,54,53,52,38,39,39,38,38,53,52,54,51,50,22,23,7,38,38,35,34,6,21,20,22,23,23,22,22,21,20,6,2,32,138,138,138,131,121,211,90,26,110,205,97,140,136,67,63,246,145,155,224,205,143,220,102,140,88,153,83,103,113,74,72,208,158,164,251,5,56,1,148,254,108,249,136,1,146,254,110,1,44,39,39,202,47,49,98,100,66,92,28,112,66,186,138,186,204,84,95,142,72,65,99,97,69,87,34,98,74,186,146,193,193,0,0,4,252,10,254,192,3,197,6,204,0,7,0,11,0,45,0,49,0,74,64,47,2,3,7,6,49,33,64,22,43,25,26,40,39,29,36,8,12,48,32,3,114,12,19,105,11,96,12,9,114,1,0,106,7,1,106,6,7,106,4,5,106,6,4,106,6,151,114,0,43,43,43,43,43,43,43,26,205,43,43,204,18,23,57,26,205,50,17,18,57,57,48,49,55,53,1,53,1,53,1,21,1,17,51,17,3,34,38,39,55,22,22,51,50,54,53,52,38,39,39,38,38,53,52,54,51,21,34,6,21,20,22,23,23,22,22,21,20,6,1,17,51,17,7,2,188,250,247,6,11,249,231,138,134,121,211,90,26,110,205,97,140,136,67,63,246,145,155,236,214,112,124,74,72,208,158,164,251,254,253,138,214,220,1,10,18,2,26,215,253,107,202,252,96,1,138,254,118,1,44,39,39,194,43,45,98,100,66,92,28,112,66,186,138,186,204,184,103,93,69,87,34,98,74,186,146,193,193,4,252,1,228,254,28,0,0,4,252,24,254,192,3,206,6,204,0,7,0,41,0,45,0,49,0,78,64,51,6,5,1,2,47,22,29,105,12,39,15,16,36,35,19,32,26,25,10,8,49,22,3,114,42,8,9,106,45,96,8,9,114,4,3,106,2,4,106,7,0,106,1,7,105,2,1,106,2,151,114,0,43,43,43,43,43,43,43,26,204,43,50,43,205,18,23,57,43,57,17,18,57,57,48,49,5,1,53,1,21,1,21,1,7,55,50,54,53,52,38,39,39,38,38,53,52,54,51,50,22,23,7,38,38,35,34,6,21,20,22,23,23,22,22,21,20,6,37,51,17,35,19,35,17,51,2,4,250,20,3,210,253,38,4,244,48,16,140,136,67,63,246,145,155,236,214,147,218,50,168,42,129,75,113,124,74,72,208,158,164,251,254,253,138,138,138,138,138,50,2,146,202,1,144,216,254,236,18,253,238,190,194,94,94,66,92,28,112,66,186,138,186,204,115,104,127,73,79,97,89,69,87,34,98,74,186,146,193,193,194,254,18,6,125,1,143,0,0,5,247,104,254,192,3,192,6,204,0,7,0,11,0,39,0,43,0,51,0,0,5,1,53,1,21,1,21,1,3,17,51,17,3,55,50,54,53,52,38,39,39,38,38,53,52,54,51,21,34,6,21,20,22,23,23,22,22,21,20,6,1,17,51,17,1,53,1,53,1,53,1,21,253,164,249,196,3,210,253,38,5,68,64,138,134,16,140,136,67,63,246,145,155,236,214,112,124,74,72,208,158,164,251,254,253,138,2,20,2,188,250,202,6,56,63,2,159,202,1,144,216,254,236,18,253,215,254,45,1,218,254,38,1,34,184,103,105,66,92,28,112,66,186,138,186,204,184,103,93,69,87,34,98,74,186,146,198,198,5,6,1,228,254,28,251,238,220,1,10,18,2,37,215,253,96,202,0,1,0,0,0,1,0,2,0,0,12,198,6,88,0,0,0,0,12,202,0,0,0,26,0,54,0,63,0,72,0,81,0,90,0,99,0,108,0,117,0,126,0,136,0,148,0,158,0,170,0,182,0,192,0,201,0,210,0,219,0,228,0,237,1,45,1,54,1,65,1,74,1,119,1,128,1,217,2,3,2,12,2,21,2,30,2,40,2,49,2,90,2,136,2,145,2,154,2,182,2,191,2,200,2,209,2,219,2,231,2,241,2,253,3,9,3,19,3,28,3,37,3,46,3,55,3,64,3,73,3,143,3,222,3,231,3,240,4,50,4,73,4,137,4,146,4,155,4,165,4,174,4,183,4,204,4,232,4,241,4,251,5,18,5,86,5,95,5,104,5,114,5,123,5,132,5,141,5,150,5,159,5,168,5,231,5,240,6,28,6,40,6,85,6,94,6,112,6,121,6,147,6,156,6,168,6,196,6,249,7,31,7,40,7,49,7,58,7,122,7,186,7,195,7,218,7,227,7,236,7,246,8,2,8,14,8,26,8,38,8,48,8,57,8,67,8,76,8,85,8,94,8,103,8,112,8,121,8,130,8,139,8,148,8,157,8,225,9,16,9,48,9,57,9,66,9,131,9,175,9,226,10,19,10,72,10,81,10,90,10,99,10,185,10,195,10,205,10,214,10,226,10,235,11,47,11,97,11,114,11,137,11,146,11,155,11,164,11,183,11,192,11,201,11,211,11,220,11,229,11,238,11,247,12,38,12,47,12,56,12,65,12,74,12,83,12,92,12,101,12,173,12,182,12,191,12,213,12,222,13,14,13,23,13,33,13,42,13,51,13,85,13,115,13,124,13,134,13,143,13,152,13,161,13,170,13,179,13,188,13,217,13,227,13,237,13,247,14,2,14,11,14,20,14,29,14,39,14,49,14,74,14,169,14,178,14,187,14,196,14,205,14,214,14,223,14,233,14,242,14,251,15,4,15,13,15,22,15,31,15,41,15,50,15,59,15,68,15,77,15,86,15,215,15,224,15,234,15,244,16,116,16,125,16,173,16,221,16,230,16,239,16,248,17,1,17,10,17,71,17,149,17,214,18,26,18,85,18,94,18,103,18,112,18,121,18,130,18,139,18,148,18,157,18,167,18,176,18,185,18,194,18,203,18,212,18,221,19,67,19,76,19,85,19,95,19,160,19,231,20,12,20,96,20,105,20,114,20,123,20,132,20,141,20,179,20,222,20,232,20,242,21,44,21,72,21,81,21,90,21,99,21,108,21,117,21,126,21,135,21,223,21,232,22,79,22,89,22,156,22,198,22,208,22,249,23,2,23,43,23,90,23,99,23,150,23,159,23,169,23,223,24,27,24,65,24,74,24,114,24,123,24,132,24,197,25,8,25,18,25,57,25,66,25,75,25,84,25,93,25,102,25,111,25,120,25,130,25,139,25,148,25,157,25,166,25,176,25,185,25,194,25,203,25,212,25,222,25,231,25,240,26,72,26,120,26,171,26,180,26,190,27,20,27,85,27,148,27,213,28,5,28,14,28,23,28,32,28,119,28,128,28,137,28,146,28,155,28,164,29,22,29,57,29,108,29,166,29,219,29,228,29,237,30,71,30,122,30,131,30,140,30,149,30,158,30,167,30,176,30,185,31,1,31,10,31,19,31,28,31,37,31,47,31,56,31,65,31,148,31,157,31,167,31,189,31,198,31,244,31,253,32,6,32,15,32,24,32,58,32,106,32,115,32,124,32,133,32,142,32,151,32,160,32,169,32,179,32,209,32,218,32,227,32,236,33,50,33,98,33,107,33,116,33,125,33,134,33,143,33,152,34,66,34,146,34,180,34,223,34,232,35,26,35,35,35,52,35,61,35,83,35,138,35,147,35,156,35,165,36,90,36,181,36,219,36,228,36,237,37,82,37,91,37,132,37,141,37,150,37,159,37,179,37,188,37,197,37,206,37,250,38,3,38,56,38,65,38,97,38,124,38,148,38,178,38,203,38,253,39,55,39,112,39,188,40,2,40,11,40,57,40,115,40,124,40,133,40,142,40,179,40,231,41,74,41,124,41,147,42,89,42,197,42,223,42,232,43,13,43,55,43,93,43,124,43,133,43,142,43,151,43,181,43,190,43,237,44,4,44,72,44,81,44,150,44,229,44,246,44,255,45,21,45,77,45,86,45,95,45,104,46,4,46,97,46,133,46,142,46,151,46,253,47,6,47,49,47,99,47,121,47,130,47,150,47,159,47,168,47,185,47,194,47,203,48,48,48,57,48,94,48,121,48,145,48,181,48,206,48,249,49,43,49,97,49,170,49,236,49,245,50,45,50,96,50,105,50,114,50,123,50,166,50,213,51,55,51,133,51,156,52,99,52,208,52,235,53,7,53,42,53,84,53,128,53,137,53,146,53,155,53,164,53,206,53,215,54,21,54,113,54,122,55,43,55,135,55,144,55,153,55,162,56,8,56,30,56,39,56,48,56,105,56,172,56,247,57,37,57,93,57,143,57,237,57,246,57,255,58,8,58,37,58,46,58,55,58,64,58,95,58,104,58,113,58,122,58,131,58,140,58,164,58,173,58,182,58,191,58,230,58,239,58,248,59,1,59,10,59,47,59,121,59,157,59,198,59,230,60,8,60,42,60,79,60,142,60,151,60,160,60,225,61,43,61,130,61,168,62,6,62,80,62,149,62,187,62,233,63,12,63,53,63,130,63,187,63,232,64,82,64,91,64,141,64,202,65,21,65,76,65,120,65,164,65,227,66,39,66,80,66,159,66,168,66,177,66,186,66,195,66,204,66,213,66,222,66,231,66,240,66,249,67,2,67,61,67,103,67,131,67,188,68,28,68,67,68,140,68,205,68,236,69,57,69,129,69,166,69,175,69,184,69,193,69,202,69,211,69,220,69,229,69,238,69,247,70,0,70,9,70,18,70,27,70,36,70,45,70,54,70,63,70,72,70,81,70,90,70,99,70,108,70,117,70,126,70,135,70,144,70,153,70,162,70,171,70,180,70,217,70,246,71,45,71,130,71,165,71,226,72,34,72,61,72,122,72,187,72,205,73,42,73,116,73,237,74,78,74,233,75,103,75,196,75,224,75,238,76,34,76,71,76,80,76,120,76,160,76,253,77,87,77,97,77,129,77,178,77,187,77,215,77,224,77,237,77,251,78,9,78,45,78,83,78,172,79,10,79,33,79,56,79,74,79,92,79,110,79,128,79,137,79,146,79,160,79,174,79,183,79,192,79,201,79,215,79,225,79,234,79,243,79,252,80,5,80,20,80,35,80,44,80,86,80,127,80,154,80,181,80,193,80,207,80,225,80,247,81,43,81,63,81,115,81,180,81,212,82,14,82,86,82,180,83,32,83,161,83,188,83,230,84,7,84,16,84,25,84,80,84,148,84,157,84,194,84,203,84,212,85,58,85,121,85,192,86,8,86,17,86,26,86,35,86,44,86,68,86,96,86,105,86,114,86,123,86,232,87,69,87,78,87,87,87,96,87,105,87,164,88,35,88,76,88,85,88,94,88,214,88,223,89,43,89,139,89,175,89,223,90,51,90,60,90,91,90,130,90,161,90,170,90,179,90,188,90,206,90,220,90,231,90,240,90,240,90,240,90,240,90,240,90,240,91,77,91,123,91,175,91,225,92,54,92,145,92,219,93,20,93,83,93,148,93,177,94,1,94,107,94,163,94,226,95,45,95,100,95,133,95,178,95,228,96,27,96,82,96,197,97,10,97,51,97,117,97,143,97,180,97,235,98,22,98,31,98,40,98,65,98,74,98,108,98,140,98,159,98,191,98,212,98,226,98,252,99,46,99,65,99,91,99,120,99,147,99,182,99,217,99,244,99,253,100,61,100,80,100,102,100,182,100,210,101,13,101,22,101,31,101,51,101,90,101,122,101,131,101,140,101,158,101,242,102,75,102,101,102,110,102,137,102,167,102,197,102,227,103,23,103,68,103,118,103,162,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,207,103,240,104,20,104,63,104,102,104,141,104,180,104,180,104,180,104,213,104,246,105,33,105,76,105,119,105,162,105,204,106,175,106,214,106,223,106,248,106,248,107,28,107,54,107,79,107,106,107,134,107,155,107,175,107,196,107,217,107,217,107,236,107,255,108,18,108,37,108,56,108,79,108,104,108,104,108,131,108,131,108,131,108,145,108,159,108,159,108,173,108,212,108,226,109,99,109,120,109,141,109,174,109,219,110,9,110,82,110,82,110,96,110,110,110,124,110,138,110,152,110,170,110,192,110,214,110,236,111,2,111,16,111,16,111,25,111,25,111,25,111,25,111,25,111,25,111,47,111,71,111,94,111,117,111,139,111,161,111,182,111,182,111,182,111,205,111,228,111,228,111,228,111,228,111,228,111,251,112,18,112,41,112,63,112,63,112,63,112,63,112,63,112,91,112,119,112,147,112,175,112,210,112,239,113,11,113,32,113,67,113,96,113,125,113,145,113,194,113,227,114,4,114,25,114,43,114,61,114,80,114,97,114,119,114,136,114,158,114,182,114,201,114,218,114,240,115,1,115,23,115,47,115,74,115,92,115,110,115,128,115,146,115,160,115,179,115,196,115,213,115,227,115,241,115,255,116,25,116,51,116,65,116,87,116,109,116,123,116,142,116,159,116,178,116,195,116,209,116,233,116,251,117,14,117,38,117,57,117,76,117,100,117,122,117,144,117,168,117,192,117,220,117,248,118,20,118,48,118,89,118,109,118,130,118,148,118,166,118,180,118,199,118,216,118,233,118,247,119,5,119,19,119,45,119,71,119,85,119,107,119,129,119,143,119,162,119,181,119,198,119,215,119,229,119,253,120,16,120,34,120,58,120,77,120,96,120,120,120,142,120,164,120,188,120,212,120,233,120,251,121,13,121,37,121,56,121,78,121,95,121,117,121,134,121,158,121,177,121,199,121,216,121,238,121,255,122,26,122,44,122,62,122,89,122,113,122,138,122,162,122,180,122,199,122,223,122,242,123,4,123,31,123,51,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,70,123,194,124,7,124,65,124,163,124,228,125,68,125,96,125,189,125,223,125,237,126,3,126,127,126,215,127,50,127,86,127,226,128,48,128,133,128,213,129,18,129,103,129,136,129,151,129,172,129,186,129,204,129,230,130,31,130,78,130,139,130,212,130,212,130,212,130,212,130,212,130,212,130,212,130,212,130,212,130,212,130,212,130,212,130,212,130,212,130,212,130,212,130,212,130,212,130,226,130,240,130,240,130,254,131,12,131,46,131,71,131,85,131,114,131,141,131,164,131,183,131,208,131,222,132,154,132,175,133,23,133,50,133,59,133,96,133,124,133,157,133,180,133,209,134,49,134,58,134,113,134,124,134,133,134,142,134,168,134,190,134,238,135,30,135,91,135,141,135,166,135,200,136,14,136,23,136,50,136,116,136,156,136,204,136,254,137,7,137,58,137,109,137,199,138,13,138,22,138,110,138,120,138,129,138,157,138,190,138,227,138,236,139,78,139,182,139,192,139,201,139,228,140,21,140,99,140,179,140,250,141,4,141,43,141,108,141,172,141,181,142,41,142,50,142,183,142,214,143,6,143,82,144,13,144,79,144,200,145,62,145,201,145,236,146,143,146,206,147,32,147,32,147,66,147,112,147,176,148,2,148,102,148,220,149,100,149,254,150,134,150,252,151,132,151,250,152,94,152,212,153,92,153,210,154,54,154,172,155,16,155,98,155,198,156,60,156,196,157,58,157,158,158,20,158,120,158,202,159,46,159,164,160,8,160,90,160,190,161,16,161,80,161,162,162,6,162,124,163,4,163,122,163,222,164,84,164,184,165,10,165,110,165,228,166,72,166,154,166,254,167,80,167,144,167,226,168,70,168,188,169,32,169,114,169,214,170,40,170,104,170,186,171,30,171,112,171,176,172,2,172,66,172,112,172,176,173,2,173,102,173,220,174,100,174,218,175,62,175,180,176,24,176,106,176,206,177,68,177,168,177,250,178,94,178,176,178,240,179,66,179,166,180,28,180,128,180,210,181,54,181,136,181,200,182,26,182,126,182,208,183,16,183,98,183,162,183,208,184,16,184,98,184,198,185,60,185,160,185,242,186,86,186,168,186,232,187,58,187,158,187,240,188,48,188,130,188,194,188,240,189,48,189,130,189,230,190,56,190,120,190,202,191,10,191,56,191,120,191,202,192,10,192,56,192,120,192,166,192,194,192,240,193,48,193,130,193,230,194,92,194,228,195,90,195,190,196,52,196,152,196,234,197,78,197,196,198,40,198,122,198,222,199,48,199,112,199,194,200,38,200,156,201,0,201,82,201,182,202,8,202,72,202,154,202,254,203,80,203,144,203,226,204,34,204,80,204,144,204,226,205,70,205,188,206,32,206,114,206,214,207,40,207,104,207,186,208,30,208,112,208,176,209,2,209,66,209,112,209,176,210,2,210,102,210,184,210,248,211,74,211,138,211,184,211,248,212,74,212,138,212,184,212,248,213,38,213,66,213,112,213,176,214,2,214,102,214,220,215,64,215,146,215,246,216,72,216,136,216,218,217,62,217,144,217,208,218,34,218,98,218,144,218,208,219,34,219,134,219,216,220,24,220,106,220,170,220,216,221,24,221,106,221,170,221,216,222,24,222,70,222,98,222,144,222,208,223,34,223,134,223,216,224,24,224,106,224,170,224,216,225,24,225,106,225,170,225,216,226,24,226,70,226,98,226,144,226,208,227,34,227,98,227,144,227,208,227,254,228,26,228,72,228,136,228,182,228,210,229,0,229,28,229,37,229,46,229,55,229,70,229,79,229,128,229,153,229,167,229,181,229,199,229,219,229,239,230,12,230,40,230,98,230,113,230,176,230,190,230,206,230,231,230,245,231,30,231,74,231,83,231,92,231,101,231,110,231,119,231,128,231,137,231,146,231,155,231,164,231,173,231,182,231,191,231,200,231,209,232,5,232,30,232,46,232,62,232,81,232,103,232,125,232,153,232,202,233,9,233,22,233,75,233,104,233,118,233,132,233,141,233,150,233,159,233,217,233,244,234,16,234,16,234,16,234,119,234,226,235,80,235,190,236,47,192,0,64,0,128,2,0,12,0,15,0,0,0,15,0,1,8,7,1,2,2,2,2,2,2,2,7,96,230,26,230,26,160,26,230,129,0,154,131,0,102,7,212,20,236,20,236,44,236,20,129,0,64,131,0,192,128,2,0,12,0,20,0,0,0,23,0,1,0,7,24,81,175,232,95,252,4,161,135,132,6,95,95,0,51,205,205,51,131,4,236,236,20,20,186,129,0,70,135,132,65,255,46,255,46,128,3,164,228,228,164,131,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,251,131,133,133,133,128,2,0,12,0,6,0,0,0,5,0,1,0,128,1,251,171,131,134,129,0,40,131,134,128,2,0,12,0,5,0,0,0,2,0,1,0,129,0,251,131,134,134,134,128,2,0,12,0,6,0,0,0,5,0,1,0,128,1,251,211,131,134,129,0,40,131,134,128,2,0,12,0,6,0,0,0,5,0,1,0,128,1,251,211,131,134,129,0,40,131,134,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,251,132,134,134,134,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,57,0,0,0,57,0,1,0,27,251,15,45,45,45,57,95,90,230,235,221,241,241,241,251,246,244,255,254,251,24,81,175,232,95,252,4,161,135,129,3,226,206,196,197,131,8,172,138,156,171,171,171,165,0,254,133,6,95,95,0,51,205,205,51,131,132,2,224,196,211,129,14,28,60,60,60,30,32,30,30,22,6,236,236,20,20,186,129,0,70,135,129,5,5,10,255,249,0,238,130,7,20,40,60,60,60,64,4,1,133,65,255,46,255,46,128,3,164,228,228,164,131,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,6,0,0,0,2,0,1,0,0,226,132,0,8,132,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,30,0,0,0,30,0,1,15,14,0,1,2,1,1,2,2,2,2,2,2,2,2,2,2,14,26,125,236,40,177,20,0,40,230,40,206,40,230,40,230,129,5,84,84,0,217,38,164,130,3,210,46,0,92,14,239,156,10,196,73,0,10,226,20,226,40,226,20,226,20,129,5,182,182,0,246,157,74,130,3,37,219,0,182,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,87,0,0,0,77,32,1,0,43,170,170,20,56,94,94,94,65,40,170,170,10,250,232,232,232,223,216,24,24,170,170,230,230,10,10,170,170,0,45,94,94,94,54,20,170,170,0,244,232,232,232,25,70,131,128,14,154,154,154,186,216,3,51,51,51,4,4,4,252,246,251,133,13,35,231,231,35,4,205,205,205,249,30,63,102,102,102,130,4,4,10,8,4,4,131,26,25,1,1,3,3,1,2,3,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,2,3,2,1,25,56,0,196,0,56,100,20,9,0,236,56,56,30,56,0,232,196,196,196,232,0,56,0,20,61,100,5,64,64,20,224,224,242,134,12,32,32,32,8,246,222,192,192,192,0,10,14,14,0,128,2,0,12,0,38,0,0,0,32,0,1,0,21,246,14,14,14,1,246,238,225,222,49,39,8,246,201,148,148,148,226,235,243,222,233,131,136,10,80,86,94,94,94,45,0,162,162,162,169,133,128,6,236,236,236,246,0,249,248,132,3,25,56,56,56,136,134,12,2,5,205,190,175,175,175,217,0,81,81,81,81,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,251,131,133,133,133,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,34,0,0,0,34,0,1,0,19,170,170,0,49,94,94,94,49,0,170,170,0,232,232,232,0,24,24,170,170,131,128,8,154,154,154,205,0,51,102,102,102,141,19,56,56,0,227,196,196,196,227,0,56,56,0,20,20,20,0,236,236,56,56,131,128,8,75,75,75,42,0,214,181,181,181,141,0,128,2,0,12,0,39,0,0,0,39,0,1,0,131,19,170,170,0,49,94,94,94,49,0,170,170,0,232,232,232,0,24,24,170,170,131,13,51,205,205,51,0,154,154,154,205,0,51,102,102,102,141,131,19,56,56,0,227,196,196,196,227,0,56,56,0,20,20,20,0,236,236,56,56,131,13,224,32,32,224,0,75,75,75,42,0,214,181,181,181,141,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,17,0,0,0,17,0,1,8,7,1,2,2,2,2,2,2,2,7,24,170,24,232,24,232,24,232,129,5,154,0,205,51,0,102,7,236,56,236,20,236,20,236,20,129,5,64,0,32,224,0,192,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,251,131,133,133,133,128,2,0,12,0,6,0,0,0,5,0,1,0,128,1,251,171,131,134,129,0,40,131,134,128,2,0,12,0,5,0,0,0,2,0,1,0,129,0,251,131,134,134,134,128,2,0,12,0,6,0,0,0,5,0,1,0,128,1,251,211,131,134,129,0,40,131,134,128,2,0,12,0,6,0,0,0,5,0,1,0,128,1,251,211,131,134,129,0,40,131,134,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,251,132,134,134,134,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,75,0,0,0,52,32,1,0,7,247,253,1,1,1,7,10,10,64,255,126,27,231,214,197,197,197,223,247,242,240,251,250,247,24,24,170,170,24,24,232,232,24,24,232,232,24,24,232,232,131,129,5,253,250,239,248,10,20,130,8,227,216,194,171,171,171,165,0,254,133,7,154,154,0,51,205,205,51,102,129,0,102,131,17,16,0,1,2,2,1,3,3,3,3,4,2,2,2,2,2,2,2,128,2,252,246,252,129,10,50,20,20,236,56,236,20,236,20,236,20,130,4,247,246,0,50,60,130,5,64,0,32,224,0,192,128,2,0,12,0,89,0,0,0,55,32,1,0,12,246,227,230,237,55,39,3,246,227,168,168,168,209,130,21,215,164,164,164,213,0,255,255,254,254,232,236,242,251,0,8,18,24,24,24,18,7,131,4,12,24,24,24,33,131,129,23,2,5,80,84,94,94,94,56,0,231,207,206,50,50,50,4,216,191,162,162,162,163,168,171,133,6,246,227,216,228,243,251,251,129,4,251,244,253,0,11,132,19,18,0,1,1,1,1,3,3,2,1,2,3,1,2,4,1,4,5,10,1,129,1,2,20,129,1,62,34,129,8,62,62,0,20,20,0,236,236,246,129,11,254,10,215,175,0,36,38,218,0,39,81,81,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,61,0,0,0,57,32,1,0,29,10,20,24,203,214,232,253,10,51,92,92,92,36,216,254,4,105,80,24,24,232,232,131,136,197,232,232,232,244,5,131,130,15,182,176,167,164,164,164,200,236,12,31,31,31,225,96,98,98,129,7,98,225,223,223,236,231,232,245,132,17,16,1,1,1,1,1,2,3,3,2,1,1,2,2,1,1,1,2,6,244,236,30,25,15,0,194,129,3,156,0,236,20,64,0,130,128,1,10,20,129,14,80,81,81,81,20,201,45,188,188,0,188,45,45,45,0,0,128,2,0,12,0,13,0,0,0,13,0,1,6,5,1,2,2,2,2,2,5,24,170,24,16,24,232,129,3,205,51,0,102,5,236,56,236,0,236,20,129,3,33,223,0,192,128,2,0,12,0,66,0,0,0,49,32,1,0,33,246,16,14,14,14,0,246,233,220,225,49,37,7,246,198,148,148,148,209,246,244,242,242,222,222,238,66,66,222,222,246,246,222,222,131,129,0,17,132,14,12,23,103,99,94,94,94,44,0,225,162,162,162,162,162,131,6,206,206,0,52,206,206,52,131,16,15,0,4,1,1,2,1,1,3,3,3,3,1,4,2,2,2,128,4,236,246,0,18,20,129,0,56,129,4,20,190,20,0,20,131,11,250,246,195,175,0,81,81,0,30,0,30,222,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,251,131,133,133,133,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,11,0,0,0,11,0,1,6,5,1,2,2,2,2,2,5,86,232,24,170,24,232,131,1,205,51,5,200,20,236,56,236,20,131,1,32,224,128,2,0,12,0,15,0,0,0,19,32,1,8,7,0,2,3,2,2,2,2,2,129,5,86,232,24,170,24,232,1,51,205,131,1,205,51,6,5,5,2,2,2,2,2,5,200,20,236,56,236,20,131,1,32,224,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,251,131,133,133,133,128,2,0,12,0,13,0,0,0,13,0,1,6,5,1,2,2,2,2,2,5,55,201,24,232,24,232,129,0,154,129,0,102,5,218,38,236,20,236,20,129,0,57,129,0,199,128,2,0,12,0,59,0,0,0,64,32,1,0,15,31,52,54,54,202,202,251,31,51,86,86,86,232,232,232,250,131,3,50,50,206,206,133,1,40,40,131,2,236,236,255,129,5,208,146,146,146,180,196,129,5,196,227,236,0,154,154,132,0,102,129,1,102,102,129,0,102,131,19,18,0,3,2,1,1,1,1,1,2,1,1,3,2,2,2,2,2,2,2,18,254,208,38,13,254,233,202,202,20,20,20,236,30,209,39,236,30,0,202,128,9,85,80,85,85,85,79,85,0,85,43,64,0,149,6,85,0,85,0,192,0,192,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,251,131,133,133,133,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,64,0,0,0,49,32,1,0,32,252,2,6,6,6,12,15,15,131,0,229,202,202,202,228,252,247,245,0,255,252,55,55,201,201,24,24,232,232,24,24,232,232,131,129,5,253,250,239,248,10,20,130,8,227,216,194,171,171,171,165,0,254,133,3,154,154,0,102,129,0,102,131,16,15,0,1,2,2,1,2,1,3,3,3,4,2,2,2,2,2,15,20,16,10,16,20,40,20,70,40,40,218,38,236,20,236,20,130,1,247,246,129,1,50,60,130,0,57,129,0,199,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,41,0,0,0,33,32,1,0,128,14,2,24,24,172,172,207,0,49,86,86,86,232,232,232,3,129,1,40,40,131,129,0,242,129,4,203,166,166,166,204,131,2,243,0,102,129,0,102,131,10,9,1,2,2,1,1,3,2,1,3,2,7,246,236,70,34,0,200,20,20,129,128,8,10,45,85,85,10,0,10,192,0,0,128,2,0,12,0,5,0,0,0,5,0,1,0,128,0,5,131,133,128,0,60,131,133,0,128,2,0,12,0,43,0,0,0,33,0,1,0,16,216,216,235,24,64,90,90,232,232,231,227,221,24,24,170,170,110,64,0,144,1,42,232,131,5,40,188,188,171,167,203,129,3,224,227,6,40,132,1,214,172,132,129,17,242,222,209,202,202,20,20,18,12,5,236,236,56,56,176,9,89,20,131,128,4,80,80,66,44,16,138,1,180,180,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,9,0,0,0,9,0,1,4,3,1,2,2,2,3,24,170,24,232,129,1,154,0,3,236,56,236,20,129,1,64,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,19,0,0,0,19,32,1,0,11,35,60,201,211,24,24,170,170,24,24,232,232,131,136,1,154,154,132,6,5,1,2,2,2,2,2,5,186,20,236,56,236,20,131,1,64,0,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,5,0,1,0,128,0,216,131,133,128,0,40,131,133,0,128,2,0,12,0,23,0,0,0,20,0,1,0,131,5,180,180,232,232,180,180,65,255,70,255,70,131,128,5,171,0,85,0,154,154,136,131,1,216,216,129,3,216,216,36,36,131,6,226,60,30,196,0,65,65,136,128,2,0,12,0,52,0,0,0,40,0,1,0,23,21,4,250,124,78,78,94,220,24,24,178,178,36,162,196,196,132,6,1,250,78,78,232,232,131,2,80,194,194,129,65,0,164,0,164,0,80,131,0,80,65,0,164,0,164,129,2,194,194,80,135,130,13,186,192,212,206,0,236,236,44,44,0,50,44,64,70,129,4,10,212,212,20,20,131,2,156,226,226,131,0,156,131,0,156,131,2,226,226,156,135,0,128,2,0,12,0,31,0,0,0,32,0,1,0,15,81,166,203,203,176,91,83,83,24,24,178,178,78,78,232,232,131,128,65,0,252,0,252,129,65,255,4,255,4,140,64,255,102,2,74,54,54,64,0,154,10,182,202,202,236,236,54,54,202,202,20,20,131,128,1,36,36,129,1,220,220,140,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,58,0,0,0,57,0,1,0,28,55,55,25,63,79,79,79,232,232,232,253,17,15,81,166,203,203,176,91,83,83,24,24,178,178,78,78,232,232,131,128,4,180,179,189,233,40,129,5,40,16,11,15,5,0,65,0,252,0,252,129,65,255,4,255,4,140,12,136,146,217,214,203,203,203,20,20,20,18,255,227,64,255,102,2,74,54,54,64,0,154,10,182,202,202,236,236,54,54,202,202,20,20,131,128,3,86,68,59,24,131,6,231,222,236,245,0,36,36,129,1,220,220,140,128,2,0,12,0,57,0,0,0,57,0,1,0,129,26,226,8,24,24,24,177,177,177,198,218,216,81,166,203,203,176,91,83,83,24,24,178,178,78,78,232,232,131,128,4,180,179,192,233,40,129,5,40,18,14,17,5,0,65,0,252,0,252,129,65,255,4,255,4,140,12,249,3,250,247,236,236,236,53,53,53,51,32,4,64,255,102,2,74,54,54,64,0,154,10,182,202,202,236,236,54,54,202,202,20,20,131,128,3,86,68,59,24,131,6,233,225,238,245,0,36,36,129,1,220,220,140,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,13,0,0,0,13,0,1,6,5,3,4,2,1,3,1,5,24,232,94,94,162,162,129,3,152,0,94,0,5,236,20,196,196,60,60,129,3,81,0,175,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,251,131,133,133,133,128,2,0,12,0,6,0,0,0,5,0,1,0,128,1,251,171,131,134,129,0,40,131,134,128,2,0,12,0,5,0,0,0,5,0,1,0,129,0,251,131,134,134,128,0,236,132,0,128,2,0,12,0,6,0,0,0,5,0,1,0,128,1,251,211,131,134,129,0,40,131,134,128,2,0,12,0,6,0,0,0,5,0,1,0,128,1,251,211,131,134,129,0,40,131,134,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,251,132,134,134,134,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,5,0,1,0,133,133,133,128,0,236,131,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,70,0,0,0,52,32,1,0,36,230,236,240,240,240,1,1,139,240,201,177,180,180,180,221,230,223,223,234,235,230,0,24,24,24,0,232,232,232,0,94,94,94,0,162,162,162,131,129,17,7,14,254,14,4,248,253,245,232,222,216,178,171,171,171,165,0,254,136,7,152,152,0,94,94,94,0,152,131,16,15,0,1,2,2,3,4,3,2,1,1,5,4,2,1,3,1,128,1,247,236,129,10,70,30,20,20,14,236,20,196,196,60,60,9,246,246,0,246,0,20,50,50,0,250,129,3,81,0,175,0,0,128,2,0,12,0,39,32,0,0,42,0,1,0,13,12,0,2,1,1,2,2,3,1,2,2,1,2,4,128,11,20,24,206,230,0,87,87,10,6,24,0,232,130,6,184,168,164,0,43,92,92,130,128,12,250,240,236,246,247,247,3,20,236,193,193,193,224,130,7,236,245,0,10,20,20,20,9,131,131,12,81,81,81,81,81,81,38,0,217,175,175,175,175,139,128,2,0,12,0,22,0,0,0,17,0,1,10,9,0,1,1,1,4,4,2,1,3,1,9,246,55,10,201,24,232,94,94,162,162,128,2,226,0,30,129,3,152,0,94,0,9,60,0,196,0,236,20,196,196,60,60,133,3,81,0,175,0,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,0,2,0,12,0,53,32,0,0,64,32,1,18,17,0,4,2,3,2,1,4,2,1,1,1,1,2,3,4,2,2,2,128,0,26,129,0,206,129,10,230,0,24,40,40,0,164,0,230,0,230,133,11,164,0,162,162,162,94,94,0,210,46,0,92,22,21,6,2,1,2,1,1,1,2,2,1,2,1,1,1,1,1,1,1,3,2,2,2,21,236,61,90,48,90,68,15,216,20,236,208,208,222,236,19,60,60,60,216,20,216,20,134,14,74,0,74,74,192,182,182,182,228,7,43,37,219,0,182,0,128,2,0,12,0,43,0,0,0,32,32,1,0,21,170,170,20,56,94,94,94,56,20,170,170,20,255,232,232,232,255,20,24,24,170,170,131,9,50,204,204,204,243,25,62,102,102,102,130,4,14,25,37,50,50,135,10,9,1,1,4,2,2,1,3,3,2,2,9,56,0,186,0,56,0,20,0,236,56,3,24,24,215,192,130,0,216,129,128,2,0,12,0,44,0,0,0,44,0,1,0,21,170,170,20,56,94,94,94,56,20,170,170,20,0,232,232,232,0,20,24,24,170,170,131,17,25,179,179,179,218,0,36,77,77,77,231,231,231,244,0,12,25,25,135,21,56,56,0,223,186,186,186,223,0,56,56,0,11,20,20,20,11,0,236,236,56,56,131,17,241,49,49,49,26,5,239,217,217,217,25,25,25,24,25,6,241,241,135,0,128,2,0,12,0,52,0,0,0,32,32,1,0,10,50,61,54,54,54,202,202,202,6,50,248,129,14,24,24,24,0,232,232,232,0,94,94,94,0,162,162,162,131,129,8,10,0,236,236,0,219,164,164,164,136,7,152,152,0,94,94,94,0,152,131,10,9,1,3,2,3,6,4,2,1,3,1,9,246,215,41,20,236,20,196,196,60,60,130,0,85,129,3,81,0,175,0,0,128,2,0,12,0,47,0,0,0,45,0,1,0,25,170,170,40,67,94,94,94,67,40,170,170,40,9,232,232,232,9,40,24,24,170,170,106,80,216,232,131,9,51,205,205,205,242,20,58,102,102,102,130,4,10,20,35,51,51,139,25,56,56,0,223,186,186,186,223,0,56,56,0,9,20,20,20,9,0,236,236,56,56,186,246,60,20,131,9,232,40,40,40,19,0,225,192,192,192,132,2,244,232,232,139,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,81,0,0,0,78,0,1,0,128,4,10,23,24,12,5,129,31,48,98,98,98,86,66,165,217,24,24,24,7,10,254,250,235,54,49,19,10,206,158,158,158,155,154,66,27,232,232,232,243,131,129,16,251,246,141,151,162,162,162,192,221,237,17,30,121,102,60,20,19,130,16,1,12,89,88,94,94,94,59,20,14,248,247,161,177,186,221,238,132,129,37,236,236,248,247,6,0,216,190,190,190,197,206,0,249,236,236,236,6,30,15,33,20,226,249,8,30,48,66,66,66,60,50,31,22,20,20,20,252,131,129,14,2,0,81,82,81,81,81,55,20,251,233,231,215,224,8,132,16,247,0,175,168,175,175,175,204,236,6,9,10,8,3,234,10,14,132,128,2,0,12,0,2,0,0,0,5,0,1,0,133,133,128,0,236,131,133,128,2,0,12,0,2,0,0,0,5,0,1,0,133,133,128,0,236,131,133,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,5,0,1,0,128,0,251,131,133,128,0,236,131,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,68,0,0,0,54,32,1,0,15,26,26,26,13,0,6,239,230,70,55,28,0,211,172,172,172,134,15,46,96,96,96,61,30,112,110,230,226,0,243,230,230,230,244,131,133,7,3,0,80,94,100,100,100,53,132,18,154,154,154,154,154,199,239,9,50,60,40,30,0,226,236,209,203,225,239,132,19,18,2,1,3,1,1,3,3,2,2,4,2,3,1,2,1,1,1,1,3,3,236,245,15,20,129,0,56,130,8,200,230,0,186,20,80,0,9,20,131,1,181,181,130,6,73,35,188,176,181,0,206,130,0,0,2,0,12,0,42,32,0,0,45,32,1,13,12,2,3,3,3,1,2,1,1,1,2,3,2,2,12,26,26,164,92,92,0,10,16,26,0,230,26,0,7,206,206,206,162,0,94,94,89,130,1,206,50,14,13,3,1,1,1,2,3,1,2,2,1,2,2,3,2,13,236,236,236,60,60,196,196,0,236,236,0,20,236,0,8,8,25,32,32,0,81,0,175,175,130,1,32,224,0,128,2,0,12,0,8,0,0,0,8,0,1,4,3,1,2,2,2,3,55,201,24,232,130,0,102,3,218,38,236,20,130,0,192,128,2,0,12,0,12,0,0,0,14,32,1,6,5,0,2,3,2,2,2,129,3,55,201,24,232,1,51,205,130,0,102,4,3,5,2,2,2,3,218,38,236,20,130,0,192,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,10,0,0,0,10,0,1,4,3,2,4,3,5,3,24,170,86,232,128,2,206,156,0,3,236,56,200,20,128,2,37,75,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,251,131,133,133,133,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,28,0,0,0,39,32,1,13,12,0,1,1,1,1,2,1,1,1,3,4,3,5,12,57,88,87,87,80,236,236,24,57,24,170,86,232,0,80,129,9,1,247,0,24,76,80,0,206,156,0,12,11,0,1,1,1,1,2,1,1,4,4,3,5,128,3,216,203,190,176,130,3,236,56,200,20,11,196,0,246,231,251,0,230,197,0,37,75,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,69,0,0,0,61,32,1,0,6,220,226,230,230,230,247,247,64,255,119,28,220,184,164,170,170,170,211,220,213,213,224,225,220,0,24,24,24,170,170,170,211,0,86,86,86,232,232,232,244,131,129,17,7,14,254,14,4,248,248,240,228,220,216,178,171,171,171,165,0,254,134,3,206,156,156,156,137,19,18,0,1,2,2,1,1,1,1,1,1,1,3,2,1,1,4,4,3,5,18,246,237,226,246,246,236,236,255,35,60,60,20,10,10,4,236,56,200,20,3,246,246,0,246,129,12,247,249,255,11,20,50,50,0,250,0,37,75,0,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,15,0,0,0,15,0,1,0,7,92,25,158,5,253,100,233,166,131,130,1,163,163,134,2,196,236,50,129,2,206,20,60,131,130,1,80,80,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,43,0,0,0,39,0,1,0,6,84,24,156,236,236,25,231,129,1,186,70,129,6,25,231,20,20,100,232,172,131,130,1,176,176,129,65,0,128,0,128,129,65,0,128,0,128,129,1,176,176,134,6,226,236,40,0,10,236,20,129,1,30,226,129,6,236,20,246,0,216,20,30,131,130,1,90,90,129,1,166,166,129,1,166,166,129,1,90,90,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,251,131,133,133,133,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,27,0,0,0,27,0,1,0,11,106,36,24,150,219,232,24,36,106,232,220,150,131,128,0,31,129,0,225,129,0,224,129,0,31,132,11,176,236,216,80,20,40,216,236,176,40,20,80,131,128,0,236,129,0,20,129,0,20,129,0,236,132,0,128,2,0,12,0,23,0,0,0,24,0,1,0,11,60,24,159,5,251,97,232,196,55,55,201,201,131,130,1,151,151,131,1,146,146,132,2,218,236,70,129,6,186,20,38,218,218,38,38,131,0,196,129,1,60,60,129,0,196,135,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,251,131,133,133,133,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,18,0,0,0,18,0,1,8,7,0,1,1,1,2,2,2,2,7,200,24,56,232,24,232,24,232,4,224,154,22,102,154,129,0,102,7,10,236,246,20,236,20,236,20,128,3,64,0,192,64,129,0,192,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,20,131,133,133,133,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,20,131,133,133,133,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,20,131,133,133,133,128,2,0,12,0,6,0,0,0,2,0,1,0,128,1,236,10,131,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,5,0,1,0,133,133,128,0,236,131,133,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,20,131,133,133,133,128,2,0,12,0,21,32,0,0,16,0,1,0,6,5,1,2,2,2,2,2,5,55,201,24,232,24,232,129,0,156,129,0,100,3,215,215,41,41,139,132,3,74,74,0,182,129,0,182,131,128,2,0,12,0,92,0,0,0,84,0,1,0,45,62,59,81,81,81,42,236,24,24,0,251,229,229,229,232,232,4,13,24,24,24,2,2,20,66,60,95,98,25,1,176,176,176,203,226,244,40,81,81,81,94,100,77,69,41,12,131,128,6,104,247,200,29,101,100,96,130,3,252,219,140,149,130,20,240,224,223,208,208,208,212,215,22,32,35,35,35,211,194,178,178,178,189,218,247,130,2,244,5,9,132,45,228,218,246,246,246,252,0,236,236,0,30,60,60,60,20,20,246,242,236,236,236,230,226,217,189,198,198,201,233,246,70,70,70,47,30,17,255,246,246,246,218,216,218,214,222,238,131,129,5,60,236,210,186,186,186,132,1,60,60,130,20,7,15,27,40,40,40,45,50,226,226,226,226,226,15,40,70,70,70,67,63,60,138,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,5,0,0,0,2,0,1,0,129,0,253,131,134,134,134,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,5,0,0,0,2,0,1,0,129,0,253,131,134,134,134,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,133,0,0,0,112,0,1,0,63,252,2,6,6,6,12,15,15,131,236,219,202,202,202,228,252,247,245,0,255,252,62,59,81,81,81,42,236,24,24,0,251,229,229,229,232,232,4,13,24,24,24,2,2,20,66,60,95,98,25,1,176,176,176,203,226,244,40,81,81,81,94,100,77,2,69,41,12,131,129,5,253,250,244,1,20,20,130,8,227,216,194,171,171,171,165,0,254,129,6,104,247,200,29,101,100,96,130,3,252,219,140,149,130,20,240,224,223,208,208,208,212,215,22,32,35,35,35,211,194,178,178,178,189,218,247,130,2,244,5,9,132,137,56,28,60,60,60,39,20,24,30,20,15,4,228,218,246,246,246,252,0,236,236,0,30,60,60,60,20,20,246,242,236,236,236,230,226,217,189,198,198,201,233,246,70,70,70,47,30,17,255,246,246,246,218,216,218,214,222,238,131,129,4,246,236,239,245,246,131,6,26,50,64,80,80,80,80,132,5,60,236,210,186,186,186,132,1,60,60,130,20,7,15,27,40,40,40,45,50,226,226,226,226,226,15,40,70,70,70,67,63,60,138,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,134,129,0,25,131,134,134,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,253,131,133,133,133,128,2,0,12,0,141,0,0,0,101,32,1,0,63,29,27,24,24,24,0,251,7,29,28,63,46,0,250,213,186,186,186,210,231,252,29,29,29,248,83,15,16,5,29,29,29,29,15,0,24,24,0,230,201,201,201,247,6,24,24,24,14,6,254,232,232,232,232,232,195,195,62,62,43,31,253,200,200,7,200,225,247,243,233,222,233,245,131,129,25,244,234,237,223,223,223,223,220,32,34,35,35,35,4,221,199,178,178,178,221,247,196,50,50,48,26,131,3,43,87,90,90,130,0,255,131,2,7,12,7,130,20,5,240,252,22,32,32,226,226,24,94,94,94,27,0,217,172,172,172,184,7,4,132,35,34,0,1,3,2,3,1,3,3,3,3,1,1,3,2,1,1,3,1,1,1,1,1,3,1,4,4,4,2,1,2,3,3,2,1,1,128,1,247,236,129,5,40,40,60,10,206,226,129,21,226,206,206,0,236,236,0,237,216,0,9,20,20,30,198,198,246,30,0,20,20,16,132,3,216,216,20,70,129,6,50,26,0,236,216,168,168,129,0,3,132,6,240,26,225,172,0,94,94,129,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,45,0,0,0,38,32,1,0,28,206,225,7,24,4,248,220,206,17,90,90,90,44,0,158,158,158,148,205,0,244,232,232,232,218,24,24,158,158,131,131,10,148,166,168,168,168,214,0,42,88,88,88,145,14,13,0,3,1,3,3,3,2,2,1,1,1,3,3,2,128,0,236,129,9,186,0,50,60,75,50,35,20,236,50,129,3,90,90,0,166,135,0,2,0,12,0,37,32,0,0,46,32,1,12,11,0,4,2,3,1,1,1,1,3,3,3,1,128,10,24,0,232,56,47,18,0,156,0,8,252,131,7,70,98,98,98,0,158,166,5,16,15,0,1,3,1,1,3,1,3,1,1,1,3,3,1,1,1,15,50,16,236,247,0,30,246,0,29,60,60,50,15,20,28,42,132,7,226,186,176,176,217,0,80,80,130,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,58,32,0,0,50,0,1,0,19,18,0,4,2,1,1,1,2,2,3,2,2,1,2,1,1,1,1,2,1,18,45,24,49,58,97,106,94,11,166,11,94,94,110,105,65,93,94,232,232,131,9,225,210,211,88,0,168,59,84,46,34,129,2,70,0,251,30,216,226,236,236,236,225,216,207,192,198,206,206,206,12,40,70,70,70,10,206,206,206,206,203,195,211,226,206,206,20,20,131,138,8,186,166,166,166,212,0,110,110,110,64,0,170,0,100,140,0,128,2,0,12,0,63,32,0,0,80,0,1,0,21,20,2,2,1,1,1,1,3,2,2,1,1,2,4,3,5,2,2,2,1,1,1,20,101,10,0,248,237,232,0,102,48,0,210,162,11,24,110,80,232,248,10,0,236,10,9,21,0,251,252,0,164,0,92,92,92,133,3,40,206,0,90,40,196,198,200,221,246,0,7,16,20,20,20,10,198,198,198,233,10,37,66,66,66,37,10,251,236,236,236,246,0,226,185,178,198,196,20,20,15,10,251,251,10,131,129,19,229,196,186,0,3,13,29,40,40,86,86,10,220,170,170,170,199,226,26,86,129,2,241,226,240,134,6,40,21,0,226,30,20,216,131,128,2,0,12,0,63,0,0,0,54,0,1,0,34,47,60,196,209,45,35,24,24,24,37,49,58,97,106,94,94,94,11,219,166,166,166,11,94,94,94,94,110,105,65,93,94,94,232,232,131,139,16,225,210,210,211,88,88,88,42,0,168,168,168,59,84,46,46,34,129,0,70,129,0,251,131,34,236,236,20,20,216,226,236,236,236,225,216,207,192,198,206,206,206,12,40,70,70,70,10,206,206,206,206,203,195,211,226,206,206,20,20,131,142,8,186,166,166,166,212,0,110,110,110,64,0,170,0,100,140,128,2,0,12,0,64,32,0,0,58,0,1,0,21,20,0,2,2,4,2,1,1,1,2,2,3,2,2,1,2,1,1,1,1,2,1,129,18,45,24,49,58,97,106,94,11,166,11,94,94,110,105,65,93,94,232,232,1,42,214,131,9,225,210,211,88,0,168,59,84,46,34,129,2,70,0,251,129,32,20,20,216,226,236,236,236,225,216,207,192,198,206,206,206,12,40,70,70,70,10,206,206,206,206,203,195,211,226,206,206,20,20,131,0,196,129,0,196,138,8,186,166,166,166,212,0,110,110,110,64,0,170,0,100,140,0,128,2,0,12,0,61,0,0,0,43,32,1,0,29,1,13,24,24,24,12,1,244,232,232,232,232,175,175,72,72,37,1,220,180,180,180,222,1,247,251,243,232,13,18,131,129,2,11,12,8,130,4,6,24,41,72,72,129,13,43,94,94,94,44,0,217,162,162,162,162,162,0,5,132,14,13,0,4,1,1,3,1,2,2,3,3,3,2,1,1,13,246,236,242,246,20,20,236,188,246,64,246,13,20,20,131,9,241,242,240,16,182,0,84,84,84,0,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,5,0,0,0,2,0,1,0,129,0,253,131,134,134,134,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,103,0,0,0,87,0,1,0,1,246,252,130,46,255,253,253,247,232,200,187,196,196,196,237,246,239,239,250,251,246,1,13,24,24,24,12,1,244,232,232,232,232,175,175,72,72,37,1,220,180,180,180,222,1,247,251,243,232,13,18,131,129,18,7,14,3,255,6,4,251,0,243,230,223,216,178,171,171,171,165,0,254,130,2,11,12,8,130,4,6,24,41,72,72,129,13,43,94,94,94,44,0,217,162,162,162,162,162,0,5,132,132,0,255,131,41,255,29,60,60,60,54,20,22,30,20,17,4,246,241,236,236,236,242,246,4,20,20,20,20,236,236,188,188,219,246,25,64,64,64,25,246,254,13,20,20,11,252,131,131,14,253,252,251,0,248,253,2,7,26,50,48,80,80,80,80,138,18,248,241,242,240,240,16,16,229,182,182,182,221,0,41,84,84,84,84,84,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,253,131,133,133,133,128,2,0,12,0,61,0,0,0,55,32,1,0,29,255,11,24,24,24,24,81,81,184,184,219,255,36,76,76,76,34,255,9,6,13,24,242,238,255,242,232,232,232,244,131,129,4,250,232,216,184,184,129,13,212,162,162,162,212,0,38,94,94,94,100,104,20,2,130,2,246,244,247,132,18,17,0,1,1,1,1,2,2,1,2,3,1,2,2,1,1,3,1,3,17,10,251,236,236,236,20,68,68,10,192,192,10,244,236,236,10,14,20,129,12,7,15,15,16,240,26,74,0,214,172,178,182,20,130,0,128,2,0,12,0,66,0,0,0,63,0,1,0,128,10,15,24,200,214,238,0,47,98,98,98,47,129,8,12,195,213,232,232,232,238,249,195,129,5,85,110,24,24,232,232,64,255,120,131,130,14,172,165,158,158,158,204,242,12,40,40,40,233,233,237,246,131,5,40,40,216,84,84,84,129,1,114,216,131,128,11,244,236,236,241,250,0,227,194,194,194,211,226,130,6,10,20,20,20,16,7,226,129,6,176,0,236,236,20,20,90,131,130,14,80,80,80,80,80,42,10,238,206,206,206,41,41,40,20,131,5,206,206,31,166,166,166,129,1,166,30,131,128,2,0,12,0,29,32,0,0,20,0,1,10,9,2,1,2,1,1,1,1,2,3,2,9,8,2,1,2,1,2,1,2,3,2,8,59,0,232,232,251,0,197,24,232,130,5,98,98,98,0,214,42,9,221,0,20,15,11,3,0,35,236,20,130,6,176,176,176,176,0,35,221,0,128,2,0,12,0,78,0,0,0,77,0,1,0,45,40,33,24,24,24,32,40,47,89,106,94,94,94,29,236,203,166,166,166,207,236,28,94,94,94,94,106,90,60,24,30,0,48,94,94,94,232,232,232,243,0,94,94,84,232,232,131,129,0,4,132,0,250,129,11,236,24,88,88,88,42,0,220,168,168,168,219,131,0,3,129,3,150,152,155,205,143,28,216,226,236,236,236,225,216,207,192,198,206,206,206,222,238,24,70,70,70,24,236,220,206,206,206,206,203,195,211,130,13,229,206,206,206,20,20,20,11,0,206,206,206,20,20,131,138,10,146,156,166,166,166,212,0,54,110,110,110,65,0,140,0,170,0,100,132,3,50,50,49,24,132,0,1,137,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,31,0,0,0,31,32,1,0,19,94,94,94,44,0,162,162,160,150,170,195,197,214,232,232,232,24,24,162,162,131,128,5,4,44,88,88,88,4,144,11,10,1,1,2,2,2,1,1,1,4,2,2,10,206,206,251,50,58,65,38,20,20,236,50,3,196,181,166,196,134,0,128,2,0,12,0,36,0,0,0,37,32,1,0,131,19,94,94,94,44,0,162,162,160,150,170,195,197,214,232,232,232,24,24,162,162,131,10,42,214,214,42,0,4,44,88,88,88,4,144,13,12,1,2,2,1,2,2,2,1,1,1,4,2,2,12,236,0,206,206,251,50,58,65,38,20,20,236,50,5,20,216,196,181,166,196,134,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,221,131,133,133,133,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,216,131,133,133,133,128,2,0,12,0,46,32,0,0,56,0,1,0,14,13,1,2,2,2,2,2,2,2,2,3,2,1,1,3,13,59,197,24,60,196,232,24,197,15,43,251,230,203,230,4,12,0,172,0,172,129,6,86,95,25,254,254,25,95,27,221,221,35,35,236,236,221,221,35,35,20,20,236,236,35,35,0,237,226,226,226,237,0,18,30,30,30,18,131,132,1,90,90,129,3,90,90,0,166,129,12,166,226,226,237,0,18,30,30,30,18,0,237,226,131,0,128,2,0,12,0,17,0,0,0,17,0,1,8,7,1,2,2,2,2,2,2,2,7,59,197,24,60,196,232,24,197,129,2,172,0,172,129,0,84,7,221,35,236,221,35,20,236,35,129,2,90,0,90,129,0,164,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,82,32,0,0,81,0,1,0,28,27,0,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,3,2,1,1,3,2,3,2,1,1,3,27,18,24,0,51,101,98,94,232,236,240,246,0,59,197,94,232,22,50,2,237,210,237,57,85,37,16,245,16,128,3,154,152,158,202,132,0,2,132,11,95,25,254,254,25,95,95,25,254,254,25,95,42,236,236,0,224,196,196,196,20,20,20,11,0,236,236,60,60,196,196,20,20,32,13,2,2,2,13,32,50,62,62,62,50,238,219,208,208,208,219,238,0,12,12,12,132,128,3,80,80,77,39,132,0,1,136,23,226,226,237,0,18,30,30,30,18,0,237,226,226,226,237,0,18,30,30,30,18,0,237,226,131,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,100,0,0,0,93,0,1,0,48,8,14,18,18,18,24,27,27,143,248,231,214,214,214,240,8,3,1,12,11,8,59,59,197,197,24,24,60,60,196,196,232,232,24,24,197,197,251,15,43,43,43,15,251,230,203,203,203,230,131,129,5,253,250,239,0,10,20,130,8,227,216,194,171,171,171,165,0,254,129,1,12,12,129,1,172,172,129,3,172,172,0,86,129,12,86,95,95,66,46,25,254,254,254,25,46,66,95,131,48,10,10,10,10,10,10,10,10,30,10,38,70,70,70,49,30,34,40,30,25,14,221,221,35,35,236,236,221,221,35,35,20,20,236,236,35,35,0,237,226,226,226,237,0,18,30,30,30,18,131,129,4,246,236,233,232,231,131,6,26,50,64,80,80,80,80,135,1,90,90,129,3,90,90,0,166,129,12,166,226,226,237,0,18,30,30,30,18,0,237,226,131,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,253,131,133,133,133,128,2,0,12,0,58,32,0,0,62,0,1,0,19,18,0,1,1,1,1,5,1,1,1,2,2,2,2,2,3,2,1,1,3,18,18,24,0,51,94,232,238,249,0,18,94,94,232,58,86,38,17,246,17,128,3,154,152,157,202,132,0,84,129,5,95,25,254,254,25,95,130,8,229,206,206,206,20,20,20,16,7,130,17,206,206,206,206,20,20,246,227,216,216,216,227,246,8,20,20,20,8,131,128,3,86,81,75,39,132,3,255,255,0,166,129,0,166,131,11,226,226,237,0,18,30,30,30,18,0,237,226,131,0,128,2,0,12,0,36,0,0,0,35,32,1,0,20,18,24,0,51,101,98,94,232,236,239,242,249,0,18,18,94,94,94,94,232,232,131,128,3,154,152,157,202,135,0,84,129,0,84,135,11,10,1,1,1,1,5,2,1,2,2,2,2,129,3,229,206,20,7,129,2,206,206,20,5,86,81,75,39,0,255,129,0,166,129,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,35,131,133,133,133,128,2,0,12,0,37,0,0,0,32,0,1,0,18,158,158,176,232,46,87,96,232,223,195,146,24,24,158,158,123,122,0,232,131,5,30,186,186,186,200,230,129,2,1,30,30,132,0,30,133,130,15,241,220,209,206,20,19,9,0,236,236,50,50,206,0,50,20,131,5,226,50,50,50,41,18,129,2,241,226,226,139,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,37,0,0,0,32,0,1,0,18,158,158,176,232,46,87,96,232,223,195,146,24,24,158,158,123,122,0,232,131,5,30,186,186,186,200,230,129,2,1,30,30,132,0,30,133,130,15,241,220,209,206,20,19,9,0,236,236,50,50,206,0,50,20,131,5,226,50,50,50,41,18,129,2,241,226,226,139,128,2,0,12,0,43,0,0,0,37,32,1,0,19,70,74,59,59,59,197,197,197,226,255,0,254,245,232,0,44,24,24,59,59,131,129,1,241,206,129,10,196,187,170,158,158,158,149,246,251,0,84,129,0,84,131,11,10,0,2,1,2,1,2,2,2,1,4,2,128,9,221,221,35,35,30,0,12,20,236,221,128,6,23,50,0,50,97,110,110,129,0,166,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,47,0,0,0,41,32,1,0,23,40,90,236,226,70,74,59,59,59,197,197,197,226,255,0,254,245,232,0,44,24,24,59,59,131,133,1,241,206,129,10,196,187,170,158,158,158,149,246,251,0,84,129,0,84,131,13,12,1,2,1,2,1,2,1,2,2,2,1,4,2,12,236,70,0,221,221,35,35,30,0,12,20,236,221,130,6,23,50,0,50,97,110,110,129,0,166,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,5,0,1,0,133,133,128,0,60,131,133,128,2,0,12,0,49,0,0,0,45,32,1,0,131,19,70,74,59,59,59,197,197,197,226,255,0,254,245,232,0,44,24,24,59,59,131,128,2,177,0,79,129,1,241,206,129,10,196,187,170,158,158,158,149,246,251,0,84,129,0,84,131,15,14,0,1,1,1,1,2,1,2,1,2,2,2,1,4,2,132,9,221,221,35,35,30,0,12,20,236,221,11,236,80,20,176,0,23,50,0,50,97,110,110,129,0,166,0,128,2,0,12,0,54,0,0,0,53,32,1,0,34,94,94,94,30,213,213,213,201,212,224,226,224,232,232,232,24,24,172,162,162,43,43,43,236,162,162,162,157,169,185,186,206,213,213,213,131,129,2,68,68,68,130,0,15,130,0,249,136,2,68,68,68,141,18,17,1,2,2,2,1,1,1,4,2,1,4,2,2,2,1,1,1,4,17,211,233,15,25,30,34,25,20,236,45,246,14,45,55,60,53,30,15,4,146,146,176,0,11,132,4,146,146,176,0,252,130,128,2,0,12,0,32,0,0,0,30,32,1,0,20,94,94,94,44,0,162,162,160,150,170,195,197,214,232,232,232,24,24,174,162,162,131,128,5,4,49,98,98,98,4,145,11,10,1,3,2,2,1,1,1,4,2,1,2,10,206,251,50,58,65,38,20,20,236,40,50,2,176,176,176,135,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,36,0,0,0,30,32,1,0,24,20,80,206,216,94,94,94,44,0,162,162,160,150,170,195,197,214,232,232,232,24,24,174,162,162,131,132,5,4,49,98,98,98,4,145,11,10,5,3,2,2,1,1,1,4,2,1,2,10,206,251,50,58,65,38,20,20,236,40,50,2,176,176,176,135,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,60,0,0,0,57,0,1,0,33,94,94,94,44,0,162,162,160,150,170,195,197,214,232,232,232,69,75,0,51,94,94,94,232,232,232,238,249,0,24,24,174,162,162,131,6,147,4,44,88,88,88,4,135,12,147,10,164,152,157,202,0,196,196,246,250,250,251,137,33,206,206,206,230,251,50,50,50,58,65,38,20,20,20,20,20,0,246,0,230,206,206,206,20,20,20,16,6,0,236,236,40,50,50,131,6,1,176,171,166,166,166,176,135,5,1,0,70,70,68,33,132,1,5,6,137,128,2,0,12,0,64,0,0,0,57,32,1,0,33,94,94,94,44,0,162,162,160,150,170,195,197,214,232,232,232,255,5,186,237,24,24,24,162,162,162,168,180,186,24,24,174,162,162,131,128,5,4,44,88,88,88,4,136,13,10,164,152,155,202,0,196,196,246,250,246,246,0,70,130,0,70,131,19,18,1,3,2,2,1,1,1,4,2,1,1,1,5,1,1,1,1,2,1,7,206,251,50,58,65,38,20,20,129,8,245,236,50,39,17,0,236,40,50,2,176,166,176,132,8,70,70,69,33,0,1,2,0,70,129,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,253,131,133,133,133,0,2,0,12,0,41,32,0,0,25,32,1,14,13,1,3,1,2,3,1,2,2,1,1,2,1,1,2,13,12,24,12,244,232,244,47,100,100,47,209,156,156,209,133,7,158,0,46,98,98,46,0,158,8,7,1,3,3,3,3,3,3,3,7,246,236,9,20,227,196,29,60,131,3,80,217,176,38,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,5,0,0,0,2,0,1,0,129,0,253,131,134,134,134,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,233,131,133,133,133,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,253,131,133,133,133,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,83,0,0,0,80,0,1,0,1,246,252,130,40,4,7,7,9,251,210,189,196,196,196,237,246,239,239,250,251,246,0,12,24,24,24,12,0,244,232,232,232,244,0,47,100,100,100,47,0,209,156,156,156,209,131,129,18,1,4,254,2,11,4,4,2,246,233,223,216,178,171,171,171,165,0,254,140,11,158,158,209,0,46,98,98,98,46,0,209,158,131,45,251,251,251,251,251,250,251,251,15,5,249,20,55,55,55,49,15,17,25,15,12,255,0,246,236,236,236,246,0,9,20,20,20,9,0,227,196,196,196,227,0,29,60,60,60,29,131,131,14,253,252,251,0,252,255,253,254,21,50,48,80,80,80,80,142,11,80,80,38,0,217,176,176,176,217,0,38,80,131,0,2,0,12,0,44,32,0,0,40,32,1,15,14,0,2,1,1,3,1,1,1,3,1,2,1,3,4,1,128,13,21,24,221,0,42,90,90,20,20,24,24,0,232,245,130,7,165,158,158,208,0,98,98,98,131,13,12,0,3,1,1,1,1,3,2,1,3,1,3,4,12,226,236,10,4,231,226,186,223,0,249,236,0,20,129,7,60,68,80,80,0,176,176,183,130,128,2,0,12,0,50,0,0,0,38,32,1,0,128,26,30,0,226,0,12,24,24,24,12,0,244,232,232,232,244,0,47,100,100,100,47,0,209,156,156,156,209,131,128,2,231,0,25,139,11,158,158,209,0,46,98,98,98,46,0,209,158,131,12,11,0,1,1,1,2,3,3,3,3,3,3,3,128,10,226,0,30,246,236,9,20,227,196,29,60,128,2,20,0,236,131,3,80,217,176,38,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,253,131,133,133,133,128,2,0,12,0,91,0,0,0,67,32,1,0,47,246,24,24,24,246,216,216,216,246,48,48,48,19,246,220,194,194,194,248,7,25,25,25,15,7,255,233,233,233,233,233,196,196,63,63,44,32,254,201,201,201,226,248,244,234,223,234,246,131,135,9,158,158,0,49,98,98,98,49,0,158,129,2,255,12,7,130,20,5,240,252,22,32,32,226,226,24,94,94,94,27,0,217,172,172,172,184,7,4,132,23,22,0,3,1,3,1,3,2,1,1,3,1,4,4,4,2,2,1,3,3,1,1,1,1,22,246,236,246,0,15,226,15,42,70,0,9,20,20,0,186,215,246,30,0,8,20,20,16,131,4,70,221,176,176,221,131,7,240,27,172,172,0,94,94,94,129,0,128,2,0,12,0,60,0,0,0,57,0,1,0,33,216,197,165,150,162,162,162,162,228,20,48,90,90,90,53,20,227,162,162,162,150,166,208,216,223,232,232,232,224,24,24,162,162,162,131,129,0,3,131,11,219,168,168,168,220,0,42,88,88,88,14,216,129,0,250,132,0,4,137,33,40,48,65,58,50,50,50,50,36,20,231,186,186,186,232,18,35,50,50,50,58,64,48,40,30,20,20,20,30,236,236,50,50,50,131,132,0,100,65,0,170,0,130,10,90,90,90,44,0,212,166,166,166,156,146,146,128,2,0,12,0,58,0,0,0,55,32,1,0,32,216,197,165,150,162,162,162,162,213,246,33,90,90,90,37,246,212,162,162,162,150,166,208,216,223,232,232,232,224,24,24,162,162,131,129,0,3,131,10,219,168,168,168,220,0,42,88,88,88,34,130,0,250,132,0,4,136,19,18,0,1,1,1,2,1,2,1,3,1,3,2,2,1,1,1,4,3,2,18,40,48,65,58,50,50,21,246,186,186,20,50,58,64,48,40,20,236,50,131,0,100,64,0,170,5,90,90,0,212,166,186,134,128,2,0,12,0,60,0,0,0,57,32,1,0,33,40,33,24,24,24,32,40,47,89,106,94,94,94,29,236,203,166,166,166,207,236,28,94,94,94,94,106,90,60,94,94,94,232,232,131,129,0,4,132,0,250,129,11,216,14,88,88,88,42,0,220,168,168,168,219,131,0,3,137,20,19,0,4,1,1,1,1,1,2,3,2,2,2,1,2,1,2,1,1,3,2,19,216,236,225,216,207,192,198,206,238,70,70,236,220,206,206,198,190,209,206,20,134,5,146,166,212,44,90,90,64,0,170,0,100,132,0,2,0,12,0,41,32,0,0,42,32,1,15,14,0,2,1,1,3,2,2,4,2,2,1,2,2,1,1,14,197,185,213,216,232,90,0,24,0,59,217,197,24,197,177,132,2,46,88,172,133,0,84,13,12,0,2,2,1,1,2,3,4,2,2,1,3,2,12,35,45,20,5,20,206,206,236,20,221,35,236,35,128,0,40,129,3,215,216,166,70,130,1,186,0,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,77,0,0,0,84,0,1,0,128,38,5,16,24,12,9,2,0,52,100,100,100,54,255,8,11,24,24,24,12,0,245,227,232,243,242,247,0,203,156,156,156,201,4,251,245,232,232,232,245,131,131,14,159,158,158,158,158,187,220,243,35,50,47,47,63,41,20,132,14,98,98,98,98,98,65,30,16,221,206,209,209,200,216,236,132,128,12,255,235,236,245,15,28,0,220,186,186,186,212,236,64,255,126,24,186,236,236,236,5,0,245,6,20,12,255,242,0,32,60,60,60,15,227,80,44,20,20,20,254,131,129,16,1,0,80,80,80,80,80,49,15,243,221,216,6,249,6,246,242,130,16,255,0,176,175,176,176,176,207,241,10,26,37,252,1,248,10,12,132,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,100,0,0,0,115,0,1,0,135,50,47,100,100,100,95,100,100,100,100,100,100,97,100,103,100,100,100,48,0,211,162,162,162,24,24,24,11,0,244,232,232,232,232,232,232,230,232,232,232,230,232,232,232,232,232,232,245,24,24,196,196,131,131,17,158,158,158,158,158,209,0,1,254,5,11,11,9,10,7,3,0,4,129,4,45,97,98,98,47,138,3,2,2,0,2,130,3,253,0,254,254,131,3,43,213,213,43,131,128,1,4,3,129,51,5,6,0,229,196,196,196,203,196,187,199,216,216,216,194,203,207,196,196,196,206,216,252,35,35,35,221,221,221,218,216,244,20,20,20,27,29,20,17,20,20,20,20,20,39,35,20,20,20,19,236,236,133,129,27,255,0,80,79,80,80,80,62,50,6,240,0,13,36,31,0,243,237,246,255,229,196,187,176,176,176,192,206,129,1,20,10,130,6,246,236,15,31,13,0,2,132,9,239,223,233,0,248,0,212,44,44,212,131,0,2,0,12,0,29,32,0,0,29,32,1,9,8,2,1,2,1,2,1,2,3,2,8,40,10,232,232,3,10,176,24,212,130,5,98,98,98,0,214,44,9,8,1,2,2,1,2,1,2,3,2,8,221,0,20,20,5,0,35,236,0,130,5,176,176,176,246,45,211,128,2,0,12,0,45,0,0,0,43,32,1,0,128,22,54,83,83,83,221,221,221,247,0,12,8,245,232,238,249,83,83,221,221,24,24,232,232,131,129,1,15,10,130,5,213,158,158,158,158,159,134,0,84,129,0,84,131,13,12,0,2,1,2,1,3,1,2,1,4,2,2,2,12,40,221,221,35,35,40,35,20,20,221,35,236,20,128,6,23,50,0,70,80,80,80,129,2,20,0,166,0,128,2,0,12,0,54,0,0,0,48,32,1,0,27,24,24,232,232,0,54,83,83,83,221,221,221,247,0,12,8,245,232,238,249,83,83,221,221,24,24,232,232,131,3,42,214,214,42,129,1,15,10,130,5,213,158,158,158,158,159,134,0,84,129,0,84,131,15,14,0,2,2,2,1,2,1,3,1,2,1,4,2,2,2,129,12,40,221,221,35,35,40,35,20,20,221,35,236,20,0,166,129,6,23,50,0,70,80,80,80,129,2,20,0,166,0,128,2,0,12,0,49,0,0,0,43,32,1,0,27,40,60,196,216,0,54,83,83,83,221,221,221,247,0,12,8,245,232,238,249,83,83,221,221,24,24,232,232,131,133,1,15,10,130,5,213,158,158,158,158,159,134,0,84,129,0,84,131,13,12,4,2,1,2,1,3,1,2,1,4,2,2,2,12,40,221,221,35,35,40,35,20,20,221,35,236,20,128,6,23,50,0,70,80,80,80,129,2,20,0,166,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,92,0,0,0,75,32,1,0,128,11,30,59,59,59,197,197,197,225,0,2,8,12,130,5,59,59,197,197,24,24,129,26,59,59,59,36,0,250,238,232,243,240,236,217,197,197,197,0,3,220,15,59,59,59,197,197,197,207,217,131,134,5,204,158,158,158,158,158,134,0,84,129,3,84,0,90,37,130,7,2,5,101,98,98,98,83,70,129,3,156,154,164,209,130,3,226,240,0,254,131,25,24,0,4,2,3,3,1,4,2,1,2,3,3,3,1,2,3,3,1,1,1,1,3,1,1,1,7,10,246,60,10,20,20,246,60,129,5,221,0,20,20,0,35,129,6,238,221,221,35,35,18,0,129,2,50,110,110,130,0,166,131,7,176,176,176,100,100,98,63,30,129,1,1,0,128,2,0,12,0,48,0,0,0,41,32,1,0,27,50,37,24,24,24,162,162,162,212,0,46,94,94,94,104,98,71,94,94,94,232,232,232,232,94,94,232,232,131,134,4,208,158,158,158,203,130,0,2,132,1,137,149,131,0,156,131,14,13,0,4,2,3,3,2,2,1,3,1,1,1,2,2,13,196,236,50,0,206,191,193,206,20,20,20,20,206,20,129,2,80,80,80,131,1,60,60,130,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,68,0,0,0,63,32,1,0,37,93,93,93,92,100,100,232,232,27,93,50,37,24,24,24,162,162,162,212,0,46,94,94,94,104,98,71,94,94,94,232,232,232,232,94,94,232,232,131,0,100,130,0,6,129,2,42,83,100,134,4,208,158,158,158,203,130,0,2,132,1,137,149,131,0,156,131,21,20,0,1,1,1,1,3,1,2,4,2,3,3,2,2,1,3,1,1,1,2,2,128,19,226,226,228,226,0,2,196,236,50,0,206,191,193,206,20,20,20,20,206,20,6,206,0,246,223,0,235,206,129,2,80,80,80,131,1,60,60,130,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,253,131,133,133,133,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,88,0,0,0,64,32,1,0,48,252,2,6,6,6,22,35,35,131,236,219,202,202,202,228,252,247,245,0,255,252,50,37,24,24,24,162,162,162,212,0,46,94,94,94,104,98,71,94,94,94,232,232,232,232,94,94,232,232,131,129,5,250,245,240,0,20,20,130,8,227,216,194,171,171,171,165,0,254,135,4,208,158,158,158,203,130,0,2,132,1,137,149,131,0,156,131,23,22,0,3,1,2,3,3,3,2,1,3,4,2,3,3,2,2,1,3,1,1,1,2,2,132,17,60,20,30,20,196,236,50,0,206,191,193,206,20,20,20,20,206,20,128,6,236,239,246,0,50,80,80,130,2,80,80,80,131,1,60,60,130,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,253,131,133,133,133,128,2,0,12,0,15,0,0,0,15,0,1,0,7,73,24,155,5,251,101,232,179,131,130,1,156,156,134,2,216,236,40,129,2,216,20,40,131,130,1,70,70,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,43,0,0,0,35,0,1,0,19,37,0,2,24,233,17,12,102,232,178,78,24,164,244,239,24,233,2,0,224,131,128,65,0,138,0,138,129,1,176,176,133,1,176,176,129,65,0,138,0,138,132,0,236,131,9,251,251,221,20,80,176,236,55,5,5,131,0,20,131,128,1,204,204,129,1,110,110,133,1,110,110,129,1,204,204,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,27,0,0,0,27,0,1,0,11,24,44,98,232,232,158,98,39,24,158,217,232,131,128,0,232,129,0,34,129,0,39,129,0,237,132,11,226,246,186,30,10,70,186,246,226,70,10,30,131,128,0,10,129,0,246,129,0,246,129,0,10,132,0,128,2,0,12,0,44,0,0,0,39,0,1,0,9,24,30,187,179,188,222,251,90,232,145,65,255,127,255,123,7,154,187,65,24,166,235,225,220,131,128,4,157,149,154,176,219,131,3,255,251,249,249,130,1,186,186,132,19,236,236,0,243,225,211,206,196,20,30,30,21,8,0,156,236,60,216,236,236,131,128,4,54,54,51,40,18,131,2,255,254,255,131,1,84,84,132,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,5,0,0,0,2,0,1,0,128,0,253,131,133,133,133,128,2,0,12,0,28,32,0,0,19,0,1,0,8,7,0,1,1,1,2,2,2,2,7,199,24,57,232,24,232,24,232,4,235,170,23,86,170,129,0,86,2,76,0,196,140,8,68,68,188,188,0,68,68,0,188,129,0,188,131,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,68,0,0,0,59,0,1,0,34,42,44,25,25,25,46,46,57,97,105,93,93,93,244,212,167,167,167,244,93,93,93,93,109,106,64,92,93,93,231,231,63,76,232,245,131,129,2,10,0,242,130,16,225,210,210,211,88,88,88,33,0,168,168,168,59,84,46,46,34,129,0,70,129,0,251,135,34,196,225,236,236,236,225,196,196,192,198,206,206,206,12,45,70,70,70,10,206,206,206,206,203,197,200,226,206,206,20,20,236,236,40,40,131,129,2,10,0,242,133,8,186,166,166,166,203,0,110,110,110,64,0,170,0,100,144,128,2,0,12,0,45,0,0,0,38,0,1,0,25,18,24,0,51,94,94,94,232,232,232,238,249,0,24,24,162,162,94,94,232,232,10,80,235,175,85,64,0,155,1,54,250,131,128,3,154,152,158,202,132,1,1,1,148,28,236,236,0,224,196,196,196,20,20,20,16,7,0,236,236,60,60,196,196,20,20,211,231,65,45,211,231,65,45,131,128,3,80,80,77,39,155,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,168,0,0,0,159,0,1,0,4,30,253,17,31,219,129,5,90,232,158,98,24,166,129,63,37,225,3,3,226,49,3,23,37,225,9,9,9,9,9,9,39,227,5,5,225,57,5,25,39,227,17,17,17,17,17,17,37,225,3,3,233,29,3,23,37,225,245,245,245,245,245,245,29,217,251,251,205,31,251,15,29,217,247,247,247,247,247,247,4,31,219,253,253,207,131,128,1,118,118,129,1,176,176,133,1,176,176,129,1,118,118,129,1,118,118,129,1,176,176,129,1,176,176,129,1,118,118,129,1,118,118,129,1,176,176,129,1,176,176,129,1,118,118,129,1,118,118,129,1,176,176,129,1,176,176,129,1,118,118,129,1,118,118,129,1,176,176,129,1,176,176,129,1,118,118,132,40,191,236,236,216,0,232,232,212,20,40,216,236,44,24,24,0,40,40,20,55,246,20,20,0,40,10,10,10,10,10,10,241,25,5,5,20,236,5,5,241,25,133,1,236,20,129,1,20,236,129,1,236,20,133,20,231,15,251,251,20,226,251,251,231,15,246,246,246,246,246,246,216,0,236,236,10,131,128,1,184,184,129,1,110,110,133,1,110,110,129,1,184,184,129,1,184,184,129,1,110,110,129,1,110,110,129,1,184,184,129,1,184,184,129,1,110,110,129,1,110,110,129,1,184,184,129,1,184,184,129,1,110,110,129,1,110,110,129,1,184,184,129,1,184,184,129,1,110,110,129,1,110,110,129,1,184,184,132,128,2,0,12,0,68,0,0,0,78,0,1,0,8,50,50,50,50,50,25,0,24,24,129,31,232,232,232,232,232,30,27,24,24,24,11,0,16,50,50,50,37,13,0,196,196,196,0,25,50,50,50,50,60,60,57,44,131,131,3,28,60,60,60,132,1,216,216,138,9,38,42,44,44,44,246,200,200,200,235,138,42,196,196,206,206,206,231,0,236,236,0,11,20,20,20,20,20,216,225,236,236,236,215,196,196,186,196,196,211,241,0,31,31,31,10,236,206,206,206,196,176,186,190,189,131,131,3,236,216,216,216,130,7,1,0,70,70,0,253,253,254,134,9,226,233,236,236,236,5,30,30,30,10,132,1,254,253,131,0,128,2,0,12,0,21,0,0,0,21,32,1,12,11,0,1,3,1,2,3,3,1,2,3,1,2,128,10,10,24,10,245,232,32,70,70,224,186,186,133,5,186,224,33,70,33,224,6,5,4,6,3,3,3,3,5,236,20,229,196,27,60,129,3,60,229,196,27,0,2,0,12,0,37,32,0,0,36,32,1,12,11,2,1,2,1,2,1,1,1,3,2,2,1,11,70,20,184,184,184,187,218,246,232,24,184,184,5,54,54,243,216,216,235,132,0,216,11,10,0,1,3,2,2,1,1,1,3,3,1,10,176,176,41,80,100,109,114,110,20,236,80,128,4,5,191,18,236,246,129,0,60,129,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,0,2,0,12,0,44,32,0,0,44,32,1,14,13,1,1,1,2,2,1,1,2,3,3,2,2,2,2,13,170,0,44,94,44,0,170,216,232,216,24,170,24,232,8,154,154,154,226,51,51,51,205,226,131,0,102,14,13,1,1,3,3,1,1,1,3,1,2,2,2,2,2,13,56,246,196,246,32,56,0,20,20,0,236,56,236,20,8,64,64,6,224,224,32,32,5,2,131,0,192,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,8,0,0,0,8,0,1,4,3,1,2,2,2,3,24,170,24,232,130,0,102,3,236,56,236,0,130,0,192,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,12,0,0,0,11,0,1,6,5,1,2,2,2,2,2,128,4,146,0,232,86,232,130,2,102,0,100,5,236,56,236,0,180,0,130,0,192,129,0,0,2,0,12,0,53,32,0,0,45,32,1,17,16,0,1,1,2,1,1,4,5,2,2,2,2,2,2,2,2,2,16,166,0,6,21,24,24,185,24,170,86,232,80,226,9,0,232,24,9,156,156,163,215,243,0,244,156,0,156,131,2,102,0,154,14,13,0,1,5,4,5,2,2,2,2,2,1,2,3,2,9,65,230,230,65,236,56,200,20,198,18,129,1,20,236,6,64,64,0,8,64,0,64,130,0,192,129,0,64,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,189,0,0,0,159,32,1,0,39,190,148,178,223,0,12,62,79,72,74,20,20,20,1,227,216,166,150,158,150,236,236,236,255,30,40,90,105,99,106,66,108,78,32,0,244,194,178,183,182,65,0,168,0,168,47,40,40,66,106,99,107,90,40,30,255,236,236,236,182,183,178,194,244,0,33,78,108,40,40,216,216,74,72,78,62,12,1,223,178,148,190,150,158,151,166,216,226,1,20,20,20,216,216,65,255,98,255,98,131,7,235,205,205,220,3,40,10,4,130,26,102,102,102,80,52,50,17,236,235,0,154,154,154,176,204,216,245,19,21,21,51,51,39,4,226,246,249,129,13,51,205,205,51,235,235,236,17,50,52,80,102,102,102,130,6,4,10,40,3,220,205,205,133,21,249,246,226,4,39,51,51,21,21,19,245,216,204,176,154,154,154,0,51,205,205,51,131,55,54,0,1,4,1,1,1,4,3,1,1,1,1,4,2,1,1,1,1,1,1,4,1,1,1,1,2,2,1,1,1,1,1,1,4,2,1,1,1,1,4,2,2,2,1,1,1,4,1,1,1,2,1,3,4,2,10,172,192,192,192,192,222,20,20,20,20,9,134,9,104,84,84,84,84,53,24,84,4,104,133,20,24,53,84,84,84,84,236,20,222,192,192,192,192,172,0,9,20,20,20,20,192,128,6,43,43,196,227,0,192,192,129,3,254,0,64,64,129,0,2,129,3,213,213,60,28,129,1,43,213,129,0,253,129,1,192,192,129,3,227,196,43,43,130,3,28,60,213,213,129,5,1,0,64,64,43,213,0,128,2,0,12,0,82,0,0,0,86,32,1,0,35,236,7,24,200,206,216,229,236,33,92,92,92,41,0,251,7,49,84,84,84,61,60,58,32,10,14,24,17,35,58,60,3,232,232,232,243,131,6,250,238,232,232,232,233,235,131,130,25,181,174,165,162,162,162,207,246,19,49,49,49,207,209,242,20,74,95,95,95,93,90,89,250,250,254,130,0,19,129,0,249,142,29,28,0,1,1,1,3,1,1,2,3,1,1,1,2,3,1,1,1,1,1,2,2,1,2,1,2,1,1,2,3,28,226,231,236,10,243,236,217,194,0,246,246,216,190,20,3,239,233,236,236,6,40,30,20,20,20,20,20,20,20,130,14,61,81,81,81,30,223,223,33,30,226,176,176,176,176,176,132,1,3,10,129,1,246,0,0,128,2,0,12,0,31,32,0,0,31,0,1,0,9,8,1,1,1,3,1,2,2,2,2,8,228,178,78,78,178,24,178,78,232,65,255,86,255,86,128,64,0,170,132,15,64,64,74,192,192,192,182,64,236,236,64,64,192,192,20,20,131,128,65,0,130,0,130,129,65,255,126,255,126,140,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,100,0,0,0,89,0,1,0,38,11,0,223,236,251,90,89,92,70,30,251,251,19,13,241,235,175,158,130,156,24,24,170,170,156,156,216,216,20,60,82,79,80,241,226,216,0,11,156,64,255,123,7,139,156,216,222,250,0,232,232,131,19,244,205,205,206,206,123,76,24,1,1,1,101,101,101,101,103,1,236,244,244,131,3,51,205,205,51,129,16,234,180,134,51,51,51,51,13,13,13,21,0,154,156,156,156,156,132,129,9,230,222,206,176,160,181,231,0,20,20,129,9,245,0,45,63,35,25,236,236,56,56,132,6,231,181,160,176,206,221,230,129,5,25,34,63,45,0,245,129,1,20,20,131,128,2,32,32,15,129,1,2,2,130,6,192,192,192,194,192,0,254,133,3,224,32,32,224,129,1,254,253,129,2,241,224,224,130,6,2,0,64,62,64,64,64,132,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,30,32,0,0,25,0,1,12,11,0,2,1,2,2,1,1,2,3,2,2,2,9,8,0,2,3,2,1,6,2,2,2,8,24,24,24,185,185,86,232,0,232,128,3,156,136,0,136,130,0,102,11,236,236,226,216,51,51,51,34,200,20,236,20,128,6,64,24,156,0,156,180,242,130,0,192,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,10,0,0,0,10,0,1,6,5,1,2,2,2,2,2,5,86,232,24,170,24,232,132,0,102,5,200,20,236,56,236,0,132,0,192,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,40,0,0,0,34,0,1,0,16,24,24,28,39,51,55,100,232,232,234,238,0,35,24,156,248,248,131,128,4,154,154,170,199,216,129,4,40,31,13,0,225,129,65,255,43,255,43,131,130,13,4,1,246,196,20,50,59,33,0,219,236,60,0,60,131,128,3,64,64,30,253,131,3,252,253,0,213,129,1,50,50,131,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,0,2,0,12,0,52,32,0,0,42,32,1,16,15,3,4,1,1,1,1,1,2,1,1,1,1,3,1,3,1,15,24,232,40,40,30,30,40,216,216,226,226,216,84,84,172,172,15,20,236,0,196,156,80,60,0,60,80,156,196,162,0,94,0,14,13,1,1,3,1,3,2,2,2,2,2,2,1,3,1,13,246,246,10,10,208,236,208,48,20,48,176,176,80,80,3,206,246,50,246,133,3,51,246,205,246,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,0,2,0,12,0,27,32,0,0,24,32,1,8,7,0,3,2,1,3,2,2,2,128,6,24,170,170,0,86,86,232,5,40,40,0,40,194,40,129,7,6,1,1,4,1,2,4,2,6,246,236,56,56,0,200,20,4,213,234,0,22,43,129,0,128,2,0,12,0,16,0,0,0,16,0,1,8,7,1,2,2,2,2,2,2,2,7,110,0,24,232,24,170,86,232,129,0,154,130,1,154,0,7,200,20,236,20,236,56,200,20,129,0,64,130,1,64,0,128,2,0,12,0,13,0,0,0,13,0,1,8,7,1,2,2,2,2,2,2,2,7,86,232,24,232,24,170,40,216,129,0,164,132,7,200,20,236,20,236,56,236,20,129,0,74,132,128,2,0,12,0,18,0,0,0,18,0,1,10,9,1,2,2,2,2,2,2,2,2,2,9,86,232,24,0,24,170,86,232,40,216,129,0,164,130,0,164,130,9,200,20,236,0,236,56,200,20,236,20,129,0,74,130,0,74,130,128,2,0,12,0,15,0,0,0,13,0,1,8,7,1,2,2,2,2,2,2,2,7,86,232,55,201,24,232,24,170,129,2,196,0,154,130,7,200,20,218,38,236,20,236,56,131,0,64,130,128,2,0,12,0,46,0,0,0,41,32,1,0,23,170,170,10,57,94,94,94,57,10,170,170,216,228,234,232,232,232,234,228,216,24,24,170,170,131,128,16,154,154,154,188,231,17,52,52,52,206,206,206,218,231,231,232,244,137,13,12,1,1,1,1,2,1,1,2,1,5,3,2,2,12,56,226,225,196,196,225,226,56,236,20,236,236,56,9,64,64,64,27,4,224,224,32,32,11,130,128,2,0,12,0,56,0,0,0,47,32,1,0,27,170,170,246,46,94,94,94,46,246,170,170,196,214,229,232,232,232,229,214,196,24,24,170,170,24,24,250,250,131,128,16,154,154,154,188,231,17,52,52,52,206,206,206,218,231,231,232,244,133,0,102,129,0,102,131,15,14,1,1,1,1,2,1,1,2,1,5,3,2,2,1,2,12,56,0,234,196,196,234,0,56,0,20,0,236,56,129,9,64,64,64,32,255,224,224,32,32,11,130,1,192,0,128,2,0,12,0,50,0,0,0,50,0,1,0,27,170,170,215,20,77,77,77,20,215,170,170,157,186,221,235,235,235,221,186,157,24,24,170,170,76,76,232,232,131,128,16,154,154,154,188,231,17,52,52,52,206,206,206,218,231,231,232,244,141,27,234,234,206,216,216,216,216,216,206,234,234,206,227,3,20,20,20,3,227,206,236,236,56,56,190,190,20,20,131,128,16,44,44,44,22,16,9,244,244,244,32,32,32,28,21,16,11,4,141,0,0,2,0,12,0,64,32,0,0,75,32,1,20,19,0,2,2,2,1,5,2,2,1,2,1,3,2,1,2,3,1,2,2,2,19,24,24,24,210,210,45,211,206,226,74,74,226,216,166,216,232,216,166,30,216,128,3,156,146,0,146,129,9,154,154,195,231,52,206,206,212,239,250,129,0,102,23,22,1,3,4,2,2,2,2,1,1,1,2,1,1,2,1,1,1,3,1,1,1,2,2,128,5,216,54,20,215,241,197,64,255,126,3,154,176,176,154,64,255,126,9,197,166,199,249,20,249,199,166,236,0,0,86,132,12,44,44,44,22,9,244,244,32,32,32,28,11,4,130,0,192,0,128,2,0,12,0,66,0,0,0,60,32,1,0,33,216,216,236,28,74,74,74,28,236,216,216,176,198,222,232,232,232,222,198,176,24,24,170,170,24,24,205,206,70,70,216,216,216,216,131,128,16,154,154,154,188,231,16,48,48,48,206,206,206,218,231,231,232,244,133,3,50,206,206,50,130,1,251,251,132,19,18,1,1,1,1,2,1,1,2,1,5,3,2,2,2,2,1,2,1,1,18,198,136,160,176,176,160,136,178,176,20,176,236,56,236,0,211,11,11,227,9,44,44,44,22,9,244,244,32,32,11,130,1,43,213,129,1,47,27,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,41,32,0,0,38,0,1,0,14,13,0,3,2,2,1,1,1,2,3,2,2,1,2,2,11,246,14,246,225,222,49,39,246,158,226,243,222,129,132,8,80,86,94,0,162,169,0,51,205,128,6,236,236,236,246,0,249,248,132,3,26,56,56,56,140,134,12,2,5,205,190,175,175,175,217,0,81,81,81,81,129,3,224,32,32,224,131,128,2,0,12,0,54,0,0,0,49,0,1,0,128,12,7,20,24,202,212,228,245,0,42,91,91,91,45,129,9,1,2,23,11,0,244,232,232,232,244,135,129,16,245,236,161,162,162,162,162,162,211,0,45,94,94,94,96,98,8,134,3,50,206,206,50,131,131,13,20,6,237,212,196,199,203,203,203,244,30,27,22,20,130,4,10,20,20,20,9,135,129,15,245,236,40,56,73,80,80,80,37,0,217,175,175,175,175,175,135,3,224,32,32,224,131,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,0,2,0,12,0,29,32,0,0,33,32,1,9,8,2,2,2,1,3,3,2,2,2,8,86,0,201,0,232,55,201,24,232,3,30,57,211,211,131,0,102,10,9,1,3,2,1,1,2,3,2,2,2,9,200,0,46,0,10,20,226,46,236,20,5,77,213,43,43,43,113,130,0,170,0,2,0,12,0,51,32,0,0,41,32,1,18,17,1,3,1,2,3,1,2,2,1,2,3,2,1,1,2,1,1,2,7,14,25,14,242,231,242,24,180,129,7,48,83,83,48,228,193,193,228,135,9,51,205,162,0,49,94,94,49,0,162,14,13,0,4,2,4,3,2,1,2,2,3,3,1,2,2,5,5,236,5,20,236,66,129,5,5,200,5,40,70,40,133,7,224,32,81,0,175,175,0,81,128,2,0,12,0,90,0,0,0,95,0,1,0,49,236,240,251,7,18,24,24,24,6,0,86,86,0,206,162,162,162,206,0,86,86,24,24,0,29,49,55,55,54,68,90,100,196,196,204,216,220,216,216,210,212,0,50,50,86,86,86,86,232,232,131,138,8,102,102,102,48,10,236,207,206,205,129,17,154,154,154,206,236,0,9,17,19,19,19,51,51,39,17,0,10,247,129,3,51,206,205,51,135,128,21,254,249,244,239,236,236,236,247,0,200,200,0,27,60,60,60,27,0,200,200,236,236,129,5,6,0,239,230,235,252,130,6,23,42,51,60,104,120,49,130,5,200,200,200,200,20,20,131,5,10,10,10,9,7,3,132,28,192,192,192,224,0,15,32,32,32,10,0,64,64,64,61,64,40,30,6,246,246,246,226,226,226,226,226,65,40,129,3,226,30,32,224,135,128,2,0,12,0,44,0,0,0,42,32,1,0,129,4,34,86,86,86,35,131,10,233,232,232,232,233,55,55,201,201,24,24,133,128,13,156,156,212,251,16,51,51,51,205,205,205,218,251,8,132,0,102,129,0,102,131,14,13,1,3,1,1,1,2,1,1,2,2,2,2,2,2,13,226,186,186,222,0,60,0,9,20,250,226,46,236,20,8,75,18,248,224,224,32,32,32,18,132,0,128,2,0,12,0,13,0,0,0,13,0,1,6,5,1,2,2,2,2,2,5,24,0,24,170,24,232,1,206,50,130,0,102,128,4,20,236,56,236,0,1,43,213,130,0,192,128,2,0,12,0,210,0,0,0,172,0,1,0,5,14,208,248,46,80,92,67,0,142,0,159,0,152,0,154,20,100,100,100,81,51,40,246,230,238,230,236,236,236,255,30,40,90,105,99,106,66,64,0,128,11,88,34,0,244,194,178,183,182,93,93,249,249,65,0,160,0,160,20,80,80,66,106,99,107,90,40,30,255,236,236,236,182,183,178,194,244,0,35,88,64,0,128,1,80,80,129,67,0,154,0,152,0,158,0,142,15,92,81,46,248,208,14,230,238,231,246,40,50,81,100,100,100,129,1,186,186,131,7,235,205,205,220,3,40,10,4,130,26,102,102,102,80,52,50,17,236,235,0,154,154,154,176,204,216,245,19,21,21,51,51,39,4,226,246,249,130,16,154,154,0,51,205,205,51,235,235,236,17,50,52,80,102,102,102,130,6,4,10,40,3,220,205,205,133,21,249,246,226,4,39,51,51,21,21,19,245,216,199,174,154,154,154,0,51,205,205,51,131,18,172,182,192,201,202,202,202,202,232,6,20,20,20,20,20,20,20,20,9,138,11,104,94,84,76,74,74,74,74,43,14,170,170,129,4,66,66,34,34,104,137,36,14,43,74,74,74,74,76,84,94,231,231,25,25,6,232,202,202,202,202,201,192,182,172,0,9,20,20,20,20,20,20,20,20,236,236,210,210,131,128,6,43,43,43,43,43,196,227,130,4,192,192,192,192,192,129,0,254,129,4,64,64,64,64,64,129,0,2,129,6,213,213,213,213,213,60,28,130,6,59,59,0,213,43,43,213,129,0,253,129,4,192,192,192,192,192,130,6,227,196,43,43,43,43,43,133,6,28,60,213,213,213,213,213,129,0,1,129,9,59,59,59,59,59,0,213,43,43,213,131,0,128,2,0,12,0,107,0,0,0,96,0,1,0,42,11,0,223,236,251,90,89,92,70,30,251,251,19,13,241,235,175,158,130,156,24,24,170,170,76,76,232,232,156,156,216,216,20,60,82,79,80,241,226,216,0,11,156,64,255,123,7,139,156,216,221,250,0,232,232,131,19,244,205,205,206,206,123,76,24,1,1,1,101,101,101,101,103,1,236,244,244,132,6,159,159,0,51,205,205,51,129,16,234,180,134,51,51,51,51,13,13,13,21,0,154,158,159,159,159,132,129,9,230,222,206,176,160,181,231,0,20,20,129,13,245,0,45,63,35,25,236,236,56,56,190,190,20,20,132,6,231,181,160,176,206,221,230,129,5,25,34,63,45,0,245,129,1,20,20,131,128,2,32,32,15,129,1,2,2,130,6,192,192,192,194,192,0,254,134,6,64,64,0,224,32,32,224,129,1,254,253,129,2,241,224,224,130,6,2,0,64,62,64,64,64,132,128,2,0,12,0,15,0,0,0,15,0,1,8,7,1,2,2,2,2,2,2,2,7,60,216,86,232,24,170,24,232,0,154,132,1,205,51,7,190,20,200,20,236,56,236,20,0,64,132,1,32,224,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,29,0,0,0,32,0,1,0,131,11,60,24,159,5,251,97,232,196,55,55,201,201,131,3,51,205,205,51,130,1,151,151,131,1,146,146,132,6,236,236,20,20,218,236,70,129,6,186,20,38,218,218,38,38,131,4,224,32,32,224,196,129,1,60,60,129,0,196,135,128,2,0,12,0,35,0,0,0,35,0,1,0,15,76,76,232,232,106,36,24,150,219,232,24,36,106,232,220,150,131,128,1,154,154,129,0,31,129,0,225,129,0,224,129,0,31,132,15,190,190,20,20,176,236,216,80,20,40,216,236,176,40,20,80,131,128,1,64,64,129,0,236,129,0,20,129,0,20,129,0,236,132,0,0,2,0,12,0,33,32,0,0,30,32,1,10,9,1,2,1,3,2,1,3,2,2,2,9,66,222,0,24,170,170,0,86,86,232,7,154,0,40,40,0,40,194,40,129,9,8,1,2,2,1,4,1,2,4,2,8,190,20,246,236,56,56,0,200,20,6,64,0,213,234,0,22,43,129,0,128,2,0,12,0,23,32,0,0,17,0,1,8,7,1,1,2,2,1,3,3,2,7,6,2,2,2,1,3,3,2,6,86,0,170,0,232,24,170,3,27,51,205,205,130,7,200,200,40,56,60,20,236,56,5,90,27,224,32,32,110,129,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,17,0,0,0,21,32,1,8,7,0,2,5,4,2,1,3,1,129,5,24,232,94,94,162,162,1,51,205,129,3,152,0,94,0,6,5,7,4,2,1,3,1,5,236,20,196,196,60,60,129,3,81,0,175,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,39,0,0,0,41,0,1,0,19,47,75,187,215,74,255,7,188,24,24,170,170,24,24,232,232,86,86,232,232,131,132,1,100,100,129,1,186,186,129,1,154,154,129,1,186,186,132,19,179,239,23,83,249,3,3,13,236,236,56,56,236,236,20,20,200,200,20,20,131,132,65,255,46,255,46,129,1,64,64,129,1,64,64,129,1,64,64,132,0,128,2,0,12,0,15,0,0,0,17,0,1,0,7,24,81,175,232,105,252,4,151,131,132,1,95,95,132,4,236,236,20,20,196,129,0,60,131,132,65,255,46,255,46,132,0,128,2,0,12,0,60,32,0,0,63,0,1,0,20,19,4,3,3,1,1,1,1,1,1,2,1,1,1,1,3,2,2,2,2,2,19,24,244,232,244,50,50,40,40,50,206,206,216,216,206,50,94,50,206,162,206,132,14,216,216,20,20,0,20,20,216,216,182,0,74,74,0,182,128,34,5,236,236,236,5,0,251,20,20,20,251,213,213,236,236,213,213,43,43,20,20,43,43,0,218,196,196,196,218,0,38,60,60,60,38,131,129,2,18,0,238,130,2,238,0,18,140,11,81,81,54,0,201,175,175,175,201,0,54,81,131,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,0,2,0,12,0,65,32,0,0,61,32,1,21,20,4,1,1,1,1,1,1,1,1,1,1,1,2,3,4,1,1,3,3,1,2,20,24,24,41,74,100,232,232,100,26,197,161,161,146,176,232,245,0,94,0,210,161,128,10,6,10,15,20,0,95,115,101,57,237,176,131,4,164,0,92,92,0,20,19,1,4,1,1,1,1,1,1,1,1,1,1,2,3,4,2,3,1,2,3,19,246,236,241,248,0,20,20,0,24,51,62,62,72,20,20,241,190,190,241,62,129,1,255,255,129,4,166,166,170,191,228,131,4,86,0,214,170,236,128,2,0,12,0,68,32,0,0,77,0,1,0,22,21,1,1,3,1,2,2,1,3,3,2,2,2,2,2,1,1,2,3,2,1,3,3,21,162,50,102,102,0,162,0,232,0,24,162,192,226,162,0,49,102,50,162,0,232,0,6,156,156,206,246,35,5,5,131,6,226,30,221,221,221,40,100,129,1,10,251,8,50,50,228,217,198,198,198,224,242,130,9,10,20,20,20,10,0,236,236,50,50,129,1,236,236,129,14,12,237,198,198,198,244,26,50,50,0,10,20,20,20,10,132,128,12,80,80,80,54,35,11,236,236,236,246,246,246,251,139,9,10,20,20,20,248,226,204,176,176,176,132,2,5,10,10,131,128,2,0,12,0,8,0,0,0,8,0,1,4,3,1,2,2,2,3,24,162,0,232,130,0,100,3,236,50,236,20,130,0,182,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,12,0,0,0,12,0,1,6,5,1,2,2,2,2,2,5,24,162,24,232,82,232,130,2,100,0,100,5,236,50,0,20,194,20,130,2,182,0,182,0,2,0,12,0,50,32,0,0,49,32,1,16,15,0,1,1,2,4,1,2,2,2,2,2,2,2,2,2,2,15,165,0,11,20,185,176,24,174,82,232,98,236,9,254,232,24,8,154,154,172,0,223,173,166,0,166,131,2,100,0,156,16,15,0,1,1,2,2,1,4,2,2,2,2,2,2,2,2,2,0,97,130,11,97,97,236,62,194,20,194,20,0,194,20,236,2,74,74,62,129,3,146,74,0,74,131,2,182,0,74,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,174,0,0,0,124,32,1,0,8,216,216,204,248,5,95,112,79,30,129,7,10,3,255,246,151,138,160,166,129,29,246,252,1,10,105,119,96,90,40,40,52,9,251,161,145,176,226,45,45,50,50,40,90,96,119,105,10,1,252,246,129,28,226,176,145,161,251,9,52,40,46,46,212,212,30,79,112,95,5,248,204,216,216,166,160,138,151,246,255,3,10,129,3,212,212,211,211,131,128,5,214,214,226,214,80,32,130,25,100,100,100,97,100,186,207,241,246,0,156,156,156,159,156,70,48,15,10,0,42,42,31,42,176,224,129,13,42,214,214,42,0,246,241,207,186,100,97,100,100,100,130,5,32,80,214,226,214,214,133,20,224,176,42,31,42,42,0,10,15,48,70,156,159,156,156,156,0,42,214,214,42,131,44,43,0,1,3,1,2,1,2,1,3,1,5,1,3,1,4,1,3,1,3,2,2,1,4,1,3,2,1,3,1,3,2,2,1,1,2,1,3,1,4,1,3,2,2,2,128,5,188,188,188,182,178,20,130,0,236,131,5,68,68,68,78,234,252,131,11,236,78,68,68,68,246,10,178,182,188,188,188,131,2,20,0,22,128,1,45,45,130,6,196,196,196,0,60,60,60,129,1,211,211,129,1,45,211,129,1,196,196,130,1,45,45,132,1,211,211,129,4,60,60,0,45,211,0,128,2,0,12,0,89,0,0,0,83,0,1,0,128,12,4,11,14,220,228,248,0,46,100,100,100,47,236,129,28,236,31,83,100,100,100,43,0,2,6,9,24,18,8,0,245,232,232,232,246,241,212,212,236,243,232,232,232,245,131,129,26,254,250,176,169,164,164,164,215,0,18,37,37,37,219,219,219,233,2,20,56,92,92,92,96,92,0,4,132,9,254,246,242,247,1,7,9,8,10,5,132,128,11,251,240,236,10,8,2,0,228,196,196,196,223,131,19,230,204,196,196,196,230,0,254,249,246,236,241,249,0,9,20,20,20,15,7,129,5,6,16,20,20,20,9,131,131,22,66,77,86,86,86,56,30,245,206,206,206,50,50,50,32,251,226,199,170,170,170,170,170,134,9,1,254,254,5,251,5,8,6,10,5,132,0,128,2,0,12,0,31,0,0,0,27,32,1,0,15,176,176,162,94,80,80,94,162,24,24,162,162,94,94,232,232,131,128,65,255,126,255,126,129,65,0,130,0,130,140,8,7,2,1,3,1,2,2,2,2,7,60,206,196,50,236,50,206,20,64,0,180,128,64,255,76,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,95,0,0,0,96,0,1,0,8,60,60,39,48,50,105,88,67,35,130,35,5,9,2,5,222,222,233,0,24,24,162,162,162,162,246,246,246,25,62,88,105,50,48,39,60,60,246,223,202,202,241,238,245,241,246,246,131,7,246,206,206,213,216,90,46,8,130,8,100,100,100,93,100,0,252,246,246,131,3,50,206,206,50,129,16,248,210,166,40,44,50,50,10,10,10,5,0,156,163,156,156,156,132,128,46,236,225,243,236,206,189,203,232,236,20,20,0,2,250,0,52,62,51,50,236,236,50,50,50,50,20,20,236,222,187,175,196,236,246,227,236,0,50,55,62,52,0,250,2,0,20,20,131,7,10,37,37,41,37,20,252,246,130,8,182,182,182,174,182,20,19,10,10,131,3,219,37,37,219,129,16,10,4,236,219,215,219,219,246,246,246,238,236,74,83,74,74,74,132,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,41,0,0,0,31,32,1,0,19,24,24,18,19,24,24,24,189,189,189,197,236,94,94,232,232,24,24,232,232,131,128,4,156,156,164,167,156,129,2,156,209,249,132,0,100,129,0,100,131,10,9,0,2,1,1,1,4,4,2,2,2,9,236,229,220,216,216,57,206,20,216,20,128,2,74,60,29,132,0,182,0,128,2,0,12,0,51,0,0,0,35,0,1,0,23,34,0,252,103,83,83,103,238,25,25,173,173,19,153,173,173,153,4,0,236,83,83,231,231,131,128,65,255,116,255,116,129,65,0,162,0,162,133,65,0,162,0,162,129,65,255,116,255,116,136,0,20,129,13,174,214,214,204,10,236,236,42,42,246,52,42,42,82,129,4,246,214,214,20,20,131,128,1,80,80,141,1,80,80,136,0,128,2,0,12,0,11,0,0,0,13,0,1,6,5,1,2,2,2,2,2,5,94,232,24,162,254,227,131,1,214,42,4,206,20,236,50,120,64,255,105,131,1,45,211,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,10,0,0,0,10,0,1,6,5,1,2,2,2,2,2,5,94,232,24,162,250,232,132,0,100,5,206,20,236,50,174,51,132,0,182,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,8,0,0,0,8,0,1,4,3,1,2,2,2,3,59,197,24,232,130,0,100,3,221,35,236,20,130,0,182,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,0,2,0,12,0,100,32,0,0,89,32,1,37,36,0,3,1,2,3,3,1,2,2,1,1,2,1,4,2,1,3,2,3,1,2,1,1,1,1,3,1,2,2,1,1,3,2,2,2,2,2,36,196,192,247,222,0,90,90,0,222,247,192,195,196,232,60,42,24,60,74,19,44,0,208,166,166,0,23,44,19,74,74,59,44,59,207,222,207,128,6,236,236,0,168,0,47,88,139,10,88,88,88,47,0,168,168,0,236,236,246,133,35,34,0,1,1,1,2,1,1,3,2,3,2,2,1,1,1,4,2,1,3,2,1,1,1,3,1,3,4,1,1,1,2,1,1,4,6,34,30,30,40,30,20,20,20,222,204,241,20,30,40,30,30,20,226,232,236,226,226,216,226,236,15,52,253,236,236,236,226,216,226,236,20,132,4,120,113,90,0,166,140,5,166,166,0,90,113,120,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,30,32,0,0,30,0,1,0,9,8,0,3,2,1,2,1,2,2,2,8,236,24,162,162,198,236,80,94,232,6,42,20,0,20,214,214,42,129,128,14,235,236,236,236,50,50,50,45,50,206,206,206,206,20,20,131,2,211,211,221,131,4,17,45,45,45,211,135,0,128,2,0,12,0,16,0,0,0,16,0,1,8,7,1,2,2,2,2,2,2,2,7,119,1,24,0,24,162,82,232,129,0,156,130,1,156,0,7,206,20,236,0,236,50,194,20,129,0,74,130,1,74,0,128,2,0,12,0,13,0,0,0,13,0,1,8,7,1,2,2,2,2,2,2,2,7,94,232,22,229,24,162,43,213,129,0,166,132,7,206,20,236,20,236,50,236,20,129,0,84,132,128,2,0,12,0,30,32,0,0,29,0,1,0,10,9,1,2,2,2,2,2,2,2,2,2,9,118,0,24,0,24,162,82,232,38,218,129,0,166,130,0,166,130,3,206,206,20,20,131,3,236,236,50,50,129,5,20,20,241,241,15,15,131,132,1,84,84,133,1,84,84,136,128,2,0,12,0,15,0,0,0,13,0,1,8,7,1,2,2,2,2,2,2,2,7,94,232,53,203,24,232,24,162,129,2,166,0,172,130,7,206,20,224,32,236,20,236,50,131,0,90,130,0,2,0,12,0,32,32,0,0,41,32,1,10,9,1,1,2,4,2,1,4,2,2,2,9,162,10,100,10,162,0,232,0,24,162,6,156,156,196,50,206,206,243,130,13,12,1,1,1,1,2,1,1,2,1,2,4,2,2,12,50,226,215,196,196,215,226,50,0,20,0,236,50,9,74,74,74,42,251,219,219,37,37,27,130,0,0,2,0,12,0,49,32,0,0,39,32,1,16,15,1,1,1,1,3,1,2,1,1,3,1,1,2,2,2,2,15,194,0,47,100,47,0,206,236,233,232,233,236,60,194,24,0,9,156,156,156,196,50,50,206,206,206,243,132,0,100,12,11,0,2,1,1,2,1,1,3,8,2,1,2,9,246,246,225,196,196,225,246,20,226,40,129,128,6,74,74,42,251,219,219,37,129,1,182,0,128,2,0,12,0,41,32,0,0,53,0,1,0,14,13,1,1,2,4,2,1,1,2,2,1,2,2,2,2,13,162,0,94,0,162,236,245,0,245,236,24,162,94,232,7,176,176,208,40,216,216,216,236,133,65,255,102,255,102,6,7,233,193,193,193,233,7,65,255,102,255,102,14,243,5,27,27,27,5,243,236,236,50,50,206,206,20,20,131,128,14,94,94,94,52,18,241,199,199,199,37,37,37,27,18,10,141,0,128,2,0,12,0,67,32,0,0,66,0,1,0,23,22,1,1,1,1,2,1,1,1,1,2,2,2,1,3,3,2,1,1,3,1,1,2,2,22,24,28,45,45,210,210,210,216,245,49,207,207,0,80,0,206,0,244,232,244,0,45,206,7,156,156,174,176,0,176,216,249,130,3,156,156,0,100,134,0,84,34,236,236,225,216,216,216,57,57,57,43,9,231,231,15,15,160,160,246,225,196,196,196,225,246,180,180,236,254,20,20,20,254,236,216,216,133,128,3,74,74,61,44,129,2,246,250,254,133,14,74,74,74,42,18,251,219,219,219,37,37,37,27,18,10,137,128,2,0,12,0,62,0,0,0,56,32,1,0,21,207,207,0,43,80,80,80,43,0,205,205,246,246,232,232,232,246,246,24,24,162,162,129,7,9,9,49,49,207,207,207,207,131,128,14,156,156,156,184,220,6,42,42,42,214,214,214,224,220,230,133,3,42,214,214,42,130,1,254,24,132,18,17,1,1,3,3,2,1,1,2,2,1,2,2,1,2,2,2,1,1,128,10,236,196,236,0,236,254,20,254,236,236,50,129,3,206,40,40,0,7,74,74,9,219,37,37,37,9,131,1,219,37,129,1,15,16,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,0,2,0,12,0,48,32,0,0,52,32,1,16,15,0,4,2,3,1,1,1,1,1,2,2,1,3,1,3,2,128,12,24,0,232,56,47,18,0,213,166,212,0,8,252,129,131,11,70,98,98,98,98,0,158,158,166,5,42,214,18,17,0,1,3,1,1,3,1,3,2,1,2,1,3,1,1,1,1,2,15,50,16,236,247,0,30,246,0,70,70,59,50,15,20,28,42,129,132,7,226,186,176,217,0,80,80,80,130,1,211,45,128,2,0,12,0,50,0,0,0,39,32,1,0,128,24,8,21,24,227,233,247,0,42,90,90,90,44,0,8,27,35,24,19,7,0,244,232,232,232,245,135,131,12,170,165,158,158,158,208,0,48,98,98,98,99,102,136,3,42,214,214,42,131,13,12,0,3,1,3,3,3,3,1,3,1,3,2,2,128,0,236,129,6,216,0,226,236,0,9,20,129,129,4,60,80,0,176,176,131,1,211,45,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,0,2,0,12,0,39,32,0,0,34,32,1,12,11,2,2,2,2,1,1,1,2,3,2,2,2,11,94,246,162,152,206,206,219,232,24,162,25,0,1,23,48,129,2,216,216,216,130,1,214,42,11,10,1,2,1,2,2,2,4,2,2,2,2,10,206,228,246,50,65,50,20,236,50,0,20,3,166,166,166,166,132,1,45,211,0,0,2,0,12,0,39,32,0,0,43,32,1,14,13,0,4,2,1,3,1,2,2,1,2,3,2,4,2,7,254,0,254,243,232,243,24,177,129,3,51,90,221,182,135,5,42,214,148,0,108,0,14,13,0,4,9,2,2,2,2,1,1,1,3,1,1,1,13,20,10,236,50,40,0,224,186,186,186,52,90,90,90,131,9,45,211,66,34,0,222,190,222,0,34,128,2,0,12,0,91,0,0,0,92,0,1,0,128,26,12,24,24,24,11,0,94,94,0,208,156,156,156,208,0,94,94,24,24,0,37,97,111,105,107,94,70,129,2,23,28,11,129,11,253,241,241,0,70,70,94,94,94,94,232,232,131,2,246,246,252,132,24,100,100,100,61,25,245,206,206,206,246,0,158,158,158,188,226,236,254,10,10,10,50,50,42,20,129,1,251,251,129,3,50,206,206,50,135,128,18,247,236,236,236,246,0,206,206,10,26,50,50,50,26,10,206,206,236,236,129,4,7,0,216,202,244,129,8,50,32,6,250,255,33,53,43,11,130,5,206,206,206,206,20,20,131,4,5,5,254,246,251,130,28,182,182,182,216,242,8,37,37,37,5,0,74,74,74,68,74,26,26,5,5,5,219,219,215,201,185,226,225,239,129,3,219,37,37,219,135,0,2,0,12,0,79,32,0,0,64,32,1,24,23,0,1,3,2,2,1,1,1,2,3,2,2,2,1,1,1,1,1,1,2,1,1,2,1,23,94,94,246,162,152,206,206,219,232,24,162,25,0,39,45,41,71,94,94,232,232,232,19,41,64,255,116,128,0,48,129,2,216,216,216,130,7,214,42,0,154,152,155,199,246,64,255,66,1,216,229,129,21,20,0,1,2,1,2,2,2,3,3,2,2,2,2,1,1,1,1,4,1,1,1,20,206,206,228,246,50,65,50,20,236,50,0,20,236,236,220,206,206,20,11,249,236,4,176,166,166,166,166,132,5,45,211,100,100,102,49,129,2,6,7,0,0,128,2,0,12,0,13,0,0,0,13,0,1,6,5,1,2,2,2,2,2,5,24,0,24,162,0,232,1,214,42,130,0,100,5,236,20,236,50,236,20,1,45,211,130,0,182,128,2,0,12,0,215,0,0,0,169,32,1,0,0,98,64,0,130,3,87,75,97,106,66,0,196,0,213,0,174,27,120,90,90,120,110,99,90,251,238,16,30,246,246,216,226,237,246,85,99,64,50,228,206,248,5,239,230,140,64,255,124,18,162,216,5,5,85,85,228,50,64,99,85,246,237,226,216,246,246,216,162,64,255,124,10,140,230,239,5,248,206,75,75,5,5,120,66,0,174,0,213,0,196,3,106,97,75,87,64,0,130,18,98,30,16,238,251,90,98,110,120,90,90,251,251,75,75,103,103,253,253,131,128,62,214,214,220,221,214,90,39,5,5,5,105,105,105,105,110,186,207,241,246,251,151,151,151,152,146,70,48,15,10,0,42,42,36,34,42,166,216,251,251,42,214,214,42,0,246,241,207,186,110,105,105,105,105,5,5,5,39,90,214,221,220,214,214,131,26,251,251,216,166,42,34,36,42,42,0,10,15,48,70,141,151,156,156,156,251,42,214,214,42,0,156,156,132,56,55,0,1,2,2,1,2,1,3,1,1,1,1,3,3,3,1,3,1,1,4,1,1,1,1,2,2,1,1,3,1,1,2,3,1,2,1,4,2,2,1,1,1,1,1,2,2,1,1,3,1,2,1,4,2,2,2,55,58,22,215,209,209,197,188,30,27,20,20,20,40,226,236,236,216,188,234,47,47,47,59,68,194,31,188,216,236,236,236,226,68,59,47,47,234,245,9,188,197,209,209,209,215,22,58,40,20,20,27,30,215,62,194,20,128,9,45,45,45,10,5,5,201,201,204,206,129,1,55,50,130,7,211,211,246,248,251,251,45,211,130,7,206,204,201,5,5,10,45,45,129,6,251,251,248,246,211,211,211,130,6,45,50,50,45,211,50,0,0,128,2,0,12,0,102,0,0,0,103,0,1,0,8,68,60,39,48,50,105,88,67,35,130,39,5,9,2,5,222,222,233,0,24,24,162,162,162,162,246,246,82,82,232,232,246,25,62,88,105,50,48,39,60,68,246,223,202,202,241,238,245,241,246,246,131,7,246,206,206,213,216,90,46,8,130,8,100,100,100,93,100,0,252,246,246,131,6,50,206,206,50,0,161,161,130,16,248,210,166,40,44,50,50,10,10,10,5,0,156,165,161,161,161,132,51,8,236,225,243,236,206,189,203,232,236,20,20,0,2,249,0,52,62,51,50,236,236,50,50,50,50,20,20,194,194,20,20,236,222,187,175,196,236,246,227,236,8,50,55,62,52,0,249,2,0,20,20,131,7,10,37,37,41,37,20,252,246,130,8,182,182,182,174,182,20,19,10,10,131,6,219,37,37,219,0,74,74,130,16,10,4,236,219,215,219,219,246,246,246,238,236,74,83,74,74,74,132,128,2,0,12,0,15,0,0,0,17,0,1,8,7,1,2,2,2,2,2,2,2,7,40,190,94,232,24,162,254,227,0,156,132,1,214,42,6,194,20,206,20,236,50,120,64,255,105,0,74,132,1,45,211,128,2,0,12,0,23,0,0,0,19,0,1,0,2,64,24,156,129,6,100,232,192,59,59,197,197,131,130,1,166,166,131,1,196,196,132,2,221,236,40,129,6,216,20,35,221,221,35,35,131,130,1,100,100,138,0,128,2,0,12,0,29,0,0,0,28,0,1,0,131,2,64,24,156,129,6,100,232,192,59,59,197,197,131,0,84,129,0,84,130,1,166,166,131,1,196,196,132,6,236,236,20,20,221,236,40,129,6,216,20,35,221,221,35,35,131,0,166,129,0,166,130,1,100,100,138,128,2,0,12,0,35,0,0,0,35,0,1,0,15,46,45,197,198,24,44,98,232,232,158,98,39,24,158,217,232,131,128,1,156,156,129,0,232,129,0,34,129,0,39,129,0,237,132,15,194,194,20,20,226,246,186,30,10,70,186,246,226,70,10,30,131,128,1,74,74,129,0,10,129,0,246,129,0,246,129,0,10,132,0,128,2,0,12,0,36,32,0,0,38,0,1,0,11,10,1,2,1,3,2,1,2,1,2,2,2,10,42,192,236,24,162,162,198,236,80,94,232,8,156,0,42,20,0,20,214,214,42,129,19,194,194,20,20,0,235,236,236,236,50,50,50,45,50,206,206,206,206,20,20,131,128,5,74,74,0,211,211,221,131,4,17,45,45,45,211,135,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,46,0,0,0,25,32,1,0,132,22,12,24,24,24,12,0,244,232,232,232,244,0,47,100,100,100,47,0,209,156,156,156,209,131,3,36,220,220,36,139,11,158,158,209,0,46,98,98,98,46,0,209,158,131,8,7,5,3,3,3,3,3,3,3,7,246,236,9,20,227,196,29,60,131,3,80,217,176,38,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,0,2,0,12,0,61,32,0,0,51,32,1,20,19,5,2,2,3,1,3,3,1,2,2,1,2,1,1,2,1,1,1,2,1,19,24,245,232,232,232,232,0,48,100,16,196,0,196,17,100,100,47,0,164,164,130,14,253,3,0,158,158,0,50,50,206,206,206,0,46,98,98,129,17,16,0,5,1,3,3,1,3,3,1,1,1,3,4,2,3,2,1,128,15,236,0,20,50,50,20,5,231,196,196,0,228,196,5,50,50,131,10,15,241,0,80,80,48,20,219,37,236,176,129,128,2,0,12,0,85,0,0,0,85,0,1,0,128,6,5,24,24,24,245,212,217,129,19,60,100,100,100,46,0,241,246,24,24,5,250,0,251,232,232,232,3,29,28,129,11,204,156,156,156,201,0,238,236,232,232,237,12,131,129,16,232,236,209,188,191,207,216,216,229,19,40,76,98,98,98,96,98,132,16,24,30,55,71,64,46,40,40,26,254,216,189,158,158,158,158,158,134,128,42,238,236,236,236,205,181,198,244,196,206,196,196,196,224,0,228,212,236,236,229,238,0,18,20,20,20,48,75,77,50,110,80,60,60,60,19,246,241,9,20,20,12,22,131,129,16,251,20,6,255,8,28,40,30,33,20,246,216,176,176,176,174,176,132,16,10,0,13,12,251,231,226,246,241,10,20,53,80,80,80,80,80,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,189,0,0,0,151,0,1,0,9,244,20,238,230,252,5,95,112,79,30,129,7,10,3,255,246,151,138,160,166,129,30,246,252,1,10,105,119,96,90,12,236,18,26,4,251,161,145,176,226,45,45,65,65,12,90,96,119,105,10,1,252,246,129,32,226,176,145,161,251,4,26,18,236,45,45,50,206,211,211,30,79,112,95,5,252,230,238,20,244,166,160,138,151,246,255,3,10,129,3,191,191,211,211,131,128,6,214,214,220,221,214,80,32,130,26,100,100,100,97,100,186,207,241,246,0,156,156,156,159,156,70,48,14,10,0,42,42,36,34,42,176,224,129,13,42,214,214,42,0,246,241,207,186,100,97,100,100,100,130,8,32,80,214,221,220,214,214,0,220,129,0,220,130,21,224,176,42,34,36,42,42,0,10,14,48,70,156,159,156,156,156,0,42,214,214,42,131,11,28,248,218,194,188,188,188,188,182,178,20,20,135,1,236,236,135,14,228,8,38,63,68,68,68,68,73,78,234,234,11,11,228,135,26,236,236,78,73,68,68,68,68,63,38,8,245,245,210,44,9,9,178,182,188,188,188,188,194,218,248,28,135,5,20,20,235,235,22,22,131,128,4,45,45,45,45,45,132,4,196,196,196,196,196,132,4,60,60,60,60,60,129,0,255,129,4,211,211,211,211,211,131,3,211,45,45,211,132,4,196,196,196,196,196,132,6,45,45,45,45,45,0,246,129,0,254,132,4,211,211,211,211,211,129,0,255,129,9,60,60,60,60,60,0,211,45,45,211,131,0,128,2,0,12,0,86,0,0,0,84,0,1,0,128,46,15,24,210,222,242,0,47,98,98,98,73,34,10,250,4,54,94,94,94,75,34,0,3,12,15,24,22,14,5,0,244,232,232,232,242,232,232,232,232,232,237,236,232,232,232,238,249,131,130,22,178,168,158,158,158,200,236,6,39,56,56,56,211,214,250,30,49,79,98,98,98,98,98,136,7,246,254,2,226,30,2,7,5,136,128,11,244,236,20,16,6,0,227,194,194,194,211,240,130,19,220,190,190,190,204,233,0,255,252,251,236,238,244,253,0,11,20,20,20,8,132,6,5,15,20,20,20,16,7,131,130,22,50,66,80,80,80,37,0,244,228,220,220,220,37,36,18,0,234,198,176,176,176,176,176,135,3,4,12,10,10,129,3,246,246,248,253,135,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,95,0,0,0,96,0,1,0,8,68,60,39,48,50,105,88,67,35,130,35,5,9,2,5,222,222,233,0,24,24,162,162,162,162,246,246,246,25,62,88,105,50,48,39,60,68,246,223,202,202,241,238,245,241,246,246,131,7,246,206,206,213,216,90,46,8,130,8,100,100,100,93,100,0,252,246,246,131,3,50,206,206,50,129,16,248,210,166,40,44,50,50,10,10,10,5,0,156,163,156,156,156,132,47,8,236,225,243,236,206,189,203,232,236,20,20,0,2,249,0,52,62,51,50,236,236,50,50,50,50,20,20,236,222,187,175,196,236,246,227,236,8,50,55,62,52,0,249,2,0,20,20,131,7,10,37,37,41,37,20,252,246,130,8,182,182,182,174,182,20,19,10,10,131,3,219,37,37,219,129,16,10,4,236,219,215,219,219,246,246,246,238,236,74,83,74,74,74,132,128,2,0,12,0,15,0,0,0,15,0,1,0,4,24,75,181,232,95,129,0,161,131,132,1,80,80,132,7,221,225,41,35,225,5,5,31,131,132,1,178,178,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,56,0,0,0,45,32,1,0,31,30,30,180,180,50,37,24,24,24,162,162,162,212,0,46,94,94,94,104,98,71,94,94,94,232,232,180,180,94,94,232,232,131,128,1,156,156,135,4,208,158,158,158,203,130,0,2,132,1,147,149,131,0,156,131,15,14,1,2,1,4,2,3,3,2,3,3,1,1,1,2,2,14,194,20,196,236,50,0,206,192,206,20,20,20,20,206,20,0,74,130,2,80,80,80,130,1,40,40,130,128,2,0,12,0,58,0,0,0,63,0,1,0,34,30,23,24,24,24,162,162,162,193,226,6,43,43,43,213,213,213,20,92,92,92,232,232,92,92,105,102,83,70,60,39,43,55,52,40,131,129,1,219,196,129,6,196,178,168,168,168,181,196,129,4,196,168,168,168,196,146,128,33,246,236,236,236,50,50,50,33,15,2,246,246,246,10,10,10,241,206,206,206,20,20,206,206,196,199,222,231,237,247,0,246,246,252,131,129,1,230,206,129,5,10,48,90,90,90,50,130,4,10,90,90,90,10,133,0,249,130,0,249,135,128,2,0,12,0,66,0,0,0,70,0,1,0,38,44,44,196,196,30,23,24,24,24,162,162,162,193,226,6,43,43,43,213,213,213,20,92,92,92,232,232,92,92,105,102,83,70,60,39,43,55,52,40,131,128,1,156,156,130,1,219,196,129,6,196,178,168,168,168,181,196,129,4,196,168,168,168,196,146,1,174,174,130,33,246,236,236,236,50,50,50,33,15,2,246,246,246,10,10,10,241,206,206,206,20,20,206,206,196,199,222,231,237,247,0,246,246,252,131,128,1,74,74,130,1,230,206,129,5,10,48,90,90,90,50,130,4,10,90,90,90,10,133,0,249,130,0,249,135,0,0,2,0,12,0,37,32,0,0,43,32,1,12,11,1,1,2,3,1,2,4,2,3,1,2,3,11,11,22,24,152,155,186,232,0,100,100,0,162,131,0,7,129,4,164,0,43,92,0,13,12,0,3,2,2,3,1,1,1,1,3,3,3,2,128,11,236,50,65,40,31,20,20,20,232,206,24,50,128,11,18,0,40,40,40,29,18,10,86,243,210,18,0,2,0,12,0,48,32,0,0,51,32,1,16,15,0,1,1,1,2,2,2,1,1,1,4,2,3,1,2,3,15,20,22,22,24,24,162,152,156,180,196,232,20,100,100,0,162,131,0,100,129,0,7,130,4,164,0,43,92,0,16,15,0,1,1,1,2,2,2,3,1,1,1,1,2,4,2,3,15,251,234,214,216,0,30,45,25,22,20,20,20,251,206,251,30,129,13,9,18,182,0,40,40,40,29,18,10,86,243,210,18,0,0,2,0,12,0,39,32,0,0,49,32,1,14,13,0,4,2,1,3,1,2,2,1,2,3,2,4,2,7,254,0,254,243,232,243,24,177,129,3,51,90,221,182,135,5,42,214,148,0,108,0,18,17,0,1,3,1,1,1,3,1,2,2,2,2,1,1,2,2,1,3,17,5,249,236,249,5,14,20,14,236,50,40,0,15,225,186,225,15,100,137,7,45,211,86,86,0,170,170,0,128,2,0,12,0,98,0,0,0,77,32,1,0,128,5,7,18,24,24,24,1,129,39,11,21,24,24,24,234,192,200,0,232,225,0,212,173,164,164,164,190,232,0,33,36,6,232,232,232,237,248,0,34,94,94,94,54,0,207,162,162,162,214,131,129,5,4,5,0,249,21,15,132,3,222,210,229,254,129,29,106,110,109,70,24,10,252,231,221,226,238,222,205,216,0,7,6,0,164,164,207,0,36,75,75,75,41,0,217,164,131,25,24,1,3,2,1,1,2,1,1,3,2,1,1,1,1,3,2,2,1,1,1,3,4,2,4,3,24,250,236,214,196,196,231,236,236,215,196,20,20,196,231,68,47,0,3,11,16,20,224,190,31,66,128,5,236,199,196,206,227,246,131,7,180,180,182,216,243,0,255,255,129,3,86,0,170,40,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,23,0,0,0,21,0,1,0,11,24,72,184,232,91,252,4,165,216,216,40,40,131,132,1,100,100,129,1,154,154,132,4,236,236,20,20,186,129,0,70,135,132,65,255,46,255,46,129,1,64,64,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,18,0,0,0,21,32,1,8,7,1,2,4,4,2,1,3,1,7,216,40,24,232,94,94,162,162,1,206,50,129,3,152,0,94,0,6,5,7,4,2,1,3,1,5,236,20,196,196,60,60,129,3,81,0,175,0,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,14,0,0,0,14,0,1,6,5,1,2,2,2,2,2,5,24,232,24,232,4,252,128,4,102,154,0,205,51,5,236,20,236,20,236,20,128,4,172,84,0,42,214,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,32,0,0,0,32,0,1,0,13,206,24,90,24,190,216,24,24,232,232,24,24,232,232,131,4,240,170,0,102,20,129,3,170,170,0,102,129,0,102,131,13,70,236,186,236,70,20,236,236,20,20,236,236,20,20,131,4,78,78,0,192,192,129,3,78,78,0,192,129,0,192,131,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,0,2,0,12,0,28,32,0,0,34,32,1,8,7,2,4,3,4,2,2,2,2,7,24,170,86,232,201,55,55,201,128,6,211,0,49,248,0,248,0,10,9,2,2,1,3,1,2,4,2,2,2,9,236,56,56,200,200,20,38,218,238,18,9,216,0,216,41,216,0,252,0,252,0,128,2,0,12,0,64,0,0,0,70,0,1,0,129,10,18,27,24,24,24,0,232,232,232,229,238,130,11,47,94,94,94,0,162,162,162,209,0,24,24,131,1,232,232,131,4,178,150,168,191,223,132,18,223,190,166,147,178,158,165,213,0,94,94,94,0,214,166,158,0,158,158,129,1,158,158,132,33,216,216,232,240,236,236,236,0,20,20,20,16,23,40,40,216,186,196,196,196,0,60,60,60,70,40,236,236,40,40,216,216,20,20,131,5,68,88,107,87,40,20,130,19,20,41,88,108,88,68,68,61,6,216,175,175,175,216,6,60,68,0,68,68,129,1,68,68,132,0,128,2,0,12,0,28,0,0,0,31,0,1,0,15,92,70,182,160,19,250,2,233,43,43,214,214,74,74,220,210,131,132,6,100,100,0,51,205,205,51,135,4,236,236,20,20,186,129,8,70,196,196,60,60,0,206,20,60,131,132,65,255,46,255,46,128,3,164,228,228,164,135,128,2,0,12,0,34,32,0,0,22,0,1,12,11,1,2,2,2,2,2,1,1,1,1,2,2,11,10,1,2,2,2,2,2,2,1,1,2,2,128,9,146,0,233,0,233,24,170,160,0,233,129,3,154,0,205,51,131,0,102,11,236,56,236,20,236,20,236,186,0,40,236,20,129,3,64,0,32,224,132,0,192,128,2,0,12,0,25,32,0,0,25,0,1,0,9,8,1,2,2,2,2,1,1,2,2,8,86,232,0,146,24,170,160,0,232,134,1,205,51,15,200,200,20,20,236,236,56,56,236,186,0,40,236,236,20,20,131,139,3,224,32,32,224,131,0,128,2,0,12,0,27,32,0,0,17,0,1,10,9,1,2,2,2,1,1,1,1,2,2,9,8,1,2,2,2,2,1,1,2,2,8,54,200,0,232,24,170,160,0,232,129,0,154,132,0,102,9,219,39,236,20,236,186,0,40,236,20,129,0,57,133,0,199,128,2,0,12,0,27,32,0,0,17,0,1,10,9,3,4,1,1,1,1,2,1,3,1,9,8,3,4,2,1,1,2,1,3,1,128,7,232,24,170,160,94,94,138,138,132,3,152,0,94,0,9,236,20,236,186,0,40,196,196,60,60,133,3,81,0,175,0,128,2,0,12,0,31,0,0,0,30,0,1,0,15,52,13,149,255,255,95,231,198,52,52,198,198,24,24,170,160,131,0,230,129,1,146,146,129,3,230,0,146,146,136,15,218,235,69,2,2,185,19,38,218,218,38,38,236,186,0,40,131,0,200,129,65,0,160,0,160,129,0,200,139,0,2,0,12,0,56,32,0,0,57,32,1,19,18,0,1,2,5,1,1,1,1,1,3,1,2,2,2,2,2,2,1,1,129,1,24,232,130,5,90,90,166,166,0,24,129,3,232,24,170,160,14,136,158,0,167,158,136,158,172,0,94,0,158,158,0,158,131,19,18,1,2,3,1,1,1,2,2,3,1,2,2,2,2,2,1,1,1,1,11,176,236,20,20,20,80,0,196,60,60,0,236,129,4,20,236,186,0,40,13,78,50,0,50,75,78,68,0,175,0,68,68,0,68,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,67,0,0,0,49,0,1,0,20,216,216,235,24,64,90,90,232,232,231,227,221,24,24,170,170,86,86,86,94,106,64,0,132,5,30,242,236,232,232,232,131,5,40,188,188,171,167,203,129,3,224,227,6,40,132,2,139,135,130,64,255,120,1,238,195,67,255,114,255,111,255,109,255,119,132,129,25,242,222,209,202,202,20,20,18,12,5,236,236,56,56,200,200,200,200,200,230,50,31,19,20,20,20,131,128,4,80,80,66,44,16,138,9,207,204,222,227,236,236,208,225,200,207,132,0,128,2,0,12,0,68,0,0,0,67,32,1,0,128,36,11,24,24,24,12,0,23,57,68,57,57,57,0,213,166,166,166,0,29,57,57,57,17,82,73,36,62,65,57,195,195,232,232,57,57,195,195,131,135,12,238,246,246,0,88,88,88,42,0,168,168,168,212,129,2,20,20,35,129,0,120,129,1,141,148,136,20,19,0,4,2,3,2,2,3,2,1,2,1,2,3,1,3,1,1,1,2,1,19,196,236,186,191,206,35,70,35,4,206,206,196,206,206,20,20,20,206,20,20,131,4,216,166,0,90,90,64,0,160,0,80,129,3,80,60,60,0,64,0,160,128,0,90,0,2,0,12,0,85,32,0,0,77,32,1,29,28,0,3,2,1,1,1,3,1,1,3,4,1,1,2,1,2,1,2,1,2,3,3,3,4,2,1,1,1,1,19,226,162,162,24,24,24,245,232,232,0,47,100,100,47,0,162,162,0,48,100,129,2,232,24,162,131,130,19,1,0,60,0,6,10,0,206,237,10,98,98,60,0,158,158,226,50,0,236,129,1,10,246,129,28,27,0,3,1,1,4,1,3,1,1,1,3,1,1,1,2,1,2,1,2,3,3,3,3,2,2,2,2,2,27,60,70,50,30,236,0,20,20,26,30,0,228,196,196,228,0,50,50,0,196,0,216,20,42,236,50,0,216,134,14,4,10,10,37,37,1,226,176,176,236,60,80,40,219,246,133,128,2,0,12,0,37,0,0,0,25,32,1,0,129,21,92,92,232,232,24,24,24,24,24,27,37,52,64,0,228,192,170,162,162,162,162,162,131,128,1,158,158,134,4,21,48,68,82,87,140,8,7,1,2,2,4,5,1,7,1,128,6,206,20,236,236,30,50,50,0,80,130,0,216,130,0,128,2,0,12,0,94,0,0,0,81,32,1,0,128,45,7,18,24,24,24,27,30,30,0,13,23,24,24,24,1,236,234,232,20,4,236,213,164,164,164,220,0,247,237,232,232,232,245,1,0,51,94,94,94,52,0,213,162,162,162,213,131,129,6,251,242,236,248,253,5,5,129,3,9,19,20,10,131,20,80,98,98,98,40,0,223,166,156,159,170,191,206,214,238,0,164,164,168,186,226,130,3,229,206,187,164,131,27,26,1,1,3,3,1,1,1,1,1,3,2,1,2,3,1,1,1,1,4,3,2,1,1,1,1,3,2,26,250,242,236,236,0,239,232,236,236,0,20,20,0,68,68,36,0,6,20,10,190,190,190,231,10,66,36,131,3,20,249,248,5,130,15,176,176,216,231,246,0,255,0,86,34,236,217,180,180,0,86,128,2,0,12,0,69,0,0,0,66,0,1,0,128,9,24,24,24,0,251,5,0,155,155,155,129,4,1,1,232,236,249,129,13,24,24,24,0,240,232,9,6,0,155,155,155,251,5,131,129,19,236,250,251,210,45,45,45,236,164,164,164,158,159,0,255,0,45,251,250,246,131,7,94,92,92,92,20,218,210,45,131,128,3,236,236,236,40,130,23,59,59,59,0,7,16,20,20,16,6,40,40,236,236,236,0,13,20,20,10,0,59,59,59,133,129,12,236,241,241,38,221,221,221,30,86,86,86,86,86,130,3,251,5,7,10,130,8,10,180,170,170,170,226,31,38,221,131,128,2,0,12,0,64,0,0,0,61,32,1,0,128,28,51,76,90,90,90,49,246,249,24,24,24,120,120,232,216,166,166,166,181,216,239,232,232,232,251,24,24,232,232,131,128,25,157,163,178,196,224,247,0,17,8,0,7,106,96,96,77,9,0,219,175,158,147,180,196,220,1,96,129,0,96,131,19,18,0,1,1,1,1,3,1,2,2,1,1,3,2,1,1,2,1,3,2,18,186,146,166,186,186,226,230,236,146,146,20,70,34,0,9,20,20,236,20,128,3,70,64,43,30,129,11,236,158,168,178,236,80,80,80,50,30,0,178,128,2,0,12,0,32,0,0,0,30,32,1,0,20,94,94,94,44,0,162,162,160,150,170,195,197,214,232,232,232,24,24,174,162,162,131,128,5,4,44,88,88,88,4,145,11,10,1,3,2,2,1,1,1,4,2,1,2,10,206,251,50,58,65,38,20,20,236,40,50,2,176,166,176,135,0,0,2,0,12,0,45,32,0,0,34,32,1,14,13,4,6,2,1,1,2,1,1,1,1,2,1,2,2,13,24,232,0,49,94,94,49,0,206,162,162,206,24,232,129,11,162,162,206,50,94,94,94,50,206,162,205,51,12,11,1,3,1,2,3,1,5,3,3,1,1,2,9,246,236,246,10,20,10,186,36,70,36,129,133,5,211,170,45,86,219,37,0,128,2,0,12,0,19,0,0,0,27,32,1,10,9,0,4,2,3,1,2,1,2,2,2,9,60,61,195,231,0,242,232,38,24,61,130,2,162,162,162,130,0,86,8,7,0,4,2,4,2,1,4,2,128,6,221,35,0,20,20,236,0,129,2,80,80,80,129,0,168,128,2,0,12,0,33,0,0,0,35,0,1,0,16,128,128,148,177,238,10,66,234,24,24,158,158,128,107,40,219,232,131,130,4,226,199,226,0,69,133,64,0,140,0,60,132,16,50,50,70,55,54,55,221,20,236,236,50,50,50,166,166,0,20,131,128,68,0,160,0,160,0,148,0,132,0,130,128,0,196,140,0,128,2,0,12,0,71,0,0,0,69,0,1,0,128,30,21,61,70,10,16,18,0,3,14,24,14,0,232,187,176,226,225,231,0,248,244,232,242,24,20,214,28,20,10,7,144,131,129,1,239,206,64,0,140,4,116,100,100,100,103,131,7,22,60,146,153,156,156,156,155,130,1,240,123,67,0,144,0,147,0,182,0,185,132,128,30,240,217,216,213,224,238,246,241,236,236,245,0,15,39,40,37,26,18,10,15,20,20,11,236,206,10,10,14,255,246,75,131,129,7,253,0,9,225,186,186,186,186,131,7,3,0,11,51,70,70,70,70,130,0,186,68,255,66,255,66,255,42,254,247,254,232,132,0,128,2,0,12,0,50,0,0,0,51,0,1,0,32,20,193,170,181,24,24,162,162,162,222,20,56,94,94,94,104,97,43,24,24,182,152,94,94,94,232,232,232,232,94,94,232,232,131,135,4,199,138,138,138,192,130,0,7,136,1,137,149,136,128,31,17,60,50,236,236,50,50,50,24,0,231,206,206,196,196,217,248,236,236,50,50,206,206,206,20,20,20,20,206,206,20,20,131,134,6,60,60,60,60,60,60,60,137,3,60,60,60,60,136,128,2,0,12,0,41,0,0,0,36,0,1,0,17,93,11,5,101,232,189,93,36,30,6,1,23,209,183,178,199,212,6,131,128,1,156,156,131,0,125,64,0,129,8,121,108,100,0,10,14,1,241,177,131,17,216,246,10,216,20,50,216,216,213,197,204,236,0,237,234,245,250,10,131,128,1,70,70,132,8,12,252,221,206,0,7,52,79,60,132,128,2,0,12,0,98,0,0,0,101,0,1,0,128,34,24,24,24,57,40,232,232,146,166,166,166,255,245,246,0,43,66,90,90,90,38,246,245,239,232,232,232,237,40,40,65,24,24,24,12,130,8,166,166,166,232,232,24,24,232,232,131,129,11,20,11,14,251,206,50,50,50,0,156,156,156,129,4,152,152,178,196,226,129,21,156,156,177,196,225,247,50,251,3,20,44,53,88,106,96,96,96,4,206,206,50,96,129,0,96,131,128,6,236,236,236,246,0,20,20,64,255,36,2,70,70,70,129,14,10,236,206,196,186,186,186,228,10,0,10,20,20,20,1,129,4,245,236,236,236,246,130,8,70,70,70,20,20,236,236,20,20,131,129,11,246,251,255,0,37,219,219,219,50,74,74,74,129,4,70,65,49,40,22,129,21,74,74,61,50,30,6,219,20,16,238,206,186,163,158,178,178,178,236,37,37,219,178,129,0,178,131,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,48,0,0,0,38,32,1,0,128,22,32,60,60,60,196,196,196,223,226,223,232,242,232,240,244,59,59,197,197,24,24,232,232,131,129,1,237,216,129,8,216,186,158,158,158,158,158,2,2,132,0,100,129,0,100,131,13,12,0,4,2,3,1,2,1,1,1,2,2,2,2,128,11,226,40,0,4,20,20,14,7,216,30,236,20,129,3,80,80,80,80,133,0,182,0,128,2,0,12,0,56,0,0,0,52,32,1,0,31,226,208,173,152,162,162,162,162,219,0,39,90,90,90,37,0,212,162,162,24,24,12,0,233,232,232,232,229,24,24,162,162,131,129,0,3,131,10,219,168,168,168,220,0,33,88,88,88,42,133,2,242,0,4,136,16,15,0,1,1,2,1,1,2,1,3,4,2,1,4,3,3,2,15,70,70,72,50,50,50,11,226,186,18,50,236,10,20,236,50,131,0,90,64,0,180,5,90,90,0,166,226,226,129,1,226,0,0,128,2,0,12,0,72,0,0,0,64,0,1,0,128,26,57,73,90,90,90,55,54,41,24,24,24,27,17,0,238,216,232,72,57,27,0,231,185,156,156,156,210,129,4,251,232,232,232,245,131,128,4,150,162,202,226,3,130,3,4,0,248,250,130,18,5,0,72,89,98,98,98,68,24,0,212,156,156,156,158,200,226,237,252,131,27,236,236,212,186,186,186,236,0,247,236,236,236,241,249,0,7,18,20,246,251,253,0,19,46,60,60,60,29,129,4,10,20,20,20,255,131,128,4,70,63,42,30,1,139,16,186,181,176,176,176,194,231,0,39,80,80,80,80,70,60,38,7,131,0,0,2,0,12,0,52,32,0,0,46,32,1,17,16,1,3,2,1,1,1,1,2,2,2,2,1,3,3,1,3,2,1,11,24,130,11,249,238,232,239,0,100,100,0,156,156,0,232,130,13,50,110,101,80,40,10,158,208,0,100,0,208,0,100,16,15,1,3,1,1,1,1,1,1,1,1,4,3,3,3,3,2,2,246,236,246,130,7,5,15,20,20,0,196,0,60,129,132,10,156,154,163,178,186,80,0,176,0,176,0,0,2,0,12,0,39,32,0,0,37,32,1,12,11,0,1,1,1,2,1,2,1,3,1,4,2,11,20,37,50,50,206,206,236,226,242,232,24,232,129,9,213,168,0,158,158,158,158,252,0,100,12,11,0,4,2,2,1,1,1,2,1,1,2,2,128,2,221,35,21,129,5,20,20,20,0,236,20,129,4,80,80,80,80,80,131,0,182,0,2,0,12,0,37,32,0,0,39,32,1,11,10,3,1,1,1,3,1,1,1,1,3,4,10,24,24,18,24,0,192,158,158,158,98,232,3,100,94,100,100,129,4,11,50,0,158,0,13,12,1,1,1,3,2,1,1,1,1,1,3,1,3,12,237,236,236,236,0,50,50,49,50,50,206,206,20,129,1,182,182,132,3,10,80,10,0,128,2,0,12,0,50,32,0,0,63,0,1,0,18,17,4,6,2,1,1,1,1,4,2,1,3,1,2,2,1,1,1,1,17,24,232,61,35,221,195,0,80,0,215,176,215,36,220,35,61,195,221,133,7,188,34,68,68,222,188,60,196,131,128,34,4,236,236,236,4,0,252,20,20,20,252,216,226,30,40,0,210,176,176,176,210,0,45,80,80,80,45,246,246,10,10,226,216,40,30,131,129,2,14,0,243,130,2,243,0,14,132,11,70,70,42,0,214,186,186,186,214,0,42,70,139,128,2,0,12,0,62,0,0,0,60,0,1,0,31,20,63,109,110,217,216,233,236,227,247,4,10,236,191,147,146,40,40,23,20,20,13,9,252,248,5,24,30,110,232,226,146,131,129,7,223,196,125,115,98,98,98,101,131,8,31,56,128,142,158,158,158,156,156,131,0,236,129,0,20,132,128,17,250,247,241,241,238,250,0,246,236,236,245,0,6,9,15,15,18,5,129,10,20,20,20,20,0,236,246,196,20,10,60,131,131,5,176,175,176,176,176,176,131,8,1,0,80,81,80,80,80,80,80,131,0,40,129,0,216,132,0,128,2,0,12,0,42,0,0,0,27,32,1,0,128,18,24,24,24,172,172,172,0,84,84,84,232,232,232,54,34,49,207,222,202,131,129,0,176,129,4,176,172,172,172,176,129,0,176,129,0,172,129,0,172,132,10,9,2,4,3,4,1,1,1,1,1,1,9,236,60,196,20,216,236,216,40,20,40,128,0,90,135,128,2,0,12,0,78,0,0,0,66,32,1,0,2,236,245,247,129,24,211,211,250,30,61,94,94,94,232,232,232,233,20,22,24,24,24,162,162,162,190,216,2,45,45,129,5,9,11,45,45,211,211,131,129,9,204,146,146,146,158,168,168,168,182,196,129,1,196,225,130,1,225,196,129,11,196,182,168,168,168,158,146,146,146,204,0,146,129,0,146,131,22,21,0,1,1,1,1,1,2,3,4,2,1,1,2,4,1,4,1,1,1,1,2,2,21,30,21,4,10,107,20,3,206,20,24,226,230,236,50,33,236,149,246,252,235,236,20,129,5,9,20,62,216,90,42,132,5,42,90,216,62,20,9,129,0,40,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,50,0,0,0,55,0,1,0,24,128,128,148,177,238,10,66,234,24,24,158,158,128,94,94,94,95,94,40,219,248,238,232,232,232,131,130,4,226,199,226,0,69,133,3,226,214,213,222,64,0,140,4,60,167,171,180,196,132,24,50,50,70,55,54,55,221,20,236,236,50,50,50,206,206,206,205,206,226,40,20,18,20,20,20,131,128,68,0,160,0,160,0,148,0,132,0,130,128,0,196,133,9,226,226,226,226,226,226,226,224,226,226,132,0,2,0,12,0,33,32,0,0,39,32,1,10,9,3,4,2,1,5,3,3,1,3,1,9,24,232,22,50,233,206,98,98,158,158,129,7,51,22,206,22,162,0,94,0,12,11,3,4,2,1,1,4,2,1,2,2,2,2,11,236,20,7,18,18,245,234,234,0,206,0,46,129,9,216,237,0,40,0,237,66,0,190,0,128,2,0,12,0,17,0,0,0,17,0,1,8,7,1,2,2,2,2,2,2,2,7,61,195,24,61,195,232,24,61,129,2,158,0,158,129,0,110,7,221,35,236,221,35,20,236,221,129,2,58,0,58,129,0,196,128,2,0,12,0,58,0,0,0,43,32,1,0,19,24,24,58,94,94,94,39,0,231,220,200,24,35,247,0,234,232,232,232,135,65,255,58,255,58,3,24,24,232,232,131,128,11,163,181,220,246,34,94,94,94,116,120,40,24,130,4,240,246,200,146,138,129,1,158,158,132,13,12,0,1,3,3,2,1,1,3,3,2,1,3,2,12,236,236,196,0,240,236,216,0,20,64,110,236,20,128,5,68,236,175,175,176,226,129,3,60,78,68,0,128,2,0,12,0,92,0,0,0,87,0,1,0,128,44,7,24,24,11,9,4,0,46,98,98,98,68,23,0,249,3,186,210,232,232,232,245,249,3,10,56,98,98,98,57,20,244,230,210,24,22,2,10,250,232,232,232,181,136,136,131,131,32,152,155,162,162,162,190,216,233,9,31,31,31,245,242,240,226,236,245,0,31,245,246,10,38,50,72,94,94,94,99,95,25,13,130,5,255,0,245,238,236,40,131,128,12,250,239,236,236,240,249,0,230,200,200,200,213,238,130,5,236,253,20,20,20,10,129,20,237,212,200,200,200,243,21,16,248,236,236,240,250,0,10,20,20,20,254,236,236,131,131,15,81,81,81,81,81,43,10,244,212,196,196,196,60,216,229,247,130,13,196,60,56,39,15,0,218,175,175,175,190,205,30,15,132,2,248,239,236,132,128,2,0,12,0,32,0,0,0,32,0,1,0,15,24,0,142,166,24,220,32,32,176,176,232,232,32,32,176,176,131,0,9,129,8,9,9,177,177,9,9,177,177,9,135,15,236,206,25,55,236,0,199,199,17,17,20,20,199,199,17,17,131,0,217,129,8,217,217,39,39,217,217,39,39,217,135,0,128,2,0,12,0,59,32,0,0,73,0,1,0,19,18,3,2,3,2,3,2,1,1,1,1,1,3,4,1,1,1,1,1,2,15,25,159,46,97,70,0,196,214,248,10,254,231,28,25,161,175,129,0,231,128,9,212,162,0,60,0,146,193,226,226,226,131,3,206,0,98,0,31,236,236,236,236,56,56,22,246,218,200,200,200,235,20,42,60,100,70,53,40,26,18,20,20,20,3,240,236,236,46,46,60,129,1,20,20,131,129,15,21,40,40,60,81,81,81,50,10,216,171,171,171,181,20,1,130,6,252,255,10,15,10,0,181,130,1,181,188,129,0,188,131,0,128,2,0,12,0,61,0,0,0,55,32,1,0,35,152,24,24,24,0,232,221,152,152,0,11,24,24,152,152,142,145,163,176,203,232,232,232,244,0,50,104,104,104,50,0,206,152,152,152,204,131,129,5,10,5,1,0,100,96,143,11,162,162,228,0,45,94,94,94,45,0,226,162,131,19,18,0,1,1,3,1,1,1,1,1,2,2,1,3,3,3,3,3,2,1,18,50,236,236,20,20,50,50,246,242,236,50,60,20,20,246,206,0,50,50,129,3,216,0,181,184,134,5,242,81,242,175,221,6,0,128,2,0,12,0,25,0,0,0,24,0,1,0,11,125,101,232,0,24,24,164,164,24,24,232,56,131,131,0,60,129,1,60,102,129,0,102,131,128,9,196,20,60,236,236,50,50,236,236,20,132,131,0,196,129,1,196,192,129,0,192,131,0,2,0,12,0,93,32,0,0,48,32,1,30,29,0,3,3,3,4,1,1,3,1,2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,2,2,4,2,128,10,24,0,232,47,98,98,0,210,158,158,210,130,14,46,98,98,98,46,0,209,158,158,158,209,11,24,244,232,128,28,236,8,236,162,200,236,51,51,236,200,162,20,236,205,205,242,20,55,94,94,94,55,20,242,205,248,20,0,20,16,15,4,6,3,1,1,4,2,1,6,3,4,2,4,3,3,3,15,236,20,229,200,200,27,56,56,0,200,27,56,246,236,9,20,129,9,81,56,35,221,35,56,35,241,175,241,131,0,128,2,0,12,0,64,0,0,0,67,32,1,0,3,24,35,104,104,64,0,151,2,232,232,232,129,25,50,106,106,106,52,0,210,158,158,158,208,80,53,24,24,24,11,0,245,232,232,104,104,114,111,93,131,128,19,156,160,0,203,0,206,230,255,162,162,211,0,30,94,94,94,29,0,211,162,146,21,20,0,1,1,1,1,1,4,1,1,1,2,1,1,2,3,3,2,1,3,2,1,20,236,236,206,206,253,20,0,232,208,208,236,10,33,56,236,236,251,10,20,206,196,20,242,61,58,242,189,242,67,67,21,236,161,161,161,0,242,0,242,242,242,242,242,0,2,0,12,0,32,32,0,0,29,32,1,10,9,3,4,1,1,1,1,2,1,3,1,9,24,232,0,30,34,4,98,98,158,158,130,6,226,41,71,162,0,94,0,10,9,3,4,1,1,1,1,1,2,2,2,1,236,20,132,2,206,0,46,130,6,20,0,236,66,0,190,0,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,25,0,0,0,21,32,1,14,13,1,3,2,1,3,1,1,1,2,2,1,1,2,2,13,11,24,0,246,232,246,0,28,61,28,0,229,195,229,133,7,195,195,0,61,61,61,0,195,6,5,4,6,3,2,2,4,5,236,20,234,206,234,50,129,3,60,0,196,0,128,2,0,12,0,18,0,0,0,18,0,1,8,7,1,2,2,2,2,2,2,2,7,31,225,24,31,225,232,24,31,7,2,2,207,2,207,2,2,67,7,226,30,236,226,30,20,236,226,7,2,2,81,2,81,2,2,193,128,2,0,12,0,48,0,0,0,49,32,1,0,11,24,24,49,73,73,73,37,15,249,24,20,8,129,9,232,232,232,204,176,176,24,24,232,232,131,128,7,206,237,26,53,68,68,68,64,132,4,10,0,228,202,206,129,1,206,206,132,15,14,0,1,3,2,1,1,1,1,2,3,1,1,1,3,2,14,236,236,196,236,237,236,236,243,20,20,20,59,90,236,20,128,13,80,0,196,196,206,10,6,0,20,42,91,110,80,0,128,2,0,12,0,81,0,0,0,75,32,1,0,128,11,7,19,24,11,9,4,0,25,54,54,54,25,130,5,216,223,232,232,232,244,129,17,28,54,54,54,20,17,16,24,18,7,0,245,232,232,232,218,206,206,131,131,26,197,197,197,197,197,217,236,252,13,13,13,216,242,242,239,236,246,0,13,243,248,21,40,58,58,58,58,132,5,246,236,234,229,229,254,131,25,24,0,3,1,3,3,3,2,1,1,1,1,2,1,1,3,2,2,1,1,1,4,1,1,1,1,128,21,236,236,0,196,0,216,0,9,20,20,9,216,216,196,0,236,236,240,251,20,20,9,129,129,14,30,30,10,236,0,236,227,236,236,0,236,20,246,226,226,131,3,253,246,246,0,0,128,2,0,12,0,25,32,0,0,32,0,1,0,8,7,1,2,2,2,2,2,2,2,7,24,211,24,31,225,232,31,225,129,2,206,0,206,130,15,236,216,0,25,236,0,226,226,20,20,20,20,226,226,20,20,131,0,246,129,8,246,246,40,40,246,246,40,40,246,135,128,2,0,12,0,61,0,0,0,48,32,1,0,128,31,12,24,24,185,185,0,31,66,66,66,42,20,226,186,186,199,229,246,240,232,232,232,245,24,24,186,186,186,216,226,232,232,131,132,11,204,204,204,224,241,7,30,30,30,0,216,244,130,2,248,241,248,133,0,50,129,0,50,131,16,15,1,2,2,1,1,3,2,2,1,3,4,3,2,1,2,2,7,247,236,30,0,241,226,10,30,129,5,20,236,30,30,0,20,129,5,30,30,30,249,236,226,132,2,226,0,206,128,2,0,12,0,53,0,0,0,61,32,1,0,33,200,24,24,24,1,232,229,211,195,195,246,6,24,24,200,195,191,192,194,196,214,232,232,232,239,0,56,56,56,0,226,195,195,195,131,133,2,49,47,25,143,8,218,218,0,36,36,36,17,0,218,131,20,19,0,1,1,2,1,1,3,2,1,1,1,1,1,3,4,2,2,2,1,3,128,18,236,236,255,20,20,40,246,236,236,0,40,60,50,20,0,216,0,18,40,128,4,20,20,1,0,206,129,1,11,20,132,4,30,0,226,226,30,0,128,2,0,12,0,21,0,0,0,20,0,1,0,11,46,53,232,226,24,24,214,214,24,24,232,232,131,135,0,49,129,0,49,131,10,246,216,20,50,236,236,40,40,236,236,20,132,135,0,195,129,0,195,131,0,2,0,12,0,52,32,0,0,58,32,1,16,15,1,2,7,3,1,3,2,2,5,1,3,1,2,3,3,3,15,11,24,232,56,56,229,200,0,56,56,200,200,0,24,0,232,15,255,245,250,219,242,2,242,245,232,0,35,0,245,250,255,250,18,17,1,3,1,2,3,1,2,4,2,2,7,4,2,3,1,2,3,1,17,246,236,246,10,20,10,216,19,40,0,226,30,246,236,246,10,20,10,17,255,255,255,255,255,255,39,255,19,255,215,255,255,255,255,255,255,255,128,2,0,12,0,53,32,0,0,63,0,1,0,19,18,0,1,3,1,2,1,2,4,2,1,2,1,1,1,1,2,3,2,3,18,24,27,61,56,232,232,60,24,10,249,232,56,61,65,64,0,61,0,200,1,251,202,130,0,254,136,3,220,0,38,220,33,236,236,225,216,216,0,20,20,20,1,206,220,236,236,236,247,0,9,20,20,0,216,196,197,202,0,237,216,216,216,0,40,40,40,131,3,251,45,43,23,129,3,236,236,243,250,135,1,246,236,132,8,30,30,15,0,226,226,226,0,30,131,0,128,2,0,12,0,12,0,0,0,11,0,1,0,128,2,38,0,218,131,128,2,196,0,54,131,2,60,0,196,132,3,236,20,20,236,131,128,2,0,12,0,88,0,0,0,85,32,1,0,128,30,38,0,218,31,31,225,225,24,24,31,31,225,225,232,232,24,24,31,31,24,24,49,73,73,73,37,15,249,24,20,8,129,9,232,232,232,204,176,176,24,24,232,232,131,128,27,196,0,54,2,2,2,2,2,207,207,2,2,207,207,2,67,2,2,67,0,206,237,26,53,68,68,68,64,132,4,10,0,228,202,206,129,1,206,206,132,27,26,0,1,1,1,2,2,2,2,2,2,2,2,1,1,3,2,1,1,1,1,2,3,1,1,1,3,2,26,20,236,236,20,226,30,236,226,30,20,236,226,236,236,196,236,237,236,236,243,20,20,20,59,90,236,20,26,236,0,20,0,2,2,81,2,81,2,2,193,0,80,0,196,196,206,10,6,0,20,42,91,110,80,0,0,2,0,12,0,63,32,0,0,73,32,1,20,19,0,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,128,18,38,0,218,24,211,24,31,225,232,31,225,31,225,24,31,225,232,24,31,128,2,196,0,54,129,2,206,0,206,130,7,2,2,207,2,207,2,2,67,23,22,0,1,1,1,1,1,1,1,1,1,2,1,2,3,2,2,2,2,2,2,2,2,2,22,20,236,236,20,236,216,0,25,236,0,226,20,20,226,20,226,30,236,226,30,20,236,226,4,246,10,30,10,246,129,5,246,246,40,246,246,40,129,7,2,2,81,2,81,2,2,193,128,2,0,12,0,114,0,0,0,114,0,1,0,128,31,38,0,218,24,24,211,211,24,24,31,31,225,225,232,232,31,31,225,225,0,7,19,24,11,9,4,0,25,54,54,54,25,130,5,216,223,232,232,232,244,129,17,28,54,54,54,20,17,16,24,18,7,0,245,232,232,232,218,206,206,131,128,2,196,0,54,132,1,206,206,129,1,206,206,136,26,197,197,197,197,197,217,236,252,13,13,13,216,242,242,239,236,246,0,13,243,248,21,40,58,58,58,58,132,5,246,236,234,229,229,254,131,59,20,236,236,20,236,216,0,25,236,0,226,226,20,20,20,20,226,226,20,20,0,250,240,236,236,240,250,0,227,196,196,196,227,0,216,216,0,9,20,20,20,9,216,216,205,196,196,196,0,245,236,236,240,251,0,10,20,20,20,9,133,4,226,246,10,246,246,129,8,246,246,40,40,246,246,40,40,246,135,26,30,30,30,30,30,20,10,252,236,236,236,0,236,227,236,236,246,0,236,20,17,1,246,226,226,226,226,134,2,253,246,246,132,0,0,2,0,12,0,88,32,0,0,94,32,1,28,27,0,1,1,1,2,2,2,2,2,2,2,2,2,2,7,3,1,3,2,2,5,1,3,1,2,3,3,3,128,26,38,0,218,31,225,24,31,225,232,24,31,11,24,232,56,56,229,200,0,56,56,200,200,0,24,0,232,128,26,196,0,54,2,2,207,2,207,2,2,67,255,245,250,219,242,2,242,245,232,0,35,0,245,250,255,250,30,29,0,1,1,1,2,2,2,2,2,2,2,2,2,3,1,2,3,1,2,4,2,2,7,4,2,3,1,2,3,1,29,20,236,236,20,226,30,236,226,30,20,236,226,246,236,246,10,20,10,216,19,40,0,226,30,246,236,246,10,20,10,29,236,0,20,0,2,2,81,2,81,2,2,193,255,255,255,255,255,255,39,255,19,255,215,255,255,255,255,255,255,255,0,2,0,12,0,154,32,0,0,143,32,1,51,50,0,1,1,1,1,3,1,2,1,1,2,2,1,2,1,3,2,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,2,2,7,3,1,3,2,2,5,1,3,1,2,3,3,3,128,10,38,0,218,0,24,11,4,0,25,54,25,129,2,216,232,244,129,31,28,54,54,20,17,16,24,18,7,0,245,232,232,218,206,206,11,24,232,56,56,229,200,0,56,56,200,200,0,24,0,232,128,2,196,0,54,129,18,197,197,197,197,236,13,13,216,242,236,0,13,243,248,21,40,58,58,58,132,20,236,234,229,229,254,255,245,250,219,242,2,242,245,232,0,35,0,245,250,255,250,47,46,0,1,1,1,1,3,1,3,3,3,2,1,1,1,1,2,1,1,3,2,2,1,1,1,4,1,1,1,1,2,3,1,2,3,1,2,4,2,2,7,4,2,3,1,2,3,1,26,20,236,236,20,0,236,236,0,196,0,216,0,9,20,20,9,216,216,196,0,236,236,240,251,20,20,9,129,17,246,236,246,10,20,10,216,19,40,0,226,30,246,236,246,10,20,10,3,246,10,30,10,129,14,30,30,10,236,0,236,227,236,236,0,236,20,246,226,226,131,21,253,246,246,0,255,255,255,255,255,255,39,255,19,255,215,255,255,255,255,255,255,255,0,0,2,0,12,0,125,32,0,0,115,32,1,41,40,0,1,1,1,4,2,1,1,2,1,2,1,1,1,1,1,1,1,2,2,2,3,1,1,2,2,2,7,3,1,3,2,2,5,1,3,1,2,3,3,3,128,39,38,0,218,24,185,0,31,66,66,20,226,186,186,199,229,246,240,232,245,24,186,216,226,232,11,24,232,56,56,229,200,0,56,56,200,200,0,24,0,232,128,13,196,0,54,0,204,204,204,241,7,30,30,0,216,244,130,0,241,130,18,50,0,50,255,245,250,219,242,2,242,245,232,0,35,0,245,250,255,250,38,37,0,1,1,1,2,2,2,1,1,3,2,2,1,3,4,3,2,1,2,2,2,3,1,2,3,1,2,4,2,2,7,4,2,3,1,2,3,1,11,20,236,236,20,247,236,30,0,241,226,10,30,129,23,20,236,30,30,0,20,246,236,246,10,20,10,216,19,40,0,226,30,246,236,246,10,20,10,3,246,10,30,10,129,5,30,30,30,249,236,226,132,20,226,0,206,255,255,255,255,255,255,39,255,19,255,215,255,255,255,255,255,255,255,0,2,0,12,0,83,32,0,0,91,32,1,28,27,0,1,1,1,1,1,1,1,2,2,2,2,2,2,7,3,1,3,2,2,5,1,3,1,2,3,3,3,128,26,38,0,218,46,53,232,226,24,214,24,232,11,24,232,56,56,229,200,0,56,56,200,200,0,24,0,232,128,2,196,0,54,134,16,49,255,245,250,219,242,2,242,245,232,0,35,0,245,250,255,250,31,30,0,1,1,1,1,1,1,1,2,2,2,1,1,2,3,1,2,3,1,2,4,2,2,7,4,2,3,1,2,3,1,30,20,236,236,20,246,216,20,50,236,40,236,20,0,246,236,246,10,20,10,216,19,40,0,226,30,246,236,246,10,20,10,3,246,10,30,10,135,18,195,255,255,255,255,255,255,39,255,19,255,215,255,255,255,255,255,255,255,0,2,0,12,0,22,32,0,0,21,32,1,6,5,1,3,2,1,1,3,5,20,48,0,235,208,235,128,4,186,159,159,186,0,6,5,0,1,3,1,1,4,128,4,238,215,238,0,41,129,3,58,82,82,24,0,128,2,0,12,0,7,0,0,0,7,0,1,0,3,60,60,181,216,131,135,3,216,216,40,40,131,135,0,128,2,0,12,0,40,32,0,0,50,0,1,0,12,11,1,3,2,1,1,3,2,3,2,1,1,3,11,20,48,0,235,208,235,20,48,0,235,208,235,1,97,27,129,7,27,97,0,186,159,159,186,0,128,22,231,196,196,196,231,0,24,60,60,60,24,0,231,196,196,196,231,0,24,60,60,60,24,131,4,136,136,171,196,220,130,3,220,196,171,136,129,8,35,60,84,120,120,120,84,60,35,132,0,128,2,0,12,0,29,32,0,0,31,0,1,0,9,8,1,3,2,1,1,3,2,1,1,8,20,48,0,235,208,235,60,181,216,1,97,27,129,1,27,97,130,128,14,231,196,196,196,231,0,24,60,60,60,24,216,216,40,40,131,4,136,136,171,196,220,130,3,220,196,171,136,135,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,0,2,0,12,0,34,32,0,0,34,32,1,10,9,0,1,1,1,2,3,2,1,1,3,9,55,59,197,201,20,48,0,235,208,235,0,156,129,6,156,0,186,159,159,186,0,10,9,0,1,1,1,1,1,3,1,1,4,9,216,196,60,40,0,238,215,238,0,41,0,120,129,0,120,129,3,58,82,82,24,128,2,0,12,0,33,32,0,0,34,0,1,0,10,9,0,1,1,1,1,1,3,1,2,2,9,59,55,201,197,0,235,208,235,20,48,128,1,100,100,130,3,69,97,97,49,15,196,216,40,60,0,17,41,41,41,17,0,238,215,215,215,238,131,128,1,136,136,130,8,231,215,197,174,174,174,197,215,231,132,128,2,0,12,0,87,0,0,0,85,32,1,0,9,53,53,53,58,73,93,104,104,104,49,129,13,245,232,232,232,229,213,204,203,203,203,201,24,65,22,129,13,245,240,0,20,48,48,48,20,0,235,208,208,208,235,131,10,156,176,169,161,176,197,224,246,43,100,100,129,11,251,246,239,235,216,207,192,176,156,120,40,36,129,2,100,100,122,129,8,227,207,186,159,159,159,186,207,227,132,27,26,0,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1,2,1,3,1,3,1,3,1,1,4,26,216,216,216,235,0,224,196,196,236,0,20,20,11,0,18,40,40,236,226,0,236,0,238,215,238,0,41,8,40,25,30,23,40,22,247,226,181,129,9,244,223,216,228,244,241,181,236,0,181,129,3,58,82,82,24,0,128,2,0,12,0,84,0,0,0,83,0,1,0,128,19,11,24,24,24,27,43,51,53,53,53,203,203,203,197,183,163,152,152,152,206,130,17,11,16,55,232,191,234,0,235,208,208,208,235,0,20,48,48,48,20,131,129,26,4,10,17,21,40,49,63,80,100,100,80,88,95,80,60,33,10,214,156,156,0,156,156,134,136,216,221,130,8,28,49,69,97,97,97,69,49,28,132,128,40,246,236,236,236,246,0,238,216,216,216,40,40,40,21,0,32,60,60,60,38,20,0,20,20,20,20,30,26,10,0,17,41,41,41,17,0,238,215,215,215,238,131,131,24,12,33,40,28,11,15,216,216,231,227,232,216,234,9,30,51,75,75,0,75,75,75,75,20,11,130,8,231,215,197,174,174,174,197,215,231,132,128,2,0,12,0,2,0,0,0,4,0,1,0,132,132,132,0,216,131,0,0,2,0,12,0,24,32,0,0,28,32,1,4,3,1,4,4,4,0,39,66,0,140,255,217,255,116,67,0,140,255,217,255,116,0,39,8,7,0,2,2,2,3,1,2,2,128,6,211,194,211,17,46,62,46,7,194,210,0,46,62,46,0,210,128,2,0,12,0,42,0,0,0,42,0,1,0,19,20,27,229,183,236,73,27,229,15,18,227,241,38,63,193,218,241,15,29,238,131,11,23,27,229,192,23,192,229,27,36,44,181,220,131,3,36,220,181,44,131,19,192,212,36,10,64,246,212,36,247,242,3,12,216,216,40,50,12,247,253,14,131,11,219,231,19,253,219,253,25,237,218,202,23,48,131,3,208,38,23,202,131,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,17,0,0,0,17,0,1,8,7,1,2,2,2,2,2,2,2,7,50,216,24,232,40,206,24,232,129,1,234,60,129,1,196,22,7,206,30,236,20,226,50,236,20,129,1,34,196,129,1,60,222,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,6,0,0,0,6,0,1,0,135,128,1,170,170,132,135,128,1,88,88,132,0,128,2,0,12,0,7,0,0,0,7,0,1,0,3,24,90,232,166,131,135,3,236,201,20,55,131,135,0,128,2,0,12,0,7,0,0,0,7,0,1,0,3,90,24,166,232,131,135,3,201,236,55,20,131,135,0,128,2,0,12,0,32,0,0,0,26,32,1,0,17,232,254,24,24,24,254,232,232,242,232,198,162,162,162,198,232,242,232,131,135,8,90,90,90,43,0,213,166,166,166,132,8,7,0,4,2,2,1,3,3,1,128,6,236,0,20,0,60,0,20,130,4,171,171,0,85,85,0,128,2,0,12,0,31,32,0,0,32,0,1,0,10,9,0,1,1,3,3,1,1,1,4,2,9,24,14,24,94,24,14,24,24,232,24,128,4,166,166,0,90,90,131,17,235,235,255,227,195,195,195,227,255,235,235,255,8,19,19,19,8,255,131,128,8,85,85,85,40,0,216,171,171,171,139,128,2,0,12,0,80,0,0,0,85,32,1,0,135,6,38,56,24,24,47,47,24,135,31,247,237,232,242,246,253,0,195,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,195,0,253,247,243,232,237,247,131,134,8,5,10,13,13,243,243,245,248,253,137,5,88,88,90,90,90,43,131,5,250,243,243,13,13,6,131,5,214,166,166,166,167,168,134,30,29,0,3,3,1,1,1,2,1,1,1,1,1,3,3,1,2,1,3,3,1,2,3,1,3,1,2,3,3,1,2,131,5,31,29,236,18,36,21,131,15,6,20,20,50,64,64,64,64,64,64,64,64,50,20,20,6,129,9,200,192,193,200,56,56,55,54,54,56,131,11,171,171,171,194,0,5,251,0,24,85,85,85,129,0,2,0,12,0,87,32,0,0,88,32,1,29,28,0,2,1,1,1,2,1,1,1,3,3,1,3,3,2,1,2,1,1,1,2,6,2,1,1,2,1,1,2,28,254,18,22,11,8,254,59,122,122,122,122,122,122,122,59,254,9,12,22,18,254,254,230,207,206,230,199,216,254,130,4,168,167,166,166,214,129,1,13,243,129,3,90,90,88,88,131,6,248,245,243,13,13,10,0,30,29,0,3,1,3,1,2,2,1,3,1,3,2,1,2,1,3,1,3,3,3,1,1,1,1,2,1,1,1,1,3,128,15,236,236,206,200,192,192,192,192,192,192,192,192,200,206,236,236,131,5,235,220,237,20,227,225,130,129,13,85,85,85,85,24,0,251,5,0,194,171,171,171,171,130,10,56,54,54,55,56,200,200,193,192,200,0,0,128,2,0,12,0,13,0,0,0,13,0,1,6,5,1,2,2,2,2,2,5,24,170,170,232,170,232,129,0,154,129,0,102,5,236,56,56,20,56,20,129,0,74,129,0,182,128,2,0,12,0,13,0,0,0,13,0,1,6,5,1,2,2,2,2,2,5,98,232,24,98,24,98,129,0,154,129,0,102,5,212,20,236,212,236,212,129,0,74,129,0,182,128,2,0,12,0,11,0,0,0,11,0,1,0,7,85,24,24,85,232,171,171,232,131,139,7,136,236,236,136,40,120,120,40,131,139,0,128,2,0,12,0,11,0,0,0,11,0,1,0,7,26,87,87,26,173,234,234,173,131,139,7,208,128,128,208,112,12,12,112,131,139,0,128,2,0,12,0,11,0,0,0,11,0,1,0,7,90,24,24,90,232,166,166,232,131,139,7,160,220,220,160,4,64,64,4,131,139,0,128,2,0,12,0,11,0,0,0,11,0,1,0,7,24,90,90,24,166,232,232,166,131,139,7,252,192,192,252,96,36,36,96,131,139,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,7,0,0,0,7,0,1,0,135,3,48,208,208,48,131,135,3,217,39,39,217,131,0,128,2,0,12,0,7,0,0,0,7,0,1,0,135,3,48,208,208,48,131,135,3,217,39,39,217,131,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,7,0,0,0,7,0,1,0,135,0,88,129,0,88,131,135,0,178,129,0,178,131,0,128,2,0,12,0,2,0,0,0,5,0,1,0,133,133,133,128,0,206,131,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,9,0,0,0,7,0,1,0,128,1,50,216,64,255,116,131,135,3,136,186,0,236,131,135,0,128,2,0,12,0,10,0,0,0,7,0,1,0,0,40,64,0,140,128,0,206,131,135,3,226,246,90,40,131,135,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,35,0,0,0,35,0,1,0,0,232,129,7,232,232,172,172,232,0,24,24,129,1,196,196,132,128,3,35,221,0,115,129,5,141,0,35,221,0,115,129,0,141,131,10,20,246,246,20,20,100,100,20,0,246,246,129,1,90,90,132,128,14,236,20,0,186,10,246,70,0,236,20,0,186,10,246,70,131,0,128,2,0,12,0,33,0,0,0,36,0,1,0,129,1,60,60,129,7,232,232,24,24,84,84,24,24,133,128,0,141,129,5,115,0,221,35,0,141,129,3,115,0,221,35,131,15,10,10,176,176,10,10,20,20,246,246,166,166,246,246,20,20,131,128,14,70,246,10,186,0,20,236,0,70,246,10,186,0,20,236,131,128,2,0,12,0,20,0,0,0,20,0,1,0,7,212,4,4,212,212,156,156,212,131,128,3,40,216,0,110,129,0,146,131,7,20,236,236,20,20,120,120,20,131,128,6,236,20,0,196,10,246,60,131,0,128,2,0,12,0,20,0,0,0,20,0,1,0,7,44,44,100,100,44,44,252,252,131,128,0,146,129,3,110,0,216,40,131,7,236,236,136,136,236,236,20,20,131,128,6,60,246,10,196,0,20,236,131,0,128,2,0,12,0,5,0,0,0,5,0,1,0,1,20,236,131,133,1,216,40,131,133,0,128,2,0,12,0,7,0,0,0,7,0,1,0,3,51,66,190,205,131,135,3,226,206,50,30,131,135,0,128,2,0,12,0,11,0,0,0,11,0,1,0,139,7,48,208,208,48,48,208,208,48,131,139,7,222,34,34,222,222,34,34,222,131,0,128,2,0,12,0,15,0,0,0,15,0,1,0,143,11,48,208,208,48,48,208,208,48,48,208,208,48,131,143,11,222,34,34,222,222,34,34,222,222,34,34,222,131,0,128,2,0,12,0,47,0,0,0,44,0,1,0,129,2,41,91,123,67,0,149,0,164,0,164,0,150,2,124,91,40,133,65,0,144,0,144,131,128,18,131,176,246,41,73,81,179,186,221,17,84,125,0,206,50,51,209,209,51,131,129,0,172,71,255,75,255,40,255,57,255,86,255,86,255,57,255,41,255,77,0,174,139,128,11,100,46,242,217,216,224,34,41,43,18,213,156,130,3,224,34,34,224,131,128,2,0,12,0,13,0,0,0,13,0,1,0,131,3,55,55,201,201,131,3,48,208,208,48,135,131,3,218,218,38,38,131,3,222,34,34,222,135,0,128,2,0,12,0,47,0,0,0,44,0,1,0,129,2,41,91,122,67,0,148,0,164,0,164,0,150,2,124,91,40,133,65,0,144,0,144,131,128,18,141,183,248,41,73,81,179,186,221,17,84,125,0,206,50,51,209,209,51,131,129,0,172,71,255,75,255,39,255,56,255,86,255,86,255,57,255,41,255,77,0,174,139,128,11,110,53,244,217,216,224,34,41,43,18,213,156,130,3,224,34,34,224,131,128,2,0,12,0,64,0,0,0,53,0,1,0,129,65,0,150,0,150,133,65,0,144,0,144,129,2,41,91,123,67,0,149,0,164,0,164,0,150,2,124,91,40,135,128,64,255,126,129,64,0,130,128,21,206,50,51,209,209,51,0,131,179,250,43,73,81,179,186,221,18,84,125,0,206,50,131,129,1,156,156,137,0,172,71,255,75,255,40,255,57,255,86,255,86,255,57,255,41,255,77,0,174,135,128,0,70,129,0,186,130,16,224,34,34,224,0,100,49,246,219,216,224,34,41,43,19,213,156,134,128,2,0,12,0,29,0,0,0,22,0,1,0,132,65,255,106,255,106,130,1,40,40,131,128,2,50,206,0,64,0,130,129,64,255,126,3,39,217,217,39,131,132,1,100,100,130,65,0,190,0,190,131,131,0,186,129,4,70,213,43,43,213,131,128,2,0,12,0,67,0,0,0,35,0,1,0,129,1,40,40,79,252,204,252,204,252,204,252,204,252,204,252,54,252,54,252,204,3,52,3,52,3,52,3,52,3,52,2,158,2,158,3,52,131,7,49,207,207,49,0,50,206,0,64,0,130,129,64,255,126,128,2,50,206,0,64,0,130,129,64,255,126,131,129,65,0,190,0,190,132,1,100,100,133,65,0,140,0,140,132,3,223,33,33,223,131,0,186,129,0,70,131,0,186,129,0,70,131,0,128,2,0,12,0,64,0,0,0,67,0,1,0,7,34,32,50,23,252,7,18,9,130,18,114,114,114,78,38,26,5,38,72,69,60,76,90,90,90,234,234,234,4,135,129,11,13,65,115,111,111,111,91,70,57,57,70,33,131,6,206,154,145,145,145,207,20,129,6,20,9,0,48,208,208,48,131,7,238,236,228,227,227,0,10,4,130,18,182,182,182,201,222,223,217,227,216,210,204,204,204,204,204,22,22,22,3,135,33,227,227,217,217,215,207,207,207,202,197,224,224,1,27,51,51,51,57,51,58,71,71,71,52,31,31,31,227,227,227,222,34,34,222,131,128,2,0,12,0,88,0,0,0,87,0,1,0,47,16,18,22,24,24,24,22,18,16,13,6,3,13,9,0,252,209,162,162,162,209,252,255,6,10,0,4,13,20,27,229,183,236,73,27,229,15,18,227,241,38,63,193,218,241,15,29,238,131,138,28,2,92,90,90,90,90,43,0,213,166,166,166,165,163,253,255,0,23,27,229,192,23,192,229,27,36,44,181,220,131,3,36,220,181,44,131,47,238,238,238,238,238,238,238,238,238,243,253,2,2,253,243,238,21,62,62,62,21,238,240,245,248,248,245,241,192,212,36,10,64,246,212,36,247,242,3,12,216,216,40,50,12,247,253,14,131,139,27,171,171,171,171,171,216,0,40,85,85,85,84,83,254,255,0,219,231,19,253,219,253,25,237,218,202,23,48,131,3,208,38,23,202,131,128,2,0,12,0,104,32,0,0,99,0,1,0,35,34,2,1,3,2,1,2,1,1,2,1,2,1,3,1,1,1,1,2,2,1,3,2,1,1,1,2,1,2,3,3,1,1,1,2,2,34,54,54,94,106,80,24,80,105,94,94,54,54,6,231,246,0,4,14,186,186,226,188,132,132,188,226,226,186,14,1,246,250,6,55,201,11,225,196,0,10,13,243,243,246,0,17,60,32,130,14,88,88,90,75,60,0,243,243,13,13,0,239,196,166,168,132,132,11,40,40,40,57,36,236,236,38,58,40,40,40,133,0,237,129,23,14,38,50,57,64,64,64,104,104,104,83,64,64,83,104,104,104,64,64,64,57,50,38,14,131,3,218,218,38,38,131,129,17,225,196,197,199,200,192,193,200,200,56,56,54,54,56,58,59,60,32,132,25,171,171,171,171,171,203,231,238,250,0,2,5,5,251,251,254,0,7,19,25,53,85,85,85,85,85,138,128,2,0,12,0,133,0,0,0,112,32,1,0,15,252,253,255,0,245,248,251,252,44,93,93,93,93,93,93,111,65,0,147,0,147,52,111,93,93,93,93,93,93,44,252,251,248,246,0,255,253,252,239,225,225,225,225,225,225,208,199,218,255,255,206,199,225,225,225,225,225,225,239,189,189,232,232,40,40,206,206,182,182,232,232,50,50,216,216,131,131,25,168,167,166,166,166,214,0,5,13,17,23,13,13,243,243,233,239,244,252,0,43,90,90,90,88,88,134,5,252,243,239,244,249,254,131,4,3,10,17,13,5,130,3,60,234,234,60,131,3,22,196,196,22,135,38,37,0,3,1,3,1,2,2,1,3,1,3,2,1,2,1,3,1,3,3,3,1,1,1,1,2,1,1,1,1,3,4,2,2,2,2,2,2,2,128,15,236,236,206,200,192,192,192,192,192,192,192,192,200,206,236,236,131,5,235,220,237,20,227,225,130,7,245,20,196,20,238,20,196,20,129,13,85,85,85,85,24,0,251,5,0,194,171,171,171,171,130,12,56,44,28,20,16,240,240,224,204,200,0,34,196,129,1,60,222,129,128,2,0,12,0,16,0,0,0,16,0,1,8,7,1,2,2,2,2,2,2,2,7,24,172,172,0,172,0,55,201,129,0,170,129,0,86,129,7,236,54,54,20,54,20,218,38,129,0,78,129,0,178,129,128,2,0,12,0,28,0,0,0,28,0,1,14,13,1,2,2,2,2,2,2,2,1,2,3,2,2,2,13,50,216,14,232,40,206,14,232,232,86,24,86,24,86,129,1,234,60,129,1,196,22,130,2,154,102,0,13,196,20,0,20,196,20,0,20,20,200,236,200,236,200,129,1,34,196,129,1,60,222,130,2,74,182,0,0,2,0,12,0,27,32,0,0,26,32,1,8,7,0,2,3,3,2,1,1,3,129,5,20,48,0,235,208,235,7,48,208,23,209,182,182,209,23,8,7,0,2,2,1,3,1,1,4,130,4,238,215,238,0,41,7,222,34,218,218,20,44,44,242,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,0,2,0,12,0,49,32,0,0,48,32,1,16,15,0,2,2,2,3,3,2,1,1,3,2,3,2,1,1,3,131,11,20,48,0,235,208,235,20,48,0,235,208,235,15,48,208,48,208,50,236,209,209,236,50,50,236,209,209,236,50,16,15,0,2,2,2,2,1,3,1,1,4,2,1,3,1,1,4,132,10,238,215,238,0,41,0,238,215,238,0,41,15,228,40,216,28,218,218,20,44,44,242,218,218,20,44,44,242,0,0,2,0,12,0,64,32,0,0,60,32,1,20,19,0,1,1,1,1,1,1,1,2,3,2,1,1,3,2,3,2,1,1,3,128,1,1,1,129,14,153,153,0,20,48,0,235,208,235,20,48,0,235,208,235,4,40,70,186,216,70,129,12,186,68,254,227,227,254,68,68,254,227,227,254,68,20,19,0,1,1,1,1,1,1,1,1,1,3,1,1,4,2,1,3,1,1,4,132,1,50,50,129,10,238,215,238,0,41,0,238,215,238,0,41,19,236,216,40,20,216,10,246,40,236,236,38,62,62,4,236,236,38,62,62,4,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,0,2,0,12,0,31,32,0,0,30,32,1,10,9,0,2,2,2,3,3,2,1,1,3,131,5,20,48,0,235,208,235,9,48,208,50,210,50,236,209,209,236,50,10,9,0,2,2,2,2,1,3,1,1,4,132,4,238,215,238,0,41,9,227,40,216,27,218,218,20,44,44,242,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,85,32,0,0,105,0,1,0,28,27,0,2,2,2,3,3,2,1,1,3,2,3,2,1,1,3,2,3,2,1,1,3,2,3,2,1,1,3,131,23,20,48,0,235,208,235,20,48,0,235,208,235,20,48,0,235,208,235,20,48,0,235,208,235,5,48,208,50,210,97,27,129,9,27,97,0,186,159,159,186,0,97,27,129,7,27,97,0,186,159,159,186,0,136,46,231,196,196,196,231,0,24,60,60,60,24,0,231,196,196,196,231,0,24,60,60,60,24,0,231,196,196,196,231,0,24,60,60,60,24,0,231,196,196,196,231,0,24,60,60,60,24,131,12,228,40,40,228,216,28,28,216,136,136,171,196,220,130,3,220,196,171,136,129,14,35,60,84,120,120,120,84,60,35,0,136,136,171,196,220,130,3,220,196,171,136,129,8,35,60,84,120,120,120,84,60,35,132,0,0,2,0,12,0,49,32,0,0,64,32,1,16,15,0,2,2,2,3,3,2,1,1,3,2,3,2,1,1,3,131,11,20,48,0,235,208,235,20,48,0,235,208,235,5,88,248,90,250,97,27,129,7,27,97,0,186,159,159,186,0,20,19,1,2,2,2,1,3,1,2,1,1,1,2,1,3,1,2,1,1,1,2,2,100,0,100,129,14,196,196,0,24,60,60,24,0,196,196,0,24,60,60,24,6,80,11,67,0,136,196,220,129,10,220,196,136,0,60,84,120,120,84,60,0,0,128,2,0,12,0,63,32,0,0,66,0,1,0,20,19,0,1,1,1,1,1,1,1,2,3,2,1,1,3,2,3,2,1,1,3,129,1,123,123,129,13,255,255,20,48,0,235,208,235,20,48,0,235,208,235,1,40,186,129,5,70,216,186,70,97,27,129,7,27,97,0,186,159,159,186,0,31,239,239,229,229,239,239,3,3,0,231,196,196,196,231,0,24,60,60,60,24,0,231,196,196,196,231,0,24,60,60,60,24,131,12,236,40,246,10,216,20,40,216,136,136,171,196,220,130,3,220,196,171,136,129,8,35,60,84,120,120,120,84,60,35,132,128,2,0,12,0,64,32,0,0,66,0,1,0,20,19,0,1,1,1,1,1,1,1,2,3,2,1,1,3,2,3,2,1,1,3,128,1,1,1,129,14,133,133,0,20,48,0,235,208,235,20,48,0,235,208,235,4,40,70,186,216,70,129,2,186,97,27,129,7,27,97,0,186,159,159,186,0,128,1,236,236,129,1,10,10,129,22,231,196,196,196,231,0,24,60,60,60,24,0,231,196,196,196,231,0,24,60,60,60,24,131,12,236,216,40,20,216,10,246,40,136,136,171,196,220,130,3,220,196,171,136,129,8,35,60,84,120,120,120,84,60,35,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,17,0,0,0,17,0,1,0,128,2,100,0,156,139,131,7,48,208,208,48,48,208,208,48,131,3,236,196,20,60,139,131,7,216,28,28,216,228,40,40,228,131,0,128,2,0,12,0,21,0,0,0,21,0,1,0,128,2,100,0,156,143,131,11,48,208,208,48,48,208,208,48,48,208,208,48,131,3,246,206,30,70,143,131,11,243,54,54,243,223,33,33,223,202,13,13,202,131,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,103,0,0,0,101,0,1,0,132,2,241,220,216,129,9,53,53,53,58,73,93,104,104,104,49,129,13,245,232,232,232,229,213,204,203,203,203,201,24,65,22,129,13,245,240,0,20,48,48,48,20,0,235,208,208,208,235,131,20,48,208,208,48,48,27,230,208,208,48,156,176,169,161,176,197,224,246,43,100,100,129,11,251,246,239,235,216,207,192,176,156,120,40,36,129,2,100,100,122,129,8,227,207,186,159,159,159,186,207,227,132,131,2,236,250,5,130,41,216,216,216,235,0,224,196,196,196,217,236,0,10,20,20,20,11,0,18,40,40,40,236,226,230,247,0,236,236,236,0,238,215,215,215,238,0,17,41,41,41,17,131,20,216,27,27,216,226,241,23,40,40,226,40,25,30,23,40,22,247,226,205,181,181,131,9,244,223,216,228,244,241,40,181,236,245,129,2,181,181,181,129,8,24,41,58,82,82,82,58,41,24,132,0,128,2,0,12,0,87,0,0,0,86,0,1,0,45,240,244,253,0,246,249,0,4,48,94,94,94,48,4,0,247,243,253,250,243,240,236,232,232,232,236,20,27,229,183,236,73,27,229,15,18,227,241,38,63,193,218,241,15,29,238,131,129,15,255,253,163,165,166,166,166,213,0,43,90,90,90,90,92,2,135,11,23,27,229,192,23,192,229,27,36,44,181,220,131,3,36,220,181,44,131,15,20,17,13,10,10,12,17,20,238,196,196,196,238,20,15,5,129,27,5,15,20,20,20,20,20,20,192,212,36,10,64,246,212,36,247,242,3,12,216,216,40,50,12,247,253,14,131,129,14,255,254,83,84,85,85,85,40,0,216,171,171,171,171,171,136,11,219,231,19,253,219,253,25,237,218,202,23,48,131,3,208,38,23,202,131,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,0,2,0,12,0,57,32,0,0,48,32,1,20,19,1,2,2,2,2,2,2,2,1,1,3,1,1,1,1,1,4,2,1,1,19,30,196,20,186,4,172,4,172,232,254,24,254,232,232,242,232,162,232,242,232,131,3,234,60,196,22,133,5,90,90,213,166,166,0,16,15,1,2,2,2,2,2,2,2,1,4,2,2,1,3,3,1,6,246,70,246,70,236,0,236,129,6,236,0,20,0,60,0,20,131,3,34,196,60,222,130,4,171,171,0,85,85,0,0,2,0,12,0,128,32,0,0,113,32,1,42,41,0,3,3,2,1,2,1,1,1,2,3,3,1,2,1,1,2,3,2,2,1,1,1,1,1,1,2,1,1,2,1,2,1,2,2,2,2,2,2,2,2,2,20,4,31,31,57,50,1,37,57,48,31,31,4,2,0,10,8,4,163,163,163,146,65,255,109,255,109,18,146,163,163,163,163,163,4,5,11,0,2,40,206,24,36,50,216,24,36,129,1,243,253,130,2,2,5,13,131,17,88,88,90,0,244,233,243,243,13,13,23,17,5,0,214,166,166,168,131,1,234,60,129,1,196,22,38,37,0,3,3,1,1,1,2,1,1,1,1,1,3,3,1,2,1,3,3,1,2,3,1,3,1,2,3,3,1,2,2,2,2,2,2,2,2,2,37,7,7,7,7,38,36,243,25,43,28,7,7,7,7,13,27,27,57,71,71,71,71,71,71,71,71,57,27,27,13,10,90,0,60,10,90,0,60,129,9,170,186,218,240,16,16,24,40,66,86,131,11,171,171,171,194,0,5,251,0,24,85,85,85,131,1,34,196,129,1,60,222,0,128,2,0,12,0,27,0,0,0,27,0,1,14,13,1,2,2,2,2,2,2,2,2,2,2,2,2,2,13,30,196,20,186,4,222,4,222,24,170,170,232,170,232,131,3,234,60,196,22,129,0,154,129,0,102,13,246,70,246,70,236,216,236,216,236,56,56,20,56,20,131,3,34,196,60,222,129,0,74,129,0,182,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,114,0,0,0,113,0,1,0,58,53,53,53,58,73,93,104,104,104,55,10,235,191,169,169,24,24,22,18,13,10,250,232,232,232,229,213,204,203,203,203,25,25,233,233,41,41,207,207,51,51,217,217,25,25,169,169,0,20,48,48,48,20,0,235,208,208,208,235,131,18,156,176,169,161,176,194,217,236,37,100,100,101,71,16,234,234,239,248,253,130,12,246,236,232,234,216,207,192,176,156,60,234,234,60,135,3,22,196,196,22,129,8,227,207,186,159,159,159,186,207,227,132,12,216,216,216,235,0,224,196,196,196,223,246,24,23,129,29,204,204,241,25,36,10,15,20,20,20,11,0,18,40,40,40,236,236,20,20,226,226,50,50,206,206,30,30,236,236,130,10,238,215,215,215,238,0,17,41,41,41,17,131,18,40,25,30,23,40,19,240,216,199,181,181,181,198,225,237,49,59,48,23,130,12,251,246,237,222,216,228,244,241,40,196,34,34,196,135,3,222,60,60,222,129,8,24,41,58,82,82,82,58,41,24,132,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,55,0,0,0,55,0,1,28,27,0,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,131,23,50,216,24,232,40,206,24,232,50,216,24,232,40,206,24,232,50,216,24,232,40,206,24,232,3,60,234,23,196,129,1,234,60,129,1,196,22,129,1,234,60,129,1,196,22,129,1,234,60,129,1,196,22,131,23,206,30,236,20,226,50,236,20,206,30,236,20,226,50,236,20,206,30,236,20,226,50,236,20,3,196,34,222,60,129,1,34,196,129,1,60,222,129,1,34,196,129,1,60,222,129,1,34,196,129,1,60,222,128,2,0,12,0,71,0,0,0,71,0,1,36,35,0,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,131,31,50,216,24,232,40,206,24,232,50,216,24,232,40,206,24,232,50,216,24,232,40,206,24,232,50,216,24,232,40,206,24,232,3,22,196,60,234,129,1,234,60,129,1,196,22,129,1,234,60,129,1,196,22,129,1,234,60,129,1,196,22,129,1,234,60,129,1,196,22,131,31,206,30,236,20,226,50,236,20,206,30,236,20,226,50,236,20,206,30,236,20,226,50,236,20,206,30,236,20,226,50,236,20,3,222,60,196,34,129,1,34,196,129,1,60,222,129,1,34,196,129,1,60,222,129,1,34,196,129,1,60,222,129,1,34,196,129,1,60,222,128,2,0,12,0,23,0,0,0,23,0,1,12,11,0,2,2,2,3,2,2,2,2,2,2,2,131,7,50,216,24,232,40,206,24,232,3,28,196,62,230,129,1,234,60,129,1,196,22,131,7,206,30,236,20,226,50,236,20,3,228,60,198,30,129,1,34,196,129,1,60,222,128,2,0,12,0,42,0,0,0,40,32,1,0,13,57,50,216,223,24,24,232,232,40,40,206,206,30,28,129,3,24,24,232,232,131,0,86,129,4,86,60,234,234,60,131,0,86,129,4,86,22,196,196,22,131,12,11,0,1,1,1,2,2,2,2,1,2,3,2,7,199,206,30,23,236,20,226,50,129,1,236,20,0,178,129,2,178,34,196,129,3,178,0,60,222,0,128,2,0,12,0,76,0,0,0,79,32,1,0,0,233,129,36,250,7,25,25,25,255,233,233,243,233,199,163,163,163,199,233,243,24,24,232,232,40,40,206,206,57,50,216,223,24,24,232,232,30,30,216,232,131,5,86,20,241,14,13,252,132,3,90,90,90,43,132,3,60,234,234,60,131,0,86,129,5,86,22,196,196,22,86,129,0,86,131,25,24,0,1,2,1,2,3,2,1,3,3,1,2,2,2,2,1,1,1,1,2,2,1,1,1,1,24,24,176,165,196,234,254,18,254,58,254,18,236,20,226,50,199,206,30,23,236,20,0,2,20,24,3,178,248,20,16,129,6,171,171,0,41,41,34,196,129,0,178,129,3,178,60,222,178,129,0,178,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,24,0,0,0,24,0,1,0,1,23,233,129,1,23,233,129,3,24,90,232,166,131,7,48,208,208,48,48,208,208,48,135,1,244,6,129,1,231,251,129,3,236,201,20,55,131,7,216,27,27,216,226,40,40,226,135,0,128,2,0,12,0,32,0,0,0,32,0,1,0,1,23,233,129,1,23,233,137,3,24,90,232,166,131,15,48,208,208,48,48,208,208,48,48,208,208,48,48,208,208,48,135,1,244,6,129,1,231,251,137,3,236,201,20,55,131,15,216,27,27,216,226,40,40,226,216,27,27,216,226,40,40,226,135,0,128,2,0,12,0,26,0,0,0,23,0,1,0,129,65,0,175,0,175,1,26,26,129,3,24,90,232,166,131,128,6,131,5,251,119,255,211,45,135,129,9,185,185,239,239,255,255,236,201,20,55,131,7,236,40,246,10,228,37,40,216,135,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,9,0,0,0,9,0,1,4,3,0,2,3,2,129,1,55,201,0,86,129,0,70,129,1,218,38,0,178,129,0,178,128,2,0,12,0,7,0,0,0,7,0,1,0,135,0,86,129,0,86,131,135,0,178,129,0,178,131,0,128,2,0,12,0,4,0,0,0,4,0,1,0,132,0,96,131,132,0,173,131,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,91,0,0,0,82,32,1,0,47,24,24,232,232,170,170,20,56,94,94,94,65,40,170,170,10,250,232,232,232,223,216,24,24,170,170,230,230,10,10,170,170,0,45,94,94,94,54,20,170,170,0,244,232,232,232,25,70,131,132,14,154,154,154,186,216,3,51,51,51,4,4,4,252,246,251,133,13,35,231,231,35,4,205,205,205,249,30,63,102,102,102,130,4,4,10,8,4,4,131,28,27,1,2,2,1,3,3,1,2,3,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,2,3,2,1,27,187,69,56,0,196,0,56,100,20,9,0,236,56,56,30,56,0,232,196,196,196,232,0,56,0,20,61,100,129,5,64,64,20,224,224,242,134,12,32,32,32,8,246,222,192,192,192,0,10,14,14,128,2,0,12,0,42,0,0,0,36,0,1,0,25,24,24,232,232,246,14,14,14,1,246,238,225,222,49,39,8,246,201,148,148,148,226,235,243,222,233,131,140,10,80,86,94,94,94,45,0,162,162,162,169,133,11,186,186,70,70,0,236,236,236,246,0,249,248,132,3,25,56,56,56,136,138,12,2,5,205,190,175,175,175,217,0,81,81,81,81,133,0,0,2,0,12,0,41,32,0,0,50,32,1,14,13,1,2,1,4,2,3,1,1,1,1,3,3,3,1,13,24,232,0,24,0,232,56,47,18,0,156,0,8,252,133,7,70,98,98,98,0,158,166,5,18,17,1,2,1,1,3,1,1,3,1,3,1,1,1,3,3,1,1,1,17,184,72,50,16,236,247,0,30,246,0,29,60,60,50,15,20,28,42,134,7,226,186,176,176,217,0,80,80,130,0,128,2,0,12,0,46,0,0,0,40,0,1,0,29,216,10,40,0,206,0,30,246,246,14,14,14,1,246,238,225,222,49,39,8,246,201,148,148,148,226,235,243,222,233,131,144,10,80,86,94,94,94,45,0,162,162,162,169,133,0,80,129,12,80,60,236,236,60,0,236,236,236,246,0,249,248,132,3,25,56,56,56,136,142,12,2,5,205,190,175,175,175,217,0,81,81,81,81,133,0,128,2,0,12,0,75,32,0,0,54,0,1,26,25,1,4,4,4,3,1,1,1,1,1,1,1,1,1,3,1,2,3,2,1,1,1,1,1,1,1,24,23,5,8,3,1,1,1,1,1,1,1,1,1,3,1,2,3,2,1,1,1,1,1,1,1,23,24,232,240,24,10,216,16,40,246,232,0,48,104,48,209,152,10,24,229,216,246,40,27,232,129,21,58,0,236,20,58,20,236,0,156,156,45,100,100,211,20,0,198,236,20,236,198,0,25,250,236,6,20,21,237,236,20,236,236,20,20,0,241,221,241,16,35,236,237,21,20,20,236,237,21,25,236,6,20,250,238,22,0,216,235,216,0,19,36,36,240,220,220,16,0,234,18,40,0,40,20,236,0,128,2,0,12,0,85,0,0,0,83,0,1,0,9,24,24,232,232,0,10,23,24,12,5,129,31,48,98,98,98,86,66,165,217,24,24,24,7,10,254,250,235,54,49,19,10,206,158,158,158,155,154,66,27,232,232,232,243,131,133,16,251,246,141,151,162,162,162,192,221,237,17,30,121,102,60,20,19,130,16,1,12,89,88,94,94,94,59,20,14,248,247,161,177,186,221,238,132,3,187,187,69,69,129,37,236,236,248,247,6,0,216,190,190,190,197,206,0,249,236,236,236,6,30,15,33,20,226,249,8,30,48,66,66,66,60,50,31,22,20,20,20,252,131,133,14,2,0,81,82,81,81,81,55,20,251,233,231,215,224,8,132,16,247,0,175,168,175,175,175,204,236,6,9,10,8,3,234,10,14,132,0,128,2,0,12,0,68,32,0,0,67,0,1,0,23,22,0,2,2,2,2,4,2,1,1,1,2,2,3,2,2,1,2,1,1,1,1,2,1,131,18,45,24,49,58,97,106,94,11,166,11,94,94,110,105,65,93,94,232,232,3,38,218,42,214,131,9,225,210,211,88,0,168,59,84,46,34,129,2,70,0,251,3,236,236,20,20,129,32,20,20,216,226,236,236,236,225,216,207,192,198,206,206,206,12,40,70,70,70,10,206,206,206,206,203,195,211,226,206,206,20,20,131,4,208,40,40,208,196,129,0,196,138,8,186,166,166,166,212,0,110,110,110,64,0,170,0,100,140,128,2,0,12,0,50,0,0,0,50,0,1,0,21,20,39,39,39,35,30,11,238,232,79,71,45,30,235,173,173,173,0,253,253,232,255,139,134,12,22,40,100,97,94,94,94,45,0,162,162,162,169,129,7,24,232,232,24,24,232,232,24,131,18,236,236,236,236,242,246,242,247,0,20,15,255,246,21,56,56,56,236,245,129,0,248,139,134,12,24,45,225,201,175,175,175,217,0,81,81,81,81,129,7,216,20,20,216,236,40,40,236,131,0,0,2,0,12,0,60,32,0,0,54,32,1,19,18,0,3,3,3,1,2,1,3,1,2,2,2,2,2,2,2,2,2,2,128,0,24,129,14,66,20,0,156,156,0,206,0,232,0,165,0,252,0,232,1,49,30,129,7,72,98,98,30,243,207,49,160,130,3,208,48,0,96,18,17,0,3,3,2,1,1,1,2,3,2,5,2,2,2,2,2,2,2,128,16,236,30,55,60,60,57,40,70,34,216,20,216,40,216,20,216,20,10,226,231,0,10,20,196,187,176,241,50,78,133,0,178,128,2,0,12,0,63,0,0,0,53,0,1,0,25,49,49,49,246,234,222,222,230,241,246,187,187,187,0,6,231,14,49,49,49,187,187,187,196,216,231,135,64,255,116,0,60,131,5,98,98,98,98,98,60,64,255,116,16,1,155,152,160,162,176,176,176,176,203,241,3,0,42,214,214,42,131,25,214,214,214,246,0,10,10,4,251,246,22,22,22,226,226,246,229,214,214,214,22,22,22,16,1,246,135,133,5,181,181,181,181,181,221,129,4,71,71,66,50,31,131,6,253,253,0,216,40,40,216,131,0,128,2,0,12,0,18,0,0,0,18,0,1,8,7,1,2,2,2,2,2,2,2,7,24,0,24,170,24,16,24,232,1,232,24,129,3,205,51,0,102,7,236,20,236,56,236,0,236,20,1,20,218,129,3,33,223,0,192,128,2,0,12,0,80,0,0,0,67,32,1,0,41,4,4,212,212,212,212,212,212,246,16,14,14,14,0,246,233,220,225,49,37,7,246,198,148,148,148,209,246,244,242,242,222,222,238,66,66,222,222,246,246,222,222,131,130,3,223,244,196,244,130,0,17,132,14,12,23,103,99,94,94,94,44,0,225,162,162,162,162,162,131,6,206,206,0,52,206,206,52,131,22,21,0,2,1,1,1,1,2,4,1,1,2,1,1,3,3,3,3,1,4,2,2,2,11,177,59,59,255,255,59,0,236,246,0,18,20,129,0,56,129,4,20,190,20,0,20,129,3,236,226,34,47,131,11,250,246,195,175,0,81,81,0,30,0,30,222,128,2,0,12,0,106,0,0,0,92,32,1,0,128,16,49,98,98,98,52,10,253,218,199,24,21,14,10,251,232,232,232,130,31,11,24,24,24,31,30,30,0,212,158,158,158,209,0,6,236,245,232,229,7,24,24,232,232,50,14,225,5,24,24,232,232,131,9,236,251,52,80,86,94,94,94,87,81,132,4,245,236,224,216,226,129,30,1,1,22,39,41,30,30,18,221,191,177,162,162,162,146,138,0,252,0,29,227,227,29,0,232,232,0,29,227,227,29,131,30,29,0,3,2,1,3,1,2,1,3,1,1,1,4,3,2,2,1,3,3,1,1,1,2,2,1,1,1,1,2,2,29,200,200,244,30,236,236,251,0,20,20,60,60,236,196,56,56,56,0,20,20,17,5,236,20,236,196,40,80,236,20,4,100,20,170,170,176,130,10,40,45,50,40,216,206,216,244,0,86,80,130,7,40,216,0,40,40,0,40,216,0,128,2,0,12,0,57,0,0,0,41,0,1,0,1,60,60,131,18,206,206,216,216,235,24,64,90,90,232,232,231,227,221,24,24,170,170,110,64,0,144,1,42,232,131,13,25,231,231,25,25,231,231,25,40,188,188,171,167,203,129,3,224,227,6,40,132,1,214,172,132,137,17,242,222,209,202,202,20,20,18,12,5,236,236,56,56,176,9,89,20,131,13,196,20,20,196,196,20,20,196,0,80,80,66,44,16,138,1,180,180,132,0,0,2,0,12,0,64,32,0,0,50,32,1,20,19,1,1,1,1,4,2,2,1,3,3,1,1,1,1,2,2,2,2,2,2,128,18,4,24,24,245,232,84,84,0,172,172,178,212,0,24,232,9,247,9,247,3,143,178,197,236,129,8,60,0,74,236,192,160,158,158,158,129,2,60,0,60,17,16,1,1,2,2,4,4,2,1,2,2,2,2,2,2,2,2,2,16,196,214,236,246,20,200,0,34,70,53,0,236,20,250,44,235,29,1,98,93,130,6,205,150,150,0,59,78,78,132,128,2,0,12,0,71,0,0,0,66,32,1,0,2,12,12,6,131,15,10,20,255,238,244,78,68,37,20,214,136,136,136,136,143,151,64,255,51,11,12,12,244,244,12,12,244,244,12,12,244,244,131,128,2,160,185,232,135,5,70,85,102,102,102,49,129,2,232,185,160,129,10,160,160,0,24,232,232,24,24,232,232,24,131,21,20,1,3,3,1,3,1,1,1,1,2,1,1,2,1,1,2,2,2,2,2,2,13,236,236,11,40,20,236,250,35,60,60,60,60,60,60,129,4,20,236,0,236,0,0,68,130,16,246,211,197,183,183,181,181,0,51,68,0,68,0,20,216,40,236,128,2,0,12,0,51,0,0,0,46,0,1,0,18,30,44,53,53,53,203,203,203,223,240,236,1,12,22,234,239,7,24,24,129,1,24,24,133,129,1,222,186,129,18,186,176,164,158,158,158,157,162,251,254,0,32,234,230,28,32,234,230,28,131,128,17,246,236,236,236,56,56,56,48,24,0,5,15,20,20,15,5,236,236,129,1,236,236,133,133,7,75,75,75,75,75,75,75,75,130,7,186,20,20,186,246,80,80,246,131,128,2,0,12,0,21,0,0,0,21,32,1,10,9,0,1,3,1,2,1,3,1,3,2,9,24,24,232,232,94,94,162,162,24,232,128,6,60,210,60,0,60,46,60,129,6,5,1,3,4,3,4,2,5,236,20,210,46,216,40,128,2,20,0,195,129,128,2,0,12,0,39,32,0,0,37,0,1,0,12,11,1,2,1,1,2,1,1,2,2,2,2,2,11,24,232,81,166,203,176,91,83,24,178,78,232,2,231,25,0,64,0,252,129,64,255,4,132,131,64,255,102,2,74,54,54,64,0,154,10,182,202,202,236,236,54,54,202,202,20,20,131,6,206,50,50,206,0,36,36,129,1,220,220,140,0,0,2,0,12,0,51,32,0,0,37,32,1,16,15,1,2,2,1,1,1,1,2,1,2,1,2,2,2,2,2,15,24,232,170,20,56,94,94,56,20,170,20,232,232,20,24,170,8,231,25,204,204,204,243,25,102,102,129,2,14,37,50,129,12,11,0,2,3,1,4,2,2,1,3,3,2,2,129,9,56,0,186,0,56,0,20,0,236,56,5,206,50,24,24,215,192,130,0,216,129,0,2,0,12,0,57,32,0,0,41,32,1,18,17,1,2,2,2,2,1,1,1,1,2,1,2,1,2,2,2,2,2,17,24,232,24,232,170,20,56,94,94,56,20,170,20,232,232,20,24,170,10,231,25,231,25,204,204,204,243,25,102,102,129,2,14,37,50,129,14,13,0,2,2,2,3,1,4,2,2,1,3,3,2,2,131,9,56,0,186,0,56,0,20,0,236,56,7,226,0,236,10,24,24,215,192,130,0,216,129,0,2,0,12,0,57,32,0,0,41,32,1,18,17,1,2,2,2,2,1,1,1,1,2,1,2,1,2,2,2,2,2,17,24,0,24,0,170,20,56,94,94,56,20,170,20,232,232,20,24,170,10,231,25,204,50,204,204,204,243,25,102,102,129,2,14,37,50,129,14,13,0,2,2,2,3,1,4,2,2,1,3,3,2,2,131,9,56,0,186,0,56,0,20,0,236,56,7,196,20,216,20,24,24,215,192,130,0,216,129,128,2,0,12,0,110,0,0,0,106,0,1,0,128,12,6,0,245,226,229,0,44,80,80,80,72,54,21,130,36,241,236,232,232,242,215,206,175,152,152,152,180,220,232,232,232,232,250,100,70,246,0,24,24,185,185,185,185,0,38,78,78,78,38,0,185,185,138,130,13,153,156,158,158,158,183,216,244,16,30,60,72,70,40,131,12,98,98,98,98,88,70,49,1,216,207,209,206,224,129,1,216,216,132,9,43,213,213,213,251,31,57,86,86,86,130,4,10,20,31,43,43,131,131,9,245,231,226,216,206,206,206,210,226,234,132,41,11,20,20,26,30,50,70,70,70,62,50,25,20,20,20,9,226,40,100,30,236,236,60,60,10,10,40,10,236,236,236,10,40,10,10,40,40,40,40,40,40,40,131,130,13,80,80,80,80,80,60,40,33,20,20,33,22,30,15,131,12,176,176,176,176,202,226,232,249,246,2,240,236,245,136,9,216,40,40,40,18,0,218,176,176,176,132,2,237,216,216,131,0,128,2,0,12,0,62,0,0,0,62,32,1,0,29,24,24,0,46,94,94,94,46,0,24,246,246,239,232,232,232,244,0,101,85,236,232,24,24,232,232,24,24,232,232,131,17,50,206,206,206,237,10,52,100,100,100,100,110,98,55,30,40,50,50,131,4,49,1,1,49,100,129,0,100,131,20,19,1,1,2,1,3,1,2,2,1,1,1,1,1,1,1,1,2,2,2,2,19,236,0,196,196,0,236,0,20,20,20,9,0,196,196,20,20,236,20,236,20,11,249,249,241,236,192,192,182,201,216,202,185,185,131,3,23,163,0,192,0,0,2,0,12,0,37,32,0,0,32,32,1,12,11,1,2,2,2,2,2,2,2,2,2,2,2,11,72,232,24,184,24,232,24,214,42,232,24,232,131,2,176,0,236,129,2,20,0,80,12,11,1,2,2,2,2,2,1,2,2,2,3,2,11,186,20,236,70,28,20,28,28,228,228,236,228,134,1,50,206,130,0,128,2,0,12,0,60,0,0,0,59,32,1,0,2,12,12,6,131,24,10,20,255,238,244,78,68,37,20,214,136,136,136,136,143,151,151,12,12,244,244,12,12,244,244,131,128,2,160,185,232,135,5,70,85,102,102,102,49,129,2,232,185,160,129,6,160,160,0,24,232,232,24,131,19,18,1,3,3,1,3,1,1,1,1,2,1,1,2,1,1,2,2,1,2,16,236,236,11,40,20,236,250,35,60,60,60,60,60,60,100,0,20,129,0,68,130,14,246,211,197,183,183,181,181,0,51,68,0,68,0,198,58,128,2,0,12,0,17,0,0,0,14,0,1,6,5,1,2,2,2,2,2,5,53,203,24,232,24,232,2,100,0,100,64,0,200,128,0,100,5,218,38,236,20,236,20,5,252,0,252,188,0,192,0,128,2,0,12,0,27,0,0,0,34,0,1,0,135,7,55,55,201,201,24,24,232,232,131,7,27,229,229,27,27,229,229,27,131,0,102,129,0,102,131,15,236,236,20,20,236,236,20,20,218,218,38,38,236,236,20,20,131,7,206,50,50,206,176,20,20,176,131,0,192,129,0,192,131,128,2,0,12,0,52,0,0,0,45,0,1,0,10,24,24,232,232,84,24,156,236,236,25,231,129,1,186,70,129,6,25,231,20,20,100,232,172,131,3,24,232,232,24,130,1,176,176,129,65,0,128,0,128,129,65,0,128,0,128,129,1,176,176,134,131,6,226,236,40,0,10,236,20,129,1,30,226,129,6,236,20,246,0,216,20,30,131,3,216,60,60,216,130,1,90,90,129,1,166,166,129,1,166,166,129,1,90,90,134,128,2,0,12,0,33,0,0,0,40,0,1,0,135,11,60,24,159,5,251,97,232,196,55,55,201,201,131,7,8,216,216,8,24,232,232,24,130,1,151,151,131,1,146,146,132,10,236,236,20,20,236,236,20,20,218,236,70,129,6,186,20,38,218,218,38,38,131,8,206,50,50,206,186,30,30,186,196,129,1,60,60,129,0,196,135,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,22,32,0,0,15,0,1,0,6,5,1,2,2,2,2,2,5,24,232,24,232,24,232,5,208,48,208,48,208,48,143,11,222,34,34,222,222,34,34,222,222,34,34,222,131,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,29,0,0,0,26,0,1,0,12,10,16,241,24,59,59,59,197,197,197,206,226,241,131,11,1,155,152,160,162,176,255,255,176,203,241,3,132,11,236,236,0,239,224,224,224,32,32,32,26,11,132,128,4,71,71,66,50,31,131,1,253,253,132,128,2,0,12,0,27,0,0,0,23,32,1,0,12,59,59,59,0,244,232,232,240,251,0,197,197,197,131,128,0,60,131,5,98,98,98,98,98,60,132,7,6,1,2,2,1,2,1,2,6,224,0,20,20,5,0,32,130,3,181,181,181,221,0,128,2,0,12,0,10,0,0,0,9,0,1,4,3,1,2,2,2,3,24,232,24,182,128,2,96,50,0,3,236,20,236,64,1,34,222,129,0,128,2,0,12,0,25,0,0,0,25,0,1,0,128,2,103,0,153,147,131,15,38,218,218,38,38,218,218,38,38,218,218,38,38,218,218,38,131,128,2,176,0,80,147,131,15,246,70,70,246,186,10,10,186,206,30,30,206,226,50,50,226,131,0,128,2,0,12,0,15,32,0,0,13,0,1,0,4,3,1,2,2,2,3,49,207,24,232,129,1,208,48,3,210,210,46,46,135,131,3,221,33,33,221,131,0,128,2,0,12,0,6,0,0,0,6,0,1,2,1,1,2,1,24,232,1,208,48,1,236,20,1,34,222,128,2,0,12,0,19,0,0,0,19,0,1,0,7,215,232,41,24,41,232,215,24,131,6,65,0,191,0,65,0,191,132,6,60,0,196,0,196,0,60,132,128,6,196,0,60,0,60,0,196,131,0,0,2,0,12,0,34,32,0,0,53,32,1,10,9,1,2,2,3,3,3,3,3,3,3,9,24,232,15,36,241,220,15,36,241,220,9,208,48,36,241,220,15,36,241,220,15,17,16,0,2,2,2,2,2,1,1,2,1,2,1,2,2,1,2,1,130,13,209,209,0,18,47,47,18,237,209,209,0,18,47,47,16,208,48,195,223,4,32,32,4,223,195,226,253,36,63,63,17,253,0,128,2,0,12,0,10,0,0,0,10,0,1,4,3,1,2,2,2,3,24,232,24,232,3,208,48,208,48,3,236,20,236,20,3,40,228,28,216,128,2,0,12,0,15,0,0,0,15,0,1,8,7,0,1,1,1,2,2,2,2,7,24,85,232,171,24,232,24,232,131,3,208,48,208,48,7,216,216,40,40,236,20,236,20,131,3,28,216,40,228,128,2,0,12,0,24,0,0,0,20,0,1,0,1,24,24,65,0,156,0,156,3,24,24,232,232,131,128,6,131,5,251,125,0,211,45,131,7,216,216,20,20,216,216,40,40,131,1,236,40,129,3,216,20,40,216,131,0,128,2,0,12,0,20,0,0,0,20,0,1,0,7,232,24,24,232,232,140,140,232,131,128,6,45,211,0,125,251,5,131,131,7,40,216,216,40,40,20,20,40,131,4,236,216,40,20,216,129,0,40,131,0,128,2,0,12,0,28,0,0,0,28,0,1,0,11,21,21,113,113,21,21,229,229,20,20,233,233,131,11,50,181,5,251,75,206,211,45,48,208,208,48,131,11,236,236,156,156,236,236,20,20,235,235,24,24,131,1,236,40,129,7,216,20,40,216,216,28,28,216,131,0,128,2,0,12,0,28,0,0,0,28,0,1,0,11,235,27,27,235,235,143,143,235,23,23,236,236,131,11,50,45,211,206,75,251,5,181,48,208,208,48,131,11,20,236,236,20,20,100,100,20,232,232,21,21,131,4,236,216,40,20,216,129,4,40,216,28,28,216,131,0,0,2,0,12,0,21,32,0,0,21,32,1,6,5,1,2,2,2,2,2,5,49,207,24,232,24,232,129,3,208,48,208,48,6,5,1,2,1,2,3,2,1,214,42,129,1,236,20,129,3,218,38,34,222,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,51,0,0,0,64,32,1,0,29,24,24,24,13,0,245,228,5,41,50,46,69,88,88,88,232,232,232,243,0,254,14,246,215,212,216,190,168,168,168,131,133,6,246,196,146,145,145,145,197,135,6,7,55,107,111,111,111,59,133,20,19,0,1,2,1,2,1,1,1,1,3,2,1,3,2,1,1,1,1,1,2,19,236,236,251,10,3,0,245,223,212,202,20,20,246,255,0,11,25,34,45,56,19,216,40,40,40,43,40,44,60,60,20,40,216,216,213,216,212,196,196,196,236,128,2,0,12,0,10,0,0,0,9,0,1,4,3,1,2,2,2,3,24,232,74,232,128,2,96,50,0,3,236,20,192,20,1,34,222,129,0,128,2,0,12,0,15,0,0,0,15,0,1,0,7,24,74,182,232,95,251,5,161,131,132,1,80,80,132,4,226,236,20,30,236,129,0,20,131,132,1,196,196,132,0,128,2,0,12,0,94,0,0,0,53,32,1,0,51,20,22,24,24,24,22,20,7,254,241,15,3,249,236,235,232,232,232,235,236,249,3,15,241,254,7,226,250,27,25,25,27,250,226,210,191,191,191,210,30,46,66,66,66,46,30,6,230,231,231,230,6,131,135,0,249,129,0,249,136,0,7,129,4,7,0,180,180,230,129,16,26,74,74,74,34,0,222,180,180,180,222,0,34,74,74,74,26,129,1,230,180,131,18,17,0,4,2,7,4,2,7,2,2,1,2,3,3,4,2,2,2,1,128,0,236,129,13,20,0,31,5,1,5,31,65,226,192,226,252,0,252,133,11,80,35,0,220,176,0,80,219,176,220,0,35,0,2,0,12,0,28,32,0,0,15,32,1,8,7,0,1,3,1,2,1,3,1,7,24,24,232,232,102,102,154,154,128,6,50,0,50,0,50,98,50,4,3,2,3,4,3,3,236,20,214,42,129,1,176,0,0,128,2,0,12,0,58,0,0,0,47,0,1,0,25,59,59,59,0,244,232,232,240,251,0,197,197,197,10,16,241,24,59,59,59,197,197,197,206,226,241,131,64,255,116,0,60,131,5,98,98,98,98,98,60,64,255,116,11,1,155,152,160,162,176,176,176,176,203,241,3,132,24,224,224,224,0,10,20,20,14,5,0,32,32,32,236,236,0,239,224,224,224,32,32,32,26,11,132,133,5,181,181,181,181,181,221,129,4,71,71,66,50,31,131,1,253,253,132,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,10,0,0,0,10,0,1,6,5,1,2,2,2,2,2,5,61,195,61,195,24,232,132,0,102,5,212,20,236,44,236,20,132,0,182,128,2,0,12,0,32,0,0,0,32,0,1,0,13,196,24,125,24,180,0,24,24,232,232,24,24,232,232,131,4,226,168,0,102,34,129,3,168,168,0,102,129,0,102,131,13,70,236,176,236,70,20,236,236,40,40,236,236,40,40,131,10,78,78,255,192,192,1,0,78,78,0,192,129,0,192,131,0,128,2,0,12,0,25,0,0,0,25,0,1,0,11,34,24,180,225,225,40,196,160,40,40,232,232,131,130,1,166,166,130,0,102,129,0,102,131,7,196,226,30,236,246,236,60,34,129,1,20,20,131,130,1,120,120,130,0,192,129,0,192,131,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,9,0,0,0,9,0,1,4,3,1,2,2,2,3,24,182,24,232,129,1,158,0,3,236,64,236,20,129,1,68,0,0,2,0,12,0,100,32,0,0,55,32,1,32,31,0,1,1,1,4,1,3,1,4,1,1,1,2,1,1,2,1,1,4,1,3,1,4,1,1,1,2,1,1,2,1,1,128,30,42,0,214,232,232,232,232,232,17,65,65,17,232,193,143,143,193,24,24,24,24,24,65,113,113,65,24,241,191,191,241,128,30,190,0,60,0,255,0,255,183,183,222,0,73,73,73,0,222,183,255,254,255,251,182,182,221,255,70,70,70,255,221,182,17,16,0,1,1,1,5,6,3,3,3,3,6,2,2,5,3,3,3,16,249,219,249,23,253,17,245,223,25,47,229,239,249,221,199,1,23,128,2,30,0,226,129,3,60,229,196,27,129,4,253,60,228,194,27,0,0,2,0,12,0,85,32,0,0,81,32,1,28,27,0,1,1,1,2,3,3,3,2,1,3,1,2,3,6,6,2,3,1,2,2,1,7,6,3,3,1,5,27,15,57,10,224,250,0,241,236,246,15,47,15,220,189,24,0,12,85,85,12,185,185,20,232,18,43,18,209,3,20,209,236,41,131,5,194,194,28,62,62,228,129,4,185,0,32,69,32,130,3,194,28,62,228,27,26,0,1,1,1,2,3,3,3,3,3,1,5,6,2,2,5,3,3,3,3,3,3,3,3,3,1,5,26,249,219,249,23,241,236,250,0,232,216,232,20,236,246,0,228,206,8,30,5,0,14,20,252,236,252,40,3,236,10,20,246,131,3,40,238,216,18,129,4,253,60,228,194,27,131,3,40,238,216,18,128,2,0,12,0,19,0,0,0,19,0,1,0,147,15,38,218,218,38,38,218,218,38,38,218,218,38,38,218,218,38,131,147,15,246,70,70,246,186,10,10,186,206,30,30,206,226,50,50,226,131,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,22,0,0,0,18,0,1,0,131,7,110,176,80,146,49,49,207,207,131,132,65,0,130,0,130,129,1,100,100,132,131,7,14,54,202,242,212,212,44,44,131,132,65,254,246,254,246,136,0,128,2,0,12,0,25,0,0,0,21,0,1,0,129,65,0,171,0,171,133,1,100,100,131,5,1,147,81,177,111,1,129,3,50,208,208,50,131,129,65,255,31,255,31,139,5,1,254,214,44,4,1,129,3,224,34,34,224,131,0,128,2,0,12,0,26,0,0,0,20,0,1,0,129,3,146,80,176,110,129,3,49,49,207,207,131,130,65,255,126,255,126,130,0,156,129,0,156,131,129,3,242,202,54,14,129,3,212,212,44,44,131,130,65,1,10,1,10,138,0,128,2,0,12,0,25,0,0,0,21,0,1,0,132,65,255,85,255,85,128,1,156,156,133,0,1,129,8,1,111,177,81,147,50,208,208,50,131,132,65,0,225,0,225,136,0,1,129,8,1,4,44,214,254,224,34,34,224,131,0,128,2,0,12,0,43,0,0,0,48,0,1,0,129,1,96,96,129,4,251,251,0,5,5,129,6,160,160,0,211,211,45,45,131,5,1,157,81,177,101,1,129,0,1,129,8,1,101,177,81,157,50,208,208,50,131,129,65,255,121,255,121,129,4,251,251,0,5,5,129,65,0,135,0,135,128,3,95,95,144,144,131,5,1,254,214,44,4,1,129,0,1,129,8,1,4,44,214,254,224,34,34,224,131,128,2,0,12,0,38,0,0,0,38,0,1,0,131,3,110,176,80,146,129,3,146,80,176,110,129,3,49,49,207,207,131,132,65,0,130,0,130,131,65,255,126,255,126,130,3,168,70,70,168,131,131,3,14,54,202,242,129,3,242,202,54,14,129,3,212,212,44,44,131,132,65,255,70,255,70,131,65,0,186,0,186,130,3,30,164,164,30,131,0,128,2,0,12,0,43,0,0,0,43,0,1,0,135,3,110,176,80,146,129,3,146,80,176,110,129,3,49,49,207,207,131,0,98,129,0,98,132,65,0,130,0,130,131,65,255,126,255,126,130,3,168,70,70,168,131,135,3,14,54,202,242,129,3,242,202,54,14,129,3,212,212,44,44,131,0,188,129,0,188,132,65,255,70,255,70,131,65,0,186,0,186,130,3,30,164,164,30,131,0,128,2,0,12,0,30,0,0,0,30,0,1,14,13,0,3,1,1,1,1,2,2,2,2,2,2,2,2,129,11,110,176,80,146,49,207,49,207,49,207,49,207,130,65,0,130,0,130,128,0,246,129,4,40,246,30,50,30,129,11,250,34,222,6,212,44,212,44,212,44,212,44,130,65,255,40,255,40,128,7,30,0,20,236,0,226,0,206,128,2,0,12,0,31,0,0,0,31,0,1,14,13,1,1,1,1,1,1,3,2,2,2,2,2,2,2,128,12,146,80,176,110,0,49,207,49,207,49,207,49,207,129,65,255,126,255,126,129,4,226,206,226,10,216,129,0,10,128,12,6,222,34,250,0,212,44,212,44,212,44,212,44,129,65,0,216,0,216,129,7,50,0,30,0,20,236,0,226,128,2,0,12,0,37,0,0,0,16,32,1,0,144,14,17,40,54,54,54,40,17,0,239,216,202,202,202,216,239,131,143,15,198,198,213,239,0,18,43,58,58,58,43,18,0,239,213,198,131,4,3,17,4,4,4,3,226,156,30,100,3,100,226,156,30,128,2,0,12,0,37,0,0,0,22,32,1,0,144,14,16,41,54,54,54,41,16,0,239,215,202,202,202,215,239,131,143,15,198,198,213,238,0,17,44,58,58,58,44,17,0,238,213,198,131,6,5,17,4,3,1,4,2,5,226,156,0,29,100,29,5,100,226,156,156,30,100,128,2,0,12,0,57,0,0,0,16,32,1,0,67,0,251,0,117,255,66,254,171,145,14,17,40,54,54,54,40,17,0,239,216,202,202,202,216,239,131,0,210,67,254,159,254,102,255,236,3,116,143,15,198,198,213,239,0,18,43,58,58,58,43,18,0,239,213,198,131,4,3,22,4,4,4,3,226,156,30,100,3,100,226,156,30,128,2,0,12,0,48,0,0,0,16,32,1,0,129,2,43,30,90,144,14,17,40,54,54,54,40,17,0,240,216,202,202,202,216,240,131,4,210,50,225,0,60,143,15,198,198,213,239,0,18,43,58,58,58,43,18,0,239,213,198,131,4,3,22,4,4,4,3,226,156,30,100,3,100,226,156,30,0,128,2,0,12,0,49,0,0,0,16,32,1,0,128,3,60,210,50,225,144,14,17,40,54,54,54,40,17,0,239,216,202,202,202,216,239,131,1,226,166,129,0,213,143,15,198,198,213,239,0,18,43,58,58,58,43,18,0,239,213,198,131,4,3,22,4,4,4,3,226,156,30,100,3,100,226,156,30,128,2,0,12,0,48,0,0,0,16,32,1,0,4,210,60,0,225,50,144,14,239,216,202,202,202,216,239,0,17,40,54,54,54,40,17,131,128,2,90,30,43,144,15,58,58,43,18,0,239,213,198,198,198,213,239,0,18,43,58,131,4,3,22,4,4,4,3,30,100,226,156,3,156,30,100,226,0,128,2,0,12,0,37,0,0,0,16,32,1,0,148,14,17,40,54,54,54,40,17,0,239,216,202,202,202,216,239,131,147,15,198,198,213,239,0,18,43,58,58,58,43,18,0,239,213,198,131,4,3,21,4,4,4,3,226,156,30,100,3,100,226,156,30,128,2,0,12,0,37,0,0,0,16,32,1,0,153,14,17,40,54,54,54,40,17,0,240,216,202,202,202,216,240,131,152,15,198,198,213,239,0,18,43,58,58,58,43,18,0,239,213,198,131,4,3,26,4,4,4,3,226,156,30,100,3,100,226,156,30,128,2,0,12,0,32,0,0,0,25,32,1,15,14,1,2,2,17,1,1,2,1,1,1,2,1,1,2,1,128,13,28,228,0,17,40,54,54,40,17,240,216,202,202,216,14,226,20,30,198,198,213,0,18,43,58,58,43,18,239,213,7,6,1,2,2,18,4,4,4,128,5,236,20,226,156,30,100,6,20,0,236,100,226,156,30,128,2,0,12,0,32,0,0,0,25,32,1,15,14,1,2,2,17,1,1,2,1,1,1,2,1,1,2,1,14,30,236,226,0,17,40,54,54,40,17,240,216,202,202,216,14,28,228,0,198,198,213,0,18,43,58,58,43,18,239,213,7,6,1,2,2,18,4,4,4,6,236,0,20,226,156,30,100,6,236,20,0,100,226,156,30,128,2,0,12,0,32,0,0,0,25,32,1,15,14,1,2,2,18,1,2,1,1,1,2,1,1,2,1,1,14,30,0,226,17,40,54,54,40,17,239,216,202,202,216,239,14,228,28,0,198,213,0,18,43,58,58,43,18,239,213,198,7,6,1,2,2,18,4,4,4,6,236,0,20,226,156,30,100,6,20,236,0,100,226,156,30,128,2,0,12,0,32,0,0,0,25,32,1,15,14,1,2,2,18,1,1,2,1,1,2,1,2,1,1,1,14,30,226,0,239,216,202,202,216,239,17,40,54,54,40,17,128,13,228,28,58,43,18,239,213,198,198,213,0,18,43,58,7,6,1,2,2,18,4,4,4,6,236,20,0,30,100,226,156,128,5,20,236,156,30,100,226,128,2,0,12,0,46,0,0,0,25,32,1,0,7,28,28,228,228,28,28,228,228,144,14,239,216,202,202,202,216,239,0,17,40,54,54,54,40,17,131,151,15,58,58,43,18,0,239,213,198,198,198,213,239,0,18,43,58,131,8,7,1,2,2,2,18,4,4,4,7,24,44,211,231,30,100,226,156,131,3,156,30,100,226,128,2,0,12,0,148,32,0,0,196,0,1,96,95,0,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,48,47,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,47,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,47,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,13,250,243,6,128,63,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,30,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,63,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,31,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,240,240,250,7,16,16,0,250,128,2,0,12,0,37,0,0,0,28,32,1,0,156,14,239,216,202,202,202,216,239,0,17,40,54,54,54,40,17,131,155,15,58,58,43,18,0,239,213,198,198,198,213,239,0,18,43,58,131,8,7,1,3,3,3,19,4,4,4,7,18,39,238,217,30,100,226,156,7,39,238,217,18,156,30,100,226,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,14,0,0,0,16,32,1,6,5,13,3,1,2,3,1,5,25,54,25,231,202,231,5,198,26,58,58,230,198,4,3,13,3,3,3,3,234,206,23,50,3,50,234,206,23,128,2,0,12,0,37,0,0,0,22,32,1,0,148,14,239,216,202,202,202,216,239,0,17,40,54,54,54,40,17,131,147,15,198,198,213,239,0,18,43,58,58,58,43,18,0,239,213,198,131,6,5,20,5,1,3,1,1,128,4,70,53,235,203,186,5,70,235,203,186,203,235,128,2,0,12,0,22,0,0,0,16,32,1,0,140,8,202,202,216,239,0,17,40,54,54,131,141,6,18,43,58,58,58,43,18,132,4,3,13,5,1,2,3,70,235,203,186,128,2,186,203,0,0,0,2,0,12,0,22,32,0,0,15,32,1,6,5,14,1,2,2,1,1,5,239,216,202,54,40,17,5,198,213,0,239,213,198,4,3,14,1,2,1,3,21,53,70,186,1,70,53,129,0,128,2,0,12,0,22,0,0,0,19,32,1,0,136,8,54,54,40,17,0,239,216,202,202,131,137,6,18,43,58,58,58,43,18,132,6,5,2,6,1,5,1,2,129,3,186,21,53,70,130,2,186,203,0,128,2,0,12,0,22,0,0,0,20,32,1,0,132,8,202,202,216,239,0,17,40,54,54,135,133,6,239,213,198,198,198,213,239,136,6,5,4,1,5,1,2,3,128,4,70,235,203,186,0,129,1,70,53,129,0,128,2,0,12,0,14,0,0,0,14,0,1,0,133,3,239,216,202,202,131,132,3,58,58,43,18,132,133,3,21,53,70,70,131,132,3,186,186,203,235,132,0,128,2,0,12,0,13,0,0,0,13,0,1,0,3,54,54,40,17,137,128,3,18,43,58,58,136,3,186,186,203,235,137,128,3,235,203,186,186,136,0,128,2,0,12,0,14,0,0,0,14,0,1,0,129,3,17,40,54,54,135,128,3,198,198,213,239,136,129,3,235,203,186,186,135,128,3,70,70,53,21,136,0,128,2,0,12,0,14,0,0,0,14,0,1,0,132,3,202,202,216,239,132,133,3,239,213,198,198,131,132,3,70,70,53,21,132,133,3,21,53,70,70,131,0,128,2,0,12,0,12,0,0,0,12,0,1,0,132,2,90,0,166,131,131,2,166,0,90,132,132,2,166,0,90,131,131,2,90,0,166,132,0,128,2,0,12,0,12,0,0,0,12,0,1,0,135,2,90,0,166,131,134,2,166,0,90,132,135,2,166,0,90,131,134,2,90,0,166,132,0,128,2,0,12,0,12,0,0,0,12,0,1,0,135,2,90,0,166,131,134,2,166,0,90,132,135,2,166,0,90,131,134,2,90,0,166,132,0,128,2,0,12,0,12,0,0,0,12,0,1,0,135,2,90,0,166,131,134,2,166,0,90,132,135,2,166,0,90,131,134,2,90,0,166,132,0,128,2,0,12,0,12,0,0,0,12,0,1,0,135,2,166,0,90,131,134,2,90,0,166,132,135,2,90,0,166,131,134,2,166,0,90,132,0,128,2,0,12,0,12,0,0,0,21,0,1,0,136,2,166,0,90,131,135,2,90,0,166,132,128,2,20,0,236,132,2,90,0,166,131,2,20,0,236,132,2,166,0,90,132,128,2,0,12,0,18,0,0,0,18,0,1,0,9,50,0,50,206,0,206,0,103,0,153,131,133,2,136,0,120,132,9,226,0,226,30,0,30,0,186,0,70,131,133,2,70,0,186,132,0,128,2,0,12,0,20,0,0,0,20,0,1,0,131,0,201,129,1,55,55,129,0,201,131,132,1,196,196,129,1,60,60,132,131,0,70,129,1,186,186,129,0,70,131,132,1,70,70,129,1,186,186,132,0,128,2,0,12,0,6,0,0,0,6,0,1,2,1,5,2,1,56,200,1,206,60,1,186,70,1,70,186,128,2,0,12,0,6,0,0,0,6,0,1,2,1,5,2,1,56,200,1,196,60,1,186,70,1,70,186,128,2,0,12,0,6,0,0,0,6,0,1,2,1,5,2,1,56,200,1,196,60,1,146,110,1,110,146,128,2,0,12,0,36,0,0,0,28,32,1,0,145,5,26,56,56,56,56,26,129,5,231,200,200,200,200,231,131,143,3,196,196,196,228,129,5,28,60,60,60,60,28,129,1,228,196,131,8,7,16,1,3,1,3,1,3,1,7,70,186,186,186,186,70,70,70,7,70,70,70,186,186,186,186,70,0,128,2,0,12,0,6,0,0,0,6,0,1,2,1,9,2,1,56,200,1,196,60,1,146,110,1,110,146,128,2,0,12,0,98,0,0,0,98,0,1,48,47,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,47,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,47,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,13,251,243,6,47,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,47,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,240,7,16,250,128,2,0,12,0,11,0,0,0,11,0,1,6,5,0,2,2,2,7,2,131,1,56,200,5,30,226,30,226,196,60,131,1,146,110,5,206,246,10,50,110,146,128,2,0,12,0,11,0,0,0,11,0,1,6,5,0,2,2,2,7,2,5,226,30,226,30,60,196,131,1,56,200,5,50,10,246,206,146,110,131,1,146,110,128,2,0,12,0,21,0,0,0,21,0,1,10,9,0,2,3,2,1,2,3,2,6,2,129,1,30,226,129,3,30,226,56,200,1,30,226,129,1,30,226,129,1,196,60,129,1,25,35,129,3,221,231,146,110,1,221,231,129,1,25,35,129,1,110,146,128,2,0,12,0,36,0,0,0,40,0,1,0,3,243,203,5,45,129,3,216,40,40,216,133,3,200,56,56,200,131,5,53,13,211,251,40,216,131,1,216,40,131,3,196,196,60,60,131,128,10,20,0,236,40,40,60,40,216,236,236,236,131,3,110,146,146,110,131,11,236,0,20,0,40,60,40,40,196,196,216,176,131,3,110,110,146,146,131,0,128,2,0,12,0,39,0,0,0,40,0,1,0,8,13,211,251,53,0,216,40,0,216,129,0,40,131,3,56,56,200,200,131,4,53,251,211,13,40,129,3,216,0,40,216,132,3,196,60,60,196,131,11,16,36,16,252,232,232,212,232,56,36,36,36,131,3,146,146,110,110,131,11,236,0,20,0,40,40,40,60,196,176,216,196,131,3,110,146,146,110,131,128,2,0,12,0,63,0,0,0,69,0,1,0,4,45,243,203,5,40,129,5,216,211,251,53,13,40,129,0,216,129,4,40,216,0,40,216,132,3,200,56,56,200,131,17,251,53,13,211,0,40,216,0,251,211,13,53,0,216,40,0,40,216,129,0,40,129,0,216,131,3,196,196,60,60,131,23,20,0,236,0,80,60,60,40,236,0,20,0,216,196,196,176,60,60,80,40,196,216,176,196,131,3,110,146,146,110,131,128,15,20,0,236,90,110,70,90,0,236,0,20,90,70,110,90,166,64,255,126,4,166,166,166,166,166,64,255,126,131,3,110,110,146,146,131,0,128,2,0,12,0,6,0,0,0,6,0,1,2,1,5,2,1,56,200,1,196,60,1,216,40,1,40,216,128,2,0,12,0,6,0,0,0,6,0,1,2,1,9,2,1,56,200,1,196,60,1,146,110,1,110,146,128,2,0,12,0,6,0,0,0,6,0,1,2,1,9,2,1,56,200,1,60,196,1,146,110,1,146,110,128,2,0,12,0,6,0,0,0,6,0,1,2,1,8,2,1,56,200,1,60,196,1,146,110,1,146,110,128,2,0,12,0,6,0,0,0,6,0,1,2,1,8,2,1,200,56,1,196,60,1,110,146,1,110,146,128,2,0,12,0,9,0,0,0,9,0,1,4,3,0,2,7,2,3,228,28,200,56,129,1,196,60,3,40,216,110,146,129,1,110,146,128,2,0,12,0,12,0,0,0,12,0,1,5,4,1,2,2,6,2,4,235,27,227,200,56,4,226,20,30,196,60,128,3,236,20,110,146,4,20,0,236,110,146,0,128,2,0,12,0,12,0,0,0,12,0,1,5,4,1,2,2,6,2,4,227,27,235,56,200,4,226,236,30,196,60,4,20,236,0,146,110,4,20,0,236,110,146,0,128,2,0,12,0,12,0,0,0,12,0,1,5,4,1,2,2,6,2,4,21,229,29,56,200,4,30,236,226,60,196,128,3,20,236,146,110,4,236,0,20,146,110,0,128,2,0,12,0,12,0,0,0,12,0,1,5,4,1,2,2,6,2,4,29,229,21,200,56,4,30,20,226,60,196,4,236,20,0,110,146,4,236,0,20,146,110,0,128,2,0,12,0,6,0,0,0,6,0,1,2,1,5,2,1,56,200,1,196,60,1,216,40,1,40,216,128,1,0,8,0,6,0,0,2,1,5,2,1,56,200,1,196,60,128,2,0,12,0,14,0,0,0,17,0,1,0,130,0,186,129,2,70,70,186,131,131,1,186,186,134,130,5,80,30,216,176,225,33,131,131,4,80,80,0,178,176,131,128,2,0,12,0,16,0,0,0,18,0,1,0,130,0,186,131,0,186,131,130,5,255,185,185,69,69,255,131,130,5,60,230,156,158,242,60,131,130,5,38,77,33,225,173,224,131,0,128,2,0,12,0,14,0,0,0,18,0,1,0,130,1,70,70,129,1,186,186,131,132,1,70,70,133,130,5,225,176,216,30,80,33,131,130,5,98,20,196,196,20,100,131,0,128,2,0,12,0,14,0,0,0,18,0,1,0,130,1,70,70,135,130,5,255,255,69,69,185,185,131,130,5,196,196,14,98,100,26,131,130,5,38,224,173,225,33,77,131,0,128,2,0,12,0,14,0,0,0,17,0,1,0,142,0,186,129,2,70,70,186,131,143,1,186,186,134,142,5,80,30,216,176,225,33,131,143,4,80,80,0,178,176,131,128,2,0,12,0,14,0,0,0,17,0,1,0,133,0,186,129,2,70,70,186,131,134,1,186,186,134,133,5,80,30,216,176,225,33,131,134,4,80,80,0,178,176,131,128,2,0,12,0,12,0,0,0,17,0,1,0,133,3,70,70,186,186,133,137,1,186,186,131,133,5,176,223,31,80,40,226,131,134,4,176,178,0,80,80,131,128,2,0,12,0,18,0,0,0,14,0,1,0,130,5,196,0,57,57,0,196,131,130,5,236,211,232,24,45,20,131,130,0,60,131,0,60,131,131,3,50,50,206,206,132,0,128,2,0,12,0,15,0,0,0,17,0,1,0,130,4,60,60,0,246,246,132,132,3,45,39,217,211,131,130,4,196,196,0,47,47,132,130,5,20,236,206,221,35,50,131,0,128,2,0,12,0,18,0,0,0,14,0,1,0,130,5,170,206,57,91,7,252,131,130,5,229,196,196,220,110,110,131,130,0,50,129,2,206,206,50,131,131,1,50,50,134,0,128,2,0,12,0,18,0,0,0,14,0,1,0,130,5,196,220,110,110,229,196,131,130,5,199,165,249,4,86,50,131,130,0,50,131,0,50,131,131,3,50,50,206,206,132,0,128,2,0,12,0,18,0,0,0,14,0,1,0,130,5,7,91,57,206,170,252,131,130,5,146,36,60,60,27,146,131,130,1,206,206,129,1,50,50,131,132,1,206,206,133,0,128,2,0,12,0,18,0,0,0,12,0,1,0,130,5,60,60,27,146,146,36,131,130,5,199,50,86,4,249,165,131,130,1,206,206,135,132,3,206,206,50,50,131,0,128,2,0,12,0,24,0,0,0,18,0,1,0,130,3,82,56,56,50,65,255,126,255,102,131,130,65,255,94,255,116,3,50,60,60,74,131,130,2,80,176,176,129,0,80,131,130,0,20,129,2,176,176,20,131,0,128,2,0,12,0,26,0,0,0,16,0,1,0,130,0,82,65,255,102,255,126,2,50,56,56,131,130,64,0,162,3,182,196,196,206,64,0,140,131,130,1,80,80,129,1,176,176,131,130,3,236,236,80,80,133,0,128,2,0,12,0,24,0,0,0,18,0,1,0,130,3,174,200,200,206,65,0,130,0,154,131,130,65,0,162,0,140,3,206,196,196,182,131,130,2,176,80,80,129,0,176,131,130,0,236,129,2,80,80,236,131,0,128,2,0,12,0,26,0,0,0,16,0,1,0,130,0,174,65,0,154,0,130,2,206,200,200,131,130,64,255,94,3,74,60,60,50,64,255,116,131,130,1,176,176,129,1,80,80,131,130,3,20,20,176,176,133,0,128,2,0,12,0,30,0,0,0,18,0,1,8,7,1,2,2,2,2,2,2,2,1,197,197,65,255,79,0,177,3,59,59,59,197,0,59,64,0,177,128,64,0,177,1,59,0,65,255,79,255,197,7,35,35,105,151,221,221,221,35,7,221,151,0,151,221,0,105,35,128,2,0,12,0,23,0,0,0,14,0,1,6,5,1,2,2,2,2,2,1,197,59,65,255,79,0,177,1,59,59,0,197,64,255,79,128,64,0,177,1,59,0,5,35,221,105,151,221,221,5,35,105,0,151,221,0,0,128,2,0,12,0,22,0,0,0,14,0,1,6,5,1,2,2,2,2,2,64,0,177,3,197,59,197,197,64,255,79,64,255,79,2,197,0,59,64,0,177,128,5,151,35,221,35,35,105,5,105,35,0,221,151,0,128,2,0,12,0,14,0,0,0,10,0,1,4,3,1,2,2,2,3,59,197,59,197,64,255,79,1,197,59,64,0,177,3,221,35,221,35,3,105,35,221,151,128,2,0,12,0,30,0,0,0,18,0,1,8,7,1,2,2,2,2,2,2,2,0,197,64,255,79,3,197,59,197,59,65,0,177,0,59,128,64,255,79,1,197,59,65,0,177,255,79,128,0,197,7,35,105,35,221,35,221,151,221,128,6,105,35,221,151,105,0,35,128,2,0,12,0,23,0,0,0,14,0,1,6,5,1,2,2,2,2,2,1,59,197,67,255,79,0,59,0,177,0,59,1,59,0,65,0,177,255,79,128,0,197,5,221,35,105,221,151,221,5,221,0,151,105,0,35,0,128,2,0,12,0,24,0,0,0,14,0,1,6,5,1,2,2,2,2,2,64,0,177,2,59,197,197,65,255,79,255,197,128,0,59,64,0,177,128,65,255,79,255,197,5,151,221,35,35,105,35,128,4,221,151,0,105,35,128,2,0,12,0,16,32,0,0,11,0,1,0,4,3,1,2,2,2,0,197,66,255,79,0,177,0,59,131,7,35,35,105,105,151,151,221,221,131,139,128,2,0,12,0,45,0,0,0,26,0,1,12,11,1,2,2,2,2,2,2,2,2,2,2,2,0,197,66,255,79,255,197,0,177,3,59,59,197,197,67,255,79,0,59,0,177,0,59,128,66,255,79,255,197,0,177,2,59,0,59,64,0,177,128,64,255,79,128,0,197,11,35,105,35,151,221,221,35,35,105,221,151,221,128,10,105,35,151,221,0,221,151,0,105,0,35,0,128,2,0,12,0,28,0,0,0,16,0,1,8,7,1,2,2,2,2,2,2,2,0,59,66,0,177,0,59,0,177,2,59,59,197,64,255,79,64,255,79,128,0,197,64,0,177,0,59,130,7,221,151,221,151,221,221,35,105,4,105,0,35,151,221,130,128,2,0,12,0,27,0,0,0,16,0,1,8,7,1,2,2,2,2,2,2,2,0,197,64,255,79,2,197,197,197,66,255,79,0,177,0,59,128,64,255,79,1,197,59,64,0,177,130,7,35,105,35,35,35,105,151,221,128,3,105,35,221,151,130,0,128,2,0,12,0,14,0,0,0,10,0,1,4,3,1,2,2,2,64,0,177,1,59,197,64,255,79,3,59,197,59,0,3,151,221,35,105,3,221,35,221,0,128,2,0,12,0,11,0,0,0,8,0,1,3,2,1,2,2,66,0,177,0,59,255,79,2,59,197,0,2,151,221,105,2,221,35,0,128,2,0,12,0,11,0,0,0,8,0,1,3,2,0,2,2,66,0,177,255,197,255,79,128,1,197,59,2,151,35,105,128,1,35,221,128,2,0,12,0,10,0,0,0,10,0,1,4,3,1,2,2,2,3,118,59,197,138,3,59,197,59,0,3,186,221,35,70,3,221,35,221,0,128,2,0,12,0,8,0,0,0,8,0,1,3,2,1,2,2,2,118,59,138,2,59,197,0,2,186,221,70,2,221,35,0,0,128,2,0,12,0,12,0,0,0,12,0,1,5,4,0,2,2,2,2,4,118,59,59,197,138,128,3,59,197,0,197,4,186,221,221,35,70,128,3,221,35,0,35,0,128,2,0,12,0,8,0,0,0,8,0,1,3,2,1,2,2,2,118,197,138,2,197,59,0,2,186,35,70,2,35,221,0,0,128,2,0,12,0,12,0,0,0,12,0,1,5,4,0,2,2,2,2,4,118,59,197,197,138,128,3,197,0,197,59,4,186,221,35,35,70,128,3,35,0,35,221,0,128,2,0,12,0,14,0,0,0,14,0,1,6,5,1,2,2,2,2,2,5,118,59,59,197,197,138,5,59,197,0,197,59,0,5,186,221,221,35,35,70,5,221,35,0,35,221,0,128,2,0,12,0,10,0,0,0,10,0,1,4,3,0,2,2,2,3,59,59,197,197,128,2,118,138,118,3,221,221,35,35,128,2,186,70,186,128,2,0,12,0,8,0,0,0,8,0,1,3,2,0,2,2,2,59,59,197,128,1,118,138,2,221,221,35,128,1,186,70,0,128,2,0,12,0,12,0,0,0,12,0,1,5,4,0,2,2,2,1,4,59,59,118,138,138,128,3,118,138,0,118,4,221,221,186,70,70,128,3,186,70,0,186,0,128,2,0,12,0,8,0,0,0,8,0,1,3,2,0,2,2,2,59,197,197,128,1,138,118,2,221,35,35,128,1,70,186,0,128,2,0,12,0,12,0,0,0,12,0,1,5,4,0,2,2,2,2,4,59,118,138,197,197,128,3,118,0,138,118,4,221,186,70,35,35,128,3,186,0,70,186,0,128,2,0,12,0,14,0,0,0,14,0,1,6,5,1,2,2,2,2,2,5,59,59,118,138,197,197,5,118,138,0,138,118,0,5,221,221,186,70,35,35,5,186,70,0,70,186,0,128,2,0,12,0,19,0,0,0,14,0,1,6,5,0,2,2,2,3,2,5,59,59,197,197,59,197,128,68,0,177,0,59,0,177,255,79,255,197,5,221,221,35,35,221,35,128,4,151,221,151,105,35,0,128,2,0,12,0,10,0,0,0,8,0,1,3,2,0,1,7,2,59,59,197,128,65,0,177,255,79,2,221,221,35,128,1,151,105,0,128,2,0,12,0,10,0,0,0,8,0,1,3,2,0,2,6,2,59,197,197,128,65,255,79,0,177,2,221,35,35,128,1,105,151,0,128,2,0,12,0,11,0,0,0,11,0,1,0,139,7,118,138,138,118,118,138,138,118,131,139,7,186,70,70,186,186,70,70,186,131,0,128,2,0,12,0,11,0,0,0,11,0,1,0,7,118,118,138,138,118,118,138,138,131,139,7,186,186,70,70,186,186,70,70,131,139,0,128,2,0,12,0,6,0,0,0,6,0,1,2,1,1,2,1,118,138,1,197,0,1,186,70,1,35,0,128,2,0,12,0,10,0,0,0,10,0,1,4,3,1,2,2,2,3,118,59,197,138,3,118,138,118,0,3,186,221,35,70,3,186,70,186,0,128,2,0,12,0,8,0,0,0,8,0,1,3,2,1,2,2,2,118,59,138,2,118,138,0,2,186,221,70,2,186,70,0,0,128,2,0,12,0,8,0,0,0,8,0,1,3,2,1,2,2,2,118,197,138,2,138,118,0,2,186,35,70,2,70,186,0,0,128,2,0,12,0,6,0,0,0,6,0,1,2,1,1,2,1,59,197,1,138,118,1,221,35,1,70,186,128,2,0,12,0,6,0,0,0,6,0,1,2,1,1,2,1,59,197,1,138,118,1,221,35,1,70,186,128,2,0,12,0,6,0,0,0,6,0,1,2,1,1,6,1,59,197,1,138,118,1,221,35,1,70,186,128,2,0,12,0,19,0,0,0,19,0,1,0,147,15,118,138,138,118,118,138,138,118,118,138,138,118,118,138,138,118,131,147,15,186,70,70,186,186,70,70,186,186,70,70,186,186,70,70,186,131,0,128,2,0,12,0,19,0,0,0,19,0,1,0,15,118,118,138,138,118,118,138,138,118,118,138,138,118,118,138,138,131,147,15,186,186,70,70,186,186,70,70,186,186,70,70,186,186,70,70,131,147,0,128,2,0,12,0,6,0,0,0,6,0,1,2,1,1,2,1,59,197,1,138,118,1,221,35,1,70,186,128,2,0,12,0,15,0,0,0,15,0,1,0,143,11,118,138,138,118,118,138,138,118,118,138,138,118,131,143,11,186,70,70,186,186,70,70,186,186,70,70,186,131,0,128,2,0,12,0,15,0,0,0,15,0,1,0,11,118,118,138,138,118,118,138,138,118,118,138,138,131,143,11,186,186,70,70,186,186,70,70,186,186,70,70,131,143,0,128,2,0,12,0,6,0,0,0,6,0,1,2,1,1,2,1,118,138,128,0,59,1,186,70,128,0,221,128,2,0,12,0,10,0,0,0,10,0,1,4,3,1,2,2,2,3,59,118,138,197,3,138,0,138,118,3,221,186,70,35,3,70,0,70,186,128,2,0,12,0,8,0,0,0,8,0,1,3,2,1,2,2,2,59,118,138,2,138,0,118,2,221,186,70,2,70,0,186,0,128,2,0,12,0,10,0,0,0,10,0,1,4,3,0,2,2,2,3,59,118,138,197,128,2,59,0,59,3,221,186,70,35,128,2,221,0,221,128,2,0,12,0,8,0,0,0,8,0,1,3,2,1,2,2,2,118,138,197,128,1,138,118,2,186,70,35,128,1,70,186,0,128,2,0,12,0,7,0,0,0,7,0,1,0,3,118,118,138,138,131,135,3,186,186,70,70,131,135,0,128,2,0,12,0,14,0,0,0,14,0,1,6,5,1,2,2,2,2,2,5,118,59,118,138,197,138,5,118,138,0,138,118,0,5,186,221,186,70,35,70,5,186,70,0,70,186,0,128,2,0,12,0,9,0,0,0,9,0,1,4,3,1,2,2,2,3,118,59,118,138,1,118,138,129,3,186,221,186,70,1,186,70,129,128,2,0,12,0,10,0,0,0,10,0,1,4,3,1,2,2,2,3,118,138,197,138,128,2,138,118,0,3,186,70,35,70,128,2,70,186,0,128,2,0,12,0,14,0,0,0,14,0,1,6,5,1,2,2,3,3,2,5,118,59,59,138,197,138,5,118,138,0,138,59,0,5,186,221,221,70,35,70,5,186,70,0,70,221,0,128,2,0,12,0,10,0,0,0,10,0,1,4,3,0,2,2,4,3,59,59,197,197,128,2,118,138,59,3,221,221,35,35,128,2,186,70,221,128,2,0,12,0,10,0,0,0,10,0,1,4,3,0,2,2,1,3,59,59,197,197,3,118,138,0,197,3,221,221,35,35,3,186,70,0,35,128,2,0,12,0,14,0,0,0,14,0,1,6,5,0,2,2,2,2,2,5,59,59,59,197,197,197,128,4,118,138,0,197,59,5,221,221,221,35,35,35,128,4,186,70,0,35,221,128,2,0,12,0,12,0,0,0,12,0,1,5,4,1,2,2,2,2,4,118,59,118,197,138,4,59,197,138,118,0,4,186,221,186,35,70,4,221,35,70,186,0,0,128,2,0,12,0,12,0,0,0,12,0,1,5,4,1,2,2,2,2,4,118,59,118,138,197,4,59,197,0,138,118,4,186,221,186,70,35,4,221,35,0,70,186,0,128,2,0,12,0,14,0,0,0,14,0,1,6,5,1,2,2,2,2,2,5,118,59,118,138,197,138,5,59,197,0,138,118,0,5,186,221,186,70,35,70,5,221,35,0,70,186,0,128,2,0,12,0,14,0,0,0,14,0,1,6,5,0,2,2,2,2,3,5,59,59,118,138,197,138,128,4,118,138,0,197,118,5,221,221,186,70,35,70,128,4,186,70,0,35,186,0,2,0,12,0,19,32,0,0,25,32,1,5,4,1,5,2,1,5,4,59,0,59,0,197,128,3,59,197,197,0,7,6,2,1,1,2,2,1,5,6,221,227,236,0,221,0,35,6,249,236,227,221,35,35,0,128,2,0,12,0,19,32,0,0,16,0,1,7,6,1,5,2,1,2,1,2,5,4,1,5,2,1,5,4,59,0,197,0,197,128,3,197,59,59,0,6,221,0,35,0,20,29,35,128,5,35,221,221,227,236,0,128,2,0,12,0,19,32,0,0,16,0,1,7,6,1,1,2,1,2,3,5,5,4,1,1,5,3,5,4,59,0,59,197,0,1,197,197,129,0,59,6,221,0,236,227,221,35,0,3,35,35,29,20,129,0,221,0,2,0,12,0,19,32,0,0,25,32,1,5,4,0,5,3,5,2,128,3,59,197,0,197,0,59,129,1,197,59,7,6,0,5,4,1,1,2,2,128,5,221,35,29,20,0,35,6,221,0,7,20,29,35,221,128,2,0,12,0,34,0,0,0,34,0,1,0,129,0,70,129,2,186,0,70,129,0,186,129,2,70,0,186,131,128,2,143,0,113,129,0,143,129,2,113,0,143,129,0,113,132,129,0,215,129,2,41,0,215,129,0,41,129,2,215,0,41,131,128,2,66,0,190,129,0,66,129,2,190,0,66,129,0,190,132,0,128,2,0,12,0,13,0,0,0,13,0,1,0,0,70,129,0,186,133,128,0,113,129,0,143,132,0,215,129,0,41,133,128,0,190,129,0,66,132,0,128,2,0,12,0,14,0,0,0,14,0,1,0,129,0,70,129,0,186,131,128,0,143,129,0,113,132,129,0,215,129,0,41,131,128,0,66,129,0,190,132,0,128,2,0,12,0,11,0,0,0,11,0,1,0,139,7,59,197,197,59,59,197,197,59,131,139,7,221,35,35,221,221,35,35,221,131,0,128,2,0,12,0,11,0,0,0,11,0,1,0,7,59,59,197,197,59,59,197,197,131,139,7,221,221,35,35,221,221,35,35,131,139,0,128,2,0,12,0,6,0,0,0,6,0,1,2,1,1,2,1,59,197,1,197,0,1,221,35,1,35,0,128,2,0,12,0,10,0,0,0,10,0,1,4,3,0,2,2,2,3,59,59,197,197,128,2,59,197,59,3,221,221,35,35,128,2,221,35,221,128,2,0,12,0,8,0,0,0,8,0,1,3,2,0,2,2,2,59,59,197,128,1,59,197,2,221,221,35,128,1,221,35,0,128,2,0,12,0,8,0,0,0,8,0,1,3,2,0,2,2,2,59,197,197,128,1,197,59,2,221,35,35,128,1,35,221,0,128,2,0,12,0,6,0,0,0,6,0,1,2,1,1,2,1,59,197,1,197,59,1,221,35,1,35,221,128,2,0,12,0,6,0,0,0,6,0,1,2,1,1,2,1,59,197,1,197,59,1,221,35,1,35,221,128,2,0,12,0,6,0,0,0,6,0,1,2,1,5,2,1,59,197,1,138,118,1,221,35,1,70,186,128,2,0,12,0,19,0,0,0,19,0,1,0,147,15,59,197,197,59,59,197,197,59,59,197,197,59,59,197,197,59,131,147,15,221,35,35,221,221,35,35,221,221,35,35,221,221,35,35,221,131,0,128,2,0,12,0,19,0,0,0,19,0,1,0,15,59,59,197,197,59,59,197,197,59,59,197,197,59,59,197,197,131,147,15,221,221,35,35,221,221,35,35,221,221,35,35,221,221,35,35,131,147,0,128,2,0,12,0,6,0,0,0,6,0,1,2,1,1,2,1,59,197,1,197,59,1,221,35,1,35,221,128,2,0,12,0,15,0,0,0,15,0,1,0,143,11,59,197,197,59,59,197,197,59,59,197,197,59,131,143,11,221,35,35,221,221,35,35,221,221,35,35,221,131,0,128,2,0,12,0,15,0,0,0,15,0,1,0,11,59,59,197,197,59,59,197,197,59,59,197,197,131,143,11,221,221,35,35,221,221,35,35,221,221,35,35,131,143,0,128,2,0,12,0,6,0,0,0,6,0,1,2,1,1,2,1,59,197,128,0,59,1,221,35,128,0,221,128,2,0,12,0,10,0,0,0,10,0,1,4,3,0,2,2,2,3,118,59,197,138,128,2,197,0,197,3,186,221,35,70,128,2,35,0,35,128,2,0,12,0,10,0,0,0,10,0,1,4,3,0,2,2,2,3,59,59,197,197,3,59,197,0,197,3,221,221,35,35,3,221,35,0,35,128,2,0,12,0,8,0,0,0,8,0,1,3,2,0,2,2,2,59,59,197,2,59,197,0,2,221,221,35,2,221,35,0,0,128,2,0,12,0,8,0,0,0,8,0,1,3,2,0,2,1,2,59,197,197,2,59,0,197,2,221,35,35,2,221,0,35,0,128,2,0,12,0,7,0,0,0,7,0,1,0,3,59,59,197,197,131,135,3,221,221,35,35,131,135,0,128,2,0,12,0,14,0,0,0,14,0,1,6,5,0,2,2,2,2,2,5,59,59,59,197,197,197,128,4,59,197,0,197,59,5,221,221,221,35,35,35,128,4,221,35,0,35,221,128,2,0,12,0,10,0,0,0,10,0,1,4,3,0,2,2,2,3,59,59,59,197,128,2,59,197,0,3,221,221,221,35,128,2,221,35,0,128,2,0,12,0,9,0,0,0,9,0,1,4,3,0,2,2,2,3,59,197,197,197,129,1,197,59,3,221,35,35,35,129,1,35,221,128,2,0,12,0,14,0,0,0,14,0,1,6,5,0,2,3,3,2,2,5,118,59,118,197,197,138,128,4,59,138,0,138,118,5,186,221,186,35,35,70,128,4,221,70,0,70,186,128,2,0,12,0,10,0,0,0,10,0,1,4,3,0,1,5,2,3,59,59,197,197,128,2,59,138,118,3,221,221,35,35,128,2,221,70,186,128,2,0,12,0,10,0,0,0,10,0,1,4,3,0,4,2,2,3,59,59,197,197,3,118,197,0,138,3,221,221,35,35,3,186,35,0,70,128,2,0,12,0,14,0,0,0,14,0,1,6,5,0,2,2,2,2,2,5,59,59,59,197,197,197,128,4,59,197,0,138,118,5,221,221,221,35,35,35,128,4,221,35,0,70,186,128,2,0,12,0,12,0,0,0,12,0,1,5,4,1,2,2,2,2,4,118,59,138,197,138,4,118,138,197,59,0,4,186,221,70,35,70,4,186,70,35,221,0,0,128,2,0,12,0,12,0,0,0,12,0,1,5,4,1,2,2,2,2,4,59,118,138,197,138,4,138,0,197,59,118,4,221,186,70,35,70,4,70,0,35,221,186,0,128,2,0,12,0,14,0,0,0,14,0,1,6,5,1,2,2,2,2,2,5,118,59,118,138,197,138,5,118,138,0,197,59,0,5,186,221,186,70,35,70,5,186,70,0,35,221,0,128,2,0,12,0,14,0,0,0,14,0,1,6,5,2,3,2,2,2,2,5,118,59,118,138,197,197,5,118,197,0,138,118,0,5,186,221,186,70,35,35,5,186,35,0,70,186,0,128,2,0,12,0,14,0,0,0,10,0,1,4,3,1,2,6,2,0,59,66,0,177,255,79,255,197,3,197,0,197,59,3,221,151,105,35,3,35,0,35,221,128,2,0,12,0,11,0,0,0,8,0,1,3,2,0,2,6,0,59,65,0,177,255,79,2,59,197,0,2,221,151,105,2,221,35,0,128,2,0,12,0,11,0,0,0,8,0,1,3,2,1,6,2,66,0,177,255,79,255,197,128,1,197,59,2,151,105,35,128,1,35,221,128,2,0,12,0,14,0,0,0,14,0,1,6,5,1,2,2,2,2,2,5,59,59,118,138,197,197,5,59,197,0,197,59,0,5,221,221,186,70,35,35,5,221,35,0,35,221,0,128,2,0,12,0,10,0,0,0,10,0,1,4,3,1,2,2,2,3,59,118,138,197,3,197,0,197,59,3,221,186,70,35,3,35,0,35,221,128,2,0,12,0,12,0,0,0,12,0,1,5,4,0,2,2,2,1,4,59,59,118,138,138,128,3,59,197,0,59,4,221,221,186,70,70,128,3,221,35,0,221,0,128,2,0,12,0,8,0,0,0,8,0,1,3,2,1,2,2,2,59,118,138,2,197,0,59,2,221,186,70,2,35,0,221,0,128,2,0,12,0,12,0,0,0,12,0,1,5,4,0,2,2,2,2,4,59,118,138,197,197,128,3,59,0,197,59,4,221,186,70,35,35,128,3,221,0,35,221,0,128,2,0,12,0,8,0,0,0,8,0,1,3,2,1,2,2,2,118,138,197,128,1,197,59,2,186,70,35,128,1,35,221,0,128,2,0,12,0,14,0,0,0,14,0,1,6,5,1,2,2,2,2,2,5,118,59,59,197,197,138,5,118,138,0,138,118,0,5,186,221,221,35,35,70,5,186,70,0,70,186,0,128,2,0,12,0,10,0,0,0,10,0,1,4,3,0,2,2,2,3,59,59,197,197,3,118,138,0,138,3,221,221,35,35,3,186,70,0,70,128,2,0,12,0,12,0,0,0,12,0,1,5,4,0,2,2,2,2,4,118,59,59,197,138,128,3,118,138,0,138,4,186,221,221,35,70,128,3,186,70,0,70,0,128,2,0,12,0,8,0,0,0,8,0,1,3,2,0,2,2,2,59,59,197,2,118,138,0,2,221,221,35,2,186,70,0,0,128,2,0,12,0,12,0,0,0,12,0,1,5,4,0,2,2,2,2,4,118,59,197,197,138,128,3,138,0,138,118,4,186,221,35,35,70,128,3,70,0,70,186,0,128,2,0,12,0,8,0,0,0,8,0,1,3,2,0,2,1,2,59,197,197,2,118,0,138,2,221,35,35,2,186,0,70,0,128,2,0,12,0,20,0,0,0,14,0,1,6,5,0,2,2,2,3,2,5,59,59,197,197,59,197,0,197,64,255,79,128,66,255,79,0,59,0,177,5,221,221,35,35,221,35,5,35,105,0,105,221,151,128,2,0,12,0,10,0,0,0,8,0,1,3,2,0,6,2,2,59,59,197,65,0,177,255,79,128,2,221,221,35,2,151,105,0,0,128,2,0,12,0,11,0,0,0,8,0,1,3,2,0,2,1,2,59,197,197,64,0,177,128,64,255,79,2,221,35,35,2,151,0,105,128,2,0,12,0,20,0,0,0,14,0,1,6,5,1,2,2,6,2,2,69,0,177,0,59,0,177,255,79,255,197,255,79,5,59,197,0,197,59,0,5,151,221,151,105,35,105,5,221,35,0,35,221,0,128,2,0,12,0,17,0,0,0,11,0,1,6,5,1,2,2,2,2,2,66,0,177,0,59,0,177,1,59,197,64,255,79,1,59,197,131,5,151,221,151,221,35,105,1,221,35,131,128,2,0,12,0,18,0,0,0,12,0,1,6,5,1,2,2,2,2,2,0,197,68,255,79,255,197,255,79,0,177,0,59,128,1,197,59,130,5,35,105,35,105,151,221,128,1,35,221,130,128,2,0,12,0,14,0,0,0,14,0,1,6,5,1,2,2,2,2,2,5,118,59,118,138,197,138,5,59,197,0,197,59,0,5,186,221,186,70,35,70,5,221,35,0,35,221,0,128,2,0,12,0,9,0,0,0,9,0,1,4,3,1,2,2,2,3,118,59,118,138,1,59,197,129,3,186,221,186,70,1,221,35,129,128,2,0,12,0,10,0,0,0,10,0,1,4,3,1,2,2,2,3,118,138,197,138,128,2,197,59,0,3,186,70,35,70,128,2,35,221,0,128,2,0,12,0,14,0,0,0,14,0,1,6,5,0,2,2,2,2,2,5,59,59,59,197,197,197,128,4,118,138,0,138,118,5,221,221,221,35,35,35,128,4,186,70,0,70,186,128,2,0,12,0,10,0,0,0,10,0,1,4,3,0,2,2,2,3,59,59,59,197,128,2,118,138,0,3,221,221,221,35,128,2,186,70,0,128,2,0,12,0,9,0,0,0,9,0,1,4,3,0,2,2,2,3,59,197,197,197,129,1,138,118,3,221,35,35,35,129,1,70,186,128,2,0,12,0,19,0,0,0,14,0,1,6,5,0,2,6,2,2,6,5,59,59,59,197,197,197,128,65,0,177,255,79,128,65,255,79,0,177,5,221,221,221,35,35,35,128,4,151,105,0,105,151,0,128,2,0,12,0,12,0,0,0,10,0,1,4,3,0,2,6,2,3,59,59,59,197,128,65,0,177,255,79,128,3,221,221,221,35,128,2,151,105,0,128,2,0,12,0,11,0,0,0,9,0,1,4,3,0,2,2,6,3,59,197,197,197,129,65,255,79,0,177,3,221,35,35,35,129,1,105,151,128,2,0,12,0,126,0,0,0,109,0,1,0,49,56,48,36,14,246,1,20,33,33,24,190,194,206,221,237,246,241,233,228,224,222,0,5,10,12,228,240,254,5,17,30,30,30,28,26,24,24,24,11,0,3,7,7,7,7,7,247,248,250,253,134,11,211,50,40,20,12,248,242,41,36,26,20,232,131,20,20,35,56,73,80,77,61,39,9,246,226,230,240,247,247,241,239,233,232,237,246,130,11,1,188,179,171,171,171,184,196,204,217,228,243,132,7,255,253,253,253,253,5,3,1,135,1,80,40,130,6,6,10,91,95,100,100,100,131,19,236,235,203,183,196,240,19,21,6,0,20,13,13,17,12,0,226,212,226,250,133,14,227,193,176,167,156,156,156,180,212,236,236,236,236,236,245,132,11,20,21,23,27,30,25,20,20,20,15,6,40,133,4,236,240,251,0,28,131,128,19,235,239,1,0,245,239,233,208,176,0,34,52,44,29,30,36,31,29,48,80,131,10,70,96,120,120,120,110,100,85,67,48,21,132,3,6,10,7,2,146,4,226,220,216,216,216,131,0,2,0,12,0,82,32,0,0,43,32,1,26,25,17,3,6,1,1,2,2,3,3,3,2,1,1,1,1,4,1,1,2,1,1,1,2,3,3,3,25,13,29,230,227,227,244,15,33,241,223,0,11,29,38,38,0,243,225,214,214,225,243,15,33,241,223,25,14,242,242,244,248,14,33,241,223,15,212,212,223,242,0,44,44,33,0,242,223,212,33,241,223,15,13,12,16,16,3,3,3,3,4,4,4,4,3,3,3,128,11,14,6,26,34,244,216,12,40,230,222,242,250,12,10,212,232,240,220,40,244,216,12,212,232,240,220,0,0,2,0,12,0,46,32,0,0,58,32,1,14,13,17,2,1,5,4,1,2,3,3,3,3,3,3,3,13,244,227,227,17,29,13,241,223,15,33,241,223,15,33,13,14,248,244,242,2,14,33,241,223,15,33,241,223,15,18,17,16,2,2,1,3,1,1,2,1,1,2,3,3,3,3,3,3,3,17,255,32,32,28,0,237,231,224,224,240,6,14,250,242,6,14,250,242,17,240,253,13,15,15,15,15,9,253,240,242,6,14,250,242,6,14,250,128,2,0,12,0,89,0,0,0,93,32,1,0,139,7,245,11,11,244,16,16,240,240,132,18,25,54,54,54,25,0,231,202,202,202,231,12,12,245,245,12,12,245,246,131,7,16,16,240,240,244,11,11,245,131,139,43,11,244,245,11,0,3,3,255,16,240,240,16,198,198,230,0,26,58,58,58,26,0,230,198,11,11,244,244,11,11,245,244,16,240,240,16,3,255,0,3,11,245,245,12,131,30,29,4,6,2,1,1,1,2,2,2,2,2,3,1,5,2,1,1,1,1,1,1,1,2,2,2,2,1,1,1,1,29,236,20,14,214,227,28,216,40,236,0,234,206,234,50,228,214,14,29,243,228,29,43,0,20,216,40,28,227,242,42,129,27,214,14,28,227,0,236,40,216,60,229,196,27,228,241,42,28,213,228,28,14,40,216,20,0,228,28,43,242,0,128,2,0,12,0,75,0,0,0,41,32,1,0,128,34,15,24,24,24,24,24,15,0,242,231,232,232,232,231,242,24,24,232,232,50,50,206,206,0,38,100,100,100,38,0,218,156,156,156,218,131,6,40,40,42,34,20,7,255,130,25,255,7,20,34,42,40,50,206,206,50,0,40,40,0,198,198,248,20,48,98,98,98,48,20,248,198,131,14,13,1,1,3,1,1,6,4,2,2,2,2,2,4,2,13,250,240,236,240,250,20,236,20,218,38,232,206,24,50,133,1,30,226,129,3,75,0,181,0,0,0,2,0,12,0,90,32,0,0,90,32,1,26,25,4,6,3,1,1,4,2,1,2,1,1,1,2,1,1,1,1,1,2,2,2,1,1,1,1,1,20,24,0,66,124,124,214,156,156,228,35,104,14,62,62,33,0,251,0,232,232,232,65,0,139,0,132,2,117,101,106,129,9,158,208,0,98,0,208,70,251,62,102,68,0,130,0,130,0,140,0,140,0,154,130,5,24,26,41,65,86,86,27,26,1,3,1,2,3,1,2,2,4,2,3,1,1,1,1,1,1,1,1,1,1,4,2,1,1,1,2,22,246,236,246,10,20,10,232,206,24,50,216,156,232,36,196,196,196,173,156,156,0,156,0,67,255,96,255,96,255,96,255,96,133,8,75,0,181,0,196,0,38,234,156,68,255,96,255,97,255,103,255,106,255,106,130,3,166,166,178,196,0,2,0,12,0,26,32,0,0,18,32,1,11,10,0,1,3,1,5,2,1,2,2,3,2,10,30,26,20,10,236,226,216,206,50,40,216,138,7,6,4,3,5,3,2,3,2,6,216,19,40,40,216,236,20,134,0,2,0,12,0,94,32,0,0,79,32,1,30,29,1,1,2,3,2,1,2,4,2,1,1,1,1,2,2,3,1,4,2,3,2,1,2,2,2,1,1,1,1,4,29,9,20,20,247,236,236,40,40,20,24,30,30,40,40,30,20,0,20,236,0,236,216,226,216,216,226,226,232,236,216,16,20,14,5,0,10,14,30,15,10,10,16,20,20,20,24,20,20,129,10,20,20,30,24,20,20,20,16,10,10,24,25,24,1,2,1,3,1,1,3,2,4,3,1,2,2,2,6,2,1,5,3,2,1,1,3,1,3,24,247,236,236,9,20,20,226,216,226,226,216,216,226,0,236,20,0,30,30,40,40,30,30,34,40,13,236,246,250,0,250,246,226,231,246,236,236,236,231,236,129,8,236,226,236,236,236,236,246,246,231,0,0,2,0,12,0,37,32,0,0,18,32,1,12,11,0,1,2,1,3,3,1,3,1,2,1,2,128,10,6,20,20,10,5,251,246,242,236,236,250,128,2,6,49,60,132,2,60,48,7,7,6,5,2,2,1,1,3,4,6,216,236,246,246,10,20,40,134,0,128,2,0,12,0,7,0,0,0,7,0,1,0,128,2,40,0,216,131,135,128,2,216,0,40,131,135,0,128,2,0,12,0,15,0,0,0,15,0,1,0,2,75,24,171,129,2,85,232,182,131,130,1,176,176,134,2,226,236,40,129,2,206,20,20,131,130,1,120,120,134,0,128,2,0,12,0,125,0,0,0,109,0,1,0,20,200,34,33,28,23,15,10,19,35,50,62,66,232,223,223,236,0,10,242,220,208,135,39,3,6,8,9,249,249,249,249,249,253,0,244,232,232,232,230,228,226,226,226,240,251,2,16,28,244,247,252,45,24,236,231,220,215,14,8,243,236,217,206,131,20,20,246,237,232,233,239,241,247,247,240,230,226,246,9,39,61,77,80,73,56,35,136,7,1,3,5,253,253,253,253,255,132,11,243,228,217,204,196,184,171,171,171,179,188,1,129,7,80,100,100,100,95,91,10,6,130,0,40,131,32,20,0,6,30,44,30,0,244,239,243,244,236,0,250,235,237,16,60,73,53,22,0,250,241,236,236,236,230,226,229,233,235,236,132,14,11,20,20,20,20,20,44,76,100,100,100,89,80,64,29,131,5,216,228,0,5,16,20,137,128,19,80,48,29,31,36,30,29,44,52,34,0,176,208,233,239,245,0,1,239,235,140,3,2,7,10,6,132,10,21,48,67,85,100,110,120,120,120,96,70,131,4,216,216,216,220,226,137,0,0,2,0,12,0,84,32,0,0,79,32,1,28,27,0,1,1,2,2,2,8,1,2,3,3,2,4,2,1,1,1,2,1,2,1,3,2,1,3,1,3,2,128,7,9,19,24,10,232,58,10,204,129,16,20,0,20,35,58,63,8,63,36,216,58,7,216,166,166,58,232,2,40,40,31,130,4,80,80,0,206,40,131,10,6,10,246,246,0,156,50,100,100,1,208,129,25,24,0,2,1,1,2,2,8,1,2,3,3,2,4,2,1,2,2,1,1,2,3,3,4,3,2,24,20,245,236,236,0,20,196,0,62,20,20,216,62,216,204,186,196,186,188,246,196,246,80,196,20,2,206,216,239,129,19,226,176,176,0,20,206,226,226,226,226,226,226,226,226,10,19,186,245,226,226,0,128,2,0,12,0,83,0,0,0,86,0,1,0,6,110,165,231,14,14,14,8,129,29,202,142,142,142,139,135,232,0,1,24,24,24,12,0,196,184,170,170,170,209,0,35,76,76,232,232,245,98,98,47,129,2,245,232,232,131,128,64,0,150,3,71,12,0,255,129,5,94,94,44,0,251,242,131,0,248,131,8,60,54,23,0,205,162,162,162,213,132,2,44,94,94,135,2,196,206,234,130,15,246,20,0,27,70,70,70,38,20,20,0,247,236,236,236,246,129,19,34,70,70,70,31,0,219,178,178,20,20,10,186,186,223,0,20,20,20,20,131,128,4,50,29,3,0,18,129,6,176,176,223,0,6,32,50,132,11,16,37,40,196,207,2,40,58,80,80,80,38,131,3,196,186,176,176,129,1,224,196,131,0,2,0,12,0,29,32,0,0,31,32,1,9,8,0,2,4,2,2,2,2,2,2,128,7,24,0,55,201,55,201,0,232,3,60,44,0,100,131,0,102,10,9,0,4,1,3,2,2,2,1,1,2,128,8,236,247,0,76,24,100,0,236,20,1,136,225,132,2,192,0,192,128,2,0,12,0,138,0,0,0,128,32,1,0,63,232,232,207,196,196,212,232,232,232,232,0,11,13,24,24,15,11,0,46,104,104,104,40,236,50,41,24,24,24,52,60,60,65,46,24,24,24,26,0,243,232,232,246,250,0,211,152,152,152,231,50,0,246,236,232,152,152,162,205,0,46,104,104,104,3,65,0,213,152,131,128,7,1,246,246,5,28,10,0,8,130,24,1,0,156,156,156,156,156,209,0,45,108,111,46,23,25,0,19,35,35,20,3,4,10,0,248,131,26,100,99,100,100,100,47,0,226,163,155,216,235,237,239,0,254,235,216,216,216,240,0,1,40,40,40,14,131,43,42,0,2,1,1,3,2,1,2,1,1,3,2,1,1,1,1,1,1,1,1,2,2,1,1,2,2,1,2,1,3,3,1,1,1,1,1,1,1,1,3,1,4,2,1,20,11,129,38,20,10,0,239,236,236,0,206,206,206,209,206,0,250,236,236,246,0,248,240,236,246,0,20,20,0,50,50,48,50,0,4,14,20,50,15,0,206,0,0,10,129,0,246,132,14,75,75,53,30,17,3,0,216,205,233,226,0,10,8,6,131,14,181,181,226,239,253,0,40,47,29,8,0,50,50,226,206,0,0,2,0,12,0,85,32,0,0,58,32,1,28,27,1,3,3,3,2,1,2,1,2,3,1,2,1,2,1,1,1,4,4,1,1,1,1,2,1,1,1,1,15,12,24,245,232,0,23,47,47,0,246,43,0,233,209,209,234,129,9,25,54,54,54,25,231,202,202,202,231,131,23,34,34,0,241,222,226,21,34,34,0,239,222,222,34,192,225,0,29,62,62,29,0,225,192,20,19,1,3,3,3,2,4,2,3,1,1,1,2,1,3,3,1,4,2,4,2,19,247,236,10,20,5,30,5,236,236,255,25,80,80,5,226,226,232,206,24,50,134,12,30,236,206,206,226,246,50,50,0,70,0,186,0,0,0,2,0,12,0,85,32,0,0,73,32,1,28,27,1,3,3,3,3,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,4,2,2,1,4,2,27,12,24,245,232,33,223,65,70,0,232,25,54,54,54,25,231,202,202,202,231,223,0,30,0,223,0,232,0,131,0,236,129,20,20,20,0,192,225,0,29,62,62,29,0,225,192,236,236,9,20,236,236,10,20,25,24,1,3,3,3,3,2,1,1,1,1,2,2,4,2,4,1,1,3,1,1,2,1,2,1,3,24,247,236,10,20,20,70,221,251,25,251,232,206,24,50,40,216,201,186,201,216,40,236,236,236,236,134,12,20,20,0,70,0,186,0,20,20,20,231,216,216,129,2,245,236,236,0,2,0,12,0,82,32,0,0,65,32,1,27,26,1,3,3,3,3,2,2,1,1,1,1,2,1,1,1,1,2,1,1,2,2,1,2,1,2,2,2,26,12,24,245,232,43,233,25,54,54,54,25,231,202,202,202,231,226,10,28,50,28,10,226,10,242,242,10,131,22,236,0,192,225,0,29,62,62,29,0,225,192,236,236,236,0,20,20,236,236,247,10,20,22,21,1,3,3,3,3,2,2,2,4,2,4,1,1,3,1,1,2,1,2,1,1,2,21,247,236,10,20,20,70,232,206,24,50,20,0,241,226,241,0,40,10,10,10,10,10,133,9,70,0,186,0,30,30,30,227,206,206,129,3,248,236,238,236,0,128,2,0,12,0,35,0,0,0,53,32,1,19,18,1,2,2,2,1,2,1,2,1,1,2,2,1,1,2,1,1,4,2,18,25,224,24,222,6,254,33,105,38,244,34,238,12,228,161,223,2,28,232,130,5,42,0,196,0,80,80,131,0,80,129,0,196,129,18,17,1,2,2,2,3,1,2,1,1,2,2,1,1,2,1,1,4,2,17,226,10,236,0,15,221,251,241,25,0,35,5,45,35,65,15,251,20,130,4,196,110,0,196,196,131,0,196,129,0,110,129,0,128,2,0,12,0,90,0,0,0,66,32,1,0,128,38,38,0,218,0,11,24,24,24,11,0,246,232,232,232,246,0,30,66,66,66,30,0,226,190,190,190,226,0,12,24,24,24,12,0,240,228,232,30,16,129,9,223,186,186,186,222,0,251,242,232,242,131,128,2,196,0,54,139,11,180,180,222,0,34,76,76,76,34,0,222,180,135,13,11,20,70,76,68,68,68,32,0,224,188,188,188,188,133,22,21,0,1,1,1,5,6,3,3,3,3,2,4,1,1,3,1,1,2,2,1,3,3,12,249,219,249,23,236,20,238,216,18,40,0,236,247,129,4,246,248,0,36,36,129,128,2,30,0,226,129,3,40,238,216,18,132,6,206,196,186,223,0,70,0,0,0,2,0,12,0,33,32,0,0,21,32,1,10,9,4,6,3,2,1,1,2,1,2,1,9,14,242,29,65,65,29,227,191,191,227,129,7,198,0,27,58,58,27,230,198,6,5,4,6,3,2,4,2,5,236,20,233,206,23,50,129,3,50,0,206,0,128,2,0,12,0,10,0,0,0,7,0,1,0,0,25,64,0,155,128,0,216,131,135,3,226,226,40,40,131,135,128,2,0,12,0,17,0,0,0,11,0,1,0,0,25,64,0,155,128,1,216,25,64,0,155,128,0,216,131,139,7,236,236,50,50,236,236,50,50,131,139,0,128,2,0,12,0,7,0,0,0,7,0,1,0,3,55,55,201,201,131,135,3,218,218,38,38,131,135,0,128,2,0,12,0,11,0,0,0,11,0,1,0,7,55,55,201,201,55,55,201,201,131,139,7,218,218,38,38,218,218,38,38,131,139,0,128,2,0,12,0,19,32,0,0,20,0,1,0,6,5,0,1,1,1,2,3,5,44,54,208,218,26,230,131,1,216,40,8,214,214,42,42,236,236,0,20,20,132,131,5,213,43,33,43,213,223,131,128,2,0,12,0,40,32,0,0,60,0,1,0,13,12,0,5,2,3,4,2,1,1,3,3,1,2,1,0,232,129,9,232,24,59,96,96,0,138,138,193,216,131,8,47,209,233,0,94,0,227,162,162,13,20,239,206,196,196,196,212,226,250,20,20,20,15,7,129,12,228,196,196,196,211,226,250,20,20,20,13,12,20,131,129,3,255,15,40,21,130,19,245,236,230,220,216,216,41,41,244,195,186,175,175,175,238,40,43,63,81,81,131,0,128,2,0,12,0,39,32,0,0,42,0,1,0,14,13,1,3,2,1,1,1,2,3,3,2,1,1,1,1,13,26,230,53,43,217,207,26,230,43,217,43,53,207,217,1,221,35,131,1,221,35,133,23,236,236,0,20,20,0,206,206,50,50,236,236,0,20,20,0,206,206,50,50,206,206,50,50,131,5,208,48,38,48,208,218,131,5,208,48,38,48,208,218,139,128,2,0,12,0,54,32,0,0,33,0,1,20,19,4,6,3,2,2,2,2,2,1,3,1,2,2,1,2,1,1,2,2,2,18,17,4,6,3,2,2,2,2,3,3,1,4,1,2,1,1,2,2,2,17,24,232,24,232,24,202,30,66,226,190,64,192,212,192,64,54,54,232,129,0,208,130,5,180,35,76,35,0,95,129,0,161,130,19,236,20,236,20,236,20,242,226,226,14,30,30,206,30,20,50,226,236,236,20,129,0,50,130,5,30,0,243,226,243,13,135,0,128,2,0,12,0,72,32,0,0,61,0,1,0,24,23,0,4,3,2,2,1,1,1,1,3,2,2,2,2,1,1,3,1,1,3,2,2,1,1,128,15,24,245,232,232,232,40,40,40,0,206,206,0,35,40,232,176,129,4,24,232,80,246,232,131,9,28,32,30,20,0,22,11,246,234,246,130,6,156,186,224,32,216,196,0,128,11,246,236,236,236,246,0,10,20,20,20,20,20,142,14,20,19,7,100,236,236,100,236,236,20,20,156,156,0,20,131,137,2,253,248,246,130,10,246,236,236,236,246,0,10,20,20,20,10,131,0,196,129,4,30,246,10,10,246,135,128,2,0,12,0,6,0,0,0,6,0,1,2,1,9,2,1,196,60,1,200,56,1,110,146,1,110,146,128,2,0,12,0,6,0,0,0,6,0,1,2,1,8,2,1,60,196,1,200,56,1,146,110,1,110,146,128,2,0,12,0,6,0,0,0,6,0,1,2,1,9,2,1,60,196,1,200,56,1,146,110,1,110,146,128,2,0,12,0,6,0,0,0,6,0,1,2,1,8,2,1,196,60,1,56,200,1,110,146,1,146,110,128,2,0,12,0,30,0,0,0,24,0,1,0,133,11,5,250,51,56,56,61,26,230,196,200,200,203,131,133,11,193,193,226,231,20,25,45,45,25,20,230,227,131,136,1,166,166,131,1,90,90,132,133,2,90,90,90,129,3,166,166,166,166,129,0,90,131,0,128,2,0,12,0,14,0,0,0,16,32,1,6,5,17,2,1,3,1,2,5,24,54,54,231,202,202,5,198,0,27,58,27,230,4,3,17,3,3,3,3,215,166,40,90,3,40,238,216,18,128,2,0,12,0,6,0,0,0,6,0,1,2,1,5,2,1,56,200,1,196,60,1,166,90,1,90,166,128,2,0,12,0,22,0,0,0,22,0,1,0,131,7,235,21,69,69,10,246,193,193,131,131,7,197,197,245,11,70,70,17,239,131,131,7,30,226,226,226,226,30,30,30,131,131,7,30,30,30,226,226,226,226,30,131,0,128,2,0,12,0,19,32,0,0,22,0,1,0,4,3,5,2,2,2,128,2,70,0,186,64,255,126,128,64,0,130,128,131,7,20,236,236,236,236,20,20,20,131,131,7,10,10,10,246,246,246,246,10,131,128,2,0,12,0,16,0,0,0,16,0,1,0,132,4,211,45,72,0,184,131,132,4,196,196,23,75,23,131,132,4,30,226,196,0,60,131,132,4,60,60,236,196,236,131,0,128,2,0,12,0,12,0,0,0,12,0,1,0,132,2,25,0,231,131,131,2,201,0,55,132,132,2,226,0,30,131,131,2,30,0,226,132,0,0,2,0,12,0,22,32,0,0,16,32,1,6,5,17,1,1,4,2,1,5,24,54,54,232,202,202,5,198,229,0,58,0,229,4,3,17,3,3,3,3,229,196,27,60,3,80,220,176,36,128,2,0,12,0,6,0,0,0,6,0,1,2,1,5,2,1,56,200,1,196,60,1,236,20,1,20,236,128,2,0,12,0,179,0,0,0,183,0,1,0,63,86,247,251,36,36,36,22,10,10,217,164,164,164,166,193,238,250,18,27,27,27,74,104,44,245,173,173,173,218,250,24,72,72,238,238,233,237,90,251,1,40,40,40,26,14,14,221,168,168,168,172,197,242,246,14,23,23,23,70,100,40,241,169,169,25,169,214,246,20,68,68,234,234,225,229,102,102,56,14,14,254,236,236,98,98,52,10,10,241,232,232,131,128,4,60,42,19,30,16,129,6,94,94,61,32,8,236,206,130,13,10,0,239,239,236,30,36,6,0,220,172,172,172,232,129,1,13,11,129,4,60,41,13,30,16,129,6,94,94,61,32,6,233,206,130,13,10,0,239,239,236,30,36,6,0,220,172,172,172,231,129,1,13,11,129,2,44,94,94,132,2,44,94,94,129,0,249,132,63,196,230,227,18,18,18,18,20,15,46,88,88,88,73,85,20,0,9,236,236,236,39,80,80,76,60,60,60,36,0,211,178,178,20,20,241,226,196,230,229,18,18,18,18,20,15,46,88,88,88,75,85,20,0,9,236,236,236,39,80,80,76,60,60,25,60,36,0,211,178,178,20,20,237,221,186,186,230,15,20,21,20,20,186,186,230,15,20,12,20,20,131,128,4,215,220,230,246,251,129,6,176,176,192,196,174,168,149,130,13,7,236,251,37,40,196,204,227,0,46,80,80,80,53,129,1,13,11,129,4,215,219,224,246,251,129,6,176,176,192,196,172,165,149,130,13,7,236,251,37,40,196,204,227,0,46,80,80,80,52,129,6,13,11,0,196,186,176,176,129,5,224,196,196,186,176,176,129,1,217,196,131,0,128,2,0,12,0,15,32,0,0,13,0,1,0,4,3,1,2,1,2,3,70,0,201,55,1,209,49,129,131,3,38,218,218,38,131,3,222,34,34,222,135,0,0,2,0,12,0,103,32,0,0,93,32,1,34,33,2,1,1,3,3,2,1,2,1,1,1,2,3,1,2,2,1,1,1,1,3,1,2,1,2,1,1,2,1,1,2,3,3,2,33,5,10,255,242,70,70,70,88,124,124,88,70,70,70,242,252,0,10,25,250,202,202,202,202,185,176,195,232,183,176,202,202,201,55,129,14,168,166,196,239,0,13,13,243,243,0,60,75,90,88,88,130,11,32,60,17,0,248,245,243,13,13,10,0,196,129,33,32,2,1,1,3,2,1,3,3,1,3,2,1,3,3,1,1,1,3,1,2,1,1,1,1,1,2,1,1,1,1,3,3,2,130,9,206,192,192,192,192,192,192,192,192,206,129,0,20,133,5,235,220,237,20,227,225,130,1,38,218,129,11,85,85,53,25,0,251,5,0,238,231,171,171,130,13,32,60,58,56,54,54,55,56,200,200,193,192,200,196,129,128,2,0,12,0,16,0,0,0,16,0,1,8,7,1,2,2,2,2,2,2,2,7,84,232,0,84,0,84,55,201,129,0,170,129,0,86,129,7,182,0,136,182,136,182,218,38,129,0,78,129,0,178,129,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,29,0,0,0,31,0,1,0,129,65,0,140,0,140,133,9,150,150,55,55,201,201,55,55,201,201,131,128,0,136,129,3,120,0,216,40,143,129,1,146,146,133,9,80,80,218,218,38,38,218,218,38,38,131,128,6,80,246,10,176,0,40,216,129,1,236,20,139,0,128,2,0,12,0,21,0,0,0,21,0,1,0,135,7,201,55,55,201,55,55,201,201,131,7,48,208,208,48,48,208,208,48,139,135,7,38,218,218,38,218,218,38,38,131,7,228,40,40,228,216,28,28,216,139,0,128,2,0,12,0,25,0,0,0,27,0,1,0,129,65,0,140,0,140,133,5,150,150,201,55,55,201,131,128,0,136,129,3,120,0,216,40,139,129,1,146,146,133,5,80,80,38,218,218,38,131,128,6,80,246,10,176,0,40,216,129,1,236,20,135,0,128,2,0,12,0,13,0,0,0,13,0,1,6,5,1,2,2,2,1,2,5,30,0,30,0,201,55,3,208,48,208,48,129,5,176,0,176,0,38,218,3,40,228,28,216,129,128,2,0,12,0,21,0,0,0,23,0,1,0,129,65,0,140,0,140,133,1,150,150,131,128,0,136,129,3,120,0,216,40,135,129,1,146,146,133,1,80,80,131,128,6,80,246,10,176,0,40,216,129,1,236,20,131,0,128,2,0,12,0,90,0,0,0,89,0,1,0,129,65,0,175,0,175,131,37,2,12,25,26,14,7,2,2,50,100,100,100,88,68,167,219,26,26,26,253,247,248,197,160,160,160,157,156,68,29,234,234,234,245,23,23,231,231,131,128,6,131,5,251,117,253,211,45,129,16,251,246,149,155,162,162,162,192,221,237,17,30,121,102,60,20,19,129,11,94,94,63,20,14,247,247,161,176,186,221,238,136,7,252,252,201,201,18,18,15,15,129,35,236,236,248,247,6,0,216,190,190,190,197,206,0,249,236,236,236,250,9,10,37,66,66,66,60,50,31,22,20,20,20,252,184,184,66,66,131,7,226,30,246,10,189,254,40,216,129,14,2,0,89,86,81,81,81,55,20,251,233,231,215,224,8,131,11,175,175,208,236,6,8,10,8,2,234,10,14,136,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,49,32,0,0,47,0,1,0,16,15,0,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,131,11,49,207,24,232,49,207,24,232,49,207,24,232,3,48,208,48,208,129,1,208,48,129,1,208,48,129,1,208,48,135,3,210,210,46,46,131,3,210,210,46,46,131,3,210,210,46,46,135,7,221,33,33,221,221,33,33,221,131,3,221,33,33,221,131,3,221,33,33,221,131,3,221,33,33,221,131,0,128,2,0,12,0,2,0,0,0,7,0,1,0,133,133,64,255,126,0,10,131,133,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,19,0,0,0,19,0,1,0,147,15,48,208,208,48,48,208,208,48,48,208,208,48,48,208,208,48,131,147,15,228,40,40,228,216,28,28,216,228,40,40,228,216,28,28,216,131,0,128,2,0,12,0,15,0,0,0,15,0,1,0,143,11,48,208,208,48,48,208,208,48,48,208,208,48,131,143,11,222,34,34,222,222,34,34,222,222,34,34,222,131,0,128,2,0,12,0,51,0,0,0,31,0,1,0,129,69,0,170,0,170,0,140,0,140,0,170,0,170,133,64,255,116,0,20,129,64,0,160,132,0,236,64,255,126,0,60,131,0,196,64,0,130,10,20,206,50,48,208,208,48,48,208,208,48,131,129,5,156,156,196,196,152,152,138,64,0,140,131,128,1,226,226,131,1,30,30,131,3,60,60,0,196,129,0,196,131,0,128,2,0,12,0,51,0,0,0,31,0,1,0,129,69,0,170,0,170,0,140,0,140,0,170,0,170,133,64,255,116,0,20,129,64,0,160,132,0,236,64,255,126,0,60,131,0,196,64,0,130,10,20,206,50,48,208,208,48,48,208,208,48,131,129,5,156,156,196,196,152,152,138,64,0,140,131,128,1,226,226,131,1,30,30,131,3,60,60,0,196,129,0,196,131,0,128,2,0,12,0,69,0,0,0,40,0,1,0,129,65,0,150,0,150,133,64,255,116,0,20,129,64,0,160,130,69,0,170,0,170,0,140,0,140,0,170,0,170,135,0,236,64,255,126,129,64,0,130,11,20,206,50,48,208,208,48,48,208,208,48,236,64,255,126,0,60,131,0,196,64,0,130,2,20,206,50,131,129,1,146,146,138,64,0,140,129,5,156,156,196,196,152,152,135,128,0,90,129,0,166,131,3,60,60,0,196,129,3,196,0,226,226,131,1,30,30,134,128,2,0,12,0,46,0,0,0,41,0,1,0,132,65,255,126,255,126,130,1,254,254,129,3,254,254,0,30,130,0,30,133,128,3,50,206,0,95,129,16,161,68,228,228,68,28,188,188,28,0,75,226,146,30,181,0,110,131,132,1,110,110,130,1,2,2,129,3,2,2,0,236,130,0,236,133,131,0,166,129,16,90,20,80,80,20,176,236,236,176,0,20,80,70,176,236,0,186,131,128,2,0,12,0,20,0,0,0,17,0,1,0,0,40,64,0,140,1,40,196,139,131,7,48,208,208,48,48,208,208,48,131,3,223,183,7,47,139,131,7,222,34,34,222,222,34,34,222,131,128,2,0,12,0,30,0,0,0,24,0,1,0,1,1,1,65,0,141,0,141,5,1,1,1,1,247,247,133,128,0,146,129,7,110,0,206,50,49,207,207,49,131,129,1,146,146,131,65,255,96,255,96,133,128,0,90,129,0,166,130,3,223,33,33,223,131,0,128,2,0,12,0,64,0,0,0,62,0,1,0,129,2,41,91,123,67,0,149,0,164,0,164,0,150,2,124,91,40,133,65,0,140,0,140,131,1,227,227,65,0,144,0,144,131,128,16,131,182,253,45,73,81,179,186,219,14,81,125,0,206,50,0,146,129,7,110,0,206,50,51,209,209,51,131,129,0,172,71,255,75,255,40,255,57,255,86,255,86,255,57,255,41,255,77,0,174,133,65,255,86,255,86,131,65,255,108,255,108,133,128,11,100,52,249,221,216,224,34,41,41,15,210,156,131,0,120,129,0,136,130,3,224,34,34,224,131,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,21,0,0,0,19,0,1,0,129,65,0,210,0,210,139,128,10,136,5,251,120,0,201,55,50,206,206,50,131,129,1,206,206,139,128,0,60,129,7,196,0,30,226,224,32,32,224,131,0,128,2,0,12,0,67,0,0,0,51,0,1,0,129,69,0,170,0,170,0,140,0,140,0,170,0,170,134,0,226,130,2,226,2,2,64,255,116,2,20,2,2,64,0,160,132,0,236,64,255,126,0,60,131,0,196,64,0,130,18,20,206,50,0,146,216,75,40,110,0,181,48,218,218,48,38,208,208,38,131,129,5,156,156,196,196,152,152,134,0,20,130,2,20,254,254,129,2,254,254,0,64,0,140,131,128,1,226,226,131,1,30,30,131,11,70,70,20,186,186,0,236,0,70,70,0,186,129,0,186,131,0,128,2,0,12,0,36,0,0,0,30,0,1,0,1,255,255,65,0,180,0,180,1,255,255,131,65,0,180,0,180,135,15,40,171,5,251,85,216,211,45,40,171,5,251,85,216,211,45,131,5,236,236,236,236,236,236,131,1,236,236,135,1,246,50,129,5,206,10,40,216,246,50,129,3,206,10,40,216,131,0,128,2,0,12,0,43,0,0,0,40,0,1,0,129,65,0,140,0,140,129,1,236,236,129,65,0,140,0,140,131,1,216,216,133,128,0,146,129,5,110,0,206,50,0,146,129,7,110,0,206,50,49,207,207,49,131,129,65,255,106,255,106,129,1,236,236,129,1,146,146,131,65,255,66,255,66,133,128,0,90,129,0,166,131,0,90,129,0,166,130,3,223,33,33,223,131,128,2,0,12,0,45,0,0,0,41,0,1,0,129,65,0,140,0,140,134,0,226,130,2,226,2,2,129,1,2,2,133,128,0,146,129,19,110,0,206,50,0,146,226,75,30,110,0,181,68,228,228,68,28,188,188,28,131,129,1,146,146,134,0,20,130,2,20,254,254,129,1,254,254,133,128,0,90,129,0,166,131,14,70,80,20,176,186,0,236,20,80,80,20,176,236,236,176,131,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,47,0,0,0,42,0,1,0,132,2,216,165,132,67,255,107,255,92,255,92,255,108,3,133,165,214,0,65,255,112,255,112,133,128,18,50,206,0,125,81,14,219,186,179,81,73,45,253,182,131,51,209,209,51,131,132,0,83,71,0,179,0,215,0,200,0,170,0,170,0,199,0,216,0,181,0,83,136,131,15,156,210,15,41,41,34,224,216,221,249,52,100,224,34,34,224,131,128,2,0,12,0,47,0,0,0,42,0,1,0,132,2,216,165,132,67,255,107,255,92,255,92,255,108,3,133,165,214,0,65,255,112,255,112,133,128,18,50,206,0,125,81,14,219,186,179,81,73,45,253,182,131,51,209,209,51,131,132,0,83,71,0,179,0,215,0,200,0,170,0,170,0,199,0,216,0,181,0,83,136,131,15,156,210,15,41,41,34,224,216,221,249,52,100,224,34,34,224,131,128,2,0,12,0,85,0,0,0,82,0,1,0,129,2,41,91,123,67,0,149,0,164,0,164,0,150,2,124,91,40,136,2,216,165,132,67,255,107,255,92,255,92,255,108,3,133,165,214,0,67,255,112,255,112,0,138,0,138,131,128,34,131,182,253,45,73,81,179,186,219,14,81,125,0,206,50,0,50,206,0,125,81,14,219,186,179,81,73,45,253,182,131,51,209,209,51,131,129,0,172,71,255,75,255,40,255,57,255,86,255,86,255,57,255,41,255,77,0,174,136,0,83,71,0,179,0,215,0,200,0,170,0,170,0,199,0,216,0,181,0,83,130,1,234,234,131,128,11,100,52,249,221,216,224,34,41,41,15,210,156,134,15,156,210,15,41,41,34,224,216,221,249,52,100,224,34,34,224,131,128,2,0,12,0,68,0,0,0,58,0,1,0,132,65,255,96,255,96,133,2,216,165,132,67,255,107,255,92,255,92,255,108,3,133,165,214,0,65,255,112,255,112,1,69,69,131,128,2,50,206,0,64,0,130,129,64,255,126,128,18,50,206,0,125,81,14,219,186,179,81,73,45,253,182,131,51,209,209,51,131,132,1,90,90,133,0,83,71,0,179,0,215,0,200,0,170,0,170,0,199,0,216,0,181,0,83,130,65,0,188,0,188,131,131,0,186,129,0,70,131,15,156,210,15,41,41,34,224,216,221,249,52,100,224,34,34,224,131,0,128,2,0,12,0,2,0,0,0,2,0,1,0,133,133,133,133,0,128,2,0,12,0,84,0,0,0,79,0,1,0,132,2,216,165,132,67,255,107,255,92,255,92,255,108,3,133,165,214,0,65,255,112,255,112,133,15,55,59,197,201,0,20,48,48,48,20,0,235,208,208,208,235,131,128,23,50,206,0,125,81,14,219,186,179,81,73,45,253,182,131,51,209,209,51,49,207,207,49,156,129,0,156,129,8,227,207,186,159,159,159,186,207,227,132,132,0,83,71,0,179,0,215,0,200,0,170,0,170,0,199,0,216,0,181,0,83,136,15,216,196,60,40,0,238,215,215,215,238,0,17,41,41,41,17,131,131,20,156,210,15,41,41,34,224,216,221,249,52,100,224,34,34,224,224,34,34,224,120,129,0,120,129,8,24,41,58,82,82,82,58,41,24,132,128,2,0,12,0,2,0,0,0,5,0,1,0,133,133,1,216,40,131,133,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,21,0,0,0,22,0,1,0,132,65,255,116,255,116,129,1,106,106,132,128,3,40,216,0,120,129,0,136,135,132,1,110,110,129,1,176,176,132,128,9,216,40,0,176,10,246,80,0,20,236,132,128,2,0,12,0,26,0,0,0,27,0,1,0,132,65,255,116,255,116,129,6,106,106,0,55,55,201,201,131,128,3,40,216,0,120,129,0,136,139,132,1,110,110,129,6,176,176,0,218,218,38,38,131,128,9,216,40,0,176,10,246,80,0,20,236,136,128,2,0,12,0,30,0,0,0,31,0,1,0,132,65,255,116,255,116,129,10,106,106,0,55,55,201,201,55,55,201,201,131,128,3,40,216,0,120,129,0,136,143,132,1,110,110,129,10,176,176,0,218,218,38,38,218,218,38,38,131,128,9,216,40,0,176,10,246,80,0,20,236,140,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,94,0,0,0,88,0,1,0,2,73,1,1,129,65,255,92,255,92,38,73,78,62,80,102,102,102,90,70,169,221,28,28,28,255,249,233,231,12,115,64,10,249,199,162,162,162,159,158,70,31,236,236,236,28,25,25,233,233,131,20,22,42,208,247,112,248,2,153,2,154,163,197,221,237,17,30,121,102,60,20,19,130,17,32,52,114,112,104,104,104,67,20,14,248,247,161,177,186,221,252,15,135,0,3,129,4,255,255,80,80,3,129,35,216,190,190,190,197,206,0,249,236,236,236,250,9,246,10,49,27,4,251,9,37,66,66,66,60,50,31,22,20,20,20,252,184,184,66,66,131,18,22,216,40,24,216,10,246,82,0,71,71,49,20,251,233,231,215,224,8,132,16,22,40,200,192,185,185,185,212,236,6,9,10,8,3,234,10,14,136,0,128,2,0,12,0,101,0,0,0,94,0,1,0,2,231,1,1,129,65,255,92,255,92,32,231,58,42,69,98,98,98,86,66,165,217,24,24,24,251,245,246,195,158,158,158,155,154,66,27,232,232,232,15,21,21,229,229,129,65,0,175,0,175,1,222,222,133,20,43,42,208,247,112,248,2,184,11,173,180,205,221,237,17,30,121,102,60,20,19,129,12,94,94,63,20,14,248,247,161,177,186,221,254,22,132,6,131,5,251,107,243,211,45,131,0,231,129,42,69,69,80,80,231,2,2,218,192,192,192,199,208,2,251,238,238,238,252,11,12,39,68,68,68,62,52,33,24,22,22,22,254,186,186,68,68,237,237,186,186,233,233,133,18,23,216,40,24,216,10,246,93,10,91,91,60,20,251,233,231,215,224,8,131,12,175,175,208,236,6,9,10,8,3,234,10,19,10,131,7,226,30,246,10,201,10,40,216,131,128,2,0,12,0,2,0,0,0,5,0,1,0,133,133,1,156,60,131,133,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,21,0,0,0,19,0,1,0,132,65,255,46,255,46,136,128,10,55,201,0,120,251,5,136,50,206,206,50,131,132,1,50,50,136,128,3,226,30,0,196,129,4,60,224,32,32,224,131,0,128,2,0,12,0,51,0,0,0,33,0,1,0,132,69,255,86,255,86,255,116,255,116,255,86,255,86,128,0,236,64,0,140,130,64,255,96,133,128,2,50,206,0,64,0,130,0,196,131,0,60,64,255,126,7,48,208,208,48,48,208,208,48,131,132,5,104,104,60,60,100,100,132,64,255,116,134,0,20,129,2,236,30,30,131,6,226,226,0,60,60,0,196,129,0,196,131,0,128,2,0,12,0,87,0,0,0,55,0,1,0,129,69,0,170,0,170,0,140,0,140,0,170,0,170,136,69,255,86,255,86,255,116,255,116,255,86,255,86,128,0,236,65,0,140,255,116,1,20,0,65,255,96,0,160,132,0,236,64,255,126,0,60,131,0,196,64,0,130,6,20,206,50,236,50,206,20,64,0,130,0,196,131,0,60,64,255,126,7,48,228,228,48,28,208,208,28,131,129,5,156,156,196,196,152,152,136,5,104,104,60,60,100,100,130,1,40,156,64,255,116,128,0,40,64,0,180,131,128,1,226,226,131,1,30,30,134,1,30,30,131,6,226,226,0,80,80,0,176,129,0,176,131,0,128,2,0,12,0,86,0,0,0,60,0,1,0,129,69,0,170,0,170,0,140,0,140,0,170,0,170,136,69,255,86,255,86,255,116,255,116,255,86,255,86,128,0,236,65,0,140,255,116,1,20,0,65,255,96,0,160,132,128,64,255,126,0,60,131,0,196,64,0,130,128,5,206,50,0,50,206,0,64,0,130,0,196,131,0,60,64,255,126,7,48,208,208,48,48,208,208,48,131,129,5,156,156,196,196,152,152,136,5,104,104,60,60,100,100,130,1,40,156,64,255,116,128,0,40,64,0,180,131,2,20,226,226,131,2,30,30,236,129,0,20,129,2,236,30,30,131,6,226,226,0,60,60,0,196,129,0,196,131,0,128,2,0,12,0,75,0,0,0,53,0,1,0,132,69,255,86,255,86,255,116,255,116,255,86,255,86,128,0,236,64,0,140,2,254,254,0,64,255,96,3,254,254,0,30,130,0,30,133,128,2,50,206,0,64,0,130,0,196,131,0,60,64,255,126,10,48,188,188,48,68,208,208,68,236,55,186,64,255,126,2,70,201,20,64,0,130,131,132,5,104,104,60,60,100,100,130,1,2,2,64,255,116,128,3,2,2,0,236,130,0,236,133,0,20,129,2,236,30,30,131,6,226,226,0,40,40,0,216,129,0,216,129,2,40,70,216,129,0,186,131,0,128,2,0,12,0,2,0,0,0,5,0,1,0,133,133,1,216,40,131,133,128,2,0,12,0,38,0,0,0,27,0,1,0,0,237,129,1,237,237,65,255,76,255,76,0,237,132,65,255,76,255,76,132,15,50,45,211,206,75,251,5,181,50,45,211,206,75,251,5,181,131,132,1,20,20,133,1,20,20,132,128,3,216,40,0,196,129,5,60,0,216,40,0,196,129,0,60,131,128,2,0,12,0,65,0,0,0,52,0,1,0,132,2,216,165,132,67,255,107,255,92,255,92,255,108,2,133,165,214,133,65,255,116,255,116,128,65,255,112,255,112,133,128,18,50,206,0,125,81,14,219,186,179,81,73,45,253,182,131,0,50,206,0,64,0,130,129,64,255,126,3,51,209,209,51,131,132,0,83,71,0,179,0,215,0,200,0,170,0,170,0,199,0,216,0,181,0,83,133,1,110,110,136,131,11,156,210,15,41,41,34,224,216,221,249,52,100,131,0,186,129,4,70,224,34,34,224,131,128,2,0,12,0,69,0,0,0,45,0,1,0,132,69,255,86,255,86,255,116,255,116,255,86,255,86,133,65,255,106,255,106,128,0,236,64,0,140,130,64,255,96,133,128,2,50,206,0,64,0,130,0,196,131,0,60,64,255,126,128,2,50,206,0,64,0,130,129,64,255,126,7,48,208,208,48,48,208,208,48,131,132,5,104,104,60,60,100,100,133,1,110,110,132,64,255,116,134,0,20,129,2,236,30,30,131,2,226,226,20,129,1,236,166,129,5,90,0,60,60,0,196,129,0,196,131,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,0,2,0,12,0,117,32,0,0,103,32,1,36,35,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,5,4,2,1,2,5,1,1,1,1,2,2,2,1,132,2,216,165,132,67,255,107,255,92,255,92,255,108,10,133,165,214,0,236,228,226,222,211,206,196,64,255,126,11,139,162,196,206,211,222,226,228,236,82,232,232,128,34,50,206,0,125,81,14,219,186,179,81,73,45,253,182,131,50,54,55,57,55,55,55,49,207,204,202,202,202,204,202,201,202,202,206,211,34,33,0,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,5,3,2,4,5,1,1,1,1,1,1,2,2,1,130,3,63,106,89,34,129,24,25,73,92,57,0,40,26,255,246,244,236,10,1,0,10,40,32,14,10,251,237,226,202,20,20,129,31,156,205,1,19,15,10,246,241,243,8,57,100,246,246,241,246,247,246,0,226,30,60,60,60,94,90,94,90,90,0,20,0,128,2,0,12,0,2,0,0,0,2,0,1,0,134,134,134,134,0,128,2,0,12,0,136,32,0,0,117,0,1,0,43,42,0,2,1,8,1,1,1,2,4,1,1,8,1,2,6,2,1,1,1,1,3,2,2,1,1,2,2,6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,26,226,201,196,196,185,171,158,136,170,186,196,196,202,226,226,234,236,240,251,0,82,232,0,251,240,233,226,132,2,216,165,132,67,255,107,255,92,255,92,255,108,3,133,165,214,0,42,54,51,54,54,54,54,55,55,201,201,201,201,198,201,201,202,201,199,201,201,0,241,54,54,53,55,54,0,50,206,0,115,71,7,216,186,179,81,73,48,4,192,141,164,14,4,15,20,3,234,216,221,223,226,206,206,206,20,20,20,131,4,2,8,10,10,2,135,3,63,106,89,34,129,3,25,73,92,57,132,63,246,246,246,246,246,246,246,246,243,239,236,236,236,237,240,241,241,15,15,25,40,50,50,50,53,57,60,60,60,60,60,60,60,60,60,60,60,63,60,60,60,101,110,107,90,90,90,60,20,20,0,246,246,246,246,246,245,246,246,246,246,246,246,246,131,11,156,205,1,19,15,10,246,241,243,8,57,100,131,128,2,0,12,0,25,0,0,0,24,0,1,0,0,200,131,65,255,91,255,91,4,170,24,90,232,166,131,7,41,45,211,246,115,251,5,192,135,0,21,129,8,255,255,80,80,247,236,201,20,55,131,7,248,216,40,20,216,10,246,72,135,128,2,0,12,0,43,0,0,0,40,0,1,0,129,65,0,175,0,175,1,33,33,129,0,228,131,65,255,91,255,91,4,198,24,90,232,166,131,128,14,131,5,251,102,238,211,45,28,45,211,246,115,251,5,179,135,8,1,1,206,206,222,222,20,20,21,129,8,255,255,80,80,247,236,201,20,55,131,15,226,30,246,10,223,32,40,216,248,216,40,20,216,10,246,72,135,0,2,0,12,0,70,32,0,0,70,32,1,22,21,0,1,2,1,2,1,1,1,1,3,2,1,3,1,1,1,1,1,1,3,3,2,21,24,24,4,236,208,246,19,7,250,26,170,170,204,212,249,231,194,192,196,166,27,0,21,255,254,254,254,248,194,150,143,143,194,208,194,254,254,13,53,108,109,109,254,208,48,22,21,0,1,2,1,1,1,2,1,1,3,2,1,3,1,1,1,1,1,1,3,2,2,21,236,236,251,10,10,12,10,238,228,2,78,78,244,250,17,11,21,26,32,52,2,2,21,228,52,32,32,32,51,53,52,52,52,32,248,208,208,214,218,212,188,188,248,222,34,128,2,0,12,0,176,0,0,0,185,0,1,0,63,24,24,24,19,0,243,233,236,252,13,7,5,33,61,60,30,5,248,230,231,242,242,242,68,68,68,14,246,245,252,22,24,11,254,254,240,234,221,219,210,216,193,166,166,166,10,14,25,31,10,229,214,217,242,10,10,10,10,10,30,20,10,10,10,25,20,30,45,68,73,18,18,73,69,46,226,17,68,68,68,17,226,202,176,176,176,202,68,68,242,242,131,11,1,1,239,237,237,237,232,200,159,148,148,148,65,255,109,255,109,1,169,212,130,1,252,252,131,33,18,80,80,80,68,93,40,3,1,1,1,6,54,90,90,90,90,42,1,1,40,40,37,37,32,2,233,220,206,206,206,206,40,40,135,18,6,10,10,246,246,251,0,156,156,234,50,76,100,100,100,53,1,208,156,135,63,236,236,236,251,10,3,247,241,234,239,223,214,211,211,208,186,192,198,222,1,20,20,20,196,196,196,197,196,226,16,51,60,45,19,8,1,245,241,2,21,34,44,54,54,54,20,255,236,235,11,52,61,56,35,20,20,20,20,20,216,8,62,62,62,25,9,216,204,189,186,196,196,186,188,204,246,222,196,196,196,222,246,33,80,80,80,33,196,196,20,20,131,15,226,50,39,30,30,30,46,50,55,70,70,70,18,232,248,251,130,63,4,250,226,226,226,226,202,176,176,176,205,16,1,236,226,226,226,220,226,218,186,186,186,214,246,226,206,206,225,249,0,17,28,24,20,20,20,20,206,206,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,10,10,15,19,228,186,186,186,205,6,226,245,10,226,226,226,226,131,128,2,0,12,0,57,0,0,0,62,0,1,0,8,26,26,26,13,0,12,19,16,7,129,11,80,80,80,230,230,230,242,0,244,237,240,249,129,6,174,174,174,26,26,230,230,131,133,5,234,201,169,147,147,147,135,5,22,55,87,109,109,109,129,3,48,208,208,48,131,130,24,239,236,248,252,243,229,218,217,202,202,202,20,20,20,30,30,33,11,238,223,245,29,74,74,74,135,31,216,10,24,20,20,20,32,50,68,80,80,80,40,40,40,10,242,236,236,236,224,206,188,176,176,176,236,216,222,34,34,222,131,128,2,0,12,0,120,0,0,0,108,0,1,0,129,2,35,84,119,68,0,149,0,164,0,164,0,150,0,128,1,98,46,131,17,23,23,23,19,22,27,29,33,44,49,51,53,55,58,59,71,94,117,65,0,129,0,129,17,116,93,71,59,58,55,53,50,49,44,33,29,27,22,19,173,173,173,131,128,52,141,190,0,44,69,77,175,182,212,3,70,115,0,204,48,50,45,206,206,206,202,201,199,201,201,201,201,201,201,201,201,204,207,207,49,49,51,54,54,54,54,54,54,54,54,51,54,54,54,54,54,54,50,131,129,3,188,143,162,221,129,3,232,188,171,204,131,37,235,235,235,215,229,1,9,12,16,19,15,8,1,250,245,246,250,253,255,255,253,250,246,245,240,233,226,219,215,223,241,245,5,18,29,53,53,53,131,128,27,100,56,6,241,240,246,10,14,17,255,204,156,0,254,254,236,0,10,10,10,16,10,9,10,10,10,7,3,130,21,15,30,30,226,226,211,196,196,196,196,196,196,196,196,161,166,161,166,166,166,0,236,131,0,128,2,0,12,0,111,0,0,0,112,0,1,0,53,24,24,24,19,0,214,222,236,251,3,246,230,251,0,18,16,236,241,243,236,246,8,10,82,82,82,232,232,232,223,226,253,233,216,221,206,236,2,4,243,236,220,197,200,226,228,234,231,221,213,216,172,172,172,131,128,23,251,239,241,241,241,251,231,214,201,201,201,192,191,208,201,201,201,200,191,171,161,161,161,251,129,25,4,17,14,14,14,17,44,56,54,54,54,66,73,64,45,43,54,54,54,59,74,93,94,94,94,251,132,42,236,236,236,246,0,238,217,206,228,219,226,230,240,236,236,230,226,222,215,206,216,198,196,202,202,202,20,20,20,11,0,252,244,246,2,10,20,14,6,1,0,3,2,129,8,2,10,10,22,41,50,50,50,50,131,53,226,0,27,50,50,50,73,80,68,70,70,70,54,50,49,50,50,50,59,50,30,40,40,40,20,20,20,0,224,196,196,196,202,206,205,216,216,216,217,217,216,219,228,236,236,236,236,236,230,206,206,206,216,226,131,0,2,0,12,0,145,32,0,0,120,32,1,46,45,1,2,1,1,1,1,1,1,6,2,1,8,1,1,1,2,4,1,1,8,1,1,1,6,2,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,29,24,0,5,16,20,22,28,30,30,56,60,60,71,85,98,120,86,70,60,60,55,39,30,30,21,20,17,5,0,174,129,2,41,91,123,67,0,149,0,164,0,164,0,150,2,124,91,40,131,28,15,202,202,203,202,202,202,202,202,205,202,202,202,202,201,201,55,55,55,55,58,55,55,55,55,55,58,55,55,129,14,131,182,253,45,73,81,179,186,219,14,81,125,0,206,50,42,41,0,1,2,9,1,2,2,1,4,5,1,1,2,2,5,5,8,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,236,236,129,2,2,10,2,137,9,253,240,236,252,22,40,35,33,30,50,129,3,188,143,162,221,129,3,232,188,171,204,130,41,236,0,10,10,11,10,9,10,10,20,19,16,15,241,206,196,196,194,196,196,196,155,146,149,166,166,196,0,100,56,6,241,240,246,10,14,17,255,204,156,0,254,0,128,2,0,12,0,30,0,0,0,26,0,1,0,7,255,73,181,196,60,250,4,137,131,1,60,60,133,130,12,48,48,80,80,0,48,208,208,48,48,208,208,48,131,7,225,237,21,37,243,1,1,19,139,130,12,228,228,196,196,0,216,28,28,216,228,40,40,228,131,0,0,2,0,12,0,184,32,0,0,130,32,1,60,59,0,1,1,1,4,1,3,1,4,2,1,3,1,2,1,1,4,1,3,1,4,2,1,1,2,1,1,1,1,1,4,1,3,1,4,2,1,3,1,2,1,1,1,1,1,1,4,1,3,1,4,2,1,1,2,1,1,1,1,1,128,58,42,204,162,232,232,232,232,232,70,70,232,190,138,138,190,24,24,24,24,24,118,118,118,24,238,186,186,186,238,232,232,232,232,232,70,70,232,190,138,138,190,21,63,0,214,24,24,24,24,24,118,118,118,24,238,186,186,186,238,128,58,200,227,21,0,255,0,255,178,220,0,78,78,0,220,178,255,254,255,251,177,219,255,33,75,75,33,255,219,177,0,255,0,255,178,220,0,78,78,0,220,178,4,204,0,50,255,254,255,251,177,219,255,33,75,75,33,255,219,177,42,41,0,1,1,1,5,6,2,4,2,1,3,1,5,2,2,4,4,2,1,3,1,5,6,2,4,2,1,3,1,1,1,1,1,5,2,2,4,4,2,1,3,1,41,1,227,205,235,5,25,15,236,15,30,50,30,237,247,1,247,212,247,6,26,6,255,19,9,230,9,24,44,24,38,8,251,25,231,241,251,241,206,241,0,20,0,128,2,40,211,171,129,5,55,231,201,201,25,55,129,6,253,55,230,199,199,25,55,129,9,55,231,201,201,25,55,37,77,0,216,129,6,253,55,230,199,199,25,55,128,2,0,12,0,60,0,0,0,53,0,1,0,128,7,23,58,91,91,91,53,14,14,130,15,12,27,32,32,32,17,248,248,238,238,238,3,14,14,238,238,131,128,4,240,12,52,80,116,65,0,140,0,140,131,15,253,253,226,193,160,133,133,133,163,183,210,253,203,216,10,183,131,128,18,206,206,206,206,206,231,0,196,10,10,10,236,238,216,216,216,239,236,244,130,2,244,196,196,133,128,6,30,24,9,0,221,186,186,133,10,31,40,48,80,80,80,41,10,5,0,30,129,0,10,131,128,2,0,12,0,79,0,0,0,72,0,1,0,1,18,17,129,22,251,250,5,5,5,239,231,241,241,241,241,252,17,17,241,241,10,9,20,20,20,254,246,131,2,11,32,32,133,64,0,130,129,64,0,130,129,2,209,176,144,66,255,96,255,96,255,96,23,148,186,213,0,156,0,50,186,92,92,45,12,236,188,188,188,240,22,49,92,2,95,226,22,131,35,236,235,20,20,5,244,236,236,236,233,241,7,20,20,20,18,236,236,20,20,5,244,236,236,236,233,241,7,20,20,20,18,216,216,20,20,131,0,176,129,0,176,129,10,11,30,50,60,60,60,49,30,9,0,30,129,12,30,226,226,237,0,20,30,30,30,19,0,235,226,135,0,2,0,12,0,28,32,0,0,28,32,1,8,7,1,2,1,2,1,1,2,1,7,25,60,60,0,232,196,196,232,7,60,0,232,196,196,232,25,60,8,7,1,1,2,1,2,1,2,1,7,243,226,226,243,13,30,30,13,7,226,243,13,30,30,13,243,226,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,3,3,3,3,4,2,4,128,6,226,0,30,0,226,0,30,7,226,0,30,0,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,4,2,4,2,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,12,30,243,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,12,30,243,226,13,30,244,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,12,30,243,226,13,30,244,226,0,30,0,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,12,30,243,226,13,30,244,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,172,32,0,0,88,32,1,56,55,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,55,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,55,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,28,27,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,26,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,27,226,0,30,0,226,0,30,0,226,12,30,243,226,13,30,244,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,196,32,0,0,100,32,1,64,63,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,63,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,63,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,32,31,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,30,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,31,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,172,32,0,0,88,32,1,56,55,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,55,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,55,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,28,27,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,26,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,27,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,12,30,243,226,13,30,244,226,0,30,0,226,13,30,244,0,2,0,12,0,172,32,0,0,88,32,1,56,55,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,55,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,55,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,28,27,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,26,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,27,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,0,30,0,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,0,30,0,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,12,30,243,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,2,3,3,3,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,12,30,243,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,172,32,0,0,88,32,1,56,55,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,55,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,55,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,28,27,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,26,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,27,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,13,30,244,226,0,30,0,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,4,2,4,2,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,12,30,243,226,13,30,244,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,12,30,243,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,2,3,3,3,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,13,30,244,226,0,30,0,226,12,30,243,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,172,32,0,0,88,32,1,56,55,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,55,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,55,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,28,27,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,26,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,27,226,13,30,244,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,13,30,244,226,12,30,243,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,0,30,0,226,12,30,243,226,13,30,244,226,0,30,0,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,13,30,244,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,12,30,243,226,0,30,0,226,13,30,244,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,12,30,243,226,13,30,244,226,12,30,243,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,13,30,244,226,12,30,243,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,12,30,243,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,4,2,4,2,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,13,30,244,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,13,30,244,226,0,30,0,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,172,32,0,0,88,32,1,56,55,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,55,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,55,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,28,27,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,26,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,27,226,0,30,0,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,13,30,244,226,0,30,0,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,0,30,0,226,13,30,244,226,0,30,0,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,13,30,244,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,13,30,244,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,0,30,0,226,13,30,244,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,13,30,244,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,4,2,4,2,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,13,30,244,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,4,2,4,2,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,4,2,4,2,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,13,30,244,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,0,30,0,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,0,30,0,226,13,30,244,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,0,30,0,226,0,30,0,226,13,30,244,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,0,30,0,226,13,30,244,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,4,2,4,2,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,3,3,3,3,4,2,4,128,6,226,0,30,0,226,0,30,7,226,0,30,0,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,4,2,4,2,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,12,30,243,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,12,30,243,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,172,32,0,0,88,32,1,56,55,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,55,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,55,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,28,27,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,26,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,27,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,12,30,243,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,3,3,3,3,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,4,2,4,2,3,3,3,3,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,12,30,243,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,12,30,243,226,12,30,243,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,12,30,243,226,0,30,0,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,12,30,243,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,3,3,3,3,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,12,30,243,226,0,30,0,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,4,2,4,2,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,4,2,4,2,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,12,30,243,226,12,30,243,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,0,30,0,226,12,30,243,226,12,30,243,226,0,30,0,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,13,30,244,226,0,30,0,226,12,30,243,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,12,30,243,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,3,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,0,30,0,226,12,30,243,226,0,30,0,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,4,2,4,2,3,3,3,3,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,12,30,243,226,0,30,0,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,4,2,4,2,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,12,30,243,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,12,30,243,226,12,30,243,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,12,30,243,226,0,30,0,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,4,2,4,2,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,3,3,3,3,3,3,3,128,6,226,0,30,0,226,0,30,7,226,0,30,0,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,4,2,4,2,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,0,30,0,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,4,2,4,2,3,3,3,128,6,226,0,30,0,226,0,30,7,226,13,30,244,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,4,2,4,2,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,3,3,3,3,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,0,30,0,226,0,30,0,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,3,3,3,3,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,0,30,0,226,0,30,0,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,3,3,3,3,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,0,30,0,226,0,30,0,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,3,3,3,3,4,2,4,128,6,226,0,30,0,226,0,30,7,226,0,30,0,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,0,30,0,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,12,30,243,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,3,3,3,3,3,3,3,128,6,226,0,30,0,226,0,30,7,226,0,30,0,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,0,30,0,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,3,3,3,3,3,3,3,128,6,226,0,30,0,226,0,30,7,226,0,30,0,226,0,30,0,0,2,0,12,0,28,32,0,0,16,32,1,8,7,1,2,1,2,1,1,2,1,7,25,60,60,0,232,196,196,232,7,60,0,232,196,196,232,25,60,4,3,0,4,2,4,128,2,226,0,30,3,226,13,30,244,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,4,2,4,2,4,2,4,128,6,226,0,30,0,226,0,30,7,226,13,30,244,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,4,2,4,2,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,12,30,243,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,12,30,243,226,13,30,244,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,12,30,243,226,13,30,244,226,12,30,243,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,12,30,243,226,13,30,244,226,12,30,243,226,13,30,244,0,2,0,12,0,172,32,0,0,88,32,1,56,55,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,55,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,55,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,28,27,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,26,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,27,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,12,30,243,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,12,30,243,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,13,30,244,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,12,30,243,226,13,30,244,226,12,30,243,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,13,30,244,226,12,30,243,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,12,30,243,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,4,2,4,2,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,12,30,243,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,12,30,243,226,13,30,244,226,12,30,243,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,0,30,0,226,12,30,243,226,13,30,244,226,12,30,243,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,13,30,244,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,12,30,243,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,0,30,0,226,12,30,243,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,4,2,4,2,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,12,30,243,226,12,30,243,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,12,30,243,226,0,30,0,226,12,30,243,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,12,30,243,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,12,30,243,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,0,30,0,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,4,2,4,2,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,3,3,3,3,4,2,4,128,6,226,0,30,0,226,0,30,7,226,0,30,0,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,4,2,4,2,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,13,30,244,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,13,30,244,226,12,30,243,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,13,30,244,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,0,30,0,226,13,30,244,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,13,30,244,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,4,2,4,2,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,4,2,4,2,4,2,4,128,6,226,0,30,0,226,0,30,7,226,13,30,244,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,4,2,4,2,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,13,30,244,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,0,30,0,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,0,30,0,226,13,30,244,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,0,30,0,226,13,30,244,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,4,2,4,2,4,2,4,128,6,226,0,30,0,226,0,30,7,226,12,30,243,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,12,30,243,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,4,2,4,2,3,3,3,128,6,226,0,30,0,226,0,30,7,226,13,30,244,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,3,3,3,3,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,0,30,0,226,0,30,0,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,4,2,4,2,3,3,3,128,6,226,0,30,0,226,0,30,7,226,13,30,244,226,0,30,0,0,2,0,12,0,28,32,0,0,16,32,1,8,7,1,2,1,2,1,1,2,1,7,25,60,60,0,232,196,196,232,7,60,0,232,196,196,232,25,60,4,3,0,4,2,4,128,2,226,0,30,3,226,12,30,243,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,3,3,3,3,4,2,4,128,6,226,0,30,0,226,0,30,7,226,0,30,0,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,4,2,4,2,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,12,30,243,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,12,30,243,226,12,30,243,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,12,30,243,226,13,30,244,0,2,0,12,0,148,32,0,0,76,32,1,48,47,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,47,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,47,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,24,23,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,22,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,23,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,12,30,243,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,12,30,243,226,0,30,0,226,12,30,243,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,12,30,243,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,12,30,243,226,0,30,0,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,4,2,4,2,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,12,30,243,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,12,30,243,226,12,30,243,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,12,30,243,226,0,30,0,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,4,2,4,2,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,4,2,4,2,4,2,4,128,6,226,0,30,0,226,0,30,7,226,13,30,244,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,4,2,4,2,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,12,30,243,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,0,30,0,226,12,30,243,226,12,30,243,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,3,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,13,30,244,226,0,30,0,226,12,30,243,226,0,30,0,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,4,2,4,2,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,12,30,243,226,0,30,0,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,0,30,0,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,4,2,4,2,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,12,30,243,226,0,30,0,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,4,2,4,2,4,2,4,128,6,226,0,30,0,226,0,30,7,226,12,30,243,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,12,30,243,226,0,30,0,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,4,2,4,2,3,3,3,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,12,30,243,226,0,30,0,226,12,30,243,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,4,2,4,2,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,12,30,243,226,12,30,243,226,0,30,0,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,4,2,4,2,3,3,3,128,6,226,0,30,0,226,0,30,7,226,12,30,243,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,12,30,243,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,3,3,3,3,4,2,4,128,6,226,0,30,0,226,0,30,7,226,0,30,0,226,12,30,243,0,2,0,12,0,28,32,0,0,16,32,1,8,7,1,2,1,2,1,1,2,1,7,25,60,60,0,232,196,196,232,7,60,0,232,196,196,232,25,60,4,3,0,3,3,3,128,2,226,0,30,3,226,0,30,0,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,3,3,3,3,4,2,4,128,6,226,0,30,0,226,0,30,7,226,0,30,0,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,4,2,4,2,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,12,30,243,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,12,30,243,226,13,30,244,0,2,0,12,0,124,32,0,0,64,32,1,40,39,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,39,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,39,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,20,19,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,18,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,19,226,0,30,0,226,0,30,0,226,0,30,0,226,12,30,243,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,4,2,4,2,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,12,30,243,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,13,30,244,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,3,3,3,3,4,2,4,128,6,226,0,30,0,226,0,30,7,226,0,30,0,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,3,3,3,3,3,3,3,3,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,0,30,0,226,0,30,0,226,0,30,0,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,12,30,243,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,3,3,3,3,3,3,3,128,6,226,0,30,0,226,0,30,7,226,0,30,0,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,3,3,3,3,3,3,3,3,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,0,30,0,226,0,30,0,226,0,30,0,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,3,3,3,3,3,3,3,128,6,226,0,30,0,226,0,30,7,226,0,30,0,226,0,30,0,0,2,0,12,0,28,32,0,0,16,32,1,8,7,1,2,1,2,1,1,2,1,7,25,60,60,0,232,196,196,232,7,60,0,232,196,196,232,25,60,4,3,0,4,2,4,128,2,226,0,30,3,226,13,30,244,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,4,2,4,2,4,2,4,128,6,226,0,30,0,226,0,30,7,226,13,30,244,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,0,30,0,226,12,30,243,0,2,0,12,0,100,32,0,0,52,32,1,32,31,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,31,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,31,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,16,15,0,4,2,4,2,3,3,3,3,3,3,3,3,4,2,4,128,14,226,0,30,0,226,0,30,0,226,0,30,0,226,0,30,15,226,13,30,244,226,0,30,0,226,0,30,0,226,12,30,243,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,3,3,3,3,4,2,4,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,0,30,0,226,12,30,243,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,4,2,4,2,3,3,3,128,6,226,0,30,0,226,0,30,7,226,13,30,244,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,3,3,3,3,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,13,30,244,226,0,30,0,226,0,30,0,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,4,2,4,2,3,3,3,128,6,226,0,30,0,226,0,30,7,226,13,30,244,226,0,30,0,0,2,0,12,0,28,32,0,0,16,32,1,8,7,1,2,1,2,1,1,2,1,7,25,60,60,0,232,196,196,232,7,60,0,232,196,196,232,25,60,4,3,0,4,2,4,128,2,226,0,30,3,226,12,30,243,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,4,2,4,2,3,3,3,128,6,226,0,30,0,226,0,30,7,226,12,30,243,226,0,30,0,0,2,0,12,0,76,32,0,0,40,32,1,24,23,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,23,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,23,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,12,11,0,4,2,4,2,3,3,3,3,3,3,3,128,10,226,0,30,0,226,0,30,0,226,0,30,11,226,12,30,243,226,0,30,0,226,0,30,0,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,4,2,4,2,3,3,3,128,6,226,0,30,0,226,0,30,7,226,12,30,243,226,0,30,0,0,2,0,12,0,28,32,0,0,16,32,1,8,7,1,2,1,2,1,1,2,1,7,25,60,60,0,232,196,196,232,7,60,0,232,196,196,232,25,60,4,3,0,3,3,3,128,2,226,0,30,3,226,0,30,0,0,2,0,12,0,52,32,0,0,28,32,1,16,15,1,2,1,2,1,1,2,1,2,2,1,2,1,1,2,1,15,25,60,60,0,232,196,196,232,25,60,60,0,232,196,196,232,15,60,0,232,196,196,232,25,60,60,0,232,196,196,232,25,60,8,7,0,3,3,3,3,3,3,3,128,6,226,0,30,0,226,0,30,7,226,0,30,0,226,0,30,0,0,2,0,12,0,28,32,0,0,16,32,1,8,7,1,2,1,2,1,1,2,1,7,25,60,60,0,232,196,196,232,7,60,0,232,196,196,232,25,60,4,3,0,3,3,3,128,2,226,0,30,3,226,0,30,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,9,0,0,0,7,0,1,0,2,236,70,236,64,255,96,131,135,3,206,40,110,50,131,135,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,0,2,0,12,0,40,32,0,0,46,32,1,12,11,1,3,2,1,1,3,2,3,2,1,1,3,11,14,34,0,241,222,241,14,34,0,241,222,241,11,35,241,222,222,241,35,35,241,222,222,241,35,14,13,1,1,2,3,2,1,2,1,1,2,1,2,2,1,13,5,245,245,28,45,45,239,227,211,211,227,251,11,11,13,248,8,32,48,20,8,248,248,8,32,48,48,20,8,128,2,0,12,0,14,0,0,0,16,32,1,6,5,1,3,2,1,1,3,5,14,34,0,241,222,241,5,35,241,222,222,241,35,4,3,1,3,3,1,3,238,212,18,44,3,208,15,40,15,128,2,0,12,0,7,0,0,0,7,0,1,0,3,52,248,147,217,131,135,3,211,191,25,45,131,135,0,128,2,0,12,0,7,0,0,0,7,0,1,0,3,45,115,14,210,131,135,3,211,231,65,45,131,135,0,128,2,0,12,0,11,0,0,0,11,0,1,0,7,57,67,212,212,51,61,206,206,131,139,7,206,236,50,20,206,236,50,20,131,139,0,128,2,0,12,0,15,0,0,0,11,0,1,0,128,3,55,201,0,90,129,0,166,131,132,1,45,45,132,4,186,186,70,70,226,129,0,30,131,139,0,128,2,0,12,0,15,0,0,0,11,0,1,0,2,55,0,166,129,2,90,0,201,131,130,1,211,211,134,2,186,186,30,129,2,226,70,70,131,139,0,0,2,0,12,0,23,32,0,0,22,32,1,7,6,1,2,4,3,1,4,2,6,7,15,186,34,70,241,248,129,2,231,205,231,129,7,6,0,3,4,3,2,4,1,128,5,206,50,232,206,50,23,129,1,33,70,130,0,128,2,0,12,0,15,32,0,0,18,0,1,8,7,1,1,2,3,1,2,5,4,4,3,4,6,5,4,3,24,232,28,228,129,1,32,224,7,232,206,206,24,50,50,226,30,7,246,252,4,10,4,252,226,30,0,128,2,0,12,0,48,0,0,0,55,0,1,0,27,19,19,19,251,2,15,20,26,35,35,55,55,55,227,227,227,240,251,239,226,226,225,222,221,206,191,191,191,131,132,5,231,216,198,186,186,186,135,6,29,40,48,70,70,70,35,133,27,206,206,206,236,243,239,246,222,183,186,186,186,186,20,20,20,30,30,3,2,20,21,45,50,50,50,50,50,131,129,11,50,50,50,49,40,49,60,60,60,55,20,20,132,7,7,0,1,246,246,246,252,246,132,128,2,0,12,0,10,32,0,0,6,0,1,0,2,1,1,2,1,26,230,1,158,0,135,128,1,76,76,132,0,128,2,0,12,0,58,0,0,0,55,32,1,0,26,30,30,30,34,37,41,41,41,24,0,246,247,227,227,227,227,227,227,227,227,233,255,2,249,246,0,247,131,128,8,236,248,8,20,32,40,52,59,59,129,5,30,40,33,22,14,6,129,2,49,6,4,129,1,59,59,131,17,16,1,1,2,1,1,3,1,3,1,1,1,2,2,1,3,1,1,16,226,226,212,206,206,216,20,60,60,51,39,30,246,236,20,216,235,128,11,253,242,239,236,216,0,20,17,12,7,0,226,129,1,216,216,128,2,0,12,0,7,0,0,0,7,0,1,0,3,50,15,186,191,131,135,3,216,206,30,40,131,135,0,128,1,0,8,0,23,0,0,0,0,246,129,6,43,90,90,232,232,239,246,131,0,75,129,0,7,130,2,32,74,75,131,128,2,0,12,0,14,0,0,0,16,32,1,6,5,1,3,2,1,1,3,5,14,34,0,241,222,241,5,34,240,221,221,240,34,4,3,1,3,3,1,3,238,212,18,44,3,222,29,54,29,128,2,0,12,0,7,0,0,0,7,0,1,0,3,62,60,191,228,131,135,3,216,216,40,40,131,135,0,128,2,0,12,0,35,0,0,0,33,0,1,0,15,20,20,58,84,84,84,60,25,40,231,216,231,236,236,236,8,131,128,13,187,187,209,237,3,21,21,43,17,246,1,253,246,246,132,15,216,216,206,196,196,196,206,216,216,40,40,31,20,20,20,246,131,128,6,10,10,5,0,250,246,246,129,2,246,247,252,134,0,128,2,0,12,0,42,0,0,0,32,32,1,0,1,246,252,130,15,5,9,9,230,230,213,196,196,196,222,246,241,239,250,248,246,131,129,5,4,9,254,7,25,2,130,8,227,216,194,171,171,171,165,0,254,132,10,9,0,1,1,1,3,3,3,3,3,1,9,4,0,250,250,240,4,54,24,24,18,129,5,10,20,10,0,50,60,129,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,0,2,0,12,0,40,32,0,0,52,32,1,12,11,1,3,2,1,1,3,2,3,2,1,1,3,11,14,34,0,241,222,241,14,34,0,241,222,241,11,34,240,221,221,240,34,34,240,221,221,240,34,16,15,0,1,1,1,2,1,3,1,2,1,1,1,2,1,3,1,15,40,21,252,252,21,40,84,84,216,197,172,172,197,216,4,4,15,7,7,32,51,95,95,51,32,7,7,32,51,95,95,51,32,128,2,0,12,0,14,0,0,0,16,32,1,6,5,1,3,2,1,1,3,5,14,34,0,241,222,241,5,35,241,222,222,241,35,4,3,1,3,3,1,3,238,212,18,44,3,246,53,78,53,128,2,0,12,0,7,0,0,0,11,0,1,0,3,46,71,167,172,131,135,3,226,186,40,30,131,128,1,30,30,132,0,128,2,0,12,0,7,0,0,0,11,0,1,0,3,75,80,176,201,131,135,3,236,226,80,40,131,128,1,30,30,132,0,128,2,0,12,0,14,0,0,0,11,0,1,0,1,25,30,64,255,126,4,151,115,120,216,241,131,139,7,246,216,40,40,226,196,10,20,131,139,128,2,0,12,0,15,0,0,0,15,0,1,0,7,20,45,211,236,75,250,6,181,131,132,1,34,34,132,7,211,191,55,35,201,38,208,45,131,132,1,177,177,132,0,128,2,0,12,0,15,0,0,0,15,0,1,0,7,45,20,181,49,207,75,236,211,131,130,1,173,173,134,2,196,216,50,129,2,206,40,60,131,130,1,30,30,134,0,0,2,0,12,0,21,32,0,0,22,32,1,6,5,3,2,2,1,2,2,5,20,191,0,30,65,236,128,2,232,205,205,129,6,5,1,2,2,3,1,2,5,247,236,90,213,166,20,5,236,0,2,30,2,0,0,128,2,0,12,0,50,0,0,0,34,32,1,0,128,22,15,20,20,20,15,0,241,236,236,236,241,0,18,46,46,46,18,0,238,210,210,210,238,131,129,2,5,0,251,130,15,251,0,5,0,216,216,241,0,15,39,39,39,15,0,241,216,131,10,9,1,3,1,2,3,1,5,3,3,1,9,227,196,227,29,60,29,236,9,20,9,9,246,5,10,10,251,246,241,226,14,30,0,128,2,0,12,0,57,0,0,0,56,0,1,0,27,20,20,20,8,252,255,13,13,9,34,41,64,64,64,238,238,238,249,4,247,234,237,227,217,213,192,192,192,131,128,1,30,15,130,6,235,212,192,175,175,175,236,129,1,236,246,130,6,21,43,66,81,81,81,30,132,27,236,236,236,240,0,255,237,216,210,210,199,174,174,174,20,20,20,16,0,250,5,20,23,47,60,80,80,80,131,129,14,22,30,30,30,41,50,52,60,60,60,40,30,30,30,8,130,5,249,246,247,236,236,236,133,128,2,0,12,0,6,0,0,0,7,0,1,0,135,128,1,156,156,132,135,3,236,40,40,236,131,128,2,0,12,0,46,0,0,0,47,0,1,0,22,29,29,29,38,34,41,50,50,50,10,253,247,20,16,10,236,236,236,237,226,229,226,226,131,129,9,11,16,10,13,27,39,65,65,65,50,131,5,10,22,18,10,12,4,132,22,231,231,231,228,231,212,191,191,191,211,222,231,231,238,0,30,30,30,24,20,14,5,5,131,129,13,5,18,20,7,253,246,226,226,226,226,0,10,10,10,129,2,2,0,252,133,128,2,0,12,0,24,0,0,0,21,0,1,0,9,33,63,63,76,80,80,236,236,13,33,131,4,50,226,226,229,232,129,2,8,47,50,131,130,5,227,196,196,20,20,10,132,4,236,30,30,25,13,129,2,247,238,236,131,128,2,0,12,0,7,0,0,0,7,0,1,0,3,49,49,193,207,131,135,3,216,216,40,40,131,135,0,128,2,0,12,0,7,0,0,0,7,0,1,0,3,50,95,206,216,131,135,3,216,226,50,40,131,135,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,128,2,0,12,0,2,0,0,0,2,0,1,0,132,132,132,132,0,0,2,0,12,0,48,32,0,0,55,32,1,16,15,0,1,1,1,2,3,2,1,1,3,2,3,2,1,1,3,15,50,100,255,215,84,104,70,55,36,55,210,230,196,181,162,181,132,3,206,187,187,206,129,4,206,187,187,206,0,18,17,0,1,1,1,1,1,1,2,1,2,2,1,3,1,2,3,2,1,17,218,198,32,52,232,220,204,204,220,244,4,4,24,8,8,47,64,64,131,13,248,248,8,32,48,48,20,8,248,8,32,48,20,8,0,0,2,0,12,0,21,32,0,0,21,32,1,6,5,1,2,2,3,1,2,5,13,24,186,39,70,232,129,3,230,206,231,0,6,5,3,2,1,2,2,2,5,196,35,20,236,221,60,128,2,37,70,70,129,0,2,0,12,0,21,32,0,0,22,32,1,6,5,1,2,2,3,1,2,5,11,24,175,39,81,232,129,3,244,200,244,0,6,5,1,2,2,3,2,2,5,232,206,40,237,216,50,5,236,0,17,30,0,246,0,128,2,0,12,0,103,0,0,0,89,32,1,0,51,24,24,232,232,24,24,232,232,170,170,20,56,94,94,94,65,40,170,170,10,250,232,232,232,223,216,24,24,170,170,230,230,10,10,170,170,0,45,94,94,94,54,20,170,170,0,244,232,232,232,25,70,131,0,47,129,3,47,0,232,232,129,14,154,154,154,186,216,3,51,51,51,4,4,4,252,246,251,133,13,35,231,231,35,4,205,205,205,249,30,63,102,102,102,130,4,4,10,8,4,4,131,30,29,1,2,2,2,2,1,3,3,1,2,3,2,1,2,2,2,2,2,1,1,1,1,1,1,1,1,2,3,2,1,29,187,69,187,69,56,0,196,0,56,100,20,9,0,236,56,56,30,56,0,232,196,196,196,232,0,56,0,20,61,100,128,8,204,74,0,64,64,20,224,224,242,134,12,32,32,32,8,246,222,192,192,192,0,10,14,14,0,128,2,0,12,0,106,0,0,0,95,0,1,0,13,24,24,232,232,24,24,232,232,0,10,23,24,12,5,129,31,48,98,98,98,86,66,165,217,24,24,24,7,10,254,250,235,54,49,19,10,206,158,158,158,155,154,66,27,232,232,232,243,131,71,249,136,249,90,249,90,249,136,6,177,6,122,6,122,6,177,129,16,251,246,141,151,162,162,162,192,221,237,17,30,121,102,60,20,19,130,16,1,12,89,88,94,94,94,59,20,14,248,247,161,177,186,221,238,132,7,187,187,69,69,187,187,69,69,129,37,236,236,248,247,6,0,216,190,190,190,197,206,0,249,236,236,236,6,30,15,33,20,226,249,8,30,48,66,66,66,60,50,31,22,20,20,20,252,131,0,198,129,3,198,0,59,59,130,14,2,0,81,82,81,81,81,55,20,251,233,231,215,224,8,132,16,247,0,175,168,175,175,175,204,236,6,9,10,8,3,234,10,14,132,128,2,0,12,0,105,0,0,0,101,0,1,0,129,65,0,175,0,175,1,30,30,129,41,23,23,231,231,2,12,25,26,14,7,2,2,50,100,100,100,88,68,167,219,26,26,26,253,247,248,197,160,160,160,157,156,68,29,234,234,234,245,23,23,231,231,131,128,9,131,5,251,106,242,211,45,0,206,206,130,16,251,246,149,155,162,162,162,192,221,237,17,30,121,102,60,20,19,129,13,94,94,63,20,14,248,247,161,177,186,221,238,0,94,129,0,94,131,11,252,252,201,201,16,16,15,15,184,184,66,66,129,35,236,236,248,247,6,0,216,190,190,190,197,206,0,249,236,236,236,250,9,10,37,66,66,66,60,50,31,22,20,20,20,252,184,184,66,66,131,10,226,30,246,10,186,251,40,216,0,12,12,130,14,2,0,89,86,81,81,81,55,20,251,233,231,215,224,8,131,13,175,175,208,236,6,9,10,8,3,234,10,14,0,175,129,0,175,131,0,128,2,0,12,0,107,0,0,0,99,0,1,0,2,55,1,1,129,65,255,92,255,92,42,55,78,62,80,102,102,102,90,70,169,221,28,28,28,255,249,233,231,12,115,64,10,249,199,162,162,162,159,158,70,31,236,236,236,28,25,233,233,25,233,25,25,233,131,20,30,42,208,247,112,248,2,161,2,154,163,197,221,237,17,30,121,102,60,20,19,130,17,32,52,114,112,104,104,104,67,20,14,248,247,161,177,186,221,252,15,65,255,120,255,120,129,1,65,65,133,0,59,129,4,255,255,80,80,59,129,39,216,190,190,190,197,206,0,249,236,236,236,250,9,246,10,49,27,4,251,9,37,66,66,66,60,50,31,22,20,20,20,252,184,66,66,184,66,184,184,66,131,18,1,216,40,24,216,10,246,61,0,71,71,49,20,251,233,231,215,224,8,132,19,22,40,200,192,185,185,185,212,236,6,9,10,8,3,234,10,14,0,71,71,129,1,196,196,133,0,128,2,0,12,0,109,0,0,0,104,0,1,0,2,27,1,1,129,65,255,92,255,92,36,27,21,21,229,229,58,42,69,98,98,98,86,66,165,217,24,24,24,251,245,246,195,158,158,158,155,154,66,27,232,232,232,15,21,21,229,229,129,65,0,175,0,175,135,24,21,42,208,247,112,248,2,162,0,173,173,0,11,173,180,205,221,237,17,30,121,102,60,20,19,129,13,94,94,63,20,14,248,247,161,177,186,221,254,22,94,129,8,94,0,131,5,251,93,229,211,45,131,0,231,129,46,69,69,80,80,231,186,186,68,68,2,2,218,192,192,192,199,208,2,251,238,238,238,252,11,12,39,68,68,68,62,52,33,24,22,22,22,254,186,186,68,68,237,237,186,186,62,62,133,22,23,216,40,24,216,10,246,93,0,91,91,0,10,91,91,60,20,251,233,231,215,224,8,131,13,175,175,208,236,6,9,10,8,3,234,10,19,10,175,129,8,175,226,30,246,10,166,231,40,216,131,0,1,0,0,7,215,0,66,121,53,134,224,95,15,60,245,0,11,8,0,0,0,0,0,216,207,225,101,0,0,0,0,219,32,55,250,242,224,251,60,5,104,8,232,0,0,0,6,0,2,0,1,0,0,0,0,0,1,0,0,7,108,254,32,0,0,4,176,242,224,251,179,5,104,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,82,4,176,0,128,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,45,4,176,0,42,4,176,0,42,4,176,0,160,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,160,4,176,0,42,4,176,0,160,4,176,0,42,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,128,4,176,0,150,4,176,0,160,4,176,0,64,4,176,0,160,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,140,4,176,0,62,4,176,0,140,4,176,0,140,4,176,0,168,4,176,0,45,4,176,0,168,4,176,0,168,4,176,0,168,4,176,0,168,4,176,0,168,4,176,0,168,4,176,0,168,4,176,0,168,4,176,0,168,4,176,0,168,4,176,0,168,4,176,0,96,4,176,0,96,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,129,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,58,4,176,0,128,4,176,0,148,4,176,0,148,4,176,0,148,4,176,0,148,4,176,0,148,4,176,255,128,4,176,0,148,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,76,4,176,0,17,4,176,0,66,4,176,0,66,4,176,0,76,4,176,0,76,4,176,0,160,4,176,0,160,4,176,0,76,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,129,4,176,0,129,4,176,0,129,4,176,0,129,4,176,0,129,4,176,0,129,4,176,0,140,4,176,0,76,4,176,0,80,4,176,0,80,4,176,0,80,4,176,0,80,4,176,0,80,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,140,4,176,0,44,4,176,0,45,4,176,0,20,4,176,0,20,4,176,0,20,4,176,0,20,4,176,0,20,4,176,0,66,4,176,0,25,4,176,0,25,4,176,0,25,4,176,0,25,4,176,0,25,4,176,0,25,4,176,0,25,4,176,0,25,4,176,0,25,4,176,0,150,4,176,0,150,4,176,0,150,4,176,0,150,4,176,0,45,4,176,0,96,4,176,0,148,4,176,0,76,4,176,0,129,4,176,0,150,4,176,0,168,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,21,4,176,0,21,4,176,0,168,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,96,4,176,0,118,4,176,0,96,4,176,0,96,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,166,4,176,0,68,4,176,0,136,4,176,0,136,4,176,0,79,4,176,0,68,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,96,4,176,0,168,4,176,0,62,4,176,255,184,4,176,255,189,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,200,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,170,4,176,0,170,4,176,0,170,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,88,4,176,0,88,4,176,0,88,4,176,0,88,4,176,0,88,4,176,0,88,4,176,0,112,4,176,0,168,4,176,0,168,4,176,0,0,4,176,0,168,4,176,0,168,4,176,0,168,4,176,255,58,4,176,0,168,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,132,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,20,4,176,0,168,4,176,0,168,4,176,0,96,4,176,0,80,4,176,0,80,4,176,0,80,4,176,0,80,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,68,4,176,0,68,4,176,0,60,4,176,0,60,4,176,0,60,4,176,0,60,4,176,0,60,4,176,0,0,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,80,4,176,0,95,4,176,0,70,4,176,0,70,4,176,0,70,4,176,0,70,4,176,0,70,4,176,0,106,4,176,0,55,4,176,0,55,4,176,0,55,4,176,0,55,4,176,0,55,4,176,0,55,4,176,0,55,4,176,0,55,4,176,0,55,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,96,4,176,0,242,4,176,0,136,4,176,0,168,4,176,0,136,4,176,0,156,4,176,0,160,4,176,0,121,4,176,246,230,4,176,1,28,4,176,1,2,4,176,1,33,4,176,0,45,4,176,0,160,4,176,0,160,4,176,0,180,4,176,0,180,4,176,0,180,4,176,0,30,4,176,0,160,4,176,0,160,4,176,0,160,4,176,0,27,4,176,0,64,4,176,0,148,4,176,0,148,4,176,0,148,4,176,0,140,4,176,0,140,4,176,0,37,4,176,0,128,4,176,0,140,4,176,0,76,4,176,0,140,4,176,0,160,4,176,0,96,4,176,0,80,4,176,0,96,4,176,0,96,4,176,0,66,4,176,0,66,4,176,0,140,4,176,0,140,4,176,0,128,4,176,0,128,4,176,0,140,4,176,0,160,4,176,0,0,4,176,0,128,4,176,0,53,4,176,0,128,4,176,0,129,4,176,0,96,4,176,0,17,4,176,0,168,4,176,0,168,4,176,0,96,4,176,0,20,4,176,0,80,4,176,0,72,4,176,0,20,4,176,255,252,4,176,0,27,4,176,0,140,4,176,0,140,4,176,0,25,4,176,0,25,4,176,0,66,4,176,0,140,4,176,0,140,4,176,0,168,4,176,0,76,4,176,0,148,4,176,0,76,4,176,0,96,4,176,0,30,4,176,0,45,4,176,0,66,4,176,0,96,4,176,0,122,4,176,0,168,4,176,1,60,4,176,1,60,4,176,1,60,4,176,0,40,4,176,0,136,4,176,0,136,4,176,0,136,4,176,0,37,4,176,0,115,4,176,0,168,4,176,0,168,4,176,0,168,4,176,0,168,4,176,0,168,4,176,0,63,4,176,0,128,4,176,0,168,4,176,0,136,4,176,0,168,4,176,0,168,4,176,0,136,4,176,0,90,4,176,0,55,4,176,0,55,4,176,0,45,4,176,0,106,4,176,0,128,4,176,0,140,4,176,0,112,4,176,0,112,4,176,0,173,4,176,0,188,4,176,0,0,4,176,0,112,4,176,0,63,4,176,0,88,4,176,0,156,4,176,0,136,4,176,0,132,4,176,0,160,4,176,0,160,4,176,0,170,4,176,0,0,4,176,0,110,4,176,0,126,4,176,0,0,4,176,0,106,4,176,0,47,4,176,0,168,4,176,0,168,4,176,0,80,4,176,0,80,4,176,0,106,4,176,0,128,4,176,0,168,4,176,0,160,4,176,0,136,4,176,0,168,4,176,0,136,4,176,0,55,4,176,0,160,4,176,0,156,4,176,0,96,4,176,0,37,4,176,0,79,4,176,0,156,4,176,0,156,4,176,0,156,4,176,0,168,4,176,0,95,4,176,0,168,4,176,0,112,4,176,0,156,4,176,0,112,4,176,0,82,4,176,0,168,4,176,0,0,4,176,0,110,4,176,0,126,4,176,0,45,4,176,0,160,4,176,0,180,4,176,0,45,4,176,0,160,4,176,0,150,4,176,0,140,4,176,0,76,4,176,0,168,4,176,0,160,4,176,0,45,4,176,0,128,4,176,0,148,4,176,0,100,4,176,0,76,4,176,0,140,4,176,0,160,4,176,0,150,4,176,0,80,4,176,0,25,4,176,0,66,4,176,0,66,4,176,0,76,4,176,0,76,4,176,255,255,4,176,255,255,4,176,255,255,4,176,255,255,4,176,255,255,4,176,255,255,4,176,255,255,4,176,0,168,4,176,0,25,4,176,0,160,4,176,0,76,4,176,0,160,4,176,0,36,4,176,0,126,4,176,0,166,4,176,0,176,4,176,0,168,4,176,0,136,4,176,0,130,4,176,0,168,4,176,0,67,4,176,0,156,4,176,0,6,4,176,0,142,4,176,0,136,4,176,0,90,4,176,0,168,4,176,0,136,4,176,0,136,4,176,0,130,4,176,0,5,4,176,0,86,4,176,0,57,4,176,0,106,4,176,0,106,4,176,0,130,4,176,0,130,4,176,0,94,4,176,0,5,4,176,0,5,4,176,0,5,4,176,0,136,4,176,0,106,4,176,0,76,4,176,0,166,4,176,0,168,4,176,0,168,4,176,0,116,4,176,0,170,4,176,0,126,4,176,0,125,4,176,0,72,4,176,0,132,4,176,0,118,4,176,0,112,4,176,0,116,4,176,0,118,4,176,0,116,4,176,1,8,4,176,1,86,4,176,1,61,4,176,1,80,4,176,1,64,4,176,1,80,4,176,1,68,4,176,1,98,4,176,1,68,4,176,1,68,4,176,1,8,4,176,1,86,4,176,1,61,4,176,1,80,4,176,1,64,4,176,1,80,4,176,1,68,4,176,1,98,4,176,1,68,4,176,1,68,4,176,1,8,4,176,1,86,4,176,1,61,4,176,1,80,4,176,1,64,4,176,1,80,4,176,1,68,4,176,1,98,4,176,1,68,4,176,1,68,4,176,1,8,4,176,1,86,4,176,1,61,4,176,1,80,4,176,1,64,4,176,1,80,4,176,1,68,4,176,1,98,4,176,1,68,4,176,1,68,4,176,0,94,4,176,0,82,4,176,0,82,4,176,0,94,4,176,0,82,4,176,0,76,4,176,0,76,4,176,0,94,4,176,1,196,4,176,1,146,4,176,1,196,4,176,1,146,4,176,0,54,4,176,1,196,4,176,1,196,4,176,0,156,4,176,0,154,4,176,1,196,4,176,1,48,4,176,0,110,4,176,0,182,4,176,0,120,4,176,1,196,4,176,0,100,4,176,0,104,4,176,0,104,4,176,1,10,4,176,0,202,4,176,1,0,4,176,0,206,4,176,1,116,4,176,0,202,4,176,0,152,4,176,0,180,4,176,0,221,4,176,0,211,4,176,0,100,4,176,0,100,4,176,0,70,4,176,0,40,4,176,0,40,4,176,0,100,4,176,0,100,4,176,0,100,4,176,0,100,4,176,1,116,4,176,0,150,4,176,0,200,4,176,0,150,4,176,1,166,4,176,1,116,4,176,1,140,4,176,0,76,4,176,0,116,4,176,0,236,4,176,1,10,4,176,1,26,4,176,1,226,4,176,252,104,4,176,247,184,4,176,247,184,4,176,252,104,4,176,252,104,4,176,247,184,4,176,252,104,4,176,247,184,4,176,252,104,4,176,252,120,4,176,252,64,4,176,252,67,4,176,253,108,4,176,252,63,4,176,252,216,4,176,253,160,4,176,249,244,4,176,247,236,4,176,248,40,4,176,253,120,4,176,252,216,4,176,253,160,4,176,249,244,4,176,247,236,4,176,252,216,4,176,252,216,4,176,252,224,4,176,248,210,4,176,253,136,4,176,253,160,4,176,248,200,4,176,252,4,4,176,247,84,4,176,252,220,4,176,252,220,4,176,252,66,4,176,252,22,4,176,252,139,4,176,251,252,4,176,247,76,4,176,251,252,4,176,251,252,4,176,252,104,4,176,252,84,4,176,252,104,4,176,252,104,4,176,252,104,4,176,252,104,4,176,252,104,4,176,247,184,4,176,243,8,4,176,252,104,4,176,252,104,4,176,247,184,4,176,252,48,4,176,252,48,4,176,247,128,4,176,252,48,4,176,252,98,4,176,247,218,4,176,252,98,4,176,247,184,4,176,252,104,4,176,1,196,4,176,1,146,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,160,4,176,0,96,4,176,0,136,4,176,0,96,4,176,0,72,4,176,0,129,4,176,0,96,4,176,0,79,4,176,0,62,4,176,0,78,4,176,0,30,4,176,0,96,4,176,0,70,4,176,0,0,4,176,0,76,4,176,0,109,4,176,0,120,4,176,0,76,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,80,4,176,0,164,4,176,0,80,4,176,0,109,4,176,0,80,4,176,0,80,4,176,0,0,4,176,0,25,4,176,1,48,4,176,0,106,4,176,0,100,4,176,255,150,4,176,0,68,4,176,1,146,4,176,0,100,4,176,0,100,4,176,0,100,4,176,0,100,4,176,0,121,4,176,0,100,4,176,0,100,4,176,0,100,4,176,0,146,4,176,0,96,4,176,0,126,4,176,0,116,4,176,0,100,4,176,0,100,4,176,0,100,4,176,0,100,4,176,0,204,4,176,0,100,4,176,0,136,4,176,0,68,4,176,0,76,4,176,0,45,4,176,0,80,4,176,0,150,4,176,0,86,4,176,0,156,4,176,0,118,4,176,0,100,4,176,0,54,4,176,0,32,4,176,0,100,4,176,0,121,4,176,0,194,4,176,0,100,4,176,0,194,4,176,0,70,4,176,0,65,4,176,0,194,4,176,0,194,4,176,0,194,4,176,0,194,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,2,88,4,176,4,26,4,176,0,0,4,176,2,88,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,2,88,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,75,4,176,0,75,4,176,0,0,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,2,88,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,0,4,176,1,48,4,176,0,75,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,75,4,176,0,75,4,176,0,75,4,176,2,88,4,176,2,88,4,176,0,75,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,80,4,176,0,0,4,176,0,0,4,176,1,44,4,176,0,0,4,176,0,0,4,176,1,44,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,1,44,4,176,1,44,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,150,4,176,0,150,4,176,0,225,4,176,0,225,4,176,0,0,4,176,0,120,4,176,0,0,4,176,0,60,4,176,0,0,4,176,0,120,4,176,0,0,4,176,0,60,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,120,4,176,0,60,4,176,0,120,4,176,0,60,4,176,0,131,4,176,0,195,4,176,0,131,4,176,0,208,4,176,0,131,4,176,0,195,4,176,0,131,4,176,0,208,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,255,150,4,176,255,150,4,176,1,26,4,176,255,150,4,176,255,150,4,176,255,150,4,176,1,26,4,176,1,26,4,176,255,150,4,176,255,150,4,176,1,26,4,176,255,150,4,176,255,150,4,176,1,26,4,176,255,150,4,176,255,150,4,176,255,150,4,176,1,132,4,176,1,132,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,1,238,4,176,1,132,4,176,255,150,4,176,255,150,4,176,255,150,4,176,1,238,4,176,0,150,4,176,1,132,4,176,1,132,4,176,255,150,4,176,255,150,4,176,1,132,4,176,255,150,4,176,255,150,4,176,255,150,4,176,0,37,4,176,1,132,4,176,1,238,4,176,0,66,4,176,1,132,4,176,1,132,4,176,255,150,4,176,255,150,4,176,1,132,4,176,1,132,4,176,1,132,4,176,255,150,4,176,255,150,4,176,1,132,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,1,238,4,176,255,150,4,176,1,238,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,150,4,176,1,238,4,176,1,238,4,176,255,150,4,176,255,150,4,176,1,238,4,176,255,150,4,176,255,150,4,176,255,150,4,176,0,37,4,176,1,238,4,176,1,238,4,176,0,66,4,176,1,238,4,176,1,238,4,176,1,132,4,176,255,150,4,176,255,150,4,176,1,238,4,176,1,238,4,176,255,150,4,176,255,150,4,176,1,238,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,1,26,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,1,132,4,176,1,132,4,176,255,150,4,176,255,150,4,176,255,150,4,176,255,150,4,176,1,132,4,176,1,238,4,176,255,150,4,176,255,150,4,176,1,238,4,176,255,150,4,176,255,150,4,176,1,26,4,176,255,150,4,176,255,150,4,176,1,132,4,176,255,150,4,176,255,150,4,176,1,238,4,176,255,150,4,176,255,150,4,176,1,238,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,2,88,4,176,4,26,4,176,0,0,4,176,2,88,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,2,88,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,0,4,176,0,31,4,176,0,136,4,176,0,36,4,176,0,89,4,176,0,49,4,176,0,69,4,176,0,109,4,176,0,126,4,176,0,0,4,176,0,108,4,176,0,56,4,176,0,36,4,176,0,69,4,176,0,26,4,176,0,26,4,176,0,26,4,176,0,29,4,176,0,52,4,176,1,2,4,176,1,206,4,176,0,242,4,176,1,244,4,176,1,244,4,176,0,220,4,176,0,0,4,176,0,220,4,176,0,58,4,176,0,76,4,176,0,80,4,176,0,75,4,176,0,0,4,176,0,0,4,176,0,212,4,176,1,6,4,176,1,10,4,176,1,72,4,176,1,104,4,176,1,6,4,176,0,0,4,176,1,168,4,176,1,159,4,176,1,29,4,176,1,119,4,176,0,75,4,176,0,0,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,75,4,176,0,80,4,176,0,75,4,176,0,0,4,176,0,212,4,176,1,72,4,176,0,0,4,176,1,159,4,176,1,29,4,176,1,119,4,176,252,10,4,176,253,22,4,176,253,68,4,176,253,114,4,176,253,198,4,176,245,72,4,176,249,112,4,176,249,152,4,176,253,22,4,176,253,109,4,176,252,10,4,176,252,64,4,176,247,184,4,176,252,104,4,176,247,184,4,176,247,184,4,176,252,4,4,176,247,84,4,176,247,184,4,176,252,104,4,176,247,184,4,176,247,184,4,176,247,84,4,176,252,104,4,176,247,184,4,176,252,216,4,176,253,74,4,176,247,184,4,176,252,104,4,176,247,184,4,176,247,184,4,176,247,184,4,176,252,64,4,176,247,144,4,176,247,144,4,176,247,144,4,176,252,238,4,176,242,224,4,176,252,84,4,176,247,164,4,176,252,179,4,176,248,144,4,176,243,224,4,176,247,164,4,176,252,24,4,176,247,104,4,176,252,84,4,176,247,164,4,176,253,74,4,176,247,144,4,176,242,224,4,176,247,144,4,176,247,144,4,176,252,76,4,176,252,64,4,176,247,144,4,176,247,144,4,176,247,164,4,176,252,64,4,176,247,164,4,176,247,144,4,176,252,64,4,176,247,144,4,176,252,24,4,176,252,24,4,176,253,68,4,176,252,25,4,176,252,104,4,176,247,104,4,176,252,44,4,176,251,220,4,176,0,156,4,176,0,5,4,176,0,0,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,0,200,4,176,2,188,4,176,2,188,4,176,2,188,4,176,0,200,4,176,0,200,4,176,2,188,4,176,0,200,4,176,0,200,4,176,2,188,4,176,2,188,4,176,0,200,4,176,0,200,4,176,2,188,4,176,0,200,4,176,0,200,4,176,2,188,4,176,2,188,4,176,2,188,4,176,0,200,4,176,0,200,4,176,2,188,4,176,0,200,4,176,0,200,4,176,2,188,4,176,2,188,4,176,0,200,4,176,0,200,4,176,2,188,4,176,0,200,4,176,0,200,4,176,2,188,4,176,1,116,4,176,1,146,4,176,1,116,4,176,1,176,4,176,0,170,0,0,1,0,0,0,1,210,0,0,1,33,0,0,1,213,0,0,0,219,0,0,1,18,0,0,1,18,0,0,0,251,0,0,1,106,0,0,0,240,0,0,0,170,0,0,1,100,0,0,1,236,0,0,1,195,0,0,1,210,0,0,1,159,0,0,2,2,0,0,1,156,0,0,1,33,0,0,1,213,4,176,1,0,4,176,1,210,4,176,1,33,4,176,1,213,4,176,0,219,4,176,1,18,4,176,1,18,4,176,0,251,4,176,1,106,4,176,0,240,4,176,0,170,4,176,2,2,4,176,1,156,0,0,1,2,0,0,1,210,0,0,0,239,0,0,1,213,0,0,0,249,0,0,1,3,0,0,0,254,0,0,0,226,0,0,1,106,0,0,0,215,0,0,0,213,0,0,1,100,0,0,1,135,0,0,1,223,0,0,2,7,0,0,0,240,4,176,1,213,4,176,1,213,4,176,0,136,0,0,0,253,0,0,1,0,4,176,0,0,0,0,0,160,0,129,252,10,252,24,247,104,0,0,0,0,0,0,0,92,0,0,0,178,0,0,0,214,0,0,0,250,0,0,1,48,0,0,1,102,0,0,1,156,0,0,1,212,0,0,2,10,0,0,2,46,0,0,2,82,0,0,2,136,0,0,2,190,0,0,2,244,0,0,3,44,0,0,3,98,0,0,3,136,0,0,3,174,0,0,3,210,0,0,3,246,0,0,4,26,0,0,4,188,0,0,4,226,0,0,5,10,0,0,5,46,0,0,5,196,0,0,5,232,0,0,6,152,0,0,7,4,0,0,7,40,0,0,7,76,0,0,7,112,0,0,7,148,0,0,7,184,0,0,8,24,0,0,8,148,0,0,8,184,0,0,8,200,0,0,9,46,0,0,9,82,0,0,9,118,0,0,9,154,0,0,9,190,0,0,9,244,0,0,10,42,0,0,10,96,0,0,10,152,0,0,10,206,0,0,10,244,0,0,11,24,0,0,11,62,0,0,11,98,0,0,11,134,0,0,11,170,0,0,12,92,0,0,13,14,0,0,13,30,0,0,13,66,0,0,13,202,0,0,14,28,0,0,14,188,0,0,14,224,0,0,15,4,0,0,15,40,0,0,15,78,0,0,15,114,0,0,15,196,0,0,16,42,0,0,16,78,0,0,16,114,0,0,16,194,0,0,17,90,0,0,17,126,0,0,17,162,0,0,17,198,0,0,17,236,0,0,18,16,0,0,18,54,0,0,18,90,0,0,18,126,0,0,18,162,0,0,19,58,0,0,19,94,0,0,19,194,0,0,19,232,0,0,20,94,0,0,20,132,0,0,20,188,0,0,20,226,0,0,21,52,0,0,21,90,0,0,21,130,0,0,21,218,0,0,22,96,0,0,22,188,0,0,22,224,0,0,23,4,0,0,23,42,0,0,23,196,0,0,24,84,0,0,24,120,0,0,24,208,0,0,24,244,0,0,25,24,0,0,25,60,0,0,25,114,0,0,25,168,0,0,25,222,0,0,26,22,0,0,26,76,0,0,26,114,0,0,26,152,0,0,26,188,0,0,26,224,0,0,27,6,0,0,27,42,0,0,27,80,0,0,27,116,0,0,27,152,0,0,27,188,0,0,27,226,0,0,28,6,0,0,28,170,0,0,29,30,0,0,29,148,0,0,29,184,0,0,29,220,0,0,30,146,0,0,31,0,0,0,31,112,0,0,31,242,0,0,32,114,0,0,32,150,0,0,32,186,0,0,32,224,0,0,33,124,0,0,33,160,0,0,33,196,0,0,33,232,0,0,34,12,0,0,34,50,0,0,34,218,0,0,35,88,0,0,35,146,0,0,35,232,0,0,36,12,0,0,36,50,0,0,36,88,0,0,36,168,0,0,36,204,0,0,36,240,0,0,37,20,0,0,37,58,0,0,37,96,0,0,37,132,0,0,37,168,0,0,38,32,0,0,38,68,0,0,38,106,0,0,38,142,0,0,38,178,0,0,38,214,0,0,38,252,0,0,39,32,0,0,39,186,0,0,39,224,0,0,40,4,0,0,40,66,0,0,40,82,0,0,40,194,0,0,40,230,0,0,41,10,0,0,41,48,0,0,41,84,0,0,41,178,0,0,42,4,0,0,42,40,0,0,42,76,0,0,42,114,0,0,42,152,0,0,42,188,0,0,42,224,0,0,43,4,0,0,43,40,0,0,43,126,0,0,43,162,0,0,43,198,0,0,43,234,0,0,44,34,0,0,44,70,0,0,44,106,0,0,44,142,0,0,44,178,0,0,44,214,0,0,45,34,0,0,45,218,0,0,45,254,0,0,46,34,0,0,46,88,0,0,46,142,0,0,46,196,0,0,46,252,0,0,47,50,0,0,47,86,0,0,47,122,0,0,47,178,0,0,47,232,0,0,48,32,0,0,48,90,0,0,48,144,0,0,48,182,0,0,48,220,0,0,49,0,0,0,49,38,0,0,49,74,0,0,50,76,0,0,50,114,0,0,50,172,0,0,50,208,0,0,51,224,0,0,52,4,0,0,52,138,0,0,53,0,0,0,53,36,0,0,53,72,0,0,53,108,0,0,53,144,0,0,53,180,0,0,54,64,0,0,55,2,0,0,55,168,0,0,56,74,0,0,56,204,0,0,56,240,0,0,57,20,0,0,57,56,0,0,57,92,0,0,57,148,0,0,57,202,0,0,58,2,0,0,58,60,0,0,58,114,0,0,58,152,0,0,58,188,0,0,58,226,0,0,59,6,0,0,59,44,0,0,59,80,0,0,60,32,0,0,60,48,0,0,60,64,0,0,60,100,0,0,60,228,0,0,61,126,0,0,61,218,0,0,62,160,0,0,62,196,0,0,62,232,0,0,63,12,0,0,63,48,0,0,63,84,0,0,63,182,0,0,64,48,0,0,64,86,0,0,64,124,0,0,65,0,0,0,65,96,0,0,65,132,0,0,65,168,0,0,65,204,0,0,65,242,0,0,66,24,0,0,66,60,0,0,66,98,0,0,67,28,0,0,67,64,0,0,68,14,0,0,68,50,0,0,68,198,0,0,69,46,0,0,69,84,0,0,69,200,0,0,69,238,0,0,70,94,0,0,70,190,0,0,70,226,0,0,71,90,0,0,71,128,0,0,71,168,0,0,72,36,0,0,72,182,0,0,73,28,0,0,73,64,0,0,73,192,0,0,73,228,0,0,74,10,0,0,74,160,0,0,75,56,0,0,75,92,0,0,75,196,0,0,75,232,0,0,76,12,0,0,76,48,0,0,76,104,0,0,76,158,0,0,76,214,0,0,77,16,0,0,77,70,0,0,77,108,0,0,77,146,0,0,77,182,0,0,77,220,0,0,78,4,0,0,78,40,0,0,78,78,0,0,78,114,0,0,78,152,0,0,78,188,0,0,78,226,0,0,79,6,0,0,79,190,0,0,80,50,0,0,80,186,0,0,80,222,0,0,81,2,0,0,81,198,0,0,82,90,0,0,82,236,0,0,83,126,0,0,84,14,0,0,84,50,0,0,84,86,0,0,84,126,0,0,85,26,0,0,85,62,0,0,85,98,0,0,85,134,0,0,85,170,0,0,85,208,0,0,86,174,0,0,87,10,0,0,87,130,0,0,88,8,0,0,88,150,0,0,88,186,0,0,88,224,0,0,89,182,0,0,90,58,0,0,90,94,0,0,90,130,0,0,90,166,0,0,90,204,0,0,90,242,0,0,91,22,0,0,91,60,0,0,91,232,0,0,92,12,0,0,92,50,0,0,92,88,0,0,92,128,0,0,92,164,0,0,92,202,0,0,92,238,0,0,93,188,0,0,93,226,0,0,94,6,0,0,94,68,0,0,94,84,0,0,94,194,0,0,94,230,0,0,95,10,0,0,95,48,0,0,95,84,0,0,95,176,0,0,96,28,0,0,96,64,0,0,96,100,0,0,96,138,0,0,96,176,0,0,96,212,0,0,96,250,0,0,97,30,0,0,97,66,0,0,97,156,0,0,97,192,0,0,97,228,0,0,98,8,0,0,98,172,0,0,99,68,0,0,99,104,0,0,99,140,0,0,99,176,0,0,99,212,0,0,99,248,0,0,100,8,0,0,101,154,0,0,102,60,0,0,102,158,0,0,103,2,0,0,103,18,0,0,103,138,0,0,103,154,0,0,103,210,0,0,103,246,0,0,104,64,0,0,104,226,0,0,104,242,0,0,105,22,0,0,105,60,0,0,106,150,0,0,107,70,0,0,107,164,0,0,107,200,0,0,107,236,0,0,108,182,0,0,108,218,0,0,109,64,0,0,109,80,0,0,109,96,0,0,109,112,0,0,109,190,0,0,109,206,0,0,109,222,0,0,109,238,0,0,110,78,0,0,110,114,0,0,111,0,0,0,111,16,0,0,111,104,0,0,111,200,0,0,112,44,0,0,112,164,0,0,113,8,0,0,113,116,0,0,113,244,0,0,114,114,0,0,115,20,0,0,115,178,0,0,115,194,0,0,116,70,0,0,116,210,0,0,116,226,0,0,117,8,0,0,117,24,0,0,117,130,0,0,118,32,0,0,118,232,0,0,119,92,0,0,119,176,0,0,121,28,0,0,121,242,0,0,122,90,0,0,122,106,0,0,122,210,0,0,123,74,0,0,123,184,0,0,124,14,0,0,124,30,0,0,124,46,0,0,124,82,0,0,124,194,0,0,124,230,0,0,125,92,0,0,125,154,0,0,126,68,0,0,126,84,0,0,126,234,0,0,127,154,0,0,127,212,0,0,127,248,0,0,128,68,0,0,128,222,0,0,128,238,0,0,129,18,0,0,129,56,0,0,130,122,0,0,131,36,0,0,131,128,0,0,131,164,0,0,131,200,0,0,132,140,0,0,132,176,0,0,133,18,0,0,133,148,0,0,133,230,0,0,133,246,0,0,134,68,0,0,134,84,0,0,134,100,0,0,134,158,0,0,134,174,0,0,134,210,0,0,135,210,0,0,135,226,0,0,136,56,0,0,136,150,0,0,136,250,0,0,137,110,0,0,137,210,0,0,138,56,0,0,138,180,0,0,139,44,0,0,139,200,0,0,140,88,0,0,140,104,0,0,140,248,0,0,141,132,0,0,141,148,0,0,141,186,0,0,141,202,0,0,142,66,0,0,142,216,0,0,143,154,0,0,144,64,0,0,144,148,0,0,145,242,0,0,146,204,0,0,147,52,0,0,147,134,0,0,147,236,0,0,148,100,0,0,148,208,0,0,148,224,0,0,148,240,0,0,149,0,0,0,149,36,0,0,149,164,0,0,149,200,0,0,150,94,0,0,151,6,0,0,151,22,0,0,152,110,0,0,153,38,0,0,153,54,0,0,153,76,0,0,153,98,0,0,154,42,0,0,154,104,0,0,154,120,0,0,154,136,0,0,155,32,0,0,155,170,0,0,156,78,0,0,156,194,0,0,157,60,0,0,157,210,0,0,158,132,0,0,158,148,0,0,158,164,0,0,158,180,0,0,159,4,0,0,159,20,0,0,159,36,0,0,159,52,0,0,159,164,0,0,159,180,0,0,159,196,0,0,159,212,0,0,159,228,0,0,159,244,0,0,160,72,0,0,160,88,0,0,160,104,0,0,160,120,0,0,160,222,0,0,160,238,0,0,160,254,0,0,161,14,0,0,161,30,0,0,161,138,0,0,162,40,0,0,162,146,0,0,163,12,0,0,163,114,0,0,163,212,0,0,164,66,0,0,164,172,0,0,165,74,0,0,165,112,0,0,165,150,0,0,166,46,0,0,166,214,0,0,167,160,0,0,168,20,0,0,168,194,0,0,169,90,0,0,169,226,0,0,170,76,0,0,170,212,0,0,171,52,0,0,171,158,0,0,172,50,0,0,172,212,0,0,173,56,0,0,174,16,0,0,174,32,0,0,174,146,0,0,175,30,0,0,175,172,0,0,176,50,0,0,176,146,0,0,176,242,0,0,177,160,0,0,178,64,0,0,178,176,0,0,179,76,0,0,179,112,0,0,179,150,0,0,179,190,0,0,179,226,0,0,180,8,0,0,180,48,0,0,180,84,0,0,180,120,0,0,180,156,0,0,180,192,0,0,180,228,0,0,181,108,0,0,181,236,0,0,182,80,0,0,182,202,0,0,183,132,0,0,183,230,0,0,184,142,0,0,185,50,0,0,185,136,0,0,186,74,0,0,186,234,0,0,187,92,0,0,187,110,0,0,187,128,0,0,187,146,0,0,187,164,0,0,187,182,0,0,187,200,0,0,187,218,0,0,187,236,0,0,187,254,0,0,188,16,0,0,188,34,0,0,188,52,0,0,188,70,0,0,188,88,0,0,188,106,0,0,188,124,0,0,188,142,0,0,188,160,0,0,188,178,0,0,188,196,0,0,188,212,0,0,188,228,0,0,188,244,0,0,189,4,0,0,189,20,0,0,189,36,0,0,189,52,0,0,189,68,0,0,189,84,0,0,189,100,0,0,189,198,0,0,190,40,0,0,190,150,0,0,191,54,0,0,191,150,0,0,192,28,0,0,192,170,0,0,192,254,0,0,193,150,0,0,194,24,0,0,194,64,0,0,195,20,0,0,195,220,0,0,196,218,0,0,197,220,0,0,199,20,0,0,200,54,0,0,201,34,0,0,201,90,0,0,201,130,0,0,201,228,0,0,202,54,0,0,202,86,0,0,202,168,0,0,202,250,0,0,203,170,0,0,204,86,0,0,204,104,0,0,204,172,0,0,205,60,0,0,205,86,0,0,205,194,0,0,205,210,0,0,205,246,0,0,206,32,0,0,206,74,0,0,206,168,0,0,207,4,0,0,207,190,0,0,208,120,0,0,208,198,0,0,209,22,0,0,209,88,0,0,209,154,0,0,209,220,0,0,210,28,0,0,210,44,0,0,210,60,0,0,210,98,0,0,210,136,0,0,210,152,0,0,210,168,0,0,210,184,0,0,210,220,0,0,210,244,0,0,211,6,0,0,211,32,0,0,211,58,0,0,211,84,0,0,211,126,0,0,211,170,0,0,211,192,0,0,212,46,0,0,212,160,0,0,212,230,0,0,213,42,0,0,213,68,0,0,213,110,0,0,213,164,0,0,213,240,0,0,214,92,0,0,214,154,0,0,215,6,0,0,215,158,0,0,215,252,0,0,216,136,0,0,217,18,0,0,218,12,0,0,218,218,0,0,219,238,0,0,220,84,0,0,220,252,0,0,221,74,0,0,221,100,0,0,221,134,0,0,222,16,0,0,222,170,0,0,222,196,0,0,223,40,0,0,223,66,0,0,223,100,0,0,224,60,0,0,224,202,0,0,225,104,0,0,226,10,0,0,226,44,0,0,226,68,0,0,226,94,0,0,226,126,0,0,226,214,0,0,227,68,0,0,227,92,0,0,227,116,0,0,227,142,0,0,228,106,0,0,229,94,0,0,229,118,0,0,229,150,0,0,229,174,0,0,229,198,0,0,230,124,0,0,231,142,0,0,232,52,0,0,232,78,0,0,232,102,0,0,233,96,0,0,233,122,0,0,234,212,0,0,236,132,0,0,237,24,0,0,237,152,0,0,238,106,0,0,238,130,0,0,238,220,0,0,239,90,0,0,239,194,0,0,239,220,0,0,239,254,0,0,240,24,0,0,240,82,0,0,240,120,0,0,240,138,0,0,240,154,0,0,240,154,0,0,240,154,0,0,240,154,0,0,240,154,0,0,240,154,0,0,241,94,0,0,241,222,0,0,242,98,0,0,243,10,0,0,243,218,0,0,244,140,0,0,245,72,0,0,245,218,0,0,246,138,0,0,247,26,0,0,247,124,0,0,248,62,0,0,249,38,0,0,249,186,0,0,250,94,0,0,251,4,0,0,251,136,0,0,251,228,0,0,252,94,0,0,252,222,0,0,253,108,0,0,253,252,0,0,254,234,0,0,255,130,0,0,255,254,0,1,0,144,0,1,0,224,0,1,1,70,0,1,1,210,0,1,2,68,0,1,2,84,0,1,2,100,0,1,2,172,0,1,2,188,0,1,2,254,0,1,3,66,0,1,3,122,0,1,3,232,0,1,4,38,0,1,4,76,0,1,4,146,0,1,5,10,0,1,5,70,0,1,5,154,0,1,5,232,0,1,6,54,0,1,6,148,0,1,6,244,0,1,7,68,0,1,7,94,0,1,7,206,0,1,8,6,0,1,8,66,0,1,8,254,0,1,9,70,0,1,9,190,0,1,9,206,0,1,9,222,0,1,10,44,0,1,10,144,0,1,10,224,0,1,10,240,0,1,11,6,0,1,11,60,0,1,12,6,0,1,13,18,0,1,13,106,0,1,13,122,0,1,13,202,0,1,14,34,0,1,14,114,0,1,14,200,0,1,15,70,0,1,15,190,0,1,16,72,0,1,16,206,0,1,17,84,0,1,17,110,0,1,17,136,0,1,17,162,0,1,17,188,0,1,17,214,0,1,17,240,0,1,18,10,0,1,18,36,0,1,18,62,0,1,18,88,0,1,18,114,0,1,18,140,0,1,18,166,0,1,18,192,0,1,18,218,0,1,18,244,0,1,19,14,0,1,19,42,0,1,19,70,0,1,19,96,0,1,19,124,0,1,19,150,0,1,19,182,0,1,19,222,0,1,19,254,0,1,20,32,0,1,20,60,0,1,20,98,0,1,20,130,0,1,21,28,0,1,22,64,0,1,24,124,0,1,24,180,0,1,25,24,0,1,25,132,0,1,25,250,0,1,26,114,0,1,26,232,0,1,27,96,0,1,27,134,0,1,27,174,0,1,28,36,0,1,28,168,0,1,29,30,0,1,29,150,0,1,30,14,0,1,30,134,0,1,31,6,0,1,32,150,0,1,33,26,0,1,33,48,0,1,33,124,0,1,33,182,0,1,34,38,0,1,34,110,0,1,34,184,0,1,34,244,0,1,35,48,0,1,35,88,0,1,35,130,0,1,35,170,0,1,35,210,0,1,35,242,0,1,36,36,0,1,36,102,0,1,36,166,0,1,36,230,0,1,37,38,0,1,37,104,0,1,37,162,0,1,37,190,0,1,37,246,0,1,38,18,0,1,38,44,0,1,38,86,0,1,38,128,0,1,38,154,0,1,38,196,0,1,39,40,0,1,39,100,0,1,40,250,0,1,41,64,0,1,41,136,0,1,41,234,0,1,42,70,0,1,42,170,0,1,43,66,0,1,43,94,0,1,43,138,0,1,43,196,0,1,43,252,0,1,44,50,0,1,44,106,0,1,44,162,0,1,44,224,0,1,45,30,0,1,45,94,0,1,45,158,0,1,45,200,0,1,45,228,0,1,46,14,0,1,46,42,0,1,46,68,0,1,46,94,0,1,46,120,0,1,46,148,0,1,46,196,0,1,46,246,0,1,47,42,0,1,47,94,0,1,47,178,0,1,47,242,0,1,48,50,0,1,48,76,0,1,48,104,0,1,48,152,0,1,48,202,0,1,48,230,0,1,49,0,0,1,49,28,0,1,49,56,0,1,49,106,0,1,49,156,0,1,49,210,0,1,50,6,0,1,50,32,0,1,50,58,0,1,50,84,0,1,50,108,0,1,50,156,0,1,50,206,0,1,50,254,0,1,51,46,0,1,51,112,0,1,51,164,0,1,51,216,0,1,52,0,0,1,52,66,0,1,52,116,0,1,52,168,0,1,52,208,0,1,53,44,0,1,53,108,0,1,53,174,0,1,53,222,0,1,54,10,0,1,54,54,0,1,54,92,0,1,54,126,0,1,54,170,0,1,54,204,0,1,54,248,0,1,55,42,0,1,55,82,0,1,55,116,0,1,55,162,0,1,55,196,0,1,55,242,0,1,56,38,0,1,56,90,0,1,56,134,0,1,56,178,0,1,56,220,0,1,57,8,0,1,57,36,0,1,57,76,0,1,57,110,0,1,57,144,0,1,57,172,0,1,57,200,0,1,57,236,0,1,58,44,0,1,58,120,0,1,58,148,0,1,58,204,0,1,59,8,0,1,59,36,0,1,59,76,0,1,59,110,0,1,59,148,0,1,59,182,0,1,59,210,0,1,60,6,0,1,60,46,0,1,60,86,0,1,60,140,0,1,60,184,0,1,60,226,0,1,61,20,0,1,61,64,0,1,61,108,0,1,61,160,0,1,61,216,0,1,62,18,0,1,62,76,0,1,62,134,0,1,62,192,0,1,63,8,0,1,63,44,0,1,63,78,0,1,63,116,0,1,63,158,0,1,63,186,0,1,63,224,0,1,64,2,0,1,64,36,0,1,64,62,0,1,64,88,0,1,64,126,0,1,64,182,0,1,64,252,0,1,65,22,0,1,65,72,0,1,65,128,0,1,65,156,0,1,65,194,0,1,65,230,0,1,66,6,0,1,66,38,0,1,66,66,0,1,66,116,0,1,66,154,0,1,66,192,0,1,66,246,0,1,67,34,0,1,67,78,0,1,67,128,0,1,67,172,0,1,67,216,0,1,68,12,0,1,68,68,0,1,68,114,0,1,68,156,0,1,68,198,0,1,68,248,0,1,69,30,0,1,69,74,0,1,69,106,0,1,69,150,0,1,69,184,0,1,69,236,0,1,70,18,0,1,70,62,0,1,70,94,0,1,70,138,0,1,70,172,0,1,70,222,0,1,71,6,0,1,71,48,0,1,71,118,0,1,71,168,0,1,71,220,0,1,72,14,0,1,72,54,0,1,72,94,0,1,72,146,0,1,72,186,0,1,72,226,0,1,73,40,0,1,73,88,0,1,73,136,0,1,73,162,0,1,73,188,0,1,73,214,0,1,73,240,0,1,74,10,0,1,74,36,0,1,74,62,0,1,74,88,0,1,74,114,0,1,74,140,0,1,74,166,0,1,74,192,0,1,74,218,0,1,74,244,0,1,75,14,0,1,75,40,0,1,75,66,0,1,75,94,0,1,75,122,0,1,75,148,0,1,75,176,0,1,75,202,0,1,75,234,0,1,76,18,0,1,76,50,0,1,76,84,0,1,76,112,0,1,76,150,0,1,76,182,0,1,77,78,0,1,78,108,0,1,80,162,0,1,81,140,0,1,82,124,0,1,83,50,0,1,84,42,0,1,84,194,0,1,85,138,0,1,85,238,0,1,86,184,0,1,87,16,0,1,87,58,0,1,87,120,0,1,88,98,0,1,89,58,0,1,89,244,0,1,90,90,0,1,91,72,0,1,92,16,0,1,92,224,0,1,93,156,0,1,94,74,0,1,95,22,0,1,95,120,0,1,95,162,0,1,95,224,0,1,96,8,0,1,96,70,0,1,96,140,0,1,97,10,0,1,97,162,0,1,98,106,0,1,99,50,0,1,99,90,0,1,99,148,0,1,99,212,0,1,99,238,0,1,100,14,0,1,100,42,0,1,100,70,0,1,100,102,0,1,100,130,0,1,100,158,0,1,100,194,0,1,100,222,0,1,100,254,0,1,101,54,0,1,101,82,0,1,101,122,0,1,101,164,0,1,101,222,0,1,102,20,0,1,102,58,0,1,102,114,0,1,102,168,0,1,102,250,0,1,103,82,0,1,103,122,0,1,103,184,0,1,103,242,0,1,104,44,0,1,104,90,0,1,104,178,0,1,104,218,0,1,106,58,0,1,106,120,0,1,107,70,0,1,107,170,0,1,107,196,0,1,108,88,0,1,108,190,0,1,109,64,0,1,109,148,0,1,109,250,0,1,110,218,0,1,110,244,0,1,111,174,0,1,111,200,0,1,111,234,0,1,112,12,0,1,112,108,0,1,112,192,0,1,113,68,0,1,113,198,0,1,114,114,0,1,115,30,0,1,115,116,0,1,115,210,0,1,116,104,0,1,116,130,0,1,116,228,0,1,117,150,0,1,118,22,0,1,118,160,0,1,119,82,0,1,119,116,0,1,119,228,0,1,120,84,0,1,121,6,0,1,121,166,0,1,121,192,0,1,122,128,0,1,122,152,0,1,122,186,0,1,123,32,0,1,123,154,0,1,124,36,0,1,124,70,0,1,125,38,0,1,126,50,0,1,126,76,0,1,126,110,0,1,126,210,0,1,127,98,0,1,128,42,0,1,128,252,0,1,129,190,0,1,129,216,0,1,130,94,0,1,131,2,0,1,131,200,0,1,131,234,0,1,132,192,0,1,132,226,0,1,134,10,0,1,134,114,0,1,135,18,0,1,135,156,0,1,136,230,0,1,137,98,0,1,138,60,0,1,138,246,0,1,140,32,0,1,140,138,0,1,141,250,0,1,142,124,0,1,143,36,0,1,143,36,0,1,143,82,0,1,143,160,0,1,144,14,0,1,144,156,0,1,145,76,0,1,146,30,0,1,147,16,0,1,148,36,0,1,149,24,0,1,149,232,0,1,150,218,0,1,151,172,0,1,152,92,0,1,153,44,0,1,154,30,0,1,154,240,0,1,155,158,0,1,156,110,0,1,157,30,0,1,157,172,0,1,158,92,0,1,159,44,0,1,160,30,0,1,160,240,0,1,161,158,0,1,162,110,0,1,163,30,0,1,163,172,0,1,164,90,0,1,165,42,0,1,165,218,0,1,166,104,0,1,167,24,0,1,167,168,0,1,168,22,0,1,168,166,0,1,169,88,0,1,170,42,0,1,171,28,0,1,171,238,0,1,172,158,0,1,173,110,0,1,174,30,0,1,174,174,0,1,175,94,0,1,176,46,0,1,176,222,0,1,177,108,0,1,178,26,0,1,178,168,0,1,179,20,0,1,179,162,0,1,180,82,0,1,181,34,0,1,181,210,0,1,182,96,0,1,183,14,0,1,183,156,0,1,184,10,0,1,184,152,0,1,185,70,0,1,185,214,0,1,186,68,0,1,186,210,0,1,187,66,0,1,187,144,0,1,187,254,0,1,188,142,0,1,189,62,0,1,190,14,0,1,191,0,0,1,191,210,0,1,192,130,0,1,193,84,0,1,194,6,0,1,194,148,0,1,195,66,0,1,196,18,0,1,196,194,0,1,197,80,0,1,198,0,0,1,198,144,0,1,198,254,0,1,199,140,0,1,200,58,0,1,201,10,0,1,201,186,0,1,202,72,0,1,202,248,0,1,203,136,0,1,203,244,0,1,204,128,0,1,205,46,0,1,205,188,0,1,206,42,0,1,206,184,0,1,207,38,0,1,207,114,0,1,207,224,0,1,208,112,0,1,209,34,0,1,209,242,0,1,210,162,0,1,211,50,0,1,211,226,0,1,212,114,0,1,212,224,0,1,213,112,0,1,214,30,0,1,214,172,0,1,215,26,0,1,215,168,0,1,216,22,0,1,216,100,0,1,216,210,0,1,217,98,0,1,218,16,0,1,218,158,0,1,219,12,0,1,219,154,0,1,220,8,0,1,220,86,0,1,220,196,0,1,221,80,0,1,221,190,0,1,222,12,0,1,222,120,0,1,222,198,0,1,222,244,0,1,223,66,0,1,223,176,0,1,224,62,0,1,224,238,0,1,225,190,0,1,226,176,0,1,227,130,0,1,228,48,0,1,229,0,0,1,229,176,0,1,230,64,0,1,230,240,0,1,231,194,0,1,232,116,0,1,233,2,0,1,233,178,0,1,234,66,0,1,234,176,0,1,235,64,0,1,235,240,0,1,236,194,0,1,237,116,0,1,238,2,0,1,238,178,0,1,239,66,0,1,239,174,0,1,240,60,0,1,240,236,0,1,241,122,0,1,241,232,0,1,242,118,0,1,242,228,0,1,243,50,0,1,243,160,0,1,244,48,0,1,244,224,0,1,245,176,0,1,246,96,0,1,246,238,0,1,247,156,0,1,248,42,0,1,248,154,0,1,249,42,0,1,249,218,0,1,250,106,0,1,250,216,0,1,251,102,0,1,251,212,0,1,252,32,0,1,252,142,0,1,253,30,0,1,253,206,0,1,254,94,0,1,254,204,0,1,255,90,0,1,255,200,0,2,0,22,0,2,0,132,0,2,1,18,0,2,1,128,0,2,1,206,0,2,2,58,0,2,2,136,0,2,2,182,0,2,3,4,0,2,3,116,0,2,4,2,0,2,4,176,0,2,5,128,0,2,6,48,0,2,6,192,0,2,7,112,0,2,8,0,0,2,8,110,0,2,8,252,0,2,9,172,0,2,10,60,0,2,10,170,0,2,11,58,0,2,11,170,0,2,11,248,0,2,12,102,0,2,12,244,0,2,13,164,0,2,14,52,0,2,14,162,0,2,15,50,0,2,15,162,0,2,15,238,0,2,16,92,0,2,16,236,0,2,17,90,0,2,17,168,0,2,18,20,0,2,18,98,0,2,18,144,0,2,18,222,0,2,19,76,0,2,19,220,0,2,20,138,0,2,21,24,0,2,21,136,0,2,22,22,0,2,22,132,0,2,22,210,0,2,23,66,0,2,23,208,0,2,24,62,0,2,24,140,0,2,24,250,0,2,25,72,0,2,25,118,0,2,25,196,0,2,26,52,0,2,26,194,0,2,27,48,0,2,27,126,0,2,27,236,0,2,28,58,0,2,28,104,0,2,28,182,0,2,29,36,0,2,29,114,0,2,29,158,0,2,29,234,0,2,30,22,0,2,30,38,0,2,30,54,0,2,30,70,0,2,30,110,0,2,30,126,0,2,30,216,0,2,31,16,0,2,31,56,0,2,31,96,0,2,31,154,0,2,31,208,0,2,32,8,0,2,32,82,0,2,32,166,0,2,33,16,0,2,33,52,0,2,33,158,0,2,33,198,0,2,34,2,0,2,34,58,0,2,34,98,0,2,34,180,0,2,35,14,0,2,35,30,0,2,35,46,0,2,35,62,0,2,35,78,0,2,35,94,0,2,35,110,0,2,35,126,0,2,35,142,0,2,35,158,0,2,35,174,0,2,35,190,0,2,35,206,0,2,35,222,0,2,35,238,0,2,35,254,0,2,36,88,0,2,36,144,0,2,36,184,0,2,36,224,0,2,37,24,0,2,37,80,0,2,37,136,0,2,37,202,0,2,38,42,0,2,38,148,0,2,38,184,0,2,39,18,0,2,39,76,0,2,39,116,0,2,39,156,0,2,39,172,0,2,39,188,0,2,39,204,0,2,40,64,0,2,40,130,0,2,40,196,0,2,40,196,0,2,40,196,0,2,41,158,0,2,42,98,0,2,43,78,0,2,44,62,0,2,44,240,0,1,0,0,6,88,0,144,0,36,0,92,0,15,0,2,0,16,0,47,0,154,0,0,3,8,15,131,0,3,0,3,0,0,0,28,1,86,0,1,0,0,0,0,1,0,0,6,0,0,0,1,0,0,0,0,1,1,0,10,0,6,0,1,0,0,0,0,1,2,0,5,0,16,0,1,0,0,0,0,1,3,0,9,0,21,0,1,0,0,0,0,1,4,0,7,0,30,0,1,0,0,0,0,1,5,0,8,0,37,0,1,0,0,0,0,1,6,0,4,0,45,0,3,0,1,4,9,0,0,0,100,0,49,0,3,0,1,4,9,0,1,0,26,0,149,0,3,0,1,4,9,0,2,0,14,0,175,0,3,0,1,4,9,0,3,0,68,0,189,0,3,0,1,4,9,0,4,0,42,1,1,0,3,0,1,4,9,0,5,0,32,1,43,0,3,0,1,4,9,0,6,0,40,1,75,0,3,0,1,4,9,0,7,0,130,1,115,0,3,0,1,4,9,0,8,0,28,1,245,0,3,0,1,4,9,0,9,0,20,2,17,0,3,0,1,4,9,0,11,0,48,2,37,0,3,0,1,4,9,0,12,0,48,2,37,0,3,0,1,4,9,0,13,22,212,2,85,0,3,0,1,4,9,0,14,0,54,25,41,0,3,0,1,4,9,1,0,0,12,25,95,0,3,0,1,4,9,1,1,0,20,25,107,0,3,0,1,4,9,1,2,0,10,25,127,0,3,0,1,4,9,1,3,0,18,25,137,0,3,0,1,4,9,1,4,0,14,0,175,0,3,0,1,4,9,1,5,0,16,25,155,0,3,0,1,4,9,1,6,0,8,25,171,87,101,105,103,104,116,69,120,116,114,97,76,105,103,104,116,76,105,103,104,116,83,101,109,105,76,105,103,104,116,82,101,103,117,108,97,114,83,101,109,105,66,111,108,100,66,111,108,100,0,169,0,32,0,50,0,48,0,50,0,48,0,32,0,77,0,105,0,99,0,114,0,111,0,115,0,111,0,102,0,116,0,32,0,67,0,111,0,114,0,112,0,111,0,114,0,97,0,116,0,105,0,111,0,110,0,46,0,32,0,65,0,108,0,108,0,32,0,82,0,105,0,103,0,104,0,116,0,115,0,32,0,82,0,101,0,115,0,101,0,114,0,118,0,101,0,100,0,46,0,67,0,97,0,115,0,99,0,97,0,100,0,105,0,97,0,32,0,67,0,111,0,100,0,101,0,82,0,101,0,103,0,117,0,108,0,97,0,114,0,50,0,48,0,48,0,55,0,46,0,48,0,48,0,49,0,59,0,83,0,65,0,74,0,65,0,59,0,67,0,97,0,115,0,99,0,97,0,100,0,105,0,97,0,67,0,111,0,100,0,101,0,45,0,82,0,101,0,103,0,117,0,108,0,97,0,114,0,67,0,97,0,115,0,99,0,97,0,100,0,105,0,97,0,32,0,67,0,111,0,100,0,101,0,32,0,82,0,101,0,103,0,117,0,108,0,97,0,114,0,86,0,101,0,114,0,115,0,105,0,111,0,110,0,32,0,50,0,48,0,48,0,55,0,46,0,48,0,48,0,49,0,67,0,97,0,115,0,99,0,97,0,100,0,105,0,97,0,67,0,111,0,100,0,101,0,45,0,82,0,101,0,103,0,117,0,108,0,97,0,114,0,67,0,97,0,115,0,99,0,97,0,100,0,105,0,97,0,32,0,67,0,111,0,100,0,101,0,32,0,105,0,115,0,32,0,97,0,32,0,116,0,114,0,97,0,100,0,101,0,109,0,97,0,114,0,107,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,77,0,105,0,99,0,114,0,111,0,115,0,111,0,102,0,116,0,32,0,103,0,114,0,111,0,117,0,112,0,32,0,111,0,102,0,32,0,99,0,111,0,109,0,112,0,97,0,110,0,105,0,101,0,115,0,46,0,83,0,97,0,106,0,97,0,32,0,84,0,121,0,112,0,101,0,119,0,111,0,114,0,107,0,115,0,65,0,97,0,114,0,111,0,110,0,32,0,66,0,101,0,108,0,108,0,104,0,116,0,116,0,112,0,58,0,47,0,47,0,115,0,97,0,106,0,97,0,116,0,121,0,112,0,101,0,119,0,111,0,114,0,107,0,115,0,46,0,99,0,111,0,109,0,77,0,105,0,99,0,114,0,111,0,115,0,111,0,102,0,116,0,32,0,115,0,117,0,112,0,112,0,108,0,105,0,101,0,100,0,32,0,102,0,111,0,110,0,116,0,46,0,32,0,89,0,111,0,117,0,32,0,109,0,97,0,121,0,32,0,117,0,115,0,101,0,32,0,116,0,104,0,105,0,115,0,32,0,102,0,111,0,110,0,116,0,32,0,116,0,111,0,32,0,99,0,114,0,101,0,97,0,116,0,101,0,44,0,32,0,100,0,105,0,115,0,112,0,108,0,97,0,121,0,44,0,32,0,97,0,110,0,100,0,32,0,112,0,114,0,105,0,110,0,116,0,32,0,99,0,111,0,110,0,116,0,101,0,110,0,116,0,32,0,97,0,115,0,32,0,112,0,101,0,114,0,109,0,105,0,116,0,116,0,101,0,100,0,32,0,98,0,121,0,32,0,116,0,104,0,101,0,32,0,108,0,105,0,99,0,101,0,110,0,115,0,101,0,32,0,116,0,101,0,114,0,109,0,115,0,32,0,111,0,114,0,32,0,116,0,101,0,114,0,109,0,115,0,32,0,111,0,102,0,32,0,117,0,115,0,101,0,44,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,77,0,105,0,99,0,114,0,111,0,115,0,111,0,102,0,116,0,32,0,112,0,114,0,111,0,100,0,117,0,99,0,116,0,44,0,32,0,115,0,101,0,114,0,118,0,105,0,99,0,101,0,44,0,32,0,111,0,114,0,32,0,99,0,111,0,110,0,116,0,101,0,110,0,116,0,32,0,105,0,110,0,32,0,119,0,104,0,105,0,99,0,104,0,32,0,116,0,104,0,105,0,115,0,32,0,102,0,111,0,110,0,116,0,32,0,119,0,97,0,115,0,32,0,105,0,110,0,99,0,108,0,117,0,100,0,101,0,100,0,46,0,32,0,89,0,111,0,117,0,32,0,109,0,97,0,121,0,32,0,111,0,110,0,108,0,121,0,32,0,40,0,105,0,41,0,32,0,101,0,109,0,98,0,101,0,100,0,32,0,116,0,104,0,105,0,115,0,32,0,102,0,111,0,110,0,116,0,32,0,105,0,110,0,32,0,99,0,111,0,110,0,116,0,101,0,110,0,116,0,32,0,97,0,115,0,32,0,112,0,101,0,114,0,109,0,105,0,116,0,116,0,101,0,100,0,32,0,98,0,121,0,32,0,116,0,104,0,101,0,32,0,101,0,109,0,98,0,101,0,100,0,100,0,105,0,110,0,103,0,32,0,114,0,101,0,115,0,116,0,114,0,105,0,99,0,116,0,105,0,111,0,110,0,115,0,32,0,105,0,110,0,99,0,108,0,117,0,100,0,101,0,100,0,32,0,105,0,110,0,32,0,116,0,104,0,105,0,115,0,32,0,102,0,111,0,110,0,116,0,59,0,32,0,97,0,110,0,100,0,32,0,40,0,105,0,105,0,41,0,32,0,116,0,101,0,109,0,112,0,111,0,114,0,97,0,114,0,105,0,108,0,121,0,32,0,100,0,111,0,119,0,110,0,108,0,111,0,97,0,100,0,32,0,116,0,104,0,105,0,115,0,32,0,102,0,111,0,110,0,116,0,32,0,116,0,111,0,32,0,97,0,32,0,112,0,114,0,105,0,110,0,116,0,101,0,114,0,32,0,111,0,114,0,32,0,111,0,116,0,104,0,101,0,114,0,32,0,111,0,117,0,116,0,112,0,117,0,116,0,32,0,100,0,101,0,118,0,105,0,99,0,101,0,32,0,116,0,111,0,32,0,104,0,101,0,108,0,112,0,32,0,112,0,114,0,105,0,110,0,116,0,32,0,99,0,111,0,110,0,116,0,101,0,110,0,116,0,46,0,32,0,65,0,110,0,121,0,32,0,111,0,116,0,104,0,101,0,114,0,32,0,117,0,115,0,101,0,32,0,105,0,115,0,32,0,112,0,114,0,111,0,104,0,105,0,98,0,105,0,116,0,101,0,100,0,46,0,10,0,32,0,10,0,84,0,104,0,101,0,32,0,102,0,111,0,108,0,108,0,111,0,119,0,105,0,110,0,103,0,32,0,108,0,105,0,99,0,101,0,110,0,115,0,101,0,44,0,32,0,98,0,97,0,115,0,101,0,100,0,32,0,111,0,110,0,32,0,116,0,104,0,101,0,32,0,83,0,73,0,76,0,32,0,79,0,112,0,101,0,110,0,32,0,70,0,111,0,110,0,116,0,32,0,108,0,105,0,99,0,101,0,110,0,115,0,101,0,32,0,40,0,104,0,116,0,116,0,112,0,115,0,58,0,47,0,47,0,115,0,99,0,114,0,105,0,112,0,116,0,115,0,46,0,115,0,105,0,108,0,46,0,111,0,114,0,103,0,47,0,79,0,70,0,76,0,41,0,44,0,32,0,97,0,112,0,112,0,108,0,105,0,101,0,115,0,32,0,116,0,111,0,32,0,116,0,104,0,105,0,115,0,32,0,102,0,111,0,110,0,116,0,46,0,32,0,65,0,100,0,100,0,105,0,116,0,105,0,111,0,110,0,97,0,108,0,32,0,108,0,105,0,99,0,101,0,110,0,115,0,101,0,32,0,116,0,101,0,114,0,109,0,115,0,32,0,109,0,97,0,121,0,32,0,98,0,101,0,32,0,102,0,111,0,117,0,110,0,100,0,32,0,111,0,110,0,32,0,116,0,104,0,101,0,32,0,71,0,105,0,116,0,72,0,117,0,98,0,32,0,114,0,101,0,112,0,111,0,115,0,105,0,116,0,111,0,114,0,121,0,32,0,102,0,111,0,114,0,32,0,116,0,104,0,105,0,115,0,32,0,102,0,111,0,110,0,116,0,32,0,40,0,104,0,116,0,116,0,112,0,115,0,58,0,47,0,47,0,103,0,105,0,116,0,104,0,117,0,98,0,46,0,99,0,111,0,109,0,47,0,109,0,105,0,99,0,114,0,111,0,115,0,111,0,102,0,116,0,47,0,99,0,97,0,115,0,99,0,97,0,100,0,105,0,97,0,45,0,99,0,111,0,100,0,101,0,47,0,98,0,108,0,111,0,98,0,47,0,109,0,97,0,115,0,116,0,101,0,114,0,47,0,76,0,73,0,67,0,69,0,78,0,83,0,69,0,41,0,46,0,10,0,32,0,10,0,80,0,101,0,114,0,109,0,105,0,115,0,115,0,105,0,111,0,110,0,32,0,105,0,115,0,32,0,104,0,101,0,114,0,101,0,98,0,121,0,32,0,103,0,114,0,97,0,110,0,116,0,101,0,100,0,44,0,32,0,102,0,114,0,101,0,101,0,32,0,111,0,102,0,32,0,99,0,104,0,97,0,114,0,103,0,101,0,44,0,32,0,116,0,111,0,32,0,97,0,110,0,121,0,32,0,112,0,101,0,114,0,115,0,111,0,110,0,32,0,111,0,98,0,116,0,97,0,105,0,110,0,105,0,110,0,103,0,32,0,97,0,32,0,99,0,111,0,112,0,121,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,44,0,32,0,116,0,111,0,32,0,117,0,115,0,101,0,44,0,32,0,115,0,116,0,117,0,100,0,121,0,44,0,32,0,99,0,111,0,112,0,121,0,44,0,32,0,109,0,101,0,114,0,103,0,101,0,44,0,32,0,101,0,109,0,98,0,101,0,100,0,44,0,32,0,109,0,111,0,100,0,105,0,102,0,121,0,44,0,32,0,114,0,101,0,100,0,105,0,115,0,116,0,114,0,105,0,98,0,117,0,116,0,101,0,44,0,32,0,97,0,110,0,100,0,32,0,115,0,101,0,108,0,108,0,32,0,109,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,32,0,97,0,110,0,100,0,32,0,117,0,110,0,109,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,32,0,99,0,111,0,112,0,105,0,101,0,115,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,44,0,32,0,115,0,117,0,98,0,106,0,101,0,99,0,116,0,32,0,116,0,111,0,32,0,116,0,104,0,101,0,32,0,102,0,111,0,108,0,108,0,111,0,119,0,105,0,110,0,103,0,32,0,99,0,111,0,110,0,100,0,105,0,116,0,105,0,111,0,110,0,115,0,58,0,10,0,32,0,10,0,49,0,41,0,32,0,78,0,101,0,105,0,116,0,104,0,101,0,114,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,110,0,111,0,114,0,32,0,97,0,110,0,121,0,32,0,111,0,102,0,32,0,105,0,116,0,115,0,32,0,105,0,110,0,100,0,105,0,118,0,105,0,100,0,117,0,97,0,108,0,32,0,99,0,111,0,109,0,112,0,111,0,110,0,101,0,110,0,116,0,115,0,44,0,32,0,105,0,110,0,32,0,79,0,114,0,105,0,103,0,105,0,110,0,97,0,108,0,32,0,111,0,114,0,32,0,77,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,32,0,86,0,101,0,114,0,115,0,105,0,111,0,110,0,115,0,44,0,32,0,109,0,97,0,121,0,32,0,98,0,101,0,32,0,115,0,111,0,108,0,100,0,32,0,98,0,121,0,32,0,105,0,116,0,115,0,101,0,108,0,102,0,46,0,10,0,32,0,10,0,50,0,41,0,32,0,79,0,114,0,105,0,103,0,105,0,110,0,97,0,108,0,32,0,111,0,114,0,32,0,77,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,32,0,86,0,101,0,114,0,115,0,105,0,111,0,110,0,115,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,109,0,97,0,121,0,32,0,98,0,101,0,32,0,98,0,117,0,110,0,100,0,108,0,101,0,100,0,44,0,32,0,114,0,101,0,100,0,105,0,115,0,116,0,114,0,105,0,98,0,117,0,116,0,101,0,100,0,32,0,97,0,110,0,100,0,47,0,111,0,114,0,32,0,115,0,111,0,108,0,100,0,32,0,119,0,105,0,116,0,104,0,32,0,97,0,110,0,121,0,32,0,115,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,44,0,32,0,112,0,114,0,111,0,118,0,105,0,100,0,101,0,100,0,32,0,116,0,104,0,97,0,116,0,32,0,101,0,97,0,99,0,104,0,32,0,99,0,111,0,112,0,121,0,32,0,99,0,111,0,110,0,116,0,97,0,105,0,110,0,115,0,32,0,116,0,104,0,101,0,32,0,97,0,98,0,111,0,118,0,101,0,32,0,99,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,110,0,111,0,116,0,105,0,99,0,101,0,32,0,97,0,110,0,100,0,32,0,116,0,104,0,105,0,115,0,32,0,108,0,105,0,99,0,101,0,110,0,115,0,101,0,46,0,32,0,84,0,104,0,101,0,115,0,101,0,32,0,99,0,97,0,110,0,32,0,98,0,101,0,32,0,105,0,110,0,99,0,108,0,117,0,100,0,101,0,100,0,32,0,101,0,105,0,116,0,104,0,101,0,114,0,32,0,97,0,115,0,32,0,115,0,116,0,97,0,110,0,100,0,45,0,97,0,108,0,111,0,110,0,101,0,32,0,116,0,101,0,120,0,116,0,32,0,102,0,105,0,108,0,101,0,115,0,44,0,32,0,104,0,117,0,109,0,97,0,110,0,45,0,114,0,101,0,97,0,100,0,97,0,98,0,108,0,101,0,32,0,104,0,101,0,97,0,100,0,101,0,114,0,115,0,32,0,111,0,114,0,32,0,105,0,110,0,32,0,116,0,104,0,101,0,32,0,97,0,112,0,112,0,114,0,111,0,112,0,114,0,105,0,97,0,116,0,101,0,32,0,109,0,97,0,99,0,104,0,105,0,110,0,101,0,45,0,114,0,101,0,97,0,100,0,97,0,98,0,108,0,101,0,32,0,109,0,101,0,116,0,97,0,100,0,97,0,116,0,97,0,32,0,102,0,105,0,101,0,108,0,100,0,115,0,32,0,119,0,105,0,116,0,104,0,105,0,110,0,32,0,116,0,101,0,120,0,116,0,32,0,111,0,114,0,32,0,98,0,105,0,110,0,97,0,114,0,121,0,32,0,102,0,105,0,108,0,101,0,115,0,32,0,97,0,115,0,32,0,108,0,111,0,110,0,103,0,32,0,97,0,115,0,32,0,116,0,104,0,111,0,115,0,101,0,32,0,102,0,105,0,101,0,108,0,100,0,115,0,32,0,99,0,97,0,110,0,32,0,98,0,101,0,32,0,101,0,97,0,115,0,105,0,108,0,121,0,32,0,118,0,105,0,101,0,119,0,101,0,100,0,32,0,98,0,121,0,32,0,116,0,104,0,101,0,32,0,117,0,115,0,101,0,114,0,46,0,10,0,32,0,10,0,51,0,41,0,32,0,78,0,111,0,32,0,77,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,32,0,86,0,101,0,114,0,115,0,105,0,111,0,110,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,109,0,97,0,121,0,32,0,117,0,115,0,101,0,32,0,116,0,104,0,101,0,32,0,82,0,101,0,115,0,101,0,114,0,118,0,101,0,100,0,32,0,70,0,111,0,110,0,116,0,32,0,78,0,97,0,109,0,101,0,40,0,115,0,41,0,32,0,117,0,110,0,108,0,101,0,115,0,115,0,32,0,101,0,120,0,112,0,108,0,105,0,99,0,105,0,116,0,32,0,119,0,114,0,105,0,116,0,116,0,101,0,110,0,32,0,112,0,101,0,114,0,109,0,105,0,115,0,115,0,105,0,111,0,110,0,32,0,105,0,115,0,32,0,103,0,114,0,97,0,110,0,116,0,101,0,100,0,32,0,98,0,121,0,32,0,116,0,104,0,101,0,32,0,99,0,111,0,114,0,114,0,101,0,115,0,112,0,111,0,110,0,100,0,105,0,110,0,103,0,32,0,67,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,72,0,111,0,108,0,100,0,101,0,114,0,46,0,32,0,84,0,104,0,105,0,115,0,32,0,114,0,101,0,115,0,116,0,114,0,105,0,99,0,116,0,105,0,111,0,110,0,32,0,111,0,110,0,108,0,121,0,32,0,97,0,112,0,112,0,108,0,105,0,101,0,115,0,32,0,116,0,111,0,32,0,116,0,104,0,101,0,32,0,112,0,114,0,105,0,109,0,97,0,114,0,121,0,32,0,102,0,111,0,110,0,116,0,32,0,110,0,97,0,109,0,101,0,32,0,97,0,115,0,32,0,112,0,114,0,101,0,115,0,101,0,110,0,116,0,101,0,100,0,32,0,116,0,111,0,32,0,116,0,104,0,101,0,32,0,117,0,115,0,101,0,114,0,115,0,46,0,10,0,32,0,10,0,52,0,41,0,32,0,84,0,104,0,101,0,32,0,110,0,97,0,109,0,101,0,40,0,115,0,41,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,67,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,72,0,111,0,108,0,100,0,101,0,114,0,40,0,115,0,41,0,32,0,111,0,114,0,32,0,116,0,104,0,101,0,32,0,65,0,117,0,116,0,104,0,111,0,114,0,40,0,115,0,41,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,32,0,115,0,104,0,97,0,108,0,108,0,32,0,110,0,111,0,116,0,32,0,98,0,101,0,32,0,117,0,115,0,101,0,100,0,32,0,116,0,111,0,32,0,112,0,114,0,111,0,109,0,111,0,116,0,101,0,44,0,32,0,101,0,110,0,100,0,111,0,114,0,115,0,101,0,32,0,111,0,114,0,32,0,97,0,100,0,118,0,101,0,114,0,116,0,105,0,115,0,101,0,32,0,97,0,110,0,121,0,32,0,77,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,32,0,86,0,101,0,114,0,115,0,105,0,111,0,110,0,44,0,32,0,101,0,120,0,99,0,101,0,112,0,116,0,32,0,116,0,111,0,32,0,97,0,99,0,107,0,110,0,111,0,119,0,108,0,101,0,100,0,103,0,101,0,32,0,116,0,104,0,101,0,32,0,99,0,111,0,110,0,116,0,114,0,105,0,98,0,117,0,116,0,105,0,111,0,110,0,40,0,115,0,41,0,32,0,111,0,102,0,32,0,116,0,104,0,101,0,32,0,67,0,111,0,112,0,121,0,114,0,105,0,103,0,104,0,116,0,32,0,72,0,111,0,108,0,100,0,101,0,114,0,40,0,115,0,41,0,32,0,97,0,110,0,100,0,32,0,116,0,104,0,101,0,32,0,65,0,117,0,116,0,104,0,111,0,114,0,40,0,115,0,41,0,32,0,111,0,114,0,32,0,119,0,105,0,116,0,104,0,32,0,116,0,104,0,101,0,105,0,114,0,32,0,101,0,120,0,112,0,108,0,105,0,99,0,105,0,116,0,32,0,119,0,114,0,105,0,116,0,116,0,101,0,110,0,32,0,112,0,101,0,114,0,109,0,105,0,115,0,115,0,105,0,111,0,110,0,46,0,10,0,32,0,10,0,53,0,41,0,32,0,84,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,44,0,32,0,109,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,32,0,111,0,114,0,32,0,117,0,110,0,109,0,111,0,100,0,105,0,102,0,105,0,101,0,100,0,44,0,32,0,105,0,110,0,32,0,112,0,97,0,114,0,116,0,32,0,111,0,114,0,32,0,105,0,110,0,32,0,119,0,104,0,111,0,108,0,101,0,44,0,32,0,109,0,117,0,115,0,116,0,32,0,98,0,101,0,32,0,100,0,105,0,115,0,116,0,114,0,105,0,98,0,117,0,116,0,101,0,100,0,32,0,101,0,110,0,116,0,105,0,114,0,101,0,108,0,121,0,32,0,117,0,110,0,100,0,101,0,114,0,32,0,116,0,104,0,105,0,115,0,32,0,108,0,105,0,99,0,101,0,110,0,115,0,101,0,44,0,32,0,97,0,110,0,100,0,32,0,109,0,117,0,115,0,116,0,32,0,110,0,111,0,116,0,32,0,98,0,101,0,32,0,100,0,105,0,115,0,116,0,114,0,105,0,98,0,117,0,116,0,101,0,100,0,32,0,117,0,110,0,100,0,101,0,114,0,32,0,97,0,110,0,121,0,32,0,111,0,116,0,104,0,101,0,114,0,32,0,108,0,105,0,99,0,101,0,110,0,115,0,101,0,46,0,32,0,84,0,104,0,101,0,32,0,114,0,101,0,113,0,117,0,105,0,114,0,101,0,109,0,101,0,110,0,116,0,32,0,102,0,111,0,114,0,32,0,102,0,111,0,110,0,116,0,115,0,32,0,116,0,111,0,32,0,114,0,101,0,109,0,97,0,105,0,110,0,32,0,117,0,110,0,100,0,101,0,114,0,32,0,116,0,104,0,105,0,115,0,32,0,108,0,105,0,99,0,101,0,110,0,115,0,101,0,32,0,100,0,111,0,101,0,115,0,32,0,110,0,111,0,116,0,32,0,97,0,112,0,112,0,108,0,121,0,32,0,116,0,111,0,32,0,97,0,110,0,121,0,32,0,100,0,111,0,99,0,117,0,109,0,101,0,110,0,116,0,32,0,99,0,114,0,101,0,97,0,116,0,101,0,100,0,32,0,117,0,115,0,105,0,110,0,103,0,32,0,116,0,104,0,101,0,32,0,70,0,111,0,110,0,116,0,32,0,83,0,111,0,102,0,116,0,119,0,97,0,114,0,101,0,46,0,10,0,32,0,10,0,84,0,72,0,69,0,32,0,70,0,79,0,78,0,84,0,32,0,83,0,79,0,70,0,84,0,87,0,65,0,82,0,69,0,32,0,73,0,83,0,32,0,80,0,82,0,79,0,86,0,73,0,68,0,69,0,68,0,32,0,34,0,65,0,83,0,32,0,73,0,83,0,34,0,44,0,32,0,87,0,73,0,84,0,72,0,79,0,85,0,84,0,32,0,87,0,65,0,82,0,82,0,65,0,78,0,84,0,89,0,32,0,79,0,70,0,32,0,65,0,78,0,89,0,32,0,75,0,73,0,78,0,68,0,44,0,32,0,69,0,88,0,80,0,82,0,69,0,83,0,83,0,32,0,79,0,82,0,32,0,73,0,77,0,80,0,76,0,73,0,69,0,68,0,44,0,32,0,73,0,78,0,67,0,76,0,85,0,68,0,73,0,78,0,71,0,32,0,66,0,85,0,84,0,32,0,78,0,79,0,84,0,32,0,76,0,73,0,77,0,73,0,84,0,69,0,68,0,32,0,84,0,79,0,32,0,65,0,78,0,89,0,32,0,87,0,65,0,82,0,82,0,65,0,78,0,84,0,73,0,69,0,83,0,32,0,79,0,70,0,32,0,77,0,69,0,82,0,67,0,72,0,65,0,78,0,84,0,65,0,66,0,73,0,76,0,73,0,84,0,89,0,44,0,32,0,70,0,73,0,84,0,78,0,69,0,83,0,83,0,32,0,70,0,79,0,82,0,32,0,65,0,32,0,80,0,65,0,82,0,84,0,73,0,67,0,85,0,76,0,65,0,82,0,32,0,80,0,85,0,82,0,80,0,79,0,83,0,69,0,32,0,65,0,78,0,68,0,32,0,78,0,79,0,78,0,73,0,78,0,70,0,82,0,73,0,78,0,71,0,69,0,77,0,69,0,78,0,84,0,32,0,79,0,70,0,32,0,67,0,79,0,80,0,89,0,82,0,73,0,71,0,72,0,84,0,44,0,32,0,80,0,65,0,84,0,69,0,78,0,84,0,44,0,32,0,84,0,82,0,65,0,68,0,69,0,77,0,65,0,82,0,75,0,44,0,32,0,79,0,82,0,32,0,79,0,84,0,72,0,69,0,82,0,32,0,82,0,73,0,71,0,72,0,84,0,46,0,32,0,73,0,78,0,32,0,78,0,79,0,32,0,69,0,86,0,69,0,78,0,84,0,32,0,83,0,72,0,65,0,76,0,76,0,32,0,84,0,72,0,69,0,32,0,67,0,79,0,80,0,89,0,82,0,73,0,71,0,72,0,84,0,32,0,72,0,79,0,76,0,68,0,69,0,82,0,32,0,66,0,69,0,32,0,76,0,73,0,65,0,66,0,76,0,69,0,32,0,70,0,79,0,82,0,32,0,65,0,78,0,89,0,32,0,67,0,76,0,65,0,73,0,77,0,44,0,32,0,68,0,65,0,77,0,65,0,71,0,69,0,83,0,32,0,79,0,82,0,32,0,79,0,84,0,72,0,69,0,82,0,32,0,76,0,73,0,65,0,66,0,73,0,76,0,73,0,84,0,89,0,44,0,32,0,73,0,78,0,67,0,76,0,85,0,68,0,73,0,78,0,71,0,32,0,65,0,78,0,89,0,32,0,71,0,69,0,78,0,69,0,82,0,65,0,76,0,44,0,32,0,83,0,80,0,69,0,67,0,73,0,65,0,76,0,44,0,32,0,73,0,78,0,68,0,73,0,82,0,69,0,67,0,84,0,44,0,32,0,73,0,78,0,67,0,73,0,68,0,69,0,78,0,84,0,65,0,76,0,44,0,32,0,79,0,82,0,32,0,67,0,79,0,78,0,83,0,69,0,81,0,85,0,69,0,78,0,84,0,73,0,65,0,76,0,32,0,68,0,65,0,77,0,65,0,71,0,69,0,83,0,44,0,32,0,87,0,72,0,69,0,84,0,72,0,69,0,82,0,32,0,73,0,78,0,32,0,65,0,78,0,32,0,65,0,67,0,84,0,73,0,79,0,78,0,32,0,79,0,70,0,32,0,67,0,79,0,78,0,84,0,82,0,65,0,67,0,84,0,44,0,32,0,84,0,79,0,82,0,84,0,32,0,79,0,82,0,32,0,79,0,84,0,72,0,69,0,82,0,87,0,73,0,83,0,69,0,44,0,32,0,65,0,82,0,73,0,83,0,73,0,78,0,71,0,32,0,70,0,82,0,79,0,77,0,44,0,32,0,79,0,85,0,84,0,32,0,79,0,70,0,32,0,84,0,72,0,69,0,32,0,85,0,83,0,69,0,32,0,79,0,82,0,32,0,73,0,78,0,65,0,66,0,73,0,76,0,73,0,84,0,89,0,32,0,84,0,79,0,32,0,85,0,83,0,69,0,32,0,84,0,72,0,69,0,32,0,70,0,79,0,78,0,84,0,32,0,83,0,79,0,70,0,84,0,87,0,65,0,82,0,69,0,32,0,79,0,82,0,32,0,70,0,82,0,79,0,77,0,32,0,79,0,84,0,72,0,69,0,82,0,32,0,68,0,69,0,65,0,76,0,73,0,78,0,71,0,83,0,32,0,73,0,78,0,32,0,84,0,72,0,69,0,32,0,70,0,79,0,78,0,84,0,32,0,83,0,79,0,70,0,84,0,87,0,65,0,82,0,69,0,46,0,104,0,116,0,116,0,112,0,115,0,58,0,47,0,47,0,115,0,99,0,114,0,105,0,112,0,116,0,115,0,46,0,115,0,105,0,108,0,46,0,111,0,114,0,103,0,47,0,79,0,70,0,76,0,87,0,101,0,105,0,103,0,104,0,116,0,69,0,120,0,116,0,114,0,97,0,76,0,105,0,103,0,104,0,116,0,76,0,105,0,103,0,104,0,116,0,83,0,101,0,109,0,105,0,76,0,105,0,103,0,104,0,116,0,83,0,101,0,109,0,105,0,66,0,111,0,108,0,100,0,66,0,111,0,108,0,100,0,0,0,0,2,0,0,0,0,0,0,255,156,0,50,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,88,0,0,0,36,0,201,1,2,6,97,6,98,6,99,6,100,6,101,6,102,0,199,6,103,6,104,6,105,6,106,6,107,0,98,6,108,0,173,6,109,1,16,1,17,0,99,1,18,0,174,0,144,1,19,0,37,0,38,0,253,0,255,0,100,1,20,1,21,0,39,0,233,1,22,1,23,0,40,0,101,1,24,1,25,0,200,6,110,6,111,6,112,6,113,6,114,0,202,1,31,6,115,0,203,6,116,1,34,1,35,6,117,6,118,6,119,6,120,0,41,0,42,0,248,1,40,1,41,6,121,1,43,0,43,1,44,6,122,1,46,0,44,1,47,0,204,1,48,0,205,0,206,0,250,6,123,0,207,6,124,1,51,1,52,1,53,0,45,1,54,0,46,6,125,0,47,1,56,1,57,6,126,1,59,0,226,0,48,0,49,1,60,1,61,6,127,1,63,6,128,0,102,0,50,0,208,1,65,0,209,6,129,6,130,6,131,6,132,6,133,0,103,6,134,0,211,6,135,1,73,6,136,6,137,6,138,6,139,6,140,1,79,1,80,6,141,6,142,0,145,1,83,0,175,0,176,0,51,0,237,0,52,0,53,1,84,1,85,6,143,0,54,1,87,0,228,0,251,1,88,6,144,6,145,6,146,0,55,1,92,1,93,6,147,6,148,0,56,0,212,1,96,0,213,0,104,6,149,0,214,6,150,1,99,6,151,6,152,6,153,6,154,6,155,1,105,1,106,1,107,1,108,1,109,0,57,6,156,0,58,1,111,1,112,1,113,1,114,0,59,0,60,0,235,1,115,0,187,6,157,1,117,6,158,6,159,6,160,0,61,1,121,0,230,1,122,1,123,1,124,1,125,1,126,1,127,1,128,6,161,0,68,0,105,1,130,6,162,6,163,6,164,6,165,6,166,6,167,0,107,6,168,6,169,6,170,6,171,6,172,0,108,6,173,0,106,6,174,1,144,1,145,0,110,1,146,0,109,0,160,1,147,0,69,0,70,0,254,1,0,0,111,1,148,1,149,0,71,0,234,1,150,1,1,0,72,0,112,1,151,1,152,0,114,6,175,6,176,6,177,6,178,6,179,0,115,1,158,6,180,0,113,6,181,1,161,1,162,6,182,6,183,6,184,6,185,6,186,0,73,0,74,0,249,1,168,1,169,6,187,1,171,0,75,1,172,6,188,1,174,0,76,0,215,0,116,1,176,0,118,0,119,6,189,0,117,6,190,1,179,1,180,1,181,1,182,0,77,6,191,1,184,0,78,6,192,1,186,0,79,1,187,1,188,6,193,1,190,0,227,0,80,0,81,1,191,1,192,1,193,6,194,1,195,6,195,0,120,0,82,0,121,1,197,0,123,6,196,6,197,6,198,6,199,6,200,0,124,6,201,0,122,6,202,1,205,6,203,6,204,6,205,6,206,6,207,1,211,1,212,6,208,6,209,0,161,1,215,0,125,0,177,0,83,0,238,0,84,0,85,1,216,1,217,6,210,0,86,1,219,0,229,0,252,1,220,6,211,0,137,1,222,0,87,1,223,1,224,6,212,6,213,6,214,0,88,0,126,1,228,0,128,0,129,6,215,0,127,6,216,1,231,6,217,6,218,6,219,6,220,6,221,1,237,1,238,1,239,1,240,1,241,0,89,6,222,0,90,1,243,1,244,1,245,1,246,0,91,0,92,0,236,1,247,0,186,6,223,1,249,6,224,6,225,6,226,0,93,1,253,0,231,1,254,1,255,2,0,2,1,2,2,2,3,2,4,2,5,2,6,2,7,0,157,0,158,6,227,6,228,6,229,6,230,6,231,6,232,6,233,6,234,6,235,6,236,6,237,6,238,6,239,6,240,6,241,6,242,6,243,6,244,6,245,6,246,6,247,6,248,6,249,6,250,6,251,6,252,6,253,6,254,6,255,7,0,7,1,7,2,7,3,7,4,7,5,7,6,7,7,7,8,7,9,7,10,7,11,7,12,7,13,7,14,7,15,7,16,7,17,7,18,7,19,7,20,7,21,7,22,7,23,7,24,7,25,7,26,7,27,7,28,7,29,7,30,7,31,7,32,7,33,7,34,7,35,7,36,7,37,7,38,7,39,7,40,7,41,7,42,7,43,7,44,7,45,7,46,7,47,7,48,7,49,7,50,7,51,7,52,7,53,7,54,7,55,7,56,7,57,7,58,7,59,7,60,7,61,7,62,7,63,7,64,7,65,7,66,7,67,7,68,7,69,7,70,7,71,7,72,7,73,7,74,7,75,7,76,7,77,7,78,7,79,7,80,7,81,7,82,7,83,7,84,7,85,7,86,7,87,7,88,7,89,7,90,7,91,7,92,7,93,7,94,7,95,7,96,7,97,7,98,7,99,7,100,7,101,7,102,7,103,7,104,7,105,7,106,7,107,7,108,7,109,7,110,7,111,7,112,7,113,7,114,7,115,7,116,7,117,7,118,7,119,2,157,2,158,2,159,7,120,2,160,2,161,2,162,2,163,2,164,2,165,2,166,2,167,2,168,2,169,2,170,2,171,2,172,2,173,2,174,2,175,2,176,2,177,2,178,7,121,2,179,2,180,2,181,2,182,2,183,2,184,2,185,2,186,2,187,7,122,2,189,2,190,2,191,2,192,2,193,2,194,2,195,2,196,2,197,2,198,2,199,7,123,2,200,2,201,2,202,0,155,2,203,7,124,2,205,2,206,2,207,2,208,2,209,2,210,2,211,2,212,2,213,2,214,2,215,2,216,2,217,2,218,2,219,2,220,2,221,2,222,7,125,0,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,2,224,7,126,7,127,7,128,7,129,7,130,7,131,7,132,7,133,7,134,7,135,2,235,2,236,2,237,2,238,2,239,2,240,2,241,2,242,2,243,2,244,2,245,2,246,2,247,2,248,2,249,2,250,2,251,2,252,2,253,2,254,7,136,7,137,7,138,7,139,7,140,7,141,7,142,7,143,7,144,7,145,0,188,0,244,0,245,0,246,3,6,3,7,3,8,3,9,0,17,0,15,0,29,0,30,0,171,0,4,0,163,0,34,0,162,0,195,0,135,0,13,7,146,0,6,3,11,7,147,0,18,0,63,0,11,0,12,0,94,0,96,0,62,0,64,7,148,7,149,7,150,7,151,0,16,7,152,0,178,0,179,7,153,7,154,7,155,0,66,3,21,0,196,0,197,0,180,0,181,0,182,0,183,3,22,0,169,0,170,0,190,0,191,0,5,0,10,3,25,3,26,3,27,3,28,3,29,3,30,3,31,3,32,3,33,3,34,3,35,3,36,3,37,3,38,3,39,3,40,3,41,3,42,3,43,3,44,3,45,3,46,3,47,3,48,3,49,3,50,3,51,3,52,3,53,3,54,3,55,3,56,3,57,3,58,3,59,3,60,3,61,3,62,3,63,3,64,3,65,3,66,3,67,3,68,3,69,3,70,3,71,3,72,3,73,7,156,7,157,3,76,3,77,3,78,3,79,3,80,3,81,3,82,3,83,3,84,3,85,3,86,3,87,3,88,7,158,7,159,0,3,7,160,3,92,7,161,7,162,7,163,0,132,7,164,0,189,0,7,3,97,7,165,7,166,0,166,0,247,7,167,7,168,7,169,7,170,3,104,7,171,7,172,7,173,3,108,7,174,7,175,7,176,7,177,7,178,0,133,7,179,7,180,7,181,0,150,7,182,7,183,3,119,7,184,3,121,3,122,7,185,7,186,0,14,0,239,0,240,0,184,0,32,0,143,0,33,0,31,0,149,0,148,0,147,0,167,0,97,0,164,0,65,0,146,3,125,0,156,7,187,7,188,0,154,0,153,0,165,7,189,0,152,3,129,0,8,0,198,7,190,7,191,7,192,7,193,7,194,7,195,7,196,7,197,7,198,7,199,7,200,7,201,7,202,7,203,7,204,7,205,7,206,7,207,7,208,7,209,7,210,7,211,7,212,7,213,7,214,7,215,7,216,7,217,7,218,7,219,7,220,7,221,7,222,7,223,7,224,7,225,7,226,7,227,7,228,7,229,7,230,7,231,7,232,7,233,7,234,7,235,7,236,7,237,7,238,7,239,7,240,7,241,7,242,7,243,7,244,7,245,7,246,7,247,7,248,7,249,7,250,7,251,7,252,7,253,7,254,7,255,8,0,8,1,8,2,8,3,8,4,8,5,8,6,8,7,8,8,8,9,8,10,8,11,8,12,8,13,0,185,8,14,8,15,8,16,8,17,8,18,8,19,8,20,8,21,8,22,8,23,8,24,8,25,8,26,8,27,8,28,8,29,8,30,8,31,8,32,8,33,8,34,8,35,8,36,8,37,8,38,8,39,8,40,8,41,8,42,8,43,8,44,8,45,8,46,8,47,8,48,8,49,8,50,8,51,8,52,8,53,8,54,8,55,8,56,8,57,8,58,8,59,8,60,8,61,8,62,8,63,8,64,8,65,8,66,8,67,8,68,8,69,8,70,8,71,8,72,8,73,8,74,8,75,8,76,8,77,8,78,8,79,8,80,8,81,8,82,8,83,8,84,8,85,8,86,8,87,8,88,8,89,8,90,8,91,8,92,8,93,8,94,8,95,8,96,8,97,8,98,8,99,8,100,8,101,8,102,8,103,8,104,8,105,8,106,8,107,8,108,8,109,8,110,8,111,8,112,8,113,8,114,8,115,8,116,8,117,8,118,8,119,8,120,8,121,8,122,8,123,8,124,8,125,8,126,8,127,8,128,8,129,8,130,8,131,8,132,8,133,8,134,8,135,8,136,8,137,8,138,8,139,8,140,8,141,8,142,8,143,8,144,8,145,8,146,8,147,8,148,8,149,8,150,8,151,8,152,8,153,8,154,8,155,8,156,8,157,8,158,8,159,8,160,8,161,8,162,8,163,8,164,8,165,8,166,8,167,8,168,8,169,8,170,8,171,8,172,8,173,8,174,8,175,8,176,8,177,8,178,8,179,8,180,8,181,8,182,8,183,8,184,8,185,8,186,8,187,8,188,8,189,8,190,8,191,8,192,8,193,8,194,8,195,8,196,8,197,8,198,8,199,8,200,8,201,8,202,8,203,8,204,8,205,8,206,8,207,8,208,8,209,8,210,8,211,8,212,8,213,8,214,8,215,8,216,8,217,8,218,8,219,8,220,8,221,8,222,8,223,8,224,8,225,8,226,8,227,8,228,8,229,8,230,8,231,8,232,8,233,8,234,8,235,8,236,8,237,8,238,8,239,8,240,8,241,8,242,8,243,8,244,8,245,8,246,8,247,8,248,0,35,0,9,0,136,0,134,0,139,0,138,8,249,0,140,8,250,0,131,4,191,4,192,0,95,0,232,0,130,8,251,0,194,8,252,4,195,8,253,8,254,8,255,9,0,9,1,9,2,9,3,9,4,9,5,9,6,9,7,9,8,9,9,9,10,9,11,9,12,9,13,9,14,9,15,9,16,9,17,9,18,9,19,9,20,9,21,9,22,9,23,9,24,9,25,9,26,9,27,4,227,4,228,4,229,4,230,4,231,4,232,4,233,4,234,4,235,4,236,4,237,4,238,4,239,4,240,4,241,4,242,4,243,4,244,4,245,4,246,4,247,4,248,4,249,4,250,4,251,4,252,4,253,4,254,4,255,5,0,5,1,5,2,5,3,5,4,5,5,5,6,5,7,5,8,5,9,5,10,5,11,5,12,5,13,5,14,5,15,5,16,5,17,5,18,5,19,5,20,5,21,5,22,5,23,5,24,5,25,5,26,5,27,5,28,5,29,5,30,5,31,5,32,5,33,5,34,5,35,5,36,5,37,5,38,5,39,5,40,5,41,9,28,9,29,9,30,9,31,9,32,9,33,9,34,9,35,9,36,9,37,9,38,9,39,9,40,9,41,9,42,9,43,9,44,9,45,9,46,9,47,9,48,9,49,9,50,9,51,9,52,9,53,9,54,9,55,9,56,9,57,9,58,9,59,9,60,9,61,9,62,9,63,9,64,9,65,9,66,9,67,9,68,9,69,9,70,9,71,9,72,9,73,9,74,9,75,9,76,9,77,9,78,9,79,9,80,9,81,9,82,9,83,9,84,9,85,9,86,9,87,9,88,9,89,9,90,9,91,9,92,9,93,9,94,9,95,9,96,9,97,9,98,9,99,9,100,9,101,9,102,9,103,9,104,9,105,9,106,9,107,9,108,9,109,9,110,9,111,9,112,9,113,9,114,9,115,9,116,9,117,9,118,9,119,9,120,9,121,9,122,9,123,9,124,9,125,9,126,9,127,9,128,9,129,9,130,9,131,9,132,9,133,9,134,9,135,9,136,9,137,9,138,9,139,9,140,9,141,9,142,9,143,9,144,9,145,9,146,9,147,9,148,9,149,9,150,9,151,9,152,9,153,9,154,9,155,9,156,9,157,9,158,9,159,9,160,9,161,9,162,9,163,9,164,9,165,9,166,9,167,9,168,9,169,9,170,9,171,9,172,9,173,9,174,9,175,9,176,9,177,9,178,9,179,9,180,9,181,9,182,9,183,9,184,9,185,9,186,9,187,9,188,9,189,9,190,9,191,9,192,9,193,9,194,9,195,9,196,9,197,9,198,9,199,9,200,9,201,9,202,9,203,9,204,9,205,9,206,9,207,9,208,9,209,9,210,9,211,9,212,9,213,9,214,9,215,9,216,9,217,9,218,9,219,9,220,9,221,9,222,9,223,9,224,9,225,9,226,9,227,9,228,9,229,9,230,9,231,9,232,9,233,9,234,9,235,9,236,9,237,9,238,9,239,9,240,9,241,9,242,9,243,9,244,9,245,9,246,9,247,9,248,9,249,9,250,9,251,9,252,9,253,9,254,9,255,10,0,10,1,10,2,10,3,10,4,10,5,10,6,10,7,10,8,10,9,10,10,10,11,10,12,10,13,10,14,10,15,10,16,10,17,10,18,10,19,10,20,10,21,10,22,10,23,10,24,10,25,10,26,10,27,10,28,10,29,10,30,10,31,10,32,10,33,10,34,10,35,10,36,6,51,6,52,10,37,10,38,10,39,10,40,10,41,6,58,10,42,6,60,10,43,10,44,6,63,10,45,10,46,10,47,10,48,10,49,0,142,0,220,0,67,0,141,0,223,0,216,0,225,0,219,0,221,0,217,0,218,0,222,0,224,10,50,10,51,6,71,6,72,10,52,10,53,10,54,10,55,10,56,6,78,10,57,6,80,10,58,6,82,6,83,10,59,6,85,6,86,6,87,10,60,10,61,6,90,6,91,10,62,6,93,6,94,6,95,6,96,6,65,98,114,101,118,101,11,65,98,114,101,118,101,97,99,117,116,101,14,65,98,114,101,118,101,100,111,116,98,101,108,111,119,11,65,98,114,101,118,101,103,114,97,118,101,15,65,98,114,101,118,101,104,111,111,107,97,98,111,118,101,11,65,98,114,101,118,101,116,105,108,100,101,6,65,99,97,114,111,110,16,65,99,105,114,99,117,109,102,108,101,120,97,99,117,116,101,19,65,99,105,114,99,117,109,102,108,101,120,100,111,116,98,101,108,111,119,16,65,99,105,114,99,117,109,102,108,101,120,103,114,97,118,101,20,65,99,105,114,99,117,109,102,108,101,120,104,111,111,107,97,98,111,118,101,16,65,99,105,114,99,117,109,102,108,101,120,116,105,108,100,101,9,65,100,111,116,98,101,108,111,119,10,65,104,111,111,107,97,98,111,118,101,7,65,109,97,99,114,111,110,7,65,111,103,111,110,101,107,10,65,114,105,110,103,97,99,117,116,101,7,65,69,97,99,117,116,101,11,67,99,105,114,99,117,109,102,108,101,120,10,67,100,111,116,97,99,99,101,110,116,6,68,99,97,114,111,110,6,68,99,114,111,97,116,6,69,98,114,101,118,101,6,69,99,97,114,111,110,16,69,99,105,114,99,117,109,102,108,101,120,97,99,117,116,101,19,69,99,105,114,99,117,109,102,108,101,120,100,111,116,98,101,108,111,119,16,69,99,105,114,99,117,109,102,108,101,120,103,114,97,118,101,20,69,99,105,114,99,117,109,102,108,101,120,104,111,111,107,97,98,111,118,101,16,69,99,105,114,99,117,109,102,108,101,120,116,105,108,100,101,10,69,100,111,116,97,99,99,101,110,116,9,69,100,111,116,98,101,108,111,119,10,69,104,111,111,107,97,98,111,118,101,7,69,109,97,99,114,111,110,7,69,111,103,111,110,101,107,5,69,111,112,101,110,3,69,115,104,6,69,116,105,108,100,101,3,69,122,104,6,71,99,97,114,111,110,11,71,99,105,114,99,117,109,102,108,101,120,12,71,99,111,109,109,97,97,99,99,101,110,116,10,71,100,111,116,97,99,99,101,110,116,4,72,98,97,114,6,72,99,97,114,111,110,11,72,99,105,114,99,117,109,102,108,101,120,2,73,74,6,73,98,114,101,118,101,9,73,100,111,116,98,101,108,111,119,10,73,104,111,111,107,97,98,111,118,101,7,73,109,97,99,114,111,110,7,73,111,103,111,110,101,107,6,73,116,105,108,100,101,11,74,99,105,114,99,117,109,102,108,101,120,12,75,99,111,109,109,97,97,99,99,101,110,116,6,76,97,99,117,116,101,6,76,99,97,114,111,110,12,76,99,111,109,109,97,97,99,99,101,110,116,4,76,100,111,116,6,78,97,99,117,116,101,6,78,99,97,114,111,110,12,78,99,111,109,109,97,97,99,99,101,110,116,3,69,110,103,9,78,104,111,111,107,108,101,102,116,6,79,98,114,101,118,101,16,79,99,105,114,99,117,109,102,108,101,120,97,99,117,116,101,19,79,99,105,114,99,117,109,102,108,101,120,100,111,116,98,101,108,111,119,16,79,99,105,114,99,117,109,102,108,101,120,103,114,97,118,101,20,79,99,105,114,99,117,109,102,108,101,120,104,111,111,107,97,98,111,118,101,16,79,99,105,114,99,117,109,102,108,101,120,116,105,108,100,101,9,79,100,111,116,98,101,108,111,119,10,79,104,111,111,107,97,98,111,118,101,5,79,104,111,114,110,10,79,104,111,114,110,97,99,117,116,101,13,79,104,111,114,110,100,111,116,98,101,108,111,119,10,79,104,111,114,110,103,114,97,118,101,14,79,104,111,114,110,104,111,111,107,97,98,111,118,101,10,79,104,111,114,110,116,105,108,100,101,13,79,104,117,110,103,97,114,117,109,108,97,117,116,7,79,109,97,99,114,111,110,7,79,111,103,111,110,101,107,5,79,111,112,101,110,11,79,115,108,97,115,104,97,99,117,116,101,6,82,97,99,117,116,101,6,82,99,97,114,111,110,12,82,99,111,109,109,97,97,99,99,101,110,116,6,83,97,99,117,116,101,11,83,99,105,114,99,117,109,102,108,101,120,12,83,99,111,109,109,97,97,99,99,101,110,116,10,71,101,114,109,97,110,100,98,108,115,5,83,99,104,119,97,4,84,98,97,114,6,84,99,97,114,111,110,8,84,99,101,100,105,108,108,97,12,84,99,111,109,109,97,97,99,99,101,110,116,6,85,98,114,101,118,101,9,85,100,111,116,98,101,108,111,119,10,85,104,111,111,107,97,98,111,118,101,5,85,104,111,114,110,10,85,104,111,114,110,97,99,117,116,101,13,85,104,111,114,110,100,111,116,98,101,108,111,119,10,85,104,111,114,110,103,114,97,118,101,14,85,104,111,114,110,104,111,111,107,97,98,111,118,101,10,85,104,111,114,110,116,105,108,100,101,13,85,104,117,110,103,97,114,117,109,108,97,117,116,7,85,109,97,99,114,111,110,7,85,111,103,111,110,101,107,5,85,114,105,110,103,6,85,116,105,108,100,101,7,86,116,117,114,110,101,100,6,87,97,99,117,116,101,11,87,99,105,114,99,117,109,102,108,101,120,9,87,100,105,101,114,101,115,105,115,6,87,103,114,97,118,101,11,89,99,105,114,99,117,109,102,108,101,120,9,89,100,111,116,98,101,108,111,119,6,89,103,114,97,118,101,10,89,104,111,111,107,97,98,111,118,101,7,89,109,97,99,114,111,110,6,89,116,105,108,100,101,6,90,97,99,117,116,101,10,90,100,111,116,97,99,99,101,110,116,16,73,97,99,117,116,101,95,74,46,108,111,99,108,78,76,68,14,67,97,99,117,116,101,46,108,111,99,108,80,76,75,14,78,97,99,117,116,101,46,108,111,99,108,80,76,75,14,79,97,99,117,116,101,46,108,111,99,108,80,76,75,14,83,97,99,117,116,101,46,108,111,99,108,80,76,75,14,90,97,99,117,116,101,46,108,111,99,108,80,76,75,6,73,115,109,97,108,108,6,97,98,114,101,118,101,11,97,98,114,101,118,101,97,99,117,116,101,14,97,98,114,101,118,101,100,111,116,98,101,108,111,119,11,97,98,114,101,118,101,103,114,97,118,101,15,97,98,114,101,118,101,104,111,111,107,97,98,111,118,101,11,97,98,114,101,118,101,116,105,108,100,101,6,97,99,97,114,111,110,16,97,99,105,114,99,117,109,102,108,101,120,97,99,117,116,101,19,97,99,105,114,99,117,109,102,108,101,120,100,111,116,98,101,108,111,119,16,97,99,105,114,99,117,109,102,108,101,120,103,114,97,118,101,20,97,99,105,114,99,117,109,102,108,101,120,104,111,111,107,97,98,111,118,101,16,97,99,105,114,99,117,109,102,108,101,120,116,105,108,100,101,9,97,100,111,116,98,101,108,111,119,10,97,104,111,111,107,97,98,111,118,101,7,97,109,97,99,114,111,110,7,97,111,103,111,110,101,107,10,97,114,105,110,103,97,99,117,116,101,7,97,101,97,99,117,116,101,11,99,99,105,114,99,117,109,102,108,101,120,10,99,100,111,116,97,99,99,101,110,116,6,100,99,97,114,111,110,6,101,98,114,101,118,101,6,101,99,97,114,111,110,16,101,99,105,114,99,117,109,102,108,101,120,97,99,117,116,101,19,101,99,105,114,99,117,109,102,108,101,120,100,111,116,98,101,108,111,119,16,101,99,105,114,99,117,109,102,108,101,120,103,114,97,118,101,20,101,99,105,114,99,117,109,102,108,101,120,104,111,111,107,97,98,111,118,101,16,101,99,105,114,99,117,109,102,108,101,120,116,105,108,100,101,10,101,100,111,116,97,99,99,101,110,116,9,101,100,111,116,98,101,108,111,119,10,101,104,111,111,107,97,98,111,118,101,7,101,109,97,99,114,111,110,7,101,111,103,111,110,101,107,5,101,111,112,101,110,3,101,115,104,6,101,116,105,108,100,101,5,115,99,104,119,97,3,101,122,104,6,103,99,97,114,111,110,11,103,99,105,114,99,117,109,102,108,101,120,12,103,99,111,109,109,97,97,99,99,101,110,116,10,103,100,111,116,97,99,99,101,110,116,4,104,98,97,114,6,104,99,97,114,111,110,11,104,99,105,114,99,117,109,102,108,101,120,8,105,100,111,116,108,101,115,115,6,105,98,114,101,118,101,9,105,100,111,116,98,101,108,111,119,10,105,104,111,111,107,97,98,111,118,101,2,105,106,7,105,109,97,99,114,111,110,7,105,111,103,111,110,101,107,6,105,116,105,108,100,101,8,106,100,111,116,108,101,115,115,11,106,99,105,114,99,117,109,102,108,101,120,12,107,99,111,109,109,97,97,99,99,101,110,116,12,107,103,114,101,101,110,108,97,110,100,105,99,6,108,97,99,117,116,101,6,108,99,97,114,111,110,12,108,99,111,109,109,97,97,99,99,101,110,116,4,108,100,111,116,6,110,97,99,117,116,101,11,110,97,112,111,115,116,114,111,112,104,101,6,110,99,97,114,111,110,12,110,99,111,109,109,97,97,99,99,101,110,116,3,101,110,103,9,110,104,111,111,107,108,101,102,116,6,111,98,114,101,118,101,16,111,99,105,114,99,117,109,102,108,101,120,97,99,117,116,101,19,111,99,105,114,99,117,109,102,108,101,120,100,111,116,98,101,108,111,119,16,111,99,105,114,99,117,109,102,108,101,120,103,114,97,118,101,20,111,99,105,114,99,117,109,102,108,101,120,104,111,111,107,97,98,111,118,101,16,111,99,105,114,99,117,109,102,108,101,120,116,105,108,100,101,9,111,100,111,116,98,101,108,111,119,10,111,104,111,111,107,97,98,111,118,101,5,111,104,111,114,110,10,111,104,111,114,110,97,99,117,116,101,13,111,104,111,114,110,100,111,116,98,101,108,111,119,10,111,104,111,114,110,103,114,97,118,101,14,111,104,111,114,110,104,111,111,107,97,98,111,118,101,10,111,104,111,114,110,116,105,108,100,101,13,111,104,117,110,103,97,114,117,109,108,97,117,116,7,111,109,97,99,114,111,110,7,111,111,103,111,110,101,107,5,111,111,112,101,110,11,111,115,108,97,115,104,97,99,117,116,101,6,114,97,99,117,116,101,6,114,99,97,114,111,110,12,114,99,111,109,109,97,97,99,99,101,110,116,6,115,97,99,117,116,101,11,115,99,105,114,99,117,109,102,108,101,120,12,115,99,111,109,109,97,97,99,99,101,110,116,5,108,111,110,103,115,4,116,98,97,114,6,116,99,97,114,111,110,8,116,99,101,100,105,108,108,97,12,116,99,111,109,109,97,97,99,99,101,110,116,4,116,101,115,104,6,117,98,114,101,118,101,9,117,100,111,116,98,101,108,111,119,10,117,104,111,111,107,97,98,111,118,101,5,117,104,111,114,110,10,117,104,111,114,110,97,99,117,116,101,13,117,104,111,114,110,100,111,116,98,101,108,111,119,10,117,104,111,114,110,103,114,97,118,101,14,117,104,111,114,110,104,111,111,107,97,98,111,118,101,10,117,104,111,114,110,116,105,108,100,101,13,117,104,117,110,103,97,114,117,109,108,97,117,116,7,117,109,97,99,114,111,110,7,117,111,103,111,110,101,107,5,117,114,105,110,103,6,117,116,105,108,100,101,7,118,116,117,114,110,101,100,6,119,97,99,117,116,101,11,119,99,105,114,99,117,109,102,108,101,120,9,119,100,105,101,114,101,115,105,115,6,119,103,114,97,118,101,11,121,99,105,114,99,117,109,102,108,101,120,9,121,100,111,116,98,101,108,111,119,6,121,103,114,97,118,101,10,121,104,111,111,107,97,98,111,118,101,7,121,109,97,99,114,111,110,6,121,116,105,108,100,101,6,122,97,99,117,116,101,10,122,100,111,116,97,99,99,101,110,116,10,100,99,97,114,111,110,46,97,108,116,16,105,97,99,117,116,101,95,106,46,108,111,99,108,78,76,68,14,99,97,99,117,116,101,46,108,111,99,108,80,76,75,14,110,97,99,117,116,101,46,108,111,99,108,80,76,75,14,111,97,99,117,116,101,46,108,111,99,108,80,76,75,14,115,97,99,117,116,101,46,108,111,99,108,80,76,75,14,122,97,99,117,116,101,46,108,111,99,108,80,76,75,10,120,46,109,117,108,116,105,112,108,121,10,119,95,119,95,119,46,108,105,103,97,4,110,109,111,100,4,65,45,99,121,5,66,101,45,99,121,5,86,101,45,99,121,5,71,101,45,99,121,6,71,106,101,45,99,121,12,71,104,101,117,112,116,117,114,110,45,99,121,5,68,101,45,99,121,5,73,101,45,99,121,10,73,101,103,114,97,118,101,45,99,121,5,73,111,45,99,121,6,90,104,101,45,99,121,5,90,101,45,99,121,5,73,105,45,99,121,10,73,105,115,104,111,114,116,45,99,121,10,73,105,103,114,97,118,101,45,99,121,5,75,97,45,99,121,6,75,106,101,45,99,121,5,69,108,45,99,121,5,69,109,45,99,121,5,69,110,45,99,121,4,79,45,99,121,5,80,101,45,99,121,5,69,114,45,99,121,5,69,115,45,99,121,5,84,101,45,99,121,4,85,45,99,121,9,85,115,104,111,114,116,45,99,121,5,69,102,45,99,121,5,72,97,45,99,121,6,67,104,101,45,99,121,6,84,115,101,45,99,121,6,83,104,97,45,99,121,8,83,104,99,104,97,45,99,121,7,68,122,104,101,45,99,121,11,83,111,102,116,115,105,103,110,45,99,121,11,72,97,114,100,115,105,103,110,45,99,121,7,89,101,114,117,45,99,121,6,76,106,101,45,99,121,6,78,106,101,45,99,121,6,68,122,101,45,99,121,4,69,45,99,121,12,69,114,101,118,101,114,115,101,100,45,99,121,4,73,45,99,121,5,89,105,45,99,121,5,74,101,45,99,121,7,84,115,104,101,45,99,121,5,73,117,45,99,121,5,73,97,45,99,121,6,68,106,101,45,99,121,12,71,104,101,115,116,114,111,107,101,45,99,121,15,90,104,101,100,101,115,99,101,110,100,101,114,45,99,121,14,75,97,100,101,115,99,101,110,100,101,114,45,99,121,14,69,110,100,101,115,99,101,110,100,101,114,45,99,121,12,85,115,116,114,97,105,103,104,116,45,99,121,18,85,115,116,114,97,105,103,104,116,115,116,114,111,107,101,45,99,121,14,72,97,100,101,115,99,101,110,100,101,114,45,99,121,15,67,104,101,100,101,115,99,101,110,100,101,114,45,99,121,7,83,104,104,97,45,99,121,11,80,97,108,111,99,104,107,97,45,99,121,8,83,99,104,119,97,45,99,121,10,73,109,97,99,114,111,110,45,99,121,10,79,98,97,114,114,101,100,45,99,121,10,85,109,97,99,114,111,110,45,99,121,13,68,101,45,99,121,46,108,111,99,108,66,71,82,13,69,108,45,99,121,46,108,111,99,108,66,71,82,13,69,102,45,99,121,46,108,111,99,108,66,71,82,4,97,45,99,121,5,98,101,45,99,121,5,118,101,45,99,121,5,103,101,45,99,121,6,103,106,101,45,99,121,12,103,104,101,117,112,116,117,114,110,45,99,121,5,100,101,45,99,121,5,105,101,45,99,121,10,105,101,103,114,97,118,101,45,99,121,5,105,111,45,99,121,6,122,104,101,45,99,121,5,122,101,45,99,121,5,105,105,45,99,121,10,105,105,115,104,111,114,116,45,99,121,10,105,105,103,114,97,118,101,45,99,121,5,107,97,45,99,121,6,107,106,101,45,99,121,5,101,108,45,99,121,5,101,109,45,99,121,5,101,110,45,99,121,4,111,45,99,121,5,112,101,45,99,121,5,101,114,45,99,121,5,101,115,45,99,121,5,116,101,45,99,121,4,117,45,99,121,9,117,115,104,111,114,116,45,99,121,5,101,102,45,99,121,5,104,97,45,99,121,6,99,104,101,45,99,121,6,116,115,101,45,99,121,6,115,104,97,45,99,121,8,115,104,99,104,97,45,99,121,7,100,122,104,101,45,99,121,11,115,111,102,116,115,105,103,110,45,99,121,11,104,97,114,100,115,105,103,110,45,99,121,7,121,101,114,117,45,99,121,6,108,106,101,45,99,121,6,110,106,101,45,99,121,6,100,122,101,45,99,121,4,101,45,99,121,12,101,114,101,118,101,114,115,101,100,45,99,121,4,105,45,99,121,5,121,105,45,99,121,5,106,101,45,99,121,7,116,115,104,101,45,99,121,5,105,117,45,99,121,5,105,97,45,99,121,6,100,106,101,45,99,121,12,103,104,101,115,116,114,111,107,101,45,99,121,15,122,104,101,100,101,115,99,101,110,100,101,114,45,99,121,14,107,97,100,101,115,99,101,110,100,101,114,45,99,121,14,101,110,100,101,115,99,101,110,100,101,114,45,99,121,12,117,115,116,114,97,105,103,104,116,45,99,121,18,117,115,116,114,97,105,103,104,116,115,116,114,111,107,101,45,99,121,14,104,97,100,101,115,99,101,110,100,101,114,45,99,121,15,99,104,101,100,101,115,99,101,110,100,101,114,45,99,121,7,115,104,104,97,45,99,121,11,112,97,108,111,99,104,107,97,45,99,121,8,115,99,104,119,97,45,99,121,10,105,109,97,99,114,111,110,45,99,121,10,111,98,97,114,114,101,100,45,99,121,10,117,109,97,99,114,111,110,45,99,121,13,118,101,45,99,121,46,108,111,99,108,66,71,82,13,103,101,45,99,121,46,108,111,99,108,66,71,82,13,100,101,45,99,121,46,108,111,99,108,66,71,82,14,122,104,101,45,99,121,46,108,111,99,108,66,71,82,13,122,101,45,99,121,46,108,111,99,108,66,71,82,13,105,105,45,99,121,46,108,111,99,108,66,71,82,18,105,105,115,104,111,114,116,45,99,121,46,108,111,99,108,66,71,82,18,105,105,103,114,97,118,101,45,99,121,46,108,111,99,108,66,71,82,13,107,97,45,99,121,46,108,111,99,108,66,71,82,13,101,108,45,99,121,46,108,111,99,108,66,71,82,13,112,101,45,99,121,46,108,111,99,108,66,71,82,13,116,101,45,99,121,46,108,111,99,108,66,71,82,14,116,115,101,45,99,121,46,108,111,99,108,66,71,82,14,115,104,97,45,99,121,46,108,111,99,108,66,71,82,16,115,104,99,104,97,45,99,121,46,108,111,99,108,66,71,82,19,115,111,102,116,115,105,103,110,45,99,121,46,108,111,99,108,66,71,82,19,104,97,114,100,115,105,103,110,45,99,121,46,108,111,99,108,66,71,82,13,105,117,45,99,121,46,108,111,99,108,66,71,82,13,98,101,45,99,121,46,108,111,99,108,83,82,66,5,65,108,112,104,97,4,66,101,116,97,5,71,97,109,109,97,7,69,112,115,105,108,111,110,4,90,101,116,97,3,69,116,97,5,84,104,101,116,97,4,73,111,116,97,5,75,97,112,112,97,6,76,97,109,98,100,97,2,77,117,2,78,117,2,88,105,7,79,109,105,99,114,111,110,2,80,105,3,82,104,111,5,83,105,103,109,97,3,84,97,117,7,85,112,115,105,108,111,110,3,80,104,105,3,67,104,105,3,80,115,105,10,65,108,112,104,97,116,111,110,111,115,12,69,112,115,105,108,111,110,116,111,110,111,115,8,69,116,97,116,111,110,111,115,9,73,111,116,97,116,111,110,111,115,12,79,109,105,99,114,111,110,116,111,110,111,115,12,85,112,115,105,108,111,110,116,111,110,111,115,10,79,109,101,103,97,116,111,110,111,115,12,73,111,116,97,100,105,101,114,101,115,105,115,15,85,112,115,105,108,111,110,100,105,101,114,101,115,105,115,9,75,97,105,83,121,109,98,111,108,5,97,108,112,104,97,4,98,101,116,97,5,103,97,109,109,97,5,100,101,108,116,97,7,101,112,115,105,108,111,110,4,122,101,116,97,3,101,116,97,5,116,104,101,116,97,4,105,111,116,97,5,107,97,112,112,97,6,108,97,109,98,100,97,2,110,117,2,120,105,7,111,109,105,99,114,111,110,3,114,104,111,10,115,105,103,109,97,102,105,110,97,108,5,115,105,103,109,97,3,116,97,117,7,117,112,115,105,108,111,110,3,112,104,105,3,99,104,105,3,112,115,105,5,111,109,101,103,97,9,105,111,116,97,116,111,110,111,115,12,105,111,116,97,100,105,101,114,101,115,105,115,17,105,111,116,97,100,105,101,114,101,115,105,115,116,111,110,111,115,12,117,112,115,105,108,111,110,116,111,110,111,115,15,117,112,115,105,108,111,110,100,105,101,114,101,115,105,115,20,117,112,115,105,108,111,110,100,105,101,114,101,115,105,115,116,111,110,111,115,12,111,109,105,99,114,111,110,116,111,110,111,115,10,111,109,101,103,97,116,111,110,111,115,10,97,108,112,104,97,116,111,110,111,115,12,101,112,115,105,108,111,110,116,111,110,111,115,8,101,116,97,116,111,110,111,115,9,107,97,105,83,121,109,98,111,108,9,122,101,114,111,46,122,101,114,111,12,122,101,114,111,105,110,102,101,114,105,111,114,11,111,110,101,105,110,102,101,114,105,111,114,11,116,119,111,105,110,102,101,114,105,111,114,13,116,104,114,101,101,105,110,102,101,114,105,111,114,12,102,111,117,114,105,110,102,101,114,105,111,114,12,102,105,118,101,105,110,102,101,114,105,111,114,11,115,105,120,105,110,102,101,114,105,111,114,13,115,101,118,101,110,105,110,102,101,114,105,111,114,13,101,105,103,104,116,105,110,102,101,114,105,111,114,12,110,105,110,101,105,110,102,101,114,105,111,114,9,122,101,114,111,46,100,110,111,109,8,111,110,101,46,100,110,111,109,8,116,119,111,46,100,110,111,109,10,116,104,114,101,101,46,100,110,111,109,9,102,111,117,114,46,100,110,111,109,9,102,105,118,101,46,100,110,111,109,8,115,105,120,46,100,110,111,109,10,115,101,118,101,110,46,100,110,111,109,10,101,105,103,104,116,46,100,110,111,109,9,110,105,110,101,46,100,110,111,109,9,122,101,114,111,46,110,117,109,114,8,111,110,101,46,110,117,109,114,8,116,119,111,46,110,117,109,114,10,116,104,114,101,101,46,110,117,109,114,9,102,111,117,114,46,110,117,109,114,9,102,105,118,101,46,110,117,109,114,8,115,105,120,46,110,117,109,114,10,115,101,118,101,110,46,110,117,109,114,10,101,105,103,104,116,46,110,117,109,114,9,110,105,110,101,46,110,117,109,114,12,122,101,114,111,115,117,112,101,114,105,111,114,12,102,111,117,114,115,117,112,101,114,105,111,114,12,102,105,118,101,115,117,112,101,114,105,111,114,11,115,105,120,115,117,112,101,114,105,111,114,13,115,101,118,101,110,115,117,112,101,114,105,111,114,13,101,105,103,104,116,115,117,112,101,114,105,111,114,12,110,105,110,101,115,117,112,101,114,105,111,114,9,111,110,101,101,105,103,104,116,104,12,116,104,114,101,101,101,105,103,104,116,104,115,11,102,105,118,101,101,105,103,104,116,104,115,12,115,101,118,101,110,101,105,103,104,116,104,115,12,101,120,99,108,97,109,100,111,117,98,108,101,14,111,110,101,100,111,116,101,110,108,101,97,100,101,114,8,111,118,101,114,108,105,110,101,43,104,101,97,118,121,108,101,102,116,112,111,105,110,116,105,110,103,97,110,103,108,101,113,117,111,116,97,116,105,111,110,109,97,114,107,111,114,110,97,109,101,110,116,44,104,101,97,118,121,114,105,103,104,116,112,111,105,110,116,105,110,103,97,110,103,108,101,113,117,111,116,97,116,105,111,110,109,97,114,107,111,114,110,97,109,101,110,116,38,109,101,100,105,117,109,108,101,102,116,112,111,105,110,116,105,110,103,97,110,103,108,101,98,114,97,99,107,101,116,111,114,110,97,109,101,110,116,39,109,101,100,105,117,109,114,105,103,104,116,112,111,105,110,116,105,110,103,97,110,103,108,101,98,114,97,99,107,101,116,111,114,110,97,109,101,110,116,10,115,111,102,116,104,121,112,104,101,110,13,104,111,114,105,122,111,110,116,97,108,98,97,114,9,104,121,112,104,101,110,116,119,111,17,110,111,110,98,114,101,97,107,105,110,103,104,121,112,104,101,110,13,117,110,100,101,114,115,99,111,114,101,100,98,108,13,113,117,111,116,101,114,101,118,101,114,115,101,100,13,103,117,105,108,108,101,109,101,116,108,101,102,116,14,103,117,105,108,108,101,109,101,116,114,105,103,104,116,18,104,121,112,104,101,110,95,104,121,112,104,101,110,46,108,105,103,97,25,104,121,112,104,101,110,95,104,121,112,104,101,110,95,104,121,112,104,101,110,46,108,105,103,97,26,104,121,112,104,101,110,95,104,121,112,104,101,110,95,103,114,101,97,116,101,114,46,108,105,103,97,15,104,121,112,104,101,110,95,98,97,114,46,108,105,103,97,19,104,121,112,104,101,110,95,103,114,101,97,116,101,114,46,108,105,103,97,27,104,121,112,104,101,110,95,103,114,101,97,116,101,114,95,103,114,101,97,116,101,114,46,108,105,103,97,16,104,121,112,104,101,110,95,108,101,115,115,46,108,105,103,97,21,104,121,112,104,101,110,95,108,101,115,115,95,108,101,115,115,46,108,105,103,97,22,104,121,112,104,101,110,95,97,115,99,105,105,116,105,108,100,101,46,108,105,103,97,23,112,97,114,101,110,108,101,102,116,95,97,115,116,101,114,105,115,107,46,108,105,103,97,18,98,114,97,99,101,108,101,102,116,95,98,97,114,46,108,105,103,97,26,98,114,97,99,101,114,105,103,104,116,95,110,117,109,98,101,114,115,105,103,110,46,108,105,103,97,20,98,114,97,99,107,101,116,108,101,102,116,95,98,97,114,46,108,105,103,97,28,98,114,97,99,107,101,116,114,105,103,104,116,95,110,117,109,98,101,114,115,105,103,110,46,108,105,103,97,18,112,101,114,105,111,100,95,104,121,112,104,101,110,46,108,105,103,97,18,112,101,114,105,111,100,95,112,101,114,105,111,100,46,108,105,103,97,25,112,101,114,105,111,100,95,112,101,114,105,111,100,95,112,101,114,105,111,100,46,108,105,103,97,24,112,101,114,105,111,100,95,112,101,114,105,111,100,95,101,113,117,97,108,46,108,105,103,97,23,112,101,114,105,111,100,95,112,101,114,105,111,100,95,108,101,115,115,46,108,105,103,97,20,112,101,114,105,111,100,95,113,117,101,115,116,105,111,110,46,108,105,103,97,17,112,101,114,105,111,100,95,101,113,117,97,108,46,108,105,103,97,16,99,111,108,111,110,95,99,111,108,111,110,46,108,105,103,97,22,99,111,108,111,110,95,99,111,108,111,110,95,99,111,108,111,110,46,108,105,103,97,22,99,111,108,111,110,95,99,111,108,111,110,95,101,113,117,97,108,46,108,105,103,97,16,99,111,108,111,110,95,101,113,117,97,108,46,108,105,103,97,18,99,111,108,111,110,95,103,114,101,97,116,101,114,46,108,105,103,97,15,99,111,108,111,110,95,108,101,115,115,46,108,105,103,97,22,99,111,108,111,110,95,115,108,97,115,104,95,115,108,97,115,104,46,108,105,103,97,24,115,101,109,105,99,111,108,111,110,95,115,101,109,105,99,111,108,111,110,46,108,105,103,97,18,101,120,99,108,97,109,95,101,120,99,108,97,109,46,108,105,103,97,25,101,120,99,108,97,109,95,101,120,99,108,97,109,95,112,101,114,105,111,100,46,108,105,103,97,17,101,120,99,108,97,109,95,101,113,117,97,108,46,108,105,103,97,23,101,120,99,108,97,109,95,101,113,117,97,108,95,101,113,117,97,108,46,108,105,103,97,20,113,117,101,115,116,105,111,110,95,112,101,114,105,111,100,46,108,105,103,97,19,113,117,101,115,116,105,111,110,95,99,111,108,111,110,46,108,105,103,97,22,113,117,101,115,116,105,111,110,95,113,117,101,115,116,105,111,110,46,108,105,103,97,19,113,117,101,115,116,105,111,110,95,101,113,117,97,108,46,108,105,103,97,24,97,115,116,101,114,105,115,107,95,112,97,114,101,110,114,105,103,104,116,46,108,105,103,97,22,97,115,116,101,114,105,115,107,95,97,115,116,101,114,105,115,107,46,108,105,103,97,31,97,115,116,101,114,105,115,107,95,97,115,116,101,114,105,115,107,95,97,115,116,101,114,105,115,107,46,108,105,103,97,21,97,115,116,101,114,105,115,107,95,103,114,101,97,116,101,114,46,108,105,103,97,19,97,115,116,101,114,105,115,107,95,115,108,97,115,104,46,108,105,103,97,25,110,117,109,98,101,114,115,105,103,110,95,112,97,114,101,110,108,101,102,116,46,108,105,103,97,25,110,117,109,98,101,114,115,105,103,110,95,98,114,97,99,101,108,101,102,116,46,108,105,103,97,27,110,117,109,98,101,114,115,105,103,110,95,98,114,97,99,107,101,116,108,101,102,116,46,108,105,103,97,21,110,117,109,98,101,114,115,105,103,110,95,99,111,108,111,110,46,108,105,103,97,22,110,117,109,98,101,114,115,105,103,110,95,101,120,99,108,97,109,46,108,105,103,97,24,110,117,109,98,101,114,115,105,103,110,95,113,117,101,115,116,105,111,110,46,108,105,103,97,26,110,117,109,98,101,114,115,105,103,110,95,110,117,109,98,101,114,115,105,103,110,46,108,105,103,97,37,110,117,109,98,101,114,115,105,103,110,95,110,117,109,98,101,114,115,105,103,110,95,110,117,109,98,101,114,115,105,103,110,46,108,105,103,97,48,110,117,109,98,101,114,115,105,103,110,95,110,117,109,98,101,114,115,105,103,110,95,110,117,109,98,101,114,115,105,103,110,95,110,117,109,98,101,114,115,105,103,110,46,108,105,103,97,21,110,117,109,98,101,114,115,105,103,110,95,101,113,117,97,108,46,108,105,103,97,26,110,117,109,98,101,114,115,105,103,110,95,117,110,100,101,114,115,99,111,114,101,46,108,105,103,97,36,110,117,109,98,101,114,115,105,103,110,95,117,110,100,101,114,115,99,111,114,101,95,112,97,114,101,110,108,101,102,116,46,108,105,103,97,19,115,108,97,115,104,95,97,115,116,101,114,105,115,107,46,108,105,103,97,16,115,108,97,115,104,95,101,113,117,97,108,46,108,105,103,97,22,115,108,97,115,104,95,101,113,117,97,108,95,101,113,117,97,108,46,108,105,103,97,18,115,108,97,115,104,95,103,114,101,97,116,101,114,46,108,105,103,97,16,115,108,97,115,104,95,115,108,97,115,104,46,108,105,103,97,22,115,108,97,115,104,95,115,108,97,115,104,95,115,108,97,115,104,46,108,105,103,97,24,98,97,99,107,115,108,97,115,104,95,98,97,99,107,115,108,97,115,104,46,108,105,103,97,30,117,110,100,101,114,115,99,111,114,101,95,98,97,114,95,117,110,100,101,114,115,99,111,114,101,46,108,105,103,97,26,117,110,100,101,114,115,99,111,114,101,95,117,110,100,101,114,115,99,111,114,101,46,108,105,103,97,9,97,110,111,116,101,108,101,105,97,13,113,117,101,115,116,105,111,110,103,114,101,101,107,16,112,117,110,99,116,117,97,116,105,111,110,115,112,97,99,101,7,110,98,115,112,97,99,101,2,67,82,13,108,105,110,101,115,101,112,97,114,97,116,111,114,4,98,97,104,116,4,99,101,100,105,9,99,111,108,111,110,115,105,103,110,4,100,111,110,103,4,101,117,114,111,12,101,117,114,111,99,117,114,114,101,110,99,121,7,103,117,97,114,97,110,105,7,104,114,121,118,110,105,97,3,107,105,112,4,108,97,114,105,4,108,105,114,97,11,108,105,114,97,84,117,114,107,105,115,104,5,109,97,110,97,116,5,110,97,105,114,97,6,112,101,115,101,116,97,4,112,101,115,111,5,114,117,98,108,101,5,114,117,112,101,101,11,114,117,112,101,101,73,110,100,105,97,110,6,115,104,101,113,101,108,5,116,101,110,103,101,6,116,117,103,114,105,107,3,119,111,110,14,98,117,108,108,101,116,111,112,101,114,97,116,111,114,13,100,105,118,105,115,105,111,110,115,108,97,115,104,11,101,113,117,105,118,97,108,101,110,99,101,23,104,111,114,105,122,111,110,116,97,108,108,105,110,101,101,120,116,101,110,115,105,111,110,10,105,110,116,101,103,114,97,108,98,116,10,105,110,116,101,103,114,97,108,116,112,18,108,111,103,105,99,97,108,110,111,116,82,101,118,101,114,115,101,100,12,110,111,116,105,100,101,110,116,105,99,97,108,12,105,110,116,101,114,115,101,99,116,105,111,110,3,79,104,109,9,105,110,99,114,101,109,101,110,116,5,109,105,99,114,111,10,111,114,116,104,111,103,111,110,97,108,20,115,116,114,105,99,116,108,121,101,113,117,105,118,97,108,101,110,116,116,111,20,118,101,99,116,111,114,79,114,67,114,111,115,115,80,114,111,100,117,99,116,7,117,112,65,114,114,111,119,10,114,105,103,104,116,65,114,114,111,119,9,100,111,119,110,65,114,114,111,119,9,108,101,102,116,65,114,114,111,119,14,108,101,102,116,82,105,103,104,116,65,114,114,111,119,11,117,112,68,111,119,110,65,114,114,111,119,15,117,112,68,111,119,110,98,97,115,101,65,114,114,111,119,11,117,112,68,97,115,104,65,114,114,111,119,13,100,97,115,104,100,111,119,110,65,114,114,111,119,19,108,111,119,101,114,79,110,101,69,105,103,104,116,104,66,108,111,99,107,20,108,111,119,101,114,79,110,101,81,117,97,114,116,101,114,66,108,111,99,107,22,108,111,119,101,114,84,104,114,101,101,69,105,103,104,116,104,115,66,108,111,99,107,14,108,111,119,101,114,72,97,108,102,66,108,111,99,107,21,108,111,119,101,114,70,105,118,101,69,105,103,104,116,104,115,66,108,111,99,107,23,108,111,119,101,114,84,104,114,101,101,81,117,97,114,116,101,114,115,66,108,111,99,107,22,108,111,119,101,114,83,101,118,101,110,69,105,103,104,116,104,115,66,108,111,99,107,9,102,117,108,108,66,108,111,99,107,14,117,112,112,101,114,72,97,108,102,66,108,111,99,107,19,117,112,112,101,114,79,110,101,69,105,103,104,116,104,66,108,111,99,107,18,108,101,102,116,79,110,101,69,105,103,104,116,104,66,108,111,99,107,19,108,101,102,116,79,110,101,81,117,97,114,116,101,114,66,108,111,99,107,21,108,101,102,116,84,104,114,101,101,69,105,103,104,116,104,115,66,108,111,99,107,9,108,101,102,116,66,108,111,99,107,20,108,101,102,116,70,105,118,101,69,105,103,104,116,104,115,66,108,111,99,107,22,108,101,102,116,84,104,114,101,101,81,117,97,114,116,101,114,115,66,108,111,99,107,21,108,101,102,116,83,101,118,101,110,69,105,103,104,116,104,115,66,108,111,99,107,10,114,105,103,104,116,66,108,111,99,107,19,114,105,103,104,116,79,110,101,69,105,103,104,116,104,66,108,111,99,107,14,108,111,119,101,114,76,101,102,116,66,108,111,99,107,15,108,111,119,101,114,82,105,103,104,116,66,108,111,99,107,14,117,112,112,101,114,76,101,102,116,66,108,111,99,107,39,117,112,112,101,114,76,101,102,116,65,110,100,76,111,119,101,114,76,101,102,116,65,110,100,76,111,119,101,114,82,105,103,104,116,66,108,111,99,107,27,117,112,112,101,114,76,101,102,116,65,110,100,76,111,119,101,114,82,105,103,104,116,66,108,111,99,107,39,117,112,112,101,114,76,101,102,116,65,110,100,85,112,112,101,114,82,105,103,104,116,65,110,100,76,111,119,101,114,76,101,102,116,66,108,111,99,107,40,117,112,112,101,114,76,101,102,116,65,110,100,85,112,112,101,114,82,105,103,104,116,65,110,100,76,111,119,101,114,82,105,103,104,116,66,108,111,99,107,15,117,112,112,101,114,82,105,103,104,116,66,108,111,99,107,27,117,112,112,101,114,82,105,103,104,116,65,110,100,76,111,119,101,114,76,101,102,116,66,108,111,99,107,40,117,112,112,101,114,82,105,103,104,116,65,110,100,76,111,119,101,114,76,101,102,116,65,110,100,76,111,119,101,114,82,105,103,104,116,66,108,111,99,107,10,115,104,97,100,101,108,105,103,104,116,11,115,104,97,100,101,109,101,100,105,117,109,9,115,104,97,100,101,100,97,114,107,11,98,108,97,99,107,67,105,114,99,108,101,11,119,104,105,116,101,67,105,114,99,108,101,11,108,97,114,103,101,67,105,114,99,108,101,24,108,101,102,116,72,97,108,102,66,108,97,99,107,87,104,105,116,101,67,105,114,99,108,101,25,114,105,103,104,116,72,97,108,102,66,108,97,99,107,87,104,105,116,101,67,105,114,99,108,101,25,108,111,119,101,114,72,97,108,102,66,108,97,99,107,87,104,105,116,101,67,105,114,99,108,101,25,117,112,112,101,114,72,97,108,102,66,108,97,99,107,87,104,105,116,101,67,105,114,99,108,101,19,108,101,102,116,72,97,108,102,66,108,97,99,107,67,105,114,99,108,101,20,114,105,103,104,116,72,97,108,102,66,108,97,99,107,67,105,114,99,108,101,21,117,112,112,101,114,82,105,103,104,116,66,108,97,99,107,67,105,114,99,108,101,20,117,112,112,101,114,76,101,102,116,87,104,105,116,101,67,105,114,99,108,101,28,117,112,112,101,114,76,101,102,116,81,117,97,100,114,97,110,116,87,104,105,116,101,67,105,114,99,108,101,28,108,111,119,101,114,76,101,102,116,81,117,97,100,114,97,110,116,87,104,105,116,101,67,105,114,99,108,101,29,108,111,119,101,114,82,105,103,104,116,81,117,97,100,114,97,110,116,87,104,105,116,101,67,105,114,99,108,101,29,117,112,112,101,114,82,105,103,104,116,81,117,97,100,114,97,110,116,87,104,105,116,101,67,105,114,99,108,101,18,118,101,114,116,105,99,97,108,70,105,108,108,67,105,114,99,108,101,12,100,111,116,116,101,100,67,105,114,99,108,101,7,102,105,115,104,101,121,101,8,98,117,108,108,115,101,121,101,11,119,104,105,116,101,66,117,108,108,101,116,13,105,110,118,101,114,115,101,66,117,108,108,101,116,18,105,110,118,101,114,115,101,87,104,105,116,101,67,105,114,99,108,101,27,117,112,112,101,114,72,97,108,102,73,110,118,101,114,115,101,87,104,105,116,101,67,105,114,99,108,101,27,108,111,119,101,114,72,97,108,102,73,110,118,101,114,115,101,87,104,105,116,101,67,105,114,99,108,101,12,117,112,112,101,114,72,97,108,102,65,114,99,12,108,111,119,101,114,72,97,108,102,65,114,99,12,117,112,112,101,114,76,101,102,116,65,114,99,13,117,112,112,101,114,82,105,103,104,116,65,114,99,13,108,111,119,101,114,82,105,103,104,116,65,114,99,12,108,111,119,101,114,76,101,102,116,65,114,99,12,98,108,97,99,107,68,105,97,109,111,110,100,12,119,104,105,116,101,68,105,97,109,111,110,100,20,108,101,102,116,72,97,108,102,66,108,97,99,107,68,105,97,109,111,110,100,21,114,105,103,104,116,72,97,108,102,66,108,97,99,107,68,105,97,109,111,110,100,19,116,111,112,72,97,108,102,66,108,97,99,107,68,105,97,109,111,110,100,22,98,111,116,116,111,109,72,97,108,102,66,108,97,99,107,68,105,97,109,111,110,100,19,98,108,97,99,107,73,110,87,104,105,116,101,68,105,97,109,111,110,100,18,98,108,97,99,107,80,97,114,97,108,108,101,108,111,103,114,97,109,18,119,104,105,116,101,80,97,114,97,108,108,101,108,111,103,114,97,109,17,98,108,97,99,107,86,101,114,116,105,99,97,108,82,101,99,116,10,102,105,108,108,101,100,82,101,99,116,9,119,104,105,116,101,82,101,99,116,17,119,104,105,116,101,86,101,114,116,105,99,97,108,82,101,99,116,11,98,108,97,99,107,83,113,117,97,114,101,11,119,104,105,116,101,83,113,117,97,114,101,25,119,104,105,116,101,82,111,117,110,100,101,100,67,111,114,110,101,114,115,83,113,117,97,114,101,18,119,104,105,116,101,73,110,66,108,97,99,107,83,113,117,97,114,101,12,100,111,116,116,101,100,83,113,117,97,114,101,20,104,111,114,105,122,111,110,116,97,108,70,105,108,108,83,113,117,97,114,101,18,118,101,114,116,105,99,97,108,70,105,108,108,83,113,117,97,114,101,20,99,114,111,115,115,104,97,116,99,104,70,105,108,108,83,113,117,97,114,101,31,117,112,112,101,114,108,101,102,116,116,111,108,111,119,101,114,114,105,103,104,116,70,105,108,108,83,113,117,97,114,101,31,117,112,112,101,114,114,105,103,104,116,116,111,108,111,119,101,114,108,101,102,116,70,105,108,108,83,113,117,97,114,101,28,100,105,97,103,111,110,97,108,99,114,111,115,115,104,97,116,99,104,70,105,108,108,83,113,117,97,114,101,16,98,108,97,99,107,83,109,97,108,108,83,113,117,97,114,101,16,119,104,105,116,101,83,109,97,108,108,83,113,117,97,114,101,19,108,101,102,116,72,97,108,102,66,108,97,99,107,83,113,117,97,114,101,20,114,105,103,104,116,72,97,108,102,66,108,97,99,107,83,113,117,97,114,101,32,117,112,112,101,114,76,101,102,116,68,105,97,103,111,110,97,108,72,97,108,102,66,108,97,99,107,83,113,117,97,114,101,33,108,111,119,101,114,82,105,103,104,116,68,105,97,103,111,110,97,108,72,97,108,102,66,108,97,99,107,83,113,117,97,114,101,32,118,101,114,116,105,99,97,108,66,105,115,101,99,116,105,110,103,76,105,110,101,87,104,105,116,101,83,113,117,97,114,101,28,119,104,105,116,101,85,112,112,101,114,76,101,102,116,81,117,97,100,114,97,110,116,83,113,117,97,114,101,28,119,104,105,116,101,76,111,119,101,114,76,101,102,116,81,117,97,100,114,97,110,116,83,113,117,97,114,101,29,119,104,105,116,101,76,111,119,101,114,82,105,103,104,116,81,117,97,100,114,97,110,116,83,113,117,97,114,101,29,119,104,105,116,101,85,112,112,101,114,82,105,103,104,116,81,117,97,100,114,97,110,116,83,113,117,97,114,101,17,109,101,100,105,117,109,87,104,105,116,101,83,113,117,97,114,101,17,109,101,100,105,117,109,66,108,97,99,107,83,113,117,97,114,101,22,109,101,100,105,117,109,87,104,105,116,101,83,109,97,108,108,83,113,117,97,114,101,22,109,101,100,105,117,109,66,108,97,99,107,83,109,97,108,108,83,113,117,97,114,101,15,117,112,66,108,97,99,107,84,114,105,97,110,103,108,101,18,114,105,103,104,116,66,108,97,99,107,84,114,105,97,110,103,108,101,17,100,111,119,110,66,108,97,99,107,84,114,105,97,110,103,108,101,17,108,101,102,116,66,108,97,99,107,84,114,105,97,110,103,108,101,15,117,112,87,104,105,116,101,84,114,105,97,110,103,108,101,18,114,105,103,104,116,87,104,105,116,101,84,114,105,97,110,103,108,101,17,100,111,119,110,87,104,105,116,101,84,114,105,97,110,103,108,101,17,108,101,102,116,87,104,105,116,101,84,114,105,97,110,103,108,101,22,117,112,87,104,105,116,101,84,114,105,97,110,103,108,101,87,105,116,104,68,111,116,23,117,112,76,101,102,116,72,97,108,102,66,108,97,99,107,84,114,105,97,110,103,108,101,24,117,112,82,105,103,104,116,72,97,108,102,66,108,97,99,107,84,114,105,97,110,103,108,101,17,114,105,103,104,116,66,108,97,99,107,80,111,105,110,116,101,114,16,108,101,102,116,66,108,97,99,107,80,111,105,110,116,101,114,17,114,105,103,104,116,87,104,105,116,101,80,111,105,110,116,101,114,16,108,101,102,116,87,104,105,116,101,80,111,105,110,116,101,114,20,117,112,66,108,97,99,107,83,109,97,108,108,84,114,105,97,110,103,108,101,23,114,105,103,104,116,66,108,97,99,107,83,109,97,108,108,84,114,105,97,110,103,108,101,22,100,111,119,110,66,108,97,99,107,83,109,97,108,108,84,114,105,97,110,103,108,101,22,108,101,102,116,66,108,97,99,107,83,109,97,108,108,84,114,105,97,110,103,108,101,20,117,112,87,104,105,116,101,83,109,97,108,108,84,114,105,97,110,103,108,101,23,114,105,103,104,116,87,104,105,116,101,83,109,97,108,108,84,114,105,97,110,103,108,101,22,100,111,119,110,87,104,105,116,101,83,109,97,108,108,84,114,105,97,110,103,108,101,22,108,101,102,116,87,104,105,116,101,83,109,97,108,108,84,114,105,97,110,103,108,101,23,117,112,112,101,114,82,105,103,104,116,66,108,97,99,107,84,114,105,97,110,103,108,101,23,108,111,119,101,114,82,105,103,104,116,66,108,97,99,107,84,114,105,97,110,103,108,101,22,108,111,119,101,114,76,101,102,116,66,108,97,99,107,84,114,105,97,110,103,108,101,22,117,112,112,101,114,76,101,102,116,66,108,97,99,107,84,114,105,97,110,103,108,101,18,117,112,112,101,114,82,105,103,104,116,84,114,105,97,110,103,108,101,18,108,111,119,101,114,82,105,103,104,116,84,114,105,97,110,103,108,101,17,108,111,119,101,114,76,101,102,116,84,114,105,97,110,103,108,101,17,117,112,112,101,114,76,101,102,116,84,114,105,97,110,103,108,101,26,98,111,120,68,111,117,98,108,101,68,111,119,110,65,110,100,72,111,114,105,122,111,110,116,97,108,20,98,111,120,68,111,117,98,108,101,68,111,119,110,65,110,100,76,101,102,116,21,98,111,120,68,111,117,98,108,101,68,111,119,110,65,110,100,82,105,103,104,116,19,98,111,120,68,111,117,98,108,101,72,111,114,105,122,111,110,116,97,108,24,98,111,120,68,111,117,98,108,101,85,112,65,110,100,72,111,114,105,122,111,110,116,97,108,18,98,111,120,68,111,117,98,108,101,85,112,65,110,100,76,101,102,116,19,98,111,120,68,111,117,98,108,101,85,112,65,110,100,82,105,103,104,116,17,98,111,120,68,111,117,98,108,101,86,101,114,116,105,99,97,108,30,98,111,120,68,111,117,98,108,101,86,101,114,116,105,99,97,108,65,110,100,72,111,114,105,122,111,110,116,97,108,24,98,111,120,68,111,117,98,108,101,86,101,114,116,105,99,97,108,65,110,100,76,101,102,116,25,98,111,120,68,111,117,98,108,101,86,101,114,116,105,99,97,108,65,110,100,82,105,103,104,116,32,98,111,120,68,111,119,110,68,111,117,98,108,101,65,110,100,72,111,114,105,122,111,110,116,97,108,83,105,110,103,108,101,26,98,111,120,68,111,119,110,68,111,117,98,108,101,65,110,100,76,101,102,116,83,105,110,103,108,101,27,98,111,120,68,111,119,110,68,111,117,98,108,101,65,110,100,82,105,103,104,116,83,105,110,103,108,101,30,98,111,120,68,111,119,110,72,101,97,118,121,65,110,100,72,111,114,105,122,111,110,116,97,108,76,105,103,104,116,24,98,111,120,68,111,119,110,72,101,97,118,121,65,110,100,76,101,102,116,76,105,103,104,116,26,98,111,120,68,111,119,110,72,101,97,118,121,65,110,100,76,101,102,116,85,112,76,105,103,104,116,25,98,111,120,68,111,119,110,72,101,97,118,121,65,110,100,82,105,103,104,116,76,105,103,104,116,27,98,111,120,68,111,119,110,72,101,97,118,121,65,110,100,82,105,103,104,116,85,112,76,105,103,104,116,32,98,111,120,68,111,119,110,72,101,97,118,121,65,110,100,85,112,72,111,114,105,122,111,110,116,97,108,76,105,103,104,116,30,98,111,120,68,111,119,110,76,105,103,104,116,65,110,100,72,111,114,105,122,111,110,116,97,108,72,101,97,118,121,24,98,111,120,68,111,119,110,76,105,103,104,116,65,110,100,76,101,102,116,72,101,97,118,121,26,98,111,120,68,111,119,110,76,105,103,104,116,65,110,100,76,101,102,116,85,112,72,101,97,118,121,25,98,111,120,68,111,119,110,76,105,103,104,116,65,110,100,82,105,103,104,116,72,101,97,118,121,27,98,111,120,68,111,119,110,76,105,103,104,116,65,110,100,82,105,103,104,116,85,112,72,101,97,118,121,32,98,111,120,68,111,119,110,76,105,103,104,116,65,110,100,85,112,72,111,114,105,122,111,110,116,97,108,72,101,97,118,121,32,98,111,120,68,111,119,110,83,105,110,103,108,101,65,110,100,72,111,114,105,122,111,110,116,97,108,68,111,117,98,108,101,26,98,111,120,68,111,119,110,83,105,110,103,108,101,65,110,100,76,101,102,116,68,111,117,98,108,101,27,98,111,120,68,111,119,110,83,105,110,103,108,101,65,110,100,82,105,103,104,116,68,111,117,98,108,101,28,98,111,120,72,101,97,118,121,68,111,117,98,108,101,68,97,115,104,72,111,114,105,122,111,110,116,97,108,26,98,111,120,72,101,97,118,121,68,111,117,98,108,101,68,97,115,104,86,101,114,116,105,99,97,108,12,98,111,120,72,101,97,118,121,68,111,119,110,25,98,111,120,72,101,97,118,121,68,111,119,110,65,110,100,72,111,114,105,122,111,110,116,97,108,19,98,111,120,72,101,97,118,121,68,111,119,110,65,110,100,76,101,102,116,20,98,111,120,72,101,97,118,121,68,111,119,110,65,110,100,82,105,103,104,116,18,98,111,120,72,101,97,118,121,72,111,114,105,122,111,110,116,97,108,12,98,111,120,72,101,97,118,121,76,101,102,116,25,98,111,120,72,101,97,118,121,76,101,102,116,65,110,100,76,105,103,104,116,82,105,103,104,116,31,98,111,120,72,101,97,118,121,81,117,97,100,114,117,112,108,101,68,97,115,104,72,111,114,105,122,111,110,116,97,108,29,98,111,120,72,101,97,118,121,81,117,97,100,114,117,112,108,101,68,97,115,104,86,101,114,116,105,99,97,108,13,98,111,120,72,101,97,118,121,82,105,103,104,116,28,98,111,120,72,101,97,118,121,84,114,105,112,108,101,68,97,115,104,72,111,114,105,122,111,110,116,97,108,26,98,111,120,72,101,97,118,121,84,114,105,112,108,101,68,97,115,104,86,101,114,116,105,99,97,108,10,98,111,120,72,101,97,118,121,85,112,23,98,111,120,72,101,97,118,121,85,112,65,110,100,72,111,114,105,122,111,110,116,97,108,17,98,111,120,72,101,97,118,121,85,112,65,110,100,76,101,102,116,22,98,111,120,72,101,97,118,121,85,112,65,110,100,76,105,103,104,116,68,111,119,110,18,98,111,120,72,101,97,118,121,85,112,65,110,100,82,105,103,104,116,16,98,111,120,72,101,97,118,121,86,101,114,116,105,99,97,108,29,98,111,120,72,101,97,118,121,86,101,114,116,105,99,97,108,65,110,100,72,111,114,105,122,111,110,116,97,108,23,98,111,120,72,101,97,118,121,86,101,114,116,105,99,97,108,65,110,100,76,101,102,116,24,98,111,120,72,101,97,118,121,86,101,114,116,105,99,97,108,65,110,100,82,105,103,104,116,31,98,111,120,76,101,102,116,68,111,119,110,72,101,97,118,121,65,110,100,82,105,103,104,116,85,112,76,105,103,104,116,29,98,111,120,76,101,102,116,72,101,97,118,121,65,110,100,82,105,103,104,116,68,111,119,110,76,105,103,104,116,27,98,111,120,76,101,102,116,72,101,97,118,121,65,110,100,82,105,103,104,116,85,112,76,105,103,104,116,33,98,111,120,76,101,102,116,72,101,97,118,121,65,110,100,82,105,103,104,116,86,101,114,116,105,99,97,108,76,105,103,104,116,29,98,111,120,76,101,102,116,76,105,103,104,116,65,110,100,82,105,103,104,116,68,111,119,110,72,101,97,118,121,27,98,111,120,76,101,102,116,76,105,103,104,116,65,110,100,82,105,103,104,116,85,112,72,101,97,118,121,33,98,111,120,76,101,102,116,76,105,103,104,116,65,110,100,82,105,103,104,116,86,101,114,116,105,99,97,108,72,101,97,118,121,31,98,111,120,76,101,102,116,85,112,72,101,97,118,121,65,110,100,82,105,103,104,116,68,111,119,110,76,105,103,104,116,22,98,111,120,76,105,103,104,116,65,114,99,68,111,119,110,65,110,100,76,101,102,116,23,98,111,120,76,105,103,104,116,65,114,99,68,111,119,110,65,110,100,82,105,103,104,116,20,98,111,120,76,105,103,104,116,65,114,99,85,112,65,110,100,76,101,102,116,21,98,111,120,76,105,103,104,116,65,114,99,85,112,65,110,100,82,105,103,104,116,21,98,111,120,76,105,103,104,116,68,105,97,103,111,110,97,108,67,114,111,115,115,37,98,111,120,76,105,103,104,116,68,105,97,103,111,110,97,108,85,112,112,101,114,76,101,102,116,84,111,76,111,119,101,114,82,105,103,104,116,37,98,111,120,76,105,103,104,116,68,105,97,103,111,110,97,108,85,112,112,101,114,82,105,103,104,116,84,111,76,111,119,101,114,76,101,102,116,28,98,111,120,76,105,103,104,116,68,111,117,98,108,101,68,97,115,104,72,111,114,105,122,111,110,116,97,108,26,98,111,120,76,105,103,104,116,68,111,117,98,108,101,68,97,115,104,86,101,114,116,105,99,97,108,12,98,111,120,76,105,103,104,116,68,111,119,110,25,98,111,120,76,105,103,104,116,68,111,119,110,65,110,100,72,111,114,105,122,111,110,116,97,108,19,98,111,120,76,105,103,104,116,68,111,119,110,65,110,100,76,101,102,116,20,98,111,120,76,105,103,104,116,68,111,119,110,65,110,100,82,105,103,104,116,18,98,111,120,76,105,103,104,116,72,111,114,105,122,111,110,116,97,108,12,98,111,120,76,105,103,104,116,76,101,102,116,25,98,111,120,76,105,103,104,116,76,101,102,116,65,110,100,72,101,97,118,121,82,105,103,104,116,31,98,111,120,76,105,103,104,116,81,117,97,100,114,117,112,108,101,68,97,115,104,72,111,114,105,122,111,110,116,97,108,29,98,111,120,76,105,103,104,116,81,117,97,100,114,117,112,108,101,68,97,115,104,86,101,114,116,105,99,97,108,13,98,111,120,76,105,103,104,116,82,105,103,104,116,28,98,111,120,76,105,103,104,116,84,114,105,112,108,101,68,97,115,104,72,111,114,105,122,111,110,116,97,108,26,98,111,120,76,105,103,104,116,84,114,105,112,108,101,68,97,115,104,86,101,114,116,105,99,97,108,10,98,111,120,76,105,103,104,116,85,112,22,98,111,120,76,105,103,104,116,85,112,65,110,100,72,101,97,118,121,68,111,119,110,23,98,111,120,76,105,103,104,116,85,112,65,110,100,72,111,114,105,122,111,110,116,97,108,17,98,111,120,76,105,103,104,116,85,112,65,110,100,76,101,102,116,18,98,111,120,76,105,103,104,116,85,112,65,110,100,82,105,103,104,116,16,98,111,120,76,105,103,104,116,86,101,114,116,105,99,97,108,29,98,111,120,76,105,103,104,116,86,101,114,116,105,99,97,108,65,110,100,72,111,114,105,122,111,110,116,97,108,23,98,111,120,76,105,103,104,116,86,101,114,116,105,99,97,108,65,110,100,76,101,102,116,24,98,111,120,76,105,103,104,116,86,101,114,116,105,99,97,108,65,110,100,82,105,103,104,116,31,98,111,120,82,105,103,104,116,68,111,119,110,72,101,97,118,121,65,110,100,76,101,102,116,85,112,76,105,103,104,116,29,98,111,120,82,105,103,104,116,72,101,97,118,121,65,110,100,76,101,102,116,68,111,119,110,76,105,103,104,116,27,98,111,120,82,105,103,104,116,72,101,97,118,121,65,110,100,76,101,102,116,85,112,76,105,103,104,116,33,98,111,120,82,105,103,104,116,72,101,97,118,121,65,110,100,76,101,102,116,86,101,114,116,105,99,97,108,76,105,103,104,116,29,98,111,120,82,105,103,104,116,76,105,103,104,116,65,110,100,76,101,102,116,68,111,119,110,72,101,97,118,121,27,98,111,120,82,105,103,104,116,76,105,103,104,116,65,110,100,76,101,102,116,85,112,72,101,97,118,121,33,98,111,120,82,105,103,104,116,76,105,103,104,116,65,110,100,76,101,102,116,86,101,114,116,105,99,97,108,72,101,97,118,121,31,98,111,120,82,105,103,104,116,85,112,72,101,97,118,121,65,110,100,76,101,102,116,68,111,119,110,76,105,103,104,116,30,98,111,120,85,112,68,111,117,98,108,101,65,110,100,72,111,114,105,122,111,110,116,97,108,83,105,110,103,108,101,24,98,111,120,85,112,68,111,117,98,108,101,65,110,100,76,101,102,116,83,105,110,103,108,101,25,98,111,120,85,112,68,111,117,98,108,101,65,110,100,82,105,103,104,116,83,105,110,103,108,101,32,98,111,120,85,112,72,101,97,118,121,65,110,100,68,111,119,110,72,111,114,105,122,111,110,116,97,108,76,105,103,104,116,28,98,111,120,85,112,72,101,97,118,121,65,110,100,72,111,114,105,122,111,110,116,97,108,76,105,103,104,116,26,98,111,120,85,112,72,101,97,118,121,65,110,100,76,101,102,116,68,111,119,110,76,105,103,104,116,22,98,111,120,85,112,72,101,97,118,121,65,110,100,76,101,102,116,76,105,103,104,116,27,98,111,120,85,112,72,101,97,118,121,65,110,100,82,105,103,104,116,68,111,119,110,76,105,103,104,116,23,98,111,120,85,112,72,101,97,118,121,65,110,100,82,105,103,104,116,76,105,103,104,116,32,98,111,120,85,112,76,105,103,104,116,65,110,100,68,111,119,110,72,111,114,105,122,111,110,116,97,108,72,101,97,118,121,28,98,111,120,85,112,76,105,103,104,116,65,110,100,72,111,114,105,122,111,110,116,97,108,72,101,97,118,121,26,98,111,120,85,112,76,105,103,104,116,65,110,100,76,101,102,116,68,111,119,110,72,101,97,118,121,22,98,111,120,85,112,76,105,103,104,116,65,110,100,76,101,102,116,72,101,97,118,121,27,98,111,120,85,112,76,105,103,104,116,65,110,100,82,105,103,104,116,68,111,119,110,72,101,97,118,121,23,98,111,120,85,112,76,105,103,104,116,65,110,100,82,105,103,104,116,72,101,97,118,121,30,98,111,120,85,112,83,105,110,103,108,101,65,110,100,72,111,114,105,122,111,110,116,97,108,68,111,117,98,108,101,24,98,111,120,85,112,83,105,110,103,108,101,65,110,100,76,101,102,116,68,111,117,98,108,101,25,98,111,120,85,112,83,105,110,103,108,101,65,110,100,82,105,103,104,116,68,111,117,98,108,101,36,98,111,120,86,101,114,116,105,99,97,108,68,111,117,98,108,101,65,110,100,72,111,114,105,122,111,110,116,97,108,83,105,110,103,108,101,30,98,111,120,86,101,114,116,105,99,97,108,68,111,117,98,108,101,65,110,100,76,101,102,116,83,105,110,103,108,101,31,98,111,120,86,101,114,116,105,99,97,108,68,111,117,98,108,101,65,110,100,82,105,103,104,116,83,105,110,103,108,101,34,98,111,120,86,101,114,116,105,99,97,108,72,101,97,118,121,65,110,100,72,111,114,105,122,111,110,116,97,108,76,105,103,104,116,28,98,111,120,86,101,114,116,105,99,97,108,72,101,97,118,121,65,110,100,76,101,102,116,76,105,103,104,116,29,98,111,120,86,101,114,116,105,99,97,108,72,101,97,118,121,65,110,100,82,105,103,104,116,76,105,103,104,116,34,98,111,120,86,101,114,116,105,99,97,108,76,105,103,104,116,65,110,100,72,111,114,105,122,111,110,116,97,108,72,101,97,118,121,28,98,111,120,86,101,114,116,105,99,97,108,76,105,103,104,116,65,110,100,76,101,102,116,72,101,97,118,121,29,98,111,120,86,101,114,116,105,99,97,108,76,105,103,104,116,65,110,100,82,105,103,104,116,72,101,97,118,121,36,98,111,120,86,101,114,116,105,99,97,108,83,105,110,103,108,101,65,110,100,72,111,114,105,122,111,110,116,97,108,68,111,117,98,108,101,30,98,111,120,86,101,114,116,105,99,97,108,83,105,110,103,108,101,65,110,100,76,101,102,116,68,111,117,98,108,101,31,98,111,120,86,101,114,116,105,99,97,108,83,105,110,103,108,101,65,110,100,82,105,103,104,116,68,111,117,98,108,101,25,108,111,119,101,114,79,110,101,69,105,103,104,116,104,66,108,111,99,107,46,115,116,121,112,111,26,108,111,119,101,114,79,110,101,81,117,97,114,116,101,114,66,108,111,99,107,46,115,116,121,112,111,28,108,111,119,101,114,84,104,114,101,101,69,105,103,104,116,104,115,66,108,111,99,107,46,115,116,121,112,111,20,108,111,119,101,114,72,97,108,102,66,108,111,99,107,46,115,116,121,112,111,27,108,111,119,101,114,70,105,118,101,69,105,103,104,116,104,115,66,108,111,99,107,46,115,116,121,112,111,29,108,111,119,101,114,84,104,114,101,101,81,117,97,114,116,101,114,115,66,108,111,99,107,46,115,116,121,112,111,28,108,111,119,101,114,83,101,118,101,110,69,105,103,104,116,104,115,66,108,111,99,107,46,115,116,121,112,111,15,102,117,108,108,66,108,111,99,107,46,115,116,121,112,111,20,117,112,112,101,114,72,97,108,102,66,108,111,99,107,46,115,116,121,112,111,25,117,112,112,101,114,79,110,101,69,105,103,104,116,104,66,108,111,99,107,46,115,116,121,112,111,24,108,101,102,116,79,110,101,69,105,103,104,116,104,66,108,111,99,107,46,115,116,121,112,111,25,108,101,102,116,79,110,101,81,117,97,114,116,101,114,66,108,111,99,107,46,115,116,121,112,111,27,108,101,102,116,84,104,114,101,101,69,105,103,104,116,104,115,66,108,111,99,107,46,115,116,121,112,111,15,108,101,102,116,66,108,111,99,107,46,115,116,121,112,111,26,108,101,102,116,70,105,118,101,69,105,103,104,116,104,115,66,108,111,99,107,46,115,116,121,112,111,28,108,101,102,116,84,104,114,101,101,81,117,97,114,116,101,114,115,66,108,111,99,107,46,115,116,121,112,111,27,108,101,102,116,83,101,118,101,110,69,105,103,104,116,104,115,66,108,111,99,107,46,115,116,121,112,111,16,114,105,103,104,116,66,108,111,99,107,46,115,116,121,112,111,25,114,105,103,104,116,79,110,101,69,105,103,104,116,104,66,108,111,99,107,46,115,116,121,112,111,20,108,111,119,101,114,76,101,102,116,66,108,111,99,107,46,115,116,121,112,111,21,108,111,119,101,114,82,105,103,104,116,66,108,111,99,107,46,115,116,121,112,111,20,117,112,112,101,114,76,101,102,116,66,108,111,99,107,46,115,116,121,112,111,45,117,112,112,101,114,76,101,102,116,65,110,100,76,111,119,101,114,76,101,102,116,65,110,100,76,111,119,101,114,82,105,103,104,116,66,108,111,99,107,46,115,116,121,112,111,33,117,112,112,101,114,76,101,102,116,65,110,100,76,111,119,101,114,82,105,103,104,116,66,108,111,99,107,46,115,116,121,112,111,45,117,112,112,101,114,76,101,102,116,65,110,100,85,112,112,101,114,82,105,103,104,116,65,110,100,76,111,119,101,114,76,101,102,116,66,108,111,99,107,46,115,116,121,112,111,46,117,112,112,101,114,76,101,102,116,65,110,100,85,112,112,101,114,82,105,103,104,116,65,110,100,76,111,119,101,114,82,105,103,104,116,66,108,111,99,107,46,115,116,121,112,111,21,117,112,112,101,114,82,105,103,104,116,66,108,111,99,107,46,115,116,121,112,111,33,117,112,112,101,114,82,105,103,104,116,65,110,100,76,111,119,101,114,76,101,102,116,66,108,111,99,107,46,115,116,121,112,111,46,117,112,112,101,114,82,105,103,104,116,65,110,100,76,111,119,101,114,76,101,102,116,65,110,100,76,111,119,101,114,82,105,103,104,116,66,108,111,99,107,46,115,116,121,112,111,16,115,104,97,100,101,108,105,103,104,116,46,115,116,121,112,111,17,115,104,97,100,101,109,101,100,105,117,109,46,115,116,121,112,111,15,115,104,97,100,101,100,97,114,107,46,115,116,121,112,111,32,114,101,118,101,114,115,101,100,82,111,116,97,116,101,100,70,108,111,114,97,108,72,101,97,114,116,66,117,108,108,101,116,16,119,104,105,116,101,83,109,105,108,105,110,103,70,97,99,101,16,98,108,97,99,107,83,109,105,108,105,110,103,70,97,99,101,11,115,117,110,87,105,116,104,82,97,121,115,5,118,101,110,117,115,4,109,97,114,115,14,115,112,97,100,101,66,108,97,99,107,83,117,105,116,13,99,108,117,98,66,108,97,99,107,83,117,105,116,14,104,101,97,114,116,66,108,97,99,107,83,117,105,116,16,100,105,97,109,111,110,100,66,108,97,99,107,83,117,105,116,9,99,104,101,99,107,109,97,114,107,24,114,111,116,97,116,101,100,70,108,111,114,97,108,72,101,97,114,116,66,117,108,108,101,116,9,112,117,98,108,105,115,104,101,100,6,99,97,114,101,111,102,6,109,105,110,117,116,101,6,115,101,99,111,110,100,9,108,105,116,101,114,83,105,103,110,6,110,117,109,101,114,111,9,101,115,116,105,109,97,116,101,100,12,98,108,97,99,107,72,101,120,97,103,111,110,22,98,108,97,99,107,72,111,114,105,122,111,110,116,97,108,69,108,108,105,112,115,101,16,98,108,97,99,107,76,97,114,103,101,67,105,114,99,108,101,16,98,108,97,99,107,76,97,114,103,101,83,113,117,97,114,101,18,98,108,97,99,107,77,101,100,105,117,109,68,105,97,109,111,110,100,30,98,108,97,99,107,77,101,100,105,117,109,68,111,119,110,84,114,105,97,110,103,108,101,67,101,110,116,114,101,100,30,98,108,97,99,107,77,101,100,105,117,109,76,101,102,116,84,114,105,97,110,103,108,101,67,101,110,116,114,101,100,18,98,108,97,99,107,77,101,100,105,117,109,76,111,122,101,110,103,101,31,98,108,97,99,107,77,101,100,105,117,109,82,105,103,104,116,84,114,105,97,110,103,108,101,67,101,110,116,114,101,100,28,98,108,97,99,107,77,101,100,105,117,109,85,112,84,114,105,97,110,103,108,101,67,101,110,116,114,101,100,13,98,108,97,99,107,80,101,110,116,97,103,111,110,17,98,108,97,99,107,83,109,97,108,108,68,105,97,109,111,110,100,17,98,108,97,99,107,83,109,97,108,108,76,111,122,101,110,103,101,20,98,108,97,99,107,86,101,114,116,105,99,97,108,69,108,108,105,112,115,101,20,98,108,97,99,107,86,101,114,121,115,109,97,108,108,83,113,117,97,114,101,21,98,111,116,116,111,109,72,97,108,102,66,108,97,99,107,67,105,114,99,108,101,22,104,111,114,105,122,111,110,116,97,108,66,108,97,99,107,72,101,120,97,103,111,110,20,108,111,119,101,114,72,97,108,102,87,104,105,116,101,83,113,117,97,114,101,24,108,111,119,101,114,76,101,102,116,72,97,108,102,87,104,105,116,101,83,113,117,97,114,101,18,116,111,112,72,97,108,102,66,108,97,99,107,67,105,114,99,108,101,18,116,111,112,72,97,108,102,87,104,105,116,101,83,113,117,97,114,101,23,116,111,112,82,105,103,104,116,72,97,108,102,87,104,105,116,101,83,113,117,97,114,101,12,119,104,105,116,101,72,101,120,97,103,111,110,22,119,104,105,116,101,72,111,114,105,122,111,110,116,97,108,69,108,108,105,112,115,101,16,119,104,105,116,101,76,97,114,103,101,83,113,117,97,114,101,18,119,104,105,116,101,77,101,100,105,117,109,68,105,97,109,111,110,100,18,119,104,105,116,101,77,101,100,105,117,109,76,111,122,101,110,103,101,13,119,104,105,116,101,80,101,110,116,97,103,111,110,17,119,104,105,116,101,83,109,97,108,108,76,111,122,101,110,103,101,20,119,104,105,116,101,86,101,114,116,105,99,97,108,69,108,108,105,112,115,101,20,119,104,105,116,101,86,101,114,121,115,109,97,108,108,83,113,117,97,114,101,24,97,109,112,101,114,115,97,110,100,95,97,109,112,101,114,115,97,110,100,46,108,105,103,97,15,98,97,114,95,104,121,112,104,101,110,46,108,105,103,97,19,98,97,114,95,98,114,97,99,101,114,105,103,104,116,46,108,105,103,97,21,98,97,114,95,98,114,97,99,107,101,116,114,105,103,104,116,46,108,105,103,97,12,98,97,114,95,98,97,114,46,108,105,103,97,24,98,97,114,95,98,97,114,95,98,97,114,95,103,114,101,97,116,101,114,46,108,105,103,97,18,98,97,114,95,98,97,114,95,101,113,117,97,108,46,108,105,103,97,20,98,97,114,95,98,97,114,95,103,114,101,97,116,101,114,46,108,105,103,97,14,98,97,114,95,101,113,117,97,108,46,108,105,103,97,16,98,97,114,95,103,114,101,97,116,101,114,46,108,105,103,97,19,100,111,108,108,97,114,95,103,114,101,97,116,101,114,46,108,105,103,97,14,112,108,117,115,95,112,108,117,115,46,108,105,103,97,19,112,108,117,115,95,112,108,117,115,95,112,108,117,115,46,108,105,103,97,17,112,108,117,115,95,103,114,101,97,116,101,114,46,108,105,103,97,22,101,113,117,97,108,95,99,111,108,111,110,95,101,113,117,97,108,46,108,105,103,97,23,101,113,117,97,108,95,101,120,99,108,97,109,95,101,113,117,97,108,46,108,105,103,97,16,101,113,117,97,108,95,101,113,117,97,108,46,108,105,103,97,22,101,113,117,97,108,95,101,113,117,97,108,95,101,113,117,97,108,46,108,105,103,97,24,101,113,117,97,108,95,101,113,117,97,108,95,103,114,101,97,116,101,114,46,108,105,103,97,18,101,113,117,97,108,95,103,114,101,97,116,101,114,46,108,105,103,97,26,101,113,117,97,108,95,103,114,101,97,116,101,114,95,103,114,101,97,116,101,114,46,108,105,103,97,20,101,113,117,97,108,95,108,101,115,115,95,108,101,115,115,46,108,105,103,97,22,101,113,117,97,108,95,115,108,97,115,104,95,101,113,117,97,108,46,108,105,103,97,19,103,114,101,97,116,101,114,95,104,121,112,104,101,110,46,108,105,103,97,27,103,114,101,97,116,101,114,95,104,121,112,104,101,110,95,103,114,101,97,116,101,114,46,108,105,103,97,18,103,114,101,97,116,101,114,95,99,111,108,111,110,46,108,105,103,97,18,103,114,101,97,116,101,114,95,101,113,117,97,108,46,108,105,103,97,26,103,114,101,97,116,101,114,95,101,113,117,97,108,95,103,114,101,97,116,101,114,46,108,105,103,97,20,103,114,101,97,116,101,114,95,103,114,101,97,116,101,114,46,108,105,103,97,27,103,114,101,97,116,101,114,95,103,114,101,97,116,101,114,95,104,121,112,104,101,110,46,108,105,103,97,26,103,114,101,97,116,101,114,95,103,114,101,97,116,101,114,95,101,113,117,97,108,46,108,105,103,97,28,103,114,101,97,116,101,114,95,103,114,101,97,116,101,114,95,103,114,101,97,116,101,114,46,108,105,103,97,16,108,101,115,115,95,104,121,112,104,101,110,46,108,105,103,97,23,108,101,115,115,95,104,121,112,104,101,110,95,104,121,112,104,101,110,46,108,105,103,97,24,108,101,115,115,95,104,121,112,104,101,110,95,103,114,101,97,116,101,114,46,108,105,103,97,21,108,101,115,115,95,104,121,112,104,101,110,95,108,101,115,115,46,108,105,103,97,15,108,101,115,115,95,99,111,108,111,110,46,108,105,103,97,30,108,101,115,115,95,101,120,99,108,97,109,95,104,121,112,104,101,110,95,104,121,112,104,101,110,46,108,105,103,97,18,108,101,115,115,95,97,115,116,101,114,105,115,107,46,108,105,103,97,26,108,101,115,115,95,97,115,116,101,114,105,115,107,95,103,114,101,97,116,101,114,46,108,105,103,97,13,108,101,115,115,95,98,97,114,46,108,105,103,97,17,108,101,115,115,95,98,97,114,95,98,97,114,46,108,105,103,97,21,108,101,115,115,95,98,97,114,95,98,97,114,95,98,97,114,46,108,105,103,97,21,108,101,115,115,95,98,97,114,95,103,114,101,97,116,101,114,46,108,105,103,97,16,108,101,115,115,95,100,111,108,108,97,114,46,108,105,103,97,24,108,101,115,115,95,100,111,108,108,97,114,95,103,114,101,97,116,101,114,46,108,105,103,97,14,108,101,115,115,95,112,108,117,115,46,108,105,103,97,22,108,101,115,115,95,112,108,117,115,95,103,114,101,97,116,101,114,46,108,105,103,97,15,108,101,115,115,95,101,113,117,97,108,46,108,105,103,97,21,108,101,115,115,95,101,113,117,97,108,95,101,113,117,97,108,46,108,105,103,97,29,108,101,115,115,95,101,113,117,97,108,95,101,113,117,97,108,95,103,114,101,97,116,101,114,46,108,105,103,97,23,108,101,115,115,95,101,113,117,97,108,95,103,114,101,97,116,101,114,46,108,105,103,97,20,108,101,115,115,95,101,113,117,97,108,95,108,101,115,115,46,108,105,103,97,17,108,101,115,115,95,103,114,101,97,116,101,114,46,108,105,103,97,14,108,101,115,115,95,108,101,115,115,46,108,105,103,97,21,108,101,115,115,95,108,101,115,115,95,104,121,112,104,101,110,46,108,105,103,97,20,108,101,115,115,95,108,101,115,115,95,101,113,117,97,108,46,108,105,103,97,19,108,101,115,115,95,108,101,115,115,95,108,101,115,115,46,108,105,103,97,20,108,101,115,115,95,97,115,99,105,105,116,105,108,100,101,46,108,105,103,97,28,108,101,115,115,95,97,115,99,105,105,116,105,108,100,101,95,103,114,101,97,116,101,114,46,108,105,103,97,31,108,101,115,115,95,97,115,99,105,105,116,105,108,100,101,95,97,115,99,105,105,116,105,108,100,101,46,108,105,103,97,15,108,101,115,115,95,115,108,97,115,104,46,108,105,103,97,23,108,101,115,115,95,115,108,97,115,104,95,103,114,101,97,116,101,114,46,108,105,103,97,22,97,115,99,105,105,116,105,108,100,101,95,104,121,112,104,101,110,46,108,105,103,97,18,97,115,99,105,105,116,105,108,100,101,95,97,116,46,108,105,103,97,21,97,115,99,105,105,116,105,108,100,101,95,101,113,117,97,108,46,108,105,103,97,23,97,115,99,105,105,116,105,108,100,101,95,103,114,101,97,116,101,114,46,108,105,103,97,26,97,115,99,105,105,116,105,108,100,101,95,97,115,99,105,105,116,105,108,100,101,46,108,105,103,97,34,97,115,99,105,105,116,105,108,100,101,95,97,115,99,105,105,116,105,108,100,101,95,103,114,101,97,116,101,114,46,108,105,103,97,22,97,115,99,105,105,99,105,114,99,117,109,95,101,113,117,97,108,46,108,105,103,97,20,112,101,114,99,101,110,116,95,112,101,114,99,101,110,116,46,108,105,103,97,12,110,111,116,101,45,109,117,115,105,99,97,108,15,110,111,116,101,100,98,108,45,109,117,115,105,99,97,108,13,98,108,97,110,107,45,98,114,97,105,108,108,101,13,100,111,116,115,49,45,98,114,97,105,108,108,101,14,100,111,116,115,49,50,45,98,114,97,105,108,108,101,15,100,111,116,115,49,50,51,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,51,52,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,51,52,53,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,51,52,53,54,45,98,114,97,105,108,108,101,19,100,111,116,115,49,50,51,52,53,54,55,45,98,114,97,105,108,108,101,20,100,111,116,115,49,50,51,52,53,54,55,56,45,98,114,97,105,108,108,101,19,100,111,116,115,49,50,51,52,53,54,56,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,51,52,53,55,45,98,114,97,105,108,108,101,19,100,111,116,115,49,50,51,52,53,55,56,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,51,52,53,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,51,52,54,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,51,52,54,55,45,98,114,97,105,108,108,101,19,100,111,116,115,49,50,51,52,54,55,56,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,51,52,54,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,51,52,55,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,51,52,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,51,52,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,51,53,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,51,53,54,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,51,53,54,55,45,98,114,97,105,108,108,101,19,100,111,116,115,49,50,51,53,54,55,56,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,51,53,54,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,51,53,55,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,51,53,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,51,53,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,51,54,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,51,54,55,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,51,54,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,51,54,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,51,55,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,51,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,51,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,50,52,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,52,53,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,52,53,54,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,52,53,54,55,45,98,114,97,105,108,108,101,19,100,111,116,115,49,50,52,53,54,55,56,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,52,53,54,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,52,53,55,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,52,53,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,52,53,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,52,54,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,52,54,55,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,52,54,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,52,54,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,52,55,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,52,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,52,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,50,53,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,53,54,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,53,54,55,45,98,114,97,105,108,108,101,18,100,111,116,115,49,50,53,54,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,53,54,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,53,55,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,53,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,53,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,50,54,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,54,55,45,98,114,97,105,108,108,101,17,100,111,116,115,49,50,54,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,54,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,50,55,45,98,114,97,105,108,108,101,16,100,111,116,115,49,50,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,50,56,45,98,114,97,105,108,108,101,14,100,111,116,115,49,51,45,98,114,97,105,108,108,101,15,100,111,116,115,49,51,52,45,98,114,97,105,108,108,101,16,100,111,116,115,49,51,52,53,45,98,114,97,105,108,108,101,17,100,111,116,115,49,51,52,53,54,45,98,114,97,105,108,108,101,18,100,111,116,115,49,51,52,53,54,55,45,98,114,97,105,108,108,101,19,100,111,116,115,49,51,52,53,54,55,56,45,98,114,97,105,108,108,101,18,100,111,116,115,49,51,52,53,54,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,51,52,53,55,45,98,114,97,105,108,108,101,18,100,111,116,115,49,51,52,53,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,51,52,53,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,51,52,54,45,98,114,97,105,108,108,101,17,100,111,116,115,49,51,52,54,55,45,98,114,97,105,108,108,101,18,100,111,116,115,49,51,52,54,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,51,52,54,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,51,52,55,45,98,114,97,105,108,108,101,17,100,111,116,115,49,51,52,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,51,52,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,51,53,45,98,114,97,105,108,108,101,16,100,111,116,115,49,51,53,54,45,98,114,97,105,108,108,101,17,100,111,116,115,49,51,53,54,55,45,98,114,97,105,108,108,101,18,100,111,116,115,49,51,53,54,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,51,53,54,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,51,53,55,45,98,114,97,105,108,108,101,17,100,111,116,115,49,51,53,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,51,53,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,51,54,45,98,114,97,105,108,108,101,16,100,111,116,115,49,51,54,55,45,98,114,97,105,108,108,101,17,100,111,116,115,49,51,54,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,51,54,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,51,55,45,98,114,97,105,108,108,101,16,100,111,116,115,49,51,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,51,56,45,98,114,97,105,108,108,101,14,100,111,116,115,49,52,45,98,114,97,105,108,108,101,15,100,111,116,115,49,52,53,45,98,114,97,105,108,108,101,16,100,111,116,115,49,52,53,54,45,98,114,97,105,108,108,101,17,100,111,116,115,49,52,53,54,55,45,98,114,97,105,108,108,101,18,100,111,116,115,49,52,53,54,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,49,52,53,54,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,52,53,55,45,98,114,97,105,108,108,101,17,100,111,116,115,49,52,53,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,52,53,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,52,54,45,98,114,97,105,108,108,101,16,100,111,116,115,49,52,54,55,45,98,114,97,105,108,108,101,17,100,111,116,115,49,52,54,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,52,54,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,52,55,45,98,114,97,105,108,108,101,16,100,111,116,115,49,52,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,52,56,45,98,114,97,105,108,108,101,14,100,111,116,115,49,53,45,98,114,97,105,108,108,101,15,100,111,116,115,49,53,54,45,98,114,97,105,108,108,101,16,100,111,116,115,49,53,54,55,45,98,114,97,105,108,108,101,17,100,111,116,115,49,53,54,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,49,53,54,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,53,55,45,98,114,97,105,108,108,101,16,100,111,116,115,49,53,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,53,56,45,98,114,97,105,108,108,101,14,100,111,116,115,49,54,45,98,114,97,105,108,108,101,15,100,111,116,115,49,54,55,45,98,114,97,105,108,108,101,16,100,111,116,115,49,54,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,49,54,56,45,98,114,97,105,108,108,101,14,100,111,116,115,49,55,45,98,114,97,105,108,108,101,15,100,111,116,115,49,55,56,45,98,114,97,105,108,108,101,14,100,111,116,115,49,56,45,98,114,97,105,108,108,101,13,100,111,116,115,50,45,98,114,97,105,108,108,101,14,100,111,116,115,50,51,45,98,114,97,105,108,108,101,15,100,111,116,115,50,51,52,45,98,114,97,105,108,108,101,16,100,111,116,115,50,51,52,53,45,98,114,97,105,108,108,101,17,100,111,116,115,50,51,52,53,54,45,98,114,97,105,108,108,101,18,100,111,116,115,50,51,52,53,54,55,45,98,114,97,105,108,108,101,19,100,111,116,115,50,51,52,53,54,55,56,45,98,114,97,105,108,108,101,18,100,111,116,115,50,51,52,53,54,56,45,98,114,97,105,108,108,101,17,100,111,116,115,50,51,52,53,55,45,98,114,97,105,108,108,101,18,100,111,116,115,50,51,52,53,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,50,51,52,53,56,45,98,114,97,105,108,108,101,16,100,111,116,115,50,51,52,54,45,98,114,97,105,108,108,101,17,100,111,116,115,50,51,52,54,55,45,98,114,97,105,108,108,101,18,100,111,116,115,50,51,52,54,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,50,51,52,54,56,45,98,114,97,105,108,108,101,16,100,111,116,115,50,51,52,55,45,98,114,97,105,108,108,101,17,100,111,116,115,50,51,52,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,50,51,52,56,45,98,114,97,105,108,108,101,15,100,111,116,115,50,51,53,45,98,114,97,105,108,108,101,16,100,111,116,115,50,51,53,54,45,98,114,97,105,108,108,101,17,100,111,116,115,50,51,53,54,55,45,98,114,97,105,108,108,101,18,100,111,116,115,50,51,53,54,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,50,51,53,54,56,45,98,114,97,105,108,108,101,16,100,111,116,115,50,51,53,55,45,98,114,97,105,108,108,101,17,100,111,116,115,50,51,53,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,50,51,53,56,45,98,114,97,105,108,108,101,15,100,111,116,115,50,51,54,45,98,114,97,105,108,108,101,16,100,111,116,115,50,51,54,55,45,98,114,97,105,108,108,101,17,100,111,116,115,50,51,54,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,50,51,54,56,45,98,114,97,105,108,108,101,15,100,111,116,115,50,51,55,45,98,114,97,105,108,108,101,16,100,111,116,115,50,51,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,50,51,56,45,98,114,97,105,108,108,101,14,100,111,116,115,50,52,45,98,114,97,105,108,108,101,15,100,111,116,115,50,52,53,45,98,114,97,105,108,108,101,16,100,111,116,115,50,52,53,54,45,98,114,97,105,108,108,101,17,100,111,116,115,50,52,53,54,55,45,98,114,97,105,108,108,101,18,100,111,116,115,50,52,53,54,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,50,52,53,54,56,45,98,114,97,105,108,108,101,16,100,111,116,115,50,52,53,55,45,98,114,97,105,108,108,101,17,100,111,116,115,50,52,53,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,50,52,53,56,45,98,114,97,105,108,108,101,15,100,111,116,115,50,52,54,45,98,114,97,105,108,108,101,16,100,111,116,115,50,52,54,55,45,98,114,97,105,108,108,101,17,100,111,116,115,50,52,54,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,50,52,54,56,45,98,114,97,105,108,108,101,15,100,111,116,115,50,52,55,45,98,114,97,105,108,108,101,16,100,111,116,115,50,52,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,50,52,56,45,98,114,97,105,108,108,101,14,100,111,116,115,50,53,45,98,114,97,105,108,108,101,15,100,111,116,115,50,53,54,45,98,114,97,105,108,108,101,16,100,111,116,115,50,53,54,55,45,98,114,97,105,108,108,101,17,100,111,116,115,50,53,54,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,50,53,54,56,45,98,114,97,105,108,108,101,15,100,111,116,115,50,53,55,45,98,114,97,105,108,108,101,16,100,111,116,115,50,53,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,50,53,56,45,98,114,97,105,108,108,101,14,100,111,116,115,50,54,45,98,114,97,105,108,108,101,15,100,111,116,115,50,54,55,45,98,114,97,105,108,108,101,16,100,111,116,115,50,54,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,50,54,56,45,98,114,97,105,108,108,101,14,100,111,116,115,50,55,45,98,114,97,105,108,108,101,15,100,111,116,115,50,55,56,45,98,114,97,105,108,108,101,14,100,111,116,115,50,56,45,98,114,97,105,108,108,101,13,100,111,116,115,51,45,98,114,97,105,108,108,101,14,100,111,116,115,51,52,45,98,114,97,105,108,108,101,15,100,111,116,115,51,52,53,45,98,114,97,105,108,108,101,16,100,111,116,115,51,52,53,54,45,98,114,97,105,108,108,101,17,100,111,116,115,51,52,53,54,55,45,98,114,97,105,108,108,101,18,100,111,116,115,51,52,53,54,55,56,45,98,114,97,105,108,108,101,17,100,111,116,115,51,52,53,54,56,45,98,114,97,105,108,108,101,16,100,111,116,115,51,52,53,55,45,98,114,97,105,108,108,101,17,100,111,116,115,51,52,53,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,51,52,53,56,45,98,114,97,105,108,108,101,15,100,111,116,115,51,52,54,45,98,114,97,105,108,108,101,16,100,111,116,115,51,52,54,55,45,98,114,97,105,108,108,101,17,100,111,116,115,51,52,54,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,51,52,54,56,45,98,114,97,105,108,108,101,15,100,111,116,115,51,52,55,45,98,114,97,105,108,108,101,16,100,111,116,115,51,52,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,51,52,56,45,98,114,97,105,108,108,101,14,100,111,116,115,51,53,45,98,114,97,105,108,108,101,15,100,111,116,115,51,53,54,45,98,114,97,105,108,108,101,16,100,111,116,115,51,53,54,55,45,98,114,97,105,108,108,101,17,100,111,116,115,51,53,54,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,51,53,54,56,45,98,114,97,105,108,108,101,15,100,111,116,115,51,53,55,45,98,114,97,105,108,108,101,16,100,111,116,115,51,53,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,51,53,56,45,98,114,97,105,108,108,101,14,100,111,116,115,51,54,45,98,114,97,105,108,108,101,15,100,111,116,115,51,54,55,45,98,114,97,105,108,108,101,16,100,111,116,115,51,54,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,51,54,56,45,98,114,97,105,108,108,101,14,100,111,116,115,51,55,45,98,114,97,105,108,108,101,15,100,111,116,115,51,55,56,45,98,114,97,105,108,108,101,14,100,111,116,115,51,56,45,98,114,97,105,108,108,101,13,100,111,116,115,52,45,98,114,97,105,108,108,101,14,100,111,116,115,52,53,45,98,114,97,105,108,108,101,15,100,111,116,115,52,53,54,45,98,114,97,105,108,108,101,16,100,111,116,115,52,53,54,55,45,98,114,97,105,108,108,101,17,100,111,116,115,52,53,54,55,56,45,98,114,97,105,108,108,101,16,100,111,116,115,52,53,54,56,45,98,114,97,105,108,108,101,15,100,111,116,115,52,53,55,45,98,114,97,105,108,108,101,16,100,111,116,115,52,53,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,52,53,56,45,98,114,97,105,108,108,101,14,100,111,116,115,52,54,45,98,114,97,105,108,108,101,15,100,111,116,115,52,54,55,45,98,114,97,105,108,108,101,16,100,111,116,115,52,54,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,52,54,56,45,98,114,97,105,108,108,101,14,100,111,116,115,52,55,45,98,114,97,105,108,108,101,15,100,111,116,115,52,55,56,45,98,114,97,105,108,108,101,14,100,111,116,115,52,56,45,98,114,97,105,108,108,101,13,100,111,116,115,53,45,98,114,97,105,108,108,101,14,100,111,116,115,53,54,45,98,114,97,105,108,108,101,15,100,111,116,115,53,54,55,45,98,114,97,105,108,108,101,16,100,111,116,115,53,54,55,56,45,98,114,97,105,108,108,101,15,100,111,116,115,53,54,56,45,98,114,97,105,108,108,101,14,100,111,116,115,53,55,45,98,114,97,105,108,108,101,15,100,111,116,115,53,55,56,45,98,114,97,105,108,108,101,14,100,111,116,115,53,56,45,98,114,97,105,108,108,101,13,100,111,116,115,54,45,98,114,97,105,108,108,101,14,100,111,116,115,54,55,45,98,114,97,105,108,108,101,15,100,111,116,115,54,55,56,45,98,114,97,105,108,108,101,14,100,111,116,115,54,56,45,98,114,97,105,108,108,101,13,100,111,116,115,55,45,98,114,97,105,108,108,101,14,100,111,116,115,55,56,45,98,114,97,105,108,108,101,13,100,111,116,115,56,45,98,114,97,105,108,108,101,13,110,117,109,101,114,97,108,45,103,114,101,101,107,18,108,111,119,101,114,110,117,109,101,114,97,108,45,103,114,101,101,107,13,97,112,111,115,116,114,111,112,104,101,109,111,100,14,99,111,109,109,97,116,117,114,110,101,100,109,111,100,16,102,105,114,115,116,116,111,110,101,99,104,105,110,101,115,101,12,100,105,101,114,101,115,105,115,99,111,109,98,13,100,111,116,97,99,99,101,110,116,99,111,109,98,9,103,114,97,118,101,99,111,109,98,9,97,99,117,116,101,99,111,109,98,16,104,117,110,103,97,114,117,109,108,97,117,116,99,111,109,98,14,99,105,114,99,117,109,102,108,101,120,99,111,109,98,9,99,97,114,111,110,99,111,109,98,9,98,114,101,118,101,99,111,109,98,8,114,105,110,103,99,111,109,98,9,116,105,108,100,101,99,111,109,98,10,109,97,99,114,111,110,99,111,109,98,13,104,111,111,107,97,98,111,118,101,99,111,109,98,20,99,111,109,109,97,116,117,114,110,101,100,97,98,111,118,101,99,111,109,98,8,104,111,114,110,99,111,109,98,12,100,111,116,98,101,108,111,119,99,111,109,98,15,99,111,109,109,97,97,99,99,101,110,116,99,111,109,98,11,99,101,100,105,108,108,97,99,111,109,98,10,111,103,111,110,101,107,99,111,109,98,13,103,114,97,118,101,116,111,110,101,99,111,109,98,13,97,99,117,116,101,116,111,110,101,99,111,109,98,17,100,105,101,114,101,115,105,115,99,111,109,98,46,99,97,115,101,18,100,111,116,97,99,99,101,110,116,99,111,109,98,46,99,97,115,101,14,103,114,97,118,101,99,111,109,98,46,99,97,115,101,14,97,99,117,116,101,99,111,109,98,46,99,97,115,101,21,104,117,110,103,97,114,117,109,108,97,117,116,99,111,109,98,46,99,97,115,101,19,99,105,114,99,117,109,102,108,101,120,99,111,109,98,46,99,97,115,101,14,99,97,114,111,110,99,111,109,98,46,99,97,115,101,14,98,114,101,118,101,99,111,109,98,46,99,97,115,101,13,114,105,110,103,99,111,109,98,46,99,97,115,101,14,116,105,108,100,101,99,111,109,98,46,99,97,115,101,15,109,97,99,114,111,110,99,111,109,98,46,99,97,115,101,18,104,111,111,107,97,98,111,118,101,99,111,109,98,46,99,97,115,101,13,104,111,114,110,99,111,109,98,46,99,97,115,101,17,97,99,117,116,101,99,111,109,98,46,108,111,99,108,80,76,75,22,97,99,117,116,101,99,111,109,98,46,99,97,115,101,46,108,111,99,108,80,76,75,15,112,101,114,105,115,112,111,109,101,110,105,99,111,109,98,5,116,111,110,111,115,10,116,111,110,111,115,46,99,97,115,101,13,100,105,101,114,101,115,105,115,116,111,110,111,115,12,98,114,101,118,101,99,111,109,98,45,99,121,17,98,114,101,118,101,99,111,109,98,45,99,121,46,99,97,115,101,7,117,110,105,48,48,48,57,3,76,73,71,16,98,97,104,116,46,66,82,65,67,75,69,84,46,54,48,48,18,100,111,108,108,97,114,46,66,82,65,67,75,69,84,46,54,48,48,31,100,111,108,108,97,114,95,103,114,101,97,116,101,114,46,108,105,103,97,46,66,82,65,67,75,69,84,46,54,48,48,28,108,101,115,115,95,100,111,108,108,97,114,46,108,105,103,97,46,66,82,65,67,75,69,84,46,54,48,48,36,108,101,115,115,95,100,111,108,108,97,114,95,103,114,101,97,116,101,114,46,108,105,103,97,46,66,82,65,67,75,69,84,46,54,48,48,7,117,110,105,49,69,65,69,7,117,110,105,49,69,66,54,7,117,110,105,49,69,66,48,7,117,110,105,49,69,66,50,7,117,110,105,49,69,66,52,7,117,110,105,48,49,67,68,7,117,110,105,49,69,65,52,7,117,110,105,49,69,65,67,7,117,110,105,49,69,65,54,7,117,110,105,49,69,65,56,7,117,110,105,49,69,65,65,7,117,110,105,49,69,65,48,7,117,110,105,49,69,65,50,7,117,110,105,49,69,66,69,7,117,110,105,49,69,67,54,7,117,110,105,49,69,67,48,7,117,110,105,49,69,67,50,7,117,110,105,49,69,67,52,7,117,110,105,49,69,66,56,7,117,110,105,49,69,66,65,7,117,110,105,48,49,57,48,7,117,110,105,48,49,65,57,7,117,110,105,49,69,66,67,7,117,110,105,48,49,66,55,7,117,110,105,48,49,50,50,7,117,110,105,48,50,49,69,7,117,110,105,49,69,67,65,7,117,110,105,49,69,67,56,7,117,110,105,48,49,51,54,7,117,110,105,48,49,51,66,7,117,110,105,48,49,52,53,7,117,110,105,48,49,57,68,7,117,110,105,49,69,68,48,7,117,110,105,49,69,68,56,7,117,110,105,49,69,68,50,7,117,110,105,49,69,68,52,7,117,110,105,49,69,68,54,7,117,110,105,49,69,67,67,7,117,110,105,49,69,67,69,7,117,110,105,49,69,68,65,7,117,110,105,49,69,69,50,7,117,110,105,49,69,68,67,7,117,110,105,49,69,68,69,7,117,110,105,49,69,69,48,7,117,110,105,48,49,69,65,7,117,110,105,48,49,56,54,7,117,110,105,48,49,53,54,7,117,110,105,48,50,49,56,7,117,110,105,49,69,57,69,7,117,110,105,48,49,56,70,7,117,110,105,48,49,54,50,7,117,110,105,48,50,49,65,7,117,110,105,49,69,69,52,7,117,110,105,49,69,69,54,7,117,110,105,49,69,69,56,7,117,110,105,49,69,70,48,7,117,110,105,49,69,69,65,7,117,110,105,49,69,69,67,7,117,110,105,49,69,69,69,7,117,110,105,48,50,52,53,7,117,110,105,49,69,70,52,7,117,110,105,49,69,70,54,7,117,110,105,48,50,51,50,7,117,110,105,49,69,70,56,7,117,110,105,48,50,54,65,7,117,110,105,49,69,65,70,7,117,110,105,49,69,66,55,7,117,110,105,49,69,66,49,7,117,110,105,49,69,66,51,7,117,110,105,49,69,66,53,7,117,110,105,48,49,67,69,7,117,110,105,49,69,65,53,7,117,110,105,49,69,65,68,7,117,110,105,49,69,65,55,7,117,110,105,49,69,65,57,7,117,110,105,49,69,65,66,7,117,110,105,49,69,65,49,7,117,110,105,49,69,65,51,7,117,110,105,49,69,66,70,7,117,110,105,49,69,67,55,7,117,110,105,49,69,67,49,7,117,110,105,49,69,67,51,7,117,110,105,49,69,67,53,7,117,110,105,49,69,66,57,7,117,110,105,49,69,66,66,7,117,110,105,48,50,53,66,7,117,110,105,48,50,56,51,7,117,110,105,49,69,66,68,7,117,110,105,48,50,53,57,7,117,110,105,48,50,57,50,7,117,110,105,48,49,50,51,7,117,110,105,48,50,49,70,7,117,110,105,49,69,67,66,7,117,110,105,49,69,67,57,7,117,110,105,48,50,51,55,7,117,110,105,48,49,51,55,7,117,110,105,48,49,51,67,7,117,110,105,48,49,52,54,7,117,110,105,48,50,55,50,7,117,110,105,49,69,68,49,7,117,110,105,49,69,68,57,7,117,110,105,49,69,68,51,7,117,110,105,49,69,68,53,7,117,110,105,49,69,68,55,7,117,110,105,49,69,67,68,7,117,110,105,49,69,67,70,7,117,110,105,49,69,68,66,7,117,110,105,49,69,69,51,7,117,110,105,49,69,68,68,7,117,110,105,49,69,68,70,7,117,110,105,49,69,69,49,7,117,110,105,48,49,69,66,7,117,110,105,48,50,53,52,7,117,110,105,48,49,53,55,7,117,110,105,48,50,49,57,7,117,110,105,48,49,54,51,7,117,110,105,48,50,49,66,7,117,110,105,48,50,65,55,7,117,110,105,49,69,69,53,7,117,110,105,49,69,69,55,7,117,110,105,49,69,69,57,7,117,110,105,49,69,70,49,7,117,110,105,49,69,69,66,7,117,110,105,49,69,69,68,7,117,110,105,49,69,69,70,7,117,110,105,48,50,56,67,7,117,110,105,49,69,70,53,7,117,110,105,49,69,70,55,7,117,110,105,48,50,51,51,7,117,110,105,49,69,70,57,7,117,110,105,50,48,55,70,7,117,110,105,48,52,49,48,7,117,110,105,48,52,49,49,7,117,110,105,48,52,49,50,7,117,110,105,48,52,49,51,7,117,110,105,48,52,48,51,7,117,110,105,48,52,57,48,7,117,110,105,48,52,49,52,7,117,110,105,48,52,49,53,7,117,110,105,48,52,48,48,7,117,110,105,48,52,48,49,7,117,110,105,48,52,49,54,7,117,110,105,48,52,49,55,7,117,110,105,48,52,49,56,7,117,110,105,48,52,49,57,7,117,110,105,48,52,48,68,7,117,110,105,48,52,49,65,7,117,110,105,48,52,48,67,7,117,110,105,48,52,49,66,7,117,110,105,48,52,49,67,7,117,110,105,48,52,49,68,7,117,110,105,48,52,49,69,7,117,110,105,48,52,49,70,7,117,110,105,48,52,50,48,7,117,110,105,48,52,50,49,7,117,110,105,48,52,50,50,7,117,110,105,48,52,50,51,7,117,110,105,48,52,48,69,7,117,110,105,48,52,50,52,7,117,110,105,48,52,50,53,7,117,110,105,48,52,50,55,7,117,110,105,48,52,50,54,7,117,110,105,48,52,50,56,7,117,110,105,48,52,50,57,7,117,110,105,48,52,48,70,7,117,110,105,48,52,50,67,7,117,110,105,48,52,50,65,7,117,110,105,48,52,50,66,7,117,110,105,48,52,48,57,7,117,110,105,48,52,48,65,7,117,110,105,48,52,48,53,7,117,110,105,48,52,48,52,7,117,110,105,48,52,50,68,7,117,110,105,48,52,48,54,7,117,110,105,48,52,48,55,7,117,110,105,48,52,48,56,7,117,110,105,48,52,48,66,7,117,110,105,48,52,50,69,7,117,110,105,48,52,50,70,7,117,110,105,48,52,48,50,7,117,110,105,48,52,57,50,7,117,110,105,48,52,57,54,7,117,110,105,48,52,57,65,7,117,110,105,48,52,65,50,7,117,110,105,48,52,65,69,7,117,110,105,48,52,66,48,7,117,110,105,48,52,66,50,7,117,110,105,48,52,66,54,7,117,110,105,48,52,66,65,7,117,110,105,48,52,67,48,7,117,110,105,48,52,68,56,7,117,110,105,48,52,69,50,7,117,110,105,48,52,69,56,7,117,110,105,48,52,69,69,15,117,110,105,48,52,49,52,46,108,111,99,108,66,71,82,15,117,110,105,48,52,49,66,46,108,111,99,108,66,71,82,15,117,110,105,48,52,50,52,46,108,111,99,108,66,71,82,7,117,110,105,48,52,51,48,7,117,110,105,48,52,51,49,7,117,110,105,48,52,51,50,7,117,110,105,48,52,51,51,7,117,110,105,48,52,53,51,7,117,110,105,48,52,57,49,7,117,110,105,48,52,51,52,7,117,110,105,48,52,51,53,7,117,110,105,48,52,53,48,7,117,110,105,48,52,53,49,7,117,110,105,48,52,51,54,7,117,110,105,48,52,51,55,7,117,110,105,48,52,51,56,7,117,110,105,48,52,51,57,7,117,110,105,48,52,53,68,7,117,110,105,48,52,51,65,7,117,110,105,48,52,53,67,7,117,110,105,48,52,51,66,7,117,110,105,48,52,51,67,7,117,110,105,48,52,51,68,7,117,110,105,48,52,51,69,7,117,110,105,48,52,51,70,7,117,110,105,48,52,52,48,7,117,110,105,48,52,52,49,7,117,110,105,48,52,52,50,7,117,110,105,48,52,52,51,7,117,110,105,48,52,53,69,7,117,110,105,48,52,52,52,7,117,110,105,48,52,52,53,7,117,110,105,48,52,52,55,7,117,110,105,48,52,52,54,7,117,110,105,48,52,52,56,7,117,110,105,48,52,52,57,7,117,110,105,48,52,53,70,7,117,110,105,48,52,52,67,7,117,110,105,48,52,52,65,7,117,110,105,48,52,52,66,7,117,110,105,48,52,53,57,7,117,110,105,48,52,53,65,7,117,110,105,48,52,53,53,7,117,110,105,48,52,53,52,7,117,110,105,48,52,52,68,7,117,110,105,48,52,53,54,7,117,110,105,48,52,53,55,7,117,110,105,48,52,53,56,7,117,110,105,48,52,53,66,7,117,110,105,48,52,52,69,7,117,110,105,48,52,52,70,7,117,110,105,48,52,53,50,7,117,110,105,48,52,57,51,7,117,110,105,48,52,57,55,7,117,110,105,48,52,57,66,7,117,110,105,48,52,65,51,7,117,110,105,48,52,65,70,7,117,110,105,48,52,66,49,7,117,110,105,48,52,66,51,7,117,110,105,48,52,66,55,7,117,110,105,48,52,66,66,7,117,110,105,48,52,67,70,7,117,110,105,48,52,68,57,7,117,110,105,48,52,69,51,7,117,110,105,48,52,69,57,7,117,110,105,48,52,69,70,15,117,110,105,48,52,51,50,46,108,111,99,108,66,71,82,15,117,110,105,48,52,51,51,46,108,111,99,108,66,71,82,15,117,110,105,48,52,51,52,46,108,111,99,108,66,71,82,15,117,110,105,48,52,51,54,46,108,111,99,108,66,71,82,15,117,110,105,48,52,51,55,46,108,111,99,108,66,71,82,15,117,110,105,48,52,51,56,46,108,111,99,108,66,71,82,15,117,110,105,48,52,51,57,46,108,111,99,108,66,71,82,15,117,110,105,48,52,53,68,46,108,111,99,108,66,71,82,15,117,110,105,48,52,51,65,46,108,111,99,108,66,71,82,15,117,110,105,48,52,51,66,46,108,111,99,108,66,71,82,15,117,110,105,48,52,51,70,46,108,111,99,108,66,71,82,15,117,110,105,48,52,52,50,46,108,111,99,108,66,71,82,15,117,110,105,48,52,52,54,46,108,111,99,108,66,71,82,15,117,110,105,48,52,52,56,46,108,111,99,108,66,71,82,15,117,110,105,48,52,52,57,46,108,111,99,108,66,71,82,15,117,110,105,48,52,52,67,46,108,111,99,108,66,71,82,15,117,110,105,48,52,52,65,46,108,111,99,108,66,71,82,15,117,110,105,48,52,52,69,46,108,111,99,108,66,71,82,15,117,110,105,48,52,51,49,46,108,111,99,108,83,82,66,7,117,110,105,48,51,57,52,7,117,110,105,48,51,65,57,7,117,110,105,48,51,67,70,7,117,110,105,48,51,66,67,7,117,110,105,48,51,67,50,7,117,110,105,48,51,68,55,7,117,110,105,50,48,56,48,7,117,110,105,50,48,56,49,7,117,110,105,50,48,56,50,7,117,110,105,50,48,56,51,7,117,110,105,50,48,56,52,7,117,110,105,50,48,56,53,7,117,110,105,50,48,56,54,7,117,110,105,50,48,56,55,7,117,110,105,50,48,56,56,7,117,110,105,50,48,56,57,7,117,110,105,50,48,55,48,7,117,110,105,48,48,66,57,7,117,110,105,48,48,66,50,7,117,110,105,48,48,66,51,7,117,110,105,50,48,55,52,7,117,110,105,50,48,55,53,7,117,110,105,50,48,55,54,7,117,110,105,50,48,55,55,7,117,110,105,50,48,55,56,7,117,110,105,50,48,55,57,9,101,120,99,108,97,109,100,98,108,7,117,110,105,50,48,51,69,7,117,110,105,50,55,54,69,7,117,110,105,50,55,54,70,7,117,110,105,50,55,54,67,7,117,110,105,50,55,54,68,7,117,110,105,48,48,65,68,7,117,110,105,50,48,49,53,7,117,110,105,50,48,49,48,7,117,110,105,50,48,49,49,20,117,110,105,65,55,55,52,65,55,55,52,65,55,55,52,46,108,105,103,97,24,117,110,105,65,55,55,52,65,55,55,52,65,55,55,52,65,55,55,52,46,108,105,103,97,7,117,110,105,48,51,55,69,7,117,110,105,50,48,48,56,7,117,110,105,48,48,65,48,7,117,110,105,50,48,50,56,7,117,110,105,48,69,51,70,7,117,110,105,50,48,66,53,13,99,111,108,111,110,109,111,110,101,116,97,114,121,4,69,117,114,111,7,117,110,105,50,48,65,48,7,117,110,105,50,48,66,50,7,117,110,105,50,48,66,52,7,117,110,105,50,48,65,68,7,117,110,105,50,48,66,69,7,117,110,105,50,48,66,65,7,117,110,105,50,48,66,67,7,117,110,105,50,48,65,54,7,117,110,105,50,48,66,49,7,117,110,105,50,48,66,68,7,117,110,105,50,48,65,56,7,117,110,105,50,48,66,57,7,117,110,105,50,48,65,65,7,117,110,105,50,48,66,56,7,117,110,105,50,48,65,69,7,117,110,105,50,48,65,57,7,117,110,105,50,50,49,57,7,117,110,105,50,50,49,53,7,117,110,105,50,51,65,70,13,114,101,118,108,111,103,105,99,97,108,110,111,116,7,117,110,105,50,50,54,50,7,117,110,105,50,49,50,54,7,117,110,105,50,50,48,54,7,117,110,105,48,48,66,53,7,117,110,105,50,50,54,51,7,117,110,105,50,65,50,70,7,97,114,114,111,119,117,112,10,97,114,114,111,119,114,105,103,104,116,9,97,114,114,111,119,100,111,119,110,9,97,114,114,111,119,108,101,102,116,9,97,114,114,111,119,98,111,116,104,9,97,114,114,111,119,117,112,100,110,12,97,114,114,111,119,117,112,100,110,98,115,101,7,117,110,105,50,49,69,49,7,117,110,105,50,49,69,51,7,117,110,105,50,53,56,49,7,117,110,105,50,53,56,50,7,117,110,105,50,53,56,51,7,100,110,98,108,111,99,107,7,117,110,105,50,53,56,53,7,117,110,105,50,53,56,54,7,117,110,105,50,53,56,55,5,98,108,111,99,107,7,117,112,98,108,111,99,107,7,117,110,105,50,53,57,52,7,117,110,105,50,53,56,70,7,117,110,105,50,53,56,69,7,117,110,105,50,53,56,68,7,108,102,98,108,111,99,107,7,117,110,105,50,53,56,66,7,117,110,105,50,53,56,65,7,117,110,105,50,53,56,57,7,114,116,98,108,111,99,107,7,117,110,105,50,53,57,53,7,117,110,105,50,53,57,54,7,117,110,105,50,53,57,55,7,117,110,105,50,53,57,56,7,117,110,105,50,53,57,57,7,117,110,105,50,53,57,65,7,117,110,105,50,53,57,66,7,117,110,105,50,53,57,67,7,117,110,105,50,53,57,68,7,117,110,105,50,53,57,69,7,117,110,105,50,53,57,70,7,108,116,115,104,97,100,101,5,115,104,97,100,101,7,100,107,115,104,97,100,101,7,117,110,105,50,53,67,70,6,99,105,114,99,108,101,7,117,110,105,50,53,69,70,7,117,110,105,50,53,68,48,7,117,110,105,50,53,68,49,7,117,110,105,50,53,68,50,7,117,110,105,50,53,68,51,7,117,110,105,50,53,68,54,7,117,110,105,50,53,68,55,7,117,110,105,50,53,68,52,7,117,110,105,50,53,68,53,7,117,110,105,50,53,70,52,7,117,110,105,50,53,70,53,7,117,110,105,50,53,70,54,7,117,110,105,50,53,70,55,7,117,110,105,50,53,67,68,7,117,110,105,50,53,67,67,7,117,110,105,50,53,67,57,7,117,110,105,50,53,67,69,10,111,112,101,110,98,117,108,108,101,116,9,105,110,118,98,117,108,108,101,116,9,105,110,118,99,105,114,99,108,101,7,117,110,105,50,53,68,65,7,117,110,105,50,53,68,66,7,117,110,105,50,53,69,48,7,117,110,105,50,53,69,49,7,117,110,105,50,53,68,67,7,117,110,105,50,53,68,68,7,117,110,105,50,53,68,69,7,117,110,105,50,53,68,70,7,117,110,105,50,53,67,54,7,117,110,105,50,53,67,55,7,117,110,105,50,66,49,54,7,117,110,105,50,66,49,55,7,117,110,105,50,66,49,56,7,117,110,105,50,66,49,57,7,117,110,105,50,53,67,56,7,117,110,105,50,53,66,48,7,117,110,105,50,53,66,49,7,117,110,105,50,53,65,69,10,102,105,108,108,101,100,114,101,99,116,7,117,110,105,50,53,65,68,7,117,110,105,50,53,65,70,9,102,105,108,108,101,100,98,111,120,7,117,110,105,50,53,65,49,7,117,110,105,50,53,65,50,7,117,110,105,50,53,65,51,7,117,110,105,50,66,49,65,7,117,110,105,50,53,65,52,7,117,110,105,50,53,65,53,7,117,110,105,50,53,65,54,7,117,110,105,50,53,65,55,7,117,110,105,50,53,65,56,7,117,110,105,50,53,65,57,7,117,110,105,50,53,65,65,7,117,110,105,50,53,65,66,7,117,110,105,50,53,69,55,7,117,110,105,50,53,69,56,7,117,110,105,50,53,69,57,7,117,110,105,50,53,69,65,7,117,110,105,50,53,69,66,7,117,110,105,50,53,70,48,7,117,110,105,50,53,70,49,7,117,110,105,50,53,70,50,7,117,110,105,50,53,70,51,7,117,110,105,50,53,70,66,7,117,110,105,50,53,70,67,7,117,110,105,50,53,70,68,7,117,110,105,50,53,70,69,7,116,114,105,97,103,117,112,7,117,110,105,50,53,66,54,7,116,114,105,97,103,100,110,7,117,110,105,50,53,67,48,7,117,110,105,50,53,66,51,7,117,110,105,50,53,66,55,7,117,110,105,50,53,66,68,7,117,110,105,50,53,67,49,7,117,110,105,50,53,69,67,7,117,110,105,50,53,69,68,7,117,110,105,50,53,69,69,7,116,114,105,97,103,114,116,7,116,114,105,97,103,108,102,7,117,110,105,50,53,66,66,7,117,110,105,50,53,67,53,7,117,110,105,50,53,66,52,7,117,110,105,50,53,66,56,7,117,110,105,50,53,66,69,7,117,110,105,50,53,67,50,7,117,110,105,50,53,66,53,7,117,110,105,50,53,66,57,7,117,110,105,50,53,66,70,7,117,110,105,50,53,67,51,7,117,110,105,50,53,69,53,7,117,110,105,50,53,69,50,7,117,110,105,50,53,69,51,7,117,110,105,50,53,69,52,7,117,110,105,50,53,70,57,7,117,110,105,50,53,70,70,7,117,110,105,50,53,70,65,7,117,110,105,50,53,70,56,7,117,110,105,50,53,54,54,7,117,110,105,50,53,53,55,7,117,110,105,50,53,53,52,7,117,110,105,50,53,53,48,7,117,110,105,50,53,54,57,7,117,110,105,50,53,53,68,7,117,110,105,50,53,53,65,7,117,110,105,50,53,53,49,7,117,110,105,50,53,54,67,7,117,110,105,50,53,54,51,7,117,110,105,50,53,54,48,7,117,110,105,50,53,54,53,7,117,110,105,50,53,53,54,7,117,110,105,50,53,53,51,7,117,110,105,50,53,51,48,7,117,110,105,50,53,49,50,7,117,110,105,50,53,50,55,7,117,110,105,50,53,48,69,7,117,110,105,50,53,49,70,7,117,110,105,50,53,52,49,7,117,110,105,50,53,50,70,7,117,110,105,50,53,49,49,7,117,110,105,50,53,50,57,7,117,110,105,50,53,48,68,7,117,110,105,50,53,50,49,7,117,110,105,50,53,52,55,7,117,110,105,50,53,54,52,7,117,110,105,50,53,53,53,7,117,110,105,50,53,53,50,7,117,110,105,50,53,52,68,7,117,110,105,50,53,52,70,7,117,110,105,50,53,55,66,7,117,110,105,50,53,51,51,7,117,110,105,50,53,49,51,7,117,110,105,50,53,48,70,7,117,110,105,50,53,48,49,7,117,110,105,50,53,55,56,7,117,110,105,50,53,55,69,7,117,110,105,50,53,48,57,7,117,110,105,50,53,48,66,7,117,110,105,50,53,55,65,7,117,110,105,50,53,48,53,7,117,110,105,50,53,48,55,7,117,110,105,50,53,55,57,7,117,110,105,50,53,51,66,7,117,110,105,50,53,49,66,7,117,110,105,50,53,55,70,7,117,110,105,50,53,49,55,7,117,110,105,50,53,48,51,7,117,110,105,50,53,52,66,7,117,110,105,50,53,50,66,7,117,110,105,50,53,50,51,7,117,110,105,50,53,52,53,7,117,110,105,50,53,50,68,7,117,110,105,50,53,51,53,7,117,110,105,50,53,51,68,7,117,110,105,50,53,51,50,7,117,110,105,50,53,51,65,7,117,110,105,50,53,52,65,7,117,110,105,50,53,52,51,7,117,110,105,50,53,54,69,7,117,110,105,50,53,54,68,7,117,110,105,50,53,54,70,7,117,110,105,50,53,55,48,7,117,110,105,50,53,55,51,7,117,110,105,50,53,55,50,7,117,110,105,50,53,55,49,7,117,110,105,50,53,52,67,7,117,110,105,50,53,52,69,7,117,110,105,50,53,55,55,7,117,110,105,50,53,50,67,7,117,110,105,50,53,49,48,7,117,110,105,50,53,48,67,7,117,110,105,50,53,48,48,7,117,110,105,50,53,55,52,7,117,110,105,50,53,55,67,7,117,110,105,50,53,48,56,7,117,110,105,50,53,48,65,7,117,110,105,50,53,55,54,7,117,110,105,50,53,48,52,7,117,110,105,50,53,48,54,7,117,110,105,50,53,55,53,7,117,110,105,50,53,55,68,7,117,110,105,50,53,51,52,7,117,110,105,50,53,49,56,7,117,110,105,50,53,49,52,7,117,110,105,50,53,48,50,7,117,110,105,50,53,51,67,7,117,110,105,50,53,50,52,7,117,110,105,50,53,49,67,7,117,110,105,50,53,52,54,7,117,110,105,50,53,50,69,7,117,110,105,50,53,51,54,7,117,110,105,50,53,51,69,7,117,110,105,50,53,51,49,7,117,110,105,50,53,51,57,7,117,110,105,50,53,52,57,7,117,110,105,50,53,52,52,7,117,110,105,50,53,54,56,7,117,110,105,50,53,53,67,7,117,110,105,50,53,53,57,7,117,110,105,50,53,52,48,7,117,110,105,50,53,51,56,7,117,110,105,50,53,50,54,7,117,110,105,50,53,49,65,7,117,110,105,50,53,49,69,7,117,110,105,50,53,49,54,7,117,110,105,50,53,52,56,7,117,110,105,50,53,51,55,7,117,110,105,50,53,50,65,7,117,110,105,50,53,49,57,7,117,110,105,50,53,50,50,7,117,110,105,50,53,49,53,7,117,110,105,50,53,54,55,7,117,110,105,50,53,53,66,7,117,110,105,50,53,53,56,7,117,110,105,50,53,54,66,7,117,110,105,50,53,54,50,7,117,110,105,50,53,53,70,7,117,110,105,50,53,52,50,7,117,110,105,50,53,50,56,7,117,110,105,50,53,50,48,7,117,110,105,50,53,51,70,7,117,110,105,50,53,50,53,7,117,110,105,50,53,49,68,7,117,110,105,50,53,54,65,7,117,110,105,50,53,54,49,7,117,110,105,50,53,53,69,13,117,110,105,50,53,56,49,46,115,116,121,112,111,13,117,110,105,50,53,56,50,46,115,116,121,112,111,13,117,110,105,50,53,56,51,46,115,116,121,112,111,13,100,110,98,108,111,99,107,46,115,116,121,112,111,13,117,110,105,50,53,56,53,46,115,116,121,112,111,13,117,110,105,50,53,56,54,46,115,116,121,112,111,13,117,110,105,50,53,56,55,46,115,116,121,112,111,11,98,108,111,99,107,46,115,116,121,112,111,13,117,112,98,108,111,99,107,46,115,116,121,112,111,13,117,110,105,50,53,57,52,46,115,116,121,112,111,13,117,110,105,50,53,56,70,46,115,116,121,112,111,13,117,110,105,50,53,56,69,46,115,116,121,112,111,13,117,110,105,50,53,56,68,46,115,116,121,112,111,13,108,102,98,108,111,99,107,46,115,116,121,112,111,13,117,110,105,50,53,56,66,46,115,116,121,112,111,13,117,110,105,50,53,56,65,46,115,116,121,112,111,13,117,110,105,50,53,56,57,46,115,116,121,112,111,13,114,116,98,108,111,99,107,46,115,116,121,112,111,13,117,110,105,50,53,57,53,46,115,116,121,112,111,13,117,110,105,50,53,57,54,46,115,116,121,112,111,13,117,110,105,50,53,57,55,46,115,116,121,112,111,13,117,110,105,50,53,57,56,46,115,116,121,112,111,13,117,110,105,50,53,57,57,46,115,116,121,112,111,13,117,110,105,50,53,57,65,46,115,116,121,112,111,13,117,110,105,50,53,57,66,46,115,116,121,112,111,13,117,110,105,50,53,57,67,46,115,116,121,112,111,13,117,110,105,50,53,57,68,46,115,116,121,112,111,13,117,110,105,50,53,57,69,46,115,116,121,112,111,13,117,110,105,50,53,57,70,46,115,116,121,112,111,13,108,116,115,104,97,100,101,46,115,116,121,112,111,11,115,104,97,100,101,46,115,116,121,112,111,13,100,107,115,104,97,100,101,46,115,116,121,112,111,7,117,110,105,50,54,49,57,9,115,109,105,108,101,102,97,99,101,12,105,110,118,115,109,105,108,101,102,97,99,101,3,115,117,110,6,102,101,109,97,108,101,4,109,97,108,101,5,115,112,97,100,101,4,99,108,117,98,5,104,101,97,114,116,7,100,105,97,109,111,110,100,7,117,110,105,50,55,49,51,7,117,110,105,50,55,54,55,7,117,110,105,50,49,49,55,7,117,110,105,50,49,48,53,7,117,110,105,50,49,49,51,7,117,110,105,50,49,49,54,7,117,110,105,50,66,50,50,7,117,110,105,50,66,50,67,7,117,110,105,50,66,50,52,7,117,110,105,50,66,49,66,7,117,110,105,50,66,50,53,7,117,110,105,50,66,67,54,7,117,110,105,50,66,67,55,7,117,110,105,50,66,50,55,7,117,110,105,50,66,67,56,7,117,110,105,50,66,67,53,7,117,110,105,50,66,49,70,7,117,110,105,50,66,50,57,7,117,110,105,50,66,50,65,7,117,110,105,50,66,50,69,7,117,110,105,50,66,49,68,7,117,110,105,50,66,67,66,7,117,110,105,50,66,50,51,7,117,110,105,50,66,49,50,7,117,110,105,50,66,49,52,7,117,110,105,50,66,67,65,7,117,110,105,50,66,49,51,7,117,110,105,50,66,49,53,7,117,110,105,50,66,50,49,7,117,110,105,50,66,50,68,7,117,110,105,50,66,49,67,7,117,110,105,50,66,50,54,7,117,110,105,50,66,50,56,7,117,110,105,50,66,50,48,7,117,110,105,50,66,50,66,7,117,110,105,50,66,50,70,7,117,110,105,50,66,49,69,11,109,117,115,105,99,97,108,110,111,116,101,14,109,117,115,105,99,97,108,110,111,116,101,100,98,108,7,117,110,105,50,56,48,48,7,117,110,105,50,56,48,49,7,117,110,105,50,56,48,51,7,117,110,105,50,56,48,55,7,117,110,105,50,56,48,70,7,117,110,105,50,56,49,70,7,117,110,105,50,56,51,70,7,117,110,105,50,56,55,70,7,117,110,105,50,56,70,70,7,117,110,105,50,56,66,70,7,117,110,105,50,56,53,70,7,117,110,105,50,56,68,70,7,117,110,105,50,56,57,70,7,117,110,105,50,56,50,70,7,117,110,105,50,56,54,70,7,117,110,105,50,56,69,70,7,117,110,105,50,56,65,70,7,117,110,105,50,56,52,70,7,117,110,105,50,56,67,70,7,117,110,105,50,56,56,70,7,117,110,105,50,56,49,55,7,117,110,105,50,56,51,55,7,117,110,105,50,56,55,55,7,117,110,105,50,56,70,55,7,117,110,105,50,56,66,55,7,117,110,105,50,56,53,55,7,117,110,105,50,56,68,55,7,117,110,105,50,56,57,55,7,117,110,105,50,56,50,55,7,117,110,105,50,56,54,55,7,117,110,105,50,56,69,55,7,117,110,105,50,56,65,55,7,117,110,105,50,56,52,55,7,117,110,105,50,56,67,55,7,117,110,105,50,56,56,55,7,117,110,105,50,56,48,66,7,117,110,105,50,56,49,66,7,117,110,105,50,56,51,66,7,117,110,105,50,56,55,66,7,117,110,105,50,56,70,66,7,117,110,105,50,56,66,66,7,117,110,105,50,56,53,66,7,117,110,105,50,56,68,66,7,117,110,105,50,56,57,66,7,117,110,105,50,56,50,66,7,117,110,105,50,56,54,66,7,117,110,105,50,56,69,66,7,117,110,105,50,56,65,66,7,117,110,105,50,56,52,66,7,117,110,105,50,56,67,66,7,117,110,105,50,56,56,66,7,117,110,105,50,56,49,51,7,117,110,105,50,56,51,51,7,117,110,105,50,56,55,51,7,117,110,105,50,56,70,51,7,117,110,105,50,56,66,51,7,117,110,105,50,56,53,51,7,117,110,105,50,56,68,51,7,117,110,105,50,56,57,51,7,117,110,105,50,56,50,51,7,117,110,105,50,56,54,51,7,117,110,105,50,56,69,51,7,117,110,105,50,56,65,51,7,117,110,105,50,56,52,51,7,117,110,105,50,56,67,51,7,117,110,105,50,56,56,51,7,117,110,105,50,56,48,53,7,117,110,105,50,56,48,68,7,117,110,105,50,56,49,68,7,117,110,105,50,56,51,68,7,117,110,105,50,56,55,68,7,117,110,105,50,56,70,68,7,117,110,105,50,56,66,68,7,117,110,105,50,56,53,68,7,117,110,105,50,56,68,68,7,117,110,105,50,56,57,68,7,117,110,105,50,56,50,68,7,117,110,105,50,56,54,68,7,117,110,105,50,56,69,68,7,117,110,105,50,56,65,68,7,117,110,105,50,56,52,68,7,117,110,105,50,56,67,68,7,117,110,105,50,56,56,68,7,117,110,105,50,56,49,53,7,117,110,105,50,56,51,53,7,117,110,105,50,56,55,53,7,117,110,105,50,56,70,53,7,117,110,105,50,56,66,53,7,117,110,105,50,56,53,53,7,117,110,105,50,56,68,53,7,117,110,105,50,56,57,53,7,117,110,105,50,56,50,53,7,117,110,105,50,56,54,53,7,117,110,105,50,56,69,53,7,117,110,105,50,56,65,53,7,117,110,105,50,56,52,53,7,117,110,105,50,56,67,53,7,117,110,105,50,56,56,53,7,117,110,105,50,56,48,57,7,117,110,105,50,56,49,57,7,117,110,105,50,56,51,57,7,117,110,105,50,56,55,57,7,117,110,105,50,56,70,57,7,117,110,105,50,56,66,57,7,117,110,105,50,56,53,57,7,117,110,105,50,56,68,57,7,117,110,105,50,56,57,57,7,117,110,105,50,56,50,57,7,117,110,105,50,56,54,57,7,117,110,105,50,56,69,57,7,117,110,105,50,56,65,57,7,117,110,105,50,56,52,57,7,117,110,105,50,56,67,57,7,117,110,105,50,56,56,57,7,117,110,105,50,56,49,49,7,117,110,105,50,56,51,49,7,117,110,105,50,56,55,49,7,117,110,105,50,56,70,49,7,117,110,105,50,56,66,49,7,117,110,105,50,56,53,49,7,117,110,105,50,56,68,49,7,117,110,105,50,56,57,49,7,117,110,105,50,56,50,49,7,117,110,105,50,56,54,49,7,117,110,105,50,56,69,49,7,117,110,105,50,56,65,49,7,117,110,105,50,56,52,49,7,117,110,105,50,56,67,49,7,117,110,105,50,56,56,49,7,117,110,105,50,56,48,50,7,117,110,105,50,56,48,54,7,117,110,105,50,56,48,69,7,117,110,105,50,56,49,69,7,117,110,105,50,56,51,69,7,117,110,105,50,56,55,69,7,117,110,105,50,56,70,69,7,117,110,105,50,56,66,69,7,117,110,105,50,56,53,69,7,117,110,105,50,56,68,69,7,117,110,105,50,56,57,69,7,117,110,105,50,56,50,69,7,117,110,105,50,56,54,69,7,117,110,105,50,56,69,69,7,117,110,105,50,56,65,69,7,117,110,105,50,56,52,69,7,117,110,105,50,56,67,69,7,117,110,105,50,56,56,69,7,117,110,105,50,56,49,54,7,117,110,105,50,56,51,54,7,117,110,105,50,56,55,54,7,117,110,105,50,56,70,54,7,117,110,105,50,56,66,54,7,117,110,105,50,56,53,54,7,117,110,105,50,56,68,54,7,117,110,105,50,56,57,54,7,117,110,105,50,56,50,54,7,117,110,105,50,56,54,54,7,117,110,105,50,56,69,54,7,117,110,105,50,56,65,54,7,117,110,105,50,56,52,54,7,117,110,105,50,56,67,54,7,117,110,105,50,56,56,54,7,117,110,105,50,56,48,65,7,117,110,105,50,56,49,65,7,117,110,105,50,56,51,65,7,117,110,105,50,56,55,65,7,117,110,105,50,56,70,65,7,117,110,105,50,56,66,65,7,117,110,105,50,56,53,65,7,117,110,105,50,56,68,65,7,117,110,105,50,56,57,65,7,117,110,105,50,56,50,65,7,117,110,105,50,56,54,65,7,117,110,105,50,56,69,65,7,117,110,105,50,56,65,65,7,117,110,105,50,56,52,65,7,117,110,105,50,56,67,65,7,117,110,105,50,56,56,65,7,117,110,105,50,56,49,50,7,117,110,105,50,56,51,50,7,117,110,105,50,56,55,50,7,117,110,105,50,56,70,50,7,117,110,105,50,56,66,50,7,117,110,105,50,56,53,50,7,117,110,105,50,56,68,50,7,117,110,105,50,56,57,50,7,117,110,105,50,56,50,50,7,117,110,105,50,56,54,50,7,117,110,105,50,56,69,50,7,117,110,105,50,56,65,50,7,117,110,105,50,56,52,50,7,117,110,105,50,56,67,50,7,117,110,105,50,56,56,50,7,117,110,105,50,56,48,52,7,117,110,105,50,56,48,67,7,117,110,105,50,56,49,67,7,117,110,105,50,56,51,67,7,117,110,105,50,56,55,67,7,117,110,105,50,56,70,67,7,117,110,105,50,56,66,67,7,117,110,105,50,56,53,67,7,117,110,105,50,56,68,67,7,117,110,105,50,56,57,67,7,117,110,105,50,56,50,67,7,117,110,105,50,56,54,67,7,117,110,105,50,56,69,67,7,117,110,105,50,56,65,67,7,117,110,105,50,56,52,67,7,117,110,105,50,56,67,67,7,117,110,105,50,56,56,67,7,117,110,105,50,56,49,52,7,117,110,105,50,56,51,52,7,117,110,105,50,56,55,52,7,117,110,105,50,56,70,52,7,117,110,105,50,56,66,52,7,117,110,105,50,56,53,52,7,117,110,105,50,56,68,52,7,117,110,105,50,56,57,52,7,117,110,105,50,56,50,52,7,117,110,105,50,56,54,52,7,117,110,105,50,56,69,52,7,117,110,105,50,56,65,52,7,117,110,105,50,56,52,52,7,117,110,105,50,56,67,52,7,117,110,105,50,56,56,52,7,117,110,105,50,56,48,56,7,117,110,105,50,56,49,56,7,117,110,105,50,56,51,56,7,117,110,105,50,56,55,56,7,117,110,105,50,56,70,56,7,117,110,105,50,56,66,56,7,117,110,105,50,56,53,56,7,117,110,105,50,56,68,56,7,117,110,105,50,56,57,56,7,117,110,105,50,56,50,56,7,117,110,105,50,56,54,56,7,117,110,105,50,56,69,56,7,117,110,105,50,56,65,56,7,117,110,105,50,56,52,56,7,117,110,105,50,56,67,56,7,117,110,105,50,56,56,56,7,117,110,105,50,56,49,48,7,117,110,105,50,56,51,48,7,117,110,105,50,56,55,48,7,117,110,105,50,56,70,48,7,117,110,105,50,56,66,48,7,117,110,105,50,56,53,48,7,117,110,105,50,56,68,48,7,117,110,105,50,56,57,48,7,117,110,105,50,56,50,48,7,117,110,105,50,56,54,48,7,117,110,105,50,56,69,48,7,117,110,105,50,56,65,48,7,117,110,105,50,56,52,48,7,117,110,105,50,56,67,48,7,117,110,105,50,56,56,48,7,117,110,105,48,51,55,52,7,117,110,105,48,51,55,53,7,117,110,105,48,50,66,67,7,117,110,105,48,50,66,66,7,117,110,105,48,50,67,57,7,117,110,105,48,51,48,56,7,117,110,105,48,51,48,55,7,117,110,105,48,51,48,66,7,117,110,105,48,51,48,50,7,117,110,105,48,51,48,67,7,117,110,105,48,51,48,54,7,117,110,105,48,51,48,65,7,117,110,105,48,51,48,52,7,117,110,105,48,51,49,50,7,117,110,105,48,51,49,66,7,117,110,105,48,51,50,54,7,117,110,105,48,51,50,55,7,117,110,105,48,51,50,56,7,117,110,105,48,51,52,48,7,117,110,105,48,51,52,49,12,117,110,105,48,51,48,56,46,99,97,115,101,12,117,110,105,48,51,48,55,46,99,97,115,101,12,117,110,105,48,51,48,66,46,99,97,115,101,12,117,110,105,48,51,48,50,46,99,97,115,101,12,117,110,105,48,51,48,67,46,99,97,115,101,12,117,110,105,48,51,48,54,46,99,97,115,101,12,117,110,105,48,51,48,65,46,99,97,115,101,12,117,110,105,48,51,48,52,46,99,97,115,101,12,117,110,105,48,51,49,66,46,99,97,115,101,7,117,110,105,48,51,52,50,11,98,114,101,118,101,99,111,109,98,99,121,16,98,114,101,118,101,99,111,109,98,99,121,46,99,97,115,101,9,117,110,105,48,69,51,70,46,49,0,64,255,146,71,255,31,145,70,255,31,144,69,255,31,143,67,255,31,142,68,255,31,141,68,114,31,140,66,255,31,139,63,54,31,138,65,255,31,137,63,255,31,136,64,147,31,135,64,255,31,134,59,255,31,133,60,147,31,132,60,255,31,131,61,255,31,130,62,255,31,129,58,255,31,128,56,255,31,127,57,255,31,126,55,255,31,125,55,205,31,124,54,171,31,123,54,255,31,122,54,128,31,121,53,255,31,120,52,255,31,119,50,27,31,118,50,171,31,117,50,255,31,116,50,128,31,115,50,86,31,114,51,45,31,113,51,255,31,112,51,74,31,111,49,255,31,110,49,205,31,109,49,114,31,108,47,114,31,107,47,255,31,106,47,171,31,105,48,255,31,104,48,171,31,103,46,255,31,102,43,24,31,101,45,255,31,100,43,255,31,99,44,255,31,98,43,61,31,97,43,25,31,96,42,255,31,95,40,128,31,94,40,255,31,93,40,86,31,92,40,52,31,91,41,255,31,90,41,64,31,89,39,255,31,88,36,128,31,87,36,255,31,86,38,255,31,85,37,255,31,84,37,86,31,83,37,38,64,255,31,82,35,255,31,81,35,52,31,80,34,255,31,79,31,255,31,78,33,255,31,77,32,255,31,76,30,255,31,75,29,255,31,74,29,128,31,73,28,61,31,72,28,255,31,70,69,94,31,69,67,128,31,68,67,69,31,65,63,128,31,64,63,52,31,62,61,114,31,61,60,64,31,60,59,61,31,57,56,79,31,51,50,16,31,49,47,45,31,48,47,79,31,47,24,27,25,92,46,27,18,31,45,43,86,31,44,205,43,85,43,10,26,25,92,42,26,11,31,41,40,28,31,40,25,255,31,39,25,6,31,38,37,128,31,37,36,86,31,36,22,205,31,35,24,22,31,34,23,7,31,33,171,31,85,32,31,12,31,31,23,255,31,30,103,29,85,29,22,255,31,28,22,6,31,27,53,25,25,91,24,61,22,119,91,26,53,25,25,91,23,61,22,119,91,21,25,69,22,78,90,19,52,18,85,17,52,16,85,18,89,16,89,13,52,12,85,5,52,4,85,12,89,4,89,15,57,14,85,11,52,10,85,7,52,6,85,1,52,0,85,14,89,10,89,6,89,0,89,9,52,8,85,3,52,64,13,2,85,8,89,2,89,16,0,3,64,64,5,1,185,1,144,0,84,43,75,184,7,255,82,75,176,8,80,91,176,1,136,176,37,83,176,1,136,176,64,81,90,176,6,136,176,0,85,90,91,88,177,1,1,142,89,133,141,141,0,29,66,75,176,144,83,88,178,3,0,0,29,66,89,177,2,2,67,81,88,177,4,3,142,89,66,0,43,0,43,43,43,0,43,0,43,0,43,0,43,43,43,43,43,0,43,0,43,43,43,0,43,0,43,43,43,1,43,1,43,1,43,1,43,1,43,1,43,43,43,0,43,43,43,43,43,43,43,43,1,43,43,43,0,43,0,43,43,43,43,1,43,43,43,1,43,0,43,1,43,43,43,0,43,43,43,43,43,1,43,43,43,43,43,0,43,43,43,43,43,43,43,43,43,43,43,43,1,43,43,43,43,43,43,43,0,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,1,43,43,43,43,43,43,43,43,43,0,43,43,43,43,43,43,43,43,1,43,43,43,43,43,43,0,43,43,43,43,43,43,43,43,43,43,43,43,24}; \ No newline at end of file diff --git a/Client/CascadiaCodeFont.h b/Client/CascadiaCodeFont.h deleted file mode 100644 index f5b558a..0000000 --- a/Client/CascadiaCodeFont.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -//Generated by Fonts/encodeFont.py -//This is crossplatform and works well, although it is a bit weird. - -extern unsigned char CascadiaCodeTTF[358448]; \ No newline at end of file diff --git a/Client/Constants.h b/Client/Constants.h index 91613ca..e033218 100644 --- a/Client/Constants.h +++ b/Client/Constants.h @@ -72,7 +72,7 @@ enum class EQ_PRESET : unsigned char MANUAL = 0xa0 }; -#define APP_NAME "SonyBridge " __HEADPHONES_APP_VERSION__ +#define APP_NAME "SonyNotch " __HEADPHONES_APP_VERSION__ #define APP_NAME_W (L"" APP_NAME) using Buffer = std::vector; @@ -177,17 +177,6 @@ enum class SOUND_POSITION_PRESET : signed char OUT_OF_RANGE = -1 }; -//Needed for converting the ImGui Combo index into the VPT index. -inline const SOUND_POSITION_PRESET SOUND_POSITION_PRESET_ARRAY[] = { - SOUND_POSITION_PRESET::OFF, - SOUND_POSITION_PRESET::FRONT_LEFT, - SOUND_POSITION_PRESET::FRONT_RIGHT, - SOUND_POSITION_PRESET::FRONT, - SOUND_POSITION_PRESET::REAR_LEFT, - SOUND_POSITION_PRESET::REAR_RIGHT, - SOUND_POSITION_PRESET::OUT_OF_RANGE -}; - enum class VPT_INQUIRED_TYPE : signed char { NO_USE = 0, diff --git a/Client/CrossPlatformGUI.cpp b/Client/CrossPlatformGUI.cpp deleted file mode 100644 index 993d9a8..0000000 --- a/Client/CrossPlatformGUI.cpp +++ /dev/null @@ -1,673 +0,0 @@ -#include "CrossPlatformGUI.h" - -#include -#include -#include -#include - -#define STB_IMAGE_IMPLEMENTATION -#define STBI_ONLY_PNG -#include "stb_image.h" - -#if defined(_WIN32) -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include -#elif defined(__linux__) -#include -#endif - -bool CrossPlatformGUI::performGUIPass() -{ - ImGui::NewFrame(); - - bool open = true; - ImGuiIO& io = ImGui::GetIO(); - - ImGui::SetNextWindowPos({ 0, 0 }); - ImGui::SetNextWindowSize(io.DisplaySize); - ImGui::Begin("SonyBridge", &open, - ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBringToFrontOnFocus); - - ImGui::TextDisabled("Not affiliated with Sony. Use at your own risk."); - ImGui::Spacing(); - - this->_drawErrors(); - this->_drawDeviceDiscovery(); - - if (this->_bt.isConnected()) - { - this->_pumpConnectionState(); - - if (this->_synced) - { - this->_drawStatusHeader(); - this->_drawASMControls(); - if (this->_isV2()) - { - this->_drawEqualizer(); - this->_drawDsee(); - } - this->_drawOptionalFeatures(); - if (!this->_isV2()) - this->_drawSurroundControls(); - - this->_sendPendingASMChanges(); - } - else - { - ImGui::Spacing(); - ImGui::TextDisabled("Reading device settings %c", "|/-\\"[(int)(ImGui::GetTime() / 0.1f) & 3]); - } - } - else - { - this->_synced = false; - this->_probed = false; - this->_initialized = false; - this->_pollCounter = 0; - } - - ImGui::End(); - ImGui::Render(); - - return open; -} - -void CrossPlatformGUI::_drawErrors() -{ - if (this->_mq.begin() == this->_mq.end()) - return; - - for (auto&& message : this->_mq) - ImGui::TextColored(ImVec4(0.95f, 0.45f, 0.45f, 1.0f), "%s", message.message.c_str()); - ImGui::Spacing(); -} - -void CrossPlatformGUI::_drawDeviceDiscovery() -{ - static std::vector connectedDevices; - static int selectedDevice = -1; - - if (!this->_beginCard("##discovery")) { this->_endCard(); return; } - - if (this->_bt.isConnected()) - { - ImGui::Text("Connected to %s", this->_connectedDevice.name.c_str()); - ImGui::Spacing(); - if (ImGui::Button("Disconnect")) - { - selectedDevice = -1; - this->_bt.disconnect(); - } - this->_endCard(); - return; - } - - this->_cardTitle("Select a device"); - - int temp = 0; - for (const auto& device : connectedDevices) - { - std::string label = (device.name.empty() ? "Unknown Device" : device.name) + "##" + device.mac; - ImGui::RadioButton(label.c_str(), &selectedDevice, temp++); - } - - ImGui::Spacing(); - - if (this->_connectFuture.valid()) - { - if (this->_connectFuture.ready()) - { - try - { - this->_connectFuture.get(); - } - catch (const RecoverableException& exc) - { - if (exc.shouldDisconnect) - this->_bt.disconnect(); - this->_mq.addMessage(exc.what()); - } - } - else - { - ImGui::Text("Connecting %c", "|/-\\"[(int)(ImGui::GetTime() / 0.05f) & 3]); - } - } - else if (ImGui::Button("Connect")) - { - if (selectedDevice != -1) - { - this->_connectedDevice = connectedDevices[selectedDevice]; - this->_connectFuture.setFromAsync([this]() { this->_bt.connect(this->_connectedDevice.mac); }); - } - } - - ImGui::SameLine(); - - if (this->_connectedDevicesFuture.valid()) - { - if (this->_connectedDevicesFuture.ready()) - { - try - { - connectedDevices = this->_connectedDevicesFuture.get(); - } - catch (const RecoverableException& exc) - { - if (exc.shouldDisconnect) - this->_bt.disconnect(); - this->_mq.addMessage(exc.what()); - } - } - else - { - ImGui::Text("Discovering %c", "|/-\\"[(int)(ImGui::GetTime() / 0.05f) & 3]); - } - } - else if (ImGui::Button("Refresh devices")) - { - selectedDevice = -1; - this->_connectedDevicesFuture.setFromAsync([this]() { return this->_bt.getConnectedDevices(); }); - } - - this->_endCard(); -} - -void CrossPlatformGUI::_pumpConnectionState() -{ - // Phase 1 - fast post-connect reads: init handshake (v2), protocol-aware ambient read, then the - // always-answered settings. Each read is guarded so one slow/unanswered reply can't block the others or - // drop the link, and we always reach _synced so the UI leaves the "Reading device settings" state. - if (!this->_synced && !this->_refreshFuture.valid()) - { - this->_refreshFuture.setFromAsync([this]() { - try { if (!this->_initialized) { this->_headphones.initDevice(); this->_initialized = true; } } - catch (const std::exception&) {} - // requestAmbientState is protocol-aware (v1 uses 66 02, v2 uses 66 17) and read-only; sending it - // immediately gives v1 devices the handshake traffic they need to stay powered on. - try { this->_headphones.requestAmbientState(); } catch (const std::exception&) {} - if (this->_isV2()) - { - try { this->_headphones.requestBattery(); } catch (const std::exception&) {} - try { this->_headphones.requestEqualizer(); } catch (const std::exception&) {} - try { this->_headphones.requestDsee(); } catch (const std::exception&) {} - } - }); - } - - if (this->_refreshFuture.valid() && this->_refreshFuture.ready()) - { - try { this->_refreshFuture.get(); } catch (const std::exception&) {} - this->_syncUIFromHeadphones(); - this->_synced = true; - this->_pollCounter = 0; - } - - if (!this->_synced) - return; - - // Phase 2 - probe optional capabilities in the background. Each unsupported GET times out (~2.5s), so - // this must not gate the UI. The Feature cards read has*() live, so they appear once probing settles. - if (this->_isV2() && !this->_probed && !this->_probeFuture.valid()) - { - this->_probeFuture.setFromAsync([this]() { try { this->_headphones.probeCapabilities(); } catch (const std::exception&) {} }); - } - if (this->_probeFuture.valid() && this->_probeFuture.ready()) - { - try { this->_probeFuture.get(); } catch (const std::exception&) {} - this->_probed = true; - this->_uiAutoPowerOff = this->_headphones.getAutoPowerOff(); - this->_uiSpeakToChat = this->_headphones.getSpeakToChat(); - this->_uiAdaptiveVolume = this->_headphones.getAdaptiveVolume(); - } - - // Poll the button-changeable ASM state so the app reflects changes made on the headphone itself. - if (this->_pollFuture.valid() && this->_pollFuture.ready()) - { - try { this->_pollFuture.get(); } catch (const std::exception&) {} - if (!this->_sendCommandFuture.valid()) - { - this->_uiAsmOn = this->_headphones.getAmbientSoundControl(); - int lvl = this->_headphones.getAsmLevel(); - this->_uiAsmMode = !this->_uiAsmOn ? 0 : (lvl > 0 ? 2 : 1); - if (lvl > 0) this->_uiAsmLevel = lvl; - this->_uiFocusOnVoice = this->_headphones.getFocusOnVoice(); - } - } - if (!this->_pollFuture.valid() && ++this->_pollCounter >= DYNAMIC_POLL_FRAMES) - { - this->_pollCounter = 0; - this->_pollFuture.setFromAsync([this]() { this->_headphones.requestAmbientState(); }); - } -} - -void CrossPlatformGUI::_syncUIFromHeadphones() -{ - this->_uiAsmOn = this->_headphones.getAmbientSoundControl(); - int lvl = this->_headphones.getAsmLevel(); - this->_uiAsmMode = !this->_uiAsmOn ? 0 : (lvl > 0 ? 2 : 1); - this->_uiAsmLevel = lvl > 0 ? lvl : 10; - this->_uiFocusOnVoice = this->_headphones.getFocusOnVoice(); - - this->_uiEqPreset = (int)(unsigned char)this->_headphones.getEqualizerPreset(); - for (int i = 0; i < 5; ++i) - this->_uiEqBands[i] = this->_headphones.getEqualizerBand(i); - this->_uiClearBass = this->_headphones.getClearBass(); - this->_uiDsee = this->_headphones.getDsee(); - - this->_uiAutoPowerOff = this->_headphones.getAutoPowerOff(); - this->_uiSpeakToChat = this->_headphones.getSpeakToChat(); - this->_uiAdaptiveVolume = this->_headphones.getAdaptiveVolume(); -} - -std::string CrossPlatformGUI::_resourceBase() -{ -#if defined(_WIN32) - char buf[MAX_PATH]; - DWORD n = GetModuleFileNameA(NULL, buf, MAX_PATH); - std::string p(buf, n > 0 ? n : 0); - auto s = p.find_last_of("\\/"); - return s == std::string::npos ? std::string(".") : p.substr(0, s); -#elif defined(__linux__) - char buf[4096]; - ssize_t n = readlink("/proc/self/exe", buf, sizeof(buf) - 1); - if (n <= 0) return "."; - buf[n] = '\0'; - std::string p(buf); - auto s = p.find_last_of('/'); - return s == std::string::npos ? std::string(".") : p.substr(0, s); -#else - return "."; -#endif -} - -const CrossPlatformGUI::DeviceTexture& CrossPlatformGUI::_deviceTexture(const std::string& name) -{ - std::string slug = name; - std::transform(slug.begin(), slug.end(), slug.begin(), [](unsigned char ch) { return (char)std::tolower(ch); }); - std::replace(slug.begin(), slug.end(), ' ', '-'); - - auto it = this->_deviceTextures.find(slug); - if (it != this->_deviceTextures.end()) - return it->second; - - DeviceTexture out; // ok == false by default; cached even on failure so we don't retry every frame. - - const std::string base = this->_resourceBase(); - const std::string candidates[] = { - base + "/resources/devices/" + slug + ".png", - base + "/" + slug + ".png", - "resources/devices/" + slug + ".png", - }; - - int w = 0, h = 0, comp = 0; - unsigned char* pixels = nullptr; - for (const auto& path : candidates) - { - pixels = stbi_load(path.c_str(), &w, &h, &comp, 4); - if (pixels) break; - } - - if (pixels && w > 0 && h > 0) - { - ImTextureData* tex = IM_NEW(ImTextureData)(); - tex->Create(ImTextureFormat_RGBA32, w, h); - memcpy(tex->GetPixels(), pixels, (size_t)w * h * 4); - tex->SetStatus(ImTextureStatus_WantCreate); - ImGui::GetPlatformIO().Textures.push_back(tex); - - out.ref = tex->GetTexRef(); - out.w = w; - out.h = h; - out.ok = true; - } - if (pixels) - stbi_image_free(pixels); - - auto res = this->_deviceTextures.emplace(slug, out); - return res.first->second; -} - -void CrossPlatformGUI::_drawStatusHeader() -{ - if (!this->_beginCard("##status")) { this->_endCard(); return; } - - const DeviceTexture& hero = this->_deviceTexture(this->_connectedDevice.name); - if (hero.ok) - { - const float cardW = ImGui::GetContentRegionAvail().x; - const float maxH = 150.f; - float scale = std::min(cardW / (float)hero.w, maxH / (float)hero.h); - if (scale > 1.f) scale = 1.f; - const ImVec2 sz(hero.w * scale, hero.h * scale); - const float offx = (cardW - sz.x) * 0.5f; - if (offx > 0.f) - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offx); - ImGui::Image(hero.ref, sz); - ImGui::Spacing(); - } - - ImGui::Text("%s", this->_connectedDevice.name.empty() ? "Sony Headphones" : this->_connectedDevice.name.c_str()); - ImGui::SameLine(); - ImGui::TextDisabled("(%s)", this->_isV2() ? "v2" : "v1"); - - if (this->_headphones.hasDualBattery()) - { - ImGui::Text("Battery L %d%% R %d%%", this->_headphones.getBatteryLeft(), this->_headphones.getBatteryRight()); - if (this->_headphones.getBatteryCase() >= 0) - ImGui::Text("Case %d%%", this->_headphones.getBatteryCase()); - } - else - { - int batt = this->_headphones.getBatteryLevel(); - if (batt >= 0) - ImGui::Text("Battery %d%%%s", batt, this->_headphones.isBatteryCharging() ? " (charging)" : ""); - } - - if (this->_headphones.hasCodec()) - ImGui::Text("Codec %s", this->_headphones.getCodec().c_str()); - if (this->_headphones.hasFirmware()) - ImGui::TextDisabled("Firmware %s", this->_headphones.getFirmware().c_str()); - - this->_endCard(); -} - -void CrossPlatformGUI::_drawASMControls() -{ - if (!this->_beginCard("##asm")) { this->_endCard(); return; } - this->_cardTitle("Ambient Sound"); - - const char* modes[] = { "Off", "Noise Cancelling", "Ambient" }; - const float widths[] = { 110.f, 150.f, 120.f }; - for (int i = 0; i < 3; ++i) - { - if (i) ImGui::SameLine(); - bool sel = this->_uiAsmMode == i; - if (sel) ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]); - if (ImGui::Button(modes[i], ImVec2(widths[i], 0))) - this->_uiAsmMode = i; - if (sel) ImGui::PopStyleColor(); - } - - if (this->_uiAsmMode == 2) - { - int maxLevel = this->_isV2() ? 20 : 19; - if (this->_uiAsmLevel < 1) this->_uiAsmLevel = 1; - if (this->_uiAsmLevel > maxLevel) this->_uiAsmLevel = maxLevel; - ImGui::Spacing(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - ImGui::SliderInt("##asmlevel", &this->_uiAsmLevel, 1, maxLevel, "Level %d"); - if (this->_headphones.isFocusOnVoiceAvailable()) - ImGui::Checkbox("Focus on Voice", &this->_uiFocusOnVoice); - } - - // Map UI intent onto the desired state (mirrors the macOS applyMode); setChanges() sends only the diff. - switch (this->_uiAsmMode) - { - case 0: - this->_headphones.setAmbientSoundControl(false); - break; - case 1: - this->_headphones.setAmbientSoundControl(true); - this->_headphones.setAsmLevel(0); - this->_headphones.setFocusOnVoice(false); - break; - case 2: - this->_headphones.setAmbientSoundControl(true); - this->_headphones.setAsmLevel(this->_uiAsmLevel < 1 ? 1 : this->_uiAsmLevel); - this->_headphones.setFocusOnVoice(this->_uiFocusOnVoice); - break; - } - - this->_endCard(); -} - -void CrossPlatformGUI::_drawEqualizer() -{ - if (!this->_beginCard("##eq")) { this->_endCard(); return; } - this->_cardTitle("Equalizer"); - - static const struct { const char* name; int val; } presets[] = { - { "Off", 0x00 }, { "Bright", 0x10 }, { "Excited", 0x11 }, { "Mellow", 0x12 }, { "Relaxed", 0x13 }, - { "Vocal", 0x14 }, { "Treble", 0x15 }, { "Bass", 0x16 }, { "Speech", 0x17 }, { "Manual", 0xA0 } - }; - - const float spacing = ImGui::GetStyle().ItemSpacing.x; - const float cellW = (ImGui::GetContentRegionAvail().x - spacing * 4.f) / 5.f; - for (int i = 0; i < 10; ++i) - { - if (i % 5) ImGui::SameLine(); - bool sel = this->_uiEqPreset == presets[i].val; - if (sel) ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]); - if (ImGui::Button(presets[i].name, ImVec2(cellW, 0))) - { - this->_uiEqPreset = presets[i].val; - int p = presets[i].val; - this->_sendFeatureCommand([this, p]() { this->_headphones.setEqualizerPreset((EQ_PRESET)p); }); - } - if (sel) ImGui::PopStyleColor(); - } - - if (this->_uiEqPreset == 0xA0) - { - ImGui::Spacing(); - const char* bandNames[] = { "Clear Bass", "400", "1k", "2.5k", "6.3k", "16k" }; - int* values[] = { &this->_uiClearBass, &this->_uiEqBands[0], &this->_uiEqBands[1], - &this->_uiEqBands[2], &this->_uiEqBands[3], &this->_uiEqBands[4] }; - bool changed = false; - for (int i = 0; i < 6; ++i) - { - std::string id = "##eqband" + std::to_string(i); - std::string fmt = std::string(bandNames[i]) + " %d"; - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::SliderInt(id.c_str(), values[i], 0, 10, fmt.c_str())) - changed = true; - } - if (changed) - { - std::vector bands(this->_uiEqBands.begin(), this->_uiEqBands.end()); - int cb = this->_uiClearBass; - this->_sendFeatureCommand([this, cb, bands]() { this->_headphones.setEqualizerCustom(cb, bands); }); - } - } - - this->_endCard(); -} - -void CrossPlatformGUI::_drawDsee() -{ - if (!this->_beginCard("##dsee")) { this->_endCard(); return; } - this->_cardTitle("DSEE Upscaling"); - - if (ImGui::Checkbox("Enable DSEE", &this->_uiDsee)) - { - bool v = this->_uiDsee; - this->_sendFeatureCommand([this, v]() { this->_headphones.setDsee(v); }); - } - - this->_endCard(); -} - -void CrossPlatformGUI::_drawOptionalFeatures() -{ - const bool any = this->_headphones.hasAutoPowerOff() || this->_headphones.hasSpeakToChat() || - this->_headphones.hasAdaptiveVolume(); - if (!any) - return; - - if (!this->_beginCard("##features")) { this->_endCard(); return; } - this->_cardTitle("Features"); - - if (this->_headphones.hasAutoPowerOff()) - { - ImGui::TextUnformatted("Auto Power-Off"); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::Combo("##apo", &this->_uiAutoPowerOff, - "Off\0After 5 min\0After 30 min\0After 1 hour\0After 3 hours\0When taken off\0\0")) - { - int idx = this->_uiAutoPowerOff; - this->_sendFeatureCommand([this, idx]() { this->_headphones.setAutoPowerOff(idx); }); - } - } - - if (this->_headphones.hasSpeakToChat()) - { - if (ImGui::Checkbox("Speak-to-Chat", &this->_uiSpeakToChat)) - { - bool v = this->_uiSpeakToChat; - this->_sendFeatureCommand([this, v]() { this->_headphones.setSpeakToChat(v); }); - } - } - - if (this->_headphones.hasAdaptiveVolume()) - { - if (ImGui::Checkbox("Adaptive Volume Control", &this->_uiAdaptiveVolume)) - { - bool v = this->_uiAdaptiveVolume; - this->_sendFeatureCommand([this, v]() { this->_headphones.setAdaptiveVolume(v); }); - } - } - - this->_endCard(); -} - -void CrossPlatformGUI::_drawSurroundControls() -{ - if (!this->_beginCard("##vpt")) { this->_endCard(); return; } - this->_cardTitle("Virtual Sound"); - - ImGui::TextDisabled("Only one may be used at a time"); - - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::Combo("##pos", &this->_uiSoundPosition, - "Off\0Front Left\0Front Right\0Front\0Rear Left\0Rear Right\0\0")) - this->_uiVptType = 0; - - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::Combo("##vpt", &this->_uiVptType, - "Off\0Outdoor Festival\0Arena\0Concert Hall\0Club\0\0")) - this->_uiSoundPosition = 0; - - this->_headphones.setSurroundPosition(SOUND_POSITION_PRESET_ARRAY[this->_uiSoundPosition]); - this->_headphones.setVptType(this->_uiVptType); - - this->_endCard(); -} - -void CrossPlatformGUI::_sendPendingASMChanges() -{ - if (this->_featureCommandFuture.valid() && this->_featureCommandFuture.ready()) - { - try { this->_featureCommandFuture.get(); } - catch (const RecoverableException& e) { if (e.shouldDisconnect) this->_bt.disconnect(); this->_mq.addMessage(e.what()); } - catch (const std::exception& e) { this->_mq.addMessage(e.what()); } - } - - if (this->_sendCommandFuture.valid() && this->_sendCommandFuture.ready()) - { - try - { - this->_sendCommandFuture.get(); - } - catch (const RecoverableException& exc) - { - std::string prefix; - if (exc.shouldDisconnect) - { - this->_bt.disconnect(); - prefix = "Disconnected due to: "; - } - this->_mq.addMessage(prefix + exc.what()); - } - catch (const std::exception& e) { this->_mq.addMessage(e.what()); } - } - else if (!this->_sendCommandFuture.valid() && this->_headphones.isChanged()) - { - this->_sendCommandFuture.setFromAsync([this]() { this->_headphones.setChanges(); }); - } -} - -bool CrossPlatformGUI::_beginCard(const char* id) -{ - return ImGui::BeginChild(id, ImVec2(0.f, 0.f), - ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysUseWindowPadding); -} - -void CrossPlatformGUI::_endCard() -{ - ImGui::EndChild(); - ImGui::Spacing(); -} - -void CrossPlatformGUI::_cardTitle(const char* title) -{ - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.55f, 0.63f, 0.72f, 1.0f)); - ImGui::TextUnformatted(title); - ImGui::PopStyleColor(); - ImGui::Spacing(); -} - -void CrossPlatformGUI::_applyTheme() -{ - ImGui::StyleColorsDark(); - ImGuiStyle& s = ImGui::GetStyle(); - - s.WindowRounding = 0.f; - s.ChildRounding = 10.f; - s.FrameRounding = 8.f; - s.GrabRounding = 8.f; - s.PopupRounding = 8.f; - s.ScrollbarRounding = 8.f; - s.WindowPadding = ImVec2(16, 16); - s.FramePadding = ImVec2(12, 7); - s.ItemSpacing = ImVec2(10, 10); - s.ItemInnerSpacing = ImVec2(8, 6); - s.ChildBorderSize = 1.f; - - const ImVec4 accent = ImVec4(0.26f, 0.55f, 0.96f, 1.00f); - const ImVec4 accentHi = ImVec4(0.36f, 0.63f, 1.00f, 1.00f); - - ImVec4* c = s.Colors; - c[ImGuiCol_WindowBg] = WINDOW_COLOR; - c[ImGuiCol_ChildBg] = ImVec4(0.13f, 0.13f, 0.15f, 1.00f); - c[ImGuiCol_PopupBg] = ImVec4(0.13f, 0.13f, 0.15f, 1.00f); - c[ImGuiCol_Border] = ImVec4(1.f, 1.f, 1.f, 0.06f); - c[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.20f, 0.23f, 1.00f); - c[ImGuiCol_FrameBgHovered] = ImVec4(0.25f, 0.25f, 0.29f, 1.00f); - c[ImGuiCol_FrameBgActive] = ImVec4(0.28f, 0.28f, 0.32f, 1.00f); - c[ImGuiCol_Text] = ImVec4(0.94f, 0.94f, 0.96f, 1.00f); - c[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.56f, 1.00f); - c[ImGuiCol_Button] = ImVec4(0.22f, 0.22f, 0.26f, 1.00f); - c[ImGuiCol_ButtonHovered] = ImVec4(0.28f, 0.28f, 0.33f, 1.00f); - c[ImGuiCol_ButtonActive] = accent; - c[ImGuiCol_CheckMark] = accent; - c[ImGuiCol_SliderGrab] = accent; - c[ImGuiCol_SliderGrabActive] = accentHi; - c[ImGuiCol_Header] = ImVec4(0.22f, 0.22f, 0.26f, 1.00f); - c[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.26f, 0.31f, 1.00f); - c[ImGuiCol_HeaderActive] = accent; - c[ImGuiCol_Separator] = ImVec4(1.f, 1.f, 1.f, 0.06f); - c[ImGuiCol_ScrollbarBg] = ImVec4(0.f, 0.f, 0.f, 0.f); -} - -CrossPlatformGUI::CrossPlatformGUI(BluetoothWrapper bt) : _bt(std::move(bt)), _headphones(_bt) -{ - this->_applyTheme(); - - ImGuiIO& io = ImGui::GetIO(); - this->_mq = TimedMessageQueue(GUI_MAX_MESSAGES); - this->_connectedDevicesFuture.setFromAsync([this]() { return this->_bt.getConnectedDevices(); }); - - io.IniFilename = nullptr; - io.WantSaveIniSettings = false; - - //AddFontFromMemory will own the pointer, so there's no leak - char* fileData = new char[sizeof(CascadiaCodeTTF)]; - memcpy(fileData, CascadiaCodeTTF, sizeof(CascadiaCodeTTF)); - ImFont* font = io.Fonts->AddFontFromMemoryTTF(reinterpret_cast(fileData), sizeof(CascadiaCodeTTF), FONT_SIZE); - IM_ASSERT(font != NULL); -} diff --git a/Client/CrossPlatformGUI.h b/Client/CrossPlatformGUI.h deleted file mode 100644 index f396939..0000000 --- a/Client/CrossPlatformGUI.h +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once - -#include "imgui/imgui.h" -#include "Constants.h" -#include "IBluetoothConnector.h" -#include "BluetoothWrapper.h" -#include "CommandSerializer.h" -#include "Exceptions.h" -#include "TimedMessageQueue.h" -#include "SingleInstanceFuture.h" -#include "CascadiaCodeFont.h" -#include "Headphones.h" - -#include -#include -#include -#include - -constexpr auto GUI_MAX_MESSAGES = 5; -constexpr auto GUI_HEIGHT = 660; -constexpr auto GUI_WIDTH = 460; -constexpr auto FPS = 60; -constexpr auto MS_PER_FRAME = 1000 / FPS; -constexpr auto FONT_SIZE = 16.0f; -const auto WINDOW_COLOR = ImVec4(0.09f, 0.09f, 0.11f, 1.00f); - -// Physical-button changes (ASM) are polled roughly every two seconds so the app stays in sync. -constexpr auto DYNAMIC_POLL_FRAMES = FPS * 2; - -class CrossPlatformGUI -{ -public: - CrossPlatformGUI(BluetoothWrapper bt); - - //Run the GUI code once. This function should be called from a loop from one of the GUI impls (Windows, OSX, Linux...) - //O: true if the user wants to close the window - bool performGUIPass(); -private: - void _applyTheme(); - - void _drawErrors(); - void _drawDeviceDiscovery(); - void _drawStatusHeader(); - void _drawASMControls(); - void _drawEqualizer(); - void _drawDsee(); - void _drawOptionalFeatures(); - void _drawSurroundControls(); - - // Connection lifecycle: read device state after connect, then poll button-changeable state. - void _pumpConnectionState(); - void _syncUIFromHeadphones(); - void _sendPendingASMChanges(); - // Fire an immediate-setter feature command (EQ/DSEE/auto-power-off/…) on the worker future if it's idle. - template void _sendFeatureCommand(F&& fn); - - bool _beginCard(const char* id); - void _endCard(); - void _cardTitle(const char* title); - - // Device hero image (loaded from resources/devices/.png, uploaded via ImGui's 1.92 texture API). - struct DeviceTexture { ImTextureRef ref; int w = 0; int h = 0; bool ok = false; }; - const DeviceTexture& _deviceTexture(const std::string& name); - std::string _resourceBase(); - - bool _isV2() { return _bt.getProtocolVersion() == SonyProtocolVersion::V2; } - - BluetoothDevice _connectedDevice; - BluetoothWrapper _bt; - SingleInstanceFuture> _connectedDevicesFuture; - SingleInstanceFuture _sendCommandFuture; - SingleInstanceFuture _featureCommandFuture; - SingleInstanceFuture _refreshFuture; - SingleInstanceFuture _probeFuture; - SingleInstanceFuture _pollFuture; - SingleInstanceFuture _connectFuture; - TimedMessageQueue _mq; - Headphones _headphones; - - bool _initialized = false; - bool _synced = false; - bool _probed = false; - int _pollCounter = 0; - - // UI state, synced from the device once after connect; user edits are pushed back to the headphones. - bool _uiAsmOn = false; - int _uiAsmMode = 0; // 0 = Off, 1 = Noise Cancelling, 2 = Ambient Sound - int _uiAsmLevel = 0; - bool _uiFocusOnVoice = false; - int _uiEqPreset = 0; - std::array _uiEqBands = { 0, 0, 0, 0, 0 }; - int _uiClearBass = 0; - bool _uiDsee = false; - int _uiAutoPowerOff = 0; - bool _uiSpeakToChat = false; - bool _uiAdaptiveVolume = false; - int _uiSoundPosition = 0; - int _uiVptType = 0; - - std::map _deviceTextures; -}; - -template -void CrossPlatformGUI::_sendFeatureCommand(F&& fn) -{ - if (_featureCommandFuture.valid()) - return; - _featureCommandFuture.setFromAsync(std::forward(fn)); -} diff --git a/Client/Fonts/CascadiaCode.ttf b/Client/Fonts/CascadiaCode.ttf deleted file mode 100644 index a271f0d..0000000 Binary files a/Client/Fonts/CascadiaCode.ttf and /dev/null differ diff --git a/Client/Fonts/FontLicense.txt b/Client/Fonts/FontLicense.txt deleted file mode 100644 index 40f856f..0000000 --- a/Client/Fonts/FontLicense.txt +++ /dev/null @@ -1,94 +0,0 @@ -Copyright (c) 2019 - Present, Microsoft Corporation, -with Reserved Font Name Cascadia Code. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/Client/Fonts/encodeFont.py b/Client/Fonts/encodeFont.py deleted file mode 100644 index 29f6d02..0000000 --- a/Client/Fonts/encodeFont.py +++ /dev/null @@ -1,20 +0,0 @@ -font = "unsigned char CascadiaCodeTTF[{}] = {{{}}};" -fontDecl = "extern unsigned char CascadiaCodeTTF[{}];" - -with open("./CascadiaCode.ttf", "rb") as f: - fbytes = f.read() - -font = font.format(len(fbytes), ",".join(map(lambda x: f"{x}", fbytes))) - -with open("../CascadiaCodeFont.cpp", "w") as f: - f.write('#include "CascadiaCodeFont.h"\n\n') - f.write("/*\n") - with open("FontLicense.txt", "r") as h: - f.write(h.read()) - f.write("*/\n\n") - f.write(font) - -with open("../CascadiaCodeFont.h", "w") as f: - f.write("#pragma once\n\n") - f.write("//Generated by Fonts/encodeFont.py\n//This is crossplatform and works well, although it is a bit weird.\n\n") - f.write(fontDecl.format(len(fbytes))) \ No newline at end of file diff --git a/Client/Headphones.cpp b/Client/Headphones.cpp index 54d010f..f41f5e9 100644 --- a/Client/Headphones.cpp +++ b/Client/Headphones.cpp @@ -1,5 +1,6 @@ #include "Headphones.h" #include "CommandSerializer.h" +#include "ProtocolParsers.h" #include #include @@ -75,18 +76,32 @@ int Headphones::getVptType() return this->_vptType.current; } +bool Headphones::isV2() +{ + return this->_conn.getProtocolVersion() == SonyProtocolVersion::V2; +} + void Headphones::initDevice() { + if (!this->isV2()) return; // v2-only (see Headphones.h) // v2 devices expect an init handshake before they answer GET inquiries. Best-effort: the reply // (INIT_REPLY, 8 bytes on v2) is ignored here - we only need the device to enter the ready state. this->_conn.sendCommandAndReadResponse( { (char)V2Command::INIT_REQUEST, 0x00 }, V2Command::INIT_REPLY ); + this->_initialized = true; +} + +bool Headphones::isInitialized() +{ + return this->_initialized; } void Headphones::requestBattery() { + // CRITICAL: 0x22 is POWER_OFF on v1 - never send it on a v1 link (see Headphones.h). + if (!this->isV2()) return; // Single battery (over-ear and most models): GET 22 00 -> RET 23 00 try { auto resp = this->_conn.sendCommandAndReadResponse({ (char)V2Command::BATTERY_GET, 0x00 }, V2Command::BATTERY_RET, 0x00); @@ -94,11 +109,25 @@ void Headphones::requestBattery() std::lock_guard guard(this->_propertyMtx); this->_batteryLevel = (unsigned char)resp[2]; this->_batteryCharging = resp[3] == 1; + this->_singleBatteryKnown = true; + this->_hasDualBattery = false; return; // found a single battery; don't waste time probing the TWS types } - } catch (...) {} + } catch (...) { + // A device whose 22 00 has already succeeded once shouldn't fall back to probing the TWS + // commands on a later transient timeout - that would wrongly flip _hasDualBattery to true + // and it's never reset afterwards. Keep the last known values and bail out. + // Read under the lock: requestBattery() can run concurrently (connect + the 60s poll each + // dispatch it), and _singleBatteryKnown is otherwise only ever written under _propertyMtx. + { + std::lock_guard guard(this->_propertyMtx); + if (this->_singleBatteryKnown) return; + } + } // TWS earbuds: dual L/R (22 09 -> 23 09 ) and case (22 0a -> 23 0a ). + // Re-check the live link before each 0x22 frame: any 0x22 is POWER_OFF on v1, whatever the subtype. + if (!this->isV2()) return; try { auto resp = this->_conn.sendCommandAndReadResponse({ (char)V2Command::BATTERY_GET, 0x09 }, V2Command::BATTERY_RET, 0x09); if (resp.size() >= 6) { @@ -110,6 +139,7 @@ void Headphones::requestBattery() } } catch (...) {} + if (!this->isV2()) return; try { auto resp = this->_conn.sendCommandAndReadResponse({ (char)V2Command::BATTERY_GET, 0x0a }, V2Command::BATTERY_RET, 0x0a); if (resp.size() >= 4) { @@ -136,27 +166,25 @@ int Headphones::getBatteryCase() { return this->_batteryCase; } void Headphones::requestEqualizer() { - // GET: 56 00 -> RET: 57 00 06 - auto resp = this->_conn.sendCommandAndReadResponse( - { (char)V2Command::EQ_GET, 0x00 }, - V2Command::EQ_RET - ); - if (resp.size() >= 3) + if (!this->isV2()) return; // v2-only (see Headphones.h) + // GET: 56 00 -> RET: 57 00 (decoded by ProtocolParsers::parseEqualizer) + auto resp = this->_conn.sendCommandAndReadResponse({ (char)V2Command::EQ_GET, 0x00 }, V2Command::EQ_RET); + if (auto eq = ProtocolParsers::parseEqualizer(resp)) { std::lock_guard guard(this->_propertyMtx); - this->_eqPreset = static_cast((unsigned char)resp[2]); - // When band data is present (57 00 06 ), decode the -10..10 values. - if (resp.size() >= 10) + this->_eqPreset = static_cast(eq->preset); + if (!eq->bands.empty()) { - this->_eqClearBass = (unsigned char)resp[4] - 10; - for (int i = 0; i < 5; i++) - { - this->_eqBands[i] = (unsigned char)resp[5 + i] - 10; - } + this->_eqBands = eq->bands; + this->_eqHasClearBass = eq->hasClearBass; + this->_eqClearBass = eq->clearBass; } } } +int Headphones::getEqualizerBandCount() { return (int)this->_eqBands.size(); } +bool Headphones::equalizerHasClearBass() { return this->_eqHasClearBass; } + EQ_PRESET Headphones::getEqualizerPreset() { return this->_eqPreset; @@ -164,6 +192,7 @@ EQ_PRESET Headphones::getEqualizerPreset() void Headphones::setEqualizerPreset(EQ_PRESET preset) { + if (!this->isV2()) return; // v2-only (see Headphones.h) // SET preset: 58 00 00 this->_conn.sendCommand({ (char)V2Command::EQ_SET, @@ -177,6 +206,7 @@ void Headphones::setEqualizerPreset(EQ_PRESET preset) void Headphones::setEqualizerCustom(int clearBass, const std::vector& bands) { + if (!this->isV2()) return; // v2-only (see Headphones.h) // SET custom: 58 00 A0 06 (0xA0 = MANUAL preset; values clamped to [-10,10]) auto clamp = [](int v) { return (char)(unsigned char)(std::max(-10, std::min(10, v)) + 10); }; Buffer cmd = { @@ -195,10 +225,7 @@ void Headphones::setEqualizerCustom(int clearBass, const std::vector& bands std::lock_guard guard(this->_propertyMtx); this->_eqPreset = EQ_PRESET::MANUAL; this->_eqClearBass = clearBass; - for (int i = 0; i < 5; i++) - { - this->_eqBands[i] = i < (int)bands.size() ? bands[i] : 0; - } + this->_eqBands.assign(bands.begin(), bands.end()); } int Headphones::getClearBass() @@ -213,6 +240,7 @@ int Headphones::getEqualizerBand(int index) void Headphones::requestDsee() { + if (!this->isV2()) return; // v2-only (see Headphones.h) // GET: e6 01 -> RET: e7 01 auto resp = this->_conn.sendCommandAndReadResponse( { (char)V2Command::DSEE_GET, 0x01 }, @@ -222,9 +250,15 @@ void Headphones::requestDsee() { std::lock_guard guard(this->_propertyMtx); this->_dsee = resp[2] != 0; + this->_hasDsee = true; } } +bool Headphones::hasDsee() +{ + return this->_hasDsee; +} + bool Headphones::getDsee() { return this->_dsee; @@ -232,6 +266,7 @@ bool Headphones::getDsee() void Headphones::setDsee(bool enabled) { + if (!this->isV2()) return; // v2-only (see Headphones.h) // SET: e8 01 this->_conn.sendCommand({ (char)V2Command::DSEE_SET, @@ -249,19 +284,15 @@ void Headphones::requestAmbientState() auto protocolVersion = this->_conn.getProtocolVersion(); if (protocolVersion == SonyProtocolVersion::V2) { - // GET: 66 17 -> RET: 67 17 01 - auto resp = this->_conn.sendCommandAndReadResponse({ 0x66, 0x17 }, 0x67); - if (resp.size() >= 7) + // GET: 66 -> RET: 67 01 <0=NC/1=Ambient> [2 more bytes on 0x19] + auto resp = this->_conn.sendCommandAndReadResponse({ 0x66, (char)this->_ncAsmInquiryType }, 0x67, this->_ncAsmInquiryType); + if (auto state = ProtocolParsers::parseNcAsmState(resp)) { - bool on = resp[3] != 0; - bool ambient = resp[4] != 0; - bool voice = resp[5] != 0; - int level = (unsigned char)resp[6]; std::lock_guard guard(this->_propertyMtx); // Update both current and desired so the UI reflects reality and isChanged() stays false. - this->_ambientSoundControl.current = this->_ambientSoundControl.desired = on; - this->_asmLevel.current = this->_asmLevel.desired = ambient ? level : 0; - this->_focusOnVoice.current = this->_focusOnVoice.desired = voice; + this->_ambientSoundControl.current = this->_ambientSoundControl.desired = state->enabled; + this->_asmLevel.current = this->_asmLevel.desired = state->ambient ? state->level : 0; + this->_focusOnVoice.current = this->_focusOnVoice.desired = state->focusOnVoice; } } else @@ -276,6 +307,19 @@ void Headphones::requestAmbientState() } } +void Headphones::probeNcAsmInquiryType() +{ + // The WH-1000XM6 answers the legacy 0x17 inquiry with all zeros and reports its real state on 0x19. + // Setting the mode still goes through 68 17, which the XM6 accepts. + if (!this->isV2()) return; // v2-only (see Headphones.h) + try + { + auto resp = this->_conn.sendCommandAndReadResponse({ 0x66, 0x19 }, 0x67, 0x19); + if (ProtocolParsers::parseNcAsmState(resp)) this->_ncAsmInquiryType = 0x19; + } + catch (...) {} +} + // --- Optional features (auto power off, firmware, codec, speak-to-chat, adaptive volume) --- namespace @@ -312,26 +356,32 @@ void Headphones::probeCapabilities() { // Each GET is best-effort: an unsupported feature times out (recv timeout -> throw) and stays unsupported, // so we never expose or send a command the device can't handle. + if (!this->isV2()) return; // v2-only (see Headphones.h) try { auto r = this->_conn.sendCommandAndReadResponse({ (char)V2Command::FW_GET, 0x02 }, V2Command::FW_RET); if (r.size() > 3) { std::lock_guard g(this->_propertyMtx); this->_firmware = std::string(r.begin() + 3, r.end()); this->_hasFirmware = true; } } catch (...) {} + // The live link is re-checked before each probe: this sequence can take ~12 s to time out. + if (!this->isV2()) return; try { auto r = this->_conn.sendCommandAndReadResponse({ (char)V2Command::CODEC_GET, 0x02 }, V2Command::CODEC_RET); if (r.size() >= 3) { auto n = codecName((unsigned char)r[2]); if (!n.empty()) { std::lock_guard g(this->_propertyMtx); this->_codec = n; this->_hasCodec = true; } } } catch (...) {} + if (!this->isV2()) return; try { auto r = this->_conn.sendCommandAndReadResponse({ (char)V2Command::APO_GET, 0x05 }, V2Command::APO_RET); if (r.size() >= 4) { std::lock_guard g(this->_propertyMtx); this->_autoPowerOff = apoIndexFromCode((unsigned char)r[2], (unsigned char)r[3]); this->_hasAutoPowerOff = true; } } catch (...) {} + if (!this->isV2()) return; try { auto r = this->_conn.sendCommandAndReadResponse({ (char)V2Command::BTNMODE_GET, (char)V2Command::SUB_ADAPTIVE_VOLUME }, V2Command::BTNMODE_RET, V2Command::SUB_ADAPTIVE_VOLUME); if (r.size() >= 3) { std::lock_guard g(this->_propertyMtx); this->_adaptiveVolume = (r[2] == 0); this->_hasAdaptiveVolume = true; } } catch (...) {} + if (!this->isV2()) return; try { auto r = this->_conn.sendCommandAndReadResponse({ (char)V2Command::BTNMODE_GET, (char)V2Command::SUB_SPEAK_TO_CHAT }, V2Command::BTNMODE_RET, V2Command::SUB_SPEAK_TO_CHAT); if (r.size() >= 3) { std::lock_guard g(this->_propertyMtx); this->_speakToChat = (r[2] == 0); this->_hasSpeakToChat = true; } @@ -343,6 +393,7 @@ int Headphones::getAutoPowerOff() { return this->_autoPowerOff; } void Headphones::setAutoPowerOff(int index) { if (index < 0 || index > 5) return; + if (!this->isV2()) return; // v2-only (see Headphones.h) this->_conn.sendCommand({ (char)V2Command::APO_SET, 0x05, (char)APO_CODES[index].first, (char)APO_CODES[index].second }); std::lock_guard guard(this->_propertyMtx); this->_autoPowerOff = index; @@ -357,6 +408,7 @@ bool Headphones::hasSpeakToChat() { return this->_hasSpeakToChat; } bool Headphones::getSpeakToChat() { return this->_speakToChat; } void Headphones::setSpeakToChat(bool enabled) { + if (!this->isV2()) return; // v2-only (see Headphones.h) // SET: f8 0c 01 (enable bit is inverted on v2) this->_conn.sendCommand({ (char)V2Command::BTNMODE_SET, (char)V2Command::SUB_SPEAK_TO_CHAT, (char)(enabled ? 0x00 : 0x01), 0x01 }); std::lock_guard guard(this->_propertyMtx); @@ -367,6 +419,7 @@ bool Headphones::hasAdaptiveVolume() { return this->_hasAdaptiveVolume; } bool Headphones::getAdaptiveVolume() { return this->_adaptiveVolume; } void Headphones::setAdaptiveVolume(bool enabled) { + if (!this->isV2()) return; // v2-only (see Headphones.h) // SET: f8 0a (inverted) this->_conn.sendCommand({ (char)V2Command::BTNMODE_SET, (char)V2Command::SUB_ADAPTIVE_VOLUME, (char)(enabled ? 0x00 : 0x01) }); std::lock_guard guard(this->_propertyMtx); diff --git a/Client/Headphones.h b/Client/Headphones.h index 6197d56..635728c 100644 --- a/Client/Headphones.h +++ b/Client/Headphones.h @@ -1,7 +1,7 @@ -#include "SingleInstanceFuture.h" #include "BluetoothWrapper.h" #include "Constants.h" +#include #include template @@ -34,8 +34,15 @@ class Headphones { void setVptType(int val); int getVptType(); + // SAFETY: every v2-only inquiry/setter below (init, battery, equalizer, DSEE, NC/ASM probe, capability + // probes and their setters) returns WITHOUT sending anything when the live link isn't v2 - opcode 0x22 + // (BATTERY_GET on v2) is POWER_OFF on v1. This guards against a stale session's queued work reaching a + // v1 headset that got connected on the same BluetoothWrapper right after. + // Handshake the device expects before it answers inquiry (GET) commands on the v2 protocol. void initDevice(); + // True once initDevice() got its reply. Per object, i.e. per connection session. + bool isInitialized(); // Battery (v2 inquiry). getBatteryLevel() returns -1 until requestBattery() succeeds. // For TWS earbuds requestBattery() also fills the per-earbud + case levels (hasDualBattery()). @@ -54,10 +61,13 @@ class Headphones { // Custom (manual) EQ: 5 band values + clear bass, each in [-10, 10]. Selects the MANUAL preset. void setEqualizerCustom(int clearBass, const std::vector& bands); int getClearBass(); - int getEqualizerBand(int index); // 0..4 + int getEqualizerBand(int index); // 0..4 (5-band layout) or 0..9 (10-band layout) + int getEqualizerBandCount(); // 0 until read, then 5 (+ Clear Bass) or 10 + bool equalizerHasClearBass(); // DSEE / audio upsampling (v2). void requestDsee(); + bool hasDsee(); // true once the device answered requestDsee() bool getDsee(); void setDsee(bool enabled); @@ -65,6 +75,9 @@ class Headphones { // changes made with the headphone's own button are reflected in the app). void requestAmbientState(); + // Picks the NC/ASM inquiry channel: 0x19 when the device answers it (WH-1000XM6), else the legacy 0x17. + void probeNcAsmInquiryType(); + // Optional features. probeCapabilities() sends each GET on connect; a feature is "supported" only if // the device answers (otherwise we must never send its SET - see the WH-1000XM4 power-off incident). void probeCapabilities(); @@ -89,6 +102,11 @@ class Headphones { bool isChanged(); void setChanges(); private: + // Checked on every v2-only call (not cached): the wrapper's link can change under a long-lived object. + bool isV2(); + + std::atomic _initialized{ false }; + Property _ambientSoundControl = { 0 }; Property _focusOnVoice = { 0 }; Property _asmLevel = { 0 }; @@ -98,13 +116,20 @@ class Headphones { int _batteryLevel = -1; bool _batteryCharging = false; bool _hasDualBattery = false; + // Set once GET 22 00 succeeds. Guards requestBattery() against a later transient timeout on 22 00 + // falling through to the TWS probes (22 09/22 0a), which would wrongly flip _hasDualBattery to true + // and never reset it - see requestBattery(). + bool _singleBatteryKnown = false; int _batteryLeft = -1; int _batteryRight = -1; int _batteryCase = -1; EQ_PRESET _eqPreset = EQ_PRESET::OFF; - std::vector _eqBands = { 0, 0, 0, 0, 0 }; + std::vector _eqBands; // empty until the first read; 5 or 10 values + bool _eqHasClearBass = false; + unsigned char _ncAsmInquiryType = 0x17; // 0x19 on the WH-1000XM6, see probeNcAsmInquiryType() int _eqClearBass = 0; bool _dsee = false; + bool _hasDsee = false; bool _hasAutoPowerOff = false; int _autoPowerOff = 0; bool _hasFirmware = false; std::string _firmware; diff --git a/Client/IBluetoothConnector.h b/Client/IBluetoothConnector.h index 54678d7..aa841c0 100644 --- a/Client/IBluetoothConnector.h +++ b/Client/IBluetoothConnector.h @@ -18,7 +18,7 @@ struct BluetoothDevice }; /* -General notes: Please look at the implementation of WindowsBluetoothConnector. +General notes: Please look at the implementation of MacOSBluetoothConnector. * Functions should throw RecoverableExceptions if they're indeed recoverable, and throw std::runtime_error otherwise. * RecoverableException can force a disconnection of the socket with an additional param (a call to disconnect()). * connect() should try the v1 service UUID (SONY_UUID) first and fall back to the v2 UUID (SONY_UUID_V2) diff --git a/Client/ProtocolParsers.cpp b/Client/ProtocolParsers.cpp new file mode 100644 index 0000000..b1b2e9e --- /dev/null +++ b/Client/ProtocolParsers.cpp @@ -0,0 +1,45 @@ +#include "ProtocolParsers.h" + +#include + +namespace ProtocolParsers +{ + std::optional parseNcAsmState(const Buffer& payload) + { + if (payload.size() < 7) return std::nullopt; + auto opcode = (unsigned char)payload[0]; + auto type = (unsigned char)payload[1]; + if ((opcode != 0x67 && opcode != 0x69) || (type != 0x17 && type != 0x19)) return std::nullopt; + if (std::all_of(payload.begin() + 2, payload.end(), [](char b) { return b == 0; })) return std::nullopt; + + NcAsmState state; + state.enabled = payload[3] != 0; + state.ambient = payload[4] != 0; + state.focusOnVoice = payload[5] != 0; + state.level = (unsigned char)payload[6]; + return state; + } + + std::optional parseEqualizer(const Buffer& payload) + { + if (payload.size() < 3 || (unsigned char)payload[0] != 0x57) return std::nullopt; + + EqualizerState state{ (unsigned char)payload[2], false, 0, {} }; + if (payload.size() < 4) return state; + size_t count = (unsigned char)payload[3]; + if (payload.size() < 4 + count) return state; + + auto value = [&](size_t i) { return (int)(unsigned char)payload[4 + i] - 10; }; + if (count == 6) + { + state.hasClearBass = true; + state.clearBass = value(0); + for (size_t i = 1; i < 6; i++) state.bands.push_back(value(i)); + } + else if (count == 10) + { + for (size_t i = 0; i < 10; i++) state.bands.push_back(value(i)); + } + return state; + } +} diff --git a/Client/ProtocolParsers.h b/Client/ProtocolParsers.h new file mode 100644 index 0000000..f4bf5fc --- /dev/null +++ b/Client/ProtocolParsers.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include "Constants.h" + +// Pure decoders for v2 inquiry replies. `payload` is the frame's field, starting with the reply opcode. +namespace ProtocolParsers +{ + struct NcAsmState + { + bool enabled; // NC/ASM effect on + bool ambient; // true = Ambient Sound, false = Noise Cancelling + bool focusOnVoice; + int level; // ambient level (meaningful when ambient) + }; + + // Accepts "67|69 17 01 " and the WH-1000XM6 "67|69 19 01 + // ". Returns nullopt when too short, for other opcodes, and for the all-zero body the XM6 sends + // back on the channel it doesn't use (67 17 00 00 00 00 00). + std::optional parseNcAsmState(const Buffer& payload); + + struct EqualizerState + { + unsigned char preset; // raw preset id (EQ_PRESET values, or ids we don't know yet like 0x30) + bool hasClearBass; // 5-band layout only + int clearBass; // -10..10 when hasClearBass + std::vector bands; // 5 or 10 values in -10..10; empty when the reply carried no band data + }; + + // "57 00 06 " (5 bands + Clear Bass) or "57 00 0a ". + std::optional parseEqualizer(const Buffer& payload); +} diff --git a/Client/SingleInstanceFuture.h b/Client/SingleInstanceFuture.h deleted file mode 100644 index d2e6c49..0000000 --- a/Client/SingleInstanceFuture.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include -#include -#include -#include - - -//A simple future wrapper class. Allows only a single instance to be active at any single time; particularly useful for GUI operations where we don't want -//to send the same commands or repeat operations before they completed. Also wraps std::async nicely with setFromAsync -template -class SingleInstanceFuture : public std::future -{ -public: - SingleInstanceFuture(void) = default; - template - void setFromAsync(Func func, Args&&... args) noexcept(false); - bool ready(); - -private: - SingleInstanceFuture(std::future other); - SingleInstanceFuture operator=(std::future& other); -}; - -template -template -inline void SingleInstanceFuture::setFromAsync(Func func, Args && ...args) -{ - if (this->valid()) - { - throw std::runtime_error("The asynchronous action was cancelled before it finished executing"); - } - *this = std::async(std::launch::async, func, std::forward(args)...); -} - -template -inline bool SingleInstanceFuture::ready() -{ - if (!this->valid()) - { - return false; - } - return this->wait_for(std::chrono::seconds(0)) == std::future_status::ready; -} - - -template -inline SingleInstanceFuture::SingleInstanceFuture(std::future other) : std::future(std::move(other)) {} - -template -inline SingleInstanceFuture SingleInstanceFuture::operator=(std::future& other) -{ - return std::future::operator=(other); -} diff --git a/Client/TimedMessageQueue.cpp b/Client/TimedMessageQueue.cpp deleted file mode 100644 index 09fecfe..0000000 --- a/Client/TimedMessageQueue.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "TimedMessageQueue.h" - -TimedMessageQueue::TimedMessageQueue(unsigned int maxMessages, unsigned long long durationMs) -{ - this->_maxMessages = maxMessages; - this->_durationMs = durationMs; -} - -void TimedMessageQueue::addMessage(std::string message) -{ - if (this->_messages.size() == this->_maxMessages) - { - this->_messages.pop_front(); - } - - this->_messages.emplace_back(std::move(message), Clock::now() + std::chrono::milliseconds(this->_durationMs)); -} - -std::deque::const_iterator TimedMessageQueue::begin() -{ - while (this->_messages.size() > 0) - { - if (this->_messages.front()._releaseTime < Clock::now()) - { - this->_messages.pop_front(); - } - else - { - //break if we reached a non-stale message, to improve perf - break; - } - } - - return this->_messages.cbegin(); -} - -std::deque::const_iterator TimedMessageQueue::end() const -{ - return this->_messages.cend(); -} diff --git a/Client/TimedMessageQueue.h b/Client/TimedMessageQueue.h deleted file mode 100644 index 6aac499..0000000 --- a/Client/TimedMessageQueue.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -using LargeCounter = unsigned long long; -using Clock = std::chrono::system_clock; -using TimePoint = std::chrono::time_point; - -auto constexpr DEFAULT_MAX_MESSAGES = 13371337; -constexpr auto DEFAULT_ERROR_MESSAGE_MS = 10000; - -struct Message -{ -public: - Message(std::string message, TimePoint releaseTime) - { - this->message = std::move(message); - this->_releaseTime = releaseTime; - } - - friend class TimedMessageQueue; - - std::string message; -private: - TimePoint _releaseTime; -}; - -class TimedMessageQueue -{ -public: - TimedMessageQueue(unsigned int maxMessages = DEFAULT_MAX_MESSAGES, unsigned long long durationMs = DEFAULT_ERROR_MESSAGE_MS); - - //I: A message, and the length of time it should remain available - void addMessage(std::string message); - - //The iteators returned are guaranteed to stay valid only until the next `begin()` or `addMessage` call. - std::deque::const_iterator begin(); - std::deque::const_iterator end() const; -private: - std::deque _messages; - unsigned int _maxMessages = DEFAULT_MAX_MESSAGES; - unsigned long long _durationMs; -}; \ No newline at end of file diff --git a/Client/imgui b/Client/imgui deleted file mode 160000 index b62bfd6..0000000 --- a/Client/imgui +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b62bfd6b06de958e4630b715225b7e8409bfd0f9 diff --git a/Client/linux/DBusHelper.cpp b/Client/linux/DBusHelper.cpp deleted file mode 100644 index abbf7a2..0000000 --- a/Client/linux/DBusHelper.cpp +++ /dev/null @@ -1,335 +0,0 @@ -#include "DBusHelper.h" -#include "../Exceptions.h" -#include -#include -#include - -DBusConnection *dbus_open_system_bus(void) -{ - DBusError error; - DBusConnection *connection = NULL; - - dbus_error_init(&error); - - connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); - - if (dbus_error_is_set(&error)) - { - printf("Could not get system bus\nError: %s\n", error.message); - dbus_error_free(&error); - return NULL; - } - - return connection; -} - -dbus_bool_t open_dict_read(DBusMessageIter *const iter, DBusMessageIter *const iter_dict) -{ - if (NULL == iter || NULL == iter_dict) - { - return FALSE; - } - - if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) - { - return FALSE; - } - - if (dbus_message_iter_get_element_type(iter) != DBUS_TYPE_DICT_ENTRY) - { - return FALSE; - } - - dbus_message_iter_recurse(iter, iter_dict); - return TRUE; -} - -dbus_bool_t read_next_object_path_entry(DBusMessageIter *const iter_object_paths, char **const object_path, DBusMessageIter *const iter_interfaces) -{ - DBusMessageIter iter_dict_entry; - - if (!iter_object_paths || !iter_interfaces) - { - goto error; - } - - if (dbus_message_iter_get_arg_type(iter_object_paths) != DBUS_TYPE_DICT_ENTRY) - { - goto error; - } - - dbus_message_iter_recurse(iter_object_paths, &iter_dict_entry); - - if (dbus_message_iter_get_arg_type(&iter_dict_entry) != DBUS_TYPE_OBJECT_PATH) - { - printf("Error: Unexpected arg type for object path\n"); - goto error; - } - - dbus_message_iter_get_basic(&iter_dict_entry, object_path); - - dbus_message_iter_next(&iter_dict_entry); - - if (FALSE == open_dict_read(&iter_dict_entry, iter_interfaces)) - { - goto error; - } - - dbus_message_iter_next(iter_object_paths); - - return TRUE; - -error: - return FALSE; -} - -dbus_bool_t read_next_interface_entry(DBusMessageIter *const interface_dict, char **const interface) -{ - DBusMessageIter iter_dict_entry; - - if (!interface_dict) - { - goto error; - } - - if (dbus_message_iter_get_arg_type(interface_dict) != DBUS_TYPE_DICT_ENTRY) - { - goto error; - } - - dbus_message_iter_recurse(interface_dict, &iter_dict_entry); - - if (dbus_message_iter_get_arg_type(&iter_dict_entry) != DBUS_TYPE_STRING) - { - printf("Error: Unexpected arg type for interface\n"); - goto error; - } - - dbus_message_iter_get_basic(&iter_dict_entry, interface); - - dbus_message_iter_next(interface_dict); - - return TRUE; - -error: - return FALSE; -} - -std::vector dbus_list_adapters(DBusConnection *const connection) -{ - - std::vector ret; - - DBusError error; - DBusMessage *msg = NULL; - DBusMessage *rsp = NULL; - DBusMessageIter args; - DBusMessageIter subargs; - DBusMessageIter interface_iter; - char *object_path = NULL; - char *interface = NULL; - char const *const device_interface = "org.bluez.Device1"; - - dbus_error_init(&error); - - msg = dbus_message_new_method_call("org.bluez", - "/", - "org.freedesktop.DBus.ObjectManager", - "GetManagedObjects"); - if (NULL == msg) - { - printf("Error: Could not obtain method call\n"); - goto clean_up; - } - - /* No arguments */ - - /* Invoke the method */ - rsp = dbus_connection_send_with_reply_and_block(connection, - msg, - DBUS_TIMEOUT_USE_DEFAULT, - &error); - if (dbus_error_is_set(&error)) - { - printf("Could not send dbus message\nError: %s\n", error.message); - dbus_error_free(&error); - goto clean_up; - } - - if (NULL == rsp) - { - printf("Error: Response was NULL\n"); - goto clean_up; - } - - if (!dbus_message_iter_init(rsp, &args)) - { - printf("Error: RCould not start message iterator on response\n"); - goto clean_up; - } - - if (!open_dict_read(&args, &subargs)) - { - printf("Error: Could not start dict read\n"); - goto clean_up; - } - - while (FALSE != read_next_object_path_entry(&subargs, &object_path, &interface_iter)) - { - /* dbus_bool_t found = FALSE; */ - while (FALSE != read_next_interface_entry(&interface_iter, &interface)) - { - if (strcmp(device_interface, interface) == 0) - { - ret.push_back(object_path); - } - } - } - -clean_up: - if (NULL != rsp) - { - dbus_message_unref(rsp); - } - - if (NULL != msg) - { - dbus_message_unref(msg); - } - return ret; -} - -std::string dbus_get_property(DBusConnection *const connection, const char *device_path, const char *property) -{ - - std::string ret; - - DBusError error; - DBusMessage *msg = NULL; - DBusMessage *rsp = NULL; - DBusMessageIter args; - DBusMessageIter subargs; - char *interface = NULL; - char const *const device_interface = "org.bluez.Device1"; - - dbus_error_init(&error); - - msg = dbus_message_new_method_call("org.bluez", - device_path, - "org.freedesktop.DBus.Properties", - "Get"); - if (NULL == msg) - { - printf("Error: Could not obtain method call\n"); - goto clean_up; - } - - /* arguments */ - dbus_message_append_args(msg, - DBUS_TYPE_STRING, &device_interface, - DBUS_TYPE_INVALID); - - dbus_message_append_args(msg, - DBUS_TYPE_STRING, &property, - DBUS_TYPE_INVALID); - - /* Invoke the method */ - rsp = dbus_connection_send_with_reply_and_block(connection, - msg, - DBUS_TIMEOUT_USE_DEFAULT, - &error); - if (dbus_error_is_set(&error)) - { - printf("Could not send dbus message\nError: %s\n", error.message); - dbus_error_free(&error); - goto clean_up; - } - - if (NULL == rsp) - { - printf("Error: Response was NULL\n"); - goto clean_up; - } - - if (!dbus_message_iter_init(rsp, &args)) - { - printf("Error: Could not start message iterator on response\n"); - goto clean_up; - } - - dbus_message_iter_recurse(&args, &subargs); - - dbus_message_iter_get_basic(&subargs, &interface); - ret = std::string(interface); - -clean_up: - if (NULL != rsp) - { - dbus_message_unref(rsp); - } - - if (NULL != msg) - { - dbus_message_unref(msg); - } - - return ret; -} - -uint8_t sdp_getServiceChannel(const char *dev_addr, uint8_t *uuid128) -{ - int status; - bdaddr_t target; - uuid_t svc_uuid; - sdp_list_t *response_list, *search_list, *attrid_list; - sdp_session_t *session = 0; - uint32_t range = 0x0000ffff; - uint8_t port = 0; - str2ba(dev_addr, &target); - /* connect to the SDP server running on the remote machine */ - const bdaddr_t bdaddr_any = {{0, 0, 0, 0, 0, 0}}; - session = sdp_connect(&bdaddr_any, &target, SDP_RETRY_IF_BUSY); - if (!session) { - throw RecoverableException("Error: could not connect to bluetooth spd server", true); -} - - sdp_uuid128_create(&svc_uuid, uuid128); - search_list = sdp_list_append(0, &svc_uuid); - attrid_list = sdp_list_append(0, &range); - // get a list of service records that have UUID 0xabcd - response_list = NULL; - status = sdp_service_search_attr_req(session, search_list, - SDP_ATTR_REQ_RANGE, attrid_list, &response_list); - if (status == 0) - { - sdp_list_t *proto_list = NULL; - sdp_list_t *r = response_list; - - // go through each of the service records - for (; r; r = r->next) - { - sdp_record_t *rec = (sdp_record_t *)r->data; - - // get a list of the protocol sequences - if (sdp_get_access_protos(rec, &proto_list) == 0) - { - // get the RFCOMM port number - port = sdp_get_proto_port(proto_list, RFCOMM_UUID); - - sdp_list_free(proto_list, 0); - } - sdp_record_free(rec); - } - } - sdp_list_free(response_list, 0); - sdp_list_free(search_list, 0); - sdp_list_free(attrid_list, 0); - sdp_close(session); - - if (port != 0) - { - printf("found service running on RFCOMM port %d\n", port); - } - - return port; -} \ No newline at end of file diff --git a/Client/linux/DBusHelper.h b/Client/linux/DBusHelper.h deleted file mode 100644 index 91af421..0000000 --- a/Client/linux/DBusHelper.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -DBusConnection *dbus_open_system_bus(); -dbus_bool_t open_dict_read(DBusMessageIter *const iter, DBusMessageIter *const iter_dict); -dbus_bool_t read_next_object_path_entry(DBusMessageIter *const iter_object_paths, char **const object_path, DBusMessageIter *const iter_interfaces); -dbus_bool_t read_next_interface_entry(DBusMessageIter *const interface_dict, char **const interface); -std::vector dbus_list_adapters(DBusConnection *const connection); -std::string dbus_get_property(DBusConnection *const connection, const char *device_path, const char *property); - -uint8_t sdp_getServiceChannel(const char *dev_addr, uint8_t *uuid128); - diff --git a/Client/linux/FindDBus.cmake b/Client/linux/FindDBus.cmake deleted file mode 100644 index 4a1a180..0000000 --- a/Client/linux/FindDBus.cmake +++ /dev/null @@ -1,59 +0,0 @@ -# - Try to find DBus -# Once done, this will define -# -# DBUS_FOUND - system has DBus -# DBUS_INCLUDE_DIRS - the DBus include directories -# DBUS_LIBRARIES - link these to use DBus -# -# Copyright (C) 2012 Raphael Kubo da Costa -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS -# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -FIND_PACKAGE(PkgConfig) -PKG_CHECK_MODULES(PC_DBUS QUIET dbus-1) - -FIND_LIBRARY(DBUS_LIBRARIES - NAMES dbus-1 - HINTS ${PC_DBUS_LIBDIR} - ${PC_DBUS_LIBRARY_DIRS} -) - -FIND_PATH(DBUS_INCLUDE_DIR - NAMES dbus/dbus.h - HINTS ${PC_DBUS_INCLUDEDIR} - ${PC_DBUS_INCLUDE_DIRS} -) - -GET_FILENAME_COMPONENT(_DBUS_LIBRARY_DIR ${DBUS_LIBRARIES} PATH) -FIND_PATH(DBUS_ARCH_INCLUDE_DIR - NAMES dbus/dbus-arch-deps.h - HINTS ${PC_DBUS_INCLUDEDIR} - ${PC_DBUS_INCLUDE_DIRS} - ${_DBUS_LIBRARY_DIR} - ${DBUS_INCLUDE_DIR} - PATH_SUFFIXES include -) - -SET(DBUS_INCLUDE_DIRS ${DBUS_INCLUDE_DIR} ${DBUS_ARCH_INCLUDE_DIR}) - -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(DBUS REQUIRED_VARS DBUS_INCLUDE_DIRS DBUS_LIBRARIES) diff --git a/Client/linux/LinuxBluetoothConnector.cpp b/Client/linux/LinuxBluetoothConnector.cpp deleted file mode 100644 index 3e0d19a..0000000 --- a/Client/linux/LinuxBluetoothConnector.cpp +++ /dev/null @@ -1,151 +0,0 @@ -#include "LinuxBluetoothConnector.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "DBusHelper.h" - -LinuxBluetoothConnector::LinuxBluetoothConnector() -{ -} -LinuxBluetoothConnector::~LinuxBluetoothConnector() -{ - //onclose event - if (isConnected()) - { - disconnect(); - } -} - -int LinuxBluetoothConnector::recv(char *buf, size_t length) -{ - ssize_t bytesRead = ::read(this->_socket, buf, length); - if (bytesRead < 0) - { - // A recv timeout (SO_RCVTIMEO) is expected while probing optional features: report it as recoverable - // WITHOUT forcing a disconnect so an unanswered GET just hides that feature instead of dropping the link. - if (errno == EAGAIN || errno == EWOULDBLOCK) - { - throw RecoverableException("recv timed out", false); - } - throw RecoverableException(std::string("Couldn't recv: ") + strerror(errno), true); - } - return (int)bytesRead; -} - -int LinuxBluetoothConnector::send(char *buf, size_t length) -{ - - size_t written = ::write(this->_socket, buf, length); - // printf("length: %ld, written: %ld\n", length, written); - // for (int i = 0; i < written; i++) - // { - // std::cout << std::setfill('0') << std::setw(2) << std::hex << (0xff & (unsigned int)buf[i]) << " "; - // } - // std::cout << '\n'; - return written; -} - -void LinuxBluetoothConnector::connect(const std::string &addrStr) -{ - - printf("connecting to %s\n", addrStr.c_str()); - struct sockaddr_rc addr = {0}; - int status; - const char *dest = addrStr.c_str(); - - // allocate a socket - this->_socket = ::socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - - uint32_t linkmode = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT; - int sl = sizeof(linkmode); - setsockopt(this->_socket, SOL_RFCOMM, RFCOMM_LM, &linkmode, sl); - - // Bound recv so capability probing can't block forever (matches the 2.5s macOS timeout). - struct timeval recvTimeout = {2, 500000}; - setsockopt(this->_socket, SOL_SOCKET, SO_RCVTIMEO, &recvTimeout, sizeof(recvTimeout)); - - // set the connection parameters (who to connect to) - addr.rc_family = AF_BLUETOOTH; - // try the v1 service UUID first, then fall back to the v2 (newer-generation) UUID. - uint8_t channel = sdp_getServiceChannel(addrStr.c_str(), SERVICE_UUID_IN_BYTES); - this->_protocolVersion = SonyProtocolVersion::V1; - if (channel == 0) - { - channel = sdp_getServiceChannel(addrStr.c_str(), SERVICE_UUID_V2_IN_BYTES); - this->_protocolVersion = SonyProtocolVersion::V2; - } - if (channel == 0) - { - throw RecoverableException("Couldn't find the Sony service record on this device (neither protocol version) - is this a supported headset?", true); - } - printf("channel: %d\n", channel); - addr.rc_channel = channel; - str2ba(dest, &addr.rc_bdaddr); - - // connect to server - status = ::connect(this->_socket, (struct sockaddr *)&addr, sizeof(addr)); - - if (status < 0) - { - throw RecoverableException("Error: could not connect to bluetooth socket", true); - } - this->_connected = true; -} - -std::vector LinuxBluetoothConnector::getConnectedDevices() -{ - - std::vector res; - - DBusConnection *connection = dbus_open_system_bus(); - if (NULL == connection) - { - return res; - } - - std::vector adapter_paths = dbus_list_adapters(connection); - for (auto &adapter : adapter_paths) - { - printf("%s\n", adapter.c_str()); - std::string name = dbus_get_property(connection, adapter.c_str(), "Name"); - std::string address = dbus_get_property(connection, adapter.c_str(), "Address"); - res.push_back({.name = name, .mac = address}); - } - - return res; -} - -void LinuxBluetoothConnector::disconnect() noexcept -{ - // close connection - if (this->_socket != -1) - { - ::close(this->_socket); - } - this->_connected = false; - printf("closed\n"); -} - -bool LinuxBluetoothConnector::isConnected() noexcept -{ - return this->_connected; -} - -SonyProtocolVersion LinuxBluetoothConnector::getProtocolVersion() noexcept -{ - return this->_protocolVersion; -} diff --git a/Client/linux/LinuxBluetoothConnector.h b/Client/linux/LinuxBluetoothConnector.h deleted file mode 100644 index ae2e01b..0000000 --- a/Client/linux/LinuxBluetoothConnector.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include -#include "../IBluetoothConnector.h" -#include "Constants.h" -#include - -class LinuxBluetoothConnector final : public IBluetoothConnector -{ -public: - LinuxBluetoothConnector(); - ~LinuxBluetoothConnector(); - virtual void connect(const std::string& addrStr) noexcept(false); - virtual int send(char* buf, size_t length) noexcept(false); - virtual int recv(char* buf, size_t length) noexcept(false); - virtual void disconnect() noexcept; - virtual bool isConnected() noexcept; - virtual std::vector getConnectedDevices() noexcept(false); - virtual SonyProtocolVersion getProtocolVersion() noexcept; - - -private: - int _socket = -1; - std::atomic _connected = false; - SonyProtocolVersion _protocolVersion = SonyProtocolVersion::V1; -}; \ No newline at end of file diff --git a/Client/linux/LinuxGUI.cpp b/Client/linux/LinuxGUI.cpp deleted file mode 100644 index 6da1590..0000000 --- a/Client/linux/LinuxGUI.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "LinuxGUI.h" -#include "imgui.h" -#include "backends/imgui_impl_glfw.h" -#include "backends/imgui_impl_opengl3.h" -#include -#include -#include "Constants.h" -#include "TimedMessageQueue.h" -#include "CrossPlatformGUI.h" - -static void glfw_error_callback(int error, const char *description) -{ - fprintf(stderr, "Glfw Error %d: %s\n", error, description); -} - -void EnterGUIMainLoop(BluetoothWrapper bt) -{ - // Setup Dear ImGui binding - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - - // init GUI - CrossPlatformGUI GUI = CrossPlatformGUI(std::move(bt)); - - // Setup window - glfwSetErrorCallback(glfw_error_callback); - if (!glfwInit()) - return; - - const char *glsl_version = "#version 150"; - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); - - // Create window with graphics context - GLFWwindow *window = glfwCreateWindow(GUI_WIDTH, GUI_HEIGHT, APP_NAME, NULL, NULL); - if (window == NULL) - return; - - glfwMakeContextCurrent(window); - glfwSwapInterval(1); // Enable vsync - - ImGuiIO &io = ImGui::GetIO(); - (void)io; - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls - - // Setup Dear ImGui style - ImGui::StyleColorsDark(); - //ImGui::StyleColorsClassic(); - - // Setup Platform/Renderer backends - ImGui_ImplGlfw_InitForOpenGL(window, true); - ImGui_ImplOpenGL3_Init(glsl_version); - - ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); - // Main loop - while (!glfwWindowShouldClose(window)) - { - - glfwPollEvents(); - - // Start the Dear ImGui frame - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - - // perform gui pass - GUI.performGUIPass(); - - int display_w, display_h; - glfwGetFramebufferSize(window, &display_w, &display_h); - glViewport(0, 0, display_w, display_h); - glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); - glClear(GL_COLOR_BUFFER_BIT); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - - glfwSwapBuffers(window); - } - - // Cleanup - ImGui_ImplOpenGL3_Shutdown(); - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); - - glfwDestroyWindow(window); - glfwTerminate(); -}; diff --git a/Client/linux/LinuxGUI.h b/Client/linux/LinuxGUI.h deleted file mode 100644 index de24869..0000000 --- a/Client/linux/LinuxGUI.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "BluetoothWrapper.h" - -void EnterGUIMainLoop(BluetoothWrapper bt); \ No newline at end of file diff --git a/Client/linux/main.cpp b/Client/linux/main.cpp deleted file mode 100644 index 847a465..0000000 --- a/Client/linux/main.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include "LinuxGUI.h" -#include "LinuxBluetoothConnector.h" -#include "BluetoothWrapper.h" - -int main(int argc, const char *argv[]) -{ - try - { - // Get bluetooth connector - std::unique_ptr connector = std::make_unique(); - // Wrap the connector using the bluetoothwrapper - BluetoothWrapper wrap(std::move(connector)); - // Start the gui - EnterGUIMainLoop(std::move(wrap)); - } - catch (const std::exception &e) - { - printf("%s", e.what()); - } - return 1; -} diff --git a/Client/macos/AppDelegate.h b/Client/macos/AppDelegate.h deleted file mode 100644 index 0217437..0000000 --- a/Client/macos/AppDelegate.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// AppDelegate.h -// SonyHeadphonesClient -// -// Created by Sem Visscher on 01/12/2020. -// - -#import -#import -#import -#import "BluetoothWrapper.h" -#import "Headphones.h" -#import "MacOSBluetoothConnector.h" - -@interface AppDelegate : NSObject - @property (weak) NSWindow* window; - -@end diff --git a/Client/macos/AppDelegate.mm b/Client/macos/AppDelegate.mm deleted file mode 100644 index 5d09dc3..0000000 --- a/Client/macos/AppDelegate.mm +++ /dev/null @@ -1,35 +0,0 @@ -// -// AppDelegate.m -// SonyHeadphonesClient -// -// Created by Sem Visscher on 01/12/2020. -// - -#import "AppDelegate.h" - -@interface AppDelegate () - - -@end - -@implementation AppDelegate -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - _window = [[[NSApplication sharedApplication] windows] firstObject]; -} - -- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag -{ - if (flag) { - return NO; - } - else { - [_window makeKeyAndOrderFront:self]; - return YES; - } -} - -- (void)applicationWillTerminate:(NSNotification *)aNotification { - // Insert code here to tear down your application -} - -@end diff --git a/Client/macos/AppDelegate.swift b/Client/macos/AppDelegate.swift new file mode 100644 index 0000000..3b6d450 --- /dev/null +++ b/Client/macos/AppDelegate.swift @@ -0,0 +1,40 @@ +import AppKit +import Combine + +final class AppDelegate: NSObject, NSApplicationDelegate { + private let model = HeadphonesModel() + private let settings = AppSettings() + private let music = MusicController() + private let deviceWatcher = DeviceWatcher() + private var statusItemController: StatusItemController? + private var notchController: NotchController? + private var cancellables = Set() + + func applicationDidFinishLaunching(_ notification: Notification) { + model.settings = settings + statusItemController = StatusItemController(model: model, settings: settings) + notchController = NotchController(model: model, music: music, settings: settings) + + // Spotify is only read while the notch is on (notch spec §4.3). $showNotch emits the current value first. + settings.$showNotch + .receive(on: DispatchQueue.main) + .sink { [weak self] show in + if show { self?.music.start() } else { self?.music.stop() } + } + .store(in: &cancellables) + + deviceWatcher.onConnect = { [weak self] address, name in + self?.model.headsetConnectedToMac(address: address, name: name) + } + deviceWatcher.onDisconnect = { [weak self] address in + self?.model.headsetDisconnectedFromMac(address: address) + } + deviceWatcher.start() + + if settings.autoConnect { model.autoConnectOnLaunch() } + } + + func applicationWillTerminate(_ notification: Notification) { + model.disconnect() + } +} diff --git a/Client/macos/AppSettings.swift b/Client/macos/AppSettings.swift new file mode 100644 index 0000000..2214b65 --- /dev/null +++ b/Client/macos/AppSettings.swift @@ -0,0 +1,99 @@ +import Foundation +import ServiceManagement + +// The user options, persisted in UserDefaults. Launch at login is backed by SMAppService (macOS 13+). +final class AppSettings: ObservableObject { + private enum Keys { + static let autoConnect = "autoConnect" + static let autoReconnect = "autoReconnect" + static let lastDeviceAddress = "lastDeviceAddress" + static let showNotch = "showNotch" + static let notchWidth = "notchOpenWidth" + static let notchHeight = "notchOpenHeight" + static let notchSide = "notchSideWidth" + static let notchZoom = "notchZoom" + static let notchArtwork = "notchRestingArtwork" + } + + private let defaults: UserDefaults + + @Published var autoConnect: Bool { + didSet { defaults.set(autoConnect, forKey: Keys.autoConnect) } + } + @Published var autoReconnect: Bool { + didSet { defaults.set(autoReconnect, forKey: Keys.autoReconnect) } + } + @Published var showNotch: Bool { + didSet { defaults.set(showNotch, forKey: Keys.showNotch) } + } + @Published private(set) var launchAtLogin: Bool + + // Notch Size submenu. Stored as the user set them; NotchLayout clamps. + @Published var notchWidth: Double { didSet { defaults.set(notchWidth, forKey: Keys.notchWidth) } } + @Published var notchHeight: Double { didSet { defaults.set(notchHeight, forKey: Keys.notchHeight) } } + @Published var notchSideWidth: Double { didSet { defaults.set(notchSideWidth, forKey: Keys.notchSide) } } + @Published var notchZoom: Double { didSet { defaults.set(notchZoom, forKey: Keys.notchZoom) } } + @Published var notchArtwork: Double { didSet { defaults.set(notchArtwork, forKey: Keys.notchArtwork) } } + // True while the Notch Size submenu is open: the notch stays open as a live preview. Not persisted. + @Published var notchPreviewing = false + + var notchLayout: NotchLayout { + NotchLayout(openSize: CGSize(width: notchWidth, height: notchHeight), + sideExtension: CGFloat(notchSideWidth), zoom: CGFloat(notchZoom), + restingArtwork: CGFloat(notchArtwork)) + } + + var lastDeviceAddress: String? { + get { defaults.string(forKey: Keys.lastDeviceAddress) } + set { defaults.set(newValue, forKey: Keys.lastDeviceAddress) } + } + + init(defaults: UserDefaults = .standard) { + self.defaults = defaults + // Spec §4: auto-connect and auto-reconnect default on; launch at login stays off until the user asks. + // Notch spec §7: the notch is shown by default. + let layout = NotchLayout.default + defaults.register(defaults: [ + Keys.autoConnect: true, Keys.autoReconnect: true, Keys.showNotch: true, + Keys.notchWidth: Double(layout.openSize.width), Keys.notchHeight: Double(layout.openSize.height), + Keys.notchSide: Double(layout.sideExtension), Keys.notchZoom: Double(layout.zoom), + Keys.notchArtwork: Double(layout.restingArtwork), + ]) + autoConnect = defaults.bool(forKey: Keys.autoConnect) + autoReconnect = defaults.bool(forKey: Keys.autoReconnect) + showNotch = defaults.bool(forKey: Keys.showNotch) + notchWidth = defaults.double(forKey: Keys.notchWidth) + notchHeight = defaults.double(forKey: Keys.notchHeight) + notchSideWidth = defaults.double(forKey: Keys.notchSide) + notchZoom = defaults.double(forKey: Keys.notchZoom) + notchArtwork = defaults.double(forKey: Keys.notchArtwork) + launchAtLogin = SMAppService.mainApp.status == .enabled + } + + func resetNotchSize() { + let layout = NotchLayout.default + notchWidth = Double(layout.openSize.width) + notchHeight = Double(layout.openSize.height) + notchSideWidth = Double(layout.sideExtension) + notchZoom = Double(layout.zoom) + notchArtwork = Double(layout.restingArtwork) + } + + // Returns an error message if macOS refused the change. + func setLaunchAtLogin(_ enabled: Bool) -> String? { + defer { launchAtLogin = SMAppService.mainApp.status == .enabled } + do { + if enabled { + try SMAppService.mainApp.register() + if SMAppService.mainApp.status == .requiresApproval { + SMAppService.openSystemSettingsLoginItems() + } + } else { + try SMAppService.mainApp.unregister() + } + return nil + } catch { + return error.localizedDescription + } + } +} diff --git a/Client/macos/Assets.xcassets/AppIcon.appiconset/Contents.json b/Client/macos/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 9dabd29..0000000 --- a/Client/macos/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { "idiom" : "mac", "scale" : "1x", "size" : "16x16", "filename" : "icon_16.png" }, - { "idiom" : "mac", "scale" : "2x", "size" : "16x16", "filename" : "icon_32.png" }, - { "idiom" : "mac", "scale" : "1x", "size" : "32x32", "filename" : "icon_32.png" }, - { "idiom" : "mac", "scale" : "2x", "size" : "32x32", "filename" : "icon_64.png" }, - { "idiom" : "mac", "scale" : "1x", "size" : "128x128", "filename" : "icon_128.png" }, - { "idiom" : "mac", "scale" : "2x", "size" : "128x128", "filename" : "icon_256.png" }, - { "idiom" : "mac", "scale" : "1x", "size" : "256x256", "filename" : "icon_256.png" }, - { "idiom" : "mac", "scale" : "2x", "size" : "256x256", "filename" : "icon_512.png" }, - { "idiom" : "mac", "scale" : "1x", "size" : "512x512", "filename" : "icon_512.png" }, - { "idiom" : "mac", "scale" : "2x", "size" : "512x512", "filename" : "icon_1024.png" } - ], - "info" : { "author" : "xcode", "version" : 1 } -} diff --git a/Client/macos/Assets.xcassets/Contents.json b/Client/macos/Assets.xcassets/Contents.json deleted file mode 100644 index d8b757a..0000000 --- a/Client/macos/Assets.xcassets/Contents.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "info" : { "author" : "xcode", "version" : 1 } -} diff --git a/Client/macos/Assets.xcassets/linkbuds-s.imageset/Contents.json b/Client/macos/Assets.xcassets/linkbuds-s.imageset/Contents.json deleted file mode 100644 index 6dcd1d8..0000000 --- a/Client/macos/Assets.xcassets/linkbuds-s.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "filename": "linkbuds-s.png" - } - ], - "info": { - "author": "xcode", - "version": 1 - } -} \ No newline at end of file diff --git a/Client/macos/Assets.xcassets/linkbuds-s.imageset/linkbuds-s.png b/Client/macos/Assets.xcassets/linkbuds-s.imageset/linkbuds-s.png deleted file mode 100644 index 89f98ed..0000000 Binary files a/Client/macos/Assets.xcassets/linkbuds-s.imageset/linkbuds-s.png and /dev/null differ diff --git a/Client/macos/Assets.xcassets/mdr-xb950bt.imageset/Contents.json b/Client/macos/Assets.xcassets/mdr-xb950bt.imageset/Contents.json deleted file mode 100644 index ee1bb8d..0000000 --- a/Client/macos/Assets.xcassets/mdr-xb950bt.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "filename": "mdr-xb950bt.png" - } - ], - "info": { - "author": "xcode", - "version": 1 - } -} \ No newline at end of file diff --git a/Client/macos/Assets.xcassets/mdr-xb950bt.imageset/mdr-xb950bt.png b/Client/macos/Assets.xcassets/mdr-xb950bt.imageset/mdr-xb950bt.png deleted file mode 100644 index 2362dac..0000000 Binary files a/Client/macos/Assets.xcassets/mdr-xb950bt.imageset/mdr-xb950bt.png and /dev/null differ diff --git a/Client/macos/Assets.xcassets/wf-1000xm4.imageset/Contents.json b/Client/macos/Assets.xcassets/wf-1000xm4.imageset/Contents.json deleted file mode 100644 index f8ee553..0000000 --- a/Client/macos/Assets.xcassets/wf-1000xm4.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "filename": "wf-1000xm4.png" - } - ], - "info": { - "author": "xcode", - "version": 1 - } -} \ No newline at end of file diff --git a/Client/macos/Assets.xcassets/wf-1000xm4.imageset/wf-1000xm4.png b/Client/macos/Assets.xcassets/wf-1000xm4.imageset/wf-1000xm4.png deleted file mode 100644 index 418be7e..0000000 Binary files a/Client/macos/Assets.xcassets/wf-1000xm4.imageset/wf-1000xm4.png and /dev/null differ diff --git a/Client/macos/Assets.xcassets/wf-1000xm5.imageset/Contents.json b/Client/macos/Assets.xcassets/wf-1000xm5.imageset/Contents.json deleted file mode 100644 index 550d4f2..0000000 --- a/Client/macos/Assets.xcassets/wf-1000xm5.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "filename": "wf-1000xm5.png" - } - ], - "info": { - "author": "xcode", - "version": 1 - } -} \ No newline at end of file diff --git a/Client/macos/Assets.xcassets/wf-1000xm5.imageset/wf-1000xm5.png b/Client/macos/Assets.xcassets/wf-1000xm5.imageset/wf-1000xm5.png deleted file mode 100644 index 413f582..0000000 Binary files a/Client/macos/Assets.xcassets/wf-1000xm5.imageset/wf-1000xm5.png and /dev/null differ diff --git a/Client/macos/Assets.xcassets/wf-c700n.imageset/Contents.json b/Client/macos/Assets.xcassets/wf-c700n.imageset/Contents.json deleted file mode 100644 index 5de1caf..0000000 --- a/Client/macos/Assets.xcassets/wf-c700n.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "filename": "wf-c700n.png" - } - ], - "info": { - "author": "xcode", - "version": 1 - } -} \ No newline at end of file diff --git a/Client/macos/Assets.xcassets/wf-c700n.imageset/wf-c700n.png b/Client/macos/Assets.xcassets/wf-c700n.imageset/wf-c700n.png deleted file mode 100644 index 1e183ff..0000000 Binary files a/Client/macos/Assets.xcassets/wf-c700n.imageset/wf-c700n.png and /dev/null differ diff --git a/Client/macos/Assets.xcassets/wh-1000xm2.imageset/Contents.json b/Client/macos/Assets.xcassets/wh-1000xm2.imageset/Contents.json deleted file mode 100644 index 8bc7fef..0000000 --- a/Client/macos/Assets.xcassets/wh-1000xm2.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "filename": "wh-1000xm2.png" - } - ], - "info": { - "author": "xcode", - "version": 1 - } -} \ No newline at end of file diff --git a/Client/macos/Assets.xcassets/wh-1000xm2.imageset/wh-1000xm2.png b/Client/macos/Assets.xcassets/wh-1000xm2.imageset/wh-1000xm2.png deleted file mode 100644 index dd502bb..0000000 Binary files a/Client/macos/Assets.xcassets/wh-1000xm2.imageset/wh-1000xm2.png and /dev/null differ diff --git a/Client/macos/Assets.xcassets/wh-1000xm3.imageset/Contents.json b/Client/macos/Assets.xcassets/wh-1000xm3.imageset/Contents.json deleted file mode 100644 index 9f33fc0..0000000 --- a/Client/macos/Assets.xcassets/wh-1000xm3.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "filename": "wh-1000xm3.png" - } - ], - "info": { - "author": "xcode", - "version": 1 - } -} \ No newline at end of file diff --git a/Client/macos/Assets.xcassets/wh-1000xm3.imageset/wh-1000xm3.png b/Client/macos/Assets.xcassets/wh-1000xm3.imageset/wh-1000xm3.png deleted file mode 100644 index febf92e..0000000 Binary files a/Client/macos/Assets.xcassets/wh-1000xm3.imageset/wh-1000xm3.png and /dev/null differ diff --git a/Client/macos/Assets.xcassets/wh-1000xm4.imageset/Contents.json b/Client/macos/Assets.xcassets/wh-1000xm4.imageset/Contents.json deleted file mode 100644 index 968d1ea..0000000 --- a/Client/macos/Assets.xcassets/wh-1000xm4.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "filename": "wh-1000xm4.png" - } - ], - "info": { - "author": "xcode", - "version": 1 - } -} \ No newline at end of file diff --git a/Client/macos/Assets.xcassets/wh-1000xm4.imageset/wh-1000xm4.png b/Client/macos/Assets.xcassets/wh-1000xm4.imageset/wh-1000xm4.png deleted file mode 100644 index 7b3662d..0000000 Binary files a/Client/macos/Assets.xcassets/wh-1000xm4.imageset/wh-1000xm4.png and /dev/null differ diff --git a/Client/macos/Assets.xcassets/wh-1000xm5.imageset/Contents.json b/Client/macos/Assets.xcassets/wh-1000xm5.imageset/Contents.json deleted file mode 100644 index f487aaa..0000000 --- a/Client/macos/Assets.xcassets/wh-1000xm5.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "filename": "wh-1000xm5.png" - } - ], - "info": { - "author": "xcode", - "version": 1 - } -} \ No newline at end of file diff --git a/Client/macos/Assets.xcassets/wh-1000xm5.imageset/wh-1000xm5.png b/Client/macos/Assets.xcassets/wh-1000xm5.imageset/wh-1000xm5.png deleted file mode 100644 index 5c58b84..0000000 Binary files a/Client/macos/Assets.xcassets/wh-1000xm5.imageset/wh-1000xm5.png and /dev/null differ diff --git a/Client/macos/Assets.xcassets/wh-1000xm6.imageset/Contents.json b/Client/macos/Assets.xcassets/wh-1000xm6.imageset/Contents.json deleted file mode 100644 index 10909c0..0000000 --- a/Client/macos/Assets.xcassets/wh-1000xm6.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "filename": "wh-1000xm6.png" - } - ], - "info": { - "author": "xcode", - "version": 1 - } -} \ No newline at end of file diff --git a/Client/macos/Assets.xcassets/wh-1000xm6.imageset/wh-1000xm6.png b/Client/macos/Assets.xcassets/wh-1000xm6.imageset/wh-1000xm6.png deleted file mode 100644 index 61f2e58..0000000 Binary files a/Client/macos/Assets.xcassets/wh-1000xm6.imageset/wh-1000xm6.png and /dev/null differ diff --git a/Client/macos/Assets.xcassets/wh-ch520.imageset/Contents.json b/Client/macos/Assets.xcassets/wh-ch520.imageset/Contents.json deleted file mode 100644 index 6d4b0a1..0000000 --- a/Client/macos/Assets.xcassets/wh-ch520.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "filename": "wh-ch520.png" - } - ], - "info": { - "author": "xcode", - "version": 1 - } -} \ No newline at end of file diff --git a/Client/macos/Assets.xcassets/wh-ch520.imageset/wh-ch520.png b/Client/macos/Assets.xcassets/wh-ch520.imageset/wh-ch520.png deleted file mode 100644 index 3d30871..0000000 Binary files a/Client/macos/Assets.xcassets/wh-ch520.imageset/wh-ch520.png and /dev/null differ diff --git a/Client/macos/Assets.xcassets/wh-ch720n.imageset/Contents.json b/Client/macos/Assets.xcassets/wh-ch720n.imageset/Contents.json deleted file mode 100644 index d0874cd..0000000 --- a/Client/macos/Assets.xcassets/wh-ch720n.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "filename": "wh-ch720n.png" - } - ], - "info": { - "author": "xcode", - "version": 1 - } -} \ No newline at end of file diff --git a/Client/macos/Assets.xcassets/wh-ch720n.imageset/wh-ch720n.png b/Client/macos/Assets.xcassets/wh-ch720n.imageset/wh-ch720n.png deleted file mode 100644 index e885a9b..0000000 Binary files a/Client/macos/Assets.xcassets/wh-ch720n.imageset/wh-ch720n.png and /dev/null differ diff --git a/Client/macos/Assets.xcassets/wh-xb900n.imageset/Contents.json b/Client/macos/Assets.xcassets/wh-xb900n.imageset/Contents.json deleted file mode 100644 index f579440..0000000 --- a/Client/macos/Assets.xcassets/wh-xb900n.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "filename": "wh-xb900n.png" - } - ], - "info": { - "author": "xcode", - "version": 1 - } -} \ No newline at end of file diff --git a/Client/macos/Assets.xcassets/wh-xb900n.imageset/wh-xb900n.png b/Client/macos/Assets.xcassets/wh-xb900n.imageset/wh-xb900n.png deleted file mode 100644 index 08a7f3e..0000000 Binary files a/Client/macos/Assets.xcassets/wh-xb900n.imageset/wh-xb900n.png and /dev/null differ diff --git a/Client/macos/Assets.xcassets/wh-xb910n.imageset/Contents.json b/Client/macos/Assets.xcassets/wh-xb910n.imageset/Contents.json deleted file mode 100644 index 6a56e55..0000000 --- a/Client/macos/Assets.xcassets/wh-xb910n.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "filename": "wh-xb910n.png" - } - ], - "info": { - "author": "xcode", - "version": 1 - } -} \ No newline at end of file diff --git a/Client/macos/Assets.xcassets/wh-xb910n.imageset/wh-xb910n.png b/Client/macos/Assets.xcassets/wh-xb910n.imageset/wh-xb910n.png deleted file mode 100644 index b40b633..0000000 Binary files a/Client/macos/Assets.xcassets/wh-xb910n.imageset/wh-xb910n.png and /dev/null differ diff --git a/Client/macos/ContentView.swift b/Client/macos/ContentView.swift deleted file mode 100644 index 45b0388..0000000 --- a/Client/macos/ContentView.swift +++ /dev/null @@ -1,448 +0,0 @@ -// -// ContentView.swift -// Sony Sound Connect-style SwiftUI interface. -// - -import SwiftUI -import AppKit - -private enum Theme { - static let bg = Color(red: 0.07, green: 0.07, blue: 0.086) - static let card = Color(red: 0.13, green: 0.13, blue: 0.16) - static let cardHi = Color(red: 0.20, green: 0.20, blue: 0.24) - static let accent = Color(red: 0.62, green: 0.62, blue: 0.96) - static let secondary = Color(white: 0.62) -} - -@available(macOS 11.0, *) -struct ContentView: View { - @StateObject private var model = HeadphonesModel() - @State private var showAbout = false - - var body: some View { - ZStack { - Theme.bg.ignoresSafeArea() - if model.connected { - connectedView - } else { - disconnectedView - } - } - .frame(minWidth: 360, minHeight: 500) - } - - // MARK: - Disconnected - - private var disconnectedView: some View { - VStack(spacing: 24) { - Spacer() - Image(systemName: "headphones") - .font(.system(size: 64, weight: .thin)) - .foregroundColor(Theme.secondary) - Text("No headphones connected") - .font(.system(size: 15, weight: .medium)) - .foregroundColor(Theme.secondary) - if let error = model.errorMessage { - Text(error) - .font(.system(size: 12)) - .foregroundColor(.red.opacity(0.9)) - .multilineTextAlignment(.center) - .padding(.horizontal, 32) - } - Button(action: model.connect) { - Text(model.connecting ? "Connecting…" : "Connect headphones") - .font(.system(size: 14, weight: .semibold)) - .foregroundColor(.white) - .frame(maxWidth: .infinity) - .padding(.vertical, 12) - .background(Theme.accent) - .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous)) - } - .buttonStyle(PlainButtonStyle()) - .disabled(model.connecting) - .padding(.horizontal, 40) - Spacer() - } - } - - // MARK: - Connected - - private var connectedView: some View { - ScrollView(showsIndicators: false) { - VStack(spacing: 16) { - deviceHero - ambientCard - if model.mode == .ambientSound { - ambientLevelCard - } - if model.supportsEqualizer { - equalizerCard - dseeCard - } - if model.hasAdaptiveVolume || model.hasSpeakToChat || model.hasAutoPowerOff { - settingsCard - } - if let error = model.errorMessage { - Text(error) - .font(.system(size: 12)) - .foregroundColor(.red.opacity(0.9)) - } - } - .padding(20) - } - } - - private var deviceHero: some View { - VStack(spacing: 12) { - HStack(spacing: 10) { - Spacer() - Button(action: { showAbout = true }) { - Image(systemName: "ellipsis") - .font(.system(size: 15, weight: .semibold)) - .foregroundColor(Theme.secondary) - .frame(width: 32, height: 32) - .background(Theme.card) - .clipShape(Circle()) - } - .buttonStyle(PlainButtonStyle()) - .popover(isPresented: $showAbout, arrowEdge: .bottom) { aboutView } - Button(action: model.disconnect) { - Image(systemName: "power") - .font(.system(size: 14, weight: .semibold)) - .foregroundColor(Theme.secondary) - .frame(width: 32, height: 32) - .background(Theme.card) - .clipShape(Circle()) - } - .buttonStyle(PlainButtonStyle()) - } - - // Product-style banner. Generic headphone graphic (device-specific Sony renders are - // copyrighted and can't be bundled) over a soft accent halo, mirroring Sony's app layout. - ZStack { - // Soft accent glow behind the product for depth. - Circle() - .fill( - RadialGradient( - gradient: Gradient(colors: [Theme.accent.opacity(0.22), Theme.accent.opacity(0.0)]), - center: .center, startRadius: 4, endRadius: 104 - ) - ) - .frame(width: 210, height: 210) - - if let image = deviceImage() { - // Background-removed product cutout floating on the dark UI. - Image(nsImage: image) - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 190, height: 190) - } else { - Image(systemName: "headphones") - .font(.system(size: 92, weight: .thin)) - .foregroundColor(.white) - } - } - - Text(model.deviceName) - .font(.system(size: 24, weight: .bold)) - .foregroundColor(.white) - - HStack(spacing: 7) { - if model.hasDualBattery { - Image(systemName: "battery.100") - .font(.system(size: 13)) - .foregroundColor(Theme.accent) - Text("L \(model.batteryLeft)% R \(model.batteryRight)%") - .font(.system(size: 13, weight: .semibold)) - .foregroundColor(Theme.secondary) - } else if model.batteryLevel >= 0 { - Image(systemName: model.batteryCharging ? "bolt.fill" : batterySymbol(model.batteryLevel)) - .font(.system(size: 13)) - .foregroundColor(model.batteryLevel <= 20 ? .red.opacity(0.9) : Theme.accent) - Text("\(model.batteryLevel)%") - .font(.system(size: 14, weight: .semibold)) - .foregroundColor(Theme.secondary) - } else { - Circle().fill(Theme.accent).frame(width: 7, height: 7) - Text("Connected") - .font(.system(size: 13, weight: .medium)) - .foregroundColor(Theme.secondary) - } - if !model.codec.isEmpty { - Text("·").foregroundColor(Theme.secondary) - Text(model.codec) - .font(.system(size: 12, weight: .semibold)) - .foregroundColor(Theme.secondary) - } - } - } - .padding(.bottom, 4) - } - - private var ambientCard: some View { - VStack(alignment: .leading, spacing: 16) { - Text("Ambient Sound Control") - .font(.system(size: 15, weight: .semibold)) - .foregroundColor(.white) - HStack(spacing: 0) { - modeButton(.noiseCanceling, "speaker.slash.fill", "Noise\nCanceling") - modeButton(.ambientSound, "wind", "Ambient\nSound") - modeButton(.off, "circle", "Off") - } - } - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Theme.card) - .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous)) - } - - private func modeButton(_ mode: SHCAmbientMode, _ symbol: String, _ label: String) -> some View { - let selected = model.mode == mode - return Button(action: { model.setMode(mode) }) { - VStack(spacing: 8) { - ZStack { - Circle() - .fill(selected ? Theme.accent : Theme.cardHi) - .frame(width: 58, height: 58) - Image(systemName: symbol) - .font(.system(size: 22, weight: .medium)) - .foregroundColor(selected ? .white : Theme.secondary) - } - Text(label) - .font(.system(size: 11, weight: .medium)) - .multilineTextAlignment(.center) - .foregroundColor(selected ? .white : Theme.secondary) - } - .frame(maxWidth: .infinity) - } - .buttonStyle(.plain) - } - - private var ambientLevelCard: some View { - VStack(alignment: .leading, spacing: 14) { - HStack { - Text("Ambient Sound Level") - .font(.system(size: 13, weight: .medium)) - .foregroundColor(Theme.secondary) - Spacer() - Text("\(model.ambientLevel)") - .font(.system(size: 20, weight: .bold, design: .rounded)) - .foregroundColor(Theme.accent) - } - Slider( - value: Binding( - get: { Double(model.ambientLevel) }, - set: { model.setLevel(Int($0.rounded())) } - ), - in: 1...Double(model.maxAmbientLevel), - step: 1 - ) - .accentColor(Theme.accent) - - if model.focusOnVoiceAvailable { - Toggle(isOn: Binding( - get: { model.focusOnVoice }, - set: { model.setFocusOnVoice($0) } - )) { - Text("Focus on Voice") - .font(.system(size: 13, weight: .medium)) - .foregroundColor(.white) - } - .toggleStyle(SwitchToggleStyle(tint: Theme.accent)) - } - } - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Theme.card) - .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous)) - } - - private let eqPresets: [(String, Int)] = [ - ("Off", 0x00), ("Bright", 0x10), ("Excited", 0x11), - ("Mellow", 0x12), ("Relaxed", 0x13), ("Vocal", 0x14), - ("Treble", 0x15), ("Bass", 0x16), ("Speech", 0x17), - ("Manual", 0xA0) - ] - private let eqBandLabels = ["400", "1k", "2.5k", "6.3k", "16k"] - - private var equalizerCard: some View { - VStack(alignment: .leading, spacing: 14) { - Text("Equalizer") - .font(.system(size: 15, weight: .semibold)) - .foregroundColor(.white) - LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())], spacing: 10) { - ForEach(eqPresets, id: \.1) { preset in - eqChip(preset.0, preset.1) - } - } - if model.eqPreset == 0xA0 { - Divider().background(Theme.cardHi) - ForEach(0..<5, id: \.self) { i in - eqBandRow(eqBandLabels[i], value: Binding( - get: { Double(model.eqBands[i]) }, - set: { model.eqBands[i] = Int($0.rounded()); model.applyCustomEq() } - ), display: model.eqBands[i]) - } - eqBandRow("Bass", value: Binding( - get: { Double(model.clearBass) }, - set: { model.clearBass = Int($0.rounded()); model.applyCustomEq() } - ), display: model.clearBass, accent: true) - } - } - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Theme.card) - .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous)) - } - - private func eqBandRow(_ label: String, value: Binding, display: Int, accent: Bool = false) -> some View { - HStack(spacing: 10) { - Text(label) - .font(.system(size: 11, weight: .medium)) - .foregroundColor(accent ? Theme.accent : Theme.secondary) - .frame(width: 34, alignment: .leading) - Slider(value: value, in: -10...10, step: 1).accentColor(Theme.accent) - Text("\(display > 0 ? "+" : "")\(display)") - .font(.system(size: 11, weight: .semibold, design: .monospaced)) - .foregroundColor(.white) - .frame(width: 26, alignment: .trailing) - } - } - - private var dseeCard: some View { - Toggle(isOn: Binding(get: { model.dsee }, set: { model.setDsee($0) })) { - VStack(alignment: .leading, spacing: 2) { - Text("DSEE").font(.system(size: 14, weight: .semibold)).foregroundColor(.white) - Text("Upscale compressed audio").font(.system(size: 11)).foregroundColor(Theme.secondary) - } - } - .toggleStyle(SwitchToggleStyle(tint: Theme.accent)) - .padding(18) - .frame(maxWidth: .infinity, alignment: .leading) - .background(Theme.card) - .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous)) - } - - private func eqChip(_ name: String, _ code: Int) -> some View { - let selected = model.eqPreset == code - return Button(action: { model.setEqualizer(code) }) { - Text(name) - .font(.system(size: 12, weight: .medium)) - .foregroundColor(selected ? .white : Theme.secondary) - .frame(maxWidth: .infinity) - .padding(.vertical, 8) - .background(selected ? Theme.accent : Theme.cardHi) - .clipShape(RoundedRectangle(cornerRadius: 9, style: .continuous)) - } - .buttonStyle(PlainButtonStyle()) - } - - private let apoOptions = ["Off", "5 min", "30 min", "1 hour", "3 hours", "When taken off"] - - private var settingsCard: some View { - VStack(alignment: .leading, spacing: 14) { - Text("Settings") - .font(.system(size: 15, weight: .semibold)) - .foregroundColor(.white) - if model.hasAdaptiveVolume { - settingToggle("Adaptive Volume", "Auto-adjust volume by surroundings", - on: model.adaptiveVolume) { model.setAdaptiveVolume($0) } - } - if model.hasSpeakToChat { - settingToggle("Speak-to-Chat", "Pause music when you talk", - on: model.speakToChat) { model.setSpeakToChat($0) } - } - if model.hasAutoPowerOff { - HStack { - VStack(alignment: .leading, spacing: 2) { - Text("Auto Power-Off").font(.system(size: 14, weight: .semibold)).foregroundColor(.white) - Text("Turn off when idle").font(.system(size: 11)).foregroundColor(Theme.secondary) - } - Spacer() - Picker("", selection: Binding( - get: { model.autoPowerOff }, - set: { model.setAutoPowerOff($0) } - )) { - ForEach(0.. Void) -> some View { - Toggle(isOn: Binding(get: { on }, set: { action($0) })) { - VStack(alignment: .leading, spacing: 2) { - Text(title).font(.system(size: 14, weight: .semibold)).foregroundColor(.white) - Text(subtitle).font(.system(size: 11)).foregroundColor(Theme.secondary) - } - } - .toggleStyle(SwitchToggleStyle(tint: Theme.accent)) - } - - // ⋯ About / device info popover. - private var aboutView: some View { - VStack(alignment: .leading, spacing: 0) { - Text(model.deviceName) - .font(.system(size: 15, weight: .bold)) - .foregroundColor(.white) - .padding(.bottom, 10) - aboutRow("Status", model.connected ? "Connected" : "Disconnected") - if model.hasDualBattery { - aboutRow("Battery L / R", "\(model.batteryLeft)% / \(model.batteryRight)%") - if model.batteryCase >= 0 { aboutRow("Case", "\(model.batteryCase)%") } - } else if model.batteryLevel >= 0 { - aboutRow("Battery", "\(model.batteryLevel)%\(model.batteryCharging ? " (charging)" : "")") - } - if !model.codec.isEmpty { aboutRow("Codec", model.codec) } - if !model.firmware.isEmpty { aboutRow("Firmware", model.firmware) } - if !model.protocolVersion.isEmpty { aboutRow("Protocol", model.protocolVersion) } - if !model.deviceMac.isEmpty { aboutRow("Bluetooth", model.deviceMac) } - Divider().background(Theme.cardHi).padding(.vertical, 10) - Text("SonyBridge · not affiliated with Sony") - .font(.system(size: 10)) - .foregroundColor(Theme.secondary.opacity(0.7)) - } - .padding(18) - .frame(width: 260) - .background(Theme.card) - } - - private func aboutRow(_ label: String, _ value: String) -> some View { - HStack { - Text(label).font(.system(size: 12)).foregroundColor(Theme.secondary) - Spacer() - Text(value).font(.system(size: 12, weight: .medium)).foregroundColor(.white) - } - .padding(.vertical, 3) - } - - // Matches the connected device name to a bundled product image (e.g. "WH-CH720N" -> "wh-ch720n"). - private func deviceImage() -> NSImage? { - let slug = model.deviceName.lowercased().replacingOccurrences(of: " ", with: "-") - return NSImage(named: slug) - } - - private func batterySymbol(_ level: Int) -> String { - switch level { - case ...15: return "battery.0" - case ...50: return "battery.25" - default: return "battery.100" - } - } -} - -// Factory so the Obj-C++ ViewController can instantiate the SwiftUI hierarchy. -@available(macOS 11.0, *) -@objc final class HeadphonesUIFactory: NSObject { - @objc static func makeViewController() -> NSViewController { - return NSHostingController(rootView: ContentView()) - } -} diff --git a/Client/macos/DeviceWatcher.swift b/Client/macos/DeviceWatcher.swift new file mode 100644 index 0000000..e0a203d --- /dev/null +++ b/Client/macos/DeviceWatcher.swift @@ -0,0 +1,38 @@ +import Foundation +import IOBluetooth + +// Reports Bluetooth devices connecting to / disconnecting from macOS, as (address, name). +final class DeviceWatcher: NSObject { + var onConnect: ((_ address: String, _ name: String) -> Void)? + var onDisconnect: ((_ address: String) -> Void)? + + private var connectNotification: IOBluetoothUserNotification? + private var disconnectNotifications: [String: IOBluetoothUserNotification] = [:] + + func start() { + connectNotification = IOBluetoothDevice.register(forConnectNotifications: self, + selector: #selector(deviceConnected(_:device:))) + for case let device as IOBluetoothDevice in IOBluetoothDevice.pairedDevices() ?? [] where device.isConnected() { + if let address = device.addressString { watchDisconnect(device, address: address) } + } + } + + @objc private func deviceConnected(_ notification: IOBluetoothUserNotification, device: IOBluetoothDevice) { + guard let address = device.addressString else { return } + watchDisconnect(device, address: address) + onConnect?(address, device.name ?? "") + } + + @objc private func deviceDisconnected(_ notification: IOBluetoothUserNotification, device: IOBluetoothDevice) { + notification.unregister() + guard let address = device.addressString else { return } + disconnectNotifications[address] = nil + onDisconnect?(address) + } + + private func watchDisconnect(_ device: IOBluetoothDevice, address: String) { + guard disconnectNotifications[address] == nil else { return } + disconnectNotifications[address] = device.register(forDisconnectNotification: self, + selector: #selector(deviceDisconnected(_:device:))) + } +} diff --git a/Client/macos/HeadphonesBridge.h b/Client/macos/HeadphonesBridge.h index dfbdd03..3019aa2 100644 --- a/Client/macos/HeadphonesBridge.h +++ b/Client/macos/HeadphonesBridge.h @@ -39,7 +39,12 @@ typedef NS_ENUM(NSInteger, SHCAmbientMode) { @property (nonatomic, readonly) NSInteger batteryCase; @property (nonatomic, readonly) NSInteger eqPreset; // raw preset byte (EQ_PRESET) @property (nonatomic, readonly) BOOL supportsEqualizer; // v2 devices only +@property (nonatomic, readonly) NSInteger equalizerBandCount; // 0 until read, then 5 or 10 +@property (nonatomic, readonly) BOOL equalizerHasClearBass; // 5-band layout +// NO while this device's equalizer write format is unverified (the WH-1000XM6's 10-band layout, spec §7). +@property (nonatomic, readonly) BOOL equalizerWritable; @property (nonatomic, readonly) NSInteger clearBass; // -10..10 +@property (nonatomic, readonly) BOOL hasDsee; // the device answered the DSEE inquiry @property (nonatomic, readonly) BOOL dsee; // DSEE / audio upsampling // Optional features (present only if the device answered the capability probe on connect). @@ -54,10 +59,26 @@ typedef NS_ENUM(NSInteger, SHCAmbientMode) { @property (nonatomic, readonly) BOOL hasAdaptiveVolume; @property (nonatomic, readonly) BOOL adaptiveVolume; -// Runs the native Bluetooth device picker (modal, main thread) and connects to the chosen device. -// completion is called on the main thread. +// Background work and sessions: every async call below captures the current connection session; once it +// ends (disconnect, or a new connection) its queued work stops before the next headphones call and its +// completion is NOT called, so a previous session can never touch the next link or overwrite the model. + +// Uses the Sony headset already connected to macOS, else runs the native Bluetooth picker (modal), then +// connects. Call on the main thread; completion runs synchronously on it, after nested run-loop pumping +// while the link opens. - (void)scanAndConnectWithCompletion:(void (^)(BOOL ok, NSString * _Nullable error))completion; +// Name heuristic for Sony headsets (WH-/WF-/WI-/MDR-/XB/LinkBuds). ++ (BOOL)looksLikeSonyHeadset:(NSString *)name NS_SWIFT_NAME(looksLikeSonyHeadset(_:)); +// Address of the first Sony headset currently connected to macOS, or nil. ++ (nullable NSString *)connectedSonyHeadsetAddress NS_SWIFT_NAME(connectedSonyHeadsetAddress()); +// YES if the device with this address is connected to macOS (its audio link is up). ++ (BOOL)isDeviceConnectedToMac:(NSString *)address NS_SWIFT_NAME(isDeviceConnectedToMac(_:)); +// Opens the control channel to a specific device, without the picker. Call on the main thread; completion +// runs synchronously on the caller's thread, after nested run-loop pumping while the link opens. +- (void)connectToAddress:(NSString *)address + completion:(void (^)(BOOL ok, NSString * _Nullable error))completion NS_SWIFT_NAME(connect(toAddress:completion:)); + - (void)disconnect; // Pushes the desired ambient/NC state to the device on a background thread; completion on main thread. @@ -66,16 +87,19 @@ typedef NS_ENUM(NSInteger, SHCAmbientMode) { focusVoice:(BOOL)focusVoice completion:(void (^)(BOOL ok, NSString * _Nullable error))completion; -// Runs the init handshake (once) then reads battery + equalizer on a background thread; completion on main. +// On a background thread: v2 devices get the init handshake + NC/ASM channel probe (once per session), then +// NC/ASM, battery, equalizer and DSEE reads - completion on main - then the optional-feature probes - +// completion on main again. v1 devices only get the NC/ASM read (completion called once). - (void)refreshStatusWithCompletion:(void (^)(void))completion; // Pushes an equalizer preset (raw EQ_PRESET byte) to the device; completion on main. - (void)setEqualizerPreset:(NSInteger)preset completion:(void (^)(BOOL ok, NSString * _Nullable error))completion; -// Current custom EQ band value (-10..10) for band 0..4. +// Current custom EQ band value (-10..10) for band 0..4 (5-band layout) or 0..9 (10-band layout). - (NSInteger)equalizerBandAtIndex:(NSInteger)index; -// Pushes manual/custom EQ (clear bass + 5 bands, each -10..10) to the device. +// Pushes manual/custom EQ (clear bass + 5 bands, each -10..10) to the device - 5-band layout only +// (equalizerWritable). - (void)setCustomEqualizerBass:(NSInteger)bass bands:(NSArray *)bands completion:(void (^)(BOOL ok, NSString * _Nullable error))completion; // Toggles DSEE / audio upsampling. @@ -85,10 +109,13 @@ typedef NS_ENUM(NSInteger, SHCAmbientMode) { - (void)setSpeakToChat:(BOOL)enabled completion:(void (^)(BOOL ok, NSString * _Nullable error))completion; - (void)setAdaptiveVolume:(BOOL)enabled completion:(void (^)(BOOL ok, NSString * _Nullable error))completion; -// Re-reads the fast-changing state (ambient/NC, level, EQ, DSEE) so changes made with the headphone's -// own button show up in the app. Called on a timer while connected. +// Re-reads the NC/ASM state only (mode, ambient level, focus on voice) so changes made with the headphone's +// own button show up in the app. Called on a timer while connected. Completion on the main thread. - (void)refreshDynamicWithCompletion:(void (^)(void))completion; +// Re-reads the battery level (v2 devices only). Completion on the main thread. +- (void)refreshBatteryWithCompletion:(void (^)(void))completion; + @end NS_ASSUME_NONNULL_END diff --git a/Client/macos/HeadphonesBridge.mm b/Client/macos/HeadphonesBridge.mm index 4f1b58d..d24da39 100644 --- a/Client/macos/HeadphonesBridge.mm +++ b/Client/macos/HeadphonesBridge.mm @@ -7,6 +7,9 @@ #import #import +#include +#include +#include #include #include "MacOSBluetoothConnector.h" #include "BluetoothWrapper.h" @@ -14,12 +17,56 @@ // RecoverableException comes in transitively via BluetoothWrapper.h -> IBluetoothConnector.h -> Exceptions.h. // (Exceptions.h isn't a project file reference, so it can't be #included directly from this directory.) +// What a background block captures: the session's Headphones object plus the bridge's session generation at +// dispatch time. One BluetoothWrapper serves the whole app lifetime, so after a disconnect a previous +// session's queued work would otherwise keep running on whatever link comes next (possibly a v1 headset, +// where the v2 battery inquiry 0x22 is POWER_OFF). Blocks call isCurrent() before every headphones call and +// stop once the session ended. +struct SHCSession { + std::shared_ptr hp; + std::shared_ptr> generation; + uint64_t token; + bool isCurrent() const { return generation->load() == token; } +}; + +// Runs a finished block's completion on the main queue, unless its session ended meanwhile: the data it +// would publish belongs to a previous connection. No caller waits on these completions. +static void SHCCompleteOnMain(SHCSession session, void (^completion)(void)) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (session.isCurrent()) completion(); + }); +} + +static void SHCFinishOnMain(SHCSession session, BOOL ok, NSString * _Nullable error, + void (^completion)(BOOL, NSString * _Nullable)) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (session.isCurrent()) completion(ok, error); + }); +} + +// Core exceptions carry English developer text ("recv timed out", "No ACK received from device", ...): log it, +// show a translated message instead. +static NSString *SHCCommandError(const std::exception &exc) { + fprintf(stderr, "[error] %s\n", exc.what()); + return NSLocalizedString(@"The headphones didn't respond.", nil); +} + +static NSString *SHCConnectionError(const std::exception &exc) { + fprintf(stderr, "[error] %s\n", exc.what()); + return NSLocalizedString(@"Couldn't open the control channel.", nil); +} + @implementation HeadphonesBridge { std::unique_ptr _bt; - std::unique_ptr _hp; + // shared_ptr: background blocks capture their own copy so a disconnect()-triggered _hp.reset() on the + // main thread can't free the object while a queued block is still mid-way through a read/write. + // One Headphones object per connection session (it also holds that session's "initialized" flag). + std::shared_ptr _hp; + // Session generation, bumped when a session ends or starts; see SHCSession. shared_ptr so blocks can + // hold it without retaining self. + std::shared_ptr> _generation; NSString *_deviceName; NSString *_deviceMac; - BOOL _initialized; // All user-initiated commands run on this SERIAL queue so quick successive taps reach the device in // order (a concurrent queue let them race and land out of order). dispatch_queue_t _cmdQueue; @@ -28,11 +75,22 @@ @implementation HeadphonesBridge { - (instancetype)init { if ((self = [super init])) { _bt = std::make_unique(std::make_unique()); - _cmdQueue = dispatch_queue_create("com.sonybridge.commands", DISPATCH_QUEUE_SERIAL); + _generation = std::make_shared>(0); + _cmdQueue = dispatch_queue_create("com.sonynotch.commands", DISPATCH_QUEUE_SERIAL); } return self; } +// Main thread only (reads _hp). +- (SHCSession)currentSession { + return SHCSession{ _hp, _generation, _generation->load() }; +} + +// Invalidates every block captured so far: they stop before their next headphones call. +- (void)bumpSession { + _generation->fetch_add(1); +} + - (BOOL)connected { return _bt && _bt->isConnected(); } @@ -103,6 +161,13 @@ - (NSInteger)clearBass { return _hp ? _hp->getClearBass() : 0; } +- (NSInteger)equalizerBandCount { return _hp ? _hp->getEqualizerBandCount() : 0; } +- (BOOL)equalizerHasClearBass { return _hp && _hp->equalizerHasClearBass(); } +// Only the 5-band + Clear Bass layout (WH-CH720N family) has a verified write format. +- (BOOL)equalizerWritable { return self.supportsEqualizer && _hp && _hp->equalizerHasClearBass(); } + +- (BOOL)hasDsee { return _hp && _hp->hasDsee(); } + - (BOOL)dsee { return _hp ? _hp->getDsee() : NO; } @@ -153,14 +218,23 @@ - (void)scanAndConnectWithCompletion:(void (^)(BOOL, NSString * _Nullable))compl } if (!device) { - completion(NO, @"No connected Sony headset found. Connect your headphones in macOS Bluetooth settings first."); + completion(NO, NSLocalizedString(@"No connected Sony headset found. Connect your headphones in macOS Bluetooth settings first.", nil)); return; } + [self connectDevice:device completion:completion]; +} + +- (void)connectDevice:(IOBluetoothDevice *)device completion:(void (^)(BOOL, NSString * _Nullable))completion { + // A connection attempt ends whatever session came before: its queued work stops before its next call, + // and no refresh can pair the new link with the old Headphones object while the link opens. + _hp.reset(); + [self bumpSession]; + try { _bt->connect([[device addressString] UTF8String]); - } catch (RecoverableException &exc) { - completion(NO, @(exc.what())); + } catch (std::exception &exc) { + completion(NO, SHCConnectionError(exc)); return; } @@ -174,127 +248,184 @@ - (void)scanAndConnectWithCompletion:(void (^)(BOOL, NSString * _Nullable))compl if (!_bt->isConnected()) { _bt->disconnect(); - completion(NO, @"Connection timed out."); + completion(NO, NSLocalizedString(@"Connection timed out.", nil)); return; } _deviceName = [device nameOrAddress]; _deviceMac = [device addressString]; - _hp = std::make_unique(*_bt); + // New session: a fresh Headphones object (not initialized yet) and a new generation. + _hp = std::make_shared(*_bt); + [self bumpSession]; completion(YES, nil); } ++ (BOOL)looksLikeSonyHeadset:(NSString *)name { + return SHCLooksLikeSonyHeadset(name); +} + ++ (nullable NSString *)connectedSonyHeadsetAddress { + for (IOBluetoothDevice *paired in [IOBluetoothDevice pairedDevices]) { + if ([paired isConnected] && SHCLooksLikeSonyHeadset([paired name])) return [paired addressString]; + } + return nil; +} + ++ (BOOL)isDeviceConnectedToMac:(NSString *)address { + IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:address]; + return device != nil && [device isConnected]; +} + +- (void)connectToAddress:(NSString *)address completion:(void (^)(BOOL, NSString * _Nullable))completion { + IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:address]; + if (!device) { + completion(NO, NSLocalizedString(@"Not connected.", nil)); + return; + } + [self connectDevice:device completion:completion]; +} + - (void)disconnect { + // First, so this session's queued work stops before its next headphones call. + [self bumpSession]; if (_bt) _bt->disconnect(); _hp.reset(); _deviceName = nil; _deviceMac = nil; - _initialized = NO; } - (void)refreshStatusWithCompletion:(void (^)(void))completion { if (!_hp || !self.connected) { completion(); return; } - Headphones *hp = _hp.get(); + SHCSession session = [self currentSession]; // CRITICAL: the init/battery/EQ inquiries below use v2 opcodes. Opcode 0x22 is BATTERY_LEVEL_REQUEST // on v2 but POWER_OFF on v1 - sending it to a v1 device (e.g. WH-1000XM4) powers the headphones off. // A v1 device still needs *some* valid handshake traffic right after connect or it drops/powers off on // its own, so read its ambient state (read-only 66 02) instead of sending nothing. + // This dispatch-time check only picks the path: the session check stops the block once this session + // ended, and Headphones re-checks the live protocol before every v2-only frame. if (_bt->getProtocolVersion() != SonyProtocolVersion::V2) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - try { hp->requestAmbientState(); } catch (std::exception &exc) {} - dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); + if (!session.isCurrent()) return; + try { session.hp->requestAmbientState(); } catch (std::exception &) {} + SHCCompleteOnMain(session, completion); }); return; } // Reads run on the global queue (not the serial command queue) so they don't block quick user taps; // per-call the connector mutex still serializes actual I/O. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + Headphones *hp = session.hp.get(); // kept alive by the block's session copy // Fast, always-supported reads first, then update the UI immediately... - try { - if (!self->_initialized) { - hp->initDevice(); - self->_initialized = YES; + // Each read is independent: one lost frame (recv timeout) must not skip the others, or a fresh + // connection stays half-initialized (no battery, no EQ, NC/ASM polled on the wrong channel). + if (!hp->isInitialized()) { + for (int attempt = 0; attempt < 2 && !hp->isInitialized(); attempt++) { + if (!session.isCurrent()) return; + try { hp->initDevice(); } catch (std::exception &) {} } - hp->requestBattery(); - hp->requestEqualizer(); - hp->requestDsee(); - } catch (std::exception &exc) {} - dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); + // Probe even if init never answered, so the NC/ASM channel is still picked (catches internally). + if (!session.isCurrent()) return; + hp->probeNcAsmInquiryType(); + } + // Current NC/ASM state, on the channel probeNcAsmInquiryType() picked. + if (!session.isCurrent()) return; + try { hp->requestAmbientState(); } catch (std::exception &) {} + if (!session.isCurrent()) return; + try { hp->requestBattery(); } catch (std::exception &) {} + if (!session.isCurrent()) return; + try { hp->requestEqualizer(); } catch (std::exception &) {} + if (!session.isCurrent()) return; + try { hp->requestDsee(); } catch (std::exception &) {} + SHCCompleteOnMain(session, completion); // ...then the optional-feature probes, which can each take a couple seconds to time out on a // device that doesn't support them. Update the UI again once they've settled. - try { hp->probeCapabilities(); } catch (std::exception &exc) {} - dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); + if (!session.isCurrent()) return; + try { hp->probeCapabilities(); } catch (std::exception &) {} + SHCCompleteOnMain(session, completion); }); } - (void)refreshDynamicWithCompletion:(void (^)(void))completion { if (!_hp || !self.connected) { completion(); return; } - Headphones *hp = _hp.get(); + SHCSession session = [self currentSession]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // The headphone's physical button only changes ambient/NC, so that's all we poll (keeps traffic low). // requestAmbientState() is protocol-aware (v2 uses 66 17, v1 uses 66 02), so this is safe on both. - try { hp->requestAmbientState(); } catch (std::exception &exc) {} - dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); + if (!session.isCurrent()) return; + try { session.hp->requestAmbientState(); } catch (std::exception &) {} + SHCCompleteOnMain(session, completion); + }); +} + +- (void)refreshBatteryWithCompletion:(void (^)(void))completion { + // CRITICAL: 0x22 is BATTERY_LEVEL_REQUEST on v2 but POWER_OFF on v1 - never send it to a v1 device. + if (!_hp || !self.connected || _bt->getProtocolVersion() != SonyProtocolVersion::V2) { completion(); return; } + SHCSession session = [self currentSession]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + if (!session.isCurrent()) return; + try { session.hp->requestBattery(); } catch (std::exception &) {} + SHCCompleteOnMain(session, completion); }); } - (void)setEqualizerPreset:(NSInteger)preset completion:(void (^)(BOOL, NSString * _Nullable))completion { if (!_hp || !self.connected) { - completion(NO, @"Not connected."); + completion(NO, NSLocalizedString(@"Not connected.", nil)); return; } // The v2 EQ SET opcode differs from v1; only issue it on confirmed v2 devices. - if (_bt->getProtocolVersion() != SonyProtocolVersion::V2) { - completion(NO, @"Equalizer control isn't supported on this device yet."); + if (!self.equalizerWritable) { + completion(NO, NSLocalizedString(@"Equalizer control isn't supported on this device yet.", nil)); return; } - Headphones *hp = _hp.get(); + SHCSession session = [self currentSession]; dispatch_async(_cmdQueue, ^{ + if (!session.isCurrent()) return; NSString *error = nil; BOOL ok = YES; try { - hp->setEqualizerPreset(static_cast((unsigned char)preset)); + session.hp->setEqualizerPreset(static_cast((unsigned char)preset)); } catch (std::exception &exc) { ok = NO; - error = @(exc.what()); + error = SHCCommandError(exc); } - dispatch_async(dispatch_get_main_queue(), ^{ - completion(ok, error); - }); + SHCFinishOnMain(session, ok, error, completion); }); } - (void)setCustomEqualizerBass:(NSInteger)bass bands:(NSArray *)bands completion:(void (^)(BOOL, NSString * _Nullable))completion { - if (!_hp || !self.connected || _bt->getProtocolVersion() != SonyProtocolVersion::V2) { - completion(NO, @"Equalizer control isn't supported on this device yet."); + if (!_hp || !self.connected || !self.equalizerWritable) { + completion(NO, NSLocalizedString(@"Equalizer control isn't supported on this device yet.", nil)); return; } std::vector cbands; for (NSNumber *n in bands) cbands.push_back((int)n.integerValue); int cbass = (int)bass; - Headphones *hp = _hp.get(); + SHCSession session = [self currentSession]; dispatch_async(_cmdQueue, ^{ + if (!session.isCurrent()) return; NSString *error = nil; BOOL ok = YES; try { - hp->setEqualizerCustom(cbass, cbands); - } catch (std::exception &exc) { ok = NO; error = @(exc.what()); } - dispatch_async(dispatch_get_main_queue(), ^{ completion(ok, error); }); + session.hp->setEqualizerCustom(cbass, cbands); + } catch (std::exception &exc) { ok = NO; error = SHCCommandError(exc); } + SHCFinishOnMain(session, ok, error, completion); }); } - (void)setDsee:(BOOL)enabled completion:(void (^)(BOOL, NSString * _Nullable))completion { if (!_hp || !self.connected || _bt->getProtocolVersion() != SonyProtocolVersion::V2) { - completion(NO, @"Not supported on this device."); + completion(NO, NSLocalizedString(@"Not supported on this device.", nil)); return; } - Headphones *hp = _hp.get(); + SHCSession session = [self currentSession]; dispatch_async(_cmdQueue, ^{ + if (!session.isCurrent()) return; NSString *error = nil; BOOL ok = YES; try { - hp->setDsee(enabled); - } catch (std::exception &exc) { ok = NO; error = @(exc.what()); } - dispatch_async(dispatch_get_main_queue(), ^{ completion(ok, error); }); + session.hp->setDsee(enabled); + } catch (std::exception &exc) { ok = NO; error = SHCCommandError(exc); } + SHCFinishOnMain(session, ok, error, completion); }); } @@ -303,7 +434,7 @@ - (void)applyMode:(SHCAmbientMode)mode focusVoice:(BOOL)focusVoice completion:(void (^)(BOOL, NSString * _Nullable))completion { if (!_hp || !self.connected) { - completion(NO, @"Not connected."); + completion(NO, NSLocalizedString(@"Not connected.", nil)); return; } @@ -323,52 +454,51 @@ - (void)applyMode:(SHCAmbientMode)mode break; } - Headphones *hp = _hp.get(); + SHCSession session = [self currentSession]; dispatch_async(_cmdQueue, ^{ + if (!session.isCurrent()) return; NSString *error = nil; BOOL ok = YES; try { - if (hp->isChanged()) hp->setChanges(); - } catch (RecoverableException &exc) { - ok = NO; - error = @(exc.what()); + if (session.hp->isChanged()) session.hp->setChanges(); } catch (std::exception &exc) { ok = NO; - error = @(exc.what()); + error = SHCCommandError(exc); } - dispatch_async(dispatch_get_main_queue(), ^{ - completion(ok, error); - }); + SHCFinishOnMain(session, ok, error, completion); }); } - (void)setAutoPowerOff:(NSInteger)index completion:(void (^)(BOOL, NSString * _Nullable))completion { - if (!_hp || !self.connected) { completion(NO, @"Not connected."); return; } - Headphones *hp = _hp.get(); + if (!_hp || !self.connected) { completion(NO, NSLocalizedString(@"Not connected.", nil)); return; } + SHCSession session = [self currentSession]; dispatch_async(_cmdQueue, ^{ + if (!session.isCurrent()) return; NSString *error = nil; BOOL ok = YES; - try { hp->setAutoPowerOff((int)index); } catch (std::exception &exc) { ok = NO; error = @(exc.what()); } - dispatch_async(dispatch_get_main_queue(), ^{ completion(ok, error); }); + try { session.hp->setAutoPowerOff((int)index); } catch (std::exception &exc) { ok = NO; error = SHCCommandError(exc); } + SHCFinishOnMain(session, ok, error, completion); }); } - (void)setSpeakToChat:(BOOL)enabled completion:(void (^)(BOOL, NSString * _Nullable))completion { - if (!_hp || !self.connected) { completion(NO, @"Not connected."); return; } - Headphones *hp = _hp.get(); + if (!_hp || !self.connected) { completion(NO, NSLocalizedString(@"Not connected.", nil)); return; } + SHCSession session = [self currentSession]; dispatch_async(_cmdQueue, ^{ + if (!session.isCurrent()) return; NSString *error = nil; BOOL ok = YES; - try { hp->setSpeakToChat(enabled); } catch (std::exception &exc) { ok = NO; error = @(exc.what()); } - dispatch_async(dispatch_get_main_queue(), ^{ completion(ok, error); }); + try { session.hp->setSpeakToChat(enabled); } catch (std::exception &exc) { ok = NO; error = SHCCommandError(exc); } + SHCFinishOnMain(session, ok, error, completion); }); } - (void)setAdaptiveVolume:(BOOL)enabled completion:(void (^)(BOOL, NSString * _Nullable))completion { - if (!_hp || !self.connected) { completion(NO, @"Not connected."); return; } - Headphones *hp = _hp.get(); + if (!_hp || !self.connected) { completion(NO, NSLocalizedString(@"Not connected.", nil)); return; } + SHCSession session = [self currentSession]; dispatch_async(_cmdQueue, ^{ + if (!session.isCurrent()) return; NSString *error = nil; BOOL ok = YES; - try { hp->setAdaptiveVolume(enabled); } catch (std::exception &exc) { ok = NO; error = @(exc.what()); } - dispatch_async(dispatch_get_main_queue(), ^{ completion(ok, error); }); + try { session.hp->setAdaptiveVolume(enabled); } catch (std::exception &exc) { ok = NO; error = SHCCommandError(exc); } + SHCFinishOnMain(session, ok, error, completion); }); } diff --git a/Client/macos/HeadphonesMenu.swift b/Client/macos/HeadphonesMenu.swift new file mode 100644 index 0000000..2d6d375 --- /dev/null +++ b/Client/macos/HeadphonesMenu.swift @@ -0,0 +1,300 @@ +import AppKit +import Combine + +// The status item's menu (spec §4). Built once; update() refreshes states, visibility and values in place, +// including while the menu is open. +final class HeadphonesMenu { + let menu = NSMenu() + private let model: HeadphonesModel + private let settings: AppSettings + private var cancellables = Set() + + private let errorItem = NSMenuItem() + private var modeItems: [(SHCAmbientMode, NSMenuItem)] = [] + private var ambientRows: [NSMenuItem] = [] // level slider + focus on voice + private let equalizerItem = NSMenuItem() + private var equalizerRowItem = NSMenuItem() + private var presetItems: [(Int, NSMenuItem)] = [] + private let equalizerNoteItem = NSMenuItem() + private var equalizerResetItem = NSMenuItem() + private var dseeItem = NSMenuItem() + private var speakToChatItem = NSMenuItem() + private var adaptiveVolumeItem = NSMenuItem() + private let autoPowerOffItem = NSMenuItem() + private var autoPowerOffItems: [NSMenuItem] = [] + private let aboutItem = NSMenuItem() + private let aboutMenu = NSMenu() + private var aboutValues: [String] = [] // cache to avoid rebuilding About menu on every slider drag + private var connectItem = NSMenuItem() + private var launchAtLoginItem = NSMenuItem() + private var autoConnectItem = NSMenuItem() + private var autoReconnectItem = NSMenuItem() + private var showNotchItem = NSMenuItem() + private let notchSizeItem = NSMenuItem() + private let notchSizeMenuDelegate = NotchSizeMenuDelegate() + + private static var presets: [(Int, String)] { + [(0x00, tr("Off")), (0x10, tr("Bright")), (0x11, tr("Excited")), (0x12, tr("Mellow")), + (0x13, tr("Relaxed")), (0x14, tr("Vocal")), (0x15, tr("Treble")), (0x16, tr("Bass")), + (0x17, tr("Speech")), (0xA0, tr("Manual"))] + } + + // Index = the bridge's auto power-off option (0=Off, 1=5 min, 2=30 min, 3=1 h, 4=3 h, 5=when taken off). + // Used for the submenu's item titles (long form). + private static var autoPowerOffOptions: [String] { + [tr("Off"), tr("5 min"), tr("30 min"), tr("1 hour"), tr("3 hours"), tr("When taken off")] + } + + // Same options, but with a short last label - used for the value shown at the right of "Auto Power-Off" + // itself, since the full "Quand le casque est retiré" collides with the title (spec §4 shows a short + // value; the submenu keeps the long label). + private static var autoPowerOffShortOptions: [String] { + var options = autoPowerOffOptions + options[options.count - 1] = tr("Taken off") + return options + } + + init(model: HeadphonesModel, settings: AppSettings) { + self.model = model + self.settings = settings + menu.autoenablesItems = false + menu.minimumWidth = MenuMetrics.width + + menu.addItem(hostingMenuItem { HeaderRow(model: model) }) + errorItem.isEnabled = false + menu.addItem(errorItem) + menu.addItem(.separator()) + addAmbientSection() + menu.addItem(.separator()) + addSoundSection() + menu.addItem(.separator()) + addAppSection() + + // objectWillChange fires before the new value is stored; hopping to the main queue reads the new state. + model.objectWillChange + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in self?.update() } + .store(in: &cancellables) + settings.objectWillChange + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in self?.update() } + .store(in: &cancellables) + update() + } + + // MARK: - Building + + private func addAmbientSection() { + menu.addItem(sectionHeader(tr("Ambient Sound Control"))) + let modes: [(SHCAmbientMode, String)] = [ + (.noiseCanceling, tr("Noise Canceling")), (.ambientSound, tr("Ambient Sound")), (.off, tr("Off")), + ] + for (mode, title) in modes { + let item = ActionMenuItem(title) { [weak model] in model?.setMode(mode) } + item.image = NSImage(systemSymbolName: StatusIcon.symbolName(for: mode), accessibilityDescription: nil) + modeItems.append((mode, item)) + menu.addItem(item) + if mode == .ambientSound { + ambientRows = [ + hostingMenuItem { AmbientLevelRow(model: model) }, + hostingMenuItem { + ToggleRow(model: model, title: tr("Focus on Voice"), indent: MenuMetrics.indent, + isOn: { $0.focusOnVoice }, set: { $0.setFocusOnVoice($1) }) + }, + ] + ambientRows.forEach { menu.addItem($0) } + } + } + } + + private func addSoundSection() { + let equalizerMenu = NSMenu() + equalizerMenu.autoenablesItems = false + equalizerMenu.minimumWidth = MenuMetrics.equalizerWidth + for (code, title) in Self.presets { + let item = ActionMenuItem(title) { [weak model] in model?.setEqualizerPreset(code) } + presetItems.append((code, item)) + equalizerMenu.addItem(item) + } + equalizerMenu.addItem(.separator()) + equalizerRowItem = hostingMenuItem(width: MenuMetrics.equalizerWidth) { EqualizerRow(model: model) } + equalizerMenu.addItem(equalizerRowItem) + equalizerNoteItem.title = tr("Equalizer changes coming soon for this model") + equalizerNoteItem.isEnabled = false + equalizerMenu.addItem(equalizerNoteItem) + equalizerResetItem = ActionMenuItem(tr("Reset")) { [weak model] in model?.resetEqualizer() } + equalizerMenu.addItem(equalizerResetItem) + equalizerItem.submenu = equalizerMenu + menu.addItem(equalizerItem) + + dseeItem = hostingMenuItem { + ToggleRow(model: model, title: tr("DSEE"), isOn: { $0.dsee }, set: { $0.setDsee($1) }) + } + speakToChatItem = hostingMenuItem { + ToggleRow(model: model, title: tr("Speak-to-Chat"), isOn: { $0.speakToChat }, set: { $0.setSpeakToChat($1) }) + } + adaptiveVolumeItem = hostingMenuItem { + ToggleRow(model: model, title: tr("Adaptive Volume"), isOn: { $0.adaptiveVolume }, set: { $0.setAdaptiveVolume($1) }) + } + for item in [dseeItem, speakToChatItem, adaptiveVolumeItem] { menu.addItem(item) } + + let autoPowerOffMenu = NSMenu() + autoPowerOffMenu.autoenablesItems = false + for (index, title) in Self.autoPowerOffOptions.enumerated() { + let item = ActionMenuItem(title) { [weak model] in model?.setAutoPowerOff(index) } + autoPowerOffItems.append(item) + autoPowerOffMenu.addItem(item) + } + autoPowerOffItem.submenu = autoPowerOffMenu + menu.addItem(autoPowerOffItem) + } + + private func addAppSection() { + aboutItem.title = tr("About the Headphones") + aboutMenu.autoenablesItems = false + aboutItem.submenu = aboutMenu + menu.addItem(aboutItem) + let optionsMenu = NSMenu() + optionsMenu.autoenablesItems = false + launchAtLoginItem = ActionMenuItem(tr("Launch at Login")) { [weak self] in self?.toggleLaunchAtLogin() } + autoConnectItem = ActionMenuItem(tr("Connect Automatically")) { [weak settings] in settings?.autoConnect.toggle() } + autoReconnectItem = ActionMenuItem(tr("Reconnect Automatically")) { [weak settings] in settings?.autoReconnect.toggle() } + showNotchItem = ActionMenuItem(tr("Show Notch")) { [weak settings] in settings?.showNotch.toggle() } + for item in [launchAtLoginItem, autoConnectItem, autoReconnectItem, showNotchItem] { optionsMenu.addItem(item) } + optionsMenu.addItem(makeNotchSizeItem()) + let optionsItem = NSMenuItem(title: tr("SonyNotch Options"), action: nil, keyEquivalent: "") + optionsItem.submenu = optionsMenu + menu.addItem(optionsItem) + connectItem = ActionMenuItem(tr("Connect…")) { [weak self] in self?.toggleConnection() } + menu.addItem(connectItem) + menu.addItem(.separator()) + menu.addItem(ActionMenuItem(tr("Quit SonyNotch"), key: "q") { NSApp.terminate(nil) }) + } + + // MARK: - Updating + + private func update() { + let connected = model.connected + + errorItem.isHidden = model.errorMessage == nil + errorItem.title = "⚠︎ " + (model.errorMessage ?? "") + + for (mode, item) in modeItems { + item.state = connected && model.mode == mode ? .on : .off + item.isEnabled = connected + } + ambientRows.forEach { $0.isHidden = model.mode != .ambientSound } + + equalizerItem.isHidden = !model.supportsEqualizer + equalizerItem.isEnabled = connected + equalizerItem.attributedTitle = titleWithValue(tr("Equalizer"), Self.presetName(model.eqPreset)) + for (code, item) in presetItems { + item.state = model.eqPreset == code ? .on : .off + item.isEnabled = connected && model.equalizerWritable + } + equalizerNoteItem.isHidden = model.equalizerWritable || model.eqBands.isEmpty + equalizerRowItem.isHidden = model.eqBands.isEmpty + equalizerResetItem.isEnabled = connected && model.equalizerWritable && model.eqPreset == 0xA0 + + dseeItem.isHidden = !model.hasDsee + speakToChatItem.isHidden = !model.hasSpeakToChat + adaptiveVolumeItem.isHidden = !model.hasAdaptiveVolume + + let shortOptions = Self.autoPowerOffShortOptions + autoPowerOffItem.isHidden = !model.hasAutoPowerOff + autoPowerOffItem.isEnabled = connected + autoPowerOffItem.attributedTitle = titleWithValue( + tr("Auto Power-Off"), + shortOptions.indices.contains(model.autoPowerOff) ? shortOptions[model.autoPowerOff] : "") + for (index, item) in autoPowerOffItems.enumerated() { + item.state = index == model.autoPowerOff ? .on : .off + } + + updateAbout() + aboutItem.isEnabled = connected + + switch model.connectionState { + case .connected: connectItem.title = tr("Disconnect") + case .connecting: connectItem.title = tr("Connecting…") + case .disconnected: connectItem.title = tr("Connect…") + } + connectItem.isEnabled = model.connectionState != .connecting + + launchAtLoginItem.state = settings.launchAtLogin ? .on : .off + autoConnectItem.state = settings.autoConnect ? .on : .off + autoReconnectItem.state = settings.autoReconnect ? .on : .off + showNotchItem.state = settings.showNotch ? .on : .off + notchSizeItem.isEnabled = settings.showNotch + } + + // Options › Notch Size: sliders applied live, the notch staying open as a preview while the submenu is open. + private func makeNotchSizeItem() -> NSMenuItem { + let sizeMenu = NSMenu() + sizeMenu.autoenablesItems = false + notchSizeMenuDelegate.settings = settings + sizeMenu.delegate = notchSizeMenuDelegate + let points: (Double) -> String = { String(Int($0.rounded())) } + let percent: (Double) -> String = { "\(Int(($0 * 100).rounded())) %" } + let rows: [(String, ReferenceWritableKeyPath, ClosedRange, (Double) -> String)] = [ + (tr("Open Width"), \.notchWidth, NotchLayout.widthRange, points), + (tr("Open Height"), \.notchHeight, NotchLayout.heightRange, points), + (tr("Closed Width"), \.notchSideWidth, NotchLayout.sideRange, points), + (tr("Closed Artwork"), \.notchArtwork, NotchLayout.artworkRange, points), + (tr("Text Size"), \.notchZoom, NotchLayout.zoomRange, percent), + ] + for (title, keyPath, range, format) in rows { + sizeMenu.addItem(hostingMenuItem(width: MenuMetrics.width + 40) { + NotchSizeRow(settings: settings, title: title, keyPath: keyPath, range: range, format: format) + }) + } + sizeMenu.addItem(.separator()) + sizeMenu.addItem(ActionMenuItem(tr("Reset Size")) { [weak settings] in settings?.resetNotchSize() }) + notchSizeItem.title = tr("Notch Size") + notchSizeItem.submenu = sizeMenu + return notchSizeItem + } + + private func updateAbout() { + // update() runs on every model change (slider drags included); rebuild only when a value changed. + let values = [model.firmware, model.codec, model.protocolVersion, model.deviceMac] + guard values != aboutValues else { return } + aboutValues = values + + aboutMenu.removeAllItems() + let rows: [(String, String)] = [ + (tr("Firmware"), model.firmware), (tr("Codec"), model.codec), + (tr("Protocol"), model.protocolVersion), (tr("Bluetooth"), model.deviceMac), + ] + for (title, value) in rows where !value.isEmpty { + let item = NSMenuItem() + item.attributedTitle = titleWithValue(title, value) + item.isEnabled = false + aboutMenu.addItem(item) + } + } + + private static func presetName(_ code: Int) -> String { + presets.first { $0.0 == code }?.1 ?? tr("Custom") + } + + private func toggleLaunchAtLogin() { + if let error = settings.setLaunchAtLogin(!settings.launchAtLogin) { model.showError(error) } + } + + private func toggleConnection() { + if model.connected { + model.disconnect() + } else { + NSApp.activate(ignoringOtherApps: true) // the fallback Bluetooth picker is a modal window + model.connect() + } + } +} + +// Opens the notch as a live preview while the Notch Size submenu is open. +private final class NotchSizeMenuDelegate: NSObject, NSMenuDelegate { + weak var settings: AppSettings? + + func menuWillOpen(_ menu: NSMenu) { settings?.notchPreviewing = true } + func menuDidClose(_ menu: NSMenu) { settings?.notchPreviewing = false } +} diff --git a/Client/macos/HeadphonesModel.swift b/Client/macos/HeadphonesModel.swift index cda475a..e815664 100644 --- a/Client/macos/HeadphonesModel.swift +++ b/Client/macos/HeadphonesModel.swift @@ -1,227 +1,353 @@ -// -// HeadphonesModel.swift -// Observable view model wrapping the Obj-C++ HeadphonesBridge for SwiftUI. -// - import Foundation import Combine +enum ConnectionState { + case disconnected, connecting, connected +} + +// Observable state of the headphones and the actions the menu triggers. Wraps the Obj-C++ HeadphonesBridge. final class HeadphonesModel: ObservableObject { + private enum PolledSetting { case ambient } + private let bridge = HeadphonesBridge() - @Published var connected = false - @Published var connecting = false - @Published var deviceName = "" - @Published var supportsVpt = false - @Published var maxAmbientLevel = 20 - - @Published var mode: SHCAmbientMode = .off - @Published var ambientLevel = 10 - @Published var focusOnVoice = false - @Published var focusOnVoiceAvailable = false - - @Published var batteryLevel = -1 - @Published var batteryCharging = false - @Published var hasDualBattery = false - @Published var batteryLeft = -1 - @Published var batteryRight = -1 - @Published var batteryCase = -1 - @Published var eqPreset = 0 - @Published var supportsEqualizer = false - @Published var eqBands = [0, 0, 0, 0, 0] - @Published var clearBass = 0 - @Published var dsee = false - - @Published var hasAutoPowerOff = false - @Published var autoPowerOff = 0 - @Published var firmware = "" - @Published var codec = "" - @Published var hasSpeakToChat = false - @Published var speakToChat = false - @Published var hasAdaptiveVolume = false - @Published var adaptiveVolume = false - @Published var deviceMac = "" - @Published var protocolVersion = "" - - @Published var errorMessage: String? - - private var pollTimer: Timer? - private var dynamicTimer: Timer? + @Published private(set) var connectionState: ConnectionState = .disconnected + var connected: Bool { connectionState == .connected } + + // Kept after a disconnect so the header still names the last headset. + @Published private(set) var deviceName = "" + @Published private(set) var deviceMac = "" + @Published private(set) var protocolVersion = "" + @Published private(set) var firmware = "" + @Published private(set) var codec = "" + @Published private(set) var maxAmbientLevel = 20 + + @Published private(set) var mode: SHCAmbientMode = .off + @Published private(set) var ambientLevel = 10 + @Published private(set) var focusOnVoice = false + + @Published private(set) var batteryLevel = -1 + @Published private(set) var batteryCharging = false + @Published private(set) var hasDualBattery = false + @Published private(set) var batteryLeft = -1 + @Published private(set) var batteryRight = -1 + @Published private(set) var batteryCase = -1 + + @Published private(set) var supportsEqualizer = false + @Published private(set) var equalizerWritable = false + @Published private(set) var eqPreset = 0 + @Published private(set) var eqBands: [Int] = [] + @Published private(set) var eqHasClearBass = false + @Published private(set) var clearBass = 0 + @Published private(set) var hasDsee = false + @Published private(set) var dsee = false + + @Published private(set) var hasAutoPowerOff = false + @Published private(set) var autoPowerOff = 0 + @Published private(set) var hasSpeakToChat = false + @Published private(set) var speakToChat = false + @Published private(set) var hasAdaptiveVolume = false + @Published private(set) var adaptiveVolume = false + + // Last error from a user action; cleared by the next successful one. + @Published private(set) var errorMessage: String? + + private var timers: [Timer] = [] + private var pollGuard = PollGuard() + private var levelThrottle = SendThrottle() + private var eqThrottle = SendThrottle() + + // Set by AppDelegate; nil means "no automatic behaviour". + var settings: AppSettings? + private var reconnectPolicy = ReconnectPolicy() + private var reconnectTimer: Timer? + private var reconnectAddress: String? + private var userDisconnected = false // after "Déconnecter": no auto-reconnect until the headset reconnects to macOS + + // MARK: - Connection + // User-initiated: uses the already-connected Sony headset, else the macOS Bluetooth picker. func connect() { - connecting = true + userDisconnected = false + cancelReconnect() + connectionState = .connecting errorMessage = nil - // Defer so SwiftUI can render the "Connecting…" state before the modal picker blocks the main thread. + // Defer so the menu can show "Connecting…" before a modal picker blocks the main thread. DispatchQueue.main.async { self.bridge.scanAndConnect { ok, error in - self.connecting = false - if ok { - self.syncFromBridge() - self.startWatchingConnection() - self.refreshStatus() - self.startDynamicPolling() - } else if let error = error { - self.errorMessage = error - } + self.handleConnectResult(ok: ok, error: error, userInitiated: true) } } } - func refreshStatus() { - bridge.refreshStatus { - self.batteryLevel = self.bridge.batteryLevel - self.batteryCharging = self.bridge.batteryCharging - self.hasDualBattery = self.bridge.hasDualBattery - self.batteryLeft = self.bridge.batteryLeft - self.batteryRight = self.bridge.batteryRight - self.batteryCase = self.bridge.batteryCase - self.eqPreset = self.bridge.eqPreset - self.clearBass = self.bridge.clearBass - self.dsee = self.bridge.dsee - self.eqBands = (0..<5).map { self.bridge.equalizerBand(at: $0) } - self.hasAutoPowerOff = self.bridge.hasAutoPowerOff - self.autoPowerOff = self.bridge.autoPowerOff - self.firmware = self.bridge.firmware ?? "" - self.codec = self.bridge.codec ?? "" - self.hasSpeakToChat = self.bridge.hasSpeakToChat - self.speakToChat = self.bridge.speakToChat - self.hasAdaptiveVolume = self.bridge.hasAdaptiveVolume - self.adaptiveVolume = self.bridge.adaptiveVolume - } - } - - func setAutoPowerOff(_ index: Int) { - autoPowerOff = index - errorMessage = nil - bridge.setAutoPowerOff(index) { ok, error in if !ok, let e = error { self.errorMessage = e } } - } - - func setSpeakToChat(_ on: Bool) { - speakToChat = on - errorMessage = nil - bridge.setSpeakToChat(on) { ok, error in if !ok, let e = error { self.errorMessage = e } } + func disconnect() { + userDisconnected = true + cancelReconnect() + stopTimers() + bridge.disconnect() + connectionState = .disconnected } - func setAdaptiveVolume(_ on: Bool) { - adaptiveVolume = on - errorMessage = nil - bridge.setAdaptiveVolume(on) { ok, error in if !ok, let e = error { self.errorMessage = e } } - } - - // Poll the button-changeable state so the app stays in sync when you use the headphone's own controls. - private func startDynamicPolling() { - stopDynamicPolling() - dynamicTimer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { [weak self] _ in - guard let self = self, self.connected else { return } - self.bridge.refreshDynamic { - self.mode = self.bridge.mode - let level = self.bridge.ambientLevel - if level > 0 { self.ambientLevel = level } - self.eqPreset = self.bridge.eqPreset - self.clearBass = self.bridge.clearBass - self.dsee = self.bridge.dsee - self.eqBands = (0..<5).map { self.bridge.equalizerBand(at: $0) } + func handleConnectResult(ok: Bool, error: String?, userInitiated: Bool) { + guard ok else { + connectionState = .disconnected + if userInitiated, let error = error { errorMessage = error } + if !userInitiated && reconnectAddress != nil { + // Only keep retrying while the option is still on; the user may have turned it off meanwhile. + if settings?.autoReconnect == true { scheduleReconnect() } else { cancelReconnect() } } + return } + cancelReconnect() + connectionState = .connected + errorMessage = nil // a failed manual attempt's error must not stay under a "Connected" header + syncFromBridge() + settings?.lastDeviceAddress = deviceMac + bridge.refreshStatus { [weak self] in self?.syncFromBridge() } // called after reads, then after probes + startTimers() } - private func stopDynamicPolling() { - dynamicTimer?.invalidate() - dynamicTimer = nil + // The control link dropped on its own (idle power-save): retry while the headset is still connected to macOS. + func linkLost() { + stopTimers() + bridge.disconnect() // resets sequence numbers and buffers for the next connection + connectionState = .disconnected + guard settings?.autoReconnect == true, !userDisconnected, !deviceMac.isEmpty else { return } + reconnectAddress = deviceMac + scheduleReconnect() } - func setEqualizer(_ preset: Int) { - eqPreset = preset - errorMessage = nil - bridge.setEqualizerPreset(preset) { ok, error in - if !ok, let error = error { self.errorMessage = error } + // MARK: - Automatic connection + + // Not user-initiated: failures stay silent (normal while the headset sleeps). + func autoConnect(toAddress address: String) { + guard connectionState == .disconnected else { return } + // With Reconnect Automatically on, a failed attempt (launch, DeviceWatcher) is retried by the failure + // path's scheduleReconnect() while the headset stays connected to macOS. + if settings?.autoReconnect == true { reconnectAddress = address } + connectionState = .connecting + bridge.connect(toAddress: address) { ok, error in + self.handleConnectResult(ok: ok, error: error, userInitiated: false) } } - // Manual EQ (preset byte 0xA0 = 160). Called as the user drags a band or clear-bass slider. - func applyCustomEq() { - eqPreset = 0xA0 - errorMessage = nil - bridge.setCustomEqualizerBass(clearBass, bands: eqBands.map { NSNumber(value: $0) }) { ok, error in - if !ok, let error = error { self.errorMessage = error } + // At launch: the last headset if macOS has it connected, else any connected Sony headset. + func autoConnectOnLaunch() { + let remembered = settings?.lastDeviceAddress.flatMap { HeadphonesBridge.isDeviceConnectedToMac($0) ? $0 : nil } + if let address = remembered ?? HeadphonesBridge.connectedSonyHeadsetAddress() { + autoConnect(toAddress: address) } } - func setDsee(_ on: Bool) { - dsee = on - errorMessage = nil - bridge.setDsee(on) { ok, error in - if !ok, let error = error { self.errorMessage = error } + // DeviceWatcher: a device just connected to macOS. + func headsetConnectedToMac(address: String, name: String) { + guard settings?.autoConnect == true, HeadphonesBridge.looksLikeSonyHeadset(name), + connectionState == .disconnected else { return } + userDisconnected = false + cancelReconnect() + // Give the audio link ~2 s to settle before opening the control channel. + DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in + guard let self = self else { return } + // The option or the device's own connection may have changed during the delay; re-check both. + guard self.settings?.autoConnect == true, HeadphonesBridge.isDeviceConnectedToMac(address) else { return } + self.autoConnect(toAddress: address) } } - func disconnect() { - stopWatchingConnection() - stopDynamicPolling() - bridge.disconnect() - connected = false - deviceName = "" + // DeviceWatcher: a device left macOS; stop retrying it (headsetConnectedToMac takes over when it's back). + func headsetDisconnectedFromMac(address: String) { + if address == reconnectAddress { cancelReconnect() } + } + + func cancelReconnect() { + reconnectTimer?.invalidate() + reconnectTimer = nil + reconnectAddress = nil + reconnectPolicy.reset() } - // The headset can drop the RFCOMM link on its own (idle power-save). Poll so the UI reflects reality - // instead of showing a stale "Connected" state. - private func startWatchingConnection() { - stopWatchingConnection() - pollTimer = Timer.scheduledTimer(withTimeInterval: 1.5, repeats: true) { [weak self] _ in + private func scheduleReconnect() { + guard let address = reconnectAddress else { return } + reconnectTimer?.invalidate() + let timer = Timer(timeInterval: reconnectPolicy.nextDelay(), repeats: false) { [weak self] _ in guard let self = self else { return } - if self.connected && !self.bridge.connected { - self.connected = false - self.deviceName = "" - self.errorMessage = "Headphones disconnected." - self.stopWatchingConnection() - self.stopDynamicPolling() - } + // The user may have turned the option off while this attempt was pending. + guard self.settings?.autoReconnect == true else { self.cancelReconnect(); return } + guard HeadphonesBridge.isDeviceConnectedToMac(address) else { self.cancelReconnect(); return } + self.autoConnect(toAddress: address) } + RunLoop.main.add(timer, forMode: .common) + reconnectTimer = timer } - private func stopWatchingConnection() { - pollTimer?.invalidate() - pollTimer = nil - } + // MARK: - Actions func setMode(_ newMode: SHCAmbientMode) { mode = newMode - pushState() + pollGuard.userChanged(.ambient) + pushAmbient() } - func setLevel(_ level: Int) { + func setLevel(_ level: Int, final: Bool) { ambientLevel = level - if mode == .ambientSound { pushState() } + pollGuard.userChanged(.ambient) + if mode == .ambientSound && levelThrottle.shouldSend(final: final) { pushAmbient() } } func setFocusOnVoice(_ on: Bool) { focusOnVoice = on - pushState() + pollGuard.userChanged(.ambient) + pushAmbient() } - private func pushState() { - errorMessage = nil - bridge.applyMode(mode, level: ambientLevel, focusVoice: focusOnVoice) { ok, error in - if ok { - self.syncFromBridge() - } else if let error = error { - self.errorMessage = error - } + func setEqualizerPreset(_ preset: Int) { + eqPreset = preset + bridge.setEqualizerPreset(preset) { [weak self] ok, error in self?.finish(ok, error) } + } + + func setEqualizerBand(_ index: Int, value: Int, final: Bool) { + guard eqBands.indices.contains(index) else { return } + eqBands[index] = value + eqPreset = 0xA0 + if eqThrottle.shouldSend(final: final) { pushCustomEqualizer() } + } + + func setClearBass(_ value: Int, final: Bool) { + clearBass = value + eqPreset = 0xA0 + if eqThrottle.shouldSend(final: final) { pushCustomEqualizer() } + } + + func resetEqualizer() { + eqBands = Array(repeating: 0, count: eqBands.count) + clearBass = 0 + eqPreset = 0xA0 + pushCustomEqualizer() + } + + func setDsee(_ on: Bool) { + dsee = on + bridge.setDsee(on) { [weak self] ok, error in self?.finish(ok, error) } + } + + func setAutoPowerOff(_ index: Int) { + autoPowerOff = index + bridge.setAutoPowerOff(index) { [weak self] ok, error in self?.finish(ok, error) } + } + + func setSpeakToChat(_ on: Bool) { + speakToChat = on + bridge.setSpeakToChat(on) { [weak self] ok, error in self?.finish(ok, error) } + } + + func setAdaptiveVolume(_ on: Bool) { + adaptiveVolume = on + bridge.setAdaptiveVolume(on) { [weak self] ok, error in self?.finish(ok, error) } + } + + func showError(_ message: String) { + errorMessage = message + } + + private func pushAmbient() { + bridge.applyMode(mode, level: ambientLevel, focusVoice: focusOnVoice) { [weak self] ok, error in + self?.finish(ok, error) } } + private func pushCustomEqualizer() { + bridge.setCustomEqualizerBass(clearBass, bands: eqBands.map { NSNumber(value: $0) }) { [weak self] ok, error in + self?.finish(ok, error) + } + } + + private func finish(_ ok: Bool, _ error: String?) { + errorMessage = ok ? nil : error + } + + // MARK: - Polling + + private func startTimers() { + stopTimers() + timers = [ + repeating(every: 1.5) { [weak self] in self?.checkLink() }, + repeating(every: 2) { [weak self] in self?.pollAmbient() }, + repeating(every: 60) { [weak self] in self?.pollBattery() }, + ] + } + + private func stopTimers() { + timers.forEach { $0.invalidate() } + timers = [] + } + + // Added in .common mode so they keep firing while the menu is open (menus run the event-tracking mode). + private func repeating(every interval: TimeInterval, _ block: @escaping () -> Void) -> Timer { + let timer = Timer(timeInterval: interval, repeats: true) { _ in block() } + RunLoop.main.add(timer, forMode: .common) + return timer + } + + private func checkLink() { + if connected && !bridge.connected { linkLost() } + } + + // Follows the headset's own NC button, unless the user just changed the mode from the menu. + private func pollAmbient() { + guard connected, pollGuard.shouldAcceptPoll(for: .ambient) else { return } + bridge.refreshDynamic { [weak self] in + guard let self = self, self.pollGuard.shouldAcceptPoll(for: .ambient) else { return } + self.readAmbientFromBridge() + } + } + + private func pollBattery() { + guard connected else { return } + bridge.refreshBattery { [weak self] in self?.readBatteryFromBridge() } + } + + // MARK: - Reading the bridge + private func syncFromBridge() { - connected = bridge.connected - deviceName = bridge.deviceName ?? "" - deviceMac = bridge.deviceMac ?? "" + deviceName = bridge.deviceName ?? deviceName + deviceMac = bridge.deviceMac ?? deviceMac protocolVersion = bridge.protocolVersionString ?? "" - supportsVpt = bridge.supportsVpt - supportsEqualizer = bridge.supportsEqualizer maxAmbientLevel = bridge.maxAmbientLevel + // refreshStatus calls this twice (the second ~12 s after connect): don't undo a mode change the user + // made meanwhile. + if pollGuard.shouldAcceptPoll(for: .ambient) { readAmbientFromBridge() } + readBatteryFromBridge() + supportsEqualizer = bridge.supportsEqualizer + equalizerWritable = bridge.equalizerWritable + eqPreset = bridge.eqPreset + eqHasClearBass = bridge.equalizerHasClearBass + clearBass = bridge.clearBass + eqBands = (0.. 0 { ambientLevel = level } focusOnVoice = bridge.focusOnVoice - focusOnVoiceAvailable = bridge.focusOnVoiceAvailable + } + + private func readBatteryFromBridge() { + batteryLevel = bridge.batteryLevel + batteryCharging = bridge.batteryCharging + hasDualBattery = bridge.hasDualBattery + batteryLeft = bridge.batteryLeft + batteryRight = bridge.batteryRight + batteryCase = bridge.batteryCase } } diff --git a/Client/macos/Localization.swift b/Client/macos/Localization.swift new file mode 100644 index 0000000..93336f3 --- /dev/null +++ b/Client/macos/Localization.swift @@ -0,0 +1,6 @@ +import Foundation + +// Looks up a UI string in Localizable.strings. Every user-facing string goes through this (checked by make test). +func tr(_ key: String) -> String { + NSLocalizedString(key, comment: "") +} diff --git a/Client/macos/MacOSBluetoothConnector.h b/Client/macos/MacOSBluetoothConnector.h index 186b06a..ea7c7f7 100644 --- a/Client/macos/MacOSBluetoothConnector.h +++ b/Client/macos/MacOSBluetoothConnector.h @@ -22,6 +22,8 @@ class MacOSBluetoothConnector final : public IBluetoothConnector virtual void disconnect() noexcept; virtual bool isConnected() noexcept; virtual void closeConnection(); + // Called from the channel-closed callback, on the connector thread: stops that thread's loop without joining it. + void markClosed() noexcept; virtual SonyProtocolVersion getProtocolVersion() noexcept; virtual std::vector getConnectedDevices() noexcept(false); @@ -36,7 +38,7 @@ class MacOSBluetoothConnector final : public IBluetoothConnector SonyProtocolVersion protocolVersion = SonyProtocolVersion::V1; private: - void *rfcommDevice; - void *rfcommchannel; + void *rfcommDevice = nullptr; + void *rfcommchannel = nullptr; std::thread uthread; }; diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index bd2db62..3a869be 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -6,10 +6,7 @@ } MacOSBluetoothConnector::~MacOSBluetoothConnector() { - // onclose event - if (isConnected()){ - disconnect(); - } + disconnect(); } @interface AsyncCommDelegate : NSObject { @@ -24,7 +21,7 @@ - (void)rfcommChannelClosed:(IOBluetoothRFCOMMChannel *)rfcommChannel{ #ifdef SHC_DEBUG_PROTOCOL fprintf(stderr, "[connect] rfcommChannelClosed\n"); #endif - delegateCPP->disconnect(); + delegateCPP->markClosed(); } #ifdef SHC_DEBUG_PROTOCOL @@ -148,6 +145,13 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) lk.unlock(); } void MacOSBluetoothConnector::connect(const std::string& addrStr){ + // A previous link's thread has stopped (markClosed) but may not have been joined yet. + if (uthread.joinable()) uthread.join(); + { + // Bytes the previous link received but nobody read must not be replayed into the new session. + std::lock_guard g(receiveDataMutex); + receivedBytes.clear(); + } // convert mac address to nsstring NSString *addressNSString = [NSString stringWithCString:addrStr.c_str() encoding:[NSString defaultCStringEncoding]]; // get device based on mac address @@ -223,17 +227,23 @@ static void _debugHexDump(const char* label, const char* buf, size_t length) return res; } -void MacOSBluetoothConnector::disconnect() noexcept +void MacOSBluetoothConnector::markClosed() noexcept { - // close connection - closeConnection(); running = false; - // notify the other thread that we are done disconnecting disconnectionConditionVariable.notify_all(); - // wait for the thread to finish - uthread.join(); +} + +void MacOSBluetoothConnector::disconnect() noexcept +{ + closeConnection(); + markClosed(); + // Never join from the connector thread itself (the channel-closed callback runs there). + if (uthread.joinable() && uthread.get_id() != std::this_thread::get_id()) { + uthread.join(); + } } void MacOSBluetoothConnector::closeConnection() { + if (!rfcommchannel) return; // get the channel IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; [chan setDelegate: nil]; diff --git a/Client/macos/Main.storyboard b/Client/macos/Main.storyboard deleted file mode 100644 index 6241e88..0000000 --- a/Client/macos/Main.storyboard +++ /dev/null @@ -1,332 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! This product is not affiliated with Sony. Use at your own risk. ! -Source: https://github.com/Plutoberth/SonyHeadphonesClient - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Client/macos/MenuRows/AmbientLevelRow.swift b/Client/macos/MenuRows/AmbientLevelRow.swift new file mode 100644 index 0000000..4e062b7 --- /dev/null +++ b/Client/macos/MenuRows/AmbientLevelRow.swift @@ -0,0 +1,29 @@ +import SwiftUI + +// Ambient Sound level slider (1…max), shown under "Son ambiant". +struct AmbientLevelRow: View { + @ObservedObject var model: HeadphonesModel + + var body: some View { + HStack(spacing: 8) { + Slider( + value: Binding(get: { Double(model.ambientLevel) }, + set: { model.setLevel(Int($0.rounded()), final: false) }), + in: 1...Double(max(model.maxAmbientLevel, 2)), + step: 1, + onEditingChanged: { editing in + if !editing { model.setLevel(model.ambientLevel, final: true) } + } + ) + .controlSize(.small) + Text(verbatim: "\(model.ambientLevel)") + .font(.system(size: 11, weight: .medium).monospacedDigit()) + .foregroundColor(.secondary) + .frame(width: 20, alignment: .trailing) + } + .padding(.leading, MenuMetrics.indent) + .padding(.trailing, MenuMetrics.trailing) + .padding(.vertical, 2) + .disabled(!model.connected) + } +} diff --git a/Client/macos/MenuRows/EqualizerRow.swift b/Client/macos/MenuRows/EqualizerRow.swift new file mode 100644 index 0000000..7563c7a --- /dev/null +++ b/Client/macos/MenuRows/EqualizerRow.swift @@ -0,0 +1,82 @@ +import AppKit +import SwiftUI + +// Manual equalizer: 10 vertical sliders (WH-1000XM6) or Clear Bass + 5 (older models). Active only on "Manual" +// and when the device's write format is verified (model.equalizerWritable). +struct EqualizerRow: View { + @ObservedObject var model: HeadphonesModel + + private static let labels5 = ["400", "1k", "2.5k", "6.3k", "16k"] + private static let labels10 = ["31", "63", "125", "250", "500", "1k", "2k", "4k", "8k", "16k"] + + private var editable: Bool { model.connected && model.equalizerWritable && model.eqPreset == 0xA0 } + private var labels: [String] { model.eqBands.count == 10 ? Self.labels10 : Self.labels5 } + + var body: some View { + HStack(alignment: .top, spacing: 0) { + if model.eqHasClearBass { + band(tr("Clear Bass"), value: model.clearBass) { model.setClearBass($0, final: $1) } + } + ForEach(Array(model.eqBands.enumerated()), id: \.offset) { index, value in + band(index < labels.count ? labels[index] : "", value: value) { + model.setEqualizerBand(index, value: $0, final: $1) + } + } + } + .padding(.leading, MenuMetrics.leading) + .padding(.trailing, MenuMetrics.trailing) + .padding(.vertical, 6) + .frame(height: MenuMetrics.equalizerHeight) + } + + private func band(_ label: String, value: Int, onChange: @escaping (Int, Bool) -> Void) -> some View { + VStack(spacing: 3) { + VerticalBandSlider(value: value, enabled: editable, onChange: onChange) + .frame(width: 20, height: 72) + Text(verbatim: label) + .font(.system(size: 9)) + .foregroundColor(.secondary) + .lineLimit(1) + } + .frame(maxWidth: .infinity) + } +} + +// A native vertical NSSlider in -10…10. onChange(value, final): final is true on mouse-up. +struct VerticalBandSlider: NSViewRepresentable { + let value: Int + let enabled: Bool + let onChange: (Int, Bool) -> Void + + func makeCoordinator() -> Coordinator { + Coordinator(onChange: onChange) + } + + func makeNSView(context: Context) -> NSSlider { + let slider = NSSlider(value: Double(value), minValue: -10, maxValue: 10, + target: context.coordinator, action: #selector(Coordinator.changed(_:))) + slider.isVertical = true + slider.isContinuous = true + slider.controlSize = .small + return slider + } + + func updateNSView(_ slider: NSSlider, context: Context) { + context.coordinator.onChange = onChange + if Int(slider.doubleValue.rounded()) != value { slider.doubleValue = Double(value) } + slider.isEnabled = enabled + } + + final class Coordinator: NSObject { + var onChange: (Int, Bool) -> Void + + init(onChange: @escaping (Int, Bool) -> Void) { + self.onChange = onChange + } + + @objc func changed(_ sender: NSSlider) { + let final = NSApp.currentEvent?.type == .leftMouseUp + onChange(Int(sender.doubleValue.rounded()), final) + } + } +} diff --git a/Client/macos/MenuRows/HeaderRow.swift b/Client/macos/MenuRows/HeaderRow.swift new file mode 100644 index 0000000..8ef0951 --- /dev/null +++ b/Client/macos/MenuRows/HeaderRow.swift @@ -0,0 +1,70 @@ +import SwiftUI + +// Menu header: headset name, connection state + codec, battery. +struct HeaderRow: View { + @ObservedObject var model: HeadphonesModel + + var body: some View { + HStack(alignment: .center, spacing: 8) { + VStack(alignment: .leading, spacing: 1) { + Text(model.deviceName.isEmpty ? "SonyNotch" : model.deviceName) + .font(.system(size: 13, weight: .semibold)) + Text(statusLine) + .font(.system(size: 11)) + .foregroundColor(.secondary) + } + Spacer(minLength: 8) + if model.connected { battery } + } + .padding(.leading, MenuMetrics.leading) + .padding(.trailing, MenuMetrics.trailing) + .padding(.vertical, 4) + } + + private var statusLine: String { + switch model.connectionState { + case .connecting: return tr("Connecting…") + case .disconnected: return tr("Not connected") + case .connected: return model.codec.isEmpty ? tr("Connected") : "\(tr("Connected")) · \(model.codec)" + } + } + + @ViewBuilder private var battery: some View { + if model.hasDualBattery { + Text(dualBatteryText) + .font(.system(size: 12)) + .foregroundColor(.secondary) + .lineLimit(1) + .fixedSize() + } else if model.batteryLevel >= 0 { + HStack(spacing: 4) { + Text(String(format: tr("%ld%%"), model.batteryLevel)) + .font(.system(size: 12)) + .foregroundColor(.secondary) + .lineLimit(1) + .fixedSize() + Image(systemName: batterySymbol) + .foregroundColor(model.batteryLevel <= 20 && !model.batteryCharging ? .red : .secondary) + } + } + } + + private var dualBatteryText: String { + var text = String(format: tr("L %ld%% R %ld%%"), model.batteryLeft, model.batteryRight) + if model.batteryCase >= 0 { + text += " " + String(format: tr("Case %ld%%"), model.batteryCase) + } + return text + } + + private var batterySymbol: String { + if model.batteryCharging { return "battery.100.bolt" } + switch model.batteryLevel { + case ..<13: return "battery.0" + case ..<38: return "battery.25" + case ..<63: return "battery.50" + case ..<88: return "battery.75" + default: return "battery.100" + } + } +} diff --git a/Client/macos/MenuRows/NotchSizeRow.swift b/Client/macos/MenuRows/NotchSizeRow.swift new file mode 100644 index 0000000..8ff83e3 --- /dev/null +++ b/Client/macos/MenuRows/NotchSizeRow.swift @@ -0,0 +1,28 @@ +import SwiftUI + +// One Notch Size slider ("Open Width ━━━●━━ 300"), bound to an AppSettings value. +struct NotchSizeRow: View { + @ObservedObject var settings: AppSettings + let title: String + let keyPath: ReferenceWritableKeyPath + let range: ClosedRange + let format: (Double) -> String + + var body: some View { + HStack(spacing: 8) { + Text(title) + .lineLimit(1) + .frame(width: 104, alignment: .leading) + Slider(value: Binding(get: { settings[keyPath: keyPath] }, set: { settings[keyPath: keyPath] = $0 }), + in: Double(range.lowerBound)...Double(range.upperBound)) + .controlSize(.small) + Text(verbatim: format(settings[keyPath: keyPath])) + .font(.system(size: 11, weight: .medium).monospacedDigit()) + .foregroundColor(.secondary) + .frame(width: 38, alignment: .trailing) + } + .padding(.leading, MenuMetrics.leading) + .padding(.trailing, MenuMetrics.trailing) + .padding(.vertical, 3) + } +} diff --git a/Client/macos/MenuRows/ToggleRow.swift b/Client/macos/MenuRows/ToggleRow.swift new file mode 100644 index 0000000..23291c8 --- /dev/null +++ b/Client/macos/MenuRows/ToggleRow.swift @@ -0,0 +1,26 @@ +import SwiftUI + +// A title with a switch on the right (Focus on Voice, DSEE, Speak-to-Chat, Adaptive Volume). +struct ToggleRow: View { + @ObservedObject var model: HeadphonesModel + let title: String + var indent: CGFloat = MenuMetrics.leading + let isOn: (HeadphonesModel) -> Bool + let set: (HeadphonesModel, Bool) -> Void + + var body: some View { + HStack { + Text(title).font(.system(size: 13)) + Spacer(minLength: 8) + Toggle("", isOn: Binding(get: { isOn(model) }, set: { set(model, $0) })) + .labelsHidden() + .toggleStyle(.switch) + .controlSize(.mini) + } + .padding(.leading, indent) + .padding(.trailing, MenuMetrics.trailing) + .padding(.vertical, 2) + .disabled(!model.connected) + .opacity(model.connected ? 1 : 0.5) + } +} diff --git a/Client/macos/MenuSupport.swift b/Client/macos/MenuSupport.swift new file mode 100644 index 0000000..0254311 --- /dev/null +++ b/Client/macos/MenuSupport.swift @@ -0,0 +1,70 @@ +import AppKit +import SwiftUI + +// A menu item that runs a closure (NSMenuItem only supports target/selector natively). +final class ActionMenuItem: NSMenuItem { + private let handler: () -> Void + + init(_ title: String, key: String = "", handler: @escaping () -> Void) { + self.handler = handler + super.init(title: title, action: #selector(fire), keyEquivalent: key) + target = self + } + + required init(coder: NSCoder) { + fatalError("init(coder:) is not supported") + } + + @objc private func fire() { + handler() + } +} + +// A small grey, non-clickable title above a group of items (like "Contrôle du son ambiant"). +func sectionHeader(_ title: String) -> NSMenuItem { + let item = NSMenuItem() + item.attributedTitle = NSAttributedString(string: title, attributes: [ + .font: NSFont.systemFont(ofSize: NSFont.smallSystemFontSize, weight: .semibold), + .foregroundColor: NSColor.secondaryLabelColor, + ]) + item.isEnabled = false + return item +} + +enum MenuMetrics { + static let width: CGFloat = 280 // main menu rows + static let equalizerWidth: CGFloat = 300 // equalizer submenu + static let equalizerHeight: CGFloat = 100 // slider 72 + spacing 3 + label ~11 + vertical paddings 2×6 ~98 + static let leading: CGFloat = 24 // lines up with native item titles + static let indent: CGFloat = 45 // rows nested under "Son ambiant", aligned with mode titles' text + static let trailing: CGFloat = 14 // right padding (mirrors the submenu-arrow column) +} + +// Wraps a SwiftUI view in a menu item, for rows a plain NSMenuItem can't express (sliders, switches, header). +// Rows keep a fixed height: optional lines (the error line, notes) are separate plain items instead. +// `width` only seeds the initial layout pass used to compute the row's fitting height; the hosted view is +// then made horizontally resizable so it follows the menu's actual width (NSMenu.minimumWidth) instead of +// staying pinned at that initial width while native items stretch the menu wider (or narrower). +func hostingMenuItem(width: CGFloat = MenuMetrics.width, @ViewBuilder _ content: () -> Content) -> NSMenuItem { + let host = NSHostingView(rootView: content().frame(maxWidth: .infinity, alignment: .leading)) + host.frame = NSRect(x: 0, y: 0, width: width, height: 0) + host.frame.size.height = host.fittingSize.height + host.autoresizingMask = [.width] + let item = NSMenuItem() + item.view = host + return item +} + +// "Title value": the value right-aligned in the secondary color, like "Égaliseur Graves ›". +func titleWithValue(_ title: String, _ value: String, width: CGFloat = MenuMetrics.width - 40) -> NSAttributedString { + let paragraph = NSMutableParagraphStyle() + paragraph.tabStops = [NSTextTab(textAlignment: .right, location: width)] + let font = NSFont.menuFont(ofSize: 0) + let text = NSMutableAttributedString(string: title, attributes: [.font: font, .paragraphStyle: paragraph]) + if !value.isEmpty { + text.append(NSAttributedString(string: "\t" + value, attributes: [ + .font: font, .paragraphStyle: paragraph, .foregroundColor: NSColor.secondaryLabelColor, + ])) + } + return text +} diff --git a/Client/macos/Music/MusicController.swift b/Client/macos/Music/MusicController.swift new file mode 100644 index 0000000..4458920 --- /dev/null +++ b/Client/macos/Music/MusicController.swift @@ -0,0 +1,170 @@ +import AppKit +import Combine + +// The music state the notch shows, from the active MusicSource (spec §5.1). Step 1: the local Spotify app. +final class MusicController: ObservableObject { + static let openRefreshInterval: TimeInterval = 5 // re-read while the notch is open (volume isn't signalled) + private static let artworkCacheSize = 8 + + @Published private(set) var status: MusicSourceStatus = .notRunning + @Published private(set) var nowPlaying: NowPlaying? + @Published private(set) var artwork: NSImage? { + didSet { artworkTint = artwork.flatMap(Self.tint(of:)) } + } + @Published private(set) var artworkTint: NSColor? // vivid average colour of the artwork + + // Something to show: a track, playing or paused (even without the right to control it). + var hasMusic: Bool { status != .notRunning && nowPlaying != nil } + + private let source: MusicSource + private var running = false + private var refreshTimer: Timer? + private var seekThrottle = SendThrottle() + private var volumeThrottle = SendThrottle() + private var artworkCache: [URL: NSImage] = [:] + private var artworkOrder: [URL] = [] + private var artworkRequest: URL? + private var lastLogLine = "" + + init(source: MusicSource = SpotifyLocalSource()) { + self.source = source + source.onChange = { [weak self] status, track in self?.apply(status, track) } + } + + func start() { + guard !running else { return } + running = true + source.start() + } + + // "Show Notch" off: no Spotify reads at all (spec §4.3). + func stop() { + guard running else { return } + running = false + notchDidClose() + source.stop() + status = .notRunning + nowPlaying = nil + artwork = nil + artworkRequest = nil + log("stopped") + } + + // Opening reads once (which also retries a refused permission, spec §6.3), then every 5 s while open. + func notchDidOpen() { + guard running else { return } + source.refresh() + refreshTimer?.invalidate() + let timer = Timer(timeInterval: Self.openRefreshInterval, repeats: true) { [weak self] _ in + guard let self = self, self.status == .ready else { return } + self.source.refresh() + } + RunLoop.main.add(timer, forMode: .common) + refreshTimer = timer + } + + func notchDidClose() { + refreshTimer?.invalidate() + refreshTimer = nil + } + + func playPause() { source.playPause() } + + func next() { source.next() } + + func previous() { source.previous() } + + // Sliders: at most one command per 150 ms while dragging, the final value always, then a read-back. + func seek(to seconds: TimeInterval, final: Bool) { + if seekThrottle.shouldSend(final: final) { source.seek(to: seconds) } + if final { source.refresh() } + } + + func setVolume(_ volume: Int, final: Bool) { + if volumeThrottle.shouldSend(final: final) { source.setVolume(volume) } + if final { source.refresh() } + } + + func launchPlayer() { source.launchPlayer() } + + func openAutomationSettings() { + if let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Automation") { + NSWorkspace.shared.open(url) + } + } + + // MARK: - Private + + private func apply(_ newStatus: MusicSourceStatus, _ track: NowPlaying?) { + guard running else { return } + status = newStatus + nowPlaying = track + loadArtwork(track?.artworkURL) + switch (newStatus, track) { + case (.notRunning, _): log("not running") + case (.permissionDenied, _): log("permission denied") + case (.ready, nil): log("nothing playing") + case (.ready, let track?): + log("\(track.isPlaying ? "playing" : "paused") \(track.trackID) vol \(track.volume.map(String.init) ?? "?")") + } + } + + // One line per actual change (the 5 s re-reads stay quiet). + private func log(_ line: String) { + guard line != lastLogLine else { return } + lastLogLine = line + fputs("[spotify] \(line)\n", stderr) + } + + private func loadArtwork(_ url: URL?) { + guard let url = url else { + artwork = nil + artworkRequest = nil + return + } + if let cached = artworkCache[url] { + artwork = cached + artworkRequest = nil + return + } + guard artworkRequest != url else { return } // already downloading + artworkRequest = url + URLSession.shared.dataTask(with: url) { [weak self] data, _, _ in + let image = data.flatMap { NSImage(data: $0) } + DispatchQueue.main.async { + guard let self = self, self.artworkRequest == url else { return } + self.artworkRequest = nil + guard let image = image else { return } + self.remember(image, for: url) + self.artwork = image + } + }.resume() + } + + // The artwork's average colour, pushed bright and saturated enough to read on black. + private static func tint(of image: NSImage) -> NSColor? { + guard let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil), + let context = CGContext(data: nil, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, + space: CGColorSpaceCreateDeviceRGB(), + bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue), + let data = context.data else { return nil } + context.interpolationQuality = .medium + context.draw(cgImage, in: CGRect(x: 0, y: 0, width: 1, height: 1)) + let pixel = data.assumingMemoryBound(to: UInt8.self) + let average = NSColor(srgbRed: CGFloat(pixel[0]) / 255, green: CGFloat(pixel[1]) / 255, + blue: CGFloat(pixel[2]) / 255, alpha: 1) + // A grey artwork has no meaningful hue (it would come out red): keep it light grey. + guard average.saturationComponent >= 0.12 else { return NSColor(white: 0.85, alpha: 1) } + return NSColor(hue: average.hueComponent, saturation: max(average.saturationComponent, 0.55), + brightness: max(average.brightnessComponent, 0.85), alpha: 1) + } + + private func remember(_ image: NSImage, for url: URL) { + artworkCache[url] = image + artworkOrder.removeAll { $0 == url } + artworkOrder.append(url) + if artworkOrder.count > Self.artworkCacheSize { + artworkCache[artworkOrder.removeFirst()] = nil + } + } +} diff --git a/Client/macos/Music/MusicSource.swift b/Client/macos/Music/MusicSource.swift new file mode 100644 index 0000000..b8e3126 --- /dev/null +++ b/Client/macos/Music/MusicSource.swift @@ -0,0 +1,22 @@ +import Foundation + +enum MusicSourceStatus: Equatable { + case notRunning // the player app isn't open + case permissionDenied // macOS refused SonyNotch the right to control it + case ready +} + +// Where the music comes from (spec §5.1). Step 1: SpotifyLocalSource; step 2 adds the Spotify Web API. +// Called on the main thread; onChange is called on the main thread. +protocol MusicSource: AnyObject { + var onChange: ((MusicSourceStatus, NowPlaying?) -> Void)? { get set } + func start() + func stop() + func refresh() + func playPause() + func next() + func previous() + func seek(to seconds: TimeInterval) + func setVolume(_ volume: Int) + func launchPlayer() +} diff --git a/Client/macos/Music/NowPlaying.swift b/Client/macos/Music/NowPlaying.swift new file mode 100644 index 0000000..02beb0f --- /dev/null +++ b/Client/macos/Music/NowPlaying.swift @@ -0,0 +1,25 @@ +import Foundation + +// What a music source can do with the current track (the Web source of step 2 depends on the device). +struct MusicCapabilities: Equatable { + var canSeek: Bool + var canSetVolume: Bool + var canChangeDevice: Bool +} + +// The track a music source is playing (or paused on). `position` was true at `positionDate`; PlaybackClock +// derives the live position from it, so nothing polls while a track plays. +struct NowPlaying: Equatable { + var trackID: String + var title: String + var artist: String + var album: String + var artworkURL: URL? + var duration: TimeInterval // seconds; 0 when unknown + var position: TimeInterval // seconds, at positionDate + var positionDate: Date + var isPlaying: Bool + var volume: Int? // 0...100; nil until known + var deviceName: String? // nil = this Mac + var capabilities: MusicCapabilities +} diff --git a/Client/macos/Music/PlaybackClock.swift b/Client/macos/Music/PlaybackClock.swift new file mode 100644 index 0000000..b06e3e7 --- /dev/null +++ b/Client/macos/Music/PlaybackClock.swift @@ -0,0 +1,20 @@ +import Foundation + +// Live playback position and its display, from the last known position (spec §6.1). +enum PlaybackClock { + static func position(of track: NowPlaying, at date: Date) -> TimeInterval { + var position = track.position + if track.isPlaying { position += date.timeIntervalSince(track.positionDate) } + if track.duration > 0 { position = min(position, track.duration) } + return max(0, position) + } + + // "1:05", "12:34", "1:02:03". + static func format(_ seconds: TimeInterval) -> String { + let total = max(0, Int(seconds.rounded(.down))) + let hours = total / 3600, minutes = total / 60 % 60, secs = total % 60 + return hours > 0 + ? String(format: "%d:%02d:%02d", hours, minutes, secs) + : String(format: "%d:%02d", minutes, secs) + } +} diff --git a/Client/macos/Music/SpotifyLocalSource.swift b/Client/macos/Music/SpotifyLocalSource.swift new file mode 100644 index 0000000..d4f8b90 --- /dev/null +++ b/Client/macos/Music/SpotifyLocalSource.swift @@ -0,0 +1,206 @@ +import AppKit + +// Reads and controls the Spotify app of this Mac (spec §6): its PlaybackStateChanged signal, plus Apple Events. +// Never sends an Apple Event while Spotify isn't running: one would launch it. +final class SpotifyLocalSource: MusicSource { + static let bundleIdentifier = "com.spotify.client" + private static let signalName = Notification.Name("com.spotify.client.PlaybackStateChanged") + private static let permissionDeniedError = -1743 // errAEEventNotPermitted + private static let notRunningErrors: Set = [-600, -609] // procNotFound, connectionInvalid + private static let launchSettleDelay: TimeInterval = 2 // Spotify answers Apple Events a moment after launch + + var onChange: ((MusicSourceStatus, NowPlaying?) -> Void)? + + // Main thread only. + private var status: MusicSourceStatus = .notRunning + private var nowPlaying: NowPlaying? + private var signalObserver: NSObjectProtocol? + private var workspaceObservers: [NSObjectProtocol] = [] + + // Every NSAppleScript is created and run on this serial queue, one at a time. + private let scriptQueue = DispatchQueue(label: "com.sonynotch.spotify") + private var readScript: NSAppleScript? // scriptQueue only + private var consentGranted = false // scriptQueue only + + // Checked before queuing, and again on the script queue right before an Apple Event goes out, so a Spotify + // quit in between is never relaunched. + private static var spotifyIsRunning: Bool { + !NSRunningApplication.runningApplications(withBundleIdentifier: bundleIdentifier).isEmpty + } + + private var isRunning: Bool { Self.spotifyIsRunning } + + func start() { + guard signalObserver == nil else { return } + signalObserver = DistributedNotificationCenter.default().addObserver( + forName: Self.signalName, object: nil, queue: .main + ) { [weak self] note in + self?.handleSignal(note.userInfo) + } + let center = NSWorkspace.shared.notificationCenter + workspaceObservers = [ + center.addObserver(forName: NSWorkspace.didLaunchApplicationNotification, object: nil, queue: .main) { [weak self] note in + guard Self.isSpotify(note) else { return } + DispatchQueue.main.asyncAfter(deadline: .now() + Self.launchSettleDelay) { self?.refresh() } + }, + center.addObserver(forName: NSWorkspace.didTerminateApplicationNotification, object: nil, queue: .main) { [weak self] note in + if Self.isSpotify(note) { self?.publish(.notRunning, nil) } + }, + ] + if isRunning { refresh() } else { publish(.notRunning, nil) } + } + + func stop() { + if let observer = signalObserver { DistributedNotificationCenter.default().removeObserver(observer) } + signalObserver = nil + workspaceObservers.forEach { NSWorkspace.shared.notificationCenter.removeObserver($0) } + workspaceObservers = [] + status = .notRunning + nowPlaying = nil + } + + func refresh() { + guard signalObserver != nil else { return } + guard isRunning else { publish(.notRunning, nil); return } + scriptQueue.async { [weak self] in + guard let self = self, Self.spotifyIsRunning else { return } + if let code = self.consentError() { + DispatchQueue.main.async { self.applyFailure(code) } + return + } + if self.readScript == nil { self.readScript = NSAppleScript(source: SpotifyScript.readState) } + let result = SpotifyScript.run(self.readScript) + DispatchQueue.main.async { self.applyRead(result) } + } + } + + func playPause() { + // Optimistic: the signal confirms a moment later. + if var track = nowPlaying { + track.position = PlaybackClock.position(of: track, at: Date()) + track.positionDate = Date() + track.isPlaying.toggle() + publish(status, track) + } + send("playpause") + } + + func next() { send("next track") } + + func previous() { send("previous track") } + + func seek(to seconds: TimeInterval) { + if var track = nowPlaying { + track.position = seconds + track.positionDate = Date() + publish(status, track) + } + // String(format:) isn't localized: always a "." decimal separator, as AppleScript source needs. + send(String(format: "set player position to %.3f", seconds)) + } + + func setVolume(_ volume: Int) { + let clamped = min(100, max(0, volume)) + if var track = nowPlaying { + track.volume = clamped + publish(status, track) + } + send("set sound volume to \(clamped)") + } + + func launchPlayer() { + guard let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: Self.bundleIdentifier) else { + fputs("[spotify] Spotify isn't installed\n", stderr) + return + } + NSWorkspace.shared.openApplication(at: url, configuration: NSWorkspace.OpenConfiguration(), + completionHandler: nil) + } + + // MARK: - Private + + private func send(_ command: String) { + guard signalObserver != nil else { return } + guard isRunning else { publish(.notRunning, nil); return } + scriptQueue.async { [weak self] in + guard let self = self, Self.spotifyIsRunning else { return } + if let code = self.consentError() { + DispatchQueue.main.async { self.applyFailure(code) } + return + } + let result = SpotifyScript.run(NSAppleScript(source: SpotifyScript.command(command))) + if case .failure(let code) = result { + DispatchQueue.main.async { self.applyFailure(code) } + } + } + } + + private func handleSignal(_ userInfo: [AnyHashable: Any]?) { + let denied = status == .permissionDenied + switch SpotifyPlaybackInfo.parse(signal: userInfo, at: Date()) { + case .stopped: + publish(denied ? .permissionDenied : .ready, nil) + case .track(var track): + // Artwork and volume only come from Apple Events: keep them for the same track, read them otherwise. + if let current = nowPlaying, current.trackID == track.trackID { + track.artworkURL = current.artworkURL + track.volume = current.volume + } + publish(denied ? .permissionDenied : .ready, track) + if track.artworkURL == nil && !denied { refresh() } + case .incomplete: + if !denied { refresh() } + } + } + + private func applyRead(_ result: SpotifyScript.Result) { + guard signalObserver != nil else { return } // stopped meanwhile + switch result { + case .success(let text): + switch SpotifyPlaybackInfo.parse(scriptResult: text, at: Date()) { + case .stopped: publish(.ready, nil) + case .track(let track): publish(.ready, track) + case .incomplete: fputs("[spotify] unexpected reply: \(text)\n", stderr) + } + case .failure(let code): + applyFailure(code) + } + } + + // Spec §6.3: a refusal stops the reads (the controller retries once per notch opening); anything else + // (timeout, busy) keeps the last known state until the next signal. + private func applyFailure(_ code: Int) { + guard signalObserver != nil else { return } + if code == Self.permissionDeniedError { + publish(.permissionDenied, nowPlaying) + } else if Self.notRunningErrors.contains(code) { + publish(.notRunning, nil) + } else { + fputs("[spotify] Apple Event failed (\(code))\n", stderr) + } + } + + // scriptQueue only. Asks for macOS's automation consent without a timeout: otherwise the scripts' own 2 s + // timeout cancels the first Apple Event while the consent prompt still waits for the user, and the read is + // lost. nil = allowed; otherwise the error to handle (-1743 refused, -600 Spotify not running). + private func consentError() -> Int? { + if consentGranted { return nil } + let target = NSAppleEventDescriptor(bundleIdentifier: Self.bundleIdentifier) + let status = AEDeterminePermissionToAutomateTarget(target.aeDesc, AEEventClass(typeWildCard), AEEventID(typeWildCard), true) + if status == noErr { + consentGranted = true + return nil + } + return Int(status) + } + + private func publish(_ newStatus: MusicSourceStatus, _ track: NowPlaying?) { + status = newStatus + nowPlaying = track + onChange?(newStatus, track) + } + + private static func isSpotify(_ note: Notification) -> Bool { + (note.userInfo?[NSWorkspace.applicationUserInfoKey] as? NSRunningApplication)?.bundleIdentifier == bundleIdentifier + } +} diff --git a/Client/macos/Music/SpotifyPlaybackInfo.swift b/Client/macos/Music/SpotifyPlaybackInfo.swift new file mode 100644 index 0000000..3f3fde0 --- /dev/null +++ b/Client/macos/Music/SpotifyPlaybackInfo.swift @@ -0,0 +1,59 @@ +import Foundation + +// Result of decoding what the local Spotify app reports. +enum SpotifyState: Equatable { + case stopped // Spotify is open with nothing loaded + case track(NowPlaying) + case incomplete // not enough information: read the state through Apple Events instead +} + +// Decodes the local Spotify app's signal and Apple Events replies (spec §6.1). Pure, tested in LogicTests. +enum SpotifyPlaybackInfo { + static let localCapabilities = MusicCapabilities(canSeek: true, canSetVolume: true, canChangeDevice: false) + static let fieldSeparator: Character = "\u{1F}" + + // com.spotify.client.PlaybackStateChanged userInfo: "Player State" (Playing / Paused / Stopped), "Track ID", + // "Name", "Artist", "Album", "Duration" (ms), "Playback Position" (s). It never carries artwork or volume. + static func parse(signal userInfo: [AnyHashable: Any]?, at date: Date) -> SpotifyState { + guard let info = userInfo, let state = info["Player State"] as? String else { return .incomplete } + if state == "Stopped" { return .stopped } + guard state == "Playing" || state == "Paused", + let trackID = info["Track ID"] as? String, !trackID.isEmpty else { return .incomplete } + return .track(NowPlaying( + trackID: trackID, + title: info["Name"] as? String ?? "", + artist: info["Artist"] as? String ?? "", + album: info["Album"] as? String ?? "", + artworkURL: nil, + duration: ((info["Duration"] as? NSNumber)?.doubleValue ?? 0) / 1000, + position: (info["Playback Position"] as? NSNumber)?.doubleValue ?? 0, + positionDate: date, + isPlaying: state == "Playing", + volume: nil, + deviceName: nil, + capabilities: localCapabilities)) + } + + // SpotifyScript.readState's reply: "stopped", or 9 fields separated by U+001F — state, track id, name, + // artist, album, duration (ms), position (ms), artwork URL, volume. + static func parse(scriptResult text: String, at date: Date) -> SpotifyState { + if text == "stopped" { return .stopped } + let fields = text.split(separator: fieldSeparator, omittingEmptySubsequences: false).map(String.init) + guard fields.count == 9, fields[0] == "playing" || fields[0] == "paused", !fields[1].isEmpty else { + return .incomplete + } + return .track(NowPlaying( + trackID: fields[1], + title: fields[2], + artist: fields[3], + album: fields[4], + artworkURL: URL(string: fields[7]), + duration: (Double(fields[5]) ?? 0) / 1000, + position: (Double(fields[6]) ?? 0) / 1000, + positionDate: date, + isPlaying: fields[0] == "playing", + volume: Int(fields[8]).map { min(100, max(0, $0)) }, + deviceName: nil, + capabilities: localCapabilities)) + } +} diff --git a/Client/macos/Music/SpotifyScript.swift b/Client/macos/Music/SpotifyScript.swift new file mode 100644 index 0000000..406cb44 --- /dev/null +++ b/Client/macos/Music/SpotifyScript.swift @@ -0,0 +1,44 @@ +import Foundation + +// AppleScript sent to the local Spotify app (spec §6). Only ever run on SpotifyLocalSource's script queue. +enum SpotifyScript { + enum Result: Equatable { + case success(String) + case failure(Int) // AppleScript / Apple Event error number + } + + // Fields joined by U+001F; times as integer milliseconds so no locale decimal separator shows up. + // Parsed by SpotifyPlaybackInfo.parse(scriptResult:at:). + static let readState = """ + with timeout of 2 seconds + tell application id "com.spotify.client" + set playerState to (player state as text) + if playerState is "stopped" then return "stopped" + set t to current track + set sep to (character id 31) + set art to artwork url of t + if art is missing value then set art to "" + return playerState & sep & (id of t) & sep & (name of t) & sep & (artist of t) & sep & (album of t) & sep & ((duration of t) as text) & sep & ((((player position) * 1000) div 1) as text) & sep & art & sep & ((sound volume) as text) + end tell + end timeout + """ + + // One command, e.g. "playpause", "next track", "set sound volume to 40". + static func command(_ body: String) -> String { + """ + with timeout of 2 seconds + tell application id "com.spotify.client" to \(body) + end timeout + """ + } + + static func run(_ script: NSAppleScript?) -> Result { + guard let script = script else { return .failure(-2700) } + var error: NSDictionary? + let output = script.executeAndReturnError(&error) + if let error = error { + return .failure((error[NSAppleScript.errorNumber] as? NSNumber)?.intValue ?? -2700) + } + return .success(output.stringValue ?? "") + } +} diff --git a/Client/macos/Notch/FlatSlider.swift b/Client/macos/Notch/FlatSlider.swift new file mode 100644 index 0000000..c490749 --- /dev/null +++ b/Client/macos/Notch/FlatSlider.swift @@ -0,0 +1,59 @@ +import SwiftUI + +// A thick flat bar without a knob (progress, volume, level). Click or drag anywhere on it; `onChange` gets the +// value while dragging (final: false) and once more when the pointer is released (final: true). `smoothing` +// glides the fill between values that arrive once a second (playback progress). +struct FlatSlider: View { + let value: Double + var range: ClosedRange = 0...1 + var step: Double? + var height: CGFloat = 5 + var smoothing = false + let onChange: (Double, Bool) -> Void + + @Environment(\.isEnabled) private var isEnabled + @Environment(\.notchScale) private var s + @State private var dragging = false + @State private var hovering = false + + var body: some View { + GeometryReader { geometry in + let width = max(geometry.size.width, 1) + let span = range.upperBound - range.lowerBound + let fraction = span > 0 ? min(1, max(0, (value - range.lowerBound) / span)) : 0 + let barHeight = (dragging || hovering ? height + 2 : height) * s + ZStack(alignment: .leading) { + Capsule().fill(Color(white: 0.25)) + Capsule() + .fill(Color(white: dragging || hovering ? 1 : 0.75)) + .frame(width: max(barHeight, width * fraction)) + .opacity(fraction > 0 ? 1 : 0) + .animation(smoothing && !dragging ? .linear(duration: 1) : .easeOut(duration: 0.08), value: fraction) + } + .frame(height: barHeight) + .frame(maxHeight: .infinity) + .contentShape(Rectangle()) + .gesture( + DragGesture(minimumDistance: 0) + .onChanged { drag in + dragging = true + onChange(Self.value(at: drag.location.x / width, range: range, step: step), false) + } + .onEnded { drag in + dragging = false + onChange(Self.value(at: drag.location.x / width, range: range, step: step), true) + } + ) + .onHover { hovering = isEnabled && $0 } + .animation(.easeOut(duration: 0.12), value: barHeight) + } + .frame(height: (height + 8) * s) + .opacity(isEnabled ? 1 : 0.4) + } + + private static func value(at fraction: CGFloat, range: ClosedRange, step: Double?) -> Double { + let raw = range.lowerBound + Double(min(1, max(0, fraction))) * (range.upperBound - range.lowerBound) + guard let step = step, step > 0 else { return raw } + return (raw / step).rounded() * step + } +} diff --git a/Client/macos/Notch/HeadphonesTab.swift b/Client/macos/Notch/HeadphonesTab.swift new file mode 100644 index 0000000..3aca285 --- /dev/null +++ b/Client/macos/Notch/HeadphonesTab.swift @@ -0,0 +1,119 @@ +import AppKit +import SwiftUI + +// Notch headphones page: NC / Ambient / Off, ambient level and Focus on Voice (spec §4.2). It calls the same +// model methods as the menu, so the poll guard and the send throttle apply here too, and both stay in sync. +struct HeadphonesTab: View { + @ObservedObject var model: HeadphonesModel + let back: () -> Void + @Environment(\.notchScale) private var s + + var body: some View { + VStack(alignment: .leading, spacing: 12 * s) { + HStack(spacing: 6 * s) { + Button(action: back) { + Image(systemName: "chevron.left") + .font(.system(size: 13 * s, weight: .semibold)) + .foregroundColor(.gray) + .frame(width: 24 * s, height: 24 * s) + .contentShape(Rectangle()) + } + .buttonStyle(PressableButtonStyle()) + .accessibilityLabel(tr("Back")) + Image(systemName: "headphones").font(.system(size: 13 * s)).foregroundColor(.white) + Text(model.deviceName.isEmpty ? tr("Headphones") : model.deviceName) + .font(.system(size: 13 * s, weight: .semibold)) + .foregroundColor(.white) + .lineLimit(1) + } + switch model.connectionState { + case .connected: + controls + case .connecting: + Text(tr("Connecting…")) + .font(.system(size: 12 * s)) + .foregroundColor(.gray) + .frame(maxWidth: .infinity) + .padding(.top, 8 * s) + case .disconnected: + HStack(spacing: 10 * s) { + Text(tr("Not connected")).font(.system(size: 12 * s)).foregroundColor(.gray) + NotchPillButton(title: tr("Connect…")) { + NSApp.activate(ignoringOtherApps: true) // the fallback Bluetooth picker is a modal window + model.connect() + } + } + .frame(maxWidth: .infinity) + .padding(.top, 8 * s) + } + } + } + + private var controls: some View { + let ambient = model.mode == .ambientSound + return VStack(spacing: 10 * s) { + ModePicker(selection: model.mode, select: { model.setMode($0) }) + + HStack(spacing: 8 * s) { + Text(tr("Level")).font(.system(size: 12 * s)).foregroundColor(.gray) + FlatSlider(value: Double(model.ambientLevel), range: 1...Double(max(model.maxAmbientLevel, 2)), + step: 1) { value, final in + model.setLevel(Int(value.rounded()), final: final) + } + Text(verbatim: "\(model.ambientLevel)") + .font(.system(size: 11 * s, weight: .medium).monospacedDigit()) + .foregroundColor(.gray) + .frame(width: 20 * s, alignment: .trailing) + Text(tr("Voice")).font(.system(size: 12 * s)).foregroundColor(.gray).padding(.leading, 6 * s) + NotchSwitch(isOn: model.focusOnVoice, label: tr("Focus on Voice")) { model.setFocusOnVoice($0) } + } + .disabled(!ambient) + .opacity(ambient ? 1 : 0.4) + .animation(.easeInOut(duration: 0.2), value: ambient) + } + } +} + +// Segmented NC / Ambient / Off control drawn in SwiftUI. The AppKit segmented picker insists on its natural +// width, wider than the notch in French, and only shrank on the next model update (~2 s later). Short labels: +// the full ones ("Réduction de bruit") don't fit a third of the notch. +private struct ModePicker: View { + let selection: SHCAmbientMode + let select: (SHCAmbientMode) -> Void + @Environment(\.notchScale) private var s + @Namespace private var pill + + private static var options: [(SHCAmbientMode, String)] { + [(.noiseCanceling, tr("NC")), (.ambientSound, tr("Ambient")), (.off, tr("Off"))] + } + + var body: some View { + HStack(spacing: 2 * s) { + ForEach(Self.options, id: \.0.rawValue) { mode, title in + let selected = selection == mode + Button { select(mode) } label: { + Text(title) + .font(.system(size: 11 * s, weight: selected ? .semibold : .regular)) + .foregroundColor(selected ? .white : .gray) + .lineLimit(1) + .frame(maxWidth: .infinity) + .padding(.vertical, 5 * s) + .background { + if selected { + RoundedRectangle(cornerRadius: 6 * s) + .fill(Color(white: 0.3)) + .matchedGeometryEffect(id: "pill", in: pill) + } + } + .contentShape(Rectangle()) + } + .buttonStyle(PressableButtonStyle()) + .accessibilityAddTraits(selected ? .isSelected : []) + } + } + .padding(2 * s) + .background(RoundedRectangle(cornerRadius: 8 * s).fill(Color(white: 0.15))) + // The selection comes back from the headset (menu, NC button), so animate on the value, not the click. + .animation(.spring(response: 0.3, dampingFraction: 0.8), value: selection) + } +} diff --git a/Client/macos/Notch/MusicTab.swift b/Client/macos/Notch/MusicTab.swift new file mode 100644 index 0000000..ebbaa4e --- /dev/null +++ b/Client/macos/Notch/MusicTab.swift @@ -0,0 +1,173 @@ +import SwiftUI + +// Notch player page (spec §4.2): artwork, title and artist; progress; headphones, previous, play/pause, next, +// volume. The volume button swaps the progress bar for Spotify's volume bar for a few seconds. Sizes follow +// the notch zoom; extra height grows the artwork. +struct MusicTab: View { + private static let volumeAutoHide: TimeInterval = 4 + + @ObservedObject var music: MusicController + let showHeadphones: () -> Void + @Environment(\.notchScale) private var s + @State private var seekValue: Double? // while dragging the progress bar + @State private var volumeValue: Double? // while dragging the volume bar + @State private var showVolume = false + @State private var volumeHideWork: DispatchWorkItem? + + // Explicit: the private @State properties would otherwise make the memberwise init private. + init(music: MusicController, showHeadphones: @escaping () -> Void) { + _music = ObservedObject(wrappedValue: music) + self.showHeadphones = showHeadphones + } + + var body: some View { + switch music.status { + case .notRunning: + message(tr("Spotify isn't open"), button: tr("Open Spotify")) { music.launchPlayer() } + case .permissionDenied: + message(tr("SonyNotch isn't allowed to control Spotify."), button: tr("Open Settings")) { + music.openAutomationSettings() + } + case .ready: + if let track = music.nowPlaying { + player(track) + } else { + message(tr("Nothing playing"), button: nil) {} + } + } + } + + private func message(_ text: String, button: String?, action: @escaping () -> Void) -> some View { + VStack(spacing: 10 * s) { + Text(text).font(.system(size: 12 * s)).foregroundColor(.gray).multilineTextAlignment(.center) + if let button = button { + NotchPillButton(title: button, action: action) + } + Spacer(minLength: 0) + HStack { + iconButton("headphones", label: tr("Headphones"), action: showHeadphones) + Spacer() + } + } + .frame(maxWidth: .infinity) + .padding(.top, 6 * s) + } + + private func player(_ track: NowPlaying) -> some View { + GeometryReader { proxy in + player(track, artwork: artworkSize(forHeight: proxy.size.height)) + } + } + + // 50 pt at the default height; each extra point of height gives the artwork 0.6 pt, within 44...88 (× zoom). + private func artworkSize(forHeight height: CGFloat) -> CGFloat { + min(88 * s, max(44 * s, 50 * s + (height - 112 * s) * 0.6)) + } + + private func player(_ track: NowPlaying, artwork: CGFloat) -> some View { + VStack(spacing: 0) { + HStack(spacing: 12 * s) { + ArtworkView(image: music.artwork, size: artwork, cornerRadius: artwork * 0.2) + VStack(alignment: .leading, spacing: 2 * s) { + Text(track.title).font(.system(size: 14 * s, weight: .semibold)).foregroundColor(.white) + Text(track.artist).font(.system(size: 13 * s)).foregroundColor(.gray) + } + .lineLimit(1) + .id(track.trackID) + .transition(.asymmetric(insertion: .opacity.combined(with: .offset(y: 6)), removal: .opacity)) + Spacer(minLength: 6 * s) + LevelBars(animating: track.isPlaying, color: music.artworkTint) + } + .animation(NotchMotion.content, value: track.trackID) + Spacer(minLength: 8 * s) + ZStack { + progress(track) + .modifier(FadeScale(amount: showVolume ? 1 : 0)) + .allowsHitTesting(!showVolume) + volume(track) + .modifier(FadeScale(amount: showVolume ? 0 : 1)) + .allowsHitTesting(showVolume) + } + .animation(NotchMotion.content, value: showVolume) + Spacer(minLength: 6 * s) + // The side buttons take equal flexible widths, so previous / play / next stay centred on the notch. + HStack(spacing: 0) { + iconButton("headphones", label: tr("Headphones"), action: showHeadphones) + .frame(maxWidth: .infinity, alignment: .leading) + HStack(spacing: 22 * s) { + iconButton("backward.fill", size: 17, color: .white, label: tr("Previous track")) { music.previous() } + iconButton(track.isPlaying ? "pause.fill" : "play.fill", size: 21, color: .white, + label: tr("Play or pause")) { music.playPause() } + .animation(NotchMotion.content, value: track.isPlaying) + iconButton("forward.fill", size: 17, color: .white, label: tr("Next track")) { music.next() } + } + iconButton(showVolume ? "speaker.wave.2.fill" : "speaker.wave.2", color: showVolume ? .white : .gray, + label: tr("Spotify volume")) { toggleVolume() } + .disabled(!track.capabilities.canSetVolume || track.volume == nil) + .frame(maxWidth: .infinity, alignment: .trailing) + } + } + } + + // Redrawn once a second, only while the notch is open (this view only exists then). + private func progress(_ track: NowPlaying) -> some View { + TimelineView(.periodic(from: .now, by: 1)) { context in + let position = seekValue ?? PlaybackClock.position(of: track, at: context.date) + HStack(spacing: 8 * s) { + timeLabel(PlaybackClock.format(position)) + FlatSlider(value: position, range: 0...max(track.duration, 1), smoothing: seekValue == nil) { value, final in + seekValue = final ? nil : value + music.seek(to: value, final: final) + } + .disabled(!track.capabilities.canSeek || track.duration <= 0) + timeLabel(PlaybackClock.format(track.duration)) + } + } + } + + private func volume(_ track: NowPlaying) -> some View { + HStack(spacing: 8 * s) { + Image(systemName: "speaker.fill").font(.system(size: 10 * s)).foregroundColor(.gray).frame(width: 34 * s) + FlatSlider(value: volumeValue ?? Double(track.volume ?? 0), range: 0...100) { value, final in + volumeValue = final ? nil : value + music.setVolume(Int(value.rounded()), final: final) + scheduleVolumeHide() + } + Image(systemName: "speaker.wave.3.fill").font(.system(size: 10 * s)).foregroundColor(.gray).frame(width: 34 * s) + } + } + + private func timeLabel(_ text: String) -> some View { + Text(verbatim: text) + .font(.system(size: 11 * s).monospacedDigit()) + .foregroundColor(.gray) + .frame(width: 36 * s) + } + + private func iconButton(_ symbol: String, size: CGFloat = 14, color: Color = .gray, label: String, + action: @escaping () -> Void) -> some View { + Button(action: action) { + Image(systemName: symbol) + .font(.system(size: size * s)) + .foregroundColor(color) + .symbolReplaceTransition() + .frame(width: 28 * s, height: 26 * s) + .contentShape(Rectangle()) + } + .buttonStyle(PressableButtonStyle()) + .accessibilityLabel(label) + } + + private func toggleVolume() { + withAnimation(NotchMotion.content) { showVolume.toggle() } + if showVolume { scheduleVolumeHide() } else { volumeHideWork?.cancel() } + } + + // The volume bar folds back once it hasn't been touched for a few seconds. + private func scheduleVolumeHide() { + volumeHideWork?.cancel() + let work = DispatchWorkItem { withAnimation(NotchMotion.content) { showVolume = false } } + volumeHideWork = work + DispatchQueue.main.asyncAfter(deadline: .now() + Self.volumeAutoHide, execute: work) + } +} diff --git a/Client/macos/Notch/NotchContent.swift b/Client/macos/Notch/NotchContent.swift new file mode 100644 index 0000000..6ee7e60 --- /dev/null +++ b/Client/macos/Notch/NotchContent.swift @@ -0,0 +1,32 @@ +import Foundation + +// What the notch shows while resting (spec §4.1) and which tab it opens on. Pure logic, tested in LogicTests. +enum NotchRestingState: Equatable { + case musicAndHeadphones // 1: artwork left, headphones mode right + case musicOnly // 2: artwork left, level bars right + case headphonesOnly // 3: headphones glyph left, mode right + case empty // 4: bare notch (hidden on a screen without a notch) +} + +enum NotchTab: Equatable { + case music, headphones +} + +enum NotchContent { + static let openDelay: TimeInterval = 0.15 // hover time before opening + static let closeDelay: TimeInterval = 0.4 // time after the pointer leaves before closing + + static func restingState(hasMusic: Bool, headphonesConnected: Bool) -> NotchRestingState { + switch (hasMusic, headphonesConnected) { + case (true, true): return .musicAndHeadphones + case (true, false): return .musicOnly + case (false, true): return .headphonesOnly + case (false, false): return .empty + } + } + + // The first opening of the session follows the music; afterwards the last tab the user picked wins. + static func tabOnOpen(lastChosen: NotchTab?, hasMusic: Bool) -> NotchTab { + lastChosen ?? (hasMusic ? .music : .headphones) + } +} diff --git a/Client/macos/Notch/NotchController.swift b/Client/macos/Notch/NotchController.swift new file mode 100644 index 0000000..d184b4e --- /dev/null +++ b/Client/macos/Notch/NotchController.swift @@ -0,0 +1,280 @@ +import AppKit +import Combine +import SwiftUI + +// Owns the notch panel (spec §4.3): picks the screen, places the panel, opens it on hover and follows the +// "Show Notch" option. +// +// The panel always keeps the largest open size the Notch Size options allow: only the SwiftUI shape inside +// animates, including while the size is changed. Resizing the window on open +// and close showed a frame of stale content at the new size (things jumped outward, then back). While +// closed, the panel lets every click through, and hover is followed from the pointer position instead of +// tracking areas. +final class NotchController { + private static let unmountDelay: TimeInterval = 0.4 // lets the closing spring settle first + private static let closedPreviewTime: TimeInterval = 1 // closed-width preview, then back to the open notch + + private let model: HeadphonesModel + private let music: MusicController + private let settings: AppSettings + private let state = NotchViewState() + private let panel = NotchPanel.make() + private var geometry: NotchGeometry? + private var lastChosenTab: NotchTab? + private var pointerInside = false + private var previewing = false // Notch Size submenu open: the pointer neither opens nor closes the notch + private var reopenWork: DispatchWorkItem? + private var hoverTimer: Timer? + private var hideWork: DispatchWorkItem? + private var unmountWork: DispatchWorkItem? + private var mouseMonitors: [Any] = [] + private var cancellables = Set() + + init(model: HeadphonesModel, music: MusicController, settings: AppSettings) { + self.model = model + self.music = music + self.settings = settings + + let container = NotchContainerView() + let host = NotchHostingView(rootView: NotchView(state: state, model: model, music: music, + selectTab: { [weak self] tab in self?.select(tab) })) + host.autoresizingMask = [.width, .height] + container.addSubview(host) + container.onHoverChange = { [weak self] in self?.pointerMoved() } + panel.contentView = container + panel.acceptsMouseMovedEvents = true + panel.ignoresMouseEvents = true + + // Global: the pointer over other apps (the notch is closed, the panel ignores the mouse). Local: over + // our own windows, the open panel included. + let events: NSEvent.EventTypeMask = [.mouseMoved, .leftMouseDragged] + if let global = NSEvent.addGlobalMonitorForEvents(matching: events, handler: { [weak self] _ in self?.pointerMoved() }) { + mouseMonitors.append(global) + } + if let local = NSEvent.addLocalMonitorForEvents(matching: events, handler: { [weak self] event in + self?.pointerMoved() + return event + }) { + mouseMonitors.append(local) + } + + NotificationCenter.default.publisher(for: NSApplication.didChangeScreenParametersNotification) + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in self?.relayout() } + .store(in: &cancellables) + // receive(on:) hops after @Published stored the new value, so the sinks read current state. + settings.$showNotch + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in self?.relayout() } + .store(in: &cancellables) + // A size slider shows what it changes: the open notch for its width, height and text size, the closed + // notch for the closed width. + Publishers.Merge3(settings.$notchWidth.dropFirst(), settings.$notchHeight.dropFirst(), settings.$notchZoom.dropFirst()) + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in self?.sizeChanged(showOpen: true) } + .store(in: &cancellables) + settings.$notchSideWidth.dropFirst().merge(with: settings.$notchArtwork.dropFirst()) + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in self?.sizeChanged(showOpen: false) } + .store(in: &cancellables) + settings.$notchPreviewing + .dropFirst() + .receive(on: DispatchQueue.main) + .sink { [weak self] on in self?.setPreviewing(on) } + .store(in: &cancellables) + model.$connectionState.combineLatest(music.$status, music.$nowPlaying) + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in self?.updateResting() } + .store(in: &cancellables) + } + + deinit { + mouseMonitors.forEach(NSEvent.removeMonitor) + } + + // MARK: - Placement + + private func relayout() { + guard settings.showNotch, let screen = Self.preferredScreen() else { + geometry = nil + if state.isOpen { + state.isOpen = false + music.notchDidClose() + } + unmountWork?.cancel() + state.openContentMounted = false + panel.ignoresMouseEvents = true + hideWork?.cancel() + panel.orderOut(nil) + return + } + let metrics = ScreenMetrics(screen) + let layout = settings.notchLayout + let geometry = NotchGeometry(screen: metrics, layout: layout) + self.geometry = geometry + state.notchHeight = geometry.notch.height + state.openSize = geometry.open.size + state.sideExtension = layout.sideExtension + state.contentScale = layout.contentScale + state.restingScale = layout.restingScale + state.restingArtworkSize = layout.restingArtworkSize(notchHeight: geometry.notch.height) + let largest = NotchLayout(openSize: CGSize(width: NotchLayout.widthRange.upperBound, + height: NotchLayout.heightRange.upperBound), + sideExtension: NotchLayout.sideRange.upperBound, zoom: 1) + let panelFrame = NotchGeometry(screen: metrics, layout: largest).open + if panel.frame != panelFrame { panel.setFrame(panelFrame, display: true) } + updateResting() + } + + // The built-in notched screen if there is one, else the primary screen (the one with the menu bar). + private static func preferredScreen() -> NSScreen? { + NSScreen.screens.first { $0.safeAreaInsets.top > 0 } ?? NSScreen.screens.first + } + + private func updateResting() { + guard let geometry = geometry else { return } + let resting = NotchContent.restingState(hasMusic: music.hasMusic, headphonesConnected: model.connected) + let frame = geometry.restingFrame(for: resting) + if state.resting != resting || (frame != nil && state.restingSize != frame?.size) { + withAnimation(state.isOpen ? NotchMotion.open : NotchMotion.close) { + state.resting = resting + if let frame = frame { state.restingSize = frame.size } + } + } + updateTrailingHover() + hideWork?.cancel() + if frame != nil || state.isOpen { + panel.orderFrontRegardless() + } else if panel.isVisible { + // Nothing to show on a screen without a notch: hide once the shape has shrunk away. + let work = DispatchWorkItem { [weak self] in + guard let self = self, !self.state.isOpen else { return } + self.panel.orderOut(nil) + } + hideWork = work + DispatchQueue.main.asyncAfter(deadline: .now() + Self.unmountDelay, execute: work) + } + } + + // MARK: - Hover + + // Only a change of side (in / out) starts the timer, so moving inside doesn't keep postponing the opening; + // the timer then reads the real pointer position, so a missed event can't leave the notch stuck. + private func pointerMoved() { + updateTrailingHover() + let inside = isPointerInHoverZone + guard inside != pointerInside else { return } + pointerInside = inside + hoverTimer?.invalidate() + let delay = inside ? NotchContent.openDelay : NotchContent.closeDelay + let timer = Timer(timeInterval: delay, repeats: false) { [weak self] _ in self?.hoverCheck() } + RunLoop.main.add(timer, forMode: .common) + hoverTimer = timer + } + + private func hoverCheck() { + let inside = isPointerInHoverZone + pointerInside = inside + if inside && !state.isOpen && !previewing { + open() + } else if !inside && state.isOpen && !previewing { + close() + } + } + + private var isPointerInHoverZone: Bool { + guard panel.isVisible, let geometry = geometry else { return false } + let pointer = NSEvent.mouseLocation + if state.isOpen { return geometry.open.contains(pointer) } + // The resting music control is clicked, not a way to open the notch. + if hasRestingMusicControl && geometry.restingTrailingZone.contains(pointer) { return false } + return geometry.restingFrame(for: state.resting)?.contains(pointer) ?? false + } + + private var hasRestingMusicControl: Bool { + state.resting == .musicAndHeadphones || state.resting == .musicOnly + } + + // While closed, the pointer over the right widening swaps the level bars for next / play, and the panel + // takes the mouse there (and only there) so the button can be clicked. + private func updateTrailingHover() { + let hovered = !state.isOpen && panel.isVisible && hasRestingMusicControl + && (geometry?.restingTrailingZone.contains(NSEvent.mouseLocation) ?? false) + if hovered != state.trailingHovered { + withAnimation(NotchMotion.content) { state.trailingHovered = hovered } + } + panel.ignoresMouseEvents = !(state.isOpen || hovered) + } + + private func open() { + unmountWork?.cancel() + hideWork?.cancel() + if !state.openContentMounted { state.tab = NotchContent.tabOnOpen(lastChosen: lastChosenTab, hasMusic: music.hasMusic) } + state.openContentMounted = true + state.trailingHovered = false + panel.ignoresMouseEvents = false + panel.orderFrontRegardless() + withAnimation(NotchMotion.open) { state.isOpen = true } + music.notchDidOpen() + } + + private func close() { + panel.ignoresMouseEvents = true // clicks reach the apps below while the shape shrinks + withAnimation(NotchMotion.close) { state.isOpen = false } + music.notchDidClose() + updateResting() + // The open content shrinks and fades with the shape (it stays mounted while closing), then leaves the + // hierarchy so its timelines stop. + let work = DispatchWorkItem { [weak self] in + guard let self = self, !self.state.isOpen else { return } + self.state.openContentMounted = false + } + unmountWork = work + DispatchQueue.main.asyncAfter(deadline: .now() + Self.unmountDelay, execute: work) + } + + // The Notch Size submenu opens the notch as a live preview; closing the menu hands it back to the pointer. + private func setPreviewing(_ on: Bool) { + previewing = on + reopenWork?.cancel() + if on { + if geometry != nil && !state.isOpen { open() } + } else { + hoverCheck() + } + } + + // Width, height and text size show on the open notch. The closed width and artwork close it while they move, + // then reopens it a second after the last change, so the other sliders find it open again. + private func sizeChanged(showOpen: Bool) { + withAnimation(NotchMotion.content) { relayout() } + guard previewing, geometry != nil else { return } + reopenWork?.cancel() + if showOpen { + if !state.isOpen { open() } + return + } + if state.isOpen { close() } + let work = DispatchWorkItem { [weak self] in + guard let self = self, self.previewing, !self.state.isOpen else { return } + self.open() + } + reopenWork = work + DispatchQueue.main.asyncAfter(deadline: .now() + Self.closedPreviewTime, execute: work) + } + + private func select(_ tab: NotchTab) { + lastChosenTab = tab + withAnimation(NotchMotion.content) { state.tab = tab } + } +} + +private extension ScreenMetrics { + init(_ screen: NSScreen) { + self.init(frame: screen.frame, + safeAreaTop: screen.safeAreaInsets.top, + auxiliaryTopLeft: screen.auxiliaryTopLeftArea, + auxiliaryTopRight: screen.auxiliaryTopRightArea, + menuBarHeight: screen.frame.maxY - screen.visibleFrame.maxY) + } +} diff --git a/Client/macos/Notch/NotchControls.swift b/Client/macos/Notch/NotchControls.swift new file mode 100644 index 0000000..8762253 --- /dev/null +++ b/Client/macos/Notch/NotchControls.swift @@ -0,0 +1,52 @@ +import SwiftUI + +// Controls drawn in SwiftUI for the notch. The AppKit-backed ones (Toggle .switch, bordered Button, segmented +// Picker) are separate views that ignore SwiftUI's scale and clip: while the notch closed, they stayed full +// size past the shrinking shape. + +// A small on/off switch. +struct NotchSwitch: View { + let isOn: Bool + let label: String + let set: (Bool) -> Void + + @Environment(\.isEnabled) private var isEnabled + @Environment(\.notchScale) private var s + + var body: some View { + Button { set(!isOn) } label: { + ZStack(alignment: isOn ? .trailing : .leading) { + Capsule().fill(isOn ? Color.green : Color(white: 0.3)) + Circle().fill(Color.white).padding(2 * s) + } + .frame(width: 30 * s, height: 18 * s) + .animation(.spring(response: 0.25, dampingFraction: 0.8), value: isOn) + } + .buttonStyle(PressableButtonStyle()) + .opacity(isEnabled ? 1 : 0.5) + .accessibilityLabel(label) + .accessibilityValue(isOn ? Text(verbatim: "1") : Text(verbatim: "0")) + .accessibilityAddTraits(.isButton) + } +} + +// A rounded grey text button ("Connect…", "Open Spotify"). +struct NotchPillButton: View { + let title: String + let action: () -> Void + @Environment(\.notchScale) private var s + + var body: some View { + Button(action: action) { + Text(title) + .font(.system(size: 12 * s, weight: .medium)) + .foregroundColor(.white) + .lineLimit(1) + .padding(.horizontal, 12 * s) + .padding(.vertical, 5 * s) + .background(Capsule().fill(Color(white: 0.22))) + .contentShape(Capsule()) + } + .buttonStyle(PressableButtonStyle()) + } +} diff --git a/Client/macos/Notch/NotchGeometry.swift b/Client/macos/Notch/NotchGeometry.swift new file mode 100644 index 0000000..8f413c5 --- /dev/null +++ b/Client/macos/Notch/NotchGeometry.swift @@ -0,0 +1,110 @@ +import CoreGraphics + +// The NSScreen values NotchGeometry needs, copied out so this file stays AppKit-free (tested in LogicTests). +// Rects are in global screen coordinates (origin at the bottom-left of the primary screen). +struct ScreenMetrics: Equatable { + var frame: CGRect + var safeAreaTop: CGFloat // NSScreen.safeAreaInsets.top (0 without a notch) + var auxiliaryTopLeft: CGRect? // NSScreen.auxiliaryTopLeftArea (nil without a notch) + var auxiliaryTopRight: CGRect? // NSScreen.auxiliaryTopRightArea + var menuBarHeight: CGFloat // frame.maxY - visibleFrame.maxY (0 when the menu bar auto-hides) +} + +// The sizes the user can set under Options › Notch Size, clamped to what the notch content can hold. +struct NotchLayout: Equatable { + static let widthRange: ClosedRange = 280...480 + static let heightRange: ClosedRange = 156...260 + static let sideRange: ClosedRange = 28...60 + static let zoomRange: ClosedRange = 0.85...1.3 + static let artworkRange: ClosedRange = 16...30 + static let `default` = NotchLayout(openSize: CGSize(width: 300, height: 166), sideExtension: 36, zoom: 1, + restingArtwork: 24) + + // The open size the player needs at zoom 1, and the side width a resting icon needs. + private static let contentMinimum = CGSize(width: 280, height: 156) + private static let restingItemMinimum: CGFloat = 30 + + let openSize: CGSize // open notch, notch height included + let sideExtension: CGFloat // resting widening on each side + let zoom: CGFloat // text and icon size asked for + let restingArtwork: CGFloat // artwork size on the closed notch, asked for + + init(openSize: CGSize, sideExtension: CGFloat, zoom: CGFloat, restingArtwork: CGFloat = 24) { + self.openSize = CGSize(width: Self.clamp(openSize.width, Self.widthRange), + height: Self.clamp(openSize.height, Self.heightRange)) + self.sideExtension = Self.clamp(sideExtension, Self.sideRange) + self.zoom = Self.clamp(zoom, Self.zoomRange) + self.restingArtwork = Self.clamp(restingArtwork, Self.artworkRange) + } + + // Closed-notch artwork size actually drawn: 2 pt clear of the notch's top and bottom, 3 pt of each side. + func restingArtworkSize(notchHeight: CGFloat) -> CGFloat { + min(restingArtwork, notchHeight - 4, sideExtension - 6) + } + + // Zoom applied to the open content: lowered when the chosen size couldn't hold the content at that zoom. + var contentScale: CGFloat { + min(zoom, openSize.width / Self.contentMinimum.width, openSize.height / Self.contentMinimum.height) + } + + // Zoom applied to the resting artwork and icons, lowered to fit the side width. + var restingScale: CGFloat { + min(zoom, sideExtension / Self.restingItemMinimum) + } + + private static func clamp(_ value: CGFloat, _ range: ClosedRange) -> CGFloat { + min(range.upperBound, max(range.lowerBound, value)) + } +} + +// Where the notch panel goes (spec §4): the real notch, or a simulated pill centred at the top of a screen +// without one. Every rect shares the notch's horizontal centre and touches the top edge of the screen. +struct NotchGeometry: Equatable { + static let simulatedWidth: CGFloat = 190 // pill width on a screen without a notch + static let fallbackMenuBarHeight: CGFloat = 24 // pill height when the menu bar auto-hides + + let hasNotch: Bool + let notch: CGRect + let layout: NotchLayout + + init(screen: ScreenMetrics, layout: NotchLayout = .default) { + self.layout = layout + let top = screen.frame.maxY + if screen.safeAreaTop > 0, let left = screen.auxiliaryTopLeft, let right = screen.auxiliaryTopRight, + screen.frame.width - left.width - right.width > 0 { + // Only the widths of the auxiliary areas are used, so their coordinate space doesn't matter. + hasNotch = true + notch = CGRect(x: screen.frame.minX + left.width, y: top - screen.safeAreaTop, + width: screen.frame.width - left.width - right.width, height: screen.safeAreaTop) + } else { + hasNotch = false + let height = screen.menuBarHeight > 0 ? screen.menuBarHeight : Self.fallbackMenuBarHeight + notch = CGRect(x: screen.frame.midX - Self.simulatedWidth / 2, y: top - height, + width: Self.simulatedWidth, height: height) + } + } + + // The notch widened on both sides, to hold the resting artwork / mode icons. + var extended: CGRect { + notch.insetBy(dx: -layout.sideExtension, dy: 0) + } + + // The right widening while resting: the music control (level bars, next / play on hover). + var restingTrailingZone: CGRect { + CGRect(x: extended.maxX - layout.sideExtension, y: notch.minY, width: layout.sideExtension, height: notch.height) + } + + var open: CGRect { + let width = max(layout.openSize.width, extended.width) + let height = max(layout.openSize.height, notch.height) + return CGRect(x: notch.midX - width / 2, y: notch.maxY - height, width: width, height: height) + } + + // Panel frame while resting; nil = hidden (nothing to show on a screen without a notch). + func restingFrame(for state: NotchRestingState) -> CGRect? { + switch state { + case .empty: return hasNotch ? notch : nil + default: return extended + } + } +} diff --git a/Client/macos/Notch/NotchMotion.swift b/Client/macos/Notch/NotchMotion.swift new file mode 100644 index 0000000..36700c7 --- /dev/null +++ b/Client/macos/Notch/NotchMotion.swift @@ -0,0 +1,75 @@ +import AppKit +import SwiftUI + +// Shared motion for the notch: springs, how content follows the shape, and button press feedback. +// With "Reduce motion" on, springs become short eases and nothing scales or moves. +enum NotchMotion { + static var reduceMotion: Bool { NSWorkspace.shared.accessibilityDisplayShouldReduceMotion } + + static var open: Animation { reduceMotion ? .easeInOut(duration: 0.15) : .spring(response: 0.36, dampingFraction: 0.74) } + static var close: Animation { reduceMotion ? .easeInOut(duration: 0.15) : .spring(response: 0.28, dampingFraction: 1) } + static var content: Animation { reduceMotion ? .easeInOut(duration: 0.15) : .spring(response: 0.3, dampingFraction: 0.85) } + + static let morphScale: CGFloat = 0.6 + + // The open panel's content grows out of the notch with the shape (same spring, no delay), instead of + // popping in after it: video at 60 fps showed a blurred panel appearing ~6 frames late. Closing is driven + // by NotchView (FadeScale on isOpen), and the content is unmounted once the shape has shrunk. + static var morph: AnyTransition { + .asymmetric( + insertion: .modifier(active: FadeScale(amount: 1, scale: morphScale), identity: FadeScale(amount: 0, scale: morphScale)), + removal: .identity) + } + + // The resting icons leave at once when the shape grows, and come back once it has shrunk. + static func resting(open: Bool) -> Animation { + open ? .easeOut(duration: 0.06) : .easeOut(duration: 0.2).delay(reduceMotion ? 0 : 0.12) + } +} + +// amount 0 = shown; 1 = transparent and scaled down to `scale` (anchored at the top, towards the notch). +// Opacity and transforms only: cheap to animate at 120 Hz, unlike blur. +struct FadeScale: ViewModifier { + let amount: CGFloat + var scale: CGFloat = 0.94 + + func body(content: Content) -> some View { + let motion = !NotchMotion.reduceMotion + return content + .opacity(Double(1 - amount)) + .scaleEffect(motion ? 1 - (1 - scale) * amount : 1, anchor: .top) + } +} + +// Buttons shrink a little while pressed, and spring back. +struct PressableButtonStyle: ButtonStyle { + func makeBody(configuration: Configuration) -> some View { + configuration.label + .scaleEffect(configuration.isPressed && !NotchMotion.reduceMotion ? 0.84 : 1) + .opacity(configuration.isPressed ? 0.7 : 1) + .animation(.spring(response: 0.25, dampingFraction: 0.6), value: configuration.isPressed) + } +} + +// Text and icon zoom inside the notch (Options › Notch Size › Text Size, already limited to what fits). +private struct NotchScaleKey: EnvironmentKey { + static let defaultValue: CGFloat = 1 +} + +extension EnvironmentValues { + var notchScale: CGFloat { + get { self[NotchScaleKey.self] } + set { self[NotchScaleKey.self] = newValue } + } +} + +extension View { + // SF Symbol swaps (play ↔ pause) morph on macOS 14+; older systems cross-fade. + @ViewBuilder func symbolReplaceTransition() -> some View { + if #available(macOS 14.0, *) { + contentTransition(.symbolEffect(.replace)) + } else { + self + } + } +} diff --git a/Client/macos/Notch/NotchPanel.swift b/Client/macos/Notch/NotchPanel.swift new file mode 100644 index 0000000..ad942c5 --- /dev/null +++ b/Client/macos/Notch/NotchPanel.swift @@ -0,0 +1,44 @@ +import AppKit +import SwiftUI + +// Borderless transparent panel above the menu bar (spec §4.3). It never becomes key or main, so the frontmost +// app keeps the keyboard; clicks still reach its controls through NotchHostingView. +final class NotchPanel: NSPanel { + // A factory rather than a custom init: NSWindow subclasses that declare their own initializer must also + // deal with NSWindow's required/unavailable initializers. + static func make() -> NotchPanel { + let panel = NotchPanel(contentRect: .zero, styleMask: [.borderless, .nonactivatingPanel], + backing: .buffered, defer: false) + panel.isOpaque = false + panel.backgroundColor = .clear + panel.hasShadow = false + panel.isMovable = false + panel.hidesOnDeactivate = false + panel.level = NSWindow.Level(rawValue: NSWindow.Level.mainMenu.rawValue + 2) + panel.collectionBehavior = [.canJoinAllSpaces, .stationary, .fullScreenAuxiliary, .ignoresCycle] + return panel + } + + override var canBecomeKey: Bool { false } + override var canBecomeMain: Bool { false } +} + +// Reports the pointer entering or leaving the panel, whichever app is active. +final class NotchContainerView: NSView { + var onHoverChange: (() -> Void)? + + override func updateTrackingAreas() { + super.updateTrackingAreas() + trackingAreas.forEach { removeTrackingArea($0) } + addTrackingArea(NSTrackingArea(rect: .zero, options: [.mouseEnteredAndExited, .activeAlways, .inVisibleRect], + owner: self, userInfo: nil)) + } + + override func mouseEntered(with event: NSEvent) { onHoverChange?() } + override func mouseExited(with event: NSEvent) { onHoverChange?() } +} + +// The panel is never key: without this, the first click would only be swallowed by the window. +final class NotchHostingView: NSHostingView { + override func acceptsFirstMouse(for event: NSEvent?) -> Bool { true } +} diff --git a/Client/macos/Notch/NotchView.swift b/Client/macos/Notch/NotchView.swift new file mode 100644 index 0000000..947be91 --- /dev/null +++ b/Client/macos/Notch/NotchView.swift @@ -0,0 +1,241 @@ +import AppKit +import SwiftUI + +// Written by NotchController, read by NotchView. +final class NotchViewState: ObservableObject { + @Published var isOpen = false + @Published var openContentMounted = false // true while open, and while the closing animation plays + @Published var trailingHovered = false // pointer over the resting music control + @Published var resting: NotchRestingState = .empty + @Published var tab: NotchTab = .music + @Published var restingSize: CGSize = .zero + @Published var openSize: CGSize = .zero + @Published var notchHeight: CGFloat = 32 + @Published var sideExtension = NotchLayout.default.sideExtension + @Published var contentScale: CGFloat = 1 // text and icon zoom, open notch + @Published var restingScale: CGFloat = 1 // same, resting icons + @Published var restingArtworkSize = NotchLayout.default.restingArtwork +} + +// Merges with the notch: the top corners flare out into the menu bar (concave, `topRadius` wide on each side, +// inside the rect), the bottom corners are rounded. +struct NotchShape: Shape { + var topRadius: CGFloat + var bottomRadius: CGFloat + + var animatableData: AnimatablePair { + get { AnimatablePair(topRadius, bottomRadius) } + set { (topRadius, bottomRadius) = (newValue.first, newValue.second) } + } + + func path(in rect: CGRect) -> Path { + let top = min(topRadius, rect.width / 4, rect.height / 2) + let body = rect.insetBy(dx: top, dy: 0) + let bottom = min(bottomRadius, body.width / 2, rect.height - top) + var path = Path() + path.move(to: CGPoint(x: rect.minX, y: rect.minY)) + path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY)) + path.addQuadCurve(to: CGPoint(x: body.maxX, y: rect.minY + top), control: CGPoint(x: body.maxX, y: rect.minY)) + path.addLine(to: CGPoint(x: body.maxX, y: rect.maxY - bottom)) + path.addQuadCurve(to: CGPoint(x: body.maxX - bottom, y: rect.maxY), control: CGPoint(x: body.maxX, y: rect.maxY)) + path.addLine(to: CGPoint(x: body.minX + bottom, y: rect.maxY)) + path.addQuadCurve(to: CGPoint(x: body.minX, y: rect.maxY - bottom), control: CGPoint(x: body.minX, y: rect.maxY)) + path.addLine(to: CGPoint(x: body.minX, y: rect.minY + top)) + path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.minY), control: CGPoint(x: body.minX, y: rect.minY)) + path.closeSubpath() + return path + } +} + +// Root view of the notch panel (spec §4): the resting strip, or the open panel (player or headphones page). The panel +// can be larger than the shape while it animates; the shape stays centred at the top. +struct NotchView: View { + static let openFlare: CGFloat = 10 + + @ObservedObject var state: NotchViewState + @ObservedObject var model: HeadphonesModel + @ObservedObject var music: MusicController + let selectTab: (NotchTab) -> Void + + var body: some View { + let size = state.isOpen ? state.openSize : state.restingSize + let shape = NotchShape(topRadius: state.isOpen ? Self.openFlare : 0, bottomRadius: state.isOpen ? 24 : 10) + ZStack(alignment: .top) { + shape.fill(Color.black) + if state.openContentMounted { + // Laid out at the final size and clipped by the growing shape, so text never reflows (or spills + // past the edges) while the spring animates. Grows in with a transition; shrinks out through the + // modifier below, since SwiftUI skipped the removal transition (content vanished at once). + openContent + .environment(\.notchScale, state.contentScale) + .padding(.top, state.notchHeight) + .frame(width: state.openSize.width, height: state.openSize.height) + .modifier(FadeScale(amount: state.isOpen ? 0 : 1, scale: NotchMotion.morphScale)) + .allowsHitTesting(state.isOpen) + .transition(NotchMotion.morph) + } + // Always mounted and faded on isOpen: an inserted resting strip (transition) didn't come back after + // a close while the open content was still mounted. + restingContent + .environment(\.notchScale, state.restingScale) + .opacity(state.isOpen ? 0 : 1) + .animation(NotchMotion.resting(open: state.isOpen), value: state.isOpen) + .allowsHitTesting(!state.isOpen) + } + // Top-aligned: the open content is taller than the shape while it grows, and the default (centred) + // alignment pushed it up past the top of the screen, then slid it down — the bar seemed to jump. + .frame(width: size.width, height: size.height, alignment: .top) + .clipShape(shape) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) + .environment(\.colorScheme, .dark) + } + + // MARK: - Resting (spec §4.1) + + private var restingContent: some View { + HStack(spacing: 0) { + leadingItem.frame(width: state.sideExtension) + Spacer(minLength: 0) + trailingItem.frame(width: state.sideExtension) + } + // Explicit width: while the (wider) open content is still mounted during a close, the strip otherwise + // took the open width, so the artwork and mode icon sat outside the shape (cut off), then jumped back. + .frame(width: state.restingSize.width, height: state.notchHeight) + } + + @ViewBuilder private var leadingItem: some View { + switch state.resting { + case .musicAndHeadphones, .musicOnly: + ArtworkView(image: music.artwork, size: state.restingArtworkSize, cornerRadius: state.restingArtworkSize * 0.25) + case .headphonesOnly: + Image(systemName: "headphones").font(.system(size: 13 * state.restingScale)).foregroundColor(.white) + case .empty: + EmptyView() + } + } + + @ViewBuilder private var trailingItem: some View { + switch state.resting { + case .musicAndHeadphones, .musicOnly: + RestingMusicControl(music: music, hovered: state.trailingHovered) + case .headphonesOnly: + Image(systemName: Self.modeSymbol(model.mode)).font(.system(size: 13 * state.restingScale)).foregroundColor(.white) + case .empty: + EmptyView() + } + } + + private static func modeSymbol(_ mode: SHCAmbientMode) -> String { + switch mode { + case .noiseCanceling: return "headphones.circle.fill" + case .ambientSound: return "ear.and.waveform" + default: return "circle.slash" + } + } + + // MARK: - Open (spec §4.2) + + private var openContent: some View { + // Both pages stay in the hierarchy (switching is then a cross-slide, not an insertion), the hidden one + // neither drawn, clickable nor read by VoiceOver. + ZStack(alignment: .top) { + page(.music) { MusicTab(music: music, showHeadphones: { selectTab(.headphones) }) } + page(.headphones) { HeadphonesTab(model: model, back: { selectTab(.music) }) } + } + .padding(.top, 8 * state.contentScale) + .padding(.horizontal, Self.openFlare + 16 * state.contentScale) + .padding(.bottom, 14 * state.contentScale) + } + + // The player slides off to the left, the headphones page comes in from the right (and back). No blur: it + // made each frame of the switch expensive. + private func page(_ tab: NotchTab, @ViewBuilder content: () -> Content) -> some View { + let selected = state.tab == tab + let motion = !NotchMotion.reduceMotion + return content() + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) + .scaleEffect(selected || !motion ? 1 : 0.96) + .offset(x: selected || !motion ? 0 : (tab == .music ? -24 : 24)) + .opacity(selected ? 1 : 0) + .allowsHitTesting(selected) + .accessibilityHidden(!selected) + } +} + +// Album artwork, or a placeholder note while it loads (or for tracks without one). +struct ArtworkView: View { + let image: NSImage? + let size: CGFloat + let cornerRadius: CGFloat + + var body: some View { + Group { + if let image = image { + Image(nsImage: image).resizable().aspectRatio(contentMode: .fill) + .id(ObjectIdentifier(image)) + .transition(.opacity) + } else { + ZStack { + Color(white: 0.2) + Image(systemName: "music.note").font(.system(size: size * 0.45)).foregroundColor(.gray) + } + } + } + .frame(width: size, height: size) + .clipShape(RoundedRectangle(cornerRadius: cornerRadius)) + .animation(.easeInOut(duration: 0.3), value: image.map(ObjectIdentifier.init)) + } +} + +// Right side of the resting notch while music is loaded: the level bars in the artwork's colour, replaced on +// hover by "next track" while playing, or "play" while paused. +struct RestingMusicControl: View { + @ObservedObject var music: MusicController + let hovered: Bool + @Environment(\.notchScale) private var s + + var body: some View { + let playing = music.nowPlaying?.isPlaying == true + ZStack { + LevelBars(animating: playing && !hovered, color: music.artworkTint) + .modifier(FadeScale(amount: hovered ? 1 : 0, scale: 0.6)) + Button { + if playing { music.next() } else { music.playPause() } + } label: { + Image(systemName: playing ? "forward.fill" : "play.fill") + .font(.system(size: 13 * s)) + .foregroundColor(.white) + .symbolReplaceTransition() + .frame(width: 30 * s, height: 26 * s) + .contentShape(Rectangle()) + } + .buttonStyle(PressableButtonStyle()) + .accessibilityLabel(playing ? tr("Next track") : tr("Play or pause")) + .modifier(FadeScale(amount: hovered ? 0 : 1, scale: 0.6)) + .allowsHitTesting(hovered) + .animation(NotchMotion.content, value: playing) + } + } +} + +// Four small bars in the artwork's colour, moving while music plays, frozen when paused. +struct LevelBars: View { + let animating: Bool + var color: NSColor? + @Environment(\.notchScale) private var s + + var body: some View { + TimelineView(.animation(minimumInterval: 1.0 / 30, paused: !animating)) { context in + let time = context.date.timeIntervalSinceReferenceDate + HStack(alignment: .bottom, spacing: 2 * s) { + ForEach(0..<4, id: \.self) { index in + Capsule() + .fill(color.map(Color.init(nsColor:)) ?? Color(white: 0.85)) + .frame(width: 3 * s, height: (animating ? 4 + 10 * abs(sin(time * 3 + Double(index) * 1.3)) : 4) * s) + } + } + .frame(height: 14 * s, alignment: .bottom) + .animation(.easeOut(duration: 0.3), value: animating) + } + } +} diff --git a/Client/macos/PollGuard.swift b/Client/macos/PollGuard.swift new file mode 100644 index 0000000..0fc4af3 --- /dev/null +++ b/Client/macos/PollGuard.swift @@ -0,0 +1,21 @@ +import Foundation + +// Ignores a polled value for a setting the user changed less than `window` seconds ago, so a read-back that +// raced the user's command doesn't briefly flip the menu back to the old state. +struct PollGuard { + let window: TimeInterval + private var lastUserChange: [Key: Date] = [:] + + init(window: TimeInterval = 3) { + self.window = window + } + + mutating func userChanged(_ key: Key, at date: Date = Date()) { + lastUserChange[key] = date + } + + func shouldAcceptPoll(for key: Key, at date: Date = Date()) -> Bool { + guard let changed = lastUserChange[key] else { return true } + return date.timeIntervalSince(changed) >= window + } +} diff --git a/Client/macos/ReconnectPolicy.swift b/Client/macos/ReconnectPolicy.swift new file mode 100644 index 0000000..dd54bd3 --- /dev/null +++ b/Client/macos/ReconnectPolicy.swift @@ -0,0 +1,18 @@ +import Foundation + +// Delays between automatic reconnection attempts: 3 s, 10 s, 30 s, then every 60 s. +struct ReconnectPolicy { + static let delays: [TimeInterval] = [3, 10, 30, 60] + private(set) var attempt = 0 + + // Delay before the next attempt; each call advances the schedule. + mutating func nextDelay() -> TimeInterval { + let delay = Self.delays[min(attempt, Self.delays.count - 1)] + attempt += 1 + return delay + } + + mutating func reset() { + attempt = 0 + } +} diff --git a/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_128.png b/Client/macos/Resources/AppIcon.iconset/icon_128x128.png similarity index 100% rename from Client/macos/Assets.xcassets/AppIcon.appiconset/icon_128.png rename to Client/macos/Resources/AppIcon.iconset/icon_128x128.png diff --git a/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_256.png b/Client/macos/Resources/AppIcon.iconset/icon_128x128@2x.png similarity index 100% rename from Client/macos/Assets.xcassets/AppIcon.appiconset/icon_256.png rename to Client/macos/Resources/AppIcon.iconset/icon_128x128@2x.png diff --git a/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_16.png b/Client/macos/Resources/AppIcon.iconset/icon_16x16.png similarity index 100% rename from Client/macos/Assets.xcassets/AppIcon.appiconset/icon_16.png rename to Client/macos/Resources/AppIcon.iconset/icon_16x16.png diff --git a/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_32.png b/Client/macos/Resources/AppIcon.iconset/icon_16x16@2x.png similarity index 100% rename from Client/macos/Assets.xcassets/AppIcon.appiconset/icon_32.png rename to Client/macos/Resources/AppIcon.iconset/icon_16x16@2x.png diff --git a/Client/macos/Resources/AppIcon.iconset/icon_256x256.png b/Client/macos/Resources/AppIcon.iconset/icon_256x256.png new file mode 100644 index 0000000..f4b375c Binary files /dev/null and b/Client/macos/Resources/AppIcon.iconset/icon_256x256.png differ diff --git a/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_512.png b/Client/macos/Resources/AppIcon.iconset/icon_256x256@2x.png similarity index 100% rename from Client/macos/Assets.xcassets/AppIcon.appiconset/icon_512.png rename to Client/macos/Resources/AppIcon.iconset/icon_256x256@2x.png diff --git a/Client/macos/Resources/AppIcon.iconset/icon_32x32.png b/Client/macos/Resources/AppIcon.iconset/icon_32x32.png new file mode 100644 index 0000000..c2ca381 Binary files /dev/null and b/Client/macos/Resources/AppIcon.iconset/icon_32x32.png differ diff --git a/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_64.png b/Client/macos/Resources/AppIcon.iconset/icon_32x32@2x.png similarity index 100% rename from Client/macos/Assets.xcassets/AppIcon.appiconset/icon_64.png rename to Client/macos/Resources/AppIcon.iconset/icon_32x32@2x.png diff --git a/Client/macos/Resources/AppIcon.iconset/icon_512x512.png b/Client/macos/Resources/AppIcon.iconset/icon_512x512.png new file mode 100644 index 0000000..53d9f1e Binary files /dev/null and b/Client/macos/Resources/AppIcon.iconset/icon_512x512.png differ diff --git a/Client/macos/Assets.xcassets/AppIcon.appiconset/icon_1024.png b/Client/macos/Resources/AppIcon.iconset/icon_512x512@2x.png similarity index 100% rename from Client/macos/Assets.xcassets/AppIcon.appiconset/icon_1024.png rename to Client/macos/Resources/AppIcon.iconset/icon_512x512@2x.png diff --git a/Client/macos/SendThrottle.swift b/Client/macos/SendThrottle.swift new file mode 100644 index 0000000..2ada2b7 --- /dev/null +++ b/Client/macos/SendThrottle.swift @@ -0,0 +1,19 @@ +import Foundation + +// Rate-limits slider commands: at most one every `interval` while dragging; the final value always goes out. +struct SendThrottle { + let interval: TimeInterval + private var lastSend: Date? + + init(interval: TimeInterval = 0.15) { + self.interval = interval + } + + mutating func shouldSend(at date: Date = Date(), final: Bool) -> Bool { + if !final, let last = lastSend, date.timeIntervalSince(last) < interval { + return false + } + lastSend = date + return true + } +} diff --git a/Client/macos/SonyHeadphonesClient.entitlements b/Client/macos/SonyHeadphonesClient.entitlements index e9da8e1..cbf07bf 100644 --- a/Client/macos/SonyHeadphonesClient.entitlements +++ b/Client/macos/SonyHeadphonesClient.entitlements @@ -8,5 +8,15 @@ com.apple.security.files.user-selected.read-only + com.apple.security.network.client + + com.apple.security.temporary-exception.apple-events + + com.spotify.client + + com.apple.security.temporary-exception.files.home-relative-path.read-write + + /Library/Logs/SonyNotch/ + diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj deleted file mode 100644 index 2ce1c62..0000000 --- a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj +++ /dev/null @@ -1,409 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 50; - objects = { - -/* Begin PBXBuildFile section */ - A87B328B259FAA8B00EA6551 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A87B328A259FAA8B00EA6551 /* Cocoa.framework */; }; - A87B328E259FAB0E00EA6551 /* IOBluetoothUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A87B328D259FAB0E00EA6551 /* IOBluetoothUI.framework */; }; - A8A3D31E283EC38600148E80 /* Headphones.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8A3D31D283EC38600148E80 /* Headphones.cpp */; }; - A8DC78EB2576923D00447738 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78EA2576923D00447738 /* main.mm */; }; - A8DC78EC2576923D00447738 /* MacOSBluetoothConnector.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */; }; - A8DC78F12576952E00447738 /* BluetoothWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78EF2576952E00447738 /* BluetoothWrapper.cpp */; }; - A8DC78F52576953600447738 /* CommandSerializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78F32576953600447738 /* CommandSerializer.cpp */; }; - A8DC78FA2576954100447738 /* TimedMessageQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78F92576954100447738 /* TimedMessageQueue.cpp */; }; - A8DC78FF2576967D00447738 /* ByteMagic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78FD2576967D00447738 /* ByteMagic.cpp */; }; - A8DC790525769A6600447738 /* IOBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8DC790425769A6600447738 /* IOBluetooth.framework */; }; - A8DC792C25769C9900447738 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC792825769C9900447738 /* AppDelegate.mm */; }; - A8DC792D25769C9900447738 /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC792A25769C9900447738 /* ViewController.mm */; }; - A8DC793225769EA500447738 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A8DC78E92576923D00447738 /* Main.storyboard */; }; - CC0000000000000000000001 /* HeadphonesBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC0000000000000000000002 /* HeadphonesBridge.mm */; }; - CC0000000000000000000004 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0000000000000000000005 /* ContentView.swift */; }; - CC0000000000000000000006 /* HeadphonesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0000000000000000000007 /* HeadphonesModel.swift */; }; - DD0000000000000000000001 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DD0000000000000000000002 /* Assets.xcassets */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - A863B14925A11DF500101F3B /* SonyHeadphonesClient.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SonyHeadphonesClient.entitlements; sourceTree = ""; }; - A87B327A259F69BA00EA6551 /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Constants.h; path = ../Constants.h; sourceTree = ""; }; - A87B328A259FAA8B00EA6551 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; - A87B328D259FAB0E00EA6551 /* IOBluetoothUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOBluetoothUI.framework; path = System/Library/Frameworks/IOBluetoothUI.framework; sourceTree = SDKROOT; }; - A8A3D31C283EC38500148E80 /* Headphones.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Headphones.h; path = ../Headphones.h; sourceTree = ""; }; - A8A3D31D283EC38600148E80 /* Headphones.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Headphones.cpp; path = ../Headphones.cpp; sourceTree = ""; }; - A8DC78E32576922700447738 /* info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = info.plist; sourceTree = ""; }; - A8DC78E62576922D00447738 /* SonyHeadphonesClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SonyHeadphonesClient.app; sourceTree = BUILT_PRODUCTS_DIR; }; - A8DC78E72576923D00447738 /* MacOSBluetoothConnector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MacOSBluetoothConnector.h; sourceTree = ""; }; - A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MacOSBluetoothConnector.mm; sourceTree = ""; }; - A8DC78E92576923D00447738 /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; - A8DC78EA2576923D00447738 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; - A8DC78EE2576950500447738 /* IBluetoothConnector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IBluetoothConnector.h; path = ../IBluetoothConnector.h; sourceTree = ""; }; - A8DC78EF2576952E00447738 /* BluetoothWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BluetoothWrapper.cpp; path = ../BluetoothWrapper.cpp; sourceTree = ""; }; - A8DC78F02576952E00447738 /* BluetoothWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BluetoothWrapper.h; path = ../BluetoothWrapper.h; sourceTree = ""; }; - A8DC78F32576953600447738 /* CommandSerializer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandSerializer.cpp; path = ../CommandSerializer.cpp; sourceTree = ""; }; - A8DC78F42576953600447738 /* CommandSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandSerializer.h; path = ../CommandSerializer.h; sourceTree = ""; }; - A8DC78F72576954100447738 /* TimedMessageQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TimedMessageQueue.h; path = ../TimedMessageQueue.h; sourceTree = ""; }; - A8DC78F82576954100447738 /* SingleInstanceFuture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SingleInstanceFuture.h; path = ../SingleInstanceFuture.h; sourceTree = ""; }; - A8DC78F92576954100447738 /* TimedMessageQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TimedMessageQueue.cpp; path = ../TimedMessageQueue.cpp; sourceTree = ""; }; - A8DC78FD2576967D00447738 /* ByteMagic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ByteMagic.cpp; path = ../ByteMagic.cpp; sourceTree = ""; }; - A8DC78FE2576967D00447738 /* ByteMagic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ByteMagic.h; path = ../ByteMagic.h; sourceTree = ""; }; - A8DC790425769A6600447738 /* IOBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOBluetooth.framework; path = System/Library/Frameworks/IOBluetooth.framework; sourceTree = SDKROOT; }; - A8DC792825769C9900447738 /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AppDelegate.mm; sourceTree = ""; }; - A8DC792925769C9900447738 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; - A8DC792A25769C9900447738 /* ViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewController.mm; sourceTree = ""; }; - A8DC792B25769C9900447738 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - CC0000000000000000000002 /* HeadphonesBridge.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = HeadphonesBridge.mm; sourceTree = ""; }; - CC0000000000000000000003 /* HeadphonesBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HeadphonesBridge.h; sourceTree = ""; }; - CC0000000000000000000005 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; - CC0000000000000000000007 /* HeadphonesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadphonesModel.swift; sourceTree = ""; }; - CC0000000000000000000008 /* SonyHeadphonesClient-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SonyHeadphonesClient-Bridging-Header.h"; sourceTree = ""; }; - DD0000000000000000000002 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - A8DC78C125757BF300447738 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - A87B328E259FAB0E00EA6551 /* IOBluetoothUI.framework in Frameworks */, - A87B328B259FAA8B00EA6551 /* Cocoa.framework in Frameworks */, - A8DC790525769A6600447738 /* IOBluetooth.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - A8DC78BB25757BF300447738 = { - isa = PBXGroup; - children = ( - A863B14925A11DF500101F3B /* SonyHeadphonesClient.entitlements */, - A87B327A259F69BA00EA6551 /* Constants.h */, - A8DC78E72576923D00447738 /* MacOSBluetoothConnector.h */, - A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */, - A8DC78EA2576923D00447738 /* main.mm */, - A8DC78E92576923D00447738 /* Main.storyboard */, - A8DC78E32576922700447738 /* info.plist */, - A8DC78E62576922D00447738 /* SonyHeadphonesClient.app */, - A8DC78EE2576950500447738 /* IBluetoothConnector.h */, - A8DC78EF2576952E00447738 /* BluetoothWrapper.cpp */, - A8DC78F02576952E00447738 /* BluetoothWrapper.h */, - A8DC78F32576953600447738 /* CommandSerializer.cpp */, - A8DC78F42576953600447738 /* CommandSerializer.h */, - A8DC78F82576954100447738 /* SingleInstanceFuture.h */, - A8DC78F92576954100447738 /* TimedMessageQueue.cpp */, - A8DC78F72576954100447738 /* TimedMessageQueue.h */, - A8DC78FD2576967D00447738 /* ByteMagic.cpp */, - A8DC78FE2576967D00447738 /* ByteMagic.h */, - A8A3D31D283EC38600148E80 /* Headphones.cpp */, - A8A3D31C283EC38500148E80 /* Headphones.h */, - A8DC792B25769C9900447738 /* AppDelegate.h */, - A8DC792825769C9900447738 /* AppDelegate.mm */, - A8DC792925769C9900447738 /* ViewController.h */, - A8DC792A25769C9900447738 /* ViewController.mm */, - CC0000000000000000000003 /* HeadphonesBridge.h */, - CC0000000000000000000002 /* HeadphonesBridge.mm */, - CC0000000000000000000005 /* ContentView.swift */, - CC0000000000000000000007 /* HeadphonesModel.swift */, - CC0000000000000000000008 /* SonyHeadphonesClient-Bridging-Header.h */, - DD0000000000000000000002 /* Assets.xcassets */, - A8DC790325769A6600447738 /* Frameworks */, - ); - sourceTree = ""; - }; - A8DC790325769A6600447738 /* Frameworks */ = { - isa = PBXGroup; - children = ( - A87B328D259FAB0E00EA6551 /* IOBluetoothUI.framework */, - A87B328A259FAA8B00EA6551 /* Cocoa.framework */, - A8DC790425769A6600447738 /* IOBluetooth.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - A8DC78C325757BF300447738 /* SonyHeadphonesClient */ = { - isa = PBXNativeTarget; - buildConfigurationList = A8DC78D825757BF500447738 /* Build configuration list for PBXNativeTarget "SonyHeadphonesClient" */; - buildPhases = ( - A8DC78C025757BF300447738 /* Sources */, - A8DC78C125757BF300447738 /* Frameworks */, - A8DC78C225757BF300447738 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SonyHeadphonesClient; - productName = SonyHeadphonesClient; - productReference = A8DC78E62576922D00447738 /* SonyHeadphonesClient.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - A8DC78BC25757BF300447738 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1230; - TargetAttributes = { - A8DC78C325757BF300447738 = { - CreatedOnToolsVersion = 12.2; - }; - }; - }; - buildConfigurationList = A8DC78BF25757BF300447738 /* Build configuration list for PBXProject "SonyHeadphonesClient" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = A8DC78BB25757BF300447738; - productRefGroup = A8DC78BB25757BF300447738; - projectDirPath = ""; - projectRoot = ""; - targets = ( - A8DC78C325757BF300447738 /* SonyHeadphonesClient */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - A8DC78C225757BF300447738 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A8DC793225769EA500447738 /* Main.storyboard in Resources */, - DD0000000000000000000001 /* Assets.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - A8DC78C025757BF300447738 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A8A3D31E283EC38600148E80 /* Headphones.cpp in Sources */, - A8DC78EB2576923D00447738 /* main.mm in Sources */, - A8DC78EC2576923D00447738 /* MacOSBluetoothConnector.mm in Sources */, - A8DC792D25769C9900447738 /* ViewController.mm in Sources */, - A8DC78F12576952E00447738 /* BluetoothWrapper.cpp in Sources */, - A8DC78FA2576954100447738 /* TimedMessageQueue.cpp in Sources */, - A8DC78F52576953600447738 /* CommandSerializer.cpp in Sources */, - A8DC78FF2576967D00447738 /* ByteMagic.cpp in Sources */, - A8DC792C25769C9900447738 /* AppDelegate.mm in Sources */, - CC0000000000000000000001 /* HeadphonesBridge.mm in Sources */, - CC0000000000000000000004 /* ContentView.swift in Sources */, - CC0000000000000000000006 /* HeadphonesModel.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - A8DC78D625757BF500447738 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 11.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - }; - name = Debug; - }; - A8DC78D725757BF500447738 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 11.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = macosx; - }; - name = Release; - }; - A8DC78D925757BF500447738 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_CXX_LANGUAGE_STANDARD = "c++17"; - CODE_SIGN_ENTITLEMENTS = SonyHeadphonesClient.entitlements; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = "$(SRCROOT)/info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 11.0; - OTHER_CPLUSPLUSFLAGS = ( - "-std=c++17", - "-stdlib=libc++", - "$(OTHER_CFLAGS)", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.semvis123.SonyHeadphonesClient; - PRODUCT_NAME = "$(TARGET_NAME)"; - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - SWIFT_VERSION = 5.0; - SWIFT_OBJC_BRIDGING_HEADER = "SonyHeadphonesClient-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - A8DC78DA25757BF500447738 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_CXX_LANGUAGE_STANDARD = "c++17"; - CODE_SIGN_ENTITLEMENTS = SonyHeadphonesClient.entitlements; - CODE_SIGN_IDENTITY = "-"; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = "$(SRCROOT)/info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 11.0; - OTHER_CPLUSPLUSFLAGS = ( - "-std=c++17", - "-stdlib=libc++", - "$(OTHER_CFLAGS)", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.semvis123.SonyHeadphonesClient; - PRODUCT_NAME = "$(TARGET_NAME)"; - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - SWIFT_VERSION = 5.0; - SWIFT_OBJC_BRIDGING_HEADER = "SonyHeadphonesClient-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - A8DC78BF25757BF300447738 /* Build configuration list for PBXProject "SonyHeadphonesClient" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - A8DC78D625757BF500447738 /* Debug */, - A8DC78D725757BF500447738 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - A8DC78D825757BF500447738 /* Build configuration list for PBXNativeTarget "SonyHeadphonesClient" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - A8DC78D925757BF500447738 /* Debug */, - A8DC78DA25757BF500447738 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = A8DC78BC25757BF300447738 /* Project object */; -} diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/Client/macos/SonyNotchApp.swift b/Client/macos/SonyNotchApp.swift new file mode 100644 index 0000000..d1d47bc --- /dev/null +++ b/Client/macos/SonyNotchApp.swift @@ -0,0 +1,30 @@ +import AppKit + +// Entry point: a menu bar-only app (LSUIElement), no window and no Dock icon. +@main +enum SonyNotchApp { + static func main() { + // The app is sandboxed, so it can only write inside the folder allowed by the + // temporary-exception entitlement. `make run` points it at + // ~/Library/Logs/SonyNotch/app.log (allowed by that exception); `open --stderr` + // fails on recent macOS, so the path is passed as a launch argument instead. + // Redirect stderr to the log file in append mode (unbuffered for live DEBUG hex + // dumps). freopen() closes stderr before it knows whether the reopen will + // succeed, so a sandbox denial would leave stderr closed with nothing to fall + // back to; open()+dup2() only touches stderr once we know the fd is valid. + if let logPath = UserDefaults.standard.string(forKey: "SonyNotchLogFile") { + let fd = open(logPath, O_WRONLY | O_CREAT | O_APPEND, 0o644) + if fd >= 0 { + dup2(fd, STDERR_FILENO) + close(fd) + setvbuf(stderr, nil, _IONBF, 0) + } + } + + let app = NSApplication.shared + let delegate = AppDelegate() + app.delegate = delegate + app.setActivationPolicy(.accessory) + withExtendedLifetime(delegate) { app.run() } + } +} diff --git a/Client/macos/StatusIcon.swift b/Client/macos/StatusIcon.swift new file mode 100644 index 0000000..478e907 --- /dev/null +++ b/Client/macos/StatusIcon.swift @@ -0,0 +1,20 @@ +import AppKit + +// Menu bar icon: one monochrome SF Symbol per mode, dimmed when disconnected (spec §6.6). +enum StatusIcon { + static func symbolName(for mode: SHCAmbientMode) -> String { + switch mode { + case .noiseCanceling: return "headphones.circle.fill" + case .ambientSound: return "ear.and.waveform" + default: return "headphones" + } + } + + static func image(connected: Bool, mode: SHCAmbientMode) -> NSImage? { + let name = connected ? symbolName(for: mode) : "headphones" + let image = NSImage(systemSymbolName: name, accessibilityDescription: "SonyNotch") + ?? NSImage(systemSymbolName: "headphones", accessibilityDescription: "SonyNotch") + image?.isTemplate = true // macOS tints it for light/dark menu bars + return image + } +} diff --git a/Client/macos/StatusItemController.swift b/Client/macos/StatusItemController.swift new file mode 100644 index 0000000..d46c776 --- /dev/null +++ b/Client/macos/StatusItemController.swift @@ -0,0 +1,22 @@ +import AppKit +import Combine + +// Owns the menu bar icon (it follows the mode and connection state) and attaches the headphones menu to it. +final class StatusItemController { + private let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength) + private let headphonesMenu: HeadphonesMenu + private var cancellables = Set() + + init(model: HeadphonesModel, settings: AppSettings) { + headphonesMenu = HeadphonesMenu(model: model, settings: settings) + statusItem.menu = headphonesMenu.menu + model.$connectionState.combineLatest(model.$mode) + .receive(on: DispatchQueue.main) + .sink { [weak self] state, mode in + let connected = state == .connected + self?.statusItem.button?.image = StatusIcon.image(connected: connected, mode: mode) + self?.statusItem.button?.appearsDisabled = !connected + } + .store(in: &cancellables) + } +} diff --git a/Client/macos/ViewController.h b/Client/macos/ViewController.h deleted file mode 100644 index df90ee3..0000000 --- a/Client/macos/ViewController.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// ViewController.h -// SonyHeadphonesClient -// -// Created by Sem Visscher on 01/12/2020. -// - -#import -#import "AppDelegate.h" - -BluetoothWrapper bt = (BluetoothWrapper)nil; -Headphones* headphones; -NSStatusItem* statusItem; - -@interface ViewController : NSViewController -@property (weak, nonatomic) IBOutlet NSTextField *connectedLabel; -@property (weak, nonatomic) IBOutlet NSTextField *ANCValuePrefixLabel; -@property (weak, nonatomic) IBOutlet NSTextField *ANCValueLabel; -@property (weak, nonatomic) IBOutlet NSButton *focusOnVoice; -@property (weak, nonatomic) IBOutlet NSButton *connectButton; -@property (weak, nonatomic) IBOutlet NSSlider *ANCSlider; -@property (weak, nonatomic) IBOutlet NSButton *ANCEnabled; -@property (weak, nonatomic) IBOutlet NSTextField *virtualSoundLabel; -@property (weak, nonatomic) IBOutlet NSTextField *soundPositionLabel; -@property (weak, nonatomic) IBOutlet NSTextField *surroundLabel; -@property (weak, nonatomic) IBOutlet NSPopUpButton *soundPosition; -@property (weak, nonatomic) IBOutlet NSPopUpButton *surround; - -@property (strong, nonatomic) NSView *vptCard; -@end - diff --git a/Client/macos/ViewController.mm b/Client/macos/ViewController.mm deleted file mode 100644 index 6577dc7..0000000 --- a/Client/macos/ViewController.mm +++ /dev/null @@ -1,51 +0,0 @@ -// -// ViewController.mm -// Thin AppKit host: the storyboard instantiates this controller; it swaps its content for the -// SwiftUI interface (built in ContentView.swift, exposed via the generated -Swift.h header). -// - -#import "ViewController.h" -#import "SonyHeadphonesClient-Swift.h" - -@implementation ViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - - // Drop the legacy storyboard controls; the SwiftUI view takes over the whole content area. - for (NSView *subview in [self.view.subviews copy]) { - [subview removeFromSuperview]; - } - - NSViewController *ui = [HeadphonesUIFactory makeViewController]; - [self addChildViewController:ui]; - ui.view.frame = self.view.bounds; - ui.view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; - [self.view addSubview:ui.view]; -} - -- (void)viewWillAppear { - [super viewWillAppear]; - - NSWindow *window = self.view.window; - if (!window) return; - - // The storyboard pins the window to a small fixed size; open it up to a portrait layout. - window.contentMinSize = NSMakeSize(360, 500); - window.contentMaxSize = NSMakeSize(560, 900); - window.styleMask |= NSWindowStyleMaskResizable; - [window setContentSize:NSMakeSize(380, 560)]; - window.titlebarAppearsTransparent = YES; - window.titleVisibility = NSWindowTitleHidden; - window.appearance = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua]; -} - -// Legacy storyboard action connections resolve to these no-op stubs (their controls are removed above). -- (IBAction)connectToDevice:(id)sender {} -- (IBAction)ANCSliderChanged:(id)sender {} -- (IBAction)ANCEnabledButtonChanged:(id)sender {} -- (IBAction)focusOnVoiceChanged:(id)sender {} -- (IBAction)surroundChanged:(id)sender {} -- (IBAction)soundPositionChanged:(id)sender {} - -@end diff --git a/Client/macos/en.lproj/InfoPlist.strings b/Client/macos/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..ab254ce --- /dev/null +++ b/Client/macos/en.lproj/InfoPlist.strings @@ -0,0 +1,3 @@ +/* Localized Info.plist values (English). Keeps an en.lproj in the bundle so non-French systems fall back to English. */ +"NSBluetoothAlwaysUsageDescription" = "This app uses Bluetooth in order to connect to your headphones."; +"NSAppleEventsUsageDescription" = "SonyNotch shows and controls the music playing in Spotify."; diff --git a/Client/macos/exportOptions.plist b/Client/macos/exportOptions.plist deleted file mode 100644 index c1e8fb6..0000000 --- a/Client/macos/exportOptions.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - method - mac-application - - diff --git a/Client/macos/fr.lproj/InfoPlist.strings b/Client/macos/fr.lproj/InfoPlist.strings new file mode 100644 index 0000000..54eb41d --- /dev/null +++ b/Client/macos/fr.lproj/InfoPlist.strings @@ -0,0 +1,3 @@ +/* Localized Info.plist values (French). */ +"NSBluetoothAlwaysUsageDescription" = "SonyNotch utilise le Bluetooth pour se connecter à votre casque."; +"NSAppleEventsUsageDescription" = "SonyNotch affiche et contrôle la musique en cours dans Spotify."; diff --git a/Client/macos/fr.lproj/Localizable.strings b/Client/macos/fr.lproj/Localizable.strings new file mode 100644 index 0000000..fa89187 --- /dev/null +++ b/Client/macos/fr.lproj/Localizable.strings @@ -0,0 +1,84 @@ +/* SonyNotch — French UI strings. Keys are the English source strings; missing keys fall back to English. */ + +/* Menu */ +"Ambient Sound Control" = "Contrôle du son ambiant"; +"Noise Canceling" = "Réduction de bruit"; +"Ambient Sound" = "Son ambiant"; +"Off" = "Désactivé"; +"Connect…" = "Connecter…"; +"Connecting…" = "Connexion…"; +"Disconnect" = "Déconnecter"; +"Quit SonyNotch" = "Quitter SonyNotch"; +"%ld%%" = "%ld %%"; +"Not connected" = "Non connecté"; +"Connected" = "Connecté"; +"L %ld%% R %ld%%" = "G %ld %% D %ld %%"; +"Case %ld%%" = "Boîtier %ld %%"; +"Clear Bass" = "Clear Bass"; +"Focus on Voice" = "Focalisation sur la voix"; +"Equalizer" = "Égaliseur"; +"Bright" = "Brillant"; +"Excited" = "Dynamique"; +"Mellow" = "Doux"; +"Relaxed" = "Détendu"; +"Vocal" = "Voix"; +"Treble" = "Aigus"; +"Bass" = "Graves"; +"Speech" = "Parole"; +"Manual" = "Manuel"; +"Custom" = "Personnalisé"; +"Equalizer changes coming soon for this model" = "Réglage de l’égaliseur bientôt disponible pour ce modèle"; +"Reset" = "Réinitialiser"; +"DSEE" = "DSEE"; +"Speak-to-Chat" = "Speak-to-Chat"; +"Adaptive Volume" = "Volume adaptatif"; +"Auto Power-Off" = "Arrêt automatique"; +"5 min" = "5 min"; +"30 min" = "30 min"; +"1 hour" = "1 heure"; +"3 hours" = "3 heures"; +"When taken off" = "Quand le casque est retiré"; +"Taken off" = "Quand retiré"; +"About the Headphones" = "À propos du casque"; +"Firmware" = "Firmware"; +"Codec" = "Codec"; +"Protocol" = "Protocole"; +"Bluetooth" = "Bluetooth"; +"SonyNotch Options" = "Options de SonyNotch"; +"Launch at Login" = "Lancer à l’ouverture de session"; +"Connect Automatically" = "Connexion automatique"; +"Reconnect Automatically" = "Reconnexion automatique"; +"Show Notch" = "Afficher l’encoche"; + +/* Errors (HeadphonesBridge.mm, HeadphonesModel.swift) */ +"No connected Sony headset found. Connect your headphones in macOS Bluetooth settings first." = "Aucun casque Sony connecté. Connectez d’abord votre casque dans les réglages Bluetooth de macOS."; +"Connection timed out." = "Délai de connexion dépassé."; +"Not connected." = "Non connecté."; +"Equalizer control isn't supported on this device yet." = "Le réglage de l’égaliseur n’est pas encore pris en charge sur cet appareil."; +"Not supported on this device." = "Non pris en charge sur cet appareil."; +"The headphones didn't respond." = "Le casque n’a pas répondu."; +"Couldn't open the control channel." = "Impossible d’ouvrir le canal de contrôle."; + +/* Notch (Notch/*.swift) */ +"Headphones" = "Casque"; +"Level" = "Niveau"; +"Spotify isn't open" = "Spotify n’est pas ouvert"; +"Open Spotify" = "Ouvrir Spotify"; +"SonyNotch isn't allowed to control Spotify." = "SonyNotch n’a pas l’autorisation de contrôler Spotify."; +"Open Settings" = "Ouvrir les réglages"; +"Nothing playing" = "Rien en cours de lecture"; +"Previous track" = "Morceau précédent"; +"Play or pause" = "Lecture ou pause"; +"Next track" = "Morceau suivant"; +"Spotify volume" = "Volume de Spotify"; +"Back" = "Retour"; +"Voice" = "Voix"; +"NC" = "Réduction"; +"Ambient" = "Ambiant"; +"Notch Size" = "Taille de l’encoche"; +"Open Width" = "Largeur ouverte"; +"Open Height" = "Hauteur ouverte"; +"Closed Width" = "Largeur fermée"; +"Text Size" = "Taille du texte"; +"Reset Size" = "Réinitialiser"; +"Closed Artwork" = "Pochette (fermée)"; diff --git a/Client/macos/info.plist b/Client/macos/info.plist index f2a1628..08b26b1 100644 --- a/Client/macos/info.plist +++ b/Client/macos/info.plist @@ -2,24 +2,43 @@ + CFBundleDevelopmentRegion + en + CFBundleLocalizations + + en + fr + CFBundleExecutable - SonyHeadphonesClient + SonyNotch CFBundleIdentifier com.semvis123.SonyHeadphonesClient CFBundleInfoDictionaryVersion 6.0 CFBundleName - SonyHeadphonesClient + SonyNotch + CFBundleDisplayName + SonyNotch CFBundlePackageType APPL + CFBundleShortVersionString + 0.5.0 + CFBundleVersion + 1 + CFBundleIconFile + AppIcon LSApplicationCategoryType public.app-category.utilities + LSMinimumSystemVersion + 13.0 + LSUIElement + NSHighResolutionCapable - True + NSBluetoothAlwaysUsageDescription This app uses Bluetooth in order to connect to your headphones. - NSMainStoryboardFile - Main + NSAppleEventsUsageDescription + SonyNotch shows and controls the music playing in Spotify. NSPrincipalClass NSApplication diff --git a/Client/macos/main.mm b/Client/macos/main.mm deleted file mode 100644 index 0eb4794..0000000 --- a/Client/macos/main.mm +++ /dev/null @@ -1,9 +0,0 @@ -#include -#import -#include "MacOSBluetoothConnector.h" -#include "BluetoothWrapper.h" - -int main(int argc, const char * argv[]) -{ - return NSApplicationMain(argc, argv); -} diff --git a/Client/resources/devices/linkbuds-s.png b/Client/resources/devices/linkbuds-s.png deleted file mode 100644 index 89f98ed..0000000 Binary files a/Client/resources/devices/linkbuds-s.png and /dev/null differ diff --git a/Client/resources/devices/mdr-xb950bt.png b/Client/resources/devices/mdr-xb950bt.png deleted file mode 100644 index 2362dac..0000000 Binary files a/Client/resources/devices/mdr-xb950bt.png and /dev/null differ diff --git a/Client/resources/devices/wf-1000xm4.png b/Client/resources/devices/wf-1000xm4.png deleted file mode 100644 index 418be7e..0000000 Binary files a/Client/resources/devices/wf-1000xm4.png and /dev/null differ diff --git a/Client/resources/devices/wf-1000xm5.png b/Client/resources/devices/wf-1000xm5.png deleted file mode 100644 index 413f582..0000000 Binary files a/Client/resources/devices/wf-1000xm5.png and /dev/null differ diff --git a/Client/resources/devices/wf-c700n.png b/Client/resources/devices/wf-c700n.png deleted file mode 100644 index 1e183ff..0000000 Binary files a/Client/resources/devices/wf-c700n.png and /dev/null differ diff --git a/Client/resources/devices/wh-1000xm2.png b/Client/resources/devices/wh-1000xm2.png deleted file mode 100644 index dd502bb..0000000 Binary files a/Client/resources/devices/wh-1000xm2.png and /dev/null differ diff --git a/Client/resources/devices/wh-1000xm3.png b/Client/resources/devices/wh-1000xm3.png deleted file mode 100644 index febf92e..0000000 Binary files a/Client/resources/devices/wh-1000xm3.png and /dev/null differ diff --git a/Client/resources/devices/wh-1000xm4.png b/Client/resources/devices/wh-1000xm4.png deleted file mode 100644 index 7b3662d..0000000 Binary files a/Client/resources/devices/wh-1000xm4.png and /dev/null differ diff --git a/Client/resources/devices/wh-1000xm5.png b/Client/resources/devices/wh-1000xm5.png deleted file mode 100644 index 5c58b84..0000000 Binary files a/Client/resources/devices/wh-1000xm5.png and /dev/null differ diff --git a/Client/resources/devices/wh-1000xm6.png b/Client/resources/devices/wh-1000xm6.png deleted file mode 100644 index 61f2e58..0000000 Binary files a/Client/resources/devices/wh-1000xm6.png and /dev/null differ diff --git a/Client/resources/devices/wh-ch520.png b/Client/resources/devices/wh-ch520.png deleted file mode 100644 index 3d30871..0000000 Binary files a/Client/resources/devices/wh-ch520.png and /dev/null differ diff --git a/Client/resources/devices/wh-ch720n.png b/Client/resources/devices/wh-ch720n.png deleted file mode 100644 index e885a9b..0000000 Binary files a/Client/resources/devices/wh-ch720n.png and /dev/null differ diff --git a/Client/resources/devices/wh-xb900n.png b/Client/resources/devices/wh-xb900n.png deleted file mode 100644 index 08a7f3e..0000000 Binary files a/Client/resources/devices/wh-xb900n.png and /dev/null differ diff --git a/Client/resources/devices/wh-xb910n.png b/Client/resources/devices/wh-xb910n.png deleted file mode 100644 index b40b633..0000000 Binary files a/Client/resources/devices/wh-xb910n.png and /dev/null differ diff --git a/Client/stb_image.h b/Client/stb_image.h deleted file mode 100644 index 9eedabe..0000000 --- a/Client/stb_image.h +++ /dev/null @@ -1,7988 +0,0 @@ -/* stb_image - v2.30 - public domain image loader - http://nothings.org/stb - no warranty implied; use at your own risk - - Do this: - #define STB_IMAGE_IMPLEMENTATION - before you include this file in *one* C or C++ file to create the implementation. - - // i.e. it should look like this: - #include ... - #include ... - #include ... - #define STB_IMAGE_IMPLEMENTATION - #include "stb_image.h" - - You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. - And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free - - - QUICK NOTES: - Primarily of interest to game developers and other people who can - avoid problematic images and only need the trivial interface - - JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) - PNG 1/2/4/8/16-bit-per-channel - - TGA (not sure what subset, if a subset) - BMP non-1bpp, non-RLE - PSD (composited view only, no extra channels, 8/16 bit-per-channel) - - GIF (*comp always reports as 4-channel) - HDR (radiance rgbE format) - PIC (Softimage PIC) - PNM (PPM and PGM binary only) - - Animated GIF still needs a proper API, but here's one way to do it: - http://gist.github.com/urraka/685d9a6340b26b830d49 - - - decode from memory or through FILE (define STBI_NO_STDIO to remove code) - - decode from arbitrary I/O callbacks - - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) - - Full documentation under "DOCUMENTATION" below. - - -LICENSE - - See end of file for license information. - -RECENT REVISION HISTORY: - - 2.30 (2024-05-31) avoid erroneous gcc warning - 2.29 (2023-05-xx) optimizations - 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff - 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes - 2.26 (2020-07-13) many minor fixes - 2.25 (2020-02-02) fix warnings - 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically - 2.23 (2019-08-11) fix clang static analysis warning - 2.22 (2019-03-04) gif fixes, fix warnings - 2.21 (2019-02-25) fix typo in comment - 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs - 2.19 (2018-02-11) fix warning - 2.18 (2018-01-30) fix warnings - 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings - 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes - 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC - 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs - 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes - 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes - 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 - RGB-format JPEG; remove white matting in PSD; - allocate large structures on the stack; - correct channel count for PNG & BMP - 2.10 (2016-01-22) avoid warning introduced in 2.09 - 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED - - See end of file for full revision history. - - - ============================ Contributors ========================= - - Image formats Extensions, features - Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) - Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) - Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) - Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) - Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) - Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) - Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) - github:urraka (animated gif) Junggon Kim (PNM comments) - Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) - socks-the-fox (16-bit PNG) - Jeremy Sawicki (handle all ImageNet JPGs) - Optimizations & bugfixes Mikhail Morozov (1-bit BMP) - Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) - Arseny Kapoulkine Simon Breuss (16-bit PNM) - John-Mark Allen - Carmelo J Fdez-Aguera - - Bug & warning fixes - Marc LeBlanc David Woo Guillaume George Martins Mozeiko - Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski - Phil Jordan Dave Moore Roy Eltham - Hayaki Saito Nathan Reed Won Chun - Luke Graham Johan Duparc Nick Verigakis the Horde3D community - Thomas Ruf Ronny Chevalier github:rlyeh - Janez Zemva John Bartholomew Michal Cichon github:romigrou - Jonathan Blow Ken Hamada Tero Hanninen github:svdijk - Eugene Golushkov Laurent Gomila Cort Stratton github:snagar - Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex - Cass Everitt Ryamond Barbiero github:grim210 - Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw - Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus - Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo - Julian Raschke Gregory Mullen Christian Floisand github:darealshinji - Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 - Brad Weinberger Matvey Cherevko github:mosra - Luca Sas Alexander Veselov Zack Middleton [reserved] - Ryan C. Gordon [reserved] [reserved] - DO NOT ADD YOUR NAME HERE - - Jacko Dirks - - To add your name to the credits, pick a random blank space in the middle and fill it. - 80% of merge conflicts on stb PRs are due to people adding their name at the end - of the credits. -*/ - -#ifndef STBI_INCLUDE_STB_IMAGE_H -#define STBI_INCLUDE_STB_IMAGE_H - -// DOCUMENTATION -// -// Limitations: -// - no 12-bit-per-channel JPEG -// - no JPEGs with arithmetic coding -// - GIF always returns *comp=4 -// -// Basic usage (see HDR discussion below for HDR usage): -// int x,y,n; -// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); -// // ... process data if not NULL ... -// // ... x = width, y = height, n = # 8-bit components per pixel ... -// // ... replace '0' with '1'..'4' to force that many components per pixel -// // ... but 'n' will always be the number that it would have been if you said 0 -// stbi_image_free(data); -// -// Standard parameters: -// int *x -- outputs image width in pixels -// int *y -- outputs image height in pixels -// int *channels_in_file -- outputs # of image components in image file -// int desired_channels -- if non-zero, # of image components requested in result -// -// The return value from an image loader is an 'unsigned char *' which points -// to the pixel data, or NULL on an allocation failure or if the image is -// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, -// with each pixel consisting of N interleaved 8-bit components; the first -// pixel pointed to is top-left-most in the image. There is no padding between -// image scanlines or between pixels, regardless of format. The number of -// components N is 'desired_channels' if desired_channels is non-zero, or -// *channels_in_file otherwise. If desired_channels is non-zero, -// *channels_in_file has the number of components that _would_ have been -// output otherwise. E.g. if you set desired_channels to 4, you will always -// get RGBA output, but you can check *channels_in_file to see if it's trivially -// opaque because e.g. there were only 3 channels in the source image. -// -// An output image with N components has the following components interleaved -// in this order in each pixel: -// -// N=#comp components -// 1 grey -// 2 grey, alpha -// 3 red, green, blue -// 4 red, green, blue, alpha -// -// If image loading fails for any reason, the return value will be NULL, -// and *x, *y, *channels_in_file will be unchanged. The function -// stbi_failure_reason() can be queried for an extremely brief, end-user -// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS -// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly -// more user-friendly ones. -// -// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. -// -// To query the width, height and component count of an image without having to -// decode the full file, you can use the stbi_info family of functions: -// -// int x,y,n,ok; -// ok = stbi_info(filename, &x, &y, &n); -// // returns ok=1 and sets x, y, n if image is a supported format, -// // 0 otherwise. -// -// Note that stb_image pervasively uses ints in its public API for sizes, -// including sizes of memory buffers. This is now part of the API and thus -// hard to change without causing breakage. As a result, the various image -// loaders all have certain limits on image size; these differ somewhat -// by format but generally boil down to either just under 2GB or just under -// 1GB. When the decoded image would be larger than this, stb_image decoding -// will fail. -// -// Additionally, stb_image will reject image files that have any of their -// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS, -// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit, -// the only way to have an image with such dimensions load correctly -// is for it to have a rather extreme aspect ratio. Either way, the -// assumption here is that such larger images are likely to be malformed -// or malicious. If you do need to load an image with individual dimensions -// larger than that, and it still fits in the overall size limit, you can -// #define STBI_MAX_DIMENSIONS on your own to be something larger. -// -// =========================================================================== -// -// UNICODE: -// -// If compiling for Windows and you wish to use Unicode filenames, compile -// with -// #define STBI_WINDOWS_UTF8 -// and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert -// Windows wchar_t filenames to utf8. -// -// =========================================================================== -// -// Philosophy -// -// stb libraries are designed with the following priorities: -// -// 1. easy to use -// 2. easy to maintain -// 3. good performance -// -// Sometimes I let "good performance" creep up in priority over "easy to maintain", -// and for best performance I may provide less-easy-to-use APIs that give higher -// performance, in addition to the easy-to-use ones. Nevertheless, it's important -// to keep in mind that from the standpoint of you, a client of this library, -// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. -// -// Some secondary priorities arise directly from the first two, some of which -// provide more explicit reasons why performance can't be emphasized. -// -// - Portable ("ease of use") -// - Small source code footprint ("easy to maintain") -// - No dependencies ("ease of use") -// -// =========================================================================== -// -// I/O callbacks -// -// I/O callbacks allow you to read from arbitrary sources, like packaged -// files or some other source. Data read from callbacks are processed -// through a small internal buffer (currently 128 bytes) to try to reduce -// overhead. -// -// The three functions you must define are "read" (reads some bytes of data), -// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). -// -// =========================================================================== -// -// SIMD support -// -// The JPEG decoder will try to automatically use SIMD kernels on x86 when -// supported by the compiler. For ARM Neon support, you must explicitly -// request it. -// -// (The old do-it-yourself SIMD API is no longer supported in the current -// code.) -// -// On x86, SSE2 will automatically be used when available based on a run-time -// test; if not, the generic C versions are used as a fall-back. On ARM targets, -// the typical path is to have separate builds for NEON and non-NEON devices -// (at least this is true for iOS and Android). Therefore, the NEON support is -// toggled by a build flag: define STBI_NEON to get NEON loops. -// -// If for some reason you do not want to use any of SIMD code, or if -// you have issues compiling it, you can disable it entirely by -// defining STBI_NO_SIMD. -// -// =========================================================================== -// -// HDR image support (disable by defining STBI_NO_HDR) -// -// stb_image supports loading HDR images in general, and currently the Radiance -// .HDR file format specifically. You can still load any file through the existing -// interface; if you attempt to load an HDR file, it will be automatically remapped -// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; -// both of these constants can be reconfigured through this interface: -// -// stbi_hdr_to_ldr_gamma(2.2f); -// stbi_hdr_to_ldr_scale(1.0f); -// -// (note, do not use _inverse_ constants; stbi_image will invert them -// appropriately). -// -// Additionally, there is a new, parallel interface for loading files as -// (linear) floats to preserve the full dynamic range: -// -// float *data = stbi_loadf(filename, &x, &y, &n, 0); -// -// If you load LDR images through this interface, those images will -// be promoted to floating point values, run through the inverse of -// constants corresponding to the above: -// -// stbi_ldr_to_hdr_scale(1.0f); -// stbi_ldr_to_hdr_gamma(2.2f); -// -// Finally, given a filename (or an open file or memory block--see header -// file for details) containing image data, you can query for the "most -// appropriate" interface to use (that is, whether the image is HDR or -// not), using: -// -// stbi_is_hdr(char *filename); -// -// =========================================================================== -// -// iPhone PNG support: -// -// We optionally support converting iPhone-formatted PNGs (which store -// premultiplied BGRA) back to RGB, even though they're internally encoded -// differently. To enable this conversion, call -// stbi_convert_iphone_png_to_rgb(1). -// -// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per -// pixel to remove any premultiplied alpha *only* if the image file explicitly -// says there's premultiplied data (currently only happens in iPhone images, -// and only if iPhone convert-to-rgb processing is on). -// -// =========================================================================== -// -// ADDITIONAL CONFIGURATION -// -// - You can suppress implementation of any of the decoders to reduce -// your code footprint by #defining one or more of the following -// symbols before creating the implementation. -// -// STBI_NO_JPEG -// STBI_NO_PNG -// STBI_NO_BMP -// STBI_NO_PSD -// STBI_NO_TGA -// STBI_NO_GIF -// STBI_NO_HDR -// STBI_NO_PIC -// STBI_NO_PNM (.ppm and .pgm) -// -// - You can request *only* certain decoders and suppress all other ones -// (this will be more forward-compatible, as addition of new decoders -// doesn't require you to disable them explicitly): -// -// STBI_ONLY_JPEG -// STBI_ONLY_PNG -// STBI_ONLY_BMP -// STBI_ONLY_PSD -// STBI_ONLY_TGA -// STBI_ONLY_GIF -// STBI_ONLY_HDR -// STBI_ONLY_PIC -// STBI_ONLY_PNM (.ppm and .pgm) -// -// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still -// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB -// -// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater -// than that size (in either width or height) without further processing. -// This is to let programs in the wild set an upper bound to prevent -// denial-of-service attacks on untrusted data, as one could generate a -// valid image of gigantic dimensions and force stb_image to allocate a -// huge block of memory and spend disproportionate time decoding it. By -// default this is set to (1 << 24), which is 16777216, but that's still -// very big. - -#ifndef STBI_NO_STDIO -#include -#endif // STBI_NO_STDIO - -#define STBI_VERSION 1 - -enum -{ - STBI_default = 0, // only used for desired_channels - - STBI_grey = 1, - STBI_grey_alpha = 2, - STBI_rgb = 3, - STBI_rgb_alpha = 4 -}; - -#include -typedef unsigned char stbi_uc; -typedef unsigned short stbi_us; - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef STBIDEF -#ifdef STB_IMAGE_STATIC -#define STBIDEF static -#else -#define STBIDEF extern -#endif -#endif - -////////////////////////////////////////////////////////////////////////////// -// -// PRIMARY API - works on images of any type -// - -// -// load image by filename, open file, or memory buffer -// - -typedef struct -{ - int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read - void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative - int (*eof) (void *user); // returns nonzero if we are at end of file/data -} stbi_io_callbacks; - -//////////////////////////////////// -// -// 8-bits-per-channel interface -// - -STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); -STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); - -#ifndef STBI_NO_STDIO -STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); -STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); -// for stbi_load_from_file, file pointer is left pointing immediately after image -#endif - -#ifndef STBI_NO_GIF -STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); -#endif - -#ifdef STBI_WINDOWS_UTF8 -STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); -#endif - -//////////////////////////////////// -// -// 16-bits-per-channel interface -// - -STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); -STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); - -#ifndef STBI_NO_STDIO -STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); -STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); -#endif - -//////////////////////////////////// -// -// float-per-channel interface -// -#ifndef STBI_NO_LINEAR - STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); - STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); - - #ifndef STBI_NO_STDIO - STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); - STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); - #endif -#endif - -#ifndef STBI_NO_HDR - STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); - STBIDEF void stbi_hdr_to_ldr_scale(float scale); -#endif // STBI_NO_HDR - -#ifndef STBI_NO_LINEAR - STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); - STBIDEF void stbi_ldr_to_hdr_scale(float scale); -#endif // STBI_NO_LINEAR - -// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR -STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); -STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); -#ifndef STBI_NO_STDIO -STBIDEF int stbi_is_hdr (char const *filename); -STBIDEF int stbi_is_hdr_from_file(FILE *f); -#endif // STBI_NO_STDIO - - -// get a VERY brief reason for failure -// on most compilers (and ALL modern mainstream compilers) this is threadsafe -STBIDEF const char *stbi_failure_reason (void); - -// free the loaded image -- this is just free() -STBIDEF void stbi_image_free (void *retval_from_stbi_load); - -// get image dimensions & components without fully decoding -STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); -STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); -STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); -STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); - -#ifndef STBI_NO_STDIO -STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); -STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); -STBIDEF int stbi_is_16_bit (char const *filename); -STBIDEF int stbi_is_16_bit_from_file(FILE *f); -#endif - - - -// for image formats that explicitly notate that they have premultiplied alpha, -// we just return the colors as stored in the file. set this flag to force -// unpremultiplication. results are undefined if the unpremultiply overflow. -STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); - -// indicate whether we should process iphone images back to canonical format, -// or just pass them through "as-is" -STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); - -// flip the image vertically, so the first pixel in the output array is the bottom left -STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); - -// as above, but only applies to images loaded on the thread that calls the function -// this function is only available if your compiler supports thread-local variables; -// calling it will fail to link if your compiler doesn't -STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply); -STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert); -STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip); - -// ZLIB client - used by PNG, available for other purposes - -STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); -STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); -STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); -STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); - -STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); -STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); - - -#ifdef __cplusplus -} -#endif - -// -// -//// end header file ///////////////////////////////////////////////////// -#endif // STBI_INCLUDE_STB_IMAGE_H - -#ifdef STB_IMAGE_IMPLEMENTATION - -#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ - || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ - || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ - || defined(STBI_ONLY_ZLIB) - #ifndef STBI_ONLY_JPEG - #define STBI_NO_JPEG - #endif - #ifndef STBI_ONLY_PNG - #define STBI_NO_PNG - #endif - #ifndef STBI_ONLY_BMP - #define STBI_NO_BMP - #endif - #ifndef STBI_ONLY_PSD - #define STBI_NO_PSD - #endif - #ifndef STBI_ONLY_TGA - #define STBI_NO_TGA - #endif - #ifndef STBI_ONLY_GIF - #define STBI_NO_GIF - #endif - #ifndef STBI_ONLY_HDR - #define STBI_NO_HDR - #endif - #ifndef STBI_ONLY_PIC - #define STBI_NO_PIC - #endif - #ifndef STBI_ONLY_PNM - #define STBI_NO_PNM - #endif -#endif - -#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) -#define STBI_NO_ZLIB -#endif - - -#include -#include // ptrdiff_t on osx -#include -#include -#include - -#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) -#include // ldexp, pow -#endif - -#ifndef STBI_NO_STDIO -#include -#endif - -#ifndef STBI_ASSERT -#include -#define STBI_ASSERT(x) assert(x) -#endif - -#ifdef __cplusplus -#define STBI_EXTERN extern "C" -#else -#define STBI_EXTERN extern -#endif - - -#ifndef _MSC_VER - #ifdef __cplusplus - #define stbi_inline inline - #else - #define stbi_inline - #endif -#else - #define stbi_inline __forceinline -#endif - -#ifndef STBI_NO_THREAD_LOCALS - #if defined(__cplusplus) && __cplusplus >= 201103L - #define STBI_THREAD_LOCAL thread_local - #elif defined(__GNUC__) && __GNUC__ < 5 - #define STBI_THREAD_LOCAL __thread - #elif defined(_MSC_VER) - #define STBI_THREAD_LOCAL __declspec(thread) - #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) - #define STBI_THREAD_LOCAL _Thread_local - #endif - - #ifndef STBI_THREAD_LOCAL - #if defined(__GNUC__) - #define STBI_THREAD_LOCAL __thread - #endif - #endif -#endif - -#if defined(_MSC_VER) || defined(__SYMBIAN32__) -typedef unsigned short stbi__uint16; -typedef signed short stbi__int16; -typedef unsigned int stbi__uint32; -typedef signed int stbi__int32; -#else -#include -typedef uint16_t stbi__uint16; -typedef int16_t stbi__int16; -typedef uint32_t stbi__uint32; -typedef int32_t stbi__int32; -#endif - -// should produce compiler error if size is wrong -typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; - -#ifdef _MSC_VER -#define STBI_NOTUSED(v) (void)(v) -#else -#define STBI_NOTUSED(v) (void)sizeof(v) -#endif - -#ifdef _MSC_VER -#define STBI_HAS_LROTL -#endif - -#ifdef STBI_HAS_LROTL - #define stbi_lrot(x,y) _lrotl(x,y) -#else - #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (-(y) & 31))) -#endif - -#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) -// ok -#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) -// ok -#else -#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." -#endif - -#ifndef STBI_MALLOC -#define STBI_MALLOC(sz) malloc(sz) -#define STBI_REALLOC(p,newsz) realloc(p,newsz) -#define STBI_FREE(p) free(p) -#endif - -#ifndef STBI_REALLOC_SIZED -#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) -#endif - -// x86/x64 detection -#if defined(__x86_64__) || defined(_M_X64) -#define STBI__X64_TARGET -#elif defined(__i386) || defined(_M_IX86) -#define STBI__X86_TARGET -#endif - -#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) -// gcc doesn't support sse2 intrinsics unless you compile with -msse2, -// which in turn means it gets to use SSE2 everywhere. This is unfortunate, -// but previous attempts to provide the SSE2 functions with runtime -// detection caused numerous issues. The way architecture extensions are -// exposed in GCC/Clang is, sadly, not really suited for one-file libs. -// New behavior: if compiled with -msse2, we use SSE2 without any -// detection; if not, we don't use it at all. -#define STBI_NO_SIMD -#endif - -#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) -// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET -// -// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the -// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. -// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not -// simultaneously enabling "-mstackrealign". -// -// See https://github.com/nothings/stb/issues/81 for more information. -// -// So default to no SSE2 on 32-bit MinGW. If you've read this far and added -// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. -#define STBI_NO_SIMD -#endif - -#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) -#define STBI_SSE2 -#include - -#ifdef _MSC_VER - -#if _MSC_VER >= 1400 // not VC6 -#include // __cpuid -static int stbi__cpuid3(void) -{ - int info[4]; - __cpuid(info,1); - return info[3]; -} -#else -static int stbi__cpuid3(void) -{ - int res; - __asm { - mov eax,1 - cpuid - mov res,edx - } - return res; -} -#endif - -#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name - -#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) -static int stbi__sse2_available(void) -{ - int info3 = stbi__cpuid3(); - return ((info3 >> 26) & 1) != 0; -} -#endif - -#else // assume GCC-style if not VC++ -#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) - -#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) -static int stbi__sse2_available(void) -{ - // If we're even attempting to compile this on GCC/Clang, that means - // -msse2 is on, which means the compiler is allowed to use SSE2 - // instructions at will, and so are we. - return 1; -} -#endif - -#endif -#endif - -// ARM NEON -#if defined(STBI_NO_SIMD) && defined(STBI_NEON) -#undef STBI_NEON -#endif - -#ifdef STBI_NEON -#include -#ifdef _MSC_VER -#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name -#else -#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) -#endif -#endif - -#ifndef STBI_SIMD_ALIGN -#define STBI_SIMD_ALIGN(type, name) type name -#endif - -#ifndef STBI_MAX_DIMENSIONS -#define STBI_MAX_DIMENSIONS (1 << 24) -#endif - -/////////////////////////////////////////////// -// -// stbi__context struct and start_xxx functions - -// stbi__context structure is our basic context used by all images, so it -// contains all the IO context, plus some basic image information -typedef struct -{ - stbi__uint32 img_x, img_y; - int img_n, img_out_n; - - stbi_io_callbacks io; - void *io_user_data; - - int read_from_callbacks; - int buflen; - stbi_uc buffer_start[128]; - int callback_already_read; - - stbi_uc *img_buffer, *img_buffer_end; - stbi_uc *img_buffer_original, *img_buffer_original_end; -} stbi__context; - - -static void stbi__refill_buffer(stbi__context *s); - -// initialize a memory-decode context -static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) -{ - s->io.read = NULL; - s->read_from_callbacks = 0; - s->callback_already_read = 0; - s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; - s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; -} - -// initialize a callback-based context -static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) -{ - s->io = *c; - s->io_user_data = user; - s->buflen = sizeof(s->buffer_start); - s->read_from_callbacks = 1; - s->callback_already_read = 0; - s->img_buffer = s->img_buffer_original = s->buffer_start; - stbi__refill_buffer(s); - s->img_buffer_original_end = s->img_buffer_end; -} - -#ifndef STBI_NO_STDIO - -static int stbi__stdio_read(void *user, char *data, int size) -{ - return (int) fread(data,1,size,(FILE*) user); -} - -static void stbi__stdio_skip(void *user, int n) -{ - int ch; - fseek((FILE*) user, n, SEEK_CUR); - ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */ - if (ch != EOF) { - ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */ - } -} - -static int stbi__stdio_eof(void *user) -{ - return feof((FILE*) user) || ferror((FILE *) user); -} - -static stbi_io_callbacks stbi__stdio_callbacks = -{ - stbi__stdio_read, - stbi__stdio_skip, - stbi__stdio_eof, -}; - -static void stbi__start_file(stbi__context *s, FILE *f) -{ - stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); -} - -//static void stop_file(stbi__context *s) { } - -#endif // !STBI_NO_STDIO - -static void stbi__rewind(stbi__context *s) -{ - // conceptually rewind SHOULD rewind to the beginning of the stream, - // but we just rewind to the beginning of the initial buffer, because - // we only use it after doing 'test', which only ever looks at at most 92 bytes - s->img_buffer = s->img_buffer_original; - s->img_buffer_end = s->img_buffer_original_end; -} - -enum -{ - STBI_ORDER_RGB, - STBI_ORDER_BGR -}; - -typedef struct -{ - int bits_per_channel; - int num_channels; - int channel_order; -} stbi__result_info; - -#ifndef STBI_NO_JPEG -static int stbi__jpeg_test(stbi__context *s); -static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); -static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_PNG -static int stbi__png_test(stbi__context *s); -static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); -static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); -static int stbi__png_is16(stbi__context *s); -#endif - -#ifndef STBI_NO_BMP -static int stbi__bmp_test(stbi__context *s); -static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); -static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_TGA -static int stbi__tga_test(stbi__context *s); -static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); -static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_PSD -static int stbi__psd_test(stbi__context *s); -static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); -static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); -static int stbi__psd_is16(stbi__context *s); -#endif - -#ifndef STBI_NO_HDR -static int stbi__hdr_test(stbi__context *s); -static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); -static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_PIC -static int stbi__pic_test(stbi__context *s); -static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); -static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_GIF -static int stbi__gif_test(stbi__context *s); -static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); -static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); -static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_PNM -static int stbi__pnm_test(stbi__context *s); -static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); -static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); -static int stbi__pnm_is16(stbi__context *s); -#endif - -static -#ifdef STBI_THREAD_LOCAL -STBI_THREAD_LOCAL -#endif -const char *stbi__g_failure_reason; - -STBIDEF const char *stbi_failure_reason(void) -{ - return stbi__g_failure_reason; -} - -#ifndef STBI_NO_FAILURE_STRINGS -static int stbi__err(const char *str) -{ - stbi__g_failure_reason = str; - return 0; -} -#endif - -static void *stbi__malloc(size_t size) -{ - return STBI_MALLOC(size); -} - -// stb_image uses ints pervasively, including for offset calculations. -// therefore the largest decoded image size we can support with the -// current code, even on 64-bit targets, is INT_MAX. this is not a -// significant limitation for the intended use case. -// -// we do, however, need to make sure our size calculations don't -// overflow. hence a few helper functions for size calculations that -// multiply integers together, making sure that they're non-negative -// and no overflow occurs. - -// return 1 if the sum is valid, 0 on overflow. -// negative terms are considered invalid. -static int stbi__addsizes_valid(int a, int b) -{ - if (b < 0) return 0; - // now 0 <= b <= INT_MAX, hence also - // 0 <= INT_MAX - b <= INTMAX. - // And "a + b <= INT_MAX" (which might overflow) is the - // same as a <= INT_MAX - b (no overflow) - return a <= INT_MAX - b; -} - -// returns 1 if the product is valid, 0 on overflow. -// negative factors are considered invalid. -static int stbi__mul2sizes_valid(int a, int b) -{ - if (a < 0 || b < 0) return 0; - if (b == 0) return 1; // mul-by-0 is always safe - // portable way to check for no overflows in a*b - return a <= INT_MAX/b; -} - -#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) -// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow -static int stbi__mad2sizes_valid(int a, int b, int add) -{ - return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); -} -#endif - -// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow -static int stbi__mad3sizes_valid(int a, int b, int c, int add) -{ - return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && - stbi__addsizes_valid(a*b*c, add); -} - -// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow -#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) -static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) -{ - return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && - stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); -} -#endif - -#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) -// mallocs with size overflow checking -static void *stbi__malloc_mad2(int a, int b, int add) -{ - if (!stbi__mad2sizes_valid(a, b, add)) return NULL; - return stbi__malloc(a*b + add); -} -#endif - -static void *stbi__malloc_mad3(int a, int b, int c, int add) -{ - if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; - return stbi__malloc(a*b*c + add); -} - -#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) -static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) -{ - if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; - return stbi__malloc(a*b*c*d + add); -} -#endif - -// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow. -static int stbi__addints_valid(int a, int b) -{ - if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow - if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0. - return a <= INT_MAX - b; -} - -// returns 1 if the product of two ints fits in a signed short, 0 on overflow. -static int stbi__mul2shorts_valid(int a, int b) -{ - if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow - if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid - if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN - return a >= SHRT_MIN / b; -} - -// stbi__err - error -// stbi__errpf - error returning pointer to float -// stbi__errpuc - error returning pointer to unsigned char - -#ifdef STBI_NO_FAILURE_STRINGS - #define stbi__err(x,y) 0 -#elif defined(STBI_FAILURE_USERMSG) - #define stbi__err(x,y) stbi__err(y) -#else - #define stbi__err(x,y) stbi__err(x) -#endif - -#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) -#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) - -STBIDEF void stbi_image_free(void *retval_from_stbi_load) -{ - STBI_FREE(retval_from_stbi_load); -} - -#ifndef STBI_NO_LINEAR -static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); -#endif - -#ifndef STBI_NO_HDR -static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); -#endif - -static int stbi__vertically_flip_on_load_global = 0; - -STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) -{ - stbi__vertically_flip_on_load_global = flag_true_if_should_flip; -} - -#ifndef STBI_THREAD_LOCAL -#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global -#else -static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set; - -STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip) -{ - stbi__vertically_flip_on_load_local = flag_true_if_should_flip; - stbi__vertically_flip_on_load_set = 1; -} - -#define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \ - ? stbi__vertically_flip_on_load_local \ - : stbi__vertically_flip_on_load_global) -#endif // STBI_THREAD_LOCAL - -static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) -{ - memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields - ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed - ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order - ri->num_channels = 0; - - // test the formats with a very explicit header first (at least a FOURCC - // or distinctive magic number first) - #ifndef STBI_NO_PNG - if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); - #endif - #ifndef STBI_NO_BMP - if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); - #endif - #ifndef STBI_NO_GIF - if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); - #endif - #ifndef STBI_NO_PSD - if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); - #else - STBI_NOTUSED(bpc); - #endif - #ifndef STBI_NO_PIC - if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); - #endif - - // then the formats that can end up attempting to load with just 1 or 2 - // bytes matching expectations; these are prone to false positives, so - // try them later - #ifndef STBI_NO_JPEG - if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); - #endif - #ifndef STBI_NO_PNM - if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); - #endif - - #ifndef STBI_NO_HDR - if (stbi__hdr_test(s)) { - float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); - return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); - } - #endif - - #ifndef STBI_NO_TGA - // test tga last because it's a crappy test! - if (stbi__tga_test(s)) - return stbi__tga_load(s,x,y,comp,req_comp, ri); - #endif - - return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); -} - -static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) -{ - int i; - int img_len = w * h * channels; - stbi_uc *reduced; - - reduced = (stbi_uc *) stbi__malloc(img_len); - if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); - - for (i = 0; i < img_len; ++i) - reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling - - STBI_FREE(orig); - return reduced; -} - -static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) -{ - int i; - int img_len = w * h * channels; - stbi__uint16 *enlarged; - - enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); - if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); - - for (i = 0; i < img_len; ++i) - enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff - - STBI_FREE(orig); - return enlarged; -} - -static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) -{ - int row; - size_t bytes_per_row = (size_t)w * bytes_per_pixel; - stbi_uc temp[2048]; - stbi_uc *bytes = (stbi_uc *)image; - - for (row = 0; row < (h>>1); row++) { - stbi_uc *row0 = bytes + row*bytes_per_row; - stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; - // swap row0 with row1 - size_t bytes_left = bytes_per_row; - while (bytes_left) { - size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); - memcpy(temp, row0, bytes_copy); - memcpy(row0, row1, bytes_copy); - memcpy(row1, temp, bytes_copy); - row0 += bytes_copy; - row1 += bytes_copy; - bytes_left -= bytes_copy; - } - } -} - -#ifndef STBI_NO_GIF -static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) -{ - int slice; - int slice_size = w * h * bytes_per_pixel; - - stbi_uc *bytes = (stbi_uc *)image; - for (slice = 0; slice < z; ++slice) { - stbi__vertical_flip(bytes, w, h, bytes_per_pixel); - bytes += slice_size; - } -} -#endif - -static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - stbi__result_info ri; - void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); - - if (result == NULL) - return NULL; - - // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. - STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); - - if (ri.bits_per_channel != 8) { - result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); - ri.bits_per_channel = 8; - } - - // @TODO: move stbi__convert_format to here - - if (stbi__vertically_flip_on_load) { - int channels = req_comp ? req_comp : *comp; - stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); - } - - return (unsigned char *) result; -} - -static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - stbi__result_info ri; - void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); - - if (result == NULL) - return NULL; - - // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. - STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); - - if (ri.bits_per_channel != 16) { - result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); - ri.bits_per_channel = 16; - } - - // @TODO: move stbi__convert_format16 to here - // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision - - if (stbi__vertically_flip_on_load) { - int channels = req_comp ? req_comp : *comp; - stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); - } - - return (stbi__uint16 *) result; -} - -#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) -static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) -{ - if (stbi__vertically_flip_on_load && result != NULL) { - int channels = req_comp ? req_comp : *comp; - stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); - } -} -#endif - -#ifndef STBI_NO_STDIO - -#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) -STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); -STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); -#endif - -#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) -STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) -{ - return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); -} -#endif - -static FILE *stbi__fopen(char const *filename, char const *mode) -{ - FILE *f; -#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) - wchar_t wMode[64]; - wchar_t wFilename[1024]; - if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) - return 0; - - if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) - return 0; - -#if defined(_MSC_VER) && _MSC_VER >= 1400 - if (0 != _wfopen_s(&f, wFilename, wMode)) - f = 0; -#else - f = _wfopen(wFilename, wMode); -#endif - -#elif defined(_MSC_VER) && _MSC_VER >= 1400 - if (0 != fopen_s(&f, filename, mode)) - f=0; -#else - f = fopen(filename, mode); -#endif - return f; -} - - -STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) -{ - FILE *f = stbi__fopen(filename, "rb"); - unsigned char *result; - if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); - result = stbi_load_from_file(f,x,y,comp,req_comp); - fclose(f); - return result; -} - -STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - unsigned char *result; - stbi__context s; - stbi__start_file(&s,f); - result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); - if (result) { - // need to 'unget' all the characters in the IO buffer - fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); - } - return result; -} - -STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - stbi__uint16 *result; - stbi__context s; - stbi__start_file(&s,f); - result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); - if (result) { - // need to 'unget' all the characters in the IO buffer - fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); - } - return result; -} - -STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) -{ - FILE *f = stbi__fopen(filename, "rb"); - stbi__uint16 *result; - if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); - result = stbi_load_from_file_16(f,x,y,comp,req_comp); - fclose(f); - return result; -} - - -#endif //!STBI_NO_STDIO - -STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) -{ - stbi__context s; - stbi__start_mem(&s,buffer,len); - return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); -} - -STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) -{ - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); - return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); -} - -STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi__context s; - stbi__start_mem(&s,buffer,len); - return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); -} - -STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) -{ - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); - return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); -} - -#ifndef STBI_NO_GIF -STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) -{ - unsigned char *result; - stbi__context s; - stbi__start_mem(&s,buffer,len); - - result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); - if (stbi__vertically_flip_on_load) { - stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); - } - - return result; -} -#endif - -#ifndef STBI_NO_LINEAR -static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - unsigned char *data; - #ifndef STBI_NO_HDR - if (stbi__hdr_test(s)) { - stbi__result_info ri; - float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); - if (hdr_data) - stbi__float_postprocess(hdr_data,x,y,comp,req_comp); - return hdr_data; - } - #endif - data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); - if (data) - return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); - return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); -} - -STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi__context s; - stbi__start_mem(&s,buffer,len); - return stbi__loadf_main(&s,x,y,comp,req_comp); -} - -STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) -{ - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); - return stbi__loadf_main(&s,x,y,comp,req_comp); -} - -#ifndef STBI_NO_STDIO -STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) -{ - float *result; - FILE *f = stbi__fopen(filename, "rb"); - if (!f) return stbi__errpf("can't fopen", "Unable to open file"); - result = stbi_loadf_from_file(f,x,y,comp,req_comp); - fclose(f); - return result; -} - -STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - stbi__context s; - stbi__start_file(&s,f); - return stbi__loadf_main(&s,x,y,comp,req_comp); -} -#endif // !STBI_NO_STDIO - -#endif // !STBI_NO_LINEAR - -// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is -// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always -// reports false! - -STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) -{ - #ifndef STBI_NO_HDR - stbi__context s; - stbi__start_mem(&s,buffer,len); - return stbi__hdr_test(&s); - #else - STBI_NOTUSED(buffer); - STBI_NOTUSED(len); - return 0; - #endif -} - -#ifndef STBI_NO_STDIO -STBIDEF int stbi_is_hdr (char const *filename) -{ - FILE *f = stbi__fopen(filename, "rb"); - int result=0; - if (f) { - result = stbi_is_hdr_from_file(f); - fclose(f); - } - return result; -} - -STBIDEF int stbi_is_hdr_from_file(FILE *f) -{ - #ifndef STBI_NO_HDR - long pos = ftell(f); - int res; - stbi__context s; - stbi__start_file(&s,f); - res = stbi__hdr_test(&s); - fseek(f, pos, SEEK_SET); - return res; - #else - STBI_NOTUSED(f); - return 0; - #endif -} -#endif // !STBI_NO_STDIO - -STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) -{ - #ifndef STBI_NO_HDR - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); - return stbi__hdr_test(&s); - #else - STBI_NOTUSED(clbk); - STBI_NOTUSED(user); - return 0; - #endif -} - -#ifndef STBI_NO_LINEAR -static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; - -STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } -STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } -#endif - -static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; - -STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } -STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } - - -////////////////////////////////////////////////////////////////////////////// -// -// Common code used by all image loaders -// - -enum -{ - STBI__SCAN_load=0, - STBI__SCAN_type, - STBI__SCAN_header -}; - -static void stbi__refill_buffer(stbi__context *s) -{ - int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); - s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original); - if (n == 0) { - // at end of file, treat same as if from memory, but need to handle case - // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file - s->read_from_callbacks = 0; - s->img_buffer = s->buffer_start; - s->img_buffer_end = s->buffer_start+1; - *s->img_buffer = 0; - } else { - s->img_buffer = s->buffer_start; - s->img_buffer_end = s->buffer_start + n; - } -} - -stbi_inline static stbi_uc stbi__get8(stbi__context *s) -{ - if (s->img_buffer < s->img_buffer_end) - return *s->img_buffer++; - if (s->read_from_callbacks) { - stbi__refill_buffer(s); - return *s->img_buffer++; - } - return 0; -} - -#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) -// nothing -#else -stbi_inline static int stbi__at_eof(stbi__context *s) -{ - if (s->io.read) { - if (!(s->io.eof)(s->io_user_data)) return 0; - // if feof() is true, check if buffer = end - // special case: we've only got the special 0 character at the end - if (s->read_from_callbacks == 0) return 1; - } - - return s->img_buffer >= s->img_buffer_end; -} -#endif - -#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) -// nothing -#else -static void stbi__skip(stbi__context *s, int n) -{ - if (n == 0) return; // already there! - if (n < 0) { - s->img_buffer = s->img_buffer_end; - return; - } - if (s->io.read) { - int blen = (int) (s->img_buffer_end - s->img_buffer); - if (blen < n) { - s->img_buffer = s->img_buffer_end; - (s->io.skip)(s->io_user_data, n - blen); - return; - } - } - s->img_buffer += n; -} -#endif - -#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM) -// nothing -#else -static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) -{ - if (s->io.read) { - int blen = (int) (s->img_buffer_end - s->img_buffer); - if (blen < n) { - int res, count; - - memcpy(buffer, s->img_buffer, blen); - - count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); - res = (count == (n-blen)); - s->img_buffer = s->img_buffer_end; - return res; - } - } - - if (s->img_buffer+n <= s->img_buffer_end) { - memcpy(buffer, s->img_buffer, n); - s->img_buffer += n; - return 1; - } else - return 0; -} -#endif - -#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) -// nothing -#else -static int stbi__get16be(stbi__context *s) -{ - int z = stbi__get8(s); - return (z << 8) + stbi__get8(s); -} -#endif - -#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) -// nothing -#else -static stbi__uint32 stbi__get32be(stbi__context *s) -{ - stbi__uint32 z = stbi__get16be(s); - return (z << 16) + stbi__get16be(s); -} -#endif - -#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) -// nothing -#else -static int stbi__get16le(stbi__context *s) -{ - int z = stbi__get8(s); - return z + (stbi__get8(s) << 8); -} -#endif - -#ifndef STBI_NO_BMP -static stbi__uint32 stbi__get32le(stbi__context *s) -{ - stbi__uint32 z = stbi__get16le(s); - z += (stbi__uint32)stbi__get16le(s) << 16; - return z; -} -#endif - -#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings - -#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) -// nothing -#else -////////////////////////////////////////////////////////////////////////////// -// -// generic converter from built-in img_n to req_comp -// individual types do this automatically as much as possible (e.g. jpeg -// does all cases internally since it needs to colorspace convert anyway, -// and it never has alpha, so very few cases ). png can automatically -// interleave an alpha=255 channel, but falls back to this for other cases -// -// assume data buffer is malloced, so malloc a new one and free that one -// only failure mode is malloc failing - -static stbi_uc stbi__compute_y(int r, int g, int b) -{ - return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); -} -#endif - -#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) -// nothing -#else -static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) -{ - int i,j; - unsigned char *good; - - if (req_comp == img_n) return data; - STBI_ASSERT(req_comp >= 1 && req_comp <= 4); - - good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); - if (good == NULL) { - STBI_FREE(data); - return stbi__errpuc("outofmem", "Out of memory"); - } - - for (j=0; j < (int) y; ++j) { - unsigned char *src = data + j * x * img_n ; - unsigned char *dest = good + j * x * req_comp; - - #define STBI__COMBO(a,b) ((a)*8+(b)) - #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) - // convert source image with img_n components to one with req_comp components; - // avoid switch per pixel, so use switch per scanline and massive macros - switch (STBI__COMBO(img_n, req_comp)) { - STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break; - STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; - STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break; - STBI__CASE(2,1) { dest[0]=src[0]; } break; - STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; - STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; - STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break; - STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; - STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break; - STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; - STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; - STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; - default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion"); - } - #undef STBI__CASE - } - - STBI_FREE(data); - return good; -} -#endif - -#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) -// nothing -#else -static stbi__uint16 stbi__compute_y_16(int r, int g, int b) -{ - return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); -} -#endif - -#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) -// nothing -#else -static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) -{ - int i,j; - stbi__uint16 *good; - - if (req_comp == img_n) return data; - STBI_ASSERT(req_comp >= 1 && req_comp <= 4); - - good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); - if (good == NULL) { - STBI_FREE(data); - return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); - } - - for (j=0; j < (int) y; ++j) { - stbi__uint16 *src = data + j * x * img_n ; - stbi__uint16 *dest = good + j * x * req_comp; - - #define STBI__COMBO(a,b) ((a)*8+(b)) - #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) - // convert source image with img_n components to one with req_comp components; - // avoid switch per pixel, so use switch per scanline and massive macros - switch (STBI__COMBO(img_n, req_comp)) { - STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break; - STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; - STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break; - STBI__CASE(2,1) { dest[0]=src[0]; } break; - STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; - STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; - STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break; - STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; - STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break; - STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; - STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; - STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; - default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion"); - } - #undef STBI__CASE - } - - STBI_FREE(data); - return good; -} -#endif - -#ifndef STBI_NO_LINEAR -static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) -{ - int i,k,n; - float *output; - if (!data) return NULL; - output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); - if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } - // compute number of non-alpha components - if (comp & 1) n = comp; else n = comp-1; - for (i=0; i < x*y; ++i) { - for (k=0; k < n; ++k) { - output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); - } - } - if (n < comp) { - for (i=0; i < x*y; ++i) { - output[i*comp + n] = data[i*comp + n]/255.0f; - } - } - STBI_FREE(data); - return output; -} -#endif - -#ifndef STBI_NO_HDR -#define stbi__float2int(x) ((int) (x)) -static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) -{ - int i,k,n; - stbi_uc *output; - if (!data) return NULL; - output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); - if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } - // compute number of non-alpha components - if (comp & 1) n = comp; else n = comp-1; - for (i=0; i < x*y; ++i) { - for (k=0; k < n; ++k) { - float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; - if (z < 0) z = 0; - if (z > 255) z = 255; - output[i*comp + k] = (stbi_uc) stbi__float2int(z); - } - if (k < comp) { - float z = data[i*comp+k] * 255 + 0.5f; - if (z < 0) z = 0; - if (z > 255) z = 255; - output[i*comp + k] = (stbi_uc) stbi__float2int(z); - } - } - STBI_FREE(data); - return output; -} -#endif - -////////////////////////////////////////////////////////////////////////////// -// -// "baseline" JPEG/JFIF decoder -// -// simple implementation -// - doesn't support delayed output of y-dimension -// - simple interface (only one output format: 8-bit interleaved RGB) -// - doesn't try to recover corrupt jpegs -// - doesn't allow partial loading, loading multiple at once -// - still fast on x86 (copying globals into locals doesn't help x86) -// - allocates lots of intermediate memory (full size of all components) -// - non-interleaved case requires this anyway -// - allows good upsampling (see next) -// high-quality -// - upsampled channels are bilinearly interpolated, even across blocks -// - quality integer IDCT derived from IJG's 'slow' -// performance -// - fast huffman; reasonable integer IDCT -// - some SIMD kernels for common paths on targets with SSE2/NEON -// - uses a lot of intermediate memory, could cache poorly - -#ifndef STBI_NO_JPEG - -// huffman decoding acceleration -#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache - -typedef struct -{ - stbi_uc fast[1 << FAST_BITS]; - // weirdly, repacking this into AoS is a 10% speed loss, instead of a win - stbi__uint16 code[256]; - stbi_uc values[256]; - stbi_uc size[257]; - unsigned int maxcode[18]; - int delta[17]; // old 'firstsymbol' - old 'firstcode' -} stbi__huffman; - -typedef struct -{ - stbi__context *s; - stbi__huffman huff_dc[4]; - stbi__huffman huff_ac[4]; - stbi__uint16 dequant[4][64]; - stbi__int16 fast_ac[4][1 << FAST_BITS]; - -// sizes for components, interleaved MCUs - int img_h_max, img_v_max; - int img_mcu_x, img_mcu_y; - int img_mcu_w, img_mcu_h; - -// definition of jpeg image component - struct - { - int id; - int h,v; - int tq; - int hd,ha; - int dc_pred; - - int x,y,w2,h2; - stbi_uc *data; - void *raw_data, *raw_coeff; - stbi_uc *linebuf; - short *coeff; // progressive only - int coeff_w, coeff_h; // number of 8x8 coefficient blocks - } img_comp[4]; - - stbi__uint32 code_buffer; // jpeg entropy-coded buffer - int code_bits; // number of valid bits - unsigned char marker; // marker seen while filling entropy buffer - int nomore; // flag if we saw a marker so must stop - - int progressive; - int spec_start; - int spec_end; - int succ_high; - int succ_low; - int eob_run; - int jfif; - int app14_color_transform; // Adobe APP14 tag - int rgb; - - int scan_n, order[4]; - int restart_interval, todo; - -// kernels - void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); - void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); - stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); -} stbi__jpeg; - -static int stbi__build_huffman(stbi__huffman *h, int *count) -{ - int i,j,k=0; - unsigned int code; - // build size list for each symbol (from JPEG spec) - for (i=0; i < 16; ++i) { - for (j=0; j < count[i]; ++j) { - h->size[k++] = (stbi_uc) (i+1); - if(k >= 257) return stbi__err("bad size list","Corrupt JPEG"); - } - } - h->size[k] = 0; - - // compute actual symbols (from jpeg spec) - code = 0; - k = 0; - for(j=1; j <= 16; ++j) { - // compute delta to add to code to compute symbol id - h->delta[j] = k - code; - if (h->size[k] == j) { - while (h->size[k] == j) - h->code[k++] = (stbi__uint16) (code++); - if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); - } - // compute largest code + 1 for this size, preshifted as needed later - h->maxcode[j] = code << (16-j); - code <<= 1; - } - h->maxcode[j] = 0xffffffff; - - // build non-spec acceleration table; 255 is flag for not-accelerated - memset(h->fast, 255, 1 << FAST_BITS); - for (i=0; i < k; ++i) { - int s = h->size[i]; - if (s <= FAST_BITS) { - int c = h->code[i] << (FAST_BITS-s); - int m = 1 << (FAST_BITS-s); - for (j=0; j < m; ++j) { - h->fast[c+j] = (stbi_uc) i; - } - } - } - return 1; -} - -// build a table that decodes both magnitude and value of small ACs in -// one go. -static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) -{ - int i; - for (i=0; i < (1 << FAST_BITS); ++i) { - stbi_uc fast = h->fast[i]; - fast_ac[i] = 0; - if (fast < 255) { - int rs = h->values[fast]; - int run = (rs >> 4) & 15; - int magbits = rs & 15; - int len = h->size[fast]; - - if (magbits && len + magbits <= FAST_BITS) { - // magnitude code followed by receive_extend code - int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); - int m = 1 << (magbits - 1); - if (k < m) k += (~0U << magbits) + 1; - // if the result is small enough, we can fit it in fast_ac table - if (k >= -128 && k <= 127) - fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); - } - } - } -} - -static void stbi__grow_buffer_unsafe(stbi__jpeg *j) -{ - do { - unsigned int b = j->nomore ? 0 : stbi__get8(j->s); - if (b == 0xff) { - int c = stbi__get8(j->s); - while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes - if (c != 0) { - j->marker = (unsigned char) c; - j->nomore = 1; - return; - } - } - j->code_buffer |= b << (24 - j->code_bits); - j->code_bits += 8; - } while (j->code_bits <= 24); -} - -// (1 << n) - 1 -static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; - -// decode a jpeg huffman value from the bitstream -stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) -{ - unsigned int temp; - int c,k; - - if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); - - // look at the top FAST_BITS and determine what symbol ID it is, - // if the code is <= FAST_BITS - c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); - k = h->fast[c]; - if (k < 255) { - int s = h->size[k]; - if (s > j->code_bits) - return -1; - j->code_buffer <<= s; - j->code_bits -= s; - return h->values[k]; - } - - // naive test is to shift the code_buffer down so k bits are - // valid, then test against maxcode. To speed this up, we've - // preshifted maxcode left so that it has (16-k) 0s at the - // end; in other words, regardless of the number of bits, it - // wants to be compared against something shifted to have 16; - // that way we don't need to shift inside the loop. - temp = j->code_buffer >> 16; - for (k=FAST_BITS+1 ; ; ++k) - if (temp < h->maxcode[k]) - break; - if (k == 17) { - // error! code not found - j->code_bits -= 16; - return -1; - } - - if (k > j->code_bits) - return -1; - - // convert the huffman code to the symbol id - c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; - if(c < 0 || c >= 256) // symbol id out of bounds! - return -1; - STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); - - // convert the id to a symbol - j->code_bits -= k; - j->code_buffer <<= k; - return h->values[c]; -} - -// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); - if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing - - sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) - k = stbi_lrot(j->code_buffer, n); - j->code_buffer = k & ~stbi__bmask[n]; - k &= stbi__bmask[n]; - j->code_bits -= n; - return k + (stbi__jbias[n] & (sgn - 1)); -} - -// get some unsigned bits -stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) -{ - unsigned int k; - if (j->code_bits < n) stbi__grow_buffer_unsafe(j); - if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing - k = stbi_lrot(j->code_buffer, n); - j->code_buffer = k & ~stbi__bmask[n]; - k &= stbi__bmask[n]; - j->code_bits -= n; - return k; -} - -stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) -{ - unsigned int k; - if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); - if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing - k = j->code_buffer; - j->code_buffer <<= 1; - --j->code_bits; - return k & 0x80000000; -} - -// given a value that's at position X in the zigzag stream, -// where does it appear in the 8x8 matrix coded as row-major? -static const stbi_uc stbi__jpeg_dezigzag[64+15] = -{ - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63, - // let corrupt input sample past end - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63 -}; - -// decode one 64-entry block-- -static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) -{ - int diff,dc,k; - int t; - - if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); - t = stbi__jpeg_huff_decode(j, hdc); - if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG"); - - // 0 all the ac values now so we can do it 32-bits at a time - memset(data,0,64*sizeof(data[0])); - - diff = t ? stbi__extend_receive(j, t) : 0; - if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG"); - dc = j->img_comp[b].dc_pred + diff; - j->img_comp[b].dc_pred = dc; - if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); - data[0] = (short) (dc * dequant[0]); - - // decode AC components, see JPEG spec - k = 1; - do { - unsigned int zig; - int c,r,s; - if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); - c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); - r = fac[c]; - if (r) { // fast-AC path - k += (r >> 4) & 15; // run - s = r & 15; // combined length - if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); - j->code_buffer <<= s; - j->code_bits -= s; - // decode into unzigzag'd location - zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short) ((r >> 8) * dequant[zig]); - } else { - int rs = stbi__jpeg_huff_decode(j, hac); - if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); - s = rs & 15; - r = rs >> 4; - if (s == 0) { - if (rs != 0xf0) break; // end block - k += 16; - } else { - k += r; - // decode into unzigzag'd location - zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); - } - } - } while (k < 64); - return 1; -} - -static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) -{ - int diff,dc; - int t; - if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); - - if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); - - if (j->succ_high == 0) { - // first scan for DC coefficient, must be first - memset(data,0,64*sizeof(data[0])); // 0 all the ac values now - t = stbi__jpeg_huff_decode(j, hdc); - if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); - diff = t ? stbi__extend_receive(j, t) : 0; - - if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG"); - dc = j->img_comp[b].dc_pred + diff; - j->img_comp[b].dc_pred = dc; - if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); - data[0] = (short) (dc * (1 << j->succ_low)); - } else { - // refinement scan for DC coefficient - if (stbi__jpeg_get_bit(j)) - data[0] += (short) (1 << j->succ_low); - } - return 1; -} - -// @OPTIMIZE: store non-zigzagged during the decode passes, -// and only de-zigzag when dequantizing -static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) -{ - int k; - if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); - - if (j->succ_high == 0) { - int shift = j->succ_low; - - if (j->eob_run) { - --j->eob_run; - return 1; - } - - k = j->spec_start; - do { - unsigned int zig; - int c,r,s; - if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); - c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); - r = fac[c]; - if (r) { // fast-AC path - k += (r >> 4) & 15; // run - s = r & 15; // combined length - if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); - j->code_buffer <<= s; - j->code_bits -= s; - zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short) ((r >> 8) * (1 << shift)); - } else { - int rs = stbi__jpeg_huff_decode(j, hac); - if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); - s = rs & 15; - r = rs >> 4; - if (s == 0) { - if (r < 15) { - j->eob_run = (1 << r); - if (r) - j->eob_run += stbi__jpeg_get_bits(j, r); - --j->eob_run; - break; - } - k += 16; - } else { - k += r; - zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift)); - } - } - } while (k <= j->spec_end); - } else { - // refinement scan for these AC coefficients - - short bit = (short) (1 << j->succ_low); - - if (j->eob_run) { - --j->eob_run; - for (k = j->spec_start; k <= j->spec_end; ++k) { - short *p = &data[stbi__jpeg_dezigzag[k]]; - if (*p != 0) - if (stbi__jpeg_get_bit(j)) - if ((*p & bit)==0) { - if (*p > 0) - *p += bit; - else - *p -= bit; - } - } - } else { - k = j->spec_start; - do { - int r,s; - int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh - if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); - s = rs & 15; - r = rs >> 4; - if (s == 0) { - if (r < 15) { - j->eob_run = (1 << r) - 1; - if (r) - j->eob_run += stbi__jpeg_get_bits(j, r); - r = 64; // force end of block - } else { - // r=15 s=0 should write 16 0s, so we just do - // a run of 15 0s and then write s (which is 0), - // so we don't have to do anything special here - } - } else { - if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); - // sign bit - if (stbi__jpeg_get_bit(j)) - s = bit; - else - s = -bit; - } - - // advance by r - while (k <= j->spec_end) { - short *p = &data[stbi__jpeg_dezigzag[k++]]; - if (*p != 0) { - if (stbi__jpeg_get_bit(j)) - if ((*p & bit)==0) { - if (*p > 0) - *p += bit; - else - *p -= bit; - } - } else { - if (r == 0) { - *p = (short) s; - break; - } - --r; - } - } - } while (k <= j->spec_end); - } - } - return 1; -} - -// take a -128..127 value and stbi__clamp it and convert to 0..255 -stbi_inline static stbi_uc stbi__clamp(int x) -{ - // trick to use a single test to catch both cases - if ((unsigned int) x > 255) { - if (x < 0) return 0; - if (x > 255) return 255; - } - return (stbi_uc) x; -} - -#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) -#define stbi__fsh(x) ((x) * 4096) - -// derived from jidctint -- DCT_ISLOW -#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ - int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ - p2 = s2; \ - p3 = s6; \ - p1 = (p2+p3) * stbi__f2f(0.5411961f); \ - t2 = p1 + p3*stbi__f2f(-1.847759065f); \ - t3 = p1 + p2*stbi__f2f( 0.765366865f); \ - p2 = s0; \ - p3 = s4; \ - t0 = stbi__fsh(p2+p3); \ - t1 = stbi__fsh(p2-p3); \ - x0 = t0+t3; \ - x3 = t0-t3; \ - x1 = t1+t2; \ - x2 = t1-t2; \ - t0 = s7; \ - t1 = s5; \ - t2 = s3; \ - t3 = s1; \ - p3 = t0+t2; \ - p4 = t1+t3; \ - p1 = t0+t3; \ - p2 = t1+t2; \ - p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ - t0 = t0*stbi__f2f( 0.298631336f); \ - t1 = t1*stbi__f2f( 2.053119869f); \ - t2 = t2*stbi__f2f( 3.072711026f); \ - t3 = t3*stbi__f2f( 1.501321110f); \ - p1 = p5 + p1*stbi__f2f(-0.899976223f); \ - p2 = p5 + p2*stbi__f2f(-2.562915447f); \ - p3 = p3*stbi__f2f(-1.961570560f); \ - p4 = p4*stbi__f2f(-0.390180644f); \ - t3 += p1+p4; \ - t2 += p2+p3; \ - t1 += p2+p4; \ - t0 += p1+p3; - -static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) -{ - int i,val[64],*v=val; - stbi_uc *o; - short *d = data; - - // columns - for (i=0; i < 8; ++i,++d, ++v) { - // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing - if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 - && d[40]==0 && d[48]==0 && d[56]==0) { - // no shortcut 0 seconds - // (1|2|3|4|5|6|7)==0 0 seconds - // all separate -0.047 seconds - // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds - int dcterm = d[0]*4; - v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; - } else { - STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) - // constants scaled things up by 1<<12; let's bring them back - // down, but keep 2 extra bits of precision - x0 += 512; x1 += 512; x2 += 512; x3 += 512; - v[ 0] = (x0+t3) >> 10; - v[56] = (x0-t3) >> 10; - v[ 8] = (x1+t2) >> 10; - v[48] = (x1-t2) >> 10; - v[16] = (x2+t1) >> 10; - v[40] = (x2-t1) >> 10; - v[24] = (x3+t0) >> 10; - v[32] = (x3-t0) >> 10; - } - } - - for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { - // no fast case since the first 1D IDCT spread components out - STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) - // constants scaled things up by 1<<12, plus we had 1<<2 from first - // loop, plus horizontal and vertical each scale by sqrt(8) so together - // we've got an extra 1<<3, so 1<<17 total we need to remove. - // so we want to round that, which means adding 0.5 * 1<<17, - // aka 65536. Also, we'll end up with -128 to 127 that we want - // to encode as 0..255 by adding 128, so we'll add that before the shift - x0 += 65536 + (128<<17); - x1 += 65536 + (128<<17); - x2 += 65536 + (128<<17); - x3 += 65536 + (128<<17); - // tried computing the shifts into temps, or'ing the temps to see - // if any were out of range, but that was slower - o[0] = stbi__clamp((x0+t3) >> 17); - o[7] = stbi__clamp((x0-t3) >> 17); - o[1] = stbi__clamp((x1+t2) >> 17); - o[6] = stbi__clamp((x1-t2) >> 17); - o[2] = stbi__clamp((x2+t1) >> 17); - o[5] = stbi__clamp((x2-t1) >> 17); - o[3] = stbi__clamp((x3+t0) >> 17); - o[4] = stbi__clamp((x3-t0) >> 17); - } -} - -#ifdef STBI_SSE2 -// sse2 integer IDCT. not the fastest possible implementation but it -// produces bit-identical results to the generic C version so it's -// fully "transparent". -static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) -{ - // This is constructed to match our regular (generic) integer IDCT exactly. - __m128i row0, row1, row2, row3, row4, row5, row6, row7; - __m128i tmp; - - // dot product constant: even elems=x, odd elems=y - #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) - - // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) - // out(1) = c1[even]*x + c1[odd]*y - #define dct_rot(out0,out1, x,y,c0,c1) \ - __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ - __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ - __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ - __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ - __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ - __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) - - // out = in << 12 (in 16-bit, out 32-bit) - #define dct_widen(out, in) \ - __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ - __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) - - // wide add - #define dct_wadd(out, a, b) \ - __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ - __m128i out##_h = _mm_add_epi32(a##_h, b##_h) - - // wide sub - #define dct_wsub(out, a, b) \ - __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ - __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) - - // butterfly a/b, add bias, then shift by "s" and pack - #define dct_bfly32o(out0, out1, a,b,bias,s) \ - { \ - __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ - __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ - dct_wadd(sum, abiased, b); \ - dct_wsub(dif, abiased, b); \ - out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ - out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ - } - - // 8-bit interleave step (for transposes) - #define dct_interleave8(a, b) \ - tmp = a; \ - a = _mm_unpacklo_epi8(a, b); \ - b = _mm_unpackhi_epi8(tmp, b) - - // 16-bit interleave step (for transposes) - #define dct_interleave16(a, b) \ - tmp = a; \ - a = _mm_unpacklo_epi16(a, b); \ - b = _mm_unpackhi_epi16(tmp, b) - - #define dct_pass(bias,shift) \ - { \ - /* even part */ \ - dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ - __m128i sum04 = _mm_add_epi16(row0, row4); \ - __m128i dif04 = _mm_sub_epi16(row0, row4); \ - dct_widen(t0e, sum04); \ - dct_widen(t1e, dif04); \ - dct_wadd(x0, t0e, t3e); \ - dct_wsub(x3, t0e, t3e); \ - dct_wadd(x1, t1e, t2e); \ - dct_wsub(x2, t1e, t2e); \ - /* odd part */ \ - dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ - dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ - __m128i sum17 = _mm_add_epi16(row1, row7); \ - __m128i sum35 = _mm_add_epi16(row3, row5); \ - dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ - dct_wadd(x4, y0o, y4o); \ - dct_wadd(x5, y1o, y5o); \ - dct_wadd(x6, y2o, y5o); \ - dct_wadd(x7, y3o, y4o); \ - dct_bfly32o(row0,row7, x0,x7,bias,shift); \ - dct_bfly32o(row1,row6, x1,x6,bias,shift); \ - dct_bfly32o(row2,row5, x2,x5,bias,shift); \ - dct_bfly32o(row3,row4, x3,x4,bias,shift); \ - } - - __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); - __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); - __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); - __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); - __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); - __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); - __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); - __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); - - // rounding biases in column/row passes, see stbi__idct_block for explanation. - __m128i bias_0 = _mm_set1_epi32(512); - __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); - - // load - row0 = _mm_load_si128((const __m128i *) (data + 0*8)); - row1 = _mm_load_si128((const __m128i *) (data + 1*8)); - row2 = _mm_load_si128((const __m128i *) (data + 2*8)); - row3 = _mm_load_si128((const __m128i *) (data + 3*8)); - row4 = _mm_load_si128((const __m128i *) (data + 4*8)); - row5 = _mm_load_si128((const __m128i *) (data + 5*8)); - row6 = _mm_load_si128((const __m128i *) (data + 6*8)); - row7 = _mm_load_si128((const __m128i *) (data + 7*8)); - - // column pass - dct_pass(bias_0, 10); - - { - // 16bit 8x8 transpose pass 1 - dct_interleave16(row0, row4); - dct_interleave16(row1, row5); - dct_interleave16(row2, row6); - dct_interleave16(row3, row7); - - // transpose pass 2 - dct_interleave16(row0, row2); - dct_interleave16(row1, row3); - dct_interleave16(row4, row6); - dct_interleave16(row5, row7); - - // transpose pass 3 - dct_interleave16(row0, row1); - dct_interleave16(row2, row3); - dct_interleave16(row4, row5); - dct_interleave16(row6, row7); - } - - // row pass - dct_pass(bias_1, 17); - - { - // pack - __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 - __m128i p1 = _mm_packus_epi16(row2, row3); - __m128i p2 = _mm_packus_epi16(row4, row5); - __m128i p3 = _mm_packus_epi16(row6, row7); - - // 8bit 8x8 transpose pass 1 - dct_interleave8(p0, p2); // a0e0a1e1... - dct_interleave8(p1, p3); // c0g0c1g1... - - // transpose pass 2 - dct_interleave8(p0, p1); // a0c0e0g0... - dct_interleave8(p2, p3); // b0d0f0h0... - - // transpose pass 3 - dct_interleave8(p0, p2); // a0b0c0d0... - dct_interleave8(p1, p3); // a4b4c4d4... - - // store - _mm_storel_epi64((__m128i *) out, p0); out += out_stride; - _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; - _mm_storel_epi64((__m128i *) out, p2); out += out_stride; - _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; - _mm_storel_epi64((__m128i *) out, p1); out += out_stride; - _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; - _mm_storel_epi64((__m128i *) out, p3); out += out_stride; - _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); - } - -#undef dct_const -#undef dct_rot -#undef dct_widen -#undef dct_wadd -#undef dct_wsub -#undef dct_bfly32o -#undef dct_interleave8 -#undef dct_interleave16 -#undef dct_pass -} - -#endif // STBI_SSE2 - -#ifdef STBI_NEON - -// NEON integer IDCT. should produce bit-identical -// results to the generic C version. -static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) -{ - int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; - - int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); - int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); - int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); - int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); - int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); - int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); - int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); - int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); - int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); - int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); - int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); - int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); - -#define dct_long_mul(out, inq, coeff) \ - int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ - int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) - -#define dct_long_mac(out, acc, inq, coeff) \ - int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ - int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) - -#define dct_widen(out, inq) \ - int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ - int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) - -// wide add -#define dct_wadd(out, a, b) \ - int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ - int32x4_t out##_h = vaddq_s32(a##_h, b##_h) - -// wide sub -#define dct_wsub(out, a, b) \ - int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ - int32x4_t out##_h = vsubq_s32(a##_h, b##_h) - -// butterfly a/b, then shift using "shiftop" by "s" and pack -#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ - { \ - dct_wadd(sum, a, b); \ - dct_wsub(dif, a, b); \ - out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ - out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ - } - -#define dct_pass(shiftop, shift) \ - { \ - /* even part */ \ - int16x8_t sum26 = vaddq_s16(row2, row6); \ - dct_long_mul(p1e, sum26, rot0_0); \ - dct_long_mac(t2e, p1e, row6, rot0_1); \ - dct_long_mac(t3e, p1e, row2, rot0_2); \ - int16x8_t sum04 = vaddq_s16(row0, row4); \ - int16x8_t dif04 = vsubq_s16(row0, row4); \ - dct_widen(t0e, sum04); \ - dct_widen(t1e, dif04); \ - dct_wadd(x0, t0e, t3e); \ - dct_wsub(x3, t0e, t3e); \ - dct_wadd(x1, t1e, t2e); \ - dct_wsub(x2, t1e, t2e); \ - /* odd part */ \ - int16x8_t sum15 = vaddq_s16(row1, row5); \ - int16x8_t sum17 = vaddq_s16(row1, row7); \ - int16x8_t sum35 = vaddq_s16(row3, row5); \ - int16x8_t sum37 = vaddq_s16(row3, row7); \ - int16x8_t sumodd = vaddq_s16(sum17, sum35); \ - dct_long_mul(p5o, sumodd, rot1_0); \ - dct_long_mac(p1o, p5o, sum17, rot1_1); \ - dct_long_mac(p2o, p5o, sum35, rot1_2); \ - dct_long_mul(p3o, sum37, rot2_0); \ - dct_long_mul(p4o, sum15, rot2_1); \ - dct_wadd(sump13o, p1o, p3o); \ - dct_wadd(sump24o, p2o, p4o); \ - dct_wadd(sump23o, p2o, p3o); \ - dct_wadd(sump14o, p1o, p4o); \ - dct_long_mac(x4, sump13o, row7, rot3_0); \ - dct_long_mac(x5, sump24o, row5, rot3_1); \ - dct_long_mac(x6, sump23o, row3, rot3_2); \ - dct_long_mac(x7, sump14o, row1, rot3_3); \ - dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ - dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ - dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ - dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ - } - - // load - row0 = vld1q_s16(data + 0*8); - row1 = vld1q_s16(data + 1*8); - row2 = vld1q_s16(data + 2*8); - row3 = vld1q_s16(data + 3*8); - row4 = vld1q_s16(data + 4*8); - row5 = vld1q_s16(data + 5*8); - row6 = vld1q_s16(data + 6*8); - row7 = vld1q_s16(data + 7*8); - - // add DC bias - row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); - - // column pass - dct_pass(vrshrn_n_s32, 10); - - // 16bit 8x8 transpose - { -// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. -// whether compilers actually get this is another story, sadly. -#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } -#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } -#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } - - // pass 1 - dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 - dct_trn16(row2, row3); - dct_trn16(row4, row5); - dct_trn16(row6, row7); - - // pass 2 - dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 - dct_trn32(row1, row3); - dct_trn32(row4, row6); - dct_trn32(row5, row7); - - // pass 3 - dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 - dct_trn64(row1, row5); - dct_trn64(row2, row6); - dct_trn64(row3, row7); - -#undef dct_trn16 -#undef dct_trn32 -#undef dct_trn64 - } - - // row pass - // vrshrn_n_s32 only supports shifts up to 16, we need - // 17. so do a non-rounding shift of 16 first then follow - // up with a rounding shift by 1. - dct_pass(vshrn_n_s32, 16); - - { - // pack and round - uint8x8_t p0 = vqrshrun_n_s16(row0, 1); - uint8x8_t p1 = vqrshrun_n_s16(row1, 1); - uint8x8_t p2 = vqrshrun_n_s16(row2, 1); - uint8x8_t p3 = vqrshrun_n_s16(row3, 1); - uint8x8_t p4 = vqrshrun_n_s16(row4, 1); - uint8x8_t p5 = vqrshrun_n_s16(row5, 1); - uint8x8_t p6 = vqrshrun_n_s16(row6, 1); - uint8x8_t p7 = vqrshrun_n_s16(row7, 1); - - // again, these can translate into one instruction, but often don't. -#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } -#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } -#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } - - // sadly can't use interleaved stores here since we only write - // 8 bytes to each scan line! - - // 8x8 8-bit transpose pass 1 - dct_trn8_8(p0, p1); - dct_trn8_8(p2, p3); - dct_trn8_8(p4, p5); - dct_trn8_8(p6, p7); - - // pass 2 - dct_trn8_16(p0, p2); - dct_trn8_16(p1, p3); - dct_trn8_16(p4, p6); - dct_trn8_16(p5, p7); - - // pass 3 - dct_trn8_32(p0, p4); - dct_trn8_32(p1, p5); - dct_trn8_32(p2, p6); - dct_trn8_32(p3, p7); - - // store - vst1_u8(out, p0); out += out_stride; - vst1_u8(out, p1); out += out_stride; - vst1_u8(out, p2); out += out_stride; - vst1_u8(out, p3); out += out_stride; - vst1_u8(out, p4); out += out_stride; - vst1_u8(out, p5); out += out_stride; - vst1_u8(out, p6); out += out_stride; - vst1_u8(out, p7); - -#undef dct_trn8_8 -#undef dct_trn8_16 -#undef dct_trn8_32 - } - -#undef dct_long_mul -#undef dct_long_mac -#undef dct_widen -#undef dct_wadd -#undef dct_wsub -#undef dct_bfly32o -#undef dct_pass -} - -#endif // STBI_NEON - -#define STBI__MARKER_none 0xff -// if there's a pending marker from the entropy stream, return that -// otherwise, fetch from the stream and get a marker. if there's no -// marker, return 0xff, which is never a valid marker value -static stbi_uc stbi__get_marker(stbi__jpeg *j) -{ - stbi_uc x; - if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } - x = stbi__get8(j->s); - if (x != 0xff) return STBI__MARKER_none; - while (x == 0xff) - x = stbi__get8(j->s); // consume repeated 0xff fill bytes - return x; -} - -// in each scan, we'll have scan_n components, and the order -// of the components is specified by order[] -#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) - -// after a restart interval, stbi__jpeg_reset the entropy decoder and -// the dc prediction -static void stbi__jpeg_reset(stbi__jpeg *j) -{ - j->code_bits = 0; - j->code_buffer = 0; - j->nomore = 0; - j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; - j->marker = STBI__MARKER_none; - j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; - j->eob_run = 0; - // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, - // since we don't even allow 1<<30 pixels -} - -static int stbi__parse_entropy_coded_data(stbi__jpeg *z) -{ - stbi__jpeg_reset(z); - if (!z->progressive) { - if (z->scan_n == 1) { - int i,j; - STBI_SIMD_ALIGN(short, data[64]); - int n = z->order[0]; - // non-interleaved data, we just need to process one block at a time, - // in trivial scanline order - // number of blocks to do just depends on how many actual "pixels" this - // component has, independent of interleaved MCU blocking and such - int w = (z->img_comp[n].x+7) >> 3; - int h = (z->img_comp[n].y+7) >> 3; - for (j=0; j < h; ++j) { - for (i=0; i < w; ++i) { - int ha = z->img_comp[n].ha; - if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; - z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); - // every data block is an MCU, so countdown the restart interval - if (--z->todo <= 0) { - if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); - // if it's NOT a restart, then just bail, so we get corrupt data - // rather than no data - if (!STBI__RESTART(z->marker)) return 1; - stbi__jpeg_reset(z); - } - } - } - return 1; - } else { // interleaved - int i,j,k,x,y; - STBI_SIMD_ALIGN(short, data[64]); - for (j=0; j < z->img_mcu_y; ++j) { - for (i=0; i < z->img_mcu_x; ++i) { - // scan an interleaved mcu... process scan_n components in order - for (k=0; k < z->scan_n; ++k) { - int n = z->order[k]; - // scan out an mcu's worth of this component; that's just determined - // by the basic H and V specified for the component - for (y=0; y < z->img_comp[n].v; ++y) { - for (x=0; x < z->img_comp[n].h; ++x) { - int x2 = (i*z->img_comp[n].h + x)*8; - int y2 = (j*z->img_comp[n].v + y)*8; - int ha = z->img_comp[n].ha; - if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; - z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); - } - } - } - // after all interleaved components, that's an interleaved MCU, - // so now count down the restart interval - if (--z->todo <= 0) { - if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); - if (!STBI__RESTART(z->marker)) return 1; - stbi__jpeg_reset(z); - } - } - } - return 1; - } - } else { - if (z->scan_n == 1) { - int i,j; - int n = z->order[0]; - // non-interleaved data, we just need to process one block at a time, - // in trivial scanline order - // number of blocks to do just depends on how many actual "pixels" this - // component has, independent of interleaved MCU blocking and such - int w = (z->img_comp[n].x+7) >> 3; - int h = (z->img_comp[n].y+7) >> 3; - for (j=0; j < h; ++j) { - for (i=0; i < w; ++i) { - short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); - if (z->spec_start == 0) { - if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) - return 0; - } else { - int ha = z->img_comp[n].ha; - if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) - return 0; - } - // every data block is an MCU, so countdown the restart interval - if (--z->todo <= 0) { - if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); - if (!STBI__RESTART(z->marker)) return 1; - stbi__jpeg_reset(z); - } - } - } - return 1; - } else { // interleaved - int i,j,k,x,y; - for (j=0; j < z->img_mcu_y; ++j) { - for (i=0; i < z->img_mcu_x; ++i) { - // scan an interleaved mcu... process scan_n components in order - for (k=0; k < z->scan_n; ++k) { - int n = z->order[k]; - // scan out an mcu's worth of this component; that's just determined - // by the basic H and V specified for the component - for (y=0; y < z->img_comp[n].v; ++y) { - for (x=0; x < z->img_comp[n].h; ++x) { - int x2 = (i*z->img_comp[n].h + x); - int y2 = (j*z->img_comp[n].v + y); - short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); - if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) - return 0; - } - } - } - // after all interleaved components, that's an interleaved MCU, - // so now count down the restart interval - if (--z->todo <= 0) { - if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); - if (!STBI__RESTART(z->marker)) return 1; - stbi__jpeg_reset(z); - } - } - } - return 1; - } - } -} - -static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) -{ - int i; - for (i=0; i < 64; ++i) - data[i] *= dequant[i]; -} - -static void stbi__jpeg_finish(stbi__jpeg *z) -{ - if (z->progressive) { - // dequantize and idct the data - int i,j,n; - for (n=0; n < z->s->img_n; ++n) { - int w = (z->img_comp[n].x+7) >> 3; - int h = (z->img_comp[n].y+7) >> 3; - for (j=0; j < h; ++j) { - for (i=0; i < w; ++i) { - short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); - stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); - z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); - } - } - } - } -} - -static int stbi__process_marker(stbi__jpeg *z, int m) -{ - int L; - switch (m) { - case STBI__MARKER_none: // no marker found - return stbi__err("expected marker","Corrupt JPEG"); - - case 0xDD: // DRI - specify restart interval - if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); - z->restart_interval = stbi__get16be(z->s); - return 1; - - case 0xDB: // DQT - define quantization table - L = stbi__get16be(z->s)-2; - while (L > 0) { - int q = stbi__get8(z->s); - int p = q >> 4, sixteen = (p != 0); - int t = q & 15,i; - if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); - if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); - - for (i=0; i < 64; ++i) - z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); - L -= (sixteen ? 129 : 65); - } - return L==0; - - case 0xC4: // DHT - define huffman table - L = stbi__get16be(z->s)-2; - while (L > 0) { - stbi_uc *v; - int sizes[16],i,n=0; - int q = stbi__get8(z->s); - int tc = q >> 4; - int th = q & 15; - if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); - for (i=0; i < 16; ++i) { - sizes[i] = stbi__get8(z->s); - n += sizes[i]; - } - if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values! - L -= 17; - if (tc == 0) { - if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; - v = z->huff_dc[th].values; - } else { - if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; - v = z->huff_ac[th].values; - } - for (i=0; i < n; ++i) - v[i] = stbi__get8(z->s); - if (tc != 0) - stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); - L -= n; - } - return L==0; - } - - // check for comment block or APP blocks - if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { - L = stbi__get16be(z->s); - if (L < 2) { - if (m == 0xFE) - return stbi__err("bad COM len","Corrupt JPEG"); - else - return stbi__err("bad APP len","Corrupt JPEG"); - } - L -= 2; - - if (m == 0xE0 && L >= 5) { // JFIF APP0 segment - static const unsigned char tag[5] = {'J','F','I','F','\0'}; - int ok = 1; - int i; - for (i=0; i < 5; ++i) - if (stbi__get8(z->s) != tag[i]) - ok = 0; - L -= 5; - if (ok) - z->jfif = 1; - } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment - static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; - int ok = 1; - int i; - for (i=0; i < 6; ++i) - if (stbi__get8(z->s) != tag[i]) - ok = 0; - L -= 6; - if (ok) { - stbi__get8(z->s); // version - stbi__get16be(z->s); // flags0 - stbi__get16be(z->s); // flags1 - z->app14_color_transform = stbi__get8(z->s); // color transform - L -= 6; - } - } - - stbi__skip(z->s, L); - return 1; - } - - return stbi__err("unknown marker","Corrupt JPEG"); -} - -// after we see SOS -static int stbi__process_scan_header(stbi__jpeg *z) -{ - int i; - int Ls = stbi__get16be(z->s); - z->scan_n = stbi__get8(z->s); - if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); - if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); - for (i=0; i < z->scan_n; ++i) { - int id = stbi__get8(z->s), which; - int q = stbi__get8(z->s); - for (which = 0; which < z->s->img_n; ++which) - if (z->img_comp[which].id == id) - break; - if (which == z->s->img_n) return 0; // no match - z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); - z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); - z->order[i] = which; - } - - { - int aa; - z->spec_start = stbi__get8(z->s); - z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 - aa = stbi__get8(z->s); - z->succ_high = (aa >> 4); - z->succ_low = (aa & 15); - if (z->progressive) { - if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) - return stbi__err("bad SOS", "Corrupt JPEG"); - } else { - if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); - if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); - z->spec_end = 63; - } - } - - return 1; -} - -static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) -{ - int i; - for (i=0; i < ncomp; ++i) { - if (z->img_comp[i].raw_data) { - STBI_FREE(z->img_comp[i].raw_data); - z->img_comp[i].raw_data = NULL; - z->img_comp[i].data = NULL; - } - if (z->img_comp[i].raw_coeff) { - STBI_FREE(z->img_comp[i].raw_coeff); - z->img_comp[i].raw_coeff = 0; - z->img_comp[i].coeff = 0; - } - if (z->img_comp[i].linebuf) { - STBI_FREE(z->img_comp[i].linebuf); - z->img_comp[i].linebuf = NULL; - } - } - return why; -} - -static int stbi__process_frame_header(stbi__jpeg *z, int scan) -{ - stbi__context *s = z->s; - int Lf,p,i,q, h_max=1,v_max=1,c; - Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG - p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline - s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG - s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires - if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); - if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); - c = stbi__get8(s); - if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); - s->img_n = c; - for (i=0; i < c; ++i) { - z->img_comp[i].data = NULL; - z->img_comp[i].linebuf = NULL; - } - - if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); - - z->rgb = 0; - for (i=0; i < s->img_n; ++i) { - static const unsigned char rgb[3] = { 'R', 'G', 'B' }; - z->img_comp[i].id = stbi__get8(s); - if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) - ++z->rgb; - q = stbi__get8(s); - z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); - z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); - z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); - } - - if (scan != STBI__SCAN_load) return 1; - - if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); - - for (i=0; i < s->img_n; ++i) { - if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; - if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; - } - - // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios - // and I've never seen a non-corrupted JPEG file actually use them - for (i=0; i < s->img_n; ++i) { - if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG"); - if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG"); - } - - // compute interleaved mcu info - z->img_h_max = h_max; - z->img_v_max = v_max; - z->img_mcu_w = h_max * 8; - z->img_mcu_h = v_max * 8; - // these sizes can't be more than 17 bits - z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; - z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; - - for (i=0; i < s->img_n; ++i) { - // number of effective pixels (e.g. for non-interleaved MCU) - z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; - z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; - // to simplify generation, we'll allocate enough memory to decode - // the bogus oversized data from using interleaved MCUs and their - // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't - // discard the extra data until colorspace conversion - // - // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) - // so these muls can't overflow with 32-bit ints (which we require) - z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; - z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; - z->img_comp[i].coeff = 0; - z->img_comp[i].raw_coeff = 0; - z->img_comp[i].linebuf = NULL; - z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); - if (z->img_comp[i].raw_data == NULL) - return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); - // align blocks for idct using mmx/sse - z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); - if (z->progressive) { - // w2, h2 are multiples of 8 (see above) - z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; - z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; - z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); - if (z->img_comp[i].raw_coeff == NULL) - return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); - z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); - } - } - - return 1; -} - -// use comparisons since in some cases we handle more than one case (e.g. SOF) -#define stbi__DNL(x) ((x) == 0xdc) -#define stbi__SOI(x) ((x) == 0xd8) -#define stbi__EOI(x) ((x) == 0xd9) -#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) -#define stbi__SOS(x) ((x) == 0xda) - -#define stbi__SOF_progressive(x) ((x) == 0xc2) - -static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) -{ - int m; - z->jfif = 0; - z->app14_color_transform = -1; // valid values are 0,1,2 - z->marker = STBI__MARKER_none; // initialize cached marker to empty - m = stbi__get_marker(z); - if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); - if (scan == STBI__SCAN_type) return 1; - m = stbi__get_marker(z); - while (!stbi__SOF(m)) { - if (!stbi__process_marker(z,m)) return 0; - m = stbi__get_marker(z); - while (m == STBI__MARKER_none) { - // some files have extra padding after their blocks, so ok, we'll scan - if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); - m = stbi__get_marker(z); - } - } - z->progressive = stbi__SOF_progressive(m); - if (!stbi__process_frame_header(z, scan)) return 0; - return 1; -} - -static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) -{ - // some JPEGs have junk at end, skip over it but if we find what looks - // like a valid marker, resume there - while (!stbi__at_eof(j->s)) { - stbi_uc x = stbi__get8(j->s); - while (x == 0xff) { // might be a marker - if (stbi__at_eof(j->s)) return STBI__MARKER_none; - x = stbi__get8(j->s); - if (x != 0x00 && x != 0xff) { - // not a stuffed zero or lead-in to another marker, looks - // like an actual marker, return it - return x; - } - // stuffed zero has x=0 now which ends the loop, meaning we go - // back to regular scan loop. - // repeated 0xff keeps trying to read the next byte of the marker. - } - } - return STBI__MARKER_none; -} - -// decode image to YCbCr format -static int stbi__decode_jpeg_image(stbi__jpeg *j) -{ - int m; - for (m = 0; m < 4; m++) { - j->img_comp[m].raw_data = NULL; - j->img_comp[m].raw_coeff = NULL; - } - j->restart_interval = 0; - if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; - m = stbi__get_marker(j); - while (!stbi__EOI(m)) { - if (stbi__SOS(m)) { - if (!stbi__process_scan_header(j)) return 0; - if (!stbi__parse_entropy_coded_data(j)) return 0; - if (j->marker == STBI__MARKER_none ) { - j->marker = stbi__skip_jpeg_junk_at_end(j); - // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 - } - m = stbi__get_marker(j); - if (STBI__RESTART(m)) - m = stbi__get_marker(j); - } else if (stbi__DNL(m)) { - int Ld = stbi__get16be(j->s); - stbi__uint32 NL = stbi__get16be(j->s); - if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); - if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); - m = stbi__get_marker(j); - } else { - if (!stbi__process_marker(j, m)) return 1; - m = stbi__get_marker(j); - } - } - if (j->progressive) - stbi__jpeg_finish(j); - return 1; -} - -// static jfif-centered resampling (across block boundaries) - -typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, - int w, int hs); - -#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) - -static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) -{ - STBI_NOTUSED(out); - STBI_NOTUSED(in_far); - STBI_NOTUSED(w); - STBI_NOTUSED(hs); - return in_near; -} - -static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) -{ - // need to generate two samples vertically for every one in input - int i; - STBI_NOTUSED(hs); - for (i=0; i < w; ++i) - out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); - return out; -} - -static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) -{ - // need to generate two samples horizontally for every one in input - int i; - stbi_uc *input = in_near; - - if (w == 1) { - // if only one sample, can't do any interpolation - out[0] = out[1] = input[0]; - return out; - } - - out[0] = input[0]; - out[1] = stbi__div4(input[0]*3 + input[1] + 2); - for (i=1; i < w-1; ++i) { - int n = 3*input[i]+2; - out[i*2+0] = stbi__div4(n+input[i-1]); - out[i*2+1] = stbi__div4(n+input[i+1]); - } - out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); - out[i*2+1] = input[w-1]; - - STBI_NOTUSED(in_far); - STBI_NOTUSED(hs); - - return out; -} - -#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) - -static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) -{ - // need to generate 2x2 samples for every one in input - int i,t0,t1; - if (w == 1) { - out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); - return out; - } - - t1 = 3*in_near[0] + in_far[0]; - out[0] = stbi__div4(t1+2); - for (i=1; i < w; ++i) { - t0 = t1; - t1 = 3*in_near[i]+in_far[i]; - out[i*2-1] = stbi__div16(3*t0 + t1 + 8); - out[i*2 ] = stbi__div16(3*t1 + t0 + 8); - } - out[w*2-1] = stbi__div4(t1+2); - - STBI_NOTUSED(hs); - - return out; -} - -#if defined(STBI_SSE2) || defined(STBI_NEON) -static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) -{ - // need to generate 2x2 samples for every one in input - int i=0,t0,t1; - - if (w == 1) { - out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); - return out; - } - - t1 = 3*in_near[0] + in_far[0]; - // process groups of 8 pixels for as long as we can. - // note we can't handle the last pixel in a row in this loop - // because we need to handle the filter boundary conditions. - for (; i < ((w-1) & ~7); i += 8) { -#if defined(STBI_SSE2) - // load and perform the vertical filtering pass - // this uses 3*x + y = 4*x + (y - x) - __m128i zero = _mm_setzero_si128(); - __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); - __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); - __m128i farw = _mm_unpacklo_epi8(farb, zero); - __m128i nearw = _mm_unpacklo_epi8(nearb, zero); - __m128i diff = _mm_sub_epi16(farw, nearw); - __m128i nears = _mm_slli_epi16(nearw, 2); - __m128i curr = _mm_add_epi16(nears, diff); // current row - - // horizontal filter works the same based on shifted vers of current - // row. "prev" is current row shifted right by 1 pixel; we need to - // insert the previous pixel value (from t1). - // "next" is current row shifted left by 1 pixel, with first pixel - // of next block of 8 pixels added in. - __m128i prv0 = _mm_slli_si128(curr, 2); - __m128i nxt0 = _mm_srli_si128(curr, 2); - __m128i prev = _mm_insert_epi16(prv0, t1, 0); - __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); - - // horizontal filter, polyphase implementation since it's convenient: - // even pixels = 3*cur + prev = cur*4 + (prev - cur) - // odd pixels = 3*cur + next = cur*4 + (next - cur) - // note the shared term. - __m128i bias = _mm_set1_epi16(8); - __m128i curs = _mm_slli_epi16(curr, 2); - __m128i prvd = _mm_sub_epi16(prev, curr); - __m128i nxtd = _mm_sub_epi16(next, curr); - __m128i curb = _mm_add_epi16(curs, bias); - __m128i even = _mm_add_epi16(prvd, curb); - __m128i odd = _mm_add_epi16(nxtd, curb); - - // interleave even and odd pixels, then undo scaling. - __m128i int0 = _mm_unpacklo_epi16(even, odd); - __m128i int1 = _mm_unpackhi_epi16(even, odd); - __m128i de0 = _mm_srli_epi16(int0, 4); - __m128i de1 = _mm_srli_epi16(int1, 4); - - // pack and write output - __m128i outv = _mm_packus_epi16(de0, de1); - _mm_storeu_si128((__m128i *) (out + i*2), outv); -#elif defined(STBI_NEON) - // load and perform the vertical filtering pass - // this uses 3*x + y = 4*x + (y - x) - uint8x8_t farb = vld1_u8(in_far + i); - uint8x8_t nearb = vld1_u8(in_near + i); - int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); - int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); - int16x8_t curr = vaddq_s16(nears, diff); // current row - - // horizontal filter works the same based on shifted vers of current - // row. "prev" is current row shifted right by 1 pixel; we need to - // insert the previous pixel value (from t1). - // "next" is current row shifted left by 1 pixel, with first pixel - // of next block of 8 pixels added in. - int16x8_t prv0 = vextq_s16(curr, curr, 7); - int16x8_t nxt0 = vextq_s16(curr, curr, 1); - int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); - int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); - - // horizontal filter, polyphase implementation since it's convenient: - // even pixels = 3*cur + prev = cur*4 + (prev - cur) - // odd pixels = 3*cur + next = cur*4 + (next - cur) - // note the shared term. - int16x8_t curs = vshlq_n_s16(curr, 2); - int16x8_t prvd = vsubq_s16(prev, curr); - int16x8_t nxtd = vsubq_s16(next, curr); - int16x8_t even = vaddq_s16(curs, prvd); - int16x8_t odd = vaddq_s16(curs, nxtd); - - // undo scaling and round, then store with even/odd phases interleaved - uint8x8x2_t o; - o.val[0] = vqrshrun_n_s16(even, 4); - o.val[1] = vqrshrun_n_s16(odd, 4); - vst2_u8(out + i*2, o); -#endif - - // "previous" value for next iter - t1 = 3*in_near[i+7] + in_far[i+7]; - } - - t0 = t1; - t1 = 3*in_near[i] + in_far[i]; - out[i*2] = stbi__div16(3*t1 + t0 + 8); - - for (++i; i < w; ++i) { - t0 = t1; - t1 = 3*in_near[i]+in_far[i]; - out[i*2-1] = stbi__div16(3*t0 + t1 + 8); - out[i*2 ] = stbi__div16(3*t1 + t0 + 8); - } - out[w*2-1] = stbi__div4(t1+2); - - STBI_NOTUSED(hs); - - return out; -} -#endif - -static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) -{ - // resample with nearest-neighbor - int i,j; - STBI_NOTUSED(in_far); - for (i=0; i < w; ++i) - for (j=0; j < hs; ++j) - out[i*hs+j] = in_near[i]; - return out; -} - -// this is a reduced-precision calculation of YCbCr-to-RGB introduced -// to make sure the code produces the same results in both SIMD and scalar -#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) -static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) -{ - int i; - for (i=0; i < count; ++i) { - int y_fixed = (y[i] << 20) + (1<<19); // rounding - int r,g,b; - int cr = pcr[i] - 128; - int cb = pcb[i] - 128; - r = y_fixed + cr* stbi__float2fixed(1.40200f); - g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); - b = y_fixed + cb* stbi__float2fixed(1.77200f); - r >>= 20; - g >>= 20; - b >>= 20; - if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } - if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } - if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } - out[0] = (stbi_uc)r; - out[1] = (stbi_uc)g; - out[2] = (stbi_uc)b; - out[3] = 255; - out += step; - } -} - -#if defined(STBI_SSE2) || defined(STBI_NEON) -static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) -{ - int i = 0; - -#ifdef STBI_SSE2 - // step == 3 is pretty ugly on the final interleave, and i'm not convinced - // it's useful in practice (you wouldn't use it for textures, for example). - // so just accelerate step == 4 case. - if (step == 4) { - // this is a fairly straightforward implementation and not super-optimized. - __m128i signflip = _mm_set1_epi8(-0x80); - __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); - __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); - __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); - __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); - __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); - __m128i xw = _mm_set1_epi16(255); // alpha channel - - for (; i+7 < count; i += 8) { - // load - __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); - __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); - __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); - __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 - __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 - - // unpack to short (and left-shift cr, cb by 8) - __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); - __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); - __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); - - // color transform - __m128i yws = _mm_srli_epi16(yw, 4); - __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); - __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); - __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); - __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); - __m128i rws = _mm_add_epi16(cr0, yws); - __m128i gwt = _mm_add_epi16(cb0, yws); - __m128i bws = _mm_add_epi16(yws, cb1); - __m128i gws = _mm_add_epi16(gwt, cr1); - - // descale - __m128i rw = _mm_srai_epi16(rws, 4); - __m128i bw = _mm_srai_epi16(bws, 4); - __m128i gw = _mm_srai_epi16(gws, 4); - - // back to byte, set up for transpose - __m128i brb = _mm_packus_epi16(rw, bw); - __m128i gxb = _mm_packus_epi16(gw, xw); - - // transpose to interleave channels - __m128i t0 = _mm_unpacklo_epi8(brb, gxb); - __m128i t1 = _mm_unpackhi_epi8(brb, gxb); - __m128i o0 = _mm_unpacklo_epi16(t0, t1); - __m128i o1 = _mm_unpackhi_epi16(t0, t1); - - // store - _mm_storeu_si128((__m128i *) (out + 0), o0); - _mm_storeu_si128((__m128i *) (out + 16), o1); - out += 32; - } - } -#endif - -#ifdef STBI_NEON - // in this version, step=3 support would be easy to add. but is there demand? - if (step == 4) { - // this is a fairly straightforward implementation and not super-optimized. - uint8x8_t signflip = vdup_n_u8(0x80); - int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); - int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); - int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); - int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); - - for (; i+7 < count; i += 8) { - // load - uint8x8_t y_bytes = vld1_u8(y + i); - uint8x8_t cr_bytes = vld1_u8(pcr + i); - uint8x8_t cb_bytes = vld1_u8(pcb + i); - int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); - int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); - - // expand to s16 - int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); - int16x8_t crw = vshll_n_s8(cr_biased, 7); - int16x8_t cbw = vshll_n_s8(cb_biased, 7); - - // color transform - int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); - int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); - int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); - int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); - int16x8_t rws = vaddq_s16(yws, cr0); - int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); - int16x8_t bws = vaddq_s16(yws, cb1); - - // undo scaling, round, convert to byte - uint8x8x4_t o; - o.val[0] = vqrshrun_n_s16(rws, 4); - o.val[1] = vqrshrun_n_s16(gws, 4); - o.val[2] = vqrshrun_n_s16(bws, 4); - o.val[3] = vdup_n_u8(255); - - // store, interleaving r/g/b/a - vst4_u8(out, o); - out += 8*4; - } - } -#endif - - for (; i < count; ++i) { - int y_fixed = (y[i] << 20) + (1<<19); // rounding - int r,g,b; - int cr = pcr[i] - 128; - int cb = pcb[i] - 128; - r = y_fixed + cr* stbi__float2fixed(1.40200f); - g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); - b = y_fixed + cb* stbi__float2fixed(1.77200f); - r >>= 20; - g >>= 20; - b >>= 20; - if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } - if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } - if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } - out[0] = (stbi_uc)r; - out[1] = (stbi_uc)g; - out[2] = (stbi_uc)b; - out[3] = 255; - out += step; - } -} -#endif - -// set up the kernels -static void stbi__setup_jpeg(stbi__jpeg *j) -{ - j->idct_block_kernel = stbi__idct_block; - j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; - j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; - -#ifdef STBI_SSE2 - if (stbi__sse2_available()) { - j->idct_block_kernel = stbi__idct_simd; - j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; - j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; - } -#endif - -#ifdef STBI_NEON - j->idct_block_kernel = stbi__idct_simd; - j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; - j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; -#endif -} - -// clean up the temporary component buffers -static void stbi__cleanup_jpeg(stbi__jpeg *j) -{ - stbi__free_jpeg_components(j, j->s->img_n, 0); -} - -typedef struct -{ - resample_row_func resample; - stbi_uc *line0,*line1; - int hs,vs; // expansion factor in each axis - int w_lores; // horizontal pixels pre-expansion - int ystep; // how far through vertical expansion we are - int ypos; // which pre-expansion row we're on -} stbi__resample; - -// fast 0..255 * 0..255 => 0..255 rounded multiplication -static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) -{ - unsigned int t = x*y + 128; - return (stbi_uc) ((t + (t >>8)) >> 8); -} - -static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) -{ - int n, decode_n, is_rgb; - z->s->img_n = 0; // make stbi__cleanup_jpeg safe - - // validate req_comp - if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); - - // load a jpeg image from whichever source, but leave in YCbCr format - if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } - - // determine actual number of components to generate - n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; - - is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); - - if (z->s->img_n == 3 && n < 3 && !is_rgb) - decode_n = 1; - else - decode_n = z->s->img_n; - - // nothing to do if no components requested; check this now to avoid - // accessing uninitialized coutput[0] later - if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; } - - // resample and color-convert - { - int k; - unsigned int i,j; - stbi_uc *output; - stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; - - stbi__resample res_comp[4]; - - for (k=0; k < decode_n; ++k) { - stbi__resample *r = &res_comp[k]; - - // allocate line buffer big enough for upsampling off the edges - // with upsample factor of 4 - z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); - if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } - - r->hs = z->img_h_max / z->img_comp[k].h; - r->vs = z->img_v_max / z->img_comp[k].v; - r->ystep = r->vs >> 1; - r->w_lores = (z->s->img_x + r->hs-1) / r->hs; - r->ypos = 0; - r->line0 = r->line1 = z->img_comp[k].data; - - if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; - else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; - else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; - else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; - else r->resample = stbi__resample_row_generic; - } - - // can't error after this so, this is safe - output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); - if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } - - // now go ahead and resample - for (j=0; j < z->s->img_y; ++j) { - stbi_uc *out = output + n * z->s->img_x * j; - for (k=0; k < decode_n; ++k) { - stbi__resample *r = &res_comp[k]; - int y_bot = r->ystep >= (r->vs >> 1); - coutput[k] = r->resample(z->img_comp[k].linebuf, - y_bot ? r->line1 : r->line0, - y_bot ? r->line0 : r->line1, - r->w_lores, r->hs); - if (++r->ystep >= r->vs) { - r->ystep = 0; - r->line0 = r->line1; - if (++r->ypos < z->img_comp[k].y) - r->line1 += z->img_comp[k].w2; - } - } - if (n >= 3) { - stbi_uc *y = coutput[0]; - if (z->s->img_n == 3) { - if (is_rgb) { - for (i=0; i < z->s->img_x; ++i) { - out[0] = y[i]; - out[1] = coutput[1][i]; - out[2] = coutput[2][i]; - out[3] = 255; - out += n; - } - } else { - z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); - } - } else if (z->s->img_n == 4) { - if (z->app14_color_transform == 0) { // CMYK - for (i=0; i < z->s->img_x; ++i) { - stbi_uc m = coutput[3][i]; - out[0] = stbi__blinn_8x8(coutput[0][i], m); - out[1] = stbi__blinn_8x8(coutput[1][i], m); - out[2] = stbi__blinn_8x8(coutput[2][i], m); - out[3] = 255; - out += n; - } - } else if (z->app14_color_transform == 2) { // YCCK - z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); - for (i=0; i < z->s->img_x; ++i) { - stbi_uc m = coutput[3][i]; - out[0] = stbi__blinn_8x8(255 - out[0], m); - out[1] = stbi__blinn_8x8(255 - out[1], m); - out[2] = stbi__blinn_8x8(255 - out[2], m); - out += n; - } - } else { // YCbCr + alpha? Ignore the fourth channel for now - z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); - } - } else - for (i=0; i < z->s->img_x; ++i) { - out[0] = out[1] = out[2] = y[i]; - out[3] = 255; // not used if n==3 - out += n; - } - } else { - if (is_rgb) { - if (n == 1) - for (i=0; i < z->s->img_x; ++i) - *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); - else { - for (i=0; i < z->s->img_x; ++i, out += 2) { - out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); - out[1] = 255; - } - } - } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { - for (i=0; i < z->s->img_x; ++i) { - stbi_uc m = coutput[3][i]; - stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); - stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); - stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); - out[0] = stbi__compute_y(r, g, b); - out[1] = 255; - out += n; - } - } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { - for (i=0; i < z->s->img_x; ++i) { - out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); - out[1] = 255; - out += n; - } - } else { - stbi_uc *y = coutput[0]; - if (n == 1) - for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; - else - for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; } - } - } - } - stbi__cleanup_jpeg(z); - *out_x = z->s->img_x; - *out_y = z->s->img_y; - if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output - return output; - } -} - -static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) -{ - unsigned char* result; - stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); - if (!j) return stbi__errpuc("outofmem", "Out of memory"); - memset(j, 0, sizeof(stbi__jpeg)); - STBI_NOTUSED(ri); - j->s = s; - stbi__setup_jpeg(j); - result = load_jpeg_image(j, x,y,comp,req_comp); - STBI_FREE(j); - return result; -} - -static int stbi__jpeg_test(stbi__context *s) -{ - int r; - stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); - if (!j) return stbi__err("outofmem", "Out of memory"); - memset(j, 0, sizeof(stbi__jpeg)); - j->s = s; - stbi__setup_jpeg(j); - r = stbi__decode_jpeg_header(j, STBI__SCAN_type); - stbi__rewind(s); - STBI_FREE(j); - return r; -} - -static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) -{ - if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { - stbi__rewind( j->s ); - return 0; - } - if (x) *x = j->s->img_x; - if (y) *y = j->s->img_y; - if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; - return 1; -} - -static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) -{ - int result; - stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); - if (!j) return stbi__err("outofmem", "Out of memory"); - memset(j, 0, sizeof(stbi__jpeg)); - j->s = s; - result = stbi__jpeg_info_raw(j, x, y, comp); - STBI_FREE(j); - return result; -} -#endif - -// public domain zlib decode v0.2 Sean Barrett 2006-11-18 -// simple implementation -// - all input must be provided in an upfront buffer -// - all output is written to a single output buffer (can malloc/realloc) -// performance -// - fast huffman - -#ifndef STBI_NO_ZLIB - -// fast-way is faster to check than jpeg huffman, but slow way is slower -#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables -#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) -#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet - -// zlib-style huffman encoding -// (jpegs packs from left, zlib from right, so can't share code) -typedef struct -{ - stbi__uint16 fast[1 << STBI__ZFAST_BITS]; - stbi__uint16 firstcode[16]; - int maxcode[17]; - stbi__uint16 firstsymbol[16]; - stbi_uc size[STBI__ZNSYMS]; - stbi__uint16 value[STBI__ZNSYMS]; -} stbi__zhuffman; - -stbi_inline static int stbi__bitreverse16(int n) -{ - n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); - n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); - n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); - n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); - return n; -} - -stbi_inline static int stbi__bit_reverse(int v, int bits) -{ - STBI_ASSERT(bits <= 16); - // to bit reverse n bits, reverse 16 and shift - // e.g. 11 bits, bit reverse and shift away 5 - return stbi__bitreverse16(v) >> (16-bits); -} - -static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) -{ - int i,k=0; - int code, next_code[16], sizes[17]; - - // DEFLATE spec for generating codes - memset(sizes, 0, sizeof(sizes)); - memset(z->fast, 0, sizeof(z->fast)); - for (i=0; i < num; ++i) - ++sizes[sizelist[i]]; - sizes[0] = 0; - for (i=1; i < 16; ++i) - if (sizes[i] > (1 << i)) - return stbi__err("bad sizes", "Corrupt PNG"); - code = 0; - for (i=1; i < 16; ++i) { - next_code[i] = code; - z->firstcode[i] = (stbi__uint16) code; - z->firstsymbol[i] = (stbi__uint16) k; - code = (code + sizes[i]); - if (sizes[i]) - if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); - z->maxcode[i] = code << (16-i); // preshift for inner loop - code <<= 1; - k += sizes[i]; - } - z->maxcode[16] = 0x10000; // sentinel - for (i=0; i < num; ++i) { - int s = sizelist[i]; - if (s) { - int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; - stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); - z->size [c] = (stbi_uc ) s; - z->value[c] = (stbi__uint16) i; - if (s <= STBI__ZFAST_BITS) { - int j = stbi__bit_reverse(next_code[s],s); - while (j < (1 << STBI__ZFAST_BITS)) { - z->fast[j] = fastv; - j += (1 << s); - } - } - ++next_code[s]; - } - } - return 1; -} - -// zlib-from-memory implementation for PNG reading -// because PNG allows splitting the zlib stream arbitrarily, -// and it's annoying structurally to have PNG call ZLIB call PNG, -// we require PNG read all the IDATs and combine them into a single -// memory buffer - -typedef struct -{ - stbi_uc *zbuffer, *zbuffer_end; - int num_bits; - int hit_zeof_once; - stbi__uint32 code_buffer; - - char *zout; - char *zout_start; - char *zout_end; - int z_expandable; - - stbi__zhuffman z_length, z_distance; -} stbi__zbuf; - -stbi_inline static int stbi__zeof(stbi__zbuf *z) -{ - return (z->zbuffer >= z->zbuffer_end); -} - -stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) -{ - return stbi__zeof(z) ? 0 : *z->zbuffer++; -} - -static void stbi__fill_bits(stbi__zbuf *z) -{ - do { - if (z->code_buffer >= (1U << z->num_bits)) { - z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */ - return; - } - z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; - z->num_bits += 8; - } while (z->num_bits <= 24); -} - -stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) -{ - unsigned int k; - if (z->num_bits < n) stbi__fill_bits(z); - k = z->code_buffer & ((1 << n) - 1); - z->code_buffer >>= n; - z->num_bits -= n; - return k; -} - -static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) -{ - int b,s,k; - // not resolved by fast table, so compute it the slow way - // use jpeg approach, which requires MSbits at top - k = stbi__bit_reverse(a->code_buffer, 16); - for (s=STBI__ZFAST_BITS+1; ; ++s) - if (k < z->maxcode[s]) - break; - if (s >= 16) return -1; // invalid code! - // code size is s, so: - b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; - if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere! - if (z->size[b] != s) return -1; // was originally an assert, but report failure instead. - a->code_buffer >>= s; - a->num_bits -= s; - return z->value[b]; -} - -stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) -{ - int b,s; - if (a->num_bits < 16) { - if (stbi__zeof(a)) { - if (!a->hit_zeof_once) { - // This is the first time we hit eof, insert 16 extra padding btis - // to allow us to keep going; if we actually consume any of them - // though, that is invalid data. This is caught later. - a->hit_zeof_once = 1; - a->num_bits += 16; // add 16 implicit zero bits - } else { - // We already inserted our extra 16 padding bits and are again - // out, this stream is actually prematurely terminated. - return -1; - } - } else { - stbi__fill_bits(a); - } - } - b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; - if (b) { - s = b >> 9; - a->code_buffer >>= s; - a->num_bits -= s; - return b & 511; - } - return stbi__zhuffman_decode_slowpath(a, z); -} - -static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes -{ - char *q; - unsigned int cur, limit, old_limit; - z->zout = zout; - if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); - cur = (unsigned int) (z->zout - z->zout_start); - limit = old_limit = (unsigned) (z->zout_end - z->zout_start); - if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory"); - while (cur + n > limit) { - if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory"); - limit *= 2; - } - q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); - STBI_NOTUSED(old_limit); - if (q == NULL) return stbi__err("outofmem", "Out of memory"); - z->zout_start = q; - z->zout = q + cur; - z->zout_end = q + limit; - return 1; -} - -static const int stbi__zlength_base[31] = { - 3,4,5,6,7,8,9,10,11,13, - 15,17,19,23,27,31,35,43,51,59, - 67,83,99,115,131,163,195,227,258,0,0 }; - -static const int stbi__zlength_extra[31]= -{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; - -static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, -257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; - -static const int stbi__zdist_extra[32] = -{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -static int stbi__parse_huffman_block(stbi__zbuf *a) -{ - char *zout = a->zout; - for(;;) { - int z = stbi__zhuffman_decode(a, &a->z_length); - if (z < 256) { - if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes - if (zout >= a->zout_end) { - if (!stbi__zexpand(a, zout, 1)) return 0; - zout = a->zout; - } - *zout++ = (char) z; - } else { - stbi_uc *p; - int len,dist; - if (z == 256) { - a->zout = zout; - if (a->hit_zeof_once && a->num_bits < 16) { - // The first time we hit zeof, we inserted 16 extra zero bits into our bit - // buffer so the decoder can just do its speculative decoding. But if we - // actually consumed any of those bits (which is the case when num_bits < 16), - // the stream actually read past the end so it is malformed. - return stbi__err("unexpected end","Corrupt PNG"); - } - return 1; - } - if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data - z -= 257; - len = stbi__zlength_base[z]; - if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); - z = stbi__zhuffman_decode(a, &a->z_distance); - if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data - dist = stbi__zdist_base[z]; - if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); - if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); - if (len > a->zout_end - zout) { - if (!stbi__zexpand(a, zout, len)) return 0; - zout = a->zout; - } - p = (stbi_uc *) (zout - dist); - if (dist == 1) { // run of one byte; common in images. - stbi_uc v = *p; - if (len) { do *zout++ = v; while (--len); } - } else { - if (len) { do *zout++ = *p++; while (--len); } - } - } - } -} - -static int stbi__compute_huffman_codes(stbi__zbuf *a) -{ - static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; - stbi__zhuffman z_codelength; - stbi_uc lencodes[286+32+137];//padding for maximum single op - stbi_uc codelength_sizes[19]; - int i,n; - - int hlit = stbi__zreceive(a,5) + 257; - int hdist = stbi__zreceive(a,5) + 1; - int hclen = stbi__zreceive(a,4) + 4; - int ntot = hlit + hdist; - - memset(codelength_sizes, 0, sizeof(codelength_sizes)); - for (i=0; i < hclen; ++i) { - int s = stbi__zreceive(a,3); - codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; - } - if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; - - n = 0; - while (n < ntot) { - int c = stbi__zhuffman_decode(a, &z_codelength); - if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); - if (c < 16) - lencodes[n++] = (stbi_uc) c; - else { - stbi_uc fill = 0; - if (c == 16) { - c = stbi__zreceive(a,2)+3; - if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); - fill = lencodes[n-1]; - } else if (c == 17) { - c = stbi__zreceive(a,3)+3; - } else if (c == 18) { - c = stbi__zreceive(a,7)+11; - } else { - return stbi__err("bad codelengths", "Corrupt PNG"); - } - if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); - memset(lencodes+n, fill, c); - n += c; - } - } - if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); - if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; - if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; - return 1; -} - -static int stbi__parse_uncompressed_block(stbi__zbuf *a) -{ - stbi_uc header[4]; - int len,nlen,k; - if (a->num_bits & 7) - stbi__zreceive(a, a->num_bits & 7); // discard - // drain the bit-packed data into header - k = 0; - while (a->num_bits > 0) { - header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check - a->code_buffer >>= 8; - a->num_bits -= 8; - } - if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG"); - // now fill header the normal way - while (k < 4) - header[k++] = stbi__zget8(a); - len = header[1] * 256 + header[0]; - nlen = header[3] * 256 + header[2]; - if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); - if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); - if (a->zout + len > a->zout_end) - if (!stbi__zexpand(a, a->zout, len)) return 0; - memcpy(a->zout, a->zbuffer, len); - a->zbuffer += len; - a->zout += len; - return 1; -} - -static int stbi__parse_zlib_header(stbi__zbuf *a) -{ - int cmf = stbi__zget8(a); - int cm = cmf & 15; - /* int cinfo = cmf >> 4; */ - int flg = stbi__zget8(a); - if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec - if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec - if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png - if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png - // window = 1 << (8 + cinfo)... but who cares, we fully buffer output - return 1; -} - -static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] = -{ - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, - 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, - 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, - 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 -}; -static const stbi_uc stbi__zdefault_distance[32] = -{ - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 -}; -/* -Init algorithm: -{ - int i; // use <= to match clearly with spec - for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; - for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; - for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; - for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; - - for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; -} -*/ - -static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) -{ - int final, type; - if (parse_header) - if (!stbi__parse_zlib_header(a)) return 0; - a->num_bits = 0; - a->code_buffer = 0; - a->hit_zeof_once = 0; - do { - final = stbi__zreceive(a,1); - type = stbi__zreceive(a,2); - if (type == 0) { - if (!stbi__parse_uncompressed_block(a)) return 0; - } else if (type == 3) { - return 0; - } else { - if (type == 1) { - // use fixed code lengths - if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , STBI__ZNSYMS)) return 0; - if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; - } else { - if (!stbi__compute_huffman_codes(a)) return 0; - } - if (!stbi__parse_huffman_block(a)) return 0; - } - } while (!final); - return 1; -} - -static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) -{ - a->zout_start = obuf; - a->zout = obuf; - a->zout_end = obuf + olen; - a->z_expandable = exp; - - return stbi__parse_zlib(a, parse_header); -} - -STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) -{ - stbi__zbuf a; - char *p = (char *) stbi__malloc(initial_size); - if (p == NULL) return NULL; - a.zbuffer = (stbi_uc *) buffer; - a.zbuffer_end = (stbi_uc *) buffer + len; - if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { - if (outlen) *outlen = (int) (a.zout - a.zout_start); - return a.zout_start; - } else { - STBI_FREE(a.zout_start); - return NULL; - } -} - -STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) -{ - return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); -} - -STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) -{ - stbi__zbuf a; - char *p = (char *) stbi__malloc(initial_size); - if (p == NULL) return NULL; - a.zbuffer = (stbi_uc *) buffer; - a.zbuffer_end = (stbi_uc *) buffer + len; - if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { - if (outlen) *outlen = (int) (a.zout - a.zout_start); - return a.zout_start; - } else { - STBI_FREE(a.zout_start); - return NULL; - } -} - -STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) -{ - stbi__zbuf a; - a.zbuffer = (stbi_uc *) ibuffer; - a.zbuffer_end = (stbi_uc *) ibuffer + ilen; - if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) - return (int) (a.zout - a.zout_start); - else - return -1; -} - -STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) -{ - stbi__zbuf a; - char *p = (char *) stbi__malloc(16384); - if (p == NULL) return NULL; - a.zbuffer = (stbi_uc *) buffer; - a.zbuffer_end = (stbi_uc *) buffer+len; - if (stbi__do_zlib(&a, p, 16384, 1, 0)) { - if (outlen) *outlen = (int) (a.zout - a.zout_start); - return a.zout_start; - } else { - STBI_FREE(a.zout_start); - return NULL; - } -} - -STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) -{ - stbi__zbuf a; - a.zbuffer = (stbi_uc *) ibuffer; - a.zbuffer_end = (stbi_uc *) ibuffer + ilen; - if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) - return (int) (a.zout - a.zout_start); - else - return -1; -} -#endif - -// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 -// simple implementation -// - only 8-bit samples -// - no CRC checking -// - allocates lots of intermediate memory -// - avoids problem of streaming data between subsystems -// - avoids explicit window management -// performance -// - uses stb_zlib, a PD zlib implementation with fast huffman decoding - -#ifndef STBI_NO_PNG -typedef struct -{ - stbi__uint32 length; - stbi__uint32 type; -} stbi__pngchunk; - -static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) -{ - stbi__pngchunk c; - c.length = stbi__get32be(s); - c.type = stbi__get32be(s); - return c; -} - -static int stbi__check_png_header(stbi__context *s) -{ - static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; - int i; - for (i=0; i < 8; ++i) - if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); - return 1; -} - -typedef struct -{ - stbi__context *s; - stbi_uc *idata, *expanded, *out; - int depth; -} stbi__png; - - -enum { - STBI__F_none=0, - STBI__F_sub=1, - STBI__F_up=2, - STBI__F_avg=3, - STBI__F_paeth=4, - // synthetic filter used for first scanline to avoid needing a dummy row of 0s - STBI__F_avg_first -}; - -static stbi_uc first_row_filter[5] = -{ - STBI__F_none, - STBI__F_sub, - STBI__F_none, - STBI__F_avg_first, - STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub -}; - -static int stbi__paeth(int a, int b, int c) -{ - // This formulation looks very different from the reference in the PNG spec, but is - // actually equivalent and has favorable data dependencies and admits straightforward - // generation of branch-free code, which helps performance significantly. - int thresh = c*3 - (a + b); - int lo = a < b ? a : b; - int hi = a < b ? b : a; - int t0 = (hi <= thresh) ? lo : c; - int t1 = (thresh <= lo) ? hi : t0; - return t1; -} - -static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; - -// adds an extra all-255 alpha channel -// dest == src is legal -// img_n must be 1 or 3 -static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n) -{ - int i; - // must process data backwards since we allow dest==src - if (img_n == 1) { - for (i=x-1; i >= 0; --i) { - dest[i*2+1] = 255; - dest[i*2+0] = src[i]; - } - } else { - STBI_ASSERT(img_n == 3); - for (i=x-1; i >= 0; --i) { - dest[i*4+3] = 255; - dest[i*4+2] = src[i*3+2]; - dest[i*4+1] = src[i*3+1]; - dest[i*4+0] = src[i*3+0]; - } - } -} - -// create the png data from post-deflated data -static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) -{ - int bytes = (depth == 16 ? 2 : 1); - stbi__context *s = a->s; - stbi__uint32 i,j,stride = x*out_n*bytes; - stbi__uint32 img_len, img_width_bytes; - stbi_uc *filter_buf; - int all_ok = 1; - int k; - int img_n = s->img_n; // copy it into a local for later - - int output_bytes = out_n*bytes; - int filter_bytes = img_n*bytes; - int width = x; - - STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); - a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into - if (!a->out) return stbi__err("outofmem", "Out of memory"); - - // note: error exits here don't need to clean up a->out individually, - // stbi__do_png always does on error. - if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); - img_width_bytes = (((img_n * x * depth) + 7) >> 3); - if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG"); - img_len = (img_width_bytes + 1) * y; - - // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, - // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), - // so just check for raw_len < img_len always. - if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); - - // Allocate two scan lines worth of filter workspace buffer. - filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0); - if (!filter_buf) return stbi__err("outofmem", "Out of memory"); - - // Filtering for low-bit-depth images - if (depth < 8) { - filter_bytes = 1; - width = img_width_bytes; - } - - for (j=0; j < y; ++j) { - // cur/prior filter buffers alternate - stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes; - stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes; - stbi_uc *dest = a->out + stride*j; - int nk = width * filter_bytes; - int filter = *raw++; - - // check filter type - if (filter > 4) { - all_ok = stbi__err("invalid filter","Corrupt PNG"); - break; - } - - // if first row, use special filter that doesn't sample previous row - if (j == 0) filter = first_row_filter[filter]; - - // perform actual filtering - switch (filter) { - case STBI__F_none: - memcpy(cur, raw, nk); - break; - case STBI__F_sub: - memcpy(cur, raw, filter_bytes); - for (k = filter_bytes; k < nk; ++k) - cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); - break; - case STBI__F_up: - for (k = 0; k < nk; ++k) - cur[k] = STBI__BYTECAST(raw[k] + prior[k]); - break; - case STBI__F_avg: - for (k = 0; k < filter_bytes; ++k) - cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); - for (k = filter_bytes; k < nk; ++k) - cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); - break; - case STBI__F_paeth: - for (k = 0; k < filter_bytes; ++k) - cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0) - for (k = filter_bytes; k < nk; ++k) - cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes])); - break; - case STBI__F_avg_first: - memcpy(cur, raw, filter_bytes); - for (k = filter_bytes; k < nk; ++k) - cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); - break; - } - - raw += nk; - - // expand decoded bits in cur to dest, also adding an extra alpha channel if desired - if (depth < 8) { - stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range - stbi_uc *in = cur; - stbi_uc *out = dest; - stbi_uc inb = 0; - stbi__uint32 nsmp = x*img_n; - - // expand bits to bytes first - if (depth == 4) { - for (i=0; i < nsmp; ++i) { - if ((i & 1) == 0) inb = *in++; - *out++ = scale * (inb >> 4); - inb <<= 4; - } - } else if (depth == 2) { - for (i=0; i < nsmp; ++i) { - if ((i & 3) == 0) inb = *in++; - *out++ = scale * (inb >> 6); - inb <<= 2; - } - } else { - STBI_ASSERT(depth == 1); - for (i=0; i < nsmp; ++i) { - if ((i & 7) == 0) inb = *in++; - *out++ = scale * (inb >> 7); - inb <<= 1; - } - } - - // insert alpha=255 values if desired - if (img_n != out_n) - stbi__create_png_alpha_expand8(dest, dest, x, img_n); - } else if (depth == 8) { - if (img_n == out_n) - memcpy(dest, cur, x*img_n); - else - stbi__create_png_alpha_expand8(dest, cur, x, img_n); - } else if (depth == 16) { - // convert the image data from big-endian to platform-native - stbi__uint16 *dest16 = (stbi__uint16*)dest; - stbi__uint32 nsmp = x*img_n; - - if (img_n == out_n) { - for (i = 0; i < nsmp; ++i, ++dest16, cur += 2) - *dest16 = (cur[0] << 8) | cur[1]; - } else { - STBI_ASSERT(img_n+1 == out_n); - if (img_n == 1) { - for (i = 0; i < x; ++i, dest16 += 2, cur += 2) { - dest16[0] = (cur[0] << 8) | cur[1]; - dest16[1] = 0xffff; - } - } else { - STBI_ASSERT(img_n == 3); - for (i = 0; i < x; ++i, dest16 += 4, cur += 6) { - dest16[0] = (cur[0] << 8) | cur[1]; - dest16[1] = (cur[2] << 8) | cur[3]; - dest16[2] = (cur[4] << 8) | cur[5]; - dest16[3] = 0xffff; - } - } - } - } - } - - STBI_FREE(filter_buf); - if (!all_ok) return 0; - - return 1; -} - -static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) -{ - int bytes = (depth == 16 ? 2 : 1); - int out_bytes = out_n * bytes; - stbi_uc *final; - int p; - if (!interlaced) - return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); - - // de-interlacing - final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); - if (!final) return stbi__err("outofmem", "Out of memory"); - for (p=0; p < 7; ++p) { - int xorig[] = { 0,4,0,2,0,1,0 }; - int yorig[] = { 0,0,4,0,2,0,1 }; - int xspc[] = { 8,8,4,4,2,2,1 }; - int yspc[] = { 8,8,8,4,4,2,2 }; - int i,j,x,y; - // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 - x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; - y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; - if (x && y) { - stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; - if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { - STBI_FREE(final); - return 0; - } - for (j=0; j < y; ++j) { - for (i=0; i < x; ++i) { - int out_y = j*yspc[p]+yorig[p]; - int out_x = i*xspc[p]+xorig[p]; - memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, - a->out + (j*x+i)*out_bytes, out_bytes); - } - } - STBI_FREE(a->out); - image_data += img_len; - image_data_len -= img_len; - } - } - a->out = final; - - return 1; -} - -static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) -{ - stbi__context *s = z->s; - stbi__uint32 i, pixel_count = s->img_x * s->img_y; - stbi_uc *p = z->out; - - // compute color-based transparency, assuming we've - // already got 255 as the alpha value in the output - STBI_ASSERT(out_n == 2 || out_n == 4); - - if (out_n == 2) { - for (i=0; i < pixel_count; ++i) { - p[1] = (p[0] == tc[0] ? 0 : 255); - p += 2; - } - } else { - for (i=0; i < pixel_count; ++i) { - if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) - p[3] = 0; - p += 4; - } - } - return 1; -} - -static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) -{ - stbi__context *s = z->s; - stbi__uint32 i, pixel_count = s->img_x * s->img_y; - stbi__uint16 *p = (stbi__uint16*) z->out; - - // compute color-based transparency, assuming we've - // already got 65535 as the alpha value in the output - STBI_ASSERT(out_n == 2 || out_n == 4); - - if (out_n == 2) { - for (i = 0; i < pixel_count; ++i) { - p[1] = (p[0] == tc[0] ? 0 : 65535); - p += 2; - } - } else { - for (i = 0; i < pixel_count; ++i) { - if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) - p[3] = 0; - p += 4; - } - } - return 1; -} - -static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) -{ - stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; - stbi_uc *p, *temp_out, *orig = a->out; - - p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); - if (p == NULL) return stbi__err("outofmem", "Out of memory"); - - // between here and free(out) below, exitting would leak - temp_out = p; - - if (pal_img_n == 3) { - for (i=0; i < pixel_count; ++i) { - int n = orig[i]*4; - p[0] = palette[n ]; - p[1] = palette[n+1]; - p[2] = palette[n+2]; - p += 3; - } - } else { - for (i=0; i < pixel_count; ++i) { - int n = orig[i]*4; - p[0] = palette[n ]; - p[1] = palette[n+1]; - p[2] = palette[n+2]; - p[3] = palette[n+3]; - p += 4; - } - } - STBI_FREE(a->out); - a->out = temp_out; - - STBI_NOTUSED(len); - - return 1; -} - -static int stbi__unpremultiply_on_load_global = 0; -static int stbi__de_iphone_flag_global = 0; - -STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) -{ - stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply; -} - -STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) -{ - stbi__de_iphone_flag_global = flag_true_if_should_convert; -} - -#ifndef STBI_THREAD_LOCAL -#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global -#define stbi__de_iphone_flag stbi__de_iphone_flag_global -#else -static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; -static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; - -STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) -{ - stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; - stbi__unpremultiply_on_load_set = 1; -} - -STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) -{ - stbi__de_iphone_flag_local = flag_true_if_should_convert; - stbi__de_iphone_flag_set = 1; -} - -#define stbi__unpremultiply_on_load (stbi__unpremultiply_on_load_set \ - ? stbi__unpremultiply_on_load_local \ - : stbi__unpremultiply_on_load_global) -#define stbi__de_iphone_flag (stbi__de_iphone_flag_set \ - ? stbi__de_iphone_flag_local \ - : stbi__de_iphone_flag_global) -#endif // STBI_THREAD_LOCAL - -static void stbi__de_iphone(stbi__png *z) -{ - stbi__context *s = z->s; - stbi__uint32 i, pixel_count = s->img_x * s->img_y; - stbi_uc *p = z->out; - - if (s->img_out_n == 3) { // convert bgr to rgb - for (i=0; i < pixel_count; ++i) { - stbi_uc t = p[0]; - p[0] = p[2]; - p[2] = t; - p += 3; - } - } else { - STBI_ASSERT(s->img_out_n == 4); - if (stbi__unpremultiply_on_load) { - // convert bgr to rgb and unpremultiply - for (i=0; i < pixel_count; ++i) { - stbi_uc a = p[3]; - stbi_uc t = p[0]; - if (a) { - stbi_uc half = a / 2; - p[0] = (p[2] * 255 + half) / a; - p[1] = (p[1] * 255 + half) / a; - p[2] = ( t * 255 + half) / a; - } else { - p[0] = p[2]; - p[2] = t; - } - p += 4; - } - } else { - // convert bgr to rgb - for (i=0; i < pixel_count; ++i) { - stbi_uc t = p[0]; - p[0] = p[2]; - p[2] = t; - p += 4; - } - } - } -} - -#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) - -static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) -{ - stbi_uc palette[1024], pal_img_n=0; - stbi_uc has_trans=0, tc[3]={0}; - stbi__uint16 tc16[3]; - stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; - int first=1,k,interlace=0, color=0, is_iphone=0; - stbi__context *s = z->s; - - z->expanded = NULL; - z->idata = NULL; - z->out = NULL; - - if (!stbi__check_png_header(s)) return 0; - - if (scan == STBI__SCAN_type) return 1; - - for (;;) { - stbi__pngchunk c = stbi__get_chunk_header(s); - switch (c.type) { - case STBI__PNG_TYPE('C','g','B','I'): - is_iphone = 1; - stbi__skip(s, c.length); - break; - case STBI__PNG_TYPE('I','H','D','R'): { - int comp,filter; - if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); - first = 0; - if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); - s->img_x = stbi__get32be(s); - s->img_y = stbi__get32be(s); - if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); - if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); - z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); - color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); - if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); - if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); - comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); - filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); - interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); - if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); - if (!pal_img_n) { - s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); - if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); - } else { - // if paletted, then pal_n is our final components, and - // img_n is # components to decompress/filter. - s->img_n = 1; - if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); - } - // even with SCAN_header, have to scan to see if we have a tRNS - break; - } - - case STBI__PNG_TYPE('P','L','T','E'): { - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); - if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); - pal_len = c.length / 3; - if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); - for (i=0; i < pal_len; ++i) { - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - } - break; - } - - case STBI__PNG_TYPE('t','R','N','S'): { - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); - if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); - if (pal_img_n) { - if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } - if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); - if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); - pal_img_n = 4; - for (i=0; i < c.length; ++i) - palette[i*4+3] = stbi__get8(s); - } else { - if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); - if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); - has_trans = 1; - // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now. - if (scan == STBI__SCAN_header) { ++s->img_n; return 1; } - if (z->depth == 16) { - for (k = 0; k < s->img_n && k < 3; ++k) // extra loop test to suppress false GCC warning - tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is - } else { - for (k = 0; k < s->img_n && k < 3; ++k) - tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger - } - } - break; - } - - case STBI__PNG_TYPE('I','D','A','T'): { - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); - if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); - if (scan == STBI__SCAN_header) { - // header scan definitely stops at first IDAT - if (pal_img_n) - s->img_n = pal_img_n; - return 1; - } - if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes"); - if ((int)(ioff + c.length) < (int)ioff) return 0; - if (ioff + c.length > idata_limit) { - stbi__uint32 idata_limit_old = idata_limit; - stbi_uc *p; - if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; - while (ioff + c.length > idata_limit) - idata_limit *= 2; - STBI_NOTUSED(idata_limit_old); - p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); - z->idata = p; - } - if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); - ioff += c.length; - break; - } - - case STBI__PNG_TYPE('I','E','N','D'): { - stbi__uint32 raw_len, bpl; - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); - if (scan != STBI__SCAN_load) return 1; - if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); - // initial guess for decoded data size to avoid unnecessary reallocs - bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component - raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; - z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); - if (z->expanded == NULL) return 0; // zlib should set error - STBI_FREE(z->idata); z->idata = NULL; - if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) - s->img_out_n = s->img_n+1; - else - s->img_out_n = s->img_n; - if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; - if (has_trans) { - if (z->depth == 16) { - if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; - } else { - if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; - } - } - if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) - stbi__de_iphone(z); - if (pal_img_n) { - // pal_img_n == 3 or 4 - s->img_n = pal_img_n; // record the actual colors we had - s->img_out_n = pal_img_n; - if (req_comp >= 3) s->img_out_n = req_comp; - if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) - return 0; - } else if (has_trans) { - // non-paletted image with tRNS -> source image has (constant) alpha - ++s->img_n; - } - STBI_FREE(z->expanded); z->expanded = NULL; - // end of PNG chunk, read and skip CRC - stbi__get32be(s); - return 1; - } - - default: - // if critical, fail - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); - if ((c.type & (1 << 29)) == 0) { - #ifndef STBI_NO_FAILURE_STRINGS - // not threadsafe - static char invalid_chunk[] = "XXXX PNG chunk not known"; - invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); - invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); - invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); - invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); - #endif - return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); - } - stbi__skip(s, c.length); - break; - } - // end of PNG chunk, read and skip CRC - stbi__get32be(s); - } -} - -static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) -{ - void *result=NULL; - if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); - if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { - if (p->depth <= 8) - ri->bits_per_channel = 8; - else if (p->depth == 16) - ri->bits_per_channel = 16; - else - return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth"); - result = p->out; - p->out = NULL; - if (req_comp && req_comp != p->s->img_out_n) { - if (ri->bits_per_channel == 8) - result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); - else - result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); - p->s->img_out_n = req_comp; - if (result == NULL) return result; - } - *x = p->s->img_x; - *y = p->s->img_y; - if (n) *n = p->s->img_n; - } - STBI_FREE(p->out); p->out = NULL; - STBI_FREE(p->expanded); p->expanded = NULL; - STBI_FREE(p->idata); p->idata = NULL; - - return result; -} - -static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) -{ - stbi__png p; - p.s = s; - return stbi__do_png(&p, x,y,comp,req_comp, ri); -} - -static int stbi__png_test(stbi__context *s) -{ - int r; - r = stbi__check_png_header(s); - stbi__rewind(s); - return r; -} - -static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) -{ - if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { - stbi__rewind( p->s ); - return 0; - } - if (x) *x = p->s->img_x; - if (y) *y = p->s->img_y; - if (comp) *comp = p->s->img_n; - return 1; -} - -static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) -{ - stbi__png p; - p.s = s; - return stbi__png_info_raw(&p, x, y, comp); -} - -static int stbi__png_is16(stbi__context *s) -{ - stbi__png p; - p.s = s; - if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) - return 0; - if (p.depth != 16) { - stbi__rewind(p.s); - return 0; - } - return 1; -} -#endif - -// Microsoft/Windows BMP image - -#ifndef STBI_NO_BMP -static int stbi__bmp_test_raw(stbi__context *s) -{ - int r; - int sz; - if (stbi__get8(s) != 'B') return 0; - if (stbi__get8(s) != 'M') return 0; - stbi__get32le(s); // discard filesize - stbi__get16le(s); // discard reserved - stbi__get16le(s); // discard reserved - stbi__get32le(s); // discard data offset - sz = stbi__get32le(s); - r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); - return r; -} - -static int stbi__bmp_test(stbi__context *s) -{ - int r = stbi__bmp_test_raw(s); - stbi__rewind(s); - return r; -} - - -// returns 0..31 for the highest set bit -static int stbi__high_bit(unsigned int z) -{ - int n=0; - if (z == 0) return -1; - if (z >= 0x10000) { n += 16; z >>= 16; } - if (z >= 0x00100) { n += 8; z >>= 8; } - if (z >= 0x00010) { n += 4; z >>= 4; } - if (z >= 0x00004) { n += 2; z >>= 2; } - if (z >= 0x00002) { n += 1;/* >>= 1;*/ } - return n; -} - -static int stbi__bitcount(unsigned int a) -{ - a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 - a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 - a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits - a = (a + (a >> 8)); // max 16 per 8 bits - a = (a + (a >> 16)); // max 32 per 8 bits - return a & 0xff; -} - -// extract an arbitrarily-aligned N-bit value (N=bits) -// from v, and then make it 8-bits long and fractionally -// extend it to full full range. -static int stbi__shiftsigned(unsigned int v, int shift, int bits) -{ - static unsigned int mul_table[9] = { - 0, - 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, - 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, - }; - static unsigned int shift_table[9] = { - 0, 0,0,1,0,2,4,6,0, - }; - if (shift < 0) - v <<= -shift; - else - v >>= shift; - STBI_ASSERT(v < 256); - v >>= (8-bits); - STBI_ASSERT(bits >= 0 && bits <= 8); - return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; -} - -typedef struct -{ - int bpp, offset, hsz; - unsigned int mr,mg,mb,ma, all_a; - int extra_read; -} stbi__bmp_data; - -static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress) -{ - // BI_BITFIELDS specifies masks explicitly, don't override - if (compress == 3) - return 1; - - if (compress == 0) { - if (info->bpp == 16) { - info->mr = 31u << 10; - info->mg = 31u << 5; - info->mb = 31u << 0; - } else if (info->bpp == 32) { - info->mr = 0xffu << 16; - info->mg = 0xffu << 8; - info->mb = 0xffu << 0; - info->ma = 0xffu << 24; - info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 - } else { - // otherwise, use defaults, which is all-0 - info->mr = info->mg = info->mb = info->ma = 0; - } - return 1; - } - return 0; // error -} - -static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) -{ - int hsz; - if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); - stbi__get32le(s); // discard filesize - stbi__get16le(s); // discard reserved - stbi__get16le(s); // discard reserved - info->offset = stbi__get32le(s); - info->hsz = hsz = stbi__get32le(s); - info->mr = info->mg = info->mb = info->ma = 0; - info->extra_read = 14; - - if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP"); - - if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); - if (hsz == 12) { - s->img_x = stbi__get16le(s); - s->img_y = stbi__get16le(s); - } else { - s->img_x = stbi__get32le(s); - s->img_y = stbi__get32le(s); - } - if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); - info->bpp = stbi__get16le(s); - if (hsz != 12) { - int compress = stbi__get32le(s); - if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); - if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes - if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel - stbi__get32le(s); // discard sizeof - stbi__get32le(s); // discard hres - stbi__get32le(s); // discard vres - stbi__get32le(s); // discard colorsused - stbi__get32le(s); // discard max important - if (hsz == 40 || hsz == 56) { - if (hsz == 56) { - stbi__get32le(s); - stbi__get32le(s); - stbi__get32le(s); - stbi__get32le(s); - } - if (info->bpp == 16 || info->bpp == 32) { - if (compress == 0) { - stbi__bmp_set_mask_defaults(info, compress); - } else if (compress == 3) { - info->mr = stbi__get32le(s); - info->mg = stbi__get32le(s); - info->mb = stbi__get32le(s); - info->extra_read += 12; - // not documented, but generated by photoshop and handled by mspaint - if (info->mr == info->mg && info->mg == info->mb) { - // ?!?!? - return stbi__errpuc("bad BMP", "bad BMP"); - } - } else - return stbi__errpuc("bad BMP", "bad BMP"); - } - } else { - // V4/V5 header - int i; - if (hsz != 108 && hsz != 124) - return stbi__errpuc("bad BMP", "bad BMP"); - info->mr = stbi__get32le(s); - info->mg = stbi__get32le(s); - info->mb = stbi__get32le(s); - info->ma = stbi__get32le(s); - if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs - stbi__bmp_set_mask_defaults(info, compress); - stbi__get32le(s); // discard color space - for (i=0; i < 12; ++i) - stbi__get32le(s); // discard color space parameters - if (hsz == 124) { - stbi__get32le(s); // discard rendering intent - stbi__get32le(s); // discard offset of profile data - stbi__get32le(s); // discard size of profile data - stbi__get32le(s); // discard reserved - } - } - } - return (void *) 1; -} - - -static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) -{ - stbi_uc *out; - unsigned int mr=0,mg=0,mb=0,ma=0, all_a; - stbi_uc pal[256][4]; - int psize=0,i,j,width; - int flip_vertically, pad, target; - stbi__bmp_data info; - STBI_NOTUSED(ri); - - info.all_a = 255; - if (stbi__bmp_parse_header(s, &info) == NULL) - return NULL; // error code already set - - flip_vertically = ((int) s->img_y) > 0; - s->img_y = abs((int) s->img_y); - - if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); - if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); - - mr = info.mr; - mg = info.mg; - mb = info.mb; - ma = info.ma; - all_a = info.all_a; - - if (info.hsz == 12) { - if (info.bpp < 24) - psize = (info.offset - info.extra_read - 24) / 3; - } else { - if (info.bpp < 16) - psize = (info.offset - info.extra_read - info.hsz) >> 2; - } - if (psize == 0) { - // accept some number of extra bytes after the header, but if the offset points either to before - // the header ends or implies a large amount of extra data, reject the file as malformed - int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original); - int header_limit = 1024; // max we actually read is below 256 bytes currently. - int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size. - if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) { - return stbi__errpuc("bad header", "Corrupt BMP"); - } - // we established that bytes_read_so_far is positive and sensible. - // the first half of this test rejects offsets that are either too small positives, or - // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn - // ensures the number computed in the second half of the test can't overflow. - if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) { - return stbi__errpuc("bad offset", "Corrupt BMP"); - } else { - stbi__skip(s, info.offset - bytes_read_so_far); - } - } - - if (info.bpp == 24 && ma == 0xff000000) - s->img_n = 3; - else - s->img_n = ma ? 4 : 3; - if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 - target = req_comp; - else - target = s->img_n; // if they want monochrome, we'll post-convert - - // sanity-check size - if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) - return stbi__errpuc("too large", "Corrupt BMP"); - - out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); - if (!out) return stbi__errpuc("outofmem", "Out of memory"); - if (info.bpp < 16) { - int z=0; - if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } - for (i=0; i < psize; ++i) { - pal[i][2] = stbi__get8(s); - pal[i][1] = stbi__get8(s); - pal[i][0] = stbi__get8(s); - if (info.hsz != 12) stbi__get8(s); - pal[i][3] = 255; - } - stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); - if (info.bpp == 1) width = (s->img_x + 7) >> 3; - else if (info.bpp == 4) width = (s->img_x + 1) >> 1; - else if (info.bpp == 8) width = s->img_x; - else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } - pad = (-width)&3; - if (info.bpp == 1) { - for (j=0; j < (int) s->img_y; ++j) { - int bit_offset = 7, v = stbi__get8(s); - for (i=0; i < (int) s->img_x; ++i) { - int color = (v>>bit_offset)&0x1; - out[z++] = pal[color][0]; - out[z++] = pal[color][1]; - out[z++] = pal[color][2]; - if (target == 4) out[z++] = 255; - if (i+1 == (int) s->img_x) break; - if((--bit_offset) < 0) { - bit_offset = 7; - v = stbi__get8(s); - } - } - stbi__skip(s, pad); - } - } else { - for (j=0; j < (int) s->img_y; ++j) { - for (i=0; i < (int) s->img_x; i += 2) { - int v=stbi__get8(s),v2=0; - if (info.bpp == 4) { - v2 = v & 15; - v >>= 4; - } - out[z++] = pal[v][0]; - out[z++] = pal[v][1]; - out[z++] = pal[v][2]; - if (target == 4) out[z++] = 255; - if (i+1 == (int) s->img_x) break; - v = (info.bpp == 8) ? stbi__get8(s) : v2; - out[z++] = pal[v][0]; - out[z++] = pal[v][1]; - out[z++] = pal[v][2]; - if (target == 4) out[z++] = 255; - } - stbi__skip(s, pad); - } - } - } else { - int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; - int z = 0; - int easy=0; - stbi__skip(s, info.offset - info.extra_read - info.hsz); - if (info.bpp == 24) width = 3 * s->img_x; - else if (info.bpp == 16) width = 2*s->img_x; - else /* bpp = 32 and pad = 0 */ width=0; - pad = (-width) & 3; - if (info.bpp == 24) { - easy = 1; - } else if (info.bpp == 32) { - if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) - easy = 2; - } - if (!easy) { - if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } - // right shift amt to put high bit in position #7 - rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); - gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); - bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); - ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); - if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } - } - for (j=0; j < (int) s->img_y; ++j) { - if (easy) { - for (i=0; i < (int) s->img_x; ++i) { - unsigned char a; - out[z+2] = stbi__get8(s); - out[z+1] = stbi__get8(s); - out[z+0] = stbi__get8(s); - z += 3; - a = (easy == 2 ? stbi__get8(s) : 255); - all_a |= a; - if (target == 4) out[z++] = a; - } - } else { - int bpp = info.bpp; - for (i=0; i < (int) s->img_x; ++i) { - stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); - unsigned int a; - out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); - out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); - out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); - a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); - all_a |= a; - if (target == 4) out[z++] = STBI__BYTECAST(a); - } - } - stbi__skip(s, pad); - } - } - - // if alpha channel is all 0s, replace with all 255s - if (target == 4 && all_a == 0) - for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) - out[i] = 255; - - if (flip_vertically) { - stbi_uc t; - for (j=0; j < (int) s->img_y>>1; ++j) { - stbi_uc *p1 = out + j *s->img_x*target; - stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; - for (i=0; i < (int) s->img_x*target; ++i) { - t = p1[i]; p1[i] = p2[i]; p2[i] = t; - } - } - } - - if (req_comp && req_comp != target) { - out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); - if (out == NULL) return out; // stbi__convert_format frees input on failure - } - - *x = s->img_x; - *y = s->img_y; - if (comp) *comp = s->img_n; - return out; -} -#endif - -// Targa Truevision - TGA -// by Jonathan Dummer -#ifndef STBI_NO_TGA -// returns STBI_rgb or whatever, 0 on error -static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) -{ - // only RGB or RGBA (incl. 16bit) or grey allowed - if (is_rgb16) *is_rgb16 = 0; - switch(bits_per_pixel) { - case 8: return STBI_grey; - case 16: if(is_grey) return STBI_grey_alpha; - // fallthrough - case 15: if(is_rgb16) *is_rgb16 = 1; - return STBI_rgb; - case 24: // fallthrough - case 32: return bits_per_pixel/8; - default: return 0; - } -} - -static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) -{ - int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; - int sz, tga_colormap_type; - stbi__get8(s); // discard Offset - tga_colormap_type = stbi__get8(s); // colormap type - if( tga_colormap_type > 1 ) { - stbi__rewind(s); - return 0; // only RGB or indexed allowed - } - tga_image_type = stbi__get8(s); // image type - if ( tga_colormap_type == 1 ) { // colormapped (paletted) image - if (tga_image_type != 1 && tga_image_type != 9) { - stbi__rewind(s); - return 0; - } - stbi__skip(s,4); // skip index of first colormap entry and number of entries - sz = stbi__get8(s); // check bits per palette color entry - if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { - stbi__rewind(s); - return 0; - } - stbi__skip(s,4); // skip image x and y origin - tga_colormap_bpp = sz; - } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE - if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { - stbi__rewind(s); - return 0; // only RGB or grey allowed, +/- RLE - } - stbi__skip(s,9); // skip colormap specification and image x/y origin - tga_colormap_bpp = 0; - } - tga_w = stbi__get16le(s); - if( tga_w < 1 ) { - stbi__rewind(s); - return 0; // test width - } - tga_h = stbi__get16le(s); - if( tga_h < 1 ) { - stbi__rewind(s); - return 0; // test height - } - tga_bits_per_pixel = stbi__get8(s); // bits per pixel - stbi__get8(s); // ignore alpha bits - if (tga_colormap_bpp != 0) { - if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { - // when using a colormap, tga_bits_per_pixel is the size of the indexes - // I don't think anything but 8 or 16bit indexes makes sense - stbi__rewind(s); - return 0; - } - tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); - } else { - tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); - } - if(!tga_comp) { - stbi__rewind(s); - return 0; - } - if (x) *x = tga_w; - if (y) *y = tga_h; - if (comp) *comp = tga_comp; - return 1; // seems to have passed everything -} - -static int stbi__tga_test(stbi__context *s) -{ - int res = 0; - int sz, tga_color_type; - stbi__get8(s); // discard Offset - tga_color_type = stbi__get8(s); // color type - if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed - sz = stbi__get8(s); // image type - if ( tga_color_type == 1 ) { // colormapped (paletted) image - if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 - stbi__skip(s,4); // skip index of first colormap entry and number of entries - sz = stbi__get8(s); // check bits per palette color entry - if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; - stbi__skip(s,4); // skip image x and y origin - } else { // "normal" image w/o colormap - if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE - stbi__skip(s,9); // skip colormap specification and image x/y origin - } - if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width - if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height - sz = stbi__get8(s); // bits per pixel - if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index - if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; - - res = 1; // if we got this far, everything's good and we can return 1 instead of 0 - -errorEnd: - stbi__rewind(s); - return res; -} - -// read 16bit value and convert to 24bit RGB -static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) -{ - stbi__uint16 px = (stbi__uint16)stbi__get16le(s); - stbi__uint16 fiveBitMask = 31; - // we have 3 channels with 5bits each - int r = (px >> 10) & fiveBitMask; - int g = (px >> 5) & fiveBitMask; - int b = px & fiveBitMask; - // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later - out[0] = (stbi_uc)((r * 255)/31); - out[1] = (stbi_uc)((g * 255)/31); - out[2] = (stbi_uc)((b * 255)/31); - - // some people claim that the most significant bit might be used for alpha - // (possibly if an alpha-bit is set in the "image descriptor byte") - // but that only made 16bit test images completely translucent.. - // so let's treat all 15 and 16bit TGAs as RGB with no alpha. -} - -static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) -{ - // read in the TGA header stuff - int tga_offset = stbi__get8(s); - int tga_indexed = stbi__get8(s); - int tga_image_type = stbi__get8(s); - int tga_is_RLE = 0; - int tga_palette_start = stbi__get16le(s); - int tga_palette_len = stbi__get16le(s); - int tga_palette_bits = stbi__get8(s); - int tga_x_origin = stbi__get16le(s); - int tga_y_origin = stbi__get16le(s); - int tga_width = stbi__get16le(s); - int tga_height = stbi__get16le(s); - int tga_bits_per_pixel = stbi__get8(s); - int tga_comp, tga_rgb16=0; - int tga_inverted = stbi__get8(s); - // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) - // image data - unsigned char *tga_data; - unsigned char *tga_palette = NULL; - int i, j; - unsigned char raw_data[4] = {0}; - int RLE_count = 0; - int RLE_repeating = 0; - int read_next_pixel = 1; - STBI_NOTUSED(ri); - STBI_NOTUSED(tga_x_origin); // @TODO - STBI_NOTUSED(tga_y_origin); // @TODO - - if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); - if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); - - // do a tiny bit of precessing - if ( tga_image_type >= 8 ) - { - tga_image_type -= 8; - tga_is_RLE = 1; - } - tga_inverted = 1 - ((tga_inverted >> 5) & 1); - - // If I'm paletted, then I'll use the number of bits from the palette - if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); - else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); - - if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency - return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); - - // tga info - *x = tga_width; - *y = tga_height; - if (comp) *comp = tga_comp; - - if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) - return stbi__errpuc("too large", "Corrupt TGA"); - - tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); - if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); - - // skip to the data's starting position (offset usually = 0) - stbi__skip(s, tga_offset ); - - if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { - for (i=0; i < tga_height; ++i) { - int row = tga_inverted ? tga_height -i - 1 : i; - stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; - stbi__getn(s, tga_row, tga_width * tga_comp); - } - } else { - // do I need to load a palette? - if ( tga_indexed) - { - if (tga_palette_len == 0) { /* you have to have at least one entry! */ - STBI_FREE(tga_data); - return stbi__errpuc("bad palette", "Corrupt TGA"); - } - - // any data to skip? (offset usually = 0) - stbi__skip(s, tga_palette_start ); - // load the palette - tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); - if (!tga_palette) { - STBI_FREE(tga_data); - return stbi__errpuc("outofmem", "Out of memory"); - } - if (tga_rgb16) { - stbi_uc *pal_entry = tga_palette; - STBI_ASSERT(tga_comp == STBI_rgb); - for (i=0; i < tga_palette_len; ++i) { - stbi__tga_read_rgb16(s, pal_entry); - pal_entry += tga_comp; - } - } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { - STBI_FREE(tga_data); - STBI_FREE(tga_palette); - return stbi__errpuc("bad palette", "Corrupt TGA"); - } - } - // load the data - for (i=0; i < tga_width * tga_height; ++i) - { - // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? - if ( tga_is_RLE ) - { - if ( RLE_count == 0 ) - { - // yep, get the next byte as a RLE command - int RLE_cmd = stbi__get8(s); - RLE_count = 1 + (RLE_cmd & 127); - RLE_repeating = RLE_cmd >> 7; - read_next_pixel = 1; - } else if ( !RLE_repeating ) - { - read_next_pixel = 1; - } - } else - { - read_next_pixel = 1; - } - // OK, if I need to read a pixel, do it now - if ( read_next_pixel ) - { - // load however much data we did have - if ( tga_indexed ) - { - // read in index, then perform the lookup - int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); - if ( pal_idx >= tga_palette_len ) { - // invalid index - pal_idx = 0; - } - pal_idx *= tga_comp; - for (j = 0; j < tga_comp; ++j) { - raw_data[j] = tga_palette[pal_idx+j]; - } - } else if(tga_rgb16) { - STBI_ASSERT(tga_comp == STBI_rgb); - stbi__tga_read_rgb16(s, raw_data); - } else { - // read in the data raw - for (j = 0; j < tga_comp; ++j) { - raw_data[j] = stbi__get8(s); - } - } - // clear the reading flag for the next pixel - read_next_pixel = 0; - } // end of reading a pixel - - // copy data - for (j = 0; j < tga_comp; ++j) - tga_data[i*tga_comp+j] = raw_data[j]; - - // in case we're in RLE mode, keep counting down - --RLE_count; - } - // do I need to invert the image? - if ( tga_inverted ) - { - for (j = 0; j*2 < tga_height; ++j) - { - int index1 = j * tga_width * tga_comp; - int index2 = (tga_height - 1 - j) * tga_width * tga_comp; - for (i = tga_width * tga_comp; i > 0; --i) - { - unsigned char temp = tga_data[index1]; - tga_data[index1] = tga_data[index2]; - tga_data[index2] = temp; - ++index1; - ++index2; - } - } - } - // clear my palette, if I had one - if ( tga_palette != NULL ) - { - STBI_FREE( tga_palette ); - } - } - - // swap RGB - if the source data was RGB16, it already is in the right order - if (tga_comp >= 3 && !tga_rgb16) - { - unsigned char* tga_pixel = tga_data; - for (i=0; i < tga_width * tga_height; ++i) - { - unsigned char temp = tga_pixel[0]; - tga_pixel[0] = tga_pixel[2]; - tga_pixel[2] = temp; - tga_pixel += tga_comp; - } - } - - // convert to target component count - if (req_comp && req_comp != tga_comp) - tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); - - // the things I do to get rid of an error message, and yet keep - // Microsoft's C compilers happy... [8^( - tga_palette_start = tga_palette_len = tga_palette_bits = - tga_x_origin = tga_y_origin = 0; - STBI_NOTUSED(tga_palette_start); - // OK, done - return tga_data; -} -#endif - -// ************************************************************************************************* -// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB - -#ifndef STBI_NO_PSD -static int stbi__psd_test(stbi__context *s) -{ - int r = (stbi__get32be(s) == 0x38425053); - stbi__rewind(s); - return r; -} - -static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) -{ - int count, nleft, len; - - count = 0; - while ((nleft = pixelCount - count) > 0) { - len = stbi__get8(s); - if (len == 128) { - // No-op. - } else if (len < 128) { - // Copy next len+1 bytes literally. - len++; - if (len > nleft) return 0; // corrupt data - count += len; - while (len) { - *p = stbi__get8(s); - p += 4; - len--; - } - } else if (len > 128) { - stbi_uc val; - // Next -len+1 bytes in the dest are replicated from next source byte. - // (Interpret len as a negative 8-bit int.) - len = 257 - len; - if (len > nleft) return 0; // corrupt data - val = stbi__get8(s); - count += len; - while (len) { - *p = val; - p += 4; - len--; - } - } - } - - return 1; -} - -static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) -{ - int pixelCount; - int channelCount, compression; - int channel, i; - int bitdepth; - int w,h; - stbi_uc *out; - STBI_NOTUSED(ri); - - // Check identifier - if (stbi__get32be(s) != 0x38425053) // "8BPS" - return stbi__errpuc("not PSD", "Corrupt PSD image"); - - // Check file type version. - if (stbi__get16be(s) != 1) - return stbi__errpuc("wrong version", "Unsupported version of PSD image"); - - // Skip 6 reserved bytes. - stbi__skip(s, 6 ); - - // Read the number of channels (R, G, B, A, etc). - channelCount = stbi__get16be(s); - if (channelCount < 0 || channelCount > 16) - return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); - - // Read the rows and columns of the image. - h = stbi__get32be(s); - w = stbi__get32be(s); - - if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); - if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); - - // Make sure the depth is 8 bits. - bitdepth = stbi__get16be(s); - if (bitdepth != 8 && bitdepth != 16) - return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); - - // Make sure the color mode is RGB. - // Valid options are: - // 0: Bitmap - // 1: Grayscale - // 2: Indexed color - // 3: RGB color - // 4: CMYK color - // 7: Multichannel - // 8: Duotone - // 9: Lab color - if (stbi__get16be(s) != 3) - return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); - - // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) - stbi__skip(s,stbi__get32be(s) ); - - // Skip the image resources. (resolution, pen tool paths, etc) - stbi__skip(s, stbi__get32be(s) ); - - // Skip the reserved data. - stbi__skip(s, stbi__get32be(s) ); - - // Find out if the data is compressed. - // Known values: - // 0: no compression - // 1: RLE compressed - compression = stbi__get16be(s); - if (compression > 1) - return stbi__errpuc("bad compression", "PSD has an unknown compression format"); - - // Check size - if (!stbi__mad3sizes_valid(4, w, h, 0)) - return stbi__errpuc("too large", "Corrupt PSD"); - - // Create the destination image. - - if (!compression && bitdepth == 16 && bpc == 16) { - out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); - ri->bits_per_channel = 16; - } else - out = (stbi_uc *) stbi__malloc(4 * w*h); - - if (!out) return stbi__errpuc("outofmem", "Out of memory"); - pixelCount = w*h; - - // Initialize the data to zero. - //memset( out, 0, pixelCount * 4 ); - - // Finally, the image data. - if (compression) { - // RLE as used by .PSD and .TIFF - // Loop until you get the number of unpacked bytes you are expecting: - // Read the next source byte into n. - // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. - // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. - // Else if n is 128, noop. - // Endloop - - // The RLE-compressed data is preceded by a 2-byte data count for each row in the data, - // which we're going to just skip. - stbi__skip(s, h * channelCount * 2 ); - - // Read the RLE data by channel. - for (channel = 0; channel < 4; channel++) { - stbi_uc *p; - - p = out+channel; - if (channel >= channelCount) { - // Fill this channel with default data. - for (i = 0; i < pixelCount; i++, p += 4) - *p = (channel == 3 ? 255 : 0); - } else { - // Read the RLE data. - if (!stbi__psd_decode_rle(s, p, pixelCount)) { - STBI_FREE(out); - return stbi__errpuc("corrupt", "bad RLE data"); - } - } - } - - } else { - // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) - // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. - - // Read the data by channel. - for (channel = 0; channel < 4; channel++) { - if (channel >= channelCount) { - // Fill this channel with default data. - if (bitdepth == 16 && bpc == 16) { - stbi__uint16 *q = ((stbi__uint16 *) out) + channel; - stbi__uint16 val = channel == 3 ? 65535 : 0; - for (i = 0; i < pixelCount; i++, q += 4) - *q = val; - } else { - stbi_uc *p = out+channel; - stbi_uc val = channel == 3 ? 255 : 0; - for (i = 0; i < pixelCount; i++, p += 4) - *p = val; - } - } else { - if (ri->bits_per_channel == 16) { // output bpc - stbi__uint16 *q = ((stbi__uint16 *) out) + channel; - for (i = 0; i < pixelCount; i++, q += 4) - *q = (stbi__uint16) stbi__get16be(s); - } else { - stbi_uc *p = out+channel; - if (bitdepth == 16) { // input bpc - for (i = 0; i < pixelCount; i++, p += 4) - *p = (stbi_uc) (stbi__get16be(s) >> 8); - } else { - for (i = 0; i < pixelCount; i++, p += 4) - *p = stbi__get8(s); - } - } - } - } - } - - // remove weird white matte from PSD - if (channelCount >= 4) { - if (ri->bits_per_channel == 16) { - for (i=0; i < w*h; ++i) { - stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; - if (pixel[3] != 0 && pixel[3] != 65535) { - float a = pixel[3] / 65535.0f; - float ra = 1.0f / a; - float inv_a = 65535.0f * (1 - ra); - pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); - pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); - pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); - } - } - } else { - for (i=0; i < w*h; ++i) { - unsigned char *pixel = out + 4*i; - if (pixel[3] != 0 && pixel[3] != 255) { - float a = pixel[3] / 255.0f; - float ra = 1.0f / a; - float inv_a = 255.0f * (1 - ra); - pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); - pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); - pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); - } - } - } - } - - // convert to desired output format - if (req_comp && req_comp != 4) { - if (ri->bits_per_channel == 16) - out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); - else - out = stbi__convert_format(out, 4, req_comp, w, h); - if (out == NULL) return out; // stbi__convert_format frees input on failure - } - - if (comp) *comp = 4; - *y = h; - *x = w; - - return out; -} -#endif - -// ************************************************************************************************* -// Softimage PIC loader -// by Tom Seddon -// -// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format -// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ - -#ifndef STBI_NO_PIC -static int stbi__pic_is4(stbi__context *s,const char *str) -{ - int i; - for (i=0; i<4; ++i) - if (stbi__get8(s) != (stbi_uc)str[i]) - return 0; - - return 1; -} - -static int stbi__pic_test_core(stbi__context *s) -{ - int i; - - if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) - return 0; - - for(i=0;i<84;++i) - stbi__get8(s); - - if (!stbi__pic_is4(s,"PICT")) - return 0; - - return 1; -} - -typedef struct -{ - stbi_uc size,type,channel; -} stbi__pic_packet; - -static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) -{ - int mask=0x80, i; - - for (i=0; i<4; ++i, mask>>=1) { - if (channel & mask) { - if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); - dest[i]=stbi__get8(s); - } - } - - return dest; -} - -static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) -{ - int mask=0x80,i; - - for (i=0;i<4; ++i, mask>>=1) - if (channel&mask) - dest[i]=src[i]; -} - -static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) -{ - int act_comp=0,num_packets=0,y,chained; - stbi__pic_packet packets[10]; - - // this will (should...) cater for even some bizarre stuff like having data - // for the same channel in multiple packets. - do { - stbi__pic_packet *packet; - - if (num_packets==sizeof(packets)/sizeof(packets[0])) - return stbi__errpuc("bad format","too many packets"); - - packet = &packets[num_packets++]; - - chained = stbi__get8(s); - packet->size = stbi__get8(s); - packet->type = stbi__get8(s); - packet->channel = stbi__get8(s); - - act_comp |= packet->channel; - - if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); - if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); - } while (chained); - - *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? - - for(y=0; ytype) { - default: - return stbi__errpuc("bad format","packet has bad compression type"); - - case 0: {//uncompressed - int x; - - for(x=0;xchannel,dest)) - return 0; - break; - } - - case 1://Pure RLE - { - int left=width, i; - - while (left>0) { - stbi_uc count,value[4]; - - count=stbi__get8(s); - if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); - - if (count > left) - count = (stbi_uc) left; - - if (!stbi__readval(s,packet->channel,value)) return 0; - - for(i=0; ichannel,dest,value); - left -= count; - } - } - break; - - case 2: {//Mixed RLE - int left=width; - while (left>0) { - int count = stbi__get8(s), i; - if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); - - if (count >= 128) { // Repeated - stbi_uc value[4]; - - if (count==128) - count = stbi__get16be(s); - else - count -= 127; - if (count > left) - return stbi__errpuc("bad file","scanline overrun"); - - if (!stbi__readval(s,packet->channel,value)) - return 0; - - for(i=0;ichannel,dest,value); - } else { // Raw - ++count; - if (count>left) return stbi__errpuc("bad file","scanline overrun"); - - for(i=0;ichannel,dest)) - return 0; - } - left-=count; - } - break; - } - } - } - } - - return result; -} - -static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) -{ - stbi_uc *result; - int i, x,y, internal_comp; - STBI_NOTUSED(ri); - - if (!comp) comp = &internal_comp; - - for (i=0; i<92; ++i) - stbi__get8(s); - - x = stbi__get16be(s); - y = stbi__get16be(s); - - if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); - if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); - - if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); - if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); - - stbi__get32be(s); //skip `ratio' - stbi__get16be(s); //skip `fields' - stbi__get16be(s); //skip `pad' - - // intermediate buffer is RGBA - result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); - if (!result) return stbi__errpuc("outofmem", "Out of memory"); - memset(result, 0xff, x*y*4); - - if (!stbi__pic_load_core(s,x,y,comp, result)) { - STBI_FREE(result); - result=0; - } - *px = x; - *py = y; - if (req_comp == 0) req_comp = *comp; - result=stbi__convert_format(result,4,req_comp,x,y); - - return result; -} - -static int stbi__pic_test(stbi__context *s) -{ - int r = stbi__pic_test_core(s); - stbi__rewind(s); - return r; -} -#endif - -// ************************************************************************************************* -// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb - -#ifndef STBI_NO_GIF -typedef struct -{ - stbi__int16 prefix; - stbi_uc first; - stbi_uc suffix; -} stbi__gif_lzw; - -typedef struct -{ - int w,h; - stbi_uc *out; // output buffer (always 4 components) - stbi_uc *background; // The current "background" as far as a gif is concerned - stbi_uc *history; - int flags, bgindex, ratio, transparent, eflags; - stbi_uc pal[256][4]; - stbi_uc lpal[256][4]; - stbi__gif_lzw codes[8192]; - stbi_uc *color_table; - int parse, step; - int lflags; - int start_x, start_y; - int max_x, max_y; - int cur_x, cur_y; - int line_size; - int delay; -} stbi__gif; - -static int stbi__gif_test_raw(stbi__context *s) -{ - int sz; - if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; - sz = stbi__get8(s); - if (sz != '9' && sz != '7') return 0; - if (stbi__get8(s) != 'a') return 0; - return 1; -} - -static int stbi__gif_test(stbi__context *s) -{ - int r = stbi__gif_test_raw(s); - stbi__rewind(s); - return r; -} - -static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) -{ - int i; - for (i=0; i < num_entries; ++i) { - pal[i][2] = stbi__get8(s); - pal[i][1] = stbi__get8(s); - pal[i][0] = stbi__get8(s); - pal[i][3] = transp == i ? 0 : 255; - } -} - -static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) -{ - stbi_uc version; - if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') - return stbi__err("not GIF", "Corrupt GIF"); - - version = stbi__get8(s); - if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); - if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); - - stbi__g_failure_reason = ""; - g->w = stbi__get16le(s); - g->h = stbi__get16le(s); - g->flags = stbi__get8(s); - g->bgindex = stbi__get8(s); - g->ratio = stbi__get8(s); - g->transparent = -1; - - if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); - if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); - - if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments - - if (is_info) return 1; - - if (g->flags & 0x80) - stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); - - return 1; -} - -static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) -{ - stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); - if (!g) return stbi__err("outofmem", "Out of memory"); - if (!stbi__gif_header(s, g, comp, 1)) { - STBI_FREE(g); - stbi__rewind( s ); - return 0; - } - if (x) *x = g->w; - if (y) *y = g->h; - STBI_FREE(g); - return 1; -} - -static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) -{ - stbi_uc *p, *c; - int idx; - - // recurse to decode the prefixes, since the linked-list is backwards, - // and working backwards through an interleaved image would be nasty - if (g->codes[code].prefix >= 0) - stbi__out_gif_code(g, g->codes[code].prefix); - - if (g->cur_y >= g->max_y) return; - - idx = g->cur_x + g->cur_y; - p = &g->out[idx]; - g->history[idx / 4] = 1; - - c = &g->color_table[g->codes[code].suffix * 4]; - if (c[3] > 128) { // don't render transparent pixels; - p[0] = c[2]; - p[1] = c[1]; - p[2] = c[0]; - p[3] = c[3]; - } - g->cur_x += 4; - - if (g->cur_x >= g->max_x) { - g->cur_x = g->start_x; - g->cur_y += g->step; - - while (g->cur_y >= g->max_y && g->parse > 0) { - g->step = (1 << g->parse) * g->line_size; - g->cur_y = g->start_y + (g->step >> 1); - --g->parse; - } - } -} - -static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) -{ - stbi_uc lzw_cs; - stbi__int32 len, init_code; - stbi__uint32 first; - stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; - stbi__gif_lzw *p; - - lzw_cs = stbi__get8(s); - if (lzw_cs > 12) return NULL; - clear = 1 << lzw_cs; - first = 1; - codesize = lzw_cs + 1; - codemask = (1 << codesize) - 1; - bits = 0; - valid_bits = 0; - for (init_code = 0; init_code < clear; init_code++) { - g->codes[init_code].prefix = -1; - g->codes[init_code].first = (stbi_uc) init_code; - g->codes[init_code].suffix = (stbi_uc) init_code; - } - - // support no starting clear code - avail = clear+2; - oldcode = -1; - - len = 0; - for(;;) { - if (valid_bits < codesize) { - if (len == 0) { - len = stbi__get8(s); // start new block - if (len == 0) - return g->out; - } - --len; - bits |= (stbi__int32) stbi__get8(s) << valid_bits; - valid_bits += 8; - } else { - stbi__int32 code = bits & codemask; - bits >>= codesize; - valid_bits -= codesize; - // @OPTIMIZE: is there some way we can accelerate the non-clear path? - if (code == clear) { // clear code - codesize = lzw_cs + 1; - codemask = (1 << codesize) - 1; - avail = clear + 2; - oldcode = -1; - first = 0; - } else if (code == clear + 1) { // end of stream code - stbi__skip(s, len); - while ((len = stbi__get8(s)) > 0) - stbi__skip(s,len); - return g->out; - } else if (code <= avail) { - if (first) { - return stbi__errpuc("no clear code", "Corrupt GIF"); - } - - if (oldcode >= 0) { - p = &g->codes[avail++]; - if (avail > 8192) { - return stbi__errpuc("too many codes", "Corrupt GIF"); - } - - p->prefix = (stbi__int16) oldcode; - p->first = g->codes[oldcode].first; - p->suffix = (code == avail) ? p->first : g->codes[code].first; - } else if (code == avail) - return stbi__errpuc("illegal code in raster", "Corrupt GIF"); - - stbi__out_gif_code(g, (stbi__uint16) code); - - if ((avail & codemask) == 0 && avail <= 0x0FFF) { - codesize++; - codemask = (1 << codesize) - 1; - } - - oldcode = code; - } else { - return stbi__errpuc("illegal code in raster", "Corrupt GIF"); - } - } - } -} - -// this function is designed to support animated gifs, although stb_image doesn't support it -// two back is the image from two frames ago, used for a very specific disposal format -static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) -{ - int dispose; - int first_frame; - int pi; - int pcount; - STBI_NOTUSED(req_comp); - - // on first frame, any non-written pixels get the background colour (non-transparent) - first_frame = 0; - if (g->out == 0) { - if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header - if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) - return stbi__errpuc("too large", "GIF image is too large"); - pcount = g->w * g->h; - g->out = (stbi_uc *) stbi__malloc(4 * pcount); - g->background = (stbi_uc *) stbi__malloc(4 * pcount); - g->history = (stbi_uc *) stbi__malloc(pcount); - if (!g->out || !g->background || !g->history) - return stbi__errpuc("outofmem", "Out of memory"); - - // image is treated as "transparent" at the start - ie, nothing overwrites the current background; - // background colour is only used for pixels that are not rendered first frame, after that "background" - // color refers to the color that was there the previous frame. - memset(g->out, 0x00, 4 * pcount); - memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) - memset(g->history, 0x00, pcount); // pixels that were affected previous frame - first_frame = 1; - } else { - // second frame - how do we dispose of the previous one? - dispose = (g->eflags & 0x1C) >> 2; - pcount = g->w * g->h; - - if ((dispose == 3) && (two_back == 0)) { - dispose = 2; // if I don't have an image to revert back to, default to the old background - } - - if (dispose == 3) { // use previous graphic - for (pi = 0; pi < pcount; ++pi) { - if (g->history[pi]) { - memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); - } - } - } else if (dispose == 2) { - // restore what was changed last frame to background before that frame; - for (pi = 0; pi < pcount; ++pi) { - if (g->history[pi]) { - memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); - } - } - } else { - // This is a non-disposal case eithe way, so just - // leave the pixels as is, and they will become the new background - // 1: do not dispose - // 0: not specified. - } - - // background is what out is after the undoing of the previou frame; - memcpy( g->background, g->out, 4 * g->w * g->h ); - } - - // clear my history; - memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame - - for (;;) { - int tag = stbi__get8(s); - switch (tag) { - case 0x2C: /* Image Descriptor */ - { - stbi__int32 x, y, w, h; - stbi_uc *o; - - x = stbi__get16le(s); - y = stbi__get16le(s); - w = stbi__get16le(s); - h = stbi__get16le(s); - if (((x + w) > (g->w)) || ((y + h) > (g->h))) - return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); - - g->line_size = g->w * 4; - g->start_x = x * 4; - g->start_y = y * g->line_size; - g->max_x = g->start_x + w * 4; - g->max_y = g->start_y + h * g->line_size; - g->cur_x = g->start_x; - g->cur_y = g->start_y; - - // if the width of the specified rectangle is 0, that means - // we may not see *any* pixels or the image is malformed; - // to make sure this is caught, move the current y down to - // max_y (which is what out_gif_code checks). - if (w == 0) - g->cur_y = g->max_y; - - g->lflags = stbi__get8(s); - - if (g->lflags & 0x40) { - g->step = 8 * g->line_size; // first interlaced spacing - g->parse = 3; - } else { - g->step = g->line_size; - g->parse = 0; - } - - if (g->lflags & 0x80) { - stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); - g->color_table = (stbi_uc *) g->lpal; - } else if (g->flags & 0x80) { - g->color_table = (stbi_uc *) g->pal; - } else - return stbi__errpuc("missing color table", "Corrupt GIF"); - - o = stbi__process_gif_raster(s, g); - if (!o) return NULL; - - // if this was the first frame, - pcount = g->w * g->h; - if (first_frame && (g->bgindex > 0)) { - // if first frame, any pixel not drawn to gets the background color - for (pi = 0; pi < pcount; ++pi) { - if (g->history[pi] == 0) { - g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; - memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); - } - } - } - - return o; - } - - case 0x21: // Comment Extension. - { - int len; - int ext = stbi__get8(s); - if (ext == 0xF9) { // Graphic Control Extension. - len = stbi__get8(s); - if (len == 4) { - g->eflags = stbi__get8(s); - g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. - - // unset old transparent - if (g->transparent >= 0) { - g->pal[g->transparent][3] = 255; - } - if (g->eflags & 0x01) { - g->transparent = stbi__get8(s); - if (g->transparent >= 0) { - g->pal[g->transparent][3] = 0; - } - } else { - // don't need transparent - stbi__skip(s, 1); - g->transparent = -1; - } - } else { - stbi__skip(s, len); - break; - } - } - while ((len = stbi__get8(s)) != 0) { - stbi__skip(s, len); - } - break; - } - - case 0x3B: // gif stream termination code - return (stbi_uc *) s; // using '1' causes warning on some compilers - - default: - return stbi__errpuc("unknown code", "Corrupt GIF"); - } - } -} - -static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays) -{ - STBI_FREE(g->out); - STBI_FREE(g->history); - STBI_FREE(g->background); - - if (out) STBI_FREE(out); - if (delays && *delays) STBI_FREE(*delays); - return stbi__errpuc("outofmem", "Out of memory"); -} - -static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) -{ - if (stbi__gif_test(s)) { - int layers = 0; - stbi_uc *u = 0; - stbi_uc *out = 0; - stbi_uc *two_back = 0; - stbi__gif g; - int stride; - int out_size = 0; - int delays_size = 0; - - STBI_NOTUSED(out_size); - STBI_NOTUSED(delays_size); - - memset(&g, 0, sizeof(g)); - if (delays) { - *delays = 0; - } - - do { - u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); - if (u == (stbi_uc *) s) u = 0; // end of animated gif marker - - if (u) { - *x = g.w; - *y = g.h; - ++layers; - stride = g.w * g.h * 4; - - if (out) { - void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride ); - if (!tmp) - return stbi__load_gif_main_outofmem(&g, out, delays); - else { - out = (stbi_uc*) tmp; - out_size = layers * stride; - } - - if (delays) { - int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers ); - if (!new_delays) - return stbi__load_gif_main_outofmem(&g, out, delays); - *delays = new_delays; - delays_size = layers * sizeof(int); - } - } else { - out = (stbi_uc*)stbi__malloc( layers * stride ); - if (!out) - return stbi__load_gif_main_outofmem(&g, out, delays); - out_size = layers * stride; - if (delays) { - *delays = (int*) stbi__malloc( layers * sizeof(int) ); - if (!*delays) - return stbi__load_gif_main_outofmem(&g, out, delays); - delays_size = layers * sizeof(int); - } - } - memcpy( out + ((layers - 1) * stride), u, stride ); - if (layers >= 2) { - two_back = out - 2 * stride; - } - - if (delays) { - (*delays)[layers - 1U] = g.delay; - } - } - } while (u != 0); - - // free temp buffer; - STBI_FREE(g.out); - STBI_FREE(g.history); - STBI_FREE(g.background); - - // do the final conversion after loading everything; - if (req_comp && req_comp != 4) - out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); - - *z = layers; - return out; - } else { - return stbi__errpuc("not GIF", "Image was not as a gif type."); - } -} - -static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) -{ - stbi_uc *u = 0; - stbi__gif g; - memset(&g, 0, sizeof(g)); - STBI_NOTUSED(ri); - - u = stbi__gif_load_next(s, &g, comp, req_comp, 0); - if (u == (stbi_uc *) s) u = 0; // end of animated gif marker - if (u) { - *x = g.w; - *y = g.h; - - // moved conversion to after successful load so that the same - // can be done for multiple frames. - if (req_comp && req_comp != 4) - u = stbi__convert_format(u, 4, req_comp, g.w, g.h); - } else if (g.out) { - // if there was an error and we allocated an image buffer, free it! - STBI_FREE(g.out); - } - - // free buffers needed for multiple frame loading; - STBI_FREE(g.history); - STBI_FREE(g.background); - - return u; -} - -static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) -{ - return stbi__gif_info_raw(s,x,y,comp); -} -#endif - -// ************************************************************************************************* -// Radiance RGBE HDR loader -// originally by Nicolas Schulz -#ifndef STBI_NO_HDR -static int stbi__hdr_test_core(stbi__context *s, const char *signature) -{ - int i; - for (i=0; signature[i]; ++i) - if (stbi__get8(s) != signature[i]) - return 0; - stbi__rewind(s); - return 1; -} - -static int stbi__hdr_test(stbi__context* s) -{ - int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); - stbi__rewind(s); - if(!r) { - r = stbi__hdr_test_core(s, "#?RGBE\n"); - stbi__rewind(s); - } - return r; -} - -#define STBI__HDR_BUFLEN 1024 -static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) -{ - int len=0; - char c = '\0'; - - c = (char) stbi__get8(z); - - while (!stbi__at_eof(z) && c != '\n') { - buffer[len++] = c; - if (len == STBI__HDR_BUFLEN-1) { - // flush to end of line - while (!stbi__at_eof(z) && stbi__get8(z) != '\n') - ; - break; - } - c = (char) stbi__get8(z); - } - - buffer[len] = 0; - return buffer; -} - -static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) -{ - if ( input[3] != 0 ) { - float f1; - // Exponent - f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); - if (req_comp <= 2) - output[0] = (input[0] + input[1] + input[2]) * f1 / 3; - else { - output[0] = input[0] * f1; - output[1] = input[1] * f1; - output[2] = input[2] * f1; - } - if (req_comp == 2) output[1] = 1; - if (req_comp == 4) output[3] = 1; - } else { - switch (req_comp) { - case 4: output[3] = 1; /* fallthrough */ - case 3: output[0] = output[1] = output[2] = 0; - break; - case 2: output[1] = 1; /* fallthrough */ - case 1: output[0] = 0; - break; - } - } -} - -static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) -{ - char buffer[STBI__HDR_BUFLEN]; - char *token; - int valid = 0; - int width, height; - stbi_uc *scanline; - float *hdr_data; - int len; - unsigned char count, value; - int i, j, k, c1,c2, z; - const char *headerToken; - STBI_NOTUSED(ri); - - // Check identifier - headerToken = stbi__hdr_gettoken(s,buffer); - if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) - return stbi__errpf("not HDR", "Corrupt HDR image"); - - // Parse header - for(;;) { - token = stbi__hdr_gettoken(s,buffer); - if (token[0] == 0) break; - if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; - } - - if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); - - // Parse width and height - // can't use sscanf() if we're not using stdio! - token = stbi__hdr_gettoken(s,buffer); - if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); - token += 3; - height = (int) strtol(token, &token, 10); - while (*token == ' ') ++token; - if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); - token += 3; - width = (int) strtol(token, NULL, 10); - - if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); - if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); - - *x = width; - *y = height; - - if (comp) *comp = 3; - if (req_comp == 0) req_comp = 3; - - if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) - return stbi__errpf("too large", "HDR image is too large"); - - // Read data - hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); - if (!hdr_data) - return stbi__errpf("outofmem", "Out of memory"); - - // Load image data - // image data is stored as some number of sca - if ( width < 8 || width >= 32768) { - // Read flat data - for (j=0; j < height; ++j) { - for (i=0; i < width; ++i) { - stbi_uc rgbe[4]; - main_decode_loop: - stbi__getn(s, rgbe, 4); - stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); - } - } - } else { - // Read RLE-encoded data - scanline = NULL; - - for (j = 0; j < height; ++j) { - c1 = stbi__get8(s); - c2 = stbi__get8(s); - len = stbi__get8(s); - if (c1 != 2 || c2 != 2 || (len & 0x80)) { - // not run-length encoded, so we have to actually use THIS data as a decoded - // pixel (note this can't be a valid pixel--one of RGB must be >= 128) - stbi_uc rgbe[4]; - rgbe[0] = (stbi_uc) c1; - rgbe[1] = (stbi_uc) c2; - rgbe[2] = (stbi_uc) len; - rgbe[3] = (stbi_uc) stbi__get8(s); - stbi__hdr_convert(hdr_data, rgbe, req_comp); - i = 1; - j = 0; - STBI_FREE(scanline); - goto main_decode_loop; // yes, this makes no sense - } - len <<= 8; - len |= stbi__get8(s); - if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } - if (scanline == NULL) { - scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); - if (!scanline) { - STBI_FREE(hdr_data); - return stbi__errpf("outofmem", "Out of memory"); - } - } - - for (k = 0; k < 4; ++k) { - int nleft; - i = 0; - while ((nleft = width - i) > 0) { - count = stbi__get8(s); - if (count > 128) { - // Run - value = stbi__get8(s); - count -= 128; - if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } - for (z = 0; z < count; ++z) - scanline[i++ * 4 + k] = value; - } else { - // Dump - if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } - for (z = 0; z < count; ++z) - scanline[i++ * 4 + k] = stbi__get8(s); - } - } - } - for (i=0; i < width; ++i) - stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); - } - if (scanline) - STBI_FREE(scanline); - } - - return hdr_data; -} - -static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) -{ - char buffer[STBI__HDR_BUFLEN]; - char *token; - int valid = 0; - int dummy; - - if (!x) x = &dummy; - if (!y) y = &dummy; - if (!comp) comp = &dummy; - - if (stbi__hdr_test(s) == 0) { - stbi__rewind( s ); - return 0; - } - - for(;;) { - token = stbi__hdr_gettoken(s,buffer); - if (token[0] == 0) break; - if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; - } - - if (!valid) { - stbi__rewind( s ); - return 0; - } - token = stbi__hdr_gettoken(s,buffer); - if (strncmp(token, "-Y ", 3)) { - stbi__rewind( s ); - return 0; - } - token += 3; - *y = (int) strtol(token, &token, 10); - while (*token == ' ') ++token; - if (strncmp(token, "+X ", 3)) { - stbi__rewind( s ); - return 0; - } - token += 3; - *x = (int) strtol(token, NULL, 10); - *comp = 3; - return 1; -} -#endif // STBI_NO_HDR - -#ifndef STBI_NO_BMP -static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) -{ - void *p; - stbi__bmp_data info; - - info.all_a = 255; - p = stbi__bmp_parse_header(s, &info); - if (p == NULL) { - stbi__rewind( s ); - return 0; - } - if (x) *x = s->img_x; - if (y) *y = s->img_y; - if (comp) { - if (info.bpp == 24 && info.ma == 0xff000000) - *comp = 3; - else - *comp = info.ma ? 4 : 3; - } - return 1; -} -#endif - -#ifndef STBI_NO_PSD -static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) -{ - int channelCount, dummy, depth; - if (!x) x = &dummy; - if (!y) y = &dummy; - if (!comp) comp = &dummy; - if (stbi__get32be(s) != 0x38425053) { - stbi__rewind( s ); - return 0; - } - if (stbi__get16be(s) != 1) { - stbi__rewind( s ); - return 0; - } - stbi__skip(s, 6); - channelCount = stbi__get16be(s); - if (channelCount < 0 || channelCount > 16) { - stbi__rewind( s ); - return 0; - } - *y = stbi__get32be(s); - *x = stbi__get32be(s); - depth = stbi__get16be(s); - if (depth != 8 && depth != 16) { - stbi__rewind( s ); - return 0; - } - if (stbi__get16be(s) != 3) { - stbi__rewind( s ); - return 0; - } - *comp = 4; - return 1; -} - -static int stbi__psd_is16(stbi__context *s) -{ - int channelCount, depth; - if (stbi__get32be(s) != 0x38425053) { - stbi__rewind( s ); - return 0; - } - if (stbi__get16be(s) != 1) { - stbi__rewind( s ); - return 0; - } - stbi__skip(s, 6); - channelCount = stbi__get16be(s); - if (channelCount < 0 || channelCount > 16) { - stbi__rewind( s ); - return 0; - } - STBI_NOTUSED(stbi__get32be(s)); - STBI_NOTUSED(stbi__get32be(s)); - depth = stbi__get16be(s); - if (depth != 16) { - stbi__rewind( s ); - return 0; - } - return 1; -} -#endif - -#ifndef STBI_NO_PIC -static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) -{ - int act_comp=0,num_packets=0,chained,dummy; - stbi__pic_packet packets[10]; - - if (!x) x = &dummy; - if (!y) y = &dummy; - if (!comp) comp = &dummy; - - if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { - stbi__rewind(s); - return 0; - } - - stbi__skip(s, 88); - - *x = stbi__get16be(s); - *y = stbi__get16be(s); - if (stbi__at_eof(s)) { - stbi__rewind( s); - return 0; - } - if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { - stbi__rewind( s ); - return 0; - } - - stbi__skip(s, 8); - - do { - stbi__pic_packet *packet; - - if (num_packets==sizeof(packets)/sizeof(packets[0])) - return 0; - - packet = &packets[num_packets++]; - chained = stbi__get8(s); - packet->size = stbi__get8(s); - packet->type = stbi__get8(s); - packet->channel = stbi__get8(s); - act_comp |= packet->channel; - - if (stbi__at_eof(s)) { - stbi__rewind( s ); - return 0; - } - if (packet->size != 8) { - stbi__rewind( s ); - return 0; - } - } while (chained); - - *comp = (act_comp & 0x10 ? 4 : 3); - - return 1; -} -#endif - -// ************************************************************************************************* -// Portable Gray Map and Portable Pixel Map loader -// by Ken Miller -// -// PGM: http://netpbm.sourceforge.net/doc/pgm.html -// PPM: http://netpbm.sourceforge.net/doc/ppm.html -// -// Known limitations: -// Does not support comments in the header section -// Does not support ASCII image data (formats P2 and P3) - -#ifndef STBI_NO_PNM - -static int stbi__pnm_test(stbi__context *s) -{ - char p, t; - p = (char) stbi__get8(s); - t = (char) stbi__get8(s); - if (p != 'P' || (t != '5' && t != '6')) { - stbi__rewind( s ); - return 0; - } - return 1; -} - -static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) -{ - stbi_uc *out; - STBI_NOTUSED(ri); - - ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n); - if (ri->bits_per_channel == 0) - return 0; - - if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); - if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); - - *x = s->img_x; - *y = s->img_y; - if (comp) *comp = s->img_n; - - if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0)) - return stbi__errpuc("too large", "PNM too large"); - - out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0); - if (!out) return stbi__errpuc("outofmem", "Out of memory"); - if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) { - STBI_FREE(out); - return stbi__errpuc("bad PNM", "PNM file truncated"); - } - - if (req_comp && req_comp != s->img_n) { - if (ri->bits_per_channel == 16) { - out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y); - } else { - out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); - } - if (out == NULL) return out; // stbi__convert_format frees input on failure - } - return out; -} - -static int stbi__pnm_isspace(char c) -{ - return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; -} - -static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) -{ - for (;;) { - while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) - *c = (char) stbi__get8(s); - - if (stbi__at_eof(s) || *c != '#') - break; - - while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) - *c = (char) stbi__get8(s); - } -} - -static int stbi__pnm_isdigit(char c) -{ - return c >= '0' && c <= '9'; -} - -static int stbi__pnm_getinteger(stbi__context *s, char *c) -{ - int value = 0; - - while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { - value = value*10 + (*c - '0'); - *c = (char) stbi__get8(s); - if((value > 214748364) || (value == 214748364 && *c > '7')) - return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int"); - } - - return value; -} - -static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) -{ - int maxv, dummy; - char c, p, t; - - if (!x) x = &dummy; - if (!y) y = &dummy; - if (!comp) comp = &dummy; - - stbi__rewind(s); - - // Get identifier - p = (char) stbi__get8(s); - t = (char) stbi__get8(s); - if (p != 'P' || (t != '5' && t != '6')) { - stbi__rewind(s); - return 0; - } - - *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm - - c = (char) stbi__get8(s); - stbi__pnm_skip_whitespace(s, &c); - - *x = stbi__pnm_getinteger(s, &c); // read width - if(*x == 0) - return stbi__err("invalid width", "PPM image header had zero or overflowing width"); - stbi__pnm_skip_whitespace(s, &c); - - *y = stbi__pnm_getinteger(s, &c); // read height - if (*y == 0) - return stbi__err("invalid width", "PPM image header had zero or overflowing width"); - stbi__pnm_skip_whitespace(s, &c); - - maxv = stbi__pnm_getinteger(s, &c); // read max value - if (maxv > 65535) - return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images"); - else if (maxv > 255) - return 16; - else - return 8; -} - -static int stbi__pnm_is16(stbi__context *s) -{ - if (stbi__pnm_info(s, NULL, NULL, NULL) == 16) - return 1; - return 0; -} -#endif - -static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) -{ - #ifndef STBI_NO_JPEG - if (stbi__jpeg_info(s, x, y, comp)) return 1; - #endif - - #ifndef STBI_NO_PNG - if (stbi__png_info(s, x, y, comp)) return 1; - #endif - - #ifndef STBI_NO_GIF - if (stbi__gif_info(s, x, y, comp)) return 1; - #endif - - #ifndef STBI_NO_BMP - if (stbi__bmp_info(s, x, y, comp)) return 1; - #endif - - #ifndef STBI_NO_PSD - if (stbi__psd_info(s, x, y, comp)) return 1; - #endif - - #ifndef STBI_NO_PIC - if (stbi__pic_info(s, x, y, comp)) return 1; - #endif - - #ifndef STBI_NO_PNM - if (stbi__pnm_info(s, x, y, comp)) return 1; - #endif - - #ifndef STBI_NO_HDR - if (stbi__hdr_info(s, x, y, comp)) return 1; - #endif - - // test tga last because it's a crappy test! - #ifndef STBI_NO_TGA - if (stbi__tga_info(s, x, y, comp)) - return 1; - #endif - return stbi__err("unknown image type", "Image not of any known type, or corrupt"); -} - -static int stbi__is_16_main(stbi__context *s) -{ - #ifndef STBI_NO_PNG - if (stbi__png_is16(s)) return 1; - #endif - - #ifndef STBI_NO_PSD - if (stbi__psd_is16(s)) return 1; - #endif - - #ifndef STBI_NO_PNM - if (stbi__pnm_is16(s)) return 1; - #endif - return 0; -} - -#ifndef STBI_NO_STDIO -STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) -{ - FILE *f = stbi__fopen(filename, "rb"); - int result; - if (!f) return stbi__err("can't fopen", "Unable to open file"); - result = stbi_info_from_file(f, x, y, comp); - fclose(f); - return result; -} - -STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) -{ - int r; - stbi__context s; - long pos = ftell(f); - stbi__start_file(&s, f); - r = stbi__info_main(&s,x,y,comp); - fseek(f,pos,SEEK_SET); - return r; -} - -STBIDEF int stbi_is_16_bit(char const *filename) -{ - FILE *f = stbi__fopen(filename, "rb"); - int result; - if (!f) return stbi__err("can't fopen", "Unable to open file"); - result = stbi_is_16_bit_from_file(f); - fclose(f); - return result; -} - -STBIDEF int stbi_is_16_bit_from_file(FILE *f) -{ - int r; - stbi__context s; - long pos = ftell(f); - stbi__start_file(&s, f); - r = stbi__is_16_main(&s); - fseek(f,pos,SEEK_SET); - return r; -} -#endif // !STBI_NO_STDIO - -STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) -{ - stbi__context s; - stbi__start_mem(&s,buffer,len); - return stbi__info_main(&s,x,y,comp); -} - -STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) -{ - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); - return stbi__info_main(&s,x,y,comp); -} - -STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) -{ - stbi__context s; - stbi__start_mem(&s,buffer,len); - return stbi__is_16_main(&s); -} - -STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) -{ - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); - return stbi__is_16_main(&s); -} - -#endif // STB_IMAGE_IMPLEMENTATION - -/* - revision history: - 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs - 2.19 (2018-02-11) fix warning - 2.18 (2018-01-30) fix warnings - 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug - 1-bit BMP - *_is_16_bit api - avoid warnings - 2.16 (2017-07-23) all functions have 16-bit variants; - STBI_NO_STDIO works again; - compilation fixes; - fix rounding in unpremultiply; - optimize vertical flip; - disable raw_len validation; - documentation fixes - 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; - warning fixes; disable run-time SSE detection on gcc; - uniform handling of optional "return" values; - thread-safe initialization of zlib tables - 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs - 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now - 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes - 2.11 (2016-04-02) allocate large structures on the stack - remove white matting for transparent PSD - fix reported channel count for PNG & BMP - re-enable SSE2 in non-gcc 64-bit - support RGB-formatted JPEG - read 16-bit PNGs (only as 8-bit) - 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED - 2.09 (2016-01-16) allow comments in PNM files - 16-bit-per-pixel TGA (not bit-per-component) - info() for TGA could break due to .hdr handling - info() for BMP to shares code instead of sloppy parse - can use STBI_REALLOC_SIZED if allocator doesn't support realloc - code cleanup - 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA - 2.07 (2015-09-13) fix compiler warnings - partial animated GIF support - limited 16-bpc PSD support - #ifdef unused functions - bug with < 92 byte PIC,PNM,HDR,TGA - 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value - 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning - 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit - 2.03 (2015-04-12) extra corruption checking (mmozeiko) - stbi_set_flip_vertically_on_load (nguillemot) - fix NEON support; fix mingw support - 2.02 (2015-01-19) fix incorrect assert, fix warning - 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 - 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG - 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) - progressive JPEG (stb) - PGM/PPM support (Ken Miller) - STBI_MALLOC,STBI_REALLOC,STBI_FREE - GIF bugfix -- seemingly never worked - STBI_NO_*, STBI_ONLY_* - 1.48 (2014-12-14) fix incorrectly-named assert() - 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) - optimize PNG (ryg) - fix bug in interlaced PNG with user-specified channel count (stb) - 1.46 (2014-08-26) - fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG - 1.45 (2014-08-16) - fix MSVC-ARM internal compiler error by wrapping malloc - 1.44 (2014-08-07) - various warning fixes from Ronny Chevalier - 1.43 (2014-07-15) - fix MSVC-only compiler problem in code changed in 1.42 - 1.42 (2014-07-09) - don't define _CRT_SECURE_NO_WARNINGS (affects user code) - fixes to stbi__cleanup_jpeg path - added STBI_ASSERT to avoid requiring assert.h - 1.41 (2014-06-25) - fix search&replace from 1.36 that messed up comments/error messages - 1.40 (2014-06-22) - fix gcc struct-initialization warning - 1.39 (2014-06-15) - fix to TGA optimization when req_comp != number of components in TGA; - fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) - add support for BMP version 5 (more ignored fields) - 1.38 (2014-06-06) - suppress MSVC warnings on integer casts truncating values - fix accidental rename of 'skip' field of I/O - 1.37 (2014-06-04) - remove duplicate typedef - 1.36 (2014-06-03) - convert to header file single-file library - if de-iphone isn't set, load iphone images color-swapped instead of returning NULL - 1.35 (2014-05-27) - various warnings - fix broken STBI_SIMD path - fix bug where stbi_load_from_file no longer left file pointer in correct place - fix broken non-easy path for 32-bit BMP (possibly never used) - TGA optimization by Arseny Kapoulkine - 1.34 (unknown) - use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case - 1.33 (2011-07-14) - make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements - 1.32 (2011-07-13) - support for "info" function for all supported filetypes (SpartanJ) - 1.31 (2011-06-20) - a few more leak fixes, bug in PNG handling (SpartanJ) - 1.30 (2011-06-11) - added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) - removed deprecated format-specific test/load functions - removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway - error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) - fix inefficiency in decoding 32-bit BMP (David Woo) - 1.29 (2010-08-16) - various warning fixes from Aurelien Pocheville - 1.28 (2010-08-01) - fix bug in GIF palette transparency (SpartanJ) - 1.27 (2010-08-01) - cast-to-stbi_uc to fix warnings - 1.26 (2010-07-24) - fix bug in file buffering for PNG reported by SpartanJ - 1.25 (2010-07-17) - refix trans_data warning (Won Chun) - 1.24 (2010-07-12) - perf improvements reading from files on platforms with lock-heavy fgetc() - minor perf improvements for jpeg - deprecated type-specific functions so we'll get feedback if they're needed - attempt to fix trans_data warning (Won Chun) - 1.23 fixed bug in iPhone support - 1.22 (2010-07-10) - removed image *writing* support - stbi_info support from Jetro Lauha - GIF support from Jean-Marc Lienher - iPhone PNG-extensions from James Brown - warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) - 1.21 fix use of 'stbi_uc' in header (reported by jon blow) - 1.20 added support for Softimage PIC, by Tom Seddon - 1.19 bug in interlaced PNG corruption check (found by ryg) - 1.18 (2008-08-02) - fix a threading bug (local mutable static) - 1.17 support interlaced PNG - 1.16 major bugfix - stbi__convert_format converted one too many pixels - 1.15 initialize some fields for thread safety - 1.14 fix threadsafe conversion bug - header-file-only version (#define STBI_HEADER_FILE_ONLY before including) - 1.13 threadsafe - 1.12 const qualifiers in the API - 1.11 Support installable IDCT, colorspace conversion routines - 1.10 Fixes for 64-bit (don't use "unsigned long") - optimized upsampling by Fabian "ryg" Giesen - 1.09 Fix format-conversion for PSD code (bad global variables!) - 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz - 1.07 attempt to fix C++ warning/errors again - 1.06 attempt to fix C++ warning/errors again - 1.05 fix TGA loading to return correct *comp and use good luminance calc - 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free - 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR - 1.02 support for (subset of) HDR files, float interface for preferred access to them - 1.01 fix bug: possible bug in handling right-side up bmps... not sure - fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all - 1.00 interface to zlib that skips zlib header - 0.99 correct handling of alpha in palette - 0.98 TGA loader by lonesock; dynamically add loaders (untested) - 0.97 jpeg errors on too large a file; also catch another malloc failure - 0.96 fix detection of invalid v value - particleman@mollyrocket forum - 0.95 during header scan, seek to markers in case of padding - 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same - 0.93 handle jpegtran output; verbose errors - 0.92 read 4,8,16,24,32-bit BMP files of several formats - 0.91 output 24-bit Windows 3.0 BMP files - 0.90 fix a few more warnings; bump version number to approach 1.0 - 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd - 0.60 fix compiling as c++ - 0.59 fix warnings: merge Dave Moore's -Wall fixes - 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian - 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available - 0.56 fix bug: zlib uncompressed mode len vs. nlen - 0.55 fix bug: restart_interval not initialized to 0 - 0.54 allow NULL for 'int *comp' - 0.53 fix bug in png 3->4; speedup png decoding - 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments - 0.51 obey req_comp requests, 1-component jpegs return as 1-component, - on 'test' only check type, not whether we support this variant - 0.50 (2006-11-19) - first released version -*/ - - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright (c) 2017 Sean Barrett -Permission 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: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE 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. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain (www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE 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 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. ------------------------------------------------------------------------------- -*/ diff --git a/Client/tests/BluetoothWrapperTests.cpp b/Client/tests/BluetoothWrapperTests.cpp new file mode 100644 index 0000000..f21e6a8 --- /dev/null +++ b/Client/tests/BluetoothWrapperTests.cpp @@ -0,0 +1,187 @@ +#include "BluetoothWrapper.h" +#include "CommandSerializer.h" +#include "FakeConnector.h" +#include +#include +#include + +// Minimal test runner (no framework). Exit code 1 on any failure. +static int failures = 0; +#define CHECK(cond) do { if (!(cond)) { failures++; std::printf("FAIL %s:%d: %s\n", __FILE__, __LINE__, #cond); } } while (0) + +static Buffer bytes(std::initializer_list values) +{ + Buffer b; + for (int v : values) b.push_back((char)v); + return b; +} + +static void testNotificationBeforeAck() +{ + auto fakeOwned = std::make_unique(); + FakeBluetoothConnector* fake = fakeOwned.get(); + BluetoothWrapper wrapper(std::move(fakeOwned)); + + // Device sends its own DATA_MDR notification (seq 0) before ACKing (seq 1) the host's frame. + fake->incomingFrames.push_back(CommandSerializer::packageDataForBt( + bytes({ 0x69, 0x19, 0x01, 0x01, 0x01, 0x00, 0x0a, 0x00, 0x00 }), DATA_TYPE::DATA_MDR, 0)); + fake->incomingFrames.push_back(CommandSerializer::packageDataForBt({}, DATA_TYPE::ACK, 1)); + + wrapper.sendCommand(bytes({ 0x68, 0x17, 0x01, 0x01, 0x01, 0x00, 0x0a })); + + // First sent frame is the command itself (seq 0); the second must be the host's ACK for the + // notification (ACK type, seq = 1 - notification's seq = 1). + CHECK(fake->sentFrames.size() >= 2); + auto firstMsg = unpackSentFrame(fake->sentFrames[0]); + CHECK(firstMsg.dataType == DATA_TYPE::DATA_MDR && firstMsg.seqNumber == 0); + auto ackMsg = unpackSentFrame(fake->sentFrames[1]); + CHECK(ackMsg.dataType == DATA_TYPE::ACK && ackMsg.seqNumber == 1); + + // Next sendCommand must use seq 1 (from the ACK), not repeat/skip because of the notification. + fake->incomingFrames.push_back(CommandSerializer::packageDataForBt({}, DATA_TYPE::ACK, 0)); + wrapper.sendCommand(bytes({ 0x68, 0x17, 0x01, 0x01, 0x01, 0x00, 0x0b })); + + CHECK(fake->sentFrames.size() >= 3); + auto secondMsg = unpackSentFrame(fake->sentFrames.back()); + CHECK(secondMsg.dataType == DATA_TYPE::DATA_MDR && secondMsg.seqNumber == 1); +} + +static void testPlainAcksToggleSeq() +{ + auto fakeOwned = std::make_unique(); + FakeBluetoothConnector* fake = fakeOwned.get(); + BluetoothWrapper wrapper(std::move(fakeOwned)); + + // Three round trips: seq goes 0 -> 1 -> 0, each answered by an ACK carrying 1 - sent seq. + fake->incomingFrames.push_back(CommandSerializer::packageDataForBt({}, DATA_TYPE::ACK, 1)); + wrapper.sendCommand(bytes({ 0x67, 0x17 })); + CHECK(unpackSentFrame(fake->sentFrames[0]).seqNumber == 0); + + fake->incomingFrames.push_back(CommandSerializer::packageDataForBt({}, DATA_TYPE::ACK, 0)); + wrapper.sendCommand(bytes({ 0x67, 0x17 })); + CHECK(unpackSentFrame(fake->sentFrames[1]).seqNumber == 1); + + fake->incomingFrames.push_back(CommandSerializer::packageDataForBt({}, DATA_TYPE::ACK, 1)); + wrapper.sendCommand(bytes({ 0x67, 0x17 })); + CHECK(unpackSentFrame(fake->sentFrames[2]).seqNumber == 0); +} + +static void testNoAckThrows() +{ + auto fakeOwned = std::make_unique(); + BluetoothWrapper wrapper(std::move(fakeOwned)); + + // No scripted incoming frames at all: recv() throws immediately, sendCommand must not hang. + bool threw = false; + try + { + wrapper.sendCommand(bytes({ 0x67, 0x17 })); + } + catch (const std::exception&) + { + threw = true; + } + CHECK(threw); +} + +static void testDataMdrNo2IsAcked() +{ + auto fakeOwned = std::make_unique(); + FakeBluetoothConnector* fake = fakeOwned.get(); + BluetoothWrapper wrapper(std::move(fakeOwned)); + + // Device sends a DATA_MDR_NO2 frame (seq 0, e.g. a slider echo) before ACKing (seq 1) the host's frame. + fake->incomingFrames.push_back(CommandSerializer::packageDataForBt( + bytes({ 0x25, 0x02, 0x01 }), DATA_TYPE::DATA_MDR_NO2, 0)); + fake->incomingFrames.push_back(CommandSerializer::packageDataForBt({}, DATA_TYPE::ACK, 1)); + + wrapper.sendCommand(bytes({ 0x68, 0x17, 0x01, 0x01, 0x01, 0x00, 0x0a })); + + // First sent frame is the command itself (seq 0); the second must be the host's ACK for the + // DATA_MDR_NO2 frame (ACK type, seq = 1 - frame's seq = 1). + CHECK(fake->sentFrames.size() >= 2); + auto firstMsg = unpackSentFrame(fake->sentFrames[0]); + CHECK(firstMsg.dataType == DATA_TYPE::DATA_MDR && firstMsg.seqNumber == 0); + if (fake->sentFrames.size() >= 2) + { + auto ackMsg = unpackSentFrame(fake->sentFrames[1]); + CHECK(ackMsg.dataType == DATA_TYPE::ACK && ackMsg.seqNumber == 1); + } + + // Next sendCommand must use seq 1 (from the device's real ACK), not skip because of the NO2 frame. + fake->incomingFrames.push_back(CommandSerializer::packageDataForBt({}, DATA_TYPE::ACK, 0)); + wrapper.sendCommand(bytes({ 0x68, 0x17, 0x01, 0x01, 0x01, 0x00, 0x0b })); + + CHECK(fake->sentFrames.size() >= 3); + auto secondMsg = unpackSentFrame(fake->sentFrames.back()); + CHECK(secondMsg.dataType == DATA_TYPE::DATA_MDR && secondMsg.seqNumber == 1); +} + +static void testSeqStays1BitAfterTimeout() +{ + auto fakeOwned = std::make_unique(); + FakeBluetoothConnector* fake = fakeOwned.get(); + BluetoothWrapper wrapper(std::move(fakeOwned)); + + // Command #1: seq 0, ACKed with seq 1. + fake->incomingFrames.push_back(CommandSerializer::packageDataForBt({}, DATA_TYPE::ACK, 1)); + wrapper.sendCommand(bytes({ 0x67, 0x17 })); + CHECK(unpackSentFrame(fake->sentFrames[0]).seqNumber == 0); + + // Command #2: seq 1, no ACK arrives (recv throws) -> sendCommand must throw. + bool threw = false; + try + { + wrapper.sendCommand(bytes({ 0x67, 0x17 })); + } + catch (const std::exception&) + { + threw = true; + } + CHECK(threw); + CHECK(unpackSentFrame(fake->sentFrames[1]).seqNumber == 1); + + // Command #3 must reuse seq 1 (the unanswered frame's seq), never advance to 2. + fake->incomingFrames.push_back(CommandSerializer::packageDataForBt({}, DATA_TYPE::ACK, 0)); + wrapper.sendCommand(bytes({ 0x67, 0x17 })); + CHECK(unpackSentFrame(fake->sentFrames[2]).seqNumber == 1); +} + +static void testSendCommandAndReadResponseSeqStays1Bit() +{ + auto fakeOwned = std::make_unique(); + FakeBluetoothConnector* fake = fakeOwned.get(); + BluetoothWrapper wrapper(std::move(fakeOwned)); + + // No scripted incoming frames: the response never arrives, sendCommandAndReadResponse throws. + bool threw = false; + try + { + wrapper.sendCommandAndReadResponse(bytes({ 0x67, 0x17 }), 0x69); + } + catch (const std::exception&) + { + threw = true; + } + CHECK(threw); + CHECK(unpackSentFrame(fake->sentFrames[0]).seqNumber == 0); + + // Next command must reuse seq 0 (the unanswered frame's seq), not advance to 1. + fake->incomingFrames.push_back(CommandSerializer::packageDataForBt({}, DATA_TYPE::ACK, 1)); + wrapper.sendCommand(bytes({ 0x67, 0x17 })); + CHECK(unpackSentFrame(fake->sentFrames[1]).seqNumber == 0); +} + +int main() +{ + testNotificationBeforeAck(); + testPlainAcksToggleSeq(); + testNoAckThrows(); + testDataMdrNo2IsAcked(); + testSeqStays1BitAfterTimeout(); + testSendCommandAndReadResponseSeqStays1Bit(); + + if (failures) { std::printf("BluetoothWrapperTests: %d failure(s)\n", failures); return 1; } + std::printf("BluetoothWrapperTests: all passed\n"); + return 0; +} diff --git a/Client/tests/FakeConnector.h b/Client/tests/FakeConnector.h new file mode 100644 index 0000000..d16dfa1 --- /dev/null +++ b/Client/tests/FakeConnector.h @@ -0,0 +1,57 @@ +#pragma once + +#include "BluetoothWrapper.h" +#include "CommandSerializer.h" +#include "IBluetoothConnector.h" +#include "Exceptions.h" +#include +#include +#include +#include + +// Records every frame handed to send() and hands back scripted incoming frames one whole frame per +// recv() call. When the script is exhausted, recv() throws like the real macOS connector does after +// its 2.5s timeout. Shared by BluetoothWrapperTests.cpp and HeadphonesTests.cpp. +class FakeBluetoothConnector : public IBluetoothConnector +{ +public: + std::vector sentFrames; + std::deque incomingFrames; + // What getProtocolVersion() reports. V1 by default (BluetoothWrapperTests don't care); tests that model a + // v2 headset set V2. + SonyProtocolVersion protocolVersion = SonyProtocolVersion::V1; + + int send(char* buf, size_t length) noexcept(false) override + { + this->sentFrames.emplace_back(buf, buf + length); + return static_cast(length); + } + + int recv(char* buf, size_t length) noexcept(false) override + { + if (this->incomingFrames.empty()) + { + throw RecoverableException("recv timed out", false); + } + auto frame = this->incomingFrames.front(); + this->incomingFrames.pop_front(); + if (frame.size() > length) + { + throw std::runtime_error("scripted frame too large for buffer"); + } + std::copy(frame.begin(), frame.end(), buf); + return static_cast(frame.size()); + } + + void connect(const std::string&) noexcept(false) override {} + void disconnect() noexcept override {} + bool isConnected() noexcept override { return true; } + std::vector getConnectedDevices() override { return {}; } + SonyProtocolVersion getProtocolVersion() noexcept override { return this->protocolVersion; } +}; + +// Decodes a frame previously recorded by FakeBluetoothConnector::send (includes START_MARKER/END_MARKER). +inline CommandSerializer::Message unpackSentFrame(const Buffer& frame) +{ + return CommandSerializer::unpackBtMessage(Buffer(frame.begin() + 1, frame.end() - 1)); +} diff --git a/Client/tests/HeadphonesTests.cpp b/Client/tests/HeadphonesTests.cpp new file mode 100644 index 0000000..3f69f24 --- /dev/null +++ b/Client/tests/HeadphonesTests.cpp @@ -0,0 +1,215 @@ +#include "Headphones.h" +#include "BluetoothWrapper.h" +#include "CommandSerializer.h" +#include "Constants.h" +#include "FakeConnector.h" +#include +#include + +// Minimal test runner (no framework). Exit code 1 on any failure. +static int failures = 0; +#define CHECK(cond) do { if (!(cond)) { failures++; std::printf("FAIL %s:%d: %s\n", __FILE__, __LINE__, #cond); } } while (0) + +static Buffer bytes(std::initializer_list values) +{ + Buffer b; + for (int v : values) b.push_back((char)v); + return b; +} + +// Scripts a single DATA_MDR reply so sendCommandAndReadResponse's read loop matches it directly - +// BluetoothWrapper ACKs DATA_MDR frames itself, so no separate scripted ACK frame is needed. +static void scriptResponse(FakeBluetoothConnector& fake, std::initializer_list payload) +{ + fake.incomingFrames.push_back(CommandSerializer::packageDataForBt(bytes(payload), DATA_TYPE::DATA_MDR, 0)); +} + +// A connector that answers only the specific (opcode, subtype) requests it's told to, and times out (throws) +// for everything else - including requests it was never asked about. The plain FIFO FakeBluetoothConnector +// can't model "this one inquiry never answers, but a later different inquiry does" because it hands back +// whatever's queued regardless of which request is asking; a device really just never replies to an +// unsupported inquiry rather than replying out of order to an unrelated one. +class SelectiveFakeConnector : public FakeBluetoothConnector +{ +public: + void scriptReplyTo(unsigned char opcode, unsigned char subtype, std::initializer_list payload) + { + this->replies.push_back({ { opcode, subtype }, bytes(payload) }); + } + + int recv(char* buf, size_t length) noexcept(false) override + { + if (this->sentFrames.empty()) throw RecoverableException("recv timed out", false); + auto lastSent = unpackSentFrame(this->sentFrames.back()); + for (const auto& entry : this->replies) + { + if (lastSent.payload.size() >= 2 + && (unsigned char)lastSent.payload[0] == entry.first.first + && (unsigned char)lastSent.payload[1] == entry.first.second) + { + auto frame = CommandSerializer::packageDataForBt(entry.second, DATA_TYPE::DATA_MDR, 0); + if (frame.size() > length) throw std::runtime_error("scripted frame too large for buffer"); + std::copy(frame.begin(), frame.end(), buf); + return static_cast(frame.size()); + } + } + throw RecoverableException("recv timed out", false); + } + +private: + std::vector, Buffer>> replies; +}; + +// Cases (1) + (2): a real WH-1000XM6 answers the single-battery inquiry once (55%, not charging), then a +// later poll's 22 00 times out (no scripted reply). The transient timeout must NOT fall back to probing +// the TWS commands (22 09 / 22 0a) - that flips hasDualBattery() to true forever, which is the header's +// "G 0 % D 9 % Boîtier 0 %" bug on a single-battery device. +static void testTransientBatteryTimeoutKeepsSingleBattery() +{ + auto fakeOwned = std::make_unique(); + FakeBluetoothConnector* fake = fakeOwned.get(); + fake->protocolVersion = SonyProtocolVersion::V2; // the WH-1000XM6 is a v2 device + BluetoothWrapper wrapper(std::move(fakeOwned)); + Headphones phones(wrapper); + + // (1) 22 00 answered -> 23 00 37 00 (level 55, not charging). + scriptResponse(*fake, { 0x23, 0x00, 0x37, 0x00 }); + phones.requestBattery(); + CHECK(phones.getBatteryLevel() == 55); + CHECK(phones.hasDualBattery() == false); + + // (2) 22 00 now times out (no scripted reply queued) - must not probe 22 09 / 22 0a, and the last + // known values must be kept. + fake->sentFrames.clear(); + phones.requestBattery(); + + for (const auto& frame : fake->sentFrames) + { + auto msg = unpackSentFrame(frame); + bool isBatteryGet = msg.payload.size() >= 2 && (unsigned char)msg.payload[0] == V2Command::BATTERY_GET; + bool isTwsProbe = isBatteryGet + && ((unsigned char)msg.payload[1] == 0x09 || (unsigned char)msg.payload[1] == 0x0a); + CHECK(!isTwsProbe); + } + CHECK(phones.hasDualBattery() == false); + CHECK(phones.getBatteryLevel() == 55); +} + +// Case (3): a TWS device whose 22 00 never answers must still pick up its dual battery from 22 09 - the +// fix must not break the existing TWS probing path for devices that have no single-battery inquiry at all. +static void testTwsDeviceWithNoSingleBatteryStillProbes() +{ + auto fakeOwned = std::make_unique(); + SelectiveFakeConnector* fake = fakeOwned.get(); + fake->protocolVersion = SonyProtocolVersion::V2; // TWS earbuds are v2 devices + BluetoothWrapper wrapper(std::move(fakeOwned)); + Headphones phones(wrapper); + + // 22 00 has no scripted reply at all (times out); only 22 09 answers, L=50% (not charging), + // R=50% (not charging); 22 0a (case) has no scripted reply either. + fake->scriptReplyTo(V2Command::BATTERY_GET, 0x09, { 0x23, 0x09, 0x32, 0x00, 0x32, 0x00 }); + phones.requestBattery(); + + CHECK(phones.hasDualBattery() == true); +} + +// Safety (final review I1): on a v1 link the v2-only inquiries and setters must send nothing at all. Opcode +// 0x22 (BATTERY_GET on v2) is POWER_OFF on v1 - a stale session's queued read landing on a v1 headset +// (e.g. WH-1000XM4) connected right after would power it off. +static void testV1ConnectionSendsNoV2OnlyFrame() +{ + auto fakeOwned = std::make_unique(); + FakeBluetoothConnector* fake = fakeOwned.get(); + fake->protocolVersion = SonyProtocolVersion::V1; + BluetoothWrapper wrapper(std::move(fakeOwned)); + Headphones phones(wrapper); + + // Each call must return (or throw) without having sent a single frame. + auto sendsNothing = [&](const char* name, auto&& call) { + fake->sentFrames.clear(); + try { call(); } catch (...) {} + if (!fake->sentFrames.empty()) std::printf(" %s sent %zu frame(s) on a v1 link\n", name, fake->sentFrames.size()); + CHECK(fake->sentFrames.empty()); + }; + sendsNothing("requestBattery", [&] { phones.requestBattery(); }); + sendsNothing("requestEqualizer", [&] { phones.requestEqualizer(); }); + sendsNothing("requestDsee", [&] { phones.requestDsee(); }); + sendsNothing("initDevice", [&] { phones.initDevice(); }); + sendsNothing("probeNcAsmInquiryType", [&] { phones.probeNcAsmInquiryType(); }); + sendsNothing("probeCapabilities", [&] { phones.probeCapabilities(); }); + sendsNothing("setEqualizerPreset", [&] { phones.setEqualizerPreset(EQ_PRESET::OFF); }); + sendsNothing("setEqualizerCustom", [&] { phones.setEqualizerCustom(0, { 0, 0, 0, 0, 0 }); }); + sendsNothing("setDsee", [&] { phones.setDsee(true); }); + sendsNothing("setAutoPowerOff", [&] { phones.setAutoPowerOff(1); }); + sendsNothing("setSpeakToChat", [&] { phones.setSpeakToChat(true); }); + sendsNothing("setAdaptiveVolume", [&] { phones.setAdaptiveVolume(true); }); + + CHECK(!phones.isInitialized()); + CHECK(!phones.hasDsee()); + CHECK(phones.getBatteryLevel() == -1); +} + +// A link that turns v1 right after the first frame goes out - models a v1 headset connected on the same +// BluetoothWrapper while a stale multi-frame call (battery TWS probes, capability probes) is still running. +class FlipsToV1AfterFirstSend : public FakeBluetoothConnector +{ +public: + int send(char* buf, size_t length) noexcept(false) override + { + int sent = FakeBluetoothConnector::send(buf, length); + this->protocolVersion = SonyProtocolVersion::V1; + return sent; + } +}; + +// The live protocol is re-checked before every v2-only frame, not only on entry: 22 09 / 22 0a are +// POWER_OFF on v1 too (the opcode, 0x22, is what matters). +static void testLinkTurningV1MidCallStopsSending() +{ + auto onlyFirstFrameSent = [](const char* name, auto&& call) { + auto fakeOwned = std::make_unique(); + FlipsToV1AfterFirstSend* fake = fakeOwned.get(); + fake->protocolVersion = SonyProtocolVersion::V2; + BluetoothWrapper wrapper(std::move(fakeOwned)); + Headphones phones(wrapper); + try { call(phones); } catch (...) {} + if (fake->sentFrames.size() != 1) std::printf(" %s sent %zu frame(s), expected 1\n", name, fake->sentFrames.size()); + CHECK(fake->sentFrames.size() == 1); + }; + onlyFirstFrameSent("requestBattery", [](Headphones& p) { p.requestBattery(); }); + onlyFirstFrameSent("probeCapabilities", [](Headphones& p) { p.probeCapabilities(); }); +} + +// A v2 device that answers the handshake is marked initialized (per Headphones object = per session), and one +// that answers the DSEE inquiry reports the capability. +static void testV2InitAndDseeCapability() +{ + auto fakeOwned = std::make_unique(); + SelectiveFakeConnector* fake = fakeOwned.get(); + fake->protocolVersion = SonyProtocolVersion::V2; + BluetoothWrapper wrapper(std::move(fakeOwned)); + Headphones phones(wrapper); + + CHECK(!phones.isInitialized()); + CHECK(!phones.hasDsee()); + fake->scriptReplyTo(V2Command::INIT_REQUEST, 0x00, { V2Command::INIT_REPLY, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); + fake->scriptReplyTo(V2Command::DSEE_GET, 0x01, { V2Command::DSEE_RET, 0x01, 0x01 }); + phones.initDevice(); + phones.requestDsee(); + CHECK(phones.isInitialized()); + CHECK(phones.hasDsee()); + CHECK(phones.getDsee()); +} + +int main() +{ + testTransientBatteryTimeoutKeepsSingleBattery(); + testTwsDeviceWithNoSingleBatteryStillProbes(); + testV1ConnectionSendsNoV2OnlyFrame(); + testLinkTurningV1MidCallStopsSending(); + testV2InitAndDseeCapability(); + + if (failures) { std::printf("HeadphonesTests: %d failure(s)\n", failures); return 1; } + std::printf("HeadphonesTests: all passed\n"); + return 0; +} diff --git a/Client/tests/LogicTests/main.swift b/Client/tests/LogicTests/main.swift new file mode 100644 index 0000000..3da79df --- /dev/null +++ b/Client/tests/LogicTests/main.swift @@ -0,0 +1,199 @@ +import Foundation +import CoreGraphics + +// Minimal test runner (XCTest isn't available without Xcode). Exit code 1 on any failure. +var failures = 0 +func check(_ condition: Bool, _ message: String, line: Int = #line) { + if !condition { + failures += 1 + print("FAIL line \(line): \(message)") + } +} + +// ReconnectPolicy: 3 s, 10 s, 30 s, then every 60 s; reset restarts. +do { + var policy = ReconnectPolicy() + let delays = (0..<6).map { _ in policy.nextDelay() } + check(delays == [3, 10, 30, 60, 60, 60], "reconnect schedule was \(delays)") + policy.reset() + check(policy.nextDelay() == 3, "reset restarts the schedule") +} + +// PollGuard: a poll is ignored for 3 s after the user changed that setting. +do { + var pollGuard = PollGuard(window: 3) + let t0 = Date(timeIntervalSince1970: 1_000) + check(pollGuard.shouldAcceptPoll(for: "ambient", at: t0), "no user change: accept") + pollGuard.userChanged("ambient", at: t0) + check(!pollGuard.shouldAcceptPoll(for: "ambient", at: t0.addingTimeInterval(2.9)), "inside the window: reject") + check(pollGuard.shouldAcceptPoll(for: "ambient", at: t0.addingTimeInterval(3)), "after the window: accept") + check(pollGuard.shouldAcceptPoll(for: "eq", at: t0.addingTimeInterval(1)), "other keys are unaffected") +} + +// SendThrottle: at most one send per 150 ms while dragging; the final value always goes out. +do { + var throttle = SendThrottle(interval: 0.15) + let t0 = Date(timeIntervalSince1970: 1_000) + check(throttle.shouldSend(at: t0, final: false), "first drag event sends") + check(!throttle.shouldSend(at: t0.addingTimeInterval(0.10), final: false), "too soon: skip") + check(throttle.shouldSend(at: t0.addingTimeInterval(0.16), final: false), "after the interval: send") + check(throttle.shouldSend(at: t0.addingTimeInterval(0.17), final: true), "final value always sends") +} + +// NotchGeometry: a 14" MacBook Pro screen (1512 × 982 pt, notch 188 pt wide, 32 pt high). +do { + let screen = ScreenMetrics(frame: CGRect(x: 0, y: 0, width: 1512, height: 982), safeAreaTop: 32, + auxiliaryTopLeft: CGRect(x: 0, y: 950, width: 662, height: 32), + auxiliaryTopRight: CGRect(x: 850, y: 950, width: 662, height: 32), + menuBarHeight: 32) + let geometry = NotchGeometry(screen: screen) + check(geometry.hasNotch, "notched screen detected") + check(geometry.notch == CGRect(x: 662, y: 950, width: 188, height: 32), "notch rect was \(geometry.notch)") + check(geometry.extended == CGRect(x: 626, y: 950, width: 260, height: 32), "extended rect was \(geometry.extended)") + check(geometry.open == CGRect(x: 606, y: 816, width: 300, height: 166), "open rect was \(geometry.open)") + check(geometry.restingFrame(for: .empty) == geometry.notch, "empty state: bare notch") + check(geometry.restingFrame(for: .musicOnly) == geometry.extended, "music: extended notch") + check(geometry.restingTrailingZone == CGRect(x: 850, y: 950, width: 36, height: 32), + "resting trailing zone was \(geometry.restingTrailingZone)") +} + +// NotchLayout: user sizes are clamped; the zoom never lays the open content out smaller than it needs. +do { + let clamped = NotchLayout(openSize: CGSize(width: 100, height: 1000), sideExtension: 5, zoom: 3) + check(clamped.openSize == CGSize(width: 280, height: 260), "open size clamped, was \(clamped.openSize)") + check(clamped.sideExtension == 28 && clamped.zoom == 1.3, "side and zoom clamped") + check(clamped.contentScale == 1, "zoom limited by the width, was \(clamped.contentScale)") + let roomy = NotchLayout(openSize: CGSize(width: 400, height: 240), sideExtension: 60, zoom: 1.2) + check(roomy.contentScale == 1.2 && roomy.restingScale == 1.2, "zoom applied when the notch is large enough") + let narrowSides = NotchLayout(openSize: NotchLayout.default.openSize, sideExtension: 30, zoom: 1.3) + check(narrowSides.restingScale == 1, "resting icons limited by the side width, was \(narrowSides.restingScale)") + check(NotchLayout.default.contentScale == 1 && NotchLayout.default.restingScale == 1, "default: no zoom") + check(NotchLayout.default.restingArtworkSize(notchHeight: 32) == 24, "default resting artwork") + let bigArtwork = NotchLayout(openSize: NotchLayout.default.openSize, sideExtension: 36, zoom: 1, restingArtwork: 40) + check(bigArtwork.restingArtwork == 30, "resting artwork clamped, was \(bigArtwork.restingArtwork)") + check(bigArtwork.restingArtworkSize(notchHeight: 32) == 28, "resting artwork fits the notch height") + let thinSides = NotchLayout(openSize: NotchLayout.default.openSize, sideExtension: 28, zoom: 1, restingArtwork: 30) + check(thinSides.restingArtworkSize(notchHeight: 32) == 22, "resting artwork fits the side width") + + let screen = ScreenMetrics(frame: CGRect(x: 0, y: 0, width: 1512, height: 982), safeAreaTop: 32, + auxiliaryTopLeft: CGRect(x: 0, y: 950, width: 662, height: 32), + auxiliaryTopRight: CGRect(x: 850, y: 950, width: 662, height: 32), + menuBarHeight: 32) + let geometry = NotchGeometry(screen: screen, layout: roomy) + check(geometry.extended == CGRect(x: 602, y: 950, width: 308, height: 32), "custom extended was \(geometry.extended)") + check(geometry.open == CGRect(x: 556, y: 742, width: 400, height: 240), "custom open was \(geometry.open)") + check(geometry.restingTrailingZone == CGRect(x: 850, y: 950, width: 60, height: 32), "custom trailing zone") +} + +// NotchGeometry: an external screen without a notch, right of the primary screen. +do { + let frame = CGRect(x: 1512, y: 0, width: 2560, height: 1440) + let geometry = NotchGeometry(screen: ScreenMetrics(frame: frame, safeAreaTop: 0, auxiliaryTopLeft: nil, + auxiliaryTopRight: nil, menuBarHeight: 25)) + check(!geometry.hasNotch, "no notch") + check(geometry.notch == CGRect(x: 2697, y: 1415, width: 190, height: 25), "simulated pill was \(geometry.notch)") + check(geometry.restingFrame(for: .empty) == nil, "empty state hides the pill") + check(geometry.restingFrame(for: .headphonesOnly) == geometry.extended, "headphones: extended pill") + + let autoHidden = NotchGeometry(screen: ScreenMetrics(frame: frame, safeAreaTop: 0, auxiliaryTopLeft: nil, + auxiliaryTopRight: nil, menuBarHeight: 0)) + check(autoHidden.notch.height == 24, "auto-hidden menu bar: fallback pill height") + let partial = NotchGeometry(screen: ScreenMetrics(frame: frame, safeAreaTop: 32, auxiliaryTopLeft: nil, + auxiliaryTopRight: nil, menuBarHeight: 32)) + check(!partial.hasNotch, "safe area without auxiliary areas: no notch") +} + +// NotchContent: resting state (spec §4.1), tab on opening, hover delays. +do { + check(NotchContent.restingState(hasMusic: true, headphonesConnected: true) == .musicAndHeadphones, "state 1") + check(NotchContent.restingState(hasMusic: true, headphonesConnected: false) == .musicOnly, "state 2") + check(NotchContent.restingState(hasMusic: false, headphonesConnected: true) == .headphonesOnly, "state 3") + check(NotchContent.restingState(hasMusic: false, headphonesConnected: false) == .empty, "state 4") + check(NotchContent.tabOnOpen(lastChosen: nil, hasMusic: true) == .music, "first open with music: Music") + check(NotchContent.tabOnOpen(lastChosen: nil, hasMusic: false) == .headphones, "first open without music: Headphones") + check(NotchContent.tabOnOpen(lastChosen: .headphones, hasMusic: true) == .headphones, "then the last chosen tab") + check(NotchContent.openDelay == 0.15 && NotchContent.closeDelay == 0.4, "hover delays") +} + +// PlaybackClock: live position from the last known one; display format. +do { + let t0 = Date(timeIntervalSince1970: 1_000) + var track = NowPlaying(trackID: "spotify:track:1", title: "A", artist: "B", album: "C", artworkURL: nil, + duration: 200, position: 30, positionDate: t0, isPlaying: true, volume: 50, + deviceName: nil, + capabilities: MusicCapabilities(canSeek: true, canSetVolume: true, canChangeDevice: false)) + check(PlaybackClock.position(of: track, at: t0.addingTimeInterval(12)) == 42, "playing: advances") + check(PlaybackClock.position(of: track, at: t0.addingTimeInterval(500)) == 200, "bounded by the duration") + check(PlaybackClock.position(of: track, at: t0.addingTimeInterval(-40)) == 0, "never negative") + track.isPlaying = false + check(PlaybackClock.position(of: track, at: t0.addingTimeInterval(12)) == 30, "paused: frozen") + track.isPlaying = true + track.duration = 0 + check(PlaybackClock.position(of: track, at: t0.addingTimeInterval(500)) == 530, "unknown duration: not bounded") + let nextTrack = NowPlaying(trackID: "spotify:track:2", title: "D", artist: "E", album: "F", artworkURL: nil, + duration: 180, position: 0, positionDate: t0.addingTimeInterval(100), isPlaying: true, + volume: 50, deviceName: nil, capabilities: track.capabilities) + check(PlaybackClock.position(of: nextTrack, at: t0.addingTimeInterval(100)) == 0, "track change: starts from 0") + check(PlaybackClock.format(65) == "1:05", "format 1:05 was \(PlaybackClock.format(65))") + check(PlaybackClock.format(754.9) == "12:34", "format rounds down") + check(PlaybackClock.format(3723) == "1:02:03", "format with hours") + check(PlaybackClock.format(-3) == "0:00", "format never negative") +} + +// SpotifyPlaybackInfo: the PlaybackStateChanged signal (spec §6.1). +do { + let t0 = Date(timeIntervalSince1970: 1_000) + let signal: [AnyHashable: Any] = [ + "Player State": "Playing", "Track ID": "spotify:track:42", "Name": "Midnight City", "Artist": "M83", + "Album": "Hurry Up, We're Dreaming", "Duration": NSNumber(value: 243_000), "Playback Position": NSNumber(value: 12.5), + ] + if case .track(let track) = SpotifyPlaybackInfo.parse(signal: signal, at: t0) { + check(track.trackID == "spotify:track:42" && track.title == "Midnight City" && track.artist == "M83", "signal: names") + check(track.duration == 243 && track.position == 12.5 && track.positionDate == t0 && track.isPlaying, "signal: timing") + check(track.artworkURL == nil && track.volume == nil && track.deviceName == nil, + "signal: no artwork or volume, this Mac") + check(track.capabilities == SpotifyPlaybackInfo.localCapabilities, "signal: local capabilities") + } else { + check(false, "signal with full info decodes to a track") + } + var paused = signal + paused["Player State"] = "Paused" + paused["Playback Position"] = nil + if case .track(let track) = SpotifyPlaybackInfo.parse(signal: paused, at: t0) { + check(!track.isPlaying && track.position == 0, "paused, no position: 0") + } else { + check(false, "paused signal decodes to a track") + } + check(SpotifyPlaybackInfo.parse(signal: ["Player State": "Stopped"], at: t0) == .stopped, "signal: stopped") + check(SpotifyPlaybackInfo.parse(signal: nil, at: t0) == .incomplete, "signal without userInfo: incomplete") + check(SpotifyPlaybackInfo.parse(signal: ["Player State": "Playing"], at: t0) == .incomplete, "signal without track id: incomplete") +} + +// SpotifyPlaybackInfo: the text SpotifyScript.readState returns (fields separated by U+001F). +do { + let t0 = Date(timeIntervalSince1970: 1_000) + let sep = "\u{1F}" + let text = ["paused", "spotify:track:7", "Title", "Artist", "Album", "180000", "61500", + "https://i.scdn.co/image/ab", "70"].joined(separator: sep) + if case .track(let track) = SpotifyPlaybackInfo.parse(scriptResult: text, at: t0) { + check(!track.isPlaying && track.duration == 180 && track.position == 61.5, "script: timing") + check(track.artworkURL == URL(string: "https://i.scdn.co/image/ab") && track.volume == 70, "script: artwork and volume") + check(track.title == "Title" && track.album == "Album" && track.positionDate == t0, "script: names") + } else { + check(false, "script result decodes to a track") + } + let local = ["playing", "spotify:local:x", "T", "", "", "1000", "0", "", "101"].joined(separator: sep) + if case .track(let track) = SpotifyPlaybackInfo.parse(scriptResult: local, at: t0) { + check(track.artworkURL == nil && track.volume == 100 && track.artist.isEmpty, "script: empty fields, volume clamped") + } else { + check(false, "script result with empty fields decodes to a track") + } + check(SpotifyPlaybackInfo.parse(scriptResult: "stopped", at: t0) == .stopped, "script: stopped") + check(SpotifyPlaybackInfo.parse(scriptResult: "garbage", at: t0) == .incomplete, "script: malformed") +} + +if failures > 0 { + print("LogicTests: \(failures) failure(s)") + exit(1) +} +print("LogicTests: all passed") diff --git a/Client/tests/ProtocolParsersTests.cpp b/Client/tests/ProtocolParsersTests.cpp new file mode 100644 index 0000000..5c356aa --- /dev/null +++ b/Client/tests/ProtocolParsersTests.cpp @@ -0,0 +1,80 @@ +#include "ProtocolParsers.h" +#include "CommandSerializer.h" +#include +#include + +// Minimal test runner (no framework). Exit code 1 on any failure. +static int failures = 0; +#define CHECK(cond) do { if (!(cond)) { failures++; std::printf("FAIL %s:%d: %s\n", __FILE__, __LINE__, #cond); } } while (0) + +static Buffer bytes(std::initializer_list values) +{ + Buffer b; + for (int v : values) b.push_back((char)v); + return b; +} + +int main() +{ + using namespace ProtocolParsers; + + // --- NC/ASM state --- + // WH-1000XM6 answer to the legacy 0x17 inquiry: all zeros = "not this channel". + CHECK(!parseNcAsmState(bytes({ 0x67, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00 })).has_value()); + // WH-1000XM6 notify on 0x19: Ambient Sound on, level 10, no voice focus. + { + auto s = parseNcAsmState(bytes({ 0x69, 0x19, 0x01, 0x01, 0x01, 0x00, 0x0a, 0x00, 0x00 })); + CHECK(s && s->enabled && s->ambient && !s->focusOnVoice && s->level == 10); + } + // WH-1000XM6 reply on 0x19: Noise Cancelling (ambient byte = 0). + { + auto s = parseNcAsmState(bytes({ 0x67, 0x19, 0x01, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x00 })); + CHECK(s && s->enabled && !s->ambient); + } + // Legacy 0x17 layout (WH-CH720N): effect off. + { + auto s = parseNcAsmState(bytes({ 0x67, 0x17, 0x01, 0x00, 0x00, 0x00, 0x01 })); + CHECK(s && !s->enabled); + } + CHECK(!parseNcAsmState(bytes({ 0x67, 0x17, 0x01 })).has_value()); // too short + CHECK(!parseNcAsmState(bytes({ 0x57, 0x17, 0x01, 0x01, 0x01, 0x00, 0x0a })).has_value()); // wrong opcode + + // --- Equalizer --- + // WH-1000XM6: unknown preset 0x30, 10 bands (offset +10 hypothesis, spec §7). + { + auto e = parseEqualizer(bytes({ 0x57, 0x00, 0x30, 0x0a, 0x0a, 0x0a, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 })); + CHECK(e && e->preset == 0x30 && !e->hasClearBass && e->bands.size() == 10); + CHECK(e && e->bands[0] == 0 && e->bands[2] == -5 && e->bands[9] == -4); + } + // 5 bands + Clear Bass (WH-CH720N): Manual, bass +3, bands -2..+2. + { + auto e = parseEqualizer(bytes({ 0x57, 0x00, 0xa0, 0x06, 13, 8, 9, 10, 11, 12 })); + CHECK(e && e->preset == 0xa0 && e->hasClearBass && e->clearBass == 3); + CHECK(e && e->bands == std::vector({ -2, -1, 0, 1, 2 })); + } + // Preset only, no band data. + { + auto e = parseEqualizer(bytes({ 0x57, 0x00, 0x16 })); + CHECK(e && e->preset == 0x16 && e->bands.empty()); + } + CHECK(!parseEqualizer(bytes({ 0x23, 0x00, 0x44, 0x00 })).has_value()); // battery reply + + // --- Framing --- + // Round trip, with a payload byte (0x3c = END_MARKER) that must be escaped. + { + Buffer payload = bytes({ 0x68, 0x17, 0x01, 0x01, 0x01, 0x00, 0x3c }); + auto frame = CommandSerializer::packageDataForBt(payload, DATA_TYPE::DATA_MDR, 1); + CHECK(frame.front() == START_MARKER && frame.back() == END_MARKER); + auto msg = CommandSerializer::unpackBtMessage(Buffer(frame.begin() + 1, frame.end() - 1)); + CHECK(msg.dataType == DATA_TYPE::DATA_MDR && msg.seqNumber == 1 && msg.payload == payload); + } + // Real WH-1000XM6 battery frame (68 %), between the 3e/3c markers. + { + auto msg = CommandSerializer::unpackBtMessage(bytes({ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x04, 0x23, 0x00, 0x44, 0x00, 0x77 })); + CHECK(msg.payload == bytes({ 0x23, 0x00, 0x44, 0x00 })); + } + + if (failures) { std::printf("ProtocolParsersTests: %d failure(s)\n", failures); return 1; } + std::printf("ProtocolParsersTests: all passed\n"); + return 0; +} diff --git a/Client/windows/WindowsBluetoothConnector.cpp b/Client/windows/WindowsBluetoothConnector.cpp deleted file mode 100644 index 6967f36..0000000 --- a/Client/windows/WindowsBluetoothConnector.cpp +++ /dev/null @@ -1,238 +0,0 @@ -#include "WindowsBluetoothConnector.h" - -void WSAStartupWrapper() -{ - int iResult; - WSADATA wsaData; - iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); - if (iResult != 0) { - throw std::runtime_error("WSAStartup failed: " + std::to_string(iResult)); - } -} - -WindowsBluetoothConnector::WindowsBluetoothConnector() -{ - static bool startedUp = false; - if (!startedUp) - { - ::WSAStartupWrapper(); - startedUp = true; - } -} - -bool WindowsBluetoothConnector::_tryConnect(const char* uuid, SOCKADDR_BTH& sab) -{ - RPC_STATUS errCode = ::UuidFromStringA((RPC_CSTR)uuid, &sab.serviceClassId); - if (errCode != RPC_S_OK) - { - throw std::runtime_error("Couldn't create GUID: " + std::to_string(errCode)); - } - return ::connect(this->_socket, (sockaddr*)&sab, sizeof(sab)) == 0; -} - -void WindowsBluetoothConnector::connect(const std::string& addrStr) -{ - if (this->_socket == INVALID_SOCKET) - { - this->_initSocket(); - } - - SOCKADDR_BTH sab = { 0 }; - sab.addressFamily = AF_BTH; - sab.btAddr = MACStringToLong(addrStr); - - // try the v1 service UUID first, then fall back to the v2 (newer-generation) UUID. - if (_tryConnect(SONY_UUID, sab)) - { - this->_protocolVersion = SonyProtocolVersion::V1; - this->_connected = true; - return; - } - - // A failed connect() can leave the socket unusable - recreate it before trying the v2 UUID. - ::closesocket(this->_socket); - this->_socket = INVALID_SOCKET; - this->_initSocket(); - - if (_tryConnect(SONY_UUID_V2, sab)) - { - this->_protocolVersion = SonyProtocolVersion::V2; - this->_connected = true; - return; - } - - throw RecoverableException("Couldn't connect: " + std::to_string(WSAGetLastError()), true); -} - -WindowsBluetoothConnector::~WindowsBluetoothConnector() -{ - if (this->_socket != INVALID_SOCKET) - { - ::closesocket(this->_socket); - } -} - -int WindowsBluetoothConnector::send(char* buf, size_t length) -{ - auto bytesSent = ::send(this->_socket, buf, length, 0); - if (bytesSent == SOCKET_ERROR) - { - throw RecoverableException("Couldn't send (" + std::to_string(WSAGetLastError()) + ")", true); - } - return bytesSent; -} - -int WindowsBluetoothConnector::recv(char* buf, size_t length) -{ - auto bytesReceived = ::recv(this->_socket, buf, length, 0); - if (bytesReceived == SOCKET_ERROR) - { - int err = WSAGetLastError(); - // A recv timeout is expected during capability probing - surface it as recoverable WITHOUT forcing a - // disconnect, so an unanswered optional-feature GET just hides that feature instead of dropping the link. - if (err == WSAETIMEDOUT) - { - throw RecoverableException("recv timed out", false); - } - throw RecoverableException("Couldn't recv (" + std::to_string(err) + ")", true); - } - return bytesReceived; -} - -std::vector WindowsBluetoothConnector::getConnectedDevices() -{ - std::vector res; - std::vector devsInRadio; - - HANDLE radio = NULL; - BLUETOOTH_FIND_RADIO_PARAMS radioSearchParams = { sizeof(BLUETOOTH_FIND_RADIO_PARAMS) }; - HBLUETOOTH_RADIO_FIND radioFindHandle = NULL; - - // Search only for connected devices - BLUETOOTH_DEVICE_SEARCH_PARAMS dev_search_params = { - sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS), 0, 0, 0, 1, 0, 15, NULL - }; - - // Iterate for available bluetooth radio devices - radioFindHandle = BluetoothFindFirstRadio(&radioSearchParams, &radio); - if (!radioFindHandle) - { - if (ERROR_NO_MORE_ITEMS == GetLastError()) - { - throw RecoverableException(NO_BLUETOOTH_DEVICES_ERROR); - } - else - { - throw std::runtime_error("BluetoothFindFirstRadio() failed with error code " + std::to_string(GetLastError())); - } - } - - do { - dev_search_params.hRadio = radio; - devsInRadio = _findDevicesInRadio(&dev_search_params); - res.insert(res.end(), devsInRadio.begin(), devsInRadio.end()); - } while (BluetoothFindNextRadio(radioFindHandle, &radio)); - - // No more radio, close the radio handle - if (!BluetoothFindRadioClose(radioFindHandle)) - throw std::runtime_error("BluetoothFindRadioClose(bt) failed with error code " + std::to_string(GetLastError())); - - return res; -} - -void WindowsBluetoothConnector::disconnect() noexcept -{ - if (this->_socket != INVALID_SOCKET) - { - this->_connected = false; - shutdown(this->_socket, SD_BOTH); - closesocket(this->_socket); - this->_socket = INVALID_SOCKET; - } -} - -bool WindowsBluetoothConnector::isConnected() noexcept -{ - return this->_connected; -} - -SonyProtocolVersion WindowsBluetoothConnector::getProtocolVersion() noexcept -{ - return this->_protocolVersion; -} - -void WindowsBluetoothConnector::_initSocket() -{ - SOCKET sock = ::socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); - if (sock == INVALID_SOCKET) - { - throw std::runtime_error("Couldn't create socket: " + std::to_string(WSAGetLastError())); - } - - ULONG enable = TRUE; - if (::setsockopt(sock, SOL_RFCOMM, SO_BTH_AUTHENTICATE, reinterpret_cast(&enable), sizeof(enable))) - { - throw std::runtime_error("Couldn't set SO_BTH_AUTHENTICATE: " + std::to_string(WSAGetLastError())); - } - - if (::setsockopt(sock, SOL_RFCOMM, SO_BTH_ENCRYPT, reinterpret_cast(&enable), sizeof(enable))) - { - throw std::runtime_error("Couldn't set SO_BTH_ENCRYPT: " + std::to_string(WSAGetLastError())); - } - - // Bound recv so it can't block forever. Capability probing sends a GET and relies on this timeout to - // decide a feature is unsupported - without it the app hangs on "Reading device settings" (matches the - // 2.5s timeout the macOS connector uses). - DWORD recvTimeoutMs = 2500; - ::setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast(&recvTimeoutMs), sizeof(recvTimeoutMs)); - - this->_socket = sock; -} - -std::string WindowsBluetoothConnector::_wstringToUtf8(const std::wstring& wstr) -{ - std::string strTo; - const int num_chars = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), NULL, 0, NULL, NULL); - - if (num_chars > 0) - { - strTo.resize(num_chars); - WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), &strTo[0], num_chars, NULL, NULL); - } - return strTo; -} - -std::vector WindowsBluetoothConnector::_findDevicesInRadio(BLUETOOTH_DEVICE_SEARCH_PARAMS* search_params) -{ - std::vector res; - - BLUETOOTH_DEVICE_INFO device_info = { sizeof(BLUETOOTH_DEVICE_INFO),0, }; - HBLUETOOTH_DEVICE_FIND dev_find_handle = NULL; - - // For each radio, get the first device - dev_find_handle = BluetoothFindFirstDevice(search_params, &device_info); - - if (!dev_find_handle) - { - if (ERROR_NO_MORE_ITEMS == GetLastError()) - { - //No devices were found, so we can just return an empty vector - return res; - } - else - { - throw std::runtime_error("BluetoothFindFirstDevice() failed with error code: " + std::to_string(GetLastError())); - } - } - - // Get the device info - do { - res.emplace_back(BluetoothDevice{ _wstringToUtf8(device_info.szName), MACBytesToString(device_info.Address.rgBytes) }); - } while (BluetoothFindNextDevice(dev_find_handle, &device_info)); - - // NO more device, close the device handle - if (!BluetoothFindDeviceClose(dev_find_handle)) - throw std::runtime_error("BluetoothFindDeviceClose(bt_dev) failed with error code: " + std::to_string(GetLastError())); - - return res; -} diff --git a/Client/windows/WindowsBluetoothConnector.h b/Client/windows/WindowsBluetoothConnector.h deleted file mode 100644 index 824b8e1..0000000 --- a/Client/windows/WindowsBluetoothConnector.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once -#include -#pragma comment(lib, "ws2_32.lib") -#pragma comment(lib, "rpcrt4.lib") -#pragma comment(lib, "Bthprops.lib") -#include -#include -#include -#include -#include -#include "IBluetoothConnector.h" -#include -#include "ByteMagic.h" -#include - -class WindowsBluetoothConnector final : public IBluetoothConnector -{ -public: - WindowsBluetoothConnector(); - - ~WindowsBluetoothConnector(); - - virtual void connect(const std::string& addrStr) noexcept(false); - virtual int send(char* buf, size_t length) noexcept(false); - virtual int recv(char* buf, size_t length) noexcept(false); - virtual void disconnect() noexcept; - virtual bool isConnected() noexcept; - - virtual std::vector getConnectedDevices() noexcept(false); - virtual SonyProtocolVersion getProtocolVersion() noexcept; - -private: - std::vector _findDevicesInRadio(BLUETOOTH_DEVICE_SEARCH_PARAMS* searchParams); - std::string _wstringToUtf8(const std::wstring& wstr); - bool _tryConnect(const char* uuid, SOCKADDR_BTH& sab); - - SOCKET _socket = INVALID_SOCKET; - std::atomic _connected = false; - SonyProtocolVersion _protocolVersion = SonyProtocolVersion::V1; - void _initSocket(); -}; \ No newline at end of file diff --git a/Client/windows/WindowsGUI.cpp b/Client/windows/WindowsGUI.cpp deleted file mode 100644 index 82c9989..0000000 --- a/Client/windows/WindowsGUI.cpp +++ /dev/null @@ -1,197 +0,0 @@ -#include "WindowsGUI.h" - -/* -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -A notice to any future readers: -This code is almost all copied from imgui/examples/example_win32_directx11. -Don't try to understand it. -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -*/ - -// Data -static ID3D11Device* g_pd3dDevice = NULL; -static ID3D11DeviceContext* g_pd3dDeviceContext = NULL; -static IDXGISwapChain* g_pSwapChain = NULL; -static ID3D11RenderTargetView* g_mainRenderTargetView = NULL; - -void EnterGUIMainLoop(BluetoothWrapper bt) -{ - //Kinda broken but it works :) - ShowWindow(GetConsoleWindow(), SW_HIDE); //SW_RESTORE to bring back - - // Create application window - WNDCLASSEXW wc = { sizeof(WNDCLASSEXW), CS_CLASSDC, WindowsGUIInternal::WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, APP_NAME_W, NULL }; - ::RegisterClassExW(&wc); - //TODO: pass window data (size, name, etc) as params and autoscale - HWND hwnd = ::CreateWindowW(wc.lpszClassName, APP_NAME_W, WS_OVERLAPPEDWINDOW, 100, 100, GUI_WIDTH, GUI_HEIGHT, NULL, NULL, wc.hInstance, NULL); - - // Initialize Direct3D - if (!WindowsGUIInternal::CreateDeviceD3D(hwnd)) - { - WindowsGUIInternal::CleanupDeviceD3D(); - ::UnregisterClassW(wc.lpszClassName, wc.hInstance); - throw std::runtime_error("Failed to create D3D device"); - } - - // Show the window - ::ShowWindow(hwnd, SW_SHOWDEFAULT); - ::UpdateWindow(hwnd); - - // Setup Dear ImGui context - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - - //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - - // Setup Platform/Renderer bindings - ImGui_ImplWin32_Init(hwnd); - ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext); - - CrossPlatformGUI gui(std::move(bt)); - - UINT presentFlags = 0; - - // Main loop - MSG msg = { 0 }; - while (msg.message != WM_QUIT) - { - // Poll and handle messages (inputs, window resize, etc.) - // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. - // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. - - if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) - { - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); - continue; - } - - // Start the Dear ImGui frame - ImGui_ImplDX11_NewFrame(); - ImGui_ImplWin32_NewFrame(); - - //if the user wants to quit - if (!gui.performGUIPass()) - { - break; - } - - - g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL); - g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, (float*)&WINDOW_COLOR); - ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); - - //We need this because Present doesn't delay when the app is minimized. - if (g_pSwapChain->Present(1, presentFlags) == DXGI_STATUS_OCCLUDED) { - presentFlags = DXGI_PRESENT_TEST; - //Artificial VSYNC when the app is minimized - Sleep(MS_PER_FRAME); - } - else { - presentFlags = 0; - } - } - - // Cleanup - ImGui_ImplDX11_Shutdown(); - ImGui_ImplWin32_Shutdown(); - ImGui::DestroyContext(); - - WindowsGUIInternal::CleanupDeviceD3D(); - ::DestroyWindow(hwnd); - ::UnregisterClassW(wc.lpszClassName, wc.hInstance); -} - -void DisplayErrorMessagebox(const std::string& message) -{ - MessageBoxA(0, message.c_str(), "Sony Headphones Client | Unrecoverable Error", MB_OK | MB_ICONSTOP); - exit(GetLastError()); -} - -namespace WindowsGUIInternal -{ - - bool CreateDeviceD3D(HWND hWnd) - { - // Setup swap chain - DXGI_SWAP_CHAIN_DESC sd; - ZeroMemory(&sd, sizeof(sd)); - sd.BufferCount = 2; - sd.BufferDesc.Width = 0; - sd.BufferDesc.Height = 0; - sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - sd.BufferDesc.RefreshRate.Numerator = 60; - sd.BufferDesc.RefreshRate.Denominator = 1; - sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; - sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - sd.OutputWindow = hWnd; - sd.SampleDesc.Count = 1; - sd.SampleDesc.Quality = 0; - sd.Windowed = TRUE; - sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - - UINT createDeviceFlags = 0; - //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; - D3D_FEATURE_LEVEL featureLevel; - const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, }; - if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK) - return false; - - CreateRenderTarget(); - return true; - } - - void CleanupDeviceD3D() - { - CleanupRenderTarget(); - if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; } - if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; } - if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } - } - - void CreateRenderTarget() - { - ID3D11Texture2D* pBackBuffer = nullptr; - g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); - if (pBackBuffer == nullptr) - { - throw std::runtime_error("Unexpected: pBackBuffer is null"); - } - g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView); - pBackBuffer->Release(); - } - - void CleanupRenderTarget() - { - if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = NULL; } - } - - // Win32 message handler - LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) - { - if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) - return true; - - switch (msg) - { - case WM_SIZE: - if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED) - { - CleanupRenderTarget(); - g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0); - CreateRenderTarget(); - } - return 0; - case WM_SYSCOMMAND: - if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu - return 0; - break; - case WM_DESTROY: - ::PostQuitMessage(0); - return 0; - } - return ::DefWindowProc(hWnd, msg, wParam, lParam); - } -} diff --git a/Client/windows/WindowsGUI.h b/Client/windows/WindowsGUI.h deleted file mode 100644 index b4be8e4..0000000 --- a/Client/windows/WindowsGUI.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include - -//The inclusion order is critical here. Do not change it. -#include "BluetoothWrapper.h" -#include "WindowsBluetoothConnector.h" - -#include "Constants.h" - -#include "imgui/imgui.h" -#include "imgui/backends/imgui_impl_win32.h" -#include "imgui/backends/imgui_impl_dx11.h" -#include -#define DIRECTINPUT_VERSION 0x0800 -#include -#include - -#include - -#include "Windows.h" - -#include "CrossPlatformGUI.h" - -// Forward declare message handler from imgui_impl_win32.cpp -extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - -void EnterGUIMainLoop(BluetoothWrapper bt); -void DisplayErrorMessagebox(const std::string& message); - -namespace WindowsGUIInternal -{ - bool CreateDeviceD3D(HWND hWnd); - void CleanupDeviceD3D(); - void CreateRenderTarget(); - void CleanupRenderTarget(); - LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); -} diff --git a/Client/windows/main.cpp b/Client/windows/main.cpp deleted file mode 100644 index fd24871..0000000 --- a/Client/windows/main.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include "WindowsBluetoothConnector.h" -#include "CommandSerializer.h" -#include "BluetoothWrapper.h" - -#include "WindowsGUI.h" - -int main() -{ - std::cout << "Initializing... If can't see the GUI, something has gone wrong." << std::endl; - try - { - std::unique_ptr connector = std::make_unique(); - BluetoothWrapper wrap(std::move(connector)); - EnterGUIMainLoop(std::move(wrap)); - } - catch (const std::exception& e) - { - DisplayErrorMessagebox(e.what()); - } -} - diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cf99bb9 --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +# SonyNotch — build without Xcode. See scripts/build.sh for the knobs. +DEBUG ?= 0 + +.PHONY: all build run test release install clean + +all: build + +build: + DEBUG_PROTOCOL=$(DEBUG) ./scripts/build.sh + +LOG_FILE := $(HOME)/Library/Logs/SonyNotch/app.log + +run: build + -pkill -x SonyNotch; while pgrep -x SonyNotch >/dev/null; do sleep 0.2; done + @mkdir -p "$(dir $(LOG_FILE))" + @ln -sfn "$(LOG_FILE)" "$(CURDIR)/build/app.log" + @echo "=== SonyNotch session $$(date '+%Y-%m-%d %H:%M:%S') ===" >> "$(LOG_FILE)" + open "$(CURDIR)/build/SonyNotch.app" --args -SonyNotchLogFile "$(LOG_FILE)" + +test: + ./scripts/test.sh + +release: + CONFIG=release ARCHS="arm64 x86_64" ./scripts/build.sh + cd build && rm -f SonyNotch.zip && ditto -c -k --keepParent SonyNotch.app SonyNotch.zip + +install: release + -pkill -x SonyNotch; while pgrep -x SonyNotch >/dev/null; do sleep 0.2; done + -pkill -x SonyBridge; rm -rf "/Applications/SonyBridge.app" # the app's former name + rm -rf "/Applications/SonyNotch.app" + ditto "$(CURDIR)/build/SonyNotch.app" "/Applications/SonyNotch.app" + open "/Applications/SonyNotch.app" + +clean: + rm -rf build diff --git a/README.md b/README.md index a67afb1..a562ba2 100644 --- a/README.md +++ b/README.md @@ -1,219 +1,158 @@ -
+# SonyNotch -SonyBridge +Control your Sony headphones from your Mac, right from the menu bar and the notch. No phone app needed. -
+SonyNotch switches noise cancelling and ambient sound, sets the equalizer and shows the battery of your Sony +Bluetooth headphones. It also turns the MacBook notch into a small player for the music playing in Spotify. -**An unofficial, open-source desktop app for Sony headphones — Noise Cancelling, Ambient Sound, EQ, DSEE and battery, without the phone.** +## Install -
+1. Download **SonyNotch.zip** from the [latest release](https://github.com/flotttt/SonyNotch/releases/latest) +2. Open the zip and drag **SonyNotch** into your Applications folder +3. Open SonyNotch. The first time, macOS says it can't check the app because it isn't signed with an Apple + developer account yet. Click Done, then go to System Settings › Privacy & Security, scroll down and click + **Open Anyway** -[![Build](https://github.com/AmitRajput-Dev/SonyBridge/actions/workflows/cmake.yml/badge.svg)](https://github.com/AmitRajput-Dev/SonyBridge/actions/workflows/cmake.yml) -[![Release](https://img.shields.io/github/v/release/AmitRajput-Dev/SonyBridge?include_prereleases&sort=semver)](https://github.com/AmitRajput-Dev/SonyBridge/releases) -[![Downloads](https://img.shields.io/github/downloads/AmitRajput-Dev/SonyBridge/total?color=success)](https://github.com/AmitRajput-Dev/SonyBridge/releases) -[![Stars](https://img.shields.io/github/stars/AmitRajput-Dev/SonyBridge?style=flat)](https://github.com/AmitRajput-Dev/SonyBridge/stargazers) -[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE) -![Platforms](https://img.shields.io/badge/platform-macOS%20%7C%20Windows%20%7C%20Linux-blue) +SonyNotch then appears in the menu bar. Allow Bluetooth access when macOS asks, and allow SonyNotch to control +Spotify for the notch player. -
+If your headphones aren't connected to the Mac yet, pair them in System Settings › Bluetooth first. -[![Download for macOS](https://img.shields.io/badge/Download-macOS-000000?style=for-the-badge&logo=apple&logoColor=white)](https://github.com/AmitRajput-Dev/SonyBridge/releases/latest) -[![Windows Beta](https://img.shields.io/badge/Windows-Beta-0078D6?style=for-the-badge&logo=windows11&logoColor=white)](https://github.com/AmitRajput-Dev/SonyBridge/releases/tag/v0.4.0-beta1) -[![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-EA4AAA?style=for-the-badge&logo=githubsponsors&logoColor=white)](https://github.com/sponsors/AmitRajput-Dev) -[![Donate via Razorpay](https://img.shields.io/badge/Donate-Razorpay-3395FF?style=for-the-badge&logo=razorpay&logoColor=white)](https://razorpay.me/@amitpratapsingrajput) +Works on macOS 13 or later, on Apple Silicon and Intel Macs. -
+## Update -**[Features](#-features)** · **[Download](#-download)** · **[How it works](#-how-it-works)** · **[Contributing](#-contributing)** · **[Credits](#-credits)** +Download the new SonyNotch.zip from the [latest release](https://github.com/flotttt/SonyNotch/releases/latest), +quit SonyNotch and replace the app in Applications. Your settings are kept. macOS may ask for the Bluetooth and +Spotify permissions again. -
+## Uninstall -SonyBridge connected to a WH-CH720N -   -SonyBridge disconnected state +If you turned on Launch at Login, turn it off first. Then quit SonyNotch and move it to the Trash. -
+## What it does ---- +### Menu bar -## Why +Click the headphones icon in the menu bar to: -Sony locks headphone settings behind their mobile-only *Sound Connect* app. If you live on a laptop, -you're stuck. SonyBridge talks to the headphones directly over Bluetooth RFCOMM using Sony's -reverse-engineered binary protocol — no phone required. +- switch between Noise Cancelling, Ambient Sound and Off, and set the ambient level and Focus on Voice +- pick an equalizer preset or make your own (read only on the WH-1000XM6 for now) +- turn DSEE, Speak-to-Chat and Adaptive Volume on or off, and set Auto Power-Off, when your model has them +- see the battery level, for each earbud and the case on true wireless models +- see the firmware, codec and Bluetooth address in About the Headphones -The original [SonyHeadphonesClient](https://github.com/Plutoberth/SonyHeadphonesClient) only spoke Sony's -**first-generation** protocol, so newer headsets (WH-CH720N, XM4/XM5, WF-series, LinkBuds…) just timed -out on connect. SonyBridge adds full **second-generation ("v2") protocol** support, a native SwiftUI app -on macOS, and a matching modern UI on Windows/Linux. +The icon shows the current sound mode and follows the NC button on your headphones. SonyNotch connects on its +own when the headphones join the Mac, reconnects if the link drops, and can launch at login. It's available in +English and French. -## ✨ Features +### Notch -- 🎚️ **Ambient Sound Control** — Noise Cancelling · Ambient Sound (0–20 levels) · Off -- 🗣️ **Focus on Voice** passthrough -- 🎛️ **Equalizer** — presets *and* a full **Manual mode** with 5 bands + Clear Bass -- ✨ **DSEE** — Sony's audio upscaling for compressed sources -- 🔋 **Battery level** — live percentage, including **per-earbud + case** for TWS models -- 🎧 **Codec & firmware** readout -- 🧩 **Capability-gated extras** — Auto Power-Off · Speak-to-Chat · Adaptive Volume (only shown when your device supports them) -- 🖼️ **Device hero image** — your headphones' official Sony product render -- 🔄 **Live button sync** — changes made on the headset reflect in the app -- 🔌 **Auto-connect** to your already-paired Sony headset -- 🧬 **Dual-protocol** — auto-detects and speaks either protocol generation -- 🌑 **Modern UI** — dark, minimal, shaped after Sony's own app (SwiftUI on macOS, Dear ImGui on Windows/Linux) +Move the pointer over the notch and it opens into a player with: -## 📥 Download +- the artwork, title and artist +- a progress bar you can click or drag +- previous, play/pause and next +- a volume button for Spotify's volume +- a headphones button to change the sound mode without opening the menu - - - - - - - - - - - - - - - - - - - -
PlatformGet itNotes
macOS +When the notch is closed, it shows the album artwork and little bars that move with the music. Hover the bars +to skip to the next track, or to resume the music when it's paused. -`brew tap AmitRajput-Dev/tap && brew install --cask sonybridge` +To change its size, open the menu and go to SonyNotch Options › Notch Size. You can set the width and height, +the size of the closed notch, the artwork and the text. You see the result live and it's saved. To hide the +notch, turn off Show Notch in the same menu. -or [**Download .app**](https://github.com/AmitRajput-Dev/SonyBridge/releases/latest) +The player works with the Spotify app for Mac, without any account or login. On a screen without a notch, it +shows up as a black pill at the top of the screen. -macOS 11+ · Apple Silicon & Intel
Windows +## Supported headphones -[**Download Beta**](https://github.com/AmitRajput-Dev/SonyBridge/releases/tag/v0.4.0-beta1) +| | Models | +|---|---| +| Tested | WH-1000XM6, WH-CH720N, ULT WEAR (WH-ULT900N) | +| Should work | WH-1000XM5, WH-XB910N, WH-CH520 | +| Earbuds, controls work but battery may not | WF-1000XM4, WF-1000XM5, WF-C700N, LinkBuds S | +| Older models, sound modes only | WH-1000XM4, WH-1000XM3, WH-1000XM2, WH-XB900N, MDR-XB950BT | -🧪 Beta — testers wanted
Linux +If you try a model that isn't tested, please [open an issue](https://github.com/flotttt/SonyNotch/issues/new) +and say how it went. -[Build from source](#-build-from-source) +## Troubleshooting -GLFW/OpenGL build
+**macOS won't open the app.** Go to System Settings › Privacy & Security and click Open Anyway, as in the +install steps. -> 💡 After launching, **connect your headphones in your OS Bluetooth settings first**, then open SonyBridge and hit *Connect*. Keep audio playing — Sony headsets drop the control link when idle to save power. +**The headphones aren't found.** Connect them in System Settings › Bluetooth, then click Connect in the +SonyNotch menu. -
-macOS install notes (Gatekeeper) +**Nothing happens after opening the app.** Check that SonyNotch is allowed in System Settings › Privacy & +Security › Bluetooth. -The app is ad-hoc signed (not notarized — no paid Apple Developer account). The Homebrew cask clears the -quarantine flag for you. For a direct download, allow it once: +**The notch says SonyNotch isn't allowed to control Spotify.** Click Open Settings and turn on Spotify under +Automation › SonyNotch. -```sh -xattr -dr com.apple.quarantine /Applications/SonyBridge.app -``` - -…or right-click the app → **Open** → **Open**. Homebrew also asks you to trust the third-party tap the -first time (`brew trust AmitRajput-Dev/tap`). -
+**The menu bar icon is missing.** When the menu bar is full, macOS hides icons behind the notch. Quit or hide a +few other menu bar apps. -## 🎧 Supported headphones +**The controls stopped responding.** Click Disconnect then Connect in the menu, or turn the headphones off and +on. -| Status | Devices | -|--------|---------| -| ✅ **Verified** | WH-CH720N, Sony ULT WEAR (WH-ULT900N) | -| 🟢 **Expected** (v2, over-ear — NC/Ambient/battery/EQ) | WH-1000XM5, WH-1000XM6, WH-XB910N, WH-CH520 | -| 🟡 **v2 earbuds** (controls work; battery format differs) | WF-1000XM4, WF-1000XM5, WF-C700N, LinkBuds S | -| 🔵 **Legacy** (v1 protocol — NC/Ambient only) | WH-1000XM4, WH-1000XM3, WH-1000XM2, WH-XB900N, MDR-XB950BT | +## For developers -> Only the WH-CH720N is fully hardware-verified. Others share the same protocol family, so the basics -> should work — per-model quirks are untested. Reports and PRs for other devices are very welcome. +### Build from source -## 🚀 Build from source - -
-macOS (native SwiftUI app) - -Requires **Xcode 14+**. +You need Apple's Command Line Tools (`xcode-select --install`). The full Xcode app isn't required. ```sh -git clone --recurse-submodules https://github.com/AmitRajput-Dev/SonyBridge.git -open SonyBridge/Client/macos/SonyHeadphonesClient.xcodeproj +git clone https://github.com/flotttt/SonyNotch.git +cd SonyNotch +make install # build and install to Applications +make run # build and launch, add DEBUG=1 to log the Bluetooth traffic +make test # unit tests and translation check +make release # universal build zipped in build/SonyNotch.zip ``` -Then ⌘R. -
+Logs go to `~/Library/Logs/SonyNotch/app.log`. Launch the app with `open`, Finder or `make`, not by running the +binary inside the bundle, or macOS closes it when it first uses Bluetooth. -
-Windows / Linux (Dear ImGui UI) +The app is written in Swift with AppKit and SwiftUI, on top of a C++ core for the headphones protocol. The code +is in `Client/`, and the notch is in `Client/macos/Notch` and `Client/macos/Music`. -**Windows** (CMake + MSVC, from a Developer Command Prompt): -```sh -cd Client && mkdir build && cd build -cmake .. && cmake --build . --config Release -``` +### Publish a release + +Push a version tag. GitHub Actions runs the tests, builds the app with that version number and attaches +SonyNotch.zip to the release. -**Linux** (`sudo apt install libbluetooth-dev libglfw3-dev libdbus-1-dev`): ```sh -cd Client && mkdir build && cd build -cmake .. && cmake --build . +git tag v1.1.0 +git push origin v1.1.0 ``` -Keep the built binary next to its `resources/` folder (device hero images load from `resources/devices/`). -
- -## 🔬 How it works +### How it talks to the headphones -Sony headphones expose a vendor RFCOMM/SPP service. Commands are framed as: +Sony headphones expose a Bluetooth serial (RFCOMM) service and accept small binary frames: ``` - ESCAPE( <4-byte BE length> ) +<0x3e> escaped( type, sequence, 4-byte length, payload, checksum ) <0x3c> ``` -Two protocol generations exist, distinguished by their SDP service UUID: - -- **v1** — `96CC203E-…` — WH-1000XM3 and older -- **v2** — `956C7B26-…` — WH-CH720N, Sony ULT WEAR, XM4/XM5, WF-series, LinkBuds… - -SonyBridge tries v1 first, falls back to v2, and remembers which succeeded. The v2 path adds the mandatory -init handshake and per-frame host-ACK the newer devices require, plus battery, EQ and DSEE inquiry commands. -Protocol byte layouts were cross-referenced against -[**GadgetBridge**](https://codeberg.org/Freeyourgadget/Gadgetbridge)'s Sony implementation. - -## 🤝 Contributing - -Contributions are very welcome — especially **device reports** and **testing on real hardware**. - -- 🐛 **Found a bug / have a device to report?** [Open an issue](https://github.com/AmitRajput-Dev/SonyBridge/issues/new) with your model and what happened. -- 🧪 **Want to test?** Grab a [release](https://github.com/AmitRajput-Dev/SonyBridge/releases) and tell us how it behaves on your headset (a screenshot helps a lot). -- 🔧 **Code?** Fork, branch, and open a PR against `main`. CI builds macOS, Windows and Linux on every PR. - -## 🙏 Credits - -SonyBridge builds directly on the work of: - -- [**SonyHeadphonesClient**](https://github.com/Plutoberth/SonyHeadphonesClient) by Plutoberth, Mr-M33533K5 & contributors — the original cross-platform client and protocol foundation -- [**semvis123**](https://github.com/semvis123) — the original macOS port -- [**GadgetBridge**](https://codeberg.org/Freeyourgadget/Gadgetbridge) — reverse-engineered v2 protocol reference - -**Community contributors & testers:** - -- [**@CrisProCrack**](https://github.com/CrisProCrack) — WH-1000XM4 (v1) connect fix -- [**@Sebsdnl**](https://github.com/Sebsdnl) — Linux/Wayland crash fix & ULT WEAR support -- **u/More_Way_6784**, **@joelslaby** — WH-1000XM4 hardware testing - -## ❤️ Support - -If SonyBridge is useful to you, consider supporting it — it keeps the reverse-engineering going: +Headphones up to the WH-1000XM4 use a first version of this protocol, newer ones use a second. SonyNotch +detects which one when it connects. The byte layouts were checked against the Sony support in +[Gadgetbridge](https://codeberg.org/Freeyourgadget/Gadgetbridge). -- 🌍 [**GitHub Sponsors**](https://github.com/sponsors/AmitRajput-Dev) — worldwide (cards, one-off or monthly) -- 🇮🇳 [**Razorpay / UPI**](https://razorpay.me/@amitpratapsingrajput) — for supporters in India +For the notch, Spotify posts a system notification on every playback change, and SonyNotch asks the app for +the artwork and volume with AppleScript. Nothing is polled while the notch is closed. -Starring the repo helps too. ⭐ +## Origins -## ⚠️ Disclaimer +SonyNotch started as a fork of [AmitRajput-Dev/SonyBridge](https://github.com/AmitRajput-Dev/SonyBridge), +which builds on [SonyHeadphonesClient](https://github.com/Plutoberth/SonyHeadphonesClient) by Plutoberth, +semvis123 and their contributors. It has since been renamed and largely rewritten. -This project is **not affiliated with, endorsed by, or connected to Sony**. It talks to your headphones -using a reverse-engineered protocol, for interoperability. Use at your own risk. +SonyNotch isn't affiliated with or endorsed by Sony. It uses a reverse engineered protocol, so use it at your +own risk. -## 📄 License +## License -[MIT](LICENSE) — original copyright retained; see [Credits](#-credits). +MIT, see [LICENSE](LICENSE). The original copyright notice is kept as the license requires. diff --git a/docs/banner.svg b/docs/banner.svg deleted file mode 100644 index b881b79..0000000 --- a/docs/banner.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - SonyBridge - Control your Sony headphones from your desktop. - - - - macOS - - Windows - - Linux - - diff --git a/docs/connected.png b/docs/connected.png deleted file mode 100644 index f5766a0..0000000 Binary files a/docs/connected.png and /dev/null differ diff --git a/docs/disconnected.png b/docs/disconnected.png deleted file mode 100644 index c1d518e..0000000 Binary files a/docs/disconnected.png and /dev/null differ diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index d626c20..0000000 --- a/docs/index.html +++ /dev/null @@ -1,442 +0,0 @@ - - - - - -SonyBridge — Control your Sony headphones from your desktop - - - - - - - - - - - - - - -
- - - -
-
- -
-
- Open-source · macOS · Windows · Linux -

Your Sony headphones,
finally on your desktop.

-

Noise cancelling, ambient sound, EQ, DSEE and battery — controlled straight from your Mac or PC. No phone, no Sony account.

- -
- $brew install --cask sonybridge - -
-
MIT licensed · builds on the community SonyHeadphonesClient
-
-
-
-
SonyBridge connected to a WH-CH720N, showing noise-cancelling and ambient controls
-
-
-
- -
-
    -
  • WH-1000XM4
  • WH-1000XM5
  • WH-1000XM6
  • WH-CH720N
  • -
  • WF-1000XM5
  • ULT WEAR
  • WF-C700N
  • LinkBuds S
  • -
  • WH-XB910N
  • WH-CH520
  • MDR-XB950BT
  • WH-1000XM3
  • -
- -
- -
-
- Everything the app hides -

Full control, minus the phone.

-

SonyBridge talks to your headset over Bluetooth using Sony's own protocol — so every setting you'd expect from the mobile app is right on your desktop.

-
-
-
-
-
-

Ambient Sound Control

-

Switch between Noise Cancelling, Ambient Sound with 20 levels, and Focus-on-Voice — with live sync when you press the button on the headset.

-
- -
-
-
-

Equalizer + Manual

-

Presets, or a full 5-band manual mode with Clear Bass.

-
-
-
-

DSEE upscaling

-

Restore detail lost to compressed audio, one toggle.

-
-
-
-

Battery, incl. TWS

-

Live percentage — left, right and case for earbuds.

-
-
-
-

Only what fits

-

Auto power-off, Speak-to-Chat & Adaptive Volume appear only when your device supports them.

-
-
-
-

Dual-protocol

-

Auto-detects v1 & v2 headsets — old and new, same app.

-
-
-
- -
-
-
- How it works -

Speaks Sony's binary protocol.

-

Sony headphones expose a vendor RFCOMM/SPP service. SonyBridge frames commands on the wire, handles the v2 init handshake and per-frame ACK the newer devices require, and reads state straight back from the headset.

-
- -
-
- -
-
- Compatibility -

Works across the Sony lineup.

-

The WH-CH720N is fully hardware-verified. The rest share the same protocol family — the basics should just work.

-
-
- Verified - Expected · v2 - v2 earbuds - Legacy · v1 -
-
- WH-CH720N - ULT WEAR - WH-1000XM5 - WH-1000XM6 - WH-XB910N - WH-CH520 - WF-1000XM4 - WF-1000XM5 - WF-C700N - LinkBuds S - WH-1000XM4 - WH-1000XM3 - WH-XB900N - MDR-XB950BT -
-
- -
-
- Get started -

Install in a minute.

-

Pair your headphones in your OS Bluetooth settings first, then open SonyBridge and hit Connect.

-
-
-
-
macOS
-
$brew install --cask sonybridge
-
macOS 11+ · Apple Silicon & Intel · or download the .app
- -
-
-
Windows BETA
-

First Windows build — same UI, testers wanted. Grab it and tell us how it runs.

- -
-
-
Linux
-

Build from source — the same modern UI runs on the GLFW/OpenGL path.

-
apt install libbluetooth-dev libglfw3-dev libdbus-1-dev
- -
-
-
- -
-
- Free & open-source -

Keep the reverse-engineering going.

-

SonyBridge is free forever. If it saved you from Sony's app, a sponsorship or a star keeps new devices and features coming.

- -
-
- - -
- -
Copied to clipboard
- - - - - diff --git a/docs/superpowers/plans/2026-09-10-menu-bar-app.md b/docs/superpowers/plans/2026-09-10-menu-bar-app.md new file mode 100644 index 0000000..6a47c70 --- /dev/null +++ b/docs/superpowers/plans/2026-09-10-menu-bar-app.md @@ -0,0 +1,2958 @@ +# SonyBridge barre des menus — plan d'implémentation + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal :** transformer SonyBridge (app à fenêtre SwiftUI) en app de barre des menus native, avec toutes les +fonctions existantes, les corrections WH-1000XM6, les options de connexion automatique, et un build sans Xcode. + +**Architecture :** `NSStatusItem` + `NSMenu` (AppKit). Les lignes riches (en-tête, curseurs, interrupteurs, +égaliseur) sont des vues SwiftUI hébergées dans des `NSMenuItem` (`NSHostingView`). Le modèle +`HeadphonesModel` (Swift, observable) pilote le pont Obj-C++ `HeadphonesBridge`, qui pilote le cœur C++ +existant. La logique pure (reconnexion, anti-retour d'affichage, limitation d'envoi, décodage des trames) est +isolée dans de petits fichiers testés par des exécutables de test. + +**Tech Stack :** Swift 5 (mode de langage), SwiftUI, AppKit, Combine, IOBluetooth, ServiceManagement ; +C++17 et Obj-C++ (ARC) ; build `swiftc` + `clang++` via `scripts/build.sh` et `Makefile` ; Python 3 (vérif. des +traductions). + +**Spec :** `docs/superpowers/specs/2026-09-10-menu-bar-app-design.md` + +## Global Constraints + +- macOS minimum : **13.0** (`LSMinimumSystemVersion`, cible `-apple-macos13.0`). +- Pas de Xcode : tout se compile avec les Command Line Tools (`make`, `make test`, `make run`, `make release`). +- Swift compilé avec `-swift-version 5` ; C++ en `-std=c++17` ; Obj-C++ avec `-fobjc-arc`. +- Bundle : `SonyBridge.app`, exécutable `SonyBridge`, identifiant **`com.semvis123.SonyHeadphonesClient`** + (inchangé), `LSUIElement = YES`. +- Textes : **tout texte affiché** passe par `tr("…")` en Swift ou `NSLocalizedString(@"…", nil)` en Obj-C++, + avec la clé en anglais et sa traduction dans `Client/macos/fr.lproj/Localizable.strings`. Pas de texte affiché + en dur ailleurs. `make test` le vérifie (à partir de la tâche 2). +- Sécurité XM6 : **ne jamais envoyer au casque une commande dont le format n'est pas vérifié** (spec §7). En + particulier, aucune écriture d'égaliseur sur la disposition 10 bandes avant la tâche 8. +- Git : c'est **l'utilisateur** qui committe. À chaque étape « Commit », afficher la commande proposée et + attendre qu'il la lance. +- Test matériel : l'agent ne voit pas l'écran. Chaque vérification visuelle est demandée à l'utilisateur, avec + une liste précise de choses à regarder. Les échanges avec le casque se lisent dans `build/app.log` + (`make run DEBUG=1`). + +## Carte des fichiers + +| Fichier | Tâche | Responsabilité | +|---|---|---| +| `scripts/build.sh` | 1 | Compile et assemble `build/SonyBridge.app` | +| `scripts/test.sh` | 2 | Compile et lance les exécutables de test + vérif. des traductions | +| `scripts/check_localization.py` | 2 | Chaque clé `tr()` a sa traduction, aucune traduction inutilisée | +| `Makefile` | 1, 2 | `make`, `run`, `test`, `release`, `clean` | +| `.github/workflows/build.yml` | 1, 2 | CI : tests + build universel | +| `Client/macos/info.plist` | 1 | App d'agent, macOS 13, nom SonyBridge | +| `Client/macos/Resources/AppIcon.iconset/` | 1 | Icône de l'app (compilée par `iconutil`) | +| `Client/macos/SonyBridgeApp.swift` | 1 | Point d'entrée `@main` | +| `Client/macos/AppDelegate.swift` | 1, 7 | Assemble modèle, réglages, surveillance Bluetooth, icône de barre | +| `Client/macos/Localization.swift` | 1 | `tr(_:)` | +| `Client/macos/MenuSupport.swift` | 1, 5, 6 | `ActionMenuItem`, `sectionHeader`, `hostingMenuItem`, `MenuMetrics`, `titleWithValue` | +| `Client/macos/StatusItemController.swift` | 1, 4, 7 | L'icône de la barre et son menu | +| `Client/macos/StatusIcon.swift` | 6 | Choix du symbole selon le mode | +| `Client/macos/HeadphonesMenu.swift` | 1, 6, 7, 8 | Construit le `NSMenu` et le synchronise avec le modèle | +| `Client/macos/MenuRows/*.swift` | 5 | `HeaderRow`, `AmbientLevelRow`, `ToggleRow`, `EqualizerRow` | +| `Client/macos/HeadphonesModel.swift` | 4, 7, 8 | État observable + actions + minuteurs + reconnexion | +| `Client/macos/ReconnectPolicy.swift` | 2 | Délais de reconnexion | +| `Client/macos/PollGuard.swift` | 2 | Ignore les relectures 3 s après un changement | +| `Client/macos/SendThrottle.swift` | 2 | Limite les envois des curseurs à 1 / 150 ms | +| `Client/macos/AppSettings.swift` | 7 | Les 3 options + lancement à l'ouverture de session | +| `Client/macos/DeviceWatcher.swift` | 7 | Connexions / déconnexions Bluetooth de macOS | +| `Client/macos/HeadphonesBridge.h/.mm` | 3, 4, 7, 8 | Pont Obj-C++ | +| `Client/ProtocolParsers.h/.cpp` | 3, 8 | Décodage / encodage purs des trames | +| `Client/Headphones.h/.cpp` | 3, 8 | Utilise `ProtocolParsers`, canal NC `0x19` | +| `Client/tests/LogicTests/main.swift` | 2 | Tests de la logique Swift | +| `Client/tests/ProtocolParsersTests.cpp` | 3, 8 | Tests du décodage avec les trames réelles | +| `Client/macos/fr.lproj/Localizable.strings` | toutes | Traductions | +| `README.md` | 1, 9 | Build, description | + +**Supprimés en tâche 1 :** `Client/macos/{main.mm, AppDelegate.h, AppDelegate.mm, ViewController.h, +ViewController.mm, Main.storyboard, ContentView.swift, exportOptions.plist}`, +`Client/macos/SonyHeadphonesClient.xcodeproj/`, `Client/macos/Assets.xcassets/`, +`.github/workflows/xcodebuild.yml`. + +--- + +### Task 1: Build par script + app d'agent avec un menu minimal + +Remplace le projet Xcode et la fenêtre par un build en ligne de commande et une icône de barre des menus. Le +menu minimal contient l'en-tête, les trois modes, Connecter/Déconnecter et Quitter. Il utilise le modèle +**existant** (`HeadphonesModel` actuel, avec `connected`, `connecting`, `mode`, `setMode`, `connect`, `disconnect`). + +**Files:** +- Create: `scripts/build.sh`, `Makefile`, `.github/workflows/build.yml` +- Create: `Client/macos/SonyBridgeApp.swift`, `Client/macos/AppDelegate.swift`, `Client/macos/Localization.swift`, + `Client/macos/MenuSupport.swift`, `Client/macos/StatusItemController.swift`, `Client/macos/HeadphonesMenu.swift` +- Create: `Client/macos/Resources/AppIcon.iconset/*.png` (copiés depuis `Assets.xcassets`) +- Modify: `Client/macos/info.plist`, `Client/macos/fr.lproj/Localizable.strings`, `README.md` (section build) +- Delete: la liste « Supprimés en tâche 1 » ci-dessus + +**Interfaces:** +- Consumes : `HeadphonesModel` actuel (`@Published connected/connecting/mode/deviceName/batteryLevel`, + `connect()`, `disconnect()`, `setMode(_:)`), `SHCAmbientMode` (`.off/.noiseCanceling/.ambientSound`). +- Produces : + - `func tr(_ key: String) -> String` + - `final class ActionMenuItem: NSMenuItem { init(_ title: String, key: String = "", handler: @escaping () -> Void) }` + - `func sectionHeader(_ title: String) -> NSMenuItem` + - `final class StatusItemController { init(model: HeadphonesModel) }` + - `final class HeadphonesMenu { let menu: NSMenu; init(model: HeadphonesModel) }` + - commandes `make`, `make run [DEBUG=1]`, `make release`, `make clean` ; app dans `build/SonyBridge.app` + +- [ ] **Step 1 : Copier l'icône dans un `.iconset`, puis supprimer les anciens fichiers** + +```bash +S=Client/macos/Assets.xcassets/AppIcon.appiconset; D=Client/macos/Resources/AppIcon.iconset +mkdir -p "$D" +for s in 16 32 128 256 512; do + cp "$S/icon_$s.png" "$D/icon_${s}x${s}.png" + cp "$S/icon_$((s*2)).png" "$D/icon_${s}x${s}@2x.png" +done +ls "$D" | wc -l # attendu : 10 +git rm -r -q Client/macos/main.mm Client/macos/AppDelegate.h Client/macos/AppDelegate.mm \ + Client/macos/ViewController.h Client/macos/ViewController.mm Client/macos/Main.storyboard \ + Client/macos/ContentView.swift Client/macos/exportOptions.plist \ + Client/macos/SonyHeadphonesClient.xcodeproj Client/macos/Assets.xcassets .github/workflows/xcodebuild.yml +``` + +- [ ] **Step 2 : Écrire `scripts/build.sh`** (puis `chmod +x scripts/build.sh`) + +`/bin/bash` sur macOS est la version 3.2 : pas de tableau vide avec `set -u`, d'où les options passées en chaînes. + +```bash +#!/bin/bash +# Builds build/SonyBridge.app with the Command Line Tools only (no Xcode needed). +# CONFIG=debug|release (default: debug) +# ARCHS="arm64 x86_64" (default: this Mac's architecture; several = universal binary via lipo) +# DEBUG_PROTOCOL=1 (hex-dumps every frame exchanged with the headphones to stderr) +set -euo pipefail +shopt -s nullglob + +ROOT=$(cd "$(dirname "$0")/.." && pwd) +CORE=$ROOT/Client +MAC=$CORE/macos +OUT=$ROOT/build +APP=$OUT/SonyBridge.app +SDK=$(xcrun --show-sdk-path) +CONFIG=${CONFIG:-debug} +ARCHS=${ARCHS:-$(uname -m)} +MIN_MACOS=13.0 + +if [ "$CONFIG" = release ]; then SWIFT_OPT="-O"; CXX_OPT="-O2"; else SWIFT_OPT="-Onone -g"; CXX_OPT="-O0 -g"; fi +SWIFT_DEFINES=""; CXX_DEFINES="" +if [ "${DEBUG_PROTOCOL:-0}" = 1 ]; then SWIFT_DEFINES="-D DEBUG_PROTOCOL"; CXX_DEFINES="-DSHC_DEBUG_PROTOCOL"; fi + +SWIFT_SOURCES=("$MAC"/*.swift "$MAC"/MenuRows/*.swift) +CXX_SOURCES=("$CORE"/*.cpp) +OBJCXX_SOURCES=("$MAC"/*.mm) + +rm -rf "$APP" +mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Resources" +BINARIES="" + +for ARCH in $ARCHS; do + OBJ=$OUT/obj/$CONFIG-$ARCH + rm -rf "$OBJ"; mkdir -p "$OBJ" + TARGET=$ARCH-apple-macos$MIN_MACOS + CXXFLAGS="-target $TARGET -isysroot $SDK -std=c++17 $CXX_OPT $CXX_DEFINES -I $CORE -I $MAC" + + echo "== [$ARCH] Swift" + swiftc -target "$TARGET" -sdk "$SDK" -swift-version 5 $SWIFT_OPT $SWIFT_DEFINES -wmo -parse-as-library \ + -module-name SonyBridge \ + -import-objc-header "$MAC/SonyHeadphonesClient-Bridging-Header.h" -I "$MAC" -I "$CORE" \ + -c "${SWIFT_SOURCES[@]}" -o "$OBJ/swift.o" + + echo "== [$ARCH] C++" + for f in "${CXX_SOURCES[@]}"; do clang++ $CXXFLAGS -c "$f" -o "$OBJ/$(basename "$f" .cpp).o"; done + + echo "== [$ARCH] Obj-C++" + for f in "${OBJCXX_SOURCES[@]}"; do + clang++ $CXXFLAGS -fobjc-arc -fmodules -fcxx-modules -c "$f" -o "$OBJ/$(basename "$f" .mm).o" + done + + echo "== [$ARCH] Link" + swiftc -target "$TARGET" -sdk "$SDK" "$OBJ"/*.o -o "$OBJ/SonyBridge" -lc++ \ + -framework AppKit -framework SwiftUI -framework Combine -framework IOBluetooth \ + -framework IOBluetoothUI -framework ServiceManagement + BINARIES="$BINARIES $OBJ/SonyBridge" +done + +lipo -create $BINARIES -output "$APP/Contents/MacOS/SonyBridge" + +echo "== Resources" +cp "$MAC/info.plist" "$APP/Contents/Info.plist" +cp -R "$MAC"/*.lproj "$APP/Contents/Resources/" +iconutil -c icns "$MAC/Resources/AppIcon.iconset" -o "$APP/Contents/Resources/AppIcon.icns" + +echo "== Sign (ad-hoc)" +codesign --force --sign - --entitlements "$MAC/SonyHeadphonesClient.entitlements" "$APP" +echo "OK -> $APP" +``` + +- [ ] **Step 3 : Écrire le `Makefile`** + +```make +# SonyBridge — build without Xcode. See scripts/build.sh for the knobs. +DEBUG ?= 0 + +.PHONY: all build run release clean + +all: build + +build: + DEBUG_PROTOCOL=$(DEBUG) ./scripts/build.sh + +run: build + -pkill -x SonyBridge + open --stdout build/app.log --stderr build/app.log build/SonyBridge.app + +release: + CONFIG=release ARCHS="arm64 x86_64" ./scripts/build.sh + cd build && rm -f SonyBridge.zip && ditto -c -k --keepParent SonyBridge.app SonyBridge.zip + +clean: + rm -rf build +``` + +- [ ] **Step 4 : Écrire `.github/workflows/build.yml`** (la tâche 2 y ajoutera `make test`) + +```yaml +name: macOS + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build: + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - name: Build (release, universal) + run: make release + - uses: actions/upload-artifact@v4 + with: + name: SonyBridge-macOS + path: build/SonyBridge.zip +``` + +- [ ] **Step 5 : Réécrire `Client/macos/info.plist`** + +```xml + + + + + CFBundleDevelopmentRegion + en + CFBundleLocalizations + + en + fr + + CFBundleExecutable + SonyBridge + CFBundleIdentifier + com.semvis123.SonyHeadphonesClient + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + SonyBridge + CFBundleDisplayName + SonyBridge + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.5.0 + CFBundleVersion + 1 + CFBundleIconFile + AppIcon + LSApplicationCategoryType + public.app-category.utilities + LSMinimumSystemVersion + 13.0 + LSUIElement + + NSHighResolutionCapable + + NSBluetoothAlwaysUsageDescription + This app uses Bluetooth in order to connect to your headphones. + NSPrincipalClass + NSApplication + + +``` + +Run : `plutil -lint Client/macos/info.plist` → `OK`. + +- [ ] **Step 6 : Écrire les fichiers Swift de base** + +`Client/macos/SonyBridgeApp.swift` : + +```swift +import AppKit + +// Entry point: a menu bar-only app (LSUIElement), no window and no Dock icon. +@main +enum SonyBridgeApp { + static func main() { + let app = NSApplication.shared + let delegate = AppDelegate() + app.delegate = delegate + app.setActivationPolicy(.accessory) + withExtendedLifetime(delegate) { app.run() } + } +} +``` + +`Client/macos/AppDelegate.swift` : + +```swift +import AppKit + +final class AppDelegate: NSObject, NSApplicationDelegate { + private let model = HeadphonesModel() + private var statusItemController: StatusItemController? + + func applicationDidFinishLaunching(_ notification: Notification) { + statusItemController = StatusItemController(model: model) + } + + func applicationWillTerminate(_ notification: Notification) { + model.disconnect() + } +} +``` + +`Client/macos/Localization.swift` : + +```swift +import Foundation + +// Looks up a UI string in Localizable.strings. Every user-facing string goes through this (checked by make test). +func tr(_ key: String) -> String { + NSLocalizedString(key, comment: "") +} +``` + +`Client/macos/MenuSupport.swift` : + +```swift +import AppKit + +// A menu item that runs a closure (NSMenuItem only supports target/selector natively). +final class ActionMenuItem: NSMenuItem { + private let handler: () -> Void + + init(_ title: String, key: String = "", handler: @escaping () -> Void) { + self.handler = handler + super.init(title: title, action: #selector(fire), keyEquivalent: key) + target = self + } + + required init(coder: NSCoder) { + fatalError("init(coder:) is not supported") + } + + @objc private func fire() { + handler() + } +} + +// A small grey, non-clickable title above a group of items (like "Contrôle du son ambiant"). +func sectionHeader(_ title: String) -> NSMenuItem { + let item = NSMenuItem() + item.attributedTitle = NSAttributedString(string: title, attributes: [ + .font: NSFont.systemFont(ofSize: NSFont.smallSystemFontSize, weight: .semibold), + .foregroundColor: NSColor.secondaryLabelColor, + ]) + item.isEnabled = false + return item +} +``` + +`Client/macos/StatusItemController.swift` (icône provisoire ; la tâche 6 ajoute `StatusIcon`) : + +```swift +import AppKit +import Combine + +// Owns the menu bar icon and attaches the headphones menu to it. +final class StatusItemController { + private let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength) + private let headphonesMenu: HeadphonesMenu + private var cancellables = Set() + + init(model: HeadphonesModel) { + headphonesMenu = HeadphonesMenu(model: model) + statusItem.menu = headphonesMenu.menu + let image = NSImage(systemSymbolName: "headphones", accessibilityDescription: "SonyBridge") + image?.isTemplate = true + statusItem.button?.image = image + model.$connected + .receive(on: DispatchQueue.main) + .sink { [weak self] connected in self?.statusItem.button?.appearsDisabled = !connected } + .store(in: &cancellables) + } +} +``` + +`Client/macos/HeadphonesMenu.swift` (version minimale, remplacée entièrement en tâche 6) : + +```swift +import AppKit +import Combine + +// The status item's menu. Minimal for now: header, modes, connect/disconnect, quit. +final class HeadphonesMenu { + let menu = NSMenu() + private let model: HeadphonesModel + private var cancellables = Set() + private let headerItem = NSMenuItem() + private var modeItems: [(SHCAmbientMode, NSMenuItem)] = [] + private var connectItem: ActionMenuItem! + + init(model: HeadphonesModel) { + self.model = model + menu.autoenablesItems = false + + headerItem.isEnabled = false + menu.addItem(headerItem) + menu.addItem(.separator()) + + menu.addItem(sectionHeader(tr("Ambient Sound Control"))) + let modes: [(SHCAmbientMode, String)] = [ + (.noiseCanceling, tr("Noise Canceling")), (.ambientSound, tr("Ambient Sound")), (.off, tr("Off")), + ] + for (mode, title) in modes { + let item = ActionMenuItem(title) { [weak model] in model?.setMode(mode) } + modeItems.append((mode, item)) + menu.addItem(item) + } + menu.addItem(.separator()) + + connectItem = ActionMenuItem(tr("Connect…")) { [weak self] in self?.toggleConnection() } + menu.addItem(connectItem) + menu.addItem(.separator()) + menu.addItem(ActionMenuItem(tr("Quit SonyBridge"), key: "q") { NSApp.terminate(nil) }) + + // objectWillChange fires before the new value is stored; hopping to the main queue reads the new state. + model.objectWillChange + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in self?.update() } + .store(in: &cancellables) + update() + } + + private func update() { + let connected = model.connected + var header = model.deviceName.isEmpty ? "SonyBridge" : model.deviceName + if connected && model.batteryLevel >= 0 { + header += " — " + String(format: tr("%ld%%"), model.batteryLevel) + } + headerItem.title = header + for (mode, item) in modeItems { + item.state = connected && model.mode == mode ? .on : .off + item.isEnabled = connected + } + connectItem.title = connected ? tr("Disconnect") : (model.connecting ? tr("Connecting…") : tr("Connect…")) + connectItem.isEnabled = !model.connecting + } + + private func toggleConnection() { + if model.connected { + model.disconnect() + } else { + NSApp.activate(ignoringOtherApps: true) // the fallback Bluetooth picker is a modal window + model.connect() + } + } +} +``` + +- [ ] **Step 7 : Remplacer `Client/macos/fr.lproj/Localizable.strings`** par les seules clés utilisées maintenant + +``` +/* SonyBridge — French UI strings. Keys are the English source strings; missing keys fall back to English. */ + +/* Menu */ +"Ambient Sound Control" = "Contrôle du son ambiant"; +"Noise Canceling" = "Réduction de bruit"; +"Ambient Sound" = "Son ambiant"; +"Off" = "Désactivé"; +"Connect…" = "Connecter…"; +"Connecting…" = "Connexion…"; +"Disconnect" = "Déconnecter"; +"Quit SonyBridge" = "Quitter SonyBridge"; +"%ld%%" = "%ld %%"; + +/* Errors (HeadphonesBridge.mm, HeadphonesModel.swift) */ +"Headphones disconnected." = "Casque déconnecté."; +"No connected Sony headset found. Connect your headphones in macOS Bluetooth settings first." = "Aucun casque Sony connecté. Connectez d’abord votre casque dans les réglages Bluetooth de macOS."; +"Connection timed out." = "Délai de connexion dépassé."; +"Not connected." = "Non connecté."; +"Equalizer control isn't supported on this device yet." = "Le réglage de l’égaliseur n’est pas encore pris en charge sur cet appareil."; +"Not supported on this device." = "Non pris en charge sur cet appareil."; +``` + +Run : `plutil -lint Client/macos/fr.lproj/Localizable.strings` → `OK`. + +- [ ] **Step 8 : Mettre à jour la section build du `README.md`** + +Remplacer le bloc `
` « macOS (native SwiftUI app) » de « 🚀 Build from source » par : + +````markdown +
+macOS (menu bar app) + +Requires the **Xcode Command Line Tools** (`xcode-select --install`) — the full Xcode app is not needed. + +```sh +git clone https://github.com/AmitRajput-Dev/SonyBridge.git +cd SonyBridge +make run # builds build/SonyBridge.app and launches it +``` + +`make test` runs the unit tests, `make release` builds a universal (Apple Silicon + Intel) zip, and +`make run DEBUG=1` logs every frame exchanged with the headphones to `build/app.log`. +
+```` + +- [ ] **Step 9 : Compiler** + +Run : `make` +Attendu : les étapes `== [arm64] Swift`, `C++`, `Obj-C++`, `Link`, `Resources`, `Sign`, puis +`OK -> …/build/SonyBridge.app`, sans erreur. + +- [ ] **Step 10 : Lancer et vérifier avec l'utilisateur** + +Run : `make run DEBUG=1 && pgrep -x SonyBridge` +Attendu : un PID. Demander à l'utilisateur de vérifier : +1. Une icône de casque est dans la barre des menus, grisée, et **rien dans le Dock**. +2. Le menu s'ouvre : « SonyBridge », « Contrôle du son ambiant », les 3 modes (grisés), « Connecter… », + « Quitter SonyBridge ⌘Q », en français. +3. « Connecter… » connecte le XM6 : l'icône n'est plus grisée, et l'en-tête affiche « WH-1000XM6 — 68 % ». +4. Cliquer sur « Son ambiant » change bien le mode dans le casque. **Connu, corrigé en tâche 3** : la coche + peut revenir sur « Désactivé » au bout de 2 s (mauvaise relecture du XM6). +5. « Quitter » ferme l'app. + +- [ ] **Step 11 : Commit** (par l'utilisateur) + +```bash +git add -A && git commit -m "feat(macos): menu bar agent app built with make (drop Xcode project and window UI)" +``` + +--- + +### Task 2: Logique pure (reconnexion, anti-retour, limitation) + `make test` + +**Files:** +- Create: `Client/macos/ReconnectPolicy.swift`, `Client/macos/PollGuard.swift`, `Client/macos/SendThrottle.swift` +- Create: `Client/tests/LogicTests/main.swift`, `scripts/test.sh`, `scripts/check_localization.py` +- Modify: `Makefile` (cible `test`), `.github/workflows/build.yml` (étape `make test`) + +**Interfaces:** +- Produces : + - `struct ReconnectPolicy { static let delays: [TimeInterval]; private(set) var attempt: Int; mutating func nextDelay() -> TimeInterval; mutating func reset() }` + - `struct PollGuard { init(window: TimeInterval = 3); mutating func userChanged(_ key: Key, at date: Date = Date()); func shouldAcceptPoll(for key: Key, at date: Date = Date()) -> Bool }` + - `struct SendThrottle { init(interval: TimeInterval = 0.15); mutating func shouldSend(at date: Date = Date(), final: Bool) -> Bool }` + - `make test` : lance `LogicTests` puis `check_localization.py` (la tâche 3 ajoute les tests C++) + +- [ ] **Step 1 : Écrire les tests** `Client/tests/LogicTests/main.swift` + +```swift +import Foundation + +// Minimal test runner (XCTest isn't available without Xcode). Exit code 1 on any failure. +var failures = 0 +func check(_ condition: Bool, _ message: String, line: Int = #line) { + if !condition { + failures += 1 + print("FAIL line \(line): \(message)") + } +} + +// ReconnectPolicy: 3 s, 10 s, 30 s, then every 60 s; reset restarts. +do { + var policy = ReconnectPolicy() + let delays = (0..<6).map { _ in policy.nextDelay() } + check(delays == [3, 10, 30, 60, 60, 60], "reconnect schedule was \(delays)") + policy.reset() + check(policy.nextDelay() == 3, "reset restarts the schedule") +} + +// PollGuard: a poll is ignored for 3 s after the user changed that setting. +do { + var pollGuard = PollGuard(window: 3) + let t0 = Date(timeIntervalSince1970: 1_000) + check(pollGuard.shouldAcceptPoll(for: "ambient", at: t0), "no user change: accept") + pollGuard.userChanged("ambient", at: t0) + check(!pollGuard.shouldAcceptPoll(for: "ambient", at: t0.addingTimeInterval(2.9)), "inside the window: reject") + check(pollGuard.shouldAcceptPoll(for: "ambient", at: t0.addingTimeInterval(3)), "after the window: accept") + check(pollGuard.shouldAcceptPoll(for: "eq", at: t0.addingTimeInterval(1)), "other keys are unaffected") +} + +// SendThrottle: at most one send per 150 ms while dragging; the final value always goes out. +do { + var throttle = SendThrottle(interval: 0.15) + let t0 = Date(timeIntervalSince1970: 1_000) + check(throttle.shouldSend(at: t0, final: false), "first drag event sends") + check(!throttle.shouldSend(at: t0.addingTimeInterval(0.10), final: false), "too soon: skip") + check(throttle.shouldSend(at: t0.addingTimeInterval(0.16), final: false), "after the interval: send") + check(throttle.shouldSend(at: t0.addingTimeInterval(0.17), final: true), "final value always sends") +} + +if failures > 0 { + print("LogicTests: \(failures) failure(s)") + exit(1) +} +print("LogicTests: all passed") +``` + +- [ ] **Step 2 : Écrire `scripts/test.sh`** (puis `chmod +x scripts/test.sh`) + +```bash +#!/bin/bash +# Builds and runs the unit test executables (plain asserts, no XCTest), then checks the translations. +set -euo pipefail + +ROOT=$(cd "$(dirname "$0")/.." && pwd) +MAC=$ROOT/Client/macos +OUT=$ROOT/build/tests +SDK=$(xcrun --show-sdk-path) +TARGET=$(uname -m)-apple-macos13.0 +mkdir -p "$OUT" + +echo "== LogicTests" +swiftc -target "$TARGET" -sdk "$SDK" -swift-version 5 \ + "$ROOT/Client/tests/LogicTests/main.swift" \ + "$MAC/ReconnectPolicy.swift" "$MAC/PollGuard.swift" "$MAC/SendThrottle.swift" \ + -o "$OUT/LogicTests" +"$OUT/LogicTests" + +echo "== Localization" +python3 "$ROOT/scripts/check_localization.py" +``` + +- [ ] **Step 3 : Ajouter la cible `test` au `Makefile`** + +Remplacer la ligne `.PHONY` et ajouter la cible : + +```make +.PHONY: all build run test release clean + +test: + ./scripts/test.sh +``` + +- [ ] **Step 4 : Lancer les tests pour les voir échouer** + +Run : `make test` +Attendu : échec de compilation, `cannot find 'ReconnectPolicy' in scope` (et `PollGuard`, `SendThrottle`). + +- [ ] **Step 5 : Écrire les trois fichiers de logique** + +`Client/macos/ReconnectPolicy.swift` : + +```swift +import Foundation + +// Delays between automatic reconnection attempts: 3 s, 10 s, 30 s, then every 60 s. +struct ReconnectPolicy { + static let delays: [TimeInterval] = [3, 10, 30, 60] + private(set) var attempt = 0 + + // Delay before the next attempt; each call advances the schedule. + mutating func nextDelay() -> TimeInterval { + let delay = Self.delays[min(attempt, Self.delays.count - 1)] + attempt += 1 + return delay + } + + mutating func reset() { + attempt = 0 + } +} +``` + +`Client/macos/PollGuard.swift` : + +```swift +import Foundation + +// Ignores a polled value for a setting the user changed less than `window` seconds ago, so a read-back that +// raced the user's command doesn't briefly flip the menu back to the old state. +struct PollGuard { + let window: TimeInterval + private var lastUserChange: [Key: Date] = [:] + + init(window: TimeInterval = 3) { + self.window = window + } + + mutating func userChanged(_ key: Key, at date: Date = Date()) { + lastUserChange[key] = date + } + + func shouldAcceptPoll(for key: Key, at date: Date = Date()) -> Bool { + guard let changed = lastUserChange[key] else { return true } + return date.timeIntervalSince(changed) >= window + } +} +``` + +`Client/macos/SendThrottle.swift` : + +```swift +import Foundation + +// Rate-limits slider commands: at most one every `interval` while dragging; the final value always goes out. +struct SendThrottle { + let interval: TimeInterval + private var lastSend: Date? + + init(interval: TimeInterval = 0.15) { + self.interval = interval + } + + mutating func shouldSend(at date: Date = Date(), final: Bool) -> Bool { + if !final, let last = lastSend, date.timeIntervalSince(last) < interval { + return false + } + lastSend = date + return true + } +} +``` + +- [ ] **Step 6 : Écrire `scripts/check_localization.py`** + +```python +#!/usr/bin/env python3 +"""Every tr("…") / NSLocalizedString("…") key must have a French translation, and every French key must be used.""" +import json +import pathlib +import re +import subprocess +import sys + +ROOT = pathlib.Path(__file__).resolve().parent.parent +MAC = ROOT / "Client" / "macos" +STRINGS = MAC / "fr.lproj" / "Localizable.strings" +LITERAL = r'"((?:[^"\\]|\\.)*)"' +PATTERNS = [re.compile(r"\btr\(" + LITERAL + r"\)"), re.compile(r"NSLocalizedString\(@?" + LITERAL)] + +french = set(json.loads(subprocess.check_output(["plutil", "-convert", "json", "-o", "-", str(STRINGS)]))) +used = set() +for path in sorted(MAC.rglob("*.swift")) + sorted(MAC.rglob("*.mm")): + text = path.read_text(encoding="utf-8") + for pattern in PATTERNS: + used.update(key.replace("\\n", "\n") for key in pattern.findall(text)) + +missing = sorted(used - french) +unused = sorted(french - used) +for key in missing: + print(f"missing French translation: {key!r}") +for key in unused: + print(f"unused French key: {key!r}") +if missing or unused: + sys.exit(1) +print(f"Localization: {len(used)} keys, all translated") +``` + +- [ ] **Step 7 : Relancer les tests** + +Run : `make test` +Attendu : `LogicTests: all passed` puis `Localization: 15 keys, all translated` (les 15 clés de la tâche 1). +Si la vérif. des traductions échoue, corriger `Localizable.strings` : la tâche 1 doit être propre. + +- [ ] **Step 8 : Ajouter les tests à la CI** + +Dans `.github/workflows/build.yml`, avant l'étape « Build (release, universal) » : + +```yaml + - name: Test + run: make test +``` + +- [ ] **Step 9 : Commit** (par l'utilisateur) + +```bash +git add -A && git commit -m "test: reconnect/poll-guard/throttle logic, localization check, make test" +``` + +--- + +### Task 3: Décodage des trames + corrections XM6 (canal `0x19`, égaliseur 10 bandes en lecture) + +**Files:** +- Create: `Client/ProtocolParsers.h`, `Client/ProtocolParsers.cpp`, `Client/tests/ProtocolParsersTests.cpp` +- Modify: `Client/Headphones.h`, `Client/Headphones.cpp` (`requestAmbientState`, `requestEqualizer`, + `setEqualizerCustom`, nouvelles méthodes), `Client/macos/HeadphonesBridge.h/.mm`, `scripts/test.sh` + +**Interfaces:** +- Produces (C++) : + - `namespace ProtocolParsers { struct NcAsmState { bool enabled; bool ambient; bool focusOnVoice; int level; }; std::optional parseNcAsmState(const Buffer&); struct EqualizerState { unsigned char preset; bool hasClearBass; int clearBass; std::vector bands; }; std::optional parseEqualizer(const Buffer&); }` + - `Headphones::probeNcAsmInquiryType()`, `int Headphones::getEqualizerBandCount()`, `bool Headphones::equalizerHasClearBass()` +- Produces (Obj-C, visible en Swift) : `equalizerBandCount: Int`, `equalizerHasClearBass: Bool`, + `equalizerWritable: Bool` sur `HeadphonesBridge`. + +- [ ] **Step 1 : Écrire les tests** `Client/tests/ProtocolParsersTests.cpp` (trames réelles du XM6, spec §7) + +```cpp +#include "ProtocolParsers.h" +#include "CommandSerializer.h" +#include +#include + +// Minimal test runner (no framework). Exit code 1 on any failure. +static int failures = 0; +#define CHECK(cond) do { if (!(cond)) { failures++; std::printf("FAIL %s:%d: %s\n", __FILE__, __LINE__, #cond); } } while (0) + +static Buffer bytes(std::initializer_list values) +{ + Buffer b; + for (int v : values) b.push_back((char)v); + return b; +} + +int main() +{ + using namespace ProtocolParsers; + + // --- NC/ASM state --- + // WH-1000XM6 answer to the legacy 0x17 inquiry: all zeros = "not this channel". + CHECK(!parseNcAsmState(bytes({ 0x67, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00 })).has_value()); + // WH-1000XM6 notify on 0x19: Ambient Sound on, level 10, no voice focus. + { + auto s = parseNcAsmState(bytes({ 0x69, 0x19, 0x01, 0x01, 0x01, 0x00, 0x0a, 0x00, 0x00 })); + CHECK(s && s->enabled && s->ambient && !s->focusOnVoice && s->level == 10); + } + // WH-1000XM6 reply on 0x19: Noise Cancelling (ambient byte = 0). + { + auto s = parseNcAsmState(bytes({ 0x67, 0x19, 0x01, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x00 })); + CHECK(s && s->enabled && !s->ambient); + } + // Legacy 0x17 layout (WH-CH720N): effect off. + { + auto s = parseNcAsmState(bytes({ 0x67, 0x17, 0x01, 0x00, 0x00, 0x00, 0x01 })); + CHECK(s && !s->enabled); + } + CHECK(!parseNcAsmState(bytes({ 0x67, 0x17, 0x01 })).has_value()); // too short + CHECK(!parseNcAsmState(bytes({ 0x57, 0x17, 0x01, 0x01, 0x01, 0x00, 0x0a })).has_value()); // wrong opcode + + // --- Equalizer --- + // WH-1000XM6: unknown preset 0x30, 10 bands (offset +10 hypothesis, spec §7). + { + auto e = parseEqualizer(bytes({ 0x57, 0x00, 0x30, 0x0a, 0x0a, 0x0a, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 })); + CHECK(e && e->preset == 0x30 && !e->hasClearBass && e->bands.size() == 10); + CHECK(e && e->bands[0] == 0 && e->bands[2] == -5 && e->bands[9] == -4); + } + // 5 bands + Clear Bass (WH-CH720N): Manual, bass +3, bands -2..+2. + { + auto e = parseEqualizer(bytes({ 0x57, 0x00, 0xa0, 0x06, 13, 8, 9, 10, 11, 12 })); + CHECK(e && e->preset == 0xa0 && e->hasClearBass && e->clearBass == 3); + CHECK(e && e->bands == std::vector({ -2, -1, 0, 1, 2 })); + } + // Preset only, no band data. + { + auto e = parseEqualizer(bytes({ 0x57, 0x00, 0x16 })); + CHECK(e && e->preset == 0x16 && e->bands.empty()); + } + CHECK(!parseEqualizer(bytes({ 0x23, 0x00, 0x44, 0x00 })).has_value()); // battery reply + + // --- Framing --- + // Round trip, with a payload byte (0x3c = END_MARKER) that must be escaped. + { + Buffer payload = bytes({ 0x68, 0x17, 0x01, 0x01, 0x01, 0x00, 0x3c }); + auto frame = CommandSerializer::packageDataForBt(payload, DATA_TYPE::DATA_MDR, 1); + CHECK(frame.front() == START_MARKER && frame.back() == END_MARKER); + auto msg = CommandSerializer::unpackBtMessage(Buffer(frame.begin() + 1, frame.end() - 1)); + CHECK(msg.dataType == DATA_TYPE::DATA_MDR && msg.seqNumber == 1 && msg.payload == payload); + } + // Real WH-1000XM6 battery frame (68 %), between the 3e/3c markers. + { + auto msg = CommandSerializer::unpackBtMessage(bytes({ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x04, 0x23, 0x00, 0x44, 0x00, 0x77 })); + CHECK(msg.payload == bytes({ 0x23, 0x00, 0x44, 0x00 })); + } + + if (failures) { std::printf("ProtocolParsersTests: %d failure(s)\n", failures); return 1; } + std::printf("ProtocolParsersTests: all passed\n"); + return 0; +} +``` + +- [ ] **Step 2 : Brancher le test dans `scripts/test.sh`**, juste avant `echo "== Localization"` : + +```bash +echo "== ProtocolParsersTests" +clang++ -target "$TARGET" -isysroot "$SDK" -std=c++17 -I "$ROOT/Client" \ + "$ROOT/Client/tests/ProtocolParsersTests.cpp" "$ROOT/Client/ProtocolParsers.cpp" \ + "$ROOT/Client/CommandSerializer.cpp" "$ROOT/Client/ByteMagic.cpp" \ + -o "$OUT/ProtocolParsersTests" +"$OUT/ProtocolParsersTests" +``` + +- [ ] **Step 3 : Voir le test échouer** + +Run : `make test` +Attendu : échec, `'ProtocolParsers.h' file not found`. + +- [ ] **Step 4 : Écrire `Client/ProtocolParsers.h`** + +```cpp +#pragma once + +#include +#include +#include "Constants.h" + +// Pure decoders for v2 inquiry replies. `payload` is the frame's field, starting with the reply opcode. +namespace ProtocolParsers +{ + struct NcAsmState + { + bool enabled; // NC/ASM effect on + bool ambient; // true = Ambient Sound, false = Noise Cancelling + bool focusOnVoice; + int level; // ambient level (meaningful when ambient) + }; + + // Accepts "67|69 17 01 " and the WH-1000XM6 "67|69 19 01 + // ". Returns nullopt when too short, for other opcodes, and for the all-zero body the XM6 sends + // back on the channel it doesn't use (67 17 00 00 00 00 00). + std::optional parseNcAsmState(const Buffer& payload); + + struct EqualizerState + { + unsigned char preset; // raw preset id (EQ_PRESET values, or ids we don't know yet like 0x30) + bool hasClearBass; // 5-band layout only + int clearBass; // -10..10 when hasClearBass + std::vector bands; // 5 or 10 values in -10..10; empty when the reply carried no band data + }; + + // "57 00 06 " (5 bands + Clear Bass) or "57 00 0a ". + std::optional parseEqualizer(const Buffer& payload); +} +``` + +- [ ] **Step 5 : Écrire `Client/ProtocolParsers.cpp`** + +```cpp +#include "ProtocolParsers.h" + +#include + +namespace ProtocolParsers +{ + std::optional parseNcAsmState(const Buffer& payload) + { + if (payload.size() < 7) return std::nullopt; + auto opcode = (unsigned char)payload[0]; + auto type = (unsigned char)payload[1]; + if ((opcode != 0x67 && opcode != 0x69) || (type != 0x17 && type != 0x19)) return std::nullopt; + if (std::all_of(payload.begin() + 2, payload.end(), [](char b) { return b == 0; })) return std::nullopt; + + NcAsmState state; + state.enabled = payload[3] != 0; + state.ambient = payload[4] != 0; + state.focusOnVoice = payload[5] != 0; + state.level = (unsigned char)payload[6]; + return state; + } + + std::optional parseEqualizer(const Buffer& payload) + { + if (payload.size() < 3 || (unsigned char)payload[0] != 0x57) return std::nullopt; + + EqualizerState state{ (unsigned char)payload[2], false, 0, {} }; + if (payload.size() < 4) return state; + size_t count = (unsigned char)payload[3]; + if (payload.size() < 4 + count) return state; + + auto value = [&](size_t i) { return (int)(unsigned char)payload[4 + i] - 10; }; + if (count == 6) + { + state.hasClearBass = true; + state.clearBass = value(0); + for (size_t i = 1; i < 6; i++) state.bands.push_back(value(i)); + } + else if (count == 10) + { + for (size_t i = 0; i < 10; i++) state.bands.push_back(value(i)); + } + return state; + } +} +``` + +- [ ] **Step 6 : Relancer les tests** + +Run : `make test` +Attendu : `LogicTests: all passed`, `ProtocolParsersTests: all passed`, `Localization: 15 keys, all translated`. + +- [ ] **Step 7 : Brancher les décodeurs dans `Client/Headphones.h`** + +Sous `void requestEqualizer();` / `EQ_PRESET getEqualizerPreset();`, ajouter : + +```cpp + int getEqualizerBandCount(); // 0 until read, then 5 (+ Clear Bass) or 10 + bool equalizerHasClearBass(); +``` + +Sous `void requestAmbientState();`, ajouter : + +```cpp + // Picks the NC/ASM inquiry channel: 0x19 when the device answers it (WH-1000XM6), else the legacy 0x17. + void probeNcAsmInquiryType(); +``` + +Remplacer le membre `std::vector _eqBands = { 0, 0, 0, 0, 0 };` par : + +```cpp + std::vector _eqBands; // empty until the first read; 5 or 10 values + bool _eqHasClearBass = false; + unsigned char _ncAsmInquiryType = 0x17; // 0x19 on the WH-1000XM6, see probeNcAsmInquiryType() +``` + +- [ ] **Step 8 : Modifier `Client/Headphones.cpp`** + +Ajouter `#include "ProtocolParsers.h"` après `#include "CommandSerializer.h"`. + +Remplacer tout le corps de `Headphones::requestEqualizer()` par : + +```cpp +void Headphones::requestEqualizer() +{ + // GET: 56 00 -> RET: 57 00 (decoded by ProtocolParsers::parseEqualizer) + auto resp = this->_conn.sendCommandAndReadResponse({ (char)V2Command::EQ_GET, 0x00 }, V2Command::EQ_RET); + if (auto eq = ProtocolParsers::parseEqualizer(resp)) + { + std::lock_guard guard(this->_propertyMtx); + this->_eqPreset = static_cast(eq->preset); + if (!eq->bands.empty()) + { + this->_eqBands = eq->bands; + this->_eqHasClearBass = eq->hasClearBass; + this->_eqClearBass = eq->clearBass; + } + } +} + +int Headphones::getEqualizerBandCount() { return (int)this->_eqBands.size(); } +bool Headphones::equalizerHasClearBass() { return this->_eqHasClearBass; } +``` + +Dans `Headphones::setEqualizerCustom`, remplacer la boucle finale qui écrit `this->_eqBands[i]` par : + +```cpp + this->_eqBands.assign(bands.begin(), bands.end()); +``` + +Dans `Headphones::requestAmbientState()`, remplacer le bloc `if (protocolVersion == SonyProtocolVersion::V2) { … }` par : + +```cpp + if (protocolVersion == SonyProtocolVersion::V2) + { + // GET: 66 -> RET: 67 01 <0=NC/1=Ambient> [2 more bytes on 0x19] + auto resp = this->_conn.sendCommandAndReadResponse({ 0x66, (char)this->_ncAsmInquiryType }, 0x67, this->_ncAsmInquiryType); + if (auto state = ProtocolParsers::parseNcAsmState(resp)) + { + std::lock_guard guard(this->_propertyMtx); + // Update both current and desired so the UI reflects reality and isChanged() stays false. + this->_ambientSoundControl.current = this->_ambientSoundControl.desired = state->enabled; + this->_asmLevel.current = this->_asmLevel.desired = state->ambient ? state->level : 0; + this->_focusOnVoice.current = this->_focusOnVoice.desired = state->focusOnVoice; + } + } +``` + +Ajouter après `requestAmbientState()` : + +```cpp +void Headphones::probeNcAsmInquiryType() +{ + // The WH-1000XM6 answers the legacy 0x17 inquiry with all zeros and reports its real state on 0x19. + // Setting the mode still goes through 68 17, which the XM6 accepts. + try + { + auto resp = this->_conn.sendCommandAndReadResponse({ 0x66, 0x19 }, 0x67, 0x19); + if (ProtocolParsers::parseNcAsmState(resp)) this->_ncAsmInquiryType = 0x19; + } + catch (...) {} +} +``` + +- [ ] **Step 9 : Exposer l'égaliseur dans `Client/macos/HeadphonesBridge.h`** + +Sous `@property (nonatomic, readonly) BOOL supportsEqualizer;`, ajouter : + +```objc +@property (nonatomic, readonly) NSInteger equalizerBandCount; // 0 until read, then 5 or 10 +@property (nonatomic, readonly) BOOL equalizerHasClearBass; // 5-band layout +// NO while this device's equalizer write format is unverified (the WH-1000XM6's 10-band layout, spec §7). +@property (nonatomic, readonly) BOOL equalizerWritable; +``` + +- [ ] **Step 10 : Modifier `Client/macos/HeadphonesBridge.mm`** + +Après `- (NSInteger)clearBass { … }`, ajouter : + +```objc +- (NSInteger)equalizerBandCount { return _hp ? _hp->getEqualizerBandCount() : 0; } +- (BOOL)equalizerHasClearBass { return _hp && _hp->equalizerHasClearBass(); } +// Only the 5-band + Clear Bass layout (WH-CH720N family) has a verified write format. +- (BOOL)equalizerWritable { return self.supportsEqualizer && _hp && _hp->equalizerHasClearBass(); } +``` + +Dans `refreshStatusWithCompletion:`, remplacer : + +```objc + if (!self->_initialized) { + hp->initDevice(); + self->_initialized = YES; + } +``` + +par : + +```objc + if (!self->_initialized) { + hp->initDevice(); + hp->probeNcAsmInquiryType(); + self->_initialized = YES; + } +``` + +Dans `setEqualizerPreset:completion:`, remplacer la condition +`if (_bt->getProtocolVersion() != SonyProtocolVersion::V2) {` par `if (!self.equalizerWritable) {`. +Dans `setCustomEqualizerBass:bands:completion:`, remplacer +`if (!_hp || !self.connected || _bt->getProtocolVersion() != SonyProtocolVersion::V2) {` par +`if (!_hp || !self.connected || !self.equalizerWritable) {`. + +- [ ] **Step 11 : Compiler et tester** + +Run : `make test && make` +Attendu : les trois lignes « all passed / all translated », puis `OK -> …/build/SonyBridge.app`. + +- [ ] **Step 12 : Vérifier sur le XM6 avec l'utilisateur** + +Run : `make run DEBUG=1`, demander à l'utilisateur de cliquer sur « Connecter… », puis +`grep -E '\[send\].* 66 19|\[recv\].* 67 19' build/app.log | head -4` +Attendu : une demande `66 19` et une réponse `67 19 …` non nulle. +Demander ensuite à l'utilisateur : +1. Choisir « Son ambiant » dans le menu : la coche **reste** sur « Son ambiant » (plus de retour sur + « Désactivé »). +2. Appuyer sur le bouton NC du casque : en 2 s environ, la coche suit le mode du casque (menu fermé puis + rouvert ; les mises à jour menu ouvert viennent en tâche 4). + +- [ ] **Step 13 : Commit** (par l'utilisateur) + +```bash +git add -A && git commit -m "fix(xm6): read NC/ASM state on channel 0x19, decode 10-band equalizer (read-only)" +``` + +--- + +### Task 4: Nouveau `HeadphonesModel` (état, minuteurs menu ouvert, anti-retour, limitation, batterie) + +Réécrit le modèle pour le menu : un état de connexion unique, les propriétés en lecture seule, les minuteurs +en mode `.common`, `PollGuard` et `SendThrottle`, la relecture de la batterie toutes les 60 s, et les erreurs +affichées seulement pour les actions de l'utilisateur. + +**Files:** +- Modify (réécriture complète) : `Client/macos/HeadphonesModel.swift` +- Modify : `Client/macos/HeadphonesBridge.h/.mm` (`refreshBatteryWithCompletion:`), + `Client/macos/StatusItemController.swift`, `Client/macos/HeadphonesMenu.swift`, + `Client/macos/fr.lproj/Localizable.strings` + +**Interfaces:** +- Consumes : `PollGuard`, `SendThrottle` (tâche 2) ; `equalizerBandCount`, `equalizerHasClearBass`, + `equalizerWritable` (tâche 3). +- Produces (utilisé par les tâches 5 à 8) : + - `enum ConnectionState { case disconnected, connecting, connected }` + - `HeadphonesModel` : `connectionState`, `connected` (calculé), `deviceName`, `deviceMac`, `protocolVersion`, + `firmware`, `codec`, `maxAmbientLevel`, `mode`, `ambientLevel`, `focusOnVoice`, `batteryLevel`, + `batteryCharging`, `hasDualBattery`, `batteryLeft`, `batteryRight`, `batteryCase`, `supportsEqualizer`, + `equalizerWritable`, `eqPreset: Int`, `eqBands: [Int]`, `eqHasClearBass`, `clearBass`, `dsee`, + `hasAutoPowerOff`, `autoPowerOff`, `hasSpeakToChat`, `speakToChat`, `hasAdaptiveVolume`, `adaptiveVolume`, + `errorMessage: String?` (tous `@Published private(set)`) + - Actions : `connect()`, `disconnect()`, `setMode(_:)`, `setLevel(_:final:)`, `setFocusOnVoice(_:)`, + `setEqualizerPreset(_:)`, `setEqualizerBand(_:value:final:)`, `setClearBass(_:final:)`, `resetEqualizer()`, + `setDsee(_:)`, `setAutoPowerOff(_:)`, `setSpeakToChat(_:)`, `setAdaptiveVolume(_:)`, `showError(_:)` + - Point d'extension pour la tâche 7 : `handleConnectResult(ok:error:userInitiated:)` et `linkLost()` + +- [ ] **Step 1 : Ajouter la relecture de la batterie au pont** + +`Client/macos/HeadphonesBridge.h`, sous `refreshDynamicWithCompletion:` : + +```objc +// Re-reads the battery level (v2 devices only). Completion on the main thread. +- (void)refreshBatteryWithCompletion:(void (^)(void))completion; +``` + +`Client/macos/HeadphonesBridge.mm`, après `refreshDynamicWithCompletion:` : + +```objc +- (void)refreshBatteryWithCompletion:(void (^)(void))completion { + // CRITICAL: 0x22 is BATTERY_LEVEL_REQUEST on v2 but POWER_OFF on v1 - never send it to a v1 device. + if (!_hp || !self.connected || _bt->getProtocolVersion() != SonyProtocolVersion::V2) { completion(); return; } + Headphones *hp = _hp.get(); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + try { hp->requestBattery(); } catch (std::exception &exc) {} + dispatch_async(dispatch_get_main_queue(), ^{ completion(); }); + }); +} +``` + +- [ ] **Step 2 : Réécrire `Client/macos/HeadphonesModel.swift`** + +```swift +import Foundation +import Combine + +enum ConnectionState { + case disconnected, connecting, connected +} + +// Observable state of the headphones and the actions the menu triggers. Wraps the Obj-C++ HeadphonesBridge. +final class HeadphonesModel: ObservableObject { + private enum PolledSetting { case ambient } + + private let bridge = HeadphonesBridge() + + @Published private(set) var connectionState: ConnectionState = .disconnected + var connected: Bool { connectionState == .connected } + + // Kept after a disconnect so the header still names the last headset. + @Published private(set) var deviceName = "" + @Published private(set) var deviceMac = "" + @Published private(set) var protocolVersion = "" + @Published private(set) var firmware = "" + @Published private(set) var codec = "" + @Published private(set) var maxAmbientLevel = 20 + + @Published private(set) var mode: SHCAmbientMode = .off + @Published private(set) var ambientLevel = 10 + @Published private(set) var focusOnVoice = false + + @Published private(set) var batteryLevel = -1 + @Published private(set) var batteryCharging = false + @Published private(set) var hasDualBattery = false + @Published private(set) var batteryLeft = -1 + @Published private(set) var batteryRight = -1 + @Published private(set) var batteryCase = -1 + + @Published private(set) var supportsEqualizer = false + @Published private(set) var equalizerWritable = false + @Published private(set) var eqPreset = 0 + @Published private(set) var eqBands: [Int] = [] + @Published private(set) var eqHasClearBass = false + @Published private(set) var clearBass = 0 + @Published private(set) var dsee = false + + @Published private(set) var hasAutoPowerOff = false + @Published private(set) var autoPowerOff = 0 + @Published private(set) var hasSpeakToChat = false + @Published private(set) var speakToChat = false + @Published private(set) var hasAdaptiveVolume = false + @Published private(set) var adaptiveVolume = false + + // Last error from a user action; cleared by the next successful one. + @Published private(set) var errorMessage: String? + + private var timers: [Timer] = [] + private var pollGuard = PollGuard() + private var levelThrottle = SendThrottle() + private var eqThrottle = SendThrottle() + + // MARK: - Connection + + // User-initiated: uses the already-connected Sony headset, else the macOS Bluetooth picker. + func connect() { + connectionState = .connecting + errorMessage = nil + // Defer so the menu can show "Connecting…" before a modal picker blocks the main thread. + DispatchQueue.main.async { + self.bridge.scanAndConnect { ok, error in + self.handleConnectResult(ok: ok, error: error, userInitiated: true) + } + } + } + + func disconnect() { + stopTimers() + bridge.disconnect() + connectionState = .disconnected + } + + func handleConnectResult(ok: Bool, error: String?, userInitiated: Bool) { + guard ok else { + connectionState = .disconnected + if userInitiated, let error = error { errorMessage = error } + return + } + connectionState = .connected + syncFromBridge() + bridge.refreshStatus { [weak self] in self?.syncFromBridge() } // called after reads, then after probes + startTimers() + } + + // The control link dropped on its own (idle power-save). Task 7 adds the automatic reconnection here. + func linkLost() { + stopTimers() + connectionState = .disconnected + } + + // MARK: - Actions + + func setMode(_ newMode: SHCAmbientMode) { + mode = newMode + pollGuard.userChanged(.ambient) + pushAmbient() + } + + func setLevel(_ level: Int, final: Bool) { + ambientLevel = level + pollGuard.userChanged(.ambient) + if mode == .ambientSound && levelThrottle.shouldSend(final: final) { pushAmbient() } + } + + func setFocusOnVoice(_ on: Bool) { + focusOnVoice = on + pollGuard.userChanged(.ambient) + pushAmbient() + } + + func setEqualizerPreset(_ preset: Int) { + eqPreset = preset + bridge.setEqualizerPreset(preset) { [weak self] ok, error in self?.finish(ok, error) } + } + + func setEqualizerBand(_ index: Int, value: Int, final: Bool) { + guard eqBands.indices.contains(index) else { return } + eqBands[index] = value + eqPreset = 0xA0 + if eqThrottle.shouldSend(final: final) { pushCustomEqualizer() } + } + + func setClearBass(_ value: Int, final: Bool) { + clearBass = value + eqPreset = 0xA0 + if eqThrottle.shouldSend(final: final) { pushCustomEqualizer() } + } + + func resetEqualizer() { + eqBands = Array(repeating: 0, count: eqBands.count) + clearBass = 0 + eqPreset = 0xA0 + pushCustomEqualizer() + } + + func setDsee(_ on: Bool) { + dsee = on + bridge.setDsee(on) { [weak self] ok, error in self?.finish(ok, error) } + } + + func setAutoPowerOff(_ index: Int) { + autoPowerOff = index + bridge.setAutoPowerOff(index) { [weak self] ok, error in self?.finish(ok, error) } + } + + func setSpeakToChat(_ on: Bool) { + speakToChat = on + bridge.setSpeakToChat(on) { [weak self] ok, error in self?.finish(ok, error) } + } + + func setAdaptiveVolume(_ on: Bool) { + adaptiveVolume = on + bridge.setAdaptiveVolume(on) { [weak self] ok, error in self?.finish(ok, error) } + } + + func showError(_ message: String) { + errorMessage = message + } + + private func pushAmbient() { + bridge.applyMode(mode, level: ambientLevel, focusVoice: focusOnVoice) { [weak self] ok, error in + self?.finish(ok, error) + } + } + + private func pushCustomEqualizer() { + bridge.setCustomEqualizerBass(clearBass, bands: eqBands.map { NSNumber(value: $0) }) { [weak self] ok, error in + self?.finish(ok, error) + } + } + + private func finish(_ ok: Bool, _ error: String?) { + errorMessage = ok ? nil : error + } + + // MARK: - Polling + + private func startTimers() { + stopTimers() + timers = [ + repeating(every: 1.5) { [weak self] in self?.checkLink() }, + repeating(every: 2) { [weak self] in self?.pollAmbient() }, + repeating(every: 60) { [weak self] in self?.pollBattery() }, + ] + } + + private func stopTimers() { + timers.forEach { $0.invalidate() } + timers = [] + } + + // Added in .common mode so they keep firing while the menu is open (menus run the event-tracking mode). + private func repeating(every interval: TimeInterval, _ block: @escaping () -> Void) -> Timer { + let timer = Timer(timeInterval: interval, repeats: true) { _ in block() } + RunLoop.main.add(timer, forMode: .common) + return timer + } + + private func checkLink() { + if connected && !bridge.connected { linkLost() } + } + + // Follows the headset's own NC button, unless the user just changed the mode from the menu. + private func pollAmbient() { + guard connected, pollGuard.shouldAcceptPoll(for: .ambient) else { return } + bridge.refreshDynamic { [weak self] in + guard let self = self, self.pollGuard.shouldAcceptPoll(for: .ambient) else { return } + self.readAmbientFromBridge() + } + } + + private func pollBattery() { + guard connected else { return } + bridge.refreshBattery { [weak self] in self?.readBatteryFromBridge() } + } + + // MARK: - Reading the bridge + + private func syncFromBridge() { + deviceName = bridge.deviceName ?? deviceName + deviceMac = bridge.deviceMac ?? deviceMac + protocolVersion = bridge.protocolVersionString ?? "" + maxAmbientLevel = bridge.maxAmbientLevel + readAmbientFromBridge() + readBatteryFromBridge() + supportsEqualizer = bridge.supportsEqualizer + equalizerWritable = bridge.equalizerWritable + eqPreset = bridge.eqPreset + eqHasClearBass = bridge.equalizerHasClearBass + clearBass = bridge.clearBass + eqBands = (0.. 0 { ambientLevel = level } + focusOnVoice = bridge.focusOnVoice + } + + private func readBatteryFromBridge() { + batteryLevel = bridge.batteryLevel + batteryCharging = bridge.batteryCharging + hasDualBattery = bridge.hasDualBattery + batteryLeft = bridge.batteryLeft + batteryRight = bridge.batteryRight + batteryCase = bridge.batteryCase + } +} +``` + +- [ ] **Step 3 : Adapter l'icône et le menu minimal au nouvel état** + +`Client/macos/StatusItemController.swift` : remplacer le bloc `model.$connected … .store(in: &cancellables)` par : + +```swift + model.$connectionState + .receive(on: DispatchQueue.main) + .sink { [weak self] state in self?.statusItem.button?.appearsDisabled = state != .connected } + .store(in: &cancellables) +``` + +`Client/macos/HeadphonesMenu.swift`, dans `update()` : remplacer +`(model.connecting ? tr("Connecting…") : tr("Connect…"))` par +`(model.connectionState == .connecting ? tr("Connecting…") : tr("Connect…"))`, et +`connectItem.isEnabled = !model.connecting` par `connectItem.isEnabled = model.connectionState != .connecting`. + +- [ ] **Step 4 : Retirer la clé devenue inutile** + +Dans `Client/macos/fr.lproj/Localizable.strings`, supprimer la ligne `"Headphones disconnected." = …;` (le +modèle n'affiche plus d'erreur quand la liaison se coupe d'elle-même). + +- [ ] **Step 5 : Tests et build** + +Run : `make test && make` +Attendu : tout passe, `Localization: 14 keys, all translated`, puis `OK -> …`. + +- [ ] **Step 6 : Vérifier avec l'utilisateur** + +Run : `make run DEBUG=1`. Demander à l'utilisateur de : +1. Se connecter, **ouvrir le menu et le laisser ouvert**, puis appuyer sur le bouton NC du casque : la coche + change pendant que le menu est ouvert (les minuteurs tournent en mode `.common`). +2. Choisir « Son ambiant » : la coche ne revient pas en arrière. +Après au moins 2 minutes connecté : `grep -c '\[send\].* 22 00' build/app.log` → au moins 2 (lecture à la +connexion + relecture toutes les 60 s). + +- [ ] **Step 7 : Commit** (par l'utilisateur) + +```bash +git add -A && git commit -m "refactor(macos): menu-oriented HeadphonesModel (connection state, common-mode timers, poll guard, battery polling)" +``` + +--- + +### Task 5: Lignes riches du menu (vues SwiftUI hébergées) + +Crée les quatre vues et les vérifie tôt dans le vrai menu : c'est le risque technique principal (spec §11). +Les curseurs de l'égaliseur sont des `NSSlider` natifs verticaux (via `NSViewRepresentable`) : les contrôles +AppKit suivent la souris de façon fiable dans un menu. + +**Files:** +- Modify : `Client/macos/MenuSupport.swift` (`MenuMetrics`, `hostingMenuItem`) +- Create : `Client/macos/MenuRows/HeaderRow.swift`, `AmbientLevelRow.swift`, `ToggleRow.swift`, `EqualizerRow.swift` +- Modify : `Client/macos/HeadphonesMenu.swift` (branchement provisoire de l'en-tête et du curseur), + `Client/macos/fr.lproj/Localizable.strings` + +**Interfaces:** +- Consumes : l'API `HeadphonesModel` de la tâche 4. +- Produces : + - `enum MenuMetrics { static let width: CGFloat; static let equalizerWidth: CGFloat; static let leading: CGFloat; static let indent: CGFloat }` + - `func hostingMenuItem(width: CGFloat = MenuMetrics.width, @ViewBuilder _ content: () -> Content) -> NSMenuItem` + - `struct HeaderRow: View { init(model:) }`, `struct AmbientLevelRow: View { init(model:) }`, + `struct ToggleRow: View { init(model:title:indent:isOn:set:) }`, `struct EqualizerRow: View { init(model:) }` + +- [ ] **Step 1 : Ajouter à `Client/macos/MenuSupport.swift`** (ajouter `import SwiftUI` en tête du fichier) + +```swift +enum MenuMetrics { + static let width: CGFloat = 280 // main menu rows + static let equalizerWidth: CGFloat = 300 // equalizer submenu + static let leading: CGFloat = 14 // lines up with native item titles + static let indent: CGFloat = 36 // rows nested under "Son ambiant" +} + +// Wraps a SwiftUI view in a menu item, for rows a plain NSMenuItem can't express (sliders, switches, header). +// Rows keep a fixed height: optional lines (the error line, notes) are separate plain items instead. +func hostingMenuItem(width: CGFloat = MenuMetrics.width, @ViewBuilder _ content: () -> Content) -> NSMenuItem { + let host = NSHostingView(rootView: content().frame(width: width, alignment: .leading)) + host.frame = NSRect(origin: .zero, size: host.fittingSize) + let item = NSMenuItem() + item.view = host + return item +} +``` + +- [ ] **Step 2 : Écrire `Client/macos/MenuRows/HeaderRow.swift`** + +```swift +import SwiftUI + +// Menu header: headset name, connection state + codec, battery. +struct HeaderRow: View { + @ObservedObject var model: HeadphonesModel + + var body: some View { + HStack(alignment: .center, spacing: 8) { + VStack(alignment: .leading, spacing: 1) { + Text(model.deviceName.isEmpty ? "SonyBridge" : model.deviceName) + .font(.system(size: 13, weight: .semibold)) + Text(statusLine) + .font(.system(size: 11)) + .foregroundColor(.secondary) + } + Spacer(minLength: 8) + if model.connected { battery } + } + .padding(.horizontal, MenuMetrics.leading) + .padding(.vertical, 4) + } + + private var statusLine: String { + switch model.connectionState { + case .connecting: return tr("Connecting…") + case .disconnected: return tr("Not connected") + case .connected: return model.codec.isEmpty ? tr("Connected") : "\(tr("Connected")) · \(model.codec)" + } + } + + @ViewBuilder private var battery: some View { + if model.hasDualBattery { + Text(String(format: tr("L %ld%% R %ld%%"), model.batteryLeft, model.batteryRight)) + .font(.system(size: 12)) + .foregroundColor(.secondary) + } else if model.batteryLevel >= 0 { + HStack(spacing: 4) { + Text(String(format: tr("%ld%%"), model.batteryLevel)) + .font(.system(size: 12)) + .foregroundColor(.secondary) + Image(systemName: batterySymbol) + .foregroundColor(model.batteryLevel <= 20 && !model.batteryCharging ? .red : .secondary) + } + } + } + + private var batterySymbol: String { + if model.batteryCharging { return "battery.100.bolt" } + switch model.batteryLevel { + case ..<13: return "battery.0" + case ..<38: return "battery.25" + case ..<63: return "battery.50" + case ..<88: return "battery.75" + default: return "battery.100" + } + } +} +``` + +- [ ] **Step 3 : Écrire `Client/macos/MenuRows/AmbientLevelRow.swift`** + +```swift +import SwiftUI + +// Ambient Sound level slider (1…max), shown under "Son ambiant". +struct AmbientLevelRow: View { + @ObservedObject var model: HeadphonesModel + + var body: some View { + HStack(spacing: 8) { + Slider( + value: Binding(get: { Double(model.ambientLevel) }, + set: { model.setLevel(Int($0.rounded()), final: false) }), + in: 1...Double(max(model.maxAmbientLevel, 2)), + step: 1, + onEditingChanged: { editing in + if !editing { model.setLevel(model.ambientLevel, final: true) } + } + ) + .controlSize(.small) + Text(verbatim: "\(model.ambientLevel)") + .font(.system(size: 11, weight: .medium).monospacedDigit()) + .foregroundColor(.secondary) + .frame(width: 20, alignment: .trailing) + } + .padding(.leading, MenuMetrics.indent) + .padding(.trailing, MenuMetrics.leading) + .padding(.vertical, 2) + .disabled(!model.connected) + } +} +``` + +- [ ] **Step 4 : Écrire `Client/macos/MenuRows/ToggleRow.swift`** + +```swift +import SwiftUI + +// A title with a switch on the right (Focus on Voice, DSEE, Speak-to-Chat, Adaptive Volume). +struct ToggleRow: View { + @ObservedObject var model: HeadphonesModel + let title: String + var indent: CGFloat = MenuMetrics.leading + let isOn: (HeadphonesModel) -> Bool + let set: (HeadphonesModel, Bool) -> Void + + var body: some View { + HStack { + Text(title).font(.system(size: 13)) + Spacer(minLength: 8) + Toggle("", isOn: Binding(get: { isOn(model) }, set: { set(model, $0) })) + .labelsHidden() + .toggleStyle(.switch) + .controlSize(.mini) + } + .padding(.leading, indent) + .padding(.trailing, MenuMetrics.leading) + .padding(.vertical, 2) + .disabled(!model.connected) + .opacity(model.connected ? 1 : 0.5) + } +} +``` + +- [ ] **Step 5 : Écrire `Client/macos/MenuRows/EqualizerRow.swift`** + +```swift +import AppKit +import SwiftUI + +// Manual equalizer: 10 vertical sliders (WH-1000XM6) or Clear Bass + 5 (older models). Active only on "Manual" +// and when the device's write format is verified (model.equalizerWritable). +struct EqualizerRow: View { + @ObservedObject var model: HeadphonesModel + + private static let labels5 = ["400", "1k", "2.5k", "6.3k", "16k"] + private static let labels10 = ["31", "63", "125", "250", "500", "1k", "2k", "4k", "8k", "16k"] + + private var editable: Bool { model.connected && model.equalizerWritable && model.eqPreset == 0xA0 } + private var labels: [String] { model.eqBands.count == 10 ? Self.labels10 : Self.labels5 } + + var body: some View { + HStack(alignment: .top, spacing: 0) { + if model.eqHasClearBass { + band(tr("Clear Bass"), value: model.clearBass) { model.setClearBass($0, final: $1) } + } + ForEach(Array(model.eqBands.enumerated()), id: \.offset) { index, value in + band(index < labels.count ? labels[index] : "", value: value) { + model.setEqualizerBand(index, value: $0, final: $1) + } + } + } + .padding(.horizontal, MenuMetrics.leading) + .padding(.vertical, 6) + } + + private func band(_ label: String, value: Int, onChange: @escaping (Int, Bool) -> Void) -> some View { + VStack(spacing: 3) { + VerticalBandSlider(value: value, enabled: editable, onChange: onChange) + .frame(width: 20, height: 72) + Text(verbatim: label) + .font(.system(size: 9)) + .foregroundColor(.secondary) + .lineLimit(1) + } + .frame(maxWidth: .infinity) + } +} + +// A native vertical NSSlider in -10…10. onChange(value, final): final is true on mouse-up. +struct VerticalBandSlider: NSViewRepresentable { + let value: Int + let enabled: Bool + let onChange: (Int, Bool) -> Void + + func makeCoordinator() -> Coordinator { + Coordinator(onChange: onChange) + } + + func makeNSView(context: Context) -> NSSlider { + let slider = NSSlider(value: Double(value), minValue: -10, maxValue: 10, + target: context.coordinator, action: #selector(Coordinator.changed(_:))) + slider.isVertical = true + slider.isContinuous = true + slider.controlSize = .small + return slider + } + + func updateNSView(_ slider: NSSlider, context: Context) { + context.coordinator.onChange = onChange + if Int(slider.doubleValue.rounded()) != value { slider.doubleValue = Double(value) } + slider.isEnabled = enabled + } + + final class Coordinator: NSObject { + var onChange: (Int, Bool) -> Void + + init(onChange: @escaping (Int, Bool) -> Void) { + self.onChange = onChange + } + + @objc func changed(_ sender: NSSlider) { + let final = NSApp.currentEvent?.type == .leftMouseUp + onChange(Int(sender.doubleValue.rounded()), final) + } + } +} +``` + +- [ ] **Step 6 : Ajouter les nouvelles clés à `Client/macos/fr.lproj/Localizable.strings`** (section « Menu ») + +``` +"Not connected" = "Non connecté"; +"Connected" = "Connecté"; +"L %ld%% R %ld%%" = "G %ld %% D %ld %%"; +"Clear Bass" = "Clear Bass"; +``` + +- [ ] **Step 7 : Branchement provisoire dans le menu minimal** (remplacé entièrement en tâche 6) + +Dans `Client/macos/HeadphonesMenu.swift` : +- Remplacer `headerItem.isEnabled = false` / `menu.addItem(headerItem)` par + `menu.addItem(hostingMenuItem { HeaderRow(model: model) })`, supprimer la propriété `headerItem` et, dans + `update()`, les lignes qui construisent `header` et affectent `headerItem.title`. +- Dans la boucle des modes, juste après `menu.addItem(item)`, ajouter : + +```swift + if mode == .ambientSound { + menu.addItem(hostingMenuItem { AmbientLevelRow(model: model) }) + menu.addItem(hostingMenuItem { + ToggleRow(model: model, title: tr("Focus on Voice"), indent: MenuMetrics.indent, + isOn: { $0.focusOnVoice }, set: { $0.setFocusOnVoice($1) }) + }) + } +``` + +et la clé `"Focus on Voice" = "Focalisation sur la voix";` dans `Localizable.strings`. + +- [ ] **Step 8 : Tests et build** + +Run : `make test && make` +Attendu : tout passe, `Localization: 19 keys, all translated` (la clé `"%ld%%"` sert maintenant à +`HeaderRow` ; `update()` ne l'utilise plus), puis `OK -> …`. + +- [ ] **Step 9 : Vérifier avec l'utilisateur** + +Run : `make run`. Demander à l'utilisateur, casque connecté : +1. L'en-tête montre le nom, « Connecté · AAC » et la batterie avec son icône, bien alignés, sans être coupés. +2. Le curseur de niveau se **fait glisser** dans le menu ouvert, et le son ambiant change dans le casque + pendant le glissement (au plus toutes les 150 ms) et au relâchement. +3. L'interrupteur « Focalisation sur la voix » bascule, et le menu reste ouvert. +Si le glissement ou l'interrupteur ne réagissent pas dans le menu : **arrêter** et remonter le problème avant +la tâche 6. Toute l'approche en dépend. + +- [ ] **Step 10 : Commit** (par l'utilisateur) + +```bash +git add -A && git commit -m "feat(macos): SwiftUI menu rows (header, level slider, switches, equalizer)" +``` + +--- + +### Task 6: Menu complet (spec §4) + icône selon le mode + +**Files:** +- Modify (réécriture complète) : `Client/macos/HeadphonesMenu.swift`, `Client/macos/StatusItemController.swift` +- Create : `Client/macos/StatusIcon.swift` +- Modify : `Client/macos/MenuSupport.swift` (`titleWithValue`), `Client/macos/fr.lproj/Localizable.strings` + +**Interfaces:** +- Consumes : tâches 1, 4 et 5. +- Produces : + - `enum StatusIcon { static func symbolName(for: SHCAmbientMode) -> String; static func image(connected: Bool, mode: SHCAmbientMode) -> NSImage? }` + - `func titleWithValue(_ title: String, _ value: String, width: CGFloat = MenuMetrics.width - 60) -> NSAttributedString` + - `HeadphonesMenu` : `private var connectItem` et la méthode `addAppSection()`, où la tâche 7 insère le + sous-menu des options. + +- [ ] **Step 1 : Ajouter `titleWithValue` à `Client/macos/MenuSupport.swift`** + +```swift +// "Title value": the value right-aligned in the secondary color, like "Égaliseur Graves ›". +func titleWithValue(_ title: String, _ value: String, width: CGFloat = MenuMetrics.width - 60) -> NSAttributedString { + let paragraph = NSMutableParagraphStyle() + paragraph.tabStops = [NSTextTab(textAlignment: .right, location: width)] + let font = NSFont.menuFont(ofSize: 0) + let text = NSMutableAttributedString(string: title, attributes: [.font: font, .paragraphStyle: paragraph]) + if !value.isEmpty { + text.append(NSAttributedString(string: "\t" + value, attributes: [ + .font: font, .paragraphStyle: paragraph, .foregroundColor: NSColor.secondaryLabelColor, + ])) + } + return text +} +``` + +- [ ] **Step 2 : Écrire `Client/macos/StatusIcon.swift`** + +```swift +import AppKit + +// Menu bar icon: one monochrome SF Symbol per mode, dimmed when disconnected (spec §6.6). +enum StatusIcon { + static func symbolName(for mode: SHCAmbientMode) -> String { + switch mode { + case .noiseCanceling: return "headphones.circle.fill" + case .ambientSound: return "ear.and.waveform" + default: return "headphones" + } + } + + static func image(connected: Bool, mode: SHCAmbientMode) -> NSImage? { + let name = connected ? symbolName(for: mode) : "headphones" + let image = NSImage(systemSymbolName: name, accessibilityDescription: "SonyBridge") + ?? NSImage(systemSymbolName: "headphones", accessibilityDescription: "SonyBridge") + image?.isTemplate = true // macOS tints it for light/dark menu bars + return image + } +} +``` + +- [ ] **Step 3 : Réécrire `Client/macos/StatusItemController.swift`** + +```swift +import AppKit +import Combine + +// Owns the menu bar icon (it follows the mode and connection state) and attaches the headphones menu to it. +final class StatusItemController { + private let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength) + private let headphonesMenu: HeadphonesMenu + private var cancellables = Set() + + init(model: HeadphonesModel) { + headphonesMenu = HeadphonesMenu(model: model) + statusItem.menu = headphonesMenu.menu + model.$connectionState.combineLatest(model.$mode) + .receive(on: DispatchQueue.main) + .sink { [weak self] state, mode in + let connected = state == .connected + self?.statusItem.button?.image = StatusIcon.image(connected: connected, mode: mode) + self?.statusItem.button?.appearsDisabled = !connected + } + .store(in: &cancellables) + } +} +``` + +- [ ] **Step 4 : Réécrire `Client/macos/HeadphonesMenu.swift`** + +```swift +import AppKit +import Combine + +// The status item's menu (spec §4). Built once; update() refreshes states, visibility and values in place, +// including while the menu is open. +final class HeadphonesMenu { + let menu = NSMenu() + private let model: HeadphonesModel + private var cancellables = Set() + + private let errorItem = NSMenuItem() + private var modeItems: [(SHCAmbientMode, NSMenuItem)] = [] + private var ambientRows: [NSMenuItem] = [] // level slider + focus on voice + private let equalizerItem = NSMenuItem() + private var presetItems: [(Int, NSMenuItem)] = [] + private let equalizerNoteItem = NSMenuItem() + private var equalizerResetItem = NSMenuItem() + private var dseeItem = NSMenuItem() + private var speakToChatItem = NSMenuItem() + private var adaptiveVolumeItem = NSMenuItem() + private let autoPowerOffItem = NSMenuItem() + private var autoPowerOffItems: [NSMenuItem] = [] + private let aboutItem = NSMenuItem() + private let aboutMenu = NSMenu() + private var connectItem = NSMenuItem() + + private static var presets: [(Int, String)] { + [(0x00, tr("Off")), (0x10, tr("Bright")), (0x11, tr("Excited")), (0x12, tr("Mellow")), + (0x13, tr("Relaxed")), (0x14, tr("Vocal")), (0x15, tr("Treble")), (0x16, tr("Bass")), + (0x17, tr("Speech")), (0xA0, tr("Manual"))] + } + + // Index = the bridge's auto power-off option (0=Off, 1=5 min, 2=30 min, 3=1 h, 4=3 h, 5=when taken off). + private static var autoPowerOffOptions: [String] { + [tr("Off"), tr("5 min"), tr("30 min"), tr("1 hour"), tr("3 hours"), tr("When taken off")] + } + + init(model: HeadphonesModel) { + self.model = model + menu.autoenablesItems = false + + menu.addItem(hostingMenuItem { HeaderRow(model: model) }) + errorItem.isEnabled = false + menu.addItem(errorItem) + menu.addItem(.separator()) + addAmbientSection() + menu.addItem(.separator()) + addSoundSection() + menu.addItem(.separator()) + addAppSection() + + // objectWillChange fires before the new value is stored; hopping to the main queue reads the new state. + model.objectWillChange + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in self?.update() } + .store(in: &cancellables) + update() + } + + // MARK: - Building + + private func addAmbientSection() { + menu.addItem(sectionHeader(tr("Ambient Sound Control"))) + let modes: [(SHCAmbientMode, String)] = [ + (.noiseCanceling, tr("Noise Canceling")), (.ambientSound, tr("Ambient Sound")), (.off, tr("Off")), + ] + for (mode, title) in modes { + let item = ActionMenuItem(title) { [weak model] in model?.setMode(mode) } + item.image = NSImage(systemSymbolName: StatusIcon.symbolName(for: mode), accessibilityDescription: nil) + modeItems.append((mode, item)) + menu.addItem(item) + if mode == .ambientSound { + ambientRows = [ + hostingMenuItem { AmbientLevelRow(model: model) }, + hostingMenuItem { + ToggleRow(model: model, title: tr("Focus on Voice"), indent: MenuMetrics.indent, + isOn: { $0.focusOnVoice }, set: { $0.setFocusOnVoice($1) }) + }, + ] + ambientRows.forEach { menu.addItem($0) } + } + } + } + + private func addSoundSection() { + let equalizerMenu = NSMenu() + equalizerMenu.autoenablesItems = false + for (code, title) in Self.presets { + let item = ActionMenuItem(title) { [weak model] in model?.setEqualizerPreset(code) } + presetItems.append((code, item)) + equalizerMenu.addItem(item) + } + equalizerMenu.addItem(.separator()) + equalizerMenu.addItem(hostingMenuItem(width: MenuMetrics.equalizerWidth) { EqualizerRow(model: model) }) + equalizerNoteItem.title = tr("Manual equalizer coming soon for this model") + equalizerNoteItem.isEnabled = false + equalizerMenu.addItem(equalizerNoteItem) + equalizerResetItem = ActionMenuItem(tr("Reset")) { [weak model] in model?.resetEqualizer() } + equalizerMenu.addItem(equalizerResetItem) + equalizerItem.submenu = equalizerMenu + menu.addItem(equalizerItem) + + dseeItem = hostingMenuItem { + ToggleRow(model: model, title: tr("DSEE"), isOn: { $0.dsee }, set: { $0.setDsee($1) }) + } + speakToChatItem = hostingMenuItem { + ToggleRow(model: model, title: tr("Speak-to-Chat"), isOn: { $0.speakToChat }, set: { $0.setSpeakToChat($1) }) + } + adaptiveVolumeItem = hostingMenuItem { + ToggleRow(model: model, title: tr("Adaptive Volume"), isOn: { $0.adaptiveVolume }, set: { $0.setAdaptiveVolume($1) }) + } + for item in [dseeItem, speakToChatItem, adaptiveVolumeItem] { menu.addItem(item) } + + let autoPowerOffMenu = NSMenu() + autoPowerOffMenu.autoenablesItems = false + for (index, title) in Self.autoPowerOffOptions.enumerated() { + let item = ActionMenuItem(title) { [weak model] in model?.setAutoPowerOff(index) } + autoPowerOffItems.append(item) + autoPowerOffMenu.addItem(item) + } + autoPowerOffItem.submenu = autoPowerOffMenu + menu.addItem(autoPowerOffItem) + } + + private func addAppSection() { + aboutItem.title = tr("About the Headphones") + aboutMenu.autoenablesItems = false + aboutItem.submenu = aboutMenu + menu.addItem(aboutItem) + connectItem = ActionMenuItem(tr("Connect…")) { [weak self] in self?.toggleConnection() } + menu.addItem(connectItem) + menu.addItem(.separator()) + menu.addItem(ActionMenuItem(tr("Quit SonyBridge"), key: "q") { NSApp.terminate(nil) }) + } + + // MARK: - Updating + + private func update() { + let connected = model.connected + + errorItem.isHidden = model.errorMessage == nil + errorItem.title = "⚠︎ " + (model.errorMessage ?? "") + + for (mode, item) in modeItems { + item.state = connected && model.mode == mode ? .on : .off + item.isEnabled = connected + } + ambientRows.forEach { $0.isHidden = model.mode != .ambientSound } + + equalizerItem.isHidden = !model.supportsEqualizer + equalizerItem.isEnabled = connected + equalizerItem.attributedTitle = titleWithValue(tr("Equalizer"), Self.presetName(model.eqPreset)) + for (code, item) in presetItems { + item.state = model.eqPreset == code ? .on : .off + item.isEnabled = connected && model.equalizerWritable + } + equalizerNoteItem.isHidden = model.equalizerWritable || model.eqBands.isEmpty + equalizerResetItem.isEnabled = connected && model.equalizerWritable && model.eqPreset == 0xA0 + + dseeItem.isHidden = !model.supportsEqualizer + speakToChatItem.isHidden = !model.hasSpeakToChat + adaptiveVolumeItem.isHidden = !model.hasAdaptiveVolume + + let options = Self.autoPowerOffOptions + autoPowerOffItem.isHidden = !model.hasAutoPowerOff + autoPowerOffItem.isEnabled = connected + autoPowerOffItem.attributedTitle = titleWithValue( + tr("Auto Power-Off"), options.indices.contains(model.autoPowerOff) ? options[model.autoPowerOff] : "") + for (index, item) in autoPowerOffItems.enumerated() { + item.state = index == model.autoPowerOff ? .on : .off + } + + updateAbout() + aboutItem.isEnabled = connected + + switch model.connectionState { + case .connected: connectItem.title = tr("Disconnect") + case .connecting: connectItem.title = tr("Connecting…") + case .disconnected: connectItem.title = tr("Connect…") + } + connectItem.isEnabled = model.connectionState != .connecting + } + + private func updateAbout() { + aboutMenu.removeAllItems() + let rows: [(String, String)] = [ + (tr("Firmware"), model.firmware), (tr("Codec"), model.codec), + (tr("Protocol"), model.protocolVersion), (tr("Bluetooth"), model.deviceMac), + ] + for (title, value) in rows where !value.isEmpty { + let item = NSMenuItem() + item.attributedTitle = titleWithValue(title, value) + item.isEnabled = false + aboutMenu.addItem(item) + } + } + + private static func presetName(_ code: Int) -> String { + presets.first { $0.0 == code }?.1 ?? tr("Custom") + } + + private func toggleConnection() { + if model.connected { + model.disconnect() + } else { + NSApp.activate(ignoringOtherApps: true) // the fallback Bluetooth picker is a modal window + model.connect() + } + } +} +``` + +- [ ] **Step 5 : Ajouter les clés à `Client/macos/fr.lproj/Localizable.strings`** (section « Menu ») + +``` +"Equalizer" = "Égaliseur"; +"Bright" = "Brillant"; +"Excited" = "Dynamique"; +"Mellow" = "Doux"; +"Relaxed" = "Détendu"; +"Vocal" = "Voix"; +"Treble" = "Aigus"; +"Bass" = "Graves"; +"Speech" = "Parole"; +"Manual" = "Manuel"; +"Custom" = "Personnalisé"; +"Manual equalizer coming soon for this model" = "Égaliseur manuel bientôt disponible pour ce modèle"; +"Reset" = "Réinitialiser"; +"DSEE" = "DSEE"; +"Speak-to-Chat" = "Speak-to-Chat"; +"Adaptive Volume" = "Volume adaptatif"; +"Auto Power-Off" = "Arrêt automatique"; +"5 min" = "5 min"; +"30 min" = "30 min"; +"1 hour" = "1 heure"; +"3 hours" = "3 heures"; +"When taken off" = "Quand le casque est retiré"; +"About the Headphones" = "À propos du casque"; +"Firmware" = "Firmware"; +"Codec" = "Codec"; +"Protocol" = "Protocole"; +"Bluetooth" = "Bluetooth"; +``` + +- [ ] **Step 6 : Tests et build** + +Run : `make test && make` +Attendu : tout passe, `Localization: 46 keys, all translated`, puis `OK -> …`. + +- [ ] **Step 7 : Vérifier avec l'utilisateur** (casque connecté, `make run`) + +Parcourir le menu avec lui, dans l'ordre de la spec §4 : +1. L'icône de la barre change avec le mode (réduction de bruit / son ambiant / désactivé) et se grise une + fois déconnecté. **Lui montrer les 3 glyphes** et demander s'ils lui conviennent (sinon, changer les noms de + symboles dans `StatusIcon.symbolName`). +2. Le curseur et « Focalisation sur la voix » n'apparaissent qu'en « Son ambiant ». +3. « Égaliseur » affiche « Personnalisé » à droite (preset `0x30` du XM6). Le sous-menu montre les presets + grisés, 10 curseurs grisés, et « Égaliseur manuel bientôt disponible pour ce modèle ». +4. DSEE et Speak-to-Chat sont présents ; Volume adaptatif est absent (le XM6 ne le gère pas). +5. « Arrêt automatique » affiche l'option en cours à droite ; changer d'option déplace la coche. +6. « À propos du casque » : Firmware 3.1.5, Codec AAC, Protocole v2, adresse Bluetooth. +7. Déconnecter : les réglages restent affichés mais grisés, et l'en-tête dit « Non connecté ». +8. Les valeurs à droite sont bien alignées et le menu n'est pas trop large (sinon, ajuster + `MenuMetrics.width` et le `width` de `titleWithValue`). + +- [ ] **Step 8 : Commit** (par l'utilisateur) + +```bash +git add -A && git commit -m "feat(macos): full headphones menu with per-mode status icon" +``` + +--- + +### Task 7: Options — connexion auto, reconnexion auto, lancement à l'ouverture de session + +**Files:** +- Create : `Client/macos/AppSettings.swift`, `Client/macos/DeviceWatcher.swift` +- Modify : `Client/macos/MacOSBluetoothConnector.h/.mm` (coupure de liaison sûre), + `Client/macos/HeadphonesBridge.h/.mm` (connexion par adresse, aides de classe), + `Client/macos/HeadphonesModel.swift`, `Client/macos/HeadphonesMenu.swift`, + `Client/macos/StatusItemController.swift`, `Client/macos/AppDelegate.swift`, + `Client/macos/fr.lproj/Localizable.strings` + +**Interfaces:** +- Consumes : `ReconnectPolicy` (tâche 2), `HeadphonesModel.handleConnectResult(ok:error:userInitiated:)` et + `linkLost()` (tâche 4), `HeadphonesMenu.addAppSection()` (tâche 6). +- Produces : + - `final class AppSettings: ObservableObject { var autoConnect: Bool; var autoReconnect: Bool; private(set) var launchAtLogin: Bool; var lastDeviceAddress: String?; func setLaunchAtLogin(_ enabled: Bool) -> String? }` + - `final class DeviceWatcher { var onConnect: ((String, String) -> Void)?; var onDisconnect: ((String) -> Void)?; func start() }` (adresse, nom) + - `HeadphonesBridge` (Swift) : `looksLikeSonyHeadset(_:)`, `connectedSonyHeadsetAddress()`, + `isDeviceConnectedToMac(_:)`, `connect(toAddress:completion:)` + - `HeadphonesModel` : `var settings: AppSettings?`, `autoConnectOnLaunch()`, `autoConnect(toAddress:)`, + `headsetConnectedToMac(address:name:)`, `headsetDisconnectedFromMac(address:)`, `cancelReconnect()` + - `StatusItemController(model:settings:)`, `HeadphonesMenu(model:settings:)` + +- [ ] **Step 1 : Rendre la coupure de liaison sûre dans `MacOSBluetoothConnector`** + +Aujourd'hui, quand le casque ferme le canal, `rfcommChannelClosed` appelle `disconnect()` **sur le fil du +connecteur lui-même**, et `disconnect()` fait `uthread.join()` : un fil qui s'attend lui-même lève une +exception dans une fonction `noexcept`, donc l'app plante. Une reconnexion ferait aussi `uthread = std::thread(…)` +sur un fil encore « joignable », ce qui plante aussi. À corriger avant toute reconnexion automatique. + +`Client/macos/MacOSBluetoothConnector.h` : +- ajouter, sous `virtual void closeConnection();` : + +```cpp + // Called from the channel-closed callback, on the connector thread: stops that thread's loop without joining it. + void markClosed() noexcept; +``` + +- initialiser les pointeurs privés : `void *rfcommDevice = nullptr;` et `void *rfcommchannel = nullptr;`. + +`Client/macos/MacOSBluetoothConnector.mm` : +- dans `rfcommChannelClosed:`, remplacer `delegateCPP->disconnect();` par `delegateCPP->markClosed();` +- remplacer le destructeur, `disconnect()` et le début de `connect()` : + +```objc +MacOSBluetoothConnector::~MacOSBluetoothConnector() +{ + disconnect(); +} + +void MacOSBluetoothConnector::markClosed() noexcept +{ + running = false; + disconnectionConditionVariable.notify_all(); +} + +void MacOSBluetoothConnector::disconnect() noexcept +{ + closeConnection(); + markClosed(); + // Never join from the connector thread itself (the channel-closed callback runs there). + if (uthread.joinable() && uthread.get_id() != std::this_thread::get_id()) { + uthread.join(); + } +} +``` + +et, en première ligne de `MacOSBluetoothConnector::connect(const std::string& addrStr)` : + +```objc + // A previous link's thread has stopped (markClosed) but may not have been joined yet. + if (uthread.joinable()) uthread.join(); +``` + +- dans `closeConnection()`, ajouter en première ligne `if (!rfcommchannel) return;`. + +- [ ] **Step 2 : Connexion par adresse dans le pont** + +`Client/macos/HeadphonesBridge.h`, sous `scanAndConnectWithCompletion:` : + +```objc +// Name heuristic for Sony headsets (WH-/WF-/WI-/MDR-/XB/LinkBuds). ++ (BOOL)looksLikeSonyHeadset:(NSString *)name NS_SWIFT_NAME(looksLikeSonyHeadset(_:)); +// Address of the first Sony headset currently connected to macOS, or nil. ++ (nullable NSString *)connectedSonyHeadsetAddress NS_SWIFT_NAME(connectedSonyHeadsetAddress()); +// YES if the device with this address is connected to macOS (its audio link is up). ++ (BOOL)isDeviceConnectedToMac:(NSString *)address NS_SWIFT_NAME(isDeviceConnectedToMac(_:)); +// Opens the control channel to a specific device, without the picker. Completion on the main thread. +- (void)connectToAddress:(NSString *)address + completion:(void (^)(BOOL ok, NSString * _Nullable error))completion NS_SWIFT_NAME(connect(toAddress:completion:)); +``` + +`Client/macos/HeadphonesBridge.mm` : dans `scanAndConnectWithCompletion:`, remplacer tout le code qui suit le +test `if (!device) { … return; }` (le `try { _bt->connect(…) }`, la boucle d'attente, et la création de `_hp` +jusqu'à `completion(YES, nil);`) par `[self connectDevice:device completion:completion];`, puis ajouter après +la méthode : + +```objc +- (void)connectDevice:(IOBluetoothDevice *)device completion:(void (^)(BOOL, NSString * _Nullable))completion { + try { + _bt->connect([[device addressString] UTF8String]); + } catch (RecoverableException &exc) { + completion(NO, @(exc.what())); + return; + } + + // A real RFCOMM open (SDP + link setup, sometimes with encryption renegotiation) can take a few + // seconds; pump the run loop until it lands or we give up. + int timeout = 80; + while (!_bt->isConnected() && timeout >= 0) { + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + timeout--; + } + + if (!_bt->isConnected()) { + _bt->disconnect(); + completion(NO, NSLocalizedString(@"Connection timed out.", nil)); + return; + } + + _deviceName = [device nameOrAddress]; + _deviceMac = [device addressString]; + _hp = std::make_unique(*_bt); + completion(YES, nil); +} + ++ (BOOL)looksLikeSonyHeadset:(NSString *)name { + return SHCLooksLikeSonyHeadset(name); +} + ++ (nullable NSString *)connectedSonyHeadsetAddress { + for (IOBluetoothDevice *paired in [IOBluetoothDevice pairedDevices]) { + if ([paired isConnected] && SHCLooksLikeSonyHeadset([paired name])) return [paired addressString]; + } + return nil; +} + ++ (BOOL)isDeviceConnectedToMac:(NSString *)address { + IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:address]; + return device != nil && [device isConnected]; +} + +- (void)connectToAddress:(NSString *)address completion:(void (^)(BOOL, NSString * _Nullable))completion { + IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:address]; + if (!device) { + completion(NO, NSLocalizedString(@"Not connected.", nil)); + return; + } + [self connectDevice:device completion:completion]; +} +``` + +- [ ] **Step 3 : Écrire `Client/macos/AppSettings.swift`** + +```swift +import Foundation +import ServiceManagement + +// The three user options, persisted in UserDefaults. Launch at login is backed by SMAppService (macOS 13+). +final class AppSettings: ObservableObject { + private enum Keys { + static let autoConnect = "autoConnect" + static let autoReconnect = "autoReconnect" + static let lastDeviceAddress = "lastDeviceAddress" + } + + private let defaults: UserDefaults + + @Published var autoConnect: Bool { + didSet { defaults.set(autoConnect, forKey: Keys.autoConnect) } + } + @Published var autoReconnect: Bool { + didSet { defaults.set(autoReconnect, forKey: Keys.autoReconnect) } + } + @Published private(set) var launchAtLogin: Bool + + var lastDeviceAddress: String? { + get { defaults.string(forKey: Keys.lastDeviceAddress) } + set { defaults.set(newValue, forKey: Keys.lastDeviceAddress) } + } + + init(defaults: UserDefaults = .standard) { + self.defaults = defaults + // Spec §4: auto-connect and auto-reconnect default on; launch at login stays off until the user asks. + defaults.register(defaults: [Keys.autoConnect: true, Keys.autoReconnect: true]) + autoConnect = defaults.bool(forKey: Keys.autoConnect) + autoReconnect = defaults.bool(forKey: Keys.autoReconnect) + launchAtLogin = SMAppService.mainApp.status == .enabled + } + + // Returns an error message if macOS refused the change. + func setLaunchAtLogin(_ enabled: Bool) -> String? { + defer { launchAtLogin = SMAppService.mainApp.status == .enabled } + do { + if enabled { + try SMAppService.mainApp.register() + if SMAppService.mainApp.status == .requiresApproval { + SMAppService.openSystemSettingsLoginItems() + } + } else { + try SMAppService.mainApp.unregister() + } + return nil + } catch { + return error.localizedDescription + } + } +} +``` + +- [ ] **Step 4 : Écrire `Client/macos/DeviceWatcher.swift`** + +```swift +import Foundation +import IOBluetooth + +// Reports Bluetooth devices connecting to / disconnecting from macOS, as (address, name). +final class DeviceWatcher: NSObject { + var onConnect: ((_ address: String, _ name: String) -> Void)? + var onDisconnect: ((_ address: String) -> Void)? + + private var connectNotification: IOBluetoothUserNotification? + private var disconnectNotifications: [String: IOBluetoothUserNotification] = [:] + + func start() { + connectNotification = IOBluetoothDevice.register(forConnectNotifications: self, + selector: #selector(deviceConnected(_:device:))) + for case let device as IOBluetoothDevice in IOBluetoothDevice.pairedDevices() ?? [] where device.isConnected() { + if let address = device.addressString { watchDisconnect(device, address: address) } + } + } + + @objc private func deviceConnected(_ notification: IOBluetoothUserNotification, device: IOBluetoothDevice) { + guard let address = device.addressString else { return } + watchDisconnect(device, address: address) + onConnect?(address, device.name ?? "") + } + + @objc private func deviceDisconnected(_ notification: IOBluetoothUserNotification, device: IOBluetoothDevice) { + notification.unregister() + guard let address = device.addressString else { return } + disconnectNotifications[address] = nil + onDisconnect?(address) + } + + private func watchDisconnect(_ device: IOBluetoothDevice, address: String) { + guard disconnectNotifications[address] == nil else { return } + disconnectNotifications[address] = device.register(forDisconnectNotification: self, + selector: #selector(deviceDisconnected(_:device:))) + } +} +``` + +- [ ] **Step 5 : Connexion et reconnexion automatiques dans `Client/macos/HeadphonesModel.swift`** + +Ajouter sous `private var eqThrottle = SendThrottle()` : + +```swift + // Set by AppDelegate; nil means "no automatic behaviour". + var settings: AppSettings? + private var reconnectPolicy = ReconnectPolicy() + private var reconnectTimer: Timer? + private var reconnectAddress: String? + private var userDisconnected = false // after "Déconnecter": no auto-reconnect until the headset reconnects to macOS +``` + +Dans `connect()`, ajouter en première ligne : + +```swift + userDisconnected = false + cancelReconnect() +``` + +Remplacer `disconnect()`, `handleConnectResult(ok:error:userInitiated:)` et `linkLost()` par : + +```swift + func disconnect() { + userDisconnected = true + cancelReconnect() + stopTimers() + bridge.disconnect() + connectionState = .disconnected + } + + func handleConnectResult(ok: Bool, error: String?, userInitiated: Bool) { + guard ok else { + connectionState = .disconnected + if userInitiated, let error = error { errorMessage = error } + if !userInitiated && reconnectAddress != nil { scheduleReconnect() } + return + } + cancelReconnect() + connectionState = .connected + syncFromBridge() + settings?.lastDeviceAddress = deviceMac + bridge.refreshStatus { [weak self] in self?.syncFromBridge() } // called after reads, then after probes + startTimers() + } + + // The control link dropped on its own (idle power-save): retry while the headset is still connected to macOS. + func linkLost() { + stopTimers() + bridge.disconnect() // resets sequence numbers and buffers for the next connection + connectionState = .disconnected + guard settings?.autoReconnect == true, !userDisconnected, !deviceMac.isEmpty else { return } + reconnectAddress = deviceMac + scheduleReconnect() + } + + // MARK: - Automatic connection + + // Not user-initiated: failures stay silent (normal while the headset sleeps). + func autoConnect(toAddress address: String) { + guard connectionState == .disconnected else { return } + connectionState = .connecting + bridge.connect(toAddress: address) { ok, error in + self.handleConnectResult(ok: ok, error: error, userInitiated: false) + } + } + + // At launch: the last headset if macOS has it connected, else any connected Sony headset. + func autoConnectOnLaunch() { + let remembered = settings?.lastDeviceAddress.flatMap { HeadphonesBridge.isDeviceConnectedToMac($0) ? $0 : nil } + if let address = remembered ?? HeadphonesBridge.connectedSonyHeadsetAddress() { + autoConnect(toAddress: address) + } + } + + // DeviceWatcher: a device just connected to macOS. + func headsetConnectedToMac(address: String, name: String) { + guard settings?.autoConnect == true, HeadphonesBridge.looksLikeSonyHeadset(name), + connectionState == .disconnected else { return } + userDisconnected = false + cancelReconnect() + // Give the audio link ~2 s to settle before opening the control channel. + DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in self?.autoConnect(toAddress: address) } + } + + // DeviceWatcher: a device left macOS; stop retrying it (headsetConnectedToMac takes over when it's back). + func headsetDisconnectedFromMac(address: String) { + if address == reconnectAddress { cancelReconnect() } + } + + func cancelReconnect() { + reconnectTimer?.invalidate() + reconnectTimer = nil + reconnectAddress = nil + reconnectPolicy.reset() + } + + private func scheduleReconnect() { + guard let address = reconnectAddress else { return } + reconnectTimer?.invalidate() + let timer = Timer(timeInterval: reconnectPolicy.nextDelay(), repeats: false) { [weak self] _ in + guard let self = self else { return } + guard HeadphonesBridge.isDeviceConnectedToMac(address) else { self.cancelReconnect(); return } + self.autoConnect(toAddress: address) + } + RunLoop.main.add(timer, forMode: .common) + reconnectTimer = timer + } +``` + +- [ ] **Step 6 : Sous-menu « Options de SonyBridge » dans `Client/macos/HeadphonesMenu.swift`** + +- Remplacer `init(model: HeadphonesModel) {` / `self.model = model` par : + +```swift + init(model: HeadphonesModel, settings: AppSettings) { + self.model = model + self.settings = settings +``` + +- Ajouter les propriétés, sous `private let model: HeadphonesModel` : + +```swift + private let settings: AppSettings + private var launchAtLoginItem = NSMenuItem() + private var autoConnectItem = NSMenuItem() + private var autoReconnectItem = NSMenuItem() +``` + +- Dans `init`, après l'abonnement à `model.objectWillChange`, ajouter : + +```swift + settings.objectWillChange + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in self?.update() } + .store(in: &cancellables) +``` + +- Dans `addAppSection()`, juste avant `connectItem = ActionMenuItem(…)`, ajouter : + +```swift + let optionsMenu = NSMenu() + optionsMenu.autoenablesItems = false + launchAtLoginItem = ActionMenuItem(tr("Launch at Login")) { [weak self] in self?.toggleLaunchAtLogin() } + autoConnectItem = ActionMenuItem(tr("Connect Automatically")) { [weak settings] in settings?.autoConnect.toggle() } + autoReconnectItem = ActionMenuItem(tr("Reconnect Automatically")) { [weak settings] in settings?.autoReconnect.toggle() } + for item in [launchAtLoginItem, autoConnectItem, autoReconnectItem] { optionsMenu.addItem(item) } + let optionsItem = NSMenuItem(title: tr("SonyBridge Options"), action: nil, keyEquivalent: "") + optionsItem.submenu = optionsMenu + menu.addItem(optionsItem) +``` + +- À la fin de `update()`, ajouter : + +```swift + launchAtLoginItem.state = settings.launchAtLogin ? .on : .off + autoConnectItem.state = settings.autoConnect ? .on : .off + autoReconnectItem.state = settings.autoReconnect ? .on : .off +``` + +- Ajouter la méthode : + +```swift + private func toggleLaunchAtLogin() { + if let error = settings.setLaunchAtLogin(!settings.launchAtLogin) { model.showError(error) } + } +``` + +- [ ] **Step 7 : Assembler dans `StatusItemController` et `AppDelegate`** + +`Client/macos/StatusItemController.swift` : remplacer `init(model: HeadphonesModel) {` par +`init(model: HeadphonesModel, settings: AppSettings) {` et `HeadphonesMenu(model: model)` par +`HeadphonesMenu(model: model, settings: settings)`. + +Réécrire `Client/macos/AppDelegate.swift` : + +```swift +import AppKit + +final class AppDelegate: NSObject, NSApplicationDelegate { + private let model = HeadphonesModel() + private let settings = AppSettings() + private let deviceWatcher = DeviceWatcher() + private var statusItemController: StatusItemController? + + func applicationDidFinishLaunching(_ notification: Notification) { + model.settings = settings + statusItemController = StatusItemController(model: model, settings: settings) + + deviceWatcher.onConnect = { [weak self] address, name in + self?.model.headsetConnectedToMac(address: address, name: name) + } + deviceWatcher.onDisconnect = { [weak self] address in + self?.model.headsetDisconnectedFromMac(address: address) + } + deviceWatcher.start() + + if settings.autoConnect { model.autoConnectOnLaunch() } + } + + func applicationWillTerminate(_ notification: Notification) { + model.disconnect() + } +} +``` + +- [ ] **Step 8 : Ajouter les clés à `Client/macos/fr.lproj/Localizable.strings`** + +``` +"SonyBridge Options" = "Options de SonyBridge"; +"Launch at Login" = "Lancer à l’ouverture de session"; +"Connect Automatically" = "Connexion automatique"; +"Reconnect Automatically" = "Reconnexion automatique"; +``` + +- [ ] **Step 9 : Tests et build** + +Run : `make test && make` +Attendu : tout passe, `Localization: 50 keys, all translated`, puis `OK -> …`. + +- [ ] **Step 10 : Vérifier avec l'utilisateur** (`make run DEBUG=1`) + +1. **Connexion au lancement** : XM6 connecté à macOS, quitter puis relancer l'app → elle se connecte seule, sans + clic (en-tête « Connecté · AAC »). +2. **Connexion auto** : éteindre le casque, puis le rallumer → environ 2 s après la connexion audio, l'app se + connecte seule. +3. **Déconnexion manuelle** : « Déconnecter » → pas de reconnexion ; éteindre puis rallumer le casque → l'app + se reconnecte. +4. **Reconnexion auto** : laisser le casque connecté sans audio jusqu'à ce que le canal de contrôle se coupe + (plusieurs minutes) → l'app **ne plante pas** et se reconnecte ; vérifier les essais avec + `grep -c '\[connect\] openRFCOMMChannelAsync' build/app.log`. +5. **Options** : décocher « Connexion automatique », quitter, relancer → l'option reste décochée et l'app ne + se connecte pas seule. +6. **Lancement à l'ouverture de session** : `cp -R build/SonyBridge.app /Applications/`, lancer la copie de + `/Applications`, cocher l'option → elle apparaît dans Réglages Système › Général › Ouverture ; fermer la + session puis la rouvrir → l'icône revient seule. Si macOS demande une approbation, les Réglages s'ouvrent + sur la bonne page. + +- [ ] **Step 11 : Commit** (par l'utilisateur) + +```bash +git add -A && git commit -m "feat(macos): auto-connect, auto-reconnect and launch at login (menu options)" +``` + +--- + +### Task 8: Expérimentations XM6 + écriture de l'égaliseur (spec §7) + +Tâche **avec l'utilisateur et le casque**. On confirme d'abord chaque format sur le matériel, puis on active +l'écriture de l'égaliseur. Un menu « Debug » (compilé seulement avec `make run DEBUG=1`) permet d'envoyer une +trame brute ; les réponses du casque arrivent dans `build/app.log`. Ce menu n'est qu'un outil de diagnostic, +en anglais : ses textes ne sont pas traduits. + +**Files:** +- Modify : `Client/macos/HeadphonesBridge.h/.mm` (`sendRawPayload:completion:`, `equalizerWritable`) +- Modify : `Client/macos/HeadphonesModel.swift` (`sendRaw(hex:)`), `Client/macos/HeadphonesMenu.swift` (menu Debug) +- Modify : `Client/ProtocolParsers.h/.cpp` (`buildCustomEqualizer`), `Client/Headphones.cpp` + (`setEqualizerCustom`), `Client/tests/ProtocolParsersTests.cpp` +- Create : `docs/xm6-protocol-notes.md` (résultats des expériences) + +**Interfaces:** +- Produces : `Buffer ProtocolParsers::buildCustomEqualizer(unsigned char manualPreset, bool hasClearBass, int clearBass, const std::vector& bands)` ; + `HeadphonesBridge.sendRawPayload(_:completion:)` ; `HeadphonesModel.sendRaw(hex:)` (seulement avec `DEBUG_PROTOCOL`). + +- [ ] **Step 1 : Envoi brut dans le pont** + +`Client/macos/HeadphonesBridge.h` : + +```objc +// Diagnostics: sends a raw payload (e.g. 56 00) and waits for the ACK; replies are hex-dumped to the log when +// built with DEBUG_PROTOCOL. Only reachable from the Debug menu of `make run DEBUG=1` builds. +- (void)sendRawPayload:(NSData *)payload completion:(void (^)(BOOL ok, NSString * _Nullable error))completion; +``` + +`Client/macos/HeadphonesBridge.mm` : + +```objc +- (void)sendRawPayload:(NSData *)payload completion:(void (^)(BOOL, NSString * _Nullable))completion { + if (!_hp || !self.connected) { completion(NO, NSLocalizedString(@"Not connected.", nil)); return; } + std::vector bytes((const char *)payload.bytes, (const char *)payload.bytes + payload.length); + BluetoothWrapper *bt = _bt.get(); + dispatch_async(_cmdQueue, ^{ + NSString *error = nil; BOOL ok = YES; + try { bt->sendCommand(bytes); } catch (std::exception &exc) { ok = NO; error = @(exc.what()); } + dispatch_async(dispatch_get_main_queue(), ^{ completion(ok, error); }); + }); +} +``` + +- [ ] **Step 2 : Menu Debug** + +`Client/macos/HeadphonesModel.swift`, dans la section « Actions » : + +```swift + #if DEBUG_PROTOCOL + // Debug menu only: sends raw bytes like "56 00"; the replies are logged to build/app.log. + func sendRaw(hex: String) { + let bytes = hex.split(whereSeparator: { $0 == " " || $0 == "," }).compactMap { UInt8($0, radix: 16) } + guard !bytes.isEmpty else { return } + bridge.sendRawPayload(Data(bytes)) { [weak self] ok, error in self?.finish(ok, error) } + } + #endif +``` + +`Client/macos/HeadphonesMenu.swift` : dans `addAppSection()`, juste avant `menu.addItem(.separator())` qui +précède « Quitter », ajouter : + +```swift + #if DEBUG_PROTOCOL + menu.addItem(ActionMenuItem("Debug: send frame…") { [weak self] in self?.promptRawFrame() }) + #endif +``` + +et la méthode : + +```swift + #if DEBUG_PROTOCOL + // Diagnostics only (not localized): asks for a hex payload and sends it as-is. + private func promptRawFrame() { + let alert = NSAlert() + alert.messageText = "Send raw payload (hex)" + let field = NSTextField(frame: NSRect(x: 0, y: 0, width: 260, height: 24)) + field.placeholderString = "56 00" + alert.accessoryView = field + alert.addButton(withTitle: "Send") + alert.addButton(withTitle: "Cancel") + NSApp.activate(ignoringOtherApps: true) + if alert.runModal() == .alertFirstButtonReturn { model.sendRaw(hex: field.stringValue) } + } + #endif +``` + +Run : `make test && make run DEBUG=1` → le menu montre « Debug: send frame… ». Envoyer `56 00` → dans +`build/app.log`, une ligne `[recv] 3e 0c … 57 00 …`. + +- [ ] **Step 3 : Expérience E1, les 2 octets de plus du canal `0x19`** + +L'utilisateur passe par les trois modes **avec le bouton du casque**, en attendant 3 s entre chaque, puis : +`grep -E '\[recv\].* 6[79] 19' build/app.log | tail -6`. +Noter dans `docs/xm6-protocol-notes.md` la valeur des octets 8 et 9 pour chaque mode. Aucun changement de code +n'est prévu : ces octets ne servent qu'à documenter (par exemple une option de l'optimiseur NC, hors +périmètre). + +- [ ] **Step 4 : Expérience E2, lecture de l'égaliseur** + +L'utilisateur règle l'égaliseur dans l'app Sony (Sound Connect) sur son téléphone, puis envoie `56 00` depuis +« Debug: send frame… », pour chacun de ces réglages : « Désactivé », « Bass Boost » (Graves), « Bright » +(Brillant), puis « Manuel » avec **31 Hz au maximum, 16 kHz au minimum, le reste à 0**. +Pour chaque réglage : `grep '\[recv\].* 57 00' build/app.log | tail -1`. Noter l'identifiant de preset (octet 3) +et les 10 valeurs. Conclure : +- le décalage : avec 31 Hz au max, la 1ʳᵉ valeur doit valoir `0x14` (20) si la plage est −10…+10 (décalage 10), + ou `0x0c` (12) si elle est −6…+6 (décalage 6) ; +- les identifiants de presets du XM6 (comparer avec `0x00, 0x10…0x17, 0xa0`). +Si l'app Sony ne peut pas se connecter pendant que le Mac est connecté, fermer SonyBridge pendant chaque +réglage, puis relancer l'app et relire. + +- [ ] **Step 5 : Expérience E3, écriture d'un preset** + +Avec l'identifiant de « Bass Boost » trouvé en E2 (noté ``) : envoyer `58 00 00`. L'utilisateur doit +**entendre** plus de basses. Relire avec `56 00` : l'octet 3 de la réponse doit valoir ``. Remettre ensuite +le preset d'origine de la même façon. + +- [ ] **Step 6 : Expérience E4, écriture de l'égaliseur manuel 10 bandes** + +Volume modéré. Envoyer `58 00 a0 0a 0d 0a 0a 0a 0a 0a 0a 0a 0a 0a` (31 Hz à +3 si le décalage est 10, le reste +à 0 ; adapter les valeurs si E2 a trouvé un autre décalage). Relire avec `56 00`. Attendu : +`57 00 a0 0a 0d 0a 0a 0a 0a 0a 0a 0a 0a 0a`. Si l'octet 3 de la réponse n'est pas `a0` (par exemple `a1` pour +un « Personnalisé 1 »), noter cet identifiant : c'est le preset « Manuel » du XM6. + +- [ ] **Step 7 : Expérience E5, les autres écritures** + +Depuis le menu : basculer DSEE, changer « Arrêt automatique », basculer Speak-to-Chat. Après chaque +changement, relire avec respectivement `e6 01`, `26 05`, `f6 0c` : la réponse (`e7 01 …`, `27 05 …`, +`f7 0c …`) doit refléter la nouvelle valeur. + +- [ ] **Step 8 : Point de décision (avec l'utilisateur)** + +Écrire les résultats E1 à E5 dans `docs/xm6-protocol-notes.md` (un tableau : trame envoyée, trame reçue, +conclusion). **Si E3 ou E4 contredisent les hypothèses** (aucun effet audible, ou une relecture différente de +ce qui a été envoyé) : **arrêter**, présenter les trames à l'utilisateur et replanifier l'écriture de +l'égaliseur. Les étapes 9 à 13 supposent que E2 à E4 ont confirmé les formats. + +- [ ] **Step 9 : Test du constructeur de trame** — ajouter à `Client/tests/ProtocolParsersTests.cpp`, avant +le bloc `// --- Framing ---` : + +```cpp + // --- Custom equalizer write --- + // 5 bands + Clear Bass (verified WH-CH720N format): 58 00 a0 06 + CHECK(buildCustomEqualizer(0xa0, true, 3, { -2, -1, 0, 1, 2 }) == bytes({ 0x58, 0x00, 0xa0, 0x06, 13, 8, 9, 10, 11, 12 })); + // 10 bands (WH-1000XM6, confirmed by experiment E4): 58 00 a0 0a + CHECK(buildCustomEqualizer(0xa0, false, 0, { 3, 0, 0, 0, 0, 0, 0, 0, 0, -10 }) + == bytes({ 0x58, 0x00, 0xa0, 0x0a, 13, 10, 10, 10, 10, 10, 10, 10, 10, 0 })); + // Values are clamped to -10..10. + CHECK(buildCustomEqualizer(0xa0, false, 0, { 15, -15 }) == bytes({ 0x58, 0x00, 0xa0, 0x02, 20, 0 })); +``` + +Si E2 a trouvé un décalage différent de 10, ou E4 un autre identifiant « Manuel », adapter les octets attendus +de la 2ᵉ assertion aux trames réellement confirmées. +Run : `make test` → échec : `use of undeclared identifier 'buildCustomEqualizer'`. + +- [ ] **Step 10 : Écrire le constructeur** + +`Client/ProtocolParsers.h`, dans le namespace : + +```cpp + // "58 00 [] ", each value clamped to -10..10. + Buffer buildCustomEqualizer(unsigned char manualPreset, bool hasClearBass, int clearBass, const std::vector& bands); +``` + +`Client/ProtocolParsers.cpp`, dans le namespace : + +```cpp + Buffer buildCustomEqualizer(unsigned char manualPreset, bool hasClearBass, int clearBass, const std::vector& bands) + { + auto encode = [](int v) { return (char)(unsigned char)(std::max(-10, std::min(10, v)) + 10); }; + Buffer cmd = { (char)V2Command::EQ_SET, 0x00, (char)manualPreset, 0x00 }; + if (hasClearBass) cmd.push_back(encode(clearBass)); + for (int band : bands) cmd.push_back(encode(band)); + cmd[3] = (char)(cmd.size() - 4); + return cmd; + } +``` + +Run : `make test` → `ProtocolParsersTests: all passed`. + +- [ ] **Step 11 : Utiliser le constructeur et ouvrir l'écriture** + +`Client/Headphones.cpp`, dans `Headphones::setEqualizerCustom`, remplacer la construction manuelle de `cmd` (le +lambda `clamp`, le `Buffer cmd = { … }` et la boucle `push_back`) et l'envoi par : + +```cpp + this->_conn.sendCommand(ProtocolParsers::buildCustomEqualizer( + static_cast(EQ_PRESET::MANUAL), this->_eqHasClearBass, clearBass, bands)); +``` + +(garder la mise à jour de `_eqPreset`, `_eqClearBass` et `_eqBands` qui suit). + +`Client/macos/HeadphonesBridge.mm`, remplacer l'implémentation de `equalizerWritable` et son commentaire par : + +```objc +// Both layouts have a verified write format: 5 bands + Clear Bass (WH-CH720N) and 10 bands (WH-1000XM6, +// docs/xm6-protocol-notes.md). Nothing is writable before the first equalizer read. +- (BOOL)equalizerWritable { return self.supportsEqualizer && _hp && _hp->getEqualizerBandCount() > 0; } +``` + +Si E2 a montré que le XM6 utilise d'autres identifiants de presets, remplacer les codes de +`HeadphonesMenu.presets` par ceux trouvés, et retirer du tableau les presets que le XM6 n'a pas (avec leur +traduction s'ils ne servent plus). + +- [ ] **Step 12 : Tests, build, vérification avec l'utilisateur** + +Run : `make test && make run DEBUG=1`. Demander à l'utilisateur : +1. Dans « Égaliseur », les presets ne sont plus grisés, et la mention « bientôt disponible » a disparu. +2. Choisir « Graves » : le son change, et la coche suit. +3. Choisir « Manuel », puis faire glisser un curseur : le son change pendant le glissement, et la valeur + reste après le relâchement. +4. Déconnecter puis reconnecter : l'égaliseur relu est celui qui a été réglé. + +- [ ] **Step 13 : Commit** (par l'utilisateur) + +```bash +git add -A && git commit -m "feat(xm6): equalizer writes (presets + 10-band manual) confirmed on hardware; debug frame sender" +``` + +--- + +### Task 9: README, vérification finale et CI + +**Files:** +- Modify : `README.md` + +- [ ] **Step 1 : Mettre le README à jour** + +- Ligne d'accroche (en gras, sous la bannière) : + `**An unofficial, open-source macOS menu bar app for Sony headphones — Noise Cancelling, Ambient Sound, EQ, DSEE and battery, without the phone.**` +- Section « ✨ Features » : + - remplacer la ligne « 🎛️ **Equalizer** … » par + `- 🎛️ **Equalizer** — presets *and* a **Manual mode** (10 bands on WH-1000XM6, 5 bands + Clear Bass on older models)` + - remplacer la ligne « 🖼️ **Device hero image** … » par + `- 📍 **Lives in the menu bar** — a native macOS menu; the icon shows the current mode` + - remplacer la ligne « 🔌 **Auto-connect** … » par + `- 🔌 **Auto-connect & auto-reconnect**, plus **Launch at Login** — each one can be turned off` + - remplacer la ligne « 🌑 **Modern UI** … » par `- 🌍 **English & French**` +- Section « 🎧 Supported headphones » : si la tâche 8 a confirmé les formats, déplacer `WH-1000XM6` de la ligne + « Expected » vers la ligne « Verified ». + +- [ ] **Step 2 : Chercher les restes de l'ancienne app** + +Run : +`grep -rnE 'xcodeproj|xcodebuild|ContentView|Main\.storyboard|HeadphonesUIFactory' --exclude-dir=.git --exclude-dir=build --exclude-dir=superpowers . || echo clean` +Attendu : `clean`. Sinon, corriger chaque occurrence. + +- [ ] **Step 3 : Build de release** + +Run : `make clean && make test && make release && lipo -archs build/SonyBridge.app/Contents/MacOS/SonyBridge` +Attendu : tout passe, `build/SonyBridge.zip` existe, et `lipo` affiche `x86_64 arm64`. + +- [ ] **Step 4 : Checklist manuelle complète avec l'utilisateur** (spec §9), sur la version de release : + +`open build/SonyBridge.app`, puis vérifier avec lui : +1. Chaque élément du menu (spec §4), casque connecté puis déconnecté. +2. Le bouton physique NC du casque, menu fermé puis menu ouvert. +3. La coupure pour inactivité, puis la reconnexion automatique ; « Déconnecter » n'entraîne pas de reconnexion. +4. Le lancement à l'ouverture de session (depuis `/Applications`). +5. La barre des menus en thème clair puis sombre : l'icône reste lisible. +6. Le Mac en anglais : `open build/SonyBridge.app --args -AppleLanguages '(en)'`, tout le menu en anglais. + +- [ ] **Step 5 : Commit, puis CI** (par l'utilisateur) + +```bash +git add -A && git commit -m "docs: README for the menu bar app" +``` + +L'utilisateur pousse sa branche et ouvre une PR vers `main` : le workflow « macOS » doit passer (`make test` +puis `make release`) et publier l'artefact `SonyBridge-macOS`. + diff --git a/docs/superpowers/plans/2026-09-11-notch.md b/docs/superpowers/plans/2026-09-11-notch.md new file mode 100644 index 0000000..c87750e --- /dev/null +++ b/docs/superpowers/plans/2026-09-11-notch.md @@ -0,0 +1,1985 @@ +# SonyBridge dans l'encoche (étape 1) — plan d'implémentation + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal :** ajouter une encoche interactive en haut de l'écran : au repos elle montre la pochette Spotify et le +mode du casque ; au survol elle s'ouvre sur deux onglets, Musique (Spotify local) et Casque (NC / Ambiant / Off). + +**Architecture :** un `NSPanel` sans bordure et non activant, placé au-dessus de la barre des menus et calé sur +l'encoche (`NotchGeometry`), héberge une vue SwiftUI (`NotchView`). La musique vient d'une interface commune +`MusicSource` ; l'étape 1 n'a que `SpotifyLocalSource` (signal `PlaybackStateChanged` + Apple Events via +`NSAppleScript`), exposée à l'interface par `MusicController`. L'onglet Casque appelle le `HeadphonesModel` existant. +Toute la logique décidable sans AppKit (géométrie, état au repos, horloge de lecture, décodage Spotify) est dans +des fichiers purs testés par `LogicTests`. + +**Tech Stack :** Swift 5 (mode de langage), SwiftUI, AppKit, Combine, Foundation (`NSAppleScript`, +`DistributedNotificationCenter`, `URLSession`) ; build `swiftc` via `scripts/build.sh` et `Makefile` ; tests +`scripts/test.sh` ; Python 3 (vérification des traductions). + +**Spec :** `docs/superpowers/specs/2026-09-11-notch-design.md` + +## Global Constraints + +- macOS minimum : **13.0** (pas d'API macOS 14+ : par exemple pas de `UnevenRoundedRectangle`, pas d'`onChange` à deux paramètres). +- Pas de Xcode : tout se compile avec les Command Line Tools (`make`, `make test`, `make run`, `make release`). +- Swift compilé avec `-swift-version 5`. +- Licence : **aucun code ni visuel copié de boring.notch (GPL-3.0)**, ni d'un autre projet GPL. Tout est écrit ici, + à partir de la documentation Apple. SonyBridge reste sous licence MIT. +- Textes : **tout texte affiché** passe par `tr("…")`, avec la clé en anglais et sa traduction dans + `Client/macos/fr.lproj/Localizable.strings` (apostrophe typographique `’` dans les traductions françaises). + `make test` le vérifie. Les textes non traduisibles (chiffres, « − ») utilisent `Text(verbatim:)`. +- Spotify : **ne jamais envoyer d'Apple Event à Spotify s'il n'est pas ouvert** (un Apple Event lancerait l'app). + Seul le bouton « Ouvrir Spotify » lance Spotify. +- Casque : l'encoche n'envoie **aucune nouvelle commande** au casque ; elle appelle uniquement + `setMode`, `setLevel(_:final:)`, `setFocusOnVoice` et `connect` du `HeadphonesModel` existant. +- Lancement de l'app : **uniquement** `make run` (qui passe par `open … --args`). Ne jamais lancer + `build/SonyBridge.app/Contents/MacOS/SonyBridge` directement (crash TCC), ne jamais utiliser `open --stdout`. + Le journal est `~/Library/Logs/SonyBridge/app.log` (lien `build/app.log`). +- Git : c'est **l'utilisateur** qui committe. À chaque étape « Commit », afficher la commande proposée et attendre + qu'il la lance. +- Test visuel et matériel : l'agent ne voit pas l'écran. Chaque vérification visuelle est demandée à + l'utilisateur, avec une liste précise de choses à regarder. + +## Carte des fichiers + +| Fichier | Tâche | Responsabilité | +|---|---|---| +| `Client/macos/Notch/NotchGeometry.swift` | 1 | **Pur.** `ScreenMetrics`, `NotchGeometry` : rectangles de l'encoche, élargi, ouvert, pastille | +| `Client/macos/Notch/NotchContent.swift` | 1 | **Pur.** `NotchRestingState`, `NotchTab`, `NotchContent` : état au repos, onglet, délais | +| `Client/macos/Music/NowPlaying.swift` | 2 | **Pur.** `MusicCapabilities`, `NowPlaying` | +| `Client/macos/Music/PlaybackClock.swift` | 2 | **Pur.** Position en direct et format « m:ss » | +| `Client/macos/Music/SpotifyPlaybackInfo.swift` | 2 | **Pur.** `SpotifyState`, décodage du signal et de la réponse AppleScript | +| `Client/macos/Music/MusicSource.swift` | 3 | `MusicSourceStatus`, protocole `MusicSource` | +| `Client/macos/Music/SpotifyScript.swift` | 3 | Textes AppleScript et exécution d'un `NSAppleScript` | +| `Client/macos/Music/SpotifyLocalSource.swift` | 3 | Source Spotify locale | +| `Client/macos/Music/MusicController.swift` | 3 | État musique publié pour l'encoche, pochette, limitation des curseurs | +| `Client/macos/Notch/NotchPanel.swift` | 4 | `NotchPanel`, `NotchContainerView` (survol), `NotchHostingView` (premier clic) | +| `Client/macos/Notch/NotchController.swift` | 4 | Écran, placement, taille, survol, option | +| `Client/macos/Notch/NotchView.swift` | 4, 5, 6 | `NotchViewState`, `NotchShape`, `NotchView`, `ArtworkView`, `LevelBars` | +| `Client/macos/Notch/HeadphonesTab.swift` | 5 | Onglet Casque | +| `Client/macos/Notch/MusicTab.swift` | 6 | Onglet Musique | +| `Client/macos/AppSettings.swift` | 3 | Option `showNotch` | +| `Client/macos/HeadphonesMenu.swift` | 3 | Case « Afficher l'encoche » | +| `Client/macos/AppDelegate.swift` | 3, 4 | Crée `MusicController` et `NotchController` | +| `Client/macos/SonyHeadphonesClient.entitlements` | 3 | Apple Events vers Spotify, réseau sortant | +| `Client/macos/info.plist`, `*.lproj/InfoPlist.strings` | 3 | `NSAppleEventsUsageDescription` | +| `Client/macos/fr.lproj/Localizable.strings` | 3–6 | Traductions | +| `scripts/build.sh` | 1 | Compile aussi `Notch/*.swift` et `Music/*.swift` | +| `scripts/test.sh` | 1, 2 | Ajoute les fichiers purs à `LogicTests` | +| `Client/tests/LogicTests/main.swift` | 1, 2 | Nouveaux tests | +| `README.md` | 6 | Fonction encoche, autorisation Spotify | + +`SpotifyScript.swift` n'est pas dans le tableau §5.1 de la spec : c'est un découpage de `SpotifyLocalSource` +(les textes AppleScript à part), sans nouvelle responsabilité. + +Nombre de clés de traduction attendu par `make test` : **54** aujourd'hui → 55 (tâche 3) → 57 (tâche 4) → +58 (tâche 5) → 67 (tâche 6). + +--- + +### Task 1: Logique pure de l'encoche + câblage du build et des tests + +**Files:** +- Create: `Client/macos/Notch/NotchGeometry.swift`, `Client/macos/Notch/NotchContent.swift` +- Modify: `Client/tests/LogicTests/main.swift` (nouveaux blocs avant `if failures > 0`) +- Modify: `scripts/test.sh` (bloc `LogicTests`), `scripts/build.sh:23` (`SWIFT_SOURCES`) + +**Interfaces:** +- Produces : + - `struct ScreenMetrics: Equatable { var frame: CGRect; var safeAreaTop: CGFloat; var auxiliaryTopLeft: CGRect?; var auxiliaryTopRight: CGRect?; var menuBarHeight: CGFloat }` + - `struct NotchGeometry: Equatable { static let sideExtension: CGFloat /* 36 */; static let simulatedWidth: CGFloat /* 190 */; static let fallbackMenuBarHeight: CGFloat /* 24 */; static let openSize: CGSize /* 380 × 190 */; let hasNotch: Bool; let notch: CGRect; init(screen: ScreenMetrics); var extended: CGRect; var open: CGRect; func restingFrame(for state: NotchRestingState) -> CGRect? }` + - `enum NotchRestingState: Equatable { case musicAndHeadphones, musicOnly, headphonesOnly, empty }` + - `enum NotchTab: Equatable { case music, headphones }` + - `enum NotchContent { static let openDelay: TimeInterval /* 0.15 */; static let closeDelay: TimeInterval /* 0.4 */; static func restingState(hasMusic: Bool, headphonesConnected: Bool) -> NotchRestingState; static func tabOnOpen(lastChosen: NotchTab?, hasMusic: Bool) -> NotchTab }` + +- [ ] **Step 1 : Écrire les tests** — dans `Client/tests/LogicTests/main.swift`, ajouter `import CoreGraphics` + sous `import Foundation` (les initialiseurs `CGRect(x:y:width:height:)` en viennent), puis insérer ces blocs + juste avant `if failures > 0 {` : + +```swift +// NotchGeometry: a 14" MacBook Pro screen (1512 × 982 pt, notch 188 pt wide, 32 pt high). +do { + let screen = ScreenMetrics(frame: CGRect(x: 0, y: 0, width: 1512, height: 982), safeAreaTop: 32, + auxiliaryTopLeft: CGRect(x: 0, y: 950, width: 662, height: 32), + auxiliaryTopRight: CGRect(x: 850, y: 950, width: 662, height: 32), + menuBarHeight: 32) + let geometry = NotchGeometry(screen: screen) + check(geometry.hasNotch, "notched screen detected") + check(geometry.notch == CGRect(x: 662, y: 950, width: 188, height: 32), "notch rect was \(geometry.notch)") + check(geometry.extended == CGRect(x: 626, y: 950, width: 260, height: 32), "extended rect was \(geometry.extended)") + check(geometry.open == CGRect(x: 566, y: 792, width: 380, height: 190), "open rect was \(geometry.open)") + check(geometry.restingFrame(for: .empty) == geometry.notch, "empty state: bare notch") + check(geometry.restingFrame(for: .musicOnly) == geometry.extended, "music: extended notch") +} + +// NotchGeometry: an external screen without a notch, right of the primary screen. +do { + let frame = CGRect(x: 1512, y: 0, width: 2560, height: 1440) + let geometry = NotchGeometry(screen: ScreenMetrics(frame: frame, safeAreaTop: 0, auxiliaryTopLeft: nil, + auxiliaryTopRight: nil, menuBarHeight: 25)) + check(!geometry.hasNotch, "no notch") + check(geometry.notch == CGRect(x: 2697, y: 1415, width: 190, height: 25), "simulated pill was \(geometry.notch)") + check(geometry.restingFrame(for: .empty) == nil, "empty state hides the pill") + check(geometry.restingFrame(for: .headphonesOnly) == geometry.extended, "headphones: extended pill") + + let autoHidden = NotchGeometry(screen: ScreenMetrics(frame: frame, safeAreaTop: 0, auxiliaryTopLeft: nil, + auxiliaryTopRight: nil, menuBarHeight: 0)) + check(autoHidden.notch.height == 24, "auto-hidden menu bar: fallback pill height") + let partial = NotchGeometry(screen: ScreenMetrics(frame: frame, safeAreaTop: 32, auxiliaryTopLeft: nil, + auxiliaryTopRight: nil, menuBarHeight: 32)) + check(!partial.hasNotch, "safe area without auxiliary areas: no notch") +} + +// NotchContent: resting state (spec §4.1), tab on opening, hover delays. +do { + check(NotchContent.restingState(hasMusic: true, headphonesConnected: true) == .musicAndHeadphones, "state 1") + check(NotchContent.restingState(hasMusic: true, headphonesConnected: false) == .musicOnly, "state 2") + check(NotchContent.restingState(hasMusic: false, headphonesConnected: true) == .headphonesOnly, "state 3") + check(NotchContent.restingState(hasMusic: false, headphonesConnected: false) == .empty, "state 4") + check(NotchContent.tabOnOpen(lastChosen: nil, hasMusic: true) == .music, "first open with music: Music") + check(NotchContent.tabOnOpen(lastChosen: nil, hasMusic: false) == .headphones, "first open without music: Headphones") + check(NotchContent.tabOnOpen(lastChosen: .headphones, hasMusic: true) == .headphones, "then the last chosen tab") + check(NotchContent.openDelay == 0.15 && NotchContent.closeDelay == 0.4, "hover delays") +} +``` + +- [ ] **Step 2 : Ajouter les fichiers purs à `LogicTests`** — dans `scripts/test.sh`, remplacer le bloc + `LogicTests` par : + +```bash +echo "== LogicTests" +swiftc -target "$TARGET" -sdk "$SDK" -swift-version 5 \ + "$ROOT/Client/tests/LogicTests/main.swift" \ + "$MAC/ReconnectPolicy.swift" "$MAC/PollGuard.swift" "$MAC/SendThrottle.swift" \ + "$MAC/Notch/NotchGeometry.swift" "$MAC/Notch/NotchContent.swift" \ + -o "$OUT/LogicTests" +"$OUT/LogicTests" +``` + +- [ ] **Step 3 : Lancer les tests pour les voir échouer** + +Run : `make test` +Attendu : échec de `swiftc`, `error: no such file or directory: '…/Client/macos/Notch/NotchGeometry.swift'`. + +- [ ] **Step 4 : Écrire `Client/macos/Notch/NotchContent.swift`** + +```swift +import Foundation + +// What the notch shows while resting (spec §4.1) and which tab it opens on. Pure logic, tested in LogicTests. +enum NotchRestingState: Equatable { + case musicAndHeadphones // 1: artwork left, headphones mode right + case musicOnly // 2: artwork left, level bars right + case headphonesOnly // 3: headphones glyph left, mode right + case empty // 4: bare notch (hidden on a screen without a notch) +} + +enum NotchTab: Equatable { + case music, headphones +} + +enum NotchContent { + static let openDelay: TimeInterval = 0.15 // hover time before opening + static let closeDelay: TimeInterval = 0.4 // time after the pointer leaves before closing + + static func restingState(hasMusic: Bool, headphonesConnected: Bool) -> NotchRestingState { + switch (hasMusic, headphonesConnected) { + case (true, true): return .musicAndHeadphones + case (true, false): return .musicOnly + case (false, true): return .headphonesOnly + case (false, false): return .empty + } + } + + // The first opening of the session follows the music; afterwards the last tab the user picked wins. + static func tabOnOpen(lastChosen: NotchTab?, hasMusic: Bool) -> NotchTab { + lastChosen ?? (hasMusic ? .music : .headphones) + } +} +``` + +- [ ] **Step 5 : Écrire `Client/macos/Notch/NotchGeometry.swift`** + +```swift +import CoreGraphics + +// The NSScreen values NotchGeometry needs, copied out so this file stays AppKit-free (tested in LogicTests). +// Rects are in global screen coordinates (origin at the bottom-left of the primary screen). +struct ScreenMetrics: Equatable { + var frame: CGRect + var safeAreaTop: CGFloat // NSScreen.safeAreaInsets.top (0 without a notch) + var auxiliaryTopLeft: CGRect? // NSScreen.auxiliaryTopLeftArea (nil without a notch) + var auxiliaryTopRight: CGRect? // NSScreen.auxiliaryTopRightArea + var menuBarHeight: CGFloat // frame.maxY - visibleFrame.maxY (0 when the menu bar auto-hides) +} + +// Where the notch panel goes (spec §4): the real notch, or a simulated pill centred at the top of a screen +// without one. Every rect shares the notch's horizontal centre and touches the top edge of the screen. +struct NotchGeometry: Equatable { + static let sideExtension: CGFloat = 36 // resting widening on each side (states 1-3) + static let simulatedWidth: CGFloat = 190 // pill width on a screen without a notch + static let fallbackMenuBarHeight: CGFloat = 24 // pill height when the menu bar auto-hides + static let openSize = CGSize(width: 380, height: 190) + + let hasNotch: Bool + let notch: CGRect + + init(screen: ScreenMetrics) { + let top = screen.frame.maxY + if screen.safeAreaTop > 0, let left = screen.auxiliaryTopLeft, let right = screen.auxiliaryTopRight, + screen.frame.width - left.width - right.width > 0 { + // Only the widths of the auxiliary areas are used, so their coordinate space doesn't matter. + hasNotch = true + notch = CGRect(x: screen.frame.minX + left.width, y: top - screen.safeAreaTop, + width: screen.frame.width - left.width - right.width, height: screen.safeAreaTop) + } else { + hasNotch = false + let height = screen.menuBarHeight > 0 ? screen.menuBarHeight : Self.fallbackMenuBarHeight + notch = CGRect(x: screen.frame.midX - Self.simulatedWidth / 2, y: top - height, + width: Self.simulatedWidth, height: height) + } + } + + // The notch widened on both sides, to hold the resting artwork / mode icons. + var extended: CGRect { + notch.insetBy(dx: -Self.sideExtension, dy: 0) + } + + var open: CGRect { + let width = max(Self.openSize.width, extended.width) + let height = max(Self.openSize.height, notch.height) + return CGRect(x: notch.midX - width / 2, y: notch.maxY - height, width: width, height: height) + } + + // Panel frame while resting; nil = hidden (nothing to show on a screen without a notch). + func restingFrame(for state: NotchRestingState) -> CGRect? { + switch state { + case .empty: return hasNotch ? notch : nil + default: return extended + } + } +} +``` + +- [ ] **Step 6 : Compiler les nouveaux dossiers dans l'app** — `scripts/build.sh:23`, remplacer la ligne par : + +```bash +SWIFT_SOURCES=("$MAC"/*.swift "$MAC"/MenuRows/*.swift "$MAC"/Notch/*.swift "$MAC"/Music/*.swift) +``` + +(`shopt -s nullglob` est déjà actif : `Music/` vide ne gêne pas.) + +- [ ] **Step 7 : Lancer les tests et le build** + +Run : `make test && make` +Attendu : `LogicTests: all passed`, les 3 autres suites passent, `Localization: 54 keys, all translated`, puis +`OK -> …/build/SonyBridge.app`, sans avertissement Swift. + +- [ ] **Step 8 : Commit (par l'utilisateur)** + +```bash +git add Client/macos/Notch Client/tests/LogicTests/main.swift scripts/test.sh scripts/build.sh && git commit -m "feat(notch): notch geometry and resting-state logic" -m "Co-Authored-By: Claude Opus 5 " +``` + +--- + +### Task 2: Logique pure de la musique + +**Files:** +- Create: `Client/macos/Music/NowPlaying.swift`, `Client/macos/Music/PlaybackClock.swift`, + `Client/macos/Music/SpotifyPlaybackInfo.swift` +- Modify: `Client/tests/LogicTests/main.swift` (nouveaux blocs avant `if failures > 0`), `scripts/test.sh` + +**Interfaces:** +- Produces : + - `struct MusicCapabilities: Equatable { var canSeek: Bool; var canSetVolume: Bool; var canChangeDevice: Bool }` + - `struct NowPlaying: Equatable { var trackID: String; var title: String; var artist: String; var album: String; var artworkURL: URL?; var duration: TimeInterval; var position: TimeInterval; var positionDate: Date; var isPlaying: Bool; var volume: Int?; var deviceName: String?; var capabilities: MusicCapabilities }` (memberwise init, arguments dans cet ordre ; `deviceName == nil` = « Ce Mac ») + - `enum PlaybackClock { static func position(of track: NowPlaying, at date: Date) -> TimeInterval; static func format(_ seconds: TimeInterval) -> String }` + - `enum SpotifyState: Equatable { case stopped; case track(NowPlaying); case incomplete }` + - `enum SpotifyPlaybackInfo { static let localCapabilities: MusicCapabilities; static let fieldSeparator: Character /* U+001F */; static func parse(signal userInfo: [AnyHashable: Any]?, at date: Date) -> SpotifyState; static func parse(scriptResult text: String, at date: Date) -> SpotifyState }` + +- [ ] **Step 1 : Écrire les tests** — dans `Client/tests/LogicTests/main.swift`, insérer avant `if failures > 0 {` : + +```swift +// PlaybackClock: live position from the last known one; display format. +do { + let t0 = Date(timeIntervalSince1970: 1_000) + var track = NowPlaying(trackID: "spotify:track:1", title: "A", artist: "B", album: "C", artworkURL: nil, + duration: 200, position: 30, positionDate: t0, isPlaying: true, volume: 50, + deviceName: nil, + capabilities: MusicCapabilities(canSeek: true, canSetVolume: true, canChangeDevice: false)) + check(PlaybackClock.position(of: track, at: t0.addingTimeInterval(12)) == 42, "playing: advances") + check(PlaybackClock.position(of: track, at: t0.addingTimeInterval(500)) == 200, "bounded by the duration") + check(PlaybackClock.position(of: track, at: t0.addingTimeInterval(-40)) == 0, "never negative") + track.isPlaying = false + check(PlaybackClock.position(of: track, at: t0.addingTimeInterval(12)) == 30, "paused: frozen") + track.isPlaying = true + track.duration = 0 + check(PlaybackClock.position(of: track, at: t0.addingTimeInterval(500)) == 530, "unknown duration: not bounded") + let nextTrack = NowPlaying(trackID: "spotify:track:2", title: "D", artist: "E", album: "F", artworkURL: nil, + duration: 180, position: 0, positionDate: t0.addingTimeInterval(100), isPlaying: true, + volume: 50, deviceName: nil, capabilities: track.capabilities) + check(PlaybackClock.position(of: nextTrack, at: t0.addingTimeInterval(100)) == 0, "track change: starts from 0") + check(PlaybackClock.format(65) == "1:05", "format 1:05 was \(PlaybackClock.format(65))") + check(PlaybackClock.format(754.9) == "12:34", "format rounds down") + check(PlaybackClock.format(3723) == "1:02:03", "format with hours") + check(PlaybackClock.format(-3) == "0:00", "format never negative") +} + +// SpotifyPlaybackInfo: the PlaybackStateChanged signal (spec §6.1). +do { + let t0 = Date(timeIntervalSince1970: 1_000) + let signal: [AnyHashable: Any] = [ + "Player State": "Playing", "Track ID": "spotify:track:42", "Name": "Midnight City", "Artist": "M83", + "Album": "Hurry Up, We're Dreaming", "Duration": NSNumber(value: 243_000), "Playback Position": NSNumber(value: 12.5), + ] + if case .track(let track) = SpotifyPlaybackInfo.parse(signal: signal, at: t0) { + check(track.trackID == "spotify:track:42" && track.title == "Midnight City" && track.artist == "M83", "signal: names") + check(track.duration == 243 && track.position == 12.5 && track.positionDate == t0 && track.isPlaying, "signal: timing") + check(track.artworkURL == nil && track.volume == nil && track.deviceName == nil, "signal: no artwork or volume, this Mac") + check(track.capabilities == SpotifyPlaybackInfo.localCapabilities, "signal: local capabilities") + } else { + check(false, "signal with full info decodes to a track") + } + var paused = signal + paused["Player State"] = "Paused" + paused["Playback Position"] = nil + if case .track(let track) = SpotifyPlaybackInfo.parse(signal: paused, at: t0) { + check(!track.isPlaying && track.position == 0, "paused, no position: 0") + } else { + check(false, "paused signal decodes to a track") + } + check(SpotifyPlaybackInfo.parse(signal: ["Player State": "Stopped"], at: t0) == .stopped, "signal: stopped") + check(SpotifyPlaybackInfo.parse(signal: nil, at: t0) == .incomplete, "signal without userInfo: incomplete") + check(SpotifyPlaybackInfo.parse(signal: ["Player State": "Playing"], at: t0) == .incomplete, "signal without track id: incomplete") +} + +// SpotifyPlaybackInfo: the text SpotifyScript.readState returns (fields separated by U+001F). +do { + let t0 = Date(timeIntervalSince1970: 1_000) + let sep = "\u{1F}" + let text = ["paused", "spotify:track:7", "Title", "Artist", "Album", "180000", "61500", + "https://i.scdn.co/image/ab", "70"].joined(separator: sep) + if case .track(let track) = SpotifyPlaybackInfo.parse(scriptResult: text, at: t0) { + check(!track.isPlaying && track.duration == 180 && track.position == 61.5, "script: timing") + check(track.artworkURL == URL(string: "https://i.scdn.co/image/ab") && track.volume == 70, "script: artwork and volume") + check(track.title == "Title" && track.album == "Album" && track.positionDate == t0, "script: names") + } else { + check(false, "script result decodes to a track") + } + let local = ["playing", "spotify:local:x", "T", "", "", "1000", "0", "", "101"].joined(separator: sep) + if case .track(let track) = SpotifyPlaybackInfo.parse(scriptResult: local, at: t0) { + check(track.artworkURL == nil && track.volume == 100 && track.artist.isEmpty, "script: empty fields, volume clamped") + } else { + check(false, "script result with empty fields decodes to a track") + } + check(SpotifyPlaybackInfo.parse(scriptResult: "stopped", at: t0) == .stopped, "script: stopped") + check(SpotifyPlaybackInfo.parse(scriptResult: "garbage", at: t0) == .incomplete, "script: malformed") +} +``` + +- [ ] **Step 2 : Ajouter les fichiers à `LogicTests`** — dans `scripts/test.sh`, bloc `LogicTests`, ajouter une + ligne après celle de `Notch/` : + +```bash + "$MAC/Music/NowPlaying.swift" "$MAC/Music/PlaybackClock.swift" "$MAC/Music/SpotifyPlaybackInfo.swift" \ +``` + +- [ ] **Step 3 : Lancer les tests pour les voir échouer** + +Run : `make test` +Attendu : échec de `swiftc`, `error: no such file or directory: '…/Client/macos/Music/NowPlaying.swift'`. + +- [ ] **Step 4 : Écrire `Client/macos/Music/NowPlaying.swift`** + +```swift +import Foundation + +// What a music source can do with the current track (the Web source of step 2 depends on the device). +struct MusicCapabilities: Equatable { + var canSeek: Bool + var canSetVolume: Bool + var canChangeDevice: Bool +} + +// The track a music source is playing (or paused on). `position` was true at `positionDate`; PlaybackClock +// derives the live position from it, so nothing polls while a track plays. +struct NowPlaying: Equatable { + var trackID: String + var title: String + var artist: String + var album: String + var artworkURL: URL? + var duration: TimeInterval // seconds; 0 when unknown + var position: TimeInterval // seconds, at positionDate + var positionDate: Date + var isPlaying: Bool + var volume: Int? // 0...100; nil until known + var deviceName: String? // nil = this Mac + var capabilities: MusicCapabilities +} +``` + +- [ ] **Step 5 : Écrire `Client/macos/Music/PlaybackClock.swift`** + +```swift +import Foundation + +// Live playback position and its display, from the last known position (spec §6.1). +enum PlaybackClock { + static func position(of track: NowPlaying, at date: Date) -> TimeInterval { + var position = track.position + if track.isPlaying { position += date.timeIntervalSince(track.positionDate) } + if track.duration > 0 { position = min(position, track.duration) } + return max(0, position) + } + + // "1:05", "12:34", "1:02:03". + static func format(_ seconds: TimeInterval) -> String { + let total = max(0, Int(seconds.rounded(.down))) + let hours = total / 3600, minutes = total / 60 % 60, secs = total % 60 + return hours > 0 + ? String(format: "%d:%02d:%02d", hours, minutes, secs) + : String(format: "%d:%02d", minutes, secs) + } +} +``` + +- [ ] **Step 6 : Écrire `Client/macos/Music/SpotifyPlaybackInfo.swift`** + +```swift +import Foundation + +// Result of decoding what the local Spotify app reports. +enum SpotifyState: Equatable { + case stopped // Spotify is open with nothing loaded + case track(NowPlaying) + case incomplete // not enough information: read the state through Apple Events instead +} + +// Decodes the local Spotify app's signal and Apple Events replies (spec §6.1). Pure, tested in LogicTests. +enum SpotifyPlaybackInfo { + static let localCapabilities = MusicCapabilities(canSeek: true, canSetVolume: true, canChangeDevice: false) + static let fieldSeparator: Character = "\u{1F}" + + // com.spotify.client.PlaybackStateChanged userInfo: "Player State" (Playing / Paused / Stopped), "Track ID", + // "Name", "Artist", "Album", "Duration" (ms), "Playback Position" (s). It never carries artwork or volume. + static func parse(signal userInfo: [AnyHashable: Any]?, at date: Date) -> SpotifyState { + guard let info = userInfo, let state = info["Player State"] as? String else { return .incomplete } + if state == "Stopped" { return .stopped } + guard state == "Playing" || state == "Paused", + let trackID = info["Track ID"] as? String, !trackID.isEmpty else { return .incomplete } + return .track(NowPlaying( + trackID: trackID, + title: info["Name"] as? String ?? "", + artist: info["Artist"] as? String ?? "", + album: info["Album"] as? String ?? "", + artworkURL: nil, + duration: ((info["Duration"] as? NSNumber)?.doubleValue ?? 0) / 1000, + position: (info["Playback Position"] as? NSNumber)?.doubleValue ?? 0, + positionDate: date, + isPlaying: state == "Playing", + volume: nil, + deviceName: nil, + capabilities: localCapabilities)) + } + + // SpotifyScript.readState's reply: "stopped", or 9 fields separated by U+001F — state, track id, name, + // artist, album, duration (ms), position (ms), artwork URL, volume. + static func parse(scriptResult text: String, at date: Date) -> SpotifyState { + if text == "stopped" { return .stopped } + let fields = text.split(separator: fieldSeparator, omittingEmptySubsequences: false).map(String.init) + guard fields.count == 9, fields[0] == "playing" || fields[0] == "paused", !fields[1].isEmpty else { + return .incomplete + } + return .track(NowPlaying( + trackID: fields[1], + title: fields[2], + artist: fields[3], + album: fields[4], + artworkURL: URL(string: fields[7]), + duration: (Double(fields[5]) ?? 0) / 1000, + position: (Double(fields[6]) ?? 0) / 1000, + positionDate: date, + isPlaying: fields[0] == "playing", + volume: Int(fields[8]).map { min(100, max(0, $0)) }, + deviceName: nil, + capabilities: localCapabilities)) + } +} +``` + +- [ ] **Step 7 : Lancer les tests et le build** + +Run : `make test && make` +Attendu : `LogicTests: all passed`, `Localization: 54 keys, all translated`, build `OK`, sans avertissement. + +- [ ] **Step 8 : Commit (par l'utilisateur)** + +```bash +git add Client/macos/Music Client/tests/LogicTests/main.swift scripts/test.sh && git commit -m "feat(music): now-playing model, playback clock and Spotify info decoding" -m "Co-Authored-By: Claude Opus 5 " +``` + +--- + +### Task 3: Source Spotify locale + `MusicController` + option « Afficher l'encoche » + +Pas de test unitaire ici (AppKit, Apple Events, signaux système) : la logique décidable est déjà testée en +tâche 2. La vérification se fait dans le journal, sur le Mac de l'utilisateur, avant que l'encoche existe. + +**Files:** +- Create: `Client/macos/Music/MusicSource.swift`, `Client/macos/Music/SpotifyScript.swift`, + `Client/macos/Music/SpotifyLocalSource.swift`, `Client/macos/Music/MusicController.swift` +- Modify: `Client/macos/AppSettings.swift`, `Client/macos/HeadphonesMenu.swift`, `Client/macos/AppDelegate.swift` +- Modify: `Client/macos/SonyHeadphonesClient.entitlements`, `Client/macos/info.plist`, + `Client/macos/en.lproj/InfoPlist.strings`, `Client/macos/fr.lproj/InfoPlist.strings`, + `Client/macos/fr.lproj/Localizable.strings` + +**Interfaces:** +- Consumes (tâche 2) : `NowPlaying`, `PlaybackClock.position(of:at:)`, `SpotifyState`, + `SpotifyPlaybackInfo.parse(signal:at:)`, `SpotifyPlaybackInfo.parse(scriptResult:at:)` ; existant : `SendThrottle`. +- Produces : + - `enum MusicSourceStatus: Equatable { case notRunning, permissionDenied, ready }` + - `protocol MusicSource: AnyObject { var onChange: ((MusicSourceStatus, NowPlaying?) -> Void)? { get set }; func start(); func stop(); func refresh(); func playPause(); func next(); func previous(); func seek(to seconds: TimeInterval); func setVolume(_ volume: Int); func launchPlayer() }` + - `final class MusicController: ObservableObject { @Published private(set) var status: MusicSourceStatus; @Published private(set) var nowPlaying: NowPlaying?; @Published private(set) var artwork: NSImage?; var hasMusic: Bool; init(source: MusicSource = SpotifyLocalSource()); func start(); func stop(); func notchDidOpen(); func notchDidClose(); func playPause(); func next(); func previous(); func seek(to seconds: TimeInterval, final: Bool); func setVolume(_ volume: Int, final: Bool); func launchPlayer(); func openAutomationSettings() }` + - `AppSettings.showNotch: Bool` (`@Published`, activée par défaut) + - `AppDelegate` : propriété `music: MusicController`, démarrée / arrêtée selon `settings.showNotch` + +- [ ] **Step 1 : Écrire `Client/macos/Music/MusicSource.swift`** + +```swift +import Foundation + +enum MusicSourceStatus: Equatable { + case notRunning // the player app isn't open + case permissionDenied // macOS refused SonyBridge the right to control it + case ready +} + +// Where the music comes from (spec §5.1). Step 1: SpotifyLocalSource; step 2 adds the Spotify Web API. +// Called on the main thread; onChange is called on the main thread. +protocol MusicSource: AnyObject { + var onChange: ((MusicSourceStatus, NowPlaying?) -> Void)? { get set } + func start() + func stop() + func refresh() + func playPause() + func next() + func previous() + func seek(to seconds: TimeInterval) + func setVolume(_ volume: Int) + func launchPlayer() +} +``` + +- [ ] **Step 2 : Écrire `Client/macos/Music/SpotifyScript.swift`** + +```swift +import Foundation + +// AppleScript sent to the local Spotify app (spec §6). Only ever run on SpotifyLocalSource's script queue. +enum SpotifyScript { + enum Result: Equatable { + case success(String) + case failure(Int) // AppleScript / Apple Event error number + } + + // Fields joined by U+001F; times as integer milliseconds so no locale decimal separator shows up. + // Parsed by SpotifyPlaybackInfo.parse(scriptResult:at:). + static let readState = """ + with timeout of 2 seconds + tell application id "com.spotify.client" + set playerState to (player state as text) + if playerState is "stopped" then return "stopped" + set t to current track + set sep to (character id 31) + set art to artwork url of t + if art is missing value then set art to "" + return playerState & sep & (id of t) & sep & (name of t) & sep & (artist of t) & sep & (album of t) & sep & ((duration of t) as text) & sep & ((((player position) * 1000) div 1) as text) & sep & art & sep & ((sound volume) as text) + end tell + end timeout + """ + + // One command, e.g. "playpause", "next track", "set sound volume to 40". + static func command(_ body: String) -> String { + """ + with timeout of 2 seconds + tell application id "com.spotify.client" to \(body) + end timeout + """ + } + + static func run(_ script: NSAppleScript?) -> Result { + guard let script = script else { return .failure(-2700) } + var error: NSDictionary? + let output = script.executeAndReturnError(&error) + if let error = error { + return .failure((error[NSAppleScript.errorNumber] as? NSNumber)?.intValue ?? -2700) + } + return .success(output.stringValue ?? "") + } +} +``` + +- [ ] **Step 3 : Écrire `Client/macos/Music/SpotifyLocalSource.swift`** + +```swift +import AppKit + +// Reads and controls the Spotify app of this Mac (spec §6): its PlaybackStateChanged signal, plus Apple Events. +// Never sends an Apple Event while Spotify isn't running: one would launch it. +final class SpotifyLocalSource: MusicSource { + static let bundleIdentifier = "com.spotify.client" + private static let signalName = Notification.Name("com.spotify.client.PlaybackStateChanged") + private static let permissionDeniedError = -1743 // errAEEventNotPermitted + private static let notRunningErrors: Set = [-600, -609] // procNotFound, connectionInvalid + private static let launchSettleDelay: TimeInterval = 2 // Spotify answers Apple Events a moment after launch + + var onChange: ((MusicSourceStatus, NowPlaying?) -> Void)? + + // Main thread only. + private var status: MusicSourceStatus = .notRunning + private var nowPlaying: NowPlaying? + private var signalObserver: NSObjectProtocol? + private var workspaceObservers: [NSObjectProtocol] = [] + + // Every NSAppleScript is created and run on this serial queue, one at a time. + private let scriptQueue = DispatchQueue(label: "com.sonybridge.spotify") + private var readScript: NSAppleScript? // scriptQueue only + + // Checked before queuing, and again on the script queue right before an Apple Event goes out, so a Spotify + // quit in between is never relaunched. + private static var spotifyIsRunning: Bool { + !NSRunningApplication.runningApplications(withBundleIdentifier: bundleIdentifier).isEmpty + } + + private var isRunning: Bool { Self.spotifyIsRunning } + + func start() { + guard signalObserver == nil else { return } + signalObserver = DistributedNotificationCenter.default().addObserver( + forName: Self.signalName, object: nil, queue: .main + ) { [weak self] note in + self?.handleSignal(note.userInfo) + } + let center = NSWorkspace.shared.notificationCenter + workspaceObservers = [ + center.addObserver(forName: NSWorkspace.didLaunchApplicationNotification, object: nil, queue: .main) { [weak self] note in + guard Self.isSpotify(note) else { return } + DispatchQueue.main.asyncAfter(deadline: .now() + Self.launchSettleDelay) { self?.refresh() } + }, + center.addObserver(forName: NSWorkspace.didTerminateApplicationNotification, object: nil, queue: .main) { [weak self] note in + if Self.isSpotify(note) { self?.publish(.notRunning, nil) } + }, + ] + if isRunning { refresh() } else { publish(.notRunning, nil) } + } + + func stop() { + if let observer = signalObserver { DistributedNotificationCenter.default().removeObserver(observer) } + signalObserver = nil + workspaceObservers.forEach { NSWorkspace.shared.notificationCenter.removeObserver($0) } + workspaceObservers = [] + status = .notRunning + nowPlaying = nil + } + + func refresh() { + guard signalObserver != nil else { return } + guard isRunning else { publish(.notRunning, nil); return } + scriptQueue.async { [weak self] in + guard let self = self, Self.spotifyIsRunning else { return } + if self.readScript == nil { self.readScript = NSAppleScript(source: SpotifyScript.readState) } + let result = SpotifyScript.run(self.readScript) + DispatchQueue.main.async { self.applyRead(result) } + } + } + + func playPause() { + // Optimistic: the signal confirms a moment later. + if var track = nowPlaying { + track.position = PlaybackClock.position(of: track, at: Date()) + track.positionDate = Date() + track.isPlaying.toggle() + publish(status, track) + } + send("playpause") + } + + func next() { send("next track") } + + func previous() { send("previous track") } + + func seek(to seconds: TimeInterval) { + if var track = nowPlaying { + track.position = seconds + track.positionDate = Date() + publish(status, track) + } + // String(format:) isn't localized: always a "." decimal separator, as AppleScript source needs. + send(String(format: "set player position to %.3f", seconds)) + } + + func setVolume(_ volume: Int) { + let clamped = min(100, max(0, volume)) + if var track = nowPlaying { + track.volume = clamped + publish(status, track) + } + send("set sound volume to \(clamped)") + } + + func launchPlayer() { + guard let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: Self.bundleIdentifier) else { + fputs("[spotify] Spotify isn't installed\n", stderr) + return + } + NSWorkspace.shared.openApplication(at: url, configuration: NSWorkspace.OpenConfiguration(), + completionHandler: nil) + } + + // MARK: - Private + + private func send(_ command: String) { + guard signalObserver != nil else { return } + guard isRunning else { publish(.notRunning, nil); return } + scriptQueue.async { [weak self] in + guard Self.spotifyIsRunning else { return } + let result = SpotifyScript.run(NSAppleScript(source: SpotifyScript.command(command))) + if case .failure(let code) = result { + DispatchQueue.main.async { self?.applyFailure(code) } + } + } + } + + private func handleSignal(_ userInfo: [AnyHashable: Any]?) { + let denied = status == .permissionDenied + switch SpotifyPlaybackInfo.parse(signal: userInfo, at: Date()) { + case .stopped: + publish(denied ? .permissionDenied : .ready, nil) + case .track(var track): + // Artwork and volume only come from Apple Events: keep them for the same track, read them otherwise. + if let current = nowPlaying, current.trackID == track.trackID { + track.artworkURL = current.artworkURL + track.volume = current.volume + } + publish(denied ? .permissionDenied : .ready, track) + if track.artworkURL == nil && !denied { refresh() } + case .incomplete: + if !denied { refresh() } + } + } + + private func applyRead(_ result: SpotifyScript.Result) { + guard signalObserver != nil else { return } // stopped meanwhile + switch result { + case .success(let text): + switch SpotifyPlaybackInfo.parse(scriptResult: text, at: Date()) { + case .stopped: publish(.ready, nil) + case .track(let track): publish(.ready, track) + case .incomplete: fputs("[spotify] unexpected reply: \(text)\n", stderr) + } + case .failure(let code): + applyFailure(code) + } + } + + // Spec §6.3: a refusal stops the reads (the controller retries once per notch opening); anything else + // (timeout, busy) keeps the last known state until the next signal. + private func applyFailure(_ code: Int) { + guard signalObserver != nil else { return } + if code == Self.permissionDeniedError { + publish(.permissionDenied, nowPlaying) + } else if Self.notRunningErrors.contains(code) { + publish(.notRunning, nil) + } else { + fputs("[spotify] Apple Event failed (\(code))\n", stderr) + } + } + + private func publish(_ newStatus: MusicSourceStatus, _ track: NowPlaying?) { + status = newStatus + nowPlaying = track + onChange?(newStatus, track) + } + + private static func isSpotify(_ note: Notification) -> Bool { + (note.userInfo?[NSWorkspace.applicationUserInfoKey] as? NSRunningApplication)?.bundleIdentifier == bundleIdentifier + } +} +``` + +- [ ] **Step 4 : Écrire `Client/macos/Music/MusicController.swift`** + +```swift +import AppKit +import Combine + +// The music state the notch shows, from the active MusicSource (spec §5.1). Step 1: the local Spotify app. +final class MusicController: ObservableObject { + static let openRefreshInterval: TimeInterval = 5 // re-read while the notch is open (volume isn't signalled) + private static let artworkCacheSize = 8 + + @Published private(set) var status: MusicSourceStatus = .notRunning + @Published private(set) var nowPlaying: NowPlaying? + @Published private(set) var artwork: NSImage? + + // Something to show: a track, playing or paused (even without the right to control it). + var hasMusic: Bool { status != .notRunning && nowPlaying != nil } + + private let source: MusicSource + private var running = false + private var refreshTimer: Timer? + private var seekThrottle = SendThrottle() + private var volumeThrottle = SendThrottle() + private var artworkCache: [URL: NSImage] = [:] + private var artworkOrder: [URL] = [] + private var artworkRequest: URL? + private var lastLogLine = "" + + init(source: MusicSource = SpotifyLocalSource()) { + self.source = source + source.onChange = { [weak self] status, track in self?.apply(status, track) } + } + + func start() { + guard !running else { return } + running = true + source.start() + } + + // "Show Notch" off: no Spotify reads at all (spec §4.3). + func stop() { + guard running else { return } + running = false + notchDidClose() + source.stop() + status = .notRunning + nowPlaying = nil + artwork = nil + artworkRequest = nil + log("stopped") + } + + // Opening reads once (which also retries a refused permission, spec §6.3), then every 5 s while open. + func notchDidOpen() { + guard running else { return } + source.refresh() + refreshTimer?.invalidate() + let timer = Timer(timeInterval: Self.openRefreshInterval, repeats: true) { [weak self] _ in + guard let self = self, self.status == .ready else { return } + self.source.refresh() + } + RunLoop.main.add(timer, forMode: .common) + refreshTimer = timer + } + + func notchDidClose() { + refreshTimer?.invalidate() + refreshTimer = nil + } + + func playPause() { source.playPause() } + + func next() { source.next() } + + func previous() { source.previous() } + + // Sliders: at most one command per 150 ms while dragging, the final value always, then a read-back. + func seek(to seconds: TimeInterval, final: Bool) { + if seekThrottle.shouldSend(final: final) { source.seek(to: seconds) } + if final { source.refresh() } + } + + func setVolume(_ volume: Int, final: Bool) { + if volumeThrottle.shouldSend(final: final) { source.setVolume(volume) } + if final { source.refresh() } + } + + func launchPlayer() { source.launchPlayer() } + + func openAutomationSettings() { + if let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Automation") { + NSWorkspace.shared.open(url) + } + } + + // MARK: - Private + + private func apply(_ newStatus: MusicSourceStatus, _ track: NowPlaying?) { + guard running else { return } + status = newStatus + nowPlaying = track + loadArtwork(track?.artworkURL) + switch (newStatus, track) { + case (.notRunning, _): log("not running") + case (.permissionDenied, _): log("permission denied") + case (.ready, nil): log("nothing playing") + case (.ready, let track?): + log("\(track.isPlaying ? "playing" : "paused") \(track.trackID) vol \(track.volume.map(String.init) ?? "?")") + } + } + + // One line per actual change (the 5 s re-reads stay quiet). + private func log(_ line: String) { + guard line != lastLogLine else { return } + lastLogLine = line + fputs("[spotify] \(line)\n", stderr) + } + + private func loadArtwork(_ url: URL?) { + guard let url = url else { + artwork = nil + artworkRequest = nil + return + } + if let cached = artworkCache[url] { + artwork = cached + artworkRequest = nil + return + } + guard artworkRequest != url else { return } // already downloading + artworkRequest = url + URLSession.shared.dataTask(with: url) { [weak self] data, _, _ in + let image = data.flatMap { NSImage(data: $0) } + DispatchQueue.main.async { + guard let self = self, self.artworkRequest == url else { return } + self.artworkRequest = nil + guard let image = image else { return } + self.remember(image, for: url) + self.artwork = image + } + }.resume() + } + + private func remember(_ image: NSImage, for url: URL) { + artworkCache[url] = image + artworkOrder.removeAll { $0 == url } + artworkOrder.append(url) + if artworkOrder.count > Self.artworkCacheSize { + artworkCache[artworkOrder.removeFirst()] = nil + } + } +} +``` + +- [ ] **Step 5 : Option `showNotch` dans `Client/macos/AppSettings.swift`** + +Remplacer le commentaire de tête, l'enum `Keys`, ajouter la propriété et compléter `init` : + +```swift +// The user options, persisted in UserDefaults. Launch at login is backed by SMAppService (macOS 13+). +final class AppSettings: ObservableObject { + private enum Keys { + static let autoConnect = "autoConnect" + static let autoReconnect = "autoReconnect" + static let lastDeviceAddress = "lastDeviceAddress" + static let showNotch = "showNotch" + } +``` + +Après la propriété `autoReconnect` : + +```swift + @Published var showNotch: Bool { + didSet { defaults.set(showNotch, forKey: Keys.showNotch) } + } +``` + +Dans `init`, remplacer les lignes `register` et suivantes jusqu'à `launchAtLogin = …` exclu par : + +```swift + // Spec §4: auto-connect and auto-reconnect default on; launch at login stays off until the user asks. + // Notch spec §7: the notch is shown by default. + defaults.register(defaults: [Keys.autoConnect: true, Keys.autoReconnect: true, Keys.showNotch: true]) + autoConnect = defaults.bool(forKey: Keys.autoConnect) + autoReconnect = defaults.bool(forKey: Keys.autoReconnect) + showNotch = defaults.bool(forKey: Keys.showNotch) +``` + +- [ ] **Step 6 : Case « Afficher l'encoche » dans `Client/macos/HeadphonesMenu.swift`** + +Après `private var autoReconnectItem = NSMenuItem()` (ligne 31) : + +```swift + private var showNotchItem = NSMenuItem() +``` + +Dans `addAppSection()`, remplacer les lignes de `autoReconnectItem = …` et la boucle `for item in […]` par : + +```swift + autoReconnectItem = ActionMenuItem(tr("Reconnect Automatically")) { [weak settings] in settings?.autoReconnect.toggle() } + showNotchItem = ActionMenuItem(tr("Show Notch")) { [weak settings] in settings?.showNotch.toggle() } + for item in [launchAtLoginItem, autoConnectItem, autoReconnectItem, showNotchItem] { optionsMenu.addItem(item) } +``` + +À la fin de `update()`, après `autoReconnectItem.state = …` : + +```swift + showNotchItem.state = settings.showNotch ? .on : .off +``` + +- [ ] **Step 7 : Démarrer / arrêter la musique selon l'option** — remplacer `Client/macos/AppDelegate.swift` par : + +```swift +import AppKit +import Combine + +final class AppDelegate: NSObject, NSApplicationDelegate { + private let model = HeadphonesModel() + private let settings = AppSettings() + private let music = MusicController() + private let deviceWatcher = DeviceWatcher() + private var statusItemController: StatusItemController? + private var cancellables = Set() + + func applicationDidFinishLaunching(_ notification: Notification) { + model.settings = settings + statusItemController = StatusItemController(model: model, settings: settings) + + // Spotify is only read while the notch is on (notch spec §4.3). $showNotch emits the current value first. + settings.$showNotch + .receive(on: DispatchQueue.main) + .sink { [weak self] show in + if show { self?.music.start() } else { self?.music.stop() } + } + .store(in: &cancellables) + + deviceWatcher.onConnect = { [weak self] address, name in + self?.model.headsetConnectedToMac(address: address, name: name) + } + deviceWatcher.onDisconnect = { [weak self] address in + self?.model.headsetDisconnectedFromMac(address: address) + } + deviceWatcher.start() + + if settings.autoConnect { model.autoConnectOnLaunch() } + } + + func applicationWillTerminate(_ notification: Notification) { + model.disconnect() + } +} +``` + +- [ ] **Step 8 : Autorisations** — remplacer `Client/macos/SonyHeadphonesClient.entitlements` par : + +```xml + + + + + com.apple.security.app-sandbox + + com.apple.security.device.bluetooth + + com.apple.security.files.user-selected.read-only + + com.apple.security.network.client + + com.apple.security.temporary-exception.apple-events + + com.spotify.client + + com.apple.security.temporary-exception.files.home-relative-path.read-write + + /Library/Logs/SonyBridge/ + + + +``` + +Dans `Client/macos/info.plist`, après la valeur de `NSBluetoothAlwaysUsageDescription` : + +```xml + NSAppleEventsUsageDescription + SonyBridge shows and controls the music playing in Spotify. +``` + +Ajouter à la fin de `Client/macos/en.lproj/InfoPlist.strings` : + +``` +"NSAppleEventsUsageDescription" = "SonyBridge shows and controls the music playing in Spotify."; +``` + +Ajouter à la fin de `Client/macos/fr.lproj/InfoPlist.strings` : + +``` +"NSAppleEventsUsageDescription" = "SonyBridge affiche et contrôle la musique en cours dans Spotify."; +``` + +- [ ] **Step 9 : Traduction** — dans `Client/macos/fr.lproj/Localizable.strings`, après la ligne + `"Reconnect Automatically" = "Reconnexion automatique";` : + +``` +"Show Notch" = "Afficher l’encoche"; +``` + +- [ ] **Step 10 : Tests et build** + +Run : `make test && make` +Attendu : toutes les suites passent, `Localization: 55 keys, all translated`, build `OK` sans avertissement. +Vérifier aussi les droits signés : `codesign -d --entitlements - build/SonyBridge.app` doit lister +`com.apple.security.network.client` et `com.apple.security.temporary-exception.apple-events`. + +- [ ] **Step 11 : Vérification avec l'utilisateur** (l'agent lance `make run`, l'utilisateur regarde) + +Lancer : `make run`. Suivre le journal : `tail -f ~/Library/Logs/SonyBridge/app.log | grep spotify`. +Demander à l'utilisateur, Spotify ouvert et en lecture avant le lancement : +1. macOS demande si « SonyBridge » peut contrôler « Spotify » → Autoriser. Attendu dans le journal : + `[spotify] playing spotify:track:… vol NN`. +2. Pause dans Spotify → `[spotify] paused spotify:track:…`. Morceau suivant → nouvel identifiant. +3. Quitter Spotify → `[spotify] not running`. Rouvrir Spotify et lancer un morceau → `playing …`. + SonyBridge ne doit **jamais** rouvrir Spotify tout seul après l'avoir quitté. +4. Menu › Options de SonyBridge › décocher « Afficher l'encoche » → `[spotify] stopped`, puis plus aucune ligne + en changeant de morceau. Recocher → une ligne `playing …`. +5. (Facultatif, par l'utilisateur) refus : `tccutil reset AppleEvents com.semvis123.SonyHeadphonesClient`, + `make run`, cliquer « Ne pas autoriser » → `[spotify] permission denied`. Réautoriser ensuite dans Réglages + Système › Confidentialité et sécurité › Automatisation › SonyBridge › Spotify. + +Note : l'autorisation peut être redemandée après chaque `make` (signature ad hoc qui change, spec §9). + +- [ ] **Step 12 : Commit (par l'utilisateur)** + +```bash +git add Client/macos && git commit -m "feat(music): local Spotify source, music controller and Show Notch option" -m "Co-Authored-By: Claude Opus 5 " +``` + +--- + +### Task 4: Panneau de l'encoche — placement, états au repos, survol + +**Files:** +- Create: `Client/macos/Notch/NotchPanel.swift`, `Client/macos/Notch/NotchView.swift`, + `Client/macos/Notch/NotchController.swift` +- Modify: `Client/macos/AppDelegate.swift`, `Client/macos/fr.lproj/Localizable.strings` + +**Interfaces:** +- Consumes : `NotchGeometry`, `ScreenMetrics`, `NotchRestingState`, `NotchTab`, `NotchContent` (tâche 1) ; + `MusicController` (`status`, `nowPlaying`, `artwork`, `hasMusic`, `notchDidOpen()`, `notchDidClose()`) (tâche 3) ; + `AppSettings.showNotch` (tâche 3) ; existant : `HeadphonesModel` (`connectionState`, `connected`, `mode`). +- Produces : + - `final class NotchViewState: ObservableObject { @Published var isOpen: Bool; @Published var resting: NotchRestingState; @Published var tab: NotchTab; @Published var restingSize: CGSize; @Published var openSize: CGSize; @Published var notchHeight: CGFloat }` + - `struct NotchView: View { init(state:model:music:selectTab:) }` avec un `tabContent` que les tâches 5 et 6 complètent + - `struct ArtworkView: View { let image: NSImage?; let size: CGFloat; let cornerRadius: CGFloat }` (réutilisée en tâche 6) + - `final class NotchController { init(model: HeadphonesModel, music: MusicController, settings: AppSettings) }` + +- [ ] **Step 1 : Écrire `Client/macos/Notch/NotchPanel.swift`** + +```swift +import AppKit +import SwiftUI + +// Borderless transparent panel above the menu bar (spec §4.3). It never becomes key or main, so the frontmost +// app keeps the keyboard; clicks still reach its controls through NotchHostingView. +final class NotchPanel: NSPanel { + // A factory rather than a custom init: NSWindow subclasses that declare their own initializer must also + // deal with NSWindow's required/unavailable initializers. + static func make() -> NotchPanel { + let panel = NotchPanel(contentRect: .zero, styleMask: [.borderless, .nonactivatingPanel], + backing: .buffered, defer: false) + panel.isOpaque = false + panel.backgroundColor = .clear + panel.hasShadow = false + panel.isMovable = false + panel.hidesOnDeactivate = false + panel.level = NSWindow.Level(rawValue: NSWindow.Level.mainMenu.rawValue + 2) + panel.collectionBehavior = [.canJoinAllSpaces, .stationary, .fullScreenAuxiliary, .ignoresCycle] + return panel + } + + override var canBecomeKey: Bool { false } + override var canBecomeMain: Bool { false } +} + +// Reports the pointer entering or leaving the panel, whichever app is active. +final class NotchContainerView: NSView { + var onHoverChange: (() -> Void)? + + override func updateTrackingAreas() { + super.updateTrackingAreas() + trackingAreas.forEach { removeTrackingArea($0) } + addTrackingArea(NSTrackingArea(rect: .zero, options: [.mouseEnteredAndExited, .activeAlways, .inVisibleRect], + owner: self, userInfo: nil)) + } + + override func mouseEntered(with event: NSEvent) { onHoverChange?() } + override func mouseExited(with event: NSEvent) { onHoverChange?() } +} + +// The panel is never key: without this, the first click would only be swallowed by the window. +final class NotchHostingView: NSHostingView { + override func acceptsFirstMouse(for event: NSEvent?) -> Bool { true } +} +``` + +- [ ] **Step 2 : Écrire `Client/macos/Notch/NotchView.swift`** + +```swift +import AppKit +import SwiftUI + +// Written by NotchController, read by NotchView. +final class NotchViewState: ObservableObject { + @Published var isOpen = false + @Published var resting: NotchRestingState = .empty + @Published var tab: NotchTab = .music + @Published var restingSize: CGSize = .zero + @Published var openSize: CGSize = .zero + @Published var notchHeight: CGFloat = 32 +} + +// Square top (it merges with the notch), rounded bottom corners. +struct NotchShape: Shape { + var bottomRadius: CGFloat + + var animatableData: CGFloat { + get { bottomRadius } + set { bottomRadius = newValue } + } + + func path(in rect: CGRect) -> Path { + let radius = min(bottomRadius, rect.width / 2, rect.height) + var path = Path() + path.move(to: CGPoint(x: rect.minX, y: rect.minY)) + path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY)) + path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - radius)) + path.addQuadCurve(to: CGPoint(x: rect.maxX - radius, y: rect.maxY), control: CGPoint(x: rect.maxX, y: rect.maxY)) + path.addLine(to: CGPoint(x: rect.minX + radius, y: rect.maxY)) + path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.maxY - radius), control: CGPoint(x: rect.minX, y: rect.maxY)) + path.closeSubpath() + return path + } +} + +// Root view of the notch panel (spec §4): the resting strip, or the open panel with its two tabs. The panel +// can be larger than the shape while it animates; the shape stays centred at the top. +struct NotchView: View { + @ObservedObject var state: NotchViewState + @ObservedObject var model: HeadphonesModel + @ObservedObject var music: MusicController + let selectTab: (NotchTab) -> Void + + var body: some View { + let size = state.isOpen ? state.openSize : state.restingSize + ZStack(alignment: .top) { + NotchShape(bottomRadius: state.isOpen ? 22 : 10).fill(Color.black) + if state.isOpen { + openContent + .padding(.top, state.notchHeight) + .transition(.opacity) + } else { + restingContent + .transition(.opacity) + } + } + .frame(width: size.width, height: size.height) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) + .environment(\.colorScheme, .dark) + } + + // MARK: - Resting (spec §4.1) + + private var restingContent: some View { + HStack(spacing: 0) { + leadingItem.frame(width: NotchGeometry.sideExtension) + Spacer(minLength: 0) + trailingItem.frame(width: NotchGeometry.sideExtension) + } + .frame(height: state.notchHeight) + } + + @ViewBuilder private var leadingItem: some View { + switch state.resting { + case .musicAndHeadphones, .musicOnly: + ArtworkView(image: music.artwork, size: 20, cornerRadius: 5) + case .headphonesOnly: + Image(systemName: "headphones").font(.system(size: 13)).foregroundColor(.white) + case .empty: + EmptyView() + } + } + + @ViewBuilder private var trailingItem: some View { + switch state.resting { + case .musicAndHeadphones, .headphonesOnly: + Image(systemName: Self.modeSymbol(model.mode)).font(.system(size: 13)).foregroundColor(.white) + case .musicOnly: + LevelBars(animating: music.nowPlaying?.isPlaying == true) + case .empty: + EmptyView() + } + } + + private static func modeSymbol(_ mode: SHCAmbientMode) -> String { + switch mode { + case .noiseCanceling: return "headphones.circle.fill" + case .ambientSound: return "ear.and.waveform" + default: return "circle.slash" + } + } + + // MARK: - Open (spec §4.2) + + private var openContent: some View { + VStack(spacing: 10) { + tabBar + tabContent.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) + } + .padding(.horizontal, 18) + .padding(.bottom, 14) + } + + private var tabBar: some View { + HStack(spacing: 18) { + tabButton(.music, title: tr("Music")) + tabButton(.headphones, title: tr("Headphones")) + } + .padding(.top, 6) + } + + private func tabButton(_ tab: NotchTab, title: String) -> some View { + let selected = state.tab == tab + return Button { selectTab(tab) } label: { + Text(title) + .font(.system(size: 12, weight: selected ? .semibold : .regular)) + .foregroundColor(selected ? .white : .gray) + .padding(.bottom, 3) + .overlay(alignment: .bottom) { + if selected { Rectangle().fill(Color.white).frame(height: 2) } + } + } + .buttonStyle(.plain) + } + + @ViewBuilder private var tabContent: some View { + switch state.tab { + case .music: Spacer() // Task 6: MusicTab + case .headphones: Spacer() // Task 5: HeadphonesTab + } + } +} + +// Album artwork, or a placeholder note while it loads (or for tracks without one). +struct ArtworkView: View { + let image: NSImage? + let size: CGFloat + let cornerRadius: CGFloat + + var body: some View { + Group { + if let image = image { + Image(nsImage: image).resizable().aspectRatio(contentMode: .fill) + } else { + ZStack { + Color(white: 0.2) + Image(systemName: "music.note").font(.system(size: size * 0.45)).foregroundColor(.gray) + } + } + } + .frame(width: size, height: size) + .clipShape(RoundedRectangle(cornerRadius: cornerRadius)) + } +} + +// Four small bars, moving while music plays (resting state 2), frozen when paused. +struct LevelBars: View { + let animating: Bool + + var body: some View { + TimelineView(.animation(minimumInterval: 1.0 / 20, paused: !animating)) { context in + let time = context.date.timeIntervalSinceReferenceDate + HStack(alignment: .bottom, spacing: 2) { + ForEach(0..<4, id: \.self) { index in + Capsule() + .fill(Color.green) + .frame(width: 3, height: animating ? 4 + 10 * abs(sin(time * 3 + Double(index) * 1.3)) : 4) + } + } + .frame(height: 14, alignment: .bottom) + } + } +} +``` + +- [ ] **Step 3 : Écrire `Client/macos/Notch/NotchController.swift`** + +```swift +import AppKit +import Combine +import SwiftUI + +// Owns the notch panel (spec §4.3): picks the screen, places and resizes the panel, opens it on hover and +// follows the "Show Notch" option. +final class NotchController { + private static let shrinkDelay: TimeInterval = 0.35 // lets the closing animation end before the panel shrinks + + private let model: HeadphonesModel + private let music: MusicController + private let settings: AppSettings + private let state = NotchViewState() + private let panel = NotchPanel.make() + private var geometry: NotchGeometry? + private var lastChosenTab: NotchTab? + private var hoverTimer: Timer? + private var shrinkWork: DispatchWorkItem? + private var cancellables = Set() + + init(model: HeadphonesModel, music: MusicController, settings: AppSettings) { + self.model = model + self.music = music + self.settings = settings + + let container = NotchContainerView() + let host = NotchHostingView(rootView: NotchView(state: state, model: model, music: music, + selectTab: { [weak self] tab in self?.select(tab) })) + host.autoresizingMask = [.width, .height] + container.addSubview(host) + container.onHoverChange = { [weak self] in self?.scheduleHoverCheck() } + panel.contentView = container + + NotificationCenter.default.publisher(for: NSApplication.didChangeScreenParametersNotification) + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in self?.relayout() } + .store(in: &cancellables) + // receive(on:) hops after @Published stored the new value, so the sinks read current state. + settings.$showNotch + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in self?.relayout() } + .store(in: &cancellables) + model.$connectionState.combineLatest(music.$status, music.$nowPlaying) + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in self?.updateResting() } + .store(in: &cancellables) + } + + // MARK: - Placement + + private func relayout() { + guard settings.showNotch, let screen = Self.preferredScreen() else { + geometry = nil + if state.isOpen { + state.isOpen = false + music.notchDidClose() + } + shrinkWork?.cancel() + panel.orderOut(nil) + return + } + let geometry = NotchGeometry(screen: ScreenMetrics(screen)) + self.geometry = geometry + state.notchHeight = geometry.notch.height + state.openSize = geometry.open.size + if state.isOpen { panel.setFrame(geometry.open, display: true) } + updateResting() + } + + // The built-in notched screen if there is one, else the primary screen (the one with the menu bar). + private static func preferredScreen() -> NSScreen? { + NSScreen.screens.first { $0.safeAreaInsets.top > 0 } ?? NSScreen.screens.first + } + + private func updateResting() { + guard let geometry = geometry else { return } + let resting = NotchContent.restingState(hasMusic: music.hasMusic, headphonesConnected: model.connected) + let frame = geometry.restingFrame(for: resting) + if state.resting != resting || (frame != nil && state.restingSize != frame?.size) { + withAnimation(animation) { + state.resting = resting + if let frame = frame { state.restingSize = frame.size } + } + } + guard !state.isOpen else { return } // close() re-applies the resting frame + if let frame = frame { + setPanelFrame(frame) + panel.orderFrontRegardless() + } else { + hidePanel(after: panel.isVisible ? Self.shrinkDelay : 0) + } + } + + // Grows at once (the shape then animates inside the larger panel) or shrinks once the animation is over, + // so the transparent panel never blocks the menu bar longer than needed. + private func setPanelFrame(_ target: CGRect) { + shrinkWork?.cancel() + let current = panel.frame + if !panel.isVisible || (target.width >= current.width && target.height >= current.height) { + panel.setFrame(target, display: true) + } else { + let work = DispatchWorkItem { [weak self] in self?.panel.setFrame(target, display: true) } + shrinkWork = work + DispatchQueue.main.asyncAfter(deadline: .now() + Self.shrinkDelay, execute: work) + } + } + + private func hidePanel(after delay: TimeInterval) { + shrinkWork?.cancel() + let work = DispatchWorkItem { [weak self] in self?.panel.orderOut(nil) } + shrinkWork = work + DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: work) + } + + // MARK: - Hover + + // Enter/exit events only schedule a check; the check reads the real pointer position, so a missed event + // can't leave the notch stuck open or closed. + private func scheduleHoverCheck() { + hoverTimer?.invalidate() + let inside = hoverZone.contains(NSEvent.mouseLocation) + let delay = inside ? NotchContent.openDelay : NotchContent.closeDelay + let timer = Timer(timeInterval: delay, repeats: false) { [weak self] _ in self?.hoverCheck() } + RunLoop.main.add(timer, forMode: .common) + hoverTimer = timer + } + + private func hoverCheck() { + let inside = panel.isVisible && hoverZone.contains(NSEvent.mouseLocation) + if inside && !state.isOpen { + open() + } else if !inside && state.isOpen { + close() + } + } + + private var hoverZone: CGRect { + guard let geometry = geometry else { return .zero } + return state.isOpen ? geometry.open : (geometry.restingFrame(for: state.resting) ?? .zero) + } + + private func open() { + guard let geometry = geometry else { return } + state.tab = NotchContent.tabOnOpen(lastChosen: lastChosenTab, hasMusic: music.hasMusic) + setPanelFrame(geometry.open) + panel.orderFrontRegardless() + withAnimation(animation) { state.isOpen = true } + music.notchDidOpen() + } + + private func close() { + withAnimation(animation) { state.isOpen = false } + music.notchDidClose() + updateResting() + } + + private func select(_ tab: NotchTab) { + lastChosenTab = tab + state.tab = tab + } + + // Spring, or a short fade-like ease when "Reduce motion" is on. + private var animation: Animation { + NSWorkspace.shared.accessibilityDisplayShouldReduceMotion + ? .easeInOut(duration: 0.15) + : .spring(response: 0.35, dampingFraction: 0.82) + } +} + +private extension ScreenMetrics { + init(_ screen: NSScreen) { + self.init(frame: screen.frame, + safeAreaTop: screen.safeAreaInsets.top, + auxiliaryTopLeft: screen.auxiliaryTopLeftArea, + auxiliaryTopRight: screen.auxiliaryTopRightArea, + menuBarHeight: screen.frame.maxY - screen.visibleFrame.maxY) + } +} +``` + +Si le SDK déclare `auxiliaryTopLeftArea` / `auxiliaryTopRightArea` comme `NSRect` non optionnel, passer +`screen.auxiliaryTopLeftArea.isEmpty ? nil : screen.auxiliaryTopLeftArea` (idem à droite). + +- [ ] **Step 4 : Créer le contrôleur** — dans `Client/macos/AppDelegate.swift`, après + `private var statusItemController: StatusItemController?` : + +```swift + private var notchController: NotchController? +``` + +et après `statusItemController = StatusItemController(model: model, settings: settings)` : + +```swift + notchController = NotchController(model: model, music: music, settings: settings) +``` + +- [ ] **Step 5 : Traductions** — ajouter à la fin de `Client/macos/fr.lproj/Localizable.strings` : + +``` + +/* Notch (Notch/*.swift) */ +"Music" = "Musique"; +"Headphones" = "Casque"; +``` + +- [ ] **Step 6 : Tests et build** + +Run : `make test && make` +Attendu : toutes les suites passent, `Localization: 57 keys, all translated`, build `OK` sans avertissement. + +- [ ] **Step 7 : Vérification avec l'utilisateur** (l'agent lance `make run`) + +Demander à l'utilisateur de regarder : +1. Casque connecté, Spotify fermé → autour de l'encoche : icône casque à gauche, icône du mode à droite (état 3). +2. Spotify en lecture → pochette à gauche, mode à droite (état 1). +3. Menu › Déconnecter → pochette + petites barres vertes qui bougent ; pause dans Spotify → barres figées (état 2). +4. Spotify quitté et casque déconnecté → encoche nue ; le survol l'ouvre quand même (état 4). +5. Survol : ouverture après un court instant, fermeture en sortant, pas de clignotement en passant vite + par-dessus ; pendant que l'encoche est ouverte, taper dans une autre app (TextEdit) : le texte va bien à + cette app. +6. Onglets : cliquer « Casque » / « Musique » ; le contenu est vide pour l'instant (normal, tâches 5 et 6) ; + après un choix, la réouverture revient sur le dernier onglet. +7. Barre des menus : encoche fermée, les menus d'app et les icônes de la barre à côté de l'encoche restent + cliquables. +8. Écran externe (ou capot fermé) : pastille noire en haut au centre de l'écran principal ; dans l'état 4, + plus de pastille. Débrancher → l'encoche revient sur l'écran intégré. +9. Options › décocher « Afficher l'encoche » → elle disparaît ; recocher → elle revient. + +- [ ] **Step 8 : Commit (par l'utilisateur)** + +```bash +git add Client/macos && git commit -m "feat(notch): notch panel with resting states and hover to open" -m "Co-Authored-By: Claude Opus 5 " +``` + +--- + +### Task 5: Onglet Casque + +**Files:** +- Create: `Client/macos/Notch/HeadphonesTab.swift` +- Modify: `Client/macos/Notch/NotchView.swift` (`tabContent`), `Client/macos/fr.lproj/Localizable.strings` + +**Interfaces:** +- Consumes : `HeadphonesModel` (`connectionState`, `mode`, `ambientLevel`, `maxAmbientLevel`, `focusOnVoice`, + `setMode(_:)`, `setLevel(_:final:)`, `setFocusOnVoice(_:)`, `connect()`) ; `NotchView.tabContent` (tâche 4). +- Produces : `struct HeadphonesTab: View { init(model: HeadphonesModel) }` + +- [ ] **Step 1 : Écrire `Client/macos/Notch/HeadphonesTab.swift`** + +```swift +import AppKit +import SwiftUI + +// Notch tab: NC / Ambient / Off, ambient level and Focus on Voice (spec §4.2). It calls the same model methods +// as the menu, so the poll guard and the send throttle apply here too, and both stay in sync. +struct HeadphonesTab: View { + @ObservedObject var model: HeadphonesModel + + var body: some View { + switch model.connectionState { + case .connected: + controls + case .connecting: + Text(tr("Connecting…")).font(.system(size: 12)).foregroundColor(.gray).padding(.top, 16) + case .disconnected: + VStack(spacing: 10) { + Text(tr("Not connected")).font(.system(size: 12)).foregroundColor(.gray) + Button(tr("Connect…")) { + NSApp.activate(ignoringOtherApps: true) // the fallback Bluetooth picker is a modal window + model.connect() + } + .controlSize(.small) + } + .padding(.top, 16) + } + } + + private var controls: some View { + let ambient = model.mode == .ambientSound + return VStack(spacing: 12) { + Picker("", selection: Binding(get: { model.mode }, set: { model.setMode($0) })) { + Text(tr("Noise Canceling")).tag(SHCAmbientMode.noiseCanceling) + Text(tr("Ambient Sound")).tag(SHCAmbientMode.ambientSound) + Text(tr("Off")).tag(SHCAmbientMode.off) + } + .pickerStyle(.segmented) + .labelsHidden() + + HStack(spacing: 8) { + Text(tr("Level")).font(.system(size: 12)) + Slider( + value: Binding(get: { Double(model.ambientLevel) }, + set: { model.setLevel(Int($0.rounded()), final: false) }), + in: 1...Double(max(model.maxAmbientLevel, 2)), + step: 1, + onEditingChanged: { editing in + if !editing { model.setLevel(model.ambientLevel, final: true) } + } + ) + .controlSize(.small) + Text(verbatim: "\(model.ambientLevel)") + .font(.system(size: 11, weight: .medium).monospacedDigit()) + .foregroundColor(.gray) + .frame(width: 20, alignment: .trailing) + } + .disabled(!ambient) + .opacity(ambient ? 1 : 0.4) + + HStack { + Text(tr("Focus on Voice")).font(.system(size: 12)) + Spacer() + Toggle("", isOn: Binding(get: { model.focusOnVoice }, set: { model.setFocusOnVoice($0) })) + .labelsHidden() + .toggleStyle(.switch) + .controlSize(.mini) + } + .disabled(!ambient) + .opacity(ambient ? 1 : 0.4) + } + } +} +``` + +- [ ] **Step 2 : Brancher l'onglet** — dans `Client/macos/Notch/NotchView.swift`, `tabContent`, remplacer la ligne + `case .headphones: Spacer() // Task 5: HeadphonesTab` par : + +```swift + case .headphones: HeadphonesTab(model: model) +``` + +- [ ] **Step 3 : Traduction** — ajouter à la fin de `Client/macos/fr.lproj/Localizable.strings` : + +``` +"Level" = "Niveau"; +``` + +- [ ] **Step 4 : Tests et build** + +Run : `make test && make` +Attendu : toutes les suites passent, `Localization: 58 keys, all translated`, build `OK` sans avertissement. + +- [ ] **Step 5 : Vérification avec l'utilisateur, sur le WH-1000XM6** (l'agent lance `make run DEBUG=1`) + +1. Onglet Casque, casque connecté : choisir Réduction de bruit / Son ambiant / Désactivé → le casque change ; le + menu (coche) et l'icône de la barre suivent. +2. Bouton NC du casque → l'encoche suit en ~2 s (ouverte ou non). +3. En Son ambiant : glisser le niveau → le casque suit sans à-coups ; « Focalisation sur la voix » bascule. + Hors Son ambiant, curseur et interrupteur sont grisés. +4. Menu › Déconnecter → l'onglet affiche « Non connecté » et « Connecter… » ; le bouton reconnecte le casque. +5. Le journal (`build/app.log`) ne montre que des trames déjà connues (`68 17`/`68 19` NC/ASM), toutes acquittées. + +- [ ] **Step 6 : Commit (par l'utilisateur)** + +```bash +git add Client/macos && git commit -m "feat(notch): headphones tab" -m "Co-Authored-By: Claude Opus 5 " +``` + +--- + +### Task 6: Onglet Musique + README + vérification finale + +**Files:** +- Create: `Client/macos/Notch/MusicTab.swift` +- Modify: `Client/macos/Notch/NotchView.swift` (`tabContent`), `Client/macos/fr.lproj/Localizable.strings`, + `README.md` + +**Interfaces:** +- Consumes : `MusicController` (`status`, `nowPlaying`, `artwork`, `playPause()`, `next()`, `previous()`, + `seek(to:final:)`, `setVolume(_:final:)`, `launchPlayer()`, `openAutomationSettings()`) (tâche 3) ; + `NowPlaying`, `PlaybackClock` (tâche 2) ; `ArtworkView`, `NotchView.tabContent` (tâche 4). +- Produces : `struct MusicTab: View { init(music: MusicController) }` + +- [ ] **Step 1 : Écrire `Client/macos/Notch/MusicTab.swift`** + +```swift +import SwiftUI + +// Notch tab: the track, its controls, Spotify's volume and the device it plays on (spec §4.2). +struct MusicTab: View { + @ObservedObject var music: MusicController + @State private var seekValue: Double? // while dragging the progress bar + @State private var volumeValue: Double? // while dragging the volume slider + + // Explicit: the private @State properties would otherwise make the memberwise init private. + init(music: MusicController) { + _music = ObservedObject(wrappedValue: music) + } + + var body: some View { + switch music.status { + case .notRunning: + message(tr("Spotify isn't open"), button: tr("Open Spotify")) { music.launchPlayer() } + case .permissionDenied: + message(tr("SonyBridge isn't allowed to control Spotify."), button: tr("Open Settings")) { + music.openAutomationSettings() + } + case .ready: + if let track = music.nowPlaying { + player(track) + } else { + message(tr("Nothing playing"), button: nil) {} + } + } + } + + private func message(_ text: String, button: String?, action: @escaping () -> Void) -> some View { + VStack(spacing: 10) { + Text(text).font(.system(size: 12)).foregroundColor(.gray).multilineTextAlignment(.center) + if let button = button { + Button(button, action: action).controlSize(.small) + } + } + .frame(maxWidth: .infinity) + .padding(.top, 16) + } + + private func player(_ track: NowPlaying) -> some View { + VStack(spacing: 8) { + HStack(spacing: 12) { + ArtworkView(image: music.artwork, size: 56, cornerRadius: 9) + VStack(alignment: .leading, spacing: 2) { + Text(track.title).font(.system(size: 13, weight: .semibold)).lineLimit(1) + Text(track.artist).font(.system(size: 11)).foregroundColor(.gray).lineLimit(1) + progress(track) + } + } + HStack(spacing: 28) { + controlButton("backward.fill", label: tr("Previous track")) { music.previous() } + controlButton(track.isPlaying ? "pause.fill" : "play.fill", size: 18, label: tr("Play or pause")) { + music.playPause() + } + controlButton("forward.fill", label: tr("Next track")) { music.next() } + } + HStack(spacing: 6) { + Image(systemName: "speaker.fill").font(.system(size: 9)).foregroundColor(.gray) + volumeSlider(track).frame(width: 110) + Image(systemName: "speaker.wave.3.fill").font(.system(size: 9)).foregroundColor(.gray) + Spacer() + Image(systemName: "hifispeaker").font(.system(size: 10)).foregroundColor(.green) + Text(track.deviceName ?? tr("This Mac")).font(.system(size: 10)).foregroundColor(.green).lineLimit(1) + } + } + } + + // Redrawn once a second, only while the notch is open (this view only exists then). + private func progress(_ track: NowPlaying) -> some View { + TimelineView(.periodic(from: .now, by: 1)) { context in + let position = seekValue ?? PlaybackClock.position(of: track, at: context.date) + VStack(spacing: 1) { + Slider( + value: Binding(get: { position }, set: { value in + seekValue = value + music.seek(to: value, final: false) + }), + in: 0...max(track.duration, 1), + onEditingChanged: { editing in + if !editing, let value = seekValue { + music.seek(to: value, final: true) + seekValue = nil + } + } + ) + .controlSize(.mini) + .disabled(!track.capabilities.canSeek || track.duration <= 0) + HStack { + Text(verbatim: PlaybackClock.format(position)) + Spacer() + Text(verbatim: "−" + PlaybackClock.format(max(0, track.duration - position))) + } + .font(.system(size: 9).monospacedDigit()) + .foregroundColor(.gray) + } + } + } + + private func volumeSlider(_ track: NowPlaying) -> some View { + Slider( + value: Binding(get: { volumeValue ?? Double(track.volume ?? 0) }, set: { value in + volumeValue = value + music.setVolume(Int(value.rounded()), final: false) + }), + in: 0...100, + onEditingChanged: { editing in + if !editing, let value = volumeValue { + music.setVolume(Int(value.rounded()), final: true) + volumeValue = nil + } + } + ) + .controlSize(.mini) + .disabled(!track.capabilities.canSetVolume || track.volume == nil) + } + + private func controlButton(_ symbol: String, size: CGFloat = 14, label: String, + action: @escaping () -> Void) -> some View { + Button(action: action) { + Image(systemName: symbol) + .font(.system(size: size)) + .foregroundColor(.white) + .frame(width: 28, height: 24) + } + .buttonStyle(.plain) + .accessibilityLabel(label) + } +} +``` + +- [ ] **Step 2 : Brancher l'onglet** — dans `Client/macos/Notch/NotchView.swift`, `tabContent`, remplacer la ligne + `case .music: Spacer() // Task 6: MusicTab` par : + +```swift + case .music: MusicTab(music: music) +``` + +- [ ] **Step 3 : Traductions** — ajouter à la fin de `Client/macos/fr.lproj/Localizable.strings` : + +``` +"Spotify isn't open" = "Spotify n’est pas ouvert"; +"Open Spotify" = "Ouvrir Spotify"; +"SonyBridge isn't allowed to control Spotify." = "SonyBridge n’a pas l’autorisation de contrôler Spotify."; +"Open Settings" = "Ouvrir les réglages"; +"Nothing playing" = "Rien en cours de lecture"; +"This Mac" = "Ce Mac"; +"Previous track" = "Morceau précédent"; +"Play or pause" = "Lecture ou pause"; +"Next track" = "Morceau suivant"; +``` + +- [ ] **Step 4 : README** — dans `README.md` : + +Après le bloc **Sound modes** (après la ligne « 🔄 **Live button sync** … »), insérer : + +```markdown + +**Notch** +- 🏝️ **Notch panel** — hover the MacBook notch (or a black pill at the top of screens without one) to control the music playing in **Spotify** (artwork, play/pause, previous/next, seek, volume) and switch Noise Cancelling / Ambient Sound / Off. Turn it off with **Show Notch** under **SonyBridge Options** +``` + +Après le paragraphe « 💡 On first launch, macOS asks for **Bluetooth permission** … », insérer : + +```markdown +> +> 🎵 With the notch on, macOS also asks whether SonyBridge may **control Spotify** — allow it to see and +> control your music from the notch (Spotify's own desktop app, no account needed). +``` + +Dans **Usage**, remplacer la ligne « - turn **Launch at Login**, **Connect Automatically**, and **Reconnect +Automatically** on or off under **SonyBridge Options**; » par : + +```markdown +- hover the **notch** to control Spotify and switch sound modes without opening the menu; +- turn **Launch at Login**, **Connect Automatically**, **Reconnect Automatically**, and **Show Notch** on or off under **SonyBridge Options**; +``` + +- [ ] **Step 5 : Tests, build et build de release** + +Run : `make test && make && make release` +Attendu : toutes les suites passent, `Localization: 67 keys, all translated`, les deux builds `OK` sans +avertissement ; `lipo -archs build/SonyBridge.app/Contents/MacOS/SonyBridge` → `x86_64 arm64`. + +- [ ] **Step 6 : Vérification finale avec l'utilisateur** (spec §8, l'agent lance `make run DEBUG=1`) + +1. Survol : ouverture, fermeture, pas de clignotement ; l'app active garde le clavier. +2. Les 4 états au repos. +3. Onglet Casque : changer de mode → le casque change, le menu et l'icône suivent ; bouton NC du casque → + l'encoche suit. +4. Onglet Musique : lecture/pause, précédent, suivant, glisser la position (le temps affiché suit, Spotify saute + au bon endroit), volume (Spotify suit) ; changer de morceau dans Spotify → l'encoche suit (titre, pochette). +5. Autorisation Spotify ; refus → message + « Ouvrir les réglages » (ouvre Automatisation). +6. Spotify fermé → « Spotify n'est pas ouvert » + « Ouvrir Spotify » ; SonyBridge ne relance jamais Spotify tout seul. +7. Écran externe, capot fermé, rebranchement : l'encoche se replace. +8. « Afficher l'encoche » décochée → plus d'encoche et plus de ligne `[spotify]` dans le journal ; recochée → elle revient. + +- [ ] **Step 7 : Commit (par l'utilisateur)** + +```bash +git add Client/macos README.md && git commit -m "feat(notch): music tab and README" -m "Co-Authored-By: Claude Opus 5 " +``` diff --git a/docs/superpowers/specs/2026-09-10-menu-bar-app-design.md b/docs/superpowers/specs/2026-09-10-menu-bar-app-design.md new file mode 100644 index 0000000..5a4b6e9 --- /dev/null +++ b/docs/superpowers/specs/2026-09-10-menu-bar-app-design.md @@ -0,0 +1,254 @@ +# SonyBridge dans la barre des menus — spec de design + +- **Date :** 2026-09-10 +- **Statut :** validé en discussion, à relire avant le plan d'implémentation +- **Casque de référence :** WH-1000XM6 (firmware 3.1.5, protocole v2) + +## 1. Objectif + +Transformer SonyBridge, aujourd'hui une app à fenêtre, en **app de barre des menus** sobre, dans l'esprit +des menus système d'Apple (Bluetooth, Wi-Fi). L'app donne accès à toutes les fonctions déjà gérées, et +corrige ce qui est faux sur le WH-1000XM6. + +## 2. Périmètre + +**Inclus** +- Toutes les fonctions existantes, dans un menu natif : mode NC / Son ambiant / Désactivé, niveau ambiant, + focalisation sur la voix, égaliseur (presets + manuel), DSEE, Speak-to-Chat, volume adaptatif, arrêt + automatique, batterie, codec, firmware. +- Les corrections XM6 : relecture de l'état NC/Ambiant, égaliseur 10 bandes. +- Trois options activables : lancer à l'ouverture de session, connexion automatique, reconnexion automatique. +- Un build par script (`make`), sans Xcode, et la CI correspondante. +- Le français et l'anglais (mécanisme de traduction existant). + +**Exclu** (projets séparés, plus tard) +- Les fonctions du XM6 encore inconnues du projet (multipoint, optimiseur NC, commandes tactiles…), qui + demandent de la rétro-ingénierie. +- L'écoute des notifications que le casque envoie de lui-même : on garde la relecture périodique. +- La mise à jour des captures d'écran du README et du site (à refaire après l'implémentation). + +## 3. Décisions + +| Sujet | Décision | Raison | +|---|---|---| +| Forme de l'interface | Menu natif (maquette « B ») | Le plus proche des menus système d'Apple | +| Égaliseur manuel | Curseurs dans le sous-menu « Égaliseur », sous les presets (option « 1 ») | Tout reste dans le menu, sans fenêtre en plus | +| Technique | `NSStatusItem` + `NSMenu` (AppKit), vues SwiftUI (`NSHostingView`) pour les lignes riches | `MenuBarExtra` n'accepte pas de curseurs en style menu ; un popover serait un faux menu | +| Icône de la barre | Monochrome, une par mode, grisée si déconnecté | Mode visible d'un coup d'œil, style système | +| Build | Script + `Makefile`, suppression du `.xcodeproj` | Pas de Xcode sur la machine de dev ; une seule façon de compiler | +| Version minimale | macOS 13 (au lieu de 11) | `SMAppService` pour le lancement à l'ouverture de session | + +## 4. Structure du menu + +``` +┌ WH-1000XM6 68 % ▭ ← en-tête (vue SwiftUI) +│ Connecté · AAC (ou « Connexion… » / « Non connecté ») +│ ⚠︎ ← seulement s'il y a une erreur +├────────── +│ Contrôle du son ambiant ← titre de section (inactif) +│ ◉ Réduction de bruit ← choix exclusifs +│ ◉ Son ambiant +│ ─────●───── 10 ← curseur 1…20 (visible en Son ambiant) +│ Focalisation sur la voix [ ] ← interrupteur (visible en Son ambiant) +│ ◉ Désactivé +├────────── +│ Égaliseur Graves › +│ ✓ Désactivé / Brillant / Dynamique / Doux / Détendu / Voix / Aigus / Graves / Parole / Manuel +│ ────────── +│ [10 curseurs verticaux] ou [5 curseurs + Clear Bass] ← actifs si « Manuel » +│ Réinitialiser +│ DSEE [ ] ← chaque ligne n'apparaît que si le casque +│ Speak-to-Chat [ ] gère la fonction +│ Volume adaptatif [ ] +│ Arrêt automatique Quand retiré › +│ ✓ Désactivé / 5 min / 30 min / 1 heure / 3 heures / Quand le casque est retiré +├────────── +│ À propos du casque › → Firmware, Codec, Protocole, Bluetooth (lignes d'info) +│ Options de SonyBridge › → ✓ Lancer à l'ouverture de session +│ ✓ Connexion automatique +│ ✓ Reconnexion automatique +│ Connecter… | Déconnecter +├────────── +└ Quitter SonyBridge ⌘Q +``` + +- La valeur courante (« Graves », « Quand retiré ») s'affiche à droite du titre du sous-menu. +- Casque déconnecté : le menu garde sa forme, les réglages sont désactivés (grisés), et l'en-tête affiche + « Non connecté ». L'élément « Connecter… » essaie d'abord le casque Sony déjà connecté à macOS + (comportement existant de `scanAndConnect`), sinon il ouvre le sélecteur Bluetooth de macOS. +- Valeurs par défaut des options : connexion auto **activée**, reconnexion auto **activée**, lancement à + l'ouverture de session **désactivé** (Apple demande que l'utilisateur l'active lui-même). + +## 5. Architecture + +### 5.1 Type d'app + +- `LSUIElement = YES` : pas d'icône dans le Dock, pas de fenêtre ni de menu d'app. +- `LSMinimumSystemVersion = 13.0`. +- Le bundle s'appelle `SonyBridge.app` (exécutable `SonyBridge`). L'identifiant + `com.semvis123.SonyHeadphonesClient` est conservé, pour que macOS ne redemande pas l'autorisation + Bluetooth. + +### 5.2 Fichiers (`Client/macos/`) + +| Fichier | Rôle | Dépend de | +|---|---|---| +| `main.swift` | Crée `NSApplication`, installe `AppDelegate`, lance la boucle | `AppDelegate` | +| `AppDelegate.swift` | Crée le modèle, les réglages et le contrôleur de barre ; démarre la connexion auto | tous les suivants | +| `StatusItemController.swift` | Possède le `NSStatusItem`, choisit l'icône selon l'état, attache le menu | `HeadphonesModel`, `HeadphonesMenu` | +| `HeadphonesMenu.swift` | Construit le `NSMenu` et le garde synchronisé avec le modèle (abonnement Combine) : états des choix, visibilité, valeurs à droite, actif/inactif | `HeadphonesModel`, `AppSettings`, `MenuRows` | +| `MenuRows/HeaderRow.swift` | En-tête : nom, état de connexion, codec, batterie (simple ou G/D/boîtier) | `HeadphonesModel` | +| `MenuRows/SliderRow.swift` | Curseur du niveau ambiant | `HeadphonesModel` | +| `MenuRows/ToggleRow.swift` | Ligne titre + interrupteur (focalisation, DSEE, Speak-to-Chat, volume adaptatif) | — (valeur + action en paramètres) | +| `MenuRows/EqualizerRow.swift` | Curseurs verticaux, 10 bandes ou 5 + Clear Bass selon le casque | `HeadphonesModel` | +| `HeadphonesModel.swift` | Existe déjà. État observable du casque et actions ; gagne la connexion/reconnexion auto et les relectures périodiques | `HeadphonesBridge`, `AppSettings`, `ReconnectPolicy`, `PollGuard` | +| `ReconnectPolicy.swift` | Logique pure : délai avant le prochain essai (3 s, 10 s, 30 s, puis 60 s) | — | +| `PollGuard.swift` | Logique pure : ignorer une relecture si l'utilisateur a changé ce réglage il y a moins de 3 s | — | +| `AppSettings.swift` | Les 3 options dans `UserDefaults` ; le lancement à l'ouverture passe par `SMAppService.mainApp` | — | +| `DeviceWatcher.swift` | Écoute les connexions Bluetooth (`IOBluetoothDevice.register(forConnectNotifications:)`) et signale qu'un casque Sony vient de se connecter | IOBluetooth | +| `HeadphonesBridge.h/.mm` | Existe déjà. Pont Obj-C++ ; s'adapte aux corrections XM6 (§7) | cœur C++ | +| `fr.lproj/`, `en.lproj/` | Traductions : textes du menu ajoutés, textes de l'ancienne fenêtre retirés | — | + +**Supprimés :** `ContentView.swift`, `main.mm`, `AppDelegate.h/.mm`, `ViewController.h/.mm`, `Main.storyboard`, +`SonyHeadphonesClient.xcodeproj`, `exportOptions.plist`, et les images des casques dans `Assets.xcassets` +(elles ne sont plus affichées). L'icône de l'app est déplacée dans `Client/macos/Resources/AppIcon.iconset`, +d'où `iconutil` la compile directement. + +### 5.3 Cœur C++ (`Client/`) + +- Nouveau `ProtocolParsers.h/.cpp` : des fonctions pures qui transforment la réponse du casque en valeurs. + - `parseNcAsmState(payload)` : gère les réponses `0x17` et `0x19`. + - `parseEqualizer(payload)` : gère 5 bandes + Clear Bass, et 10 bandes. + - `Headphones.cpp` les appelle, au lieu de décoder les octets lui-même. +- Le reste du cœur (mise en trame, ACK, connexion RFCOMM) ne change pas. + +## 6. Fonctionnement + +### 6.1 Connexion automatique (option activée) + +1. L'app retient l'adresse du dernier casque connecté (`UserDefaults`). +2. Au lancement : si ce casque est connecté à macOS, l'app ouvre le canal de contrôle. À défaut, elle prend le + premier casque connecté dont le nom ressemble à un Sony (règle existante `SHCLooksLikeSonyHeadset`). +3. Ensuite, `DeviceWatcher` signale chaque connexion Bluetooth. Pour un casque Sony, l'app attend 2 s (le + temps que l'audio s'établisse) puis ouvre le canal. + +### 6.2 Reconnexion automatique (option activée) + +- Si le canal se coupe alors que le casque est toujours connecté à macOS, l'app réessaie selon + `ReconnectPolicy` : 3 s, 10 s, 30 s, puis toutes les 60 s. +- L'app arrête d'essayer quand le casque se déconnecte de macOS (la connexion auto prendra le relais). +- Après un clic sur **Déconnecter**, pas de reconnexion auto jusqu'au prochain branchement du casque ou au + prochain clic sur « Connecter… ». + +### 6.3 Relectures périodiques + +- État NC/Ambiant : toutes les 2 s (suit le bouton physique du casque). Batterie : toutes les 60 s. +- Les minuteurs sont ajoutés en mode `RunLoop.Mode.common`, pour continuer à tourner **pendant que le menu + est ouvert**. Le menu se met alors à jour en direct. + +### 6.4 Commandes + +- Une action met à jour l'affichage tout de suite, puis la commande part sur la file série existante, dans + l'ordre des clics. +- `PollGuard` ignore les relectures d'un réglage pendant 3 s après que l'utilisateur l'a modifié : sans ça, + l'affichage reviendrait brièvement en arrière. +- Les curseurs (niveau ambiant, égaliseur) envoient une commande quand on relâche, et au plus toutes les + 150 ms pendant le glissement, pour ne pas saturer la liaison. + +### 6.5 Erreurs + +- La dernière erreur s'affiche sur une ligne « ⚠︎ message » sous l'en-tête. Elle disparaît à la prochaine + action réussie. Pas de fenêtre d'alerte. +- Les échecs de connexion automatique ne s'affichent pas (ils sont normaux quand le casque dort). Seuls les + échecs d'une action de l'utilisateur s'affichent. + +### 6.6 Icône + +- Des images modèles (*template*) monochromes, que macOS colore selon la barre (clair ou sombre) : une par + mode (réduction de bruit, son ambiant, désactivé), plus une version grisée quand le casque est déconnecté. +- On part de symboles SF (`SF Symbols`) ; les glyphes exacts sont montrés pour validation pendant + l'implémentation. + +## 7. Corrections WH-1000XM6 + +Constats tirés des trames réelles capturées le 2026-09-10 : + +| Fonction | Trame reçue | Constat | +|---|---|---| +| État NC/ASM, demande `66 17` | `67 17 00 00 00 00 00` | Tout à zéro : ce canal n'est pas celui du XM6 | +| Changement de mode `68 17 01 01 01 00 0a` | accepté, puis notification `69 19 01 01 01 00 0a 00 00` | Le changement marche ; le vrai état arrive sur le canal `0x19`, avec 2 octets de plus | +| Égaliseur, demande `56 00` | `57 00 30 0a 0a 0a 05 05 06 06 06 06 06 06` | Preset `0x30` inconnu ; `0x0a` = 10 valeurs de bandes | +| Volume adaptatif, demande `f6 0a` | aucune réponse | Pas géré : la ligne est masquée | + +**Correction de la relecture NC/Ambiant** +- À la connexion, l'app envoie `66 19`. Si la réponse fait au moins 7 octets, elle relit l'état par `0x19`. + Sinon, elle garde `0x17` (anciens modèles). +- L'envoi des changements continue par `68 17`, dont le fonctionnement est vérifié sur le XM6. + +**Correction de l'égaliseur** +- `parseEqualizer` lit l'octet de nombre de valeurs : + - `0x06` → Clear Bass + 5 bandes (existant) ; + - `0x0a` → 10 bandes, sans Clear Bass. +- Le sous-menu affiche les curseurs qui correspondent. Un preset inconnu est affiché « Personnalisé » ; aucun + preset n'est coché. + +**Points à déterminer par expérimentation** (étape 3 de la construction, avec l'utilisateur et le casque) +1. Le sens des 2 octets de plus de `0x19` : changer de mode avec le bouton du casque et lire les trames. +2. Le décalage des valeurs des bandes (hypothèse −10…+10 avec un décalage de 10, à confirmer) et les + identifiants des presets du XM6 : comparer avec l'app Sony, puis envoyer un preset et relire. +3. Le format d'envoi de l'égaliseur manuel à 10 bandes (hypothèse `58 00 a0 0a <10 valeurs>`) : essai pas à + pas, l'utilisateur à l'écoute. + +**Règle de sécurité :** tant qu'un format n'est pas confirmé, la commande correspondante n'est **jamais** +envoyée au XM6. Les curseurs 10 bandes restent inactifs, avec la mention « bientôt disponible ». + +## 8. Build et CI + +- `scripts/build.sh` : compile le Swift (`swiftc`, avec l'en-tête de pont), le C++ et l'Obj-C++ + (`clang++`, C++17, ARC), fait l'édition de liens, assemble `build/SonyBridge.app` (plist, `.lproj`, icône + via `iconutil`) et signe en ad hoc avec les entitlements existants. + - Variables : `CONFIG=debug|release` ; `ARCHS="arm64 x86_64"` pour une app universelle (fusion avec `lipo`) ; + `DEBUG_PROTOCOL=1` pour activer `SHC_DEBUG_PROTOCOL`. +- `Makefile` : + - `make` : compile ; + - `make run` : compile, relance l'app, et envoie les logs dans `build/app.log` ; + - `make test` : lance les tests ; + - `make release` : app universelle zippée ; + - `make clean`. +- CI : `.github/workflows/build.yml` (sur `main` et les PR) exécute `make test` et `make release`, puis publie + le zip comme artefact. `xcodebuild.yml` est supprimé. +- README : section « Build from source » réécrite (`make run`), description de l'app de barre des menus. + +## 9. Tests + +- **`make test`** compile et lance deux petits exécutables de test (assertions simples, sans XCTest, qui n'est + pas disponible sans Xcode) : + - `Client/tests/ProtocolParsersTests.cpp` : `parseNcAsmState` et `parseEqualizer` avec les trames réelles + du XM6 (§7) et des trames des anciens formats (`0x17`, 5 bandes + Clear Bass) ; aller-retour mise en trame + / décodage (`packageDataForBt` / `unpackBtMessage`), échappement et somme de contrôle. + - `Client/tests/LogicTests.swift` : `ReconnectPolicy` (suite des délais, remise à zéro) et `PollGuard` + (fenêtre de 3 s). +- **Checklist manuelle** avec le XM6 : chaque élément du menu, synchronisation avec le bouton physique, menu + ouvert pendant un changement, coupure pour inactivité puis reconnexion, déconnexion manuelle (pas de + reconnexion), lancement à l'ouverture de session, bascule clair/sombre de la barre, français et anglais. + +## 10. Ordre de construction + +1. **Base** : `scripts/build.sh` + `Makefile`, point d'entrée Swift, app d'agent, icône et menu minimal + (en-tête + modes + Quitter), sur le cœur existant. +2. **Menu complet** : toutes les lignes de §4, avec les fonctions actuelles ; `ContentView.swift` supprimé. +3. **Corrections XM6** : `ProtocolParsers` + tests, relecture `0x19`, égaliseur 10 bandes, puis les + expérimentations de §7. +4. **Options** : `AppSettings`, `DeviceWatcher`, connexion et reconnexion auto, lancement à l'ouverture de + session. +5. **Nettoyage** : suppression du `.xcodeproj` et des fichiers morts, CI, README, traductions. + +## 11. Risques + +| Risque | Parade | +|---|---| +| Taille et surbrillance des vues SwiftUI dans un `NSMenu` | Taille fixée par ligne ; vérifié dès l'étape 1 avec le curseur | +| Minuteurs gelés pendant l'ouverture du menu | Mode `RunLoop.Mode.common` (§6.3) | +| La connexion bloque le fil principal quelques secondes (boucle d'attente existante dans `HeadphonesBridge`) | Acceptable en arrière-plan ; l'en-tête affiche « Connexion… » | +| Formats XM6 non confirmés | Règle de sécurité §7 ; fonctions désactivées tant qu'elles ne sont pas vérifiées | +| Autorisation Bluetooth redemandée | Identifiant de bundle conservé | diff --git a/docs/superpowers/specs/2026-09-11-notch-design.md b/docs/superpowers/specs/2026-09-11-notch-design.md new file mode 100644 index 0000000..7745858 --- /dev/null +++ b/docs/superpowers/specs/2026-09-11-notch-design.md @@ -0,0 +1,300 @@ +# SonyBridge dans l'encoche — spec de design (étape 1) + +- **Date :** 2026-09-11 +- **Statut :** validé en discussion, à relire avant le plan d'implémentation +- **Casque de référence :** WH-1000XM6 (protocole v2) +- **Découpage :** étape 1 (cette spec) = encoche + onglet Casque + Spotify local ; étape 2 (spec séparée, plus + tard) = connexion Spotify (SSO) + source Web + changement d'appareil. + +## 1. Objectif + +Ajouter à SonyBridge une **encoche interactive** en haut de l'écran, dans l'esprit de « Dynamic Island » : +au repos, elle montre discrètement la musique en cours et le mode du casque ; au survol, elle s'ouvre et +permet de piloter la musique (Spotify) et le mode du casque sans ouvrir le menu. + +Le menu de la barre des menus reste l'interface complète ; l'encoche est un accès rapide. + +## 2. Périmètre + +**Inclus (étape 1)** +- L'encoche (panneau au-dessus de la barre des menus), sur l'écran intégré à encoche, ou une pastille + simulée sur un écran sans encoche. +- Onglet **Musique** : pochette, titre, artiste, barre de progression avec temps écoulé et restant (on peut + la glisser pour avancer), précédent / lecture-pause / suivant, volume Spotify, appareil (« Ce Mac »). +- Onglet **Casque** : NC / Ambiant / Off, curseur de niveau ambiant, Focus voix. +- La source **Spotify local** : l'app Spotify du Mac, lue et pilotée sans compte. +- L'option « Afficher l'encoche » dans les options de SonyBridge. +- Le français et l'anglais (mécanisme `tr()` existant). + +**Exclu de l'étape 1** +- Connexion au compte Spotify (SSO), source Web, changement d'appareil Spotify Connect → étape 2 (§10). +- « J'aime » (ajout aux Titres likés) : non retenu. +- Autres lecteurs (Apple Music, navigateurs…) : l'API privée d'Apple (MediaRemote) est verrouillée depuis + macOS 15.4, trop fragile. +- Batterie et égaliseur dans l'encoche : restent dans le menu. + +## 3. Décisions + +| Sujet | Décision | Raison | +|---|---|---| +| Licence | Implémentation originale à partir de la documentation Apple ; aucun code ni visuel copié de boring.notch (GPL-3.0) | SonyBridge reste sous licence MIT ; l'idée d'une encoche n'est pas protégée, le code l'est | +| Disposition ouverte | Onglets **Musique \| Casque** (maquette « B ») | Encoche compacte | +| Ouverture | Au survol, fermeture quand la souris sort | Rapide, comme boring.notch | +| Écran sans encoche | Pastille simulée en haut au centre de l'écran principal | Même comportement partout | +| Source musique | Spotify local (AppleScript + signaux Spotify) à l'étape 1 ; Spotify Web (SSO) à l'étape 2, avec repli local | Utilisable par tous sans compte développeur ; le SSO n'est possible qu'avec un Client ID par utilisateur (§10) | +| Extras Musique | Volume, avancer dans le morceau ; changer d'appareil à l'étape 2 | Choix de l'utilisateur | +| Réglages casque dans l'encoche | Mode NC/Ambiant/Off, niveau ambiant + Focus voix | Choix de l'utilisateur ; le reste est dans le menu | +| Technique | `NSPanel` sans bordure, non activant, contenu SwiftUI (`NSHostingView`) | Pas de vol du focus clavier ; SwiftUI déjà utilisé pour les lignes du menu | + +## 4. L'encoche + +### 4.1 États au repos + +« Musique présente » = Spotify est ouvert **et** son état est lecture ou pause avec un morceau courant. +« Casque connecté » = `HeadphonesModel.connectionState == .connected` (« Connexion… » compte comme non connecté). + +| # | Musique | Casque | Au repos | +|---|---|---|---| +| 1 | oui | oui | Pochette à gauche, mode du casque à droite (◉ NC, ◎ Ambiant, ○ Off) | +| 2 | oui | non | Pochette à gauche, petites barres à droite, animées en lecture, figées en pause | +| 3 | non | oui | Icône casque à gauche, mode à droite | +| 4 | non | non | Encoche nue, sans extension. Sur un écran **sans** encoche, la pastille simulée est masquée | + +Dans les états 1 à 3, l'encoche s'élargit d'environ 36 pt de chaque côté pour loger ces éléments. +Le survol ouvre l'encoche dans tous les états où elle est visible, y compris l'état 4 sur un écran à encoche. + +### 4.2 État ouvert + +``` +╭──────────────────────────────────╮ Onglet Musique +│ Musique Casque │ +│ ┌────┐ Midnight City │ +│ │ ♪ │ M83 │ +│ └────┘ ━━━━━━━●────── 1:32 −2:31│ ← barre de progression (glissable) +│ ⏮ ⏸ ⏭ │ +│ 🔈 ───────●──── 🔊 │ ← volume Spotify +│ 🔊 Ce Mac │ ← appareil +╰──────────────────────────────────╯ + +╭──────────────────────────────────╮ Onglet Casque +│ Musique Casque │ +│ [ NC | Ambiant | Off ] │ ← choix exclusifs +│ Niveau ─────●───── 12 │ ← grisé hors mode Ambiant +│ Focus voix [ ● ] │ ← grisé hors mode Ambiant +╰──────────────────────────────────╯ +``` + +- Taille ouverte fixe (environ 380 × 190 pt, encoche comprise, à ajuster à la vérification visuelle), la même pour les deux + onglets : pas de saut de taille en changeant d'onglet. +- Coins inférieurs arrondis ; le haut se confond avec l'encoche. +- **Casque non connecté** : « Non connecté » + bouton « Connecter », qui appelle `HeadphonesModel.connect()` + (même comportement que « Connecter… » dans le menu). Pendant la connexion : « Connexion… ». +- **Spotify non ouvert** : « Spotify n'est pas ouvert » + bouton « Ouvrir Spotify » (lance l'app). +- **Autorisation refusée** : « SonyBridge n'a pas l'autorisation de contrôler Spotify » + bouton + « Ouvrir les réglages » (Réglages Système › Confidentialité et sécurité › Automatisation). +- **Spotify ouvert mais rien en cours** (état stopped) : « Rien en cours de lecture ». +- Le curseur de niveau va de 1 à `maxAmbientLevel` (20, ou 19 sur les anciens modèles), comme dans le menu. + +### 4.3 Comportement + +- **Ouverture** après ~0,15 s de survol ; **fermeture** ~0,4 s après la sortie de la souris. Ces délais sont + des constantes, testées dans la logique pure (§8). +- **Animation** : ouverture et fermeture en ressort, à partir de la forme de l'encoche ; fondu simple si + « Réduire les animations » est activé (`NSWorkspace.shared.accessibilityDisplayShouldReduceMotion`). +- **Focus** : le panneau ne devient jamais la fenêtre active (non activant) ; les clics y fonctionnent + sans voler le clavier à l'app courante. +- **Zone de clic** : repliée, la fenêtre fait exactement la taille de l'encoche (élargie ou non) ; elle ne + prend la taille ouverte que pendant l'ouverture. Elle ne bloque donc jamais la barre des menus en dehors + de l'encoche. +- **Onglet à l'ouverture** : au premier survol de la session, Musique si une musique est présente, sinon + Casque ; ensuite le dernier onglet choisi (en mémoire seulement, pas enregistré). +- **Écrans** : l'écran intégré à encoche s'il existe, sinon l'écran principal avec la pastille simulée. + L'encoche se replace à chaque changement d'écrans (`NSApplication.didChangeScreenParametersNotification`) : + écran branché/débranché, capot fermé, résolution changée. +- **Bureaux et plein écran** : visible sur tous les bureaux et par-dessus les apps en plein écran. +- **Option** « Afficher l'encoche » décochée : le panneau est retiré ; aucune lecture Spotify n'est faite. +- **Synchronisation** avec le menu : les deux lisent le même `HeadphonesModel` ; un changement de mode dans + l'encoche apparaît aussitôt dans le menu et l'icône, et inversement. + +## 5. Architecture + +### 5.1 Fichiers (`Client/macos/`) + +Nouveaux dossiers `Notch/` et `Music/`. Les fichiers marqués **pur** n'importent que Foundation : ils sont +compilés dans `LogicTests`. + +| Fichier | Rôle | Dépend de | +|---|---|---| +| `Notch/NotchGeometry.swift` | **Pur.** À partir du cadre de l'écran, de `safeAreaInsets.top` et des zones `auxiliaryTopLeftArea` / `auxiliaryTopRightArea` (passés en valeurs), calcule le rectangle de l'encoche, sa version élargie, le rectangle ouvert, ou la pastille simulée | — | +| `Notch/NotchContent.swift` | **Pur.** Choisit l'état au repos (§4.1) à partir de « musique présente » et « casque connecté », et l'onglet à l'ouverture ; contient les délais d'ouverture/fermeture | — | +| `Notch/NotchPanel.swift` | `NSPanel` sans bordure, transparent, non activant, niveau au-dessus de la barre des menus, présent sur tous les bureaux et en plein écran | AppKit | +| `Notch/NotchController.swift` | Possède le panneau ; choisit l'écran ; suit les changements d'écrans ; gère le survol (zone de suivi + délais) et la taille du panneau ; suit `AppSettings.showNotch` | `NotchPanel`, `NotchGeometry`, `NotchContent`, `HeadphonesModel`, `MusicController`, `AppSettings` | +| `Notch/NotchView.swift` | Vue SwiftUI racine : état au repos, état ouvert avec les onglets | `MusicTab`, `HeadphonesTab` | +| `Notch/MusicTab.swift` | Onglet Musique (§4.2) | `MusicController` | +| `Notch/HeadphonesTab.swift` | Onglet Casque (§4.2) ; appelle `setMode` / `setLevel(_:final:)` / `setFocusOnVoice` / `connect` du modèle | `HeadphonesModel` | +| `Music/NowPlaying.swift` | **Pur.** Structure : titre, artiste, album, identifiant du morceau, URL de la pochette, durée, position + date de cette position, lecture/pause, volume, nom de l'appareil, capacités (`canSeek`, `canSetVolume`, `canChangeDevice`) | — | +| `Music/PlaybackClock.swift` | **Pur.** Position affichée à un instant donné : avance pendant la lecture, figée en pause, bornée à la durée | `NowPlaying` | +| `Music/SpotifyPlaybackInfo.swift` | **Pur.** Transforme le `userInfo` du signal Spotify en `NowPlaying` (durée en ms → s, champs manquants, état « Stopped ») | `NowPlaying` | +| `Music/MusicSource.swift` | Protocole commun : état publié (`NowPlaying?` + état de la source : non ouvert / autorisation refusée / prêt), `playPause`, `next`, `previous`, `seek(to:)`, `setVolume(_:)`, `refresh()` | `NowPlaying` | +| `Music/SpotifyLocalSource.swift` | Implémentation locale (§6) | `MusicSource`, `SpotifyPlaybackInfo`, AppKit | +| `Music/MusicController.swift` | `ObservableObject` lu par l'encoche : expose l'état de la source active, la pochette téléchargée, et relaie les commandes (avec `SendThrottle` pour le volume et la position). Étape 1 : une seule source, la locale | `MusicSource`, `SendThrottle` | + +**Fichiers modifiés** +- `AppSettings.swift` : `showNotch` (`UserDefaults`, **activé** par défaut). +- `AppDelegate.swift` : crée `MusicController` et `NotchController`. +- `HeadphonesMenu.swift` : case « Afficher l'encoche » dans « Options de SonyBridge ». +- `scripts/build.sh` : ajoute `Notch/*.swift` et `Music/*.swift` aux sources Swift. +- `scripts/test.sh` : compile les fichiers purs avec `LogicTests`. +- `Client/tests/LogicTests/main.swift` : nouveaux tests (§8). +- `fr.lproj/Localizable.strings` : nouveaux textes. +- `SonyHeadphonesClient.entitlements` et `info.plist` (§5.2). + +### 5.2 Bac à sable et autorisations + +- `com.apple.security.temporary-exception.apple-events` = `["com.spotify.client"]` : envoyer des Apple Events + à Spotify depuis l'app en bac à sable. (Si le runtime renforcé est activé un jour, il faudra aussi + `com.apple.security.automation.apple-events`.) +- `com.apple.security.network.client` : télécharger la pochette (et, à l'étape 2, parler à l'API Spotify). +- `info.plist` : `NSAppleEventsUsageDescription`, texte affiché par macOS à la première demande. + +### 5.3 Flux de données + +``` +Spotify (app du Mac) ──signal PlaybackStateChanged──▶ SpotifyLocalSource ──NowPlaying──▶ MusicController ──▶ NotchView + ▲ │ │ + └──────────── Apple Events (lecture, volume…) ◀───┴──────────── commandes ◀───────────┘ + +HeadphonesModel (existant) ◀──── setMode / setLevel / setFocusOnVoice ──── HeadphonesTab + └──────── @Published mode, niveau, voix, connexion ──────────▶ NotchView + menu +``` + +## 6. Source Spotify locale + +### 6.1 Lecture de l'état + +- **Signal** `com.spotify.client.PlaybackStateChanged` (`DistributedNotificationCenter`) : Spotify l'émet à + chaque changement de morceau, lecture ou pause. Si le signal contient ses informations (`userInfo` : + titre, artiste, album, durée, position, état), `SpotifyPlaybackInfo` les décode ; sinon (par exemple si le + bac à sable les retire), le signal sert seulement de déclencheur et on relit l'état par Apple Events. +- **Relecture par Apple Events** (`player state`, `current track` : nom, artiste, album, id, durée, + `artwork url` ; `player position` ; `sound volume`) : + - au lancement de SonyBridge si Spotify est déjà ouvert ; + - quand Spotify s'ouvre (`NSWorkspace.didLaunchApplicationNotification`) ; + - toutes les 5 s **uniquement quand l'encoche est ouverte** (le volume ne déclenche pas de signal) ; + - juste après une commande de position ou de volume. +- **Position** : `PlaybackClock` calcule la position affichée à partir de la dernière position connue et de + l'heure ; l'interface se redessine environ une fois par seconde **seulement quand l'encoche est ouverte**. +- **Pochette** : téléchargée depuis `artwork url` (`URLSession`), gardée en mémoire pour les derniers morceaux. +- Spotify quitte (`NSWorkspace.didTerminateApplicationNotification`) → état « non ouvert », `NowPlaying` vidé. + +### 6.2 Commandes + +- `playpause`, `next track`, `previous track`, `set player position`, `set sound volume` (volume de Spotify, + 0–100, pas celui du Mac). +- Volume et position : la valeur affichée change tout de suite ; l'envoi passe par `SendThrottle` + (au plus une commande par 150 ms pendant qu'on glisse, la valeur finale toujours envoyée). +- Les Apple Events partent d'une file série en arrière-plan, avec un délai maximal de 2 s : l'interface ne se + fige jamais si Spotify ne répond pas. + +### 6.3 Protections et erreurs + +- **Aucun Apple Event n'est envoyé si Spotify n'est pas ouvert** (vérifié avec + `NSRunningApplication.runningApplications(withBundleIdentifier: "com.spotify.client")`) : un Apple Event + vers une app fermée la lancerait. Seul le bouton « Ouvrir Spotify » lance l'app. +- **Autorisation** : la première commande ou relecture déclenche la demande de macOS. Si elle est refusée + (`errAEEventNotPermitted`, -1743), la source passe à l'état « autorisation refusée » (§4.2) et arrête ses + relectures ; elle réessaie une seule fois à chaque ouverture de l'encoche (macOS ne redemande pas, l'échec + est immédiat), pour voir si l'autorisation a été accordée entre-temps dans les réglages. +- **Échec ou délai dépassé** : on garde le dernier état connu et on relit au prochain signal ; aucune + alerte, les erreurs sont seulement écrites dans le journal (stderr). + +## 7. Réglages et traductions + +- « Options de SonyBridge » gagne une case **Afficher l'encoche** (activée par défaut). +- Tous les nouveaux textes passent par `tr()` et ont leur traduction dans `fr.lproj/Localizable.strings` ; + `make test` le vérifie (`check_localization.py` parcourt déjà tous les `.swift` sous `Client/macos/`). + +## 8. Tests + +**Automatiques** (ajoutés à `LogicTests`, lancés par `make test`) +- `NotchGeometry` : écran avec encoche → rectangle de l'encoche, version élargie et rectangle ouvert centrés + sous le haut de l'écran ; écran sans encoche → pastille centrée ; cas limites (zones auxiliaires absentes, + écran décalé dans l'espace global). +- `NotchContent` : les 4 états au repos ; onglet à l'ouverture (premier survol puis dernier onglet) ; délais. +- `PlaybackClock` : avance en lecture, figée en pause, bornée à la durée, remise à zéro au changement de morceau. +- `SpotifyPlaybackInfo` : décodage complet, champs manquants, durée en ms, état « Stopped » → pas de musique. + +**Manuels** (par l'utilisateur, sur son Mac et son WH-1000XM6) +1. Survol : ouverture, fermeture, pas de clignotement ; l'app active garde le clavier. +2. Les 4 états au repos. +3. Onglet Casque : changer de mode → le casque change, le menu et l'icône suivent ; bouton NC du casque → + l'encoche suit. +4. Onglet Musique : lecture/pause, suivant, précédent, glisser la position, volume ; changer de morceau dans + Spotify → l'encoche suit. +5. Demande d'autorisation Spotify ; refus → message et bouton des réglages. +6. Spotify fermé → message et bouton « Ouvrir Spotify » ; SonyBridge ne relance jamais Spotify tout seul. +7. Écran externe, capot fermé, rebranchement : l'encoche se replace (pastille simulée sur l'écran externe). +8. Option « Afficher l'encoche » décochée → plus d'encoche ; recochée → elle revient. + +## 9. Risques + +- **Autorisation redemandée après chaque `make`** : macOS rattache l'autorisation d'automatisation à la + signature de l'app, qui change à chaque build ad hoc. Gênant en développement, pas pour l'app installée. +- **API Spotify locale non documentée** : le signal et le dictionnaire AppleScript de Spotify n'ont pas de + garantie officielle (stables depuis des années). En cas de casse, seul l'onglet Musique local est touché. +- **`userInfo` du signal en bac à sable** : non garanti ; le design relit l'état par Apple Events si besoin (§6.1). +- **Extension au repos** : les ~36 pt de chaque côté de l'encoche peuvent recouvrir un élément de la barre + des menus collé à l'encoche ; à vérifier visuellement, largeur ajustable. +- **Pastille simulée** : elle recouvre le centre de la barre des menus sur un écran sans encoche (zone + habituellement vide) ; masquée quand il n'y a rien à afficher. + +## 10. Étape 2 (aperçu, spec séparée) + +Connexion au compte Spotify (Authorization Code + PKCE, sans secret ; jetons dans le Trousseau), source +`SpotifyWebSource` (`/me/player`, interrogé pendant la lecture), changement d'appareil (Spotify Connect), +fenêtre « Spotify… » pour saisir le Client ID. `MusicController` choisira la source Web si l'utilisateur est +connecté, sinon la locale. + +Contraintes Spotify vérifiées le 2026-09-11 : +- une app en mode développement accepte **5 utilisateurs** au plus, ajoutés à la main, et son propriétaire + doit avoir **Premium** (depuis février 2026) ; +- le quota étendu est réservé aux entreprises (≥ 250 000 utilisateurs actifs par mois) depuis mai 2025 ; +- les commandes de lecture restent disponibles en mode développement ; +- adresse de retour : `http://127.0.0.1:` ou un schéma personnalisé (`localhost` refusé). + +Conséquence : pour un repo public, **chaque utilisateur crée sa propre app développeur Spotify** et colle son +Client ID dans SonyBridge ; sans cela, l'encoche reste sur la source locale. + +Sources : [quotas Spotify](https://developer.spotify.com/documentation/web-api/concepts/quota-modes), +[migration février 2026](https://developer.spotify.com/documentation/web-api/tutorials/february-2026-migration-guide), +[adresses de retour](https://developer.spotify.com/documentation/web-api/concepts/redirect_uri). + +## 11. Ordre de construction (indicatif, le plan fait foi) + +1. Logique pure + tests (`NotchGeometry`, `NotchContent`, `NowPlaying`, `PlaybackClock`, `SpotifyPlaybackInfo`). +2. Panneau + contrôleur : l'encoche apparaît au bon endroit, s'ouvre et se ferme au survol, suit les écrans. +3. Onglet Casque branché sur `HeadphonesModel` + option « Afficher l'encoche ». +4. Source Spotify locale + `MusicController` + onglet Musique + autorisations. +5. États au repos complets, animations, vérification visuelle et matérielle. + +## 12. Changements pendant l'implémentation (2026-09-17) + +Décidés avec l'utilisateur sur l'app en marche ; ils remplacent §4.2 et une partie de §4.3. + +- **Plus d'onglets.** L'encoche ouverte est un lecteur façon « Dynamic Island » (maquette fournie par + l'utilisateur) : pochette, titre, artiste et petites barres à la couleur de la pochette ; temps écoulé, barre + plate, durée totale ; boutons 🎧 ⏮ ⏯ ⏭ 🔀 🔊. 🎧 fait glisser le lecteur vers le panneau Casque (‹ retour) ; + 🔊 remplace la progression par la barre de volume Spotify, repliée après 4 s sans action. Le lecteur + s'ouvre sur la page choisie en dernier (première ouverture : Musique s'il y a une musique, sinon Casque). +- **Lecture aléatoire** : ajoutée puis retirée (le bouton décentrait lecture/pause). « J'aime » n'existe pas + en local (étape 2). +- **Taille ouverte 300 × 166 pt** ; coins du haut évasés vers la barre des menus. +- **Aucun contrôle AppKit dans l'encoche** (sélecteur segmenté, `Slider`, `Toggle`, bouton bordé) : ils + ignorent l'échelle et le découpage SwiftUI et débordaient à l'ouverture, au changement de page et à la + fermeture. Remplacés par `ModePicker`, `FlatSlider`, `NotchSwitch`, `NotchPillButton`. +- **Fenêtre de taille fixe** : le panneau garde la taille ouverte, seule la forme s'anime ; fermé, il laisse + passer les clics (`ignoresMouseEvents`) et le survol suit la position du pointeur (moniteurs d'événements + global et local). Redimensionner la fenêtre affichait une image de contenu décalé. +- **Animations** (`NotchMotion`) : le contenu grandit et rétrécit avec la forme (même ressort, sans flou) ; + il reste monté pendant la fermeture puis est retiré ; la bande du repos a une largeur fixe et revient en + fondu. Vérifié par captures d'écran à 60/120 images par seconde. diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..119115e --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,67 @@ +#!/bin/bash +# Builds build/SonyNotch.app with the Command Line Tools only (no Xcode needed). +# CONFIG=debug|release (default: debug) +# ARCHS="arm64 x86_64" (default: this Mac's architecture; several = universal binary via lipo) +# DEBUG_PROTOCOL=1 (hex-dumps every frame exchanged with the headphones to stderr) +set -euo pipefail +shopt -s nullglob + +ROOT=$(cd "$(dirname "$0")/.." && pwd) +CORE=$ROOT/Client +MAC=$CORE/macos +OUT=$ROOT/build +APP=$OUT/SonyNotch.app +SDK=$(xcrun --show-sdk-path) +CONFIG=${CONFIG:-debug} +ARCHS=${ARCHS:-$(uname -m)} +MIN_MACOS=13.0 + +if [ "$CONFIG" = release ]; then SWIFT_OPT="-O"; CXX_OPT="-O2"; else SWIFT_OPT="-Onone -g"; CXX_OPT="-O0 -g"; fi +SWIFT_DEFINES=""; CXX_DEFINES="" +if [ "${DEBUG_PROTOCOL:-0}" = 1 ]; then SWIFT_DEFINES="-D DEBUG_PROTOCOL"; CXX_DEFINES="-DSHC_DEBUG_PROTOCOL"; fi + +SWIFT_SOURCES=("$MAC"/*.swift "$MAC"/MenuRows/*.swift "$MAC"/Notch/*.swift "$MAC"/Music/*.swift) +CXX_SOURCES=("$CORE"/*.cpp) +OBJCXX_SOURCES=("$MAC"/*.mm) + +rm -rf "$APP" +mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Resources" +BINARIES="" + +for ARCH in $ARCHS; do + OBJ=$OUT/obj/$CONFIG-$ARCH + rm -rf "$OBJ"; mkdir -p "$OBJ" + TARGET=$ARCH-apple-macos$MIN_MACOS + CXXFLAGS="-target $TARGET -isysroot $SDK -std=c++17 $CXX_OPT $CXX_DEFINES -I $CORE -I $MAC" + + echo "== [$ARCH] Swift" + swiftc -target "$TARGET" -sdk "$SDK" -swift-version 5 $SWIFT_OPT $SWIFT_DEFINES -wmo -parse-as-library \ + -module-name SonyNotch \ + -import-objc-header "$MAC/SonyHeadphonesClient-Bridging-Header.h" -I "$MAC" -I "$CORE" \ + -c "${SWIFT_SOURCES[@]}" -o "$OBJ/swift.o" + + echo "== [$ARCH] C++" + for f in "${CXX_SOURCES[@]}"; do clang++ $CXXFLAGS -c "$f" -o "$OBJ/$(basename "$f" .cpp).o"; done + + echo "== [$ARCH] Obj-C++" + for f in "${OBJCXX_SOURCES[@]}"; do + clang++ $CXXFLAGS -fobjc-arc -fmodules -fcxx-modules -c "$f" -o "$OBJ/$(basename "$f" .mm).o" + done + + echo "== [$ARCH] Link" + swiftc -target "$TARGET" -sdk "$SDK" "$OBJ"/*.o -o "$OBJ/SonyNotch" -lc++ \ + -framework AppKit -framework SwiftUI -framework Combine -framework IOBluetooth \ + -framework IOBluetoothUI -framework ServiceManagement + BINARIES="$BINARIES $OBJ/SonyNotch" +done + +lipo -create $BINARIES -output "$APP/Contents/MacOS/SonyNotch" + +echo "== Resources" +cp "$MAC/info.plist" "$APP/Contents/Info.plist" +cp -R "$MAC"/*.lproj "$APP/Contents/Resources/" +iconutil -c icns "$MAC/Resources/AppIcon.iconset" -o "$APP/Contents/Resources/AppIcon.icns" + +echo "== Sign (ad-hoc)" +codesign --force --sign - --entitlements "$MAC/SonyHeadphonesClient.entitlements" "$APP" +echo "OK -> $APP" diff --git a/scripts/check_localization.py b/scripts/check_localization.py new file mode 100755 index 0000000..7631cb5 --- /dev/null +++ b/scripts/check_localization.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +"""Every tr("…") / NSLocalizedString("…") key must have a French translation, and every French key must be used.""" +import json +import pathlib +import re +import subprocess +import sys + +ROOT = pathlib.Path(__file__).resolve().parent.parent +MAC = ROOT / "Client" / "macos" +STRINGS = MAC / "fr.lproj" / "Localizable.strings" +LITERAL = r'"((?:[^"\\]|\\.)*)"' +PATTERNS = [re.compile(r"\btr\(" + LITERAL + r"\)"), re.compile(r"NSLocalizedString\(@?" + LITERAL)] + +def unescape_source_literal(key): + r"""Unescape source string literals: \n → newline, \t → tab, and any other \X → X.""" + def replace_escape(match): + char = match.group(1) + escapes = {'n': '\n', 't': '\t', 'r': '\r', '"': '"', '\\': '\\'} + return escapes.get(char, char) + return re.sub(r"\\(.)", replace_escape, key) + +french = set(json.loads(subprocess.check_output(["plutil", "-convert", "json", "-o", "-", str(STRINGS)]))) +used = set() +for path in sorted(MAC.rglob("*.swift")) + sorted(MAC.rglob("*.mm")): + text = path.read_text(encoding="utf-8") + for pattern in PATTERNS: + used.update(unescape_source_literal(key) for key in pattern.findall(text)) + +missing = sorted(used - french) +unused = sorted(french - used) +for key in missing: + print(f"missing French translation: {key!r}") +for key in unused: + print(f"unused French key: {key!r}") +if missing or unused: + sys.exit(1) +print(f"Localization: {len(used)} keys, all translated") diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 0000000..580f7ab --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Builds and runs the unit test executables (plain asserts, no XCTest), then checks the translations. +set -euo pipefail + +ROOT=$(cd "$(dirname "$0")/.." && pwd) +MAC=$ROOT/Client/macos +OUT=$ROOT/build/tests +SDK=$(xcrun --show-sdk-path) +TARGET=$(uname -m)-apple-macos13.0 +mkdir -p "$OUT" + +echo "== LogicTests" +swiftc -target "$TARGET" -sdk "$SDK" -swift-version 5 \ + "$ROOT/Client/tests/LogicTests/main.swift" \ + "$MAC/ReconnectPolicy.swift" "$MAC/PollGuard.swift" "$MAC/SendThrottle.swift" \ + "$MAC/Notch/NotchGeometry.swift" "$MAC/Notch/NotchContent.swift" \ + "$MAC/Music/NowPlaying.swift" "$MAC/Music/PlaybackClock.swift" "$MAC/Music/SpotifyPlaybackInfo.swift" \ + -o "$OUT/LogicTests" +"$OUT/LogicTests" + +echo "== ProtocolParsersTests" +clang++ -target "$TARGET" -isysroot "$SDK" -std=c++17 -I "$ROOT/Client" \ + "$ROOT/Client/tests/ProtocolParsersTests.cpp" "$ROOT/Client/ProtocolParsers.cpp" \ + "$ROOT/Client/CommandSerializer.cpp" "$ROOT/Client/ByteMagic.cpp" \ + -o "$OUT/ProtocolParsersTests" +"$OUT/ProtocolParsersTests" + +echo "== BluetoothWrapperTests" +clang++ -target "$TARGET" -isysroot "$SDK" -std=c++17 -I "$ROOT/Client" \ + "$ROOT/Client/tests/BluetoothWrapperTests.cpp" "$ROOT/Client/BluetoothWrapper.cpp" \ + "$ROOT/Client/CommandSerializer.cpp" "$ROOT/Client/ByteMagic.cpp" \ + -o "$OUT/BluetoothWrapperTests" +"$OUT/BluetoothWrapperTests" + +echo "== HeadphonesTests" +clang++ -target "$TARGET" -isysroot "$SDK" -std=c++17 -I "$ROOT/Client" \ + "$ROOT/Client/tests/HeadphonesTests.cpp" "$ROOT/Client/Headphones.cpp" "$ROOT/Client/ProtocolParsers.cpp" \ + "$ROOT/Client/BluetoothWrapper.cpp" "$ROOT/Client/CommandSerializer.cpp" "$ROOT/Client/ByteMagic.cpp" \ + -o "$OUT/HeadphonesTests" +"$OUT/HeadphonesTests" + +echo "== Localization" +python3 "$ROOT/scripts/check_localization.py"