.
diff --git a/lib/ESPDASH/README.md b/lib/ESPDASH/README.md
new file mode 100644
index 0000000..170d062
--- /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/docs/dash-github-splash.png b/lib/ESPDASH/docs/dash-github-splash.png
new file mode 100644
index 0000000..4ee26c5
Binary files /dev/null and b/lib/ESPDASH/docs/dash-github-splash.png differ
diff --git a/lib/ESPDASH/docs/dash-github-splash.psd b/lib/ESPDASH/docs/dash-github-splash.psd
new file mode 100644
index 0000000..ecaafb9
Binary files /dev/null and b/lib/ESPDASH/docs/dash-github-splash.psd differ
diff --git a/lib/ESPDASH/docs/logo-collapsed.svg b/lib/ESPDASH/docs/logo-collapsed.svg
new file mode 100644
index 0000000..21cfafd
--- /dev/null
+++ b/lib/ESPDASH/docs/logo-collapsed.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/ESPDASH/docs/logo.svg b/lib/ESPDASH/docs/logo.svg
new file mode 100644
index 0000000..d8fc1d2
--- /dev/null
+++ b/lib/ESPDASH/docs/logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/lib/ESPDASH/docs/preview.png b/lib/ESPDASH/docs/preview.png
new file mode 100644
index 0000000..9a277f6
Binary files /dev/null and b/lib/ESPDASH/docs/preview.png differ
diff --git a/lib/ESPDASH/docs/pro-preview.png b/lib/ESPDASH/docs/pro-preview.png
new file mode 100644
index 0000000..50eff08
Binary files /dev/null and b/lib/ESPDASH/docs/pro-preview.png differ
diff --git a/lib/ESPDASH/examples/AccessPoint/AccessPoint.ino b/lib/ESPDASH/examples/AccessPoint/AccessPoint.ino
new file mode 100644
index 0000000..4e42878
--- /dev/null
+++ b/lib/ESPDASH/examples/AccessPoint/AccessPoint.ino
@@ -0,0 +1,82 @@
+/*
+ -----------------------------
+ ESPDASH Lite - AccessPoint Example
+ -----------------------------
+
+ Skill Level: Intermediate
+
+ In this example we will be booting up our ESP Module in Access Point (SoftAP) mode
+ and initialize our dashboard which can be accessed via 192.168.4.1
+
+ Github: https://github.com/ayushsharma82/ESP-DASH
+ WiKi: https://docs.espdash.pro
+
+ Works with both ESP8266 & ESP32
+
+ -------------------------------
+
+ Upgrade to ESP-DASH Pro: https://espdash.pro
+
+*/
+
+#include
+#if defined(ESP8266)
+ /* ESP8266 Dependencies */
+ #include
+ #include
+ #include
+#elif defined(ESP32)
+ /* ESP32 Dependencies */
+ #include
+ #include
+ #include
+#endif
+#include
+
+
+/* Your SoftAP WiFi Credentials */
+const char* ssid = ""; // SSID
+const char* password = ""; // Password
+
+/* Start Webserver */
+AsyncWebServer server(80);
+
+/* Attach ESP-DASH to AsyncWebServer */
+ESPDash dashboard(&server);
+
+/*
+ Dashboard Cards
+ Format - (Dashboard Instance, Card Type, Card Name, Card Symbol(optional) )
+*/
+Card temperature(&dashboard, TEMPERATURE_CARD, "Temperature", "°C");
+Card humidity(&dashboard, HUMIDITY_CARD, "Humidity", "%");
+
+
+void setup() {
+ Serial.begin(115200);
+
+ /* Start Access Point */
+ WiFi.mode(WIFI_AP);
+ WiFi.softAPConfig(IPAddress(192, 168, 4, 1), IPAddress(192, 168, 4, 1), IPAddress(255, 255, 255, 0));
+ WiFi.softAP(ssid, password);
+ Serial.print("IP Address: ");
+ Serial.println(WiFi.softAPIP());
+
+ /* Start AsyncWebServer */
+ server.begin();
+}
+
+void loop() {
+ /* Update Card Values */
+ temperature.update((int)random(0, 50));
+ humidity.update((int)random(0, 100));
+
+ /* Send Updates to our Dashboard (realtime) */
+ dashboard.sendUpdates();
+
+ /*
+ Delay is just for demonstration purposes in this example,
+ Replace this code with 'millis interval' in your final project.
+ */
+ delay(3000);
+}
\ No newline at end of file
diff --git a/lib/ESPDASH/examples/Basic/Basic.ino b/lib/ESPDASH/examples/Basic/Basic.ino
new file mode 100644
index 0000000..1500810
--- /dev/null
+++ b/lib/ESPDASH/examples/Basic/Basic.ino
@@ -0,0 +1,85 @@
+/*
+ -----------------------
+ ESPDASH Lite - Basic Example
+ -----------------------
+
+ Skill Level: Intermediate
+
+ In this example we will be creating a basic dashboard which consists
+ of some cards and then update them in realtime ( at 3s interval ).
+
+ Github: https://github.com/ayushsharma82/ESP-DASH
+ WiKi: https://docs.espdash.pro
+
+ Works with both ESP8266 & ESP32
+
+ -------------------------------
+
+ Upgrade to ESP-DASH Pro: https://espdash.pro
+
+*/
+
+#include
+#if defined(ESP8266)
+ /* ESP8266 Dependencies */
+ #include
+ #include
+ #include
+#elif defined(ESP32)
+ /* ESP32 Dependencies */
+ #include
+ #include
+ #include
+#endif
+#include
+
+
+/* Your WiFi Credentials */
+const char* ssid = ""; // SSID
+const char* password = ""; // Password
+
+/* Start Webserver */
+AsyncWebServer server(80);
+
+/* Attach ESP-DASH to AsyncWebServer */
+ESPDash dashboard(&server);
+
+/*
+ Dashboard Cards
+ Format - (Dashboard Instance, Card Type, Card Name, Card Symbol(optional) )
+*/
+Card temperature(&dashboard, TEMPERATURE_CARD, "Temperature", "°C");
+Card humidity(&dashboard, HUMIDITY_CARD, "Humidity", "%");
+
+
+void setup() {
+ Serial.begin(115200);
+
+ /* Connect WiFi */
+ WiFi.mode(WIFI_STA);
+ WiFi.begin(ssid, password);
+ if (WiFi.waitForConnectResult() != WL_CONNECTED) {
+ Serial.printf("WiFi Failed!\n");
+ return;
+ }
+ Serial.print("IP Address: ");
+ Serial.println(WiFi.localIP());
+
+ /* Start AsyncWebServer */
+ server.begin();
+}
+
+void loop() {
+ /* Update Card Values */
+ temperature.update((int)random(0, 50));
+ humidity.update((int)random(0, 100));
+
+ /* Send Updates to our Dashboard (realtime) */
+ dashboard.sendUpdates();
+
+ /*
+ Delay is just for demonstration purposes in this example,
+ Replace this code with 'millis interval' in your final project.
+ */
+ delay(3000);
+}
\ No newline at end of file
diff --git a/lib/ESPDASH/examples/Benchmark/Benchmark.ino b/lib/ESPDASH/examples/Benchmark/Benchmark.ino
new file mode 100644
index 0000000..e64afb2
--- /dev/null
+++ b/lib/ESPDASH/examples/Benchmark/Benchmark.ino
@@ -0,0 +1,118 @@
+/*
+ -----------------------------
+ ESPDASH Lite - Benchmark Example
+ -----------------------------
+ Use this benchmark example to test if ESP-DASH is working properly on your platform.
+
+ Github: https://github.com/ayushsharma82/ESP-DASH
+ WiKi: https://docs.espdash.pro
+
+ Works with both ESP8266 & ESP32
+ -------------------------------
+
+ Upgrade to ESP-DASH Pro: https://espdash.pro
+*/
+
+#include
+#if defined(ESP8266)
+ /* ESP8266 Dependencies */
+ #include
+ #include
+ #include
+#elif defined(ESP32)
+ /* ESP32 Dependencies */
+ #include
+ #include
+ #include
+#endif
+
+#include
+
+
+/* Your WiFi Credentials */
+const char* ssid = ""; // SSID
+const char* password = ""; // Password
+
+/* Start Webserver */
+AsyncWebServer server(80);
+
+/* Attach ESP-DASH to AsyncWebServer */
+ESPDash dashboard(&server);
+
+Card generic(&dashboard, GENERIC_CARD, "Generic");
+Card temp(&dashboard, TEMPERATURE_CARD, "Temperature", "°C");
+Card hum(&dashboard, HUMIDITY_CARD, "Humidity", "%");
+Card status1(&dashboard, STATUS_CARD, "Status 1", "success");
+Card status2(&dashboard, STATUS_CARD, "Status 2", "warning");
+Card status3(&dashboard, STATUS_CARD, "Status 3", "danger");
+Card status4(&dashboard, STATUS_CARD, "Status 4", "idle");
+Card progress(&dashboard, PROGRESS_CARD, "Progress", "", 0, 100);
+Card button(&dashboard, BUTTON_CARD, "Test Button");
+Card slider(&dashboard, SLIDER_CARD, "Test Slider", "", 0, 255);
+
+Chart bar(&dashboard, BAR_CHART, "Power Usage (kWh)");
+
+// Bar Chart Data
+String XAxis[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+int YAxis[] = {0, 0, 0, 0, 0, 0, 0};
+
+
+void setup() {
+ Serial.begin(115200);
+
+ /* Connect WiFi */
+ WiFi.mode(WIFI_STA);
+ WiFi.begin(ssid, password);
+ if (WiFi.waitForConnectResult() != WL_CONNECTED) {
+ Serial.printf("WiFi Failed!\n");
+ return;
+ }
+ Serial.print("IP Address: ");
+ Serial.println(WiFi.localIP());
+
+ bar.updateX(XAxis, 7);
+
+ /* Attach Button Callback */
+ button.attachCallback([&](bool value){
+ /* Print our new button value received from dashboard */
+ Serial.println("Button Triggered: "+String((value)?"true":"false"));
+ /* Make sure we update our button's value and send update to dashboard */
+ button.update(value);
+ dashboard.sendUpdates();
+ });
+
+ /* Attach Slider Callback */
+ slider.attachCallback([&](int value){
+ /* Print our new slider value received from dashboard */
+ Serial.println("Slider Triggered: "+String(value));
+ /* Make sure we update our slider's value and send update to dashboard */
+ slider.update(value);
+ dashboard.sendUpdates();
+ });
+
+ /* Start AsyncWebServer */
+ server.begin();
+}
+
+void loop() {
+ // Randomize YAxis Values ( for demonstration purposes only )
+ for(int i=0; i < 7; i++){
+ YAxis[i] = (int)random(0, 200);
+ }
+
+ /* Update Chart Y Axis (yaxis_array, array_size) */
+ bar.updateY(YAxis, 7);
+
+ // Update all cards with random values
+ generic.update((int)random(0, 100));
+ temp.update((int)random(0, 100));
+ hum.update((int)random(0, 100));
+ status1.update("success");
+ status2.update("warning");
+ status3.update("danger");
+ status4.update("idle");
+ progress.update((int)random(0, 100));
+
+ dashboard.sendUpdates();
+ delay(2000);
+}
\ No newline at end of file
diff --git a/lib/ESPDASH/examples/Chart/Chart.ino b/lib/ESPDASH/examples/Chart/Chart.ino
new file mode 100644
index 0000000..34185d6
--- /dev/null
+++ b/lib/ESPDASH/examples/Chart/Chart.ino
@@ -0,0 +1,100 @@
+/*
+ -----------------------
+ ESPDASH Lite - Chart Example
+ -----------------------
+
+ Skill Level: Intermediate
+
+ In this example we will learn how to create a bar chart
+ and then update it at a regular interval.
+
+ Github: https://github.com/ayushsharma82/ESP-DASH
+ WiKi: https://docs.espdash.pro
+
+ Works with both ESP8266 & ESP32
+
+ -------------------------------
+
+ Upgrade to ESP-DASH Pro: https://espdash.pro
+
+*/
+
+#include
+#if defined(ESP8266)
+ /* ESP8266 Dependencies */
+ #include
+ #include
+ #include
+#elif defined(ESP32)
+ /* ESP32 Dependencies */
+ #include
+ #include
+ #include
+#endif
+#include
+
+
+/* Your WiFi Credentials */
+const char* ssid = ""; // SSID
+const char* password = ""; // Password
+
+/* Start Webserver */
+AsyncWebServer server(80);
+
+/* Attach ESP-DASH to AsyncWebServer */
+ESPDash dashboard(&server);
+
+/*
+ Dashboard Charts
+ Format - (Dashboard Instance, Chart Type, Chart Name )
+*/
+// Bar Chart Data
+String XAxis[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+int YAxis[] = {0, 0, 0, 0, 0, 0, 0};
+
+// Bar Chart Instance
+Chart power(&dashboard, BAR_CHART, "Power Usage (kWh)");
+
+
+void setup() {
+ Serial.begin(115200);
+
+ /* Connect WiFi */
+ WiFi.mode(WIFI_STA);
+ WiFi.begin(ssid, password);
+ if (WiFi.waitForConnectResult() != WL_CONNECTED) {
+ Serial.printf("WiFi Failed!\n");
+ return;
+ }
+ Serial.print("IP Address: ");
+ Serial.println(WiFi.localIP());
+
+ /*
+ Update Chart X Axis (xaxis_array, array_size)
+ -------------------
+ We need to update X Axis once only as it will not be changing in this example
+ */
+ power.updateX(XAxis, 7);
+
+ /* Start AsyncWebServer */
+ server.begin();
+}
+
+void loop() {
+ // Randomize YAxis Values ( for demonstration purposes only )
+ for(int i=0; i < 7; i++){
+ YAxis[i] = (int)random(0, 200);
+ }
+
+ /* Update Chart Y Axis (yaxis_array, array_size) */
+ power.updateY(YAxis, 7);
+
+ /* Send Updates to our Dashboard (realtime) */
+ dashboard.sendUpdates();
+
+ /*
+ Delay is just for demonstration purposes in this example,
+ Replace this code with 'millis interval' in your final project.
+ */
+ delay(3000);
+}
diff --git a/lib/ESPDASH/examples/Dynamic/Dynamic.ino b/lib/ESPDASH/examples/Dynamic/Dynamic.ino
new file mode 100644
index 0000000..f7df0c9
--- /dev/null
+++ b/lib/ESPDASH/examples/Dynamic/Dynamic.ino
@@ -0,0 +1,107 @@
+/*
+ -------------------------
+ ESPDASH Lite - Dynamic Example
+ -------------------------
+
+ Skill Level: Advanced ( Must have good knowledge about heap, pointers and destructors )
+
+ In this example we will be creating a dynamic dashboard which consists
+ of some cards and then remove a card from dashboard after some time.
+
+ Github: https://github.com/ayushsharma82/ESP-DASH
+ WiKi: https://docs.espdash.pro
+
+ Works with both ESP8266 & ESP32
+
+ -------------------------------
+
+ Upgrade to ESP-DASH Pro: https://espdash.pro
+
+*/
+
+#include
+#if defined(ESP8266)
+ /* ESP8266 Dependencies */
+ #include
+ #include
+ #include
+#elif defined(ESP32)
+ /* ESP32 Dependencies */
+ #include
+ #include
+ #include
+#endif
+#include
+
+
+/* Your WiFi Credentials */
+const char* ssid = ""; // SSID
+const char* password = ""; // Password
+
+/* Start Webserver */
+AsyncWebServer server(80);
+
+/* Attach ESP-DASH to AsyncWebServer */
+ESPDash dashboard(&server);
+
+/*
+ Dashboard Cards
+ Format - (Dashboard Instance, Card Type, Card Name, Card Symbol(optional) )
+*/
+Card* temperature = new Card(&dashboard, TEMPERATURE_CARD, "Temperature", "°C");
+Card* humidity = new Card(&dashboard, HUMIDITY_CARD, "Humidity", "%");
+
+/*
+ Removal Time for demonstration purposes only
+ In your final project,
+ You will decide when to add or remove cards, these variables are not requried.
+*/
+unsigned long removalTime = 30000; // Remove after 30s ( 30000 Millis )
+bool cardRemoved = false;
+
+void setup() {
+ Serial.begin(115200);
+
+ /* Connect WiFi */
+ WiFi.mode(WIFI_STA);
+ WiFi.begin(ssid, password);
+ if (WiFi.waitForConnectResult() != WL_CONNECTED) {
+ Serial.printf("WiFi Failed!\n");
+ return;
+ }
+ Serial.print("IP Address: ");
+ Serial.println(WiFi.localIP());
+
+ /* Start AsyncWebServer */
+ server.begin();
+}
+
+void loop() {
+ /* Update Card Values */
+ if(temperature != nullptr) // Check if our pointer has not been deleted & then only access 'update' method
+ temperature->update((int)random(0, 50));
+
+ if(humidity != nullptr) // Check if our pointer has not been deleted & then only access 'update' method
+ humidity->update((int)random(0, 100));
+
+
+ /* Remove our card when removal time is elapsed */
+ if(millis() > removalTime && !cardRemoved){
+ if(humidity != nullptr){
+ /* Calling 'delete' will remove this card from our dashboard instance and will free-up consumed heap */
+ delete humidity;
+ humidity = nullptr; // Make sure to set this pointer to 'nullptr' when deleted
+ }
+ // Set our removal flag
+ cardRemoved = true;
+ }
+
+ /* Send Updates to our Dashboard (realtime) */
+ dashboard.sendUpdates();
+
+ /*
+ Delay is just for demonstration purposes in this example,
+ Replace this code with 'millis interval' in your final project.
+ */
+ delay(3000);
+}
diff --git a/lib/ESPDASH/examples/Interactive/Interactive.ino b/lib/ESPDASH/examples/Interactive/Interactive.ino
new file mode 100644
index 0000000..775ca40
--- /dev/null
+++ b/lib/ESPDASH/examples/Interactive/Interactive.ino
@@ -0,0 +1,97 @@
+/*
+ -----------------------------
+ ESPDASH Lite - Interactive Example
+ -----------------------------
+
+ Skill Level: Intermediate
+
+ In this example we will be creating a interactive dashboard which consists
+ of a button and a slider.
+
+ Github: https://github.com/ayushsharma82/ESP-DASH
+ WiKi: https://docs.espdash.pro
+
+ Works with both ESP8266 & ESP32
+
+ -------------------------------
+
+ Upgrade to ESP-DASH Pro: https://espdash.pro
+
+*/
+
+#include
+#if defined(ESP8266)
+ /* ESP8266 Dependencies */
+ #include
+ #include
+ #include
+#elif defined(ESP32)
+ /* ESP32 Dependencies */
+ #include
+ #include
+ #include
+#endif
+#include
+
+
+/* Your WiFi Credentials */
+const char* ssid = ""; // SSID
+const char* password = ""; // Password
+
+/* Start Webserver */
+AsyncWebServer server(80);
+
+/* Attach ESP-DASH to AsyncWebServer */
+ESPDash dashboard(&server);
+
+/*
+ Button Card
+ Format - (Dashboard Instance, Card Type, Card Name)
+*/
+Card button(&dashboard, BUTTON_CARD, "Test Button");
+
+/*
+ Slider Card
+ Format - (Dashboard Instance, Card Type, Card Name, Card Symbol(optional), int min, int max)
+*/
+Card slider(&dashboard, SLIDER_CARD, "Test Slider", "", 0, 255);
+
+
+void setup() {
+ Serial.begin(115200);
+
+ /* Connect WiFi */
+ WiFi.mode(WIFI_STA);
+ WiFi.begin(ssid, password);
+ if (WiFi.waitForConnectResult() != WL_CONNECTED) {
+ Serial.printf("WiFi Failed!\n");
+ return;
+ }
+ Serial.print("IP Address: ");
+ Serial.println(WiFi.localIP());
+
+ /* Attach Button Callback */
+ button.attachCallback([&](bool value){
+ /* Print our new button value received from dashboard */
+ Serial.println("Button Triggered: "+String((value)?"true":"false"));
+ /* Make sure we update our button's value and send update to dashboard */
+ button.update(value);
+ dashboard.sendUpdates();
+ });
+
+ /* Attach Slider Callback */
+ slider.attachCallback([&](int value){
+ /* Print our new slider value received from dashboard */
+ Serial.println("Slider Triggered: "+String(value));
+ /* Make sure we update our slider's value and send update to dashboard */
+ slider.update(value);
+ dashboard.sendUpdates();
+ });
+
+ /* Start AsyncWebServer */
+ server.begin();
+}
+
+void loop() {
+ /* Nothing so far */
+}
\ No newline at end of file
diff --git a/lib/ESPDASH/keywords.txt b/lib/ESPDASH/keywords.txt
new file mode 100644
index 0000000..1e31794
--- /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 0000000..ae2c2ab
--- /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.3",
+ "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 0000000..9aed56d
--- /dev/null
+++ b/lib/ESPDASH/library.properties
@@ -0,0 +1,9 @@
+name=ESP-DASH
+version=4.0.3
+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 0000000..01d9003
--- /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 0000000..7c0747e
--- /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 0000000..4088c25
--- /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 0000000..796b1a3
--- /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 0000000..97ff7f2
--- /dev/null
+++ b/lib/ESPDASH/src/ESPDash.cpp
@@ -0,0 +1,517 @@
+#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);
+ // Serial.write(buffer->get(), len);
+ // Serial.println();
+ 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 0000000..ab54d14
--- /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 0000000..b32bddc
--- /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 0000000..bf796dc
--- /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 0000000..a197bf9
--- /dev/null
+++ b/lib/ESPDASH/src/dash_webpage.cpp
@@ -0,0 +1,3008 @@
+#include "dash_webpage.h"
+
+const uint8_t DASH_HTML[90104] PROGMEM = {
+31,139,8,0,0,0,0,0,2,3,204,57,103,115,227,56,178,223,239,87,200,124,126,58,162,6,162,229,9,47,
+80,198,184,38,110,222,153,90,237,165,81,169,124,20,217,146,112,166,0,46,0,218,214,200,250,239,175,27,12,160,
+61,179,117,95,94,218,32,53,209,141,206,137,242,197,201,219,15,111,126,253,219,199,119,163,173,219,149,47,255,112,
+65,95,163,50,83,27,17,129,138,94,254,97,52,186,216,66,86,16,128,224,14,92,54,202,183,153,177,224,68,244,
+167,95,223,79,254,35,26,157,181,200,82,170,235,145,129,82,68,50,215,42,26,109,13,172,69,116,182,206,110,232,
+57,193,15,164,29,50,82,217,14,68,116,35,225,182,210,198,69,35,164,114,160,144,241,173,44,220,86,20,128,23,
+97,226,31,248,72,42,233,100,86,78,108,158,149,32,206,147,105,96,230,164,43,225,229,223,178,185,46,127,25,125,
+152,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,86,255,153,191,248,143,167,197,121,242,15,251,135,155,204,140,10,35,62,172,254,1,185,75,10,88,75,
+5,31,141,174,192,184,61,175,191,142,144,96,103,116,111,211,163,55,224,62,220,170,238,222,91,104,212,208,166,161,
+123,167,190,78,55,223,239,86,186,108,104,170,158,87,101,180,211,100,64,178,205,236,128,154,239,190,66,82,181,200,
+239,236,59,85,239,192,100,171,18,60,191,95,148,136,37,119,28,152,120,233,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,239,164,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,127,81,72,14,
+220,45,96,201,102,114,29,191,83,44,220,211,107,244,76,236,24,219,253,254,29,3,174,54,168,252,145,255,210,139,
+174,201,142,141,161,155,51,212,222,186,209,202,136,117,173,114,39,181,138,217,161,57,115,162,208,57,26,170,92,146,
+27,200,28,188,43,129,158,226,136,82,55,98,137,129,242,71,105,29,169,229,198,99,151,216,186,162,204,180,67,56,
+110,115,168,66,98,157,21,17,99,141,66,51,178,162,145,99,201,142,94,212,111,53,152,253,28,74,140,146,54,175,
+208,166,63,146,180,5,21,202,35,86,203,63,50,166,98,203,102,10,110,71,63,213,46,35,237,63,172,44,152,27,
+48,177,69,15,7,25,154,100,88,134,154,234,196,167,182,16,81,190,149,101,65,6,68,44,16,26,34,212,73,86,
+20,80,252,172,11,176,204,36,46,219,252,156,237,252,157,31,191,251,249,135,104,60,54,100,187,16,143,52,66,132,
+138,13,59,178,68,55,90,196,157,85,252,208,11,163,172,176,245,202,25,0,4,143,108,214,249,125,4,177,237,92,
+175,49,19,186,200,217,68,42,7,27,35,221,126,60,142,117,120,18,3,12,227,22,85,90,131,49,96,42,93,202,
+220,211,246,71,31,253,145,120,76,67,183,114,163,173,213,70,110,164,34,131,106,11,19,140,118,1,138,218,135,141,
+46,117,50,120,20,145,84,121,89,23,16,165,95,220,204,148,86,251,157,174,191,188,163,119,210,69,233,163,67,139,
+30,157,52,183,35,174,143,189,23,20,121,1,227,100,19,168,186,92,33,88,156,76,103,157,115,128,162,190,6,151,
+111,145,140,250,38,215,236,120,156,173,76,60,112,103,237,48,147,3,223,191,58,159,252,33,39,218,186,99,18,203,
+68,56,252,8,165,18,120,232,88,178,67,119,30,179,128,121,173,226,30,225,123,74,87,36,177,170,203,114,64,232,
+128,88,200,4,229,190,203,80,225,90,15,144,87,102,192,159,242,18,147,79,162,47,59,130,40,144,126,246,250,7,
+101,78,132,188,116,66,184,20,33,129,221,67,142,199,3,6,218,171,20,221,223,127,149,105,9,110,244,25,130,171,
+182,106,200,27,81,216,140,62,195,239,150,127,134,85,204,63,131,247,188,112,28,121,139,246,41,168,123,215,91,22,
+28,116,13,123,139,167,73,9,106,227,182,120,107,26,232,247,77,107,5,174,124,244,101,87,9,86,108,116,143,233,
+35,180,152,46,49,5,142,225,250,128,232,208,19,157,47,177,32,47,49,240,144,228,238,46,177,152,242,16,51,78,
+136,216,183,77,150,122,76,96,115,243,72,139,197,83,98,17,116,161,3,188,10,204,247,98,151,20,210,184,61,26,
+114,163,101,49,154,178,174,98,9,217,58,222,134,96,132,226,94,44,185,17,63,101,110,155,236,178,187,142,77,235,
+22,110,91,128,249,22,73,161,202,196,116,150,93,152,89,246,68,156,51,189,200,150,162,189,130,224,189,197,143,206,
+47,250,216,2,45,254,222,62,58,8,150,222,246,150,114,203,53,89,27,186,143,33,159,55,56,141,134,38,85,108,
+248,3,111,95,227,229,198,65,228,190,86,223,151,207,158,134,201,129,22,130,24,98,207,158,61,237,237,81,104,143,
+186,128,153,122,242,132,185,133,90,138,201,121,103,129,107,21,158,156,7,105,32,67,58,56,106,140,143,74,88,50,
+192,124,192,42,136,78,177,3,199,142,234,89,14,103,159,11,188,126,106,18,93,38,89,85,129,42,222,80,87,142,
+29,11,4,31,26,183,16,137,84,22,140,123,13,40,14,200,29,247,247,143,74,251,99,83,217,85,102,64,57,26,
+22,137,129,157,190,129,134,171,28,80,254,56,40,134,223,169,170,33,249,155,127,74,254,243,60,142,182,206,85,233,
+217,217,237,237,109,114,251,44,209,102,115,246,116,58,157,158,217,155,77,196,135,220,62,253,62,183,95,225,206,43,
+254,64,250,223,226,150,156,174,70,163,104,128,90,201,7,184,33,74,195,151,21,72,99,244,221,13,138,163,193,7,
+10,76,220,16,240,24,151,16,217,122,235,107,4,131,194,238,226,1,66,144,251,47,187,107,175,156,51,114,85,59,
+192,240,165,146,246,194,225,9,102,3,140,199,50,177,15,142,57,12,56,127,215,54,189,54,147,254,233,34,138,201,
+126,117,229,247,198,171,43,54,200,65,213,140,17,74,228,223,85,81,177,212,207,72,235,246,37,68,72,224,129,36,
+183,150,34,32,232,110,67,112,117,69,27,163,39,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,189,10,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,190,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,155,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,103,12,230,64,244,190,163,162,5,28,138,145,174,157,149,5,140,114,189,171,180,66,105,221,171,
+152,252,156,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,151,180,31,205,35,158,24,77,103,244,254,75,202,34,44,253,82,208,133,
+86,69,95,141,135,175,197,65,188,12,51,145,184,147,241,171,44,191,182,11,183,156,13,103,137,22,115,243,37,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,71,3,20,64,40,218,
+49,129,11,244,177,145,83,1,205,156,31,36,125,126,242,240,103,69,159,111,141,192,90,222,73,75,205,217,234,242,
+6,208,58,10,250,95,37,218,50,11,125,223,160,11,254,42,113,241,33,196,20,239,37,110,11,42,174,52,27,56,
+234,123,63,138,62,5,103,55,194,95,75,65,25,49,7,231,89,127,11,98,26,56,87,122,224,92,76,181,66,251,
+29,116,246,45,92,84,208,78,199,89,152,111,21,44,190,133,37,98,159,60,225,123,106,101,252,71,116,32,250,152,
+29,233,218,190,93,48,121,127,87,76,185,23,248,131,236,153,33,88,233,42,102,113,216,33,28,82,184,139,79,189,
+64,135,187,68,232,125,159,128,226,246,90,210,11,115,12,12,189,128,48,54,111,132,57,196,232,129,79,65,218,241,
+22,123,3,196,189,252,70,198,236,179,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,125,47,89,151,82,167,
+240,32,170,223,184,16,83,73,29,225,27,39,14,38,157,242,60,197,60,171,210,111,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,154,86,203,134,204,245,12,104,159,31,168,247,109,
+219,233,189,154,231,248,175,23,248,152,124,112,225,55,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,167,172,226,119,29,228,175,85,162,166,155,125,237,237,197,58,38,69,42,198,95,9,136,247,
+77,159,152,11,67,59,65,252,138,205,230,151,232,177,57,38,209,30,237,76,227,185,200,227,87,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,188,
+90,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,149,144,139,
+130,128,185,104,46,191,21,175,232,123,70,47,49,175,46,227,192,168,152,76,136,25,75,175,124,106,189,101,151,39,
+198,67,115,236,14,215,45,116,73,218,165,183,29,5,222,73,239,200,89,136,122,233,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,47,248,54,68,199,112,110,232,92,49,255,5,158,159,89,182,111,160,189,11,32,184,224,221,112,201,251,
+242,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,95,220,195,124,240,122,192,227,217,67,111,145,16,195,96,
+103,98,28,6,19,37,192,73,65,19,122,72,41,2,210,243,226,64,19,7,149,26,106,209,182,84,146,222,190,201,
+79,151,66,224,123,48,74,174,250,237,130,211,82,194,3,17,249,161,140,167,108,120,182,112,103,207,206,239,167,203,
+123,113,126,113,225,254,245,217,224,189,249,47,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,173,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,188,50,113,79,50,203,7,117,16,
+224,164,140,215,140,175,251,162,251,200,154,110,246,117,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,
+179,59,156,182,249,134,251,23,22,187,219,74,75,147,147,190,147,14,37,106,119,60,213,244,118,211,27,169,4,81,
+60,126,147,193,36,251,218,177,88,132,89,163,154,98,69,247,198,195,151,34,149,248,63,148,125,88,35,102,102,79,
+154,210,86,137,173,252,203,14,169,116,60,158,210,12,71,167,183,34,44,160,143,78,238,208,215,148,12,237,225,32,
+35,40,172,129,20,169,248,215,104,136,113,248,145,218,183,126,202,227,190,13,204,194,68,123,190,236,94,171,120,38,
+246,38,54,92,114,185,120,182,228,84,238,157,129,135,28,29,233,196,143,113,180,170,157,163,215,87,158,141,199,25,
+69,144,111,208,131,145,119,124,196,65,252,125,93,194,221,136,62,38,244,138,188,201,170,201,115,156,102,202,77,44,
+236,228,74,151,197,200,25,244,160,84,27,250,35,37,140,110,39,107,20,52,90,105,83,128,153,60,237,0,36,82,
+182,249,77,109,116,122,160,31,107,47,163,213,102,178,42,107,144,118,235,191,91,210,135,103,212,4,38,248,110,226,
+32,74,233,2,129,237,233,226,95,254,109,69,255,46,71,91,125,3,38,69,236,198,100,251,201,139,105,123,224,169,
+134,220,162,227,8,111,239,236,36,71,53,192,140,170,59,52,166,218,79,158,38,47,188,82,211,229,241,239,236,200,
+119,49,54,72,118,248,128,95,14,129,198,53,52,209,188,11,185,162,152,89,204,34,45,52,52,206,146,249,117,196,
+233,103,100,198,45,98,145,71,133,151,23,57,182,101,127,185,162,70,128,195,48,31,255,7,166,193,173,137,51,110,
+120,201,75,31,151,203,27,138,146,135,243,70,68,122,109,98,122,102,173,196,246,238,51,156,81,152,116,241,255,84,
+84,202,255,143,81,41,155,168,160,219,30,36,38,186,88,198,37,59,160,99,98,233,208,159,109,96,240,92,211,121,
+22,206,206,143,188,160,35,92,0,62,198,174,13,39,157,112,139,72,78,221,102,80,93,223,181,63,161,251,10,163,
+117,178,212,206,166,126,189,236,118,75,123,20,174,255,171,21,253,202,50,35,82,175,25,253,69,49,53,136,231,135,
+12,249,221,64,154,5,226,82,228,216,76,52,246,104,90,216,48,179,250,191,6,202,166,252,61,62,234,25,69,18,
+199,11,198,60,158,114,35,242,164,63,103,60,242,204,3,193,57,207,144,192,31,18,182,81,52,160,159,113,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,151,182,243,58,254,157,225,175,13,255,236,248,192,234,41,111,45,62,63,14,187,213,251,135,221,234,
+97,3,122,19,71,244,195,54,227,64,96,149,185,45,194,106,0,111,98,224,17,45,72,17,143,148,86,208,29,21,
+248,252,211,116,52,221,62,125,126,243,244,249,183,255,197,173,117,168,71,138,195,224,87,241,109,111,118,108,99,6,
+216,11,123,189,247,222,139,167,79,62,15,228,131,73,79,222,253,126,217,195,142,57,114,189,95,10,77,46,146,144,
+228,223,66,242,220,19,170,45,65,73,145,235,156,41,237,140,40,82,70,7,174,132,81,134,249,227,219,158,52,18,
+201,200,112,127,100,17,209,143,68,150,118,186,118,21,44,237,231,18,242,161,165,47,222,120,177,62,69,91,112,196,
+180,193,95,71,242,117,27,32,104,217,61,89,206,86,139,229,38,126,212,201,55,57,106,200,17,95,170,93,221,220,
+240,97,200,127,195,121,15,167,13,46,30,189,19,48,53,157,42,144,167,148,142,107,131,77,199,6,124,254,79,40,
+60,17,42,211,164,85,238,149,77,135,160,78,30,52,174,70,158,24,180,29,52,31,200,255,15,157,191,30,235,124,
+176,198,174,214,196,246,18,208,68,180,205,4,170,191,177,55,181,237,178,43,190,113,245,162,190,129,13,176,231,11,
+13,40,186,197,171,48,36,226,95,229,242,240,244,27,182,158,62,198,181,202,115,220,116,146,88,71,146,189,237,7,
+33,1,0,8,72,128,10,2,180,158,229,10,81,114,200,242,103,127,148,229,189,53,82,224,67,190,163,55,96,228,
+31,99,241,221,136,197,104,191,243,27,45,186,45,191,160,237,11,73,133,165,142,160,78,83,226,43,215,123,88,139,
+200,136,126,135,205,95,111,60,129,84,31,218,9,42,55,110,60,18,38,118,16,173,152,150,86,49,197,200,92,21,
+199,213,235,38,190,231,234,211,66,152,98,247,136,137,36,31,113,145,21,46,135,219,104,173,35,146,194,125,206,164,
+203,89,159,18,58,161,207,167,90,254,221,62,85,63,53,87,11,20,154,0,72,192,88,151,171,233,116,86,1,35,
+220,24,194,170,190,111,61,162,199,45,61,166,139,58,208,241,186,3,148,162,126,192,78,88,184,9,255,216,210,13,
+39,32,128,16,51,129,142,189,85,223,159,219,237,185,238,187,66,53,116,5,182,241,89,187,113,125,239,34,108,145,
+187,245,156,80,98,248,232,103,55,171,118,179,154,96,178,221,34,248,125,67,128,125,54,229,110,65,136,178,99,243,
+224,8,45,231,103,91,132,67,236,94,125,255,168,195,22,23,1,175,99,175,123,208,124,179,67,25,23,180,71,95,
+129,79,202,206,210,198,102,135,51,115,32,67,111,254,175,99,69,142,55,89,59,239,122,5,20,114,25,242,139,103,
+36,41,145,110,226,66,164,246,142,242,213,68,65,174,178,26,202,5,223,33,157,163,205,83,1,203,190,128,213,207,
+9,72,221,149,76,180,31,97,43,85,121,17,54,239,109,200,64,4,217,104,227,83,19,160,163,56,48,243,128,174,
+47,22,217,199,172,3,119,104,99,175,167,171,109,40,249,208,203,222,123,197,7,127,101,40,249,40,82,217,223,18,
+76,164,144,121,194,148,20,169,83,66,75,45,50,173,172,72,69,26,162,0,254,69,158,230,111,43,205,84,38,70,
+169,227,133,208,121,202,209,32,235,183,227,212,46,140,193,105,16,223,37,21,73,234,114,154,130,27,208,207,215,146,
+25,145,253,220,76,142,231,34,203,88,42,244,72,199,65,77,200,132,201,64,228,158,248,139,147,147,104,189,201,223,
+81,90,164,30,155,37,178,112,52,146,218,206,115,189,188,9,3,143,42,101,153,48,186,184,102,186,136,151,56,158,
+130,209,191,42,98,234,97,196,212,255,245,136,249,233,206,157,6,208,193,66,56,202,2,85,179,230,245,143,223,121,
+187,188,187,15,133,177,80,205,124,3,250,97,65,15,225,122,171,192,50,210,31,243,234,47,127,78,251,79,246,23,
+140,220,166,12,30,230,175,121,115,228,0,83,232,75,114,61,157,162,9,249,44,155,150,125,167,195,243,61,34,68,
+100,165,69,146,25,166,10,81,36,133,75,69,110,10,111,177,201,11,34,75,241,71,54,34,85,38,210,162,96,74,
+190,174,146,79,141,48,89,102,35,42,87,52,4,23,70,141,28,247,35,176,193,8,35,97,164,98,202,188,174,212,
+49,172,82,39,241,0,190,63,117,63,15,194,148,189,112,176,99,122,111,129,127,104,224,201,221,96,82,84,157,183,
+53,212,22,186,58,179,109,237,232,43,123,131,188,145,88,207,58,203,11,41,55,52,252,110,236,44,21,249,246,225,
+37,246,218,9,237,186,19,214,79,43,244,131,122,127,147,238,179,4,200,48,236,118,249,189,4,65,180,74,248,28,
+195,138,204,134,79,72,154,182,159,168,136,115,9,222,228,253,39,136,247,112,234,32,55,149,9,13,193,225,23,63,
+99,130,211,213,241,143,140,240,251,125,60,99,94,224,146,228,77,169,70,223,210,194,7,229,2,236,118,36,59,134,
+6,81,219,195,248,166,62,228,74,50,55,155,111,184,100,13,153,44,206,235,83,110,143,54,53,107,125,41,51,15,
+230,55,197,50,180,176,99,50,191,185,117,45,158,108,173,253,214,69,110,174,110,48,235,168,182,134,1,34,151,55,
+168,148,230,241,106,109,23,179,189,195,106,241,236,216,182,179,145,121,180,250,244,7,150,173,99,239,33,109,143,62,
+144,129,68,55,220,123,235,189,11,51,37,4,17,189,62,253,253,238,57,231,159,138,213,126,75,25,1,109,239,120,
+232,114,61,128,191,177,252,240,35,134,245,223,63,85,252,251,66,111,4,76,240,55,13,62,118,11,248,27,40,151,
+48,8,255,182,25,178,131,240,243,3,93,240,55,210,29,118,37,2,58,107,43,118,7,254,70,43,196,79,90,28,
+0,160,243,255,252,37,0,46,202,126,176,6,127,68,38,20,207,208,11,203,35,144,79,190,35,82,186,141,105,188,
+15,248,38,137,104,166,145,32,213,4,43,245,169,77,79,4,229,93,188,108,177,39,109,212,255,124,240,85,32,255,
+125,201,210,79,102,80,175,200,168,255,251,223,247,35,219,145,72,232,149,191,255,36,250,195,234,127,216,63,206,156,
+13,125,161,175,223,253,55,108,25,49,141,213,220,207,248,222,141,206,111,60,240,246,245,174,170,176,219,231,229,98,
+177,181,199,43,179,49,251,199,224,56,86,103,101,76,111,145,112,176,239,112,91,208,210,111,183,254,29,116,173,195,
+94,210,207,178,249,17,111,163,26,23,220,129,235,143,110,97,193,188,177,206,108,191,236,117,153,152,177,106,223,51,
+71,112,115,98,139,31,206,167,230,119,107,78,171,126,53,152,205,127,118,195,237,89,166,111,48,69,157,247,160,62,
+236,219,24,242,108,25,45,159,29,150,137,157,87,1,254,113,137,95,62,157,211,218,74,203,76,172,191,1,115,90,
+182,169,234,106,62,158,10,207,150,20,99,54,239,151,191,97,47,119,163,145,213,108,129,189,45,12,182,20,205,88,
+239,237,116,175,185,184,190,198,103,97,196,125,175,245,97,75,101,74,99,200,227,143,109,142,201,38,179,189,136,217,
+101,214,63,45,127,107,43,249,185,242,215,250,204,41,198,106,55,199,222,126,35,81,176,196,62,48,88,209,232,239,
+172,181,171,112,119,170,223,85,25,159,211,9,186,147,23,224,170,50,198,135,137,219,193,105,231,155,241,235,159,125,
+47,12,206,178,35,190,255,124,135,101,134,157,165,126,175,232,200,149,191,12,175,239,157,87,123,235,211,190,219,252,
+31,235,204,85,252,122,82,5,62,151,169,34,173,89,178,41,245,62,87,47,138,209,63,213,222,132,56,75,124,237,
+121,98,102,125,159,232,237,213,97,243,200,164,88,254,197,231,196,87,51,84,101,253,119,120,253,117,176,207,81,232,
+236,99,32,71,205,107,39,247,26,159,195,63,239,103,139,179,100,255,215,255,175,154,139,16,223,199,124,197,11,162,
+188,211,231,254,10,199,63,141,112,148,173,38,62,135,212,217,127,41,213,139,21,62,103,241,194,26,151,67,110,111,
+103,111,227,196,194,223,56,185,55,251,92,100,79,58,143,85,139,127,27,23,189,254,69,161,157,57,136,243,230,185,
+84,228,209,225,115,156,86,251,175,28,155,176,229,100,108,219,171,116,88,219,232,177,147,71,181,228,194,142,147,91,
+81,236,202,129,239,125,178,147,143,230,79,59,113,230,207,7,107,7,250,249,137,195,125,159,67,92,9,22,103,238,
+250,189,138,254,242,190,253,210,113,239,253,87,124,223,70,69,58,115,84,56,179,147,226,115,219,253,245,242,247,91,
+22,248,189,165,248,189,190,254,178,215,127,219,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,247,185,240,205,97,241,93,193,232,170,192,120,92,249,91,
+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,190,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,63,39,168,19,60,190,26,145,78,184,115,30,137,172,186,210,113,14,249,33,47,28,
+120,183,133,29,28,156,115,133,171,30,255,180,174,137,52,63,254,209,95,32,73,61,188,179,11,204,166,7,128,10,
+28,25,167,53,126,64,154,236,43,15,202,35,63,15,108,150,148,57,41,2,241,72,76,69,32,9,182,160,240,163,
+178,103,92,193,17,20,81,45,52,133,207,30,55,63,222,226,125,224,113,112,80,10,45,124,72,21,224,4,48,69,
+33,235,149,55,235,109,222,226,27,118,155,55,202,115,40,182,191,164,73,98,207,192,62,146,37,214,181,184,36,148,
+118,78,107,170,62,166,85,186,30,193,222,139,87,5,188,166,2,168,17,40,174,40,110,155,79,94,63,202,165,74,
+200,61,245,57,59,145,108,188,89,156,156,95,228,96,231,54,47,3,95,160,120,138,126,158,97,105,187,18,151,88,
+241,212,188,48,51,60,146,218,217,102,0,244,224,2,146,123,131,157,196,233,106,177,189,215,155,172,170,109,91,195,
+212,204,83,134,59,168,253,177,189,170,252,144,108,104,112,200,116,113,83,117,107,80,27,114,111,71,252,176,210,59,
+183,189,157,18,95,83,47,168,53,25,132,3,212,22,146,100,59,79,46,76,151,176,23,193,227,113,167,247,85,249,
+0,4,58,132,250,123,144,121,116,82,176,158,100,1,82,152,158,37,135,27,170,32,160,146,50,216,68,182,187,69,
+77,174,199,112,110,233,115,32,239,90,220,39,1,216,60,191,102,36,214,64,222,214,43,38,1,58,93,15,3,8,
+42,245,0,126,9,247,98,227,196,220,157,48,28,112,128,37,240,172,180,213,78,159,29,242,119,95,7,244,222,160,
+195,100,241,59,218,134,59,36,22,107,145,158,192,56,43,14,101,96,1,17,164,179,243,72,91,104,67,233,112,129,
+171,234,80,8,113,23,29,240,13,40,200,59,110,11,226,122,4,162,118,241,192,49,14,120,85,240,86,243,213,179,
+77,188,178,237,103,201,211,233,130,113,226,87,20,55,224,131,137,210,230,65,172,221,247,81,184,50,172,90,234,184,
+223,178,168,162,0,105,2,111,120,173,114,0,9,40,59,123,28,7,150,235,162,140,147,53,153,126,247,7,134,239,
+134,101,93,45,160,50,130,38,188,46,141,99,16,214,253,105,99,80,165,144,159,179,150,12,226,106,167,250,83,23,
+202,254,71,176,199,92,96,219,143,81,8,213,158,99,255,70,77,19,206,85,123,11,180,45,79,81,200,160,7,200,
+205,163,173,170,202,126,62,187,58,248,22,126,38,249,77,22,160,34,238,179,179,168,190,114,202,251,207,87,13,19,
+241,195,88,253,206,227,11,20,194,228,192,23,147,36,201,150,255,189,114,54,168,175,68,11,242,140,213,38,191,251,
+232,207,51,78,195,103,116,113,254,71,142,77,168,45,240,232,212,35,160,209,67,70,10,97,240,188,47,59,46,217,
+200,143,191,190,12,67,153,102,34,190,238,47,118,198,241,243,245,98,191,183,5,106,183,27,160,78,137,66,16,6,
+179,242,250,158,141,80,246,139,108,15,55,243,167,207,135,126,36,135,71,191,50,157,206,47,106,82,27,210,247,250,
+140,86,253,204,82,107,127,202,104,199,211,105,66,30,37,16,198,129,141,211,91,152,237,254,148,53,247,202,78,162,
+121,164,237,35,221,36,189,181,184,54,149,146,141,8,218,222,35,76,40,174,16,92,66,210,28,174,181,60,171,231,
+113,185,0,229,105,4,18,161,76,12,127,68,199,74,214,103,20,199,250,113,13,252,208,108,100,190,103,123,230,183,
+193,146,160,52,217,70,111,0,71,198,89,158,37,144,23,94,170,2,26,160,43,63,142,9,172,164,241,228,101,1,
+129,165,150,193,235,247,123,38,219,47,111,219,223,255,207,20,160,125,7,245,132,10,63,170,170,246,174,174,226,204,
+172,42,152,80,55,126,237,126,196,25,28,126,155,103,190,207,171,107,164,118,196,152,175,159,66,4,251,203,192,236,
+46,22,198,199,164,89,251,249,232,32,196,31,121,90,51,9,10,128,102,120,49,48,133,215,41,224,24,168,125,62,
+148,185,243,53,111,183,22,147,188,253,109,98,20,2,65,36,128,73,254,26,254,149,175,24,156,163,44,247,219,162,
+45,48,188,117,134,31,130,17,51,120,79,113,211,228,43,175,77,24,27,79,166,44,76,159,55,69,70,133,70,242,
+132,81,108,95,211,209,130,17,124,11,64,245,194,75,206,248,234,150,169,189,78,206,73,40,251,205,12,21,92,110,
+182,184,200,153,89,92,182,88,146,162,180,109,162,200,43,39,154,194,174,92,173,215,88,28,64,173,237,131,101,230,
+42,196,56,165,152,142,144,227,135,202,176,176,78,109,64,202,33,115,17,183,5,107,164,162,124,73,250,93,122,40,
+74,42,195,31,24,50,2,98,245,193,112,239,10,40,230,13,75,167,242,208,253,166,191,149,141,27,153,240,29,18,
+93,60,132,105,192,220,90,198,176,56,127,50,147,222,212,199,83,122,104,239,136,146,145,232,197,143,59,66,2,52,
+251,162,9,107,50,132,211,46,189,164,24,203,120,115,2,53,140,75,109,246,40,135,4,112,154,197,178,46,29,79,
+174,31,233,207,148,70,78,188,126,117,58,45,124,212,204,174,143,134,41,12,41,251,227,53,166,154,185,95,161,122,
+230,157,163,113,242,134,140,191,62,116,54,217,211,59,74,180,111,0,142,231,95,166,101,193,25,66,253,190,65,174,
+61,228,10,235,115,248,125,28,49,43,12,233,16,229,70,43,54,199,45,117,10,166,246,115,253,144,246,245,89,202,
+138,238,250,134,68,155,72,161,26,168,217,60,195,111,14,73,184,157,173,116,212,241,85,155,200,18,191,117,86,64,
+255,11,63,22,209,46,253,52,26,35,181,186,245,18,27,210,201,225,239,221,197,225,245,131,167,50,147,96,173,227,
+29,164,233,98,175,29,94,195,124,8,207,133,62,19,105,170,229,222,77,94,89,246,133,249,19,74,170,11,189,164,
+114,174,124,192,113,58,115,31,126,9,191,21,73,230,170,63,11,115,97,14,45,69,48,179,162,78,48,246,74,45,
+185,60,58,214,197,51,94,195,44,40,2,48,76,86,88,47,47,165,122,188,81,94,114,240,40,241,233,29,178,216,
+15,234,53,52,250,159,34,79,134,59,29,99,10,101,21,128,166,254,12,105,23,86,220,158,124,113,47,252,219,128,
+57,237,137,95,2,92,103,156,35,182,87,139,109,188,221,251,167,122,21,143,97,61,147,44,80,19,221,147,90,27,
+3,111,224,214,130,91,31,126,68,134,140,0,173,0,231,222,182,9,103,156,152,183,66,172,57,82,32,49,228,126,
+181,231,121,177,74,161,142,105,174,47,45,129,12,178,53,234,111,171,74,246,140,112,76,113,125,240,215,239,248,248,
+89,34,64,246,68,154,224,199,12,181,219,33,181,186,139,219,190,252,9,159,75,126,137,244,223,34,145,153,254,121,
+31,13,60,125,116,127,53,215,69,94,13,52,78,126,191,231,84,60,170,154,36,123,132,106,168,117,105,68,88,225,
+134,17,122,228,18,129,27,129,65,138,195,204,62,101,244,17,188,223,248,170,109,36,112,247,71,227,194,145,111,7,
+70,112,232,227,128,180,44,102,98,31,148,83,243,23,244,19,206,130,146,62,253,48,146,252,36,202,146,91,49,82,
+45,69,107,62,92,212,70,6,30,197,93,226,23,33,43,252,184,55,161,139,195,173,130,93,100,111,19,238,206,148,
+133,164,130,162,42,163,14,253,83,202,19,100,205,44,242,199,217,247,165,46,41,252,111,253,60,226,4,250,110,2,
+23,255,169,23,9,12,73,89,192,196,238,66,161,15,76,181,117,81,243,144,207,232,250,68,205,34,130,221,90,100,
+130,196,17,214,224,76,44,4,72,92,146,54,172,155,188,249,149,248,67,142,61,32,106,53,15,235,158,211,220,34,
+139,67,218,49,181,136,199,247,124,21,193,69,212,133,243,123,125,114,48,241,23,190,191,29,240,240,129,96,21,150,
+220,224,184,170,242,219,53,190,174,222,28,160,254,56,238,179,67,130,126,21,108,181,205,52,219,61,224,219,63,179,
+159,251,231,197,104,99,244,82,248,245,185,13,31,21,0,1,247,146,160,170,136,210,24,162,55,111,183,106,254,49,
+205,228,35,243,103,172,201,101,79,167,56,166,8,212,192,175,103,125,36,180,162,210,176,136,99,114,230,57,170,196,
+13,117,108,244,12,186,7,16,157,83,68,198,248,215,63,246,220,202,138,117,111,224,16,188,200,225,90,154,252,137,
+232,248,166,52,29,7,15,240,40,18,225,228,176,74,17,232,195,22,219,157,150,75,148,167,130,191,160,175,155,86,
+103,69,142,43,219,90,203,123,45,54,151,253,244,7,68,203,43,93,9,70,84,79,185,190,239,117,164,152,50,158,
+141,255,95,187,57,106,245,192,60,116,198,75,253,16,134,253,187,104,124,185,18,237,125,48,41,174,69,229,83,78,
+52,122,83,241,46,113,147,175,47,171,90,83,227,191,145,56,36,156,253,11,228,149,245,135,59,213,26,128,45,171,
+4,248,59,86,148,152,151,57,99,190,95,130,194,61,4,229,171,194,111,46,38,168,122,94,249,234,40,222,71,113,
+181,98,83,192,160,121,133,213,69,53,130,53,98,221,96,207,218,43,199,229,138,131,234,159,239,144,162,126,100,210,
+184,76,20,237,21,108,201,111,203,127,199,56,185,94,162,187,80,173,2,234,23,135,42,122,104,0,192,145,76,82,
+171,167,115,95,149,0,136,106,99,128,63,172,87,241,76,87,252,71,60,102,101,159,54,121,193,86,170,45,151,132,
+119,121,68,148,152,95,89,69,144,160,74,104,111,182,44,50,28,81,50,184,92,123,160,79,52,161,197,108,190,176,
+94,191,241,86,29,8,240,163,163,251,180,163,167,32,34,249,39,208,248,30,47,187,69,250,43,203,59,79,114,66,
+133,172,240,237,248,212,252,120,11,66,205,180,244,163,131,132,215,30,64,0,170,193,63,44,136,172,126,178,61,253,
+237,176,230,207,105,31,24,78,18,29,252,50,54,84,221,90,198,52,239,225,37,194,1,114,42,85,201,204,55,63,
+177,17,77,86,94,108,143,59,134,106,213,118,90,188,156,170,156,189,253,113,42,182,160,187,205,59,60,95,149,234,
+137,54,80,123,90,4,114,0,28,23,248,135,18,44,68,62,4,243,55,33,106,228,169,71,150,195,193,124,83,102,
+161,174,106,205,11,172,150,190,191,206,44,161,79,160,42,64,209,124,241,24,31,86,76,120,181,38,131,185,27,82,
+34,94,239,7,175,187,73,241,182,205,115,33,143,250,113,183,58,27,31,239,70,215,124,144,91,86,243,43,30,98,
+162,186,144,229,60,191,24,74,181,79,123,74,174,157,182,115,52,242,81,125,125,156,101,115,24,184,147,163,202,139,
+97,213,176,38,140,62,128,193,71,160,239,164,56,94,34,55,211,36,214,196,132,90,185,65,248,218,46,96,119,246,
+226,243,79,19,184,227,35,92,21,190,209,149,42,47,87,246,248,244,226,108,105,249,247,226,91,137,114,253,0,169,
+64,55,37,230,135,212,61,117,127,46,206,43,193,87,22,156,153,196,44,206,179,57,83,213,235,231,227,140,94,53,
+101,12,154,55,121,47,209,115,162,135,234,79,248,123,147,232,184,220,31,178,137,4,36,14,9,160,249,182,120,167,
+29,56,116,57,189,11,235,93,245,96,111,0,0,219,114,91,248,165,210,157,206,132,190,17,62,107,10,0,3,247,
+6,205,23,0,235,175,117,154,151,251,0,206,25,185,168,7,110,135,10,2,190,43,207,85,36,18,78,35,177,35,
+146,188,121,92,98,18,53,74,134,187,234,94,32,108,68,77,68,200,247,68,158,63,84,8,16,132,76,25,229,43,
+195,23,246,177,18,227,251,102,104,255,153,47,245,15,245,129,141,47,192,159,119,78,209,254,240,208,54,26,25,246,
+178,184,210,92,213,98,82,138,143,187,140,80,156,26,34,130,98,221,111,65,50,36,155,81,240,154,223,90,122,67,
+240,209,139,197,13,217,122,229,45,214,64,173,150,239,181,139,250,242,174,113,117,138,18,229,2,43,94,24,230,222,
+62,127,177,164,127,60,228,202,18,66,125,191,243,198,241,40,124,180,126,124,226,59,254,101,187,78,204,22,105,243,
+237,116,111,33,27,128,168,152,107,182,209,165,14,126,41,11,57,48,200,83,216,28,210,245,26,204,69,39,179,210,
+238,201,230,150,204,163,67,233,208,182,214,211,212,168,143,227,119,33,104,118,87,21,117,83,134,225,115,185,106,91,
+144,61,118,166,60,1,214,147,241,219,27,161,33,160,251,179,59,153,5,173,128,140,230,155,157,192,89,85,61,100,
+9,207,53,16,39,28,30,46,27,210,219,115,65,77,1,209,94,126,169,142,197,47,123,174,246,183,122,124,54,251,
+116,65,7,184,10,185,241,83,104,38,117,26,78,65,112,85,31,192,24,234,214,2,173,230,153,241,24,182,199,62,
+144,10,211,45,192,137,5,87,172,98,161,174,249,33,232,92,85,229,92,225,147,159,31,173,22,101,230,41,21,97,
+128,60,245,19,188,189,40,138,68,50,4,78,38,248,45,28,191,47,209,57,80,1,0,74,18,156,98,156,85,80,
+78,250,45,13,224,116,68,78,36,163,81,210,53,29,136,151,27,74,126,19,126,25,171,109,101,177,6,208,126,53,
+169,154,212,106,244,104,42,73,125,50,97,34,183,4,8,214,52,206,219,207,77,231,229,91,19,49,146,20,106,31,
+145,173,136,185,38,132,11,112,17,127,234,174,172,129,90,5,178,218,233,5,23,223,121,29,46,111,251,228,24,79,
+21,14,159,158,98,84,176,94,55,150,45,145,74,66,10,46,4,190,222,164,96,47,65,9,170,91,8,130,66,58,
+192,66,108,114,104,2,160,57,31,25,120,187,134,201,170,86,111,117,71,3,205,69,8,34,240,215,9,123,35,145,
+162,87,29,0,232,215,135,92,121,81,241,42,183,48,49,158,95,32,172,8,106,64,176,6,71,17,218,7,187,18,
+172,194,121,84,253,91,167,224,243,42,68,54,160,154,81,6,90,136,196,19,43,247,226,240,242,235,19,106,134,136,
+152,167,222,144,118,49,188,65,39,249,143,79,247,6,238,118,228,23,7,34,139,230,205,86,28,44,205,189,222,130,
+170,6,212,83,200,244,75,243,77,224,1,81,187,184,205,54,124,0,128,235,8,234,16,158,95,160,25,247,41,100,
+188,250,102,155,131,89,213,69,51,253,195,94,222,4,197,47,182,164,113,52,250,235,10,158,89,28,125,35,219,31,
+250,195,116,4,33,84,75,176,127,24,99,233,144,88,123,127,136,27,211,186,247,65,71,126,232,8,204,27,248,173,
+27,111,207,248,164,35,86,120,76,183,157,168,22,113,23,0,104,84,29,116,170,207,219,39,185,178,250,116,181,192,
+3,38,4,240,122,163,158,84,107,87,50,163,31,240,192,33,181,141,242,4,186,5,154,223,181,188,70,46,116,95,
+72,229,195,116,22,105,103,94,41,246,76,252,3,100,150,40,31,3,217,33,219,68,165,195,247,53,190,88,120,169,
+61,67,251,25,149,45,104,107,145,179,121,237,193,74,182,44,54,1,218,79,180,140,93,171,130,163,62,232,235,228,
+174,242,99,250,6,84,169,66,4,165,241,49,159,196,248,88,55,107,97,232,90,52,244,160,23,159,179,89,69,149,
+160,86,154,242,121,176,2,75,178,180,250,77,191,136,74,165,243,163,202,94,45,134,166,100,201,14,50,198,86,238,
+33,72,0,42,4,158,21,190,237,112,152,60,141,23,21,39,36,31,219,2,213,227,131,138,1,139,211,28,78,57,
+179,12,209,38,215,125,150,128,156,199,48,99,39,10,32,236,213,0,220,63,5,205,252,49,40,17,225,165,9,0,
+46,106,187,160,93,88,164,199,11,218,169,163,250,191,31,110,140,36,18,168,96,194,61,60,95,189,122,155,156,175,
+1,67,26,134,53,40,2,160,206,43,78,191,85,190,173,1,201,46,175,227,237,138,224,24,248,231,110,249,235,178,
+235,90,236,243,198,77,91,50,188,116,100,158,37,231,35,134,17,63,128,167,127,172,100,132,189,86,220,140,37,52,
+169,209,191,170,96,255,138,158,160,74,66,79,79,238,248,12,250,250,253,13,203,129,124,226,243,235,214,64,253,16,
+139,159,7,18,218,1,6,170,192,55,208,83,33,153,63,181,36,13,224,82,41,168,202,223,219,77,84,46,230,223,
+33,203,177,168,175,188,161,16,177,223,24,212,122,114,170,103,135,2,211,228,126,33,163,8,138,62,123,13,198,149,
+59,203,157,110,193,213,245,62,27,3,40,239,21,115,32,148,163,40,204,206,107,26,95,218,123,137,239,253,117,185,
+181,223,212,77,177,11,70,168,246,3,109,124,152,82,225,57,17,107,21,199,223,123,157,221,31,161,166,88,6,5,
+166,111,172,143,202,240,133,122,235,197,54,87,225,9,23,213,170,63,74,34,90,149,67,86,117,125,242,167,218,237,
+177,135,140,76,243,225,119,194,101,86,193,8,13,182,165,187,35,181,47,210,255,145,95,10,78,104,100,31,151,60,
+72,87,209,233,199,179,15,3,117,48,224,156,171,83,198,93,174,218,131,76,76,4,146,114,40,23,208,20,93,202,
+53,0,230,24,161,164,20,230,245,253,243,167,80,46,144,174,56,170,3,103,43,40,92,124,205,115,88,8,47,141,
+0,141,139,35,207,146,152,73,68,123,167,141,138,8,109,139,141,139,103,42,0,221,3,160,182,149,104,196,17,186,
+42,95,2,188,138,12,253,207,2,109,225,185,75,103,169,74,67,74,139,174,191,41,58,104,55,115,17,64,76,21,
+24,64,88,99,173,164,217,196,106,184,4,243,41,234,31,127,58,220,44,121,196,107,33,61,248,154,83,143,111,108,
+39,160,48,10,27,22,124,34,96,97,252,40,205,70,116,39,91,176,253,203,240,188,86,21,129,199,124,148,158,210,
+126,0,98,184,89,41,218,54,164,11,1,66,245,123,161,180,241,95,114,37,173,34,45,21,47,66,123,61,125,0,
+97,35,178,214,241,117,130,218,173,181,23,62,227,63,231,55,45,59,187,146,145,11,102,37,77,90,103,28,101,27,
+197,64,119,232,83,58,128,193,96,161,16,191,7,143,122,47,133,237,13,210,246,167,29,254,76,186,182,188,177,75,
+146,9,197,141,199,226,69,69,113,119,104,161,26,32,133,66,228,58,187,133,155,252,45,182,148,63,124,159,231,103,
+149,54,209,223,190,97,117,81,102,94,127,11,237,45,112,53,185,57,181,41,36,193,74,40,37,201,205,238,24,191,
+244,54,205,169,248,17,200,201,29,248,184,119,145,177,217,0,207,22,87,237,57,50,26,7,72,189,222,126,183,55,
+124,187,225,27,1,17,106,170,33,207,154,111,55,164,235,127,4,198,170,245,2,96,114,85,192,35,101,110,239,192,
+150,223,78,178,31,178,179,35,189,125,198,217,221,15,209,101,178,119,163,138,162,102,180,170,223,161,166,11,85,32,
+124,9,188,128,53,164,116,55,4,167,162,6,173,197,174,225,214,139,89,216,214,180,239,214,107,129,86,68,31,162,
+161,2,7,184,2,206,89,24,167,213,84,229,204,55,235,35,73,79,128,121,55,207,136,88,67,233,93,64,91,168,
+165,47,64,145,225,203,160,219,94,44,141,217,23,187,57,191,238,132,245,168,104,70,58,25,138,49,66,33,241,122,
+45,239,218,1,5,192,57,91,76,253,145,131,14,98,35,78,208,17,54,138,218,149,191,213,84,56,82,78,195,26,
+120,205,21,62,234,67,50,204,1,192,113,6,254,207,85,245,107,115,118,82,114,199,14,0,93,114,51,51,246,231,
+87,91,119,117,242,2,63,14,3,158,13,204,26,84,10,59,57,109,155,56,100,2,85,253,243,152,220,225,22,199,
+79,180,32,144,172,190,0,21,172,218,191,149,218,169,0,230,224,13,153,184,188,34,140,212,105,208,128,16,141,142,
+10,133,226,13,167,39,161,166,56,120,48,85,12,7,197,114,91,204,172,125,78,172,157,143,194,115,10,134,239,212,
+217,81,133,147,51,182,26,208,101,154,251,13,36,245,230,108,210,151,166,155,242,106,160,83,154,106,57,162,160,239,
+81,230,240,236,184,78,20,192,60,188,190,83,240,144,232,70,36,190,18,222,92,16,50,43,124,185,186,15,181,26,
+158,2,126,10,159,36,182,250,27,22,178,196,180,203,183,214,162,190,126,72,107,71,244,174,121,52,15,230,42,190,
+79,208,1,51,255,62,148,26,142,158,16,203,238,197,201,79,127,194,136,139,141,155,45,15,213,221,122,4,152,172,
+234,0,0,206,193,204,202,249,238,182,130,88,219,247,194,182,46,195,65,122,78,11,234,95,232,78,247,31,75,123,
+125,17,74,117,82,3,81,56,41,31,140,162,42,198,192,235,226,89,178,230,72,154,97,36,21,95,5,120,107,245,
+208,93,255,15,149,212,141,35,86,94,139,35,122,97,95,233,150,66,139,213,50,193,157,232,216,199,194,177,169,222,
+184,237,52,70,133,42,193,125,75,47,149,2,250,174,92,245,189,190,238,53,85,215,104,240,106,15,105,163,164,75,
+82,164,121,58,53,246,89,35,62,158,74,236,156,200,172,83,15,234,192,104,149,241,76,104,231,146,20,253,54,147,
+91,206,62,145,126,144,151,22,106,174,130,74,193,208,234,174,187,76,191,70,60,101,202,60,71,10,197,247,49,206,
+72,181,84,157,86,84,42,15,199,62,74,88,35,105,60,10,118,98,7,252,183,8,212,198,133,53,228,244,194,77,
+174,180,211,22,219,79,132,64,165,21,40,135,153,40,90,152,41,59,194,8,232,111,221,193,72,39,204,143,81,108,
+10,187,167,131,232,139,33,80,76,169,85,3,55,181,154,72,236,228,213,110,162,230,75,113,88,162,26,170,184,95,
+161,74,192,160,54,122,26,35,227,172,112,143,102,115,147,233,87,228,2,24,187,211,218,126,253,35,127,190,120,192,
+231,157,192,217,65,173,60,83,81,218,4,102,15,248,26,71,141,23,130,102,244,244,34,144,51,80,212,62,82,9,
+15,167,22,80,200,249,205,64,133,194,192,119,82,2,28,153,191,209,78,7,169,18,166,223,99,152,187,244,27,61,
+6,163,163,13,251,166,64,245,66,98,240,220,42,50,188,199,7,11,239,98,125,18,120,101,167,88,210,74,166,243,
+49,133,242,43,210,157,6,130,160,254,181,252,4,19,216,83,117,135,38,55,92,188,242,148,218,51,234,211,126,178,
+66,217,49,177,56,85,33,98,120,59,80,126,151,8,42,100,136,181,61,182,39,197,148,54,153,45,219,60,100,192,
+156,117,99,165,205,211,16,149,186,4,35,71,251,117,237,13,218,75,216,26,255,82,213,183,214,171,72,119,43,251,
+34,175,6,111,77,168,119,106,214,173,254,32,232,234,90,76,168,238,215,149,152,131,175,161,143,56,142,171,48,179,
+95,223,245,144,107,214,48,71,83,133,2,52,166,159,230,250,46,228,165,183,12,130,95,186,62,86,16,138,170,230,
+22,139,45,113,162,89,167,116,175,153,54,119,251,158,100,82,234,31,171,155,25,36,227,246,213,137,151,58,161,166,
+5,90,71,100,18,172,72,162,244,198,133,16,85,223,127,236,243,5,157,212,72,135,20,25,3,100,220,208,118,127,
+84,119,122,152,79,156,250,218,197,239,33,19,67,8,200,203,4,149,220,127,52,237,53,104,133,182,230,19,215,120,
+171,253,69,162,245,121,82,254,236,91,114,29,96,20,102,244,30,155,188,17,111,151,142,61,225,192,164,227,116,88,
+37,205,211,159,154,184,220,239,103,51,184,151,80,179,15,242,175,136,218,22,252,243,112,59,186,207,218,193,12,119,
+213,71,131,59,117,15,159,46,204,203,124,120,207,4,14,32,33,242,124,189,80,13,50,107,37,30,8,185,170,161,
+209,28,214,166,77,0,159,170,195,6,29,247,87,203,36,151,162,232,62,10,144,195,56,97,55,244,186,211,46,41,
+127,177,68,247,105,123,219,166,103,52,107,168,75,209,164,230,15,246,76,121,197,125,131,203,145,84,195,75,127,143,
+231,74,206,39,125,65,183,0,180,126,191,94,250,21,246,204,29,219,175,172,136,24,241,48,223,202,247,120,63,45,
+7,18,1,6,110,139,164,111,161,237,143,243,42,230,8,101,99,42,31,106,108,110,110,18,88,133,106,194,190,114,
+19,66,242,189,129,252,221,25,107,122,29,211,114,159,216,127,203,252,21,89,195,244,133,165,251,227,72,104,31,8,
+157,66,33,92,5,69,192,169,251,52,123,72,137,98,114,217,158,170,123,244,194,231,222,241,4,154,179,196,75,92,
+153,154,107,88,170,8,100,7,19,218,161,51,193,231,117,181,200,41,141,0,165,211,241,39,245,185,146,23,40,136,
+99,106,191,86,93,244,170,223,92,153,217,198,151,134,15,253,51,255,36,154,195,155,220,251,23,188,132,53,200,90,
+141,202,8,247,48,241,237,23,188,53,215,90,160,29,140,129,206,7,153,88,74,212,215,34,2,2,14,128,134,70,
+226,187,75,37,82,87,247,177,34,238,243,185,248,77,87,31,208,185,211,81,242,70,187,154,213,172,162,199,7,89,
+121,53,116,213,96,176,227,32,251,166,141,219,35,234,98,150,71,207,230,181,75,162,146,121,59,66,159,229,161,10,
+149,80,219,196,67,109,83,198,7,38,215,1,255,43,28,223,225,3,154,184,38,199,233,153,175,143,12,63,16,254,
+8,48,215,184,153,82,112,107,10,243,9,87,102,174,195,28,216,83,192,50,233,240,9,88,43,124,50,141,177,165,
+244,138,151,48,149,41,7,37,17,127,155,163,58,235,111,102,102,233,227,122,254,116,243,81,40,170,2,40,73,28,
+173,207,46,62,234,159,135,47,50,103,10,215,107,16,41,254,173,38,242,154,92,133,76,221,134,246,145,97,64,129,
+108,49,211,182,22,79,224,211,104,184,5,61,40,101,249,54,29,46,86,129,118,151,10,167,131,146,24,182,94,1,
+206,150,106,207,230,232,6,164,83,69,194,129,219,235,5,127,236,5,34,221,18,67,51,96,56,233,37,209,76,230,
+71,149,210,158,39,35,48,115,191,45,173,224,65,89,27,137,215,98,89,93,202,67,210,164,143,33,117,226,88,108,
+95,78,38,210,69,127,68,211,83,149,237,193,69,74,45,130,177,188,11,134,36,2,147,118,131,90,245,63,101,246,
+196,67,187,205,234,238,204,186,46,208,94,3,33,34,119,136,2,61,146,186,105,208,66,167,102,188,73,138,151,130,
+0,193,194,81,80,57,52,19,148,169,2,143,88,106,87,71,23,50,17,47,187,136,234,92,53,242,69,76,241,199,
+16,53,47,127,41,30,31,146,107,195,23,240,159,218,176,60,207,177,230,36,175,182,28,88,243,60,226,2,221,253,
+104,143,71,246,251,144,5,134,111,129,121,48,146,7,149,230,155,163,172,105,220,64,29,183,22,118,210,211,95,148,
+239,60,85,177,96,134,209,145,90,219,75,186,253,90,113,236,77,45,67,196,164,172,254,25,134,220,36,52,113,136,
+92,53,141,205,140,162,196,0,162,34,58,174,103,126,50,52,74,244,42,35,222,117,144,245,4,52,93,158,161,23,
+174,82,151,216,125,123,84,107,225,114,51,162,58,74,68,17,113,197,67,160,196,122,117,128,142,148,152,79,178,207,
+205,115,157,247,20,149,26,13,138,230,222,249,54,123,237,206,88,140,209,54,13,119,41,157,176,215,143,91,141,186,
+249,59,152,98,151,248,117,240,97,152,45,9,122,36,29,110,3,2,91,150,0,2,54,104,2,254,161,20,93,226,
+133,170,75,135,109,87,196,69,10,68,29,124,108,255,85,223,121,52,139,236,39,58,178,240,181,218,170,192,153,47,
+229,10,98,118,75,252,172,46,205,190,113,208,40,182,249,226,1,13,87,7,101,182,214,151,5,243,128,141,100,104,
+63,174,19,32,88,64,176,32,11,86,117,254,18,65,173,206,238,187,103,202,220,71,1,112,119,161,211,10,41,200,
+91,178,124,54,158,46,218,192,7,119,130,24,1,83,89,154,171,223,8,136,83,7,220,177,35,172,207,142,131,224,
+48,48,124,186,55,43,117,192,39,17,191,20,114,235,175,215,34,47,17,196,31,77,36,54,94,197,74,119,223,224,
+19,13,207,227,51,122,94,112,204,246,94,221,209,51,39,243,190,49,232,69,194,191,46,74,15,55,1,202,56,187,
+10,126,202,46,250,164,110,59,202,19,201,249,238,135,171,94,29,184,201,218,24,242,68,245,161,0,174,195,200,42,
+40,3,222,195,167,43,170,7,51,77,62,15,176,134,135,126,72,208,213,208,230,158,195,53,175,92,73,226,115,76,
+87,160,79,138,245,237,170,20,94,45,212,125,38,11,44,66,85,80,181,2,129,239,44,190,91,248,243,20,138,231,
+105,103,175,250,237,243,134,232,161,169,232,1,141,26,35,139,167,212,228,0,145,99,210,60,132,237,43,6,123,110,
+124,72,85,27,184,150,2,141,173,219,32,201,4,254,135,127,126,218,67,123,86,142,141,161,38,186,117,236,157,195,
+139,222,147,224,110,61,239,122,163,249,52,53,117,123,155,135,77,251,124,240,147,11,12,87,56,236,141,249,186,158,
+157,87,225,164,223,4,61,50,240,128,229,131,197,141,30,186,120,77,196,92,203,185,22,124,95,106,185,100,26,109,
+22,248,78,225,43,151,113,227,247,117,145,228,77,62,242,75,8,35,25,120,253,188,200,150,250,250,96,111,147,157,
+122,165,44,177,8,239,42,223,127,163,222,231,60,185,226,91,165,99,106,124,93,56,134,93,95,5,186,181,6,131,
+148,93,42,95,226,227,240,159,7,82,120,238,197,69,7,203,3,3,94,135,16,122,11,24,37,70,57,248,23,217,
+63,30,142,73,26,219,30,84,176,201,137,134,113,103,48,75,239,10,246,164,162,97,244,246,179,51,252,137,35,156,
+107,123,117,133,14,109,81,134,99,206,140,194,61,47,209,195,12,226,120,150,251,55,60,59,209,192,8,22,164,247,
+171,246,16,215,219,111,153,127,211,250,33,131,67,87,245,95,76,91,178,105,202,70,172,57,178,133,151,24,131,57,
+52,126,200,50,218,173,177,83,251,75,2,255,31,168,121,33,45,206,157,86,215,245,223,83,23,248,223,125,189,101,
+179,255,143,187,235,236,110,219,134,162,223,251,43,216,109,157,3,182,150,247,81,195,248,152,217,81,119,118,151,13,
+69,116,24,71,34,37,2,20,165,52,63,190,239,226,17,160,192,74,206,222,11,48,136,55,240,0,61,128,58,184,
+55,23,131,207,130,214,175,11,146,57,164,215,95,242,13,248,122,111,100,111,247,186,107,174,246,90,239,139,94,214,
+157,143,86,92,214,53,215,115,231,106,249,154,238,197,59,19,130,244,14,147,64,231,1,209,112,93,248,94,94,60,
+241,111,20,187,123,196,208,98,224,201,187,112,226,207,47,79,183,240,251,111,252,80,131,27,194,189,77,231,192,22,
+60,128,29,139,4,14,119,94,234,78,240,157,21,200,248,213,119,131,19,131,228,200,150,144,28,10,72,142,203,142,
+199,34,25,82,91,11,132,183,21,164,244,151,92,47,200,215,221,205,198,111,96,171,77,247,204,117,207,215,94,233,
+47,132,164,177,80,161,169,34,80,73,108,37,67,229,39,32,117,168,231,132,123,74,92,226,207,113,137,63,143,138,
+149,151,248,61,179,38,58,5,49,195,112,116,132,41,147,186,244,49,49,191,189,110,180,46,189,64,168,30,21,73,
+146,125,2,193,186,214,14,150,207,109,37,134,162,20,19,49,22,3,113,44,230,226,137,168,196,76,44,196,145,184,
+37,46,139,123,13,241,211,213,141,88,76,29,111,79,12,23,159,22,189,171,133,97,44,252,61,186,74,70,196,89,
+244,59,21,141,76,162,255,47,116,175,232,93,103,161,219,81,162,33,117,35,186,13,169,242,57,176,181,220,194,30,
+223,24,104,237,231,53,160,181,178,5,90,219,255,155,201,87,250,17,19,240,222,203,188,81,46,86,140,242,110,209,
+123,192,163,156,233,104,97,134,153,234,104,166,61,193,91,45,65,144,24,252,86,244,238,176,96,165,163,91,70,80,
+233,168,66,101,221,18,247,200,48,206,12,19,70,102,150,189,106,58,221,48,205,185,105,46,154,102,217,32,102,31,
+154,103,169,167,44,109,131,97,108,130,174,194,189,32,13,247,218,40,24,252,89,3,3,1,10,100,21,218,197,0,
+89,182,131,93,139,105,234,18,248,42,237,90,136,83,183,75,42,27,184,169,65,155,62,165,238,221,205,151,233,79,
+232,23,95,255,222,114,119,26,135,223,31,219,208,227,137,239,167,5,178,56,16,203,169,9,215,176,9,37,1,26,
+75,159,53,102,98,186,244,191,249,166,111,130,63,48,63,30,55,18,169,54,237,79,76,123,213,180,207,154,170,66,
+23,134,225,185,20,197,73,33,112,120,15,3,247,216,10,66,6,122,236,6,21,253,77,195,174,37,173,192,84,113,
+173,238,177,7,44,182,183,205,121,248,152,229,141,84,142,70,65,34,85,18,18,229,125,34,139,22,172,198,229,69,
+221,84,7,69,160,82,57,204,171,165,93,55,104,237,218,38,133,170,102,64,214,29,148,214,163,243,0,60,42,45,
+136,129,63,164,1,134,219,123,192,181,236,154,125,250,32,224,200,56,124,12,195,192,165,129,129,143,214,34,215,101,
+141,0,31,193,43,249,34,200,117,233,193,194,209,146,250,231,7,223,221,214,80,16,23,203,43,178,25,84,112,155,
+254,158,230,68,37,212,203,75,141,72,27,112,78,221,196,209,12,235,39,110,108,240,138,217,77,12,61,158,241,162,
+240,189,104,208,80,110,39,113,190,12,18,93,37,73,198,113,243,220,229,120,166,97,13,7,28,58,157,227,232,196,
+102,88,86,102,231,203,164,215,192,91,80,92,121,4,219,110,178,176,4,79,71,52,148,5,227,144,152,249,5,214,
+78,96,232,216,25,154,191,140,33,59,160,36,27,90,141,228,254,88,211,250,55,106,103,107,98,178,134,183,5,58,
+236,238,47,233,231,214,230,207,147,167,198,173,73,100,158,153,186,112,146,38,126,149,179,191,56,119,88,231,226,215,
+236,200,6,24,26,2,230,31,90,142,162,19,63,40,214,14,105,102,246,28,152,26,203,121,72,235,120,123,19,139,
+154,12,214,11,107,62,178,53,69,43,43,9,187,52,158,167,200,30,150,27,199,186,233,150,158,225,25,226,141,235,
+23,42,52,85,24,222,137,205,199,28,120,201,34,55,101,92,40,236,63,224,167,104,158,228,92,20,40,10,33,185,
+120,200,69,202,207,78,185,24,26,250,173,82,12,157,244,80,76,234,180,58,166,122,163,115,192,197,49,50,43,61,
+58,94,122,244,132,139,10,5,157,111,144,88,169,199,172,238,113,203,16,236,18,122,251,94,244,103,158,208,8,154,
+173,127,151,240,234,212,148,46,53,237,253,221,33,26,95,203,149,20,139,63,167,127,19,112,27,39,55,156,130,226,
+14,216,178,206,192,77,202,231,161,152,10,180,80,34,247,2,212,233,136,219,16,194,41,168,150,186,1,41,62,15,
+197,84,160,133,164,188,224,185,255,32,229,106,2,36,252,212,32,225,175,38,22,10,31,183,207,74,29,49,197,193,
+18,93,214,33,225,227,243,145,240,83,70,194,67,69,27,10,63,53,80,248,152,79,76,42,209,212,165,35,98,58,
+34,29,246,15,55,250,223,33,56,83,40,216,49,156,106,125,209,5,219,102,63,186,151,97,120,188,41,214,237,162,
+153,75,234,211,39,107,96,180,21,18,79,29,117,107,63,194,115,178,150,209,51,80,75,221,122,246,204,140,110,140,
+56,154,252,20,191,149,252,132,201,241,82,33,237,209,26,54,113,182,179,147,151,106,204,158,61,230,197,168,152,86,
+12,211,91,144,158,235,115,168,153,27,215,223,64,198,131,35,94,42,237,136,74,71,100,1,103,201,218,81,165,15,
+149,174,231,166,183,161,140,215,246,140,25,163,66,94,43,120,237,125,72,124,175,23,240,122,193,94,191,145,132,6,
+199,188,100,185,108,237,8,214,86,36,185,248,173,38,185,22,109,215,145,97,121,136,137,138,29,44,15,173,179,158,
+136,121,37,115,42,161,158,57,122,202,21,189,164,237,5,198,7,116,138,235,23,56,100,12,124,210,241,239,239,36,
+88,103,184,33,47,30,20,138,139,203,36,11,58,197,123,222,75,94,31,220,95,30,127,160,101,247,10,20,4,254,
+173,143,227,183,229,160,151,27,146,47,247,109,65,77,250,149,74,5,54,8,229,211,126,149,244,185,195,171,80,42,
+179,71,201,23,162,236,16,195,113,182,76,139,90,70,163,156,184,8,111,233,156,70,153,128,99,247,6,237,172,27,
+95,224,176,117,76,243,52,146,19,133,215,236,31,74,75,231,85,34,65,233,162,4,104,186,161,250,52,42,185,195,
+231,170,35,60,165,106,141,82,161,14,89,81,175,70,47,83,228,211,55,166,233,212,104,26,109,44,39,211,97,221,
+230,113,141,180,169,208,16,179,47,154,120,131,203,172,100,46,180,156,168,56,155,7,68,119,230,38,193,117,234,138,
+2,157,108,59,245,177,19,227,186,108,9,73,93,108,51,72,209,248,133,94,53,175,244,150,28,237,126,241,82,228,
+104,253,66,92,3,57,154,183,92,54,69,179,84,186,194,45,147,45,143,43,237,231,236,124,76,251,250,175,89,240,
+70,16,110,183,14,90,222,219,13,232,244,24,198,142,218,75,125,173,118,246,202,110,45,146,17,54,131,221,23,119,
+44,168,228,99,13,218,66,153,61,30,255,199,222,113,104,57,114,194,126,133,244,230,225,16,157,244,222,123,47,175,
+205,219,231,45,239,188,158,203,120,211,147,127,143,164,25,108,121,103,247,182,94,191,20,64,66,18,48,8,33,56,
+159,104,169,249,11,117,245,227,227,215,52,183,139,240,66,133,37,21,122,156,23,44,175,100,28,52,186,39,58,160,
+112,43,28,130,179,98,56,212,71,5,254,218,0,34,222,135,175,152,26,239,163,162,86,53,88,90,152,37,245,41,
+166,89,189,67,169,14,193,218,236,83,80,16,180,247,41,65,112,179,162,32,98,242,14,196,90,77,168,36,169,9,
+66,57,137,165,149,49,5,131,60,148,85,58,5,101,45,20,64,89,67,233,59,118,93,207,72,144,12,12,169,79,
+49,75,72,104,53,24,31,98,161,78,91,55,75,58,151,224,157,9,4,20,164,66,169,1,201,48,139,149,82,9,
+38,24,228,97,231,28,165,239,64,229,39,8,36,19,144,160,79,129,7,45,154,217,48,36,229,102,36,135,199,232,
+100,143,221,56,66,27,104,52,158,71,232,107,45,227,130,36,15,60,62,158,133,196,9,205,196,214,167,77,27,129,
+69,101,234,210,166,18,161,34,105,11,205,194,240,249,97,76,121,18,64,54,9,32,39,1,44,119,17,172,156,4,
+112,146,129,33,20,198,67,102,141,249,185,42,17,107,229,59,221,33,254,93,19,92,79,223,236,183,183,230,181,234,
+148,88,66,84,197,23,18,24,200,247,240,201,177,188,160,192,194,96,181,225,127,102,106,93,124,1,215,234,17,85,
+54,62,172,81,27,150,70,240,52,130,169,6,58,226,238,225,86,177,115,115,191,91,28,54,7,100,47,155,27,205,
+135,221,225,28,179,175,113,249,207,251,74,75,129,123,111,206,55,145,146,4,178,169,11,10,110,19,84,169,94,133,
+161,136,122,199,52,137,191,227,111,253,57,141,192,67,200,179,99,248,224,150,181,66,171,66,157,208,112,145,232,64,
+100,177,112,59,33,139,213,161,197,234,69,232,30,50,100,156,241,181,53,6,220,70,91,134,17,7,187,169,45,251,
+117,99,203,196,101,240,32,183,62,13,134,39,149,241,9,158,215,224,141,85,251,242,178,253,111,120,139,107,206,119,
+158,175,45,143,221,120,174,216,37,61,122,13,159,124,170,157,36,228,80,152,213,222,98,199,134,154,37,57,141,36,
+172,99,239,124,197,110,46,139,237,48,35,12,203,35,1,71,226,197,172,25,189,194,246,223,48,48,228,33,226,19,
+198,247,243,244,74,253,178,214,186,59,209,114,127,141,132,232,113,45,230,77,184,78,251,109,141,102,155,242,169,181,
+92,32,235,167,157,205,222,38,32,208,122,76,117,76,16,146,45,12,33,29,18,97,97,77,167,36,139,87,131,36,
+143,34,13,23,200,134,87,9,4,66,145,188,4,177,72,40,178,37,201,2,170,246,242,103,245,25,140,253,117,99,
+119,125,149,100,9,12,82,70,24,37,7,217,158,164,247,202,141,93,133,177,167,102,100,206,137,97,208,6,124,112,
+38,186,121,3,81,138,49,163,236,102,155,68,54,191,37,11,212,216,241,43,89,62,17,69,237,73,163,29,35,187,
+113,38,105,64,17,63,163,211,49,196,28,60,131,64,195,168,8,134,28,146,240,87,114,222,129,15,89,73,6,163,
+128,82,36,49,181,158,192,34,233,11,203,40,82,174,164,142,44,34,210,84,81,33,35,169,182,46,135,20,109,32,
+48,205,32,232,20,193,91,151,8,64,89,152,154,145,198,41,65,157,73,20,10,0,95,25,8,37,169,9,226,17,
+109,73,21,244,64,50,40,253,185,126,43,254,236,95,160,153,105,32,84,220,105,223,251,244,13,224,29,52,12,156,
+29,210,195,161,119,109,3,176,126,219,248,19,226,142,25,126,73,249,242,159,244,196,237,137,244,80,74,185,193,213,
+211,63,229,60,121,171,224,172,219,236,24,180,5,76,45,234,211,151,180,168,53,188,161,176,174,19,139,58,141,95,
+120,246,202,163,111,235,43,64,11,48,84,96,61,183,113,192,8,107,235,42,166,39,118,208,97,107,201,6,77,110,
+242,62,184,22,168,52,132,247,3,163,220,126,115,28,215,56,12,93,216,132,253,52,37,77,19,202,179,244,186,147,
+118,68,187,187,175,146,103,107,223,245,234,210,81,123,62,239,99,197,143,117,115,228,208,39,223,88,180,47,111,35,
+113,210,222,104,39,200,63,158,124,163,71,228,3,228,171,204,219,251,250,92,41,183,184,88,145,117,139,179,64,251,
+151,206,49,148,226,8,100,7,34,85,4,67,190,58,19,222,218,152,0,145,81,71,254,135,206,69,38,23,231,82,
+118,180,49,32,101,210,110,252,71,214,5,201,30,88,100,144,205,100,13,206,27,19,83,224,46,80,71,234,206,46,
+183,24,91,81,23,223,97,240,89,207,131,189,37,22,4,241,227,45,230,154,78,35,7,151,90,1,183,186,197,95,
+123,221,242,212,69,80,125,56,194,32,49,190,29,179,218,124,44,74,106,190,173,212,153,253,54,202,138,118,224,146,
+201,180,43,212,226,204,90,214,47,75,199,246,152,163,45,192,184,40,201,35,139,96,7,53,37,36,176,69,37,109,
+77,12,37,100,94,9,217,27,176,224,21,95,166,100,99,99,113,150,14,250,129,60,57,55,122,111,41,72,79,110,
+104,86,58,148,132,10,130,154,160,64,7,122,41,148,46,121,82,113,222,120,144,13,67,22,157,35,168,186,136,180,
+6,197,133,2,82,194,204,143,160,13,4,133,235,191,134,8,52,44,217,140,96,243,108,24,206,240,211,47,187,170,
+127,152,163,210,204,123,44,125,59,63,196,187,214,22,181,110,222,236,183,139,221,135,117,133,95,203,122,93,94,98,
+189,74,79,240,108,239,79,110,50,218,184,72,43,33,90,88,88,157,109,110,56,93,255,36,72,60,176,177,24,170,
+20,165,69,213,178,36,110,166,212,34,45,91,212,48,82,15,169,108,91,178,200,126,72,218,42,236,76,103,246,210,
+138,147,143,43,78,62,67,113,174,87,71,78,85,143,213,221,84,143,168,83,36,243,154,97,75,35,162,85,160,93,
+196,57,78,88,25,228,252,187,108,181,73,105,209,56,29,26,39,152,156,177,88,29,32,227,244,165,100,149,213,46,
+69,21,181,243,177,137,250,17,156,200,174,61,225,135,169,23,158,204,157,131,126,103,65,159,163,19,126,107,95,203,
+87,57,3,202,83,83,197,237,240,201,206,174,193,191,182,192,158,32,115,142,3,25,75,129,10,253,37,216,132,219,
+60,32,132,215,156,42,166,103,126,134,250,211,219,233,101,59,4,81,59,169,2,219,205,244,162,153,138,169,205,220,
+183,202,215,206,22,164,124,45,42,223,226,182,7,70,206,122,86,69,250,169,245,84,21,251,141,42,62,86,197,116,
+182,38,230,107,208,68,136,39,168,226,99,85,108,167,170,120,69,69,164,154,123,167,124,15,151,163,213,221,165,253,
+249,238,223,169,157,122,157,182,120,200,20,242,174,187,118,143,174,234,236,72,213,121,237,128,174,82,151,237,225,252,
+165,39,159,148,127,15,233,181,39,126,225,223,83,253,246,63,109,215,193,228,170,13,132,255,202,61,38,97,32,195,
+235,169,188,48,158,150,94,166,164,87,31,166,28,228,144,33,96,230,41,115,190,255,158,253,180,139,5,24,94,47,
+119,39,88,105,87,210,106,23,173,108,125,168,115,254,34,192,73,82,245,105,214,121,40,109,78,155,244,93,183,180,
+31,194,6,73,84,185,238,207,251,37,60,140,32,188,246,132,240,202,214,142,60,194,249,173,192,189,32,47,113,221,
+228,236,224,88,199,238,237,166,207,252,248,196,143,125,221,170,184,226,81,180,5,23,14,3,169,68,119,69,144,67,
+119,69,48,108,99,134,210,112,223,225,30,23,53,103,144,10,56,137,165,57,138,174,177,225,18,139,100,22,147,187,
+15,79,167,167,22,35,21,146,94,210,131,183,199,168,228,238,35,115,211,6,133,233,158,97,241,86,20,91,140,20,
+91,88,197,250,65,181,73,54,201,61,174,53,244,146,136,148,92,248,1,107,104,212,48,63,76,72,120,194,31,82,
+39,145,52,54,165,178,55,133,108,102,52,105,39,105,45,61,75,189,137,109,20,207,176,141,103,142,236,139,15,215,
+242,161,136,123,168,150,233,245,72,181,221,162,106,215,15,78,204,95,204,182,189,145,237,110,70,215,192,244,161,236,
+25,6,239,121,86,77,201,229,197,221,115,180,237,229,186,173,91,106,66,84,26,233,194,152,127,110,119,193,165,184,
+44,247,77,127,112,102,48,152,153,253,191,184,163,164,182,96,87,149,192,71,12,219,116,105,183,220,80,162,59,100,
+141,19,244,172,62,220,8,93,149,123,39,104,152,76,215,3,53,214,78,160,132,26,107,161,194,148,169,146,22,59,
+84,121,204,117,112,141,49,215,52,230,215,115,32,2,146,122,234,121,72,98,128,15,192,82,128,5,23,57,243,230,
+0,32,124,190,167,138,88,155,187,227,209,219,2,38,64,20,217,22,43,160,128,128,105,172,197,1,39,176,19,156,
+0,183,233,122,100,111,122,217,149,175,79,174,172,77,125,134,165,2,11,217,146,30,217,146,158,219,146,72,73,130,
+74,184,122,112,245,145,30,116,75,249,99,165,75,169,6,165,154,72,139,170,81,200,142,128,148,145,13,246,90,20,
+143,50,118,60,164,205,208,17,183,25,62,163,253,27,45,15,3,147,22,146,230,164,65,217,192,188,157,184,83,250,
+60,119,226,19,194,141,77,7,131,93,4,39,83,184,119,168,63,47,117,150,122,15,160,9,70,183,70,35,119,35,
+162,117,180,55,228,98,49,149,35,27,170,70,164,130,72,137,127,14,14,236,199,27,78,171,55,224,93,189,45,56,
+236,161,253,144,138,21,216,136,58,131,44,141,225,124,39,230,238,240,95,149,193,197,46,77,40,17,2,51,196,234,
+29,182,101,45,40,249,246,221,203,153,103,179,75,175,227,165,184,61,240,120,246,76,21,236,224,153,42,0,90,103,
+221,51,99,78,42,36,21,240,64,96,201,193,130,139,148,121,105,40,225,89,44,115,55,242,44,181,236,89,59,156,
+66,222,162,72,27,41,244,85,193,148,212,208,75,181,108,74,44,32,198,195,194,212,145,64,64,18,169,177,105,73,
+161,34,72,80,200,250,148,213,45,215,103,117,123,94,43,116,235,186,147,177,49,142,164,252,27,37,142,100,210,92,
+210,116,122,170,221,254,204,123,164,113,203,211,169,98,83,176,243,233,162,73,78,97,110,175,50,159,114,35,94,112,
+70,237,227,103,0,213,5,122,253,253,222,76,92,214,76,239,208,245,67,202,160,157,222,35,100,117,202,207,91,238,
+247,133,30,34,30,131,60,176,95,197,56,155,50,14,39,153,69,175,202,20,75,139,77,54,203,145,56,106,115,152,
+209,155,182,190,106,179,142,114,222,105,167,57,60,235,57,155,223,103,116,65,87,111,254,109,195,175,25,233,221,71,
+169,87,2,47,220,79,224,225,106,189,19,182,214,52,94,174,53,143,151,107,45,226,48,137,77,173,187,72,161,214,
+109,180,91,197,150,35,128,43,76,252,151,113,196,224,186,249,50,190,188,49,228,214,144,99,75,222,130,60,65,251,
+214,51,28,207,51,177,178,0,9,217,87,124,8,174,241,22,233,66,215,142,199,9,21,182,235,108,28,198,100,86,
+49,64,38,125,219,213,237,221,166,46,45,190,141,163,157,181,183,127,140,145,75,100,0,237,193,0,151,232,59,198,
+249,195,154,74,223,197,20,0,32,182,74,195,211,237,135,23,213,213,233,142,58,163,43,123,71,231,125,142,111,31,
+93,80,109,34,228,162,32,192,241,3,131,62,198,251,71,214,145,171,12,164,178,48,166,5,36,42,201,25,235,80,
+0,78,75,145,18,143,182,242,14,35,224,100,198,131,14,234,34,174,179,153,225,58,91,78,98,12,189,242,98,201,
+169,40,104,74,162,58,243,186,25,180,178,178,225,209,31,215,4,163,212,0,15,22,84,186,136,140,167,179,241,113,
+163,50,223,15,11,64,234,4,103,23,177,108,61,122,20,32,252,216,228,196,158,71,255,128,157,141,85,90,79,236,
+57,177,231,204,158,11,59,208,72,30,28,80,99,239,77,179,105,238,113,172,22,122,13,10,178,87,106,74,136,21,
+70,62,233,178,143,216,231,19,121,111,199,235,89,182,22,203,214,139,150,173,95,193,178,93,119,226,119,52,53,161,
+171,228,245,220,213,237,102,123,234,234,22,93,229,71,129,166,132,186,10,199,157,140,161,15,252,27,190,181,173,241,
+103,28,224,177,217,164,195,227,1,23,80,29,184,241,183,66,184,151,76,215,126,87,241,26,90,237,198,156,50,217,
+17,182,21,160,180,26,188,109,244,32,136,113,81,69,142,35,11,78,129,141,21,145,34,172,213,157,250,120,196,180,
+140,140,227,17,51,188,162,30,48,148,74,249,1,3,166,200,206,130,46,59,252,88,170,140,176,244,140,96,147,156,
+135,212,53,242,18,244,48,63,9,236,134,205,233,145,34,123,234,206,158,175,30,214,180,85,22,183,131,196,4,171,
+171,89,13,128,206,245,13,117,41,115,0,184,83,42,222,167,161,136,8,121,241,144,146,43,164,97,119,175,76,3,
+83,97,168,110,125,233,228,109,240,24,173,10,187,185,61,184,238,162,92,206,13,141,131,45,202,197,220,27,121,102,
+149,137,198,97,18,208,116,127,119,231,223,247,182,244,247,61,210,194,0,102,211,159,62,32,37,234,136,212,166,45,
+230,143,149,42,186,241,49,62,15,78,24,190,62,66,145,179,198,110,152,231,206,192,20,162,107,118,146,107,104,194,
+105,163,239,90,64,208,78,114,13,139,127,59,195,213,97,104,28,216,7,144,112,138,17,117,93,164,238,129,4,235,
+4,214,146,181,194,24,192,50,247,12,205,128,149,177,68,201,17,174,91,18,130,149,194,147,74,167,25,126,247,180,
+60,36,5,143,59,204,52,238,178,73,228,16,2,96,88,69,8,190,219,186,99,68,233,232,205,80,31,60,224,216,
+9,121,28,59,61,217,181,89,124,253,4,130,108,148,97,165,32,132,95,147,130,188,5,41,18,145,132,167,166,114,
+176,37,141,237,198,194,249,85,70,203,210,57,243,92,124,58,233,99,150,174,177,35,235,140,249,233,152,153,161,116,
+107,252,146,59,22,33,47,232,177,34,100,117,177,44,0,121,99,246,91,219,14,27,39,189,150,166,217,97,95,79,
+6,178,206,135,228,131,169,136,79,134,151,182,156,10,96,81,183,252,102,51,158,241,167,149,136,203,133,246,225,245,
+112,243,22,170,156,15,204,170,72,206,127,174,196,215,30,248,91,194,192,118,188,86,224,21,254,128,127,109,226,151,
+194,191,94,197,65,31,3,255,202,211,208,131,9,196,85,153,73,139,23,40,89,244,135,147,20,101,149,182,25,118,
+73,201,123,17,254,39,237,200,251,218,198,149,255,191,79,145,178,45,63,203,150,29,219,73,56,76,76,94,203,150,
+125,189,219,109,121,101,127,52,143,117,130,154,168,4,153,181,148,158,225,187,191,25,201,138,101,194,190,115,143,72,
+158,25,205,104,78,29,6,98,122,139,82,225,125,43,8,155,22,192,217,150,71,145,255,128,58,10,146,205,163,236,
+148,31,59,175,38,159,216,84,69,151,236,155,244,56,33,172,185,164,149,4,86,29,113,38,199,57,135,15,98,171,
+178,184,233,250,247,254,210,241,59,71,243,162,82,209,39,217,249,220,139,118,163,4,65,246,175,236,225,133,254,20,
+209,159,36,222,234,35,202,155,146,78,26,167,105,51,236,168,20,170,226,16,47,224,9,164,248,149,45,24,68,208,
+69,103,41,112,3,169,230,172,243,226,201,187,206,115,62,101,66,50,160,232,154,105,159,151,185,53,136,183,62,154,
+96,141,4,109,190,112,113,81,126,129,202,143,60,62,114,1,107,208,104,77,204,215,212,248,51,209,153,161,141,42,
+246,199,146,73,245,208,254,198,236,113,85,92,177,27,247,36,247,181,188,189,85,96,96,153,42,63,124,88,129,251,
+35,72,112,85,162,252,72,46,96,174,209,20,14,182,94,69,156,223,124,47,243,179,177,53,223,122,54,81,20,85,
+228,71,153,11,160,165,18,24,2,105,76,207,75,51,222,76,142,234,69,68,243,224,81,113,125,189,248,166,47,40,
+110,136,27,20,19,55,40,238,18,35,26,43,141,188,214,134,1,215,57,119,195,192,169,217,164,90,97,58,38,5,
+161,234,230,166,94,96,69,206,243,67,94,159,70,43,220,3,46,216,71,168,42,26,4,65,14,128,74,191,7,202,
+182,234,191,225,65,75,149,215,246,107,143,84,206,32,150,121,42,96,164,155,210,243,162,166,166,162,166,247,132,21,
+82,179,38,64,142,8,43,97,84,143,205,84,227,179,35,5,177,81,79,250,107,225,6,12,154,137,231,241,134,161,
+154,224,8,130,155,150,255,95,186,145,147,219,77,94,29,113,188,21,108,206,159,188,195,65,176,252,155,24,225,82,
+183,219,219,173,71,76,56,195,247,94,92,167,168,202,77,66,58,81,165,202,183,144,39,98,102,2,131,175,19,81,
+69,114,57,145,170,242,98,186,75,208,28,103,165,30,10,123,179,53,42,220,209,24,45,109,236,204,238,187,171,82,
+189,111,221,222,254,119,162,93,41,117,225,0,166,102,226,247,49,48,60,199,40,98,121,53,97,21,30,137,59,28,
+8,10,49,69,204,75,13,197,247,105,242,152,11,174,152,23,184,247,13,215,58,6,215,83,187,15,50,71,60,83,
+205,196,31,183,240,119,250,0,3,171,158,212,55,19,76,16,72,14,165,212,42,129,149,120,132,85,249,61,87,115,
+111,235,1,68,213,117,81,73,118,188,40,11,5,98,187,176,180,102,188,171,232,183,242,255,226,225,171,44,224,141,
+130,111,108,41,193,157,225,246,182,101,169,13,12,124,45,221,22,169,53,180,153,200,96,6,206,93,155,77,17,19,
+206,230,71,133,128,35,6,29,129,182,204,121,180,96,98,166,230,64,130,5,95,230,101,152,28,200,67,136,123,25,
+134,68,25,135,50,138,149,157,74,114,192,22,146,117,52,33,82,12,203,3,25,4,127,66,5,236,49,122,52,219,
+42,111,47,31,180,204,43,43,248,79,56,85,192,107,76,241,211,209,71,242,166,132,217,247,251,32,231,30,95,173,
+238,169,213,202,42,3,129,170,234,174,205,155,68,175,103,44,143,169,88,235,124,192,134,226,32,8,24,90,66,194,
+226,197,198,48,47,133,141,212,27,117,201,212,19,136,150,175,192,174,108,1,240,200,197,45,198,244,26,57,54,81,
+155,89,151,28,179,200,154,125,237,176,171,226,218,43,33,168,173,161,126,220,202,236,105,197,10,136,123,115,246,103,
+183,45,40,114,102,213,48,235,71,172,53,60,144,90,39,73,64,15,180,96,142,194,77,183,41,8,235,211,74,51,
+199,207,101,147,233,103,91,231,231,58,183,207,207,97,155,176,206,114,232,59,187,146,173,177,81,252,213,71,147,239,
+97,226,48,43,154,184,67,247,32,115,171,120,93,191,36,24,154,163,189,25,52,7,223,61,9,169,254,221,43,201,
+232,136,121,24,166,130,100,72,128,211,47,157,0,0,236,173,37,246,23,79,17,200,228,51,5,94,203,133,53,9,
+74,253,238,90,251,128,225,98,252,227,166,22,15,114,163,43,86,205,88,181,90,125,46,180,229,208,138,21,214,251,
+161,4,3,86,122,230,42,23,103,213,152,2,43,69,8,140,84,92,44,89,205,162,112,61,2,248,53,147,5,4,
+217,52,47,214,222,25,78,129,223,130,148,94,113,182,24,83,51,253,187,60,192,220,146,101,53,253,97,102,153,125,
+41,110,28,51,124,169,13,252,167,230,21,198,188,210,154,87,104,243,74,50,2,41,130,74,146,109,148,240,121,33,
+95,125,17,175,171,242,154,193,177,210,228,161,162,28,247,118,214,17,146,144,186,94,94,22,120,191,241,2,62,163,
+173,166,102,253,38,140,6,134,134,229,124,29,33,47,10,128,219,240,99,58,90,70,54,11,51,214,232,245,180,46,
+235,104,122,160,186,44,26,255,161,101,77,250,130,24,84,221,132,59,212,70,113,200,14,8,135,252,93,175,102,140,
+138,144,145,49,101,185,8,18,103,196,166,209,103,173,221,158,222,139,62,84,94,140,47,86,78,174,193,18,71,144,
+243,30,9,184,217,178,121,137,53,192,68,229,188,41,244,247,220,101,133,30,183,112,110,177,166,39,194,172,17,246,
+196,47,249,119,166,139,21,118,218,165,170,54,98,7,121,16,244,178,66,23,121,140,220,81,105,26,23,60,44,90,
+250,216,251,141,171,114,41,217,242,26,23,89,11,51,151,155,109,72,41,240,176,114,197,196,210,174,214,167,249,139,
+66,205,163,215,79,232,73,158,250,167,244,109,145,159,4,167,180,226,185,89,160,163,215,175,222,62,121,247,228,239,
+143,207,159,188,60,126,242,242,201,187,223,232,81,145,159,118,147,189,152,62,133,54,165,83,6,77,159,190,17,249,
+169,159,118,123,244,74,25,150,139,114,150,196,244,69,253,36,249,76,52,90,252,2,94,177,97,84,19,232,11,72,
+15,171,101,254,197,100,6,239,38,172,135,169,207,235,152,103,134,242,186,252,226,33,103,236,127,92,148,96,202,43,
+133,249,65,176,242,119,237,198,215,19,195,60,25,37,25,52,233,40,197,102,48,26,100,73,76,124,39,28,95,23,
+238,60,206,48,160,204,108,255,168,144,165,142,73,161,189,37,242,228,64,12,217,129,8,2,194,31,8,176,38,94,
+73,65,126,45,229,220,19,132,214,61,222,21,164,149,7,30,91,197,144,154,53,154,33,161,44,129,57,214,64,188,
+161,10,75,2,10,93,123,128,112,166,197,26,39,223,227,242,101,241,210,107,109,39,220,93,19,119,171,134,45,158,
+54,64,180,50,197,68,122,60,84,100,232,40,254,115,209,206,100,215,5,205,252,67,53,204,33,255,88,160,14,115,
+238,136,41,173,24,180,143,89,164,141,141,98,42,155,197,87,12,165,54,87,9,153,43,198,184,234,26,85,74,93,
+114,240,141,163,22,139,29,243,8,22,161,208,41,190,106,56,118,60,253,8,112,71,201,115,229,102,128,239,233,88,
+116,240,215,162,141,7,108,247,212,193,63,211,120,76,184,251,78,85,69,77,84,158,80,102,151,89,215,34,190,34,
+93,5,105,204,15,136,242,115,136,61,22,4,214,72,142,81,47,203,182,81,85,244,53,228,209,87,42,160,247,13,
+122,223,168,116,194,139,249,44,16,190,48,65,86,26,68,161,10,145,122,194,41,101,229,48,140,6,254,41,196,90,
+25,228,39,132,254,208,127,137,35,43,233,5,55,91,233,76,186,127,11,132,183,150,152,70,216,58,113,236,156,82,
+18,56,48,51,187,212,53,243,171,194,101,133,1,20,188,45,200,131,147,240,180,161,249,232,184,194,227,15,78,130,
+19,32,112,130,140,53,187,4,187,41,208,67,104,137,173,34,180,194,150,17,90,96,91,134,146,208,5,246,42,236,
+77,177,135,249,65,231,166,87,173,141,34,33,177,224,90,28,27,88,222,5,188,243,48,189,226,16,206,46,211,225,
+188,153,130,80,27,25,97,35,139,174,131,143,81,238,106,254,220,45,177,154,65,216,75,119,119,246,40,126,238,186,
+38,82,86,191,60,97,225,78,19,116,135,77,96,163,236,16,102,200,135,77,80,35,44,16,117,1,126,207,236,65,
+58,94,173,176,73,232,169,104,206,201,97,227,186,148,38,177,15,142,200,19,66,124,227,90,16,160,83,219,63,233,
+50,66,232,83,103,160,51,44,132,113,252,206,33,65,66,47,89,254,195,252,69,229,12,231,65,241,230,229,137,120,
+179,44,46,244,179,111,32,175,150,202,130,66,142,147,72,73,77,233,96,160,250,229,209,128,12,147,17,132,44,140,
+204,48,116,189,208,14,8,19,59,230,104,57,225,83,195,222,17,176,134,26,29,17,21,36,86,138,69,111,138,65,
+65,40,7,71,165,102,84,74,26,53,42,101,5,185,186,88,120,232,53,194,124,222,204,176,161,217,148,103,85,115,
+69,194,88,71,40,23,142,80,87,172,197,184,66,93,45,93,146,77,169,155,154,182,181,125,11,110,212,74,105,79,
+79,75,233,113,255,41,248,216,138,183,120,27,8,136,182,99,29,180,86,109,205,226,212,231,142,231,30,127,189,46,
+51,27,175,163,56,219,8,78,136,77,43,206,165,197,149,56,220,8,73,87,113,75,253,158,153,163,62,31,70,3,
+84,253,182,4,63,69,25,218,14,109,134,13,178,177,200,17,175,76,156,29,194,12,192,105,94,83,17,147,144,55,
+154,225,116,45,173,75,98,253,100,249,53,100,142,127,26,123,181,25,103,183,225,214,111,36,104,236,137,175,76,249,
+212,85,252,20,55,217,81,188,59,160,81,175,177,229,38,221,83,135,206,178,107,40,157,18,118,219,162,40,192,79,
+105,148,36,41,140,237,15,112,162,1,192,145,33,26,208,193,220,212,124,31,21,211,75,135,35,198,157,231,37,209,
+110,156,12,246,2,52,80,88,63,144,27,59,227,246,16,99,200,141,97,129,29,22,36,86,148,51,212,172,201,53,
+137,221,214,185,105,225,153,137,120,202,7,170,65,58,32,102,46,138,16,55,79,238,32,9,20,4,73,163,93,9,
+21,93,135,126,18,94,178,200,42,160,161,232,78,66,91,32,215,16,195,164,155,70,187,131,209,110,52,216,73,49,
+79,209,204,169,11,195,164,64,209,26,134,162,161,65,154,26,226,82,165,81,234,144,237,247,128,176,133,221,105,161,
+247,250,64,224,88,173,209,66,59,26,20,113,181,67,215,18,63,26,100,27,10,154,164,241,117,12,220,28,212,87,
+250,127,189,92,86,151,11,214,213,175,71,58,159,227,40,137,246,221,123,253,25,87,243,229,4,10,196,85,215,165,
+252,169,98,197,197,21,115,174,249,227,206,211,229,229,101,209,121,6,84,108,81,252,55,215,251,51,149,255,136,179,
+152,38,89,66,211,44,165,189,172,71,251,89,159,14,178,1,221,201,118,232,110,182,75,247,178,61,186,159,237,211,
+135,89,18,211,71,89,146,208,163,44,73,233,207,89,210,163,143,179,164,79,143,179,100,64,11,196,78,16,59,69,
+236,5,98,25,98,63,2,246,134,222,231,249,86,156,164,189,254,96,103,119,111,255,225,163,163,159,31,31,111,209,
+119,5,46,204,247,249,25,223,78,6,99,250,216,62,122,124,59,237,199,228,240,176,63,14,214,216,151,12,177,13,
+10,119,254,136,113,110,52,127,117,183,21,47,193,238,17,222,126,234,206,204,118,38,182,83,56,219,140,71,122,224,
+231,2,76,213,220,230,173,239,247,237,55,146,252,180,133,231,17,232,245,87,43,108,6,35,88,216,171,44,29,12,
+182,103,234,12,127,46,109,236,39,187,116,214,64,82,3,153,52,144,158,129,20,153,97,160,97,125,13,67,154,155,
+76,243,223,53,252,247,9,200,211,34,44,251,225,176,191,178,140,65,142,229,136,96,203,9,132,233,238,192,1,239,
+0,216,72,220,55,18,119,29,228,222,120,172,69,227,170,210,88,228,137,99,17,109,214,209,187,34,123,92,172,77,
+178,189,13,230,8,148,54,177,110,102,166,153,144,0,109,59,4,142,35,165,173,140,63,173,220,240,125,215,202,109,
+200,135,85,108,223,28,112,103,103,101,247,113,235,77,30,7,56,85,238,79,203,57,140,96,172,135,140,125,72,249,
+1,161,49,5,233,238,38,242,78,210,187,40,175,196,38,101,87,51,197,235,101,32,79,28,226,63,238,32,246,129,
+12,217,98,83,235,117,92,228,221,127,84,179,73,49,250,224,125,144,190,119,22,6,209,135,139,113,64,188,7,100,
+116,246,65,210,113,160,97,236,95,3,189,81,134,240,238,6,130,140,128,235,7,114,191,219,216,230,123,235,204,125,
+92,68,236,43,155,218,195,54,203,65,103,231,222,247,94,125,87,4,65,129,47,39,236,184,42,15,16,116,160,201,
+33,236,33,78,70,96,243,138,100,149,182,157,189,125,19,72,151,140,169,196,182,55,166,37,182,144,174,194,142,75,
+245,56,65,50,65,168,180,192,190,6,74,146,73,66,75,11,220,209,192,146,100,37,161,16,244,2,34,92,66,56,
+151,16,187,204,253,113,162,191,105,245,154,72,92,7,220,239,104,102,239,254,15,8,202,27,218,193,118,86,183,19,
+221,94,9,147,247,228,247,12,73,239,166,4,44,177,7,7,116,157,55,151,139,98,180,154,127,153,172,230,242,51,
+209,78,116,93,48,202,46,216,236,14,167,61,216,132,212,62,252,79,92,248,98,227,61,168,242,157,211,84,18,50,
+180,166,87,210,10,62,2,222,237,197,228,65,146,66,234,176,80,248,155,233,83,133,61,186,31,86,16,191,52,76,
+236,33,239,76,122,49,112,241,246,240,163,79,198,141,133,95,22,183,165,227,101,10,124,128,164,29,144,180,163,5,
+49,95,221,33,170,164,253,176,68,65,241,90,142,240,32,215,132,215,195,143,196,149,243,105,67,142,214,59,161,209,
+192,4,171,212,55,5,42,96,135,9,248,89,230,73,23,31,8,85,126,46,41,131,15,82,191,251,232,233,119,31,
+248,6,221,207,147,80,133,140,98,63,200,85,243,42,189,121,137,11,97,224,222,176,86,93,157,17,208,155,233,158,
+132,222,68,247,202,230,68,201,48,101,240,56,109,21,181,144,2,29,80,145,110,170,39,172,127,120,217,202,44,33,
+161,42,152,247,60,47,195,10,239,179,15,97,215,48,239,122,105,8,207,36,131,30,142,164,139,28,15,215,108,228,
+137,80,146,238,60,240,196,80,142,118,178,152,100,8,23,35,79,134,12,225,105,230,129,119,177,215,135,49,11,127,
+39,14,192,78,244,108,177,138,233,116,5,31,133,99,218,115,97,79,206,54,85,218,175,71,241,202,159,123,10,150,
+54,170,243,23,19,149,100,220,51,67,136,126,179,242,138,57,229,238,171,104,159,243,81,194,139,146,106,152,251,186,
+172,216,36,251,84,108,144,253,118,7,217,203,77,178,135,101,235,250,163,7,42,195,255,4,59,13,209,73,171,220,
+189,191,179,220,233,82,167,236,85,20,86,40,44,118,122,125,181,133,39,64,40,201,94,217,222,63,217,182,10,165,
+136,98,24,248,47,139,67,112,198,130,187,115,248,201,8,218,115,119,123,255,206,166,197,97,44,91,141,92,111,155,
+153,244,77,125,150,89,104,5,187,24,31,169,4,150,243,183,65,221,240,138,225,207,2,183,69,210,50,5,146,5,
+54,203,235,140,133,47,23,78,233,231,64,163,109,3,201,207,129,242,58,227,26,176,231,60,251,61,50,20,139,118,
+145,151,169,51,144,223,87,77,211,199,205,223,204,116,205,159,228,85,199,69,102,163,73,166,221,226,108,79,255,194,
+173,190,110,125,4,25,130,69,3,207,4,75,223,142,201,161,143,157,175,255,253,172,126,52,195,230,98,241,89,48,
+58,231,117,103,94,240,15,23,224,210,87,49,236,147,127,141,42,201,170,206,115,105,57,26,51,209,160,248,197,189,
+156,246,207,172,169,199,40,168,78,241,237,76,87,241,250,84,47,64,82,138,98,248,216,53,169,168,59,72,66,193,
+39,87,144,184,34,83,135,220,43,74,238,53,215,42,65,238,20,212,223,228,156,109,133,163,184,85,84,138,144,27,
+10,206,220,225,250,39,48,123,133,77,202,128,41,44,108,231,6,228,154,168,12,185,82,208,159,90,171,146,99,223,
+190,34,155,131,92,114,85,5,18,83,60,113,171,11,46,118,144,115,90,71,113,166,240,207,217,32,7,84,200,13,
+78,21,47,89,200,161,130,182,115,143,35,118,83,229,113,80,68,149,39,138,78,22,204,135,233,98,140,217,120,194,
+41,222,152,186,178,5,199,77,32,248,47,243,154,11,29,72,104,159,114,237,125,123,38,135,243,214,208,224,81,198,
+150,188,146,60,142,243,245,169,110,52,27,139,61,168,2,90,116,81,141,30,157,76,114,41,221,124,75,195,210,127,
+57,197,243,243,69,72,138,158,91,144,95,78,4,132,39,247,15,52,109,48,220,130,224,26,212,191,167,173,70,208,
+9,62,246,59,89,107,147,229,0,216,207,136,39,171,99,29,48,89,127,89,243,217,141,209,222,240,54,242,199,195,
+56,176,142,251,192,80,86,231,202,255,143,253,93,92,158,221,56,42,125,44,49,253,211,121,64,74,182,164,146,128,
+78,211,254,114,30,71,22,17,188,115,216,101,160,247,139,172,182,169,139,100,160,3,77,203,246,52,175,27,53,194,
+140,225,142,36,49,46,155,174,136,88,114,251,81,222,214,38,107,4,12,242,91,44,113,146,32,77,221,217,200,74,
+206,253,254,65,179,119,146,79,152,250,195,60,14,136,17,138,186,18,226,66,64,57,247,127,100,169,243,232,8,43,
+93,5,187,187,247,195,39,134,101,156,107,140,16,127,208,5,169,116,210,100,120,251,66,94,104,140,246,175,71,30,
+238,233,161,199,58,246,109,35,235,14,180,123,177,144,196,53,70,35,223,245,143,81,151,91,219,248,50,129,185,165,
+65,229,79,46,24,35,56,60,199,155,187,174,42,67,0,220,114,94,173,99,179,104,15,119,116,93,211,146,224,87,
+26,203,37,31,156,196,250,77,210,169,93,197,206,11,210,93,151,169,70,19,184,219,94,195,207,152,26,34,23,232,
+174,7,215,33,35,174,110,190,229,159,142,199,141,42,88,212,93,198,243,195,69,66,123,21,141,251,131,70,110,58,
+105,138,17,250,10,143,188,203,135,82,196,206,200,138,212,111,253,212,139,141,124,41,15,152,253,237,199,213,179,41,
+81,50,96,198,237,188,252,241,19,210,43,75,231,117,206,233,237,220,171,143,141,70,217,209,102,246,183,163,156,164,
+52,16,247,227,188,172,81,28,154,204,185,83,107,114,43,122,61,29,35,19,92,8,172,187,118,6,13,32,43,103,
+76,238,190,59,227,20,57,165,50,9,188,154,118,63,14,241,242,254,188,150,139,18,203,170,78,211,121,212,199,134,
+123,26,228,148,2,219,96,131,18,59,108,178,150,35,71,22,253,227,237,69,102,231,213,171,65,146,137,141,195,220,
+61,61,190,120,63,225,68,155,216,36,122,194,127,206,247,186,194,36,43,212,121,208,189,182,33,169,67,62,192,3,
+225,121,74,99,118,49,73,17,254,37,106,19,179,139,13,64,174,18,77,64,144,58,59,106,181,3,102,81,36,95,
+232,78,92,130,82,93,184,146,6,164,47,235,76,196,217,41,186,30,91,51,247,77,40,128,212,142,130,201,180,36,
+56,219,177,52,190,36,193,171,107,92,27,98,18,156,13,217,182,206,117,157,64,196,190,130,243,242,211,94,77,102,
+66,205,17,132,238,17,79,52,80,161,63,68,65,102,237,235,139,80,34,92,149,32,54,0,226,34,201,126,45,185,
+213,53,130,63,201,38,157,145,7,55,255,213,125,216,52,129,137,192,201,107,3,163,147,139,207,147,181,92,1,30,
+79,211,241,3,196,168,90,195,30,120,77,176,10,190,106,11,96,173,183,214,55,46,70,25,61,78,155,157,78,72,
+212,73,88,41,177,218,113,17,2,128,22,153,250,164,45,172,179,216,88,207,131,92,240,90,40,93,209,181,6,220,
+102,9,91,58,232,109,12,89,101,210,188,92,62,205,235,125,28,11,48,99,8,52,111,50,225,17,103,160,71,250,
+123,124,42,38,142,196,202,169,135,241,53,227,61,5,25,225,100,69,30,185,128,100,68,244,200,136,127,246,144,194,
+187,88,34,229,175,183,17,89,99,86,184,101,33,234,76,168,64,76,16,4,193,142,31,227,83,141,197,24,29,145,
+82,217,64,46,249,206,41,22,25,40,69,60,10,191,10,193,190,53,93,5,142,142,116,161,243,243,163,230,148,216,
+130,122,245,246,120,74,73,8,38,223,129,136,211,73,206,200,217,42,1,101,27,6,19,60,192,254,4,193,152,201,
+48,3,141,103,20,144,218,40,170,31,214,51,148,124,69,143,173,143,208,111,37,155,166,170,196,123,57,195,108,144,
+79,243,197,79,163,124,186,228,82,117,9,204,229,163,222,171,69,211,201,1,204,196,252,33,127,220,156,175,109,129,
+12,158,10,129,156,105,75,153,49,240,37,207,72,53,213,13,162,62,149,70,116,222,182,2,231,251,184,223,171,191,
+109,140,32,250,23,3,65,38,99,203,146,5,238,31,227,132,132,141,52,224,255,43,41,34,101,245,93,67,86,107,
+127,173,42,100,39,5,187,22,213,138,230,97,204,69,68,98,166,43,131,166,54,1,175,21,87,55,174,148,171,108,
+145,139,130,209,117,1,32,126,204,62,65,247,249,188,64,45,118,62,177,3,28,15,180,140,18,164,169,106,36,163,
+54,135,218,140,169,235,167,36,70,87,74,90,111,94,1,36,203,209,67,165,213,162,250,100,52,31,198,7,161,44,
+26,78,253,63,198,206,67,185,109,24,6,160,191,210,93,209,162,121,86,211,233,59,166,123,239,189,7,156,242,20,
+249,28,42,165,216,93,255,123,1,238,236,180,73,200,128,27,154,0,30,227,120,193,79,38,148,247,167,17,184,75,
+188,0,45,238,67,21,95,219,59,164,165,185,221,66,3,157,208,219,137,173,119,33,146,155,182,138,198,144,56,198,
+193,35,171,230,194,225,127,61,47,7,210,98,84,60,24,136,42,86,24,92,188,92,17,102,7,18,132,81,155,116,
+89,161,217,250,78,191,239,241,157,182,151,14,4,184,171,109,117,194,145,75,205,121,134,44,29,124,148,239,251,213,
+213,230,252,41,178,39,48,119,209,103,232,231,199,140,34,209,252,230,42,175,241,141,123,191,158,19,196,60,87,146,
+86,204,231,74,56,58,222,255,101,103,249,126,194,221,255,143,44,189,121,207,145,56,18,182,127,208,255,140,244,76,
+66,154,241,227,218,208,76,176,222,76,176,222,76,176,222,76,136,42,32,7,229,101,180,82,188,91,175,176,204,84,
+201,67,6,178,32,152,16,26,217,175,108,235,78,114,224,150,10,106,250,49,82,220,186,136,20,154,94,83,10,65,
+57,203,69,123,43,67,71,43,67,71,43,131,76,151,98,236,231,253,150,168,121,151,248,87,24,8,91,169,44,113,
+101,188,4,45,236,144,29,144,184,226,9,111,241,123,134,223,224,150,21,245,177,157,241,77,72,212,170,92,33,111,
+45,181,237,188,182,58,175,45,114,158,134,78,120,170,236,234,10,144,228,42,68,205,49,198,200,19,235,102,189,109,
+240,102,201,120,168,137,9,219,2,149,220,131,221,73,40,178,252,16,157,254,67,197,83,103,173,134,253,10,208,109,
+223,164,64,158,184,146,225,133,142,197,35,159,16,157,128,69,217,192,206,40,234,222,131,194,100,91,90,2,233,166,
+74,150,228,108,165,37,186,184,45,82,33,111,124,114,143,18,198,221,38,172,207,166,197,227,21,242,63,0,55,191,
+200,163,71,245,178,197,206,221,111,5,248,159,171,184,98,242,161,197,99,132,186,74,189,101,74,50,168,117,67,39,
+101,13,190,29,173,53,213,247,115,94,98,206,35,208,187,142,120,249,14,20,35,76,83,118,185,174,126,237,215,236,
+238,94,205,134,197,126,205,110,239,209,108,163,251,85,109,241,88,81,17,121,23,108,20,17,66,137,53,137,131,165,
+212,29,37,147,128,71,58,48,6,35,107,83,197,23,136,131,193,184,161,125,132,2,198,189,0,250,52,187,106,49,
+90,243,112,223,98,90,45,234,53,220,171,215,212,40,99,172,110,200,201,100,100,51,70,224,87,24,231,53,93,31,
+97,174,54,163,30,127,138,115,40,110,147,184,117,226,214,139,103,73,60,115,226,153,23,131,4,20,65,93,53,99,
+96,40,6,238,166,46,135,228,221,197,19,181,215,42,171,136,62,179,29,58,175,26,210,204,18,22,155,235,168,170,
+84,33,105,42,92,35,254,36,195,110,20,24,101,178,150,148,76,53,19,231,35,192,57,239,124,139,214,224,61,31,
+17,74,85,197,38,54,55,225,74,162,187,29,245,59,18,43,181,21,45,198,214,46,97,58,27,137,166,41,160,125,
+35,177,76,162,92,42,223,105,191,137,47,141,135,154,70,29,166,161,85,11,118,215,57,20,195,144,118,199,152,114,
+26,206,231,91,204,207,66,126,230,187,114,126,12,165,179,178,232,150,156,151,116,134,71,101,145,231,99,191,122,227,
+88,113,0,44,6,171,246,170,218,228,46,213,193,117,83,183,166,183,91,43,62,133,162,98,172,85,16,197,217,75,
+151,206,144,46,58,209,159,244,142,190,41,111,106,215,65,255,128,225,182,129,175,157,210,120,235,223,165,240,9,88,
+171,76,193,51,170,33,143,129,125,250,120,187,27,184,8,90,117,123,213,17,105,245,232,49,21,65,191,162,97,34,
+223,60,226,124,191,253,103,239,207,219,219,54,146,197,97,244,255,251,41,44,254,50,103,0,179,41,75,158,229,156,
+3,186,205,199,137,227,196,25,103,25,219,217,70,175,30,13,4,54,77,196,16,192,1,64,75,10,7,223,253,86,
+85,87,119,23,64,80,114,206,204,185,235,251,36,22,209,251,86,93,93,93,93,203,184,240,120,91,142,69,11,134,
+61,139,30,11,62,35,138,220,6,65,181,102,83,228,109,4,194,190,65,202,217,74,243,25,41,205,55,157,250,23,
+24,36,82,202,243,57,74,229,86,231,64,63,224,207,88,31,198,4,161,95,228,3,246,170,59,51,194,169,128,82,
+226,220,105,200,151,184,208,100,2,99,117,231,211,63,82,121,62,121,156,237,61,30,234,15,85,190,4,119,73,20,
+123,9,220,165,119,36,206,71,150,238,244,132,94,99,152,186,129,185,158,112,54,82,100,191,51,75,102,19,255,15,
+56,117,224,24,214,28,64,69,113,142,128,203,71,102,190,203,111,76,241,26,187,162,141,126,106,172,30,220,49,16,
+116,45,250,143,67,239,164,207,7,249,34,62,244,76,97,174,76,41,42,52,31,40,120,102,229,124,175,42,48,153,
+160,236,119,181,109,39,222,142,193,164,173,182,217,218,106,85,113,128,242,158,219,90,208,154,138,222,173,210,171,188,
+0,218,253,247,95,26,32,254,219,60,75,225,53,122,107,126,175,30,132,24,12,60,171,243,180,128,143,38,45,155,
+89,99,234,28,136,105,148,98,198,23,116,178,10,147,76,216,6,144,66,249,177,47,201,234,95,114,122,252,88,93,
+219,79,92,127,238,63,169,96,234,157,12,125,58,88,144,200,234,121,193,46,41,135,139,21,203,98,126,129,6,69,
+124,188,204,62,146,49,243,89,88,197,227,217,77,222,104,52,9,203,81,176,179,83,130,83,189,187,170,150,56,74,
+60,28,26,152,81,74,107,0,194,147,163,19,30,202,85,10,145,240,239,89,179,129,120,187,216,71,12,114,85,249,
+37,13,27,231,193,197,124,134,11,37,98,144,154,7,120,247,101,224,146,249,46,47,195,194,67,195,27,128,113,184,
+62,251,44,116,236,120,216,246,49,161,76,179,174,174,95,229,101,40,177,172,211,235,103,228,147,251,115,6,172,111,
+203,183,213,38,164,155,38,171,243,75,196,169,72,1,69,114,107,190,176,199,169,194,56,36,171,34,33,93,106,56,
+41,238,124,13,195,162,165,45,136,243,80,231,203,189,244,127,180,54,29,214,186,197,68,251,106,229,81,76,104,65,
+213,62,80,226,171,214,228,98,50,53,115,198,55,86,48,159,53,27,114,211,68,149,218,193,149,40,217,89,99,3,
+21,138,30,95,215,121,155,94,22,134,150,14,34,146,157,1,189,52,83,115,156,194,161,185,134,11,58,70,161,6,
+149,233,250,172,241,215,155,95,163,34,94,244,175,6,48,231,104,227,44,249,60,42,84,22,119,10,167,175,136,119,
+92,94,23,93,135,106,187,72,132,126,169,241,236,249,71,26,237,46,112,174,54,182,55,112,248,28,229,199,180,99,
+89,119,140,188,124,92,16,100,186,28,168,151,55,177,40,96,162,172,54,243,238,98,149,22,197,37,177,204,5,200,
+78,58,37,66,73,175,169,163,211,80,45,134,186,78,28,16,127,19,151,3,84,182,250,134,117,23,98,251,105,113,
+70,188,64,192,77,48,9,247,255,130,127,167,147,7,19,178,250,6,9,118,235,47,220,135,79,162,218,32,231,230,
+230,193,100,234,234,19,102,93,241,68,240,203,111,5,162,91,49,243,21,156,48,54,70,131,90,149,73,155,109,109,
+222,154,155,54,106,226,99,178,107,165,140,21,176,111,226,24,174,191,37,93,42,170,88,149,194,169,151,80,89,42,
+117,137,87,58,214,171,42,9,129,243,15,198,171,10,2,239,210,250,50,125,103,0,129,20,176,222,195,8,160,11,
+64,147,183,36,148,10,171,131,87,9,95,209,104,5,168,92,96,179,235,22,175,165,77,10,138,58,240,193,81,115,
+86,78,10,148,184,212,253,242,174,148,237,225,12,217,138,39,233,188,64,85,132,85,180,210,6,213,142,86,71,172,
+187,249,69,180,138,143,52,218,24,169,53,206,43,243,35,86,65,107,15,115,196,88,83,166,79,80,184,218,53,149,
+61,129,127,80,233,82,175,206,178,115,181,116,53,30,125,17,45,81,218,167,87,223,50,142,231,57,226,167,182,170,
+77,20,236,110,84,92,27,220,6,160,169,237,83,55,144,120,23,250,190,165,190,47,13,140,205,60,104,206,42,232,
+255,249,188,34,34,36,67,67,26,91,79,53,212,226,81,182,29,62,199,231,206,127,245,240,28,69,186,229,8,217,
+1,225,129,252,209,99,124,182,79,252,99,168,16,239,143,218,89,19,63,132,167,235,114,218,132,230,242,198,146,76,
+173,70,26,16,79,107,84,83,71,152,155,60,94,34,25,226,150,176,133,73,64,205,105,231,24,150,162,232,70,129,
+142,51,137,126,200,45,144,194,175,181,141,139,57,252,204,133,38,179,124,168,205,201,54,199,188,99,242,246,152,204,
+234,188,193,109,167,214,16,68,98,24,203,170,21,4,144,100,221,54,4,49,75,29,173,225,209,61,126,248,89,138,
+203,144,121,5,211,44,92,199,9,102,51,175,218,11,253,110,164,90,239,151,111,191,126,245,18,184,220,238,208,56,
+7,85,162,189,12,150,30,246,57,226,120,39,64,59,56,187,197,33,65,4,147,238,75,252,198,67,137,170,143,50,
+53,203,112,130,16,102,224,147,231,8,190,57,86,101,126,218,4,192,241,66,118,72,210,70,86,177,100,5,216,106,
+245,68,159,64,47,216,14,9,48,123,12,156,167,64,175,175,209,110,108,188,99,163,14,168,215,94,103,216,45,181,
+130,245,249,30,107,206,138,170,49,148,179,111,43,163,206,73,229,98,2,101,144,152,122,91,69,102,234,37,168,151,
+241,195,149,42,131,192,53,134,99,181,156,234,191,150,200,191,201,203,255,149,252,7,59,91,35,17,98,45,57,77,
+146,66,175,224,230,121,250,103,212,174,152,21,170,210,161,150,105,102,226,135,169,170,117,104,136,163,120,98,102,21,
+180,90,163,5,139,217,79,240,239,171,216,37,76,107,72,168,84,129,145,106,25,162,33,255,148,242,195,96,66,238,
+89,13,209,144,27,35,225,223,79,247,116,125,146,224,106,2,170,72,109,199,222,252,245,245,219,211,139,199,15,87,
+80,12,211,161,194,84,149,240,239,241,67,250,199,21,116,48,127,153,145,51,0,53,85,186,55,105,114,172,20,246,
+171,201,99,141,195,252,243,32,69,12,143,79,196,240,208,238,24,80,86,87,77,67,93,241,221,227,200,127,173,115,
+190,43,62,143,236,174,236,220,208,66,79,253,255,178,134,21,13,89,253,191,97,152,152,244,111,25,166,172,116,153,
+54,107,185,255,85,217,43,208,111,171,236,239,94,7,163,249,49,154,80,199,195,129,239,42,63,34,110,123,122,130,
+150,3,172,147,173,40,150,154,92,67,197,37,82,111,6,190,24,169,193,99,161,155,167,200,83,95,181,51,67,33,
+120,100,168,137,228,162,224,45,36,182,213,102,102,3,79,176,205,182,173,174,166,38,180,112,75,167,141,68,216,18,
+89,186,29,103,219,80,84,155,226,38,102,62,210,214,58,163,84,187,21,242,141,60,209,62,88,197,248,177,195,174,
+45,2,201,55,100,76,248,169,61,190,81,230,248,150,52,232,233,232,129,183,204,37,160,226,112,67,64,125,182,41,
+100,67,230,163,47,86,169,22,10,41,17,198,74,58,34,127,168,154,116,133,214,66,142,144,147,188,240,185,90,110,
+44,233,53,223,98,243,195,14,137,97,24,63,140,123,7,129,243,251,107,14,119,210,109,77,96,84,46,128,78,216,
+156,222,36,248,243,248,70,113,248,214,134,111,33,108,40,33,49,148,205,133,111,109,248,86,237,119,230,147,54,204,
+169,170,128,16,245,242,178,82,139,62,213,21,67,156,7,65,23,65,215,101,188,109,76,28,221,73,20,231,144,92,
+109,142,45,155,70,229,56,250,42,86,150,172,115,22,31,72,27,30,175,78,5,52,6,84,70,175,118,8,59,128,
+39,50,70,247,82,99,245,77,212,235,29,234,138,210,84,218,160,238,39,42,174,202,94,6,50,26,121,133,4,159,
+77,142,149,221,117,227,169,170,196,222,99,100,134,99,40,167,48,174,192,201,152,143,66,109,94,48,85,232,137,27,
+136,197,61,22,104,29,153,68,79,79,253,136,211,115,28,99,160,220,96,128,158,48,18,177,72,67,250,233,194,49,
+216,201,226,88,76,70,90,244,25,112,109,75,204,18,66,90,164,184,108,159,166,141,193,145,113,206,16,161,251,233,
+98,160,229,112,123,218,53,127,111,218,53,80,205,239,214,104,33,131,244,55,176,156,223,143,131,219,89,137,247,246,
+22,31,15,178,118,155,22,168,112,178,4,176,1,95,16,175,16,127,164,186,157,142,164,189,198,233,87,133,54,99,
+5,159,53,104,235,71,101,218,140,21,125,110,108,242,90,15,186,187,176,175,21,143,147,108,222,135,62,49,185,67,
+4,40,160,14,121,36,89,85,211,210,96,12,12,255,113,56,68,106,181,22,216,38,197,208,40,78,95,231,66,63,
+120,7,251,90,221,38,165,186,78,26,181,78,42,101,169,247,164,238,224,54,232,137,45,68,172,52,87,165,248,14,
+95,64,131,253,164,142,78,228,105,132,39,226,172,102,204,140,153,2,141,38,99,247,178,41,25,128,90,191,26,212,
+59,109,124,118,90,32,172,128,171,30,79,28,196,244,66,80,251,201,94,253,110,140,148,67,86,29,98,123,89,148,
+248,60,81,179,97,135,229,228,57,246,121,83,16,23,230,181,121,7,234,134,17,136,207,91,14,230,63,163,255,107,
+57,141,22,201,255,117,12,191,241,34,142,54,55,255,52,87,255,68,225,247,79,30,197,170,58,80,42,111,83,184,
+176,254,19,245,240,115,12,150,107,83,231,237,63,183,101,99,90,224,87,92,22,40,49,25,61,152,45,206,78,102,
+255,125,110,255,146,56,126,140,213,6,230,75,93,244,245,198,163,9,240,72,80,200,153,76,41,22,49,137,7,195,
+233,111,88,78,151,217,174,254,237,245,33,48,93,231,238,198,163,167,40,67,171,12,60,20,179,245,197,205,205,36,
+9,44,127,140,249,29,16,51,143,52,136,6,51,109,226,43,114,230,146,210,2,159,69,166,57,92,33,67,55,111,
+203,126,55,119,157,42,53,26,78,65,187,44,139,190,173,148,164,85,21,164,229,241,162,92,212,250,41,24,107,66,
+97,133,252,172,133,159,243,56,129,40,140,72,162,24,62,132,53,140,26,173,97,52,177,129,52,157,22,81,133,214,
+211,70,20,237,159,135,39,29,238,214,14,150,58,65,79,94,68,160,36,200,206,181,224,70,145,72,173,96,92,39,
+17,156,25,214,113,54,97,120,153,168,9,3,22,126,250,93,17,2,54,73,218,45,42,90,41,229,141,253,19,15,
+125,116,139,213,150,104,154,50,13,165,90,190,212,106,34,158,166,142,150,146,47,246,173,51,150,162,115,98,75,17,
+43,226,75,58,130,89,122,252,115,102,211,41,54,48,50,231,91,190,233,189,175,155,32,52,98,20,88,192,96,65,
+21,91,154,48,95,107,127,227,121,9,220,30,4,191,210,129,95,85,32,231,7,7,86,21,230,248,58,173,203,232,
+247,47,75,122,133,38,63,0,15,168,224,3,100,127,231,171,220,44,147,7,147,223,79,203,233,239,39,191,71,33,
+140,201,196,203,169,251,135,7,108,213,126,170,150,63,98,249,130,0,187,1,179,132,24,213,138,0,62,7,217,103,
+8,195,175,16,165,123,111,192,82,215,174,196,53,231,182,179,128,70,136,221,122,56,226,69,3,207,179,129,12,66,
+245,194,12,248,47,200,33,15,178,60,149,62,81,117,48,111,81,61,169,129,208,169,144,5,151,210,43,152,74,143,
+52,243,229,81,178,64,4,120,85,82,105,42,6,178,164,58,181,187,231,8,245,129,69,254,47,162,52,182,233,103,
+230,119,41,55,120,206,25,67,43,222,248,17,174,90,131,60,207,227,44,205,214,6,25,188,54,171,0,208,162,199,
+61,219,93,229,37,204,28,208,66,73,211,233,92,85,250,182,138,90,21,53,168,194,241,24,143,109,242,34,167,159,
+2,205,144,178,174,119,58,45,120,14,169,116,29,149,106,230,13,140,84,113,76,181,213,168,47,32,15,189,95,250,
+134,220,250,236,243,254,131,97,30,171,86,94,30,188,78,7,221,125,34,70,26,79,90,134,95,191,20,179,83,20,
+163,98,35,36,243,114,214,60,61,157,199,149,110,166,37,136,68,41,131,70,167,26,93,37,165,174,92,255,139,10,
+15,221,60,41,157,57,195,87,194,52,33,182,139,64,128,205,149,231,64,49,63,49,177,202,138,59,50,60,213,70,
+160,243,181,159,106,255,140,234,187,202,93,124,2,171,133,101,159,180,243,184,156,78,109,108,243,180,196,216,102,118,
+122,142,6,143,154,217,204,171,7,61,61,1,122,235,137,171,100,225,172,21,33,109,230,77,220,125,91,193,251,32,
+50,193,209,164,87,181,129,191,205,58,39,164,101,249,170,240,177,45,109,212,121,232,236,138,207,30,178,86,116,193,
+166,58,33,232,191,97,239,53,173,41,77,221,88,14,123,235,57,111,99,175,47,183,248,72,235,138,146,61,232,114,
+149,191,219,250,103,22,249,232,114,202,198,160,119,190,5,188,158,116,93,172,190,173,142,97,70,62,7,88,142,140,
+126,234,249,189,147,139,170,124,142,38,151,167,239,72,133,196,154,116,155,31,234,135,249,168,230,209,46,102,21,238,
+73,141,52,120,89,121,36,62,54,31,190,143,41,244,209,109,113,88,212,254,46,199,24,219,6,12,172,134,209,245,
+14,161,166,127,164,134,102,236,153,63,180,249,101,66,235,120,232,122,243,91,176,40,205,17,202,229,128,177,44,199,
+70,111,80,205,237,40,42,157,20,217,9,162,20,49,179,21,244,154,89,240,136,189,160,119,28,10,157,144,70,81,
+42,121,192,33,57,244,198,240,41,164,202,187,76,239,193,94,95,46,35,92,40,63,153,246,176,34,237,177,60,177,
+50,114,171,186,186,138,228,230,191,166,205,15,16,61,65,163,76,57,94,67,200,144,54,138,203,197,187,203,54,194,
+139,19,74,142,85,209,196,191,133,77,208,144,139,55,0,183,59,123,67,70,168,61,135,251,109,250,238,60,153,88,
+112,153,168,11,143,43,17,50,46,200,104,110,147,228,234,162,174,170,246,141,13,25,229,235,78,74,117,241,14,216,
+252,105,13,127,147,70,185,39,77,164,101,160,179,103,181,130,69,206,207,249,252,240,167,13,206,20,192,228,205,109,
+84,41,158,110,15,162,181,74,61,94,228,185,175,241,213,209,125,31,95,32,53,229,130,56,114,76,197,7,76,232,
+66,175,244,231,21,6,21,78,208,77,65,142,63,115,85,199,49,101,20,70,223,158,27,251,30,88,213,189,210,175,
+205,170,192,29,116,56,243,49,79,15,94,103,83,91,237,119,206,176,28,128,223,88,77,50,157,22,173,83,235,180,
+233,181,91,65,48,14,102,134,177,226,234,26,84,127,110,49,94,102,226,135,85,122,11,113,64,152,105,236,21,244,
+46,125,135,135,67,8,232,38,10,68,35,206,167,206,240,79,49,152,86,156,71,185,21,235,17,99,69,59,1,35,
+248,124,186,193,133,68,16,97,67,106,73,11,112,179,189,164,245,69,88,105,90,4,20,222,28,234,98,233,103,176,
+73,222,86,80,61,42,25,251,119,164,4,54,32,53,90,81,163,1,160,56,254,152,35,240,252,58,12,85,205,30,
+84,85,170,30,66,85,133,196,183,7,163,58,192,80,165,6,80,132,17,8,69,219,130,211,238,130,33,217,82,117,
+44,135,123,12,155,6,215,113,225,0,2,151,30,65,114,49,120,118,31,32,232,46,177,148,77,114,47,72,98,101,
+191,29,14,25,8,101,199,135,61,12,48,184,151,197,37,96,53,205,222,236,229,116,105,81,98,202,135,32,70,48,
+208,234,157,29,132,155,2,241,38,127,226,24,118,189,135,123,228,210,132,160,124,196,47,33,133,67,152,192,147,158,
+52,16,205,223,157,206,29,205,227,83,149,172,91,137,218,84,222,188,9,73,47,208,50,215,194,208,29,205,64,210,
+75,159,17,82,74,184,216,81,138,167,160,150,133,179,124,152,47,114,60,160,233,18,248,190,116,177,120,81,4,242,
+6,153,139,233,50,221,160,36,13,210,192,124,120,15,22,170,141,131,117,229,99,33,228,5,177,182,128,39,183,16,
+106,133,228,248,71,89,189,196,14,197,126,213,218,115,127,188,226,179,162,136,215,165,20,32,216,14,40,104,198,6,
+101,192,6,141,192,6,85,127,251,215,184,16,120,90,166,186,196,22,157,8,76,75,148,126,125,44,103,62,106,45,
+241,255,14,237,115,162,214,49,154,246,178,87,2,119,23,160,244,141,75,199,226,126,117,226,24,38,29,19,108,37,
+128,73,82,100,6,3,143,23,121,191,117,220,187,21,188,243,92,190,193,168,154,48,170,74,140,170,118,56,46,237,
+180,65,18,37,181,251,38,142,145,207,118,77,120,233,243,186,134,253,57,121,109,208,17,12,54,178,52,45,172,9,
+93,13,167,226,180,79,227,227,95,170,188,140,38,179,167,147,120,138,127,167,225,210,156,90,170,33,86,173,198,125,
+134,86,222,160,227,199,118,115,97,252,123,203,140,32,41,250,175,203,168,113,39,20,140,21,227,123,146,239,155,223,
+62,74,177,118,126,172,64,116,56,91,192,64,102,209,160,117,123,198,81,191,107,221,53,77,24,71,110,241,220,19,
+82,69,42,211,190,163,200,119,132,77,16,173,245,83,52,103,12,92,30,148,17,17,188,144,53,242,66,252,113,183,
+194,81,102,52,186,53,100,181,180,56,44,238,10,47,168,0,65,104,12,22,177,181,231,229,132,225,191,246,27,36,
+64,29,10,159,70,24,231,175,15,87,97,255,106,148,30,89,180,201,190,153,235,197,87,45,217,140,101,52,29,54,
+225,101,143,93,28,6,81,225,32,218,64,94,95,21,228,165,23,167,19,13,240,226,42,195,135,151,122,129,174,214,
+199,158,228,82,6,42,227,153,39,232,135,121,50,246,167,140,29,160,116,110,186,107,236,54,16,192,72,27,66,102,
+35,115,145,40,162,51,171,26,102,6,166,116,239,204,111,143,5,1,168,42,236,82,219,235,18,49,181,207,144,216,
+67,138,15,21,117,60,57,108,161,150,21,129,10,221,52,232,171,15,138,128,248,18,148,243,192,93,120,228,134,32,
+5,125,173,236,192,34,95,164,82,5,182,227,50,198,139,163,211,4,136,204,222,238,81,68,27,67,23,233,192,190,
+40,216,56,130,52,166,221,12,23,101,110,230,177,209,114,177,198,216,107,80,215,158,164,77,160,125,1,71,162,18,
+200,131,18,233,111,196,146,187,46,48,121,36,114,251,130,109,62,211,41,210,8,91,13,197,128,205,50,223,131,23,
+124,111,64,210,126,137,100,72,78,60,31,152,170,198,99,109,218,253,77,188,128,5,196,81,224,183,108,225,83,86,
+232,25,152,217,101,1,104,51,52,244,92,146,17,101,6,180,50,112,85,4,23,163,106,130,65,178,220,18,144,254,
+54,3,243,224,35,245,45,12,206,109,241,62,22,194,148,189,27,212,190,37,224,16,81,14,189,114,152,216,33,141,
+6,196,6,155,158,216,224,197,36,142,249,174,21,0,173,127,183,178,181,126,40,156,101,223,207,191,123,243,242,213,
+183,223,252,243,159,167,102,6,182,176,82,227,205,219,123,78,3,240,149,240,32,60,110,222,231,224,115,12,63,213,
+203,202,59,126,184,153,44,128,187,138,140,213,128,8,174,139,253,45,149,83,121,52,228,139,106,39,170,214,198,69,
+24,244,91,154,195,26,163,229,79,252,170,85,101,119,79,166,211,71,81,58,37,255,192,133,253,154,103,218,202,249,
+100,49,112,163,50,181,230,224,26,131,235,185,195,147,229,195,76,45,225,239,218,17,62,155,26,196,195,170,109,147,
+192,147,75,5,230,79,87,15,163,26,126,26,120,53,86,183,16,115,75,49,240,211,224,99,170,42,225,56,224,172,
+211,229,48,43,198,248,172,2,62,222,239,111,25,41,192,39,188,71,234,20,105,254,147,32,103,191,134,183,211,245,
+147,114,118,10,215,229,53,66,126,161,51,151,109,61,165,59,252,17,160,138,163,44,38,240,189,54,112,172,0,51,
+240,68,125,40,32,198,192,55,128,47,100,60,135,122,28,96,119,141,198,132,71,148,179,178,233,28,74,131,17,229,
+166,103,5,182,130,16,180,149,62,177,166,189,106,253,135,71,193,120,97,26,43,106,169,121,88,63,164,106,184,201,
+138,195,113,39,176,42,207,5,2,72,152,143,151,21,179,108,228,188,240,172,236,205,73,134,99,33,133,131,140,6,
+93,235,20,58,94,184,156,25,77,75,58,220,199,107,157,162,168,239,10,126,74,192,66,248,242,172,163,245,172,134,
+200,24,12,83,167,103,127,135,119,115,52,237,241,247,115,189,158,85,62,162,196,136,213,172,130,145,100,232,7,208,
+22,44,160,216,108,237,11,62,118,5,167,149,143,176,5,167,92,80,76,193,51,154,2,57,1,6,39,160,141,5,
+135,4,230,194,234,5,150,180,173,11,52,119,84,249,40,154,158,49,144,177,22,236,145,183,82,91,214,115,161,4,
+192,212,52,51,71,5,205,26,204,157,155,152,12,182,238,172,64,228,220,224,53,101,77,210,145,81,134,67,44,104,
+122,214,201,73,87,97,82,186,200,22,95,183,17,100,3,62,100,12,249,108,224,28,55,25,199,78,49,140,143,169,
+54,152,96,176,163,29,208,144,31,86,252,170,122,172,220,159,135,134,169,15,218,80,19,90,153,197,158,43,8,85,
+35,190,104,137,159,0,73,119,177,157,106,93,169,138,160,6,98,144,47,70,197,204,244,20,11,34,57,236,28,66,
+212,248,73,2,22,26,122,105,191,148,23,112,169,249,21,1,163,111,125,134,91,47,15,99,31,109,144,168,230,106,
+30,251,106,30,143,87,243,248,214,103,216,175,70,58,66,232,81,84,98,179,224,57,133,10,59,105,249,69,186,105,
+240,73,95,231,238,92,200,224,92,200,8,185,198,36,65,128,38,115,95,150,144,178,169,172,248,193,215,213,146,237,
+197,151,85,91,149,102,18,35,168,58,151,30,212,76,134,108,185,51,55,161,184,190,56,221,119,189,128,240,243,71,
+161,1,249,103,120,35,57,11,246,182,166,167,170,158,69,229,130,212,114,127,87,147,52,132,41,27,18,113,72,237,
+180,23,199,14,67,31,223,216,184,91,25,119,75,113,143,49,31,162,102,206,3,211,200,225,91,132,253,14,29,139,
+108,62,37,249,154,239,80,68,22,38,134,0,72,202,52,188,168,14,184,137,234,153,247,247,207,53,203,42,219,162,
+88,107,47,85,236,241,82,146,4,86,95,250,27,152,94,161,94,218,10,225,90,41,57,251,102,157,66,171,175,171,
+170,61,183,86,27,219,99,52,49,210,35,23,86,121,239,21,193,215,186,79,147,71,101,120,223,203,241,125,79,5,
+191,12,232,138,134,25,195,144,173,180,126,104,68,103,113,239,163,157,167,92,177,61,106,152,17,60,223,237,188,88,
+169,231,171,205,182,53,75,18,145,128,250,7,154,101,223,21,242,121,7,74,195,164,96,49,119,227,254,1,121,236,
+129,250,120,94,104,122,102,69,31,249,189,247,85,248,40,76,255,105,226,47,123,2,223,187,14,189,124,44,38,179,
+201,212,192,147,158,63,46,172,18,253,31,81,123,62,136,162,60,47,80,129,0,213,230,181,52,158,127,214,78,177,
+124,53,133,145,195,243,182,215,37,229,87,218,210,190,210,150,252,74,91,186,87,218,146,94,105,75,222,169,126,182,
+190,21,207,66,81,142,207,52,173,101,180,227,123,253,17,208,57,126,165,197,156,189,42,134,92,255,18,221,224,66,
+137,156,188,190,144,226,150,33,14,63,242,243,249,209,7,101,137,18,163,118,213,106,213,152,246,167,164,82,246,235,
+103,100,46,88,169,111,235,153,84,101,115,228,132,88,14,30,212,70,84,123,28,23,186,66,125,22,218,232,254,92,
+32,206,139,19,160,249,172,64,141,71,146,90,135,243,71,3,142,162,136,159,102,107,139,199,50,31,245,51,68,33,
+230,130,6,221,12,2,197,84,0,141,148,169,203,234,38,73,59,225,97,170,146,82,47,25,9,140,195,56,14,136,
+238,39,37,250,90,109,52,0,18,249,244,108,142,161,190,55,249,175,208,61,220,65,236,76,24,226,38,170,214,0,
+33,141,154,108,210,37,246,30,157,224,219,24,206,5,32,69,107,10,9,189,206,173,59,77,43,0,245,175,116,109,
+215,59,2,82,55,165,79,116,149,95,227,224,56,14,190,172,51,88,170,43,217,42,11,16,201,166,11,230,251,240,
+56,217,206,160,24,229,153,166,246,87,109,48,202,102,135,56,251,65,125,145,202,7,197,108,21,63,218,62,52,44,
+1,95,34,161,41,211,179,217,50,126,180,129,116,91,30,50,136,185,125,91,12,60,49,208,225,160,221,3,49,92,
+59,253,119,216,24,136,184,172,76,73,21,3,234,226,37,37,177,38,101,124,216,62,183,75,104,169,117,117,8,90,
+84,138,11,134,130,128,184,2,233,200,10,100,156,224,23,107,222,186,249,154,101,252,91,240,188,25,63,109,144,196,
+31,5,127,168,82,3,102,76,189,20,159,170,212,36,12,0,91,106,124,6,59,132,144,195,134,39,158,73,194,75,
+218,186,37,53,202,213,154,192,229,182,206,149,175,35,105,48,236,88,157,191,18,138,20,139,132,150,85,209,8,171,
+96,74,142,92,131,8,55,170,138,97,244,10,182,101,142,186,94,53,246,183,9,3,202,7,3,162,158,164,156,201,
+15,42,31,14,138,178,21,218,67,132,128,217,140,7,136,144,79,228,195,96,83,17,15,172,108,105,87,121,126,211,
+161,173,180,28,238,186,121,54,211,75,134,252,21,175,224,26,163,24,242,87,252,225,48,109,38,77,121,100,179,202,
+22,137,213,90,198,151,11,225,222,37,3,160,79,128,96,247,91,40,211,191,230,129,114,204,84,173,10,41,244,185,
+238,37,175,145,104,10,51,7,233,25,92,107,145,133,138,249,160,242,199,16,181,63,83,226,101,168,25,158,67,112,
+229,71,145,3,209,197,156,251,246,16,31,114,250,9,84,51,196,207,93,30,221,60,42,21,199,235,234,145,123,221,
+69,194,202,98,71,255,120,101,165,114,160,167,120,152,112,136,43,129,33,112,4,207,31,228,234,231,208,127,71,139,
+177,60,247,155,155,191,171,94,126,155,74,159,152,24,171,131,202,84,64,62,224,110,224,154,32,212,96,136,74,66,
+160,90,68,7,75,234,82,213,126,204,170,118,35,198,166,218,155,227,158,206,84,73,90,214,244,55,70,57,62,212,
+79,180,211,242,186,216,247,217,8,174,145,218,250,214,243,82,118,104,238,99,147,54,168,38,43,188,55,162,244,14,
+84,211,205,153,152,1,128,253,28,149,40,95,241,19,122,52,105,73,173,215,106,227,198,138,179,213,164,95,125,87,
+206,46,67,209,168,93,208,108,151,62,34,211,193,147,62,19,72,170,68,14,159,97,169,42,144,33,68,73,195,136,
+5,14,55,55,40,15,232,40,145,197,20,165,132,153,197,42,140,107,182,1,165,248,35,55,71,241,247,135,206,171,
+11,156,29,16,115,139,49,236,211,69,30,22,159,22,31,85,65,41,4,237,23,6,77,201,67,61,73,11,255,74,
+47,59,143,9,167,62,222,60,61,89,224,47,132,69,115,47,71,80,32,54,104,175,70,183,246,227,182,83,21,198,
+146,228,59,198,210,7,196,214,154,198,219,224,41,157,226,119,163,42,252,46,240,187,82,45,126,103,248,93,171,20,
+191,215,248,13,27,93,184,206,129,8,84,155,52,142,246,44,26,226,186,125,157,110,194,106,189,40,132,150,31,144,
+151,158,36,155,126,245,230,219,111,88,82,44,95,221,70,94,232,168,104,240,16,140,124,51,150,15,74,53,3,1,
+94,28,91,230,218,11,20,209,108,237,202,67,137,6,74,224,68,244,52,82,63,31,92,138,177,51,24,60,94,113,
+225,216,157,55,97,11,96,137,176,122,81,40,155,79,243,105,59,51,248,48,105,15,14,76,107,53,68,120,105,112,
+145,219,72,167,169,38,193,32,211,227,3,15,171,157,186,249,174,216,54,216,249,80,120,86,118,10,115,193,32,95,
+181,245,94,90,215,169,47,69,143,67,119,165,253,161,208,81,140,149,189,148,153,184,117,121,195,128,97,202,214,251,
+105,208,118,88,219,102,56,191,249,226,87,59,195,201,151,133,20,234,255,178,234,113,26,230,68,65,77,138,22,125,
+150,210,103,221,22,19,50,119,239,81,52,203,77,150,250,204,236,223,118,38,203,188,54,236,189,83,245,210,191,171,
+243,170,206,219,219,94,150,115,200,211,132,60,50,13,186,63,201,175,54,85,221,166,101,11,149,229,116,45,70,217,
+250,231,46,143,46,197,72,126,228,145,180,82,18,145,95,164,71,202,170,254,112,14,246,194,27,98,150,12,138,111,
+170,129,55,220,137,213,147,92,236,46,77,123,109,76,153,60,55,42,171,174,240,178,153,124,155,42,43,181,140,146,
+155,171,182,75,124,166,111,91,159,41,178,247,40,0,99,145,185,133,8,129,85,178,38,218,17,223,59,201,149,41,
+151,9,150,222,150,72,187,21,85,181,73,74,22,10,109,58,215,53,151,251,119,198,230,255,157,203,137,23,239,89,
+14,252,178,223,33,248,159,248,130,98,54,7,47,190,27,158,27,108,133,42,109,168,202,170,211,70,249,241,212,162,
+239,105,167,97,150,232,33,167,21,108,79,238,82,70,165,215,182,59,43,148,194,92,170,45,146,103,43,126,185,152,
+234,66,173,241,207,18,186,183,5,210,109,249,100,11,79,125,81,26,1,191,241,119,197,57,112,57,99,98,185,1,
+23,102,25,103,179,153,90,131,204,96,246,59,44,6,127,220,249,180,126,146,193,88,177,162,88,141,54,205,67,103,
+97,96,41,187,233,95,14,165,52,26,190,149,220,63,33,181,31,178,218,185,5,78,149,155,165,66,204,82,102,103,
+201,119,110,77,149,172,108,231,150,220,185,109,167,253,114,168,13,190,148,226,110,189,194,11,239,165,181,167,113,161,
+110,212,123,70,224,215,36,43,86,68,141,122,175,46,240,229,16,191,98,100,122,170,15,148,148,70,21,36,88,167,
+91,5,124,99,54,117,75,73,87,255,252,231,117,20,171,103,20,56,130,208,135,40,48,166,223,232,181,122,174,215,
+243,55,79,244,10,102,253,77,124,163,219,179,55,200,215,58,186,225,87,146,232,66,103,209,13,173,205,5,180,248,
+30,98,174,116,17,93,208,74,65,103,157,143,229,219,8,81,202,165,78,49,137,186,178,120,147,60,135,28,222,11,
+243,51,202,177,177,111,189,1,240,47,105,126,222,240,252,48,252,215,126,158,226,152,103,36,134,158,190,81,239,245,
+69,16,135,10,117,31,168,117,117,71,173,27,97,173,111,224,233,14,141,27,224,51,143,121,71,230,69,6,140,25,
+199,194,232,243,103,0,184,208,10,62,226,52,98,216,33,67,183,242,239,78,134,250,199,130,147,251,79,148,223,12,
+223,16,81,254,87,183,179,83,220,63,6,136,227,50,102,103,185,45,189,97,53,246,13,107,30,67,23,230,33,101,
+36,161,249,157,134,122,173,191,189,6,122,244,180,193,108,213,239,90,151,177,10,114,185,21,230,221,245,65,95,236,
+158,209,167,48,222,19,149,3,225,26,170,72,53,61,173,21,108,222,161,157,158,130,54,157,54,0,96,65,220,13,
+178,20,191,107,96,231,81,55,254,249,79,248,109,171,205,34,229,96,84,146,127,121,59,107,220,165,246,119,182,83,
+192,99,0,44,215,48,222,235,80,168,162,214,92,190,72,8,84,18,52,238,160,108,101,196,145,44,98,164,187,50,
+111,135,193,3,206,120,19,181,172,190,18,128,50,96,117,249,197,70,112,169,54,152,167,241,188,108,105,110,10,17,
+78,227,16,206,185,151,233,60,58,130,215,85,108,200,77,123,141,205,19,162,69,201,2,235,88,24,11,151,36,196,
+16,59,20,216,160,126,71,191,136,237,111,213,193,241,139,160,231,132,52,210,39,245,34,157,54,144,158,217,214,86,
+48,236,87,144,21,48,47,110,82,43,15,223,0,164,201,186,127,193,214,107,228,189,197,74,122,232,198,228,33,213,
+125,84,194,109,174,60,14,146,128,16,52,139,54,249,217,195,139,124,57,217,7,34,47,37,44,141,82,144,79,197,
+38,242,147,10,216,244,66,122,180,134,81,115,74,178,115,243,13,211,134,167,78,225,103,93,101,14,42,241,154,182,
+34,227,250,246,149,89,45,1,223,5,81,168,104,163,174,212,165,186,112,125,186,209,233,98,118,154,208,238,219,0,
+168,92,217,19,108,51,133,67,203,156,109,224,172,226,205,3,44,177,27,130,114,136,190,10,209,87,83,136,134,108,
+80,20,98,81,225,164,7,101,144,66,107,6,105,118,213,46,25,47,93,116,72,249,95,168,21,22,195,187,142,127,
+60,223,240,131,255,10,122,182,74,54,118,20,124,102,152,179,21,52,173,46,169,35,48,176,233,41,156,172,122,131,
+14,220,231,203,128,162,46,32,227,18,50,206,47,113,102,229,130,69,191,224,125,132,100,190,147,9,35,189,137,218,
+156,36,87,106,115,154,92,192,23,138,169,219,121,143,150,184,249,10,72,8,113,80,171,234,47,78,135,238,107,191,
+47,162,75,133,55,249,109,180,82,80,76,109,142,113,180,16,165,174,96,144,107,125,217,173,158,64,252,72,6,207,
+92,17,15,8,194,38,221,110,96,81,11,206,250,65,140,98,3,90,233,230,13,19,3,253,8,78,127,158,54,107,
+159,134,1,17,255,45,177,163,125,106,136,226,60,95,193,206,151,149,139,24,37,84,226,49,53,132,56,197,247,58,
+132,58,225,99,131,177,76,120,121,25,220,222,114,60,251,247,110,116,29,59,59,251,140,54,211,47,205,131,15,127,
+56,254,207,227,83,233,231,236,250,250,250,216,9,254,87,245,59,225,216,236,113,40,134,80,81,231,151,91,148,22,
+251,72,7,103,100,192,238,175,69,207,128,157,183,57,106,64,109,176,105,131,149,48,222,238,254,250,170,56,223,182,
+44,201,118,216,41,71,64,165,45,0,153,51,14,214,93,148,85,139,35,29,218,213,146,106,4,120,2,215,16,177,
+220,90,237,214,121,37,213,26,210,104,71,77,39,173,98,45,199,196,28,243,151,2,65,222,55,173,129,105,170,29,
+51,31,131,73,176,206,59,51,140,60,234,24,224,187,131,129,173,106,211,172,135,3,133,195,107,48,160,19,213,159,
+137,139,202,10,110,90,14,13,201,59,113,21,219,205,146,12,96,170,241,169,11,149,194,99,28,6,125,31,108,143,
+184,120,171,113,218,142,203,10,8,63,190,6,2,225,34,167,222,79,10,234,220,176,119,111,192,225,92,57,225,243,
+188,53,87,13,35,210,190,222,70,165,57,149,15,252,42,232,45,217,23,27,139,17,235,167,208,232,108,86,199,133,
+38,233,225,226,248,34,37,171,109,139,8,62,219,170,77,139,167,165,95,40,64,146,33,160,93,134,24,74,181,96,
+98,14,160,155,30,103,224,96,199,186,160,194,208,232,185,170,172,203,233,120,110,95,173,209,20,143,159,66,134,153,
+70,149,120,249,4,10,255,29,204,87,51,137,99,229,106,64,98,227,120,8,124,131,114,72,241,227,173,115,18,171,
+210,1,140,85,115,155,250,225,119,241,16,110,91,101,216,177,246,16,194,227,14,5,208,158,149,249,85,35,205,163,
+202,37,98,254,140,33,246,76,59,96,207,236,184,42,224,43,122,72,6,48,163,85,73,128,122,13,42,72,59,215,
+117,140,230,225,99,150,174,195,107,58,86,205,124,28,91,196,110,46,134,104,217,71,177,197,204,185,115,19,222,161,
+124,22,93,168,236,251,160,159,209,253,226,212,53,79,4,155,184,67,65,91,129,227,198,11,120,101,159,142,118,222,
+161,185,114,115,132,189,136,204,177,216,120,188,101,197,134,80,38,128,153,225,86,106,179,220,102,198,109,6,207,183,
+47,21,180,224,50,199,200,202,29,108,186,184,227,166,34,150,197,235,173,115,112,124,127,87,159,57,19,191,176,138,
+45,104,250,91,176,67,250,246,190,9,200,87,92,207,29,219,215,15,219,217,139,243,59,137,111,18,118,223,54,228,
+224,11,25,42,153,41,224,202,200,133,240,110,68,45,75,108,28,102,87,110,149,206,178,158,229,42,203,46,179,240,
+115,203,6,5,191,179,66,132,127,45,184,155,203,70,79,132,233,118,112,244,83,232,221,101,85,21,38,29,58,199,
+50,232,234,11,78,234,78,145,53,137,225,243,134,105,34,80,56,94,54,177,194,193,146,174,47,92,200,0,200,48,
+210,111,44,184,23,53,54,113,209,0,190,199,213,55,61,147,181,73,219,169,146,184,161,67,62,220,20,57,47,232,
+136,191,155,219,147,240,47,253,147,112,255,192,66,129,174,70,95,154,232,12,101,42,136,206,111,73,176,209,27,166,
+175,57,21,35,21,228,128,4,156,61,135,67,195,161,178,42,53,228,2,180,240,69,129,149,221,110,96,253,89,170,
+162,118,75,101,82,178,202,249,222,64,14,251,13,54,110,193,115,170,117,148,205,153,104,163,200,183,158,176,170,48,
+64,92,174,244,22,109,176,185,93,224,119,17,6,25,95,203,226,173,223,103,174,4,18,119,112,9,105,137,202,227,
+56,251,156,175,13,7,145,5,227,237,163,227,216,117,173,92,253,186,9,153,174,242,198,52,142,48,176,83,50,52,
+45,110,99,59,62,19,131,77,27,153,26,239,122,176,124,116,26,68,127,101,247,206,66,231,80,254,176,156,137,25,
+83,181,238,207,199,172,154,203,9,45,135,211,37,166,200,99,154,90,137,217,138,149,152,81,56,95,238,154,189,42,
+0,145,81,141,7,34,49,129,18,142,26,101,80,174,207,237,233,157,156,10,62,165,236,113,43,232,7,37,51,249,
+243,81,204,88,220,81,17,137,153,122,243,83,14,230,71,53,58,76,39,204,102,232,170,159,74,26,97,234,1,203,
+202,159,207,7,107,167,241,41,15,79,124,208,166,48,79,202,88,29,13,86,86,46,96,115,174,211,65,207,79,164,
+205,61,243,228,100,191,68,229,50,20,218,60,42,127,247,88,21,232,97,176,120,122,186,120,60,43,146,2,130,114,
+123,133,39,218,83,37,158,126,11,188,10,13,107,118,91,55,170,72,7,176,187,78,243,118,104,246,220,131,57,18,
+148,50,2,113,112,60,80,157,195,248,136,237,2,239,90,190,109,214,164,242,89,155,95,144,141,209,197,158,128,150,
+75,181,152,64,46,120,31,129,92,19,85,238,181,124,118,126,23,243,11,79,8,32,7,162,216,137,18,252,132,242,
+80,55,19,133,86,42,38,226,218,3,33,107,15,6,62,88,94,110,114,174,190,194,220,132,178,125,238,207,56,52,
+184,206,129,28,213,151,68,173,76,188,57,236,137,218,17,74,226,135,69,229,192,43,57,53,127,80,118,69,146,137,
+244,143,63,81,171,210,101,70,104,115,223,8,108,238,187,173,252,23,160,80,254,246,250,0,255,40,122,46,82,190,
+12,182,185,99,232,158,55,26,44,251,40,12,219,14,13,214,42,161,20,231,205,226,86,229,119,76,163,129,36,29,
+199,124,230,78,84,142,89,149,147,46,222,155,15,171,158,94,160,134,15,223,228,121,102,55,222,144,112,242,85,193,
+71,88,200,68,193,126,174,159,138,174,59,48,160,166,55,34,31,47,59,68,103,118,238,50,219,205,152,236,124,206,
+100,231,23,10,252,166,117,157,170,13,106,79,143,231,192,116,52,255,44,82,155,196,143,146,22,177,71,35,116,234,
+67,222,228,56,159,60,58,166,23,38,74,86,217,169,117,190,52,227,117,182,213,71,214,232,65,204,158,161,8,92,
+180,136,255,196,6,186,152,9,129,159,171,33,33,16,239,4,17,164,91,101,67,126,246,7,151,98,167,79,106,34,
+19,119,33,192,212,38,234,32,246,105,59,163,135,245,177,57,129,129,230,233,55,233,149,65,42,219,223,3,75,64,
+27,254,228,67,234,196,214,223,12,234,71,35,108,3,251,54,176,43,98,186,147,53,240,103,14,198,120,155,227,208,
+58,48,127,66,16,241,9,84,29,26,173,161,81,210,115,42,137,100,37,125,234,24,138,216,139,9,234,78,88,180,
+101,23,202,124,107,25,126,81,159,184,115,28,66,213,232,79,10,186,205,28,98,182,242,196,147,113,142,103,126,237,
+241,138,23,176,233,241,39,13,44,140,89,130,128,53,84,230,89,186,159,120,88,193,220,199,237,218,148,17,93,219,
+125,22,93,118,138,98,136,97,60,104,101,216,233,225,34,41,34,171,161,135,178,33,68,251,50,172,177,234,90,247,
+53,104,84,42,174,54,246,156,100,174,123,29,200,250,194,82,244,82,215,252,172,160,37,206,250,126,115,62,153,4,
+29,4,76,197,56,30,31,72,82,133,235,27,245,127,108,89,226,160,178,225,68,50,205,89,102,121,176,43,93,225,
+39,83,247,186,164,59,75,22,219,23,66,248,3,115,190,58,118,164,28,112,58,143,153,114,91,170,181,74,69,197,
+164,32,183,10,23,19,92,237,37,0,208,50,80,80,59,84,96,208,235,80,166,194,240,10,247,22,208,230,80,99,
+171,50,100,67,242,136,86,158,223,216,8,114,209,19,139,114,165,156,169,7,160,22,6,78,149,130,164,70,215,91,
+230,113,80,32,158,126,255,122,6,55,32,210,119,18,248,65,33,85,115,34,205,104,22,35,15,85,125,83,85,31,
+245,88,149,159,225,209,125,62,71,61,90,63,231,254,149,170,58,182,244,136,159,22,38,48,80,11,59,50,210,64,
+99,177,239,135,131,77,57,121,206,61,91,254,216,249,8,47,103,234,223,193,194,166,139,66,46,163,247,76,211,27,
+181,227,156,120,124,126,34,241,119,55,112,169,191,29,90,34,129,179,211,85,77,198,167,16,115,212,230,3,58,64,
+80,208,24,210,109,94,182,20,238,146,248,252,102,144,130,235,69,206,123,111,240,229,162,178,207,100,240,213,244,158,
+202,218,76,60,52,27,82,228,28,50,3,74,77,93,68,29,34,252,18,224,67,182,191,26,228,222,179,245,175,18,
+191,157,253,47,86,147,179,54,192,74,27,16,45,155,204,75,241,219,75,167,195,108,100,188,140,20,251,160,122,133,
+235,195,18,225,240,101,171,102,101,166,21,42,186,195,236,151,26,194,138,58,211,114,71,140,235,68,105,155,111,212,
+50,111,144,124,89,38,57,13,82,242,176,199,159,84,145,197,243,166,170,91,179,124,110,31,12,190,54,240,227,196,
+145,26,54,122,100,159,63,3,232,62,169,224,237,176,137,25,60,17,116,89,113,121,68,219,243,157,127,160,18,6,
+67,113,104,184,63,168,214,43,86,26,105,114,18,240,144,170,73,116,199,224,183,65,231,217,238,68,165,186,113,93,
+169,159,164,164,170,132,11,91,104,210,28,34,181,86,187,212,37,238,16,143,66,217,26,93,6,109,147,105,158,6,
+13,136,126,2,40,15,95,99,225,146,110,159,235,191,110,173,121,0,248,205,98,76,106,167,58,243,59,79,174,109,
+158,73,141,75,185,235,81,165,148,144,27,123,27,231,222,10,15,126,206,123,31,94,190,134,46,112,42,235,186,207,
+192,31,141,138,130,234,54,33,11,58,35,147,187,185,99,91,29,147,42,189,89,250,98,82,92,27,248,213,54,221,
+75,242,132,74,203,172,207,80,33,81,206,124,217,29,127,178,107,249,215,216,194,80,35,113,56,186,191,135,210,13,
+148,150,86,192,90,178,219,101,20,124,63,183,74,46,214,48,152,11,160,13,9,60,122,190,111,76,77,178,223,77,
+20,75,59,96,37,108,116,214,40,253,230,243,47,158,189,125,249,195,231,23,47,191,121,241,242,155,151,111,127,166,
+170,155,133,113,25,190,251,246,205,203,94,6,169,98,155,237,169,80,158,181,228,90,136,149,140,61,205,113,102,48,
+26,127,48,58,212,112,229,33,89,170,254,54,244,18,136,35,248,26,101,47,1,134,127,176,20,170,221,73,101,236,
+208,90,20,75,124,207,222,97,206,89,160,160,66,221,142,35,252,120,226,95,149,57,75,39,149,204,131,70,188,92,
+121,126,69,49,108,116,104,137,77,163,166,67,78,168,212,218,84,64,250,197,127,19,237,178,203,223,160,103,23,0,
+176,15,246,163,86,212,32,62,119,151,170,208,112,18,221,228,13,42,117,216,143,181,46,51,82,250,40,99,124,188,
+149,138,150,75,127,202,109,225,148,219,62,65,225,149,173,27,238,6,224,121,123,174,118,176,221,146,43,5,39,127,
+114,217,233,141,186,208,27,209,53,255,77,75,177,212,23,72,33,192,154,65,179,234,42,86,75,180,177,115,169,150,
+200,126,216,104,88,9,64,198,112,20,171,146,224,47,198,4,139,11,125,218,169,75,235,132,36,94,62,216,46,236,
+219,134,151,126,92,27,26,105,113,220,139,52,9,90,107,160,210,201,204,153,20,241,171,51,249,66,72,70,233,252,
+93,11,122,194,143,177,254,106,44,223,102,91,149,243,175,117,7,196,46,4,38,202,222,111,56,111,207,182,100,202,
+160,124,103,123,174,118,82,78,90,186,166,225,41,198,125,178,23,168,196,220,223,129,94,235,107,51,156,68,68,176,
+53,250,33,169,45,196,210,201,66,48,5,0,237,190,112,250,44,241,113,84,122,183,23,23,182,119,243,225,118,10,
+59,165,97,184,176,69,1,77,87,176,20,30,141,217,224,153,9,49,142,234,97,169,68,78,238,28,67,228,199,220,
+171,151,215,6,231,21,122,129,129,18,149,21,213,69,227,117,212,23,121,178,71,239,228,177,42,178,160,144,5,200,
+22,184,127,112,119,93,154,18,240,41,119,20,201,166,29,66,80,2,71,174,33,163,177,246,180,177,14,171,248,34,
+250,172,61,112,17,237,223,67,65,144,29,54,26,252,21,14,165,60,111,22,247,186,61,183,191,221,8,103,94,2,
+7,104,140,64,212,132,1,255,4,135,235,170,135,89,113,175,112,197,124,126,72,31,80,118,161,122,15,114,8,23,
+253,44,86,251,240,249,94,188,37,17,191,29,171,21,159,6,223,32,201,180,31,253,25,156,5,253,104,83,34,109,
+99,235,121,3,117,202,238,124,194,134,86,6,45,223,150,25,10,217,251,71,18,126,155,131,59,3,236,94,25,240,
+199,248,112,94,230,131,123,63,79,98,145,151,239,9,172,27,140,241,75,175,225,64,110,25,224,157,175,64,82,12,
+176,123,13,50,243,133,134,118,39,242,13,194,186,90,63,63,176,187,134,93,136,229,226,183,93,104,122,216,109,123,
+71,217,95,91,85,122,64,96,42,143,156,177,160,144,135,218,170,13,128,242,138,237,45,44,147,21,251,107,221,36,
+91,34,185,201,127,217,203,231,96,204,181,116,223,10,208,104,171,32,123,28,211,219,254,173,200,114,219,203,114,139,
+89,82,164,236,69,150,186,151,165,198,44,133,54,193,89,154,202,48,196,5,154,168,80,214,14,150,90,67,244,7,
+17,93,171,10,239,161,208,69,154,13,63,68,10,129,244,246,203,37,106,140,65,247,14,38,215,152,92,31,76,78,
+49,57,63,152,156,97,242,135,131,201,235,184,19,243,237,81,117,88,40,242,230,228,157,251,157,133,53,62,239,120,
+199,142,150,242,149,218,44,161,88,220,245,59,208,142,148,230,243,14,237,96,94,32,7,170,93,27,59,126,193,131,
+222,223,2,174,26,173,181,155,144,133,27,122,226,98,186,218,208,64,251,146,19,140,101,227,14,77,30,181,117,117,
+123,207,86,99,196,2,122,169,77,20,130,10,63,229,62,179,251,36,238,40,245,179,181,201,222,15,235,149,115,143,
+91,130,189,111,69,246,3,57,246,158,187,142,17,120,186,160,41,153,56,68,105,160,239,77,240,106,85,30,249,91,
+69,188,131,222,217,119,164,225,251,148,24,205,218,144,253,95,119,198,65,147,157,241,174,159,243,230,243,155,214,148,
+68,40,66,43,192,106,41,34,99,107,28,197,93,190,83,166,235,36,62,185,127,54,195,4,245,188,73,114,13,111,
+111,55,244,210,228,162,233,214,114,32,95,220,93,110,243,98,249,109,253,61,173,173,239,131,4,157,251,49,15,223,
+44,1,115,239,247,208,179,6,141,95,233,185,233,33,87,7,118,120,81,55,254,6,83,218,47,24,8,217,84,134,
+153,15,201,46,49,8,11,224,204,138,206,171,8,232,79,124,187,10,45,193,122,92,90,248,83,198,173,159,224,247,
+142,226,93,62,35,60,172,53,198,26,121,34,147,126,225,224,37,176,195,249,224,115,12,179,80,250,16,100,21,62,
+136,245,206,99,103,200,248,181,105,42,244,171,207,32,216,19,211,140,7,199,181,172,224,152,35,15,145,15,29,13,
+52,146,54,232,228,117,66,209,74,225,125,13,203,139,219,131,155,181,164,198,123,67,202,247,6,54,82,213,90,137,
+27,163,181,191,180,47,142,78,146,18,230,154,216,14,42,211,45,186,8,41,221,60,159,181,40,66,68,238,232,112,
+83,246,135,67,156,27,159,85,55,202,215,131,235,14,17,86,161,248,139,8,81,92,188,88,218,241,83,110,186,138,
+227,104,97,218,172,191,201,228,215,145,108,118,127,246,243,201,116,80,177,185,202,145,206,150,89,130,123,186,8,15,
+83,184,171,120,19,92,160,27,129,225,39,25,252,33,50,215,218,227,49,100,141,39,12,122,61,109,145,33,10,31,
+231,100,32,102,75,178,249,86,166,41,211,171,120,30,6,90,116,117,0,79,0,203,253,110,13,4,28,246,239,121,
+176,132,126,157,84,225,238,119,153,85,192,126,149,94,194,36,70,120,224,86,48,140,90,173,4,43,163,177,219,151,
+232,6,26,142,213,29,105,80,119,132,212,68,54,122,57,45,213,234,108,121,174,201,73,230,26,246,150,157,185,40,
+59,131,215,250,77,172,240,30,88,115,156,177,113,158,183,177,234,6,139,53,24,202,141,27,202,173,28,202,176,131,
+222,165,161,115,104,8,99,3,128,124,146,145,200,251,90,23,216,69,109,112,178,83,232,13,114,89,92,39,87,168,
+139,180,70,69,197,218,199,32,60,134,46,166,157,4,148,143,237,227,142,104,27,64,6,73,74,222,96,111,93,176,
+208,64,38,65,14,9,231,42,219,31,17,237,8,181,117,48,4,253,111,0,142,86,4,71,75,189,134,17,109,181,
+129,105,87,25,12,75,142,8,108,234,109,145,126,90,134,65,113,100,129,145,126,92,89,135,154,100,152,58,164,29,
+36,70,15,219,244,220,209,55,140,75,239,42,132,152,3,75,144,241,235,55,136,46,162,129,208,185,32,96,171,253,
+99,164,134,161,181,8,165,100,15,207,95,175,26,121,189,242,204,13,151,211,143,236,29,91,189,227,219,169,245,187,
+91,118,142,22,127,13,138,101,230,5,176,212,221,224,135,226,65,192,10,178,53,58,1,75,222,221,11,48,15,150,
+84,222,186,96,131,88,140,251,224,75,64,164,149,130,180,189,212,56,22,232,15,74,24,13,71,105,187,135,40,156,
+184,223,94,124,129,130,170,166,248,244,38,168,177,83,16,226,137,92,204,203,175,211,161,115,254,225,44,54,218,35,
+28,152,100,143,81,224,238,138,3,98,58,78,213,30,81,123,145,143,33,169,168,10,93,88,247,134,97,217,16,79,
+33,195,110,156,23,199,204,186,131,156,188,78,81,217,53,101,90,117,186,201,162,212,163,154,121,224,119,194,209,11,
+216,6,192,156,103,253,74,111,207,82,158,106,230,232,127,18,109,25,2,208,2,203,26,21,174,86,79,174,58,70,
+86,128,168,106,116,66,113,4,85,57,17,155,113,48,200,84,171,104,143,84,177,213,128,195,227,168,138,119,182,162,
+26,222,241,150,246,29,111,25,67,2,214,23,239,62,162,58,230,66,119,114,215,61,43,10,155,139,20,60,239,164,
+168,252,2,150,64,24,6,227,111,130,77,111,134,108,122,220,60,205,185,223,63,159,68,53,26,24,101,19,159,129,
+237,137,29,1,24,250,22,40,139,85,129,207,151,59,111,209,210,157,10,207,74,219,195,123,72,62,227,64,169,209,
+158,94,227,77,45,81,140,247,150,128,85,3,159,23,253,130,248,3,8,238,48,182,41,224,224,240,98,38,147,9,
+155,244,111,48,111,51,150,183,9,121,59,150,191,190,251,110,35,86,12,5,16,61,247,43,70,202,15,253,205,105,
+147,129,195,144,30,29,133,209,170,205,34,119,245,244,151,76,187,29,134,243,136,118,183,66,79,58,100,110,236,211,
+237,237,141,50,18,9,142,111,95,190,197,208,227,180,177,57,159,213,6,113,10,68,165,122,192,84,1,233,64,85,
+232,62,75,5,34,221,246,158,161,14,146,24,216,65,79,222,246,252,177,79,22,142,182,69,8,226,79,42,22,181,
+202,202,78,169,181,78,225,96,74,167,5,30,77,193,222,71,3,199,210,124,197,236,50,184,136,173,142,157,156,91,
+182,168,221,187,111,178,242,149,193,164,121,114,73,186,126,91,199,53,212,20,178,33,112,146,146,199,64,14,97,49,
+177,245,79,2,71,211,95,100,229,51,200,96,150,221,160,22,148,80,91,82,251,121,239,46,228,30,216,203,56,25,
+102,26,228,160,21,40,227,46,80,232,195,99,111,252,118,84,17,229,251,84,99,255,158,140,246,144,231,35,88,190,
+61,116,228,206,43,93,123,238,24,76,123,8,232,52,139,246,238,15,170,37,27,206,76,59,44,247,54,45,38,193,
+204,235,198,213,239,78,85,160,29,61,215,89,183,86,40,128,247,188,104,189,23,214,53,119,96,95,219,76,112,188,
+176,55,254,118,218,248,230,124,28,183,232,243,123,229,73,134,47,16,209,52,170,178,143,140,165,170,186,59,151,116,
+72,194,112,230,97,174,241,251,49,188,141,161,106,222,29,224,160,204,111,171,127,80,185,193,234,15,149,81,70,123,
+64,151,16,134,55,47,183,21,84,165,199,238,126,170,214,214,106,153,81,41,235,134,232,67,28,87,54,128,76,198,
+185,99,30,203,69,67,222,124,188,27,233,253,75,241,90,103,131,9,27,185,27,227,240,144,172,93,156,193,139,99,
+219,125,137,14,10,254,174,38,107,252,37,83,5,147,243,228,140,126,212,82,103,247,223,161,145,140,223,14,36,4,
+249,209,131,238,125,106,67,215,181,225,30,64,210,79,93,233,204,237,107,148,205,90,186,105,166,139,143,90,249,83,
+243,74,200,74,248,111,93,40,156,69,215,244,170,54,6,120,204,48,75,87,86,250,244,202,47,162,148,66,185,159,
+30,30,46,218,223,83,87,124,70,214,67,121,245,122,107,147,6,97,221,128,231,125,185,35,188,80,123,51,158,35,
+11,183,210,107,183,112,190,175,163,75,135,111,112,122,125,255,162,224,220,21,122,61,100,101,44,247,88,25,173,42,
+161,82,103,163,196,94,136,126,174,162,6,175,199,69,24,65,80,24,160,248,224,81,3,22,100,100,17,50,180,207,
+68,71,134,124,148,112,2,124,71,173,91,66,55,125,35,47,24,140,198,6,177,251,210,49,45,116,158,157,143,140,
+32,0,84,11,249,49,143,90,32,81,197,172,95,132,113,61,103,81,142,110,43,185,109,225,114,2,133,155,120,49,
+20,122,114,103,210,8,128,25,40,229,41,29,200,200,21,251,137,144,80,136,90,237,208,0,50,38,15,85,231,94,
+17,251,117,94,52,124,26,135,142,182,14,17,55,125,201,63,127,110,147,25,246,195,189,46,123,253,222,57,53,227,
+163,134,251,182,183,152,21,204,105,213,57,117,23,66,35,162,75,76,164,203,142,150,202,35,72,84,5,131,148,223,
+88,232,4,6,110,91,99,56,23,229,37,165,55,78,106,204,97,182,247,170,231,233,237,117,12,211,255,247,26,192,
+65,12,153,163,67,194,25,43,84,229,120,67,225,17,247,140,100,119,206,241,33,183,199,202,142,49,8,76,161,8,
+82,227,249,30,155,59,88,121,15,86,12,140,251,172,195,125,184,82,184,233,237,144,152,157,113,130,215,227,234,105,
+179,176,149,230,101,99,234,214,15,163,81,213,12,237,63,36,213,19,7,52,188,92,62,11,212,57,171,226,110,88,
+146,22,31,245,28,119,135,216,252,170,98,90,136,14,81,99,237,100,122,109,255,76,63,181,162,34,60,140,169,198,
+35,54,11,162,160,233,83,93,207,211,217,44,206,216,147,208,12,30,171,45,215,10,224,24,73,250,121,74,102,112,
+211,184,194,28,136,5,199,200,131,121,143,127,4,152,48,242,15,15,76,76,5,230,174,194,215,106,127,237,145,115,
+128,195,245,47,54,131,84,191,159,187,225,220,221,201,116,216,227,225,186,172,130,25,225,92,138,17,39,181,236,63,
+242,96,147,157,189,106,200,108,29,1,14,2,232,94,253,125,184,242,94,229,130,165,201,51,28,8,42,125,224,164,
+161,250,164,109,68,160,97,126,147,192,27,124,99,43,16,207,115,10,5,110,207,227,142,189,197,125,135,201,97,15,
+130,74,201,150,166,133,215,88,128,121,116,54,25,192,215,68,237,157,143,146,186,159,181,74,54,84,33,247,163,95,
+157,92,9,95,221,112,99,6,117,224,211,80,219,27,20,97,185,183,190,147,94,145,48,253,59,56,94,239,233,137,
+50,94,119,174,220,155,149,217,99,116,5,122,207,212,168,50,180,253,125,217,112,135,239,46,116,162,134,77,65,29,
+221,179,246,152,73,227,6,5,230,159,73,15,62,251,116,60,241,246,246,51,237,229,8,70,163,178,32,118,155,243,
+244,31,127,114,153,214,66,72,230,160,128,152,183,252,38,85,123,246,25,57,164,222,163,75,164,203,178,180,141,144,
+163,35,229,110,70,152,72,232,171,174,215,27,253,170,130,251,59,242,252,34,68,137,64,250,34,206,243,162,141,189,
+188,66,220,167,39,229,152,59,214,142,209,48,234,86,229,86,198,138,135,0,59,199,118,153,173,169,7,68,72,162,
+248,168,90,240,135,199,255,249,231,255,4,11,143,240,57,195,239,255,2,114,138,253,175,68,130,231,89,42,239,250,
+179,158,165,49,250,231,65,108,88,199,221,221,156,46,235,234,41,191,17,76,33,156,170,88,21,108,101,201,203,166,
+216,42,90,210,175,107,238,169,232,45,228,137,26,172,68,176,203,130,37,140,108,223,134,138,57,134,73,124,187,134,
+114,165,105,26,231,140,192,21,254,6,73,183,8,90,199,177,130,237,93,88,81,243,174,170,111,191,51,53,90,205,
+75,223,25,85,219,42,66,76,156,64,129,230,97,9,41,167,177,2,137,191,109,249,62,169,30,65,152,236,26,215,
+108,34,11,160,22,59,221,128,21,173,89,245,232,177,16,126,91,142,116,211,229,134,153,192,18,204,223,206,193,224,
+34,4,209,54,59,2,58,218,15,122,210,120,44,130,73,83,78,242,235,59,54,134,121,237,141,81,69,181,174,102,
+81,202,225,69,139,18,212,179,246,216,118,57,69,40,84,105,200,156,234,10,253,123,251,11,37,150,173,102,30,54,
+200,111,220,163,199,15,189,187,88,59,23,30,96,82,40,138,201,126,110,6,51,201,51,149,137,185,217,142,45,33,
+31,153,104,158,158,28,232,137,152,83,140,145,52,9,238,39,149,6,222,60,134,249,5,180,70,3,242,243,0,206,
+241,211,208,83,251,200,135,124,56,100,239,187,71,3,157,161,168,67,182,109,80,158,113,7,125,127,67,29,46,20,
+124,126,94,46,147,172,111,14,77,145,187,92,226,156,75,195,216,127,173,194,152,188,203,156,60,94,136,177,38,190,
+201,48,54,136,150,118,226,111,154,253,153,241,72,160,66,57,191,240,106,32,31,15,83,141,178,146,149,42,28,155,
+58,227,55,93,34,135,180,65,113,158,105,9,94,56,214,228,133,99,169,81,69,68,173,80,138,109,229,184,184,26,
+88,157,142,112,169,49,57,139,85,97,207,99,24,220,18,170,171,32,42,92,0,133,253,174,92,26,15,68,33,68,
+158,69,105,185,16,35,113,62,71,68,160,223,13,37,44,115,242,104,241,117,11,213,38,17,138,111,124,89,213,249,
+175,21,192,19,224,132,197,105,50,59,141,31,218,135,154,167,218,216,176,144,210,30,42,1,168,42,56,126,93,251,
+138,80,29,0,251,212,152,167,249,49,178,131,173,173,76,85,58,227,153,113,226,115,128,11,157,91,204,193,214,237,
+49,15,154,189,135,165,91,68,141,158,0,92,32,179,103,130,112,66,229,26,247,141,177,152,234,205,225,25,171,49,
+161,88,74,57,105,21,233,59,40,91,115,79,141,226,42,27,90,69,107,217,98,206,27,48,179,180,49,75,161,149,
+198,74,95,187,188,159,67,87,61,165,156,190,201,44,223,135,130,250,144,185,62,172,59,77,83,56,111,132,237,88,
+144,41,64,253,20,230,81,125,74,141,188,38,157,86,20,5,136,12,73,10,163,126,60,57,130,109,116,150,96,156,
+173,81,68,175,209,130,9,176,50,214,202,186,255,60,199,210,144,59,142,21,197,55,50,126,111,48,97,110,32,235,
+112,183,149,139,40,215,151,14,146,84,174,63,96,30,131,140,129,4,3,62,33,212,226,115,75,195,151,237,194,36,
+248,139,70,188,68,94,95,129,204,203,171,140,57,49,132,43,141,165,67,169,11,108,97,151,151,171,2,149,160,174,
+200,12,95,219,41,82,8,234,197,234,22,43,72,183,109,5,53,192,231,233,226,248,15,127,72,78,32,179,149,96,
+125,159,63,48,40,194,180,36,97,214,195,66,8,190,123,55,141,143,146,143,252,247,103,245,143,237,119,203,54,252,
+11,143,237,86,18,130,101,32,83,0,191,181,174,135,81,43,135,200,44,11,240,138,165,31,240,217,189,156,6,249,
+135,43,251,8,191,65,68,182,57,171,24,145,137,183,248,43,149,209,91,252,202,35,50,138,92,199,80,105,13,9,
+30,157,173,238,123,158,110,182,27,160,252,238,206,36,76,4,241,129,50,175,172,52,206,240,170,224,5,182,163,209,
+231,231,10,255,30,120,130,174,240,111,28,31,122,64,124,112,242,219,30,16,221,154,150,110,77,155,78,143,62,32,
+170,90,87,110,88,42,213,128,244,235,120,49,57,155,76,107,75,89,76,39,234,1,6,0,72,167,147,243,73,114,
+207,163,225,224,65,242,190,231,72,126,139,76,187,190,32,241,97,81,229,19,101,87,76,102,159,31,22,223,99,241,
+181,253,27,34,197,119,191,237,109,211,95,214,237,93,70,157,40,35,239,134,170,61,124,223,247,146,248,65,104,30,
+150,136,141,254,73,9,177,29,47,87,218,177,136,88,161,83,242,232,0,253,38,74,58,138,145,20,26,28,158,106,
+29,132,12,94,111,11,83,67,212,74,223,243,176,102,84,131,252,230,113,254,223,42,86,91,155,52,96,191,162,184,
+148,156,148,126,177,165,106,212,42,168,107,110,180,153,111,158,32,141,178,9,154,154,87,67,32,220,160,53,84,208,
+74,248,38,186,114,114,8,241,98,135,39,52,98,17,147,46,147,162,75,220,194,20,217,22,241,235,167,169,133,37,
+154,147,6,171,184,208,251,89,232,93,203,101,65,244,112,163,163,171,160,48,179,235,98,215,160,122,175,119,129,138,
+192,99,19,155,191,36,58,65,237,31,143,201,209,13,244,55,135,202,120,235,196,246,58,118,195,39,38,127,179,18,
+226,77,146,45,46,143,105,36,23,199,214,164,183,186,133,56,23,72,108,162,115,108,128,9,168,146,27,168,241,75,
+10,199,138,61,32,44,134,9,137,45,208,205,183,128,122,222,123,97,71,208,32,190,7,6,54,170,5,225,49,102,
+46,135,215,222,38,142,189,149,94,95,29,84,134,121,57,52,7,66,230,189,186,86,40,60,163,46,236,247,250,152,
+238,10,204,44,27,240,220,73,72,77,189,199,227,136,228,166,73,130,137,182,200,97,198,96,160,145,155,131,119,127,
+41,22,90,235,102,168,185,167,82,111,204,172,71,71,19,140,90,31,118,41,81,207,64,107,173,73,155,27,124,179,
+173,5,91,192,87,136,166,59,128,96,33,22,5,27,35,50,61,191,83,225,157,94,150,23,128,110,226,51,153,50,
+114,114,176,20,14,180,240,77,180,2,152,66,239,137,248,21,123,173,111,72,98,55,170,96,21,217,251,144,90,179,
+124,46,114,4,32,161,22,143,243,156,228,99,224,186,100,233,127,95,72,173,109,61,164,151,101,37,107,220,109,192,
+27,63,227,34,92,133,42,194,18,146,64,196,240,209,215,167,250,55,142,54,230,186,66,73,218,157,163,111,118,18,
+62,248,218,232,47,24,139,198,143,26,0,63,216,120,173,104,236,139,112,199,78,170,206,227,195,33,131,159,215,84,
+221,39,122,195,240,82,169,90,56,87,147,88,63,120,88,99,38,103,185,207,60,25,160,187,42,118,199,159,170,226,
+224,87,183,237,113,59,164,246,38,220,224,214,40,70,175,44,159,33,105,248,234,106,185,188,181,109,13,169,127,140,
+129,31,27,110,252,226,48,238,236,47,88,172,26,38,16,24,174,147,214,65,56,223,248,83,184,130,181,35,44,137,
+135,109,159,21,208,117,7,209,178,215,173,28,59,226,76,16,122,46,59,111,249,214,226,253,6,239,227,80,217,43,
+154,227,164,226,211,16,55,56,138,131,164,251,116,12,30,148,158,142,201,144,142,41,144,121,192,30,39,121,190,87,
+26,5,156,75,251,194,33,228,40,141,74,241,38,191,38,137,92,188,203,162,235,153,149,94,206,214,248,32,27,43,
+50,206,174,11,127,1,134,216,130,47,190,51,17,187,62,34,57,109,184,225,174,217,43,163,203,21,83,125,176,113,
+86,83,168,207,203,221,29,33,19,11,158,9,179,69,147,172,168,183,151,218,236,3,208,21,137,10,236,235,175,16,
+30,204,11,116,86,208,2,79,98,172,232,10,200,233,100,171,47,213,70,111,103,151,129,33,184,137,159,84,104,184,
+92,195,45,125,163,140,170,227,135,149,90,163,168,50,196,94,206,244,6,92,238,40,40,55,165,195,89,143,85,93,
+199,222,10,47,14,117,19,63,164,76,175,0,23,146,125,36,159,17,57,73,243,203,169,190,64,111,91,23,206,177,
+19,157,112,27,62,103,237,49,191,85,124,30,110,167,27,100,187,29,60,203,7,214,82,26,222,173,114,107,227,153,
+65,150,139,191,65,238,91,173,63,183,174,153,62,21,123,76,157,62,58,177,48,194,46,27,77,192,241,158,107,102,
+97,101,15,219,37,208,170,15,195,196,53,114,247,18,149,183,42,12,42,131,101,132,224,26,149,197,201,202,127,123,
+234,108,136,11,195,3,201,16,47,217,230,20,244,39,97,36,60,79,245,154,105,244,245,49,177,239,30,174,220,215,
+35,180,235,37,152,125,46,131,59,161,173,108,81,170,239,199,86,109,192,86,109,220,175,212,48,231,149,170,244,132,
+63,45,104,58,43,160,11,180,168,233,20,63,121,97,83,69,203,94,116,163,18,124,18,13,27,237,117,0,75,214,
+6,33,225,61,233,153,86,159,16,86,6,20,220,16,10,222,71,180,188,241,189,101,244,242,172,98,177,55,47,50,
+24,119,221,123,84,205,215,19,88,193,201,28,190,195,51,199,222,187,134,215,12,150,81,84,80,237,35,202,228,248,
+191,20,36,201,136,255,246,216,22,110,50,210,214,199,253,22,172,132,13,50,232,147,247,246,165,38,150,106,156,160,
+126,46,246,30,31,181,235,124,105,160,251,180,47,160,78,107,162,235,194,85,238,122,58,97,239,132,216,151,119,80,
+36,217,249,112,215,169,11,186,154,113,161,96,18,234,210,128,75,180,103,237,223,76,93,97,62,111,30,242,235,30,
+43,227,95,184,205,221,171,139,129,11,111,139,221,145,211,95,65,172,47,222,202,219,186,152,78,201,178,147,59,42,
+238,187,36,213,83,52,62,64,52,191,39,52,4,231,229,222,222,201,92,247,247,140,107,72,209,152,230,20,132,144,
+100,79,1,131,165,103,143,207,213,199,119,216,191,74,85,146,1,116,95,151,57,219,191,173,207,232,160,17,14,149,
+41,252,253,159,245,125,192,17,185,71,84,195,154,234,97,204,192,47,106,65,84,160,180,210,230,101,108,2,255,197,
+40,52,21,66,23,168,232,158,14,150,248,102,18,12,180,160,206,149,249,141,124,153,27,199,151,185,189,151,47,51,
+198,57,57,190,161,103,129,177,148,91,68,207,158,151,211,231,195,152,99,250,101,118,203,36,2,142,142,101,236,164,
+211,168,88,208,23,50,107,226,233,36,158,116,247,179,69,120,170,71,121,35,200,22,249,31,115,68,156,13,13,207,
+5,217,159,193,226,163,248,26,217,1,190,6,202,86,143,242,53,248,84,102,53,174,165,78,233,67,152,228,48,243,
+45,113,50,182,211,233,192,40,7,208,113,64,75,13,86,112,139,116,211,14,208,168,190,60,91,157,3,29,81,203,
+163,246,185,201,0,247,23,209,241,159,226,164,30,33,248,160,72,172,110,160,232,18,139,14,57,64,73,58,82,4,
+178,130,94,4,145,60,236,116,255,194,95,32,111,96,212,72,215,57,226,232,190,41,4,50,120,132,39,160,42,89,
+7,111,84,32,106,71,239,251,27,181,85,151,120,217,63,200,43,202,84,163,138,251,68,125,61,149,215,159,94,111,
+92,137,17,215,221,149,204,27,33,97,58,34,101,216,72,27,92,93,28,24,190,205,0,245,227,45,212,77,8,86,
+21,230,64,185,239,41,234,231,3,161,225,239,34,21,164,117,221,215,76,98,108,47,47,209,60,19,4,127,51,149,
+65,94,89,38,191,145,106,184,199,114,41,17,13,95,143,18,13,55,131,147,191,83,183,195,152,78,109,138,45,144,
+3,216,129,170,42,218,124,147,236,50,54,164,137,113,121,91,4,11,198,19,200,223,243,253,118,147,245,28,227,234,
+83,213,192,63,123,197,62,161,11,207,147,239,195,233,146,227,5,111,218,42,118,77,154,85,77,148,122,135,164,77,
+94,98,104,21,210,80,45,207,167,97,104,171,137,69,245,33,214,79,159,27,248,68,241,186,163,19,124,118,244,7,
+193,181,186,126,104,212,7,245,225,33,222,181,15,228,159,185,2,121,217,47,0,90,84,232,44,85,173,96,227,195,
+231,87,106,173,150,200,149,220,68,63,217,216,27,252,156,218,248,121,9,140,200,217,5,156,38,48,104,184,111,221,
+224,87,165,103,209,213,148,34,107,248,188,156,98,172,187,46,17,145,253,83,194,207,241,63,39,141,26,115,50,205,
+239,74,133,97,98,108,220,72,10,238,25,251,169,238,162,205,24,77,150,254,77,80,218,5,169,182,237,104,60,247,
+106,36,238,103,142,235,27,223,176,164,201,112,175,143,9,116,169,125,254,224,1,229,230,96,47,160,12,62,243,43,
+93,232,167,211,146,141,68,254,26,149,40,190,238,248,19,239,237,187,22,29,143,195,183,173,121,165,51,40,9,47,
+76,37,114,7,1,101,177,113,53,58,28,172,111,168,118,106,188,25,53,223,58,57,117,136,106,230,119,190,174,90,
+218,182,225,73,231,162,237,171,68,213,156,99,246,223,39,49,21,249,44,175,193,189,253,202,212,166,204,204,225,114,
+153,204,22,247,26,67,3,9,120,236,58,39,248,223,43,163,103,223,11,218,232,4,44,166,29,50,167,17,244,133,
+202,184,207,127,200,27,94,26,230,196,34,97,228,57,120,135,237,108,148,177,224,126,210,5,189,63,49,196,191,29,
+25,248,188,21,47,105,136,80,123,212,91,5,115,238,119,9,215,149,180,170,55,43,137,153,181,163,116,141,239,171,
+218,121,77,176,164,68,154,236,30,49,213,160,164,246,105,64,172,81,60,21,9,214,179,78,84,113,164,112,165,149,
+1,88,73,73,151,200,15,143,125,220,123,167,246,49,201,225,168,147,222,213,251,54,29,0,192,182,133,237,136,250,
+201,168,233,46,158,130,160,153,31,169,26,105,226,68,237,250,83,179,86,126,214,86,12,250,163,32,164,28,14,90,
+58,28,180,245,56,104,227,113,208,85,167,1,177,175,212,90,21,136,8,221,128,112,24,75,117,1,97,30,24,70,
+108,149,120,6,245,163,187,84,23,60,228,247,250,182,242,35,21,52,135,130,65,92,135,146,239,31,22,152,251,3,
+96,236,217,117,252,200,143,128,129,147,33,208,78,196,219,138,30,204,230,61,92,181,121,248,190,143,168,174,32,162,
+57,110,49,175,157,16,207,136,226,242,251,56,240,253,236,195,195,145,137,103,24,144,211,63,68,171,97,32,195,74,
+161,202,12,71,54,46,104,124,162,42,65,103,95,200,69,29,226,83,49,133,227,112,141,81,99,59,207,19,62,72,
+209,120,202,131,191,12,129,8,186,230,184,135,53,137,18,72,65,229,221,155,117,240,250,111,172,208,184,56,73,250,
+147,221,239,140,172,227,97,245,232,251,223,118,183,168,229,94,79,117,45,20,63,51,93,239,107,245,168,181,142,82,
+50,29,138,55,87,92,74,4,202,21,70,182,213,6,226,236,219,30,70,46,53,16,198,153,155,20,203,179,218,234,
+37,15,71,46,181,218,248,104,185,206,234,234,163,238,52,151,7,238,52,87,72,102,140,223,105,46,45,153,204,186,
+125,3,108,251,158,206,129,247,112,6,188,39,91,26,239,227,155,41,103,236,3,211,123,85,197,156,215,96,222,105,
+137,185,221,60,95,31,42,131,91,178,61,123,127,174,110,209,148,194,122,42,247,28,16,147,43,25,241,179,125,211,
+120,134,214,75,147,27,124,204,224,207,233,245,0,147,95,43,49,115,128,120,196,244,38,219,110,126,1,116,249,173,
+191,231,92,222,251,2,250,94,125,24,123,254,84,48,21,215,99,247,154,15,234,189,186,189,243,94,115,169,96,65,
+227,110,128,50,238,97,117,122,214,5,217,51,165,201,182,182,142,205,168,173,227,214,239,133,6,56,46,158,189,121,
+100,175,123,21,188,41,220,185,37,233,209,193,64,89,111,121,47,42,167,218,63,14,8,129,230,178,27,221,141,119,
+51,7,8,113,10,46,137,239,88,27,47,190,127,24,249,118,96,75,153,56,249,141,146,45,165,216,200,94,157,219,
+178,55,26,214,234,6,175,221,70,32,11,85,250,237,93,84,184,59,7,66,42,13,217,48,245,138,241,85,215,237,
+31,236,109,240,57,102,123,38,187,17,76,8,40,126,73,56,130,252,210,232,239,24,93,229,5,165,33,127,185,79,
+82,53,49,16,124,186,28,210,80,13,185,6,165,186,16,141,9,130,202,25,69,176,205,59,177,33,33,234,221,14,
+27,46,116,122,120,103,96,75,5,203,234,145,215,111,188,251,210,102,195,171,175,164,192,48,91,152,42,82,152,63,
+38,133,211,79,123,177,177,176,108,44,9,36,57,183,158,48,29,183,234,235,225,255,94,62,221,188,79,34,50,150,
+193,190,85,182,111,223,186,8,225,186,118,252,232,246,189,27,146,205,212,165,187,169,98,156,169,233,40,65,86,202,
+233,24,164,133,199,116,63,134,207,163,67,84,58,158,159,215,84,14,169,63,24,206,221,164,143,175,250,48,177,114,
+207,125,0,142,243,211,174,43,12,49,52,150,213,246,221,186,220,182,104,113,250,183,179,52,210,58,19,12,141,100,
+215,163,43,240,89,66,158,169,200,155,249,205,220,15,121,118,224,163,9,31,44,248,41,14,14,8,133,67,5,67,
+225,48,154,40,207,65,177,48,180,199,74,97,122,30,121,41,202,82,226,201,228,79,39,191,155,4,178,250,100,112,
+132,253,225,207,39,170,182,39,214,228,244,4,179,114,29,144,211,153,112,132,164,122,210,217,89,181,62,85,170,26,
+38,118,196,191,138,239,128,116,197,50,76,195,154,36,151,39,109,54,38,107,95,211,67,255,105,96,227,20,230,29,
+202,17,88,196,8,97,8,153,26,22,128,69,210,123,74,44,206,228,95,203,200,215,251,133,110,135,16,195,165,124,
+173,196,201,178,110,70,77,215,65,85,182,89,135,165,221,190,240,21,95,165,27,239,212,209,217,106,200,135,136,241,
+68,94,46,131,98,108,227,145,61,106,68,39,165,90,229,69,97,219,174,247,28,172,54,80,252,189,241,169,193,123,
+143,42,220,171,182,143,167,144,146,67,81,246,48,77,142,242,209,35,215,46,45,122,175,119,40,135,60,22,130,47,
+156,2,85,99,152,23,102,120,231,181,213,59,128,190,33,41,237,238,16,46,151,243,173,9,245,124,20,7,78,209,
+140,122,73,122,156,122,140,240,158,86,38,9,188,4,228,232,204,4,118,89,203,106,80,115,175,249,208,146,185,253,
+246,184,33,37,182,88,161,243,225,169,54,113,210,194,95,213,118,93,120,15,124,109,254,93,239,129,247,191,70,40,
+198,55,184,188,248,149,144,235,145,11,142,244,190,238,239,84,17,23,78,255,83,246,172,94,116,250,54,35,143,213,
+117,60,31,218,218,77,247,204,236,194,235,10,228,142,73,247,6,109,198,120,232,87,165,119,141,227,187,128,113,7,
+140,111,80,18,189,15,144,73,190,163,74,4,85,201,206,185,117,211,183,20,113,143,69,142,121,239,22,141,238,135,
+80,76,3,212,198,50,9,205,200,199,206,156,135,120,45,139,184,200,49,138,184,116,106,208,140,190,145,139,30,60,
+89,103,0,153,227,55,216,6,137,165,127,253,137,40,72,17,21,97,201,179,145,135,163,245,71,93,178,86,7,46,
+89,176,140,203,3,151,44,148,149,117,15,71,27,157,218,143,224,193,251,74,241,228,37,151,93,255,42,126,161,191,
+67,225,158,197,213,97,123,95,55,247,128,45,104,233,195,69,218,91,223,38,74,244,189,70,154,123,248,32,101,102,
+167,225,29,247,90,155,249,53,95,228,174,221,76,227,109,237,26,111,107,131,146,215,177,122,166,111,22,31,146,93,
+167,222,232,111,162,91,16,229,140,213,115,253,12,30,191,244,200,235,213,45,196,43,40,244,163,126,6,57,81,178,
+247,205,71,61,97,21,123,114,89,169,186,85,69,156,96,131,80,225,252,153,124,221,122,238,95,183,126,140,161,5,
+5,137,104,214,254,26,135,142,61,152,189,135,63,79,47,212,37,108,200,103,206,20,207,45,100,131,13,203,150,84,
+96,180,176,170,152,238,47,140,171,123,47,140,215,135,46,140,92,114,120,93,188,86,207,84,67,188,172,195,87,198,
+149,106,212,58,254,248,151,110,105,32,85,5,127,81,160,152,239,63,135,36,121,195,37,240,138,100,245,138,6,158,
+122,202,240,234,117,118,242,113,207,225,248,244,87,67,246,32,115,249,113,229,66,254,64,4,11,7,181,149,66,158,
+231,125,18,66,115,63,3,60,165,159,217,211,255,59,194,143,146,136,13,156,30,56,63,131,152,109,204,135,141,109,
+167,235,94,91,138,182,200,113,31,189,190,135,154,181,217,14,62,210,57,12,139,52,172,71,4,64,191,98,189,191,
+65,64,231,144,20,78,239,29,237,118,232,148,163,239,86,130,175,160,184,230,185,179,86,200,89,3,50,229,203,50,
+62,184,231,193,152,41,73,159,102,164,20,185,150,190,71,86,210,247,200,178,211,245,158,239,145,21,61,180,150,109,
+224,234,190,106,97,55,115,189,89,12,23,113,101,22,101,2,177,173,42,212,8,18,201,98,204,20,171,19,85,34,
+152,168,229,162,242,245,65,235,189,250,214,49,240,49,166,167,80,227,201,29,53,174,99,155,45,86,232,239,108,214,
+36,80,225,172,233,122,238,143,26,62,250,165,198,30,156,234,249,192,44,105,171,110,131,12,43,126,144,234,80,227,
+220,133,236,110,112,226,172,206,207,13,206,158,85,241,185,197,88,67,177,183,24,107,48,214,42,249,149,177,215,101,
+148,21,106,52,206,41,212,143,176,94,160,234,169,102,80,231,62,198,202,49,140,21,97,248,214,166,27,151,142,205,
+216,112,234,109,122,245,95,191,201,80,83,213,177,67,133,252,55,61,27,126,252,211,224,255,54,135,231,184,254,237,
+60,158,143,23,114,9,166,216,237,160,162,88,125,140,228,139,44,115,216,205,64,192,78,56,110,193,165,247,59,199,
+88,246,243,12,235,94,65,25,230,60,67,24,206,187,88,85,66,97,218,62,155,212,33,166,228,183,161,32,131,184,
+168,30,193,149,243,225,126,66,114,138,101,83,29,85,248,52,211,30,239,113,17,88,110,124,190,183,198,213,44,125,
+24,200,215,125,216,24,22,152,165,255,10,231,126,239,113,248,32,255,126,184,158,236,166,128,236,113,221,124,102,213,
+112,150,240,125,203,223,91,180,189,197,244,56,221,253,225,128,155,29,255,233,225,79,115,171,203,180,85,87,188,23,
+47,53,92,225,237,67,19,226,11,158,168,48,30,75,104,93,1,155,232,138,56,235,87,241,198,115,214,171,171,13,
+76,133,173,31,189,23,95,186,204,6,51,3,69,118,21,24,189,23,64,145,93,157,51,11,127,3,52,196,102,122,
+176,22,117,173,235,253,123,39,146,151,107,138,206,1,195,149,25,233,55,218,241,122,196,104,1,29,26,2,94,236,
+124,163,223,147,156,79,255,61,3,34,174,237,237,64,178,104,48,250,70,191,215,91,47,50,243,1,57,253,43,117,
+155,44,123,124,249,147,30,207,254,250,0,175,255,189,191,52,220,67,63,92,169,139,17,18,172,155,143,208,95,23,
+234,74,125,32,157,163,177,133,186,199,225,193,0,128,60,131,222,51,238,104,226,188,235,79,54,8,178,115,204,110,
+59,173,213,249,125,220,248,10,50,148,211,105,23,171,178,235,175,108,95,23,250,62,5,0,150,11,184,71,24,234,
+56,197,170,209,24,8,250,141,125,102,229,146,54,85,145,214,136,132,38,243,103,82,52,233,95,229,216,157,116,255,
+99,121,37,15,35,31,205,182,67,110,74,143,125,38,225,236,164,195,145,253,223,28,176,255,155,3,134,51,42,45,
+91,112,69,130,200,56,203,131,29,214,243,233,40,79,12,57,93,202,145,239,181,3,104,100,234,166,197,43,22,149,
+167,141,134,1,200,178,204,155,77,145,222,226,29,64,138,208,7,209,123,226,16,195,38,196,61,99,231,148,32,110,
+80,84,2,116,224,181,189,41,61,221,86,152,93,247,166,180,123,58,135,123,12,124,135,221,204,220,233,147,223,192,
+153,246,77,244,72,195,223,66,206,121,45,142,251,140,87,27,105,251,4,200,53,39,172,60,153,154,125,113,103,111,
+78,62,254,24,74,14,239,200,254,190,220,240,183,37,37,189,182,159,108,29,55,117,224,180,169,22,57,233,214,167,
+183,87,242,172,255,53,190,91,61,224,187,121,53,192,221,5,250,110,71,184,184,88,193,155,238,43,12,56,57,15,
+225,255,195,31,149,117,55,191,139,39,151,34,37,58,206,125,59,81,205,199,203,105,143,156,143,245,65,2,43,149,
+244,155,231,57,21,64,225,20,68,225,20,129,194,201,116,11,18,121,247,243,230,10,149,141,73,36,175,152,255,4,
+43,5,127,172,139,246,192,79,98,163,199,208,0,50,239,210,69,237,200,190,100,117,124,163,182,20,115,235,99,110,
+213,6,169,151,37,80,47,91,187,119,33,146,126,21,178,157,18,123,170,47,61,219,105,27,251,69,88,143,46,66,
+166,10,181,33,218,163,123,67,199,44,226,7,212,49,130,208,191,194,92,24,156,113,130,213,96,108,110,60,198,48,
+102,135,152,62,177,39,41,241,12,222,28,62,1,239,65,102,1,217,124,22,48,193,107,64,54,159,217,145,53,25,
+226,70,24,219,103,114,108,161,111,167,116,234,32,14,195,28,162,19,57,206,126,154,17,54,66,167,18,126,152,191,
+85,184,120,136,216,81,201,129,159,55,166,19,53,130,194,81,215,129,209,248,199,75,60,119,243,15,105,253,224,58,
+27,152,196,221,93,92,144,161,187,139,11,107,237,11,212,12,63,243,71,113,242,62,87,159,146,224,183,136,251,58,
+87,207,249,237,84,196,22,70,225,124,137,152,215,70,125,231,136,51,17,253,44,87,223,229,50,223,155,82,189,70,
+232,146,81,185,122,67,203,34,35,63,203,187,120,30,60,26,91,107,128,117,117,253,0,173,98,126,94,215,176,89,
+39,160,199,216,60,184,50,237,186,90,62,128,175,178,106,31,228,87,27,130,45,228,238,63,32,79,83,64,142,166,
+128,176,30,32,193,74,110,34,17,244,31,64,23,54,208,32,22,131,9,249,0,107,188,60,158,196,204,95,48,101,
+159,169,128,77,75,223,76,104,145,161,179,139,212,248,165,165,62,10,41,97,25,205,153,247,227,211,37,155,111,233,
+71,47,243,213,106,44,158,118,200,183,163,73,0,232,54,161,31,13,241,30,138,181,155,206,40,31,122,80,55,101,
+48,128,168,242,216,66,207,251,12,176,60,206,86,98,74,193,199,187,48,210,255,233,164,76,9,203,229,64,161,44,
+0,52,209,154,213,45,252,189,237,146,95,43,202,216,249,146,95,103,67,111,162,222,35,181,191,194,11,199,212,67,
+23,202,24,178,46,161,205,158,75,232,200,90,41,241,15,107,157,54,32,214,28,251,114,236,23,136,203,121,247,64,
+149,38,199,208,21,49,236,129,49,30,85,170,84,133,116,35,251,108,104,45,14,254,122,32,109,108,107,149,98,126,
+37,90,36,202,161,127,99,198,33,200,82,55,185,95,225,167,23,248,198,243,26,197,84,64,239,172,26,88,249,39,
+53,113,182,145,101,181,137,23,89,1,92,67,58,242,201,182,195,208,42,181,80,6,38,191,70,154,141,63,100,56,
+203,196,167,131,214,220,184,160,209,16,15,16,142,213,10,7,14,133,53,16,59,195,215,36,23,152,174,3,33,84,
+37,43,100,141,174,243,100,9,188,74,196,78,164,168,203,144,199,5,226,46,100,63,193,188,149,231,167,139,9,254,
+172,228,9,150,199,248,189,160,97,189,4,5,43,154,246,41,211,43,252,165,79,10,180,163,203,245,49,108,100,118,
+181,214,157,70,243,186,138,70,65,67,232,52,172,50,197,181,170,150,106,132,91,189,2,109,42,189,236,123,56,94,
+195,131,205,124,195,32,83,70,27,149,169,109,220,137,33,189,25,154,209,100,59,16,232,70,243,8,173,63,40,35,
+99,111,57,214,221,166,252,54,237,19,54,193,154,10,48,84,103,13,104,216,37,100,229,65,198,223,66,252,45,196,
+247,94,43,154,127,212,204,144,222,84,215,176,52,143,227,169,15,213,16,146,224,254,75,190,111,2,240,236,220,85,
+247,55,68,97,185,96,5,2,27,24,88,127,223,1,26,131,119,113,96,15,208,98,26,168,192,143,193,90,84,219,
+225,91,57,195,26,32,136,22,136,152,18,178,179,45,138,157,115,79,92,247,221,37,167,124,17,43,186,184,35,239,
+79,141,0,155,161,125,58,236,166,79,173,184,93,94,127,113,29,201,2,31,103,221,49,85,6,215,250,38,58,59,
+112,147,39,235,143,59,166,179,58,253,30,171,6,60,215,18,158,131,129,192,49,5,138,55,43,244,65,246,219,70,
+196,115,234,167,172,234,141,239,187,76,108,11,86,12,241,102,179,107,253,134,252,85,90,200,63,244,40,27,166,163,
+136,200,34,163,91,210,165,206,246,150,163,177,151,9,16,129,116,246,240,189,159,59,66,20,150,252,36,2,54,178,
+121,143,0,26,182,119,66,195,176,170,43,141,108,249,109,12,12,196,116,17,193,120,252,52,101,253,105,90,243,52,
+173,58,244,116,115,21,39,87,136,53,17,73,242,236,222,87,108,127,118,209,183,83,152,221,31,114,57,187,31,7,
+221,11,163,25,93,31,149,11,15,126,77,156,244,150,42,57,59,15,205,92,143,24,212,188,48,216,74,172,112,57,
+113,251,218,167,161,84,215,108,127,14,78,210,159,104,105,38,9,124,254,108,63,217,188,232,17,227,8,62,74,121,
+85,145,215,130,150,214,155,179,26,129,245,183,76,147,10,128,0,8,69,53,188,47,163,2,237,160,67,178,129,228,
+22,143,160,172,133,97,23,139,179,243,164,234,144,54,120,158,105,162,130,155,196,34,215,59,198,201,67,132,87,141,
+27,100,146,139,42,23,132,109,26,85,65,185,228,7,247,141,222,220,99,149,10,180,83,59,103,146,209,125,199,130,
+231,113,22,158,1,149,233,26,142,67,230,249,175,117,97,175,90,217,249,124,13,35,90,19,22,71,213,239,254,140,
+173,251,51,86,112,113,62,71,58,156,154,148,150,218,229,251,184,241,223,218,133,252,216,73,192,93,230,198,254,212,
+219,165,79,237,128,100,7,85,177,207,101,75,99,203,247,171,165,177,105,107,72,170,8,26,83,89,92,15,134,94,
+192,220,140,35,173,44,108,171,154,121,63,31,61,108,46,39,198,218,41,188,170,152,230,55,215,225,231,72,76,34,
+213,39,128,144,179,242,254,219,97,37,9,130,159,47,144,136,194,29,149,190,189,167,244,237,93,165,187,142,81,220,
+23,176,173,217,148,43,25,105,85,108,206,85,57,235,173,226,144,90,73,66,26,25,124,112,245,132,74,35,163,159,
+26,56,156,145,55,33,169,231,247,205,193,236,95,84,158,154,160,146,214,190,22,74,89,92,86,55,56,133,195,186,
+150,131,166,217,82,56,142,222,111,156,6,72,142,50,49,170,34,163,164,165,155,254,134,165,120,161,198,138,63,157,
+169,171,25,119,35,113,121,102,46,71,39,218,254,86,82,71,206,114,21,155,202,85,78,93,209,232,19,85,234,40,
+71,230,87,236,192,213,60,65,57,32,19,55,58,63,51,64,192,109,152,147,146,84,193,44,19,9,89,37,181,162,
+95,43,46,156,164,26,8,78,228,143,49,168,219,78,26,5,147,147,52,10,106,129,10,132,81,189,102,104,181,208,
+142,193,143,74,113,27,128,104,167,131,134,186,216,179,196,195,128,95,245,6,188,235,104,128,54,104,30,0,129,238,
+18,185,239,37,245,168,145,21,147,104,160,125,128,7,45,38,88,109,150,237,106,162,38,152,92,243,180,1,154,137,
+0,214,29,254,232,157,149,19,56,81,192,154,205,204,18,62,120,48,39,214,194,205,9,246,216,62,14,78,167,170,
+230,17,78,117,213,237,143,227,237,224,250,70,227,82,187,15,159,86,55,32,14,100,121,238,165,90,219,224,151,60,
+103,157,182,106,7,126,105,217,56,89,62,180,75,182,75,97,85,43,166,112,118,200,83,124,99,77,240,232,20,161,
+88,101,64,240,179,117,33,188,220,100,136,180,197,20,61,202,184,239,243,180,103,102,57,181,122,125,122,189,88,63,
+44,147,2,223,60,210,15,105,94,160,84,26,117,89,65,126,11,208,77,156,248,236,101,136,198,146,205,160,164,29,
+157,16,201,247,147,244,121,111,177,9,214,149,209,176,223,90,183,95,65,73,55,163,125,233,198,24,19,109,91,98,
+166,21,98,62,139,63,108,108,19,98,217,46,116,172,42,31,135,40,134,51,214,62,146,49,141,117,199,255,190,97,
+247,253,170,224,239,219,137,131,209,48,201,70,97,147,192,37,7,7,128,137,247,59,80,197,10,219,196,248,79,169,
+202,164,113,73,69,236,190,106,255,149,198,42,168,166,218,158,248,48,180,255,1,95,206,224,34,28,234,111,226,80,
+157,220,127,213,88,221,157,96,35,8,170,106,40,149,69,136,161,133,63,241,84,196,149,16,7,127,4,18,250,75,
+197,110,28,80,56,65,135,172,24,84,173,149,88,200,73,144,65,38,98,88,181,244,131,201,118,162,69,6,142,81,
+45,127,96,38,154,194,144,135,35,84,107,127,69,151,94,239,113,26,44,30,64,44,197,162,193,57,86,193,244,40,
+161,131,95,73,253,198,144,52,27,90,200,6,85,169,153,182,65,199,170,95,161,75,91,222,55,192,184,178,187,158,
+197,135,78,1,23,81,230,208,63,27,86,70,110,162,138,183,66,82,217,221,17,43,99,75,217,204,143,86,22,129,
+40,108,126,202,205,119,228,95,26,251,74,62,106,96,190,107,37,163,34,97,82,208,55,126,162,90,43,128,65,59,
+115,6,11,93,171,156,247,131,216,0,197,72,9,187,35,125,17,220,24,114,39,100,58,61,210,48,127,215,72,2,
+210,215,58,152,101,191,214,72,235,67,66,127,216,187,38,189,194,11,99,133,238,112,225,182,152,216,136,53,71,72,
+159,2,159,202,93,223,95,38,159,199,68,130,196,241,3,64,184,156,17,132,158,248,179,3,131,83,221,168,166,3,
+62,26,76,104,196,251,28,120,107,24,114,248,193,68,60,37,248,233,199,26,58,245,114,128,175,219,209,110,149,145,
+96,50,236,176,106,0,15,104,15,153,11,124,82,216,170,225,172,240,52,128,167,179,107,32,23,208,146,146,24,16,
+132,20,49,223,186,88,249,99,164,140,242,197,89,111,33,209,193,95,127,153,228,254,188,49,163,124,8,127,146,40,
+114,250,61,114,158,40,36,113,7,103,138,42,248,12,41,220,51,44,163,121,224,248,29,95,123,76,143,161,181,130,
+89,147,39,136,106,29,160,218,213,95,241,234,47,59,253,218,218,201,75,85,9,57,254,169,87,120,251,231,78,172,
+53,212,189,84,133,199,241,168,69,76,196,71,234,15,13,56,193,96,148,13,143,18,108,103,118,129,221,109,196,141,
+146,113,148,113,248,168,245,72,165,157,150,1,11,153,105,163,114,127,122,229,254,80,19,172,204,102,220,241,5,1,
+4,78,45,58,18,87,183,100,86,93,208,40,169,164,81,30,20,254,56,46,207,210,128,86,24,159,236,145,25,167,
+29,204,197,248,65,13,234,89,136,195,228,100,7,6,36,172,203,195,53,185,126,108,104,246,10,30,207,252,178,141,
+50,107,77,48,38,87,35,46,32,230,122,1,211,87,168,198,98,235,90,25,137,82,26,22,82,227,212,101,156,96,
+102,198,233,211,236,216,246,31,74,173,32,77,113,229,186,86,46,101,170,87,170,214,5,79,58,113,61,69,159,215,
+131,62,211,106,12,186,92,29,238,114,165,26,58,127,150,202,244,144,90,227,68,233,40,153,187,92,217,99,42,244,
+121,169,86,161,199,85,175,199,149,46,236,184,187,14,248,61,26,139,222,234,186,251,242,24,111,174,19,120,180,175,
+182,168,179,128,14,0,24,63,224,43,221,134,63,119,227,216,64,89,92,209,117,49,189,22,64,163,59,40,0,212,
+31,159,172,8,38,6,61,40,218,47,220,191,177,106,253,144,117,248,4,154,246,20,82,28,57,175,253,39,80,187,
+22,69,180,238,210,209,122,224,65,204,127,1,93,55,117,163,221,23,180,230,160,221,191,203,156,237,126,133,190,146,
+240,180,65,7,133,252,213,117,112,121,231,158,57,191,97,157,178,158,173,120,12,1,115,114,190,5,255,250,203,86,
+75,134,125,205,145,189,109,113,170,115,93,102,212,41,212,104,125,107,110,107,227,196,70,196,12,24,255,41,71,111,
+252,103,24,182,225,143,78,49,2,227,141,204,126,168,250,108,182,70,23,109,148,251,215,124,187,188,110,159,247,4,
+49,17,180,8,70,7,226,152,6,226,237,126,179,178,150,64,212,242,224,172,253,90,71,203,169,76,203,237,59,255,
+193,101,83,87,112,46,240,251,195,213,241,165,1,108,98,94,81,63,250,111,16,253,180,40,238,28,81,176,70,136,
+53,203,45,204,99,116,165,46,225,86,122,137,53,7,5,130,94,240,152,101,79,200,172,14,168,169,92,77,81,72,
+20,16,140,90,13,31,64,3,46,72,90,37,54,89,98,60,188,55,170,127,67,72,170,16,193,153,107,213,187,245,
+128,243,165,71,235,193,205,167,6,213,128,88,45,71,172,120,197,115,160,134,224,112,32,229,90,207,101,29,228,11,
+71,117,178,84,215,120,65,133,70,111,18,198,91,183,9,161,2,172,76,109,52,92,204,10,71,41,103,228,117,21,
+14,150,52,0,215,86,173,212,38,86,16,89,136,239,140,191,241,24,10,9,64,201,108,99,245,172,129,242,225,78,
+224,18,183,72,128,108,143,175,225,227,22,63,214,54,99,255,150,192,153,37,39,149,233,138,173,237,60,162,147,45,
+33,58,44,232,162,167,88,47,227,22,74,157,98,253,76,120,194,39,27,149,135,92,157,250,33,74,67,229,4,107,
+78,222,245,10,193,98,222,159,203,75,217,149,88,93,58,34,0,27,196,138,239,33,122,0,40,189,80,193,79,213,
+46,205,254,177,205,107,35,124,124,199,187,174,54,133,73,155,16,41,252,233,195,34,126,254,193,148,45,58,40,68,
+25,61,247,120,203,46,75,199,211,144,151,103,62,228,153,125,250,35,209,135,240,208,124,202,10,56,249,213,246,10,
+215,119,207,165,138,145,244,177,65,178,134,201,246,82,151,24,226,173,189,179,51,106,220,36,139,66,205,130,2,171,
+162,66,94,204,163,38,78,144,201,149,55,207,218,150,222,53,197,8,79,58,175,214,2,136,14,19,156,117,175,23,
+25,75,96,140,206,155,239,45,112,150,133,67,240,65,40,154,60,94,78,96,39,163,180,194,94,67,237,190,56,181,
+134,25,239,152,14,207,245,228,19,90,247,95,154,137,250,53,211,112,142,109,179,181,85,160,152,92,85,219,198,44,
+171,235,114,162,40,26,215,130,99,241,147,99,161,243,28,185,221,76,44,203,211,212,6,255,112,52,125,251,20,172,
+79,84,237,227,7,149,251,248,237,102,191,118,0,36,159,25,240,147,143,135,111,17,219,169,55,141,70,229,105,111,
+165,6,191,38,147,64,215,127,185,247,216,222,160,240,163,42,45,171,24,86,178,206,47,1,255,69,206,48,111,172,
+154,97,18,219,238,37,70,116,126,214,230,231,218,105,200,38,59,6,154,146,247,101,163,168,250,32,6,104,28,82,
+86,156,211,56,184,99,176,179,64,137,130,45,62,171,246,95,112,240,95,22,85,246,126,162,136,135,9,96,142,138,
+183,226,27,51,144,100,218,12,162,38,234,13,178,194,194,61,38,69,82,215,247,190,18,142,192,34,71,35,87,49,
+90,160,128,114,101,28,195,7,79,15,247,145,230,50,246,68,52,151,121,132,78,254,31,123,247,162,178,41,155,113,
+216,150,175,160,10,158,23,25,58,191,170,244,107,184,98,110,16,71,125,32,9,100,16,58,10,171,247,163,87,150,
+202,143,71,49,200,87,85,44,92,160,137,220,89,90,126,72,155,99,198,46,119,151,251,101,0,35,191,102,103,214,
+201,35,144,244,246,3,159,58,75,60,110,58,109,197,57,60,243,8,83,19,99,89,62,73,171,172,24,72,146,43,
+200,31,124,32,148,36,102,132,229,67,92,67,113,210,89,97,110,123,49,100,139,226,178,224,155,27,76,186,33,137,
+225,52,39,97,197,216,99,158,240,158,183,167,91,230,38,66,53,228,71,247,235,173,149,36,253,246,178,49,53,58,
+33,175,224,208,176,111,49,56,237,253,203,78,21,215,186,134,251,91,30,165,56,249,102,249,13,190,116,89,47,128,
+53,62,107,66,2,79,176,79,154,67,130,65,2,38,220,145,43,219,86,180,172,50,244,82,74,166,219,242,98,137,
+203,145,144,10,249,101,91,27,90,250,222,203,239,207,255,107,99,145,93,14,163,241,195,252,247,141,197,182,255,202,
+216,238,166,27,186,183,127,134,134,130,252,40,255,81,121,165,134,92,95,231,37,224,203,227,229,224,200,155,163,105,
+136,207,26,216,72,80,54,87,175,76,80,97,192,249,129,81,3,92,108,107,68,200,195,211,18,89,60,112,146,224,
+32,98,113,175,102,120,135,154,236,21,141,27,222,219,97,78,138,86,253,163,138,177,93,126,225,19,85,253,21,170,
+162,138,150,6,165,202,32,160,6,181,242,116,31,174,56,84,246,197,93,75,14,111,242,207,202,168,180,111,238,77,
+159,212,175,244,77,21,69,40,233,32,222,59,129,75,91,228,208,40,209,166,115,67,201,42,123,210,139,182,11,172,
+108,79,17,18,112,165,94,83,223,60,88,165,190,206,66,167,40,82,148,233,130,246,33,84,242,218,100,76,85,168,
+245,32,150,47,234,153,38,39,19,107,252,1,237,111,124,171,22,16,85,123,136,106,98,69,203,130,220,102,177,9,
+16,39,56,239,195,116,42,64,19,37,84,143,74,109,218,139,57,195,21,2,23,66,50,118,239,154,202,155,138,246,
+10,196,180,55,222,24,149,137,0,13,86,42,143,97,62,160,27,66,115,1,229,168,184,195,103,181,170,189,77,48,
+247,245,243,185,31,16,34,236,18,218,109,16,252,153,86,188,147,252,145,61,188,159,2,242,205,160,201,94,30,15,
+121,11,140,190,204,216,207,119,76,104,117,72,137,74,246,31,151,35,56,50,120,154,199,142,72,245,182,162,40,218,
+153,181,152,159,185,99,205,29,165,231,126,3,202,105,42,241,217,230,27,244,199,102,24,230,3,5,81,197,9,237,
+30,17,163,234,112,205,3,232,182,231,46,138,84,14,52,63,193,214,41,30,234,189,38,141,205,13,13,234,6,254,
+160,132,2,31,231,252,171,236,118,124,64,3,129,135,145,131,228,119,187,206,15,30,146,161,119,237,241,39,155,186,
+186,201,137,143,17,2,122,215,225,158,217,165,68,14,39,63,100,208,44,125,253,156,41,11,152,201,23,89,119,134,
+199,232,95,178,121,3,31,218,53,60,78,246,75,104,184,171,77,152,47,168,172,143,9,34,215,141,159,115,223,141,
+156,187,1,95,182,27,223,100,49,182,130,240,137,53,240,89,124,247,61,227,0,86,190,239,246,241,121,225,163,228,
+141,65,64,226,179,50,40,85,28,29,69,180,195,243,230,51,187,193,205,82,190,245,124,69,104,150,179,190,168,34,
+184,10,48,91,1,141,64,101,181,49,229,103,4,213,61,15,87,192,139,121,144,151,86,145,112,63,235,226,69,150,
+252,148,241,46,189,233,43,16,51,96,220,244,20,133,111,101,136,197,251,225,168,85,61,169,96,153,229,19,190,143,
+132,248,142,101,195,157,240,127,112,57,132,15,209,183,168,145,141,37,133,56,26,43,152,157,7,146,203,103,237,214,
+105,99,85,7,252,164,131,129,14,219,113,184,206,187,239,219,184,243,213,245,33,108,208,71,130,39,216,130,65,189,
+27,115,248,77,16,118,102,219,219,140,184,3,105,243,91,127,37,60,49,81,188,160,208,69,91,37,80,13,111,211,
+166,235,110,250,142,217,67,240,53,178,97,220,68,113,171,127,171,244,238,3,251,54,239,187,52,206,81,211,38,239,
+84,9,116,72,157,123,108,143,36,60,30,53,60,130,201,201,100,196,0,222,64,247,218,217,195,211,57,206,128,113,
+146,54,167,65,146,214,95,137,189,140,165,65,217,27,234,89,172,68,164,241,162,173,46,53,158,71,217,147,83,51,
+251,227,63,255,153,61,61,53,167,127,130,149,33,215,188,25,30,194,249,42,207,38,200,139,251,7,142,192,196,157,
+67,166,87,109,104,203,186,202,222,183,60,59,59,125,40,174,231,117,172,30,159,196,214,244,238,174,100,141,41,235,
+153,10,247,232,11,214,90,120,158,191,203,219,38,73,21,84,53,22,223,141,43,222,23,61,40,103,15,234,86,156,
+61,86,160,222,158,91,129,105,85,84,239,210,58,111,215,87,31,181,36,249,35,47,129,122,122,162,196,96,96,248,
+121,28,135,227,14,202,131,159,56,252,121,108,127,254,180,248,91,117,204,107,143,22,88,11,130,117,101,155,4,208,
+144,22,39,104,110,189,93,188,214,173,239,31,22,237,217,99,94,166,89,123,230,86,44,241,159,16,235,87,217,245,
+36,172,117,252,84,35,179,23,232,7,209,239,28,87,215,232,124,214,139,139,149,33,105,185,239,114,189,115,74,29,
+117,147,252,173,234,230,204,123,39,157,142,137,10,202,115,39,222,217,205,169,119,145,12,159,82,23,15,131,100,192,
+34,153,208,114,76,212,59,88,75,147,176,138,158,172,43,40,67,158,18,11,220,90,58,196,20,12,125,91,126,230,
+31,236,57,234,45,86,136,1,172,153,189,154,253,23,5,108,53,52,161,250,105,123,236,107,166,68,82,189,12,137,
+25,6,197,64,236,77,253,121,218,172,65,102,78,132,190,181,57,78,56,138,123,218,41,82,154,145,26,133,10,137,
+25,88,221,254,155,196,31,29,147,238,143,29,150,193,158,163,41,144,215,94,107,16,97,221,135,254,4,193,28,21,
+71,92,125,111,80,135,148,167,231,68,196,208,96,100,99,127,80,98,74,241,145,4,125,66,203,239,239,124,70,210,
+227,241,195,114,122,64,201,119,249,113,88,127,11,88,180,65,161,157,93,7,189,252,197,126,164,104,191,50,153,100,
+204,85,202,234,170,105,158,217,184,210,164,78,137,10,155,248,20,106,93,2,102,167,217,229,111,238,119,253,238,50,
+141,30,255,233,79,234,65,248,115,114,252,159,127,138,39,46,167,239,47,248,46,139,1,18,107,68,192,12,139,199,
+12,82,19,90,67,248,245,159,123,57,17,218,250,25,89,15,247,206,236,50,207,253,133,8,18,14,244,134,45,14,
+94,154,176,141,46,86,60,227,56,47,3,27,132,71,185,125,27,107,126,4,52,21,77,236,195,195,4,246,237,32,
+33,93,225,228,199,118,139,79,220,18,78,56,76,10,62,245,168,13,195,0,215,46,51,206,229,167,33,182,27,233,
+116,211,235,181,141,27,203,232,23,102,212,180,226,96,97,39,195,206,115,119,239,44,35,245,173,254,54,100,30,246,
+15,0,85,90,91,45,132,45,94,229,87,57,176,104,62,33,81,167,6,19,16,156,217,112,222,114,97,240,101,13,
+183,125,21,148,66,107,178,221,164,82,36,226,225,196,84,133,182,198,158,170,167,193,192,12,20,83,5,202,4,62,
+42,99,85,8,43,114,244,100,94,198,54,255,137,197,238,107,181,226,28,75,93,61,61,181,220,107,82,23,135,219,
+49,218,9,137,160,157,216,94,145,136,67,242,87,67,213,103,10,53,37,193,28,79,61,91,170,26,253,116,156,168,
+149,134,188,243,245,147,213,124,61,157,198,62,99,115,182,62,199,63,211,211,115,127,60,249,196,212,214,227,142,152,
+36,157,46,161,211,221,32,27,70,249,41,254,68,138,140,136,9,182,88,83,225,156,95,224,100,19,141,29,171,18,
+195,182,246,71,102,26,181,208,103,180,16,132,177,176,16,175,56,193,117,76,156,66,193,100,191,106,36,47,164,93,
+15,47,202,37,196,196,222,156,45,86,215,183,249,19,236,183,168,211,224,123,230,59,244,151,48,208,207,10,138,62,
+168,161,37,221,111,21,26,165,69,176,222,226,105,227,42,46,186,177,22,66,87,205,122,92,98,84,72,138,230,82,
+70,212,64,123,40,8,102,33,17,175,211,244,192,107,198,132,51,243,117,120,75,13,102,168,144,202,99,95,170,37,
+59,107,49,121,1,3,85,214,179,88,46,61,139,161,228,62,154,34,225,102,114,148,125,81,205,116,74,245,52,15,
+165,220,25,130,194,190,182,19,186,226,17,47,176,184,88,159,195,20,184,70,226,240,53,247,186,78,94,252,197,136,
+254,25,104,151,164,247,155,89,169,140,46,30,9,56,40,30,153,24,1,188,2,208,62,153,199,233,116,10,1,177,
+79,170,105,250,208,216,133,20,116,111,165,80,231,27,196,105,50,24,40,178,116,214,114,160,25,12,244,64,69,98,
+204,165,92,62,191,82,126,17,201,131,206,99,207,139,224,73,207,113,5,140,62,133,5,109,73,232,23,178,225,154,
+206,224,15,160,12,228,222,132,34,222,8,56,95,89,214,238,105,196,74,28,45,88,226,40,193,40,254,94,96,18,
+70,169,239,26,109,215,4,73,23,204,128,18,7,112,205,12,197,115,208,52,155,154,4,127,102,38,32,201,231,77,
+15,73,2,96,10,64,124,212,226,230,60,232,6,178,154,66,255,141,155,71,177,76,85,236,209,139,20,43,173,246,
+118,107,110,81,49,183,32,13,49,181,100,138,12,175,53,61,199,187,53,134,189,219,221,84,195,221,228,207,172,87,
+146,75,43,100,136,212,145,43,151,225,202,208,237,60,34,50,124,33,192,162,152,85,170,158,21,113,130,179,116,2,
+41,209,126,21,167,49,100,120,244,56,201,52,100,31,105,1,17,50,250,255,156,234,230,73,187,200,146,89,166,138,
+39,213,44,5,193,153,167,245,52,141,227,128,30,252,52,212,107,59,229,63,192,143,209,79,133,111,213,119,153,112,
+187,249,232,177,157,113,28,65,243,20,242,179,156,152,247,192,233,184,68,86,25,4,239,171,231,243,210,9,110,156,
+144,46,188,0,224,173,233,217,225,240,116,50,200,131,8,50,249,68,136,184,19,100,176,112,134,123,210,10,166,206,
+61,71,174,141,144,46,68,115,165,136,224,11,12,50,205,233,96,32,250,2,226,144,52,141,23,244,235,79,152,211,
+248,161,65,34,156,37,18,166,206,95,73,232,68,202,115,229,84,47,90,8,238,26,182,11,135,76,148,64,109,132,
+66,5,195,217,160,24,14,51,49,86,15,196,151,198,200,94,225,108,221,247,148,181,45,163,220,15,196,160,190,171,
+223,126,192,108,192,8,237,35,98,2,51,116,76,29,195,92,132,58,215,235,161,84,44,82,254,141,21,62,170,220,
+5,160,230,103,251,148,223,163,138,78,231,210,83,78,230,148,231,215,157,46,8,54,200,197,50,250,81,14,186,105,
+179,70,93,234,116,70,80,147,15,116,0,104,45,183,186,106,201,238,99,26,171,95,35,35,252,10,75,150,165,137,
+17,117,221,0,238,191,0,53,81,189,134,159,125,35,127,55,241,244,106,214,90,173,89,124,227,114,52,255,98,163,
+163,140,197,189,166,25,138,65,192,30,193,172,201,70,127,215,88,93,182,120,190,196,110,82,97,236,214,71,118,101,
+123,176,43,179,203,233,88,87,182,208,21,150,139,243,158,69,48,107,178,21,93,217,216,57,169,173,77,90,19,144,
+230,236,171,228,43,62,215,173,17,132,159,146,173,162,143,159,147,141,186,114,162,51,75,233,213,199,233,223,123,155,
+204,67,246,92,235,172,251,57,211,126,75,221,194,31,27,64,168,132,32,254,28,100,205,33,231,95,183,248,215,6,
+217,222,177,253,229,106,170,141,44,193,139,209,139,194,17,202,8,59,61,50,134,185,210,50,102,109,134,153,144,116,
+171,209,116,132,151,187,197,122,130,40,138,23,65,177,185,113,206,68,173,62,242,203,253,138,25,139,128,232,206,88,
+180,149,211,25,75,121,37,6,38,227,95,15,91,176,74,69,50,130,110,190,238,178,221,239,98,94,14,187,220,159,
+133,26,21,16,101,148,61,218,240,64,181,25,240,234,136,246,38,94,182,230,170,161,103,27,78,160,70,199,99,145,
+110,238,197,178,109,26,110,33,80,205,62,166,168,160,27,77,251,22,96,239,51,228,89,235,29,79,188,56,69,101,
+47,195,105,42,99,7,90,251,158,79,124,177,109,76,253,181,31,186,140,12,243,195,205,109,223,97,71,204,114,152,
+93,164,12,203,208,140,13,6,100,47,164,180,203,125,92,214,31,25,158,127,116,129,107,104,200,75,223,221,79,50,
+251,130,228,248,215,248,38,180,111,9,227,184,9,239,84,204,191,246,225,56,22,144,210,210,207,96,208,20,98,139,
+25,8,37,113,127,166,6,233,233,77,60,50,11,253,76,50,101,63,247,176,74,153,50,102,186,163,237,6,246,98,
+241,92,219,185,238,39,173,114,61,77,140,234,117,42,41,69,24,211,27,203,222,247,247,15,189,193,39,192,67,138,
+219,177,50,152,193,184,12,223,124,254,197,179,65,134,18,51,148,119,212,208,96,134,230,112,13,214,104,46,117,163,
+140,201,116,46,181,216,196,210,128,238,39,81,75,105,33,108,98,235,117,38,47,97,88,236,115,132,106,50,84,71,
+41,75,55,178,104,21,30,56,228,140,170,154,104,52,80,165,99,242,72,86,214,121,13,145,224,173,174,205,214,128,
+143,88,249,151,181,126,7,86,62,210,161,149,143,90,163,109,37,105,116,46,12,1,107,70,242,11,31,219,140,48,
+102,170,106,252,69,109,43,72,40,133,165,82,85,227,175,240,138,130,119,63,243,180,36,93,201,82,55,54,96,146,
+210,207,176,81,180,86,38,246,243,92,42,138,134,234,187,78,170,196,48,224,217,211,96,136,151,81,228,25,207,133,
+1,130,135,104,62,54,246,16,54,38,241,25,178,143,254,33,145,26,39,74,54,60,36,5,244,235,141,225,142,27,
+133,101,237,98,95,202,99,5,111,1,151,230,182,79,71,33,139,228,198,86,138,182,19,236,23,190,233,9,179,185,
+93,95,36,120,247,177,120,139,203,125,207,134,246,118,127,141,122,189,146,169,234,12,147,206,131,207,6,73,95,74,
+86,123,195,172,245,138,217,203,245,192,50,62,122,54,106,82,52,44,132,199,205,156,210,250,221,24,28,221,237,240,
+212,54,3,74,160,28,10,2,223,67,25,148,177,60,49,15,31,130,191,253,36,245,67,121,131,86,89,175,76,217,
+224,144,221,136,154,177,72,98,157,14,179,15,143,219,81,168,240,36,211,180,36,234,10,126,4,80,175,221,29,7,
+70,15,127,237,232,15,64,2,194,93,232,251,115,151,234,123,178,52,208,71,216,153,50,73,118,127,24,237,233,19,
+247,212,84,169,38,62,8,133,39,177,156,185,79,183,121,177,228,13,38,151,201,102,17,137,8,247,162,15,178,220,
+220,139,224,60,9,53,56,12,231,172,236,150,40,145,79,5,222,86,188,103,139,5,240,39,66,9,180,87,16,66,
+220,155,160,156,208,235,246,103,206,149,218,43,73,211,185,60,217,193,84,223,255,131,21,212,238,50,140,186,59,199,
+252,124,2,40,12,118,81,181,173,51,186,62,96,44,93,7,197,132,253,45,179,115,47,70,48,14,230,177,66,69,
+221,195,179,34,43,16,35,126,145,183,110,0,43,252,20,99,121,49,8,187,141,221,249,201,243,94,107,123,248,134,
+169,64,133,44,174,49,144,143,140,246,119,9,54,58,201,183,172,132,147,16,218,57,197,131,188,62,106,227,125,162,
+212,12,233,209,114,148,20,109,251,148,112,57,115,229,232,221,233,109,229,178,201,97,244,146,58,158,129,113,12,43,
+18,61,130,29,197,32,195,130,35,153,124,5,205,160,232,232,84,138,27,87,15,221,138,219,90,239,162,22,242,195,
+100,203,203,89,31,57,135,251,96,255,42,40,74,196,251,215,167,253,43,216,216,93,106,244,70,118,210,141,97,208,
+209,121,30,159,173,11,124,241,249,178,170,222,55,72,155,137,195,186,172,218,124,117,251,29,89,42,132,52,53,66,
+172,247,91,1,94,167,175,117,15,149,114,213,162,181,201,48,207,36,238,70,49,237,206,14,241,238,202,124,22,95,
+215,16,159,142,149,26,230,193,98,178,128,55,229,75,213,223,93,215,32,139,239,1,134,24,153,124,70,248,5,231,
+127,127,137,238,200,236,103,213,89,108,198,92,140,157,4,51,121,95,234,98,96,13,111,196,245,96,57,157,198,21,
+153,127,80,149,37,168,244,95,35,115,236,94,1,213,89,101,159,158,85,169,90,123,220,196,118,46,62,114,84,62,
+239,225,65,221,125,128,12,43,188,43,183,175,114,252,188,145,52,169,164,200,96,230,252,27,229,222,121,73,207,147,
+66,66,128,252,44,98,84,16,19,96,3,61,228,244,137,89,224,22,56,242,134,47,29,120,90,31,9,69,133,230,
+41,186,14,42,159,160,160,138,205,59,100,29,142,240,71,248,42,232,94,44,214,193,247,226,43,127,160,69,200,81,
+91,35,158,50,77,235,196,27,33,98,13,8,196,52,94,141,103,171,75,225,11,145,51,206,86,234,164,79,122,198,
+243,84,183,252,186,184,232,165,60,42,147,237,163,136,222,12,86,211,63,63,77,201,51,24,197,68,190,192,241,159,
+18,244,110,82,12,48,228,12,109,42,211,203,126,60,243,170,196,51,96,127,183,246,229,94,141,200,94,33,195,27,
+21,242,131,109,186,213,195,213,116,249,112,137,15,96,155,210,63,88,218,143,180,129,47,24,96,52,28,247,244,207,
+241,163,84,205,78,21,246,171,151,181,120,148,113,252,172,23,191,244,241,113,79,219,177,81,190,201,74,213,152,56,
+178,96,117,119,39,101,51,186,85,238,1,108,65,122,12,139,251,36,159,25,201,146,0,242,172,186,117,226,116,107,
+78,58,230,118,39,38,152,194,177,87,150,146,165,105,26,43,29,84,117,246,10,3,19,176,7,215,42,29,35,206,
+201,10,85,120,191,133,197,109,148,233,175,38,102,73,225,24,30,63,131,221,225,186,53,232,99,190,192,35,247,192,
+121,203,21,248,156,170,12,244,226,222,102,118,247,181,85,94,55,104,227,172,72,225,103,173,236,118,73,86,138,193,
+37,89,118,227,155,11,55,142,3,217,135,143,213,70,95,180,209,254,194,199,138,13,124,100,85,19,109,98,117,105,
+67,8,82,27,59,110,207,122,135,234,172,128,17,188,205,95,62,92,241,125,230,234,225,210,137,196,251,97,123,120,
+27,140,223,195,246,197,116,27,123,229,242,97,221,87,190,238,75,89,55,69,201,170,229,34,112,178,173,216,78,135,
+199,171,142,253,128,214,228,46,209,37,52,103,88,167,229,18,120,44,246,98,138,208,49,36,180,2,41,105,24,235,
+200,187,172,37,188,6,81,108,252,68,146,92,252,17,39,189,218,237,175,204,57,108,145,98,7,245,35,177,54,136,
+97,75,44,221,254,120,251,207,240,188,93,118,86,6,171,242,194,95,117,167,188,157,169,116,112,253,47,244,62,192,
+28,105,203,132,58,226,151,100,134,92,100,127,90,11,127,8,52,163,199,132,60,10,134,207,165,232,226,37,92,23,
+86,226,186,48,27,205,190,183,91,0,187,211,209,182,132,222,109,225,37,180,88,100,139,104,169,155,135,60,211,184,
+27,30,154,176,22,75,8,138,35,166,129,52,38,152,43,28,6,93,62,240,137,136,163,109,172,41,151,147,197,82,
+183,28,23,249,79,120,231,197,172,252,61,66,52,123,100,28,45,103,235,105,29,63,196,28,156,95,192,197,108,77,
+130,174,67,114,90,150,223,206,86,119,148,95,65,121,222,89,56,27,1,142,200,105,126,235,3,115,57,202,8,89,
+234,33,53,14,131,133,163,50,84,1,89,124,223,2,241,15,163,25,35,245,161,147,93,55,220,98,187,30,232,66,
+229,195,253,36,103,106,56,135,106,63,115,60,136,235,217,58,26,116,116,63,235,160,244,208,146,209,222,34,140,101,
+31,214,49,52,153,180,63,51,163,5,226,184,243,151,241,241,179,86,158,149,253,141,197,219,155,172,248,181,97,47,
+155,254,94,246,236,220,32,1,66,159,182,125,8,181,118,247,66,229,47,88,175,126,192,52,245,39,34,39,119,7,
+56,16,188,202,119,221,39,120,214,70,111,8,35,194,79,237,80,248,233,155,8,77,96,89,188,68,156,20,105,147,
+66,149,179,153,50,179,25,59,125,184,235,2,208,13,207,76,201,232,16,172,23,34,147,239,188,188,72,46,41,214,
+33,137,115,236,54,143,128,132,0,158,55,204,45,31,54,163,219,190,115,42,209,179,82,185,42,226,96,185,110,36,
+95,16,161,217,101,45,190,87,236,189,250,185,183,26,54,208,10,127,130,208,21,252,35,147,171,86,114,64,93,169,
+75,117,161,110,212,123,90,11,107,91,211,160,81,77,148,22,64,228,119,150,241,34,168,45,247,156,61,71,224,124,
+191,168,130,219,136,44,86,37,145,82,122,163,183,199,77,139,110,134,213,149,110,208,47,41,254,1,245,40,228,53,
+162,140,240,187,140,236,142,94,66,190,32,254,161,46,244,13,116,238,8,165,16,65,160,245,11,248,137,47,116,145,
+195,188,92,89,31,252,87,40,33,115,129,70,109,110,244,229,156,30,251,161,143,148,17,58,207,24,110,201,115,72,
+210,143,211,233,58,126,175,151,40,246,8,245,190,183,245,226,79,52,90,243,123,168,121,170,47,227,57,91,159,189,
+136,85,109,191,110,122,90,12,23,42,237,89,240,186,65,245,129,122,29,53,65,239,234,90,7,123,150,144,249,131,
+174,125,176,136,213,173,126,166,159,70,76,1,87,103,207,96,114,60,29,92,219,160,87,203,99,226,240,54,66,237,
+136,20,191,200,191,44,19,137,16,186,142,153,78,196,192,135,88,81,173,77,82,113,133,200,241,239,246,156,186,180,
+242,133,112,40,78,33,31,16,193,253,6,102,160,4,200,64,25,177,116,55,60,174,195,222,145,251,194,53,242,228,
+4,208,207,211,160,98,178,64,78,103,66,25,247,154,55,103,173,211,64,145,173,60,39,207,204,212,248,8,103,16,
+81,132,62,157,181,177,23,77,26,178,24,167,237,67,73,126,185,174,189,74,163,17,14,226,226,103,121,33,85,6,
+142,220,196,118,135,187,33,230,194,143,59,106,103,195,70,227,71,99,109,142,244,127,113,58,67,7,85,125,215,189,
+126,141,70,231,201,197,98,1,27,19,199,157,12,251,131,131,124,100,226,203,29,31,25,114,93,224,177,239,201,201,
+194,36,237,83,252,124,122,178,192,171,88,96,171,141,175,171,115,109,219,62,213,80,170,125,98,196,133,198,171,97,
+122,227,199,165,127,138,199,135,72,31,208,197,122,255,197,93,181,244,166,40,6,46,11,247,194,58,93,139,53,234,
+215,130,241,80,141,23,63,30,231,181,240,104,148,57,116,113,42,181,87,154,241,55,40,68,235,77,136,247,119,41,
+140,175,14,220,211,106,56,224,6,154,22,184,229,83,93,45,170,30,119,100,90,163,85,42,140,30,242,10,234,96,
+18,127,140,129,92,60,44,159,166,15,155,69,10,172,144,226,81,147,20,15,155,39,233,195,114,81,64,56,125,212,
+116,242,146,60,62,21,124,77,245,141,28,185,135,140,197,209,81,155,220,253,124,237,45,60,251,3,235,11,249,74,
+39,129,200,95,37,134,206,71,101,103,212,206,222,244,3,173,83,119,186,193,249,114,194,229,197,216,61,95,173,247,
+25,102,83,184,214,159,38,128,60,87,246,78,174,150,120,40,110,117,117,143,224,7,158,98,65,223,104,177,149,94,
+164,80,45,71,111,128,222,190,12,14,73,222,250,221,10,168,163,84,111,213,38,238,232,216,165,227,85,129,47,107,
+117,171,158,169,55,234,185,250,81,189,80,175,137,39,225,40,53,56,233,46,35,193,159,199,35,66,4,103,43,245,
+70,95,204,174,212,143,152,141,8,219,233,149,122,173,91,78,247,135,97,45,232,189,80,39,230,135,162,84,16,74,
+65,172,107,6,170,188,213,23,80,215,27,237,114,78,87,253,218,144,8,247,117,121,146,248,131,188,190,173,212,51,
+234,221,115,170,26,11,96,247,94,232,214,166,247,235,195,40,89,33,101,135,162,182,32,148,130,120,91,14,123,247,
+1,123,7,213,251,172,162,123,198,146,179,68,169,212,66,234,143,234,182,211,52,245,35,5,17,196,227,63,197,190,
+236,175,81,237,175,171,111,123,2,135,53,9,28,190,212,245,217,219,243,57,214,36,80,140,149,192,132,132,125,100,
+252,50,142,187,48,197,220,108,152,221,219,233,170,235,245,251,246,112,191,105,152,173,151,87,252,95,238,52,204,240,
+12,103,248,195,108,37,87,129,219,103,230,238,47,32,223,207,219,170,175,52,163,208,146,170,184,81,157,170,32,202,
+191,126,244,75,108,5,91,128,176,155,223,60,89,207,209,246,103,235,71,112,247,22,188,137,99,24,208,91,161,165,
+247,23,8,89,181,188,219,22,202,6,93,37,122,122,254,208,66,242,80,47,79,173,49,214,235,254,169,55,46,104,
+29,45,94,187,224,167,253,186,26,25,47,235,155,191,215,149,61,116,212,13,18,129,239,165,169,156,107,77,59,255,
+189,122,25,171,98,241,1,104,188,231,250,133,190,78,110,245,27,253,163,126,173,175,213,146,173,119,183,55,167,201,
+7,213,222,158,38,183,170,189,121,156,60,131,239,199,201,27,5,209,207,21,196,254,168,32,242,133,130,184,215,108,
+106,232,165,162,145,39,127,145,138,136,183,237,190,34,226,135,86,168,58,174,91,161,218,248,6,3,114,72,201,181,
+140,17,117,52,109,39,143,224,161,108,222,122,68,54,15,200,242,254,93,229,126,188,239,81,189,199,241,13,139,168,
+84,157,46,85,61,138,224,83,129,224,21,51,186,10,169,101,152,121,174,215,218,233,74,174,58,93,169,37,98,255,
+210,242,249,1,251,47,167,107,192,240,171,197,108,157,108,1,151,207,14,156,255,151,112,86,220,133,196,213,47,122,
+114,149,47,151,133,33,158,88,227,241,121,31,125,111,212,179,64,24,252,132,254,228,104,142,168,199,228,191,46,236,
+241,70,98,240,219,128,149,127,99,21,140,182,253,86,243,69,127,30,41,186,140,231,207,0,224,113,219,81,164,250,
+0,161,155,206,215,231,209,246,191,169,66,137,184,27,137,0,111,245,8,218,222,10,252,215,28,192,127,13,227,191,
+6,241,223,173,254,88,236,55,221,118,247,205,234,16,107,239,119,250,131,222,199,217,179,223,220,233,15,31,221,105,
+236,242,221,147,31,38,190,227,94,163,70,149,224,6,254,98,161,52,41,4,19,240,151,0,118,254,14,213,142,147,
+179,132,211,47,244,137,186,9,130,138,23,79,110,224,186,125,17,239,222,235,20,100,244,213,181,126,111,55,211,252,
+163,176,253,5,52,250,102,148,109,12,73,83,126,10,102,156,254,252,110,70,196,5,210,58,207,37,103,225,133,254,
+2,110,201,139,107,175,120,194,125,122,169,95,0,13,39,143,21,248,28,40,81,219,115,101,160,107,61,175,23,209,
+7,253,70,249,253,190,200,240,11,21,156,129,205,118,133,252,243,197,107,61,123,241,240,199,233,143,168,62,36,192,
+5,227,77,59,32,238,1,96,94,98,222,100,44,209,87,49,172,127,164,234,3,53,39,35,41,216,59,181,130,133,
+127,253,80,147,98,105,4,231,20,144,46,209,233,236,69,252,16,234,182,108,186,53,185,107,123,123,188,167,182,237,
+96,26,142,212,162,133,12,3,93,220,24,15,87,227,26,107,16,36,26,138,160,243,12,195,84,253,167,64,25,189,
+158,189,177,116,211,63,244,7,252,196,189,52,111,174,115,184,104,68,191,64,51,105,99,28,146,77,62,157,233,107,
+228,109,95,214,38,125,63,199,36,134,90,78,178,9,29,151,126,198,165,121,130,146,127,204,116,51,40,77,59,150,
+83,184,240,186,101,101,134,127,144,168,226,167,206,60,96,59,125,195,221,119,188,154,107,138,178,1,62,160,195,68,
+16,248,116,221,37,159,249,94,71,228,74,89,39,188,215,10,185,101,201,115,127,178,55,1,234,240,104,111,2,188,
+225,169,142,32,200,231,243,107,229,55,120,242,12,191,233,202,79,126,72,127,81,109,157,150,77,97,155,58,131,227,
+234,92,185,14,1,57,16,220,223,92,118,135,80,30,47,108,56,150,91,62,150,7,236,102,132,139,3,231,166,183,
+193,194,251,195,171,42,242,116,91,171,37,30,112,61,227,218,138,106,9,68,213,104,46,232,147,60,190,106,252,153,
+164,154,238,16,46,108,247,6,99,156,149,5,65,51,148,142,82,104,60,241,80,117,131,119,178,122,28,21,34,65,
+50,173,84,161,235,222,53,158,6,152,41,207,240,17,74,69,13,190,197,248,203,19,22,46,253,222,94,100,110,188,
+165,220,215,81,230,191,213,122,170,11,216,155,9,198,81,5,54,10,247,175,172,118,150,14,170,197,216,59,235,157,
+249,122,109,23,20,87,135,1,168,221,120,34,64,14,129,142,189,234,95,111,106,230,71,224,107,77,255,229,121,145,
+243,1,181,135,132,93,216,62,153,186,73,214,93,159,116,69,117,187,136,206,249,145,71,0,11,41,193,132,221,80,
+166,92,13,158,14,28,224,225,110,241,80,0,72,92,204,39,87,198,54,202,131,224,60,126,121,225,119,198,50,82,
+78,158,62,59,95,241,254,139,143,172,216,17,146,182,254,190,80,189,253,118,85,59,163,166,196,252,240,62,235,35,
+249,230,208,6,9,141,129,87,123,64,18,182,133,82,89,37,71,230,113,123,238,54,243,31,141,125,210,73,63,144,
+220,238,177,247,147,175,13,135,208,14,95,196,14,149,48,7,186,217,170,106,199,226,124,229,46,133,158,46,58,244,
+116,131,4,255,253,34,80,67,197,214,70,242,145,86,192,185,39,55,98,104,50,138,229,207,208,114,93,176,45,249,
+20,206,99,115,23,121,211,196,113,184,200,38,39,52,183,200,33,187,179,219,158,65,214,222,168,70,143,8,191,51,
+67,116,16,203,57,15,240,225,98,231,128,194,43,166,68,164,136,143,214,23,143,214,206,167,4,124,209,169,132,252,
+90,183,74,101,24,129,230,140,16,103,79,41,187,118,92,8,99,237,18,225,157,50,90,15,110,234,174,166,112,225,
+212,62,139,143,130,60,164,196,240,93,218,174,169,109,180,56,247,182,138,138,99,116,129,113,203,117,96,76,6,49,
+25,196,248,190,96,118,9,46,184,250,97,161,131,187,141,102,232,190,201,203,7,53,104,13,208,28,15,236,11,129,
+183,166,8,236,151,65,15,78,213,45,252,220,158,118,202,134,31,219,240,227,14,173,84,154,160,92,237,75,180,92,
+164,245,101,90,46,212,98,169,157,165,0,10,201,153,192,233,229,24,154,114,121,239,47,6,188,137,125,46,64,200,
+33,163,209,10,120,96,105,134,29,205,246,111,1,206,164,236,21,113,96,75,62,7,81,51,253,30,134,105,165,75,
+201,48,109,250,12,83,218,131,85,31,111,214,119,215,121,34,55,13,30,180,67,174,131,85,253,183,239,153,227,2,
+234,5,178,100,90,21,208,105,21,207,42,160,249,51,17,95,91,188,26,79,107,72,88,235,149,78,241,36,18,25,
+16,107,114,185,149,143,246,88,147,11,22,58,131,130,202,184,221,98,196,110,233,77,133,50,114,207,248,52,187,236,
+166,7,245,198,67,61,177,217,60,196,171,85,236,107,193,108,1,218,105,121,195,43,61,206,249,200,25,38,145,158,
+95,140,17,100,179,127,40,206,1,166,111,115,196,203,222,122,138,124,73,151,88,73,70,141,212,215,199,71,206,177,
+154,180,189,34,125,99,75,203,43,100,195,21,73,103,52,219,202,119,204,194,83,221,248,252,46,142,147,144,224,113,
+147,63,93,68,26,193,70,8,227,146,203,32,237,70,17,193,135,49,119,126,5,173,4,234,124,254,9,158,91,107,
+117,162,86,42,195,135,97,152,178,15,48,101,118,109,222,162,32,227,161,179,84,18,169,152,47,41,189,253,180,134,
+247,161,53,103,51,92,65,191,20,208,52,11,167,214,186,192,128,119,153,145,234,210,146,208,108,47,163,10,23,100,
+188,17,245,5,69,132,14,61,132,64,57,31,183,210,84,215,14,230,191,136,74,26,49,249,89,157,246,234,122,200,
+73,65,102,43,142,19,44,139,115,106,59,234,116,233,51,167,75,191,14,186,244,171,160,75,191,236,244,154,121,173,
+133,50,42,141,113,102,91,101,171,135,233,61,81,149,195,156,37,47,238,104,53,74,80,123,235,40,37,11,162,253,
+75,147,187,93,246,239,78,128,86,206,59,187,106,184,151,70,8,8,6,244,33,161,164,56,214,31,241,62,194,99,
+94,142,241,0,33,34,252,238,141,59,246,8,115,159,156,56,0,24,127,28,255,138,175,138,165,254,156,37,154,49,
+1,127,143,127,85,176,16,76,174,140,13,196,183,14,172,5,99,130,35,125,138,91,160,255,25,163,240,51,105,128,
+76,240,153,163,6,125,208,36,152,92,202,228,251,231,164,217,159,129,174,83,88,207,244,212,214,20,33,65,50,156,
+55,204,52,218,23,63,109,212,163,238,208,59,165,164,182,60,197,126,159,155,246,50,176,174,167,19,188,99,190,124,
+62,81,210,149,151,112,225,101,14,208,20,169,54,72,83,164,232,207,82,219,250,112,117,162,35,120,212,78,173,213,
+7,173,113,59,237,185,216,106,186,113,62,215,61,154,22,119,157,171,109,208,252,5,132,97,44,194,232,80,189,209,
+26,210,28,194,219,161,14,156,196,98,223,115,141,209,221,170,145,82,23,18,68,35,156,181,140,47,140,52,145,33,
+237,27,219,185,225,19,183,201,42,8,56,203,24,128,24,1,148,140,83,20,203,241,64,113,252,213,172,54,168,223,
+69,234,116,93,222,32,43,17,234,17,82,47,156,47,0,122,222,124,231,190,191,93,121,171,156,182,253,144,77,137,
+34,184,68,239,208,252,113,45,151,130,43,134,233,22,245,57,153,183,114,190,93,71,6,177,38,3,149,175,193,196,
+194,98,179,31,142,170,172,109,144,90,135,241,79,39,199,147,105,197,228,84,187,174,171,235,7,104,248,252,115,188,
+150,70,19,59,159,203,202,52,15,202,10,184,119,64,140,60,0,50,238,193,100,26,174,43,21,24,22,126,128,199,
+52,89,191,109,213,10,237,212,213,48,227,189,137,133,27,218,151,254,59,162,110,180,62,220,160,250,1,110,51,49,
+165,190,219,168,120,213,109,203,177,217,17,67,43,237,208,26,49,180,121,137,61,131,134,189,5,236,242,28,173,129,
+81,244,151,224,153,17,38,142,147,48,132,169,131,30,115,234,63,90,72,147,54,152,87,123,182,167,62,51,209,8,
+172,168,51,179,248,18,23,15,22,4,37,213,236,55,122,202,244,134,127,207,99,54,124,218,170,50,196,179,5,96,
+232,1,78,230,32,214,102,179,54,15,171,26,50,9,203,136,109,63,77,58,56,102,227,71,242,201,160,13,182,196,
+251,182,163,80,56,178,141,0,52,98,162,212,55,213,38,34,255,236,249,185,243,170,84,198,199,191,84,121,105,243,
+212,26,165,43,101,169,84,215,92,170,128,47,159,211,27,179,172,20,30,195,105,220,51,42,181,14,70,165,38,249,
+114,2,171,4,30,11,38,110,166,40,204,59,252,221,122,204,70,117,48,103,96,221,66,124,97,162,103,173,154,176,
+235,238,102,162,188,50,50,187,246,246,217,110,32,155,139,155,112,158,13,169,6,250,44,118,222,212,132,163,57,151,
+125,91,241,153,140,81,19,138,241,233,23,184,101,151,175,9,120,235,28,125,190,13,187,42,235,233,247,238,28,109,
+181,71,199,199,199,94,70,205,224,82,77,220,86,152,168,214,89,79,31,201,181,45,101,62,172,234,179,208,232,221,
+181,170,97,31,169,248,231,220,173,251,203,250,33,216,130,172,100,121,127,57,63,233,84,236,13,78,201,253,165,252,
+228,17,43,39,140,113,136,75,46,112,239,237,15,77,77,66,96,66,85,240,56,239,40,239,135,231,161,198,150,180,
+3,61,92,208,143,207,129,145,45,70,3,61,92,202,3,7,91,39,115,107,126,247,114,110,203,59,23,148,235,224,
+177,222,95,129,28,182,47,237,23,246,222,194,126,232,190,172,95,221,251,139,250,245,181,57,248,60,63,131,162,38,
+248,95,104,60,2,171,208,167,151,159,67,222,122,183,238,208,110,226,57,36,87,112,66,135,24,8,107,173,101,47,
+145,116,202,151,11,238,215,141,201,162,150,204,28,36,63,68,141,170,125,83,233,157,77,213,241,188,87,65,138,142,
+30,240,63,142,232,59,30,125,71,62,0,254,26,149,103,206,18,239,180,57,87,104,66,49,86,40,254,24,193,47,
+166,178,57,94,159,216,141,53,205,22,254,172,157,239,19,144,39,31,69,70,94,74,126,58,13,71,217,104,78,246,
+177,80,30,75,234,39,246,86,38,249,67,206,32,117,107,56,70,195,7,32,75,55,176,176,203,30,221,241,251,201,
+239,167,237,244,247,147,7,185,165,59,210,7,14,36,204,242,193,239,167,229,148,206,18,79,210,146,69,241,183,45,
+33,225,119,107,118,76,183,25,61,34,46,208,106,19,16,219,157,85,255,14,26,79,72,49,243,188,191,132,44,248,
+36,36,10,216,79,123,180,63,15,199,107,212,134,35,229,130,107,12,165,84,171,38,228,115,161,40,194,35,120,165,
+27,134,170,165,172,39,118,190,208,1,196,198,146,241,136,149,173,84,202,206,172,124,17,98,37,113,131,156,28,122,
+163,223,43,49,105,144,171,127,103,135,183,101,232,178,170,187,139,225,60,53,26,72,189,158,199,254,10,157,42,181,
+113,240,17,195,16,128,52,192,89,73,166,140,13,50,222,221,141,130,0,233,175,232,131,71,213,49,249,167,196,205,
+150,161,103,10,114,40,25,123,71,129,252,129,166,182,128,75,158,179,141,133,111,34,97,255,38,246,236,161,170,88,
+90,27,101,34,85,137,111,7,107,157,156,89,230,106,201,10,121,66,69,20,175,92,175,230,195,16,225,151,68,78,
+242,155,22,221,244,173,209,106,10,173,166,233,198,138,14,61,224,176,53,18,213,160,57,220,224,232,211,127,250,211,
+100,215,33,117,118,181,142,2,64,52,60,179,71,102,113,118,158,92,172,45,254,130,22,186,209,46,73,154,90,206,
+38,201,175,149,189,57,109,52,41,5,227,219,5,195,108,10,166,196,209,94,201,149,137,10,253,52,229,110,161,41,
+66,173,139,16,130,61,208,3,188,134,12,62,29,2,75,82,121,225,84,124,188,149,244,247,213,192,252,177,50,61,
+73,152,183,45,55,202,151,131,96,14,11,29,110,53,79,252,181,186,1,188,199,166,123,161,76,56,192,13,92,7,
+226,56,248,102,112,213,225,108,12,234,42,101,93,225,0,130,10,230,173,215,209,168,98,109,29,226,114,99,85,220,
+237,219,93,190,236,89,39,61,2,0,200,113,13,89,183,129,190,79,22,187,46,201,67,145,139,245,152,79,112,180,
+115,43,47,232,97,248,214,84,115,43,77,53,251,131,140,188,148,23,58,197,91,84,166,161,51,6,44,132,145,35,
+111,239,23,170,97,217,3,59,27,73,234,89,141,55,208,15,7,172,169,202,20,140,79,112,28,130,11,243,253,238,
+250,185,125,131,55,182,191,216,75,9,15,128,57,3,148,130,176,210,4,119,240,124,203,122,109,57,9,53,0,100,
+169,206,38,147,115,181,11,166,224,209,224,61,45,128,11,0,82,195,6,208,37,155,180,197,92,246,109,22,127,121,
+236,238,11,112,219,17,78,152,162,168,245,41,24,29,115,114,108,87,25,56,57,16,221,202,128,145,1,84,148,243,
+109,222,174,165,27,142,220,15,11,145,248,5,21,186,152,44,140,110,19,27,67,79,132,23,136,209,141,102,165,187,
+5,72,97,37,240,27,43,19,170,253,192,213,138,234,218,133,175,48,241,21,133,18,215,80,194,187,37,225,39,223,
+124,255,201,151,117,116,115,241,224,28,12,71,251,76,183,162,226,166,28,116,5,123,205,197,32,227,34,135,135,225,
+148,38,6,186,16,92,61,199,144,131,216,104,207,90,228,7,181,213,171,234,26,173,6,52,38,18,75,246,126,221,
+95,178,127,180,193,73,227,142,205,218,238,186,142,120,2,54,136,11,133,55,217,50,178,25,21,1,217,216,141,189,
+30,139,29,243,195,85,134,187,179,116,11,87,158,165,214,27,213,175,81,225,9,36,76,172,10,115,108,136,186,249,
+251,75,123,156,61,160,190,61,112,86,147,82,26,27,212,105,227,147,7,159,236,210,238,239,68,42,21,199,23,232,
+243,234,118,88,223,117,90,151,80,221,187,178,66,245,184,7,53,111,135,7,232,67,19,40,165,180,121,192,59,116,
+164,90,239,27,175,180,238,240,214,26,192,39,99,163,181,98,218,230,21,232,236,105,252,3,188,69,85,195,240,244,
+135,3,204,14,171,81,154,117,170,80,43,200,15,127,214,231,192,55,137,85,78,59,199,111,159,209,137,179,124,75,
+239,101,51,211,169,220,62,37,249,221,193,190,69,176,218,5,239,60,209,75,185,52,171,176,52,75,223,194,86,223,
+66,80,101,168,138,145,158,109,61,239,21,170,170,206,182,240,119,59,175,81,185,16,254,64,96,108,124,48,108,76,
+116,227,220,118,170,196,224,234,108,137,163,196,113,246,101,232,71,135,89,35,124,64,77,133,58,251,210,9,102,22,
+22,120,21,71,208,148,213,194,47,66,53,234,23,1,40,31,255,141,174,208,230,254,212,35,134,189,164,13,220,54,
+208,188,115,66,221,109,45,13,121,235,156,54,74,238,87,74,135,79,162,4,114,182,74,168,249,131,99,67,125,95,
+175,15,214,167,177,45,250,138,21,13,73,229,206,45,102,227,220,98,42,83,211,231,27,211,206,131,3,67,35,177,
+229,171,134,238,16,121,32,125,201,78,37,106,105,65,82,131,73,72,55,152,26,125,88,146,22,149,225,102,222,153,
+96,214,222,211,89,95,181,214,191,93,41,68,239,115,42,90,198,206,199,245,179,254,85,194,223,87,237,206,213,48,
+230,96,130,12,15,43,162,156,252,144,122,76,239,186,151,134,151,255,7,240,242,214,162,43,28,169,159,23,106,63,
+118,201,148,23,225,228,64,62,76,234,26,206,51,236,35,243,189,169,14,92,129,3,117,96,82,215,112,158,97,29,
+126,17,219,152,234,97,208,59,80,21,167,118,141,200,57,172,144,227,185,95,12,176,7,234,227,84,103,159,50,236,
+7,153,203,210,151,89,97,82,59,207,17,66,26,246,87,70,237,134,43,101,11,68,241,112,165,100,90,199,219,64,
+146,41,220,79,132,207,86,225,3,211,217,217,223,61,138,251,100,215,118,127,87,64,146,156,251,178,207,156,123,57,
+81,137,50,178,154,191,99,169,99,124,54,180,199,33,212,98,160,150,97,221,131,92,13,103,251,251,94,212,185,186,
+187,71,204,253,185,187,63,179,59,58,193,12,33,223,3,153,138,97,153,238,27,223,35,248,164,71,206,32,167,132,
+32,59,239,245,165,236,102,182,108,191,75,54,206,181,129,12,37,220,191,52,15,105,33,105,72,68,86,216,1,123,
+145,89,82,228,240,218,53,128,13,22,45,45,153,111,225,104,193,35,168,139,30,94,2,230,42,153,139,143,111,25,
+77,55,164,94,123,246,84,29,217,220,88,183,1,213,192,254,208,160,119,165,229,166,99,7,12,219,215,225,89,73,
+189,37,76,135,51,131,63,224,53,190,102,226,123,58,206,5,226,167,181,79,90,233,167,239,12,30,167,106,21,199,
+99,9,141,90,141,198,195,201,91,209,201,123,32,253,203,3,241,109,137,9,93,160,57,158,213,117,122,123,188,170,
+171,171,40,16,87,25,95,75,172,151,220,204,222,53,70,206,97,194,237,235,180,161,151,175,154,102,221,224,177,158,
+117,72,56,246,167,125,48,227,236,168,97,160,182,124,214,226,200,140,29,153,32,255,57,102,199,69,96,120,109,121,
+222,49,122,248,38,189,50,75,255,118,106,185,35,26,175,32,225,18,184,251,164,129,14,153,37,94,56,212,206,161,
+149,164,70,223,208,223,213,102,149,223,152,6,13,232,188,109,162,17,204,163,16,148,88,186,162,198,101,255,108,29,
+213,10,253,26,84,199,92,49,154,38,47,245,11,124,140,89,148,81,156,148,126,130,177,190,193,29,9,33,9,165,
+30,160,54,3,21,149,48,101,93,96,226,100,200,196,49,49,209,122,5,252,241,143,123,221,176,22,28,42,13,212,
+219,9,10,67,171,14,15,70,240,170,72,0,4,58,81,65,85,246,200,69,198,106,37,238,247,80,73,207,109,70,
+238,182,95,137,18,132,126,203,229,254,225,44,188,118,26,251,216,196,114,137,188,113,195,205,177,130,10,42,29,122,
+124,93,210,254,239,45,137,145,124,141,180,127,9,1,154,52,43,182,75,0,173,201,26,223,9,39,0,215,188,245,
+27,85,161,216,90,199,122,12,228,113,231,87,114,131,24,30,113,191,189,46,209,251,168,169,219,91,4,160,6,146,
+143,97,33,183,153,113,14,188,225,5,31,22,20,253,250,196,234,232,84,56,32,251,76,94,122,118,121,243,38,92,
+116,141,2,74,214,223,116,75,88,4,36,175,4,139,174,233,177,232,42,77,62,166,107,93,226,79,170,163,26,72,
+96,244,238,118,102,121,115,232,185,9,250,144,194,101,236,205,26,126,224,23,92,70,125,129,95,158,35,231,121,116,
+228,204,113,173,39,127,56,254,207,227,83,231,206,242,249,90,159,209,109,82,185,139,164,98,209,108,39,51,61,241,
+158,72,38,231,97,140,159,55,131,91,227,216,165,20,66,207,215,158,181,146,123,214,10,230,144,151,236,215,253,202,
+92,60,50,157,124,164,129,75,60,148,43,225,103,129,60,246,89,9,127,18,140,157,97,156,0,201,79,155,62,17,
+238,165,179,131,209,29,119,188,207,135,198,69,45,99,246,181,41,151,8,48,234,175,214,191,111,85,126,86,161,5,
+152,214,40,104,170,71,149,127,187,254,248,198,124,109,0,88,239,0,174,155,189,218,114,73,227,163,199,96,152,44,
+242,24,140,19,60,177,166,85,224,70,174,157,39,251,227,240,6,246,233,237,203,37,20,78,114,128,142,96,144,38,
+39,95,84,177,194,88,118,161,109,99,57,16,40,251,109,142,6,202,203,26,247,130,31,15,246,103,120,165,102,207,
+182,219,220,51,194,141,126,106,132,95,239,216,62,39,11,95,166,175,134,143,240,146,7,56,2,255,101,128,255,105,
+99,125,229,105,193,182,38,232,231,7,127,252,86,145,121,138,110,218,159,182,49,14,238,172,154,162,207,234,184,147,
+104,74,240,179,120,67,248,11,44,66,227,85,181,109,76,181,109,39,150,133,87,46,218,196,63,96,231,253,43,133,
+28,134,48,68,77,168,238,217,154,220,152,225,188,17,219,162,196,87,2,28,192,136,192,134,245,231,140,239,38,105,
+1,155,107,121,139,178,14,208,139,227,7,36,120,12,30,172,219,245,131,151,207,31,252,126,50,173,128,214,154,78,
+126,255,224,106,11,173,94,154,7,75,251,112,0,124,3,251,12,2,244,183,121,96,23,0,127,48,75,109,160,170,
+37,190,189,120,137,219,225,41,3,17,251,167,240,136,113,93,34,213,253,229,6,199,25,149,62,248,207,127,130,151,
+107,36,164,122,153,142,45,237,255,25,205,76,84,198,94,228,188,159,107,224,87,190,81,112,19,108,54,0,24,228,
+171,27,5,18,80,246,154,65,75,101,26,24,155,133,83,135,88,83,136,149,110,188,85,186,165,190,73,163,56,120,
+203,73,237,39,3,103,33,221,219,244,237,243,101,124,165,112,23,157,154,195,162,63,182,243,34,130,179,144,172,158,
+112,248,114,101,248,70,238,99,154,22,4,226,154,129,99,158,27,19,114,100,219,186,54,229,158,59,243,94,9,143,
+134,123,177,23,236,209,219,183,133,150,130,200,65,123,63,91,193,238,218,145,255,16,110,79,27,24,42,148,126,229,
+19,123,101,26,146,141,251,122,56,28,102,80,248,122,164,244,197,134,103,213,59,126,247,185,214,32,105,105,74,56,
+251,242,76,68,167,109,219,119,221,114,17,60,123,63,207,27,242,194,41,59,53,116,237,194,133,150,213,107,114,25,
+175,47,83,36,101,41,146,175,159,43,52,229,84,83,234,115,67,54,111,79,164,5,124,126,86,33,203,32,249,25,
+3,209,185,165,242,143,82,208,135,40,226,93,159,39,56,121,145,230,5,108,189,182,122,96,55,212,3,43,70,143,
+59,239,247,237,3,134,233,7,220,207,7,72,58,211,254,124,7,19,93,62,192,87,14,255,32,218,125,215,30,219,
+133,177,210,174,147,140,143,153,137,250,180,137,213,48,117,195,199,198,68,125,187,142,85,120,12,204,211,130,12,221,
+244,167,20,142,14,49,13,150,17,32,128,119,143,224,222,137,68,178,25,148,151,45,252,123,38,98,77,199,234,9,
+165,211,234,105,212,133,44,86,245,141,12,193,251,95,188,128,51,175,90,84,73,179,40,31,53,9,97,215,131,204,
+141,59,121,27,61,214,198,93,108,141,187,248,25,123,236,12,49,129,131,122,6,132,129,120,112,142,251,110,197,195,
+62,90,96,60,134,169,182,164,182,4,118,63,247,114,176,199,185,178,75,160,146,104,219,122,28,60,70,152,136,230,
+45,163,36,244,57,111,34,129,234,60,6,228,204,248,108,23,242,2,96,81,4,38,113,6,238,52,157,110,144,92,
+111,203,18,104,13,155,131,95,193,109,150,79,173,173,116,16,188,117,134,124,91,7,12,166,75,56,103,168,172,147,
+1,127,110,202,25,81,141,150,29,199,139,192,8,236,49,52,75,236,91,15,78,19,148,253,181,238,225,201,238,83,
+67,231,125,101,5,224,135,179,206,162,32,178,236,16,249,146,64,92,56,47,22,19,59,16,120,156,177,59,108,50,
+15,137,186,30,49,249,90,243,199,199,156,36,14,84,82,144,82,64,34,102,12,2,184,125,181,195,159,164,238,72,
+198,4,168,73,66,125,236,181,64,213,22,73,143,227,2,143,39,163,34,230,168,154,72,93,212,150,50,101,179,173,
+89,214,231,75,144,30,125,249,188,137,198,5,141,37,51,255,135,200,40,212,10,65,70,45,189,35,55,29,91,174,
+255,150,221,41,80,141,119,137,178,115,117,142,153,196,161,166,71,35,150,225,242,85,171,20,26,139,232,121,3,253,
+204,199,200,55,231,59,228,217,57,233,23,86,186,114,194,143,125,143,130,0,89,155,72,202,4,25,251,148,218,148,
+84,45,146,24,72,13,162,86,169,253,186,113,42,202,30,77,166,106,233,181,53,178,133,184,28,37,235,133,215,72,
+231,43,212,18,201,75,204,85,167,75,192,49,168,24,151,214,148,17,186,102,222,85,245,45,102,181,177,93,135,28,
+158,31,162,74,201,254,213,126,162,252,123,47,244,181,192,190,174,225,237,192,190,196,192,1,71,45,197,115,136,112,
+157,115,34,59,64,24,127,222,136,120,149,197,192,63,135,40,40,228,226,98,4,57,81,84,38,41,120,244,128,137,
+62,97,133,23,68,224,244,206,133,212,106,9,18,14,144,234,168,232,117,188,210,24,158,11,227,207,75,13,207,245,
+94,112,110,13,164,62,209,9,203,104,151,47,147,194,242,120,214,164,128,230,149,144,104,74,41,216,197,170,60,91,
+209,129,188,234,224,23,221,184,165,120,97,194,137,106,20,131,194,14,46,197,124,27,192,39,61,74,44,105,22,235,
+86,120,137,177,219,67,249,25,141,85,77,220,199,79,171,27,78,35,121,47,123,94,50,209,51,4,219,64,220,177,
+182,111,255,181,140,239,93,210,170,41,82,166,199,72,72,69,200,117,128,222,54,246,62,60,171,236,47,140,240,169,
+9,18,96,141,54,40,169,0,26,4,77,108,27,100,90,95,168,38,224,149,66,24,69,45,103,38,238,70,9,54,
+200,68,121,78,98,219,3,184,102,79,72,157,2,46,245,212,56,178,68,46,172,140,223,247,101,109,86,166,54,101,
+22,42,240,36,130,31,117,210,42,107,202,211,141,56,49,78,61,201,141,216,155,122,244,50,217,146,6,86,173,103,
+57,58,172,225,121,56,168,99,139,55,124,24,179,173,61,238,177,25,239,152,142,33,202,145,226,150,82,248,100,108,
+209,188,107,10,186,132,82,242,157,83,162,172,239,10,51,244,93,225,111,172,40,187,78,117,214,222,170,137,236,173,
+184,12,85,252,142,42,41,19,140,33,3,113,248,5,184,204,254,194,142,69,207,6,7,167,160,140,213,161,214,32,
+197,238,207,84,213,225,153,86,87,131,39,219,180,71,165,96,33,130,20,93,217,95,160,154,93,113,180,208,196,14,
+58,38,19,103,160,5,162,62,88,29,26,103,188,137,123,225,84,141,176,135,66,170,53,150,1,166,81,137,47,54,
+204,136,138,38,239,221,17,34,17,75,193,136,37,172,53,154,91,221,245,159,75,222,18,254,85,24,41,99,214,157,
+144,29,193,87,222,190,219,178,66,168,125,236,134,101,109,171,28,3,8,77,141,181,248,31,255,209,207,150,197,93,
+127,88,132,4,217,39,23,140,152,133,141,122,51,212,245,237,112,13,241,146,106,113,235,250,134,49,10,60,75,239,
+131,183,138,248,25,117,12,60,76,44,167,154,170,139,226,142,189,171,112,208,22,28,182,53,74,163,82,158,73,240,
+76,55,32,31,248,229,207,248,59,137,84,64,21,119,111,51,228,84,152,143,228,84,168,70,31,188,68,30,149,130,
+19,231,5,9,183,61,18,197,9,33,174,77,246,158,136,241,79,243,18,149,40,57,201,231,255,82,222,101,125,154,
+23,100,11,34,144,227,211,36,156,236,33,57,119,85,45,209,171,117,16,171,196,87,8,43,110,57,84,243,164,218,
+14,163,186,249,225,214,220,202,113,171,49,99,168,19,47,112,150,1,90,91,31,62,211,192,58,52,252,243,120,110,
+23,192,38,89,117,163,168,39,139,21,204,58,122,199,244,28,224,149,229,0,207,87,253,49,120,168,90,246,92,155,
+76,87,76,210,127,11,48,176,42,170,235,40,198,51,186,118,39,113,94,178,197,33,116,157,142,14,23,173,165,85,
+142,92,160,61,85,185,104,236,147,177,38,119,153,72,103,101,72,103,121,160,239,175,48,15,4,47,142,135,111,99,
+131,21,236,226,30,67,40,156,185,191,78,20,136,118,45,111,188,104,241,142,185,54,73,170,2,191,38,41,248,36,
+45,156,44,59,198,126,73,70,246,97,137,240,98,144,164,254,108,237,129,35,62,111,144,214,115,19,165,246,10,161,
+122,196,125,39,225,60,32,10,175,201,98,73,37,123,234,121,114,168,245,115,50,118,51,224,164,81,74,191,219,223,
+65,135,233,127,126,16,237,83,234,3,158,21,122,85,247,249,218,99,154,152,6,168,221,163,239,237,27,1,176,105,
+142,14,242,180,224,236,108,197,29,221,223,174,182,229,254,157,91,198,196,221,232,110,247,52,209,90,70,39,45,191,
+12,155,96,45,232,251,50,199,187,229,243,192,101,138,98,47,150,106,43,1,186,106,93,45,147,82,145,224,108,210,
+168,172,218,2,36,84,29,62,241,5,134,119,73,178,133,125,53,16,112,82,94,37,213,252,21,138,11,19,237,218,
+141,182,57,156,120,201,245,98,211,247,48,123,142,120,115,248,102,140,63,198,72,232,110,186,23,104,56,191,78,76,
+215,225,125,171,134,71,8,24,67,101,47,96,76,183,167,83,216,23,211,218,81,178,167,172,166,6,145,49,161,242,
+50,58,9,242,176,149,62,5,213,90,51,175,0,5,229,43,90,249,70,149,81,21,199,174,207,124,90,138,7,235,
+198,54,135,116,37,43,188,97,221,62,50,114,211,95,157,157,158,243,10,76,171,179,199,231,188,10,240,253,135,115,
+180,135,217,71,32,94,14,125,28,211,114,54,192,10,119,33,244,186,229,67,48,112,136,246,57,8,106,104,211,220,
+95,54,85,233,28,146,60,209,112,193,51,92,0,2,243,33,79,26,182,186,231,55,171,6,111,233,40,29,44,110,
+137,226,10,139,154,161,225,198,132,249,124,32,26,32,55,164,87,80,35,200,199,192,134,97,202,161,159,211,211,251,
+124,255,217,65,10,224,66,93,117,119,96,86,158,195,184,27,160,227,251,38,223,103,188,231,112,61,162,181,144,122,
+55,170,188,227,236,51,116,35,51,241,189,36,148,156,175,249,255,168,246,254,128,35,163,94,32,196,45,218,200,81,
+182,68,37,39,166,139,19,128,142,131,19,120,96,30,186,184,27,76,233,62,95,110,56,192,22,247,34,110,149,52,
+41,173,148,54,204,39,85,103,6,211,58,191,119,93,92,119,26,187,2,168,14,45,103,143,187,134,111,104,82,205,
+4,114,30,6,149,189,154,227,206,29,123,187,195,253,225,23,222,225,38,245,221,250,174,69,185,21,201,254,12,172,
+180,163,1,127,20,78,20,136,33,252,97,195,73,20,12,37,196,10,158,163,119,146,165,17,179,101,9,246,71,130,
+56,120,156,191,234,78,154,33,203,189,211,227,249,231,50,154,110,215,106,60,35,49,113,58,215,174,20,169,19,56,
+69,224,33,31,30,159,75,172,242,30,116,23,176,152,71,12,124,223,70,140,245,36,176,12,200,3,196,175,136,199,
+166,211,54,198,144,157,198,62,250,139,197,93,29,147,61,122,136,69,101,247,212,112,24,160,32,55,98,30,111,28,
+130,107,31,55,36,49,224,185,168,210,153,135,112,174,46,27,141,110,26,125,167,154,39,21,50,119,194,217,110,240,
+49,155,78,97,127,133,6,128,42,249,66,24,119,94,113,239,46,99,21,195,39,144,241,190,3,93,216,13,230,235,
+227,176,233,71,175,48,211,24,119,119,85,32,198,96,44,102,110,158,194,162,207,102,38,222,91,86,242,7,116,215,
+130,201,94,246,71,40,151,203,243,23,145,59,119,145,21,249,70,53,120,43,92,242,13,81,85,195,67,182,102,180,
+215,58,180,103,47,50,191,25,235,217,233,171,61,114,177,166,148,140,178,182,70,173,207,112,171,63,116,146,84,20,
+154,217,72,54,204,199,238,196,41,139,52,169,81,217,248,41,167,147,221,61,114,51,238,43,195,192,140,162,156,217,
+63,231,128,92,84,198,120,165,226,148,169,203,130,7,180,196,206,140,207,172,85,35,19,171,250,183,161,104,63,13,
+82,115,187,121,102,47,63,160,169,250,53,28,41,94,121,209,115,211,158,103,199,120,214,144,86,43,131,56,75,196,
+84,90,79,156,124,199,100,81,49,33,69,165,209,201,208,222,41,182,59,76,191,162,191,224,114,192,224,245,226,164,
+130,59,137,119,89,102,78,226,106,24,150,116,177,29,99,203,26,218,10,33,34,138,85,152,21,250,162,184,136,141,
+12,51,106,195,246,30,97,191,111,172,166,131,13,220,202,0,113,225,18,148,31,242,12,57,127,24,187,46,37,70,
+93,108,210,186,49,75,108,148,49,83,2,146,95,138,209,137,23,120,245,44,147,221,71,185,91,249,165,141,168,19,
+226,28,179,156,123,75,59,78,58,187,166,114,183,99,27,219,82,182,112,63,98,96,100,208,13,153,135,247,46,30,
+221,99,130,54,234,252,110,114,102,0,71,229,177,93,1,146,90,171,224,48,4,104,58,114,145,201,145,225,47,124,
+78,150,221,202,139,188,189,253,24,234,105,238,27,56,50,93,91,189,123,103,135,45,43,137,119,251,50,18,56,46,
+125,52,30,143,147,189,95,7,15,127,188,136,35,251,66,145,161,194,119,185,152,160,169,103,120,145,130,178,102,162,
+170,67,212,96,173,43,129,22,188,248,168,151,153,111,34,47,42,58,191,108,201,132,88,69,171,5,123,216,79,69,
+169,122,210,9,142,102,58,48,201,200,20,118,121,43,181,227,115,50,41,187,184,87,77,138,42,173,146,78,38,181,
+186,38,177,253,1,32,197,145,225,184,121,194,199,231,4,14,181,14,103,226,254,140,120,158,238,115,227,247,105,132,
+43,19,64,21,183,176,152,190,126,200,51,247,163,88,201,215,19,89,67,119,129,111,247,142,124,84,38,208,66,54,
+94,125,231,88,57,238,125,95,159,220,245,90,133,36,19,209,74,148,99,124,60,29,199,222,73,83,59,117,118,199,
+228,178,15,250,206,188,36,51,183,108,35,220,83,193,21,238,171,130,180,7,152,52,57,9,112,15,133,205,106,3,
+101,27,47,70,230,210,109,251,68,236,6,129,48,12,141,95,60,151,220,125,63,243,66,30,232,142,179,205,149,130,
+173,141,102,229,254,252,199,151,87,233,59,54,242,18,112,159,239,14,156,197,56,181,223,191,126,101,179,116,114,124,
+59,207,132,250,190,49,53,199,222,35,109,130,185,95,251,56,87,38,25,72,87,157,116,195,90,37,87,72,242,218,
+16,84,228,236,170,210,41,145,239,12,62,151,82,121,102,174,89,184,99,67,189,104,82,170,238,88,231,220,62,204,
+58,159,77,63,233,90,185,239,159,117,170,70,248,155,85,140,178,4,114,164,204,230,83,200,82,138,42,186,216,141,
+143,117,119,144,245,199,7,217,104,26,233,225,249,57,24,207,53,62,27,133,202,238,154,13,76,86,45,62,154,103,
+48,27,62,59,198,160,90,48,239,205,241,130,30,246,48,119,220,169,202,23,199,28,94,128,87,136,25,97,58,187,
+155,18,134,125,177,68,19,57,65,21,148,22,24,194,131,146,117,196,170,12,226,37,21,133,150,198,22,173,161,242,
+218,86,184,39,176,215,244,10,13,119,118,184,138,158,168,19,172,83,116,167,83,104,119,237,25,215,37,5,151,226,
+69,10,208,139,60,107,185,245,61,203,90,2,170,124,216,242,11,116,120,122,141,231,104,15,197,33,127,24,133,146,
+127,189,145,195,2,150,221,144,113,63,118,24,27,52,155,111,91,154,56,139,131,232,217,159,157,167,106,237,204,101,
+161,186,249,129,211,26,248,174,189,3,49,86,242,236,62,155,92,76,166,205,116,194,69,66,119,38,231,248,154,102,
+221,134,122,81,134,244,73,1,231,68,26,239,208,134,88,122,238,53,88,224,12,27,107,187,238,55,44,154,157,195,
+251,104,118,6,237,246,26,172,157,138,154,234,151,116,239,206,49,57,179,124,6,244,126,96,130,15,239,189,41,165,
+34,147,189,107,134,121,135,199,178,204,141,212,63,177,133,7,108,182,138,105,236,186,139,133,80,206,216,104,171,152,
+136,208,116,95,206,251,155,234,1,215,249,96,133,38,49,31,164,237,3,170,21,76,243,85,142,24,29,54,203,83,
+145,216,211,26,132,148,124,71,0,107,29,53,104,136,215,191,100,120,25,224,114,40,2,236,207,190,209,167,34,172,
+34,238,250,135,26,131,161,159,84,249,174,41,140,208,40,155,175,219,175,117,8,200,61,140,190,198,124,1,169,21,
+238,110,181,6,237,157,140,172,146,160,244,238,122,72,194,173,122,17,255,241,31,172,82,130,41,12,26,68,148,70,
+70,181,8,180,40,188,95,89,85,225,186,255,94,182,183,235,106,213,208,245,18,105,62,149,250,204,54,242,80,161,
+212,23,66,250,79,158,98,253,235,192,142,146,146,86,213,6,77,246,14,217,165,42,15,22,198,147,191,5,123,103,
+46,78,13,159,57,99,60,78,106,20,125,27,28,145,204,156,235,71,10,253,167,246,184,76,17,64,142,173,144,216,
+157,44,31,130,155,9,222,162,199,95,160,165,119,125,202,107,23,252,88,12,198,95,176,202,143,101,16,136,70,85,
+4,178,153,80,144,158,157,150,67,41,69,170,162,219,111,62,222,245,223,85,233,229,131,231,67,40,109,26,111,75,
+124,31,147,224,43,90,137,132,76,161,159,209,53,39,211,160,52,210,14,183,20,228,41,224,74,231,183,222,96,175,
+253,21,174,58,85,73,192,162,206,90,101,23,209,137,100,130,194,130,77,255,172,0,131,170,123,233,142,28,89,107,
+220,224,105,48,162,18,129,245,252,253,221,158,30,218,216,88,20,183,246,30,54,200,212,186,27,29,57,243,92,16,
+48,246,53,98,24,2,206,236,45,187,228,224,3,35,64,98,184,197,123,118,149,238,98,246,84,118,35,33,117,215,
+117,236,154,169,33,106,227,135,232,93,126,156,67,4,66,80,163,64,41,41,31,151,176,0,6,123,11,244,140,19,
+225,89,154,85,94,26,214,220,203,77,3,213,168,157,179,75,153,236,76,185,189,50,53,237,192,79,91,69,170,76,
+201,151,157,242,13,141,231,216,230,157,242,6,80,199,179,252,163,237,84,205,150,221,198,115,188,133,28,236,156,124,
+60,195,119,235,78,193,100,209,62,26,207,81,214,174,17,83,143,231,192,75,69,142,103,213,91,146,109,180,65,245,
+178,33,3,202,219,242,227,11,243,13,82,150,239,132,138,99,83,247,52,186,118,77,139,155,191,124,71,166,203,55,
+40,67,253,53,249,192,79,26,133,199,217,109,82,171,106,139,154,117,233,50,223,162,16,109,94,150,62,132,130,15,
+214,111,142,110,30,165,243,188,103,10,63,63,78,235,204,94,41,84,57,203,148,153,102,177,42,158,54,139,8,115,
+23,34,189,192,52,204,131,136,57,78,66,66,3,9,95,65,194,87,88,91,86,84,141,241,117,35,27,88,218,171,
+249,92,26,197,184,69,203,56,103,19,234,248,27,178,108,165,108,224,243,114,9,159,56,4,142,231,0,198,159,139,
+218,94,143,88,81,194,22,120,183,176,7,0,158,134,24,15,70,51,67,39,114,94,10,38,199,155,79,249,16,236,
+180,227,193,86,120,26,36,195,156,34,75,17,199,15,203,71,143,61,226,109,163,66,157,40,145,33,139,227,206,145,
+26,97,60,73,26,53,199,33,24,43,55,58,159,128,129,88,133,145,38,101,11,41,33,12,173,212,156,142,197,124,
+42,134,48,77,154,2,203,205,80,7,15,28,98,152,105,254,208,59,88,110,99,128,148,210,197,52,208,243,86,86,
+80,149,174,130,160,208,236,160,75,0,96,218,3,192,162,7,106,25,128,154,90,7,25,163,246,88,128,229,180,156,
+154,89,161,200,99,112,6,254,176,51,140,152,22,137,149,125,94,106,231,35,102,171,155,89,138,216,208,47,235,75,
+155,127,86,38,39,224,85,110,13,223,107,250,190,109,117,244,114,250,23,92,210,15,173,190,109,201,127,219,246,225,
+109,251,40,186,109,167,101,156,108,231,75,29,109,103,31,112,213,25,1,110,66,239,142,79,78,78,213,246,225,122,
+102,30,253,20,63,90,171,43,204,187,193,218,46,117,58,189,154,46,213,5,116,229,106,182,84,114,81,111,194,50,
+190,151,75,119,29,214,233,67,167,95,227,225,182,82,107,117,49,187,68,167,195,235,217,141,122,6,127,223,171,55,
+250,114,122,243,232,86,61,215,23,179,247,143,158,169,31,245,106,122,173,94,192,223,15,234,53,164,93,63,250,81,
+253,2,105,31,30,189,192,73,56,180,93,215,232,44,51,86,239,159,158,132,89,2,16,120,166,158,19,195,96,110,
+115,190,60,190,81,47,143,111,213,123,136,190,152,126,21,243,36,152,22,243,190,80,23,156,23,155,97,39,24,166,
+133,34,240,231,54,86,31,100,221,148,255,151,177,186,63,96,205,234,151,41,205,235,119,47,227,14,171,243,253,92,
+41,28,202,74,225,192,86,36,59,117,61,168,246,71,245,122,172,218,107,245,218,85,169,46,103,190,235,111,177,200,
+173,186,220,239,249,91,40,248,22,251,125,35,27,160,220,111,198,26,184,193,106,213,155,184,235,97,45,161,232,60,
+68,47,187,21,208,32,159,229,117,134,102,181,26,185,39,42,149,65,244,246,138,229,153,147,218,161,220,20,46,62,
+64,92,81,46,236,44,108,44,177,205,170,233,247,225,185,174,208,176,17,158,52,112,7,44,226,156,156,105,68,208,
+227,230,155,244,155,168,70,227,142,169,174,166,245,239,190,87,240,207,74,108,71,233,84,127,31,252,201,138,122,211,
+88,185,26,84,26,6,244,146,7,20,54,119,169,110,135,3,145,155,187,86,114,196,41,110,238,226,192,230,158,213,
+184,177,51,24,174,192,7,211,218,186,58,164,49,2,193,207,199,26,14,91,141,193,117,169,26,149,97,178,170,8,
+82,214,48,37,107,114,85,178,142,115,239,151,133,106,59,84,188,80,21,86,48,94,86,174,238,139,245,62,182,147,
+36,173,218,73,55,59,181,178,161,175,170,188,36,50,16,103,163,82,133,119,151,252,204,121,209,163,225,79,230,71,
+232,226,169,88,68,185,112,87,83,63,124,172,108,24,171,209,41,216,194,35,47,14,147,56,233,231,27,230,186,132,
+59,71,49,193,247,194,176,30,192,167,226,245,44,98,85,248,185,109,98,213,195,227,42,140,61,102,141,235,231,249,
+3,224,227,2,84,54,15,110,218,161,61,167,102,11,148,221,128,41,218,215,147,149,128,222,75,9,96,36,163,61,
+248,203,72,9,36,50,222,67,212,48,94,64,165,230,40,49,21,24,133,198,37,132,148,185,23,178,204,203,215,120,
+215,25,187,56,179,51,129,77,19,157,129,38,146,2,107,124,100,98,120,151,242,86,88,230,48,36,222,206,239,171,
+168,65,15,83,45,236,24,211,65,166,222,137,232,198,56,60,14,123,84,217,122,128,36,86,221,94,47,66,165,208,
+29,172,148,63,69,165,76,36,133,80,175,82,59,130,229,64,159,108,147,102,112,193,133,115,109,3,74,77,43,85,
+204,210,248,169,254,30,172,71,224,115,15,217,188,187,210,223,182,81,173,50,56,243,214,211,165,191,98,130,215,159,
+43,122,208,36,151,53,223,85,185,112,253,136,212,5,210,19,18,125,52,97,38,42,57,19,67,250,180,59,48,255,
+234,223,50,3,45,44,79,197,254,186,20,15,62,201,6,126,39,215,58,106,166,85,76,190,167,162,122,154,78,179,
+105,1,161,185,32,157,60,225,180,142,31,174,136,116,242,132,19,198,116,93,91,85,69,155,111,190,99,105,191,161,
+225,242,225,196,121,159,55,3,116,99,6,128,81,122,215,96,145,97,182,62,188,71,99,87,43,140,225,17,217,40,
+207,110,144,59,196,140,35,165,197,241,31,254,144,140,236,158,242,233,247,11,26,217,170,168,0,11,148,143,190,143,
+33,27,20,244,130,73,98,246,159,184,56,92,3,31,231,248,24,236,122,208,203,191,243,153,87,235,6,186,234,52,
+75,162,1,186,152,246,240,4,14,170,61,118,30,131,76,228,87,161,136,31,214,202,175,0,134,226,17,148,244,84,
+255,4,71,35,52,24,119,61,247,135,199,3,135,138,170,149,238,194,252,148,97,90,224,244,127,234,88,20,170,86,
+85,60,127,33,131,42,237,185,79,236,186,231,57,42,104,78,224,36,154,204,159,7,191,22,122,39,22,35,241,126,
+53,69,115,201,228,255,172,86,171,201,222,17,195,8,80,222,98,96,93,228,177,244,88,49,156,159,120,56,63,81,
+128,190,124,225,142,123,18,124,102,232,61,207,146,147,65,196,68,152,22,169,248,34,138,246,65,236,161,244,89,138,
+72,196,77,23,132,168,175,170,29,68,224,193,35,157,21,134,34,24,84,173,8,196,152,119,224,184,80,100,247,145,
+170,221,139,138,229,73,25,202,96,80,116,75,198,196,74,158,180,161,8,133,85,43,67,152,85,130,72,200,204,0,
+36,67,130,178,248,213,147,89,129,168,70,154,250,248,86,100,250,82,222,132,177,29,179,217,152,229,162,45,224,98,
+221,154,178,129,60,100,1,118,123,153,103,47,17,98,54,149,245,159,5,172,29,102,32,149,85,91,149,102,178,48,
+69,242,235,58,212,92,187,37,219,117,129,89,234,108,214,240,185,149,224,145,9,27,46,169,116,57,59,237,180,113,
+241,53,197,14,41,189,6,111,161,153,188,52,147,130,108,243,4,222,38,170,39,64,233,52,79,83,248,122,154,58,
+236,73,18,222,94,238,190,80,69,133,158,82,143,241,71,229,208,147,36,123,82,128,164,231,122,81,78,179,89,145,
+192,63,113,15,253,113,143,238,222,32,254,68,146,187,71,160,113,43,53,183,146,218,86,10,110,160,211,48,17,13,
+214,130,93,133,233,174,8,41,237,144,239,146,172,128,165,229,93,192,45,59,93,146,125,179,173,218,168,43,162,46,
+183,128,185,182,79,116,6,212,227,54,222,232,230,12,104,237,104,9,55,208,109,178,141,227,223,213,231,234,104,115,
+220,188,207,209,43,222,10,137,60,246,39,184,129,117,222,224,21,100,133,188,221,4,7,114,5,149,46,85,229,86,
+24,143,218,141,63,95,11,40,47,170,79,78,108,229,99,229,98,117,116,84,132,73,250,102,132,247,209,30,219,137,
+114,51,83,41,94,84,59,37,169,156,18,59,15,133,156,135,140,231,193,210,236,0,32,43,248,183,180,179,162,46,
+213,5,99,197,27,125,141,76,242,105,148,45,210,217,117,114,13,93,174,212,123,251,134,137,30,212,47,97,76,30,
+240,215,234,50,86,34,116,213,11,93,196,177,181,159,143,243,176,133,121,184,137,78,226,115,229,167,115,11,211,185,
+133,233,140,21,114,7,150,79,52,146,243,75,228,164,114,238,37,228,222,210,66,196,248,254,149,151,91,199,55,189,
+214,88,248,131,134,226,234,86,95,255,243,100,126,171,181,222,128,123,249,39,87,139,43,253,33,249,240,20,59,122,
+169,63,32,120,68,171,135,235,233,117,252,104,58,93,197,73,244,62,18,189,188,86,144,99,163,111,105,54,174,52,
+21,184,208,31,58,200,36,246,92,57,106,152,86,25,45,113,22,112,219,69,136,119,164,115,30,151,163,108,72,134,
+50,62,40,4,141,65,4,103,248,106,29,62,192,226,227,248,224,72,226,3,44,226,160,134,172,222,127,179,78,126,
+20,248,225,151,113,204,243,233,255,0,243,188,44,146,191,182,161,230,31,4,76,22,198,66,36,72,204,193,24,81,
+84,192,135,72,213,8,47,110,143,159,3,14,197,24,6,74,184,196,200,155,120,172,236,233,195,179,41,239,50,141,
+152,251,159,247,208,69,99,222,93,153,17,132,81,107,244,163,38,205,97,165,104,14,171,137,177,29,60,208,143,27,
+68,244,195,187,169,197,167,169,67,145,134,80,164,153,34,226,132,46,15,89,158,254,166,105,91,248,126,173,89,16,
+206,142,88,74,85,134,99,246,175,98,12,223,175,113,5,61,241,206,131,89,136,201,77,196,144,249,78,247,67,251,
+145,119,58,214,210,244,66,10,227,151,188,11,122,38,147,81,22,28,251,49,72,67,190,26,198,210,18,15,98,8,
+43,245,227,120,88,131,88,191,3,0,125,134,194,94,175,82,68,203,39,75,174,227,240,29,112,43,117,57,137,24,
+31,24,59,29,186,223,143,202,176,21,202,143,217,10,49,172,89,41,118,221,72,223,133,244,1,146,240,229,23,233,
+166,89,132,169,77,250,115,58,255,172,136,100,37,170,84,45,189,59,141,79,203,73,71,246,120,108,44,174,121,111,
+230,219,32,237,38,231,222,199,250,117,59,48,231,221,187,80,183,71,29,50,43,101,112,213,14,179,112,60,226,128,
+193,218,255,80,140,88,240,225,212,24,182,120,94,55,237,80,148,202,119,222,216,176,237,128,127,18,147,170,14,40,
+157,65,123,246,188,43,210,143,173,73,88,151,240,252,126,91,27,108,248,115,188,165,156,119,185,135,133,187,13,239,
+160,100,189,170,122,181,215,250,7,150,165,222,109,216,254,101,98,188,126,34,98,150,166,179,178,14,117,95,105,208,
+223,73,206,208,162,10,32,241,210,94,178,50,101,217,107,86,193,184,150,250,196,211,105,214,123,64,74,86,216,0,
+210,59,53,26,165,223,234,234,108,117,174,54,240,179,164,215,199,45,158,144,241,46,181,210,204,219,120,238,206,84,
+198,101,87,150,2,76,47,155,40,106,102,91,84,27,120,20,109,224,199,126,199,234,82,23,145,37,23,252,94,0,
+25,85,72,179,51,193,21,95,122,150,101,26,44,80,156,46,82,88,46,160,81,16,12,223,216,149,25,136,75,176,
+19,204,216,221,193,48,141,178,143,242,118,252,234,86,218,21,228,75,105,216,115,115,163,141,117,236,10,251,92,172,
+146,83,155,48,251,71,69,253,31,186,114,29,24,63,18,220,129,126,84,243,117,127,40,115,47,129,132,232,173,72,
+52,77,142,220,61,16,87,242,62,34,61,251,255,213,223,68,177,106,121,15,29,160,121,44,116,23,30,21,216,58,
+238,186,31,90,186,194,34,233,51,153,67,64,222,97,229,237,14,238,140,219,182,157,72,223,233,0,150,123,222,210,
+79,134,87,90,244,8,28,110,191,124,137,253,131,202,210,205,167,230,215,156,25,37,13,74,111,140,226,92,40,207,
+61,154,40,188,218,163,47,19,135,74,241,155,97,14,63,25,125,39,39,29,142,227,55,222,128,7,183,115,17,152,
+96,117,210,175,164,222,93,216,111,39,118,114,17,60,173,224,171,58,146,102,97,94,128,56,163,24,236,188,188,102,
+191,104,246,169,249,64,69,238,96,243,32,5,147,7,134,25,196,8,59,194,126,91,182,179,42,126,210,28,215,150,
+251,222,128,56,120,107,249,6,76,38,124,251,47,177,126,173,242,131,140,34,210,187,31,209,86,28,241,63,228,201,
+250,65,243,211,227,33,86,225,222,248,55,213,53,142,95,61,142,167,62,108,102,53,132,159,248,176,152,145,169,155,
+38,200,0,29,250,201,247,40,24,136,109,184,195,10,155,52,152,235,231,59,115,221,98,174,251,216,165,135,199,227,
+85,39,124,214,142,228,59,241,52,215,192,1,220,195,27,172,228,197,227,0,68,54,55,225,206,110,20,74,88,89,
+129,145,215,46,67,48,9,130,137,18,185,64,34,183,30,1,30,139,31,62,102,228,117,144,74,242,203,15,20,18,
+247,224,201,241,41,40,187,255,173,245,178,154,152,197,106,75,2,83,15,223,176,250,60,183,114,192,78,9,124,153,
+82,118,77,73,62,94,185,199,199,203,114,212,96,176,141,221,216,159,91,171,48,67,139,37,79,253,225,4,122,162,
+129,55,76,43,54,76,247,173,101,231,17,222,156,204,33,20,144,161,196,94,167,202,151,193,111,156,238,79,251,201,
+97,5,146,63,42,170,142,113,33,242,45,145,185,93,219,196,63,4,223,234,39,29,54,248,239,196,90,30,213,164,
+116,157,25,242,240,47,211,6,185,247,172,248,230,116,97,107,129,115,36,147,30,115,195,15,229,134,95,155,219,66,
+48,61,122,162,172,181,90,171,85,240,82,181,246,110,171,23,209,74,215,192,202,78,3,59,9,29,90,73,118,19,
+133,51,93,206,86,10,64,1,175,228,80,166,162,50,6,226,10,109,166,43,201,142,194,35,80,74,29,96,56,102,
+245,191,148,212,246,50,86,245,43,156,158,222,186,19,207,162,109,64,190,174,195,160,221,231,233,143,144,243,139,161,
+161,229,128,164,123,0,11,200,155,195,111,96,131,108,72,249,241,121,21,149,126,131,183,9,52,218,144,226,96,69,
+127,79,144,178,175,109,44,117,85,85,252,123,130,207,25,151,54,197,118,94,85,252,97,75,21,54,13,71,171,42,
+251,131,101,196,0,255,50,120,247,53,37,30,79,159,74,182,114,57,88,233,253,44,32,121,131,227,26,149,173,65,
+171,146,108,73,221,47,10,182,167,210,189,137,40,144,212,250,53,106,194,84,84,155,87,102,69,19,114,84,160,211,
+118,136,192,31,30,15,39,91,65,24,8,188,198,73,25,102,246,83,198,25,56,187,157,165,126,237,54,78,52,16,
+50,201,66,131,102,108,164,108,73,100,27,10,226,252,212,179,89,142,251,45,198,43,134,45,58,107,109,195,165,110,
+185,14,136,65,8,104,52,65,151,1,48,47,81,30,169,210,127,145,225,158,116,81,2,251,150,235,185,77,108,241,
+235,196,168,117,82,58,92,82,117,248,252,38,115,78,1,68,92,110,248,110,177,196,12,226,224,95,141,37,225,183,
+133,127,151,174,6,191,48,126,91,157,132,229,152,249,72,172,9,106,137,253,226,12,11,112,236,176,68,29,139,245,
+25,148,9,241,178,212,37,182,227,75,141,52,21,18,134,229,176,181,78,218,43,255,62,31,225,158,106,235,221,15,
+213,201,249,19,225,23,46,243,168,81,140,110,1,112,41,5,213,145,162,174,49,56,200,66,60,193,224,196,240,65,
+6,31,43,74,50,138,128,84,57,24,138,5,58,249,170,207,137,227,185,5,230,155,159,53,252,246,179,33,66,148,
+24,42,250,7,123,68,200,225,26,144,65,119,240,28,60,190,133,127,215,240,111,45,90,252,107,62,250,54,112,3,
+52,41,60,81,44,102,244,144,4,17,183,20,113,107,35,42,29,65,150,105,126,124,109,179,77,193,54,202,2,18,
+226,89,169,106,76,187,133,180,181,45,1,105,107,155,214,4,98,6,75,163,164,9,230,108,0,238,160,166,105,5,
+48,7,165,166,53,195,27,4,236,71,199,164,234,171,127,137,84,13,231,77,47,26,15,46,31,17,204,203,202,24,
+123,152,13,132,21,86,120,213,127,118,133,92,245,123,136,219,225,27,111,175,108,98,148,55,7,45,207,234,82,13,
+207,246,134,237,62,170,157,221,198,149,125,63,199,19,25,208,11,166,32,114,5,0,170,121,218,226,197,58,79,254,
+177,246,15,176,10,82,112,189,170,227,107,52,125,176,166,207,53,73,57,247,152,155,41,0,47,64,69,173,160,107,
+184,137,173,200,166,143,175,212,204,160,78,121,159,6,227,80,52,65,89,248,106,185,156,96,134,177,106,43,101,6,
+101,27,87,86,94,90,135,55,2,222,19,184,77,165,58,196,128,74,31,230,193,29,59,36,211,135,217,108,166,246,
+126,58,221,147,68,1,146,156,164,251,29,20,81,200,60,160,231,171,5,144,213,13,80,193,88,57,132,202,36,42,
+41,220,121,66,85,74,15,176,107,203,0,162,80,80,64,39,22,123,69,228,41,52,12,194,70,175,134,196,169,63,
+111,19,43,80,209,191,112,239,61,41,247,129,116,130,102,222,38,158,82,21,111,201,175,254,189,52,41,122,76,249,
+219,218,25,34,94,213,198,192,85,97,119,113,65,230,33,47,46,172,102,254,179,58,99,249,246,228,121,174,240,61,
+217,5,127,104,21,45,157,11,127,155,171,79,211,218,133,94,229,82,160,250,147,129,180,23,59,160,134,205,130,22,
+225,209,70,39,251,193,240,110,143,115,182,238,218,170,118,106,188,155,7,228,190,165,40,29,252,24,88,95,21,252,
+157,179,232,158,87,215,130,220,179,83,126,66,67,9,208,165,120,86,172,207,138,233,244,92,231,224,13,82,173,160,
+204,234,9,84,49,95,161,217,63,44,112,169,129,125,0,255,110,184,178,247,90,72,101,68,171,233,105,252,48,141,
+167,167,83,56,187,3,157,213,207,242,216,102,81,38,134,92,31,244,245,236,61,53,124,163,223,207,111,158,92,207,
+111,160,169,203,41,116,224,230,28,206,136,11,254,186,157,95,62,210,32,197,9,127,184,229,91,217,242,202,181,250,
+236,80,171,167,178,85,128,246,55,0,227,207,59,26,39,63,167,110,244,236,84,221,232,91,232,197,51,234,197,70,
+31,255,233,97,96,39,190,1,41,217,135,145,237,205,236,121,60,131,8,219,73,136,189,128,136,88,109,158,110,233,
+145,112,163,150,212,107,117,165,111,226,57,207,232,82,173,245,149,227,42,250,89,206,206,165,243,200,118,53,124,157,
+194,163,13,104,55,229,239,43,126,177,236,44,92,226,106,95,216,21,85,55,80,97,139,179,118,13,31,23,240,49,
+187,177,107,170,91,244,36,60,69,37,239,26,152,167,58,183,54,175,163,20,179,196,143,174,31,150,228,194,243,150,
+43,253,160,139,127,146,88,204,7,50,233,156,61,129,55,201,141,206,0,30,234,56,201,158,94,193,32,175,32,184,
+132,32,41,251,62,108,166,80,19,62,77,86,210,62,235,173,174,103,167,196,39,254,38,90,1,90,135,159,101,236,
+32,91,44,20,140,41,86,111,194,221,8,195,243,103,112,26,192,108,226,207,237,127,252,199,165,101,203,190,206,163,
+207,243,8,157,84,158,61,59,143,113,25,155,46,134,178,54,239,155,67,121,223,132,188,93,253,20,196,82,111,177,
+128,207,153,159,221,66,6,14,164,228,92,149,102,125,163,175,104,208,75,189,213,181,183,197,122,25,150,171,168,217,
+33,175,124,24,149,111,172,244,4,228,253,212,136,76,42,196,97,22,53,166,186,114,11,176,48,193,212,137,218,161,
+118,6,27,239,10,50,28,13,182,126,200,91,43,90,116,44,144,16,145,238,147,205,42,92,172,165,241,29,194,5,
+100,213,120,206,36,1,25,114,36,134,30,60,195,147,152,45,172,76,146,42,248,126,78,157,92,38,5,70,185,64,
+214,233,10,15,29,212,47,255,20,81,107,19,245,36,8,74,13,231,215,43,36,67,43,114,37,172,106,224,32,87,
+120,59,156,157,198,177,202,22,205,48,67,26,3,167,3,54,44,234,40,206,202,164,209,102,86,58,102,118,201,246,
+249,154,142,92,90,149,43,141,182,196,39,60,189,248,110,169,130,194,79,90,188,131,35,175,93,95,33,103,183,156,
+65,167,39,138,238,142,108,25,101,204,58,106,18,124,143,34,252,154,99,46,16,239,112,214,189,243,14,79,158,178,
+19,154,225,98,12,13,223,177,138,26,166,195,140,122,243,203,40,246,128,230,221,243,125,149,82,149,105,148,93,161,
+42,113,43,93,154,232,44,85,225,138,235,235,56,143,201,89,51,24,240,43,216,94,52,243,200,251,111,51,107,157,
+7,71,182,108,107,134,30,86,214,189,82,105,13,108,224,16,213,230,87,6,106,14,205,34,155,21,245,17,185,238,
+194,248,231,27,94,153,101,167,205,138,148,60,189,198,132,57,110,215,181,105,214,85,177,252,231,63,255,248,144,78,
+51,144,151,216,198,8,167,141,159,83,20,37,199,91,139,221,25,58,115,91,165,57,190,99,167,52,126,167,120,7,
+205,204,235,14,90,78,24,130,249,77,220,110,24,190,1,250,205,217,169,70,102,187,178,47,149,220,159,171,174,139,
+237,137,186,153,55,215,121,11,171,107,142,61,136,193,214,66,42,171,104,219,203,73,178,209,112,164,103,132,178,17,
+136,231,151,181,73,223,207,49,131,7,68,200,211,174,92,30,151,131,65,55,25,234,17,255,253,251,18,46,21,27,
+178,158,243,32,192,250,3,223,250,131,223,127,178,19,157,233,126,255,247,184,147,3,211,27,64,6,202,25,242,200,
+25,152,59,193,121,107,6,8,34,63,108,59,199,160,92,193,136,157,158,133,57,150,198,142,132,238,206,234,176,0,
+10,146,219,140,132,62,183,46,210,0,154,160,105,101,124,123,193,157,1,161,19,48,247,58,100,179,198,170,36,133,
+85,160,148,248,114,188,56,58,77,40,238,100,49,129,57,1,218,127,146,148,66,36,102,53,228,149,81,31,17,48,
+127,141,74,239,16,220,42,56,148,214,237,89,76,117,178,105,40,122,109,120,81,84,105,27,133,59,247,39,17,218,
+3,20,212,7,233,209,54,139,40,42,173,13,212,201,12,246,146,251,158,78,172,103,210,118,218,224,97,170,145,139,
+78,2,172,13,16,122,216,22,218,178,226,206,59,217,99,43,118,108,67,217,123,252,93,167,27,144,42,246,86,150,
+203,248,41,106,95,136,161,166,97,242,173,211,245,164,133,11,182,125,161,50,128,229,121,242,137,156,109,252,18,67,
+119,184,197,69,96,6,37,24,141,29,176,145,200,187,68,39,145,24,64,104,33,247,41,160,223,249,3,206,86,100,
+120,214,18,74,67,243,40,148,78,75,216,143,194,103,193,79,208,57,38,78,6,0,214,151,254,158,18,217,211,123,
+81,178,81,44,252,132,15,180,253,67,49,124,27,207,234,81,199,207,55,186,245,60,119,248,188,165,79,190,145,250,
+135,137,145,39,93,127,213,106,240,54,228,88,0,117,223,189,17,61,206,50,234,179,210,138,223,119,170,37,77,15,
+50,138,162,240,228,88,194,95,202,66,10,35,71,248,112,128,7,164,124,162,223,191,218,113,123,13,223,177,43,232,
+42,9,205,142,10,127,87,241,195,166,47,252,77,49,172,36,32,185,74,197,62,28,4,32,64,142,159,20,13,192,
+245,121,133,182,253,131,101,46,85,33,193,137,174,228,88,36,111,209,34,205,150,180,72,201,169,84,198,99,76,66,
+169,4,92,68,191,226,214,146,80,181,214,181,7,39,12,165,4,74,240,193,112,147,172,3,148,88,128,138,21,120,
+9,173,243,165,149,168,46,210,218,187,217,183,57,233,186,229,164,221,61,24,18,219,20,49,105,86,71,48,117,25,
+64,196,45,252,189,117,211,76,69,159,179,46,197,139,186,186,178,215,110,95,126,29,119,172,5,37,52,160,42,75,
+49,222,209,108,161,214,113,240,102,26,86,33,91,5,174,90,196,7,50,57,201,63,88,213,130,22,46,161,109,28,
+234,249,174,116,8,12,251,54,111,159,230,243,118,54,11,232,204,56,203,104,14,133,221,0,178,241,129,219,56,166,
+3,199,123,25,8,21,175,87,131,23,24,205,91,175,164,143,142,125,197,11,121,78,132,11,255,88,229,37,27,2,
+5,52,16,222,69,106,40,213,208,127,188,218,52,177,151,187,111,240,102,146,105,114,201,80,30,49,22,143,120,166,
+161,35,5,174,28,238,124,21,226,50,23,23,39,134,139,0,126,241,233,184,161,160,220,109,40,195,113,25,198,197,
+24,29,6,190,26,217,31,136,85,177,4,18,70,244,10,161,172,113,1,93,250,113,226,142,112,51,145,234,229,202,
+218,158,96,97,146,53,193,28,79,160,195,162,157,42,227,161,98,93,229,201,241,224,77,36,211,21,24,2,242,25,
+215,58,179,184,4,20,199,224,19,38,115,190,134,204,219,21,10,64,227,157,61,245,146,43,8,238,63,180,209,190,
+100,242,174,147,119,130,101,255,200,199,145,177,15,95,64,38,217,26,168,60,62,219,173,137,62,38,42,125,135,224,
+138,138,238,106,188,113,83,233,7,165,116,62,106,189,181,142,54,182,36,78,197,86,224,208,112,245,182,108,214,249,
+170,133,92,76,55,248,17,152,208,203,237,240,168,134,126,14,250,96,70,251,96,160,15,106,135,98,90,8,124,69,
+10,63,169,229,27,161,210,249,59,232,156,125,60,183,2,77,244,150,82,3,27,61,166,123,93,29,151,190,123,133,
+245,61,242,0,162,115,187,174,5,32,243,148,183,80,151,123,123,216,242,53,14,234,223,123,141,27,74,102,245,140,
+42,192,139,175,23,193,179,146,89,185,4,178,156,129,204,190,97,162,136,76,1,127,164,7,135,121,22,192,40,11,
+19,177,6,48,202,144,163,3,64,194,2,103,88,253,18,195,8,69,24,194,142,192,115,64,163,240,2,142,108,2,
+36,71,86,170,160,223,229,156,7,202,253,180,51,154,218,25,45,120,70,75,113,210,108,196,78,34,81,77,127,210,
+132,141,132,45,126,18,25,79,105,53,188,113,194,41,129,244,141,75,197,189,233,211,152,230,241,78,142,253,180,101,
+148,203,85,248,192,217,117,168,86,128,251,23,77,178,70,241,114,185,68,107,126,108,46,140,135,126,152,81,46,255,
+5,212,181,64,106,19,237,231,1,254,53,154,49,163,114,208,182,24,108,51,193,62,15,242,61,202,138,79,150,202,
+203,78,6,226,197,119,228,202,195,138,133,105,228,229,88,194,216,193,50,68,176,153,47,186,148,250,89,163,245,159,
+55,108,92,54,56,219,104,216,217,70,76,151,88,164,75,67,17,136,177,110,116,213,81,237,205,102,98,108,176,65,
+236,243,50,218,36,2,181,166,46,117,174,132,208,22,105,184,251,67,9,231,82,57,12,228,52,142,43,18,233,199,
+105,150,82,204,123,66,207,101,95,50,176,80,166,36,70,67,138,122,29,128,20,213,10,126,224,8,65,202,162,137,
+207,231,149,208,114,88,195,153,176,70,45,135,10,154,241,186,171,156,224,53,108,68,198,88,213,116,167,144,132,96,
+174,82,86,66,168,59,72,95,244,228,168,19,95,197,138,170,236,124,184,61,102,169,80,140,191,223,224,68,234,117,
+97,105,157,28,38,224,43,70,123,150,35,22,48,240,51,151,158,182,137,182,155,208,213,97,213,226,210,84,248,91,
+197,177,16,218,204,123,66,155,149,212,95,105,246,229,9,64,218,102,1,93,65,180,208,194,31,24,224,2,3,73,
+187,192,96,114,18,74,95,14,177,154,68,82,141,71,82,170,10,228,1,114,165,71,214,183,48,251,171,59,207,180,
+95,84,207,181,128,73,50,138,22,189,65,60,150,146,158,142,69,157,129,218,128,177,240,1,223,84,219,58,67,173,
+87,123,141,76,214,110,38,176,6,108,8,107,233,246,164,71,87,36,249,170,214,18,20,151,216,213,149,27,234,214,
+246,4,196,81,25,139,210,39,34,80,181,180,125,82,27,253,75,69,6,120,182,178,154,43,172,102,19,15,58,120,
+229,58,184,228,14,146,28,29,172,206,90,109,253,101,207,49,70,227,14,187,222,207,2,17,46,67,94,198,120,176,
+123,22,115,88,175,139,254,122,237,200,74,52,63,82,211,174,180,38,167,130,225,41,1,67,149,26,104,93,17,161,
+58,175,232,249,7,225,111,168,229,78,207,187,53,106,248,207,106,213,204,202,0,242,177,80,13,106,198,84,131,228,
+201,136,73,115,120,212,246,187,10,37,167,154,158,126,218,47,141,36,82,233,80,49,110,62,75,229,71,208,168,140,
+94,118,42,101,9,58,188,194,169,84,3,16,211,83,139,88,36,183,42,133,171,37,227,193,175,105,240,43,244,201,
+146,6,164,132,207,78,123,175,75,75,93,117,26,40,44,93,168,173,46,17,37,3,39,221,61,120,230,226,149,113,
+169,104,89,106,5,140,104,128,169,6,153,251,241,64,175,131,193,127,3,152,201,12,48,83,97,153,80,87,36,20,
+29,239,54,3,228,68,19,92,170,85,216,67,151,80,73,57,168,36,99,244,182,241,10,86,104,213,125,14,234,95,
+192,28,87,32,76,194,213,192,246,25,152,160,224,161,68,87,11,255,192,154,76,202,170,252,213,212,213,4,83,195,
+187,105,88,176,155,213,93,11,150,94,98,87,26,5,247,205,234,26,86,43,69,171,104,53,47,26,171,251,25,43,
+20,189,96,244,151,180,196,43,14,19,92,56,176,172,96,230,209,207,253,151,118,0,53,178,41,98,69,16,51,108,
+152,193,163,113,45,5,200,41,186,222,72,148,111,198,215,202,2,19,119,215,92,221,91,179,16,223,202,135,168,21,
+232,168,54,182,85,251,62,86,10,135,237,32,185,145,30,66,105,89,232,53,103,40,132,184,179,19,188,214,25,79,
+241,74,103,0,166,184,157,209,154,217,64,176,28,230,238,22,251,98,98,133,203,230,59,48,88,174,181,171,203,46,
+151,25,118,48,86,31,160,150,56,38,62,253,45,243,233,177,139,40,97,61,226,167,100,56,250,104,192,82,151,178,
+231,116,13,219,51,139,137,26,221,53,249,83,169,227,106,159,129,89,163,80,130,191,106,168,130,133,104,96,15,186,
+89,132,79,73,53,254,128,150,136,11,237,45,78,143,48,61,235,216,217,102,180,20,110,189,138,82,232,81,25,179,
+35,211,220,206,134,180,187,185,199,192,247,75,123,252,1,223,94,152,72,78,233,210,250,137,157,48,93,168,198,221,
+60,246,134,202,87,103,123,131,41,8,10,172,245,62,232,61,7,129,192,108,136,37,133,96,152,190,131,217,134,117,
+81,193,131,199,112,238,13,217,251,127,155,95,17,189,29,242,77,240,140,191,199,144,59,94,92,194,121,226,47,40,
+181,110,130,191,135,218,250,123,168,93,139,41,13,193,141,118,142,190,215,163,148,208,255,241,152,118,84,165,82,218,
+253,177,2,232,197,125,67,174,29,82,85,193,168,252,176,24,108,228,240,0,97,134,145,225,235,198,126,214,193,163,
+73,121,239,112,197,85,180,12,3,108,236,0,155,254,141,216,15,176,18,221,174,148,152,174,189,254,143,173,14,112,
+214,160,237,48,91,164,6,134,1,230,129,143,143,209,87,7,44,104,223,120,217,111,92,188,157,121,72,193,199,19,
+87,95,50,82,91,231,238,173,63,52,26,123,138,252,29,36,238,192,233,212,151,236,26,92,183,10,66,86,188,3,
+186,143,215,63,47,199,176,133,115,197,203,114,160,141,100,41,121,219,194,10,75,73,218,22,137,220,80,149,18,109,
+40,116,174,207,129,96,4,72,25,156,209,15,43,215,179,220,115,137,90,255,149,239,89,141,239,69,96,134,220,167,
+208,215,220,178,157,127,110,62,86,8,236,34,93,46,133,94,75,97,222,65,169,47,243,22,252,237,145,123,53,206,
+69,194,216,102,249,18,70,34,172,183,46,171,237,187,117,185,109,81,197,196,87,65,139,230,200,183,190,164,89,235,
+190,130,225,243,22,255,202,182,177,137,129,229,156,170,216,94,149,232,60,189,31,239,197,222,251,209,87,41,207,252,
+48,150,242,202,72,60,127,101,152,79,206,126,35,102,213,175,168,150,85,11,217,162,123,196,227,46,174,200,196,136,
+236,106,112,119,214,47,187,95,29,94,208,113,252,61,51,205,94,232,171,63,190,118,56,11,102,208,129,82,121,151,
+6,249,149,229,6,244,253,38,58,238,58,183,157,163,27,202,65,110,106,115,240,30,178,136,196,208,123,125,18,51,
+41,187,98,163,228,172,134,10,226,36,146,115,219,31,146,95,188,126,117,24,211,91,71,81,67,220,201,161,141,171,
+54,88,151,193,82,69,228,175,196,71,47,77,13,179,109,139,170,179,0,227,118,111,88,223,137,206,171,32,161,9,
+239,58,186,212,79,91,255,45,118,7,237,98,244,38,104,125,112,115,33,252,116,238,167,109,2,6,70,139,201,94,
+51,149,140,239,147,252,25,197,251,27,202,116,184,144,125,11,58,3,39,8,124,113,93,230,13,218,5,142,119,114,
+57,197,90,156,12,5,13,90,158,56,228,188,67,151,129,189,94,182,120,214,90,29,22,229,20,7,179,234,106,179,
+109,205,219,188,45,140,93,199,72,162,204,84,162,201,162,211,63,160,37,232,42,232,106,26,170,23,43,109,107,224,
+255,170,81,8,204,6,128,183,230,182,97,236,175,171,235,38,170,149,181,219,52,61,61,1,8,91,15,225,42,11,
+217,129,60,237,103,151,27,219,227,253,76,181,190,49,171,104,228,131,177,68,14,161,4,108,134,208,32,23,241,225,
+184,243,61,29,88,88,195,101,170,148,171,59,169,3,67,143,230,30,79,69,107,141,25,168,51,39,2,91,232,3,
+40,61,211,67,252,9,239,190,200,191,154,166,236,78,191,5,246,26,58,173,176,134,144,38,184,79,39,202,70,225,
+171,23,150,212,147,43,224,150,23,108,3,126,137,114,106,91,61,243,186,191,67,0,12,143,46,27,117,21,172,150,
+95,234,114,10,162,250,211,10,8,135,20,221,185,190,133,38,162,13,181,20,179,0,75,116,101,45,42,101,103,153,
+39,99,206,167,151,211,199,15,211,167,36,150,177,154,234,181,18,169,209,21,88,186,60,73,78,227,115,125,162,182,
+152,184,156,78,99,85,156,93,157,107,171,221,114,66,218,45,91,85,195,45,97,201,218,59,151,193,147,157,234,55,
+165,47,167,72,243,174,58,15,24,163,171,227,151,241,95,95,158,193,177,135,177,107,93,207,90,94,158,84,45,113,
+100,40,14,70,198,53,78,238,159,245,75,117,17,102,253,102,116,214,47,123,179,126,129,50,105,219,105,67,211,188,
+182,179,188,156,166,42,99,102,145,157,180,165,155,180,45,76,208,198,230,184,154,78,161,127,208,59,156,242,11,55,
+229,27,158,114,24,86,114,197,83,126,35,166,124,25,100,237,150,234,38,198,117,107,236,180,67,173,119,181,186,234,
+210,229,47,219,166,117,83,24,89,206,178,196,145,30,167,13,189,194,221,129,152,250,235,34,89,232,41,25,164,42,
+213,96,105,113,16,117,139,210,206,222,176,119,99,162,42,28,126,2,131,16,147,112,4,131,89,54,187,117,112,80,
+33,250,247,133,167,141,56,40,103,253,253,139,15,147,146,173,151,33,91,207,196,41,208,145,217,49,128,56,154,188,
+180,95,191,189,218,88,101,164,249,98,231,10,191,176,76,102,79,243,26,127,208,110,246,171,182,6,30,253,77,84,
+64,118,30,161,42,166,154,191,167,77,135,175,84,195,177,201,26,229,185,61,27,128,63,246,131,241,232,200,40,51,
+204,9,35,77,121,148,16,250,87,26,224,241,234,130,199,200,3,199,207,59,198,109,227,7,131,231,42,97,244,157,
+92,101,33,226,37,65,84,186,190,133,14,192,85,232,96,178,29,197,132,253,117,34,180,143,2,123,32,114,152,216,
+158,3,243,164,237,249,194,181,53,32,59,4,21,223,56,184,79,35,248,153,194,125,16,224,35,41,145,124,240,226,
+32,188,49,42,187,49,60,39,232,75,156,233,170,86,5,110,135,246,24,182,200,248,150,80,25,146,15,53,147,15,
+59,203,166,90,43,183,187,86,157,174,213,82,103,150,168,216,234,229,163,199,44,241,230,189,154,210,14,134,225,52,
+226,236,42,194,119,100,207,49,76,31,61,200,148,128,125,144,178,86,141,165,56,50,166,56,44,214,8,4,203,149,
+184,227,93,74,226,229,130,136,23,232,108,172,110,180,151,216,123,70,118,135,113,177,172,168,195,21,16,142,87,228,
+194,212,134,47,33,124,25,12,2,54,204,214,99,92,245,35,136,160,61,15,221,83,167,132,65,26,193,186,197,116,
+31,82,41,142,50,152,157,123,238,190,149,53,64,64,169,67,203,113,207,7,81,234,4,179,9,51,113,207,125,64,
+177,61,130,184,55,103,63,170,102,96,248,237,185,15,251,78,73,227,118,178,77,117,134,200,166,238,223,186,29,12,
+191,208,59,22,138,185,178,194,239,111,254,250,250,237,227,71,143,165,178,197,243,227,16,240,26,193,16,235,62,123,
+170,28,63,118,234,53,192,198,13,56,124,104,96,105,174,80,115,240,23,253,102,186,157,103,121,212,168,23,234,181,
+250,37,182,88,139,123,0,137,254,128,138,150,32,118,15,173,159,196,88,139,64,6,88,21,86,84,26,24,89,207,
+138,250,188,145,60,116,150,24,181,242,68,77,244,75,108,189,140,192,50,60,53,100,141,27,213,146,172,225,212,215,
+234,54,121,161,174,1,220,144,68,225,89,248,165,139,147,198,190,106,188,134,206,2,40,226,212,178,126,208,143,88,
+1,242,78,189,73,165,70,112,117,213,251,61,152,252,4,223,215,159,211,166,80,16,53,189,128,161,101,106,135,96,
+255,222,180,235,26,111,249,201,115,150,142,80,126,63,37,114,111,61,15,223,40,221,173,174,245,200,241,166,62,220,
+113,228,206,175,23,27,141,42,63,173,60,52,167,43,121,64,161,128,34,26,99,247,152,29,141,127,19,83,242,164,
+75,168,180,44,120,43,234,194,204,31,32,78,30,3,6,106,115,120,223,213,162,190,172,34,239,146,181,165,65,61,
+207,107,67,243,21,123,45,143,139,233,106,126,144,214,194,105,69,90,171,191,25,158,17,54,65,174,55,200,78,175,
+121,181,198,146,184,145,231,186,233,81,103,207,36,117,166,126,236,33,182,103,254,27,24,110,50,164,107,177,44,177,
+122,161,175,166,219,233,115,194,155,175,53,26,221,251,5,254,222,206,11,220,149,180,49,34,137,144,175,23,111,144,
+8,124,61,125,49,93,61,245,171,128,215,85,42,54,213,183,106,67,251,23,8,62,170,78,223,189,118,54,51,108,
+243,132,234,253,101,122,251,84,44,7,84,107,43,121,61,53,46,43,211,15,43,223,142,237,176,190,111,93,109,118,
+191,184,222,95,125,139,123,62,122,29,207,111,96,175,169,95,212,51,220,192,23,41,154,82,159,194,212,192,136,97,
+176,73,232,180,162,243,42,86,239,35,91,142,138,64,46,232,230,84,195,172,36,118,26,58,216,116,119,128,77,23,
+14,167,193,161,44,197,141,91,204,160,74,60,4,13,31,130,141,46,48,192,71,160,125,89,54,227,196,108,117,223,
+233,90,107,223,191,84,27,79,79,224,99,3,29,169,184,231,181,157,207,194,170,97,169,149,14,85,45,117,168,236,
+16,241,26,72,120,20,57,26,16,147,177,90,7,26,50,131,186,43,84,184,37,146,65,245,224,100,25,75,125,157,
+205,240,50,132,184,108,185,205,76,20,33,214,211,79,125,147,16,244,155,249,36,158,175,117,54,21,77,184,166,123,
+128,178,153,57,222,133,155,227,217,97,252,228,44,211,109,177,231,41,244,121,69,6,159,197,102,171,196,150,220,150,
+81,74,231,217,56,169,81,247,141,232,50,137,100,229,88,134,113,68,133,148,142,239,1,200,186,86,198,34,235,173,
+90,163,216,208,104,119,71,1,141,129,204,32,144,181,12,100,37,2,89,235,129,204,95,37,29,156,45,12,174,34,
+215,59,45,121,142,1,85,94,160,36,174,199,127,207,218,200,203,9,33,219,170,98,201,45,134,194,1,171,15,174,
+237,144,102,70,151,37,182,146,163,213,216,253,88,149,112,217,45,131,52,217,116,90,198,72,8,233,234,172,60,87,
+212,28,183,197,40,200,193,63,183,103,27,179,64,216,120,244,112,224,246,12,85,118,156,68,82,81,210,191,147,16,
+78,28,26,193,59,186,118,14,139,148,113,117,247,125,255,14,102,206,107,158,199,243,125,95,71,228,103,79,8,36,
+12,217,241,170,210,31,96,2,88,50,225,168,66,103,78,230,184,42,95,25,160,31,209,153,83,35,157,57,141,177,
+243,85,233,203,73,39,81,165,44,215,145,152,97,201,153,130,167,40,153,73,190,170,95,243,171,186,179,233,21,229,
+253,1,161,62,181,107,12,110,58,174,191,49,126,115,245,144,133,10,101,24,128,235,80,168,97,187,153,240,227,237,
+123,126,188,181,139,54,81,23,206,65,221,207,236,157,97,95,38,200,102,37,91,154,63,55,17,177,110,248,181,203,
+91,21,231,7,82,52,73,214,30,59,221,29,131,175,235,100,109,132,92,24,1,52,98,68,220,41,180,220,68,146,
+211,206,59,145,77,114,45,121,223,153,46,194,61,163,141,191,45,187,92,163,77,151,254,37,197,116,246,161,218,85,
+226,183,123,168,160,29,114,243,143,135,124,18,174,195,2,52,45,23,14,1,247,60,204,54,87,115,220,3,122,235,
+196,173,247,26,199,88,2,223,226,220,153,146,208,5,86,165,125,195,221,238,17,3,115,122,201,142,83,117,109,209,
+201,169,249,131,226,133,31,76,201,224,209,75,193,224,45,59,124,222,236,191,122,147,170,6,82,170,248,169,90,239,
+215,25,216,189,16,143,238,147,251,241,167,48,22,6,67,43,12,205,128,104,3,124,145,229,187,40,154,37,179,45,
+123,116,74,9,225,5,241,143,39,254,186,122,122,162,250,47,7,114,141,6,242,3,202,115,9,123,151,159,196,200,
+235,141,36,188,189,244,80,215,249,245,118,125,10,239,151,23,254,121,184,255,46,76,30,37,107,225,56,178,150,50,
+0,88,8,27,140,204,226,196,121,168,86,5,158,17,169,180,213,227,117,244,177,87,73,123,198,222,48,207,237,121,
+170,252,57,150,236,203,124,120,98,55,169,148,115,103,238,5,60,21,95,84,147,116,104,41,221,93,20,125,10,6,
+84,255,202,26,210,124,148,114,119,86,159,134,129,80,165,93,185,168,96,82,179,112,135,194,163,63,42,113,68,251,
+194,118,8,114,93,208,186,205,216,205,51,245,55,79,185,114,152,219,7,135,246,4,36,156,39,60,163,93,231,144,
+171,162,195,251,94,104,244,27,242,212,111,200,176,9,105,181,38,19,168,76,216,226,75,164,45,62,172,248,40,183,
+130,132,205,143,57,92,9,38,85,57,137,253,94,24,102,61,155,244,225,124,162,38,246,197,11,62,240,13,107,114,
+30,60,62,162,94,95,199,79,212,207,203,251,159,168,255,197,7,229,11,222,140,255,254,55,223,251,237,159,252,235,
+207,187,119,91,218,13,29,13,227,130,207,163,242,222,247,59,49,34,57,1,254,89,79,22,19,89,253,40,135,5,
+141,151,114,255,34,42,237,37,117,97,127,153,72,75,78,231,189,229,64,92,82,6,122,211,223,95,30,134,215,67,
+73,113,246,202,114,7,230,99,175,127,178,131,85,34,134,81,117,50,231,56,105,28,86,203,19,192,130,19,43,185,
+174,196,37,125,86,191,107,162,86,202,174,26,133,171,33,68,88,217,116,90,229,9,139,154,249,164,136,112,233,108,
+116,54,48,250,70,223,70,31,54,215,246,210,129,47,162,106,165,205,20,223,42,171,89,9,167,90,45,89,195,150,
+195,137,217,75,200,178,178,133,26,178,118,166,127,122,56,59,254,83,156,96,85,51,159,102,84,99,211,32,9,239,
+127,51,200,186,35,60,243,83,178,86,244,241,115,178,10,15,143,89,192,111,69,231,24,208,67,62,179,26,210,196,
+135,175,173,189,235,110,165,75,177,240,143,30,15,150,30,102,217,247,173,118,125,75,67,223,10,223,55,239,180,38,
+172,85,21,207,225,230,212,186,155,211,9,252,87,58,38,51,95,181,198,107,18,200,27,238,116,198,174,92,172,228,
+181,46,241,215,58,231,125,5,75,158,213,42,61,239,25,71,248,122,160,213,132,52,232,243,114,140,6,109,15,211,
+160,70,181,125,26,148,164,249,105,54,62,45,170,236,189,54,68,25,63,99,202,152,18,4,97,252,188,236,19,198,
+212,39,19,200,88,191,152,178,206,249,128,182,109,61,81,43,115,221,71,216,134,156,247,19,183,129,190,28,80,145,
+226,116,67,160,73,118,76,63,194,246,44,150,147,78,82,153,129,22,27,144,166,254,24,84,92,248,177,249,67,167,
+164,133,30,79,243,77,232,103,50,56,46,15,154,174,133,110,121,161,179,159,236,2,255,104,210,247,95,167,27,50,
+218,243,134,23,165,217,94,242,186,140,94,82,24,46,254,229,187,137,250,201,32,99,239,206,123,10,230,121,135,121,
+98,202,110,151,21,66,119,47,166,47,244,191,177,146,101,85,95,165,197,129,181,188,111,41,79,255,116,114,242,239,
+95,203,103,70,239,224,86,80,167,239,232,174,69,218,171,125,51,227,71,214,118,17,9,6,0,70,103,35,57,244,
+92,137,71,180,209,46,255,188,125,130,38,111,60,26,168,173,78,21,239,79,196,149,32,68,84,195,181,171,97,221,
+226,88,208,233,67,199,89,241,188,156,234,20,149,16,240,231,86,77,167,85,215,121,101,236,242,81,133,138,233,143,
+32,78,161,249,12,211,16,168,221,213,127,67,138,233,37,233,164,55,250,155,237,213,37,92,9,190,251,246,205,203,
+183,47,127,248,252,226,229,55,47,94,126,243,242,237,207,138,100,155,105,112,100,9,40,12,174,122,82,195,224,42,
+215,231,2,6,87,201,193,161,199,146,98,100,112,153,46,134,110,191,144,97,248,55,124,176,204,98,208,43,109,72,
+171,104,141,238,102,1,165,66,69,105,104,35,29,153,23,163,11,26,8,234,216,14,172,3,75,219,18,239,121,70,
+220,217,11,173,124,129,246,34,158,213,117,122,123,76,6,181,144,27,67,210,7,199,233,102,83,220,82,254,132,53,
+43,241,189,56,15,8,254,121,43,84,168,217,125,69,14,167,178,101,221,33,15,67,10,113,191,161,88,116,133,225,
+149,227,254,254,255,248,123,252,116,118,10,122,19,176,55,242,150,194,137,104,224,179,158,178,130,195,233,166,127,113,
+40,21,86,103,223,101,213,136,180,121,25,139,251,30,223,61,147,154,157,45,163,123,70,175,98,255,172,92,210,58,
+9,179,163,78,120,220,149,178,182,173,19,42,243,29,125,67,102,5,167,110,210,191,228,34,51,141,190,81,187,111,
+133,59,188,69,185,101,219,166,235,127,82,137,190,70,49,69,219,49,53,195,33,250,177,75,235,148,205,208,80,8,
+245,22,49,40,10,154,45,97,241,161,233,10,237,1,54,72,63,120,99,66,254,2,95,139,55,93,214,238,32,78,
+41,22,126,65,52,74,102,35,168,180,141,89,219,24,91,177,141,90,105,199,160,84,75,47,92,142,170,55,238,115,
+51,224,185,146,214,140,222,48,245,170,172,65,179,210,115,186,209,151,142,126,122,61,253,112,108,145,50,87,3,97,
+36,63,154,16,36,126,142,107,228,132,216,137,104,172,140,139,125,10,163,112,121,115,155,87,68,169,21,154,208,154,
+234,213,195,76,146,223,209,106,6,102,202,120,196,111,172,179,180,41,7,173,219,188,79,45,215,86,93,184,153,191,
+214,158,121,76,215,229,102,225,153,244,169,42,68,229,113,34,67,115,104,124,251,240,122,10,134,203,182,241,67,153,
+130,81,212,9,92,7,238,67,183,180,221,117,51,111,251,242,22,248,186,203,135,235,94,217,37,150,117,217,176,180,
+159,242,27,111,127,78,60,138,94,199,187,75,237,59,124,169,140,124,134,131,84,102,20,220,196,222,14,182,113,42,
+56,166,47,49,160,126,136,152,234,81,239,125,98,33,19,197,186,64,63,178,180,141,196,186,196,88,234,102,111,46,
+235,233,227,41,206,196,205,119,238,72,132,170,74,117,13,12,157,31,162,107,174,18,139,98,136,224,131,3,182,102,
+8,116,88,237,137,235,208,90,116,136,39,137,186,43,116,140,46,167,122,195,15,143,187,129,176,220,149,216,127,223,
+245,176,211,109,98,92,38,52,222,238,39,235,9,152,229,93,208,217,157,152,167,57,131,252,12,35,221,21,203,211,
+8,2,179,82,213,67,27,40,212,23,220,195,165,170,145,43,152,66,27,72,48,76,249,155,103,136,188,29,251,219,
+17,188,140,79,171,105,253,180,181,35,98,198,50,93,214,48,109,86,205,106,47,134,113,36,20,76,191,189,187,11,
+198,77,77,173,188,218,66,226,108,105,215,44,213,234,140,218,100,218,13,81,88,18,242,113,139,76,55,79,116,148,
+146,99,205,133,237,117,194,61,76,32,165,130,216,76,115,124,243,84,215,51,136,129,221,144,185,97,196,10,230,43,
+83,150,104,195,4,95,117,172,50,97,213,182,217,215,174,185,229,87,228,214,127,209,170,154,96,147,147,162,225,206,
+116,227,114,250,47,49,67,202,150,238,41,223,191,90,121,165,118,60,139,121,234,74,161,115,209,134,149,88,152,153,
+46,147,86,204,10,140,3,227,80,82,195,132,74,223,10,5,117,132,185,210,139,20,14,235,69,136,91,148,83,109,
+18,113,157,135,152,153,110,166,38,193,31,52,25,45,180,222,154,225,122,123,248,130,117,151,240,133,110,172,171,90,
+56,109,197,67,197,77,84,234,166,162,64,24,201,160,177,74,121,27,209,235,96,253,121,37,205,58,47,123,214,154,
+183,29,10,148,212,108,225,75,195,60,182,42,117,140,147,43,253,22,195,133,202,130,109,59,9,75,105,96,11,108,
+166,58,75,82,9,237,209,102,166,179,56,145,121,102,1,247,193,233,21,79,155,97,137,169,52,138,184,133,12,100,
+9,169,108,163,13,222,169,237,166,154,241,230,2,56,192,148,43,76,113,59,189,229,15,121,51,254,106,120,195,24,
+60,124,251,117,20,3,179,182,149,189,149,215,208,73,153,50,43,143,41,210,218,82,38,134,153,176,239,222,4,114,
+13,41,65,144,178,37,10,46,14,89,62,247,224,197,217,126,129,12,106,199,244,102,210,42,254,162,247,194,196,40,
+36,250,146,9,71,78,58,81,211,79,3,226,4,72,77,255,176,33,62,29,41,59,18,5,56,173,40,144,153,30,
+44,61,193,80,241,233,162,198,247,14,131,148,162,229,173,22,31,205,91,173,240,56,108,111,181,211,82,73,161,179,
+31,76,208,251,161,247,30,71,86,15,60,145,193,70,232,199,100,105,182,54,203,103,232,65,103,196,53,154,156,41,
+223,192,39,233,120,238,79,144,66,133,49,132,200,33,35,24,17,207,5,125,245,92,175,209,247,253,156,98,156,218,
+239,246,221,171,209,97,45,99,196,9,221,143,30,70,248,83,91,198,242,113,42,163,24,89,246,162,110,247,163,110,
+250,25,126,187,190,17,225,167,159,246,163,126,238,69,17,21,111,233,138,253,248,240,18,53,146,136,196,80,175,96,
+151,151,0,36,105,193,158,87,250,147,191,7,32,247,47,121,119,81,155,166,42,62,152,144,93,178,26,135,245,5,
+198,184,127,205,119,66,63,18,38,202,129,135,111,184,114,218,86,35,182,80,237,195,49,138,223,148,206,198,38,104,
+215,248,66,30,100,193,152,93,8,52,170,178,143,202,85,36,218,107,60,238,114,221,197,234,0,141,142,15,96,96,
+211,185,138,209,14,148,236,148,191,168,202,25,99,7,113,97,6,63,95,137,62,136,65,241,174,31,217,144,214,241,
+139,149,81,18,70,25,60,198,193,99,218,224,132,240,134,160,156,124,33,166,42,129,135,97,25,184,237,104,74,173,
+75,187,69,70,11,178,229,32,111,172,11,190,1,29,167,136,141,161,103,42,132,170,94,168,198,16,246,251,83,191,
+73,165,237,114,196,239,198,35,77,185,149,135,237,211,224,49,225,206,177,135,238,253,0,249,42,255,128,90,235,157,
+173,26,125,121,17,193,141,31,52,90,248,232,160,195,63,177,46,19,116,188,230,110,96,255,83,254,166,187,54,117,
+212,118,9,70,25,43,202,75,181,161,97,145,97,14,151,129,90,161,186,236,231,104,85,172,160,93,35,225,223,224,
+80,159,97,214,251,166,139,234,59,56,91,47,8,179,125,20,172,216,172,99,192,194,248,241,48,180,112,209,127,39,
+184,92,100,181,73,91,67,80,47,165,120,228,249,167,74,61,208,186,163,229,103,59,131,240,199,247,0,233,46,103,
+131,79,101,218,120,99,105,79,50,50,199,199,214,214,62,147,27,82,25,48,248,18,76,240,9,213,193,84,167,28,
+136,34,50,171,29,11,5,66,138,80,165,85,27,68,113,115,124,219,231,66,13,124,82,17,44,224,19,49,194,22,
+248,1,102,96,237,1,118,133,0,217,134,165,70,219,50,12,35,43,113,36,8,48,90,35,34,146,57,196,225,48,
+200,86,203,108,254,152,24,84,214,197,251,231,79,115,224,232,169,198,79,157,122,239,32,79,85,122,223,211,233,253,
+24,95,130,129,51,227,128,11,142,44,83,199,104,137,37,233,100,133,173,163,74,239,56,34,57,233,122,18,140,169,
+126,102,206,74,255,74,119,46,102,162,25,163,178,0,48,184,23,18,82,203,88,82,40,244,233,17,54,90,117,24,
+82,43,62,75,192,141,50,159,204,49,72,243,251,222,103,8,232,194,231,226,157,203,89,60,58,192,116,111,54,81,
+144,137,192,153,195,16,150,206,116,223,253,199,174,35,21,75,0,79,184,142,202,147,90,101,200,72,131,91,88,73,
+239,163,33,41,158,75,66,106,205,31,61,82,106,205,31,74,44,203,169,186,73,86,104,149,17,254,222,242,229,147,
+165,62,220,157,209,9,127,40,75,61,37,200,89,183,84,19,124,222,118,221,8,33,91,143,211,171,32,78,71,241,
+99,68,12,27,142,112,8,90,181,72,71,32,189,94,151,105,33,191,5,164,48,223,85,204,143,191,130,96,178,149,
+218,74,76,103,101,141,63,195,62,143,59,208,196,197,162,100,207,43,111,41,211,220,56,155,70,213,241,205,41,108,
+246,219,211,88,201,184,199,24,247,184,31,247,7,140,251,67,220,141,212,41,217,36,78,104,201,174,137,115,7,162,
+196,125,186,238,95,160,211,78,151,225,146,92,132,75,114,38,47,201,235,222,37,121,69,151,228,148,46,163,75,117,
+139,151,230,214,177,100,54,129,91,165,237,174,6,117,72,117,163,222,43,224,172,122,83,168,242,114,25,93,235,237,
+20,180,66,84,35,94,213,47,209,62,146,190,156,1,127,76,95,79,107,242,19,81,199,9,198,79,55,152,50,165,
+148,25,164,96,58,114,217,46,33,89,84,113,1,57,253,237,25,13,177,78,235,164,17,55,87,76,223,204,124,142,
+76,173,226,89,157,92,104,65,210,171,202,51,51,162,247,26,68,214,245,123,104,240,82,95,192,223,27,125,49,197,
+14,189,199,206,99,202,148,82,166,148,2,93,133,126,189,199,9,58,77,46,213,205,227,4,166,224,15,9,108,136,
+211,228,189,186,125,156,92,171,219,63,36,31,58,47,173,62,234,103,146,249,153,149,110,164,153,126,107,233,6,173,
+106,134,7,157,198,68,101,144,71,191,145,194,232,246,89,12,46,57,95,241,46,96,178,209,238,217,50,86,70,72,
+85,103,225,59,146,249,56,215,152,112,53,233,161,75,30,125,170,203,30,3,91,25,33,105,205,73,116,174,56,166,
+104,237,152,162,108,4,149,14,115,91,136,216,192,100,179,13,108,188,226,40,240,60,190,157,214,61,209,5,27,167,
+101,228,20,166,104,122,10,139,87,33,249,143,169,229,62,23,125,150,58,61,60,234,14,62,209,242,54,86,85,120,
+49,28,158,157,40,251,156,234,209,227,19,147,132,193,147,34,8,43,102,74,240,144,215,157,174,212,10,231,173,18,
+143,29,75,191,64,78,5,60,86,91,221,192,176,151,49,190,97,60,89,137,241,45,34,25,154,33,239,50,65,229,
+100,3,67,221,16,108,140,235,118,93,122,221,46,161,86,143,165,165,148,221,189,34,118,61,215,146,29,108,198,70,
+170,101,109,85,22,79,51,168,242,70,95,77,11,208,28,236,59,212,4,61,232,45,32,211,191,152,219,79,189,172,
+162,244,190,52,158,129,28,104,18,34,137,85,191,190,186,39,44,40,43,170,135,210,144,162,22,214,55,147,254,60,
+235,190,171,209,211,123,218,145,186,117,46,13,3,100,160,74,181,67,149,63,159,197,71,161,55,83,183,42,195,9,
+156,173,227,225,180,54,172,64,183,85,167,49,102,152,1,220,223,16,175,114,160,252,214,87,119,187,97,117,183,247,
+250,233,123,171,236,54,112,174,117,239,212,175,113,210,0,209,95,170,91,84,38,7,88,70,161,29,6,163,155,46,
+22,206,178,188,22,220,61,235,208,235,129,111,224,2,27,152,158,98,19,179,199,216,8,252,29,105,6,112,238,125,
+125,230,188,175,81,103,239,82,93,41,132,113,223,59,25,123,127,71,125,61,23,10,251,134,61,131,126,197,113,39,
+11,14,137,102,198,19,132,221,249,234,39,206,104,220,243,65,145,87,60,179,37,149,194,144,61,185,107,213,123,138,
+74,82,245,81,152,165,180,152,165,12,152,133,109,70,72,132,161,182,254,49,110,115,215,217,161,174,194,83,221,155,
+120,39,112,242,27,181,177,8,121,186,181,232,119,233,241,240,114,90,117,112,18,110,196,81,194,236,116,79,6,168,
+91,245,140,206,37,121,246,212,7,207,24,62,39,86,238,156,144,167,217,37,204,235,224,132,193,145,219,229,251,33,
+26,80,234,168,49,186,69,245,245,203,163,64,8,212,189,231,32,16,133,131,89,157,226,223,19,56,214,79,212,109,
+56,126,175,159,220,194,225,116,109,117,102,96,127,158,93,159,171,155,209,213,199,20,217,171,27,232,203,5,119,4,
+59,241,94,95,48,195,1,58,243,158,235,247,172,170,222,153,100,84,11,115,182,193,113,10,165,175,222,114,22,49,
+146,27,39,234,153,118,85,205,63,60,121,6,93,253,16,95,69,239,207,62,156,99,81,89,98,14,189,97,126,198,
+85,220,1,52,12,210,121,230,108,22,158,56,92,221,153,174,8,168,61,71,98,64,179,248,203,202,8,209,210,35,
+89,138,223,70,178,112,173,158,102,225,35,125,240,26,173,204,1,101,116,89,254,126,90,70,74,23,200,53,116,41,
+227,196,75,10,91,42,37,226,37,237,19,47,41,48,46,126,27,241,82,246,223,207,45,149,24,176,155,188,108,8,
+154,191,82,14,115,56,212,114,131,15,98,73,33,136,243,204,17,231,235,30,213,191,10,84,255,82,82,253,219,30,
+213,191,33,170,191,57,150,215,135,120,46,103,168,217,67,160,166,119,134,54,189,51,212,136,195,183,239,155,216,244,
+206,7,227,108,58,167,211,21,162,236,218,17,229,124,239,219,191,133,113,213,84,36,155,45,85,129,49,255,216,166,
+144,179,205,179,207,182,53,87,151,169,66,209,223,233,18,171,149,239,159,149,191,41,124,92,51,88,201,122,182,25,
+109,136,83,21,118,102,131,95,220,152,157,220,143,171,127,139,229,198,107,183,117,83,251,219,209,97,32,21,113,111,
+43,92,211,234,80,27,138,103,223,244,172,192,26,119,246,247,22,16,53,142,77,80,137,191,176,151,112,127,47,127,
+75,38,68,61,67,112,248,106,48,124,172,82,141,38,246,255,141,170,236,199,45,162,18,208,238,8,84,58,178,125,
+218,81,182,143,228,49,141,115,128,144,219,84,247,37,165,211,49,126,10,234,173,239,243,83,106,21,178,198,42,67,
+198,10,180,99,153,44,95,52,246,177,24,95,244,35,98,102,28,105,228,161,64,207,125,224,22,101,6,36,143,37,
+27,227,177,100,252,33,95,160,82,251,219,123,167,74,249,163,247,46,5,70,83,228,163,20,132,111,213,189,12,19,
+207,61,36,228,35,215,234,227,89,124,236,83,72,114,240,122,190,14,88,85,97,28,58,76,236,117,29,24,121,97,
+238,62,15,73,12,189,83,149,55,73,128,124,39,59,123,221,188,212,222,129,99,25,63,57,62,57,57,69,183,233,
+92,117,221,127,250,86,169,184,118,211,233,133,23,129,1,9,49,136,31,198,248,35,83,70,251,99,209,29,137,38,
+188,117,161,45,29,239,16,23,30,144,138,234,50,45,158,21,155,117,170,121,185,7,216,191,82,173,85,51,64,235,
+9,202,12,244,223,85,101,143,19,175,231,27,56,12,88,208,196,33,22,59,57,136,244,39,59,71,255,56,214,132,
+116,138,27,211,19,7,238,46,239,64,79,62,156,133,189,135,215,162,174,25,230,29,50,143,67,126,100,15,147,242,
+92,180,235,73,35,166,44,112,89,116,193,196,86,38,240,199,80,0,51,181,27,60,139,135,206,212,38,159,165,101,
+89,1,131,30,234,3,115,244,220,200,131,180,125,64,13,60,152,76,83,247,108,48,232,129,151,135,204,172,144,101,
+113,238,251,212,145,191,129,38,183,238,254,29,111,217,225,165,207,214,232,67,119,25,53,136,16,208,247,54,89,84,
+147,163,214,163,92,106,111,86,18,48,0,204,250,107,98,64,146,150,104,3,218,150,54,141,183,45,40,95,198,66,
+119,154,177,60,228,178,102,111,241,16,24,175,40,136,38,31,110,234,212,239,72,137,3,96,196,195,133,246,35,127,
+55,178,224,149,21,90,74,15,76,78,109,17,45,212,131,243,88,171,42,6,53,62,47,109,51,156,175,90,69,141,
+219,75,224,50,205,179,115,253,196,14,102,18,81,132,197,15,128,28,6,51,135,26,228,208,116,55,218,235,1,123,
+87,78,192,136,34,121,181,109,157,9,97,247,158,193,193,7,198,227,158,62,208,186,182,158,181,56,221,120,235,71,
+75,175,228,14,243,10,62,84,37,188,186,87,193,16,101,45,12,81,214,221,112,54,229,155,33,243,217,75,230,178,
+7,127,64,158,73,76,199,104,53,122,140,74,71,124,53,251,25,137,74,248,168,241,56,107,232,227,54,238,186,162,
+244,197,161,83,80,31,233,98,188,102,93,12,230,163,11,21,153,162,84,34,127,242,204,216,183,220,151,101,238,53,
+53,12,249,24,224,162,244,236,95,148,145,151,141,246,218,26,93,124,64,143,34,15,98,62,254,243,88,8,80,24,
+40,87,155,198,180,191,165,0,245,18,13,31,75,53,30,159,91,25,29,196,150,58,176,78,95,86,109,190,186,5,
+254,13,218,78,141,38,252,174,111,115,88,139,218,38,118,179,106,37,148,32,210,26,103,142,213,94,113,106,124,80,
+122,68,193,60,95,133,121,19,199,55,171,157,207,125,218,152,218,57,170,62,193,152,63,243,70,161,233,148,202,44,
+84,33,58,233,164,182,137,247,166,122,162,220,6,36,165,110,161,63,194,26,29,19,181,231,141,187,126,119,153,70,
+39,138,254,59,254,175,120,98,165,197,57,241,255,172,86,43,142,121,49,166,130,36,25,205,201,99,181,199,227,77,
+254,172,2,23,59,97,206,42,30,218,178,126,138,8,149,96,200,54,214,209,119,175,172,191,2,250,210,28,21,202,
+15,110,165,208,5,27,51,54,0,78,146,77,120,245,155,63,75,193,71,172,56,188,225,252,169,255,134,243,103,193,
+27,98,19,215,65,142,158,44,206,120,134,209,161,244,125,38,26,15,175,207,134,194,37,238,137,67,251,11,221,112,
+41,227,161,63,119,79,208,39,187,229,182,182,95,127,60,1,136,73,27,172,106,2,191,230,219,109,251,215,45,250,
+60,233,66,118,128,175,146,116,99,224,195,138,252,217,224,196,121,83,200,77,147,4,47,247,68,32,194,175,37,11,
+225,195,226,61,247,241,243,228,188,83,238,153,114,231,218,102,151,183,202,119,236,49,104,54,117,42,136,89,236,132,
+40,78,242,89,107,129,202,59,127,182,84,221,211,19,129,10,208,202,43,110,182,32,214,224,44,247,150,218,44,12,
+23,73,78,156,126,49,158,204,254,72,25,132,232,0,192,179,133,233,16,239,16,43,136,45,98,221,96,247,127,50,
+193,250,56,232,115,217,32,166,148,120,51,179,165,136,152,121,82,250,99,233,76,68,59,83,44,147,9,99,21,63,
+238,64,7,99,72,136,212,96,144,154,193,73,249,87,198,148,219,222,78,39,9,144,96,249,113,79,125,5,136,130,
+97,140,213,4,211,249,200,76,180,136,179,166,26,43,138,189,124,218,94,121,110,246,155,8,13,162,96,126,164,134,
+59,21,94,124,112,64,190,244,56,145,217,183,29,31,143,154,120,200,195,244,122,186,82,110,30,35,121,35,18,75,
+114,234,32,166,183,185,76,143,123,226,31,26,66,2,6,212,240,1,34,164,250,168,129,145,132,174,83,125,190,230,
+1,123,154,30,161,118,106,240,38,246,191,56,121,226,197,202,140,189,88,65,172,251,236,24,140,61,164,82,72,64,
+177,151,156,194,176,69,201,62,155,79,232,246,116,29,253,73,49,89,85,165,63,28,66,140,63,185,124,196,221,182,
+32,208,47,129,179,232,0,196,7,134,156,124,145,11,187,243,117,210,215,158,12,168,74,86,138,41,253,124,2,175,
+66,198,21,23,234,39,52,50,101,226,163,209,144,5,162,125,252,78,139,111,105,233,223,100,213,134,176,47,121,110,
+74,51,140,67,4,251,233,106,32,93,185,187,184,32,5,191,139,11,75,24,60,55,153,235,70,185,82,47,200,133,
+69,114,187,82,214,82,83,242,126,165,222,108,47,45,214,121,179,82,246,227,25,124,48,81,245,122,213,185,45,253,
+114,165,189,238,128,126,234,52,1,219,160,9,184,136,140,246,42,132,179,83,21,60,58,238,188,99,79,130,139,22,
+29,136,90,3,161,45,210,59,214,231,105,172,76,28,116,24,95,172,246,253,86,5,149,194,214,90,10,37,167,123,
+14,159,189,244,37,130,249,5,196,113,77,251,50,148,226,188,72,71,87,11,147,52,157,205,249,107,240,88,225,28,
+90,227,31,20,243,39,174,134,101,8,228,177,58,129,76,108,235,99,147,123,121,116,99,198,229,209,91,103,154,138,
+52,162,17,13,14,132,203,63,96,212,107,164,245,244,137,116,93,65,251,7,165,243,80,0,121,192,192,27,100,194,
+137,112,167,220,224,134,31,156,10,75,215,91,172,71,201,107,81,117,100,112,24,221,165,216,87,252,146,180,52,51,
+19,53,104,143,117,180,79,52,184,99,238,89,71,202,146,145,115,248,130,75,26,11,251,98,243,131,61,242,142,157,
+243,230,5,214,133,244,62,52,127,102,176,35,45,44,14,128,64,169,90,245,185,117,76,178,215,147,88,253,186,130,
+164,224,5,38,238,150,6,54,199,21,189,7,183,233,171,252,42,111,27,111,249,23,162,159,147,43,251,101,210,162,
+81,4,23,48,157,239,218,247,13,224,42,92,105,236,94,97,168,76,82,98,230,164,9,185,190,206,203,175,211,27,
+100,0,204,7,184,25,75,18,203,60,7,244,64,214,192,224,160,43,209,100,184,129,143,102,111,10,66,207,121,120,
+208,158,46,189,171,11,221,88,255,14,111,177,58,41,38,206,89,149,209,46,235,80,4,188,162,67,70,184,109,218,
+159,126,136,210,36,229,103,112,221,125,87,22,85,82,29,55,8,0,184,164,211,211,120,31,82,253,211,152,47,21,
+149,100,153,94,157,238,195,187,239,45,102,58,254,83,114,18,11,23,69,45,56,85,210,64,25,76,167,113,195,182,
+208,169,157,164,238,194,86,237,184,215,222,213,249,112,59,140,65,85,75,110,217,91,239,170,118,129,14,154,1,241,
+4,181,126,222,163,199,34,102,204,253,130,19,67,191,160,219,63,123,80,7,22,205,72,100,220,237,57,101,23,74,
+216,140,46,143,180,163,170,17,62,108,255,121,7,33,20,56,236,3,184,49,161,52,81,165,69,229,69,20,181,179,
+225,44,199,143,134,171,212,235,12,66,208,222,172,17,148,250,249,66,71,248,237,83,19,224,0,187,33,186,32,71,
+133,115,201,222,230,177,21,138,132,68,202,36,134,44,48,231,176,191,83,87,49,143,73,148,126,56,58,18,239,188,
+126,64,24,177,139,231,110,3,103,195,82,195,205,163,53,239,170,250,118,50,135,8,119,109,214,59,26,106,226,133,
+185,19,72,12,90,240,67,240,146,154,244,95,238,187,108,222,217,125,142,30,226,90,179,73,42,133,72,130,204,172,
+144,219,57,24,79,67,134,100,84,6,249,218,36,195,20,218,193,201,154,208,78,254,14,176,82,178,82,108,63,234,
+83,91,219,18,181,235,182,186,66,113,152,141,134,249,87,132,124,174,168,222,75,124,88,188,208,71,223,68,40,126,
+135,191,105,172,222,227,111,22,171,107,29,93,206,174,226,71,209,10,54,43,109,246,15,250,139,50,178,145,155,71,
+160,116,188,85,183,138,140,34,227,81,241,225,201,169,153,157,254,17,140,35,94,192,191,27,199,59,227,125,119,213,
+41,254,186,236,206,231,207,237,86,207,76,94,68,151,143,62,196,51,10,174,138,10,54,240,21,132,213,243,167,27,
+128,98,106,239,249,195,15,220,90,172,190,137,10,220,55,183,182,248,166,186,142,78,79,240,161,230,131,168,239,195,
+195,219,248,209,109,172,4,194,92,68,207,244,160,133,135,31,212,27,217,9,138,138,19,200,120,5,9,151,177,130,
+65,128,199,40,56,182,158,167,81,148,206,234,248,81,165,62,60,2,187,123,241,34,194,238,123,8,244,98,88,54,
+215,7,181,142,177,67,54,244,92,61,211,53,84,152,198,201,123,236,197,197,162,78,158,65,248,102,145,38,48,111,
+58,155,157,98,222,55,179,103,144,23,154,127,78,223,88,203,181,137,158,43,209,204,243,216,53,223,107,29,10,137,
+201,132,96,48,129,238,177,233,95,202,8,166,20,254,62,131,212,254,220,225,132,46,126,76,96,10,159,201,90,159,
+209,28,170,55,50,238,13,197,17,28,188,96,83,29,48,71,17,188,127,60,67,222,33,208,104,67,68,171,158,61,
+1,49,253,23,211,41,14,70,212,20,61,155,190,128,201,182,109,212,234,43,180,254,126,173,242,56,166,204,113,226,
+138,197,243,23,79,158,195,107,252,139,184,95,245,129,170,2,102,135,133,131,110,189,129,110,165,11,227,37,51,174,
+17,191,4,60,196,136,70,165,216,129,212,118,96,49,146,65,167,73,191,249,180,131,133,58,2,158,233,27,13,13,
+64,167,251,201,111,186,158,198,45,84,142,196,227,110,237,81,127,98,112,103,191,118,119,156,178,11,116,232,69,27,
+225,251,143,142,140,181,1,208,0,88,53,177,29,112,86,53,240,13,224,143,47,96,170,214,199,255,249,167,135,237,
+195,104,2,87,108,119,222,187,241,123,144,108,1,104,235,152,213,28,175,62,158,172,36,124,218,35,40,161,24,135,
+239,33,60,33,227,61,228,168,164,235,252,213,189,133,129,5,202,223,31,101,112,116,72,27,32,214,194,74,12,248,
+197,147,118,211,54,182,39,202,180,229,87,19,196,137,212,148,189,224,4,66,141,36,18,158,181,127,51,117,5,7,
+118,255,5,68,82,113,70,82,113,229,61,84,92,131,153,29,255,61,60,74,234,167,141,54,139,38,41,84,138,129,
+74,151,64,255,16,3,167,13,2,52,95,147,215,231,12,127,43,168,241,9,16,22,217,147,147,5,48,224,226,164,
+120,138,33,252,83,67,176,227,75,73,133,138,219,88,244,116,30,85,79,157,197,153,175,159,253,116,241,230,217,11,
+180,56,243,246,243,47,62,127,13,236,252,39,62,237,229,55,189,52,114,38,25,94,84,171,135,199,39,127,66,77,
+159,168,154,162,44,29,188,104,69,205,172,136,59,79,54,54,129,108,36,229,58,156,94,164,128,15,27,77,70,156,
+107,231,135,15,40,202,158,24,58,215,136,249,137,147,170,60,137,80,46,162,70,224,48,215,220,163,178,119,46,184,
+14,65,244,244,84,53,79,1,23,194,80,176,7,85,97,142,175,211,186,140,254,78,254,55,65,242,128,29,174,45,
+59,219,153,99,223,240,131,79,118,101,247,224,186,218,22,203,7,181,105,224,16,127,192,246,24,225,158,249,96,187,
+121,208,86,144,165,233,30,216,114,15,176,231,152,132,241,167,39,39,39,199,127,199,131,5,209,112,156,56,186,219,
+155,147,246,243,162,12,62,126,157,158,194,7,116,177,145,142,16,155,24,42,232,246,138,248,157,112,200,134,208,144,
+96,31,183,138,238,231,94,222,139,68,43,243,50,156,10,143,85,41,222,231,61,45,81,42,38,67,90,190,119,16,
+25,210,98,247,9,210,91,44,44,200,17,115,236,191,45,221,98,252,108,91,66,5,34,232,87,208,40,22,39,248,
+48,76,152,192,142,35,164,178,196,151,80,157,8,129,4,110,159,222,129,228,94,152,158,100,58,255,192,89,3,94,
+128,165,225,183,50,32,194,26,85,5,210,126,228,166,117,93,69,181,162,236,19,194,97,147,88,181,238,189,110,17,
+201,167,59,129,56,29,4,7,212,233,128,23,160,38,228,243,177,62,159,47,25,171,58,220,40,134,11,30,22,217,
+132,42,74,95,22,145,204,248,13,100,112,139,131,107,204,224,122,223,232,168,156,1,205,31,252,110,250,211,80,157,
+198,32,8,110,102,186,81,229,84,55,221,222,41,96,134,7,64,185,143,251,161,242,209,75,23,47,192,231,16,16,
+154,75,190,187,69,133,251,90,237,99,25,230,4,199,29,31,113,223,6,77,254,171,124,119,207,165,221,222,214,19,
+51,122,1,247,232,239,19,180,111,213,38,193,47,38,196,24,32,20,146,83,27,115,232,204,25,219,227,114,21,135,
+32,14,75,185,8,226,49,82,46,70,149,72,23,236,15,94,238,3,196,74,81,27,136,134,82,16,13,165,39,26,
+42,45,133,134,168,107,200,216,116,125,62,241,59,33,32,99,243,200,35,47,48,215,92,73,193,199,38,190,251,94,
+250,239,189,113,30,186,11,254,43,23,192,174,251,182,196,219,157,123,60,154,67,240,240,221,238,187,240,240,80,55,
+199,64,160,152,58,207,228,157,238,31,210,64,70,254,72,210,217,242,246,65,54,51,98,152,157,211,64,37,254,56,
+184,14,246,243,19,206,141,99,85,202,83,18,227,122,109,152,56,150,124,153,13,180,67,152,225,112,63,90,76,143,
+99,40,87,15,90,36,85,96,25,87,245,154,170,33,185,208,53,208,42,50,214,19,21,144,12,86,108,151,213,131,
+62,239,5,125,254,253,82,213,9,204,83,133,58,173,211,105,170,82,156,135,19,210,203,61,133,136,26,171,5,14,
+203,226,20,239,36,149,188,127,164,15,251,61,120,8,74,47,197,252,122,157,163,74,231,19,64,234,53,84,5,231,
+109,250,196,159,107,25,79,66,122,19,176,252,160,79,217,160,79,13,99,146,87,229,255,62,177,124,144,44,246,204,
+214,43,201,78,192,244,129,45,0,101,206,137,95,93,34,195,45,222,217,74,209,127,191,62,242,6,138,121,216,159,
+68,37,50,65,193,213,99,73,252,251,238,223,135,29,253,105,129,60,108,170,124,128,44,69,6,35,50,120,116,38,
+8,115,128,132,222,40,226,123,176,236,120,194,191,192,155,197,105,247,135,106,227,15,85,207,248,7,98,30,50,44,
+144,15,51,32,243,35,52,42,164,159,30,222,110,69,28,79,179,120,142,139,213,160,236,205,19,128,243,168,138,128,
+76,172,33,51,236,25,8,164,81,169,136,109,91,195,103,163,224,11,190,49,39,240,34,48,198,38,54,20,81,83,
+110,12,251,41,131,249,115,157,7,202,135,129,111,251,238,157,105,90,179,132,5,4,8,192,75,107,228,71,120,2,
+64,225,91,253,237,204,226,64,123,18,204,176,52,104,3,178,19,76,46,138,152,244,166,83,165,6,76,103,79,242,
+251,200,174,242,48,217,85,254,239,145,93,229,56,125,226,143,52,222,191,139,201,201,36,249,159,147,43,163,164,29,
+247,106,62,70,187,13,144,8,226,238,125,254,57,70,251,145,204,48,112,215,1,29,133,209,88,147,221,8,10,81,
+232,71,224,25,59,159,123,109,124,231,89,142,217,185,48,114,237,35,234,192,255,244,120,247,39,225,193,227,220,195,
+143,220,112,123,212,128,25,225,250,118,175,248,212,175,222,165,117,222,174,175,242,108,50,127,245,241,71,127,40,199,
+167,135,20,159,234,217,75,205,202,129,112,25,214,139,8,219,91,41,68,1,53,254,244,99,182,214,46,177,225,101,
+93,109,190,27,88,245,250,156,93,17,33,245,190,242,194,63,95,134,239,120,106,156,68,53,23,17,102,249,190,25,
+90,232,50,250,11,75,207,194,243,24,232,152,36,159,164,152,193,169,196,152,88,173,19,199,18,123,216,10,242,175,
+11,117,254,205,155,126,83,141,175,151,158,59,173,181,192,102,177,163,21,73,218,25,250,205,194,215,225,118,10,95,
+93,146,63,193,44,79,101,6,155,220,37,46,198,101,23,237,253,178,146,179,186,43,146,220,58,47,202,131,241,115,
+12,171,58,201,217,73,150,72,97,71,101,144,212,86,27,81,4,131,234,18,162,45,227,95,20,225,152,78,153,125,
+221,1,114,8,117,118,238,236,157,96,161,42,47,249,209,136,167,13,13,254,122,60,32,146,21,185,18,97,19,190,
+62,118,241,211,163,42,57,241,79,89,78,161,186,152,78,131,174,120,45,133,246,201,96,109,168,128,163,241,176,153,
+163,218,181,206,156,112,60,31,97,107,237,75,4,11,4,133,202,73,96,17,178,161,172,224,20,75,170,52,182,154,
+136,25,27,156,95,106,132,30,178,15,187,82,189,161,98,118,56,216,176,185,37,55,179,213,43,238,27,61,146,63,
+43,223,21,6,58,53,133,74,55,146,172,219,148,209,54,70,53,69,128,162,141,2,213,10,181,60,190,86,39,234,
+244,191,224,236,191,116,177,183,16,187,86,255,125,162,30,255,39,144,31,63,208,25,162,182,228,201,177,203,105,54,
+194,60,226,165,117,6,48,139,54,57,103,112,106,160,131,57,8,183,16,190,132,240,101,220,239,187,53,76,241,51,
+140,140,224,55,128,217,15,24,181,39,54,236,137,92,127,215,50,158,126,246,241,120,239,194,248,185,247,225,139,126,
+184,236,241,243,4,186,183,136,82,77,221,228,56,124,92,0,32,14,140,34,8,40,76,79,227,56,41,241,136,2,
+105,63,107,242,38,162,32,142,203,22,170,3,71,39,167,177,214,83,40,164,26,223,88,187,136,10,29,225,28,52,
+174,177,26,202,181,178,177,150,230,168,128,198,26,110,236,146,216,132,17,5,113,210,108,161,75,217,216,165,130,248,
+105,33,237,255,209,44,10,10,150,247,198,248,182,168,194,182,128,249,3,84,89,161,22,123,170,123,144,136,206,137,
+229,166,25,221,48,141,216,48,25,234,197,62,1,78,172,223,48,227,16,159,169,116,90,79,205,89,118,142,15,72,
+171,1,72,2,236,194,106,34,204,78,191,138,99,4,253,22,115,110,245,23,171,200,65,227,10,33,249,251,85,180,
+66,232,253,43,198,91,216,221,192,78,224,59,198,77,130,145,96,93,67,184,69,216,88,207,23,87,206,167,186,181,
+180,49,197,146,236,11,99,11,129,117,23,123,103,106,194,100,243,74,222,48,173,159,119,252,129,205,178,112,26,99,
+128,84,49,216,183,131,42,172,152,238,29,0,210,20,228,76,183,137,233,91,17,197,56,84,114,204,133,173,207,177,
+58,254,27,250,130,191,176,67,23,182,76,18,153,167,16,130,232,39,255,125,18,115,85,189,138,254,66,21,9,191,
+240,210,113,184,88,117,52,140,170,115,191,198,141,110,103,167,243,230,41,44,117,51,155,133,189,89,126,4,94,108,
+226,216,106,137,86,22,171,121,29,75,177,68,153,42,188,185,209,100,197,75,180,244,203,211,233,125,4,130,118,186,
+119,238,200,182,2,127,155,78,147,87,63,120,77,221,120,203,237,87,120,184,87,251,135,187,212,193,220,40,19,148,
+214,215,179,43,123,154,173,224,3,207,168,229,108,61,189,98,37,170,237,108,5,223,206,64,40,120,236,48,3,188,
+140,221,130,61,52,208,88,85,181,243,229,81,29,211,175,28,251,184,175,142,158,103,142,85,61,180,245,202,142,173,
+115,28,175,137,155,227,180,206,96,1,110,44,86,134,62,221,242,23,186,18,249,62,158,123,255,230,213,216,214,36,
+81,168,6,85,70,217,112,14,106,68,73,233,142,83,144,238,40,73,184,99,180,60,52,195,158,150,101,121,209,255,
+159,70,68,192,216,115,4,202,251,230,117,182,45,82,63,71,181,112,124,149,162,105,102,244,254,119,84,130,118,75,
+13,255,82,4,111,128,241,200,185,160,30,120,117,174,123,62,159,211,129,75,231,86,200,111,142,120,153,110,247,197,
+59,251,142,145,105,37,172,102,137,106,164,90,167,239,5,126,74,101,175,240,48,57,110,171,213,10,111,25,214,135,
+106,217,68,107,0,169,73,231,222,19,63,53,146,217,122,39,139,132,1,161,111,165,115,63,78,34,126,25,47,65,
+218,27,67,221,63,195,173,122,218,243,252,202,148,205,208,0,230,208,163,82,86,246,56,170,49,217,73,214,67,103,
+78,232,226,70,26,232,85,165,244,13,229,243,124,217,55,213,59,239,141,121,248,132,69,164,170,65,119,61,244,25,
+251,217,24,205,141,68,106,137,153,241,43,222,159,37,145,95,188,50,149,56,158,255,57,135,231,116,192,225,1,112,
+247,55,192,33,43,220,39,218,91,196,201,111,231,138,239,241,156,135,131,124,52,92,172,184,179,143,118,92,15,129,
+5,2,93,143,93,182,159,69,42,67,197,35,128,53,20,249,178,202,139,86,42,213,227,137,191,250,174,12,233,121,
+111,33,80,157,65,153,243,62,147,163,129,55,89,60,175,23,13,250,147,139,189,221,66,91,251,190,242,35,121,104,
+204,139,188,189,141,74,220,181,7,159,91,231,226,42,217,202,238,184,232,5,92,151,168,43,9,254,29,208,202,94,
+213,163,27,196,123,186,87,194,242,84,128,27,178,238,13,130,153,128,223,97,142,114,214,248,28,114,65,103,129,246,
+28,38,193,225,228,72,76,223,135,184,235,221,34,36,119,224,251,71,209,222,58,122,173,221,211,120,40,189,72,244,
+47,85,2,15,135,110,105,86,48,218,135,102,138,178,23,182,169,231,185,21,56,120,81,87,87,118,88,146,123,50,
+16,69,5,200,15,150,115,135,131,241,236,152,153,231,170,204,199,164,239,61,103,43,228,143,31,154,36,106,125,57,
+8,74,54,201,126,23,239,235,26,246,229,254,222,221,221,61,159,223,36,174,196,212,116,163,100,150,88,163,225,2,
+193,86,176,26,149,67,81,202,112,107,64,57,64,238,9,158,83,123,122,233,170,69,31,77,221,222,201,207,254,132,
+6,246,76,134,208,51,251,106,90,122,251,252,82,184,6,160,64,130,59,80,133,254,146,231,19,61,41,67,183,131,
+164,217,239,133,7,22,121,184,82,209,145,254,114,252,93,48,103,226,32,168,232,11,222,93,113,232,2,192,185,111,
+3,107,112,142,132,250,171,230,235,245,180,56,17,192,134,8,224,146,9,224,198,17,192,85,167,71,15,224,176,104,
+247,20,31,90,67,113,141,14,85,102,90,245,174,206,151,201,206,81,100,232,190,102,95,111,215,131,141,247,168,55,
+47,29,45,86,14,169,37,204,242,49,147,222,127,203,142,149,81,135,240,12,54,34,9,175,82,90,149,226,16,70,
+7,34,204,142,255,11,24,218,253,222,0,213,142,224,12,9,198,38,41,237,124,52,104,48,184,218,91,131,113,19,
+131,70,158,9,225,168,248,203,202,27,212,20,177,24,21,88,213,159,167,217,58,138,50,181,198,243,15,170,90,31,
+209,43,83,170,63,98,254,50,22,227,157,59,27,186,119,26,154,32,73,245,249,79,220,167,149,74,161,95,168,137,
+47,220,115,66,127,130,145,133,90,87,112,1,172,241,2,88,135,11,96,166,203,97,35,227,119,192,58,142,29,113,
+191,22,196,253,170,211,217,252,104,5,68,253,26,133,209,4,217,190,26,88,146,91,15,172,199,101,146,140,223,183,
+28,151,237,147,241,31,53,137,134,214,98,136,127,145,114,243,239,21,133,30,199,44,53,114,239,134,102,226,248,70,
+213,195,113,18,167,113,215,49,15,186,3,3,103,96,210,34,92,220,181,67,24,254,148,134,5,80,76,33,166,155,
+238,135,233,82,243,200,172,45,145,81,95,151,227,200,251,36,118,86,134,231,194,226,134,243,35,105,238,30,90,93,
+181,152,167,193,239,96,101,42,56,251,61,96,83,106,108,83,192,230,226,77,81,88,93,135,35,227,86,201,143,226,
+46,152,20,92,90,181,22,60,86,156,144,234,99,64,195,119,10,89,175,188,215,84,134,46,187,237,50,124,202,12,
+6,32,224,6,126,139,106,221,246,92,52,177,86,43,59,106,146,214,244,16,110,37,71,195,239,101,188,63,237,179,
+48,132,165,189,89,253,232,241,108,101,249,22,179,106,182,166,119,9,140,34,14,70,61,93,113,99,54,1,130,130,
+133,209,42,238,145,58,129,178,106,237,118,106,102,89,21,93,220,245,204,151,4,251,171,8,134,221,167,134,158,118,
+208,232,96,90,188,98,177,14,136,244,111,59,194,3,59,235,203,153,190,51,118,239,142,104,162,4,234,149,197,2,
+198,56,149,154,154,103,231,251,250,153,39,221,240,8,67,105,52,79,134,226,125,137,223,154,246,86,14,91,186,71,
+246,68,73,22,217,128,251,196,215,103,23,25,84,208,195,64,216,145,36,46,1,56,253,236,124,107,146,199,216,121,
+93,246,63,169,61,214,43,14,166,227,217,13,74,149,122,55,9,19,103,23,13,248,144,66,53,118,162,4,63,33,
+228,200,56,13,39,100,24,203,173,120,189,75,45,143,69,169,235,136,179,61,241,142,40,223,230,248,46,93,20,121,
+99,32,2,151,161,186,186,170,74,28,187,29,53,137,44,54,232,78,191,83,227,121,48,141,115,253,25,230,8,176,
+47,140,113,47,211,159,205,31,69,166,117,181,173,247,178,252,225,207,230,79,156,231,241,31,59,181,76,111,247,178,
+252,215,159,255,232,243,252,1,234,185,54,230,125,200,116,202,77,157,252,241,191,124,46,168,8,210,218,245,94,85,
+143,255,252,248,191,204,159,221,240,30,119,234,31,168,148,111,234,189,234,254,243,191,254,235,143,144,209,87,119,107,
+210,145,190,159,254,233,143,230,63,81,157,190,117,111,96,239,205,109,19,189,205,99,33,254,100,153,185,30,116,102,
+194,119,208,39,13,166,221,165,199,103,144,169,154,46,211,13,98,238,29,201,186,212,73,169,172,29,131,70,229,77,
+245,35,204,6,206,90,213,97,86,204,129,124,133,102,238,53,190,122,250,80,165,214,19,215,60,178,177,107,93,210,
+185,255,9,252,133,211,189,214,33,159,87,51,101,25,27,178,203,158,248,0,49,140,165,238,102,212,80,125,36,176,
+128,75,132,213,127,103,162,10,234,173,180,70,161,21,168,137,246,248,183,43,168,107,194,125,71,123,192,137,76,64,
+86,244,180,22,44,185,182,218,231,75,102,78,4,211,243,63,43,136,243,250,170,176,0,213,147,102,118,42,221,136,
+214,250,109,126,150,181,224,74,244,156,222,24,105,109,23,252,155,28,144,25,39,87,170,199,184,238,232,169,37,48,
+99,34,51,131,23,35,144,190,170,237,227,114,252,68,123,139,3,212,70,23,2,208,143,115,241,44,220,123,63,147,
+189,247,66,165,243,234,169,28,140,129,193,204,102,97,24,84,63,118,12,198,83,159,251,206,5,64,1,202,97,133,
+50,188,165,170,227,167,186,13,42,187,181,232,149,89,244,154,72,78,68,31,63,193,25,244,125,107,251,51,59,61,
+85,6,99,6,158,104,109,127,160,226,246,156,251,36,39,164,21,181,27,94,79,235,66,214,196,57,164,2,120,16,
+251,251,193,190,118,237,174,168,208,33,91,142,4,254,135,210,42,167,86,218,128,25,90,24,219,2,127,19,115,214,
+192,132,156,85,88,77,39,0,103,185,7,56,114,59,85,122,218,120,184,107,207,78,156,234,75,137,144,13,93,30,
+170,188,216,103,75,85,16,200,165,186,2,171,152,186,158,167,88,11,28,6,81,170,78,161,104,92,104,67,150,49,
+233,22,31,181,72,135,144,52,4,110,0,191,25,67,31,243,106,244,109,112,71,194,217,131,171,11,53,92,35,117,
+79,230,56,235,56,133,110,214,144,29,26,212,181,42,251,250,56,10,155,165,147,213,183,91,217,183,177,35,179,40,
+19,156,28,132,65,101,28,231,250,165,249,88,225,62,246,57,164,201,126,24,158,240,214,2,8,126,193,145,3,63,
+29,103,219,150,121,139,150,48,110,39,28,65,125,250,30,99,123,140,108,43,121,141,195,230,8,235,190,25,118,214,
+18,4,213,57,206,227,54,233,44,106,96,104,13,136,191,43,84,254,181,31,80,95,112,199,193,203,78,134,150,222,
+103,199,23,214,26,224,49,71,55,199,24,142,231,64,59,123,202,251,5,209,22,141,114,18,74,77,20,199,123,125,
+241,72,249,216,126,88,220,12,65,250,21,24,26,162,66,160,83,61,165,238,253,81,155,227,16,144,50,144,251,50,
+87,132,124,63,241,182,28,59,103,187,228,22,200,14,175,117,219,139,252,216,69,60,200,42,31,87,179,144,179,172,
+220,90,28,3,8,0,187,133,96,96,168,29,164,132,28,98,45,229,16,211,3,114,136,126,215,20,81,22,239,142,
+106,207,100,207,136,77,215,215,42,105,148,141,141,213,81,42,51,166,55,152,177,18,106,213,202,198,198,93,100,223,
+174,48,189,96,94,135,99,124,187,62,196,42,114,146,121,71,94,50,15,221,200,177,74,13,208,56,153,193,20,59,
+155,19,168,11,171,26,190,36,144,80,242,39,81,19,251,158,53,49,48,193,167,225,32,132,41,71,24,184,142,98,
+68,72,21,100,174,124,102,248,92,84,152,25,54,235,48,235,244,212,139,43,202,185,168,224,20,240,47,20,97,236,
+13,100,175,226,110,48,204,225,34,187,212,183,176,160,208,191,171,141,19,10,53,135,189,123,151,46,233,155,207,191,
+120,214,75,242,88,48,88,135,54,26,241,175,42,251,104,55,182,74,185,134,160,165,236,62,90,217,231,202,88,240,
+195,156,104,99,149,87,69,135,85,89,28,28,22,139,102,186,103,18,24,231,152,32,102,19,186,238,39,187,39,229,
+9,239,26,56,32,63,225,61,129,79,76,108,196,48,189,20,173,171,75,213,65,106,51,213,235,2,215,79,213,30,
+141,11,220,234,246,23,32,173,116,219,86,111,222,231,155,69,91,69,6,107,65,52,171,124,149,190,194,62,92,127,
+150,90,147,81,40,219,158,252,141,89,77,41,119,78,221,81,79,28,239,161,116,224,89,80,32,216,45,12,61,197,
+217,67,34,122,178,176,104,43,1,26,35,164,114,93,136,13,237,21,177,177,252,8,111,13,48,21,178,173,121,197,
+189,28,118,32,238,68,5,120,104,89,16,61,177,206,244,85,53,191,83,219,7,177,199,80,174,210,51,22,16,60,
+99,229,178,162,108,201,194,232,211,89,147,24,29,29,46,3,107,75,111,61,170,58,88,177,4,248,97,11,165,174,
+146,82,71,213,236,35,10,63,62,143,241,81,201,171,90,186,132,39,127,64,43,16,199,143,255,52,55,186,68,73,
+8,84,18,80,37,126,151,244,61,56,129,89,192,208,10,28,150,106,149,34,1,144,156,62,138,204,244,116,138,175,
+11,126,107,12,247,160,71,253,163,234,87,106,207,182,102,99,119,106,173,43,134,97,128,219,202,195,155,81,229,33,
+72,53,164,133,241,121,84,5,149,186,83,82,188,240,55,143,69,37,142,90,50,34,164,191,51,164,36,95,208,77,
+68,173,129,50,32,4,182,210,70,45,213,22,169,233,12,0,96,165,167,173,199,192,43,113,71,65,142,212,32,49,
+91,208,161,150,224,20,90,138,187,84,6,41,238,83,243,167,135,233,158,89,86,51,157,60,72,203,37,216,254,42,
+241,171,54,112,175,169,30,172,210,250,1,140,171,6,127,231,121,187,126,224,6,244,160,90,65,198,20,50,78,128,
+204,11,30,13,228,41,227,141,140,57,11,216,252,70,42,177,25,81,140,75,189,34,191,8,75,144,14,89,226,24,
+144,90,93,170,20,23,127,59,157,198,166,66,39,189,106,227,240,11,20,32,33,85,97,98,197,159,115,91,4,76,
+56,135,124,25,37,47,190,235,152,157,200,161,4,162,126,122,53,187,180,175,197,87,250,233,244,42,190,223,176,136,
+164,30,228,86,69,64,241,106,177,206,186,163,165,206,22,134,137,179,168,85,131,164,56,145,105,3,162,142,200,61,
+172,23,14,63,28,156,141,126,193,4,198,221,118,81,9,102,177,236,144,80,76,117,64,105,170,208,3,244,164,50,
+116,208,80,227,237,96,173,11,252,42,206,1,168,208,2,143,90,98,4,160,160,21,252,111,145,168,218,246,231,36,
+12,165,1,116,191,92,172,147,44,70,81,187,138,97,194,177,169,220,60,109,22,127,141,54,234,108,171,194,171,123,
+178,29,149,16,96,60,137,227,37,120,177,24,211,95,62,12,128,205,116,106,226,70,183,216,83,246,8,193,157,27,
+153,186,134,175,81,6,137,81,143,180,238,213,133,147,175,186,99,111,176,163,50,251,18,122,60,14,83,229,97,108,
+43,207,208,113,213,59,166,192,166,248,182,124,108,209,223,61,162,248,247,181,237,139,60,114,21,206,136,114,11,93,
+225,71,227,242,225,216,184,61,2,68,196,48,104,120,160,73,161,194,99,95,143,153,221,58,54,54,217,82,24,209,
+179,92,24,108,116,92,153,24,137,79,241,26,172,106,45,158,127,85,122,159,242,36,241,71,220,3,232,117,82,62,
+172,166,192,53,81,107,248,170,225,171,234,186,61,12,127,112,144,76,218,237,237,187,6,55,17,157,34,231,255,252,
+103,121,44,120,155,238,228,29,223,227,39,158,150,0,22,196,30,53,33,44,93,247,215,160,26,104,1,142,77,104,
+144,153,122,84,31,95,75,197,85,8,175,227,217,169,119,59,10,186,103,105,114,218,237,99,111,220,151,3,55,197,
+100,45,16,5,5,112,87,227,161,229,118,233,208,95,113,160,100,160,159,217,26,248,120,36,58,83,24,180,76,8,
+85,99,217,225,157,211,147,181,190,182,97,203,26,137,218,129,29,195,103,69,241,29,94,79,237,147,176,189,134,198,
+2,143,52,67,60,2,3,194,42,178,20,125,136,152,143,170,46,158,31,234,16,69,248,33,176,106,207,128,168,31,
+247,248,124,92,4,169,11,156,231,143,158,80,70,155,119,143,209,178,98,220,173,28,199,41,7,49,236,132,30,46,
+197,162,77,246,71,38,2,30,133,190,2,248,181,103,238,63,86,232,211,224,165,125,232,193,141,50,153,191,148,15,
+60,108,191,192,82,12,202,113,61,208,20,48,102,78,152,141,129,196,18,238,35,252,173,177,4,126,244,105,41,166,
+208,146,137,216,102,19,213,219,145,88,109,231,159,112,136,88,73,38,120,63,153,236,105,6,157,118,61,93,97,111,
+220,26,151,132,200,118,157,7,101,251,74,217,7,124,179,64,41,153,28,88,127,104,148,27,133,101,32,208,112,32,
+146,12,195,87,45,84,56,129,248,137,106,241,121,27,190,146,202,142,56,237,168,6,27,87,219,184,162,163,138,226,
+196,215,143,209,161,1,12,141,182,128,9,220,4,85,84,41,172,149,155,224,184,26,227,124,19,254,37,180,158,85,
+14,50,178,69,58,141,80,189,1,14,130,25,200,253,103,73,202,188,185,183,65,241,246,229,125,188,185,22,167,54,
+200,131,194,122,125,87,57,158,153,204,66,50,136,28,47,110,78,114,191,120,228,23,118,19,154,55,195,210,86,57,
+223,215,198,223,116,69,127,85,85,239,183,27,202,133,39,110,175,27,176,194,70,249,195,109,191,59,34,29,213,245,
+100,89,207,50,147,119,188,110,191,69,238,126,143,119,64,189,11,254,151,131,48,8,186,133,117,124,85,149,6,170,
+167,126,146,18,139,53,179,44,214,236,169,54,104,134,6,253,180,176,170,116,102,109,98,186,123,214,99,111,218,139,
+22,219,208,98,159,116,188,246,37,5,79,187,115,209,86,51,108,107,13,248,181,158,158,2,39,14,63,102,240,145,
+225,199,185,146,166,157,214,83,116,107,136,70,213,225,194,82,217,174,216,54,50,106,163,134,87,9,224,245,8,166,
+111,55,190,128,163,231,11,16,145,136,17,239,194,132,70,31,186,109,168,242,14,118,17,215,18,12,79,149,252,181,
+104,135,88,220,184,243,161,140,227,164,213,198,101,196,105,220,235,174,110,85,123,39,153,25,1,72,9,48,83,109,
+31,170,226,71,67,24,252,223,165,246,6,189,41,31,14,155,159,246,96,158,44,210,191,45,61,86,111,76,157,155,
+102,50,135,40,143,219,5,158,39,175,4,102,121,143,145,218,207,216,108,223,27,212,200,77,54,185,178,34,1,54,
+248,109,169,94,5,85,78,27,247,170,84,175,133,236,128,141,252,212,40,92,97,27,120,201,1,234,158,141,122,91,
+122,91,182,208,251,179,235,76,253,109,13,6,116,149,89,158,7,140,143,102,94,25,16,21,32,173,28,120,38,200,
+7,220,117,65,173,5,245,89,188,52,228,188,153,194,5,180,212,63,33,255,2,223,125,188,217,228,12,0,186,213,
+175,162,73,150,150,31,210,102,18,171,151,101,68,18,145,255,79,226,174,187,185,113,28,217,255,191,159,130,167,189,
+245,74,239,64,141,168,100,91,30,206,212,198,139,19,106,243,174,202,53,11,145,148,201,51,211,144,138,214,249,62,
+251,251,53,26,132,72,90,158,240,226,4,17,177,209,104,52,186,27,13,16,20,73,87,125,249,244,21,30,43,4,
+68,52,159,94,147,236,16,57,82,176,109,212,59,112,81,55,201,32,125,230,37,33,209,67,118,52,91,163,60,253,
+248,176,117,15,80,46,175,81,141,171,19,33,49,52,199,157,156,210,175,116,215,77,212,47,130,155,168,164,243,167,
+253,62,134,78,57,75,217,207,142,174,29,253,236,250,126,104,132,43,39,252,253,181,216,191,144,197,173,86,205,251,
+239,0,7,20,164,28,200,48,193,247,196,151,124,53,71,71,165,152,111,93,184,7,46,146,243,215,20,102,5,228,
+28,37,72,181,198,34,73,231,38,18,189,156,107,19,160,67,176,240,208,0,16,210,53,59,160,233,50,237,118,233,
+40,143,84,219,37,55,81,55,174,218,22,220,13,97,218,21,85,131,124,8,229,171,130,107,210,43,32,93,201,86,
+90,42,36,127,70,164,68,64,87,116,51,132,117,85,183,64,88,127,174,164,71,64,94,107,32,88,47,3,68,64,
+103,173,246,221,158,238,202,125,109,35,32,236,46,123,135,191,71,243,229,243,142,190,252,24,135,35,72,38,118,174,
+25,66,236,130,225,186,116,29,34,176,51,55,177,255,241,143,116,0,109,137,252,160,123,33,86,196,77,248,199,111,
+174,6,17,96,66,145,51,153,162,212,194,154,60,160,123,161,220,165,234,77,143,41,103,114,70,162,68,14,37,245,
+12,49,77,230,88,100,200,212,169,61,67,98,147,63,17,5,242,117,106,15,237,187,104,30,72,204,49,92,180,32,
+87,38,79,120,173,173,128,204,55,86,192,203,213,105,43,0,159,54,90,85,95,54,41,125,145,250,226,110,37,152,
+187,134,66,141,224,200,12,221,216,12,221,164,241,34,83,81,159,147,87,102,95,146,174,254,215,92,208,89,72,156,
+62,97,53,90,214,39,107,134,201,154,61,77,171,201,154,209,100,45,137,188,144,149,52,209,140,13,172,248,42,243,
+187,7,250,214,65,57,43,49,232,106,6,255,5,216,99,120,32,185,228,13,125,72,69,205,94,114,126,31,190,65,
+142,160,144,8,104,155,87,228,72,134,114,172,68,179,116,139,51,231,57,38,112,42,230,223,20,221,76,57,108,83,
+53,147,103,64,16,64,49,228,93,73,179,154,190,214,72,155,132,81,171,45,145,49,108,148,201,168,140,60,157,239,
+220,11,159,178,191,83,8,53,100,128,52,50,160,197,106,169,98,181,193,67,86,131,138,171,15,251,170,26,234,248,
+227,134,90,250,162,224,161,110,140,100,154,153,145,124,32,38,253,104,3,25,121,131,62,116,84,147,244,137,9,123,
+104,133,248,191,184,177,23,208,127,246,104,48,176,148,217,17,248,246,18,51,207,146,139,50,139,215,43,242,93,230,
+246,176,63,177,248,69,114,132,58,106,160,212,86,251,43,60,88,238,250,93,80,34,96,169,217,16,149,89,93,232,
+19,95,245,83,153,192,67,218,17,233,3,60,203,92,166,29,178,45,126,235,6,45,124,233,176,160,125,83,200,189,
+61,6,166,116,110,203,102,43,162,115,66,232,191,208,202,32,231,244,236,204,193,4,132,25,213,133,88,170,97,0,
+231,166,175,116,11,138,26,169,223,194,223,171,79,16,61,77,141,53,41,150,228,81,22,185,72,132,249,64,188,75,
+122,13,38,79,134,65,219,112,135,171,207,42,209,76,130,77,73,20,49,23,117,242,199,128,204,228,224,233,27,205,
+135,215,102,234,130,191,202,28,129,104,163,206,233,37,50,74,87,248,255,69,153,67,237,127,39,81,8,75,43,51,
+189,129,42,221,62,111,142,235,241,178,139,142,18,183,217,97,139,75,70,250,158,178,237,127,197,111,122,204,41,143,
+193,204,253,10,195,178,185,65,176,160,32,5,36,5,114,216,169,8,199,20,46,128,8,194,94,45,28,214,202,44,
+107,233,107,213,86,126,108,96,115,118,182,81,88,36,42,103,113,204,121,115,12,66,82,236,26,146,2,188,33,33,
+181,193,23,47,6,214,32,28,142,55,195,241,95,6,119,138,201,99,209,161,99,152,200,243,214,69,129,210,124,228,
+78,103,233,207,166,32,183,63,173,210,118,136,57,195,42,70,121,99,29,49,95,98,25,85,9,230,147,44,142,73,
+42,84,253,254,68,197,189,199,91,247,78,180,238,113,235,231,85,132,178,46,57,210,110,220,171,53,126,193,41,173,
+182,67,77,146,137,229,92,134,206,68,58,150,99,129,60,206,192,26,254,101,108,98,54,254,254,84,69,29,103,104,
+13,54,206,228,142,1,60,142,252,242,29,89,39,250,181,212,84,61,175,98,123,138,57,28,107,247,108,89,235,153,
+169,222,232,89,97,90,79,179,52,168,39,217,197,58,14,144,78,95,124,202,124,95,101,101,166,129,225,128,227,6,
+190,73,216,68,1,14,111,83,27,160,137,53,28,227,95,85,119,151,196,202,70,10,87,171,124,246,228,201,118,187,
+237,111,71,253,172,184,121,50,28,12,6,79,104,54,80,201,210,8,39,223,253,125,25,7,59,139,126,108,47,139,
+173,136,94,6,177,249,180,168,245,207,117,73,95,190,170,162,91,27,227,17,210,207,31,15,209,124,116,125,111,196,
+110,124,243,59,193,205,143,66,175,1,213,0,82,78,107,235,70,230,246,64,147,39,61,85,165,200,182,77,68,168,
+6,119,242,205,177,124,168,164,189,74,93,188,175,97,200,21,139,203,91,69,16,75,250,186,92,91,173,160,184,77,
+82,220,6,95,37,254,172,30,141,111,142,209,169,53,220,197,199,232,216,2,178,58,136,22,230,163,241,32,223,93,
+91,185,61,177,26,152,112,23,72,103,109,67,116,205,226,35,181,250,193,218,193,129,118,200,54,65,177,140,1,49,
+140,124,63,72,13,129,119,71,188,89,107,236,197,23,208,26,120,172,16,96,129,152,144,234,64,15,89,137,4,252,
+72,233,1,217,79,143,146,21,12,180,0,61,10,33,249,17,243,195,227,71,200,143,37,215,91,243,35,103,105,135,
+38,242,90,19,9,63,22,244,128,18,233,9,24,63,59,241,70,151,184,213,246,207,94,204,191,128,253,179,135,110,
+121,190,133,61,179,117,149,130,97,1,206,88,7,88,65,163,11,221,109,223,239,58,72,116,25,66,247,15,183,255,
+250,215,23,103,23,208,117,164,1,255,203,188,186,127,192,171,80,159,141,89,208,19,251,182,182,123,190,121,190,233,
+231,138,206,179,238,198,133,234,219,247,4,203,251,35,29,128,247,6,120,111,24,239,13,227,173,109,209,239,201,226,
+252,226,108,140,252,239,121,129,177,135,110,236,137,29,219,120,223,147,141,7,152,135,91,178,241,90,90,66,236,153,
+126,100,227,81,25,121,50,159,109,60,100,239,89,249,51,27,248,93,61,88,20,248,14,21,27,70,65,104,108,191,
+218,98,143,215,100,37,0,146,137,224,118,58,87,45,195,80,194,48,52,43,13,73,75,2,114,40,243,186,9,56,
+82,49,189,50,114,187,250,221,10,149,230,71,197,106,127,6,227,26,251,198,94,216,77,121,1,114,240,100,25,40,
+34,207,176,48,161,6,43,83,142,166,0,194,90,38,219,147,129,69,198,147,202,67,100,128,15,73,45,138,64,222,
+94,105,71,194,177,58,207,160,225,233,234,148,199,213,239,235,88,97,96,104,197,148,153,181,110,218,223,189,145,187,
+168,172,173,120,57,107,214,57,241,225,188,79,199,222,249,104,57,233,168,210,168,187,87,117,239,175,233,10,241,174,
+67,212,132,192,46,217,167,69,231,217,20,97,116,142,3,162,161,175,61,60,230,218,48,171,76,234,229,199,153,212,
+161,47,188,218,234,105,208,48,172,179,7,199,54,35,253,21,15,99,197,209,218,131,183,76,211,99,189,130,234,213,
+119,92,81,2,231,75,111,97,120,86,54,36,167,108,144,66,214,100,101,14,99,127,125,22,137,101,84,148,43,246,
+225,144,225,22,28,173,161,180,110,158,253,198,251,116,100,59,201,99,186,135,116,250,124,51,210,63,92,63,108,89,
+180,183,70,27,213,229,71,84,87,21,130,199,42,112,153,199,228,182,145,235,70,96,107,108,202,196,34,185,159,239,
+236,105,71,59,146,21,121,220,128,164,56,140,112,72,113,60,2,4,32,69,131,74,94,103,28,43,248,33,233,33,
+133,199,177,144,150,7,92,117,229,226,65,156,92,146,128,52,195,84,173,15,50,200,125,206,143,41,223,12,90,149,
+239,137,24,176,124,242,78,44,73,132,4,13,81,225,55,157,94,224,16,101,241,191,144,185,40,213,234,192,156,8,
+43,220,103,133,106,217,172,176,249,252,239,209,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,228,66,176,5,63,104,192,167,250,36,159,175,26,106,253,161,22,
+30,153,241,166,33,0,55,99,8,240,88,33,208,186,186,203,192,143,25,126,124,109,148,44,141,1,42,205,37,84,
+155,36,10,131,250,5,127,117,240,109,68,67,134,137,226,136,2,29,77,1,249,7,58,112,171,234,137,44,107,251,
+236,10,172,195,89,128,155,230,37,154,151,199,230,37,55,47,175,33,211,27,67,180,110,72,243,114,69,155,90,41,
+123,212,218,34,188,36,17,174,74,144,12,47,43,25,94,246,85,154,18,68,149,8,186,249,56,17,180,246,133,207,
+34,72,129,106,201,32,249,65,50,232,252,161,16,138,63,164,226,112,240,176,162,247,94,119,2,189,40,144,6,197,
+95,126,120,241,15,247,247,167,176,138,45,58,181,135,186,46,204,246,97,199,82,102,180,251,46,43,218,210,70,184,
+171,108,240,209,96,98,93,14,58,22,145,15,245,182,246,252,130,172,64,50,35,17,118,28,138,116,158,61,45,233,
+197,188,103,79,159,232,39,173,49,45,56,204,19,124,119,213,114,250,151,225,104,242,214,57,239,95,146,81,127,73,
+73,195,254,24,63,244,28,225,7,173,244,207,145,231,92,244,71,182,142,218,14,234,169,2,118,85,101,20,218,163,
+201,93,50,28,246,167,214,116,220,191,8,9,204,91,2,234,140,81,97,130,242,147,254,212,158,170,95,103,130,74,
+3,251,178,127,105,87,81,4,206,109,4,199,244,8,109,170,125,151,56,163,115,128,27,58,4,125,56,234,159,199,
+54,126,40,111,130,248,133,138,35,159,227,200,191,140,145,56,182,47,166,125,39,28,78,251,23,119,137,61,118,0,
+122,58,160,162,23,4,234,18,160,208,217,209,93,114,62,5,74,83,84,125,107,59,128,2,116,8,119,155,80,185,
+164,95,52,195,168,77,99,116,253,18,93,126,11,220,44,244,28,139,69,170,203,161,65,159,22,133,244,176,185,83,
+35,234,11,53,218,31,218,232,132,61,160,186,32,53,50,70,0,66,1,164,58,192,30,253,7,65,144,61,69,14,
+61,9,49,64,0,145,47,250,19,219,1,174,8,76,237,243,254,152,104,48,86,1,2,133,6,145,57,180,38,200,
+30,131,160,14,145,224,66,17,58,38,200,19,85,234,173,61,166,22,168,119,28,0,129,0,29,244,66,120,168,127,
+199,10,125,170,61,66,24,191,4,76,117,14,145,49,32,1,55,11,97,238,40,32,225,255,5,213,69,211,84,227,
+28,255,167,168,59,69,234,57,254,15,129,22,165,208,211,81,148,25,82,71,129,47,58,14,50,162,208,80,13,37,
+5,238,146,11,112,6,70,107,99,143,136,17,135,248,217,168,209,179,41,136,212,145,10,143,251,163,141,14,14,55,
+60,188,8,80,149,187,14,248,154,24,26,15,204,143,103,214,39,150,245,20,147,173,154,18,133,244,2,123,177,167,
+82,72,125,246,123,115,233,213,112,216,13,44,122,245,20,15,242,218,209,83,95,234,56,168,84,112,200,143,15,95,
+11,144,208,119,106,58,250,14,134,226,71,121,2,243,182,39,205,8,32,222,120,48,62,48,45,1,73,57,146,223,
+234,93,114,231,243,26,121,222,111,155,176,219,112,14,179,6,130,228,123,52,18,161,135,94,201,212,252,156,253,96,
+228,107,74,219,190,166,213,187,237,25,99,164,52,157,148,235,28,66,158,172,116,43,135,85,221,57,186,183,95,225,
+177,66,64,80,32,160,192,55,104,148,29,222,165,113,120,23,198,221,77,107,160,66,169,71,201,138,198,213,46,239,
+150,163,187,228,69,80,218,118,100,151,117,71,247,201,124,227,232,206,244,34,72,61,3,181,244,73,91,142,239,228,
+29,22,13,245,129,146,164,73,162,189,168,104,62,190,54,119,111,174,221,103,107,210,56,253,200,55,154,154,142,172,
+174,159,122,149,166,94,27,67,39,119,149,2,243,196,154,28,132,97,55,175,12,157,4,134,206,250,218,13,51,132,
+114,216,2,84,120,137,134,38,85,67,62,55,228,156,159,104,104,121,170,33,73,13,45,185,33,159,26,146,186,161,
+130,26,90,114,67,239,180,168,12,252,160,1,31,136,178,69,85,42,254,202,30,171,85,52,106,161,213,19,118,24,
+189,220,107,209,15,77,215,146,100,43,29,181,33,86,44,237,68,238,44,73,47,244,215,28,68,236,30,202,62,24,
+0,87,98,86,93,139,28,172,138,199,10,1,131,107,2,92,147,99,15,19,238,97,82,179,233,174,168,78,137,58,
+130,2,217,195,202,69,163,114,193,149,51,93,57,102,254,231,214,243,51,103,76,75,127,207,93,131,133,68,20,129,
+126,218,52,204,69,40,28,177,22,158,50,13,255,146,138,144,33,136,24,12,157,162,32,188,204,103,163,33,42,47,
+81,121,162,43,23,84,185,64,101,159,42,243,61,27,84,121,169,43,203,170,50,205,168,53,191,181,24,31,95,143,
+204,129,127,126,228,211,156,240,199,132,11,230,57,182,187,154,133,150,237,66,5,21,226,238,209,84,92,183,161,6,
+141,10,242,52,212,162,85,200,64,229,9,12,160,107,109,4,191,11,56,65,38,35,248,138,10,211,250,81,61,179,
+119,55,70,45,181,45,231,176,181,196,109,137,244,92,54,183,53,86,243,33,139,116,72,160,44,237,118,216,217,209,
+17,171,249,57,164,217,99,235,222,69,116,82,42,183,87,129,70,178,190,75,160,174,220,236,170,41,84,167,36,85,
+217,179,4,244,254,55,165,234,105,105,186,124,55,9,151,126,155,132,206,57,72,248,255,68,173,209,240,72,45,194,
+228,255,156,90,139,199,119,227,220,63,240,198,155,151,129,177,153,120,191,20,134,120,161,44,191,215,86,197,244,90,
+160,83,105,224,173,2,159,119,218,244,142,6,142,74,33,62,170,115,168,23,210,49,157,142,136,230,23,215,61,163,
+194,230,137,47,114,159,14,244,207,107,199,91,124,150,89,122,248,214,0,68,94,80,242,69,211,50,167,131,11,225,
+171,180,210,152,30,29,124,230,195,118,180,82,249,119,183,112,169,127,61,34,178,187,164,133,124,136,31,74,97,35,
+200,67,239,148,239,116,165,52,137,114,9,209,118,96,231,212,136,183,181,141,160,3,22,168,205,10,225,244,202,158,
+3,101,88,68,233,45,171,2,90,125,25,119,250,222,46,61,58,190,219,72,220,85,94,246,220,190,32,235,112,254,
+233,242,130,254,94,191,219,33,196,13,18,36,99,76,209,151,108,67,106,34,8,210,150,153,138,98,208,78,199,220,
+59,152,162,70,75,105,194,112,88,104,141,197,129,0,1,230,238,192,184,220,3,81,242,3,92,247,111,248,12,136,
+208,71,5,36,142,10,136,68,235,97,77,30,119,143,116,16,187,167,61,118,79,207,60,240,185,231,18,179,9,30,
+19,66,0,103,129,37,113,210,203,204,167,195,103,21,199,36,52,123,242,179,41,169,178,164,95,177,162,187,6,43,
+146,150,226,100,195,147,72,31,170,244,11,78,55,204,137,140,209,113,198,37,252,90,230,194,45,174,136,109,214,124,
+71,195,226,185,233,18,235,208,89,87,2,140,82,126,152,118,203,249,226,90,56,248,171,252,168,20,227,99,54,172,
+245,136,30,207,53,235,9,249,92,26,16,117,110,68,67,96,35,42,140,105,46,133,67,81,67,189,222,76,42,128,
+149,254,140,79,73,131,53,87,101,82,247,180,50,148,39,74,73,46,101,148,27,143,51,133,132,86,115,244,52,178,
+226,56,156,109,61,245,198,111,156,53,214,78,122,250,41,106,51,84,72,50,93,99,250,241,232,39,228,211,84,75,
+248,34,74,120,48,58,127,242,51,111,77,184,169,239,91,16,224,126,152,149,171,63,117,158,248,178,12,183,101,71,
+157,200,243,143,18,97,141,57,203,206,113,242,85,155,228,28,201,45,151,246,209,215,61,12,70,61,193,149,40,234,
+195,8,77,253,238,223,190,127,245,82,95,95,132,37,89,87,221,78,34,83,127,214,193,113,196,89,172,94,245,238,
+220,195,106,145,229,62,245,172,163,169,222,221,66,138,23,251,3,33,182,185,82,33,151,96,233,155,61,182,122,239,
+1,189,241,66,218,3,105,124,76,144,68,40,189,111,44,58,127,77,55,50,134,225,72,85,173,36,40,75,73,66,
+145,107,139,125,229,73,186,223,244,53,94,36,228,88,185,107,228,102,234,26,46,250,140,125,119,172,40,76,125,156,
+8,79,135,6,138,244,224,158,119,64,72,177,182,2,128,13,175,128,192,211,58,100,174,164,218,211,33,50,125,72,
+54,154,237,251,145,184,197,239,173,216,224,119,163,223,62,234,116,40,2,215,154,110,21,92,140,38,101,225,51,64,
+10,53,1,198,21,64,159,32,250,234,88,21,66,48,117,101,66,129,84,240,21,12,237,38,68,185,79,22,89,140,
+96,89,79,231,47,27,83,0,15,157,225,232,40,157,182,71,80,127,102,16,33,252,50,166,68,51,198,52,148,5,
+247,157,131,77,92,189,247,226,202,59,51,8,238,196,190,10,238,185,13,26,141,222,35,35,128,148,60,75,193,248,
+101,125,0,78,208,223,152,180,95,192,128,252,226,169,172,12,200,47,240,234,33,76,105,137,61,204,126,4,192,64,
+175,119,192,216,252,161,186,217,128,29,169,42,255,214,69,6,57,235,65,197,83,249,27,23,25,200,231,77,44,210,
+213,102,4,57,240,46,140,226,22,70,177,194,200,103,148,124,224,212,106,115,44,84,9,53,198,170,221,152,240,42,
+79,149,225,1,119,145,75,133,120,72,79,150,163,145,231,108,46,136,1,63,85,14,201,174,202,212,165,228,238,84,
+41,36,187,42,83,196,117,138,24,78,225,208,59,71,201,107,209,196,123,64,147,102,203,19,161,74,48,47,185,200,
+21,30,33,184,63,85,104,95,21,218,115,33,142,191,81,251,129,143,151,231,124,183,89,92,120,166,131,109,54,5,
+115,222,208,21,68,71,177,25,66,81,196,129,44,42,25,27,34,201,109,111,35,250,124,107,37,84,133,152,66,234,
+190,95,12,102,169,145,125,141,219,212,23,221,237,59,234,4,244,78,48,164,165,17,235,80,153,166,233,154,142,130,
+86,240,93,170,248,115,176,248,62,243,110,3,168,107,42,153,165,170,172,187,86,225,44,15,82,55,71,208,32,227,
+38,20,227,102,220,197,61,122,249,87,242,121,129,103,185,155,144,250,6,185,56,187,233,118,74,5,188,15,90,250,
+123,178,68,208,29,191,22,235,53,98,160,175,193,167,255,213,63,94,125,255,205,215,144,226,166,35,192,186,55,123,
+180,252,171,215,223,188,60,59,211,58,236,243,67,71,143,25,157,219,141,48,100,247,159,107,154,191,131,126,234,141,
+106,43,74,143,84,177,182,84,37,80,36,197,82,122,18,140,42,59,107,231,110,209,223,211,42,19,202,42,88,201,
+40,198,48,95,1,105,93,227,150,106,240,254,183,41,96,246,124,218,251,241,205,109,239,160,59,21,169,91,137,184,
+103,100,200,204,165,94,144,240,137,94,28,7,172,54,131,118,31,183,25,244,198,23,139,227,17,79,34,198,14,235,
+192,149,44,72,221,27,43,4,145,111,226,128,130,95,238,255,234,119,59,50,207,59,244,50,200,39,159,60,125,194,
+247,196,61,251,196,194,31,222,50,177,212,185,12,117,142,242,137,7,75,252,217,39,255,33,102,124,87,140,152,201,
+37,56,230,176,200,96,252,71,119,160,216,76,111,205,34,229,74,7,249,171,156,131,42,170,96,206,48,98,145,95,
+37,241,45,133,159,6,147,224,60,88,220,183,96,219,246,106,139,18,233,10,232,206,44,220,0,30,174,146,248,64,
+103,219,109,62,155,53,195,6,196,149,189,13,22,183,209,202,38,44,9,149,192,150,62,252,208,200,28,12,62,187,
+178,147,236,206,94,201,133,202,153,141,175,236,172,30,171,5,149,159,119,41,147,40,222,207,214,145,93,202,180,180,
+233,109,138,37,212,50,4,111,98,175,35,97,131,92,113,96,115,130,248,18,152,220,190,144,222,247,42,74,175,181,
+138,239,131,155,44,176,126,252,171,248,46,131,243,28,110,162,32,222,4,88,180,73,235,101,176,14,196,23,69,36,
+99,241,18,57,214,247,128,47,106,141,116,190,32,208,150,58,226,96,125,147,100,255,140,176,238,169,192,85,9,38,
+254,189,82,28,162,67,160,26,117,238,23,153,191,63,36,24,245,40,5,225,235,180,138,210,16,45,173,238,195,226,
+192,41,200,103,242,235,156,106,76,104,47,128,71,206,201,119,247,114,177,40,102,91,20,8,186,243,21,221,24,137,
+5,78,131,228,126,224,101,5,191,24,188,78,81,159,218,180,252,108,133,101,201,213,251,10,220,135,142,8,135,34,
+28,137,112,44,194,137,8,167,7,140,3,15,163,65,75,165,108,155,157,144,135,38,234,173,134,76,185,133,192,172,
+129,168,63,212,129,128,116,64,227,222,163,21,215,45,38,77,41,147,156,62,206,124,104,241,64,2,209,89,230,210,
+11,196,247,223,190,64,216,198,235,22,234,27,23,47,130,52,206,4,146,164,151,137,175,148,16,146,37,222,146,89,
+4,220,188,133,44,202,88,23,81,80,96,232,183,194,128,186,58,246,207,9,146,251,50,145,113,92,235,243,197,224,
+179,251,114,13,172,215,121,45,245,124,242,153,25,74,30,56,115,243,102,117,56,237,10,43,18,98,180,216,86,254,
+220,217,66,223,200,74,208,14,250,14,105,187,63,156,80,155,128,141,49,70,148,98,234,205,162,131,162,95,148,250,
+52,211,204,124,61,201,29,72,140,101,94,6,179,42,128,87,236,0,61,21,81,154,211,214,122,190,162,195,58,185,
+64,243,88,154,10,2,44,33,234,235,180,53,32,77,15,121,174,158,224,214,22,135,26,198,174,238,215,28,84,173,
+115,115,220,15,117,179,45,221,135,48,75,179,212,224,55,87,194,140,35,215,58,86,4,80,125,85,4,148,74,240,
+138,184,225,110,76,246,64,2,148,23,204,184,214,213,241,40,146,166,141,106,137,215,239,245,204,40,129,142,229,198,
+103,74,0,45,33,127,75,82,43,7,88,18,212,205,25,185,208,117,38,56,45,226,197,18,75,211,80,250,217,150,
+107,231,69,118,3,28,203,195,99,163,59,155,85,216,170,13,46,187,132,146,180,117,135,143,121,104,180,153,167,37,
+0,99,161,123,143,190,122,225,201,222,19,81,151,81,16,251,87,26,123,59,227,139,90,237,97,190,171,161,192,32,
+106,211,240,20,48,166,138,169,179,140,32,80,215,121,156,73,95,227,246,14,250,19,191,152,169,93,174,19,176,195,
+222,28,90,143,163,18,84,88,129,165,23,49,148,254,219,117,6,91,192,143,233,136,196,3,41,35,194,66,240,135,
+34,5,207,252,138,177,238,85,63,209,183,195,9,86,227,99,242,135,99,2,68,240,58,22,208,166,235,3,181,174,
+21,28,245,240,20,167,154,169,80,4,138,231,171,49,189,87,51,103,198,204,128,174,120,65,168,4,148,153,59,15,
+179,14,250,164,221,204,185,210,26,244,210,147,35,185,100,80,40,94,218,42,116,26,156,201,254,8,144,179,211,136,
+125,0,0,51,255,138,44,54,243,239,0,23,85,137,50,234,74,91,200,226,25,70,145,4,145,95,101,232,131,134,
+247,81,114,35,176,175,45,54,145,31,100,130,223,221,19,114,237,71,153,136,150,133,76,2,17,36,139,192,23,153,
+122,163,209,48,131,98,129,182,76,228,187,169,9,36,131,163,239,247,179,166,99,249,211,152,20,236,161,188,174,32,
+50,223,178,249,211,54,81,204,77,218,246,110,102,13,174,90,105,123,147,198,87,105,155,104,121,27,192,21,218,140,
+238,143,81,224,173,0,58,245,248,222,196,115,153,82,238,49,178,55,145,40,197,44,188,203,178,164,74,97,23,172,
+93,166,50,183,201,188,245,86,41,132,202,204,130,120,217,69,9,198,140,139,101,5,56,85,198,166,22,148,90,24,
+248,54,125,33,183,74,211,151,40,219,60,121,218,169,164,225,136,215,219,133,11,169,214,43,85,58,9,66,48,32,
+102,89,35,133,133,138,30,16,11,71,119,30,230,49,99,89,159,46,151,203,99,102,149,90,220,44,186,19,28,180,
+24,209,217,252,169,245,196,234,79,122,15,65,176,120,5,124,252,253,116,128,63,181,34,167,243,222,157,204,173,7,
+126,59,155,206,206,2,41,29,166,35,21,154,232,87,198,172,45,100,105,40,64,39,0,212,16,87,9,225,58,48,
+12,195,41,81,74,252,108,70,71,98,197,81,203,45,131,60,146,85,228,63,171,187,206,37,199,85,37,252,255,62,
+133,110,94,85,217,28,129,130,131,110,126,137,155,188,63,38,120,66,213,120,147,119,54,169,244,238,135,15,26,104,
+97,214,88,91,39,207,241,142,244,117,243,209,4,3,162,27,13,94,94,237,204,38,200,189,211,154,236,138,193,96,
+96,44,138,45,245,130,216,100,47,137,109,231,34,42,68,12,211,216,17,227,161,148,177,128,138,59,10,23,194,50,
+248,37,145,67,70,65,139,35,38,35,68,203,76,196,139,89,7,233,158,54,10,27,250,50,224,151,5,80,33,64,
+240,155,32,23,15,67,235,41,11,130,71,237,68,107,168,68,167,218,119,251,131,75,13,156,8,72,66,250,86,121,
+162,234,244,130,150,180,106,181,1,150,86,205,209,45,165,32,190,165,81,181,37,89,42,74,142,64,155,225,203,210,
+254,57,50,85,1,144,1,144,26,176,139,185,39,221,174,131,185,220,110,244,127,163,96,135,47,6,231,242,127,62,
+188,218,2,67,40,220,119,5,93,141,194,31,191,144,86,83,223,147,154,215,98,74,77,164,212,56,165,102,20,135,
+101,235,166,91,95,172,195,39,15,46,209,40,78,210,19,102,171,129,171,99,216,158,164,0,48,85,7,162,117,81,
+219,132,135,118,0,44,43,142,43,39,184,14,166,80,203,251,124,225,136,242,83,4,110,70,129,114,122,8,55,163,
+176,115,201,116,42,17,214,77,229,86,98,152,128,128,237,254,47,43,221,175,118,47,189,0,183,144,40,66,200,94,
+32,232,94,4,250,254,5,138,186,153,80,152,91,72,100,229,32,229,73,234,206,97,27,71,219,56,164,35,100,237,
+147,17,224,211,72,226,225,126,184,1,55,193,250,15,15,163,248,104,203,26,230,90,13,105,59,215,198,76,130,113,
+3,88,209,61,49,227,60,9,33,202,67,45,33,190,29,192,86,43,198,134,27,192,107,151,150,212,58,151,146,184,
+152,247,114,96,215,91,57,10,123,181,172,38,120,69,73,238,117,79,94,8,252,59,248,123,36,242,207,30,131,191,
+218,134,191,180,161,125,42,47,226,37,67,185,72,160,159,203,178,192,8,202,211,216,123,45,192,74,129,96,191,140,
+32,248,191,17,14,30,51,70,255,135,4,97,101,225,36,255,141,36,72,51,10,187,12,91,210,250,44,94,174,9,
+251,184,181,68,79,246,235,117,188,190,116,105,5,118,13,140,85,107,10,61,158,130,49,48,138,73,140,145,29,60,
+60,228,158,30,32,114,27,68,125,164,194,68,163,224,209,75,150,75,63,39,188,65,77,211,0,119,212,51,195,155,
+189,118,30,74,5,159,138,78,172,125,7,242,238,93,89,82,123,251,134,214,155,121,123,187,154,209,144,21,130,35,
+22,90,218,81,240,144,194,193,134,90,25,104,107,161,81,76,78,232,13,116,231,119,189,192,106,69,65,19,207,32,
+41,61,8,130,22,101,25,43,198,217,94,239,223,127,196,119,54,214,51,155,21,78,58,10,27,201,57,232,95,254,
+91,8,168,53,136,20,42,64,141,133,252,125,181,19,86,75,72,166,5,42,154,121,113,187,182,204,94,172,108,138,
+160,95,91,96,101,145,232,176,222,224,238,183,246,158,41,124,182,211,66,184,167,57,32,156,22,25,104,95,3,127,
+252,228,249,232,179,224,231,218,35,21,204,148,48,60,156,107,139,57,166,20,234,36,19,57,145,191,127,55,132,157,
+55,154,231,29,147,154,82,93,59,85,154,136,210,218,86,133,52,217,86,158,32,68,77,69,10,162,232,92,141,125,
+176,33,208,47,206,228,116,103,8,11,110,213,212,133,106,26,90,113,211,72,18,167,44,75,159,1,219,49,25,38,
+100,76,224,149,113,252,236,241,248,96,126,95,108,145,108,139,110,83,168,182,205,218,227,11,172,230,20,88,105,242,
+90,234,79,46,3,138,122,38,230,123,198,26,109,36,17,51,76,166,207,132,249,62,98,221,253,127,71,241,50,187,
+151,151,147,55,235,130,62,103,201,223,105,183,17,58,192,60,171,149,38,174,171,115,196,104,195,153,196,18,21,221,
+232,234,104,206,18,223,99,205,49,143,89,85,154,85,161,25,207,215,197,254,118,22,47,44,85,170,195,231,44,239,
+231,253,19,198,162,217,212,13,78,17,156,239,27,212,157,47,39,230,221,57,95,203,237,12,230,186,209,214,174,138,
+77,147,53,120,22,173,172,112,4,69,115,171,117,190,191,213,115,136,155,149,49,88,181,245,5,173,55,203,102,133,
+186,88,109,138,11,44,238,230,212,176,174,221,77,182,229,226,65,52,79,205,7,209,252,72,164,240,51,107,36,82,
+5,125,50,118,235,212,23,179,86,5,126,50,223,230,153,141,182,41,186,53,254,63,199,234,143,60,39,136,69,59,
+81,217,164,84,54,19,149,46,165,210,141,2,43,36,183,145,140,85,18,144,214,35,180,254,2,216,4,208,34,122,
+52,112,80,120,216,237,9,113,143,179,130,146,127,10,233,233,161,155,43,211,35,183,231,197,194,110,66,221,169,36,
+57,96,74,51,77,32,69,42,1,96,159,160,158,230,176,74,233,3,37,243,235,169,249,144,196,5,224,234,93,84,
+90,17,171,179,39,92,227,89,162,69,53,174,105,79,217,34,36,62,30,152,211,78,172,109,238,83,127,181,98,108,
+79,247,76,93,10,169,18,250,43,166,255,233,200,233,19,236,70,213,168,236,112,98,105,247,114,226,246,212,8,164,
+254,45,72,19,97,227,133,199,253,225,17,30,210,137,184,131,216,31,78,138,221,108,94,128,231,95,253,93,210,181,
+135,181,229,30,161,147,186,118,252,190,176,168,84,11,19,249,153,39,234,241,128,248,87,146,15,69,93,33,187,90,
+15,160,126,48,138,19,148,37,113,154,213,75,155,231,196,138,85,83,110,154,44,35,70,205,60,35,223,120,206,82,
+210,84,154,231,244,51,104,150,18,99,91,158,48,12,105,89,66,63,201,229,57,105,110,203,115,162,193,243,140,124,
+134,207,114,210,10,59,67,200,23,214,57,66,76,105,221,53,126,118,47,47,49,148,62,231,120,237,62,60,30,53,
+35,111,130,210,207,191,218,40,253,207,18,255,240,105,76,200,114,161,47,214,26,150,21,20,186,83,133,180,23,34,
+166,37,187,34,205,4,123,90,175,103,46,105,210,72,249,83,22,193,251,81,46,38,122,231,20,72,230,235,40,174,
+32,169,205,170,245,167,74,213,13,132,10,198,203,203,171,198,19,166,75,27,243,254,34,42,101,137,29,65,246,232,
+68,168,119,133,201,187,246,110,51,117,84,17,85,92,3,37,109,79,26,87,136,5,143,3,67,112,238,101,255,78,
+247,114,35,90,196,171,162,5,127,22,94,224,69,90,11,251,87,142,23,233,120,32,202,162,255,214,28,146,108,60,
+223,31,158,121,126,137,244,75,119,209,158,46,36,115,123,243,124,173,61,158,215,251,47,143,120,187,107,179,168,22,
+66,45,100,201,147,220,62,91,178,173,144,237,113,210,36,136,5,74,149,73,227,63,108,158,123,61,87,47,159,204,
+203,122,135,51,196,86,99,20,116,136,92,247,191,231,71,10,152,43,36,134,153,158,144,55,123,124,191,164,104,142,
+132,80,239,52,107,120,130,64,230,150,19,133,30,152,18,49,76,220,145,210,159,110,150,246,233,205,76,231,183,183,
+189,62,202,170,236,237,38,23,9,201,252,178,159,110,200,233,125,239,155,23,233,244,122,64,81,101,31,237,48,246,
+137,205,253,255,189,168,74,95,85,20,38,48,56,75,245,155,157,78,252,147,189,113,62,246,214,229,216,51,63,16,
+153,108,46,227,142,204,10,66,99,145,155,154,132,244,185,83,112,2,203,60,205,62,183,22,220,183,194,254,9,104,
+148,5,25,254,235,51,13,56,190,43,148,133,233,96,143,175,16,121,164,3,113,239,240,82,246,125,255,141,201,82,
+142,148,37,204,47,243,181,51,254,195,217,172,207,62,154,120,145,99,97,51,31,170,63,14,95,103,30,223,191,78,
+74,173,112,252,199,15,201,102,35,108,40,32,13,103,7,95,126,45,110,138,55,35,43,59,223,59,61,37,219,154,
+224,51,31,120,6,158,132,82,8,226,122,122,52,251,180,15,207,135,235,172,29,122,221,64,221,9,151,81,119,162,
+167,59,102,39,226,54,16,186,193,156,172,203,198,167,219,74,129,121,215,196,7,99,66,191,210,46,24,252,136,170,
+157,204,184,152,151,205,7,218,102,242,172,42,121,213,71,46,170,124,17,223,61,191,50,127,102,98,105,158,89,200,
+47,216,133,56,160,13,44,99,198,95,223,226,39,42,100,141,34,58,226,48,148,98,200,46,68,123,236,19,80,214,
+208,7,140,54,57,115,153,101,166,174,218,205,66,214,213,66,53,221,66,108,202,100,241,15,199,184,168,145,45,188,
+228,208,190,172,60,233,142,56,221,57,231,130,19,228,43,198,82,31,252,117,246,53,216,111,222,53,170,39,13,61,
+20,95,212,143,190,246,221,77,179,205,108,123,34,192,163,250,15,103,14,177,205,55,7,158,97,115,243,43,111,100,
+42,198,15,48,134,128,235,7,30,64,98,243,114,13,37,62,94,233,140,94,221,135,249,125,8,83,54,201,116,220,
+126,161,142,126,114,246,67,95,78,145,79,153,65,3,211,166,15,27,29,91,118,39,106,76,154,65,22,77,228,223,
+206,35,76,229,236,182,228,58,237,108,101,133,176,42,116,49,175,244,209,201,169,101,35,177,247,139,116,85,69,122,
+151,251,93,204,166,214,234,140,119,132,103,114,245,249,27,242,88,181,197,186,133,139,224,210,44,218,217,165,104,224,
+36,168,244,71,102,51,137,92,17,148,211,15,232,144,160,124,104,219,46,206,41,187,153,131,12,114,91,68,102,252,
+219,109,93,24,60,214,66,209,242,42,12,56,108,130,139,226,230,161,52,254,227,176,191,125,188,42,94,32,88,138,
+66,94,87,157,222,145,41,7,113,184,221,109,237,0,129,183,111,184,0,189,165,141,208,131,48,188,19,249,52,72,
+15,251,143,246,130,116,47,143,232,131,122,34,160,13,112,50,130,13,2,254,138,133,1,55,211,192,47,168,32,54,
+75,74,30,234,101,238,152,112,189,230,66,220,5,114,40,212,149,77,29,226,181,129,144,210,217,240,28,40,228,66,
+116,160,115,97,212,12,84,79,222,98,49,4,132,234,137,20,227,119,96,240,48,20,139,140,169,110,32,43,213,152,
+126,240,116,207,154,175,137,90,47,138,161,132,238,133,221,34,153,167,90,87,38,207,79,79,140,167,62,229,169,29,
+79,157,230,105,235,206,240,236,106,53,161,74,116,62,223,247,212,72,234,151,150,118,196,113,69,251,50,71,188,238,
+238,187,7,125,148,212,92,225,244,27,46,232,29,120,250,68,50,78,56,210,203,239,172,192,36,48,122,154,3,7,
+10,255,246,155,239,1,247,22,16,137,182,8,4,0
+};
diff --git a/lib/ESPDASH/src/dash_webpage.h b/lib/ESPDASH/src/dash_webpage.h
new file mode 100644
index 0000000..803e84f
--- /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[90104];
+
+#endif
diff --git a/lib/ESPDASH/src/vector.h b/lib/ESPDASH/src/vector.h
new file mode 100644
index 0000000..1c55e7f
--- /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 0000000..2b5457c
--- /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 0000000..e659a7c
--- /dev/null
+++ b/lib/MycilaAppInfo/MycilaAppInfo.cpp
@@ -0,0 +1,83 @@
+// 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 "Pro (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_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),
+ debug(firmware.indexOf("-debug") >= 0),
+ trial(firmware.indexOf("-trial") >= 0) {}
+
+String Mycila::AppInfoClass::getDownloadableFirmware() const {
+ int i = firmware.indexOf("-debug");
+ if (i >= 0)
+ return firmware.substring(0, i) + firmware.substring(i + 6);
+ i = firmware.indexOf("-trial");
+ if (i >= 0)
+ return firmware.substring(0, i) + firmware.substring(i + 6);
+ return firmware;
+}
+
+void Mycila::AppInfoClass::toJson(const JsonObject& root) const {
+ 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 0000000..ce1f7e0
--- /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();
+
+ String getDownloadableFirmware() const;
+
+ 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 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 0000000..808ac96
--- /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 0000000..2b5457c
--- /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 0000000..e62dc63
--- /dev/null
+++ b/lib/MycilaButton/MycilaButton.cpp
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+#include
+
+#define TAG "BUTTON"
+
+void Mycila::ButtonClass::begin() {
+ if (_enabled)
+ return;
+
+ if (!ButtonConfig.isEnabled())
+ return;
+
+ int32_t pin = ButtonConfig.getPin();
+ 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.info(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));
+ _button->attachLongPressHoldEventCb(
+ +[](void* handle, void* data) {
+ Mycila::ButtonClass* self = (Mycila::ButtonClass*)data;
+ self->_lastEvent = ButtonEvent::BUTTON_LONG_PRESS_HOLD;
+ },
+ this);
+ _button->attachSingleClickEventCb(
+ +[](void* handle, void* data) {
+ Mycila::ButtonClass* self = (Mycila::ButtonClass*)data;
+ self->_lastEvent = ButtonEvent::BUTTON_CLICKED;
+ },
+ this);
+
+ _enabled = true;
+}
+
+void Mycila::ButtonClass::end() {
+ if (!_enabled)
+ return;
+ Logger.info(TAG, "Disable Push Button...");
+ _enabled = false;
+ _button->del();
+ delete _button;
+ _button = nullptr;
+ _pin = GPIO_NUM_NC;
+}
+
+void Mycila::ButtonClass::loop() {
+ if (!_enabled)
+ return;
+ if (_lastEvent == ButtonEvent::BUTTON_CLICKED) {
+ _lastEvent = ButtonEvent::IDLE;
+ _callback(ButtonConfig.getPressAction());
+ } else if (_lastEvent == ButtonEvent::BUTTON_LONG_PRESS_HOLD) {
+ _lastEvent = ButtonEvent::IDLE;
+ _callback(ButtonConfig.getLongPressAction());
+ }
+}
+
+void Mycila::ButtonClass::toJson(const JsonObject& root) const {
+ root["enabled"] = _enabled;
+}
+
+namespace Mycila {
+ ButtonClass Button;
+ ButtonConfigClass ButtonConfig;
+} // namespace Mycila
diff --git a/lib/MycilaButton/MycilaButton.h b/lib/MycilaButton/MycilaButton.h
new file mode 100644
index 0000000..249efed
--- /dev/null
+++ b/lib/MycilaButton/MycilaButton.h
@@ -0,0 +1,53 @@
+// 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 ButtonConfigClass {
+ public:
+ int32_t getPin() const;
+ bool isEnabled() const;
+ String getPressAction() const;
+ String getLongPressAction() const;
+ };
+
+ class ButtonClass {
+ public:
+ ~ButtonClass() { end(); }
+
+ void begin();
+ void loop();
+ void end();
+
+ 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;
+ volatile ButtonEvent _lastEvent = ButtonEvent::IDLE;
+ ButtonActionCallback _callback;
+ gpio_num_t _pin = GPIO_NUM_NC;
+ };
+
+ extern ButtonConfigClass ButtonConfig;
+ extern ButtonClass Button;
+} // namespace Mycila
diff --git a/lib/MycilaButton/library.properties b/lib/MycilaButton/library.properties
new file mode 100644
index 0000000..059c616
--- /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 0000000..2b5457c
--- /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 0000000..11d2813
--- /dev/null
+++ b/lib/MycilaBuzzer/MycilaBuzzer.cpp
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+#include
+
+#define TAG "BUZZER"
+
+void Mycila::BuzzerClass::begin() {
+ if (_enabled)
+ return;
+
+ if (!BuzzerConfig.isEnabled())
+ return;
+
+ int32_t pin = BuzzerConfig.getPin();
+ 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.info(TAG, "Enable Buzzer...");
+ Logger.debug(TAG, "- Pin: %u", _pin);
+
+ _enabled = true;
+}
+
+void Mycila::BuzzerClass::end() {
+ if (_enabled) {
+ Logger.info(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;
+ BuzzerConfigClass BuzzerConfig;
+} // namespace Mycila
diff --git a/lib/MycilaBuzzer/MycilaBuzzer.h b/lib/MycilaBuzzer/MycilaBuzzer.h
new file mode 100644
index 0000000..1f1685a
--- /dev/null
+++ b/lib/MycilaBuzzer/MycilaBuzzer.h
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+#include
+
+namespace Mycila {
+ class BuzzerConfigClass {
+ public:
+ int32_t getPin() const;
+ bool isEnabled() const;
+ };
+
+ class BuzzerClass {
+ public:
+ void begin();
+ void end();
+
+ void toJson(const JsonObject& root) const;
+
+ void beep(uint8_t count = 1, uint32_t duration = 150) 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 BuzzerConfigClass BuzzerConfig;
+ extern BuzzerClass Buzzer;
+} // namespace Mycila
diff --git a/lib/MycilaBuzzer/library.properties b/lib/MycilaBuzzer/library.properties
new file mode 100644
index 0000000..0cdc099
--- /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 0000000..2b5457c
--- /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 0000000..8ff1a8c
--- /dev/null
+++ b/lib/MycilaDimmer/MycilaDimmer.cpp
@@ -0,0 +1,79 @@
+// 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() {
+ if (_enabled)
+ return;
+
+ if (!DimmerConfig.isEnabled(name)) {
+ Logger.warn(TAG, "Disable Dimmer '%s'", name);
+ return;
+ }
+
+ int32_t pin = DimmerConfig.getPin(name);
+ 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.info(TAG, "Enable Dimmer '%s'...", name);
+ Logger.debug(TAG, "- Pin: %u", _pin);
+ Logger.debug(TAG, "- Type: %s", DimmerTypeNames[static_cast(DimmerConfig.getType(name))]);
+
+ _dimmer = new DimmableLightLinearized(_pin);
+ _level = 0;
+ _dimmer->setBrightness(0);
+ _enabled = true;
+}
+
+void Mycila::Dimmer::end() {
+ if (_enabled) {
+ Logger.info(TAG, "Disable Dimmer '%s'", name);
+ _enabled = false;
+ _level = 0;
+ _dimmer->setBrightness(0);
+ delete _dimmer;
+ _dimmer = nullptr;
+ _pin = GPIO_NUM_NC;
+ }
+}
+
+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";
+}
+
+namespace Mycila {
+ DimmerConfigClass DimmerConfig;
+} // namespace Mycila
diff --git a/lib/MycilaDimmer/MycilaDimmer.h b/lib/MycilaDimmer/MycilaDimmer.h
new file mode 100644
index 0000000..6509e32
--- /dev/null
+++ b/lib/MycilaDimmer/MycilaDimmer.h
@@ -0,0 +1,67 @@
+// 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 DimmerConfigClass {
+ public:
+ bool isEnabled(const char* name) const;
+ int32_t getPin(const char* name) const;
+ DimmerType getType(const char* name) const;
+ };
+
+ class Dimmer {
+ public:
+ explicit Dimmer(const char* name) : name(name) {}
+
+ void begin();
+ 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; }
+
+ gpio_num_t getPin() const { return _pin; }
+ bool isEnabled() const { return _enabled; }
+
+ void toJson(const JsonObject& root) const;
+
+ public:
+ const char* name;
+
+ private:
+ bool _enabled = false;
+ uint8_t _level = 0;
+ gpio_num_t _pin = GPIO_NUM_NC;
+ DimmerLevelCallback _callback = nullptr;
+ DimmableLightLinearized* _dimmer = nullptr;
+ };
+
+ extern DimmerConfigClass DimmerConfig;
+} // namespace Mycila
diff --git a/lib/MycilaDimmer/library.properties b/lib/MycilaDimmer/library.properties
new file mode 100644
index 0000000..b6af791
--- /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/MycilaDisplay/LICENSE b/lib/MycilaDisplay/LICENSE
new file mode 100644
index 0000000..2b5457c
--- /dev/null
+++ b/lib/MycilaDisplay/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/MycilaDisplay/MycilaDisplay.cpp b/lib/MycilaDisplay/MycilaDisplay.cpp
new file mode 100644
index 0000000..4adc32d
--- /dev/null
+++ b/lib/MycilaDisplay/MycilaDisplay.cpp
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+#include
+
+#include
+
+#define TAG "DISPLAY"
+
+#define DISPLAY_FONT u8g2_font_5x8_tr
+#define DISPLAY_LINE_HEIGHT_PX 9
+
+static const char* DisplayTypeNames[] = {"SH1106", "SH1107", "SSD1306"};
+
+void Mycila::DisplayClass::begin() {
+ if (_enabled)
+ return;
+
+ if (!DisplayConfig.isEnabled())
+ return;
+
+ int32_t clkPin = DisplayConfig.getClockPin();
+ if (GPIO_IS_VALID_OUTPUT_GPIO(clkPin)) {
+ _clkPin = (gpio_num_t)clkPin;
+ } else {
+ Logger.error(TAG, "Invalid Clock pin: %u", _clkPin);
+ _clkPin = GPIO_NUM_NC;
+ return;
+ }
+
+ int32_t dataPin = DisplayConfig.getDataPin();
+ if (GPIO_IS_VALID_OUTPUT_GPIO(dataPin)) {
+ _dataPin = (gpio_num_t)dataPin;
+ } else {
+ Logger.error(TAG, "Invalid Data pin: %u", _dataPin);
+ _dataPin = GPIO_NUM_NC;
+ return;
+ }
+
+ DisplayType type = DisplayConfig.getType();
+
+ Logger.info(TAG, "Enable Display...");
+ Logger.debug(TAG, "- Type: %s", DisplayTypeNames[static_cast(type)]);
+ Logger.debug(TAG, "- Clock Pin: %u", _clkPin);
+ Logger.debug(TAG, "- Data Pin: %u", _dataPin);
+ Logger.debug(TAG, "- Rotation: %u°", DisplayConfig.getRotation());
+ Logger.debug(TAG, "- Power Save Delay: %u seconds", DisplayConfig.getPowerSaveDelay());
+
+ switch (type) {
+ case DisplayType::SSD1306:
+ switch (DisplayConfig.getRotation()) {
+ case 90:
+ _display = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(U8G2_R1, U8X8_PIN_NONE, _clkPin, _dataPin);
+ break;
+ case 180:
+ _display = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(U8G2_R2, U8X8_PIN_NONE, _clkPin, _dataPin);
+ break;
+ case 270:
+ _display = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(U8G2_R3, U8X8_PIN_NONE, _clkPin, _dataPin);
+ break;
+ default:
+ _display = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(U8G2_R0, U8X8_PIN_NONE, _clkPin, _dataPin);
+ break;
+ }
+ break;
+ case DisplayType::SH1106:
+ switch (DisplayConfig.getRotation()) {
+ case 90:
+ _display = new U8G2_SH1106_128X64_NONAME_F_HW_I2C(U8G2_R1, U8X8_PIN_NONE, _clkPin, _dataPin);
+ break;
+ case 180:
+ _display = new U8G2_SH1106_128X64_NONAME_F_HW_I2C(U8G2_R2, U8X8_PIN_NONE, _clkPin, _dataPin);
+ break;
+ case 270:
+ _display = new U8G2_SH1106_128X64_NONAME_F_HW_I2C(U8G2_R3, U8X8_PIN_NONE, _clkPin, _dataPin);
+ break;
+ default:
+ _display = new U8G2_SH1106_128X64_NONAME_F_HW_I2C(U8G2_R0, U8X8_PIN_NONE, _clkPin, _dataPin);
+ break;
+ }
+ break;
+ case DisplayType::SH1107:
+ switch (DisplayConfig.getRotation()) {
+ case 90:
+ _display = new U8G2_SH1107_64X128_F_HW_I2C(U8G2_R2, U8X8_PIN_NONE, _clkPin, _dataPin);
+ break;
+ case 180:
+ _display = new U8G2_SH1107_64X128_F_HW_I2C(U8G2_R3, U8X8_PIN_NONE, _clkPin, _dataPin);
+ break;
+ case 270:
+ _display = new U8G2_SH1107_64X128_F_HW_I2C(U8G2_R0, U8X8_PIN_NONE, _clkPin, _dataPin);
+ break;
+ default:
+ _display = new U8G2_SH1107_64X128_F_HW_I2C(U8G2_R1, U8X8_PIN_NONE, _clkPin, _dataPin);
+ break;
+ }
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ _display->begin();
+ _display->setPowerSave(false);
+ _display->setFont(DISPLAY_FONT);
+
+ _enabled = true;
+ _active = true;
+}
+
+void Mycila::DisplayClass::end() {
+ if (!_enabled)
+ return;
+ Logger.info(TAG, "Disable Display...");
+ _enabled = false;
+ _active = false;
+ _display->clear();
+ delete _display;
+ _dataPin = GPIO_NUM_NC;
+ _clkPin = GPIO_NUM_NC;
+}
+
+void Mycila::DisplayClass::loop() {
+ if (!_enabled)
+ return;
+
+ // readjust live power save state
+ const uint32_t delay = DisplayConfig.getPowerSaveDelay();
+ _powerSave.setEnable(delay > 0, false);
+
+ if (_active && delay > 0 && _powerSave.isAllowed(delay)) {
+ Logger.info(TAG, "Display power saving...");
+ _display->setPowerSave(true);
+ _active = false;
+
+ } else if (!_active && delay == 0) {
+ Logger.info(TAG, "Display power saving disabled");
+ _display->setPowerSave(false);
+ _active = true;
+ }
+}
+
+void Mycila::DisplayClass::setActive(bool active) {
+ if (!_enabled)
+ return;
+
+ if (active == _active)
+ return;
+
+ if (active && !_active) {
+ _display->setPowerSave(false);
+ _active = true;
+ } else if (!active && _active) {
+ _display->setPowerSave(true);
+ _active = false;
+ }
+}
+
+void Mycila::DisplayClass::print(const char lines[MYCILA_DISPLAY_LINE_COUNT][MYCILA_DISPLAY_LINE_LENGTH]) {
+ if (!_enabled)
+ return;
+
+ bool changed = false;
+ for (int i = 0; i < MYCILA_DISPLAY_LINE_COUNT; i++) {
+ if (strcmp(_lines[i], lines[i]) != 0) {
+ snprintf(_lines[i], MYCILA_DISPLAY_LINE_LENGTH, "%s", lines[i]);
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ _display->clearBuffer();
+ _display->drawStr(1, DISPLAY_LINE_HEIGHT_PX, _lines[0]);
+ _display->drawStr(1, 2 * DISPLAY_LINE_HEIGHT_PX + 1, _lines[1]);
+ _display->drawStr(1, 3 * DISPLAY_LINE_HEIGHT_PX + 2, _lines[2]);
+ _display->drawStr(1, 4 * DISPLAY_LINE_HEIGHT_PX + 3, _lines[3]);
+ _display->drawStr(1, 5 * DISPLAY_LINE_HEIGHT_PX + 4, _lines[4]);
+ _display->drawStr(1, 6 * DISPLAY_LINE_HEIGHT_PX + 5, _lines[5]);
+ _display->sendBuffer();
+
+ if (!_active)
+ _display->setPowerSave(false);
+
+ _active = true;
+ _powerSave.touch();
+ }
+}
+
+namespace Mycila {
+ DisplayClass Display;
+ DisplayConfigClass DisplayConfig;
+} // namespace Mycila
diff --git a/lib/MycilaDisplay/MycilaDisplay.h b/lib/MycilaDisplay/MycilaDisplay.h
new file mode 100644
index 0000000..26b271c
--- /dev/null
+++ b/lib/MycilaDisplay/MycilaDisplay.h
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+
+#include
+#include
+
+#define MYCILA_DISPLAY_LINE_COUNT 6
+#define MYCILA_DISPLAY_LINE_LENGTH 32
+
+namespace Mycila {
+ enum DisplayType {
+ SH1106 = 0,
+ SH1107,
+ SSD1306
+ };
+
+ class DisplayConfigClass {
+ public:
+ bool isEnabled() const;
+ DisplayType getType() const;
+ int32_t getClockPin() const;
+ int32_t getDataPin() const;
+ uint32_t getRotation() const;
+ uint32_t getPowerSaveDelay() const;
+ };
+
+ class DisplayClass {
+ public:
+ ~DisplayClass() { end(); }
+
+ void begin();
+ void end();
+ void loop();
+
+ void setActive(bool active);
+ // Up to 6 lines supported, 25 chars long
+ void print(const char lines[MYCILA_DISPLAY_LINE_COUNT][MYCILA_DISPLAY_LINE_LENGTH]);
+
+ bool isEnabled() const { return _enabled; }
+ // true if on, false if off or power saving
+ bool isActive() const { return _active; }
+
+ gpio_num_t getClockPin() const { return _clkPin; }
+ gpio_num_t getDataPin() const { return _dataPin; }
+
+ private:
+ bool _enabled = false;
+ bool _active = false;
+ DisplayType _display_type = DisplayType::SH1106;
+ U8G2* _display;
+ Throttle _powerSave = Throttle(true);
+ gpio_num_t _clkPin = GPIO_NUM_NC;
+ gpio_num_t _dataPin = GPIO_NUM_NC;
+ char _lines[MYCILA_DISPLAY_LINE_COUNT][MYCILA_DISPLAY_LINE_LENGTH];
+ };
+
+ extern DisplayConfigClass DisplayConfig;
+ extern DisplayClass Display;
+} // namespace Mycila
diff --git a/lib/MycilaGrid/LICENSE b/lib/MycilaGrid/LICENSE
new file mode 100644
index 0000000..2b5457c
--- /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 0000000..b2abe9d
--- /dev/null
+++ b/lib/MycilaGrid/MycilaGrid.cpp
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+
+#include
+#include
+#include
+#include
+
+#define TAG "POWER"
+
+void Mycila::GridClass::begin() {
+ _topic = GridConfig.getGridPowerMQTTTopic();
+
+ Logger.info(TAG, "Enable Grid Data...");
+ Logger.debug(TAG, "- MQTT Grid Power 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() {
+ Logger.info(TAG, "Disable Grid Data...");
+ if (!_topic.isEmpty()) {
+ MQTT.unsubscribe(_topic);
+ _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() ? JSY.power2 : (_isMQTTGridPowerExpired() ? 0 : _mqttGridPower);
+}
+
+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;
+ GridConfigClass GridConfig;
+} // namespace Mycila
diff --git a/lib/MycilaGrid/MycilaGrid.h b/lib/MycilaGrid/MycilaGrid.h
new file mode 100644
index 0000000..247957c
--- /dev/null
+++ b/lib/MycilaGrid/MycilaGrid.h
@@ -0,0 +1,43 @@
+// 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 GridConfigClass {
+ public:
+ String getGridPowerMQTTTopic() const;
+ };
+
+ class GridClass {
+ public:
+ void begin();
+ void end();
+
+ void toJson(const JsonObject& root) const;
+
+ float getFrequency() const;
+ float getPower() const;
+ float getVoltage() const;
+ inline bool isOnline() const { return getFrequency() > 0; }
+
+ private:
+ volatile float _mqttGridPower = 0;
+ volatile uint32_t _mqttGridPowerUpdateTime = 0;
+ String _topic;
+
+ private:
+ bool _isMQTTGridPowerExpired() const { return millis() - _mqttGridPowerUpdateTime >= YASOLR_MQTT_GRID_POWER_EXPIRATION * 1000; }
+ };
+
+ extern GridClass Grid;
+ extern GridConfigClass GridConfig;
+} // namespace Mycila
diff --git a/lib/MycilaGrid/library.properties b/lib/MycilaGrid/library.properties
new file mode 100644
index 0000000..8c331dd
--- /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 0000000..2b5457c
--- /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 0000000..1b315eb
--- /dev/null
+++ b/lib/MycilaHTTPd/MycilaHTTPd.cpp
@@ -0,0 +1,124 @@
+// 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::begin() {
+ if (_enabled)
+ return;
+
+ Logger.info(TAG, "Enable HTTPd...");
+ Logger.debug(TAG, "- Authentication: %s", (!HTTPdConfig.getUsername().isEmpty() && !HTTPdConfig.getPassword().isEmpty()) ? "true" : "false");
+ Logger.debug(TAG, "- Username: %s", HTTPdConfig.getUsername().c_str());
+ Logger.debug(TAG, "- Password: %s", HTTPdConfig.getPassword().isEmpty() ? "" : "********");
+
+ server.onNotFound([](AsyncWebServerRequest* request) {
+ request->send(404);
+ });
+ server.begin();
+ MDNS.addService("http", "tcp", 80);
+ _enabled = true;
+}
+
+void Mycila::HTTPdClass::end() {
+ if (!_enabled)
+ return;
+ Logger.info(TAG, "Disable HTTPd...");
+ server.end();
+ mdns_service_remove("_http", "_tcp");
+ _enabled = 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) {
+ const String _username = HTTPdConfig.getUsername();
+ const String _password = HTTPdConfig.getPassword();
+ const bool _auth = !_username.isEmpty() && !_password.isEmpty();
+ return handler->setAuthentication(anonymous ? "" : (_auth ? _username.c_str() : ""), anonymous ? "" : (_auth ? _password.c_str() : ""));
+}
+
+namespace Mycila {
+ HTTPdClass HTTPd;
+ HTTPdConfigClass HTTPdConfig;
+} // namespace Mycila
diff --git a/lib/MycilaHTTPd/MycilaHTTPd.h b/lib/MycilaHTTPd/MycilaHTTPd.h
new file mode 100644
index 0000000..3e2ceba
--- /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 HTTPdConfigClass {
+ public:
+ bool isEnabled() const;
+ String getUsername() const;
+ String getPassword() const;
+ };
+
+ class HTTPdClass {
+ public:
+ 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);
+
+ public:
+ AsyncWebServer server = AsyncWebServer(80);
+
+ private:
+ bool _enabled;
+
+ private:
+ AsyncWebHandler& _authenticate(AsyncWebHandler* handler, bool anonymous);
+ };
+
+ extern HTTPdConfigClass HTTPdConfig;
+ extern HTTPdClass HTTPd;
+} // namespace Mycila
diff --git a/lib/MycilaHTTPd/library.properties b/lib/MycilaHTTPd/library.properties
new file mode 100644
index 0000000..af7d0dc
--- /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 0000000..2b5457c
--- /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 0000000..2033523
--- /dev/null
+++ b/lib/MycilaLights/MycilaLights.cpp
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+#include
+
+#define TAG "LIGHTS"
+
+void Mycila::LightsClass::begin(LightState green, LightState yellow, LightState red) {
+ if (LightsConfig.isEnabled()) {
+ Logger.info(TAG, "Enable Physical LEDs...");
+
+ int32_t greenPin = LightsConfig.getGreenPin();
+ 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;
+ }
+
+ int32_t yellowPin = LightsConfig.getYellowPin();
+ 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;
+ }
+
+ int32_t redPin = LightsConfig.getRedPin();
+ 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;
+ }
+ }
+
+ set(green, yellow, red);
+}
+
+void Mycila::LightsClass::end() {
+ Logger.info(TAG, "Disable Physical LEDs...");
+ set(LightState::OFF, LightState::OFF, LightState::OFF);
+ _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;
+ LightsConfigClass LightsConfig;
+} // namespace Mycila
diff --git a/lib/MycilaLights/MycilaLights.h b/lib/MycilaLights/MycilaLights.h
new file mode 100644
index 0000000..b6c86d0
--- /dev/null
+++ b/lib/MycilaLights/MycilaLights.h
@@ -0,0 +1,71 @@
+// 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 LightsConfigClass {
+ public:
+ int32_t getGreenPin() const;
+ int32_t getYellowPin() const;
+ int32_t getRedPin() const;
+ bool isEnabled() const;
+ };
+
+ class LightsClass {
+ public:
+ void begin(LightState green = LightState::NONE, LightState yellow = LightState::NONE, LightState red = LightState::NONE);
+ 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 LightsConfigClass LightsConfig;
+ extern LightsClass Lights;
+} // namespace Mycila
diff --git a/lib/MycilaLights/library.properties b/lib/MycilaLights/library.properties
new file mode 100644
index 0000000..c00ff5b
--- /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/MycilaOTA/LICENSE b/lib/MycilaOTA/LICENSE
new file mode 100644
index 0000000..2b5457c
--- /dev/null
+++ b/lib/MycilaOTA/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/MycilaOTA/MycilaOTA.cpp b/lib/MycilaOTA/MycilaOTA.cpp
new file mode 100644
index 0000000..f1f7a87
--- /dev/null
+++ b/lib/MycilaOTA/MycilaOTA.cpp
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+#include
+#include
+
+#include
+#include
+
+#ifdef APP_VERSION_PRO
+#include
+#else
+#include
+#endif
+
+#define TAG "OTA"
+
+void Mycila::OTAClass::begin() {
+ if (_enabled)
+ return;
+
+ const String hostname = OTAConfig.getHostname();
+
+ if (hostname.isEmpty())
+ return;
+
+ Logger.info(TAG, "Enable OTA...");
+
+ const String password = OTAConfig.getPassword();
+
+ Logger.debug(TAG, "- ota://%s:%u", hostname.c_str(), MYCILA_OTA_PORT);
+ ArduinoOTA.setHostname(hostname.c_str());
+ ArduinoOTA.setPort(MYCILA_OTA_PORT);
+ if (!password.isEmpty())
+ ArduinoOTA.setPassword(password.c_str());
+ ArduinoOTA.setRebootOnSuccess(false);
+ ArduinoOTA.onStart([this]() {
+ if (_prepareCallback)
+ _prepareCallback();
+ });
+ ArduinoOTA.onEnd([this]() {
+ if (_completeCallback)
+ _completeCallback(true);
+ });
+ ArduinoOTA.onError([this](ota_error_t error) {
+ if (_completeCallback)
+ _completeCallback(false);
+ });
+ ArduinoOTA.setMdnsEnabled(true);
+ ArduinoOTA.begin();
+ ArduinoOTA.setMdnsEnabled(false); // so that end() does not end MDNS
+
+ Logger.debug(TAG, "- http://%s/update", (hostname + (hostname.indexOf(".") >= 0 ? "" : ".local")).c_str());
+ if (!_elegantOTAInitialized) {
+#ifdef APP_VERSION_PRO
+ ElegantOTA.setID(OTAConfig.getID().c_str());
+ ElegantOTA.setTitle(OTAConfig.getTitle().c_str());
+ ElegantOTA.setFWVersion(OTAConfig.getFWVersion().c_str());
+ ElegantOTA.setFirmwareMode(true);
+ ElegantOTA.setFilesystemMode(false);
+#endif
+ ElegantOTA.setAutoReboot(false);
+ ElegantOTA.setAuth(OTAConfig.getUsername().c_str(), OTAConfig.getPassword().c_str());
+ ElegantOTA.onStart([this]() {
+ if (_prepareCallback)
+ _prepareCallback();
+ });
+ ElegantOTA.onEnd([this](bool success) {
+ if (_completeCallback)
+ _completeCallback(success);
+ });
+ ElegantOTA.begin(&HTTPd.server, OTAConfig.getUsername().c_str(), OTAConfig.getPassword().c_str());
+ _elegantOTAInitialized = true;
+ }
+
+ _enabled = true;
+}
+
+void Mycila::OTAClass::loop() {
+ if (_enabled) {
+ ArduinoOTA.handle();
+#ifdef APP_VERSION_PRO
+ ElegantOTA.loop();
+#endif
+ }
+}
+
+void Mycila::OTAClass::end() {
+ if (!_enabled)
+ return;
+ Logger.info(TAG, "Disable OTA...");
+ MDNS.disableArduino();
+ ArduinoOTA.end();
+ _enabled = false;
+}
+
+namespace Mycila {
+ OTAClass OTA;
+ OTAConfigClass OTAConfig;
+} // namespace Mycila
diff --git a/lib/MycilaOTA/MycilaOTA.h b/lib/MycilaOTA/MycilaOTA.h
new file mode 100644
index 0000000..dd3eb77
--- /dev/null
+++ b/lib/MycilaOTA/MycilaOTA.h
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+
+#ifndef MYCILA_OTA_PORT
+#define MYCILA_OTA_PORT 3232
+#endif
+
+namespace Mycila {
+ typedef std::function OTACompleteCallback;
+ typedef std::function OTAPrepareCallback;
+
+ class OTAConfigClass {
+ public:
+ String getHostname() const;
+ String getUsername() const;
+ String getPassword() const;
+
+ String getID() const;
+ String getTitle() const;
+ String getFWVersion() const;
+ };
+
+ class OTAClass {
+ public:
+ void listen(OTACompleteCallback callback) { _completeCallback = callback; }
+ void listen(OTAPrepareCallback callback) { _prepareCallback = callback; }
+
+ void begin();
+ void loop();
+ void end();
+
+ bool isEnabled() const { return _enabled; }
+
+ private:
+ bool _enabled = false;
+ bool _elegantOTAInitialized = false;
+ OTAPrepareCallback _prepareCallback = nullptr;
+ OTACompleteCallback _completeCallback = nullptr;
+ };
+
+ extern OTAConfigClass OTAConfig;
+ extern OTAClass OTA;
+} // namespace Mycila
diff --git a/lib/MycilaOTA/library.properties b/lib/MycilaOTA/library.properties
new file mode 100644
index 0000000..b51202e
--- /dev/null
+++ b/lib/MycilaOTA/library.properties
@@ -0,0 +1,5 @@
+name=MycilaOTA
+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 0000000..2b5457c
--- /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 0000000..37e4727
--- /dev/null
+++ b/lib/MycilaRelayManager/MycilaRelayManager.cpp
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+
+#include
+#include
+#include
+
+#define TAG "RELAY-M"
+
+void Mycila::RelayManagerClass::begin() {
+ for (auto& relay : relays) {
+ relay.begin();
+ }
+}
+
+void Mycila::RelayManagerClass::end() {
+ for (auto& relay : relays) {
+ relay.end();
+ }
+}
+
+void Mycila::RelayManagerClass::toJson(const JsonObject& root) const {
+ for (int i = 0; i < relays.size(); i++) {
+ auto& relay = relays[i];
+ JsonObject outputJson = root[relay.name].to();
+ relay.toJson(outputJson);
+ }
+}
+
+void Mycila::RelayManagerClass::loop() {
+ if (millis() - _lastCheck >= MYCILA_RELAY_PAUSE_DURATION * 1000) {
+ 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.name);
+ if (threshold > 0 && grid <= -(threshold + round(threshold * MYCILA_RELAY_THRESHOLD_TOLERANCE_START / 100.0))) {
+ Logger.info(TAG, "Excess above %u W +%u%%: starting relay '%s'...", threshold, MYCILA_RELAY_THRESHOLD_TOLERANCE_START, relay.name);
+ 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.name);
+ if (threshold > 0 && grid - threshold >= -(threshold - round(threshold * MYCILA_RELAY_THRESHOLD_TOLERANCE_STOP / 100.0))) {
+ Logger.info(TAG, "Excess below %u W -%u%%: stopping relay '%s'...", threshold, MYCILA_RELAY_THRESHOLD_TOLERANCE_STOP, relay.name);
+ relay.setState(false);
+ // we stop the loop and let time for routing to adjust before checking again
+ return;
+ }
+ }
+ }
+ }
+
+ _lastCheck = millis();
+ }
+}
+
+bool Mycila::RelayManagerClass::tryRelayState(int idx, bool switchOn, uint32_t duration) {
+ auto& relay = relays[idx];
+
+ if (!relay.isEnabled())
+ return false;
+
+ if (RelayManagerConfig.getPowerThreshold(relay.name) > 0) {
+ Logger.warn(TAG, "Auto Mode '%s' is activated: unable to switch Relay...", relay.name);
+ return false;
+ }
+
+ relay.setState(switchOn, duration);
+ _lastCheck = millis();
+ 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 0000000..afde583
--- /dev/null
+++ b/lib/MycilaRelayManager/MycilaRelayManager.h
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#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
+
+#ifndef MYCILA_RELAY_PAUSE_DURATION
+#define MYCILA_RELAY_PAUSE_DURATION 60
+#endif
+
+namespace Mycila {
+
+ class RelayManagerConfigClass {
+ public:
+ uint16_t getPowerThreshold(const char* name) const;
+ };
+
+ class RelayManagerClass {
+ public:
+ void begin();
+ void loop();
+ void end();
+
+ void toJson(const JsonObject& root) const;
+
+ bool tryRelayState(int idx, bool state, uint32_t duration = 0);
+
+ public:
+ std::vector relays;
+
+ private:
+ uint32_t _lastCheck = 0;
+ };
+
+ 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 0000000..3c3b9e9
--- /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 0000000..2b5457c
--- /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 0000000..b4259a9
--- /dev/null
+++ b/lib/MycilaRouter/MycilaRouter.cpp
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+
+#include
+#include
+#include
+
+#define TAG "ROUTER"
+
+void Mycila::RouterClass::begin() {
+ for (auto& output : outputs) {
+ output.begin();
+ }
+}
+
+void Mycila::RouterClass::end() {
+ for (auto& output : outputs) {
+ output.end();
+ }
+}
+
+void Mycila::RouterClass::loop() {
+ outputs[_loopIdx].loop();
+ _loopIdx = (_loopIdx + 1) % outputs.size();
+}
+
+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 (int i = 0; i < outputs.size(); i++) {
+ auto& output = outputs[i];
+ JsonObject outputJson = root[output.name].to();
+ output.toJson(outputJson);
+ outputJson["power"] = getOutputPower(i);
+ }
+}
+
+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;
+}
+
+float Mycila::RouterClass::getOutputPower(int idx) const {
+ int routing = 0;
+ float dimmerLevel = 0;
+
+ for (size_t i = 0, max = outputs.size(); i < max; i++) {
+ const uint8_t level = outputs[i].dimmer.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 = getOutputResistance(idx);
+
+ return (u * u / r) * (dimmerLevel / 100.0);
+}
+
+float Mycila::RouterClass::getOutputResistance(int idx) const {
+ // TODO: auto-calibration or config ?
+ return 227.34;
+}
+
+namespace Mycila {
+ RouterClass Router;
+} // namespace Mycila
diff --git a/lib/MycilaRouter/MycilaRouter.h b/lib/MycilaRouter/MycilaRouter.h
new file mode 100644
index 0000000..3986bec
--- /dev/null
+++ b/lib/MycilaRouter/MycilaRouter.h
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+
+#include
+#include
+
+namespace Mycila {
+ class RouterClass {
+ public:
+ void begin();
+ void loop();
+ void end();
+
+ void toJson(const JsonObject& root) const;
+
+ float getVirtualGridPower() const;
+ float getTotalRoutedPower() const;
+ float getTotalPowerFactor() const;
+ float getTotalTHDi() const;
+ float getTotalRoutedEnergy() const;
+
+ float getOutputPower(int idx) const;
+ float getOutputResistance(int idx) const;
+
+ inline bool isRouting() const { return outputs[0].getState() == RouterOutputState::OUTPUT_ROUTING || outputs[1].getState() == RouterOutputState::OUTPUT_ROUTING; }
+
+ public:
+ std::vector outputs;
+ uint8_t _loopIdx = 0;
+ };
+
+ extern RouterClass Router;
+} // namespace Mycila
diff --git a/lib/MycilaRouter/library.properties b/lib/MycilaRouter/library.properties
new file mode 100644
index 0000000..d54acb7
--- /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 0000000..2b5457c
--- /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 0000000..846eaf6
--- /dev/null
+++ b/lib/MycilaRouterOutput/MycilaRouterOutput.cpp
@@ -0,0 +1,270 @@
+// 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"};
+
+Mycila::RouterOutput::RouterOutput(const char* name) : name(name),
+ dimmer(name),
+ relay(name),
+ temperatureSensor(name) {}
+
+void Mycila::RouterOutput::begin() {
+ dimmer.begin();
+ relay.begin();
+ temperatureSensor.begin();
+
+ if (isEnabled()) {
+ Logger.debug(TAG, "Enable Router Output '%s'...", name);
+ Logger.debug(TAG, " - Dimmer: %s", RouterOutputConfig.isAutoDimmerEnabled(name) ? "auto" : "manual");
+ Logger.debug(TAG, " - Dimmer Level Limit: %u %", RouterOutputConfig.getDimmerLevelLimit(name));
+ Logger.debug(TAG, " - Bypass: %s", RouterOutputConfig.isAutoBypassEnabled(name) ? "auto" : "manual");
+ Logger.debug(TAG, " - Auto Time: %s to %s %s", RouterOutputConfig.getAutoStartTime(name).c_str(), RouterOutputConfig.getAutoStopTime(name).c_str(), RouterOutputConfig.getWeekDays(name).c_str());
+ Logger.debug(TAG, " - Auto Start Temperature: %u °C", RouterOutputConfig.getAutoStartTemperature(name));
+ Logger.debug(TAG, " - Auto Stop Temperature: %u °C", RouterOutputConfig.getAutoStopTemperature(name));
+
+ } else {
+ Logger.warn(TAG, "Disable Router Output '%s'...", name);
+ }
+}
+
+void Mycila::RouterOutput::end() {
+ _autoBypassEnabled = false;
+ dimmer.off();
+ relay.off();
+ dimmer.end();
+ relay.end();
+ temperatureSensor.end();
+}
+
+void Mycila::RouterOutput::loop() {
+ temperatureSensor.loop();
+
+ if (!dimmer.isEnabled())
+ return;
+
+ if (millis() - _lastCheck >= 500) {
+ // Auto BP rules
+ _autoBypassLoop();
+
+ // dimmer limit
+ if (!_autoBypassEnabled && dimmer.isOn()) {
+ uint8_t limit = RouterOutputConfig.getDimmerLevelLimit(dimmer.name);
+ if (dimmer.getLevel() > limit) {
+ Logger.warn(TAG, "Dimmer '%s' reached its limit at %u %", dimmer.name, limit);
+ dimmer.setLevel(limit);
+ }
+ }
+
+ _lastCheck = millis();
+ }
+}
+
+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.name, 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);
+}
+
+void Mycila::RouterOutput::_autoBypassLoop() {
+ 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 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);
+}
+
+// _setBypassRelay
+void Mycila::RouterOutput::_setBypassRelay(bool state) {
+ if (relay.isEnabled()) {
+ Logger.debug(TAG, "Turning %s Bypass Relay '%s'...", state ? "on" : "off", relay.name);
+ if (state)
+ dimmer.off();
+ relay.setState(state);
+
+ } else {
+ Logger.debug(TAG, "Turning %s Dimmer '%s'...", state ? "on" : "off", dimmer.name);
+ 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 0000000..921183a
--- /dev/null
+++ b/lib/MycilaRouterOutput/MycilaRouterOutput.h
@@ -0,0 +1,81 @@
+// 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:
+ explicit RouterOutput(const char* name);
+
+ void begin();
+ void loop();
+ void end();
+
+ RouterOutputState getState() const;
+ const char* getStateString() const;
+ bool isEnabled() const { return dimmer.isEnabled(); }
+
+ 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);
+
+ void toJson(const JsonObject& root) const;
+
+ public:
+ const char* name;
+ Dimmer dimmer;
+ Relay relay;
+ TemperatureSensor temperatureSensor;
+
+ private:
+ bool _autoBypassEnabled = false;
+ RouterOutputStateCallback _callback = nullptr;
+ u_int32_t _lastCheck = 0;
+
+ private:
+ void _autoBypassLoop();
+ 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 0000000..1758f57
--- /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 0000000..2b5457c
--- /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 0000000..b01f514
--- /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...");
+ if (_callback)
+ _callback(SystemEvent::BEFORE_RESET);
+ nvs_flash_erase();
+ nvs_flash_init();
+ esp_restart();
+}
+
+void Mycila::SystemClass::restart() {
+ Logger.debug(TAG, "Triggering System Restart...");
+ if (_callback)
+ _callback(SystemEvent::BEFORE_RESTART);
+ 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 0000000..5d978dc
--- /dev/null
+++ b/lib/MycilaSystem/MycilaSystem.h
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+#include
+#include
+
+namespace Mycila {
+ enum class SystemEvent {
+ BEFORE_RESET,
+ BEFORE_RESTART,
+ };
+
+ typedef std::function SystemEventCallback;
+
+ typedef struct {
+ uint32_t total;
+ uint32_t used;
+ uint32_t free;
+ float usage;
+ } SystemMemory;
+
+ class SystemClass {
+ public:
+ void begin();
+
+ void listen(SystemEventCallback callback) { _callback = callback; }
+
+ void reset();
+ void restart();
+
+ 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;
+
+ private:
+ SystemEventCallback _callback = nullptr;
+ };
+
+ extern SystemClass System;
+} // namespace Mycila
diff --git a/lib/MycilaSystem/library.properties b/lib/MycilaSystem/library.properties
new file mode 100644
index 0000000..1646a9d
--- /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/MycilaTemperatureSensor/LICENSE b/lib/MycilaTemperatureSensor/LICENSE
new file mode 100644
index 0000000..2b5457c
--- /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 0000000..4b8d304
--- /dev/null
+++ b/lib/MycilaTemperatureSensor/MycilaTemperatureSensor.cpp
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#include
+#include
+
+#define TAG "DS18B20"
+
+void Mycila::TemperatureSensor::begin() {
+ if (_enabled)
+ return;
+
+ if (!TemperatureSensorConfig.isEnabled(name))
+ return;
+
+ int32_t pin = TemperatureSensorConfig.getPin(name);
+ 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.info(TAG, "Enable Temperature Sensor '%s'...", name);
+ Logger.debug(TAG, "- Pin: %u", _pin);
+ Logger.debug(TAG, "- Refresh Interval: %u seconds", MYCILA_TEMPERATURE_READ_INTERVAL);
+
+ _enabled = true;
+}
+
+void Mycila::TemperatureSensor::end() {
+ if (_enabled) {
+ Logger.info(TAG, "Disable Temperature Sensor '%s'...", name);
+ _enabled = false;
+ _temperature = 0;
+ _lastUpdate = 0;
+ _pin = GPIO_NUM_NC;
+ }
+}
+
+void Mycila::TemperatureSensor::loop() {
+ if (!_enabled)
+ return;
+ if (millis() - _lastRead >= MYCILA_TEMPERATURE_READ_INTERVAL * 1000) {
+ _read();
+ _lastRead = millis();
+ }
+}
+
+void Mycila::TemperatureSensor::_read() {
+ 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();
+}
+
+namespace Mycila {
+ TemperatureSensorConfigClass TemperatureSensorConfig;
+} // namespace Mycila
diff --git a/lib/MycilaTemperatureSensor/MycilaTemperatureSensor.h b/lib/MycilaTemperatureSensor/MycilaTemperatureSensor.h
new file mode 100644
index 0000000..7f9dfc8
--- /dev/null
+++ b/lib/MycilaTemperatureSensor/MycilaTemperatureSensor.h
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023-2024 Mathieu Carbou and others
+ */
+#pragma once
+
+#include
+#include
+#include
+
+#ifndef MYCILA_TEMPERATURE_READ_INTERVAL
+#define MYCILA_TEMPERATURE_READ_INTERVAL 10
+#endif
+
+namespace Mycila {
+ typedef std::function TemperatureChangeCallback;
+
+ class TemperatureSensorConfigClass {
+ public:
+ bool isEnabled(const char* name) const;
+ int32_t getPin(const char* name) const;
+ };
+
+ class TemperatureSensor {
+ public:
+ explicit TemperatureSensor(const char* name) : name(name) {}
+ ~TemperatureSensor() { end(); }
+
+ void begin();
+ void loop();
+ void end();
+
+ void listen(TemperatureChangeCallback callback) { _callback = callback; }
+
+ float getTemperature() const { return _temperature; }
+ bool isEnabled() const { return _enabled; }
+ bool isValid() const { return millis() - _lastUpdate < 6 * MYCILA_TEMPERATURE_READ_INTERVAL * 1000; }
+ u_int32_t getLastUpdate() const { return _lastUpdate; }
+ String getTemperatureAsString() const;
+ gpio_num_t getPin() const { return _pin; };
+
+ void toJson(const JsonObject& root) const;
+
+ public:
+ const char* name;
+
+ private:
+ u_int32_t _lastRead = 0;
+ OneWire _oneWire;
+ DallasTemperature _dallas;
+ bool _enabled = false;
+ gpio_num_t _pin = GPIO_NUM_NC;
+ float _temperature = 0;
+ uint32_t _lastUpdate = 0;
+ TemperatureChangeCallback _callback = nullptr;
+
+ private:
+ void _read();
+ };
+
+ extern TemperatureSensorConfigClass TemperatureSensorConfig;
+} // namespace Mycila
diff --git a/lib/MycilaTemperatureSensor/library.properties b/lib/MycilaTemperatureSensor/library.properties
new file mode 100644
index 0000000..7838757
--- /dev/null
+++ b/lib/MycilaTemperatureSensor/library.properties
@@ -0,0 +1,5 @@
+name=MycilaTemperatureSensor
+version=1.0.0
+author=Mathieu Carbou