Merge remote-tracking branch 'upstream/main' into mdev

This commit is contained in:
Ewoud
2023-02-06 21:06:13 +01:00
27 changed files with 4603 additions and 4258 deletions

View File

@@ -20,6 +20,7 @@
- usermod enhancements (PIR, Temperature, Battery (PR #2975), Analog Clock (PR #2993)) - usermod enhancements (PIR, Temperature, Battery (PR #2975), Analog Clock (PR #2993))
- new usermod SHT (PR #2963) - new usermod SHT (PR #2963)
- 2D matrix set up with gaps or irregular panels (breaking change!) (PR #2892) - 2D matrix set up with gaps or irregular panels (breaking change!) (PR #2892)
- palette blending/transitions
- random palette smooth changes - random palette smooth changes
- hex color notations in custom palettes - hex color notations in custom palettes
- allow more virtual buses - allow more virtual buses
@@ -34,6 +35,7 @@
- [internal] completely rewritten Segment & WS2812FX handling code - [internal] completely rewritten Segment & WS2812FX handling code
- [internal] ability to add custom effects via usermods - [internal] ability to add custom effects via usermods
- [internal] set of 2D drawing functions - [internal] set of 2D drawing functions
- transitions on every segment (including ESP8266)
- enhanced old and new 2D effects (metadata: default values) - enhanced old and new 2D effects (metadata: default values)
- custom palettes (up to 10; upload palette0.json, palette1.json, ...) - custom palettes (up to 10; upload palette0.json, palette1.json, ...)
- custom effect sliders and options, quick filters - custom effect sliders and options, quick filters
@@ -51,6 +53,7 @@
- allow disabling pull-up resistors on buttons - allow disabling pull-up resistors on buttons
- SD card support (PR #2877) - SD card support (PR #2877)
- enhanced HTTP API to support custom effect sliders & options (X1, X2, X3, M1, M2, M3) - enhanced HTTP API to support custom effect sliders & options (X1, X2, X3, M1, M2, M3)
- multiple UDP sync message retries (PR #2830)
- network debug printer (PR #2870) - network debug printer (PR #2870)
- automatic UI PC mode on large displays - automatic UI PC mode on large displays
- removed support for upgrading from pre-0.10 (EEPROM) - removed support for upgrading from pre-0.10 (EEPROM)

6
package-lock.json generated
View File

@@ -3845,9 +3845,9 @@
} }
}, },
"http-cache-semantics": { "http-cache-semantics": {
"version": "4.1.0", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
"integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="
}, },
"http-signature": { "http-signature": {
"version": "1.2.0", "version": "1.2.0",

View File

@@ -22,8 +22,12 @@
//class name. Use something descriptive and leave the ": public Usermod" part :) //class name. Use something descriptive and leave the ": public Usermod" part :)
class MyExampleUsermod : public Usermod { class MyExampleUsermod : public Usermod {
private: private:
//Private class members. You can declare variables and functions only accessible to your usermod here
// Private class members. You can declare variables and functions only accessible to your usermod here
bool enabled = false;
bool initDone = false;
unsigned long lastTime = 0; unsigned long lastTime = 0;
// set your config variables to their boot default value (this can also be done in readFromConfig() or a constructor if you prefer) // set your config variables to their boot default value (this can also be done in readFromConfig() or a constructor if you prefer)
@@ -37,15 +41,56 @@ class MyExampleUsermod : public Usermod {
long testLong; long testLong;
int8_t testPins[2]; int8_t testPins[2];
// string that are used multiple time (this will save some flash memory)
static const char _name[];
static const char _enabled[];
// any private methods should go here (non-inline methosd should be defined out of class)
void publishMqtt(const char* state, bool retain = false); // example for publishing MQTT message
public: public:
//Functions called by WLED
// non WLED related methods, may be used for data exchange between usermods (non-inline methods should be defined out of class)
/**
* Enable/Disable the usermod
*/
inline void enable(bool enable) { enabled = enable; }
/**
* Get usermod enabled/disabled state
*/
inline bool isEnabled() { return enabled; }
// in such case add the following to another usermod:
// in private vars:
// #ifdef USERMOD_EXAMPLE
// MyExampleUsermod* UM;
// #endif
// in setup()
// #ifdef USERMOD_EXAMPLE
// UM = (MyExampleUsermod*) usermods.lookup(USERMOD_ID_EXAMPLE);
// #endif
// somewhere in loop() or other member method
// #ifdef USERMOD_EXAMPLE
// if (UM != nullptr) isExampleEnabled = UM->isEnabled();
// if (!isExampleEnabled) UM->enable(true);
// #endif
// methods called by WLED (can be inlined as they are called only once but if you call them explicitly define them out of class)
/* /*
* setup() is called once at boot. WiFi is not yet connected at this point. * setup() is called once at boot. WiFi is not yet connected at this point.
* readFromConfig() is called prior to setup()
* You can use it to initialize variables, sensors or similar. * You can use it to initialize variables, sensors or similar.
*/ */
void setup() { void setup() {
// do your set-up here
//Serial.println("Hello from my usermod!"); //Serial.println("Hello from my usermod!");
initDone = true;
} }
@@ -69,6 +114,11 @@ class MyExampleUsermod : public Usermod {
* Instead, use a timer check as shown here. * Instead, use a timer check as shown here.
*/ */
void loop() { void loop() {
// if usermod is disabled or called during strip updating just exit
// NOTE: on very long strips strip.isUpdating() may always return true so update accordingly
if (!enabled || strip.isUpdating()) return;
// do your magic here
if (millis() - lastTime > 1000) { if (millis() - lastTime > 1000) {
//Serial.println("I'm alive!"); //Serial.println("I'm alive!");
lastTime = millis(); lastTime = millis();
@@ -81,19 +131,25 @@ class MyExampleUsermod : public Usermod {
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI. * Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
* Below it is shown how this could be used for e.g. a light sensor * Below it is shown how this could be used for e.g. a light sensor
*/ */
/*
void addToJsonInfo(JsonObject& root) void addToJsonInfo(JsonObject& root)
{ {
int reading = 20; // if "u" object does not exist yet wee need to create it
//this code adds "u":{"Light":[20," lux"]} to the info object
JsonObject user = root["u"]; JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u"); if (user.isNull()) user = root.createNestedObject("u");
JsonArray lightArr = user.createNestedArray("Light"); //name //this code adds "u":{"ExampleUsermod":[20," lux"]} to the info object
lightArr.add(reading); //value //int reading = 20;
lightArr.add(" lux"); //unit //JsonArray lightArr = user.createNestedArray(FPSTR(_name))); //name
//lightArr.add(reading); //value
//lightArr.add(F(" lux")); //unit
// if you are implementing a sensor usermod, you may publish sensor data
//JsonObject sensor = root[F("sensor")];
//if (sensor.isNull()) sensor = root.createNestedObject(F("sensor"));
//temp = sensor.createNestedArray(F("light"));
//temp.add(reading);
//temp.add(F("lux"));
} }
*/
/* /*
@@ -102,7 +158,12 @@ class MyExampleUsermod : public Usermod {
*/ */
void addToJsonState(JsonObject& root) void addToJsonState(JsonObject& root)
{ {
//root["user0"] = userVar0; if (!initDone || !enabled) return; // prevent crash on boot applyPreset()
JsonObject usermod = root[FPSTR(_name)];
if (usermod.isNull()) usermod = root.createNestedObject(FPSTR(_name));
//usermod["user0"] = userVar0;
} }
@@ -112,7 +173,14 @@ class MyExampleUsermod : public Usermod {
*/ */
void readFromJsonState(JsonObject& root) void readFromJsonState(JsonObject& root)
{ {
userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value if (!initDone) return; // prevent crash on boot applyPreset()
JsonObject usermod = root[FPSTR(_name)];
if (!usermod.isNull()) {
// expect JSON usermod data in usermod name object: {"ExampleUsermod:{"user0":10}"}
userVar0 = usermod["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
}
// you can as well check WLED state JSON keys
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!")); //if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
} }
@@ -154,8 +222,10 @@ class MyExampleUsermod : public Usermod {
*/ */
void addToConfig(JsonObject& root) void addToConfig(JsonObject& root)
{ {
JsonObject top = root.createNestedObject("exampleUsermod"); JsonObject top = root.createNestedObject(FPSTR(_name));
top["great"] = userVar0; //save these vars persistently whenever settings are saved top[FPSTR(_enabled)] = enabled;
//save these vars persistently whenever settings are saved
top["great"] = userVar0;
top["testBool"] = testBool; top["testBool"] = testBool;
top["testInt"] = testInt; top["testInt"] = testInt;
top["testLong"] = testLong; top["testLong"] = testLong;
@@ -188,7 +258,7 @@ class MyExampleUsermod : public Usermod {
// default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor // default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor
// setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed) // setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed)
JsonObject top = root["exampleUsermod"]; JsonObject top = root[FPSTR(_name)];
bool configComplete = !top.isNull(); bool configComplete = !top.isNull();
@@ -201,6 +271,8 @@ class MyExampleUsermod : public Usermod {
// A 3-argument getJsonValue() assigns the 3rd argument as a default value if the Json value is missing // A 3-argument getJsonValue() assigns the 3rd argument as a default value if the Json value is missing
configComplete &= getJsonValue(top["testInt"], testInt, 42); configComplete &= getJsonValue(top["testInt"], testInt, 42);
configComplete &= getJsonValue(top["testLong"], testLong, -42424242); configComplete &= getJsonValue(top["testLong"], testLong, -42424242);
// "pin" fields have special handling in settings page (or some_pin as well)
configComplete &= getJsonValue(top["pin"][0], testPins[0], -1); configComplete &= getJsonValue(top["pin"][0], testPins[0], -1);
configComplete &= getJsonValue(top["pin"][1], testPins[1], -1); configComplete &= getJsonValue(top["pin"][1], testPins[1], -1);
@@ -208,6 +280,21 @@ class MyExampleUsermod : public Usermod {
} }
/*
* appendConfigData() is called when user enters usermod settings page
* it may add additional metadata for certain entry fields (adding drop down is possible)
* be careful not to add too much as oappend() buffer is limited to 3k
*/
void appendConfigData()
{
oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":great")); oappend(SET_F("',1,'<i>(this is a great config value)</i>');"));
oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":testString")); oappend(SET_F("',1,'enter any string you want');"));
oappend(SET_F("dd=addDropdown('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F("','testInt');"));
oappend(SET_F("addOption(dd,'Nothing',0);"));
oappend(SET_F("addOption(dd,'Everything',42);"));
}
/* /*
* handleOverlayDraw() is called just before every show() (LED strip update frame) after effects have set the colors. * handleOverlayDraw() is called just before every show() (LED strip update frame) after effects have set the colors.
* Use this to blank out some LEDs or set them to a different color regardless of the set effect mode. * Use this to blank out some LEDs or set them to a different color regardless of the set effect mode.
@@ -219,6 +306,71 @@ class MyExampleUsermod : public Usermod {
} }
/**
* handleButton() can be used to override default button behaviour. Returning true
* will prevent button working in a default way.
* Replicating button.cpp
*/
bool handleButton(uint8_t b) {
yield();
// ignore certain button types as they may have other consequences
if (!enabled
|| buttonType[b] == BTN_TYPE_NONE
|| buttonType[b] == BTN_TYPE_RESERVED
|| buttonType[b] == BTN_TYPE_PIR_SENSOR
|| buttonType[b] == BTN_TYPE_ANALOG
|| buttonType[b] == BTN_TYPE_ANALOG_INVERTED) {
return false;
}
bool handled = false;
// do your button handling here
return handled;
}
#ifndef WLED_DISABLE_MQTT
/**
* handling of MQTT message
* topic only contains stripped topic (part after /wled/MAC)
*/
bool onMqttMessage(char* topic, char* payload) {
// check if we received a command
//if (strlen(topic) == 8 && strncmp_P(topic, PSTR("/command"), 8) == 0) {
// String action = payload;
// if (action == "on") {
// enabled = true;
// return true;
// } else if (action == "off") {
// enabled = false;
// return true;
// } else if (action == "toggle") {
// enabled = !enabled;
// return true;
// }
//}
return false;
}
/**
* onMqttConnect() is called when MQTT connection is established
*/
void onMqttConnect(bool sessionPresent) {
// do any MQTT related initialisation here
//publishMqtt("I am alive!");
}
#endif
/**
* onStateChanged() is used to detect WLED state change
* @mode parameter is CALL_MODE_... parameter used for notifications
*/
void onStateChange(uint8_t mode) {
// do something if WLED state changed (color, brightness, effect, preset, etc)
}
/* /*
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!). * getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed. * This could be used in the future for the system to determine whether your usermod is installed.
@@ -231,3 +383,24 @@ class MyExampleUsermod : public Usermod {
//More methods can be added in the future, this example will then be extended. //More methods can be added in the future, this example will then be extended.
//Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class! //Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class!
}; };
// add more strings here to reduce flash memory usage
const char MyExampleUsermod::_name[] PROGMEM = "ExampleUsermod";
const char MyExampleUsermod::_enabled[] PROGMEM = "enabled";
// implementation of non-inline member methods
void MyExampleUsermod::publishMqtt(const char* state, bool retain)
{
#ifndef WLED_DISABLE_MQTT
//Check if MQTT Connected, otherwise it will crash the 8266
if (WLED_MQTT_CONNECTED) {
char subuf[64];
strcpy(subuf, mqttDeviceTopic);
strcat_P(subuf, PSTR("/example"));
mqtt->publish(subuf, 0, retain, state);
}
#endif
}

View File

@@ -110,6 +110,7 @@ private:
if (m_offOnly && bri && (switchOn || (!PIRtriggered && !switchOn))) return; //if lights on and off only, do nothing if (m_offOnly && bri && (switchOn || (!PIRtriggered && !switchOn))) return; //if lights on and off only, do nothing
if (PIRtriggered && switchOn) return; //if already on and triggered before, do nothing if (PIRtriggered && switchOn) return; //if already on and triggered before, do nothing
PIRtriggered = switchOn; PIRtriggered = switchOn;
DEBUG_PRINT(F("PIR: strip=")); DEBUG_PRINTLN(switchOn?"on":"off");
if (switchOn) { if (switchOn) {
if (m_onPreset) { if (m_onPreset) {
if (currentPlaylist>0 && !offMode) { if (currentPlaylist>0 && !offMode) {
@@ -366,6 +367,19 @@ public:
sensor[F("motion")] = sensorPinState || offTimerStart>0 ? true : false; sensor[F("motion")] = sensorPinState || offTimerStart>0 ? true : false;
} }
/**
* onStateChanged() is used to detect WLED state change
*/
void onStateChange(uint8_t mode) {
DEBUG_PRINT(F("PIR: offTimerStart=")); DEBUG_PRINTLN(offTimerStart);
if (PIRtriggered && offTimerStart) {
// checking PIRtriggered and offTimerStart will prevent cancellation upon On trigger
DEBUG_PRINTLN(F("PIR: Canceled."));
offTimerStart = 0;
PIRtriggered = false;
}
}
/** /**
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object). * addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients * Values in the state object may be modified by connected clients

View File

@@ -29,7 +29,11 @@
#include "fcn_declare.h" #include "fcn_declare.h"
#define IBN 5100 #define IBN 5100
// paletteBlend: 0 - wrap when moving, 1 - always wrap, 2 - never wrap, 3 - none (undefined)
#define PALETTE_SOLID_WRAP (strip.paletteBlend == 1 || strip.paletteBlend == 3) #define PALETTE_SOLID_WRAP (strip.paletteBlend == 1 || strip.paletteBlend == 3)
#define PALETTE_MOVING_WRAP !(strip.paletteBlend == 2 || (strip.paletteBlend == 0 && SEGMENT.speed == 0))
#define indexToVStrip(index, stripNr) ((index) | (int((stripNr)+1)<<16)) #define indexToVStrip(index, stripNr) ((index) | (int((stripNr)+1)<<16))
// effect utility functions // effect utility functions
@@ -1923,11 +1927,10 @@ uint16_t mode_palette() {
counter = counter >> 8; counter = counter >> 8;
} }
bool noWrap = (strip.paletteBlend == 2 || (strip.paletteBlend == 0 && SEGMENT.speed == 0));
for (int i = 0; i < SEGLEN; i++) for (int i = 0; i < SEGLEN; i++)
{ {
uint8_t colorIndex = (i * 255 / SEGLEN) - counter; uint8_t colorIndex = (i * 255 / SEGLEN) - counter;
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(colorIndex, false, noWrap, 255)); SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(colorIndex, false, PALETTE_MOVING_WRAP, 255));
} }
return FRAMETIME; return FRAMETIME;
@@ -3266,11 +3269,11 @@ uint16_t mode_exploding_fireworks(void)
if (SEGENV.aux0 < 2) { //FLARE if (SEGENV.aux0 < 2) { //FLARE
if (SEGENV.aux0 == 0) { //init flare if (SEGENV.aux0 == 0) { //init flare
flare->pos = 0; flare->pos = 0;
flare->posX = strip.isMatrix ? random16(2,cols-1) : (SEGMENT.intensity > random8()); // will enable random firing side on 1D flare->posX = strip.isMatrix ? random16(2,cols-3) : (SEGMENT.intensity > random8()); // will enable random firing side on 1D
uint16_t peakHeight = 75 + random8(180); //0-255 uint16_t peakHeight = 75 + random8(180); //0-255
peakHeight = (peakHeight * (rows -1)) >> 8; peakHeight = (peakHeight * (rows -1)) >> 8;
flare->vel = sqrtf(-2.0f * gravity * peakHeight); flare->vel = sqrtf(-2.0f * gravity * peakHeight);
flare->velX = strip.isMatrix ? (random8(8)-4)/32.f : 0; // no X velocity on 1D flare->velX = strip.isMatrix ? (random8(9)-4)/32.f : 0; // no X velocity on 1D
flare->col = 255; //brightness flare->col = 255; //brightness
SEGENV.aux0 = 1; SEGENV.aux0 = 1;
} }
@@ -3297,16 +3300,16 @@ uint16_t mode_exploding_fireworks(void)
* Size is proportional to the height. * Size is proportional to the height.
*/ */
int nSparks = flare->pos + random8(4); int nSparks = flare->pos + random8(4);
nSparks = constrain(nSparks, 1, numSparks); nSparks = constrain(nSparks, 4, numSparks);
// initialize sparks // initialize sparks
if (SEGENV.aux0 == 2) { if (SEGENV.aux0 == 2) {
for (int i = 1; i < nSparks; i++) { for (int i = 1; i < nSparks; i++) {
sparks[i].pos = flare->pos; sparks[i].pos = flare->pos;
sparks[i].posX = flare->posX; sparks[i].posX = flare->posX;
sparks[i].vel = (float(random16(0, 20000)) / 10000.0f) - 0.9f; // from -0.9 to 1.1 sparks[i].vel = (float(random16(20001)) / 10000.0f) - 0.9f; // from -0.9 to 1.1
sparks[i].vel *= rows<32 ? 0.5f : 1; // reduce velocity for smaller strips sparks[i].vel *= rows<32 ? 0.5f : 1; // reduce velocity for smaller strips
sparks[i].velX = strip.isMatrix ? (float(random16(0, 4000)) / 10000.0f) - 0.2f : 0; // from -0.2 to 0.2 sparks[i].velX = strip.isMatrix ? (float(random16(10001)) / 10000.0f) - 0.5f : 0; // from -0.5 to 0.5
sparks[i].col = 345;//abs(sparks[i].vel * 750.0); // set colors before scaling velocity to keep them bright sparks[i].col = 345;//abs(sparks[i].vel * 750.0); // set colors before scaling velocity to keep them bright
//sparks[i].col = constrain(sparks[i].col, 0, 345); //sparks[i].col = constrain(sparks[i].col, 0, 345);
sparks[i].colIndex = random8(); sparks[i].colIndex = random8();

View File

@@ -420,8 +420,8 @@ void Segment::set(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t o
markForReset(); markForReset();
return; return;
} }
if (i1 < Segment::maxWidth) start = i1; // Segment::maxWidth equals strip.getLengthTotal() for 1D if (i1 < Segment::maxWidth || (i1 >= Segment::maxWidth*Segment::maxHeight && i1 < strip.getLengthTotal())) start = i1; // Segment::maxWidth equals strip.getLengthTotal() for 1D
stop = i2 > Segment::maxWidth ? Segment::maxWidth : MAX(1,i2); stop = i2 > Segment::maxWidth*Segment::maxHeight ? MIN(i2,strip.getLengthTotal()) : (i2 > Segment::maxWidth ? Segment::maxWidth : MAX(1,i2));
startY = 0; startY = 0;
stopY = 1; stopY = 1;
#ifndef WLED_DISABLE_2D #ifndef WLED_DISABLE_2D
@@ -866,6 +866,7 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATT
} }
return; return;
} else if (Segment::maxHeight!=1 && (width()==1 || height()==1)) { } else if (Segment::maxHeight!=1 && (width()==1 || height()==1)) {
if (start < Segment::maxWidth*Segment::maxHeight) {
// we have a vertical or horizontal 1D segment (WARNING: virtual...() may be transposed) // we have a vertical or horizontal 1D segment (WARNING: virtual...() may be transposed)
int x = 0, y = 0; int x = 0, y = 0;
if (virtualHeight()>1) y = i; if (virtualHeight()>1) y = i;
@@ -873,6 +874,7 @@ void IRAM_ATTR_YN Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATT
setPixelColorXY(x, y, col); setPixelColorXY(x, y, col);
return; return;
} }
}
#endif #endif
if (leds) leds[i] = col; if (leds) leds[i] = col;
@@ -1741,6 +1743,20 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
_segments[i].spacing = 0; _segments[i].spacing = 0;
_mainSegment = i; _mainSegment = i;
} }
// do we have LEDs after the matrix? (ignore buses)
if (autoSegments && _length > Segment::maxWidth*Segment::maxHeight /*&& getActiveSegmentsNum() == 2*/) {
if (_segments.size() == getLastActiveSegmentId()+1)
_segments.push_back(Segment(Segment::maxWidth*Segment::maxHeight, _length));
else {
size_t i = getLastActiveSegmentId() + 1;
_segments[i].start = Segment::maxWidth*Segment::maxHeight;
_segments[i].stop = _length;
_segments[i].startY = 0;
_segments[i].stopY = 1;
_segments[i].grouping = 1;
_segments[i].spacing = 0;
}
}
#endif #endif
} else if (autoSegments) { //make one segment per bus } else if (autoSegments) { //make one segment per bus
uint16_t segStarts[MAX_NUM_SEGMENTS] = {0}; uint16_t segStarts[MAX_NUM_SEGMENTS] = {0};
@@ -1764,6 +1780,7 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
s++; s++;
} }
_segments.clear(); _segments.clear();
_segments.reserve(s); // prevent reallocations
for (size_t i = 0; i < s; i++) { for (size_t i = 0; i < s; i++) {
Segment seg = Segment(segStarts[i], segStops[i]); Segment seg = Segment(segStarts[i], segStops[i]);
seg.selected = true; seg.selected = true;
@@ -1811,8 +1828,7 @@ bool WS2812FX::checkSegmentAlignment() {
//After this function is called, setPixelColor() will use that segment (offsets, grouping, ... will apply) //After this function is called, setPixelColor() will use that segment (offsets, grouping, ... will apply)
//Note: If called in an interrupt (e.g. JSON API), original segment must be restored, //Note: If called in an interrupt (e.g. JSON API), original segment must be restored,
//otherwise it can lead to a crash on ESP32 because _segment_index is modified while in use by the main thread //otherwise it can lead to a crash on ESP32 because _segment_index is modified while in use by the main thread
uint8_t WS2812FX::setPixelSegment(uint8_t n) uint8_t WS2812FX::setPixelSegment(uint8_t n) {
{
uint8_t prevSegId = _segment_index; uint8_t prevSegId = _segment_index;
if (n < _segments.size()) { if (n < _segments.size()) {
_segment_index = n; _segment_index = n;
@@ -1821,8 +1837,7 @@ uint8_t WS2812FX::setPixelSegment(uint8_t n)
return prevSegId; return prevSegId;
} }
void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) {
{
if (i2 >= i) if (i2 >= i)
{ {
for (uint16_t x = i; x <= i2; x++) setPixelColor(x, col); for (uint16_t x = i; x <= i2; x++) setPixelColor(x, col);
@@ -1832,14 +1847,12 @@ void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col)
} }
} }
void WS2812FX::setTransitionMode(bool t) void WS2812FX::setTransitionMode(bool t) {
{
for (segment &seg : _segments) if (!seg.transitional) seg.startTransition(t ? _transitionDur : 0); for (segment &seg : _segments) if (!seg.transitional) seg.startTransition(t ? _transitionDur : 0);
} }
#ifdef WLED_DEBUG #ifdef WLED_DEBUG
void WS2812FX::printSize() void WS2812FX::printSize() {
{
size_t size = 0; size_t size = 0;
for (const Segment &seg : _segments) size += seg.getSize(); for (const Segment &seg : _segments) size += seg.getSize();
DEBUG_PRINTF("Segments: %d -> %uB\n", _segments.size(), size); DEBUG_PRINTF("Segments: %d -> %uB\n", _segments.size(), size);
@@ -1850,8 +1863,7 @@ void WS2812FX::printSize()
} }
#endif #endif
void WS2812FX::loadCustomPalettes() void WS2812FX::loadCustomPalettes() {
{
byte tcp[72]; //support gradient palettes with up to 18 entries byte tcp[72]; //support gradient palettes with up to 18 entries
CRGBPalette16 targetPalette; CRGBPalette16 targetPalette;
customPalettes.clear(); // start fresh customPalettes.clear(); // start fresh
@@ -1953,7 +1965,7 @@ void WS2812FX::deserializeMap(uint8_t n) {
customMappingSize = map.size(); customMappingSize = map.size();
customMappingTable = new uint16_t[customMappingSize]; customMappingTable = new uint16_t[customMappingSize];
for (uint16_t i=0; i<MIN(map.size(),customMappingSize); i++) { for (uint16_t i=0; i<MIN(map.size(),customMappingSize); i++) {
customMappingTable[i] = (uint16_t) map[i]; customMappingTable[i] = (uint16_t) (map[i]<0 ? 0xFFFFU : map[i]);
} }
loadedLedmap = n; loadedLedmap = n;
setUpMatrix(false); //WLEDMM: apply logical to physical mapping after the ledmap setUpMatrix(false); //WLEDMM: apply logical to physical mapping after the ledmap
@@ -1967,11 +1979,6 @@ void WS2812FX::deserializeMap(uint8_t n) {
WS2812FX* WS2812FX::instance = nullptr; WS2812FX* WS2812FX::instance = nullptr;
//Bus static member definition, would belong in bus_manager.cpp
int16_t Bus::_cct = -1;
uint8_t Bus::_cctBlend = 0;
uint8_t Bus::_gAWM = 255;
const char JSON_mode_names[] PROGMEM = R"=====(["FX names moved"])====="; const char JSON_mode_names[] PROGMEM = R"=====(["FX names moved"])=====";
//WLEDMM netmindz ar palette add Audio responsive //WLEDMM netmindz ar palette add Audio responsive
const char JSON_palette_names[] PROGMEM = R"=====([ const char JSON_palette_names[] PROGMEM = R"=====([

540
wled00/bus_manager.cpp Normal file
View File

@@ -0,0 +1,540 @@
/*
* Class implementation for addressing various light types
*/
#include <Arduino.h>
#include <IPAddress.h>
#include "const.h"
#include "pin_manager.h"
#include "bus_wrapper.h"
#include "bus_manager.h"
//colors.cpp
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
uint16_t approximateKelvinFromRGB(uint32_t rgb);
void colorRGBtoRGBW(byte* rgb);
//udp.cpp
uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte *buffer, uint8_t bri=255, bool isRGBW=false);
// enable additional debug output
#if defined(WLED_DEBUG_HOST)
#include "net_debug.h"
#define DEBUGOUT NetDebug
#else
#define DEBUGOUT Serial
#endif
#ifdef WLED_DEBUG
#ifndef ESP8266
#include <rom/rtc.h>
#endif
#define DEBUG_PRINT(x) DEBUGOUT.print(x)
#define DEBUG_PRINTLN(x) DEBUGOUT.println(x)
#define DEBUG_PRINTF(x...) DEBUGOUT.printf(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#define DEBUG_PRINTF(x...)
#endif
//color mangling macros
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
#define R(c) (byte((c) >> 16))
#define G(c) (byte((c) >> 8))
#define B(c) (byte(c))
#define W(c) (byte((c) >> 24))
void ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) {
if (_count >= WLED_MAX_COLOR_ORDER_MAPPINGS) {
return;
}
if (len == 0) {
return;
}
if (colorOrder > COL_ORDER_MAX) {
return;
}
_mappings[_count].start = start;
_mappings[_count].len = len;
_mappings[_count].colorOrder = colorOrder;
_count++;
}
uint8_t IRAM_ATTR ColorOrderMap::getPixelColorOrder(uint16_t pix, uint8_t defaultColorOrder) const {
if (_count == 0) return defaultColorOrder;
// upper nibble containd W swap information
uint8_t swapW = defaultColorOrder >> 4;
for (uint8_t i = 0; i < _count; i++) {
if (pix >= _mappings[i].start && pix < (_mappings[i].start + _mappings[i].len)) {
return _mappings[i].colorOrder | (swapW << 4);
}
}
return defaultColorOrder;
}
uint32_t Bus::autoWhiteCalc(uint32_t c) {
uint8_t aWM = _autoWhiteMode;
if (_gAWM < 255) aWM = _gAWM;
if (aWM == RGBW_MODE_MANUAL_ONLY) return c;
uint8_t w = W(c);
//ignore auto-white calculation if w>0 and mode DUAL (DUAL behaves as BRIGHTER if w==0)
if (w > 0 && aWM == RGBW_MODE_DUAL) return c;
uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(c);
w = r < g ? (r < b ? r : b) : (g < b ? g : b);
if (aWM == RGBW_MODE_AUTO_ACCURATE) { r -= w; g -= w; b -= w; } //subtract w in ACCURATE mode
return RGBW32(r, g, b, w);
}
BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com) : Bus(bc.type, bc.start, bc.autoWhite), _colorOrderMap(com) {
if (!IS_DIGITAL(bc.type) || !bc.count) return;
if (!pinManager.allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return;
_pins[0] = bc.pins[0];
if (IS_2PIN(bc.type)) {
if (!pinManager.allocatePin(bc.pins[1], true, PinOwner::BusDigital)) {
cleanup(); return;
}
_pins[1] = bc.pins[1];
}
reversed = bc.reversed;
_needsRefresh = bc.refreshReq || bc.type == TYPE_TM1814;
_skip = bc.skipAmount; //sacrificial pixels
_len = bc.count + _skip;
_iType = PolyBus::getI(bc.type, _pins, nr);
if (_iType == I_NONE) return;
_busPtr = PolyBus::create(_iType, _pins, _len, nr);
_valid = (_busPtr != nullptr);
_colorOrder = bc.colorOrder;
DEBUG_PRINTF("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n", _valid?"S":"Uns", nr, _len, bc.type, _pins[0],_pins[1],_iType);
}
void BusDigital::show() {
PolyBus::show(_busPtr, _iType);
}
bool BusDigital::canShow() {
return PolyBus::canShow(_busPtr, _iType);
}
void BusDigital::setBrightness(uint8_t b) {
//Fix for turning off onboard LED breaking bus
#ifdef LED_BUILTIN
if (_bri == 0 && b > 0) {
if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) PolyBus::begin(_busPtr, _iType, _pins);
}
#endif
Bus::setBrightness(b);
PolyBus::setBrightness(_busPtr, _iType, b);
}
//If LEDs are skipped, it is possible to use the first as a status LED.
//TODO only show if no new show due in the next 50ms
void BusDigital::setStatusPixel(uint32_t c) {
if (_skip && canShow()) {
PolyBus::setPixelColor(_busPtr, _iType, 0, c, _colorOrderMap.getPixelColorOrder(_start, _colorOrder));
PolyBus::show(_busPtr, _iType);
}
}
void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) {
if (_type == TYPE_SK6812_RGBW || _type == TYPE_TM1814) c = autoWhiteCalc(c);
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
if (reversed) pix = _len - pix -1;
else pix += _skip;
PolyBus::setPixelColor(_busPtr, _iType, pix, c, _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder));
}
uint32_t BusDigital::getPixelColor(uint16_t pix) {
if (reversed) pix = _len - pix -1;
else pix += _skip;
return PolyBus::getPixelColor(_busPtr, _iType, pix, _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder));
}
uint8_t BusDigital::getPins(uint8_t* pinArray) {
uint8_t numPins = IS_2PIN(_type) ? 2 : 1;
for (uint8_t i = 0; i < numPins; i++) pinArray[i] = _pins[i];
return numPins;
}
void BusDigital::setColorOrder(uint8_t colorOrder) {
// upper nibble contains W swap information
if ((colorOrder & 0x0F) > 5) return;
_colorOrder = colorOrder;
}
void BusDigital::reinit() {
PolyBus::begin(_busPtr, _iType, _pins);
}
void BusDigital::cleanup() {
DEBUG_PRINTLN(F("Digital Cleanup."));
PolyBus::cleanup(_busPtr, _iType);
_iType = I_NONE;
_valid = false;
_busPtr = nullptr;
pinManager.deallocatePin(_pins[1], PinOwner::BusDigital);
pinManager.deallocatePin(_pins[0], PinOwner::BusDigital);
}
BusPwm::BusPwm(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
_valid = false;
if (!IS_PWM(bc.type)) return;
uint8_t numPins = NUM_PWM_PINS(bc.type);
#ifdef ESP8266
analogWriteRange(255); //same range as one RGB channel
analogWriteFreq(WLED_PWM_FREQ);
#else
_ledcStart = pinManager.allocateLedc(numPins);
if (_ledcStart == 255) { //no more free LEDC channels
deallocatePins(); return;
}
#endif
for (uint8_t i = 0; i < numPins; i++) {
uint8_t currentPin = bc.pins[i];
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusPwm)) {
deallocatePins(); return;
}
_pins[i] = currentPin; //store only after allocatePin() succeeds
#ifdef ESP8266
pinMode(_pins[i], OUTPUT);
#else
ledcSetup(_ledcStart + i, WLED_PWM_FREQ, 8);
ledcAttachPin(_pins[i], _ledcStart + i);
#endif
}
reversed = bc.reversed;
_valid = true;
}
void BusPwm::setPixelColor(uint16_t pix, uint32_t c) {
if (pix != 0 || !_valid) return; //only react to first pixel
if (_type != TYPE_ANALOG_3CH) c = autoWhiteCalc(c);
if (_cct >= 1900 && (_type == TYPE_ANALOG_3CH || _type == TYPE_ANALOG_4CH)) {
c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
}
uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(c);
uint8_t w = W(c);
uint8_t cct = 0; //0 - full warm white, 255 - full cold white
if (_cct > -1) {
if (_cct >= 1900) cct = (_cct - 1900) >> 5;
else if (_cct < 256) cct = _cct;
} else {
cct = (approximateKelvinFromRGB(c) - 1900) >> 5;
}
uint8_t ww, cw;
#ifdef WLED_USE_IC_CCT
ww = w;
cw = cct;
#else
//0 - linear (CCT 127 = 50% warm, 50% cold), 127 - additive CCT blending (CCT 127 = 100% warm, 100% cold)
if (cct < _cctBlend) ww = 255;
else ww = ((255-cct) * 255) / (255 - _cctBlend);
if ((255-cct) < _cctBlend) cw = 255;
else cw = (cct * 255) / (255 - _cctBlend);
ww = (w * ww) / 255; //brightness scaling
cw = (w * cw) / 255;
#endif
switch (_type) {
case TYPE_ANALOG_1CH: //one channel (white), relies on auto white calculation
_data[0] = w;
break;
case TYPE_ANALOG_2CH: //warm white + cold white
_data[1] = cw;
_data[0] = ww;
break;
case TYPE_ANALOG_5CH: //RGB + warm white + cold white
_data[4] = cw;
w = ww;
case TYPE_ANALOG_4CH: //RGBW
_data[3] = w;
case TYPE_ANALOG_3CH: //standard dumb RGB
_data[0] = r; _data[1] = g; _data[2] = b;
break;
}
}
//does no index check
uint32_t BusPwm::getPixelColor(uint16_t pix) {
if (!_valid) return 0;
return RGBW32(_data[0], _data[1], _data[2], _data[3]);
}
void BusPwm::show() {
if (!_valid) return;
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) {
uint8_t scaled = (_data[i] * _bri) / 255;
if (reversed) scaled = 255 - scaled;
#ifdef ESP8266
analogWrite(_pins[i], scaled);
#else
ledcWrite(_ledcStart + i, scaled);
#endif
}
}
uint8_t BusPwm::getPins(uint8_t* pinArray) {
if (!_valid) return 0;
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) {
pinArray[i] = _pins[i];
}
return numPins;
}
void BusPwm::deallocatePins() {
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) {
pinManager.deallocatePin(_pins[i], PinOwner::BusPwm);
if (!pinManager.isPinOk(_pins[i])) continue;
#ifdef ESP8266
digitalWrite(_pins[i], LOW); //turn off PWM interrupt
#else
if (_ledcStart < 16) ledcDetachPin(_pins[i]);
#endif
}
#ifdef ARDUINO_ARCH_ESP32
pinManager.deallocateLedc(_ledcStart, numPins);
#endif
}
BusOnOff::BusOnOff(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
_valid = false;
if (bc.type != TYPE_ONOFF) return;
uint8_t currentPin = bc.pins[0];
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusOnOff)) {
return;
}
_pin = currentPin; //store only after allocatePin() succeeds
pinMode(_pin, OUTPUT);
reversed = bc.reversed;
_valid = true;
}
void BusOnOff::setPixelColor(uint16_t pix, uint32_t c) {
if (pix != 0 || !_valid) return; //only react to first pixel
c = autoWhiteCalc(c);
uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(c);
uint8_t w = W(c);
_data = bool((r+g+b+w) && _bri) ? 0xFF : 0;
}
uint32_t BusOnOff::getPixelColor(uint16_t pix) {
if (!_valid) return 0;
return RGBW32(_data, _data, _data, _data);
}
void BusOnOff::show() {
if (!_valid) return;
digitalWrite(_pin, reversed ? !(bool)_data : (bool)_data);
}
uint8_t BusOnOff::getPins(uint8_t* pinArray) {
if (!_valid) return 0;
pinArray[0] = _pin;
return 1;
}
BusNetwork::BusNetwork(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
_valid = false;
// switch (bc.type) {
// case TYPE_NET_ARTNET_RGB:
// _rgbw = false;
// _UDPtype = 2;
// break;
// case TYPE_NET_E131_RGB:
// _rgbw = false;
// _UDPtype = 1;
// break;
// case TYPE_NET_DDP_RGB:
// _rgbw = false;
// _UDPtype = 0;
// break;
// default: // TYPE_NET_DDP_RGB / TYPE_NET_DDP_RGBW
_rgbw = bc.type == TYPE_NET_DDP_RGBW;
_UDPtype = 0;
// break;
// }
_UDPchannels = _rgbw ? 4 : 3;
_data = (byte *)malloc(bc.count * _UDPchannels);
if (_data == nullptr) return;
memset(_data, 0, bc.count * _UDPchannels);
_len = bc.count;
_client = IPAddress(bc.pins[0],bc.pins[1],bc.pins[2],bc.pins[3]);
_broadcastLock = false;
_valid = true;
}
void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
if (!_valid || pix >= _len) return;
if (isRgbw()) c = autoWhiteCalc(c);
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
uint16_t offset = pix * _UDPchannels;
_data[offset] = R(c);
_data[offset+1] = G(c);
_data[offset+2] = B(c);
if (_rgbw) _data[offset+3] = W(c);
}
uint32_t BusNetwork::getPixelColor(uint16_t pix) {
if (!_valid || pix >= _len) return 0;
uint16_t offset = pix * _UDPchannels;
return RGBW32(_data[offset], _data[offset+1], _data[offset+2], _rgbw ? (_data[offset+3] << 24) : 0);
}
void BusNetwork::show() {
if (!_valid || !canShow()) return;
_broadcastLock = true;
realtimeBroadcast(_UDPtype, _client, _len, _data, _bri, _rgbw);
_broadcastLock = false;
}
uint8_t BusNetwork::getPins(uint8_t* pinArray) {
for (uint8_t i = 0; i < 4; i++) {
pinArray[i] = _client[i];
}
return 4;
}
void BusNetwork::cleanup() {
_type = I_NONE;
_valid = false;
if (_data != nullptr) free(_data);
_data = nullptr;
}
//utility to get the approx. memory usage of a given BusConfig
uint32_t BusManager::memUsage(BusConfig &bc) {
uint8_t type = bc.type;
uint16_t len = bc.count + bc.skipAmount;
if (type > 15 && type < 32) {
#ifdef ESP8266
if (bc.pins[0] == 3) { //8266 DMA uses 5x the mem
if (type > 29) return len*20; //RGBW
return len*15;
}
if (type > 29) return len*4; //RGBW
return len*3;
#else //ESP32 RMT uses double buffer?
if (type > 29) return len*8; //RGBW
return len*6;
#endif
}
if (type > 31 && type < 48) return 5;
if (type == 44 || type == 45) return len*4; //RGBW
return len*3; //RGB
}
int BusManager::add(BusConfig &bc) {
if (getNumBusses() - getNumVirtualBusses() >= WLED_MAX_BUSSES) return -1;
if (bc.type >= TYPE_NET_DDP_RGB && bc.type < 96) {
busses[numBusses] = new BusNetwork(bc);
} else if (IS_DIGITAL(bc.type)) {
busses[numBusses] = new BusDigital(bc, numBusses, colorOrderMap);
} else if (bc.type == TYPE_ONOFF) {
busses[numBusses] = new BusOnOff(bc);
} else {
busses[numBusses] = new BusPwm(bc);
}
return numBusses++;
}
//do not call this method from system context (network callback)
void BusManager::removeAll() {
DEBUG_PRINTLN(F("Removing all."));
//prevents crashes due to deleting busses while in use.
while (!canAllShow()) yield();
for (uint8_t i = 0; i < numBusses; i++) delete busses[i];
numBusses = 0;
}
void BusManager::show() {
for (uint8_t i = 0; i < numBusses; i++) {
busses[i]->show();
}
}
void BusManager::setStatusPixel(uint32_t c) {
for (uint8_t i = 0; i < numBusses; i++) {
busses[i]->setStatusPixel(c);
}
}
void IRAM_ATTR BusManager::setPixelColor(uint16_t pix, uint32_t c, int16_t cct) {
for (uint8_t i = 0; i < numBusses; i++) {
Bus* b = busses[i];
uint16_t bstart = b->getStart();
if (pix < bstart || pix >= bstart + b->getLength()) continue;
busses[i]->setPixelColor(pix - bstart, c);
}
}
void BusManager::setBrightness(uint8_t b) {
for (uint8_t i = 0; i < numBusses; i++) {
busses[i]->setBrightness(b);
}
}
void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) {
if (cct > 255) cct = 255;
if (cct >= 0) {
//if white balance correction allowed, save as kelvin value instead of 0-255
if (allowWBCorrection) cct = 1900 + (cct << 5);
} else cct = -1;
Bus::setCCT(cct);
}
uint32_t BusManager::getPixelColor(uint16_t pix) {
for (uint8_t i = 0; i < numBusses; i++) {
Bus* b = busses[i];
uint16_t bstart = b->getStart();
if (pix < bstart || pix >= bstart + b->getLength()) continue;
return b->getPixelColor(pix - bstart);
}
return 0;
}
bool BusManager::canAllShow() {
for (uint8_t i = 0; i < numBusses; i++) {
if (!busses[i]->canShow()) return false;
}
return true;
}
Bus* BusManager::getBus(uint8_t busNr) {
if (busNr >= numBusses) return nullptr;
return busses[busNr];
}
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
uint16_t BusManager::getTotalLength() {
uint16_t len = 0;
for (uint8_t i=0; i<numBusses; i++) len += busses[i]->getLength();
return len;
}
// Bus static member definition
int16_t Bus::_cct = -1;
uint8_t Bus::_cctBlend = 0;
uint8_t Bus::_gAWM = 255;

View File

@@ -6,45 +6,11 @@
*/ */
#include "const.h" #include "const.h"
#include "pin_manager.h"
#include "bus_wrapper.h"
#include <Arduino.h>
//colors.cpp
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
void colorRGBtoRGBW(byte* rgb);
// enable additional debug output
#if defined(WLED_DEBUG_HOST)
#define DEBUGOUT NetDebug
#else
#define DEBUGOUT Serial
#endif
#ifdef WLED_DEBUG
#ifndef ESP8266
#include <rom/rtc.h>
#endif
#define DEBUG_PRINT(x) DEBUGOUT.print(x)
#define DEBUG_PRINTLN(x) DEBUGOUT.println(x)
#define DEBUG_PRINTF(x...) DEBUGOUT.printf(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#define DEBUG_PRINTF(x...)
#endif
#define GET_BIT(var,bit) (((var)>>(bit))&0x01) #define GET_BIT(var,bit) (((var)>>(bit))&0x01)
#define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit))) #define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit)))
#define UNSET_BIT(var,bit) ((var)&=(~(uint16_t)(0x0001<<(bit)))) #define UNSET_BIT(var,bit) ((var)&=(~(uint16_t)(0x0001<<(bit))))
//color mangling macros
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
#define R(c) (byte((c) >> 16))
#define G(c) (byte((c) >> 8))
#define B(c) (byte(c))
#define W(c) (byte((c) >> 24))
//temporary struct for passing bus configuration to bus //temporary struct for passing bus configuration to bus
struct BusConfig { struct BusConfig {
uint8_t type; uint8_t type;
@@ -88,21 +54,7 @@ struct ColorOrderMapEntry {
}; };
struct ColorOrderMap { struct ColorOrderMap {
void add(uint16_t start, uint16_t len, uint8_t colorOrder) { void add(uint16_t start, uint16_t len, uint8_t colorOrder);
if (_count >= WLED_MAX_COLOR_ORDER_MAPPINGS) {
return;
}
if (len == 0) {
return;
}
if (colorOrder > COL_ORDER_MAX) {
return;
}
_mappings[_count].start = start;
_mappings[_count].len = len;
_mappings[_count].colorOrder = colorOrder;
_count++;
}
uint8_t count() const { uint8_t count() const {
return _count; return _count;
@@ -120,17 +72,7 @@ struct ColorOrderMap {
return &(_mappings[n]); return &(_mappings[n]);
} }
inline uint8_t IRAM_ATTR getPixelColorOrder(uint16_t pix, uint8_t defaultColorOrder) const { uint8_t getPixelColorOrder(uint16_t pix, uint8_t defaultColorOrder) const;
if (_count == 0) return defaultColorOrder;
// upper nibble containd W swap information
uint8_t swapW = defaultColorOrder >> 4;
for (uint8_t i = 0; i < _count; i++) {
if (pix >= _mappings[i].start && pix < (_mappings[i].start + _mappings[i].len)) {
return _mappings[i].colorOrder | (swapW << 4);
}
}
return defaultColorOrder;
}
private: private:
uint8_t _count; uint8_t _count;
@@ -214,94 +156,31 @@ class Bus {
bool _valid; bool _valid;
bool _needsRefresh; bool _needsRefresh;
uint8_t _autoWhiteMode; uint8_t _autoWhiteMode;
static uint8_t _gAWM; // definition in FX_fcn.cpp static uint8_t _gAWM;
static int16_t _cct; // definition in FX_fcn.cpp static int16_t _cct;
static uint8_t _cctBlend; // definition in FX_fcn.cpp static uint8_t _cctBlend;
uint32_t autoWhiteCalc(uint32_t c) { uint32_t autoWhiteCalc(uint32_t c);
uint8_t aWM = _autoWhiteMode;
if (_gAWM < 255) aWM = _gAWM;
if (aWM == RGBW_MODE_MANUAL_ONLY) return c;
uint8_t w = W(c);
//ignore auto-white calculation if w>0 and mode DUAL (DUAL behaves as BRIGHTER if w==0)
if (w > 0 && aWM == RGBW_MODE_DUAL) return c;
uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(c);
w = r < g ? (r < b ? r : b) : (g < b ? g : b);
if (aWM == RGBW_MODE_AUTO_ACCURATE) { r -= w; g -= w; b -= w; } //subtract w in ACCURATE mode
return RGBW32(r, g, b, w);
}
}; };
class BusDigital : public Bus { class BusDigital : public Bus {
public: public:
BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com) : Bus(bc.type, bc.start, bc.autoWhite), _colorOrderMap(com) { BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com);
if (!IS_DIGITAL(bc.type) || !bc.count) return;
if (!pinManager.allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return;
_pins[0] = bc.pins[0];
if (IS_2PIN(bc.type)) {
if (!pinManager.allocatePin(bc.pins[1], true, PinOwner::BusDigital)) {
cleanup(); return;
}
_pins[1] = bc.pins[1];
}
reversed = bc.reversed;
_needsRefresh = bc.refreshReq || bc.type == TYPE_TM1814;
_skip = bc.skipAmount; //sacrificial pixels
_len = bc.count + _skip;
_iType = PolyBus::getI(bc.type, _pins, nr);
if (_iType == I_NONE) return;
_busPtr = PolyBus::create(_iType, _pins, _len, nr);
_valid = (_busPtr != nullptr);
_colorOrder = bc.colorOrder;
DEBUG_PRINTF("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n", _valid?"S":"Uns", nr, _len, bc.type, _pins[0],_pins[1],_iType);
};
inline void show() { inline void show();
PolyBus::show(_busPtr, _iType);
}
inline bool canShow() { bool canShow();
return PolyBus::canShow(_busPtr, _iType);
}
void setBrightness(uint8_t b) { void setBrightness(uint8_t b);
//Fix for turning off onboard LED breaking bus
#ifdef LED_BUILTIN
if (_bri == 0 && b > 0) {
if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) PolyBus::begin(_busPtr, _iType, _pins);
}
#endif
Bus::setBrightness(b);
PolyBus::setBrightness(_busPtr, _iType, b);
}
//If LEDs are skipped, it is possible to use the first as a status LED. void setStatusPixel(uint32_t c);
//TODO only show if no new show due in the next 50ms
void setStatusPixel(uint32_t c) {
if (_skip && canShow()) {
PolyBus::setPixelColor(_busPtr, _iType, 0, c, _colorOrderMap.getPixelColorOrder(_start, _colorOrder));
PolyBus::show(_busPtr, _iType);
}
}
void setPixelColor(uint16_t pix, uint32_t c) { void setPixelColor(uint16_t pix, uint32_t c);
if (_type == TYPE_SK6812_RGBW || _type == TYPE_TM1814) c = autoWhiteCalc(c);
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
if (reversed) pix = _len - pix -1;
else pix += _skip;
PolyBus::setPixelColor(_busPtr, _iType, pix, c, _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder));
}
uint32_t getPixelColor(uint16_t pix) { uint32_t getPixelColor(uint16_t pix);
if (reversed) pix = _len - pix -1;
else pix += _skip;
return PolyBus::getPixelColor(_busPtr, _iType, pix, _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder));
}
inline uint8_t getColorOrder() { uint8_t getColorOrder() {
return _colorOrder; return _colorOrder;
} }
@@ -309,35 +188,17 @@ class BusDigital : public Bus {
return _len - _skip; return _len - _skip;
} }
uint8_t getPins(uint8_t* pinArray) { uint8_t getPins(uint8_t* pinArray);
uint8_t numPins = IS_2PIN(_type) ? 2 : 1;
for (uint8_t i = 0; i < numPins; i++) pinArray[i] = _pins[i];
return numPins;
}
void setColorOrder(uint8_t colorOrder) { void setColorOrder(uint8_t colorOrder);
// upper nibble contains W swap information
if ((colorOrder & 0x0F) > 5) return;
_colorOrder = colorOrder;
}
inline uint8_t skippedLeds() { uint8_t skippedLeds() {
return _skip; return _skip;
} }
inline void reinit() { void reinit();
PolyBus::begin(_busPtr, _iType, _pins);
}
void cleanup() { void cleanup();
DEBUG_PRINTLN(F("Digital Cleanup."));
PolyBus::cleanup(_busPtr, _iType);
_iType = I_NONE;
_valid = false;
_busPtr = nullptr;
pinManager.deallocatePin(_pins[1], PinOwner::BusDigital);
pinManager.deallocatePin(_pins[0], PinOwner::BusDigital);
}
~BusDigital() { ~BusDigital() {
cleanup(); cleanup();
@@ -346,7 +207,7 @@ class BusDigital : public Bus {
private: private:
uint8_t _colorOrder = COL_ORDER_GRB; uint8_t _colorOrder = COL_ORDER_GRB;
uint8_t _pins[2] = {255, 255}; uint8_t _pins[2] = {255, 255};
uint8_t _iType = I_NONE; uint8_t _iType = 0; //I_NONE;
uint8_t _skip = 0; uint8_t _skip = 0;
void * _busPtr = nullptr; void * _busPtr = nullptr;
const ColorOrderMap &_colorOrderMap; const ColorOrderMap &_colorOrderMap;
@@ -355,119 +216,16 @@ class BusDigital : public Bus {
class BusPwm : public Bus { class BusPwm : public Bus {
public: public:
BusPwm(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) { BusPwm(BusConfig &bc);
_valid = false;
if (!IS_PWM(bc.type)) return;
uint8_t numPins = NUM_PWM_PINS(bc.type);
#ifdef ESP8266 void setPixelColor(uint16_t pix, uint32_t c);
analogWriteRange(255); //same range as one RGB channel
analogWriteFreq(WLED_PWM_FREQ);
#else
_ledcStart = pinManager.allocateLedc(numPins);
if (_ledcStart == 255) { //no more free LEDC channels
deallocatePins(); return;
}
#endif
for (uint8_t i = 0; i < numPins; i++) {
uint8_t currentPin = bc.pins[i];
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusPwm)) {
deallocatePins(); return;
}
_pins[i] = currentPin; //store only after allocatePin() succeeds
#ifdef ESP8266
pinMode(_pins[i], OUTPUT);
#else
ledcSetup(_ledcStart + i, WLED_PWM_FREQ, 8);
ledcAttachPin(_pins[i], _ledcStart + i);
#endif
}
reversed = bc.reversed;
_valid = true;
};
void setPixelColor(uint16_t pix, uint32_t c) {
if (pix != 0 || !_valid) return; //only react to first pixel
if (_type != TYPE_ANALOG_3CH) c = autoWhiteCalc(c);
if (_cct >= 1900 && (_type == TYPE_ANALOG_3CH || _type == TYPE_ANALOG_4CH)) {
c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
}
uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(c);
uint8_t w = W(c);
uint8_t cct = 0; //0 - full warm white, 255 - full cold white
if (_cct > -1) {
if (_cct >= 1900) cct = (_cct - 1900) >> 5;
else if (_cct < 256) cct = _cct;
} else {
cct = (approximateKelvinFromRGB(c) - 1900) >> 5;
}
uint8_t ww, cw;
#ifdef WLED_USE_IC_CCT
ww = w;
cw = cct;
#else
//0 - linear (CCT 127 = 50% warm, 50% cold), 127 - additive CCT blending (CCT 127 = 100% warm, 100% cold)
if (cct < _cctBlend) ww = 255;
else ww = ((255-cct) * 255) / (255 - _cctBlend);
if ((255-cct) < _cctBlend) cw = 255;
else cw = (cct * 255) / (255 - _cctBlend);
ww = (w * ww) / 255; //brightness scaling
cw = (w * cw) / 255;
#endif
switch (_type) {
case TYPE_ANALOG_1CH: //one channel (white), relies on auto white calculation
_data[0] = w;
break;
case TYPE_ANALOG_2CH: //warm white + cold white
_data[1] = cw;
_data[0] = ww;
break;
case TYPE_ANALOG_5CH: //RGB + warm white + cold white
_data[4] = cw;
w = ww;
case TYPE_ANALOG_4CH: //RGBW
_data[3] = w;
case TYPE_ANALOG_3CH: //standard dumb RGB
_data[0] = r; _data[1] = g; _data[2] = b;
break;
}
}
//does no index check //does no index check
uint32_t getPixelColor(uint16_t pix) { uint32_t getPixelColor(uint16_t pix);
if (!_valid) return 0;
return RGBW32(_data[0], _data[1], _data[2], _data[3]);
}
void show() { void show();
if (!_valid) return;
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) {
uint8_t scaled = (_data[i] * _bri) / 255;
if (reversed) scaled = 255 - scaled;
#ifdef ESP8266
analogWrite(_pins[i], scaled);
#else
ledcWrite(_ledcStart + i, scaled);
#endif
}
}
uint8_t getPins(uint8_t* pinArray) { uint8_t getPins(uint8_t* pinArray);
if (!_valid) return 0;
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) {
pinArray[i] = _pins[i];
}
return numPins;
}
void cleanup() { void cleanup() {
deallocatePins(); deallocatePins();
@@ -484,66 +242,21 @@ class BusPwm : public Bus {
uint8_t _ledcStart = 255; uint8_t _ledcStart = 255;
#endif #endif
void deallocatePins() { void deallocatePins();
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) {
pinManager.deallocatePin(_pins[i], PinOwner::BusPwm);
if (!pinManager.isPinOk(_pins[i])) continue;
#ifdef ESP8266
digitalWrite(_pins[i], LOW); //turn off PWM interrupt
#else
if (_ledcStart < 16) ledcDetachPin(_pins[i]);
#endif
}
#ifdef ARDUINO_ARCH_ESP32
pinManager.deallocateLedc(_ledcStart, numPins);
#endif
}
}; };
class BusOnOff : public Bus { class BusOnOff : public Bus {
public: public:
BusOnOff(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) { BusOnOff(BusConfig &bc);
_valid = false;
if (bc.type != TYPE_ONOFF) return;
uint8_t currentPin = bc.pins[0]; void setPixelColor(uint16_t pix, uint32_t c);
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusOnOff)) {
return;
}
_pin = currentPin; //store only after allocatePin() succeeds
pinMode(_pin, OUTPUT);
reversed = bc.reversed;
_valid = true;
};
void setPixelColor(uint16_t pix, uint32_t c) { uint32_t getPixelColor(uint16_t pix);
if (pix != 0 || !_valid) return; //only react to first pixel
c = autoWhiteCalc(c);
uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(c);
uint8_t w = W(c);
_data = bool((r+g+b+w) && _bri) ? 0xFF : 0; void show();
}
uint32_t getPixelColor(uint16_t pix) { uint8_t getPins(uint8_t* pinArray);
if (!_valid) return 0;
return RGBW32(_data, _data, _data, _data);
}
void show() {
if (!_valid) return;
digitalWrite(_pin, reversed ? !(bool)_data : (bool)_data);
}
uint8_t getPins(uint8_t* pinArray) {
if (!_valid) return 0;
pinArray[0] = _pin;
return 1;
}
void cleanup() { void cleanup() {
pinManager.deallocatePin(_pin, PinOwner::BusOnOff); pinManager.deallocatePin(_pin, PinOwner::BusOnOff);
@@ -561,89 +274,33 @@ class BusOnOff : public Bus {
class BusNetwork : public Bus { class BusNetwork : public Bus {
public: public:
BusNetwork(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) { BusNetwork(BusConfig &bc);
_valid = false;
// switch (bc.type) {
// case TYPE_NET_ARTNET_RGB:
// _rgbw = false;
// _UDPtype = 2;
// break;
// case TYPE_NET_E131_RGB:
// _rgbw = false;
// _UDPtype = 1;
// break;
// case TYPE_NET_DDP_RGB:
// _rgbw = false;
// _UDPtype = 0;
// break;
// default: // TYPE_NET_DDP_RGB / TYPE_NET_DDP_RGBW
_rgbw = bc.type == TYPE_NET_DDP_RGBW;
_UDPtype = 0;
// break;
// }
_UDPchannels = _rgbw ? 4 : 3;
_data = (byte *)malloc(bc.count * _UDPchannels);
if (_data == nullptr) return;
memset(_data, 0, bc.count * _UDPchannels);
_len = bc.count;
_client = IPAddress(bc.pins[0],bc.pins[1],bc.pins[2],bc.pins[3]);
_broadcastLock = false;
_valid = true;
};
bool hasRGB() { return true; } bool hasRGB() { return true; }
bool hasWhite() { return _rgbw; } bool hasWhite() { return _rgbw; }
void setPixelColor(uint16_t pix, uint32_t c) { void setPixelColor(uint16_t pix, uint32_t c);
if (!_valid || pix >= _len) return;
if (isRgbw()) c = autoWhiteCalc(c);
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
uint16_t offset = pix * _UDPchannels;
_data[offset] = R(c);
_data[offset+1] = G(c);
_data[offset+2] = B(c);
if (_rgbw) _data[offset+3] = W(c);
}
uint32_t getPixelColor(uint16_t pix) { uint32_t getPixelColor(uint16_t pix);
if (!_valid || pix >= _len) return 0;
uint16_t offset = pix * _UDPchannels;
return RGBW32(_data[offset], _data[offset+1], _data[offset+2], _rgbw ? (_data[offset+3] << 24) : 0);
}
void show() { void show();
if (!_valid || !canShow()) return;
_broadcastLock = true;
realtimeBroadcast(_UDPtype, _client, _len, _data, _bri, _rgbw);
_broadcastLock = false;
}
inline bool canShow() { bool canShow() {
// this should be a return value from UDP routine if it is still sending data out // this should be a return value from UDP routine if it is still sending data out
return !_broadcastLock; return !_broadcastLock;
} }
uint8_t getPins(uint8_t* pinArray) { uint8_t getPins(uint8_t* pinArray);
for (uint8_t i = 0; i < 4; i++) {
pinArray[i] = _client[i];
}
return 4;
}
inline bool isRgbw() { bool isRgbw() {
return _rgbw; return _rgbw;
} }
inline uint16_t getLength() { uint16_t getLength() {
return _len; return _len;
} }
void cleanup() { void cleanup();
_type = I_NONE;
_valid = false;
if (_data != nullptr) free(_data);
_data = nullptr;
}
~BusNetwork() { ~BusNetwork() {
cleanup(); cleanup();
@@ -664,129 +321,31 @@ class BusManager {
BusManager() {}; BusManager() {};
//utility to get the approx. memory usage of a given BusConfig //utility to get the approx. memory usage of a given BusConfig
static uint32_t memUsage(BusConfig &bc) { static uint32_t memUsage(BusConfig &bc);
uint8_t type = bc.type;
uint16_t len = bc.count + bc.skipAmount;
if (type > 15 && type < 32) {
#ifdef ESP8266
if (bc.pins[0] == 3) { //8266 DMA uses 5x the mem
if (type > 29) return len*20; //RGBW
return len*15;
}
if (type > 29) return len*4; //RGBW
return len*3;
#else //ESP32 RMT uses double buffer?
if (type > 29) return len*8; //RGBW
return len*6;
#endif
}
if (type > 31 && type < 48) return 5;
if (type == 44 || type == 45) return len*4; //RGBW
return len*3; //RGB
}
/*
int add(BusConfig &bc); int add(BusConfig &bc);
void removeAll(); //do not call this method from system context (network callback)
void setStatusPixel(uint32_t c);
void setPixelColor(uint16_t pix, uint32_t c, int16_t cct=-1);
void setBrightness(uint8_t b);
void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
uint32_t getPixelColor(uint16_t pix);
bool canAllShow();
Bus* getBus(uint8_t busNr);
void show();
uint16_t getTotalLength(); //semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
*/
// the following functions are inlined by compiler since they are defined within class definition
// they should be placed in cpp file instead
int add(BusConfig &bc) {
if (getNumBusses() - getNumVirtualBusses() >= WLED_MAX_BUSSES) return -1;
if (bc.type >= TYPE_NET_DDP_RGB && bc.type < 96) {
busses[numBusses] = new BusNetwork(bc);
} else if (IS_DIGITAL(bc.type)) {
busses[numBusses] = new BusDigital(bc, numBusses, colorOrderMap);
} else if (bc.type == TYPE_ONOFF) {
busses[numBusses] = new BusOnOff(bc);
} else {
busses[numBusses] = new BusPwm(bc);
}
return numBusses++;
}
//do not call this method from system context (network callback) //do not call this method from system context (network callback)
void removeAll() { void removeAll();
DEBUG_PRINTLN(F("Removing all."));
//prevents crashes due to deleting busses while in use.
while (!canAllShow()) yield();
for (uint8_t i = 0; i < numBusses; i++) delete busses[i];
numBusses = 0;
}
void show() { void show();
for (uint8_t i = 0; i < numBusses; i++) {
busses[i]->show();
}
}
void setStatusPixel(uint32_t c) { void setStatusPixel(uint32_t c);
for (uint8_t i = 0; i < numBusses; i++) {
busses[i]->setStatusPixel(c);
}
}
void IRAM_ATTR setPixelColor(uint16_t pix, uint32_t c, int16_t cct=-1) { void IRAM_ATTR setPixelColor(uint16_t pix, uint32_t c, int16_t cct=-1);
for (uint8_t i = 0; i < numBusses; i++) {
Bus* b = busses[i];
uint16_t bstart = b->getStart();
if (pix < bstart || pix >= bstart + b->getLength()) continue;
busses[i]->setPixelColor(pix - bstart, c);
}
}
void setBrightness(uint8_t b) { void setBrightness(uint8_t b);
for (uint8_t i = 0; i < numBusses; i++) {
busses[i]->setBrightness(b);
}
}
void setSegmentCCT(int16_t cct, bool allowWBCorrection = false) { void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
if (cct > 255) cct = 255;
if (cct >= 0) {
//if white balance correction allowed, save as kelvin value instead of 0-255
if (allowWBCorrection) cct = 1900 + (cct << 5);
} else cct = -1;
Bus::setCCT(cct);
}
uint32_t getPixelColor(uint16_t pix) { uint32_t getPixelColor(uint16_t pix);
for (uint8_t i = 0; i < numBusses; i++) {
Bus* b = busses[i];
uint16_t bstart = b->getStart();
if (pix < bstart || pix >= bstart + b->getLength()) continue;
return b->getPixelColor(pix - bstart);
}
return 0;
}
bool canAllShow() { bool canAllShow();
for (uint8_t i = 0; i < numBusses; i++) {
if (!busses[i]->canShow()) return false;
}
return true;
}
Bus* getBus(uint8_t busNr) { Bus* getBus(uint8_t busNr);
if (busNr >= numBusses) return nullptr;
return busses[busNr];
}
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit()) //semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
uint16_t getTotalLength() { uint16_t getTotalLength();
uint16_t len = 0;
for (uint8_t i=0; i<numBusses; i++) len += busses[i]->getLength();
return len;
}
inline void updateColorOrderMap(const ColorOrderMap &com) { inline void updateColorOrderMap(const ColorOrderMap &com) {
memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap)); memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap));

View File

@@ -731,7 +731,7 @@ function populateSegments(s)
let rvXck = `<label class="check revchkl">Reverse ${isM?'':'direction'}<input type="checkbox" id="seg${i}rev" onchange="setRev(${i})" ${inst.rev?"checked":""}><span class="checkmark"></span></label>`; let rvXck = `<label class="check revchkl">Reverse ${isM?'':'direction'}<input type="checkbox" id="seg${i}rev" onchange="setRev(${i})" ${inst.rev?"checked":""}><span class="checkmark"></span></label>`;
let miXck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mi" onchange="setMi(${i})" ${inst.mi?"checked":""}><span class="checkmark"></span></label>`; let miXck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mi" onchange="setMi(${i})" ${inst.mi?"checked":""}><span class="checkmark"></span></label>`;
let rvYck = "", miYck =""; let rvYck = "", miYck ="";
if (isM) { if (isM && staX<mw*mh) {
rvYck = `<label class="check revchkl">Reverse<input type="checkbox" id="seg${i}rY" onchange="setRevY(${i})" ${inst.rY?"checked":""}><span class="checkmark"></span></label>`; rvYck = `<label class="check revchkl">Reverse<input type="checkbox" id="seg${i}rY" onchange="setRevY(${i})" ${inst.rY?"checked":""}><span class="checkmark"></span></label>`;
miYck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mY" onchange="setMiY(${i})" ${inst.mY?"checked":""}><span class="checkmark"></span></label>`; miYck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mY" onchange="setMiY(${i})" ${inst.mY?"checked":""}><span class="checkmark"></span></label>`;
} }
@@ -775,19 +775,19 @@ function populateSegments(s)
<input type="text" class="ptxt noslide" id="seg${i}t" autocomplete="off" maxlength=32 value="${inst.n?inst.n:""}" placeholder="Enter name..."/> <input type="text" class="ptxt noslide" id="seg${i}t" autocomplete="off" maxlength=32 value="${inst.n?inst.n:""}" placeholder="Enter name..."/>
<table class="infot segt"> <table class="infot segt">
<tr> <tr>
<td>${isM?'Start X':'Start LED'}</td> <td>${isM&&staX<mw*mh?'Start X':'Start LED'}</td>
<td>${isM?(cfg.comp.seglen?"Width":"Stop X"):(cfg.comp.seglen?"LED count":"Stop LED")}</td> <td>${isM&&staX<mw*mh?(cfg.comp.seglen?"Width":"Stop X"):(cfg.comp.seglen?"LED count":"Stop LED")}</td>
<td>${isM?'':'Offset'}</td> <td>${isM&&staX<mw*mh?'':'Offset'}</td>
</tr> </tr>
<tr> <tr>
<td><input class="noslide segn" id="seg${i}s" type="number" min="0" max="${(isM?mw:ledCount)-1}" value="${staX}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td> <td><input class="noslide segn" id="seg${i}s" type="number" min="0" max="${(isM&&staX<mw*mh?mw:ledCount)-1}" value="${staX}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
<td><input class="noslide segn" id="seg${i}e" type="number" min="0" max="${(isM?mw:ledCount)-(cfg.comp.seglen?staX:0)}" value="${stoX-(cfg.comp.seglen?staX:0)}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td> <td><input class="noslide segn" id="seg${i}e" type="number" min="0" max="${(isM&&staX<mw*mh?mw:ledCount)}" value="${stoX-(cfg.comp.seglen?staX:0)}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
<td style="text-align:revert;">${isM?miXck+'<br>'+rvXck:''}<input class="noslide segn ${isM?'hide':''}" id="seg${i}of" type="number" value="${inst.of}" oninput="updateLen(${i})"></td> <td style="text-align:revert;">${isM&&staX<mw*mh?miXck+'<br>'+rvXck:''}<input class="noslide segn ${isM&&staX<mw*mh?'hide':''}" id="seg${i}of" type="number" value="${inst.of}" oninput="updateLen(${i})"></td>
</tr> </tr>
${isM ? '<tr><td>Start Y</td><td>'+(cfg.comp.seglen?'Height':'Stop Y')+'</td><td></td></tr>'+ ${isM&&staX<mw*mh ? '<tr><td>Start Y</td><td>'+(cfg.comp.seglen?'Height':'Stop Y')+'</td><td></td></tr>'+
'<tr>'+ '<tr>'+
'<td><input class="noslide segn" id="seg'+i+'sY" type="number" min="0" max="'+(mh-1)+'" value="'+staY+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+ '<td><input class="noslide segn" id="seg'+i+'sY" type="number" min="0" max="'+(mh-1)+'" value="'+staY+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+
'<td><input class="noslide segn" id="seg'+i+'eY" type="number" min="0" max="'+(mh-(cfg.comp.seglen?staY:0))+'" value="'+(stoY-(cfg.comp.seglen?staY:0))+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+ '<td><input class="noslide segn" id="seg'+i+'eY" type="number" min="0" max="'+mh+'" value="'+(stoY-(cfg.comp.seglen?staY:0))+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+
'<td style="text-align:revert;">'+miYck+'<br>'+rvYck+'</td>'+ '<td style="text-align:revert;">'+miYck+'<br>'+rvYck+'</td>'+
'</tr>':''} '</tr>':''}
<tr> <tr>
@@ -798,17 +798,18 @@ function populateSegments(s)
<tr> <tr>
<td><input class="noslide segn" id="seg${i}grp" type="number" min="1" max="255" value="${inst.grp}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td> <td><input class="noslide segn" id="seg${i}grp" type="number" min="1" max="255" value="${inst.grp}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
<td><input class="noslide segn" id="seg${i}spc" type="number" min="0" max="255" value="${inst.spc}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td> <td><input class="noslide segn" id="seg${i}spc" type="number" min="0" max="255" value="${inst.spc}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
<td style="text-align:left;"><button class="btn btn-xs" onclick="setSeg(${i})"><i class="icons btn-icon" id="segc${i}">&#xe390;</i></button></td> <td style="text-align:revert;"><button class="btn btn-xs" onclick="setSeg(${i})"><i class="icons btn-icon" id="segc${i}">&#xe390;</i></button></td>
</tr> </tr>
</table> </table>
<div class="h bp" id="seg${i}len"></div> <div class="h bp" id="seg${i}len"></div>
${!isM?rvXck:''} ${!(isM&&staX<mw*mh)?rvXck:''}
${isM&&stoY-staY>1&&stoX-staX>1?map2D:''} ${isM&&staX<mw*mh&&stoY-staY>1&&stoX-staX>1?map2D:''}
${s.AudioReactive && s.AudioReactive.on ? "" : sndSim} ${s.AudioReactive && s.AudioReactive.on ? "" : sndSim}
${s.CustomEffects && s.CustomEffects.on && fxName.includes("Custom Effect") ? cusEff : ""} ${s.CustomEffects && s.CustomEffects.on && fxName.includes("Custom Effect") ? cusEff : ""}
<label class="check revchkl" id="seg${i}lbtm"> <label class="check revchkl" id="seg${i}lbtm">
${isM?'Transpose':'Mirror effect'} ${isM&&staX<mw*mh?'Transpose':'Mirror effect'}${isM&&staX<mw*mh?
<input type="checkbox" id="seg${i}${isM?'tp':'mi'}" onchange="${(isM?'setTp(':'setMi(')+i})" ${isM?(inst.tp?"checked":""):(inst.mi?"checked":"")}> '<input type="checkbox" id="seg'+i+'tp" onchange="setTp('+i+')" '+(inst.tp?"checked":"")+'>':
'<input type="checkbox" id="seg'+i+'mi" onchange="setMi('+i+')" '+(inst.mi?"checked":"")+'>'}
<span class="checkmark"></span> <span class="checkmark"></span>
</label> </label>
<div class="del"> <div class="del">
@@ -1078,10 +1079,30 @@ function updateLen(s)
var start = parseInt(gId(`seg${s}s`).value); var start = parseInt(gId(`seg${s}s`).value);
var stop = parseInt(gId(`seg${s}e`).value) + (cfg.comp.seglen?start:0); var stop = parseInt(gId(`seg${s}e`).value) + (cfg.comp.seglen?start:0);
var len = stop - start; var len = stop - start;
let sY = gId(`seg${s}sY`);
let eY = gId(`seg${s}eY`);
let sX = gId(`seg${s}s`);
let eX = gId(`seg${s}e`);
let of = gId(`seg${s}of`);
let mySH = gId("mkSYH");
let mySD = gId("mkSYD");
if (isM) { if (isM) {
// do we have 1D segment *after* the matrix?
if (start >= mw*mh) {
if (sY) { sY.value = 0; sY.max = 0; sY.min = 0; }
if (eY) { eY.value = 1; eY.max = 1; eY.min = 0; }
sX.min = mw*mh; sX.max = ledCount-1;
eX.min = mw*mh+1; eX.max = ledCount;
if (mySH) mySH.classList.add("hide");
if (mySD) mySD.classList.add("hide");
if (of) of.classList.remove("hide");
} else {
// matrix setup // matrix setup
let startY = parseInt(gId(`seg${s}sY`).value); if (mySH) mySH.classList.remove("hide");
let stopY = parseInt(gId(`seg${s}eY`).value) + (cfg.comp.seglen?startY:0); if (mySD) mySD.classList.remove("hide");
if (of) of.classList.add("hide");
let startY = parseInt(sY.value);
let stopY = parseInt(eY.value) + (cfg.comp.seglen?startY:0);
len *= (stopY-startY); len *= (stopY-startY);
let tPL = gId(`seg${s}lbtm`); let tPL = gId(`seg${s}lbtm`);
if (stop-start>1 && stopY-startY>1) { if (stop-start>1 && stopY-startY>1) {
@@ -1104,6 +1125,7 @@ function updateLen(s)
} }
} }
} }
}
var out = "(delete)"; var out = "(delete)";
if (len > 1) { if (len > 1) {
out = `${len} LEDs`; out = `${len} LEDs`;
@@ -1119,6 +1141,7 @@ function updateLen(s)
var virt = Math.ceil(len/(grp + spc)); var virt = Math.ceil(len/(grp + spc));
if (!isNaN(virt) && (grp > 1 || spc > 0)) out += ` (${virt} virtual)`; if (!isNaN(virt) && (grp > 1 || spc > 0)) out += ` (${virt} virtual)`;
} }
if (isM && start >= mw*mh) out += " [strip]";
gId(`seg${s}len`).innerHTML = out; gId(`seg${s}len`).innerHTML = out;
draw(); draw();
@@ -1840,11 +1863,11 @@ function makeSeg()
<td><input class="noslide segn" id="seg${lu}e" type="number" min="0" max="${ct}" value="${ct}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td> <td><input class="noslide segn" id="seg${lu}e" type="number" min="0" max="${ct}" value="${ct}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
<td><button class="btn btn-xs" onclick="setSeg(${lu});"><i class="icons bth-icon" id="segc${lu}">&#xe390;</i></button></td> <td><button class="btn btn-xs" onclick="setSeg(${lu});"><i class="icons bth-icon" id="segc${lu}">&#xe390;</i></button></td>
</tr> </tr>
${isM ? '<tr><td>Start Y</td><td>'+(cfg.comp.seglen?'Height':'Stop Y')+'</td></tr>'+ <tr id="mkSYH" class="${isM?"":"hide"}"><td>Start Y</td><td>${cfg.comp.seglen?'Height':'Stop Y'}</td></tr>
'<tr>'+ <tr id="mkSYD" class="${isM?"":"hide"}">
'<td><input class="noslide segn" id="seg'+lu+'sY" type="number" min="0" max="'+(mh-1)+'" value="'+0+'" oninput="updateLen('+lu+')" onkeydown="segEnter('+lu+')"></td>'+ <td><input class="noslide segn" id="seg${lu}sY" type="number" min="0" max="${mh-1}" value="0" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
'<td><input class="noslide segn" id="seg'+lu+'eY" type="number" min="0" max="'+mh+'" value="'+mh+'" oninput="updateLen('+lu+')" onkeydown="segEnter('+lu+')"></td>'+ <td><input class="noslide segn" id="seg${lu}eY" type="number" min="0" max="${mh}" value="${isM?mh:1}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
'</tr>':''} </tr>
</table> </table>
<div class="h" id="seg${lu}len">${ledCount - ns} LEDs</div> <div class="h" id="seg${lu}len">${ledCount - ns} LEDs</div>
<div class="c"><button class="btn btn-p" onclick="resetUtil()">Cancel</button></div> <div class="c"><button class="btn btn-p" onclick="resetUtil()">Cancel</button></div>
@@ -2174,25 +2197,26 @@ function setSeg(s)
let sX = gId(`seg${s}s`); let sX = gId(`seg${s}s`);
let eX = gId(`seg${s}e`); let eX = gId(`seg${s}e`);
var start = parseInt(sX.value); var start = parseInt(sX.value);
var stop = parseInt(eX.value); var stop = parseInt(eX.value) + (cfg.comp.seglen?start:0);
if (start<sX.min || start>sX.max) {sX.value=sX.min; return;} // prevent out of bounds if (start<sX.min || start>sX.max) {sX.value=sX.min; return;} // prevent out of bounds
if (stop<eX.min || stop>eX.max) {eX.value=eX.max; return;} // prevent out of bounds if (stop<eX.min || stop-(cfg.comp.seglen?start:0)>eX.max) {eX.value=eX.max; return;} // prevent out of bounds
if ((cfg.comp.seglen && stop == 0) || (!cfg.comp.seglen && stop <= start)) {delSeg(s); return;} if ((cfg.comp.seglen && stop == 0) || (!cfg.comp.seglen && stop <= start)) {delSeg(s); return;}
var obj = {"seg": {"id": s, "n": name, "start": start, "stop": (cfg.comp.seglen?start:0)+stop}}; var obj = {"seg": {"id": s, "n": name, "start": start, "stop": stop}};
if (isM) { if (isM && start<mw*mh) {
let sY = gId(`seg${s}sY`); let sY = gId(`seg${s}sY`);
let eY = gId(`seg${s}eY`); let eY = gId(`seg${s}eY`);
var startY = parseInt(sY.value); var startY = parseInt(sY.value);
var stopY = parseInt(eY.value); var stopY = parseInt(eY.value) + (cfg.comp.seglen?startY:0);
if (startY<sY.min || startY>sY.max) {sY.value=sY.min; return;} // prevent out of bounds if (startY<sY.min || startY>sY.max) {sY.value=sY.min; return;} // prevent out of bounds
if (stopY<eY.min || stopY>eY.max) {eY.value=eY.max; return;} // prevent out of bounds if (stopY<eY.min || stopY>eY.max) {eY.value=eY.max; return;} // prevent out of bounds
obj.seg.startY = startY; obj.seg.startY = startY;
obj.seg.stopY = (cfg.comp.seglen?startY:0)+stopY; obj.seg.stopY = stopY;
} }
if (gId(`seg${s}grp`)) { // advanced options, not present in new segment dialog (makeSeg()) let g = gId(`seg${s}grp`);
var grp = parseInt(gId(`seg${s}grp`).value); if (g) { // advanced options, not present in new segment dialog (makeSeg())
var spc = parseInt(gId(`seg${s}spc`).value); let grp = parseInt(g.value);
var ofs = parseInt(gId(`seg${s}of` ).value); let spc = parseInt(gId(`seg${s}spc`).value);
let ofs = parseInt(gId(`seg${s}of` ).value);
obj.seg.grp = grp; obj.seg.grp = grp;
obj.seg.spc = spc; obj.seg.spc = spc;
obj.seg.of = ofs; obj.seg.of = ofs;

View File

@@ -5,7 +5,7 @@
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
<meta charset="utf-8"> <meta charset="utf-8">
<title>DMX Settings</title> <title>DMX Settings</title>
<script> <script>
var d=document; var d=document;
var loc = false, locip; var loc = false, locip;
function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");} function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}
@@ -65,8 +65,8 @@
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=7'; var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=7';
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
} }
</script> </script>
<style>@import url("style.css");</style> <style>@import url("style.css");</style>
</head> </head>
<body onload="S()"> <body onload="S()">
<form id="form_s" name="Sf" method="post"> <form id="form_s" name="Sf" method="post">

View File

@@ -7,12 +7,12 @@
<title>LED Settings</title> <title>LED Settings</title>
<script> <script>
var d=document,laprev=55,maxB=1,maxV=0,maxM=4000,maxPB=4096,maxL=1333,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32 var d=document,laprev=55,maxB=1,maxV=0,maxM=4000,maxPB=4096,maxL=1333,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
var customStarts=false,startsDirty=[],maxCOOverrides=5;
var loc = false, locip;
d.um_p = []; d.um_p = [];
d.rsvd = []; d.rsvd = [];
d.ro_gpio = []; d.ro_gpio = [];
d.max_gpio = 39; d.max_gpio = 39;
var customStarts=false,startsDirty=[],maxCOOverrides=5;
var loc = false, locip;
function H(){window.open("https://mm.kno.wled.ge/features/settings/#led-settings");} function H(){window.open("https://mm.kno.wled.ge/features/settings/#led-settings");}
function B(){window.open("/settings","_self");} function B(){window.open("/settings","_self");}
function gId(n){return d.getElementById(n);} function gId(n){return d.getElementById(n);}
@@ -27,7 +27,6 @@
d.body.appendChild(scE); d.body.appendChild(scE);
// success event // success event
scE.addEventListener("load", () => { scE.addEventListener("load", () => {
//console.log("File loaded");
GetV();checkSi();setABL(); GetV();checkSi();setABL();
if (d.um_p[0]==-1) d.um_p.shift(); if (d.um_p[0]==-1) d.um_p.shift();
}); });
@@ -142,6 +141,7 @@
if (t == 44 || t == 45) return len*4; //RGBW if (t == 44 || t == 45) return len*4; //RGBW
return len*3; return len*3;
} }
function UI(change=false) function UI(change=false)
{ {
var isRGBW = false, memu = 0; var isRGBW = false, memu = 0;
@@ -362,11 +362,11 @@ ${i+1}:
<span id="psd${i}">Start:</span> <input type="number" name="LS${i}" id="ls${i}" class="l starts" min="0" max="8191" value="${lastEnd(i)}" oninput="startsDirty[${i}]=true;UI();" required />&nbsp; <span id="psd${i}">Start:</span> <input type="number" name="LS${i}" id="ls${i}" class="l starts" min="0" max="8191" value="${lastEnd(i)}" oninput="startsDirty[${i}]=true;UI();" required />&nbsp;
<div id="dig${i}c" style="display:inline">Length: <input type="number" name="LC${i}" class="l" min="1" max="${maxPB}" value="1" required oninput="UI()" /></div><br> <div id="dig${i}c" style="display:inline">Length: <input type="number" name="LC${i}" class="l" min="1" max="${maxPB}" value="1" required oninput="UI()" /></div><br>
</div> </div>
<span id="p0d${i}">GPIO:</span> <input type="number" name="L0${i}" min="0" max="48" required class="s" onchange="UI()"/> <span id="p0d${i}">GPIO:</span> <input type="number" name="L0${i}" required class="s" onchange="UI()"/>
<span id="p1d${i}"></span><input type="number" name="L1${i}" min="0" max="48" class="s" onchange="UI()"/> <span id="p1d${i}"></span><input type="number" name="L1${i}" class="s" onchange="UI()"/>
<span id="p2d${i}"></span><input type="number" name="L2${i}" min="0" max="48" class="s" onchange="UI()"/> <span id="p2d${i}"></span><input type="number" name="L2${i}" class="s" onchange="UI()"/>
<span id="p3d${i}"></span><input type="number" name="L3${i}" min="0" max="48" class="s" onchange="UI()"/> <span id="p3d${i}"></span><input type="number" name="L3${i}" class="s" onchange="UI()"/>
<span id="p4d${i}"></span><input type="number" name="L4${i}" min="0" max="48" class="s" onchange="UI()"/> <span id="p4d${i}"></span><input type="number" name="L4${i}" class="s" onchange="UI()"/>
<div id="dig${i}r" style="display:inline"><br><span id="rev${i}">Reversed</span>: <input type="checkbox" name="CV${i}"></div> <div id="dig${i}r" style="display:inline"><br><span id="rev${i}">Reversed</span>: <input type="checkbox" name="CV${i}"></div>
<div id="dig${i}s" style="display:inline"><br>Skip first LEDs: <input type="number" name="SL${i}" min="0" max="255" value="0" oninput="UI()"></div> <div id="dig${i}s" style="display:inline"><br>Skip first LEDs: <input type="number" name="SL${i}" min="0" max="255" value="0" oninput="UI()"></div>
<div id="dig${i}f" style="display:inline"><br>Off Refresh: <input id="rf${i}" type="checkbox" name="RF${i}"></div> <div id="dig${i}f" style="display:inline"><br>Off Refresh: <input id="rf${i}" type="checkbox" name="RF${i}"></div>
@@ -436,7 +436,7 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
var c = gId("btns").innerHTML; var c = gId("btns").innerHTML;
var bt = "BT" + String.fromCharCode((i<10?48:55)+i); var bt = "BT" + String.fromCharCode((i<10?48:55)+i);
var be = "BE" + String.fromCharCode((i<10?48:55)+i); var be = "BE" + String.fromCharCode((i<10?48:55)+i);
c += `Button ${i} GPIO: <input type="number" min="-1" max="48" name="${bt}" onchange="UI()" class="xs" value="${p}">`; c += `Button ${i} GPIO: <input type="number" name="${bt}" onchange="UI()" class="xs" value="${p}">`;
c += `&nbsp;<select name="${be}">` c += `&nbsp;<select name="${be}">`
c += `<option value="0" ${t==0?"selected":""}>Disabled</option>`; c += `<option value="0" ${t==0?"selected":""}>Disabled</option>`;
c += `<option value="2" ${t==2?"selected":""}>Pushbutton</option>`; c += `<option value="2" ${t==2?"selected":""}>Pushbutton</option>`;

View File

@@ -9,8 +9,8 @@
var loc = false, locip; var loc = false, locip;
function gId(s){return d.getElementById(s);} function gId(s){return d.getElementById(s);}
function toggle(el){gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide");} function toggle(el){gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide");}
function hideNoDMX(){gId("dmxOnOff2").style.display="none";} function hideNoDMX(){gId("dmxOnOff2").style.display="none";} //WLEDMM
function hideNoLOX(){gId("loxOnOff2").style.display="none";} function hideNoLOX(){gId("loxOnOff2").style.display="none";} //WLEDMM
function H(){window.open("https://mm.kno.wled.ge/interfaces/udp-notifier/");} function H(){window.open("https://mm.kno.wled.ge/interfaces/udp-notifier/");}
function B(){window.open("/settings","_self");} function B(){window.open("/settings","_self");}
function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;} function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;}
@@ -70,7 +70,7 @@
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
} }
</script> </script>
<style>@import url("style.css");</style> <style>@import url("style.css");</style>
</head> </head>
<body onload="S()"> <body onload="S()">
<form id="form_s" name="Sf" method="post" onsubmit="GC()"> <form id="form_s" name="Sf" method="post" onsubmit="GC()">
@@ -170,7 +170,7 @@ Timeout: <input name="ET" type="number" min="1" max="65000" required> ms<br>
Force max brightness: <input type="checkbox" name="FB"><br> Force max brightness: <input type="checkbox" name="FB"><br>
Disable realtime gamma correction: <input type="checkbox" name="RG"><br> Disable realtime gamma correction: <input type="checkbox" name="RG"><br>
Realtime LED offset: <input name="WO" type="number" min="-255" max="255" required> Realtime LED offset: <input name="WO" type="number" min="-255" max="255" required>
<div id="dmxOnOff2"> <div id="dmxOnOff2"> <!--WLEDMM-->
<br><em style="color:darkorange">This firmware build does not include DMX output support. <br></em> <br><em style="color:darkorange">This firmware build does not include DMX output support. <br></em>
</div> </div>
<hr class="sml"> <hr class="sml">
@@ -235,7 +235,7 @@ Hue Bridge IP:<br>
(when first connecting)<br> (when first connecting)<br>
</div> </div>
Hue status: <span class="sip"> Disabled in this build </span> Hue status: <span class="sip"> Disabled in this build </span>
<div id="loxOnOff2"> <div id="loxOnOff2"> <!--WLEDMM-->>
<br><em style="color:darkorange">This firmware build does not include Loxone Lighting support. <br></em> <br><em style="color:darkorange">This firmware build does not include Loxone Lighting support. <br></em>
</div> </div>
<h3>Serial</h3> <h3>Serial</h3>

View File

@@ -264,19 +264,20 @@ class Usermod {
virtual ~Usermod() { if (um_data) delete um_data; } virtual ~Usermod() { if (um_data) delete um_data; }
virtual void setup() = 0; // pure virtual, has to be overriden virtual void setup() = 0; // pure virtual, has to be overriden
virtual void loop() = 0; // pure virtual, has to be overriden virtual void loop() = 0; // pure virtual, has to be overriden
virtual void handleOverlayDraw() {} virtual void handleOverlayDraw() {} // called after all effects have been processed, just before strip.show()
virtual bool handleButton(uint8_t b) { return false; } virtual bool handleButton(uint8_t b) { return false; } // button overrides are possible here
virtual bool getUMData(um_data_t **data) { if (data) *data = nullptr; return false; }; virtual bool getUMData(um_data_t **data) { if (data) *data = nullptr; return false; }; // usermod data exchange [see examples for audio effects]
virtual void connected() {} virtual void connected() {} // called when WiFi is (re)connected
virtual void appendConfigData() {} virtual void appendConfigData() {} // helper function called from usermod settings page to add metadata for entry fields
virtual void addToJsonState(JsonObject& obj) {} virtual void addToJsonState(JsonObject& obj) {} // add JSON objects for WLED state
virtual void addToJsonInfo(JsonObject& obj) {} virtual void addToJsonInfo(JsonObject& obj) {} // add JSON objects for UI Info page
virtual void readFromJsonState(JsonObject& obj) {} virtual void readFromJsonState(JsonObject& obj) {} // process JSON messages received from web server
virtual void addToConfig(JsonObject& obj) {} virtual void addToConfig(JsonObject& obj) {} // add JSON entries that go to cfg.json
virtual bool readFromConfig(JsonObject& obj) { return true; } // Note as of 2021-06 readFromConfig() now needs to return a bool, see usermod_v2_example.h virtual bool readFromConfig(JsonObject& obj) { return true; } // Note as of 2021-06 readFromConfig() now needs to return a bool, see usermod_v2_example.h
virtual void onMqttConnect(bool sessionPresent) {} virtual void onMqttConnect(bool sessionPresent) {} // fired when MQTT connection is established (so usermod can subscribe)
virtual bool onMqttMessage(char* topic, char* payload) { return false; } virtual bool onMqttMessage(char* topic, char* payload) { return false; } // fired upon MQTT message received (wled topic)
virtual void onUpdateBegin(bool) {} virtual void onUpdateBegin(bool) {} // fired prior to and after unsuccessful firmware update
virtual void onStateChange(uint8_t mode) {} // fired upon WLED state change
virtual uint16_t getId() {return USERMOD_ID_UNSPECIFIED;} virtual uint16_t getId() {return USERMOD_ID_UNSPECIFIED;}
}; };
@@ -301,6 +302,7 @@ class UsermodManager {
void onMqttConnect(bool sessionPresent); void onMqttConnect(bool sessionPresent);
bool onMqttMessage(char* topic, char* payload); bool onMqttMessage(char* topic, char* payload);
void onUpdateBegin(bool); void onUpdateBegin(bool);
void onStateChange(uint8_t);
bool add(Usermod* um); bool add(Usermod* um);
Usermod* lookup(uint16_t mod_id); Usermod* lookup(uint16_t mod_id);
Usermod* lookupName(const char *mod_name); //WLEDMM Usermod* lookupName(const char *mod_name); //WLEDMM

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -273,6 +273,9 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
JsonArray iarr = elem[F("i")]; //set individual LEDs JsonArray iarr = elem[F("i")]; //set individual LEDs
if (!iarr.isNull()) { if (!iarr.isNull()) {
uint8_t oldMap1D2D = seg.map1D2D;
seg.map1D2D = M12_Pixels; // no mapping
// set brightness immediately and disable transition // set brightness immediately and disable transition
transitionDelayTemp = 0; transitionDelayTemp = 0;
jsonTransitionOnce = true; jsonTransitionOnce = true;
@@ -316,6 +319,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
set = 0; set = 0;
} }
} }
seg.map1D2D = oldMap1D2D; // restore mapping
strip.trigger(); // force segment update strip.trigger(); // force segment update
} }
// send UDP/WS if segment options changed (except selection; will also deselect current preset) // send UDP/WS if segment options changed (except selection; will also deselect current preset)

View File

@@ -129,6 +129,9 @@ void stateUpdated(byte callMode) {
//deactivate nightlight if target brightness is reached //deactivate nightlight if target brightness is reached
if (bri == nightlightTargetBri && callMode != CALL_MODE_NO_NOTIFY && nightlightMode != NL_MODE_SUN) nightlightActive = false; if (bri == nightlightTargetBri && callMode != CALL_MODE_NO_NOTIFY && nightlightMode != NL_MODE_SUN) nightlightActive = false;
// notify usermods of state change
usermods.onStateChange(callMode);
if (fadeTransition) { if (fadeTransition) {
//set correct delay if not using notification delay //set correct delay if not using notification delay
if (callMode != CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay; // load actual transition duration if (callMode != CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay; // load actual transition duration

View File

@@ -15,6 +15,7 @@ class NetworkDebugPrinter : public Print {
virtual void flush( bool txOnly) { return;} // WLEDMM virtual void flush( bool txOnly) { return;} // WLEDMM
}; };
// use it on your linux/macOS with: nc -p 7868 -u -l -s <network ip>
extern NetworkDebugPrinter NetDebug; extern NetworkDebugPrinter NetDebug;
#endif #endif

View File

@@ -156,7 +156,7 @@ void serializePlaylist(JsonObject sObj) {
JsonArray ps = playlist.createNestedArray("ps"); JsonArray ps = playlist.createNestedArray("ps");
JsonArray dur = playlist.createNestedArray("dur"); JsonArray dur = playlist.createNestedArray("dur");
JsonArray transition = playlist.createNestedArray(F("transition")); JsonArray transition = playlist.createNestedArray(F("transition"));
playlist[F("repeat")] = playlistRepeat; playlist[F("repeat")] = (playlistIndex < 0) ? playlistRepeat - 1 : playlistRepeat; // remove added repetition count (if not yet running)
playlist["end"] = playlistEndPreset; playlist["end"] = playlistEndPreset;
playlist["r"] = playlistOptions & PL_OPTION_SHUFFLE; playlist["r"] = playlistOptions & PL_OPTION_SHUFFLE;
for (int i=0; i<playlistLen; i++) { for (int i=0; i<playlistLen; i++) {

View File

@@ -274,7 +274,7 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
} else { } else {
// this is a playlist or API call // this is a playlist or API call
if (sObj[F("playlist")].isNull()) { if (sObj[F("playlist")].isNull()) {
// we will save API call immediately // we will save API call immediately (often causes presets.json corruption)
presetToSave = 0; presetToSave = 0;
if (index > 250 || !fileDoc) return; // cannot save API calls to temporary preset (255) if (index > 250 || !fileDoc) return; // cannot save API calls to temporary preset (255)
sObj.remove("o"); sObj.remove("o");
@@ -284,11 +284,12 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
sObj.remove(F("psave")); sObj.remove(F("psave"));
if (sObj["n"].isNull()) sObj["n"] = saveName; if (sObj["n"].isNull()) sObj["n"] = saveName;
initPresetsFile(); // just in case if someone deleted presets.json using /edit initPresetsFile(); // just in case if someone deleted presets.json using /edit
writeObjectToFileUsingId(getFileName(index), index, fileDoc); writeObjectToFileUsingId(getFileName(index<255), index, fileDoc);
presetsModifiedTime = toki.second(); //unix time presetsModifiedTime = toki.second(); //unix time
updateFSInfo(); updateFSInfo();
} else { } else {
// store playlist // store playlist
// WARNING: playlist will be loaded in json.cpp after this call and will have repeat counter increased by 1
includeBri = true; // !sObj["on"].isNull(); includeBri = true; // !sObj["on"].isNull();
playlistSave = true; playlistSave = true;
} }

View File

@@ -40,6 +40,7 @@ bool UsermodManager::onMqttMessage(char* topic, char* payload) {
return false; return false;
} }
void UsermodManager::onUpdateBegin(bool init) { for (byte i = 0; i < numMods; i++) ums[i]->onUpdateBegin(init); } // notify usermods that update is to begin void UsermodManager::onUpdateBegin(bool init) { for (byte i = 0; i < numMods; i++) ums[i]->onUpdateBegin(init); } // notify usermods that update is to begin
void UsermodManager::onStateChange(uint8_t mode) { for (byte i = 0; i < numMods; i++) ums[i]->onStateChange(mode); } // notify usermods that WLED state changed
/* /*
* Enables usermods to lookup another Usermod. * Enables usermods to lookup another Usermod.

View File

@@ -96,10 +96,6 @@
#include "my_config.h" #include "my_config.h"
#endif #endif
#ifdef WLED_DEBUG_HOST
#include "net_debug.h"
#endif
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>
#ifdef WLED_ADD_EEPROM_SUPPORT #ifdef WLED_ADD_EEPROM_SUPPORT
#include <EEPROM.h> #include <EEPROM.h>
@@ -730,6 +726,7 @@ WLED_GLOBAL volatile uint8_t jsonBufferLock _INIT(0);
// enable additional debug output // enable additional debug output
#if defined(WLED_DEBUG_HOST) #if defined(WLED_DEBUG_HOST)
#include "net_debug.h"
// On the host side, use netcat to receive the log statements: nc -l 7868 -u // On the host side, use netcat to receive the log statements: nc -l 7868 -u
// use -D WLED_DEBUG_HOST='"192.168.xxx.xxx"' or FQDN within quotes // use -D WLED_DEBUG_HOST='"192.168.xxx.xxx"' or FQDN within quotes
#define DEBUGOUT NetDebug #define DEBUGOUT NetDebug