.
diff --git a/lib/ESPDASH/README.md b/lib/ESPDASH/README.md
new file mode 100644
index 00000000..170d062c
--- /dev/null
+++ b/lib/ESPDASH/README.md
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+DASH V4 is the 4th-gen blazing fast library to create a functional & real-time dashboard for ESP8266 & ESP32 microcontrollers. This library includes charts, display cards, interactive buttons and many more components to create a perfect dashboard which is accessible locally via your IoT device's IP. DASH does not require any kind of internet connection, everything is stored locally.
+
+
+
+Features
+
+- 🔥 Automatic webpage generation.
+- ⏱️ Realtime updates to all connected clients.
+- 🎷 No need to learn HTML/CSS/JS. ESP-DASH provides you with a C++ interface.
+- 🛫 Ready to use components for your data.
+- 🏀 It's dynamic! Add or remove components anytime from the webpage.
+- 📈 Inbuilt charts support.
+
+
+
+
+
+Documentation
+Learn more about Installation & Usage: Click Here
+
+
+
+
+Open-Source Preview
+
+
+
+
+
+Want More? Upgrade to Pro
+
+ESP-DASH Pro comes with the following extended functionality:
+- 11 Exclusive Widgets ( Line, Area, Pie, Text Input, Joystick and more! )
+- Tabs Support ~ Add multiple pages to your dashboard.
+- Custom Title
+- Custom Branding
+- Custom Widget Size
+- Enable/Disable Animations
+- Atlast, It is a fantastic way to support the developer for the time went into the making & maintaining the library.
+
+
Available here:
+
+- [Official Website](https://espdash.pro)
+
+
+
+
+
+
+
+
+
+
+Contributions
+Every contribution to this repository is highly appreciated! If you spot any bug or problem, open a issue or pull request so that it can be rectified for everyone.
+
+**For feature requests:** Please open a issue and I'll add the feature in a future release once I get some time in my hands.
+
+
+
+
+
+License
+
+ESP-DASH is licensed under General Public License v3 ( GPLv3 ). If you are intending to use ESP-DASH in a commercial project, please consider buying the [ESP-DASH Pro](https://espdash.pro) which comes with a less restrictive SCL-1.0 license ( SOFTT Commercial License 1.0 ).
+
+
+
diff --git a/lib/ESPDASH/keywords.txt b/lib/ESPDASH/keywords.txt
new file mode 100644
index 00000000..1e31794f
--- /dev/null
+++ b/lib/ESPDASH/keywords.txt
@@ -0,0 +1,13 @@
+ESPDash KEYWORD1
+Card KEYWORD1
+Chart KEYWORD1
+Statistic KEYWORD1
+setAuthentication KEYWORD2
+sendUpdates KEYWORD2
+refreshLayout KEYWORD2
+add KEYWORD2
+remove KEYWORD2
+update KEYWORD2
+attachCallback KEYWORD2
+updateX KEYWORD2
+updateY KEYWORD2
\ No newline at end of file
diff --git a/lib/ESPDASH/library.json b/lib/ESPDASH/library.json
new file mode 100644
index 00000000..021652b7
--- /dev/null
+++ b/lib/ESPDASH/library.json
@@ -0,0 +1,30 @@
+{
+ "name": "ESP-DASH",
+ "keywords": "EspDash, esp8266, esp32, ui, dashboard, user, ux, interface, gui, iot, arduino, Wifi, server",
+ "description": "A blazing fast library to create realtime dashboards for ESP8266's and ESP32's.",
+ "repository":
+ {
+ "type": "git",
+ "url": "https://github.com/ayushsharma82/ESP-DASH.git"
+ },
+ "authors":
+ [
+ {
+ "name": "Ayush Sharma",
+ "email": "asrocks5@gmail.com",
+ "maintainer": true
+ }
+ ],
+ "version": "4.0.4",
+ "frameworks": "arduino",
+ "platforms": ["espressif32", "espressif8266"],
+ "dependencies":
+ [
+ {
+ "name": "ESP Async WebServer"
+ },
+ {
+ "name": "ArduinoJson"
+ }
+ ]
+}
diff --git a/lib/ESPDASH/library.properties b/lib/ESPDASH/library.properties
new file mode 100644
index 00000000..f571f9ab
--- /dev/null
+++ b/lib/ESPDASH/library.properties
@@ -0,0 +1,9 @@
+name=ESP-DASH
+version=4.0.4
+author=Ayush Sharma
+category=Communication
+maintainer=Ayush Sharma
+sentence=A blazing fast library to create realtime dashboards for ESP8266's and ESP32's.
+paragraph=ESP-DASH lets you create functional and beautiful dashboards for your ESP8266 / ESP32 without the need of an internet connection.
+url=https://github.com/ayushsharma82/ESP-DASH
+architectures=esp8266,esp32
diff --git a/lib/ESPDASH/src/Card.cpp b/lib/ESPDASH/src/Card.cpp
new file mode 100644
index 00000000..01d9003e
--- /dev/null
+++ b/lib/ESPDASH/src/Card.cpp
@@ -0,0 +1,140 @@
+#include "Card.h"
+
+/*
+ Constructor
+*/
+Card::Card(ESPDash *dashboard, const int type, const char* name, const char* symbol, const int min, const int max, const int step){
+ _dashboard = dashboard;
+ _id = dashboard->nextId();
+ _type = type;
+ _name = name;
+ _symbol = symbol;
+ _value_min = min;
+ _value_max = max;
+ _value_step = step;
+ _dashboard->add(this);
+}
+
+/*
+ Attach Function Callback
+*/
+void Card::attachCallback(std::function cb){
+ _callback = cb;
+}
+
+
+/*
+ Value update methods
+*/
+void Card::update(int value, const char* symbol){
+ /* Clear String if it was used before */
+ if(_value_type == Card::STRING){
+ _value_s = "";
+ }
+ /* Store new value */
+ _value_type = Card::INTEGER;
+ if(strcmp(_symbol.c_str(), symbol) != 0 || _value_i != value)
+ _changed = true;
+ _value_i = value;
+ _symbol = symbol;
+}
+
+void Card::update(int value){
+ /* Clear String if it was used before */
+ if(_value_type == Card::STRING){
+ _value_s = "";
+ }
+ /* Store new value */
+ _value_type = Card::INTEGER;
+ if(_value_i != value)
+ _changed = true;
+ _value_i = value;
+}
+
+void Card::update(float value, const char* symbol){
+ /* Clear String if it was used before */
+ if(_value_type == Card::STRING){
+ _value_s = "";
+ }
+ /* Store new value */
+ _value_type = Card::FLOAT;
+ if(strcmp(_symbol.c_str(), symbol) != 0 || _value_f != value)
+ _changed = true;
+ _value_f = value;
+ _symbol = symbol;
+}
+
+void Card::update(float value){
+ /* Clear String if it was used before */
+ if(_value_type == Card::STRING){
+ _value_s = "";
+ }
+ /* Store new value */
+ _value_type = Card::FLOAT;
+ if(_value_f != value)
+ _changed = true;
+ _value_f = value;
+}
+
+void Card::update(const String &value, const char* symbol){
+ update(value.c_str(), symbol);
+}
+
+void Card::update(const String &value){
+ update(value.c_str());
+}
+
+void Card::update(const char* value, const char* symbol){
+ if(_value_type == Card::STRING){
+ if(strcmp(_value_s.c_str(), value) != 0)
+ _changed = true;
+ }
+ if (strcmp(_symbol.c_str(), symbol) != 0) {
+ _changed = true;
+ }
+ _value_type = Card::STRING;
+ _symbol = symbol;
+ _value_s = value;
+}
+
+void Card::update(const char* value){
+ if(_value_type == Card::STRING){
+ if(strcmp(_value_s.c_str(), value) != 0)
+ _changed = true;
+ }
+
+ _value_type = Card::STRING;
+ _value_s = value;
+}
+
+void Card::update(bool value, const char* symbol){
+ /* Clear String if it was used before */
+ if(_value_type == Card::STRING){
+ _value_s = "";
+ }
+ /* Store new value */
+ _value_type = Card::INTEGER;
+ if(strcmp(_symbol.c_str(), symbol) != 0 || _value_i != value)
+ _changed = true;
+ _value_i = value;
+ _symbol = symbol;
+}
+
+void Card::update(bool value){
+ /* Clear String if it was used before */
+ if(_value_type == Card::STRING){
+ _value_s = "";
+ }
+ /* Store new value */
+ _value_type = Card::INTEGER;
+ if(_value_i != value)
+ _changed = true;
+ _value_i = value;
+}
+
+/*
+ Destructor
+*/
+Card::~Card(){
+ _dashboard->remove(this);
+}
diff --git a/lib/ESPDASH/src/Card.h b/lib/ESPDASH/src/Card.h
new file mode 100644
index 00000000..7c0747e5
--- /dev/null
+++ b/lib/ESPDASH/src/Card.h
@@ -0,0 +1,70 @@
+#ifndef __CARD_H
+#define __CARD_H
+
+
+#include
+#include "Arduino.h"
+
+#include "ESPDash.h"
+#include "ArduinoJson.h"
+
+struct CardNames {
+ int value;
+ const char* type;
+};
+
+// functions defaults to zero (number card)
+enum {
+ GENERIC_CARD,
+ TEMPERATURE_CARD,
+ HUMIDITY_CARD,
+ STATUS_CARD,
+ SLIDER_CARD,
+ BUTTON_CARD,
+ PROGRESS_CARD
+};
+
+// Forward Declaration
+class ESPDash;
+
+// Card Class
+class Card {
+ private:
+ ESPDash *_dashboard;
+
+ uint32_t _id;
+ const char* _name;
+ int _type;
+ bool _changed;
+ enum { INTEGER, FLOAT, STRING } _value_type;
+ union alignas(4) {
+ float _value_f;
+ int _value_i;
+ };
+ String _value_s;
+ int _value_min;
+ int _value_max;
+ int _value_step;
+ String _symbol;
+ std::function _callback = nullptr;
+
+ public:
+ Card(ESPDash *dashboard, const int type, const char* name, const char* symbol = "", const int min = 0, const int max = 0, const int step = 1);
+ void attachCallback(std::function cb);
+ void update(int value);
+ void update(int value, const char* symbol);
+ void update(bool value);
+ void update(bool value, const char* symbol);
+ void update(float value);
+ void update(float value, const char* symbol);
+ void update(const char* value);
+ void update(const char* value, const char* symbol);
+ void update(const String &value);
+ void update(const String &value, const char* symbol);
+ ~Card();
+
+ friend class ESPDash;
+};
+
+
+#endif
diff --git a/lib/ESPDASH/src/Chart.cpp b/lib/ESPDASH/src/Chart.cpp
new file mode 100644
index 00000000..4088c25d
--- /dev/null
+++ b/lib/ESPDASH/src/Chart.cpp
@@ -0,0 +1,144 @@
+#include "Chart.h"
+
+/*
+ Constructor
+*/
+Chart::Chart(ESPDash *dashboard, const int type, const char* name){
+ _dashboard = dashboard;
+ _id = dashboard->nextId();
+ _type = type;
+ _name = name;
+ _dashboard->add(this);
+}
+
+#if DASH_USE_LEGACY_CHART_STORAGE == 1
+ void Chart::emptyXAxisVectors() {
+ if(!_x_axis_i.Empty())
+ _x_axis_i.Clear();
+ if(!_x_axis_f.Empty())
+ _x_axis_f.Clear();
+ if(!_x_axis_s.Empty())
+ _x_axis_s.Clear();
+ }
+
+ void Chart::emptyYAxisVectors() {
+ if(!_y_axis_i.Empty())
+ _y_axis_i.Clear();
+ if(!_y_axis_f.Empty())
+ _y_axis_f.Clear();
+ }
+#else
+ void Chart::clearXAxisPointers() {
+ _x_axis_i_ptr = nullptr;
+ _x_axis_f_ptr = nullptr;
+ _x_axis_char_ptr = nullptr;
+ _x_axis_s_ptr = nullptr;
+ _x_axis_ptr_size = 0;
+ }
+
+ void Chart::clearYAxisPointers() {
+ _y_axis_i_ptr = nullptr;
+ _y_axis_f_ptr = nullptr;
+ _y_axis_ptr_size = 0;
+ }
+#endif
+
+/*
+ Value update methods
+*/
+void Chart::updateX(int arr_x[], size_t x_size){
+ _x_axis_type = GraphAxisType::INTEGER;
+ #if DASH_USE_LEGACY_CHART_STORAGE == 1
+ emptyXAxisVectors();
+ for(int i=0; i < x_size; i++){
+ _x_axis_i.PushBack(arr_x[i]);
+ }
+ #else
+ clearXAxisPointers();
+ _x_axis_i_ptr = arr_x;
+ _x_axis_ptr_size = x_size;
+ #endif
+ _changed = true;
+}
+
+void Chart::updateX(float arr_x[], size_t x_size){
+ _x_axis_type = GraphAxisType::FLOAT;
+ #if DASH_USE_LEGACY_CHART_STORAGE == 1
+ emptyXAxisVectors();
+ for(int i=0; i < x_size; i++){
+ _x_axis_f.PushBack(arr_x[i]);
+ }
+ #else
+ clearXAxisPointers();
+ _x_axis_f_ptr = arr_x;
+ _x_axis_ptr_size = x_size;
+ #endif
+ _changed = true;
+}
+
+void Chart::updateX(String arr_x[], size_t x_size){
+ _x_axis_type = GraphAxisType::STRING;
+ #if DASH_USE_LEGACY_CHART_STORAGE == 1
+ emptyXAxisVectors();
+ for(int i=0; i < x_size; i++){
+ _x_axis_s.PushBack(arr_x[i].c_str());
+ }
+ #else
+ clearXAxisPointers();
+ _x_axis_s_ptr = arr_x;
+ _x_axis_ptr_size = x_size;
+ #endif
+ _changed = true;
+}
+
+void Chart::updateX(const char* arr_x[], size_t x_size){
+ _x_axis_type = GraphAxisType::CHAR;
+ #if DASH_USE_LEGACY_CHART_STORAGE == 1
+ emptyXAxisVectors();
+ for(int i=0; i < x_size; i++){
+ _x_axis_s.PushBack(String(arr_x[i]));
+ }
+ #else
+ clearXAxisPointers();
+ _x_axis_char_ptr = arr_x;
+ _x_axis_ptr_size = x_size;
+ #endif
+ _changed = true;
+}
+
+void Chart::updateY(int arr_y[], size_t y_size){
+ _y_axis_type = GraphAxisType::INTEGER;
+ #if DASH_USE_LEGACY_CHART_STORAGE == 1
+ emptyYAxisVectors();
+ for(int i=0; i < y_size; i++){
+ _y_axis_i.PushBack(arr_y[i]);
+ }
+ #else
+ clearYAxisPointers();
+ _y_axis_i_ptr = arr_y;
+ _y_axis_ptr_size = y_size;
+ #endif
+ _changed = true;
+}
+
+void Chart::updateY(float arr_y[], size_t y_size){
+ _y_axis_type = GraphAxisType::FLOAT;
+ #if DASH_USE_LEGACY_CHART_STORAGE == 1
+ emptyYAxisVectors();
+ for(int i=0; i < y_size; i++){
+ _y_axis_f.PushBack(arr_y[i]);
+ }
+ #else
+ clearYAxisPointers();
+ _y_axis_f_ptr = arr_y;
+ _y_axis_ptr_size = y_size;
+ #endif
+ _changed = true;
+}
+
+/*
+ Destructor
+*/
+Chart::~Chart(){
+ _dashboard->remove(this);
+}
\ No newline at end of file
diff --git a/lib/ESPDASH/src/Chart.h b/lib/ESPDASH/src/Chart.h
new file mode 100644
index 00000000..796b1a3d
--- /dev/null
+++ b/lib/ESPDASH/src/Chart.h
@@ -0,0 +1,82 @@
+#ifndef __CHART_H
+#define __CHART_H
+
+#include
+#include "Arduino.h"
+#include "vector.h"
+
+#include "ESPDash.h"
+#include "ArduinoJson.h"
+
+#ifndef DASH_USE_LEGACY_CHART_STORAGE
+ #define DASH_USE_LEGACY_CHART_STORAGE 0
+#endif
+
+// Default to Line Chart
+enum {
+ BAR_CHART,
+};
+
+struct ChartNames {
+ int value;
+ const char* type;
+};
+
+enum GraphAxisType { INTEGER, FLOAT, CHAR, STRING };
+
+// Forward Declaration
+class ESPDash;
+
+// Chart Class
+class Chart {
+ private:
+ ESPDash *_dashboard;
+
+ uint32_t _id;
+ const char *_name;
+ int _type;
+ bool _changed;
+ GraphAxisType _x_axis_type;
+ GraphAxisType _y_axis_type;
+
+ #if DASH_USE_LEGACY_CHART_STORAGE == 1
+ /* X-Axis */
+ Vector _x_axis_i;
+ Vector _x_axis_f;
+ Vector _x_axis_s;
+ /* Y-Axis */
+ Vector _y_axis_i;
+ Vector _y_axis_f;
+
+ void emptyXAxisVectors();
+ void emptyYAxisVectors();
+ #else
+ /* X-Axis */
+ int *_x_axis_i_ptr = nullptr;
+ float *_x_axis_f_ptr = nullptr;
+ const char **_x_axis_char_ptr = nullptr;
+ String *_x_axis_s_ptr = nullptr;
+ unsigned int _x_axis_ptr_size = 0;
+ /* Y-Axis */
+ int *_y_axis_i_ptr = nullptr;
+ float *_y_axis_f_ptr = nullptr;
+ unsigned int _y_axis_ptr_size = 0;
+
+ void clearXAxisPointers();
+ void clearYAxisPointers();
+ #endif
+
+ public:
+ Chart(ESPDash *dashboard, const int type, const char* name);
+ void updateX(int arr_x[], size_t x_size);
+ void updateX(float arr_x[], size_t x_size);
+ void updateX(String arr_x[], size_t x_size);
+ void updateX(const char* arr_x[], size_t x_size);
+ void updateY(int arr_y[], size_t y_size);
+ void updateY(float arr_y[], size_t y_size);
+ ~Chart();
+
+ friend class ESPDash;
+};
+
+#endif
\ No newline at end of file
diff --git a/lib/ESPDASH/src/ESPDash.cpp b/lib/ESPDASH/src/ESPDash.cpp
new file mode 100644
index 00000000..f7b52b41
--- /dev/null
+++ b/lib/ESPDASH/src/ESPDash.cpp
@@ -0,0 +1,515 @@
+#include "ESPDash.h"
+
+// Integral type to string pairs events
+// ID, type
+struct CardNames cardTags[] = {
+ {GENERIC_CARD, "generic"},
+ {TEMPERATURE_CARD, "temperature"},
+ {HUMIDITY_CARD, "humidity"},
+ {STATUS_CARD, "status"},
+ {SLIDER_CARD, "slider"},
+ {BUTTON_CARD, "button"},
+ {PROGRESS_CARD, "progress"},
+};
+
+// Integral type to string pairs events
+// ID, type
+struct ChartNames chartTags[] = {
+ {BAR_CHART, "bar"},
+};
+
+
+/*
+ Constructors
+*/
+ESPDash::ESPDash(AsyncWebServer* server) : ESPDash(server, "/", true) {}
+
+ESPDash::ESPDash(AsyncWebServer* server, bool enable_default_stats) : ESPDash(server, "/", enable_default_stats) {}
+
+ESPDash::ESPDash(AsyncWebServer* server, const char* uri, bool enable_default_stats) {
+ _server = server;
+ default_stats_enabled = enable_default_stats;
+
+ // Initialize AsyncWebSocket
+ _ws = new AsyncWebSocket("/dashws");
+
+ // Attach AsyncWebServer Routes
+ _server->on(uri, HTTP_GET, [this](AsyncWebServerRequest *request){
+ if(basic_auth){
+ if(!request->authenticate(username, password))
+ return request->requestAuthentication();
+ }
+ // respond with the compressed frontend
+ AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", DASH_HTML, sizeof(DASH_HTML));
+ response->addHeader("Content-Encoding", "gzip");
+ response->addHeader("Cache-Control", "public, max-age=900");
+ request->send(response);
+ });
+
+ // Websocket Callback Handler
+ _ws->onEvent([&](AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len){
+ // Request Buffer
+#if ARDUINOJSON_VERSION_MAJOR == 7
+ JsonDocument json;
+#else
+ StaticJsonDocument<200> json;
+#endif
+
+ if (type == WS_EVT_DATA) {
+ AwsFrameInfo * info = (AwsFrameInfo * ) arg;
+ if (info -> final && info -> index == 0 && info -> len == len) {
+ if (info -> opcode == WS_TEXT) {
+ data[len] = 0;
+ deserializeJson(json, reinterpret_cast(data));
+ // client side commands parsing
+ if (json["command"] == "get:layout") {
+ _asyncAccessInProgress = true;
+ generateLayoutJSON(client, false);
+ _asyncAccessInProgress = false;
+ } else if (json["command"] == "ping") {
+ return _ws->text(client->id(), "{\"command\":\"pong\"}");
+ } else if (json["command"] == "button:clicked") {
+ // execute and reference card data struct to funtion
+ uint32_t id = json["id"].as();
+ for(int i=0; i < cards.Size(); i++){
+ Card *p = cards[i];
+ if(id == p->_id){
+ if(p->_callback != nullptr){
+ _asyncAccessInProgress = true;
+ p->_callback(json["value"].as());
+ _asyncAccessInProgress = false;
+ }
+ }
+ }
+ } else if (json["command"] == "slider:changed") {
+ // execute and reference card data struct to funtion
+ uint32_t id = json["id"].as();
+ for(int i=0; i < cards.Size(); i++){
+ Card *p = cards[i];
+ if(id == p->_id){
+ if(p->_callback != nullptr){
+ _asyncAccessInProgress = true;
+ p->_callback(json["value"].as());
+ _asyncAccessInProgress = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ });
+
+ // Attach Websocket Instance to AsyncWebServer
+ _server->addHandler(_ws);
+}
+
+void ESPDash::setAuthentication(const char *user, const char *pass) {
+ basic_auth = strlen(user) > 0 && strlen(pass) > 0;
+ if(basic_auth) {
+ strncpy(username, user, sizeof(username));
+ strncpy(password, pass, sizeof(password));
+ _ws->setAuthentication(user, pass);
+ }
+}
+
+void ESPDash::setAuthentication(const String &user, const String &pass) {
+ setAuthentication(user.c_str(), pass.c_str());
+}
+
+// Add Card
+void ESPDash::add(Card *card) {
+ cards.PushBack(card);
+}
+
+// Remove Card
+void ESPDash::remove(Card *card) {
+ for(int i=0; i < cards.Size(); i++){
+ Card *p = cards[i];
+ if(p->_id == card->_id){
+ cards.Erase(i);
+ return;
+ }
+ }
+}
+
+
+// Add Chart
+void ESPDash::add(Chart *chart) {
+ charts.PushBack(chart);
+}
+
+// Remove Card
+void ESPDash::remove(Chart *chart) {
+ for(int i=0; i < charts.Size(); i++){
+ Chart *p = charts[i];
+ if(p->_id == chart->_id){
+ charts.Erase(i);
+ return;
+ }
+ }
+}
+
+// Add Statistic
+void ESPDash::add(Statistic *statistic) {
+ statistics.PushBack(statistic);
+}
+
+// Remove Statistic
+void ESPDash::remove(Statistic *statistic) {
+ for(int i=0; i < statistics.Size(); i++){
+ Statistic *p = statistics[i];
+ if(p->_id == statistic->_id){
+ statistics.Erase(i);
+ return;
+ }
+ }
+}
+
+// generates the layout JSON string to the frontend
+void ESPDash::generateLayoutJSON(AsyncWebSocketClient* client, bool changes_only, Card* onlyCard) {
+#if ARDUINOJSON_VERSION_MAJOR == 6
+ DynamicJsonDocument doc(DASH_JSON_DOCUMENT_ALLOCATION);
+#else
+ JsonDocument doc;
+#endif
+
+ // preparing layout
+ if (!changes_only) {
+ doc["command"] = "update:layout:begin";
+ } else {
+ doc["command"] = "update:components";
+ }
+ if (!changes_only) {
+ send(client, doc);
+ }
+
+ // Generate JSON for all Cards
+ doc["command"] = changes_only ? "update:components" : "update:layout:next";
+ for (int i = 0; i < cards.Size(); i++) {
+ Card* c = cards[i];
+ if (changes_only) {
+ if (!c->_changed && (onlyCard == nullptr || onlyCard->_id != c->_id)) {
+ continue;
+ }
+ }
+
+ // Generate JSON
+#if ARDUINOJSON_VERSION_MAJOR == 6
+ JsonObject obj = doc["cards"].createNestedObject();
+#else
+ JsonObject obj = doc["cards"].add();
+#endif
+ generateComponentJSON(obj, c, changes_only);
+
+ if (overflowed(doc)) {
+ doc["cards"].as().remove(doc["cards"].as().size() - 1);
+ send(client, doc);
+ doc["command"] = changes_only ? "update:components" : "update:layout:next";
+ i--;
+ continue;
+ }
+
+ // Clear change flags
+ if (changes_only) {
+ c->_changed = false;
+ }
+ }
+
+ if (doc["cards"].as().size() > 0)
+ send(client, doc);
+
+ // Generate JSON for all Charts
+ doc["command"] = changes_only ? "update:components" : "update:layout:next";
+ for (int i = 0; i < charts.Size(); i++) {
+ Chart* c = charts[i];
+ if (changes_only) {
+ if (!c->_changed) {
+ continue;
+ }
+ }
+
+ // Generate JSON
+#if ARDUINOJSON_VERSION_MAJOR == 7
+ JsonObject obj = doc["charts"].add();
+#else
+ JsonObject obj = doc["charts"].createNestedObject();
+#endif
+ generateComponentJSON(obj, c, changes_only);
+
+ if (overflowed(doc)) {
+ doc["charts"].as().remove(doc["charts"].as().size() - 1);
+ send(client, doc);
+ doc["command"] = changes_only ? "update:components" : "update:layout:next";
+ i--;
+ continue;
+ }
+
+ // Clear change flags
+ if (changes_only) {
+ c->_changed = false;
+ }
+ }
+
+ if (doc["charts"].as().size() > 0)
+ send(client, doc);
+
+ // Generate JSON for all Statistics
+ doc["command"] = changes_only ? "update:components" : "update:layout:next";
+ int idx = 0;
+
+ // Check if default statistics are needed
+ if (default_stats_enabled) {
+ if (!changes_only) {
+ // Hardware
+ doc["stats"][idx]["i"] = -1;
+ doc["stats"][idx]["k"] = "Hardware";
+ doc["stats"][idx]["v"] = DASH_HARDWARE;
+ idx++;
+
+ // SDK Version
+ doc["stats"][idx]["i"] = -2;
+ doc["stats"][idx]["k"] = "SDK Version";
+#if defined(ESP8266)
+ doc["stats"][idx]["v"] = ESP.getCoreVersion();
+#elif defined(ESP32)
+ doc["stats"][idx]["v"] = String(esp_get_idf_version());
+#endif
+ idx++;
+
+ // MAC Address
+ doc["stats"][idx]["i"] = -3;
+ doc["stats"][idx]["k"] = "MAC Address";
+ doc["stats"][idx]["v"] = WiFi.macAddress();
+ idx++;
+ }
+
+ // Free Heap
+ doc["stats"][idx]["i"] = -4;
+ doc["stats"][idx]["k"] = "Free Heap (SRAM)";
+ doc["stats"][idx]["v"] = ESP.getFreeHeap();
+ idx++;
+
+ // WiFi Mode
+ doc["stats"][idx]["i"] = -5;
+ doc["stats"][idx]["k"] = "WiFi Mode";
+ doc["stats"][idx]["v"] = WiFi.getMode();
+ idx++;
+
+ // WiFi Signal
+ doc["stats"][idx]["i"] = -6;
+ doc["stats"][idx]["k"] = "WiFi Signal";
+ doc["stats"][idx]["v"] = WiFi.RSSI();
+ idx++;
+ }
+
+ // Loop through user defined stats
+ for (int i = 0; i < statistics.Size(); i++) {
+ Statistic* s = statistics[i];
+ if (changes_only) {
+ if (!s->_changed) {
+ continue;
+ }
+ }
+
+ doc["stats"][idx]["i"] = s->_id;
+ doc["stats"][idx]["k"] = s->_key;
+ if (changes_only || strlen(s->_value) > 0)
+ doc["stats"][idx]["v"] = s->_value;
+ doc["stats"][idx]["v"] = s->_value;
+ idx++;
+
+ if (overflowed(doc)) {
+ doc["stats"].as().remove(idx - 1);
+ send(client, doc);
+ doc["command"] = changes_only ? "update:components" : "update:layout:next";
+ i--;
+ idx = 0;
+ continue;
+ }
+
+ // Clear change flags
+ if (changes_only) {
+ s->_changed = false;
+ }
+ }
+
+ if (idx > 0)
+ send(client, doc);
+}
+
+void ESPDash::send(AsyncWebSocketClient* client, JsonDocument& doc) {
+ const size_t len = measureJson(doc);
+ AsyncWebSocketMessageBuffer* buffer = _ws->makeBuffer(len);
+ assert(buffer);
+ serializeJson(doc, buffer->get(), len);
+ if (client != nullptr) {
+ client->text(buffer);
+ } else {
+ _ws->textAll(buffer);
+ }
+ doc.clear();
+}
+
+bool ESPDash::overflowed(JsonDocument& doc) {
+ return doc.overflowed() || measureJson(doc.as()) > DASH_JSON_SIZE;
+}
+
+/*
+ Generate Card JSON
+*/
+void ESPDash::generateComponentJSON(JsonObject& doc, Card* card, bool change_only){
+ doc["id"] = card->_id;
+ if (!change_only){
+ doc["n"] = card->_name;
+ doc["t"] = cardTags[card->_type].type;
+ doc["min"] = card->_value_min;
+ doc["max"] = card->_value_max;
+ if (card->_value_step != 1)
+ doc["step"] = card->_value_step;
+ }
+ if(change_only || !card->_symbol.isEmpty())
+ doc["s"] = card->_symbol;
+
+ switch (card->_value_type) {
+ case Card::INTEGER:
+ doc["v"] = card->_value_i;
+ break;
+ case Card::FLOAT:
+ doc["v"] = String(card->_value_f, 2);
+ break;
+ case Card::STRING:
+ if(change_only || !card->_value_s.isEmpty()) {
+ doc["v"] = card->_value_s;
+ }
+ break;
+ default:
+ // blank value
+ break;
+ }
+}
+
+
+/*
+ Generate Chart JSON
+*/
+void ESPDash::generateComponentJSON(JsonObject& doc, Chart* chart, bool change_only){
+ doc["id"] = chart->_id;
+ if(!change_only){
+ doc["n"] = chart->_name;
+ doc["t"] = chartTags[chart->_type].type;
+ }
+
+ JsonArray xAxis = doc["x"].to();
+ switch (chart->_x_axis_type) {
+ case GraphAxisType::INTEGER:
+ #if DASH_USE_LEGACY_CHART_STORAGE == 1
+ for(int i=0; i < chart->_x_axis_i.Size(); i++)
+ xAxis.add(chart->_x_axis_i[i]);
+ #else
+ if (chart->_x_axis_i_ptr != nullptr) {
+ for(unsigned int i=0; i < chart->_x_axis_ptr_size; i++)
+ xAxis.add(chart->_x_axis_i_ptr[i]);
+ }
+ #endif
+ break;
+ case GraphAxisType::FLOAT:
+ #if DASH_USE_LEGACY_CHART_STORAGE == 1
+ for(int i=0; i < chart->_x_axis_f.Size(); i++)
+ xAxis.add(chart->_x_axis_f[i]);
+ #else
+ if (chart->_x_axis_f_ptr != nullptr) {
+ for(unsigned int i=0; i < chart->_x_axis_ptr_size; i++)
+ xAxis.add(chart->_x_axis_f_ptr[i]);
+ }
+ #endif
+ break;
+ case GraphAxisType::CHAR:
+ #if DASH_USE_LEGACY_CHART_STORAGE == 1
+ for(int i=0; i < chart->_x_axis_s.Size(); i++)
+ xAxis.add(chart->_x_axis_s[i].c_str());
+ #else
+ if (chart->_x_axis_char_ptr != nullptr) {
+ for(unsigned int i=0; i < chart->_x_axis_ptr_size; i++)
+ xAxis.add(chart->_x_axis_char_ptr[i]);
+ }
+ #endif
+ break;
+ case GraphAxisType::STRING:
+ #if DASH_USE_LEGACY_CHART_STORAGE == 1
+ for(int i=0; i < chart->_x_axis_s.Size(); i++)
+ xAxis.add(chart->_x_axis_s[i].c_str());
+ #else
+ if (chart->_x_axis_s_ptr != nullptr) {
+ for(unsigned int i=0; i < chart->_x_axis_ptr_size; i++)
+ xAxis.add(chart->_x_axis_s_ptr[i]);
+ }
+ #endif
+ break;
+ default:
+ // blank value
+ break;
+ }
+
+ JsonArray yAxis = doc["y"].to();
+ switch (chart->_y_axis_type) {
+ case GraphAxisType::INTEGER:
+ #if DASH_USE_LEGACY_CHART_STORAGE == 1
+ for(int i=0; i < chart->_y_axis_i.Size(); i++)
+ yAxis.add(chart->_y_axis_i[i]);
+ #else
+ if (chart->_y_axis_i_ptr != nullptr) {
+ for(unsigned int i=0; i < chart->_y_axis_ptr_size; i++)
+ yAxis.add(chart->_y_axis_i_ptr[i]);
+ }
+ #endif
+ break;
+ case GraphAxisType::FLOAT:
+ #if DASH_USE_LEGACY_CHART_STORAGE == 1
+ for(int i=0; i < chart->_y_axis_f.Size(); i++)
+ yAxis.add(chart->_y_axis_f[i]);
+ #else
+ if (chart->_y_axis_f_ptr != nullptr) {
+ for(unsigned int i=0; i < chart->_y_axis_ptr_size; i++)
+ yAxis.add(chart->_y_axis_f_ptr[i]);
+ }
+ #endif
+ break;
+ default:
+ // blank value
+ break;
+ }
+}
+
+/* Send Card Updates to all clients */
+void ESPDash::sendUpdates(bool force) {
+ _ws->cleanupClients(DASH_MAX_WS_CLIENTS);
+ if (!hasClient()) {
+ return;
+ }
+ generateLayoutJSON(nullptr, !force);
+}
+
+void ESPDash::refreshCard(Card *card) {
+ _ws->cleanupClients(DASH_MAX_WS_CLIENTS);
+ if (!hasClient()) {
+ return;
+ }
+ generateLayoutJSON(nullptr, true, card);
+}
+
+uint32_t ESPDash::nextId() {
+ return _idCounter++;
+}
+
+bool ESPDash::hasClient() {
+ return _ws->count() > 0;
+}
+
+/*
+ Destructor
+*/
+ESPDash::~ESPDash(){
+ _server->removeHandler(_ws);
+ delete _ws;
+}
diff --git a/lib/ESPDASH/src/ESPDash.h b/lib/ESPDASH/src/ESPDash.h
new file mode 100644
index 00000000..ab54d14f
--- /dev/null
+++ b/lib/ESPDASH/src/ESPDash.h
@@ -0,0 +1,135 @@
+/*
+____ ____ ___ ___ ____ ____ _ _
+|___ [__ |__] | \ |__| [__ |__|
+|___ ___] | |__/ | | ___] | |
+
+ESP-DASH V3
+---------------------
+Author: Ayush Sharma
+First Commit: Nov 5, 2017
+Github URL: https://github.com/ayushsharma82/ESP-DASH
+
+*/
+
+#ifndef ESPDash_h
+#define ESPDash_h
+
+#include
+#include
+#include
+#include
+
+#include "Arduino.h"
+#include "stdlib_noniso.h"
+#include "dash_webpage.h"
+#include "vector.h"
+
+#if defined(ESP8266)
+ #define DASH_HARDWARE "ESP8266"
+ #include "ESP8266WiFi.h"
+ #include "ESPAsyncTCP.h"
+#elif defined(ESP32)
+ #define DASH_HARDWARE "ESP32"
+ #include "WiFi.h"
+ #include "AsyncTCP.h"
+#endif
+
+#define DASH_STATUS_IDLE "i"
+#define DASH_STATUS_SUCCESS "s"
+#define DASH_STATUS_WARNING "w"
+#define DASH_STATUS_DANGER "d"
+
+#include "ESPAsyncWebServer.h"
+#include "ArduinoJson.h"
+#include "Card.h"
+#include "Chart.h"
+#include "Statistic.h"
+
+#ifndef DASH_JSON_SIZE
+#define DASH_JSON_SIZE 2048
+#endif
+
+#if ARDUINOJSON_VERSION_MAJOR == 6 && !defined(DASH_JSON_DOCUMENT_ALLOCATION)
+#define DASH_JSON_DOCUMENT_ALLOCATION DASH_JSON_SIZE * 3
+#endif
+
+#ifndef DASH_USE_LEGACY_CHART_STORAGE
+ #define DASH_USE_LEGACY_CHART_STORAGE 0
+#endif
+
+#ifndef DASH_MAX_WS_CLIENTS
+ #define DASH_MAX_WS_CLIENTS DEFAULT_MAX_WS_CLIENTS
+#endif
+
+// Forward Declaration
+class Card;
+class Chart;
+class Statistic;
+
+// ESPDASH Class
+class ESPDash{
+ private:
+ AsyncWebServer* _server = nullptr;
+ AsyncWebSocket* _ws = nullptr;
+
+ Vector cards;
+ Vector charts;
+ Vector statistics;
+ bool default_stats_enabled = false;
+ bool basic_auth = false;
+ char username[64];
+ char password[64];
+ uint32_t _idCounter = 0;
+
+ volatile bool _asyncAccessInProgress = false;
+
+ // Generate layout json
+ void generateLayoutJSON(AsyncWebSocketClient* client, bool changes_only = false, Card* onlyCard = nullptr);
+ void send(AsyncWebSocketClient* client, JsonDocument& doc);
+ bool overflowed(JsonDocument& doc);
+
+ // Generate Component JSON
+ void generateComponentJSON(JsonObject& obj, Card* card, bool change_only = false);
+ void generateComponentJSON(JsonObject& obj, Chart* chart, bool change_only = false);
+
+ public:
+ ESPDash(AsyncWebServer* server, const char* uri, bool enable_default_stats = true);
+ ESPDash(AsyncWebServer* server, bool enable_default_stats);
+ ESPDash(AsyncWebServer* server);
+
+ // Set Authentication
+ void setAuthentication(const char* user, const char* pass);
+ void setAuthentication(const String &user, const String &pass);
+
+ // Add Card
+ void add(Card *card);
+ // Remove Card
+ void remove(Card *card);
+
+ // Add Chart
+ void add(Chart *card);
+ // Remove Chart
+ void remove(Chart *card);
+
+ // Add Statistic
+ void add(Statistic *statistic);
+ // Remove Statistic
+ void remove(Statistic *statistic);
+
+ // Notify client side to update values
+ void sendUpdates(bool force = false);
+ void refreshLayout() { sendUpdates(true); }
+ void refreshCard(Card *card);
+
+ uint32_t nextId();
+
+ bool hasClient();
+
+ // can be used to check if the async_http task might currently access the cards data,
+ // in which case you should not modify them
+ bool isAsyncAccessInProgress() { return _asyncAccessInProgress; }
+
+ ~ESPDash();
+};
+
+#endif
diff --git a/lib/ESPDASH/src/Statistic.cpp b/lib/ESPDASH/src/Statistic.cpp
new file mode 100644
index 00000000..b32bddc2
--- /dev/null
+++ b/lib/ESPDASH/src/Statistic.cpp
@@ -0,0 +1,22 @@
+#include "Statistic.h"
+
+Statistic::Statistic(ESPDash *dashboard, const char *key, const char *value) {
+ _dashboard = dashboard;
+ _id = dashboard->nextId();
+ // Safe copy
+ _key = key;
+ strncpy(_value, value, sizeof(_value));
+ _dashboard->add(this);
+}
+
+void Statistic::set(const char *value) {
+ // Safe copy
+ _changed = strcmp(_value, value) != 0;
+ if(_changed)
+ strncpy(_value, value, sizeof(_value));
+
+}
+
+Statistic::~Statistic() {
+ _dashboard->remove(this);
+}
\ No newline at end of file
diff --git a/lib/ESPDASH/src/Statistic.h b/lib/ESPDASH/src/Statistic.h
new file mode 100644
index 00000000..bf796dc4
--- /dev/null
+++ b/lib/ESPDASH/src/Statistic.h
@@ -0,0 +1,30 @@
+#ifndef __STAT_H
+#define __STAT_H
+
+#include
+#include "Arduino.h"
+#include "vector.h"
+
+#include "ESPDash.h"
+#include "ArduinoJson.h"
+
+// Forward Declaration
+class ESPDash;
+
+class Statistic {
+ private:
+ ESPDash *_dashboard;
+ uint32_t _id;
+ const char *_key;
+ char _value[64];
+ bool _changed = false;
+
+ public:
+ Statistic(ESPDash *dashboard, const char *key, const char *value = "");
+ void set(const char *value);
+ ~Statistic();
+
+ friend class ESPDash;
+};
+
+#endif
\ No newline at end of file
diff --git a/lib/ESPDASH/src/dash_webpage.cpp b/lib/ESPDASH/src/dash_webpage.cpp
new file mode 100644
index 00000000..0096c7e9
--- /dev/null
+++ b/lib/ESPDASH/src/dash_webpage.cpp
@@ -0,0 +1,3008 @@
+#include "dash_webpage.h"
+
+const uint8_t DASH_HTML[90101] PROGMEM = {
+31,139,8,0,0,0,0,0,2,3,204,57,105,115,219,184,146,223,231,87,200,92,175,30,81,129,104,121,102,178,
+7,101,196,149,115,238,73,42,154,119,69,165,242,163,200,150,132,49,5,112,0,208,182,34,235,191,111,55,120,128,
+118,146,122,95,246,154,67,106,162,27,125,95,148,47,78,94,189,125,249,219,223,223,189,30,109,221,174,124,246,213,
+5,125,141,202,76,109,68,4,42,122,246,213,104,116,177,133,172,32,0,193,29,184,108,148,111,51,99,193,137,232,
+207,191,189,153,252,71,52,58,107,145,165,84,215,35,3,165,136,100,174,85,52,218,26,88,139,232,108,157,221,208,
+115,130,31,72,59,100,164,178,29,136,232,70,194,109,165,141,139,70,72,229,64,33,227,91,89,184,173,40,0,47,
+194,196,63,240,145,84,210,201,172,156,216,60,43,65,156,39,211,192,204,73,87,194,179,191,103,115,93,190,31,189,
+157,207,47,206,252,73,139,181,185,145,149,27,185,125,133,194,118,186,168,75,64,187,206,206,50,139,70,216,51,169,
+10,184,75,190,253,143,167,249,122,149,159,39,191,219,175,110,50,51,42,140,120,187,250,29,114,151,20,176,150,10,
+222,25,93,129,113,123,94,127,30,33,193,206,232,222,166,71,111,192,189,189,85,221,189,87,208,168,161,77,67,247,
+90,125,158,110,190,223,173,116,217,208,84,61,175,202,104,167,201,128,100,155,217,1,53,223,125,134,164,106,145,63,
+216,215,170,222,129,201,86,37,120,126,239,149,136,37,119,28,152,120,230,208,159,35,121,89,24,127,114,128,158,50,
+61,153,114,140,195,90,110,234,254,249,214,72,215,193,55,89,89,67,10,71,150,202,133,91,10,224,175,165,231,138,
+60,15,107,109,98,18,4,196,220,221,223,199,78,28,142,140,85,38,193,152,149,49,73,30,143,223,43,36,7,238,
+22,176,100,51,185,142,95,43,22,238,233,53,122,38,118,140,237,190,124,199,128,171,13,42,127,228,239,123,209,53,
+217,177,49,116,115,134,218,91,55,90,25,177,174,85,238,164,86,49,59,52,103,78,20,58,71,67,149,75,114,3,
+153,131,215,37,208,83,28,81,234,70,44,49,80,254,44,173,35,181,220,120,236,18,91,87,148,153,118,8,199,109,
+14,85,72,172,179,34,98,172,81,104,70,86,52,114,44,217,209,139,250,163,6,179,159,67,137,81,210,230,57,218,
+244,39,146,182,160,66,121,196,106,249,39,198,84,108,217,76,193,237,232,151,218,101,164,253,219,149,5,115,3,38,
+182,232,225,32,67,147,12,203,80,83,157,248,212,22,34,202,183,178,44,200,128,136,5,66,67,132,58,201,138,2,
+138,95,117,1,150,153,196,101,155,95,179,157,191,243,243,15,191,254,20,141,199,134,108,23,226,145,70,136,80,177,
+97,71,150,232,70,139,184,179,138,31,122,97,148,21,182,94,57,3,128,224,145,205,58,191,143,32,182,157,235,53,
+102,66,23,57,155,72,229,96,99,164,219,143,199,177,14,79,98,128,97,220,162,74,107,48,6,76,165,75,153,123,
+218,254,232,157,63,18,143,105,232,86,110,180,181,218,200,141,84,100,80,109,97,130,209,46,64,81,251,176,209,165,
+78,6,143,34,146,42,47,235,2,162,244,147,155,153,210,106,191,211,245,167,119,244,78,186,40,125,116,104,209,163,
+147,230,118,196,245,177,247,130,34,47,96,156,108,2,85,151,43,4,139,147,233,172,115,14,80,212,215,224,242,45,
+146,81,223,228,154,29,143,179,149,137,7,238,172,29,102,114,224,251,55,231,147,63,228,68,91,119,76,98,153,8,
+135,31,161,84,2,15,29,75,118,232,206,99,22,48,47,84,220,35,124,79,233,138,36,86,117,89,14,8,29,16,
+11,153,160,220,215,25,42,92,235,1,242,202,12,248,83,94,98,242,73,244,101,71,16,5,210,143,94,255,160,204,
+137,144,151,78,8,151,34,36,176,123,200,241,120,192,64,123,149,162,251,251,207,50,45,193,141,62,66,112,213,86,
+13,121,35,10,155,209,71,248,98,249,103,88,197,252,35,120,207,11,199,145,183,104,159,130,186,119,193,178,222,65,
+215,176,183,120,154,148,160,54,110,139,183,166,129,126,223,180,86,224,202,71,95,118,149,96,197,70,247,152,62,66,
+139,233,18,83,224,24,174,15,136,14,61,209,249,18,11,242,18,3,15,73,238,238,18,139,41,15,49,227,132,136,
+125,219,100,169,199,4,54,55,143,180,88,124,77,44,130,46,116,128,87,129,249,94,236,146,66,26,183,71,67,110,
+180,44,70,83,214,85,44,33,91,199,219,16,140,80,220,139,37,55,226,151,204,109,147,93,118,215,177,105,221,194,
+109,11,48,223,34,41,84,153,152,206,178,11,51,203,158,136,115,166,23,217,82,180,87,16,188,183,248,209,249,69,
+31,91,160,197,223,219,71,7,193,210,219,222,82,110,185,38,107,67,247,49,228,243,6,167,209,208,164,138,13,127,
+224,237,107,188,220,56,136,220,215,234,251,236,155,175,195,228,64,11,65,12,177,103,223,124,221,219,163,208,30,117,
+1,51,245,228,9,115,11,181,20,147,243,206,2,215,42,60,57,15,210,64,134,116,112,212,24,31,149,176,100,128,
+249,128,85,16,157,98,7,142,29,213,179,28,206,62,23,120,253,210,36,186,76,178,170,2,85,188,164,174,28,59,
+22,8,222,54,110,33,18,169,44,24,247,2,80,28,144,59,238,239,31,149,246,187,166,178,171,204,128,114,52,44,
+18,3,59,125,3,13,87,57,160,252,121,80,12,95,168,170,33,249,203,127,74,254,235,60,142,182,206,85,233,217,
+217,237,237,109,114,251,77,162,205,230,236,235,233,116,122,102,111,54,17,31,114,251,240,101,110,191,193,157,87,252,
+129,244,191,199,45,57,93,141,70,209,0,181,146,15,112,67,148,134,79,43,144,198,232,235,27,20,71,131,15,20,
+152,184,33,224,49,46,33,178,245,214,231,8,6,133,221,197,3,132,32,247,95,118,215,158,59,103,228,170,118,128,
+225,75,37,237,133,195,19,204,6,24,143,101,98,31,28,115,24,112,254,161,109,122,109,38,253,211,69,20,147,253,
+234,202,239,141,87,87,108,144,131,170,25,35,148,200,95,84,81,177,212,207,72,235,246,37,68,72,224,129,36,183,
+150,34,32,232,110,67,112,117,229,55,70,34,241,128,144,136,106,240,128,31,227,49,125,146,85,151,1,65,46,82,
+156,64,54,72,244,97,255,149,196,58,186,36,229,210,39,50,16,61,15,68,244,96,178,125,178,54,122,71,101,141,
+41,220,238,63,129,188,104,71,144,67,102,79,28,151,201,237,86,151,62,135,104,4,141,199,120,175,200,92,38,134,
+245,244,166,245,114,103,143,107,125,20,69,169,11,84,243,118,177,94,213,171,85,9,54,5,113,114,206,243,76,229,
+80,250,77,90,225,243,17,75,63,116,226,199,101,113,227,39,211,203,218,58,189,243,15,17,27,46,80,210,13,80,
+40,11,200,99,140,91,63,10,231,131,81,184,247,227,122,142,142,31,76,105,25,251,110,119,50,7,230,182,70,223,
+142,104,227,124,109,12,230,64,244,166,163,162,5,28,138,145,174,157,149,5,140,114,189,171,180,66,105,221,171,152,
+252,152,17,93,208,107,14,65,196,90,145,88,18,148,156,158,38,90,93,225,34,133,198,85,181,221,62,236,12,102,
+72,151,173,29,152,171,186,66,175,195,167,180,239,204,35,158,24,77,103,244,254,83,202,34,44,253,82,208,133,86,
+69,95,141,135,207,197,65,60,11,51,145,184,147,241,171,44,191,182,11,183,156,13,103,137,22,115,243,41,155,99,
+8,78,55,150,251,5,201,32,239,246,117,70,210,94,199,248,137,166,183,199,172,46,221,59,3,20,64,40,218,49,
+129,11,244,177,145,83,1,205,156,159,36,125,126,240,240,71,69,159,175,140,192,90,222,73,75,205,217,234,242,6,
+208,58,10,250,223,36,218,50,11,125,223,160,11,254,38,113,241,33,196,20,239,37,110,11,42,174,52,27,56,234,
+71,63,138,62,4,103,55,194,95,72,65,25,49,7,231,89,127,15,98,26,56,87,122,224,92,76,181,66,251,29,
+116,246,61,92,84,208,78,199,89,152,111,21,44,190,135,37,98,159,60,225,123,106,101,252,103,116,32,250,152,29,
+233,218,190,93,48,121,127,87,76,185,23,248,147,236,153,33,88,233,42,102,113,216,33,28,82,184,139,15,189,64,
+135,187,68,232,125,31,128,226,246,66,210,11,115,12,12,189,128,48,54,111,132,57,196,232,129,15,65,218,241,22,
+123,3,196,189,252,70,198,236,163,234,197,35,216,137,247,94,230,200,44,47,33,67,23,163,73,15,7,99,216,36,
+214,38,219,80,69,159,52,29,130,90,70,147,217,120,203,1,18,172,252,36,110,211,157,205,58,135,201,102,181,153,
+181,223,98,49,57,95,242,192,110,60,14,112,82,53,27,11,149,190,124,88,61,93,246,253,40,89,151,82,167,240,
+32,170,223,185,16,83,73,29,225,59,39,14,38,157,242,60,197,60,171,210,239,220,96,67,82,13,65,98,112,3,
+135,24,129,156,113,164,71,160,10,68,210,181,189,145,116,196,143,248,20,48,209,75,32,107,73,65,25,187,97,242,
+101,238,225,114,74,183,52,129,116,143,2,39,251,151,107,60,160,232,33,23,18,221,100,107,76,69,251,64,130,66,
+145,64,92,138,248,28,159,40,206,36,86,163,216,129,41,191,153,86,203,134,204,245,12,104,159,31,168,247,125,219,
+233,189,154,231,248,175,23,248,152,124,112,225,15,57,92,65,185,225,25,47,121,206,183,124,205,14,228,240,66,116,
+25,205,107,161,59,176,18,69,27,250,93,183,11,206,170,201,100,198,118,11,185,168,150,36,101,41,170,150,100,69,
+45,224,202,135,241,151,172,226,119,29,228,175,85,162,166,155,125,237,237,197,58,38,69,42,198,159,11,136,247,77,
+159,152,11,67,59,65,252,156,205,230,151,232,177,57,38,209,30,237,76,227,185,200,227,231,124,207,248,60,201,209,
+119,252,42,177,68,199,87,168,134,152,35,19,90,12,118,227,241,93,123,238,23,254,108,101,227,106,178,91,60,95,
+178,174,123,92,119,105,198,111,59,40,100,218,13,234,113,144,14,69,162,239,247,201,46,206,248,150,113,227,89,238,
+201,88,82,96,43,112,112,75,99,29,175,39,147,163,119,73,49,30,215,3,203,86,139,154,202,226,185,144,139,130,
+128,185,104,46,191,18,207,233,123,70,47,49,207,47,227,192,168,152,76,136,25,75,175,124,106,189,98,151,39,198,
+67,115,236,14,215,45,116,73,218,165,183,29,5,222,73,239,200,89,136,122,230,1,58,141,111,125,46,162,67,136,
+26,253,118,77,207,136,33,25,248,88,162,107,76,243,208,170,62,140,9,41,188,156,53,74,120,149,81,124,137,222,
+48,45,49,26,121,19,123,235,194,190,191,10,57,182,211,15,151,188,195,145,43,250,176,226,112,122,106,115,93,65,
+122,126,244,113,214,125,182,53,57,165,7,90,24,212,66,47,121,38,28,126,209,120,203,134,191,35,148,20,103,195,
+252,87,134,173,83,45,202,37,54,215,217,35,138,140,89,68,32,30,8,159,225,7,183,45,37,113,23,217,17,74,
+11,163,79,248,54,68,199,112,110,232,92,49,255,5,158,159,89,182,111,160,189,11,32,184,224,245,112,201,251,244,
+39,2,172,255,147,110,111,77,15,199,65,61,187,88,182,189,9,211,123,192,111,208,134,188,66,135,174,189,166,150,
+119,155,75,170,121,88,56,82,195,135,189,54,205,142,126,105,152,217,241,216,38,59,191,150,115,117,127,143,195,53,
+14,139,69,137,37,191,203,42,250,189,4,83,178,196,235,241,149,65,251,46,77,211,206,146,36,41,89,234,32,46,
+25,151,195,165,9,75,30,219,88,54,236,232,65,249,247,238,97,62,120,61,224,241,236,161,183,72,136,97,176,51,
+49,14,131,137,18,224,164,160,9,61,164,20,1,233,121,113,160,137,131,74,13,181,104,91,42,73,111,223,228,167,
+75,33,240,61,24,37,87,253,118,193,105,41,225,129,136,252,80,198,83,54,60,91,184,179,111,206,239,167,203,123,
+113,126,113,225,254,245,155,193,123,243,239,238,113,127,245,179,145,245,14,198,101,132,198,113,55,74,115,239,13,17,
+194,233,213,71,229,27,128,126,40,183,24,215,54,136,181,227,74,187,43,248,163,206,74,12,252,10,93,95,164,244,
+171,88,200,129,197,114,152,4,237,147,180,40,77,65,238,209,15,70,58,29,12,243,132,158,145,214,193,157,75,219,
+190,29,187,164,61,193,188,47,47,75,114,67,71,130,30,102,188,223,67,27,85,188,139,210,140,219,107,89,93,53,
+42,226,58,98,180,118,169,75,92,102,54,128,140,60,23,58,59,206,204,120,140,85,230,31,154,238,191,165,37,17,
+11,62,247,65,132,75,32,151,38,222,21,247,247,216,71,226,53,47,56,166,98,29,18,23,199,74,219,72,46,107,
+12,107,90,116,53,233,121,96,202,55,204,22,235,37,239,0,81,49,12,252,73,158,4,61,199,227,60,241,0,162,
+135,112,92,97,187,31,143,125,6,173,25,90,120,100,222,79,97,87,218,210,250,138,80,254,104,97,66,154,144,152,
+151,170,209,130,145,63,58,87,248,93,194,37,219,125,97,232,66,107,207,90,60,55,113,79,50,203,7,117,16,224,
+164,140,215,140,175,251,162,123,199,154,110,246,121,106,106,40,51,151,72,229,140,198,254,226,98,74,188,30,203,56,
+181,152,94,43,4,50,149,111,181,65,32,111,94,226,74,104,232,104,181,62,238,169,5,28,243,50,179,118,244,87,
+119,56,109,243,13,247,47,44,118,183,149,150,38,39,125,39,29,74,212,238,120,170,233,237,166,55,82,9,162,120,
+252,38,131,73,246,185,99,177,8,179,70,53,197,138,238,141,135,47,69,42,241,127,40,123,187,70,204,204,158,52,
+165,173,18,91,249,151,29,82,233,120,60,165,25,142,78,111,69,88,64,31,157,220,161,175,41,25,218,195,65,70,
+80,88,3,41,82,241,207,209,16,227,240,35,181,111,253,148,199,125,27,152,133,137,246,237,178,123,173,226,153,216,
+155,216,112,201,229,226,155,37,167,114,239,12,60,228,232,72,39,126,142,163,85,237,28,189,190,242,108,60,206,40,
+130,124,131,30,140,188,227,35,14,226,31,235,18,238,70,244,49,161,87,228,77,86,77,190,197,105,166,220,196,194,
+78,174,116,89,140,156,65,15,74,181,161,63,82,194,232,118,178,70,65,163,149,54,5,152,201,215,29,128,68,202,
+54,191,169,141,78,15,244,99,237,101,180,218,76,86,101,13,210,110,253,119,75,250,240,140,154,192,4,223,77,28,
+68,41,93,32,176,61,93,252,203,191,173,232,223,229,104,171,111,192,164,136,221,152,108,63,121,58,109,15,60,213,
+144,91,116,28,225,237,157,157,228,168,6,152,81,117,135,198,84,251,201,215,201,83,175,212,116,121,252,7,59,242,
+93,140,13,146,29,222,226,151,67,192,187,134,38,90,227,66,174,40,102,22,179,72,11,13,141,179,100,126,29,113,
+250,25,153,113,139,88,228,81,225,229,69,142,109,217,95,174,168,17,224,48,204,199,255,129,105,112,107,226,140,27,
+94,242,210,199,229,242,134,162,228,225,188,17,145,94,155,152,158,89,43,177,189,251,13,206,40,76,186,248,127,42,
+42,229,255,199,168,148,77,84,208,109,15,18,19,93,44,227,146,29,208,49,177,116,232,207,54,48,120,174,233,60,
+11,103,231,71,94,208,17,46,0,239,98,215,134,147,78,184,69,36,167,110,51,168,174,31,218,159,208,125,133,209,
+58,89,106,103,83,191,94,118,187,165,61,10,215,255,213,138,126,101,153,17,169,215,140,254,162,152,26,196,243,67,
+134,252,110,32,205,2,113,41,114,108,38,26,123,52,45,108,152,89,253,95,3,101,83,254,30,31,245,140,34,137,
+227,5,99,30,79,185,17,121,210,159,51,30,121,230,129,224,156,103,72,224,15,9,219,40,26,208,223,112,139,232,
+246,20,61,180,104,222,202,44,87,203,182,197,174,244,8,195,2,170,240,221,214,171,107,234,220,105,67,173,204,214,
+21,208,206,242,123,219,121,29,255,193,240,23,134,127,116,124,96,245,148,183,22,159,31,135,221,234,205,195,110,245,
+176,1,189,140,35,250,97,155,113,32,176,202,220,22,97,53,128,55,49,240,136,22,164,136,71,74,43,232,142,10,
+124,254,101,58,154,110,255,139,91,235,80,143,20,135,193,175,162,219,222,236,177,141,25,32,23,246,122,239,189,23,
+103,152,204,176,159,7,242,193,164,39,239,126,146,13,11,14,185,222,183,81,44,23,73,35,201,191,133,148,62,82,
+250,77,113,230,8,85,71,144,130,167,42,5,169,172,230,89,12,116,97,146,107,169,193,93,223,117,164,57,143,230,
+154,185,43,140,136,110,38,178,180,147,141,173,208,210,126,41,33,223,245,164,226,141,151,235,19,236,139,28,129,210,
+248,175,35,249,34,14,36,40,209,183,172,151,229,106,189,13,154,58,249,22,135,13,57,226,43,181,173,155,27,46,
+12,185,111,56,31,224,109,139,15,143,222,243,152,154,110,21,146,11,74,199,181,206,166,3,3,62,251,55,20,30,
+113,153,40,210,42,35,101,187,139,87,39,243,26,151,115,34,118,218,246,154,247,228,103,67,231,111,142,117,62,217,
+99,203,13,177,189,70,104,194,219,102,129,170,191,49,43,76,187,238,139,111,108,189,170,111,224,1,216,241,133,29,
+48,186,5,187,48,74,196,190,73,197,193,201,119,176,41,118,240,89,166,41,190,244,146,24,75,146,189,75,147,56,
+1,16,16,144,0,21,10,208,58,150,43,140,146,83,150,159,252,89,150,103,155,178,42,167,124,143,126,1,45,254,
+28,139,95,140,89,28,206,59,191,211,162,219,252,43,58,190,144,84,184,213,17,212,105,114,252,202,245,1,238,69,
+100,68,127,192,230,175,55,30,79,170,15,204,2,43,55,110,60,226,122,236,32,74,130,18,70,130,4,50,87,201,
+240,233,77,61,126,103,242,243,140,235,108,104,2,30,165,115,198,147,204,166,232,54,74,169,17,73,226,123,10,194,
+166,16,82,252,32,28,243,185,18,255,180,79,213,79,205,213,228,132,55,95,184,129,198,186,46,139,98,89,33,70,
+184,49,133,85,161,111,61,162,230,150,154,233,161,246,116,252,185,61,148,162,113,136,157,112,227,38,252,99,114,59,
+93,0,1,66,192,196,253,43,187,190,187,183,221,189,14,93,161,154,186,2,108,93,214,110,175,190,119,238,143,200,
+253,126,78,40,209,127,244,51,219,178,221,150,11,92,108,216,4,127,108,8,176,47,11,102,87,132,40,123,54,159,
+28,98,207,253,211,14,225,16,187,151,63,62,234,177,197,121,135,215,119,190,121,191,249,110,64,25,231,116,70,47,
+145,79,202,206,210,193,102,192,153,41,34,67,103,254,111,226,142,60,62,100,13,222,245,26,82,200,101,200,47,158,
+19,168,68,106,14,10,145,218,59,210,85,19,121,185,242,106,34,23,249,14,233,28,251,60,21,48,15,5,172,126,
+73,64,26,46,69,164,220,12,157,84,249,185,63,188,183,62,3,225,101,163,131,79,77,128,142,226,192,146,0,93,
+40,150,179,143,101,7,238,168,143,185,158,46,187,80,242,177,147,61,248,137,223,255,59,67,201,39,131,202,254,153,
+96,34,184,72,35,144,130,199,86,114,37,20,79,148,52,60,230,113,23,5,4,240,52,78,223,149,10,100,194,231,
+177,101,25,87,105,204,176,67,18,246,99,212,207,207,193,104,18,55,36,230,81,108,83,90,130,105,164,159,109,4,
+104,158,252,210,74,150,165,60,73,32,230,106,174,198,65,141,139,8,132,39,50,71,252,213,197,73,180,96,241,247,
+164,226,177,195,102,145,200,44,205,36,187,117,174,151,55,2,228,81,198,144,112,173,178,107,150,27,120,9,226,41,
+49,250,55,69,76,53,141,152,234,255,30,49,63,31,220,105,2,29,12,10,71,89,160,106,217,188,249,233,123,239,
+230,119,119,81,97,224,212,145,223,64,253,128,215,131,127,238,20,152,143,244,7,78,253,249,47,105,255,241,238,10,
+200,109,114,239,97,238,153,53,135,22,97,10,125,73,174,139,2,187,144,207,66,145,135,78,135,237,51,34,140,200,
+82,241,40,209,32,51,158,69,153,141,121,170,51,103,177,209,75,60,137,241,31,217,136,144,9,143,179,12,164,120,
+83,70,159,107,174,147,196,140,168,76,210,20,140,107,57,183,204,205,0,147,25,230,92,11,9,82,191,41,229,17,
+90,165,138,198,19,184,241,52,252,204,11,147,7,225,96,96,122,182,194,255,168,129,199,119,189,73,81,117,94,103,
+168,45,234,234,212,180,181,165,175,236,13,230,141,248,102,217,91,158,79,185,97,199,31,246,172,161,34,223,16,94,
+226,89,59,162,83,119,4,97,90,33,12,234,225,33,221,101,9,48,195,48,156,242,131,4,193,104,151,112,57,134,
+146,204,134,45,72,154,54,76,84,140,115,9,206,228,221,39,136,15,240,214,67,110,42,19,154,130,195,175,126,193,
+4,139,242,232,138,17,254,184,139,109,224,4,206,73,222,152,106,244,13,109,124,168,92,4,187,61,201,236,161,6,
+177,182,7,216,182,62,96,82,128,93,238,111,153,128,6,77,150,238,155,19,102,14,183,53,180,174,148,153,121,243,
+43,112,27,90,153,61,50,191,125,99,91,108,233,172,253,214,121,170,47,111,128,177,84,91,3,8,145,243,27,84,
+74,179,83,110,204,106,57,59,168,86,207,255,196,178,85,232,60,168,164,209,7,98,19,90,156,248,204,224,238,20,
+162,72,161,64,41,174,79,191,255,238,189,95,5,59,150,51,33,10,121,182,188,25,234,63,77,4,109,239,120,232,
+114,61,128,191,177,252,240,35,134,245,223,158,42,254,253,161,55,2,38,248,155,6,31,187,5,252,13,148,75,24,
+132,127,215,12,217,65,248,249,129,46,248,27,233,14,187,18,1,157,181,21,187,3,127,163,21,226,39,45,14,0,
+208,249,63,254,18,0,23,101,63,88,255,237,27,76,40,158,161,23,150,71,32,159,124,71,164,116,27,211,120,31,
+240,77,18,209,76,35,65,170,9,86,234,83,155,158,8,202,187,120,217,98,79,218,168,255,249,224,171,64,254,251,
+146,165,159,204,160,94,145,81,255,183,223,247,35,219,145,72,232,149,191,125,18,253,97,245,63,236,31,103,206,134,
+190,208,215,239,254,27,182,140,152,198,106,238,103,124,239,70,231,55,30,120,251,122,87,85,216,237,243,114,177,216,
+218,227,149,217,152,253,99,112,28,171,179,50,166,183,72,56,216,119,184,45,104,233,183,91,255,14,186,214,97,47,
+233,103,217,252,136,183,81,141,11,238,192,245,71,183,176,96,222,88,103,182,95,246,186,76,204,88,181,239,153,35,
+184,57,177,197,15,231,83,243,187,53,167,85,191,26,204,230,63,187,225,246,44,211,55,152,162,206,123,80,31,246,
+109,12,127,107,48,90,62,59,44,19,59,175,2,252,227,18,191,124,58,167,181,149,150,153,88,127,3,230,180,108,
+83,213,213,124,60,21,158,45,41,198,108,222,47,127,195,94,238,70,35,171,217,2,123,91,24,108,41,154,177,222,
+219,233,94,115,113,125,141,207,194,136,251,94,235,195,150,202,148,198,144,199,31,219,28,147,77,102,123,17,179,203,
+172,127,90,254,214,86,242,115,229,175,245,153,83,140,213,110,142,189,253,70,162,96,137,125,96,176,162,209,223,89,
+107,87,225,238,84,191,171,50,62,167,19,116,39,47,192,85,101,140,15,19,183,131,211,206,55,227,215,63,251,94,
+24,156,101,71,124,255,249,14,203,12,59,75,253,94,209,145,43,127,25,94,223,59,175,246,214,167,125,183,249,31,
+214,153,171,248,245,164,10,124,46,83,69,90,179,100,83,234,125,174,94,20,163,127,170,189,9,113,150,248,218,243,
+196,204,250,62,209,219,171,195,230,145,73,177,252,139,207,137,175,102,168,202,250,239,240,250,235,96,159,163,208,217,
+199,64,142,154,215,78,238,53,62,135,127,222,207,22,103,201,254,175,255,95,53,23,33,190,143,249,138,23,68,121,
+167,207,253,21,142,127,26,225,40,91,77,124,14,169,179,255,82,170,23,43,124,206,226,133,53,46,135,220,222,206,
+222,198,137,133,191,113,114,111,246,185,200,158,116,30,171,22,255,54,46,122,253,139,66,59,115,16,231,205,115,169,
+200,163,195,231,56,173,246,95,57,54,97,203,201,216,182,87,233,176,182,209,99,39,143,106,201,133,29,39,183,162,
+216,149,3,223,251,100,39,31,205,159,118,226,204,159,15,214,14,244,243,19,135,251,62,135,184,18,44,206,220,245,
+123,21,253,229,125,251,165,227,222,251,175,248,190,141,138,116,230,168,112,102,39,197,231,182,251,235,229,111,91,22,
+248,189,165,248,189,190,254,178,215,127,215,2,135,60,255,184,86,229,176,228,88,205,89,195,110,235,207,222,221,213,
+153,223,85,245,179,95,248,62,118,127,254,49,190,207,191,63,78,147,102,202,219,180,171,2,111,185,201,105,205,98,
+157,136,58,107,180,20,223,187,60,207,188,100,219,81,187,147,231,128,41,31,170,148,177,169,202,97,170,19,225,159,
+152,226,211,152,83,113,111,114,228,137,61,123,111,84,154,124,168,204,145,241,200,210,199,2,219,193,123,236,65,90,
+52,93,162,189,173,143,197,74,211,242,78,226,41,126,53,88,255,136,202,190,139,223,187,148,81,43,86,240,134,184,
+242,179,117,64,142,63,9,19,0,0,207,82,210,236,240,0,38,242,76,1,30,161,8,92,245,82,106,202,49,206,
+36,55,192,144,232,126,210,88,142,67,227,59,139,253,251,187,240,205,97,241,93,193,232,170,192,120,92,249,59,119,
+68,56,62,40,120,99,217,174,67,242,127,24,158,199,111,238,101,87,147,233,72,52,203,127,72,188,98,234,227,69,
+234,220,59,222,240,141,20,255,254,194,68,195,102,151,110,217,25,171,124,147,31,241,163,138,177,23,51,203,29,255,
+107,158,124,59,219,92,138,27,53,0,50,13,53,79,148,194,183,53,241,253,241,45,194,103,69,156,68,248,68,102,
+211,12,109,246,140,225,123,58,221,72,209,217,207,28,69,254,244,236,167,167,177,198,83,136,173,38,206,207,210,82,
+128,206,64,210,148,140,19,104,164,213,175,27,89,247,5,168,38,221,217,62,179,254,41,230,111,123,211,221,45,60,
+191,167,158,183,181,183,188,74,236,117,99,52,127,179,228,178,24,167,78,0,136,187,109,51,226,119,149,99,55,169,
+236,78,21,120,227,227,211,198,35,134,29,132,253,187,189,1,123,139,193,186,120,50,10,34,130,65,206,98,245,173,
+205,102,112,122,206,61,195,180,244,65,222,239,37,4,85,146,91,204,33,196,207,248,119,127,246,30,119,119,222,194,
+184,148,96,86,68,184,252,182,229,193,102,178,22,210,92,175,230,147,135,95,69,143,220,45,9,131,236,202,224,173,
+148,223,49,69,197,161,218,109,152,69,140,201,51,251,201,158,197,189,4,171,192,193,60,219,48,12,243,47,145,9,
+146,251,172,252,240,211,104,223,130,200,159,172,103,122,57,153,79,124,144,29,185,91,11,136,17,153,82,27,104,74,
+10,186,100,35,64,232,40,13,185,222,43,201,66,241,189,183,28,135,75,141,115,215,16,150,94,141,45,101,49,235,
+170,230,213,71,73,50,252,255,111,80,39,120,124,53,34,157,112,231,60,18,89,117,165,227,28,242,67,94,56,240,
+110,11,59,56,56,231,10,87,61,254,105,93,19,105,126,252,163,191,64,146,122,120,103,23,152,77,15,0,21,56,
+50,78,107,252,128,52,217,87,30,148,71,126,30,216,44,41,115,82,4,226,145,152,138,64,18,108,65,225,71,101,
+207,184,130,35,40,162,90,104,10,159,61,110,126,188,197,251,192,227,224,160,20,90,248,144,42,192,9,96,138,66,
+214,43,111,214,219,188,197,55,236,54,111,148,231,80,108,127,73,147,196,158,129,125,36,75,172,107,113,73,40,237,
+156,214,84,125,76,171,116,61,130,189,23,175,10,120,77,5,80,35,80,92,81,220,54,159,188,126,148,75,149,144,
+123,234,115,118,34,217,120,179,56,57,191,200,193,206,109,94,6,190,64,241,20,253,60,195,210,118,37,46,177,226,
+169,121,97,102,120,36,181,179,205,0,232,193,5,36,247,6,59,137,211,213,98,123,175,55,89,85,219,182,134,169,
+153,167,12,119,80,251,99,123,85,249,33,217,208,224,144,233,226,166,234,214,160,54,228,222,142,248,97,165,119,110,
+123,59,37,190,166,94,80,107,50,8,7,168,45,36,201,118,158,92,152,46,97,47,130,199,227,78,239,171,242,1,
+8,116,8,245,247,32,243,232,164,96,61,201,2,164,48,61,75,14,55,84,65,64,37,101,176,137,108,119,139,154,
+92,143,225,220,210,231,64,222,181,184,79,2,176,121,126,205,72,172,129,188,173,87,76,2,116,186,30,6,16,84,
+234,1,252,18,238,197,198,137,185,59,97,56,224,0,75,224,89,105,171,157,62,59,228,239,190,14,232,189,65,135,
+201,226,119,180,13,119,72,44,214,34,61,129,113,86,28,202,192,2,34,72,103,231,145,182,208,134,210,225,2,87,
+213,161,16,226,46,58,224,27,80,144,119,220,22,196,245,8,68,237,226,129,99,28,240,170,224,173,230,171,103,155,
+120,101,219,207,146,167,211,5,227,196,175,40,110,192,7,19,165,205,131,88,187,239,163,112,101,88,181,212,113,191,
+101,81,69,1,210,4,222,240,90,229,0,18,80,118,246,56,14,44,215,69,25,39,107,50,253,238,15,12,223,13,
+203,186,90,64,101,4,77,120,93,26,199,32,172,251,211,198,160,74,33,63,103,45,25,196,213,78,245,167,46,148,
+253,143,96,143,185,192,182,31,163,16,170,61,199,254,141,154,38,156,171,246,22,104,91,158,162,144,65,15,144,155,
+71,91,85,149,253,124,118,117,240,45,252,76,242,155,44,64,69,220,103,103,81,125,229,148,247,159,175,26,38,226,
+135,177,250,157,199,23,40,132,201,129,47,38,73,146,45,255,123,229,108,80,95,137,22,228,25,171,77,126,247,209,
+159,103,156,134,207,232,226,252,143,28,155,80,91,224,209,169,71,64,163,135,140,20,194,224,121,95,118,92,178,145,
+31,127,125,25,134,50,205,68,124,221,95,236,140,227,231,235,197,126,111,11,212,110,55,64,157,18,133,32,12,102,
+229,245,61,27,161,236,23,217,30,110,230,79,159,15,253,72,14,143,126,101,58,157,95,212,164,54,164,239,245,25,
+173,250,153,165,214,254,148,209,142,167,211,132,60,74,32,140,3,27,167,183,48,219,253,41,107,238,149,157,68,243,
+183,132,143,116,147,244,214,226,218,84,74,54,34,104,123,143,48,161,184,66,112,9,73,115,184,214,242,172,158,199,
+229,2,148,167,17,72,132,50,49,252,17,29,43,89,159,81,28,235,199,53,240,67,179,145,249,158,237,153,223,6,
+75,130,210,100,27,189,1,28,25,103,121,150,64,94,120,169,10,104,128,174,252,56,38,176,146,198,147,151,5,4,
+150,90,6,175,223,239,153,108,191,188,109,127,175,42,63,128,246,29,212,19,42,252,168,170,218,187,186,138,51,179,
+170,96,66,221,248,181,251,17,103,112,248,109,158,249,62,175,174,145,218,17,99,190,126,10,17,236,47,3,179,187,
+88,24,31,147,102,237,231,163,131,16,127,228,105,205,36,40,0,154,225,197,192,20,94,167,128,99,160,246,249,80,
+230,206,215,188,221,90,76,242,246,183,137,81,8,4,145,0,38,249,107,248,87,190,98,112,142,178,220,111,139,182,
+192,240,214,25,126,8,70,204,224,61,197,77,147,175,188,54,97,108,60,153,178,48,125,222,20,25,21,26,201,19,
+70,177,125,77,71,11,70,240,45,0,213,11,47,57,227,171,91,166,246,58,57,39,161,236,55,51,84,112,185,217,
+226,34,103,102,113,217,98,73,138,210,182,137,34,175,156,104,10,187,114,181,94,99,113,0,181,182,15,150,153,171,
+16,227,148,98,58,66,142,31,42,195,194,58,181,1,41,135,204,69,220,22,172,145,138,242,37,233,119,233,161,40,
+169,12,127,96,200,8,136,213,7,195,189,43,160,152,55,44,157,202,67,247,155,254,86,54,110,100,194,119,72,116,
+241,16,166,1,115,107,25,195,226,252,201,76,122,83,31,79,233,161,189,35,74,70,162,23,63,238,8,9,208,236,
+139,38,172,201,16,78,187,244,146,98,44,227,205,9,212,48,46,181,217,163,28,18,192,105,22,203,186,116,60,185,
+126,164,63,83,26,57,241,250,213,233,180,240,81,51,187,62,26,166,48,164,236,143,215,152,106,230,126,133,234,153,
+119,142,198,201,27,50,254,250,208,217,100,79,239,40,209,190,1,56,158,127,153,150,5,103,8,245,251,6,185,246,
+144,43,172,207,225,247,113,196,172,48,164,67,148,27,173,216,28,183,212,41,152,218,207,245,67,218,215,103,41,43,
+186,235,27,18,109,34,133,106,160,102,243,12,191,57,36,225,118,182,210,81,199,87,109,34,75,252,214,89,1,253,
+47,252,88,68,187,244,211,104,140,212,234,214,75,108,72,39,135,191,119,23,135,215,15,158,202,76,130,181,142,119,
+144,166,139,189,118,120,13,243,33,60,23,250,76,164,169,150,123,55,121,101,217,23,230,79,40,169,46,244,146,202,
+185,242,1,199,233,204,125,248,37,252,86,36,153,171,254,44,204,133,57,180,20,193,204,138,58,193,216,43,181,228,
+242,232,88,23,207,120,13,179,160,8,192,48,89,97,189,188,148,234,241,70,121,201,193,163,196,167,119,200,98,63,
+168,215,208,232,127,138,60,25,238,116,140,41,148,85,0,154,250,51,164,93,88,113,123,242,197,189,240,239,2,230,
+180,39,126,9,112,157,113,142,216,94,45,182,241,118,239,159,234,85,60,134,245,76,178,64,77,116,79,106,109,12,
+188,129,91,11,110,125,248,17,25,50,2,180,2,156,123,219,38,156,113,98,222,10,177,230,72,129,196,144,251,213,
+158,231,197,42,133,58,166,185,190,180,4,50,200,214,168,191,173,42,217,51,194,49,197,245,193,95,191,227,227,103,
+137,0,217,19,105,130,31,51,212,110,135,212,234,46,110,251,242,39,124,46,249,37,210,127,139,68,102,250,231,125,
+52,240,244,209,253,213,92,23,121,53,208,56,249,253,158,83,241,168,106,146,236,17,170,161,214,165,17,97,133,27,
+70,232,145,75,4,110,4,6,41,14,51,251,148,209,71,240,126,227,171,182,145,192,221,31,141,11,71,190,29,24,
+193,161,143,3,210,178,152,137,125,80,78,205,95,208,79,56,11,74,250,244,195,72,242,147,40,75,110,197,72,181,
+20,173,249,112,81,27,25,120,20,119,137,95,132,172,240,227,222,132,46,14,183,10,118,145,189,77,184,59,83,22,
+146,10,138,170,140,58,244,79,41,79,144,53,179,200,31,103,223,151,186,164,240,191,245,243,136,19,232,187,9,92,
+252,167,94,36,48,36,101,1,19,187,11,133,62,48,213,214,69,205,67,62,163,235,19,53,139,8,118,107,145,9,
+18,71,88,131,51,177,16,32,113,73,218,176,110,242,230,87,226,15,57,246,128,168,213,60,172,123,78,115,139,44,
+14,105,199,212,34,30,223,243,85,4,23,81,23,206,239,245,201,193,196,95,248,254,118,192,195,7,130,85,88,114,
+131,227,170,202,111,215,248,186,122,115,128,250,227,184,207,14,9,250,85,176,213,54,211,108,247,128,111,255,204,126,
+238,159,23,163,141,209,75,225,215,231,54,124,84,0,4,220,75,130,170,34,74,99,136,222,188,221,170,249,199,52,
+147,143,204,159,177,38,151,61,157,226,152,34,80,3,191,158,245,145,208,138,74,195,34,142,201,153,231,168,18,55,
+212,177,209,51,232,30,64,116,78,17,25,227,95,255,216,115,43,43,214,189,129,67,240,34,135,107,105,242,39,162,
+227,155,210,116,28,60,192,163,72,132,147,195,42,69,160,15,91,108,119,90,46,81,158,10,254,130,190,110,90,157,
+21,57,174,108,107,45,239,181,216,92,246,211,31,16,45,175,116,37,24,81,61,229,250,190,215,145,98,202,120,54,
+190,205,51,231,168,213,3,243,208,25,47,245,67,24,246,239,162,241,229,74,180,247,193,164,184,22,149,79,57,209,
+232,77,197,187,196,77,190,190,172,106,77,141,255,70,226,144,112,246,47,144,87,214,31,238,84,107,0,182,172,18,
+224,239,88,81,98,94,230,140,249,126,9,10,247,16,148,175,10,191,185,152,160,234,121,229,171,163,120,31,197,213,
+138,77,1,131,230,21,86,23,213,8,214,136,117,131,61,107,175,28,151,43,14,170,127,190,67,138,250,145,73,227,
+50,81,180,87,176,37,191,45,255,29,227,228,122,137,238,66,181,10,168,95,28,170,232,161,1,0,71,50,73,173,
+158,206,125,85,2,32,170,141,1,254,176,94,197,51,93,241,31,241,152,149,125,218,228,5,91,169,182,92,18,222,
+229,17,81,98,126,101,21,65,130,42,161,189,217,178,200,112,68,201,224,114,237,129,62,209,132,22,179,249,194,122,
+253,198,91,117,32,192,143,142,238,211,142,158,130,136,228,159,64,227,123,188,236,22,233,175,44,239,60,201,9,21,
+178,194,183,227,83,243,227,45,8,53,211,210,143,14,18,94,123,0,1,168,6,255,176,32,178,250,201,246,244,183,
+195,154,63,167,125,96,56,73,116,240,203,216,80,117,107,25,211,188,135,151,8,7,200,169,84,37,51,223,252,196,
+70,52,89,121,177,61,238,24,170,85,219,105,241,114,170,114,246,246,199,169,216,130,238,54,239,240,124,85,170,39,
+218,64,237,105,17,200,1,112,92,224,31,74,176,16,249,16,204,223,132,168,145,167,30,89,14,7,243,77,153,133,
+186,170,53,47,176,90,250,254,58,179,132,62,129,170,0,69,243,197,99,124,88,49,225,213,154,12,230,110,72,137,
+120,189,31,188,238,38,197,219,54,207,133,60,234,199,221,234,108,124,188,27,93,243,65,110,89,205,175,120,136,137,
+234,66,150,243,252,98,40,213,62,237,41,185,118,218,206,209,200,71,245,245,113,150,205,97,224,78,142,42,47,134,
+85,195,154,48,250,0,6,31,129,190,147,226,120,137,220,76,147,88,19,19,106,229,6,225,107,187,128,221,217,139,
+207,63,77,224,142,143,112,85,248,70,87,170,188,92,217,227,211,139,179,165,229,223,139,111,37,202,245,3,164,2,
+221,148,152,31,82,247,212,253,185,56,175,4,95,89,112,102,18,179,56,207,230,76,85,175,159,143,51,122,213,148,
+49,104,222,228,189,68,207,137,30,170,63,225,239,77,162,227,114,127,200,38,18,144,56,36,128,230,219,226,157,118,
+224,208,229,244,46,172,119,213,131,189,1,0,108,203,109,225,151,74,119,58,19,250,70,248,172,41,0,12,220,27,
+52,95,0,172,191,214,105,94,238,3,56,103,228,162,30,184,29,42,8,248,174,60,87,145,72,56,141,196,142,72,
+242,230,113,137,73,212,40,25,238,170,123,129,176,17,53,17,33,223,19,121,254,80,33,64,16,50,101,148,175,12,
+95,216,199,74,140,239,155,161,253,103,190,212,63,212,7,54,190,0,127,222,57,69,251,195,67,219,104,100,216,203,
+226,74,115,85,139,73,41,62,238,50,66,113,106,136,8,138,117,191,5,201,144,108,70,193,107,126,107,233,13,193,
+71,47,22,55,100,235,149,183,88,3,181,90,190,215,46,234,203,187,198,213,41,74,148,11,172,120,97,152,123,251,
+252,197,146,254,241,144,43,75,8,245,253,206,27,199,163,240,209,250,241,137,239,248,151,237,58,49,91,164,205,183,
+211,189,133,108,0,162,98,174,217,70,151,58,248,165,44,228,192,32,79,97,115,72,215,107,48,23,157,204,74,187,
+39,155,91,50,143,14,165,67,219,90,79,83,163,62,142,223,133,160,217,93,85,212,77,25,134,207,229,170,109,65,
+246,216,153,242,4,88,79,198,111,111,132,134,128,238,207,238,100,22,180,2,50,154,111,118,2,103,85,245,144,37,
+60,215,64,156,112,120,184,108,72,111,207,5,53,5,68,123,249,165,58,22,191,236,185,218,223,234,241,217,236,211,
+5,29,224,42,228,198,79,161,153,212,105,56,5,193,85,125,0,99,168,91,11,180,154,103,198,99,216,30,251,64,
+42,76,183,0,39,22,92,177,138,133,186,230,135,160,115,85,149,115,133,79,126,126,180,90,148,153,167,84,132,1,
+242,212,79,240,246,162,40,18,201,16,56,153,224,183,112,252,190,68,231,64,5,0,40,73,112,138,113,86,65,57,
+233,183,52,128,211,17,57,145,140,70,73,215,116,32,94,110,40,249,77,248,101,172,182,149,197,26,64,251,213,164,
+106,82,171,209,163,169,36,245,201,132,137,220,18,32,88,211,56,111,63,55,157,151,111,77,196,72,82,168,125,68,
+182,34,230,154,16,46,192,69,252,169,187,178,6,106,21,200,106,167,23,92,124,231,117,184,188,237,147,99,60,85,
+56,124,122,138,81,193,122,221,88,182,68,42,9,41,184,16,248,122,147,130,189,4,37,168,110,33,8,10,233,0,
+11,177,201,161,9,128,230,124,100,224,237,26,38,171,90,189,213,29,13,52,23,33,136,0,144,10,246,70,34,69,
+175,58,0,208,175,15,185,242,162,226,85,110,97,98,60,191,64,88,17,212,128,96,13,142,34,180,15,118,37,88,
+133,243,168,250,183,78,193,231,85,136,108,64,53,163,12,180,16,137,39,86,238,197,225,229,215,39,212,12,17,49,
+79,189,33,237,98,120,131,78,242,31,159,238,13,220,237,200,47,14,68,22,205,155,173,56,88,154,123,189,5,85,
+13,168,167,144,233,151,230,155,192,3,162,118,113,155,109,248,0,0,215,17,212,33,60,191,64,51,238,83,200,120,
+245,205,54,7,179,170,139,102,250,135,189,188,9,138,95,108,73,227,104,244,215,21,60,179,56,250,70,182,63,244,
+135,233,8,66,168,150,96,255,48,198,210,33,177,246,254,16,55,166,117,239,131,142,252,208,17,152,55,240,91,55,
+222,158,241,73,71,172,240,152,110,59,81,45,226,46,0,208,168,58,232,84,159,183,79,114,101,245,233,106,129,7,
+76,8,224,245,70,61,169,214,174,100,70,63,224,129,67,106,27,229,9,116,11,52,191,107,121,141,92,232,190,144,
+202,135,233,44,210,206,188,82,236,153,248,7,200,44,81,62,6,178,67,182,137,74,135,239,107,124,177,240,82,123,
+134,246,51,42,91,208,214,34,103,243,218,131,149,108,89,108,2,180,159,104,25,187,86,5,71,125,208,215,201,93,
+229,199,244,13,168,82,133,8,74,227,99,62,137,241,177,110,214,194,208,181,104,232,65,47,62,103,179,138,42,65,
+173,52,229,243,96,5,150,100,105,245,155,126,17,149,74,231,71,149,189,90,12,77,201,146,29,100,140,173,220,67,
+144,0,84,8,60,43,124,219,225,48,121,26,47,42,78,72,62,182,5,170,199,7,21,3,22,167,57,156,114,102,
+25,162,77,174,251,44,1,57,143,97,198,78,20,64,216,171,1,184,127,10,154,249,99,80,34,194,75,19,0,92,
+212,118,65,187,176,72,143,23,180,83,71,245,127,63,220,24,73,36,80,193,132,123,120,190,122,245,54,57,95,3,
+134,52,12,107,80,4,64,157,87,156,126,171,124,91,3,146,93,94,199,219,21,193,49,240,207,221,242,215,101,215,
+181,216,231,141,155,182,100,120,233,200,60,75,206,71,12,35,126,0,79,255,88,201,8,123,173,184,25,75,104,82,
+163,127,85,193,254,21,61,65,149,132,158,158,220,241,25,244,245,251,27,150,3,249,196,231,215,173,129,250,33,22,
+63,15,36,180,3,12,84,129,111,160,167,66,50,127,106,73,26,192,165,82,80,149,191,183,155,168,92,204,191,67,
+150,99,81,95,121,67,33,98,191,49,168,245,228,84,207,14,5,166,201,253,66,70,17,20,125,246,26,140,43,119,
+150,59,221,130,171,235,125,54,6,80,222,43,230,64,40,71,81,152,157,215,52,190,180,247,18,223,251,235,114,107,
+191,169,155,98,23,140,80,237,7,218,248,48,165,194,115,34,214,42,142,191,247,58,187,63,66,77,177,12,10,76,
+223,88,31,149,225,11,245,214,139,109,174,194,19,46,170,85,127,148,68,180,42,135,172,234,250,228,79,181,219,99,
+15,25,153,230,195,239,132,203,172,130,17,26,108,75,119,71,106,95,164,255,35,191,20,156,208,200,62,46,121,144,
+174,162,211,143,103,31,6,234,96,192,57,87,167,140,187,92,181,7,153,152,8,36,229,80,46,160,41,186,148,107,
+0,204,49,66,73,41,204,235,251,231,79,161,92,32,93,113,84,7,206,86,80,184,248,154,231,176,16,94,26,1,
+26,23,71,158,37,49,147,136,246,78,27,21,17,218,22,27,23,207,84,0,186,7,64,109,43,209,136,35,116,85,
+190,4,120,21,25,250,159,5,218,194,115,151,206,82,149,134,148,22,93,127,83,116,208,110,230,34,128,152,42,48,
+128,176,198,90,73,179,137,213,112,9,230,83,212,63,254,116,184,89,242,136,215,66,122,240,53,167,30,223,216,78,
+64,97,20,54,44,248,68,192,194,248,81,154,141,232,78,182,96,251,151,225,121,173,42,2,143,249,40,61,165,253,
+0,196,112,179,82,180,109,72,23,2,132,234,247,66,105,227,191,228,74,90,69,90,42,94,132,246,122,250,0,194,
+70,100,173,227,235,4,181,91,107,47,124,198,127,206,111,90,118,118,37,35,23,204,74,154,180,206,56,202,54,138,
+129,238,208,167,116,0,131,193,66,33,126,15,30,245,94,10,219,27,164,237,79,59,252,153,116,109,121,99,151,36,
+19,138,27,143,197,139,138,226,238,208,66,53,64,10,133,200,117,118,11,55,249,59,108,41,127,248,62,207,207,42,
+109,162,191,125,195,234,162,204,188,254,22,218,91,224,106,114,115,106,83,72,130,149,80,74,146,155,221,49,126,233,
+109,154,83,241,35,144,147,59,240,113,239,34,99,179,1,158,45,174,218,115,100,52,14,144,122,189,253,110,111,248,
+118,195,55,2,34,212,84,67,158,53,223,110,72,215,255,8,140,85,235,5,192,228,170,128,71,202,220,222,129,45,
+191,157,100,63,100,103,71,122,251,140,179,187,31,162,203,100,239,70,21,69,205,104,85,191,67,77,23,170,64,248,
+18,120,1,107,72,233,110,8,78,69,13,90,139,93,195,173,23,179,176,173,105,223,173,215,2,173,136,62,68,67,
+5,14,112,5,156,179,48,78,171,169,202,153,111,214,71,146,158,0,243,110,158,17,177,134,210,187,128,182,80,75,
+95,128,34,195,151,65,183,189,88,26,179,47,118,115,126,221,9,235,81,209,140,116,50,20,99,132,66,226,245,90,
+222,181,3,10,128,115,182,152,250,35,7,29,196,70,156,160,35,108,20,181,43,127,171,169,112,164,156,134,53,240,
+154,43,124,212,135,100,152,3,128,227,12,252,159,171,234,215,230,236,164,228,142,29,0,186,228,102,102,236,207,175,
+182,238,234,228,5,126,28,6,60,27,152,53,168,20,118,114,218,54,113,200,4,170,250,231,49,185,195,45,142,159,
+104,65,32,89,125,1,42,88,181,127,43,181,83,1,204,193,27,50,113,121,69,24,169,211,160,1,33,26,29,21,
+10,197,27,78,79,66,77,113,240,96,170,24,14,138,229,182,152,89,251,156,88,59,31,133,231,20,12,223,169,179,
+163,10,39,103,108,53,160,203,52,247,27,72,234,205,217,164,47,77,55,229,213,64,167,52,213,114,68,65,223,163,
+204,225,217,113,157,40,128,121,120,125,167,224,33,209,141,72,124,37,188,185,32,100,86,248,114,117,31,106,53,60,
+5,252,20,62,73,108,245,55,44,100,137,105,151,111,173,69,125,253,144,214,142,232,93,243,104,30,204,85,124,159,
+160,3,102,254,125,40,53,28,61,33,150,221,139,147,159,254,132,17,23,27,55,91,30,170,187,245,8,48,89,213,
+1,0,156,131,153,149,243,221,109,5,177,182,239,133,109,93,134,131,244,156,22,212,191,208,157,238,63,150,246,250,
+34,148,234,164,6,162,112,82,62,24,69,85,140,129,215,197,179,100,205,145,52,195,72,42,190,10,240,214,234,161,
+187,254,31,42,169,27,71,172,188,22,71,244,194,190,210,45,133,22,171,101,130,59,209,177,143,133,99,83,189,113,
+219,105,140,10,85,130,251,150,94,42,5,244,93,185,234,123,125,221,107,170,174,209,224,213,30,210,70,73,151,164,
+72,243,116,106,236,179,70,124,60,149,216,57,145,89,167,30,212,129,209,42,227,153,208,206,37,41,250,109,38,183,
+156,125,34,253,32,47,45,212,92,5,149,130,161,213,93,119,153,126,141,120,202,148,121,142,20,138,239,99,156,145,
+106,169,58,173,168,84,30,142,125,148,176,70,210,120,20,236,196,14,248,111,17,168,141,11,107,200,233,133,155,92,
+105,167,45,182,159,8,129,74,43,80,14,51,81,180,48,83,118,132,17,208,223,186,131,145,78,152,31,163,216,20,
+118,79,7,209,23,67,160,152,82,171,6,110,106,53,145,216,201,171,221,68,205,151,226,176,68,53,84,113,191,66,
+149,128,65,109,244,52,70,198,89,225,30,205,230,38,211,175,200,5,48,118,167,181,253,250,71,254,124,241,128,207,
+59,129,179,131,90,121,166,162,180,9,204,30,240,53,142,26,47,4,205,232,233,69,32,103,160,168,125,164,18,30,
+78,45,160,144,243,155,129,10,133,129,239,164,4,56,50,127,163,157,14,82,37,76,191,199,48,119,233,55,122,12,
+70,71,27,246,77,129,234,133,196,224,185,85,100,120,143,15,22,222,197,250,36,240,202,78,177,164,149,76,231,99,
+10,229,87,164,59,13,4,65,253,107,249,9,38,176,167,234,14,77,110,184,120,229,41,181,103,212,167,253,100,133,
+178,99,98,113,170,66,196,240,118,160,252,46,17,84,200,16,107,123,108,79,138,41,109,50,91,182,121,200,128,57,
+235,198,74,155,167,33,42,117,9,70,142,246,235,218,27,180,151,176,53,254,165,170,111,173,87,145,238,86,246,69,
+94,13,222,154,80,239,212,172,91,253,65,208,213,181,152,80,221,175,43,49,7,95,67,31,113,28,87,97,102,191,
+190,235,33,215,172,97,142,166,10,5,104,76,63,205,245,93,200,75,111,25,4,191,116,125,172,32,20,85,205,45,
+22,91,226,68,179,78,233,94,51,109,238,246,61,201,164,212,63,86,55,51,72,198,237,171,19,47,117,66,77,11,
+180,142,200,36,88,145,68,233,141,11,33,170,190,255,216,231,11,58,169,145,14,41,50,6,200,184,161,237,254,168,
+238,244,48,159,56,245,181,139,223,67,38,134,16,144,151,9,42,185,255,104,218,107,208,10,109,205,39,174,241,86,
+251,139,68,235,243,164,252,217,183,228,58,192,40,204,232,61,54,121,35,222,46,29,123,194,129,73,199,233,176,74,
+154,167,63,53,113,185,223,207,102,112,47,161,102,31,228,95,17,181,45,248,231,225,118,116,159,181,131,25,238,170,
+143,6,119,234,30,62,93,152,151,249,240,158,9,28,64,66,228,249,122,161,26,100,214,74,60,16,114,85,67,163,
+57,172,77,155,0,62,85,135,13,58,238,175,150,73,46,69,209,125,20,32,135,113,194,110,232,117,167,93,82,254,
+98,137,238,211,246,182,77,207,104,214,80,151,162,73,205,31,236,153,242,138,251,6,151,35,169,134,151,254,30,207,
+149,156,79,250,130,110,1,104,253,126,189,244,43,236,153,59,182,95,89,17,49,226,97,190,149,239,241,126,90,14,
+36,2,12,220,22,73,223,66,219,31,231,85,204,17,202,198,84,62,212,216,220,220,36,176,10,213,132,125,229,38,
+132,228,123,3,249,187,51,214,244,58,166,229,62,177,255,150,249,43,178,134,233,11,75,247,199,145,208,62,16,58,
+133,66,184,10,138,128,83,247,105,246,144,18,197,228,178,61,85,247,232,133,207,189,227,9,52,103,137,151,184,50,
+53,215,176,84,17,200,14,38,180,67,103,130,207,235,106,145,83,26,1,74,167,227,79,234,115,37,47,80,16,199,
+212,126,173,186,232,85,191,185,50,179,141,47,13,31,250,103,254,73,52,135,55,185,247,47,120,9,107,144,181,26,
+149,17,238,97,226,219,47,120,107,174,181,64,59,24,3,157,15,50,177,148,168,175,69,4,4,28,0,13,141,196,
+119,151,74,164,174,238,99,69,220,231,115,241,155,174,62,160,115,167,163,228,141,118,53,171,89,69,143,15,178,242,
+106,232,170,193,96,199,65,246,77,27,183,71,212,197,44,143,158,205,107,151,68,37,243,118,132,62,203,67,21,42,
+161,182,137,135,218,166,140,15,76,174,3,254,87,56,190,195,7,52,113,77,142,211,51,95,31,25,126,32,252,17,
+96,174,113,51,165,224,214,20,230,19,174,204,92,135,57,176,167,128,101,210,225,19,176,86,248,100,26,99,75,233,
+21,47,97,42,83,14,74,34,254,54,71,117,214,223,204,204,210,199,245,252,233,230,163,80,84,5,80,146,56,90,
+159,93,124,212,63,15,95,100,206,20,174,215,32,82,252,91,77,228,53,185,10,153,186,13,237,35,195,128,2,217,
+98,166,109,45,158,192,167,209,112,11,122,80,202,242,109,58,92,172,2,237,46,21,78,7,37,49,108,189,2,156,
+45,213,158,205,209,13,72,167,138,132,3,183,215,11,254,216,11,68,186,37,134,102,192,112,210,75,162,153,204,143,
+42,165,61,79,70,96,230,126,91,90,193,131,178,54,18,175,197,178,186,148,135,164,73,31,67,234,196,177,216,190,
+156,76,164,139,254,136,166,167,42,219,131,139,148,90,4,99,121,23,12,73,4,38,237,6,181,234,127,202,236,137,
+135,118,155,213,221,153,117,93,160,189,6,66,68,238,16,5,122,36,117,211,160,133,78,205,120,147,20,47,5,1,
+130,133,163,160,114,104,38,40,83,5,30,177,212,174,142,46,100,34,94,118,17,213,185,106,228,139,152,226,143,33,
+106,94,254,82,60,62,36,215,134,47,224,63,181,97,121,158,99,205,73,94,109,57,176,230,121,196,5,186,251,209,
+30,143,236,247,33,11,12,223,2,243,96,36,15,42,205,55,71,89,211,184,129,58,110,45,236,164,167,191,40,223,
+121,170,98,193,12,163,35,181,182,151,116,251,181,226,216,155,90,134,136,73,89,253,51,12,185,73,104,226,16,185,
+106,26,155,25,69,137,1,68,69,116,92,207,252,100,104,148,232,85,70,188,235,32,235,9,104,186,60,67,47,92,
+165,46,177,251,246,168,214,194,229,102,68,117,148,136,34,226,138,135,64,137,245,234,0,29,41,49,159,100,159,155,
+231,58,239,41,42,53,26,20,205,189,243,109,246,218,157,177,24,163,109,26,238,82,58,97,175,31,183,26,117,243,
+119,48,197,46,241,235,224,195,48,91,18,244,72,58,220,6,4,182,44,1,4,108,208,4,252,67,41,186,196,11,
+85,151,14,219,174,136,139,20,136,58,248,216,254,171,190,243,104,22,217,79,116,100,225,107,181,85,129,51,95,202,
+21,196,236,150,248,89,93,154,125,227,160,81,108,243,197,3,26,174,14,202,108,173,47,11,230,1,27,201,208,126,
+92,39,64,176,128,96,65,22,172,234,252,37,130,90,157,221,119,207,148,185,143,2,224,238,66,167,21,82,144,183,
+100,249,108,60,93,180,129,15,238,4,49,2,166,178,52,87,191,17,16,167,14,184,99,71,88,159,29,7,193,97,
+96,248,116,111,86,234,128,79,34,126,41,228,214,95,175,69,94,34,136,63,154,72,108,188,138,149,238,190,193,39,
+26,158,199,103,244,188,224,152,237,189,186,163,103,78,230,125,99,208,139,132,127,93,148,30,110,2,148,113,118,21,
+252,148,93,244,73,221,118,148,39,146,243,221,15,87,189,58,112,147,181,49,228,137,234,67,1,92,135,145,85,80,
+6,188,135,79,87,84,15,102,154,124,30,96,13,15,253,144,160,171,161,205,61,135,107,94,185,146,196,231,152,174,
+64,159,20,235,219,85,41,188,90,168,251,76,22,88,132,170,160,106,5,2,223,89,124,183,240,231,41,20,207,211,
+206,94,245,219,231,13,209,67,83,209,3,26,53,70,22,79,169,201,1,34,199,164,121,8,219,87,12,246,220,248,
+144,170,54,112,45,5,26,91,183,65,146,9,252,15,255,252,180,135,246,172,28,27,67,77,116,235,216,59,135,23,
+189,39,193,221,122,222,245,70,243,105,106,234,246,54,15,155,246,249,224,39,23,24,174,112,216,27,243,117,61,59,
+175,194,73,191,9,122,100,224,1,203,7,139,27,61,116,241,154,136,185,150,115,45,248,190,212,114,201,52,218,44,
+240,157,194,87,46,227,198,239,235,34,201,155,124,228,151,16,70,50,240,250,121,145,45,245,245,193,222,38,59,245,
+74,89,98,17,222,85,190,255,70,189,207,121,114,197,183,74,199,212,248,186,112,12,187,190,10,116,107,13,6,41,
+187,84,190,196,199,225,63,15,164,240,220,139,139,14,150,7,6,188,14,33,244,22,48,74,140,114,240,47,178,127,
+60,28,147,52,182,61,168,96,147,19,13,227,206,96,150,222,21,236,73,69,195,232,237,103,103,248,19,71,56,215,
+246,234,10,29,218,162,12,199,156,25,133,123,94,162,135,25,196,241,44,247,111,120,118,162,129,17,44,72,239,87,
+237,33,174,183,223,50,255,166,245,67,6,135,174,234,191,152,182,100,211,148,141,88,115,100,11,47,49,6,115,104,
+252,144,101,180,91,99,167,246,151,4,254,55,80,243,66,90,156,59,173,174,235,191,183,46,240,191,231,122,203,102,
+255,47,55,215,217,220,54,206,132,191,191,191,130,239,85,113,102,153,147,235,101,148,48,30,51,61,74,175,215,52,
+50,100,66,230,201,170,4,40,74,190,252,248,219,93,16,132,192,72,215,123,26,32,148,109,128,23,80,6,207,115,
+43,248,95,208,248,117,83,24,14,233,221,143,124,3,243,188,55,182,175,123,221,51,87,251,172,247,23,62,214,93,
+141,183,60,214,229,231,185,43,181,249,76,247,214,155,57,66,122,83,25,232,89,128,52,92,55,191,16,183,206,252,
+23,197,245,59,98,146,194,240,228,35,50,226,219,143,135,251,244,187,71,31,42,112,67,116,220,174,13,216,39,11,
+72,143,69,2,71,135,191,234,77,240,155,45,200,248,237,111,131,37,35,57,166,27,72,14,69,72,142,59,53,143,
+133,76,63,250,0,132,183,31,100,248,23,77,207,209,214,163,182,179,155,176,213,60,124,90,15,159,237,124,210,159,
+131,32,95,114,208,88,1,170,72,91,153,82,229,9,33,117,248,17,63,143,20,244,136,127,70,143,248,103,113,190,
+245,17,191,167,150,163,147,35,51,140,137,14,112,41,171,210,199,196,188,248,189,209,186,253,11,66,117,145,75,57,
+253,15,4,235,126,51,88,62,183,21,164,80,192,28,38,48,128,62,172,224,18,74,88,194,26,78,225,21,220,129,
+209,13,135,134,110,37,176,168,121,123,18,50,241,42,239,220,203,153,177,240,101,124,15,149,192,211,248,37,22,110,
+142,212,31,78,26,229,157,7,102,210,235,88,106,154,245,48,126,77,179,138,159,129,173,205,44,236,241,15,3,173,
+189,219,1,90,43,26,160,181,47,123,134,124,165,27,27,2,222,209,212,243,114,189,197,203,183,121,231,107,227,229,
+82,199,107,118,51,211,241,82,123,19,95,53,38,18,137,193,139,188,243,198,76,44,117,252,138,39,42,29,151,84,
+217,181,197,61,50,140,167,204,132,49,229,109,175,220,160,135,220,60,227,230,220,53,11,135,152,61,231,190,204,19,
+150,53,193,48,54,65,151,209,113,144,69,199,77,20,12,253,217,14,3,97,208,202,54,180,11,3,89,14,130,35,
+139,105,218,67,240,85,182,103,33,78,123,123,40,210,193,77,25,109,122,133,195,247,218,191,102,60,162,95,124,249,
+199,155,195,209,15,127,60,29,67,223,207,125,59,45,144,165,6,177,12,57,92,169,11,37,2,26,11,159,53,102,
+206,67,186,159,125,214,229,224,15,248,99,223,205,200,52,183,95,114,123,233,218,151,174,170,104,8,195,240,92,138,
+50,73,33,168,241,30,12,247,216,15,34,3,244,56,10,74,252,155,69,123,150,180,130,151,138,107,213,136,99,194,
+98,123,199,156,135,143,217,60,72,197,120,28,72,161,100,132,148,247,82,228,13,88,77,157,23,181,171,14,242,64,
+101,34,157,149,27,167,110,208,56,181,57,133,42,231,144,53,135,74,107,209,79,1,120,84,150,35,3,127,132,14,
+70,7,199,132,107,57,226,115,250,122,96,34,227,240,49,12,3,23,12,3,31,239,68,174,139,10,1,62,38,171,
+196,47,65,174,11,15,22,78,45,153,127,127,240,205,245,93,225,184,88,94,145,118,80,146,217,248,119,136,143,126,
+85,103,86,104,138,52,131,115,170,38,19,205,168,234,169,125,35,171,12,187,9,211,227,177,21,185,179,194,71,67,
+213,39,73,109,203,64,234,82,202,169,137,155,111,46,199,51,139,42,56,96,90,203,156,196,103,54,195,26,97,118,
+189,56,189,6,254,134,226,202,5,233,174,23,139,182,224,112,140,174,172,13,14,137,153,95,88,219,25,41,234,215,
+138,86,191,70,145,117,72,78,83,43,17,205,159,104,220,255,44,118,185,43,38,219,121,91,72,134,61,253,5,126,
+110,28,254,102,241,212,196,95,196,138,103,166,42,234,153,28,191,178,214,191,254,133,110,109,193,175,89,207,6,228,
+26,7,204,187,180,156,198,103,126,80,172,30,148,92,178,221,164,106,34,86,17,238,227,131,54,109,106,84,88,109,
+172,213,216,214,20,238,44,25,237,161,63,87,148,61,44,55,142,53,179,222,122,204,51,100,14,174,103,88,104,172,
+88,120,231,211,107,124,225,69,141,22,234,201,133,162,243,135,248,41,92,207,204,20,57,21,57,8,83,156,155,34,
+51,125,67,83,164,76,191,85,64,90,207,78,97,94,165,213,9,214,157,204,129,41,250,148,89,177,171,191,209,117,
+105,138,146,138,18,150,33,40,26,177,172,70,188,98,130,93,68,111,143,226,111,103,18,61,112,71,255,81,47,4,
+108,202,54,154,142,123,97,15,238,88,174,164,4,190,93,244,16,184,77,55,55,186,5,37,33,177,101,61,101,110,
+82,190,15,37,88,112,203,121,203,11,80,24,194,107,154,196,183,32,51,235,33,207,226,251,80,130,5,181,224,44,
+47,120,161,37,199,187,39,9,9,191,96,36,252,61,105,161,240,73,243,174,20,194,226,179,235,60,100,39,18,62,
+249,105,36,252,130,145,240,44,162,9,133,95,48,20,62,49,55,38,37,53,14,9,33,193,43,210,73,247,164,213,
+189,70,193,89,144,128,67,230,84,235,194,30,177,109,118,227,209,148,220,51,135,98,213,14,110,45,113,76,23,181,
+17,163,45,8,238,181,212,173,221,152,250,81,219,20,251,136,90,234,213,251,247,236,221,132,226,200,249,41,249,83,
+242,19,45,142,151,10,67,88,106,210,73,119,59,187,120,153,166,213,179,215,188,132,42,220,74,110,122,27,210,51,
+125,69,98,86,108,250,31,144,241,200,16,47,149,134,80,234,24,53,240,93,210,24,170,244,137,210,213,218,116,90,
+138,173,182,119,204,132,42,104,53,95,59,252,31,18,207,234,53,89,189,102,171,255,144,132,198,134,123,201,114,83,
+219,41,105,219,146,228,146,63,51,201,53,105,187,78,153,229,33,65,42,118,102,121,240,239,122,144,152,157,204,169,
+132,185,30,104,164,216,50,74,216,81,196,248,64,131,146,234,11,28,101,140,16,30,242,191,47,113,98,149,225,82,
+222,60,92,40,83,220,193,185,68,167,56,242,190,228,117,137,251,203,227,15,180,236,94,129,162,9,63,84,215,241,
+215,98,208,153,49,201,87,253,191,5,21,233,87,38,20,177,65,40,159,246,171,192,159,59,250,42,148,137,233,133,
+252,8,138,16,25,142,167,155,180,168,69,60,158,33,23,225,43,61,67,47,37,113,236,62,212,114,210,250,136,46,
+91,125,92,167,177,152,43,250,154,125,163,176,116,94,5,37,40,157,23,4,154,118,84,159,44,210,12,248,191,10,
+193,19,170,118,8,5,117,98,4,117,42,244,50,70,62,251,195,36,13,89,210,184,181,153,76,211,170,205,227,26,
+105,80,161,113,204,62,114,241,38,46,51,118,190,13,51,164,226,116,29,33,124,84,47,66,61,104,15,242,31,217,
+59,14,229,198,113,221,175,232,245,38,241,17,236,218,153,235,189,247,94,53,25,223,198,179,46,123,114,174,223,253,
+251,1,176,32,195,113,188,78,219,94,18,146,0,1,144,20,65,16,100,108,136,136,4,143,52,50,49,35,137,171,
+59,36,17,52,5,69,91,31,232,87,155,35,189,4,71,251,180,191,80,112,180,55,250,250,21,14,142,166,213,197,
+214,27,85,129,122,84,19,183,21,43,237,147,197,129,239,180,239,189,102,161,19,65,227,79,59,90,250,116,195,225,
+244,248,236,66,165,11,93,171,189,125,233,110,253,50,153,209,102,16,207,223,177,234,167,110,122,66,97,11,187,197,
+116,222,81,243,23,234,234,235,167,175,105,238,20,225,133,10,11,42,244,56,47,88,94,73,168,23,185,158,154,82,
+184,21,14,193,41,24,14,245,33,192,47,26,24,227,125,4,193,72,188,15,65,173,36,88,90,172,115,245,38,166,
+165,122,129,82,19,163,115,37,228,88,65,52,33,228,12,209,215,109,5,9,147,23,32,73,53,161,178,166,38,8,
+229,100,150,214,14,41,88,228,161,76,232,42,104,71,161,0,149,179,148,190,224,198,122,70,130,102,96,168,122,19,
+179,140,132,206,128,13,49,181,212,105,231,235,108,74,27,131,183,145,128,22,169,80,106,68,50,204,146,80,86,138,
+9,214,242,176,115,158,210,23,64,248,9,2,205,4,36,232,77,224,65,171,102,54,12,185,242,53,201,225,49,122,
+221,99,63,140,208,69,26,77,224,17,6,169,101,92,212,228,145,199,199,179,144,57,161,153,216,122,180,121,35,176,
+173,10,117,105,172,36,76,171,105,91,154,133,245,227,135,33,229,73,128,173,73,0,61,9,224,184,139,224,244,36,
+128,215,12,12,161,48,30,50,107,204,231,162,68,172,149,47,44,231,248,93,19,92,79,31,28,119,183,39,82,181,
+39,150,16,85,241,133,4,6,242,157,255,117,40,207,40,176,48,56,99,249,95,93,141,197,255,224,90,61,161,202,
+38,196,17,181,97,105,20,79,163,152,36,208,17,119,15,183,138,163,91,199,203,217,188,153,146,189,108,254,223,188,
+186,156,79,48,123,31,151,255,164,23,90,10,220,123,107,50,70,74,210,200,70,22,20,220,33,168,146,92,133,161,
+8,185,99,218,137,191,19,110,255,188,27,129,135,144,135,99,248,224,150,181,34,11,132,157,48,112,145,232,64,100,
+177,112,59,65,139,133,25,31,208,36,116,15,27,50,206,248,218,26,3,110,163,45,195,136,131,203,93,91,246,253,
+198,150,169,203,224,181,92,121,53,24,158,84,134,87,240,60,5,207,172,186,27,139,142,111,61,23,79,77,248,206,
+243,169,197,169,27,207,21,187,164,39,79,209,43,159,164,147,136,92,23,106,233,45,118,108,93,179,32,167,145,132,
+45,217,59,95,177,155,203,98,151,152,49,134,228,145,128,19,245,198,172,154,222,194,246,199,122,96,200,67,196,103,
+140,239,243,221,43,245,203,90,235,229,153,150,251,125,36,68,143,107,54,105,226,117,218,111,103,13,219,148,55,157,
+227,2,89,63,227,93,9,46,3,129,46,96,106,82,134,152,93,203,16,210,33,17,22,70,186,74,179,132,106,45,
+41,160,72,203,5,178,225,34,129,64,104,53,47,65,44,18,90,221,146,102,129,74,122,249,121,245,22,12,253,245,
+67,119,131,72,114,4,70,45,35,14,146,163,110,79,211,135,202,15,93,133,161,167,118,96,46,153,97,48,22,66,
+244,54,249,73,3,73,139,177,131,236,102,155,68,55,191,37,11,170,161,227,87,178,124,42,138,218,95,173,241,140,
+92,14,51,73,3,74,248,24,189,73,49,149,24,24,4,26,134,32,24,242,72,194,79,201,7,15,33,150,74,51,
+216,10,40,69,18,43,245,4,182,154,190,101,25,173,150,171,169,19,139,72,52,85,84,40,72,106,156,47,49,39,
+23,9,204,53,68,147,19,4,231,51,2,36,11,83,59,208,248,74,81,23,18,133,2,32,8,3,161,52,53,67,
+52,162,45,169,138,30,72,6,165,159,203,179,226,199,254,14,154,153,6,162,224,246,61,239,253,27,192,11,104,24,
+56,155,207,167,39,247,110,3,112,97,219,248,19,226,238,25,126,69,121,227,103,122,197,237,153,244,208,98,116,20,
+174,222,253,43,231,217,91,5,103,203,205,142,65,91,192,174,69,253,251,37,45,170,132,55,84,214,117,199,162,238,
+198,47,60,188,242,232,217,6,1,104,1,70,1,198,185,77,130,25,173,173,23,76,79,236,96,226,214,146,141,134,
+220,228,99,240,29,80,105,29,222,15,108,229,143,155,211,184,198,99,232,194,38,30,231,93,210,188,67,121,72,175,
+151,218,142,24,127,239,85,242,176,246,93,175,46,157,116,231,243,62,86,252,178,110,142,28,250,215,103,102,221,141,
+109,36,78,218,51,221,14,242,167,191,62,211,35,242,33,242,85,38,221,3,125,174,212,91,92,18,164,108,113,14,
+104,255,50,37,197,182,245,4,178,3,145,5,193,80,16,103,34,56,151,50,32,50,153,196,255,232,92,100,75,235,
+125,46,158,54,6,164,204,198,15,255,116,93,212,236,145,69,70,221,76,49,224,131,181,41,71,238,2,117,68,239,
+236,178,197,56,65,93,124,135,193,215,122,78,111,46,176,160,137,159,108,49,215,115,26,153,94,106,5,220,94,206,
+126,185,185,92,236,93,4,226,195,17,6,137,167,139,147,213,248,176,56,145,124,91,169,11,251,109,148,181,198,131,
+207,182,208,174,32,197,218,57,214,47,71,199,246,84,146,107,129,113,73,147,39,22,193,14,106,206,72,224,218,42,
+27,103,83,108,99,225,149,80,130,5,7,161,226,203,148,98,93,106,189,163,131,126,36,79,206,15,222,91,142,218,
+147,91,55,171,29,74,66,69,69,77,80,164,3,189,22,74,151,60,185,245,193,6,208,13,67,81,157,35,72,92,
+68,90,131,234,66,1,41,161,14,3,232,34,65,241,250,175,33,34,13,75,55,163,216,2,27,134,3,126,250,101,
+87,245,39,19,84,154,73,143,165,15,39,115,188,107,237,80,235,38,205,113,55,251,238,81,93,225,215,178,94,23,
+151,88,175,218,19,60,236,253,233,77,198,88,159,104,37,36,7,51,103,138,43,13,167,227,71,130,212,11,54,102,
+235,170,138,210,182,146,178,38,110,118,169,85,218,110,81,195,64,189,78,117,219,154,69,247,67,211,138,176,131,206,
+236,165,21,167,156,86,156,114,88,113,174,83,71,246,169,199,234,94,170,71,50,57,145,121,45,176,165,17,201,85,
+96,124,194,57,206,88,25,245,252,251,226,140,205,121,214,120,19,27,175,152,188,117,88,29,161,224,244,229,236,42,
+103,124,78,85,50,62,164,38,153,199,112,34,151,221,25,31,76,189,240,100,30,77,123,12,124,138,208,82,249,173,
+189,42,95,250,12,168,79,77,130,59,226,147,157,27,193,95,182,192,158,32,123,142,3,25,75,1,129,126,81,108,
+202,109,22,196,232,53,103,193,244,204,207,80,191,191,157,94,218,17,136,218,201,2,108,55,211,75,51,26,35,205,
+60,168,202,215,213,51,82,190,14,149,111,118,199,3,35,103,61,171,34,125,212,122,87,21,251,39,170,184,81,197,
+124,88,19,203,53,104,34,164,39,170,120,134,42,118,187,170,120,69,69,164,154,251,169,124,143,146,163,181,188,247,
+251,243,189,186,83,219,119,157,54,123,68,21,242,94,187,118,143,161,234,28,105,213,121,106,74,87,169,139,110,62,
+249,223,95,255,170,191,135,244,212,95,190,224,207,83,253,176,250,235,87,230,79,218,174,115,201,81,28,8,255,191,
+167,240,184,238,40,216,98,226,101,246,40,95,206,57,103,15,6,49,176,131,192,139,224,150,13,126,247,235,143,22,
+22,96,152,205,127,44,144,186,91,82,171,27,181,176,62,148,230,97,86,71,66,217,45,53,78,155,116,44,43,53,
+47,97,221,208,207,44,235,215,124,10,15,163,17,94,57,33,188,196,220,145,71,56,191,21,184,23,148,133,150,21,
+30,28,28,187,52,123,187,233,157,31,159,248,145,23,165,12,50,30,69,67,56,113,24,72,166,117,151,184,49,233,
+142,146,110,27,51,148,134,123,133,123,92,20,92,64,42,224,36,208,205,145,116,141,13,151,88,36,179,152,216,58,
+223,159,158,154,244,84,72,122,137,42,59,199,168,196,214,5,110,176,119,186,237,94,203,98,207,40,54,233,41,54,
+49,138,117,220,108,21,174,194,19,174,213,179,67,159,148,156,56,46,107,168,215,48,199,11,73,120,200,47,169,67,
+95,55,54,34,218,135,137,222,204,216,166,74,167,5,247,140,232,7,182,145,220,96,27,55,142,236,147,15,215,244,
+161,136,57,84,203,249,69,79,181,106,82,181,243,7,39,198,79,102,219,118,207,118,87,189,107,96,250,64,123,128,
+193,123,156,85,83,114,185,56,62,68,219,94,206,219,186,201,13,41,55,3,202,11,230,31,155,93,112,17,46,211,
+124,91,87,203,17,12,102,108,255,79,236,40,145,33,84,89,10,124,68,183,77,151,118,203,117,20,170,18,219,165,
+91,179,250,112,163,243,101,154,47,221,45,103,211,117,151,27,52,192,161,112,110,208,232,92,152,50,85,82,98,135,
+42,143,57,161,24,105,204,41,169,232,98,4,68,64,82,12,61,15,73,0,240,1,88,18,176,224,34,102,222,24,
+0,132,79,115,170,136,181,185,161,237,191,107,192,4,40,71,111,139,213,160,0,151,243,88,139,29,78,96,163,113,
+2,220,166,235,158,189,53,211,174,124,189,119,229,166,173,175,101,201,192,66,182,212,244,108,169,57,176,37,150,18,
+186,153,230,170,193,85,251,77,167,91,42,239,43,93,83,109,65,181,245,27,173,106,16,153,17,208,52,122,131,125,
+163,21,15,26,51,30,186,205,208,17,183,25,62,211,56,15,27,253,48,104,211,68,167,49,105,80,111,96,94,15,
+220,41,122,156,59,241,9,225,173,77,187,157,93,184,123,83,56,169,138,79,211,70,68,246,25,52,193,232,86,191,
+231,110,148,105,28,237,5,185,88,64,116,100,67,89,47,43,161,172,208,57,4,7,214,253,13,167,217,11,240,174,
+218,16,118,123,104,223,34,178,4,27,81,71,144,165,1,156,175,99,86,213,253,76,192,197,46,219,80,194,3,102,
+136,213,219,109,203,154,80,242,238,181,203,145,103,179,75,207,227,165,184,61,236,241,240,76,233,110,200,51,41,1,
+90,103,222,51,3,78,50,36,25,240,64,96,137,193,130,139,136,121,105,40,225,89,44,115,211,243,44,57,237,89,
+27,156,66,94,130,164,244,37,250,42,97,74,178,235,165,156,54,37,22,16,224,97,209,214,17,66,64,232,203,129,
+105,49,81,226,134,32,50,62,101,116,203,245,25,221,30,214,10,221,90,214,96,108,90,71,146,206,67,169,29,169,
+77,99,157,70,195,83,237,242,3,239,225,198,205,76,167,146,77,193,204,167,147,38,57,132,185,61,203,124,202,141,
+120,194,25,181,14,110,0,170,107,232,53,237,51,135,123,25,51,61,162,235,115,42,160,157,222,61,100,117,196,207,
+91,238,247,162,233,34,158,22,121,96,254,138,89,174,210,192,27,20,38,181,76,35,44,45,86,98,84,162,227,168,
+85,53,202,223,150,197,85,41,20,149,188,90,14,75,120,214,91,174,254,28,229,107,116,245,234,110,233,125,201,72,
+239,218,143,236,20,120,225,122,0,15,151,243,157,48,181,70,193,116,173,113,48,93,107,18,120,33,239,94,216,248,
+18,181,174,253,205,44,182,28,1,92,210,198,127,130,35,6,203,138,167,241,229,219,54,187,108,179,3,147,189,70,
+246,0,237,91,140,113,60,55,97,101,1,18,50,159,248,208,184,198,29,210,137,174,61,122,52,200,133,237,46,87,
+75,198,100,102,1,64,38,117,169,138,242,120,91,164,6,223,198,209,206,220,215,63,250,200,37,50,128,178,106,129,
+75,244,31,227,248,97,77,212,199,152,2,0,196,150,145,183,191,125,107,145,93,237,239,168,51,77,102,238,232,188,
+207,254,237,197,130,106,211,66,22,9,1,142,91,12,211,2,223,31,153,71,174,50,144,202,192,152,38,144,168,36,
+167,175,67,13,112,154,138,148,120,180,165,93,245,128,147,130,7,29,185,147,184,206,237,8,215,89,114,18,96,232,
+165,29,232,146,140,130,166,208,47,132,173,70,208,202,204,132,71,127,93,19,140,178,1,120,48,33,234,196,111,61,
+157,141,143,27,37,28,199,75,0,169,211,56,59,159,101,55,189,71,1,194,143,85,76,236,177,255,45,216,217,88,
+117,235,137,61,38,246,152,217,99,205,14,52,146,13,7,108,176,247,102,187,218,158,112,172,230,217,91,16,178,87,
+54,148,16,43,140,124,208,101,7,177,207,187,250,187,29,207,103,217,141,182,236,102,210,178,155,103,176,108,203,26,
+248,29,77,77,232,42,121,61,119,117,189,90,239,187,186,70,87,249,81,208,80,66,93,133,227,14,198,208,1,254,
+13,255,218,22,248,233,7,120,108,54,81,247,120,192,5,84,7,110,252,102,8,247,194,225,218,239,42,152,67,171,
+61,108,79,153,84,132,109,5,40,173,0,111,233,159,185,1,46,50,127,185,212,11,78,13,27,75,124,73,88,171,
+163,226,209,35,76,203,40,120,244,8,51,188,164,30,48,148,74,58,46,3,166,200,206,92,37,170,159,83,41,138,
+186,98,4,155,46,57,167,174,145,151,160,135,241,94,160,234,54,167,251,146,236,73,29,60,95,109,172,105,51,17,
+148,157,196,16,171,171,81,13,128,206,213,91,234,146,88,2,112,39,101,144,71,158,22,225,241,226,33,34,87,136,
+60,117,146,70,110,91,161,39,119,221,170,122,231,190,142,86,121,106,108,15,150,53,41,151,75,189,214,193,38,229,
+98,238,245,237,118,149,137,198,97,18,104,232,254,120,227,156,218,107,250,189,69,90,232,192,108,205,123,103,164,196,
+198,39,181,53,6,243,199,74,213,186,113,48,62,103,123,12,95,237,131,228,160,177,43,230,57,234,152,60,116,205,
+76,114,91,154,112,74,255,155,18,16,180,189,220,150,197,217,141,112,117,24,154,37,236,3,72,56,201,136,58,229,
+203,19,100,193,58,129,181,100,173,48,6,48,141,237,54,175,5,43,99,137,18,35,92,55,89,8,86,18,91,87,
+58,44,112,212,189,180,10,19,30,119,152,105,160,196,32,114,240,0,48,204,124,4,223,101,161,24,81,106,190,12,
+69,225,18,199,78,40,227,216,233,246,166,20,193,245,109,8,50,81,134,145,130,16,126,86,10,202,14,165,232,136,
+196,219,55,149,131,45,221,88,101,132,235,79,25,205,72,231,194,67,241,209,160,143,34,154,97,71,209,33,243,189,
+62,51,67,233,230,248,185,116,32,66,127,160,199,136,208,171,139,105,1,40,235,179,239,76,59,76,156,244,92,154,
+102,135,125,62,25,40,58,28,146,55,135,34,222,237,62,218,210,17,96,81,55,243,101,51,158,241,135,149,104,151,
+243,204,195,235,124,245,18,170,28,15,204,188,72,46,127,188,196,231,28,248,29,97,96,21,175,21,120,133,223,225,
+95,183,193,83,225,95,175,2,183,14,128,127,229,105,232,108,0,113,149,237,164,197,11,20,225,255,181,12,147,52,
+139,74,129,93,82,250,187,8,124,149,21,21,222,183,82,101,97,64,146,187,199,99,142,239,53,196,84,51,223,170,
+69,17,47,190,219,220,17,97,117,114,45,238,43,59,117,28,97,94,210,42,135,102,157,252,47,245,143,159,210,207,
+30,98,156,239,78,111,29,189,178,184,181,248,40,9,202,234,228,142,90,252,71,251,236,78,206,145,197,95,217,227,
+23,250,33,138,239,40,188,213,71,145,29,58,132,170,185,184,48,108,31,21,121,85,166,100,47,52,18,160,248,81,
+100,130,44,40,90,32,36,41,23,85,34,22,223,124,241,243,226,235,52,20,185,18,68,113,202,205,94,23,126,167,
+16,123,191,52,193,51,146,122,115,47,205,9,98,239,251,75,200,136,177,129,110,185,218,19,167,123,106,236,137,246,
+152,246,164,20,119,107,161,170,15,58,196,236,167,101,32,197,174,191,146,107,138,113,168,240,63,105,79,194,159,54,
+238,236,87,105,211,227,103,217,178,177,13,228,48,56,244,190,239,54,175,233,75,121,89,67,85,162,13,145,179,182,
+114,180,33,223,253,205,72,22,146,3,251,191,15,36,102,70,51,154,83,23,155,101,96,153,42,223,125,88,129,251,
+35,72,112,89,162,252,168,158,195,92,163,41,28,108,189,138,56,255,228,123,153,31,140,141,249,150,179,137,162,168,
+34,87,101,46,128,150,214,192,16,72,99,122,88,234,241,122,114,84,45,34,138,7,143,138,211,211,249,47,117,65,
+113,77,220,160,152,184,65,177,78,140,176,86,26,121,173,13,3,174,115,238,134,129,83,189,73,53,194,84,76,10,
+66,229,245,117,179,192,138,156,231,187,188,57,141,86,184,7,156,179,159,80,85,20,8,130,28,0,149,122,7,202,
+54,154,191,225,65,75,153,55,246,107,143,148,206,32,150,121,50,96,164,147,210,195,162,161,166,162,161,247,132,17,
+210,176,38,64,142,8,35,97,212,140,205,164,245,217,99,9,177,209,76,250,178,112,3,6,205,196,243,120,197,80,
+54,56,130,224,186,229,255,175,110,228,228,102,147,215,68,28,111,5,155,243,39,239,112,16,44,255,58,70,120,173,
+218,251,247,91,95,49,225,52,223,219,113,147,162,50,215,9,233,68,149,44,63,67,158,136,153,14,12,190,76,68,
+25,213,103,147,90,86,94,76,183,8,154,227,160,84,67,97,111,182,68,133,155,10,163,164,141,157,217,253,118,85,
+106,246,173,247,239,255,51,209,174,148,166,112,0,83,61,241,187,24,24,158,99,20,113,118,50,97,21,30,137,111,
+113,32,40,196,20,49,239,20,20,223,211,234,103,92,112,201,188,192,189,111,56,85,49,184,156,218,93,144,57,226,
+153,180,19,127,218,194,175,245,1,6,86,51,169,95,58,152,32,144,28,202,90,169,4,86,226,17,86,229,175,92,
+30,121,27,247,32,170,78,139,170,102,207,230,101,33,65,108,7,150,214,140,119,36,253,85,254,87,60,124,153,5,
+220,42,248,209,148,18,220,25,130,163,26,150,202,192,192,215,208,109,144,70,67,147,137,12,102,224,220,181,153,20,
+209,225,172,127,42,4,28,49,232,8,180,101,206,163,57,19,51,121,4,36,88,240,235,188,12,147,65,189,11,113,
+95,135,33,145,74,30,48,197,202,78,107,50,96,243,154,221,82,132,72,49,44,7,117,16,252,13,21,176,199,232,
+81,108,171,188,189,124,208,50,175,140,224,191,225,84,1,175,49,197,79,71,159,154,219,18,102,222,247,65,206,109,
+190,88,220,150,139,133,81,6,2,85,54,93,147,55,137,90,207,88,30,83,177,212,121,192,134,98,16,4,12,45,
+81,195,226,197,198,48,47,137,77,173,54,234,248,23,56,32,90,46,129,93,217,2,224,145,139,27,140,238,89,57,
+38,81,237,172,75,142,89,212,152,221,58,236,164,56,245,74,8,106,99,168,171,27,153,61,173,88,1,113,175,207,
+254,236,166,5,69,206,140,26,122,253,136,149,134,131,90,233,84,19,208,3,45,152,163,112,221,181,5,97,121,90,
+177,115,60,47,109,166,31,108,28,30,170,220,62,60,132,109,194,50,203,161,239,236,74,54,198,90,241,247,63,117,
+190,135,137,195,172,176,113,135,238,65,230,70,241,166,126,213,96,104,142,246,102,208,12,126,123,53,164,250,111,175,
+36,163,199,204,195,48,21,36,67,2,156,126,233,4,0,96,111,44,177,207,61,73,32,147,15,36,120,45,23,198,
+36,40,245,183,107,237,1,195,197,248,234,186,17,15,114,163,19,86,205,88,181,88,156,23,202,114,104,197,10,235,
+253,176,6,3,86,106,230,50,23,7,213,152,2,43,73,8,140,148,92,156,177,134,69,225,122,4,240,75,38,115,
+8,178,105,94,44,189,51,156,2,191,57,41,189,226,96,62,166,122,250,235,60,192,220,146,101,52,189,210,179,204,
+46,138,107,199,12,23,141,129,255,214,188,66,155,183,54,230,21,202,188,53,25,129,20,65,107,146,173,148,240,163,
+162,126,127,33,62,84,229,41,131,99,165,206,67,73,57,238,237,140,35,106,66,154,122,121,92,224,253,198,91,248,
+140,54,108,205,250,38,180,6,154,134,229,124,25,33,111,11,128,155,240,99,42,90,70,38,11,51,102,245,122,213,
+148,117,52,61,80,29,23,214,127,104,89,157,190,32,6,85,215,225,14,181,81,236,178,1,225,144,191,203,213,140,
+81,17,50,50,166,44,23,65,226,140,88,53,250,172,181,219,83,123,209,135,210,139,241,97,101,239,20,44,241,24,
+114,222,35,1,215,91,54,47,49,6,152,200,156,219,66,127,219,93,86,232,179,22,206,45,214,116,79,232,53,194,
+156,248,107,254,155,97,177,82,157,118,169,106,140,120,11,121,16,244,178,68,23,121,140,172,169,52,214,5,15,11,
+87,159,229,253,198,73,121,86,179,179,83,88,100,45,76,221,189,180,33,165,192,195,202,9,19,103,102,181,222,207,
+223,22,242,40,250,240,146,238,229,169,191,79,63,23,249,94,176,79,43,158,235,5,58,250,240,254,243,203,47,47,
+255,231,233,225,203,119,207,224,95,211,242,229,27,125,92,228,251,157,100,59,166,175,160,77,233,148,65,211,163,31,
+69,190,239,167,157,46,61,145,154,229,188,156,37,49,125,219,124,171,249,76,88,45,158,131,87,76,24,53,4,234,
+2,210,195,106,153,95,232,204,224,157,132,117,49,245,121,19,243,76,83,158,150,23,30,114,198,254,207,121,9,166,
+60,145,152,31,4,43,127,199,108,124,61,49,204,147,81,146,65,147,142,82,108,250,163,126,150,196,196,119,194,241,
+67,225,206,227,0,3,74,207,246,175,10,89,170,152,20,202,91,34,79,6,98,200,6,34,8,8,191,39,192,154,
+120,37,5,249,117,86,31,121,130,208,166,199,59,130,180,242,192,99,139,24,82,179,65,51,36,172,75,96,142,53,
+16,111,168,194,146,128,66,167,30,32,156,105,49,235,228,219,188,126,87,188,243,90,219,9,119,215,196,221,170,97,
+138,167,9,16,165,76,49,169,61,30,74,50,116,20,127,82,180,51,217,117,129,157,127,40,135,57,228,31,11,228,
+110,206,29,49,165,17,163,236,131,139,116,99,163,152,214,118,241,21,195,90,153,171,132,204,21,99,92,117,181,42,
+165,42,57,248,226,168,196,98,71,127,5,139,80,232,20,151,10,142,29,79,125,5,184,163,228,161,116,51,192,247,
+84,44,58,248,83,209,198,3,182,179,239,224,95,43,60,38,220,93,167,170,162,38,50,79,40,51,203,172,107,17,
+95,146,142,132,52,230,3,34,253,28,98,143,5,193,210,72,150,243,113,217,54,170,140,46,67,30,93,82,1,189,
+95,208,251,69,107,39,188,152,207,2,225,11,29,100,165,70,20,178,16,169,39,156,82,86,14,195,168,239,239,67,
+172,149,65,190,71,232,149,250,75,28,89,73,127,112,189,149,206,106,247,111,129,240,214,18,99,133,45,19,199,204,
+41,37,129,3,211,179,75,93,51,191,47,92,86,24,64,193,231,130,220,219,11,247,45,205,79,199,21,30,191,183,
+23,236,1,129,19,100,204,238,18,204,166,64,13,161,37,182,146,208,10,91,70,104,129,109,25,214,132,206,177,87,
+97,111,138,61,204,15,122,164,123,213,210,40,53,36,22,92,139,99,3,203,187,128,55,15,221,43,118,225,236,50,
+29,30,217,41,8,185,146,17,38,178,232,50,248,24,229,174,230,111,220,18,171,24,132,221,116,107,115,155,226,231,
+150,107,34,105,244,203,19,22,110,218,160,219,181,129,141,178,67,152,33,31,218,160,70,88,32,154,2,252,39,51,
+7,233,120,177,192,38,161,251,194,158,147,67,235,186,148,38,177,15,142,200,19,66,124,237,90,16,160,82,219,223,
+235,48,66,232,43,103,160,51,44,132,113,124,237,144,32,161,199,44,191,210,127,81,57,195,121,80,188,121,121,41,
+62,158,21,63,212,119,95,67,222,159,73,3,10,57,78,34,37,13,165,131,129,234,151,71,125,50,76,70,16,178,
+48,50,195,208,245,66,51,32,76,204,152,199,103,19,62,213,236,29,1,75,168,214,17,81,65,98,165,56,104,87,
+140,18,132,114,112,84,170,71,165,196,170,81,73,35,200,213,197,192,67,207,10,243,185,157,161,75,179,42,79,169,
+230,138,196,177,142,80,46,28,161,174,88,131,113,133,186,90,186,36,171,82,87,53,109,107,251,25,220,168,148,82,
+158,158,150,53,84,174,87,224,99,35,222,224,77,32,32,218,140,117,208,74,181,37,139,125,159,59,158,123,122,121,
+90,102,38,94,71,113,182,18,156,9,33,70,156,75,139,43,113,184,18,146,174,226,134,250,79,166,143,250,124,24,
+245,81,245,155,18,252,20,101,40,59,180,25,90,164,181,200,99,94,233,56,219,133,25,128,211,60,91,17,147,144,
+91,205,112,186,134,214,37,49,126,50,252,44,153,227,31,107,175,54,227,236,38,220,248,141,4,214,158,248,100,202,
+167,174,226,251,184,201,142,226,173,62,141,186,214,150,171,116,175,28,58,195,206,82,58,37,236,166,69,81,128,159,
+210,40,73,82,24,219,235,227,68,3,128,35,67,52,160,131,185,110,248,62,42,166,199,14,71,140,59,207,75,162,
+173,56,233,111,7,104,160,176,249,66,174,205,140,219,67,180,33,87,134,5,102,88,144,24,81,206,80,189,38,55,
+36,102,91,231,166,133,167,39,226,73,31,168,250,105,159,232,185,72,66,156,60,89,71,18,72,8,18,171,93,9,
+21,93,133,126,18,30,179,200,40,160,160,232,78,66,219,32,199,16,195,164,147,70,91,253,209,86,212,223,76,49,
+79,209,204,169,11,195,164,64,209,10,134,162,161,65,154,6,226,82,165,81,234,144,237,116,129,176,133,221,108,161,
+183,123,64,224,88,205,106,161,28,13,138,184,218,161,107,137,31,245,179,21,5,117,210,248,42,6,174,7,205,149,
+254,131,227,179,234,120,206,58,234,121,228,214,121,28,37,209,142,123,175,63,227,242,232,108,2,5,226,164,227,82,
+222,169,88,241,227,132,57,215,252,241,173,87,103,199,199,197,173,215,64,197,230,197,191,115,189,63,147,249,85,156,
+197,52,201,18,154,102,41,237,102,93,218,203,122,180,159,245,233,102,182,73,183,178,45,186,157,109,211,157,108,135,
+62,204,146,152,62,202,146,132,62,206,146,148,62,201,146,46,125,154,37,61,250,44,75,250,180,64,236,4,177,83,
+196,254,64,44,67,236,79,192,94,211,187,60,223,136,147,180,219,235,111,110,109,239,60,124,244,248,201,211,103,27,
+244,75,129,11,243,93,126,192,239,39,253,49,125,106,190,122,252,126,218,139,201,238,110,111,28,44,177,95,25,98,
+45,10,119,254,136,113,110,52,63,185,219,138,175,96,247,8,111,63,85,103,102,58,19,211,41,156,109,198,35,53,
+240,188,0,83,217,219,188,229,253,190,249,55,146,220,217,192,243,8,244,122,139,5,54,253,17,44,236,85,150,246,
+251,247,103,242,0,127,151,54,246,147,45,58,179,144,84,67,38,22,210,213,144,34,211,12,20,172,167,96,72,115,
+157,41,254,91,154,255,14,1,121,74,132,97,63,28,246,22,134,49,200,49,28,17,108,56,129,48,213,237,59,224,
+77,0,107,137,59,90,226,150,131,220,30,143,149,104,92,85,172,69,94,58,22,81,102,29,125,41,178,167,197,210,
+36,247,239,131,57,2,169,76,172,154,153,110,38,36,64,219,14,129,227,72,42,43,227,175,149,45,223,47,173,220,
+134,124,88,196,230,229,128,59,59,43,179,143,91,110,242,56,192,169,116,127,45,231,48,130,177,30,50,246,33,229,
+251,132,198,20,164,187,155,200,181,164,235,40,79,196,42,101,71,49,197,235,101,32,79,28,226,191,196,26,182,64,
+134,108,177,105,244,122,86,228,157,255,171,102,147,98,244,221,251,94,251,222,65,24,68,223,127,140,3,226,221,35,
+163,131,239,53,29,7,10,198,254,49,208,27,101,8,239,172,32,200,8,184,126,39,119,59,214,54,191,91,103,238,
+103,69,196,46,217,212,28,182,89,14,58,59,247,190,183,155,187,34,8,10,124,156,48,227,170,60,64,208,64,145,
+67,216,67,156,140,192,230,21,201,42,101,59,115,251,38,144,46,25,211,26,219,238,152,150,216,66,186,10,51,46,
+85,227,4,201,4,161,181,1,246,20,176,38,89,77,104,105,128,155,10,88,146,172,36,20,130,94,64,132,215,16,
+206,37,196,46,115,127,78,244,66,169,103,35,113,25,112,127,160,153,189,187,87,16,148,215,244,22,182,179,166,157,
+168,246,68,232,188,39,127,100,72,186,158,18,176,196,28,28,208,117,222,81,61,47,70,139,163,139,201,226,168,62,
+39,202,137,174,11,70,217,15,54,91,227,180,123,171,144,198,135,255,138,11,223,174,188,131,74,223,57,77,37,33,
+67,107,122,37,173,224,35,224,157,110,76,238,37,41,164,14,11,133,191,154,62,85,216,165,59,97,69,19,66,195,
+196,28,242,14,106,47,6,46,222,54,126,244,200,216,90,248,107,113,83,58,94,166,192,7,72,218,4,73,155,74,
+16,243,229,26,81,37,237,133,37,10,138,151,114,132,7,185,38,188,46,126,36,174,156,119,43,114,148,222,9,141,
+250,205,147,174,186,41,144,1,219,77,192,207,117,158,116,240,11,161,210,207,107,202,224,131,52,111,31,93,245,246,
+129,47,232,126,158,132,50,100,20,251,65,46,237,83,186,125,196,133,48,112,111,88,171,142,202,8,232,205,84,175,
+134,222,68,245,74,123,162,84,79,37,120,156,54,138,26,72,129,14,168,72,39,85,19,86,63,94,54,50,75,72,
+168,10,230,125,148,151,97,133,247,217,187,176,107,56,234,120,105,8,223,73,6,61,28,73,231,57,30,174,217,200,
+19,97,77,58,71,129,39,134,245,104,51,139,73,134,112,49,242,234,144,33,60,205,60,240,46,246,122,48,102,238,
+111,198,1,216,137,30,204,23,49,157,46,224,163,112,76,123,40,236,205,128,158,78,251,121,20,175,252,185,39,97,
+105,163,42,127,49,81,73,6,16,53,132,168,151,149,247,204,41,119,151,162,125,206,71,9,111,75,170,96,238,115,
+89,177,74,246,174,88,33,251,182,134,236,235,42,217,195,178,117,253,209,5,149,225,255,4,59,150,104,175,85,238,
+254,92,91,238,84,169,147,230,42,10,43,20,22,59,181,190,154,194,19,32,148,100,239,77,143,44,159,89,96,22,
+129,178,15,45,117,149,83,171,65,133,253,158,234,27,135,163,37,113,167,0,197,98,99,36,114,176,133,122,46,36,
+217,18,81,159,35,226,219,18,33,242,75,209,244,85,205,67,127,204,160,73,112,33,23,32,83,23,63,251,166,169,
+236,166,87,102,150,171,72,30,48,24,132,115,196,54,144,132,50,228,169,126,225,86,229,8,131,206,12,58,9,118,
+38,208,73,157,48,121,94,152,171,58,222,126,253,144,138,57,50,83,49,34,114,88,238,80,11,76,56,213,77,237,
+99,216,178,254,66,169,196,250,203,84,45,21,215,247,176,169,85,227,214,94,36,91,67,69,254,104,202,238,255,138,
+252,234,242,255,73,54,107,3,6,162,24,134,238,242,106,79,160,46,204,204,169,194,204,184,126,116,185,230,155,45,
+169,247,23,171,249,227,72,76,197,41,253,236,58,17,143,53,49,22,62,185,34,70,98,251,32,134,226,188,94,237,
+223,103,98,32,140,255,114,79,70,172,109,250,226,122,34,122,54,238,204,122,126,78,228,68,210,180,37,242,34,217,
+252,36,186,246,46,68,71,88,207,253,125,221,59,87,16,187,61,209,246,212,149,104,137,185,87,53,61,236,197,13,
+179,179,169,139,255,57,27,81,52,160,23,212,196,114,71,148,132,185,123,71,217,105,67,86,82,32,67,86,197,119,
+199,143,171,171,224,115,220,118,162,159,229,207,80,146,89,46,211,49,44,22,114,87,26,105,164,93,119,19,59,181,
+157,77,211,126,249,190,25,57,247,75,107,45,232,61,129,53,163,55,10,152,240,126,24,38,158,117,62,124,27,222,
+255,123,52,209,198,248,247,183,169,159,59,156,30,179,127,48,11,73,193,113,3,242,151,29,1,97,75,249,13,141,
+151,40,110,64,112,9,234,183,221,74,122,72,21,92,232,110,164,109,21,43,246,128,221,132,254,164,117,40,61,42,
+235,147,53,223,255,187,209,92,255,44,240,217,102,232,89,203,157,103,120,86,235,202,255,251,238,58,204,239,255,221,
+82,238,66,142,234,231,251,30,38,85,57,229,4,180,27,215,135,253,48,176,56,193,89,139,81,122,122,49,75,235,
+42,182,129,12,252,64,227,188,218,77,203,64,141,48,131,191,38,49,140,243,186,205,2,154,92,157,201,222,154,88,
+25,1,189,60,139,37,140,210,73,93,182,85,96,37,167,110,125,167,214,91,177,199,143,221,102,26,48,18,246,89,
+89,8,113,32,160,100,251,175,210,212,58,100,132,149,172,130,155,235,23,253,57,70,138,113,214,70,136,111,232,0,
+83,90,73,82,188,122,40,59,52,70,243,167,37,119,183,116,215,161,29,187,166,150,118,27,186,121,56,147,244,107,
+140,246,124,221,221,7,109,94,85,181,203,35,152,43,234,213,253,209,122,99,4,251,7,216,115,219,22,185,247,128,
+43,78,173,181,108,18,223,67,29,109,91,55,36,248,177,246,101,163,243,54,2,127,37,230,148,182,96,235,4,233,
+168,243,88,34,9,196,80,79,224,5,170,250,192,25,178,203,196,181,176,136,139,191,191,205,159,109,183,151,234,193,
+172,108,19,158,238,14,210,181,83,167,113,183,209,158,235,86,146,98,116,125,130,7,190,73,147,146,133,214,72,139,
+216,173,220,216,137,140,92,46,27,152,245,213,217,162,217,24,41,26,48,195,106,154,191,249,12,230,229,185,117,90,
+103,247,108,234,84,199,70,123,185,161,203,201,93,13,50,147,146,64,220,14,211,188,244,98,145,164,206,181,74,147,
+27,241,215,113,26,153,160,66,96,29,181,53,72,0,201,115,198,164,236,243,61,102,145,99,204,163,192,147,106,183,
+67,31,14,47,246,75,184,40,49,47,222,169,91,135,248,184,228,142,122,153,37,207,149,175,188,18,55,24,100,41,
+83,14,43,186,251,171,131,212,78,173,23,129,68,19,106,139,186,107,186,127,248,98,196,140,214,161,142,116,196,223,
+78,183,218,194,196,74,168,125,175,99,109,124,84,133,188,132,6,252,131,24,135,164,98,146,32,124,37,222,38,102,
+27,106,128,20,37,201,0,32,85,118,208,104,7,76,78,17,123,225,119,226,28,148,250,133,11,73,64,186,179,214,
+4,204,157,162,211,178,197,114,87,251,12,40,201,17,152,76,67,130,147,28,115,227,114,82,156,84,99,27,31,162,
+224,36,200,166,177,182,109,5,162,239,19,136,51,252,214,42,50,227,75,14,32,116,140,216,130,129,23,186,77,16,
+100,82,62,197,16,66,132,139,28,196,37,128,168,72,172,63,134,92,82,141,224,115,25,164,53,178,97,229,63,89,
+15,235,218,51,17,56,217,173,103,100,82,240,57,170,42,46,0,183,187,113,251,18,206,40,26,195,14,120,49,176,
+240,174,104,50,96,141,183,198,213,54,4,41,221,142,151,55,90,33,82,43,221,94,104,52,114,230,61,128,6,153,
+234,164,201,42,91,97,96,29,247,178,192,107,160,180,89,219,24,112,151,179,95,209,70,87,99,184,85,42,77,243,
+225,124,90,214,227,144,129,25,188,167,233,50,17,14,253,244,116,79,63,15,199,96,226,64,172,156,106,24,175,102,
+188,38,47,37,28,43,113,143,44,64,82,34,254,72,136,63,119,112,133,179,33,135,201,111,86,35,170,80,158,224,
+138,133,40,19,161,14,98,130,67,208,217,246,44,28,99,44,132,96,137,18,165,2,178,209,181,86,177,184,129,98,
+192,166,240,141,35,216,53,166,45,192,209,150,14,180,127,176,85,155,34,87,160,30,63,219,238,98,20,130,201,181,
+32,194,184,147,57,178,85,17,129,146,12,189,241,14,96,189,131,195,152,201,48,3,13,251,23,99,146,81,80,61,
+44,115,40,246,138,63,86,46,192,127,11,89,215,69,33,218,75,22,38,129,156,79,7,55,14,242,210,229,188,44,
+42,96,14,103,186,174,102,117,43,19,48,17,243,203,244,226,102,93,89,101,176,224,24,8,100,77,147,75,141,158,
+15,169,70,44,169,172,209,235,49,52,130,117,85,35,112,186,13,235,181,234,187,10,1,68,247,176,39,184,201,84,
+121,206,2,215,247,97,132,193,6,9,205,79,34,41,192,100,213,93,77,149,198,254,18,85,176,78,2,22,65,117,
+130,166,126,72,65,68,34,166,19,129,198,6,134,29,35,174,172,109,46,75,217,44,11,5,35,107,61,64,56,75,
+58,65,246,193,52,195,91,108,93,100,11,56,108,104,30,116,5,44,74,24,163,50,135,183,25,85,117,114,69,13,
+54,23,179,158,62,6,136,21,7,7,47,29,37,42,91,66,211,102,184,19,170,66,194,172,31,3,222,24,201,39,
+25,145,134,248,201,137,22,207,232,191,199,183,237,29,206,150,126,123,254,211,217,64,255,236,255,122,198,214,171,229,
+72,238,155,75,69,143,135,196,113,28,252,120,174,154,30,14,255,61,157,47,71,120,235,218,127,191,124,64,12,199,
+10,147,30,47,15,114,154,29,225,12,163,49,108,37,172,240,177,245,85,255,122,192,123,218,225,163,45,141,242,173,
+238,140,33,200,153,75,89,141,183,210,175,233,123,220,5,224,227,143,179,250,223,242,121,2,57,155,50,242,247,15,
+226,190,132,187,109,91,249,247,171,196,122,47,167,164,5,169,182,239,91,41,195,58,105,147,110,255,52,77,235,220,
+237,248,239,227,75,83,144,197,27,154,208,37,225,218,174,163,239,254,230,55,88,73,219,105,223,126,114,98,17,131,
+125,48,0,6,51,131,193,121,52,69,66,251,222,169,216,199,191,49,127,253,14,70,204,239,148,68,143,197,59,53,
+103,235,120,235,217,89,158,29,8,254,119,158,7,206,251,157,58,171,231,70,191,213,183,222,122,38,152,52,211,115,
+109,116,76,48,246,152,96,236,49,193,216,99,130,71,1,4,148,75,156,82,88,172,151,156,204,84,106,15,233,44,
+11,220,17,162,37,219,175,120,214,61,136,138,91,68,76,241,103,95,9,195,26,41,58,122,21,80,65,241,201,165,
+181,167,140,214,159,50,90,127,202,192,209,37,169,251,84,15,180,230,117,176,127,45,123,152,173,100,6,118,101,34,
+53,180,48,125,20,64,82,143,15,168,187,16,48,31,136,146,187,229,241,49,182,241,13,38,81,39,146,174,127,103,
+156,183,182,216,170,45,182,32,60,117,133,136,144,152,211,206,75,9,81,33,97,46,207,115,72,98,185,213,163,202,
+15,119,185,112,41,233,39,167,64,98,122,85,62,109,9,133,147,95,55,89,178,88,174,224,211,170,187,175,80,214,
+227,75,10,144,196,165,54,188,101,157,251,145,15,38,58,206,44,202,56,219,25,133,226,157,57,242,178,149,166,167,
+114,10,37,83,203,89,154,36,36,226,54,100,21,242,55,251,243,3,126,114,193,151,176,46,186,43,26,47,247,77,
+23,73,234,149,220,219,107,119,87,84,56,135,162,181,118,146,132,163,33,67,115,99,4,92,133,210,162,149,164,67,
+235,117,27,144,213,219,124,232,107,72,111,219,188,163,47,107,2,253,100,141,203,239,202,164,134,34,124,238,54,234,
+238,115,217,190,127,46,91,223,124,46,219,183,207,100,187,174,239,178,129,196,10,81,11,12,155,7,193,132,146,82,
+194,14,22,191,60,74,93,48,120,196,192,116,164,89,43,148,104,200,28,172,156,29,226,30,225,188,156,233,121,137,
+215,236,178,102,191,178,198,125,77,145,53,211,138,238,234,29,78,9,150,147,90,13,66,166,142,196,91,27,209,207,
+59,150,154,110,246,233,107,218,237,235,121,71,178,32,2,95,5,240,21,131,175,44,248,50,128,47,25,124,105,193,
+165,44,9,84,78,73,5,87,230,4,46,5,55,93,246,65,186,75,132,170,91,21,81,132,55,219,203,218,162,6,
+152,217,149,205,118,67,168,10,9,2,166,220,28,177,68,182,227,171,16,170,139,88,82,50,164,12,118,62,243,146,
+133,119,54,199,85,71,107,126,85,54,42,108,18,38,102,17,74,126,192,4,236,246,231,127,154,154,249,21,233,214,
+254,59,253,94,238,147,98,53,49,218,239,36,197,73,130,75,101,11,213,91,98,26,255,80,51,166,174,25,173,186,
+42,205,147,109,72,170,1,118,103,244,43,80,157,253,190,18,168,214,126,95,218,162,88,142,161,218,136,44,44,201,
+177,75,71,194,35,11,146,143,207,165,155,249,132,125,73,209,104,222,51,73,15,99,145,234,247,211,134,98,59,109,
+134,9,127,46,147,132,62,85,98,81,172,179,122,76,33,181,23,162,191,215,108,125,147,46,106,95,151,237,175,101,
+255,109,87,174,106,213,210,210,255,68,228,251,210,24,213,37,246,140,170,143,117,80,153,86,223,206,21,39,74,171,
+250,185,52,243,208,123,146,152,206,29,126,231,135,249,60,89,60,92,123,255,245,180,241,184,105,159,2,39,2,123,
+21,204,110,247,76,52,185,141,134,106,253,182,169,77,70,198,190,209,202,217,90,243,169,212,154,111,58,13,26,24,
+48,41,237,249,2,86,185,250,156,248,7,252,60,213,134,167,12,161,191,169,71,226,85,191,103,196,93,1,86,226,
+174,209,148,174,240,161,201,132,250,234,247,167,127,149,227,253,137,201,32,188,120,40,127,213,245,138,158,75,98,232,
+37,73,151,174,216,156,143,61,221,201,9,107,99,28,119,67,184,158,184,100,124,145,253,179,73,42,27,249,31,232,
+81,7,134,132,171,4,184,40,238,0,116,248,168,212,251,250,78,53,191,160,41,82,201,19,101,239,193,205,183,77,
+105,240,126,28,94,39,125,61,74,151,185,77,79,53,234,90,181,73,129,234,87,14,158,89,59,223,107,77,46,19,
+132,253,214,55,102,18,252,24,76,140,190,169,54,124,171,202,7,56,237,185,45,5,222,84,228,195,186,188,174,27,
+226,221,191,248,78,17,243,111,234,170,36,158,240,70,125,33,94,68,8,2,175,186,186,108,232,163,47,219,126,214,
+171,174,38,102,26,86,204,208,160,179,87,152,98,226,124,0,9,216,143,125,199,94,255,138,195,249,145,184,181,159,
+24,127,215,126,190,130,41,31,210,208,87,163,1,201,236,61,47,154,37,237,120,176,242,52,91,24,160,81,150,8,
+79,147,63,78,88,37,73,216,122,253,213,93,221,75,184,132,117,32,163,186,146,233,84,62,92,235,21,122,137,205,
+161,39,140,114,92,79,20,94,236,29,184,174,92,151,4,164,255,175,250,45,193,237,96,239,57,146,211,237,119,220,
+109,224,193,67,190,198,64,37,16,112,243,68,239,33,15,29,50,175,234,54,14,60,85,188,37,26,167,227,115,72,
+194,219,78,160,237,0,137,121,250,141,190,125,91,183,49,199,170,43,111,95,241,155,220,111,28,97,253,212,126,208,
+219,24,175,250,170,171,47,177,166,130,3,202,146,169,137,185,138,52,86,243,113,133,200,104,74,169,92,84,190,11,
+37,140,179,182,54,35,240,208,213,171,71,241,255,50,54,158,198,218,32,210,106,173,194,18,19,107,16,93,8,180,
+208,106,77,46,38,83,181,112,235,141,53,204,119,55,27,106,213,103,90,60,208,145,168,120,176,206,6,52,76,143,
+111,187,218,148,151,141,226,161,59,83,20,169,232,94,154,234,28,76,160,107,190,226,134,183,81,42,65,84,178,59,
+235,195,241,230,183,172,201,151,195,163,1,225,28,62,206,138,55,89,35,170,124,39,128,190,38,127,112,249,101,179,
+219,225,218,46,152,208,239,36,246,158,127,149,217,195,5,112,181,181,173,161,205,103,175,158,243,140,117,119,199,248,
+149,143,11,166,76,159,2,247,242,38,118,9,152,8,123,155,249,225,98,93,54,205,37,139,204,19,146,157,236,68,
+18,42,6,85,237,29,198,98,17,162,150,45,162,225,112,114,56,192,101,171,191,186,187,11,185,253,180,107,70,190,
+4,225,22,136,194,252,95,186,223,233,228,197,132,189,190,81,132,157,250,75,255,17,162,184,52,74,185,189,123,49,
+153,250,242,18,183,174,216,17,194,240,91,131,104,147,96,94,211,14,99,33,178,158,95,171,178,191,233,212,7,117,
+103,178,62,159,179,95,43,161,216,192,158,194,185,208,39,45,31,42,116,46,218,228,81,175,228,202,82,43,91,28,
+233,220,189,170,150,23,112,247,3,184,208,20,184,42,187,203,242,74,209,2,210,208,120,143,1,196,23,208,77,222,
+150,151,84,26,29,28,37,66,65,79,22,128,203,5,54,185,52,56,150,246,229,175,42,195,135,5,45,252,229,164,
+192,137,167,119,191,194,83,202,118,115,166,100,205,113,185,104,112,21,97,157,173,165,194,181,163,245,158,187,187,249,
+109,182,206,247,36,124,140,116,18,120,117,242,136,117,188,181,135,20,57,74,170,228,1,140,171,125,85,213,49,253,
+167,66,87,114,125,86,157,139,149,47,113,239,219,108,5,107,159,65,121,171,60,95,212,88,159,140,238,84,22,253,
+110,104,87,26,157,6,168,170,155,19,223,145,252,33,182,253,134,219,190,82,212,55,245,162,63,211,212,254,243,133,
+102,38,164,130,35,141,155,192,53,116,137,82,214,140,213,241,181,127,191,122,188,143,130,111,217,131,56,32,42,200,
+191,60,130,218,190,8,202,208,196,188,63,51,179,62,223,39,213,117,59,237,99,117,117,111,89,38,35,193,3,98,
+183,198,53,117,208,220,228,104,5,54,196,15,161,1,18,148,249,224,31,134,101,16,159,40,240,112,38,243,15,181,
+37,82,250,181,190,113,145,34,96,46,86,89,213,227,219,156,206,231,88,120,152,220,204,217,173,206,41,166,157,216,
+80,16,204,48,242,138,53,2,37,169,26,123,166,152,149,204,54,164,116,207,247,191,46,49,12,85,184,96,90,197,
+227,56,211,108,21,174,246,82,187,251,244,90,239,119,31,126,124,251,61,73,185,253,166,113,78,87,137,30,37,176,
+252,112,72,145,231,15,9,105,199,199,110,169,75,0,56,214,125,133,111,108,74,92,124,86,137,89,5,4,129,102,
+240,105,113,68,223,14,42,170,128,182,132,224,220,64,238,192,210,102,246,98,201,154,86,171,245,177,60,160,86,56,
+63,36,36,236,81,180,159,190,167,193,134,223,216,252,193,59,117,168,231,101,87,161,89,98,77,227,243,103,148,92,
+53,186,87,156,114,232,43,163,171,249,202,197,132,242,128,153,250,160,51,53,13,22,212,171,124,127,45,218,104,112,
+141,112,46,86,83,249,115,11,249,77,221,254,223,72,255,124,99,59,48,33,214,147,211,164,104,228,154,78,158,244,
+50,104,41,215,179,70,104,25,75,153,86,42,223,47,69,39,125,69,1,228,16,51,211,84,107,7,15,22,179,191,
+209,255,31,114,31,49,237,40,66,139,6,64,177,138,96,74,63,229,244,212,153,152,122,214,17,24,169,9,72,255,
+255,246,59,77,159,20,24,77,90,42,74,219,176,211,159,127,249,112,120,113,68,40,168,231,136,167,2,75,209,210,
+255,163,125,254,239,10,216,17,254,42,149,98,128,74,210,114,128,180,180,175,28,14,163,233,250,154,167,248,231,78,
+38,16,215,191,4,226,186,246,153,14,85,157,238,123,110,138,107,94,0,254,111,54,46,52,5,105,198,205,77,27,
+55,246,208,211,253,63,171,88,112,151,197,255,135,110,34,234,255,72,55,211,66,87,101,191,73,231,191,104,7,25,
+134,117,181,195,217,235,105,180,158,195,133,58,54,7,119,86,249,43,214,182,147,3,120,14,176,143,108,101,121,122,
+147,107,124,113,137,175,55,147,92,140,175,193,35,211,221,9,100,234,107,51,83,28,34,37,67,199,44,23,7,239,
+41,210,232,237,204,6,142,81,167,49,250,122,170,98,13,247,188,219,164,11,118,186,88,250,25,103,235,16,92,154,
+112,85,204,2,208,150,58,227,88,59,21,234,109,186,163,253,106,47,198,63,181,217,153,38,178,124,99,193,68,64,
+237,252,78,168,249,61,223,160,231,173,135,116,153,171,70,77,226,9,1,247,217,166,148,12,194,199,144,77,11,67,
+153,68,18,70,33,59,102,127,184,152,114,13,111,33,123,144,36,47,67,42,227,42,43,6,213,27,84,63,110,80,
+210,13,21,186,241,187,157,0,126,127,171,233,76,122,211,49,25,181,75,226,19,182,135,119,5,126,142,238,132,11,
+223,219,240,61,133,21,71,20,138,147,249,240,189,13,223,139,199,141,249,143,38,226,84,104,98,68,131,189,108,122,
+139,190,148,218,81,92,32,65,15,224,227,50,78,27,19,207,119,50,199,57,102,87,251,185,21,211,136,26,189,215,
+185,176,108,157,247,248,192,183,225,113,116,106,168,50,226,50,6,165,83,216,19,60,179,49,114,16,155,139,191,102,
+131,214,225,174,40,163,210,6,229,48,82,248,162,248,48,80,113,207,53,24,62,27,141,120,204,186,167,99,69,139,
+214,3,88,161,15,237,148,250,21,37,25,139,39,169,182,110,28,87,232,153,27,64,49,199,34,175,147,70,177,234,
+105,8,56,60,71,31,35,231,70,29,12,140,81,2,5,15,25,208,133,62,88,100,57,40,162,193,139,190,106,232,
+16,138,36,49,36,147,24,159,236,171,178,87,232,25,167,76,1,114,24,159,116,180,29,79,79,59,230,31,149,217,
+16,215,124,181,129,135,12,190,191,129,124,97,62,142,78,103,45,206,237,6,202,131,202,220,148,13,46,156,172,136,
+108,232,45,136,183,88,63,74,105,166,79,196,253,2,244,139,70,170,167,50,190,234,225,235,71,84,82,61,149,245,
+181,178,209,27,57,106,238,210,106,43,142,138,106,49,164,190,4,185,227,5,48,161,58,200,72,42,221,241,208,0,
+66,221,63,138,155,72,39,54,201,106,83,34,244,228,154,190,169,147,251,193,15,52,175,197,125,209,138,219,162,23,
+155,66,11,203,189,23,221,78,154,69,96,182,176,176,50,174,218,228,59,126,17,15,246,55,177,119,144,238,70,216,
+17,103,157,91,153,145,40,242,104,41,244,81,50,145,6,168,212,31,70,229,78,251,144,156,7,8,5,184,162,159,
+142,28,65,6,33,42,253,224,81,249,190,143,156,34,45,58,66,7,73,68,242,121,32,102,227,6,167,200,243,226,
+243,190,97,41,204,47,234,138,174,27,102,100,62,111,37,152,159,178,127,95,77,179,101,241,239,115,250,205,151,121,
+182,189,251,164,174,63,145,241,59,153,189,231,66,63,147,171,54,101,83,87,159,112,15,191,70,176,221,168,174,54,
+159,110,218,94,25,146,87,92,54,176,152,204,94,204,150,103,7,179,255,126,110,255,178,57,126,142,98,163,240,165,
+107,134,247,198,179,9,201,72,96,228,204,174,20,155,156,205,131,105,247,87,206,78,215,137,93,131,238,117,159,132,
+174,11,127,226,145,83,5,29,178,130,162,216,122,95,220,222,77,138,40,242,7,228,229,132,28,26,73,152,6,91,
+222,36,20,84,59,60,149,13,212,34,211,154,142,144,177,153,247,237,160,153,144,115,180,18,142,83,224,151,101,57,
+244,149,82,24,161,41,174,206,151,237,178,147,39,228,172,9,198,10,245,153,161,31,50,99,38,16,0,69,150,211,
+71,226,13,163,131,55,140,62,87,20,39,203,38,211,240,158,246,196,69,251,215,169,74,135,155,245,64,67,93,224,
+37,47,102,80,10,136,115,45,185,49,16,220,10,96,187,116,129,83,227,50,206,38,142,94,38,98,226,8,11,159,
+97,86,196,128,141,74,253,22,53,38,181,242,70,251,18,69,31,159,98,165,101,154,166,142,135,18,198,29,106,37,
+51,79,4,182,69,167,26,123,227,157,165,200,154,197,82,44,138,248,142,183,96,103,61,254,198,137,233,132,115,48,
+178,112,167,124,53,208,175,171,104,52,162,4,121,192,112,134,42,54,55,175,124,134,127,41,127,75,210,30,144,95,
+235,201,79,55,144,252,160,99,186,81,243,219,178,107,179,47,190,111,89,11,205,239,0,188,224,140,47,32,254,174,
+215,181,90,21,47,38,95,76,219,233,23,147,47,96,132,49,153,4,59,245,160,120,64,173,246,83,24,247,145,167,
+26,4,154,13,72,18,33,194,36,1,168,131,172,26,66,57,45,68,235,245,13,200,117,235,115,220,186,212,22,11,
+112,66,236,199,195,51,47,146,100,158,61,37,72,174,94,168,145,252,5,18,242,104,203,163,229,129,232,162,123,11,
+125,220,17,163,163,33,130,43,89,11,38,202,61,233,228,242,176,44,72,2,110,84,202,212,85,12,37,41,101,105,
+103,207,30,238,3,39,233,191,205,202,220,198,159,169,151,165,171,240,220,37,140,181,4,231,71,24,181,158,50,180,
+243,170,172,54,10,2,94,155,52,33,208,102,32,61,123,184,174,91,194,28,241,66,69,191,147,181,208,242,94,103,
+70,100,61,174,112,28,97,219,230,87,228,228,9,241,12,165,187,235,93,78,27,135,67,206,221,101,173,152,5,7,
+35,58,207,185,180,14,247,5,210,77,239,221,208,145,219,80,124,62,84,24,214,185,48,233,225,161,245,77,230,179,
+79,230,22,141,99,227,232,55,12,197,236,16,102,84,206,9,201,162,157,245,39,135,139,92,203,126,218,146,73,148,
+80,112,58,213,75,93,180,82,251,246,55,26,155,110,93,180,222,157,225,219,196,53,33,234,5,17,160,186,246,156,
+56,230,99,149,139,170,249,76,130,19,169,146,229,124,19,80,29,212,168,161,169,174,137,199,52,90,200,123,108,22,
+121,59,157,90,104,127,210,2,218,207,14,207,225,240,168,159,205,194,245,160,147,3,226,183,142,125,33,75,239,173,
+8,188,89,112,113,247,147,38,253,32,132,224,112,233,165,183,244,183,223,212,188,104,89,185,42,125,220,180,22,116,
+30,27,187,110,130,102,184,158,95,56,87,157,20,12,223,52,247,122,163,90,213,245,86,194,110,130,228,237,41,237,
+203,61,148,180,62,43,251,131,110,215,245,213,77,80,179,164,74,151,67,231,12,250,33,212,128,227,201,110,151,139,
+159,244,156,48,242,134,104,57,83,242,36,200,123,39,23,186,125,13,151,203,211,43,190,66,98,93,186,45,158,107,
+135,250,67,213,195,47,166,142,231,164,62,117,120,169,195,34,254,20,62,66,27,75,106,163,159,226,52,168,195,89,
+14,136,173,131,58,214,81,239,6,155,80,63,220,82,99,53,118,207,31,251,252,82,177,118,108,186,222,253,22,6,
+165,223,131,93,14,57,203,242,98,244,30,215,220,246,178,214,91,145,29,96,73,73,48,171,169,213,78,4,143,213,
+139,90,231,67,161,17,169,83,20,157,110,112,96,135,78,149,219,133,68,251,57,215,123,52,215,87,171,12,3,21,
+144,105,55,43,190,61,86,23,214,70,110,221,233,235,44,157,252,183,60,249,137,162,39,112,202,84,227,24,194,142,
+180,97,46,151,63,92,154,12,7,39,88,142,233,108,18,116,97,19,56,114,9,14,224,30,206,78,217,9,117,144,
+112,127,40,175,206,139,137,37,151,137,184,8,107,37,40,227,130,157,230,246,69,45,46,58,173,205,169,13,41,17,
+245,108,173,184,184,34,49,127,217,209,223,162,23,94,165,9,94,134,26,123,214,9,26,228,250,220,237,31,97,183,
+1,166,136,38,239,238,51,45,28,186,3,137,118,162,12,235,162,195,125,7,173,163,255,158,95,128,155,242,65,244,
+28,177,80,96,82,19,6,185,223,104,4,5,16,116,215,240,195,159,181,232,242,156,19,38,78,223,94,43,171,15,
+212,221,32,247,47,106,221,96,6,61,159,120,238,208,131,227,108,105,139,125,239,29,203,17,249,61,85,82,26,143,
+166,83,174,77,217,15,234,213,20,204,163,155,97,20,172,111,233,234,207,61,224,105,34,167,88,69,23,27,79,132,
+149,68,171,168,117,229,21,54,135,24,144,125,22,153,70,224,83,86,248,211,140,208,10,60,166,83,177,123,194,89,
+209,67,66,35,80,159,110,49,144,32,17,231,72,173,48,68,55,55,151,239,25,172,232,219,128,80,236,228,160,168,
+85,192,96,95,124,208,84,60,46,25,7,61,82,65,19,144,43,213,92,105,32,40,15,159,123,64,166,243,231,169,
+170,127,68,85,90,116,99,170,210,96,190,3,25,117,145,134,180,24,81,17,0,160,162,155,198,197,125,142,134,210,
+154,244,60,237,238,156,38,13,198,113,233,9,2,67,15,146,92,142,212,238,163,5,122,87,88,206,166,248,93,146,
+68,97,255,243,116,232,136,48,109,248,184,133,145,6,31,37,241,17,40,166,31,99,143,17,43,75,145,160,124,76,
+98,76,3,70,62,216,78,120,20,36,58,249,3,47,176,27,40,238,33,165,137,193,84,137,223,82,140,11,33,194,
+33,189,232,9,236,190,119,178,246,60,79,136,21,105,217,34,41,77,212,253,105,140,250,6,158,185,150,138,207,104,
+138,162,190,247,9,17,211,230,203,150,99,2,7,181,106,188,231,195,122,89,99,131,230,67,224,199,214,67,113,80,
+36,246,6,194,197,114,85,110,97,73,3,30,24,171,241,227,129,50,121,244,174,60,79,140,188,8,106,51,36,236,
+214,27,157,88,142,255,33,175,151,104,80,30,70,205,156,135,237,21,106,197,4,46,219,212,128,224,102,196,65,187,
+213,160,141,171,65,159,172,6,122,56,253,59,12,4,118,203,82,182,168,209,155,192,24,230,244,187,121,138,249,204,
+88,230,255,10,254,57,113,235,24,174,189,236,145,192,159,5,56,126,235,227,145,61,140,78,158,19,210,17,97,11,
+233,84,86,66,24,76,50,94,170,23,155,66,122,42,184,10,82,190,81,175,250,216,43,157,244,170,243,107,92,185,
+147,10,44,74,105,231,77,158,67,206,118,203,235,210,155,174,163,249,57,249,69,225,33,24,84,178,82,134,198,132,
+143,134,211,100,183,47,243,249,63,117,221,102,147,217,201,36,159,226,239,52,30,154,75,203,53,228,194,72,204,51,
+120,121,163,134,207,237,228,2,252,163,21,70,176,21,253,143,109,214,251,29,138,250,10,248,192,242,125,251,63,223,
+203,100,236,66,95,137,233,240,190,128,137,205,226,78,75,115,230,64,47,141,63,166,37,206,145,13,246,189,196,170,
+72,84,50,52,20,114,71,163,186,108,35,79,224,206,184,201,23,176,17,73,100,33,27,200,66,194,118,183,70,47,
+43,238,221,134,146,90,94,156,6,119,141,3,42,81,16,156,193,98,181,14,178,156,216,253,95,194,4,137,84,7,
+227,211,12,176,112,124,184,142,243,87,194,122,100,105,138,199,110,174,151,63,24,246,25,235,150,233,56,9,47,7,
+226,226,216,9,141,78,152,200,94,95,55,252,74,47,208,9,7,188,24,101,250,8,86,47,212,212,110,30,88,46,
+161,168,48,135,121,166,126,194,147,178,63,109,238,9,101,231,209,221,161,217,196,0,83,226,150,18,171,52,21,155,
+34,122,183,170,17,51,132,210,71,123,190,153,39,12,160,208,104,146,25,52,137,133,218,103,96,246,192,241,225,162,
+78,96,135,45,213,186,139,64,141,236,123,188,213,71,89,200,124,9,249,60,113,55,97,113,3,73,81,91,181,237,
+88,22,178,104,209,160,30,159,48,95,238,29,22,196,100,14,102,143,96,222,152,154,200,27,246,69,227,157,35,196,
+238,245,253,120,80,22,106,145,43,153,14,214,83,226,181,139,230,177,165,77,228,125,51,34,191,23,53,225,20,252,
+55,86,201,135,93,20,242,164,139,219,183,206,231,51,239,34,125,226,171,161,25,137,89,22,143,232,5,250,6,176,
+246,43,176,33,53,203,124,8,85,125,88,181,121,246,247,249,146,6,16,189,192,119,90,195,87,238,66,207,200,205,
+174,51,128,86,99,71,207,45,59,81,118,132,214,70,169,74,34,197,208,125,116,72,86,91,6,50,156,102,8,15,
+1,40,239,169,115,126,138,15,87,33,196,60,58,65,61,246,4,28,1,237,248,85,14,149,251,69,163,39,179,193,
+126,96,54,120,49,201,115,119,214,138,132,54,60,91,217,82,127,109,188,103,223,55,239,79,191,127,251,211,187,79,
+159,14,213,140,124,97,149,42,184,183,15,146,6,146,43,97,35,156,247,31,107,122,115,12,159,226,123,29,30,126,
+184,155,44,73,186,90,208,239,34,158,219,154,199,83,170,230,252,112,228,139,107,39,162,147,202,3,20,222,45,173,
+105,140,225,249,19,95,157,208,118,246,84,178,252,50,43,167,252,62,112,99,191,22,149,180,118,62,85,78,210,168,
+138,34,108,112,131,224,102,225,215,201,118,191,18,43,250,187,241,140,207,182,35,243,48,77,170,21,82,185,104,114,
+127,186,222,207,58,250,233,73,107,44,238,9,114,207,16,250,233,161,76,21,45,182,3,155,116,186,26,39,5,36,
+36,77,232,227,227,227,41,147,26,240,37,175,71,202,82,81,210,131,104,103,191,33,221,233,230,184,157,29,210,113,
+121,3,202,111,100,229,147,109,166,124,134,223,163,165,98,175,202,153,124,111,21,109,43,36,12,60,16,191,54,4,
+81,244,77,228,75,9,207,169,28,79,216,187,94,34,226,75,78,169,109,188,11,149,209,137,114,63,240,2,171,41,
+68,117,149,199,214,181,87,39,255,244,101,116,94,88,230,130,107,234,247,187,125,46,198,85,169,93,56,149,248,253,
+232,112,1,2,137,248,248,94,59,145,77,138,23,135,149,71,56,169,208,23,190,112,80,113,167,59,89,82,195,27,
+159,178,98,180,148,227,121,188,145,37,76,125,215,244,211,210,42,4,205,179,204,54,179,142,128,57,57,166,46,207,
+254,65,122,115,184,246,248,199,185,220,204,116,0,180,0,172,103,154,122,82,225,29,64,155,177,161,108,179,77,200,
+120,228,51,78,117,0,216,140,83,151,49,65,193,43,70,65,138,0,5,4,152,60,145,144,16,46,236,189,192,150,
+167,117,3,119,71,58,128,24,61,79,145,140,245,96,15,217,74,7,98,1,86,18,130,233,24,51,123,13,99,141,
+112,231,17,83,209,212,157,53,88,156,123,28,83,54,108,29,153,85,232,98,195,232,217,20,7,59,141,168,114,89,
+45,127,52,25,37,35,57,100,78,233,108,224,28,147,204,65,167,8,67,153,106,131,5,130,59,158,1,61,191,195,
+138,47,45,76,234,80,103,236,152,250,89,31,106,201,173,204,230,209,83,16,162,195,122,97,88,158,64,81,159,19,
+59,117,82,11,205,84,67,16,200,197,56,155,154,30,34,35,216,97,255,32,68,135,79,54,176,144,212,74,251,37,
+130,129,75,231,180,8,0,223,135,4,247,193,30,198,42,109,192,84,187,98,142,66,49,71,79,23,115,116,31,18,
+60,46,38,125,8,97,192,81,37,147,5,251,20,46,236,148,237,183,229,182,135,74,95,214,126,95,168,104,95,168,
+120,113,205,217,130,0,46,115,191,111,41,102,171,173,249,193,143,122,229,252,197,183,218,232,86,77,114,144,170,127,
+210,131,171,169,32,150,59,243,8,197,248,2,221,159,211,128,56,245,71,35,105,241,175,112,34,57,11,163,170,167,
+135,162,155,101,237,146,175,229,190,236,216,26,66,181,61,155,56,148,22,237,205,220,175,208,243,59,11,187,79,97,
+247,12,59,66,58,44,205,156,6,200,243,225,123,208,254,142,58,91,110,191,98,251,154,247,48,145,37,196,48,1,
+165,54,13,223,232,103,158,137,26,184,247,15,234,154,149,174,110,96,214,58,136,77,230,120,155,178,4,246,190,244,
+59,66,111,114,189,212,36,198,181,169,229,236,233,166,164,90,127,209,218,156,91,175,141,102,14,23,35,3,118,97,
+93,15,180,8,161,212,199,60,121,214,70,253,94,13,253,158,136,239,50,224,41,26,39,24,166,100,173,125,135,38,
+105,44,230,62,252,60,213,194,251,163,190,173,177,191,91,188,88,171,231,235,237,141,81,43,54,145,160,242,71,55,
+203,222,55,169,122,135,114,19,82,144,205,159,184,255,2,25,123,228,62,94,55,146,213,172,120,35,127,160,95,165,
+143,70,13,85,19,255,246,200,224,155,76,246,149,84,203,201,108,50,85,164,210,11,219,133,189,68,255,159,112,123,
+62,154,162,188,110,112,129,0,215,230,101,234,60,255,204,76,145,95,79,169,231,164,222,14,119,73,157,150,182,181,
+90,218,214,105,105,91,175,165,109,49,83,9,108,91,27,176,245,83,162,22,202,106,168,105,140,21,180,67,95,191,
+167,230,125,24,233,4,103,111,155,177,212,191,197,51,184,148,163,230,87,95,248,226,150,98,9,63,228,249,78,233,
+3,91,162,66,137,7,189,94,247,202,252,173,208,194,126,253,29,194,5,107,245,109,95,38,21,213,2,146,16,43,
+193,163,210,152,107,207,243,70,106,220,103,225,137,30,246,5,150,188,120,3,154,175,27,220,120,100,171,117,218,127,
+36,173,81,12,248,219,108,99,215,177,42,128,254,78,32,172,92,84,161,199,32,113,76,13,241,72,149,184,212,119,
+69,153,236,133,191,233,212,234,165,98,131,113,234,199,51,166,251,69,187,147,134,122,78,132,164,176,31,246,115,42,
+239,180,254,141,154,135,25,228,30,19,38,216,68,116,146,40,164,23,147,109,185,66,235,241,8,190,133,184,84,68,
+82,60,166,20,49,104,220,102,39,121,4,168,252,181,236,236,120,103,196,234,150,252,137,167,242,59,116,206,194,240,
+101,31,131,229,178,138,27,97,9,162,216,238,162,251,62,108,39,55,51,202,198,105,166,165,253,21,91,128,108,114,
+130,217,15,110,75,122,249,160,153,173,243,47,111,246,149,179,128,111,193,104,166,241,213,108,149,127,185,165,120,155,
+159,18,36,184,253,48,84,53,10,123,215,91,122,5,49,29,59,195,119,156,24,188,112,33,225,158,206,141,172,221,
+144,178,89,147,80,33,108,213,237,41,181,116,82,63,71,45,162,196,128,193,16,16,35,80,62,49,2,149,139,8,
+131,181,48,30,95,179,202,253,54,14,111,42,160,141,162,220,71,227,62,68,43,105,101,44,131,21,159,208,98,18,
+59,128,154,250,144,192,118,33,166,176,225,73,16,146,184,33,53,126,72,149,240,165,22,116,184,237,106,17,202,40,
+122,132,189,168,243,55,94,34,147,65,130,103,85,56,97,77,132,146,79,28,131,120,109,20,218,209,232,53,77,203,
+186,165,246,118,104,111,31,59,84,143,58,196,45,41,67,34,215,169,122,220,41,78,214,200,64,17,9,205,86,174,
+131,160,124,102,31,70,147,138,101,96,173,225,89,21,228,77,207,77,165,213,120,214,45,170,153,92,57,202,95,187,
+17,220,0,228,40,127,237,62,252,74,91,165,174,60,170,153,182,89,114,177,73,225,237,50,121,222,165,34,162,47,
+136,97,15,83,168,146,191,213,145,115,172,68,39,154,212,232,115,51,136,222,128,105,138,152,163,248,138,142,181,16,
+161,34,29,21,126,68,160,199,152,74,52,67,253,120,31,162,35,63,76,14,146,38,214,174,109,251,80,228,12,35,
+184,100,130,47,124,26,217,127,217,10,7,151,250,75,175,221,5,99,101,87,199,160,188,178,86,57,212,82,108,38,
+46,228,10,161,46,56,128,195,31,165,26,166,144,255,128,199,88,135,251,237,221,63,196,32,61,199,218,79,68,230,
+226,217,203,84,196,62,96,54,184,146,40,212,35,196,57,41,160,151,217,179,57,101,43,186,208,103,209,249,30,163,
+42,115,55,31,220,153,106,249,150,53,255,205,97,199,135,251,137,22,45,191,52,143,223,108,164,167,145,76,119,31,
+100,41,15,87,4,221,150,61,174,201,38,175,55,194,122,7,215,28,23,142,153,33,130,125,131,75,148,111,157,10,
+61,155,24,190,214,107,111,227,230,194,37,235,248,126,245,231,82,238,42,152,70,61,196,155,237,233,27,145,229,72,
+165,239,24,36,209,66,194,167,172,85,21,108,8,97,105,152,57,131,195,237,29,236,1,61,39,178,156,194,74,216,
+137,88,19,231,154,38,46,41,97,203,173,97,254,190,239,95,117,161,189,131,32,247,128,184,55,93,210,205,226,171,
+230,15,21,208,38,134,246,75,5,87,242,245,28,54,233,136,241,182,243,136,56,12,112,117,114,176,196,47,133,147,
+234,190,127,98,9,68,133,246,104,116,111,63,238,119,66,3,202,150,239,128,242,7,65,59,201,253,237,177,75,151,
+248,238,133,198,119,131,111,45,12,190,43,124,119,162,196,247,6,223,56,45,171,128,72,2,224,218,164,242,188,103,
+211,179,212,237,199,114,187,136,71,130,38,185,229,71,236,101,96,201,166,63,156,254,244,206,89,138,213,235,251,44,
+24,29,53,61,54,193,44,84,99,229,160,92,50,49,224,205,220,10,215,190,129,137,166,177,35,79,57,122,228,32,
+68,12,110,164,190,25,29,138,209,24,4,231,107,151,57,247,251,77,156,2,200,17,71,47,139,121,235,105,61,53,
+51,5,197,164,221,56,16,103,36,1,130,53,120,146,90,165,143,166,170,2,65,199,143,143,94,88,221,137,187,247,
+205,77,143,198,199,204,179,118,39,144,138,58,249,214,116,143,226,118,59,241,93,210,226,164,185,117,108,110,108,40,
+160,105,43,211,68,174,246,244,132,65,221,76,107,31,198,81,221,113,108,251,49,126,235,229,111,22,195,197,119,77,
+106,212,255,157,30,72,26,22,204,65,77,26,131,55,75,249,179,51,205,132,221,221,135,37,218,217,77,182,242,76,
+61,62,237,76,86,117,167,220,235,157,98,16,255,190,171,117,87,155,251,65,146,115,74,211,199,52,105,28,53,127,
+82,95,111,117,103,202,214,80,97,53,31,139,97,91,255,218,167,145,109,210,147,127,186,158,152,212,18,209,43,254,
+31,231,21,195,238,60,219,138,224,136,57,21,80,252,85,143,94,195,157,216,123,146,203,135,75,101,110,149,106,139,
+215,74,84,250,26,135,205,226,167,82,88,171,101,88,110,174,205,174,8,137,126,50,33,81,102,207,81,68,198,73,
+98,67,128,100,85,169,250,236,129,229,222,69,45,84,187,42,144,251,166,5,239,214,104,189,45,90,103,20,218,239,
+124,211,124,234,151,202,166,127,233,83,226,224,61,171,73,94,246,18,228,127,16,50,38,216,28,105,124,183,14,55,
+92,11,10,237,185,72,189,147,74,132,254,116,73,219,203,157,36,44,177,34,199,36,98,79,215,164,138,115,111,108,
+115,214,176,194,92,137,27,176,103,107,167,185,152,202,70,108,240,103,69,205,187,33,214,109,117,124,67,170,190,172,
+204,72,222,248,178,57,39,41,103,206,34,55,146,194,172,242,106,54,19,27,178,25,172,94,34,27,253,241,251,211,
+230,184,162,190,162,160,92,60,89,181,235,186,51,6,78,109,55,131,230,48,181,70,131,174,228,247,17,210,133,46,
+139,7,63,192,165,240,88,106,18,44,85,22,75,161,113,27,46,100,109,27,183,114,141,187,217,201,48,28,98,11,
+77,41,102,235,53,14,188,151,214,159,198,133,184,19,31,221,2,126,203,182,98,77,214,139,143,226,2,154,67,124,
+65,16,66,82,115,142,42,51,77,17,246,209,173,134,190,145,76,220,115,212,245,167,79,183,89,46,94,113,96,143,
+66,191,102,81,48,125,42,55,226,181,220,44,78,143,229,154,176,126,154,223,73,115,118,10,185,214,222,157,211,146,
+100,23,178,202,238,120,108,46,168,198,143,4,185,150,77,118,193,35,69,141,245,111,44,223,103,88,82,46,101,137,
+40,110,202,242,180,120,77,41,246,124,138,87,156,98,107,117,189,145,240,47,25,63,167,14,63,142,254,187,128,167,
+60,119,24,201,169,165,167,226,163,188,136,230,80,177,236,103,74,93,127,166,212,109,226,173,111,244,210,29,156,27,
+64,205,163,174,216,189,200,72,48,227,69,24,67,249,12,17,23,188,224,99,77,99,129,29,4,186,58,232,157,20,
+183,207,25,78,62,86,81,254,117,172,67,132,253,175,52,179,67,204,31,69,204,113,155,187,199,114,13,235,176,122,
+171,195,90,228,212,132,69,140,121,34,162,127,41,169,92,251,222,94,79,45,58,233,145,76,191,52,62,161,142,118,
+185,26,105,31,6,164,159,206,158,39,85,97,110,78,104,79,194,29,21,81,74,86,173,53,22,111,210,76,15,233,
+54,157,84,68,96,209,220,141,146,52,47,123,154,121,220,140,79,159,232,215,232,237,178,116,193,172,197,84,208,22,
+107,174,73,230,165,109,84,214,204,104,149,235,221,186,7,23,129,178,147,46,127,83,48,169,20,112,238,32,74,79,
+194,70,54,57,248,174,202,163,190,11,132,243,116,21,93,90,188,78,8,101,36,234,10,131,13,114,209,91,164,233,
+131,44,59,117,55,133,5,167,247,11,206,121,176,233,220,219,35,237,42,42,242,104,239,184,122,44,180,176,44,176,
+15,11,35,115,203,70,12,185,95,2,123,220,239,24,102,177,237,213,59,218,126,65,122,222,72,163,60,238,150,229,
+180,167,248,202,214,182,166,110,191,165,164,180,242,98,146,90,123,248,158,40,45,45,251,29,106,239,32,123,203,69,
+250,66,55,162,199,92,247,94,75,167,185,118,30,45,1,41,168,150,166,248,123,160,151,84,115,242,152,136,130,149,
+112,234,148,130,223,84,236,179,128,84,90,77,47,210,23,173,169,215,46,166,120,240,248,38,180,97,215,105,2,214,
+69,229,169,18,199,180,53,59,215,183,90,102,177,162,245,46,154,66,101,91,113,45,46,197,133,111,211,157,44,151,
+179,195,130,103,223,150,72,229,218,238,96,219,41,109,90,234,108,251,178,241,147,135,68,98,119,76,229,4,190,142,
+224,235,41,129,41,25,101,37,40,46,156,12,168,140,98,120,204,40,206,142,218,165,91,151,46,118,224,252,47,196,
+26,217,112,214,9,202,243,173,83,248,175,169,101,235,98,107,123,225,246,12,117,182,166,170,197,37,55,132,58,70,
+211,109,117,44,183,115,170,98,177,138,75,212,5,37,92,81,194,197,37,48,155,14,88,246,14,231,17,182,249,46,
+38,110,209,155,136,237,65,113,45,182,135,197,5,125,193,76,221,226,61,91,97,242,53,20,17,97,43,10,15,7,
+103,135,231,107,255,220,100,151,2,39,249,155,108,45,40,155,216,206,209,91,2,137,107,234,228,70,94,238,214,199,
+4,127,34,65,16,174,36,10,132,196,39,221,195,200,163,22,237,245,35,136,112,14,180,202,237,169,99,6,134,0,
+23,255,186,236,55,33,14,129,4,254,19,139,163,67,108,4,185,52,63,232,186,77,10,79,33,34,185,18,143,216,
+24,114,49,161,213,49,180,75,222,216,112,171,76,212,188,140,78,111,53,246,254,71,39,186,157,123,236,236,107,158,
+76,255,236,95,252,250,167,249,127,157,31,166,239,156,221,222,222,206,189,225,191,238,174,146,135,205,142,98,54,80,
+69,87,95,222,192,90,236,15,62,112,198,14,236,126,110,6,14,236,130,207,81,69,215,6,123,19,189,132,185,233,
+30,142,175,14,216,221,180,45,251,14,59,116,0,42,212,16,145,121,231,96,187,139,86,27,244,116,236,87,43,189,
+70,128,29,184,35,192,234,198,222,110,93,232,244,90,67,153,61,112,213,133,17,238,150,99,161,230,238,75,144,33,
+239,169,81,132,166,206,11,243,17,44,162,119,222,153,114,139,71,151,19,125,239,168,99,235,78,245,155,113,71,105,
+243,26,117,232,64,12,49,113,161,173,225,166,149,208,176,189,147,43,226,102,187,98,7,152,226,105,212,197,66,73,
+25,135,96,108,3,90,228,179,27,9,180,205,91,77,140,159,59,6,18,227,146,162,62,32,5,119,110,220,235,222,
+180,134,187,194,121,61,175,141,186,238,221,66,58,188,183,161,165,139,117,27,190,142,247,150,172,198,198,174,136,221,
+9,85,58,155,117,121,35,217,122,184,153,95,148,236,181,109,153,209,167,209,166,108,78,218,48,80,180,72,198,128,
+244,9,114,202,101,200,197,92,102,176,125,67,144,150,161,44,42,48,86,122,46,180,125,114,58,95,64,107,109,253,
+195,5,20,58,154,233,69,139,195,231,182,211,87,132,175,126,146,231,194,151,0,102,99,62,34,190,113,62,112,252,
+56,117,78,114,209,122,130,177,215,220,166,161,251,187,124,76,183,70,40,247,176,246,152,194,243,29,12,208,94,181,
+245,117,159,186,71,77,135,200,201,103,20,139,103,204,72,60,243,224,138,34,185,98,160,100,34,51,30,149,130,184,
+215,120,5,233,193,55,29,96,223,125,250,222,237,236,49,61,51,78,142,99,179,216,201,229,40,58,109,99,50,197,
+212,185,127,38,124,7,251,44,62,80,89,253,96,192,232,227,236,220,180,192,4,171,124,7,67,219,100,141,123,58,
+67,184,236,179,227,153,247,28,174,60,142,208,138,76,205,147,137,231,166,108,50,33,132,138,100,166,92,45,157,90,
+221,84,202,79,134,32,183,111,5,213,224,19,231,16,229,142,38,93,190,115,85,101,222,25,105,58,206,241,225,251,
+207,181,217,37,114,26,214,100,10,170,225,20,220,129,191,253,61,4,212,107,95,206,243,211,55,116,219,251,139,11,
+51,201,157,36,236,188,237,249,129,47,8,84,42,213,208,145,209,101,194,217,136,107,78,87,227,136,221,116,170,236,
+172,232,57,29,229,180,201,206,248,217,56,135,130,239,173,17,225,207,141,107,230,170,151,147,196,117,251,68,124,219,
+200,135,75,173,27,85,182,99,95,50,120,234,203,20,245,78,176,55,137,177,122,67,245,25,93,56,94,245,185,64,
+103,249,174,47,29,200,136,200,0,12,19,139,206,69,189,141,92,246,180,222,99,244,213,192,101,109,97,118,162,101,
+105,232,88,14,55,133,228,5,15,241,239,22,118,39,252,183,225,78,248,120,195,130,65,87,47,47,85,118,6,155,
+10,230,243,13,27,54,6,199,244,157,139,5,80,80,10,138,0,246,252,26,26,55,149,117,43,41,21,45,11,223,
+54,40,236,126,75,227,239,172,42,58,63,84,170,100,175,156,31,21,165,176,223,228,227,246,163,154,219,135,178,93,
+34,158,40,169,174,39,142,42,117,16,195,85,222,195,7,155,159,5,97,22,33,232,214,235,52,187,9,243,204,231,
+0,115,71,135,16,51,199,135,131,89,117,190,84,46,8,17,76,240,143,142,190,203,206,39,212,178,143,137,174,235,
+94,245,158,49,0,74,82,85,73,138,168,157,223,19,131,79,155,52,54,127,24,208,242,222,97,52,253,77,155,119,
+22,27,7,251,195,118,150,96,76,116,114,136,143,153,94,164,8,109,71,232,74,81,20,86,154,78,36,216,202,69,
+130,209,169,212,159,195,158,142,68,164,68,31,136,40,65,96,74,71,189,80,176,235,243,115,250,33,69,133,223,165,
+120,187,77,248,7,145,38,194,254,56,198,88,190,227,44,233,202,52,192,79,59,194,143,232,101,68,39,97,51,54,
+53,160,146,123,88,6,194,178,246,231,139,209,216,73,168,242,176,227,119,100,23,112,220,230,98,111,52,178,233,0,
+246,231,178,28,181,252,32,245,185,167,142,15,30,231,208,62,65,35,213,151,237,203,35,209,224,133,193,230,228,112,
+121,52,107,138,134,130,233,244,138,42,218,67,145,168,126,27,28,133,198,37,251,169,155,105,190,3,184,187,45,107,
+51,118,123,30,200,28,12,101,10,192,26,156,143,174,206,1,158,57,191,192,15,198,157,54,59,190,242,217,169,127,
+22,45,223,211,245,93,79,135,106,57,161,84,208,143,252,15,246,254,181,187,109,35,73,0,134,191,191,191,194,230,
+147,103,23,109,54,101,201,153,204,238,130,110,243,200,118,156,120,198,113,60,182,115,27,29,29,13,4,54,77,68,
+32,192,1,64,73,12,23,255,253,173,234,174,174,110,128,160,228,76,102,191,61,39,177,136,190,223,171,171,170,235,
+162,127,29,201,98,175,229,179,243,187,152,95,120,67,0,58,16,9,39,74,240,51,202,67,221,142,36,90,169,24,
+5,100,15,132,172,61,24,248,32,121,185,209,185,252,11,230,54,32,155,115,191,160,80,143,156,3,57,170,111,13,
+182,50,98,115,216,35,185,51,32,137,30,22,165,219,94,241,137,254,82,218,21,137,71,161,127,252,145,92,20,46,
+51,238,54,247,141,155,205,125,55,37,127,1,8,165,111,214,7,248,103,222,113,145,242,173,183,205,45,160,123,108,
+52,184,211,71,175,112,219,55,88,43,89,41,46,48,139,91,22,239,44,142,134,218,100,20,243,130,110,84,23,179,
+40,70,173,216,155,15,171,158,158,163,134,15,81,242,52,179,107,54,36,28,255,37,167,43,204,103,50,193,110,174,
+159,243,182,61,48,160,186,51,34,142,15,59,100,238,236,204,101,182,135,49,222,113,206,120,199,11,5,126,211,218,
+86,86,26,181,167,135,115,96,58,154,127,14,82,235,152,71,105,22,177,131,35,180,242,58,171,51,156,79,26,29,
+225,11,35,25,86,217,202,101,54,215,195,117,54,229,103,214,200,91,204,222,161,102,115,225,34,254,47,54,208,10,
+66,4,126,41,251,136,128,216,5,72,144,106,164,13,241,236,247,136,98,167,79,170,35,45,90,31,32,108,19,117,
+16,187,184,157,86,253,250,208,156,192,190,230,233,219,100,165,17,203,102,58,176,80,207,188,202,16,98,39,182,254,
+186,87,63,26,97,235,217,183,129,83,33,12,77,86,195,159,41,24,227,173,143,124,235,192,252,241,65,132,39,80,
+181,111,180,130,70,141,158,83,97,80,86,163,79,45,160,136,37,76,80,119,194,130,45,187,80,250,123,203,240,139,
+186,200,157,227,16,202,90,125,145,27,106,230,16,179,149,38,222,24,231,56,229,181,71,18,207,67,211,163,47,106,
+88,24,61,7,1,107,168,140,89,186,95,240,94,193,220,71,205,82,23,145,33,219,57,139,42,90,105,98,12,195,
+184,215,74,191,211,253,69,146,6,173,134,30,134,13,33,216,15,195,10,171,174,84,87,131,70,38,1,105,67,247,
+164,229,186,87,30,173,207,45,70,31,234,154,159,229,102,137,211,174,223,156,47,70,94,7,1,83,49,142,198,55,
+18,59,79,190,153,254,15,45,139,240,42,27,78,36,83,159,165,150,7,187,80,37,126,18,118,175,10,67,179,164,
+194,190,16,194,31,152,243,197,145,67,229,128,211,121,68,152,219,92,46,101,226,43,182,10,114,11,79,152,224,106,
+207,97,3,205,61,6,181,67,5,6,181,244,101,74,12,47,240,108,1,110,14,53,54,50,69,54,36,141,104,193,
+252,198,58,64,23,25,89,12,87,202,153,122,0,108,161,231,84,201,75,106,180,157,101,30,222,10,134,167,223,37,
+207,128,2,50,250,78,1,124,144,136,213,28,135,102,52,243,129,135,170,174,169,170,207,122,172,202,206,240,234,62,
+159,162,30,45,207,57,191,82,149,71,22,31,225,105,33,4,3,181,176,35,29,26,104,204,247,253,112,144,41,39,
+230,220,147,229,143,29,71,176,156,41,191,131,249,67,23,249,92,90,237,153,166,215,114,71,57,241,250,252,34,132,
+223,109,207,165,254,166,111,137,4,238,78,87,181,49,62,133,144,163,210,215,232,0,65,66,99,136,183,177,108,41,
+208,146,248,252,166,17,131,235,68,78,59,111,240,197,172,180,207,100,240,85,119,158,202,154,52,120,104,214,70,145,
+179,207,12,40,148,233,34,234,16,225,87,176,125,140,237,175,26,185,247,100,253,171,192,111,103,255,139,212,228,172,
+13,176,194,6,130,150,117,202,82,252,150,232,116,144,205,24,47,51,138,125,80,189,196,245,33,137,112,248,178,85,
+147,50,211,2,21,221,97,246,11,5,97,105,58,211,80,71,180,235,68,97,155,175,229,60,171,17,125,153,199,153,
+25,100,200,195,30,126,82,69,22,207,135,178,106,244,252,165,125,48,248,78,195,143,19,71,170,201,232,145,125,254,
+244,91,247,105,9,111,135,181,160,237,137,91,151,20,151,7,180,61,63,241,3,85,96,48,20,135,134,231,195,212,
+186,34,165,145,58,51,2,30,161,106,146,161,49,232,109,208,121,182,59,150,137,170,93,87,170,167,137,81,85,194,
+133,205,149,209,28,50,106,173,118,169,11,60,33,12,66,201,26,93,10,109,27,211,60,53,26,16,253,2,64,30,
+190,198,2,145,110,159,235,191,107,172,121,0,248,77,5,38,53,99,149,242,201,11,215,54,75,67,141,203,240,212,
+163,74,169,1,110,228,109,156,122,27,120,240,115,222,251,144,248,234,187,192,41,173,235,62,100,74,40,84,20,148,
+219,216,88,208,25,152,220,245,29,199,234,200,168,210,235,57,23,11,197,181,129,95,109,211,89,146,199,87,90,164,
+93,134,138,17,229,204,230,237,209,23,187,134,126,181,45,12,53,26,14,71,251,15,95,186,134,210,161,21,176,198,
+216,237,210,18,190,95,90,37,23,107,24,204,5,208,134,4,94,61,63,212,186,50,178,223,117,36,66,59,96,5,
+28,116,210,40,125,251,245,55,167,31,95,255,248,245,197,235,183,175,94,191,125,253,241,23,83,117,61,211,46,195,
+187,239,63,188,238,100,8,85,108,211,61,21,202,179,198,184,22,34,37,99,198,57,206,52,70,227,15,70,251,26,
+86,188,147,67,213,223,218,188,4,226,8,190,67,217,75,216,195,63,90,12,213,158,164,66,56,176,22,137,16,222,
+147,119,152,115,18,40,40,81,183,227,33,126,60,229,87,101,202,210,134,74,230,94,35,62,92,121,122,69,209,100,
+116,104,142,77,163,166,67,102,64,169,181,169,128,248,11,127,27,220,101,151,125,64,207,46,113,41,175,237,71,37,
+77,131,248,220,93,200,92,193,77,116,155,213,168,212,97,63,150,170,72,141,210,71,33,240,241,54,84,180,156,243,
+45,183,129,91,110,243,20,133,87,54,110,184,107,216,207,155,115,185,131,227,22,175,36,220,252,241,101,171,214,242,
+66,173,131,174,241,183,89,138,185,186,64,12,1,214,12,154,149,43,33,231,104,99,231,82,206,145,253,176,86,176,
+18,0,140,225,42,150,133,217,127,2,19,44,44,228,180,19,151,214,6,146,120,89,239,184,144,111,27,90,250,97,
+109,104,196,197,241,44,154,73,80,74,1,150,110,204,156,133,34,126,85,218,121,33,68,163,116,76,107,65,79,232,
+49,150,73,227,240,109,182,145,25,253,90,119,64,228,66,96,36,45,125,67,121,59,182,37,19,218,202,119,182,231,
+106,55,202,73,115,215,52,60,197,184,79,242,2,21,235,251,59,208,105,125,169,251,147,136,0,182,66,63,36,149,
+221,177,230,102,177,123,10,225,145,253,194,233,179,200,199,195,130,221,94,92,216,222,77,251,199,201,159,148,154,246,
+133,45,10,96,186,132,165,96,48,102,131,103,218,199,56,172,135,164,18,41,185,117,12,145,95,51,86,47,175,52,
+206,43,244,2,3,5,42,43,202,139,154,117,212,103,89,188,135,239,100,66,230,169,87,200,2,96,11,220,63,160,
+93,231,186,64,120,106,59,138,104,211,14,119,80,12,87,174,54,70,99,237,109,99,29,86,17,33,122,218,28,32,
+68,187,116,40,8,178,195,65,131,191,129,67,41,230,205,218,179,142,247,246,247,235,192,153,87,0,3,20,70,32,
+104,194,0,63,193,225,186,170,126,86,60,43,84,49,221,31,161,15,40,187,80,157,7,57,220,23,221,44,86,251,
+240,229,94,188,69,17,191,31,170,21,159,6,63,32,202,180,31,253,2,238,130,110,180,46,16,183,177,245,124,128,
+58,195,238,124,65,134,86,122,45,111,139,20,133,236,249,145,132,222,230,128,102,128,211,27,6,248,26,239,207,203,
+180,75,247,211,36,34,167,254,202,108,235,26,99,120,233,21,92,200,13,109,120,231,43,208,40,6,216,179,6,153,
+137,160,49,167,19,249,6,126,93,173,159,31,56,93,253,46,136,112,241,155,214,55,221,239,182,165,81,246,215,86,
+22,188,17,8,203,51,206,88,80,200,67,110,228,26,182,242,130,236,45,204,227,5,249,107,93,199,27,131,114,27,
+255,101,175,95,130,49,215,194,125,75,0,163,141,132,236,66,152,183,253,109,144,101,219,201,178,197,44,9,98,246,
+65,150,170,147,165,194,44,185,210,222,89,154,76,49,68,5,234,40,151,214,14,150,92,66,244,117,16,93,201,18,
+233,80,232,162,153,13,30,162,9,129,244,246,235,57,106,140,65,247,14,38,87,152,92,29,76,78,48,57,59,152,
+156,98,242,245,193,228,165,104,131,249,102,80,237,23,202,120,115,98,231,126,103,126,141,207,91,58,177,131,165,184,
+82,155,197,23,19,109,183,3,205,64,105,186,239,208,14,230,5,114,160,154,165,182,227,15,120,208,251,71,192,85,
+163,148,114,19,50,115,67,143,93,76,91,105,51,208,174,228,4,65,89,209,162,201,163,166,42,183,247,28,53,2,
+44,160,151,90,71,62,40,241,51,60,103,246,156,136,214,164,190,88,234,244,170,95,111,56,247,120,36,200,251,86,
+100,63,144,99,207,220,117,140,192,219,5,77,201,8,31,165,0,191,215,222,171,85,241,144,169,10,177,131,222,217,
+119,36,126,159,218,31,205,82,27,251,191,238,142,131,38,91,205,174,159,179,250,235,219,70,23,6,81,132,86,128,
+213,146,71,218,214,56,8,187,184,83,186,109,67,120,114,255,108,250,9,234,120,147,164,26,62,110,215,230,165,201,
+69,27,170,229,64,62,209,94,110,178,124,254,125,245,131,89,91,238,67,184,117,238,135,60,68,89,2,228,222,239,
+33,179,6,53,175,244,84,119,128,171,219,118,72,168,107,166,96,10,251,5,3,49,54,149,97,230,125,178,75,244,
+194,2,56,179,65,231,101,4,248,39,190,93,249,150,96,61,46,237,254,147,218,173,95,200,239,29,130,187,116,71,
+240,94,171,181,53,242,100,76,250,249,139,215,108,59,156,15,186,199,48,11,165,119,183,172,196,7,177,206,125,236,
+12,25,191,215,117,137,126,245,105,11,118,196,52,69,239,186,14,43,56,162,200,67,232,67,107,6,26,133,54,232,
+66,114,66,154,149,66,122,13,203,7,212,131,155,181,184,66,186,33,33,186,129,140,84,53,86,226,70,43,197,68,
+251,236,225,113,92,192,92,27,182,131,76,85,131,46,66,10,55,207,103,13,138,16,25,119,116,120,40,187,195,49,
+156,27,206,170,106,201,245,224,186,67,132,85,40,254,38,66,16,39,102,115,59,126,147,219,144,226,56,90,152,54,
+235,111,50,254,109,32,155,61,159,221,124,97,58,168,216,172,50,196,179,195,44,222,61,93,132,151,41,208,42,108,
+130,11,116,35,48,252,52,133,63,6,205,181,246,120,180,177,198,227,7,189,28,55,200,16,133,143,115,99,32,102,
+99,100,243,173,76,83,170,22,98,234,7,154,183,149,223,158,176,45,247,187,213,19,112,216,167,243,96,9,121,157,
+100,238,232,187,212,42,96,191,73,46,97,18,35,188,112,75,244,215,45,23,1,43,163,182,199,215,224,13,102,56,
+86,119,164,70,221,17,163,38,178,86,243,113,33,23,103,243,115,101,156,100,46,225,108,217,153,139,210,51,120,173,
+95,11,137,116,96,69,113,218,198,49,111,99,209,250,197,26,26,202,173,27,202,54,28,74,191,131,236,210,208,57,
+52,148,41,154,48,120,154,26,145,247,165,202,177,139,74,227,100,39,208,27,228,178,184,78,46,80,23,105,137,138,
+138,21,199,224,126,244,93,76,218,96,163,124,118,31,119,6,183,1,96,16,39,198,27,236,214,5,115,5,104,82,
+171,58,251,92,166,251,35,50,39,66,110,220,30,130,254,215,176,143,22,102,31,205,213,18,70,180,81,26,166,93,
+166,48,172,112,68,96,83,111,131,248,211,156,6,229,35,115,140,228,113,165,45,106,146,97,106,136,59,244,33,186,
+63,166,231,14,191,33,88,122,87,33,132,28,88,194,24,191,254,128,224,34,234,10,157,135,8,108,185,127,141,84,
+48,180,198,236,82,180,48,197,228,85,29,146,87,204,220,112,57,121,100,159,200,234,29,81,167,214,239,110,209,58,
+92,252,61,40,150,233,87,192,82,167,193,239,137,7,1,43,200,214,232,4,44,233,116,207,192,60,88,92,178,117,
+193,26,161,24,245,129,75,64,164,149,130,180,189,84,56,22,232,15,74,24,245,71,105,187,135,32,220,112,191,89,
+124,193,4,101,101,226,147,91,175,198,110,130,16,111,208,197,172,248,46,233,59,231,239,207,98,173,24,224,192,36,
+51,68,1,218,21,7,68,120,156,172,24,80,179,200,71,31,85,148,185,202,173,123,67,191,108,8,167,144,97,55,
+204,139,35,102,221,65,78,94,43,77,217,165,201,180,104,85,157,70,9,131,154,169,231,119,194,213,11,208,6,182,
+57,205,250,74,109,206,18,154,106,226,232,127,17,109,104,7,160,5,150,37,42,92,45,158,174,90,2,86,0,168,
+42,116,66,241,16,170,114,34,54,195,219,32,149,141,52,103,164,20,86,3,14,175,163,82,236,108,69,21,188,227,
+205,237,59,222,92,64,2,214,39,118,159,81,29,113,161,219,240,212,157,230,185,205,101,20,60,239,196,168,120,1,
+11,64,12,189,241,183,128,77,175,251,108,122,60,60,245,57,159,159,47,162,10,13,140,146,137,79,207,246,196,142,
+192,30,250,30,48,139,69,142,207,151,59,182,104,233,110,133,211,194,246,240,30,148,79,187,173,84,43,198,215,232,
+80,135,32,134,189,37,96,213,192,231,69,191,32,124,1,1,13,99,155,2,14,14,45,102,60,26,145,73,255,26,
+243,214,67,121,107,159,183,37,249,235,187,105,155,96,197,80,0,145,185,95,2,49,63,244,55,167,116,10,14,67,
+58,120,20,70,203,38,141,28,233,201,68,166,61,14,253,121,68,187,91,190,39,45,50,55,246,241,246,230,86,234,
+16,8,14,31,95,162,98,204,227,180,182,57,79,43,141,48,5,162,18,213,99,170,128,116,160,204,85,151,165,2,
+145,238,120,79,80,7,41,28,216,33,79,222,246,254,177,79,22,14,183,197,29,68,159,166,88,212,72,43,59,37,
+151,42,129,139,41,25,231,120,53,121,123,31,53,92,75,211,5,177,203,128,16,91,28,57,57,183,116,86,185,119,
+223,120,193,149,193,164,49,186,20,186,126,91,138,10,106,242,217,112,115,26,37,143,158,28,194,108,100,235,31,121,
+142,38,19,178,225,51,72,111,150,221,160,102,38,161,178,168,246,203,14,45,228,30,216,11,17,247,51,245,114,152,
+21,40,68,235,49,244,254,181,55,76,29,149,6,243,125,166,176,127,79,7,123,72,243,225,45,223,30,186,114,167,
+165,170,152,59,6,211,238,3,42,73,163,61,250,65,54,198,134,51,225,14,243,189,67,139,73,48,243,170,118,245,
+187,91,21,112,71,230,58,171,198,10,5,208,153,15,90,239,132,85,69,29,24,208,54,243,108,13,236,13,83,167,
+53,55,199,113,212,34,231,103,229,73,218,95,32,162,169,101,105,31,25,11,89,182,119,46,105,31,133,161,204,253,
+92,195,244,49,188,141,161,106,222,29,219,65,234,223,87,127,175,114,141,213,31,42,35,181,226,141,30,238,48,164,
+188,220,81,144,165,26,162,253,100,165,172,213,50,45,19,210,13,81,135,56,174,100,0,217,24,231,22,52,150,139,
+218,120,243,97,55,210,251,68,241,82,165,221,9,27,162,141,113,120,136,214,206,206,224,197,177,105,191,69,7,5,
+255,144,163,37,254,26,83,5,163,243,248,204,252,200,185,74,239,167,161,17,141,223,244,36,4,233,209,195,208,125,
+114,109,200,181,254,25,64,212,79,174,84,234,206,53,202,102,205,221,52,27,194,71,46,248,214,92,5,178,18,252,
+173,114,137,179,232,154,94,84,90,3,143,25,102,105,101,165,79,87,188,136,161,20,202,253,248,112,127,209,254,145,
+184,226,19,99,61,148,86,175,179,54,137,23,214,245,112,158,203,61,68,130,154,205,120,14,44,220,66,45,221,194,
+113,95,7,151,14,223,224,212,242,254,69,193,185,203,213,178,207,202,152,239,177,50,26,89,64,165,206,70,137,37,
+136,126,41,163,26,201,227,220,143,192,43,12,152,120,239,81,3,22,100,96,17,82,180,207,100,174,140,240,81,194,
+9,240,61,108,220,18,186,233,27,120,193,64,48,182,31,187,47,29,211,64,231,201,249,200,0,0,64,181,144,95,
+179,168,1,20,53,152,245,11,63,174,151,36,202,209,110,66,110,155,39,78,160,112,45,102,125,161,39,119,39,13,
+108,48,13,165,24,211,129,140,84,113,56,17,188,11,81,171,29,26,64,198,228,161,234,220,43,98,183,206,139,154,
+110,99,223,209,198,1,226,186,43,249,199,247,182,49,195,126,184,215,69,167,223,59,167,102,252,176,166,190,237,45,
+102,9,115,90,182,78,221,197,128,145,160,75,132,164,135,29,45,36,3,72,84,5,131,148,223,89,232,24,6,142,
+173,241,181,18,148,15,49,189,97,84,99,10,179,189,87,61,77,111,167,99,152,254,127,215,0,14,162,207,28,237,
+35,206,88,161,44,134,27,242,143,184,103,70,118,231,28,31,114,59,172,108,129,65,96,10,69,144,42,166,123,108,
+110,111,229,221,91,49,208,238,179,242,244,112,41,241,208,211,144,44,59,227,24,201,227,242,89,61,179,149,102,69,
+173,171,134,135,81,203,114,130,246,31,226,242,169,219,52,180,92,156,5,234,156,148,162,237,151,52,139,143,122,142,
+187,67,108,126,89,18,46,100,46,81,109,237,100,178,182,127,170,158,89,81,17,26,198,88,225,21,155,122,81,208,
+228,153,170,166,201,100,34,82,242,36,52,129,199,106,203,181,130,125,140,40,253,52,49,102,112,19,81,98,14,132,
+130,67,232,193,180,195,63,2,72,24,241,195,3,33,83,158,185,43,241,181,154,201,158,112,14,112,184,252,98,211,
+75,229,243,220,246,230,238,110,166,195,30,15,215,101,13,152,17,206,165,152,225,164,22,221,71,30,108,178,181,164,
+70,152,173,53,27,7,55,232,94,253,221,125,197,94,229,188,165,201,51,28,8,42,125,224,164,161,250,164,109,36,
+0,195,244,38,129,20,124,109,43,8,158,231,36,10,220,158,139,150,188,197,189,195,100,127,6,65,165,196,88,245,
+101,9,53,223,157,232,108,212,219,95,35,185,119,63,134,216,253,164,145,97,67,37,114,63,186,213,117,87,98,36,
+7,15,166,87,7,62,241,181,125,64,17,150,123,235,59,238,20,241,211,191,131,235,245,158,158,72,205,186,115,197,
+222,172,76,158,160,43,208,123,166,70,22,190,237,31,138,154,58,124,119,161,99,217,111,10,234,104,79,155,35,66,
+141,107,20,152,63,13,61,248,236,227,241,134,183,183,159,105,47,135,55,26,149,122,177,219,140,166,255,232,139,203,
+164,10,132,100,14,10,136,177,229,183,80,181,103,159,145,99,212,123,84,129,120,89,154,52,17,114,116,66,185,155,
+1,38,18,250,170,235,244,70,189,41,129,126,71,158,95,132,32,17,80,95,132,121,44,218,216,201,27,136,251,116,
+164,28,51,199,218,209,10,70,221,200,204,202,88,209,16,224,228,216,46,147,53,117,15,8,141,40,62,170,22,124,
+249,228,191,254,252,95,96,225,17,62,39,248,253,223,128,78,145,255,149,40,224,121,22,146,93,127,86,147,68,160,
+127,30,132,134,149,104,239,230,116,89,87,79,217,109,192,20,194,169,18,50,39,43,75,44,155,98,171,104,140,126,
+93,125,79,69,31,33,79,84,99,37,1,187,204,91,194,72,247,109,168,232,35,152,196,143,75,40,87,232,186,118,
+206,8,92,225,159,16,117,139,160,117,28,43,216,222,133,21,213,159,202,106,251,78,87,104,53,47,249,164,101,101,
+171,240,49,34,134,2,245,163,2,82,78,132,4,137,191,77,113,21,151,143,33,108,236,26,87,100,34,11,118,45,
+118,186,6,43,90,147,242,241,147,214,119,115,62,208,77,151,27,102,2,75,16,127,59,3,131,139,16,68,219,236,
+184,209,209,126,208,211,154,161,8,38,141,41,137,215,119,104,12,211,138,141,81,69,149,42,39,81,66,225,89,131,
+18,212,147,230,200,118,57,193,93,40,19,159,57,81,37,250,247,102,130,18,203,150,19,222,27,198,111,220,227,39,
+143,216,93,172,157,11,222,48,9,20,197,100,158,155,222,76,210,76,165,193,220,108,134,150,144,174,76,52,79,111,
+28,232,5,49,39,24,19,226,36,120,158,100,226,121,243,24,166,23,208,10,13,200,79,253,118,22,207,124,79,237,
+35,31,242,225,144,189,239,30,13,84,138,162,14,233,166,70,121,198,29,244,253,131,233,112,46,225,243,235,98,30,
+167,93,115,104,210,184,203,149,171,164,107,24,251,111,165,31,19,187,204,201,196,44,24,107,204,77,250,177,201,162,
+99,39,254,182,222,159,25,6,2,37,202,249,249,87,131,240,241,48,81,40,43,89,202,220,177,169,83,122,211,53,
+232,144,210,40,206,51,46,192,11,199,210,120,225,152,43,84,17,145,11,148,98,91,56,46,174,2,86,167,67,92,
+42,76,78,133,204,237,125,12,131,155,67,117,37,68,121,2,48,176,223,149,133,198,3,81,8,145,102,49,180,92,
+136,145,56,159,3,34,208,159,210,190,78,185,241,104,241,93,3,213,198,17,138,111,124,91,86,217,111,37,236,39,
+128,9,179,147,120,114,34,30,217,135,154,103,74,219,112,32,165,221,87,2,144,165,119,252,186,228,138,80,29,0,
+251,84,235,103,217,17,178,131,173,173,76,89,56,227,153,34,230,28,224,66,103,139,57,200,186,61,230,65,179,247,
+66,54,179,168,86,35,216,23,200,236,25,225,62,49,229,106,247,141,177,152,202,230,240,180,213,152,144,36,165,28,
+55,210,232,59,72,91,115,71,141,98,149,246,173,162,53,100,49,231,3,152,89,90,235,121,160,149,70,74,95,187,
+172,155,67,149,29,165,156,174,201,44,238,67,110,250,144,186,62,44,91,101,166,112,90,7,182,99,65,166,0,245,
+83,136,71,245,220,52,242,30,117,90,141,8,72,164,141,164,48,234,199,27,71,176,181,74,99,140,179,53,6,209,
+75,180,96,2,172,140,165,180,238,63,207,177,52,228,22,66,154,248,58,140,223,27,76,224,126,169,222,59,109,197,
+44,202,212,165,219,73,50,83,215,152,71,35,99,32,198,0,39,248,90,56,119,104,248,178,153,233,24,127,209,136,
+87,144,151,43,8,243,210,42,99,78,12,225,74,99,105,95,234,2,91,216,101,197,34,71,37,168,149,49,195,215,
+180,210,40,4,117,98,85,131,21,36,155,166,132,26,224,243,100,118,244,229,151,241,49,100,182,18,172,87,217,3,
+141,34,76,115,35,204,122,88,8,129,187,119,91,115,84,248,200,127,127,86,126,108,191,91,182,225,15,60,182,91,
+73,8,146,129,76,96,251,45,85,213,143,90,56,64,102,89,128,43,146,126,192,103,247,98,236,229,31,86,246,17,
+126,141,128,108,125,86,18,32,11,222,226,87,50,53,111,241,11,6,100,38,114,41,160,210,74,206,61,56,91,220,
+247,60,93,111,214,128,249,221,157,41,48,17,68,23,202,180,180,210,56,125,82,129,5,182,163,193,231,231,18,255,
+30,120,130,46,241,175,16,135,30,16,31,28,255,190,7,68,183,166,133,91,211,186,85,131,15,136,178,82,165,27,
+150,76,20,0,253,74,204,70,103,163,113,101,49,139,241,72,62,192,0,108,210,241,232,124,20,223,247,104,216,125,
+144,188,239,57,146,222,34,147,182,43,72,124,88,84,249,88,218,21,11,179,79,15,139,239,145,248,218,62,133,104,
+226,219,223,247,182,201,196,186,165,101,228,177,212,33,109,40,155,195,244,62,75,226,123,161,121,88,34,50,250,23,
+74,136,237,104,185,146,214,158,48,116,167,101,60,58,36,181,181,218,30,9,68,133,122,151,167,92,122,33,131,247,
+155,92,87,200,35,86,247,60,172,105,89,35,191,121,152,255,183,16,114,99,147,122,236,87,20,151,10,39,165,91,
+108,46,107,185,240,234,154,107,165,167,235,167,136,163,172,189,166,230,170,191,9,215,104,13,21,180,18,126,138,86,
+78,14,65,204,118,120,67,35,20,209,201,60,206,219,216,45,76,158,110,16,190,62,79,236,94,50,115,82,99,21,
+23,106,63,139,121,215,114,89,16,60,220,170,104,229,21,102,118,173,112,13,202,43,181,243,88,4,94,155,216,252,
+165,193,19,228,254,245,24,63,188,133,254,102,88,153,61,58,194,146,99,183,116,99,210,55,41,33,222,198,233,236,
+242,200,140,228,226,200,154,244,150,91,136,115,129,216,38,58,199,6,152,128,42,185,30,27,191,52,97,33,201,3,
+194,172,159,16,219,2,237,116,3,160,231,138,133,29,65,131,248,158,61,176,150,13,8,143,17,115,217,191,246,214,
+66,176,149,94,174,14,42,195,188,20,154,2,34,115,37,111,36,10,207,200,11,251,189,60,50,180,130,144,251,135,
+38,194,178,114,45,175,240,58,50,114,211,70,130,201,28,145,195,140,65,143,35,215,135,105,255,64,44,180,82,117,
+95,115,79,38,108,204,172,131,71,155,61,106,125,216,37,6,123,6,92,107,105,180,185,193,55,219,50,96,11,112,
+133,104,186,3,16,22,195,162,32,99,68,186,227,119,202,191,211,135,229,131,141,174,197,89,152,50,112,115,216,205,
+136,120,223,79,209,2,246,148,241,158,8,95,130,181,190,33,137,220,168,130,85,100,246,33,181,36,249,92,228,8,
+64,66,21,60,206,83,18,199,0,185,100,241,127,46,36,151,182,30,163,151,101,37,107,28,53,192,198,207,168,8,
+85,33,115,191,132,70,32,162,255,232,203,169,252,198,209,8,170,203,151,52,167,115,240,205,46,220,31,68,54,50,
+129,49,171,121,212,176,241,189,141,215,210,140,125,230,105,236,184,108,25,30,246,25,252,180,166,242,62,209,27,218,
+47,165,172,2,231,106,33,212,247,30,214,136,201,89,236,51,79,122,224,174,20,238,250,147,165,240,126,117,155,14,
+183,35,212,222,4,10,110,137,98,244,210,242,25,226,154,72,87,203,229,173,108,107,136,253,99,12,252,216,112,205,
+139,67,176,179,187,96,66,214,132,32,208,190,142,27,183,195,137,226,79,128,4,107,6,88,18,143,154,46,43,160,
+109,15,130,101,214,173,28,186,226,180,23,122,46,90,182,124,107,225,126,141,244,56,84,246,198,204,113,92,210,109,
+136,7,28,197,65,146,125,60,6,47,74,198,99,82,196,99,114,100,30,144,199,73,154,239,133,66,1,231,194,190,
+112,4,114,148,90,38,72,201,47,141,68,46,210,178,232,122,102,161,230,147,37,62,200,10,105,140,179,171,156,9,
+96,136,205,137,240,157,4,177,203,135,70,78,27,40,220,37,121,101,116,185,132,169,15,14,206,98,12,245,177,220,
+221,67,100,98,193,51,97,58,171,227,133,233,237,165,210,251,27,104,101,68,5,246,245,87,12,28,204,114,116,86,
+208,0,79,98,168,232,2,208,233,120,163,46,229,90,109,38,151,158,33,184,22,79,75,52,92,174,128,74,95,75,
+45,43,241,168,148,75,20,85,134,216,203,137,90,131,203,29,9,229,198,230,114,86,67,85,87,130,173,240,226,80,
+215,226,145,201,244,6,96,161,177,143,196,25,145,147,52,189,28,171,11,244,182,117,225,28,59,153,27,110,77,247,
+172,189,230,55,146,238,195,205,120,141,108,183,131,119,121,207,90,74,77,167,181,115,180,241,206,64,203,197,111,145,
+251,86,169,175,173,107,166,231,193,25,147,39,143,143,237,30,33,151,141,218,195,120,230,154,217,189,178,7,237,98,
+104,149,195,48,113,117,231,244,34,150,183,200,53,42,131,165,6,192,213,50,21,241,130,191,25,59,235,195,66,255,
+64,210,135,75,182,57,9,253,137,9,8,79,19,181,36,28,125,121,100,216,119,143,22,238,235,49,218,245,10,152,
+125,46,131,187,161,173,108,81,162,238,135,86,141,135,86,141,232,86,170,137,243,106,170,100,196,223,44,104,50,201,
+161,11,102,81,147,49,126,210,194,38,210,44,123,222,14,74,240,133,96,88,43,214,1,44,72,27,68,250,87,77,
+11,149,213,177,129,202,0,130,107,3,130,247,1,45,29,124,182,140,94,156,149,36,246,198,34,131,162,109,175,80,
+53,95,141,96,5,71,83,248,246,207,28,123,239,26,172,25,28,70,153,130,114,31,80,198,71,255,45,33,41,140,
+248,31,134,182,64,201,132,182,62,238,183,96,229,109,144,225,12,179,183,47,57,178,88,227,8,245,115,177,247,248,
+168,93,101,115,13,221,55,231,2,234,180,38,186,46,92,229,174,167,35,242,78,136,125,249,4,69,226,29,135,219,
+86,94,24,210,140,10,121,147,80,151,26,92,162,157,54,127,215,85,137,249,216,60,228,119,29,86,198,31,160,230,
+238,213,197,192,133,183,197,14,231,244,36,136,245,197,91,178,173,139,241,216,88,118,98,214,240,61,8,114,53,70,
+227,3,6,231,103,68,35,224,188,220,219,187,48,215,253,61,163,26,18,52,166,57,6,33,164,78,79,191,142,146,
+179,39,231,242,243,59,204,175,82,229,61,12,32,238,242,126,182,63,222,103,116,208,8,151,202,24,254,254,107,125,
+239,114,68,238,19,213,32,83,61,22,50,208,139,154,23,21,40,172,180,121,33,180,231,191,104,137,166,66,12,1,
+21,221,211,193,2,223,76,188,129,22,212,185,210,191,147,47,115,235,248,50,219,123,249,50,67,156,147,163,91,243,
+44,48,148,178,69,240,204,188,156,46,31,70,31,153,95,98,183,140,34,224,232,88,198,78,50,142,242,153,249,66,
+102,141,24,143,196,168,189,159,45,66,83,61,200,27,65,182,200,191,204,17,113,54,52,152,11,178,63,131,249,103,
+241,53,210,3,124,13,148,173,30,228,107,208,173,76,106,92,115,149,152,143,192,36,135,158,110,12,39,99,51,30,
+247,140,114,0,30,7,184,84,111,5,55,136,55,237,0,140,170,203,179,5,48,47,103,85,120,213,190,212,41,192,
+254,60,58,250,74,196,213,0,194,7,69,132,188,133,162,115,44,218,231,0,197,201,64,17,200,10,122,17,6,229,
+33,167,251,23,76,64,222,194,168,17,175,115,200,209,125,83,8,104,240,0,79,64,150,97,29,116,80,1,169,29,
+164,247,215,114,35,47,145,216,63,200,43,74,101,45,243,251,68,125,25,203,235,78,47,27,87,34,192,117,119,37,
+211,58,144,48,29,144,50,172,67,27,92,173,240,12,223,186,7,250,145,10,117,19,130,85,249,57,144,238,123,140,
+250,249,128,104,48,45,82,66,90,219,126,71,40,198,230,242,18,205,51,65,240,119,99,25,198,43,203,232,95,199,
+26,134,44,151,26,164,225,187,65,164,225,182,119,243,183,114,219,143,105,229,58,223,0,58,128,29,40,203,188,201,
+214,241,46,37,67,154,24,151,53,185,183,96,140,202,36,29,223,111,183,105,199,49,174,58,145,53,252,179,36,246,
+177,33,120,158,254,224,111,151,12,9,188,113,35,201,53,105,90,214,81,194,14,73,235,172,192,208,194,167,161,90,
+30,167,97,104,163,12,139,234,90,168,103,47,53,124,162,120,221,195,99,124,118,228,139,224,70,222,60,210,242,90,
+94,63,66,90,251,64,254,137,43,144,21,221,2,43,181,65,103,169,114,1,7,31,62,255,34,151,114,46,208,64,
+79,244,179,141,189,197,207,177,141,159,22,192,136,156,92,192,109,2,131,6,122,235,22,191,74,53,137,86,99,19,
+89,193,231,229,24,99,29,185,100,144,236,159,99,122,142,255,37,174,229,144,147,105,122,87,202,53,33,99,195,70,
+82,240,204,216,79,121,23,110,70,96,178,224,55,193,208,46,72,185,105,6,227,169,87,3,113,191,80,92,215,248,
+134,69,77,186,103,125,88,160,75,238,243,7,15,40,55,123,123,1,133,247,153,95,170,92,61,27,23,100,36,242,
+183,168,64,241,117,199,159,184,178,239,90,230,122,236,191,109,77,75,149,66,73,120,97,42,144,59,8,32,139,140,
+171,153,203,193,250,134,106,198,154,205,168,113,235,198,169,67,84,17,191,243,125,217,152,99,235,159,116,46,154,174,
+74,84,69,57,38,255,115,44,76,145,23,89,149,110,86,11,93,233,34,213,135,203,165,97,54,209,105,12,13,36,
+224,181,235,156,224,255,32,181,154,252,16,224,70,199,96,49,237,144,57,13,175,47,84,136,46,255,33,171,105,105,
+136,19,139,136,17,115,240,14,219,217,40,68,192,253,52,4,122,119,98,12,255,118,96,224,211,38,120,73,67,128,
+218,193,222,74,152,115,62,37,84,87,220,200,206,172,196,122,210,12,226,53,220,87,185,99,77,176,184,64,156,236,
+30,49,85,175,164,246,220,3,214,72,140,131,4,235,89,39,42,41,50,112,165,149,194,182,10,37,93,34,30,30,
+249,184,103,167,246,194,200,225,200,227,14,233,189,77,122,27,96,211,192,113,68,253,100,212,116,15,158,130,160,153,
+159,76,53,161,137,19,185,235,78,205,82,242,172,45,104,235,15,110,33,233,96,208,220,193,160,13,195,160,53,195,
+160,85,171,0,176,47,228,82,230,8,8,221,128,112,24,115,121,129,97,59,48,140,216,200,224,25,148,71,119,41,
+47,104,200,87,106,91,242,72,3,156,67,194,32,110,124,201,171,71,57,230,190,6,136,61,185,17,143,121,4,180,
+57,105,7,218,137,248,88,154,7,179,105,7,86,173,31,93,117,1,213,10,34,234,163,6,243,218,9,97,70,20,
+149,223,135,129,87,147,235,71,3,19,79,123,32,156,254,62,88,245,3,233,87,10,85,166,56,178,97,65,227,99,
+89,6,120,246,69,184,168,251,240,148,167,112,120,95,99,212,208,201,99,196,7,49,26,198,60,232,75,155,45,130,
+174,57,238,97,77,162,4,18,171,188,123,179,14,172,255,70,10,141,179,227,184,59,217,221,206,132,117,60,42,31,
+255,240,251,104,139,42,60,235,137,170,2,197,207,84,85,251,90,61,114,169,162,196,152,14,69,202,21,151,18,55,
+229,2,35,155,114,13,113,246,109,15,35,231,10,16,227,212,77,138,229,89,109,212,156,134,19,46,181,92,115,116,
+184,206,114,245,89,52,205,229,1,154,102,133,104,198,48,77,115,105,209,100,210,237,235,65,219,43,115,15,92,193,
+29,112,101,108,105,92,137,219,49,101,236,110,166,43,89,10,202,171,49,239,184,192,220,110,158,111,14,149,193,35,
+217,156,93,157,203,45,154,82,88,142,195,51,7,200,228,34,140,248,197,190,105,156,162,245,210,248,22,31,51,232,
+115,124,211,131,228,55,50,152,57,0,60,193,244,198,155,118,122,1,120,249,150,233,156,203,123,95,64,175,228,245,
+208,243,167,132,169,184,25,162,107,174,229,149,220,222,73,215,92,74,88,80,209,118,65,198,125,172,78,102,93,24,
+123,166,102,178,173,173,99,61,104,235,184,225,179,80,3,199,133,217,155,15,45,185,87,194,155,194,157,71,210,60,
+58,104,40,203,150,247,162,98,172,248,113,32,16,104,46,218,225,211,120,39,115,192,0,206,128,75,194,29,107,196,
+236,135,71,17,183,3,71,74,139,248,248,247,170,198,251,161,177,58,183,101,111,212,164,213,13,94,187,117,0,44,
+100,193,199,59,47,241,116,246,132,84,106,99,195,148,21,227,203,182,221,191,216,27,239,115,204,246,44,236,134,55,
+33,32,233,37,225,33,228,15,141,254,14,225,85,44,40,13,249,139,125,148,170,22,128,240,169,162,143,67,213,198,
+53,168,169,11,193,88,128,80,57,163,8,182,121,39,54,20,136,122,55,253,134,115,149,28,62,25,216,82,78,178,
+122,198,235,55,210,190,230,176,33,233,27,98,96,152,205,79,149,81,152,63,50,10,167,207,59,177,34,176,108,28,
+34,72,225,220,50,98,58,108,213,151,247,255,189,124,186,105,23,69,36,40,131,125,43,109,223,190,119,17,129,235,
+218,225,171,155,123,215,71,155,77,151,238,198,138,113,166,198,131,8,89,17,78,71,47,205,63,166,243,24,190,142,
+14,97,233,120,127,222,152,114,136,253,193,112,238,70,125,184,234,123,144,149,195,244,0,92,231,39,109,155,107,195,
+208,152,151,155,79,203,98,211,160,197,233,223,207,210,72,170,52,96,104,196,187,14,94,193,79,36,116,167,34,111,
+230,119,115,63,194,187,3,31,77,232,98,193,207,224,226,128,144,191,84,48,228,47,163,145,100,14,138,221,67,123,
+172,20,194,231,145,151,34,45,38,30,143,190,58,254,127,71,30,173,62,238,93,97,95,254,249,88,86,246,198,26,
+157,28,99,86,170,3,114,178,9,199,120,84,141,90,59,171,214,167,74,89,193,196,14,248,87,225,14,132,174,88,
+250,105,88,83,200,229,73,234,181,78,155,247,230,161,255,196,179,113,114,253,9,229,8,44,96,132,48,132,116,5,
+11,64,34,233,29,37,22,103,242,175,33,224,203,126,161,155,254,142,161,82,92,171,225,100,89,55,163,186,109,161,
+42,219,172,131,210,238,92,112,197,171,100,237,252,216,177,173,134,172,15,24,143,67,226,210,43,198,214,12,236,81,
+35,58,46,228,34,203,115,219,118,181,231,96,181,134,226,87,154,83,189,247,30,153,187,87,109,142,55,33,25,14,
+69,218,203,52,126,152,13,94,185,118,105,209,123,189,3,57,198,99,97,89,188,200,81,53,134,120,97,154,78,94,
+83,126,130,221,215,71,165,29,13,225,114,57,223,154,80,207,103,113,224,164,153,81,150,164,199,169,199,8,246,180,
+50,138,225,37,32,67,103,38,112,202,26,82,131,154,178,230,67,99,204,237,55,71,181,81,98,19,18,157,15,143,
+149,22,113,3,127,101,211,182,254,61,240,189,254,119,189,7,222,255,26,33,9,222,224,242,226,87,108,92,143,92,
+80,36,251,186,191,83,69,60,112,250,159,144,103,245,188,85,219,212,120,172,174,196,180,111,107,55,217,51,179,155,
+203,107,200,45,140,238,13,218,140,225,221,47,11,118,141,195,93,192,184,3,198,55,76,146,121,31,48,38,249,30,
+150,65,80,22,228,156,91,213,93,75,17,247,88,228,152,118,168,104,116,63,132,98,26,160,54,150,134,187,25,249,
+216,169,243,16,175,194,34,46,114,8,35,46,156,26,52,129,111,228,162,123,79,214,105,43,155,97,10,182,70,100,
+233,143,63,17,121,41,162,220,47,121,58,240,112,180,252,44,34,107,113,128,200,130,101,156,31,32,178,80,86,214,
+61,28,173,85,98,63,188,7,239,149,164,201,139,47,219,46,41,126,161,222,161,112,207,108,117,216,222,215,237,61,
+219,22,180,244,129,144,102,235,219,6,19,189,82,136,115,247,31,164,244,228,196,191,227,222,40,61,189,33,66,238,
+198,205,52,82,107,55,72,173,245,74,222,8,121,170,110,103,215,241,174,149,31,212,79,209,22,68,57,133,124,169,
+78,225,241,75,13,188,94,109,33,94,66,161,95,213,41,228,68,201,222,15,159,245,132,149,239,201,101,37,114,43,
+115,17,67,131,88,225,244,52,124,221,122,201,175,91,191,10,104,65,66,34,154,181,191,193,161,99,15,38,87,240,
+231,217,133,188,132,3,121,234,76,241,108,33,27,28,88,178,164,2,163,133,85,197,116,38,24,23,247,18,140,55,
+135,8,70,42,217,39,23,111,228,169,172,13,47,235,48,201,184,144,181,92,138,207,127,233,14,13,164,74,239,47,
+10,20,243,249,179,143,146,215,84,2,73,36,171,87,212,243,212,83,248,87,175,179,227,207,123,14,199,167,191,10,
+178,123,153,203,207,43,231,243,123,36,56,112,80,91,74,228,121,222,39,33,52,229,25,160,41,125,97,111,255,119,
+6,62,134,72,172,231,244,192,253,233,197,108,5,93,54,182,157,182,125,111,49,218,60,195,115,244,254,30,108,214,
+102,59,248,72,231,32,44,226,176,12,8,0,127,197,122,127,135,128,206,33,41,156,206,59,218,182,239,148,163,235,
+86,130,72,80,92,243,204,89,43,164,172,30,152,18,177,140,15,238,153,55,102,106,164,79,83,163,20,185,12,125,
+143,44,66,223,35,243,86,85,123,190,71,22,230,161,181,104,60,87,247,77,19,37,146,234,77,5,16,226,82,207,
+138,24,98,27,153,203,1,32,146,10,204,36,228,177,44,112,155,200,249,172,228,250,160,245,78,125,75,1,124,140,
+241,9,212,120,124,71,141,75,97,179,9,137,254,206,38,117,140,78,79,235,182,227,254,168,166,171,63,212,216,187,
+134,249,237,153,37,109,228,214,203,176,226,135,81,29,170,157,187,144,221,45,78,156,213,249,185,197,217,179,42,62,
+91,140,213,38,118,139,177,26,99,173,146,95,33,88,151,49,172,80,161,113,206,64,253,8,235,5,172,222,212,12,
+234,220,71,88,57,134,177,34,12,111,109,186,118,233,216,140,13,39,108,211,171,251,250,109,12,53,149,45,57,84,
+200,126,215,179,225,231,63,13,254,95,115,120,142,170,223,207,227,249,124,33,23,111,138,221,14,42,18,242,115,36,
+95,194,50,135,221,12,120,232,132,227,14,184,244,124,114,180,101,63,79,176,238,5,148,33,206,51,132,225,190,19,
+178,12,20,166,237,179,73,229,99,10,122,27,242,50,136,179,242,49,144,156,143,246,19,226,19,44,155,168,168,196,
+167,153,230,104,143,139,64,114,227,211,189,53,46,39,201,35,143,190,238,239,141,189,103,141,228,143,112,238,247,30,
+135,15,242,239,251,235,73,110,10,140,61,174,219,23,86,13,103,14,223,91,250,222,160,237,45,194,199,13,237,15,
+23,220,228,232,171,71,63,79,173,46,211,70,174,232,44,94,42,32,225,237,67,19,194,11,154,40,63,30,139,104,
+173,128,77,180,50,156,245,149,88,51,103,189,92,173,97,42,108,253,232,189,248,210,101,214,144,25,49,178,149,103,
+244,94,0,70,182,58,39,22,254,26,112,136,245,248,96,45,242,70,85,251,116,39,162,151,75,19,157,1,132,43,
+82,163,223,104,199,203,128,209,110,116,104,8,120,177,211,181,186,50,114,62,221,247,12,136,184,177,212,65,200,162,
+193,232,91,117,165,54,44,50,115,141,156,254,133,220,198,243,14,95,254,184,195,179,191,57,192,235,191,98,162,225,
+30,252,97,37,47,6,80,176,118,58,128,127,93,200,149,188,54,58,71,131,11,117,143,195,131,238,6,98,6,61,
+51,238,204,196,177,235,79,50,8,178,115,204,110,59,173,229,249,125,220,248,18,50,20,227,113,43,100,209,118,87,
+182,171,11,125,159,2,0,201,5,220,35,12,117,148,96,213,104,12,4,253,198,158,90,185,164,117,153,39,21,2,
+161,209,244,52,20,77,250,163,28,187,227,246,95,150,87,226,61,242,217,108,59,228,166,116,216,103,225,62,59,110,
+113,100,255,31,7,236,255,227,128,225,140,134,150,45,168,162,0,201,56,203,188,29,214,243,241,32,79,12,57,93,
+210,161,239,149,219,208,200,212,77,242,55,36,42,111,14,26,4,48,203,60,171,215,121,178,69,26,32,20,161,247,
+162,247,134,67,12,135,16,207,140,157,83,187,227,186,69,195,13,237,121,109,31,10,198,219,114,189,107,63,20,246,
+76,103,64,199,192,183,63,205,196,157,62,254,29,156,105,110,162,131,26,254,30,116,142,181,56,238,51,94,173,67,
+219,39,128,174,57,97,229,209,88,239,139,59,179,57,121,241,57,152,28,210,200,76,47,215,244,109,81,73,214,246,
+11,91,199,67,237,57,109,178,65,78,186,245,233,205,74,158,213,31,227,187,85,61,190,27,171,1,238,46,208,119,
+59,238,139,139,5,188,233,190,193,128,147,243,8,252,127,240,85,89,181,211,187,120,114,9,98,162,195,220,183,99,
+89,127,190,156,246,192,253,88,29,68,176,146,16,127,99,158,83,14,24,78,110,48,156,220,99,56,169,106,64,34,
+239,126,222,92,46,211,33,137,228,5,241,159,96,165,224,143,117,209,238,249,73,100,244,24,26,64,230,93,50,171,
+28,218,23,47,142,110,229,198,196,108,57,102,43,215,136,189,204,1,123,217,216,179,11,145,230,87,34,219,41,182,
+183,250,156,217,78,27,193,139,176,28,92,132,84,230,114,109,112,143,246,131,185,102,17,62,160,142,17,132,254,8,
+115,161,123,199,133,172,6,109,115,227,53,134,49,59,132,244,177,189,73,13,207,224,195,225,27,240,30,96,230,129,
+205,11,15,9,222,3,176,121,97,71,86,167,8,27,97,108,47,194,177,249,190,157,152,91,7,97,24,230,8,58,
+145,225,236,39,169,129,70,232,84,130,135,217,21,46,254,253,128,29,149,28,232,121,99,60,146,3,32,28,117,29,
+8,140,127,190,196,115,59,189,78,170,7,55,105,207,36,238,238,226,194,24,186,187,184,176,214,190,64,205,240,5,
+95,197,241,85,38,159,27,193,239,32,238,187,76,190,164,183,211,32,54,215,18,231,43,136,121,175,229,59,135,156,
+5,209,167,153,124,151,133,249,62,20,242,61,238,174,48,42,147,31,204,178,132,145,47,178,86,76,189,71,99,107,
+13,176,42,111,30,160,85,204,175,171,10,14,235,8,244,24,235,7,43,221,44,203,249,3,248,42,202,230,65,182,
+90,219,189,165,231,241,3,227,105,10,208,209,4,0,214,3,68,88,141,155,72,220,250,15,160,11,107,104,16,139,
+193,132,92,195,26,207,143,70,130,248,11,186,232,50,21,176,233,208,55,19,90,100,104,237,34,213,188,180,166,143,
+161,148,112,16,77,153,247,227,147,57,153,111,233,70,207,179,197,98,40,222,156,144,239,7,147,96,163,219,132,110,
+52,196,243,46,86,110,58,163,172,239,65,93,23,222,0,162,204,132,221,61,87,41,64,121,156,173,88,23,1,31,
+239,66,135,254,79,71,69,98,160,92,6,24,202,12,182,38,90,179,218,194,223,109,27,255,86,154,140,45,151,252,
+46,237,123,19,101,143,212,1,9,207,142,169,251,46,148,49,100,93,66,235,61,151,208,145,181,82,194,15,107,173,
+210,32,214,44,184,28,249,5,162,114,236,30,168,84,198,49,116,105,24,246,192,24,143,74,89,200,60,116,35,123,
+218,183,22,7,127,121,147,214,182,181,82,18,191,18,45,18,101,208,191,33,227,16,198,82,183,113,191,66,79,47,
+240,141,247,53,138,169,128,222,89,217,179,242,111,212,196,173,141,44,210,82,159,165,57,112,13,205,149,111,108,59,
+244,173,82,7,202,192,198,175,145,34,227,15,198,122,186,225,211,65,107,110,92,208,168,143,135,29,142,213,6,14,
+28,114,107,32,118,130,175,73,46,48,94,122,68,168,140,23,200,26,93,102,241,28,120,149,8,157,140,162,46,237,
+60,42,32,90,159,253,24,243,150,204,79,15,38,248,69,65,19,28,94,227,247,110,13,235,37,200,91,209,180,79,
+153,172,240,151,60,69,143,20,9,213,71,123,35,181,171,181,108,21,154,215,149,102,20,102,8,173,130,85,54,113,
+141,172,66,53,194,141,90,128,54,149,154,119,61,28,47,225,193,102,186,166,45,83,68,107,153,202,141,104,131,33,
+125,232,154,209,100,59,16,232,70,243,33,90,127,144,58,140,221,82,172,163,166,248,152,118,17,27,111,77,5,24,
+170,147,26,52,236,98,99,229,33,140,223,66,252,22,226,59,175,21,245,63,43,98,72,175,203,27,88,154,39,98,
+204,161,10,66,225,118,127,155,237,155,0,60,59,119,213,253,29,65,88,22,176,2,129,13,12,172,191,119,0,198,
+224,93,28,216,3,102,49,53,84,192,99,176,22,213,118,248,86,78,123,13,0,68,3,72,76,1,217,201,22,197,
+206,185,39,174,186,238,146,19,34,196,242,86,180,198,251,83,29,108,155,190,125,58,236,38,167,150,212,46,173,127,
+64,142,164,158,143,179,108,9,43,3,178,190,142,206,14,80,242,198,250,227,142,240,172,86,93,97,213,0,231,26,
+3,231,96,32,112,77,129,226,205,2,125,144,253,190,17,209,156,242,148,149,157,241,189,75,131,99,65,138,33,108,
+54,187,82,31,140,191,74,187,243,15,61,202,250,233,200,35,99,145,209,45,233,92,165,123,203,81,91,98,2,68,
+32,157,61,124,246,115,103,0,133,69,63,13,2,27,217,188,15,97,55,108,238,220,13,253,170,86,10,217,242,27,
+1,12,196,4,77,162,158,241,52,165,221,105,90,210,52,45,90,244,116,179,18,241,10,161,38,2,73,154,221,251,
+138,237,207,46,250,118,242,179,251,99,22,206,238,231,237,238,153,86,4,174,31,22,51,222,126,181,136,59,75,21,
+159,157,251,102,110,6,12,106,94,104,108,69,72,92,78,60,190,246,105,40,81,21,217,159,131,155,244,103,179,52,
+163,24,62,127,177,159,100,94,244,33,193,8,186,74,105,85,145,215,130,150,214,235,179,10,55,235,239,153,38,233,
+55,2,0,20,89,211,185,140,114,180,131,14,201,26,146,27,188,130,82,244,18,144,207,206,206,227,178,69,220,224,
+101,170,12,22,92,199,22,184,222,49,78,26,34,188,106,220,34,147,60,168,114,102,160,77,45,75,40,23,255,232,
+190,209,155,187,144,73,0,118,42,231,76,50,186,239,90,96,30,103,206,12,168,84,85,112,29,18,207,127,169,114,
+75,106,165,231,211,37,140,104,105,160,56,170,126,119,103,108,217,157,177,156,138,211,61,210,226,212,36,102,169,93,
+190,207,27,255,214,46,228,231,78,2,158,50,55,246,103,108,151,62,177,3,10,59,40,243,125,46,91,34,44,223,
+175,10,141,77,91,67,82,185,215,152,74,69,213,27,122,14,115,51,12,180,82,127,172,42,226,253,124,246,176,169,
+92,48,214,86,34,169,162,235,223,93,7,207,81,48,137,166,190,96,19,82,86,58,127,59,172,36,198,237,199,5,
+226,160,112,107,74,111,239,41,189,189,171,116,219,18,136,251,6,142,53,153,114,53,70,90,37,153,115,149,206,122,
+107,112,73,45,8,145,102,6,31,144,158,80,105,164,213,51,13,151,51,242,38,66,236,249,170,62,152,253,155,146,
+177,9,83,210,218,215,66,41,139,203,242,22,167,176,95,215,188,215,52,89,10,199,209,243,193,169,1,229,40,98,
+45,75,99,148,180,112,211,95,147,20,47,212,88,210,167,51,117,53,161,110,196,46,207,196,229,104,131,182,191,15,
+177,35,103,185,138,76,229,74,167,174,168,213,177,44,84,148,33,243,75,184,237,170,159,162,28,144,22,181,202,206,
+52,32,112,107,226,164,196,165,55,203,100,132,172,226,74,154,95,43,46,28,39,10,16,78,228,143,209,86,183,157,
+212,18,38,39,174,37,212,2,21,4,70,245,234,190,213,66,59,6,30,149,164,54,0,208,142,123,13,181,130,89,
+226,126,192,111,58,3,222,181,102,128,54,168,31,0,130,238,18,169,239,133,233,81,221,169,24,69,3,237,3,60,
+104,49,225,106,91,217,174,58,170,189,201,53,198,13,208,76,4,176,238,240,71,237,172,156,192,177,4,214,108,170,
+231,240,65,131,57,182,22,110,142,177,199,246,113,112,60,150,21,141,112,172,202,118,127,28,31,123,228,155,25,151,
+220,93,63,47,111,65,28,200,242,220,11,185,180,193,111,105,206,90,101,213,14,104,105,217,56,89,214,183,75,182,
+75,96,85,75,194,112,118,200,83,252,96,77,240,168,4,119,49,122,138,63,35,235,66,72,220,164,8,180,131,41,
+122,156,82,223,167,73,199,204,114,98,245,250,212,114,182,124,84,196,57,190,121,36,215,73,150,163,84,154,233,178,
+132,252,118,67,215,34,230,236,133,143,198,146,117,175,164,29,93,32,146,207,147,244,117,103,177,205,94,151,90,193,
+121,107,220,121,5,37,221,212,156,75,55,70,97,112,219,2,51,45,16,242,89,248,97,99,107,31,75,118,161,133,
+44,57,14,65,12,101,172,56,146,32,141,117,199,127,85,147,251,126,153,211,247,118,228,246,168,159,100,45,177,73,
+224,146,131,3,192,152,253,14,148,66,98,155,24,255,220,84,25,215,46,41,23,238,171,226,175,68,72,175,154,106,
+123,194,97,104,255,26,95,206,128,16,246,245,215,194,87,23,158,191,114,168,238,54,96,35,48,86,181,175,127,96,
+0,67,3,127,196,56,136,43,32,14,254,4,64,232,175,37,185,113,64,225,4,229,179,98,80,54,86,98,33,51,
+130,12,97,34,134,101,99,126,48,217,78,116,144,129,98,100,67,31,152,201,76,161,207,67,17,178,177,191,65,151,
+222,239,113,26,44,28,64,40,69,162,193,25,86,65,248,168,1,7,191,25,245,27,109,164,217,208,66,54,168,74,
+77,148,13,58,86,253,2,93,218,210,185,1,198,149,61,245,36,62,116,2,176,200,100,246,253,179,97,169,195,67,
+84,210,81,136,75,123,58,132,212,182,148,205,252,120,97,1,136,196,230,199,212,124,107,252,75,99,95,141,143,26,
+152,239,74,134,81,81,96,82,144,27,63,150,141,21,192,48,39,115,2,11,93,201,140,206,67,112,0,242,129,18,
+246,68,114,17,60,24,225,73,72,85,242,80,193,252,221,32,10,104,190,150,222,44,251,141,66,92,31,18,186,195,
+222,213,201,10,9,198,18,221,225,2,181,24,219,136,37,69,132,62,5,158,135,167,190,187,76,156,71,71,1,138,
+195,3,192,125,57,49,59,244,152,239,14,12,142,85,45,235,22,248,104,48,161,17,157,115,224,173,97,200,193,7,
+29,209,148,224,39,143,213,119,234,117,15,94,55,131,221,42,162,128,201,176,195,170,97,123,64,123,200,92,160,155,
+194,86,13,119,5,227,0,140,103,87,128,46,160,37,165,96,64,16,146,134,249,214,10,201,215,72,17,101,179,179,
+206,66,162,131,191,238,50,133,231,243,86,15,242,33,248,38,145,198,233,247,192,125,34,17,197,237,221,41,50,167,
+59,36,167,151,15,7,230,129,227,119,116,195,144,30,67,75,9,179,22,222,32,178,113,27,213,174,254,130,86,127,
+222,170,247,214,78,94,34,11,200,241,191,106,129,212,63,117,98,169,160,238,185,204,25,198,163,22,177,65,62,18,
+190,52,224,6,131,81,214,52,74,176,157,217,122,118,183,14,40,74,130,81,218,193,163,134,129,74,51,46,60,20,
+210,227,90,102,124,123,101,124,169,5,172,204,122,216,241,133,217,16,56,181,232,72,92,110,141,89,245,0,71,73,
+66,28,229,65,206,215,113,113,150,120,176,66,240,100,15,205,56,105,97,46,134,47,106,80,207,66,24,22,78,182,
+103,64,194,186,60,90,26,215,143,181,153,189,156,198,51,189,108,162,212,90,19,20,198,213,136,11,4,115,61,131,
+233,203,101,109,161,117,37,117,8,82,106,18,82,163,212,185,136,49,51,193,244,113,122,100,251,15,165,22,144,38,
+169,114,85,73,151,50,86,11,89,169,156,38,221,112,61,131,62,47,187,125,182,171,209,235,114,121,184,203,165,172,
+205,253,51,151,186,3,212,106,39,74,103,146,169,203,165,189,166,124,159,231,114,225,123,92,118,122,92,170,220,142,
+187,109,129,223,163,176,232,86,85,237,183,71,72,185,142,224,209,190,220,160,206,2,58,0,32,248,128,175,116,107,
+250,220,13,67,3,105,97,69,219,10,243,90,0,141,238,160,0,96,127,116,179,226,54,209,232,65,209,126,225,249,
+21,178,225,33,43,255,9,56,237,9,164,56,116,94,241,39,96,187,22,68,52,142,232,104,120,243,32,228,191,128,
+174,235,170,86,238,11,90,115,187,157,223,101,206,118,191,65,95,141,240,180,70,7,133,244,213,182,64,188,83,207,
+156,223,176,86,90,207,86,52,6,15,57,41,223,140,126,153,216,106,140,97,95,253,208,82,91,148,234,92,151,105,
+121,2,53,90,223,154,155,74,59,177,145,96,6,52,127,134,163,215,252,233,135,173,233,163,149,4,192,232,32,147,
+31,170,46,155,173,86,57,16,213,252,154,111,151,215,157,243,142,32,38,110,45,179,71,123,226,152,26,226,237,121,
+179,178,150,136,212,218,193,89,251,181,14,151,147,169,10,143,239,244,71,151,77,174,224,94,160,247,135,213,209,165,
+6,104,162,223,152,126,116,223,32,186,105,145,104,29,82,176,196,29,171,231,27,152,199,104,37,47,129,42,189,196,
+154,189,2,65,39,120,68,178,39,198,172,14,168,169,172,198,40,36,10,0,70,46,250,15,160,30,22,196,141,12,
+14,89,172,121,191,215,178,75,33,196,165,143,160,204,149,236,80,61,224,124,233,241,178,71,249,84,160,26,32,228,
+124,192,138,151,152,2,54,4,151,131,81,174,101,46,107,47,159,191,170,227,185,188,65,2,21,26,189,141,9,110,
+109,99,3,10,176,50,185,86,64,152,229,14,83,78,141,215,85,184,88,18,191,185,54,114,33,215,66,66,100,30,
+124,167,244,141,215,144,79,0,76,102,35,228,105,13,229,61,77,224,18,55,136,128,108,142,110,224,99,139,31,75,
+155,177,75,37,80,230,144,147,74,120,197,198,118,30,193,201,198,0,58,44,232,162,199,88,47,193,22,147,58,198,
+250,9,241,196,79,107,84,30,114,181,242,199,40,241,149,155,189,230,228,93,87,184,45,166,221,185,188,12,187,34,
+228,165,67,2,236,64,150,242,30,164,7,54,37,11,21,252,92,238,146,244,159,155,172,210,129,143,111,177,107,43,
+157,235,164,246,145,129,63,125,88,196,175,175,117,209,160,131,66,148,209,115,143,183,228,178,116,56,13,121,121,250,
+58,75,237,211,159,17,125,240,15,205,39,164,128,147,173,54,43,92,223,61,151,42,58,196,143,53,162,53,132,182,
+23,170,192,16,29,237,157,157,81,237,38,57,40,84,207,76,96,145,151,200,139,121,92,139,24,153,92,89,125,218,
+52,230,93,51,24,225,113,203,106,45,0,232,48,193,89,247,122,149,146,4,198,224,188,113,111,129,179,28,58,4,
+239,134,162,209,147,249,8,78,50,74,43,236,53,212,236,139,83,43,152,241,150,240,240,76,141,190,48,235,254,107,
+61,146,191,165,10,238,177,77,186,180,10,20,163,85,185,169,245,188,188,41,70,210,68,227,90,80,44,126,82,44,
+116,158,34,55,235,145,101,121,234,74,227,31,138,54,223,156,130,245,5,85,115,124,175,114,142,223,172,247,107,135,
+141,196,153,1,62,113,60,124,7,177,173,252,80,43,84,158,102,43,53,248,53,26,121,188,254,219,189,199,246,26,
+133,31,101,97,89,197,176,146,85,118,9,240,47,114,134,121,133,172,251,73,100,187,215,48,162,179,179,38,59,87,
+78,67,54,222,209,166,41,232,92,214,210,84,239,197,0,181,3,202,146,114,106,183,239,104,219,217,77,137,130,45,
+156,85,241,23,92,252,151,121,153,94,141,164,225,97,194,54,71,197,219,224,27,51,24,201,180,9,68,141,228,7,
+100,133,121,58,38,65,84,151,123,95,6,142,192,34,135,35,151,2,45,80,64,185,66,8,248,160,233,161,62,154,
+185,20,140,68,83,153,199,232,228,255,9,187,23,13,155,178,25,251,109,113,5,165,247,188,72,187,243,47,165,122,
+15,36,230,26,97,212,181,145,64,6,161,35,191,122,191,178,178,84,118,52,8,65,254,82,138,192,5,90,144,59,
+77,138,235,164,62,34,232,114,119,185,183,189,61,242,91,122,102,157,60,2,74,111,63,240,169,179,192,235,166,85,
+86,156,131,153,71,152,26,107,203,242,137,27,105,197,64,226,76,66,126,239,3,161,48,98,70,88,222,199,213,38,
+46,116,86,152,217,94,244,217,162,184,44,248,230,6,147,174,141,196,112,146,25,97,69,193,144,199,191,231,237,233,
+150,185,137,144,181,241,163,251,221,198,74,146,126,127,89,235,10,157,144,151,112,105,216,183,24,156,246,46,177,83,
+138,74,85,64,191,101,81,130,147,175,231,111,241,165,203,122,1,172,240,89,19,19,236,4,115,210,20,18,52,34,
+48,158,70,46,109,91,209,188,76,141,151,82,52,221,150,229,115,92,142,216,168,144,95,54,149,54,75,223,121,249,
+253,229,255,108,44,190,203,225,104,120,152,255,190,177,216,246,223,104,219,221,100,109,232,246,23,104,40,136,71,249,
+207,146,149,26,50,117,147,21,0,47,143,230,189,43,111,138,166,33,94,212,112,144,160,108,38,223,104,175,194,128,
+243,3,163,134,125,177,169,16,32,247,111,75,100,241,192,77,130,131,16,1,93,77,251,29,106,178,36,26,53,188,
+119,194,156,20,173,252,103,41,176,93,122,225,11,170,250,27,84,101,42,154,107,148,42,131,128,236,213,74,211,125,
+184,98,95,217,55,119,45,57,188,201,159,22,81,97,223,220,235,46,170,95,170,219,50,138,80,210,33,120,239,4,
+46,109,158,65,163,6,55,157,106,147,44,211,167,157,104,187,192,210,246,20,119,2,174,212,123,211,55,222,86,9,
+215,153,171,4,69,138,82,149,155,115,8,149,188,215,41,97,21,114,217,139,37,66,61,85,198,201,196,18,127,64,
+251,27,223,170,131,29,85,241,142,170,133,52,203,130,220,230,224,16,32,76,112,222,135,205,173,0,77,20,80,61,
+42,181,41,22,115,6,18,2,23,34,100,236,222,53,149,183,165,57,43,16,211,220,178,49,42,29,1,24,44,101,
+38,96,62,160,27,129,230,2,202,81,81,135,207,42,89,177,77,48,247,245,203,57,15,8,1,118,1,237,214,184,
+253,9,87,188,19,253,9,123,120,63,6,196,205,160,201,94,26,143,241,22,24,125,155,146,159,111,97,193,234,62,
+38,202,236,63,42,103,246,145,198,219,92,56,36,149,109,69,153,104,103,214,98,122,230,174,53,119,149,158,243,1,
+12,167,169,192,103,155,159,208,31,155,166,61,239,49,136,82,196,230,244,4,49,178,242,100,30,236,110,123,239,162,
+72,101,79,243,19,108,157,226,165,222,105,82,219,220,208,160,170,225,15,74,40,208,117,78,191,210,30,199,7,102,
+32,240,48,114,16,253,110,150,217,193,75,210,247,174,57,250,98,93,149,183,153,225,99,248,128,218,181,120,102,118,
+137,65,135,227,31,83,104,214,124,253,146,74,187,49,227,111,210,246,12,175,209,191,166,211,26,62,148,107,120,24,
+237,15,119,195,93,109,194,124,65,101,93,72,16,185,110,252,146,113,55,50,234,6,124,217,110,252,148,10,108,5,
+247,39,214,64,119,241,221,116,198,1,168,124,31,245,241,117,206,81,93,138,129,119,226,105,225,149,42,30,62,140,
+204,9,207,234,23,246,128,235,121,248,214,243,23,3,102,41,235,171,50,2,82,128,216,10,104,4,42,173,180,46,
+94,152,93,221,241,112,5,188,152,7,89,97,21,9,247,179,206,94,165,241,207,41,157,210,219,174,2,49,109,140,
+219,142,162,240,54,12,145,120,63,92,181,50,148,10,238,100,249,130,232,17,31,223,146,108,184,19,254,247,46,135,
+240,33,122,139,26,217,88,50,16,71,35,5,179,115,143,114,113,214,118,153,212,86,117,128,39,29,12,116,216,142,
+3,57,239,190,183,162,229,234,58,59,172,223,71,179,159,224,8,122,245,110,204,193,135,192,159,204,166,115,24,241,
+4,154,195,79,254,74,236,196,68,98,134,33,116,48,23,99,53,246,152,214,109,123,219,117,204,238,131,239,145,13,
+227,38,138,90,253,123,169,118,215,228,219,188,235,210,56,67,77,155,172,149,5,224,33,85,198,208,30,81,120,188,
+106,104,4,163,227,209,128,1,188,158,238,181,179,135,167,50,156,1,237,36,109,78,88,146,214,211,209,44,99,169,
+81,246,198,244,76,200,32,82,179,104,171,75,21,211,40,125,122,162,39,127,250,223,255,77,159,157,232,147,175,96,
+101,140,107,222,20,47,225,108,145,165,35,228,197,253,19,71,160,69,235,128,233,170,241,109,89,87,217,251,150,103,
+39,39,143,2,242,188,18,242,201,177,176,166,119,119,5,105,76,89,207,84,120,70,95,145,214,194,203,236,83,214,
+212,113,34,161,170,161,248,118,88,241,62,239,236,114,242,160,110,197,217,133,4,245,246,204,10,76,203,188,252,148,
+84,89,179,92,125,214,146,100,143,89,2,245,228,88,6,131,129,225,103,66,248,235,14,202,131,159,56,252,121,98,
+127,190,154,253,189,60,162,181,71,11,172,185,217,235,210,54,9,91,35,180,56,97,230,150,237,226,53,110,125,191,
+156,53,103,79,104,153,38,205,153,91,177,24,62,57,150,87,217,245,196,175,181,120,166,128,217,139,168,105,208,239,
+12,87,87,171,108,210,137,19,82,27,105,185,119,153,218,57,165,142,170,142,255,94,182,83,226,189,27,157,142,145,
+244,202,115,199,236,236,230,132,93,36,195,103,168,139,135,65,99,192,34,30,153,229,24,201,79,176,150,58,38,21,
+189,176,46,175,12,121,98,88,224,214,210,33,166,96,232,251,226,5,63,216,83,212,71,172,16,3,88,51,121,53,
+251,111,19,176,213,152,9,85,207,154,35,174,217,36,26,213,75,159,152,98,48,24,136,165,212,95,38,245,18,100,
+230,130,208,247,54,199,49,69,81,79,91,105,148,102,66,141,66,137,200,12,172,110,247,77,226,79,142,73,247,167,
+22,203,96,207,209,20,200,123,214,26,196,189,206,161,175,32,152,161,226,136,171,239,3,234,144,210,244,28,7,49,
+102,48,97,99,95,202,96,74,241,145,4,125,66,135,223,239,56,163,209,227,225,97,57,61,160,248,93,118,228,215,
+223,110,44,115,64,161,157,93,11,189,252,213,126,36,104,191,50,30,165,196,85,74,171,178,174,79,109,92,161,19,
+167,68,133,77,60,135,90,231,0,217,205,236,210,55,245,187,250,116,153,68,79,190,250,74,62,240,127,142,143,254,
+235,43,49,226,156,174,191,224,187,76,192,78,172,16,0,211,94,60,162,45,53,50,107,8,191,252,185,151,19,119,
+91,55,163,215,195,61,156,61,204,115,127,33,179,19,14,244,134,44,14,94,106,127,140,46,22,52,227,56,47,61,
+27,132,15,51,251,54,86,255,4,96,42,26,217,135,135,17,156,219,94,66,178,192,201,23,246,136,143,220,18,142,
+40,108,20,124,170,65,27,134,126,95,187,204,56,151,207,125,108,59,208,233,186,211,107,27,55,148,145,23,102,208,
+180,98,111,97,71,253,206,251,238,30,46,19,234,91,253,189,207,60,236,94,0,178,176,182,90,12,180,120,147,173,
+50,96,209,124,97,68,157,106,76,192,237,76,134,243,230,51,141,47,107,120,236,75,175,20,90,25,219,77,50,65,
+36,30,110,76,153,43,107,236,169,124,230,13,204,64,49,153,163,76,224,227,66,200,60,176,34,103,158,204,11,97,
+243,31,91,232,190,148,11,202,49,87,229,179,19,203,189,54,234,226,81,148,160,157,144,8,218,17,150,68,50,28,
+146,191,105,83,125,42,127,138,230,2,204,241,84,147,185,172,208,79,199,177,92,40,200,59,93,62,93,76,151,227,
+177,224,140,245,217,242,28,255,140,79,206,249,122,226,196,196,214,227,174,152,56,25,207,209,249,104,47,27,70,241,
+20,127,209,21,25,225,9,182,80,83,226,156,95,224,100,27,28,91,200,2,195,182,246,199,122,28,53,208,103,180,
+16,132,177,176,16,111,40,193,117,204,223,66,129,201,126,89,135,188,144,102,217,39,148,11,136,17,108,206,22,171,
+235,218,252,241,246,91,228,137,247,61,243,14,253,37,244,244,179,188,162,15,106,104,133,238,183,114,133,210,34,88,
+111,254,172,118,21,231,237,80,11,190,171,122,57,44,49,26,72,138,102,161,140,168,134,246,80,16,204,238,68,36,
+167,205,3,175,30,18,206,204,150,254,45,213,155,161,66,44,143,124,169,22,228,172,69,103,57,12,84,90,207,98,
+89,232,89,12,37,247,209,20,9,53,147,161,236,139,172,199,99,83,79,253,40,148,59,195,173,176,175,237,132,174,
+120,130,23,88,92,172,175,97,10,92,35,194,127,77,89,215,137,197,95,116,208,63,13,237,26,233,253,122,82,72,
+173,242,199,193,62,200,31,107,129,27,188,132,173,125,60,21,201,120,12,129,224,156,148,227,228,145,182,11,25,224,
+189,165,68,157,111,16,167,73,97,160,200,210,89,134,3,77,97,160,7,42,10,198,92,132,203,199,43,197,139,104,
+60,232,60,97,94,4,77,122,134,43,160,213,9,44,104,99,132,126,33,27,174,233,4,254,0,200,64,238,141,47,
+194,70,192,137,100,89,186,167,17,43,113,52,35,137,163,24,163,232,123,134,73,24,37,223,213,202,174,9,162,46,
+152,1,37,14,128,204,244,197,51,208,52,27,235,24,127,38,218,3,201,151,117,23,72,158,157,7,27,241,113,131,
+135,243,160,27,200,114,12,253,215,110,30,131,101,42,5,131,151,80,172,180,220,59,173,153,5,197,212,66,104,136,
+169,49,166,200,144,172,233,56,222,173,48,204,110,119,19,5,180,201,159,73,175,36,11,173,144,33,80,71,174,92,
+138,43,99,168,243,200,160,225,179,96,91,228,147,82,86,147,92,196,56,75,199,144,18,237,87,113,34,32,195,227,
+39,113,170,32,251,64,11,8,144,209,255,231,88,213,79,155,89,26,79,82,153,63,45,39,9,8,206,60,171,198,
+137,16,12,30,252,52,84,75,59,229,63,194,143,102,22,84,129,110,95,211,192,237,230,227,39,118,198,113,4,245,
+51,200,79,114,98,236,129,211,113,137,172,50,8,210,171,231,211,194,9,110,28,27,93,248,96,3,111,116,199,14,
+7,227,201,32,15,18,160,201,199,129,136,59,237,12,35,156,225,158,180,188,169,115,230,200,53,17,226,133,104,174,
+20,1,124,142,65,194,57,221,30,136,190,129,56,68,77,197,204,252,242,13,115,34,30,105,68,194,73,34,97,236,
+252,149,248,78,36,52,87,78,245,162,129,224,174,38,187,112,200,68,241,216,134,47,148,243,62,235,20,195,97,198,
+218,234,129,112,105,140,236,20,78,151,93,79,89,155,34,202,120,32,26,245,93,249,248,1,179,1,35,20,71,8,
+179,205,208,49,181,128,185,240,117,46,151,125,169,88,196,252,107,43,124,84,58,2,160,162,103,251,132,222,163,242,
+86,101,161,167,156,212,41,207,47,91,149,155,189,97,92,44,163,31,101,175,155,54,169,229,165,74,38,102,215,100,
+61,29,0,179,150,27,85,54,198,238,99,34,228,111,145,14,252,10,135,44,75,45,16,116,221,2,236,191,0,53,
+81,181,132,159,125,35,127,183,98,188,154,52,86,107,22,223,184,28,206,63,91,171,40,37,113,175,113,138,98,16,
+112,70,48,107,188,86,239,106,171,203,38,166,115,236,166,41,140,221,250,204,174,108,14,118,101,114,57,30,234,202,
+6,187,98,229,226,216,179,8,102,141,55,65,87,214,118,78,42,107,147,86,123,160,57,249,75,252,23,186,215,173,
+17,132,159,227,141,52,31,191,196,107,185,114,162,51,243,208,171,143,211,191,103,155,204,125,246,92,227,172,251,57,
+211,126,115,213,192,31,27,192,93,9,65,252,57,200,154,67,206,191,106,240,175,244,108,33,103,221,142,170,41,215,
+97,9,90,140,78,20,142,48,140,176,211,19,198,16,87,58,140,89,234,126,38,68,221,42,52,29,193,114,183,88,
+15,139,162,120,17,20,155,27,231,44,168,149,35,191,221,175,152,160,8,136,238,12,69,91,57,157,161,148,55,122,
+49,88,209,251,126,11,86,169,40,140,48,148,175,35,182,187,93,204,138,126,151,187,179,80,161,2,98,24,101,175,
+54,188,80,109,6,36,29,209,222,196,235,70,175,106,243,108,67,9,166,209,225,88,196,155,59,177,100,155,134,90,
+240,88,51,199,228,37,116,163,110,62,194,222,123,129,60,107,181,163,137,15,110,209,176,151,254,54,13,99,123,90,
+251,204,39,190,216,212,186,250,46,28,58,71,250,249,161,230,54,159,176,35,122,206,217,247,83,250,101,204,140,245,
+6,100,8,82,123,202,57,46,237,142,12,239,63,67,192,213,102,200,115,238,238,23,169,125,65,114,252,107,124,19,
+218,183,132,113,84,251,119,42,226,95,115,88,136,96,167,52,230,167,55,104,19,34,139,25,184,75,68,119,166,122,
+233,201,173,24,152,133,110,166,48,101,63,119,191,202,48,101,200,116,71,211,246,236,197,226,189,182,115,221,143,27,
+233,122,26,107,217,233,84,92,4,97,76,175,45,123,159,233,15,181,198,39,192,67,138,219,66,106,204,160,93,134,
+183,95,127,115,218,203,80,96,134,226,142,26,106,204,80,31,174,193,26,205,53,221,40,4,130,99,252,198,247,161,
+208,128,238,23,81,99,210,124,88,11,235,117,38,43,96,88,228,115,196,212,164,77,29,69,88,186,14,139,150,254,
+129,35,156,81,89,25,28,13,84,233,8,61,10,43,107,89,67,196,123,171,107,210,37,192,35,82,254,37,173,223,
+158,149,143,164,111,229,163,82,104,91,41,52,58,231,135,128,53,35,250,133,143,109,58,48,102,42,43,252,69,109,
+43,72,40,2,75,165,178,194,223,192,43,10,210,126,250,89,97,116,37,11,85,219,128,142,11,158,97,45,205,90,
+105,193,243,92,72,19,13,213,183,109,168,18,67,27,207,222,6,125,184,140,34,207,120,47,244,0,60,70,219,107,
+99,15,96,99,18,221,33,251,224,31,18,77,227,6,147,245,15,73,30,252,178,49,220,97,163,176,164,93,204,165,
+24,42,176,5,92,51,183,93,60,10,89,36,183,182,82,180,157,96,191,240,77,47,48,155,219,118,69,130,119,159,
+11,183,168,220,15,100,104,111,247,183,168,211,171,48,85,158,97,210,185,247,217,16,226,151,33,171,189,38,214,122,
+73,236,229,170,103,25,31,61,27,213,9,26,22,194,235,102,106,210,186,221,232,93,221,77,255,214,214,61,76,160,
+232,11,2,223,131,25,20,194,223,152,247,95,130,191,239,38,165,161,124,64,171,172,43,93,212,56,100,55,162,122,
+40,210,176,78,251,217,251,215,237,224,174,96,148,105,92,24,236,10,126,130,77,189,116,52,14,138,5,23,132,145,
+29,216,9,184,239,124,223,95,114,170,235,201,92,67,31,225,100,134,73,97,247,251,209,140,159,184,167,166,82,214,
+226,224,46,60,22,225,204,61,223,100,249,156,14,88,184,76,54,75,144,136,251,62,232,67,88,110,202,34,56,79,
+125,13,14,194,57,43,187,5,74,228,155,2,31,75,58,179,249,12,248,19,190,4,218,43,240,33,234,141,87,78,
+232,116,251,133,115,165,246,38,196,233,92,158,244,96,42,247,255,96,5,149,35,134,81,119,231,136,158,79,0,132,
+193,41,42,55,85,106,200,7,140,53,228,96,48,97,127,79,237,220,135,35,24,220,230,66,162,162,238,225,89,233,
+86,192,35,126,149,53,110,0,11,252,12,198,242,170,23,118,7,187,229,201,99,175,181,29,120,67,88,160,68,22,
+215,208,150,143,180,98,90,130,140,78,18,149,21,83,18,238,118,74,225,45,175,30,54,98,31,41,213,125,124,180,
+24,68,69,155,46,38,92,76,92,57,243,238,244,177,116,217,194,97,116,146,90,154,129,97,8,203,137,1,128,29,
+132,32,253,130,3,153,184,130,186,87,116,112,42,3,138,171,3,110,3,106,173,67,168,249,252,48,217,33,113,214,
+5,206,158,30,236,146,130,65,9,177,79,62,237,147,96,67,180,212,32,69,118,220,14,64,208,225,121,30,158,173,
+11,124,241,249,182,44,175,106,196,205,130,203,186,40,155,108,177,125,103,45,21,70,141,28,64,214,187,173,0,175,
+147,107,221,3,165,84,117,208,218,168,159,103,36,218,65,72,187,179,67,188,187,50,206,194,117,245,225,233,80,169,
+126,30,44,22,22,96,83,190,166,250,187,235,234,101,225,30,96,136,128,201,11,3,95,112,254,247,151,232,142,204,
+60,171,206,98,51,230,34,232,20,48,147,247,165,46,122,214,240,6,92,15,22,227,177,40,141,249,7,89,90,132,
+74,253,45,210,71,238,21,80,158,149,246,233,89,22,178,177,215,141,176,115,241,153,163,226,188,135,7,117,247,5,
+210,175,240,174,220,92,229,240,125,19,226,164,33,70,6,51,199,111,148,123,247,165,125,158,244,18,2,198,207,34,
+70,121,49,1,50,208,99,156,62,17,11,220,110,142,172,38,162,3,111,235,135,129,162,66,253,12,93,7,21,79,
+81,80,197,230,237,179,14,7,248,35,142,20,108,73,221,205,251,94,124,195,23,90,132,28,181,37,194,41,93,55,
+78,188,17,34,150,0,64,116,205,106,60,27,85,4,190,16,41,227,100,33,143,187,168,167,152,38,170,161,215,197,
+89,39,229,113,17,111,30,71,230,205,96,49,254,243,179,196,120,6,51,49,17,23,56,250,42,70,239,38,121,15,
+66,78,208,166,178,121,217,23,19,86,37,158,0,251,187,177,47,247,114,64,246,10,25,222,168,144,239,109,211,45,
+30,45,198,243,71,115,124,0,91,23,252,96,105,63,146,26,190,96,128,81,127,220,227,63,139,199,137,156,156,72,
+236,87,39,107,254,56,165,248,73,39,126,206,241,162,163,237,88,75,110,178,148,21,38,14,44,88,213,222,133,217,
+12,31,149,123,54,54,163,30,251,197,57,137,51,35,90,226,183,60,169,110,29,59,221,154,227,150,184,221,177,246,
+166,112,44,201,82,144,52,77,109,165,131,202,214,146,48,48,1,123,251,90,38,67,200,185,177,66,229,223,111,97,
+113,107,169,187,171,137,89,18,184,134,135,239,96,119,185,110,52,250,152,207,241,202,61,112,223,82,5,156,83,22,
+30,95,220,59,204,142,94,91,100,85,141,54,206,242,4,126,150,210,30,151,120,33,105,187,196,243,118,248,112,225,
+193,113,91,246,209,19,185,86,23,77,180,191,240,66,174,232,129,181,172,163,181,144,151,54,132,91,106,109,199,205,
+172,119,168,206,10,24,193,219,252,229,163,5,209,51,171,71,115,39,18,207,195,230,253,214,27,63,239,237,139,241,
+70,176,114,121,191,238,21,215,125,25,214,109,162,194,170,195,69,160,100,91,177,157,14,134,171,142,253,128,214,228,
+46,209,37,52,101,88,38,197,28,120,44,150,48,197,221,209,71,180,60,42,169,9,234,132,180,172,69,188,122,81,
+100,252,36,68,185,232,67,196,157,218,237,111,152,179,215,34,197,118,235,71,100,173,23,67,150,88,218,253,241,118,
+159,225,233,184,236,172,12,86,201,194,95,85,43,217,206,84,210,35,255,115,181,191,97,30,42,203,132,122,72,47,
+201,180,115,145,253,105,45,252,225,166,25,188,38,194,171,160,255,92,138,46,94,60,185,176,8,200,133,201,96,246,
+189,211,2,208,221,92,109,115,232,221,6,94,66,243,89,58,139,230,170,126,68,51,141,167,225,145,246,107,49,135,
+96,112,197,212,144,70,8,115,137,195,48,196,7,62,17,81,180,141,213,197,124,52,155,187,197,139,35,254,132,119,
+94,204,74,223,3,72,51,3,227,104,62,89,142,43,241,8,115,80,254,96,95,160,65,218,99,49,128,78,251,242,
+155,201,226,142,242,11,44,111,79,22,206,134,223,71,198,105,126,195,129,105,56,202,8,89,234,62,85,248,193,194,
+85,233,171,128,44,190,111,140,252,195,104,134,80,125,232,100,219,246,143,216,174,179,117,161,242,253,243,228,71,218,
+159,67,185,159,89,116,227,186,182,142,122,29,221,207,218,43,221,183,100,180,183,8,67,217,251,117,244,77,38,237,
+207,204,96,1,33,90,38,198,135,239,218,240,174,236,30,44,58,222,198,138,95,227,207,178,238,158,101,102,231,122,
+9,16,243,105,219,135,80,99,79,47,84,254,138,244,234,123,76,83,190,17,41,185,61,192,129,160,85,190,139,158,
+160,89,27,164,16,6,132,159,154,190,240,211,79,17,154,192,178,112,201,112,82,66,155,20,178,152,76,164,158,76,
+200,233,195,93,4,64,219,191,51,153,209,209,101,189,24,52,249,78,226,37,228,146,98,29,33,114,142,221,166,17,
+24,33,128,151,53,113,203,251,205,168,166,235,156,42,232,89,33,93,21,194,91,174,27,200,231,69,104,118,105,131,
+239,21,123,175,126,238,173,134,12,180,194,31,47,116,5,255,140,201,85,43,57,32,87,242,82,94,200,91,121,101,
+214,194,218,214,212,104,84,19,165,5,16,248,157,165,180,8,114,67,61,39,207,17,56,223,175,74,239,54,34,21,
+178,48,168,148,90,171,205,81,221,160,155,97,185,82,53,250,37,197,63,160,30,133,188,70,148,17,254,148,26,187,
+163,151,144,207,139,127,200,11,117,11,157,123,136,82,136,32,208,250,13,252,136,11,149,103,48,47,43,235,131,127,
+133,18,50,23,104,212,230,86,93,78,205,99,63,244,209,100,196,206,91,8,55,167,57,52,210,143,227,241,82,92,
+169,57,136,61,98,189,87,182,94,252,137,6,107,190,130,154,199,234,82,76,201,250,236,133,144,149,253,186,237,104,
+49,92,200,164,99,193,235,22,213,7,170,101,84,123,189,171,27,229,237,89,66,230,107,85,113,48,23,114,171,78,
+213,179,136,48,224,242,236,20,38,135,241,224,202,6,89,45,143,144,195,109,132,218,17,137,249,66,255,178,22,73,
+196,208,141,32,60,17,3,215,66,154,90,235,184,164,10,145,227,223,238,57,117,105,194,23,194,190,56,69,71,120,
+38,121,139,25,76,2,100,48,25,177,116,219,191,174,195,179,227,207,133,107,228,233,49,128,159,103,94,197,100,134,
+156,206,216,100,220,107,94,159,53,78,3,37,108,229,165,241,204,108,26,31,224,12,34,136,80,39,147,70,176,104,
+82,159,197,56,110,30,133,232,151,235,218,155,36,26,224,32,206,126,9,9,82,169,229,177,136,109,119,168,27,60,
+23,193,184,163,102,210,111,84,60,30,106,115,160,255,179,147,9,58,168,234,184,238,229,69,24,158,39,23,139,5,
+108,140,16,109,24,230,139,195,248,200,196,151,59,186,50,194,117,129,199,190,167,199,51,29,55,207,240,243,217,241,
+12,73,49,207,86,27,94,87,231,218,182,121,166,160,84,243,84,7,4,13,171,97,178,241,227,130,159,226,241,33,
+146,3,42,95,238,191,184,203,198,188,41,134,3,15,10,119,194,42,89,6,107,212,173,5,227,161,26,47,126,60,
+204,107,33,62,139,62,68,56,21,138,149,102,152,130,66,176,94,251,120,166,165,48,190,60,64,167,85,112,193,245,
+52,45,240,200,39,170,156,149,29,238,200,184,66,171,84,24,221,231,21,84,222,36,254,16,3,57,127,84,60,75,
+30,213,179,4,88,33,249,227,58,206,31,213,79,147,71,197,44,135,112,242,184,110,67,34,121,120,42,136,76,229,
+70,30,186,135,140,217,195,135,77,124,247,243,53,91,120,230,11,235,155,240,149,46,220,68,76,74,244,157,143,134,
+157,145,59,75,233,123,92,167,106,85,141,243,229,132,203,243,33,58,95,46,247,25,102,99,32,235,79,98,0,158,
+11,75,147,203,57,94,138,27,85,222,35,248,129,183,152,215,55,154,109,66,47,82,168,150,163,214,128,111,95,122,
+135,36,31,249,180,2,232,40,228,71,185,22,173,185,118,205,245,42,193,151,181,220,202,83,249,65,190,148,191,202,
+87,242,189,225,73,56,76,13,110,186,203,40,224,207,227,21,17,4,39,11,249,65,93,76,86,242,87,204,102,16,
+219,241,74,190,87,13,165,243,101,88,121,124,47,168,19,243,67,81,83,80,190,199,88,215,12,84,185,85,23,80,
+215,7,229,114,142,23,221,218,16,9,231,186,24,37,190,14,201,183,133,60,53,189,123,105,170,198,2,216,189,87,
+170,177,233,221,250,48,42,172,208,100,135,162,182,32,148,130,120,91,14,123,119,141,189,131,234,57,107,208,61,109,
+209,89,131,169,84,94,234,207,214,109,167,105,204,35,5,17,196,163,175,4,151,253,45,170,152,92,253,216,17,56,
+172,140,192,225,107,85,157,125,60,159,98,77,1,136,177,18,152,144,176,15,140,95,11,209,250,41,166,102,253,236,
+110,199,139,182,211,239,237,225,126,155,97,54,44,175,248,127,220,105,152,225,9,206,240,245,100,17,174,2,181,79,
+204,221,183,32,223,79,199,170,171,52,35,209,146,106,64,81,157,72,47,202,191,124,252,86,88,193,22,64,236,166,
+183,79,151,83,180,253,217,240,8,238,62,130,183,66,192,128,62,6,90,122,127,133,144,85,203,219,54,80,214,235,
+42,153,167,231,235,6,146,251,122,121,114,137,177,172,251,39,63,184,160,117,180,120,227,130,207,187,117,213,97,124,
+88,223,244,74,149,246,210,145,183,136,4,94,133,166,114,110,148,57,249,87,242,181,144,249,236,26,112,188,151,234,
+149,186,137,183,234,131,250,85,189,87,55,114,78,214,187,155,219,147,248,90,54,219,147,120,43,155,219,39,241,41,
+124,63,137,63,72,136,126,41,33,246,87,9,145,175,36,196,189,39,83,67,175,165,25,121,252,215,80,17,113,219,
+236,43,34,94,55,129,170,227,178,9,84,27,63,96,32,28,82,124,211,141,225,58,234,166,13,175,224,190,108,222,
+114,64,54,15,208,242,46,173,114,63,220,103,80,207,48,190,38,17,149,178,85,133,172,6,1,124,18,0,120,73,
+140,174,60,212,50,76,153,235,181,116,186,146,139,86,149,114,142,208,191,176,124,126,185,81,243,241,18,32,252,98,
+54,89,198,27,128,229,147,3,247,255,37,220,21,119,1,113,249,86,141,86,217,124,158,107,195,19,171,25,158,119,
+193,247,90,158,122,196,224,103,244,39,103,230,200,244,216,248,175,243,103,188,14,33,248,214,67,229,223,89,5,129,
+109,62,106,92,244,151,129,162,115,49,61,197,13,15,199,206,68,202,107,8,221,182,92,159,7,219,127,188,194,62,
+224,174,67,0,184,85,3,96,123,19,192,191,250,0,252,171,9,254,213,8,255,182,234,115,161,223,120,211,222,55,
+171,251,80,187,223,233,107,181,15,179,39,191,187,211,215,159,221,233,246,244,190,201,247,19,223,82,175,81,163,42,
+224,6,190,181,187,52,206,3,38,224,91,191,237,152,134,106,134,209,89,3,211,47,212,177,188,245,130,138,23,79,
+111,129,220,190,16,187,43,149,128,140,190,188,81,87,246,48,77,63,11,218,95,64,163,31,6,217,198,144,52,166,
+167,96,130,233,47,239,102,68,92,32,174,243,50,228,44,188,82,223,0,149,60,187,97,197,19,234,211,107,245,10,
+112,184,240,90,129,207,158,18,181,189,87,122,186,214,211,106,22,93,171,15,146,207,251,44,197,47,84,112,6,54,
+219,10,249,231,179,247,106,242,234,209,175,227,95,81,125,40,216,46,24,175,155,30,114,15,27,230,53,230,141,135,
+18,185,138,126,253,3,85,31,168,57,30,72,193,222,201,5,44,252,251,71,202,40,150,70,112,79,1,234,18,157,
+76,94,137,71,80,183,101,211,45,141,187,182,143,71,123,106,219,110,79,195,149,154,55,144,161,167,139,43,240,114,
+213,174,177,26,183,68,141,17,150,204,193,176,169,254,57,96,70,239,39,31,44,222,244,79,117,141,159,120,150,166,
+245,77,6,132,70,244,22,154,73,106,237,128,108,252,124,162,110,144,183,125,89,233,228,106,138,73,180,107,41,201,
+38,180,84,250,148,74,211,4,197,255,156,168,186,87,218,156,88,74,161,194,203,134,148,25,254,105,68,21,159,59,
+243,128,205,248,3,117,223,241,106,110,76,148,13,208,5,237,39,194,108,159,182,189,164,59,159,117,68,86,210,58,
+225,189,145,200,45,139,95,242,205,94,251,93,135,87,123,237,247,27,222,234,184,5,233,126,126,47,249,128,199,167,
+248,109,72,126,227,135,244,173,108,170,164,168,115,219,212,25,92,87,231,210,117,8,208,1,239,254,230,178,61,4,
+242,104,97,253,181,220,208,181,220,99,55,227,190,56,112,111,178,13,22,58,31,172,170,72,211,109,173,150,240,198,
+101,198,181,21,213,10,0,85,173,168,32,39,49,188,170,249,78,146,117,123,8,22,54,123,131,209,206,202,66,128,
+51,20,14,83,168,25,121,40,219,238,96,101,53,12,10,17,33,25,151,50,87,85,135,140,55,3,76,37,51,124,
+2,165,162,26,223,98,152,120,194,194,5,159,237,89,234,198,91,132,231,58,74,249,91,46,199,42,135,179,25,99,
+156,169,192,70,225,249,13,171,157,36,189,106,49,246,206,122,39,92,175,237,130,164,234,48,0,181,107,70,2,194,
+33,152,107,175,252,227,77,77,120,4,92,107,242,199,231,37,152,15,168,221,39,236,252,241,73,229,109,188,108,187,
+168,43,170,219,69,230,158,31,120,4,176,59,197,155,176,235,203,148,203,222,211,129,219,120,120,90,120,23,0,16,
+15,230,147,42,35,27,229,94,112,30,191,88,248,157,160,76,40,39,111,62,91,174,120,255,197,39,172,216,33,146,
+182,254,174,80,189,253,118,85,59,163,166,134,249,193,62,235,163,240,205,161,241,18,26,61,175,246,0,36,108,11,
+133,180,74,142,196,227,102,238,54,241,31,181,125,210,73,174,141,220,238,17,251,201,87,154,66,104,135,47,34,135,
+74,152,3,221,108,149,149,99,113,190,113,68,33,227,69,135,158,110,16,225,191,95,4,170,175,216,90,135,124,164,
+5,112,238,141,27,49,52,25,69,242,103,104,185,206,219,150,4,46,232,76,223,133,222,212,66,120,66,54,62,54,
+115,139,28,178,59,187,205,12,178,230,86,214,106,64,248,157,24,162,221,88,202,121,136,15,39,156,3,10,86,76,
+137,140,34,62,90,95,124,184,116,62,37,224,203,220,74,200,175,117,171,84,248,17,40,202,8,113,246,150,178,107,
+71,133,48,214,46,17,210,148,209,178,71,169,187,154,60,193,169,56,11,71,65,30,163,196,240,46,105,150,166,109,
+180,56,247,177,140,242,35,116,129,177,165,58,48,38,133,152,20,98,184,47,152,61,220,46,184,250,126,161,189,187,
+141,186,239,190,137,229,131,106,180,6,168,143,122,246,133,192,91,83,4,246,203,160,7,39,114,11,63,219,147,86,
+218,240,19,27,126,210,162,149,74,237,149,171,185,68,67,69,26,46,211,80,161,6,75,237,44,6,144,123,206,4,
+29,155,220,179,46,66,186,63,239,241,38,246,185,0,62,71,24,141,86,192,61,75,211,159,104,178,127,139,39,219,
+203,94,89,14,108,65,247,32,106,166,223,195,48,45,85,17,50,76,235,46,195,212,156,193,178,11,55,171,187,235,
+60,14,15,141,76,212,30,215,193,170,254,219,247,204,97,1,245,28,89,50,141,244,224,180,20,147,18,112,254,52,
+136,175,44,92,21,227,10,18,150,106,161,18,188,137,130,12,8,53,169,220,130,163,25,106,82,193,92,165,80,80,
+106,119,90,116,112,90,58,83,33,117,120,102,56,205,46,187,238,236,122,205,187,222,176,217,120,199,203,133,224,90,
+48,155,223,237,102,121,253,43,61,206,249,192,29,198,64,47,92,140,125,96,51,112,41,78,97,79,111,51,132,203,
+108,61,37,124,73,239,66,37,142,26,170,175,11,143,156,99,181,208,246,74,232,27,59,180,188,98,108,184,34,234,
+140,102,91,137,198,204,25,235,198,231,247,224,58,241,9,12,155,248,118,241,105,118,111,248,48,46,121,16,36,96,
+231,35,232,50,166,206,47,160,21,143,157,79,191,192,123,107,41,143,229,66,166,248,48,12,83,118,13,83,102,215,
+230,35,10,50,30,186,75,67,36,21,243,197,5,219,79,171,233,28,90,115,54,253,21,228,165,128,166,73,56,181,
+82,57,6,216,101,70,162,10,139,66,147,189,140,210,19,200,72,17,117,5,69,2,29,122,8,161,114,62,28,165,
+177,170,220,158,255,38,42,204,136,141,159,213,113,167,174,71,148,228,101,182,132,136,177,44,206,169,237,168,211,165,
+79,157,46,253,210,235,210,47,188,46,253,188,85,75,226,181,230,82,203,68,224,204,54,210,86,15,211,123,44,75,
+7,57,11,90,220,193,106,100,128,237,45,163,196,88,16,237,18,77,142,186,236,210,78,0,86,206,91,187,106,120,
+150,6,16,8,218,232,125,68,73,218,88,190,226,57,130,33,47,199,240,134,240,17,124,122,69,75,30,97,238,147,
+19,135,13,70,31,71,191,225,171,98,161,190,38,137,102,76,192,223,163,223,36,44,4,161,43,67,3,225,214,129,
+181,160,181,119,164,111,226,102,232,127,70,75,252,140,107,64,19,56,115,84,163,15,154,24,147,139,48,249,254,57,
+169,247,103,160,109,37,214,51,62,177,53,69,136,144,244,231,13,51,13,246,133,167,205,244,168,61,244,78,25,98,
+91,140,177,223,231,166,189,240,172,235,241,8,105,204,215,47,71,50,116,229,21,184,240,210,7,112,138,68,105,196,
+41,18,244,103,169,108,125,184,58,209,67,120,212,78,172,213,7,165,240,56,237,185,216,170,219,97,62,215,61,154,
+22,119,221,171,141,215,252,5,128,161,45,192,104,81,189,209,26,210,236,239,183,67,29,56,22,193,185,167,26,163,
+187,85,35,67,93,72,16,141,112,214,50,190,209,161,137,140,208,190,177,157,27,186,113,235,180,132,128,179,140,1,
+128,17,182,146,118,138,98,25,94,40,142,191,154,86,26,245,187,140,58,93,155,213,200,74,132,122,2,169,23,202,
+231,55,122,86,191,115,223,223,47,216,42,167,109,223,103,147,65,17,92,162,79,104,254,184,10,151,194,86,140,211,
+29,212,231,100,222,138,233,102,25,105,132,154,180,169,184,6,45,2,139,205,60,28,89,90,219,32,149,242,227,31,
+143,142,70,227,146,208,169,102,89,149,55,15,208,240,249,215,72,150,70,35,59,159,243,82,215,15,138,18,184,119,
+128,140,60,0,52,238,193,104,236,201,149,18,12,11,63,192,107,218,88,191,109,228,2,237,212,85,48,227,157,137,
+5,10,237,91,254,142,76,55,26,14,215,168,126,128,199,44,152,82,238,54,42,94,181,155,98,96,118,194,161,21,
+118,104,117,48,180,105,129,61,131,134,217,2,118,113,142,214,192,76,244,183,224,153,17,38,142,146,48,132,169,189,
+30,83,234,63,27,72,11,109,48,47,246,108,79,189,208,209,192,94,145,103,122,246,45,46,30,44,8,74,170,217,
+111,244,148,201,134,127,207,5,25,62,109,100,225,227,201,2,48,244,0,39,179,23,107,179,89,155,135,101,5,153,
+2,203,136,77,55,45,116,112,76,198,143,194,39,131,198,219,18,239,218,142,66,225,200,38,130,173,33,12,166,190,
+46,215,145,241,207,158,157,59,175,74,133,56,250,181,204,10,155,167,82,40,93,25,150,74,84,69,165,114,248,226,
+156,108,204,178,148,120,13,39,162,99,84,106,233,141,74,141,178,249,8,86,9,60,22,140,220,76,153,48,157,240,
+79,203,33,27,213,222,156,129,117,11,241,141,142,78,27,57,34,215,221,245,72,178,50,50,185,246,230,108,183,144,
+205,197,141,40,207,218,168,6,114,22,59,111,114,68,209,148,203,190,173,112,38,173,229,200,196,112,250,5,30,217,
+249,123,179,121,171,12,125,190,245,187,26,214,211,237,221,57,218,106,143,142,142,142,88,70,77,227,82,141,220,81,
+24,201,198,89,79,31,200,181,41,194,124,88,213,11,223,232,221,181,202,126,31,77,241,175,169,91,247,151,229,33,
+216,130,164,100,121,127,57,158,116,83,236,3,78,201,253,165,120,242,12,43,199,143,177,15,75,46,240,236,237,15,
+77,142,124,96,100,170,160,113,30,46,239,135,199,187,198,150,180,3,61,92,144,199,231,182,145,45,102,6,122,184,
+20,111,14,178,78,230,214,252,238,229,220,20,119,46,40,213,65,99,189,191,130,112,216,92,154,23,246,222,194,60,
+116,46,203,171,123,127,81,94,95,155,131,238,243,51,40,170,189,255,133,154,1,88,137,62,189,120,14,233,232,109,
+221,165,93,139,41,36,151,112,67,251,24,8,43,165,194,94,34,234,148,205,103,212,175,91,157,70,141,49,115,16,
+255,24,213,178,226,166,146,59,155,170,196,180,83,65,130,142,30,240,63,138,232,58,30,253,100,124,0,252,45,42,
+206,156,37,222,113,125,46,209,132,162,144,40,254,24,193,47,166,146,57,94,78,108,135,154,38,11,127,214,206,247,
+49,200,147,15,2,35,150,146,31,143,253,85,54,152,147,124,44,20,71,33,246,35,216,202,36,125,132,51,104,186,
+213,31,163,166,11,144,164,27,72,216,101,15,239,248,207,209,127,142,155,241,127,142,30,100,22,239,72,30,184,45,
+161,231,15,254,115,92,140,205,93,194,40,173,177,40,254,177,49,64,248,211,146,28,211,173,7,175,136,11,180,218,
+4,200,118,107,213,191,189,198,19,98,204,52,239,175,33,11,62,9,5,5,236,167,189,218,95,250,235,53,106,252,
+149,114,65,53,250,82,178,145,35,227,115,33,207,253,35,120,169,106,218,85,243,176,30,225,124,161,195,22,27,74,
+150,149,234,180,82,74,59,179,225,139,16,41,137,107,228,228,152,55,250,189,18,163,26,185,250,119,118,120,83,248,
+46,203,170,189,232,207,83,173,0,213,235,120,236,47,209,169,82,35,188,143,24,218,1,136,3,156,21,198,148,177,
+70,198,187,163,40,204,70,250,27,250,224,145,149,48,254,41,241,176,165,232,153,194,56,148,20,236,40,144,62,208,
+212,22,112,201,51,178,177,240,83,20,216,191,17,204,30,42,243,185,181,81,22,164,202,224,219,237,181,54,156,89,
+226,106,133,21,242,86,230,40,90,185,78,205,135,119,4,47,73,56,201,31,26,116,211,183,68,171,41,102,53,117,
+59,84,180,239,1,135,172,145,200,26,205,225,122,71,159,252,201,183,201,174,69,236,108,181,140,252,134,168,105,102,
+31,234,217,217,121,124,177,180,240,11,90,104,135,187,196,56,117,119,54,141,252,90,209,153,211,90,25,165,96,124,
+187,160,61,155,128,41,113,180,87,178,210,81,174,158,37,212,45,52,69,168,84,238,67,112,6,58,27,175,54,6,
+159,14,109,75,163,242,66,169,248,120,27,226,223,171,158,249,99,169,59,146,48,31,27,106,148,136,3,111,14,11,
+29,110,213,79,153,172,174,1,238,89,211,189,88,198,95,224,26,200,1,33,188,111,6,87,29,206,70,175,174,34,
+172,203,95,64,80,193,180,97,29,141,82,40,235,16,151,26,43,69,187,111,119,249,178,99,157,244,33,108,128,12,
+215,144,116,27,204,247,241,108,215,198,153,47,114,177,28,242,9,142,118,110,67,2,221,15,223,154,106,110,66,83,
+205,124,145,25,47,229,185,74,144,138,74,21,116,70,131,133,48,227,200,155,253,66,213,36,123,96,103,35,78,152,
+213,120,11,253,112,155,53,145,169,132,241,5,28,7,239,194,124,191,187,60,183,31,144,98,251,171,37,74,104,0,
+196,25,48,41,184,87,106,239,14,158,168,172,247,150,147,80,193,134,44,228,217,104,116,46,119,222,20,60,26,188,
+55,11,224,2,0,212,176,1,116,201,22,218,98,46,186,54,139,129,152,34,122,1,168,157,192,9,83,20,53,156,
+130,209,130,146,133,93,101,228,228,0,42,16,6,116,24,64,69,57,110,115,187,12,221,112,100,60,44,4,226,214,
+46,253,197,104,166,85,19,219,24,243,68,120,129,16,93,43,82,186,155,129,20,86,12,191,66,106,95,237,53,85,
+27,84,215,204,184,194,152,43,242,37,110,160,4,187,37,161,39,223,108,255,201,151,116,116,179,224,193,217,27,142,
+230,76,219,160,226,186,232,117,5,123,77,197,32,227,44,139,209,254,33,78,12,116,193,187,122,22,144,195,176,209,
+78,27,228,7,53,229,155,242,6,173,6,212,58,10,150,236,106,217,93,178,127,54,222,73,227,142,204,218,238,218,
+214,240,4,108,16,23,10,41,217,34,178,25,165,217,100,67,20,123,53,20,59,228,135,171,240,180,115,232,22,174,
+56,75,172,55,170,223,162,156,17,36,76,44,115,125,164,13,118,243,143,215,246,58,123,96,250,246,192,89,77,74,
+204,216,160,78,27,31,63,248,98,151,180,255,16,88,89,126,116,129,62,175,182,253,250,110,146,170,128,234,62,21,
+37,170,199,61,168,232,56,60,64,31,154,128,41,37,245,3,58,161,3,213,178,111,188,194,186,195,91,42,216,62,
+41,25,173,13,166,109,90,130,206,158,194,63,192,91,148,21,12,79,93,31,96,118,88,141,210,180,149,185,92,64,
+126,248,179,60,7,190,137,144,153,57,57,124,124,6,39,206,242,45,217,203,102,170,146,240,248,20,198,239,14,246,
+45,130,213,206,233,228,5,189,12,151,102,225,151,102,206,45,108,212,22,130,50,69,85,140,228,108,195,188,87,168,
+170,60,219,192,223,205,180,66,229,66,248,3,129,161,241,193,176,49,209,141,115,211,202,2,131,139,179,57,142,18,
+199,217,149,161,31,28,102,133,251,3,106,202,229,217,183,78,48,51,183,155,87,82,132,153,178,42,240,139,80,14,
+250,69,0,204,135,191,209,21,218,148,111,61,100,216,119,112,3,119,12,20,157,28,95,119,83,133,134,188,85,102,
+14,74,198,43,165,252,167,193,4,50,178,74,168,232,131,98,125,125,223,45,15,214,167,176,45,243,37,164,25,146,
+204,156,91,204,218,185,197,148,186,50,159,31,116,51,245,14,12,117,8,45,223,212,134,134,200,60,234,107,236,84,
+162,150,22,36,89,183,148,90,64,69,232,195,210,104,81,105,106,230,147,246,102,237,25,207,250,75,99,253,219,21,
+129,232,125,102,138,22,194,249,184,62,237,146,18,76,175,218,147,171,96,204,222,4,25,94,86,6,115,226,33,117,
+152,222,85,39,13,137,255,7,240,242,214,160,43,28,175,159,23,214,126,228,146,77,94,220,39,7,242,97,82,91,
+83,158,126,31,137,239,109,234,192,21,56,80,7,38,181,53,229,233,215,193,139,216,8,83,15,109,189,3,85,81,
+106,91,7,57,251,21,82,60,245,139,54,236,129,250,40,213,217,167,244,231,33,204,101,241,203,52,215,137,157,231,
+8,119,26,246,55,140,218,245,87,202,22,136,68,127,165,194,180,150,142,65,136,166,80,63,113,127,54,18,31,152,
+206,206,254,193,32,238,139,93,211,254,67,2,74,114,206,101,79,157,123,185,160,18,169,195,106,254,129,165,142,240,
+217,208,94,135,80,139,134,90,250,117,247,114,213,148,237,31,123,81,231,242,238,30,17,247,231,238,254,76,238,232,
+4,49,132,184,7,97,42,134,195,116,110,124,31,225,11,60,114,122,57,37,220,178,211,78,95,138,118,98,203,118,
+187,100,227,92,27,200,80,194,243,107,230,33,201,67,28,18,129,21,118,192,18,50,115,27,217,37,187,250,123,131,
+68,75,11,199,183,32,92,240,33,212,101,30,94,60,228,42,136,139,143,111,25,117,219,195,94,187,246,84,29,218,
+92,91,183,1,101,215,254,80,191,119,133,229,166,99,7,52,217,215,161,89,73,156,37,76,134,153,222,31,240,18,
+95,51,241,61,29,231,2,225,211,146,147,22,234,217,39,141,215,169,92,8,49,148,80,203,197,96,60,220,188,165,
+185,121,15,164,127,123,32,190,41,48,161,245,56,199,105,85,37,219,163,69,85,174,34,143,92,165,68,150,88,47,
+185,169,165,53,6,238,97,3,219,151,73,109,94,190,42,51,235,26,175,245,180,69,196,177,59,237,253,25,39,71,
+13,93,181,229,179,6,71,166,237,200,2,244,159,98,118,84,4,134,215,20,231,45,129,135,183,201,74,207,249,237,
+212,114,71,20,146,32,158,8,220,125,81,67,135,244,28,9,14,185,115,96,37,174,208,55,244,187,74,47,178,91,
+93,163,1,157,143,117,52,0,121,36,110,37,146,174,168,112,217,95,44,163,74,162,95,131,242,136,42,70,211,228,
+133,122,133,143,49,179,34,18,113,193,19,140,245,245,104,36,220,73,40,245,0,181,105,168,168,128,41,107,61,19,
+39,69,38,142,22,6,215,203,225,15,63,238,181,253,90,112,168,102,160,222,78,16,15,173,60,60,152,128,87,101,
+4,64,160,19,37,84,101,175,92,100,172,150,1,125,15,149,116,220,102,100,238,248,21,40,65,200,71,46,227,135,
+51,255,218,169,237,99,19,201,37,210,193,245,148,99,9,21,148,202,247,248,166,48,231,191,179,36,58,228,107,36,
+93,34,4,112,210,52,223,204,97,107,141,150,248,78,56,130,125,77,71,191,150,37,138,173,181,164,199,96,60,238,
+252,102,220,32,250,71,220,239,111,10,244,62,170,171,102,139,27,168,134,228,35,88,200,77,170,157,3,111,120,193,
+135,5,69,191,62,66,62,60,9,28,144,189,8,137,158,93,86,127,240,132,174,150,128,201,50,165,91,192,34,32,
+122,21,176,232,234,14,139,174,84,198,199,116,165,10,252,73,84,84,1,10,140,222,221,206,44,111,14,61,55,65,
+31,18,32,198,62,44,225,7,126,193,101,212,55,248,197,28,57,230,209,25,103,142,75,53,250,242,232,191,142,78,
+156,59,203,151,75,117,102,168,73,233,8,73,73,162,217,78,102,122,196,158,72,70,231,126,140,95,215,93,170,113,
+144,40,133,208,203,37,179,86,50,102,173,96,142,144,200,126,223,173,204,197,35,211,137,35,53,16,241,80,174,128,
+159,25,242,216,39,5,252,137,49,118,130,113,193,150,124,94,119,145,112,150,206,246,70,119,220,245,62,237,27,23,
+181,140,217,247,186,152,227,134,145,127,179,254,125,203,226,69,137,22,96,26,45,161,169,14,86,254,253,242,243,27,
+227,218,96,99,125,130,125,93,239,213,150,133,56,62,122,12,134,201,50,30,131,113,130,71,214,180,10,80,228,202,
+121,178,63,242,111,96,207,183,175,231,80,56,206,96,119,120,131,52,153,241,69,37,36,198,146,11,109,27,75,1,
+143,217,111,50,52,80,94,84,120,22,120,60,216,159,62,73,77,158,109,55,25,51,194,181,122,166,3,191,222,194,
+62,39,7,190,76,223,236,61,194,135,228,215,254,254,47,252,254,31,215,214,87,158,10,216,214,102,247,211,131,63,
+126,203,72,63,67,55,237,207,26,129,131,59,43,199,232,179,90,180,33,152,10,248,89,116,32,152,128,197,221,184,
+42,55,181,46,55,205,200,178,240,138,89,19,243,3,118,22,146,20,3,56,8,209,22,8,234,78,151,198,141,25,
+206,155,97,91,20,248,74,128,3,24,16,216,176,254,156,241,221,36,201,225,112,205,183,40,235,0,189,56,122,96,
+4,143,193,131,117,179,124,240,250,229,131,255,28,141,75,192,181,198,163,255,124,176,218,64,171,151,250,193,220,62,
+28,0,223,192,62,131,0,254,173,31,216,5,192,31,204,82,105,168,106,142,111,47,44,113,219,191,101,32,98,255,
+22,30,48,174,107,80,117,38,110,112,156,81,225,130,96,137,31,188,92,35,34,213,201,116,100,113,255,23,102,102,
+162,66,176,200,121,55,87,207,175,124,45,129,18,172,215,176,49,140,175,110,20,72,64,217,107,218,90,50,85,192,
+216,204,157,58,196,210,132,72,233,134,173,210,205,213,109,18,9,239,45,39,161,79,187,57,243,208,189,77,215,62,
+95,74,36,133,35,116,42,10,7,253,177,157,15,34,108,22,146,213,243,14,95,86,154,40,114,142,169,27,16,136,
+171,123,142,121,110,181,207,145,110,170,74,23,123,238,204,59,37,24,12,119,98,47,200,163,55,183,133,150,130,140,
+131,246,110,182,156,220,181,35,255,193,83,79,107,24,42,148,126,195,137,157,50,181,145,141,251,174,63,28,98,80,
+112,61,161,244,197,154,102,149,29,191,115,174,37,72,90,234,2,238,190,44,13,162,147,166,233,186,110,185,240,158,
+189,95,102,181,241,194,25,118,170,239,218,133,10,205,203,247,198,101,188,186,76,16,149,53,145,68,126,46,208,148,
+83,101,82,95,106,99,243,246,56,180,128,79,207,42,198,50,72,118,70,155,232,220,98,249,15,19,208,135,200,197,
+174,203,19,28,189,74,178,28,142,94,83,62,176,7,234,129,21,163,199,147,247,159,205,3,218,211,15,168,159,15,
+16,117,54,231,243,19,76,116,241,0,95,57,248,65,180,125,215,28,217,133,177,210,174,163,148,174,153,145,124,94,
+11,217,79,93,211,181,49,146,223,47,133,244,143,129,89,146,27,67,55,221,41,133,171,35,152,6,203,8,8,54,
+239,30,194,189,11,18,141,205,160,172,104,224,223,105,16,171,91,82,79,40,156,86,79,45,47,194,98,101,215,200,
+16,188,255,137,25,220,121,229,172,140,235,89,241,184,142,13,116,61,200,220,184,147,183,209,97,109,220,197,214,184,
+139,159,177,199,206,8,39,176,91,79,23,49,8,31,156,69,215,173,184,63,71,51,140,199,176,169,45,174,44,130,
+221,205,61,239,157,113,170,236,18,176,36,115,108,25,6,15,33,38,65,243,150,81,226,251,156,213,81,0,234,24,
+2,82,102,124,182,243,121,97,99,153,8,76,162,12,212,105,115,187,65,114,181,41,10,192,53,108,14,122,5,183,
+89,158,91,91,233,85,114,227,12,249,54,110,51,232,54,246,57,169,178,150,3,225,189,25,206,136,172,85,216,113,
+36,4,6,246,30,237,230,16,250,86,189,219,4,101,127,173,123,120,99,247,169,54,247,125,105,4,224,251,179,14,
+180,69,191,236,30,240,53,2,113,254,190,152,141,236,64,224,113,198,158,176,209,212,39,170,106,192,228,107,69,31,
+159,115,147,184,173,146,128,148,2,34,49,67,59,128,218,151,59,252,137,171,214,200,152,0,54,105,64,31,121,45,
+144,149,5,210,195,176,128,225,100,148,11,138,170,12,170,139,218,82,186,168,55,21,201,250,124,155,92,235,215,47,
+235,104,88,208,56,100,230,255,24,105,137,90,33,200,168,53,239,200,117,75,150,235,191,39,119,10,166,198,187,68,
+217,169,58,199,76,162,80,221,193,17,11,79,124,85,50,129,198,34,243,188,129,126,230,5,242,205,137,134,60,59,
+55,250,133,165,42,157,240,99,215,163,32,236,172,117,20,202,4,105,251,148,90,23,166,90,68,49,16,27,68,173,
+82,251,117,235,84,148,25,76,38,114,206,218,26,233,44,32,142,226,229,140,53,210,137,132,154,35,122,137,185,170,
+100,14,48,6,21,227,146,202,100,132,174,233,79,101,181,197,172,54,182,109,145,195,243,99,84,202,176,127,21,79,
+20,191,247,66,95,115,236,235,18,222,14,236,75,12,92,112,166,37,49,133,8,215,57,39,178,3,136,241,215,117,
+16,47,83,1,252,115,136,130,66,46,78,224,150,11,138,134,73,18,30,61,96,162,143,73,225,5,1,184,121,231,
+66,108,181,0,9,7,72,117,88,244,82,44,20,134,167,129,241,231,185,130,231,122,22,156,91,2,170,111,240,132,
+121,180,203,230,113,110,121,60,75,163,128,198,74,72,102,74,77,176,21,178,56,91,152,11,121,209,194,47,186,113,
+75,144,96,194,137,170,37,109,133,29,16,197,68,13,224,147,158,73,44,204,44,86,77,224,37,198,30,15,201,51,
+42,100,101,184,143,207,203,91,74,51,242,94,246,190,36,164,167,191,109,61,114,71,218,190,221,215,50,162,187,216,
+170,41,97,166,71,136,72,69,200,117,128,222,214,150,30,158,148,246,23,70,248,76,123,9,176,90,105,148,84,0,
+13,130,90,216,6,9,215,15,84,19,144,164,8,140,162,22,19,45,218,65,132,13,50,153,60,199,194,246,0,200,
+236,145,81,167,0,162,222,52,142,44,145,11,43,227,247,67,81,233,133,174,116,145,250,10,24,69,224,81,199,141,
+180,166,60,221,136,99,237,212,147,220,136,217,212,35,203,100,135,56,176,108,152,229,232,160,6,243,112,80,199,22,
+41,124,24,179,173,93,116,216,140,119,76,71,31,228,132,226,150,161,240,201,208,162,177,107,10,67,132,154,228,59,
+167,68,90,223,21,186,239,187,130,41,86,148,93,39,71,12,142,150,10,122,27,18,67,37,189,163,134,152,9,198,
+24,3,113,248,5,176,204,254,194,137,69,207,6,7,167,160,16,242,80,107,66,218,42,84,34,43,255,76,171,202,
+222,147,109,210,193,82,176,144,217,41,170,180,191,128,53,187,226,104,161,137,28,116,140,70,206,64,11,68,93,91,
+29,26,103,188,137,122,225,84,141,176,135,129,84,171,8,3,132,163,26,190,88,63,35,42,154,92,185,43,36,4,
+44,57,1,22,191,214,104,110,117,215,125,46,249,104,224,175,196,200,48,102,217,6,178,35,248,202,219,117,91,150,
+7,106,31,187,126,89,219,42,197,0,64,147,67,45,254,199,127,116,179,165,162,237,14,203,0,65,242,201,5,35,
+38,97,163,206,12,181,93,59,92,125,184,36,27,60,186,220,48,70,129,103,233,253,237,45,35,122,70,29,218,30,
+90,132,83,109,170,139,68,75,222,85,40,104,11,246,219,26,196,81,77,158,145,247,76,215,67,31,232,229,79,51,
+77,194,98,91,93,218,91,247,57,21,250,51,57,21,178,86,7,137,200,135,69,192,137,99,65,194,77,7,69,113,
+66,136,75,157,94,25,100,252,121,86,160,18,37,37,113,254,111,67,90,150,211,88,144,205,139,64,14,79,83,224,
+100,15,209,185,85,57,71,175,214,94,172,18,95,33,172,184,229,158,154,39,214,118,24,212,77,15,183,230,86,142,
+90,21,4,161,142,89,224,44,5,176,182,60,124,167,129,117,104,248,199,112,110,231,183,77,188,104,7,65,79,42,
+36,204,58,122,199,100,14,240,194,114,128,167,139,238,24,120,87,205,59,174,77,198,11,66,233,191,135,61,176,200,
+203,155,72,224,29,93,185,155,56,43,200,226,16,186,78,71,135,139,214,210,42,69,206,208,158,106,184,104,228,147,
+177,50,238,50,17,207,74,17,207,226,77,223,93,97,26,8,18,142,135,169,177,222,10,182,162,195,16,242,119,238,
+111,35,9,162,93,243,91,22,45,222,17,215,38,78,164,231,215,196,57,221,164,185,147,101,199,216,111,141,145,125,
+88,34,36,12,226,132,239,214,206,118,196,231,13,163,245,92,71,137,37,33,100,7,185,111,195,125,238,1,5,107,
+178,88,84,201,222,122,140,14,53,60,39,67,148,1,37,13,98,250,237,254,9,58,140,255,211,131,104,23,83,239,
+241,172,208,171,58,231,107,142,204,196,212,128,237,62,252,193,190,17,0,155,230,225,65,158,22,220,157,77,64,163,
+51,117,181,41,246,105,238,48,70,180,131,167,157,113,162,101,24,29,55,244,50,172,189,181,160,31,138,12,105,203,
+151,158,203,20,9,22,75,181,149,0,94,181,44,231,113,33,141,224,108,92,203,180,220,192,78,40,91,124,226,243,
+12,239,194,200,22,118,213,64,192,73,121,25,151,211,55,40,46,108,112,215,118,176,205,254,196,135,92,47,50,125,
+15,179,231,144,55,7,111,134,248,99,4,132,238,198,123,1,135,227,117,34,188,14,233,173,10,30,33,96,12,165,
+37,192,8,111,79,198,112,46,198,149,195,100,79,72,77,13,34,133,1,229,69,116,236,229,97,75,117,2,170,181,
+122,90,2,8,202,22,102,229,107,89,68,165,16,174,207,116,91,6,15,214,181,109,14,241,74,82,120,195,186,57,
+50,114,211,95,158,157,156,211,10,140,203,179,39,231,118,21,240,251,203,115,180,135,217,5,32,44,135,62,12,105,
+41,27,64,133,187,0,122,213,208,37,232,57,68,251,28,4,217,183,105,206,196,166,44,156,67,146,167,10,8,60,
+77,5,32,48,237,243,164,127,140,60,191,89,214,72,165,163,116,112,64,37,6,36,44,106,134,122,138,9,243,113,
+32,234,1,55,196,87,80,35,136,99,224,192,16,230,208,205,201,248,62,209,63,59,72,1,88,168,202,246,14,200,
+74,115,40,218,30,56,190,111,242,57,227,61,151,235,67,92,139,142,222,141,44,238,184,251,180,161,200,180,184,31,
+133,10,230,107,250,47,213,222,29,112,164,229,43,220,113,179,38,114,152,173,193,146,99,221,138,24,118,199,193,9,
+60,48,15,173,104,123,83,186,207,151,235,15,176,193,179,136,71,37,137,11,43,165,13,243,105,170,211,189,105,157,
+222,187,46,174,59,181,93,1,84,135,14,103,143,186,134,111,104,161,154,9,228,60,188,85,246,106,22,173,187,246,
+118,135,251,67,47,188,253,67,202,221,122,215,160,220,74,200,254,244,172,180,135,61,254,40,220,40,16,99,224,135,
+13,199,222,58,68,36,36,60,71,239,66,150,134,32,203,18,228,143,4,97,240,48,127,213,221,52,125,150,123,171,
+134,243,79,195,104,67,93,203,225,140,134,137,211,82,187,93,145,58,15,83,2,56,196,225,225,185,196,42,239,1,
+119,12,197,60,96,32,122,27,33,214,83,207,50,48,30,32,126,67,56,54,30,55,2,67,118,26,187,224,79,4,
+180,58,38,51,120,16,65,101,247,212,112,120,67,65,110,132,60,108,28,130,106,31,54,36,209,227,185,200,194,153,
+135,112,174,46,107,133,110,26,185,83,245,211,18,153,59,254,110,215,248,152,109,110,97,38,161,97,67,21,68,16,
+138,150,21,247,238,54,86,209,125,2,25,238,59,224,133,109,119,190,62,19,154,126,246,10,19,142,113,119,87,3,
+192,232,141,197,76,245,51,88,244,201,68,139,189,101,53,254,128,238,133,117,212,203,238,8,247,73,208,230,214,112,
+231,46,210,60,91,203,26,169,194,57,81,136,178,236,95,178,21,129,189,198,129,61,75,200,252,110,168,103,167,175,
+98,224,98,77,41,105,105,109,141,90,159,225,86,127,232,56,46,77,104,98,35,201,48,31,185,19,55,89,66,147,
+26,165,141,31,83,186,177,187,103,220,140,115,101,24,152,152,40,103,246,207,57,32,15,42,35,184,82,82,202,216,
+101,193,11,58,132,206,4,207,172,85,35,45,100,245,251,64,52,79,67,168,185,93,159,90,226,7,52,85,191,131,
+43,133,149,23,153,155,246,50,61,194,187,198,104,181,210,22,39,137,152,82,169,145,147,239,24,205,74,66,164,76,
+105,116,50,180,119,139,237,14,227,175,232,47,184,232,49,120,89,156,52,224,78,34,45,75,204,73,92,13,77,146,
+46,212,49,107,89,67,89,33,68,4,177,18,179,66,95,36,21,177,145,126,70,109,216,210,17,246,251,214,106,58,
+216,192,54,12,24,46,92,140,242,67,204,144,227,203,216,117,41,214,242,98,157,84,181,158,99,163,4,153,64,157,
+170,149,4,78,88,224,149,89,38,187,207,114,183,242,182,137,76,39,130,123,204,114,238,45,238,56,106,237,154,134,
+167,29,219,216,20,97,11,247,3,6,2,6,109,159,121,120,239,226,25,58,198,107,163,78,239,70,103,122,251,168,
+56,178,43,96,164,214,74,184,12,97,55,61,116,145,241,67,77,95,248,156,28,118,43,3,122,98,251,57,216,211,
+148,27,120,168,219,166,252,244,201,14,59,172,68,236,246,101,36,112,92,234,225,112,60,78,246,126,29,52,252,225,
+34,14,237,243,69,250,10,223,197,108,132,166,158,225,69,10,202,234,145,44,15,97,131,149,42,3,176,192,226,163,
+44,51,95,71,44,42,58,189,108,140,9,177,210,172,22,156,97,158,138,66,118,164,19,28,206,116,96,146,145,41,
+236,242,150,114,71,247,100,92,180,162,83,77,130,42,173,33,158,108,212,234,234,216,246,7,54,41,142,204,174,153,
+41,54,60,39,112,169,181,56,19,247,103,196,251,116,159,27,191,143,35,172,180,223,170,120,132,131,233,235,134,152,
+185,31,9,25,190,158,132,53,180,23,248,118,239,208,71,169,61,46,100,227,229,59,199,202,113,239,251,234,248,174,
+215,42,68,153,12,174,100,114,12,143,167,165,216,59,113,106,167,206,238,152,92,246,65,223,153,151,36,230,150,109,
+132,122,26,112,133,187,170,32,205,1,38,77,102,4,184,251,194,102,149,134,178,53,139,145,185,116,219,190,65,118,
+189,64,24,134,134,9,207,57,117,159,103,62,144,7,186,227,110,115,165,224,104,163,89,185,63,255,233,245,42,249,
+68,70,94,60,236,227,238,192,93,140,83,251,195,251,55,54,75,27,142,111,199,76,168,31,106,93,81,236,61,210,
+38,152,251,61,199,185,50,113,79,186,234,184,237,215,26,114,133,66,94,155,212,93,177,10,89,56,37,242,157,198,
+231,82,83,158,152,107,118,223,145,161,94,52,41,85,181,86,231,156,30,102,157,207,166,159,85,37,221,247,47,42,
+145,3,252,205,82,160,44,65,56,82,98,243,73,100,41,69,165,33,236,134,199,186,59,200,250,163,139,108,48,205,
+232,225,241,28,12,231,26,158,141,92,166,119,205,6,38,203,6,31,205,83,152,13,206,142,49,168,22,76,103,115,
+184,32,239,61,204,45,90,89,114,113,204,193,2,188,129,152,17,166,147,187,169,192,176,47,150,168,35,39,168,130,
+210,2,253,253,32,195,58,132,44,188,120,73,105,66,115,109,139,86,80,121,101,43,220,19,216,171,59,133,250,39,
+219,147,162,199,242,24,235,12,186,211,74,180,187,118,74,117,133,130,75,98,150,192,238,69,158,117,120,244,153,101,
+29,110,212,240,97,139,23,232,240,244,106,230,104,247,197,33,127,220,223,37,127,172,145,123,5,44,219,62,227,126,
+232,50,214,104,54,223,182,52,114,22,7,209,179,63,57,79,85,202,153,203,66,117,243,3,183,53,240,93,59,23,
+162,144,225,221,125,54,186,24,141,235,241,136,138,248,238,140,206,241,53,205,186,13,101,81,134,228,105,14,247,68,
+34,118,104,67,44,57,103,13,22,184,195,134,218,174,186,13,7,205,78,225,125,52,61,131,118,59,13,86,78,69,
+77,118,75,186,119,103,97,156,89,158,2,190,239,153,224,125,186,55,49,169,200,100,111,235,126,222,254,181,28,230,
+70,236,223,178,166,187,108,182,146,112,236,170,21,129,80,206,208,104,75,97,144,208,100,95,206,251,109,249,128,234,
+124,176,64,147,152,15,146,230,129,169,21,76,243,149,14,25,237,55,75,83,17,219,219,26,132,148,184,35,0,181,
+30,214,104,136,151,95,50,88,6,184,232,139,0,243,221,55,248,84,132,85,136,182,123,169,117,68,228,31,116,223,
+53,3,35,52,210,230,107,247,107,237,111,228,14,68,95,98,62,15,212,114,71,91,45,65,123,39,53,86,73,80,
+122,119,217,71,225,22,157,136,255,248,15,84,41,161,20,218,26,6,41,141,180,108,112,211,162,240,126,105,85,133,
+171,238,123,217,222,169,171,100,141,228,165,193,249,100,194,153,109,228,161,66,9,23,66,252,47,188,197,186,228,192,
+206,36,197,141,172,52,154,236,237,179,75,101,230,45,140,199,127,247,246,206,92,156,236,63,115,10,188,78,42,20,
+125,235,93,145,196,156,235,70,6,250,79,205,81,145,224,6,57,178,66,98,119,178,124,204,190,25,33,21,61,252,
+2,29,122,215,55,121,237,130,31,5,131,97,2,171,248,92,6,65,208,168,140,64,54,19,10,154,103,167,121,95,
+74,209,84,209,238,55,47,118,221,119,85,243,242,65,243,17,40,109,106,182,37,190,15,73,240,21,173,64,68,38,
+87,167,134,204,73,21,40,141,52,253,35,5,121,114,49,45,248,232,245,206,218,223,34,192,115,10,179,89,228,89,
+35,237,34,58,145,76,80,88,176,233,47,114,48,168,186,151,238,208,145,165,194,3,158,120,35,42,17,88,207,223,
+63,237,201,161,131,141,69,241,104,239,65,131,84,46,219,193,145,19,207,5,55,198,190,70,12,237,128,51,75,101,
+23,20,124,160,121,75,236,31,241,142,93,165,187,152,61,165,61,72,136,221,181,45,185,102,170,13,182,241,99,244,
+41,59,202,32,2,119,80,45,65,41,41,27,150,176,0,6,123,3,248,140,19,225,153,235,69,86,104,210,220,203,
+116,13,213,200,157,179,75,25,239,116,177,89,233,202,156,192,231,141,52,170,76,241,183,173,228,134,134,115,108,178,
+86,178,1,212,225,44,255,108,90,89,145,101,183,225,28,31,33,7,57,39,31,206,240,110,217,74,152,44,115,142,
+134,115,20,149,107,68,87,195,57,144,168,200,240,174,250,104,100,27,109,80,190,174,141,1,229,77,241,249,133,137,
+130,12,203,183,129,138,99,93,117,52,186,118,117,131,135,191,248,100,76,151,175,81,134,250,59,227,3,63,174,37,
+94,103,219,184,146,229,6,53,235,146,121,182,65,33,218,172,40,56,132,130,15,214,111,142,170,31,39,211,172,99,
+10,63,59,74,170,212,146,20,178,152,164,82,143,83,33,243,103,245,44,194,220,121,144,158,99,26,230,65,192,44,
+98,159,80,67,194,95,32,225,47,88,91,154,151,181,230,186,145,13,28,218,171,249,58,52,138,177,69,203,56,103,
+35,211,241,15,198,178,149,180,129,175,139,57,124,226,16,40,158,2,24,127,30,212,246,126,192,138,18,182,64,167,
+133,60,0,208,52,8,188,24,245,4,157,200,177,20,76,134,148,79,241,8,236,180,227,197,150,51,14,146,98,206,
+32,75,46,196,163,226,241,19,6,188,77,148,203,99,25,100,72,133,104,29,170,225,199,19,39,81,125,228,131,66,
+186,209,113,2,6,132,244,35,141,139,6,82,124,24,90,169,40,29,139,113,42,134,76,90,27,40,55,234,190,14,
+30,56,196,208,227,236,17,59,88,110,4,236,148,194,197,212,104,159,51,172,160,44,92,5,94,161,217,237,174,96,
+3,38,157,13,152,119,182,90,10,91,77,46,189,140,81,115,20,108,203,113,49,214,147,92,26,143,193,41,248,195,
+78,49,98,156,199,86,246,121,174,156,143,152,141,170,39,9,66,67,94,214,215,54,255,164,136,143,193,171,220,18,
+190,151,230,123,219,168,232,245,248,175,184,164,215,141,218,54,198,127,219,230,209,182,121,28,109,155,113,33,226,205,
+116,174,162,205,228,26,87,157,0,224,218,247,238,232,248,248,68,110,30,45,39,250,241,207,226,241,82,174,48,239,
+26,107,187,84,201,120,53,158,203,11,232,202,106,50,151,225,162,222,250,101,188,10,151,238,198,175,211,117,171,222,
+227,229,182,144,75,121,49,185,68,167,195,203,201,173,60,133,191,87,242,131,186,28,223,62,222,202,151,234,98,114,
+245,248,84,254,170,22,227,27,249,10,254,94,203,247,144,118,243,248,87,249,22,210,174,31,191,194,73,56,116,92,
+151,232,44,83,200,171,103,199,126,150,96,11,156,202,151,134,97,48,181,57,95,31,221,202,215,71,91,121,5,209,
+23,227,191,8,154,4,221,96,222,87,242,130,242,98,51,228,4,67,55,80,4,254,108,133,188,238,212,141,249,223,
+14,213,125,141,53,203,183,99,51,175,239,94,139,22,171,227,126,46,36,14,101,33,113,96,11,35,59,117,211,171,
+246,87,249,126,168,218,27,249,222,85,41,47,39,220,245,143,88,100,43,47,247,123,254,17,10,126,196,126,223,118,
+26,192,220,31,134,26,184,197,106,229,7,209,118,160,86,160,232,220,7,47,187,5,224,32,47,178,42,69,179,90,
+117,120,38,74,153,66,244,102,69,242,204,113,229,64,110,2,132,143,46,230,38,23,118,22,14,86,112,204,202,241,
+15,254,185,46,87,112,16,158,214,64,3,230,34,51,206,52,34,232,113,253,54,121,27,85,104,220,49,81,229,184,
+250,127,127,144,240,207,74,108,71,201,88,253,224,253,201,6,245,38,66,186,26,100,226,7,244,154,6,228,15,119,
+33,183,253,129,132,135,187,146,225,136,19,60,220,249,129,195,61,169,240,96,167,48,220,0,30,140,43,235,234,208,
+140,17,16,126,186,214,112,216,114,104,95,23,178,150,41,38,203,210,236,148,37,76,201,210,184,42,89,138,140,253,
+178,152,218,14,21,207,101,137,21,12,151,13,87,247,213,114,31,218,133,40,173,220,133,110,118,42,105,67,127,41,
+179,194,160,129,56,27,165,204,217,93,242,169,243,162,103,134,63,154,62,68,23,79,249,44,202,2,119,53,213,163,
+39,210,134,177,26,149,128,45,60,227,197,97,36,226,110,190,126,174,75,160,57,242,17,190,23,250,245,0,62,21,
+173,103,46,100,206,115,91,11,217,129,227,210,143,93,144,198,245,203,236,1,240,113,97,87,214,15,110,155,190,61,
+167,122,3,152,93,143,41,218,213,147,13,55,122,39,133,183,81,55,26,26,218,139,12,55,73,24,207,59,170,31,
+31,236,74,69,81,193,84,96,20,26,151,8,164,204,89,200,50,43,222,35,173,51,68,56,147,51,129,117,29,157,
+129,38,146,4,107,124,198,196,240,46,161,163,48,207,96,72,116,156,175,202,168,70,15,83,13,156,24,221,66,166,
+206,141,232,198,216,191,14,59,88,217,178,7,36,22,237,94,47,124,165,208,29,172,148,62,131,74,9,73,242,161,
+78,165,118,4,243,158,62,217,58,73,129,192,133,123,109,13,74,77,11,153,79,18,241,76,253,0,214,35,240,185,
+199,216,188,91,169,239,155,168,146,41,220,121,203,241,156,73,76,240,250,179,50,15,154,198,101,205,187,50,11,92,
+63,34,118,129,248,68,8,62,106,63,19,101,56,19,125,252,180,61,48,255,242,223,50,3,13,44,79,73,254,186,
+36,13,62,78,123,126,39,151,42,170,199,165,48,190,167,162,106,156,140,211,113,14,161,105,128,58,49,226,180,20,
+143,22,6,117,98,196,9,99,218,182,41,203,188,201,214,239,72,218,175,111,184,188,63,113,236,243,166,7,110,116,
+111,99,20,236,26,44,210,196,214,135,247,104,236,106,137,49,52,34,27,133,151,202,222,9,209,195,64,105,118,244,
+229,151,241,192,233,41,158,253,48,51,35,91,228,37,64,129,226,241,15,2,178,65,65,22,76,10,102,255,169,139,
+195,53,224,56,199,199,32,215,131,44,255,78,119,94,165,106,232,170,211,44,137,122,224,98,220,129,19,56,168,230,
+200,121,12,210,17,175,66,46,30,85,146,87,0,67,98,0,36,61,83,63,195,213,8,13,138,182,227,254,240,168,
+231,80,81,54,161,187,48,158,50,76,243,156,254,231,142,69,33,43,89,138,233,171,48,40,147,142,251,196,182,125,
+153,161,130,230,8,110,162,209,244,165,247,107,161,118,193,98,196,236,87,51,104,46,30,253,63,139,197,98,180,119,
+197,16,0,12,169,24,88,151,240,90,122,34,105,159,31,243,62,63,150,0,190,184,112,235,123,66,62,51,212,158,
+103,201,81,47,98,20,152,22,41,137,16,69,251,32,246,82,122,145,32,16,113,211,5,33,211,87,217,244,34,240,
+226,9,157,21,250,34,24,148,77,16,16,152,183,231,184,48,200,206,145,178,217,139,18,225,77,233,203,96,176,219,
+45,142,17,50,188,105,125,17,19,150,77,24,194,172,225,22,241,153,105,3,133,161,0,179,248,141,209,44,143,84,
+35,78,125,180,13,50,125,27,82,194,216,142,94,175,245,124,214,228,64,88,55,186,168,33,143,177,0,187,185,204,
+210,215,184,99,214,165,245,159,133,172,29,203,64,42,202,166,44,244,104,166,243,248,183,165,175,185,114,75,182,107,
+61,179,212,217,172,161,123,43,198,43,19,14,92,92,170,98,114,210,42,237,226,43,140,221,195,244,106,164,66,211,
+144,104,54,10,178,245,83,120,155,40,159,2,166,83,63,75,224,235,89,226,160,167,145,240,102,185,251,92,230,37,
+122,74,61,194,31,153,65,79,226,244,105,14,146,158,203,89,49,78,39,121,12,255,2,58,244,215,61,188,123,141,
+240,19,81,238,14,130,70,173,84,212,74,98,91,201,169,129,86,193,68,212,88,11,118,21,166,187,52,64,105,135,
+124,151,120,1,44,45,118,1,55,111,85,97,236,155,109,228,90,174,12,118,185,1,200,181,121,170,82,192,30,55,
+98,173,234,51,192,181,163,57,80,160,155,120,35,196,255,91,157,203,135,235,163,250,42,67,175,120,11,68,242,200,
+159,224,26,214,121,141,36,200,2,121,187,49,14,100,5,149,206,101,233,86,24,175,218,53,223,175,57,148,15,170,
+143,143,109,229,67,229,132,124,248,48,247,147,244,211,0,239,163,57,178,19,229,102,166,148,180,168,118,74,146,112,
+74,236,60,228,225,60,164,52,15,22,103,135,13,178,128,127,115,59,43,242,82,94,16,84,188,85,55,200,36,31,
+71,233,44,153,220,196,55,208,229,82,94,217,55,76,244,160,126,9,99,226,141,191,148,151,66,6,161,85,39,116,
+33,132,181,159,143,243,176,129,121,184,141,142,197,185,228,233,220,192,116,110,96,58,133,68,238,192,252,169,66,116,
+126,142,156,84,202,61,135,220,27,179,16,2,223,191,178,98,227,248,166,55,10,11,95,43,40,46,183,234,230,127,
+143,167,91,165,212,26,220,203,63,93,205,86,234,58,190,126,134,29,189,84,215,184,61,162,197,163,229,248,70,60,
+30,143,23,34,142,174,162,160,151,55,18,114,172,213,214,204,198,74,153,2,23,234,186,133,76,193,153,43,6,13,
+211,74,173,66,152,5,220,246,32,68,39,210,57,143,203,80,54,36,69,25,31,20,130,198,32,110,103,248,106,28,
+60,192,226,195,240,224,97,8,15,176,136,219,53,198,234,253,79,203,248,215,0,62,188,29,134,60,207,255,5,200,
+243,58,143,255,214,248,154,127,12,246,100,174,237,142,4,137,57,24,35,138,10,112,200,168,26,33,225,246,228,37,
+192,80,140,161,77,9,68,76,72,137,11,105,111,31,154,205,144,150,9,221,57,253,178,7,46,106,253,105,165,7,
+0,70,165,208,143,90,104,14,43,65,115,88,181,192,118,240,66,63,170,17,208,247,105,83,11,79,19,7,34,181,
+1,145,122,140,128,19,186,220,103,121,50,165,105,91,248,97,169,72,16,206,142,56,148,170,244,215,236,223,130,49,
+252,176,196,21,100,228,157,6,51,11,38,55,14,134,76,52,221,143,205,103,210,116,164,165,201,66,10,195,68,222,
+133,121,38,235,70,225,118,236,198,32,14,249,166,23,75,75,220,141,49,80,169,27,71,195,234,197,242,9,0,240,
+233,11,179,94,101,16,29,62,89,82,29,135,105,192,77,168,203,105,144,241,158,177,211,190,251,253,168,240,71,161,
+248,156,163,32,96,205,138,224,212,13,244,61,144,62,64,20,190,248,38,89,215,51,63,181,113,119,78,167,47,242,
+40,172,68,22,178,49,239,78,195,211,114,220,26,123,60,54,22,215,188,51,243,141,151,118,11,231,158,99,121,221,
+14,204,121,251,201,215,205,160,35,204,106,50,80,181,123,89,40,30,97,64,111,237,127,204,7,44,248,80,170,128,
+35,158,85,117,211,23,165,226,206,107,27,182,29,224,39,177,80,213,1,165,51,204,153,61,111,243,228,115,107,10,
+172,75,48,191,223,214,6,7,254,28,169,148,243,54,227,189,112,183,225,29,148,172,151,101,167,246,74,253,72,178,
+212,187,53,217,191,140,53,235,39,34,100,169,91,43,235,80,117,149,6,153,38,57,67,139,42,0,196,11,75,100,
+165,210,178,215,172,130,113,21,234,19,143,199,105,231,1,41,94,96,3,136,239,84,104,148,126,163,202,179,197,185,
+92,195,207,220,188,62,110,240,134,20,187,196,74,51,111,196,212,221,169,4,203,86,22,3,76,46,235,40,170,39,
+27,84,27,120,28,173,225,199,126,11,121,169,242,200,162,11,124,22,64,70,21,210,236,76,80,197,151,204,178,76,
+188,5,138,147,89,2,203,5,56,10,110,195,15,118,101,122,226,18,228,4,83,56,26,12,211,76,246,65,222,14,
+175,110,169,168,160,35,74,253,153,155,106,165,173,99,87,56,231,193,42,57,181,9,189,127,85,84,255,161,74,215,
+129,225,43,193,93,232,15,43,34,247,251,50,247,225,38,49,248,86,20,52,109,28,185,243,38,46,67,122,36,244,
+236,255,55,166,68,177,234,144,14,237,129,121,44,52,120,166,247,161,181,104,219,31,27,67,194,34,234,51,154,66,
+32,164,97,67,234,14,104,198,77,211,140,66,223,233,103,231,251,222,210,143,251,36,45,122,4,38,234,215,19,177,
+95,202,52,89,63,215,191,101,196,40,65,191,36,114,24,230,198,35,234,209,72,34,105,143,190,76,28,40,197,111,
+218,115,248,73,224,59,62,110,113,28,191,151,2,238,82,231,65,96,68,213,177,175,34,181,187,176,223,78,236,228,
+194,123,90,193,87,117,68,205,252,188,0,114,102,98,176,243,33,153,253,170,222,199,230,61,22,185,131,195,131,24,
+76,230,25,102,16,19,216,17,230,99,217,76,74,241,180,62,170,44,247,189,6,113,240,198,242,13,8,77,248,254,
+15,177,126,173,242,67,39,10,81,239,110,68,83,82,196,191,200,147,229,65,211,211,227,33,86,225,222,248,215,229,
+13,142,95,62,17,99,14,235,73,5,225,167,28,14,102,100,236,166,9,50,64,135,126,230,30,121,3,177,53,117,
+88,98,147,26,115,253,114,103,174,45,230,186,143,93,122,120,60,172,58,193,89,91,35,223,137,183,185,2,14,224,
+30,220,32,37,47,26,7,0,178,169,246,52,187,150,40,97,101,5,70,222,187,12,222,36,8,38,134,192,5,75,
+147,56,12,192,49,241,232,9,1,175,131,88,18,47,63,98,72,182,7,79,143,78,64,217,253,239,13,203,106,98,
+22,171,45,9,76,61,124,195,234,242,220,138,30,59,197,243,101,138,176,107,50,228,227,21,123,124,188,52,67,13,
+6,219,216,173,253,217,90,133,25,179,88,253,91,63,156,64,70,26,232,192,52,193,129,105,191,183,236,60,3,55,
+71,83,8,121,96,24,66,175,19,201,101,240,27,167,251,121,55,217,175,64,252,39,105,170,35,88,136,124,75,100,
+110,87,54,241,75,239,91,253,184,197,6,255,157,80,139,65,77,130,228,204,30,15,255,50,169,145,123,79,138,111,
+164,11,139,135,47,27,98,210,99,110,248,49,185,225,215,230,54,59,216,62,122,162,172,181,92,202,133,247,82,181,
+100,183,213,179,104,161,42,96,101,39,158,157,132,14,173,66,118,147,9,167,170,152,44,36,108,5,36,201,161,76,
+105,202,104,136,203,149,30,47,66,118,20,94,129,161,212,1,134,5,169,255,37,70,109,47,37,85,191,220,233,233,
+45,219,224,89,180,241,192,215,117,24,180,251,24,255,240,57,191,233,27,90,246,64,186,179,97,17,120,219,240,7,
+56,32,107,163,252,248,178,140,10,62,224,77,12,141,214,70,113,176,52,127,143,17,179,175,108,172,233,170,44,233,
+247,24,159,51,46,109,138,237,188,44,233,195,150,202,109,26,142,86,150,246,7,203,4,3,252,107,239,221,87,23,
+120,61,61,15,217,202,69,111,165,247,179,128,228,13,142,107,80,182,6,173,74,146,37,117,94,20,108,79,38,123,
+19,145,35,170,245,91,84,251,169,40,215,111,244,194,76,200,195,28,157,182,67,4,254,208,120,108,50,9,194,64,
+224,61,78,74,63,51,79,25,101,160,236,118,150,186,181,219,184,160,1,159,41,44,132,181,12,149,226,150,130,108,
+125,65,156,159,59,54,203,241,188,9,36,49,108,209,73,99,27,46,84,67,117,64,12,238,128,90,153,221,165,97,
+155,23,40,143,84,170,191,134,225,142,116,81,12,231,150,234,217,198,182,248,77,172,229,50,46,28,44,41,91,124,
+126,11,115,142,97,139,184,220,240,221,96,137,9,196,193,191,10,75,194,111,3,255,46,93,13,188,48,124,172,142,
+253,114,76,56,18,107,130,90,4,47,78,191,0,197,246,75,84,34,92,159,110,25,31,31,150,186,196,118,184,212,
+64,83,62,161,95,14,91,107,67,123,229,63,100,3,220,83,101,189,251,161,58,57,125,226,254,5,98,30,53,138,
+209,45,0,46,101,128,117,36,168,107,12,14,178,16,78,208,118,162,253,97,12,62,150,38,73,75,179,73,165,219,
+67,34,0,39,127,233,114,226,104,110,129,249,198,179,134,223,60,27,65,200,36,250,138,254,73,30,17,50,32,3,
+82,232,14,222,131,71,91,248,119,3,255,150,65,139,127,203,6,223,6,110,1,39,133,39,138,217,196,60,36,65,
+196,214,68,108,109,68,169,34,200,50,206,142,110,108,182,49,216,70,153,65,130,152,20,178,194,180,45,164,45,109,
+9,72,91,218,180,218,35,51,88,26,37,77,48,103,13,251,14,106,26,151,176,231,160,212,184,162,253,6,1,251,
+209,18,170,250,230,15,161,170,254,190,233,68,227,197,213,137,48,87,88,39,198,94,102,61,97,133,5,146,250,167,
+43,228,170,223,139,220,118,223,120,59,101,99,45,217,28,116,120,87,23,178,127,183,215,100,247,81,238,236,49,46,
+237,251,57,222,200,0,94,48,5,129,43,108,160,138,166,77,204,150,89,252,207,37,63,192,74,72,193,245,42,143,
+110,208,244,193,210,124,46,141,148,115,135,185,153,192,230,133,93,81,73,232,26,30,98,43,178,201,241,165,156,104,
+212,41,239,226,96,20,138,70,40,11,95,206,231,35,204,48,84,109,41,117,175,108,237,202,134,68,107,159,34,160,
+51,129,199,52,84,135,24,196,210,125,30,60,177,30,77,31,206,102,51,53,247,227,233,140,18,249,157,228,36,221,
+239,192,136,124,230,30,62,95,206,0,173,174,1,11,198,202,33,84,196,81,97,194,45,35,170,161,244,0,185,182,
+244,91,20,10,6,187,19,139,189,177,232,233,101,2,194,70,111,250,200,41,223,183,177,21,168,232,18,220,123,79,
+202,221,77,58,66,51,111,35,198,84,131,183,228,55,255,94,156,20,61,166,252,125,233,12,17,47,42,173,129,84,
+216,93,92,24,243,144,23,23,86,51,255,180,74,73,190,61,126,153,73,124,79,118,193,31,27,105,150,206,133,191,
+207,228,243,164,114,161,55,89,40,80,253,69,71,218,139,29,80,195,97,65,139,240,104,163,147,252,96,176,219,227,
+140,172,187,54,178,25,107,118,243,128,220,183,4,165,131,159,0,235,171,132,191,83,18,221,99,117,45,200,61,57,
+161,39,52,148,0,157,7,207,138,213,89,62,30,159,171,12,188,65,202,5,148,89,60,133,42,166,11,52,251,135,
+5,46,21,176,15,224,223,45,85,118,165,2,169,140,104,49,62,17,143,18,49,62,25,195,221,237,241,172,110,150,
+39,54,139,212,2,114,93,171,155,201,149,105,248,86,93,77,111,159,222,76,111,161,169,203,49,116,224,246,28,238,
+136,11,250,218,78,47,31,43,144,226,132,63,212,242,54,108,121,225,90,61,61,212,234,73,216,42,236,246,15,176,
+199,95,182,102,156,244,156,186,86,147,19,121,171,182,208,139,83,211,139,181,58,250,234,145,103,39,126,0,41,217,
+71,145,237,205,228,165,152,64,132,237,36,196,94,64,132,144,235,103,27,243,72,184,150,115,211,107,185,82,183,98,
+74,51,58,151,75,181,114,92,69,158,229,244,60,116,30,217,44,250,175,83,120,181,1,238,38,153,94,225,197,178,
+179,112,137,171,125,97,87,84,222,66,133,13,206,218,13,124,92,192,199,228,214,174,169,106,208,147,240,24,149,188,
+43,177,75,84,102,109,94,71,9,102,17,143,111,30,21,198,133,231,150,42,189,86,249,255,26,177,152,107,99,210,
+57,125,10,111,146,107,149,194,126,168,68,156,62,91,193,32,87,16,156,67,208,40,251,62,170,199,80,19,62,77,
+150,161,125,214,173,170,38,39,134,79,252,83,180,0,176,14,63,115,225,118,118,176,80,48,38,33,63,120,218,8,
+195,211,83,184,13,96,54,241,103,251,31,255,113,105,217,178,239,179,232,235,44,66,39,149,103,167,231,2,151,177,
+110,5,148,181,121,63,28,202,251,193,231,109,171,103,32,150,186,197,2,156,51,59,219,66,6,10,36,198,185,170,
+153,245,181,90,153,65,207,213,70,85,108,139,245,210,47,87,94,145,67,222,240,97,52,124,99,53,79,64,236,167,
+38,200,36,125,28,102,145,67,170,43,91,216,11,35,76,29,201,29,106,103,144,241,46,47,195,81,99,235,135,188,
+181,162,69,199,28,17,145,208,125,178,94,116,125,241,242,43,2,110,54,99,213,120,74,40,129,49,228,104,24,122,
+240,12,111,196,108,97,101,226,68,194,247,75,211,201,121,156,99,148,11,164,173,42,241,210,65,253,242,231,8,90,
+235,168,35,65,80,40,184,191,222,32,26,90,26,87,194,178,2,14,114,137,212,225,228,68,8,153,206,234,126,134,
+68,0,167,3,14,44,234,40,78,138,184,86,122,82,56,102,118,65,246,249,234,214,184,180,42,22,10,109,137,143,
+104,122,241,221,82,122,133,159,36,255,4,87,94,179,92,33,103,183,152,64,167,71,210,208,142,100,25,101,200,58,
+106,236,125,143,226,254,213,71,84,64,236,112,214,217,121,135,71,79,201,9,205,240,98,176,225,59,82,81,195,116,
+152,81,54,191,140,98,15,104,222,61,219,87,41,149,169,66,217,21,83,37,30,165,75,29,157,37,210,147,184,92,
+199,185,48,206,154,193,128,95,78,246,162,137,71,222,125,155,89,170,204,59,178,37,91,51,230,97,101,217,41,149,
+84,192,6,246,81,77,182,210,80,179,111,22,217,172,168,143,72,117,231,154,159,111,104,101,230,173,210,11,163,228,
+201,26,19,250,168,89,86,186,94,150,249,252,127,255,247,79,143,204,109,6,242,18,27,129,251,180,230,57,253,41,
+170,16,5,164,247,83,149,186,163,82,31,221,113,82,106,62,41,236,160,153,120,221,94,203,9,67,48,191,177,59,
+13,253,55,64,62,156,173,172,195,108,43,122,169,180,253,89,181,173,176,55,234,122,90,223,100,13,172,174,62,226,
+45,6,71,11,177,172,188,105,46,71,241,90,193,149,158,34,200,54,155,120,122,89,233,228,106,138,25,120,35,66,
+158,102,225,242,184,28,180,117,227,190,30,241,63,126,40,128,168,88,27,235,57,15,252,94,127,192,173,63,248,207,
+47,118,65,103,218,255,252,135,104,195,129,169,117,43,90,233,12,121,100,180,153,219,128,243,86,247,0,68,118,216,
+118,142,70,185,130,1,59,61,51,125,20,26,59,10,116,119,22,135,5,80,16,221,38,32,244,181,117,145,6,187,
+9,154,150,154,219,243,238,12,12,56,1,115,175,125,54,171,144,133,81,88,5,76,137,136,227,217,195,147,216,196,
+29,207,70,48,39,128,251,143,226,194,247,168,90,244,121,101,166,143,184,49,127,139,10,118,8,110,21,28,10,235,
+246,76,152,58,201,52,148,121,109,120,149,151,73,19,121,154,251,139,8,237,1,6,216,135,209,163,173,103,81,84,
+88,27,168,163,9,156,37,247,61,30,89,207,164,205,184,198,203,84,33,23,221,8,176,214,128,232,97,91,104,203,
+202,117,158,100,143,173,216,177,13,165,87,248,187,76,214,32,85,204,86,150,11,241,12,181,47,130,161,38,126,242,
+173,211,245,184,1,2,219,190,80,105,128,242,52,249,6,157,173,121,137,177,131,182,197,153,103,6,197,24,141,29,
+176,145,200,187,68,39,145,24,192,221,98,220,167,128,126,231,143,56,91,145,166,89,139,77,26,154,71,49,233,102,
+9,187,81,248,44,248,5,58,199,196,201,128,141,245,45,211,41,145,189,189,103,5,25,197,130,79,252,64,219,63,
+38,134,168,241,180,26,116,252,124,171,26,230,185,195,231,214,124,18,69,202,15,19,3,79,186,76,106,213,72,13,
+57,22,64,213,117,111,100,30,103,9,244,89,105,197,31,90,217,24,77,15,99,20,69,226,205,49,135,191,38,139,
+81,24,121,136,15,7,120,65,134,79,244,251,164,29,181,87,19,141,93,66,87,141,208,236,160,240,119,41,30,213,
+93,225,111,19,67,74,2,33,87,41,223,223,7,126,19,32,199,47,20,13,192,245,121,131,182,253,189,101,46,89,
+34,194,137,174,228,72,36,111,214,32,206,22,55,136,201,201,36,140,199,152,216,164,154,205,101,240,87,60,90,225,
+174,90,170,138,183,19,134,18,179,149,224,131,246,77,188,244,187,196,110,40,33,193,75,104,149,205,173,68,117,158,
+84,236,102,223,230,52,228,150,147,118,231,109,104,216,166,8,73,211,42,130,169,75,97,71,108,225,239,214,77,179,
+41,250,146,116,41,94,85,229,202,146,221,92,126,41,90,210,130,10,52,160,74,139,49,222,209,108,46,151,194,123,
+51,245,171,144,46,60,87,45,162,11,217,56,201,63,88,213,204,44,92,108,142,177,175,231,93,225,0,24,246,109,
+218,60,203,166,205,100,226,193,153,118,150,209,28,8,187,5,96,195,129,173,16,230,194,97,47,3,190,226,229,162,
+247,2,163,232,232,89,16,209,146,175,248,64,158,19,247,5,63,86,177,100,131,199,128,122,194,187,136,13,37,10,
+250,143,164,77,45,88,238,190,70,202,36,85,198,37,67,241,144,160,120,68,51,13,29,201,113,229,240,228,75,31,
+151,186,56,17,107,91,4,225,11,167,227,129,130,114,91,42,227,227,82,140,19,24,237,7,190,24,56,31,8,85,
+177,4,34,70,230,21,66,90,227,2,170,224,113,226,137,112,51,145,168,249,194,218,158,32,97,146,165,217,115,52,
+129,14,138,182,178,16,125,197,186,146,209,113,239,77,36,85,37,24,2,226,140,75,149,90,88,2,138,99,240,9,
+147,57,93,66,230,205,2,5,160,145,102,79,88,114,5,183,251,143,77,180,47,153,188,107,67,154,96,222,189,242,
+113,100,228,195,23,128,73,186,4,44,143,238,118,107,162,207,34,149,220,115,36,81,209,93,13,27,55,13,253,160,
+20,206,71,45,91,235,104,132,69,113,74,178,2,135,134,171,55,69,189,204,22,13,228,34,188,129,71,160,125,47,
+55,253,171,26,250,217,235,131,30,236,131,134,62,200,29,138,105,225,230,203,19,248,73,44,223,8,149,206,63,65,
+231,236,227,185,21,104,50,111,41,21,176,209,133,161,235,42,81,112,247,114,235,123,228,1,146,123,118,93,115,0,
+230,9,29,161,54,99,123,216,225,107,28,212,191,247,26,215,151,204,234,24,85,128,23,95,22,193,179,146,89,89,
+184,201,50,218,100,246,13,19,69,100,114,248,19,122,112,152,166,126,27,165,126,34,150,176,141,82,228,232,192,38,
+33,129,51,172,126,142,97,220,69,24,194,142,192,115,64,45,145,0,71,54,1,162,35,11,153,155,223,249,148,6,
+106,251,73,51,154,216,25,205,105,70,139,224,166,89,7,39,201,136,106,242,77,227,15,18,182,248,69,164,25,211,
+170,233,224,248,91,2,241,27,151,138,103,147,211,8,231,97,39,199,60,109,169,201,229,42,124,224,236,58,148,11,
+128,253,179,58,94,162,120,121,184,68,75,122,108,206,53,239,126,152,81,42,255,13,212,53,67,108,19,237,231,1,
+252,213,138,32,163,116,187,109,214,61,102,33,251,220,203,247,72,43,62,89,72,150,157,244,200,11,119,100,197,123,
+197,238,105,228,229,88,196,216,237,101,136,32,51,95,134,40,229,89,51,235,63,173,201,184,172,119,182,81,147,179,
+13,97,136,88,196,75,125,17,136,177,110,116,229,195,138,205,102,98,44,219,32,246,121,9,108,26,4,181,50,93,
+106,93,137,64,91,164,166,238,247,37,156,11,233,32,144,211,56,46,141,72,63,78,115,40,197,188,39,244,92,116,
+37,3,115,169,11,195,104,72,80,175,3,128,162,92,192,15,92,33,136,89,212,226,124,90,6,90,14,75,184,19,
+150,168,229,80,66,51,172,187,74,9,172,97,19,100,20,178,50,52,69,136,8,102,50,33,37,132,170,133,244,89,
+71,142,58,230,42,22,166,202,150,195,205,17,73,133,98,252,253,6,39,18,214,133,53,235,68,144,192,145,24,205,
+89,134,80,64,195,207,52,244,180,109,112,187,145,33,29,22,13,46,77,137,191,165,16,129,208,102,214,17,218,44,
+67,253,149,122,95,158,0,164,109,102,208,21,4,11,198,220,114,156,205,48,16,55,51,12,198,199,190,244,101,31,
+170,133,64,170,102,32,37,75,143,30,32,87,122,96,125,115,189,191,186,211,84,241,162,50,215,2,38,73,75,179,
+232,53,194,177,196,232,233,88,208,233,177,13,24,11,93,240,117,185,169,82,212,122,181,100,100,188,116,51,129,53,
+96,67,88,75,187,39,61,186,48,146,175,114,25,110,197,57,118,117,225,134,186,177,61,1,113,84,130,162,230,19,
+1,168,156,219,62,201,181,122,91,26,3,60,155,176,154,21,86,179,22,189,14,174,92,7,231,212,65,35,71,7,
+171,179,148,27,38,246,28,99,84,180,216,245,110,22,136,112,25,178,66,224,197,206,44,102,191,94,23,221,245,218,
+25,43,209,244,72,109,78,165,53,57,229,13,79,5,123,168,148,61,173,43,131,168,78,75,243,252,131,251,175,171,
+136,64,207,187,21,106,248,79,42,89,79,10,191,229,69,160,26,84,15,169,6,133,55,35,38,77,225,81,155,79,
+21,74,78,213,29,253,180,183,117,136,164,154,75,69,187,249,44,36,143,160,150,169,121,217,41,165,69,232,144,132,
+147,137,130,77,108,159,90,252,34,185,85,201,93,45,41,13,126,105,6,191,64,159,44,137,7,74,248,236,180,247,
+186,52,87,101,171,0,195,82,185,220,168,2,65,50,112,210,221,131,103,22,188,50,206,165,89,150,74,2,35,26,
+246,84,141,204,125,209,211,235,160,237,191,6,200,164,123,144,41,183,76,168,149,17,138,22,187,117,15,56,153,9,
+46,228,194,159,161,75,168,164,232,85,146,18,120,91,179,130,21,90,117,159,130,250,23,48,199,37,8,147,80,53,
+75,89,119,77,80,176,241,134,213,140,31,88,227,81,81,22,191,233,170,28,97,170,127,55,245,11,118,187,184,107,
+193,146,75,236,74,45,129,222,44,111,96,181,18,180,138,86,209,162,145,186,159,182,66,209,51,2,127,113,99,120,
+197,126,130,115,183,45,75,152,121,244,115,255,173,29,64,133,108,10,33,205,142,233,55,76,219,163,118,45,249,157,
+147,183,157,145,72,110,134,107,37,129,137,187,107,46,239,173,57,16,223,202,250,160,21,240,168,70,216,170,185,143,
+165,196,97,187,157,92,119,60,132,226,178,224,107,206,158,16,226,206,78,240,82,165,52,197,11,149,194,54,197,227,
+140,214,204,122,130,229,48,119,91,236,139,22,18,151,141,59,208,91,174,165,171,203,46,151,238,119,80,200,107,168,
+69,8,195,167,223,18,159,30,187,136,18,214,3,126,74,250,163,143,122,44,245,80,246,220,144,97,123,102,49,81,
+163,187,50,254,84,42,81,238,51,48,43,20,74,96,82,67,230,36,68,3,103,208,205,34,124,134,88,227,143,104,
+137,56,87,108,113,122,128,233,89,9,103,155,209,98,184,213,34,74,160,71,133,32,71,166,153,157,141,208,238,230,
+30,3,159,151,246,232,26,223,94,8,73,78,12,209,250,133,157,48,149,203,218,81,30,123,67,37,210,217,82,48,
+185,217,5,214,122,31,246,222,6,1,193,172,13,75,10,183,97,242,9,102,27,214,69,122,15,30,253,185,215,198,
+222,255,199,108,101,240,109,159,111,132,119,252,61,134,220,145,112,241,247,9,19,40,149,170,189,191,135,202,250,123,
+168,92,139,137,25,130,27,237,20,125,175,71,137,1,255,71,67,218,81,165,76,204,233,23,18,118,47,158,27,227,
+218,33,145,37,10,82,201,190,251,10,30,30,226,88,126,100,248,186,177,159,181,247,104,82,220,55,220,144,28,46,
+252,0,107,59,192,186,75,17,243,0,203,160,219,165,12,166,107,175,255,67,171,3,156,53,104,219,207,150,81,3,
+195,0,241,192,135,199,200,213,1,11,154,27,47,186,141,7,111,103,188,83,240,241,196,213,23,15,212,214,58,186,
+245,199,90,97,79,145,191,131,200,29,56,157,250,150,92,131,171,70,66,200,138,119,64,247,145,252,99,57,134,13,
+220,43,44,203,129,54,146,67,201,219,70,200,34,148,164,109,16,201,245,85,201,160,13,137,206,245,41,224,141,0,
+73,141,51,122,189,112,61,203,152,75,212,240,87,182,103,53,190,19,129,25,50,78,49,95,83,203,118,254,165,254,
+92,33,176,139,100,62,15,244,90,114,253,9,74,125,155,53,224,111,207,184,87,163,92,70,24,91,207,95,195,72,
+2,235,173,243,114,243,105,89,108,26,84,49,225,42,204,162,57,244,173,43,105,214,184,47,111,248,188,193,191,97,
+219,216,68,207,114,78,153,111,86,5,58,79,239,198,179,216,123,55,122,149,208,204,247,99,77,222,78,100,211,213,
+193,164,155,179,219,136,94,116,43,170,186,85,179,108,209,61,226,113,23,43,99,98,36,236,170,119,119,214,45,187,
+95,29,18,232,56,254,142,153,102,22,250,234,142,175,233,207,130,238,117,160,144,236,210,32,91,89,110,64,215,111,
+162,227,174,83,219,25,186,161,236,230,166,54,187,239,33,179,40,24,122,167,79,193,76,134,93,177,81,225,172,250,
+10,68,28,133,115,219,29,18,47,94,183,58,140,233,172,99,80,131,104,195,161,13,171,54,88,151,193,161,138,200,
+223,12,31,189,208,21,204,182,45,42,207,252,30,183,103,195,250,78,116,94,5,13,152,96,215,209,133,122,214,240,
+183,63,29,246,20,163,55,65,235,131,155,10,225,167,115,63,109,19,48,48,88,44,236,53,97,201,248,62,73,159,
+145,216,63,80,186,197,133,236,91,208,233,56,65,32,194,117,158,213,104,23,88,236,186,203,201,107,113,220,23,52,
+104,104,226,144,243,14,93,6,246,122,209,224,93,107,117,88,164,83,28,76,203,213,122,211,232,143,89,147,107,187,
+142,81,8,50,147,16,76,230,173,250,17,45,65,151,94,87,83,155,122,177,210,166,2,254,175,28,220,129,105,111,
+227,45,169,109,24,251,251,242,166,142,42,105,237,54,141,79,142,97,135,45,251,251,42,245,217,1,61,237,102,15,
+15,54,195,253,84,54,220,152,85,52,226,160,8,129,131,47,1,135,193,55,72,69,56,44,90,238,105,207,194,26,
+46,83,41,93,221,113,229,25,122,102,238,241,86,180,214,152,1,59,115,34,176,185,58,0,210,83,213,135,159,240,
+238,139,252,171,113,66,238,244,27,96,175,161,211,10,107,8,105,132,231,116,36,109,20,190,122,97,73,53,90,1,
+183,60,39,27,240,115,148,83,219,168,9,235,254,246,55,160,127,116,89,203,149,183,90,126,169,138,49,136,234,143,
+75,64,28,18,116,231,250,17,154,136,214,166,37,65,2,44,209,202,90,84,74,207,82,70,99,206,199,151,227,39,
+143,146,103,70,44,99,49,86,75,25,164,70,43,176,116,121,28,159,136,115,117,44,55,152,56,31,143,133,204,207,
+86,231,202,106,183,28,27,237,150,141,172,128,74,152,147,246,206,165,247,100,39,187,77,169,203,49,226,188,139,150,
+55,198,224,234,240,50,254,241,229,233,93,123,24,187,84,213,164,161,229,73,228,28,71,134,226,96,198,184,198,241,
+253,179,126,41,47,252,172,223,14,206,250,101,103,214,47,80,38,109,51,174,205,52,47,237,44,207,199,137,76,137,
+89,100,39,109,238,38,109,3,19,180,182,57,86,227,49,244,15,122,135,83,126,225,166,124,77,83,14,195,138,87,
+52,229,183,193,148,207,189,172,221,92,222,10,92,183,218,78,59,212,122,87,171,139,54,153,255,186,169,27,55,133,
+145,229,44,135,48,146,97,90,215,43,220,157,128,169,187,46,33,11,61,49,6,169,10,217,91,90,28,68,213,160,
+180,51,27,246,174,117,84,250,203,47,128,32,134,73,56,0,193,44,155,221,58,56,40,17,252,115,225,113,29,92,
+148,147,238,249,197,135,201,144,173,151,34,91,79,139,4,240,200,244,8,182,56,154,188,180,95,191,191,90,33,83,
+163,249,98,231,10,191,176,76,106,111,243,10,127,208,110,246,155,166,2,30,253,109,148,99,118,59,66,153,143,21,
+125,143,235,22,95,169,250,99,11,107,12,239,237,73,111,251,99,63,8,142,14,140,50,197,156,48,210,196,142,18,
+67,127,164,1,26,175,202,105,140,52,112,252,188,99,220,54,190,55,120,170,18,70,223,118,86,153,185,219,157,45,
+26,186,190,133,14,0,41,116,48,217,142,98,68,254,58,113,183,15,110,118,143,228,16,178,61,5,230,73,211,241,
+133,107,107,64,118,8,42,190,81,112,31,71,224,153,194,115,224,247,71,92,32,250,192,226,32,116,48,74,123,48,
+152,19,244,45,206,116,89,201,28,143,67,115,4,71,100,248,72,200,20,209,135,138,208,135,157,101,83,45,165,59,
+93,139,86,85,114,174,82,139,84,108,212,252,241,19,146,120,99,175,166,230,4,163,43,192,224,238,202,253,119,100,
+239,49,76,31,188,200,100,176,247,65,202,90,214,22,227,72,9,227,176,80,195,35,44,171,128,198,187,12,145,151,
+11,131,188,64,103,133,188,85,44,177,119,106,236,14,227,98,89,81,135,21,32,142,43,227,194,212,134,47,33,124,
+233,13,2,214,196,214,35,88,245,43,136,160,189,244,221,147,39,6,130,212,1,235,22,211,57,36,19,28,165,55,
+59,247,210,125,75,107,128,128,82,187,150,227,94,246,162,228,49,102,11,204,196,189,228,128,36,123,4,162,51,103,
+191,202,186,103,248,237,37,135,185,83,161,113,187,176,77,121,134,192,166,234,82,221,110,15,191,82,59,18,138,89,
+89,225,247,15,127,123,255,241,9,26,230,228,172,241,203,35,31,96,141,96,136,117,159,29,85,142,95,91,249,30,
+246,198,45,56,124,168,97,105,86,168,57,248,86,125,24,111,166,105,22,213,242,149,124,47,223,10,11,181,168,7,
+144,200,23,84,52,7,177,123,104,253,88,96,45,1,48,192,170,176,162,66,71,47,187,86,212,167,117,200,67,39,
+137,81,43,79,84,71,111,133,245,50,2,203,240,76,27,107,220,168,150,100,13,167,190,151,219,248,149,188,129,237,
+182,140,89,201,240,109,43,226,218,190,106,188,135,206,194,86,196,169,37,253,160,95,177,2,228,157,178,73,165,58,
+224,234,202,171,189,61,249,5,190,175,191,52,135,66,66,212,248,2,134,150,202,29,110,251,43,221,44,43,164,242,
+227,151,36,29,33,249,60,197,225,217,122,233,191,81,186,91,222,168,129,235,77,94,223,113,229,78,111,102,107,133,
+42,63,77,120,105,142,23,225,5,133,2,138,104,140,157,33,59,26,255,54,76,201,227,54,54,165,195,130,219,160,
+46,204,124,13,113,225,53,160,161,54,7,247,93,45,242,219,50,98,151,172,141,25,212,203,172,210,102,190,4,107,
+121,92,140,23,211,131,184,22,78,43,226,90,221,195,112,106,160,9,114,189,65,118,122,73,171,53,148,68,141,188,
+84,117,7,59,59,13,177,51,249,107,7,176,157,242,55,48,220,194,144,170,130,101,17,242,149,90,141,55,227,151,
+6,110,190,87,104,116,239,45,252,221,78,115,60,149,230,96,68,33,64,190,153,125,64,36,240,253,248,213,120,241,
+140,87,1,201,85,83,108,172,182,114,109,206,239,120,44,77,117,234,238,181,179,153,225,152,199,166,222,183,227,237,
+179,96,57,160,90,91,201,251,177,118,89,9,127,88,112,59,182,195,234,190,117,181,217,121,113,217,95,125,131,103,
+62,122,47,166,183,112,214,228,91,121,138,7,248,34,65,83,234,99,152,26,24,49,12,54,246,157,150,230,190,18,
+242,42,178,229,76,17,200,5,221,28,43,152,149,216,78,67,11,135,238,142,109,211,250,203,169,119,41,135,226,198,
+13,102,144,5,94,130,154,46,193,90,229,24,160,43,208,190,44,235,97,100,182,188,239,118,173,20,247,47,81,154,
+241,9,124,108,48,87,42,158,121,101,231,51,183,106,88,114,161,124,85,115,229,43,59,132,188,122,20,30,69,142,
+122,200,164,144,75,143,67,162,6,75,137,10,183,6,101,144,157,125,50,23,161,190,206,186,79,12,33,44,155,111,
+82,29,69,8,245,212,51,110,18,130,124,152,143,197,116,169,210,113,208,132,107,186,179,81,214,19,199,187,112,115,
+60,57,12,159,156,101,186,13,246,60,129,62,47,140,193,231,224,176,149,193,145,220,20,81,98,238,179,97,84,163,
+234,26,209,37,20,201,202,177,236,197,33,22,82,56,190,7,0,235,74,106,11,172,55,114,137,98,67,131,221,29,
+220,104,180,201,52,110,178,134,54,89,129,155,172,225,77,198,164,164,219,103,51,141,171,72,245,142,11,154,227,248,
+216,248,236,121,195,240,239,180,137,88,78,8,217,86,37,73,110,209,46,236,177,250,128,108,135,52,61,184,44,194,
+74,142,150,67,244,177,44,128,216,45,188,52,217,120,92,8,68,132,84,121,86,156,75,211,28,181,69,32,200,237,
+127,106,207,54,102,55,97,205,224,225,0,245,12,85,182,148,100,164,162,66,255,78,129,112,98,223,8,222,195,27,
+231,176,72,106,87,119,215,247,111,111,230,88,243,92,76,247,125,29,25,63,123,129,64,66,159,29,47,75,117,13,
+19,64,146,9,15,75,116,230,164,143,202,226,141,6,252,17,157,57,213,161,51,167,33,118,190,44,194,114,236,36,
+170,8,203,181,70,204,176,160,76,222,83,84,152,41,124,85,191,161,87,117,103,211,43,202,186,3,66,125,106,215,
+24,80,58,174,191,2,191,169,122,200,98,10,165,24,0,114,200,215,176,89,143,232,241,246,138,30,111,237,162,141,
+228,133,115,80,247,11,121,103,216,151,9,178,89,141,45,205,95,234,200,176,110,232,181,139,173,138,211,3,41,154,
+36,107,142,156,238,142,198,215,117,99,109,196,184,48,130,221,136,17,162,149,104,185,201,72,78,59,239,68,54,201,
+181,196,190,51,93,132,123,70,27,126,91,118,185,6,155,46,248,37,69,183,246,161,218,85,226,143,59,87,208,244,
+185,249,71,125,62,9,213,97,55,180,89,46,28,2,158,121,152,109,170,230,168,179,233,173,19,183,206,107,28,65,
+9,124,139,115,119,74,108,8,88,153,116,13,119,187,71,12,204,201,146,29,39,242,198,130,147,19,253,165,164,133,
+239,79,73,247,209,75,194,224,45,59,124,90,239,191,122,27,85,13,196,84,241,83,54,236,215,25,216,189,16,143,
+238,147,187,241,39,48,22,218,134,86,24,154,54,162,13,16,33,75,180,40,154,37,179,45,51,56,53,9,254,5,
+241,79,199,76,174,158,28,203,238,203,65,184,70,61,249,1,201,92,194,14,241,19,235,144,188,9,17,111,150,30,
+106,91,94,111,215,39,255,126,121,193,207,195,221,119,97,227,81,178,10,28,71,86,161,12,0,22,194,6,35,61,
+59,118,30,170,101,142,119,68,18,218,234,97,29,125,236,85,220,156,145,55,204,115,123,159,74,190,199,226,125,153,
+15,70,118,227,82,58,119,230,44,224,41,137,80,141,147,190,165,116,71,40,114,10,6,100,151,100,229,52,31,37,
+29,205,202,105,24,240,85,218,149,139,114,66,53,115,119,41,60,254,147,12,174,104,46,108,135,16,174,11,90,183,
+25,162,60,19,166,60,195,149,195,220,28,236,219,19,232,120,219,164,25,109,91,7,92,165,185,188,239,221,141,124,
+32,79,248,64,250,67,104,86,107,52,130,202,2,91,124,113,104,139,15,43,126,152,89,65,194,250,167,12,72,130,
+81,89,140,4,159,133,126,214,179,81,119,159,143,228,200,190,120,193,7,190,97,141,206,189,199,71,212,235,107,233,
+137,250,101,113,255,19,245,31,124,80,190,160,195,248,239,127,243,189,223,254,201,31,127,222,189,219,210,174,239,168,
+31,23,124,62,44,238,125,191,11,70,20,78,0,63,235,117,139,113,86,30,101,191,160,102,41,247,111,162,194,18,
+169,51,251,75,72,90,124,50,237,44,7,194,146,130,241,77,79,191,60,242,175,135,33,198,217,41,75,29,152,14,
+189,254,133,29,44,227,96,24,101,27,230,28,70,141,253,106,49,2,28,112,98,67,174,171,225,146,158,86,159,234,
+168,9,101,87,181,196,213,8,68,88,201,116,90,73,136,5,171,233,73,4,184,230,110,116,54,48,186,70,223,6,
+31,54,151,150,232,192,23,81,185,80,122,140,111,149,229,164,128,91,173,10,89,195,150,195,137,217,11,200,178,176,
+133,106,169,17,130,255,252,104,114,244,149,136,177,170,9,167,105,89,219,52,72,66,250,111,2,89,119,6,206,252,
+28,47,165,249,248,37,94,248,135,199,212,195,183,188,37,6,244,30,159,89,246,113,226,195,100,107,135,220,45,85,
+17,44,252,227,39,189,165,135,89,230,190,85,174,111,137,239,91,206,125,99,167,53,126,173,74,49,5,202,169,113,
+148,211,49,252,87,56,38,51,145,90,195,53,5,192,27,104,58,109,87,78,200,144,172,139,153,172,115,222,87,176,
+228,89,37,147,243,142,113,132,239,122,90,77,136,131,190,44,134,112,208,230,48,14,170,101,211,197,65,141,52,191,
+153,141,231,121,153,94,41,109,48,227,83,194,140,77,66,128,24,191,44,186,136,177,233,147,102,52,214,47,102,88,
+231,180,135,219,54,140,212,134,185,238,67,108,125,206,251,145,91,143,95,118,177,200,240,118,195,77,19,239,8,127,
+132,227,153,207,71,109,136,101,122,92,172,135,154,242,53,40,169,240,19,253,101,43,67,11,61,140,243,141,204,207,
+104,255,186,28,54,93,11,221,98,161,179,159,237,2,255,164,147,171,239,146,181,49,218,243,129,22,165,222,92,210,
+186,12,18,41,180,47,254,48,109,34,127,214,200,216,187,147,78,193,60,159,48,143,48,217,237,178,66,232,238,197,
+228,66,255,23,43,89,148,213,42,201,15,172,229,125,75,121,242,213,241,241,191,127,45,79,181,218,1,85,80,37,
+159,12,173,101,180,87,187,102,198,31,90,219,69,70,48,0,32,58,25,201,49,207,149,120,69,107,229,242,79,155,
+167,104,242,134,193,64,101,117,170,232,124,34,172,4,33,162,10,200,174,154,116,139,69,128,167,247,29,103,137,105,
+49,86,9,42,33,224,207,86,142,199,101,219,178,50,118,241,184,68,197,244,199,16,39,209,124,134,174,205,86,187,
+171,255,218,40,166,23,70,39,189,86,111,55,171,75,32,9,222,125,255,225,245,199,215,63,126,125,241,250,237,171,
+215,111,95,127,252,69,26,217,102,51,56,99,9,200,15,174,124,90,193,224,74,215,231,28,6,87,134,131,67,143,
+37,249,192,224,82,149,247,221,126,33,195,240,239,248,96,153,10,208,43,173,141,86,209,18,221,205,138,182,133,138,
+18,223,70,50,48,47,90,229,102,32,168,99,219,183,14,28,216,150,184,162,25,113,119,47,180,242,13,218,139,56,
+173,170,100,123,100,12,106,33,55,198,72,31,28,37,235,117,190,53,249,99,210,172,196,247,226,204,3,248,151,77,
+160,66,77,238,43,50,184,149,45,235,14,121,24,161,16,247,7,19,139,174,48,88,57,238,31,255,191,127,136,103,
+147,19,208,155,128,179,145,53,38,28,7,13,188,232,40,43,56,152,174,187,132,67,33,177,58,251,46,43,7,164,
+205,11,17,208,123,68,123,198,21,57,91,70,247,140,172,98,127,90,204,237,58,121,179,163,78,120,220,149,178,182,
+173,99,83,230,157,249,134,204,18,110,221,184,75,228,34,51,205,124,163,118,223,2,79,120,131,114,203,182,77,215,
+255,184,12,250,26,9,19,109,199,84,247,135,200,99,15,173,83,214,125,67,33,166,183,8,65,81,208,108,14,139,
+15,77,151,104,15,176,70,252,129,141,9,49,1,95,249,55,93,210,238,176,156,82,44,252,202,224,40,169,141,48,
+165,109,204,210,198,216,138,109,212,66,57,6,165,156,179,112,57,170,222,184,207,117,135,231,74,90,51,106,77,216,
+171,180,6,205,10,230,116,163,47,29,245,236,102,124,125,100,129,50,85,3,97,68,63,106,31,52,252,28,215,200,
+177,97,39,162,177,50,42,246,28,70,225,242,102,54,111,16,37,23,104,66,107,172,22,143,210,16,253,142,22,19,
+48,83,70,35,254,96,157,165,141,41,104,221,230,61,183,92,91,121,225,102,254,70,49,243,216,144,203,245,140,153,
+244,137,204,131,202,69,28,134,166,208,248,230,209,205,24,12,151,109,196,163,48,5,163,76,39,112,29,168,15,237,
+220,118,215,205,188,237,203,71,224,235,206,31,45,59,101,231,88,214,101,195,210,60,229,183,108,127,46,120,20,189,
+17,187,75,197,29,190,148,58,124,134,131,84,98,20,220,10,182,131,173,157,10,142,238,74,12,200,31,35,194,122,
+228,21,39,230,65,98,184,46,208,143,52,105,162,96,93,4,150,186,221,155,203,106,252,100,140,51,113,251,206,93,
+137,80,85,33,111,128,161,243,99,116,67,85,98,81,12,153,253,65,1,91,51,4,90,172,246,216,117,104,25,116,
+136,38,201,118,215,235,24,93,142,213,154,30,30,119,61,97,185,85,112,254,222,117,160,211,54,214,46,19,26,111,
+231,201,122,10,102,121,103,230,238,142,245,179,140,182,252,4,35,29,137,197,56,66,0,89,177,234,61,27,40,166,
+47,120,134,11,89,33,87,48,129,54,16,97,24,211,55,205,144,241,118,204,212,17,188,140,143,203,113,245,172,177,
+35,34,198,178,33,214,48,109,82,78,42,22,195,120,24,40,152,126,127,119,23,180,155,154,74,178,218,66,236,108,
+105,87,36,213,234,140,218,164,202,13,49,176,36,196,113,179,84,213,79,85,148,24,199,154,51,219,235,152,122,24,
+67,74,9,177,169,162,248,250,153,170,38,16,3,167,33,117,195,16,18,230,43,149,22,105,195,4,174,90,200,52,
+176,106,91,239,107,215,108,233,21,185,225,47,179,170,218,219,228,52,209,64,51,221,186,156,252,21,204,144,180,165,
+59,202,247,111,22,172,212,142,119,49,77,93,17,232,92,52,126,37,102,122,162,138,184,9,102,5,198,129,113,40,
+169,161,125,165,31,3,5,117,220,115,5,139,20,246,235,197,29,55,43,198,74,199,1,57,15,49,19,85,143,117,
+140,63,104,50,58,208,122,171,251,235,205,251,11,214,61,220,95,232,198,186,172,2,167,173,120,169,184,137,74,220,
+84,228,184,71,82,104,172,148,108,35,122,233,173,63,47,66,179,206,243,142,181,230,77,139,2,37,21,89,248,82,
+48,143,141,76,28,227,100,165,62,98,56,151,169,183,109,23,238,165,196,179,5,214,99,149,198,73,184,219,163,245,
+68,165,34,14,243,76,60,236,131,219,75,140,235,126,137,113,104,20,113,3,25,140,37,164,162,137,214,72,83,219,
+67,53,161,195,5,251,0,83,86,152,226,78,122,195,34,249,129,69,231,62,133,209,125,248,14,215,145,7,102,109,
+43,179,149,87,223,201,48,101,82,88,254,149,181,165,108,24,102,129,125,247,218,163,107,136,9,130,148,173,193,224,
+132,207,242,53,111,47,202,246,22,50,200,29,225,155,113,35,233,203,188,23,198,90,34,210,23,143,40,114,212,6,
+53,253,220,67,78,0,213,228,135,141,224,211,161,178,3,81,0,211,242,28,153,233,222,210,19,12,21,159,46,42,
+124,239,208,136,41,90,222,106,254,217,188,213,18,175,195,102,171,156,150,74,2,157,189,214,94,239,199,188,247,56,
+180,186,231,137,12,14,66,55,38,77,210,165,158,159,162,7,157,1,215,104,225,76,113,3,95,36,195,185,191,64,
+12,21,198,224,35,251,140,96,4,60,23,230,171,227,122,205,124,223,207,41,198,169,125,183,239,94,205,92,214,97,
+76,112,67,119,163,251,17,124,107,135,177,116,157,134,81,4,44,59,81,219,253,168,219,110,134,223,175,111,100,224,
+211,207,251,81,191,116,162,12,22,111,241,138,253,120,255,18,53,144,136,200,80,167,96,155,21,176,73,146,156,60,
+175,116,39,255,254,13,178,183,228,237,69,165,235,50,191,214,62,123,159,213,24,214,231,25,227,252,154,239,132,126,
+194,61,81,244,60,124,3,201,105,91,141,200,66,53,135,5,138,223,20,206,198,38,104,215,112,33,222,178,96,204,
+206,7,106,89,218,71,229,50,10,218,171,25,118,185,238,98,117,0,70,135,7,208,179,233,92,10,180,3,21,116,
+138,193,80,103,198,200,65,156,159,65,128,90,190,15,157,65,73,140,31,56,144,214,241,139,149,81,10,140,50,48,
+196,193,107,90,227,132,208,129,48,57,137,32,54,85,2,15,195,50,112,155,193,148,74,21,246,136,12,22,36,203,
+65,108,172,11,190,1,28,39,8,141,161,103,210,135,202,78,168,194,16,246,251,57,31,210,208,118,57,194,119,205,
+64,51,60,202,253,246,205,224,49,225,206,177,251,238,253,8,249,74,126,64,173,212,206,86,141,190,188,12,194,141,
+31,102,180,240,209,66,135,127,38,93,38,232,120,69,221,192,254,39,244,109,104,109,211,81,219,37,24,165,144,38,
+175,169,13,13,139,236,229,160,12,166,21,83,151,253,28,172,138,20,180,43,209,194,55,14,245,20,179,222,55,93,
+166,190,131,179,245,202,64,182,207,218,43,54,235,208,102,33,248,120,120,183,80,209,127,231,118,185,72,43,157,52,
+218,236,250,80,138,39,188,255,100,161,122,90,119,102,249,201,206,32,252,225,30,32,222,229,108,240,201,84,105,54,
+150,246,52,53,230,248,200,218,218,139,240,64,74,13,6,95,188,9,190,64,117,48,81,9,5,162,200,152,213,22,
+94,129,208,70,200,194,170,13,162,184,57,190,237,83,161,26,62,77,17,44,192,137,24,97,11,252,8,51,176,228,
+13,187,192,13,217,248,165,70,219,50,180,71,22,193,149,16,108,163,37,2,34,206,209,189,28,122,217,42,159,45,
+188,38,186,185,90,177,127,255,212,7,174,158,114,248,214,169,246,46,242,68,38,247,61,157,222,15,241,195,109,224,
+204,56,224,130,35,203,212,49,90,68,136,58,89,97,235,168,84,59,138,136,143,219,142,4,99,162,78,245,89,193,
+175,116,231,193,76,212,67,88,22,108,12,234,69,184,83,11,17,98,40,230,147,1,54,90,117,232,99,43,156,197,
+195,198,48,95,152,163,151,198,231,158,51,120,112,193,185,232,228,114,22,2,7,152,206,102,19,3,52,17,56,115,
+24,194,210,169,234,186,255,216,181,70,197,18,182,39,144,163,225,77,45,83,100,164,1,21,86,152,247,81,159,36,
+166,33,34,181,164,143,14,42,181,164,15,25,44,203,137,188,141,23,104,149,17,254,110,137,248,36,169,15,71,51,
+58,225,15,105,177,167,24,57,235,22,107,130,207,109,219,14,32,178,213,48,190,10,226,116,38,126,8,137,33,195,
+17,14,64,203,6,241,8,196,215,171,34,201,195,239,96,167,16,223,53,152,31,38,65,48,217,74,109,197,186,181,
+178,198,47,176,207,251,14,52,121,195,99,50,243,202,27,147,105,170,157,77,163,242,232,246,4,14,251,246,68,200,
+48,238,9,198,61,233,198,125,137,113,95,138,118,160,206,144,77,226,132,150,236,154,56,119,32,50,160,167,171,46,
+1,157,180,170,240,68,114,238,137,228,52,36,146,151,29,34,121,97,136,228,196,16,163,115,185,69,162,185,113,44,
+153,181,231,86,41,123,170,65,29,82,222,202,43,9,156,85,54,133,26,18,151,209,141,218,140,65,43,68,214,193,
+171,250,37,218,71,82,151,147,74,94,169,155,113,101,252,68,84,34,198,248,241,26,83,198,38,101,2,41,152,142,
+92,182,75,72,14,170,184,128,156,76,61,163,33,214,113,21,215,1,229,138,233,235,9,231,72,229,66,76,170,248,
+66,5,40,189,44,153,153,17,93,169,141,188,81,87,208,224,165,186,128,191,183,234,98,140,29,186,194,206,99,202,
+216,164,140,77,10,116,21,250,117,133,19,116,18,95,202,219,39,49,76,193,151,49,28,136,147,248,74,110,159,196,
+55,114,251,101,124,221,178,180,250,160,159,73,226,103,150,170,14,205,244,91,75,55,104,85,211,63,232,212,58,42,
+188,60,250,109,40,140,110,159,197,128,200,249,11,157,2,66,27,237,153,45,132,212,129,84,117,234,191,163,48,31,
+229,26,18,174,54,122,232,33,143,62,81,69,135,129,45,117,32,105,77,73,230,94,113,76,209,202,49,69,201,8,
+170,185,204,109,33,195,6,54,54,219,192,198,43,142,2,239,227,237,184,234,136,46,216,56,21,70,142,97,138,198,
+39,176,120,37,162,255,152,90,236,115,209,39,137,211,195,51,221,193,39,90,58,198,178,244,47,134,253,187,19,101,
+159,19,53,120,125,98,82,96,240,36,247,194,138,169,12,120,200,203,86,149,114,129,243,86,6,143,29,115,94,32,
+167,2,46,228,70,213,48,236,185,192,55,140,167,139,96,124,179,40,12,77,144,119,25,163,114,178,134,161,174,205,
+222,24,214,237,186,100,221,174,64,173,30,75,135,82,118,247,138,216,117,92,75,182,112,24,235,80,45,107,35,83,
+49,78,161,202,91,181,26,231,160,57,216,117,168,9,122,208,27,0,166,127,213,219,231,44,171,24,122,95,26,206,
+96,28,104,26,64,34,100,183,190,42,20,22,236,84,84,245,165,33,131,90,72,223,44,244,231,89,117,93,141,158,
+220,211,78,168,91,231,210,48,96,12,84,201,166,175,242,199,89,56,10,189,153,210,170,236,77,224,100,41,250,211,
+90,147,2,221,70,158,8,204,48,129,125,127,107,120,149,61,229,183,174,186,219,45,169,187,93,169,103,87,86,217,
+173,235,92,235,254,169,95,226,164,1,160,191,148,91,84,38,135,189,140,66,59,180,141,110,91,17,56,203,98,45,
+184,123,214,161,211,3,110,224,2,27,24,159,96,19,147,39,216,8,252,29,104,6,96,238,125,125,166,188,239,81,
+103,239,82,174,36,238,113,238,93,24,123,127,71,185,158,11,137,125,195,158,65,191,132,104,195,130,93,164,153,225,
+132,129,238,136,203,117,239,104,60,243,94,145,55,120,102,139,75,137,33,123,115,87,178,243,20,21,39,242,179,32,
+75,97,33,75,225,33,11,217,140,8,1,134,220,240,99,220,250,174,187,67,174,252,83,221,7,177,11,96,242,7,
+185,182,0,121,188,177,224,119,206,112,120,62,46,91,184,9,215,193,85,66,236,116,70,3,228,86,158,154,123,41,
+188,123,170,131,119,12,221,19,11,119,79,132,183,217,37,204,107,239,134,193,145,219,229,251,49,234,97,234,168,49,
+186,65,245,245,203,135,30,17,168,58,207,65,32,10,7,179,58,198,191,199,112,173,31,203,173,191,126,111,158,110,
+225,114,186,177,58,51,112,62,207,110,206,229,237,224,234,99,74,216,171,91,232,203,5,117,4,59,113,165,46,136,
+225,0,157,185,162,250,153,85,213,185,147,180,108,96,206,214,56,206,64,233,171,179,156,185,64,116,227,88,158,42,
+87,213,244,250,233,41,116,245,90,172,162,171,179,235,115,44,26,150,152,98,111,44,63,99,37,90,216,13,189,116,
+154,57,155,133,38,14,87,119,162,74,179,169,153,35,209,195,89,152,88,25,64,90,58,40,75,254,251,80,22,170,
+149,113,22,186,210,123,175,209,82,31,80,70,15,203,223,143,203,132,210,5,225,26,186,148,97,228,37,129,35,149,
+24,228,37,233,34,47,9,48,46,126,31,242,82,116,223,207,45,150,232,161,91,151,216,96,156,191,148,14,114,56,
+208,114,139,15,98,113,30,32,231,169,67,206,151,29,172,127,225,177,254,121,136,245,111,58,88,255,218,96,253,245,
+81,72,62,136,105,56,67,245,30,0,213,157,59,180,238,220,161,58,184,124,187,190,137,117,231,126,208,206,166,115,
+50,94,32,200,174,28,82,78,116,223,62,21,70,85,155,34,233,100,46,115,140,249,231,38,129,156,77,150,190,216,
+84,84,93,42,115,105,254,142,231,84,45,191,127,150,76,41,124,94,51,88,201,114,178,30,108,136,82,37,118,102,
+141,95,212,152,157,220,207,171,127,131,229,134,107,183,117,155,246,55,131,195,64,44,226,222,86,168,166,197,161,54,
+36,205,190,238,88,129,213,238,238,239,44,32,106,28,107,175,18,127,97,137,112,166,203,63,26,19,162,204,16,236,
+191,26,244,31,171,100,173,12,251,255,86,150,246,99,139,160,4,180,59,60,150,142,108,159,102,144,237,19,242,152,
+134,57,64,200,109,170,186,146,210,201,16,63,5,245,214,247,249,41,149,244,89,133,76,145,177,2,237,88,38,203,
+55,181,125,44,198,23,253,200,48,51,30,42,228,161,64,207,57,176,69,153,129,144,199,146,14,241,88,82,250,8,
+95,160,18,251,219,121,167,74,232,163,243,46,5,70,83,194,71,41,8,111,229,189,12,19,230,30,26,224,19,174,
+213,231,179,248,200,167,80,200,193,235,248,58,32,85,133,225,221,161,5,235,58,16,240,194,220,93,30,82,48,244,
+86,150,108,146,0,249,78,118,246,218,105,161,216,129,99,33,158,30,29,31,159,160,219,116,170,186,234,62,125,203,
+36,32,187,205,237,133,132,64,15,133,232,197,247,99,248,202,12,163,249,90,116,87,162,246,111,93,104,75,135,29,
+226,194,3,82,94,94,38,249,105,190,94,38,138,150,187,7,253,75,217,88,53,3,180,158,32,117,79,255,93,150,
+246,58,97,61,95,207,97,192,130,90,248,88,236,100,47,146,111,118,138,254,117,176,137,192,41,174,48,79,28,120,
+186,216,129,94,248,112,230,207,30,146,69,109,221,207,219,103,30,251,252,200,30,54,202,115,209,174,35,141,152,144,
+192,101,222,122,19,91,105,0,63,250,2,152,137,61,224,169,232,59,83,27,189,72,138,162,4,6,61,212,7,230,
+232,169,145,7,73,243,192,52,240,96,52,78,88,14,167,219,3,150,135,76,173,144,101,126,206,125,106,141,191,129,
+58,179,238,254,29,111,217,193,165,23,75,244,161,59,143,106,4,8,232,123,219,88,84,11,71,173,6,185,212,108,
+86,18,32,0,204,250,123,195,128,52,90,162,53,104,91,218,52,58,182,160,124,41,2,221,105,130,242,144,203,154,
+189,197,75,96,184,34,47,154,124,184,169,19,62,145,33,12,128,17,247,23,154,71,254,105,96,193,75,43,180,148,
+28,152,156,202,2,90,168,7,231,177,146,165,0,53,62,150,182,233,207,87,37,163,218,157,37,112,153,198,236,92,
+158,216,222,76,34,136,176,240,1,128,67,111,230,80,131,28,154,110,247,123,61,200,222,229,9,24,80,36,47,55,
+141,51,33,236,222,51,40,248,64,51,236,233,110,90,215,214,105,131,211,141,84,63,90,122,53,238,48,87,240,33,
+203,192,171,123,233,13,81,86,129,33,202,170,237,207,102,248,102,72,124,246,130,184,236,222,31,16,51,137,205,53,
+90,14,95,163,129,35,190,138,252,140,68,5,124,84,120,157,213,230,99,43,218,54,47,184,56,116,10,234,51,186,
+24,239,73,23,131,248,232,129,138,76,94,200,32,127,124,170,237,91,238,235,34,99,77,13,109,124,12,80,81,243,
+236,159,23,17,203,70,179,182,70,43,14,232,81,100,94,204,135,63,143,2,1,10,13,229,42,93,235,230,247,20,
+48,189,68,195,199,161,26,15,231,150,90,121,177,165,22,172,211,3,160,201,22,91,224,223,160,237,212,104,68,239,
+250,54,135,181,168,173,133,155,85,43,161,4,145,214,56,179,144,123,197,77,227,189,210,3,10,230,217,194,207,91,
+112,125,147,218,249,148,211,134,212,206,165,198,135,207,226,5,27,133,54,183,84,106,119,21,130,147,54,212,54,97,
+111,170,199,210,29,64,171,212,237,245,71,72,163,99,36,247,188,113,87,159,46,147,232,88,154,255,142,254,91,140,
+172,180,56,37,254,63,139,197,130,98,94,13,169,32,133,140,230,248,137,220,227,241,198,127,150,158,139,29,19,103,
+21,47,237,78,253,24,225,43,193,144,109,172,53,223,157,178,76,2,114,105,138,242,229,123,84,41,116,193,198,12,
+13,128,146,194,38,88,253,230,207,161,224,35,86,236,223,112,190,234,190,225,252,57,224,13,145,137,107,47,71,111,
+44,206,48,195,232,80,250,62,19,141,134,215,101,67,225,18,119,196,161,153,160,235,47,165,232,251,115,103,132,62,
+222,205,55,149,253,250,211,49,236,152,164,198,170,70,240,171,191,223,52,127,219,160,207,147,214,103,135,253,85,24,
+221,24,248,176,34,127,54,56,114,222,20,50,93,199,222,203,189,65,16,225,215,162,133,240,97,225,158,251,248,101,
+116,222,74,247,76,185,163,182,157,203,91,201,29,123,2,154,77,173,244,98,22,187,64,20,39,126,209,216,77,197,
+206,159,45,86,247,236,56,0,5,104,229,21,15,155,23,107,112,150,123,11,165,103,154,138,196,199,78,191,24,111,
+102,190,82,122,33,188,0,204,221,66,120,8,59,196,242,98,139,88,55,216,253,31,141,176,62,10,114,46,27,196,
+148,2,41,51,91,202,32,51,79,11,190,150,206,130,104,103,138,101,52,34,168,194,227,246,120,48,134,2,145,26,
+12,154,102,112,82,254,200,152,50,219,219,241,40,6,20,44,59,234,168,175,0,82,208,143,177,154,96,42,27,152,
+137,6,97,214,88,97,69,130,229,211,246,202,83,179,63,69,104,16,5,243,35,54,220,74,255,226,131,3,226,210,
+195,72,102,215,118,188,24,52,241,144,249,233,101,188,50,60,60,58,228,141,4,80,146,83,187,49,157,195,165,59,
+220,19,255,208,192,9,24,144,253,7,8,78,245,81,93,35,9,120,4,186,124,205,3,246,52,25,160,182,178,247,
+38,246,127,56,121,193,139,149,30,122,177,130,88,247,217,210,54,230,157,106,66,221,93,108,9,31,12,91,144,204,
+217,56,161,221,211,117,228,155,98,180,40,11,190,28,124,12,223,92,28,113,183,45,8,244,75,224,44,58,0,242,
+129,33,39,95,228,194,238,126,29,117,181,39,61,168,226,74,41,165,155,47,128,171,144,113,65,133,186,9,117,152,
+50,226,104,52,100,129,96,31,191,147,252,123,179,244,31,210,114,109,160,175,241,220,148,164,24,135,0,246,249,162,
+39,93,185,187,184,48,10,126,23,23,22,49,120,201,222,171,227,98,33,95,25,23,22,241,118,33,173,165,166,248,
+106,33,63,108,46,45,212,249,176,144,246,227,20,62,8,169,122,191,104,221,145,126,189,80,172,59,160,158,57,77,
+192,198,107,2,206,34,173,88,133,112,114,34,189,71,199,29,59,246,52,251,162,65,7,162,214,64,104,131,248,142,
+245,121,42,164,22,94,135,241,213,98,223,111,149,87,41,108,172,165,80,227,116,207,193,179,215,92,194,155,95,64,
+24,87,55,175,125,41,202,139,120,116,57,211,113,221,218,156,191,121,143,21,206,161,53,254,65,49,127,195,213,176,
+12,129,76,200,99,200,68,182,62,214,25,203,163,107,61,44,143,222,56,211,84,70,35,26,193,96,79,184,252,26,
+163,222,35,174,167,142,67,215,21,230,252,160,116,30,10,32,239,51,240,194,76,56,17,238,150,235,81,248,222,169,
+112,232,122,139,244,40,105,45,202,214,24,28,70,119,41,246,21,191,48,90,154,169,142,106,180,199,58,216,39,51,
+184,35,234,89,107,148,37,35,231,240,229,39,136,18,129,125,177,233,193,30,177,99,231,172,126,133,117,33,190,15,
+205,159,105,236,72,3,139,3,91,160,144,141,252,218,58,38,217,235,137,144,191,45,32,201,123,129,17,237,92,195,
+225,88,153,247,224,38,121,147,173,178,166,102,203,191,16,253,210,184,178,159,199,13,26,69,112,1,221,114,215,126,
+168,17,86,193,74,99,247,114,109,202,196,5,102,142,107,159,235,187,172,248,46,185,69,6,192,180,7,155,177,164,
+97,153,103,0,30,140,53,48,184,232,10,52,25,174,225,163,222,155,2,223,115,26,30,180,167,10,118,117,161,106,
+235,223,225,35,86,23,138,137,83,86,169,149,203,218,23,1,47,237,37,227,221,54,237,79,63,68,41,35,229,167,
+113,221,185,43,179,50,46,143,106,220,0,184,164,227,19,177,191,83,249,105,140,75,69,133,177,76,47,79,246,247,
+59,247,22,51,29,125,21,31,139,192,69,81,3,78,149,20,96,6,227,177,168,201,22,186,85,216,173,90,127,84,
+91,234,53,187,58,239,30,135,225,93,213,24,183,236,13,187,170,157,161,131,102,0,60,94,173,159,206,232,81,16,
+51,228,126,193,137,161,95,16,245,111,60,168,3,139,102,32,82,180,123,78,217,3,37,108,2,151,15,149,195,170,
+113,127,216,254,211,9,194,93,224,160,15,192,198,216,164,5,85,90,80,158,71,81,51,233,207,178,120,220,95,165,
+78,103,112,7,237,205,154,217,165,60,95,232,8,191,121,166,253,62,192,110,116,187,192,163,194,185,36,111,243,216,
+138,137,132,68,147,41,24,114,0,57,251,253,29,187,138,105,76,65,233,71,131,35,97,231,245,61,196,136,92,60,
+183,107,184,27,230,10,40,143,70,127,42,171,237,104,10,17,142,108,86,59,51,212,152,133,185,99,72,244,90,240,
+253,237,21,106,210,127,187,239,178,121,103,207,121,140,182,248,244,58,46,37,2,9,99,102,197,184,157,131,241,212,
+198,144,140,76,33,95,19,167,152,98,78,112,188,52,96,39,251,4,80,41,94,72,178,31,245,220,214,54,71,237,
+186,141,42,81,28,102,173,96,254,165,1,62,43,83,239,37,62,44,94,168,135,63,69,40,126,135,191,137,144,87,
+248,155,10,121,163,162,203,201,74,60,142,22,112,88,205,97,191,86,223,20,145,141,92,63,6,165,227,141,220,74,
+99,20,25,175,138,235,167,39,122,114,242,39,48,142,120,1,255,110,29,239,140,206,221,170,149,244,117,217,158,79,
+95,218,163,158,234,44,143,46,31,95,139,137,9,46,242,18,14,240,10,194,242,229,179,53,236,98,211,222,203,71,
+215,212,154,144,63,69,57,158,155,173,45,190,46,111,162,147,99,124,168,185,14,234,187,126,180,21,143,183,66,6,
+0,115,22,157,170,94,11,143,174,229,135,78,39,48,74,196,144,113,5,9,151,66,194,32,192,99,20,92,91,47,
+147,40,74,38,149,120,92,202,235,199,96,119,79,204,34,236,62,239,64,22,195,178,185,174,229,82,96,135,108,232,
+165,60,85,21,84,152,136,248,10,123,113,49,171,226,83,8,223,206,146,24,230,77,165,147,19,204,251,97,114,10,
+121,161,249,151,244,125,45,111,116,244,82,6,205,188,20,174,249,78,235,80,40,152,76,8,178,9,116,15,77,255,
+90,68,48,165,240,247,20,82,187,115,135,19,58,251,53,134,41,60,13,107,61,53,115,40,63,132,113,31,76,156,
+217,7,175,200,84,7,204,81,4,239,31,167,200,59,4,28,173,15,104,229,233,83,16,211,127,53,30,227,96,130,
+154,162,211,241,43,152,108,219,70,37,255,130,214,223,111,100,38,132,201,44,98,87,76,76,95,61,125,9,175,241,
+175,68,183,234,3,85,121,200,14,11,7,221,250,128,110,14,102,154,37,51,110,16,190,120,56,68,128,70,38,216,
+129,196,118,96,54,144,65,37,113,183,249,164,133,133,122,8,60,211,15,10,26,128,78,119,147,63,180,29,141,91,
+168,28,145,199,221,146,65,127,172,241,100,191,119,52,78,209,122,60,244,162,137,240,253,71,69,218,218,0,168,97,
+91,213,194,14,56,45,107,248,134,237,143,47,96,178,82,71,255,245,213,163,230,81,52,2,18,219,221,247,110,252,
+188,37,27,216,180,149,32,53,199,213,231,163,149,6,158,118,16,74,40,70,225,123,16,79,200,120,15,58,26,226,
+117,76,186,55,48,48,143,249,243,85,6,87,71,104,3,196,90,88,17,0,95,24,181,27,55,194,222,40,227,134,
+94,77,16,38,154,166,44,129,227,17,53,35,145,112,218,252,93,87,37,92,216,221,23,144,16,139,211,33,22,87,
+220,131,197,213,152,217,241,223,253,163,164,122,86,43,61,171,227,92,38,24,40,85,1,248,143,97,224,52,94,128,
+230,59,227,245,57,197,223,18,106,124,10,136,69,250,244,120,6,12,56,17,231,207,48,132,127,42,8,182,68,148,
+148,168,184,141,69,79,166,81,249,204,89,156,249,238,244,231,139,15,167,175,208,226,204,199,175,191,249,250,61,176,
+243,159,114,218,235,183,157,52,227,76,210,191,168,150,143,142,142,191,66,77,159,168,28,163,44,29,188,104,69,245,
+36,23,45,163,141,181,71,27,141,114,29,78,47,98,192,135,141,38,35,204,181,243,67,23,148,201,30,107,115,175,
+25,230,39,78,170,100,20,161,152,69,117,0,195,92,115,143,139,206,189,224,58,4,209,227,19,89,63,3,88,8,
+67,193,30,148,185,62,186,73,170,34,250,135,241,191,9,146,7,228,112,109,222,218,206,28,113,195,15,190,216,21,
+237,131,155,114,147,207,31,84,186,134,75,252,1,217,99,4,58,243,193,102,253,160,41,33,75,221,62,176,229,30,
+96,207,49,9,227,79,142,143,143,143,254,129,23,11,130,97,17,59,188,155,205,73,243,188,72,141,143,95,39,168,
+18,0,93,172,67,71,136,181,128,10,218,189,34,124,18,14,217,16,234,35,236,195,86,209,121,238,67,186,40,104,
+101,90,248,91,225,137,44,130,247,121,198,37,10,73,104,72,67,116,135,65,67,26,236,190,217,233,13,22,14,208,
+17,125,196,223,22,111,209,60,219,22,81,129,8,243,27,224,40,22,38,112,24,38,44,128,142,3,168,114,8,47,
+161,186,32,4,18,184,93,124,7,146,59,97,243,36,211,242,3,103,133,112,193,190,231,203,74,1,18,86,203,210,
+163,246,3,148,214,77,25,85,210,100,31,25,24,54,18,178,113,239,117,179,40,124,186,11,0,167,219,193,30,116,
+186,205,11,187,198,231,227,88,206,199,37,133,172,60,69,209,95,112,191,200,218,87,81,112,89,4,50,195,20,72,
+143,138,67,62,114,151,188,175,85,84,76,0,231,247,126,55,249,54,148,39,2,4,193,245,68,213,178,24,171,186,
+221,187,5,116,255,2,40,246,97,63,84,62,72,116,209,2,124,13,129,64,115,137,187,155,151,120,174,229,62,148,
+33,78,176,104,233,138,251,222,107,242,175,178,221,61,68,187,165,214,99,61,72,128,51,248,251,2,237,91,53,177,
+247,139,9,49,26,16,133,248,196,198,28,186,115,134,206,120,184,138,253,45,14,75,57,243,226,49,161,92,140,44,
+16,47,216,31,124,120,14,16,42,69,141,71,26,138,0,105,40,24,105,40,85,71,104,8,187,134,140,77,215,231,
+99,62,9,30,24,235,199,12,188,192,92,115,25,10,62,214,226,110,186,244,223,73,113,30,166,5,255,8,1,216,
+182,223,23,72,221,185,199,163,41,4,15,211,118,239,252,195,67,85,31,1,130,162,171,44,13,105,186,127,134,6,
+50,178,199,33,158,29,82,31,198,102,134,128,217,57,241,88,226,175,61,114,176,155,223,192,92,33,100,17,222,146,
+24,215,105,67,11,17,242,101,214,208,142,129,12,135,251,209,96,186,16,80,174,234,182,72,170,192,65,92,217,105,
+170,130,228,92,85,128,171,132,177,140,84,64,50,88,177,157,151,15,186,188,23,244,249,247,107,89,197,48,79,37,
+234,180,142,199,137,76,112,30,142,141,94,238,9,68,84,88,45,112,88,102,39,72,147,148,33,253,145,60,234,246,
+224,17,40,189,228,211,155,101,134,42,157,79,1,168,87,80,21,220,183,201,83,190,215,82,154,132,228,214,67,249,
+94,159,210,94,159,106,130,36,111,138,255,123,100,249,32,90,204,204,214,85,200,78,192,244,158,45,0,169,207,13,
+191,186,64,134,155,216,217,74,209,127,191,122,200,6,138,105,216,95,68,5,50,65,193,213,99,97,248,247,237,191,
+15,58,242,109,129,60,108,83,121,23,88,134,25,116,144,129,193,89,128,152,195,78,232,140,66,220,3,101,135,19,
+254,8,111,246,65,225,47,213,154,47,85,102,252,3,50,15,25,102,200,135,233,161,249,17,26,21,82,207,14,31,
+183,92,136,113,42,166,184,88,53,202,222,60,133,125,30,149,17,160,137,21,100,22,34,134,64,18,21,210,176,109,
+43,248,172,37,124,193,55,230,4,94,4,198,216,196,218,68,84,38,55,134,121,202,96,254,92,231,1,243,161,205,
+183,249,244,73,215,141,158,195,2,194,14,64,162,53,226,17,30,195,166,224,86,127,63,179,216,227,158,102,207,144,
+52,104,13,178,19,132,46,6,49,201,109,43,11,5,144,206,222,228,247,161,93,197,97,180,171,248,191,67,187,138,
+97,252,132,175,52,58,191,179,209,241,40,254,215,209,149,65,212,142,122,53,29,196,221,186,64,4,97,247,62,255,
+28,163,121,36,19,12,220,117,65,71,126,52,214,100,55,110,133,200,247,195,243,140,157,207,189,70,220,121,151,99,
+118,42,140,92,251,200,116,224,95,189,222,249,38,60,120,157,243,254,9,15,220,30,54,160,7,184,190,237,27,186,
+245,203,79,73,149,53,203,85,150,142,166,111,62,255,234,247,229,232,246,8,197,167,58,246,82,211,162,39,92,134,
+245,34,192,102,43,133,40,160,70,159,60,102,107,237,18,27,158,87,229,250,93,207,170,215,215,228,138,8,177,247,
+5,11,255,124,235,191,197,88,59,137,106,42,18,152,229,251,169,111,161,75,171,111,44,62,11,207,99,114,119,19,
+127,145,96,6,167,18,163,133,92,198,142,37,246,168,9,208,191,214,215,249,119,54,253,38,107,174,215,60,119,90,
+107,129,245,108,103,86,36,110,38,232,55,11,95,135,155,49,124,181,113,246,20,179,60,11,51,216,228,54,118,49,
+46,123,208,222,219,69,56,171,187,60,206,172,243,162,204,27,63,199,176,172,226,140,156,100,5,41,228,168,12,146,
+154,114,29,20,193,160,188,132,104,203,248,15,138,80,76,43,245,190,238,128,113,8,117,118,238,236,157,96,161,50,
+43,232,209,136,166,13,13,254,50,28,8,146,165,113,37,66,38,124,57,118,246,243,227,50,62,230,167,44,167,80,
+157,143,199,94,87,188,10,133,246,141,193,90,95,1,69,227,101,51,69,181,107,149,58,225,120,186,194,150,138,75,
+120,11,4,185,204,140,192,34,100,67,89,193,49,150,148,137,176,154,136,41,25,156,159,43,220,61,198,62,236,66,
+118,134,138,217,225,98,195,230,230,212,204,70,45,168,111,230,145,252,180,248,148,107,232,212,24,42,93,135,104,221,
+186,136,54,2,213,20,97,23,173,37,168,86,200,249,209,141,60,150,39,255,125,44,228,165,139,221,66,236,82,254,
+207,177,124,242,95,128,126,252,104,238,16,185,49,158,28,219,204,204,134,159,71,36,90,39,176,103,209,38,231,4,
+110,13,116,48,7,225,6,194,151,16,190,20,221,190,91,195,20,191,192,200,204,254,245,219,236,71,140,218,19,27,
+102,36,151,105,45,205,248,51,199,35,221,133,241,83,246,225,139,126,184,236,245,243,20,186,55,139,18,101,186,73,
+113,248,184,0,155,216,51,138,32,32,49,61,17,34,46,240,138,2,105,63,107,242,38,50,65,28,151,45,84,121,
+142,78,102,198,90,141,161,144,172,185,177,102,22,229,42,194,57,168,93,99,21,148,107,194,198,26,51,71,57,52,
+86,83,99,151,134,77,24,153,32,78,154,45,116,25,54,118,41,33,126,156,135,246,255,204,44,6,24,44,157,141,
+225,99,81,250,99,1,243,7,160,178,68,45,246,68,117,118,34,58,39,14,15,205,224,129,169,131,3,147,162,94,
+236,83,224,196,242,129,25,222,241,169,76,198,213,88,159,165,231,248,128,180,232,109,73,216,187,176,154,184,103,199,
+127,17,2,183,126,131,57,55,234,155,69,228,118,227,2,119,242,15,139,104,129,187,247,111,24,111,247,238,26,78,
+2,209,24,183,49,70,110,227,77,224,22,97,109,61,95,172,156,79,117,107,105,99,140,37,201,23,198,6,2,203,
+86,176,51,53,63,191,208,90,214,129,176,199,22,194,194,97,153,57,141,49,0,170,24,236,218,65,13,172,152,238,
+95,0,129,41,200,137,106,98,221,181,34,138,113,168,228,152,5,182,62,135,234,248,31,232,11,254,194,9,157,217,
+50,113,164,159,65,8,162,159,254,207,177,160,170,58,21,253,213,84,20,250,133,15,28,135,7,171,30,23,104,11,
+150,215,184,86,205,228,100,90,63,131,165,174,39,19,127,54,139,207,128,139,181,16,86,75,180,180,80,141,117,44,
+131,37,74,101,206,230,70,227,5,45,209,156,151,167,85,251,0,4,237,116,239,220,149,109,5,254,214,173,50,94,
+253,224,53,117,205,150,219,87,120,185,151,251,151,123,168,131,185,150,218,43,173,47,39,43,123,155,45,224,3,239,
+168,249,100,57,94,145,18,213,102,178,128,111,103,32,20,60,118,232,30,92,198,110,193,25,234,105,172,202,202,249,
+242,40,143,204,111,56,246,97,95,29,29,207,28,139,170,111,235,149,28,91,103,56,94,45,234,163,164,74,97,1,
+110,45,84,134,62,109,233,11,93,137,252,32,166,236,223,188,28,58,154,70,20,170,70,149,81,50,156,131,26,81,
+161,116,199,9,72,119,20,70,184,99,176,60,52,67,158,150,131,242,97,255,127,30,16,1,35,207,17,40,239,155,
+85,233,38,79,120,142,170,192,241,85,130,166,153,209,251,223,195,2,180,91,42,248,151,224,246,134,61,30,57,23,
+212,61,175,206,85,199,231,115,210,115,233,220,4,242,155,3,94,166,155,125,241,206,174,99,100,179,18,86,179,68,
+214,161,90,39,247,2,63,67,101,47,255,48,57,108,171,213,10,111,105,210,135,106,200,68,171,223,82,163,214,189,
+39,62,215,33,179,245,78,22,9,109,132,174,149,206,253,184,16,240,135,241,225,150,102,99,168,251,119,184,85,79,
+123,153,173,116,81,247,13,96,246,61,42,165,69,135,163,42,140,157,100,213,119,230,68,46,110,216,64,175,44,66,
+223,80,156,231,219,174,169,222,105,103,204,253,39,44,131,170,106,116,215,99,62,5,207,198,96,110,68,82,11,204,
+140,95,98,127,150,130,252,193,43,83,129,227,249,215,57,60,39,61,14,15,108,119,166,0,251,172,112,78,180,84,
+196,241,239,231,138,239,241,156,251,131,124,220,95,44,209,210,163,157,169,199,110,11,220,116,29,118,217,126,150,80,
+25,74,12,108,172,190,200,151,85,94,180,82,169,12,39,254,214,233,74,23,53,33,114,81,158,65,153,243,46,147,
+163,134,55,89,188,175,103,53,250,147,19,108,183,208,214,190,175,252,104,60,52,102,121,214,108,163,2,79,237,193,
+231,214,105,64,74,54,97,119,92,244,12,200,37,211,149,24,255,246,112,101,86,245,104,123,241,140,247,134,123,121,
+28,108,55,100,221,107,220,102,188,127,247,115,20,147,154,115,132,11,58,97,220,115,127,173,159,72,135,98,114,31,
+68,219,165,34,2,238,192,15,143,163,189,117,100,173,221,19,209,149,94,36,252,215,84,130,166,123,104,105,22,48,
+218,71,122,140,178,23,182,169,151,153,21,56,120,85,149,43,59,172,144,123,210,19,69,133,157,207,154,9,123,131,
+97,118,204,132,185,42,211,33,233,123,230,108,249,252,226,145,142,163,134,203,65,48,100,147,236,119,241,190,174,97,
+95,238,239,221,221,221,227,252,58,118,37,198,186,29,66,179,194,53,234,47,16,28,5,171,81,217,23,165,244,84,
+3,202,1,82,79,240,158,218,211,75,151,13,250,104,106,247,110,126,242,39,212,179,103,210,223,61,147,191,140,11,
+182,207,31,10,215,192,46,8,183,59,96,133,76,228,113,34,163,50,134,58,136,235,253,94,248,205,34,117,247,153,
+106,160,191,20,127,215,158,211,194,11,42,114,193,187,43,246,93,128,125,206,109,96,13,206,145,80,119,213,184,94,
+198,197,13,2,172,13,2,92,16,2,92,59,4,184,108,213,224,5,236,23,237,158,226,125,107,40,174,209,190,202,
+76,35,63,85,217,60,222,57,140,12,221,215,236,235,237,242,182,97,143,122,211,194,225,98,69,31,91,194,44,159,
+51,233,221,183,108,33,181,60,4,103,176,145,16,241,42,66,171,82,20,194,104,143,132,217,241,127,3,67,187,223,
+27,160,220,153,125,134,8,99,29,23,118,62,106,52,24,92,238,173,193,176,137,65,29,222,9,254,170,248,235,130,
+13,106,6,177,24,229,89,213,95,39,233,50,138,82,185,196,251,15,170,90,62,52,175,76,137,250,140,249,75,73,
+140,119,234,108,232,222,105,104,194,72,170,79,127,166,62,45,100,2,253,66,77,252,192,61,39,244,199,27,89,168,
+84,9,4,96,133,4,96,229,9,192,84,21,123,141,12,2,167,74,8,135,220,47,3,228,126,209,170,116,250,112,
+1,72,253,18,133,209,2,180,125,209,179,36,183,236,89,143,75,67,52,126,223,114,92,186,143,198,127,214,36,106,
+90,139,46,252,69,204,141,223,43,114,53,12,89,42,228,222,245,205,196,17,69,213,129,113,33,76,163,174,99,30,
+116,7,6,206,192,66,139,112,162,109,250,123,248,185,25,22,236,98,19,34,188,233,254,61,93,40,26,153,181,37,
+50,232,235,114,24,120,31,11,103,101,120,26,88,220,112,126,36,245,221,67,171,202,6,243,212,248,237,173,76,121,
+103,191,7,108,74,13,29,10,56,92,116,40,114,171,235,240,80,187,85,226,81,220,181,39,3,46,173,92,6,60,
+86,156,144,242,115,182,6,119,10,89,175,116,214,100,138,46,187,237,50,60,39,6,3,32,112,61,191,69,149,106,
+58,46,154,72,171,149,28,53,117,172,233,165,71,29,142,6,159,101,164,159,246,89,24,129,165,189,73,245,248,201,
+100,97,249,22,147,114,178,52,239,18,24,101,56,24,213,120,65,141,217,4,8,6,44,140,70,82,143,228,49,148,
+149,75,119,82,83,203,170,104,69,219,49,95,226,237,175,226,54,108,159,107,243,180,131,70,7,147,252,13,137,117,
+64,36,191,237,4,30,216,73,95,78,119,157,177,179,59,162,145,12,64,111,88,204,67,140,147,80,83,243,236,124,
+95,63,243,184,237,95,97,40,141,198,104,40,210,75,244,214,180,183,114,216,210,61,178,39,50,100,145,245,184,79,
+68,62,187,72,175,130,238,7,66,142,36,113,9,192,233,103,203,173,133,60,198,150,117,217,191,146,123,172,87,28,
+76,235,103,151,148,42,213,110,228,39,206,46,26,240,33,3,213,216,145,12,248,9,62,71,74,105,56,33,253,88,
+106,133,245,46,85,120,45,134,186,142,56,219,35,118,68,249,49,195,119,233,60,207,106,13,17,184,12,229,106,85,
+22,56,118,59,106,35,178,88,163,59,253,86,14,231,193,52,202,245,103,152,35,128,190,48,198,189,76,127,214,127,
+10,50,45,203,77,181,151,229,203,63,235,175,40,207,147,63,181,114,158,108,247,178,252,247,159,255,196,121,190,132,
+122,110,180,190,242,153,78,168,169,227,63,253,55,231,130,138,32,173,89,238,85,245,228,207,79,254,91,255,217,13,
+239,73,43,255,137,74,249,186,218,171,238,191,254,251,191,255,4,25,185,186,173,78,6,250,126,242,213,159,244,127,
+161,58,125,227,222,192,174,244,182,142,62,102,34,16,127,178,204,92,222,58,147,192,119,208,23,53,166,221,165,199,
+167,145,169,154,204,147,53,66,238,157,145,117,169,226,66,90,59,6,181,204,234,242,39,152,13,156,181,178,197,172,
+152,3,249,10,245,148,53,190,58,250,80,133,82,35,215,60,178,177,43,85,152,123,255,11,248,11,183,123,165,124,
+62,86,51,37,25,27,99,151,61,230,0,50,140,59,186,155,81,109,234,51,2,11,184,68,88,253,59,29,149,80,
+111,169,20,10,173,64,77,230,140,127,191,128,186,70,212,119,180,7,28,135,9,200,138,30,87,1,75,174,41,247,
+249,146,169,19,193,100,254,103,9,113,172,175,10,11,80,62,173,39,39,161,27,209,74,125,204,206,210,6,92,137,
+158,155,55,70,179,182,51,250,141,15,200,140,27,87,170,71,184,238,232,169,197,51,99,34,61,129,23,35,144,190,
+170,236,227,178,120,170,216,226,128,105,163,245,1,232,199,121,240,44,220,121,63,11,123,207,66,165,211,242,89,56,
+24,13,131,241,232,92,165,76,253,216,49,24,79,117,206,157,243,27,5,48,135,5,202,240,22,178,18,207,84,227,
+85,118,171,160,87,122,214,105,34,62,14,250,248,5,206,32,247,173,233,206,236,248,68,106,140,233,121,162,181,253,
+129,138,155,115,234,83,56,33,77,80,187,166,245,180,46,100,181,200,32,21,182,135,97,127,63,216,215,174,221,229,
+37,58,100,203,16,193,191,46,172,114,106,169,52,152,161,133,177,205,240,55,214,103,53,76,200,89,137,213,180,193,
+198,153,239,111,156,224,56,149,106,92,243,190,107,206,142,157,234,75,129,59,27,186,220,87,121,177,207,150,50,55,
+91,46,81,37,88,197,84,213,52,193,90,224,50,136,18,121,2,69,69,174,180,177,140,105,168,248,168,65,60,196,
+72,67,224,1,224,195,232,251,152,149,131,111,131,59,35,156,221,35,93,76,195,21,98,247,198,28,103,37,18,232,
+102,5,217,161,65,85,201,162,171,143,35,77,179,120,25,113,187,165,125,27,123,168,103,69,140,147,131,123,80,106,
+199,185,126,173,63,87,184,143,124,14,41,99,63,12,111,120,107,1,4,191,224,202,129,159,150,178,109,138,172,65,
+75,24,219,17,69,152,62,253,128,177,29,70,182,149,188,198,97,83,132,117,223,12,39,107,14,130,234,20,199,176,
+45,116,22,213,51,180,6,200,223,10,149,127,237,7,212,231,221,113,208,178,27,67,75,87,233,209,133,181,6,120,
+68,209,245,17,134,197,20,112,103,198,188,95,25,220,162,150,78,66,169,142,132,216,235,11,3,229,35,251,97,97,
+51,4,205,111,0,161,33,202,7,90,217,81,234,222,31,181,62,242,1,47,3,57,36,115,101,128,239,23,108,203,
+177,117,182,75,182,128,118,176,214,109,55,242,51,23,113,144,85,126,88,205,34,156,101,233,214,226,8,182,0,176,
+91,204,30,232,107,7,201,64,14,177,10,229,16,147,97,57,68,127,169,230,81,42,118,15,43,102,178,167,134,77,
+215,213,42,169,165,141,21,242,97,18,102,76,110,49,99,25,168,85,75,27,43,218,200,190,93,97,122,78,188,14,
+199,248,118,125,16,50,114,146,121,15,89,50,15,221,200,145,74,13,224,56,169,198,20,59,155,35,168,11,171,234,
+191,36,24,161,228,47,162,90,112,207,106,1,76,240,177,191,8,97,202,113,15,220,68,2,1,82,9,153,75,159,
+185,20,179,18,51,195,97,237,103,29,159,176,184,98,56,23,37,220,2,254,133,130,199,94,67,246,82,180,253,97,
+246,22,217,165,126,132,5,133,254,173,214,78,40,84,31,246,238,93,184,164,183,95,127,115,218,73,98,40,232,173,
+67,107,133,240,87,22,93,176,43,172,82,174,54,187,165,104,63,91,217,103,165,237,246,195,156,104,99,149,86,69,
+249,85,153,29,28,22,137,102,186,103,18,24,231,144,32,102,237,187,206,147,221,145,242,132,119,13,28,16,79,120,
+71,224,19,19,235,96,152,44,69,235,234,146,149,151,218,76,212,50,199,245,147,21,131,241,0,182,186,243,5,64,
+43,217,52,229,135,171,108,61,107,202,72,99,45,8,102,37,87,201,21,118,247,245,139,196,154,140,66,217,246,248,
+239,196,106,74,168,115,242,142,122,132,216,3,233,192,179,48,1,111,183,208,247,20,103,15,145,232,209,204,130,173,
+24,112,12,159,74,117,33,52,180,36,98,109,249,17,108,13,48,9,100,91,179,146,122,217,239,128,104,131,10,240,
+210,178,91,244,216,58,211,151,229,244,78,109,31,132,30,125,185,74,102,44,224,246,20,210,101,69,217,146,153,86,
+39,147,58,214,42,58,92,6,214,214,188,245,200,242,96,197,225,134,239,183,80,168,50,46,84,84,78,62,163,240,
+147,115,129,143,74,172,106,233,18,158,126,137,86,32,142,158,124,53,213,170,64,73,8,84,18,144,5,126,23,246,
+187,123,3,147,128,161,21,56,44,228,34,65,4,32,62,121,28,233,241,201,24,95,23,248,104,244,207,32,131,254,
+65,245,43,185,103,91,179,182,39,181,82,37,237,97,216,183,37,239,55,45,139,67,59,85,27,45,140,175,163,210,
+171,212,157,24,197,11,166,60,102,101,112,213,26,35,66,234,157,54,74,242,185,161,68,228,18,48,3,3,192,22,
+74,203,185,220,32,54,157,194,6,88,168,113,195,16,120,17,208,40,200,145,234,37,166,51,115,169,197,56,133,22,
+227,46,164,70,140,251,68,127,245,40,217,51,203,170,199,163,7,73,49,7,219,95,5,126,85,26,232,154,242,193,
+34,169,30,192,184,42,240,119,158,53,203,7,110,64,15,202,5,100,76,32,227,104,92,9,239,209,32,188,101,216,
+200,24,89,192,118,111,164,29,32,141,24,227,92,45,140,95,132,57,72,135,204,113,12,136,173,206,101,130,139,191,
+25,143,133,46,209,73,175,92,59,248,2,5,140,144,42,155,88,9,238,185,13,110,76,184,135,184,140,12,9,223,
+165,32,39,114,40,129,168,158,173,38,151,246,181,120,165,158,141,87,226,126,195,34,33,246,16,30,85,220,40,172,
+22,235,172,59,90,236,108,166,9,57,139,26,217,75,18,113,152,214,69,234,44,186,135,245,194,229,135,131,179,209,
+175,8,193,184,219,46,170,217,179,88,182,143,40,38,202,131,52,153,171,30,120,146,41,58,104,168,144,58,88,170,
+28,191,242,115,216,84,104,129,71,206,49,2,64,208,2,254,183,64,84,110,186,115,226,135,82,3,184,159,207,150,
+113,42,80,212,174,164,61,225,216,84,110,158,214,179,191,69,107,121,182,145,254,213,61,222,12,74,8,16,156,196,
+241,154,253,98,33,38,19,31,26,182,205,120,172,69,173,26,236,41,121,132,160,206,13,76,93,77,100,148,70,100,
+148,129,214,189,186,112,225,171,238,208,27,108,40,179,63,184,123,24,134,201,226,48,180,13,239,208,97,213,59,194,
+192,198,248,182,124,100,193,223,125,162,248,247,180,205,69,30,187,10,39,6,115,243,93,161,71,227,226,209,208,184,
+25,0,34,96,8,27,222,215,164,144,254,177,175,195,204,110,28,27,219,216,82,24,208,179,156,105,108,116,88,153,
+24,145,207,224,53,88,86,42,120,254,149,201,125,202,147,134,63,226,30,64,111,226,226,81,57,6,174,137,92,194,
+87,5,95,101,219,238,67,248,67,131,36,212,110,239,220,213,120,136,204,45,114,254,191,255,91,28,5,188,77,119,
+243,14,159,241,99,198,37,128,5,177,135,77,132,150,174,59,107,80,118,181,0,7,39,212,203,76,61,174,142,110,
+66,197,85,8,47,197,228,132,221,142,130,238,89,18,159,180,251,208,27,207,101,207,77,177,177,22,136,130,2,120,
+170,241,210,114,167,180,239,175,216,99,50,208,207,116,9,124,60,35,58,147,107,180,76,8,85,99,217,62,205,201,
+104,45,215,214,111,89,33,82,219,179,99,120,154,231,239,144,60,181,79,194,150,12,21,1,28,169,251,112,4,6,
+132,85,164,9,250,16,209,159,85,157,152,30,234,144,137,224,33,160,106,207,62,82,63,236,241,249,40,247,82,23,
+56,207,159,61,161,4,54,239,30,163,101,197,56,170,28,199,25,14,162,223,9,213,95,138,89,19,239,143,44,8,
+48,8,125,3,251,215,222,185,255,92,160,79,131,215,246,161,7,15,202,104,250,58,124,224,33,251,5,22,99,144,
+142,235,129,166,128,49,115,76,108,12,68,150,240,28,225,111,133,37,240,163,139,75,17,134,22,143,130,99,54,146,
+157,19,137,213,182,252,132,99,144,149,120,132,244,201,104,79,51,232,164,237,232,10,179,113,107,92,18,131,182,171,
+204,43,219,151,210,62,224,235,25,74,201,100,192,250,67,163,220,40,44,3,129,154,2,81,200,48,124,211,64,133,
+35,136,31,201,6,159,183,225,43,46,237,136,147,214,212,96,227,42,27,151,183,166,34,17,115,253,24,237,27,192,
+208,96,11,152,64,77,152,138,74,137,181,82,19,20,87,97,28,55,193,47,161,213,164,116,59,35,157,37,227,8,
+213,27,224,34,152,148,226,113,26,39,196,155,251,232,21,111,95,223,199,155,107,112,106,189,60,40,172,215,187,210,
+241,204,194,44,70,6,145,226,67,202,41,56,47,12,252,252,105,66,243,102,88,218,42,231,115,109,244,109,72,244,
+55,101,121,181,89,99,46,115,227,118,186,1,43,172,37,95,110,123,221,161,116,86,215,11,203,50,203,44,164,241,
+218,253,22,169,251,29,222,129,233,157,247,191,236,133,65,208,45,172,227,171,202,196,99,61,213,211,196,176,88,83,
+203,98,77,159,41,141,102,104,208,79,11,169,74,167,214,38,166,163,179,158,176,105,47,179,216,218,44,246,113,75,
+107,95,152,224,73,123,30,180,85,247,219,90,2,124,173,198,39,192,137,195,143,9,124,164,248,113,46,67,211,78,
+203,49,186,53,68,163,234,64,176,148,182,43,182,141,212,180,81,193,171,4,240,122,2,166,111,59,188,128,131,247,
+11,32,145,8,17,239,130,132,90,29,162,54,100,113,7,187,136,106,241,134,167,10,250,154,53,125,40,174,221,253,
+80,8,17,55,74,187,140,56,141,123,221,85,141,108,238,68,51,35,216,82,193,54,147,77,119,87,137,199,253,61,
+248,127,139,237,245,122,83,60,234,55,63,238,236,121,99,145,254,99,193,80,189,214,85,166,235,209,20,162,24,182,
+7,112,222,120,37,208,243,123,140,212,190,32,179,125,31,80,35,55,94,103,210,138,4,216,224,247,133,124,227,85,
+57,109,220,155,66,190,15,100,7,108,228,115,45,113,133,109,224,53,5,76,247,108,212,199,130,109,217,66,239,207,
+110,82,249,247,37,24,208,149,122,126,238,33,62,154,121,165,141,40,1,104,101,192,51,65,62,224,174,245,106,45,
+168,207,194,210,144,211,122,12,4,104,161,126,70,254,5,190,251,176,217,228,20,54,116,163,222,68,163,52,41,174,
+147,122,36,228,235,34,50,18,145,114,21,25,207,167,223,195,79,3,31,50,59,251,243,57,194,14,185,134,24,120,
+54,18,59,155,85,173,202,72,203,179,26,59,33,32,57,139,55,144,31,255,204,35,160,5,225,114,121,23,53,84,
+28,39,82,180,193,107,83,61,119,119,215,167,236,168,2,9,163,26,229,79,143,142,96,233,12,179,212,242,217,97,
+104,158,207,78,246,161,225,219,49,225,219,115,185,5,3,251,87,116,53,111,223,67,61,48,131,152,130,198,161,172,
+157,248,218,154,230,24,153,24,246,117,161,118,54,203,218,122,83,136,209,227,56,70,36,134,198,66,72,167,86,9,
+140,242,140,80,128,17,214,5,63,84,1,124,81,201,17,204,233,162,136,34,20,229,73,204,115,201,167,44,202,93,
+219,210,14,67,114,187,146,27,52,66,40,47,42,91,18,85,64,162,196,98,105,133,76,172,27,145,26,62,168,160,
+250,255,19,119,221,205,141,227,200,254,255,253,20,60,237,157,87,122,7,106,68,37,219,210,112,166,54,94,220,80,
+123,155,85,174,89,136,164,76,158,153,134,84,180,206,247,217,223,175,209,32,68,210,178,119,230,197,9,34,98,163,
+209,104,116,55,26,32,152,33,172,171,186,5,194,250,115,37,61,2,242,141,6,130,245,50,64,4,116,214,234,208,
+237,233,174,60,212,54,2,66,188,103,118,252,91,180,88,189,238,232,203,143,113,56,130,100,98,231,134,33,196,46,
+24,174,75,215,33,2,59,115,19,251,239,127,79,7,208,86,200,15,186,87,98,77,220,132,127,252,230,106,16,1,
+38,20,57,147,41,74,45,172,201,3,186,23,202,93,169,222,244,152,114,38,103,36,74,228,80,82,207,16,211,100,
+142,69,134,76,157,218,51,36,54,249,19,81,32,95,167,246,208,190,139,230,129,196,2,195,69,11,114,101,242,132,
+55,218,10,200,124,99,5,252,184,62,111,5,224,211,70,235,234,203,38,165,47,82,95,220,175,5,115,215,80,168,
+17,28,153,161,27,155,161,155,52,94,100,42,234,115,114,110,246,37,233,234,127,205,5,157,165,196,233,19,86,163,
+101,125,178,102,152,172,217,203,180,154,172,25,77,214,146,200,11,89,73,19,205,216,192,138,175,50,191,123,132,96,
+202,203,89,137,65,87,51,248,207,192,30,195,3,201,37,111,233,67,42,106,246,146,243,251,248,57,114,4,133,68,
+64,219,188,34,71,50,148,99,37,154,165,91,92,56,175,49,129,83,177,248,188,232,102,202,97,155,170,153,60,3,
+130,0,138,33,239,74,154,213,244,181,70,218,36,140,90,109,137,140,97,163,76,70,101,228,249,124,231,65,248,148,
+253,173,66,168,33,3,164,145,1,45,86,75,21,171,13,30,179,26,84,92,125,216,215,213,80,199,239,55,212,210,
+23,5,15,117,99,36,211,204,140,228,35,49,233,71,91,200,200,91,244,161,67,77,146,0,216,217,67,43,196,255,
+229,173,189,132,254,179,71,131,129,165,204,142,192,183,87,152,121,150,92,150,89,188,89,147,239,50,183,135,253,137,
+197,47,146,35,212,81,3,165,182,218,191,198,131,229,174,223,13,64,105,150,154,13,81,153,213,133,62,241,85,63,
+149,9,60,164,29,145,62,194,179,204,101,218,33,219,226,151,110,208,194,151,14,11,218,183,133,60,216,99,96,74,
+231,182,108,182,34,58,103,132,254,151,90,25,228,156,158,93,56,152,128,48,163,186,16,75,53,12,224,220,244,149,
+110,65,81,35,245,91,248,123,245,9,162,167,169,177,38,197,138,60,202,34,23,137,48,31,136,119,73,175,193,228,
+201,48,104,91,213,97,243,89,37,154,73,176,41,137,34,230,162,78,254,24,144,153,28,60,125,163,197,240,198,76,
+93,240,87,153,35,16,109,213,57,189,68,70,233,26,255,63,46,115,168,253,111,37,10,97,105,101,166,55,80,165,
+219,231,205,113,61,94,118,209,81,226,54,59,236,112,201,72,223,83,182,253,207,248,77,79,57,229,41,152,185,159,
+98,88,182,183,8,22,20,164,128,164,64,14,59,21,225,152,194,5,16,65,216,171,133,195,90,153,85,45,125,163,
+218,202,79,13,108,47,46,182,10,139,68,229,44,79,57,111,78,65,72,138,125,67,82,128,55,36,164,54,248,226,
+203,129,53,8,135,227,237,112,252,231,193,189,98,242,88,116,232,24,38,242,188,77,81,160,52,31,185,211,89,250,
+179,41,200,237,79,171,180,61,98,206,176,138,81,222,88,71,204,151,88,70,85,130,249,36,139,99,146,10,85,191,
+63,81,113,239,233,214,189,51,173,123,220,250,101,21,161,172,107,142,180,27,247,106,141,95,113,74,171,237,80,147,
+100,98,57,215,161,51,145,142,229,88,32,143,51,176,134,127,30,155,152,141,191,63,84,81,199,25,90,131,173,51,
+185,103,0,79,35,191,122,38,235,76,191,86,154,170,151,85,140,242,28,135,99,237,158,173,106,61,51,213,27,61,
+43,76,235,105,150,6,245,36,187,216,196,1,210,233,139,79,153,239,171,172,204,52,48,28,112,220,192,55,9,219,
+40,192,225,109,106,99,96,129,62,99,252,171,234,238,147,88,217,72,225,122,157,207,94,188,216,237,118,253,221,168,
+159,21,183,47,134,131,193,224,5,205,6,42,89,26,225,228,187,191,174,226,96,111,209,143,237,101,177,21,209,203,
+32,54,159,22,181,254,185,41,233,203,87,85,116,103,99,60,66,250,249,253,49,90,140,110,30,140,216,141,111,127,
+37,184,249,73,232,53,160,26,64,202,105,109,221,202,220,30,104,242,164,231,170,20,217,174,137,8,213,224,78,190,
+57,149,15,149,180,87,169,203,223,106,24,114,197,226,242,86,17,196,146,190,46,215,86,43,40,110,147,20,183,193,
+87,137,63,171,71,227,219,83,116,106,13,247,241,41,58,182,128,108,21,12,237,197,104,60,200,247,55,86,110,79,
+172,6,38,220,5,210,89,187,16,93,179,248,72,173,126,176,118,112,160,29,178,109,80,172,98,64,12,35,223,15,
+82,67,224,125,29,111,210,26,7,241,49,180,6,30,107,4,88,32,38,164,58,208,67,86,34,1,63,82,122,64,
+246,211,163,100,5,3,45,64,15,168,2,126,196,252,240,248,17,242,99,197,245,54,252,200,89,218,161,137,188,214,
+68,194,143,37,61,160,68,122,2,198,207,94,188,209,37,238,180,253,115,16,139,143,97,255,28,160,91,94,239,96,
+207,236,92,165,96,88,128,51,214,1,86,208,232,66,119,215,247,187,14,18,93,134,208,253,221,221,191,254,245,241,
+197,21,116,29,105,192,255,50,175,30,30,241,42,212,103,99,22,244,196,161,173,237,94,111,95,111,251,185,162,243,
+172,187,117,161,250,14,61,193,242,254,68,7,224,189,5,222,91,198,123,203,120,107,91,244,31,100,113,126,124,49,
+70,254,63,120,129,113,128,110,236,137,61,219,120,255,32,27,15,48,143,119,100,227,181,180,132,56,16,253,216,198,
+163,50,242,124,62,217,120,148,125,96,229,207,108,224,119,245,96,81,224,91,84,108,24,5,161,177,253,106,139,61,
+94,147,149,0,72,38,130,219,233,204,91,134,161,132,97,104,86,26,146,150,4,228,80,230,117,19,112,164,98,122,
+101,228,118,245,187,21,42,205,143,138,245,225,2,198,53,246,141,189,176,155,242,2,228,232,201,50,80,68,158,209,
+194,4,13,86,166,28,77,1,132,181,76,182,39,3,75,25,79,148,135,200,0,31,146,90,22,129,188,155,107,71,
+194,169,58,207,160,225,249,234,148,199,213,31,234,88,97,96,104,197,148,153,181,110,218,223,191,145,251,168,172,173,
+120,57,107,214,57,243,225,188,15,199,222,229,104,53,233,168,210,168,123,80,117,31,110,232,10,241,174,67,212,132,
+192,46,217,167,69,231,217,20,97,116,142,3,162,161,175,61,60,22,218,48,171,76,234,213,251,153,212,161,47,188,
+218,234,105,208,48,172,179,71,199,54,35,253,21,15,99,197,209,218,131,183,76,211,83,189,130,234,213,119,92,81,
+2,231,75,239,200,244,213,54,36,167,108,41,5,214,100,101,14,99,127,125,22,137,85,84,148,107,246,225,144,225,
+22,156,172,161,180,110,158,253,194,251,116,100,59,201,83,186,135,116,204,253,16,233,239,174,31,118,44,218,91,163,
+141,234,242,61,170,171,10,193,83,21,184,204,83,114,219,200,117,35,176,53,54,101,98,145,220,207,247,246,180,163,
+29,201,138,60,110,64,82,28,70,56,164,56,30,1,2,144,162,65,37,175,51,142,21,252,144,244,144,194,227,88,
+72,203,3,174,186,118,241,32,78,46,73,64,86,195,100,214,7,25,228,62,231,199,148,111,6,173,202,247,68,12,
+88,62,121,39,86,36,66,130,134,168,240,155,78,47,112,136,178,248,191,148,185,40,213,234,192,156,8,43,220,87,
+133,106,217,172,176,249,252,239,201,119,140,21,54,131,146,174,98,202,146,186,22,187,89,87,210,133,59,36,15,99,
+17,96,157,236,22,25,66,18,19,227,236,66,176,5,63,104,192,167,250,36,159,231,13,181,254,88,11,143,204,120,
+211,16,128,155,49,4,120,172,17,104,93,221,101,224,199,12,63,190,49,74,150,198,0,149,22,18,170,77,18,133,
+65,253,130,191,58,248,54,162,33,195,68,113,68,129,142,166,128,252,29,29,184,85,245,68,150,181,125,118,5,214,
+225,44,192,77,243,18,205,203,83,243,146,155,151,55,144,233,141,33,218,52,164,121,185,166,77,173,148,61,106,109,
+17,94,146,8,87,37,72,134,151,149,12,47,251,42,77,9,162,74,4,221,190,159,8,218,248,194,103,17,164,64,
+181,100,144,124,39,25,116,249,88,8,197,239,82,113,56,120,92,209,251,77,119,2,189,40,144,6,197,159,191,251,
+242,239,238,175,47,97,21,91,116,106,15,117,93,152,237,195,142,165,204,104,247,57,43,218,210,70,184,171,108,240,
+209,96,98,93,15,58,22,145,15,245,118,246,226,138,172,64,50,35,17,118,28,138,116,94,189,44,233,197,188,87,
+47,95,232,39,173,49,45,56,204,147,65,255,202,114,250,215,225,104,242,214,185,236,95,147,81,127,77,73,195,254,
+24,63,244,28,225,7,173,244,47,145,231,92,245,71,182,142,218,14,234,169,2,118,85,101,20,218,163,201,125,50,
+28,246,167,214,116,220,191,10,9,204,91,2,234,140,81,97,130,242,147,254,212,158,170,95,103,130,74,3,251,186,
+127,109,87,81,4,46,109,4,199,244,8,109,170,125,159,56,163,75,128,27,58,4,125,56,234,95,198,54,126,40,
+111,130,248,149,138,35,159,227,200,191,142,145,56,182,175,166,125,39,28,78,251,87,247,137,61,118,0,122,58,160,
+162,87,4,234,26,160,208,217,209,125,114,57,5,74,83,84,125,107,59,4,101,96,19,238,54,161,114,77,191,104,
+134,81,155,198,232,250,53,186,252,22,184,89,232,57,22,139,84,151,67,131,62,45,10,233,97,115,167,70,212,23,
+106,180,63,180,209,9,123,64,117,65,106,100,140,0,132,2,72,117,128,61,250,15,130,32,123,138,28,122,18,98,
+128,0,34,95,245,39,182,3,92,17,152,218,151,253,49,209,96,172,2,4,10,13,34,115,104,77,144,61,6,65,
+29,34,193,149,34,116,76,144,39,170,212,91,123,76,45,80,239,56,0,2,1,58,232,133,240,80,255,142,21,250,
+84,123,132,48,126,9,152,234,28,34,99,64,2,110,22,194,220,81,64,194,255,43,170,139,166,169,198,37,254,79,
+81,119,138,212,75,252,31,2,45,74,161,167,163,40,51,164,142,2,95,116,28,100,68,161,161,26,74,10,220,39,
+87,224,12,140,214,214,30,17,35,14,241,179,85,163,103,83,16,169,35,21,30,247,71,91,29,28,110,121,120,17,
+160,42,247,29,240,53,49,52,30,152,31,175,172,15,44,235,37,38,91,53,37,10,233,5,246,242,64,165,144,250,
+234,215,230,210,171,225,176,27,88,244,234,41,30,228,181,163,167,190,212,113,80,169,224,144,31,239,190,22,32,161,
+239,212,116,244,61,12,197,247,242,4,230,109,79,154,17,64,188,241,96,124,96,90,2,146,114,36,191,213,115,114,
+231,163,58,121,126,211,54,97,183,225,2,102,13,4,201,63,208,72,132,30,122,37,83,243,35,246,131,145,175,41,
+109,251,154,214,207,219,51,198,72,105,58,41,55,57,132,60,89,233,86,14,171,186,115,114,111,127,141,199,26,1,
+65,129,128,2,159,163,81,118,120,151,198,225,93,24,119,55,173,129,10,165,30,37,43,26,87,187,188,91,142,238,
+146,23,65,105,219,145,93,214,29,221,103,243,141,163,59,211,139,32,245,12,212,210,39,109,57,190,147,103,44,26,
+234,3,37,73,147,68,123,81,209,98,124,99,238,222,220,184,175,54,164,113,250,145,111,52,53,29,89,221,188,244,
+42,77,189,49,134,78,238,42,5,230,137,13,57,8,195,110,94,25,58,9,12,157,205,141,27,102,8,229,176,5,
+168,240,10,13,77,170,134,124,110,200,185,60,211,208,234,92,67,74,197,174,184,33,159,26,146,186,161,130,26,90,
+113,67,207,90,84,6,126,208,128,15,68,217,162,42,21,127,101,79,213,42,26,181,208,234,25,59,140,94,238,181,
+232,135,166,107,73,178,149,142,218,16,43,150,118,34,247,150,164,23,250,107,14,34,118,15,101,239,12,128,43,49,
+171,110,68,14,86,197,99,141,128,193,53,1,174,201,169,135,9,247,48,169,217,116,115,170,83,162,142,160,64,246,
+184,114,209,168,92,112,229,76,87,142,153,255,185,245,252,194,25,211,210,223,115,55,96,33,17,69,160,159,54,13,
+115,17,10,71,108,132,167,76,195,63,167,34,100,8,34,6,67,167,40,8,47,243,197,104,136,202,43,84,158,232,
+202,5,85,46,80,217,167,202,124,207,6,85,94,233,202,178,170,76,51,106,195,111,45,198,167,215,35,115,224,159,
+159,248,52,39,252,49,225,130,69,142,237,174,102,161,85,187,80,65,133,184,123,52,21,55,109,168,65,163,130,60,
+15,181,104,23,50,80,105,2,19,208,141,54,130,159,3,78,144,201,8,158,83,97,90,63,170,103,246,124,99,212,
+82,219,114,14,91,75,220,150,72,207,101,115,91,99,189,24,178,72,135,4,202,210,110,135,157,29,29,177,94,92,
+66,154,61,181,238,93,70,103,164,114,123,21,104,36,235,243,2,117,237,102,243,166,80,157,146,84,101,207,18,208,
+251,223,148,170,231,165,233,234,121,18,174,252,54,9,157,75,144,240,255,137,90,163,97,141,90,192,228,255,156,90,
+203,167,119,227,220,223,241,198,155,151,129,177,153,120,63,21,134,120,161,44,255,161,173,138,233,141,64,167,210,192,
+91,7,62,239,180,233,29,13,28,149,66,124,84,231,80,47,164,99,58,29,17,45,174,110,122,70,133,45,18,95,
+228,62,29,232,95,212,142,183,248,44,179,244,240,109,0,136,188,160,228,139,166,101,78,7,23,194,87,105,165,49,
+61,58,248,204,135,237,104,165,242,239,110,225,82,255,122,68,100,119,69,11,249,16,63,148,194,70,144,135,222,41,
+223,233,90,105,18,229,18,162,237,192,206,185,17,111,107,27,65,7,44,80,155,21,194,249,149,61,7,202,176,136,
+210,59,86,5,180,250,50,238,244,131,93,122,116,124,183,145,184,175,188,236,185,125,69,214,225,226,195,213,21,253,
+189,121,222,33,196,13,18,36,99,76,209,151,108,67,106,34,8,210,150,153,138,98,208,78,167,220,123,152,162,70,
+75,105,194,112,88,176,198,210,129,0,1,230,238,192,184,220,3,81,242,3,92,247,111,248,12,64,232,154,2,18,
+39,5,68,162,245,184,33,143,187,71,58,136,221,211,30,187,167,103,30,248,220,115,137,217,4,143,9,33,176,238,
+231,146,56,233,171,204,167,195,103,21,199,36,52,123,242,139,41,169,178,164,95,177,162,187,1,43,146,150,226,100,
+195,147,72,31,170,244,43,78,55,204,137,140,209,105,198,37,252,90,230,210,45,230,196,54,27,190,163,97,249,218,
+116,137,117,232,172,43,1,70,41,63,76,187,213,98,121,35,28,252,85,126,84,138,241,49,27,214,122,68,143,215,
+154,245,132,124,45,13,136,58,55,162,33,98,35,20,198,52,151,194,161,168,161,94,111,38,21,192,74,127,198,231,
+164,193,134,171,50,169,123,90,25,202,51,165,36,151,50,202,141,199,153,66,66,171,57,122,26,89,113,26,206,182,
+158,122,227,55,206,26,107,39,61,253,20,181,25,42,36,153,174,49,253,120,244,19,170,174,96,150,119,118,37,60,
+24,157,63,250,153,183,33,220,212,247,45,8,112,63,204,202,245,31,59,47,124,89,134,59,218,2,57,73,131,13,
+230,43,59,198,201,79,109,146,115,36,183,220,217,39,63,247,48,24,245,4,87,162,168,15,3,52,245,187,127,253,
+199,215,95,233,171,139,176,28,235,170,155,73,100,234,207,58,56,138,56,139,213,107,222,157,7,88,44,178,60,164,
+158,117,50,211,187,59,72,240,226,160,186,188,157,83,104,235,42,88,252,138,249,78,239,59,160,39,94,72,251,31,
+141,15,9,146,248,164,119,141,69,231,47,233,86,198,48,26,169,170,149,4,101,41,73,32,114,109,113,168,188,72,
+15,219,190,198,139,4,28,43,118,141,220,76,93,193,69,159,176,239,142,21,117,169,143,19,225,233,208,64,145,29,
+156,243,12,132,20,235,42,0,216,242,234,7,252,172,67,230,58,170,3,29,32,211,7,100,163,217,161,31,137,59,
+252,222,137,45,126,183,250,205,163,78,135,34,112,171,233,86,193,193,104,82,22,62,1,228,80,19,96,92,1,244,
+9,162,175,142,84,33,4,51,87,38,20,72,5,95,191,208,110,66,148,135,100,153,197,8,150,245,116,254,170,49,
+2,244,208,25,142,142,210,73,123,4,245,39,6,17,194,47,99,74,52,99,76,67,89,112,223,57,216,196,213,251,
+77,92,121,87,6,193,189,56,84,193,3,183,65,163,209,123,98,4,144,146,103,41,152,190,172,15,192,25,250,27,
+115,246,99,24,143,31,191,148,149,241,248,49,94,59,132,25,45,177,127,217,143,0,24,232,245,142,24,155,223,85,
+183,26,176,19,85,229,223,185,200,32,71,61,168,120,46,127,235,34,3,249,188,129,69,122,218,140,32,7,158,195,
+40,110,97,20,43,140,124,70,201,7,78,173,54,199,66,149,80,99,172,218,141,9,175,242,92,25,30,112,23,185,
+92,136,134,244,108,57,26,121,206,230,130,24,240,115,229,144,236,170,76,93,74,238,207,149,66,178,171,50,69,108,
+40,82,231,20,14,61,59,74,94,139,38,222,35,154,52,91,158,8,85,130,121,201,69,174,240,8,193,195,185,66,
+135,170,208,129,11,113,252,141,218,11,124,186,60,231,187,205,226,194,51,29,108,179,41,152,243,150,174,31,58,137,
+205,16,74,34,14,100,81,201,216,16,73,110,123,11,209,231,27,43,161,38,196,20,82,183,18,131,219,39,197,96,
+150,26,217,183,237,213,45,210,238,238,153,58,1,189,15,12,105,105,196,58,212,165,105,186,166,159,160,21,124,151,
+42,254,24,44,255,145,121,119,1,84,53,149,204,82,85,214,221,168,112,150,7,169,155,35,104,144,113,19,138,113,
+51,238,242,1,189,252,11,249,187,192,179,220,77,72,125,131,92,156,221,118,59,165,2,222,7,45,253,3,89,33,
+232,142,95,139,245,26,49,208,215,224,211,255,244,239,95,255,227,243,207,32,197,77,71,128,117,111,246,100,249,175,
+191,249,252,171,139,11,173,195,62,58,118,244,152,209,153,221,8,67,246,240,145,166,249,51,244,83,111,83,91,81,
+122,162,138,181,163,42,129,34,41,150,209,147,96,84,217,88,123,119,135,254,158,87,153,80,86,193,90,70,49,134,
+121,14,164,117,141,59,170,193,123,223,166,128,217,239,105,239,197,55,183,188,131,238,84,164,110,37,226,94,145,17,
+179,144,122,49,194,167,121,113,20,176,218,8,218,191,223,70,208,27,95,44,79,199,59,137,24,123,172,1,215,178,
+32,117,111,44,16,68,62,143,3,10,126,114,248,139,223,237,200,60,239,208,139,32,31,124,240,242,5,223,17,247,
+234,3,11,127,120,187,196,82,103,50,212,25,202,23,30,172,240,87,31,252,135,152,241,61,49,98,38,87,224,152,
+227,50,131,225,31,221,131,98,51,189,45,139,148,185,14,242,23,57,7,85,84,193,156,97,196,34,191,74,226,27,
+10,63,12,38,193,101,176,124,104,193,182,237,245,14,37,210,53,208,157,89,184,253,59,92,39,241,145,206,181,219,
+124,46,107,134,205,135,185,189,11,150,119,209,218,38,44,9,149,192,150,62,124,208,200,28,12,254,48,183,147,236,
+222,94,203,165,202,153,141,231,118,86,143,213,130,202,199,187,146,73,20,31,102,155,200,46,101,90,218,244,38,197,
+10,106,25,130,55,177,55,145,176,65,174,56,176,57,65,124,2,76,238,190,148,222,63,84,148,94,105,21,255,8,
+110,179,192,250,254,47,226,219,12,142,115,184,136,130,120,27,96,193,38,173,175,130,77,32,62,46,34,25,139,175,
+144,99,253,3,240,69,173,145,206,199,4,218,82,199,27,172,207,147,236,159,17,214,60,21,184,42,193,196,255,161,
+20,135,232,16,168,70,157,135,101,230,31,142,9,70,61,74,65,248,58,173,162,52,68,75,235,135,176,56,114,10,
+242,153,252,58,167,26,147,117,150,235,145,115,242,253,131,92,46,139,217,14,5,130,238,98,77,183,69,98,113,211,
+32,185,31,120,89,193,47,5,111,82,212,167,54,45,63,91,99,73,50,255,173,2,15,161,35,194,161,8,71,34,
+28,139,112,34,194,233,17,227,192,195,104,208,82,41,187,102,39,228,177,129,122,187,33,83,110,41,48,107,32,234,
+143,117,32,32,29,208,120,240,104,181,117,135,73,83,202,36,167,15,51,31,91,60,144,64,116,150,185,244,2,241,
+143,47,190,68,216,198,171,22,234,251,22,95,6,105,156,9,36,73,47,19,159,42,33,36,75,188,33,179,12,184,
+121,11,89,148,177,41,162,160,192,208,239,132,1,53,63,245,207,9,146,135,50,145,113,92,235,243,213,224,15,15,
+229,6,88,111,242,90,234,229,228,15,102,40,121,224,204,173,155,213,193,180,57,86,35,196,104,177,173,124,185,179,
+165,190,141,149,160,29,245,253,209,118,127,56,65,155,4,27,99,140,40,197,212,91,69,71,69,191,40,245,105,166,
+153,249,122,150,59,144,24,203,188,12,102,85,0,175,215,1,122,42,162,52,167,109,245,124,77,7,117,114,129,230,
+177,44,21,4,88,66,212,215,105,107,64,154,30,242,92,61,195,173,45,14,53,140,93,221,173,57,168,90,231,230,
+184,31,234,86,91,186,11,97,150,102,169,193,111,161,132,25,71,110,116,172,8,160,250,170,8,40,149,224,245,112,
+195,221,152,236,129,4,40,47,152,113,173,249,233,24,146,166,141,106,137,215,238,245,204,40,129,142,229,198,103,74,
+0,173,32,127,75,82,43,71,88,18,212,205,25,185,207,117,38,56,45,226,197,18,75,211,80,250,217,142,107,231,
+69,118,11,28,203,227,83,163,59,155,85,216,170,205,45,187,132,146,180,117,135,79,121,104,180,153,167,37,0,99,
+161,123,143,190,122,225,217,222,19,81,87,81,16,251,115,141,189,157,241,37,173,246,48,223,215,80,96,16,181,105,
+120,14,24,83,197,212,89,69,16,168,155,60,206,164,175,113,123,134,254,196,47,102,106,151,155,4,236,112,48,7,
+214,227,168,4,21,214,96,233,101,12,165,255,118,147,193,22,240,99,58,30,241,72,202,136,176,16,252,145,72,193,
+51,191,98,172,7,213,79,244,237,120,134,213,248,136,252,241,148,0,17,188,137,5,180,233,230,72,173,107,5,71,
+61,60,199,169,102,42,20,129,226,249,106,76,31,212,204,153,49,51,160,43,94,16,42,1,101,230,206,227,172,163,
+62,101,55,115,230,90,131,94,123,114,36,87,12,10,197,75,91,133,206,131,51,217,239,1,114,118,30,177,119,0,
+96,230,95,145,197,102,254,29,225,158,42,81,70,93,103,11,89,60,195,40,146,32,242,171,12,125,200,240,33,74,
+110,5,246,180,197,54,242,131,76,240,123,123,66,110,252,40,19,209,170,144,73,32,130,100,25,248,34,83,111,51,
+26,102,80,44,208,150,137,124,47,53,129,100,112,24,227,61,107,58,150,63,141,73,193,222,201,27,3,81,241,109,
+219,252,97,19,197,220,162,109,239,103,214,96,222,74,59,152,52,190,70,219,68,203,187,0,110,208,102,244,112,138,
+2,111,5,208,169,199,15,38,158,203,148,114,79,145,131,137,68,41,102,225,125,150,37,85,10,187,95,237,50,149,
+185,77,230,173,183,78,33,84,102,22,196,203,62,74,48,102,92,44,43,192,169,50,54,181,160,212,194,192,183,233,
+235,184,85,154,190,64,217,230,201,211,78,37,13,71,188,222,46,92,72,181,94,169,210,73,16,130,1,49,203,26,
+41,44,84,244,128,88,56,182,243,56,143,25,203,250,112,181,90,213,50,117,106,113,187,236,78,112,200,98,68,231,
+242,167,214,11,171,63,233,61,6,193,226,21,240,241,247,195,1,254,212,138,156,207,123,62,153,91,15,252,118,54,
+157,155,5,82,58,76,199,41,52,209,231,198,172,45,100,105,40,64,187,255,106,136,171,132,112,19,48,195,152,148,
+40,37,126,54,163,35,177,226,168,229,150,65,30,201,255,172,238,58,151,28,87,149,240,255,251,20,186,121,85,101,
+115,4,10,14,186,249,37,110,242,254,152,224,9,85,227,77,222,217,164,210,187,31,62,104,160,133,89,99,109,157,
+60,199,59,226,235,230,163,65,24,16,221,104,92,2,47,174,38,251,28,228,222,103,77,118,197,96,48,48,22,121,
+75,99,129,55,57,150,112,219,99,17,85,34,134,105,236,136,241,184,150,65,64,213,29,133,11,95,25,252,146,200,
+33,163,160,197,17,147,17,162,101,38,218,197,172,131,116,79,27,133,13,123,25,240,203,2,104,16,32,248,77,144,
+139,133,161,245,148,5,193,163,118,162,53,84,162,83,237,187,253,193,229,6,78,4,36,33,125,171,60,81,117,122,
+65,75,90,181,218,0,75,171,230,232,150,82,16,223,210,168,218,154,44,21,101,71,144,205,240,101,105,255,20,153,
+170,0,200,0,72,13,216,197,220,147,190,175,131,185,220,110,244,127,163,96,7,47,6,231,238,127,62,188,218,2,
+67,24,220,119,5,93,141,194,31,189,144,86,83,167,73,205,107,49,165,38,82,106,156,82,51,138,195,178,117,211,
+173,175,214,225,147,7,151,184,41,78,210,19,102,155,129,171,99,216,158,228,0,48,85,7,162,117,209,218,132,135,
+251,0,88,86,28,87,78,112,29,76,161,59,239,203,133,19,202,79,17,72,140,2,245,244,16,18,163,176,115,201,
+116,42,17,214,69,229,86,98,152,128,128,237,254,47,43,221,175,118,47,189,0,73,72,20,33,100,47,16,116,47,
+2,125,255,2,69,221,76,40,76,18,18,89,57,72,121,146,186,115,216,198,209,54,14,233,8,89,251,108,4,248,
+60,146,120,184,15,110,64,34,88,255,225,97,20,31,109,93,195,92,171,33,109,231,218,152,73,48,18,128,21,165,
+137,25,103,73,8,81,30,106,9,241,247,1,108,181,98,108,72,0,94,187,188,164,214,185,156,196,197,60,151,3,
+187,222,202,81,216,171,101,53,193,43,202,114,175,123,242,66,224,223,193,167,145,201,63,123,12,254,106,27,254,202,
+134,126,245,194,139,120,201,80,46,18,232,231,178,44,48,130,242,60,54,173,5,88,41,120,152,150,17,4,255,55,
+194,193,99,198,232,255,144,32,172,44,156,228,191,145,4,121,70,97,151,97,75,90,159,197,203,53,97,31,183,150,
+232,201,126,189,142,87,151,46,173,192,174,129,177,106,77,161,199,83,48,6,70,49,137,47,178,131,135,135,220,211,
+3,68,110,131,168,143,84,152,104,20,60,114,201,114,233,231,132,55,104,105,26,224,142,122,102,120,179,215,142,67,
+169,224,83,209,153,181,239,64,222,189,43,75,186,223,254,70,235,205,188,189,93,205,104,200,10,193,17,11,45,237,
+40,120,56,225,96,195,172,12,180,181,208,40,38,167,243,6,74,249,93,47,176,90,81,208,196,51,72,74,15,130,
+160,69,69,198,138,113,177,215,251,247,31,241,157,141,245,204,102,133,147,142,194,70,113,14,250,151,255,22,2,106,
+13,34,133,10,80,99,33,159,174,118,194,106,9,201,180,64,69,51,47,146,107,203,236,197,202,230,8,250,181,5,
+86,22,137,14,234,13,46,189,181,105,166,240,217,78,11,33,77,115,64,56,41,50,208,190,6,254,240,201,243,209,
+23,193,206,180,199,42,152,41,97,120,56,211,22,115,76,41,212,73,33,114,34,127,255,110,8,59,111,52,207,59,
+38,53,165,186,118,170,52,17,165,181,173,10,105,178,173,60,65,136,154,138,20,68,209,153,26,251,96,67,160,95,
+156,201,233,206,16,22,220,170,169,11,213,52,180,226,166,145,36,206,89,150,190,0,182,99,50,76,200,152,192,43,
+227,232,217,227,241,193,252,190,216,34,217,22,221,166,80,109,155,181,199,87,88,205,169,176,210,228,181,212,159,92,
+1,20,241,76,204,247,140,53,218,72,34,102,152,76,159,9,243,125,196,186,251,255,142,98,101,118,47,47,39,111,
+214,5,125,206,146,191,211,110,35,116,128,121,86,43,77,92,87,231,136,113,15,103,18,75,52,116,163,155,163,57,
+75,124,143,53,199,60,102,85,105,86,133,219,120,190,45,246,183,179,120,97,169,82,29,62,103,121,63,239,159,48,
+22,205,166,110,112,130,224,124,223,160,238,124,57,49,239,206,249,86,110,103,48,215,141,182,118,85,108,154,172,193,
+179,104,101,133,227,39,154,91,173,243,253,173,158,67,220,172,140,193,170,173,47,185,123,115,108,86,104,139,213,166,
+184,192,226,110,78,11,235,214,221,100,239,28,31,68,243,212,241,32,154,31,137,20,126,102,141,68,170,160,79,198,
+110,157,251,98,214,170,192,79,230,219,60,243,166,109,138,110,141,255,207,177,250,227,206,9,98,209,78,84,54,41,
+149,205,68,165,75,169,116,163,192,10,201,109,36,99,149,4,164,245,8,214,95,4,54,1,180,136,30,13,28,20,
+30,118,123,135,208,227,172,160,236,159,66,126,122,232,230,202,244,200,237,121,177,176,155,80,119,42,73,14,152,242,
+76,51,72,145,202,0,216,103,168,167,37,172,82,250,64,201,252,122,106,62,36,113,5,184,122,23,213,86,196,234,
+236,9,215,120,150,104,81,141,107,218,83,182,8,137,143,7,230,180,19,107,91,250,212,95,173,24,219,211,61,83,
+151,66,170,132,254,138,233,127,58,114,250,4,187,81,53,42,59,156,86,218,189,156,184,61,53,2,169,127,3,210,
+68,216,120,225,113,127,120,132,135,116,34,238,32,246,7,147,98,55,155,23,224,249,87,127,151,208,122,122,109,185,
+71,12,161,110,29,191,47,44,42,213,194,68,126,222,137,122,60,32,254,149,228,67,81,87,200,174,214,3,168,31,
+140,226,12,101,73,156,102,245,210,230,57,177,98,213,148,155,38,203,136,81,51,207,200,55,158,179,148,52,149,230,
+57,253,12,154,165,196,216,150,39,12,67,90,150,144,38,185,60,167,159,219,242,156,184,225,121,70,62,195,103,57,
+105,133,157,33,100,11,235,44,33,166,180,238,26,63,187,151,23,25,74,159,51,188,118,31,30,143,154,145,55,65,
+233,231,95,109,148,254,103,137,127,248,52,38,100,185,208,23,107,13,203,10,10,221,169,66,218,11,17,211,146,93,
+145,102,130,61,173,215,51,151,52,105,164,252,41,139,224,253,40,23,83,189,51,10,36,243,109,20,55,144,212,102,
+213,250,83,165,218,6,66,5,227,229,229,77,227,9,211,181,141,120,127,25,141,178,196,142,32,123,116,34,212,187,
+194,228,93,123,183,153,58,170,136,42,110,129,146,182,39,141,43,196,130,199,129,33,56,243,178,127,167,123,185,17,
+45,226,85,209,130,63,11,47,240,18,173,133,253,11,199,139,116,60,16,21,209,127,107,9,73,54,94,238,15,207,
+60,191,70,250,133,187,184,159,46,36,115,123,243,124,173,61,158,215,251,47,143,120,179,107,179,168,22,66,45,100,
+201,179,220,62,91,178,173,144,237,113,114,75,16,11,148,170,147,198,127,216,50,247,122,174,94,62,153,23,245,14,
+103,136,173,198,40,232,0,185,238,127,207,143,20,48,87,72,12,51,61,33,111,246,248,126,73,209,28,9,161,222,
+105,214,240,4,129,204,45,39,10,61,48,37,98,152,184,35,165,63,221,44,237,211,155,153,206,111,111,123,125,84,
+84,217,219,77,46,18,146,249,101,63,221,144,211,251,222,55,47,210,249,245,128,162,202,62,218,97,236,19,155,251,
+255,123,81,149,190,169,40,76,96,112,150,234,183,58,157,248,39,123,227,124,236,173,203,177,103,126,32,50,217,92,
+198,29,153,85,132,198,34,55,53,9,233,75,167,224,4,86,120,154,125,110,43,184,111,133,253,243,207,168,11,10,
+252,215,103,26,112,124,87,40,11,211,193,30,95,33,242,72,7,226,222,225,133,236,251,254,27,179,165,28,41,75,
+152,95,230,91,103,252,135,179,89,159,123,52,241,34,199,194,22,62,84,127,28,190,206,60,190,127,157,148,90,225,
+248,143,31,146,205,70,216,80,64,26,206,13,190,252,90,220,20,191,141,172,238,124,239,244,148,108,107,130,207,124,
+224,25,120,18,74,33,136,235,233,209,236,211,62,60,31,174,179,118,232,117,3,117,39,92,70,221,137,158,238,152,
+157,136,219,64,232,6,115,178,46,27,159,111,43,5,230,93,19,31,140,9,253,74,187,96,240,35,170,118,50,227,
+98,94,54,31,104,155,201,179,170,228,85,31,185,168,242,85,124,247,252,202,252,137,137,165,121,102,33,191,96,23,
+226,128,54,176,140,25,127,125,139,159,168,146,53,170,232,136,195,80,138,33,187,16,237,177,79,64,89,67,31,48,
+218,228,204,101,150,153,182,106,55,11,89,87,11,213,116,11,177,41,147,213,63,28,227,170,70,182,240,154,67,251,
+178,250,164,59,226,116,231,156,11,78,144,175,24,75,125,240,215,217,215,96,191,121,207,168,158,52,244,80,124,81,
+63,250,218,119,55,193,54,255,222,19,1,30,213,127,56,115,136,109,190,57,240,12,155,196,175,252,38,83,53,126,
+136,49,4,92,63,240,0,18,155,151,185,81,226,227,149,46,232,213,125,152,223,135,48,101,147,76,199,237,23,234,
+232,39,103,63,244,229,20,249,148,25,52,48,109,250,176,209,177,101,41,81,99,210,12,178,120,34,255,102,30,97,
+26,103,183,37,215,105,103,27,43,132,85,161,139,121,165,143,78,78,119,54,18,123,191,72,87,85,164,119,185,223,
+197,108,106,173,206,120,71,120,33,87,159,191,161,140,85,91,172,91,184,8,46,45,162,157,93,139,6,78,130,74,
+127,100,182,144,200,21,65,37,253,128,14,9,42,135,182,237,226,146,242,219,140,40,32,179,69,100,198,191,221,214,
+133,193,99,45,20,45,175,194,128,195,38,184,40,110,30,74,227,63,14,251,219,199,171,226,5,130,165,40,228,117,
+213,233,29,153,114,16,135,219,221,214,14,16,120,243,134,11,208,91,218,8,61,8,195,251,144,79,131,244,176,255,
+104,47,72,247,242,136,62,168,39,2,218,0,39,35,216,32,224,175,87,24,144,152,6,126,65,5,177,89,82,242,
+80,47,147,98,194,245,154,11,145,10,228,80,168,43,155,59,196,107,3,33,165,179,225,57,80,200,133,232,64,231,
+194,168,25,168,158,188,193,98,8,8,181,19,41,198,239,191,224,97,40,22,25,83,221,64,86,170,49,253,224,233,
+158,221,190,38,186,123,81,12,37,116,47,236,22,201,50,213,186,50,101,126,122,98,60,245,41,79,237,120,234,52,
+79,91,119,134,103,87,171,9,85,162,243,249,190,167,70,82,191,180,182,35,142,43,218,23,57,226,85,119,223,61,
+232,163,164,230,10,167,223,112,65,239,191,211,39,146,113,194,145,94,124,103,5,38,131,209,211,28,56,80,248,183,
+223,124,15,242,210,81,83,178,8,4,0
+};
diff --git a/lib/ESPDASH/src/dash_webpage.h b/lib/ESPDASH/src/dash_webpage.h
new file mode 100644
index 00000000..139825be
--- /dev/null
+++ b/lib/ESPDASH/src/dash_webpage.h
@@ -0,0 +1,8 @@
+#ifndef dash_webpage_h
+#define dash_webpage_h
+
+#include
+
+extern const uint8_t DASH_HTML[90101];
+
+#endif
diff --git a/lib/ESPDASH/src/vector.h b/lib/ESPDASH/src/vector.h
new file mode 100644
index 00000000..1c55e7f2
--- /dev/null
+++ b/lib/ESPDASH/src/vector.h
@@ -0,0 +1,243 @@
+#ifndef VectorClass
+#define VectorClass
+
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#define SWAP(type, a, b) type tmp ## a = a; a = b; b = tmp ## a;
+
+// This class implements missing vector from STL
+template class Vector
+{
+ VectorType *begin;
+ VectorType *storage;
+ int head;
+
+public:
+ VectorType OB;
+
+ // We can save a few re-sizings if we know how large the array is likely to grow to be
+ Vector(int initialSize = 0)
+ {
+ begin = new VectorType[initialSize]; //points to the beginning of the new array
+ head = initialSize - 1;
+ storage = begin + initialSize; //points to the element one outside of the array (such that end - begin = capacity)
+ }
+
+ Vector(Vector &obj)
+ {
+ begin = new VectorType[0]; // Points to the beginning of the new array, it's zero but this line keeps malloc from seg faulting should we delete begin before resizing it
+ head = -1;
+ storage = begin; //points to the element one outside of the array (such that end - begin = capacity)
+
+ *this = obj;
+ }
+
+ // If there's anything in the vector then delete the array, if there's no array then doing will will cause seg faults
+ virtual ~Vector() { delete[] begin; }
+
+ Vector &operator=(Vector &obj)
+ {
+ // Reallocate the underlying buffer to the same size as the
+ Resize(obj.Size());
+
+ for(int i = 0; i < obj.Size(); i++)
+ (*this)[i] = obj[i];
+
+ head = obj.head;
+
+ return *this;
+ }
+
+ // Swaps the underlying array and characteristics of this vector with another of the same type, very quickly
+ void Swap(Vector &obj)
+ {
+ SWAP(int, head, obj.head);
+ SWAP(VectorType*, begin, obj.begin);
+ SWAP(VectorType*, storage, obj.storage);
+ }
+
+ // Checks the entire Vector to see whether a matching item exists. Bear in mind that the VectorType might need to implement
+ // equality operator (operator==) for this to work properly.
+ bool Contains(VectorType element)
+ {
+ for(int i = 0; i < Size(); i++)
+ if(operator [](i) == element)
+ return true;
+
+ return false;
+ }
+
+ int Find(VectorType element)
+ {
+ for(int i = 0; i < Size(); i++)
+ if(operator [](i) == element)
+ return i;
+
+ return -1;
+ }
+
+ void PushBack(VectorType element) { PushBack(&element, 1); }
+
+ void PushBack(const VectorType *elements, int len)
+ {
+ // If the length plus this's size is greater than the capacity, reallocate to that size.
+ if(len + Size() > Capacity())
+ ReAllocate(MAX(Size() + len, Size() * 2));
+
+ int append = MIN(storage - begin - head - 1, len), prepend = len - append;
+
+ // memcpy the data starting at the head all the way up to the last element *(storage - 1)
+ memcpy((begin + head + 1), elements, sizeof(VectorType) * append);
+
+ // If there's still data to copy memcpy whatever remains, starting at the first element *(begin) until the end of data. The first step will have ensured
+ // that we don't crash into the tail during this process.
+ memcpy(begin,(elements + append), sizeof(VectorType) * prepend);
+
+ // Re-recalculate head and size.
+ head += len;
+ }
+
+ void Erase(unsigned int position) { Erase(position, position + 1); }
+
+ // Erase an arbitrary section of the vector from first up to last minus one. Like the stl counterpart, this is pretty labour intensive so go easy on it.
+ void Erase(int first, int last)
+ {
+ // For this we'll set the value of the array at first to the value of the array at last plus one. We'll do that all the way up to toIndex
+ for(int i = 0; i < (Size() - first); i++)
+ {
+ // If by trying to fill in the next element with the ones ahead of it we'll be running off the end of the vector, stop.
+ if((i + last) > (Size() - 1))
+ break;
+
+ begin[first + i] = begin[last + i];
+ }
+
+ // Adjust the head to reflect the new size
+ head -= last - first;
+ }
+
+ // Remove the most recent element in the array
+ void PopBack()
+ {
+ if(Size() > 0)
+ head--;
+ }
+
+ // Empty the vector, or to be precise - forget the fact that there was ever anything in there.
+ void Clear() { head = -1; }
+
+ // Returns a bool indicating whether or not there are any elements in the array
+ bool Empty() { return head == -1; }
+
+ // Returns the oldest element in the array (the one added before any other)
+ VectorType const &Back() { return *begin; }
+
+ // Returns the newest element in the array (the one added after every other)
+ VectorType const &Front() { return begin[head]; }
+
+ // Returns the nth element in the vector
+ VectorType &operator[](int n)
+ {
+ if(n < Size())
+ return begin[n];
+ else
+ return OB; // out of bounds
+ }
+
+ // Returns a pointer such that the vector's data is laid out between ret to ret + size
+ VectorType *Data() { return begin; }
+
+ // Recreates the vector to hold len elements, all being copies of val
+ void Assign(int len, const VectorType &val)
+ {
+ delete[] begin;
+
+ // Allocate an array the same size as the one passed in
+ begin = new VectorType[len];
+ storage = begin + len;
+
+ // Refresh the head and tail, assuming the array is in order, which it really has to be
+ head = len - 1;
+
+ for(int i = 0 ; i < Size(); i++)
+ begin[i] = val;
+ }
+
+ // Recreates the vector using an external array
+ void Assign(VectorType *array, int len)
+ {
+ delete[] begin;
+
+ // Allocate an array the same size as the one passed in
+ begin = new VectorType[len];
+ storage = begin + len;
+
+ // Refresh the head and tail, assuming the array is in order, which it really has to be
+ head = len - 1;
+
+ // Copy over the memory
+ memcpy(begin, array, sizeof(VectorType) * len);
+ }
+
+ // Returns the number of elements that the vector will support before needing resizing
+ int Capacity() { return (storage - begin); }
+
+ // Returns the number of elements in vector
+ int Size() { return head + 1; }
+
+ // Requests that the capacity of the allocated storage space for the elements
+ // of the vector be at least enough to hold size elements.
+ void Reserve(unsigned int size)
+ {
+ if(size > Capacity())
+ ReAllocate(size);
+ }
+
+ // Resizes the vector
+ void Resize(unsigned int size)
+ {
+ // If necessary, resize the underlying array to fit the new size
+ if(size > Capacity())
+ ReAllocate(size);
+
+ // Now revise the head and size (tail needn't change) to reflect the new size
+ head = size - 1;
+ }
+
+private:
+
+ void ReAllocate(unsigned int size)
+ {
+ // Just in case we're re-allocating less room than we had before, make sure that we don't overrun the buffer by trying to write more elements than
+ // are now possible for this vector to hold.
+ if(Size() > (int)size)
+ head = size - 1;
+
+ // Allocate an array twice the size of that of the old
+ VectorType *_begin = new VectorType[size];
+ VectorType *_storage = _begin + size;
+
+ int _head = Size() - 1;
+
+ // Copy across all the old array's data and rearrange it!
+ for(int i = 0; i < Size(); i++)
+ _begin[i] = (*this)[i];
+
+ // Free the old memory
+ delete[] begin;
+
+ // Redirect the old array to point to the new one
+ begin = _begin;
+ storage = _storage;
+ head = _head;
+ }
+};
+
+#endif
\ No newline at end of file
diff --git a/lib/MycilaAppInfo/LICENSE b/lib/MycilaAppInfo/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaAppInfo/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaAppInfo/MycilaAppInfo.cpp b/lib/MycilaAppInfo/MycilaAppInfo.cpp
new file mode 100644
index 00000000..9be1849c
--- /dev/null
+++ b/lib/MycilaAppInfo/MycilaAppInfo.cpp
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+
+#include
+
+#ifndef APP_NAME
+#define APP_NAME "YaSolR"
+#endif
+
+#ifndef APP_MANUFACTURER
+#define APP_MANUFACTURER "Mathieu Carbou"
+#endif
+
+#ifdef APP_VERSION_PRO
+#ifdef APP_VERSION_TRIAL
+#define APP_MODEL "Trial"
+#else
+#define APP_MODEL "Pro"
+#endif
+#endif
+
+#ifdef APP_VERSION_OSS
+#define APP_MODEL "OSS"
+#endif
+
+#ifndef BUILD_TAG
+#define BUILD_TAG ""
+#endif
+
+#ifndef BUILD_HASH
+#define BUILD_HASH ""
+#endif
+
+#ifndef BUILD_TIMESAMP
+#define BUILD_TIMESAMP ""
+#endif
+
+#ifndef BUILD_NAME
+#define BUILD_NAME ""
+#endif
+
+Mycila::AppInfoClass::AppInfoClass() : id(_getEspId()),
+ name(APP_NAME),
+ version(BUILD_TAG),
+ model(APP_MODEL),
+ manufacturer(APP_MANUFACTURER),
+ firmware(String(APP_NAME) + (!version.startsWith("v") || version.indexOf("_") >= 0 ? "-local" : ("-" + version)) + "-" + BUILD_NAME),
+ buildHash(BUILD_HASH),
+ buildDate(strlen(BUILD_TIMESAMP) == 0 ? __DATE__ " " __TIME__ : BUILD_TIMESAMP),
+ debug(firmware.indexOf("debug") >= 0),
+ trial(firmware.indexOf("trial") >= 0) {}
+
+void Mycila::AppInfoClass::toJson(const JsonObject& root) const {
+ root["buildDate"] = buildDate;
+ root["buildHash"] = buildHash;
+ root["debug"] = debug;
+ root["firmware"] = firmware;
+ root["id"] = id;
+ root["manufacturer"] = manufacturer;
+ root["model"] = model;
+ root["name"] = name;
+ root["trial"] = trial;
+ root["version"] = version;
+}
+
+String Mycila::AppInfoClass::_getEspId() const {
+ uint32_t chipId = 0;
+ for (int i = 0; i < 17; i += 8) {
+ chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
+ }
+ String espId = String(chipId, HEX);
+ espId.toUpperCase();
+ return espId;
+}
+
+namespace Mycila {
+ AppInfoClass AppInfo;
+} // namespace Mycila
diff --git a/lib/MycilaAppInfo/MycilaAppInfo.h b/lib/MycilaAppInfo/MycilaAppInfo.h
new file mode 100644
index 00000000..9e3fa2bc
--- /dev/null
+++ b/lib/MycilaAppInfo/MycilaAppInfo.h
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+
+namespace Mycila {
+ class AppInfoClass {
+ public:
+ AppInfoClass();
+
+ void toJson(const JsonObject& root) const;
+
+ public:
+ const String id;
+ const String name;
+ const String version;
+ const String model;
+ const String manufacturer;
+ const String firmware;
+ const String buildHash;
+ const String buildDate;
+ const bool debug;
+ const bool trial;
+
+ private:
+ String _getEspId() const;
+ };
+
+ extern AppInfoClass AppInfo;
+} // namespace Mycila
diff --git a/lib/MycilaAppInfo/library.properties b/lib/MycilaAppInfo/library.properties
new file mode 100644
index 00000000..808ac96f
--- /dev/null
+++ b/lib/MycilaAppInfo/library.properties
@@ -0,0 +1,5 @@
+name=MycilaAppInfo
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/lib/MycilaButton/LICENSE b/lib/MycilaButton/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaButton/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaButton/MycilaButton.cpp b/lib/MycilaButton/MycilaButton.cpp
new file mode 100644
index 00000000..655f9043
--- /dev/null
+++ b/lib/MycilaButton/MycilaButton.cpp
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+#include
+
+#define TAG "BUTTON"
+
+void Mycila::ButtonClass::begin(const uint8_t pin, const String& pressAction, const String& longPressAction) {
+ if (_enabled)
+ return;
+
+ if (GPIO_IS_VALID_GPIO(pin)) {
+ _pin = (gpio_num_t)pin;
+ } else {
+ Logger.error(TAG, "Invalid pin: %u", _pin);
+ _pin = GPIO_NUM_NC;
+ return;
+ }
+
+ Logger.debug(TAG, "Enable Push Button...");
+ Logger.debug(TAG, "- Pin: %u", _pin);
+
+ _button = new ::Button(_pin, false);
+ const int32_t duration = 8000;
+ _button->setParam(button_param_t::BUTTON_LONG_PRESS_TIME_MS, reinterpret_cast(duration));
+
+ _pressAction = pressAction;
+ _longPressAction = longPressAction;
+
+ if (!_pressAction.isEmpty()) {
+ _button->attachSingleClickEventCb(
+ +[](void* handle, void* data) {
+ Mycila::ButtonClass* self = (Mycila::ButtonClass*)data;
+ self->_lastEvent = ButtonEvent::BUTTON_CLICKED;
+ },
+ this);
+ }
+
+ if (!_longPressAction.isEmpty()) {
+ _button->attachLongPressHoldEventCb(
+ +[](void* handle, void* data) {
+ Mycila::ButtonClass* self = (Mycila::ButtonClass*)data;
+ self->_lastEvent = ButtonEvent::BUTTON_LONG_PRESS_HOLD;
+ },
+ this);
+ }
+
+ _enabled = true;
+}
+
+void Mycila::ButtonClass::end() {
+ if (!_enabled)
+ return;
+ Logger.debug(TAG, "Disable Push Button...");
+ _enabled = false;
+ _button->del();
+ delete _button;
+ _button = nullptr;
+ _pin = GPIO_NUM_NC;
+ _lastEvent = ButtonEvent::IDLE;
+}
+
+void Mycila::ButtonClass::processEvents() {
+ if (!_enabled)
+ return;
+ ButtonEvent evt = _lastEvent;
+ _lastEvent = ButtonEvent::IDLE;
+ switch (evt) {
+ case ButtonEvent::BUTTON_CLICKED:
+ _callback(_pressAction);
+ break;
+ case ButtonEvent::BUTTON_LONG_PRESS_HOLD:
+ _callback(_longPressAction);
+ break;
+ default:
+ break;
+ }
+}
+
+void Mycila::ButtonClass::toJson(const JsonObject& root) const {
+ root["enabled"] = _enabled;
+}
+
+namespace Mycila {
+ ButtonClass Button;
+} // namespace Mycila
diff --git a/lib/MycilaButton/MycilaButton.h b/lib/MycilaButton/MycilaButton.h
new file mode 100644
index 00000000..1f397c11
--- /dev/null
+++ b/lib/MycilaButton/MycilaButton.h
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+#include
+#include
+
+namespace Mycila {
+ enum class ButtonEvent {
+ IDLE,
+ BUTTON_CLICKED,
+ BUTTON_LONG_PRESS_HOLD
+ };
+
+ typedef std::function ButtonActionCallback;
+
+ class ButtonClass {
+ public:
+ ~ButtonClass() { end(); }
+
+ void begin(const uint8_t pin, const String& pressAction = emptyString, const String& longPressAction = emptyString);
+ void end();
+
+ void processEvents();
+
+ void toJson(const JsonObject& root) const;
+
+ void listen(ButtonActionCallback callback) { _callback = callback; }
+ bool isEnabled() const { return _enabled; }
+ gpio_num_t getPin() const { return _pin; }
+
+ private:
+ bool _enabled = false;
+ ::Button* _button = nullptr;
+ ButtonEvent _lastEvent = ButtonEvent::IDLE;
+ ButtonActionCallback _callback;
+ gpio_num_t _pin = GPIO_NUM_NC;
+ String _pressAction = emptyString;
+ String _longPressAction = emptyString;
+ };
+
+ extern ButtonClass Button;
+} // namespace Mycila
diff --git a/lib/MycilaButton/library.properties b/lib/MycilaButton/library.properties
new file mode 100644
index 00000000..059c6165
--- /dev/null
+++ b/lib/MycilaButton/library.properties
@@ -0,0 +1,5 @@
+name=MycilaButton
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/lib/MycilaBuzzer/LICENSE b/lib/MycilaBuzzer/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaBuzzer/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaBuzzer/MycilaBuzzer.cpp b/lib/MycilaBuzzer/MycilaBuzzer.cpp
new file mode 100644
index 00000000..f0f7d3e0
--- /dev/null
+++ b/lib/MycilaBuzzer/MycilaBuzzer.cpp
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+#include
+
+#define TAG "BUZZER"
+
+void Mycila::BuzzerClass::begin(const uint8_t pin) {
+ if (_enabled)
+ return;
+
+ if (GPIO_IS_VALID_OUTPUT_GPIO(pin)) {
+ _pin = (gpio_num_t)pin;
+ } else {
+ Logger.error(TAG, "Invalid pin: %u", _pin);
+ _pin = GPIO_NUM_NC;
+ return;
+ }
+
+ ledcSetup(0, 1000, 8);
+ ledcAttachPin(_pin, 0);
+ Logger.debug(TAG, "Enable Buzzer...");
+ Logger.debug(TAG, "- Pin: %u", _pin);
+
+ _enabled = true;
+}
+
+void Mycila::BuzzerClass::end() {
+ if (_enabled) {
+ Logger.debug(TAG, "Disable Buzzer...");
+ _enabled = false;
+ ledcDetachPin(_pin);
+ digitalWrite(_pin, LOW);
+ pinMode(_pin, INPUT);
+ _pin = GPIO_NUM_NC;
+ }
+}
+
+void Mycila::BuzzerClass::beep(uint8_t count, uint32_t duration) const {
+ if (_enabled && count > 0)
+ while (count-- > 0) {
+ ledcWriteTone(0, 1000);
+ delay(duration);
+ ledcWriteTone(0, 0);
+ if (count > 0)
+ delay(duration + duration / 2);
+ }
+}
+
+void Mycila::BuzzerClass::toJson(const JsonObject& root) const {
+ root["enabled"] = _enabled;
+}
+
+namespace Mycila {
+ BuzzerClass Buzzer;
+} // namespace Mycila
diff --git a/lib/MycilaBuzzer/MycilaBuzzer.h b/lib/MycilaBuzzer/MycilaBuzzer.h
new file mode 100644
index 00000000..f3174d80
--- /dev/null
+++ b/lib/MycilaBuzzer/MycilaBuzzer.h
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+#include
+
+namespace Mycila {
+ class BuzzerClass {
+ public:
+ void begin(const uint8_t pin);
+ void end();
+
+ void toJson(const JsonObject& root) const;
+
+ void beep(uint8_t count = 1, uint32_t duration = 100) const;
+ bool isEnabled() const { return _enabled; }
+ gpio_num_t getPin() const { return _pin; }
+
+ private:
+ bool _enabled = false;
+ gpio_num_t _pin = GPIO_NUM_NC;
+ };
+
+ extern BuzzerClass Buzzer;
+} // namespace Mycila
diff --git a/lib/MycilaBuzzer/library.properties b/lib/MycilaBuzzer/library.properties
new file mode 100644
index 00000000..0cdc0991
--- /dev/null
+++ b/lib/MycilaBuzzer/library.properties
@@ -0,0 +1,5 @@
+name=MycilaBuzzer
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/lib/MycilaDimmer/LICENSE b/lib/MycilaDimmer/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaDimmer/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaDimmer/MycilaDimmer.cpp b/lib/MycilaDimmer/MycilaDimmer.cpp
new file mode 100644
index 00000000..aaee4ac4
--- /dev/null
+++ b/lib/MycilaDimmer/MycilaDimmer.cpp
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+
+#include
+#include
+
+#define TAG "DIMMER"
+
+static const char* DimmerTypeNames[] = {
+ "Robodyn / TRIAC-based",
+ "Random SSR",
+ "Zero-Cross SSR"};
+
+void Mycila::Dimmer::begin(const uint32_t pin, const DimmerType type) {
+ if (_enabled)
+ return;
+
+ if (GPIO_IS_VALID_OUTPUT_GPIO(pin)) {
+ _pin = (gpio_num_t)pin;
+ } else {
+ Logger.error(TAG, "Disable Dimmer '%s': Invalid pin: %u", name, _pin);
+ _pin = GPIO_NUM_NC;
+ return;
+ }
+
+ Logger.debug(TAG, "Enable Dimmer '%s'...", name);
+ Logger.debug(TAG, "- Pin: %u", _pin);
+ Logger.debug(TAG, "- Type: %s", DimmerTypeNames[static_cast(type)]);
+
+ pinMode(_pin, OUTPUT);
+ digitalWrite(_pin, LOW);
+
+ _dimmer = new DimmableLightLinearized(_pin);
+ _level = 0;
+ _dimmer->setBrightness(0);
+ _enabled = true;
+}
+
+void Mycila::Dimmer::end() {
+ if (_enabled) {
+ Logger.debug(TAG, "Disable Dimmer '%s'", name);
+ _enabled = false;
+ _level = 0;
+ _dimmer->setBrightness(0);
+ delete _dimmer;
+ _dimmer = nullptr;
+ _pin = GPIO_NUM_NC;
+ digitalWrite(_pin, LOW);
+ }
+}
+
+void Mycila::Dimmer::setLevel(uint8_t newLevel) {
+ if (!_enabled)
+ return;
+ if (newLevel > 100)
+ newLevel = 100;
+ if (_level == newLevel)
+ return;
+ const uint8_t oldLevel = _level;
+ _level = newLevel;
+ _dimmer->setBrightness(map(_level, 0, 100, 0, 255));
+ if (_callback && (oldLevel == 0 || oldLevel == 100 || newLevel == 0 || newLevel == 100))
+ _callback(newLevel == 0 ? DimmerLevel::OFF : (newLevel == 100 ? DimmerLevel::FULL : DimmerLevel::DIM));
+}
+
+void Mycila::Dimmer::toJson(const JsonObject& root) const {
+ root["enabled"] = _enabled;
+ root["level"] = _level;
+ root["state"] = _level > 0 ? "on" : "off";
+}
diff --git a/lib/MycilaDimmer/MycilaDimmer.h b/lib/MycilaDimmer/MycilaDimmer.h
new file mode 100644
index 00000000..ea386ad5
--- /dev/null
+++ b/lib/MycilaDimmer/MycilaDimmer.h
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+namespace Mycila {
+ enum class DimmerType { TRIAC = 0,
+ SSR_RANDOM,
+ SSR_ZC };
+
+ enum class DimmerLevel { OFF,
+ FULL,
+ DIM };
+
+ typedef std::function DimmerLevelCallback;
+
+ class Dimmer {
+ public:
+ explicit Dimmer(const char* name) : name(name) {}
+ ~Dimmer() { end(); }
+
+ void begin(const uint32_t pin, const DimmerType type);
+ void end();
+
+ void listen(DimmerLevelCallback callback) { _callback = callback; }
+
+ // level: 0-100 (%)
+ void setLevel(uint8_t level);
+ // level: 0-100 (%)
+ uint8_t getLevel() const { return _level; }
+
+ inline void off() { setLevel(0); }
+ bool isOff() const { return _level == 0; }
+ bool isOn() const { return _level > 0; }
+ bool isOnAtFullPower() const { return _level >= 100; }
+
+ const char* getName() const { return name; }
+ gpio_num_t getPin() const { return _pin; }
+ bool isEnabled() const { return _enabled; }
+
+ void toJson(const JsonObject& root) const;
+
+ private:
+ const char* name;
+ bool _enabled = false;
+ uint8_t _level = 0;
+ gpio_num_t _pin = GPIO_NUM_NC;
+ DimmerLevelCallback _callback = nullptr;
+ DimmableLightLinearized* _dimmer = nullptr;
+ };
+} // namespace Mycila
diff --git a/lib/MycilaDimmer/library.properties b/lib/MycilaDimmer/library.properties
new file mode 100644
index 00000000..b6af7915
--- /dev/null
+++ b/lib/MycilaDimmer/library.properties
@@ -0,0 +1,5 @@
+name=MycilaDimmer
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/lib/MycilaGrid/LICENSE b/lib/MycilaGrid/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaGrid/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaGrid/MycilaGrid.cpp b/lib/MycilaGrid/MycilaGrid.cpp
new file mode 100644
index 00000000..eaf41f44
--- /dev/null
+++ b/lib/MycilaGrid/MycilaGrid.cpp
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+
+#include
+#include
+#include
+#include
+
+#define TAG "POWER"
+
+void Mycila::GridClass::begin(const String& gridPowerMQTTTopic) {
+ if (!_topic.isEmpty())
+ return;
+
+ _topic = gridPowerMQTTTopic;
+
+ Logger.debug(TAG, "Enable MQTT Grid Power...");
+ Logger.debug(TAG, "- MQTT Topic: %s", _topic.c_str());
+
+ if (!_topic.isEmpty()) {
+ MQTT.subscribe(_topic, [this](const String& topic, const String& payload) {
+ _mqttGridPower = payload.toFloat();
+ _mqttGridPowerUpdateTime = millis();
+ });
+ }
+}
+
+void Mycila::GridClass::end() {
+ if (!_topic.isEmpty()) {
+ Logger.debug(TAG, "Disable Grid Power from MQTT...");
+ MQTT.unsubscribe(_topic);
+ _topic = emptyString;
+ _mqttGridPower = 0;
+ _mqttGridPowerUpdateTime = 0;
+ }
+}
+
+float Mycila::GridClass::getFrequency() const {
+ float freq = JSY.frequency;
+ return freq > 0 ? freq : ZCD.getFrequency();
+}
+
+float Mycila::GridClass::getPower() const {
+ return !_topic.isEmpty() && !isMQTTGridPowerExpired() ? _mqttGridPower : (JSY.isEnabled() ? JSY.power2 : 0);
+}
+
+float Mycila::GridClass::getVoltage() const {
+ return JSY.voltage2;
+}
+
+void Mycila::GridClass::toJson(const JsonObject& root) const {
+ const uint8_t gridFrequency = getFrequency();
+ root["frequency"] = gridFrequency;
+ root["power"] = getPower();
+ root["voltage"] = getVoltage();
+ root["online"] = gridFrequency > 0;
+ JsonObject jsy = root["jsy"].to();
+ Mycila::JSY.toJson(jsy);
+ JsonObject zcd = root["zcd"].to();
+ Mycila::ZCD.toJson(zcd);
+}
+
+namespace Mycila {
+ GridClass Grid;
+} // namespace Mycila
diff --git a/lib/MycilaGrid/MycilaGrid.h b/lib/MycilaGrid/MycilaGrid.h
new file mode 100644
index 00000000..19363b65
--- /dev/null
+++ b/lib/MycilaGrid/MycilaGrid.h
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+
+#ifndef YASOLR_MQTT_GRID_POWER_EXPIRATION
+#define YASOLR_MQTT_GRID_POWER_EXPIRATION 60
+#endif
+
+namespace Mycila {
+ class GridClass {
+ public:
+ void begin(const String& gridPowerMQTTTopic = emptyString);
+ void end();
+
+ void toJson(const JsonObject& root) const;
+
+ float getFrequency() const;
+ float getPower() const;
+ float getVoltage() const;
+ inline bool isOnline() const { return getFrequency() > 0; }
+ bool isMQTTGridPowerExpired() const { return millis() - _mqttGridPowerUpdateTime >= YASOLR_MQTT_GRID_POWER_EXPIRATION * 1000; }
+
+ private:
+ float _mqttGridPower = 0;
+ uint32_t _mqttGridPowerUpdateTime = 0;
+ String _topic;
+ };
+
+ extern GridClass Grid;
+} // namespace Mycila
diff --git a/lib/MycilaGrid/library.properties b/lib/MycilaGrid/library.properties
new file mode 100644
index 00000000..8c331dd6
--- /dev/null
+++ b/lib/MycilaGrid/library.properties
@@ -0,0 +1,5 @@
+name=MycilaGrid
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/lib/MycilaHTTPd/LICENSE b/lib/MycilaHTTPd/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaHTTPd/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaHTTPd/MycilaHTTPd.cpp b/lib/MycilaHTTPd/MycilaHTTPd.cpp
new file mode 100644
index 00000000..48704bfd
--- /dev/null
+++ b/lib/MycilaHTTPd/MycilaHTTPd.cpp
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+#include
+
+#include
+
+#ifndef MYCILA_API_PATH
+#define MYCILA_API_PATH "/api"
+#endif
+
+#define TAG "HTTP"
+
+void Mycila::HTTPdClass::init(AsyncWebServer* server, const String& username, const String& password) {
+ if (_server)
+ return;
+
+ _username = username;
+ _password = password;
+ _auth = !_username.isEmpty() && !_password.isEmpty();
+
+ Logger.debug(TAG, "Initializing HTTPd...");
+ Logger.debug(TAG, "- Authentication: %s", _auth ? "true" : "false");
+ Logger.debug(TAG, "- Username: %s", _username.c_str());
+ Logger.debug(TAG, "- Password: %s", _password.isEmpty() ? "" : "********");
+
+ _server = server;
+ _running = false;
+}
+
+void Mycila::HTTPdClass::begin() {
+ if (!_server)
+ return;
+ if (_running)
+ return;
+ Logger.info(TAG, "Enable HTTPd...");
+ _server->onNotFound([](AsyncWebServerRequest* request) {
+ request->send(404);
+ });
+ _server->begin();
+ MDNS.addService("http", "tcp", 80);
+ _running = true;
+}
+
+void Mycila::HTTPdClass::end() {
+ if (!_server)
+ return;
+ if (!_running)
+ return;
+ Logger.info(TAG, "Disable HTTPd...");
+ mdns_service_remove("_http", "_tcp");
+ _server->end();
+ _server = nullptr;
+ _running = false;
+}
+
+AsyncWebHandler& Mycila::HTTPdClass::get(const char* path, ArRequestHandlerFunction onRequest, bool anonymous) {
+ Logger.debug(TAG, "[GET ] %s", path);
+ return _authenticate(&_server->on(path, HTTP_GET, onRequest), anonymous);
+}
+
+AsyncWebHandler& Mycila::HTTPdClass::post(const char* path, ArRequestHandlerFunction onRequest, bool anonymous) {
+ Logger.debug(TAG, "[POST ] %s", path);
+ return _authenticate(&_server->on(path, HTTP_POST, onRequest), anonymous);
+}
+
+AsyncWebHandler& Mycila::HTTPdClass::del(const char* path, ArRequestHandlerFunction onRequest, bool anonymous) {
+ Logger.debug(TAG, "[DELETE] %s", path);
+ return _authenticate(&_server->on(path, HTTP_DELETE, onRequest), anonymous);
+}
+
+AsyncWebHandler& Mycila::HTTPdClass::any(const char* path, ArRequestHandlerFunction onRequest, bool anonymous) {
+ Logger.debug(TAG, "[ANY ] %s", path);
+ return _authenticate(&_server->on(path, HTTP_ANY, onRequest), anonymous);
+}
+
+AsyncWebHandler& Mycila::HTTPdClass::apiGET(const char* path, ArRequestHandlerFunction onRequest, bool anonymous) {
+ String url;
+ url.reserve(strlen(MYCILA_API_PATH) + strlen(path));
+ url += MYCILA_API_PATH;
+ url += path;
+ Logger.debug(TAG, "[GET ] %s", url.c_str());
+ return _authenticate(&_server->on(url.c_str(), HTTP_GET, onRequest), anonymous);
+}
+
+AsyncWebHandler& Mycila::HTTPdClass::apiPOST(const char* path, ArRequestHandlerFunction onRequest, bool anonymous) {
+ String url;
+ url.reserve(strlen(MYCILA_API_PATH) + strlen(path));
+ url += MYCILA_API_PATH;
+ url += path;
+ Logger.debug(TAG, "[POST ] %s", url.c_str());
+ return _authenticate(&_server->on(url.c_str(), HTTP_POST, onRequest), anonymous);
+}
+
+AsyncWebHandler& Mycila::HTTPdClass::apiUPLOAD(const char* path, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload, bool anonymous) {
+ String url;
+ url.reserve(strlen(MYCILA_API_PATH) + strlen(path));
+ url += MYCILA_API_PATH;
+ url += path;
+ Logger.debug(TAG, "[UPLOAD] %s", url.c_str());
+ return _authenticate(&_server->on(url.c_str(), HTTP_POST, onRequest, onUpload), anonymous);
+}
+
+AsyncWebHandler& Mycila::HTTPdClass::apiDELETE(const char* path, ArRequestHandlerFunction onRequest, bool anonymous) {
+ String url;
+ url.reserve(strlen(MYCILA_API_PATH) + strlen(path));
+ url += MYCILA_API_PATH;
+ url += path;
+ Logger.debug(TAG, "[DELETE] %s", url.c_str());
+ return _authenticate(&_server->on(url.c_str(), HTTP_DELETE, onRequest), anonymous);
+}
+
+AsyncWebHandler& Mycila::HTTPdClass::apiANY(const char* path, ArRequestHandlerFunction onRequest, bool anonymous) {
+ String url;
+ url.reserve(strlen(MYCILA_API_PATH) + strlen(path));
+ url += MYCILA_API_PATH;
+ url += path;
+ Logger.debug(TAG, "[ANY ] %s", url.c_str());
+ return _authenticate(&_server->on(url.c_str(), HTTP_ANY, onRequest), anonymous);
+}
+
+AsyncWebSocket& Mycila::HTTPdClass::webSocket(const char* path) {
+ AsyncWebSocket* ws = new AsyncWebSocket(path);
+ _authenticate(ws, false);
+ _server->addHandler(ws);
+ return *ws;
+}
+
+AsyncWebHandler& Mycila::HTTPdClass::_authenticate(AsyncWebHandler* handler, bool anonymous) {
+ return handler->setAuthentication(anonymous ? "" : (_auth ? _username.c_str() : ""), anonymous ? "" : (_auth ? _password.c_str() : ""));
+}
+
+namespace Mycila {
+ HTTPdClass HTTPd;
+} // namespace Mycila
diff --git a/lib/MycilaHTTPd/MycilaHTTPd.h b/lib/MycilaHTTPd/MycilaHTTPd.h
new file mode 100644
index 00000000..6ea8d25f
--- /dev/null
+++ b/lib/MycilaHTTPd/MycilaHTTPd.h
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+
+namespace Mycila {
+ class HTTPdClass {
+ public:
+ void init(AsyncWebServer* server, const String& username = emptyString, const String& password = emptyString);
+ void begin();
+ void end();
+
+ AsyncWebHandler& get(const char* path, ArRequestHandlerFunction onRequest, bool anonymous = false);
+ AsyncWebHandler& post(const char* path, ArRequestHandlerFunction onRequest, bool anonymous = false);
+ AsyncWebHandler& del(const char* path, ArRequestHandlerFunction onRequest, bool anonymous = false);
+ AsyncWebHandler& any(const char* path, ArRequestHandlerFunction onRequest, bool anonymous = false);
+
+ AsyncWebHandler& apiGET(const char* path, ArRequestHandlerFunction onRequest, bool anonymous = false);
+ AsyncWebHandler& apiPOST(const char* path, ArRequestHandlerFunction onRequest, bool anonymous = false);
+ AsyncWebHandler& apiUPLOAD(const char* path, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload, bool anonymous = false);
+ AsyncWebHandler& apiDELETE(const char* path, ArRequestHandlerFunction onRequest, bool anonymous = false);
+ AsyncWebHandler& apiANY(const char* path, ArRequestHandlerFunction onRequest, bool anonymous = false);
+
+ AsyncWebSocket& webSocket(const char* path);
+
+ bool isEnabled() const { return _server != nullptr; }
+ bool isRunning() const { return _running; }
+ bool isAuthEnabled() const { return _auth; }
+ const String& getUsername() const { return _username; }
+ const String& getPassword() const { return _password; }
+
+ private:
+ AsyncWebServer* _server = nullptr;
+ String _username = emptyString;
+ String _password = emptyString;
+ bool _auth = false;
+ bool _running = false;
+
+ private:
+ AsyncWebHandler& _authenticate(AsyncWebHandler* handler, bool anonymous);
+ };
+
+ extern HTTPdClass HTTPd;
+} // namespace Mycila
diff --git a/lib/MycilaHTTPd/library.properties b/lib/MycilaHTTPd/library.properties
new file mode 100644
index 00000000..af7d0dc7
--- /dev/null
+++ b/lib/MycilaHTTPd/library.properties
@@ -0,0 +1,5 @@
+name=MycilaHTTPd
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/lib/MycilaLights/LICENSE b/lib/MycilaLights/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaLights/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaLights/MycilaLights.cpp b/lib/MycilaLights/MycilaLights.cpp
new file mode 100644
index 00000000..5d23cb9f
--- /dev/null
+++ b/lib/MycilaLights/MycilaLights.cpp
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+#include
+
+#define TAG "LIGHTS"
+
+void Mycila::LightsClass::begin(const uint8_t greenPin, const uint8_t yellowPin, const uint8_t redPin) {
+ Logger.debug(TAG, "Enable Physical LEDs...");
+
+ if (GPIO_IS_VALID_OUTPUT_GPIO(greenPin)) {
+ _greenPin = (gpio_num_t)greenPin;
+ Logger.debug(TAG, "- Pin: %u (green)", _greenPin);
+ pinMode(_greenPin, OUTPUT);
+ } else {
+ Logger.error(TAG, "Invalid pin: %u", _greenPin);
+ _greenPin = GPIO_NUM_NC;
+ }
+
+ if (GPIO_IS_VALID_OUTPUT_GPIO(yellowPin)) {
+ _yellowPin = (gpio_num_t)yellowPin;
+ Logger.debug(TAG, "- Pin: %u (yellow)", _yellowPin);
+ pinMode(_yellowPin, OUTPUT);
+ } else {
+ Logger.error(TAG, "Invalid pin: %u", _yellowPin);
+ _yellowPin = GPIO_NUM_NC;
+ }
+
+ if (GPIO_IS_VALID_OUTPUT_GPIO(redPin)) {
+ _redPin = (gpio_num_t)redPin;
+ Logger.debug(TAG, "- Pin: %u (red)", _redPin);
+ pinMode(_redPin, OUTPUT);
+ } else {
+ Logger.error(TAG, "Invalid pin: %u", _redPin);
+ _redPin = GPIO_NUM_NC;
+ }
+}
+
+void Mycila::LightsClass::end() {
+ set(LightState::OFF, LightState::OFF, LightState::OFF);
+ if (_greenPin != GPIO_NUM_NC)
+ digitalWrite(_greenPin, LOW);
+ if (_yellowPin != GPIO_NUM_NC)
+ digitalWrite(_yellowPin, LOW);
+ if (_redPin != GPIO_NUM_NC)
+ digitalWrite(_redPin, LOW);
+ _greenPin = GPIO_NUM_NC;
+ _yellowPin = GPIO_NUM_NC;
+ _redPin = GPIO_NUM_NC;
+}
+
+void Mycila::LightsClass::set(LightState green, LightState yellow, LightState red) {
+ if (green != LightState::NONE)
+ _green = green == LightState::ON;
+ if (yellow != LightState::NONE)
+ _yellow = yellow == LightState::ON;
+ if (red != LightState::NONE)
+ _red = red == LightState::ON;
+ if (_greenPin != GPIO_NUM_NC)
+ digitalWrite(_greenPin, _green ? HIGH : LOW);
+ if (_yellowPin != GPIO_NUM_NC)
+ digitalWrite(_yellowPin, _yellow ? HIGH : LOW);
+ if (_redPin != GPIO_NUM_NC)
+ digitalWrite(_redPin, _red ? HIGH : LOW);
+}
+
+void Mycila::LightsClass::toJson(const JsonObject& root) const {
+ root["code"] = toString();
+ root["green"] = _green ? "on" : "off";
+ root["red"] = _red ? "on" : "off";
+ root["yellow"] = _yellow ? "on" : "off";
+}
+
+namespace Mycila {
+ LightsClass Lights;
+} // namespace Mycila
diff --git a/lib/MycilaLights/MycilaLights.h b/lib/MycilaLights/MycilaLights.h
new file mode 100644
index 00000000..288ff698
--- /dev/null
+++ b/lib/MycilaLights/MycilaLights.h
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+#include
+
+namespace Mycila {
+ enum class LightState {
+ NONE = 0,
+ ON,
+ OFF
+ };
+
+ class LightsClass {
+ public:
+ void begin(const uint8_t greenPin, const uint8_t yellowPin, const uint8_t redPin);
+ void end();
+
+ bool isEnabled() const { return _greenPin != GPIO_NUM_NC || _yellowPin != GPIO_NUM_NC || _redPin != GPIO_NUM_NC; }
+
+ inline void setAllOn() { set(LightState::ON, LightState::ON, LightState::ON); }
+ inline void setAllOff() { set(LightState::OFF, LightState::OFF, LightState::OFF); }
+
+ inline void setGreen(bool state) { set(state ? LightState::ON : LightState::OFF, LightState::NONE, LightState::NONE); }
+ inline void setYellow(bool state) { set(LightState::NONE, state ? LightState::ON : LightState::OFF, LightState::NONE); }
+ inline void setRed(bool state) { set(LightState::NONE, LightState::NONE, state ? LightState::ON : LightState::OFF); }
+ void set(LightState green, LightState yellow, LightState red);
+
+ LightState getGreen() const { return _green ? LightState::ON : LightState::OFF; }
+ LightState getYellow() const { return _yellow ? LightState::ON : LightState::OFF; }
+ LightState getRed() const { return _red ? LightState::ON : LightState::OFF; }
+
+ inline bool isGreenOn() const { return getGreen() == LightState::ON; }
+ inline bool isYellowOn() const { return getYellow() == LightState::ON; }
+ inline bool isRedOn() const { return getRed() == LightState::ON; }
+
+ inline bool areAllOn() const { return isGreenOn() && isYellowOn() && isRedOn(); }
+ inline bool areAllOff() const { return !isGreenOn() && !isYellowOn() && !isRedOn(); }
+
+ inline String toString() const { return String(isGreenOn() ? "🟢 " : "⚫ ") + (isYellowOn() ? "🟡 " : "⚫ ") + (isRedOn() ? "🔴" : "⚫"); }
+
+ void toJson(const JsonObject& root) const;
+
+ gpio_num_t getGreenPin() const { return _greenPin; }
+ gpio_num_t getYellowPin() const { return _yellowPin; }
+ gpio_num_t getRedPin() const { return _redPin; }
+
+ private:
+ gpio_num_t _greenPin = GPIO_NUM_NC;
+ gpio_num_t _yellowPin = GPIO_NUM_NC;
+ gpio_num_t _redPin = GPIO_NUM_NC;
+ bool _green = false;
+ bool _yellow = false;
+ bool _red = false;
+ };
+
+ extern LightsClass Lights;
+} // namespace Mycila
diff --git a/lib/MycilaLights/library.properties b/lib/MycilaLights/library.properties
new file mode 100644
index 00000000..c00ff5b6
--- /dev/null
+++ b/lib/MycilaLights/library.properties
@@ -0,0 +1,5 @@
+name=MycilaLights
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/lib/MycilaRelayManager/LICENSE b/lib/MycilaRelayManager/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaRelayManager/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaRelayManager/MycilaRelayManager.cpp b/lib/MycilaRelayManager/MycilaRelayManager.cpp
new file mode 100644
index 00000000..159bdbfa
--- /dev/null
+++ b/lib/MycilaRelayManager/MycilaRelayManager.cpp
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+
+#include
+#include
+#include
+
+#ifndef MYCILA_RELAY_THRESHOLD_TOLERANCE_START
+#define MYCILA_RELAY_THRESHOLD_TOLERANCE_START 20
+#endif
+
+#ifndef MYCILA_RELAY_THRESHOLD_TOLERANCE_STOP
+#define MYCILA_RELAY_THRESHOLD_TOLERANCE_STOP 20
+#endif
+
+#define TAG "RELAY-M"
+
+void Mycila::RelayManagerClass::toJson(const JsonObject& root) const {
+ for (const auto& relay : _relays) {
+ relay->toJson(root[relay->getName()].to());
+ }
+}
+
+void Mycila::RelayManagerClass::autoCommute() {
+ const float grid = Router.getVirtualGridPower();
+
+ // check if we need to start a relay
+ {
+ for (auto& relay : _relays) {
+ if (relay->isEnabled() && relay->isOff()) {
+ const float threshold = RelayManagerConfig.getPowerThreshold(relay->getName());
+ if (threshold > 0 && grid <= -(threshold + round(threshold * MYCILA_RELAY_THRESHOLD_TOLERANCE_START / 100.0))) {
+ Logger.info(TAG, "Auto starting relay '%s'...", relay->getName());
+ relay->setState(true);
+ // we stop the loop and let time for routing to adjust before checking again
+ return;
+ }
+ }
+ }
+ }
+
+ // check if we need to stop a relay
+ {
+ for (int i = _relays.size() - 1; i >= 0; i--) {
+ auto& relay = _relays[i];
+ if (relay->isEnabled() && relay->isOn()) {
+ const float threshold = RelayManagerConfig.getPowerThreshold(relay->getName());
+ if (threshold > 0 && grid - threshold >= -(threshold - round(threshold * MYCILA_RELAY_THRESHOLD_TOLERANCE_STOP / 100.0))) {
+ Logger.info(TAG, "Auto stopping relay '%s'...", relay->getName());
+ relay->setState(false);
+ // we stop the loop and let time for routing to adjust before checking again
+ return;
+ }
+ }
+ }
+ }
+}
+
+bool Mycila::RelayManagerClass::tryRelayState(Relay* relay, bool switchOn, uint32_t duration) {
+ if (!relay->isEnabled())
+ return false;
+
+ if (RelayManagerConfig.getPowerThreshold(relay->getName()) > 0) {
+ Logger.warn(TAG, "Auto Mode '%s' is activated: unable to switch Relay...", relay->getName());
+ return false;
+ }
+
+ relay->setState(switchOn, duration);
+ return true;
+}
+
+namespace Mycila {
+ RelayManagerClass RelayManager;
+ RelayManagerConfigClass RelayManagerConfig;
+} // namespace Mycila
diff --git a/lib/MycilaRelayManager/MycilaRelayManager.h b/lib/MycilaRelayManager/MycilaRelayManager.h
new file mode 100644
index 00000000..e82a6539
--- /dev/null
+++ b/lib/MycilaRelayManager/MycilaRelayManager.h
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+
+#include
+#include
+
+namespace Mycila {
+
+ class RelayManagerConfigClass {
+ public:
+ uint16_t getPowerThreshold(const char* name) const;
+ };
+
+ class RelayManagerClass {
+ public:
+ void setRelays(const std::vector relays) { _relays = relays; }
+
+ void toJson(const JsonObject& root) const;
+
+ void autoCommute();
+ bool tryRelayState(Relay* relay, bool state, uint32_t duration = 0);
+
+ private:
+ std::vector _relays = {};
+ };
+
+ extern RelayManagerConfigClass RelayManagerConfig;
+ extern RelayManagerClass RelayManager;
+} // namespace Mycila
diff --git a/lib/MycilaRelayManager/library.properties b/lib/MycilaRelayManager/library.properties
new file mode 100644
index 00000000..3c3b9e92
--- /dev/null
+++ b/lib/MycilaRelayManager/library.properties
@@ -0,0 +1,5 @@
+name=MycilaRelayManager
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/lib/MycilaRouter/LICENSE b/lib/MycilaRouter/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaRouter/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaRouter/MycilaRouter.cpp b/lib/MycilaRouter/MycilaRouter.cpp
new file mode 100644
index 00000000..a930ea0f
--- /dev/null
+++ b/lib/MycilaRouter/MycilaRouter.cpp
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+
+#include
+#include
+#include
+
+#define TAG "ROUTER"
+
+void Mycila::RouterClass::toJson(const JsonObject& root) const {
+ root["energy"] = getTotalRoutedEnergy();
+ root["power_factor"] = getTotalPowerFactor();
+ root["power"] = getTotalRoutedPower();
+ root["thdi"] = getTotalTHDi();
+ root["virtual_grid_power"] = getVirtualGridPower();
+ for (const auto& output : _outputs) {
+ output->toJson(root[output->getName()].to());
+ }
+}
+
+float Mycila::RouterClass::getVirtualGridPower() const {
+ return Grid.getPower() - getTotalRoutedPower();
+}
+
+float Mycila::RouterClass::getTotalRoutedPower() const {
+ for (auto& output : _outputs) {
+ if (output->getState() == RouterOutputState::OUTPUT_ROUTING) {
+ return abs(JSY.power1);
+ }
+ }
+ return 0;
+}
+
+float Mycila::RouterClass::getTotalTHDi() const {
+ for (auto& output : _outputs) {
+ if (output->getState() == RouterOutputState::OUTPUT_ROUTING) {
+ // https://fr.electrical-installation.org/frwiki/Indicateur_de_distorsion_harmonique_:_facteur_de_puissance
+ const float phi = 0; // no phase shift for resistive load between voltage and current (cos(phi) = 1)
+ const float pf = getTotalPowerFactor();
+ return sqrt(pow(cos(phi), 2) / pow(pf, 2) - 1);
+ }
+ }
+ return 0;
+}
+
+float Mycila::RouterClass::getTotalPowerFactor() const {
+ for (auto& output : _outputs) {
+ if (output->getState() == RouterOutputState::OUTPUT_ROUTING) {
+ return JSY.powerFactor1;
+ }
+ }
+ return 0;
+}
+
+float Mycila::RouterClass::getTotalRoutedEnergy() const {
+ return JSY.energy1 + JSY.energyReturned1;
+}
+
+bool Mycila::RouterClass::isRouting() const {
+ for (const auto& output : _outputs) {
+ if (output->getState() == RouterOutputState::OUTPUT_ROUTING) {
+ return true;
+ }
+ }
+ return false;
+}
+
+namespace Mycila {
+ RouterClass Router;
+} // namespace Mycila
+
+//TODO: do we need power per output ?
+// float Mycila::RouterClass::getOutputPower(const RouterOutput* output) const {
+// const int idx = &output - &_outputs[0];
+
+// int routing = 0;
+// float dimmerLevel = 0;
+
+// for (size_t i = 0, max = _outputs.size(); i < max; i++) {
+// const uint8_t level = _outputs[i].getDimmer()->getLevel();
+// if (level > 0) {
+// routing++;
+// if (i == idx)
+// dimmerLevel = level;
+// } else if (i == idx) {
+// return 0;
+// }
+// }
+
+// // more accurate
+// if (routing == 1)
+// return abs(JSY.power1);
+
+// // approximation with P = U * U / R
+// const float u = Grid.getVoltage();
+// const float r = output.getResistance(idx);
+
+// return (u * u / r) * (dimmerLevel / 100.0);
+// }
diff --git a/lib/MycilaRouter/MycilaRouter.h b/lib/MycilaRouter/MycilaRouter.h
new file mode 100644
index 00000000..7b5976a1
--- /dev/null
+++ b/lib/MycilaRouter/MycilaRouter.h
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+
+#include
+#include
+
+namespace Mycila {
+ class RouterClass {
+ public:
+ void setOutputs(const std::vector& outputs) { _outputs = outputs; }
+
+ void toJson(const JsonObject& root) const;
+
+ float getVirtualGridPower() const;
+ float getTotalRoutedPower() const;
+ float getTotalPowerFactor() const;
+ float getTotalTHDi() const;
+ float getTotalRoutedEnergy() const;
+
+ bool isRouting() const;
+
+ private:
+ std::vector _outputs = {};
+ };
+
+ extern RouterClass Router;
+} // namespace Mycila
diff --git a/lib/MycilaRouter/library.properties b/lib/MycilaRouter/library.properties
new file mode 100644
index 00000000..d54acb79
--- /dev/null
+++ b/lib/MycilaRouter/library.properties
@@ -0,0 +1,5 @@
+name=MycilaRouter
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/lib/MycilaRouterOutput/LICENSE b/lib/MycilaRouterOutput/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaRouterOutput/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaRouterOutput/MycilaRouterOutput.cpp b/lib/MycilaRouterOutput/MycilaRouterOutput.cpp
new file mode 100644
index 00000000..992b3c71
--- /dev/null
+++ b/lib/MycilaRouterOutput/MycilaRouterOutput.cpp
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+
+#include
+#include
+#include
+
+#define TAG "OUTPUT"
+
+static const char* RouterOutputStateNames[] = {
+ "Disabled",
+ "Idle",
+ "Routing",
+ "Manual Bypass",
+ "Auto Bypass",
+};
+
+static const char* DaysOfWeek[] = {"sun", "mon", "tue", "wed", "thu", "fri", "sat"};
+
+void Mycila::RouterOutput::applyDimmerLimit() {
+ if (!_dimmer->isEnabled())
+ return;
+ if (_autoBypassEnabled)
+ return;
+ if (_dimmer->isOff())
+ return;
+ uint8_t limit = RouterOutputConfig.getDimmerLevelLimit(_dimmer->getName());
+ if (_dimmer->getLevel() > limit) {
+ Logger.warn(TAG, "Dimmer '%s' reached its limit at %u %", _dimmer->getName(), limit);
+ _dimmer->setLevel(limit);
+ }
+}
+
+bool Mycila::RouterOutput::tryBypassRelayState(bool switchOn) {
+ if (_autoBypassEnabled && !switchOn) {
+ Logger.warn(TAG, "Auto Bypass '%s' is activated: unable to turn of bypass relay", _name);
+ return false;
+ }
+ _setBypassRelay(switchOn);
+ return true;
+}
+
+bool Mycila::RouterOutput::tryDimmerLevel(uint8_t level) {
+ if (!_dimmer->isEnabled())
+ return false;
+
+ if (_autoBypassEnabled) {
+ Logger.warn(TAG, "Auto Bypass '%s' is activated: unable to change dimmer level", _name);
+ return false;
+ }
+
+ if (RouterOutputConfig.isAutoDimmerEnabled(_name)) {
+ Logger.warn(TAG, "Auto Dimmer '%s' is activated: unable to change dimmer level", _name);
+ return false;
+ }
+
+ Logger.debug(TAG, "Setting Dimmer '%s' level to %u %...", _dimmer->getName(), level);
+ _relay->off();
+ _dimmer->setLevel(level);
+ return true;
+}
+
+Mycila::RouterOutputState Mycila::RouterOutput::getState() const {
+ if (!_dimmer->isEnabled())
+ return RouterOutputState::OUTPUT_DISABLED;
+ if (_dimmer->getLevel() > 0)
+ return RouterOutputState::OUTPUT_ROUTING;
+ // dimmer level is 0
+ if (_autoBypassEnabled)
+ return RouterOutputState::OUTPUT_BYPASS_AUTO;
+ if (_relay->isOn())
+ return RouterOutputState::OUTPUT_BYPASS_MANUAL;
+ return RouterOutputState::OUTPUT_IDLE;
+}
+
+const char* Mycila::RouterOutput::getStateString() const { return RouterOutputStateNames[static_cast(getState())]; }
+
+void Mycila::RouterOutput::toJson(const JsonObject& root) const {
+ root["enabled"] = _dimmer->isEnabled();
+ root["state"] = RouterOutputStateNames[static_cast(getState())];
+ JsonObject dimmerJson = root["dimmer"].to();
+ _dimmer->toJson(dimmerJson);
+ JsonObject relayJson = root["bypass_relay"].to();
+ _relay->toJson(relayJson);
+ JsonObject temperatureSensorJson = root["temp_sensor"].to();
+ _temperatureSensor->toJson(temperatureSensorJson);
+}
+
+float Mycila::RouterOutput::getResistance() const {
+ // TODO: auto-calibration or config ?
+ return 227.34;
+}
+
+void Mycila::RouterOutput::autoBypass() {
+ if (!RouterOutputConfig.isAutoBypassEnabled(_name)) {
+ if (_autoBypassEnabled) {
+ Logger.warn(TAG, "Auto Bypass disabled: stopping Auto Bypass '%s'...", _name);
+ _autoBypassEnabled = false;
+ _setBypassRelay(false);
+ }
+ return;
+ }
+
+ if (!_relay->isEnabled() && !_dimmer->isEnabled()) {
+ if (_autoBypassEnabled) {
+ Logger.warn(TAG, "Relay and dimmer disabled: stopping Auto Bypass '%s'...", _name);
+ _autoBypassEnabled = false;
+ _setBypassRelay(false);
+ }
+ return;
+ }
+
+ if (!_temperatureSensor->isEnabled()) {
+ if (_autoBypassEnabled) {
+ Logger.warn(TAG, "Temperature Sensor disabled: stopping Auto Bypass '%s'...", _name);
+ _autoBypassEnabled = false;
+ _setBypassRelay(false);
+ }
+ return;
+ }
+
+ if (!_temperatureSensor->isValid()) {
+ if (_autoBypassEnabled) {
+ Logger.warn(TAG, "Temperature sensor is not answering: stopping Auto Bypass '%s'...", _name);
+ _autoBypassEnabled = false;
+ _setBypassRelay(false);
+ }
+ return;
+ }
+
+ const float temp = _temperatureSensor->getTemperature();
+
+ if (temp >= RouterOutputConfig.getAutoStopTemperature(_name)) {
+ if (_autoBypassEnabled) {
+ Logger.info(TAG, "Temperature reached %.02f °C: stopping Auto Bypass '%s'...", temp, _name);
+ _autoBypassEnabled = false;
+ _setBypassRelay(false);
+ }
+ return;
+ }
+
+ if (temp >= RouterOutputConfig.getAutoStartTemperature(_name)) {
+ // temperature OK, no need to start
+ return;
+ }
+
+ if (!NTP.isSynced()) {
+ if (_autoBypassEnabled) {
+ Logger.warn(TAG, "NTP not available: stopping Auto Bypass '%s'...", _name);
+ _autoBypassEnabled = false;
+ _setBypassRelay(false);
+ }
+ return;
+ }
+
+ struct tm timeInfo;
+ if (!getLocalTime(&timeInfo, 5)) {
+ if (_autoBypassEnabled) {
+ Logger.warn(TAG, "Unable to get time: stopping Auto Bypass '%s'...", _name);
+ _autoBypassEnabled = false;
+ _setBypassRelay(false);
+ }
+ return;
+ }
+
+ const String autoStart = RouterOutputConfig.getAutoStartTime(_name);
+ const String autoStop = RouterOutputConfig.getAutoStopTime(_name);
+ const int inRange = Time::timeInRange(&timeInfo, autoStart, autoStop);
+ if (inRange == -1) {
+ if (_autoBypassEnabled) {
+ Logger.warn(TAG, "Time range %s to %s is invalid: stopping Auto Bypass '%s'...", autoStart.c_str(), autoStop.c_str(), _name);
+ _autoBypassEnabled = false;
+ _setBypassRelay(false);
+ }
+ return;
+ }
+
+ if (!inRange) {
+ if (_autoBypassEnabled) {
+ Logger.info(TAG, "Time reached %s: stopping Auto Bypass '%s'...", autoStop.c_str(), _name);
+ _autoBypassEnabled = false;
+ _setBypassRelay(false);
+ }
+ return;
+ }
+
+ // time and temp OK, let's start
+ if (!_autoBypassEnabled) {
+ // auto bypass is not enabled, let's start it
+ const char* wday = DaysOfWeek[timeInfo.tm_wday];
+ if (RouterOutputConfig.getWeekDays(_name).indexOf(wday) >= 0) {
+ Logger.info(TAG, "Time within %s-%s on %s: starting Auto Bypass '%s' at %.02f °C...", autoStart.c_str(), autoStop.c_str(), wday, _name, temp);
+ _autoBypassEnabled = true;
+ _setBypassRelay(true);
+ }
+ return;
+ }
+
+ // auto bypass is enabled
+
+ // relay is on ?
+ if (_relay->isOn())
+ return;
+
+ // or relay is disabled and dimmer at full power tu replace it ?
+ if (!_relay->isEnabled() && _dimmer->isOnAtFullPower())
+ return;
+
+ // start bypass
+ Logger.info(TAG, "Auto Bypass '%s' is activated: restarting Relay...", _name);
+ _setBypassRelay(true);
+}
+
+void Mycila::RouterOutput::_setBypassRelay(bool state) {
+ if (_relay->isEnabled()) {
+ Logger.debug(TAG, "Turning %s Bypass Relay '%s'...", state ? "on" : "off", _relay->getName());
+ if (state)
+ _dimmer->off();
+ _relay->setState(state);
+
+ } else {
+ Logger.debug(TAG, "Turning %s Dimmer '%s'...", state ? "on" : "off", _dimmer->getName());
+ _dimmer->setLevel(state ? 100 : 0);
+ }
+}
+
+namespace Mycila {
+ RouterOutputConfigClass RouterOutputConfig;
+} // namespace Mycila
diff --git a/lib/MycilaRouterOutput/MycilaRouterOutput.h b/lib/MycilaRouterOutput/MycilaRouterOutput.h
new file mode 100644
index 00000000..f1d07e24
--- /dev/null
+++ b/lib/MycilaRouterOutput/MycilaRouterOutput.h
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+#include
+
+#include
+
+namespace Mycila {
+ enum class RouterOutputState {
+ // output disabled
+ OUTPUT_DISABLED = 0,
+ // idle
+ OUTPUT_IDLE,
+ // excess power sent to load
+ OUTPUT_ROUTING,
+ // full power sent to load through relay (manual trigger)
+ OUTPUT_BYPASS_MANUAL,
+ // full power sent to load through relay (auto trigger)
+ OUTPUT_BYPASS_AUTO
+ };
+
+ typedef std::function RouterOutputStateCallback;
+
+ class RouterOutputConfigClass {
+ public:
+ bool isAutoDimmerEnabled(const char* name) const;
+ uint8_t getDimmerLevelLimit(const char* name) const;
+ bool isAutoBypassEnabled(const char* name) const;
+ uint8_t getAutoStartTemperature(const char* name) const;
+ uint8_t getAutoStopTemperature(const char* name) const;
+ String getAutoStartTime(const char* name) const;
+ String getAutoStopTime(const char* name) const;
+ String getWeekDays(const char* name) const;
+ };
+
+ class RouterOutput {
+ public:
+ RouterOutput(const char* name, Dimmer* dimmer, TemperatureSensor* temperatureSensor, Relay* relay) : _name(name),
+ _dimmer(dimmer),
+ _temperatureSensor(temperatureSensor),
+ _relay(relay) {}
+
+ void autoBypass();
+ void applyDimmerLimit();
+
+ const char* getName() const { return _name; }
+ RouterOutputState getState() const;
+ const char* getStateString() const;
+ bool isEnabled() const { return _dimmer->isEnabled(); }
+ const Dimmer* getDimmer() const { return _dimmer; }
+ const TemperatureSensor* getTemperatureSensor() const { return _temperatureSensor; }
+ const Relay* getBypassRelay() const { return _relay; }
+
+ void listen(RouterOutputStateCallback callback) { _callback = callback; }
+
+ bool isBypassRelayOn() const { return _relay->isEnabled() ? _relay->isOn() : _dimmer->isOn(); }
+ bool isBypassRelayEnabled() const { return _relay->isEnabled() || _dimmer->isEnabled(); }
+ bool tryBypassRelayToggle() { return tryBypassRelayState(!isBypassRelayOn()); }
+ bool tryBypassRelayState(bool state);
+ // level: 0-100 (%)
+ bool tryDimmerLevel(uint8_t level);
+
+ float getResistance() const;
+
+ void toJson(const JsonObject& root) const;
+
+ private:
+ const char* _name;
+ Dimmer* _dimmer;
+ const TemperatureSensor* _temperatureSensor;
+ Relay* _relay;
+ bool _autoBypassEnabled = false;
+ RouterOutputStateCallback _callback = nullptr;
+
+ private:
+ void _setBypassRelay(bool state);
+ };
+
+ extern RouterOutputConfigClass RouterOutputConfig;
+} // namespace Mycila
diff --git a/lib/MycilaRouterOutput/library.properties b/lib/MycilaRouterOutput/library.properties
new file mode 100644
index 00000000..1758f57f
--- /dev/null
+++ b/lib/MycilaRouterOutput/library.properties
@@ -0,0 +1,5 @@
+name=MycilaRouterOutput
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/lib/MycilaSystem/LICENSE b/lib/MycilaSystem/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaSystem/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaSystem/MycilaSystem.cpp b/lib/MycilaSystem/MycilaSystem.cpp
new file mode 100644
index 00000000..b9f2db0b
--- /dev/null
+++ b/lib/MycilaSystem/MycilaSystem.cpp
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+#include
+
+#include
+#include
+#include
+
+#define TAG "SYSTEM"
+
+#define KEY_BOOTS "boots"
+#define KEY_RESETS "resets"
+
+#ifndef MYCILA_NVM_RESET_BOOT_DELAY
+#define MYCILA_NVM_RESET_BOOT_DELAY 3
+#endif
+
+void Mycila::SystemClass::begin() {
+ Logger.info(TAG, "Initializing File System...");
+ nvs_flash_init();
+ if (LittleFS.begin(false))
+ Logger.debug(TAG, "File System initialized");
+ else {
+ Logger.error(TAG, "Failed. Trying to format...");
+ if (LittleFS.begin(true))
+ Logger.info(TAG, "Successfully formatted and initialized");
+ else
+ Logger.error(TAG, "Failed to format");
+ }
+
+ Preferences prefs;
+ prefs.begin(TAG, false);
+
+ _boots = (prefs.isKey(KEY_BOOTS) ? prefs.getULong(KEY_BOOTS, 0) : 0) + 1;
+ prefs.putULong(KEY_BOOTS, _boots);
+ Logger.debug(TAG, "Booted %llu times", _boots);
+
+#ifdef MYCILA_BOOT_WAIT_FOR_RESET
+ const int count = (prefs.isKey(KEY_RESETS) ? prefs.getInt(KEY_RESETS, 0) : 0) + 1;
+ prefs.putInt(KEY_RESETS, count);
+ if (count >= 3) {
+ prefs.end();
+ reset();
+ } else {
+ Logger.warn(TAG, "WAITING FOR HARD RESET...");
+ for (uint32_t d = 0; d < MYCILA_NVM_RESET_BOOT_DELAY * 1000UL; d += 500) {
+ delay(500);
+ }
+ prefs.remove(KEY_RESETS);
+ Logger.debug(TAG, "No hard reset");
+ }
+#endif
+
+ prefs.end();
+}
+
+void Mycila::SystemClass::reset() {
+ Logger.debug(TAG, "Triggering System Reset...");
+ nvs_flash_erase();
+ nvs_flash_init();
+ esp_restart();
+}
+
+void Mycila::SystemClass::restart(uint32_t delayMillisBeforeRestart) {
+ Logger.debug(TAG, "Triggering System Restart...");
+ if (delayMillisBeforeRestart == 0)
+ esp_restart();
+ else {
+ _delayedTask.once_ms(delayMillisBeforeRestart, esp_restart);
+ }
+}
+
+const Mycila::SystemMemory Mycila::SystemClass::getMemory() const {
+ multi_heap_info_t info;
+ heap_caps_get_info(&info, MALLOC_CAP_INTERNAL);
+ return {
+ .total = info.total_free_bytes + info.total_allocated_bytes,
+ .used = info.total_allocated_bytes,
+ .free = info.total_free_bytes,
+ .usage = round(static_cast(info.total_allocated_bytes) / static_cast(info.total_free_bytes + info.total_allocated_bytes) * 10000) / 100};
+}
+
+void Mycila::SystemClass::toJson(const JsonObject& root) const {
+ SystemMemory memory = getMemory();
+ esp_chip_info_t chip_info;
+ esp_chip_info(&chip_info);
+ root["boots"] = _boots;
+ root["chip_cores"] = chip_info.cores;
+ root["chip_model"] = ESP.getChipModel();
+ root["chip_revision"] = chip_info.revision;
+ root["cpu_freq"] = ESP.getCpuFreqMHz();
+ root["heap_total"] = memory.total;
+ root["heap_usage"] = memory.usage;
+ root["heap_used"] = memory.used;
+ root["uptime"] = getUptime();
+}
+
+namespace Mycila {
+ SystemClass System;
+} // namespace Mycila
diff --git a/lib/MycilaSystem/MycilaSystem.h b/lib/MycilaSystem/MycilaSystem.h
new file mode 100644
index 00000000..b12ff973
--- /dev/null
+++ b/lib/MycilaSystem/MycilaSystem.h
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+namespace Mycila {
+ typedef struct {
+ uint32_t total;
+ uint32_t used;
+ uint32_t free;
+ float usage;
+ } SystemMemory;
+
+ class SystemClass {
+ public:
+ void begin();
+
+ void reset();
+ void restart(uint32_t delayMillisBeforeRestart = 0);
+
+ inline int64_t getUptime() const { return esp_timer_get_time() / (int64_t)1000000; }
+ const SystemMemory getMemory() const;
+ uint32_t getBootCount() const { return _boots; }
+
+ void toJson(const JsonObject& root) const;
+
+ private:
+ uint32_t _boots = 0;
+ Ticker _delayedTask;
+ };
+
+ extern SystemClass System;
+} // namespace Mycila
diff --git a/lib/MycilaSystem/library.properties b/lib/MycilaSystem/library.properties
new file mode 100644
index 00000000..1646a9d2
--- /dev/null
+++ b/lib/MycilaSystem/library.properties
@@ -0,0 +1,5 @@
+name=MycilaSystem
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/lib/MycilaTaskManager/LICENSE b/lib/MycilaTaskManager/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaTaskManager/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaTaskManager/MycilaTaskManager.h b/lib/MycilaTaskManager/MycilaTaskManager.h
new file mode 100644
index 00000000..2cc74db5
--- /dev/null
+++ b/lib/MycilaTaskManager/MycilaTaskManager.h
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+
+#ifdef MYCILA_TASK_MANAGER_JSON_SUPPORT
+#include
+#endif
+
+#define MYCILA_TASK_MANAGER_VERSION "1.0.0"
+#define MYCILA_TASK_MANAGER_VERSION_MAJOR 1
+#define MYCILA_TASK_MANAGER_VERSION_MINOR 0
+#define MYCILA_TASK_MANAGER_VERSION_REVISION 0
+
+namespace Mycila {
+ namespace TimeUnit {
+ constexpr uint32_t MICROSECONDS = 1UL;
+ constexpr uint32_t MILLISECONDS = 1000UL;
+ constexpr uint32_t SECONDS = 1000000UL;
+ constexpr uint32_t MINUTES = 60 * SECONDS;
+ constexpr uint32_t HOURS = 60 * MINUTES;
+ constexpr uint32_t DAYS = 24 * HOURS;
+ } // namespace TimeUnit
+
+ enum class TaskType {
+ // once enabled, the task will run once and then disable itself
+ ONCE,
+ // the task will run at the specified interval as long as it is enabled
+ FOREVER
+ };
+
+ class Task;
+
+ typedef std::function TaskFunction;
+ typedef std::function TaskPredicate;
+ typedef std::function TaskIntervalSupplier;
+ typedef std::function TaskDoneCallback;
+
+ class Task {
+ public:
+ Task(const char* name, TaskFunction fn, TaskType type = TaskType::FOREVER, uint32_t intervalMicros = 0, bool enabled = false) : _name(name),
+ _fn(fn),
+ _type(type) {
+ assert(_fn);
+ setInterval(intervalMicros);
+ setEnabled(enabled);
+ }
+
+ const char* getName() const { return _name; }
+ TaskType getType() const { return _type; }
+ uint32_t getInterval() const { return _intervalSupplier ? _intervalSupplier() : 0; }
+ bool isEnabled() const { return _enabledPredicate && _enabledPredicate(); }
+ bool isRunning() const { return _running; }
+ bool isEarlyRunRequested() const { return _requestEarlyRun; }
+ bool isDebug() const { return _debugPredicate && _debugPredicate(); }
+ uint32_t getLastStart() const { return _lastStart; }
+ uint32_t getLastEnd() const { return _lastEnd; }
+ uint32_t getLastRuntime(uint32_t unit = TimeUnit::MICROSECONDS) const { return _lastRuntime / unit; }
+ bool shouldRun() const {
+ if (!isEnabled())
+ return false;
+ const uint32_t itvl = getInterval();
+ return itvl == 0 || isEarlyRunRequested() || micros() - getLastEnd() >= itvl;
+ }
+
+ Task& setEnabled(bool enabled) { return enabled ? resume() : pause(); }
+ Task& pause() {
+ _enabledPredicate = nullptr;
+ return *this;
+ }
+ Task& resume() {
+ _enabledPredicate = []() {
+ return true;
+ };
+ return *this;
+ }
+ Task& when(TaskPredicate predicate) {
+ _enabledPredicate = predicate;
+ return *this;
+ }
+
+ Task& setInterval(uint32_t intervalMicros) {
+ if (intervalMicros == 0) {
+ _intervalSupplier = nullptr;
+ }
+ _intervalSupplier = [intervalMicros]() {
+ return intervalMicros;
+ };
+ return *this;
+ }
+ Task& interval(TaskIntervalSupplier supplier) {
+ _intervalSupplier = supplier;
+ return *this;
+ }
+
+ Task& setData(void* params) {
+ _params = params;
+ return *this;
+ }
+
+ Task& debug() {
+ _debugPredicate = []() {
+ return true;
+ };
+ return *this;
+ }
+ Task& debugIf(TaskPredicate predicate) {
+ _debugPredicate = predicate;
+ return *this;
+ }
+
+ bool tryRun() {
+ if (!isEnabled())
+ return false;
+ const uint32_t itvl = getInterval();
+ const uint32_t now = micros();
+ if (itvl != 0 && !isEarlyRunRequested() && now - getLastEnd() < itvl)
+ return false;
+ _run(now);
+ return true;
+ }
+
+ Task& forceRun() {
+ _run(micros());
+ return *this;
+ }
+
+ Task& requestEarlyRun() {
+ _requestEarlyRun = true;
+ return *this;
+ }
+
+ Task& onDone(TaskDoneCallback doneCallback) {
+ _onDone = doneCallback;
+ return *this;
+ }
+
+#ifdef MYCILA_TASK_MANAGER_JSON_SUPPORT
+ void toJson(const JsonObject& root) const {
+ root["debug"] = isDebug();
+ root["earlyRunRequested"] = isEarlyRunRequested();
+ root["enabled"] = isEnabled();
+ root["interval"] = getInterval();
+ root["lastEnd"] = getLastEnd();
+ root["lastRuntime"] = getLastRuntime();
+ root["lastStart"] = getLastStart();
+ root["name"] = getName();
+ root["running"] = isRunning();
+ root["type"] = getType() == TaskType::ONCE ? "ONCE" : "FOREVER";
+ }
+#endif
+
+ private:
+ const char* _name;
+ const TaskFunction _fn;
+ bool _requestEarlyRun = false;
+ bool _running = false;
+ TaskDoneCallback _onDone = nullptr;
+ TaskIntervalSupplier _intervalSupplier = nullptr;
+ TaskPredicate _debugPredicate = nullptr;
+ TaskPredicate _enabledPredicate = nullptr;
+ TaskType _type;
+ uint32_t _lastEnd = 0;
+ uint32_t _lastRuntime = 0;
+ uint32_t _lastStart = 0;
+ void* _params = nullptr;
+
+ private:
+ void _run(uint32_t now) {
+ _lastStart = now;
+ _running = true;
+ _fn(_params);
+ _running = false;
+ _requestEarlyRun = false;
+ const uint32_t end = micros();
+ _lastEnd = end;
+ _lastRuntime = end - now;
+ if (_type == TaskType::ONCE)
+ pause();
+ if (isDebug())
+ ESP_LOGD("TASK", "Finished '%s' in %u us", _name, (_lastEnd - _lastStart));
+ if (_onDone)
+ _onDone(*this);
+ }
+ };
+
+ class TaskManagerClass {
+ public:
+ void loop();
+
+ private:
+ std::vector _tasks;
+ };
+
+ extern TaskManagerClass TaskManager;
+} // namespace Mycila
diff --git a/lib/MycilaTaskManager/library.properties b/lib/MycilaTaskManager/library.properties
new file mode 100644
index 00000000..ff78cbaf
--- /dev/null
+++ b/lib/MycilaTaskManager/library.properties
@@ -0,0 +1,5 @@
+name=MycilaTaskManager
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/lib/MycilaTemperatureSensor/LICENSE b/lib/MycilaTemperatureSensor/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaTemperatureSensor/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaTemperatureSensor/MycilaTemperatureSensor.cpp b/lib/MycilaTemperatureSensor/MycilaTemperatureSensor.cpp
new file mode 100644
index 00000000..d973b0cd
--- /dev/null
+++ b/lib/MycilaTemperatureSensor/MycilaTemperatureSensor.cpp
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+#include
+
+#define TAG "DS18B20"
+
+void Mycila::TemperatureSensor::begin(const uint8_t pin, uint32_t expirationDelay) {
+ if (_enabled)
+ return;
+
+ if (GPIO_IS_VALID_GPIO(pin)) {
+ _pin = (gpio_num_t)pin;
+ } else {
+ Logger.error(TAG, "Disable Temperature Sensor '%s': Invalid pin: %u", name, _pin);
+ _pin = GPIO_NUM_NC;
+ return;
+ }
+
+ _oneWire.begin(_pin);
+ _dallas.setOneWire(&_oneWire);
+ _dallas.begin();
+ if (_dallas.getDS18Count() == 0) {
+ Logger.error(TAG, "Disable Temperature Sensor '%s': No DS18B20 sensor found on pin: %u", name, _pin);
+ return;
+ } else {
+ _dallas.setWaitForConversion(false);
+ _dallas.requestTemperatures();
+ }
+
+ Logger.debug(TAG, "Enable Temperature Sensor '%s'...", name);
+ Logger.debug(TAG, "- Pin: %u", _pin);
+ Logger.debug(TAG, "- Expiration: %u seconds", expirationDelay);
+
+ _expirationDelay = expirationDelay;
+ _enabled = true;
+}
+
+void Mycila::TemperatureSensor::end() {
+ if (_enabled) {
+ Logger.debug(TAG, "Disable Temperature Sensor '%s'...", name);
+ _enabled = false;
+ _temperature = 0;
+ _lastUpdate = 0;
+ _pin = GPIO_NUM_NC;
+ }
+}
+
+void Mycila::TemperatureSensor::read() {
+ if (!_enabled)
+ return;
+ float read = _dallas.getTempCByIndex(0);
+ _dallas.requestTemperatures();
+ if (!isnan(read) && read > 0) {
+ read = round(read * 100) / 100;
+ Logger.debug(TAG, "Temperature Sensor '%s': %.02f °C", name, read);
+ _lastUpdate = millis();
+ if (abs(read - _temperature) > 0.2 || !isValid()) {
+ _temperature = read;
+ if (_callback)
+ _callback(name, _temperature);
+ }
+ }
+}
+
+String Mycila::TemperatureSensor::getTemperatureAsString() const {
+ if (!_enabled || !isValid())
+ return "??.??";
+ char buffer[6];
+ snprintf(buffer, sizeof(buffer), "%5.2f", _temperature);
+ return buffer;
+}
+
+void Mycila::TemperatureSensor::toJson(const JsonObject& root) const {
+ root["enabled"] = _enabled;
+ root["temperature"] = _temperature;
+ root["valid"] = isValid();
+}
diff --git a/lib/MycilaTemperatureSensor/MycilaTemperatureSensor.h b/lib/MycilaTemperatureSensor/MycilaTemperatureSensor.h
new file mode 100644
index 00000000..1291ba16
--- /dev/null
+++ b/lib/MycilaTemperatureSensor/MycilaTemperatureSensor.h
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+#include
+
+#ifndef MYCILA_TEMPERATURE_EXPIRATION_DELAY
+#define MYCILA_TEMPERATURE_EXPIRATION_DELAY 60
+#endif
+
+namespace Mycila {
+ typedef std::function TemperatureChangeCallback;
+ class TemperatureSensor {
+ public:
+ explicit TemperatureSensor(const char* name) : name(name) {}
+ ~TemperatureSensor() { end(); }
+
+ void begin(const uint8_t pin, uint32_t expirationDelay = 0);
+ void end();
+
+ void read();
+
+ void listen(TemperatureChangeCallback callback) { _callback = callback; }
+
+ float getTemperature() const { return _temperature; }
+ bool isEnabled() const { return _enabled; }
+ bool isValid() const { return _expirationDelay == 0 ? _enabled : (millis() - _lastUpdate < _expirationDelay * 1000); }
+ uint32_t getLastUpdate() const { return _lastUpdate; }
+ uint32_t getExpirationDelay() const { return _expirationDelay; }
+
+ String getTemperatureAsString() const;
+ gpio_num_t getPin() const { return _pin; };
+
+ void toJson(const JsonObject& root) const;
+
+ public:
+ const char* name;
+
+ private:
+ OneWire _oneWire;
+ DallasTemperature _dallas;
+ bool _enabled = false;
+ gpio_num_t _pin = GPIO_NUM_NC;
+ float _temperature = 0;
+ uint32_t _lastUpdate = 0;
+ uint32_t _expirationDelay = 0;
+ TemperatureChangeCallback _callback = nullptr;
+ };
+} // namespace Mycila
diff --git a/lib/MycilaTemperatureSensor/library.properties b/lib/MycilaTemperatureSensor/library.properties
new file mode 100644
index 00000000..78387571
--- /dev/null
+++ b/lib/MycilaTemperatureSensor/library.properties
@@ -0,0 +1,5 @@
+name=MycilaTemperatureSensor
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/lib/MycilaTime/LICENSE b/lib/MycilaTime/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaTime/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaTime/MycilaTime.h b/lib/MycilaTime/MycilaTime.h
new file mode 100644
index 00000000..6ac69860
--- /dev/null
+++ b/lib/MycilaTime/MycilaTime.h
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+
+#include
+#include
+
+namespace Mycila {
+ class Time {
+ public:
+ static String toISO8601Str(time_t unixTime) {
+ if (unixTime == 0)
+ return emptyString;
+ char buffer[21];
+ strftime(buffer, sizeof(buffer), "%FT%TZ", gmtime(&unixTime));
+ return buffer;
+ }
+
+ static String toLocalStr(time_t unixTime) {
+ if (unixTime == 0)
+ return emptyString;
+ struct tm timeInfo;
+ localtime_r(&unixTime, &timeInfo);
+ char buffer[20];
+ strftime(buffer, sizeof(buffer), "%F %T", &timeInfo);
+ return buffer;
+ }
+
+ static time_t getUnixTime() {
+ time_t now;
+ struct tm timeinfo;
+ if (!NTP.isSynced() || !getLocalTime(&timeinfo, 5))
+ return 0;
+ time(&now);
+ return now;
+ }
+
+ inline static String getISO8601Str() { return toISO8601Str(getUnixTime()); }
+
+ inline static String getLocalStr() { return toLocalStr(getUnixTime()); }
+
+ static int toMinutes(const String& time, char sep = ':') {
+ int i = time.indexOf(sep);
+ if (i < 0)
+ return i;
+ return time.substring(0, i).toInt() * 60 + time.substring(i + 1).toInt();
+ }
+
+ static int timeInRange(struct tm* timeInfo, const String& start, const String& end, char sep = ':') {
+ const int startMinutes = toMinutes(start, sep);
+ if (startMinutes == -1)
+ return -1;
+
+ const int stopMinutes = toMinutes(end, sep);
+ if (stopMinutes == -1)
+ return -1;
+
+ if (startMinutes == stopMinutes)
+ return false; // range is empty
+
+ const uint16_t timeMinutes = timeInfo->tm_hour * 60 + timeInfo->tm_min;
+
+ // cases:
+ // startMinutes < stopMinutes : i.e. 06:00 -> 22:00
+ // startMinutes > stopMinutes : i.e. 22:00 -> 06:00
+ return (startMinutes < stopMinutes && timeMinutes >= startMinutes && timeMinutes < stopMinutes) || (startMinutes > stopMinutes && (timeMinutes >= startMinutes || timeMinutes < stopMinutes));
+ }
+ };
+
+} // namespace Mycila
diff --git a/lib/MycilaTime/library.properties b/lib/MycilaTime/library.properties
new file mode 100644
index 00000000..622e8185
--- /dev/null
+++ b/lib/MycilaTime/library.properties
@@ -0,0 +1,5 @@
+name=MycilaTime
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/lib/MycilaZeroCrossDetection/LICENSE b/lib/MycilaZeroCrossDetection/LICENSE
new file mode 100644
index 00000000..2b5457c6
--- /dev/null
+++ b/lib/MycilaZeroCrossDetection/LICENSE
@@ -0,0 +1,10 @@
+The MIT License (MIT)
+---------------------
+
+Copyright © 2023-2024, Mathieu Carbou
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/MycilaZeroCrossDetection/MycilaZeroCrossDetection.cpp b/lib/MycilaZeroCrossDetection/MycilaZeroCrossDetection.cpp
new file mode 100644
index 00000000..a025183f
--- /dev/null
+++ b/lib/MycilaZeroCrossDetection/MycilaZeroCrossDetection.cpp
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+#include
+
+#include
+#include
+
+#define TAG "ZCD"
+
+void Mycila::ZeroCrossDetectionClass::begin(const uint8_t pin, const uint8_t frequency) {
+ if (_enabled)
+ return;
+
+ if (GPIO_IS_VALID_GPIO(pin)) {
+ _pin = (gpio_num_t)pin;
+ } else {
+ Logger.error(TAG, "Invalid Zero-Cross Detection pin: %u", _pin);
+ _pin = GPIO_NUM_NC;
+ return;
+ }
+
+ Logger.debug(TAG, "Enable Zero-Cross Detection...");
+ Logger.debug(TAG, "- Pin: %u", _pin);
+ Logger.debug(TAG, "- Grid Frequency: %u Hz", frequency);
+
+#if defined(ESP32) && defined(FILTER_INT_PERIOD)
+ // https://github.com/fabianoriccardi/dimmable-light/wiki/Notes-about-specific-architectures#interrupt-issue
+ Thyristor::semiPeriodShrinkMargin = 400;
+#endif
+ DimmableLightLinearized::setFrequency(frequency);
+ DimmableLightLinearized::frequencyMonitorAlwaysOn(true);
+ DimmableLightLinearized::setSyncPin(_pin);
+ DimmableLightLinearized::begin();
+
+ _enabled = true;
+}
+
+void Mycila::ZeroCrossDetectionClass::end() {
+ if (_enabled) {
+ Logger.debug(TAG, "Disable Zero-Cross Detection...");
+ _enabled = false;
+ DimmableLightLinearized::setFrequency(0);
+ _pin = GPIO_NUM_NC;
+ }
+}
+
+float Mycila::ZeroCrossDetectionClass::getFrequency() { return _enabled ? DimmableLightLinearized::getDetectedFrequency() : 0; }
+
+void Mycila::ZeroCrossDetectionClass::toJson(const JsonObject& root) {
+ root["enabled"] = _enabled;
+ root["frequency"] = getFrequency();
+}
+
+namespace Mycila {
+ ZeroCrossDetectionClass ZCD;
+} // namespace Mycila
diff --git a/lib/MycilaZeroCrossDetection/MycilaZeroCrossDetection.h b/lib/MycilaZeroCrossDetection/MycilaZeroCrossDetection.h
new file mode 100644
index 00000000..420251f0
--- /dev/null
+++ b/lib/MycilaZeroCrossDetection/MycilaZeroCrossDetection.h
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+
+namespace Mycila {
+ class ZeroCrossDetectionClass {
+ public:
+ void begin(const uint8_t pin, const uint8_t frequency = 50);
+ void end();
+
+ bool isEnabled() const { return _enabled; }
+ gpio_num_t getPin() const { return _pin; }
+ // if activated, the monitored frequency based on zero-cross detection. Can be close to 50 or 60 Hz or more depending on the ZCD module.
+ float getFrequency();
+
+ void toJson(const JsonObject& root);
+
+ private:
+ bool _enabled = false;
+ gpio_num_t _pin = GPIO_NUM_NC;
+ };
+
+ extern ZeroCrossDetectionClass ZCD;
+} // namespace Mycila
diff --git a/lib/MycilaZeroCrossDetection/library.properties b/lib/MycilaZeroCrossDetection/library.properties
new file mode 100644
index 00000000..7af734bf
--- /dev/null
+++ b/lib/MycilaZeroCrossDetection/library.properties
@@ -0,0 +1,5 @@
+name=MycilaZeroCrossDetection
+version=1.0.0
+author=Mathieu Carbou
+maintainer=Mathieu Carbou
+architectures=esp32
diff --git a/partitions.csv b/partitions.csv
new file mode 100644
index 00000000..437d3025
--- /dev/null
+++ b/partitions.csv
@@ -0,0 +1,6 @@
+# Name, Type, SubType, Offset, Size, Flags
+nvs, data, nvs, 0x9000, 0x5000,
+otadata, data, ota, 0xe000, 0x2000,
+app0, app, ota_0, 0x10000, 0x1F0000,
+app1, app, ota_1, 0x200000, 0x1F0000,
+spiffs, data, spiffs, 0x3F0000, 0x10000,
diff --git a/pio/data.py b/pio/data.py
new file mode 100644
index 00000000..5d7267a0
--- /dev/null
+++ b/pio/data.py
@@ -0,0 +1,10 @@
+import gzip
+import os
+
+os.makedirs('.pio/data', exist_ok=True)
+
+for filename in ['config.html', 'logo-icon.png', 'logo.png']:
+ with open('data/' + filename, 'rb') as f_in:
+ with gzip.open('.pio/data/' + filename + '.gz', 'wb') as f_out:
+ print('gzip \'data/' + filename + '\' to \'.pio/data/' + filename + '.gz\'')
+ f_out.writelines(f_in)
diff --git a/pio/factory.py b/pio/factory.py
new file mode 100644
index 00000000..6358072d
--- /dev/null
+++ b/pio/factory.py
@@ -0,0 +1,87 @@
+# Part of ESPEasy build toolchain.
+#
+# Combines separate bin files with their respective offsets into a single file
+# This single file must then be flashed to an ESP32 node with 0 offset.
+#
+# Original implementation: Bartłomiej Zimoń (@uzi18)
+# Maintainer: Gijs Noorlander (@TD-er)
+#
+# Special thanks to @Jason2866 (Tasmota) for helping debug flashing to >4MB flash
+# Thanks @jesserockz (esphome) for adapting to use esptool.py with merge_bin
+#
+# Typical layout of the generated file:
+# Offset | File
+# 0x1000 | bootloader.bin
+# 0x8000 | partitions.bin
+# 0xe000 | boot_app0.bin
+# 0x10000 | firmware.bin
+# 0x3F0000 | littlefs.bin
+
+Import("env")
+
+platform = env.PioPlatform()
+
+import sys
+import subprocess
+from os.path import join
+
+sys.path.append(join(platform.get_package_dir("tool-esptoolpy")))
+import esptool
+
+def esp32_create_combined_bin(source, target, env):
+ print("Generating combined binary for serial flashing")
+
+ # subprocess.run(["pio", "run", "-e", env.get("PIOENV"), "-t", "buildfs"])
+
+ # The offset from begin of the file where the app0 partition starts
+ # This is defined in the partition .csv file
+ app_offset = 0x10000
+ # offset for spdiff partition
+ # fs_offset = 0x3F0000
+
+ new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.factory.bin")
+ sections = env.subst(env.get("FLASH_EXTRA_IMAGES"))
+ firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin")
+ # fs_name = env.subst("$BUILD_DIR/littlefs.bin")
+ chip = env.get("BOARD_MCU")
+ flash_size = env.BoardConfig().get("upload.flash_size")
+ flash_freq = env.BoardConfig().get("build.f_flash", '40m')
+ flash_freq = flash_freq.replace('000000L', 'm')
+ flash_mode = env.BoardConfig().get("build.flash_mode", "dio")
+ memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi")
+ if flash_mode == "qio" or flash_mode == "qout":
+ flash_mode = "dio"
+ if memory_type == "opi_opi" or memory_type == "opi_qspi":
+ flash_mode = "dout"
+ cmd = [
+ "--chip",
+ chip,
+ "merge_bin",
+ "-o",
+ new_file_name,
+ "--flash_mode",
+ flash_mode,
+ "--flash_freq",
+ flash_freq,
+ "--flash_size",
+ flash_size,
+ ]
+
+ print(" Offset | File")
+ for section in sections:
+ sect_adr, sect_file = section.split(" ", 1)
+ print(f" - {sect_adr} | {sect_file}")
+ cmd += [sect_adr, sect_file]
+
+ print(f" - {hex(app_offset)} | {firmware_name}")
+ cmd += [hex(app_offset), firmware_name]
+
+ # print(f" - {hex(fs_offset)} | {fs_name}")
+ # cmd += [hex(fs_offset), fs_name]
+
+ print('Using esptool.py arguments: %s' % ' '.join(cmd))
+
+ esptool.main(cmd)
+
+
+env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_create_combined_bin)
\ No newline at end of file
diff --git a/pio/version.py b/pio/version.py
new file mode 100644
index 00000000..938aa5c6
--- /dev/null
+++ b/pio/version.py
@@ -0,0 +1,40 @@
+import subprocess
+import os
+from datetime import datetime, timezone
+
+def get_build_flag():
+ ret = subprocess.run(["git", "rev-parse", "HEAD"], stdout=subprocess.PIPE, text=True) #Uses any tags
+ full_hash = ret.stdout.strip()
+ ret = subprocess.run(["git", "symbolic-ref", "--short", "HEAD"], stdout=subprocess.PIPE, text=True) # retrieve branch name
+ branch = ret.stdout.strip()
+ short_hash = full_hash[:8]
+
+ build_version = branch + "_" + short_hash
+
+ # get the GITHUB_REF_NAME
+ ref_name = os.environ.get('GITHUB_REF_NAME')
+ if ref_name:
+ if ref_name.startswith("v"):
+ build_version = ref_name
+ else:
+ build_version = ref_name + "_" + short_hash
+
+ # Check if the source has been modified since the last commit
+ ret = subprocess.run(["git", "diff-index", "--quiet", "HEAD", "--"], stdout=subprocess.PIPE, text=True)
+ if ret.returncode != 0:
+ build_version += "_modified"
+
+ build_flags = "-D BUILD_TAG=\\\"" + build_version + "\\\" " + "-D BUILD_HASH=\\\"" + short_hash + "\\\" " + "-D BUILD_TIMESAMP=\\\"" + datetime.now(timezone.utc).isoformat() + "\\\""
+
+ return build_flags
+
+build_flags = get_build_flag()
+
+if "SCons.Script" == __name__:
+ print ("Firmware Revision: " + build_flags)
+ Import("env")
+ env.Append(
+ BUILD_FLAGS=[get_build_flag()]
+ )
+elif "__main__" == __name__:
+ print(build_flags)
diff --git a/platformio.ini b/platformio.ini
new file mode 100644
index 00000000..e9afc406
--- /dev/null
+++ b/platformio.ini
@@ -0,0 +1,957 @@
+; PlatformIO Project Configuration File
+;
+; Build options: build flags, source filter
+; Upload options: custom upload port, speed and extra flags
+; Library options: dependencies, extra library storages
+; Advanced options: extra scripting
+;
+; Please visit documentation for the other options and examples
+; https://docs.platformio.org/page/projectconf.html
+
+[platformio]
+name = YaSolR
+extra_configs = platformio_override.ini
+
+[env]
+framework = arduino
+platform = espressif32@6.5.0
+board = esp32dev
+monitor_filters = esp32_exception_decoder, log2file
+monitor_speed = 115200
+upload_protocol = esptool
+upload_speed = 921600
+extra_scripts =
+ pre:pio/data.py
+ pre:pio/version.py
+ post:pio/factory.py
+lib_compat_mode = strict
+lib_ldf_mode = deep+
+; https://registry.platformio.org/
+lib_deps =
+ ArduinoOTA
+ bertmelis/espMqttClient @ 1.6.0
+ bblanchon/ArduinoJson @ 7.0.3
+ bblanchon/StreamUtils @ 1.8.0
+ esp-arduino-libs/ESP32_Button @ 0.0.1
+ esphome/AsyncTCP-esphome @ 2.1.2
+ mathieucarbou/ESP Async WebServer @ 2.7.0
+ mathieucarbou/MycilaHADiscovery @ 1.0.1
+ mathieucarbou/MycilaConfig @ 1.4.0
+ mathieucarbou/MycilaEasyDisplay @ 1.0.1
+ mathieucarbou/MycilaESPConnect @ 3.2.1
+ mathieucarbou/MycilaJSY @ 3.3.2
+ mathieucarbou/MycilaLogger @ 2.1.0
+ mathieucarbou/MycilaMQTT @ 1.3.0
+ mathieucarbou/MycilaNTP @ 2.1.0
+ mathieucarbou/MycilaRelay @ 2.0.0
+ mathieucarbou/MycilaTaskMonitor @ 2.0.0
+ milesburton/DallasTemperature @ 3.11.0
+ olikraus/U8g2 @ 2.35.9
+ paulstoffregen/OneWire @ 2.3.8
+ ; fabianoriccardi/Dimmable Light for Arduino @ 1.6.0
+ https://github.com/mathieucarbou/fabianoriccardi-dimmable-light#fixes
+build_flags =
+ -D BUILD_NAME=\"$PIOENV\"
+ -Wall -Wextra
+ ; -Werror
+ ; Have to remove -Werror because of
+ ; https://github.com/espressif/arduino-esp32/issues/9044 and
+ ; https://github.com/espressif/arduino-esp32/issues/9045
+ -Wunused -Wmisleading-indentation -Wduplicated-cond -Wlogical-op -Wnull-dereference
+ -std=c++17
+ -std=gnu++17
+ -D ARDUINO_LOOP_STACK_SIZE=256*15
+ -D CONFIG_ASYNC_TCP_RUNNING_CORE=1
+ -D CONFIG_ASYNC_TCP_STACK_SIZE=256*15
+ -D CONFIG_ETH_ENABLED
+ -D DASH_DEFAULT_CARD_SIZE_LG=6
+ -D DASH_DEFAULT_CARD_SIZE_MD=6
+ -D DASH_DEFAULT_CARD_SIZE_SM=6
+ -D DASH_DEFAULT_CARD_SIZE_XL=6
+ -D DASH_DEFAULT_CARD_SIZE_XS=12
+ -D DASH_DEFAULT_CARD_SIZE_XXL=3
+ -D DASH_JSON_SIZE=512*4
+ -D DASH_MAX_WS_CLIENTS=3
+ -D ELEGANTOTA_USE_ASYNC_WEBSERVER=1
+ -D EMC_ALLOW_NOT_CONNECTED_PUBLISH=0
+ -D EMC_RX_BUFFER_SIZE=512
+ -D EMC_TASK_STACK_SIZE=256*12
+ -D EMC_TX_BUFFER_SIZE=512
+ -D EMC_TX_TIMEOUT=5000
+ -D EMC_WAIT_FOR_CONNACK=0
+ -D FILTER_INT_PERIOD
+ -D MONITOR_FREQUENCY
+ -D MYCILA_CONFIG_JSON_SUPPORT
+ -D MYCILA_JSY_ASYNC_STACK_SIZE=256*6
+ -D MYCILA_JSY_JSON_SUPPORT
+ -D MYCILA_NTP_JSON_SUPPORT
+ -D MYCILA_RELAY_JSON_SUPPORT
+ -D MYCILA_TASK_MANAGER_JSON_SUPPORT
+ -D MYCILA_TASK_MONITOR_JSON_SUPPORT
+ -D MYCILA_TASK_MONITOR_STACK_FREE_MAX=1024
+ -D MYCILA_TASK_MONITOR_STACK_FREE_MIN=256
+ -D NETWORK_FREQ_RUNTIME
+ -D WEBSERIAL_MAX_WS_CLIENTS=3
+ -D WS_MAX_QUEUED_MESSAGES=32
+ -D YASOLR_DISABLE_BROWNOUT_DETECTOR
+build_unflags =
+ -std=gnu++11
+board_build.partitions = partitions.csv
+board_build.filesystem = littlefs
+board_build.embed_files =
+ .pio/data/logo.png.gz
+ .pio/data/logo-icon.png.gz
+ .pio/data/config.html.gz
+
+; --------------------------------------------------------------------
+; RELEASES
+; --------------------------------------------------------------------
+
+[release]
+; https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-compiler-optimization-assertion-level
+build_flags =
+ -O2
+ -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO
+ -D NDEBUG
+ -D RELEASE=1
+
+[debug]
+build_flags =
+ -O0
+ -ggdb -ggdb3 -g3
+ -D CONFIG_ARDUHAL_LOG_COLORS
+ ; -D CONFIG_LOG_COLORS
+ -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
+ ; -D DEBUG
+ ; -D DEBUG_ESP_MQTT_CLIENT
+ ; -D ENABLE_DEBUG
+ ; -D ESPCONNECT_DEBUG
+ ; -D MYCILA_BOOT_WAIT_FOR_RESET
+ -D YASOLR_RELAY_PAUSE_DURATION=10
+ ; -D WEBSERIAL_DEBUG
+
+; --------------------------------------------------------------------
+; MODELS
+; --------------------------------------------------------------------
+
+[oss]
+build_flags = -D APP_VERSION_OSS
+lib_deps =
+ https://github.com/ayushsharma82/ElegantOTA
+lib_ignore =
+ ElegantOTAPro
+ ESPDASHPro
+ WebSerialLite
+
+[pro]
+build_flags = -D APP_VERSION_PRO
+lib_deps =
+lib_ignore =
+ ElegantOTA
+ ESPDASH
+
+[trial]
+build_flags =
+ ${pro.build_flags}
+ -D APP_VERSION_TRIAL
+ -D MYCILA_TRIAL_DURATION=259200
+lib_deps =
+ mathieucarbou/MycilaTrial @ 1.0.0
+lib_ignore =
+ ElegantOTA
+ ESPDASH
+
+; --------------------------------------------------------------------
+; SHORTCUTS
+; --------------------------------------------------------------------
+
+[unpin]
+build_flags =
+ -D YASOLR_BUTTON_PIN=-1
+ -D YASOLR_BUZZER_PIN=-1
+ -D YASOLR_DISPLAY_CLOCK_PIN=-1
+ -D YASOLR_DISPLAY_DATA_PIN=-1
+ -D YASOLR_JSY_RX_PIN=-1
+ -D YASOLR_JSY_TX_PIN=-1
+ -D YASOLR_LIGHTS_GREEN_PIN=-1
+ -D YASOLR_LIGHTS_RED_PIN=-1
+ -D YASOLR_LIGHTS_YELLOW_PIN=-1
+ -D YASOLR_OUTPUT1_DIMMER_PIN=-1
+ -D YASOLR_OUTPUT1_RELAY_PIN=-1
+ -D YASOLR_OUTPUT1_TEMP_PIN=-1
+ -D YASOLR_OUTPUT2_DIMMER_PIN=-1
+ -D YASOLR_OUTPUT2_RELAY_PIN=-1
+ -D YASOLR_OUTPUT2_TEMP_PIN=-1
+ -D YASOLR_RELAY1_PIN=-1
+ -D YASOLR_RELAY2_PIN=-1
+ -D YASOLR_SYSTEM_TEMP_PIN=-1
+ -D YASOLR_ZCD_PIN=-1
+
+
+; --------------------------------------------------------------------
+; ENVIRONMENTs
+; --------------------------------------------------------------------
+
+; esp32dev (defaul)
+
+[env:oss-esp32]
+build_type = release
+lib_deps =
+ ${env.lib_deps}
+ ${oss.lib_deps}
+lib_ignore =
+ ${env.lib_ignore}
+ ${oss.lib_ignore}
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${release.build_flags}
+
+[env:oss-esp32-debug]
+build_type = debug
+lib_deps =
+ ${env.lib_deps}
+ ${oss.lib_deps}
+lib_ignore =
+ ${env.lib_ignore}
+ ${oss.lib_ignore}
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${debug.build_flags}
+
+[env:pro-esp32]
+build_type = release
+lib_deps =
+ ${env.lib_deps}
+ ${pro.lib_deps}
+lib_ignore =
+ ${env.lib_ignore}
+ ${pro.lib_ignore}
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${release.build_flags}
+
+[env:pro-esp32-debug]
+build_type = debug
+lib_deps =
+ ${env.lib_deps}
+ ${pro.lib_deps}
+lib_ignore =
+ ${env.lib_ignore}
+ ${pro.lib_ignore}
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${debug.build_flags}
+
+[env:trial-esp32]
+build_type = release
+lib_deps =
+ ${env.lib_deps}
+ ${trial.lib_deps}
+lib_ignore =
+ ${env.lib_ignore}
+ ${trial.lib_ignore}
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${release.build_flags}
+
+[env:trial-esp32-debug]
+build_type = debug
+lib_deps =
+ ${env.lib_deps}
+ ${trial.lib_deps}
+lib_ignore =
+ ${env.lib_ignore}
+ ${trial.lib_ignore}
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${debug.build_flags}
+
+; nodemcu-32s
+
+[env:oss-esp32s]
+extends = env:oss-esp32
+board = nodemcu-32s
+
+[env:oss-esp32s-debug]
+extends = env:oss-esp32-debug
+board = nodemcu-32s
+
+[env:pro-esp32s]
+extends = env:pro-esp32
+board = nodemcu-32s
+
+[env:pro-esp32s-debug]
+extends = env:pro-esp32-debug
+board = nodemcu-32s
+
+[env:trial-esp32s]
+extends = env:trial-esp32
+board = nodemcu-32s
+
+[env:trial-esp32s-debug]
+extends = env:trial-esp32-debug
+board = nodemcu-32s
+
+; esp32c3
+
+[esp32c3]
+build_flags =
+ -D MYCILA_JSY_SERIAL=Serial1
+ -D YASOLR_BUTTON_PIN=10
+ -D YASOLR_BUZZER_PIN=18
+ -D YASOLR_DISPLAY_CLOCK_PIN=6
+ -D YASOLR_DISPLAY_DATA_PIN=7
+ -D YASOLR_JSY_RX_PIN=20
+ -D YASOLR_JSY_TX_PIN=21
+ -D YASOLR_LIGHTS_GREEN_PIN=-1
+ -D YASOLR_LIGHTS_RED_PIN=-1
+ -D YASOLR_LIGHTS_YELLOW_PIN=-1
+ -D YASOLR_OUTPUT1_DIMMER_PIN=1
+ -D YASOLR_OUTPUT1_RELAY_PIN=2
+ -D YASOLR_OUTPUT1_TEMP_PIN=0
+ -D YASOLR_OUTPUT2_DIMMER_PIN=8
+ -D YASOLR_OUTPUT2_RELAY_PIN=9
+ -D YASOLR_OUTPUT2_TEMP_PIN=5
+ -D YASOLR_RELAY1_PIN=20
+ -D YASOLR_RELAY2_PIN=21
+ -D YASOLR_SYSTEM_TEMP_PIN=4
+ -D YASOLR_ZCD_PIN=3
+
+[env:oss-esp32c3]
+extends = env:oss-esp32
+board = esp32-c3-devkitc-02
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${release.build_flags}
+ ${esp32c3.build_flags}
+
+[env:oss-esp32c3-debug]
+extends = env:oss-esp32-debug
+board = esp32-c3-devkitc-02
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${debug.build_flags}
+ ${esp32c3.build_flags}
+
+[env:pro-esp32c3]
+extends = env:pro-esp32
+board = esp32-c3-devkitc-02
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${release.build_flags}
+ ${esp32c3.build_flags}
+
+[env:pro-esp32c3-debug]
+extends = env:pro-esp32-debug
+board = esp32-c3-devkitc-02
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${debug.build_flags}
+ ${esp32c3.build_flags}
+
+[env:trial-esp32c3]
+extends = env:trial-esp32
+board = esp32-c3-devkitc-02
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${release.build_flags}
+ ${esp32c3.build_flags}
+
+[env:trial-esp32c3-debug]
+extends = env:trial-esp32
+board = esp32-c3-devkitc-02
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${debug.build_flags}
+ ${esp32c3.build_flags}
+
+; esp32s3
+
+[esp32s3]
+build_flags =
+ -D YASOLR_OUTPUT2_DIMMER_PIN=36
+ -D YASOLR_OUTPUT1_DIMMER_PIN=37
+ -D YASOLR_DISPLAY_CLOCK_PIN=38
+ -D YASOLR_BUTTON_PIN=39
+ -D YASOLR_OUTPUT1_RELAY_PIN=40
+ -D YASOLR_BUZZER_PIN=8
+
+[env:oss-esp32s3]
+extends = env:oss-esp32
+board = esp32-s3-devkitc-1
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${release.build_flags}
+ ${esp32s3.build_flags}
+
+[env:oss-esp32s3-debug]
+extends = env:oss-esp32-debug
+board = esp32-s3-devkitc-1
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${debug.build_flags}
+ ${esp32s3.build_flags}
+
+[env:pro-esp32s3]
+extends = env:pro-esp32
+board = esp32-s3-devkitc-1
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${release.build_flags}
+ ${esp32s3.build_flags}
+
+[env:pro-esp32s3-debug]
+extends = env:pro-esp32-debug
+board = esp32-s3-devkitc-1
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${debug.build_flags}
+ ${esp32s3.build_flags}
+
+[env:trial-esp32s3]
+extends = env:trial-esp32
+board = esp32-s3-devkitc-1
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${release.build_flags}
+ ${esp32s3.build_flags}
+
+[env:trial-esp32s3-debug]
+extends = env:trial-esp32-debug
+board = esp32-s3-devkitc-1
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${debug.build_flags}
+ ${esp32s3.build_flags}
+
+; lolin32_lite
+
+[lolin32_lite]
+build_flags =
+ -D YASOLR_BUZZER_PIN=14
+ -D YASOLR_DISPLAY_DATA_PIN=19
+
+[env:oss-lolin32_lite]
+extends = env:oss-esp32
+board = lolin32_lite
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${release.build_flags}
+ ${lolin32_lite.build_flags}
+
+[env:oss-lolin32_lite-debug]
+extends = env:oss-esp32-debug
+board = lolin32_lite
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${debug.build_flags}
+ ${lolin32_lite.build_flags}
+
+[env:pro-lolin32_lite]
+extends = env:pro-esp32
+board = lolin32_lite
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${release.build_flags}
+ ${lolin32_lite.build_flags}
+
+[env:pro-lolin32_lite-debug]
+extends = env:pro-esp32-debug
+board = lolin32_lite
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${debug.build_flags}
+ ${lolin32_lite.build_flags}
+
+[env:trial-lolin32_lite]
+extends = env:trial-esp32
+board = lolin32_lite
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${release.build_flags}
+ ${lolin32_lite.build_flags}
+
+[env:trial-lolin32_lite-debug]
+extends = env:trial-esp32
+board = lolin32_lite
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${debug.build_flags}
+ ${lolin32_lite.build_flags}
+
+; lolin_s2_mini
+
+[lolin_s2_mini]
+build_flags =
+ -D MYCILA_JSY_SERIAL=Serial1
+ -D YASOLR_BUTTON_PIN=7
+ -D YASOLR_BUZZER_PIN=14
+ -D YASOLR_DISPLAY_CLOCK_PIN=9
+ -D YASOLR_DISPLAY_DATA_PIN=8
+ -D YASOLR_JSY_RX_PIN=39
+ -D YASOLR_JSY_TX_PIN=37
+ -D YASOLR_LIGHTS_GREEN_PIN=3
+ -D YASOLR_LIGHTS_RED_PIN=6
+ -D YASOLR_OUTPUT1_DIMMER_PIN=10
+ -D YASOLR_OUTPUT1_RELAY_PIN=21
+ -D YASOLR_OUTPUT2_DIMMER_PIN=11
+
+[env:oss-lolin_s2_mini]
+extends = env:oss-esp32
+board = lolin_s2_mini
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${release.build_flags}
+ ${lolin_s2_mini.build_flags}
+
+[env:oss-lolin_s2_mini-debug]
+extends = env:oss-esp32-debug
+board = lolin_s2_mini
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${debug.build_flags}
+ ${lolin_s2_mini.build_flags}
+
+[env:pro-lolin_s2_mini]
+extends = env:pro-esp32
+board = lolin_s2_mini
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${release.build_flags}
+ ${lolin_s2_mini.build_flags}
+
+[env:pro-lolin_s2_mini-debug]
+extends = env:pro-esp32-debug
+board = lolin_s2_mini
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${debug.build_flags}
+ ${lolin_s2_mini.build_flags}
+
+[env:trial-lolin_s2_mini]
+extends = env:trial-esp32
+board = lolin_s2_mini
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${release.build_flags}
+ ${lolin_s2_mini.build_flags}
+
+[env:trial-lolin_s2_mini-debug]
+extends = env:trial-esp32
+board = lolin_s2_mini
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${debug.build_flags}
+ ${lolin_s2_mini.build_flags}
+
+; esp32_poe
+
+[esp32_poe]
+build_flags =
+ -D ESPCONNECT_ETH_RESET_ON_START
+ -D ESPCONNECT_ETH_SUPPORT
+ -D YASOLR_BUTTON_PIN=-1
+ -D YASOLR_BUZZER_PIN=-1
+ -D YASOLR_DISPLAY_CLOCK_PIN=16
+ -D YASOLR_DISPLAY_DATA_PIN=13
+ -D YASOLR_JSY_RX_PIN=33
+ -D YASOLR_JSY_TX_PIN=35
+ -D YASOLR_LIGHTS_GREEN_PIN=-1
+ -D YASOLR_LIGHTS_RED_PIN=-1
+ -D YASOLR_LIGHTS_YELLOW_PIN=-1
+ -D YASOLR_OUTPUT1_DIMMER_PIN=2
+ -D YASOLR_OUTPUT1_RELAY_PIN=4
+ -D YASOLR_OUTPUT1_TEMP_PIN=5
+ -D YASOLR_OUTPUT2_DIMMER_PIN=-1
+ -D YASOLR_OUTPUT2_RELAY_PIN=-1
+ -D YASOLR_OUTPUT2_TEMP_PIN=-1
+ -D YASOLR_RELAY1_PIN=14
+ -D YASOLR_RELAY2_PIN=15
+ -D YASOLR_SYSTEM_TEMP_PIN=0
+ -D YASOLR_ZCD_PIN=36
+
+[env:oss-esp32_poe]
+extends = env:oss-esp32
+board = esp32-poe
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${release.build_flags}
+ ${esp32_poe.build_flags}
+
+[env:oss-esp32_poe-debug]
+extends = env:oss-esp32-debug
+board = esp32-poe
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${debug.build_flags}
+ ${esp32_poe.build_flags}
+
+[env:pro-esp32_poe]
+extends = env:pro-esp32
+board = esp32-poe
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${release.build_flags}
+ ${esp32_poe.build_flags}
+
+[env:pro-esp32_poe-debug]
+extends = env:pro-esp32-debug
+board = esp32-poe
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${debug.build_flags}
+ ${esp32_poe.build_flags}
+
+[env:trial-esp32_poe]
+extends = env:trial-esp32
+board = esp32-poe
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${release.build_flags}
+ ${esp32_poe.build_flags}
+
+[env:trial-esp32_poe-debug]
+extends = env:trial-esp32
+board = esp32-poe
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${debug.build_flags}
+ ${esp32_poe.build_flags}
+
+; wt32_eth01
+; https://github.com/egnor/wt32-eth01
+
+[wt32_eth01]
+build_flags =
+ -D ESPCONNECT_ETH_RESET_ON_START
+ -D ESPCONNECT_ETH_SUPPORT
+ -D ETH_PHY_POWER=16
+ -D ETH_PHY_ADDR=1
+ -D YASOLR_BUTTON_PIN=-1
+ -D YASOLR_BUZZER_PIN=-1
+ -D YASOLR_DISPLAY_CLOCK_PIN=-1
+ -D YASOLR_DISPLAY_DATA_PIN=-1
+ -D YASOLR_JSY_TX_PIN=5
+ -D YASOLR_LIGHTS_GREEN_PIN=-1
+ -D YASOLR_LIGHTS_RED_PIN=-1
+ -D YASOLR_LIGHTS_YELLOW_PIN=-1
+ -D YASOLR_OUTPUT1_DIMMER_PIN=2
+ -D YASOLR_OUTPUT1_RELAY_PIN=12
+ -D YASOLR_OUTPUT1_TEMP_PIN=15
+ -D YASOLR_OUTPUT2_DIMMER_PIN=-1
+ -D YASOLR_OUTPUT2_RELAY_PIN=-1
+ -D YASOLR_OUTPUT2_TEMP_PIN=-1
+ -D YASOLR_RELAY1_PIN=14
+ -D YASOLR_RELAY2_PIN=-1
+
+[env:oss-wt32_eth01]
+extends = env:oss-esp32
+board = wt32-eth01
+upload_speed = 460800
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${release.build_flags}
+ ${wt32_eth01.build_flags}
+
+[env:oss-wt32_eth01-debug]
+extends = env:oss-esp32-debug
+board = wt32-eth01
+upload_speed = 460800
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${debug.build_flags}
+ ${wt32_eth01.build_flags}
+
+[env:pro-wt32_eth01]
+extends = env:pro-esp32
+board = wt32-eth01
+upload_speed = 460800
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${release.build_flags}
+ ${wt32_eth01.build_flags}
+
+[env:pro-wt32_eth01-debug]
+extends = env:pro-esp32-debug
+board = wt32-eth01
+upload_speed = 460800
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${debug.build_flags}
+ ${wt32_eth01.build_flags}
+
+[env:trial-wt32_eth01]
+extends = env:trial-esp32
+board = wt32-eth01
+upload_speed = 460800
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${release.build_flags}
+ ${wt32_eth01.build_flags}
+
+[env:trial-wt32_eth01-debug]
+extends = env:trial-esp32-debug
+board = wt32-eth01
+upload_speed = 460800
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${debug.build_flags}
+ ${wt32_eth01.build_flags}
+
+; lilygo_eth_lite_s3
+; https://github.com/Xinyuan-LilyGO/LilyGO-T-ETH-Series/
+
+[lilygo_eth_lite_s3]
+build_flags =
+ ; -UARDUINO_USB_CDC_ON_BOOT
+ -D ETH_PHY_ADDR=1
+ -D ESPCONNECT_ETH_SUPPORT
+ -D ESPCONNECT_ETH_CS=9
+ -D ESPCONNECT_ETH_INT=13
+ -D ESPCONNECT_ETH_MISO=11
+ -D ESPCONNECT_ETH_MOSI=12
+ -D ESPCONNECT_ETH_RST=14
+ -D ESPCONNECT_ETH_SCLK=10
+ -D YASOLR_BUTTON_PIN=1
+ -D YASOLR_BUZZER_PIN=2
+ -D YASOLR_DISPLAY_CLOCK_PIN=40
+ -D YASOLR_DISPLAY_DATA_PIN=41
+ -D YASOLR_JSY_RX_PIN=17
+ -D YASOLR_JSY_TX_PIN=18
+ -D YASOLR_LIGHTS_GREEN_PIN=38
+ -D YASOLR_LIGHTS_RED_PIN=46
+ -D YASOLR_LIGHTS_YELLOW_PIN=21
+ -D YASOLR_OUTPUT1_DIMMER_PIN=19
+ -D YASOLR_OUTPUT1_RELAY_PIN=20
+ -D YASOLR_OUTPUT1_TEMP_PIN=3
+ -D YASOLR_OUTPUT2_DIMMER_PIN=7
+ -D YASOLR_OUTPUT2_RELAY_PIN=15
+ -D YASOLR_OUTPUT2_TEMP_PIN=16
+ -D YASOLR_RELAY1_PIN=5
+ -D YASOLR_RELAY2_PIN=6
+ -D YASOLR_SYSTEM_TEMP_PIN=4
+ -D YASOLR_ZCD_PIN=8
+
+[env:oss-lilygo_eth_lite_s3]
+extends = env:oss-esp32
+board = esp32s3box
+upload_speed = 115200
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${release.build_flags}
+ ${lilygo_eth_lite_s3.build_flags}
+
+[env:oss-lilygo_eth_lite_s3-debug]
+extends = env:oss-esp32-debug
+board = esp32s3box
+upload_speed = 115200
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${debug.build_flags}
+ ${lilygo_eth_lite_s3.build_flags}
+
+[env:pro-lilygo_eth_lite_s3]
+extends = env:pro-esp32
+board = esp32s3box
+upload_speed = 115200
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${release.build_flags}
+ ${lilygo_eth_lite_s3.build_flags}
+
+[env:pro-lilygo_eth_lite_s3-debug]
+extends = env:pro-esp32-debug
+board = esp32s3box
+upload_speed = 115200
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${debug.build_flags}
+ ${lilygo_eth_lite_s3.build_flags}
+
+[env:trial-lilygo_eth_lite_s3]
+extends = env:trial-esp32
+board = esp32s3box
+upload_speed = 115200
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${release.build_flags}
+ ${lilygo_eth_lite_s3.build_flags}
+
+[env:trial-lilygo_eth_lite_s3-debug]
+extends = env:trial-esp32
+board = esp32s3box
+upload_speed = 115200
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${debug.build_flags}
+ ${lilygo_eth_lite_s3.build_flags}
+
+; m5stack-atom
+; TODO: add default pinout for m5stack-atom
+
+[m5stack_atom]
+build_flags =
+ ${unpin.build_flags}
+
+[env:oss-m5stack_atom]
+extends = env:oss-esp32
+board = m5stack-atom
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${release.build_flags}
+ ${m5stack_atom.build_flags}
+
+[env:oss-m5stack_atom-debug]
+extends = env:oss-esp32-debug
+board = m5stack-atom
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${debug.build_flags}
+ ${m5stack_atom.build_flags}
+
+[env:pro-m5stack_atom]
+extends = env:pro-esp32
+board = m5stack-atom
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${release.build_flags}
+ ${m5stack_atom.build_flags}
+
+[env:pro-m5stack_atom-debug]
+extends = env:pro-esp32-debug
+board = m5stack-atom
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${debug.build_flags}
+ ${m5stack_atom.build_flags}
+
+[env:trial-m5stack_atom]
+extends = env:trial-esp32
+board = m5stack-atom
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${release.build_flags}
+ ${m5stack_atom.build_flags}
+
+[env:trial-m5stack_atom-debug]
+extends = env:trial-esp32
+board = m5stack-atom
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${debug.build_flags}
+ ${m5stack_atom.build_flags}
+
+; m5stack-atoms3
+; TODO: add default pinout for m5stack-atoms3
+
+[m5stack_atoms3]
+build_flags =
+ ${unpin.build_flags}
+
+[env:oss-m5stack_atoms3]
+extends = env:oss-esp32
+board = m5stack-atoms3
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${release.build_flags}
+ ${m5stack_atoms3.build_flags}
+
+[env:oss-m5stack_atoms3-debug]
+extends = env:oss-esp32-debug
+board = m5stack-atoms3
+build_flags =
+ ${env.build_flags}
+ ${oss.build_flags}
+ ${debug.build_flags}
+ ${m5stack_atoms3.build_flags}
+
+[env:pro-m5stack_atoms3]
+extends = env:pro-esp32
+board = m5stack-atoms3
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${release.build_flags}
+ ${m5stack_atoms3.build_flags}
+
+[env:pro-m5stack_atoms3-debug]
+extends = env:pro-esp32-debug
+board = m5stack-atoms3
+build_flags =
+ ${env.build_flags}
+ ${pro.build_flags}
+ ${debug.build_flags}
+ ${m5stack_atoms3.build_flags}
+
+[env:trial-m5stack_atoms3]
+extends = env:trial-esp32
+board = m5stack-atoms3
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${release.build_flags}
+ ${m5stack_atoms3.build_flags}
+
+[env:trial-m5stack_atoms3-debug]
+extends = env:trial-esp32
+board = m5stack-atoms3
+build_flags =
+ ${env.build_flags}
+ ${trial.build_flags}
+ ${debug.build_flags}
+ ${m5stack_atoms3.build_flags}
diff --git a/platformio_override.ini.template b/platformio_override.ini.template
new file mode 100644
index 00000000..ed5a9d3c
--- /dev/null
+++ b/platformio_override.ini.template
@@ -0,0 +1,23 @@
+; *** PlatformIO Project Configuration Override File ***
+; *** Changes done here override settings in platformio.ini ***
+;
+; Place your personal settings like monitor_port and upload_port here
+; instead of editing platformio.ini
+; to avoid annoying merge conflicts when you pull updates into your
+; personal clone of the repository
+;
+; Please visit documentation for the options and examples
+; http://docs.platformio.org/en/stable/projectconf.html
+
+[platformio]
+; default_envs = pro-esp32-debug, oss-esp32-debug, trial-esp32-debug, trial-esp32s-debug, trial-esp32c3-debug, trial-esp32s3-debug, trial-lolin32_lite-debug, trial-lolin_s2_mini-debug, trial-esp32_poe-debug, trial-wt32_eth01-debug, trial-lilygo_eth_lite_s3-debug, trial-m5stack_atom-debug, trial-m5stack_atoms3-debug
+; default_envs = oss-esp32-debug
+; default_envs = pro-esp32-debug
+; default_envs = pro-lilygo_eth_lite_s3-debug
+; default_envs = pro-wt32_eth01-debug
+; default_envs = trial-esp32_poe
+; default_envs = trial-esp32-debug
+; default_envs = trial-esp32s3-debug
+; default_envs = trial-lilygo_eth_lite_s3-debug
+; default_envs = trial-lolin_s2_mini-debug
+; default_envs = trial-wt32_eth01-debug
diff --git a/src/YaSolRClass.cpp b/src/YaSolRClass.cpp
new file mode 100644
index 00000000..ad73d65f
--- /dev/null
+++ b/src/YaSolRClass.cpp
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+
+#include
+
+void YaSolR::YaSolRClass::_initHTTPd() {
+ Mycila::HTTPd.init(&webServer, YASOLR_ADMIN_USERNAME, Mycila::Config.get(KEY_ADMIN_PASSWORD));
+}
+
+void YaSolR::YaSolRClass::_initWebsite() {
+ YaSolR::Website.init();
+}
+
+void YaSolR::YaSolRClass::updateWebsite() {
+ YaSolR::Website.update();
+}
+
+namespace YaSolR {
+ YaSolRClass YaSolR;
+} // namespace YaSolR
diff --git a/src/YaSolR_API_MQTT.cpp b/src/YaSolR_API_MQTT.cpp
new file mode 100644
index 00000000..0c4cbe34
--- /dev/null
+++ b/src/YaSolR_API_MQTT.cpp
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+
+#define TAG "YASOLR"
+
+void YaSolR::YaSolRClass::_initMQTT() {
+ Mycila::Logger.info(TAG, "Initializing MQTT API...");
+
+ const String baseTopic = Mycila::Config.get(KEY_MQTT_TOPIC);
+
+ // config
+
+ Mycila::MQTT.subscribe(baseTopic + "/config/+/set", [](const String& topic, const String& payload) {
+ const int end = topic.lastIndexOf("/");
+ const int start = topic.lastIndexOf("/", end - 1);
+ const String key = topic.substring(start + 1, end);
+ const char* keyRef = Mycila::Config.keyRef(key.c_str());
+ if (keyRef)
+ Mycila::Config.set(keyRef, payload);
+ });
+
+ // relays
+
+ Mycila::MQTT.subscribe(baseTopic + "/relays/" NAME_RELAY1 "/state/set", [this](const String& topic, const String& payload) {
+ if (relay1.isEnabled()) {
+ int start = payload.indexOf("=");
+ String state = start >= 0 ? payload.substring(0, start) : payload;
+ uint32_t duration = start >= 0 ? payload.substring(start + 1).toInt() : 0;
+ if (state == YASOLR_ON)
+ Mycila::RelayManager.tryRelayState(&relay1, true, duration);
+ else if (state == YASOLR_OFF)
+ Mycila::RelayManager.tryRelayState(&relay1, false, duration);
+ }
+ });
+ Mycila::MQTT.subscribe(baseTopic + "/relays/" NAME_RELAY2 "/state/set", [this](const String& topic, const String& payload) {
+ if (relay2.isEnabled()) {
+ int start = payload.indexOf("=");
+ String state = start >= 0 ? payload.substring(0, start) : payload;
+ uint32_t duration = start >= 0 ? payload.substring(start + 1).toInt() : 0;
+ if (state == YASOLR_ON)
+ Mycila::RelayManager.tryRelayState(&relay2, true, duration);
+ else if (state == YASOLR_OFF)
+ Mycila::RelayManager.tryRelayState(&relay2, false, duration);
+ }
+ });
+
+ // router
+
+ Mycila::MQTT.subscribe(baseTopic + "/router/" NAME_OUTPUT1 "/dimmer/level/set", [](const String& topic, const String& payload) {
+ output1.tryDimmerLevel(payload.toInt());
+ });
+
+ Mycila::MQTT.subscribe(baseTopic + "/router/" NAME_OUTPUT2 "/dimmer/level/set", [](const String& topic, const String& payload) {
+ output2.tryDimmerLevel(payload.toInt());
+ });
+
+ Mycila::MQTT.subscribe(baseTopic + "/router/" NAME_OUTPUT1 "/bypass_relay/state/set", [](const String& topic, const String& payload) {
+ if (output1.isBypassRelayEnabled()) {
+ if (payload == YASOLR_ON)
+ output1.tryBypassRelayState(true);
+ else if (payload == YASOLR_OFF)
+ output1.tryBypassRelayState(false);
+ }
+ });
+
+ Mycila::MQTT.subscribe(baseTopic + "/router/" NAME_OUTPUT2 "/bypass_relay/state/set", [](const String& topic, const String& payload) {
+ if (output2.isBypassRelayEnabled()) {
+ if (payload == YASOLR_ON)
+ output2.tryBypassRelayState(true);
+ else if (payload == YASOLR_OFF)
+ output2.tryBypassRelayState(false);
+ }
+ });
+
+ // system
+
+ Mycila::MQTT.subscribe(baseTopic + "/system/restart", [=](const String& topic, const String& payload) {
+ restartTask.resume();
+ });
+
+ Mycila::MQTT.subscribe(baseTopic + "/system/reset", [=](const String& topic, const String& payload) {
+ resetTask.resume();
+ });
+}
diff --git a/src/YaSolR_API_REST.cpp b/src/YaSolR_API_REST.cpp
new file mode 100644
index 00000000..e15e61d3
--- /dev/null
+++ b/src/YaSolR_API_REST.cpp
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+
+#include
+#include
+#include