UI Enhancements (#582)

* Fix logo
* Websocket implemented
* Finally get the enroll button working!
This commit is contained in:
Darrell 2022-08-10 21:39:17 -04:00 committed by GitHub
parent f7d23a1ae9
commit bd141f6e79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 2503 additions and 1427 deletions

View File

@ -1,214 +1,6 @@
--- ---
Language: Cpp BasedOnStyle: Google
# BasedOnStyle: LLVM ColumnLimit: 0
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 999
CommentPragmas: '^ IWYU pragma:'
QualifierAlignment: Leave
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
PackConstructorInitializers: BinPack
BasedOnStyle: ''
ConstructorInitializerAllOnOneLineOrOnePerLine: false
AllowAllConstructorInitializersOnNextLine: true
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentRequiresClause: true
IndentWidth: 4 IndentWidth: 4
IndentWrappedFunctionNames: false
InsertBraces: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PenaltyIndentedWhitespace: 0
PointerAlignment: Right
PPIndentWidth: -1
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RequiresClausePosition: OwnLine
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseCRLF: false UseCRLF: false
UseTab: Never UseTab: Never
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
- NS_SWIFT_NAME
- CF_SWIFT_NAME

View File

@ -1,6 +1,7 @@
#include "Enrollment.h" #include "Enrollment.h"
#include "globals.h" #include "globals.h"
#include "mqtt.h" #include "mqtt.h"
#include "HttpServer.h"
#include <NimBLEDevice.h> #include <NimBLEDevice.h>
#include <NimBLEAdvertisedDevice.h> #include <NimBLEAdvertisedDevice.h>
@ -11,7 +12,7 @@
namespace Enrollment namespace Enrollment
{ {
static const char hex_digits[] = "0123456789abcdef"; static const char hex_digits[] = "0123456789abcdef";
static bool enrolling = false, lastEnrolling = false; static bool lastEnrolling = false;
static NimBLEServer *pServer; static NimBLEServer *pServer;
static String id; static String id;
static unsigned long lastLoop = 0; static unsigned long lastLoop = 0;
@ -217,6 +218,7 @@ namespace Enrollment
{ {
if (enrolling != lastEnrolling) if (enrolling != lastEnrolling)
{ {
HttpServer::SendState();
auto pAdvertising = NimBLEDevice::getAdvertising(); auto pAdvertising = NimBLEDevice::getAdvertising();
if (enrolling) if (enrolling)
{ {
@ -229,12 +231,19 @@ namespace Enrollment
Serial.println("Advertising stopped"); Serial.println("Advertising stopped");
} }
lastEnrolling = enrolling; lastEnrolling = enrolling;
if (enrolling) enrollingEndMillis = millis() + 120000;
}
if (enrolling && enrollingEndMillis < millis())
{
enrolling = false;
} }
if (millis() - lastLoop > 1000) if (millis() - lastLoop > 1000)
{ {
lastLoop = millis(); lastLoop = millis();
if (enrolling) HttpServer::SendState();
if (pServer->getConnectedCount()) if (pServer->getConnectedCount())
{ {
NimBLEService *pSvc = pServer->getServiceByUUID("180D"); NimBLEService *pSvc = pServer->getServiceByUUID("180D");

View File

@ -1,63 +1,72 @@
#include "MotionSensors.h" #include "HttpServer.h"
#include <AsyncWiFiSettings.h>
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include <AsyncWiFiSettings.h>
#include "ArduinoJson.h"
#include "AsyncJson.h"
#include "Enrollment.h"
#include "GUI.h"
#include "MotionSensors.h"
#include "defaults.h"
#include "globals.h" #include "globals.h"
#include "mqtt.h" #include "mqtt.h"
#include "string_utils.h" #include "string_utils.h"
#include "defaults.h"
#include "GUI.h"
#include "HttpServer.h"
#include "AsyncJson.h"
#include "ArduinoJson.h"
#include "ui_bundle_css.h" #include "ui_bundle_css.h"
#include "ui_index_html.h" #include "ui_index_html.h"
#include "ui_index_js.h" #include "ui_index_js.h"
namespace HttpServer namespace HttpServer {
{
void serializeConfigs(JsonObject& root) void serializeInfo(JsonObject &root) {
{ root["room"] = room;
}
void serializeState(JsonObject &root) {
JsonObject node = root.createNestedObject("state");
node["enrolling"] = enrolling;
if (enrolling) node["remaining_ms"] = enrollingEndMillis - millis();
}
void serializeConfigs(JsonObject &root) {
JsonArray devices = root.createNestedArray("configs"); JsonArray devices = root.createNestedArray("configs");
auto f = BleFingerprintCollection::getConfigs(); auto f = BleFingerprintCollection::getConfigs();
for (auto it = f.begin(); it != f.end(); ++it) for (auto it = f.begin(); it != f.end(); ++it) {
{
JsonObject node = devices.createNestedObject(); JsonObject node = devices.createNestedObject();
node["id"]=it->id; node["id"] = it->id;
node["alias"] = it->alias; node["alias"] = it->alias;
node["name"]=it->name; node["name"] = it->name;
node["rss@1m"]=it->calRssi; node["rss@1m"] = it->calRssi;
}
} }
}
void serializeDevices(JsonObject& root) void serializeDevices(JsonObject &root) {
{
JsonArray devices = root.createNestedArray("devices"); JsonArray devices = root.createNestedArray("devices");
auto f = fingerprints.getCopy(); auto f = fingerprints.getCopy();
for (auto it = f.begin(); it != f.end(); ++it) for (auto it = f.begin(); it != f.end(); ++it) {
{
if ((*it)->getVisible()) { if ((*it)->getVisible()) {
JsonObject node = devices.createNestedObject(); JsonObject node = devices.createNestedObject();
(*it)->fill(&node); (*it)->fill(&node);
} }
} }
} }
bool servingJson = false; bool servingJson = false;
void serveJson(AsyncWebServerRequest* request) {
void serveJson(AsyncWebServerRequest *request) {
if (servingJson) request->send(429, "Too Many Requests", "Too Many Requests"); if (servingJson) request->send(429, "Too Many Requests", "Too Many Requests");
servingJson = true; servingJson = true;
const String& url = request->url(); const String &url = request->url();
short subJson = 0; short subJson = 0;
if (url.indexOf("devices") > 0) subJson = 1; if (url.indexOf("devices") > 0) subJson = 1;
if (url.indexOf("configs") > 0) subJson = 2; if (url.indexOf("configs") > 0) subJson = 2;
AsyncJsonResponse* response = new AsyncJsonResponse(false, JSON_BUFFER_SIZE); AsyncJsonResponse *response = new AsyncJsonResponse(false, JSON_BUFFER_SIZE);
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
root["room"] = room; serializeInfo(root);
switch (subJson) switch (subJson) {
{
case 1: case 1:
serializeDevices(root); serializeDevices(root);
break; break;
@ -68,11 +77,60 @@ namespace HttpServer
response->setLength(); response->setLength();
request->send(response); request->send(response);
servingJson = false; servingJson = false;
}
void sendDataWs(AsyncWebSocketClient *client) {
if (!ws.count()) return;
AsyncWebSocketMessageBuffer *buffer;
{ // scope JsonDocument so it releases its buffer
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
JsonObject root = doc.to<JsonObject>();
serializeState(root);
serializeInfo(root);
size_t len = measureJson(doc);
size_t heap1 = ESP.getFreeHeap();
buffer = ws.makeBuffer(len); // will not allocate correct memory sometimes
size_t heap2 = ESP.getFreeHeap();
if (!buffer || heap1 - heap2 < len) {
ws.closeAll(1013); // code 1013 = temporary overload, try again later
ws.cleanupClients(0); // disconnect all clients to release memory
return; // out of memory
}
serializeJson(doc, (char *)buffer->get(), len + 1);
}
if (client) {
client->text(buffer);
} else {
ws.textAll(buffer);
}
}
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
if (type == WS_EVT_CONNECT) {
sendDataWs(NULL);
} else if (type == WS_EVT_DATA) {
AwsFrameInfo *info = (AwsFrameInfo *)arg;
if (info->final && info->index == 0 && info->len == len) {
if (info->opcode == WS_TEXT) {
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
DeserializationError error = deserializeJson(doc, data, len);
JsonObject root = doc.as<JsonObject>();
if (error || root.isNull()) {
return;
} }
void serializeConfig(){}; if (root.containsKey("command") && root.containsKey("payload")) {
void Init(AsyncWebServer *server) String command = root["command"].as<String>();
{ String payload = root["payload"].as<String>();
Enrollment::Command(command, payload);
}
}
}
}
}
void Init(AsyncWebServer *server) {
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Origin"), "*"); DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Origin"), "*");
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Methods"), "*"); DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Methods"), "*");
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Headers"), "*"); DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Headers"), "*");
@ -88,23 +146,39 @@ namespace HttpServer
server->on("/index.js", HTTP_GET, serveIndexJs); server->on("/index.js", HTTP_GET, serveIndexJs);
server->on("/json", HTTP_GET, serveJson); server->on("/json", HTTP_GET, serveJson);
AsyncCallbackJsonWebHandler *handler = new AsyncCallbackJsonWebHandler("/json", [](AsyncWebServerRequest *request, JsonVariant &json) AsyncCallbackJsonWebHandler *handler = new AsyncCallbackJsonWebHandler(
{ "/json", [](AsyncWebServerRequest *request, JsonVariant &json) {
bool verboseResponse = false; bool verboseResponse = false;
bool isConfig = false; bool isConfig = false;
{ {
DynamicJsonDocument doc(1500); DynamicJsonDocument doc(1500);
DeserializationError error = deserializeJson(doc, (uint8_t *) (request->_tempObject)); DeserializationError error =
deserializeJson(doc, (uint8_t *)(request->_tempObject));
JsonObject root = doc.as<JsonObject>(); JsonObject root = doc.as<JsonObject>();
if (error || root.isNull()) if (error || root.isNull()) {
{
request->send(400, "application/json", F("{\"error\":9}")); request->send(400, "application/json", F("{\"error\":9}"));
return; return;
} }
const String& url = request->url(); const String &url = request->url();
} }
request->send(200, "application/json", F("{\"success\":true}")); request->send(200, "application/json", F("{\"success\":true}"));
}); });
server->addHandler(handler); server->addHandler(handler);
} server->addHandler(&ws);
ws.onEvent(onWsEvent);
} }
void Loop() { ws.cleanupClients(); }
void UpdateStart() {
ws.enable(false);
ws.textAll("OTA Update Started");
ws.closeAll();
}
void UpdateEnd() { ws.enable(true); }
void SendState() { sendDataWs(NULL); }
} // namespace HttpServer

View File

@ -1,7 +1,18 @@
#pragma once #pragma once
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>
namespace HttpServer namespace HttpServer
{ {
void Init(AsyncWebServer* server);
} void Init(AsyncWebServer *server);
void Loop();
void UpdateStart();
void UpdateEnd();
void SendState();
} // namespace HttpServer

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <Arduino.h> #include <Arduino.h>
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <BleFingerprintCollection.h> #include <BleFingerprintCollection.h>
@ -32,6 +33,9 @@ _DECL String room, id, statusTopic, teleTopic, roomsTopic, setTopic, configTopic
_DECL AsyncMqttClient mqttClient; _DECL AsyncMqttClient mqttClient;
_DECL DynamicJsonDocument doc _INIT_N(((2048))); _DECL DynamicJsonDocument doc _INIT_N(((2048)));
_DECL String localIp; _DECL String localIp;
_DECL AsyncWebSocket ws _INIT_N((("/ws")));
_DECL bool enrolling;
_DECL unsigned long enrollingEndMillis;
// I2C // I2C
_DECL int I2C_Bus_1_SDA; _DECL int I2C_Bus_1_SDA;

View File

@ -586,6 +586,7 @@ void loop()
if (freeHeap < 10000) Serial.printf("Low memory: %u bytes free", freeHeap); if (freeHeap < 10000) Serial.printf("Low memory: %u bytes free", freeHeap);
firmwareUpdate(); firmwareUpdate();
Motion::Loop(); Motion::Loop();
HttpServer::Loop();
#ifdef SENSORS #ifdef SENSORS
DHT::Loop(); DHT::Loop();
BH1750::Loop(); BH1750::Loop();

View File

@ -203,6 +203,8 @@ void firmwareUpdate()
updateStartedMillis = millis(); updateStartedMillis = millis();
mqttClient.disconnect(); mqttClient.disconnect();
NimBLEDevice::getScan()->stop(); NimBLEDevice::getScan()->stop();
SPIFFS.end();
HttpServer::UpdateStart();
GUI::updateStart(); GUI::updateStart();
httpUpdate.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS); httpUpdate.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
httpUpdate.onProgress([](int progress, int total) httpUpdate.onProgress([](int progress, int total)
@ -211,6 +213,7 @@ void firmwareUpdate()
}); });
t_httpUpdate_return ret = httpUpdate.update(client, firmwareUrl); t_httpUpdate_return ret = httpUpdate.update(client, firmwareUrl);
GUI::updateEnd(); GUI::updateEnd();
HttpServer::UpdateEnd();
switch (ret) switch (ret)
{ {
@ -221,12 +224,9 @@ void firmwareUpdate()
case HTTP_UPDATE_NO_UPDATES: case HTTP_UPDATE_NO_UPDATES:
Serial.printf("No Update!\n"); Serial.printf("No Update!\n");
break; break;
case HTTP_UPDATE_OK:
Serial.printf("Update OK!\n");
break;
} }
SPIFFS.begin(true);
updateStartedMillis = 0; updateStartedMillis = 0;
#endif #endif
} }

