first working

This commit is contained in:
Harvey Fong 2025-07-26 13:01:31 -06:00
parent a7046c07c5
commit a0ce0d5115
5 changed files with 1227 additions and 1 deletions

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2025 oomer
Copyright (c) 2025 Harvey Fong
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:

152
Makefile Normal file
View File

@ -0,0 +1,152 @@
# Project configuration
EXECUTABLE_NAME = poomer-discord
PLATFORM = $(shell uname)
BUILD_TYPE ?= release# Default to release build if not specified
# Version configuration (can be overridden)
DPP_VERSION ?= $(shell find ../DPP/build/library -name "libdpp.so.*.*.*" -type f | head -1 | sed 's/.*libdpp\.so\.//')
DPP_VERSION := $(or $(DPP_VERSION),10.1.4)# Fallback version if auto-detection fails
# Common paths
DPP_PATH = ../DPP
OBJ_DIR = obj/$(PLATFORM)/$(BUILD_TYPE)
BIN_DIR = bin/$(PLATFORM)/$(BUILD_TYPE)
OUTPUT_FILE = $(BIN_DIR)/$(EXECUTABLE_NAME)
# Platform-specific configuration
ifeq ($(PLATFORM), Darwin)
# macOS configuration
SDK_LIB_EXT = dylib
DPP_LIB_NAME = libdpp.$(SDK_LIB_EXT)
MACOS_SDK_PATH = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
# Compiler settings
CC = clang
CXX = clang++
# Architecture flags
ARCH_FLAGS = -arch arm64 -mmacosx-version-min=11.0 -isysroot $(MACOS_SDK_PATH)
# Linking flags - Use multiple rpath entries to look in executable directory
LINKER_FLAGS = $(ARCH_FLAGS) -framework Cocoa -framework IOKit -fvisibility=hidden -O5 \
-rpath @executable_path \
-rpath .
else
# Linux configuration
SDK_LIB_EXT = so
DPP_LIB_NAME = libdpp.$(SDK_LIB_EXT)
# Compiler settings
CC = gcc
CXX = g++
# Architecture flags
ARCH_FLAGS = -m64 -D_FILE_OFFSET_BITS=64
# Linking flags
LINKER_FLAGS = $(ARCH_FLAGS) -fvisibility=hidden -O3 -Wl,-rpath,'$$ORIGIN' -Wl,-rpath,'$$ORIGIN/lib'
endif
# Common include and library paths
INCLUDE_PATHS = -I$(DPP_PATH)/include
DPP_BUILD_DIR = $(DPP_PATH)/build/library
# Platform-specific versioned library filename
ifeq ($(PLATFORM), Darwin)
DPP_VERSIONED_FILE = libdpp.$(DPP_VERSION).$(SDK_LIB_EXT)
else
DPP_VERSIONED_FILE = libdpp.$(SDK_LIB_EXT).$(DPP_VERSION)
endif
# Library flags
LIB_PATHS = -L$(DPP_BUILD_DIR)
LIBRARIES = -ldpp
# Build type specific flags
ifeq ($(BUILD_TYPE), debug)
CPP_DEFINES = -D_DEBUG -DDL_USE_SHARED
COMMON_FLAGS = $(ARCH_FLAGS) -fvisibility=hidden -g -O0 $(INCLUDE_PATHS)
else
CPP_DEFINES = -DNDEBUG=1 -DDL_USE_SHARED
COMMON_FLAGS = $(ARCH_FLAGS) -fvisibility=hidden -O3 $(INCLUDE_PATHS)
endif
# Language-specific flags
C_FLAGS = $(COMMON_FLAGS) -std=c17
CXX_FLAGS = $(COMMON_FLAGS) -std=c++17 -Wno-deprecated-declarations
# Objects
OBJECTS = $(EXECUTABLE_NAME).o
OBJECT_FILES = $(patsubst %,$(OBJ_DIR)/%,$(OBJECTS))
# Build rules
$(OBJ_DIR)/$(EXECUTABLE_NAME).o: $(EXECUTABLE_NAME).cpp
@mkdir -p $(@D)
$(CXX) -c -o $@ $< $(CXX_FLAGS) $(CPP_DEFINES)
$(OUTPUT_FILE): $(OBJECT_FILES)
@mkdir -p $(@D)
$(CXX) -o $@ $(OBJECT_FILES) $(LINKER_FLAGS) $(LIB_PATHS) $(LIBRARIES)
@echo "Copying libraries to $(BIN_DIR)..."
ifeq ($(PLATFORM), Darwin)
@# macOS: Handle versioned libraries (same as Linux)
@if [ -f $(DPP_BUILD_DIR)/$(DPP_VERSIONED_FILE) ]; then \
cp $(DPP_BUILD_DIR)/$(DPP_VERSIONED_FILE) $(BIN_DIR)/$(DPP_VERSIONED_FILE); \
ln -sf $(DPP_VERSIONED_FILE) $(BIN_DIR)/$(DPP_LIB_NAME); \
else \
cp $(DPP_BUILD_DIR)/$(DPP_LIB_NAME) $(BIN_DIR)/$(DPP_LIB_NAME); \
fi
else
@# Linux: Handle versioned libraries (follow standard convention)
@if [ -f $(DPP_BUILD_DIR)/$(DPP_VERSIONED_FILE) ]; then \
cp $(DPP_BUILD_DIR)/$(DPP_VERSIONED_FILE) $(BIN_DIR)/$(DPP_VERSIONED_FILE); \
ln -sf $(DPP_VERSIONED_FILE) $(BIN_DIR)/$(DPP_LIB_NAME); \
else \
cp $(DPP_BUILD_DIR)/$(DPP_LIB_NAME) $(BIN_DIR)/$(DPP_LIB_NAME); \
fi
endif
@echo "Build complete: $(OUTPUT_FILE)"
# Boilerplate for makefile
.PHONY: clean cleanall all info
# Add default target
all: $(OUTPUT_FILE)
info:
@echo "Build Configuration:"
@echo " Platform: $(PLATFORM)"
@echo " Build Type: $(BUILD_TYPE)"
@echo " DPP Version (detected): $(DPP_VERSION)"
@echo " DPP Versioned File: $(DPP_VERSIONED_FILE)"
@echo " SDK Library Extension: $(SDK_LIB_EXT)"
@echo " Output File: $(OUTPUT_FILE)"
clean:
rm -f $(OBJ_DIR)/$(EXECUTABLE_NAME).o
rm -f $(OUTPUT_FILE)
rm -f $(BIN_DIR)/$(DPP_LIB_NAME)
rm -f $(BIN_DIR)/$(DPP_VERSIONED_FILE)
rm -f $(BIN_DIR)/*.$(SDK_LIB_EXT)
rmdir $(OBJ_DIR) 2>/dev/null || true
rmdir $(BIN_DIR) 2>/dev/null || true
cleanall:
rm -f obj/*/release/*.o
rm -f obj/*/debug/*.o
rm -f bin/*/release/$(EXECUTABLE_NAME)
rm -f bin/*/debug/$(EXECUTABLE_NAME)
rm -f bin/*/release/$(DPP_LIB_NAME)
rm -f bin/*/debug/$(DPP_LIB_NAME)
rm -f bin/*/release/$(DPP_VERSIONED_FILE)
rm -f bin/*/debug/$(DPP_VERSIONED_FILE)
rm -f bin/*/release/*.$(SDK_LIB_EXT)
rm -f bin/*/debug/*.$(SDK_LIB_EXT)
rmdir obj/*/release 2>/dev/null || true
rmdir obj/*/debug 2>/dev/null || true
rmdir bin/*/release 2>/dev/null || true
rmdir bin/*/debug 2>/dev/null || true
rmdir obj/* 2>/dev/null || true
rmdir bin/* 2>/dev/null || true
rmdir obj 2>/dev/null || true
rmdir bin 2>/dev/null || true

View File

@ -1,2 +1,67 @@
# poomer-discord
### Overview
Prototype C++ Discord bot, that supports 2 features
- listens for /oomer command and replies, then 5 seconds later it sends a jpeg
- When one or more jpegs are dropped into a channel, it will read the jpeg, flip it vertically and send it back to the channel
- In both cases it will use @{user} in the reponse to notify the submitter
----
### Technical details
- Uses DPP c++ lib for Discord comms
- depends on openssl and zlib
- non blocking multi-threaded, so it can listen for other users sending /oomer command while spawning one or more threads to deal with jpeg replies
- jpeg image is stored as byte data in embedded_image.h to avoid an on disk jpeg.
## Build
### Ubuntu 24.04 LTS
```
sudo apt update
sudo apt upgrade -y
sudo apt install build-essential curl git cmake zlib1g-dev libssl-dev -y
mkdir workdir
cd workdir
git clone https://github.com/brainboxdotcc/DPP.git
cd DPP
cmake -B ./build
cmake --build ./build -j8
cd ..
git clone https://git.indoodle.com/oomer/poomer-discord.git
cd poomer-discord
curl -LO https://raw.githubusercontent.com/nothings/stb/master/stb_image.h
curl -LO https://raw.githubusercontent.com/nothings/stb/master/stb_image_write.h
make all -j4
```
### MacOS
```
mkdir workdir
cd workdir
mkdir homebrew
curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip-components 1 -C homebrew
eval "$(homebrew/bin/brew shellenv)"
brew update --force --quiet
brew install openssl
git clone https://github.com/brainboxdotcc/DPP.git
cd DPP
/Applications/CMake.app/Contents/bin/cmake -B ./build \
-DOPENSSL_ROOT_DIR=../homebrew/opt/openssl@3 \
-DOPENSSL_INCLUDE_DIR=../homebrew/opt/openssl@3/include \
-DOPENSSL_CRYPTO_LIBRARY=../homebrew/opt/openssl@3/lib/libcrypto.a \
-DOPENSSL_SSL_LIBRARY=../homebrew/opt/openssl@3/lib/libssl.a
/Applications/CMake.app/Contents/bin/cmake --build ./build -j8
cd ..
git clone https://git.indoodle.com/oomer/poomer-discord.git
cd poomer-discord
curl -LO https://raw.githubusercontent.com/nothings/stb/master/stb_image.h
curl -LO https://raw.githubusercontent.com/nothings/stb/master/stb_image_write.h
make all -j4
```

581
embedded_image.h Normal file
View File

@ -0,0 +1,581 @@
#ifndef OOMERBOT_JPEG_H
#define OOMERBOT_JPEG_H
// Auto-generated header file containing embedded oomerbot.jpeg
// Generated from: oomerbot.jpeg
// Size: 6777 bytes
#include <cstddef>
const unsigned char oomerbot_jpeg_data[] = {
0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
0x01, 0x00, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xe1, 0x00, 0xb8,
0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00,
0x00, 0x08, 0x00, 0x05, 0x01, 0x1a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x4a, 0x01, 0x1b, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x52, 0x01, 0x31, 0x00, 0x02, 0x00, 0x00, 0x00, 0x18,
0x00, 0x00, 0x00, 0x5a, 0x01, 0x32, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14,
0x00, 0x00, 0x00, 0x72, 0x87, 0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01,
0x46, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x4d, 0x65, 0x61, 0x74, 0x20,
0x41, 0x63, 0x6f, 0x72, 0x6e, 0x20, 0x38, 0x2e, 0x31, 0x2e, 0x31, 0x00,
0x32, 0x30, 0x32, 0x35, 0x3a, 0x30, 0x37, 0x3a, 0x32, 0x36, 0x20, 0x30,
0x39, 0x3a, 0x34, 0x32, 0x3a, 0x31, 0x35, 0x00, 0x00, 0x03, 0xa0, 0x01,
0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02,
0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xa0, 0x03,
0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xc0, 0x00, 0x11, 0x08, 0x01, 0x00, 0x01, 0x00, 0x03,
0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00,
0x1f, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0xff, 0xc4, 0x00, 0xb5, 0x10, 0x00,
0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00,
0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21,
0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81,
0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24,
0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56,
0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86,
0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3,
0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1,
0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc4, 0x00,
0x1f, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0xff, 0xc4, 0x00, 0xb5, 0x11, 0x00,
0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00,
0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31,
0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08,
0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15,
0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18,
0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39,
0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55,
0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84,
0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4,
0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xdb, 0x00,
0x43, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x22, 0x14, 0x14, 0x22,
0x30, 0x22, 0x22, 0x22, 0x30, 0x40, 0x30, 0x30, 0x30, 0x30, 0x40, 0x51,
0x40, 0x40, 0x40, 0x40, 0x40, 0x51, 0x62, 0x51, 0x51, 0x51, 0x51, 0x51,
0x51, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x76, 0x76, 0x76,
0x76, 0x76, 0x76, 0x89, 0x89, 0x89, 0x89, 0x89, 0x9a, 0x9a, 0x9a, 0x9a,
0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x18,
0x19, 0x19, 0x27, 0x24, 0x27, 0x43, 0x24, 0x24, 0x43, 0xa1, 0x6d, 0x5a,
0x6d, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
0xa1, 0xa1, 0xa1, 0xff, 0xdd, 0x00, 0x04, 0x00, 0x10, 0xff, 0xda, 0x00,
0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0xec,
0xe8, 0xa2, 0x8a, 0x00, 0x28, 0xa2, 0x8a, 0x00, 0x28, 0xa2, 0x8a, 0x00,
0x28, 0xa2, 0x92, 0x80, 0x16, 0x8a, 0xc8, 0xb9, 0xd6, 0x2d, 0x60, 0x25,
0x23, 0xfd, 0xe3, 0x0f, 0x4e, 0x9f, 0x9d, 0x73, 0xf7, 0x3a, 0xad, 0xe5,
0xc7, 0xca, 0x1b, 0x62, 0xfa, 0x2f, 0x1f, 0xad, 0x03, 0x51, 0x67, 0x57,
0x71, 0x7f, 0x6b, 0x6d, 0xc4, 0xaf, 0xf3, 0x7f, 0x74, 0x72, 0x6b, 0x1a,
0x5d, 0x7c, 0xe4, 0x88, 0x62, 0xfc, 0x58, 0xff, 0x00, 0x41, 0x5c, 0xe7,
0xd6, 0x93, 0x14, 0x16, 0xa2, 0x8d, 0x49, 0x75, 0x8b, 0xf9, 0x3a, 0x30,
0x41, 0xfe, 0xc8, 0xaa, 0x0f, 0x3c, 0xf2, 0xf3, 0x23, 0xb3, 0x7d, 0x4d,
0x47, 0x45, 0x3b, 0x0e, 0xc2, 0x73, 0x47, 0x5e, 0xb4, 0xbd, 0xe8, 0xa0,
0x62, 0x62, 0x8c, 0x9a, 0x5e, 0xd4, 0x62, 0x80, 0x25, 0x4b, 0x8b, 0x88,
0xbf, 0xd5, 0xbb, 0x2f, 0xd0, 0xe2, 0xaf, 0x47, 0xac, 0x5f, 0xc7, 0xd5,
0x83, 0x0f, 0x71, 0x59, 0x94, 0x1f, 0x6a, 0x05, 0x63, 0xa3, 0x8f, 0x5f,
0xc7, 0xfa, 0xe8, 0xff, 0x00, 0x15, 0x3f, 0xd0, 0xd6, 0xc5, 0xb5, 0xfd,
0xad, 0xd0, 0xfd, 0xd3, 0x8c, 0xff, 0x00, 0x74, 0xf0, 0x6b, 0x83, 0x22,
0x8c, 0x77, 0x1c, 0x52, 0x13, 0x8a, 0x3d, 0x26, 0x8a, 0xe2, 0x2d, 0xf5,
0x6b, 0xcb, 0x7c, 0x02, 0xde, 0x62, 0xfa, 0x37, 0xf8, 0xd6, 0xfd, 0xae,
0xb3, 0x6b, 0x70, 0x42, 0x3e, 0x63, 0x63, 0xeb, 0xd3, 0xf3, 0xa0, 0x87,
0x16, 0x6c, 0x51, 0x49, 0x4b, 0x40, 0x82, 0x8a, 0x28, 0xa0, 0x02, 0x8a,
0x28, 0xa0, 0x02, 0x8a, 0x28, 0xa0, 0x0f, 0xff, 0xd0, 0xec, 0xe8, 0xa2,
0x8a, 0x00, 0x28, 0xa2, 0x8a, 0x00, 0x28, 0xa2, 0xb2, 0xb5, 0x1d, 0x49,
0x6c, 0xd7, 0x64, 0x78, 0x69, 0x0f, 0x6e, 0xc3, 0xeb, 0x40, 0x17, 0x6e,
0x2e, 0x61, 0xb5, 0x4f, 0x32, 0x66, 0xc0, 0xfd, 0x4f, 0xd2, 0xb9, 0x3b,
0xed, 0x56, 0x7b, 0xbc, 0xc7, 0x1f, 0xc9, 0x1f, 0xa7, 0x73, 0xf5, 0xac,
0xe9, 0x66, 0x96, 0xe1, 0xfc, 0xc9, 0x98, 0xb1, 0xa6, 0x50, 0x68, 0xa2,
0x37, 0xa1, 0xa7, 0x52, 0x1a, 0x75, 0x32, 0x84, 0x3d, 0x29, 0x68, 0xa5,
0xa6, 0x02, 0x63, 0xd2, 0x8e, 0xd4, 0xe0, 0xa4, 0xf4, 0x14, 0xef, 0x25,
0xc0, 0xdd, 0x8a, 0x76, 0x60, 0x46, 0x69, 0x71, 0x53, 0xf9, 0x04, 0xae,
0x73, 0x40, 0x87, 0xe4, 0xdd, 0x9e, 0xd9, 0xa7, 0xca, 0xc0, 0xaf, 0xd4,
0xe2, 0x97, 0x15, 0x3a, 0xdb, 0xfc, 0xbb, 0x89, 0xc6, 0x79, 0xa6, 0xac,
0x05, 0xf9, 0xcf, 0x1f, 0xce, 0x8e, 0x56, 0x04, 0x1d, 0x7a, 0x52, 0xe2,
0xac, 0x1b, 0x76, 0x1d, 0x0d, 0x31, 0xa3, 0x75, 0xea, 0x29, 0x72, 0xb0,
0x21, 0x34, 0x53, 0x98, 0x11, 0xd6, 0x8a, 0x40, 0x36, 0x90, 0x75, 0xc8,
0xa5, 0x34, 0x01, 0xc5, 0x20, 0x35, 0x6c, 0xb5, 0x69, 0xad, 0x48, 0x49,
0x3e, 0x78, 0xfd, 0x3b, 0x8f, 0xa5, 0x75, 0x76, 0xf7, 0x30, 0xdd, 0x27,
0x99, 0x0b, 0x64, 0x7e, 0xa3, 0xeb, 0x5e, 0x7f, 0x52, 0xc3, 0x3c, 0xb6,
0xef, 0xe6, 0x44, 0xc5, 0x4f, 0xb5, 0x04, 0xb8, 0x9e, 0x87, 0x45, 0x64,
0xe9, 0xda, 0x9a, 0x5e, 0x0d, 0x92, 0x61, 0x64, 0x1d, 0xbb, 0x1f, 0xa5,
0x6b, 0x52, 0x33, 0xb0, 0x51, 0x45, 0x14, 0x00, 0x51, 0x45, 0x14, 0x01,
0xff, 0xd1, 0xec, 0xe8, 0xa2, 0x8a, 0x00, 0x28, 0xa2, 0xb2, 0xb5, 0x2d,
0x44, 0x59, 0xa6, 0xc4, 0xe6, 0x46, 0x1c, 0x7b, 0x0f, 0x5a, 0x00, 0x6e,
0xa5, 0xa9, 0x2d, 0x9a, 0xf9, 0x71, 0xf3, 0x29, 0xfd, 0x3d, 0xcd, 0x71,
0xec, 0xcd, 0x23, 0x16, 0x72, 0x49, 0x3c, 0x92, 0x68, 0x66, 0x69, 0x18,
0xbb, 0x9c, 0x93, 0xc9, 0x26, 0x92, 0x99, 0xaa, 0x56, 0x1a, 0x38, 0xa7,
0x8a, 0x4a, 0x00, 0x27, 0xa5, 0x03, 0x03, 0x4e, 0x55, 0x2c, 0x76, 0x81,
0x9a, 0x98, 0x44, 0x0c, 0x65, 0xf3, 0x9a, 0x99, 0x70, 0xae, 0x08, 0xe8,
0xc2, 0xad, 0x43, 0xb8, 0x58, 0x85, 0x60, 0x62, 0xf8, 0x6e, 0x38, 0xcd,
0x59, 0x11, 0x22, 0xf6, 0xa5, 0x5c, 0xef, 0x63, 0xf4, 0x15, 0x26, 0x4d,
0x6d, 0x18, 0xa4, 0x31, 0xb8, 0x03, 0xa5, 0x38, 0xf4, 0x14, 0x66, 0x91,
0x9d, 0x17, 0xef, 0x55, 0x0c, 0x84, 0xe6, 0x33, 0x9f, 0xe1, 0x3f, 0xa5,
0x33, 0x23, 0x60, 0x43, 0xd3, 0x3c, 0xfd, 0x05, 0x2b, 0x4e, 0x39, 0x0a,
0xa4, 0xfd, 0x6a, 0x0c, 0x3c, 0x44, 0x3b, 0x2e, 0x73, 0xfa, 0x56, 0x4d,
0xf6, 0x11, 0x6f, 0x05, 0xce, 0x5b, 0x81, 0xd8, 0x53, 0xea, 0x21, 0x3a,
0xb1, 0xf9, 0x81, 0x15, 0x28, 0x2a, 0xdf, 0x74, 0x83, 0x5a, 0x26, 0xba,
0x00, 0xb4, 0x1e, 0xb4, 0xe0, 0x0e, 0x69, 0x08, 0x35, 0x43, 0x21, 0x94,
0x0d, 0x87, 0xf0, 0xa4, 0x68, 0x50, 0xf3, 0xd2, 0x9d, 0x28, 0xf9, 0x0d,
0x23, 0xe5, 0x88, 0x8c, 0x77, 0xeb, 0xf4, 0xa8, 0x68, 0x45, 0x22, 0x8d,
0xc1, 0xf5, 0xa6, 0xe2, 0xaf, 0x28, 0xcb, 0x93, 0xd8, 0x70, 0x29, 0xae,
0x04, 0x87, 0x6a, 0x8f, 0xa9, 0xf4, 0xac, 0x9c, 0x02, 0xc5, 0x2a, 0x4c,
0x67, 0x9a, 0x99, 0xa2, 0x3c, 0xec, 0xe4, 0x0e, 0xa6, 0xa3, 0xa8, 0x68,
0x42, 0x2b, 0x32, 0x36, 0xe4, 0x38, 0x20, 0xe4, 0x57, 0x61, 0xa6, 0x6a,
0x6b, 0x76, 0xbe, 0x54, 0xbc, 0x4a, 0x3f, 0x5a, 0xe3, 0xbb, 0xd3, 0x95,
0x99, 0x18, 0x3a, 0x9c, 0x11, 0xc8, 0x22, 0xa4, 0x4d, 0x5c, 0xf4, 0x7a,
0x2b, 0x27, 0x4c, 0xd4, 0x45, 0xe2, 0x18, 0xdf, 0xfd, 0x62, 0x8e, 0x7d,
0xc7, 0xad, 0x6b, 0x50, 0x64, 0x14, 0x51, 0x45, 0x00, 0x7f, 0xff, 0xd2,
0xec, 0xe8, 0xa2, 0x92, 0x80, 0x21, 0xb9, 0xb8, 0x4b, 0x58, 0x5a, 0x69,
0x3a, 0x0f, 0xd4, 0xd7, 0x07, 0x3c, 0xef, 0x73, 0x2b, 0x4b, 0x21, 0xe5,
0x8d, 0x68, 0x6a, 0xd7, 0xbf, 0x6a, 0x9b, 0xcb, 0x8c, 0xfe, 0xed, 0x3a,
0x7b, 0x9f, 0x5a, 0xca, 0xa6, 0x69, 0x14, 0x27, 0x4a, 0x5c, 0xd2, 0xf6,
0xa9, 0x62, 0x45, 0x63, 0x89, 0x3f, 0x0a, 0x69, 0x14, 0x30, 0x46, 0xc4,
0x6e, 0xec, 0x2a, 0xd6, 0xc1, 0x18, 0x12, 0x2f, 0xe3, 0x4e, 0xe6, 0x3e,
0x0f, 0x2b, 0xfa, 0xd4, 0x7e, 0x72, 0xac, 0x65, 0x07, 0x24, 0x70, 0x3e,
0x95, 0xaa, 0x49, 0x0c, 0x73, 0x61, 0x46, 0xf5, 0xe8, 0x7a, 0x8a, 0x68,
0x60, 0x62, 0x0c, 0x3a, 0xad, 0x53, 0xe4, 0xd1, 0x8c, 0x54, 0x73, 0x8a,
0xe6, 0x8a, 0xb2, 0x84, 0xdc, 0x4e, 0x32, 0x49, 0xa3, 0xcc, 0x2d, 0xf7,
0x14, 0x9f, 0x7e, 0x95, 0x5e, 0x06, 0x41, 0xc3, 0x8f, 0xa1, 0xab, 0x1b,
0x9d, 0xff, 0x00, 0xd5, 0x8c, 0x0f, 0x53, 0x5a, 0xa9, 0x5d, 0x0c, 0x46,
0xc8, 0xfb, 0xed, 0x8f, 0x61, 0x49, 0xb3, 0x3c, 0xe3, 0x68, 0xfd, 0x6a,
0x55, 0x40, 0xa7, 0x3d, 0x4f, 0xa9, 0xa6, 0xb7, 0xef, 0x18, 0x8f, 0xe1,
0x1d, 0x7d, 0xe9, 0xd8, 0x06, 0xa2, 0x86, 0x39, 0x03, 0x0a, 0x3a, 0x7b,
0xfb, 0xd4, 0xac, 0xa1, 0xc6, 0xd3, 0x4b, 0x4a, 0x3a, 0xd3, 0x48, 0x65,
0x5d, 0xbd, 0x78, 0xce, 0x3a, 0x8f, 0xea, 0x28, 0x0a, 0x18, 0x65, 0x7e,
0x61, 0xe8, 0x7a, 0xfe, 0x75, 0x2b, 0x82, 0x0f, 0x98, 0xbd, 0x47, 0x5f,
0x71, 0x48, 0x54, 0x37, 0xce, 0x9c, 0x1a, 0x9b, 0x08, 0x45, 0x3c, 0xe0,
0x31, 0x53, 0xe8, 0xd4, 0xed, 0xd2, 0x2f, 0x51, 0x9f, 0xa5, 0x00, 0xab,
0xe5, 0x5c, 0x72, 0x29, 0x8c, 0x1a, 0x21, 0xb8, 0x1c, 0x81, 0xd8, 0xd3,
0xd8, 0x05, 0x92, 0x55, 0x28, 0x46, 0x70, 0x7d, 0x0d, 0x08, 0xe0, 0x2b,
0x48, 0xc4, 0x64, 0xd5, 0x39, 0x24, 0x79, 0x0f, 0x3d, 0x3d, 0x2a, 0x3c,
0x56, 0x4e, 0xa6, 0xa1, 0x72, 0xf2, 0x6e, 0x75, 0x0a, 0x38, 0x1d, 0xcf,
0x73, 0x4e, 0x24, 0x1f, 0xdd, 0xa0, 0xc7, 0xa9, 0xaa, 0xab, 0x33, 0xaa,
0xed, 0x1c, 0xff, 0x00, 0x4a, 0xb4, 0x8c, 0x80, 0x6d, 0xe8, 0x7d, 0xea,
0xe2, 0xd3, 0x02, 0x60, 0x15, 0x57, 0x00, 0x71, 0x50, 0x49, 0x0a, 0xb7,
0x2b, 0xc1, 0xa9, 0xfb, 0x52, 0x55, 0xb4, 0x9e, 0x83, 0x33, 0x59, 0x4a,
0xb6, 0x0d, 0x34, 0xd5, 0xe9, 0x14, 0x12, 0xb9, 0xf5, 0xaa, 0x92, 0x21,
0x56, 0xdb, 0x58, 0x4a, 0x36, 0x24, 0x58, 0x26, 0x92, 0xda, 0x55, 0x9a,
0x3e, 0xab, 0x5d, 0xe5, 0xb5, 0xc2, 0x5d, 0x42, 0xb3, 0x47, 0xd0, 0xfe,
0x86, 0xbc, 0xfe, 0xb5, 0x34, 0xab, 0xef, 0xb2, 0x4f, 0xe5, 0xc8, 0x7f,
0x76, 0xfc, 0x1f, 0x63, 0xeb, 0x59, 0x93, 0x24, 0x76, 0x94, 0x52, 0x52,
0xd0, 0x66, 0x7f, 0xff, 0xd3, 0xec, 0xeb, 0x23, 0x58, 0xba, 0x36, 0xf6,
0xbb, 0x10, 0xe1, 0xa4, 0x38, 0x1f, 0x4e, 0xf5, 0xaf, 0x5c, 0x4e, 0xad,
0x73, 0xf6, 0x9b, 0xc2, 0x17, 0xee, 0xc7, 0xf2, 0x8f, 0xeb, 0x40, 0xe2,
0xb5, 0x33, 0x32, 0x73, 0xcd, 0x2d, 0x18, 0xa9, 0x63, 0x8d, 0x8f, 0xcc,
0x06, 0x40, 0xaa, 0x4a, 0xe6, 0xa2, 0xc6, 0x17, 0x39, 0x7e, 0x2a, 0xd1,
0x09, 0x20, 0xc0, 0x3f, 0x95, 0x39, 0x4a, 0xb2, 0x8c, 0x52, 0x14, 0x43,
0xd4, 0x0a, 0xdd, 0x46, 0xc8, 0x62, 0x2b, 0x10, 0x76, 0x3f, 0x5f, 0x5f,
0x5a, 0xa4, 0xe7, 0x73, 0x12, 0x3b, 0xd5, 0x99, 0x63, 0x50, 0x84, 0x8c,
0xf1, 0x4d, 0x85, 0x01, 0x62, 0xc7, 0xb7, 0x4a, 0x99, 0x26, 0xf4, 0x01,
0x63, 0xb7, 0x07, 0x96, 0xa5, 0x68, 0x10, 0xf4, 0xe2, 0xac, 0x81, 0x49,
0xb4, 0xd5, 0xf2, 0x2b, 0x05, 0x8c, 0xd2, 0xa5, 0x5b, 0x69, 0xad, 0x14,
0x6d, 0xca, 0x08, 0xa8, 0xa6, 0x42, 0x57, 0x38, 0xe4, 0x54, 0x71, 0x49,
0x80, 0x54, 0x75, 0x3d, 0x2a, 0x17, 0xba, 0xec, 0x05, 0x82, 0xc5, 0x9b,
0xcb, 0x53, 0xf5, 0x3e, 0x95, 0x20, 0xc2, 0x8c, 0x0e, 0x82, 0x9b, 0x1a,
0x85, 0xe0, 0x52, 0xd6, 0xab, 0xb8, 0xc5, 0xcf, 0xb5, 0x28, 0x23, 0xd2,
0x9b, 0x4a, 0x3b, 0xd3, 0x00, 0xe2, 0xa2, 0x18, 0x46, 0xdb, 0xfc, 0x27,
0xa7, 0xd6, 0xa4, 0xa4, 0x65, 0x0c, 0x30, 0x69, 0x30, 0x15, 0xa3, 0x57,
0x1c, 0xf5, 0xec, 0x6a, 0x8c, 0xcc, 0xe0, 0xec, 0x63, 0x9c, 0x55, 0xc4,
0x6c, 0xa9, 0x0d, 0xd4, 0x75, 0xaa, 0x2d, 0xf3, 0xc9, 0x81, 0xdc, 0xd6,
0x75, 0x36, 0xd0, 0x4c, 0x48, 0xe3, 0x67, 0xfa, 0x55, 0x93, 0x6e, 0x95,
0x32, 0x20, 0x50, 0x00, 0xa7, 0x90, 0x49, 0xa7, 0x1a, 0x6a, 0xc1, 0x63,
0x3d, 0xe2, 0x29, 0xf3, 0x0e, 0x45, 0x58, 0x88, 0x87, 0x5d, 0xad, 0xce,
0x3f, 0x95, 0x4a, 0xcb, 0x91, 0x83, 0x54, 0xc0, 0x28, 0xf8, 0xce, 0x39,
0xc6, 0x7d, 0xaa, 0x6d, 0xca, 0xc0, 0xb4, 0x63, 0xc7, 0xdc, 0x24, 0x7f,
0x2a, 0x4c, 0xc8, 0xbf, 0x78, 0x67, 0xdc, 0x53, 0x0e, 0xd3, 0xd1, 0x99,
0xbe, 0x94, 0x14, 0x62, 0x39, 0xf9, 0x47, 0xd4, 0x9a, 0xaf, 0x40, 0x07,
0x75, 0x2b, 0x9c, 0xf4, 0x20, 0xd2, 0x12, 0x84, 0x12, 0xe7, 0x93, 0x4d,
0x58, 0x51, 0xce, 0x79, 0xc7, 0xf3, 0xa7, 0x22, 0x15, 0x1f, 0x2f, 0x24,
0x70, 0x41, 0xa9, 0xd5, 0xee, 0x05, 0x46, 0x18, 0x3c, 0x74, 0xa6, 0x11,
0x9a, 0xd0, 0x3b, 0x1c, 0x6d, 0x6e, 0x0f, 0xa1, 0xaa, 0x6e, 0x85, 0x1b,
0x06, 0xb3, 0x94, 0x6c, 0x23, 0xb0, 0xd1, 0xee, 0x4c, 0xf6, 0xa1, 0x18,
0xe5, 0xa3, 0xe3, 0xf0, 0xed, 0x5a, 0xd5, 0xc4, 0xe9, 0x37, 0x3f, 0x67,
0xbc, 0x50, 0xdf, 0x75, 0xfe, 0x53, 0xf8, 0xf4, 0xae, 0xda, 0xa0, 0xca,
0x4b, 0x53, 0xff, 0xd4, 0xe9, 0xef, 0xae, 0x05, 0xad, 0xab, 0xcd, 0xdf,
0x18, 0x1f, 0x53, 0x5c, 0x17, 0x27, 0x93, 0xd4, 0xd7, 0x49, 0xaf, 0xc9,
0x9f, 0x2e, 0x1c, 0xfa, 0xb1, 0x1f, 0xa0, 0xae, 0x6c, 0x0a, 0x0d, 0x22,
0x87, 0xa2, 0x96, 0x60, 0x05, 0x68, 0x28, 0xda, 0x30, 0x2a, 0x08, 0xe2,
0x2a, 0x32, 0x0e, 0x09, 0xa9, 0x36, 0xc9, 0xfd, 0xef, 0xd2, 0xb7, 0x82,
0xb1, 0x68, 0x7b, 0xa6, 0x4e, 0xe1, 0xc1, 0xf5, 0xa4, 0x12, 0x15, 0xe2,
0x41, 0xf8, 0xf6, 0xa0, 0x89, 0x73, 0xf7, 0x87, 0xe5, 0x49, 0x89, 0x0f,
0x07, 0x06, 0xaf, 0xd0, 0x02, 0x63, 0xf2, 0x7e, 0x22, 0x92, 0x30, 0x02,
0xd4, 0x2e, 0x1d, 0x70, 0x0f, 0x4c, 0xf4, 0xa9, 0xd3, 0xa0, 0xa4, 0x9d,
0xd8, 0x12, 0x8e, 0x94, 0xda, 0x5e, 0xd4, 0x95, 0x63, 0x10, 0xf2, 0x31,
0x50, 0xc5, 0x18, 0x2c, 0x41, 0x19, 0xc0, 0xa9, 0x8d, 0x32, 0x2e, 0x59,
0x8f, 0xd2, 0xa1, 0xee, 0x84, 0x49, 0xe4, 0xa7, 0xa5, 0x27, 0x94, 0x3b,
0x12, 0x3f, 0x1a, 0x7e, 0xe5, 0x50, 0x72, 0x71, 0x4c, 0xf3, 0x97, 0xb6,
0x4f, 0xd2, 0xa9, 0xd8, 0x62, 0x6c, 0x61, 0xd1, 0x8d, 0x2e, 0x25, 0x03,
0x82, 0x0f, 0xe1, 0x47, 0x99, 0x21, 0xe8, 0xa7, 0xf1, 0xa5, 0xfd, 0xe9,
0x1c, 0x90, 0x28, 0xd3, 0xa0, 0x0d, 0xcc, 0xbe, 0x80, 0xd2, 0x6f, 0x61,
0xf7, 0x97, 0xf5, 0xa7, 0x6c, 0xfe, 0xf3, 0x13, 0xfa, 0x52, 0x88, 0xe3,
0x1f, 0xc3, 0x4a, 0xcc, 0x44, 0x0d, 0x32, 0xf0, 0xca, 0x0e, 0xe1, 0xfc,
0xaa, 0x28, 0x46, 0x5f, 0x27, 0xd2, 0xaf, 0x90, 0xb8, 0xc5, 0x55, 0x88,
0x60, 0x9f, 0xcb, 0xf2, 0xa9, 0x71, 0x77, 0x40, 0x58, 0x1d, 0x68, 0xa1,
0x69, 0x2b, 0x41, 0x86, 0x4d, 0x40, 0xe3, 0x73, 0xa8, 0xf7, 0xa9, 0xcd,
0x42, 0x4f, 0xef, 0x17, 0x3d, 0x05, 0x4c, 0x84, 0x58, 0x38, 0x5f, 0xc2,
0xa1, 0xe6, 0x43, 0xfe, 0xcf, 0xf3, 0xa5, 0xe6, 0x53, 0x93, 0xf7, 0x7b,
0x0f, 0x5a, 0x92, 0x9e, 0xe3, 0x14, 0x75, 0xa8, 0x5f, 0xe5, 0x93, 0x77,
0x63, 0xc1, 0xa9, 0x87, 0x5a, 0x63, 0x00, 0xc0, 0x83, 0x43, 0x5a, 0x00,
0x8c, 0xa1, 0x86, 0x08, 0xcd, 0x41, 0x24, 0x24, 0x8c, 0xa9, 0xce, 0x3d,
0x6a, 0x64, 0x24, 0x8c, 0x1e, 0xa3, 0x83, 0x4f, 0x1d, 0xea, 0x5a, 0x4c,
0x46, 0x5f, 0x43, 0xe9, 0x5d, 0xed, 0x8d, 0xc7, 0xda, 0x6d, 0x92, 0x5e,
0xf8, 0xc3, 0x7d, 0x45, 0x71, 0x13, 0x28, 0x0d, 0xc5, 0x6f, 0x78, 0x7e,
0x5f, 0xf5, 0xb0, 0x93, 0xe8, 0xc3, 0xf9, 0x57, 0x3b, 0x56, 0xd0, 0x89,
0x23, 0xff, 0xd5, 0x6e, 0xb1, 0x27, 0x99, 0x7e, 0xc3, 0xb2, 0x80, 0xb5,
0x9e, 0x83, 0xe6, 0xc9, 0xe8, 0x3a, 0xd3, 0xae, 0x1f, 0xcd, 0xb8, 0x79,
0x3f, 0xbc, 0xc4, 0xfe, 0x75, 0x3c, 0x29, 0x85, 0xc9, 0xef, 0x57, 0x05,
0x76, 0x6c, 0x91, 0x38, 0x1e, 0x86, 0x9c, 0x01, 0xcd, 0x42, 0xbf, 0x21,
0xd8, 0x7a, 0x76, 0xa9, 0x47, 0x5a, 0xe8, 0x45, 0x0a, 0x41, 0xcd, 0x14,
0x66, 0x98, 0xec, 0x42, 0xf1, 0xd4, 0xf0, 0x29, 0xb0, 0x1a, 0xaa, 0x24,
0x2c, 0x4f, 0x43, 0xc0, 0xa6, 0xc6, 0x46, 0xdc, 0x1e, 0xb5, 0x32, 0x9d,
0x8b, 0x8e, 0xc0, 0x55, 0x5d, 0xc4, 0x31, 0x7c, 0x7c, 0xa4, 0xd4, 0x3d,
0x2c, 0x22, 0xdf, 0x18, 0xa4, 0xc7, 0xbd, 0x37, 0x3d, 0x29, 0x33, 0x55,
0x71, 0x83, 0x70, 0x2a, 0x24, 0x8b, 0x7a, 0xee, 0x24, 0x8c, 0xfa, 0x53,
0x65, 0x62, 0x41, 0x55, 0xfc, 0x6a, 0x54, 0xde, 0x7e, 0x5d, 0xc1, 0x48,
0xed, 0x8a, 0x8d, 0x1b, 0x10, 0xa2, 0x1d, 0xa3, 0x20, 0xfe, 0x82, 0x97,
0x12, 0x0e, 0x84, 0x7e, 0x54, 0xed, 0x92, 0x63, 0xef, 0xfe, 0x94, 0x9e,
0x5b, 0xff, 0x00, 0x78, 0xfe, 0x95, 0x56, 0xec, 0x80, 0x4f, 0xde, 0xfb,
0x1a, 0x0b, 0xc8, 0x06, 0x0a, 0xfe, 0x46, 0x97, 0xca, 0x3d, 0xcb, 0x50,
0x62, 0x5e, 0xf9, 0xfc, 0xcd, 0x16, 0x63, 0x1b, 0xe6, 0x1e, 0xea, 0x68,
0xf3, 0x57, 0xb8, 0x23, 0xf0, 0xa5, 0xf2, 0x93, 0xd2, 0x97, 0xcb, 0x8f,
0xfb, 0xa2, 0x8d, 0x44, 0x21, 0x9a, 0x2f, 0xef, 0x54, 0x68, 0x54, 0xbb,
0x60, 0xf1, 0x9a, 0x9c, 0xa2, 0x03, 0xc0, 0x15, 0x58, 0xae, 0x07, 0x9a,
0x3d, 0x7f, 0x4a, 0x52, 0xbf, 0x50, 0x2c, 0x8c, 0x62, 0x8c, 0x7b, 0xd3,
0x15, 0x81, 0x5c, 0x8a, 0x33, 0x55, 0x71, 0x8e, 0x35, 0x58, 0xab, 0x48,
0xd9, 0x5f, 0xe1, 0xa9, 0x1d, 0xb6, 0x8a, 0x96, 0x25, 0xda, 0x31, 0xf9,
0xd4, 0xda, 0xee, 0xc2, 0x18, 0xad, 0x21, 0x19, 0x04, 0x1f, 0xa8, 0xa7,
0x6f, 0x90, 0x75, 0x50, 0x7e, 0x94, 0xd6, 0x05, 0x0e, 0xf5, 0xe9, 0xdc,
0x54, 0x80, 0x82, 0x32, 0x29, 0xa0, 0x1a, 0x25, 0x03, 0xef, 0x29, 0x14,
0x09, 0x23, 0x3d, 0xe9, 0xe3, 0xa1, 0xa6, 0x90, 0x0f, 0x51, 0x4f, 0x51,
0x8c, 0x25, 0x55, 0xc3, 0x03, 0xc1, 0xe0, 0xd0, 0x58, 0xb6, 0x55, 0x3f,
0x13, 0x50, 0x4e, 0x11, 0x40, 0x00, 0x72, 0x6a, 0x5d, 0xae, 0x8b, 0xf2,
0x9c, 0x8f, 0x43, 0x51, 0x7d, 0x6c, 0x20, 0xf2, 0xc6, 0xc2, 0xa3, 0xbd,
0x4d, 0xa3, 0xc9, 0xe5, 0x5f, 0x85, 0x3c, 0x6f, 0x05, 0x6a, 0x1f, 0x30,
0x7f, 0x10, 0xc5, 0x46, 0xaf, 0xe4, 0x5d, 0x47, 0x38, 0xe8, 0x18, 0x1a,
0x89, 0xa5, 0x6b, 0xa1, 0x3d, 0x8f, 0xff, 0xd6, 0xcb, 0x50, 0x4b, 0xfa,
0xd5, 0xf5, 0x2a, 0x47, 0xcb, 0x55, 0x6d, 0xf1, 0xe6, 0x73, 0xe9, 0x56,
0x8a, 0x21, 0xe7, 0xa1, 0xf5, 0xad, 0xa0, 0xb4, 0xb9, 0xba, 0x15, 0x94,
0x30, 0xc5, 0x2c, 0x6c, 0x4f, 0x07, 0xa8, 0xa6, 0x65, 0x97, 0xaf, 0x23,
0xd4, 0x52, 0x9c, 0x30, 0xdf, 0x19, 0xc9, 0x15, 0xa0, 0x12, 0x54, 0x7f,
0x7a, 0x4f, 0x65, 0xfe, 0x74, 0xe2, 0xc3, 0x66, 0xf1, 0x50, 0x67, 0x8d,
0xa7, 0xf1, 0xc7, 0x73, 0xe9, 0x43, 0x60, 0x4b, 0xfe, 0xb7, 0x93, 0xf7,
0x47, 0xeb, 0x51, 0xc9, 0x28, 0xc1, 0x54, 0x19, 0xfe, 0x54, 0xad, 0xb8,
0x8c, 0x1f, 0xc1, 0x47, 0xf5, 0xa4, 0xd9, 0x82, 0x23, 0xee, 0x79, 0x35,
0x2e, 0xfd, 0x00, 0x68, 0x57, 0x44, 0xdc, 0x4f, 0xe1, 0x4a, 0x04, 0x8f,
0x1e, 0xfc, 0xe0, 0x54, 0x9f, 0x7d, 0xf1, 0xfc, 0x2b, 0xfc, 0xe9, 0x33,
0x88, 0xdd, 0x7d, 0x09, 0xa2, 0xc0, 0x35, 0x06, 0x61, 0x3e, 0xbd, 0xea,
0x5c, 0x07, 0x50, 0x4f, 0xa7, 0x5a, 0x6a, 0x0d, 0xac, 0x57, 0xd4, 0x66,
0x9d, 0x17, 0xdc, 0x03, 0xd3, 0x8a, 0x6b, 0xb0, 0x0b, 0xb8, 0xa6, 0x03,
0xf4, 0xf5, 0xa7, 0xd2, 0xb7, 0x3c, 0x1a, 0x87, 0x0c, 0x9f, 0x77, 0x91,
0xe9, 0xfe, 0x15, 0x5b, 0x0c, 0x9b, 0x26, 0x94, 0x93, 0x4c, 0x56, 0x0d,
0xc8, 0xa7, 0x1e, 0xb5, 0x40, 0x19, 0x34, 0xa0, 0xf3, 0xd2, 0x9b, 0x4a,
0x3a, 0xd0, 0x03, 0x65, 0x6f, 0x94, 0xe3, 0xa9, 0xe3, 0xf3, 0xa6, 0x3e,
0x30, 0x22, 0x5e, 0xff, 0x00, 0xca, 0x86, 0x39, 0x90, 0x0e, 0xcb, 0xc9,
0xa6, 0x83, 0x80, 0x65, 0x3d, 0x4f, 0x4a, 0x86, 0xc4, 0x35, 0xd0, 0x21,
0x1e, 0x57, 0x53, 0xda, 0x9b, 0x99, 0x0a, 0xe4, 0x01, 0x53, 0xc6, 0xa4,
0x12, 0xed, 0xf7, 0x8d, 0x23, 0x29, 0x07, 0x7a, 0x75, 0xee, 0x3d, 0x69,
0x72, 0xf5, 0x02, 0x13, 0x18, 0x31, 0xf9, 0x84, 0xe4, 0xf5, 0xa9, 0xc2,
0x3a, 0x7d, 0xce, 0x47, 0xa1, 0xa8, 0x86, 0x0e, 0x54, 0x74, 0x6e, 0x95,
0x3c, 0x67, 0x31, 0xe6, 0x88, 0xa4, 0x03, 0x43, 0x02, 0x71, 0xd0, 0xfa,
0x1a, 0x61, 0xcc, 0x6d, 0xfe, 0xc9, 0xfd, 0x2a, 0x46, 0x50, 0xdd, 0x69,
0x87, 0x7a, 0x8c, 0x7d, 0xe5, 0xfd, 0x69, 0xb0, 0x25, 0xed, 0x4d, 0x24,
0x01, 0x93, 0x51, 0xa4, 0x81, 0x46, 0xdc, 0xe4, 0x76, 0xf6, 0xf6, 0xa4,
0x95, 0x81, 0x3b, 0x4f, 0x41, 0xc9, 0xa3, 0x9b, 0x4b, 0x81, 0x59, 0xf2,
0xed, 0xb8, 0xd5, 0xee, 0xc2, 0xab, 0x01, 0xc7, 0x3e, 0xdf, 0xa9, 0xab,
0x0e, 0xca, 0xa0, 0x67, 0xf2, 0xa9, 0x8f, 0x56, 0x02, 0x1c, 0x77, 0xaa,
0x73, 0x05, 0xc6, 0x50, 0x70, 0x3f, 0x2a, 0xb3, 0xb4, 0xbf, 0x2f, 0xc0,
0xf4, 0xa6, 0x4e, 0x00, 0x8f, 0x8a, 0x52, 0x57, 0x40, 0x7f, 0xff, 0xd7,
0xa3, 0x12, 0x90, 0x85, 0x87, 0x50, 0x73, 0x56, 0x81, 0xc8, 0xcd, 0x41,
0x03, 0xa9, 0x52, 0x3d, 0x6a, 0x44, 0xe0, 0x6d, 0xf4, 0xae, 0x88, 0xec,
0x6e, 0x4b, 0x4d, 0x2a, 0xb8, 0x2c, 0x78, 0xf7, 0xa8, 0xa4, 0x9d, 0x53,
0x81, 0xc9, 0xaa, 0x6d, 0x24, 0x92, 0x9f, 0x6a, 0x25, 0x34, 0x82, 0xe4,
0xa5, 0xb7, 0x37, 0x96, 0xad, 0xc1, 0x3d, 0x6a, 0xc0, 0x02, 0x3f, 0x95,
0x39, 0x6a, 0xa6, 0x22, 0x38, 0xcd, 0x5d, 0x83, 0xee, 0xe0, 0xfd, 0xee,
0xa6, 0xa2, 0x1a, 0xbd, 0x40, 0x95, 0x57, 0x6a, 0xe7, 0xa9, 0x3d, 0x4d,
0x42, 0x18, 0xf2, 0xc3, 0xab, 0x70, 0x3e, 0x95, 0x2c, 0xad, 0x84, 0xc7,
0xad, 0x36, 0x35, 0xfe, 0x23, 0xf8, 0x7b, 0x0a, 0xd5, 0xef, 0x64, 0x04,
0x8a, 0x02, 0xae, 0xd1, 0x50, 0xbf, 0x02, 0x41, 0xeb, 0x8a, 0x9e, 0xa0,
0x97, 0xef, 0xe3, 0xd4, 0x0f, 0xe7, 0x44, 0xb6, 0x01, 0xed, 0x80, 0x55,
0xbd, 0x38, 0xfc, 0xe9, 0x63, 0xc6, 0x58, 0x7a, 0x1a, 0x57, 0x1b, 0x94,
0x8a, 0x64, 0x67, 0x2c, 0x4f, 0xa8, 0x06, 0x8e, 0xa0, 0x4e, 0x71, 0x9e,
0xb4, 0x98, 0xf7, 0xa0, 0xf5, 0xa4, 0xab, 0x18, 0xd3, 0x1e, 0x4e, 0xe5,
0x38, 0x34, 0x06, 0x39, 0xda, 0xc3, 0x0d, 0x4f, 0x1d, 0x69, 0xac, 0x03,
0x0c, 0x1a, 0x56, 0xec, 0x03, 0xb0, 0x68, 0x1d, 0x6a, 0x10, 0xcf, 0x1f,
0x0c, 0x72, 0xbe, 0xb4, 0xf7, 0x93, 0x6c, 0x6c, 0xd9, 0xed, 0x45, 0xd0,
0x10, 0x12, 0x09, 0x39, 0xe8, 0x4f, 0x3f, 0x41, 0x52, 0x20, 0x2c, 0x77,
0xb7, 0xe0, 0x2a, 0x38, 0x54, 0xb0, 0x05, 0xba, 0x55, 0x83, 0x22, 0x2f,
0xde, 0xc0, 0xa8, 0x8f, 0x76, 0x21, 0xc3, 0xa1, 0xa4, 0xa6, 0x79, 0xaa,
0x47, 0xca, 0x09, 0xfa, 0x52, 0x66, 0x43, 0xd0, 0x01, 0xf5, 0xab, 0xba,
0x18, 0xc9, 0x10, 0x8f, 0x99, 0x3a, 0xf5, 0xc5, 0x3a, 0x16, 0x06, 0x2f,
0xc4, 0xd2, 0xec, 0x63, 0xf7, 0x9c, 0xfe, 0x1c, 0x55, 0x2c, 0x00, 0xf9,
0x3f, 0x74, 0x93, 0x8a, 0xcd, 0xbb, 0x3b, 0x88, 0xba, 0x64, 0x41, 0xdf,
0xf2, 0xa4, 0xde, 0x4f, 0xdd, 0x52, 0x7f, 0x4a, 0x14, 0x38, 0x1c, 0x61,
0x87, 0xe5, 0x4b, 0xbc, 0x0f, 0xbc, 0x0a, 0xfd, 0x6a, 0xae, 0x04, 0x52,
0xa9, 0x29, 0xb9, 0x80, 0x18, 0xfc, 0xea, 0x9e, 0x24, 0x90, 0x9c, 0x73,
0x53, 0xdc, 0xca, 0x1b, 0x0a, 0xbd, 0x05, 0x6c, 0xe8, 0xd2, 0xd9, 0x44,
0x08, 0x73, 0x89, 0x0f, 0x73, 0xd2, 0xb1, 0x9b, 0x4d, 0x89, 0xb3, 0x9f,
0x52, 0xeb, 0x95, 0xe8, 0x6a, 0xe2, 0x95, 0x5e, 0x58, 0x1c, 0xfa, 0x9a,
0x5b, 0xbd, 0x8f, 0x76, 0xfe, 0x58, 0xc0, 0xce, 0x07, 0xe2, 0x69, 0x16,
0x35, 0xe5, 0x7a, 0x11, 0xc5, 0x38, 0x5c, 0x11, 0x2e, 0x41, 0xe4, 0x54,
0x13, 0xff, 0x00, 0xab, 0xa5, 0x31, 0x11, 0xca, 0xb6, 0x2a, 0x19, 0x59,
0xc2, 0xec, 0x62, 0x0d, 0x54, 0x9e, 0x9a, 0x8c, 0xff, 0xd0, 0xaa, 0x42,
0xc3, 0x34, 0xb0, 0x91, 0x9c, 0x31, 0x00, 0x54, 0x0c, 0x1f, 0x27, 0x1c,
0x0a, 0xd3, 0xd4, 0xd3, 0xca, 0xd4, 0x98, 0xf6, 0x70, 0x0f, 0xf9, 0xfc,
0xaa, 0xaa, 0x8c, 0xaf, 0x3f, 0xc5, 0x5a, 0x45, 0x5d, 0x58, 0xd9, 0x6c,
0x51, 0x44, 0xde, 0x71, 0xdf, 0xd2, 0xaf, 0xa4, 0x28, 0xa0, 0x16, 0xff,
0x00, 0xeb, 0x55, 0x37, 0x06, 0x37, 0xdc, 0x3a, 0x8a, 0xb7, 0xbc, 0x4a,
0x02, 0x8f, 0xc6, 0x9c, 0x2c, 0xb7, 0x04, 0x3b, 0x01, 0x81, 0x7e, 0xd8,
0xe2, 0x82, 0xa4, 0x22, 0xba, 0xf5, 0x02, 0x95, 0xf8, 0x8c, 0xfd, 0x2a,
0x19, 0x66, 0x08, 0xbb, 0x57, 0xae, 0x2b, 0x46, 0xd2, 0xdc, 0x64, 0x9f,
0xeb, 0x9c, 0x11, 0xf7, 0x54, 0x7e, 0xb5, 0x3e, 0x31, 0x59, 0x71, 0x3a,
0xab, 0x7c, 0xe3, 0x83, 0x57, 0xc4, 0x71, 0x91, 0x90, 0x29, 0x42, 0x57,
0x04, 0x4b, 0x8a, 0x86, 0x51, 0xfb, 0xd4, 0xfa, 0xd0, 0xcb, 0x1a, 0x0c,
0xb1, 0x23, 0xf1, 0x35, 0x0a, 0x06, 0x79, 0x37, 0x72, 0x00, 0xe4, 0x77,
0xa7, 0x27, 0xd0, 0x0b, 0x95, 0x02, 0x71, 0x36, 0xdf, 0xaf, 0xf8, 0xd3,
0xfc, 0xc6, 0x5f, 0xbe, 0x32, 0x3d, 0x45, 0x34, 0x91, 0xe6, 0xa4, 0x83,
0xa1, 0xe2, 0x9b, 0x60, 0x4d, 0x45, 0x04, 0xa8, 0xe4, 0xf1, 0x4c, 0xf3,
0x14, 0xfd, 0xc0, 0x4d, 0x53, 0x63, 0x24, 0x14, 0xd2, 0x40, 0xe4, 0xd3,
0x40, 0x91, 0x87, 0x50, 0xbf, 0x4a, 0x04, 0x4b, 0xd4, 0xf2, 0x7d, 0xe8,
0xd4, 0x06, 0xf9, 0x80, 0xf0, 0xa0, 0xb7, 0xd2, 0xaa, 0xcb, 0xb8, 0x71,
0x8c, 0x03, 0xc9, 0x15, 0x7f, 0x18, 0x15, 0x06, 0xdd, 0xc0, 0x16, 0xfe,
0x23, 0xfa, 0x62, 0xa2, 0x49, 0xb1, 0x08, 0x81, 0x24, 0x19, 0xdc, 0x4f,
0xb5, 0x4a, 0x11, 0x17, 0xa0, 0x15, 0x4d, 0x54, 0xa3, 0x11, 0xd2, 0xad,
0x2c, 0x9d, 0x9f, 0x8f, 0x43, 0xd8, 0xd2, 0x8b, 0xee, 0x04, 0xdf, 0xc3,
0x49, 0x4a, 0x7a, 0x0a, 0x4a, 0xd0, 0x63, 0x5c, 0xed, 0x52, 0x6a, 0xb6,
0xcc, 0x44, 0xbe, 0xc4, 0xd4, 0xf2, 0x73, 0x85, 0xf5, 0x34, 0xd0, 0x37,
0x43, 0x8f, 0x5c, 0xd4, 0x3d, 0x58, 0x86, 0xa3, 0x6d, 0x1e, 0xc7, 0xf4,
0x34, 0xf9, 0x1f, 0x68, 0xc0, 0xea, 0x6a, 0xb9, 0x90, 0x20, 0xdd, 0x8c,
0xee, 0x1c, 0x8f, 0x7a, 0xad, 0xe6, 0x37, 0x6e, 0x95, 0x0e, 0x76, 0x56,
0x0b, 0x96, 0x92, 0x10, 0x72, 0xa7, 0xae, 0x01, 0xfc, 0xea, 0x17, 0x85,
0x90, 0xe4, 0x71, 0x4d, 0x59, 0x9f, 0x39, 0xcf, 0xb5, 0x4c, 0x7e, 0x75,
0x27, 0x27, 0x03, 0xd6, 0xa7, 0x46, 0xb4, 0x11, 0x5b, 0x73, 0xa9, 0xc9,
0xeb, 0x56, 0x56, 0xe0, 0x16, 0x0c, 0xc3, 0xd8, 0xd3, 0xda, 0x14, 0x09,
0xc9, 0xc5, 0x43, 0x1a, 0xa6, 0x79, 0xe9, 0xeb, 0x45, 0x9a, 0x60, 0x59,
0x25, 0x9f, 0xfd, 0x91, 0xfa, 0xd3, 0x7c, 0xa1, 0x24, 0xf1, 0x42, 0xbf,
0xc4, 0xc3, 0x34, 0xe5, 0x24, 0x1d, 0xad, 0xf8, 0x1a, 0xb5, 0xa6, 0xa7,
0x9b, 0xa9, 0x29, 0xec, 0x80, 0x9a, 0xa9, 0xec, 0x0f, 0x63, 0xff, 0xd1,
0xbb, 0xaf, 0xc5, 0xf3, 0x45, 0x30, 0x1e, 0xaa, 0x7f, 0x9d, 0x64, 0x86,
0x62, 0x3e, 0x55, 0xfc, 0xeb, 0xb0, 0xbe, 0xb7, 0xfb, 0x4d, 0xab, 0xc6,
0x3e, 0xf7, 0x55, 0xfa, 0x8a, 0xe3, 0xe1, 0x7c, 0xae, 0x0f, 0x51, 0xc5,
0x69, 0x4f, 0xb1, 0xa4, 0x19, 0x1c, 0x81, 0xc9, 0x19, 0xc7, 0xe1, 0x4e,
0x58, 0xe3, 0xdd, 0x81, 0xd0, 0x8c, 0xd4, 0xa0, 0xe6, 0x42, 0x7d, 0x06,
0x2a, 0x19, 0x49, 0x57, 0x26, 0x3f, 0x4e, 0x7d, 0xaa, 0xda, 0xb6, 0xa5,
0x8c, 0x99, 0xc2, 0x7c, 0xaa, 0x4f, 0xbd, 0x57, 0x03, 0x27, 0x2d, 0xf8,
0x50, 0x07, 0xcc, 0x4b, 0xd5, 0x87, 0x58, 0xf6, 0x70, 0x4e, 0x7d, 0xeb,
0x2d, 0xf5, 0x10, 0x8d, 0x1e, 0x7a, 0x1c, 0x8c, 0x66, 0x88, 0xe5, 0x78,
0xc6, 0x0f, 0x22, 0x92, 0x20, 0xe3, 0x90, 0x78, 0xe9, 0x9a, 0x98, 0x46,
0xaa, 0x1f, 0x3c, 0xed, 0xaa, 0x4b, 0xaa, 0x01, 0xc8, 0xbe, 0x6b, 0x64,
0x9c, 0x8e, 0xe7, 0xfa, 0x54, 0x91, 0xf2, 0x59, 0xbd, 0xf1, 0xf9, 0x55,
0x18, 0xe4, 0x74, 0x62, 0x16, 0xac, 0xa2, 0x9e, 0x12, 0x42, 0x47, 0xb7,
0xad, 0x5c, 0x65, 0x71, 0x93, 0x19, 0x14, 0x1c, 0x0e, 0x4f, 0xa0, 0xaa,
0x92, 0x6e, 0x2e, 0x36, 0x8c, 0x1c, 0xf6, 0xab, 0x27, 0xfe, 0x79, 0xc7,
0xc7, 0xaf, 0xb5, 0x31, 0x40, 0xf3, 0x46, 0x3a, 0x0c, 0xd3, 0x96, 0xa0,
0x11, 0x18, 0xdf, 0xaf, 0xde, 0x1d, 0x73, 0x56, 0x2a, 0xac, 0xb1, 0x95,
0x7d, 0xeb, 0xc6, 0x6a, 0x64, 0x90, 0x37, 0x07, 0xad, 0x38, 0xbb, 0x68,
0xc0, 0x9b, 0xb5, 0x25, 0x2f, 0x6a, 0x4a, 0xb1, 0x91, 0x48, 0x73, 0x84,
0x1f, 0xc5, 0xfc, 0xa9, 0xcf, 0xc1, 0x4f, 0xaf, 0xf4, 0xa6, 0xa7, 0xcc,
0x4b, 0xfe, 0x02, 0x9d, 0x27, 0x54, 0xfa, 0xd4, 0xf9, 0x88, 0x63, 0xaf,
0xcd, 0xf5, 0xfe, 0x62, 0x9a, 0x0e, 0x07, 0x23, 0xe5, 0x3d, 0x47, 0xa1,
0xa9, 0x5c, 0x6e, 0x5c, 0x0e, 0xbd, 0xa9, 0x99, 0xe9, 0x27, 0x63, 0xd6,
0x93, 0x5a, 0x80, 0xe2, 0xcd, 0x1f, 0x5f, 0x99, 0x7d, 0x7b, 0x8a, 0x90,
0x10, 0x46, 0x45, 0x47, 0xfe, 0xac, 0xe0, 0xfd, 0xd3, 0xd3, 0xda, 0x9a,
0xc3, 0x67, 0xcc, 0x87, 0xea, 0x3b, 0x55, 0x5e, 0xc0, 0x2b, 0x10, 0x64,
0xff, 0x00, 0x74, 0x66, 0x91, 0x19, 0x56, 0x35, 0x1d, 0x49, 0x1d, 0x2a,
0xb3, 0x4e, 0x06, 0xe2, 0x07, 0x5a, 0x58, 0xd5, 0x8a, 0xee, 0xeb, 0xf8,
0xd6, 0x7c, 0xda, 0xe8, 0x04, 0x2c, 0x32, 0xfb, 0x4f, 0x73, 0x5d, 0x7d,
0xa6, 0x99, 0x6b, 0xf6, 0x75, 0x2e, 0x37, 0x16, 0x19, 0xcf, 0x4e, 0xb5,
0xc9, 0xed, 0x05, 0xb8, 0xe3, 0x06, 0xba, 0x6d, 0x2f, 0x52, 0x8d, 0xd0,
0x41, 0x29, 0x0a, 0x57, 0x80, 0x4f, 0xf2, 0xac, 0x88, 0x95, 0xfa, 0x15,
0x35, 0x3d, 0x28, 0x46, 0xbe, 0x74, 0x1f, 0x74, 0x75, 0x1e, 0x95, 0x85,
0x1e, 0x49, 0xc1, 0x38, 0xc1, 0xe6, 0xbb, 0x6b, 0xeb, 0x88, 0x16, 0xd5,
0xf7, 0x30, 0x3b, 0x81, 0x03, 0x1c, 0xf3, 0x5c, 0x59, 0x09, 0xf7, 0xbb,
0x13, 0x42, 0xee, 0x11, 0x64, 0xe1, 0x55, 0x8e, 0x4f, 0x4f, 0x53, 0xd4,
0xd3, 0xcb, 0x46, 0x06, 0x32, 0x31, 0x4c, 0x09, 0x9f, 0xba, 0x80, 0x7d,
0x69, 0x76, 0x1f, 0xe2, 0x3f, 0x97, 0x15, 0xaa, 0x2c, 0x89, 0xca, 0x01,
0xf2, 0xb7, 0xe1, 0x5b, 0x9a, 0x04, 0x64, 0xb4, 0xb7, 0x07, 0xbe, 0x14,
0x7f, 0x33, 0x58, 0xb2, 0xed, 0x54, 0xda, 0xa3, 0x93, 0xc5, 0x76, 0x56,
0x16, 0xff, 0x00, 0x65, 0xb5, 0x48, 0x8f, 0x5c, 0x64, 0xfd, 0x4d, 0x67,
0x3d, 0xc8, 0x91, 0xff, 0xd2, 0xec, 0xeb, 0x8d, 0xd4, 0x20, 0xfb, 0x2d,
0xf3, 0x11, 0xf7, 0x64, 0xe4, 0x7e, 0x3f, 0xfd, 0x7a, 0xec, 0xab, 0x23,
0x58, 0xb6, 0x33, 0xdb, 0x6f, 0x41, 0x96, 0x8f, 0x9f, 0xc3, 0xbd, 0x34,
0xec, 0xee, 0x54, 0x5d, 0x99, 0xcc, 0xab, 0x1c, 0x61, 0x7a, 0xb1, 0xa9,
0x55, 0x42, 0x8c, 0x55, 0x78, 0x4b, 0x11, 0xf2, 0x8c, 0xfd, 0x4d, 0x4b,
0xfb, 0xd3, 0xe9, 0x5b, 0xc5, 0xe9, 0x73, 0x52, 0x19, 0xa1, 0xee, 0x3a,
0x7f, 0x2a, 0x64, 0x72, 0xbc, 0x60, 0xa9, 0x19, 0xf4, 0xab, 0x24, 0x3e,
0x32, 0xcd, 0xfa, 0x53, 0x23, 0x42, 0xa3, 0x71, 0x1b, 0x87, 0xa7, 0xa5,
0x4b, 0x8e, 0xb7, 0x40, 0x28, 0x0a, 0x07, 0xc8, 0x72, 0x3b, 0x8a, 0x89,
0x9f, 0x82, 0xbf, 0x41, 0xf9, 0x54, 0xca, 0x10, 0x9c, 0x1e, 0x41, 0xe8,
0x7f, 0xa5, 0x43, 0x34, 0x6a, 0xad, 0x85, 0xef, 0x43, 0xbd, 0x80, 0x6c,
0x08, 0x4b, 0x02, 0x7b, 0xf3, 0x56, 0x27, 0x95, 0x55, 0x76, 0xf5, 0x35,
0x0f, 0x9a, 0x23, 0xce, 0x3a, 0xe3, 0x02, 0xa2, 0x44, 0x69, 0x1b, 0x27,
0x9a, 0x9b, 0xd9, 0x59, 0x08, 0x92, 0x29, 0xdd, 0x01, 0xe3, 0x39, 0xa9,
0xa3, 0x75, 0x56, 0xc3, 0x71, 0x81, 0x8e, 0x69, 0x7c, 0xb0, 0x8a, 0x07,
0x72, 0x45, 0x54, 0x90, 0xef, 0x93, 0xeb, 0x4e, 0xee, 0x20, 0x69, 0x36,
0x1d, 0x71, 0x50, 0x10, 0x31, 0x92, 0x3f, 0xde, 0xc7, 0x63, 0xea, 0x2a,
0x98, 0xde, 0xbc, 0xa9, 0xfe, 0x95, 0x2a, 0x49, 0x26, 0xec, 0xb1, 0x1d,
0x3b, 0xd3, 0xe7, 0xbe, 0xe3, 0xb9, 0x75, 0x5b, 0x18, 0x57, 0xfc, 0x0f,
0xad, 0x12, 0x1c, 0x0c, 0x0e, 0xa7, 0x8a, 0xa8, 0xd2, 0x32, 0x0d, 0xae,
0xbc, 0x1e, 0x45, 0x2a, 0x4a, 0xe7, 0xe6, 0x23, 0x76, 0x2a, 0xb9, 0xfa,
0x05, 0xcb, 0xa1, 0x40, 0x18, 0x07, 0xa5, 0x32, 0x51, 0xca, 0x7d, 0x69,
0x8b, 0x23, 0x37, 0x21, 0x73, 0xf8, 0xd3, 0x26, 0x90, 0x8c, 0x12, 0xb8,
0xc1, 0xaa, 0x72, 0x56, 0x02, 0xce, 0x0d, 0x45, 0xc2, 0x12, 0xad, 0xd0,
0xf3, 0xfe, 0x35, 0x54, 0xcf, 0x23, 0x0c, 0x82, 0x14, 0x53, 0x17, 0x76,
0xf0, 0x58, 0xe7, 0x3d, 0xcd, 0x43, 0x9a, 0xe8, 0x17, 0x26, 0x69, 0xc2,
0x82, 0x83, 0xe6, 0x03, 0xbf, 0xb5, 0x32, 0x22, 0xce, 0x72, 0x46, 0xec,
0x76, 0xa9, 0xde, 0x20, 0x63, 0xc2, 0xf3, 0x8e, 0x7e, 0xb5, 0x4d, 0x1c,
0xc2, 0xf9, 0x1d, 0xaa, 0x64, 0xda, 0x6a, 0xe0, 0x4b, 0x30, 0x56, 0xe8,
0x30, 0x7d, 0x2a, 0x38, 0x9d, 0x97, 0x2a, 0x3a, 0x9e, 0x28, 0x67, 0x92,
0x53, 0x93, 0xd2, 0x9a, 0xe0, 0xa9, 0x04, 0xfe, 0x35, 0x2d, 0xeb, 0x74,
0x22, 0xcb, 0xab, 0x85, 0x04, 0x00, 0x31, 0x50, 0x15, 0x2a, 0xc4, 0xa9,
0xc1, 0xef, 0x56, 0x44, 0x81, 0xa2, 0x04, 0xf5, 0x04, 0x66, 0x84, 0x05,
0xf8, 0xec, 0x7a, 0x9f, 0xe9, 0x56, 0xd2, 0x7b, 0x0c, 0xad, 0xf3, 0x91,
0x86, 0x6e, 0x3d, 0xaa, 0x55, 0x52, 0x09, 0x05, 0x73, 0x81, 0xd2, 0xa5,
0x64, 0x0a, 0x70, 0x3e, 0xeb, 0x7e, 0x86, 0x91, 0x4f, 0xcc, 0x09, 0xfa,
0x1a, 0x4a, 0x36, 0x7a, 0x80, 0x8a, 0xfb, 0x7e, 0xef, 0x23, 0xd3, 0xb8,
0xa9, 0x41, 0x04, 0x64, 0x53, 0x99, 0x03, 0x0e, 0x45, 0x56, 0x75, 0x68,
0xfe, 0x65, 0x3d, 0x7b, 0x1a, 0xbd, 0x50, 0x17, 0xb4, 0xf8, 0x3e, 0xd5,
0x7e, 0x33, 0xf7, 0x63, 0xf9, 0x8f, 0xe1, 0x5d, 0x95, 0x64, 0x68, 0xd6,
0xa6, 0xde, 0xd7, 0x7b, 0x8c, 0x3c, 0x87, 0x27, 0xe9, 0xda, 0xb5, 0xeb,
0x06, 0xef, 0xa9, 0x94, 0x9d, 0xd9, 0xff, 0xd3, 0xec, 0xe9, 0x29, 0x68,
0xa0, 0x0e, 0x3f, 0x51, 0xb5, 0x36, 0x37, 0x1e, 0x6c, 0x63, 0xf7, 0x52,
0x7e, 0x87, 0xd2, 0xa0, 0x0d, 0x9e, 0x6b, 0xb0, 0xb9, 0xb7, 0x8e, 0xe6,
0x16, 0x86, 0x4e, 0x87, 0xf4, 0xae, 0x25, 0x95, 0xed, 0x64, 0x6b, 0x79,
0x87, 0x2b, 0xd3, 0xde, 0xb4, 0x84, 0xad, 0xa1, 0xa4, 0x58, 0xf6, 0x3b,
0x98, 0x2f, 0x61, 0xc9, 0xa9, 0x86, 0x30, 0x6a, 0xb2, 0xb0, 0x51, 0xc7,
0xcc, 0x4f, 0x5c, 0x53, 0xf1, 0x23, 0x0e, 0x4e, 0xd1, 0xed, 0x5a, 0xa6,
0x58, 0x92, 0x2a, 0x63, 0x39, 0xda, 0x6a, 0xb1, 0xcc, 0x8d, 0x96, 0xab,
0x24, 0x2c, 0x6a, 0x58, 0x72, 0x69, 0xac, 0xbf, 0x28, 0x88, 0x75, 0xea,
0x6a, 0x64, 0xae, 0x04, 0x29, 0x13, 0x48, 0xd9, 0x3f, 0xfe, 0xaa, 0xbc,
0xb1, 0x84, 0x18, 0x15, 0x0a, 0x2b, 0x2a, 0x29, 0x53, 0x9c, 0xf6, 0x34,
0xf1, 0x20, 0xce, 0x1b, 0x83, 0xef, 0x4e, 0x29, 0x20, 0x1b, 0x39, 0xda,
0x05, 0x50, 0x19, 0xc9, 0x20, 0x13, 0xda, 0xac, 0xdc, 0x9e, 0x47, 0xb5,
0x45, 0x19, 0x40, 0x06, 0xee, 0x95, 0x9c, 0xf5, 0x90, 0x85, 0x13, 0x73,
0x9d, 0xbc, 0xf7, 0xa9, 0x50, 0x00, 0x7c, 0xcf, 0xcc, 0x7a, 0x52, 0x34,
0x67, 0x1b, 0xc7, 0x03, 0xd3, 0xad, 0x48, 0xfb, 0xb1, 0x96, 0xc6, 0x7d,
0x47, 0x14, 0xd2, 0x7d, 0x46, 0x45, 0x77, 0xf7, 0xbf, 0x01, 0x52, 0x5b,
0x0f, 0x94, 0x9f, 0xa5, 0x42, 0x09, 0x66, 0x01, 0x87, 0xff, 0x00, 0xaa,
0xac, 0xc4, 0x55, 0x55, 0x89, 0xe3, 0x9a, 0x71, 0xd6, 0x57, 0x01, 0xec,
0x88, 0x79, 0x3c, 0x7b, 0xd5, 0x39, 0x0b, 0x39, 0xc6, 0x72, 0x07, 0x7f,
0xad, 0x5b, 0xe1, 0xfe, 0x67, 0xe1, 0x47, 0x6f, 0x5a, 0x87, 0x05, 0xd4,
0xe3, 0xbf, 0x27, 0xfc, 0x2a, 0xa5, 0xa8, 0x15, 0x55, 0xf6, 0x11, 0x91,
0xd3, 0x8e, 0x6a, 0x51, 0x32, 0xe4, 0x0c, 0x70, 0x0d, 0x4a, 0xd1, 0xa0,
0x40, 0x4b, 0x75, 0x1d, 0x0f, 0x35, 0x51, 0x80, 0x03, 0x70, 0x18, 0xc5,
0x64, 0xef, 0x11, 0x17, 0x32, 0x07, 0x31, 0xe4, 0x7e, 0x1c, 0x55, 0x57,
0xe4, 0x6e, 0xc6, 0x2a, 0xc2, 0x09, 0x19, 0x46, 0x46, 0x54, 0x7a, 0x53,
0xa4, 0x2a, 0x57, 0x04, 0x10, 0x47, 0x4c, 0x8a, 0xa6, 0xae, 0x86, 0x47,
0x03, 0x12, 0x49, 0x5c, 0x67, 0xde, 0x96, 0x6c, 0x1f, 0xbc, 0x30, 0x7a,
0x54, 0x28, 0xac, 0xbf, 0x3a, 0x76, 0xab, 0x2a, 0x04, 0x83, 0xe7, 0xe4,
0xfa, 0x51, 0x1d, 0x55, 0x84, 0x56, 0x08, 0xd8, 0x1e, 0x95, 0x79, 0x19,
0x36, 0xed, 0x1c, 0x7b, 0x1a, 0x8c, 0x0e, 0x0c, 0x4d, 0xf8, 0x53, 0xc6,
0x24, 0x8c, 0x6e, 0x1c, 0xd5, 0x45, 0x5b, 0x61, 0x8e, 0x60, 0x18, 0x60,
0xd5, 0x56, 0xca, 0x9c, 0x1e, 0xb5, 0x36, 0xd7, 0x5f, 0xba, 0x73, 0xec,
0x6a, 0x39, 0x08, 0x61, 0xcf, 0x06, 0x89, 0x01, 0x39, 0x3f, 0x28, 0x35,
0x63, 0x4d, 0xb5, 0x37, 0xb7, 0x1e, 0x64, 0x83, 0xf7, 0x49, 0xfa, 0x9f,
0x4a, 0xa3, 0x12, 0xc9, 0x72, 0x52, 0xde, 0x31, 0xf3, 0x1e, 0x2b, 0xb6,
0xb6, 0xb7, 0x4b, 0x58, 0x56, 0x18, 0xfa, 0x0f, 0xd4, 0xfa, 0xd4, 0x4e,
0x57, 0xd0, 0x89, 0x32, 0x7a, 0x5a, 0x28, 0xac, 0xcc, 0xcf, 0xff, 0xd4,
0xec, 0xe8, 0xa2, 0x8a, 0x00, 0x2b, 0x2b, 0x52, 0xd3, 0x96, 0xf1, 0x37,
0xa7, 0x12, 0x28, 0xe3, 0xdf, 0xda, 0xb5, 0x68, 0xa0, 0x0e, 0x0d, 0x49,
0x46, 0x31, 0x48, 0x36, 0xb2, 0xf0, 0x45, 0x4b, 0xda, 0xba, 0x1d, 0x4b,
0x4d, 0x5b, 0xb5, 0xf3, 0x23, 0xf9, 0x65, 0x5e, 0x87, 0xd7, 0xd8, 0xd7,
0x34, 0x1d, 0x94, 0x98, 0xe5, 0x18, 0x65, 0xeb, 0x9a, 0xda, 0x13, 0xe8,
0xcd, 0xa3, 0x2b, 0x88, 0xe4, 0x6e, 0x1e, 0xdc, 0xff, 0x00, 0x85, 0x39,
0x14, 0x80, 0x4b, 0x75, 0x3d, 0x6a, 0x38, 0xfe, 0x72, 0x5c, 0x8e, 0x3b,
0x55, 0x8e, 0x2a, 0x96, 0xba, 0x8c, 0x6c, 0x67, 0xf7, 0x6b, 0x4e, 0x20,
0x11, 0x83, 0x4c, 0x8f, 0x1b, 0x71, 0xe8, 0x4d, 0x12, 0x1e, 0x88, 0x0f,
0x26, 0xab, 0xa0, 0x10, 0x79, 0x61, 0xdf, 0x8e, 0x9d, 0xa9, 0xaf, 0x6e,
0xc0, 0xff, 0x00, 0x85, 0x5a, 0x23, 0x0e, 0x98, 0xfa, 0x54, 0x84, 0x1c,
0xd4, 0xf2, 0x26, 0x16, 0x32, 0xf6, 0x32, 0x9c, 0x13, 0x8a, 0xb6, 0x9b,
0x50, 0xe7, 0x86, 0x1e, 0xbd, 0xe9, 0xd2, 0x29, 0x73, 0xb4, 0x76, 0x19,
0xa7, 0xaa, 0x23, 0x80, 0x48, 0x1c, 0xd2, 0x8c, 0x6c, 0xf4, 0x02, 0x09,
0x08, 0x69, 0x72, 0x39, 0x15, 0x0f, 0x9a, 0x55, 0xba, 0x64, 0x66, 0xac,
0x08, 0x93, 0x7b, 0x0c, 0x7a, 0x54, 0x9e, 0x52, 0x7b, 0xfe, 0x74, 0xb9,
0x5b, 0xd4, 0x0a, 0xc6, 0x76, 0x94, 0x6c, 0x03, 0x19, 0xa7, 0xe4, 0x85,
0xda, 0x4e, 0xdf, 0x6c, 0x50, 0xe8, 0x01, 0xf9, 0x73, 0xf2, 0xf2, 0x6a,
0x47, 0x8d, 0x02, 0x13, 0x8e, 0xd4, 0x59, 0xf5, 0x02, 0x89, 0x0c, 0x6a,
0x58, 0xe1, 0x66, 0xe7, 0xaf, 0xf2, 0xa9, 0xe3, 0x50, 0xbf, 0x29, 0x1d,
0x47, 0x14, 0xf8, 0xfe, 0x5c, 0xa1, 0xed, 0xd2, 0x94, 0x61, 0xdc, 0x56,
0x22, 0x8b, 0x3f, 0x74, 0xb1, 0x1f, 0x4a, 0x9f, 0x62, 0xf5, 0x3c, 0x9f,
0x7a, 0x62, 0xa8, 0x60, 0xca, 0x7b, 0x1a, 0x72, 0xb1, 0xce, 0xc6, 0xeb,
0xfc, 0xea, 0xd7, 0x98, 0xc4, 0x1c, 0x6e, 0x8f, 0xd7, 0x91, 0x48, 0x06,
0xf4, 0x56, 0x1c, 0x10, 0x3a, 0xd3, 0x9f, 0x8d, 0xaf, 0xf8, 0x1a, 0x6c,
0x7c, 0x02, 0x3d, 0x0d, 0x1d, 0x6c, 0x02, 0x16, 0xde, 0x31, 0x8c, 0x38,
0xa5, 0x52, 0x37, 0x67, 0xfb, 0xdf, 0xce, 0x9c, 0xca, 0x1a, 0xa0, 0x72,
0xc8, 0x41, 0x34, 0x3d, 0x35, 0x02, 0xcf, 0x15, 0x13, 0x92, 0xcc, 0x22,
0x8c, 0x6e, 0x66, 0xe3, 0x14, 0x85, 0x99, 0x88, 0x48, 0x86, 0xe6, 0x6e,
0x98, 0xae, 0x9f, 0x4d, 0xd3, 0x56, 0xd1, 0x7c, 0xd9, 0x7e, 0x69, 0x5b,
0xa9, 0xf4, 0xf6, 0x15, 0x33, 0x9f, 0x44, 0x29, 0x4a, 0xc2, 0xe9, 0x9a,
0x70, 0xb3, 0x4d, 0xef, 0xcc, 0x8c, 0x39, 0xf6, 0xf6, 0xad, 0x5a, 0x28,
0xac, 0x4c, 0x42, 0x8a, 0x28, 0xa0, 0x0f, 0xff, 0xd5, 0xec, 0xe8, 0xa2,
0x8a, 0x00, 0x28, 0xa2, 0x8a, 0x00, 0x2b, 0x2b, 0x51, 0xd3, 0x52, 0xf1,
0x77, 0xa6, 0x16, 0x41, 0xdf, 0xd7, 0xeb, 0x5a, 0xb4, 0x50, 0x07, 0x08,
0xeb, 0x2d, 0xb3, 0xf9, 0x57, 0x0a, 0x54, 0x8a, 0x78, 0x39, 0xae, 0xc6,
0xe2, 0xda, 0x1b, 0xa4, 0xf2, 0xe6, 0x5c, 0x8f, 0xd4, 0x57, 0x2d, 0x75,
0xa6, 0x5c, 0x59, 0x13, 0x24, 0x5f, 0xbc, 0x8f, 0xaf, 0xb8, 0xfa, 0xd6,
0x91, 0x9f, 0x73, 0x45, 0x22, 0xaa, 0xf0, 0x5b, 0xd8, 0xd2, 0x20, 0xcf,
0xce, 0x7b, 0xf4, 0xfa, 0x54, 0x41, 0xf7, 0xb1, 0x5e, 0x99, 0x39, 0x35,
0x62, 0xb4, 0x5a, 0x96, 0x35, 0xfb, 0x37, 0xa1, 0x15, 0x26, 0x7b, 0xd3,
0x18, 0x65, 0x48, 0xf6, 0xa6, 0x31, 0xca, 0x00, 0x3b, 0xd3, 0xbd, 0x80,
0x74, 0x64, 0x90, 0x5b, 0xd4, 0xd3, 0xa2, 0x24, 0x6e, 0x5f, 0x4a, 0x51,
0x80, 0x30, 0x29, 0x84, 0xed, 0x70, 0x7d, 0x78, 0xa3, 0x60, 0x1c, 0xa4,
0xf9, 0x8d, 0xf8, 0x53, 0x99, 0xc2, 0x82, 0x4f, 0x6a, 0x8d, 0x4f, 0xef,
0x1b, 0xf0, 0xa4, 0x3f, 0x3b, 0x6d, 0xec, 0x39, 0x34, 0x5f, 0x40, 0x1c,
0x07, 0xee, 0x9b, 0x3d, 0x4f, 0x34, 0x8c, 0x41, 0x87, 0x3e, 0xa2, 0xa4,
0xed, 0x55, 0xff, 0x00, 0xe5, 0x9e, 0xdf, 0x7c, 0x7e, 0xb4, 0x30, 0x26,
0x65, 0x0c, 0xbc, 0x1e, 0x47, 0x4a, 0x66, 0x47, 0xcb, 0x27, 0xe0, 0x6a,
0x4a, 0x8e, 0x45, 0x03, 0x9e, 0xc7, 0xaf, 0xf8, 0xd0, 0xfb, 0x80, 0xe5,
0x18, 0x91, 0x87, 0xd0, 0xd2, 0xb2, 0x6e, 0x15, 0x12, 0x9c, 0xb0, 0x27,
0xae, 0x31, 0xf9, 0x54, 0xb4, 0x20, 0x18, 0x72, 0xc3, 0xcb, 0x6e, 0xb4,
0xd8, 0xc9, 0x24, 0xe6, 0xa4, 0x71, 0x9f, 0xa8, 0xaa, 0xde, 0x67, 0x97,
0x21, 0x2d, 0xdc, 0x54, 0xb7, 0x67, 0xa8, 0x16, 0x89, 0xc5, 0x46, 0x16,
0x5b, 0xb7, 0xf2, 0x6d, 0xd7, 0x71, 0xf5, 0xec, 0x2a, 0xe5, 0xa6, 0x9b,
0x71, 0x7b, 0x89, 0x26, 0xfd, 0xdc, 0x5f, 0xa9, 0xfa, 0x57, 0x53, 0x05,
0xbc, 0x36, 0xc9, 0xe5, 0xc2, 0xbb, 0x47, 0xea, 0x6a, 0x25, 0x3b, 0xe8,
0x88, 0x72, 0x28, 0xe9, 0xda, 0x62, 0x59, 0x8d, 0xee, 0x77, 0x48, 0x7b,
0xfa, 0x7d, 0x2b, 0x56, 0x8a, 0x2b, 0x33, 0x30, 0xa2, 0x8a, 0x28, 0x00,
0xa2, 0x8a, 0x28, 0x03, 0xff, 0xd6, 0xec, 0xe8, 0xa2, 0x8a, 0x00, 0x28,
0xa2, 0x8a, 0x00, 0x28, 0xa2, 0x8a, 0x00, 0x29, 0x29, 0x68, 0xa0, 0x0c,
0x8b, 0xad, 0x1e, 0xda, 0xe0, 0x97, 0x4f, 0xdd, 0xb9, 0xee, 0x3a, 0x7e,
0x55, 0x87, 0x3e, 0x9d, 0x7d, 0x6b, 0xce, 0x3c, 0xc5, 0xf5, 0x5e, 0x6b,
0xb3, 0xa2, 0x9a, 0x76, 0xd8, 0xa5, 0x26, 0x8e, 0x09, 0x66, 0x43, 0xc3,
0x7c, 0xa7, 0xde, 0x92, 0x3f, 0x98, 0x81, 0xfd, 0xd1, 0x5d, 0x95, 0xc5,
0x85, 0xad, 0xd7, 0xfa, 0xd4, 0x19, 0xf5, 0x1c, 0x1a, 0xc7, 0x7d, 0x05,
0x97, 0x26, 0x09, 0x7f, 0x06, 0x1f, 0xd4, 0x55, 0xa9, 0xf7, 0x29, 0x4c,
0xcc, 0xc5, 0x35, 0xc1, 0x28, 0x71, 0xd7, 0xad, 0x59, 0x7d, 0x33, 0x52,
0x8b, 0xa2, 0x87, 0x1e, 0xc7, 0xff, 0x00, 0xd5, 0x55, 0x18, 0xcf, 0x17,
0x12, 0xc6, 0xcb, 0xf5, 0x18, 0xab, 0xe7, 0x4c, 0xab, 0xa1, 0xa0, 0xe0,
0xb3, 0x7b, 0x0a, 0x7a, 0x0c, 0x0c, 0x9e, 0xa7, 0x93, 0x55, 0x55, 0xc0,
0x38, 0x3d, 0x2a, 0x7f, 0xb4, 0x2f, 0xbd, 0x25, 0x25, 0xd4, 0x64, 0xdd,
0xaa, 0x03, 0xc3, 0x6d, 0xf5, 0x20, 0xd2, 0xfd, 0xa1, 0x2a, 0x36, 0x95,
0x4b, 0x86, 0x03, 0xa5, 0x39, 0x49, 0x01, 0x66, 0x86, 0xe4, 0x62, 0x98,
0x9e, 0x7c, 0xbc, 0x43, 0x13, 0x37, 0xd0, 0x55, 0xb4, 0xd3, 0x75, 0x29,
0x7a, 0xa8, 0x41, 0xee, 0x7f, 0xfd, 0x74, 0x39, 0xa1, 0x5d, 0x19, 0xc3,
0x29, 0x20, 0x07, 0xa5, 0x3d, 0xa5, 0x51, 0xc0, 0xe4, 0xfb, 0x56, 0xd4,
0x7a, 0x0b, 0x12, 0x0c, 0xf2, 0xfe, 0x00, 0x7f, 0x53, 0x5b, 0x16, 0xf6,
0x36, 0xb6, 0xbf, 0xea, 0x90, 0x67, 0xd4, 0xf2, 0x6b, 0x3e, 0x7b, 0x6c,
0x4f, 0x31, 0xcd, 0x43, 0xa7, 0x5f, 0x5d, 0x7c, 0xc4, 0x79, 0x6b, 0xea,
0x78, 0xff, 0x00, 0xeb, 0xd6, 0xdd, 0xb6, 0x91, 0x6b, 0x6e, 0x43, 0xb7,
0xef, 0x18, 0x77, 0x3d, 0x3f, 0x2a, 0xd6, 0xa2, 0xa5, 0xb6, 0xf7, 0x25,
0xc9, 0xb1, 0x29, 0x68, 0xa2, 0x91, 0x21, 0x45, 0x14, 0x50, 0x01, 0x45,
0x14, 0x50, 0x01, 0x45, 0x14, 0x50, 0x07, 0xff, 0xd9
};
const size_t oomerbot_jpeg_size = 6777;
#endif // OOMERBOT_JPEG_H

428
poomer-discord.cpp Normal file
View File

@ -0,0 +1,428 @@
// Discord bot library - provides all Discord API functionality
#include "../DPP/include/dpp/dpp.h"
// Standard input/output - for console logging (std::cout, std::cerr)
#include <iostream>
// String handling - for std::string class and std::to_string() function
#include <string>
// Terminal I/O control - for hiding password input in getHiddenInput()
#include <termios.h>
// Unix standard definitions - provides STDIN_FILENO constant
#include <unistd.h>
// Time functions - for std::time() to generate timestamps
#include <ctime>
// Dynamic arrays - for std::vector to hold image byte data
#include <vector>
// Threading support - for std::thread to send images asynchronously
#include <thread>
// Time utilities - for std::chrono::seconds() delays
#include <chrono>
// Algorithm functions - for std::transform (string case conversion)
#include <algorithm>
// STB Image library - single header for loading images (JPEG, PNG, etc.)
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
// STB Image Write library - single header for saving images
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
// Embedded image data - contains the JPEG as a byte array (our generated header)
#include "embedded_image.h"
/**
* Function to securely input text without displaying it on screen (like password input)
* This is used for Discord bot tokens to keep them private in the terminal
*
* @param prompt - The text to display before asking for input
* @return std::string - The hidden text that was typed
*/
std::string getHiddenInput(const std::string& prompt) {
// Display the prompt to the user
std::cout << prompt;
std::cout.flush(); // Force immediate output (don't wait for newline)
// Save current terminal settings so we can restore them later
termios oldt;
tcgetattr(STDIN_FILENO, &oldt); // Get current terminal attributes
// Create new terminal settings that disable echo (hide typed characters)
termios newt = oldt; // Copy current settings
newt.c_lflag &= ~ECHO; // Remove the ECHO flag (disables character display)
tcsetattr(STDIN_FILENO, TCSANOW, &newt); // Apply new settings immediately
// Read the hidden input
std::string input;
std::getline(std::cin, input); // Read entire line (including spaces)
// Restore original terminal settings (re-enable echo)
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
std::cout << std::endl; // Add newline since user's Enter wasn't displayed
return input;
}
/**
* Function to vertically flip JPEG image data using STB libraries (upside-down)
*
* @param image_data - The JPEG data as bytes
* @return std::vector<uint8_t> - The vertically flipped JPEG image data
*/
std::vector<uint8_t> flipImageVertically(const std::vector<uint8_t>& image_data) {
std::cout << "📸 Flipping image (" << image_data.size() << " bytes)..." << std::endl;
// Step 1: Decode JPEG to raw pixel data
int width, height, channels;
unsigned char* decoded_data = stbi_load_from_memory(
image_data.data(), // Input JPEG data
image_data.size(), // Size of input data
&width, // Output: image width
&height, // Output: image height
&channels, // Output: number of color channels
0 // Desired channels (0 = keep original)
);
if (!decoded_data) {
std::cout << "❌ Failed to decode JPEG image: " << stbi_failure_reason() << std::endl;
return image_data; // Return original if decode fails
}
std::cout << "✅ Decoded image: " << width << "x" << height << " pixels, " << channels << " channels" << std::endl;
// Step 2: Create buffer for flipped image data
int bytes_per_pixel = channels;
int row_size = width * bytes_per_pixel;
std::vector<unsigned char> flipped_pixels(width * height * bytes_per_pixel);
// Step 3: Flip vertically (reverse row order to make image upside-down)
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// Calculate source and destination pixel positions
int src_index = (y * width + x) * bytes_per_pixel; // Original position
int dst_index = ((height - 1 - y) * width + x) * bytes_per_pixel; // Flipped position (vertically)
// Copy all color channels for this pixel
for (int c = 0; c < bytes_per_pixel; c++) {
flipped_pixels[dst_index + c] = decoded_data[src_index + c];
}
}
}
// Step 4: Encode flipped pixels back to JPEG
std::vector<uint8_t> output_jpeg;
// Helper function to capture JPEG data written by stb_image_write
// This is a "callback" - STB calls this function whenever it has encoded data to write
auto write_func = [](void* context, void* data, int size) {
// Cast void* back to our vector (context is the &output_jpeg from below)
std::vector<uint8_t>* output = static_cast<std::vector<uint8_t>*>(context);
uint8_t* bytes = static_cast<uint8_t*>(data);
// Append the new JPEG bytes to our output vector
output->insert(output->end(), bytes, bytes + size);
};
// Write flipped pixels to JPEG format (quality: 90/100)
int success = stbi_write_jpg_to_func(
write_func, // Callback function to capture data
&output_jpeg, // Context passed to callback
width, // Image width
height, // Image height
channels, // Number of channels
flipped_pixels.data(), // Pixel data
90 // JPEG quality (0-100)
);
// Clean up decoded image memory
stbi_image_free(decoded_data);
if (!success) {
std::cout << "❌ Failed to encode flipped image to JPEG" << std::endl;
return image_data; // Return original if encode fails
}
return output_jpeg;
}
/**
* MAIN FUNCTION - Entry point of the Discord bot program
* Sets up the bot, registers commands, and starts the event loop
*/
int main() {
// Step 1: Get Discord bot token securely from user
std::cout << "=== Discord Bot Startup ===" << std::endl;
std::string BOT_TOKEN = getHiddenInput("Enter Discord Bot Token: ");
// Validate that a token was provided
if (BOT_TOKEN.empty()) {
std::cerr << "Error: Bot token cannot be empty!" << std::endl;
return 1; // Exit with error code
}
// Step 2: Create Discord bot instance
// dpp::cluster is the main bot class that handles all Discord connections
// i_default_intents gives basic permissions, i_message_content allows reading message text
dpp::cluster bot(BOT_TOKEN, dpp::i_default_intents | dpp::i_message_content);
// Step 3: Enable logging to see what the bot is doing
bot.on_log(dpp::utility::cout_logger());
// Step 4: Set up event handler for file uploads
// Lambda function that gets called whenever a message with attachments is posted
bot.on_message_create([&bot](const dpp::message_create_t& event) {
// Ignore messages sent by bots (including our own) to prevent loops
if (event.msg.author.is_bot()) {
return; // Early exit - don't process bot messages
}
// Check if this message has any file attachments
if (!event.msg.attachments.empty()) {
// Debug output to console (only you see this, not Discord users)
std::cout << "\n=== FILE UPLOAD DETECTED ===" << std::endl;
std::cout << "User: " << event.msg.author.username << "#" << event.msg.author.discriminator << std::endl;
std::cout << "Channel ID: " << event.msg.channel_id << std::endl;
std::cout << "Message ID: " << event.msg.id << std::endl;
std::cout << "Attachments: " << event.msg.attachments.size() << std::endl;
// Flag to track if we found any JPEG files
bool found_jpeg = false;
std::vector<dpp::attachment> jpeg_attachments; // Store JPEG attachments for processing
// Loop through each attached file
for (const auto& attachment : event.msg.attachments) {
// Print file details to console
std::cout << " - File: " << attachment.filename << std::endl;
std::cout << " Size: " << attachment.size << " bytes" << std::endl;
std::cout << " URL: " << attachment.url << std::endl;
// Check if filename ends with ".jpg" or ".jpeg" (case-insensitive)
std::string filename_lower = attachment.filename;
// Convert entire filename to lowercase for easier comparison
std::transform(filename_lower.begin(), filename_lower.end(), filename_lower.begin(), ::tolower);
// Check if file ends with .jpg (4 chars) or .jpeg (5 chars)
// substr(length - N) gets the last N characters of the string
if ((filename_lower.length() >= 4 && filename_lower.substr(filename_lower.length() - 4) == ".jpg") ||
(filename_lower.length() >= 5 && filename_lower.substr(filename_lower.length() - 5) == ".jpeg")) {
std::cout << " ✅ JPEG FILE DETECTED!" << std::endl;
found_jpeg = true;
jpeg_attachments.push_back(attachment); // Store for processing
}
}
// If we found JPEG files, process them
if (found_jpeg) {
std::cout << "\n🎯 ACTION: Processing JPEG file upload" << std::endl;
// Add emoji reaction to the message (like clicking a reaction in Discord)
bot.message_add_reaction(event.msg.id, event.msg.channel_id, "🔄");
// Send a text response in the same channel
bot.message_create(dpp::message(event.msg.channel_id, "📸 JPEG detected! Flipping image upside-down..."));
// Process each JPEG in a separate thread (after 5 second delay)
// We use threads so the bot doesn't freeze while processing images
for (const auto& jpeg_attachment : jpeg_attachments) {
std::thread([&bot, // Capture bot by reference (shared)
channel_id = event.msg.channel_id, // Copy these values into the thread
user_id = event.msg.author.id, // so they don't get lost when event ends
attachment_url = jpeg_attachment.url,
original_filename = jpeg_attachment.filename
]() {
// Wait 5 seconds before processing
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "\n--- PROCESSING JPEG IMAGE ---" << std::endl;
std::cout << "Downloading: " << original_filename << std::endl;
std::cout << "From URL: " << attachment_url << std::endl;
// Download the image using DPP's HTTP client
std::cout << "🌐 Starting image download..." << std::endl;
bot.request(attachment_url, dpp::m_get, [&bot, channel_id, user_id, original_filename](const dpp::http_request_completion_t& response) {
if (response.status == 200) {
std::cout << "✅ Downloaded image (" << response.body.size() << " bytes)" << std::endl;
// Convert response body to vector for processing
std::vector<uint8_t> original_data(response.body.begin(), response.body.end());
// Flip the image vertically (upside-down)
std::vector<uint8_t> flipped_data = flipImageVertically(original_data);
// Create new filename for flipped image
std::string flipped_filename = "upside_down_" + original_filename;
// Create message with flipped image
std::string message_text = "🔄 Here's your upside-down image! <@" + std::to_string(user_id) + ">";
dpp::message msg(channel_id, message_text);
msg.add_file(flipped_filename, std::string(flipped_data.begin(), flipped_data.end()));
// Send the flipped image
bot.message_create(msg, [original_filename](const dpp::confirmation_callback_t& callback) {
if (callback.is_error()) {
std::cout << "❌ Failed to send flipped image: " << callback.get_error().message << std::endl;
} else {
std::cout << "✅ Successfully sent flipped " << original_filename << "!" << std::endl;
}
});
} else {
std::cout << "❌ Failed to download image. Status: " << response.status << std::endl;
bot.message_create(dpp::message(channel_id, "❌ Failed to download image for processing."));
}
});
}).detach(); // detach() = thread runs independently, we don't wait for it to finish
}
}
std::cout << "============================" << std::endl;
}
});
// Step 5: Set up slash command handler (commands that start with /)
// [&bot] captures the bot variable by reference so we can use it inside the lambda
bot.on_slashcommand([&bot](const dpp::slashcommand_t& event) {
// Generate unique ID for this command execution (for debugging)
static int command_counter = 0; // static = keeps value between function calls (like a global variable)
int command_id = ++command_counter; // Pre-increment: add 1 then use value (so first command = 1)
// Print detailed debug information about the command
std::cout << "\n=== COMMAND RECEIVED #" << command_id << " ===" << std::endl;
std::cout << "Command: " << event.command.get_command_name() << std::endl;
std::cout << "User: " << event.command.get_issuing_user().username << "#" << event.command.get_issuing_user().discriminator << std::endl;
std::cout << "User ID: " << event.command.get_issuing_user().id << std::endl;
std::cout << "Guild ID: " << event.command.guild_id << std::endl;
std::cout << "Channel ID: " << event.command.channel_id << std::endl;
std::cout << "Timestamp: " << std::time(nullptr) << std::endl; // Unix timestamp
std::cout << "Interaction ID: " << event.command.id << std::endl;
// Check if this is the command we care about
if (event.command.get_command_name() == "oomer") {
std::cout << "Status: EXPECTED COMMAND (Execution #" << command_id << ")" << std::endl;
std::cout << "========================" << std::endl;
// CRITICAL: Must acknowledge Discord interaction within 3 seconds
// or Discord shows "The application did not respond" error
std::cout << "Sending interaction acknowledgment for command #" << command_id << "..." << std::endl;
event.reply("🚀 Render started... (Command #" + std::to_string(command_id) + ")");
// Generate unique thread ID for debugging async operations
static int thread_counter = 0; // Separate counter for threads
int current_thread_id = ++thread_counter;
// Start background thread to send image after delay
// This prevents blocking the main Discord event loop
std::thread([&bot, // Capture bot by reference
channel_id = event.command.channel_id, // Copy channel ID
user_id = event.command.get_issuing_user().id, // Copy user ID
thread_id = current_thread_id, // Copy thread ID
cmd_id = command_id // Copy command ID
]() {
// Wait 5 seconds before sending image (simulates processing time)
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "\n--- SENDING EMBEDDED IMAGE ---" << std::endl;
std::cout << "Using embedded JPEG data (" << oomerbot_jpeg_size << " bytes)..." << std::endl;
// Create vector from embedded image data (no file I/O needed!)
// This copies data from the compiled-in byte array to a vector
std::vector<uint8_t> image_data(oomerbot_jpeg_data, oomerbot_jpeg_data + oomerbot_jpeg_size);
// Sanity check - make sure we have image data
if (!image_data.empty()) {
// Create message text with user mention (@username becomes clickable)
std::string message_text = "🎨 Render complete! <@" + std::to_string(user_id) + ">";
// Create Discord message object
dpp::message msg(channel_id, message_text);
// Attach the image file to the message
// First parameter: filename that appears in Discord
// Second parameter: file data as string
msg.add_file("oomerbot.jpeg", std::string(image_data.begin(), image_data.end()));
// Send the message with image attachment
// Lambda function handles the response (success or error)
bot.message_create(msg, [thread_id, cmd_id](const dpp::confirmation_callback_t& callback) {
if (callback.is_error()) {
// Something went wrong - print error details
std::cout << "❌ Thread #" << thread_id << " (command #" << cmd_id << ") failed to send image: " << callback.get_error().message << std::endl;
std::cout << "Error code: " << callback.get_error().code << std::endl;
} else {
// Success!
std::cout << "✅ Thread #" << thread_id << " (command #" << cmd_id << ") successfully sent embedded oomerbot.jpeg!" << std::endl;
}
});
} else {
// This should never happen since image is embedded at compile time
std::cout << "❌ Embedded image data is empty" << std::endl;
}
}).detach(); // detach() = thread runs independently, don't wait for it
} else {
// Handle unexpected commands (probably old registrations)
std::cout << "Status: UNEXPECTED COMMAND (probably old registration) - Command #" << command_id << std::endl;
std::cout << "========================" << std::endl;
event.reply("⚠️ This command is no longer supported. Please use `/oomer` instead.");
}
});
// Step 6: Set up bot ready event (called when bot successfully connects to Discord)
bot.on_ready([&bot](const dpp::ready_t& event) {
// run_once ensures this only happens on first connection, not reconnections
if (dpp::run_once<struct register_bot_commands>()) {
std::cout << "Bot is ready! Starting command registration..." << std::endl;
std::cout << "Bot user: " << bot.me.username << " (ID: " << bot.me.id << ")" << std::endl;
// Clean up any old slash commands before registering new ones
std::cout << "Clearing old global commands..." << std::endl;
bot.global_commands_get([&bot](const dpp::confirmation_callback_t& callback) {
if (!callback.is_error()) {
// Get list of existing commands
auto commands = std::get<dpp::slashcommand_map>(callback.value);
std::cout << "Found " << commands.size() << " existing commands" << std::endl;
// Delete each old command
for (auto& command : commands) {
std::cout << "Deleting old command: " << command.second.name << std::endl;
bot.global_command_delete(command.first, [](const dpp::confirmation_callback_t& del_callback) {
if (del_callback.is_error()) {
std::cout << "❌ Failed to delete command: " << del_callback.get_error().message << std::endl;
} else {
std::cout << "✅ Command deleted successfully" << std::endl;
}
});
}
} else {
std::cout << "❌ Failed to get existing commands: " << callback.get_error().message << std::endl;
}
// Register our new slash command
std::cout << "Registering oomer command..." << std::endl;
// Parameters: command_name, description, bot_id
bot.global_command_create(dpp::slashcommand("oomer", "render oj", bot.me.id), [](const dpp::confirmation_callback_t& reg_callback) {
if (reg_callback.is_error()) {
std::cout << "❌ Failed to register command: " << reg_callback.get_error().message << std::endl;
} else {
std::cout << "✅ Command registered successfully!" << std::endl;
}
});
});
}
});
// Step 7: Start the bot and run forever
// st_wait means the program will not exit, it will keep running until interrupted
std::cout << "Starting bot event loop..." << std::endl;
bot.start(dpp::st_wait);
// This line should never be reached unless the bot shuts down
return 0;
}