diff --git a/chdb/__init__.py b/chdb/__init__.py index c5e9109c2fb..f2396a997da 100644 --- a/chdb/__init__.py +++ b/chdb/__init__.py @@ -82,7 +82,10 @@ def query(sql, output_format="CSV", path="", udf_path=""): # alias for query sql = query +PyReader = _chdb.PyReader + __all__ = [ + "PyReader", "ChdbError", "query", "sql", diff --git a/chdb/rwabc.py b/chdb/rwabc.py new file mode 100644 index 00000000000..1b868030bcd --- /dev/null +++ b/chdb/rwabc.py @@ -0,0 +1,65 @@ +from abc import ABC, abstractmethod +from typing import List, Any + + +class PyReader(ABC): + def __init__(self, data: Any): + """ + Initialize the reader with data. The exact type and structure of `data` can vary. + + Args: + data (Any): The data with which to initialize the reader, format and type are not strictly defined. + """ + self.data = data + + @abstractmethod + def read(self, col_names: List[str], count: int) -> List[Any]: + """ + Read a specified number of rows from the given columns and return a list of objects, + where each object is a sequence of values for a column. + + Args: + col_names (List[str]): List of column names to read. + count (int): Maximum number of rows to read. + + Returns: + List[Any]: List of sequences, one for each column. + """ + pass + + +class PyWriter(ABC): + def __init__(self, col_names: List[str], types: List[type], data: Any): + """ + Initialize the writer with column names, their types, and initial data. + + Args: + col_names (List[str]): List of column names. + types (List[type]): List of types corresponding to each column. + data (Any): Initial data to setup the writer, format and type are not strictly defined. + """ + self.col_names = col_names + self.types = types + self.data = data + self.blocks = [] + + @abstractmethod + def write(self, col_names: List[str], columns: List[List[Any]]) -> None: + """ + Save columns of data to blocks. Must be implemented by subclasses. + + Args: + col_names (List[str]): List of column names that are being written. + columns (List[List[Any]]): List of columns data, each column is represented by a list. + """ + pass + + @abstractmethod + def finalize(self) -> bytes: + """ + Assemble and return the final data from blocks. Must be implemented by subclasses. + + Returns: + bytes: The final serialized data. + """ + pass diff --git a/programs/local/LocalChdb.cpp b/programs/local/LocalChdb.cpp index b632a034c89..bc2c1324e0a 100644 --- a/programs/local/LocalChdb.cpp +++ b/programs/local/LocalChdb.cpp @@ -1,6 +1,6 @@ #include "LocalChdb.h" - -#include +#include +#include extern bool inside_main = true; @@ -51,6 +51,7 @@ local_result_v2 * queryToBuffer( for (auto & arg : argv) argv_char.push_back(const_cast(arg.c_str())); + py::gil_scoped_release release; return query_stable_v2(argv_char.size(), argv_char.data()); } @@ -147,6 +148,34 @@ PYBIND11_MODULE(_chdb, m) .def("has_error", &query_result::has_error) .def("error_message", &query_result::error_message); + py::class_>(m, "PyReader") + .def( + py::init(), + "Initialize the reader with data. The exact type and structure of `data` can vary." + "you must hold the data with `self.data` in your inherit class\n\n" + "Args:\n" + " data (Any): The data with which to initialize the reader, format and type are not strictly defined.") + .def( + "read", + [](DB::PyReader & self, const std::vector & col_names, int count) + { + // GIL is held when called from Python code. Release it to avoid deadlock + py::gil_scoped_release release; + return std::move(self.read(col_names, count)); + }, + "Read a specified number of rows from the given columns and return a list of objects, " + "where each object is a sequence of values for a column.\n\n" + "Args:\n" + " col_names (List[str]): List of column names to read.\n" + " count (int): Maximum number of rows to read.\n\n" + "Returns:\n" + " List[Any]: List of sequences, one for each column.") + .def( + "get_schema", + &DB::PyReader::getSchema, + "Return a list of column names and their types.\n\n" + "Returns:\n" + " List[str, str]: List of column name and type pairs."); m.def( "query", diff --git a/pyproject.toml b/pyproject.toml index e49ce6b218c..556bcbe6e16 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,3 +4,8 @@ build-backend = "setuptools.build_meta" [tool.cibuildwheel] build-frontend = "pip" + +[tool.pyright] +include = ["chdb"] +exclude = ["src", "contrib", "programs", "build", "buildlib", "dist", "venv", ".venv", ".vscode", ".git", "__pycache__", ".mypy_cache", ".pytest_cache"] + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5c4d38ff662..176913f5b54 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -193,7 +193,7 @@ if (TARGET ch_contrib::jemalloc) target_link_libraries (clickhouse_common_io PUBLIC ch_contrib::jemalloc) endif() -target_link_libraries (clickhouse_common_io PUBLIC ch_contrib::sparsehash ch_contrib::incbin) +target_link_libraries (clickhouse_common_io PUBLIC ch_contrib::sparsehash ch_contrib::incbin ch_contrib::icu) add_subdirectory(Access/Common) add_subdirectory(Common/ZooKeeper) @@ -264,6 +264,83 @@ target_link_libraries (dbms PRIVATE ch_contrib::libdivide) if (TARGET ch_contrib::jemalloc) target_link_libraries (dbms PRIVATE ch_contrib::jemalloc) endif() + +# Include path from shell cmd "python3 -m pybind11 --includes" +execute_process(COMMAND python3 -m pybind11 --includes + OUTPUT_VARIABLE PYBIND11_INCLUDES + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +# Extract and set include directories specifically for source using pybind11 +string(REGEX MATCHALL "-I([^ ]+)" INCLUDE_DIRS_MATCHES ${PYBIND11_INCLUDES}) +set(PYTHON_INCLUDE_DIRS "") +foreach(INCLUDE_DIR_MATCH ${INCLUDE_DIRS_MATCHES}) + string(REGEX REPLACE "-I" "" INCLUDE_DIR_MATCH ${INCLUDE_DIR_MATCH}) + # Accumulate all include directories + set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIRS};${INCLUDE_DIR_MATCH}") +endforeach() + +# Apply the include directories to Storages/StoragePython.cpp and Processors/Sources/PythonSource.cpp +set_source_files_properties(Storages/StoragePython.cpp PROPERTIES INCLUDE_DIRECTORIES "${PYTHON_INCLUDE_DIRS}") +set_source_files_properties(Processors/Sources/PythonSource.cpp PROPERTIES INCLUDE_DIRECTORIES "${PYTHON_INCLUDE_DIRS}") +set_source_files_properties(Columns/ColumnPyObject.cpp PROPERTIES INCLUDE_DIRECTORIES "${PYTHON_INCLUDE_DIRS}") +set_source_files_properties(Common/PythonUtils.cpp PROPERTIES INCLUDE_DIRECTORIES "${PYTHON_INCLUDE_DIRS}") + +# get python version, something like python3.x +execute_process(COMMAND python3 -c "import sys; print('python3.'+str(sys.version_info[1]))" + OUTPUT_VARIABLE PYTHON_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +# remove all warning, because pybind11 will generate a lot of warning +if (OS_LINUX) + # pybind11 will try to find x86_64-linux-gnu/${PYTHON_VERSION}/pyconfig.h + # use -idirafter to make it find the right one and not polute the include path + # set_source_files_properties(Storages/StoragePython.cpp PROPERTIES COMPILE_FLAGS + # "-w -idirafter /usr/include -include x86_64-linux-gnu/${PYTHON_VERSION}/pyconfig.h" + # ) + if (PYTHON_VERSION STREQUAL "python3.6" OR PYTHON_VERSION STREQUAL "python3.7" OR PYTHON_VERSION STREQUAL "python3.8") + set_source_files_properties(Storages/StoragePython.cpp PROPERTIES COMPILE_FLAGS + "-w -idirafter /usr/include -include crypt.h" + ) + set_source_files_properties(Processors/Sources/PythonSource.cpp PROPERTIES COMPILE_FLAGS + "-w -idirafter /usr/include -include crypt.h" + ) + set_source_files_properties(Columns/ColumnPyObject.cpp PROPERTIES COMPILE_FLAGS + "-w -idirafter /usr/include -include crypt.h" + ) + set_source_files_properties(Common/PythonUtils.cpp PROPERTIES COMPILE_FLAGS + "-w -idirafter /usr/include -include crypt.h" + ) + else() + set_source_files_properties(Storages/StoragePython.cpp PROPERTIES COMPILE_FLAGS + "-w" + ) + set_source_files_properties(Processors/Sources/PythonSource.cpp PROPERTIES COMPILE_FLAGS + "-w" + ) + set_source_files_properties(Columns/ColumnPyObject.cpp PROPERTIES COMPILE_FLAGS + "-w" + ) + set_source_files_properties(Common/PythonUtils.cpp PROPERTIES COMPILE_FLAGS + "-w" + ) + endif() +elseif (OS_DARWIN) + set_source_files_properties(Storages/StoragePython.cpp PROPERTIES COMPILE_FLAGS + "-w" + ) + set_source_files_properties(Processors/Sources/PythonSource.cpp PROPERTIES COMPILE_FLAGS + "-w" + ) + set_source_files_properties(Columns/ColumnPyObject.cpp PROPERTIES COMPILE_FLAGS + "-w" + ) + set_source_files_properties(Common/PythonUtils.cpp PROPERTIES COMPILE_FLAGS + "-w" + ) +endif() + set (all_modules dbms) macro (dbms_target_include_directories) diff --git a/src/Columns/ColumnString.h b/src/Columns/ColumnString.h index e8e5ebbcbf9..f507cbeb629 100644 --- a/src/Columns/ColumnString.h +++ b/src/Columns/ColumnString.h @@ -1,7 +1,8 @@ #pragma once -#include #include +#include +#include #include #include @@ -154,7 +155,6 @@ class ColumnString final : public COWHelper { const size_t old_size = chars.size(); const size_t new_size = old_size + length + 1; - chars.resize(new_size); if (length) memcpy(chars.data() + old_size, pos, length); diff --git a/src/Columns/ColumnVectorHelper.h b/src/Columns/ColumnVectorHelper.h index b8ea6ca427f..e75784e09c5 100644 --- a/src/Columns/ColumnVectorHelper.h +++ b/src/Columns/ColumnVectorHelper.h @@ -40,6 +40,14 @@ class ColumnVectorHelper : public IColumn reinterpret_cast(this) + sizeof(*this)) ->push_back_raw(ptr); } + + template + void appendRawData(const char * ptr, size_t count) + { + return reinterpret_cast, PADDING_FOR_SIMD - 1, PADDING_FOR_SIMD> *>( + reinterpret_cast(this) + sizeof(*this)) + ->append_raw(ptr, count); + } }; } diff --git a/src/Common/ErrorCodes.cpp b/src/Common/ErrorCodes.cpp index 28f8e6c6021..0b86b4e2f15 100644 --- a/src/Common/ErrorCodes.cpp +++ b/src/Common/ErrorCodes.cpp @@ -586,6 +586,8 @@ M(704, CANNOT_USE_QUERY_CACHE_WITH_NONDETERMINISTIC_FUNCTIONS) \ M(705, TABLE_NOT_EMPTY) \ M(706, LIBSSH_ERROR) \ + M(707, PY_EXCEPTION_OCCURED) \ + M(708, PY_OBJECT_NOT_FOUND) \ M(999, KEEPER_EXCEPTION) \ M(1000, POCO_EXCEPTION) \ M(1001, STD_EXCEPTION) \ diff --git a/src/Common/PODArray.h b/src/Common/PODArray.h index 68c1e325f0c..f386a2e397c 100644 --- a/src/Common/PODArray.h +++ b/src/Common/PODArray.h @@ -277,6 +277,18 @@ class PODArrayBase : private boost::noncopyable, private TAllocator /// empty c_end += ELEMENT_SIZE; } + template + void append_raw(const void * ptr, size_t count, TAllocatorParams &&... allocator_params) /// NOLINT + { + size_t bytes_to_copy = byte_size(count); + size_t required_capacity = size() + bytes_to_copy; + if (unlikely(required_capacity > capacity())) + reserve(required_capacity, std::forward(allocator_params)...); + + memcpy(c_end, ptr, bytes_to_copy); + c_end += bytes_to_copy; + } + void protect() { #ifndef NDEBUG diff --git a/src/Common/PythonUtils.cpp b/src/Common/PythonUtils.cpp new file mode 100644 index 00000000000..5eda802bab1 --- /dev/null +++ b/src/Common/PythonUtils.cpp @@ -0,0 +1,318 @@ +#include + +#include +#include +#include +#include +#include +#include +#include "Columns/ColumnString.h" + +namespace DB +{ + +const char * ConvertPyUnicodeToUtf8(const void * input, int kind, size_t codepoint_cnt, size_t & output_size) +{ + if (input == nullptr) + return nullptr; + + char * output_buffer = new char[4 * codepoint_cnt]; // Allocate buffer for UTF-8 output + + size_t real_size = 0; + + switch (kind) + { + case 1: { // Handle 1-byte characters (Latin1/ASCII equivalent in ICU) + const char * start = (const char *)input; + const char * end = start + codepoint_cnt; + char code_unit; + char * target = output_buffer; + int32_t append_size = 0; + + while (start < end) + { + code_unit = *start++; + U8_APPEND_UNSAFE(target, append_size, code_unit); + } + real_size += append_size; + output_buffer[real_size] = '\0'; // Null terminate the output string + // LOG_DEBUG(&Poco::Logger::get("PythonUtils"), "Coverted 1byte String: {}", output_buffer); + break; + } + case 2: { // Handle 2-byte characters (UTF-16 equivalent) + const UChar * start = (const UChar *)input; + const UChar * end = start + codepoint_cnt; + UChar code_unit; + char * target = output_buffer; + int32_t append_size = 0; + + while (start < end) + { + code_unit = *start++; + U8_APPEND_UNSAFE(target, append_size, code_unit); + } + real_size += append_size; + output_buffer[real_size] = '\0'; // Null terminate the output string + // LOG_DEBUG(&Poco::Logger::get("PythonUtils"), "Coverted 2byte String: {}", output_buffer); + break; + } + case 4: { // Handle 4-byte characters (Assume UCS-4/UTF-32) + const UInt32 * start = (const UInt32 *)input; + const UInt32 * end = start + codepoint_cnt; + UInt32 code_unit; + char * target = output_buffer; + int32_t append_size = 0; + + while (start < end) + { + code_unit = *start++; + U8_APPEND_UNSAFE(target, append_size, code_unit); + } + real_size += append_size; + output_buffer[real_size] = '\0'; // Null terminate the output string + // LOG_DEBUG(&Poco::Logger::get("PythonUtils"), "Coverted 4byte String: {}", output_buffer); + break; + } + default: + delete[] output_buffer; // Clean up memory allocation if kind is unsupported + throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Unsupported unicode kind {}", kind); + } + + output_size = real_size; + return output_buffer; +} + +size_t +ConvertPyUnicodeToUtf8(const void * input, int kind, size_t codepoint_cnt, ColumnString::Offsets & offsets, ColumnString::Chars & chars) +{ + if (input == nullptr) + return 0; + + size_t estimated_size = codepoint_cnt * 4 + 1; // Allocate buffer for UTF-8 output + size_t chars_cursor = chars.size(); + size_t target_size = chars_cursor + estimated_size; + chars.resize(target_size); + + switch (kind) + { + case 1: { // Handle 1-byte characters (Latin1/ASCII equivalent in ICU) + const char * start = (const char *)input; + const char * end = start + codepoint_cnt; + char code_unit; + int32_t append_size = 0; + + while (start < end) + { + code_unit = *start++; + U8_APPEND_UNSAFE(chars.data(), chars_cursor, code_unit); + } + break; + } + case 2: { // Handle 2-byte characters (UTF-16 equivalent) + const UChar * start = (const UChar *)input; + const UChar * end = start + codepoint_cnt; + UChar code_unit; + int32_t append_size = 0; + + while (start < end) + { + code_unit = *start++; + U8_APPEND_UNSAFE(chars.data(), chars_cursor, code_unit); + } + break; + } + case 4: { // Handle 4-byte characters (Assume UCS-4/UTF-32) + const UInt32 * start = (const UInt32 *)input; + const UInt32 * end = start + codepoint_cnt; + UInt32 code_unit; + int32_t append_size = 0; + + while (start < end) + { + code_unit = *start++; + U8_APPEND_UNSAFE(chars.data(), chars_cursor, code_unit); + } + break; + } + default: + throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Unsupported unicode kind {}", kind); + } + + chars[chars_cursor++] = '\0'; // Null terminate the output string and increase the cursor + offsets.push_back(chars_cursor); + chars.resize_assume_reserved(chars_cursor); + + return chars_cursor; +} + +void FillColumnString(PyObject * obj, ColumnString * column) +{ + ColumnString::Offsets & offsets = column->getOffsets(); + ColumnString::Chars & chars = column->getChars(); + if (PyUnicode_IS_COMPACT_ASCII(obj)) + { + const char * data = reinterpret_cast(PyUnicode_1BYTE_DATA(obj)); + size_t unicode_len = PyUnicode_GET_LENGTH(obj); + column->insertData(data, unicode_len); + } + else + { + PyCompactUnicodeObject * unicode = reinterpret_cast(obj); + if (unicode->utf8 != nullptr) + { + // It's utf8 string, treat it like ASCII + const char * data = reinterpret_cast(unicode->utf8); + column->insertData(data, unicode->utf8_length); + } + else if (PyUnicode_IS_COMPACT(obj)) + { + auto kind = PyUnicode_KIND(obj); + const char * data; + size_t codepoint_cnt; + + if (kind == PyUnicode_1BYTE_KIND) + data = reinterpret_cast(PyUnicode_1BYTE_DATA(obj)); + else if (kind == PyUnicode_2BYTE_KIND) + data = reinterpret_cast(PyUnicode_2BYTE_DATA(obj)); + else if (kind == PyUnicode_4BYTE_KIND) + data = reinterpret_cast(PyUnicode_4BYTE_DATA(obj)); + else + throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Unsupported unicode kind {}", kind); + codepoint_cnt = PyUnicode_GET_LENGTH(obj); + ConvertPyUnicodeToUtf8(data, kind, codepoint_cnt, offsets, chars); + } + else + { + // always convert it to utf8, but this case is rare, here goes the slow path + py::gil_scoped_acquire acquire; + Py_ssize_t bytes_size = -1; + const char * data = PyUnicode_AsUTF8AndSize(obj, &bytes_size); + if (bytes_size < 0) + throw Exception(ErrorCodes::PY_EXCEPTION_OCCURED, "Failed to convert Python unicode object to UTF-8"); + column->insertData(data, bytes_size); + } + } +} + + +const char * GetPyUtf8StrData(PyObject * obj, size_t & buf_len) +{ + // See: https://github.com/python/cpython/blob/3.9/Include/cpython/unicodeobject.h#L81 + if (PyUnicode_IS_COMPACT_ASCII(obj)) + { + const char * data = reinterpret_cast(PyUnicode_1BYTE_DATA(obj)); + buf_len = PyUnicode_GET_LENGTH(obj); + return data; + } + else + { + PyCompactUnicodeObject * unicode = reinterpret_cast(obj); + if (unicode->utf8 != nullptr) + { + // It's utf8 string, treat it like ASCII + const char * data = reinterpret_cast(unicode->utf8); + buf_len = unicode->utf8_length; + return data; + } + else if (PyUnicode_IS_COMPACT(obj)) + { + auto kind = PyUnicode_KIND(obj); + /// We could not use the implementation provided by CPython like below because it requires GIL holded by the caller + // if (kind == PyUnicode_1BYTE_KIND || kind == PyUnicode_2BYTE_KIND || kind == PyUnicode_4BYTE_KIND) + // { + // // always convert it to utf8 + // const char * data = PyUnicode_AsUTF8AndSize(obj, &unicode->utf8_length); + // buf_len = unicode->utf8_length; + // // set the utf8 buffer back + // unicode->utf8 = const_cast(data); + // return data; + // } + const char * data; + size_t codepoint_cnt; + + if (kind == PyUnicode_1BYTE_KIND) + data = reinterpret_cast(PyUnicode_1BYTE_DATA(obj)); + else if (kind == PyUnicode_2BYTE_KIND) + data = reinterpret_cast(PyUnicode_2BYTE_DATA(obj)); + else if (kind == PyUnicode_4BYTE_KIND) + data = reinterpret_cast(PyUnicode_4BYTE_DATA(obj)); + else + throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Unsupported unicode kind {}", kind); + // always convert it to utf8, and we can't use as function provided by CPython because it requires GIL + // holded by the caller. So we have to do it manually with libicu + codepoint_cnt = PyUnicode_GET_LENGTH(obj); + data = ConvertPyUnicodeToUtf8(data, kind, codepoint_cnt, buf_len); + // set the utf8 buffer back like PyUnicode_AsUTF8AndSize does, so that we can reuse it + // and also we can avoid the memory leak + unicode->utf8 = const_cast(data); + unicode->utf8_length = buf_len; + return data; + } + else + { + // always convert it to utf8, but this case is rare, here goes the slow path + py::gil_scoped_acquire acquire; + // PyUnicode_AsUTF8AndSize caches the UTF-8 encoded string in the unicodeobject + // and subsequent calls will return the same string. The memory is released + // when the unicodeobject is deallocated. + Py_ssize_t bytes_size = -1; + const char * data = PyUnicode_AsUTF8AndSize(obj, &bytes_size); + if (bytes_size < 0) + throw Exception(ErrorCodes::PY_EXCEPTION_OCCURED, "Failed to convert Python unicode object to UTF-8"); + buf_len = bytes_size; + return data; + } + } +} + +bool _isInheritsFromPyReader(const py::handle & obj) +{ + // Check directly if obj is an instance of a class named "PyReader" + if (py::str(obj.attr("__class__").attr("__name__")).cast() == "PyReader") + return true; + + // Check the direct base classes of obj's class for "PyReader" + py::tuple bases = obj.attr("__class__").attr("__bases__"); + for (auto base : bases) + if (py::str(base.attr("__name__")).cast() == "PyReader") + return true; + + return false; +} + +// Will try to get the ref of py::array from pandas Series, or PyArrow Table +// without import numpy or pyarrow. Just from class name for now. +const void * tryGetPyArray(const py::object & obj, py::handle & result, std::string & type_name, size_t & row_count) +{ + py::gil_scoped_acquire acquire; + type_name = py::str(obj.attr("__class__").attr("__name__")).cast(); + if (type_name == "ndarray") + { + // Return the handle of py::array directly + row_count = py::len(obj); + py::array array = obj.cast(); + result = array; + return array.data(); + } + else if (type_name == "Series") + { + // Try to get the handle of py::array from pandas Series + py::array array = obj.attr("values"); + row_count = py::len(obj); + result = array; + return array.data(); + } + else if (type_name == "Table") + { + // Try to get the handle of py::array from PyArrow Table + py::array array = obj.attr("to_pandas")(); + row_count = py::len(obj); + result = array; + return array.data(); + } + + // chdb todo: maybe convert list to py::array? + + return nullptr; +} +} diff --git a/src/Common/PythonUtils.h b/src/Common/PythonUtils.h new file mode 100644 index 00000000000..9069febb68f --- /dev/null +++ b/src/Common/PythonUtils.h @@ -0,0 +1,203 @@ +#pragma once + +#include +#include +// #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace DB +{ + +namespace ErrorCodes +{ +extern const int NOT_IMPLEMENTED; +extern const int PY_EXCEPTION_OCCURED; +} + +namespace py = pybind11; + + +struct ColumnWrapper +{ + void * buf; // we may modify the data when cast it to PyObject **, so we need a non-const pointer + size_t row_count; + py::handle data; + DataTypePtr dest_type; + std::string py_type; //py::handle type, eg. numpy.ndarray; + std::string row_format; + std::string encoding; // utf8, utf16, utf32, etc. + std::string name; +}; + +using PyObjectVec = std::vector; +using PyObjectVecPtr = std::shared_ptr; +using PyColumnVec = std::vector; +using PyColumnVecPtr = std::shared_ptr; + +// Template wrapper function to handle any return type +template +auto execWithGIL(Func func, Args &&... args) -> decltype(func(std::forward(args)...)) +{ + py::gil_scoped_acquire acquire; + return func(std::forward(args)...); +} + +// Helper function to convert Python 1,2,4 bytes unicode string to utf8 with icu4c +// kind: 1 for 1-byte characters (Latin1/ASCII equivalent in ICU) +// 2 for 2-byte characters (UTF-16 equivalent) +// 4 for 4-byte characters (Assume UCS-4/UTF-32) +const char * ConvertPyUnicodeToUtf8(const void * input, int kind, size_t codepoint_cnt, size_t & output_size); + +size_t +ConvertPyUnicodeToUtf8(const void * input, int kind, size_t codepoint_cnt, ColumnString::Offsets & offsets, ColumnString::Chars & chars); + +const char * GetPyUtf8StrData(PyObject * obj, size_t & buf_len); + +void FillColumnString(PyObject * obj, ColumnString * column); + +inline const char * GetPyUtf8StrDataWithGIL(PyObject * obj, size_t & buf_len) +{ + return execWithGIL([&]() { return GetPyUtf8StrData(obj, buf_len); }); +} + + +// Helper function to check if an object's class is or inherits from PyReader with a maximum depth +bool _isInheritsFromPyReader(const py::handle & obj); + +inline bool isInheritsFromPyReader(const py::object & obj) +{ + return execWithGIL([&]() { return _isInheritsFromPyReader(obj); }); +} + +// Helper function to check if object is a pandas DataFrame +inline bool isPandasDf(const py::object & obj) +{ + return execWithGIL( + [&]() + { + auto pd_data_frame_type = py::module_::import("pandas").attr("DataFrame"); + return py::isinstance(obj, pd_data_frame_type); + }); +} + +// Helper function to check if object is a PyArrow Table +inline bool isPyarrowTable(const py::object & obj) +{ + return execWithGIL( + [&]() + { + auto table_type = py::module_::import("pyarrow").attr("Table"); + return py::isinstance(obj, table_type); + }); +} + +// Specific wrappers for common use cases +inline auto castToPyList(const py::object & obj) +{ + return execWithGIL([&]() { return obj.cast(); }); +} + +inline auto castToPyArray(const py::object & obj) +{ + return execWithGIL([&]() { return obj.cast(); }); +} + +inline std::string castToStr(const py::object & obj) +{ + return execWithGIL([&]() { return py::str(obj).cast(); }); +} + +inline std::string getPyType(const py::object & obj) +{ + return execWithGIL([&]() { return obj.get_type().attr("__name__").cast(); }); +} + +template +inline std::vector castToVector(const py::object & obj) +{ + return execWithGIL([&]() { return obj.cast>(); }); +} + +inline std::vector castToPyHandleVector(const py::handle obj) +{ + return execWithGIL([&]() { return obj.cast>(); }); +} + +template +inline std::shared_ptr> castToSharedPtrVector(const py::object & obj) +{ + return execWithGIL([&]() { return std::make_shared>(obj.cast>()); }); +} + +inline size_t getObjectLength(const py::object & obj) +{ + return execWithGIL([&]() { return py::len(obj); }); +} + +inline py::object getValueByKey(const py::object & obj, const std::string & key) +{ + return execWithGIL([&]() { return obj[py::str(key)]; }); +} + +inline size_t getLengthOfValueByKey(const py::object & obj, const std::string & key) +{ + return execWithGIL([&]() { return py::len(obj[py::str(key)]); }); +} + +template +inline T castObject(const py::object & obj) +{ + return execWithGIL([&]() { return obj.cast(); }); +} + +inline bool hasAttribute(const py::object & obj, const char * attr_name) +{ + return execWithGIL([&]() { return py::hasattr(obj, attr_name); }); +} + +inline std::string getStringAttribute(const py::object & obj, const char * attr_name) +{ + return execWithGIL([&]() { return obj.attr(attr_name).cast(); }); +} + +template +inline bool isInstanceOf(const py::object & obj) +{ + return execWithGIL([&]() { return py::isinstance(obj); }); +} + +inline size_t getPythonObjectLength(const py::object & obj) +{ + return execWithGIL([&]() { return py::len(obj); }); +} + +inline py::object getAttribute(const py::object & obj, const char * name) +{ + return execWithGIL([&]() { return obj.attr(name); }); +} + +inline py::object callMethod(const py::object & obj, const char * method_name) +{ + return execWithGIL([&]() { return obj.attr(method_name)(); }); +} + +inline std::vector readData(const py::object & data_source, const std::vector & names, size_t cursor, size_t count) +{ + return execWithGIL([&]() { return data_source.attr("read")(names, cursor, count).cast>(); }); +} + +const void * tryGetPyArray(const py::object & obj, py::handle & result, std::string & type_name, size_t & row_count); + +} // namespace DB diff --git a/src/Core/TypeId.h b/src/Core/TypeId.h index 9c634d2321c..e8b2223e190 100644 --- a/src/Core/TypeId.h +++ b/src/Core/TypeId.h @@ -49,6 +49,7 @@ enum class TypeIndex IPv4, IPv6, JSONPaths, + PyObject, }; /** diff --git a/src/DataTypes/Utils.cpp b/src/DataTypes/Utils.cpp index e58331a8bcb..e637a8aa379 100644 --- a/src/DataTypes/Utils.cpp +++ b/src/DataTypes/Utils.cpp @@ -224,6 +224,11 @@ bool canBeSafelyCasted(const DataTypePtr & from_type, const DataTypePtr & to_typ case TypeIndex::Nothing: case TypeIndex::JSONPaths: return false; + case TypeIndex::PyObject: { + if (to_which_type.isString()) + return true; + return false; + } } return true; diff --git a/src/Processors/Sources/PythonSource.cpp b/src/Processors/Sources/PythonSource.cpp new file mode 100644 index 00000000000..6fe9e3eff12 --- /dev/null +++ b/src/Processors/Sources/PythonSource.cpp @@ -0,0 +1,432 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace DB +{ + +namespace py = pybind11; + +namespace ErrorCodes +{ +extern const int PY_OBJECT_NOT_FOUND; +extern const int PY_EXCEPTION_OCCURED; +} + +PythonSource::PythonSource( + py::object & data_source_, + const Block & sample_block_, + PyColumnVecPtr column_cache, + size_t data_source_row_count, + size_t max_block_size_, + size_t stream_index, + size_t num_streams) + : ISource(sample_block_.cloneEmpty()) + , data_source(data_source_) + , sample_block(sample_block_) + , column_cache(column_cache) + , data_source_row_count(data_source_row_count) + , max_block_size(max_block_size_) + , stream_index(stream_index) + , num_streams(num_streams) + , cursor(0) +{ + description.init(sample_block_); +} + +template +void PythonSource::insert_from_list(const py::list & obj, const MutableColumnPtr & column) +{ + py::gil_scoped_acquire acquire; + for (auto && item : obj) + column->insert(item.cast()); +} + +void PythonSource::insert_string_from_array(const py::handle obj, const MutableColumnPtr & column) +{ + auto array = castToPyHandleVector(obj); + for (auto && item : array) + { + size_t str_len; + const char * ptr = GetPyUtf8StrData(item.ptr(), str_len); + column->insertData(ptr, str_len); + } +} + +void PythonSource::insert_string_from_array_raw( + PyObject ** buf, const MutableColumnPtr & column, const size_t offset, const size_t row_count) +{ + column->reserve(row_count); + for (size_t i = offset; i < offset + row_count; ++i) + { + size_t str_len; + const char * ptr = GetPyUtf8StrData(buf[i], str_len); + column->insertData(ptr, str_len); + } +} + +void PythonSource::convert_string_array_to_block( + PyObject ** buf, const MutableColumnPtr & column, const size_t offset, const size_t row_count) +{ + ColumnString * string_column = typeid_cast(column.get()); + if (string_column == nullptr) + throw Exception(ErrorCodes::BAD_TYPE_OF_FIELD, "Column is not a string column"); + ColumnString::Chars & data = string_column->getChars(); + ColumnString::Offsets & offsets = string_column->getOffsets(); + offsets.reserve(row_count); + for (size_t i = offset; i < offset + row_count; ++i) + { + FillColumnString(buf[i], string_column); + // Try to help reserve memory for the string column data every 100 rows to avoid frequent reallocations + // Check the avg size of the string column data and reserve memory accordingly + if ((i - offset) % 100 == 99) + { + size_t data_size = data.size(); + size_t counter = i - offset + 1; + size_t avg_size = data_size / counter; + size_t reserve_size = avg_size * row_count; + if (reserve_size > data.capacity()) + { + LOG_DEBUG(logger, "Reserving memory for string column data: {} bytes", reserve_size); + data.reserve(reserve_size); + } + } + } +} + +template +void PythonSource::insert_from_ptr(const void * ptr, const MutableColumnPtr & column, const size_t offset, const size_t row_count) +{ + column->reserve(row_count); + // get the raw data from the array and memcpy it into the column + ColumnVectorHelper * helper = static_cast(column.get()); + const char * start = static_cast(ptr) + offset * sizeof(T); + helper->appendRawData(start, row_count); +} + + +template +ColumnPtr PythonSource::convert_and_insert(const py::object & obj, UInt32 scale) +{ + MutableColumnPtr column; + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + column = ColumnDecimal::create(0, scale); + else if constexpr (std::is_same_v) + column = ColumnString::create(); + else + column = ColumnVector::create(); + + std::string type_name; + size_t row_count; + py::handle py_array; + const void * data = tryGetPyArray(obj, py_array, type_name, row_count); + if (!py_array.is_none()) + { + if constexpr (std::is_same_v) + insert_string_from_array(py_array, column); + else + insert_from_ptr(data, column, 0, row_count); + return column; + } + + if (type_name == "list") + { + //reserve the size of the column + column->reserve(row_count); + insert_from_list(obj, column); + return column; + } + + throw Exception(ErrorCodes::BAD_TYPE_OF_FIELD, "Unsupported type {} for value {}", getPyType(obj), castToStr(obj)); +} + + +template +ColumnPtr PythonSource::convert_and_insert_array(const ColumnWrapper & col_wrap, size_t & cursor, const size_t count, UInt32 scale) +{ + MutableColumnPtr column; + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) + column = ColumnDecimal::create(0, scale); + else if constexpr (std::is_same_v) + column = ColumnString::create(); + else + column = ColumnVector::create(); + + if (col_wrap.data.is_none()) + throw Exception(ErrorCodes::PY_EXCEPTION_OCCURED, "Column data is None"); + + if constexpr (std::is_same_v) + convert_string_array_to_block(static_cast(col_wrap.buf), column, cursor, count); + else + insert_from_ptr(col_wrap.buf, column, cursor, count); + + return column; +} + +void PythonSource::destory(PyObjectVecPtr & data) +{ + // manually destory PyObjectVec and trigger the py::object dec_ref with GIL holded + py::gil_scoped_acquire acquire; + data->clear(); + data.reset(); +} + +Chunk PythonSource::genChunk(size_t & num_rows, PyObjectVecPtr data) +{ + Columns columns(description.sample_block.columns()); + for (size_t i = 0; i < data->size(); ++i) + { + if (i == 0) + num_rows = getObjectLength((*data)[i]); + const auto & column = (*data)[i]; + const auto & type = description.sample_block.getByPosition(i).type; + WhichDataType which(type); + + try + { + // Dispatch to the appropriate conversion function based on data type + if (which.isUInt8()) + columns[i] = convert_and_insert(column); + else if (which.isUInt16()) + columns[i] = convert_and_insert(column); + else if (which.isUInt32()) + columns[i] = convert_and_insert(column); + else if (which.isUInt64()) + columns[i] = convert_and_insert(column); + else if (which.isUInt128()) + columns[i] = convert_and_insert(column); + else if (which.isUInt256()) + columns[i] = convert_and_insert(column); + else if (which.isInt8()) + columns[i] = convert_and_insert(column); + else if (which.isInt16()) + columns[i] = convert_and_insert(column); + else if (which.isInt32()) + columns[i] = convert_and_insert(column); + else if (which.isInt64()) + columns[i] = convert_and_insert(column); + else if (which.isInt128()) + columns[i] = convert_and_insert(column); + else if (which.isInt256()) + columns[i] = convert_and_insert(column); + else if (which.isFloat32()) + columns[i] = convert_and_insert(column); + else if (which.isFloat64()) + columns[i] = convert_and_insert(column); + else if (which.isDecimal128()) + { + const auto & dtype = typeid_cast *>(type.get()); + columns[i] = convert_and_insert(column, dtype->getScale()); + } + else if (which.isDecimal256()) + { + const auto & dtype = typeid_cast *>(type.get()); + columns[i] = convert_and_insert(column, dtype->getScale()); + } + else if (which.isDateTime()) + columns[i] = convert_and_insert(column); + else if (which.isDateTime64()) + columns[i] = convert_and_insert(column); + else if (which.isString()) + columns[i] = convert_and_insert(column); + else + throw Exception( + ErrorCodes::BAD_TYPE_OF_FIELD, + "Unsupported type {} for column {}", + type->getName(), + description.sample_block.getByPosition(i).name); + } + catch (const Exception & e) + { + destory(data); + LOG_ERROR(logger, "Error processing column {}: {}", i, e.what()); + throw; + } + } + + destory(data); + + if (num_rows == 0) + return {}; + + return Chunk(std::move(columns), num_rows); +} + +std::shared_ptr +PythonSource::scanData(const py::object & data, const std::vector & col_names, size_t & cursor, size_t count) +{ + py::gil_scoped_acquire acquire; + auto block = std::make_shared(); + // Access columns directly by name and slice + for (const auto & col : col_names) + { + py::object col_data = data[py::str(col)]; // Use dictionary-style access + block->push_back(col_data.attr("__getitem__")(py::slice(cursor, cursor + count, 1))); + } + + if (!block->empty()) + cursor += py::len((*block)[0]); // Update cursor based on the length of the first column slice + + return std::move(block); +} + + + +Chunk PythonSource::scanDataToChunk() +{ + auto names = description.sample_block.getNames(); + if (names.empty()) + return {}; + + // 1. Try to get the column data from the data source by column name with GIL + // 2. Get the raw data from the array to bypass GIL + // 3. Insert the raw data into the column with given cursor and count + // a. If the column is a string column, convert it to UTF-8 + // b. If the column is a numeric column, directly insert the raw data + Columns columns(description.sample_block.columns()); + if (names.size() != columns.size()) + throw Exception(ErrorCodes::PY_EXCEPTION_OCCURED, "Column cache size mismatch"); + + auto rows_per_stream = data_source_row_count / num_streams; + auto start = stream_index * rows_per_stream; + auto end = (stream_index + 1) * rows_per_stream; + if (stream_index == num_streams - 1) + end = data_source_row_count; + if (cursor == 0) + cursor = start; + auto count = std::min(max_block_size, end - cursor); + if (count == 0) + return {}; + LOG_DEBUG(logger, "Stream index {} Reading {} rows from {}", stream_index, count, cursor); + + for (size_t i = 0; i < columns.size(); ++i) + { + const auto & col = (*column_cache)[i]; + const auto & type = description.sample_block.getByPosition(i).type; + + WhichDataType which(type); + try + { + // Dispatch to the appropriate conversion function based on data type + if (which.isUInt8()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isUInt16()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isUInt32()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isUInt64()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isUInt128()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isUInt256()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isInt8()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isInt16()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isInt32()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isInt64()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isInt128()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isInt256()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isFloat32()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isFloat64()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isDecimal128()) + { + const auto & dtype = typeid_cast *>(type.get()); + columns[i] = convert_and_insert_array(col, cursor, count, dtype->getScale()); + } + else if (which.isDecimal256()) + { + const auto & dtype = typeid_cast *>(type.get()); + columns[i] = convert_and_insert_array(col, cursor, count, dtype->getScale()); + } + else if (which.isDateTime()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isDateTime64()) + columns[i] = convert_and_insert_array(col, cursor, count); + else if (which.isString()) + columns[i] = convert_and_insert_array(col, cursor, count); + else + throw Exception(ErrorCodes::BAD_TYPE_OF_FIELD, "Unsupported type {} for column {}", type->getName(), col.name); + + if (logger->debug()) + { + // log first 10 rows of the column + std::stringstream ss; + LOG_DEBUG(logger, "Column {} structure: {}", col.name, columns[i]->dumpStructure()); + for (size_t j = 0; j < std::min(count, static_cast(10)); ++j) + { + Field value; + columns[i]->get(j, value); + ss << toString(value) << ", "; + } + LOG_DEBUG(logger, "Column {} data: {}", col.name, ss.str()); + } + } + catch (const Exception & e) + { + LOG_ERROR(logger, "Error processing column {}: {}", i, e.what()); + throw; + } + } + cursor += count; + + return Chunk(std::move(columns), count); +} + + +Chunk PythonSource::generate() +{ + size_t num_rows = 0; + auto names = description.sample_block.getNames(); + if (names.empty()) + return {}; + + if (isInheritsFromPyReader(data_source)) + { + PyObjectVecPtr data; + py::gil_scoped_acquire acquire; + data = std::move(castToSharedPtrVector(data_source.attr("read")(names, max_block_size))); + if (data->empty()) + return {}; + + return std::move(genChunk(num_rows, data)); + } + else + { + return std::move(scanDataToChunk()); + } +} +} diff --git a/src/Processors/Sources/PythonSource.h b/src/Processors/Sources/PythonSource.h new file mode 100644 index 00000000000..5fe1b12f817 --- /dev/null +++ b/src/Processors/Sources/PythonSource.h @@ -0,0 +1,77 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace DB +{ + +namespace py = pybind11; + +class PyReader; + + +class PythonSource : public ISource +{ +public: + PythonSource( + py::object & data_source_, + const Block & sample_block_, + PyColumnVecPtr column_cache, + size_t data_source_row_count, + size_t max_block_size_, + size_t stream_index, + size_t num_streams); + + ~PythonSource() override = default; + + String getName() const override { return "Python"; } + Chunk genChunk(size_t & num_rows, PyObjectVecPtr data); + Chunk generate() override; + + +private: + py::object & data_source; // Do not own the reference + + Block sample_block; + PyColumnVecPtr column_cache; + size_t data_source_row_count; + const UInt64 max_block_size; + // Caller will only pass stream index and total stream count + // to the constructor, we need to calculate the start offset and end offset. + const size_t stream_index; + const size_t num_streams; + size_t cursor; + + Poco::Logger * logger = &Poco::Logger::get("TableFunctionPython"); + ExternalResultDescription description; + + PyObjectVecPtr scanData(const py::object & data, const std::vector & col_names, size_t & cursor, size_t count); + template + ColumnPtr convert_and_insert_array(const ColumnWrapper & col_wrap, size_t & cursor, size_t count, UInt32 scale = 0); + template + ColumnPtr convert_and_insert(const py::object & obj, UInt32 scale = 0); + template + void insert_from_ptr(const void * ptr, const MutableColumnPtr & column, size_t offset, size_t row_count); + + void convert_string_array_to_block(PyObject ** buf, const MutableColumnPtr & column, size_t offset, size_t row_count); + + + template + void insert_from_list(const py::list & obj, const MutableColumnPtr & column); + + void insert_string_from_array(py::handle obj, const MutableColumnPtr & column); + + void insert_string_from_array_raw(PyObject ** buf, const MutableColumnPtr & column, size_t offset, size_t row_count); + void prepareColumnCache(Names & names, Columns & columns); + Chunk scanDataToChunk(); + void destory(PyObjectVecPtr & data); +}; +} diff --git a/src/Storages/StoragePython.cpp b/src/Storages/StoragePython.cpp new file mode 100644 index 00000000000..01ed814f9e0 --- /dev/null +++ b/src/Storages/StoragePython.cpp @@ -0,0 +1,344 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace DB +{ + +namespace ErrorCodes +{ +extern const int BAD_ARGUMENTS; +extern const int LOGICAL_ERROR; +extern const int BAD_TYPE_OF_FIELD; +} + + +StoragePython::StoragePython( + const StorageID & table_id_, + const ColumnsDescription & columns_, + const ConstraintsDescription & constraints_, + py::object reader_, + ContextPtr context_) + : IStorage(table_id_), data_source(reader_), WithContext(context_->getGlobalContext()) +{ + StorageInMemoryMetadata storage_metadata; + storage_metadata.setColumns(columns_); + storage_metadata.setConstraints(constraints_); + setInMemoryMetadata(storage_metadata); +} + +Pipe StoragePython::read( + const Names & column_names, + const StorageSnapshotPtr & storage_snapshot, + SelectQueryInfo & /*query_info*/, + ContextPtr /*context_*/, + QueryProcessingStage::Enum /*processed_stage*/, + size_t max_block_size, + size_t num_streams) +{ + storage_snapshot->check(column_names); + + Block sample_block = prepareSampleBlock(column_names, storage_snapshot); + + // num_streams = 3; // for chdb testing + + prepareColumnCache(column_names, sample_block.getColumns(), sample_block); + + if (isInheritsFromPyReader(data_source)) + return Pipe(std::make_shared(data_source, sample_block, column_cache, data_source_row_count, max_block_size, 0, 1)); + + Pipes pipes; + for (size_t stream = 0; stream < num_streams; ++stream) + pipes.emplace_back(std::make_shared( + data_source, sample_block, column_cache, data_source_row_count, max_block_size, stream, num_streams)); + return Pipe::unitePipes(std::move(pipes)); +} + +Block StoragePython::prepareSampleBlock(const Names & column_names, const StorageSnapshotPtr & storage_snapshot) +{ + Block sample_block; + for (const String & column_name : column_names) + { + auto column_data = storage_snapshot->metadata->getColumns().getPhysical(column_name); + sample_block.insert({column_data.type, column_data.name}); + } + return sample_block; +} + +void StoragePython::prepareColumnCache(const Names & names, const Columns & columns, const Block & sample_block) +{ + // check column cache with GIL holded + py::gil_scoped_acquire acquire; + if (column_cache == nullptr) + { + // fill in the cache + column_cache = std::make_shared(columns.size()); + for (size_t i = 0; i < columns.size(); ++i) + { + const auto & col_name = names[i]; + auto & col = (*column_cache)[i]; + col.name = col_name; + try + { + py::object col_data = data_source[py::str(col_name)]; + col.buf = const_cast(tryGetPyArray(col_data, col.data, col.py_type, col.row_count)); + if (col.buf == nullptr) + throw Exception( + ErrorCodes::PY_EXCEPTION_OCCURED, "Convert to array failed for column {} type {}", col_name, col.py_type); + col.dest_type = sample_block.getByPosition(i).type; + data_source_row_count = col.row_count; + } + catch (const Exception & e) + { + LOG_ERROR(logger, "Error processing column {}: {}", col_name, e.what()); + throw; + } + } + } +} + +ColumnsDescription StoragePython::getTableStructureFromData(py::object data_source) +{ + if (!data_source) + throw Exception(ErrorCodes::LOGICAL_ERROR, "Python reader not initialized"); + py::gil_scoped_acquire acquire; + std::vector> schema; + if (isInheritsFromPyReader(data_source)) + schema = data_source.attr("get_schema")().cast>>(); + else + schema = PyReader::getSchemaFromPyObj(data_source); + + auto * logger = &Poco::Logger::get("StoragePython"); + if (logger->debug()) + { + LOG_DEBUG(logger, "Schema content:"); + for (const auto & item : schema) + LOG_DEBUG(logger, "Column: {}, Type: {}", String(item.first), String(item.second)); + } + + NamesAndTypesList names_and_types; + + // Define regular expressions for different data types + RE2 pattern_int(R"(\bint(\d+))"); + RE2 pattern_generic_int(R"(\bint\b|)"); // Matches generic 'int' + RE2 pattern_uint(R"(\buint(\d+))"); + RE2 pattern_float(R"(\b(float|double)(\d+))"); + RE2 pattern_decimal128(R"(decimal128\((\d+),\s*(\d+)\))"); + RE2 pattern_decimal256(R"(decimal256\((\d+),\s*(\d+)\))"); + RE2 pattern_date32(R"(\bdate32\b)"); + RE2 pattern_date64(R"(\bdate64\b)"); + RE2 pattern_time32(R"(\btime32\b)"); + RE2 pattern_time64_us(R"(\btime64\[us\]\b)"); + RE2 pattern_time64_ns(R"(\btime64\[ns\]\b||str|DataType\(string\)|DataType\(binary\)|binary\[pyarrow\]|dtype\[object_\]|dtype\('S|dtype\('O'\))"); + + // Iterate through each pair of name and type string in the schema + for (const auto & [name, typeStr] : schema) + { + std::shared_ptr data_type; + + std::string bits, precision, scale; + if (RE2::PartialMatch(typeStr, pattern_int, &bits)) + { + if (bits == "8") + data_type = std::make_shared(); + else if (bits == "16") + data_type = std::make_shared(); + else if (bits == "32") + data_type = std::make_shared(); + else if (bits == "64") + data_type = std::make_shared(); + else if (bits == "128") + data_type = std::make_shared(); + else if (bits == "256") + data_type = std::make_shared(); + } + else if (RE2::PartialMatch(typeStr, pattern_uint, &bits)) + { + if (bits == "8") + data_type = std::make_shared(); + else if (bits == "16") + data_type = std::make_shared(); + else if (bits == "32") + data_type = std::make_shared(); + else if (bits == "64") + data_type = std::make_shared(); + else if (bits == "128") + data_type = std::make_shared(); + else if (bits == "256") + data_type = std::make_shared(); + } + else if (RE2::PartialMatch(typeStr, pattern_generic_int)) + { + data_type = std::make_shared(); // Default to 64-bit integers for generic 'int' + } + else if (RE2::PartialMatch(typeStr, pattern_float, &bits)) + { + if (bits == "32") + data_type = std::make_shared(); + else if (bits == "64") + data_type = std::make_shared(); + } + else if (RE2::PartialMatch(typeStr, pattern_decimal128, &precision, &scale)) + { + data_type = std::make_shared(std::stoi(precision), std::stoi(scale)); + } + else if (RE2::PartialMatch(typeStr, pattern_decimal256, &precision, &scale)) + { + data_type = std::make_shared(std::stoi(precision), std::stoi(scale)); + } + else if (RE2::PartialMatch(typeStr, pattern_date32)) + { + data_type = std::make_shared(); + } + else if (RE2::PartialMatch(typeStr, pattern_date64)) + { + data_type = std::make_shared(3); // date64 corresponds to DateTime64(3) + } + else if (RE2::PartialMatch(typeStr, pattern_time32)) + { + data_type = std::make_shared(); + } + else if (RE2::PartialMatch(typeStr, pattern_time64_us)) + { + data_type = std::make_shared(6); // time64[us] corresponds to DateTime64(6) + } + else if (RE2::PartialMatch(typeStr, pattern_time64_ns)) + { + data_type = std::make_shared(9); // time64[ns] corresponds to DateTime64(9) + } + else if (RE2::PartialMatch(typeStr, pattern_string_binary)) + { + data_type = std::make_shared(); + } + else + { + throw Exception(ErrorCodes::TYPE_MISMATCH, "Unrecognized data type: {}", typeStr); + } + + names_and_types.push_back({name, data_type}); + } + + return ColumnsDescription(names_and_types); +} + +std::vector> PyReader::getSchemaFromPyObj(const py::object data) +{ + std::vector> schema; + if (!py::hasattr(data, "__class__")) + { + throw Exception( + ErrorCodes::UNKNOWN_FORMAT, "Unknown data type for schema inference. Consider inheriting PyReader and overriding getSchema()."); + } + + auto type_name = data.attr("__class__").attr("__name__").cast(); + + if (py::isinstance(data)) + { + // If the data is a Python dictionary + for (auto item : data.cast()) + { + std::string key = py::str(item.first).cast(); + py::list values = py::cast(item.second); + std::string dtype = py::str(values[0].attr("__class__").attr("__name__")).cast(); + if (!values.empty()) + schema.emplace_back(key, dtype); + } + return schema; + } + + if (py::hasattr(data, "dtypes")) + { + // If the data is a Pandas DataFrame + py::object dtypes = data.attr("dtypes"); + py::list columns = data.attr("columns"); + for (size_t i = 0; i < py::len(columns); ++i) + { + std::string name = py::str(columns[i]).cast(); + std::string dtype = py::str(py::repr(dtypes[columns[i]])).cast(); + schema.emplace_back(name, dtype); + } + return schema; + } + + if (py::hasattr(data, "schema")) + { + // If the data is a Pyarrow Table + py::object tbl_schema = data.attr("schema"); + auto names = tbl_schema.attr("names").cast(); + auto types = tbl_schema.attr("types").cast(); + for (size_t i = 0; i < py::len(names); ++i) + { + std::string name = py::str(names[i]).cast(); + std::string dtype = py::str(types[i]).cast(); + schema.emplace_back(name, dtype); + } + return schema; + } + + if (type_name == "recarray") + { + // if it's numpy.recarray + py::object dtype = data.attr("dtype"); + py::list fields = dtype.attr("fields"); + py::dict fields_dict = fields.cast(); + // fields_dict looks like: + // {'TIME': (dtype('int64'), 0), + // 'FX' : (dtype('int64'), 8), + // 'FY' : (dtype('int64'), 16), + // 'FZ' : (dtype('S68'), 24)} + for (auto field : fields_dict) + { + std::string name = field.first.cast(); + std::string dtype_str = py::str(field.second).cast(); + schema.emplace_back(name, dtype_str); + } + return schema; + } + + throw Exception( + ErrorCodes::UNKNOWN_FORMAT, + "Unknown data type {} for schema inference. Consider inheriting PyReader and overriding getSchema().", + py::str(data.attr("__class__")).cast()); +} + +void registerStoragePython(StorageFactory & factory) +{ + factory.registerStorage( + "Python", + [](const StorageFactory::Arguments & args) -> StoragePtr + { + if (args.engine_args.size() != 1) + throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Python engine requires 1 argument: PyReader object"); + + py::object reader = std::any_cast(args.engine_args[0]); + return std::make_shared(args.table_id, args.columns, args.constraints, reader, args.getLocalContext()); + }, + {.supports_settings = true, .supports_parallel_insert = false}); +} +} diff --git a/src/Storages/StoragePython.h b/src/Storages/StoragePython.h new file mode 100644 index 00000000000..219171fddd1 --- /dev/null +++ b/src/Storages/StoragePython.h @@ -0,0 +1,183 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace DB +{ + +namespace py = pybind11; + +namespace ErrorCodes +{ +extern const int UNKNOWN_FORMAT; +extern const int NOT_IMPLEMENTED; +extern const int PY_EXCEPTION_OCCURED; +} +class PyReader +{ +public: + explicit PyReader(const py::object & data) : data(data) { } + ~PyReader() + { + py::gil_scoped_acquire acquire; + if (data.is_none()) + return; + data.release(); + } + + // Read `count` rows from the data, and return a list of columns + // chdb todo: maybe return py::list is better, but this is just a shallow copy + std::vector read(const std::vector & /*col_names*/, int /*count*/) + { + throw Exception(ErrorCodes::NOT_IMPLEMENTED, "read() method is not implemented"); + } + + // // readDataPtr is similar to readData but return pointer to py::object + // static std::shared_ptr>> + // readDataPtr(const py::object & data, const std::vector & col_names, size_t & cursor, size_t count) + // { + // py::gil_scoped_acquire acquire; + // auto block = std::make_shared>>(); + // // Access columns directly by name and slice + // for (const auto & col : col_names) + // { + // py::object col_data = data[py::str(col)]; // Use dictionary-style access + // auto col_block = std::make_shared>(); + // for (size_t i = cursor; i < cursor + count; i++) + // col_block->push_back(col_data.attr("__getitem__")(i).ptr()); + // block->push_back(col_block); + // } + + // if (!block->empty()) + // cursor += py::len((*block)[0]); // Update cursor based on the length of the first column slice + + // return block; + // } + + // Return a vector of column names and their types, as a list of pairs. + // The order is important, and should match the order of the data. + // This is the default implementation, which trys to infer the schema from the every first row + // of this.data column. + // The logic is: + // 1. If the data is a map with column names as keys and column data as values, then we use + // the key and type of every first element in the value list. + // eg: + // d = {'a': [1, 2, 3], 'b': ['x', 'y', 'z'], 'c': [1.0, 1e10, 1.2e100]} + // schema = {name: repr(type(value[0])) for name, value in d.items()} + // out: + // schema = {'a': "", 'b': "", 'c': ""} + // 2. If the data is a Pandas DataFrame, then we use the column names and dtypes. + // We use the repr of the dtype, which is a string representation of the dtype. + // eg: + // df = pd.DataFrame(d) + // schema = {name: repr(dtype) for name, dtype in zip(df.columns, df.dtypes)} + // out: + // schema = {'a': "dtype('int64')", 'b': "dtype('O')", 'c': "dtype('float64')"} + // Note: + // 1. dtype('O') means object type, which is a catch-all for any types. we just treat it as string. + // 2. the dtype of a Pandas DataFrame is a numpy.dtype object, which is not a Python type object. + // + // When using Pandas >= 2.0, we can use the pyarrow as dtype_backend: + // eg: + // df_arr = pd.read_json('{"a": [1, 2, 3], "b": ["x", "y", "z"], "c": [1.0, 1.111, 2.222]}', dtype_backend="pyarrow") + // schema = {name: repr(dtype) for name, dtype in zip(df_arr.columns, df_arr.dtypes)} + // out: + // schema = {'a': 'int64[pyarrow]', 'b': 'string[pyarrow]', 'c': 'double[pyarrow]'} + // 3. if the data is a Pyarrow Table, then we use the column names and types. + // eg: + // tbl = pa.Table.from_pandas(df) + // schema = {field.name: repr(field.type) for field in tbl.schema} + // out: + // schema = {'a': 'DataType(int64)', 'b': 'DataType(string)', 'c': 'DataType(double)'} + // 4. User can override this function to provide a more accurate schema. + // eg: "DataTypeUInt8", "DataTypeUInt16", "DataTypeUInt32", "DataTypeUInt64", "DataTypeUInt128", "DataTypeUInt256", + // "DataTypeInt8", "DataTypeInt16", "DataTypeInt32", "DataTypeInt64", "DataTypeInt128", "DataTypeInt256", + // "DataTypeFloat32", "DataTypeFloat64", "DataTypeString", + + static std::vector> getSchemaFromPyObj(py::object data); + + std::vector> getSchema() { return getSchemaFromPyObj(data); } + +protected: + py::object data; +}; + +// // Trampoline class +// // see: https://pybind11.readthedocs.io/en/stable/advanced/classes.html#trampolines +// class PyReaderTrampoline : public PyReader +// { +// public: +// using PyReader::PyReader; // Inherit constructors + +// // Just forward the virtual function call to Python +// std::vector read(const std::vector & col_names, int count) override +// { +// PYBIND11_OVERRIDE_PURE( +// std::vector, // Return type List[object] +// PyReader, // Parent class +// read, // Name of the function in C++ (must match Python name) +// col_names, // Argument(s) +// count); +// } +// }; + +class StoragePython : public IStorage, public WithContext +{ +public: + StoragePython( + const StorageID & table_id_, + const ColumnsDescription & columns_, + const ConstraintsDescription & constraints_, + py::object reader_, + ContextPtr context_); + + ~StoragePython() override + { + // Destroy the reader with the GIL + py::gil_scoped_acquire acquire; + data_source.dec_ref(); + data_source.release(); + } + + std::string getName() const override { return "Python"; } + + Pipe read( + const Names & column_names, + const StorageSnapshotPtr & storage_snapshot, + SelectQueryInfo & query_info, + ContextPtr context_, + QueryProcessingStage::Enum processed_stage, + size_t max_block_size, + size_t num_streams) override; + + Block prepareSampleBlock(const Names & column_names, const StorageSnapshotPtr & storage_snapshot); + + static ColumnsDescription getTableStructureFromData(py::object data_source); + +private: + void prepareColumnCache(const Names & names, const Columns & columns, const Block & sample_block); + py::object data_source; + PyColumnVecPtr column_cache; + size_t data_source_row_count; + Poco::Logger * logger = &Poco::Logger::get("StoragePython"); +}; + +void registerStoragePython(StorageFactory & factory); + + +} diff --git a/src/Storages/registerStorages.cpp b/src/Storages/registerStorages.cpp index b971e9b623a..453bf4bab53 100644 --- a/src/Storages/registerStorages.cpp +++ b/src/Storages/registerStorages.cpp @@ -25,6 +25,8 @@ void registerStorageLiveView(StorageFactory & factory); void registerStorageGenerateRandom(StorageFactory & factory); void registerStorageExecutable(StorageFactory & factory); void registerStorageWindowView(StorageFactory & factory); +//chdb todo: add a #if USE_PYTHON here +void registerStoragePython(StorageFactory & factory); #if USE_AWS_S3 void registerStorageS3(StorageFactory & factory); @@ -123,8 +125,9 @@ void registerStorages() registerStorageGenerateRandom(factory); registerStorageExecutable(factory); registerStorageWindowView(factory); + registerStoragePython(factory); - #if USE_AWS_S3 +#if USE_AWS_S3 registerStorageS3(factory); registerStorageCOS(factory); registerStorageOSS(factory); diff --git a/src/TableFunctions/CMakeLists.txt b/src/TableFunctions/CMakeLists.txt index b02a0e79f9c..37ce96a8244 100644 --- a/src/TableFunctions/CMakeLists.txt +++ b/src/TableFunctions/CMakeLists.txt @@ -17,6 +17,41 @@ extract_into_parent_list(clickhouse_table_functions_headers dbms_headers TableFunctionFactory.h ) +# Include path from shell cmd "python3 -m pybind11 --includes" +execute_process(COMMAND python3 -m pybind11 --includes + OUTPUT_VARIABLE PYBIND11_INCLUDES + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +# Extract and set include directories specifically for source using pybind11 +string(REGEX MATCHALL "-I([^ ]+)" INCLUDE_DIRS_MATCHES ${PYBIND11_INCLUDES}) +set(PYTHON_INCLUDE_DIRS "") +foreach(INCLUDE_DIR_MATCH ${INCLUDE_DIRS_MATCHES}) + string(REGEX REPLACE "-I" "" INCLUDE_DIR_MATCH ${INCLUDE_DIR_MATCH}) + # Accumulate all include directories + set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIRS};${INCLUDE_DIR_MATCH}") +endforeach() + +# Add include directories for pybind11 +set_source_files_properties(TableFunctionPython.cpp PROPERTIES INCLUDE_DIRECTORIES "${PYTHON_INCLUDE_DIRS}") + +# remove all warning, because pybind11 will generate a lot of warning +if (OS_LINUX) + if (PYTHON_VERSION STREQUAL "python3.6" OR PYTHON_VERSION STREQUAL "python3.7" OR PYTHON_VERSION STREQUAL "python3.8") + set_source_files_properties(TableFunctionPython.cpp PROPERTIES COMPILE_FLAGS + "-w -idirafter /usr/include -include crypt.h" + ) + else() + set_source_files_properties(TableFunctionPython.cpp PROPERTIES COMPILE_FLAGS + "-w" + ) + endif() +elseif (OS_DARWIN) + set_source_files_properties(TableFunctionPython.cpp PROPERTIES COMPILE_FLAGS + "-w" + ) +endif() + add_library(clickhouse_table_functions ${clickhouse_table_functions_headers} ${clickhouse_table_functions_sources}) target_link_libraries(clickhouse_table_functions PRIVATE clickhouse_parsers clickhouse_storages_system dbms) diff --git a/src/TableFunctions/TableFunctionPython.cpp b/src/TableFunctions/TableFunctionPython.cpp new file mode 100644 index 00000000000..5a7ef58078a --- /dev/null +++ b/src/TableFunctions/TableFunctionPython.cpp @@ -0,0 +1,139 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace DB +{ + +namespace ErrorCodes +{ +extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; +extern const int PY_OBJECT_NOT_FOUND; +extern const int PY_EXCEPTION_OCCURED; +} + +// Function to find instance of PyReader, pandas DataFrame, or PyArrow Table, filtered by variable name +py::object find_instances_of_pyreader(const std::string & var_name) +{ + py::module inspect = py::module_::import("inspect"); + py::object current_frame = inspect.attr("currentframe")(); + + while (!current_frame.is_none()) + { + auto local_dict = py::reinterpret_borrow(current_frame.attr("f_locals")); + auto global_dict = py::reinterpret_borrow(current_frame.attr("f_globals")); + + for (const auto & dict : {local_dict, global_dict}) + { + if (dict.contains(var_name)) + { + py::object obj = dict[var_name.data()]; + if (isInheritsFromPyReader(obj) || isPandasDf(obj) || isPyarrowTable(obj)) + return obj; + } + } + + current_frame = current_frame.attr("f_back"); + } + + // not found + return py::none(); +} + +void TableFunctionPython::parseArguments(const ASTPtr & ast_function, ContextPtr context) +{ + py::gil_scoped_acquire acquire; + const auto & func_args = ast_function->as(); + + if (!func_args.arguments) + throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Table function 'python' must have arguments."); + + ASTs & args = func_args.arguments->children; + + if (args.size() != 1) + throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Python table requires 1 argument: PyReader object"); + + auto py_reader_arg = evaluateConstantExpressionOrIdentifierAsLiteral(args[0], context); + + try + { + // get the py_reader_arg without quotes + auto py_reader_arg_str = py_reader_arg->as().value.safeGet(); + LOG_DEBUG(logger, "Python object name: {}", py_reader_arg_str); + + // strip all quotes like '"` if any. eg. 'PyReader' -> PyReader, "PyReader" -> PyReader + py_reader_arg_str.erase( + std::remove_if(py_reader_arg_str.begin(), py_reader_arg_str.end(), [](char c) { return c == '\'' || c == '\"' || c == '`'; }), + py_reader_arg_str.end()); + + auto instance = find_instances_of_pyreader(py_reader_arg_str); + if (instance.is_none()) + throw Exception( + ErrorCodes::PY_OBJECT_NOT_FOUND, + "Python object not found in the Python environment\n" + "Ensure that the object is type of PyReader, pandas DataFrame, or PyArrow Table and is in the global or local scope"); + + LOG_DEBUG( + logger, + "Python object found in Python environment with name: {} type: {}", + py_reader_arg_str, + py::str(instance.attr("__class__")).cast()); + + reader = instance; + } + catch (py::error_already_set & e) + { + throw Exception(ErrorCodes::PY_EXCEPTION_OCCURED, e.what()); + } +} + +StoragePtr TableFunctionPython::executeImpl( + const ASTPtr & /*ast_function*/, + ContextPtr context, + const String & table_name, + ColumnsDescription /*cached_columns*/, + bool is_insert_query) const +{ + if (!reader) + throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Python data source not initialized"); + + auto columns = getActualTableStructure(context, is_insert_query); + + auto storage + = std::make_shared(StorageID(getDatabaseName(), table_name), columns, ConstraintsDescription{}, reader, context); + storage->startup(); + return storage; +} + +ColumnsDescription TableFunctionPython::getActualTableStructure(ContextPtr /*context*/, bool /*is_insert_query*/) const +{ + return StoragePython::getTableStructureFromData(reader); +} + +void registerTableFunctionPython(TableFunctionFactory & factory) +{ + factory.registerFunction( + {.documentation + = {.description = R"( +Passing Pandas DataFrame or Pyarrow Table to ClickHouse engine. +For any other data structure, you can also create a table interface to a Python data source and reads data +from a PyReader object. +This table function requires a single argument which is a PyReader object used to read data from Python. +)", + .examples = {{"1", "SELECT * FROM Python(PyReader)", ""}}}}, + TableFunctionFactory::CaseInsensitive); +} + +} diff --git a/src/TableFunctions/TableFunctionPython.h b/src/TableFunctions/TableFunctionPython.h new file mode 100644 index 00000000000..6297a1dd2ed --- /dev/null +++ b/src/TableFunctions/TableFunctionPython.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace DB +{ + +class TableFunctionPython : public ITableFunction +{ +public: + static constexpr auto name = "python"; + std::string getName() const override { return name; } + ~TableFunctionPython() override + { + // Acquire the GIL before destroying the reader object + py::gil_scoped_acquire acquire; + reader.dec_ref(); + reader.release(); + } + +private: + Poco::Logger * logger = &Poco::Logger::get("TableFunctionPython"); + StoragePtr executeImpl( + const ASTPtr & ast_function, + ContextPtr context, + const std::string & table_name, + ColumnsDescription cached_columns, + bool is_insert_query) const override; + const char * getStorageTypeName() const override { return "Python"; } + + void parseArguments(const ASTPtr & ast_function, ContextPtr context) override; + + ColumnsDescription getActualTableStructure(ContextPtr context, bool is_insert_query) const override; + py::object reader; +}; + +} diff --git a/src/TableFunctions/registerTableFunctions.cpp b/src/TableFunctions/registerTableFunctions.cpp index de29c8074b1..966020f6408 100644 --- a/src/TableFunctions/registerTableFunctions.cpp +++ b/src/TableFunctions/registerTableFunctions.cpp @@ -22,6 +22,8 @@ void registerTableFunctions() registerTableFunctionGenerate(factory); registerTableFunctionMongoDB(factory); registerTableFunctionRedis(factory); + //chdb todo: add a #if USE_PYTHON here + registerTableFunctionPython(factory); #if USE_AWS_S3 registerTableFunctionS3(factory); diff --git a/src/TableFunctions/registerTableFunctions.h b/src/TableFunctions/registerTableFunctions.h index 4e39324aba6..106c2062242 100644 --- a/src/TableFunctions/registerTableFunctions.h +++ b/src/TableFunctions/registerTableFunctions.h @@ -19,6 +19,8 @@ void registerTableFunctionInput(TableFunctionFactory & factory); void registerTableFunctionGenerate(TableFunctionFactory & factory); void registerTableFunctionMongoDB(TableFunctionFactory & factory); void registerTableFunctionRedis(TableFunctionFactory & factory); +//chdb todo: add a #if USE_PYTHON here +void registerTableFunctionPython(TableFunctionFactory & factory); #if USE_AWS_S3 void registerTableFunctionS3(TableFunctionFactory & factory); diff --git a/tests/pd_zerocopy.ipynb b/tests/pd_zerocopy.ipynb new file mode 100644 index 00000000000..97d518cb4e7 --- /dev/null +++ b/tests/pd_zerocopy.ipynb @@ -0,0 +1,1409 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Read parquet file into memory. Time cost: 1.2989869117736816 s\n", + "Parquet file size: 1395695970 bytes\n", + "Read parquet file as old pandas dataframe. Time cost: 13.909124374389648 s\n", + "Dataframe(numpy) size: 4700000128 bytes\n" + ] + } + ], + "source": [ + "#!python3\n", + "\n", + "import os\n", + "import time\n", + "import chdb\n", + "import chdb.dataframe as cdf\n", + "import pandas as pd\n", + "import numpy as np\n", + "import pyarrow as pa\n", + "import pyarrow.parquet as pq\n", + "import duckdb\n", + "\n", + "# from pyarrow.interchange import from_dataframe\n", + "from utils import current_dir\n", + "\n", + "# # if hits_0.parquet is not available, download it:\n", + "# # https://datasets.clickhouse.com/hits_compatible/athena_partitioned/hits_0.parquet\n", + "# if not os.path.exists(os.path.join(current_dir, \"hits_0.parquet\")):\n", + "# opener = urllib.request.URLopener()\n", + "# opener.addheader(\"User-Agent\", \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36\")\n", + "# opener.retrieve(\"https://datasets.clickhouse.com/hits_compatible/athena_partitioned/hits_0.parquet\",\n", + "# os.path.join(current_dir, \"hits_0.parquet\"))\n", + "\n", + "# 122MB parquet file\n", + "# hits_0 = os.path.join(current_dir, \"hits_0.parquet\")\n", + "\n", + "# 14GB parquet file\n", + "# hits_0 = os.path.join(current_dir, \"hits.parquet\")\n", + "\n", + "# 6.3GB parquet file\n", + "# hits_0 = os.path.join(current_dir, \"hits_50m.parquet\")\n", + "\n", + "# 1.3G parquet file\n", + "hits_0 = os.path.join(current_dir, \"hits1.parquet\")\n", + "\n", + "sql = \"\"\"SELECT RegionID, SUM(AdvEngineID), COUNT(*) AS c, AVG(ResolutionWidth), COUNT(DISTINCT UserID)\n", + " FROM __table__ GROUP BY RegionID ORDER BY c DESC LIMIT 10\"\"\"\n", + "\n", + "\n", + "t = time.time()\n", + "# read parquet file into memory\n", + "with open(hits_0, \"rb\") as f:\n", + " data = f.read()\n", + "print(\"Read parquet file into memory. Time cost:\", time.time() - t, \"s\")\n", + "print(\"Parquet file size:\", len(data), \"bytes\")\n", + "del data\n", + "\n", + "# read parquet file as old pandas dataframe\n", + "t = time.time()\n", + "hits = pd.read_parquet(hits_0)\n", + "print(\"Read parquet file as old pandas dataframe. Time cost:\", time.time() - t, \"s\")\n", + "print(\"Dataframe(numpy) size:\", hits.memory_usage().sum(), \"bytes\")" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 1373850796\n", + "1 1373894390\n", + "2 1373894393\n", + "3 1373894395\n", + "4 1373894426\n", + "5 1373894428\n", + "6 1373894431\n", + "7 1373839520\n", + "8 1373839671\n", + "9 1373839673\n", + "Name: EventTime, dtype: int64\n", + "0 2013-07-15 01:13:16\n", + "1 2013-07-15 13:19:50\n", + "2 2013-07-15 13:19:53\n", + "3 2013-07-15 13:19:55\n", + "4 2013-07-15 13:20:26\n", + "5 2013-07-15 13:20:28\n", + "6 2013-07-15 13:20:31\n", + "7 2013-07-14 22:05:20\n", + "8 2013-07-14 22:07:51\n", + "9 2013-07-14 22:07:53\n", + "Name: EventTime, dtype: datetime64[ns]\n", + "0 2013-07-15\n", + "1 2013-07-15\n", + "2 2013-07-15\n", + "3 2013-07-15\n", + "4 2013-07-15\n", + "5 2013-07-15\n", + "6 2013-07-15\n", + "7 2013-07-15\n", + "8 2013-07-15\n", + "9 2013-07-15\n", + "Name: EventDate, dtype: datetime64[ns]\n" + ] + }, + { + "data": { + "text/plain": [ + "WatchID int64\n", + "JavaEnable int16\n", + "Title object\n", + "GoodEvent int16\n", + "EventTime datetime64[ns]\n", + " ... \n", + "FromTag object\n", + "HasGCLID int16\n", + "RefererHash int64\n", + "URLHash int64\n", + "CLID int32\n", + "Length: 105, dtype: object" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# fix some types\n", + "print(hits[\"EventTime\"][0:10])\n", + "hits[\"EventTime\"] = pd.to_datetime(hits[\"EventTime\"], unit=\"s\")\n", + "print(hits[\"EventTime\"][0:10])\n", + "\n", + "hits[\"EventDate\"] = pd.to_datetime(hits[\"EventDate\"], unit=\"D\")\n", + "print(hits[\"EventDate\"][0:10])\n", + "\n", + "# fix all object columns to string\n", + "# for col in hits.columns:\n", + "# if hits[col].dtype == \"O\":\n", + "# hits[col] = hits[col].astype(str)\n", + "\n", + "hits.dtypes" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Convert old dataframe to numpy array. Time cost: 8.034706115722656e-05 s\n" + ] + } + ], + "source": [ + "# convert dataframe to numpy array\n", + "t = time.time()\n", + "df_npy = hits[\"RegionID\"].to_numpy()\n", + "print(\"Convert old dataframe to numpy array. Time cost:\", time.time() - t, \"s\")\n", + "del df_npy" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "class myReader(chdb.PyReader):\n", + " def __init__(self, data):\n", + " self.data = data\n", + " self.cursor = 0\n", + " super().__init__(data)\n", + "\n", + " def read(self, col_names, count):\n", + " # print(\"read\", col_names, count)\n", + " # get the columns from the data with col_names\n", + " block = [self.data[col] for col in col_names]\n", + " # print(\"columns and rows\", len(block), len(block[0]))\n", + " # get the data from the cursor to cursor + count\n", + " block = [col[self.cursor : self.cursor + count] for col in block]\n", + " # print(\"columns and rows\", len(block), len(block[0]))\n", + " # move the cursor\n", + " self.cursor += block[0].shape[0]\n", + " return block" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "queries = [\n", + "\"SELECT COUNT(*) FROM hits;\",\n", + "\"SELECT COUNT(*) FROM hits WHERE AdvEngineID <> 0;\",\n", + "\"SELECT SUM(AdvEngineID), COUNT(*), AVG(ResolutionWidth) FROM hits;\",\n", + "\"SELECT AVG(UserID) FROM hits;\",\n", + "\"SELECT COUNT(DISTINCT UserID) FROM hits;\",\n", + "\"SELECT COUNT(DISTINCT SearchPhrase) FROM hits;\",\n", + "\"SELECT MIN(EventDate), MAX(EventDate) FROM hits;\",\n", + "\"SELECT AdvEngineID, COUNT(*) FROM hits WHERE AdvEngineID <> 0 GROUP BY AdvEngineID ORDER BY COUNT(*) DESC;\",\n", + "\"SELECT RegionID, COUNT(DISTINCT UserID) AS u FROM hits GROUP BY RegionID ORDER BY u DESC LIMIT 10;\",\n", + "\"SELECT RegionID, SUM(AdvEngineID), COUNT(*) AS c, AVG(ResolutionWidth), COUNT(DISTINCT UserID) FROM hits GROUP BY RegionID ORDER BY c DESC LIMIT 10;\",\n", + "\"SELECT MobilePhoneModel, COUNT(DISTINCT UserID) AS u FROM hits WHERE MobilePhoneModel <> '' GROUP BY MobilePhoneModel ORDER BY u DESC LIMIT 10;\",\n", + "\"SELECT MobilePhone, MobilePhoneModel, COUNT(DISTINCT UserID) AS u FROM hits WHERE MobilePhoneModel <> '' GROUP BY MobilePhone, MobilePhoneModel ORDER BY u DESC LIMIT 10;\",\n", + "\"SELECT SearchPhrase, COUNT(*) AS c FROM hits WHERE SearchPhrase <> '' GROUP BY SearchPhrase ORDER BY c DESC LIMIT 10;\",\n", + "\"SELECT SearchPhrase, COUNT(DISTINCT UserID) AS u FROM hits WHERE SearchPhrase <> '' GROUP BY SearchPhrase ORDER BY u DESC LIMIT 10;\",\n", + "\"SELECT SearchEngineID, SearchPhrase, COUNT(*) AS c FROM hits WHERE SearchPhrase <> '' GROUP BY SearchEngineID, SearchPhrase ORDER BY c DESC LIMIT 10;\",\n", + "\"SELECT UserID, COUNT(*) FROM hits GROUP BY UserID ORDER BY COUNT(*) DESC LIMIT 10;\",\n", + "\"SELECT UserID, SearchPhrase, COUNT(*) FROM hits GROUP BY UserID, SearchPhrase ORDER BY COUNT(*) DESC LIMIT 10;\",\n", + "\"SELECT UserID, SearchPhrase, COUNT(*) FROM hits GROUP BY UserID, SearchPhrase LIMIT 10;\",\n", + "\"SELECT UserID, extract(minute FROM EventTime) AS m, SearchPhrase, COUNT(*) FROM hits GROUP BY UserID, m, SearchPhrase ORDER BY COUNT(*) DESC LIMIT 10;\",\n", + "\"SELECT UserID FROM hits WHERE UserID = 435090932899640449;\",\n", + "\"SELECT COUNT(*) FROM hits WHERE URL LIKE '%google%';\",\n", + "\"SELECT SearchPhrase, MIN(URL), COUNT(*) AS c FROM hits WHERE URL LIKE '%google%' AND SearchPhrase <> '' GROUP BY SearchPhrase ORDER BY c DESC LIMIT 10;\",\n", + "\"SELECT SearchPhrase, MIN(URL), MIN(Title), COUNT(*) AS c, COUNT(DISTINCT UserID) FROM hits WHERE Title LIKE '%Google%' AND URL NOT LIKE '%.google.%' AND SearchPhrase <> '' GROUP BY SearchPhrase ORDER BY c DESC LIMIT 10;\",\n", + "\"SELECT * FROM hits WHERE URL LIKE '%google%' ORDER BY EventTime LIMIT 10;\",\n", + "\"SELECT SearchPhrase FROM hits WHERE SearchPhrase <> '' ORDER BY EventTime LIMIT 10;\",\n", + "\"SELECT SearchPhrase FROM hits WHERE SearchPhrase <> '' ORDER BY SearchPhrase LIMIT 10;\",\n", + "\"SELECT SearchPhrase FROM hits WHERE SearchPhrase <> '' ORDER BY EventTime, SearchPhrase LIMIT 10;\",\n", + "\"SELECT CounterID, AVG(STRLEN(URL)) AS l, COUNT(*) AS c FROM hits WHERE URL <> '' GROUP BY CounterID HAVING COUNT(*) > 100000 ORDER BY l DESC LIMIT 25;\",\n", + "\"SELECT REGEXP_REPLACE(Referer, '^https?://(?:www\\.)?([^/]+)/.*$', '\\1') AS k, AVG(STRLEN(Referer)) AS l, COUNT(*) AS c, MIN(Referer) FROM hits WHERE Referer <> '' GROUP BY k HAVING COUNT(*) > 100000 ORDER BY l DESC LIMIT 25;\",\n", + "\"SELECT SUM(ResolutionWidth), SUM(ResolutionWidth + 1), SUM(ResolutionWidth + 2), SUM(ResolutionWidth + 3), SUM(ResolutionWidth + 4), SUM(ResolutionWidth + 5), SUM(ResolutionWidth + 6), SUM(ResolutionWidth + 7), SUM(ResolutionWidth + 8), SUM(ResolutionWidth + 9), SUM(ResolutionWidth + 10), SUM(ResolutionWidth + 11), SUM(ResolutionWidth + 12), SUM(ResolutionWidth + 13), SUM(ResolutionWidth + 14), SUM(ResolutionWidth + 15), SUM(ResolutionWidth + 16), SUM(ResolutionWidth + 17), SUM(ResolutionWidth + 18), SUM(ResolutionWidth + 19), SUM(ResolutionWidth + 20), SUM(ResolutionWidth + 21), SUM(ResolutionWidth + 22), SUM(ResolutionWidth + 23), SUM(ResolutionWidth + 24), SUM(ResolutionWidth + 25), SUM(ResolutionWidth + 26), SUM(ResolutionWidth + 27), SUM(ResolutionWidth + 28), SUM(ResolutionWidth + 29), SUM(ResolutionWidth + 30), SUM(ResolutionWidth + 31), SUM(ResolutionWidth + 32), SUM(ResolutionWidth + 33), SUM(ResolutionWidth + 34), SUM(ResolutionWidth + 35), SUM(ResolutionWidth + 36), SUM(ResolutionWidth + 37), SUM(ResolutionWidth + 38), SUM(ResolutionWidth + 39), SUM(ResolutionWidth + 40), SUM(ResolutionWidth + 41), SUM(ResolutionWidth + 42), SUM(ResolutionWidth + 43), SUM(ResolutionWidth + 44), SUM(ResolutionWidth + 45), SUM(ResolutionWidth + 46), SUM(ResolutionWidth + 47), SUM(ResolutionWidth + 48), SUM(ResolutionWidth + 49), SUM(ResolutionWidth + 50), SUM(ResolutionWidth + 51), SUM(ResolutionWidth + 52), SUM(ResolutionWidth + 53), SUM(ResolutionWidth + 54), SUM(ResolutionWidth + 55), SUM(ResolutionWidth + 56), SUM(ResolutionWidth + 57), SUM(ResolutionWidth + 58), SUM(ResolutionWidth + 59), SUM(ResolutionWidth + 60), SUM(ResolutionWidth + 61), SUM(ResolutionWidth + 62), SUM(ResolutionWidth + 63), SUM(ResolutionWidth + 64), SUM(ResolutionWidth + 65), SUM(ResolutionWidth + 66), SUM(ResolutionWidth + 67), SUM(ResolutionWidth + 68), SUM(ResolutionWidth + 69), SUM(ResolutionWidth + 70), SUM(ResolutionWidth + 71), SUM(ResolutionWidth + 72), SUM(ResolutionWidth + 73), SUM(ResolutionWidth + 74), SUM(ResolutionWidth + 75), SUM(ResolutionWidth + 76), SUM(ResolutionWidth + 77), SUM(ResolutionWidth + 78), SUM(ResolutionWidth + 79), SUM(ResolutionWidth + 80), SUM(ResolutionWidth + 81), SUM(ResolutionWidth + 82), SUM(ResolutionWidth + 83), SUM(ResolutionWidth + 84), SUM(ResolutionWidth + 85), SUM(ResolutionWidth + 86), SUM(ResolutionWidth + 87), SUM(ResolutionWidth + 88), SUM(ResolutionWidth + 89) FROM hits;\",\n", + "\"SELECT SearchEngineID, ClientIP, COUNT(*) AS c, SUM(IsRefresh), AVG(ResolutionWidth) FROM hits WHERE SearchPhrase <> '' GROUP BY SearchEngineID, ClientIP ORDER BY c DESC LIMIT 10;\",\n", + "\"SELECT WatchID, ClientIP, COUNT(*) AS c, SUM(IsRefresh), AVG(ResolutionWidth) FROM hits WHERE SearchPhrase <> '' GROUP BY WatchID, ClientIP ORDER BY c DESC LIMIT 10;\",\n", + "\"SELECT WatchID, ClientIP, COUNT(*) AS c, SUM(IsRefresh), AVG(ResolutionWidth) FROM hits GROUP BY WatchID, ClientIP ORDER BY c DESC LIMIT 10;\",\n", + "\"SELECT URL, COUNT(*) AS c FROM hits GROUP BY URL ORDER BY c DESC LIMIT 10;\",\n", + "\"SELECT 1, URL, COUNT(*) AS c FROM hits GROUP BY 1, URL ORDER BY c DESC LIMIT 10;\",\n", + "\"SELECT ClientIP, ClientIP - 1, ClientIP - 2, ClientIP - 3, COUNT(*) AS c FROM hits GROUP BY ClientIP, ClientIP - 1, ClientIP - 2, ClientIP - 3 ORDER BY c DESC LIMIT 10;\",\n", + "\"SELECT URL, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND DontCountHits = 0 AND IsRefresh = 0 AND URL <> '' GROUP BY URL ORDER BY PageViews DESC LIMIT 10;\",\n", + "\"SELECT Title, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND DontCountHits = 0 AND IsRefresh = 0 AND Title <> '' GROUP BY Title ORDER BY PageViews DESC LIMIT 10;\",\n", + "\"SELECT URL, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND IsRefresh = 0 AND IsLink <> 0 AND IsDownload = 0 GROUP BY URL ORDER BY PageViews DESC LIMIT 10 OFFSET 1000;\",\n", + "\"SELECT TraficSourceID, SearchEngineID, AdvEngineID, CASE WHEN (SearchEngineID = 0 AND AdvEngineID = 0) THEN Referer ELSE '' END AS Src, URL AS Dst, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND IsRefresh = 0 GROUP BY TraficSourceID, SearchEngineID, AdvEngineID, Src, Dst ORDER BY PageViews DESC LIMIT 10 OFFSET 1000;\",\n", + "\"SELECT URLHash, EventDate, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND IsRefresh = 0 AND TraficSourceID IN (-1, 6) AND RefererHash = 3594120000172545465 GROUP BY URLHash, EventDate ORDER BY PageViews DESC LIMIT 10 OFFSET 100;\",\n", + "\"SELECT WindowClientWidth, WindowClientHeight, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND IsRefresh = 0 AND DontCountHits = 0 AND URLHash = 2868770270353813622 GROUP BY WindowClientWidth, WindowClientHeight ORDER BY PageViews DESC LIMIT 10 OFFSET 10000;\",\n", + "\"SELECT DATE_TRUNC('minute', EventTime) AS M, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-14' AND EventDate <= '2013-07-15' AND IsRefresh = 0 AND DontCountHits = 0 GROUP BY DATE_TRUNC('minute', EventTime) ORDER BY DATE_TRUNC('minute', EventTime) LIMIT 10 OFFSET 1000;\",\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "counter = 0\n", + "def bench(sql):\n", + " global counter\n", + " con = duckdb.connect()\n", + " df_reader = myReader(hits)\n", + " duckdb_time = 0\n", + " chdb_time = 0\n", + " print(\"Q\"+str(counter)+\":\", sql)\n", + " t = time.time()\n", + " try:\n", + " ret = con.execute(sql).fetch_df()\n", + " duckdb_time = time.time() - t\n", + " print(\"DuckDB return:\", ret)\n", + " except Exception as e:\n", + " print(\"DuckDB error:\", e)\n", + " # replace 'hits' with 'Python(df_reader)'\n", + " sql = sql.replace(\"hits\", \"Python(df_reader)\")\n", + " sql = sql.replace(\"STRLEN\", \"length\")\n", + " t = time.time()\n", + " try:\n", + " ret = chdb.query(sql, \"Dataframe\")\n", + " chdb_time = time.time() - t\n", + " print(\"chDB return:\", ret)\n", + " except Exception as e:\n", + " print(\"chDB error:\", e)\n", + " counter += 1\n", + " return duckdb_time, chdb_time" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Q0: SELECT COUNT(*) FROM hits;\n", + "DuckDB return: count_star()\n", + "0 10000000\n", + "chDB return: count()\n", + "0 10000000\n", + "Q1: SELECT COUNT(*) FROM hits WHERE AdvEngineID <> 0;\n", + "DuckDB return: count_star()\n", + "0 257266\n", + "chDB return: count()\n", + "0 257266\n", + "Q2: SELECT SUM(AdvEngineID), COUNT(*), AVG(ResolutionWidth) FROM hits;\n", + "DuckDB return: sum(AdvEngineID) count_star() avg(ResolutionWidth)\n", + "0 5276263.0 10000000 1506.781497\n", + "chDB return: sum(AdvEngineID) count() avg(ResolutionWidth)\n", + "0 5276263 10000000 1506.781497\n", + "Q3: SELECT AVG(UserID) FROM hits;\n", + "DuckDB return: avg(UserID)\n", + "0 2.302915e+18\n", + "chDB return: avg(UserID)\n", + "0 -1.522547e+11\n", + "Q4: SELECT COUNT(DISTINCT UserID) FROM hits;\n", + "DuckDB return: count(DISTINCT UserID)\n", + "0 1620177\n", + "chDB return: uniqExact(UserID)\n", + "0 1620177\n", + "Q5: SELECT COUNT(DISTINCT SearchPhrase) FROM hits;\n", + "DuckDB return: count(DISTINCT SearchPhrase)\n", + "0 873731\n", + "chDB return: uniqExact(SearchPhrase)\n", + "0 873731\n", + "Q6: SELECT MIN(EventDate), MAX(EventDate) FROM hits;\n", + "DuckDB return: min(EventDate) max(EventDate)\n", + "0 2013-07-02 2013-07-31\n", + "chDB return: min(EventDate) max(EventDate)\n", + "0 2013-07-02 08:00:00+08:00 2013-07-31 08:00:00+08:00\n", + "Q7: SELECT AdvEngineID, COUNT(*) FROM hits WHERE AdvEngineID <> 0 GROUP BY AdvEngineID ORDER BY COUNT(*) DESC;\n", + "DuckDB return: AdvEngineID count_star()\n", + "0 27 107474\n", + "1 2 94688\n", + "2 45 38390\n", + "3 13 8763\n", + "4 44 7479\n", + "5 25 341\n", + "6 50 80\n", + "7 52 34\n", + "8 3 9\n", + "9 28 8\n", + "chDB return: AdvEngineID count()\n", + "0 27 107474\n", + "1 2 94688\n", + "2 45 38390\n", + "3 13 8763\n", + "4 44 7479\n", + "5 25 341\n", + "6 50 80\n", + "7 52 34\n", + "8 3 9\n", + "9 28 8\n", + "Q8: SELECT RegionID, COUNT(DISTINCT UserID) AS u FROM hits GROUP BY RegionID ORDER BY u DESC LIMIT 10;\n", + "DuckDB return: RegionID u\n", + "0 229 289257\n", + "1 2 114971\n", + "2 208 77428\n", + "3 158 41988\n", + "4 169 37128\n", + "5 34 33622\n", + "6 55 28894\n", + "7 107 26996\n", + "8 42 26944\n", + "9 32 26577\n", + "chDB return: RegionID u\n", + "0 229 289257\n", + "1 2 114971\n", + "2 208 77428\n", + "3 158 41988\n", + "4 169 37128\n", + "5 34 33622\n", + "6 55 28894\n", + "7 107 26996\n", + "8 42 26944\n", + "9 32 26577\n", + "Q9: SELECT RegionID, SUM(AdvEngineID), COUNT(*) AS c, AVG(ResolutionWidth), COUNT(DISTINCT UserID) FROM hits GROUP BY RegionID ORDER BY c DESC LIMIT 10;\n", + "DuckDB return: RegionID sum(AdvEngineID) c avg(ResolutionWidth) \\\n", + "0 229 1626324.0 2031299 1553.786671 \n", + "1 2 313589.0 877397 1423.540215 \n", + "2 208 193458.0 468731 1357.893244 \n", + "3 32 53121.0 357921 1545.596458 \n", + "4 42 83542.0 206186 1586.465808 \n", + "5 55 74805.0 194788 1420.300629 \n", + "6 158 25099.0 182178 947.637969 \n", + "7 34 95038.0 175820 1568.273206 \n", + "8 226 47675.0 145891 1586.239096 \n", + "9 36 53042.0 141420 1588.640758 \n", + "\n", + " count(DISTINCT UserID) \n", + "0 289257 \n", + "1 114971 \n", + "2 77428 \n", + "3 26577 \n", + "4 26944 \n", + "5 28894 \n", + "6 41988 \n", + "7 33622 \n", + "8 17202 \n", + "9 20111 \n", + "chDB return: RegionID sum(AdvEngineID) c avg(ResolutionWidth) \\\n", + "0 229 1626324 2031299 1553.786671 \n", + "1 2 313589 877397 1423.540215 \n", + "2 208 193458 468731 1357.893244 \n", + "3 32 53121 357921 1545.596458 \n", + "4 42 83542 206186 1586.465808 \n", + "5 55 74805 194788 1420.300629 \n", + "6 158 25099 182178 947.637969 \n", + "7 34 95038 175820 1568.273206 \n", + "8 226 47675 145891 1586.239096 \n", + "9 36 53042 141420 1588.640758 \n", + "\n", + " uniqExact(UserID) \n", + "0 289257 \n", + "1 114971 \n", + "2 77428 \n", + "3 26577 \n", + "4 26944 \n", + "5 28894 \n", + "6 41988 \n", + "7 33622 \n", + "8 17202 \n", + "9 20111 \n", + "Q10: SELECT MobilePhoneModel, COUNT(DISTINCT UserID) AS u FROM hits WHERE MobilePhoneModel <> '' GROUP BY MobilePhoneModel ORDER BY u DESC LIMIT 10;\n", + "DuckDB return: MobilePhoneModel u\n", + "0 [105, 80, 97, 100] 80774\n", + "1 [105, 80, 104, 111, 110, 101] 3568\n", + "2 [65, 53, 48, 48] 1396\n", + "3 [78, 56, 45, 48, 48] 446\n", + "4 [79, 78, 69, 32, 84, 79, 85, 67, 72, 32, 54, 4... 273\n", + "5 [105, 80, 104, 111] 196\n", + "6 [51, 49, 49, 48, 48, 48, 48] 144\n", + "7 [71, 84, 45, 80, 55, 51, 48, 48, 66] 139\n", + "8 [71, 84, 45, 73, 57, 53, 48, 48] 131\n", + "9 [101, 97, 103, 108, 101, 55, 53] 131\n", + "chDB return: MobilePhoneModel u\n", + "0 iPad 80774\n", + "1 iPhone 3568\n", + "2 A500 1396\n", + "3 N8-00 446\n", + "4 ONE TOUCH 6030A 273\n", + "5 iPho 196\n", + "6 3110000 144\n", + "7 GT-P7300B 139\n", + "8 eagle75 131\n", + "9 GT-I9500 131\n", + "Q11: SELECT MobilePhone, MobilePhoneModel, COUNT(DISTINCT UserID) AS u FROM hits WHERE MobilePhoneModel <> '' GROUP BY MobilePhone, MobilePhoneModel ORDER BY u DESC LIMIT 10;\n", + "DuckDB return: MobilePhone MobilePhoneModel u\n", + "0 1 [105, 80, 97, 100] 68519\n", + "1 5 [105, 80, 97, 100] 3788\n", + "2 6 [105, 80, 97, 100] 2210\n", + "3 7 [105, 80, 97, 100] 1980\n", + "4 118 [65, 53, 48, 48] 1394\n", + "5 26 [105, 80, 104, 111, 110, 101] 1058\n", + "6 6 [105, 80, 104, 111, 110, 101] 1039\n", + "7 10 [105, 80, 97, 100] 965\n", + "8 13 [105, 80, 97, 100] 770\n", + "9 32 [105, 80, 97, 100] 746\n", + "chDB return: MobilePhone MobilePhoneModel u\n", + "0 1 iPad 68519\n", + "1 5 iPad 3788\n", + "2 6 iPad 2210\n", + "3 7 iPad 1980\n", + "4 118 A500 1394\n", + "5 26 iPhone 1058\n", + "6 6 iPhone 1039\n", + "7 10 iPad 965\n", + "8 13 iPad 770\n", + "9 32 iPad 746\n", + "Q12: SELECT SearchPhrase, COUNT(*) AS c FROM hits WHERE SearchPhrase <> '' GROUP BY SearchPhrase ORDER BY c DESC LIMIT 10;\n", + "DuckDB return: SearchPhrase c\n", + "0 [208, 178, 208, 181, 208, 180, 208, 190, 208, ... 4947\n", + "1 [209, 129, 208, 188, 208, 190, 209, 130, 209, ... 3338\n", + "2 [209, 129, 208, 188, 208, 190, 209, 130, 209, ... 2553\n", + "3 [208, 178, 208, 181, 208, 180, 208, 190, 208, ... 2473\n", + "4 [208, 178, 208, 181, 208, 180, 208, 190, 208, ... 2032\n", + "5 [208, 178, 208, 181, 208, 180, 208, 190, 208, ... 1686\n", + "6 [208, 187, 209, 142, 208, 186, 209, 129, 32, 5... 1559\n", + "7 [208, 190, 209, 130, 208, 180, 209, 139, 209, ... 1272\n", + "8 [209, 130, 208, 176, 209, 135, 208, 186, 208, ... 1248\n", + "9 [209, 128, 208, 181, 209, 134, 208, 181, 208, ... 1244\n", + "chDB return: SearchPhrase c\n", + "0 ведомосквы вместу 4947\n", + "1 смотреть онлайн бесплатно 3338\n", + "2 смотреть онлайн 2553\n", + "3 ведомосквы вы из 2473\n", + "4 ведомосквиталия страции 2032\n", + "5 ведомосковский 1686\n", + "6 люкс 20 иномаровск 1559\n", + "7 отдых в кино 1272\n", + "8 тачки рецепт собстве 1248\n", + "9 рецепты сбербан 1244\n", + "Q13: SELECT SearchPhrase, COUNT(DISTINCT UserID) AS u FROM hits WHERE SearchPhrase <> '' GROUP BY SearchPhrase ORDER BY u DESC LIMIT 10;\n", + "DuckDB return: SearchPhrase u\n", + "0 [209, 129, 208, 188, 208, 190, 209, 130, 209, ... 2717\n", + "1 [209, 129, 208, 188, 208, 190, 209, 130, 209, ... 2085\n", + "2 [208, 178, 208, 181, 208, 180, 208, 190, 208, ... 1385\n", + "3 [208, 187, 209, 142, 208, 186, 209, 129, 32, 5... 1190\n", + "4 [209, 129, 208, 188, 208, 190, 209, 130, 209, ... 1031\n", + "5 [208, 181, 208, 177, 209, 131, 209, 130, 209, ... 1007\n", + "6 [208, 181, 208, 177, 209, 131, 209, 130, 209, ... 978\n", + "7 [209, 129, 208, 188, 208, 190, 209, 130, 209, ... 953\n", + "8 [209, 128, 208, 181, 209, 134, 208, 181, 208, ... 909\n", + "9 [209, 132, 45, 49] 894\n", + "chDB return: SearchPhrase u\n", + "0 смотреть онлайн бесплатно 2717\n", + "1 смотреть онлайн 2085\n", + "2 ведомосквы вместу 1385\n", + "3 люкс 20 иномаровск 1190\n", + "4 смотреть 1031\n", + "5 ебутсы арениксандройд полнечный 1007\n", + "6 ебутсы для 978\n", + "7 смотреть онлайн бесплатно в хорошем 953\n", + "8 рецепты сбербан 909\n", + "9 ф-1 894\n", + "Q14: SELECT SearchEngineID, SearchPhrase, COUNT(*) AS c FROM hits WHERE SearchPhrase <> '' GROUP BY SearchEngineID, SearchPhrase ORDER BY c DESC LIMIT 10;\n", + "DuckDB return: SearchEngineID SearchPhrase c\n", + "0 2 [208, 178, 208, 181, 208, 180, 208, 190, 208, ... 3480\n", + "1 2 [209, 129, 208, 188, 208, 190, 209, 130, 209, ... 2194\n", + "2 2 [208, 178, 208, 181, 208, 180, 208, 190, 208, ... 1859\n", + "3 2 [208, 178, 208, 181, 208, 180, 208, 190, 208, ... 1682\n", + "4 2 [209, 129, 208, 188, 208, 190, 209, 130, 209, ... 1540\n", + "5 2 [208, 178, 208, 181, 208, 180, 208, 190, 208, ... 1440\n", + "6 95 [208, 190, 209, 130, 208, 180, 209, 139, 209, ... 1261\n", + "7 2 [208, 187, 209, 142, 208, 186, 209, 129, 32, 5... 1257\n", + "8 2 [209, 128, 208, 181, 209, 134, 208, 181, 208, ... 1172\n", + "9 4 [208, 191, 208, 190, 208, 186, 208, 181, 209, ... 959\n", + "chDB return: SearchEngineID SearchPhrase c\n", + "0 2 ведомосквы вместу 3480\n", + "1 2 смотреть онлайн бесплатно 2194\n", + "2 2 ведомосквы вы из 1859\n", + "3 2 ведомосковский 1682\n", + "4 2 смотреть онлайн 1540\n", + "5 2 ведомосквиталия страции 1440\n", + "6 95 отдых в кино 1261\n", + "7 2 люкс 20 иномаровск 1257\n", + "8 2 рецепты сбербан 1172\n", + "9 4 покеты рецепт засня 959\n", + "Q15: SELECT UserID, COUNT(*) FROM hits GROUP BY UserID ORDER BY COUNT(*) DESC LIMIT 10;\n", + "DuckDB return: UserID count_star()\n", + "0 1313338681122956954 29097\n", + "1 1907779576417363396 16854\n", + "2 2305303682471783379 10588\n", + "3 6103038218306105832 2994\n", + "4 3631826469396741283 2828\n", + "5 6949028786848070043 2496\n", + "6 2035345969173555084 2261\n", + "7 517714522250745823 2119\n", + "8 6762020047108358913 2051\n", + "9 6718662516719813769 1678\n", + "chDB return: UserID count()\n", + "0 1313338681122956954 29097\n", + "1 1907779576417363396 16854\n", + "2 2305303682471783379 10588\n", + "3 6103038218306105832 2994\n", + "4 3631826469396741283 2828\n", + "5 6949028786848070043 2496\n", + "6 2035345969173555084 2261\n", + "7 517714522250745823 2119\n", + "8 6762020047108358913 2051\n", + "9 6718662516719813769 1678\n", + "Q16: SELECT UserID, SearchPhrase, COUNT(*) FROM hits GROUP BY UserID, SearchPhrase ORDER BY COUNT(*) DESC LIMIT 10;\n", + "DuckDB return: UserID SearchPhrase count_star()\n", + "0 1313338681122956954 [] 29097\n", + "1 1907779576417363396 [] 16854\n", + "2 2305303682471783379 [] 10588\n", + "3 6103038218306105832 [] 2994\n", + "4 3631826469396741283 [] 2827\n", + "5 6949028786848070043 [] 2496\n", + "6 2035345969173555084 [] 2259\n", + "7 517714522250745823 [] 2119\n", + "8 6762020047108358913 [] 2051\n", + "9 6718662516719813769 [] 1651\n", + "chDB return: UserID SearchPhrase count()\n", + "0 1313338681122956954 29097\n", + "1 1907779576417363396 16854\n", + "2 2305303682471783379 10588\n", + "3 6103038218306105832 2994\n", + "4 3631826469396741283 2827\n", + "5 6949028786848070043 2496\n", + "6 2035345969173555084 2259\n", + "7 517714522250745823 2119\n", + "8 6762020047108358913 2051\n", + "9 6718662516719813769 1651\n", + "Q17: SELECT UserID, SearchPhrase, COUNT(*) FROM hits GROUP BY UserID, SearchPhrase LIMIT 10;\n", + "DuckDB return: UserID SearchPhrase \\\n", + "0 -5627973928080731456 [208, 188, 208, 190, 208, 179, 209, 131, 209, ... \n", + "1 -5559699448450058766 [] \n", + "2 -5528876654789979294 [] \n", + "3 -5470057502286193376 [] \n", + "4 -5375069617527156279 [] \n", + "5 -5330171504170722833 [] \n", + "6 -5317883671594541868 [] \n", + "7 -5306916608111263156 [209, 128, 208, 181, 209, 134, 208, 181, 208, ... \n", + "8 -5300394725647264452 [] \n", + "9 -5255231155009379631 [] \n", + "\n", + " count_star() \n", + "0 1 \n", + "1 7 \n", + "2 51 \n", + "3 6 \n", + "4 2 \n", + "5 2 \n", + "6 24 \n", + "7 1 \n", + "8 2 \n", + "9 2 \n", + "chDB return: UserID SearchPhrase \\\n", + "0 1666914814759040438 ареньера фабриколести нижний вволге \n", + "1 5319950495870793034 \n", + "2 5742717625414611048 \n", + "3 896421534586754490 \n", + "4 4581954397323777304 \n", + "5 4858662943892668247 ники из как манипу \n", + "6 5347912626652471260 порядом 2 2013 ворождения на двернушка 8 месяц \n", + "7 4117481054795982924 \n", + "8 2305483527112189819 маленькина leifheitdsq \n", + "9 3552892264426602525 \n", + "\n", + " count() \n", + "0 1 \n", + "1 17 \n", + "2 8 \n", + "3 1 \n", + "4 2 \n", + "5 1 \n", + "6 1 \n", + "7 40 \n", + "8 1 \n", + "9 1 \n", + "Q18: SELECT UserID, extract(minute FROM EventTime) AS m, SearchPhrase, COUNT(*) FROM hits GROUP BY UserID, m, SearchPhrase ORDER BY COUNT(*) DESC LIMIT 10;\n", + "DuckDB return: UserID m SearchPhrase count_star()\n", + "0 1313338681122956954 31 [] 589\n", + "1 1313338681122956954 28 [] 578\n", + "2 1313338681122956954 29 [] 572\n", + "3 1313338681122956954 33 [] 567\n", + "4 1313338681122956954 27 [] 557\n", + "5 1313338681122956954 32 [] 554\n", + "6 1313338681122956954 30 [] 552\n", + "7 1313338681122956954 34 [] 546\n", + "8 1313338681122956954 26 [] 540\n", + "9 1313338681122956954 10 [] 539\n", + "chDB return: UserID m SearchPhrase count()\n", + "0 1313338681122956954 31 589\n", + "1 1313338681122956954 28 578\n", + "2 1313338681122956954 29 572\n", + "3 1313338681122956954 33 567\n", + "4 1313338681122956954 27 557\n", + "5 1313338681122956954 32 554\n", + "6 1313338681122956954 30 552\n", + "7 1313338681122956954 34 546\n", + "8 1313338681122956954 26 540\n", + "9 1313338681122956954 10 539\n", + "Q19: SELECT UserID FROM hits WHERE UserID = 435090932899640449;\n", + "DuckDB return: Empty DataFrame\n", + "Columns: [UserID]\n", + "Index: []\n", + "chDB return: Empty DataFrame\n", + "Columns: [UserID]\n", + "Index: []\n", + "Q20: SELECT COUNT(*) FROM hits WHERE URL LIKE '%google%';\n", + "DuckDB error: Binder Error: No function matches the given name and argument types '~~(BLOB, STRING_LITERAL)'. You might need to add explicit type casts.\n", + "\tCandidate functions:\n", + "\t~~(VARCHAR, VARCHAR) -> BOOLEAN\n", + "\n", + "LINE 1: SELECT COUNT(*) FROM hits WHERE URL LIKE '%google%';\n", + " ^\n", + "chDB return: count()\n", + "0 621\n", + "Q21: SELECT SearchPhrase, MIN(URL), COUNT(*) AS c FROM hits WHERE URL LIKE '%google%' AND SearchPhrase <> '' GROUP BY SearchPhrase ORDER BY c DESC LIMIT 10;\n", + "DuckDB error: Binder Error: No function matches the given name and argument types '~~(BLOB, STRING_LITERAL)'. You might need to add explicit type casts.\n", + "\tCandidate functions:\n", + "\t~~(VARCHAR, VARCHAR) -> BOOLEAN\n", + "\n", + "LINE 1: ...RL), COUNT(*) AS c FROM hits WHERE URL LIKE '%google%' AND SearchPhrase <> '' ...\n", + " ^\n", + "chDB return: SearchPhrase \\\n", + "0 зачать онлайн бесплатно \n", + "1 ани пух ходу \n", + "2 комбактерина кабачки в крополь интерном сад тю... \n", + "3 строитель верси джейкоциты вычета \n", + "4 один инструктура птахани нюши смотреть краси \n", + "5 как миксетин инструкция общая \n", + "6 в август 247 грустимошка на кристрат \n", + "7 славлять породится отели 2013 смотреть \n", + "8 лога в змеиновосибирске в хорошем качестве вне... \n", + "9 михайловар для андроизводские новок \n", + "\n", + " min(URL) c \n", + "0 http://tienskaia-moda-brietielkakh-2%2F%2Fwww.... 2 \n", + "1 http://interinburg/detail.google,yandex.aspx#l... 2 \n", + "2 http://samara.irr.ru/catalog_googleTBR%26ad%3D... 2 \n", + "3 http://ru.tv/smsarhiv/num-9/nf-3/csrf-39818/go... 2 \n", + "4 http://bdsm_position/2624217,2013-07-01:2013/f... 2 \n", + "5 http://samara.irr.ru/catalog_googleMBR%26ad%3D... 2 \n", + "6 http://tienskaia-moda-briuki/google.ru/~apok.r... 1 \n", + "7 http:%2F%2Fvk.com.ua/google-jarkovskaya-Lipeckd 1 \n", + "8 http://tienskaia-moda-briez%2F&sr=http://voron... 1 \n", + "9 http://psyche.html?1=1&cid=577&oki=1&option=Ju... 1 \n", + "Q22: SELECT SearchPhrase, MIN(URL), MIN(Title), COUNT(*) AS c, COUNT(DISTINCT UserID) FROM hits WHERE Title LIKE '%Google%' AND URL NOT LIKE '%.google.%' AND SearchPhrase <> '' GROUP BY SearchPhrase ORDER BY c DESC LIMIT 10;\n", + "DuckDB error: Binder Error: No function matches the given name and argument types '~~(BLOB, STRING_LITERAL)'. You might need to add explicit type casts.\n", + "\tCandidate functions:\n", + "\t~~(VARCHAR, VARCHAR) -> BOOLEAN\n", + "\n", + "LINE 1: ...DISTINCT UserID) FROM hits WHERE Title LIKE '%Google%' AND URL NOT LIKE '%.goo...\n", + " ^\n", + "chDB return: SearchPhrase \\\n", + "0 коптимиквиды юриста с роуз рая \n", + "1 ведомосквы вместу \n", + "2 коптимиквиды юрий жд ворожные моем \n", + "3 заделать магнездо \n", + "4 вспомидоры,отека обучение стека \n", + "5 авторы для jimm f/4-5.6 dc union arkham текст \n", + "6 ведомосквиталия страции \n", + "7 вспышки нижний эльдар \n", + "8 создать+новосибируюсь песни летние \n", + "9 коптимизаностиницы \n", + "\n", + " min(URL) \\\n", + "0 https://produkty%2Fpulove.ru/booklyattion-war-... \n", + "1 http://mysw.info/newsru.ru/compatible \n", + "2 https://produkty%2Fpulove.ru/booklyattion-war-... \n", + "3 http://auto.ria.ua/search/ab_district=1&cid=57... \n", + "4 https://produkty%2Fpulove.ru/booklyattion-war-... \n", + "5 http://nn.jobinmoscow.ru/real-estate/rent/Sroc... \n", + "6 https://produkty%2Fpulove.ru/booklyattion-war-... \n", + "7 http://mysw.info/newsru.ru/compatible \n", + "8 http://auto.ria.ua/search/ab_district=1&cid=57... \n", + "9 https://produkty%2Fpulove.ru/booklyattion-war-... \n", + "\n", + " min(Title) c uniqExact(UserID) \n", + "0 Легко на участные участников., Цены - Стильная... 45 12 \n", + "1 Convent-менеджер с Google Players 1.3 кв. м.- ... 17 11 \n", + "2 Легко на участные участников., Цены - Стильная... 16 6 \n", + "3 AUTO.ria.ua: продажа | Востов-на-Дону, чашечка... 13 13 \n", + "4 Легко на участные участников., Цены - Стильная... 10 1 \n", + "5 Google Papa Rapalace Rescu - модной тканика Ас... 9 9 \n", + "6 Легко на участные участников., Цены - Стильная... 8 3 \n", + "7 Convent-менеджер с Google Players 1.3 кв. м.- ... 8 6 \n", + "8 AUTO.ria.ua: продажа | Востов-на-Дону, чашечка... 8 1 \n", + "9 Легко на участные участников., Цены - Стильная... 8 2 \n", + "Q23: SELECT * FROM hits WHERE URL LIKE '%google%' ORDER BY EventTime LIMIT 10;\n", + "DuckDB error: Binder Error: No function matches the given name and argument types '~~(BLOB, STRING_LITERAL)'. You might need to add explicit type casts.\n", + "\tCandidate functions:\n", + "\t~~(VARCHAR, VARCHAR) -> BOOLEAN\n", + "\n", + "LINE 1: SELECT * FROM hits WHERE URL LIKE '%google%' ORDER BY EventTime LIMI...\n", + " ^\n", + "chDB return: WatchID JavaEnable \\\n", + "0 7316105502961799889 1 \n", + "1 5289360038140010777 1 \n", + "2 8187290215265952247 1 \n", + "3 7067335108757864491 1 \n", + "4 9031598395811274817 1 \n", + "5 8603313135134757044 1 \n", + "6 8850598978691021476 1 \n", + "7 8139397706041785641 1 \n", + "8 7270306648984929955 1 \n", + "9 6405590155111045434 1 \n", + "\n", + " Title GoodEvent \\\n", + "0 Аренда 2 игры для женщин в интернет-магазин - ... 1 \n", + "1 Инвеста.Информленны - bonprix collection - Кош... 1 \n", + "2 Инвеста.Информленны - bonprix collection - Кош... 1 \n", + "3 Прогноз поселка - продаже Жена для руб.- Профи... 1 \n", + "4 Инвеста.Информленны - bonprix collection - Кош... 1 \n", + "5 Инвеста.Информленны - bonprix collection - Кош... 1 \n", + "6 Инвеста.Информленны - bonprix collection - Кош... 1 \n", + "7 Инвеста.Информленны - bonprix collection - Кош... 1 \n", + "8 Инвеста.Информленны - bonprix collection - Кош... 1 \n", + "9 Инвеста.Информленны - bonprix collection - Кош... 1 \n", + "\n", + " EventTime EventDate CounterID ClientIP \\\n", + "0 2013-07-02 05:27:24+08:00 2013-07-02 08:00:00+08:00 7525 1419090217 \n", + "1 2013-07-02 07:02:43+08:00 2013-07-02 08:00:00+08:00 7525 -1260511522 \n", + "2 2013-07-02 07:04:18+08:00 2013-07-02 08:00:00+08:00 7525 -1260511522 \n", + "3 2013-07-02 07:04:26+08:00 2013-07-02 08:00:00+08:00 5822 959273659 \n", + "4 2013-07-02 07:05:21+08:00 2013-07-02 08:00:00+08:00 7525 -1260511522 \n", + "5 2013-07-02 07:05:27+08:00 2013-07-02 08:00:00+08:00 7525 -1260511522 \n", + "6 2013-07-02 07:05:56+08:00 2013-07-02 08:00:00+08:00 7525 -1260511522 \n", + "7 2013-07-02 07:06:41+08:00 2013-07-02 08:00:00+08:00 7525 -1260511522 \n", + "8 2013-07-02 07:07:23+08:00 2013-07-02 08:00:00+08:00 7525 -1260511522 \n", + "9 2013-07-02 07:07:33+08:00 2013-07-02 08:00:00+08:00 7525 -1260511522 \n", + "\n", + " RegionID UserID ... UTMSource UTMMedium UTMCampaign \\\n", + "0 229 3033510353420765788 ... \n", + "1 41 3813931635822850500 ... \n", + "2 41 3813931635822850500 ... \n", + "3 32 736458148605978079 ... \n", + "4 41 3813931635822850500 ... \n", + "5 41 3813931635822850500 ... \n", + "6 41 3813931635822850500 ... \n", + "7 41 3813931635822850500 ... \n", + "8 41 3813931635822850500 ... \n", + "9 41 3813931635822850500 ... \n", + "\n", + " UTMContent UTMTerm FromTag HasGCLID RefererHash \\\n", + "0 0 -7095314016616002272 \n", + "1 0 8622994845783504296 \n", + "2 0 8622994845783504296 \n", + "3 0 -7429996293906404352 \n", + "4 0 8622994845783504296 \n", + "5 0 524931272629027392 \n", + "6 0 524931272629027392 \n", + "7 0 524931272629027392 \n", + "8 0 524931272629027392 \n", + "9 0 662346848875253897 \n", + "\n", + " URLHash CLID \n", + "0 -2039922795398915081 0 \n", + "1 441678500069920832 0 \n", + "2 441678500069920832 0 \n", + "3 -4158922421105595558 0 \n", + "4 441678500069920832 0 \n", + "5 775047382916449082 0 \n", + "6 775047382916449082 0 \n", + "7 775047382916449082 0 \n", + "8 775047382916449082 0 \n", + "9 -5547551342880266035 0 \n", + "\n", + "[10 rows x 105 columns]\n", + "Q24: SELECT SearchPhrase FROM hits WHERE SearchPhrase <> '' ORDER BY EventTime LIMIT 10;\n", + "DuckDB return: SearchPhrase\n", + "0 [209, 129, 208, 184, 208, 188, 208, 191, 209, ...\n", + "1 [208, 189, 208, 190, 209, 135, 208, 189, 208, ...\n", + "2 [208, 190, 209, 130, 208, 180, 209, 139, 209, ...\n", + "3 [209, 129, 208, 186, 208, 176, 209, 135, 208, ...\n", + "4 [208, 188, 208, 176, 209, 128, 209, 136, 208, ...\n", + "5 [208, 186, 209, 131, 208, 191, 208, 184, 209, ...\n", + "6 [208, 178, 208, 176, 208, 186, 208, 176, 208, ...\n", + "7 [208, 178, 208, 181, 208, 189, 208, 179, 209, ...\n", + "8 [48, 208, 177, 49, 32, 208, 186, 209, 131, 208...\n", + "9 [209, 129, 208, 176, 208, 189, 208, 176, 208, ...\n", + "chDB return: SearchPhrase\n", + "0 ночно китая женщины\n", + "1 симптомы регистратов\n", + "2 скачать читалию в духовке\n", + "3 отдыха чем прокат\n", + "4 маршава нибудь в омске главнованные автобаза ф...\n", + "5 купить ваз 2121099 инжира 1 сезон смотреть онл...\n", + "6 вакансионал 28 неделю вытяжного печь бабка бу ...\n", + "7 венгридический якутии видео ни\n", + "8 санандроид малининец фармарин\n", + "9 0б1 купить в парня смотреть онлайн\n", + "Q25: SELECT SearchPhrase FROM hits WHERE SearchPhrase <> '' ORDER BY SearchPhrase LIMIT 10;\n", + "DuckDB return: SearchPhrase\n", + "0 [32, 209, 129, 208, 178, 208, 181, 209, 130, 2...\n", + "1 [33, 32, 104, 101, 107, 116, 100, 102, 32, 103...\n", + "2 [36, 95, 103, 101, 116, 32, 97, 109, 50, 32, 2...\n", + "3 [36, 95, 103, 101, 116, 32, 105, 116, 32, 111,...\n", + "4 [36, 95, 103, 101, 116, 32, 108, 117, 99, 107,...\n", + "5 [36, 95, 112, 111, 115, 108, 97, 110, 100, 111...\n", + "6 [36, 95, 112, 111, 115, 116, 32, 114, 106, 107...\n", + "7 [36, 95, 112, 111, 115, 116, 97, 114, 115, 104...\n", + "8 [36, 100, 32, 208, 191, 209, 128, 208, 184, 20...\n", + "9 [36, 100, 32, 208, 191, 209, 128, 208, 184, 20...\n", + "chDB return: SearchPhrase\n", + "0 светы женске 2 сезон\n", + "1 ! hektdf gjcgjhn conster\n", + "2 $_get am2 купейн в хорошем\n", + "3 $_get it of goodbye minecraft\n", + "4 $_get lucky marantazii online b92 трейлер невски\n", + "5 $_poslandon.ru/moscow 2 торговлю\n", + "6 $_post rjktcfhtdcr\n", + "7 $_postarshippuden paris stan\n", + "8 $d причина\n", + "9 $d причина\n", + "Q26: SELECT SearchPhrase FROM hits WHERE SearchPhrase <> '' ORDER BY EventTime, SearchPhrase LIMIT 10;\n", + "DuckDB return: SearchPhrase\n", + "0 [208, 189, 208, 190, 209, 135, 208, 189, 208, ...\n", + "1 [209, 129, 208, 184, 208, 188, 208, 191, 209, ...\n", + "2 [208, 190, 209, 130, 208, 180, 209, 139, 209, ...\n", + "3 [209, 129, 208, 186, 208, 176, 209, 135, 208, ...\n", + "4 [208, 186, 209, 131, 208, 191, 208, 184, 209, ...\n", + "5 [208, 188, 208, 176, 209, 128, 209, 136, 208, ...\n", + "6 [208, 178, 208, 176, 208, 186, 208, 176, 208, ...\n", + "7 [208, 178, 208, 181, 208, 189, 208, 179, 209, ...\n", + "8 [48, 208, 177, 49, 32, 208, 186, 209, 131, 208...\n", + "9 [48, 208, 177, 49, 32, 208, 186, 209, 131, 208...\n", + "chDB return: SearchPhrase\n", + "0 ночно китая женщины\n", + "1 симптомы регистратов\n", + "2 отдыха чем прокат\n", + "3 скачать читалию в духовке\n", + "4 купить ваз 2121099 инжира 1 сезон смотреть онл...\n", + "5 маршава нибудь в омске главнованные автобаза ф...\n", + "6 вакансионал 28 неделю вытяжного печь бабка бу ...\n", + "7 венгридический якутии видео ни\n", + "8 0б1 купить без програма\n", + "9 0б1 купить в парня смотреть онлайн\n", + "Q27: SELECT CounterID, AVG(STRLEN(URL)) AS l, COUNT(*) AS c FROM hits WHERE URL <> '' GROUP BY CounterID HAVING COUNT(*) > 100000 ORDER BY l DESC LIMIT 25;\n", + "DuckDB error: Binder Error: No function matches the given name and argument types 'strlen(BLOB)'. You might need to add explicit type casts.\n", + "\tCandidate functions:\n", + "\tstrlen(VARCHAR) -> BIGINT\n", + "\n", + "LINE 1: SELECT CounterID, AVG(STRLEN(URL)) AS l, COUNT(*) AS c FROM h...\n", + " ^\n", + "chDB return: CounterID l c\n", + "0 1634 198.148049 315442\n", + "1 786 186.750714 120528\n", + "2 515 126.359674 102793\n", + "3 62 93.217962 613474\n", + "4 3922 87.880246 3861827\n", + "5 38 76.436656 507770\n", + "6 1483 71.266113 869128\n", + "7 2264 67.700580 278338\n", + "8 40367 67.641345 218299\n", + "9 1095 65.021542 363337\n", + "10 1830 64.919784 113980\n", + "11 40206 63.381008 217355\n", + "12 5822 62.768687 383161\n", + "13 1060 61.041178 252489\n", + "14 7525 58.612668 584968\n", + "Q28: SELECT REGEXP_REPLACE(Referer, '^https?://(?:www\\.)?([^/]+)/.*$', '\u0001') AS k, AVG(STRLEN(Referer)) AS l, COUNT(*) AS c, MIN(Referer) FROM hits WHERE Referer <> '' GROUP BY k HAVING COUNT(*) > 100000 ORDER BY l DESC LIMIT 25;\n", + "DuckDB error: Binder Error: No function matches the given name and argument types 'regexp_replace(BLOB, STRING_LITERAL, STRING_LITERAL)'. You might need to add explicit type casts.\n", + "\tCandidate functions:\n", + "\tregexp_replace(VARCHAR, VARCHAR, VARCHAR) -> VARCHAR\n", + "\tregexp_replace(VARCHAR, VARCHAR, VARCHAR, VARCHAR) -> VARCHAR\n", + "\n", + "LINE 1: SELECT REGEXP_REPLACE(Referer, '^https?://(?:w...\n", + " ^\n", + "chDB return: k l c min(Referer)\n", + "0 \u0001 99.401568 7697804 http://%26ad%3D1%260.html&ei=9e71d2f0b6590/3/w...\n", + "Q29: SELECT SUM(ResolutionWidth), SUM(ResolutionWidth + 1), SUM(ResolutionWidth + 2), SUM(ResolutionWidth + 3), SUM(ResolutionWidth + 4), SUM(ResolutionWidth + 5), SUM(ResolutionWidth + 6), SUM(ResolutionWidth + 7), SUM(ResolutionWidth + 8), SUM(ResolutionWidth + 9), SUM(ResolutionWidth + 10), SUM(ResolutionWidth + 11), SUM(ResolutionWidth + 12), SUM(ResolutionWidth + 13), SUM(ResolutionWidth + 14), SUM(ResolutionWidth + 15), SUM(ResolutionWidth + 16), SUM(ResolutionWidth + 17), SUM(ResolutionWidth + 18), SUM(ResolutionWidth + 19), SUM(ResolutionWidth + 20), SUM(ResolutionWidth + 21), SUM(ResolutionWidth + 22), SUM(ResolutionWidth + 23), SUM(ResolutionWidth + 24), SUM(ResolutionWidth + 25), SUM(ResolutionWidth + 26), SUM(ResolutionWidth + 27), SUM(ResolutionWidth + 28), SUM(ResolutionWidth + 29), SUM(ResolutionWidth + 30), SUM(ResolutionWidth + 31), SUM(ResolutionWidth + 32), SUM(ResolutionWidth + 33), SUM(ResolutionWidth + 34), SUM(ResolutionWidth + 35), SUM(ResolutionWidth + 36), SUM(ResolutionWidth + 37), SUM(ResolutionWidth + 38), SUM(ResolutionWidth + 39), SUM(ResolutionWidth + 40), SUM(ResolutionWidth + 41), SUM(ResolutionWidth + 42), SUM(ResolutionWidth + 43), SUM(ResolutionWidth + 44), SUM(ResolutionWidth + 45), SUM(ResolutionWidth + 46), SUM(ResolutionWidth + 47), SUM(ResolutionWidth + 48), SUM(ResolutionWidth + 49), SUM(ResolutionWidth + 50), SUM(ResolutionWidth + 51), SUM(ResolutionWidth + 52), SUM(ResolutionWidth + 53), SUM(ResolutionWidth + 54), SUM(ResolutionWidth + 55), SUM(ResolutionWidth + 56), SUM(ResolutionWidth + 57), SUM(ResolutionWidth + 58), SUM(ResolutionWidth + 59), SUM(ResolutionWidth + 60), SUM(ResolutionWidth + 61), SUM(ResolutionWidth + 62), SUM(ResolutionWidth + 63), SUM(ResolutionWidth + 64), SUM(ResolutionWidth + 65), SUM(ResolutionWidth + 66), SUM(ResolutionWidth + 67), SUM(ResolutionWidth + 68), SUM(ResolutionWidth + 69), SUM(ResolutionWidth + 70), SUM(ResolutionWidth + 71), SUM(ResolutionWidth + 72), SUM(ResolutionWidth + 73), SUM(ResolutionWidth + 74), SUM(ResolutionWidth + 75), SUM(ResolutionWidth + 76), SUM(ResolutionWidth + 77), SUM(ResolutionWidth + 78), SUM(ResolutionWidth + 79), SUM(ResolutionWidth + 80), SUM(ResolutionWidth + 81), SUM(ResolutionWidth + 82), SUM(ResolutionWidth + 83), SUM(ResolutionWidth + 84), SUM(ResolutionWidth + 85), SUM(ResolutionWidth + 86), SUM(ResolutionWidth + 87), SUM(ResolutionWidth + 88), SUM(ResolutionWidth + 89) FROM hits;\n", + "DuckDB return: sum(ResolutionWidth) sum((ResolutionWidth + 1)) \\\n", + "0 1.506781e+10 1.507781e+10 \n", + "\n", + " sum((ResolutionWidth + 2)) sum((ResolutionWidth + 3)) \\\n", + "0 1.508781e+10 1.509781e+10 \n", + "\n", + " sum((ResolutionWidth + 4)) sum((ResolutionWidth + 5)) \\\n", + "0 1.510781e+10 1.511781e+10 \n", + "\n", + " sum((ResolutionWidth + 6)) sum((ResolutionWidth + 7)) \\\n", + "0 1.512781e+10 1.513781e+10 \n", + "\n", + " sum((ResolutionWidth + 8)) sum((ResolutionWidth + 9)) ... \\\n", + "0 1.514781e+10 1.515781e+10 ... \n", + "\n", + " sum((ResolutionWidth + 80)) sum((ResolutionWidth + 81)) \\\n", + "0 1.586781e+10 1.587781e+10 \n", + "\n", + " sum((ResolutionWidth + 82)) sum((ResolutionWidth + 83)) \\\n", + "0 1.588781e+10 1.589781e+10 \n", + "\n", + " sum((ResolutionWidth + 84)) sum((ResolutionWidth + 85)) \\\n", + "0 1.590781e+10 1.591781e+10 \n", + "\n", + " sum((ResolutionWidth + 86)) sum((ResolutionWidth + 87)) \\\n", + "0 1.592781e+10 1.593781e+10 \n", + "\n", + " sum((ResolutionWidth + 88)) sum((ResolutionWidth + 89)) \n", + "0 1.594781e+10 1.595781e+10 \n", + "\n", + "[1 rows x 90 columns]\n", + "chDB return: sum(ResolutionWidth) sum(plus(ResolutionWidth, 1)) \\\n", + "0 15067814968 15077814968 \n", + "\n", + " sum(plus(ResolutionWidth, 2)) sum(plus(ResolutionWidth, 3)) \\\n", + "0 15087814968 15097814968 \n", + "\n", + " sum(plus(ResolutionWidth, 4)) sum(plus(ResolutionWidth, 5)) \\\n", + "0 15107814968 15117814968 \n", + "\n", + " sum(plus(ResolutionWidth, 6)) sum(plus(ResolutionWidth, 7)) \\\n", + "0 15127814968 15137814968 \n", + "\n", + " sum(plus(ResolutionWidth, 8)) sum(plus(ResolutionWidth, 9)) ... \\\n", + "0 15147814968 15157814968 ... \n", + "\n", + " sum(plus(ResolutionWidth, 80)) sum(plus(ResolutionWidth, 81)) \\\n", + "0 15867814968 15877814968 \n", + "\n", + " sum(plus(ResolutionWidth, 82)) sum(plus(ResolutionWidth, 83)) \\\n", + "0 15887814968 15897814968 \n", + "\n", + " sum(plus(ResolutionWidth, 84)) sum(plus(ResolutionWidth, 85)) \\\n", + "0 15907814968 15917814968 \n", + "\n", + " sum(plus(ResolutionWidth, 86)) sum(plus(ResolutionWidth, 87)) \\\n", + "0 15927814968 15937814968 \n", + "\n", + " sum(plus(ResolutionWidth, 88)) sum(plus(ResolutionWidth, 89)) \n", + "0 15947814968 15957814968 \n", + "\n", + "[1 rows x 90 columns]\n", + "Q30: SELECT SearchEngineID, ClientIP, COUNT(*) AS c, SUM(IsRefresh), AVG(ResolutionWidth) FROM hits WHERE SearchPhrase <> '' GROUP BY SearchEngineID, ClientIP ORDER BY c DESC LIMIT 10;\n", + "DuckDB return: SearchEngineID ClientIP c sum(IsRefresh) avg(ResolutionWidth)\n", + "0 2 -1262139876 189 14.0 1560.063492\n", + "1 2 -927025522 187 26.0 1621.368984\n", + "2 2 -19034471 184 29.0 1734.782609\n", + "3 2 1124827693 182 90.0 1730.005495\n", + "4 95 993936935 176 0.0 1828.000000\n", + "5 2 2128431738 155 26.0 1591.477419\n", + "6 2 2145233773 151 25.0 1578.662252\n", + "7 2 -792059583 148 10.0 1683.074324\n", + "8 2 -1993532306 145 6.0 1625.655172\n", + "9 95 2031325834 138 1.0 1368.000000\n", + "chDB return: SearchEngineID ClientIP c sum(IsRefresh) avg(ResolutionWidth)\n", + "0 2 -1262139876 189 14 1560.063492\n", + "1 2 -927025522 187 26 1621.368984\n", + "2 2 -19034471 184 29 1734.782609\n", + "3 2 1124827693 182 90 1730.005495\n", + "4 95 993936935 176 0 1828.000000\n", + "5 2 2128431738 155 26 1591.477419\n", + "6 2 2145233773 151 25 1578.662252\n", + "7 2 -792059583 148 10 1683.074324\n", + "8 2 -1993532306 145 6 1625.655172\n", + "9 95 2031325834 138 1 1368.000000\n", + "Q31: SELECT WatchID, ClientIP, COUNT(*) AS c, SUM(IsRefresh), AVG(ResolutionWidth) FROM hits WHERE SearchPhrase <> '' GROUP BY WatchID, ClientIP ORDER BY c DESC LIMIT 10;\n", + "DuckDB return: WatchID ClientIP c sum(IsRefresh) avg(ResolutionWidth)\n", + "0 7668931906021847229 -1341721422 1 0.0 1368.0\n", + "1 7165456824243544940 -497906719 1 1.0 1368.0\n", + "2 7274491739174625216 -415569899 1 0.0 1368.0\n", + "3 7406021713284022826 1717291897 1 0.0 1368.0\n", + "4 7299732091516868359 -1664378212 1 1.0 1917.0\n", + "5 4637080173602452460 1171287087 1 0.0 1368.0\n", + "6 5623647906101507338 1282438732 1 1.0 1368.0\n", + "7 4935551290596596970 1597930024 1 0.0 508.0\n", + "8 5356841580292029681 1895254206 1 1.0 1638.0\n", + "9 7508876853831984449 355770987 1 0.0 1368.0\n", + "chDB return: WatchID ClientIP c sum(IsRefresh) avg(ResolutionWidth)\n", + "0 6427115150554230793 736252994 1 0 1996.0\n", + "1 4965054029390764634 -1206595968 1 0 166.0\n", + "2 6030703977865133751 434911724 1 0 1996.0\n", + "3 6691203620596311846 2003800917 1 0 1087.0\n", + "4 5786133618012580033 1390766629 1 0 1368.0\n", + "5 5985454501189037066 1832002778 1 0 1638.0\n", + "6 5494909287200572026 1492278923 1 0 1828.0\n", + "7 4698453950679016700 -1916962470 1 0 1750.0\n", + "8 8745161824300249528 1528045946 1 1 1638.0\n", + "9 7352065519984549840 1557735347 1 0 1638.0\n", + "Q32: SELECT WatchID, ClientIP, COUNT(*) AS c, SUM(IsRefresh), AVG(ResolutionWidth) FROM hits GROUP BY WatchID, ClientIP ORDER BY c DESC LIMIT 10;\n", + "DuckDB return: WatchID ClientIP c sum(IsRefresh) avg(ResolutionWidth)\n", + "0 5669147813168388202 409164014 1 0.0 1087.0\n", + "1 5187536155584756374 -259055783 1 0.0 1638.0\n", + "2 7850753339231053767 1546731662 1 0.0 888.0\n", + "3 8164199526683261115 -1836087206 1 0.0 1996.0\n", + "4 6959364879658339258 -864817513 1 0.0 1087.0\n", + "5 8064063979301589313 -864817513 1 0.0 1087.0\n", + "6 6501263592117931177 1175231813 1 0.0 1996.0\n", + "7 5081318513238856894 -1675522215 1 0.0 2038.0\n", + "8 7513405411154202290 877381272 1 0.0 1368.0\n", + "9 8207609364521618888 877381272 1 0.0 1368.0\n", + "chDB return: WatchID ClientIP c sum(IsRefresh) avg(ResolutionWidth)\n", + "0 7045311802744285412 -1341502114 1 0 1996.0\n", + "1 7997911216135529594 -1050444826 1 0 1750.0\n", + "2 8844035097706011452 1902611968 1 0 0.0\n", + "3 5053190322681433435 -1147935011 1 0 1368.0\n", + "4 6157344501559484646 1722727351 1 0 1638.0\n", + "5 5256342968841438052 749361268 1 0 1638.0\n", + "6 5074356965705409073 1539704498 1 0 508.0\n", + "7 7713773151322457084 53805758 1 0 1087.0\n", + "8 4836369074268702547 2053634497 1 0 1750.0\n", + "9 4848806411334622685 2132338069 1 0 1638.0\n", + "Q33: SELECT URL, COUNT(*) AS c FROM hits GROUP BY URL ORDER BY c DESC LIMIT 10;\n", + "DuckDB return: URL c\n", + "0 [104, 116, 116, 112, 58, 47, 47, 115, 112, 45,... 100821\n", + "1 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 90604\n", + "2 [104, 116, 116, 112, 58, 37, 50, 70, 37, 50, 7... 46281\n", + "3 [104, 116, 116, 112, 58, 47, 47, 107, 111, 109... 43455\n", + "4 [104, 116, 116, 112, 58, 47, 47, 97, 102, 105,... 35161\n", + "5 [104, 116, 116, 112, 58, 47, 47, 115, 112, 45,... 31018\n", + "6 [104, 116, 116, 112, 58, 37, 50, 70, 37, 50, 7... 28878\n", + "7 [104, 116, 116, 112, 58, 47, 47, 97, 102, 105,... 26520\n", + "8 [104, 116, 116, 112, 58, 47, 47, 115, 105, 98,... 25242\n", + "9 [104, 116, 116, 112, 58, 47, 47, 115, 112, 45,... 17068\n", + "chDB return: URL c\n", + "0 http://sp-money.yandex.ru/comme%2F27.0.1453.11... 100821\n", + "1 http://irr.ru/index.php?showalbum/login-leniya... 90604\n", + "2 http:%2F%2Fdlia-zhienskaia-moda-tunika 46281\n", + "3 http://komme%2F27.0.1453.116 43455\n", + "4 http://afisha.yandex.ru/region/vacancies 35161\n", + "5 http://sp-money.yandex.ru%26target 31018\n", + "6 http:%2F%2Fwwww.bonprix.ru/mosclinindzya 28878\n", + "7 http://afisha.yandex.ru/region-ware-ne-niz%2F%... 26520\n", + "8 http://sib1.adriver 25242\n", + "9 http://sp-money.yandex.ua/search&event=little 17068\n", + "Q34: SELECT 1, URL, COUNT(*) AS c FROM hits GROUP BY 1, URL ORDER BY c DESC LIMIT 10;\n", + "DuckDB return: 1 URL c\n", + "0 1 [104, 116, 116, 112, 58, 47, 47, 115, 112, 45,... 100821\n", + "1 1 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 90604\n", + "2 1 [104, 116, 116, 112, 58, 37, 50, 70, 37, 50, 7... 46281\n", + "3 1 [104, 116, 116, 112, 58, 47, 47, 107, 111, 109... 43455\n", + "4 1 [104, 116, 116, 112, 58, 47, 47, 97, 102, 105,... 35161\n", + "5 1 [104, 116, 116, 112, 58, 47, 47, 115, 112, 45,... 31018\n", + "6 1 [104, 116, 116, 112, 58, 37, 50, 70, 37, 50, 7... 28878\n", + "7 1 [104, 116, 116, 112, 58, 47, 47, 97, 102, 105,... 26520\n", + "8 1 [104, 116, 116, 112, 58, 47, 47, 115, 105, 98,... 25242\n", + "9 1 [104, 116, 116, 112, 58, 47, 47, 115, 112, 45,... 17068\n", + "chDB return: 1 URL c\n", + "0 1 http://sp-money.yandex.ru/comme%2F27.0.1453.11... 100821\n", + "1 1 http://irr.ru/index.php?showalbum/login-leniya... 90604\n", + "2 1 http:%2F%2Fdlia-zhienskaia-moda-tunika 46281\n", + "3 1 http://komme%2F27.0.1453.116 43455\n", + "4 1 http://afisha.yandex.ru/region/vacancies 35161\n", + "5 1 http://sp-money.yandex.ru%26target 31018\n", + "6 1 http:%2F%2Fwwww.bonprix.ru/mosclinindzya 28878\n", + "7 1 http://afisha.yandex.ru/region-ware-ne-niz%2F%... 26520\n", + "8 1 http://sib1.adriver 25242\n", + "9 1 http://sp-money.yandex.ua/search&event=little 17068\n", + "Q35: SELECT ClientIP, ClientIP - 1, ClientIP - 2, ClientIP - 3, COUNT(*) AS c FROM hits GROUP BY ClientIP, ClientIP - 1, ClientIP - 2, ClientIP - 3 ORDER BY c DESC LIMIT 10;\n", + "DuckDB return: ClientIP (ClientIP - 1) (ClientIP - 2) (ClientIP - 3) c\n", + "0 -1698104457 -1698104458 -1698104459 -1698104460 29119\n", + "1 -1175819552 -1175819553 -1175819554 -1175819555 16854\n", + "2 -1206311089 -1206311090 -1206311091 -1206311092 6087\n", + "3 720685641 720685640 720685639 720685638 5420\n", + "4 1515409054 1515409053 1515409052 1515409051 4254\n", + "5 1928873128 1928873127 1928873126 1928873125 3290\n", + "6 -1323047292 -1323047293 -1323047294 -1323047295 2998\n", + "7 -1313501018 -1313501019 -1313501020 -1313501021 2746\n", + "8 1151807695 1151807694 1151807693 1151807692 2702\n", + "9 -267589304 -267589305 -267589306 -267589307 2526\n", + "chDB return: ClientIP minus(ClientIP, 1) minus(ClientIP, 2) minus(ClientIP, 3) \\\n", + "0 -1698104457 -1698104458 -1698104459 -1698104460 \n", + "1 -1175819552 -1175819553 -1175819554 -1175819555 \n", + "2 -1206311089 -1206311090 -1206311091 -1206311092 \n", + "3 720685641 720685640 720685639 720685638 \n", + "4 1515409054 1515409053 1515409052 1515409051 \n", + "5 1928873128 1928873127 1928873126 1928873125 \n", + "6 -1323047292 -1323047293 -1323047294 -1323047295 \n", + "7 -1313501018 -1313501019 -1313501020 -1313501021 \n", + "8 1151807695 1151807694 1151807693 1151807692 \n", + "9 -267589304 -267589305 -267589306 -267589307 \n", + "\n", + " c \n", + "0 29119 \n", + "1 16854 \n", + "2 6087 \n", + "3 5420 \n", + "4 4254 \n", + "5 3290 \n", + "6 2998 \n", + "7 2746 \n", + "8 2702 \n", + "9 2526 \n", + "Q36: SELECT URL, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND DontCountHits = 0 AND IsRefresh = 0 AND URL <> '' GROUP BY URL ORDER BY PageViews DESC LIMIT 10;\n", + "DuckDB return: URL PageViews\n", + "0 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 85646\n", + "1 [104, 116, 116, 112, 58, 47, 47, 107, 111, 109... 42422\n", + "2 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 15165\n", + "3 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 13779\n", + "4 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 10559\n", + "5 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 8997\n", + "6 [104, 116, 116, 112, 58, 47, 47, 107, 111, 109... 6322\n", + "7 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 3633\n", + "8 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 3363\n", + "9 [104, 116, 116, 112, 58, 47, 47, 107, 111, 109... 2538\n", + "chDB return: URL PageViews\n", + "0 http://irr.ru/index.php?showalbum/login-leniya... 85646\n", + "1 http://komme%2F27.0.1453.116 42422\n", + "2 http://irr.ru/index.php?showalbum/login-kapust... 15165\n", + "3 http://irr.ru/index.php?showalbum/login-kapust... 13779\n", + "4 http://irr.ru/index.php 10559\n", + "5 http://irr.ru/index.php?showalbum/login 8997\n", + "6 http://komme%2F27.0.1453.116 Safari%2F5.0 (com... 6322\n", + "7 http://irr.ru/index.php?showalbum/login-kupalnik 3633\n", + "8 http://irr.ru/index.php?showalbum/login-kapust... 3363\n", + "9 http://komme%2F27.0.1453.116 Safari 2538\n", + "Q37: SELECT Title, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND DontCountHits = 0 AND IsRefresh = 0 AND Title <> '' GROUP BY Title ORDER BY PageViews DESC LIMIT 10;\n", + "DuckDB return: Title PageViews\n", + "0 [208, 162, 208, 181, 209, 129, 209, 130, 32, 4... 102228\n", + "1 [208, 168, 208, 176, 209, 128, 208, 176, 209, ... 68968\n", + "2 [208, 159, 209, 128, 208, 184, 208, 188, 208, ... 67496\n", + "3 [208, 145, 209, 128, 209, 142, 208, 186, 208, ... 31750\n", + "4 [208, 162, 208, 181, 208, 191, 208, 187, 208, ... 19270\n", + "5 [68, 97, 118, 101, 32, 97, 110, 100, 32, 72, 1... 11962\n", + "6 [208, 159, 209, 128, 208, 184, 208, 188, 208, ... 11618\n", + "7 [65, 85, 84, 79, 46, 114, 105, 97, 46, 117, 97... 11611\n", + "8 [79, 87, 65, 80, 114, 111, 102, 101, 115, 115,... 8965\n", + "9 [208, 162, 209, 128, 209, 131, 209, 129, 208, ... 8445\n", + "chDB return: Title PageViews\n", + "0 Тест (Россия) - Яндекс 102228\n", + "1 Шарарай), Выбрать! - обсуждаются на голд: Шоуб... 68968\n", + "2 Приморск - IRR.ru 67496\n", + "3 Брюки New Era H (Асус) 258 общая выплаток, гор... 31750\n", + "4 Теплоску на 19270\n", + "5 Dave and Hotpoint sport – самые вещие 11962\n", + "6 Приморск (Россия) - Яндекс.Видео 11618\n", + "7 AUTO.ria.ua ™ - Аппер 11611\n", + "8 OWAProfessign), продать 8965\n", + "9 Труси - Шоубиз 8445\n", + "Q38: SELECT URL, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND IsRefresh = 0 AND IsLink <> 0 AND IsDownload = 0 GROUP BY URL ORDER BY PageViews DESC LIMIT 10 OFFSET 1000;\n", + "DuckDB return: URL PageViews\n", + "0 [104, 116, 116, 112, 58, 47, 47, 115, 109, 101... 2\n", + "1 [104, 116, 116, 112, 58, 47, 47, 115, 116, 97,... 2\n", + "2 [104, 116, 116, 112, 58, 47, 47, 109, 97, 115,... 2\n", + "3 [104, 116, 116, 112, 58, 47, 47, 101, 120, 116... 2\n", + "4 [104, 116, 116, 112, 58, 47, 47, 103, 117, 105... 2\n", + "5 [104, 116, 116, 112, 58, 47, 47, 97, 102, 105,... 2\n", + "6 [104, 116, 116, 112, 58, 47, 47, 106, 111, 98,... 2\n", + "7 [104, 116, 116, 112, 37, 51, 65, 37, 50, 53, 5... 2\n", + "8 [104, 116, 116, 112, 58, 47, 47, 118, 105, 100... 2\n", + "9 [104, 116, 116, 112, 58, 47, 47, 97, 108, 112,... 2\n", + "chDB return: URL PageViews\n", + "0 http://pogoda.yandex.ru/places/premiery%2Fpage... 2\n", + "1 http://stalker-pub-20087898675494,960948/#page... 2\n", + "2 http://stalker-pub-20087898675494,960948/#page... 2\n", + "3 http://video.yandex.ru/price_do=¤cy 2\n", + "4 http://kemerovokuznetsi/#tabsinternet Explorer... 2\n", + "5 http://afisha.yandex.ru/?favorite_off=FORID:10... 2\n", + "6 http://sravni.ru/search=0&city_id 2\n", + "7 http://komanipulya33497_36779014826580/price_o... 2\n", + "8 http://koolti-1t.html?sort=price=меньше 0/manu... 2\n", + "9 http://bonprix.ru/omsk/event=big 2\n", + "Q39: SELECT TraficSourceID, SearchEngineID, AdvEngineID, CASE WHEN (SearchEngineID = 0 AND AdvEngineID = 0) THEN Referer ELSE '' END AS Src, URL AS Dst, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND IsRefresh = 0 GROUP BY TraficSourceID, SearchEngineID, AdvEngineID, Src, Dst ORDER BY PageViews DESC LIMIT 10 OFFSET 1000;\n", + "DuckDB return: TraficSourceID SearchEngineID AdvEngineID \\\n", + "0 -1 0 0 \n", + "1 0 0 0 \n", + "2 -1 0 0 \n", + "3 0 0 0 \n", + "4 1 0 0 \n", + "5 1 0 0 \n", + "6 3 2 0 \n", + "7 -1 0 0 \n", + "8 -1 0 0 \n", + "9 -1 0 0 \n", + "\n", + " Src \\\n", + "0 [104, 116, 116, 112, 58, 47, 47, 115, 116, 97,... \n", + "1 [] \n", + "2 [104, 116, 116, 112, 58, 47, 47, 115, 116, 97,... \n", + "3 [] \n", + "4 [104, 116, 116, 112, 58, 47, 47, 109, 121, 115... \n", + "5 [104, 116, 116, 112, 58, 47, 47, 103, 111, 111... \n", + "6 [] \n", + "7 [104, 116, 116, 112, 58, 47, 47, 107, 105, 110... \n", + "8 [104, 116, 116, 112, 58, 47, 47, 115, 116, 97,... \n", + "9 [104, 116, 116, 112, 58, 47, 47, 115, 116, 97,... \n", + "\n", + " Dst PageViews \n", + "0 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 13 \n", + "1 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 13 \n", + "2 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 13 \n", + "3 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 13 \n", + "4 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 13 \n", + "5 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 13 \n", + "6 [104, 116, 116, 112, 58, 47, 47, 107, 111, 109... 13 \n", + "7 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 13 \n", + "8 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 13 \n", + "9 [104, 116, 116, 112, 58, 47, 47, 105, 114, 114... 13 \n", + "chDB return: TraficSourceID SearchEngineID AdvEngineID \\\n", + "0 -1 0 0 \n", + "1 -1 0 0 \n", + "2 5 0 0 \n", + "3 -1 0 0 \n", + "4 -1 0 0 \n", + "5 -1 0 0 \n", + "6 -1 0 0 \n", + "7 -1 0 0 \n", + "8 -1 0 0 \n", + "9 1 0 0 \n", + "\n", + " Src \\\n", + "0 http://state=19945206/foto-4/login-2491724/?bu... \n", + "1 http://state=19945206/foto-4/login-avanga_728x... \n", + "2 http://state=19945206/foto-4/login-2006/make=К... \n", + "3 http://state=19945206/foto-4/login-2491724/?bu... \n", + "4 http://state=19945206/foto-4/login-kupe_921675... \n", + "5 http://state=19945206/foto-4/login-2006/makumi... \n", + "6 http://state=19945206/foto-4/login-2006/makumi... \n", + "7 http://state=19945206/foto-4/login-2006/makumi... \n", + "8 http://state=19945206/foto-4/login-2491724/?bu... \n", + "9 http://acase.php?input_who1=2&input_who2=1 \n", + "\n", + " Dst PageViews \n", + "0 http://irr.ru/index.php?showalbum/login-kapust... 13 \n", + "1 http://irr.ru/index.php?showalbum/login-kapust... 13 \n", + "2 http://ekburg.irr.ru%2Fpuloveplanet 13 \n", + "3 http://irr.ru/index.php?showalbum/login-kapust... 13 \n", + "4 http://irr.ru/index.php?showalbum/login.html_p... 13 \n", + "5 http://irr.ru/index.php?showalbum/login-kupalj... 13 \n", + "6 http://irr.ru/index.php?showalbum/login-leniya... 13 \n", + "7 http://irr.ru/index.php?showalbum/login-leniya... 13 \n", + "8 http://irr.ru/index.php?showalbum/login-kapust... 13 \n", + "9 http://komme%2F27.0.1453.116 Safari%2F5.0 (com... 13 \n", + "Q40: SELECT URLHash, EventDate, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND IsRefresh = 0 AND TraficSourceID IN (-1, 6) AND RefererHash = 3594120000172545465 GROUP BY URLHash, EventDate ORDER BY PageViews DESC LIMIT 10 OFFSET 100;\n", + "DuckDB return: URLHash EventDate PageViews\n", + "0 8436286387721556030 2013-07-15 23\n", + "1 -1285046671250476833 2013-07-15 23\n", + "2 -8435826299601811261 2013-07-15 23\n", + "3 7719727592795372103 2013-07-15 22\n", + "4 3756346524397046411 2013-07-15 22\n", + "5 -3172049944036544851 2013-07-15 22\n", + "6 -3950137591013798111 2013-07-15 22\n", + "7 2680587802399303961 2013-07-15 22\n", + "8 1387759335351574242 2013-07-15 22\n", + "9 -6314751298222231545 2013-07-15 21\n", + "chDB return: URLHash EventDate PageViews\n", + "0 8436286387721556030 2013-07-15 08:00:00+08:00 23\n", + "1 7516345568886640333 2013-07-15 08:00:00+08:00 23\n", + "2 -8435826299601811261 2013-07-15 08:00:00+08:00 23\n", + "3 -3950137591013798111 2013-07-15 08:00:00+08:00 22\n", + "4 7719727592795372103 2013-07-15 08:00:00+08:00 22\n", + "5 1387759335351574242 2013-07-15 08:00:00+08:00 22\n", + "6 3756346524397046411 2013-07-15 08:00:00+08:00 22\n", + "7 2680587802399303961 2013-07-15 08:00:00+08:00 22\n", + "8 -3172049944036544851 2013-07-15 08:00:00+08:00 22\n", + "9 -6841350226646068633 2013-07-15 08:00:00+08:00 21\n", + "Q41: SELECT WindowClientWidth, WindowClientHeight, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND IsRefresh = 0 AND DontCountHits = 0 AND URLHash = 2868770270353813622 GROUP BY WindowClientWidth, WindowClientHeight ORDER BY PageViews DESC LIMIT 10 OFFSET 10000;\n", + "DuckDB return: Empty DataFrame\n", + "Columns: [WindowClientWidth, WindowClientHeight, PageViews]\n", + "Index: []\n", + "chDB return: Empty DataFrame\n", + "Columns: [WindowClientWidth, WindowClientHeight, PageViews]\n", + "Index: []\n", + "Q42: SELECT DATE_TRUNC('minute', EventTime) AS M, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-14' AND EventDate <= '2013-07-15' AND IsRefresh = 0 AND DontCountHits = 0 GROUP BY DATE_TRUNC('minute', EventTime) ORDER BY DATE_TRUNC('minute', EventTime) LIMIT 10 OFFSET 1000;\n", + "DuckDB return: M PageViews\n", + "0 2013-07-15 12:40:00 434\n", + "1 2013-07-15 12:41:00 378\n", + "2 2013-07-15 12:42:00 395\n", + "3 2013-07-15 12:43:00 391\n", + "4 2013-07-15 12:44:00 366\n", + "5 2013-07-15 12:45:00 406\n", + "6 2013-07-15 12:46:00 395\n", + "7 2013-07-15 12:47:00 381\n", + "8 2013-07-15 12:48:00 385\n", + "9 2013-07-15 12:49:00 415\n", + "chDB return: Empty DataFrame\n", + "Columns: [M, PageViews]\n", + "Index: []\n" + ] + }, + { + "data": { + "image/png": "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jzFr1qzIzs6OVatWRYUKFaJKlSrRsGHD2H777aNJkyaRnu7Mow01d+7cGDlyZPz++++RnZ0dixcvjrJly0aFChWiTp060bhx49hxxx2jWrVqqR4VAAAAgC2MoDkAAAAAsEWoUqVKgVpubu563SsvLy/69OkTPXv2jAEDBsTixYvXeG39+vXj2GOPjeuuu67Yofbbbrstbr/99gK9//T777/HXXfdFW+88UYsWbKk0HvUrVs3evToEVdddVVUrFixWP0LM3bs2Hj44Yfjo48+it9++22t11aoUCHat28fxx9/fJx88skb1H/69Olx7733Rs+ePWPBggWFXlOtWrXo1q1b3HTTTVGzZs1i3b9Dhw7xxRdf5K/bt28fAwYMyF+/8cYbcd9998WwYcMK3Z+VlRUnnnhi3H333Wv8Pi9fvjyefvrpePTRRwsEif/3OVx44YVx0003RYUKFYr1HCIiVq5cGf/5z3/i/fffjwEDBsSPP/6Y+JkpTJMmTeLUU0+NSy+9NGrVqlXsnj179ozu3bsnauPGjYvGjRtHRMTo0aPjH//4R/Tp06fQ35WzzjqrVILmjzzySFxxxRWJ3/OsrKzo2bNnnHzyySXer6Q0adKkQG327Nnrda958+bFI488Eu+++2788MMPa/xZSE9Pjz333DP++te/xtlnn13gEyCK6rvvvosnn3wy3nrrrTX+nv6vKlWqRNu2bePwww+Prl27rvM1cvU3zdx6661x2223FXvObt26xUsvvZS/btSoUYwfP77Y91mTAQMGRMeOHdf4+O23317gtX1165pp2bJl8eyzz8bLL78c33777TpnSktLi5122ikOOOCA6Nq1a3Ts2LFE39QCAAAAwNbJMRIAAAAAwBahsKBm7dq1i32fgQMHRuvWreOEE06I999/f60h84iIqVOnxuOPPx5NmzaNW265Zb3D7at7/PHHY5dddomePXuuMWQe8ccpxrfeemvssssu6wyGr83s2bOje/fusdNOO8Wjjz5apHstWbIkPvzww/jrX/8a22yzzXr37tOnTzRv3jz++c9/rjW8On/+/Hj44Ydjp512isGDB693v/+VnZ0dRxxxRJx00klrDJlH/BEif/nll2OXXXaJ//znPwUe/+mnn6J169Zx2WWXrTFk/udzuOeee2L33XePSZMmFWvWN954I7bZZps4+OCD45FHHomRI0euM2Qe8ccbFu68885o1KhRPP7448XquS533XVXtGzZMnr16rXO35WSkpubG1dccUVcdtllid+3GjVqxGeffbZJh8wjIipVqlSglp2dXax7rFq1Ku69997YYYcd4rbbbovhw4ev9WchNzc3hg0bFhdccEHstNNOiTddFMXy5cvj/PPPj7Zt28bzzz9fpJB5xB/P67PPPosrrrgiunbtWqyeW7MBAwZEixYt4tJLLy1SyDzijzcp/fzzz/HMM89Ely5d4rPPPivlKQEAAADYGgiaAwAAAACbvenTpxcI91atWjX/xOWieuaZZ+LAAw+M77//vtgzLF++PO6888449thjNzhwe8MNN8TFF18cy5YtK/Ke8ePHx3777RdTpkwpdr+RI0dGmzZtomfPnrFy5cpi74+IWLhw4Xrte+qpp+KEE06I+fPnF3nPnDlz4qCDDooffvhhvXr+aeHChdGxY8d4//33i7xnwYIFceSRRyZ6//DDD7H//vvHqFGjinyfMWPGRIcOHYoc2I2I+O9//7veJ19H/PHGgIsvvjguvPDC9b7H/7rooovi5ptvXu+fmfWxdOnSOP744+Phhx9O1HfYYYf45ptvYr/99ttos6yvwn7WK1euXOT9CxcujKOOOiquv/76Yv3e/GncuHHRuXPneOGFF4p0fU5OThx++OHxzDPPlNgbaVizDz74IA455JAYN25cqkcBAAAAgPCZeQAAAADAZu/ee+8tcJrvMcccE2lpacW6x/XXX1+gXrFixejcuXO0adMmttlmm6hcuXIsWLAgfvvtt/j0008LhNL//e9/xznnnBP/+te/1uu5PP3003HPPffkr2vXrh2HHnpotGnTJmrXrh3Lli2LMWPGRN++fWP06NGJvTNnzozzzz8/3nvvvSL3+/777+OAAw4oNBxfpUqV6NixY+y9995Rp06dqFSpUixYsCCmTJkS3333XXz99dcxZ86c9XqeEREffvhhXHzxxfnfu6pVq0aXLl1in332iTp16kRubm6MHz8+3nvvvRgyZEhi7+LFi6N79+7x7bffRkbG+v1V95lnnpn4/rVq1SoOPfTQ2H777aNSpUoxffr0+M9//hP9+vVLBGyXLFkSZ511Vnz//fcxe/bsOOKII/L/HDIzM6Njx45x4IEHRv369SMjIyPGjx8f7777boHnMHbs2Lj++uvjiSeeWK/5GzVqFHvssUe0aNEiGjRoEJUrV47y5cvHokWLYurUqfHDDz/Exx9/XCDM/tRTT8Wuu+4aPXr0WK++ERHPPvtsYu5KlSpF586dY9999426detGXl5eTJo0Kfr37x9lypRZ7z7/a+bMmXHkkUfG0KFDE/W99tor+vXrt16fYJAKI0eOLFBr0qRJkfYuWbIkOnToUOibYZo0aRIdO3aM3XbbLWrUqBEZGRkxe/bs+Pbbb+ODDz6IWbNm5V+7YsWK+Otf/xp169aNww8/fK0977nnnvj8888L1Bs2bBhdunSJFi1aRN26daNcuXKxZMmSyM7OjjFjxsSoUaPim2++2Wgn3W9MlSpVit133z1/PWLEiMTjdevWjXr16q31HvXr1y9Qmz17dpx11lmxfPnyRD0jIyMOOOCA2GeffaJx48b5b0zIzs6OmTNnxujRo+P777+Pn3/+eX2fEgAAAAAUStAcAAAAANhs5eXlxYMPPhj//Oc/E/WyZcvGtddeW+T7fP7553HjjTcmauXLl49bbrklevToEVWqVCl037333hsDBgyIv/71r/H777/n119//fXYf//946KLLirGs/nD5ZdfHhF/BJbvuOOOuPzyy6NcuXIFrrvjjjvi0UcfjSuuuCIRgn7//fdj8ODB0a5du3X2mjNnThx33HEFgqCVK1eO66+/Pi677LKoUKHCGvevWrUq+vfvHy+88EK88cYbRXyG/+fKK6+M3NzcSEtLiyuvvDJuuummqFatWoHrbrrppnjjjTfirLPOSpzy/sMPP8Rbb70VJ598crF7Dx48OD/Muf3228czzzwTBx10UIHrLr300vjuu+/i8MMPjxkzZuTXR44cGW+88Ua89tpr+afIH3TQQfHEE09Es2bNCtzn+uuvjxdffDHOPffcWLVqVX796aefjhtuuCEaNGhQpLl33XXXOOecc+Kwww4rtM/qli9fHs8880zcdNNNkZ2dnV+/8sor4+ijj45tt922SH1X9/e//z3/vy+44IK46667ombNmgWuu+GGG4p1Mv+a/Pzzz3HYYYcVOOX52GOPjd69e0f58uU3uMfGsGTJkvjoo48K1PfZZ58i7e/Ro0eBkHmLFi3i4YcfjoMOOmiNb65ZunRp/POf/4xbbrklVqxYERF/vH6eccYZMXLkyDX+/C1btizuv//+RK1ChQrx2GOPxVlnnRXp6Wv/4Nzly5fHl19+GS+++OJ6fdrCpqp169aJTzVY/c/9ggsuiNtuu63Y933qqacKfGpB586d47nnnovttttunfvHjx8fffv2jSeffLLYvQEAAACgMGv/G0AAAAAAgE3IihUrYu7cuTF06NB4+OGHY4899oirr766wHWPPPJItGjRokj3XLhwYZx22mmJsHadOnViyJAhcd11160xZP6nDh06xHfffRe77bZbon7bbbfFkiVLijTD/1q2bFlkZWXFhx9+GNddd12hIfOIP4KNl156adx5550FHnvuueeK1Ouiiy6KCRMmJGoNGjSIQYMGxfXXX7/WkHlERJkyZeKggw6KV199NcaMGVOknv9r2bJlkZaWFi+99FLcf//9hYbM/3TiiSfG888/X6Be1Oe6uj9D5s2bN4+vv/660JD5n1q1ahVvv/12gTDp5ZdfHv369YuIiFNOOSU+/PDDtYa/u3fvHrfffnuilpubG7169SrSzFdccUWMHDkyLrvssiKFzCMisrKy4pJLLomBAwcmfpaXL18ejz/+eJHuUZg/w/IPPPBAPPnkk4WGzP+0pp/hovriiy9in332KRAyv+yyy+Ktt97abELmERF33313gSBxRkZGkd4s8cYbb8RLL72UqB1zzDExfPjw6Ny581o/waF8+fJx3XXXxXvvvReZmZn59Xnz5sXdd9+9xn2ff/55LFq0KFF74oknonv37usMmUf88fPXuXPnePXVV+PDDz9c5/Vbu3fffTex3nnnnaNfv35FCplHRDRu3DiuuOKK+OWXX6J9+/alMSIAAAAAWxlBcwAAAABgk/HFF19EWlraGr/Kli0bNWvWjL322iuuuOKKGDFiRGJ/gwYNom/fvnH++ecXuedTTz2VOKk6PT093n333dh1112LfI+qVatG3759o2zZsvm12bNnr3cI+r777otOnToV6dprrrmmwKnUH3/88Tr3/fzzz/Hmm28mauXKlYsPPvigWM/9T40bNy72nog/wtNnnHFGka499dRTo23btonaF198sd4nZmdlZcXrr78e9erVW+e1++yzTxx66KGJ2syZMyMiYqeddornnnsuMjLW/SGiV111VYFAfVEDuFWrVi3SdYXZbbfdCgSKCwvuF8fxxx8fV1555QbdY1169+4dXbp0iXnz5uXX0tPT4+GHH46HH364SGHnTUFeXl7cf//9hYa6e/ToEdtss806999xxx2J2u677x5vvPFG4nVnXbp06RK33nprovbiiy/m/yyvbuzYsYl1+fLl47TTTityv/+1rjeuUPDP+4wzzoisrKxi3yctLW2zegMGAAAAAJuuzeNvYAEAAAAA1mK//faLt99+O8aNGxfHHHNMkffl5OTEww8/nKideeaZ0a5du2LPsMMOOxQITPft23e97nPRRRcV+frMzMw46aSTErXJkyevMTj6p/vuuy9xintExK233rpeIfP1VaVKlQKh13U5/fTTE+uVK1fGyJEj16v/GWecUazne/zxxxdav+WWW4ocoi1XrlwcccQRidqIESMiLy+vyHOsr9NPPz1x6vXMmTPj119/Xa97paenx/33319SoxXqrrvuitNPPz1ycnLyaxUqVIg+ffrEZZddVqq9N1Rubm7Mnz8/RowYEY899ljssccecc011xT4Pu+5555rPVH8T++//36MHj06UfvnP/+ZOJ28qK688sqoXLly/nrZsmVrfLPDwoULE+uqVasW6Q0VrJ/V/7zX9kkBAAAAALAxCJoDAAAAAJu9r776Knr06BF33nlnzJkzp8j7vv7665g6dWqi9te//nW95zj88MMT68GDB8fy5cuLdY+zzz672Kc0r37Kd0TEL7/8stY9/fr1S6wrVaoUF154YbH6bqgTTzwxqlSpUqw96/Nc1+Scc84p1vV77LFHgVrlypXjhBNO2KD7LFy4MKZMmVKse6yPqlWrRp06dRK1wYMHr9e9DjzwwPU+xX5dVq5cGeecc07cfPPNiXqdOnWif//+xXozSWnr2LFjoZ++UKZMmahevXq0bNkyLrnkkgKfvhDxx5/hJ598EhUrVlxnn7feeiuxbtasWbRv3369Zi5fvnx07NgxURswYECh164edJ4xY0aMGTNmvfqybqv/eX/11VcpmgQAAAAA/uDYCQAAAABgk1GxYsVo2rTpWq9ZtGhRzJs3L+bOnZuoT58+Pe6444546qmn4vnnny9wanRhvvjii8Q6MzMz2rRpU/zB/3/bb799Yr1s2bL46aefomXLlkW+x/qER5s0aVKgtmDBgjVeP3r06Jg1a1aidtRRR0XVqlWL3XtDbIznuiYVKlSI1q1bF2tPo0aNCtTatWtX7FOlCwtoz58/Pxo0aFCs++Tl5cV3330X3333Xfz4448xefLkWLhwYWRnZ8eKFSsK3bP6783EiROL1fNPqweVS0p2dnZ07do1Pv3000R9p512ig8//LDA79jmqGXLlnH11VfHqaeemjhhfm1Wf63aZ599NmiG1f8chw8fXuh1e+21V2Kdl5cXJ598cvTt2zcaNmy4QTNQ0F577RXvvvtu/rp3796x9957x4UXXljknxUAAAAAKEmC5gAAAADAJqN169ZrPFl3ddOmTYv//Oc/8dRTTyVOfZ05c2Ycc8wx0atXrzj11FPXeo9BgwYVqBV2YnZR5eTkFKjNnj27WPdo1qxZsfsWFhBfW/j6m2++KVDbd999i913Q22M57omjRo1ioyM4v0VeeXKlQvU1vXGiKLepzjPYcGCBXH//ffHyy+/HBMmTCh2//81f/789dq35557blDfwkyaNCkOP/zw+PHHHxP1/fffP955552oUaNGiffc2KpUqRKnnnpqnHjiiUUODk+dOjXGjx+fqH300UfFegPL6qZPn55Yr+l1qmXLlrHHHnskgujfffdd7LjjjnHiiSfGiSeeGAceeGCUL19+vWfh/3Tv3j0RNM/Ly4uLLroonnjiiejevXscffTR6/WaAwAAAADrS9AcAAAAANgsbbPNNnHaaafFaaedFo8++mhcdtllkZeXFxERq1atirPPPjt23333+Mtf/rLGe0yePDmxXrFiRYwYMaJE55wzZ06xrl+fMG1hJ2qv6UTriIgZM2YUqO26667F7ruhNsZzXZPq1auXSO+Suk9Rn8O7774b559/fqHfw/WxPiH9iIg6deqUSP8/TZo0Kdq1axdTp05N1E855ZR48cUXIysrq0T7lZQmTZpEpUqVErW8vLxYvHhxTJ06NZYuXZp4LDs7O6699tro169f9OvXr0ifIrD661TEH7/DJfUzELH216knnngiOnToEMuXL8+vLVu2LHr16hW9evWKsmXLRps2baJdu3ax1157xQEHHBB169Ytsdm2JkcffXQcc8wx8c477yTqo0ePjquvvjquvvrqaNiwYey3337Rpk2b2GeffaJVq1bFftMMAAAAABRVeqoHAAAAAADYUJdccklcc801idry5cvjkksuWeu+4obA18fqQdN1KSyEXNLmzp1boLY+gekNtTGea2n33pjP4dVXX43jjz++RAPG6xPSj/jjZO6SNHbs2AIh82OPPTZ69+69yYbMIyKee+65+OGHHxJfI0aMiDFjxsTChQtj2LBhceGFFxYIAg8cODCOOOKIQj8FYXUb43Vq2bJla3ysXbt28d5770WtWrUKfTwnJycGDRoUDzzwQJx44olRr169aNGiRdxyyy3xyy+/lNbIW6zevXuv9dM4Jk2aFK+99lpceeWV0a5du6hevXocd9xx8cYbbyTeDAAAAAAAJUHQHAAAAADYItxwww1RoUKFRK1///4xatSoNe6ZN29eaY+1ScrOzi5QW/1UZjYtv//+e5x99tmxatWqRD0zMzOOPfbYeOihh+Kzzz6LX375JebOnRuLFy+O3NzcyMvLS3w1atSoROYp6ROUC7vfe++9F3369CnRPhtTmTJlolWrVvHEE0/E559/XuD08q+++qrAG2QKsym8Th100EHxyy+/xPXXX7/GwPn/+umnn+LOO++M5s2bR9euXWPcuHEbYcotQ4UKFaJ3797x8ccfR4cOHSItLW2t1y9atCj69u0bJ510UjRp0iSefvrp/E/3AAAAAIANJWgOAAAAAGwRqlatGvvvv3+B+scff7zGPeXLl0+s69atWyCYu6Ff3bp1K+mnusEKO4160aJFKZiEorruuusKnFZ8yCGHxIQJE+Ltt9+Oyy+/PDp16hQ77rhjVK9ePSpUqFBoQLW4J+xvLPvuu29cd911idqKFSvi5JNPjpdeeilFU5WcAw44IN58881IT0/+s8yjjz4aX3zxxVr3rv46FRHx//7f/yvx16p1qVGjRtx9990xbdq0+Oijj+Lqq6+Otm3bRtmyZde4Jy8vL/r06RMtW7Zc62sxBXXp0iX69+8f48aNi8ceeyxOOOGEqF+//lr3TJkyJS644II4+uiji3RaPgAAAACsi6A5AAAAALDFaNasWYHaiBEj1nj96ifzbgonB28MNWvWLFDbWp775mjx4sXRr1+/RG3PPfeMf//737HNNtsU616b8vf5nnvuib/97W+J2qpVq6J79+7xxBNPpGiqktO5c+e4/PLLE7W8vLy4+OKLC5xU/78KO0F87ty5JT1ekWVkZMTBBx8c9913XwwZMiSys7Nj4MCBcc8990SHDh0KPZ0+Ozs7jj/++Pj11183yowrVqzYKH02hkaNGsVFF10Ub7zxRkyZMiUmTJgQr7zySpx33nnRoEGDQvf069cvLrrooo08KQAAAABbIkFzAAAAAGCLUdhJ3bNnz17j9XXr1k2sc3JyYtq0aSU+16amXr16BWojR45MwSQUxZdfflngNPPrr78+MjMzi3WfSZMmbfIB3BtuuCEeeeSRxGnseXl5cdFFF8U//vGPFE5WMu68884Cp1KPGjVqrae2r/46FRExYcKEEp9tfWVlZcV+++0X1113XfTv3z+mT58ef//736NatWqJ6xYvXhw333zzWu+1ekh9fX9e58yZs177NgfbbbddnHbaafH000/HpEmTon///tGlS5cC1z3//PMxevToFEwIAAAAwJZE0BwAAAAA2GIsWLCgQK1MmTJrvH6vvfYqUPvyyy9LdKZN0d57712gNmjQoBRMQlFMmjSpQG3//fcv9n2++eabkhin1F1yySXx/PPPF/jd/X//7/+tM6i8qatQoULccccdBeq333575OTkFLqnadOmUaNGjUTt66+/Xusp6KlUs2bNuPbaa2Pw4MFRuXLlxGPvvfdegTdN/K/V3yyUnZ29XjOMGTNmvfZtjjp06BAff/xxnHfeeYl6Xl5e9O3bN0VTAQAAALClEDQHAAAAALYYP//8c4FaYad3/6lz584Fam+//XaJzrQpat68eYFTkvv161doUJ/UK+xU/tWDx0Xx+uuvl8Q4G0X37t3j1VdfLXBq+1133RVXXHFFiqYqGWeddVY0bdo0UZs4cWI899xzhV6fnp4enTp1StQWLVoUn3zySanNWBJ22mmnOOeccxK1JUuWxO+//77GPaufgj527Nhi950yZcpae5SG1d8UkYo3Adx9990F5vBJFQAAAABsKEFzAAAAAGCLMG/evEJP5W7evPka97Rv3z6qVq2aqPXp0yd+++23Ep9vU3PMMcck1osWLYonnngiNcOwVhUrVixQKyx8vja///57vPvuuyU10kZx4oknRt++faNcuXKJ+sMPPxznnXde5ObmpmiyDZORkRG33HJLgfrdd9+9xtO+jz766AK1e+65p8RnK2k777xzgdra3tCy0047JdbDhg0r9vf5mWeeKdb1JWH1k9sXLVq00WeoWbNm1K5dO1Hz5iEAAAAANpSgOQAAAACwRbjzzjtj2bJlBepHHXXUGvdUrFixwOnIq1atitNPP32Ngc8txdVXX13g9Ns77rgjfvzxxxRNxJpss802BWrFOc06Nzc3zj777JScsryhDj/88Pjggw+iUqVKifqzzz4bZ5xxRqxcuTJFk22YU089tUCoesqUKfH0008Xev1JJ51U4BT0gQMHxkMPPVRqM5aEadOmFaitHob+X61atUqsZ86cGZ9//nmR+02cODEeeeSRog9YQqpXr55Yr89J7Btq2bJlMW/evERtbX/WAAAAAFAUguYAAAAAwGbv4YcfLjRweeCBBxYIZ67uiiuuiFq1aiVqQ4cOja5du673abAzZ86Mm266KT799NP12r8xNG3aNE499dREbdmyZXHYYYfFqFGjin2/8ePHl9BkrG7//fcvULvrrrsiOzt7nXtzc3Pj/PPPjy+//LI0RtsoOnbsGJ9++mlUq1YtUX/11Veja9eum+WbQsqUKVPoqeb33ntvLF26tEA9IyMjbr/99gL1a6+9do3h9KL4+uuvC7wO/K+HHnpovV/HsrOzo2fPnolatWrVolGjRmvcc+ihhxaoXXfddbFixYp19ps3b1507do15s+fX9xRN9iuu+6aWH/xxRexePHiYt1jzJgxceedd8asWbPWa4ann366wO/C7rvvvl73AgAAAIA/CZoDAAAAAJuladOmxSuvvBL77rtvgVPJIyIyMzPj0UcfXed9qlSpEv/6178iIyMjUX/vvfeiVatW0bt37yKdmrxs2bJ499134/TTT49GjRrF3/72t/UOqm8sjzzySOywww6J2uTJk2PfffeNv//977FkyZK17l+1alX0798/Tj/99GjWrFlpjrpV22abbWK//fZL1MaMGRMHH3xwTJgwYY37fvnllzjkkEPiueeei4g/wsoVKlQo1VlLS7t27aJ///4FTmh+991346ijjlrnz+qm6OSTT44WLVokatOmTYsnn3yy0OtPPfXU6N69e6K2cuXKuOCCC+L444+PkSNHFqnv5MmT45///Ge0a9cu9t133/j3v/+9xmu/+OKL6NKlS+yyyy5x9913x88//1ykHqNHj46DDjqowM/niSeeGJmZmWvct88++0Tz5s0Tte+//z6OO+64mDt37hr39e/fP/bee+/49ttvIyKiXLlyRZqzpOyzzz6J9YIFC+Kkk06Kn376qcj3WLRoUdxyyy2x3Xbbxemnnx59+/Yt9E0Hq8vJyYn7778/rrnmmkS9TJkycfLJJxe5PwAAAAAUJmPdlwAAAAAAbBzDhg2Lli1brvWaxYsXx9y5c9caOszIyIjevXsXCHGuSadOneKRRx6JHj16JOq///57nH766XHVVVdFhw4dolWrVlG7du2oVKlSLFy4MObPnx9jx46N7777Ln744YcihQI3JdWqVYs+ffrEAQccEAsXLsyvZ2dnx3XXXRd33313dOrUKdq1axd16tSJSpUqxYIFC2Lq1KkxfPjwGDRoUMycOTOFz2Drcfvtt0enTp0StcGDB8eOO+4YRx99dOy3335Rr169WLZsWUyZMiU+/fTTGDhwYOJNErfccks8//zzaw2nb8patmwZX375ZRx00EExZcqU/Ponn3wShxxySLz33ntRpUqVFE5YPOnp6XHrrbfGSSedlKj//e9/jwsuuKDQNwU89dRTMWbMmBg4cGCi/vbbb8fbb78du+++e7Rv3z6aNWsWNWvWjPT09Jg/f37MmTMnRo0aFd9991389ttvkZeXV6xZR48eHTfeeGPceOON0bhx49hjjz1i9913j7p160a1atUiIyMjsrOz82cbNGhQgR41a9Ys9FT21d19991x7LHHJmrvvfdeNGnSJLp27Rpt2rSJ6tWr5/f7+OOPY/jw4fnX7rffftGoUaPo3bt3sZ7jhjjzzDPjpptuSvy+vf/++/H+++9H9erVo27dupGVlZXYU79+/fjggw8K3GvZsmXRu3fv6N27d5QvXz5atmwZe+yxRzRr1iyqVasWlStXjuXLl8f06dNjxIgR8dFHHxX6OnzddddFw4YNS/7JAgAAALBVETQHAAAAADYZixcvjhEjRmzQPerVqxfPPvtsHHHEEcXad+GFF0adOnWie/fuidB1RMSMGTPi9ddfj9dff32DZtsUtWzZMgYNGhRHHnlkgQBydnZ29O3bN/r27Zui6fjTgQceGNddd13ce++9iXpOTk68+eab8eabb651/+mnnx433XRTPP/886U5Zqnbeeed46uvvopOnTrF2LFj8+sDBw6MTp06xccffxw1atRI4YTFc8IJJ8Sdd94Zo0aNyq/NnDkzHnvssbj22msLXF+2bNn45JNP4qKLLooXXnihwOMjRozY4NfQdRk/fnyMHz++WK8L1apVi7fffjvq1au3zmuPOeaY6N69e7z44ouJ+vz58+O5557LP6G/MM2bN4++ffvG1VdfXeTZSsI222wTN910U9x2220FHps3b17MmzevQH3+/PnrvO/SpUvjm2++iW+++aZY85x00klx6623FmsPAAAAABQmPdUDAAAAAACUhFq1asXVV18dP//8c7FD5n86/vjjY9iwYeu9/08ZGRlxxBFHxG677bZB99lYdt111xg6dGicfvrpkZ6+fn9tXKdOnRKeitXdfffdcdNNN0VaWlqR95QpUyZuuOGGeOmll4q1b1PWuHHjGDhwYDRv3jxRHzZsWLRv3z6mT5+eosmKLy0trdBw8n333ReLFi0qdE+5cuXi+eefj1deeSV22GGHDepfp06dAp/k8L+KEgxfl/322y8GDRoUBxxwQJH3PPvss3HuuecWq0/nzp3jq6++ilq1ahV3xBJx8803x9/+9rcoW7bseu2vUKFCVK5ceYNmqFSpUtxzzz3x2muvRWZm5gbdCwAAAAAiBM0BAAAAgM1M2bJlo1atWtGkSZM4+OCD4/rrr49+/frF1KlT47777ouqVatu0P133HHH6NevX4wYMSLOPffc2H777Yu0r2bNmtG1a9d4+umnY8qUKdGvX7/YcccdN2iWjalOnTrx8ssvx6hRo+Lcc8+Nhg0brnNP1apV47jjjovXXnstJk2atBGm3LqlpaXFnXfeGV999VUceuiha31TQIUKFeLUU0+N7777Lv72t7+t9xsINlX169ePL7/8MvbYY49EfdSoUXHAAQfExIkTUzRZ8R133HHRsmXLRG327NnxyCOPrHXfaaedFr/++mv07t07Dj300CKHlFu0aBGXXnppfPDBBzFlypT4xz/+scZrn3rqqRg/fnw8/vjj0bVr19h2222L1KN8+fLRtWvX6NevXwwcODBatGhRpH1/KlOmTDzzzDPx6aefxj777LPWN0nsvvvu8corr8Qnn3yS0tPs09PT44YbbogpU6bEY489FieddFLssssuUatWrShXrtw69++4444xe/bs+OSTT+LKK6+Mvfbaq8ih9ebNm8ftt98ev/32W1x33XVbzJtKAAAAAEi9tLy8vLxUDwEAAAAAsCmbOHFijBw5MmbPnh1z5syJZcuWRaVKlaJKlSqx3Xbbxc4771zkAObm5Oeff46ffvopZs+eHbNnz460tLSoXLly1K9fP3beeefYcccdo0yZMqkec6s1f/78+Oqrr2LixIkxb968yMjIiFq1asVOO+0Ubdq0iaysrFSPyEa0cuXKGD58eEyYMCHmzJkTc+fOjfT09KhcuXJUr149mjVrFjvvvHNUqlRpg/pMmzYtxowZE+PHj4+5c+fG4sWL8/vUqlUr/vKXv8TOO+8cGRkZJfTMImbNmhVfffVVTJs2LebNmxdZWVnRsGHDaNu2bZHfDLQ5Wr58eYwZMyZ+//33mDp1aixcuDCWL18eFSpUiKpVq0bjxo1j9913T9kp7gAAAABs+QTNAQAAAAAAAAAAAABI2LI+KxMAAAAAAAAAAAAAgA0maA4AAAAAAAAAAAAAQIKgOQAAAAAAAAAAAAAACYLmAAAAAAAAAAAAAAAkCJoDAAAAAAAAAAAAAJAgaA4AAAAAAAAAAAAAQIKgOQAAAAAAAAAAAAAACYLmAAAAAAAAAAAAAAAkCJoDAAAAAAAAAAAAAJAgaA4AAAAAAAAAAAAAQIKgOQAAAAAAAAAAAAAACYLmAAAAAAAAAAAAAAAkCJoDAAAAAAAAAAAAAJAgaA4AAAAAAAAAAAAAQIKgOQAAAAAAAAAAAAAACYLmAAAAAAAAAAAAAAAkCJoDAAAAAAAAAAAAAJAgaA4AAAAAAAAAAAAAQIKgOQAAAAAAAAAAAAAACYLmAAAAAAAAAAAAAAAkCJoDAAAAAAAAAAAAAJCQkeoBYF3mz58fX3zxRf66YcOGkZWVlcKJAAAAAAAAAAAAAKB0LV++PCZNmpS/bt++fVSrVm2j9Rc0Z5P3xRdfxDHHHJPqMQAAAAAAAAAAAAAgZd555504+uijN1q/9I3WCQAAAAAAAAAAAACAzYKgOQAAAAAAAAAAAAAACRmpHgDWpWHDhon1O++8E02bNk3RNAAAAAAAAAAAAABQ+saMGRPHHHNM/nr1TG1pEzRnk5eVlZVYN23aNP7yl7+kaBoAAAAAAAAAAAAA2PhWz9SWtvSN2g0AAAAAAAAAAAAAgE2eE80BAAAAAABYo0WLFsXQoUNj5syZUalSpdhjjz1i2223TfVYAAAAAEApEzTfSi1evDiGDBkSv/76a8ybNy8iIqpWrRrbb7997LLLLtGwYcMUTwgAAAAAAGwMP/30UwwfPjwOOOCAaNCgQX595cqVceONN8Zjjz0Wy5YtS+w5/PDD4+mnn45tttlmY48LAAAAAGwkguYpNmXKlBg6dGgMGTIkhg4dGsOGDYuFCxfmP96oUaMYP358ifUbOHBgPPjgg/HBBx9ETk7OGq/bdttt4+CDD46rrroqWrRoUWL9AQAAAACATctdd90Vb775ZkyaNClRP+OMM+KNN96IvLy8qFOnTjRu3Djmzp0b48ePj/feey/233//GDp0aNSoUSNFkwMAAAAApUnQPAUGDRoUDzzwQAwZMiSmTp26UXouWLAgevToEa+++mqRrp8yZUq88MIL0aZNG0FzAAAAAADYgg0ePDhatmwZdevWza8NGjQoXn/99ahdu3b07NkzDj300PzHJk2aFBdeeGF88MEHcc8998R9992XirEBAAAAgFKWnuoBtkbffvtt9O3bd6OFzKdMmRL77LNPoSHzunXrxm677RZt2rSJpk2bRkaG9x4AAAAAAMDWZNq0abHDDjskah999FGkpaXFM888kwiZR0Q0bNgw3nzzzahfv3688847G3FSAAAAAGBjkirexFSqVCkWLVpUYvfLzs6OQw45JP773//m16pXrx7XXXddnHDCCbH99tsnrs/JyYnhw4fHBx98EL179y6xOQAAAAAAgE1T+fLlY+nSpYnarFmzIiLiwAMPXOOevfbaK95///1Snw8AAAAASA1B8xSqXLlytGrVKtq0aRNt27aNNm3axLhx46Jjx44l1uPKK6+MUaNG5a/bt28fffr0iZo1axZ6fdmyZWOvvfaKvfbaK2677bZYsGBBic0CAAAAAABsev7yl7/E119/HcuXL4+srKyIiGjQoEFEREyfPj0qV65c6L5p06ZF1apVN9qcAAAAAMDGlZ7qAbZGRx55ZIwePTrmz58f/fv3j3/84x/RtWvXaNSoUYn2GTBgQLzwwgv56zZt2sQHH3ywxpD56tLS0qJatWolOhMAAAAAALBpOfvss2POnDlx+eWX59dOPfXUKFu2bNx4442F7unXr18MGTIkDjjggI00JQAAAACwsTnRPAWaNGmyUfpceeWVkZeXFxERGRkZ8dxzz0WFChU2Sm8AAAAAAGDz0K1bt3j99dfj6aefjhEjRsTFF18ce++9dzz66KPRo0ePaNmyZZxxxhnRuHHjmDdvXgwYMCBef/31yMzMjFtuuSXV4wMAAAAApUTQfAv17bffxvDhw/PXxxxzTOy2224pnAgAAAAAANhUvfPOO3H++edHr169YsiQIYnHfvzxx7j22mvz13l5eVGrVq145ZVXYtddd93YowIAAAAAG0l6qgegdDz//POJ9emnn56iSQAAAAAAgE1dVlZW9OzZ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dogmTZqkehQAAAAAoJRkpHqArdWgQYNi6dKlBeojRoxIrJctWxafffZZofeoX79+tGjRYo09unbtGu3bt48vvvgiIiIWLFgQHTt2jDvuuCO6d+8eVapUyb922LBhcc0118SAAQMS93jwwQejZs2aRX1aAAAAAADAVmDy5Mkxfvz4SEtLS/UoAAAAAEApETRPkdNOOy0mTJiwzutmzJgRnTt3LvSxs846K3r27LnW/a+99lrsu++++aeUZ2dnx+WXXx7XXnttNGnSJCpWrBiTJ0+O6dOnF9h77rnnxnnnnbfuJwMAAAAAAGxVevXqFUuWLEn1GAAAAABAKRI038Jts8028eWXX8axxx4bw4YNy6/n5OTETz/9VOie9PT0uOWWW+LWW2/dWGMCAAAAAACbkTZt2qR6BAAAAACglKWnegBKX4MGDeKbb76Jxx57LJo0abLG67KysuLYY4+NESNGCJkDAAAAAAAAAAAAwFbMieYpMn78+I3aLyMjIy666KK46KKLYtSoUTF8+PCYOnVq5ObmRq1ataJRo0ax3377RYUKFTbqXAAAAAAAAAAAAABsmMaNG8eECRMiIqJRo0YbPafKlknQfCu0yy67xC677JLqMQAAAAAAgM3A0KFD46OPPopp06ZFxYoVY88994zjjjsuypUrl+rRAAAAAIBSJGgOAAAAAACwFbvhhhuiVatWcfzxxyfqixcvjjPPPDPeeeediIjIy8uLiIi0tLS49tpr46233op27dpt7HEBAACALdT/nsi9JllZWZGVlRU1a9aMevXqRbNmzeIvf/lL7LvvvtG2bdvIzMzcSNNufXr27Bndu3df6zVlypSJrKysqFSpUtStWzcaNGgQzZs3j1atWkX79u1j2223Xe/+AwYMiI4dOxbp2oyMjKhSpUrUqlUrdtttt9h7773jlFNOiW222Wa9+2+tBM0BAAAAAAC2Yvfee29069atQNC8W7du0bdv36hZs2Z07949mjVrFvPmzYu33347hg4dGkcccUT8+OOP/oEOAACAjabxde+neoQtxvh7D0/1COtl+fLlsXz58sjOzo5x48bFN998k/9YtWrV4rjjjotLLrkkWrZsmboht2KrVq2KJUuWxJIlS2LmzJnx448/xocffpj/eNu2baNbt27RrVu3KF++fKnNsXLlypg7d27MnTs3fv3113jrrbfi2muvjbPPPjv+/ve/R/Xq1Uut95YmPdUDAAAAAAAAsGn5/vvvo0+fPtGgQYP48ccf4x//+Eece+65ce2118bgwYPjvPPOi7lz58bDDz+c6lEBAAAAIiJi/vz58cILL8Qee+wRJ5xwQkyZMiXVI7GaoUOHRo8ePWL77bePXr16bdTeq1atimeffTbatGkTkyZN2qi9N2dONAcAAAAAACDhww8/jLS0tPjHP/4R9erVK/D4Aw88EH369IkPP/ww/v73v6dgQgAAAGBLd//998fuu++eqK1YsSLmzZsX8+fPjwkTJsQ333wTw4YNi6VLlyaue+utt2LAgAHx5ptvRocOHTbi1FuP3XbbLR544IEC9ezs7Jg/f37MnTs3vv/++xg8eHCMGzcucc2MGTPirLPOio8//jheeOGFyMrKKnb/unXrxiuvvFLoY8uWLYvZs2fH999/H2+99VZMmzYt/7Hff/89jjrqqBg2bFiUKVOm2H23NoLmAAAAAAAAJEyePDkiIg444IBCH69YsWLsueee8fXXX2/MsQAAAICtSKtWrYoUEl+6dGm8/PLL8fDDD8dPP/2UX589e3Ycdthh8eGHH0b79u1LcdKtU/Xq1eOggw4q0rU//vhjPPTQQ9G7d+/IycnJr7/66quxcOHC6Nu3b7FD3+XKlVtn/27dusU//vGPuOqqq+KJJ57Ir//www/Rq1ev6N69e7F6bo3SUz0AAAAAAAAAm5Zy5cpFxB//YLgmtWvXjlWrVm2skQAAAAAKVb58+TjvvPNi5MiRccUVVyQeW7p0aZxwwgmJE63Z+Hbdddd44YUX4ptvvonGjRsnHuvXr1/cdtttpda7XLly8fjjj0enTp0S9TfeeKPUem5JBM0BAAAAAAC2cmPGjIlevXrlf82dOzciIiZMmLDGPdOmTYtatWptrBEBAAAA1iojIyMefPDBePDBBxP1WbNmxTXXXJOiqfhfe+65ZwwbNiy23377RP3ee++Nn3/+uVR7n3/++Yn1yJEjS7XfliIj1QMAAAAAAACQWoMGDYpBgwblr/Py8iItLS0+/PDD2HnnnQtcv2jRovj222+jdevWG3NMAAAAgHW64oorYuDAgdG3b9/82quvvho333xz7LTTTimcbM1ycnJiyJAhMWHChJg1a1YsWbIkKleuHI0aNYpddtklmjRpkuoRS0zNmjXjjTfeiH333TdycnIiImLlypVxxx13xKuvvlpqfVu0aJFYz5o1q9R6bUkEzQEAAAAAALZit9566xofq1OnTqH1Xr16xaJFi6Jdu3alNRYAAADAerv//vvj3Xffjdzc3Ij44031Tz/9dIHTziMievbsGd27d89fv/jii9GtW7ci90pLS8v/7/bt28eAAQOKvPebb76Je+65Jz7//PNYsmTJGq9r3LhxdO3aNS644IISD53fcMMNcc899+SvK1asGK+//nocfvjhJdrnf7Vu3TpOPfXU6NmzZ36tT58+MXv27FL7BL3//T5FRJQvX75U+mxpBM0BAAAAAAC2YmsLmq/JiSeeGIcffnjUrFmzFCYCAAAA2DA77LBDHHnkkfHuu+/m1955551Cg+apsHDhwujevXv06dOnSNePHz8+7r///vj222+LFWRfmxUrVsQ555wTL7/8cn6tdu3a8f7770ebNm1KpMfaXHbZZYmgeU5OTnzwwQdx5plnlkq/n376KbFu2rRpqfTZ0qSnegAAAAAAAAA2L7Vq1YpGjRpFpUqVUj0KAAAAQKGOO+64xHrcuHExYcKEFE3zfyZPnhx77713oSHzypUrx8477xxt27aNnXbaKcqVK1cqMyxcuDAOP/zwRMh8hx12iK+//nqjhMwjIlq2bBnbb799ota/f/9S6/fss88m1p07dy61XlsSQXMAAAAAAACK7cMPP4xevXqlegwAAACAQu21114FasOHD0/BJP8nJycnjj/++Bg9enSifswxx8TAgQNj3rx58dNPP8WQIUPi559/joULF8a3334bN954Y2y33XYlMsP06dOjffv28emnn+bXWrduHd98881GP+V79e9RaXx/cnJy4qqrroqPP/44v1axYsW46KKLSrzXligj1QMAAAAAAACw+bnjjjti6NChpfZxxgAAAAAbYscdd4xKlSrFokWL8mtjx45N4UQRt956awwdOjR/XbZs2ejZs2eccsophV6fkZERrVu3jtatW8ett94agwcP3qD+P//8cxx66KExfvz4/NohhxwSb731VlSsWHGD7r0+WrVqFf/617/y18X5/ixbtiw+++yzQh/LycmJWbNmxQ8//BB9+vSJSZMm5T+WmZkZL730UjRs2HD9B9+KCJoDAAAAAAAAAAAAsEVJS0uLmjVrJoLm06ZNS9k8c+fOjUcffTRRe+yxx9YYMl9dZmZm7L///uvd/+uvv44jjzwy5s6dm1/r1q1bPPvss5GRkZo4ca1atRLrhQsXxuLFi4sUep8xY0Z07ty5yL0yMzPjkEMOiTvuuCNatmxZ3FG3WumpHgAAAAAAAAAAAAAASlq1atUS6/8NnW9szz33XCxevDh/vf/++8e55567UXq/8847cdBBByVC5jfeeGO8+OKLKQuZRxT8/kSUzvcoLS0tjjjiiDj//PNj9913L/H7b8kEzQEAAAAAALZiZcqUWa+vIUOGpHp0AAAAgLWqVKlSYp2Tk5OiSSI++eSTxPrSSy/dKH2ffPLJOP7442Pp0qUR8cffBT355JNx1113bZT+a7P69yeidL5HeXl50bdv3zjiiCOibdu28fPPP5d4jy2VoDkAAAAAAMBWLC8vL/Ly8qJs2bLF+kpLS0v16AAAAABrtXDhwsQ6KysrJXOsXLkyBg8enL9OT0+PQw45pNT73nDDDdGjR4/Izc2NiIjy5ctHnz594oILLij13kWx+vcnoujfo0aNGuX/vdbqX6tWrYp58+bFsGHD4r777osddtghf9+wYcOiXbt2MXz48BJ7HlsyQXMAAAAAAICt2LbbbhtpaWkxYcKEWLp0aZG/2rZtm+rRAQAAANZqwYIFiXVhJ2hvDNOnT4/Fixfnr3faaadSnWXlypVx1llnxT333JNfq1mzZnz22Wdx9NFHl1rf4lr9+xNRMt+j9PT0qFatWrRq1SquvvrqGDVqVHTt2jXR99hjj018TyicoDkAAAAAAMBW7M/A+LBhw1I8CQAAAEDJycvLi9mzZydq9evXT8ksc+fOTazr1KlTqv2mTJkSvXr1yl9Xq1Ytvvrqq9hnn31KtW9xzZw5M7GuWrVqVKhQocT7lC9fPl555ZVo3Lhxfm3ChAnxyCOPlHivLY2gOQAAAAAAwFasbdu2kZeXF0OHDi3Wvry8vFKaCAAAAGDD/fzzzwVOrG7SpElKZlm4cGFiXdonq2dmZkZaWlr+ev78+fHWW2+Vas/18d133yXWpfn9ycrKigsuuCBRe/HFF0ut35ZC0BwAAAAAAGAr1rlz5zj66KOjYsWKxdp3yy23xAsvvFBKUwEAAABsmMLeVL/HHnukYJKIypUrJ9aLFi0q1X7169eP559/PtLT/y8mfPPNN8fNN99cqn2La/XvUWl/f1Y/0f23336LWbNmlWrPzV1GqgcAAAAAAAAgdfbcc8/o27dvsfcddthhpTANAAAAQMlY/QTvpk2bRoMGDQpc978nfxfXkiVLinRdjRo1EuuZM2eud8+i6t69e5QtWzbOOuusWLVqVURE3HXXXbF8+fL4xz/+Uer91+X777+P8ePHJ2odO3Ys1Z516tQpUJs0aVLUrl27VPtuzpxoDgAAAAAAAAAAAMAWY+zYsfHBBx8kascee2yh15YrVy6xXrp0aZH7FPU07Hr16kWlSpXy17/88kupn2oeEXHaaafFa6+9FpmZmfm1++67Ly677LJS770ujzzySGKdlZUVhx56aKn2XLFiRYHa8uXLS7Xn5k7QHAAAAAAAAAAAAIAtxtVXXx25ubn56/T09DjvvPMKvbZKlSqJ9YwZM4rc59tvvy3SdRkZGbH33nvnr3Nzc+Ojjz4qcp8NccIJJ8Sbb74ZZcuWza898sgjceGFF0ZeXt5GmWF1w4YNi9deey1RO/HEEwuc/F7SJk6cWKBW2Cnn/B9BcwAAAAAAAAAAAAC2CA899FD07ds3UTvzzDOjadOmhV7fqFGjxHr48OFF7vX6668X+dpDDjkksV79RO/SdPTRR8c777yTOL39qaeeinPOOScRyN8Y5syZEyeeeGLk5OTk1zIzM+Pmm28u9d4ff/xxYl2hQoVo0KBBqffdnAmaAwAAAAAAAAAAALBZW7lyZVx11VVx5ZVXJur16tWLv//972vct9NOO0WFChXy159++mnMnz9/nf2+/fbbAoH2tTn77LOjcuXK+euBAwfGs88+W+T9G+rQQw+N9957L/FcX3zxxTjzzDNj1apVG2WG77//Ptq0aRPjxo1L1G+++eZo1qxZqfYeN25cPP/884lap06dIisrq1T7bu4EzQEAAAAAAAAAAADYLC1btiyeffbZ2G233eLBBx9MPFahQoV46623ok6dOmvcX6ZMmTj44IPz10uXLo1rr712rT1///33OPHEE4sV0K5WrVpcdtllidrFF18c//rXv4q0f8WKFTFw4MAi9ytMp06d4sMPP4xKlSrl13r37h2nnHJKrFy5coPuvTY//vhjnHPOObH33nsXCJkfd9xxceONN5Za74iIESNGxCGHHBKLFy9O1K+66qpS7bslyEj1AAAAAAAAAAAAAADwv7777rsC4ecVK1bE/PnzY/78+TF+/PgYPHhwDBs2LJYsWVJgf926deOtt96Kfffdd529zj333MTp5M8++2ysXLky7rrrrqhfv35+fe7cudGrV6+48847Y+7cudGkSZP4/fffi/ycbrnllvjss89i8ODBERGRk5MTp5xySrz55ptx5ZVXRrt27aJMmTL5169cuTJGjBgRffv2jV69esUOO+wQAwYMKHK/whxwwAHxySefxCGHHBLZ2dkREfHmm2/GihUr4vXXX4+yZcsW6T7z5s2Lzz77rEB94cKFMX/+/JgzZ04MHz48Bg8eHGPHji30Ht27d4+nn3460tOLf272smXLCu0fEZGbmxsLFy6MMWPGxH/+85/47LPPIjc3N3HNOeecE+3bty92362NoDkAAAAAAAAAAAAAm5Srr756vfeefPLJ8dBDD0W9evWKdP2hhx4aRxxxRLz33nv5tRdffDF69uwZzZo1i2rVqsXcuXNj7Nix+YHlihUrxhtvvBGtWrUq8lyZmZnx1ltvxcEHHxyjR4/Or7/99tvx9ttvR+XKlaNhw4ZRuXLlWLBgQYwfPz6WLVuWf90OO+xQ5F5rs/fee8fnn38eXbp0iXnz5kVExDvvvBPHHntsvP3225GVlbXOe4wcOTI6d+68Xv232WabeOCBB+KUU05Zr/0RETNmzFjv/ieffHI8/fTT6917a1L8twAAAAAAAAAAAAAAwCakRo0ace6558aPP/4Yr732WpFD5n966aWXok2bNolaXl5e/PrrrzF06NAYM2ZMfsi8Ro0a8cEHH8See+5Z7Dm33XbbGDRoUBx11FEFHlu4cGH897//jSFDhsTPP/+cCJmXtNatW8d//vOfqFWrVn7tgw8+iCOPPDKWLl1aKj332muvePrpp2Ps2LEbFDJfXw0aNIiXXnopXnvttcTJ8ayZE80BAAAAAAAAAAAA2OSVLVs2ypUrFzVr1ox69epFs2bNYpdddol999032rRpE5mZmet97xo1akT//v3j3nvvjYcffjgWLVpU4JqMjIw4+eST4+9//3vUr19/vXtVrVo13n333RgwYEDcc889MWDAgMjJyVnj9TvttFOccMIJce655653z8K0bNkyBgwYEJ06dYoZM2ZERMSnn34ahx12WPTr1y8qVapUrPulp6dHVlZWVK5cOerUqRPbbbdd7LzzztG6deto3779Bv2ZFVelSpWiatWqsf3220erVq2iS5cucfDBBwuYF1NaXl5eXqqHgLUZPXp07LLLLvnrUaNGxV/+8pcUTgQAAAAAAAAAAMC6rFy5Mn777bdErVmzZpGR4YxcNm05OTkxcODA+O2332LOnDlRrly5aNKkSbRv3z6qV69e4v0WL14cgwYNismTJ8fs2bNj1apVUaVKldh+++1jt912iwYNGpR4T0pWab3epTpD69UaAAAAAAAAAAAAAP5/ZcuWjU6dOkWnTp02Sr+KFStGly5dNkovKA5BcwAAAAAAgK3RbVVL4Z4LSv6eAAAAAEBKpKd6AAAAAAAAAAAAAAAANi2C5gAAAAAAAAAAAAAAJAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAAECCoDkAAAAAAAAAAAAAAAmC5gAAAAAAAAAAAAAAJAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAAECCoDkAAAAAAAAAAAAAAAmC5gAAAAAAAAAAAAAAJAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAAECCoDkAAAAAAAAAAAAAAAmC5gAAAAAAAAAAAAAAJAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAAECCoDkAAAAAAAAAAAAAAAmC5gAAAAAAAAAAAAAAJAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAAECCoDkAAAAAAAAAAAAAAAmC5gAAAAAAAAAAAAAAJAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAAECCoDkAAAAAAAAAAAAAAAmC5gAAAAAAAAAAAAAAJAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAwBanZ8+ekZaWlv/Vs2fPVI8EmxVBcwAAAAAAAAAAAAAAEgTNAQAAAAAAAAAAAGADdOvWLXF6emFfZcuWjcqVK0fDhg2jVatW0bVr17j55pvj/fffjwULFmxQ/9tuu22d/f/8KleuXNStWzdatmwZ3bt3j5dffjkWL15cQn8SbEkyUj0AAAAAAAAAAAAAwDrdVjXVE2w5btuwUDPrZ8WKFbFixYpYtGhRTJ48Ob7//vv8x8qWLRtdunSJ8847L4444ohIS0srtTmWL18eM2fOjJkzZ8aIESOiZ8+ecdFFF8Wtt94al112WWRkiBfzByeaAwAAAAAAAAAAAEAK5eTkxHvvvRdHHXVUtGrVKgYPHrxR+y9cuDCuvvrqOPbYY2P58uUbtTebLm85AAAAAAAAAAAAAIASdMYZZ8SZZ56ZqOXm5sb8+fNj/vz5MX369Bg6dGgMGTIkZs+enbhu+PDhsd9++8X9998fl19++Xr179KlS1xzzTWFPrZ48eKYMmVKfP311/HOO+/E4sWL8x9777334uqrr45HH310vfqyZRE0BwAAAAAAAAAAAIAStMMOO8RBBx20zuvy8vLio48+ioceeig+/fTT/PqqVaviiiuuiJycnLj22muL3X+bbbZZZ/8ePXrE1KlT46STToqvvvoqv/7EE0/EZZddFk2bNi12X7Ys6akeAAAAAAAAAAAAAAC2RmlpaXHooYfGJ598Ei+//HJUqFAh8fh1112XCKCXtPr168e///3vqFmzZn4tNzc3+vTpU2o92XwImgMAAAAAAAAAAABAip1++unx+eefR9myZfNreXl5ccEFF0ROTk6p9a1evXqcdNJJidrIkSNLrR+bj4xUDwAAAAAAAAAAAAAAhZk4cWIMGzYsZs2aFXPmzImyZctGjRo1YqeddoqWLVtGxYoV1/veubm5MXTo0BgxYkTMmTMnKlasGNtss00ccMABUa9evRJ8FkXXrl27uO++++Kyyy7Lr40dOzZ69uwZ5513Xqn1bdGiRWI9a9asUuvF5kPQHAAAAAAAAAAAAIBNxqJFi+KRRx6Jnj17xm+//bbG67KysuKAAw6Ic845J4477rjIzMws0v1zc3PjySefjHvvvTcmT55c4PG0tLTo0qVL3H///bHLLrus9/NYXxdffHH885//jLFjx+bXnnrqqVINmqelpSXW5cuXL7VebD7SUz0AAAAAAAAAAAAAAEREvPvuu7H99tvHjTfeuNaQeUTE8uXL49NPP42TTz45Bg0aVKT7Z2dnR5cuXeLiiy8uNGQeEZGXlxcff/xx7LXXXvHxxx8X+zlsqPT09LjkkksSteHDh8fEiRNLredPP/2UWDdt2rTUerH5EDQHAAAAAAAAAAAAIOUefPDBOO6442L27NmJelpaWjRs2DBatWoVLVu2jPr166/X/VesWBFHHHFEfP755/m1OnXqxJ577hm77bZbVKxYMXH9kiVLomvXrjFhwoT16rchjjvuuAK1/v37l0qv7OzseOONNxK1zp07l0ovNi+C5gAAAAAAAAAAAACk1DvvvBNXXXVV5Obm5tfq1q0bjzzySEydOjUmTpwYw4YNi+HDh8eUKVNixowZ8eqrr8ZRRx0V6elFi8Pee++9MXDgwIiIOO2002LkyJExY8aM+O6772LEiBExZ86ceOGFF6JKlSr5exYtWhTXXnttyT7ZIthuu+2iXr16idrw4cNLvM/MmTPj2GOPjZkzZ+bXWrZsGV26dCnxXmx+MlI9AAAAAAAAAAAAAABbrxkzZkT37t0Ttf333z/+/e9/R7Vq1QrdU6dOnTjllFPilFNOiV9//TUqVKiwzj5jx46NtLS0eOaZZ+Kvf/1rgcezsrKie/fu0bRp0+jQoUN+6L1v374xa9asqF27dvGf3AZo1apVvP/++/nrsWPHFnnvtGnT4rPPPiv0sSVLlsTUqVPjm2++ib59+8bChQvzH6tXr168/vrrRQ7vs2UTNAcAAAAAAAAAAAAgZf75z3/G/Pnz89fNmjWLDz/8MCpWrFik/TvuuGORe1166aWFhsz/1/777x8nnHBCvP766xERsWLFivj888/j5JNPLnKfklCrVq3Eetq0aUXe+8knn8Qnn3xS5OurVKkSp512Wtx+++0bPVDPpsvbDQAAAAAAAAAAAABIiZycnHjyyScTtaeeeqrIIfPiKF++fNx8881Fuvakk05KrL///vsSn2ddVj/NfdGiRaXSp3z58nHGGWfE+eefL2ROgqA5AAAAAAAAAAAAACkxdOjQxGnmu+yySxx44IGl0uuggw6KmjVrFunali1bJtaTJk0qhYnWrlKlSol1Tk5OqfRZunRpPP7449GyZcs47bTTYsGCBaXSh82PoDkAAAAAAAAAAAAAKTFw4MDE+tBDDy21Xq1bty7ytXXq1EmsUxG+XrhwYWKdlZVV5L1nnXVW5OXlFfqVk5MTM2fOjP79+8dVV10VVapUyd/36quvRvv27WPevHkl9jzYfAmaAwAAAAAAAAAAAJASv//+e2JdnDB4ca0eHl+bihUrJtZLly4t6XHWafVw++onnK+vzMzMqF27dnTo0CHuv//+GDVqVDRv3jz/8REjRsS5555bIr3YvAmaAwAAAAAAAAAAAJASc+fOTayLEwYvrnLlyq333ry8vBKcpGhmzpyZWNevX79U+jRs2DD69OkT6en/Fyvu06dPfPPNN6XSj82HoDkAAAAAAAAAAAAAKbFw4cLEuqRO7d4SfP/994l1kyZNSq1X8+bNo0uXLonaiy++WGr92DwImgMAAAAAAAAAAACQEpUrV06sFy1alKJJNi0TJkyIGTNmJGp77LFHqfbcZ599EutBgwaVaj82fYLmAAAAAAAAAAAAAKREjRo1EuuZM2emaJJNy1tvvVWg1rFjx1LtWadOncR60qRJpdqPTZ+gOQAAAAAAAAAAAAAp0axZs8R62LBhKZpk05GbmxuPP/54otamTZvYdtttS7XvihUrEuvly5eXaj82fYLmAAAAAAAAAAAAAKTE/vvvn1h/+OGHKZpk0/HYY4/FuHHjErULLrig1PtOnDgxsV79hHO2PoLmAAAAAAAAAAAAAKREmzZtokaNGvnrUaNGxX/+858UTpRagwcPjmuuuSZR23HHHeOMM84o9d4ff/xxgb5s3QTNAQAAAAAAAAAAAEiJzMzM6NGjR6J2wQUXxOLFi1M0Ueq88sor0alTp8jJycmvpaenx9NPPx2ZmZml2vvNN9+MkSNHJmqHH354qfZk0ydoDgAAAAAAAAAAAEDKXHrppYlTzX/77bc47LDDYv78+UXa/8svv8TkyZNLabrSlZeXFx999FF06dIlzjjjjFiyZEni8QceeCA6dOhQqjO8+eab0b1790StRo0a0a1bt1Lty6YvI9UDAAAAAAAAAAAAALD1ql27dvTs2TOOPvroyMvLi4iIL7/8Mpo3bx433nhjnHDCCVG3bt3EnpkzZ8bnn38er732Wrz//vvx+eefR4MGDVIxfqHGjh0bn332WaKWm5sbCxYsiPnz58f06dNj6NChMXjw4Jg9e3aB/ZmZmfHwww8XOO29qKZNm1ag/59WrlwZ8+bNi9GjR0e/fv0KnGQeEfHwww8nwv9snQTNAQAAAAAAAAAAAEipI488Mh588MG48sor88Pm06dPj0suuSQuvfTS2G677aJ27dqxatWqmDFjRkydOjXFE6/dyy+/HC+//PJ67W3dunU8+eST0bp16/Xu/8knn8Qnn3xS7H1lypSJBx54IM4444z17s2WQ9AcAAAAAAAAAAAAgJS7/PLLY7vttotzzz035s6dm1/Py8uLCRMmxIQJE1I4XekqW7ZsHHLIIXH++efHYYcdlpIZ2rRpE4899li0bds2Jf3Z9AiaAwAAAAAAAAAAAJu+2xakegI2guOOOy46deoUDzzwQPTq1Wut4fKKFStGp06d4uyzz479999/I065fjIyMiIrKyuqVasWdevWje233z5atGgR7dq1i/333z8qV668UeZIT0+PKlWqRLVq1WLnnXeONm3axLHHHht77LHHRunP5iMt78/PF4BN1OjRo2OXXXbJX48aNSr+8pe/pHAiAAAAAADYAtxWtRTu6R/8AQAA+D8rV66M3377LVFr1qxZZGQ4I5ei++mnn2LkyJExa9asmD9/flSoUCFq164dO++8c+y2226RlZWV6hGh1F7vUp2h9WoNAAAAAAAAAAAAwCapefPm0bx581SPAVul9FQPAAAAAAAAAAAAAADApkXQHAAAAAAAAAAAAACABEFzAAAAAAAAAAAAAAASBM0BAAAAAAAAAAAAAEgQNAcAAAAAAAAAAAAAIEHQHAAAAAAAAAAAAACABEFzAAAAAAAAAAAAAAASBM0BAAAAAAAAAAAAAEgQNAcAAAAAAAAAAAAAIEHQHAAAAAAAAAAAAACABEFzAAAAAAAAAAAAAAASBM0BAAAAAAAAAAAAAEgQNAcAAAAAAAAAAAAAIEHQHAAAAAAAAAAAAACABEFzAAAAAAAAAAAAAAASBM0BAAAAAAAAAACAEpeWllaglpeXl4JJAEpXbm5ugVphr4GbG0FzAAAAAAAAAAAAoMSlpxeMKK5YsSIFkwCUrpUrVxaoFfYauLnZ/J8BAAAAAAAAAAAAsMlJS0uLsmXLJmqLFi1K0TQApWf117ayZcs60RwAAAAAAAAAAABgTSpXrpxYZ2dnR15eXoqmASh5eXl5kZ2dnait/tq3uRI0BwAAAAAAAAAAAErF6mHLFStWxJQpU4TNgS1CXl5eTJkyJVasWJGoV6lSJUUTlayMVA8AAAAAAAAAAAAAbJnKlSsXmZmZiRDmwoUL4/fff48qVapEpUqVIiMjI9LTnZsLbB5yc3Nj5cqVsWjRosjOzi4QMs/MzIysrKwUTVeyBM0BAAAAAAAAAACAUpGWlhb169ePiRMnJk4xX7FiRcyZMyfmzJmTwukAStafr3lpaWmpHqVEeAsQAAAAAAAAAAAAUGoqVKgQ22233RYTvAQoTFpaWmy33XZRoUKFVI9SYgTNAQAAAAAAAAAAgFL1Z9g8MzMz1aMAlLjMzMwtLmQeEZGR6gEAAAAAAAAAAACALV+FChWiSZMmsXz58sjOzo6FCxdGTk5OqscCWC9ly5aNypUrR5UqVSIrK2uL/NQGQXMAAAAAAAAAAABgo0hLS4ty5cpFuXLlok6dOpGXlxe5ubmRl5eX6tEAiiQtLS3S09O3yGD56gTNAQAAAAAAAAAAgJRIS0uLMmXKpHoMAAqRnuoBAAAAAAAAAAAAAADYtAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAAECCoDkAAAAAAAAAAAAAAAmC5gAAAAAAAAAAAAAAJAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAAECCoDkAAAAAAAAAAAAAAAmC5gAAAAAAAAAAAAAAJAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAAECCoDkAAAAAAAAAAAAAAAmC5gAAAAAAAAAAAAAAJAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAAECCoDkAAAAAAAAAAAAAAAmC5gAAAAAAAAAAAAAAJAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAAECCoDkAAAAAAAAAAAAAAAmC5gAAAAAAAAAAAAAAJAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAAECCoDkAAAAAAAAAAAAAAAmC5gAAAAAAAAAAAAAAJAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAAECCoDkAAAAAAAAAAAAAAAmC5gAAAAAAAAAAAAAAJAiaAwAAAAAAAAAAAACQIGgOAAAAAAAAAAAAAECCoDkAAAAAAAAAAAAAAAmC5gAAAAAAAAAAAAAAJAiap9iUKVOib9++cd1118WBBx4YVapUibS0tPyvxo0bl2r/H3/8McqWLZvomZaWFj179izVvgAAAAAAAAAAAADApisj1QNsjQYNGhQPPPBADBkyJKZOnZqyOVatWhXnnHNOrFixImUzAAAAAAAAAAAAAACbHkHzFPj222+jb9++qR4jHnroofj2229TPQYAAAAAAAAAAAAAsIlJT/UAJFWqVGmj9Pn999/jlltuyV9XrFhxo/QFAAAAAAAAAAAAADZ9TjRPocqVK0erVq2iTZs20bZt22jTpk2MGzcuOnbsWKp98/Ly4txzz42lS5dGRMSRRx4Z2dnZ8cUXX5RqXwAAAAAAAAAAAABg8yBongJHHnlkdOnSJXbeeedIT08eKj9u3LhS7//ss89G//79I+KPE9Qff/zxOOOMM0q9LwAAAAAAAAAAAACweRA0T4EmTZqkrPeUKVPi2muvzV//7W9/i4YNG6ZsHgAAAAAAAAAAAABg05O+7kvYkvTo0SMWLFgQERFt27aNiy++OMUTAQAAAAAAAAAAAACbGkHzrci//vWv+Pe//x0RERkZGfHss89GerofAQAAAAAAAAAAAAAgScp4KzFnzpy49NJL89dXXXVV7LbbbimcCAAAAAAAAAAAAADYVAmabyUuu+yymDVrVkRENGnSJG699dYUTwQAAAAAAAAAAAAAbKoEzbcCH3zwQfTu3Tt//dRTT0X58uVTOBEAAAAAAAAAAAAAsCkTNN/CLVy4MC644IL89RlnnBEHHXRQCicCAAAAAAAAAAAAADZ1GakegNL1//7f/4tJkyZFREStWrXiwQcfTOk8M2fOjFmzZhVrz5gxY0ppGgAAAAAAAAAAAACgMILmW7CBAwfGU089lb9+4IEHolatWimcKOKJJ56I22+/PaUzAAAAAAAAAAAAAABrl57qASgdy5Yti3POOSfy8vIiIuKggw6KM888M8VTAQAAAAAAAAAAAACbA0HzLdStt94av/32W0RElC9fPnGyOQAAAAAAAAAAAADA2mSkegBK3vfffx8PPPBA/vqWW26JJk2apHCi/9OjR4844YQTirVnzJgxccwxx5TOQAAAAAAAAAAAAABAAYLmW5iVK1fG2WefHatWrYqIiN122y2uvvrqFE/1f+rUqRN16tRJ9RgAAAAAAAAAAAAAwFqkp3oAStYrr7wSI0aMiIiI9PT0eOaZZyIjw/sJAAAAAAAAAAAAAICiEzTfwsyfPz//v3Nzc6Ndu3aRlpa2zq8vvvgicZ/u3bsnHj/mmGM27hMBAAAAAAAAAAAAAFJG0BwAAAAAAAAAAAAAgARBcwAAAAAAAAAAAAAAEjJSPQAl6/jjj49ddtml2PuuuuqqGDlyZP76mmuuiS5duuSv69SpUyLzAQAAAAAAAAAAAACbPkHzLUzDhg2jYcOGxd5XvXr1xLpFixZx0EEHldRYAAAAAAAAAAAAAMBmJD3VAwAAAAAAAAAAAAAAsGkRNAcAAAAAAAAAAAAAICEj1QNsrQYNGhRLly4tUB8xYkRivWzZsvjss88KvUf9+vWjRYsWpTIfAAAAAAAAAAAAALD1EjRPkdNOOy0mTJiwzutmzJgRnTt3LvSxs846K3r27FnCkwEAAAAAAAAAAAAAW7v0VA8AAAAAAAAAAAAAAMCmRdAcAAAAAAAAAAAAAICEjFQPsLUaP358qkdIGDBgQKpHAAAAAAAAAACA/4+de4+ysq4XP/7ZwwByURTlInKRi2igpnHxkoFoKGgDmnlEPaEeMo/kSdNqSSaFt45HPaIWYaWRhbfQNCJvZEhAgiDRyUBFGK6CIBcBGRDm+f1R7p9fFWJkhj0zvF5rzWo/3/18v89nu1r+9fYBAKCa8EZzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAAEkJzAAAAAAAAAAAAAAASQnMAAAAAAAAAAAAAABJCcwAAAAAAAAAAAAAA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CaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkAAAAAAAAAAAAAAAmhOQAAAAAAAAAAAAAACaE5AAAAAAAAAAAAAAAJoTkA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Lo466qjo3LnzDu+dOHFiXHPNNZFlWURE5HK55Pssy+Khhx6KfffdN3784x9X6dwAAAAAAAAAAAAAADVZtX6j+fPPP5//PGjQoJ3ee/XVV0eWZfnAPMuyaN68eeyzzz759SzL4ic/+UlMmzatSucGAAAAAAAAAAAAAKjJqm1ovmDBgli9enX+un///ju8949//GP87W9/y0fmPXr0iNdffz3efPPNWLduXdxxxx0R8f/fcn7nnXdW4eQAAAAAAAAAAAAAADVbtQ3NX3vttfznunXrxpFHHrnDex9++OGI+MdbzOvWrRvjxo2Ljh075vd+4xvfiMsvvzyyLIssy2LChAmxefPmqv0BAAAAAAAAAAAAAAA1VLUNzRctWhQR/3gLebt27aJOnTo7vPfZZ5+NXC4XuVwuBgwYEG3atPnIPVdeeWX+85YtW2LOnDmVPzQAAAAAAAAAAAAAQC1QbUPzDRs25D83adJkh/ctXrw4H6VHRJx11lkfe99hhx0WzZo1y1/Pmzdv94cEAAAAAAAAAAAAAKiFqm1ovmXLlvznnb3NfNq0aRERkWVZRESccsopO7z3g286X7t27e6OCAAAAAAAAAAAAABQK1Xb0LxRo0b5z+vXr9/hfS+88EL+c4cOHaJly5Y7vLdevXr5z+++++5uTggAAAAAAAAAAAAAUDtV29D8wAMPjIh/vKm8tLQ0tm3b9rH3PfPMMxERkcvlolevXjs9c926dfnPDRs2rJxBAQAAAAAAAAAAAABqmWobmh955JH5z1u2bImJEyd+5J4///nPUVpaGrlcLiIiTj755J2euWLFivznpk2bVs6gAAAAAAAAAAAAAAC1TLUNzY866qg44IADIpfLRZZl8d3vfje2bNmS/3779u1x/fXXR8Q/3npep06dOO2003Z43uLFi5M3mnfo0KHKZgcAAAAAAAAAAAAAqMmKCz3AjhQXF8f5558fo0aNilwuF7Nnz47PfOYzcfHFF0fdunXj0UcfjenTp+ffZn766adHixYtdnjetGnTkusuXbpU6fwAAAAAAAAAAAAAADVVtQ3NIyKuv/76GDt2bLzzzjsRETF37ty49tprk3uyLIuioqIYPnz4Ts967LHH8p87deoUBx54YOUPDAAAAAAAAAAAAABQCxQVeoCdadGiRTz66KNRr169yLIs//by92VZFhERN9xwQ/To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s/z1q6++WhljAgAAAAAAAAAAAADUOtU2NJ86dWpkWRZZlkVxcXEMGjRot8886KCD8p9Xr1692+cBAAAAAAAAAAAAANRG1TY0X7FiRURE5HK56NSpUzRq1Gi3z9xvv/3ynzdu3Ljb5wEAAAAAAAAAAAAA1EbFhR5gR9avX5///MFAfHds2rQp/7lBgwaVcmZNtGXLlpg9e3bMnTs31q5dG5s3b4799tsvmjdvHp/5zGeiU6dOkcvlCj0mAAAAAAAAAAAAAFAg1TY0P+CAA/KfPxid747335IeEXHggQdWypk1yaxZs+LOO++McePGxZYtW3Z43yGHHBJDhgyJK6+8Mpo2bboHJwQAAAAAAAAAAAAAqoOiQg+wIy1atIiIiCzLYuHChbF169bdOu/111+P1atX56/btGmzW+fVJOXl5XHttddGz549Y+zYsTuNzCMili1bFjfccEN06dIlnn766T00JQAAAAAAAAAAAABQXVTb0Lx79+75z1u3bo3nn39+t84bO3Zs/nO9evXi+OOP363zapLLLrssbr311igvL0/WGzZsGEcddVT07NkzOnbsGLlcLvl+5cqVMXDgwHjqqaf25LgAAAAAAAAAAAAAQIFV29C8TZs20aVLl3z8fOutt37is95888245557IpfLRS6Xi5NOOin22Wefyhq1Whs3blz87Gc/S9a6dOkSEyZMiPXr18df//rXmD59esyfPz9WrlwZI0aMiHr16uXv3bp1a1x00UWxdu3aPT06AAAAAAAAAAAAAFAg1TY0j4i49NJLI8uyiIiYPHly3HzzzRU+Y8OGDfGlL30p1q5dmz/rqquuqswxq7URI0Yk1927d48ZM2bEGWecEcXFxcl3zZo1i+HDh8dTTz2VfLdq1aoYPXr0HpkXAAAAAAAAAAAAACi8ah2aDx06NA499NCIiMiyLIYPHx5f+9rXYv369bu0/5lnnomePXvGiy++mH+beY8ePeLMM8+swqmrjwULFsTf/va3ZG3UqFHRqFGjne475ZRTYsiQIcna+PHjK30+AAAAAAAAAAAAAKB6Kv7XtxRO3bp146GHHopTTjklysrKIsuyGD16dDzwwANRUlIS3bp1i4h/ROi5XC4mTJgQL7/8csyfPz+ef/75eOONN/LfZVkWTZs2jYceeqjAv2rPefXVV5Pr1q1bR48ePXZp7znnnBP33ntv/nr+/PmVOhsAAAAAAAAAAAAAUH1V69A8IuK4446Lhx9+OAYNGhRlZWUREbFp06Z45JFH4pFHHsnfl2VZjBw5MrmOiHxk3qRJkxg3bly0b99+j85fSGvWrEmu27Rps8t727Ztm1yvW7euMkYCAAAAAAAAAAAAAGqAokIPsCtKSkpixowZ0aVLl/wbyt+Xy+Xyf1mWJYH5+2tdu3aN6dOnx8knn1ygX1AYTZo0Sa43b968y3s/fO9BBx1UKTMBAAAAAAAAAAAAANVfjQjNIyK6du0af/nLX+LBBx+Mnj17RkTkw/IPBuYfXO/atWv84he/iDlz5kTnzp0LNXrBHHPMMcn13LlzY9OmTbu0d8aMGcn1+//MAQAAAAAAAAAAAIDar7jQA1REnTp1YtCgQTFo0KBYs2ZNTJkyJebOnRtvv/12rFu3Lho2bBgHHXRQtG/fPvr06ROtWrUq9MgF1bp16zjxxBNj2rRpERGxZcuWuPvuu2PYsGE73bdly5YYOXJksjZkyJCqGhMAAAAAAAAAAAAAqGZqVGj+QU2bNo0BAwbEgAEDCj1KtXbrrbdG7969o7y8PCIihg8fHq1atYqLLrroY+9ft25dfPnLX465c+fm10pKSqKkpGSPzAsAAAAAAAAAAAAAFF6NDc3ZNSeddFL88Ic/jK997WuRZVls27YtLr744vjRj34UX/ziF+Pwww+PBg0axOrVq2P69Onx4IMPxpo1a/L7+/btGw899FABfwEAAAAAAAAAAAAAsKcJzfcCl19+eRx++OHx9a9/PV555ZWIiHjppZfipZde2uGeDh06xLe//e249NJLo6ioqNJmeeutt2LVqlUV2jN//vxKez4AAAAAAAAAAAAA8K8JzfcSp5xySrz00ksxfPjwuPPOO2P79u07vLdt27bxzW9+My644IJKjcwjIkaNGhUjRoyo1DMBAAAAAAAAAAAAgMpVuRUx1dbo0aOjY8eOcfvtt+80Mo+IWLx4cQwdOjQOPfTQuP/++/fQhAAAAAAAAAAAAABAdVGj3mi+ffv2mDlzZsyePTsWL14c77zzTmzevDmyLKvQOblcLu67774qmrJ6ee+99+L888+Pxx57LL/WtGnTuOKKK+ILX/hCHHbYYdGoUaNYvXp1zJw5M37+85/HE088EVmWxZo1a2LIkCExd+7cuO222wr4KwAAAAAAAAAAAACAPalGhObr16+Pm266KX75y1/GqlWrduusLMv2qtD88ssvTyLznj17xpNPPhktW7ZM7jv44IOjpKQkSkpK4re//W2cd955UVZWFhERt99+e3Tp0iUuueSS3Z5n6NChce6551Zoz/z58+Os/8fe3cd7PR/+43+8izqqIZU1UqlJ2MoqJFPIVa5zzURyObUhFxuxbGz4fI2NLWTI2D7GykVrm8uilZW0T62ZrpTUakVFF4p0fn98fvrsrLLinPPunHO/327ntvN6XrzPIy/jXR6v5/uEEz73zwYAAAAAAAAAAAAANs0WXzR/5ZVX0rNnzyxatKjMyeWFQqGIqaqGUaNGlSnU77jjjvnd736XJk2afOq+4447Lj//+c9z3nnnrRu76qqrcvrpp2ebbbb5XJl23HHH7Ljjjp/rNQAAAAAAAAAAAACAilWr2AE+zd/+9rccccQRWbhw4bqTyD9RWlr6mb5qkjvvvLPM9WWXXfYfS+af6N27d9q0abPu+t13382wYcPKNR8AAAAAAAAAAAAAsGXaok80v+SSS7J8+fJ1BfPS0tIcfvjhOf744/PVr341jRo1Sr169YqccstUWlqaF198sczYscceu8n7a9WqlaOPPjrTpk1bN/byyy/nG9/4RrllBAAAAAAAAAAAAAC2TFts0XzmzJkZPXp0CoVCSktL07BhwwwdOjQHHXRQsaNVCUuWLMl7771XZmzXXXfdrNf49/Xz5s373LkAAAAAAAAAAAAAgC1frWIH2JgxY8Yk+d+TuQuFQu69914l882wevXq9ca22mrznivYeuuty1x//PHHnysTAAAAAAAAAAAAAFA1bLFF8wULFqz7vmHDhjnppJOKmKbqadSo0Xpj//jHPzbrNf79BPMmTZp8rkwAAAAAAAAAAAAAQNWwxRbNa9eunSQpFApp1apVCoVCkRNVLXXq1MmXvvSlMmMvvvjiZr3GCy+8UOa6devWnzsXAAAAAAAAAAAAALDl22KL5s2bN1/3/apVq4qYpOrq3r17meuf/OQnWbNmzSbtfemll/LKK6986usBAAAAAAAAAAAAANXTFls079KlSwqFQkpLSzN79uxNLkjzf84666wy11OmTMkll1yStWvXfuq+GTNm5Mwzzywztttuu2X//fcv94wAAAAAAAAAAAAAwJZniy2a77zzzjn00EOTJCtW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OfHEE1NSUlLsaJ/J7Nmz06dPn7z00ktJktLS0vXWvPbaaxk2bFi+//3v56CDDsr999+fli1bVnJSAACqGkVzAAAAAAAAAACqjWuvvTYdO3bMSSedVGZ8xYoVOfvss/Pkk08m+b9CdqFQyNVXX53f/va36dy5c2XH/Vz+8Y9/pHPnzlm4cGHatWuXk08+OR06dEizZs1Sv379JP/76547d24mTpyYxx9/PCNHjsz++++f1157LTvttFORfwUAAGzJFM0BAAAAAAAAAKg2brnllvTu3Xu9onnv3r3zxBNPpFGjRjn33HOz2267ZcmSJRk2bFjGjx+fY445Jn/961/zpS99qUjJN9/111+fhQsX5vbbb89ll1220XXt2rXLUUcdleuuuy633357rrzyynzve9/LL37xi8oLCwBAlaNoDgAAAAAAAABAtTZx4sQMHTo0zZo1y/jx49O0adN1c1dffXUuvvjiDB48OD/5yU9y6623FjHp5vnjH/+Y/fbb71NL5v+uf//+efzxx/OHP/yh4oIBAFAt1Cp2AAAAAAAAAAAAqEh/+MMfUigU8l//9V9lSuaf+PGPf5xGjRpVufL14sWL07Jly83e16JFiyxevLj8AwEAUK0omgMAAAAAAAAAUK3NnTs3SdK1a9cNztevXz8dOnTIrFmzKjPW59a8efOMHj06K1eu3OQ9K1euzOjRo7PLLrtUYDIAAKoDRXMAAAAAAAAAAKq1kpKSJEnDhg03uqZJkyb5+OOPKytSuTjttNPyj3/8I0cccUQmT578H9dPnjw5RxxxRBYsWJAzzzyzEhICAFCVbVXsAAAAAAAAAAAAUJ5mzJiRX/7yl+uuFy9enCR566230rZt2w3umT9/fho3blwp+crLtddem+eeey5jxozJ1772tbRu3TodOnRIs2bNUq9evST/e4L53LlzM3HixMycOTOlpaXp3LlzrrnmmiKnBwBgS6doDgAAAAAAAABAtTJmzJiMGTNm3XVpaWkKhUL+8Ic/bLBovnz58rz66qvp1KlTZcb83EpKSjJq1KjceOON+fnPf54ZM2ZkxowZSZJCoZDkf3/tn9huu+3Sr1+/XHfddalbt25RMgMAUHUomgMAAAAAAAAAUG0MHDhwo3M77rjjBsd/+ctfZvny5encuXNFxaowdevWzU033ZSBAwdmzJgxmTRpUubMmZPly5cnSRo0aJDmzZunffv2OeCAA7L11lsXOTEAAFWFojkAAAAAAAAAANXGpxXNN+bUU0/N0UcfnUaNGlVAosqx9dZb56CDDspBBx1U7CgAAFQTiuYAAAAAAAAAANRojRs3TuPGjYsdAwAAtii1ih0AAAAAAAAAAAAAAIAtixPNAQAAAAAAAAColpYsWZIRI0Zk0qRJeeutt7Js2bLUqlUrDRs2zF577ZWDDjoo+++/f7FjVqrevXtnzpw5KRQKeeGFF4odBwCALZiiOQAAAAAAAAAA1cry5ctz1VVX5YEHHsiaNWvWmy8tLU2hUEiSfOUrX8ldd92Vrl27VnbMohg3blymTp267tcPAAAbo2gOAAAAAAAAAEC1sXLlyhx44IGZPHlyGjRokHbt2qVRo0aZNWtW/vrXv2brrbfOFVdckdq1a2fMmDF5+eWXc8ghh2Tw4MHp06dPseNXuJtvvjnvvfdesWMAAFAFKJoDAAAAAAAAAFBt/OhHP8qkSZNyxhln5Gc/+1kaNmy4bm7ChAk5+eSTM3To0PzP//xPttlmm0yePDknnXRSvvnNb6ZTp05p165dEdNXvBNOOKHYEQAAqCJqFTsAAAAAAAAAAACUl8cffzwtWrTIQw89VKZkniSdOnXK4MGDM3369PzmN79JkrRr1y5PP/101q5dm9tuu60YkQEAYIukaA4AAAAAAAAAQLUxZ86cdOzYMVtttdUG57t06ZIkee2119aN7bHHHtl///0zcuTISslYGSZPnpxevXqlefPmKSkpSePGjXP44Ydn2LBhxY4GAEAVoWgOAAAAAAAAAEC10aBBg7z11lsbnf9krnbt2mXGd9lllyxatKhCs5W3q6++OnXq1MmECRPKjD/66KPZd9998+tf/zpz587Nhx9+mMWLF+f555/PKaeckm9+85tFSgwAQFWiaA4AAAAAAAAAQLXRpUuXTJw4MQ899NB6c2vWrMmVV16ZQqGQDh06lJlbtGhRtt9++0pKWT5eeOGFNGvWLJ06dVo3Nn/+/Jx33nn58MMPc/LJJ+f3v/99Xn/99fzpT3/KTTfdlIYNG2bw4MF55JFHipgcAICqYMOfEQQAAAAAAAAAAFXQNddck9///vfp06dPHn300XTr1i0NGzbMW2+9lf/+7//OnDlz0qxZs5x66qnr9nz88ceZNGlS9tprryIm33yzZ8/O/vvvX2bsscceywcffJCrrroqt956a5m5Ll265Kijjsr++++fe++9N2eddVZlxgUAoIpRNAcAAAAAAAAAoNro3LlzhgwZkgsuuCDPPPNMnn322XVzpaWladasWYYPH56SkpJ141OmTMmee+5Z5YrXH3zwQbbddtsyY9OmTUuhUEi/fv02uGfvvfdOly5d8uqrr1ZGRAAAqjBFcwAAAAAAAAAAqpVvfOMbOeiggzJkyJC89tprWbFiRZo0aZKuXbvmG9/4RurXr19mffv27TNy5Mgipf3smjdvnilTppQZ+6RAX69evY3u22abbVJaWlqh2QAAqPoUzQEAAAAAAAAAqHZ23nnnDBgwoNgxKtQxxxyTO+64IyNGjMjRRx+dJDn00ENzxx135Le//W0uuuii9fYsWLAgY8eOzR577FHZcYEka9euzVNPPZXhw4dn8uTJeeutt7Js2bIkyRe+8IW0aNEi7dq1y3HHHZfjjjsutWrVKnJiAGoy/xYCAAAAAAAAAIAq6Lvf/W4aNmyY008/Pffee29Wr16dHj165Pjjj8/ll1+eH//4x3n33XeTJB999FGef/75HHnkkXnvvfc2WEIHKtaECROyxx575OSTT86QIUMyceLEvPvuu/nwww/z4Ycf5t13383EiRMzZMiQnHTSSdlzzz0zYcKEYscGoAZTNAcAAAAAAAAAgCqocePGeeaZZ1JSUpJLLrkkTZo0Sbdu3bLVVltlzZo1ufrqq7PjjjvmC1/4QrbZZpscccQRmTx5cs4555ycd955xY4PNcobb7yRgw46KNOnT8+xxx6bX/7yl5kyZUqWLl2ajz76KB999FGWLl2aKVOm5Je//GWOOeaYTJs2LQcffHDeeOONYscHoIbaqtgBAAAAAAAAAACgmAYMGJD58+enUCjk/vvvL3aczdKxY8f8/e9/z/e+97386le/yujRo9dbs2LFiiRJ+/btc/XVV+eMM86o7JhQ4w0cODCrVq3K0KFD07Nnzw2u2XbbbbPnnntmzz33zFlnnZVhw4bllFNOyQ033JBHH320khMDgKI5AAAAAAAAAAA13LBhwzJ16tQqWTRP/vdk80GDBuX222/PhAkT8vrrr2fJkiVZu3ZtGjRokBYtWuRrX/tadtlll2JHhRpr5MiR6dq160ZL5hty4oknplu3bnnxxRcrMBkAbJyiOQAAAAAAAAAANVq/fv3yzjvvFDvG51ZSUpKvf/3r+frXv17sKMC/Wb58eRo3brzZ+xo3brzuUwkAoLIpmgMAAAAAAAAAUKP17du32BGAau7LX/5yXnjhhbzzzjubXDhftGhRXnjhhbRu3bqC0wHAhtUqdgAAAAAAAAAAAACozs4999wsWbIkBx54YIYPH56PP/54o2s//vjjPP300znwwAOzdOnS9OnTpxKTAsD/caI5AAAAAAAAAAA1xurVqzNu3LjMnz8/9evXT4cOHbLTTjsVOxb8RytWrMiyZcuSJF/4whdSv379Iidic1x66aUZPXp0nnzyyZxwwgnZZptt8pWvfCXNmjVLvXr1kiQrV67M3LlzM2XKlHzwwQcpLS3NiSeemEsvvbTI6QGoqRTNAQAAAAAAAACoNp599tnsvPPO2Wuvvdabu+uuu3LDDTdk6dKlZcaPP/74DB48OI0bN66klPCfvf/++7n//vszfPjwTJ48OUuWLCkz37Bhw7Rr1y7HHXdc+vTpk2233bZISdkUtWrVytChQ3P//ffn9ttvzxtvvJHx48dn/PjxG1y/xx57pH///unTp08KhUIlpwWA/6VoXsNNnTo1kyZNyty5c7Ny5cpss802+eIXv5g2bdqkffv2qVu3brEjAgAAAAAAAABssiOPPDLnnntu7r///jLjN910UwYOHJjS0tJ06tQpu+22W5YsWbLuhOGZM2dm/PjxuhJsEZ5++umce+65Wbp0aUpLS5Mk22+//bpTzFesWJHFixdn1KhReemll3LTTTflwQcfzLHHHlvM2PwHhUIh559/fs4///zMnj07kyZNypw5c7J8+fIkSYMGDdK8efO0b98+LVu2LG5YAIiieY20bNmy3HXXXfnFL36RWbNmbXRdnTp1su++++bkk0/28SsAAAAAAAAAQJXxSTH3E2+//XZuvPHGbLPNNnniiSdy2GGHrZtbtGhRevbsmVdeeSX33HOPjgRF98orr+Skk05K7dq1861vfSsnn3xyOnTokHr16pVZt3LlykycODGPP/54Bg8enJNOOimjR4/OfvvtV6TkbI6WLVsqkwOwxatV7ABUrt/97nfZbbfdMmDAgE8tmSfJhx9+mD/96U+5+eabKykdAAAAAAAAAED5e/LJJ/PRRx/luuuuK1MyT5ImTZrkkUceSd26dfPYY48VKSH8n5tuuim1atXKSy+9lJ/85Cf5+te/vl7JPEnq1auXr3/96/npT3+aF198MUly4403VnZcAKAaUzSvQe64444cd9xx+ec//1lmvKSkJK1atcq+++6br371q2ncuHGREgIAAAAAAAAAlL9p06alUCjk5JNP3uB8y5Yt07Fjx/z973+v5GSwvj//+c/p3r37Zp1Mvv/+++ewww7LK6+8UoHJ+DweeeSRzJ49u9gxAGCzKJrXEPfff3/69+9f5qOhevTokT/84Q9ZunRpZs6cmXHjxmXy5MlZtGhR5s2bl4cffjgnnXRS6tSpU8TkAAAAAAAAAACfz9q1a5Mku+yyy0bXtGjRIitWrKisSLBRH374YUpKSjZ7X506dfLhhx9WQKLimzx5cl5++eVix/hczj777LRu3TrdunXLL37xi7z33nvFjgQA/5GieQ0wY8aM9OvXb9311ltvnV//+tf5/e9/nyOPPDJ169Zdb89OO+2Us846K7/97W8zadKkyowLAAAAAAAAAPC5LF++PHPmzFn31ahRoyTJ/PnzN7pn6dKladiwYWVFhI3aY4898uyzz+bNN9/c5D0zZszIc889lz322KMCkxXPpZdemkMOOaTYMT630tLSjB49OhdddFGaNm2aU045JU8//XTWrFlT7GgAsEGK5jXAhRdemFWrVq27/tWvfpUzzjhjk/f7TRQAAAAAAAAAUJUMHTo0u+6667qvH/7wh0mSsWPHbnD92rVrM3HixE898RwqyyWXXJKVK1emc+fOueuuu/KPf/xjo2vnz5+fO++8M126dMkHH3xQ5jDK6qa0tLTYET63nj17ZtCgQencuXNWr16doUOHpmfPnvnSl76Ufv365c9//nOxIwJAGVsVOwAV66mnnsrIkSPXXZ9yyik55ZRTipgIAAAAAAAAAKDidO3aNYVCYYNz06ZN2+D48OHDs2DBgpx44okVGa1ctfzuiHJ/zdm3HF3ur8nm6927d/7nf/4nd955Zy677LJcdtlladKkSZo1a5Z69eolSVauXJm5c+dm0aJFSf63hH3ZZZfl7LPPLmb0zVanTp1NWvfxxx+vt75QKGT16tUVkquibLfddrn44otz8cUXZ/bs2Xn44Yfzq1/9KtOmTcugQYNy9913p1WrVunVq1e+8Y1vpHXr1sWODEANp2hezQ0ePLjM9cCBA4uUBAAAAAAAAACg4o0aNWqz9+y444558MEHs99++5V/IPgMfvKTn+SYY47J7bffnpEjR2bhwoVZuHDheuvq1q2bQw45JP3790/37t2LkPTzWbNmTQqFwiafVr5mzZoKTlR5WrZsmeuvvz7XX399Xn311Tz88MN57LHHMnPmzHz/+9/P97///ey///7p1atXTj311DRs2LDYkQGogRTNq7F58+blmWeeWXe99957Z6+99ipiIgAAAAAAAACALc/++++f/fffv9gxoIxDDz00hx56aFatWpWpU6dmzpw5Wb58eZKkQYMGad68eXbfffeUlJQUOeln17Zt20ydOjUXXXRRbrnllmy33XYbXHfwwQfn5ZdfXneyeXWzzz77ZJ999skdd9yRZ599Ng8//HCefvrpjB07Nq+88kouu+yyfPDBB8WOCUANpGhejf3xj38s8+bq4IMPLmIaAAAAAAAAAABgc5WUlKR9+/Zp3759saOUu0mTJuWHP/xhbrnlljz11FP58Y9/nDPOOKPYsYqmdu3a6dGjR3r06JEVK1Zk2LBhefjhhzNy5MhiRwOghqpV7ABUnFdffbXM9b++2fzLX/6Sb3/722nfvn0aNmyYevXqpWXLljnssMNy2223Zd68eZUdFwAAAAAAAAAAqEG23nrr3HDDDfnLX/6S1q1b56yzzsoRRxyRmTNnFjta0dWvXz+9evXKs88+m7fffrvYcQCooRTNq7F/L5q3atUqy5cvz3nnnZcOHTrkrrvuyuTJk7N06dJ88MEHeeutt/L888/nqquuym677ZZrr702H330UZHSAwAAAAAAAAAA/2r+/Pm5/vrr07Vr17Rt2zadOnXKhRdemAkTJhQ72ueyxx57ZPTo0fn5z3+e8ePH56tf/WpuvPFG3aX/X9OmTYsdAYAaStG8GpsxY0aZ61q1aqVr16554IEH/uPeDz74IDfffHOOOuqoLFu2rKIiAgAAAAAAAAAA/+K2225LmzZtMnHixDLjo0aNyl577ZUf/ehH+dOf/pRp06Zl4sSJ+cUvfpHOnTvn1ltvLVLi8nPxxRfn73//e3r06JGBAwemffv2GTlyZLFjlYsHH3ww5513XrFjAMBm2arYAagYa9euXa8g/u1vfzt/+ctfkiSFQiHHHHNMjjrqqDRr1iwrVqzIX/7ylzz88MP5xz/+sW7P888/n969e2fo0KHlkmvhwoVZtGjRZu3598I8AAAAAAAAAABUV8OGDcuKFSvSoUOHdWNLly7NySefnKVLl2afffbJueeem5YtW2bx4sUZNWpUHnrooVx77bVp165devToUcT0n1/Tpk0zdOjQPPXUU+nXr18OPfTQlJSUFDvW53bOOecUOwIAbDZF82rqvffeS2lpaZmxT55ybNSoUZ544okceOCBZeZPO+20XHfddbnooovy61//et34sGHD8stf/jJnn3325841aNCgfP/73//crwMAAAAAAAAAANXR9OnT07FjxzJjv/nNb7J48eL06tUrDz30UJm5M888M6eeemp69OiRO+64o8oXzT9x/PHHp3v37rnmmmvyu9/9rthxAKBGqlXsAFSM5cuXb3C8du3aGTFixHol8080aNAgDz/8cA4//PAy4z/60Y/WK64DAAAAAAAAAADla9myZWnUqFGZsSlTpqRQKOT666/f4J5DDz00nTt3zquvvloZEStNgwYNctddd2XWrFmZNWtWseMAQI2jaF5NbezjYs4///zst99+n7q3Vq1aufvuu1Or1v/97TF16tS89NJL5ZoRAAAAAAAAAAAoa6eddsr06dPLjNWuXTtJ0qRJk43ua9y4cT788MMKzUblGjBgQPr06ZPzzjuv2FEAqKG2KnYAKkaDBg02OH7BBRds0v5WrVrl0EMPzbPPPrtu7KWXXspBBx30uXJdcsklOeWUUzZrz4wZM3LCCSd8rp8LAAAAAAAAAABVweGHH55f/OIXGTdu3LoDJbt06ZI777wzzzzzTE499dT19ixbtix//vOf07p168qOW+HmzJmT+fPnp379+mnbtm222qrmVN6GDRuWqVOnplAo5P777y92HABqoJrzb90aZptttknt2rXz8ccfrxv7whe+kK997Wub/BrdunUrUzSfMGHC58614447Zscdd/zcrwMAAAAAAAAAANXRNddck0ceeSQnnHBChgwZkiOOOCInnXRSOnfunG9+85upXbt2TjrppHXrp0+fnr59+2bhwoW54ooriph8802bNi3bbbddvvjFL643N3z48HznO9/J1KlT143Vq1cvF1xwQW6++ebUrVu3MqMWRb9+/fLOO+8UOwYANZiieTW24447Zv78+euuv/zlL6dWrVqbvH/33Xcvc71w4cJyywYAAAAAAAAAAKyvRYsWefzxx3PSSSflqKOOSqtWrdKlS5fsvffemTBhQk499dQ0aNAgzZs3z5IlS7JgwYKsXbs2hx12WC6//PJix98se+yxR3r37r3ead0PPvhgLrjggqxduzY77rhjWrdunSVLlmTq1Kn56U9/msmTJ+e5555LoVAoUvLK0bdv32JHAKCGUzSvxvbYY48yRfNtt912s/b/+/olS5aUSy4AAAAAAAAAgIrQ8rsjyv01Z99ydLm/JvwnPXr0yMSJE9O/f/88++yzmTlzZgqFQkpLS5Mky5Yty9/+9rckSaNGjdK/f/9cddVVqV27djFjb7bS0tJ1v6ZPvPPOO/nWt76VWrVq5Z577sl55523rlD+t7/9LaecckpGjhyZIUOG5Nxzzy1GbACoMRTNq7E999wzL7744rrr1atXb9b+VatWlbmuV69eueQCAAAAAAAAAAA+Xdu2bfP73/8+c+fOzahRo/L6669nyZIlWbt2bRo0aJAWLVrka1/7Wrp06VLlCuaf5oknnsjKlStzxRVX5Pzzzy8zt9dee+XRRx9Np06d8sgjj1Srovnq1aszbty4zJ8/P/Xr10+HDh2y0047FTsWADWconk11qFDhzLX//znPzdr/8KFC8tcN2rU6HNnAgAAAAAAAAAANl2zZs1y1llnFTtGpfnb3/6WQqGQPn36bHC+Xbt26dChQyZPnlzJyT6fZ599NjvvvHP22muv9ebuuuuu3HDDDVm6dGmZ8eOPPz6DBw9O48aNKyklAJRVq9gBqDhHH310atX6v1s8a9asLF68eJP3v/baa2Wud99993LLBgAAAAAAAAAA8O9Wr16dJGnVqtVG17Rq1Srvv/9+ZUUqF0ceeWRuv/329cZvuummXHbZZVmyZEk6duyY008/PUcccUTq1auXJ598Mt27d1/31wQAKpuieTW244475oADDigzNmzYsE3au2bNmjzxxBNlxg466KDyigYAAAAAAAAAALCe1q1bJ0kWLVq00TUrV67MdtttV1mRyk1paWmZ67fffjs33nhjttlmmzzzzDMZP358fvWrX+X3v/993nzzzXTp0iVTpkzJPffcU6TEANR0iubV3EUXXVTm+v/9v/+3SU+43XfffVmwYMG662233TZHHHFEuecDAAAAAAAAAAA+nwEDBqRPnz4577zzih1lsz300EOpXbv2uq/vfOc7SZLXXntto3smTZqUnXbaqbIiVpgnn3wyH330Ua677rocdthhZeaaNGmSRx55JHXr1s1jjz1WpIQA1HSK5tXcGWecka9+9avrrqdNm5aLLrooa9eu3eiecePG5eqrry4zdskll1TJpwABAAAAAAAAAKC6GzZsWIYMGZIhQ4YUO8pmad68+Ua/Ro4cucE9I0eOzFtvvZV99tmnktOWv2nTpqVQKOTkk0/e4HzLli3TsWPH/P3vf6/kZADwv7YqdgAqVq1atXLHHXfksMMOW/fRKw899FDmzZuXW265JR07dly39r333sv999+fgQMHZvny5evG27Rpk2uvvbbSswMAAAAAAAAAAP9Zv3798s477xQ7xmabPXv2Zu9ZtWpVBg4cmCOOOKL8A1WyTw4L3WWXXTa6pkWLFhk/fnxlRQKAMhTNa4Du3bvn5ptvzne/+911Y88//3w6deqUpk2bplmzZlmxYkVmzpyZDz/8sMzeRo0a5be//W2+8IUvVHZsAAAAAAAAAABgE/Tt27fYESpNjx490qNHj2LH+EyWL1+eOXPmrLtu1KhRkmT+/Plp2bLlBvcsXbo0DRs2rIx4ALAeRfMa4jvf+U7q1auXK664Ih999NG68QULFmTBggUb3LP77rtn+PDh2W233SorJgAAAAAAAAAAQLU0dOjQDB06dL3xsWPHbrBovnbt2kycOPFTTzwHgIqkaF6DfOtb38phhx2WG264IcOGDStTOP9Xu+66ay677LJcfPHFqVOnTiWnBAAAAAAAAAAANmb16tUZN25c5s+fn/r166dDhw7Zaaedih2L/6Br164pFAobnJs2bdoGx4cPH54FCxbkxBNPrMhoALBRiuY1TNu2bfPoo4/m/fffz9ixYzN9+vS89957adCgQb74xS+mQ4cO2X333YsdEwAAAAAAAAAAaqRnn302O++8c/baa6/15u66667ccMMNWbp0aZnx448/PoMHD07jxo0rKWXxDBgwIPPnz0+hUMj9999f7DibbNSoUZu9Z8cdd8yDDz6Y/fbbr/wDAcAmUDSvobbddtsceeSROfLII4sdBQAAAAAAAAAA+P8deeSROffcc9crUd90000ZOHBgSktL06lTp+y2225ZsmRJRo8enSeffDIzZ87M+PHjU7du3SIlrxzDhg3L1KlTq1zR/LPYf//9s//++xc7BgA1mKI5AAAAAAAAAADAFqS0tLTM9dtvv50b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OenYsWMR07KpasJ9vfjii9O7d+/1iubf/va3M2jQoNSpUycnnXRSdttttyxZsiQjRozIX/7yl3Tv3j2TJk3KdtttV6Tk5a958+YZPnx4sWMAAAAAAABUGEVzAAAAgEo0ePDgXH755Vm1alWSZIcddsh///d/59BDD83FF1+c++67L6WlpevWDxo0KHfccUe+9a1vFSsym6Am39epU6fm7rvvzg477JCXX345e+6557q5Dz/8MKeddlqefvrp3Hnnnbn++uuLmBQAAAAAAIDNUavYAQAAAAA2ZOXKlfnnP/+ZRYsW5aOPPip2nHIxduzYfPOb38yHH36YQw45JEcccUSWLVuW0047LU8++WQGDx6cY489No899lhefPHFfO9730vdunXTv3///M///E+x47MRNf2+Dh8+PKWlpbnpppvKlMyTpE6dOrnvvvvSoEGDPP3000VK+PnMnj07v/3tbzNy5MisWbOmzNwzzzyTAQMG5JJLLsl//dd/Zfr06UVKCQAAAAAAUP6caA4AAABsEVasWJEHHnggTz31VCZNmpTFixeXmf/yl7+cgw8+OOeff346depUpJSfzx133JEkeeKJJ3LMMcckSV544YUcdthhueCCC3Laaaflv//7v9etP+igg9K2bduceeaZGTRoUAYPHlyU3Hy6mn5fZ82alUKhkB49emxwvnHjxunYsWNee+21Sk72+V1//fW5+eab151G36ZNmzzzzDP50pe+lJNOOikjRoxYN1coFDJgwIDcdNNN+c53vlPM2AAAAAAAAOXCieYAAABA0T3//PNp1apVLrvssrz44ot59913U1paWuZr+vTpGTx4cPbbb7+cf/75+fDDD4sde7ONHTs27dq1W1dGTpLu3bunU6dOWbx4ca6++ur19px++ulp2bJlXn755cqMymao6fe1du3aSZKmTZtudM1OO+2U1atXV1akcvHkk0/mhz/8Ybbeeusce+yxOfbYYzN79uz06tUr//Vf/5Xf/e53ad++fX7wgx/kpz/9ac4888yUlpbm2muvzXPPPVfs+AAAAAAAAJ+bE80BAACAopo0aVKOOeaYrFmzJmeccUYOPvjgNGrUKLNmzcqQIUPyxhtv5Kc//WkOO+ywjBkzJj//+c/zwAMPZP78+RkxYkSx42+Wd955JwceeOB6461bt85rr72W3XfffYP79txzz4waNaqC0/FZ1bT7umDBgjIF+UKhkCSZO3duWrduvcE9ixYtSqNGjSolX3m5++67U6tWrTz33HP5+te/niR5+eWXc/DBB2fy5Mnp2bNnHn/88dSq9X9neZx88snp2bNn7rrrrhx22GHFig4AAAAAAFAuFM0BAACAorrpppuyZs2aDBs2LMcdd1yZucsvvzynnXZaLr/88kyZMiVnn312zj777FxwwQV54IEH8tBDD+Wcc84pUvLN16BBg6xatWq98ZKSkiRJvXr1Nrhv++23z9q1ays0G59dTbuvzzzzTJ555pn1xl988cUNFs0//PDDTJgwIW3btq2MeOXmtddey/7777+uZJ4kXbt2TZcuXTJ27Nj84Ac/KFMyT5Ljjz8+nTp1yrhx4yo7LgAAAAAAQLlTNAcAAACK6uWXX86+++67Xsn8Ez/4wQ/y+OOP59FHH82AAQOSJHfddVeeeOKJPPDAA1WqaP7FL34xc+fOXW+8W7du2Wqrjf8xzYIFC9KkSZOKjMbnUJPu66f9/21DZfskeeyxx7JkyZJ07ty5omJViPfffz+77LLLeuPNmjVLkrRq1WqD+3bddddMmjSpQrMBAAAAAABUBkVzAAAAoKjee++9NG3adKPzX/rSl5Ikb7/99rqxkpKSHHDAARk9enSF5ytP7du3z7Bhw7JixYrUr19/3Xjv3r3Tu3fvDe756KOP8tprr6VTp06VlJLNVZPu64MPPrjZe/bZZ5+MHDkybdq0qYBEFWf77bcv88+dT3zyUMGbb76Zvfbaa735WbNmpUGDBhWeDwAAAAAAoKLV+s9LAAAAACrOLrvsknHjxuWDDz7Y4PyLL76YJOud/LzNNttk9erVFZ6vPB155JFp165dXn/99U3e8+STT+a9997LQQcdVHHB+Fzc10+3++67p1u3buseGqkq9tlnn7zyyiv505/+tG7s5ZdfztixY9OoUaN8//vfX2/PiBEjMmHChLRr164yowIAAAAAAFQIJ5oDAAAARXXCCSfkxz/+cU499dTcfffdadas2bq5Z599NhdffHEKhUKOPPLIMvvmzJnzqSehb4nOOeecnHPOOZu156tf/WpGjhy5wZOT2TK4r9XTZZddlj/84Q859NBDc8ghhyT53wdf6tatm8ceeyyHHnpo9t1335xwwgnZbrvtMmHChPzqV79KoVDY7L8fACBJPv7444wdOzb/+Mc/0rRp03Tp0iVbb731RtePHTs2M2bMyNlnn12JKQEAAACoSRTNAQAAgKK69tprM2zYsIwYMSKtW7fOrrvumoYNG+att97KP//5z5SWluaUU07JAQccsG7PokWLMmHChJxyyilFTF452rZtm7Zt2xY7BuWsqt7XRx55JF//+tfTsmXLYkepcIcddlhuv/32XHPNNfnjH/+YJNl+++3zwAMP5KCDDsqtt96aq666Kq+99lqSpLS0NEly6qmnpnfv3sWKDUAVNXbs2HzjG9/InDlz1o01adIkN954Yy644IIN7rnvvvvyy1/+UtEcoJx44AcAAGB9iuYAAABAUTVs2DBjxozJBRdckBEjRmTatGnr5urWrZtLLrkkN998c5k9q1atyn333ZeOHTtWdlyo0c4+++wUCoV8/etfT69evXLKKadku+22K3asCnPZZZflrLPOyrhx41K3bt3su+++2XbbbZMkV1xxRTp27JhHHnkkc+fOTdOmTXPCCSfkhBNOKG5oAKqc2bNnp0ePHlm2bFm22267tGnTJm+99VYWLlyYiy++OM8880x+9atfpW7dusWOClBteeAHAABgwxTNAQAAgKJr2rRphg8fnrlz52bixIlZsWJFmjRpUqbU+a922WWXnHPOOUVI+vnUpNOga5Kadl9LS0szevTo/OlPf8q3vvWtHHPMMenVq1eOOuqobLVV9fvjxsaNG+foo4/e4NxBBx2Ugw46qHIDAVDt3HrrrVm2bFnOPffc/PznP09JSUlKS0vz61//OpdffnmeeOKJHHHEEXn66ac3+N4YgM/HAz8AAAAbV6vYAQAAAAA+0axZsxx33HE544wzcuihh1a7Is3ZZ5+d1q1bp1u3bvnFL36R9957r9iRKAc17b727NkzgwYNSufOnbN69eoMHTo0PXv2zJe+9KX069cvf/7zn4sdEQCqlOeeey7NmjXLPffck5KSkiRJoVDIN77xjbz22mvp0KFDXn755RxyyCF55513ipwWoPr51wd+5s+fn3HjxmX+/Pl5+OGH06hRo3UP/Lz//vvFjgoAAFDpFM0BAAAAKtEnp0FfdNFFadq0aU455ZQ8/fTTWbNmTbGj8TnUpPu63Xbb5eKLL86YMWPy5ptv5vvf/3522223vPvuuxk0aFAOOOCA7LbbbvnBD36QmTNnFjsuAGzx5s6dm3333Tdbb731enO77LJLXnrppRx55JGZOHFiunbtmnnz5hUhJVDTnH/++fnlL3+Z5cuXFztKhfPADwAAwMYpmgMAAABbrPnz5+f6669P165d07Zt23Tq1CkXXnhhJkyYUOxon5nToKunmnpfW7Zsmeuvvz5vvPFGxo0bl379+qVJkyaZOXNmvv/976dNmzb5+te/nnvvvTdLliwpdtwKN2DAgPTp0yfnnXdesaMAUIXUqVMnH3/88Ubn69Wrl6effjqnn3563njjjRx44IEe5gIq3AMPPJBzzz03TZs2zVlnnZU//vGPWbt2bbFjVQgP/AAAAGycojkAAABQVLfddlvatGmTiRMnlhkfNWpU9tprr/zoRz/Kn/70p0ybNi0TJ07ML37xi3Tu3Dm33nprkRJ/Pk6Drp7c12SfffbJnXfemXnz5mXEiBE57bTTss0222Ts2LG55JJLstNOOxU7YoUbNmxYhgwZkiFDhhQ7CgBVSJs2bTJ+/PhPXbPVVlvlV7/6Vb75zW9m9uzZ6dq1a6ZNm1ZJCYGaqm7dulm5cmV+/etf5+ijj87OO++c/v37r/f796rOAz8AAAAbp2gOAAAAFNWwYcOyYsWKdOjQYd3Y0qVLc/LJJ2fp0qXp1KlTBg0alN///vd55JFHcv7556d27dq59tpr84c//KGIyT8/p0FXTzX9vtauXTs9evTIr3/96/zzn//MQw89lO7du2fNmjXFjlbh+vXrl4EDB+Z73/tesaMAUIUccsghWbBgQV566aVPXVcoFPLzn/881157bebPn19tPzEF2HKcfvrpef3113PNNdekRYsW+ec//5mf/vSn2WeffbLXXnvl1ltvzdtvv13smJ+bB34AAAA2TtEcAAAAKKrp06fnq1/9apmx3/zmN1m8eHF69eqVcePG5eKLL86RRx6ZM888M4MHD86IESNSq1at3HHHHUVKXf6cBl091fT7Wr9+/fTq1SvPPvtstSig/Cd9+/bNwIEDM3DgwGJHAaAKOe6441JaWpqbb755k9bfdNNN+fGPf1zBqQD+V9u2bfPDH/4wb775Zl5++eWcf/752X777fP3v/891157bXbdddcccsghefDBB7Ns2bJix/1MPPADAACwcYrmAAAAQFEtW7YsjRo1KjM2ZcqUFAqFXH/99Rvcc+ihh6Zz58559dVXKyNiparJp0FXZ+5r0rRp02JHAIAt0gEHHJDp06dn0KBBm7zn8ssvz8SJE/Piiy9WYDKAsj75ZKb58+dn6NChOf7447P11ltn1KhROf/889O0adOcccYZGTFiRLGjbhYP/AAAAGzcVsUOAAAAANRsO+20U6ZPn15mrHbt2kmSJk2abHRf48aN8+GHH1ZotmL75DToXr16ZcGCBcWOQzmpyvf1wQcfzJe//OVix9iiLFy4MKtWrUrz5s2LHQWAKqpQKKR169abva99+/YVkAbgP6tTp0569uyZnj175r333stvfvObPPLIIxkzZkx+85vf5PHHH69SD9V+8sBPoVDY5D2XX355DjnkkCxdurTiggEAAGwBnGgOAAAAFNXhhx+eiRMnZty4cevGunTpktLS0jzzzDMb3LNs2bL8+c9//kyFnKrKadDVU1W7r+ecc04OOOCAYsfYopx22mlp1apVsWMAAEBRbLfddrnwwgvz8ssvZ9asWbnpppvStm3bYsfaLJ888LO57+vbt2+fbt26VVAqAACALYOiOQAAAFBU11xzTUpKSnLCCSesK5afdNJJ6dy5c775zW9m6NChZdZPnz49J510UhYuXJizzz67GJE/swcffDDnnXdesWNQztxXSktLix0BgGpq/vz5uf7669O1a9e0bds2nTp1yoUXXpgJEyYUOxrAepo3b55rr702U6ZMKXYUAAAAyslWxQ4AAAAA1GwtWrTI448/npNOOilHHXVUWrVqlS5dumTvvffOhAkTcuqpp6ZBgwZp3rx5lixZkgULFmTt2rU57LDDcvnllxc7/mY555xzih2BCuC+Vk9t2rTZpHXz5s1bb32hUMjUqVMrJBcA1c9tt92WwYMH59FHH02HDh3WjY8aNSonnnhi3nvvvTIPNU2cODEPPPBAfvjDH+Y73/lOMSID1Bjz58/PoEGD8tJLL2XhwoVp0KBBOnTokAsvvDCdOnUqdjwAAIAKp2gOAAAAFF2PHj0yceLE9O/fP88++2xmzpyZQqGwrlCzbNmy/O1vf0uSNGrUKP37989VV12V2rVrFzM2sAkGDBiQ+fPnp1Ao5P777y92nE02Y8aMMv8c2pT1nygUChUVC4BqaNiwYVmxYkWZkvnSpUtz8sknZ+nSpdlnn31y7rnnpmXLllm8eHFGjRqVhx56KNdee23atWuXHj16FDE9UF3NmjUrDRo0KHaMSuGBHwAAgI1TNAcAAKgB5s2blxdeeCHz589P/fr106FDh3Tp0qXYsaCMtm3b5ve//33mzp2bUaNG5fXXX8+SJUuydu3aNGjQIC1atMjXvva1dOnSRcEcqpBhw4Zl6tSpVa5o3rhx4yxevDgXXnhhrrzyymy11Yb/KPX000/P+PHj8+abb1ZyQgCqi+nTp6djx45lxn7zm99k8eLF6dWrVx566KEyc2eeeWZOPfXU9OjRI3fccYeiOVAhWrRoUewIlcYDPwAAABunaA4AAFANDB48OLvvvnu6detWZnzt2rW56qqr8rOf/Sxr1qwpM7f33nvnscceS+vWrSszKvxHzZo1y1lnnVXsGFuMqnoaNJ+uJt3Xfv365Z133il2jM32xhtvpH///rn33nszZsyY3HPPPRt8SKukpCRJzSriAFC+li1blkaNGpUZmzJlSgqFQq6//voN7jn00EPTuXPnvPrqq5UREaBa88APAADAximaAwAAVAMXX3xxevfuvV7R/Nvf/nYGDRqUOnXq5KSTTspuu+2WJUuWZMSIEfnLX/6S7t27Z9KkSdluu+2KlBz4T6rqadB8upp0X/v27VvsCJ/JDjvskCFDhqRXr1656KKL0rVr1/Tp0ye33nprGjZsWOx4AFQjO+20U6ZPn15m7JNP8GnSpMlG9zVu3DgffvhhhWYD+DRz5sxZ9+l5bdu23einAG3pPPADAACwcbWKHQAAAICKMXXq1Nx9993ZYYcdMnHixDz22GP54Q9/mEGDBmX69Ok5/vjj8/bbb+fOO+8sdlTgU/Tr1y8DBw7M9773vWJHoRy5r1VH9+7dM2XKlFx55ZUZMmRI2rZtm4cffrjYsQCoRg4//PBMnDgx48aNWzfWpUuXlJaW5plnntngnmXLluXPf/6zT6gCKsy0adPyz3/+c4Nzw4cPz5577pldd901Xbp0Sfv27dOwYcP0798/q1evruSkn58HfgAAADZO0RwAAKCaGj58eEpLS3PTTTdlzz33LDNXp06d3HfffWnQoEGefvrpIiWEz27AgAHp06dPzjvvvGJHqXB9+/bNwIEDM3DgwGJHoRxV9/u6cOHCzJkzp9gxyk1JSUluueWWTJgwIS1atEjv3r3TvXv3TJs2rdjRAKgGrrnmmpSUlOSEE05YVyw/6aST0rlz53zzm9/M0KFDy6yfPn16TjrppCxcuDBnn312MSIDNcAee+yRa6+9dr3xBx98MD179swbb7yRJk2apHPnztl9992zcuXK/PSnP83RRx+d0tLSIiT+7DzwAwAAsHGK5gAAANXUrFmzUigU0qNHjw3ON27cOB07dlSSo0oaNmxYhgwZkiFDhhQ7CrABp512Wlq1alXsGOWuXbt2GTduXG6//fa8+uqrad++fSZPnlzsWABUcS1atMjjjz+e9957L0cddVR222239OnTJ3vvvXeWLVuWU089Ndttt12++tWvplmzZtljjz3y/PPP59BDD83ll19e7Pifydq1a/PEE0+kT58+6dSpU5o0aZKSkpKUlJSkSZMm6dSpU/r06ZMnn3wya9euLXZcqJFKS0vXK4y/8847+da3vpVatWpl8ODBmT9/fsaMGZPXX389kydPzu67756RI0dWud+re+AHAABg47YqdgAAAAAqxicf8du0adONrtlpp50yduzYyooE5aZfv3555513ih2jwixcuDCrVq1K8+bNix2FclTT7mtVO8VwUxUKhVx66aXp2bNn+vbtmxEjRqRQKBQ7FgBVXI8ePTJx4sT0798/zz77bGbOnJlCobDu36fLli3L3/72tyRJo0aN0r9//1x11VXrft9XlUyYMCHf+MY3MmPGjA2+X3j33Xfz7rvvZuLEiXnooYey22675ZFHHkmnTp2KkBb4V0888URWrlyZK664Iueff36Zub322iuPPvpoOnXqlEceeSTnnntukVJuvk8e+DnppJNy1FFHpVWrVunSpUv23nvvTJgwIaeeemoaNGiQ5s2bZ8mSJVmwYEHWrl2bww47rMo+8AMAALCpFM0BAACqiQULFuTll19ed/1J6W3u3Lkb/RjfRYsWpVGjRpWSD8pT3759ix2hQp122mkZPXp01qxZU+wolKPqcF/btGmzSevmzZu33vpCoZCpU6dWSK5iaN68eYYPH17sGABUI23bts3vf//7zJ07N6NGjcrrr7+eJUuWZO3atWnQoEFatGiRr33ta+nSpUuVLJgnyRtvvJGDDjooK1euzHHHHZeTTz45HTp0SLNmzVK/fv0kyYoVKzJ37txMnDgxjz/+eIYPH56DDz44r776atq2bVvkXwHUbH/7299SKBTSp0+fDc63a9cuHTp0qJKf+lOTHvgBAADYHIrmAAAA1cQzzzyz7uN9/9WLL764waL5hx9+mAkTJvgP9bCFqq6nQdd0Vf2+zpgxo0zZYlPWf8Kp3wCwaZo1a5azzjqr2DEqxMCBA7Nq1aoMHTo0PXv23OCabbfdNnvuuWf23HPPnHXWWRk2bFhOOeWU3HDDDXn00UcrOTHwr1avXp0kadWq1UbXtGrVKn/5y18qK1K5qgkP/AAAAGwuRXMAAIBq4Jxzztno3KpVqzY4/thjj2XJkiXp3LlzRcWCcrVw4cKsWrUqzZs3L3aUz8xp0NVTTbqvjRs3zuLFi3PhhRfmyiuvzFZbbfiPF08//fSMHz8+b775ZiUnBAC2ZCNHjkzXrl03WjLfkBNPPDHdunXLiy++WIHJgE3xyUEGixYtSrNmzTa4ZuXKldluu+0qM1a5q84P/AAAAGwuRXMAAIBq4MEHH9zsPfvss09Gjhy5yQVJKLbTTjsto0ePzpo1a4od5TNzGnT1VJPu6xtvvJH+/fvn3nvvzZgxY3LPPfekS5cu660rKSlJkrRo0aKyIwIAW7Dly5encePGm72vcePGWbFiRQUkAj7NQw89lIceemi98ddee22jRfNJkyZlp512quhoAAAAVBJFcwAAgBpq9913z+67717sGLBZNrXIu6VyGnT1VJPu6w477JAhQ4akV69eueiii9K1a9f06dMnt956axo2bFjseABQYwwYMCDz589PoVDI/fffX+w4m+zLX/5yXnjhhbzzzjubXDhftGhRXnjhhXUnKQOVo3nz5ht9MHbkyJE5/vjjNzj+1ltv5bzzzqvoeAAAAFQSRXMAAACgqDb1VP158+att75QKGTq1KkVkqsiOA26eqqJ97V79+6ZMmVKbrjhhtx+++156qmnctttt6VXr17FjgYANcKwYcMyderUKlc0P/fcc3PFFVfkwAMPzH/913/lqKOOSu3atTe49uOPP86IESNy9dVXZ+nSpbn++usrOS3UbLNnz97sPatWrcrAgQNzxBFHlH+gLUxVfeAHAABgcymaAwAA1CAHH3xwRo8enTVr1hQ7CqwzY8aMFAqFTT6tfMaMGeu+39jpalsqp0FXTzX1vpaUlOSWW27JmWeemfPPPz+9e/fOkCFDcvfddxc7GgBUe/369cs777xT7Bib7dJLL83o0aPz5JNP5oQTTsg222yTr3zlK2nWrFnq1auXJFm5cmXmzp2bKVOm5IMPPkhpaWlOPPHEXHrppUVOD/wnPXr0SI8ePYodo1JU1Qd+AAAANpeiOQBAJXnggQcyd+7cfO973yt2FKCG29QyL1SWxo0bZ/Hixbnwwgtz5ZVXZqutNvzHFaeffnrGjx+fN998s5ITlj+nQVdPNfW+tmvXLuPGjcudd96Z66+/Pu3bt19XFAMAKkbfvn2LHeEzqVWrVoYOHZr7778/t99+e954442MHz8+48eP3+D6PfbYI/3790+fPn2q3EOmQPVWVR/4AQAA2FyK5gAAleS+++7L+PHjFc2BCnH44Ydv0rpJkyatt75QKOSZZ56pkFywKd544430798/9957b8aMGZN77rknXbp0WW9dSUlJkqRFixaVHbFCOA26eqqp97VQKOTSSy9Nz54907dv34wYMUIZDADYoEKhkPPPPz/nn39+Zs+enUmTJmXOnDlZvnx5kqRBgwZp3rx52rdvn5YtWxY3LMBGVNUHfgAAADaXojkAAEA18Pzzz6dQKGzyaeXPP//8uu8VASm2HXbYIUOGDEmvXr1y0UUXpWvXrunTp09uvfXWNGzYsNjxKpzToKunmnpfmzdvnuHDhxc7BgBUSwsXLsyqVavSvHnzYkcpNy1btlQmh2pkwIABmT9/fgqFQu6///5ixwEAAKAcKJoDAGymOXPmfKZ9q1evLuckAP+nbt26+eijj3LhhRfm9NNP3+i6yy67LJMnT86LL75Yielg03Tv3j1TpkzJDTfckNtvvz1PPfVUbrvttvTq1avY0Sqc06CrJ/cVAChPp512WkaPHp01a9YUOwrABg0bNixTp06ttkXz6vjADwAAwH+iaA4AsJlatmz5mQpCpaWlikVAhZk8eXIuvPDCDB48OLNnz86gQYOy6667rrdu++23T5J069atkhPCpikpKcktt9ySM888M+eff3569+6dIUOG5O677y52tErhNOjqyX0FAMrLpn6KVVV38MEHK9VDFdSvX7+88847xY5RYTzwAwAA1ESK5gAAn1GbNm02a/1bb73lVHOgwuy2224ZOXJk7r///lx99dX5yle+kgEDBuTqq6/OVlv5rV91Nnny5CxdujRdu3YtdpRy1a5du4wbNy533nlnrr/++rRv3z716tUrdiygBmn53RHl/pqzbzm63F8TgKpvU/+MaZSXJQABAABJREFUad68eeutLxQKmTp1aoXkKraaUqqH6qRv377FjlDh/LMJAACoabQNAAA2U6tWrTJr1qw8++yz2WWXXTZ53/7775/x48dXYDKA5Lzzzsuxxx6bb3/727nuuuvyq1/9Kvfcc08OPPDAYkejglx66aXV9jStQqGQSy+9ND179kzfvn0zYsQInw4CAEC1M2PGjBQKhU0uL86YMWPd91Xt/fHhhx++SesmTZq03vpCoZBnnnmmQnIBNZsHfgAAADZO0RwAYDPtu+++mTVrVl577bXNKpoDVJYdd9wxjz76aM4+++xccsklOeigg3LOOefk//2//1fsaFSQ6n6aVvPmzTN8+PBixwAAgArRuHHjLF68OBdeeGGuvPLKjX4q1emnn57x48fnzTffrOSE5ef555/frFL9888/v+77qlaqh5pi4cKFWbVqVZo3b17sKJ9ZTXrgBwAAYHMpmgMAbKZ99903jz76aMaPH58TTjhhk/dV9xIgsOU56qij8vrrr2fAgAG56667Mnz48NSpU6fYscrV22+/nX/84x9p2rRpWrRo8alrp02blgULFqRr166VlO7z2dR79fHHH6+3vlAoZPXq1RWSCwAAKlt1ft+fJG+88Ub69++fe++9N2PGjMk999yTLl26rLeupKQkSf7jX4MtWd26dfPRRx/lwgsvzOmnn77RdZdddlkmT56cF198sRLTAZ/FaaedVuU/aa0mPfADAACwuRTNAQA201FHHZW33noru+2222btu/vuu/P+++9XUCqADatXr17uuOOOfOMb38gFF1yQSZMmVYuTlqZPn55zzz03r7zyyrqxdu3a5dZbb93oR7HffPPN+eUvf7mumL2lW7NmzWadplWV/4MuAABsSE14358kO+ywQ4YMGZJevXrloosuSteuXdOnT5/ceuutadiwYbHjlavJkyfnwgsvzODBgzN79uwMGjQou+6663rrtt9++yRJt27dKjkh8FlU9UNWatIDPwAAAJurVrEDAABUNW3atMkdd9yRc889d7P2fe1rX/Mfx4Ci6dSpUyZMmJBZs2ZV+VOX3nnnnXTr1i1jx45NaWlpGjdunNq1a2fSpEnp0aNHrrzyymJHLBdt27ZNklx00UVZsmRJ1q5du8Gvbt26pVAorDcOAABVWU153/+vunfvnilTpuTKK6/MkCFD0rZt2zz88MPFjlWudtttt4wcOTKDBw/O+PHj85WvfCU/+tGPPDgLW6A2bdps0tf48ePXW7/77rsXOf3m+eSBn+eeey4rV65M165dc+GFF2bJkiXFjgYAAFB0iuYAAAA1RO3atdOiRYsqf+rSrbfemgULFuTII4/MvHnz8s9//jOLFi3KjTfemLp16+aOO+7IGWecUeWLCpMmTcr111+fBx98MHvssUf++7//u9iRAACg0tSU9/3/rqSkJLfccksmTJiQFi1apHfv3unevXumTZtW7Gjl6rzzzsvf//73HHvssbnuuuvSvn37jB49utixgH8xY8aMzJw5MzNmzPjUrw8++CClpaXrjVdFNeGBHwAAgM2laA4AAECVMmLEiDRp0iS/+c1v8qUvfSlJst1222XAgAEZM2ZMmjdvnsceeyzHHXdcPvjggyKn/ey23nrr3HDDDfnLX/6S1q1b56yzzsoRRxyRmTNnFjsaAABUuJryvn9j2rVrl3HjxuX222/Pq6++mvbt22fy5MnFjlWudtxxxzz66KP53e9+lxUrVuSggw5Knz598u677xY7GpCkcePGKRQKueiiizJ9+vTMmjVrg1/77bdfCoVCmbGq/Gl6NeWBHwAAgE21VbEDAABUZcuWLUudOnVSt27dMuPz5s3Lc889l0WLFqV169Y58sgjU69evSKlBNiwAQMGZP78+SkUCrn//vuLHWeTzZ49O4cffni+8IUvrDf3ta99LePGjUuPHj3yxz/+MUcccURGjBixwbVVxR577JHRo0fnnnvuyTXXXJOvfvWrueaaa/Ld7343W2+9dbHjATVMy++OKPfXnH3L0eX+mgBUfTXtff+GFAqFXHrppenZs2f69u2bESNGpFAoFDtWuTvqqKPy+uuvZ8CAAbnrrrsyfPjw1KlTp9ixoMZ744030r9//9x7770ZM2ZM7rnnnnTp0mW9dSUlJUlS5T9B79998sDPnXfemeuvvz7t27f3Z/wAAECN5ERzAIDPYOLEidl3332z/fbbp379+jn88MPz1ltvJUkefvjh7L777jnvvPPy3e9+N6ecckratGmTsWPHFjk1QFnDhg3LkCFDMmTIkGJH2SyFQuFTC9Y77rhjXnrppXTr1i1/+tOfcvDBB1eLE/Euvvji/P3vf0+PHj0ycODAtG/fPiNHjix2LAAAqBA19X3/hjRv3jzDhw/P2rVr8/HHHxc7ToWoV69e7rjjjvz5z39Os2bNMn/+/GJHghpvhx12yJAhQ/Lcc89l5cqV6dq1ay688MIsWbKk2NEqzScP/EyZMiWHHnpojfq1AwAAfMKJ5gAAm2nOnDk55JBD8v7776ekpCS1a9fO888/n2OOOSaPPvpozj///DRt2jTHHntsGjdunFGjRuXll1/Osccem9dffz1f/OIXi/1LAEiS9OvXL++8806xY2y2Vq1aZeLEiZ+6pkGDBvnjH/+YU089NcOHD0/Xrl3TrFmzSkpYcZo2bZqhQ4fmqaeeSr9+/XLooYeuOzkMKB6nfANA+avJ7/trsk6dOmXChAmZO3dusaMA/7/u3btnypQpueGGG3L77bfnqaeeym233ZZevXoVO1ql+eSBHwAAgJpI0RwAYDPdeuutef/993PNNdfkBz/4QQqFQm655ZZcd911Oeuss9KuXbu88MIL2XbbbdftGTBgQG6++eb87Gc/y4033ljE9AD/p2/fvsWO8Jl069Ytd999d1577bV07Nhxo+vq1q2bYcOGpXfv3vnVr36VN954oxJTVqzjjz8+3bt3zzXXXJPf/e53xY7DZlBIBgDYNN7311y1a9dOixYtih0D+BclJSW55ZZbcuaZZ+b8889P7969M2TIkNx9993FjgYAAEAFq1XsAAAAVc1zzz2XFi1a5Kabbkrt2rVTq1atXHvttWndunUmT56cH/3oR2VK5kly3XXXZYcddsgf/vCHIqUGqD6OP/74lJaW5rbbbvuPa2vXrp2HH3443/rWt1JaWloJ6SpPgwYNctddd2XWrFmZNWtWseMAAEC58r4fYMvTrl27jBs3LrfffnteffXVtG/fPpMnTy52LAAAACqQE80BADbT22+/nSOPPDKFQqHMeLt27fLmm29u8JStbbbZJnvvvXcmTJhQWTEBNmjhwoVZtWpVmjdvXuwon9nBBx+c5557LrVqbfqz0z/96U/TvXv3LFmypAKTAQAA5cX7fj4xYMCAzJ8/P4VCIffff3+x40CNVygUcumll6Znz57p27dvRowYsd6flQMAAFB9KJoDAGymrbfeOnXq1Flv/JNTzHfYYYcN7mvatGk++OCDCs0G8J+cdtppGT16dNasWVPsKJ/ZVlttle7du2/2vuOOO64C0lAeWn53RLm/5uxbji731wQAoPJ4388nhg0blqlTpyqawxamefPmGT58eLFjAAAAUME2/RgIAACSJE2aNMk//vGP9cZ33HHHtGrVaqP73nvvvY2W0AEqk4+SrzpWrVqV6667Lq1bt84222yTXXfdNZdffnkWLFiw0T3nnntuttrKc+UAAED10K9fvwwcODDf+973ih0FAAAAoMbxX54BADbTHnvskdGjR2ft2rVlPr751ltvza233rrRff/zP/+TFi1aVEZEoAZq06bNJq2bN2/eeusLhUKmTp1aIbn47NasWZMjjjgif/rTn9Y9HPDWW2/lzjvvzMMPP5wHHnhgo6c1epgAAACoLvr27VvsCAAAAAA1lhPNAQA2U6dOnbJs2bKMGzduk/e88sormTdvXg488MAKTAbUZDNmzMjMmTMzY8aMT/364IMPUlpaut54VVMTTvoeNGhQRo8enV122SW//vWv87e//S3Dhw/PIYccksWLF+fEE0/MoEGDih0TAAAqTE143w8AAAAAWzJFcwCAzXT99ddn2bJl2XfffTd5z5IlSzJw4MCcc845FZgMqMkaN26cQqGQiy66KNOnT8+sWbM2+LXffvulUCiUGXvzzTeLHX+zfHLS980335xZs2Zl9erV6076/spXvpKnn356o3ur0knfv/71r1NSUpIXXnghp59+evbYY48cffTRee655zJo0KBstdVW+da3vpWbbrqp2FEBAKDc1ZT3/WzYwoULM2fOnGLHAAAAAKjxFM0BADZT7dq1U79+/dSuXXuT9xx11FEZOHBgvvKVr1RgMqAme+ONN3LWWWfl3nvvTc+ePTNv3ry0aNFiva+SkpIkWW+8KqkpJ32//vrrOeCAA9K6dev15i6++OI899xz2W677TJw4MBcccUVRUgIAAAVp6a872fDTjvttLRq1arYMQAAAABqPJ8dCAAAUA3ssMMOGTJkSHr16pWLLrooXbt2TZ8+fXLrrbemYcOGxY5Xrv71pO9PStifnPZ9zz335LLLLsu3vvWtLF68ONddd12R0352q1evTpMmTTY6f+CBB+bll1/O4Ycfnp/85Cd5//33M3jw4EpMCAAAFaemvO9PkpbfHVGurzf7lqPL9fWKxcn0AAAAAMWnaA4AAFCNdO/ePVOmTMkNN9yQ22+/PU899VRuu+229OrVq9jRys1/Oul7r732yvHHH5+BAwdmyZIl+fGPf1yElJ/fzjvvnGnTpn3qmq985SsZM2ZMDjvssDzwwANZvnz5Zn3iBgAAbKlqyvv+mqZNmzabtG7evHnrrS8UCpk6dWqF5AJqrvJ+2CepPg/8AAAAJIrmAACVYsCAAZk/f34KhULuv//+YscBqrmSkpLccsstOfPMM3P++eend+/eGTJkSO6+++5iRysXNeWk7/322y+PP/545s6dm2bNmm103a677prRo0fniCOOyGOPPaZoDgBAtVBT3vfXNDNmzEihUNjk08pnzJix7vtCoVBRsQAAAADYiFrFDgAAUBMMGzYsQ4YMyZAhQ4odBahB2rVrl3HjxuX222/Pq6++mvbt22fy5MnFjvW5bc5J37vuumseeOCBnHnmmfnoo48qKWH5OPbYY7N27dr8/Oc//49rv/SlL+Xll1/OfvvtlzVr1lRCOgAAqFg15X1/TdO4ceMUCoVcdNFFmT59embNmrXBr/322y+FQqHM2Jtvvlns+AAAAMD/x979x3s93//jv70q/Z7ol4hKkfxYSJqi8mMNIb+2sZGfzVhZmx97jxBmG+/5Mb8yGfJrM1uF3n4mUYRUm8SKRlmqKSqpSHW+f3ze+jrviqJzXp1zrtfL5VwuncfzcX91OxcuvF6vc3s+XlQ5TjQHACgH/fr1y/z584sdA6iCCoVC+vfvn6OPPjp9+/bNI488UuFPgasqJ30fdthhGTBgQOrVq7de+7fYYouMGjUqF154YRYuXFi24QAAoIxVlef9Vc3UqVNzzjnn5NZbb83zzz+fP/zhD+nSpcsa+2rXrp0kadmyZXlHBAAAAOBznGgOAFAO+vbtm4EDB2bgwIHFjgJUUS1atMiIESOyatWqrFy5sthxvpaqctJ3gwYN8qtf/Sq//OUv13umTp06ue6663LnnXeWYTIAACh7VeV5f1XTsGHDDBkyJCNHjszSpUvTrVu3nHHGGVmwYEGxowEAAACwFk40BwAAoEJx0jcAAFR+nvdXbgcddFCmTJmSSy+9NNdee20eeuihXH311endu3exowFJWv3ykY3+mDOuPGyjPyYAAABlT9EcAKCMvPfee/n444/TokWLYkcBqFQ+O+l7Q3x20jcAAFAxeN5f+dWuXTtXXnllfvjDH6ZPnz455ZRTMmTIkNxyyy3FjgYAAADA/1I0BwAoI8cdd1zGjh3rI5sBKDcDBgzInDlzUigUcvvttxc7DgAAwJdq3759Xnrppdxwww25+OKLs/vuu6du3brFjgUAAABAkmrFDgAAUJmVlJQUOwIAVciwYcMyZMiQDBkypNhRAAAA1luhUEj//v0zZcqUfPvb386CBQuKHQkAAACAONEcAGCDtW3bdr32vfvuu2vsLxQKmTZtWpnkAmDdqspJ3/369cv8+fOLHQMAAIqiqjzvr8xatGiRESNGFDsGAAAAAP9L0RwAYANNnz49hUJhvU8rnz59+uo/FwqFsooFwBcYNmxYpk2bVukLJ3379i12BAAAKJqq8rwfAAAAAMqLojkAwAZq3LhxPvjgg5xxxhk577zzUqPG2p9SHX/88Rk/fnzeeuutck4IwP/lpG8AAKj8PO8HAAAAgI1L0RwAYANNnTo155xzTm699dY8//zz+cMf/pAuXbqssa927dpJkpYtW5Z3RAD+j8p80vd7772Xjz/+OC1atCh2FAAAKKrK/LwfAAAAAIqhWrEDAABUNA0bNsyQIUMycuTILF26NN26dcsZZ5yRBQsWFDsaAFXQcccdl9atWxc7BgAAAAAAAACVjKI5AMBXdNBBB2XKlCk577zzMmTIkLRr1y733HNPsWMB8L/ee++9vPPOO8WOUS5KSkqKHQEAAIqiKj3vBwAAAIDyVqPYAQAAKrLatWvnyiuvzA9/+MP06dMnp5xySoYMGZJbbrml2NGAKqTVLx/Z6I8548rDNvpjlrfjjjsuY8eOzYoVK4od5Stp27bteu17991319hfKBQybdq0MskFAACbkor+vB8AAAAANmWK5gAAG0H79u3z0ksv5YYbbsjFF1+c3XffPXXr1i12LIAqryKf9D19+vQUCoX1/hmmT5+++s+FQqGsYgEAwCanIj/vBwAAAIBNmaI5AMBGUigU0r9//xx99NHp27dvHnnkEUU/gDJQVU76bty4cT744IOcccYZOe+881Kjxtpfwh9//PEZP3583nrrrXJOCAAAZaeqPO8HAAAAgE2ZojkAwEbWokWLjBgxotgxACqtqnLS99SpU3POOefk1ltvzfPPP58//OEP6dKlyxr7ateunSRp2bJleUcEAIAyU1We9wMAAADApqxasQMAAADAhmjcuHEKhUJ+/OMf580338zbb7+91q9vfetbKRQKpdYq0qnfDRs2zJAhQzJy5MgsXbo03bp1yxlnnJEFCxYUOxoAAJS5qvK8HwAAAAA2ZU40BwAAoEKpaid9H3TQQZkyZUou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EgAAAKqWCRMm5IQTTsj06dNTUlKyxvX3338/77//fiZNmpS77rorO+64Y+6999507NixCGkBKgcnmgMAAAAAAHzOVVddlblz5+aQQw7Ju+++m//85z+ZN29efvWrX6VWrVq57rrr8oMf/CArVqwodlQAAACoEqZOnZr9998/b775Zo444ojcfffdmTJlShYuXJhPP/00n376aRYuXJgpU6bk7rvvzuGHH5433ngjBxxwQKZOnVrs+AAVlqI5AAAAAADA5zzyyCNp0qRJ/vKXv2TrrbdOkjRo0CADBgzI888/nxYtWuSBBx5Ir169smzZsiKnBQAAgMpv4MCB+fjjjzN06NA8+OCDOfHEE7PLLrtk8803T/Xq1VO9evVsvvnm2WWXXXLiiSfmoYceyt/+9rcsXbo0l156abHjA1RYiuYAAAAAAACfM2PGjHTu3Dnf+MY31ri255575qWXXsoee+yRxx9/PAcffHAWL15chJQAAABQdYwePTrdunXL0Ucfvd4zxxxzTLp3756nn366DJMBVG6K5gAAAAAAAJ9TKBSy2WabrfN606ZN8+yzz6Z79+557rnncsABB+T9998vx4QAAABQtXz00Udp3LjxBs81btw4S5YsKYNEAFWDojlJkv333z8lJSWrv2bMmFHsSAAAAAAAUBStW7fOpEmTvnBP/fr18/jjj+eII47IpEmT0q1bt8yePbucEgIAAEDVssMOO2TUqFGZP3/+es/Mmzcvo0aNSps2bcowGUDlpmgOAAAAAADwOd27d8+MGTMyceLEL9xXq1atDBs2LCeccEL++c9/5qmnniqnhAAAAFC1nHrqqVmwYEG6du2aESNGZOXKlevcu3Llyjz88MPp2rVrFi5cmNNOO60ckwJULjWKHQAAAAAAAGBTcuSRR2bQoEG5+uqr8+c///kL91avXj333HNPGjZsmBtvvDGFQqGcUgIAAEDV0b9//4wdOzYPPvhgjjrqqNSpUye77bZbtt1229StWzdJsnTp0syaNStTpkzJsmXLUlJSkmOOOSb9+/cvcnqAikvRHAAAAAAA4HMOOOCAjBw5MtWqrf8Hw15//fU56KCDsmDBgjJMBgAAAFVTtWrVMnTo0Nx+++259tprM3Xq1IwfPz7jx49f6/6dd94555xzTk477TQ3hQN8DYrmAAAAAAAAn1OjRo0cdNBBGzzXq1evMkgDAAAAJEmhUEifPn3Sp0+fzJgxI6+88kreeeedfPTRR0mS+vXrp0WLFtl9993TqlWr4oYFqCQUzQEAAAAAAAAAAIAKo1WrVsrkAOVA0RwAAAAAAGAdFi9enJo1a6ZWrVql1t99992MHDky8+bNS5s2bXLIIYekbt26RUoJAAAAALDxKZoDAAAAAAD8H5MmTcqZZ56ZiRMnplAo5MADD8xtt92Wli1b5p577slZZ52VZcuWrd6/9dZb54EHHkiXLl2KmBoAAAAqPzeFA5QfRXMAAAAAAIDPeeedd3LggQfmww8/TO3atVO9evU89dRTOfzww3P//fenT58+adasWY444og0btw4zzzzTMaMGZMjjjgir7/+erbaaqti/wgAAABQ6bgpHKD8VSt2AAAAAAAAgE3JVVddlQ8//DAXXHBBFi9enEWLFuWKK67Ia6+9lhNPPDHt27fPq6++mptuuimXXnppnnnmmVxwwQVZsGBBbrrppmLHBwAAgErns5vCJ0yYkFq1aqVOnTqrbwp/7bXX0qdPnzRq1ChnnXVWLr744nTt2jWzZ8/OEUcckf/85z/Fjg9QYSmaAwAAAAAAfM7IkSPTsmXLXHHFFalevXqqVauWCy+8MG3atMnkyZPzm9/8JptvvnmpmYsuuigNGzbMY489VqTUAAAAUHm5KRygOBTNAQAAAAAAPuff//539thjjxQKhVLr7du3T5Lstddea8zUqVMne+yxR6ZPn14uGQEAAKAqcVM4QHEomgMAAAAAAHzOZpttlpo1a66x/tkvrBs2bLjWuWbNmmXZsmVlmg0AAACqIjeFAxSHojkAAAAAAMDnNGnSJLNnz15jvWnTpmnduvU65xYtWrTOEjoAAADw1bkpHKA4FM0BAAAAAAA+Z+edd87kyZOzatWqUutXXXVV3nzzzXXO/eMf/0jLli3LOh4AAABUOW4KBygORXMAAAAAAIDP6dixYxYvXpyXXnppvWdeeOGFvPvuu+natWsZJgMAAICqyU3hAMWhaA4AAAAAAPA5F198cRYvXpxOnTqt98yCBQsycODAnHzyyWWYDAAAAKomN4UDFEeNYgcAAAAAAADYlFSvXj316tXboJmePXumZ8+eZZQIAAAAqraLL744559/fmrXrr3eM5/dFH7ssceWYTKAyk3RHAAAAAAAAAAAANhkuSkcoDiqFTsAAAAAAAAAAAAAAACbFieaAwAAAAAAfE0DBgzInDlzUigUcvvttxc7DgAAAADA16ZoDgAAAAAA8DUNGzYs06ZNUzQHAACATYSbwgG+PkVzAAAAAACAr6lfv36ZP39+sWMAAAAA/8tN4QBfn6I5AAAAAADA19S3b99iRwAAAAA+x03hAF+fojkAAAAAAAAAAABQqbgpHODrUzQHAAAAAABYi1WrVuX1119PzZo1s+OOO6ZQKKy+NnHixIwYMSLz5s1LmzZtctxxx6V58+ZFTAsAAAAAsHEpmgMAAAAAAPwfjz76aPr06ZP//Oc/SZK2bdvmz3/+c/bYY4/89re/zcUXX5ySkpKUlJSkUCjkkksuyV133ZVjjz22yMkBAACg8nJTOED5UjQHAAAAAAD4nClTpuToo4/Op59+mjZt2mSzzTbLtGnT0qtXr/zpT3/KgAEDstdee+W4445L48aN88wzz+Tee+/NSSedlD333DOtW7cu9o8AAAAAlY6bwgHKX7ViBwAAAAAAANiU/O53v8unn36aQYMG5c0338zrr7+eIUOGZNasWTnppJPSo0ePvPDCCznvvPNyyimnZMiQIbnuuuuybNmy3HjjjcWODwAAAJXOZzeFz507N61bt85OO+2UN954I7169cpzzz2XAQMGZM8998xVV12VO+64I717987HH3+ck046KW+99Vax4wNUWIrmAAAAAAAAn/Pss89mp512yplnnrl6rXfv3tl1110zc+bMXHLJJalRo/SHxp511lnZeuutM2rUqPKOCwAAAJWem8IBikPRHAAAAAAA4HPmzp2bXXfddY31nXfeOUnyzW9+c41rNWrUyDe/+c3MmDGjrOMBAABAleOmcIDiUDQHAAAAAAD4nNq1a691vV69ekmSzTfffK3XGzdunOXLl5dZLgAAAKiq3BQOUByK5gAAAAAAAJ/TtGnTvPvuu2us77rrrjnwwAPXOff++++ncePGZRkNAAAAqiQ3hQMUh6I5AAAAAADA53zzm9/M5MmT1/hF9HnnnZeRI0eudaakpCQTJ05M69atyyMiAAAAVCluCgcoDkVzAAAAAACAz9l3331Tt27dTJw4cb1nnnzyycyfPz/du3cvw2QAAABQNbkpHKA4FM0BAAAAAAA+55xzzsm8efPSuXPn9Z75xje+kTvvvDOnn356GSYDAACAqslN4QDFUaPYAQAAAAAAACq6Ll26pEuXLsWOAQAAAJXSOeeck3POOWeDZj67KVzRHOCrUzQHAAAAAAAAAAAAKhU3hQN8fdWKHQAAAAAAAAAAAAAAgE2LojkAAAAAAAAAAAAAAKUomgMAAAAAAAAAAAAAUIqiOQAAAAAAAAAAAAAApSiaAwAAAAAAAAAAAABQiqI5AAAAAAAAAAAAAAClKJoDAAAAAAAAAAAAAFCKojkAAAAAAAAAAAAAAKUomgMAAAAAAAAAAAAAUIqiOQAAAAAAAAAAAAAApdQodgAAAAAAAIBNxqUNyuAxF238xwQAAAAAKGOK5gAAAAAAAAAAAMCmaWPfFO6GcID1Vq3YAQAAAAAAAAAAAAAA2LQomgMAAAAAAAAAAAAAUIqiOQAAAAAAAAAAAAAApSiaAwAAAAAAAAAAAABQiqI5AAAAAAAAAAAAAAClKJoDAAAAAAAAAAAAAFCKojkAAAAAAAAAAAAAAKUomgMAAAAAAAAAAAAAUIqiOQAAAAAAAAAAAAAApSiaAwAAAAAAAAAAAABQiqI5AAAAAAAAAAAAAAClKJoDAAAAAAAAAAAAAFCKojkAAAAAAAAAAAAAAKUomgMAAAAAAAAAAAAAUIqiOQAAAAAAAAAAAAAApSiaAwAAAAAAAAAAAABQiqI5AAAAAAAAAAAAAAClKJoDAAAAAAAAAAAAAFCKojkAAAAAAAAAAAAAAKUomgMAAAAAAAAAAAAAUIqiOQAAAAAAAAAAAAAApSiaAwAAAAAAAAAAAABQiqI5AAAAAAAAAAAAAAClKJoDAAAAAAAAAAAAAFCKojkAAAAAAAAAAAAAAKUomgMAAAAAAAAAAAAAUIqiOQAAAAAAAAAAAAAApSiaAwAAAAAAAAAAAABQiqI5AAAAAAAAAAAAAAClKJoDAAAAAAAAAAAAAFCKojkAAAAAAAAAAAAAAKUomgMAAAAAAAAAAAAAUIqiOQAAAAAAAAAAAAAApSiaAwAAAAAAAAAAAABQiqI5AAAAAAAAAAAAAAClKJoDAAAAAAAAAAAAAFCKojkAAAAAAAAAAAAAAKUomgMAAAAAAAAAAAAAUIqiOQAAAAAAAAAAAAAApSiaAwAAAAAAAAAAAABQiqI5AAAAAAAAAAAAAAClKJoDAAAAAAAAAAAAAFCKojkAAAAAAAAAAAAAAKUomgMAAAAAAAAAAAAAUIqiOQAAAAAAAAAAAAAApSiaAwAAAAAAAAAAAABQiqI5AAAAAAAAAAAAAAClKJoDAAAAAAAAAAAAAFCKojkAAAAAAAAAAAAAAKUomgMAAAAAAAAAAAAAUIqiOQAAAAAAAAAAAAAApSiaAwAAAAAAAAAAAABQiqI5AAAAAAAAAAAAAAClKJoDAAAAAAAAAAAAAFCKojkAAAAAAAAAAAAAAKUomgMAAAAAAAAAAAAAUIqiOQAAAAAAAAAAAAAApSiaAwAAAAAAAAAAAABQiqI5AAAAAAAAAAAAAAClKJoDAAAAAAAAAAAAAFCKojkAAAAAAAAAm4w+ffrk7rvvzkcffVTsKAAAAFClKZoDAAAAAAAAsMm44447cuqpp6ZZs2Y58cQT8/jjj2fVqlXFjgUAAABVjqI5AAAAAAAAAJuUWrVqZenSpfnTn/6Uww47LM2bN88555yTSZMmFTsaAAAAVBmK5gAAAAAAwNf27rvv5u67785VV12Vm266KePGjSt2JAAqsOOPPz6vv/56LrjggrRs2TL/+c9/cv3112fvvffOrrvumquuuir//ve/ix0TAAAAKjVFcwAAAAAA4EsNHjw4zz777Brrq1atyrnnnpvWrVvn1FNPzYUXXpj+/funa9eu2WuvvfKvf/2rCGkBqAzatWuXX//613nrrbcyZsyY9OnTJ1tssUX++c9/5sILL8z222+fAw88MHfeeWcWL15c7LgAAABQ6SiaAwAAAAAAX+rMM8/MXXfdtcb6T3/601x33XUpFAo59thj88tf/jI//vGPs+222+bvf/97DjrooCxatKgIiQGoTPbbb7/ceuutmTNnToYOHZojjzwym222WZ555pn06dMnzZo1yw9+8IM88sgjxY4KAAAAlUaNYgcAAAAAAAAqpmnTpuWWW25Jw4YNM2bMmOyyyy6rry1fvjzHHXdcHn744dxwww25+OKLi5gUgMqiZs2aOfroo3P00Udn0aJF+ctf/pJ77703zz//fP7yl7/kr3/9a1asWFHsmAAAAFApONEcAAAAAAD4SkaMGJGSkpJcccUVpUrmyf8rAt52222pX79+Hn744SIlBKAya9CgQc4444yMGTMmb7/9dq644oq0a9eu2LEAAACg0lA0BwAAAAAAvpK33347hUIhhx566FqvN27cOHvttVfeeOONck4GQFXTokWLXHjhhZkyZUqxowAAAECloWgOAAAAAAB8JdWrV0+SNGvWbJ17ttlmm3zyySflFQkAAAAAgI2kRrEDAAAAAAAAFcPcuXMzZsyY1d8XCoUkyaxZs9KmTZu1zsybNy+NGjUql3wAVA5vv/126tevX+wYAAAAUOUpmgMAAAAAAOvliSeeyBNPPLHG+tNPP73Wovny5cszYcKEtGvXrjziAVBJtGzZstgRAAAAgCiaAwAAAAAA6+Hkk09e57WPP/54resPPPBAFixYkH322aesYgEAAAAAUEYUzQEAAAAAgC915513bvDM3nvvndGjR6dt27ZlkAiAqmD+/Pl59NFHM3ny5MycOTOLFy9OknzjG99Iy5Yt0759+/Ts2TONGzcuclIAAACofBTNAQAAAACAMrHTTjtlp512KnYMACqghQsX5pxzzsm9996blStXpqSkZK37CoVCqlevnt69e+eaa67JFltsUb5BAQAAoBJTNAcAAAAAAABgk7Fo0aJ07tw506ZNS5MmTXLEEUekQ4cO2XbbbVOvXr0kyZIlSzJr1qxMmjQpI0aMyJ133plx48blpZdeyuabb17knwAAAAAqB0VzAAAAAABgg8yfPz+PPvpoJk+enJkzZ2bx4sVJkm984xtp2bJl2rdvn549e6Zx48ZFTgpARXTppZdm2rRpOfvss/O73/0uNWvW/ML9y5cvz/nnn58bb7wxl156aa699tpySgpQua1cuTLjxo3L7Nmz06xZs3Tp0iWbbbbZOvePGzcu06dPz0knnVSOKQEAKEuK5gAAAAAAwHpZuHBhzjnnnNx7771ZuXJlSkpK1rqvUCikevXq6d27d6655ppsscUW5RsUgApt+PDh2W233XL99dev1/6aNWvm+uuvz+jRozNs2DBFc4CNYNy4cTnhhBPyzjvvrF5r0qRJfvWrX+VHP/rRWmduu+223H333YrmAACViKI5AAAAAADwpRYtWpTOnTtn2rRpadKkSY444oh06NAh2267berVq5ckWbJkSWbNmpVJkyZlxIgRufPOOzNu3Li89NJL2XzzzYv8EwBQUcydOzedO3fe4Lldd901Dz744MYPBFDFzJgxI4ceemgWL16cBg0apG3btpk5c2bee++9nHnmmXniiSdy3333pVatWsWOCgBAGVM0BwAAAAAAvtSll16aadOm5eyzz87vfve71KxZ8wv3L1++POeff35uvPHGXHrppU6XBWC9NWvWLBMmTMiqVatSrVq19ZpZuXJlJkyYkK222qqM0wFUfldddVUWL16cU089NTfffHNq166dkpKS/OlPf8rPf/7zDB8+PAcffHAefvhhN5QCAFRy6/eqHAAAAAAAqNKGDx+e3XbbLddff/2XlsyTpGbNmrn++uuz2267ZdiwYeWQEIDK4sgjj8y//vWvHH/88Zk3b96X7p8/f35+8IMf5K233spRRx1V9gEBKrmRI0dm2223zR/+8IfUrl07SVIoFHLCCSdk4sSJ6dChQ8aMGZMDDzww8+fPL3JaAADKkhPNAQAAAACALzV37tx07tx5g+d23XXXPPjggxs/EACV1mWXXZZHH300f/vb3zJixIh07do1HTp0yLbbbpu6desmSZYuXZpZs2Zl0qRJGTt2bD755JPssMMOufTSS4sbHqASmDVrVg4//PBsttlma1zbbrvt8uyzz+a73/1uHn/88XTr1i0jR45M8+bNi5AUAICypmgOAAAAAAB8qWbNmmXChAlZtWpVqlVbvw9MXblyZSZMmJCtttqqjNMBUJlsscUWefHFF9O/f//cf//9eeqppzJq1Ki17i0pKUm1atVywgkn5Pe//3222GKL8g0LUAnVrFkzK1euXOf1unXr5uGHH85JJ52U+++/P127ds3IkSPLMSEAAOVF0RwAAAAAAPhSRx55ZG688cYcf/zxufnmm9OkSZMv3D9//vz85Cc/yVtvvZWzzz67nFICUFk0atQo9957b66++uo8/vjjeeWVV/LOO+/ko48+SpLUr18/LVq0yO67755DDjkkzZo1K3JigMqjbdu2GT9+/BfuqVGjRu67775sueWWueWWW9KtW7e0atWqfAICAFBuFM0BAAAAAIAvddlll+XRRx/N3/72t4wYMSJdu3ZNhw4dsu2226Zu3bpJkqVLl2bWrFmZNGlSxo4dm08++SQ77LBDLr300uKGB6DCatasWU455ZRixwCoUg488MBcc801efbZZ9O9e/d17isUCrn55puz5ZZb5je/+U3mzp1bjikBACgPiuYAAAAAAMCX2mKLLfLiiy+mf//+uf/++/PUU09l1KhRa91bUlKSatWq5YQTTsjvf//7bLHFFuUbFgAA+Mp69eqVq6++Or/97W+/sGj+mSuuuCKNGjXKeeedVw7pAAAoT4rmAAAAAADAemnUqFHuvffeXH311Xn88cfzyiuv5J133slHH32UJKlfv35atGiR3XffPYccckiaNWtW5MQAAMCG2nffffPmm2+mUCis98zPf/7zHHjggVm4cGHZBQMAoNwpmgMAAAAAABukWbNmOeWUU4odAwBWGzBgQObMmZNCoZDbb7+92HEAKrRCoZA2bdps8Nzuu+9eBmkAACgmRXMAAAAAAAAAKrRhw4Zl2rRpiuYAAACwESmaAwAAAAAAAFCh9evXL/Pnzy92DIBKZ8GCBXnkkUfyyiuvZObMmVm8eHGqVauWLbfcMrvuumv233//dO7cudgxAQAoI4rmAAAAAABAmRgwYEDmzJnjdFkAylzfvn2LHQGgUvnoo49y/vnn54477siKFSvWuF5SUpJCoZAk2W233XLjjTemW7du5R0TAIAypmgOAAAAAACUiWHDhmXatGmK5gAAUIEsXbo0Xbt2zeTJk1O/fv20b98+jRo1yttvv51XX301m222Wc4999xUr149zz//fMaMGZMDDzwwgwcPzmmnnVbs+AAAbESK5gAAAAAAQJno169f5s+fX+wYAFRgK1asyPvvv5+GDRtms802+8K9H3zwQT766KO0aNGinNIBVE6/+c1v8sorr+QHP/hBbrrppmy55Zarr02YMCHf/e53M3To0PzjH/9InTp1Mnny5Bx77LE566yz0rFjx7Rv376I6QEA2JiqFTsAAAAAAABQOfXt2zcDBw7MwIEDix0FgApm/vz5OfHEE7P55ptnm222yTe+8Y0cffTRefXVV9c5c+6556Z169blmBKgcvrrX/+ali1b5q677ipVMk+Sjh07ZvDgwXnzzTfzl7/8JUnSvn37PPzww1m1alWuvvrqYkQGAKCMKJoDAAAAAAAAsMlYsmRJunXrlj//+c/5+OOPU1JSkuXLl+ehhx7K3nvvnZtuummdsyUlJeWYFKByeuedd7LXXnulRo0aa73epUuXJMnEiRNXr+28887p3LlzRo8eXS4ZAQAoH4rmAAAAAADABlmxYkX+85//5NNPP/3SvR988EHeeeedckgFQGVx7bXXZurUqdljjz0ybty4LFmyJK+++mpOP/30fPrpp+nfv39+8YtfFDsmQKVVv379zJw5c53XP7tWvXr1Uuvbbbdd5s2bV6bZAAAoX4rmAAAAAADAepk/f35OPPHEbL755tlmm23yjW98I0cffXReffXVdc6ce+65ad26dTmmBKCiGzp0aDbffPM8+uij2WeffVKnTp3suuuuue222zJixIg0aNAg11xzTX70ox85wRygDHTp0iWTJk3KXXfdtca1FStW5LzzzkuhUEiHDh1KXZs3b1622GKLckoJAEB5UDQHAAAAAAC+1JIlS9KtW7f8+c9/zscff5ySkpIsX748Dz30UPbee+/cdNNN65xVAgRgQ0yfPj1dunTJVltttca1nj17Zty4cdluu+1yxx135LjjjsuKFSuKkBKg8rrgggtSrVq1nHbaaTn00ENz5ZVX5tZbb82FF16YHXfcMU8++WS23XbbfP/73189s3LlyrzyyivZZZddipgcAICNTdEcAAAAAAD4Utdee22mTp2aPfbYI+PGjcuSJUvy6quv5vTTT8+nn36a/v375xe/+EWxYwJQCaxcuTKbb775Oq+3a9cuzz//fNq1a5ehQ4fmyCOPzMcff1yOCQEqt3322SdDhgxJrVq18sQTT2TAgAH5yU9+kquuuiozZ85M8+bNM2LEiNSuXXv1zJQpU7LLLrvkxBNPLGJyAAA2thrFDgAAAAAAAGz6hg4dms033zyPPvro6hNmd91119x22205+uijc+KJJ+aaa67JggULMnjw4BQKhSInBqCiatmyZaZMmfKFe5o3b57nnnsuhxxySB5//PEccsghadSoUTklBKj8TjjhhOy///4ZMmRIJk6cmCVLlqRJkybp1q1bTjjhhNSrV6/U/t133z2jR48uUloAAMqKojkAAAAAAPClpk+fnm7duq0umX9ez549M27cuBxyyCG54447smjRovzpT39KjRp+DQHAhtt3330zZMiQvPHGG2nbtu0692255ZZ5+umn06tXr4wePdpNTgAbWfPmzTNgwIBixwAAoIiqFTsAAAAAAACw6Vu5cmU233zzdV5v165dnn/++bRr1y5Dhw7NkUcemY8//rgcEwJQWfTq1SslJSW57rrrvnRvvXr18thjj+Woo45KSUlJOaQDAACAqsNRIgAAAAAAwJdq2bJlpkyZ8oV7mjdvnueeey6HHHJIHn/88RxyyCFp1KhROSUEoLL4zne+k9tuuy2bbbbZeu2vWbNm/va3v+Wmm27KggULyjgdAAAAVB2K5gAAAAAAwJfad999M2TIkLzxxhtp27btOvdtueWWefrpp9OrV6+MHj06hUKhHFMCUBnUqVMnp59++gbNVKtWLT/96U/LKBEAX2bAgAGZM2dOCoVCbr/99mLHAQBgI6lW7AAAAAAAAFAZvPbaa7npppsyePDgvP3226vXV6xYkeuuuy77779/dt111/Tq1SsPPvhg8YJ+Rb169UpJSUmuu+66L91br169PPbYYznqqKNSUlJSDukAAIBiGjZsWIYMGZIhQ4YUOwoAABuRE80BAAAAAOBruuiii3LllVeuLlVvttlm+eMf/5gTTjghxx57bEaMGLF67z//+c888sgjOeecc/K73/2uWJE32He+853cdttt2WyzzdZrf82aNfO3v/0tN910UxYsWFDG6QAAgGLq169f5s+fX+wYAABsZIrmAAAAAADwNTzyyCP5zW9+k/r16+e4447LZpttlr/85S8544wz8sknn2TEiBE5++yz07t37zRu3DjPPPNM/uu//ivXXnttevXqla5duxb7R1gvderUyemnn75BM9WqVctPf/rTMkoEAABsKvr27VvsCAAAlAFF8yqipKQkM2bMyKuvvppZs2Zl4cKFqVWrVrbccsvsuOOO2XvvvVO7du1ixwQAAAAAqHAGDRqUQqGQUaNGZe+9906SnHXWWdlzzz3Tv3//9O3bN9dff/3q/aecckqaN2+egw8+OLfeemuFKZoDAAAAAFC1KJpXYgsWLMiDDz6Yxx9/PE8//fQXfkTRZpttlsMOOyw/+9nP0r1793JMCQAAAABQsU2YMCHf+ta3VpfMk+Sb3/xmunTpkueffz5nnXXWGjM9evRIu3bt8sILL5RnVAAAgDLz2GOPZd68eTnppJOKHQUAgI2kWrEDUDb69u2bZs2a5bTTTssDDzzwhSXzJPn000/z4IMPZv/998/JJ5+cDz/8sJySAgAAAABUbAsWLEirVq3WWG/RokWSZIcddljrXNu2bTNnzpyyjAYAAFBuLr/88px66qnFjgEAwEbkRPNK6qWXXsry5cvXWK9evXq23nrrbLXVVvn0008zc+bMLFq0qNSeu+++O1OnTs2oUaNSv3798ooMAAAAAFAhNWjQIIsXL15jfbPNNkuS1KxZc61z9erVS7VqzoMBAAAAAGDT5B3sKmCLLbbIT37ykzzyyCNZsGBB/v3vf2fChAl55ZVX8v7772f06NHp2rVrqZnx48fnlFNOKU5gAAAAAIAKZOutt84777yzxvqxxx6byy+/fJ1zs2bNStOmTcsyGgAAAAAAfGWK5pVYq1at8sc//jGzZ8/OzTffnJ49e+Yb3/hGqT3Vq1fP/vvvn9GjR+eMM84odW3o0KEZPXp0eUYGAAAAAKhw9txzz7z22mtZsGBBqfXDDz88AwYMWOvMsmXLMnHixOy6667lEREAAGC9Va9e/St9vfTSS8WODgDARlaj2AEoG5dddll69Oixzo9k/b+qV6+eQYMGZdKkSZkwYcLq9T/+8Y854IADyiomAAAAAECF993vfjdLly7NO++8ky233HK9Zu67774sXbo0+++/f9mGAwAA2EAlJSVJklq1am3Q3PLly8siDgAARaRoXkkddthhGzxTvXr1/OIXv8j3v//91WtPPPHExowFAAAAAFDpHHHEETniiCM2aOaoo45Kjx490rRp0zJKBQAA8NU0b948s2fPzsyZMzfoNUvnzp0zfvz4MkwGAEB5UzSnlK5du5b6/v3338/SpUtTt27dIiUCAAAAAKh8GjdunMaNGxc7BgBsei5tUAaPuWjjPyZAJdapU6c8+OCDmTBhQnr27FnsOAAAFFG1Ygdg07K2j3VdtMgbLwAAAAAAAAAASbJq1aoMHz48p512Wjp27JgmTZqkdu3aqV27dpo0aZKOHTvmtNNOy4MPPphVq1YVO+4G69SpU0pKSjb4dPKSkpIySgQAQLE40ZxS3n333TXWGjVqVIQkAAAAAAAV35w5czJo0KA8++yzee+991K/fv106NAhZ5xxRjp27FjseOvP6bIAAJAkmTBhQk444YRMnz59rcXq999/P++//34mTZqUu+66KzvuuGPuvffeCvX8v0ePHnnxxRdTr169DZq75JJLMm/evDJKBQBAMSiaU8rYsWNLfd+yZcvUrFmzSGkAAAAAADZ9V199dQYPHpz7778/HTp0WL3+zDPP5JhjjsmiRYtKFVAmTZqUO+64I7/+9a/zX//1X8WIDAAAfAVTp07N/vvvn6VLl6ZXr1757ne/mw4dOmTbbbddXcpesmRJZs2alUmTJuWvf/1rRowYkQMOOCAvv/xy2rVrV+SfYP106NAhw4cP3+C5nj17lkEaAACKSdGcUu64445S33sRAAAAAADwxYYNG5YlS5aUKpkvXLgw3/3ud7Nw4cLsvffeOfXUU9OqVat88MEHeeaZZ3LXXXflwgsvTPv27XPooYcWMT0AALC+Bg4cmI8//jhDhw7N0UcfvdY9m2++eXbZZZfssssuOfHEEzNs2LB873vfy6WXXpr777+/nBMDAMDXo2jOao8++mjGjBlTau2UU07ZqH/He++9t8EfkzR9+vSNmgEAAAAAYGN68803s9dee5Va+8tf/pIPPvggvXv3zl133VXq2g9/+MN8//vfz6GHHprrrrtO0RwAACqI0aNHp1u3bussma/NMccck+7du+fpp58uw2Tw9b377rsZNWpU5syZk3r16qVDhw7p0qVLsWMBAEWmaE6S5IMPPsiPf/zjUmtHHXVUOnXqtFH/nkGDBuWyyy7bqI8JAAAAAFBMixcvTqNGjUqtTZkyJYVCIRdffPFaZ7797W9nn332ycsvv1weEQEAgI3go48+SuPGjTd4rnHjxlmyZEkZJIL1N3jw4Oy0007p3r17qfVVq1bl/PPPz0033ZQVK1aUurbHHnvkgQceSJs2bcozKgCwCalW7AAU36pVq3LiiSdm1qxZq9caNGiQG264oYipAAAAAAAqhm222SZvvvlmqbXq1asnSZo0abLOucaNG2f58uVlmg0AANh4dthhh4waNSrz589f75l58+Zl1KhRiroU3ZlnnrnGJ24lyU9/+tNcd911KRQKOfbYY/PLX/4yP/7xj7Ptttvm73//ew466KAsWrSoCIkBgE2Bojk5//zz89hjj5Vau/XWW7PddtsVKREAAAAAQMXxne98J5MmTcpLL720eq1Lly4pKSnJE088sdaZxYsX58UXX1Q2AQCACuTUU0/NggUL0rVr14wYMSIrV65c596VK1fm4YcfTteuXbNw4cKcdtpp5ZgU1s+0adNyyy23pGHDhpk0aVIeeOCB/PrXv86gQYPy5ptv5sgjj8y///1vh1UCQBVWo9gBKK4bbrgh1157bam1X/ziFznuuOPK5O/7yU9+ku9973sbNDN9+vQcddRRZZIHAAAAAODruuCCC3LvvffmqKOOypAhQ3LwwQfn2GOPzT777JOzzjor1atXz7HHHrt6/5tvvpm+ffvmvffey7nnnlvE5ABUFXfccUdmzZqVSy65pNhRACq0/v37Z+zYsXnwwQdz1FFHpU6dOtltt92y7bbbpm7dukmSpUuXZtasWZkyZUqWLVuWkpKSHHPMMenfv3+R08OaRowYkZKSklxxxRXZZZddSl2rWbNmbrvttjz99NN5+OGHc/HFFxcpJQBQTIrmVdif/vSn/OxnPyu1dsopp+TKK68ss7+zadOmadq0aZk9PgAAAABAeWvZsmX++te/5thjj03Pnj3TunXrdOnSJXvssUcmTJiQ73//+6lfv35atGiRBQsWZO7cuVm1alV69OiRn//858WOD0AVcNttt2X8+PGK5gBfU7Vq1TJ06NDcfvvtufbaazN16tSMHz8+48ePX+v+nXfeOeecc05OO+20FAqFck4LX+7tt99OoVDIoYceutbrjRs3zl577ZWJEyeWczIAYFOhaF5F/c///E9OPvnklJSUrF475phj8sc//tGLGwAAAACADXTooYdm0qRJOeecc/Lkk0/mX//6VwqFwur3YBcvXpzXXnstSdKoUaOcc845Of/881O9evVixgYAADZQoVBInz590qdPn8yYMSOvvPJK3nnnnXz00UdJsvom09133z2tWrUqblj4Ep+9Jm3WrNk692yzzTYZN25ceUXiKyopKcn//M//5KGHHsorr7ySmTNnZvHixalWrVq23HLL7LrrrjnggANy0kknZZtttil2XAAqEEXzKmj06NH53ve+lxUrVqxe69GjR/785z/7pQYAAAAAwFfUrl27PProo5k1a1aeeeaZvP7661mwYEFWrVqV+vXrp2XLltlzzz3TpUsX78UC8JW88847X2nuk08+2chJAEiSVq1aKZNTocydOzdjxoxZ/f1nh1HOmjUrbdq0WevMvHnz0qhRo3LJx1fz6quv5oc//GFef/31UoeOfmbZsmWZPXt2Ro4cmcsuuywDBgzIRRddVISkAFREiuZVzEsvvZRevXrl448/Xr3WpUuXDB8+PDVr1ixiMgAAAACAymHbbbfNiSeeWOwYAFRCrVq1+kqfTlxSUuJTjQGAPPHEE3niiSfWWH/66afXWjRfvnx5JkyYkHbt2pVHPL6CGTNmpGvXrvnwww/TpUuXHHDAAWnUqFHefvvtPPDAA/nggw/y3//939ltt93y/PPP5/bbb8/AgQMzY8aM/PGPfyx2fAAqAEXzKmTy5Mk59NBDV39cU5LsueeeefTRR1OvXr0iJgMAAAAAAADWV9u2bTdo/8yZM51qDlBO3nnnncyZMyf16tVLu3btUqNGBavmXNpgIz/eoo37eHxlJ5988jqvff7Ays974IEHsmDBguyzzz5lFYuv6bLLLsuHH36YG2+8MX379i117corr0zPnj0zcODA/POf/8xBBx2U888/P9///vdz5513plevXunVq1eRkgNQUVSwZ7N8VdOmTUuPHj2yYMGC1Ws777xznnjiiTRosJFfJAAAAAAAAAAbXevWrfP222/nySefzHbbbbfec507d8748ePLMBlA1fDGG2+kQYMG2Wqrrda4NmLEiPzXf/1Xpk2btnqtbt26+dGPfpTf/va3qVWrVnlGhTXceeedGzyz9957Z/To0Rt8kxvl58knn8wee+yxRsk8SerUqZPf//732XPPPfOnP/0p5557burUqZO77rorrVq1yh/+8AdFcwC+VLViB6DszZw5M9/+9rfz3nvvrV7bfvvtM3LkyDRp0qSIyQAAAAAAqqYBAwbktNNOy+mnn17sKABUIJ06dUqSTJw4schJAKqmnXfeORdeeOEa63feeWeOPvroTJ06NU2aNMk+++yTnXbaKUuXLs3111+fww47LCUlJUVIDF/PTjvtlO7du2frrbcudhTW4f3330+bNm3Wef2za9OnT1+91rBhw3Tt2jUvv/xymecDoOJTNK/k5syZk4MOOiizZs1avda8efOMGjUqzZs3L2IyAAAAAICqa9iwYRkyZEiGDBlS7CgAVCCdOnVKSUnJBp9OrtwIsHGUlJSs8d/U+fPn5+yzz061atUyePDgzJkzJ88//3xef/31TJ48OTvttFNGjx7tuT9QJrbaaqtMmjQpq1atWuv1z8rkDRo0KLXeoEGDfPTRR2WeD4CKT9G8Evvggw/So0eP/Otf/1q91qRJk4wcOTLbb799EZMBAAAAAFRt/fr1y8CBA3PJJZcUOwoAFUjPnj3Tv3//7Ljjjhs0d8stt+Tpp58uo1QAVdvw4cOzdOnS9O/fP3369EmhUFh9bdddd83999+f6tWr59577y1iSlh/BxxwQGrUqFHsGKynQw89NDNmzMiZZ56ZpUuXlro2derUnHHGGSkUCtl///1LXXv33XfTtGnTckwKQEXlWUEltXjx4hxyyCF57bXXVq9tscUWefLJJ7PzzjsXMRkAAAAAAH379i12BAAqoLZt2+a6667b4Lk999yzDNIAkCSvvfZaCoVCTjvttLVeb9++fTp06JDJkyeXczL46nwaSsVx8cUXZ+jQobn99tszfPjw7LXXXtlyyy0zc+bMvPzyy1m5cmW6d++eQw45ZPXM4sWL8/LLL5daA4B1UTSvpHr16rX6o08+c84552T+/Pl56qmnNuixPnsCAgAAAAAAAADA/++TTz5JkrRu3Xqde1q3bp2///3v5RUJ1uo73/nOeu175ZVX1thfKBTyxBNPlEkuvp7mzZtn9OjR+eEPf5gpU6bkySefLHX96KOPzu23315qbe7cufmv//qvHHjggeUZFYAKStG8knrmmWfWWPuqH8E6evToNT4+BQAAAACAr+exxx7LvHnzctJJJxU7CgAA8BW1adMmSTJv3rxsu+22a92zdOnSNGjQoDxjwRqeeuqpFAqF9T6t/PMHWRYKhbKKxUaw2267ZfLkyXn++eczceLELFmyJE2aNEm3bt3Stm3bNfbvuOOOGThwYBGSAlARKZoDAAAAAEARXH755Rk/fryiOQAb3QEHHJCxY8dmxYoVxY4CUOncddddueuuu9ZYnzhx4jqL5q+88kq22Wabso4GX6hWrVr59NNPc8YZZ+T4449f576f/exnmTx5cp5++ulyTMfGsO+++2bfffctdgwAKhlFcwAAAAAAAIBKZn1PKwVg/bVo0WKdJzuPHj06Rx555FrXZ86cmdNPP72s48EXmjx5cs4444wMHjw4M2bMyKBBg7L99tuvsW+LLbZIknTv3r2cEwIAmyJF80rKG0cAAAAAAABQuXznO99Zr32vvPLKGvsLhUKeeOKJMskFUFXMmDFjg2c+/vjjDBw4MAcffPDGDwQbYMcdd8zo0aNz++235xe/+EV22223DBgwIL/4xS9So0bVqpC9++67GTVqVObMmZN69eqlQ4cO6dKlS7FjfW2LFy9OzZo1U6tWrVLr7777bkaOHJl58+alTZs2OeSQQ1K3bt0ipQSgoqlazxIAAAAAAGAjq169+leaKykpWedpiACwNk899VQKhcJ6Hzr11FNPrf6z/+cAFMehhx6aQw89tNgxYLXTTz89RxxxRH7605/moosuyn333Zc//OEP6dq1a7GjbTSDBw/OTjvttMap7KtWrcr555+fm266KStWrCh1bY899sgDDzyQNm3alGfUjWLSpEk588wzM3HixBQKhRx44IG57bbb0rJly9xzzz0566yzsmzZstX7t9566zzwwAOVolwP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Oz/+8Y+LFR0AAAAAAKiCnGgOAAAAAFAOpk6dmq5du64umSfJNttsk27duqWkpCSnn376GjM77bRTOnfunNdff708owIAAAAAADjRHAAAAAA2VR988EHGjRuXmjVrZp999snmm2+++trw4cPz0EMPZd68eWnTpk1OPvnk7LXXXkVMy5f55JNP0qBBgzXWP/vn2qhRo7XONWrUKEuXLi3TbAAAAAAAAP+XojkAAAAAbIIGDx6cn//85/n444+TJA0bNsyf//znfPvb386ZZ56Z2267LSUlJav3Dxo0KNddd13OPvvsYkXmS2y99daZMmXKGuufrU2cODHdunUrda2kpCR///vf07hx43LJCAAAAAAA8JlqxQ4AAAAAwNe3atWqDB8+PKeddlo6duyYJk2apHbt2qldu3aaNGmSjh075rTTTsuDDz6YVatWFTsuX2LcuHE566yzsnz58hx44IE5+OCDs3jx4hx33HF58MEHM3jw4BxxxBF54IEH8vTTT+eSSy5JrVq1cs455+Qf//hHseOzDgcccED++c9/5ne/+93qtauuuir//Oc/s+eee+anP/1p5s6du/paSUlJLrroorz11lvZZ599ihEZAAAAAACowpxoDgAAAFDBTZgwISeccEKmT59e6oTrz7z//vt5//33M2nSpNx1113Zcccdc++996Zjx45FSMv6uO6665Ikw4cPz+GHH54kGTVqVHr06JEf/ehHOe644/LnP/959f79998/7dq1yw9/+MMMGjQogwcPLkpuvtiFF16Yv/71r/nlL3+Zyy+/PEmydOnStGjRIsOHD0/79u3Ttm3b7LPPPmnQoEH+/ve/5+233061atXSv3//IqcHAAAAAACqGieaAwAAAFRgU6dOzf77758333wzRxxxRO6+++5MmTIlCxcuzKeffppPP/00CxcuzJQpU3L33Xfn8MMPzxtvvJEDDjggU6dOLXZ81mHcuHFp37796pJ5khx00EHp2LFjPvjgg/ziF79YY+b4449Pq1atMmbMmPKMygbYcccd8+STT2b33XfPkiVLsmzZsnTv3j1PPvlktttuuwwdOjSbbbZZnnrqqQwdOjRvvfVWatasmeuvvz7dunUrdnwAAGADLF68OJdddlkOP/zwnHzyyaVeq7355pv5wQ9+kObNm6du3brZZZddMnDgwCxdurSIiQEAANbkRHMAAACg0vn2t7+dbt265YQTTkibNm2KHadMDRw4MB9//HGGDh2ao48+eq17Nt988+yyyy7ZZZddcuKJJ2bYsGH53ve+l0svvTT3339/OSdmfcyfPz9du3ZdY71NmzaZOHFidtppp7XO7bLLLnnmmWfKOF35e+utt/Lee++lfv362WmnnbLZZpsVO9JX1qVLl0yaNClLlizJZpttlpo1a66+duCBB2b69Ol55JFHMmvWrDRr1iyHHHJImjVrVsTEAADAhvroo4/SpUuXvP7666s/eezee+/Nfffdlz333DP77bdf3n///dX7p06dmiuuuCKPPfZYxo4dm1q1ahUrOkDFd2mDjfx4izbu4wFABeNEcwAAAKDSefrpp3PZZZelbdu22W+//XLrrbdmwYIFxY5VJkaPHp1u3bqts2S+Nsccc0y6d++ep59+ugyT8XXUr18/H3/88RrrtWvXTpLUrVt3rXNbbLFFVq1aVabZNrY5c+Zk3Lhx+eCDD9a4dsstt6RFixbZcccds++++2b33XfPlltumZ/+9KcV/qS/evXqlSqZf2bLLbfMiSeemF/+8pc55ZRTlMwBAKACuvrqq/Paa6/lW9/6VoYNG5Zhw4alU6dOOffcc3PRRRdl6dKlueaaa/LOO+9k0aJFGTlyZHbddddMnDgx119/fbHjAwAArOZEcwCACmD8+PF5/PHHM2fOnNSrVy8dOnTIMcccs7poBAAb25NPPpm5c+fmpJNOKnaUr6xRo0ZZvHhxxo0blxdeeCH9+/dPz54907t37xx++OEV+kTkz/voo4/SuHHjDZ5r3LhxlixZUgaJ2Bi22mqrzJo1a4317t27p0aNdb+lN3fu3DRp0qQso210F110UYYMGZJ//etfadiw4er1c889N7///e9Xn/7XtGnTLFy4MEuXLs3NN9+cF198Mc8++2zq1KlTrOgAQAVSGV7jQGVXmd4HHz58eLbccss88cQT+cY3vpEkOeCAA7L99ttn2LBh+f3vf5+zzz579f6DDjoojz/+eHbeeef85S9/yS9+8YtiRQcAACjFieYAAJuACy+8MEOHDl1jfcmSJTn22GPTuXPnXHbZZbn11ltz7bXXpnfv3tlhhx3y4osvFiEtAFXBb3/725x66qnFjvG1HH744Zk7d25uvfXW7Lfffvn000/z4IMP5rvf/W6aNWuWs846K88991yxY35tO+ywQ0aNGpX58+ev98y8efMyatSotGnTpgyT8XXsvvvuefXVV9e4GeCUU07JbbfdttaZTz/9NBMnTkzbtm3LI+JG89xzz+Wb3/xmWrVqtXpt8uTJ+f3vf586derk5ptvzpIlSzJ37twsW7Yszz33XPbaa69MnDgx11xzTfGCfwX33ntvZsyYUewYAFAlVYbXOFDRVaX3wadPn54uXbqsLpknSYMGDbLvvvsmSb773e+uMbPNNtukc+fOefPNN8stJwAAwJdRNAcA2ARceeWVeeSRR9ZYP+WUUzJ8+PA0bNgw5557bm699dZceeWV2XvvvTN79uwcfvjhmTNnThESA1BRzZ49e72+PvnkkyTJnDlzSq1XNA0aNMiPfvSjPPvss5kxY0Z+/etfZ+edd86CBQty6623pnv37mndunUGDhxYYX+Re+qpp2bBggXp2rVrRowYkZUrV65z78qVK/Pwww+na9euWbhwYU477bRyTMqGOOSQQ9K+ffu8/vrr6z3z4IMPZtGiRdl///3LLlgZmD17dnbYYYdSaw899FCS5KabbspZZ521+tTyQqGQLl265NFHH03Dhg1z//33l3ver+Okk05KmzZt0r179/zxj3/MokWLih0JACq8qvYaByqyqvQ++MqVK9d6Evtna/Xq1VvrXJ06dbJ8+fIyzQYAALAh1v05uwAAFNWkSZMydOjQbLvtthk/fnyaNWu2+tovfvGLnHnmmRk8eHB+//vf56qrripiUgAqkm233TaFQmGD9n+mUChkxYoVZRGrXGy33Xa54IILcsEFF+Tvf/977rnnnvzlL3/JjBkzcsUVV+SKK67I3nvvnd69e6dv377Fjrve+vfvn7Fjx+bBBx/MUUcdlTp16mS33XbLtttum7p16yZJli5dmlmzZmXKlClZtmxZSkpKcswxx6R///5FTs+6nHzyyTn55JM3aOab3/xmRo8enV133bWMUpWNatXWPAvj3XffTZIceeSRa51p3LhxunTpkpEjR5ZptrJQUlKSsWPH5rnnnsvZZ5+dww8/PL17907Pnj1To4a3awFgQ1Xl1zhQGVTW98G32267TJo0KSUlJav/G7Vq1apMnDgxSTJ27NgcdthhpWaWL1+eCRMmZKuttir3vAAAAOviRHMAgE3UY489lkKhkP/+7/8u9eb6Z6655po0atQojz32WBHSAVCRFQqFtGjR4gu/atasmSSl1rbbbrsiJ9949txzz1x77bX597//nSeeeCInnHBC6tWrl/Hjx+enP/1pseNtkGrVqmXo0KEZPHhwdtpppyxdujTjx4/PsGHDcu+99+bee+/NsGHDMn78+CxdujTt2rXLbbfdlr/+9a8bVMhh09euXbt07949jRs3LnaUDdKuXbu8+OKLWbVq1eq1Jk2aJMkXnvi9aNGi1SedVyRHH310Bg0alH322SeffPJJhg4dmqOPPjpbb711+vXrlxdffLHYEQH4P6644oqcfvrpxY6xUSxZsiRz587N3Llzs2TJkmLH2Wi8xoGKq7K+D37wwQdnxowZ6d+/f957772899576d+/f2bOnJkePXrk7LPPziuvvLJ6/5IlS3LGGWdk9uzZ6datWxGTAwAAlOaIHACATdSsWbOSZJ1vKterVy8dOnTIuHHjyjMWABXcgQcemKeffjrt2rXLoEGDsv3226913wEHHJAxY8bk7bffLueE5atatWrp0aNHevTokWXLlmX48OG57777ih1rgxUKhfTp0yd9+vTJjBkz8sorr+Sdd97JRx99lCSpX79+WrRokd133z2tWrUqblj4P37wgx/knHPOya9//etcfPHFSZLvfe97+e1vf5trr702N9xwwxozL730Ul544YUcdNBB5R33a2vQoEHOPPPMnHnmmZkxY0buueee3HfffXnjjTcyaNCg3HLLLWndunV69+6dE044IW3atCl2ZIAq75FHHsn48eNz++23FzvKBvvwww9z++23Z8SIEZk8eXIWLFhQ6vqWW26Z9u3bp1evXjnttNOy+eabFynpV+c1DlRslfV98AEDBuSBBx7IzTffnJtvvjnJ//t0o/bt2+fPf/5z2rdvn44dO2b77bdPgwYNMm3atCxZsiQ1atTIeeedV+T0AAAA/z8nmgMAbKJq166d5P/9wm9dmjRpkpUrV5ZXJAAqgaeeeip33HFHXn755ey222757W9/66Pi/1edOnXywx/+MI888kixo3wtrVq1ypFHHpmzzz47F1xwQS644IKcffbZOfLII5XMK5B77703M2bMKHaMctGvX7906NAhl156aX7wgx9k3Lhx2XnnnfPrX/86N998c4444ogMHTo0EydOzFNPPZWLLrooBx98cFauXJlf/vKXxY7/tbRq1SoXX3xxpk6dmpdeein9+vVLkyZN8q9//SuXXXZZ2rZtm/322y+33nrrGsVAAPgyDz/8cLbffvucd955eeaZZ/LBBx+kQYMG2WabbbLNNtukQYMG+eCDD/LMM8/k3HPPTevWrTNixIhix95gXuNAxVZZ3wffeuutM27cuBx55JFp2LBhtt5665xyyil54oknsuWWW+aRRx7J9ttvn+nTp2fixIn56KOP0qRJkzzwwAPZfffdix0fAABgNSeaAwBsIqZPn56777579fcffPBBkmTmzJlp167dWmfmzJmTxo0bl0s+ACqPU045JYcffnj69++fAQMG5L777ssf/vCH7LfffsWOBvyvk046KYVCIfvtt1969+6d733ve2nQoEGxY5WJGjVqZOTIkTn22GPzl7/8JQ888EBq1KiRRo0apXr16nn00Ufz6KOPrt5fUlKSmjVr5rbbbqtUHym/9957Z++99851112XJ598Mvfcc08efvjhjBs3Li+88EJ+9rOfZdmyZcWOCVChjRkz5ivNffjhhxs5Sdl74YUXcuyxx6Z69eo5++yz893vfjcdOnRI3bp1S+1bunRpJk2alL/+9a8ZPHhwjj322IwdOzbf+ta3ipT8q/EaByqOqvQ++A477JBhw4at9Vr79u3z+uuv58UXX8ysWbPSrFmzdO7cObVq1SrnlAAAAF9M0RwAYBPx/PPP5/nnn1/9fUlJSQqFQh577LG1vsH+0Ucf5eWXX07Hjh3LMyYAlUTjxo1z3333pXfv3jnrrLPSvXv3nHLKKbn66qu/8BSximLVqlXFjlBu7r333uy3335OK6+ESkpKMnbs2Dz33HM5++yzc/jhh6d3797p2bNnatSoXG/rbbnllnn66afzwAMP5Lbbbsvzzz+fuXPnrrFv++23T69evfKzn/0sLVu2LELSsle9evUceuihOfTQQ7NkyZIMGzYs99xzT0aPHl3saAAV3v77759CobDBc5+9R1ORXHHFFalWrVqeffbZLyyN161bN/vtt1/222+/HH/88enevXt+9atf5X/+53/KMe3GUdlf40Bl4X3w/1+NGjXcEAMAAGzyKtdvpAAAKqiBAweu81rTpk3Xun733Xfno48+yj777FNWsQCoAg455JC89tprufjii3PDDTfkf/7nf3LVVVelpKSk2NFYT1Xp5Ouq5uijj06PHj1yzz33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3ihWrBjq1q2LihUrombNmjh48CDatm2LCRMmmLv4REREREREWkw0JyIiIlIAJtcQkRL9/PPPKFSoEH7//XeMHz8eEyZMQEREBG7fvo3Vq1dj2rRpWLRoEZo3b466deti2LBhOHz4MOzt7fHjjz+au/hGqVKlCgBg//79uHTpksH/LPG182rp1FVTh+6gQYPQrFkzcxeDKM/UNDCEiIjMKywsDE+fPkWDBg20nz18+BA9e/bEw4cP0ahRIyxduhS7d+/Ghg0bMHz4cNja2iIwMBB79uwxY8mNp6akerU845BylS1bFlu3bsW2bduQnJyMtm3b4tSpU4rbphKorR28Y8eOiI6ORvv27fHPP/9g/fr1+OGHH/D69WsIIZCcnIwLFy7g9u3bKF68OObMmYNdu3Zp72FERERERERKwERzIiIiIgVgcg0RKdHly5fRokULlC1bVvtZ+fLl4efnByFEljMo16hRA76+vrh48aIpi5pvb731FgAgKirKzCWRn5o6ddmhS2ozbdo0DB061OJmuFfTwJCMzp49i88//xw9e/ZE48aN4enpCU9PTzRu3Bg9e/bE559/jrNnz5q7mEREVuXq1auoW7euzmebN29GUlISBg4ciJMnT2LkyJHo0KED+vfvj+XLl2PXrl2wsbHBggULzFTqvFFTUr2annFI2bp164ZLly5h1KhRKF26NFxdXRW5TXNSYzu4p6cndu/ejbi4OPz444/49NNP8dFHH+HDDz/EhAkTsHDhQkRERCAhIQEBAQEoUKCAuYucZ0lJSfjtt9+wf/9+PH78WOd327Ztw+DBg/HOO+/gk08+UUUbHBERERGRtbDcpxQiIiJSjaSkJBw/fhz29vbw8fFB0aJFtb/btm0bduzYgbt378LDwwODBg1Cw4YNzVjavElPrunRowc6deqEKlWqoGnTpqhfvz7OnDmD3r17w8nJCa6urnjw4AESEhKQlpaGt99+26KTa4hI2V68eIFixYrpfZ5+H878avJ0JUuWREpKiqxlk9pbb72FTZs24dSpU+jevbvB6wkh5CuUTAICArBhwwZ0794da9euRfv27XU6dW1tbdGjRw/t8levXsXo0aORmJiISZMmmbHkeZPeoRsfH4/w8HBcvHgRDx48QFpaGpycnODm5gZvb280bdqUCeZk8cLCwnDlyhVoNBqsWrXK3MUxSvrAkIkTJ2L//v24du0aNBqN9j6bPjAEePM9M3HiREyZMsUir9u4uDgMHToUERERALL+LomKikJYWBhmzZoFf39/rFq1Cu7u7iYuKRGR9UlOTtZ7jvnrr7+g0WgQFBSU5Tpt27aFj48PTp8+bYoiSubq1at6bWQZk+rXrVun87v+/fujd+/e6NixIxYsWICOHTuasrj5orZnHFI2JycnLF68GIsXL1b0Ns1Fze3gFStWxIABA8xdDNksX74cEyZMwPPnzwEAJUqUwMaNG9G2bVuMHDkSK1as0Hn2Wbp0KRYsWICxY8eaq8hERERERGQgJpoTERGRoqmpcVJNyTVEZBnKlSuHv/76S+/z9M+ioqLg5+en8zshBM6ePYtSpUqZpIxS6dSpE27cuIFq1aoZtd7333+vN0OT0qm1U9faO3SNNW3aNNy5c8ciE5Ipe2PGjMG9e/fMXYw8U8PAkNu3b8PHxweJiYnw8vJCz5490aBBA1SsWBGFCxcGADx9+hTx8fGIjo5GaGgojhw5Al9fX0RFRaF8+fJmjoCIyLKVL18eV69e1fks/TvFxcUl2/VKlSqFly9fylo2qakpqV6tzzhElort4Nbn+PHj+Pjjj2FjY4PWrVvDzs4Ohw8fRp8+fbBq1SosX74cXbt2xYABA1CqVCmEh4dj3rx5mDhxIlq0aIH69eubOwQiIiIiIsoBE82JiIhIsdTYOKmG5BoishytWrXCjz/+iHnz5mHKlCkAgLlz5+LSpUto0KABPvnkE+zduxdly5YF8CbJfPr06bh+/TreffddcxbdaNWrV8eCBQuMXs/b21uG0siPnbpkyTNfU/ZGjx5t7iJIwpoHhgQFBSExMREhISEYP358tst5eXmhU6dOmD59OkJCQjB58mTMmDEDK1euNF1hiYisULt27bBy5UqcPHkSTZo0AQA0bdoU3377Lfbt24fevXvrrZOcnIwTJ07Aw8PD1MXNFzUl1QN8xiFluXnzJu7cuYPChQvD09MTBQrkv0tejm2aE9vBrUt6m9q2bdvQuXNnAMChQ4fw9ttv48MPP0SfPn2wceNG7fL+/v7w9PRE//79sXTpUixfvtws5SYiIiIiIsNY9hMoERERWTU1N05ac3INEVmOwMBAhIaG4rPPPsPnn38OAEhJSYGrqyu2bdsGLy8vVK9eHT4+PihWrBjOnj2Lf/75BzY2Nhg3bpyZS0+5Yaeuuln6zNdElmrv3r1o0qRJjknmmU2cOBGhoaHYs2ePfAUjIlKJgIAAbNiwAd27d8fatWvRvn179OjRAz4+Pvj4449ha2uLHj16aJe/evUqRo8ejcTEREyaNMmMJTeempLq0/EZh0zh77//RrFixVCmTBm93+3cuROffvoprly5ov2sUKFC+PDDD/Hll1/CwcHBZNu0FGwH12Wpbx87fvw4vLy8tP04ANCmTRs0atQIUVFRmDp1qt46ffv2RWBgII4ePWrKohIRERERUR4w0ZyIiIgUi42TRETmVa1aNezfvx9jxozBuXPnYGNjg5YtW2LZsmWoVKkStm7dil69euHgwYPadRwcHDB//nz4+fmZseRkDHbq/h9L7dDNC2uZ+Votzp49i507dyImJgY3btxAcnIyAKBIkSJwc3ODl5cXunTpYrFvWVCTpKSkPH1Hurm54dy5c9IXiIhIZdzc3BAaGooePXqgU6dOqFKlCpo2bYr69evjzJkz6N27N5ycnODq6ooHDx4gISEBaWlpePvttzFhwgRzF98oakqqz4zPOCSnmjVrYvDgwXrPjGvWrMGHH36ItLQ0lC5dGh4eHnjw4AGuXLmCRYsWISYmBgcOHIBGozHJNskyWerbx+7du4cWLVrofe7h4YGoqCjUqFEjy/Vq1aqF8PBwmUtHRERERET5xURzIiIiUiw2ThIRmV/Tpk0RHR2Np0+fws7ODvb29trftW7dGrGxsdi1axfi4+NRtmxZdOjQAWXLljVjieVjba+pJn2W2qFL1isuLg5Dhw5FREQEAEAIobdMVFQUwsLCMGvWLPj7+2PVqlVwd3c3cUlNz1IHhri6uiIyMhIpKSkoVKiQQeukpKQgMjISlSpVkrl0RETq0LFjR0RHR2PixInYv38/rl27Bo1Go/2eTU5OxoULFwAAJUuWxMSJEzFlyhSLmwFbTUn1RKYkhNCrl9+7dw9jx46FjY0Nli1bhmHDhmmTvy9cuIBevXrhyJEjWLt2LYYMGWKSbZJlstS3jzk5OeH58+d6nzs6OgJAts8+zs7OSEtLk7VsRERERESUf+wVJyIiIsVi42TOLDW5hogsU+HChbP8vHjx4lYxU5yaX1NN/8dSO3Qz4szX1uP27dvw8fFBYmIivLy80LNnTzRo0AAVK1bU3pOfPn2K+Ph4REdHIzQ0FEeOHIGvry+ioqJQvnx5M0cgL0sdGNKnTx/Mnj0b7du3x5IlS+Dl5ZXj8jExMRg9ejQSEhIQFBRkolISEVk/T09P7N69G/Hx8QgPD8fFixfx4MEDpKWlwcnJCW5ubvD29kbTpk0tLsE8I7Uk1ROZ27Zt25CSkoJJkyZh+PDhOr+rXbs2Nm3ahEaNGmHDhg0GJ4XLsU1LpaZ2cEt9+1iZMmUQHx+v93nLli1znKghISEBLi4uchaNiIiIiIgkwERzIiIiUiw2TubMUpNriIiUiK+pzplaOnUttUMX4MzX1igoKAiJiYkICQnB+PHjs13Oy8sLnTp1wvTp0xESEoLJkydjxowZWLlypekKawaWOjAkMDAQBw4cwLFjx+Dt7Q0PDw/tAIL0gbQpKSnaAQTXrl2DEAI+Pj4ICAgwc+mJiKxPxYoVrWLgbE7UklRvLLU845BpXLhwARqNBkOHDs3y915eXmjQoAFiYmLMuk1LxXZw5atXrx7CwsLw9OlTnckqBg8ejMGDB2e5zqtXrxAVFYVGjRqZqJRERERERJRXTDQnIiIixWLjZM4sNbmGiKxPq1atEBkZidevX5u7KHnG11TnjJ26ysaZr63T3r170aRJkxyTzDObOHEiQkNDsWfPHvkKphCWOjDE0dER4eHh+OKLL7BkyRLExsYiNjYWALTfMRm/j4oVK4YxY8Zg+vTpfIMGERHlixqS6o3BZxyS0osXLwAAVapUyXaZKlWq4OzZs2bdpqWyhnZwa3/7WIcOHRAbG4uLFy+icePGBq2zfft2PHr0CP7+/vIWjoiIiIiI8o2J5kRERKRYbJzMmaUm1xCRdcpq9mRLx9dU/x9L79S19g5dznxtnZKSkuDn52f0em5ubjh37pz0BSLJODg4YPbs2QgODsaxY8dw/vx53Lx5E0+ePAEAODk5wdXVFfXq1UOzZs1gZ2dn5hITERFZH0t/xiFl8fDwAADcvXsXFStWzHKZlJQUFCtWzKzbtFSW3A6ulrePDRo0CIMGDTJqnbp16+LIkSOoXbu2TKUiIiIiIiKpMNGciIiIFIuNk0RE5tWuXTuDljt//rze8hqNBvv27ZOlXKbC11T/H0vt1FVLhy5nvrZOrq6uiIyMREpKCgoVKmTQOikpKYiMjESlSpVkLp18rH1gSEZ2dnbw9/dXxSBZIiJLNm3aNNy5c4czX1sZS33GIWVYt24d1q1bp/d5VFRUtknh58+fz/FtUnJsk8zLEt4+9u+//+L27dsoW7Ys3Nzcclz277//RkJCQp4GRGfF09MTnp6ekmyLiIiIiIjkxURzIiIisirW0DippuQaIlK2gwcPQqPRGDxb+cGDB7X/r9Fo5CqWyfA11ZbNEjp0pcKZr61Tnz59MHv2bLRv3x5LliyBl5dXjsvHxMRg9OjRSEhIQFBQkIlKKR21DAwhIiLLExYWhitXrqgi0ZxJ9US5c3V1zbbN48iRI+jWrVuWn9+4cQPDhg0z2TYtgbW3gyv57WNXr17FkCFD8Mcff+iUY+7cudlOPPHll1/ixx9/RGpqqmzlIiIiIiIiZWKiOREREZFCMLmGiJTGwcEBr169wogRI9C3b99slxs/fjxiYmJw+PBhE5ZOfmp4TbU1d+oquUNXamqd+draBQYG4sCBAzh27Bi8vb3h4eGhHSyRfpxTUlK0gyWuXbsGIQR8fHwQEBBg5tIbR00DQ4iIyPKMGTMG9+7dM3cxTMIakuqt+RmHlCEuLs7odZ4/f47g4GC0b9/eZNtUMrW0gyv17WP37t1Dy5YtkZCQAABwcXHBgwcPcP78eXTs2BETJkzA/PnzZdl3q1atEBkZidevX8uyfSIiIiIikgcTzYmIiMjiWUPjJJNriEiJYmJiMGLECCxfvhxxcXFYunQpKleurLecs7MzAKBly5YmLqG01PSaajV06iq1Q1cOapv5Wi0cHR0RHh6OL774AkuWLEFsbCxiY2MB/N9bIzJeu8WKFcOYMWMwffp0ODg4mKXMeaWmgSFERGR5Ro8ebe4imIwlJ9Wr4RmHLFfHjh3RsWNHxW/TFNTUDq7Ut4/NnTsXCQkJ6NChA1atWoVy5crh0aNH+O677zBnzhwsWLAAt27dwvr161GggPTpJIa+OZGIiIiIiJSDieZERERkFSy9cZLJNUSkRNWqVcORI0ewatUqTJ06FXXq1MG0adMwdepUWTqazElNr6lWS6euUjt05aCmma/VxsHBAbNnz0ZwcDCOHTuG8+fP4+bNm3jy5AkAwMnJCa6urqhXrx6aNWsGOzs7M5c4b9Q0MISIiEjJLDWpXi3POETWQE3t4Ep9+9iuXbvg4uKCzZs3o0iRIgDeDFyeNm0aOnXqhPfeew9btmzBo0ePsHXrVhQsWDDXbbZr186gfZ8/f15veY1Gg3379uUhEiIiIiIiMhXrygwgIiIiq6Kmxkkm1xCRkg0bNgxdunTBJ598gunTp+Onn37CsmXL0KJFC3MXTTJqek21Wjp1ldqhKwc1zXytVnZ2dvD394e/v7+5iyILNQ0MISIi5Th79ix27tyJmJgY3LhxA8nJyQCAIkWKwM3NDV5eXujSpQu8vb3NXFLKjVqecYisgZrawZX69rG4uDi0a9dOm2Sekbe3N06ePImOHTti7969aN++PXbt2pXlshkdPHgQGo3G4AmBDh48qP3/7CZ+ICIiIiIi5WCiORERESmWmhonmVxDREpXunRpbNq0CR988AFGjRoFf39/DBo0CPPmzTN30czGUl9TrZZOXaV26MpFLTNfk3VS08AQIiIyv7i4OAwdOhQREREAsn5LXlRUFMLCwjBr1iz4+/tj1apVcHd3N3FJpWPtSfVqecYhyzVt2jTcuXMHGo0Gq1atUuw2TUFN7eBKffuYRqPJsU2gdOnSiIiIQJcuXRAREYFWrVrlOqmPg4MDXr16hREjRqBv377ZLjd+/HjExMTg8OHDeS4/ERERERGZHhPNiYiISLHU1DjJ5BoishSdOnXCxYsXMW3aNCxevBg7d+6Evb29uYtFRlBLp65SO3TlZu0zX5N1UtvAECIiMp/bt2/Dx8cHiYmJ8PLyQs+ePbV1xMKFCwMAnj59qq0jhoaG4siRI/D19UVUVBTKly9v5giMo5akerU845DlCgsLw5UrVyRNCpdjm6agpnZwpb59rEqVKoiOjs5xGScnJ+zduxe9e/fGzp074efnh4oVK2a7fExMDEaMGIHly5cjLi4OS5cuReXKlfWWc3Z2BgC0bNkyXzEQEREREZFpMdGciIiIFEtNjZNMriEiS1KoUCEsWLAA77//Pj788EOcP3/e4t4koWZq6dRVaocuEelT68AQIiIyvaCgICQmJiIkJCTH2a+9vLzQqVMnTJ8+HSEhIZg8eTJmzJiBlStXmq6w+aSmpHq1POOQ5RozZgzu3bun+G2agtrawZX49rGWLVvi+++/R1RUFBo2bJhj2cPCwjB48GD89NNPuHz5crbLVqtWDUeOHMGqVaswdepU1KlTB9OmTcPUqVNRoABTUoiIiIiILB1r9URERKRYamqcZHINEVmiRo0a4cyZM4iPjzd3UczCUl9TraZOXSV26BKRPg4MISIiU9m7dy+aNGmSY5J5ZhMnTkRoaCj27NkjX8FkoKakejU945BlGj16tEVs0xTU2g6upLePdevWDUuXLsX8+fOxcePGHJe1tbXF+vXrUaJECSxevDjXiSaGDRuGLl264JNPPsH06dPx008/YdmyZWjRooWUIRARERERkYlZV4YWERERWSU1NE4yuYaILJWtrS3c3NzMXQyzsNTXVKuxU1dJHbpElDUODCEiIlNISkqCn5+f0eu5ubnh3Llz0hdIRmpKqlfjMw6RpWI7uPm1atUKBw4cgI2NjcHrLFq0CG3atMGDBw9yXbZ06dLYtGkTPvjgA4waNQr+/v4YNGgQ5s2bl59iExERERGRGTHRnIiIiCyCGhonmVxDRGRZLPU11ezUJSIls/qBITOLSby9R9Juj4jIyrm6uiIyMhIpKSnaBOTcpKSkIDIyEpUqVZK5dNJSU1I9n3HIXM6ePYudO3ciJiYGN27cQHJyMgCgSJEicHNzg5eXF7p06QJvb2+zblNp2A5uXgUKFECbNm2MXq9r165GLd+pUydcvHgR06ZNw+LFi7Fz507Y29sbvV8iIiIiIjI/JpoTERGRRVFD46TVJ9cQkVWbNm0a7ty5Y3GzfOeFpb6mGmCnLhERERGpU58+fTB79my0b98eS5YsgZeXV47Lx8TEYPTo0UhISEBQUJCJSikNNSXVA3zGIdOKi4vD0KFDERERAUB3IEO6qKgohIWFYdasWfD398eqVavg7u5u0m0qHdvBrV+hQoWwYMECvP/++/jwww9x/vx57QAgIiIiIiKyHEw0JyIiIovDxkkiIuUKCwvDlStXVJFobg3YqUtEREREahIYGIgDBw7g2LFj8Pb2hoeHBxo0aICKFStqk7FTUlIQHx+P6OhoXLt2DUII+Pj4ICAgwMylN46akuoz4jMOye327dvw8fFBYmIivLy80LNnT+19pHDhwgCAp0+fau8joaGhOHLkCHx9fREVFYXy5cubZJtEhkhOToa9vb3e2x1u3bqFAwcO4O7du/Dw8ECHDh0MHrSUlUaNGuHMmTOIj4/Pb5GJiIiIiMgMmGhOREREFouNk0REyjNmzBjcu3fP3MXIFzW8ppqIiIiISI0cHR0RHh6OL774AkuWLEFsbCxiY2MBQDuJQcZZhIsVK4YxY8Zg+vTpekl4SqempHoiUwoKCkJiYiJCQkIwfvz4bJfz8vJCp06dMH36dISEhGDy5MmYMWMGVq5caZJtEuUkOjoaI0eORFRUFDQaDVq3bo0VK1bAzc0N69evx8cff4xnz55ply9Xrhy2bNmCpk2b5nmftra2cHNzk6L4RERERERkYkw0JyIiIovGxkkiImUZPXq0uYuQZ2p8TTURERERkdo4ODhg9uzZCA4OxrFjx3D+/HncvHkTT548AQA4OTnB1dUV9erVQ7NmzWBnZ2fmEueNmpLqiUxp7969aNKkSY4J4ZlNnDgRoaGh2LNnj8m2SZSdmzdvonXr1nj8+DEcHR1ha2uLgwcPonPnzti0aROGDx+OsmXLokuXLihVqhTCw8Nx9OhRdOnSBRcvXkSZMmXMHQIREREREZkYE82JiIiIiIhI9fiaaiJSnJnFJN7eI2m3R0REZOHs7Ozg7+8Pf39/cxdFNmpJqicypaSkJPj5+Rm9npubG86dO2eybRJlZ+7cuXj8+DECAgLw+eefQ6PR4KuvvsL06dMxYMAAeHl54dChQyhatKh2nWnTpuHLL7/Ed999hy+++EKSckybNg137tyBRqPBqlWrJNkmkZxiYmLw8OHDPN2viYiIiCwdE82JiIjIqrBxkohIHmfPnsXOnTsRExODGzduIDk5GQBQpEgRuLm5wcvLC126dIG3t7eZS5o3fE01ERERERFZKzUk1ROZiqurKyIjI5GSkoJChQoZtE5KSgoiIyNRqVIlk22TKDsHDhyAm5sbZs+erX3DRWBgINasWYOYmBjs3btXJ8kcAKZPn44ffvgBe/bskSzRPCwsDFeuXGFfDlmMcePGITIyEq9fvzZ3UYiIiIhMzsbcBSAiIiKSUlhYGNauXYu1a9eauyhERFYhLi4OrVu3RqNGjTBr1iyEhYUhKioKf//9N/7++29ERUUhLCwMM2fORKNGjdCmTRvExcWZu9hGy+trqps0acLXVBMRERERERGpRJ8+fXD79m20b98eMTExuS4fExOD9u3bIyEhAf379zfZNomy8++//6J+/fraJPN0Xl5eAICGDRvqrVOwYEHUr18fsbGxkpVjzJgxCA4OxowZMyTbJpHchBDmLgIRqUxSUhJ+++037N+/H48fP9b53bZt2zB48GC88847+OSTTxAVFWWmUhKRGnBGcyIiIrIqY8aMwb1798xdDCIiPatXr0Z8fLxFdZ7cvn0bPj4+SExMhJeXF3r27IkGDRqgYsWKKFy4MADg6dOniI+PR3R0NEJDQ3HkyBH4+voiKioK5cuXN3MEhuNrqsmizSwm8fYeSbs9IiIiIiIiKxEYGIgDBw7g2LFj8Pb2hoeHh7atJH028pSUFG1bybVr1yCEgI+PDwICAky2TaLs2NnZwd7eXu/z9FnMS5QokeV6ZcuWxbNnzyQrx+jRoyXbFpEhsmufz+p6yEpqaqre8hqNBi9evJCukEREGSxfvhwTJkzA8+fPAbz5jt64cSPatm2LkSNHYsWKFToDYJYuXYoFCxZg7Nix5iqySVlivyuRJWOiOREREVkVNk4SkVKtWLECp06dsqgGj6CgICQmJiIkJCTHmb69vLzQqVMnTJ8+HSEhIZg8eTJmzJiBlStXmq6w+cTXVBMRERERERFRbhwdHREeHo4vvvgCS5YsQWxsrHaW5/QZojMm/BQrVgxjxozB9OnT4eDgYLJtkplJPSAckGxQuIuLC27fvq33eenSpVGlSpVs13v06FG2SehEliC79vnXr19Do9EYPFv569ev5SgeEZGO48eP4+OPP4aNjQ1at24NOzs7HD58GH369MGqVauwfPlydO3aFQMGDECpUqUQHh6OefPmYeLEiWjRogXq169v7hBkZ4n9rkSWjInmRERERERk9dLS0rBjxw7s3LkTMTExuHHjBpKTkwEARYoUgZubG7y8vNC1a1d07doVNjY2Zi6xMuzduxdNmjTJMck8s4kTJyI0NBR79uyRr2Ay6NOnD2bPno327dtjyZIl2tcFZycmJgajR49GQkICgoKCTFRKMgpn+SYiIiIiIiIZODg4YPbs2QgODsaxY8dw/vx53Lx5E0+ePAEAODk5wdXVFfXq1UOzZs1gZ2dnlm0SZaVmzZqIjIxEWlqaThvo3LlzMXfu3GzXO3fuHNzc3HLd/tmzZ3Ntg+3SpQu8vb3zHwyRBDw9PXHlyhV89NFH+Oqrr1CsWNZtiq1atcLRo0e1M5sTEclpwYIFAIBt27ahc+fOAIBDhw7h7bffxocffog+ffpg48aN2uX9/f3h6emJ/v37Y+nSpVi+fLlZyk1E1ouJ5kRERGQR2DhJRHl15swZvP/++4iNjc1yVpL79+/j/v37iI6Oxrp161CtWjVs2LABjRo1ynJ7N2/ezFM5LPEVmklJSfDz8zN6PTc3N5w7d076AsmIr6kmkpcQAr/99ht27NiB8+fPa+tzNjY2KF68OGrXro1WrVrhgw8+QPny5c1dXDI1DgwhIiIiIgtkZ2cHf39/+Pv7K3qbRBk1atQIu3fvxsmTJ+Hr62vQOn/88Qdu3bqFvn37ZrtMXFwchg4dioiICADIsh02KioKYWFhmDVrFvz9/bFq1Sq4u7vnKQ5SL6nb58+fP485c+bgq6++wo4dO/DNN9+gX79++SkiEVG+HT9+HF5eXtokcwBo06YNGjVqhKioKEydOlVvnb59+yIwMBBHjx41ZVHzTU39rkSWjInmRERWbPjw4fDz88N7770HJycncxeHrJxc55sqGicV/BpNsl5paWlYv349Tp8+jZIlS2LgwIGoWrUqgDeJ1/Pnz8fRo0fx4MEDuLu7o1evXhg0aJDFzfR9+fJl+Pv7IyUlBV27dkXPnj21ycOFCxcGADx9+lSbPBwaGoqdO3eiVatWOH36NDw9PfW26e7urn1tsTGEEHlaz5xcXV0RGRmJlJQUbbJ1blJSUhAZGYlKlSrJXDpp8TXVRPL5888/0b9/f1y8eDHLutyzZ89w+/ZtHDhwALNmzcK0adMwffr0bLenlu8wIiIiIiIiq8J2cEUICgrClClT4OjoaPA6Dx48QHBwMHr06JHl72/fvg0fHx8kJibCy8vLoDbYI0eOwNfXF1FRURxwTkaRun3ezs4OM2fORJ8+fTBixAgMGDAAa9euxdKlS+Hh4SFFkYmIjHbv3j20aNFC73MPDw9ERUWhRo0aWa5Xq1YthIeHy1w6aamp3xVg/wZZLiaaExFZsdWrV2PNmjUYNWoUunfvjgEDBqBdu3asgKjAy5cvkZSUBCcnJ5MNMpDjfGPjJJE8Xr16hfbt2yMiIkKb8Dd37lzs3r0bNWvWRPPmzREXF6f93eXLl7Fv3z5s27YNO3bsyPKhXamDm4KDg/H8+XNs3boV7777bpbLFC1aFLVq1UKtWrUwYMAAhIWFoVevXpg5cyY2bdqU7barV69uVFlu3LhhcaPr+/Tpg9mzZ6N9+/ZYsmQJvLy8clw+JiYGo0ePRkJCAoKCgkxUSunwNdVE0ouLi0OLFi3w+PFjNG3aFK1atULJkiXxzz//YMuWLUhKSsLXX3+NOnXq4NixY1i1ahWCg4MRFxeHlStX6m1Pju8wIiIiIrJgTFwlIjKKra2ttn/FUJ06dUKnTp2y/X1QUBASExMREhKC8ePHZ7ucl5cXOnXqhOnTpyMkJASTJ0/GjBkzsnz+J8qN1O3zNWvWRGRkJJYtW4aAgADUrVsXAQEB+Oyzz9gOTEQm5+TkhOfPn+t9nj5QLLvJoZydnZGWliZr2eRiqf2uxuTmsH+DLBkTzYmIshETE4OHDx/Cz8/P3EXJFwcHB6SkpODnn3/Gxo0bUbp0afTr1w8DBgxAgwYNzF08yoOUlBQ8fPgQJUqU0JtxYs+ePfjf//6HkydPIjU1FQBQpUoVfPzxx5gwYYLsFU+pzzc2TloOOe6Z1nIfNoSpY12yZAnCw8NRpUoVjBkzBkIILF26FB999BFatWqFGzduYMyYMejVqxeKFSuGU6dOYcaMGdi1axeWL1+Ojz76SG+bSh3cdOTIEfj5+WWbZJ6V9957Dy1btsThw4ez/H2VKlXwzz//YP/+/UbN2u3r64tTp04ZvLwSBAYG4sCBAzh27Bi8vb3h4eGhHfCT3oiVkpKiHfBz7do1CCHg4+ODgIAAM5c+76z6NdVSJ2EwAYNyMWvWLDx+/BiLFy/G6NGjdX731VdfoVOnTggODsalS5fQpk0bTJkyBb1798aaNWvQtWtXdO3aVWcdOb7DiMg4aqqnExERERFR7vbu3YsmTZrk2I+T2cSJExEaGoo9e/bIVzCySnK3z48cORLdu3fH6NGjERwcjI0bN2LJkiX5KTIRkZah7WplypRBfHy83uctW7ZEgQLZp3smJCTAxcUl3+U0JSX3u0qdm8P+DbJknNKWiCgb48aNQ+vWrc1djHzr27cvLl68iICAALi5ueG///7DokWL0LhxY9SuXRtz587Fv//+a+5iyu7WrVv48ccfMXfuXHz33Xc4fvy4uYuUZ1OnTkWlSpVw/fp1nc9DQkLQuXNnHDt2DK9fv4YQAkIIXLt2DVOmTEHXrl1lH70q9fmW18bJJk2asHHSxOS4Zyr1PhwTE4OjR49Kuk1Tx/rzzz+jUKFC+P333zF+/HhMmDABERERuH37NlavXo1p06Zh0aJFaN68OerWrYthw4bh8OHDsLe3x48//pjtdjMONnnnnXdQoUIFTJw4EdHR0SaLLbMnT56gVKlSRq9XqlQpPH36NMvfvfXWWwCAqKiofJXNEjg6OiI8PByBgYEoWrQoYmNjsWXLFoSEhGDOnDmYM2cOQkJCsGXLFsTGxqJo0aKYNm0ajhw5AgcHB3MXn4gUYP/+/ahfv75ekjkAFCxYEAsXLsTjx4/x888/az9bt24dChcujGXLlumtI9d3GBEZTuq6qxz1ayIiIiIiMp2kpCS4u7sbvZ6bmxuSkpKkLxBZNVO0z5ctWxZbt27Ftm3bkJycjLZt21rcJDJEpEyGtqvVq1cPf/75p15f5eDBg7FixYos13n16hWioqKMnhlcasbm5ii531Xq3Bz2b5AlY6I5EVmEpKQk/Pbbb9i/fz8eP36s87tt27Zh8ODBeOedd/DJJ59IWvlIfx2JKckRq6enJ+bMmYPr16/j6NGjGD58OJydnXHp0iUEBgaicuXKaN26NdasWYPk5GQ5wsqSlLEuX74cERERep+npaVh0qRJqFKlCoYMGYLAwECMGzcOLVq0QMOGDXHt2jVJY8qOlLFGRESgevXqqFWrlvaza9eu4bPPPoOtrS2mTJmCixcvameY3bBhA9zd3bF7926TjLiX8nxj46RlkeOeaY77cG7kSgo3ZayXL19GixYtULZsWe1n5cuXh5+fH4QQGDZsmN46NWrUgK+vLy5evJjtdpU4uKlq1ao4dOgQ7t27Z/A6d+/exaFDh+Dh4ZHl79966y0IIYxuWFbi+WwIBwcHzJ49G4mJiTh8+DAWLFiACRMmYPjw4Rg+fDgmTJiABQsW4PDhw0hMTMQXX3zBJHMi0rp//36291MA2t/FxsZqPytRogRatGiB06dP6y0v13cYERlHynqNUgeYEpEVmllM+n9EREQqMG3aNAwdOjTLZ24AcHV1RWRkJFJSUgzeZkpKCiIjI42auZQIMG37fLdu3XDp0iWMGjUKpUuXhqurq9HbICLKzJD7UYcOHeDl5WVUm/b27dvx6NEj2d/WK3VujpL7XaXOzWH/Blmy7N+lQESkEMuXL8eECRPw/PlzAG+SDjZu3Ii2bdti5MiRWLFihU4FYunSpViwYAHGjh2b5fbs7e0N2m/6q00yLq/RaPDixYu8hpIrqWPNSvPmzdG8eXMsXrwYu3btwvr167Fnzx6Eh4cjIiICY8aMQdeuXTFgwAC88847kseYTupYR44cicGDB6Nly5Y6n3/yySdYunQp7O3t0aNHD1SrVg0PHjzArl27cPbsWbRp0wbnz59HsWLydQxJHeu///6r93CwdetWvH79Gl9//TUmT56s/bx8+fLo378/fH19Ub9+faxdu9ao8yW/8nu+ZWycLFSokEH7ZOOktOS4Zyr5PmwoQx9clRrrixcvsrzvFS1aFABQsmTJLNcrWbJkrp0F6YNN5syZg99//x3r16/HL7/8oh1sMm3aNPj5+WHgwIHo2bMnihQpkv+AcjBkyBBMmjQJLVq0wNdff41OnTrB1tY2y2VTU1Oxa9cuTJ06FQ8fPkRQUFCWy3Xq1Ak3btxAtWrVjCrL999/rzfYyJLY2dnB399f9gYqIrIuZcqUQXR0NNLS0mBjoz/fQXoyeebvpWLFiuHJkyd6y8v5HUakduasu1rqgDwiIsWSIwl+5iPpt0lERBYhLCwMV65cgUajwapVq/R+36dPH8yePRvt27fHkiVL4OXlleP2YmJiMHr0aCQkJGTbBkuUHVO3zzs5OWHx4sVYvHix0esSkXpI3a42aNAgDBo0yKgy1K1bF0eOHEHt2rWNWs9YUufmKLnfVercHPZvkCVjojkRKdrx48fx8ccfw8bGBq1bt4adnR0OHz6MPn36YNWqVVi+fLk2SbVUqVIIDw/HvHnzMHHiRLRo0QL169fX2+br16+h0WgM7sR8/fq1xFFlTY5Yc2Jvb493330X7777Lh49eoTNmzdjw4YNOHbsGDZv3ozQ0FDZYjdVrFeuXMH333+PEiVK4OjRozqjDF++fIk+ffrg119/xbfffitbQ5YcsaampurNFPvPP/9Ao9Hggw8+yLIclStXRrNmzcz2OvK8nm9snDQ/Oe6ZSr0Py5FYo9RYy5Urh7/++kvv8/TPoqKi4Ofnp/M7IQTOnj2LUqVKGbwfJQxuGjduHCIjI7F9+3Z0794dBQsWRJ06dVCxYkXtAJb0UeZ//fUXnj17BiEE3nvvPYwbNy7LbVavXh0LFiwwuize3t75ioWIyBJ17NgRK1aswMiRI7Fw4UKdwYOXL1/GiBEjoNFo9Bprb926hdKlS+ttz1TfYURqJHXdVamDLomIiIiIyDhjxozJ8Y2RgYGBOHDgAI4dOwZvb294eHigQYMGWbbBRkdH49q1axBCwMfHBwEBAaYKg6wE2+eJSImU0Cfs6ekJT09PybdriPzk5ij5vi51bg77N8iS6U8lRUSkIOmViW3btuHAgQPYvXs3du3ahQcPHuDDDz9Enz59sH37dvTs2RP+/v6YOXMmVq1ahdTUVCxdujTLbaZXrD766CM8ePAAaWlpWf5r2bIlNBqN3ueWFKuhihUrhhEjRuDo0aP4559/MHv2bFkroKaKdefOnRBCYPbs2ToVWeBNB/aKFSvg5OSEX3/9VdL4MpIj1ipVqiA6Olrns/RRjzk9kKSmpqJAAfOPMTPmfAsMDESTJk20jZPVq1dH3759MXnyZMyYMQMzZszA5MmT0bdvX1SvXh3e3t44duwYmjRpwsZJichxz1Tqffj169dITU3F69evc/wnhIAQQuezV69eWVSsrVq1wqVLlzBv3jztZ3PnzsWlS5fg7e2NTz75BAkJCdrfCSEwffp0XL9+HT4+PkbvL32wSVhYGBISErBs2TI0a9YMz58/x+bNm9GtWzdJ4sqKjY0Ntm7diuXLl6NGjRpISUnBqVOnEBYWhg0bNmDDhg0ICwvDqVOnkJKSAk9PT6xYsQKhoaHQaDSylYuISC2CgoJQokQJrFq1Cm5ubujQoQP69euHpk2bom7durh27Rr8/PzQoUMH7TrJyck4ffo0GjZsqLc9U3+HEamJ1HVXOerXUktLS8O2bdswdOhQNGrUCC4uLnB0dISjoyNcXFzQqFEjDB06FNu3b5e1fi43tcQJMFZrjZXI0qnpelVTrERqMnr0aAQHByM4ODjL3zs6OiI8PByBgYEoWrQoYmNjsWXLFoSEhGjffhkSEoItW7YgNjYWRYsWxbRp03DkyBG95C0iS3Hu3DmzTfBFRMqj1D5hU1FCbo4cpM7NYf8GWTImmhORoh0/fhxeXl7o3Lmz9rM2bdqgUaNGSEpKwtSpU/XW6du3L9zd3bN9sDt//jyCgoKwZs0a1KxZExs3bpSt/MaQI9a8cHV1RWBgYJaj6KRiqljTRxJ27Ngxy9+XKlUKDRs2xN9//218EAaSI9b33nsP169fx8qVK7WfdenSBUIIrF69Ost1rl69imPHjhk9873ccjvf2DhpfnLcM5V6H5ajAUCpsQYGBqJgwYL47LPPUKRIERQpUgSBgYFwdXXFtm3bcOPGDVSvXh3t2rVDr169UK1aNXz11VewsbHJdpZvQ5l6cBPwZkbM4cOH4+LFi7h+/Tq2bduGRYsWae8jixYtwrZt23D9+nVcuHABw4YNY5I5EZFEKlSooH1d5/3797F//35s3rwZJ06cQGpqKt59911s27ZNZ52EhAR8+umnmDBhgt72zPkdRmTtpK67Kr2D7cyZM6hZsyZ69uyJtWvXIjo6Gvfv38fLly/x8uVL3L9/H9HR0Vi7di169OiBWrVq4cyZM7KXS2pqiRNgrNYaK5GlU9P1qqZYiUifg4MDZs+ejcTERBw+fBgLFizAhAkTMHz4cAwfPhwTJkzAggULcPjwYSQmJuKLL75gPw5ZtI8//hitW7c2dzGISCGU0idsrkEwSsjNkYPUuTns3yBLxkRzIlK0e/fuoUaNGnqfe3h4AECWvwOAWrVqIT4+Psvf2dnZYebMmTh79iw8PDwwYMAAtG/fHteuXZOu4HkgR6xKZapYbW1tAQBly5bNdpny5cvL+jpuOWKdPHky3NzcMGrUKAQEBODWrVto1qwZRo0ahVmzZmHs2LGIiorC/fv3ERsbi5UrV6Jt27Z49uwZxo8fL1lspsLGSfOS456p1PuwHA0ASo21WrVq2L9/P+rVq4enT5/i2bNnaNmyJfbv349KlSph69atsLOzw8GDB7F161Zcv34d9vb2WLRokd7ruvLDFIObMnN3d0e3bt0wduxYBAQEICAgAGPHjkW3bt3g7u4u6745wwkRqVWdOnUQExODyMhILFy4EHPmzMHy5ctx+fJlbN26Fc7OzjrLV6tWDcHBwWjRooXetpTyHUZkjaSuuyqlgy0rly9fhr+/P65evYouXbrgxx9/xF9//YWHDx/i1atXePXqFR4+fIi//voLP/74Izp37oy///4brVq1wuXLl81dfIOpJU6AsVprrESWTk3Xq5piJbImZ8+exeeff46ePXuicePG8PT0hKenJxo3boyePXvi888/x9mzZ43app2dHfz9/TFu3Dh88803+OGHH/DDDz/gm2++wbhx4+Dv7w87OzuZIiLKnhzt80IISbdHRJZLKX3C5hoEY47cHFP0u0qdm8P+DbJk+nP0ExEpiJOTE54/f673uaOjIwCgUKFCWa7n7Oyc6+xXNWvWRGRkJJYtW4aAgADUrVsXAQEB+Oyzz8zSwCFHrP/88w+cnJykK6RE5DquCQkJOhXJ9Nlo4+PjtYndmd29exclS5Y0uOzGkiPWwoUL49ChQ+jYsSPmzp2Lr7/+GhUrVkT58uWh0WiwdOlSLF26VGcdIQSCg4PRvXv3/AWUA7nPt/TGSX9/f9n2QdmT456ptPtwegNAnz59MGLECAwYMABr167F0qVLs72HGEppsQJA06ZNER0djadPn8LOzg729vba37Vu3RqxsbHYtWsX4uPjUbZsWXTo0CHHxgHK3ccff4zTp0/n+Co1IiJr1qxZMzRr1izf2+F3GJG8pKq7ylm/zq/g4GA8f/4cW7duxbvvvpvlMkWLFkWtWrVQq1YtDBgwAGFhYejVqxdmzpyJTZs2mbjEeaOWOAHGmpm1xEpk6dR0vaopViJrEBcXh6FDhyIiIgJA1smyUVFRCAsLw6xZs+Dv749Vq1bJPlEHkZzYPk9EpqCEPmFTDIJRQm6OKe7rcuTmsH+DLBUTzYlI0cqUKZPlrM4tW7ZEgQLZ38ISEhLg4uJi0D5GjhyJ7t27Y/To0QgODsbGjRuxZMmSPJc5r+SI1c3NTbLySUmu47pv3z7s27dP7/PDhw9nWZl9+fIlzpw5o32dtxzkirVy5cqIiYnBwoULsWLFCly7dg3//vuv3nKOjo5o3749pk6dCl9f37wFYSClnm8kLTnumUq5D6eTswFAabECbx6Qs1K8eHEMGDDA4O0odXBTXp07dw6PHz+WfHQ4ZzghIpKOVN9hRJQ1qequSuhgy+zIkSPw8/PLNhEuK++99x5atmyJw4cPy1gyaaklToCx5sZSYyWydGq6XtUSq/tnuyTfZpxjf8m3iZmPpN8mWY3bt2/Dx8cHiYmJ8PLyQs+ePdGgQQNUrFhR+5z99OlTxMfHIzo6GqGhoThy5Ah8fX0RFRWF8uXLmzkCorzLqn2+SpUqedrW7du381scIrJiSuwTlpJScnNM0e8qV24O+zfI0jDRnIgUrV69eggLC8PTp091vmQHDx6MwYMHZ7nOq1evEBUVhUaNGhm8n7Jly2Lr1q3YsWMHxowZg7Zt22pnnDYVU8WqBHLEOmjQoGz3l9WM4gCwZcsWPHjwAD4+PoYX3khyHld7e3tMnToVU6dORXx8PC5evIgHDx4gLS0NTk5OcHNzg6enp84ISCIpyHHPVMJ9ODO5GgCUGKsUrG2wCWc3ISKS3r1797B7927ExMTgxo0bSE5OBgAUKVIEbm5u8PLyQqdOnVCqVCkzl5SI0klZd1VSB9uTJ0/ydK8pVaoUnj59KkOJ5KGWOAHGaghLjJXI0qnpelVTrESWLigoCImJiQgJCcH48eOzXS79GX369OkICQnB5MmTMWPGDKxcudJ0hSUygbi4OGg0mjwlK6bP4EtElJX8tKspeRCMUnNz5MTcHCImmhORwnXo0AGxsbG4ePEiGjdubNA627dvx6NHj+Dv72/0/rp164Y2bdogICAAv/32m9Hr54fcsSopqUOOWNesWWN0ORo3bowjR46gevXqRq9rKFOdwxUrVkTFihXzWErpKel8I/nIcc805304K3ImhSslVl6v2cuuYVnJjTtEREr08OFDTJw4ERs2bEBqamq291eNRgNbW1sMHDgQ33zzDZydnXPcLr/DiExHqrqrUgZdVq1aFYcOHcK9e/cMvkfcvXsXhw4dyvb1v0qkljgBxpobS42VyNKp6XpVU6xElm7v3r1o0qRJjknmmU2cOBGhoaHYs2ePfAUjMpDU7fOlSpXC/fv3cfHiRRQvXtygbQkh0LlzZ5w9ezZPZSEidclLu5qSB8FInZtjaf2uUuXmsH+DLA0TzYlI0QYNGpTjaLis1K1bF0eOHEHt2rXztE8nJycsXrwYixcvztP6eSVXrHIldeSHOY5rVmrUqIEaNWpItr2sKCVWU1Hi+UbykuOeaa77cE7kSgo3Z6xyXq/W/mCs5MYdyqOZxSTeHl9RTZTu0aNH8PX1xZUrV+Di4oIuXbrk+ErunTt3Ys2aNTh+/DhOnjyJokWL6m2TdU4i85Cy7mruQZdDhgzBpEmT0KJFC3z99dfo1KkTbG1ts1w2NTUVu3btwtSpU/Hw4UMEBQWZuLR5p5Y4AcZqrbESWTo1Xa9qipXI0iUlJcHPz8/o9dzc3HDu3DnpC0RkJKnb59966y3s2bMH8fHx8PT0NHhbdnZ2Ru+fiNTL2HY1axsEk1Nujtr6Xdm/QZaKieZEZHU8PT2Negi0ZLnFKkdSh7nwuGZNScmc1nS+EWVFiQnweSXX9arEB2M5RsFbW+MOEZGcZs6ciStXrmDs2LGYN29erq+OfPnyJaZMmYLFixdj5syZCAkJ0fk965xE1sOc9etx48YhMjIS27dvR/fu3VGwYEHUqVMHFStWRKFChQAAKSkpiI+Px19//YVnz55BCIH33nsP48aNM3l580otcQKM1VpjJbJ0arpe1RQrkaVzdXVFZGQkUlJStNdnblJSUhAZGYlKlSrJXDqi3EndPv/WW29h9+7dOH36NNq2bSt1cYmI8kRNg2Aspd9Vitwc9m+QJWOiORGpmpKSdOUgdVKHpbD24wooM5lTreebmshxbanhek2npFjluF6V+mAsxyh41TTuSD3LN8CZvolUaNu2bahTpw4WLVpk0PL29vZYtGgRjhw5grCwML3vHNY5iUxDSXVXOdjY2GDr1q1YtWoVQkJCcPnyZZw6dQqnTp3KcvmaNWti4sSJGDp0qEXNlKSWOAHGaq2xElk6NV2vaoqVyNL16dMHs2fPRvv27bFkyRJ4eXnluHxMTAxGjx6NhIQEvoGAFEHq9nl/f3/Uq1cPjx4Z13Y9fPhwdOjQwah1iEgdpGhXs5RBMFLFquR+Vylzc9i/QZaMieZEZDGk7ORUYpJuRlLFKnVShxx4XI2PVanJnJZwvlHeyHFtqeV6BZQZqxzXq1IfjOUYBW8pjTtEREqQkJAAX19fo9erXbs2tm/frvc565xE8pKr7qrExHWNRoPhw4dj+PDhiIuLw/nz53Hz5k08efIEwJsZ111dXVGvXj24u7ubrFxSU0ucAGO11liJLJ2arlc1xUpkyQIDA3HgwAEcO3YM3t7e8PDw0PYxZX4DQXR0NK5duwYhBHx8fBAQEGDm0hNJ3z7v5+eXpxlxhw0blu99E5F1kbJdTemDYKSMVcn9rlLn5rB/gywZE82JSPGk7uRUapIuIH2sUid1SInHVZ+hsSo1mVPJ5xvlnRzXlpquV6XGKsf1qtQHYzlGwSu9cYeISEnKli2LM2fOIC0tDTY2Ngatk5qaijNnzqBMmTJ6v2Odk0g+ctRdlTjoMivu7u6qSHhTS5wAYyUiZVLT9aqmWIksjaOjI8LDw/HFF19gyZIliI2NRWxsLID/e8Njxnp7sWLFMGbMGEyfPh0ODg5mKTNRRmyfJyIlkrpdTcmDYKSOVcn3dalzc9i/QZaMieZEpGhydHIqNUlXjlilTuqQCo9r/mJVajKnUs83yh85ri01Xa9KjVWO61WpD8ZyjIJXcuMOEZHSdOvWDYsXL0bfvn2xZMkSuLi45Lj8vXv3MGrUKFy/fh1jx47V+z3rnETykbruqtRBl0REREREaufg4IDZs2cjODgYx44dy/ENBM2aNctxUg4iU2P7PBEpkVL7hOUgdaxKvq9LnZvD/g2yZEw0JyJFk6MyptQkXTlilTqpQyo8rtkzJFalJnMq9Xyj/JHj2lLT9arUWOW4XpX6YKzkUfBERGowa9Ys7N69G7/88gt27tyJFi1a5PhK7sjISLx48QJVq1bFzJkz9bbHOieRfKSuu1pKB9u9e/ewe/duxMTE4MaNG0hOTgYAFClSBG5ubvDy8kKnTp1QqlQpk5RHLmqJE2CsgHXGSmTp1HS9qilWIktnZ2cHf39/+Pv7m7soREREFk2pfcJyUFOsUufmsH+DLBkTzYlI0eSooCg1SVeOWKVO6pAKj2v2DIlVqcmckp9vM4tJX8iZxiWakjzXlpquV6XGKsf3g1IfjJU8Cp6ISA2cnZ1x4sQJjBs3Dps2bcLBgwdx6NChLJcVQsDGxgbvv/8+Fi5cCGdnZ71llPqMQ2QNpK67Kr3T6eHDh5g4cSI2bNiA1NRUCCGyXE6j0cDW1hYDBw7EN998k+W9ScnUEifAWLNiDbESWTo1Xa9qipWIMmBfDqnQtGnTcOfOHWg0GqxatcrcxSEiBVBqn7Ac1BSr1Lk57N8gS8ZEcyJSNDkqKEpN0pUjVqmTOqTC45q7nGJVajKnUs83yh85ri01Xa9KjVWO65UPxkRElJ2SJUtiw4YNmD9/Pvbu3ZvjK7k7dOiAsmXLZrst1jmJ5CN13VXJnU6PHj2Cr68vrly5AhcXF3Tp0kVbdy1cuDAA4OnTp9q6686dO7FmzRocP34cJ0+eRNGiRWUtn1TUEifAWK01ViJLp6brVU2xEhERhYWF4cqVK0w0JyItJfQJm2oQjBJiNRWpc3PYv0GWjInmRKRoclRQlJqkK1dlTMqkDqnwuOYst1iVnMypxPON8keOa0tN16tSYwWkv175YJwzznBCRPTmu3bw4MH53g7rnETykLruquROp5kzZ+LKlSsYO3Ys5s2bB3t7+xyXf/nyJaZMmYLFixdj5syZFvOKX7XECTDWnFhyrESWTk3Xq5piJSIiyyN1+/yYMWNw7949CUpGRNZCCX3CphoEo4RYTdXvKkduDvs3yFJpRHbvLSNSiAsXLqBOnTran//66y/Url3bjCUiUxo3bhwWL16Mnj17GlVB2bp1K8aOHYuFCxfqLfPw4UM0btwY165dg4ODg1EVgVOnTsmWDCdHrErF45o9Q4/r/fv3tcmcaWlp0Gg0WS6XnszZr18/LFy4ECVLlsxvSKaj0Nctun+2S4KC6Ipz7C/5NqV6taQc15aarlelxiq3hIQEPhhnUrNmTW3jTmpqquTbV9O9ySJilegezFjzh7HmA19RbTQ1HVfGmj9KjRWQvu6q5HYOd3d3FC1aFDExMUat5+XlhcePHyMuLu7/PlTosysgcZwAY80vxmo0qe/DSn3GARhrfig6VjVdryqJ1SLqhwBjNZKaYpUFr9f8UUusZj5/5W6fl4OajitjzR/Gmg8KblfLiyVLlmgHwQQHB+d7e9lRQqymvK+rIjeHLIK5c2g5ozkRKZoco8OUOuOqkmeplhqPa/6PK0c5kqnIcW2p6XpVaqxyk2rGWnORYxQ8ZzghIiIipZO67qrkdo6EhAT4+voavV7t2rWxfft26QskE7XECTBWQ1hirESWTk3Xq5piJSIiy8P2eSKSmxL6hEePHi3JdnKjhFhNeV9nbg7RG0w0JyJFk6uCosSKgBIqY6bC4yrdcbX0ZE6yDHJcW2q6XpUYK+VMjlfLmapxh4jIGpjqtZdEpE/KuquS2znKli2LM2fOIC0tDTY2Ngatk5qaijNnzqBMmTKylk1KaokTYKy5sdRYiSydmq5XNcVKRESWx9D2+bNnz2Lnzp2IiYnBjRs3kJycDAAoUqQI3Nzc4OXlhS5dusDb21vO4hKRhVJTn7C5YzVHvytzc0jtmGhORIonZwVFaRUBc1fGANMldfC4WucDhbGYRGRZ5Li21HS9Ki1WY6npeuXsJkRE5iX1gB81fYcRSUWquqtSn4e7deuGxYsXo2/fvliyZAlcXFxyXP7evXsYNWoUrl+/jrFjx5qkjFJQS5wAY82JJcdKZOnUdL2qKVYiIrI+cXFxGDp0KCIiIgC8GQydWVRUFMLCwjBr1iz4+/tj1apVcHd3N3FJicgSSN0nrORBMJbe/20J2L9BSsFEcyKyGGqqoJgzVjlmcc0Jj6u6mfp8IzIUr1d9clyvSn0wNmYUvJIbd4iILJXUA35Y5yQyP6XVr2fNmoXdu3fjl19+wc6dO9GiRQs0aNAAFStWRKFChQAAKSkpiI+PR3R0NCIjI/HixQtUrVoVM2fONG/hjaCWOAHGaq2xElk6NV2vaoqViIiUQ4r2+du3b8PHxweJiYnw8vJCz549td9hhQsXBgA8ffpU+x0WGhqKI0eOwNfXF1FRUShfvrxJYiUi9VHjIBj2u+pj/wYpBRPNiYhIB2dxtU5KTebk+UZkOeS4Xi35wViNjTtERKYi9WsvWeckosycnZ1x4sQJjBs3Dps2bcLBgwdx6NChLJcVQsDGxgbvv/8+Fi5cCGdnZ9MWNh/UEifAWK01ViJLp6brVU2xEhGR+UnZPh8UFITExESEhIRg/Pjx2e7Ty8sLnTp1wvTp0xESEoLJkydjxowZWLlypVRhERFpqW0QjDX1u0qdm8P+DVIKJpoTERlAqUm6cpA6qUPJ1HRclZrMqabzTU3kuLbUdL0qNVY5rldTPxhLNQpebY07RESWjnVOIvkote5qiJIlS2LDhg2YP38+9u7di/Pnz+PmzZt48uQJAMDJyQmurq6oV68eOnTogLJly5q5xHmjljgBxmqtsRJZOjVdr2qKlYiIzEfq9vm9e/eiSZMmOSaZZzZx4kSEhoZiz549UoZGRCqTU7uatQ2CySlWa+t3lTo3h/0bpBRMNCciqyNHJ6dSk3QtuUPXWDyu+cNRjmRKclxbarpelRqrHEz1YCz1KHhra9whIjIVvvaSyPpIXXc1RztH2bJlMXjwYJPsy5zUEifAWIlImdR0vaopViJL4/7ZLsm3Geco+SaJciR1+3xSUhL8/PyMLoebmxvOnTtn9HpEROlyaleztkEwOcVqbf2uzM0ha8VEcyKyOnIk6Cm1ImBMrJae1MHjmj+mHuVo6ecb5Y8c15aarldLneVbqeQYBW9tjTtERHKT67WX1v4dRmQJpK67qmnQJRERERERERlP6vZ5V1dXREZGIiUlBYUKFTJoeykpKYiMjESlSpUMLgMRUWY5tatZ2yCYnGK1tn5XQ3Nz2L9BloaJ5kRkdeRI0FPqq0gMiVWupA5T43G1DNZyvlH+yHFtqel6tdRZvjNS0oOxHKPgra1xh4hITnIM+GGdk0g5pK67WvLzMBEREREREclP6vb5Pn36YPbs2Wjfvj2WLFkCLy+vHLcTExOD0aNHIyEhAUFBQUaXg4goXU7tatY2CCanWNXW78r+DbJUTDQnIquj1GREOeQWqxxJHebC45o1JSVzWtP5RmQoS703yXW9KvHBWI5R8NbWuENEJCepB/ywzklk3ZRcv542bRru3Llj9bOtqyVOgLESkTKp6XpVU6xERCQdqdvnAwMDceDAARw7dgze3t7w8PDQtjWlbz8lJUXb1nTt2jUIIeDj44OAgABJYyMiSqemQTCW0u8qRW4O+zfIkjHRnIhUTUlJunKQYxZXS2DtxxVQZjKnWs83NZHj2lLD9ZpOSbHKcb0q9cFYjlHwamrcISLKL6kH/LDOSWQaSqq7KkVYWBiuXLli9clwaokTYKxEpExqul7VFCsREUlH6vZ5R0dHhIeH44svvsCSJUsQGxuL2NhYAIBGowGg2w9brFgxjBkzBtOnT4eDg4OEkRGRtZCiXc1SBsFIEavS+12lzM1h/wZZMiaaE5HFkLKTU4lJuhlJFascs7hKjcfV+FiVmsxpCecb5Y0c15ZarldAmbHKcb0q9cFYjlHwltK4Q0SkBFIP+GGdk0hectVdrSFxfcyYMbh37565iyE7tcQJMFYiUiY1Xa9qipWIiKQjR/u8g4MDZs+ejeDgYBw7dgznz5/HzZs38eTJEwCAk5MTXF1dUa9ePTRr1gx2dnYmi5eILIeU7WpKHwQjZaxK7neVOjeH/RtkyZhoTkSKJ3Unp1KTdOWIVY5ZXKXC45r3WJWazKnk843yTo5rS03Xq1JjleN6VeqDsRyj4JXeuENEpCRSD/hhnZNIPnLUXZU46DKvRo8ebe4imIRa4gQYKxEpk5quVzXFSkRE0pGzfd7Ozg7+/v7w9/eXrfxEZJ3kaFdT6iAYqWNVcr+r1Lk57N8gS8ZEcyJSNDkqY0pN0pUjVjlmcZUCj2v+YlVqMqdSzzfKHzmuLTVdr0qNVY7rVakPxnKNgldq4w4RkdJIPeCHdU4i+Uhdd1XqoEsiIiIiIiKybGyfJyKlkbNPWGmDYOSIVan3dalzc9i/QZaMieZEpGhyVFCUmqQrR6xyzOIqBR5XfcbEqtRkTqWeb5Q/clxbarpelRqrHNerUh+M5R4Fr7TGHSIipZF6wA/rnETykbruqtRBl5mdPXsWO3fuRExMDG7cuIHk5GQAQJEiReDm5gYvLy906dIF3t7eJimPXNQSJ8BYAeuMlcjSqel6VVOsRERkXmyfJyKlUGqfsBzkjFVp93Wpc3PYv0GWjInmRKRoclRQlJqkK0escs3iml88rjnLLValJnMq9Xyj/JHj2lLT9arUWOW4XpX8YKzUUfBERGog9YAf1jmJ5CN13VXpHWxxcXEYOnQoIiIiAOjei9JFRUUhLCwMs2bNgr+/P1atWgV3d3fZyyYltcQJMNbMrCVWIkunputVTbESEREREWWk1D5hOagpVqlzc9i/QZaMieZEpGhyVFCUmqQrR6xyz+KaVzyuucspVqUmcyr1fKP8kePaUtP1qtRY5bheLeHBWGmj4ImI1ELKAT+scxLJR+q6q5I7nW7fvg0fHx8kJibCy8sLPXv21NZdCxcuDAB4+vSptu4aGhqKI0eOwNfXF1FRUShfvrys5ZOKWuIEGKu1xkpk6dR0vaopViIiIiKizJTaJywHNcUqdW4O+zfIkjHRnIgUTY4KilKTdOWqjClxFlce15zlFquSkzmVeL5R/shxbanpelVqrID01ysfjImIKDdSDfhhnZNIHlLXXZXc6RQUFITExESEhITkOOO6l5cXOnXqhOnTpyMkJASTJ0/GjBkzsHLlSlnLJxW1xAkw1qxYQ6xElk5N16uaYiUiIiIiykzJfcJSU1OscuTmsH+DLBUTzYlI0eSooCg1SVfuypiSZnHlcc2eIbFaQjKnks43yh85ri01Xa9KjTUjKa9XPhgTEZEpsc5JJC2p665K7nTau3cvmjRpkmMiXGYTJ05EaGgo9uzZI1/BJKaWOAHGmhtLjZXI0qnpelVTrEREREREmVlCn7BU1BSrnLk57N8gS8NEcyJSNDkqKEpN0lVTZYzHNf/HlcmcZCpyXFtqul6VGqvc+GBMREREZHmkrrsquZ0jKSkJfn5+Rq/n5uaGc+fOSV8gmaglToCxGsISYyWydGq6XtUUKxERERFRZmrqE1ZTrABzc4jSMdGciBRNrgqKEisCaqqM8bhKd1yZzEmmIMe1pabrVYmxEhERERFlRcq6q5LbOVxdXREZGYmUlBRt0ntuUlJSEBkZiUqVKslaNimpJU6AsebGUmMlsnRqul7VFCsRERERUVbU1CespljTMTeH1I6J5ip17do1nDp1CvHx8Xj58iWKFy8OT09PNG3aFI6OjuYuHpEOOSsoSqsIqKkyxuNqnceVrJsc15aarlelxUpERERElB2p6q5KfR7u06cPZs+ejfbt22PJkiXw8vLKcfmYmBiMHj0aCQkJCAoKMkkZpaCWOAHGmhNLjpXI0qnpelVTrEREREREOVFTn7CaYiVSOyaaq8z27dvxxRdfIDo6OsvfOzk5YfDgwQgODkapUqVMXDqinKmpgsJYrZOaYiWydLxeiYiIiIiko7T6dWBgIA4cOIBjx47B29sbHh4eaNCgASpWrKidhTUlJQXx8fGIjo7GtWvXIISAj48PAgICzFx6w6klToCxWmusRJZOTdermmIlIiIiIiIiUhsmmqvEixcvMGzYMPz00085LvfkyRN899132Lx5M3755Rf4+fmZqIRERERERERERERE8nN0dER4eDi++OILLFmyBLGxsYiNjQUAaDQaAIAQQrt8sWLFMGbMGEyfPh0ODg5mKXNeqCVOgLFaa6xElk5N16uaYiUiIiszs5jE23sk7faIiIiIFICJ5iqQlpaGPn36YMeOHTqf29rawtXVFcWKFcM///yDR4/+r8J79+5ddOzYEQcPHoSvr6+pi0xEREREREREREQkGwcHB8yePRvBwcE4duwYzp8/j5s3b+LJkycA3rz50dXVFfXq1UOzZs1gZ2dn5hLnjVriBBirtcZKZOnUdL2qKVYiIiIiIiIiNWGiuQrMmzdPL8l85MiRCAoKQvny5QG8SUbfsWMHxo8fj5s3bwJ48wq73r1746+//kKxYhKP4iQiIiIiIiIiIiIyMzs7O/j7+8Pf39/cRZGVWuIEGCsRKZOarlc1xUpEREREJAu+bYGIFIaJ5lbu/v37mDNnjs5nX375JT777DOdz2xsbPDuu+/irbfeQvPmzREXFwcAiI+PR0hICGbNmmWqIhMRERERKZfUDTsAG3eIiIiIiIiIiIiIiHLh/tkuybcZ5yj5JomIyBhMqieyCEw0t3Jff/01kpOTtT/7+fnh008/zXb5ChUqYOXKlWjbtq32swULFuCTTz5ByZIlZS0rEREREZGU2OhMRERERERERERERERERERElHdMNLdiaWlpWLNmjc5nM2fOhEajyXG9Nm3aoEWLFoiMjAQAJCcnY8uWLfj4449lKysRERERERERWRdZBvx89Y7k2yQiIiIiIiIiIiIiIiKirDHR3IodP34cd+/e1f5cpUoV+Pv7G7TusGHDtInmALB9+3YmmhMRERFZASb9ERGRReNrNImIiIiIiIiIiIiIiIhMhonmVmzXLt0korfffjvX2cwzLptReHg4nj59isKFC0tWPiKSmdQJGACTMChHUievxjlKujkikhO/c4iIiIiIiIiIiIiIiIiIiPSxP50sHBPNrdi5c+d0fm7atKnB65YvXx7u7u6Ii4sDALx8+RIXL15E48aNJSwhEREZjZVPIiIiIiIiIiIiIiIiIiIiIiJZcKJFIl1MNLdily5d0vm5Vq1aRq1fq1YtbaJ5+vaYaE5EisTkayIiIiIiIiIiIiIiIiIiIiIiWUidfA0wAZvIUjDR3Eo9e/YMN2/e1PmsUqVKRm0j8/JXrlzJd7mIzI4JyUREBpPnQbG/5NuU4j6spliJiIiIiDKziPow68JERERERERERKQwTL4mIjVgormVunfvHoQQ2p/t7OxQunRpo7ZRoUIFnZ8TExMlKRuRMdT0KhLGmneMlYiIiIiIiIiIiIiIiIiIiIiIiEhaTDS3Uk+ePNH5uVChQtBoNEZto3DhwjluMy8SExNx9+5do9a5ePGizs+xsbH5LgdZjpd3b0i6vQsOqZJu781GL0iyGcaad4w1vxtlrMaQOk6AseZ/o4zVGIw1fxhrfjeqklgV+t0KMNb8bZCxGoux5g9jzc8GGaux1BSr5BKVWWeSBWPNH8ZqNLW0NQGMNT+UHKvkFHy9Sk6hsVpEnQlgrEZirPnDWPO7UZXEqtB6BMBY87dBxmosxpo/jDU/G2SsxuKzKylN5pzZFy9emHT/GpFx2muyGqdPn8Zbb72l/blMmTJISEgwahvff/89Ro0apf25c+fO2LlzZ77KNXPmTMyaNStf2yAiIiIiIiIiIiIiIiIiIiIiIiIiIlKb7du3o1u3bibbn43J9kQm9fz5c52f7e3tjd6Gg4ODzs/Pnj3LV5mIiIiIiIiIiIiIiIiIiIiIiIiIiIjIMjDR3Eo5Ojrq/Pzy5Uujt5F5ev3M2yQiIiIiIiIiIiIiIiIiIiIiIiIiIiLrVMDcBSB5ODk56fyceYZzQ2SewTzzNvNi1KhR6NWrl1HrPH78GGfOnEHRokXh7OyMSpUq6c22TpSb2NhYdO/eXfvz9u3bUbVqVfMVSEaMlbFaOsbKWC0dY2Wslo6xMlZLx1gZq6VjrIzV0qklVrXECTBWxmr5GCtjtXSMlbFaOsbKWC0dY2Wslo6xMlZLx1gZqyVTS5wkvxcvXuDff//V/tyyZUuT7p+J5lYqc1J4SkoKhBDQaDQGb+Pp06c5bjMvSpcujdKlSxu9nq+vb773TZRR1apVUbt2bXMXwyQYq3VirNaJsVonxmqdGKt1YqzWibFaJ8ZqnRirdVJLrGqJE2Cs1oqxWifGap0Yq3VirNaJsVonxmqdGKt1YqzWibFaJ7XEqpY4SR4NGjQw275tzLZnklWpUqV0kspfvXqFxMREo7Zx69YtnZ/zkiBOREREREREREREREREREREREREREREloeJ5laqYMGCcHV11fns5s2bRm0j8/Kenp75LhcREREREREREREREREREREREREREREpHxPNrVjmxPCLFy8atf6lS5dy3B4RERERERERERERERERERERERERERFZJyaaW7H69evr/Hz8+HGD171z5w7i4uK0P9vZ2aFWrVoSlYyIiIiIiIiIiIiIiIiIiIiIiIiIiIiUjInmVqxz5846Px88eBBCCIPW3b9/v87PrVq1gpOTk2RlIyIiIiIiIiIiIiIiIiIiIiIiIiIiIuViorkVa9q0KUqVKqX9+fr16wgPDzdo3VWrVun83K1bNymLRkRERERERERERERERERERERERERERArGRHMrZmNjg8GDB+t8NmvWrFxnNT906BAiIyO1PxcpUgS9e/eWo4hERERERERERERERERERERERERERESkQEw0t3KffvopnJyctD9HRERg7ty52S5/69YtDB8+XOezcePG6cyMTkRERERERERERERERERERERERERERNaNieZWrlSpUggMDNT5LCAgAKNGjcLt27e1n6WlpWH79u1o2rQp4uLitJ+XL18ekyZNMlVxiYiIiIiIiIiIiIiIiIiIiIiIiIiISAGYaK4Cn376KTp37qzz2ffffw9XV1d4eHigQYMGKFmyJN59913cvHlTu0zBggWxZcsWODs7m7jEREREREREREREREREREREREREREREZE5MNFcBGxsbhIaGom/fvjqfp6am4vr16zh79iwePnyo87uSJUti9+7daNasmQlLSkREREREREREREREREREREREREREREpQwNwFINNwdHTExo0b0bNnT8yePRvnzp3LcrnChQtj0KBBCA4ORunSpU1bSCIZubi4IDg4WOdna8VYrRNjtU6M1ToxVuvEWK0TY7VOjNU6MVbrxFitk1piVUucAGO1VozVOjFW68RYrRNjtU6M1ToxVuvEWK0TY7VOjNU6qSVWtcRJ1k8jhBDmLgSZXmxsLE6ePIlbt27h5cuXcHZ2Rs2aNdGsWTM4Ojqau3hERERERERERERERERERERERERERERkRkw0JyIiIiIiIiIiIiIiIiIiIiIiIiIiIiIdNuYuABEREREREREREREREREREREREREREREpCxPNiYiIiIiIiIiIiIiIiIiIiIiIiIiIiEgHE82JiIiIiIiIiIiIiIiIiIiIiIiIiIiISAcTzYmIiIiIiIiIiIiIiIiIiIiI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IebOnSu++uorMWXKFPHOO+8IV1fXLLdVuHBhsX//frPEmG7x4sXZfodWr15dDBkyRMybN09s2rRJREZGiujoaHHp0iVx/fp1cenSJREdHS0iIyPFpk2bxNdffy2GDBkiqlevnuU2bWxsxLfffmvWeE1BCfWIq1evausEme9VWf2c/tno0aP13pSSEyXE2qtXrxzrhlndV16/fi3c3d31fuft7S169uwpevbsKRo3bqx9Hsq4zPjx480SJ+tM2UtKShJubm65ngfZPTM4ODiY5TXzDx480Plb7927N8fl08/1jGWvVq2a+PLLL8Xx48fF/fv3xatXr0RycrK4du2a2LJli+jVq5d21v70dZydncW9e/dMFOX/MbTe1LBhQ7FkyRKRlJRk8jJK5dKlS9q3oWSM087OTpQrV044OzvrxR0QECBu3Lgh7O3tdc7NDz/8UPz666/izz//FJcvXxaHDh0SAQEBOs8J6f8NDw83S7x//vmnKFWqlE5Zcrr+MtebJkyYIEaOHCl69eolateurVPHyrit0qVLm+VazWjQoEFZlq1KlSpixIgRYt26deL06dO5vpknISFBnDp1Sqxbt06MGDFCVKlSJcvvrIEDB5ooMvNRQl1i7969Om2guX1Xpv/csGHDHPsJMjN3rK9fvxbe3t65fldmjPGbb74RDx8+1LZtp//Ow8NDTJgwQXz33Xfiu+++E1OmTBE1a9bUuzY6dOhg8jiFMF+9yRzH1dh6059//ql91s0cX5kyZUTDhg2Fj4+Ptq6c1TPdxo0bTRCZrn///VenLLm9laZRo0Y6y9va2oohQ4aIP/74Q7x+/Vpv+f/++09899132vtxerwFChQQFy5ckCusbGX1d8/qXHRwcBC9evWy2P45IYTYv3+/Xox2dnaiWbNmol+/fqJ79+6iQoUKOsv0799fnDp1SudYeXp6ip9++knnbQwvXrwQ+/btE61atdK7v5nrzcNbtmzRec7MfA3WqlVLVKtWTa++mF5vWrlypdi0aZNYsmSJGD16tPDz89PWnTJur0CBAmLdunVmiVEI9s/Jwdz1CCHU1T9HlB0mmhORRQgKCtKpSBYvXlysWrVKpKWlSbaPlStX6rzuz8bGRgQFBUm2fSUydyXl7Nmzep31lSpVEvPmzRMnTpwQV65cEYcPHxazZs3KcqCBjY1Nlq/+zYq5Y506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rVs3o9vxM7KWelO5cuXy9fw5duxYneNqytmyv/zyS+1+69evn+OyLi4u2mXzk+OQcTb/lStX5nk7eWHIcU3vn3v//fcN6p8rV66covrnhBBixYoV2nI6OzsbtM4333yjE1tMTIzB+0tLSxPOzs5mOa6HDh3KdxtMxreT5nQNp6amigYNGmj3l9tbAKTE/jnrrDOpqX+OKDfKGrJFRJSF+/fvA3gzWqtKlSqyzC6VUYECBXRmR0jfv6mJ/z8Dn7W6dOmS9v8LFSqEDh06GLxuwYIFERoaivHjx2tnOhFC4JdffkG3bt3w4sULOYqcZ3fv3tX+f4UKFQyaqbJ+/fo6Pxsz40DdunVRsGBB7ejI2NhYg9eVwu//r737jo+izh8//p5NJwkECKG3AIpwFAGBw0MBAbHQ7B1QT9BTviCevYCe2Mud+tWzgiB6CPw4OFSkhWIDpUrvSI0QAiQkkPL5/cF352ZSNrubKZvd1/Px2IcJ7u5nXtlkd3bmszMrVsibb74piYmJopSSnJwcGTNmjHTv3l02bNjg6LKEigMHDuif0hYR/QhKgTAeeVpEZP369dYsnB+8n35WSsnBgwd9Pjd5l09ETEekDZTxtidOnAj6fuykaZpcdtllMmXKFDl8+LB88MEH+tEAvM9NmuFTyocOHZJXX31V2rVrJ127dpV3331XsrOzXVt+789V0zSpV6+eX7cpeb26desGNKbx+k4+rnv37hWRc60tWrSQ2rVrB3wfxiNiZWVlyYEDB8q97t13361/nZub6+iRdL2tIudec1q1amXreOedd540atRIf15w+siGXt71Jrsvbvnpp5/0ThGR0aNH+33bm2++WZYsWSJ16tQRkXN/B9nZ2dKvXz9ZvHix9QtbScb1lvj4ePnTn/5U4W169erl83tfvOug3udrf49OZZWvv/5aGjduLEopKS4ulrfeekvatm0r8+bNc3Q5QsnRo0dlz549InLucRk1alS5Zy0qj/GINsXFxT6PKm61lJQUETn391rREfKNRzUL9gh9mqZJ06ZN9e+N7z1CQXJystx9992yfPly2b59uzzxxBP677xxfcn7/c8//yz333+/1K9fX2688Ub56quv9CNOu8X7OGmaJi1btvTrCFglz1x03nnn+T1edHS0NG/eXP/eyfXFTZs26V/XqlWrwiNplcX7XkcpJd9//71+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X3s8ngpPJ2s8ArqTR9O7+OKLTeuH48aNC/oo7hUpLCw0HW3O4/E4vs7kncwpcu531HvGBzuEyjpTZY901bx5c1m+fLmcf/75+jpTXl6eDB06VGbOnGnF4laK8eiugW5jCPYxMr62BnrmPavVrl1bpk2bJnPmzNGP4KeUkmnTpskFF1wQ0PNuVVXyTBlWHBmwojN3We2+++4TkXO/k5s3b5ZHH320zOsNHz5cf41YvXq1vPfeewGNc/z4cRk3bpz+u5+SklJqG3xVc+mll+oHNvjkk098HtjASR07dhSR/x6p3rheUJaCgoJS602B7PuZNWuWFBYW6p1t2rQJfKGD1LJlS/3r7OxsWbhwYcD38eWXX5q+D+QokMZtzXbr0aOHJCYm6uvDo0ePtu2IkocOHZLRo0frvxPVqlVz/CAkxm1NhYWFsnr1akfHd4r3zAFWbGuKi4uTWbNmyY033miabD5x4kTTtkO3GD8EE+gH0oJdbzJ+GMStsxkZ3XPPPbJx40bTh7e2b98uffv2lREjRvh99q6qquTzq3FbYCCMt3N6ffjBBx8UEdHPQnPdddeVOYn8hhtu0Hv3798f8If116xZI08//bT+u9+iRQtHX1/t4N0/t2TJEtm1a5c888wz0rx5c9NBDtzQpUsXEfnv88zf//53n9fPzMzU9596vf/++36P592e5cYHCDp06CAi51rPnDkj06ZNC/g+PvroI/3r6Ohoady4sc/rG/8+nNo2zP459s/5c1+hvH8OqJACgCrgo48+UpqmKY/Ho/93+PDhavfu3Zbc/+7du9WwYcOUx+MxjfHhhx9acv+B+OKLL/TxPR6Pevrpp20ba+HChUrTNH08J23bts009pIlSyy53wULFqjExETTY9m8eXP13nvvuda6evVq09j79++v8Dbr169XQ4YM0S+BKCoqUtWqVdPHmzNnTrCLbovs7Gw1YsSIUn/T/fr1U7t27Sp1fePfw6JFi1xY4vIZl23atGlq79695V7at2+vX3/58uUBj1VcXKySkpL0+5g+fboNRb6VfC6OjY1Vjz76qDp+/LjpepmZmapJkyb6732NGjXUyy+/rI4ePVrufS9atEj17t3b9LcbFRWlVq5caXNVaU7+zi1btkzdddddqnr16o4/Nyml1KBBg0y9gwcPVocOHSp1vS+++EJVr15dv67xb3jQoEEqPz/f5zjPPfecaZyLLrrIrqRy9ejRw/Sc8+abb/p1u8LCQnX77beblv/WW2/1eZuCggIVFxen32bWrFlWJPjttttuMy1v9+7d1datWy0dY8uWLapbt26m17fbbrvN0jH88dprr5mW4Z///KdtY7m53rR8+XLT2FasA+fl5akrrrii1Ovxs88+62rr4sWL9bGjoqJUXl5ehbep7PI2aNBAv+2nn34azGLborCwUL3wwgsqISHB1NemTZty1yWqynpTRctmfEyCff5q1KiRq+/r+vXrZ2oeMmSIOnz4cKnrTZs2zXS90aNHq9OnT1d4/xkZGapp06amv9+JEyfakVIuJ37fcnNz1eTJk1WfPn1MrU5r0qSJPn61atXUd999V+b1CgsL1bXXXqsvZ+PGjfXns6+//rrCcfbt26dSU1P1sVJSUqxO8am4uNg0ftOmTVVmZqbft//hhx9UbGys/nvRtWvXCm9Tr149/ef18ccfV2bxA1ZyXXjIkCE+37ME4+jRo2rw4MGmcQYOHGjpGP6YOHGi6bXkk08+sW2sUFmP8Hg8Zb63CdTRo0dVp06dTOtM0dHRavLkya62fvvtt/rYMTEx6uzZsxXeprLL631Oc+Pv1ZeTJ0+qkSNHltque9lll6kdO3aUeZtwWWeqXbu2fv2ytqn5o2nTpo68nypLcXGx6ty5s+lxe+CBB8p8D/Dmm2/qv7/R0dHq9ddf92uMrVu3qgsvvND0u//www9bnVIhJ37n9u7dqyZMmKBatmzp2nNTcXGxqlOnjv6Y1q5dW23btq3c6//lL3/Rl7NWrVpK0zQVFxenVq1aVeFYx48fV82aNdPHSkxMVIWFhVbm+FRYWKhvz9M0TbVv317l5ub6fftt27appKQk/fbt2rWr8DbG5+EPPvigMosfMONjpWmaatGihWX7dLyWLFmiWrRoYfr9/ctf/mLpGP546623TMvwj3/8w7ax3FyX+Omnn0xjb968udL3WVxcrO66665S25ruvvtu07qL061Lly41jX3q1KkKb1PZxyYtLU2/7bRp04JZbNt8/vnn+vJ5lzEtLU1NnTq1zOuHy3pTenq6fv1ff/01qPGM71/tfE9VnltuuaXUdv+yWhYsWKBfx/te159905MmTVI1a9Y0/f3+7//+rx0pPjn1O7ds2TI1YsQI074vp11wwQX6zzsmJkZ9+eWXZV7vxIkTqmfPnvpytm3bNqD3ZuvXr9fnT2iapurWrWt1SoUaNmyoj5+amupzHbGk2bNnm36nL7nkkgpvY3yv5OQ2f/bP2YP9c0BoYKI5gCrDuKPe+9+oqCh12WWXqZdeekktX75cHTt2zK/7Onr0qFq2bJl68cUX1WWXXaaioqJM9+vxeFTfvn1tLirbrl27TMtxxRVX2DaWmyspxcXFqkaNGnrnI488Ytl9r1ixQqWkpJh2MMXExLg2MeH06dP675jH41EzZ860dbzNmzebHteNGzfaOl6wFixYYNqw4/F4VLVq1dSLL75o2ilQFTZiGZfR18V7PX8nuBqV/HDGTz/9ZENRxf7nf/6nVHd8fLy65ppr1FtvvaWWLVum9u/fr7Zs2aI6d+5sWubo6GjVrl07de2116oRI0aoW265RV122WWqVq1apX5GHo9HPf744640uvE7d/r06XI35NrJOxHD+LOPi4tTl1xyibr11lvVNddcY5pYpWnnPrxz/PhxfYOjd6PWv/71L3Xy5En9vgsKCtTixYvVlVdeWerxdWNSwldffVWq9ZprrlG//PJLubeZN2+evtPbeLuKdniuXLnS9Lu/ZcsWq3N82r17d6kPXcXHx6sRI0ao5cuXq6KioqDut6ioSC1fvlwNHz5cxcfHm+4/MTHRsg8ABsK7gce7LHfddZdtY7m53pSdnW3qtGpHxtmzZ00TIr3/veSSS1xr3bdvn2lsfyYY5OTkqLVr1+qXQGRlZZnGC+bDYHbbunWraUeCpp2btHrPPfeo7Oxs03WrwnqTx+NRAwYMUCNGjCj3YpxoHsy684kTJ0zjzZ8/34Yi3w4ePKgaNGhgWhdMSUlRjzzyiFq/fr3puhMnTjT9DaampqrRo0ermTNnqg0bNqi9e/eqbdu2qeXLl6s333xT9ezZ03R9TdPUeeedV+EHv6zm9O/b3r171bPPPqtatWpl+1glPfvss6afd3x8vHrggQfU4sWL1fbt29X69evVRx99pNq3b69fJzo6Ws2dO1d/jklMTFRTpkwpd4yffvpJf3/kHevee+91sPKchx56yNR6wQUXqDVr1lR4u5kzZ5baIf3qq6/6vM3hw4dNvUuXLrWowj9r164tta2gTp06asKECWrfvn2Vuu99+/ap8ePH65PtjNsm1q1bZ1GB/7zrMd5lue+++2wfy431iN9//93U+fnnn1tyvydOnFAXX3xxqdfiG264wbXWnTt3msYu+dpSlt9//13Nnj1bvwTi1KlTpr8VqycXWiEjI0O1atXK9DuQkJCgJk6cWGryaVVZZxo2bJiaMGFCuZfmzZvr1587d27AY+Xm5pq2Wc6bN8+GIt82b96sbyP2tjRv3ly9++67pbb1//nPfzb93rdt21a9/vrr6pdfftEnDZ49e1b99ttvavbs2er2228v9d61Xr16pQ6Y4ASnf+eWL1+u7rzzTlW9enXbxyrpr3/9q+n5snbt2uq1115Tu3btUgUFBerkyZNq0aJF6oorrjA97p988on++NatW1ctW7as3DH27dununbtavp9qOigAHa4++67TY9tz5491YEDByq83cqVK00H6fB4Kj7gUMn3rgsXLrQqwy+///57qfUaj8ejevXqpaZMmaKOHDkS1P0ePnxYTZkyRfXq1avUe5zU1NSAPvRoFe92PW/r7bffbttYbq435eTkmF4DrJxMWtY+hDZt2rjWeujQIdPYK1asqPA2hYWFKjs7W78E4siRI6bxfvjhh2AX3TbHjh1Tt956a6nH6fLLLy+1jbeqrDd17NhR9e7du9yLcdJpMJP/jx49anpc3fhZnDhxQv9b8j5usbGx6sYbb1Rz5swx7Z+ZOnWqaT0oNjZWDRo0SL322mtq7ty5aunSperbb79VU6ZMUWPGjDF9eMt7m65duwa9L6EynP6dO336tPr0009dmRvi/TCl8Wd/9dVXq48//lgtWLBAzZkzRz311FOqXr16pm1S33//vf4zio6OVs8991y5B2yZPn26ql27tmkMNz54+be//c3UWq9evQoPlldYWKhee+01/XfZe/uKPnBXch/D999/b2WKT+yfswf754DQoCnl8HnTACBIJ06ckP79+8uqVav0082IlD5NSkJCgjRs2FASExMlPj5eYmNj5ezZs5Kfny+5ubly4MCBUqcSVYbTIimlpEuXLvLtt9+aTkPrpLS0NDl27JgopaR27dry+++/2zLOokWLpF+/fnp7UVGRLeOUZ8iQITJnzhwREalXr57s379fPB6PJfe9evVqGTBggBw7dkxExHS6Pu3/TkHjpNatW8u2bdtE0zR54IEHbD31zfvvvy+jRo0SkXOnljx58qRlP1ernT59Wh5//HF5++23Tacoa9++vbz//vty0UUXmU5nvmDBAunTp4/LS/1fxmWraJXK+FzVt29fmT9/fkBjffjhh3LPPffo42ZnZ0tSUlKAS2yNp556SiZOnKh/r/w4tZzx51PyuiWfz5VScu+998o777xj1SIHJJR/5+wwYsQImTx5crmvrSUfu3/9619y3XXXyfPPPy9PPfWU6bnV4/FIrVq1JDo6Wo4dOyYFBQX6fXjvs3379rJq1SpHT/Hrdc0118js2bNNyywiUr9+fWnfvr3UqlVLioqKJDMzU1avXi0nT54s9TO55ZZbZMqUKT7HeeKJJ+SFF14QEZFatWoFfEpWK0yfPl1uueUWffmNvYmJidK1a1dp06aNNG7cWBo1alTuetP+/ftl3759smnTJlm1apXk5uaa7k8pJR6PRz777DO58cYbHe/My8uT6tWrS3FxsSilpF27drJu3TpbxvKuN4mIK+sS7du3l19//VU0TZN+/frJN998Y8n9FhcXy4gRI2TKlCml/jbcWm+qWbOmforhV199VcaOHWvbWCUf18zMTP300aHmf//3f+Wxxx7TT9OraZrUrVtX/v73v8v1118vIqH9GuZdNn/WG0T++/t37733yttvvx3QWBkZGXq7pmmyfft2SU9PD2q5K2Pjxo3Sv39/OXToUKn2mjVrSocOHSQ9PV2qV68uGRkZsmbNGv22/qxbee8zNTVVMjIyHD+VcSj/vlntxIkT0rZtWzl06JCIlL/+a1xvuPXWW+XTTz+VXr16yfLly/XbtG7dWq666ipp3ry5REdHy8GDB2Xx4sWyYsUK0+MaExMj69atk9atWzvaeuzYMWnZsqX+PKyUkqioKBkwYIAMGjRIOnToYFpnWrVqlXzxxRfyyy+/mJa/Xr16smvXLp+nJ/7ss8/k9ttvFxGRqKgoycrKkuTkZEc6vf7+97/L2LFjy1wXPv/886VHjx4BrzN9//33sm3bNhEp/bti9+taeU6ePGk61W+XLl1k5cqVtozl9jrTeeedJzt27BBN02To0KEyY8YMS+739OnTMnjwYFm0aFHIrDMlJyfL6dOnRUTk7bfflnvvvde2sVasWCGXXHKJiJx7XPfv3y/169e3bbxg5efny9NPPy1vvPGG/h5B0zT5wx/+IO+//75069ZNREL7NSzYdaYHH3xQXnnllYDG+vHHH6VHjx4icu5x3bhxo+OvOyIiS5culUGDBumnlfc2RUdHS7t27UzrTJMnT5bVq1frtzX+jIzP5V7G16aEhASZP3++46eUF3Hvdy4vL08SEhIcGcvr0KFD0rZtWzlx4oSI+N5u6P1/V155pcydO1cuvPBCWb9+vf7v/fv3l4EDB5Zab/ryyy/lzJkzpvv44YcfpGvXro51ioj89ttvct5558nZs2f1373k5GQZNmyYDBw4sNz1ptmzZ0thYaH+u1mjRg3ZvXu3z/1R/+///T+59tprRcS9964ZGRly1VVXSX5+voiUfmybN28e8HrTnj179Nsb/17j4+Plq6++kl69ejnaKCJSUFAgycnJUlBQIEopOe+882TLli22jOX2elO3bt30fa7du3eX7777zrL7fuqpp+T5558PmfWmtLQ0OXr0qGiaJn/729/kscces22sefPmycCBA0Xk3PN/VlaWVK9e3bbxKuOrr76Se++9V3777Tf9MUpISJBnnnlGxo0bJx6PJyzXm4YPHy4fffRRQGN98803cuWVV4rIub/XPXv2SOPGjYNa7so4ePCgXH755bJx48Yy25s1a6avN23btk02btyo/z9fPyPj+2GllKSnp8uyZcukQYMG9sWUI5R/56x25swZ6dixY7nbELyMj493noFxnoWmaVKzZk3p06ePab0pIyND9u3bZ3qNTUxMlE2bNjn++5ubmyvnnXeeHD58WG/SNE3atm1b7nrTzJkz5fDhw6afS4sWLWTz5s0SFRVV7ljGuRIxMTFy4sQJn9unrMb+Oeu5vc4USfvnAJ8CnJgOAK7Ky8tTo0aNUtHR0aZPjXk/0VXy4v3//lxH+7+jEY0cOdKvU5Xb6aqrrjItX7CnPq2I26ddeeedd0zjz5o1y9L737hxY6mjCLrVOnz4cH1su4/A16dPH32sSy+91NaxrPLDDz+U+hR+dHS0euCBB1w/QoAv5T2vVHSJjY316+g2Rv3799dvf95559lU5L9ly5ap1q1bV/q5uOT/q1evnpo0aZKrbcblCrXfOTvk5+ebTs9V1sX7eD322GP67QoLC0sd1a+i19nU1FS1adMm11pzcnJMp703Lnd5zcbvu3XrVuHRYgsLC/VTGWuapm688UaH6kqbPn26SkpK8qvXn0tZP5PExET1xRdfuNaolFIdO3bUlycmJsa29Ti315vGjh2rjx8VFaX27t1r6f3fd999pY6c4FarcV3m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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "# Benchmark results\n", + "duckdb_times = []\n", + "chdb_times = []\n", + "\n", + "counter = 0\n", + "for query in queries:\n", + " duckdb_time, chdb_time = bench(query)\n", + " duckdb_times.append(duckdb_time)\n", + " chdb_times.append(chdb_time)\n", + "\n", + "x = range(len(queries))\n", + "xlable = [f\"Q{num}\" for num in x]\n", + "width = 0.35\n", + "\n", + "fig, ax = plt.subplots(figsize=(10, 6), dpi=300)\n", + "\n", + "rects1 = ax.bar(x, duckdb_times, width, label=\"DuckDB\")\n", + "rects2 = ax.bar([i + width for i in x], chdb_times, width, label=\"chDB\")\n", + "\n", + "ax.set_ylabel(\"Time (s)\")\n", + "ax.set_title(\"Benchmark Results\")\n", + "ax.set_xticks([i + width / 2 for i in x])\n", + "ax.set_xticklabels(xlable, rotation=90)\n", + "ax.legend()\n", + "\n", + "# Add the value of each bar on top\n", + "for rect in rects1 + rects2:\n", + " height = rect.get_height()\n", + " ax.annotate(\n", + " f\"{height:.2f}\",\n", + " xy=(rect.get_x() + rect.get_width() / 2, height),\n", + " xytext=(0, 3),\n", + " textcoords=\"offset points\",\n", + " ha=\"center\",\n", + " va=\"bottom\",\n", + " rotation=90, # Rotate the text 90°\n", + " fontsize=5, # Set the font size to a smaller value\n", + " )\n", + "\n", + "\n", + "fig.tight_layout()\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}