View File

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

File diff suppressed because it is too large Load Diff

1153
ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -15,9 +15,11 @@
"@rollup/plugin-node-resolve": "^13.3.0", "@rollup/plugin-node-resolve": "^13.3.0",
"@sveltejs/vite-plugin-svelte": "^1.0.1", "@sveltejs/vite-plugin-svelte": "^1.0.1",
"autoprefixer": "^10.4.8", "autoprefixer": "^10.4.8",
"brotli": "^1.3.3",
"concurrently": "^7.3.0", "concurrently": "^7.3.0",
"cssnano": "^5.1.12", "cssnano": "^5.1.12",
"mime": "^3.0.0", "mime": "^3.0.0",
"node-zopfli": "^2.1.4",
"pascal-case": "^3.1.2", "pascal-case": "^3.1.2",
"postcss": "^8.4.14", "postcss": "^8.4.14",
"postcss-load-config": "^4.0.1", "postcss-load-config": "^4.0.1",

View File

@ -7,7 +7,7 @@ import htmlTemplate from 'rollup-plugin-generate-html-template';
import { readFile, writeFile } from 'fs'; import { readFile, writeFile } from 'fs';
import { basename } from 'path'; import { basename } from 'path';
import { promisify } from 'util'; import { promisify } from 'util';
import zlib from 'zlib'; import zlib from 'node:zlib';
import { VERSION, } from 'rollup'; import { VERSION, } from 'rollup';
import { pascalCase } from "pascal-case"; import { pascalCase } from "pascal-case";
import mime from 'mime'; import mime from 'mime';
@ -31,9 +31,8 @@ function hexdump(buffer) {
return lines.join(",\n"); return lines.join(",\n");
} }
function cppGzipped(html, fileName, contentType) { function cppCompressed(input, fileName, contentType) {
return new Promise((resolve, reject) => zlib.gzip(input, { level: zlib.constants.Z_BEST_COMPRESSION }, function (error, result) {
return new Promise((resolve, reject) => zlib.gzip(html, { level: zlib.constants.Z_BEST_COMPRESSION }, function (error, result) {
if (error) { if (error) {
reject(err); reject(err);
} }
@ -59,7 +58,7 @@ function cppGzipped(html, fileName, contentType) {
`; `;
resolve(src); resolve(src);
})); }));
} }
const isFunction = (arg) => typeof arg === 'function'; const isFunction = (arg) => typeof arg === 'function';
const isRegExp = (arg) => Object.prototype.toString.call(arg) === '[object RegExp]'; const isRegExp = (arg) => Object.prototype.toString.call(arg) === '[object RegExp]';
@ -95,7 +94,7 @@ function cpp(options = {}) {
? options.fileName ? options.fileName
: (fileName) => fileName + (options.fileName || '.cpp'); : (fileName) => fileName + (options.fileName || '.cpp');
const plugin = { const plugin = {
name: 'gzip', name: 'cpp',
generateBundle(outputOptions, bundle, isWrite) { generateBundle(outputOptions, bundle, isWrite) {
if (!isWrite) if (!isWrite)
return; return;
@ -118,7 +117,7 @@ function cpp(options = {}) {
options.minSize > fileContent.length) { options.minSize > fileContent.length) {
return Promise.resolve(); return Promise.resolve();
} }
return Promise.resolve(cppGzipped(fileContent, fileName)) return Promise.resolve(cppCompressed(fileContent, fileName))
.then(compressedContent => { .then(compressedContent => {
writeFilePromise(mapFileName(fileName), compressedContent); writeFilePromise(mapFileName(fileName), compressedContent);
@ -126,7 +125,7 @@ function cpp(options = {}) {
}) })
.catch((err) => { .catch((err) => {
console.error(err); console.error(err);
return Promise.reject('[rollup-plugin-gzip] Error compressing file ' + return Promise.reject('[rollup-plugin-cpp] Error compressing file ' +
fileName); fileName);
}); });
}) })
@ -136,12 +135,12 @@ function cpp(options = {}) {
!options.additionalFiles.length) !options.additionalFiles.length)
return Promise.resolve(); return Promise.resolve();
const compressAdditionalFiles = () => Promise.all(options.additionalFiles.map(filePath => readFilePromise(filePath) const compressAdditionalFiles = () => Promise.all(options.additionalFiles.map(filePath => readFilePromise(filePath)
.then(fileContent => cppGzipped(fileContent, basename(filePath))) .then(fileContent => cppCompressed(fileContent, basename(filePath)))
.then(compressedContent => { .then(compressedContent => {
return writeFilePromise(mapFileName(filePath), compressedContent); return writeFilePromise(mapFileName(filePath), compressedContent);
}) })
.catch((err) => { .catch((err) => {
return Promise.reject('[rollup-plugin-gzip] Error compressing additional file ' + return Promise.reject('[rollup-plugin-cpp] Error compressing additional file ' +
filePath + '\n' + err); filePath + '\n' + err);
}))); })));
// additional files can be processed outside of rollup after a delay // additional files can be processed outside of rollup after a delay

View File

@ -22,6 +22,12 @@
h: 1792, h: 1792,
svg: `<path d="M685 483q16 0 27.5-11.5t11.5-27.5-11.5-27.5-27.5-11.5-27 11.5-11 27.5 11 27.5 27 11.5zm422 0q16 0 27-11.5t11-27.5-11-27.5-27-11.5-27.5 11.5-11.5 27.5 11.5 27.5 27.5 11.5zm-812 184q42 0 72 30t30 72v430q0 43-29.5 73t-72.5 30-73-30-30-73v-430q0-42 30-72t73-30zm1060 19v666q0 46-32 78t-77 32h-75v227q0 43-30 73t-73 30-73-30-30-73v-227h-138v227q0 43-30 73t-73 30q-42 0-72-30t-30-73l-1-227h-74q-46 0-78-32t-32-78v-666h918zm-232-405q107 55 171 153.5t64 215.5h-925q0-117 64-215.5t172-153.5l-71-131q-7-13 5-20 13-6 20 6l72 132q95-42 201-42t201 42l72-132q7-12 20-6 12 7 5 20zm477 488v430q0 43-30 73t-73 30q-42 0-72-30t-30-73v-430q0-43 30-72.5t72-29.5q43 0 73 29.5t30 72.5z"/>`, svg: `<path d="M685 483q16 0 27.5-11.5t11.5-27.5-11.5-27.5-27.5-11.5-27 11.5-11 27.5 11 27.5 27 11.5zm422 0q16 0 27-11.5t11-27.5-11-27.5-27-11.5-27.5 11.5-11.5 27.5 11.5 27.5 27.5 11.5zm-812 184q42 0 72 30t30 72v430q0 43-29.5 73t-72.5 30-73-30-30-73v-430q0-42 30-72t73-30zm1060 19v666q0 46-32 78t-77 32h-75v227q0 43-30 73t-73 30-73-30-30-73v-227h-138v227q0 43-30 73t-73 30q-42 0-72-30t-30-73l-1-227h-74q-46 0-78-32t-32-78v-666h918zm-232-405q107 55 171 153.5t64 215.5h-925q0-117 64-215.5t172-153.5l-71-131q-7-13 5-20 13-6 20 6l72 132q95-42 201-42t201 42l72-132q7-12 20-6 12 7 5 20zm477 488v430q0 43-30 73t-73 30q-42 0-72-30t-30-73v-430q0-43 30-72.5t72-29.5q43 0 73 29.5t30 72.5z"/>`,
}, },
{
name: "fingerprint",
w: 32,
h: 32,
svg: `<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10"><path d="m4.2 27.3.5-1c2-3.8 3-7.9 3-12.1v0c0-4.3 3.4-8 7.9-8.2a8 8 0 0 1 8.4 7.8v4.9c0 1.4.8 2.6 2 3.2h0"/><path d="M3.9 14.6c0-7 5.3-12.6 12-12.6s12 5.6 12 12.6V18"/><path d="m7.3 30 .1-.2a31 31 0 0 0 4.8-16.3v0c0-1.8 1.5-3.4 3.5-3.5 2.1-.1 3.9 1.4 3.9 3.3v0c.4 7.7-3.9 16.6-3.9 16.6"/><path d="m16 14-.2 1.4c-.6 5-1.9 9.9-3.8 14.6h0"/><g>`
}
]; ];
let displayIcon = icons.find((e) => e.name === name); let displayIcon = icons.find((e) => e.name === name);
</script> </script>

View File

@ -6,20 +6,21 @@
<div class="flex flex-col sm:flex-row sm:justify-around"> <div class="flex flex-col sm:flex-row sm:justify-around">
<div class="w-72 h-screen"> <div class="w-72 h-screen">
<div class="flex items-center justify-start mx-6 mt-10"> <div class="flex items-center justify-start mx-6 mt-10">
<svg class="h-10" preserveAspectRatio="xMidYMid" version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 204 204"> <svg class="h-12" viewBox="0 0 210 210" xmlns="http://www.w3.org/2000/svg">
<circle cx="102" cy="102" r="102" fill="#fff" /> <circle style="fill:#fff" cx="105" cy="105" r="105"/>
<path d="M3.42 102.13c-.04 57.18 47.35 98.12 99.2 98.09 57.46-.32 98.2-49.29 97.75-98.23-.03-28.4-10.65-47.14-17.55-56.35-7.38-9.71-6.07-12.38-17.74-.72l-9.3 9.3c24.2 32.31 20.42 61.25 7.6 83.7-25.5 35.3-49.6 32.8-49.6 32.8-8.63 10.92-14.66 10.4-24.32 2.04-30.59-1.88-58-34.54-59.12-69.25-.13-11.12 2.82-20.08 8.15-32.36-7.42-13.89-.35-25.14 15.7-23.15 0 0 19.51-17.51 44.8-18.32 28.29-1.26 50.29 18.14 50.29 18.14l9.3-9.4c10.8-10.9 10.68-8.91-1.72-18.62-.1.7-18.27-16.62-61.54-16.34-43.27.28-91.87 41.5-91.9 98.67z" /> <circle cx="134.5" cy="129.5" r="6"/>
<path d="M96.26 38.92c-12.62.72-25.74 8.82-35.04 14.46 2.48 12.33-5 21.34-14.58 21.1-9.55 18-6.64 31.97-6.64 31.97-.3 31.5 39.77 64.78 52.38 53.17 6.9-6.3 13.06-5.17 19.96 1.23 10.53 4.94 26.33-8.08 33.54-15.23 22-21.9 24.8-55.7 6.7-80.6l-3.2-4.4-6.3 6.3-6.3 6.2c14.65 19.66 7.32 43.8 7.32 43.8 2.88 14.8-3.88 24.35-18.38 21.78-11.95 8.42-34.24 9.22-48.54-.28-6.6-4.3-10.4-8.6-14.4-16.4-15.18-33.19 6.6-64.4 38.8-64.6 13.82.47 18.53 2.97 28.8 9.2l12.5-12.5-4.4-3.2c-13.4-9.7-27.61-12.84-42.22-12z" /> <circle cx="104" cy="170" r="6"/>
<path d="M91.08 67.62c-7.8 2.8-14.3 7.9-18.5 14.4-11.6 17.9-5.6 40.8 13.2 51 6 3.2 6.8 3.4 16.3 3.4 8-.1 10.9-.5 14.7-2.2 4.5-2.1 4.6-2.3 3.9-5.5-1.6-7.5 3.4-13.8 11.1-13.8 3.4 0 3.8-.3 4.7-3.8 2.5-8.8.6-21.2-4.4-28.9l-1.7-2.6-9.8 9.8c-7.9 7.9-9.7 10.2-9.8 12.7-.2 6.8-8.4 10.3-14 6.1-6.21-5.49-1.4-15.11 5.1-15.3 3.1 0 4.5-1.1 12.6-9.6 6.9-7.2 8.9-10 8.1-10.9-.6-.7-3.4-2.3-6.3-3.5-7.1-3.2-18.4-3.7-25.2-1.3z" /> <circle cx="50.8" cy="63.5" r="6"/>
<circle r="6" cy="126.75" cx="132.5" /> <path d="m176.7 38.5-18.6 18.3a71.6 71.6 0 0 1-42 117.8 13 13 0 0 1-24.3 0A71.6 71.6 0 0 1 40.4 71.4a13 13 0 0 1 10.4-21 12.9 12.9 0 0 1 4.9 1 71.6 71.6 0 0 1 96-1L170 31.7a97.8 97.8 0 1 0 6.8 6.8z"/>
<circle cx="101.5" cy="167" r="6" /> <path d="M116.3 165.3a62.5 62.5 0 0 0 35.2-102l-13.4 13.1a43.8 43.8 0 0 1 6.4 44.6 13 13 0 0 1-16.6 19.7 43.7 43.7 0 1 1 4.2-70.4l13.1-13.4a62.4 62.4 0 0 0-82.7.6 13 13 0 0 1 1.4 6 13.1 13.1 0 0 1-13 13 13.4 13.4 0 0 1-2.7-.2 62.5 62.5 0 0 0 43.5 89 13 13 0 0 1 24.6 0z"/>
<circle cx="48.75" cy="60.75" r="6" /> <path d="M112.2 101.9a7.9 7.9 0 0 1 .3 2.1 8.3 8.3 0 1 1-8.3-8.3 8.5 8.5 0 0 1 2.5.4l19.4-19.6a35.1 35.1 0 1 0-3.7 57.6 13 13 0 0 1 12.2-17.7 12.8 12.8 0 0 1 2.5.2 35.1 35.1 0 0 0-5-34.1z"/>
</svg> </svg>
<span class="text-gray-600 dark:text-gray-300 ml-4 text-2xl font-bold"> ESPresense </span>
<span class="text-gray-900 dark:text-gray-100 ml-2 text-3xl font-thin"> ESPresense </span>
</div> </div>
<nav class="mt-10 px-6 "> <nav class="mt-10 px-6 ">
<SidebarItem icon="device" title="Devices" href="/" /> <SidebarItem icon="device" title="Devices" href="/" />
<SidebarItem icon="contact" title="Fingerprints" href="/fingerprints" /> <SidebarItem icon="fingerprint" title="Fingerprints" href="/fingerprints" />
</nav> </nav>
</div> </div>
</div> </div>

View File

@ -1,10 +1,14 @@
<script> <script>
import { devices, events, enroll } from '../stores';
import Stats from "../components/Stats.svelte"; import Stats from "../components/Stats.svelte";
let name;
</script> </script>
<Stats /> <Stats />
{#if $events?.state != null }
<label for="name">Name</label> <label for="name">Name</label>
<input id="name" type="text" class=" bg-gray-200 relative" placeholder="Name" /> <input id="name" type="text" class=" bg-gray-200 relative" placeholder="Name" bind:value={name} />
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded disabled:opacity-50 disabled:cursor-not-allowed" disabled={$events.state.enrolling} on:click={()=>enroll(name)}>
Enroll Enroll
</button> </button>
{/if}

View File

@ -27,8 +27,9 @@ export const devices = readable([], function start(set) {
}); });
var initialValue = {}; var initialValue = {};
var socket = null;
export const events = readable(initialValue, function start(set) { export const events = readable(initialValue, function start(set) {
const socket = new WebSocket(`ws://${location.hostname}/ws`); socket = new WebSocket(`${location.origin.replace('http://','ws://')}/ws`);
socket.addEventListener('open', function (event) { socket.addEventListener('open', function (event) {
console.log("It's open"); console.log("It's open");
@ -36,6 +37,7 @@ export const events = readable(initialValue, function start(set) {
socket.addEventListener('message', function (event) { socket.addEventListener('message', function (event) {
initialValue = JSON.parse(event.data); initialValue = JSON.parse(event.data);
console.log("Receive: " + event.data);
set(initialValue); set(initialValue);
}); });
@ -44,3 +46,8 @@ export const events = readable(initialValue, function start(set) {
}; };
}); });
export function enroll(name) {
var d = JSON.stringify({ command:"enroll", payload:name });
console.log("Send: " + d);
socket.send(d);
}

View File

@ -7,7 +7,12 @@ export default defineConfig({
server: { server: {
proxy: { proxy: {
'^/json': { '^/json': {
target: 'http://192.168.128.180/', target: 'http://192.168.128.134/',
changeOrigin: true,
rewrite: (path) => path
},
'^/ws': {
target: 'ws://192.168.128.134/',
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path rewrite: (path) => path
}, },