diff --git a/Arduino/McLighting/McLighting.ino b/Arduino/McLighting/McLighting.ino index b229a748..83f18ba8 100644 --- a/Arduino/McLighting/McLighting.ino +++ b/Arduino/McLighting/McLighting.ino @@ -271,9 +271,11 @@ void initMqtt() { mqtt_intopic[sizeof(mqtt_intopic) - 1] = 0x00; snprintf(mqtt_outtopic, sizeof(mqtt_outtopic), "%s/out", mqtt_clientid); mqtt_outtopic[sizeof(mqtt_outtopic) - 1] = 0x00; - #if defined(MQTT_HOME_ASSISTANT_SUPPORT) - snprintf(mqtt_ha_config, sizeof(mqtt_ha_config), "homeassistant/light/%s/config", mqtt_clientid); - mqtt_ha_config[sizeof(mqtt_ha_config) - 1] = 0x00; + #if defined(ENABLE_HOMEASSISTANT) + #if defined(MQTT_HOMEASSISTANT_SUPPORT) + snprintf(mqtt_ha_config, sizeof(mqtt_ha_config), "homeassistant/light/%s/config", mqtt_clientid); + mqtt_ha_config[sizeof(mqtt_ha_config) - 1] = 0x00; + #endif snprintf(mqtt_ha_state_in, sizeof(mqtt_ha_state_in), "home/%s_ha/state/in", mqtt_clientid); mqtt_ha_state_in[sizeof(mqtt_ha_state_in) - 1] = 0x00; snprintf(mqtt_ha_state_out, sizeof(mqtt_ha_state_out), "home/%s_ha/state/out", mqtt_clientid); @@ -655,9 +657,6 @@ void loop() { if (State.mode == OFF) { if (prevmode != State.mode) { - #if defined(ENABLE_MQTT) - snprintf(mqtt_buf, sizeof(mqtt_buf), "OK =off", ""); - #endif #if defined(POWER_SUPPLY) digitalWrite(POWER_SUPPLY, !POWER_ON); // power off -> external power supply #endif @@ -674,19 +673,9 @@ void loop() { if (State.mode == SET) { State.mode = HOLD; - // Segment - if (prevsegment != State.segment) { - #if defined(ENABLE_MQTT) - snprintf(mqtt_buf, sizeof(mqtt_buf), "OK Ss%i", State.segment); - #endif - //prevsegment = State.segment; - } // Mode - if (segState.mode[State.segment] != fx_mode) { + if ((segState.mode[State.segment] != fx_mode) || prevmode == OFF) { segState.mode[State.segment] = fx_mode; - #if defined(ENABLE_MQTT) - snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /%i", segState.mode[State.segment]); - #endif strip->strip_off(); autoCount[State.segment] = 0; autoDelay[State.segment] = 0; @@ -701,13 +690,10 @@ void loop() { }*/ // Brightness if (strip->getBrightness() != State.brightness) { - #if defined(ENABLE_MQTT) - snprintf(mqtt_buf, sizeof(mqtt_buf), "OK %%%i", State.brightness); - #endif brightness_trans = State.brightness; } // Speed - if (fx_speed != segState.speed[State.segment]) { + if (fx_speed != segState.speed[prevsegment]) { #if defined(ENABLE_MQTT) snprintf(mqtt_buf, sizeof(mqtt_buf), "OK ?%i", segState.speed[prevsegment]); #endif @@ -739,12 +725,6 @@ void loop() { } //strip->setBrightness(brightness_actual); #if defined(ENABLE_MQTT) - #if ENABLE_MQTT == 0 - mqtt_client->publish(mqtt_outtopic, mqtt_buf); - #endif - #if ENABLE_MQTT == 1 - mqtt_client->publish(mqtt_outtopic, qospub, false, mqtt_buf); - #endif #if defined(ENABLE_HOMEASSISTANT) if(ha_send_data.active()) ha_send_data.detach(); ha_send_data.once(DELAY_MQTT_HA_MESSAGE, tickerSendState); diff --git a/Arduino/McLighting/WS2812FX.cpp b/Arduino/McLighting/WS2812FX.cpp index dad49aca..2e49feb7 100644 --- a/Arduino/McLighting/WS2812FX.cpp +++ b/Arduino/McLighting/WS2812FX.cpp @@ -61,7 +61,7 @@ void WS2812FX::init() { // void WS2812FX::timer() { // for (int j=0; j < 1000; j++) { -// uint16_t delay = (this->*_mode[SEGMENT.mode])(); +// uint16_t delay = (this->*_modes[_seg->mode])(); // } // } @@ -69,15 +69,20 @@ void WS2812FX::service() { if(_running || _triggered) { unsigned long now = millis(); // Be aware, millis() rolls over every 49 days bool doShow = false; - for(uint8_t i=0; i < _num_segments; i++) { - _segment_index = i; - CLR_FRAME; - if(now > SEGMENT_RUNTIME.next_time || _triggered) { - SET_FRAME; - doShow = true; - uint16_t delay = (this->*_mode[SEGMENT.mode])(); - SEGMENT_RUNTIME.next_time = now + max(delay, SPEED_MIN); - SEGMENT_RUNTIME.counter_mode_call++; + for(uint8_t i=0; i < _active_segments_len; i++) { + if(_active_segments[i] != INACTIVE_SEGMENT) { + _segment_index = i; + _seg = &_segments[_active_segments[i]]; + _seg_len = (uint16_t)(_seg->stop - _seg->start + 1); + _seg_rt = &_segment_runtimes[i]; + CLR_FRAME_CYCLE; + if(now > _seg_rt->next_time || _triggered) { + SET_FRAME; + doShow = true; + uint16_t delay = (this->*_modes[_seg->mode])(); + _seg_rt->next_time = now + max(delay, SPEED_MIN); + _seg_rt->counter_mode_call++; + } } } if(doShow) { @@ -91,23 +96,15 @@ void WS2812FX::service() { // overload setPixelColor() functions so we can use gamma correction // (see https://learn.adafruit.com/led-tricks-gamma-correction/the-issue) void WS2812FX::setPixelColor(uint16_t n, uint32_t c) { - if(IS_GAMMA) { - uint8_t w = (c >> 24) & 0xFF; - uint8_t r = (c >> 16) & 0xFF; - uint8_t g = (c >> 8) & 0xFF; - uint8_t b = c & 0xFF; - Adafruit_NeoPixel::setPixelColor(n, gamma8(r), gamma8(g), gamma8(b), gamma8(w)); - } else { - Adafruit_NeoPixel::setPixelColor(n, c); - } + uint8_t w = (c >> 24) & 0xFF; + uint8_t r = (c >> 16) & 0xFF; + uint8_t g = (c >> 8) & 0xFF; + uint8_t b = c & 0xFF; + setPixelColor(n, r, g, b, w); } void WS2812FX::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) { - if(IS_GAMMA) { - Adafruit_NeoPixel::setPixelColor(n, gamma8(r), gamma8(g), gamma8(b)); - } else { - Adafruit_NeoPixel::setPixelColor(n, r, g, b); - } + setPixelColor(n, r, g, b, 0); } void WS2812FX::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w) { @@ -125,13 +122,17 @@ void WS2812FX::copyPixels(uint16_t dest, uint16_t src, uint16_t count) { memmove(pixels + (dest * bytesPerPixel), pixels + (src * bytesPerPixel), count * bytesPerPixel); } +// change the underlying Adafruit_NeoPixel pixels pointer (use with care) +void WS2812FX::setPixels(uint16_t num_leds, uint8_t* ptr) { + free(Adafruit_NeoPixel::pixels); // free existing data (if any) + Adafruit_NeoPixel::pixels = ptr; + Adafruit_NeoPixel::numLEDs = num_leds; + Adafruit_NeoPixel::numBytes = num_leds * ((wOffset == rOffset) ? 3 : 4); +} + // overload show() functions so we can use custom show() void WS2812FX::show(void) { - if(customShow == NULL) { - Adafruit_NeoPixel::show(); - } else { - customShow(); - } + customShow == NULL ? Adafruit_NeoPixel::show() : customShow(); } void WS2812FX::start() { @@ -174,17 +175,16 @@ void WS2812FX::setSpeed(uint16_t s) { } void WS2812FX::setSpeed(uint8_t seg, uint16_t s) { -// resetSegmentRuntime(seg); _segments[seg].speed = constrain(s, SPEED_MIN, SPEED_MAX); } void WS2812FX::increaseSpeed(uint8_t s) { - uint16_t newSpeed = constrain(SEGMENT.speed + s, SPEED_MIN, SPEED_MAX); + uint16_t newSpeed = constrain(_seg->speed + s, SPEED_MIN, SPEED_MAX); setSpeed(newSpeed); } void WS2812FX::decreaseSpeed(uint8_t s) { - uint16_t newSpeed = constrain(SEGMENT.speed - s, SPEED_MIN, SPEED_MAX); + uint16_t newSpeed = constrain(_seg->speed - s, SPEED_MIN, SPEED_MAX); setSpeed(newSpeed); } @@ -201,13 +201,11 @@ void WS2812FX::setColor(uint32_t c) { } void WS2812FX::setColor(uint8_t seg, uint32_t c) { -// resetSegmentRuntime(seg); _segments[seg].colors[0] = c; } void WS2812FX::setColors(uint8_t seg, uint32_t* c) { -// resetSegmentRuntime(seg); - for(uint8_t i=0; i _segments[0].stop - _segments[0].start + 1) s = 1; - s = _segments[0].stop - _segments[0].start + 1 - s; - - for(uint16_t i=_segments[0].start + s; i <= (_segments[0].stop - _segments[0].start + 1); i++) { - setPixelColor(i, 0); - } + uint16_t seglen = _segments[0].stop - _segments[0].start + 1; + fill(BLACK, _segments[0].start, seglen); show(); - setLength(s); + if (s < seglen) setLength(seglen - s); } boolean WS2812FX::isRunning() { @@ -271,16 +265,24 @@ boolean WS2812FX::isFrame() { return isFrame(0); } -boolean WS2812FX::isFrame(uint8_t segIndex) { - return (_segment_runtimes[segIndex].aux_param2 & FRAME); +boolean WS2812FX::isFrame(uint8_t seg) { + uint8_t* ptr = (uint8_t*)memchr(_active_segments, seg, _active_segments_len); + if(ptr == NULL) return false; // segment not active + return (_segment_runtimes[ptr - _active_segments].aux_param2 & FRAME); } boolean WS2812FX::isCycle() { return isCycle(0); } -boolean WS2812FX::isCycle(uint8_t segIndex) { - return (_segment_runtimes[segIndex].aux_param2 & CYCLE); +boolean WS2812FX::isCycle(uint8_t seg) { + uint8_t* ptr = (uint8_t*)memchr(_active_segments, seg, _active_segments_len); + if(ptr == NULL) return false; // segment not active + return (_segment_runtimes[ptr - _active_segments].aux_param2 & CYCLE); +} + +void WS2812FX::setCycle() { + SET_CYCLE; } uint8_t WS2812FX::getMode(void) { @@ -299,7 +301,6 @@ uint16_t WS2812FX::getSpeed(uint8_t seg) { return _segments[seg].speed; } - uint8_t WS2812FX::getOptions(uint8_t seg) { return _segments[seg].options; } @@ -343,9 +344,9 @@ uint32_t* WS2812FX::getColors(uint8_t seg) { uint8_t WS2812FX::getSegmentIndex(void) { return _segment_index; } - + WS2812FX::Segment* WS2812FX::getSegment(void) { - return &_segments[_segment_index]; + return _seg; } WS2812FX::Segment* WS2812FX::getSegment(uint8_t seg) { @@ -357,17 +358,23 @@ WS2812FX::Segment* WS2812FX::getSegments(void) { } WS2812FX::Segment_runtime* WS2812FX::getSegmentRuntime(void) { - return &_segment_runtimes[_segment_index]; + return _seg_rt; } WS2812FX::Segment_runtime* WS2812FX::getSegmentRuntime(uint8_t seg) { - return &_segment_runtimes[seg]; + uint8_t* ptr = (uint8_t*)memchr(_active_segments, seg, _active_segments_len); + if(ptr == NULL) return NULL; // segment not active + return &_segment_runtimes[ptr - _active_segments]; } WS2812FX::Segment_runtime* WS2812FX::getSegmentRuntimes(void) { return _segment_runtimes; } +uint8_t* WS2812FX::getActiveSegments(void) { + return _active_segments; +} + const __FlashStringHelper* WS2812FX::getModeName(uint8_t m) { if(m < MODE_COUNT) { return _names[m]; @@ -376,22 +383,32 @@ const __FlashStringHelper* WS2812FX::getModeName(uint8_t m) { } } -void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, bool reverse) { +void WS2812FX::setIdleSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, uint8_t options) { uint32_t colors[] = {color, 0, 0}; - setSegment(n, start, stop, mode, colors, speed, reverse); + setIdleSegment(n, start, stop, mode, colors, speed, options); } -void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, uint8_t options) { - uint32_t colors[] = {color, 0, 0}; +void WS2812FX::setIdleSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint16_t speed, uint8_t options) { setSegment(n, start, stop, mode, colors, speed, options); + if(n < _active_segments_len) removeActiveSegment(n);; +} + +void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, bool reverse) { + uint32_t colors[] = {color, 0, 0}; + setSegment(n, start, stop, mode, colors, speed, (uint8_t)(reverse ? REVERSE : NO_OPTIONS)); } void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint16_t speed, bool reverse) { setSegment(n, start, stop, mode, colors, speed, (uint8_t)(reverse ? REVERSE : NO_OPTIONS)); } +void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, uint8_t options) { + uint32_t colors[] = {color, 0, 0}; + setSegment(n, start, stop, mode, colors, speed, options); +} + void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint16_t speed, uint8_t options) { - if(n < (sizeof(_segments) / sizeof(_segments[0]))) { + if(n < _segments_len) { if(n + 1 > _num_segments) _num_segments = n + 1; _segments[n].start = start; _segments[n].stop = stop; @@ -399,34 +416,75 @@ void WS2812FX::setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode _segments[n].speed = speed; _segments[n].options = options; - for(uint8_t i=0; i g -> b -> back to r @@ -454,7 +511,6 @@ uint32_t WS2812FX::color_wheel(uint8_t pos) { } } - /* * Returns a new, random wheel index with a minimum distance of 42 from pos. */ @@ -483,7 +539,7 @@ uint8_t WS2812FX::random8() { // note random8(lim) generates numbers in the range 0 to (lim -1) uint8_t WS2812FX::random8(uint8_t lim) { uint8_t r = random8(); - r = (r * lim) >> 8; + r = ((uint16_t)r * lim) >> 8; return r; } @@ -528,14 +584,20 @@ uint32_t* WS2812FX::intensitySums() { return intensities; } + +/* ##################################################### +# +# Mode Functions +# +##################################################### */ + /* * No blinking. Just plain old static light. */ uint16_t WS2812FX::mode_static(void) { - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { - setPixelColor(i, SEGMENT.colors[0]); - } - return 500; + fill(_seg->colors[0], _seg->start, _seg_len); + SET_CYCLE; + return _seg->speed; } @@ -545,16 +607,15 @@ uint16_t WS2812FX::mode_static(void) { * if(strobe == true) then create a strobe effect */ uint16_t WS2812FX::blink(uint32_t color1, uint32_t color2, bool strobe) { - uint32_t color = ((SEGMENT_RUNTIME.counter_mode_call & 1) == 0) ? color1 : color2; - if(IS_REVERSE) color = (color == color1) ? color2 : color1; - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { - setPixelColor(i, color); - } - - if((SEGMENT_RUNTIME.counter_mode_call & 1) == 0) { - return strobe ? 20 : (SEGMENT.speed / 2); + if(_seg_rt->counter_mode_call & 1) { + uint32_t color = (IS_REVERSE) ? color1 : color2; // off + fill(color, _seg->start, _seg_len); + SET_CYCLE; + return strobe ? _seg->speed - 20 : (_seg->speed / 2); } else { - return strobe ? SEGMENT.speed - 20 : (SEGMENT.speed / 2); + uint32_t color = (IS_REVERSE) ? color2 : color1; // on + fill(color, _seg->start, _seg_len); + return strobe ? 20 : (_seg->speed / 2); } } @@ -563,7 +624,7 @@ uint16_t WS2812FX::blink(uint32_t color1, uint32_t color2, bool strobe) { * Normal blinking. 50% on/off time. */ uint16_t WS2812FX::mode_blink(void) { - return blink(SEGMENT.colors[0], SEGMENT.colors[1], false); + return blink(_seg->colors[0], _seg->colors[1], false); } @@ -571,7 +632,7 @@ uint16_t WS2812FX::mode_blink(void) { * Classic Blink effect. Cycling through the rainbow. */ uint16_t WS2812FX::mode_blink_rainbow(void) { - return blink(color_wheel(SEGMENT_RUNTIME.counter_mode_call & 0xFF), SEGMENT.colors[1], false); + return blink(color_wheel(_seg_rt->counter_mode_call & 0xFF), _seg->colors[1], false); } @@ -579,7 +640,7 @@ uint16_t WS2812FX::mode_blink_rainbow(void) { * Classic Strobe effect. */ uint16_t WS2812FX::mode_strobe(void) { - return blink(SEGMENT.colors[0], SEGMENT.colors[1], true); + return blink(_seg->colors[0], _seg->colors[1], true); } @@ -587,7 +648,7 @@ uint16_t WS2812FX::mode_strobe(void) { * Classic Strobe effect. Cycling through the rainbow. */ uint16_t WS2812FX::mode_strobe_rainbow(void) { - return blink(color_wheel(SEGMENT_RUNTIME.counter_mode_call & 0xFF), SEGMENT.colors[1], true); + return blink(color_wheel(_seg_rt->counter_mode_call & 0xFF), _seg->colors[1], true); } @@ -597,46 +658,46 @@ uint16_t WS2812FX::mode_strobe_rainbow(void) { * if (bool rev == true) then LEDs are turned off in reverse order */ uint16_t WS2812FX::color_wipe(uint32_t color1, uint32_t color2, bool rev) { - if(SEGMENT_RUNTIME.counter_mode_step < SEGMENT_LENGTH) { - uint32_t led_offset = SEGMENT_RUNTIME.counter_mode_step; + if(_seg_rt->counter_mode_step < _seg_len) { + uint32_t led_offset = _seg_rt->counter_mode_step; if(IS_REVERSE) { - setPixelColor(SEGMENT.stop - led_offset, color1); + setPixelColor(_seg->stop - led_offset, color1); } else { - setPixelColor(SEGMENT.start + led_offset, color1); + setPixelColor(_seg->start + led_offset, color1); } } else { - uint32_t led_offset = SEGMENT_RUNTIME.counter_mode_step - SEGMENT_LENGTH; + uint32_t led_offset = _seg_rt->counter_mode_step - _seg_len; if((IS_REVERSE && !rev) || (!IS_REVERSE && rev)) { - setPixelColor(SEGMENT.stop - led_offset, color2); + setPixelColor(_seg->stop - led_offset, color2); } else { - setPixelColor(SEGMENT.start + led_offset, color2); + setPixelColor(_seg->start + led_offset, color2); } } - if(SEGMENT_RUNTIME.counter_mode_step % SEGMENT_LENGTH == 0) SET_CYCLE; - else CLR_CYCLE; + _seg_rt->counter_mode_step = (_seg_rt->counter_mode_step + 1) % (_seg_len * 2); + + if(_seg_rt->counter_mode_step == 0) SET_CYCLE; - SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % (SEGMENT_LENGTH * 2); - return (SEGMENT.speed / (SEGMENT_LENGTH * 2)); + return (_seg->speed / (_seg_len * 2)); } /* * Lights all LEDs one after another. */ uint16_t WS2812FX::mode_color_wipe(void) { - return color_wipe(SEGMENT.colors[0], SEGMENT.colors[1], false); + return color_wipe(_seg->colors[0], _seg->colors[1], false); } uint16_t WS2812FX::mode_color_wipe_inv(void) { - return color_wipe(SEGMENT.colors[1], SEGMENT.colors[0], false); + return color_wipe(_seg->colors[1], _seg->colors[0], false); } uint16_t WS2812FX::mode_color_wipe_rev(void) { - return color_wipe(SEGMENT.colors[0], SEGMENT.colors[1], true); + return color_wipe(_seg->colors[0], _seg->colors[1], true); } uint16_t WS2812FX::mode_color_wipe_rev_inv(void) { - return color_wipe(SEGMENT.colors[1], SEGMENT.colors[0], true); + return color_wipe(_seg->colors[1], _seg->colors[0], true); } @@ -645,10 +706,10 @@ uint16_t WS2812FX::mode_color_wipe_rev_inv(void) { * Then starts over with another color. */ uint16_t WS2812FX::mode_color_wipe_random(void) { - if(SEGMENT_RUNTIME.counter_mode_step % SEGMENT_LENGTH == 0) { // aux_param will store our random color wheel index - SEGMENT_RUNTIME.aux_param = get_random_wheel_index(SEGMENT_RUNTIME.aux_param); + if(_seg_rt->counter_mode_step % _seg_len == 0) { // aux_param will store our random color wheel index + _seg_rt->aux_param = get_random_wheel_index(_seg_rt->aux_param); } - uint32_t color = color_wheel(SEGMENT_RUNTIME.aux_param); + uint32_t color = color_wheel(_seg_rt->aux_param); return color_wipe(color, color, false) * 2; } @@ -657,10 +718,10 @@ uint16_t WS2812FX::mode_color_wipe_random(void) { * Random color introduced alternating from start and end of strip. */ uint16_t WS2812FX::mode_color_sweep_random(void) { - if(SEGMENT_RUNTIME.counter_mode_step % SEGMENT_LENGTH == 0) { // aux_param will store our random color wheel index - SEGMENT_RUNTIME.aux_param = get_random_wheel_index(SEGMENT_RUNTIME.aux_param); + if(_seg_rt->counter_mode_step % _seg_len == 0) { // aux_param will store our random color wheel index + _seg_rt->aux_param = get_random_wheel_index(_seg_rt->aux_param); } - uint32_t color = color_wheel(SEGMENT_RUNTIME.aux_param); + uint32_t color = color_wheel(_seg_rt->aux_param); return color_wipe(color, color, true) * 2; } @@ -670,13 +731,11 @@ uint16_t WS2812FX::mode_color_sweep_random(void) { * to the next random color. */ uint16_t WS2812FX::mode_random_color(void) { - SEGMENT_RUNTIME.aux_param = get_random_wheel_index(SEGMENT_RUNTIME.aux_param); // aux_param will store our random color wheel index - uint32_t color = color_wheel(SEGMENT_RUNTIME.aux_param); - - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { - setPixelColor(i, color); - } - return (SEGMENT.speed); + _seg_rt->aux_param = get_random_wheel_index(_seg_rt->aux_param); // aux_param will store our random color wheel index + uint32_t color = color_wheel(_seg_rt->aux_param); + fill(color, _seg->start, _seg_len); + SET_CYCLE; + return _seg->speed; } @@ -685,14 +744,15 @@ uint16_t WS2812FX::mode_random_color(void) { * to another random color. */ uint16_t WS2812FX::mode_single_dynamic(void) { - if(SEGMENT_RUNTIME.counter_mode_call == 0) { - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + if(_seg_rt->counter_mode_call == 0) { + for(uint16_t i=_seg->start; i <= _seg->stop; i++) { setPixelColor(i, color_wheel(random8())); } } - setPixelColor(SEGMENT.start + random16(SEGMENT_LENGTH), color_wheel(random8())); - return (SEGMENT.speed); + setPixelColor(_seg->start + random16(_seg_len), color_wheel(random8())); + SET_CYCLE; + return _seg->speed; } @@ -701,10 +761,11 @@ uint16_t WS2812FX::mode_single_dynamic(void) { * to new random colors. */ uint16_t WS2812FX::mode_multi_dynamic(void) { - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + for(uint16_t i=_seg->start; i <= _seg->stop; i++) { setPixelColor(i, color_wheel(random8())); } - return (SEGMENT.speed); + SET_CYCLE; + return _seg->speed; } @@ -713,7 +774,7 @@ uint16_t WS2812FX::mode_multi_dynamic(void) { * Use mode "fade" if you like to have something similar with a different speed. */ uint16_t WS2812FX::mode_breath(void) { - int lum = SEGMENT_RUNTIME.counter_mode_step; + int lum = _seg_rt->counter_mode_step; if(lum > 255) lum = 511 - lum; // lum = 15 -> 255 -> 15 uint16_t delay; @@ -726,17 +787,14 @@ uint16_t WS2812FX::mode_breath(void) { else if(lum <= 150) delay = 11; // 5 else delay = 10; // 4 - uint32_t color = SEGMENT.colors[0]; - uint8_t w = (color >> 24 & 0xFF) * lum / 256; - uint8_t r = (color >> 16 & 0xFF) * lum / 256; - uint8_t g = (color >> 8 & 0xFF) * lum / 256; - uint8_t b = (color & 0xFF) * lum / 256; - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { - setPixelColor(i, r, g, b, w); - } + uint32_t color = color_blend(_seg->colors[1], _seg->colors[0], lum); + fill(color, _seg->start, _seg_len); - SEGMENT_RUNTIME.counter_mode_step += 2; - if(SEGMENT_RUNTIME.counter_mode_step > (512-15)) SEGMENT_RUNTIME.counter_mode_step = 15; + _seg_rt->counter_mode_step += 2; + if(_seg_rt->counter_mode_step > (512-15)) { + _seg_rt->counter_mode_step = 15; + SET_CYCLE; + } return delay; } @@ -745,17 +803,18 @@ uint16_t WS2812FX::mode_breath(void) { * Fades the LEDs between two colors */ uint16_t WS2812FX::mode_fade(void) { - int lum = SEGMENT_RUNTIME.counter_mode_step; + int lum = _seg_rt->counter_mode_step; if(lum > 255) lum = 511 - lum; // lum = 0 -> 255 -> 0 - uint32_t color = color_blend(SEGMENT.colors[0], SEGMENT.colors[1], lum); - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { - setPixelColor(i, color); - } + uint32_t color = color_blend(_seg->colors[1], _seg->colors[0], lum); + fill(color, _seg->start, _seg_len); - SEGMENT_RUNTIME.counter_mode_step += 4; - if(SEGMENT_RUNTIME.counter_mode_step > 511) SEGMENT_RUNTIME.counter_mode_step = 0; - return (SEGMENT.speed / 128); + _seg_rt->counter_mode_step += 4; + if(_seg_rt->counter_mode_step > 511) { + _seg_rt->counter_mode_step = 0; + SET_CYCLE; + } + return (_seg->speed / 128); } @@ -763,27 +822,28 @@ uint16_t WS2812FX::mode_fade(void) { * scan function - runs a block of pixels back and forth. */ uint16_t WS2812FX::scan(uint32_t color1, uint32_t color2, bool dual) { - int8_t dir = SEGMENT_RUNTIME.aux_param ? -1 : 1; + int8_t dir = _seg_rt->aux_param ? -1 : 1; uint8_t size = 1 << SIZE_OPTION; - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { - setPixelColor(i, color2); - } + fill(color2, _seg->start, _seg_len); for(uint8_t i = 0; i < size; i++) { if(IS_REVERSE || dual) { - setPixelColor(SEGMENT.stop - SEGMENT_RUNTIME.counter_mode_step - i, color1); + setPixelColor(_seg->stop - _seg_rt->counter_mode_step - i, color1); } if(!IS_REVERSE || dual) { - setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.counter_mode_step + i, color1); + setPixelColor(_seg->start + _seg_rt->counter_mode_step + i, color1); } } - SEGMENT_RUNTIME.counter_mode_step += dir; - if(SEGMENT_RUNTIME.counter_mode_step == 0) SEGMENT_RUNTIME.aux_param = 0; - if(SEGMENT_RUNTIME.counter_mode_step >= (uint16_t)(SEGMENT_LENGTH - size)) SEGMENT_RUNTIME.aux_param = 1; + _seg_rt->counter_mode_step += dir; + if(_seg_rt->counter_mode_step == 0) { + _seg_rt->aux_param = 0; + SET_CYCLE; + } + if(_seg_rt->counter_mode_step >= (uint16_t)(_seg_len - size)) _seg_rt->aux_param = 1; - return (SEGMENT.speed / (SEGMENT_LENGTH * 2)); + return (_seg->speed / (_seg_len * 2)); } @@ -791,7 +851,7 @@ uint16_t WS2812FX::scan(uint32_t color1, uint32_t color2, bool dual) { * Runs a block of pixels back and forth. */ uint16_t WS2812FX::mode_scan(void) { - return scan(SEGMENT.colors[0], SEGMENT.colors[1], false); + return scan(_seg->colors[0], _seg->colors[1], false); } @@ -799,7 +859,7 @@ uint16_t WS2812FX::mode_scan(void) { * Runs two blocks of pixels back and forth in opposite directions. */ uint16_t WS2812FX::mode_dual_scan(void) { - return scan(SEGMENT.colors[0], SEGMENT.colors[1], true); + return scan(_seg->colors[0], _seg->colors[1], true); } @@ -807,13 +867,14 @@ uint16_t WS2812FX::mode_dual_scan(void) { * Cycles all LEDs at once through a rainbow. */ uint16_t WS2812FX::mode_rainbow(void) { - uint32_t color = color_wheel(SEGMENT_RUNTIME.counter_mode_step); - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { - setPixelColor(i, color); - } + uint32_t color = color_wheel(_seg_rt->counter_mode_step); + fill(color, _seg->start, _seg_len); + + _seg_rt->counter_mode_step = (_seg_rt->counter_mode_step + 1) & 0xFF; + + if(_seg_rt->counter_mode_step == 0) SET_CYCLE; - SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) & 0xFF; - return (SEGMENT.speed / 256); + return (_seg->speed / 256); } @@ -821,13 +882,61 @@ uint16_t WS2812FX::mode_rainbow(void) { * Cycles a rainbow over the entire string of LEDs. */ uint16_t WS2812FX::mode_rainbow_cycle(void) { - for(uint16_t i=0; i < SEGMENT_LENGTH; i++) { - uint32_t color = color_wheel(((i * 256 / SEGMENT_LENGTH) + SEGMENT_RUNTIME.counter_mode_step) & 0xFF); - setPixelColor(SEGMENT.start + i, color); + for(uint16_t i=0; i < _seg_len; i++) { + uint32_t color = color_wheel(((i * 256 / _seg_len) + _seg_rt->counter_mode_step) & 0xFF); + setPixelColor(_seg->start + i, color); + } + + _seg_rt->counter_mode_step = (_seg_rt->counter_mode_step + 1) & 0xFF; + + if(_seg_rt->counter_mode_step == 0) SET_CYCLE; + + return (_seg->speed / 256); +} + + +/* + * Tricolor chase function + */ +uint16_t WS2812FX::tricolor_chase(uint32_t color1, uint32_t color2, uint32_t color3) { + uint8_t sizeCnt = 1 << SIZE_OPTION; + uint8_t sizeCnt2 = sizeCnt + sizeCnt; + uint8_t sizeCnt3 = sizeCnt2 + sizeCnt; + uint16_t index = _seg_rt->counter_mode_step % sizeCnt3; + for(uint16_t i=0; i < _seg_len; i++, index++) { + index = index % sizeCnt3; + + uint32_t color = color3; + if(index < sizeCnt) color = color1; + else if(index < sizeCnt2) color = color2; + + if(IS_REVERSE) { + setPixelColor(_seg->start + i, color); + } else { + setPixelColor(_seg->stop - i, color); + } } - SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) & 0xFF; - return (SEGMENT.speed / 256); + _seg_rt->counter_mode_step++; + if(_seg_rt->counter_mode_step % _seg_len == 0) SET_CYCLE; + + return (_seg->speed / _seg_len); +} + + +/* + * Tricolor chase mode + */ +uint16_t WS2812FX::mode_tricolor_chase(void) { + return tricolor_chase(_seg->colors[0], _seg->colors[1], _seg->colors[2]); +} + + +/* + * Alternating white/red/black pixels running. + */ +uint16_t WS2812FX::mode_circus_combustus(void) { + return tricolor_chase(RED, WHITE, BLACK); } @@ -836,7 +945,7 @@ uint16_t WS2812FX::mode_rainbow_cycle(void) { * Inspired by the Adafruit examples. */ uint16_t WS2812FX::mode_theater_chase(void) { - return tricolor_chase(SEGMENT.colors[0], SEGMENT.colors[1], SEGMENT.colors[1]); + return tricolor_chase(_seg->colors[0], _seg->colors[1], _seg->colors[1]); } @@ -845,9 +954,9 @@ uint16_t WS2812FX::mode_theater_chase(void) { * Inspired by the Adafruit examples. */ uint16_t WS2812FX::mode_theater_chase_rainbow(void) { - SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) & 0xFF; - uint32_t color = color_wheel(SEGMENT_RUNTIME.counter_mode_step); - return tricolor_chase(color, SEGMENT.colors[1], SEGMENT.colors[1]); + _seg_rt->counter_mode_step = (_seg_rt->counter_mode_step + 1) & 0xFF; + uint32_t color = color_wheel(_seg_rt->counter_mode_step); + return tricolor_chase(color, _seg->colors[1], _seg->colors[1]); } @@ -855,23 +964,20 @@ uint16_t WS2812FX::mode_theater_chase_rainbow(void) { * Running lights effect with smooth sine transition. */ uint16_t WS2812FX::mode_running_lights(void) { - uint8_t w = ((SEGMENT.colors[0] >> 24) & 0xFF); - uint8_t r = ((SEGMENT.colors[0] >> 16) & 0xFF); - uint8_t g = ((SEGMENT.colors[0] >> 8) & 0xFF); - uint8_t b = (SEGMENT.colors[0] & 0xFF); - uint8_t size = 1 << SIZE_OPTION; - uint8_t sineIncr = max(1, (256 / SEGMENT_LENGTH) * size); - for(uint16_t i=0; i < SEGMENT_LENGTH; i++) { - int lum = (int)sine8(((i + SEGMENT_RUNTIME.counter_mode_step) * sineIncr)); + uint8_t sineIncr = max(1, (256 / _seg_len) * size); + for(uint16_t i=0; i < _seg_len; i++) { + int lum = (int)sine8(((i + _seg_rt->counter_mode_step) * sineIncr)); + uint32_t color = color_blend(_seg->colors[0], _seg->colors[1], lum); if(IS_REVERSE) { - setPixelColor(SEGMENT.start + i, (r * lum) / 256, (g * lum) / 256, (b * lum) / 256, (w * lum) / 256); + setPixelColor(_seg->start + i, color); } else { - setPixelColor(SEGMENT.stop - i, (r * lum) / 256, (g * lum) / 256, (b * lum) / 256, (w * lum) / 256); + setPixelColor(_seg->stop - i, color); } } - SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % 256; - return (SEGMENT.speed / SEGMENT_LENGTH); + _seg_rt->counter_mode_step = (_seg_rt->counter_mode_step + 1) % 256; + if(_seg_rt->counter_mode_step == 0) SET_CYCLE; + return (_seg->speed / _seg_len); } @@ -879,19 +985,17 @@ uint16_t WS2812FX::mode_running_lights(void) { * twinkle function */ uint16_t WS2812FX::twinkle(uint32_t color1, uint32_t color2) { - if(SEGMENT_RUNTIME.counter_mode_step == 0) { - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { - setPixelColor(i, color2); - } - uint16_t min_leds = max(1, SEGMENT_LENGTH / 5); // make sure, at least one LED is on - uint16_t max_leds = max(1, SEGMENT_LENGTH / 2); // make sure, at least one LED is on - SEGMENT_RUNTIME.counter_mode_step = random(min_leds, max_leds); + if(_seg_rt->counter_mode_step == 0) { + fill(color2, _seg->start, _seg_len); + uint16_t min_leds = (_seg_len / 4) + 1; // make sure, at least one LED is on + _seg_rt->counter_mode_step = random(min_leds, min_leds * 2); + SET_CYCLE; } - setPixelColor(SEGMENT.start + random16(SEGMENT_LENGTH), color1); + setPixelColor(_seg->start + random16(_seg_len), color1); - SEGMENT_RUNTIME.counter_mode_step--; - return (SEGMENT.speed / SEGMENT_LENGTH); + _seg_rt->counter_mode_step--; + return (_seg->speed / _seg_len); } /* @@ -899,7 +1003,7 @@ uint16_t WS2812FX::twinkle(uint32_t color1, uint32_t color2) { * Inspired by www.tweaking4all.com/hardware/arduino/arduino-led-strip-effects/ */ uint16_t WS2812FX::mode_twinkle(void) { - return twinkle(SEGMENT.colors[0], SEGMENT.colors[1]); + return twinkle(_seg->colors[0], _seg->colors[1]); } /* @@ -907,7 +1011,7 @@ uint16_t WS2812FX::mode_twinkle(void) { * Inspired by www.tweaking4all.com/hardware/arduino/arduino-led-strip-effects/ */ uint16_t WS2812FX::mode_twinkle_random(void) { - return twinkle(color_wheel(random8()), SEGMENT.colors[1]); + return twinkle(color_wheel(random8()), _seg->colors[1]); } @@ -915,7 +1019,7 @@ uint16_t WS2812FX::mode_twinkle_random(void) { * fade out functions */ void WS2812FX::fade_out() { - return fade_out(SEGMENT.colors[1]); + return fade_out(_seg->colors[1]); } void WS2812FX::fade_out(uint32_t targetColor) { @@ -932,7 +1036,7 @@ void WS2812FX::fade_out(uint32_t targetColor) { int g2 = (color >> 8) & 0xff; int b2 = color & 0xff; - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + for(uint16_t i=_seg->start; i <= _seg->stop; i++) { color = getPixelColor(i); // current color if(rate == 0) { // old fade-to-black algorithm setPixelColor(i, (color >> 1) & 0x7F7F7F7F); @@ -995,12 +1099,11 @@ uint16_t WS2812FX::twinkle_fade(uint32_t color) { if(random8(3) == 0) { uint8_t size = 1 << SIZE_OPTION; - uint16_t index = SEGMENT.start + random16(SEGMENT_LENGTH - size); - for(uint8_t i=0; istart + random16(_seg_len - size); + fill(color, index, size); + SET_CYCLE; } - return (SEGMENT.speed / 8); + return (_seg->speed / 8); } @@ -1008,7 +1111,7 @@ uint16_t WS2812FX::twinkle_fade(uint32_t color) { * Blink several LEDs on, fading out. */ uint16_t WS2812FX::mode_twinkle_fade(void) { - return twinkle_fade(SEGMENT.colors[0]); + return twinkle_fade(_seg->colors[0]); } @@ -1019,21 +1122,33 @@ uint16_t WS2812FX::mode_twinkle_fade_random(void) { return twinkle_fade(color_wheel(random8())); } +/* + * Sparkle function + * color1 = background color + * color2 = sparkle color + */ +uint16_t WS2812FX::sparkle(uint32_t color1, uint32_t color2) { + if(_seg_rt->counter_mode_step == 0) { + fill(color1, _seg->start, _seg_len); + } + + uint8_t size = 1 << SIZE_OPTION; + fill(color1, _seg->start + _seg_rt->aux_param3, size); + + _seg_rt->aux_param3 = random16(_seg_len - size); // aux_param3 stores the random led index + fill(color2, _seg->start + _seg_rt->aux_param3, size); + + SET_CYCLE; + return (_seg->speed / 32); +} + /* * Blinks one LED at a time. * Inspired by www.tweaking4all.com/hardware/arduino/arduino-led-strip-effects/ */ uint16_t WS2812FX::mode_sparkle(void) { - uint8_t size = 1 << SIZE_OPTION; - for(uint8_t i=0; icolors[1], _seg->colors[0]); } @@ -1042,20 +1157,7 @@ uint16_t WS2812FX::mode_sparkle(void) { * Inspired by www.tweaking4all.com/hardware/arduino/arduino-led-strip-effects/ */ uint16_t WS2812FX::mode_flash_sparkle(void) { - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { - setPixelColor(i, SEGMENT.colors[0]); - } - - if(random8(5) == 0) { - uint8_t size = 1 << SIZE_OPTION; - uint16_t index = SEGMENT.start + random16(SEGMENT_LENGTH - size); - for(uint8_t j=0; jcolors[0], WHITE); } @@ -1064,17 +1166,15 @@ uint16_t WS2812FX::mode_flash_sparkle(void) { * Inspired by www.tweaking4all.com/hardware/arduino/arduino-led-strip-effects/ */ uint16_t WS2812FX::mode_hyper_sparkle(void) { - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { - setPixelColor(i, SEGMENT.colors[0]); - } + fill(_seg->colors[0], _seg->start, _seg_len); - if(random8(5) < 2) { - for(uint16_t i=0; i < max(1, SEGMENT_LENGTH/3); i++) { - setPixelColor(SEGMENT.start + random16(SEGMENT_LENGTH), WHITE); - } - return 20; + uint8_t size = 1 << SIZE_OPTION; + for(uint8_t i=0; i<8; i++) { + fill(WHITE, _seg->start + random16(_seg_len - size), size); } - return SEGMENT.speed; + + SET_CYCLE; + return (_seg->speed / 32); } @@ -1082,23 +1182,21 @@ uint16_t WS2812FX::mode_hyper_sparkle(void) { * Strobe effect with different strobe count and pause, controlled by speed. */ uint16_t WS2812FX::mode_multi_strobe(void) { - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { - setPixelColor(i, BLACK); - } + fill(_seg->colors[1], _seg->start, _seg_len); - uint16_t delay = 200 + ((9 - (SEGMENT.speed % 10)) * 100); - uint16_t count = 2 * ((SEGMENT.speed / 100) + 1); - if(SEGMENT_RUNTIME.counter_mode_step < count) { - if((SEGMENT_RUNTIME.counter_mode_step & 1) == 0) { - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { - setPixelColor(i, SEGMENT.colors[0]); - } + uint16_t delay = 200 + ((9 - (_seg->speed % 10)) * 100); + uint16_t count = 2 * ((_seg->speed / 100) + 1); + if(_seg_rt->counter_mode_step < count) { + if((_seg_rt->counter_mode_step & 1) == 0) { + fill(_seg->colors[0], _seg->start, _seg_len); delay = 20; } else { delay = 50; } } - SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % (count + 1); + + _seg_rt->counter_mode_step = (_seg_rt->counter_mode_step + 1) % (count + 1); + if(_seg_rt->counter_mode_step == 0) SET_CYCLE; return delay; } @@ -1108,29 +1206,27 @@ uint16_t WS2812FX::mode_multi_strobe(void) { * color1 = background color * color2 and color3 = colors of two adjacent leds */ - uint16_t WS2812FX::chase(uint32_t color1, uint32_t color2, uint32_t color3) { uint8_t size = 1 << SIZE_OPTION; for(uint8_t i=0; icounter_mode_step + i) % _seg_len; + uint16_t b = (a + size) % _seg_len; + uint16_t c = (b + size) % _seg_len; if(IS_REVERSE) { - setPixelColor(SEGMENT.stop - a, color1); - setPixelColor(SEGMENT.stop - b, color2); - setPixelColor(SEGMENT.stop - c, color3); + setPixelColor(_seg->stop - a, color1); + setPixelColor(_seg->stop - b, color2); + setPixelColor(_seg->stop - c, color3); } else { - setPixelColor(SEGMENT.start + a, color1); - setPixelColor(SEGMENT.start + b, color2); - setPixelColor(SEGMENT.start + c, color3); + setPixelColor(_seg->start + a, color1); + setPixelColor(_seg->start + b, color2); + setPixelColor(_seg->start + c, color3); } } - if(SEGMENT_RUNTIME.counter_mode_step + (size * 3) == SEGMENT_LENGTH) SET_CYCLE; - else CLR_CYCLE; + if(_seg_rt->counter_mode_step + (size * 3) == _seg_len) SET_CYCLE; - SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % SEGMENT_LENGTH; - return (SEGMENT.speed / SEGMENT_LENGTH); + _seg_rt->counter_mode_step = (_seg_rt->counter_mode_step + 1) % _seg_len; + return (_seg->speed / _seg_len); } @@ -1138,7 +1234,7 @@ uint16_t WS2812FX::chase(uint32_t color1, uint32_t color2, uint32_t color3) { * Bicolor chase mode */ uint16_t WS2812FX::mode_bicolor_chase(void) { - return chase(SEGMENT.colors[0], SEGMENT.colors[1], SEGMENT.colors[2]); + return chase(_seg->colors[0], _seg->colors[1], _seg->colors[2]); } @@ -1146,7 +1242,7 @@ uint16_t WS2812FX::mode_bicolor_chase(void) { * White running on _color. */ uint16_t WS2812FX::mode_chase_color(void) { - return chase(SEGMENT.colors[0], WHITE, WHITE); + return chase(_seg->colors[0], WHITE, WHITE); } @@ -1154,7 +1250,7 @@ uint16_t WS2812FX::mode_chase_color(void) { * Black running on _color. */ uint16_t WS2812FX::mode_chase_blackout(void) { - return chase(SEGMENT.colors[0], BLACK, BLACK); + return chase(_seg->colors[0], BLACK, BLACK); } @@ -1162,7 +1258,7 @@ uint16_t WS2812FX::mode_chase_blackout(void) { * _color running on white. */ uint16_t WS2812FX::mode_chase_white(void) { - return chase(WHITE, SEGMENT.colors[0], SEGMENT.colors[0]); + return chase(WHITE, _seg->colors[0], _seg->colors[0]); } @@ -1170,10 +1266,10 @@ uint16_t WS2812FX::mode_chase_white(void) { * White running followed by random color. */ uint16_t WS2812FX::mode_chase_random(void) { - if(SEGMENT_RUNTIME.counter_mode_step == 0) { - SEGMENT_RUNTIME.aux_param = get_random_wheel_index(SEGMENT_RUNTIME.aux_param); + if(_seg_rt->counter_mode_step == 0) { + _seg_rt->aux_param = get_random_wheel_index(_seg_rt->aux_param); } - return chase(color_wheel(SEGMENT_RUNTIME.aux_param), WHITE, WHITE); + return chase(color_wheel(_seg_rt->aux_param), WHITE, WHITE); } @@ -1181,10 +1277,10 @@ uint16_t WS2812FX::mode_chase_random(void) { * Rainbow running on white. */ uint16_t WS2812FX::mode_chase_rainbow_white(void) { - uint16_t n = SEGMENT_RUNTIME.counter_mode_step; - uint16_t m = (SEGMENT_RUNTIME.counter_mode_step + 1) % SEGMENT_LENGTH; - uint32_t color2 = color_wheel(((n * 256 / SEGMENT_LENGTH) + (SEGMENT_RUNTIME.counter_mode_call & 0xFF)) & 0xFF); - uint32_t color3 = color_wheel(((m * 256 / SEGMENT_LENGTH) + (SEGMENT_RUNTIME.counter_mode_call & 0xFF)) & 0xFF); + uint16_t n = _seg_rt->counter_mode_step; + uint16_t m = (_seg_rt->counter_mode_step + 1) % _seg_len; + uint32_t color2 = color_wheel(((n * 256 / _seg_len) + (_seg_rt->counter_mode_call & 0xFF)) & 0xFF); + uint32_t color3 = color_wheel(((m * 256 / _seg_len) + (_seg_rt->counter_mode_call & 0xFF)) & 0xFF); return chase(WHITE, color2, color3); } @@ -1194,9 +1290,9 @@ uint16_t WS2812FX::mode_chase_rainbow_white(void) { * White running on rainbow. */ uint16_t WS2812FX::mode_chase_rainbow(void) { - uint8_t color_sep = 256 / SEGMENT_LENGTH; - uint8_t color_index = SEGMENT_RUNTIME.counter_mode_call & 0xFF; - uint32_t color = color_wheel(((SEGMENT_RUNTIME.counter_mode_step * color_sep) + color_index) & 0xFF); + uint8_t color_sep = 256 / _seg_len; + uint8_t color_index = _seg_rt->counter_mode_call & 0xFF; + uint32_t color = color_wheel(((_seg_rt->counter_mode_step * color_sep) + color_index) & 0xFF); return chase(color, WHITE, WHITE); } @@ -1206,45 +1302,50 @@ uint16_t WS2812FX::mode_chase_rainbow(void) { * Black running on rainbow. */ uint16_t WS2812FX::mode_chase_blackout_rainbow(void) { - uint8_t color_sep = 256 / SEGMENT_LENGTH; - uint8_t color_index = SEGMENT_RUNTIME.counter_mode_call & 0xFF; - uint32_t color = color_wheel(((SEGMENT_RUNTIME.counter_mode_step * color_sep) + color_index) & 0xFF); + uint8_t color_sep = 256 / _seg_len; + uint8_t color_index = _seg_rt->counter_mode_call & 0xFF; + uint32_t color = color_wheel(((_seg_rt->counter_mode_step * color_sep) + color_index) & 0xFF); return chase(color, BLACK, BLACK); } - /* - * White flashes running on _color. + * running white flashes function. + * color1 = background color + * color2 = flash color */ -uint16_t WS2812FX::mode_chase_flash(void) { +uint16_t WS2812FX::chase_flash(uint32_t color1, uint32_t color2) { const static uint8_t flash_count = 4; - uint8_t flash_step = SEGMENT_RUNTIME.counter_mode_call % ((flash_count * 2) + 1); + uint8_t flash_step = _seg_rt->counter_mode_call % ((flash_count * 2) + 1); - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { - setPixelColor(i, SEGMENT.colors[0]); - } - - uint16_t delay = (SEGMENT.speed / SEGMENT_LENGTH); if(flash_step < (flash_count * 2)) { - if(flash_step % 2 == 0) { - uint16_t n = SEGMENT_RUNTIME.counter_mode_step; - uint16_t m = (SEGMENT_RUNTIME.counter_mode_step + 1) % SEGMENT_LENGTH; - if(IS_REVERSE) { - setPixelColor(SEGMENT.stop - n, WHITE); - setPixelColor(SEGMENT.stop - m, WHITE); - } else { - setPixelColor(SEGMENT.start + n, WHITE); - setPixelColor(SEGMENT.start + m, WHITE); - } - delay = 20; + uint32_t color = (flash_step % 2 == 0) ? color2 : color1; + uint16_t n = _seg_rt->counter_mode_step; + uint16_t m = (_seg_rt->counter_mode_step + 1) % _seg_len; + if(IS_REVERSE) { + setPixelColor(_seg->stop - n, color); + setPixelColor(_seg->stop - m, color); } else { - delay = 30; + setPixelColor(_seg->start + n, color); + setPixelColor(_seg->start + m, color); } + return 30; } else { - SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % SEGMENT_LENGTH; + _seg_rt->counter_mode_step = (_seg_rt->counter_mode_step + 1) % _seg_len; + if(_seg_rt->counter_mode_step == 0) { + // update aux_param so mode_chase_flash_random() will select the next color + _seg_rt->aux_param = get_random_wheel_index(_seg_rt->aux_param); + SET_CYCLE; + } } - return delay; + return (_seg->speed / _seg_len); +} + +/* + * White flashes running on _color. + */ +uint16_t WS2812FX::mode_chase_flash(void) { + return chase_flash(_seg->colors[0], WHITE); } @@ -1252,34 +1353,7 @@ uint16_t WS2812FX::mode_chase_flash(void) { * White flashes running, followed by random color. */ uint16_t WS2812FX::mode_chase_flash_random(void) { - const static uint8_t flash_count = 4; - uint8_t flash_step = SEGMENT_RUNTIME.counter_mode_call % ((flash_count * 2) + 1); - - for(uint16_t i=0; i < SEGMENT_RUNTIME.counter_mode_step; i++) { - setPixelColor(SEGMENT.start + i, color_wheel(SEGMENT_RUNTIME.aux_param)); - } - - uint16_t delay = (SEGMENT.speed / SEGMENT_LENGTH); - if(flash_step < (flash_count * 2)) { - uint16_t n = SEGMENT_RUNTIME.counter_mode_step; - uint16_t m = (SEGMENT_RUNTIME.counter_mode_step + 1) % SEGMENT_LENGTH; - if(flash_step % 2 == 0) { - setPixelColor(SEGMENT.start + n, WHITE); - setPixelColor(SEGMENT.start + m, WHITE); - delay = 20; - } else { - setPixelColor(SEGMENT.start + n, color_wheel(SEGMENT_RUNTIME.aux_param)); - setPixelColor(SEGMENT.start + m, BLACK); - delay = 30; - } - } else { - SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % SEGMENT_LENGTH; - - if(SEGMENT_RUNTIME.counter_mode_step == 0) { - SEGMENT_RUNTIME.aux_param = get_random_wheel_index(SEGMENT_RUNTIME.aux_param); - } - } - return delay; + return chase_flash(color_wheel(_seg_rt->aux_param), WHITE); } @@ -1287,32 +1361,28 @@ uint16_t WS2812FX::mode_chase_flash_random(void) { * Alternating pixels running function. */ uint16_t WS2812FX::running(uint32_t color1, uint32_t color2) { - uint8_t size = 4 << SIZE_OPTION; - for(uint16_t i=0; i < SEGMENT_LENGTH; i++) { - if((i + SEGMENT_RUNTIME.counter_mode_step) % size < (size / 2)) { - if(IS_REVERSE) { - setPixelColor(SEGMENT.start + i, color1); - } else { - setPixelColor(SEGMENT.stop - i, color1); - } - } else { - if(IS_REVERSE) { - setPixelColor(SEGMENT.start + i, color2); - } else { - setPixelColor(SEGMENT.stop - i, color2); - } - } + uint8_t size = 2 << SIZE_OPTION; + uint32_t color = (_seg_rt->counter_mode_step & size) ? color1 : color2; + + if(IS_REVERSE) { + copyPixels(_seg->start, _seg->start + 1, _seg_len - 1); + setPixelColor(_seg->stop, color); + } else { + copyPixels(_seg->start + 1, _seg->start, _seg_len - 1); + setPixelColor(_seg->start, color); } - SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % size; - return (SEGMENT.speed / SEGMENT_LENGTH); + _seg_rt->counter_mode_step = (_seg_rt->counter_mode_step + 1) % _seg_len; + if(_seg_rt->counter_mode_step == 0) SET_CYCLE; + return (_seg->speed / _seg_len); } + /* * Alternating color/white pixels running. */ uint16_t WS2812FX::mode_running_color(void) { - return running(SEGMENT.colors[0], WHITE); + return running(_seg->colors[0], _seg->colors[1]); } @@ -1343,23 +1413,14 @@ uint16_t WS2812FX::mode_halloween(void) { * Random colored pixels running. */ uint16_t WS2812FX::mode_running_random(void) { - if(IS_REVERSE) { - copyPixels(SEGMENT.start, SEGMENT.start + 1, SEGMENT_LENGTH - 1); - } else { - copyPixels(SEGMENT.start + 1, SEGMENT.start, SEGMENT_LENGTH - 1); + uint8_t size = 2 << SIZE_OPTION; + if((_seg_rt->counter_mode_step) % size == 0) { + _seg_rt->aux_param = get_random_wheel_index(_seg_rt->aux_param); } - if(SEGMENT_RUNTIME.counter_mode_step == 0) { - SEGMENT_RUNTIME.aux_param = get_random_wheel_index(SEGMENT_RUNTIME.aux_param); - if(IS_REVERSE) { - setPixelColor(SEGMENT.stop, color_wheel(SEGMENT_RUNTIME.aux_param)); - } else { - setPixelColor(SEGMENT.start, color_wheel(SEGMENT_RUNTIME.aux_param)); - } - } + uint32_t color = color_wheel(_seg_rt->aux_param); - SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % (2 << SIZE_OPTION); - return (SEGMENT.speed / SEGMENT_LENGTH); + return running(color, color); } @@ -1369,30 +1430,28 @@ uint16_t WS2812FX::mode_running_random(void) { uint16_t WS2812FX::mode_larson_scanner(void) { fade_out(); - if(SEGMENT_RUNTIME.counter_mode_step < SEGMENT_LENGTH) { + if(_seg_rt->counter_mode_step < _seg_len) { if(IS_REVERSE) { - setPixelColor(SEGMENT.stop - SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + setPixelColor(_seg->stop - _seg_rt->counter_mode_step, _seg->colors[0]); } else { - setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + setPixelColor(_seg->start + _seg_rt->counter_mode_step, _seg->colors[0]); } } else { - uint16_t index = (SEGMENT_LENGTH * 2) - SEGMENT_RUNTIME.counter_mode_step - 2; + uint16_t index = (_seg_len * 2) - _seg_rt->counter_mode_step - 2; if(IS_REVERSE) { - setPixelColor(SEGMENT.stop - index, SEGMENT.colors[0]); + setPixelColor(_seg->stop - index, _seg->colors[0]); } else { - setPixelColor(SEGMENT.start + index, SEGMENT.colors[0]); + setPixelColor(_seg->start + index, _seg->colors[0]); } } - if(SEGMENT_RUNTIME.counter_mode_step % SEGMENT_LENGTH == 0) SET_CYCLE; - else CLR_CYCLE; - - SEGMENT_RUNTIME.counter_mode_step++; - if(SEGMENT_RUNTIME.counter_mode_step >= (uint16_t)((SEGMENT_LENGTH * 2) - 2)) { - SEGMENT_RUNTIME.counter_mode_step = 0; + _seg_rt->counter_mode_step++; + if(_seg_rt->counter_mode_step >= (uint16_t)((_seg_len * 2) - 2)) { + _seg_rt->counter_mode_step = 0; + SET_CYCLE; } - return (SEGMENT.speed / (SEGMENT_LENGTH * 2)); + return (_seg->speed / (_seg_len * 2)); } @@ -1403,13 +1462,15 @@ uint16_t WS2812FX::mode_comet(void) { fade_out(); if(IS_REVERSE) { - setPixelColor(SEGMENT.stop - SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + setPixelColor(_seg->stop - _seg_rt->counter_mode_step, _seg->colors[0]); } else { - setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.counter_mode_step, SEGMENT.colors[0]); + setPixelColor(_seg->start + _seg_rt->counter_mode_step, _seg->colors[0]); } - SEGMENT_RUNTIME.counter_mode_step = (SEGMENT_RUNTIME.counter_mode_step + 1) % SEGMENT_LENGTH; - return (SEGMENT.speed / SEGMENT_LENGTH); + _seg_rt->counter_mode_step = (_seg_rt->counter_mode_step + 1) % _seg_len; + if(_seg_rt->counter_mode_step == 0) SET_CYCLE; + + return (_seg->speed / _seg_len); } @@ -1422,8 +1483,8 @@ uint16_t WS2812FX::fireworks(uint32_t color) { // for better performance, manipulate the Adafruit_NeoPixels pixels[] array directly uint8_t *pixels = getPixels(); uint8_t bytesPerPixel = getNumBytesPerPixel(); // 3=RGB, 4=RGBW - uint16_t startPixel = SEGMENT.start * bytesPerPixel + bytesPerPixel; - uint16_t stopPixel = SEGMENT.stop * bytesPerPixel ; + uint16_t startPixel = _seg->start * bytesPerPixel + bytesPerPixel; + uint16_t stopPixel = _seg->stop * bytesPerPixel ; for(uint16_t i=startPixel; i > 2) + pixels[i] + @@ -1433,23 +1494,22 @@ uint16_t WS2812FX::fireworks(uint32_t color) { uint8_t size = 2 << SIZE_OPTION; if(!_triggered) { - for(uint16_t i=0; istart + random16(_seg_len - size); + fill(color, index, size); + SET_CYCLE; } } } else { - for(uint16_t i=0; istart + random16(_seg_len - size); + fill(color, index, size); + SET_CYCLE; } } - return (SEGMENT.speed / SEGMENT_LENGTH); + + return (_seg->speed / _seg_len); } /* @@ -1458,7 +1518,7 @@ uint16_t WS2812FX::fireworks(uint32_t color) { uint16_t WS2812FX::mode_fireworks(void) { uint32_t color = BLACK; do { // randomly choose a non-BLACK color from the colors array - color = SEGMENT.colors[random8(NUM_COLORS)]; + color = _seg->colors[random8(MAX_NUM_COLORS)]; } while (color == BLACK); return fireworks(color); } @@ -1475,16 +1535,18 @@ uint16_t WS2812FX::mode_fireworks_random(void) { * Fire flicker function */ uint16_t WS2812FX::fire_flicker(int rev_intensity) { - byte w = (SEGMENT.colors[0] >> 24) & 0xFF; - byte r = (SEGMENT.colors[0] >> 16) & 0xFF; - byte g = (SEGMENT.colors[0] >> 8) & 0xFF; - byte b = (SEGMENT.colors[0] & 0xFF); + byte w = (_seg->colors[0] >> 24) & 0xFF; + byte r = (_seg->colors[0] >> 16) & 0xFF; + byte g = (_seg->colors[0] >> 8) & 0xFF; + byte b = (_seg->colors[0] & 0xFF); byte lum = max(w, max(r, max(g, b))) / rev_intensity; - for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) { + for(uint16_t i=_seg->start; i <= _seg->stop; i++) { int flicker = random8(lum); setPixelColor(i, max(r - flicker, 0), max(g - flicker, 0), max(b - flicker, 0), max(w - flicker, 0)); } - return (SEGMENT.speed / SEGMENT_LENGTH); + + SET_CYCLE; + return (_seg->speed / _seg_len); } /* @@ -1505,83 +1567,45 @@ uint16_t WS2812FX::mode_fire_flicker_soft(void) { * Random flickering, more intensity. */ uint16_t WS2812FX::mode_fire_flicker_intense(void) { - return fire_flicker(1.7); -} - - -/* - * Tricolor chase function - */ -uint16_t WS2812FX::tricolor_chase(uint32_t color1, uint32_t color2, uint32_t color3) { - uint8_t sizeCnt = 1 << SIZE_OPTION; - uint16_t index = SEGMENT_RUNTIME.counter_mode_call % (sizeCnt * 3); - for(uint16_t i=0; i < SEGMENT_LENGTH; i++, index++) { - index = index % (sizeCnt * 3); - - uint32_t color = color3; - if(index < sizeCnt) color = color1; - else if(index < (sizeCnt * 2)) color = color2; - - if(IS_REVERSE) { - setPixelColor(SEGMENT.start + i, color); - } else { - setPixelColor(SEGMENT.stop - i, color); - } - } - - return (SEGMENT.speed / SEGMENT_LENGTH); -} - - -/* - * Tricolor chase mode - */ -uint16_t WS2812FX::mode_tricolor_chase(void) { - return tricolor_chase(SEGMENT.colors[0], SEGMENT.colors[1], SEGMENT.colors[2]); + return fire_flicker(1); } -/* - * Alternating white/red/black pixels running. - */ -uint16_t WS2812FX::mode_circus_combustus(void) { - return tricolor_chase(RED, WHITE, BLACK); -} - /* * ICU mode */ uint16_t WS2812FX::mode_icu(void) { - uint16_t dest = SEGMENT_RUNTIME.counter_mode_step & 0xFFFF; + uint16_t dest = _seg_rt->counter_mode_step & 0xFFFF; - setPixelColor(SEGMENT.start + dest, SEGMENT.colors[0]); - setPixelColor(SEGMENT.start + dest + SEGMENT_LENGTH/2, SEGMENT.colors[0]); + setPixelColor(_seg->start + dest, _seg->colors[0]); + setPixelColor(_seg->start + dest + _seg_len/2, _seg->colors[0]); - if(SEGMENT_RUNTIME.aux_param3 == dest) { // pause between eye movements + if(_seg_rt->aux_param3 == dest) { // pause between eye movements if(random8(6) == 0) { // blink once in a while - setPixelColor(SEGMENT.start + dest, BLACK); - setPixelColor(SEGMENT.start + dest + SEGMENT_LENGTH/2, BLACK); + setPixelColor(_seg->start + dest, BLACK); + setPixelColor(_seg->start + dest + _seg_len/2, BLACK); return 200; } - SEGMENT_RUNTIME.aux_param3 = random16(SEGMENT_LENGTH/2); + _seg_rt->aux_param3 = random16(_seg_len/2); + SET_CYCLE; return 1000 + random16(2000); } - setPixelColor(SEGMENT.start + dest, BLACK); - setPixelColor(SEGMENT.start + dest + SEGMENT_LENGTH/2, BLACK); + setPixelColor(_seg->start + dest, BLACK); + setPixelColor(_seg->start + dest + _seg_len/2, BLACK); - if(SEGMENT_RUNTIME.aux_param3 > SEGMENT_RUNTIME.counter_mode_step) { - SEGMENT_RUNTIME.counter_mode_step++; + if(_seg_rt->aux_param3 > _seg_rt->counter_mode_step) { + _seg_rt->counter_mode_step++; dest++; - } else if (SEGMENT_RUNTIME.aux_param3 < SEGMENT_RUNTIME.counter_mode_step) { - SEGMENT_RUNTIME.counter_mode_step--; + } else if (_seg_rt->aux_param3 < _seg_rt->counter_mode_step) { + _seg_rt->counter_mode_step--; dest--; } - setPixelColor(SEGMENT.start + dest, SEGMENT.colors[0]); - setPixelColor(SEGMENT.start + dest + SEGMENT_LENGTH/2, SEGMENT.colors[0]); + setPixelColor(_seg->start + dest, _seg->colors[0]); + setPixelColor(_seg->start + dest + _seg_len/2, _seg->colors[0]); - return (SEGMENT.speed / SEGMENT_LENGTH); + return (_seg->speed / _seg_len); } /* @@ -1616,7 +1640,7 @@ uint16_t WS2812FX::mode_custom_8() { } uint16_t WS2812FX::mode_custom_9() { return customModes[9](); -} +} /* * Custom mode helpers */ diff --git a/Arduino/McLighting/WS2812FX.h b/Arduino/McLighting/WS2812FX.h index 5405457b..975681d7 100644 --- a/Arduino/McLighting/WS2812FX.h +++ b/Arduino/McLighting/WS2812FX.h @@ -45,6 +45,8 @@ #define DEFAULT_MODE (uint8_t)0 #define DEFAULT_SPEED (uint16_t)1000 #define DEFAULT_COLOR (uint32_t)0xFF0000 +#define DEFAULT_COLORS { RED, GREEN, BLUE } +#define COLORS(...) (const uint32_t[]){__VA_ARGS__} #if defined(ESP8266) || defined(ESP32) //#pragma message("Compiling for ESP") @@ -58,14 +60,13 @@ #define BRIGHTNESS_MIN (uint8_t)0 #define BRIGHTNESS_MAX (uint8_t)255 -/* each segment uses 36 bytes of SRAM memory, so if you're application fails because of - insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ -#define MAX_NUM_SEGMENTS 10 -#define NUM_COLORS 3 /* number of colors per segment */ -#define MAX_CUSTOM_MODES 10 -#define SEGMENT _segments[_segment_index] -#define SEGMENT_RUNTIME _segment_runtimes[_segment_index] -#define SEGMENT_LENGTH (uint16_t)(SEGMENT.stop - SEGMENT.start + 1) +/* each segment uses 36 bytes of SRAM memory, so if you're compile fails + because of insufficient flash memory, decreasing MAX_NUM_SEGMENTS may help */ +#define MAX_NUM_SEGMENTS 10 +#define MAX_NUM_ACTIVE_SEGMENTS 10 +#define INACTIVE_SEGMENT 255 /* max uint_8 */ +#define MAX_NUM_COLORS 3 /* number of colors per segment */ +#define MAX_CUSTOM_MODES 10 // some common colors #define RED (uint32_t)0xFF0000 @@ -79,8 +80,11 @@ #define PURPLE (uint32_t)0x400080 #define ORANGE (uint32_t)0xFF3000 #define PINK (uint32_t)0xFF1493 +#define GRAY (uint32_t)0x101010 #define ULTRAWHITE (uint32_t)0xFFFFFFFF -#define DARK(c) (uint32_t)((c >> 4) & 0x0f0f0f0f) +#define DIM(c) (uint32_t)((c >> 2) & 0x3f3f3f3f) // color at 25% intensity +#define DARK(c) (uint32_t)((c >> 4) & 0x0f0f0f0f) // color at 6% intensity + // segment options // bit 7: reverse animation @@ -90,7 +94,7 @@ // bits 0: TBD #define NO_OPTIONS (uint8_t)B00000000 #define REVERSE (uint8_t)B10000000 -#define IS_REVERSE ((SEGMENT.options & REVERSE) == REVERSE) +#define IS_REVERSE ((_seg->options & REVERSE) == REVERSE) #define FADE_XFAST (uint8_t)B00010000 #define FADE_FAST (uint8_t)B00100000 #define FADE_MEDIUM (uint8_t)B00110000 @@ -98,22 +102,23 @@ #define FADE_XSLOW (uint8_t)B01010000 #define FADE_XXSLOW (uint8_t)B01100000 #define FADE_GLACIAL (uint8_t)B01110000 -#define FADE_RATE ((SEGMENT.options >> 4) & 7) +#define FADE_RATE ((_seg->options >> 4) & 7) #define GAMMA (uint8_t)B00001000 -#define IS_GAMMA ((SEGMENT.options & GAMMA) == GAMMA) +#define IS_GAMMA ((_seg->options & GAMMA) == GAMMA) #define SIZE_SMALL (uint8_t)B00000000 #define SIZE_MEDIUM (uint8_t)B00000010 #define SIZE_LARGE (uint8_t)B00000100 #define SIZE_XLARGE (uint8_t)B00000110 -#define SIZE_OPTION ((SEGMENT.options >> 1) & 3) +#define SIZE_OPTION ((_seg->options >> 1) & 3) // segment runtime options (aux_param2) -#define FRAME (uint8_t)B10000000 -#define SET_FRAME (SEGMENT_RUNTIME.aux_param2 |= FRAME) -#define CLR_FRAME (SEGMENT_RUNTIME.aux_param2 &= ~FRAME) -#define CYCLE (uint8_t)B01000000 -#define SET_CYCLE (SEGMENT_RUNTIME.aux_param2 |= CYCLE) -#define CLR_CYCLE (SEGMENT_RUNTIME.aux_param2 &= ~CYCLE) +#define FRAME (uint8_t)B10000000 +#define SET_FRAME (_seg_rt->aux_param2 |= FRAME) +#define CLR_FRAME (_seg_rt->aux_param2 &= ~FRAME) +#define CYCLE (uint8_t)B01000000 +#define SET_CYCLE (_seg_rt->aux_param2 |= CYCLE) +#define CLR_CYCLE (_seg_rt->aux_param2 &= ~CYCLE) +#define CLR_FRAME_CYCLE (_seg_rt->aux_param2 &= ~(FRAME | CYCLE)) #define MODE_COUNT (sizeof(_names)/sizeof(_names[0])) @@ -172,7 +177,7 @@ #define FX_MODE_HALLOWEEN 52 #define FX_MODE_BICOLOR_CHASE 53 #define FX_MODE_TRICOLOR_CHASE 54 -#define FX_MODE_ICU 55 +#define FX_MODE_ICU 55 #define FX_MODE_CUSTOM 56 // keep this for backward compatiblity #define FX_MODE_CUSTOM_0 56 // custom modes need to go at the end #define FX_MODE_CUSTOM_1 57 @@ -183,10 +188,11 @@ #define FX_MODE_CUSTOM_6 62 #define FX_MODE_CUSTOM_7 63 #define FX_MODE_CUSTOM_8 64 -#define FX_MODE_CUSTOM_9 65 +#define FX_MODE_CUSTOM_9 65 -// create GLOBAL names to allow WS2812FX to compile with sketches and other libs that store strings -// in PROGMEM (get rid of the "section type conflict with __c" errors once and for all. Amen.) +// create GLOBAL names to allow WS2812FX to compile with sketches and other libs +// that store strings in PROGMEM (get rid of the "section type conflict with __c" +// errors once and for all. Amen.) const char name_0[] PROGMEM = "Static"; const char name_1[] PROGMEM = "Blink"; const char name_2[] PROGMEM = "Breath"; @@ -320,25 +326,25 @@ static const __FlashStringHelper* _names[] = { FSH(name_62), FSH(name_63), FSH(name_64), - FSH(name_65) + FSH(name_65) }; class WS2812FX : public Adafruit_NeoPixel { - typedef uint16_t (WS2812FX::*mode_ptr)(void); - - // segment parameters public: + typedef uint16_t (WS2812FX::*mode_ptr)(void); + + // segment parameters typedef struct Segment { // 20 bytes uint16_t start; uint16_t stop; uint16_t speed; uint8_t mode; uint8_t options; - uint32_t colors[NUM_COLORS]; + uint32_t colors[MAX_NUM_COLORS]; } segment; - // segment runtime parameters + // segment runtime parameters typedef struct Segment_runtime { // 16 bytes unsigned long next_time; uint32_t counter_mode_step; @@ -348,91 +354,28 @@ class WS2812FX : public Adafruit_NeoPixel { uint16_t aux_param3; // auxilary param (usually stores a segment index) } segment_runtime; - WS2812FX(uint16_t n, uint8_t p, neoPixelType t) : Adafruit_NeoPixel(n, p, t) { - _mode[FX_MODE_STATIC] = &WS2812FX::mode_static; - _mode[FX_MODE_BLINK] = &WS2812FX::mode_blink; - _mode[FX_MODE_COLOR_WIPE] = &WS2812FX::mode_color_wipe; - _mode[FX_MODE_COLOR_WIPE_INV] = &WS2812FX::mode_color_wipe_inv; - _mode[FX_MODE_COLOR_WIPE_REV] = &WS2812FX::mode_color_wipe_rev; - _mode[FX_MODE_COLOR_WIPE_REV_INV] = &WS2812FX::mode_color_wipe_rev_inv; - _mode[FX_MODE_COLOR_WIPE_RANDOM] = &WS2812FX::mode_color_wipe_random; - _mode[FX_MODE_RANDOM_COLOR] = &WS2812FX::mode_random_color; - _mode[FX_MODE_SINGLE_DYNAMIC] = &WS2812FX::mode_single_dynamic; - _mode[FX_MODE_MULTI_DYNAMIC] = &WS2812FX::mode_multi_dynamic; - _mode[FX_MODE_RAINBOW] = &WS2812FX::mode_rainbow; - _mode[FX_MODE_RAINBOW_CYCLE] = &WS2812FX::mode_rainbow_cycle; - _mode[FX_MODE_SCAN] = &WS2812FX::mode_scan; - _mode[FX_MODE_DUAL_SCAN] = &WS2812FX::mode_dual_scan; - _mode[FX_MODE_FADE] = &WS2812FX::mode_fade; - _mode[FX_MODE_THEATER_CHASE] = &WS2812FX::mode_theater_chase; - _mode[FX_MODE_THEATER_CHASE_RAINBOW] = &WS2812FX::mode_theater_chase_rainbow; - _mode[FX_MODE_TWINKLE] = &WS2812FX::mode_twinkle; - _mode[FX_MODE_TWINKLE_RANDOM] = &WS2812FX::mode_twinkle_random; - _mode[FX_MODE_TWINKLE_FADE] = &WS2812FX::mode_twinkle_fade; - _mode[FX_MODE_TWINKLE_FADE_RANDOM] = &WS2812FX::mode_twinkle_fade_random; - _mode[FX_MODE_SPARKLE] = &WS2812FX::mode_sparkle; - _mode[FX_MODE_FLASH_SPARKLE] = &WS2812FX::mode_flash_sparkle; - _mode[FX_MODE_HYPER_SPARKLE] = &WS2812FX::mode_hyper_sparkle; - _mode[FX_MODE_STROBE] = &WS2812FX::mode_strobe; - _mode[FX_MODE_STROBE_RAINBOW] = &WS2812FX::mode_strobe_rainbow; - _mode[FX_MODE_MULTI_STROBE] = &WS2812FX::mode_multi_strobe; - _mode[FX_MODE_BLINK_RAINBOW] = &WS2812FX::mode_blink_rainbow; - _mode[FX_MODE_CHASE_WHITE] = &WS2812FX::mode_chase_white; - _mode[FX_MODE_CHASE_COLOR] = &WS2812FX::mode_chase_color; - _mode[FX_MODE_CHASE_RANDOM] = &WS2812FX::mode_chase_random; - _mode[FX_MODE_CHASE_RAINBOW] = &WS2812FX::mode_chase_rainbow; - _mode[FX_MODE_CHASE_FLASH] = &WS2812FX::mode_chase_flash; - _mode[FX_MODE_CHASE_FLASH_RANDOM] = &WS2812FX::mode_chase_flash_random; - _mode[FX_MODE_CHASE_RAINBOW_WHITE] = &WS2812FX::mode_chase_rainbow_white; - _mode[FX_MODE_CHASE_BLACKOUT] = &WS2812FX::mode_chase_blackout; - _mode[FX_MODE_CHASE_BLACKOUT_RAINBOW] = &WS2812FX::mode_chase_blackout_rainbow; - _mode[FX_MODE_COLOR_SWEEP_RANDOM] = &WS2812FX::mode_color_sweep_random; - _mode[FX_MODE_RUNNING_COLOR] = &WS2812FX::mode_running_color; - _mode[FX_MODE_RUNNING_RED_BLUE] = &WS2812FX::mode_running_red_blue; - _mode[FX_MODE_RUNNING_RANDOM] = &WS2812FX::mode_running_random; - _mode[FX_MODE_LARSON_SCANNER] = &WS2812FX::mode_larson_scanner; - _mode[FX_MODE_COMET] = &WS2812FX::mode_comet; - _mode[FX_MODE_FIREWORKS] = &WS2812FX::mode_fireworks; - _mode[FX_MODE_FIREWORKS_RANDOM] = &WS2812FX::mode_fireworks_random; - _mode[FX_MODE_MERRY_CHRISTMAS] = &WS2812FX::mode_merry_christmas; - _mode[FX_MODE_FIRE_FLICKER] = &WS2812FX::mode_fire_flicker; - _mode[FX_MODE_FIRE_FLICKER_SOFT] = &WS2812FX::mode_fire_flicker_soft; - _mode[FX_MODE_FIRE_FLICKER_INTENSE] = &WS2812FX::mode_fire_flicker_intense; - _mode[FX_MODE_CIRCUS_COMBUSTUS] = &WS2812FX::mode_circus_combustus; - _mode[FX_MODE_HALLOWEEN] = &WS2812FX::mode_halloween; - _mode[FX_MODE_BICOLOR_CHASE] = &WS2812FX::mode_bicolor_chase; - _mode[FX_MODE_TRICOLOR_CHASE] = &WS2812FX::mode_tricolor_chase; -// if flash memory is constrained (I'm looking at you Arduino Nano), replace modes -// that use a lot of flash with mode_static (reduces flash footprint by about 2100 bytes) -#ifdef REDUCED_MODES - _mode[FX_MODE_BREATH] = &WS2812FX::mode_static; - _mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_static; - _mode[FX_MODE_ICU] = &WS2812FX::mode_static; -#else - _mode[FX_MODE_BREATH] = &WS2812FX::mode_breath; - _mode[FX_MODE_RUNNING_LIGHTS] = &WS2812FX::mode_running_lights; - _mode[FX_MODE_ICU] = &WS2812FX::mode_icu; -#endif - _mode[FX_MODE_CUSTOM_0] = &WS2812FX::mode_custom_0; - _mode[FX_MODE_CUSTOM_1] = &WS2812FX::mode_custom_1; - _mode[FX_MODE_CUSTOM_2] = &WS2812FX::mode_custom_2; - _mode[FX_MODE_CUSTOM_3] = &WS2812FX::mode_custom_3; - _mode[FX_MODE_CUSTOM_4] = &WS2812FX::mode_custom_4; - _mode[FX_MODE_CUSTOM_5] = &WS2812FX::mode_custom_5; - _mode[FX_MODE_CUSTOM_6] = &WS2812FX::mode_custom_6; - _mode[FX_MODE_CUSTOM_7] = &WS2812FX::mode_custom_7; - _mode[FX_MODE_CUSTOM_8] = &WS2812FX::mode_custom_8; - _mode[FX_MODE_CUSTOM_9] = &WS2812FX::mode_custom_9; - + WS2812FX(uint16_t num_leds, uint8_t pin, neoPixelType type, + uint8_t max_num_segments=MAX_NUM_SEGMENTS, + uint8_t max_num_active_segments=MAX_NUM_ACTIVE_SEGMENTS) + : Adafruit_NeoPixel(num_leds, pin, type) { + brightness = DEFAULT_BRIGHTNESS + 1; // Adafruit_NeoPixel internally offsets brightness by 1 _running = false; - _num_segments = 1; - _segments[0].mode = DEFAULT_MODE; - _segments[0].colors[0] = DEFAULT_COLOR; - _segments[0].start = 0; - _segments[0].stop = n - 1; - _segments[0].speed = DEFAULT_SPEED; - resetSegmentRuntimes(); + + _segments_len = max_num_segments; + _active_segments_len = max_num_active_segments; + + // create all the segment arrays and init to zeros + _segments = new segment[_segments_len](); + _active_segments = new uint8_t[_active_segments_len](); + _segment_runtimes = new segment_runtime[_active_segments_len](); + + // init segment pointers + _seg = _segments; + _seg_rt = _segment_runtimes; + + resetSegments(); + setSegment(0, 0, num_leds - 1, DEFAULT_MODE, DEFAULT_COLOR, DEFAULT_SPEED, NO_OPTIONS); } void @@ -467,18 +410,25 @@ class WS2812FX : public Adafruit_NeoPixel { increaseLength(uint16_t s), decreaseLength(uint16_t s), trigger(void), + setCycle(void), setNumSegments(uint8_t n), setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, bool reverse), setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, uint8_t options), setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint16_t speed, bool reverse), setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint16_t speed, uint8_t options), - resetSegments(), - resetSegmentRuntimes(), + setIdleSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, uint8_t options), + setIdleSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint16_t speed, uint8_t options), + addActiveSegment(uint8_t seg), + removeActiveSegment(uint8_t seg), + swapActiveSegment(uint8_t oldSeg, uint8_t newSeg), + resetSegments(void), + resetSegmentRuntimes(void), resetSegmentRuntime(uint8_t), setPixelColor(uint16_t n, uint32_t c), setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b), setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w), copyPixels(uint16_t d, uint16_t s, uint16_t c), + setPixels(uint16_t, uint8_t*), show(void); boolean @@ -487,7 +437,8 @@ class WS2812FX : public Adafruit_NeoPixel { isFrame(void), isFrame(uint8_t), isCycle(void), - isCycle(uint8_t); + isCycle(uint8_t), + isActiveSegment(uint8_t seg); uint8_t random8(void), @@ -519,6 +470,7 @@ class WS2812FX : public Adafruit_NeoPixel { uint32_t* getColors(uint8_t); uint32_t* intensitySums(void); + uint8_t* getActiveSegments(void); const __FlashStringHelper* getModeName(uint8_t m); @@ -540,12 +492,15 @@ class WS2812FX : public Adafruit_NeoPixel { color_wipe(uint32_t, uint32_t, bool), twinkle(uint32_t, uint32_t), twinkle_fade(uint32_t), + sparkle(uint32_t, uint32_t), chase(uint32_t, uint32_t, uint32_t), + chase_flash(uint32_t, uint32_t), running(uint32_t, uint32_t), fireworks(uint32_t), fire_flicker(int), tricolor_chase(uint32_t, uint32_t, uint32_t), scan(uint32_t, uint32_t, bool); + uint32_t color_blend(uint32_t, uint32_t, uint8_t); @@ -616,7 +571,8 @@ class WS2812FX : public Adafruit_NeoPixel { mode_custom_6(void), mode_custom_7(void), mode_custom_8(void), - mode_custom_9(void); + mode_custom_9(void); + private: uint16_t _rand16seed; uint16_t (*customModes[MAX_CUSTOM_MODES])(void) { @@ -637,15 +593,89 @@ class WS2812FX : public Adafruit_NeoPixel { _running, _triggered; - mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element + segment* _segments; // array of segments (20 bytes per element) + segment_runtime* _segment_runtimes; // array of segment runtimes (16 bytes per element) + uint8_t* _active_segments; // array of active segments (1 bytes per element) + uint8_t _segments_len = 0; // size of _segments array + uint8_t _active_segments_len = 0; // size of _segments_runtime and _active_segments arrays + uint8_t _num_segments = 0; // number of configured segments in the _segments array uint8_t _segment_index = 0; - uint8_t _num_segments = 1; - segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 20 bytes per element - // start, stop, speed, mode, options, color[] - { 0, 7, DEFAULT_SPEED, FX_MODE_STATIC, NO_OPTIONS, {DEFAULT_COLOR}} - }; - segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 16 bytes per element + + segment* _seg; // currently active segment (20 bytes) + segment_runtime* _seg_rt; // currently active segment runtime (16 bytes) + + uint16_t _seg_len; // num LEDs in the currently active segment }; +// define static array of member function pointers. +// function pointers MUST be in the same order as the corresponding name in the _name array. +static WS2812FX::mode_ptr _modes[MODE_COUNT] = { + &WS2812FX::mode_static, + &WS2812FX::mode_blink, + &WS2812FX::mode_breath, + &WS2812FX::mode_color_wipe, + &WS2812FX::mode_color_wipe_inv, + &WS2812FX::mode_color_wipe_rev, + &WS2812FX::mode_color_wipe_rev_inv, + &WS2812FX::mode_color_wipe_random, + &WS2812FX::mode_random_color, + &WS2812FX::mode_single_dynamic, + &WS2812FX::mode_multi_dynamic, + &WS2812FX::mode_rainbow, + &WS2812FX::mode_rainbow_cycle, + &WS2812FX::mode_scan, + &WS2812FX::mode_dual_scan, + &WS2812FX::mode_fade, + &WS2812FX::mode_theater_chase, + &WS2812FX::mode_theater_chase_rainbow, + &WS2812FX::mode_running_lights, + &WS2812FX::mode_twinkle, + &WS2812FX::mode_twinkle_random, + &WS2812FX::mode_twinkle_fade, + &WS2812FX::mode_twinkle_fade_random, + &WS2812FX::mode_sparkle, + &WS2812FX::mode_flash_sparkle, + &WS2812FX::mode_hyper_sparkle, + &WS2812FX::mode_strobe, + &WS2812FX::mode_strobe_rainbow, + &WS2812FX::mode_multi_strobe, + &WS2812FX::mode_blink_rainbow, + &WS2812FX::mode_chase_white, + &WS2812FX::mode_chase_color, + &WS2812FX::mode_chase_random, + &WS2812FX::mode_chase_rainbow, + &WS2812FX::mode_chase_flash, + &WS2812FX::mode_chase_flash_random, + &WS2812FX::mode_chase_rainbow_white, + &WS2812FX::mode_chase_blackout, + &WS2812FX::mode_chase_blackout_rainbow, + &WS2812FX::mode_color_sweep_random, + &WS2812FX::mode_running_color, + &WS2812FX::mode_running_red_blue, + &WS2812FX::mode_running_random, + &WS2812FX::mode_larson_scanner, + &WS2812FX::mode_comet, + &WS2812FX::mode_fireworks, + &WS2812FX::mode_fireworks_random, + &WS2812FX::mode_merry_christmas, + &WS2812FX::mode_fire_flicker, + &WS2812FX::mode_fire_flicker_soft, + &WS2812FX::mode_fire_flicker_intense, + &WS2812FX::mode_circus_combustus, + &WS2812FX::mode_halloween, + &WS2812FX::mode_bicolor_chase, + &WS2812FX::mode_tricolor_chase, + &WS2812FX::mode_icu, + &WS2812FX::mode_custom_0, + &WS2812FX::mode_custom_1, + &WS2812FX::mode_custom_2, + &WS2812FX::mode_custom_3, + &WS2812FX::mode_custom_4, + &WS2812FX::mode_custom_5, + &WS2812FX::mode_custom_6, + &WS2812FX::mode_custom_7, + &WS2812FX::mode_custom_8, + &WS2812FX::mode_custom_9 +}; #endif diff --git a/Arduino/McLighting/data/index.htm b/Arduino/McLighting/data/index.htm index d601d0c1..7b1c6920 100644 --- a/Arduino/McLighting/data/index.htm +++ b/Arduino/McLighting/data/index.htm @@ -1602,8 +1602,9 @@

warning

else xhr.open("GET", url, true); xhr.send(post); } + function getModes() { - document.getElementById("percentage").innerHTML = "0%"; + document.getElementById("percentage").innerHTML = "0%"; document.getElementById("percentage-done").setAttribute("stroke-dasharray", "0,100"); document.getElementById("modal-content").innerHTML = language.en.loadModes; xhttp("http://" + host + "/get_modes", false, function(e) { @@ -1611,7 +1612,7 @@

warning

if (e && e.substring(0,6) !== "ERROR!") { modes = JSON.parse(e); if (typeof modes[0] !== "undefined") { - modes.forEach(item => { + modes.forEach(item => { if (item.name && item.name.length > 0) { data.modes.push({ title: item.name, id: item.mode }); } @@ -1625,45 +1626,7 @@

warning

}); } -function getConfig() { - document.getElementById("percentage").innerHTML = "75%"; - document.getElementById("percentage-done").setAttribute("stroke-dasharray", "75,100"); - document.getElementById("modal-content").innerHTML = language.en.loadConfig; - xhttp("http://" + host + "/config", false, function(e) { - console.log("Getting config via REST:", e); - if (e && e.substring(0,6) !== "ERROR!") { - var res = JSON.parse(e); - if (res) { - if (typeof res.hostname !== "undefined") config.hostname = res.hostname; - if (typeof res.mqtt_host !== "undefined") config.mqtt_host = res.mqtt_host; - if (typeof res.mqtt_port !== "undefined") config.mqtt_port = res.mqtt_port; - if (typeof res.mqtt_user !== "undefined") config.mqtt_user = res.mqtt_user; - if (typeof res.mqtt_pass !== "undefined") config.mqtt_pass = res.mqtt_pass; - if (typeof res.ws_seg !== "undefined") config.ws_seg = res.ws_seg; - if (typeof res.ws_cnt !== "undefined") config.ws_cnt = res.ws_cnt; - if (typeof res.ws_rgbo !== "undefined") { - config.ws_rgbo = res.ws_rgbo; - config.enable_rgbw = config.ws_rgbo.includes("W"); - } - if (typeof res.ws_pin !== "undefined") config.ws_pin = res.ws_pin; - if (typeof res.ws_trans !== "undefined") config.ws_trans = res.ws_trans; - } - } else { - console.error(e); - document.getElementById("percentage").innerHTML = language.en.error; - showSnackbar(language.en.loadError, "error", 5000); - } - if (config.enable_rgbw) { - document.getElementById("white").parentNode.className = ""; - } else { - document.getElementById("white").parentNode.className = "hidden"; - white.value = 0; - segstate.color.w = 0; - segstate.color.w2 = 0; - segstate.color.w3 = 0; - } - }); -} + function showModes(mode, index) { //console.log("Mode: " + mode.title + " - ID: " + mode.id + " - Hidden: " + mode.hidden); var div = document.createElement("DIV"); @@ -1691,7 +1654,7 @@

warning

document.getElementById("modes").appendChild(div); } function readSettings() { - document.getElementById("percentage").innerHTML = "25%"; + document.getElementById("percentage").innerHTML = "33%"; document.getElementById("percentage-done").setAttribute("stroke-dasharray", "25,100"); document.getElementById("modal-content").innerHTML = language.en.loadSettings; xhttp("http://" + host + "/uistate.json", false, function(e) { @@ -1711,6 +1674,7 @@

warning

} }); } + function applySettings() { // Make sure language contains all the words from English translation. if (settings.lang !== "en") { @@ -1723,6 +1687,7 @@

warning

translate(document.body); document.title = language[settings.lang].title; data.modes.forEach(mode => { + console.log("something"); mode.hidden = false; if (settings.visibility.indexOf(mode.id) > -1) { mode.hidden = true; @@ -2037,8 +2002,6 @@

warning

colmain.dispatchEvent(event); colfont.dispatchEvent(event); colback.dispatchEvent(event); - colbtn.dispatchEvent(event); - colbtns.dispatchEvent(event); document.getElementById("settings-open").addEventListener('click', ()=>{ var icons = document.getElementsByClassName("icon--link"); @@ -2159,7 +2122,7 @@

warning

function ws_connect() { data.connection = new ReconnectingWebSocket(ws_url, "arduino", ws_options); - document.getElementById("percentage").innerHTML = "75%"; + document.getElementById("percentage").innerHTML = "66%"; document.getElementById("percentage-done").setAttribute("stroke-dasharray", "75,100"); document.getElementById("modal-content").innerHTML = language[settings.lang].loadWebsock; @@ -2167,14 +2130,10 @@

warning

data.connection.onopen = function() { console.log("WebSocket open"); data.is_connected = true; - data.refresh_interval = setInterval(() => ws_send("$"), 10000); var con = document.getElementById("disconnected"); con.className = "hidden"; con = document.getElementById("connected"); con.className = con.className = ""; - //setTimeout(function() { ws_send("$"); }, 2000); - //setTimeout(function() { ws_send("C"); }, 3000); - //setTimeout(function() { ws_send("~"); }, 4000); document.getElementById("percentage").innerHTML = "100%"; document.getElementById("percentage-done").setAttribute("stroke-dasharray", "100,100"); document.getElementById("modal-content").innerHTML = language[settings.lang].loadReady; @@ -2205,6 +2164,7 @@

warning

// Log messages from the server data.connection.onmessage = function(e) { console.log("WebSocket from server: ", e.data); + console.log("data.init: ", data.init); try { var res = JSON.parse(e.data); // document.getElementById('modal').style.display = "none"; @@ -2311,10 +2271,9 @@

warning

// init display Colors displayColors(true); console.log("displayColors finished!"); - select_active_button(); - console.log("select_active_button finished!"); + select_active_button(); + console.log("select_active_button finished!"); } - console.log("data.init: ", data.init); if (data.init == true) { console.log("Initializing..."); // Set selected mode button @@ -2323,10 +2282,11 @@

warning

setTimeout(() => { document.getElementById('modal').style.display = "none"; document.getElementById('container').style.display = ""; - }, 500); + }, 50); initSettings(); initcolorSliders(); data.init = false; + data.refresh_interval = setInterval(() => ws_send("$"), 10000); } } catch (e) {} }; @@ -2361,7 +2321,7 @@

warning

function select_active_button() { btns = document.getElementsByClassName("btn"); - for (i = 0; i < btns.length; i++) { + for (i = 0; i < btns.length; i++) { btns[i].style.backgroundColor = settings.theme_btn; } if (state.mode != 1 || (state.mode == 1 && segstate.mode != 57)) { // CUSTOM WS MODE @@ -2374,8 +2334,9 @@

warning

segments.className = segments.className.replace(/\b hidden\b/g, ""); } if (state.mode >= 1) { - document.getElementById(segstate.mode).style.backgroundColor = settings.theme_btnsel; - if (segstate.mode == 56) { // AUTOPLAY + document.getElementById(segstate.mode).style.backgroundColor = settings.theme_btnsel; + document.getElementById("on").style.backgroundColor = settings.theme_btnsel; + if (segstate.mode == 56) { // AUTOPLAY disable_modebuttons(false); disable_color_selection(true); disable_bright_selection(false); @@ -2451,6 +2412,7 @@

warning

} select_active_button(); ws_send("/" + mode_id); + ws_send("$"); } function set_speed() { ws_send("?" + segstate.speed); @@ -2597,7 +2559,7 @@

warning

function drawCircle() { let radius = canvas.width / 2; let image = context.createImageData(2 * radius, 2 * radius); - let data = image.data; + let idata = image.data; for (let x = -radius; x < radius; x++) { for (let y = -radius; y < radius; y++) { @@ -2624,10 +2586,10 @@

warning

let [red, green, blue] = hsv2rgb(hue, saturation, value); let alpha = 255; - data[index] = red; - data[index + 1] = green; - data[index + 2] = blue; - data[index + 3] = alpha; + idata[index] = red; + idata[index + 1] = green; + idata[index + 2] = blue; + idata[index + 3] = alpha; } } this.context.putImageData(image, 0, 0); @@ -2682,14 +2644,16 @@

warning

document.addEventListener("DOMContentLoaded", function(event) { // Code to run since DOM is loaded and ready getModes(); - readSettings(); - ws_connect(); - ws_send("$"); - //ws_send("C"); - getConfig(); - canvas.width = 400; - canvas.height = 400; - redrawColorPicker(); + setTimeout(function() { + readSettings(); + }, 500); + setTimeout(function() { + ws_connect(); + ws_send("$"); + canvas.width = 400; + canvas.height = 400; + redrawColorPicker(); + }, 1000); }); diff --git a/Arduino/McLighting/data/index.htm.gz b/Arduino/McLighting/data/index.htm.gz index c85a8981..c777c419 100644 Binary files a/Arduino/McLighting/data/index.htm.gz and b/Arduino/McLighting/data/index.htm.gz differ diff --git a/Arduino/McLighting/definitions.h b/Arduino/McLighting/definitions.h index 60fdbc3c..cf82f8f0 100644 --- a/Arduino/McLighting/definitions.h +++ b/Arduino/McLighting/definitions.h @@ -19,7 +19,7 @@ char HOSTNAME[65] = "McLightingRGBW"; // Friedly hostname is configurable just //#define ENABLE_MQTT_HOSTNAME_CHIPID // Uncomment/comment to add ESPChipID to end of MQTT hostname //#define ENABLE_MQTT_INCLUDE_IP // uncomment/comment to add the IP-adress to the MQTT message #define ENABLE_HOMEASSISTANT // If defined, enable Homeassistant integration, ENABLE_MQTT must be active -#define MQTT_HOME_ASSISTANT_SUPPORT // If defined, use AMQTT and select Tools -> IwIP Variant -> Higher Bandwidth +#define MQTT_HOMEASSISTANT_SUPPORT // If defined, use AMQTT and select Tools -> IwIP Variant -> Higher Bandwidth #define DELAY_MQTT_HA_MESSAGE 5 // HA Status is send after DELAY_MQTT_HA_MESSAGE seconds, to save bandwith //#define ENABLE_BUTTON 14 // If defined, enable button handling code, see: https://github.com/toblum/McLighting/wiki/Button-control, the value defines the input pin (14 / D5) for switching the LED strip on / off, connect this PIN to ground to trigger button. @@ -74,7 +74,7 @@ uint8_t prevsegment = 0; uint8_t _sn[4] = {255,255,255,0}; #endif -#if defined(MQTT_HOME_ASSISTANT_SUPPORT) +#if defined(MQTT_HOMEASSISTANT_SUPPORT) #define MQTT_HOME_ASSISTANT_0_87_SUPPORT // Comment if using HA version < 0.87 #endif @@ -93,7 +93,7 @@ uint8_t prevsegment = 0; #if defined(ENABLE_HOMEASSISTANT) and !defined(ENABLE_MQTT) #error "To use HA, you have to either enable PubCubClient or AsyncMQTT" #endif -#if !defined(ENABLE_HOMEASSISTANT) and defined(MQTT_HOME_ASSISTANT_SUPPORT) +#if !defined(ENABLE_HOMEASSISTANT) and defined(MQTT_HOMEASSISTANT_SUPPORT) #error "To use HA support, you have to either enable Homeassistant component" #endif diff --git a/Arduino/McLighting/helper_functions.h b/Arduino/McLighting/helper_functions.h index 70a5150c..61eee633 100644 --- a/Arduino/McLighting/helper_functions.h +++ b/Arduino/McLighting/helper_functions.h @@ -321,3 +321,15 @@ uint32_t trans(uint32_t _newcolor, uint32_t _oldcolor, uint8_t _level, uint8_t _ _oldcolor = scale_wrgb(_oldcolor, 255-_level); return _newcolor + _oldcolor; } + +#if defined(ENABLE_MQTT) + void sendmqtt() { + #if ENABLE_MQTT == 0 + mqtt_client->publish(mqtt_outtopic, mqtt_buf); + #endif + #if ENABLE_MQTT == 1 + mqtt_client->publish(mqtt_outtopic, qospub, false, mqtt_buf); + #endif + memset(mqtt_buf,0,sizeof(mqtt_buf)); + } +#endif diff --git a/Arduino/McLighting/htm_index_gz.h b/Arduino/McLighting/htm_index_gz.h index 025b3889..2da4ace5 100644 --- a/Arduino/McLighting/htm_index_gz.h +++ b/Arduino/McLighting/htm_index_gz.h @@ -1,7 +1,7 @@ #include -#define index_htm_gz_len 20878 +#define index_htm_gz_len 20635 static const char index_htm_gz[] PROGMEM ={ - 0x1f, 0x8b, 0x08, 0x08, 0x15, 0xb1, 0x36, 0x5e, 0x04, 0x00, 0x69, 0x6e, + 0x1f, 0x8b, 0x08, 0x08, 0xc8, 0x7c, 0x95, 0x5f, 0x04, 0x00, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x00, 0xe4, 0x5d, 0x59, 0x77, 0x1b, 0x4b, 0x11, 0x7e, 0xe7, 0x1c, 0xfe, 0xc3, 0x5c, 0x05, 0x12, 0x09, 0x24, 0x59, 0x8b, 0x6d, 0x1c, 0x3b, 0xf2, 0x25, 0xc9, 0x75, 0x42, 0x20, @@ -1055,690 +1055,670 @@ static const char index_htm_gz[] PROGMEM ={ 0x29, 0x0d, 0xfd, 0x15, 0xb0, 0x3d, 0x7a, 0x04, 0x1a, 0x71, 0x52, 0xcd, 0x60, 0x36, 0x7f, 0xb1, 0x0c, 0x62, 0xa8, 0x04, 0x4e, 0xe3, 0x14, 0x2c, 0x2c, 0x59, 0x39, 0x9e, 0x0f, 0x06, 0x18, 0xf1, 0xff, 0x55, 0xde, 0x91, - 0x28, 0xb7, 0x52, 0xc3, 0x7e, 0x65, 0x09, 0xc7, 0xdb, 0x40, 0x92, 0x36, - 0xe9, 0x6b, 0x81, 0x17, 0x02, 0x03, 0xe5, 0x01, 0x8f, 0xe1, 0x1a, 0xfa, - 0xb8, 0xa6, 0xd3, 0xe9, 0xe4, 0xd8, 0xa6, 0x0b, 0x69, 0x12, 0x76, 0x37, - 0xb4, 0xa5, 0x94, 0xe1, 0x0f, 0xf9, 0x25, 0x24, 0xd9, 0x5e, 0xdf, 0xbb, - 0xde, 0xd0, 0x70, 0x76, 0xe0, 0x25, 0xb1, 0x25, 0x59, 0x96, 0x65, 0x59, - 0xbe, 0xe4, 0x17, 0x5a, 0x16, 0x32, 0xfc, 0x74, 0xd2, 0xa9, 0x15, 0x4e, - 0x5b, 0x21, 0xff, 0xf4, 0xcb, 0x2f, 0x3f, 0xff, 0xf2, 0x85, 0xc8, 0x7a, - 0x4a, 0x8b, 0x95, 0x67, 0x94, 0x75, 0xaf, 0x2c, 0x66, 0x63, 0x2b, 0xb7, - 0xa9, 0xbd, 0xe8, 0xf2, 0x7f, 0xeb, 0x8b, 0xcf, 0x31, 0xee, 0x4f, 0x44, - 0x1a, 0x50, 0x64, 0xd2, 0xff, 0x26, 0xce, 0x24, 0xd8, 0x87, 0x4f, 0x5d, - 0x50, 0x04, 0x80, 0x4a, 0x4b, 0x64, 0x4d, 0xaf, 0x78, 0x9e, 0x14, 0x14, - 0x2d, 0x55, 0xb6, 0xbd, 0x77, 0xfb, 0x6a, 0x9d, 0x64, 0x53, 0xf8, 0x01, - 0xbe, 0x93, 0xb9, 0x7f, 0xb5, 0xff, 0x72, 0x6b, 0x18, 0x8c, 0xdc, 0x9d, - 0xad, 0x96, 0x48, 0x01, 0xfc, 0xaf, 0x77, 0x8b, 0x22, 0x4b, 0x27, 0x9b, - 0x22, 0xa1, 0x33, 0xfd, 0xab, 0x1f, 0x20, 0x6f, 0x9c, 0x5f, 0x8e, 0xb3, - 0x0c, 0x2f, 0x34, 0x00, 0xd9, 0x4e, 0x1f, 0xce, 0xf7, 0xb4, 0xeb, 0x48, - 0xc3, 0x21, 0x94, 0xf1, 0xa2, 0xcb, 0xd5, 0xc0, 0x60, 0x4d, 0x78, 0x7b, - 0x3d, 0xf0, 0x12, 0xca, 0xc8, 0xb0, 0x8c, 0x20, 0xef, 0x56, 0x2d, 0xfc, - 0xd7, 0x38, 0x50, 0xb7, 0x07, 0x45, 0x9c, 0x5f, 0x21, 0x28, 0xb0, 0xc1, - 0xce, 0xe4, 0xc8, 0x4e, 0x92, 0x90, 0xa4, 0x9c, 0x6f, 0xfb, 0x7d, 0x08, - 0x2e, 0xa5, 0x7c, 0xa4, 0x6c, 0x91, 0x02, 0xb5, 0x9f, 0xd2, 0x31, 0xbc, - 0x78, 0x76, 0xf2, 0xfc, 0x09, 0x50, 0xb2, 0x56, 0x1b, 0x12, 0x54, 0x73, - 0x98, 0x39, 0x6d, 0x26, 0xec, 0x4a, 0x03, 0x2c, 0xa9, 0x1f, 0xb5, 0xa9, - 0x07, 0x70, 0xdd, 0x69, 0x59, 0xaa, 0x4f, 0xa4, 0xa1, 0x62, 0x1f, 0x9f, - 0x7c, 0xfe, 0x59, 0x6f, 0x3d, 0xce, 0xe8, 0x7a, 0xbe, 0xa3, 0x3b, 0xf1, - 0xab, 0x11, 0x57, 0x7c, 0xa7, 0x84, 0x88, 0xca, 0x98, 0x2d, 0x06, 0x5d, - 0xab, 0x80, 0xf2, 0x72, 0x3f, 0x8c, 0x45, 0x57, 0x60, 0x53, 0x9d, 0xd0, - 0xb2, 0x34, 0x02, 0xeb, 0x2d, 0xc7, 0x57, 0x54, 0xa1, 0xf2, 0x07, 0xbf, - 0x5e, 0x24, 0xdf, 0x44, 0xac, 0xf8, 0xa3, 0x15, 0x0f, 0x2a, 0x9b, 0xdd, - 0xb2, 0xba, 0xe3, 0x51, 0x92, 0x25, 0xb5, 0x4e, 0x94, 0xce, 0xd8, 0x4f, - 0x82, 0x43, 0x63, 0xea, 0x27, 0x09, 0x2a, 0xee, 0x4c, 0x6e, 0xdc, 0xd1, - 0x45, 0xfb, 0xf2, 0x20, 0x10, 0xc1, 0x2f, 0x36, 0x4a, 0x7d, 0xf7, 0x6b, - 0x24, 0x23, 0x6a, 0x50, 0xcc, 0x2f, 0x57, 0xd7, 0x27, 0x4b, 0xb0, 0x1f, - 0x93, 0x71, 0x16, 0xab, 0xc0, 0x65, 0xe0, 0xdd, 0x4e, 0x24, 0x8e, 0xc6, - 0xc2, 0x74, 0x77, 0x7f, 0xdf, 0x65, 0x4b, 0x30, 0xcd, 0xea, 0xe7, 0x2c, - 0x6e, 0xf0, 0x9f, 0xea, 0xe8, 0xaf, 0x1f, 0xee, 0xa6, 0xa7, 0xbf, 0x7e, - 0xf8, 0xf0, 0x5d, 0x9d, 0x55, 0xb7, 0xbe, 0xaf, 0x4f, 0x09, 0x6e, 0xbb, - 0x8e, 0xce, 0x70, 0x1f, 0xbc, 0x93, 0x53, 0x38, 0xa7, 0xa0, 0x6e, 0x0e, - 0x50, 0x12, 0xdb, 0x6d, 0x02, 0x00, 0xa4, 0x3c, 0x9b, 0x1c, 0x59, 0x76, - 0x80, 0x57, 0x41, 0x42, 0x8c, 0x34, 0x84, 0x61, 0x2d, 0xe9, 0xf2, 0x48, - 0xad, 0x97, 0xb4, 0x84, 0x18, 0xe9, 0x18, 0x81, 0xc4, 0xd7, 0xab, 0xcc, - 0x4f, 0x5c, 0x42, 0x8c, 0x34, 0x8c, 0x50, 0xe2, 0x78, 0xca, 0xd7, 0x4b, - 0x5c, 0x42, 0x8c, 0x74, 0x8c, 0x40, 0xe2, 0x78, 0x5c, 0xd8, 0x4b, 0x5c, - 0x42, 0x8c, 0x74, 0x8c, 0x7a, 0xe2, 0xec, 0xdc, 0x31, 0xa4, 0xfb, 0x88, - 0x0b, 0x88, 0x91, 0x02, 0x1e, 0x44, 0x76, 0xba, 0x2c, 0xaa, 0xc9, 0x12, - 0xc4, 0x48, 0x82, 0x07, 0xc8, 0x99, 0x9f, 0x82, 0x8e, 0xa2, 0xf0, 0x41, - 0x88, 0x17, 0x27, 0x31, 0x47, 0x2a, 0xa5, 0x61, 0x35, 0x96, 0x72, 0x7a, - 0x1a, 0xf0, 0x74, 0x52, 0x60, 0x31, 0xa6, 0x8b, 0x0d, 0xfa, 0x3b, 0xad, - 0x6f, 0xc8, 0xdc, 0x04, 0x0c, 0x1c, 0x76, 0x75, 0xd6, 0xe9, 0xb2, 0x5a, - 0x4a, 0x04, 0x31, 0x52, 0xc0, 0x83, 0xa4, 0x44, 0x27, 0xc1, 0xbd, 0x64, - 0x25, 0xc4, 0x48, 0x43, 0xf8, 0x5f, 0x8c, 0x68, 0x42, 0x60, 0x76, 0x13, - 0x83, 0x12, 0x05, 0x56, 0x80, 0x66, 0xd6, 0xc0, 0x3b, 0x98, 0x53, 0x48, - 0xc3, 0x33, 0x24, 0xda, 0xa1, 0x8d, 0x16, 0x8e, 0x6c, 0xf5, 0xb3, 0x87, - 0xad, 0xc9, 0xb3, 0x47, 0xaf, 0xd5, 0x42, 0xdc, 0xfb, 0x56, 0xfb, 0x36, - 0x84, 0xb5, 0xf3, 0x13, 0x08, 0x36, 0x08, 0x84, 0x3b, 0x30, 0xe0, 0xee, - 0xdd, 0x4b, 0xe8, 0xd4, 0x92, 0x6c, 0xb6, 0x80, 0x1e, 0x58, 0x27, 0xa2, - 0x07, 0xb0, 0xcb, 0x06, 0xd8, 0xdb, 0xd3, 0xc6, 0x48, 0x04, 0x7c, 0x12, - 0xe1, 0x50, 0x8b, 0xc0, 0x3d, 0x72, 0xe7, 0x70, 0xc0, 0x8d, 0xba, 0xd1, - 0xb3, 0xf7, 0x95, 0x8c, 0x74, 0xc6, 0x53, 0x3f, 0x22, 0x01, 0x29, 0x39, - 0x4c, 0x62, 0x6d, 0xe5, 0x38, 0x10, 0xbe, 0x5c, 0x3e, 0x12, 0x4d, 0x20, - 0xe2, 0x44, 0xf2, 0x56, 0x88, 0x5b, 0xef, 0x3f, 0xfb, 0xba, 0xa5, 0x42, - 0xe7, 0xeb, 0x65, 0x05, 0xf4, 0xc9, 0x17, 0xef, 0x7e, 0xa6, 0x81, 0xa7, - 0xd3, 0x55, 0x05, 0xf8, 0x33, 0x0d, 0x76, 0x52, 0x54, 0x91, 0x7e, 0xef, - 0xab, 0xe7, 0xcf, 0x3f, 0xd7, 0x89, 0x4f, 0x1a, 0x71, 0x5e, 0xdc, 0x14, - 0x36, 0x34, 0x4c, 0x9c, 0x49, 0xad, 0x62, 0x43, 0x9e, 0xb1, 0x21, 0xca, - 0xb6, 0x20, 0x85, 0x85, 0xe2, 0x25, 0xfd, 0x04, 0x4e, 0x3b, 0xe2, 0xb1, - 0xa9, 0x18, 0xc8, 0x2a, 0x59, 0xba, 0x7a, 0x6a, 0x2f, 0xb5, 0x73, 0x20, - 0x48, 0xd3, 0xf0, 0x01, 0xa9, 0xad, 0x64, 0x81, 0xf5, 0x42, 0x54, 0xf1, - 0x06, 0xbc, 0xcc, 0x41, 0x46, 0x46, 0x82, 0x25, 0x99, 0x4c, 0x01, 0xc5, - 0xe0, 0x62, 0x0f, 0xe4, 0x59, 0x9b, 0x38, 0x08, 0x1c, 0x73, 0x0c, 0xdc, - 0xca, 0x91, 0x58, 0x3a, 0x9b, 0xc9, 0x22, 0xf9, 0x89, 0xd6, 0x4a, 0xba, - 0x47, 0x90, 0xa9, 0x16, 0xea, 0x3d, 0xe1, 0x59, 0x2e, 0xf4, 0x97, 0xf7, - 0x90, 0x38, 0x12, 0x34, 0xb8, 0x4e, 0x1c, 0x12, 0x96, 0x90, 0x0a, 0xc4, - 0xe9, 0x6d, 0x7d, 0xf3, 0x35, 0x7a, 0x89, 0xa6, 0xd9, 0xbf, 0x58, 0x51, - 0x56, 0x5a, 0x04, 0xa0, 0xc9, 0x77, 0xf4, 0x4e, 0xd4, 0xa2, 0x5d, 0x93, - 0xf3, 0xc9, 0xea, 0xe6, 0x1c, 0x36, 0xae, 0x80, 0x62, 0xc2, 0xdf, 0xe8, - 0x8f, 0x9e, 0x28, 0x79, 0x0a, 0x59, 0x9f, 0x80, 0x8a, 0xd5, 0x7c, 0xbe, - 0x48, 0x58, 0xa7, 0xa3, 0xc5, 0x14, 0x29, 0x21, 0x54, 0x72, 0xaf, 0x9d, - 0xa1, 0x6c, 0xbd, 0x09, 0xa1, 0x94, 0xd2, 0xcb, 0x36, 0xb4, 0x03, 0x40, - 0x7d, 0x59, 0x93, 0x42, 0xcd, 0xd2, 0xcb, 0xbb, 0x58, 0x24, 0x37, 0xd1, - 0x4d, 0xde, 0x1f, 0x44, 0xf9, 0xd5, 0x51, 0x74, 0x35, 0x7b, 0x1c, 0x2d, - 0xe0, 0x00, 0xc8, 0xcd, 0x62, 0x80, 0x6a, 0x19, 0xfb, 0x85, 0x13, 0xb1, - 0x44, 0x12, 0x46, 0x90, 0xe7, 0x9f, 0xc0, 0x85, 0x46, 0x8d, 0x2b, 0x60, - 0xc5, 0xb4, 0x50, 0x59, 0x52, 0x3e, 0xca, 0xf2, 0xe7, 0x96, 0x34, 0x06, - 0x3b, 0x9a, 0xe9, 0x0c, 0x76, 0x30, 0xd3, 0xe1, 0x15, 0x0e, 0x58, 0xd7, - 0xd8, 0xa4, 0xcc, 0xee, 0x7f, 0x9f, 0xaf, 0x96, 0xcd, 0x66, 0x3c, 0xf8, - 0x28, 0x4c, 0x24, 0xe3, 0xc4, 0x9b, 0x13, 0x9d, 0xe2, 0x6a, 0x2d, 0x2f, - 0x1e, 0x86, 0xcd, 0x79, 0xde, 0xd1, 0x27, 0x37, 0xa0, 0x06, 0x77, 0xf7, - 0xfa, 0x1a, 0xec, 0x97, 0xec, 0xdc, 0x64, 0xf9, 0x50, 0x7f, 0x59, 0xc2, - 0x75, 0x5a, 0x5c, 0xb2, 0xb8, 0xf2, 0x11, 0xc8, 0x3d, 0x97, 0x48, 0x17, - 0xd0, 0xe1, 0x63, 0x7e, 0x0b, 0x12, 0x46, 0xa7, 0x12, 0xa3, 0xed, 0x5a, - 0xbf, 0x7b, 0x41, 0xe4, 0x9a, 0x91, 0x8e, 0x21, 0xbd, 0x4d, 0x5e, 0x17, - 0xe4, 0x6e, 0x12, 0xef, 0xe2, 0x4a, 0xac, 0x54, 0x1a, 0x77, 0x13, 0xcf, - 0xda, 0xb6, 0xeb, 0xa6, 0xe5, 0x83, 0x64, 0x4c, 0x14, 0xb7, 0xa7, 0x43, - 0x81, 0x55, 0x4a, 0x35, 0x7e, 0x80, 0x09, 0x25, 0x5f, 0x78, 0x94, 0x4f, - 0xd5, 0x7e, 0xc6, 0xd6, 0xfc, 0x6a, 0x3d, 0x1e, 0xa1, 0x03, 0xf8, 0x7c, - 0x0e, 0x5f, 0xd0, 0x8c, 0x16, 0xc6, 0xd3, 0xf8, 0x9a, 0x2e, 0xd8, 0xaf, - 0x0a, 0x40, 0x31, 0x01, 0xae, 0x85, 0x51, 0x65, 0xe9, 0x53, 0x44, 0x9f, - 0x8a, 0x73, 0x0d, 0xa5, 0xde, 0x53, 0xd3, 0x8c, 0x53, 0xf0, 0x84, 0xf1, - 0x02, 0x0e, 0x58, 0xf5, 0x08, 0x5f, 0x0d, 0xc9, 0xa3, 0x8b, 0x6c, 0x75, - 0x15, 0x3d, 0x5d, 0xce, 0x61, 0xe1, 0xed, 0x52, 0x3c, 0x1c, 0x84, 0xc4, - 0x7b, 0x72, 0x65, 0x55, 0xdb, 0xf4, 0x65, 0x32, 0x4b, 0x96, 0x28, 0x2f, - 0x5b, 0x87, 0x88, 0x28, 0x28, 0x91, 0xda, 0xdd, 0xdc, 0x7a, 0xa4, 0x00, - 0x98, 0xaa, 0x84, 0x34, 0xdc, 0xba, 0x64, 0x7b, 0x4c, 0x04, 0xeb, 0xd5, - 0x36, 0xef, 0xc6, 0x35, 0xa2, 0x81, 0xea, 0x8d, 0x4c, 0xd5, 0xab, 0x84, - 0xd7, 0xad, 0x08, 0xa5, 0x99, 0xba, 0x28, 0x3f, 0x84, 0x28, 0x93, 0xb8, - 0x34, 0x57, 0x93, 0xd5, 0xec, 0xd6, 0xb4, 0x61, 0xdc, 0x25, 0x19, 0xf9, - 0x4a, 0x66, 0xf9, 0x80, 0x24, 0xd7, 0xfb, 0xb4, 0xb5, 0x46, 0xfc, 0x65, - 0xac, 0x35, 0x6a, 0x83, 0x07, 0x99, 0x2b, 0x81, 0x6f, 0x35, 0xa8, 0xbc, - 0x46, 0xdc, 0x23, 0xb7, 0xf4, 0xf3, 0x8b, 0xd2, 0x9d, 0x80, 0x05, 0xc8, - 0x6e, 0x5f, 0x36, 0x9d, 0x93, 0x76, 0x91, 0x39, 0x5a, 0x87, 0x56, 0xf8, - 0x5f, 0x82, 0x22, 0x68, 0xad, 0x9f, 0xb1, 0xcb, 0xbd, 0xde, 0x0e, 0xe1, - 0xbb, 0x67, 0x2a, 0x86, 0x9f, 0xac, 0xed, 0xfe, 0xd8, 0xcd, 0x2e, 0x25, - 0x61, 0xf4, 0x09, 0xbd, 0x13, 0x69, 0x7b, 0x3d, 0x20, 0xb2, 0xab, 0xf7, - 0x01, 0x8f, 0x6f, 0xf8, 0x7c, 0xc0, 0x7f, 0xc6, 0x9a, 0xc7, 0xb9, 0x58, - 0x4d, 0x78, 0xfe, 0x7b, 0xf0, 0x35, 0x3e, 0x25, 0x73, 0xcb, 0x4c, 0x46, - 0x7a, 0x71, 0x5b, 0x4a, 0xae, 0x7d, 0xd6, 0x89, 0xee, 0xd8, 0x45, 0xeb, - 0x47, 0xd8, 0x0b, 0x53, 0x76, 0x9f, 0x7d, 0x0f, 0xc7, 0x88, 0x47, 0x82, - 0xe7, 0xb2, 0x44, 0x3e, 0x00, 0xc7, 0x8f, 0x04, 0xfa, 0xa3, 0x0e, 0x95, - 0xd4, 0x89, 0x1e, 0x69, 0xa3, 0x0b, 0x9d, 0x4f, 0x70, 0xce, 0x0b, 0x4e, - 0xd8, 0xd5, 0x53, 0x1a, 0x43, 0x04, 0xd5, 0x76, 0xfd, 0xd0, 0x95, 0x80, - 0xe9, 0x52, 0x30, 0x8c, 0x51, 0xeb, 0x21, 0x2c, 0xa4, 0xc2, 0xe2, 0x57, - 0xc7, 0xc7, 0x4f, 0x4f, 0x4e, 0x8c, 0x06, 0x40, 0x3b, 0xd7, 0x91, 0x43, - 0x4a, 0xc8, 0x2c, 0xd7, 0xec, 0x01, 0x34, 0x66, 0x81, 0x17, 0x90, 0xb3, - 0x8d, 0x27, 0xa0, 0x78, 0x40, 0xf3, 0xdd, 0xc6, 0xd6, 0xba, 0xec, 0x42, - 0x20, 0x16, 0xe6, 0x3c, 0x8b, 0xfe, 0x11, 0x6c, 0xd2, 0xd9, 0xfc, 0x9f, - 0x09, 0xc4, 0x51, 0xd3, 0xed, 0xeb, 0x17, 0x38, 0xa5, 0x37, 0x87, 0x00, - 0xdd, 0xcb, 0x4d, 0xd8, 0xb1, 0x22, 0xbb, 0xa3, 0xbe, 0xa0, 0xfc, 0x2c, - 0xb7, 0xc1, 0xbc, 0xfe, 0x78, 0x73, 0x37, 0x1c, 0xbb, 0xce, 0x7a, 0x85, - 0x5e, 0x4c, 0x88, 0x69, 0x51, 0x36, 0xed, 0x54, 0xc6, 0x40, 0xff, 0x90, - 0x88, 0x65, 0x78, 0x9c, 0x34, 0x73, 0xec, 0x73, 0x49, 0x0c, 0xf0, 0x9d, - 0xa8, 0xaf, 0xdf, 0x32, 0x21, 0xc2, 0x36, 0x5d, 0x34, 0xf6, 0x21, 0x94, - 0x71, 0x27, 0xc5, 0x64, 0xf5, 0xde, 0xd9, 0x29, 0xd9, 0xdc, 0x9b, 0x76, - 0x57, 0x72, 0x9a, 0x81, 0xbb, 0xe8, 0xb5, 0xad, 0x63, 0x61, 0xab, 0xe5, - 0x89, 0x78, 0x21, 0x0a, 0x76, 0xbf, 0x61, 0x75, 0x66, 0x01, 0xa7, 0xa0, - 0x4a, 0xb6, 0xcc, 0x53, 0xac, 0x11, 0xcb, 0xe7, 0x8c, 0x68, 0xe5, 0xe7, - 0x44, 0x26, 0x99, 0xf1, 0x48, 0x02, 0xc0, 0x00, 0x07, 0x96, 0x36, 0x33, - 0x3a, 0x01, 0x0d, 0x8c, 0x74, 0x40, 0x7e, 0xd4, 0x51, 0xd9, 0x04, 0x87, - 0x52, 0x1c, 0x3e, 0x75, 0xfe, 0xde, 0xed, 0xb1, 0x98, 0xb3, 0xc4, 0x2d, - 0xc6, 0x12, 0x05, 0x95, 0x38, 0x5f, 0x24, 0x73, 0xb0, 0x47, 0xc2, 0x1f, - 0x97, 0x83, 0x7f, 0x4a, 0x4b, 0x22, 0xf0, 0xf1, 0x56, 0x74, 0xc3, 0xf7, - 0xb1, 0xe0, 0x17, 0xc4, 0xc9, 0x53, 0x65, 0x7e, 0x73, 0x9a, 0x9e, 0xa9, - 0x93, 0x21, 0x4a, 0x70, 0x5f, 0xfc, 0x91, 0xf3, 0xd6, 0x37, 0xf9, 0xe5, - 0x1f, 0x99, 0x72, 0xd0, 0x32, 0x1a, 0x07, 0x6a, 0x51, 0x7f, 0xa9, 0xd1, - 0x96, 0xd1, 0x8d, 0xce, 0x4b, 0x1d, 0x23, 0x07, 0x16, 0x23, 0x6f, 0xb6, - 0x54, 0x71, 0x27, 0xfc, 0x1e, 0x38, 0x7b, 0x21, 0x2b, 0x1a, 0x2f, 0x67, - 0xe5, 0x31, 0xb6, 0x62, 0x65, 0x34, 0x04, 0x60, 0xe9, 0x57, 0x52, 0x8c, - 0x35, 0xa6, 0xd3, 0x56, 0x86, 0xfc, 0x72, 0x0d, 0x81, 0x7e, 0xd1, 0x87, - 0x8e, 0xc9, 0x7f, 0xd0, 0xfc, 0xef, 0x4c, 0xbd, 0x9b, 0xe1, 0x25, 0x32, - 0x0f, 0x23, 0x32, 0x01, 0x6c, 0x2f, 0x8d, 0x49, 0x18, 0x0d, 0x5c, 0x94, - 0xf3, 0x13, 0xb9, 0x0e, 0x23, 0xe2, 0x3b, 0x68, 0xe3, 0x3f, 0x98, 0x62, - 0x1f, 0x4a, 0xb9, 0x37, 0xce, 0x0a, 0x3a, 0x9d, 0x64, 0x18, 0x2b, 0x4a, - 0xb7, 0x8b, 0x9a, 0x47, 0xfc, 0xe0, 0xed, 0x24, 0x7b, 0x08, 0x66, 0x54, - 0xa9, 0x97, 0x40, 0xb4, 0xba, 0x04, 0x1d, 0x4e, 0x51, 0xfd, 0x61, 0x2a, - 0xdf, 0xe9, 0x08, 0x9b, 0x5e, 0x30, 0x62, 0xba, 0xbd, 0x60, 0xa4, 0x4b, - 0x91, 0xef, 0xaa, 0x96, 0xd3, 0xe0, 0xad, 0xba, 0x67, 0x72, 0x39, 0x0d, - 0xff, 0x38, 0x8e, 0x31, 0xdf, 0xa6, 0xc6, 0x6a, 0x75, 0x88, 0x51, 0x1b, - 0xd8, 0x39, 0x85, 0x3e, 0x45, 0xd8, 0xb3, 0x5e, 0xf9, 0x60, 0xaf, 0xc4, - 0x22, 0x10, 0x6d, 0xb9, 0x81, 0x91, 0x31, 0xba, 0x2a, 0x41, 0x09, 0x2d, - 0xd1, 0x46, 0xc3, 0xa1, 0x04, 0x68, 0x74, 0x90, 0x7b, 0x06, 0x7d, 0x6b, - 0x75, 0x95, 0x14, 0x97, 0x40, 0x29, 0xba, 0x4c, 0xb2, 0xc4, 0xf0, 0x1e, - 0x69, 0x6a, 0x92, 0xf3, 0xa8, 0x4a, 0x55, 0x2d, 0xc9, 0x81, 0x64, 0x53, - 0x4a, 0x34, 0xc1, 0x31, 0xe8, 0xaa, 0x99, 0xd5, 0x80, 0x57, 0xda, 0x57, - 0x02, 0x5f, 0xd0, 0x20, 0x2b, 0x4a, 0xf3, 0x97, 0x68, 0x57, 0x48, 0x6e, - 0x3f, 0xfa, 0xeb, 0xc3, 0x61, 0x64, 0x75, 0x44, 0x82, 0xa0, 0x6d, 0xee, - 0x65, 0xea, 0x60, 0x4d, 0x6a, 0x66, 0x6d, 0x8a, 0x1a, 0x65, 0x0d, 0x6d, - 0x21, 0xb4, 0x8e, 0x2f, 0xc1, 0x26, 0x98, 0x98, 0x6d, 0x57, 0x65, 0xe5, - 0x86, 0x68, 0x45, 0x6d, 0x4b, 0x20, 0x51, 0x5d, 0x89, 0x66, 0xd6, 0xb7, - 0xcc, 0x30, 0x01, 0x9b, 0xd7, 0x58, 0x65, 0x4d, 0x92, 0xf1, 0xd7, 0xf9, - 0x0a, 0x2b, 0x6d, 0x21, 0xfb, 0x6b, 0x0d, 0x3b, 0xb3, 0xf5, 0xb5, 0x06, - 0x20, 0x59, 0x6b, 0x91, 0x62, 0xd7, 0x5a, 0x64, 0x18, 0x80, 0xdb, 0xd6, - 0x9a, 0xb3, 0x26, 0xbe, 0x57, 0xd6, 0x7a, 0x0d, 0xb5, 0x36, 0x91, 0xfd, - 0xb5, 0xa6, 0x2d, 0xe3, 0xda, 0x5a, 0x23, 0x90, 0xac, 0xb5, 0x48, 0xb1, - 0x6a, 0x2d, 0x32, 0x4c, 0xc0, 0x2d, 0x6b, 0xcd, 0x58, 0x93, 0x64, 0xaa, - 0x6a, 0xbd, 0x81, 0x5a, 0x5b, 0xc8, 0x15, 0x6d, 0x0d, 0xde, 0x47, 0x6d, - 0xad, 0x11, 0x48, 0xd6, 0x5a, 0xa4, 0x58, 0xb5, 0x16, 0x19, 0x26, 0xe0, - 0x96, 0xb5, 0x66, 0xac, 0x49, 0x32, 0x55, 0xb5, 0xc6, 0xa1, 0xde, 0x42, - 0x76, 0xd6, 0x1a, 0x86, 0x5a, 0x1e, 0x80, 0xcb, 0x5f, 0x6d, 0xe1, 0xea, - 0x02, 0xa0, 0x3a, 0xc2, 0x1a, 0x3e, 0xa7, 0xbe, 0x8d, 0x2f, 0x1c, 0xcf, - 0x1d, 0x0f, 0x9b, 0x69, 0xcd, 0x98, 0x99, 0xca, 0x6c, 0xa5, 0xaa, 0xf5, - 0x43, 0xa4, 0x84, 0x2d, 0x9b, 0x95, 0xf9, 0x52, 0x3c, 0x75, 0x68, 0x80, - 0x35, 0xe9, 0xc0, 0x1a, 0x21, 0x20, 0x2c, 0x89, 0xf8, 0x9b, 0xf4, 0x24, - 0x87, 0x16, 0xd5, 0x31, 0x5d, 0xcd, 0x49, 0xe1, 0xbb, 0x78, 0x7e, 0x1e, - 0xd4, 0xa0, 0xd3, 0xa5, 0x34, 0x5b, 0x2a, 0xb2, 0xa8, 0xb6, 0xde, 0xaa, - 0x36, 0xe0, 0x16, 0xda, 0x2c, 0xce, 0x79, 0xe8, 0x64, 0xfc, 0xda, 0x9c, - 0x63, 0xdd, 0x75, 0x64, 0x6d, 0xb8, 0x86, 0x56, 0x4c, 0xa2, 0x58, 0x91, - 0xe2, 0x45, 0x9a, 0xe5, 0x05, 0x35, 0xae, 0xb5, 0x64, 0x22, 0xa1, 0x78, - 0x8c, 0x4b, 0x02, 0xf3, 0x20, 0xdb, 0xf3, 0xff, 0xed, 0x34, 0xff, 0xcf, - 0x68, 0x7f, 0xb3, 0x1e, 0x10, 0xd0, 0x0b, 0x82, 0x7b, 0x82, 0x52, 0xed, - 0x06, 0x3d, 0x42, 0xd3, 0xc6, 0x75, 0xba, 0xac, 0x57, 0x42, 0x00, 0x12, - 0x35, 0x46, 0x04, 0x87, 0xe2, 0x41, 0xaa, 0xcc, 0xdf, 0x4a, 0xdf, 0x18, - 0x23, 0xf0, 0x6f, 0x95, 0x9a, 0x89, 0x01, 0x52, 0xe2, 0x38, 0xbb, 0x18, - 0x1e, 0xc9, 0xa9, 0xaf, 0x15, 0x42, 0xf9, 0xa7, 0x23, 0x12, 0x66, 0xf7, - 0x26, 0x32, 0x60, 0x66, 0x21, 0xd9, 0x61, 0x73, 0x0b, 0x05, 0x1a, 0x13, - 0xeb, 0xcd, 0x25, 0x41, 0xd9, 0x0d, 0x87, 0xc9, 0x43, 0x09, 0xb1, 0x55, - 0xd3, 0x71, 0x71, 0xe3, 0x47, 0x55, 0xe3, 0xe1, 0x54, 0xdd, 0xc0, 0x72, - 0x8f, 0x77, 0xc5, 0xb8, 0xda, 0x9b, 0x63, 0xb3, 0x66, 0xe9, 0xcc, 0x31, - 0x0c, 0x43, 0xb6, 0x10, 0x47, 0xbc, 0xd5, 0xd1, 0xce, 0x97, 0x75, 0xfb, - 0x1a, 0xbc, 0x3d, 0x09, 0xa7, 0x64, 0x09, 0xd2, 0xc8, 0xe5, 0xd3, 0x89, - 0x00, 0x55, 0xfc, 0xac, 0x1a, 0x2d, 0x4e, 0x41, 0x1a, 0x06, 0x96, 0x47, - 0x1a, 0xab, 0x75, 0xad, 0x30, 0x56, 0x6b, 0x29, 0x0b, 0xf8, 0xd1, 0x48, - 0x14, 0x00, 0x6e, 0x4b, 0x02, 0x52, 0x15, 0x80, 0xed, 0xe4, 0x40, 0x7c, - 0xe3, 0x47, 0x85, 0x14, 0xce, 0x74, 0x29, 0x00, 0xb0, 0x53, 0x08, 0xd3, - 0xd5, 0x26, 0xc4, 0xfb, 0x41, 0x30, 0xa9, 0x15, 0xf4, 0xcb, 0x52, 0x79, - 0xaa, 0xbf, 0x84, 0x68, 0xe4, 0x16, 0x98, 0xc7, 0x15, 0x09, 0xbf, 0x4a, - 0xe5, 0xa7, 0xba, 0xca, 0x4f, 0xa5, 0x4b, 0xb0, 0x8d, 0xda, 0x6e, 0xd1, - 0xbc, 0x9a, 0x14, 0xd9, 0x73, 0xd3, 0xf5, 0x62, 0x64, 0x70, 0x55, 0xa6, - 0x51, 0x42, 0xfd, 0x83, 0x8c, 0x23, 0x63, 0xc8, 0x32, 0x8f, 0x2c, 0xb9, - 0xde, 0x40, 0x72, 0x38, 0xa1, 0x2f, 0x71, 0xa9, 0x95, 0x22, 0x02, 0x6c, - 0xf4, 0x0a, 0x3e, 0xc6, 0x8d, 0x58, 0x12, 0xbc, 0x81, 0xf2, 0xd8, 0xf4, - 0x46, 0x7a, 0x99, 0xbf, 0x44, 0xfc, 0x2d, 0x6f, 0xf9, 0x9b, 0xbf, 0x84, - 0x2d, 0x13, 0xd8, 0xc3, 0xd6, 0x15, 0x1d, 0x6a, 0x05, 0x1a, 0x67, 0x17, - 0xe5, 0x51, 0x07, 0x2a, 0x2d, 0x48, 0x1f, 0x10, 0x30, 0x40, 0x21, 0x10, - 0xec, 0x9f, 0xa5, 0x11, 0xc8, 0x91, 0xa5, 0x12, 0x3c, 0x3d, 0x48, 0x27, - 0x10, 0xb0, 0x46, 0x29, 0xfa, 0x03, 0x44, 0x93, 0xf0, 0x4d, 0x96, 0x84, - 0xfe, 0x89, 0x5a, 0x41, 0xd4, 0x83, 0xd4, 0x82, 0x20, 0x03, 0xf4, 0x82, - 0xe0, 0xfe, 0x59, 0x8a, 0x41, 0x2c, 0x59, 0x9a, 0x21, 0x32, 0x82, 0x54, - 0x83, 0x20, 0xab, 0x75, 0x03, 0xcc, 0x85, 0x0e, 0xfe, 0x2f, 0x57, 0x0d, - 0x20, 0x16, 0x66, 0x30, 0x00, 0x30, 0xc4, 0x60, 0x00, 0xd8, 0x3f, 0xcc, - 0x60, 0x20, 0x47, 0xb6, 0x5a, 0x50, 0x7a, 0x98, 0xc1, 0x00, 0xc0, 0x1a, - 0x83, 0x71, 0xd4, 0x56, 0x81, 0xff, 0xb5, 0xd6, 0x82, 0x22, 0xe6, 0x53, - 0xc0, 0x7c, 0x7b, 0xa7, 0x42, 0x89, 0xa6, 0xbf, 0xdd, 0x86, 0x85, 0x7e, - 0xa2, 0x6a, 0xc4, 0xd0, 0x99, 0xc8, 0xf3, 0x53, 0xfa, 0x21, 0x76, 0x0a, - 0x9f, 0xe1, 0xde, 0xf9, 0x19, 0x63, 0xc1, 0x3d, 0xc3, 0x9d, 0xfe, 0x50, - 0xbd, 0x4e, 0xca, 0x20, 0xf0, 0x9c, 0xaf, 0x54, 0x59, 0x96, 0xd6, 0xa3, - 0x7d, 0xfc, 0x64, 0x46, 0x2d, 0x29, 0x38, 0x52, 0x1e, 0x11, 0x60, 0xc7, - 0xa3, 0xa6, 0x69, 0x36, 0x95, 0xa8, 0xb8, 0x5d, 0x99, 0x8d, 0xaf, 0x95, - 0x3d, 0x4e, 0xd8, 0x6f, 0xa3, 0x73, 0x87, 0x94, 0xce, 0x76, 0xe2, 0x38, - 0x53, 0xc5, 0x8a, 0x9f, 0x37, 0x14, 0xc4, 0x65, 0xe1, 0x8d, 0x96, 0x5e, - 0x9d, 0xbc, 0x01, 0xcf, 0x7a, 0x2d, 0xe0, 0xd4, 0x42, 0xc9, 0x6c, 0x54, - 0xbe, 0x7f, 0xc0, 0xb9, 0x76, 0x73, 0xee, 0x59, 0x90, 0x2c, 0xe8, 0xec, - 0x16, 0x1d, 0x23, 0x79, 0x7a, 0x71, 0x91, 0x4c, 0xeb, 0x56, 0xb2, 0x8a, - 0xae, 0x85, 0x20, 0xc4, 0xe5, 0xa4, 0x26, 0xe5, 0x6e, 0xde, 0x52, 0xf1, - 0x22, 0x6d, 0xb9, 0xcc, 0xc5, 0xaf, 0xbe, 0x54, 0x72, 0x61, 0x9d, 0x0d, - 0xf3, 0x83, 0x86, 0x5f, 0x1b, 0x71, 0x51, 0x99, 0xcc, 0x49, 0x39, 0x5a, - 0xed, 0xe6, 0x87, 0xce, 0xed, 0xc9, 0x47, 0xd2, 0x07, 0x11, 0x47, 0xbb, - 0xfa, 0x33, 0x8f, 0x03, 0xed, 0xb8, 0xde, 0xad, 0x96, 0xbf, 0x9e, 0xfb, - 0x0f, 0x59, 0x4f, 0xa5, 0x5e, 0xce, 0x79, 0xe8, 0xe2, 0x6a, 0x9c, 0x2e, - 0x6b, 0xcf, 0x51, 0x74, 0x11, 0x4a, 0x68, 0xb8, 0xc0, 0xb2, 0xad, 0xa4, - 0xf2, 0x2a, 0x8a, 0x0a, 0xda, 0x68, 0x05, 0xcd, 0x45, 0x0c, 0xca, 0x50, - 0xca, 0xb4, 0x76, 0xc6, 0x2f, 0x93, 0x1b, 0x02, 0xab, 0x62, 0x45, 0x42, - 0xdf, 0xa6, 0x3f, 0xa2, 0x29, 0x89, 0xe9, 0x44, 0xf5, 0x33, 0x18, 0x7e, - 0x05, 0x3a, 0x3f, 0x08, 0x17, 0xf7, 0x3b, 0x83, 0x76, 0xa7, 0x7f, 0xd4, - 0x7e, 0x75, 0xf0, 0xe6, 0x9b, 0xed, 0xd7, 0xfc, 0x70, 0x07, 0x02, 0xee, - 0xf0, 0x8d, 0xd7, 0xab, 0xe0, 0x0e, 0x05, 0x5c, 0xbf, 0xff, 0xb8, 0xdd, - 0xde, 0xeb, 0xc3, 0x39, 0xaf, 0x90, 0x30, 0xd8, 0xc5, 0x6a, 0xb5, 0x98, - 0x8c, 0x1b, 0x74, 0x1e, 0x2a, 0x34, 0x84, 0xf2, 0xc5, 0x6a, 0x55, 0x24, - 0xbb, 0x20, 0x6c, 0xb2, 0x2c, 0x5a, 0x25, 0x06, 0x99, 0x53, 0xb4, 0xe1, - 0xc1, 0x21, 0xda, 0xec, 0x47, 0x2f, 0xf6, 0xfb, 0xfd, 0x47, 0xd1, 0x13, - 0xf8, 0xf2, 0xf4, 0xe9, 0xd3, 0x47, 0x21, 0x94, 0x89, 0xe5, 0xdd, 0x11, - 0xa6, 0x7b, 0x2c, 0xdb, 0x51, 0x37, 0xfb, 0x13, 0xbe, 0x17, 0x54, 0xdf, - 0x9f, 0x10, 0x4a, 0xf4, 0x27, 0x81, 0xe5, 0xeb, 0x4f, 0x98, 0xa7, 0x42, - 0x36, 0x5a, 0xe2, 0xb1, 0x69, 0x01, 0x77, 0x7a, 0x89, 0x21, 0x62, 0xa2, - 0x83, 0xb7, 0xa6, 0x80, 0x5c, 0xc4, 0x3d, 0x52, 0x41, 0x1d, 0xab, 0x97, - 0x0a, 0x42, 0x09, 0xa9, 0x08, 0x2c, 0x9f, 0x54, 0x30, 0x4f, 0x87, 0xdc, - 0x5e, 0x2a, 0x8c, 0x3b, 0x41, 0x27, 0x5c, 0x2a, 0xfc, 0x80, 0x7d, 0x93, - 0xbe, 0x84, 0x00, 0x21, 0xa4, 0xc5, 0xc9, 0x9b, 0x87, 0xa7, 0x5c, 0xee, - 0xc3, 0xed, 0x8a, 0x34, 0x2e, 0x84, 0xef, 0x8a, 0x36, 0x9b, 0x1c, 0xec, - 0x90, 0x3a, 0xcc, 0x35, 0x76, 0x26, 0x73, 0x31, 0x75, 0xd9, 0x21, 0x7d, - 0x98, 0x09, 0x6d, 0xcf, 0x3e, 0x3f, 0xcd, 0x58, 0x24, 0x37, 0xc5, 0x1e, - 0xdd, 0xf1, 0x63, 0xfd, 0x7c, 0x96, 0xac, 0xd9, 0x59, 0xf4, 0x08, 0x92, - 0x24, 0xcd, 0x08, 0x23, 0xb4, 0x63, 0x90, 0xce, 0xd0, 0xc1, 0x18, 0x51, - 0xff, 0xd9, 0x63, 0xb1, 0x08, 0xa5, 0x9f, 0x87, 0x1c, 0x8f, 0x95, 0x17, - 0x20, 0xe5, 0xc4, 0xdd, 0x73, 0x34, 0x96, 0x68, 0x7a, 0x8f, 0xc7, 0xc2, - 0x1f, 0x83, 0x80, 0x53, 0xb1, 0x75, 0x23, 0xd0, 0x60, 0x30, 0x70, 0x8e, - 0x6f, 0xf7, 0xc1, 0x4a, 0x72, 0x92, 0xcc, 0xe1, 0x81, 0x80, 0xed, 0xc6, - 0x3a, 0xf8, 0x0b, 0x38, 0x47, 0xb7, 0x1b, 0xf2, 0x2c, 0xe4, 0xe1, 0x0e, - 0x08, 0xd3, 0x51, 0xda, 0xdd, 0x90, 0xc6, 0x03, 0xb6, 0xbb, 0xa1, 0x8c, - 0xc7, 0x6e, 0x77, 0x44, 0x9a, 0x05, 0x9c, 0xdb, 0x0d, 0xed, 0x7c, 0x9d, - 0xec, 0xaa, 0x19, 0x85, 0xb1, 0xd9, 0x8e, 0xb4, 0xe5, 0xaf, 0x14, 0x01, - 0x93, 0x22, 0x00, 0xd2, 0xbc, 0x95, 0xc2, 0x3b, 0x25, 0x82, 0x2c, 0x15, - 0xee, 0x4f, 0xcc, 0x87, 0x88, 0x31, 0x4e, 0x25, 0xdc, 0x51, 0x11, 0x44, - 0xba, 0xb0, 0x3a, 0xd3, 0x64, 0x7c, 0x28, 0x96, 0x21, 0xd4, 0xd9, 0xaa, - 0x4c, 0xfd, 0xa4, 0xd7, 0xa6, 0xde, 0x68, 0x25, 0xe2, 0x81, 0xa7, 0xe0, - 0x95, 0xdc, 0x30, 0x5b, 0x79, 0x3e, 0x9e, 0x16, 0x29, 0xac, 0xfb, 0xb1, - 0x9b, 0xfb, 0x71, 0xdb, 0xaf, 0x2c, 0x79, 0x90, 0xb6, 0x00, 0x55, 0x43, - 0x61, 0x72, 0xaf, 0xc6, 0x10, 0xb4, 0x06, 0xdb, 0x64, 0x41, 0xc8, 0x49, - 0x0d, 0x4a, 0xd1, 0x4a, 0x6d, 0x5c, 0x5f, 0xee, 0x20, 0xd0, 0x53, 0x8b, - 0x17, 0xe3, 0x69, 0xc2, 0x9f, 0x5c, 0x69, 0x12, 0x87, 0x97, 0xcf, 0xe3, - 0xbd, 0xe1, 0x1f, 0xe5, 0x24, 0xa7, 0x06, 0x04, 0x1b, 0xb4, 0x0e, 0xa4, - 0x58, 0xd6, 0x43, 0xe4, 0x1e, 0x10, 0xb8, 0xbf, 0x13, 0xd6, 0xa5, 0xd8, - 0x73, 0xd1, 0x8e, 0xb6, 0xa1, 0x18, 0x05, 0xa2, 0x69, 0x1e, 0xd6, 0xc9, - 0x10, 0x77, 0xb7, 0x47, 0xf5, 0xfc, 0x59, 0x78, 0xe3, 0x8c, 0x6b, 0xbf, - 0xbc, 0xf8, 0x42, 0x77, 0xab, 0x60, 0x1f, 0x22, 0x6a, 0x99, 0x97, 0xa8, - 0x01, 0xb8, 0xbc, 0xcc, 0x25, 0x42, 0x26, 0xb4, 0xed, 0x7b, 0x55, 0xf4, - 0xa7, 0xd3, 0x8c, 0x5e, 0x1b, 0xc9, 0xe0, 0x05, 0xd6, 0x95, 0x51, 0xcc, - 0x48, 0x58, 0xb8, 0x6c, 0xb8, 0x54, 0x96, 0xe4, 0x74, 0x6d, 0x46, 0x3c, - 0xd5, 0x19, 0x31, 0xfd, 0xcb, 0x15, 0x24, 0xfd, 0x2a, 0xec, 0xd5, 0x78, - 0x6d, 0x5d, 0x83, 0x95, 0x7f, 0xe6, 0x6d, 0x30, 0x8b, 0xcf, 0x1a, 0x83, - 0x26, 0xae, 0x82, 0xa9, 0x31, 0x6a, 0xc2, 0xea, 0x65, 0x78, 0x62, 0x5a, - 0xdf, 0xf9, 0x73, 0xfe, 0xa1, 0xea, 0x23, 0xfa, 0xd9, 0xe2, 0x5c, 0x35, - 0x0d, 0x75, 0xa4, 0xb7, 0x1b, 0xe9, 0x86, 0xfb, 0x52, 0x14, 0xaf, 0x36, - 0xbf, 0x10, 0xd5, 0x6a, 0x5b, 0xcd, 0x4a, 0xd7, 0x1f, 0xcd, 0x66, 0x1d, - 0x2f, 0x16, 0x7f, 0x55, 0x8b, 0xa2, 0x5c, 0x99, 0x74, 0xa2, 0x51, 0x93, - 0xe6, 0x1d, 0xba, 0xc9, 0x11, 0x80, 0x2e, 0x1b, 0x4a, 0xda, 0x4e, 0x3c, - 0x7f, 0xa7, 0x76, 0x8c, 0x7c, 0xf9, 0x76, 0x2d, 0xaa, 0x2b, 0x71, 0x6f, - 0x2f, 0x28, 0xd7, 0x06, 0xe9, 0xd0, 0xbc, 0x8f, 0x26, 0xa6, 0xd2, 0xb5, - 0xfd, 0x56, 0x65, 0xf3, 0xe4, 0x0e, 0x1e, 0x94, 0x62, 0x0c, 0x71, 0xc6, - 0xdd, 0xdd, 0x07, 0x9e, 0xf5, 0x85, 0xa9, 0x72, 0x88, 0x1a, 0x37, 0xd0, - 0xda, 0x30, 0xa3, 0xa4, 0xb6, 0xd8, 0x03, 0x4e, 0x54, 0x9b, 0xb0, 0xa1, - 0xb0, 0x20, 0xbf, 0x05, 0x38, 0x96, 0x72, 0x0c, 0xab, 0x2e, 0xe3, 0xde, - 0xba, 0x72, 0xab, 0xdf, 0xc3, 0xbe, 0xca, 0xe7, 0xf8, 0x9c, 0xcd, 0x6d, - 0x27, 0xc2, 0x27, 0xeb, 0xa1, 0x4e, 0xb5, 0x37, 0x61, 0x79, 0xf9, 0x9c, - 0x40, 0xd9, 0xd4, 0x37, 0xda, 0x1e, 0x3b, 0x90, 0x15, 0xe9, 0x5e, 0x2f, - 0x33, 0x86, 0x62, 0x71, 0xbc, 0x14, 0xf7, 0xbc, 0x69, 0xcf, 0xf2, 0xc5, - 0xf1, 0x6c, 0xf0, 0xfa, 0xe0, 0x75, 0xda, 0xb4, 0x7c, 0xf1, 0xf1, 0x74, - 0x7c, 0x71, 0xb8, 0xdf, 0x92, 0x2e, 0xd6, 0xbb, 0xcb, 0xf4, 0x6a, 0x4c, - 0x95, 0x48, 0x73, 0x62, 0x78, 0xc6, 0x22, 0xb9, 0x90, 0x08, 0xe8, 0x9e, - 0x55, 0x8c, 0xd7, 0xe1, 0xd9, 0x8d, 0xf1, 0x08, 0x4a, 0xe9, 0xe3, 0x97, - 0xb6, 0xeb, 0x72, 0x6b, 0x0b, 0xc5, 0x00, 0xbb, 0xdf, 0x44, 0x86, 0x95, - 0xe0, 0x7e, 0x23, 0xe4, 0x2e, 0xe0, 0x56, 0xac, 0x46, 0x8c, 0xd9, 0x86, - 0xe8, 0x9e, 0x8b, 0x54, 0x06, 0xec, 0x8e, 0xbe, 0x49, 0x26, 0x27, 0x2b, - 0xf0, 0xd8, 0x0b, 0x3a, 0xa6, 0x40, 0x41, 0xba, 0x17, 0x09, 0x3d, 0xcc, - 0xcf, 0xb7, 0xbb, 0x81, 0xfc, 0x9d, 0xf9, 0x62, 0x38, 0xe7, 0xe8, 0x49, - 0xd4, 0xc7, 0x9a, 0xb1, 0x5c, 0x38, 0x07, 0xf8, 0x65, 0x52, 0x64, 0x29, - 0x3e, 0x32, 0x3e, 0xe0, 0x69, 0x59, 0x22, 0x71, 0xde, 0x4f, 0x16, 0xe3, - 0xdb, 0x0f, 0xb3, 0xd5, 0xf5, 0x07, 0x63, 0x7c, 0x14, 0x5b, 0x02, 0xcd, - 0x92, 0xc9, 0x66, 0xce, 0x5e, 0x2f, 0x07, 0xb6, 0x86, 0xfa, 0xbb, 0xc4, - 0x22, 0x6a, 0xc0, 0x62, 0xa1, 0x07, 0x0e, 0xd0, 0x2f, 0x8a, 0x1e, 0x2f, - 0x56, 0x30, 0x4e, 0xae, 0x57, 0x05, 0xe8, 0x42, 0x0a, 0x03, 0xd8, 0x6d, - 0x84, 0x6e, 0x9e, 0xc2, 0x70, 0xae, 0xdc, 0xdd, 0x76, 0x3e, 0x5e, 0x2e, - 0x03, 0x76, 0xc4, 0x98, 0x68, 0x85, 0x5c, 0x87, 0x34, 0x90, 0x31, 0x94, - 0x12, 0x53, 0x95, 0xa3, 0xd6, 0xa7, 0xe3, 0xe5, 0x86, 0x4a, 0xa2, 0xd4, - 0xd9, 0x93, 0x27, 0x15, 0xcc, 0x52, 0xec, 0x81, 0xbb, 0x1f, 0x92, 0x64, - 0x7d, 0x4c, 0xc0, 0xac, 0xb2, 0xf7, 0x8a, 0xc3, 0x5e, 0xcb, 0x1e, 0xb4, - 0xc2, 0xe9, 0x99, 0x0a, 0xe6, 0x7f, 0x86, 0x1d, 0xed, 0x83, 0x36, 0xe3, - 0xa9, 0x9c, 0x1b, 0x4b, 0x1a, 0x5d, 0x80, 0xa4, 0xae, 0xa3, 0xbb, 0x9e, - 0x90, 0xea, 0x73, 0x3d, 0x1b, 0xbb, 0x9d, 0x40, 0xab, 0xc6, 0x34, 0xe8, - 0x37, 0x83, 0x79, 0xad, 0x7c, 0x4d, 0x5f, 0xa3, 0x20, 0x40, 0x53, 0x6a, - 0x08, 0x81, 0x51, 0xa8, 0x7b, 0x98, 0x63, 0xf1, 0x1d, 0xf8, 0x4d, 0x06, - 0x9d, 0x95, 0x06, 0x20, 0x06, 0x07, 0x8a, 0xcf, 0x7e, 0x7a, 0xce, 0x92, - 0x88, 0xda, 0x0f, 0x45, 0xed, 0x19, 0xb4, 0x54, 0x1d, 0xbc, 0x26, 0x68, - 0xaa, 0x0e, 0xa6, 0xf1, 0xab, 0x96, 0x3d, 0xe8, 0x1e, 0x57, 0x56, 0xe4, - 0x23, 0x19, 0x66, 0xd6, 0x0e, 0xe0, 0x01, 0x1c, 0x91, 0x10, 0xf8, 0x24, - 0xed, 0x4b, 0xd1, 0x9f, 0x80, 0xb3, 0xb2, 0xe3, 0xe2, 0x5a, 0x9e, 0x11, - 0x57, 0xe4, 0xc9, 0x1b, 0x7d, 0x0c, 0xcb, 0x35, 0xce, 0x66, 0x9b, 0x74, - 0xb9, 0x82, 0xaf, 0xb2, 0x3b, 0x43, 0xe9, 0xfe, 0x10, 0x21, 0xc7, 0x25, - 0x75, 0x14, 0x94, 0x54, 0x0d, 0xaa, 0x27, 0x90, 0x41, 0xfa, 0x26, 0x01, - 0xbf, 0xd2, 0xf2, 0xa0, 0xd7, 0x98, 0xc0, 0x90, 0xac, 0x92, 0x31, 0x78, - 0x1e, 0xf5, 0xd4, 0x91, 0xfe, 0xca, 0x41, 0x1d, 0x83, 0xc9, 0x2c, 0x9c, - 0xbf, 0x80, 0x1e, 0xf3, 0xda, 0x6b, 0x06, 0xce, 0x9f, 0xeb, 0x3b, 0x06, - 0xf7, 0xaa, 0xa5, 0xb6, 0x7e, 0xb7, 0x5a, 0x6e, 0x24, 0x3d, 0x6e, 0xdb, - 0x6b, 0xd0, 0xb8, 0x75, 0x95, 0x30, 0xfd, 0x88, 0xa1, 0x53, 0xda, 0x64, - 0xad, 0x82, 0xc5, 0xfd, 0x3e, 0xf4, 0xaf, 0x9d, 0x48, 0xbc, 0xdb, 0xdd, - 0xa9, 0xc4, 0xff, 0xac, 0xf0, 0x44, 0xd7, 0xac, 0xb3, 0xb4, 0x6f, 0x8d, - 0x22, 0x69, 0xe0, 0x1c, 0x8c, 0x84, 0xc6, 0x4a, 0xbd, 0x0f, 0x6a, 0x3b, - 0x72, 0x49, 0x82, 0xdb, 0xee, 0x29, 0x41, 0xaf, 0x96, 0x81, 0x8d, 0x76, - 0x1f, 0x10, 0xcb, 0x06, 0xac, 0x48, 0x39, 0xa2, 0xab, 0xe3, 0x2f, 0x89, - 0x49, 0xca, 0xa5, 0x27, 0x81, 0x44, 0x29, 0x80, 0x59, 0x26, 0x85, 0x8f, - 0x4d, 0x92, 0x64, 0xf7, 0x62, 0x9c, 0x2e, 0x12, 0x19, 0xd1, 0xc4, 0x2b, - 0x5b, 0x62, 0x58, 0x67, 0xd9, 0x62, 0x58, 0x67, 0xb7, 0xda, 0xb6, 0x02, - 0xfe, 0x26, 0x5b, 0x78, 0x6c, 0x69, 0xed, 0x54, 0xea, 0xdf, 0x1d, 0x73, - 0xde, 0x88, 0x83, 0x44, 0x51, 0x19, 0x41, 0x32, 0x39, 0x48, 0x46, 0x1d, - 0x5a, 0xbf, 0xb9, 0x4c, 0x96, 0x6c, 0x50, 0x95, 0x22, 0x4d, 0x73, 0xf2, - 0xc0, 0x3a, 0xf4, 0xae, 0x0c, 0x45, 0x7e, 0x20, 0xa9, 0xf3, 0xe1, 0x17, - 0x52, 0xb3, 0x9f, 0x92, 0xcc, 0xd9, 0x1a, 0x72, 0x44, 0x90, 0xee, 0xae, - 0x37, 0x7e, 0x63, 0xd9, 0x4e, 0x54, 0x9a, 0x3d, 0xc5, 0x4b, 0xcb, 0xd6, - 0x4f, 0x66, 0x76, 0x38, 0x34, 0x02, 0xc9, 0x92, 0x8b, 0x2c, 0xc9, 0x2f, - 0xcf, 0x69, 0x95, 0x14, 0x26, 0xa1, 0x6c, 0xe8, 0x7f, 0xc6, 0x7f, 0xc5, - 0xd4, 0xd7, 0xe4, 0x71, 0xaf, 0x97, 0x5a, 0xed, 0x0e, 0x39, 0xbd, 0xfb, - 0x58, 0x56, 0x03, 0xc3, 0x25, 0x3d, 0x15, 0xae, 0xc5, 0x0d, 0xac, 0x44, - 0x58, 0x2f, 0xe1, 0x74, 0xb7, 0x1a, 0x78, 0xf6, 0xf6, 0x7c, 0x4f, 0x11, - 0xca, 0x9a, 0xf3, 0xf9, 0xc3, 0x00, 0xeb, 0xde, 0x0c, 0xf5, 0x98, 0xa3, - 0x1e, 0x34, 0x47, 0xfd, 0x95, 0xa3, 0x3e, 0x46, 0xd4, 0xa0, 0xcd, 0x0d, - 0x6f, 0x8f, 0x83, 0x56, 0x7b, 0xb9, 0xd5, 0x8c, 0x44, 0x78, 0xb7, 0x03, - 0xe2, 0xd4, 0xef, 0x82, 0x78, 0xdc, 0xb6, 0xef, 0x61, 0xb4, 0xd2, 0x5b, - 0xe1, 0x28, 0xef, 0xb4, 0x07, 0x92, 0x97, 0xd0, 0xb4, 0x0b, 0xb2, 0x89, - 0x50, 0x6d, 0x27, 0x34, 0xe3, 0xb9, 0xd1, 0x63, 0x99, 0x65, 0x7f, 0x73, - 0xf6, 0xc9, 0xb6, 0xab, 0xd2, 0x9f, 0xac, 0xe6, 0x11, 0x8d, 0x88, 0xb9, - 0xaf, 0x16, 0x94, 0xab, 0xd6, 0x82, 0x12, 0x9c, 0x55, 0xa1, 0x1c, 0xb5, - 0x32, 0x22, 0xcc, 0x1b, 0x7d, 0x36, 0xad, 0x12, 0xba, 0x0e, 0xf6, 0x98, - 0x58, 0x64, 0xb7, 0xc7, 0x74, 0x91, 0xf0, 0xed, 0x91, 0x32, 0x86, 0xf4, - 0xe4, 0xbc, 0x99, 0x38, 0x6b, 0xe8, 0x10, 0x79, 0xed, 0x0a, 0xfc, 0xd5, - 0x3b, 0x9b, 0x5b, 0x59, 0x96, 0x20, 0xeb, 0x22, 0xac, 0x58, 0xe3, 0x0a, - 0x19, 0x63, 0xfe, 0x36, 0x65, 0xb7, 0xb6, 0x09, 0xf2, 0xc7, 0xcb, 0x25, - 0xaf, 0xa9, 0x1f, 0xbd, 0xe6, 0x6e, 0x21, 0x48, 0x0f, 0xc1, 0x1f, 0x28, - 0x71, 0x02, 0xfb, 0x56, 0xa0, 0x40, 0x8f, 0x2e, 0xf3, 0xe3, 0x18, 0x2c, - 0xe0, 0x6b, 0x40, 0x1f, 0x2d, 0x63, 0x25, 0x05, 0x45, 0x3a, 0x96, 0x9a, - 0x8d, 0xe4, 0x39, 0x69, 0x16, 0xf1, 0xb8, 0x87, 0xb4, 0x55, 0x0e, 0x41, - 0x51, 0xc3, 0xde, 0x6e, 0x29, 0x31, 0xf7, 0xf6, 0x82, 0x16, 0x45, 0x1f, - 0x91, 0xe5, 0x7b, 0x24, 0x36, 0x79, 0xf9, 0x9b, 0x85, 0xd8, 0x64, 0x4b, - 0xe8, 0xad, 0xf6, 0xb6, 0x93, 0x5e, 0x05, 0x28, 0x1f, 0xd8, 0x85, 0x7f, - 0xff, 0xc4, 0x93, 0x31, 0x22, 0xa6, 0x86, 0xfd, 0x66, 0x87, 0x1e, 0xab, - 0x60, 0xa4, 0x42, 0x0f, 0xa3, 0xa0, 0xd3, 0x79, 0xee, 0xa0, 0x07, 0x01, - 0x6f, 0x6f, 0xe0, 0x5a, 0xb1, 0x9f, 0x23, 0xca, 0x1d, 0x95, 0x80, 0x21, - 0x04, 0xe5, 0x8b, 0xcc, 0xc1, 0x8f, 0x93, 0xd8, 0x6f, 0x4d, 0x1b, 0x94, - 0x0c, 0x99, 0xcb, 0x46, 0xa2, 0xf0, 0x6d, 0xd1, 0xb1, 0x7c, 0xeb, 0x15, - 0x63, 0xbc, 0x39, 0x80, 0x8d, 0x27, 0xb1, 0x43, 0x0a, 0xb0, 0x6b, 0x4a, - 0x7b, 0xda, 0xbc, 0x0d, 0x4f, 0xe8, 0xa1, 0x3e, 0x76, 0x8d, 0x39, 0xa7, - 0x98, 0x62, 0xb5, 0x82, 0x21, 0x58, 0x4b, 0x26, 0x00, 0x77, 0x67, 0xdc, - 0x85, 0x1f, 0x49, 0xf0, 0x61, 0x48, 0x24, 0x00, 0xf7, 0x6d, 0xfe, 0xa0, - 0xd6, 0xc7, 0x2b, 0xd5, 0x36, 0x4b, 0x26, 0x4f, 0x00, 0x33, 0x2a, 0xc1, - 0x87, 0x01, 0xf7, 0xf1, 0xdd, 0xb7, 0xea, 0x43, 0x18, 0xba, 0xb8, 0x39, - 0xf7, 0x69, 0x24, 0xd0, 0xb2, 0x94, 0x12, 0xc0, 0x43, 0xf5, 0x92, 0xce, - 0x13, 0x05, 0xab, 0xa4, 0xf5, 0x08, 0xb7, 0xa4, 0x51, 0xa3, 0x8c, 0x95, - 0x7a, 0x68, 0x3e, 0x0e, 0x2e, 0xa9, 0x86, 0x69, 0xa0, 0x51, 0x27, 0x3a, - 0x53, 0x11, 0x5c, 0x27, 0xfb, 0xc9, 0x13, 0x49, 0x04, 0x1e, 0xb4, 0x1b, - 0x06, 0x61, 0x65, 0x1a, 0x56, 0x3f, 0x10, 0x6b, 0xae, 0x61, 0x0d, 0x02, - 0xb1, 0x26, 0x1a, 0xd6, 0x41, 0x20, 0x16, 0x9c, 0xe3, 0x64, 0x11, 0x39, - 0x9e, 0xaf, 0x3e, 0x4a, 0x6e, 0xe2, 0x53, 0xb5, 0x8e, 0x1d, 0x8d, 0xf7, - 0x8e, 0xc6, 0x53, 0x47, 0x2b, 0xeb, 0xac, 0x1d, 0x56, 0xda, 0xf5, 0x40, - 0x63, 0xf2, 0x71, 0x20, 0x93, 0x99, 0x8e, 0x76, 0x18, 0x88, 0x36, 0xd7, - 0xd1, 0x8e, 0x02, 0xd1, 0x26, 0x3a, 0xda, 0xeb, 0x81, 0x68, 0x20, 0xc9, - 0x81, 0x47, 0x94, 0x8f, 0x35, 0x71, 0x1d, 0x6a, 0xbf, 0x8e, 0xf0, 0x97, - 0x2c, 0x2c, 0x5c, 0x94, 0x07, 0x1a, 0x97, 0x6f, 0x04, 0x72, 0x99, 0xe9, - 0x68, 0x6f, 0x06, 0xa2, 0xcd, 0x75, 0xb4, 0x7e, 0x68, 0x07, 0x98, 0x18, - 0x78, 0xa1, 0x5d, 0x00, 0x84, 0x79, 0xe0, 0x11, 0xe6, 0x1b, 0x9a, 0xc0, - 0xde, 0xd4, 0xb5, 0xd4, 0x50, 0xda, 0x3e, 0x88, 0xf3, 0x21, 0x86, 0x43, - 0xb4, 0x24, 0x66, 0x34, 0xe1, 0x51, 0xd5, 0x8a, 0x62, 0x54, 0x19, 0x8d, - 0xb6, 0x97, 0x79, 0x98, 0x8a, 0x6a, 0x22, 0xd0, 0xf6, 0xe6, 0x3e, 0xc4, - 0xea, 0xa8, 0xb3, 0xbd, 0x89, 0x1f, 0xcf, 0x1f, 0x69, 0x96, 0xd4, 0x8c, - 0x23, 0x06, 0x98, 0xdb, 0x0a, 0x41, 0x0d, 0xb6, 0x16, 0xd4, 0x60, 0x6b, - 0x49, 0x0d, 0xb6, 0x15, 0xd5, 0x60, 0x6b, 0x59, 0x0d, 0x1a, 0x09, 0xcb, - 0x23, 0xab, 0x83, 0xad, 0x65, 0x75, 0xb0, 0xb5, 0xac, 0x0e, 0xb6, 0x95, - 0xd5, 0xc1, 0xd6, 0xb2, 0x3a, 0x08, 0x97, 0x95, 0xdb, 0xb9, 0x64, 0xef, - 0x6b, 0x36, 0x72, 0x2a, 0x2b, 0x9e, 0xa1, 0xbc, 0xb3, 0x62, 0xae, 0x9a, - 0x2f, 0x51, 0x86, 0x04, 0x86, 0xf5, 0x44, 0x82, 0x0d, 0x72, 0xb9, 0x2a, - 0x1e, 0xb2, 0xbc, 0xab, 0x7f, 0xca, 0x32, 0x28, 0x90, 0xab, 0x2f, 0x70, - 0x6b, 0x90, 0xf7, 0x2b, 0xe2, 0x8c, 0xd6, 0xf2, 0xe7, 0x78, 0x0d, 0xb3, - 0x96, 0x3f, 0x80, 0xf1, 0xf0, 0x07, 0x59, 0x61, 0xde, 0x79, 0xc5, 0x73, - 0x9a, 0x77, 0xf5, 0x0f, 0x6a, 0x06, 0x05, 0x47, 0xf5, 0x06, 0x43, 0x0d, - 0xe6, 0xcf, 0xfd, 0x22, 0xe7, 0x5d, 0xfd, 0x9b, 0x9c, 0x51, 0x48, 0x18, - 0x53, 0x6f, 0xd8, 0xd2, 0x10, 0xfe, 0x2a, 0x1e, 0xf5, 0xbc, 0xab, 0x78, - 0xd6, 0x33, 0x64, 0xca, 0x3d, 0x5d, 0x1a, 0x8d, 0x2b, 0x69, 0x05, 0x72, - 0x06, 0x14, 0x6a, 0x39, 0xd3, 0x5f, 0x06, 0x0d, 0x58, 0x0c, 0x98, 0xae, - 0x36, 0x1e, 0xc6, 0xa6, 0x61, 0xcb, 0x01, 0x7f, 0xd9, 0xcb, 0xa2, 0x61, - 0x17, 0x03, 0x8d, 0x7a, 0xfc, 0x05, 0xaf, 0x95, 0x46, 0x51, 0xf8, 0xbb, - 0x98, 0x61, 0x15, 0xba, 0x6e, 0xf0, 0x48, 0x26, 0xfd, 0xe9, 0x27, 0x70, - 0x77, 0x53, 0xa8, 0xb2, 0x44, 0x1a, 0x36, 0xd8, 0xed, 0x0b, 0xd0, 0x00, - 0x57, 0xf7, 0xba, 0x29, 0xfc, 0xa0, 0x29, 0xc2, 0x41, 0x15, 0x02, 0x68, - 0x79, 0xd0, 0x88, 0x1b, 0xfe, 0x0a, 0xed, 0x5d, 0xc5, 0x3b, 0xb4, 0xb5, - 0x7d, 0x12, 0x60, 0x9c, 0x9a, 0x0c, 0xe9, 0x81, 0x3d, 0xd2, 0xf7, 0x8a, - 0xed, 0x5d, 0xdd, 0x3b, 0xb6, 0x8d, 0xe3, 0x92, 0xd8, 0x6c, 0x12, 0xa5, - 0x50, 0x6b, 0x4b, 0xc1, 0x72, 0xc2, 0x4d, 0x87, 0x23, 0xa4, 0x8f, 0x46, - 0x69, 0xd8, 0xec, 0x2c, 0xbe, 0x71, 0xef, 0x37, 0x38, 0x9c, 0x5d, 0x73, - 0xfa, 0x78, 0xf3, 0xb7, 0xb6, 0x80, 0xfe, 0x60, 0xfb, 0x02, 0xf8, 0xdd, - 0xdf, 0xc0, 0x00, 0x5b, 0xcd, 0xe9, 0xc3, 0xdd, 0xdf, 0xda, 0x0a, 0x1c, - 0xc1, 0xee, 0x67, 0x50, 0x3f, 0xc2, 0x17, 0xe5, 0xc0, 0xc0, 0x34, 0x5a, - 0x0d, 0x85, 0xb5, 0x98, 0x60, 0x35, 0x01, 0x78, 0x79, 0xcc, 0x0d, 0xdf, - 0xd3, 0x31, 0x4f, 0xa0, 0xd8, 0x25, 0x11, 0x58, 0x0f, 0xfc, 0x54, 0x7a, - 0xb7, 0xaa, 0xfc, 0xc1, 0x8f, 0x2b, 0x47, 0x6f, 0x47, 0xfb, 0xfe, 0xd2, - 0xec, 0x63, 0xda, 0x74, 0x92, 0xec, 0x2e, 0xa2, 0xc7, 0xd6, 0x9e, 0x48, - 0x6a, 0x9d, 0x28, 0x9d, 0xb1, 0x9f, 0x04, 0x27, 0x8f, 0x52, 0x06, 0x4e, - 0x02, 0x28, 0x39, 0xe0, 0xe4, 0xbf, 0x39, 0xb5, 0x8f, 0x1c, 0xb3, 0x7a, - 0xfb, 0x99, 0x13, 0x03, 0xc0, 0xfb, 0x74, 0x8a, 0xaf, 0x24, 0xba, 0x8b, - 0x15, 0x7d, 0x49, 0xff, 0x02, 0x49, 0x0b, 0xd2, 0xff, 0xe0, 0x8a, 0x9f, - 0xf3, 0x9c, 0x1e, 0x2c, 0xc9, 0x56, 0x8b, 0xdc, 0x0f, 0x28, 0x36, 0x66, - 0x08, 0xc1, 0x86, 0x13, 0xf9, 0xbc, 0x0a, 0xf4, 0xf6, 0xe9, 0xb0, 0xe6, - 0x34, 0x92, 0x86, 0x12, 0x5d, 0x40, 0x31, 0xf9, 0x65, 0x32, 0x7b, 0x41, - 0x1b, 0xff, 0x83, 0x6e, 0xb7, 0x79, 0x4b, 0x70, 0x61, 0x79, 0x0b, 0xa2, - 0x06, 0xf6, 0x92, 0x22, 0xbd, 0x43, 0x49, 0xd0, 0x06, 0x59, 0xf9, 0xcb, - 0xb5, 0xef, 0x54, 0x66, 0x46, 0xe2, 0x15, 0xd8, 0xda, 0x83, 0x59, 0xcf, - 0x00, 0x3a, 0x1d, 0x2f, 0xd2, 0x9f, 0x61, 0xf7, 0xb0, 0xd7, 0xeb, 0x59, - 0x9c, 0xc9, 0xab, 0x7b, 0xf2, 0x39, 0x22, 0x52, 0x6e, 0x56, 0x27, 0x17, - 0xb0, 0xcf, 0xda, 0x68, 0xeb, 0xf5, 0x4d, 0xee, 0x56, 0x42, 0xc1, 0x36, - 0x57, 0xf2, 0xa4, 0xf5, 0x27, 0xfc, 0xb1, 0x4c, 0xb0, 0x39, 0x2e, 0xb5, - 0x94, 0xc7, 0x3a, 0xd8, 0xf9, 0x99, 0xa6, 0x37, 0xba, 0x9a, 0xed, 0x13, - 0xd6, 0x52, 0x2b, 0xe3, 0x7e, 0xb8, 0x28, 0x3a, 0x8f, 0xe3, 0xd1, 0x61, - 0x7d, 0x6f, 0xff, 0x65, 0xd2, 0xf2, 0x77, 0xf0, 0xa9, 0x5c, 0xfc, 0x73, - 0x02, 0x49, 0x8d, 0x92, 0x67, 0x07, 0xfc, 0x57, 0xc0, 0xa6, 0x78, 0xd9, - 0x31, 0xa2, 0xbd, 0x5d, 0xb9, 0x75, 0x6c, 0x9f, 0x72, 0xa3, 0xf3, 0x32, - 0x7c, 0x4f, 0x98, 0x74, 0xd0, 0xde, 0x02, 0x3e, 0x89, 0x10, 0x88, 0x74, - 0x5a, 0x00, 0x0e, 0xdd, 0xbb, 0xcb, 0x2a, 0x31, 0xf5, 0xa0, 0xb7, 0x48, - 0x7b, 0x61, 0x84, 0xe7, 0x81, 0xd0, 0xae, 0xcb, 0x14, 0x3c, 0xab, 0x43, - 0x90, 0x46, 0xf2, 0xb1, 0x0e, 0x28, 0x0f, 0x8a, 0x1f, 0x5f, 0x42, 0x0e, - 0x9d, 0x11, 0xf7, 0x01, 0xe4, 0xd3, 0x5a, 0x88, 0x75, 0x2d, 0x44, 0x26, - 0x20, 0x24, 0x77, 0x36, 0xd8, 0xc9, 0x69, 0x0d, 0x9d, 0x93, 0xb3, 0x12, - 0x80, 0xa4, 0x1b, 0x72, 0xfa, 0xb9, 0xf2, 0x46, 0x81, 0xaf, 0x79, 0xd4, - 0xe3, 0x9a, 0xc5, 0x8a, 0x1a, 0x0b, 0xd1, 0x7b, 0x9b, 0x6c, 0xe1, 0x38, - 0x08, 0x61, 0x37, 0x95, 0x1c, 0xd5, 0x9c, 0x47, 0xea, 0xc5, 0xad, 0xcd, - 0x73, 0xb6, 0x3c, 0x88, 0x06, 0x86, 0xd2, 0xe3, 0x9c, 0x76, 0x53, 0x5d, - 0xaf, 0xdc, 0x31, 0x0c, 0xda, 0x80, 0x63, 0x40, 0x40, 0xb8, 0x2e, 0xf6, - 0x03, 0x38, 0x36, 0xdb, 0xa0, 0xc1, 0x20, 0xb6, 0x25, 0xe6, 0x36, 0x68, - 0xb4, 0x7a, 0xb9, 0x35, 0xe2, 0x96, 0xbc, 0xe2, 0xc2, 0xe7, 0xb6, 0x78, - 0x5b, 0x16, 0x89, 0xb3, 0xc8, 0xad, 0xca, 0x44, 0xc4, 0x9a, 0x42, 0xc1, - 0x2a, 0x98, 0xaa, 0x73, 0x6f, 0x58, 0x27, 0xcf, 0x78, 0x2e, 0xc0, 0x27, - 0x45, 0xd8, 0x55, 0x3e, 0x80, 0xd3, 0x23, 0xba, 0xca, 0x8b, 0x70, 0x40, - 0xc3, 0x7f, 0x0f, 0x0e, 0x32, 0xe9, 0x0a, 0x5c, 0x83, 0xd1, 0x4f, 0xf4, - 0x1c, 0xbd, 0x8a, 0x89, 0x38, 0xa8, 0x11, 0xf5, 0xa3, 0x5f, 0x7e, 0xd1, - 0xd2, 0x46, 0x90, 0x86, 0x76, 0x03, 0xc6, 0x5b, 0x1d, 0xf2, 0xf0, 0x75, - 0x34, 0x17, 0x6c, 0xe4, 0xfc, 0xea, 0xe4, 0xf9, 0xe7, 0x9f, 0x46, 0xd0, - 0xcd, 0x3f, 0xfd, 0xfc, 0xfd, 0xa7, 0xc6, 0x63, 0x62, 0x95, 0xf7, 0x24, - 0x79, 0xef, 0x76, 0x5f, 0x0d, 0xe7, 0xf8, 0x0f, 0x7e, 0x3b, 0x9c, 0x91, - 0x6d, 0x74, 0x59, 0x30, 0xec, 0x59, 0x19, 0x06, 0x03, 0xcc, 0xd9, 0x88, - 0xda, 0xfa, 0x88, 0x48, 0x6c, 0x74, 0x79, 0xd7, 0xdd, 0x64, 0x6f, 0xb3, - 0x4d, 0xb5, 0xfa, 0xa3, 0x99, 0x0f, 0xe4, 0x2f, 0x41, 0xf1, 0x82, 0x94, - 0x54, 0x90, 0xc3, 0x23, 0x60, 0x81, 0x2e, 0x0c, 0x7e, 0xf5, 0xfc, 0xf3, - 0x2f, 0x3e, 0x79, 0xf7, 0x3b, 0x5d, 0xde, 0xc2, 0x2e, 0x23, 0x38, 0xbf, - 0x7e, 0x1d, 0x93, 0x6f, 0x60, 0x58, 0x7d, 0xaf, 0x01, 0x07, 0xe7, 0xd3, - 0x0b, 0xcb, 0x4e, 0xd9, 0x48, 0xe0, 0x6a, 0xca, 0x74, 0x18, 0xc2, 0x43, - 0x59, 0x2e, 0x8a, 0x79, 0x6a, 0xf9, 0x3a, 0xab, 0x25, 0xd3, 0xf6, 0xf3, - 0x6f, 0x4e, 0x18, 0xda, 0x9f, 0x53, 0x76, 0x97, 0x3e, 0x0a, 0xcd, 0x6f, - 0xa6, 0x1f, 0x52, 0xe3, 0xb6, 0xd3, 0x54, 0xbd, 0xeb, 0x71, 0x90, 0xda, - 0xce, 0xb7, 0x55, 0x07, 0x54, 0x3a, 0x46, 0x40, 0x37, 0xa4, 0x76, 0xf9, - 0x6f, 0x6a, 0xd4, 0x1b, 0x4c, 0xa3, 0x9e, 0x7f, 0xfd, 0xaf, 0xa9, 0x1e, - 0x02, 0x87, 0xd7, 0xef, 0x4d, 0x3e, 0x42, 0x3c, 0xed, 0xf7, 0x0e, 0xfa, - 0xff, 0x9a, 0x3a, 0x36, 0x69, 0xc2, 0xa3, 0x7d, 0x5e, 0xc5, 0x0f, 0xd2, - 0x2c, 0x19, 0xec, 0xf7, 0x07, 0xff, 0x9a, 0x5a, 0x32, 0xe0, 0xda, 0xd7, - 0xc7, 0xff, 0x74, 0x0d, 0x10, 0xf8, 0x2f, 0xab, 0x82, 0xf5, 0x16, 0xb7, - 0xde, 0x5a, 0xfb, 0x8d, 0x02, 0x1d, 0xb4, 0x56, 0x17, 0x17, 0x8d, 0xc2, - 0x36, 0xc9, 0xa1, 0x72, 0x2b, 0x09, 0x36, 0xd5, 0x03, 0x5b, 0x90, 0x0d, - 0x10, 0xfc, 0x4a, 0x6f, 0xbb, 0xb9, 0xde, 0x52, 0x54, 0xff, 0x38, 0x20, - 0x94, 0xdb, 0x36, 0x8e, 0x3a, 0xc3, 0xf4, 0x7a, 0xea, 0x36, 0xa3, 0xb2, - 0x76, 0x5b, 0xf0, 0x09, 0x78, 0xdb, 0x4d, 0xb8, 0x08, 0xb1, 0x29, 0x97, - 0x8a, 0x46, 0x38, 0x27, 0xa9, 0x57, 0xda, 0x15, 0x6c, 0x3b, 0x94, 0x07, - 0x98, 0x1d, 0xd4, 0xf1, 0x90, 0x77, 0xef, 0xf1, 0x65, 0xfb, 0x30, 0x47, - 0x51, 0x60, 0xd8, 0xf5, 0xa8, 0x88, 0x71, 0x91, 0x14, 0x54, 0x19, 0x42, - 0x3e, 0xc7, 0xe2, 0xee, 0xa4, 0xb7, 0x0a, 0x52, 0x99, 0x24, 0xe0, 0x1d, - 0xe4, 0x78, 0x13, 0x66, 0x9e, 0x64, 0x25, 0x90, 0xca, 0x8e, 0x7e, 0x22, - 0xbc, 0xaf, 0x7b, 0xd0, 0x5a, 0x1e, 0xc7, 0x06, 0x08, 0xb7, 0xd1, 0x02, - 0x37, 0xf4, 0x03, 0xe8, 0x9f, 0xb0, 0x84, 0xce, 0x17, 0x17, 0x73, 0xcd, - 0x7b, 0x15, 0xa5, 0xa3, 0x39, 0xa0, 0x0e, 0x2e, 0xb9, 0xb0, 0xf9, 0xd8, - 0xb7, 0x6d, 0x0b, 0x7c, 0xd4, 0x2e, 0xe4, 0x96, 0x77, 0xbc, 0xe8, 0xe6, - 0x3a, 0x2f, 0x90, 0xa4, 0x66, 0xc8, 0x8c, 0xb4, 0x06, 0xe7, 0x8b, 0x06, - 0xde, 0x3b, 0x80, 0xa7, 0x9f, 0x11, 0x76, 0xa2, 0xcb, 0x13, 0xe6, 0x0e, - 0x1a, 0x2f, 0x03, 0x0d, 0xeb, 0xec, 0xbb, 0x8b, 0x0a, 0x99, 0x1a, 0x46, - 0x20, 0xf8, 0xe8, 0x5e, 0x59, 0xca, 0x8b, 0x58, 0x8a, 0x3c, 0x75, 0x68, - 0xee, 0xa4, 0x76, 0xac, 0x33, 0x57, 0x56, 0xca, 0xdc, 0x4a, 0x99, 0x9c, - 0xb5, 0x15, 0x4b, 0x14, 0x7c, 0x4a, 0x4e, 0xf2, 0x54, 0xc3, 0xd4, 0xc0, - 0xe6, 0xca, 0x4e, 0x9a, 0xdb, 0x49, 0x93, 0x41, 0x28, 0x63, 0x07, 0x1e, - 0xc6, 0xea, 0x38, 0x3b, 0xb0, 0x39, 0xb3, 0x93, 0xe6, 0x76, 0xd2, 0xe4, - 0x40, 0xe3, 0xec, 0x1e, 0x3f, 0x79, 0x10, 0x14, 0xe5, 0xcd, 0x09, 0xf8, - 0xce, 0xc3, 0xa0, 0xd0, 0x65, 0xa5, 0xf1, 0xf2, 0xa7, 0x71, 0xd5, 0x34, - 0xe1, 0x11, 0xab, 0x13, 0xbd, 0x65, 0x71, 0xce, 0xa0, 0x29, 0x78, 0x1e, - 0xbf, 0xe9, 0x84, 0xc1, 0x79, 0x01, 0x9b, 0x65, 0x20, 0xee, 0x31, 0x4b, - 0x8b, 0x1f, 0x0d, 0x66, 0x04, 0xa7, 0x05, 0xbb, 0xb8, 0x5a, 0xaf, 0x96, - 0x40, 0x98, 0xd5, 0x7b, 0x5a, 0x8a, 0x27, 0x4b, 0x8a, 0x4d, 0xb6, 0x8c, - 0xe2, 0xd6, 0x3e, 0x0a, 0x86, 0x59, 0x0a, 0xc8, 0xee, 0x15, 0xab, 0x93, - 0x22, 0x03, 0x9b, 0x16, 0x43, 0x84, 0x5c, 0x18, 0x81, 0x17, 0x29, 0x4c, - 0x7d, 0xba, 0x03, 0x4c, 0xff, 0x6a, 0xbd, 0x86, 0x1d, 0xa6, 0x71, 0x9e, - 0xc4, 0x96, 0x19, 0x92, 0x82, 0x85, 0x2f, 0x56, 0x11, 0x92, 0x07, 0x01, - 0x02, 0xbb, 0x84, 0x6d, 0x28, 0xd5, 0x91, 0xd1, 0xf7, 0x65, 0x0c, 0x7c, - 0x19, 0xd0, 0x00, 0x36, 0x3f, 0xab, 0xe5, 0x09, 0x99, 0x09, 0x6a, 0x03, - 0x16, 0xcf, 0x4f, 0xeb, 0x66, 0x2f, 0x38, 0x96, 0x22, 0xb5, 0x98, 0x40, - 0xeb, 0x95, 0x30, 0xba, 0x84, 0xdc, 0x5b, 0x67, 0xf4, 0xf9, 0x7e, 0x72, - 0x31, 0xde, 0x2c, 0x0a, 0x92, 0x80, 0xa4, 0xc6, 0x40, 0xe4, 0xe3, 0x29, - 0xc5, 0x6a, 0x33, 0xbd, 0xc4, 0x67, 0x5e, 0xa5, 0x89, 0x13, 0x74, 0x29, - 0x02, 0x23, 0x87, 0x1f, 0x67, 0xd0, 0x76, 0xd2, 0xce, 0x61, 0x99, 0x90, - 0x69, 0xb8, 0x49, 0x37, 0x4f, 0xa2, 0x4f, 0xc7, 0xc5, 0x65, 0x8f, 0x1c, - 0xa0, 0x58, 0xc5, 0x7c, 0x8e, 0xa5, 0xd0, 0x8e, 0x6b, 0x6f, 0x0d, 0x93, - 0xdb, 0x6f, 0xa3, 0x2e, 0x50, 0xef, 0x81, 0x61, 0x05, 0xd3, 0xf2, 0x49, - 0x72, 0x51, 0xb4, 0x3b, 0x3a, 0xa5, 0xdb, 0x50, 0x4a, 0xdf, 0x49, 0x4a, - 0x98, 0xb7, 0x6e, 0x2b, 0xa6, 0x58, 0xa8, 0xba, 0xbf, 0xf2, 0x14, 0xc7, - 0x0b, 0x2b, 0xbe, 0x45, 0xc5, 0x58, 0x91, 0xdf, 0x86, 0x70, 0xce, 0x40, - 0xbf, 0x73, 0xf3, 0x26, 0xdb, 0x91, 0x47, 0x80, 0xe5, 0xdd, 0x86, 0x7a, - 0xda, 0xb3, 0x2b, 0xa8, 0xe3, 0xfb, 0xd0, 0xfe, 0x31, 0xf0, 0xd5, 0xbb, - 0xe9, 0x44, 0xf8, 0x71, 0x0b, 0x97, 0xea, 0xe0, 0xbf, 0x36, 0xdd, 0x3e, - 0x43, 0x42, 0x32, 0x94, 0xf5, 0x39, 0xa7, 0x21, 0x95, 0x9c, 0x12, 0x8c, - 0x00, 0xa0, 0x64, 0x80, 0x7c, 0xf6, 0x1b, 0xe2, 0x3d, 0x61, 0xa0, 0x27, - 0x3d, 0x93, 0xe1, 0x1b, 0x06, 0xe5, 0xb4, 0x05, 0x25, 0x42, 0x8f, 0xe4, - 0x24, 0xcf, 0xa2, 0x91, 0x64, 0xc1, 0x83, 0x90, 0xe9, 0xe0, 0xe2, 0x4a, - 0x84, 0x07, 0x7a, 0xee, 0x82, 0xee, 0xfb, 0xa0, 0x27, 0x2e, 0xe8, 0x81, - 0x0f, 0xfa, 0x5a, 0x81, 0x96, 0x63, 0xb8, 0x3c, 0x08, 0xac, 0x73, 0x67, - 0x9c, 0xf5, 0xb5, 0x99, 0x91, 0xc7, 0x79, 0xed, 0xa2, 0xed, 0x43, 0x4c, - 0xf6, 0x1e, 0x32, 0xb6, 0x90, 0x77, 0x7f, 0xdc, 0xbf, 0xd3, 0xed, 0xdc, - 0x73, 0x37, 0x36, 0x3c, 0xec, 0x57, 0x85, 0x34, 0xf3, 0xc2, 0xb5, 0x4d, - 0xeb, 0x04, 0x42, 0x03, 0xe9, 0x6a, 0xf2, 0x97, 0x18, 0x3b, 0x62, 0xbf, - 0x13, 0xc1, 0x7f, 0xdc, 0x8c, 0x5f, 0xa7, 0xb3, 0xe2, 0xb2, 0xfc, 0x75, - 0x99, 0xa0, 0xdf, 0xa0, 0x0c, 0x2c, 0x82, 0x76, 0xc8, 0x9b, 0x4d, 0x6a, - 0xa9, 0xc4, 0x26, 0xa5, 0x43, 0x35, 0x6c, 0xc7, 0x4d, 0x02, 0x7d, 0x83, - 0x83, 0x4d, 0xac, 0x94, 0x58, 0x16, 0xba, 0xf7, 0xea, 0xab, 0x1c, 0xf4, - 0xd5, 0xe8, 0x7d, 0x80, 0xcc, 0x79, 0xa7, 0xc2, 0x51, 0x42, 0x64, 0xec, - 0x49, 0xd9, 0x28, 0xd4, 0x34, 0x8b, 0x3a, 0x4d, 0xa0, 0xfe, 0xd9, 0xb7, - 0xd1, 0x48, 0xab, 0x71, 0xb4, 0x17, 0x0d, 0x86, 0x26, 0xd0, 0x77, 0x00, - 0xa4, 0x09, 0x42, 0x40, 0xd9, 0x17, 0x38, 0x39, 0xd5, 0x8e, 0xc0, 0x0c, - 0x92, 0x27, 0x96, 0x44, 0xf7, 0xe3, 0xbf, 0x84, 0x1d, 0xe7, 0x4d, 0x6e, - 0xb3, 0xf4, 0xb8, 0x77, 0xa8, 0x80, 0xc2, 0x96, 0xb3, 0x02, 0x1a, 0x6b, - 0xb0, 0xdd, 0xa8, 0xbf, 0xdf, 0xd6, 0xd9, 0x23, 0xf0, 0x68, 0xb2, 0xca, - 0x40, 0xe1, 0x30, 0x51, 0x36, 0xfd, 0x24, 0x99, 0xa7, 0xcb, 0x2f, 0xc0, - 0x92, 0xc5, 0x6d, 0x13, 0x9c, 0xb5, 0x9d, 0x0e, 0x3e, 0xce, 0xa6, 0x76, - 0xfd, 0x54, 0x6e, 0x48, 0x7f, 0x06, 0xd0, 0x2c, 0x64, 0x1d, 0xbf, 0x78, - 0xd6, 0x61, 0x1b, 0xbf, 0x92, 0x38, 0xb5, 0x05, 0x5e, 0xfb, 0xd5, 0x98, - 0x7a, 0x12, 0xc5, 0x60, 0x06, 0x73, 0xca, 0x5c, 0x46, 0x63, 0xb2, 0xaa, - 0x08, 0xc4, 0x99, 0x78, 0xa1, 0xad, 0xb3, 0xb1, 0x48, 0x97, 0xc9, 0x37, - 0x54, 0xd9, 0x51, 0xf4, 0x78, 0xa8, 0xe7, 0xb1, 0xb0, 0x05, 0x27, 0x38, - 0x4f, 0x87, 0xdc, 0xd6, 0x8b, 0xfb, 0xf4, 0xd7, 0x72, 0x42, 0xc5, 0x6d, - 0x23, 0x99, 0xee, 0xf6, 0x97, 0xe2, 0x28, 0x79, 0xbe, 0x48, 0x17, 0x0b, - 0x16, 0xed, 0x6e, 0x92, 0x8c, 0x37, 0x45, 0x7a, 0xb1, 0x59, 0x88, 0x20, - 0xc3, 0x02, 0xa4, 0x18, 0xff, 0x90, 0x2c, 0xe9, 0xd2, 0x31, 0x1d, 0x4a, - 0x7a, 0x12, 0x5d, 0x16, 0xc5, 0x1a, 0xc2, 0x55, 0xe5, 0x05, 0xac, 0x15, - 0xc0, 0xb8, 0x9b, 0x5d, 0x2c, 0x56, 0xd7, 0x60, 0x95, 0xae, 0xf6, 0x7e, - 0xdc, 0x24, 0x39, 0x6d, 0x9c, 0xee, 0xf5, 0xdf, 0x18, 0x1c, 0x1d, 0xbe, - 0xb1, 0xff, 0x78, 0x6f, 0xb2, 0x49, 0x17, 0x78, 0xd0, 0xa0, 0x3b, 0xee, - 0x12, 0xd9, 0x2e, 0xf9, 0x59, 0xdd, 0x74, 0xd9, 0xbd, 0x2c, 0xae, 0x16, - 0x87, 0xc6, 0xf3, 0x7e, 0x60, 0x1c, 0x16, 0xcc, 0xc4, 0xf0, 0xaf, 0x6f, - 0x81, 0x93, 0x79, 0x54, 0xfe, 0x7a, 0xcd, 0xf0, 0xcf, 0xe5, 0x6b, 0xcf, - 0xef, 0x72, 0xc4, 0x98, 0x01, 0x76, 0xc1, 0x67, 0x96, 0x2d, 0x05, 0x1a, - 0xd3, 0x7f, 0xc3, 0x7c, 0x76, 0x00, 0x3c, 0x55, 0x81, 0x44, 0x38, 0x1e, - 0x70, 0x9f, 0x46, 0xd9, 0xb9, 0xe8, 0x82, 0x3c, 0x5f, 0x59, 0x3a, 0x24, - 0x40, 0x4d, 0x5d, 0xd3, 0x07, 0x5d, 0x81, 0x65, 0xa7, 0x02, 0x09, 0x3d, - 0x55, 0xd5, 0x49, 0x23, 0x47, 0x8a, 0xc2, 0xc8, 0x80, 0xca, 0xba, 0x92, - 0x49, 0x81, 0x65, 0x92, 0x60, 0xd5, 0xa7, 0x36, 0x76, 0x2e, 0x6a, 0x4f, - 0xa9, 0x8f, 0x97, 0xf9, 0x22, 0x86, 0x31, 0x49, 0xb4, 0x15, 0xee, 0x7b, - 0x63, 0xc4, 0x0e, 0x3c, 0x89, 0xf1, 0x72, 0xbb, 0xe5, 0xc1, 0x8e, 0xc3, - 0x0a, 0xbd, 0x97, 0x2a, 0x8b, 0xc6, 0xa4, 0x49, 0x97, 0x2f, 0x2e, 0xd3, - 0xbc, 0x57, 0xdd, 0xcb, 0x33, 0x26, 0x4c, 0x55, 0x7e, 0x52, 0x64, 0x40, - 0x7d, 0x83, 0x70, 0xc7, 0x0b, 0xb8, 0x7d, 0x7f, 0x9d, 0x62, 0x8f, 0x0f, - 0xb1, 0x1c, 0xc0, 0x65, 0xb8, 0xe5, 0x40, 0x49, 0xa0, 0x51, 0xe0, 0xe8, - 0xd2, 0x1a, 0x5e, 0xdd, 0x9e, 0xcf, 0x91, 0x3b, 0x48, 0x96, 0x7e, 0x15, - 0x7f, 0xcd, 0xf2, 0x13, 0x30, 0x15, 0xe3, 0xec, 0x43, 0x96, 0x2d, 0x06, - 0xb8, 0xfe, 0xeb, 0xf8, 0x29, 0x48, 0x4b, 0x74, 0x7a, 0xc2, 0x88, 0xdd, - 0x69, 0x2b, 0x56, 0x6b, 0x04, 0x86, 0xfd, 0x68, 0x7c, 0xfd, 0xa7, 0x16, - 0x14, 0x3c, 0x35, 0xb1, 0xff, 0x4c, 0x86, 0xc3, 0xd3, 0xfe, 0x2a, 0x81, - 0xa1, 0x17, 0x4a, 0x90, 0x02, 0x08, 0xa7, 0x26, 0x58, 0xb6, 0x94, 0xb7, - 0x36, 0x9a, 0x45, 0xbf, 0xa1, 0x1c, 0xec, 0xce, 0x50, 0xd6, 0x0e, 0xcc, - 0xcc, 0x8c, 0xbb, 0x87, 0x66, 0xe9, 0x0d, 0x08, 0xa3, 0xb5, 0x48, 0x0a, - 0xae, 0x6d, 0xde, 0xa1, 0x99, 0x60, 0x52, 0x74, 0x9b, 0xad, 0x16, 0x97, - 0xce, 0x34, 0x68, 0x53, 0xa9, 0xb5, 0xf2, 0x7b, 0x5b, 0x52, 0x20, 0xf7, - 0x17, 0x08, 0x10, 0x21, 0xe1, 0x67, 0x2b, 0xd6, 0x16, 0x41, 0x6e, 0x20, - 0xbf, 0xcb, 0x30, 0x87, 0xf0, 0xe3, 0xad, 0xa8, 0xfc, 0xae, 0xef, 0xbf, - 0x4b, 0x8c, 0x5b, 0x15, 0xe3, 0x56, 0xc1, 0xb8, 0x35, 0x30, 0x04, 0x17, - 0xa7, 0x19, 0x78, 0xfc, 0x97, 0x29, 0x3a, 0xa8, 0x37, 0xb7, 0x83, 0xf5, - 0x6a, 0x31, 0xce, 0x62, 0x98, 0x04, 0xdc, 0x22, 0xa7, 0x8e, 0x10, 0x10, - 0xd1, 0xdb, 0x9c, 0xa2, 0x24, 0x66, 0x84, 0xbb, 0xfe, 0x21, 0x5d, 0x53, - 0x7c, 0x6b, 0xa0, 0x72, 0xdb, 0x06, 0xf1, 0x80, 0x15, 0x48, 0x97, 0x20, - 0x9a, 0x1c, 0x94, 0x65, 0x5c, 0xc0, 0xf8, 0x4a, 0xa3, 0x6f, 0x9e, 0xce, - 0xe0, 0xf3, 0x42, 0x19, 0x67, 0x9d, 0x27, 0xfa, 0xc0, 0xb5, 0xdb, 0x38, - 0x4e, 0x6e, 0xd9, 0xd5, 0x98, 0xd1, 0xe5, 0x16, 0x60, 0x6d, 0x00, 0xdf, - 0x62, 0xa8, 0x90, 0xc5, 0x3f, 0xad, 0xc7, 0xa5, 0xf3, 0x0d, 0x2b, 0x9f, - 0x0a, 0x26, 0x6b, 0x82, 0x67, 0xec, 0x68, 0x91, 0x92, 0xb1, 0x93, 0xe6, - 0xd1, 0x3a, 0xbd, 0x49, 0x16, 0x90, 0x46, 0x30, 0xd4, 0x3c, 0xac, 0xad, - 0x28, 0x12, 0x51, 0xcf, 0x2e, 0x3b, 0x5b, 0x5d, 0x7f, 0xc2, 0x0e, 0xdc, - 0x8e, 0x94, 0xa6, 0x1e, 0xda, 0x80, 0xe3, 0xd9, 0xf7, 0x9b, 0xbc, 0x48, - 0x66, 0xdf, 0xa2, 0xb0, 0xc1, 0xfe, 0x72, 0x40, 0xee, 0xc4, 0xc1, 0x38, - 0x0d, 0x2d, 0xce, 0x86, 0xf1, 0xd3, 0xee, 0x21, 0x45, 0xb3, 0x3d, 0xc3, - 0x58, 0x42, 0xa7, 0xfb, 0x68, 0xa7, 0xe1, 0x7b, 0x0c, 0x0c, 0xa9, 0x12, - 0x05, 0x8e, 0x9d, 0x3c, 0xb6, 0xfd, 0x45, 0xa3, 0x2f, 0x79, 0xeb, 0x2e, - 0xfa, 0x76, 0x47, 0x45, 0x93, 0x38, 0xa5, 0xc7, 0x84, 0x45, 0x26, 0xb0, - 0x8c, 0xcc, 0xc5, 0x9c, 0x25, 0x3f, 0x6e, 0xd2, 0x0c, 0x08, 0x3e, 0x8e, - 0xf2, 0xc5, 0xaa, 0xc8, 0x85, 0xdc, 0x25, 0x49, 0x9b, 0x22, 0x35, 0x17, - 0xf9, 0x12, 0x42, 0xa0, 0x50, 0xa3, 0x58, 0x56, 0xf1, 0x55, 0xd9, 0x24, - 0x6d, 0xf4, 0x32, 0x24, 0x07, 0x43, 0x97, 0xee, 0x5c, 0xd2, 0xa4, 0x09, - 0xf4, 0xc6, 0xd1, 0x64, 0xf9, 0x18, 0x16, 0x6d, 0xc6, 0x3c, 0x84, 0x5d, - 0x16, 0xed, 0xf9, 0x1b, 0x57, 0x4c, 0xbe, 0xfa, 0xbd, 0x7d, 0x67, 0x29, - 0xa7, 0x30, 0x49, 0xea, 0xb0, 0x19, 0x5e, 0x87, 0xe6, 0x72, 0x34, 0x99, - 0xcd, 0x7f, 0x1a, 0xc0, 0x3c, 0x3a, 0x06, 0x16, 0x3a, 0x4a, 0x59, 0x1d, - 0x46, 0xad, 0xed, 0xd2, 0xa1, 0xc5, 0xfa, 0x72, 0x8c, 0x8a, 0x76, 0x78, - 0x68, 0x16, 0x43, 0x32, 0x3b, 0x25, 0xe1, 0x20, 0x6d, 0x28, 0x6f, 0xe8, - 0xcb, 0x07, 0x79, 0xf5, 0x01, 0x86, 0xb1, 0x53, 0x05, 0x35, 0x00, 0x28, - 0xe2, 0xb6, 0x0a, 0xe8, 0x00, 0x80, 0x18, 0x63, 0xbe, 0x65, 0x6a, 0x7d, - 0x8c, 0x5f, 0x6f, 0x94, 0x55, 0x07, 0xd2, 0x20, 0x1a, 0x19, 0xf7, 0x8d, - 0x45, 0x61, 0xdd, 0x20, 0xe9, 0x16, 0x1a, 0x0a, 0xa4, 0xb1, 0x3a, 0xff, - 0x31, 0x2b, 0xe2, 0x1b, 0x68, 0x63, 0xe4, 0xe3, 0x16, 0x3e, 0x6f, 0x55, - 0x13, 0x0b, 0x76, 0x40, 0x00, 0x42, 0x51, 0xcb, 0x41, 0x0c, 0xeb, 0x1a, - 0x37, 0x04, 0x20, 0xd7, 0xe3, 0x84, 0x01, 0x34, 0xca, 0x16, 0xa6, 0x04, - 0x3e, 0xd5, 0x28, 0xc8, 0xf0, 0x13, 0xd4, 0x0f, 0x3a, 0xc9, 0xef, 0xbf, - 0x75, 0xa2, 0xdf, 0x7f, 0x3b, 0x83, 0x04, 0x98, 0x2e, 0x8b, 0x6c, 0x41, - 0x13, 0x10, 0x41, 0xb0, 0x04, 0x08, 0xf5, 0x02, 0xff, 0x58, 0xc2, 0xc9, - 0x82, 0x63, 0xa4, 0x0d, 0x5c, 0x73, 0x9f, 0x03, 0xa7, 0x4d, 0xb1, 0xe2, - 0x83, 0x90, 0xe6, 0x02, 0xaa, 0xce, 0x57, 0x8d, 0xc6, 0x68, 0x42, 0x9a, - 0x5e, 0x42, 0x7f, 0x06, 0x5d, 0x61, 0x59, 0x40, 0x4d, 0x82, 0x2b, 0x32, - 0x02, 0x42, 0x7d, 0x80, 0x81, 0x0f, 0x60, 0x00, 0x8a, 0x93, 0x39, 0xd0, - 0xc5, 0x38, 0x0d, 0xc0, 0x8d, 0xfb, 0x51, 0x97, 0x4b, 0x72, 0x92, 0xc7, - 0x31, 0x61, 0xbd, 0x8c, 0x4e, 0x7c, 0x17, 0x3c, 0x7e, 0x55, 0xe6, 0x59, - 0x1f, 0xb4, 0x1c, 0xfe, 0x9f, 0xf4, 0xb5, 0x45, 0x41, 0x42, 0x78, 0x1b, - 0x26, 0x0e, 0x70, 0x86, 0x8b, 0xca, 0xb4, 0x03, 0x7b, 0xc6, 0xa7, 0x12, - 0x17, 0x35, 0xea, 0x94, 0x15, 0x0e, 0x4d, 0x06, 0xba, 0x71, 0xa6, 0xcf, - 0xd7, 0x35, 0x9a, 0x7d, 0x95, 0xe6, 0xa0, 0x9a, 0x26, 0xd0, 0x62, 0x64, - 0x6b, 0x68, 0x0e, 0x54, 0x9a, 0x07, 0xd5, 0x34, 0xf7, 0x25, 0xcd, 0x9b, - 0x2a, 0x9a, 0x07, 0x2a, 0xcd, 0xc7, 0xb5, 0x34, 0x4b, 0x56, 0xab, 0x68, - 0x3e, 0x56, 0x69, 0x1e, 0xd6, 0xd6, 0x7d, 0x3f, 0x84, 0xe6, 0xa1, 0x4a, - 0xf3, 0x28, 0xac, 0x8d, 0xf6, 0x65, 0xdd, 0xa9, 0xd3, 0x4b, 0x85, 0xb8, - 0x2a, 0x35, 0xb0, 0xcb, 0xcb, 0x26, 0x28, 0xe9, 0x7e, 0xcc, 0x81, 0x18, - 0xd1, 0xa2, 0xa0, 0x60, 0x57, 0x90, 0xc0, 0x3f, 0x27, 0xf4, 0x79, 0xa6, - 0x78, 0x9d, 0xe2, 0xbe, 0x46, 0xd6, 0x99, 0x77, 0x26, 0x44, 0x55, 0x04, - 0xf3, 0x02, 0x81, 0xf5, 0xc5, 0x90, 0x05, 0xb6, 0xf1, 0x4c, 0xef, 0xe3, - 0x90, 0x02, 0x3a, 0x0c, 0x65, 0xb1, 0x2f, 0x73, 0xfe, 0x05, 0xca, 0xb5, - 0xd6, 0xca, 0xe9, 0x22, 0xd8, 0x02, 0xc6, 0xb8, 0x18, 0x23, 0xb9, 0xaa, - 0xeb, 0x58, 0x94, 0xd0, 0xc3, 0x7f, 0x9e, 0x8b, 0x45, 0x26, 0x6a, 0x51, - 0x4a, 0xa6, 0xf1, 0x2a, 0x5d, 0x96, 0xb1, 0xcb, 0x7a, 0xfa, 0x63, 0x06, - 0x12, 0xc8, 0x1f, 0x80, 0xf0, 0xb4, 0x84, 0x39, 0x93, 0x72, 0xf4, 0x97, - 0x4d, 0x5a, 0x5f, 0x26, 0xd3, 0xc1, 0x25, 0xba, 0x6a, 0x74, 0x72, 0xfc, - 0xe5, 0xb3, 0x2f, 0x9e, 0xe3, 0xba, 0x57, 0xf5, 0xcb, 0x06, 0x84, 0x3a, - 0xc5, 0x87, 0xee, 0xf1, 0xde, 0x64, 0xf5, 0x1b, 0x07, 0x52, 0x28, 0x06, - 0x16, 0x1c, 0xfa, 0x74, 0x9d, 0x7b, 0x20, 0xa1, 0x8a, 0xfd, 0x1c, 0xfb, - 0x75, 0x8b, 0xd6, 0xfb, 0x9f, 0x7f, 0x4a, 0xbb, 0x34, 0x90, 0xb6, 0x1a, - 0xcf, 0x92, 0x19, 0xcc, 0x44, 0x45, 0x03, 0x94, 0xdb, 0x13, 0xb2, 0xcd, - 0xa1, 0x20, 0x6c, 0xd9, 0x6c, 0xb3, 0x8c, 0xf2, 0x74, 0x39, 0x4d, 0x22, - 0x40, 0xc7, 0xe0, 0x8b, 0x0b, 0xc2, 0xa5, 0x17, 0x55, 0x32, 0x8c, 0xdb, - 0xc8, 0x17, 0x51, 0x93, 0x82, 0xee, 0x69, 0x89, 0x79, 0x03, 0xe5, 0xc9, - 0x0b, 0x05, 0xde, 0x68, 0xb9, 0x7a, 0x1c, 0x4e, 0x51, 0xba, 0x16, 0x61, - 0xb3, 0x2c, 0x80, 0x85, 0x30, 0x10, 0x98, 0xfa, 0x3c, 0x01, 0xfa, 0xa4, - 0x78, 0x42, 0x51, 0x5f, 0x6f, 0x93, 0x39, 0xde, 0x87, 0xd8, 0xb5, 0x7b, - 0x52, 0x6f, 0xed, 0xe5, 0xd3, 0x2c, 0x5d, 0x17, 0x6f, 0x43, 0x12, 0xfd, - 0x9c, 0xac, 0x66, 0xb7, 0xf0, 0xe3, 0xad, 0x3d, 0x5c, 0x99, 0x81, 0x2f, - 0x7f, 0x00, 0x39, 0x32, 0x9d, 0xe3, 0x7a, 0xa8, 0x01, 0x00 + 0x36, 0xb7, 0x4e, 0x03, 0x3f, 0xf3, 0x2f, 0x4c, 0x38, 0x9e, 0x03, 0x49, + 0x9a, 0xa4, 0xaf, 0xe5, 0x08, 0x81, 0x81, 0x72, 0x3d, 0x86, 0x6b, 0xe8, + 0xe3, 0x9a, 0x4e, 0xe7, 0x4d, 0x92, 0xba, 0xa9, 0x21, 0x4d, 0x82, 0xed, + 0xd0, 0x16, 0x28, 0xc3, 0x3f, 0xe4, 0x2f, 0xb1, 0xbb, 0x92, 0xac, 0xdb, + 0x96, 0xcd, 0x0b, 0x67, 0x07, 0x5e, 0x12, 0x69, 0x77, 0xb5, 0x5a, 0xad, + 0x56, 0xab, 0x6b, 0xf5, 0x6c, 0xc7, 0x42, 0x86, 0x9f, 0x4e, 0x3a, 0xb5, + 0xc2, 0xe9, 0x2a, 0xe4, 0xdf, 0xfb, 0xe2, 0x8b, 0xcf, 0xbe, 0x78, 0x36, + 0xb2, 0x9e, 0xd2, 0x62, 0xe5, 0x19, 0x65, 0xdd, 0x2b, 0x8b, 0xd9, 0xd8, + 0xca, 0x5d, 0x6a, 0x2f, 0xba, 0xfc, 0xdf, 0xf9, 0xfc, 0x33, 0x8c, 0xfb, + 0x13, 0x91, 0x06, 0x14, 0x99, 0xf4, 0xbf, 0x89, 0x33, 0x09, 0xf6, 0xc1, + 0x7b, 0x2e, 0x28, 0x02, 0x40, 0xa5, 0x65, 0x64, 0x2d, 0xd7, 0x6e, 0x99, + 0x14, 0x14, 0x2f, 0x95, 0xb5, 0xfe, 0x33, 0xde, 0xdd, 0xab, 0x6d, 0x92, + 0x2d, 0xe0, 0x07, 0xb8, 0x4e, 0xe6, 0xf6, 0xd5, 0xf0, 0x85, 0x0e, 0x2f, + 0x2a, 0x00, 0xb9, 0x7f, 0xb1, 0x59, 0x23, 0x05, 0x70, 0xbf, 0xde, 0x2e, + 0x8a, 0x2c, 0x9d, 0xef, 0x8a, 0x84, 0x8e, 0xf4, 0x6f, 0xbe, 0x87, 0xbc, + 0x59, 0x7e, 0x35, 0xcb, 0x32, 0xbc, 0xcf, 0x00, 0x64, 0x7b, 0x23, 0x38, + 0xde, 0xd3, 0xad, 0x23, 0x0d, 0x67, 0x50, 0x66, 0xab, 0x3e, 0xd7, 0x02, + 0x83, 0x35, 0xe1, 0xec, 0x0d, 0xc0, 0x49, 0x28, 0x03, 0xc3, 0x32, 0x82, + 0xbc, 0x57, 0x75, 0xf0, 0x5f, 0xe3, 0x3c, 0xdd, 0x01, 0x14, 0xf1, 0xe4, + 0x1a, 0x41, 0x81, 0x0d, 0x76, 0x24, 0x47, 0xf6, 0x91, 0x84, 0xc4, 0xe4, + 0x7c, 0xda, 0xef, 0x03, 0xf0, 0x28, 0xe5, 0x1b, 0x65, 0xab, 0x14, 0xa8, + 0xfd, 0x98, 0xce, 0xe0, 0xc1, 0xb3, 0xd3, 0xc7, 0xaf, 0x03, 0x25, 0x6b, + 0xb1, 0x21, 0x41, 0x2d, 0x87, 0x89, 0xd3, 0x6e, 0xce, 0x6e, 0x34, 0xc0, + 0x8a, 0xfa, 0x71, 0x97, 0x3a, 0x00, 0x57, 0x9d, 0x8e, 0xa5, 0xf9, 0x44, + 0x1a, 0x2a, 0xf6, 0xd1, 0xe9, 0x67, 0x9f, 0x0e, 0xb6, 0xb3, 0x8c, 0x6e, + 0xe7, 0x3b, 0x7a, 0x13, 0xbf, 0x19, 0x71, 0xcd, 0x37, 0x4a, 0x18, 0x51, + 0x19, 0xb2, 0x85, 0x35, 0x35, 0xfe, 0x31, 0x90, 0xf2, 0x32, 0x3f, 0x8c, + 0x3d, 0xd7, 0xc2, 0x86, 0x7a, 0xfe, 0x80, 0x3c, 0x81, 0x0d, 0xd6, 0xb3, + 0x6b, 0xaa, 0x41, 0xf9, 0x83, 0x5f, 0x27, 0x92, 0x6f, 0x20, 0x56, 0xfc, + 0xd1, 0x0a, 0x07, 0x95, 0xcd, 0x6e, 0x55, 0xfd, 0xcc, 0xa3, 0x22, 0x4b, + 0x6a, 0xbd, 0x28, 0xbd, 0x60, 0x3f, 0x09, 0x0e, 0x8d, 0xa7, 0x9f, 0x24, + 0xa8, 0xb4, 0x33, 0xb9, 0x71, 0xc7, 0x16, 0x0d, 0xca, 0x83, 0x3e, 0x04, + 0xbf, 0xd0, 0x28, 0x15, 0xdc, 0xaf, 0x82, 0x8c, 0xa8, 0x41, 0x31, 0xbf, + 0xda, 0xdc, 0x9c, 0xae, 0xc1, 0x5e, 0xcc, 0x67, 0x59, 0xac, 0x02, 0x97, + 0x81, 0x76, 0x7b, 0x91, 0x38, 0x0a, 0x0b, 0xd3, 0xdb, 0xe1, 0xd0, 0x65, + 0x3b, 0x30, 0xcd, 0xe8, 0xd7, 0x44, 0x98, 0x75, 0x6c, 0x10, 0x1f, 0x48, + 0x93, 0x5e, 0xab, 0x14, 0xed, 0x02, 0x43, 0x9c, 0xa6, 0xba, 0x00, 0x08, + 0xb2, 0xc7, 0x4e, 0x80, 0xc0, 0x03, 0x6a, 0x0b, 0xec, 0x0a, 0x51, 0x3f, + 0x7a, 0xf4, 0xae, 0x92, 0x91, 0x5e, 0xf0, 0xd4, 0x0f, 0xe9, 0x09, 0x4f, + 0x25, 0xe7, 0x8a, 0x12, 0xba, 0xca, 0xde, 0x1d, 0x3e, 0x33, 0x3a, 0x15, + 0x12, 0x13, 0x41, 0x9d, 0xb8, 0xd0, 0xe2, 0xce, 0xbb, 0x8f, 0xbe, 0xea, + 0xa8, 0xd0, 0xf9, 0x76, 0x5d, 0x01, 0x7d, 0xfa, 0xf9, 0xdb, 0x9f, 0x02, + 0xb8, 0xb6, 0x31, 0x58, 0x01, 0xfe, 0x48, 0x83, 0x9d, 0x17, 0x55, 0xa4, + 0xdf, 0xf9, 0xf2, 0xf1, 0xe3, 0xcf, 0x74, 0xe2, 0xf3, 0x46, 0x9c, 0x17, + 0xb7, 0x85, 0x05, 0x4d, 0xa3, 0x1c, 0x6e, 0x53, 0xc6, 0x86, 0x3c, 0x63, + 0x43, 0x94, 0x5d, 0x41, 0x0a, 0x0b, 0xc5, 0x1b, 0x75, 0x09, 0x1c, 0x4d, + 0xc0, 0x3d, 0xce, 0x18, 0xc8, 0x2a, 0x59, 0xda, 0xfe, 0x62, 0x47, 0x7b, + 0x56, 0x95, 0x03, 0x41, 0x9a, 0x86, 0x0f, 0x48, 0x5d, 0x25, 0x0b, 0x2c, + 0x02, 0xa2, 0x8a, 0x07, 0x5b, 0x65, 0x0e, 0x32, 0x32, 0x15, 0x2c, 0xc9, + 0x64, 0x8a, 0xfe, 0x01, 0xa7, 0x70, 0x21, 0xcf, 0x5a, 0x71, 0x41, 0xe0, + 0x98, 0x63, 0xe0, 0xba, 0x8b, 0xc4, 0xd2, 0xd8, 0x34, 0x1e, 0xf4, 0x55, + 0x0b, 0xf5, 0x1e, 0xc7, 0x28, 0x67, 0xe5, 0xe5, 0xa1, 0x61, 0x8e, 0x04, + 0x0d, 0xae, 0x13, 0xa7, 0xad, 0x61, 0xfc, 0xa7, 0x4f, 0x0f, 0xe1, 0x9a, + 0x4f, 0xc7, 0x4a, 0x34, 0xad, 0x3b, 0xc6, 0x8a, 0xb2, 0xd2, 0x88, 0x4d, + 0x23, 0x65, 0xf4, 0x56, 0xd4, 0xa1, 0x25, 0x8e, 0x27, 0xf3, 0xcd, 0xed, + 0x13, 0x58, 0x65, 0x02, 0x8a, 0x09, 0x7f, 0x50, 0x37, 0x7a, 0x5d, 0xc9, + 0x53, 0xc8, 0xfa, 0x04, 0x54, 0x6c, 0x96, 0xcb, 0x55, 0xc2, 0x3a, 0x1d, + 0x79, 0x3e, 0x52, 0x42, 0xa0, 0xe4, 0x86, 0x84, 0x18, 0x23, 0x1d, 0x99, + 0xad, 0x35, 0x21, 0x94, 0x52, 0x0e, 0x7f, 0x86, 0x76, 0x00, 0xa8, 0x2f, + 0x6b, 0x5e, 0xa8, 0x59, 0x5a, 0x79, 0xda, 0x03, 0xf5, 0xc7, 0xd1, 0xf5, + 0xc5, 0xc3, 0x68, 0x05, 0xbb, 0x35, 0xb7, 0xab, 0x31, 0xaa, 0x65, 0xec, + 0x17, 0x4e, 0xc4, 0x12, 0x49, 0x18, 0x41, 0x43, 0x32, 0x8c, 0x9d, 0x5d, + 0x8d, 0x2b, 0x60, 0xc5, 0x5c, 0x91, 0xcb, 0x12, 0x19, 0x41, 0x1d, 0x45, + 0x17, 0xec, 0x43, 0x98, 0x0e, 0xc8, 0xe1, 0xe1, 0x7e, 0x3c, 0x90, 0xf1, + 0xd1, 0xd3, 0x77, 0x41, 0x78, 0x85, 0x03, 0xbc, 0x90, 0x5d, 0xca, 0x16, + 0x56, 0xbf, 0xcb, 0x37, 0xeb, 0x66, 0x8e, 0x08, 0x46, 0x70, 0x8f, 0x64, + 0x50, 0x57, 0xd3, 0xf7, 0x28, 0xae, 0xb7, 0xf2, 0x96, 0x40, 0x98, 0x1b, + 0xf2, 0x96, 0xee, 0x71, 0x80, 0x1a, 0xfc, 0x7c, 0xaf, 0x4f, 0x98, 0xbe, + 0x60, 0x87, 0x1c, 0xca, 0x57, 0x75, 0xcb, 0x12, 0x6e, 0xd2, 0xe2, 0x8a, + 0x05, 0x81, 0x8d, 0x40, 0xee, 0xb9, 0x44, 0xba, 0x84, 0x0e, 0x1f, 0xf3, + 0x2b, 0x0b, 0x30, 0x3a, 0x95, 0x18, 0x5d, 0x97, 0xb3, 0xfd, 0xac, 0xc8, + 0x35, 0xc3, 0x12, 0x42, 0x7a, 0xb7, 0x8b, 0xd5, 0x87, 0xdc, 0x5d, 0xe2, + 0x75, 0x85, 0x62, 0xa5, 0xd2, 0xb8, 0xf4, 0x77, 0xde, 0xb5, 0x7d, 0x22, + 0x2d, 0x1f, 0x24, 0x63, 0xa2, 0xb8, 0x9f, 0x44, 0xa6, 0x5b, 0xd0, 0xa5, + 0x1a, 0x3f, 0x05, 0x1f, 0x8f, 0xcf, 0x12, 0xe4, 0xbb, 0x72, 0x38, 0x8e, + 0x20, 0xe5, 0x50, 0xdf, 0x05, 0x63, 0xdd, 0xf3, 0xd9, 0x47, 0xb4, 0x32, + 0xde, 0xb1, 0xd5, 0x75, 0xc1, 0x0e, 0x01, 0x1c, 0xbb, 0xdd, 0x0b, 0xc3, + 0xb9, 0x30, 0x2b, 0x2d, 0xbd, 0x8a, 0xe8, 0x13, 0xb1, 0x0d, 0x21, 0x5f, + 0x50, 0xe6, 0x8f, 0x4d, 0xe7, 0x11, 0x9e, 0x97, 0x05, 0xbb, 0xce, 0x9e, + 0x62, 0x8e, 0x2e, 0xb3, 0xcd, 0xb5, 0x78, 0x79, 0x59, 0x7d, 0xb4, 0x79, + 0x20, 0x27, 0x42, 0xda, 0x1a, 0x2d, 0x93, 0x5a, 0xb2, 0x46, 0x89, 0xd9, + 0x5a, 0x44, 0x44, 0x41, 0x8d, 0xd4, 0x0e, 0xe7, 0xd6, 0x24, 0x05, 0xc0, + 0x54, 0x26, 0xa4, 0xe1, 0xd6, 0x26, 0xdb, 0x67, 0x22, 0x58, 0xaf, 0xbe, + 0x79, 0xd7, 0x99, 0x11, 0x0d, 0x94, 0x6f, 0x6a, 0x2a, 0x5f, 0x25, 0xbc, + 0x6e, 0x47, 0x28, 0xcd, 0xd4, 0x46, 0xf9, 0x21, 0x44, 0x99, 0xc4, 0xa5, + 0xc1, 0x9a, 0x6f, 0x2e, 0xee, 0x4c, 0x2b, 0xc6, 0x9d, 0x92, 0xa9, 0xaf, + 0x64, 0x96, 0x0f, 0x48, 0xd2, 0x5d, 0xd7, 0xa6, 0x0a, 0xf8, 0x8b, 0x4f, + 0x15, 0x9e, 0xd1, 0xac, 0x4f, 0xf9, 0xca, 0xae, 0x36, 0xcd, 0xd5, 0x86, + 0x16, 0x32, 0x66, 0x82, 0xb6, 0xd5, 0xd8, 0xf2, 0x46, 0x90, 0x78, 0x62, + 0xbd, 0x74, 0x36, 0x60, 0x6e, 0xd1, 0x1f, 0xc9, 0x66, 0x75, 0xd2, 0x2e, + 0x32, 0x47, 0xcb, 0xd1, 0x64, 0xfd, 0x79, 0x28, 0x82, 0xa6, 0xed, 0xac, + 0x2a, 0xdc, 0x27, 0xee, 0x11, 0x7e, 0xd7, 0xd9, 0xbb, 0x0d, 0x2f, 0x5a, + 0x5b, 0xc8, 0xb1, 0x55, 0x42, 0x4a, 0xc9, 0x18, 0xea, 0xf4, 0x2e, 0xa6, + 0x2d, 0xdb, 0x80, 0x38, 0xaf, 0xdf, 0x05, 0x3c, 0xbe, 0x76, 0xf3, 0x3e, + 0xff, 0x19, 0x6b, 0xfe, 0xe8, 0x6a, 0x33, 0xe7, 0xf9, 0xef, 0xc0, 0xd7, + 0xf8, 0x8c, 0x8c, 0x31, 0x33, 0x28, 0xe9, 0xe5, 0x5d, 0x29, 0xb9, 0xee, + 0x79, 0x2f, 0xfa, 0x99, 0xdd, 0x99, 0x7a, 0x80, 0x3d, 0x34, 0x65, 0x57, + 0xd3, 0x0e, 0x70, 0x04, 0x79, 0x20, 0x78, 0x2e, 0x4b, 0xe4, 0xc3, 0x73, + 0xfc, 0x40, 0xa0, 0x3f, 0xe8, 0x51, 0x49, 0xbd, 0xe8, 0x81, 0x36, 0xf6, + 0xd0, 0x56, 0x83, 0x73, 0xd6, 0x70, 0xca, 0x6e, 0x91, 0xd0, 0x08, 0x23, + 0xa8, 0x76, 0xeb, 0x07, 0xb6, 0x04, 0x0c, 0x9b, 0x82, 0x61, 0x8c, 0x69, + 0x4f, 0xc3, 0x7e, 0x2a, 0x2c, 0x7e, 0x79, 0x72, 0xf2, 0xde, 0xe9, 0xa9, + 0xd1, 0x00, 0x68, 0x05, 0x7b, 0x72, 0xc0, 0x09, 0x99, 0x92, 0x99, 0xbd, + 0x83, 0x46, 0x34, 0xf0, 0x11, 0x72, 0xb6, 0x86, 0x04, 0x14, 0x0f, 0x69, + 0x72, 0xd6, 0xd8, 0x96, 0x97, 0xdd, 0x0b, 0xc4, 0xc2, 0x5c, 0x6b, 0xd1, + 0x3f, 0x82, 0x0d, 0x3e, 0x9b, 0xac, 0x32, 0x81, 0x38, 0x6a, 0xda, 0xbe, + 0x7e, 0x4d, 0xe6, 0x9f, 0x8a, 0xba, 0xeb, 0x3e, 0x70, 0xc2, 0x76, 0x08, + 0xed, 0x8e, 0xfa, 0xac, 0xf2, 0xb3, 0x5c, 0xd1, 0xf2, 0x7a, 0xeb, 0xcd, + 0x9d, 0x74, 0xe8, 0x3a, 0xb8, 0x60, 0x0a, 0x74, 0x42, 0x4c, 0x8b, 0xb2, + 0xfe, 0xa6, 0x32, 0x06, 0xfa, 0x87, 0x44, 0x2c, 0xc3, 0xe3, 0xa4, 0x99, + 0x63, 0x9f, 0x4b, 0x62, 0x80, 0xef, 0x45, 0x23, 0xfd, 0xc0, 0x28, 0x11, + 0xb6, 0xe9, 0xe2, 0x40, 0x10, 0x42, 0x19, 0x17, 0x49, 0x4c, 0x56, 0xef, + 0x9d, 0x9d, 0x92, 0xcd, 0xcc, 0x69, 0xe1, 0x24, 0xa7, 0xf9, 0xb9, 0x8b, + 0x9e, 0x3d, 0xa2, 0x6f, 0xd6, 0xa7, 0xe2, 0xb1, 0x07, 0x58, 0xc8, 0x86, + 0x55, 0xd5, 0x15, 0x6c, 0x68, 0x96, 0x6c, 0x99, 0x07, 0x52, 0x22, 0x96, + 0xcf, 0x19, 0xd1, 0xca, 0x2f, 0x5f, 0xd7, 0x26, 0xf0, 0xd7, 0x81, 0x01, + 0x0e, 0x2c, 0x6d, 0x66, 0x74, 0x0a, 0x1a, 0x18, 0xe9, 0x80, 0xfc, 0xd4, + 0x82, 0xb2, 0x9e, 0x0d, 0xa5, 0x38, 0x3c, 0xee, 0xfc, 0x9d, 0xbb, 0x13, + 0x31, 0xa3, 0x89, 0x3b, 0x8c, 0x25, 0xba, 0x1f, 0x0a, 0x9b, 0xb7, 0x4b, + 0xb0, 0x47, 0x62, 0xd0, 0x91, 0x8e, 0x41, 0x0a, 0x84, 0x86, 0x13, 0xf8, + 0x78, 0x23, 0xba, 0xe5, 0x4b, 0x54, 0xf0, 0x0b, 0x42, 0xde, 0xa8, 0x32, + 0xbf, 0x3d, 0x4b, 0xcf, 0xd5, 0xa9, 0x12, 0x25, 0xb8, 0xcf, 0xf0, 0xca, + 0x59, 0xed, 0x6b, 0xfc, 0x1c, 0xaf, 0x4c, 0x39, 0xec, 0x18, 0x8d, 0x03, + 0xb5, 0xa8, 0xbf, 0x9f, 0x60, 0xcb, 0xe8, 0x56, 0xe7, 0xa5, 0x8e, 0x91, + 0x43, 0x8b, 0x91, 0xd7, 0x3a, 0xaa, 0xb8, 0x13, 0x7e, 0xa5, 0x8b, 0x3d, + 0x76, 0x11, 0xcd, 0xd6, 0x17, 0xe5, 0x8e, 0x74, 0xb1, 0x31, 0x1a, 0x02, + 0xb0, 0xf4, 0xd3, 0xa5, 0xc6, 0xb9, 0xa3, 0xb3, 0x4e, 0x86, 0xfc, 0x72, + 0x0d, 0x81, 0x7e, 0x31, 0x82, 0x8e, 0xc9, 0x7f, 0xd0, 0xec, 0xf0, 0x5c, + 0x3d, 0x66, 0xe9, 0x25, 0xb2, 0x0c, 0x23, 0x32, 0x07, 0x6c, 0x2f, 0x8d, + 0x79, 0x18, 0x0d, 0xdc, 0x52, 0xf3, 0x13, 0xb9, 0x09, 0x23, 0xe2, 0xdb, + 0x33, 0xf3, 0xef, 0x31, 0xd9, 0xfb, 0x4b, 0xf7, 0xc6, 0xb6, 0xbf, 0xd3, + 0x81, 0x86, 0xb1, 0xa2, 0x74, 0xc9, 0xa8, 0x79, 0xc4, 0x0f, 0xde, 0x4e, + 0xb2, 0x87, 0x60, 0x46, 0x95, 0x7a, 0x09, 0x44, 0xab, 0x4b, 0xd0, 0x3e, + 0x93, 0xea, 0x2b, 0x53, 0xf9, 0x4e, 0x27, 0xd9, 0xf4, 0x90, 0x11, 0xd3, + 0xed, 0x21, 0x23, 0x5d, 0x0a, 0x62, 0x53, 0xb5, 0xd8, 0x06, 0xcf, 0xce, + 0x3c, 0x92, 0x8b, 0x6d, 0xf8, 0xc7, 0x71, 0x8c, 0xd9, 0x38, 0x35, 0x56, + 0xa7, 0x47, 0x8c, 0xda, 0xc0, 0xce, 0x09, 0xf6, 0x19, 0xc2, 0x9e, 0x0f, + 0xca, 0xb7, 0xf7, 0x24, 0x16, 0x81, 0x68, 0x8b, 0x11, 0x8c, 0x8c, 0xd1, + 0x55, 0x09, 0x4a, 0x68, 0x89, 0x36, 0x1a, 0x4e, 0x24, 0x40, 0xa3, 0x33, + 0x59, 0x17, 0x9b, 0xa8, 0x74, 0x86, 0xa3, 0xab, 0x24, 0x4b, 0x0c, 0xef, + 0x91, 0xa6, 0x2d, 0x39, 0x0f, 0x90, 0x50, 0xd5, 0x92, 0x1c, 0x48, 0x36, + 0xa5, 0x44, 0x13, 0x1c, 0x83, 0xae, 0x9a, 0x59, 0x0d, 0x78, 0xa5, 0x9b, + 0xec, 0xe0, 0x0b, 0x1a, 0x64, 0x45, 0x69, 0xde, 0x12, 0xed, 0x0a, 0x89, + 0x6b, 0xf7, 0x95, 0xf5, 0xe1, 0x30, 0xb2, 0x3a, 0x22, 0x41, 0xd0, 0xe6, + 0x97, 0xf9, 0x07, 0x22, 0x5d, 0x07, 0x6b, 0x52, 0x33, 0x9d, 0x10, 0x90, + 0x36, 0xca, 0x9a, 0xd8, 0x42, 0xe8, 0x9c, 0x5c, 0x81, 0x4d, 0x30, 0x31, + 0xbb, 0x8e, 0xca, 0xca, 0x80, 0x02, 0x55, 0xb5, 0x2d, 0x81, 0x44, 0x75, + 0x25, 0x9a, 0x59, 0xdf, 0x32, 0xc3, 0x04, 0x6c, 0x5e, 0x63, 0x95, 0x35, + 0x49, 0xc6, 0x5f, 0xe7, 0x6b, 0xac, 0xb4, 0x85, 0xec, 0xaf, 0xf5, 0x76, + 0x93, 0xd5, 0xd7, 0x1a, 0x80, 0x64, 0xad, 0x45, 0x8a, 0x5d, 0x6b, 0x91, + 0x61, 0x00, 0xb6, 0xad, 0x35, 0x67, 0x4d, 0x7c, 0xaf, 0xac, 0xf5, 0x16, + 0x6a, 0x6d, 0x22, 0xfb, 0x6b, 0x4d, 0x51, 0x21, 0x6a, 0x6b, 0x8d, 0x40, + 0xb2, 0xd6, 0x22, 0xc5, 0xaa, 0xb5, 0xc8, 0x30, 0x01, 0x5b, 0xd6, 0x9a, + 0xb1, 0x26, 0xc9, 0x54, 0xd5, 0x7a, 0x07, 0xb5, 0xb6, 0x90, 0x2b, 0xda, + 0x1a, 0xbc, 0x8f, 0xda, 0x5a, 0x23, 0x90, 0xac, 0xb5, 0x48, 0xb1, 0x6a, + 0x2d, 0x32, 0x4c, 0xc0, 0x96, 0xb5, 0x66, 0xac, 0x49, 0x32, 0x55, 0xb5, + 0xc6, 0xa1, 0xde, 0x42, 0x76, 0xd6, 0x1a, 0x86, 0x5a, 0x1e, 0x4b, 0xc3, + 0x5f, 0x6d, 0xe1, 0xea, 0x02, 0xa0, 0x3a, 0xc2, 0x1a, 0x3e, 0xa7, 0x28, + 0x8f, 0xd8, 0x58, 0x0a, 0xc7, 0x73, 0xcf, 0xc3, 0x66, 0x5a, 0x33, 0x66, + 0xa6, 0x32, 0x5b, 0xa9, 0x6a, 0xfd, 0x10, 0x29, 0x61, 0xcb, 0x66, 0x65, + 0xbe, 0x14, 0x4f, 0x9d, 0x18, 0x60, 0x4d, 0x3a, 0xb0, 0x46, 0x08, 0x08, + 0x4b, 0x22, 0xfe, 0x26, 0x3d, 0xcd, 0xa1, 0x45, 0x75, 0x4c, 0x57, 0x73, + 0x52, 0x24, 0x0e, 0x9e, 0x9f, 0x07, 0x35, 0xe8, 0x62, 0x2d, 0xcd, 0x96, + 0x8a, 0x2c, 0xaa, 0xad, 0xb7, 0xaa, 0x0d, 0xd8, 0x42, 0x9b, 0x19, 0x29, + 0x20, 0xad, 0x91, 0xf1, 0x6b, 0x73, 0x8e, 0x75, 0xd7, 0x91, 0xb5, 0xe1, + 0x1a, 0x5a, 0x31, 0x89, 0x62, 0x45, 0x8a, 0x97, 0x69, 0x96, 0x17, 0xd4, + 0xb8, 0xd6, 0x92, 0x89, 0x84, 0xe2, 0xe1, 0xaa, 0x08, 0xcc, 0x83, 0x6c, + 0xcf, 0xff, 0xdb, 0x69, 0xfe, 0x9f, 0xd1, 0xfe, 0x66, 0x3d, 0x20, 0xa0, + 0x17, 0x04, 0xf7, 0x04, 0xa5, 0xda, 0x0d, 0x7a, 0x84, 0xa6, 0x8d, 0xdb, + 0x74, 0x5d, 0xaf, 0x84, 0x00, 0x24, 0x6a, 0x8c, 0x08, 0x0e, 0xc5, 0x83, + 0x54, 0x99, 0xdf, 0x4a, 0xdf, 0x18, 0x23, 0xf0, 0x6f, 0x95, 0x9a, 0x89, + 0x01, 0x52, 0xe2, 0x38, 0xbb, 0x18, 0x06, 0x3a, 0xaa, 0xaf, 0x15, 0x42, + 0xf9, 0xa7, 0x23, 0x12, 0x66, 0xff, 0x26, 0x32, 0x60, 0x66, 0x21, 0xd9, + 0x61, 0x73, 0x0b, 0x05, 0x1a, 0x13, 0xeb, 0xcd, 0x25, 0x41, 0xd9, 0x0d, + 0x87, 0xc9, 0x13, 0x09, 0xd1, 0xaa, 0xe9, 0xb8, 0xb8, 0xf1, 0xa3, 0xaa, + 0xf1, 0x70, 0xaa, 0x6e, 0x60, 0xb9, 0xc7, 0xbb, 0x62, 0x56, 0xed, 0xcd, + 0xb1, 0x59, 0xb3, 0x74, 0xe6, 0x18, 0x86, 0x21, 0x5b, 0x08, 0x09, 0xda, + 0xe9, 0xc9, 0xd2, 0x16, 0x18, 0xbc, 0x56, 0x83, 0xb7, 0x27, 0xe1, 0x94, + 0x2c, 0x41, 0x1a, 0xb9, 0x7c, 0x3a, 0x11, 0xa0, 0x8a, 0x9f, 0x55, 0xa3, + 0xc5, 0x19, 0x48, 0xc3, 0xc0, 0xf2, 0x48, 0x63, 0xb3, 0xad, 0x15, 0xc6, + 0x66, 0x2b, 0x65, 0x01, 0x3f, 0x1a, 0x89, 0x02, 0xc0, 0x6d, 0x49, 0x40, + 0xaa, 0x02, 0xd0, 0x4e, 0x0e, 0xc4, 0x37, 0x7e, 0x54, 0x48, 0xe1, 0x5c, + 0x97, 0x02, 0x00, 0x3b, 0x85, 0xb0, 0xd8, 0xec, 0x42, 0xbc, 0x1f, 0x04, + 0x93, 0x5a, 0x41, 0xbf, 0x2c, 0x95, 0xa7, 0xfa, 0x4b, 0x88, 0x46, 0x6e, + 0x81, 0x46, 0x03, 0x68, 0x12, 0x7e, 0x95, 0xca, 0x2f, 0x74, 0x95, 0x5f, + 0x48, 0x97, 0xa0, 0x8d, 0xda, 0xb6, 0x68, 0x5e, 0x4d, 0x8a, 0xec, 0xe5, + 0xc8, 0x7a, 0x31, 0x32, 0xb8, 0x2a, 0xd3, 0x28, 0xa1, 0xfe, 0x41, 0xc6, + 0x91, 0x31, 0x64, 0x99, 0x47, 0x96, 0x5c, 0x6f, 0x20, 0x39, 0x9c, 0xd0, + 0x97, 0xb8, 0xd4, 0x4a, 0x11, 0xcc, 0x2d, 0x7a, 0x11, 0xdf, 0xd5, 0x44, + 0x2c, 0x09, 0xde, 0x40, 0x79, 0x6c, 0x7a, 0x53, 0xbd, 0xcc, 0x5f, 0x22, + 0xfe, 0x2c, 0xa7, 0xfc, 0xcd, 0x1f, 0xb5, 0x94, 0x09, 0xec, 0x8d, 0xca, + 0x8a, 0x0e, 0xb5, 0x01, 0x8d, 0xb3, 0x8b, 0xf2, 0xa8, 0x03, 0x95, 0x16, + 0xa4, 0x0f, 0x08, 0x18, 0xa0, 0x10, 0x08, 0xf6, 0xcf, 0xd2, 0x08, 0xe4, + 0xc8, 0x52, 0x09, 0x9e, 0x1e, 0xa4, 0x13, 0x08, 0x58, 0xa3, 0x14, 0xa3, + 0x31, 0xa2, 0x49, 0xf8, 0x26, 0x4b, 0x42, 0xff, 0x44, 0xad, 0x20, 0xea, + 0x41, 0x6a, 0x41, 0x90, 0x01, 0x7a, 0x41, 0x70, 0xff, 0x2c, 0xc5, 0x20, + 0x96, 0x2c, 0xcd, 0x10, 0x19, 0x41, 0xaa, 0x41, 0x90, 0xd5, 0xba, 0x01, + 0xe6, 0x42, 0x07, 0xff, 0x97, 0xab, 0x06, 0x10, 0x0b, 0x33, 0x18, 0x00, + 0x18, 0x62, 0x30, 0x00, 0xec, 0x1f, 0x66, 0x30, 0x90, 0x23, 0x5b, 0x2d, + 0x28, 0x3d, 0xcc, 0x60, 0x00, 0x60, 0x8d, 0xc1, 0x38, 0xee, 0xaa, 0xc0, + 0xff, 0x5a, 0x6b, 0x41, 0xc1, 0x6f, 0x29, 0xf6, 0xad, 0xbd, 0x53, 0xa1, + 0x04, 0xc6, 0x6d, 0xb7, 0x61, 0xa1, 0x9f, 0xb6, 0x9a, 0x32, 0x74, 0x26, + 0xf2, 0xfc, 0x8c, 0x7e, 0x88, 0x9d, 0xc2, 0x47, 0xb8, 0x77, 0x7e, 0xce, + 0x58, 0x70, 0xcf, 0x70, 0x17, 0xdf, 0x57, 0xaf, 0x93, 0x32, 0x08, 0x3c, + 0x05, 0x2c, 0x55, 0x96, 0xa5, 0x0d, 0x68, 0x1f, 0x9f, 0xae, 0x92, 0xcb, + 0x23, 0x41, 0x4a, 0x3c, 0x60, 0x76, 0x74, 0x8a, 0x3d, 0xc5, 0xdf, 0x51, + 0x6e, 0xc1, 0x66, 0xb3, 0x1b, 0x65, 0x8f, 0x13, 0xf6, 0xdb, 0xe8, 0x54, + 0x22, 0xa5, 0xb3, 0x9d, 0x38, 0xce, 0x54, 0xb1, 0xe1, 0xa7, 0x11, 0x05, + 0x71, 0x59, 0x78, 0xa3, 0xa5, 0x57, 0x27, 0x6f, 0xc0, 0xb3, 0x5e, 0x0b, + 0x38, 0xb5, 0x50, 0x32, 0x1b, 0x95, 0xa1, 0x8c, 0x39, 0xd7, 0x6e, 0xce, + 0x3d, 0x0b, 0x92, 0x05, 0x9d, 0xeb, 0xa2, 0x63, 0x24, 0xef, 0x5d, 0x5e, + 0x26, 0x8b, 0xba, 0x95, 0xac, 0xa2, 0x6f, 0x21, 0x08, 0x71, 0x39, 0xa9, + 0x09, 0x8e, 0x35, 0xbf, 0x9d, 0xa0, 0xbc, 0x48, 0x2d, 0x97, 0xb9, 0x88, + 0x0a, 0x14, 0x53, 0xc5, 0x85, 0x75, 0x36, 0xcc, 0x0f, 0x0a, 0xb6, 0x2c, + 0xf0, 0x92, 0x86, 0x8b, 0xca, 0x7c, 0x49, 0xca, 0xd1, 0xe9, 0x36, 0x3f, + 0x92, 0x6e, 0x4f, 0x3e, 0x92, 0x11, 0x88, 0x38, 0xda, 0xd7, 0x9f, 0x79, + 0x1c, 0x68, 0xcf, 0xf5, 0xee, 0x74, 0xfc, 0xf5, 0x1c, 0x3e, 0xcd, 0x7a, + 0x2a, 0xf5, 0x72, 0xce, 0x43, 0x57, 0xd7, 0xb3, 0x74, 0x5d, 0x7b, 0x8e, + 0xa2, 0x8f, 0x50, 0x42, 0xc3, 0x05, 0x96, 0x6d, 0x25, 0x95, 0x00, 0xe7, + 0x2a, 0x68, 0xa3, 0x15, 0x34, 0x17, 0x31, 0x28, 0x43, 0x29, 0xd3, 0xda, + 0x19, 0xbf, 0x4a, 0x6e, 0x09, 0xac, 0x8a, 0x15, 0x09, 0x7d, 0x97, 0xfe, + 0x80, 0xa6, 0x24, 0xa6, 0xf3, 0xd6, 0x8f, 0x60, 0xf8, 0x15, 0xe8, 0xfc, + 0x20, 0x5c, 0x3c, 0xea, 0x8d, 0xbb, 0xbd, 0xd1, 0x71, 0xf7, 0xa5, 0xf1, + 0x6b, 0xaf, 0x75, 0x5f, 0xf6, 0xc3, 0x1d, 0x0a, 0xb8, 0xa3, 0x57, 0x5f, + 0xa9, 0x82, 0x3b, 0x12, 0x70, 0xa3, 0xd1, 0xc3, 0x6e, 0xf7, 0x60, 0x04, + 0xe7, 0xbc, 0x42, 0x22, 0x5a, 0x16, 0x9b, 0xcd, 0x6a, 0x3e, 0x6b, 0xd0, + 0x79, 0xa8, 0xd0, 0x10, 0xca, 0x97, 0x9b, 0x4d, 0x91, 0xec, 0x83, 0xb0, + 0xc9, 0xb2, 0x68, 0x95, 0x18, 0x64, 0x4e, 0x81, 0x03, 0xc7, 0x47, 0x68, + 0xb3, 0x1f, 0x3c, 0x37, 0x1a, 0x8d, 0x1e, 0x44, 0xaf, 0xc3, 0x97, 0xf7, + 0xde, 0x7b, 0xef, 0x41, 0x08, 0x65, 0x62, 0x79, 0x7f, 0x84, 0xe9, 0x96, + 0x4b, 0x3b, 0xea, 0x66, 0x7f, 0xc2, 0xd0, 0xff, 0xf5, 0xfd, 0x09, 0xa1, + 0x44, 0x7f, 0x12, 0x58, 0xbe, 0xfe, 0x84, 0x79, 0x2a, 0x64, 0xa3, 0x25, + 0x1e, 0x9b, 0x16, 0x70, 0xa7, 0x97, 0x18, 0x22, 0x26, 0x3a, 0x78, 0x6b, + 0x0a, 0xc8, 0x45, 0xdc, 0x23, 0x15, 0xd4, 0xb1, 0x7a, 0xa9, 0x20, 0x94, + 0x90, 0x8a, 0xc0, 0xf2, 0x49, 0x05, 0xf3, 0x74, 0xc8, 0xf6, 0x52, 0x61, + 0xdc, 0x09, 0x3a, 0xe1, 0x52, 0xe1, 0x87, 0xef, 0x9b, 0xf4, 0x25, 0x04, + 0x08, 0x21, 0x2d, 0x4e, 0xde, 0x3c, 0x7d, 0xca, 0xe5, 0x3e, 0xdc, 0xbe, + 0x48, 0xe3, 0x42, 0xf8, 0xbe, 0x68, 0xb3, 0xc9, 0xc1, 0x1e, 0xa9, 0xc3, + 0x5c, 0x63, 0x6f, 0x32, 0x17, 0x53, 0x97, 0x3d, 0xd2, 0x87, 0x99, 0x50, + 0x7b, 0xf6, 0xf9, 0x69, 0xc6, 0x22, 0xb9, 0x2d, 0x0e, 0xe8, 0x06, 0x20, + 0xeb, 0xe7, 0x17, 0xc9, 0x96, 0x9d, 0x45, 0x8f, 0x20, 0x49, 0xd2, 0x8c, + 0x30, 0xd8, 0x2a, 0xc6, 0xdb, 0x0a, 0x1d, 0x8c, 0x11, 0xf5, 0x9f, 0x3d, + 0x16, 0x8b, 0xa8, 0xb8, 0x79, 0xc8, 0xf1, 0x58, 0x79, 0x3d, 0x52, 0x4e, + 0xdc, 0x3d, 0x47, 0x63, 0x89, 0xa6, 0xf7, 0x78, 0x2c, 0xfc, 0x31, 0x08, + 0x38, 0x15, 0x5b, 0x37, 0x02, 0x8d, 0xc7, 0x63, 0xe7, 0xf8, 0x76, 0x1f, + 0xac, 0x24, 0xa7, 0xc9, 0x12, 0x62, 0xfd, 0xb6, 0x1b, 0xeb, 0xe0, 0x2f, + 0xe0, 0x1c, 0xdd, 0x7e, 0xc8, 0xb3, 0xe8, 0x45, 0x7b, 0x20, 0x4c, 0x47, + 0x69, 0xf7, 0x43, 0x1a, 0x0f, 0xd8, 0xee, 0x87, 0x32, 0x1e, 0xbb, 0xdd, + 0x13, 0x69, 0x16, 0x3b, 0x66, 0x3f, 0xb4, 0xf3, 0x6d, 0xb2, 0xaf, 0x66, + 0x14, 0xc6, 0xa6, 0x1d, 0x69, 0xcb, 0x5f, 0x29, 0x02, 0x26, 0x45, 0x00, + 0xa4, 0x79, 0x2b, 0x85, 0x77, 0x4a, 0x04, 0x59, 0x2a, 0xdc, 0x9f, 0x98, + 0x0f, 0x11, 0x63, 0x9c, 0x4a, 0xb8, 0xa3, 0x22, 0x88, 0xf4, 0x61, 0x75, + 0xa6, 0xc9, 0xf8, 0x50, 0xac, 0x43, 0xa8, 0xb3, 0x55, 0x99, 0xfa, 0x49, + 0xaf, 0x4d, 0xbd, 0xd1, 0x4a, 0xc4, 0x53, 0x9e, 0x82, 0x57, 0x72, 0xc3, + 0x6c, 0xe5, 0x93, 0xd9, 0xa2, 0x48, 0x61, 0xdd, 0x8f, 0xdd, 0xeb, 0x8f, + 0xbb, 0x7e, 0x65, 0xc9, 0x83, 0xb4, 0x05, 0xa8, 0x1a, 0x0a, 0x93, 0x7b, + 0x35, 0x86, 0xa0, 0x35, 0xd8, 0x26, 0x0b, 0x42, 0x4e, 0x6a, 0x50, 0x8a, + 0x56, 0x6a, 0xe3, 0xfa, 0x72, 0x07, 0x81, 0x5e, 0x4d, 0xba, 0x9c, 0x2d, + 0x12, 0x1e, 0x3d, 0xbd, 0x49, 0x48, 0x3d, 0x3e, 0x8f, 0xf7, 0x46, 0x72, + 0x92, 0x93, 0x9c, 0x1a, 0x10, 0x6c, 0x50, 0x0f, 0x08, 0x5c, 0xbd, 0x09, + 0xeb, 0x0d, 0xec, 0xd1, 0x46, 0x97, 0x58, 0x57, 0xa0, 0xd2, 0x42, 0xaa, + 0x4f, 0xd7, 0x3f, 0x10, 0x97, 0xb2, 0xa7, 0xf5, 0xfc, 0x59, 0x78, 0xb3, + 0x8c, 0x2b, 0xae, 0xbc, 0xb3, 0x42, 0xd7, 0xa2, 0x60, 0x0b, 0x21, 0xea, + 0x98, 0xb7, 0xa3, 0x01, 0xb8, 0xbc, 0x87, 0x25, 0x62, 0x21, 0x74, 0xed, + 0x2b, 0x51, 0xf4, 0xa7, 0xd3, 0x8c, 0x5e, 0x9e, 0xca, 0xa8, 0x04, 0xd6, + 0x6d, 0x4f, 0xcc, 0x48, 0x58, 0xd0, 0x4a, 0xb8, 0x0f, 0x96, 0xe4, 0x74, + 0xe3, 0x45, 0x3c, 0x98, 0x15, 0x31, 0xd5, 0xc9, 0x15, 0x24, 0xfd, 0x86, + 0xeb, 0xf5, 0x6c, 0xab, 0xde, 0x6e, 0x8d, 0xf4, 0x3f, 0xf3, 0x22, 0x97, + 0xc5, 0x67, 0x9d, 0x2d, 0x12, 0xb7, 0xb8, 0xf0, 0x36, 0x3d, 0xa4, 0x7d, + 0x0a, 0x3f, 0xc3, 0xea, 0x65, 0x38, 0x51, 0x9a, 0xda, 0xff, 0x39, 0xd7, + 0x4e, 0x75, 0xef, 0xfc, 0x6c, 0x71, 0xae, 0x9a, 0x86, 0xd4, 0xd1, 0xdb, + 0x8d, 0x74, 0xc3, 0x7d, 0x9f, 0x89, 0x57, 0x9b, 0xdf, 0x65, 0xea, 0x74, + 0xad, 0x66, 0xa5, 0x9b, 0x8b, 0x66, 0xb3, 0xce, 0x56, 0xab, 0xbf, 0xaa, + 0x45, 0x51, 0xae, 0x4c, 0x3a, 0xd1, 0xb4, 0x49, 0xf3, 0x4e, 0xdc, 0xe4, + 0x08, 0x40, 0x97, 0x0d, 0x25, 0xb5, 0x13, 0xcf, 0xdf, 0xa9, 0x1d, 0x53, + 0x5f, 0xbe, 0x5d, 0x8b, 0xea, 0x4a, 0xdc, 0xdb, 0x6b, 0xc1, 0xb5, 0xd1, + 0x37, 0x34, 0xc7, 0xa1, 0x89, 0xa9, 0x74, 0xed, 0x9c, 0x55, 0xd9, 0x3c, + 0xb9, 0xf9, 0x06, 0xa5, 0x18, 0xa3, 0x93, 0x71, 0xed, 0xf6, 0x29, 0x4f, + 0xd8, 0xc2, 0x54, 0x39, 0x44, 0x8d, 0x1b, 0x68, 0x6d, 0x98, 0x51, 0x52, + 0x5b, 0xec, 0x29, 0xce, 0x31, 0x9b, 0xb0, 0xa1, 0xb0, 0x20, 0xbf, 0x05, + 0xf8, 0x84, 0x72, 0x0c, 0xf3, 0x95, 0xe1, 0x8b, 0x7f, 0xa1, 0x5f, 0xa1, + 0xbe, 0xce, 0x97, 0x18, 0x54, 0xfe, 0xae, 0x17, 0xe1, 0xc3, 0xb1, 0x50, + 0xa7, 0xda, 0x4b, 0xac, 0xbc, 0x7c, 0x4e, 0xa0, 0x6c, 0xea, 0x5b, 0x6d, + 0x7b, 0x1c, 0xc8, 0x8a, 0x74, 0xaf, 0x83, 0x18, 0x43, 0xb1, 0x38, 0x5e, + 0x8a, 0x2b, 0xda, 0xb4, 0xdd, 0xf8, 0xdc, 0xec, 0x62, 0xfc, 0xca, 0xf8, + 0x15, 0xda, 0x6f, 0x7c, 0xee, 0xe1, 0x62, 0x76, 0x79, 0x34, 0xec, 0x48, + 0xef, 0xe8, 0xed, 0x75, 0x7a, 0x3d, 0xa3, 0x4a, 0xa4, 0x39, 0x31, 0x7c, + 0xc1, 0x42, 0xb4, 0x90, 0x08, 0xe8, 0x8a, 0x54, 0x8c, 0x37, 0xd9, 0xd9, + 0x65, 0xef, 0x08, 0x4a, 0x19, 0xe1, 0x97, 0xae, 0xeb, 0x5e, 0x6a, 0x07, + 0xc5, 0x00, 0x1b, 0xd7, 0x44, 0x86, 0x97, 0xe0, 0x7e, 0x06, 0x3c, 0xe0, + 0x42, 0xab, 0x46, 0x8c, 0xd9, 0x86, 0xe8, 0x9e, 0x8b, 0x54, 0x86, 0xcd, + 0x54, 0x1f, 0x6c, 0x07, 0xe5, 0xa0, 0x50, 0x99, 0x2b, 0xf8, 0x71, 0x93, + 0x8b, 0x17, 0xf4, 0xe5, 0x5b, 0x9f, 0xf6, 0xd3, 0xf7, 0xd1, 0x08, 0x6b, + 0xc6, 0x72, 0x95, 0xa7, 0xf4, 0xa3, 0x31, 0x4f, 0xcb, 0x12, 0x89, 0xf3, + 0x6e, 0xb2, 0x9a, 0xdd, 0x7d, 0x90, 0x6d, 0x6e, 0xde, 0x9f, 0xe1, 0xd3, + 0x94, 0x12, 0x88, 0x5e, 0x5a, 0x66, 0x6f, 0x88, 0x02, 0x5b, 0x13, 0xfd, + 0x75, 0x40, 0x71, 0xe1, 0x7f, 0xb5, 0xd2, 0xef, 0xfc, 0xeb, 0x77, 0x3c, + 0xe9, 0xd5, 0xe4, 0x68, 0xbb, 0x29, 0x40, 0x17, 0x52, 0x18, 0xc0, 0xee, + 0xe8, 0x6d, 0x6e, 0x85, 0xe1, 0x5c, 0xb9, 0x76, 0xed, 0x7c, 0x42, 0x54, + 0xc6, 0xe1, 0x88, 0x31, 0xd1, 0x0a, 0x7c, 0x0a, 0x69, 0xfc, 0x85, 0x71, + 0xaa, 0x72, 0xd4, 0xf9, 0x64, 0xb6, 0xde, 0x51, 0x49, 0x94, 0x7a, 0xf1, + 0xfa, 0xeb, 0x15, 0xcc, 0x52, 0xd8, 0x80, 0x9f, 0xbf, 0x4f, 0x92, 0xed, + 0x09, 0x01, 0xb3, 0xca, 0xde, 0x2b, 0xbe, 0x76, 0x2d, 0x7b, 0xd0, 0x0a, + 0x67, 0xe7, 0x2a, 0x98, 0xff, 0x31, 0x54, 0xb4, 0x0f, 0xda, 0x64, 0xa5, + 0x72, 0x5a, 0x2b, 0x69, 0xf4, 0x01, 0x92, 0xba, 0x8e, 0xee, 0x7a, 0x42, + 0xaa, 0xcf, 0xf5, 0x6c, 0xec, 0x76, 0x02, 0xad, 0x1a, 0xd3, 0xa0, 0x5f, + 0xea, 0xe5, 0xb5, 0xf2, 0x35, 0x7d, 0x8d, 0x82, 0x00, 0x4d, 0xa9, 0x21, + 0x04, 0x46, 0x01, 0x67, 0x61, 0x7a, 0xc4, 0x37, 0xcf, 0x77, 0x18, 0xc9, + 0x9f, 0x06, 0x20, 0x06, 0x07, 0x8a, 0xcf, 0x7e, 0x7a, 0x8e, 0x81, 0x88, + 0xda, 0x4f, 0x44, 0xed, 0x19, 0xb4, 0x54, 0x1d, 0xbc, 0xe1, 0x67, 0xaa, + 0x0e, 0xa6, 0xf1, 0x5b, 0x92, 0x03, 0xe8, 0x1e, 0xd7, 0x56, 0x48, 0x23, + 0x02, 0xa0, 0x08, 0x1c, 0x76, 0xec, 0x0d, 0xe0, 0x88, 0x84, 0xc0, 0xe7, + 0x57, 0x5f, 0x88, 0xfe, 0x04, 0x9c, 0x95, 0x1d, 0x37, 0x76, 0xbf, 0x60, + 0x0d, 0x3a, 0x3a, 0xcb, 0x2e, 0x76, 0xe9, 0x7a, 0x03, 0x5f, 0x65, 0x77, + 0x86, 0xd2, 0xfd, 0xd1, 0x3d, 0x4e, 0x4a, 0xea, 0x28, 0x28, 0xa9, 0x1a, + 0x54, 0x4f, 0x20, 0x83, 0xf4, 0x4d, 0x02, 0x7e, 0xa5, 0xe5, 0xa1, 0x28, + 0x31, 0x81, 0x21, 0x59, 0x25, 0x63, 0x54, 0x3c, 0xea, 0xa9, 0x53, 0x3d, + 0xd6, 0x70, 0x1d, 0x83, 0xc9, 0x45, 0x38, 0x7f, 0x01, 0x3d, 0xe6, 0xe5, + 0x97, 0x0d, 0x9c, 0x3f, 0xd7, 0x77, 0x0c, 0xee, 0x55, 0x4b, 0x6d, 0xfd, + 0xee, 0x74, 0xdc, 0x48, 0x7a, 0x40, 0xb6, 0x97, 0xa1, 0x71, 0xeb, 0x2a, + 0x61, 0xfa, 0x11, 0x13, 0xa7, 0xb4, 0xc9, 0x5a, 0x05, 0x8b, 0xfb, 0x5d, + 0xe8, 0x5f, 0x7b, 0x91, 0x78, 0xbf, 0xbf, 0x57, 0x89, 0xff, 0x59, 0xe1, + 0x89, 0xae, 0x59, 0x67, 0x69, 0xdf, 0x98, 0x46, 0xd2, 0xc0, 0xd5, 0x35, + 0x7d, 0x27, 0x7c, 0x16, 0xea, 0x6e, 0x3b, 0x72, 0x49, 0x82, 0xdb, 0xee, + 0x3d, 0x82, 0xde, 0xac, 0x03, 0x1b, 0xed, 0x3e, 0x20, 0x0c, 0x0d, 0x58, + 0x91, 0x72, 0x44, 0x57, 0xc7, 0x5f, 0x12, 0x93, 0x94, 0xcb, 0x40, 0x02, + 0x89, 0x52, 0x00, 0xb3, 0x4c, 0x0a, 0x1f, 0x9b, 0x24, 0xc9, 0xfe, 0xe5, + 0x2c, 0x5d, 0x25, 0x32, 0x18, 0x89, 0x57, 0xb6, 0xc4, 0xb0, 0xce, 0xb2, + 0xc5, 0xb0, 0xce, 0x6e, 0xb5, 0x6d, 0x05, 0xfc, 0x5d, 0xb6, 0xf2, 0xd8, + 0xd2, 0xda, 0xa9, 0x94, 0x3f, 0xc4, 0xe2, 0xf1, 0xf1, 0x7e, 0x42, 0x2c, + 0xbe, 0xf2, 0x14, 0x43, 0x2c, 0x1a, 0x21, 0x8c, 0x28, 0xdc, 0x22, 0x48, + 0x26, 0x07, 0xc9, 0xa8, 0x43, 0xeb, 0xd7, 0x57, 0xc9, 0x9a, 0x0d, 0xaa, + 0x52, 0xa4, 0x69, 0x4e, 0x1e, 0x58, 0x8f, 0xa2, 0xbb, 0x53, 0xd0, 0x06, + 0x92, 0x3a, 0x1f, 0x7e, 0x21, 0x35, 0xfb, 0x31, 0xc9, 0x5c, 0xad, 0x21, + 0x47, 0x04, 0x3b, 0x8c, 0xba, 0xad, 0xe3, 0x65, 0x3b, 0x51, 0x69, 0xf6, + 0x14, 0x4f, 0x7d, 0x0d, 0x5e, 0x46, 0x32, 0x6b, 0x60, 0x6f, 0xa4, 0x83, + 0xc1, 0x95, 0xaf, 0x41, 0xe7, 0x0e, 0x53, 0x6e, 0x4e, 0xb7, 0xd5, 0x78, + 0x11, 0xa0, 0x39, 0xa6, 0xde, 0x81, 0x72, 0xbc, 0xd0, 0x90, 0x44, 0xb8, + 0xf2, 0x01, 0x71, 0xa6, 0x7d, 0x21, 0x05, 0xb4, 0xd5, 0x40, 0x0c, 0xc6, + 0x79, 0x27, 0xdc, 0xc5, 0xbd, 0xea, 0x21, 0x8d, 0x95, 0x4d, 0x15, 0x91, + 0x4d, 0x07, 0x6a, 0x55, 0xd1, 0x0c, 0x48, 0x46, 0x0f, 0x37, 0xc1, 0xee, + 0x35, 0x30, 0x34, 0x5b, 0xb1, 0x71, 0x27, 0x4b, 0x2e, 0xb3, 0x24, 0xbf, + 0x7a, 0x92, 0xf2, 0xd4, 0xae, 0xab, 0xd2, 0x1f, 0x6f, 0x96, 0x11, 0x8d, + 0x0b, 0xb9, 0xaf, 0x16, 0x94, 0xab, 0xd6, 0x82, 0x12, 0x9c, 0x55, 0xa1, + 0x1c, 0xb5, 0x32, 0x22, 0x4e, 0x19, 0x7d, 0x36, 0xad, 0x12, 0x0e, 0xa0, + 0xf6, 0xc8, 0x50, 0x64, 0x77, 0x27, 0x74, 0x13, 0xee, 0xcd, 0xa9, 0x62, + 0x49, 0x07, 0x72, 0xf6, 0x48, 0x9c, 0x35, 0x74, 0x0b, 0xbc, 0xdd, 0x14, + 0xfe, 0xea, 0x5d, 0xae, 0x56, 0x1d, 0x35, 0xa8, 0xb3, 0x0a, 0xa3, 0xd0, + 0xb8, 0x42, 0xc6, 0xc8, 0xd7, 0xa6, 0xec, 0x4e, 0x9b, 0x28, 0x75, 0xbc, + 0x5c, 0xf2, 0x1d, 0x46, 0xd1, 0xcb, 0xee, 0x16, 0x82, 0xf4, 0x10, 0xfc, + 0xb1, 0x12, 0xe8, 0x6e, 0x64, 0x45, 0xba, 0xf3, 0xe8, 0x32, 0x3f, 0x4f, + 0xc0, 0xa2, 0x99, 0x06, 0xf4, 0xd1, 0x32, 0xd8, 0x4f, 0x50, 0x20, 0x5f, + 0xa9, 0xd9, 0x48, 0x9e, 0x93, 0x66, 0x01, 0x7d, 0x07, 0x48, 0x1b, 0x39, + 0x7c, 0x46, 0x8f, 0xbe, 0x49, 0x45, 0x62, 0x70, 0x29, 0x02, 0x2b, 0x7f, + 0xa9, 0x75, 0x01, 0x95, 0x76, 0xe9, 0x6c, 0x66, 0xbe, 0x2c, 0x20, 0xcb, + 0x38, 0x38, 0x08, 0x5a, 0x44, 0x7c, 0x40, 0x36, 0xf2, 0x81, 0xd8, 0xcf, + 0xe4, 0x2f, 0xed, 0x60, 0xe3, 0xae, 0xd1, 0x24, 0xdb, 0xeb, 0xf9, 0x1a, + 0xe7, 0x50, 0x3e, 0x70, 0x0c, 0xff, 0xba, 0xa2, 0xaa, 0x42, 0xb2, 0xd3, + 0x71, 0x95, 0x11, 0x57, 0x11, 0x53, 0xdc, 0xba, 0x77, 0xbc, 0x77, 0xa0, + 0x5f, 0xcb, 0x9f, 0xaa, 0xd0, 0x93, 0x28, 0xe8, 0x20, 0x9a, 0xfb, 0x7e, + 0x7f, 0x74, 0x5f, 0xcb, 0x14, 0xae, 0xad, 0xfa, 0x39, 0xa2, 0xdc, 0x69, + 0x09, 0x18, 0x42, 0x50, 0xbe, 0x23, 0x68, 0x92, 0xf5, 0x3a, 0xf7, 0xf6, + 0x0b, 0x89, 0x06, 0x25, 0xcf, 0x1e, 0x05, 0x7f, 0x42, 0x3d, 0x3a, 0x91, + 0x2f, 0x94, 0x61, 0x38, 0x33, 0x07, 0xb0, 0xf1, 0x90, 0x63, 0x48, 0x01, + 0x76, 0x4d, 0x69, 0xfb, 0x96, 0xb7, 0xe1, 0x29, 0x3d, 0x2f, 0xc3, 0x6e, + 0xec, 0xe6, 0x14, 0x3e, 0xab, 0x56, 0x30, 0x04, 0x6b, 0xc9, 0x04, 0xe0, + 0x7e, 0x36, 0xae, 0x7d, 0x4f, 0x25, 0xf8, 0x24, 0xe4, 0xd2, 0xbb, 0xfb, + 0xe2, 0x7a, 0x50, 0xeb, 0xe3, 0xed, 0x61, 0x9b, 0x25, 0x93, 0x27, 0x80, + 0x99, 0x96, 0xe0, 0x93, 0x80, 0xab, 0xe7, 0xee, 0x0b, 0xe4, 0x21, 0x0c, + 0x5d, 0xde, 0x3e, 0xf1, 0x69, 0x24, 0xd0, 0xb2, 0x94, 0x12, 0xc0, 0x43, + 0xf5, 0x92, 0x8e, 0xce, 0x04, 0xab, 0xa4, 0xf5, 0x74, 0xa4, 0xa4, 0x51, + 0xa3, 0x8c, 0x95, 0x7a, 0x68, 0x3e, 0x69, 0x29, 0xa9, 0x86, 0x69, 0xa0, + 0x51, 0x27, 0x3a, 0x3e, 0x10, 0x5c, 0x27, 0xfb, 0xa5, 0x58, 0x49, 0x04, + 0x1f, 0xac, 0x0f, 0xc2, 0xca, 0x34, 0xac, 0x51, 0x20, 0xd6, 0x52, 0xc3, + 0x1a, 0x07, 0x62, 0xcd, 0x35, 0xac, 0xc3, 0x40, 0x2c, 0x38, 0xb2, 0xc8, + 0x82, 0x4f, 0x3c, 0xde, 0x7c, 0x98, 0xdc, 0xc6, 0x67, 0x6a, 0x1d, 0x7b, + 0x1a, 0xef, 0x3d, 0x8d, 0xa7, 0x9e, 0x56, 0xd6, 0x79, 0x37, 0xac, 0xb4, + 0x9b, 0xb1, 0xc6, 0xe4, 0xc3, 0x40, 0x26, 0x33, 0x1d, 0xed, 0x28, 0x10, + 0x6d, 0xa9, 0xa3, 0x1d, 0x07, 0xa2, 0xcd, 0x75, 0xb4, 0x57, 0x02, 0xd1, + 0x40, 0x92, 0x63, 0x8f, 0x28, 0x1f, 0x6a, 0xe2, 0x3a, 0xd2, 0x7e, 0x1d, + 0xe3, 0x2f, 0x59, 0x58, 0xb8, 0x28, 0x0f, 0x35, 0x2e, 0x5f, 0x0d, 0xe4, + 0x32, 0xd3, 0xd1, 0x5e, 0x0b, 0x44, 0x5b, 0xea, 0x68, 0xa3, 0xd0, 0x0e, + 0x30, 0x37, 0xf0, 0x42, 0xbb, 0x00, 0x08, 0xf3, 0xd0, 0x23, 0xcc, 0x57, + 0x35, 0x81, 0xbd, 0xa6, 0x6b, 0xa9, 0xa1, 0xb4, 0x23, 0x10, 0xe7, 0xd3, + 0x18, 0x0e, 0x7d, 0x0f, 0x4a, 0xfb, 0x2d, 0x62, 0x65, 0xe0, 0xd5, 0x41, + 0xe6, 0x61, 0x2a, 0xaa, 0x09, 0xb6, 0x3a, 0x58, 0xfa, 0x10, 0xab, 0x03, + 0xac, 0x0e, 0xe6, 0x7e, 0x3c, 0x7f, 0x50, 0x55, 0x52, 0x33, 0x8e, 0x18, + 0x60, 0x6e, 0x2b, 0x04, 0x35, 0x6e, 0x2d, 0xa8, 0x71, 0x6b, 0x49, 0x8d, + 0xdb, 0x8a, 0x6a, 0xdc, 0x5a, 0x56, 0xe3, 0x46, 0xc2, 0xf2, 0xc8, 0xea, + 0xb0, 0xb5, 0xac, 0x0e, 0x5b, 0xcb, 0xea, 0xb0, 0xad, 0xac, 0x0e, 0x5b, + 0xcb, 0xea, 0x30, 0x5c, 0x56, 0x6e, 0xe7, 0xf2, 0x84, 0x36, 0xd2, 0x1a, + 0x39, 0x95, 0x65, 0xe8, 0x50, 0x87, 0x17, 0x60, 0x85, 0x17, 0x8d, 0xa6, + 0x1a, 0xce, 0x24, 0x24, 0x06, 0xaa, 0x27, 0xe8, 0x69, 0x90, 0xcb, 0x25, + 0xa3, 0x7c, 0xfa, 0x99, 0x93, 0x30, 0x53, 0x1d, 0x67, 0x12, 0x14, 0xb3, + 0xd4, 0x17, 0xa3, 0x34, 0xc8, 0xfb, 0x15, 0x21, 0x35, 0x6b, 0xf9, 0x23, + 0x98, 0xa9, 0x86, 0x53, 0xcb, 0x1f, 0xc0, 0x78, 0xf8, 0x83, 0xac, 0x30, + 0xef, 0x5c, 0x46, 0xce, 0xf4, 0xf3, 0x27, 0x61, 0xa6, 0x3a, 0xce, 0x24, + 0x28, 0x0e, 0xa8, 0x37, 0xee, 0x67, 0x30, 0x7f, 0x14, 0xe3, 0xd2, 0xcf, + 0x9f, 0x84, 0x99, 0xea, 0x38, 0x93, 0x28, 0x24, 0x62, 0xa7, 0x37, 0x42, + 0x67, 0x08, 0x7f, 0x3c, 0x6a, 0x61, 0x54, 0xd1, 0x39, 0x04, 0xcc, 0x54, + 0x41, 0x08, 0x99, 0x72, 0x2f, 0xd6, 0x46, 0xe3, 0x4a, 0x5a, 0x81, 0x9c, + 0x01, 0x85, 0x5a, 0xce, 0x00, 0x46, 0x72, 0xb6, 0x08, 0x58, 0x0c, 0x58, + 0x6c, 0x76, 0x1e, 0xc6, 0x16, 0x61, 0xcb, 0x01, 0x22, 0x7a, 0x5b, 0x14, + 0x3c, 0xab, 0xe0, 0x65, 0x48, 0x4c, 0xc1, 0xb1, 0x8c, 0x25, 0xd7, 0xe4, + 0x00, 0xaa, 0x76, 0x07, 0xce, 0x17, 0x9f, 0xae, 0x9a, 0x93, 0x64, 0x8d, + 0x47, 0x69, 0x11, 0xf2, 0xc6, 0x42, 0x1d, 0xa4, 0xb0, 0x12, 0xbd, 0xbb, + 0x48, 0x72, 0x58, 0xbf, 0x92, 0xcb, 0x80, 0x2e, 0xa1, 0xd8, 0xc4, 0x4a, + 0x11, 0x34, 0xab, 0x10, 0x0d, 0x1a, 0x1d, 0xf5, 0xf0, 0x5a, 0xfd, 0xa6, + 0xb5, 0x72, 0x62, 0x75, 0x3f, 0x85, 0x2a, 0x8b, 0xa9, 0x61, 0x83, 0xdd, + 0x50, 0x80, 0x06, 0xb8, 0xba, 0x37, 0x4d, 0xe1, 0xc7, 0x4d, 0x11, 0x0e, + 0xab, 0x10, 0x40, 0xcb, 0x83, 0x46, 0x5c, 0x5b, 0xf5, 0xb7, 0xe9, 0xba, + 0xb6, 0x4f, 0x22, 0xcc, 0x54, 0x41, 0xa8, 0xed, 0x93, 0x00, 0xe3, 0xd4, + 0x64, 0x48, 0x0f, 0xec, 0x91, 0x74, 0x39, 0xa3, 0x82, 0x2d, 0x09, 0x33, + 0xd5, 0x50, 0x26, 0x8d, 0x43, 0x70, 0xd8, 0x6c, 0x12, 0xa5, 0x50, 0x6b, + 0x4b, 0x71, 0x61, 0xc2, 0x4d, 0x87, 0x23, 0x7a, 0x8d, 0x46, 0x69, 0xd2, + 0xec, 0xec, 0xba, 0x71, 0xc5, 0x35, 0x38, 0x72, 0x5b, 0x73, 0xfa, 0x78, + 0xc9, 0xb5, 0xb6, 0x80, 0xd1, 0xb8, 0x7d, 0x01, 0xfc, 0x9a, 0x6b, 0x60, + 0x2c, 0xa9, 0xe6, 0xf4, 0xe1, 0x9a, 0x6b, 0x6d, 0x05, 0x8e, 0xe1, 0x8c, + 0x63, 0x50, 0x3f, 0xc2, 0x87, 0xd5, 0xc0, 0xc0, 0x34, 0x5a, 0x0d, 0x85, + 0xb5, 0x98, 0x60, 0x35, 0x89, 0xb2, 0xff, 0xd1, 0x23, 0xc0, 0x12, 0xd6, + 0x3b, 0xb5, 0x8f, 0x9c, 0xb3, 0x7a, 0xff, 0x8b, 0xf1, 0xf4, 0xe7, 0x7d, + 0x25, 0xc4, 0x53, 0x12, 0x7f, 0x59, 0xfe, 0x0b, 0xfa, 0x17, 0x48, 0x1a, + 0x90, 0xb5, 0xef, 0xd7, 0x3b, 0x39, 0xcf, 0xe9, 0x6d, 0x8e, 0x6c, 0xb3, + 0xca, 0xfd, 0x80, 0x62, 0x63, 0x86, 0x10, 0x6c, 0x38, 0x91, 0xcf, 0xab, + 0xc0, 0xde, 0x12, 0xaf, 0x39, 0xbd, 0xa3, 0xa1, 0x44, 0x97, 0x50, 0x4c, + 0x7e, 0x95, 0x5c, 0xd0, 0x4b, 0xe7, 0xf4, 0xd0, 0xb4, 0xef, 0xf2, 0x16, + 0x65, 0x6a, 0x94, 0x5c, 0x90, 0x06, 0x41, 0x7f, 0x43, 0xca, 0xe9, 0x31, + 0x55, 0x54, 0x3c, 0x61, 0x5a, 0x7b, 0xf8, 0xe8, 0x11, 0x40, 0xa7, 0xb3, + 0x55, 0xfa, 0x13, 0xec, 0x0d, 0x0e, 0x06, 0x03, 0xab, 0x14, 0x79, 0xb3, + 0x4c, 0xbe, 0x96, 0x43, 0x0a, 0xc9, 0xf8, 0x73, 0x01, 0xfb, 0x2c, 0x84, + 0xb6, 0xc6, 0xde, 0xe4, 0xea, 0x1f, 0x14, 0x6c, 0x73, 0x25, 0x4f, 0x13, + 0x7f, 0xcc, 0x5f, 0x7a, 0x04, 0x3b, 0x61, 0xaa, 0x92, 0x71, 0x2e, 0x9b, + 0xce, 0x63, 0x35, 0xbd, 0xb5, 0xd4, 0x6c, 0x6f, 0xaf, 0x96, 0x5a, 0x19, + 0x96, 0xc2, 0x45, 0xd1, 0x79, 0xe4, 0x0c, 0x0f, 0xa4, 0x7b, 0xbb, 0x1c, + 0x13, 0x96, 0xbf, 0x4f, 0x2e, 0xe4, 0x7a, 0x9d, 0x1b, 0x48, 0xea, 0x8c, + 0x3c, 0x18, 0x80, 0xaa, 0xe9, 0x3c, 0xd9, 0xc0, 0x9a, 0x47, 0x9c, 0x7e, + 0x60, 0xf2, 0x94, 0xd1, 0x91, 0x9e, 0xef, 0x74, 0x7b, 0x74, 0xd0, 0x7c, + 0x58, 0xf9, 0xfa, 0xf8, 0x02, 0x2f, 0x05, 0x46, 0xb4, 0xfb, 0x2b, 0x37, + 0x97, 0xed, 0xd3, 0x60, 0x44, 0x93, 0xef, 0x1a, 0x93, 0x1e, 0xdb, 0x9b, + 0xc4, 0xa7, 0x11, 0x02, 0xd1, 0x7e, 0xaf, 0x00, 0x9c, 0xb8, 0xf7, 0x9f, + 0x55, 0x62, 0xea, 0x81, 0x68, 0x91, 0xf6, 0xec, 0x14, 0xb9, 0x47, 0x7b, + 0xae, 0xa4, 0xfc, 0xda, 0xe9, 0x12, 0xa4, 0x91, 0x7c, 0xa2, 0x03, 0xca, + 0x03, 0xd5, 0x27, 0x57, 0x90, 0x43, 0x67, 0xa9, 0x7d, 0x00, 0xf9, 0xa2, + 0x16, 0x62, 0x5b, 0x0b, 0x91, 0x09, 0x08, 0xc9, 0x9d, 0x0d, 0x76, 0x7a, + 0x56, 0x43, 0xe7, 0xf4, 0xbc, 0x04, 0x20, 0xe9, 0x86, 0x9c, 0x12, 0xae, + 0x3c, 0x79, 0xef, 0x6b, 0x1e, 0xf5, 0x58, 0x63, 0xb1, 0xa1, 0xc6, 0x42, + 0xf4, 0xc1, 0x2e, 0x5b, 0x39, 0x8e, 0x4a, 0xd8, 0x4d, 0x25, 0x47, 0x33, + 0xe7, 0xd1, 0x73, 0x71, 0xbb, 0xf1, 0x09, 0x5b, 0x16, 0x44, 0x23, 0x45, + 0xe9, 0x71, 0x4e, 0xbb, 0xa8, 0xae, 0x87, 0xdc, 0x18, 0x06, 0x6d, 0xbc, + 0x31, 0x20, 0x20, 0x5c, 0x17, 0xde, 0x00, 0x1c, 0x9a, 0x36, 0x68, 0x30, + 0x78, 0xb5, 0xc4, 0x6c, 0x83, 0x46, 0xab, 0x96, 0xad, 0x11, 0x5b, 0xf2, + 0x8a, 0x0b, 0x9e, 0x6d, 0xf1, 0x5a, 0x16, 0x89, 0xb3, 0xc7, 0x56, 0x65, + 0x22, 0x62, 0x4d, 0xa1, 0x60, 0x15, 0x4c, 0xd5, 0xb9, 0x37, 0xad, 0x93, + 0x7b, 0x4c, 0x17, 0xe0, 0xf3, 0x22, 0xec, 0xca, 0x1b, 0xc0, 0x31, 0x2f, + 0x81, 0x6e, 0x8c, 0xc9, 0xdb, 0x62, 0x40, 0xc0, 0x7f, 0x59, 0x0c, 0x32, + 0xe9, 0x9e, 0x58, 0x83, 0xe1, 0x53, 0x74, 0x1b, 0xbd, 0x7e, 0x89, 0x38, + 0x9d, 0x11, 0x8d, 0xa2, 0x5f, 0x7e, 0xd1, 0xd2, 0xa6, 0x90, 0x86, 0x46, + 0x03, 0x06, 0x6c, 0x1d, 0xf2, 0xe8, 0x15, 0xb4, 0x15, 0x6c, 0xe8, 0xfd, + 0xf2, 0xf4, 0xf1, 0x67, 0x9f, 0x44, 0xd0, 0xc7, 0x3f, 0xf9, 0xec, 0xdd, + 0xf7, 0x8c, 0xc7, 0xb2, 0x2a, 0x2f, 0x13, 0xf2, 0xae, 0xed, 0xbe, 0x3f, + 0xcd, 0xf1, 0x9f, 0xfa, 0x15, 0x6a, 0x46, 0xb6, 0xd1, 0x8d, 0xba, 0xb0, + 0x67, 0x53, 0x18, 0x0c, 0x30, 0x67, 0x23, 0x6a, 0x8b, 0x22, 0x22, 0xb1, + 0xd1, 0x0d, 0x57, 0x77, 0x93, 0xbd, 0xc9, 0x77, 0xd2, 0x60, 0x98, 0xde, + 0xb3, 0xab, 0xe5, 0xad, 0xf7, 0x66, 0xdd, 0x28, 0x76, 0x03, 0x51, 0x05, + 0x76, 0xb1, 0x22, 0xc6, 0x49, 0x0b, 0x50, 0xaa, 0x63, 0xa8, 0x0c, 0xdd, + 0xcf, 0xfb, 0xf2, 0xf1, 0x67, 0x9f, 0x7f, 0xfc, 0xf6, 0xb7, 0x7a, 0xcb, + 0x09, 0xf3, 0x8e, 0xe0, 0xfc, 0xb6, 0x73, 0x8c, 0x7e, 0x8a, 0xe9, 0x99, + 0x7b, 0xc7, 0x01, 0xf0, 0x83, 0xbd, 0xb0, 0xec, 0x90, 0x8e, 0x04, 0xae, + 0xa6, 0x4c, 0x67, 0x29, 0x7c, 0x94, 0xe5, 0x9a, 0x9a, 0xbb, 0x96, 0xaf, + 0xb0, 0x5a, 0xb2, 0x7e, 0xf3, 0xe4, 0xeb, 0x53, 0x86, 0xf6, 0xe7, 0xba, + 0x8d, 0x4b, 0xb3, 0x45, 0x1f, 0x6a, 0xa6, 0x69, 0x52, 0x77, 0xdb, 0xe9, + 0xbc, 0xde, 0x89, 0x39, 0x48, 0x6d, 0x37, 0x6e, 0xd5, 0x95, 0x95, 0x2e, + 0x16, 0xd0, 0xa1, 0xa9, 0x5d, 0xfe, 0x9b, 0x1a, 0xf5, 0x2a, 0xd3, 0xa8, + 0xc7, 0x5f, 0xfd, 0x6b, 0xaa, 0x87, 0xc0, 0xe1, 0xf5, 0x7b, 0x8d, 0x8f, + 0x35, 0xef, 0x8d, 0x06, 0x87, 0xa3, 0x7f, 0x4d, 0x1d, 0x9b, 0x34, 0xe1, + 0xf1, 0x90, 0x57, 0xf1, 0xfd, 0x34, 0x4b, 0xc6, 0xc3, 0xd1, 0xf8, 0x5f, + 0x53, 0x4b, 0x06, 0x5c, 0xfb, 0x4e, 0xf7, 0x9f, 0xae, 0x01, 0x02, 0xff, + 0x65, 0x55, 0xb0, 0x5e, 0xad, 0xd6, 0x5b, 0x6b, 0xd8, 0x28, 0xae, 0x40, + 0x67, 0x73, 0x79, 0xd9, 0x62, 0x90, 0x44, 0x92, 0xad, 0x24, 0xd8, 0x54, + 0x0f, 0x6c, 0x41, 0x36, 0x40, 0xf0, 0x2b, 0xbd, 0xed, 0x2d, 0x7b, 0x4b, + 0x51, 0xdd, 0xec, 0x80, 0xa0, 0x67, 0x6d, 0xfc, 0x7d, 0x86, 0xe9, 0x75, + 0xf8, 0x6d, 0x46, 0x65, 0xed, 0x5a, 0xf0, 0x09, 0x78, 0xed, 0xe6, 0x6d, + 0x84, 0xd8, 0x94, 0x4b, 0x45, 0x23, 0x9c, 0x73, 0xdd, 0x6b, 0xed, 0xc6, + 0xb3, 0x1d, 0x39, 0x03, 0xcc, 0x0e, 0xea, 0x78, 0xc8, 0x0b, 0xf1, 0xe2, + 0x0d, 0xf8, 0x7a, 0xcf, 0x50, 0x60, 0xd8, 0xf5, 0xa8, 0x08, 0x29, 0x91, + 0x14, 0x54, 0x19, 0x42, 0x7e, 0x82, 0xc5, 0xfd, 0x2c, 0xfd, 0x5e, 0x90, + 0xca, 0x3c, 0x01, 0xef, 0x20, 0xc7, 0x45, 0xa7, 0x65, 0x92, 0x95, 0x40, + 0x2a, 0x3b, 0xfa, 0x81, 0xf2, 0x91, 0xee, 0x8b, 0x6b, 0x79, 0x1c, 0x1b, + 0x20, 0xdc, 0x46, 0x0b, 0xdc, 0xd0, 0xf7, 0xa1, 0x7f, 0xc2, 0x0a, 0x3c, + 0x5f, 0xe7, 0xcc, 0xb5, 0x49, 0x87, 0x28, 0x1d, 0xcd, 0x01, 0x75, 0x70, + 0xc9, 0x85, 0xcd, 0xc7, 0xd0, 0xb6, 0x2d, 0xf0, 0x51, 0x1b, 0xd0, 0xab, + 0x5c, 0x4e, 0xa3, 0x8b, 0xe2, 0xbc, 0x40, 0x9a, 0x27, 0x2a, 0x0b, 0x6d, + 0x24, 0x45, 0x43, 0x86, 0xa4, 0x45, 0x72, 0x1a, 0x5a, 0x42, 0xbf, 0x05, + 0x74, 0x8c, 0x23, 0xc7, 0x2e, 0x74, 0x79, 0x60, 0xdd, 0x41, 0xe3, 0x05, + 0xa0, 0x61, 0x1d, 0xa5, 0x77, 0x51, 0x21, 0xd3, 0xc3, 0x08, 0x04, 0x9f, + 0x04, 0x2c, 0x4b, 0x79, 0x0e, 0x4b, 0x91, 0x87, 0x18, 0xcd, 0x8d, 0xd9, + 0x9e, 0x75, 0x84, 0xcb, 0x4a, 0x59, 0x5a, 0x29, 0xf3, 0xf3, 0xae, 0x62, + 0x99, 0x82, 0x0f, 0xdd, 0x49, 0x9e, 0x6a, 0x98, 0x1a, 0xdb, 0x5c, 0xd9, + 0x49, 0x4b, 0x3b, 0x69, 0x3e, 0x0e, 0x65, 0xec, 0xd0, 0xc3, 0x58, 0x1d, + 0x67, 0x87, 0x36, 0x67, 0x76, 0xd2, 0xd2, 0x4e, 0x9a, 0x1f, 0x6a, 0x9c, + 0xdd, 0xe3, 0x27, 0x8b, 0x41, 0xa2, 0xbd, 0xa5, 0x7f, 0x22, 0xa2, 0x90, + 0xd0, 0x2d, 0xa9, 0xd9, 0xfa, 0xc7, 0x59, 0xd5, 0xb4, 0xe1, 0x01, 0xab, + 0x13, 0xbd, 0x02, 0xf1, 0x84, 0x41, 0x53, 0xd8, 0x39, 0x7e, 0xc5, 0x0a, + 0xc3, 0xda, 0x02, 0x36, 0xcb, 0x40, 0xdc, 0x13, 0x96, 0x16, 0x3f, 0x18, + 0x5f, 0x10, 0x9c, 0x16, 0x6b, 0xe2, 0x7a, 0xbb, 0x59, 0x03, 0x61, 0x56, + 0xef, 0x45, 0x29, 0x9e, 0x2c, 0x29, 0x76, 0xd9, 0x3a, 0x8a, 0x3b, 0x43, + 0x14, 0x0c, 0xb3, 0x1c, 0x90, 0x3d, 0x28, 0x36, 0xa7, 0x45, 0x06, 0x36, + 0x2e, 0x86, 0xd8, 0xb2, 0x30, 0x22, 0xaf, 0x52, 0x98, 0x0a, 0xf5, 0xc7, + 0x98, 0xfe, 0xe5, 0x76, 0x0b, 0x1b, 0x56, 0xb3, 0x3c, 0x89, 0x2d, 0xb3, + 0x24, 0x05, 0x0b, 0x5f, 0xac, 0x22, 0x24, 0x0f, 0x02, 0x04, 0x36, 0x1d, + 0xbb, 0x50, 0xaa, 0x23, 0x63, 0xe4, 0xcb, 0x18, 0xfb, 0x32, 0xa0, 0x01, + 0x6c, 0x7e, 0x36, 0xeb, 0x53, 0x32, 0x1b, 0xd4, 0x06, 0x2c, 0x9c, 0x9e, + 0xd6, 0xcd, 0x9e, 0x75, 0xac, 0x70, 0x6a, 0x21, 0x79, 0xb6, 0x1b, 0x61, + 0x84, 0x09, 0x79, 0xb0, 0xcd, 0xe8, 0xf3, 0xdd, 0xe4, 0x72, 0xb6, 0x5b, + 0x15, 0x24, 0x01, 0x49, 0x8d, 0x81, 0xc8, 0x67, 0x47, 0x8a, 0xcd, 0x6e, + 0x71, 0x85, 0x0f, 0xa4, 0x4a, 0x93, 0x27, 0xe8, 0x52, 0xec, 0x42, 0x0e, + 0x3f, 0xcb, 0xa0, 0xed, 0xa4, 0xdd, 0xc3, 0x32, 0x21, 0xd3, 0x70, 0x9b, + 0x6e, 0x5f, 0x8f, 0x3e, 0x99, 0x15, 0x57, 0x03, 0x72, 0x88, 0x62, 0x15, + 0xf3, 0x31, 0x96, 0x42, 0x1b, 0xb8, 0x83, 0x2d, 0x4c, 0x76, 0xbf, 0x89, + 0xfa, 0x40, 0x7d, 0x00, 0x86, 0x16, 0x4c, 0xcb, 0xc7, 0xc9, 0x65, 0xd1, + 0xed, 0xe9, 0x94, 0xee, 0x42, 0x29, 0x7d, 0x2b, 0x29, 0x61, 0xde, 0xb6, + 0xab, 0x98, 0x66, 0xa1, 0xea, 0xfe, 0xca, 0x53, 0x18, 0x2d, 0xac, 0x78, + 0x8b, 0x8a, 0xb1, 0x22, 0xbf, 0x09, 0xe1, 0x9c, 0x81, 0x7e, 0xeb, 0xe6, + 0x4d, 0xb6, 0x23, 0x8f, 0x9d, 0xca, 0xbb, 0x0d, 0xf5, 0xb4, 0x47, 0xd7, + 0x50, 0xc7, 0x77, 0xa1, 0xfd, 0x63, 0xe0, 0x6b, 0x70, 0xdb, 0x8b, 0xf0, + 0xe3, 0x0e, 0x36, 0x63, 0xe0, 0xbf, 0x2e, 0x5d, 0x66, 0x43, 0x42, 0x32, + 0x08, 0xf4, 0x13, 0x4e, 0x43, 0x2a, 0x39, 0x25, 0x18, 0xa1, 0x33, 0xc9, + 0x00, 0xf9, 0xec, 0x37, 0x84, 0x5b, 0xc2, 0x38, 0x4b, 0x7a, 0x26, 0xc3, + 0x37, 0x0c, 0xca, 0x59, 0x07, 0x4a, 0x84, 0x1e, 0xc9, 0x49, 0x9e, 0x47, + 0x53, 0xc9, 0x82, 0x07, 0x21, 0xd3, 0xc1, 0xc5, 0x0d, 0x0b, 0x0f, 0xf4, + 0xd2, 0x05, 0x3d, 0xf2, 0x41, 0xcf, 0x5d, 0xd0, 0x63, 0x1f, 0xf4, 0x8d, + 0x02, 0x2d, 0xc7, 0x74, 0x79, 0xae, 0x58, 0xe7, 0xce, 0x38, 0x3a, 0x6c, + 0x33, 0x23, 0x4f, 0x07, 0xdb, 0x45, 0xdb, 0x67, 0xa2, 0xec, 0x2d, 0x69, + 0x6c, 0x21, 0xef, 0x76, 0xbb, 0x7f, 0xe3, 0xdc, 0xb9, 0x85, 0x6f, 0xec, + 0xa3, 0xd8, 0xef, 0xf1, 0x68, 0xe6, 0x85, 0x6b, 0x9b, 0xd6, 0x09, 0x84, + 0x06, 0xd2, 0x9d, 0xe8, 0x2f, 0x30, 0x74, 0xc3, 0xb0, 0x17, 0xc1, 0x7f, + 0xdc, 0x8c, 0xdf, 0xa4, 0x17, 0xc5, 0x55, 0xf9, 0xeb, 0x2a, 0x41, 0xbf, + 0x41, 0x19, 0x58, 0x04, 0xed, 0x90, 0xd7, 0x8e, 0xd4, 0x52, 0x89, 0x4d, + 0x4a, 0x87, 0x6a, 0xd8, 0x8e, 0x9c, 0x04, 0xfa, 0x1a, 0x07, 0x9b, 0x58, + 0x29, 0xb1, 0x2c, 0xf4, 0xe0, 0xa5, 0x97, 0x38, 0xe8, 0x4b, 0xd1, 0xbb, + 0x00, 0x99, 0xf3, 0x4e, 0x85, 0xa3, 0x84, 0xc8, 0x38, 0x90, 0xb2, 0x51, + 0xa8, 0x69, 0x16, 0x75, 0x91, 0xe0, 0x4e, 0xe8, 0x37, 0xd1, 0x54, 0xab, + 0x71, 0x74, 0x10, 0x8d, 0x27, 0x26, 0xd0, 0xb7, 0x00, 0xa4, 0x09, 0x42, + 0x40, 0xd9, 0xf7, 0x41, 0x39, 0xd5, 0x9e, 0xc0, 0x0c, 0x92, 0x27, 0x96, + 0x44, 0x17, 0xf3, 0xbf, 0x80, 0xcd, 0xf0, 0x5d, 0x6e, 0xb3, 0xf4, 0x70, + 0x70, 0xa4, 0x80, 0xc2, 0x6e, 0xb8, 0x02, 0x1a, 0x6b, 0xb0, 0x7d, 0xd8, + 0xc3, 0xed, 0xea, 0xec, 0x11, 0x78, 0x34, 0xdf, 0x64, 0xa0, 0x70, 0x98, + 0x28, 0x9b, 0x7e, 0x9e, 0x2c, 0xd3, 0xf5, 0xe7, 0x60, 0xc9, 0xe2, 0xae, + 0x09, 0xce, 0xda, 0x4e, 0x07, 0x9f, 0x65, 0x0b, 0xbb, 0x7e, 0x2a, 0x37, + 0xa4, 0x3f, 0x63, 0x68, 0x16, 0xb2, 0x8e, 0x9f, 0x3f, 0xea, 0xb1, 0x4d, + 0x69, 0x49, 0x9c, 0xda, 0x02, 0xef, 0x1b, 0x6b, 0x4c, 0xbd, 0x1e, 0xc5, + 0x60, 0x06, 0x73, 0xca, 0x5c, 0x47, 0x33, 0xb2, 0xaa, 0x08, 0xc4, 0x99, + 0x78, 0xb6, 0xab, 0xb3, 0xb1, 0x4a, 0xd7, 0xc9, 0xd7, 0x54, 0xd9, 0x69, + 0xf4, 0x70, 0xa2, 0xe7, 0xb1, 0x78, 0x09, 0xa7, 0x38, 0x6f, 0x87, 0xdc, + 0xce, 0x73, 0x43, 0xfa, 0xeb, 0x38, 0xa1, 0xe2, 0xae, 0x91, 0x4c, 0x41, + 0x05, 0x4a, 0x71, 0x94, 0x3c, 0x5f, 0xa6, 0xab, 0x15, 0x0b, 0x36, 0x37, + 0x4f, 0x66, 0xbb, 0x22, 0xbd, 0xdc, 0xad, 0x44, 0x78, 0x5e, 0x01, 0x52, + 0xcc, 0xbe, 0x4f, 0xd6, 0x74, 0xdb, 0x99, 0xce, 0x38, 0xbd, 0x1e, 0x5d, + 0x15, 0xc5, 0x16, 0xa2, 0x45, 0xe5, 0x05, 0xac, 0x1d, 0xc0, 0xb8, 0x9b, + 0x5d, 0xae, 0x36, 0x37, 0x60, 0x95, 0xae, 0x0f, 0x7e, 0xd8, 0x25, 0x39, + 0xed, 0xc7, 0x1e, 0x8c, 0x5e, 0x1d, 0x1f, 0x1f, 0xbd, 0x3a, 0x7c, 0x78, + 0x30, 0xdf, 0xa5, 0x2b, 0x3c, 0x03, 0xd1, 0x9f, 0xf5, 0x89, 0x6c, 0x9f, + 0xfc, 0xac, 0x7e, 0xba, 0xee, 0x5f, 0x15, 0xd7, 0xab, 0x23, 0xe3, 0x61, + 0x3c, 0x30, 0x0e, 0x2b, 0x66, 0x62, 0xf8, 0xd7, 0x37, 0xc0, 0xc9, 0x3c, + 0x2e, 0x7f, 0xbd, 0x6c, 0xf8, 0xe7, 0xf2, 0x9d, 0xe4, 0xb7, 0x39, 0x62, + 0xcc, 0x00, 0xfb, 0xe0, 0x33, 0xcb, 0x96, 0x02, 0x8d, 0x19, 0xbd, 0x6a, + 0x06, 0xec, 0x07, 0x4f, 0x55, 0x20, 0x11, 0x8e, 0x07, 0xdc, 0xa7, 0x51, + 0x76, 0x2e, 0xba, 0x20, 0x8f, 0x37, 0x96, 0x0e, 0x09, 0x50, 0x53, 0xd7, + 0xf4, 0x41, 0x57, 0x60, 0xd9, 0xa9, 0x40, 0x42, 0x4f, 0x55, 0x75, 0xd2, + 0xc8, 0x91, 0xa2, 0x30, 0x32, 0xa0, 0xb2, 0xae, 0x64, 0x52, 0x60, 0x99, + 0x24, 0x58, 0xf5, 0xa9, 0x8d, 0x9d, 0x8b, 0xda, 0x53, 0xea, 0xe3, 0x55, + 0xbe, 0x8a, 0x61, 0x4c, 0x12, 0x6d, 0x85, 0xdb, 0xe9, 0x18, 0x2a, 0x04, + 0x0f, 0x89, 0xbc, 0xd0, 0xed, 0x78, 0xb0, 0xe3, 0xb0, 0x42, 0xef, 0xa5, + 0xca, 0xa2, 0x31, 0x69, 0xd2, 0xe5, 0x8b, 0xab, 0x34, 0x1f, 0x54, 0xf7, + 0xf2, 0x8c, 0x09, 0x53, 0x95, 0x9f, 0x14, 0x19, 0x50, 0xdf, 0x21, 0xdc, + 0xc9, 0x0a, 0xae, 0xfd, 0xdf, 0xa4, 0xd8, 0xe3, 0x43, 0x2c, 0x07, 0x70, + 0x19, 0x6e, 0x39, 0x50, 0x12, 0x68, 0x14, 0x38, 0xba, 0xb4, 0x86, 0xd7, + 0x77, 0x4f, 0x96, 0xc8, 0x1d, 0x24, 0x4b, 0xbf, 0x8a, 0xbf, 0x03, 0xf9, + 0x31, 0x98, 0x8a, 0x59, 0xf6, 0x01, 0xcb, 0x16, 0x03, 0xdc, 0xe8, 0x15, + 0xfc, 0x14, 0xa4, 0x25, 0x3a, 0x3d, 0xfe, 0xc3, 0xae, 0xc8, 0x15, 0x9b, + 0x2d, 0x02, 0xc3, 0x36, 0x37, 0xbe, 0x9b, 0x53, 0x0b, 0x0a, 0x9e, 0x9a, + 0xd8, 0xd6, 0x26, 0xc3, 0xe1, 0x69, 0x7f, 0x95, 0xc0, 0xc4, 0x0b, 0x25, + 0x48, 0x01, 0x84, 0x53, 0x13, 0x2c, 0x5b, 0xca, 0x5b, 0x1b, 0xcd, 0xa2, + 0xdf, 0x50, 0x8e, 0xf7, 0x67, 0x28, 0x6b, 0x07, 0x66, 0x66, 0xc6, 0xdd, + 0x43, 0xb3, 0xf4, 0x06, 0x84, 0xd1, 0x5a, 0x25, 0x05, 0xd7, 0x36, 0xef, + 0xd0, 0x4c, 0x30, 0x29, 0xba, 0xcd, 0x56, 0x8b, 0x4b, 0x67, 0x1a, 0xb4, + 0xa9, 0xd4, 0x5a, 0xf9, 0xbd, 0xab, 0x52, 0xa0, 0x20, 0x35, 0x53, 0x46, + 0x49, 0x38, 0xda, 0x8a, 0xb9, 0x45, 0x98, 0x5b, 0xc8, 0xef, 0x33, 0xd4, + 0x09, 0xfc, 0x78, 0x23, 0x2a, 0xbf, 0xeb, 0x5b, 0xfb, 0x12, 0xe3, 0x4e, + 0xc5, 0xb8, 0x53, 0x30, 0xee, 0x0c, 0x0c, 0xc1, 0xc6, 0x59, 0x06, 0x2e, + 0xff, 0x55, 0x8a, 0x1e, 0xea, 0xed, 0xdd, 0x78, 0xbb, 0x59, 0xcd, 0xb2, + 0x18, 0x66, 0x01, 0x77, 0xc8, 0xaa, 0x23, 0xa4, 0x44, 0xf4, 0x26, 0xa7, + 0x28, 0x89, 0x19, 0xe1, 0xa6, 0xbf, 0x4f, 0xb7, 0x14, 0x5f, 0x1a, 0xa8, + 0xdc, 0x75, 0x41, 0x3e, 0x60, 0x06, 0xd2, 0x35, 0xc8, 0x26, 0x07, 0x6d, + 0x99, 0x15, 0x30, 0xc0, 0xd2, 0xf0, 0x9b, 0xa7, 0x17, 0xf0, 0x79, 0xa9, + 0x0c, 0xb4, 0xce, 0xd3, 0x86, 0xe0, 0xdb, 0xed, 0x12, 0x7b, 0x4f, 0xce, + 0xae, 0xc6, 0x05, 0x5d, 0x96, 0x01, 0xd6, 0xc6, 0xf0, 0x2d, 0x86, 0x0a, + 0x59, 0xfc, 0xd3, 0x02, 0x5d, 0xba, 0xdc, 0xb1, 0xf2, 0xa9, 0x60, 0x32, + 0x27, 0x78, 0xfe, 0x8f, 0x56, 0x2d, 0x19, 0x3b, 0x69, 0x1e, 0x6d, 0xd3, + 0xdb, 0x64, 0x05, 0x69, 0x08, 0xc3, 0x1b, 0x9a, 0xda, 0x8a, 0x62, 0x20, + 0x0d, 0xec, 0xb2, 0xb3, 0xcd, 0xcd, 0xc7, 0xec, 0x00, 0xef, 0x54, 0x69, + 0xeb, 0x89, 0x0d, 0x38, 0xbb, 0xf8, 0x6e, 0x97, 0x17, 0xc9, 0xc5, 0x37, + 0x28, 0x6c, 0x30, 0xc0, 0x1c, 0x90, 0x7b, 0x71, 0x30, 0x50, 0x43, 0x8b, + 0xb3, 0x71, 0xfc, 0xac, 0x7f, 0x44, 0xd1, 0x64, 0xcf, 0x31, 0x8a, 0xd1, + 0xd9, 0x10, 0x0d, 0x35, 0x7c, 0x8f, 0x81, 0x21, 0x55, 0xa2, 0xc0, 0xb1, + 0x93, 0xc7, 0xae, 0xbf, 0x68, 0x74, 0x26, 0xef, 0xdc, 0x45, 0xdf, 0xed, + 0xa9, 0x68, 0x12, 0xa7, 0x74, 0x99, 0xb0, 0xc8, 0x04, 0xd6, 0x95, 0xb9, + 0x98, 0xb3, 0xe4, 0x87, 0x5d, 0x9a, 0x01, 0xc1, 0x87, 0x51, 0xbe, 0xda, + 0x14, 0xb9, 0x90, 0xbb, 0x24, 0x69, 0x53, 0xa4, 0xe6, 0x22, 0x67, 0x42, + 0x08, 0x14, 0x6a, 0x14, 0xcb, 0x2a, 0xbe, 0x24, 0x9b, 0xa4, 0x8b, 0x6e, + 0x86, 0xe4, 0x60, 0xe2, 0xd2, 0x9d, 0x2b, 0x9a, 0x35, 0x81, 0xde, 0x38, + 0x9a, 0x2c, 0x9f, 0xc1, 0xaa, 0xcd, 0x8c, 0x87, 0x90, 0xcb, 0xa2, 0x03, + 0x7f, 0xe3, 0x8a, 0xd9, 0xd7, 0x68, 0x30, 0x74, 0x96, 0x72, 0x06, 0xb3, + 0xa4, 0x1e, 0x9b, 0xe2, 0xf5, 0x68, 0x32, 0x47, 0xb3, 0xd9, 0xfc, 0xc7, + 0x31, 0x4c, 0xa4, 0x63, 0x60, 0xa1, 0xa7, 0x94, 0xd5, 0x63, 0xd4, 0xba, + 0x2e, 0x1d, 0x5a, 0x6d, 0xaf, 0x66, 0xa8, 0x68, 0x47, 0x47, 0x56, 0x31, + 0x64, 0x52, 0xce, 0x48, 0x3a, 0x48, 0x1c, 0x0a, 0x9c, 0x78, 0x01, 0x40, + 0x62, 0x23, 0x00, 0x62, 0x0c, 0x55, 0x82, 0x8d, 0x01, 0x8c, 0x18, 0xae, + 0x84, 0x3a, 0x04, 0x28, 0xc6, 0x9c, 0x6f, 0xed, 0x5a, 0x1f, 0xe8, 0xb7, + 0x3b, 0x65, 0xe9, 0x81, 0xb4, 0x88, 0x86, 0xc7, 0xa1, 0xb1, 0x32, 0xac, + 0x1b, 0x25, 0xdd, 0x4c, 0x43, 0x81, 0x34, 0x60, 0xe7, 0x3f, 0x64, 0x45, + 0x7c, 0x0b, 0xed, 0x8c, 0x7c, 0xdc, 0xc1, 0xe7, 0x9d, 0x6a, 0x67, 0xc1, + 0x16, 0x08, 0x40, 0x28, 0x6a, 0x3d, 0x8e, 0x61, 0x71, 0xe3, 0x96, 0x00, + 0xe4, 0xa2, 0x9c, 0x30, 0x82, 0x46, 0xd9, 0xc2, 0x9c, 0xc0, 0xa7, 0x1a, + 0x89, 0x18, 0x7e, 0x82, 0x0a, 0x42, 0x47, 0xf9, 0xfd, 0xb7, 0x5e, 0xf4, + 0xfb, 0x6f, 0xe7, 0x90, 0x00, 0x73, 0x66, 0x91, 0x2d, 0x68, 0x02, 0x22, + 0x88, 0x96, 0x00, 0xa1, 0x5e, 0xe0, 0x24, 0x4b, 0x38, 0x59, 0x70, 0x8c, + 0xb4, 0x81, 0x6b, 0xee, 0x78, 0xe0, 0xdc, 0x29, 0x56, 0x1c, 0x11, 0xd2, + 0x5e, 0x40, 0xd5, 0xf9, 0xaa, 0xd1, 0x1a, 0x4d, 0x48, 0x8b, 0x2b, 0xe8, + 0xd3, 0xa0, 0x2f, 0x2c, 0x0b, 0xa8, 0x49, 0x70, 0x45, 0x46, 0x40, 0x68, + 0x04, 0x30, 0xf0, 0x01, 0x0c, 0x40, 0x71, 0x32, 0x07, 0xba, 0x19, 0xa7, + 0x01, 0xb8, 0xf1, 0x28, 0xea, 0x73, 0x49, 0xce, 0xf3, 0x38, 0x26, 0xac, + 0x17, 0xd0, 0x93, 0xef, 0x83, 0xdb, 0xaf, 0xca, 0x3c, 0x1b, 0x81, 0xa6, + 0xc3, 0xff, 0xf3, 0x91, 0xb6, 0x32, 0x48, 0x08, 0x6f, 0xc2, 0xec, 0x01, + 0x8e, 0x88, 0x51, 0x99, 0x76, 0x70, 0xcd, 0xf8, 0x4c, 0xe2, 0xa2, 0x46, + 0x9d, 0xb1, 0xc2, 0xa1, 0xc9, 0x40, 0x37, 0xce, 0xf5, 0x49, 0xbb, 0x46, + 0x73, 0xa4, 0xd2, 0x1c, 0x57, 0xd3, 0x04, 0x5a, 0x8c, 0x6c, 0x0d, 0xcd, + 0xb1, 0x4a, 0xf3, 0xb0, 0x9a, 0xe6, 0x50, 0xd2, 0xbc, 0xad, 0xa2, 0x79, + 0xa8, 0xd2, 0x7c, 0x58, 0x4b, 0xb3, 0x64, 0xb5, 0x8a, 0xe6, 0x43, 0x95, + 0xe6, 0x51, 0x6d, 0xdd, 0x87, 0x21, 0x34, 0x8f, 0x54, 0x9a, 0xc7, 0x61, + 0x6d, 0x34, 0x94, 0x75, 0xa7, 0x4e, 0x2f, 0x15, 0xe2, 0xba, 0xd4, 0xc0, + 0x3e, 0x2f, 0x9b, 0xa0, 0xa4, 0x0b, 0xb2, 0x04, 0x62, 0x44, 0x8b, 0x42, + 0x92, 0x5d, 0x43, 0x02, 0xff, 0x9c, 0xd3, 0xe7, 0xb9, 0xe2, 0x7a, 0x8a, + 0x3b, 0x20, 0x59, 0x6f, 0xd9, 0x9b, 0x13, 0x55, 0x11, 0x4a, 0x0c, 0x04, + 0x36, 0x12, 0xc3, 0x16, 0xd8, 0xc7, 0x73, 0xbd, 0x8f, 0x43, 0x0a, 0xe8, + 0x30, 0x94, 0xc5, 0xbe, 0x2c, 0xf9, 0x17, 0x28, 0xd7, 0x5a, 0x30, 0xa7, + 0xcb, 0x65, 0x2b, 0x18, 0xe7, 0x62, 0x8c, 0xa6, 0xaa, 0x2e, 0x66, 0x51, + 0xc2, 0x00, 0xff, 0x79, 0x2c, 0x56, 0x9a, 0xa8, 0x45, 0x29, 0x99, 0xc6, + 0xac, 0x74, 0x5d, 0x46, 0x4e, 0x1b, 0xe8, 0x0f, 0x0a, 0x48, 0x20, 0x7f, + 0xf8, 0xc3, 0xb3, 0x12, 0xe6, 0x5c, 0xca, 0xd1, 0x5f, 0x36, 0x69, 0x7d, + 0x99, 0x4c, 0xa7, 0x99, 0xe8, 0xfa, 0xd2, 0xe9, 0xc9, 0x17, 0x8f, 0x3e, + 0x7f, 0x8c, 0x8b, 0x5f, 0xd5, 0xaf, 0x0b, 0x10, 0xea, 0x02, 0xdf, 0x89, + 0xc7, 0xbb, 0x98, 0xd5, 0xef, 0x0c, 0x48, 0xa1, 0x18, 0x58, 0x70, 0xa6, + 0xd4, 0x75, 0x18, 0x82, 0x84, 0x2a, 0x36, 0x75, 0xec, 0x17, 0x26, 0x3a, + 0xef, 0x7e, 0xf6, 0x09, 0x6d, 0xd5, 0x40, 0xda, 0x66, 0x76, 0x91, 0x5c, + 0xc0, 0x74, 0x54, 0x34, 0x40, 0xb9, 0x47, 0x21, 0xdb, 0x1c, 0x0a, 0xc2, + 0x96, 0xcd, 0x76, 0xeb, 0x28, 0x4f, 0xd7, 0x8b, 0x24, 0x02, 0x74, 0x0c, + 0xfd, 0xb8, 0x22, 0x5c, 0x7a, 0xd5, 0x24, 0xc3, 0xa8, 0x91, 0x7c, 0x25, + 0x35, 0x29, 0xe8, 0xee, 0x17, 0xbb, 0x2e, 0xe3, 0x8a, 0xaf, 0xcf, 0x8f, + 0x41, 0x22, 0x8e, 0xbc, 0x09, 0x81, 0xc0, 0x74, 0x69, 0x62, 0x58, 0x85, + 0xf7, 0x0c, 0x64, 0x59, 0x01, 0x6f, 0x21, 0xcd, 0xd8, 0x65, 0x85, 0x04, + 0x6d, 0x02, 0x01, 0xfd, 0x74, 0x38, 0xa4, 0x64, 0x7d, 0x35, 0x4f, 0xa6, + 0x57, 0xbc, 0x6b, 0x4e, 0x6e, 0x18, 0x1b, 0x1c, 0x55, 0x59, 0xbf, 0x71, + 0x90, 0x2f, 0xb2, 0x74, 0x5b, 0xbc, 0x09, 0x49, 0xf4, 0x73, 0xbe, 0xb9, + 0xb8, 0x83, 0x1f, 0x6f, 0x1c, 0xe0, 0xea, 0xcd, 0x9b, 0x7f, 0x00, 0xd4, + 0x4d, 0x20, 0xf1, 0xa1, 0x9f, 0x01, 0x00 }; diff --git a/Arduino/McLighting/json_functions.h b/Arduino/McLighting/json_functions.h index 9967a027..84fb74f3 100644 --- a/Arduino/McLighting/json_functions.h +++ b/Arduino/McLighting/json_functions.h @@ -136,9 +136,15 @@ void getConfigJSON() { } char * listModesJSON() { - const size_t bufferSize = JSON_ARRAY_SIZE(strip->getModeCount() + 1) + (strip->getModeCount() + 1)*JSON_OBJECT_SIZE(2) + 2000; + const size_t bufferSize = JSON_ARRAY_SIZE(strip->getModeCount() + 3) + (strip->getModeCount() + 1)*JSON_OBJECT_SIZE(2) + 2000; DynamicJsonDocument jsonBuffer(bufferSize); JsonArray root = jsonBuffer.to(); + JsonObject objecttoggle = root.createNestedObject(); + objecttoggle["mode"] = "toggle"; + objecttoggle["name"] = "TOGGLE"; + JsonObject objecton = root.createNestedObject(); + objecton["mode"] = "on"; + objecton["name"] = "ON"; JsonObject objectoff = root.createNestedObject(); objectoff["mode"] = "off"; objectoff["name"] = "OFF"; diff --git a/Arduino/McLighting/request_handlers.h b/Arduino/McLighting/request_handlers.h index 1dc18f1c..fa1c68bc 100644 --- a/Arduino/McLighting/request_handlers.h +++ b/Arduino/McLighting/request_handlers.h @@ -150,14 +150,23 @@ void handleRangeDifferentColors(uint8_t * mypayload) { bool setModeByStateString(String saved_state_string) { if (getValue(saved_state_string, '|', 0) == "STA") { DBG_OUTPUT_PORT.printf("Parsed state: %s\r\n", saved_state_string.c_str()); + String str_mode = getValue(saved_state_string, '|', 1); State.mode = static_cast(str_mode.toInt()); + String str_fx_mode = getValue(saved_state_string, '|', 2); fx_mode = str_fx_mode.toInt(); - String str_fx_speed = getValue(saved_state_string, '|', 3); - segState.speed[State.segment] = str_fx_speed.toInt(); + + String _fx_speed = getValue(saved_state_string, '|', 3); + segState.speed[State.segment] = _fx_speed.toInt(); + #if defined(ENABLE_MQTT) + //snprintf(mqtt_buf, sizeof(mqtt_buf), "OK ?%i", _fx_speed); + //sendmqtt(); + #endif + String str_brightness = getValue(saved_state_string, '|', 4); State.brightness = str_brightness.toInt(); + String str_red = getValue(saved_state_string, '|', 5); main_color.red = str_red.toInt(); String str_green = getValue(saved_state_string, '|', 6); @@ -166,6 +175,7 @@ bool setModeByStateString(String saved_state_string) { main_color.blue = str_blue.toInt(); String str_white = getValue(saved_state_string, '|', 8); main_color.white = str_white.toInt(); + str_red = getValue(saved_state_string, '|', 9); back_color.red = str_red.toInt(); str_green = getValue(saved_state_string, '|', 10); @@ -174,6 +184,7 @@ bool setModeByStateString(String saved_state_string) { back_color.blue = str_blue.toInt(); str_white = getValue(saved_state_string, '|', 12); back_color.white = str_white.toInt(); + str_red = getValue(saved_state_string, '|', 13); xtra_color.red = str_red.toInt(); str_green = getValue(saved_state_string, '|', 14); @@ -182,10 +193,9 @@ bool setModeByStateString(String saved_state_string) { xtra_color.blue = str_blue.toInt(); str_white = getValue(saved_state_string, '|', 16); xtra_color.white = str_white.toInt(); + DBG_OUTPUT_PORT.print("Set to state: "); DBG_OUTPUT_PORT.println(listStateJSON()); - //prevmode=mode; - //State.mode = SET; return true; } else { DBG_OUTPUT_PORT.println("Saved state not found!"); @@ -199,12 +209,39 @@ void handleSetWS2812FXMode(uint8_t * mypayload) { fx_mode = (uint8_t) strtol((const char *) &mypayload[1], NULL, 10); fx_mode = constrain(fx_mode, 0, strip->getModeCount() - 1); State.mode = SET; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /%i", fx_mode); + sendmqtt(); + #endif } else { - if (strcmp((char *) &mypayload[1], "off") == 0) { - if (State.mode == OFF) { State.mode = SET; } else { State.mode = OFF; }; + if (strcmp((char *) &mypayload[1], "toggle") == 0) { + if (State.mode == OFF) { + State.mode = SET; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /%i", segState.mode[State.segment]); + sendmqtt(); + #endif + } else { + State.mode = OFF; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /off", ""); + sendmqtt(); + #endif + } } if (strcmp((char *) &mypayload[1], "on") == 0) { State.mode = SET; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /%i", segState.mode[State.segment]); + sendmqtt(); + #endif + } + if (strcmp((char *) &mypayload[1], "off") == 0) { + State.mode = OFF; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /off", ""); + sendmqtt(); + #endif } } } @@ -276,7 +313,11 @@ void checkpayload(uint8_t * _payload, bool mqtt = false, uint8_t num = 0) { //memcpy(hexcolors_trans, segState.colors[State.segment], sizeof(hexcolors_trans)); _updateState = true; Dbg_Prefix(mqtt, num); - DBG_OUTPUT_PORT.printf("Set segment to: [%u]\r\n", State.segment); + DBG_OUTPUT_PORT.printf("Set segment to: [%u]\r\n", _seg); + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK Ss%i", _seg); + sendmqtt(); + #endif } } // / ==> Set segment first LED @@ -289,6 +330,10 @@ void checkpayload(uint8_t * _payload, bool mqtt = false, uint8_t num = 0) { setSegmentSize(); Dbg_Prefix(mqtt, num); DBG_OUTPUT_PORT.printf("Set segment start to: [%u]\r\n", _seg_start); + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK S[%i", _seg_start); + sendmqtt(); + #endif } } // / ==> Set segment last LED @@ -301,18 +346,25 @@ void checkpayload(uint8_t * _payload, bool mqtt = false, uint8_t num = 0) { setSegmentSize(); Dbg_Prefix(mqtt, num); DBG_OUTPUT_PORT.printf("Set segment stop to: [%u]\r\n", _seg_stop); + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK S]%i", _seg_stop); + sendmqtt(); + #endif } } if (_payload[1] == 'o') { - char _fx_options[4]; - snprintf(_fx_options, sizeof(_fx_options), "%s", &_payload[2]); - _fx_options[3] = 0x00; - if (((constrain(atoi(_fx_options), 0, 255)>>1)<<1) != segState.options) { - segState.options= ((constrain(atoi(_fx_options), 0, 255)>>1)<<1); + uint8_t _fx_options = (uint8_t) strtol((const char *) &_payload[2], NULL, 10); + _fx_options = ((constrain(_fx_options, 0, 255)>>1)<<1); + if (_fx_options != segState.options) { + segState.options= _fx_options; _updateSegState = true; strip->setOptions(State.segment, segState.options); Dbg_Prefix(mqtt, num); - DBG_OUTPUT_PORT.printf("Set segment options to: [%u]\r\n", segState.options); + DBG_OUTPUT_PORT.printf("Set segment options to: [%u]\r\n", _fx_options); + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK So%i", _fx_options); + sendmqtt(); + #endif } } char * buffer = listSegmentStateJSON(State.segment); @@ -373,11 +425,17 @@ void checkpayload(uint8_t * _payload, bool mqtt = false, uint8_t num = 0) { // ? ==> Set speed if (_payload[0] == '?') { uint16_t _fx_speed = (uint16_t) strtol((const char *) &_payload[1], NULL, 10); - segState.speed[State.segment] = constrain(_fx_speed, SPEED_MIN, SPEED_MAX ); + _fx_speed = constrain(_fx_speed, SPEED_MIN, SPEED_MAX ); + //if (segState.speed[State.segment] != _fx_speed) {} State.mode = SET; + segState.speed[State.segment] = _fx_speed; _updateSegState = true; Dbg_Prefix(mqtt, num); - DBG_OUTPUT_PORT.printf("Set speed to: [%u]\r\n", segState.speed[State.segment]); + DBG_OUTPUT_PORT.printf("Set speed to: [%u]\r\n", _fx_speed); + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK ?%i", _fx_speed); + sendmqtt(); + #endif } // % ==> Set brightness @@ -389,6 +447,10 @@ void checkpayload(uint8_t * _payload, bool mqtt = false, uint8_t num = 0) { Dbg_Prefix(mqtt, num); DBG_OUTPUT_PORT.printf("Set brightness to: [%u]\r\n", State.brightness); _updateState = true; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK %%%i", State.brightness); + sendmqtt(); + #endif } } @@ -432,6 +494,7 @@ void checkpayload(uint8_t * _payload, bool mqtt = false, uint8_t num = 0) { } #if defined(ENABLE_STATE_SAVE) if (_updateState) { + //State.mode = SET; if(save_state.active()) save_state.detach(); save_state.once(3, tickerSaveState); } @@ -941,7 +1004,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght ha_send_data.detach(); mqtt_client->subscribe(mqtt_ha_state_in, qossub); ha_send_data.once(DELAY_MQTT_HA_MESSAGE, tickerSendState); - #if defined(MQTT_HOME_ASSISTANT_SUPPORT) + #if defined(MQTT_HOMEASSISTANT_SUPPORT) const size_t bufferSize = JSON_ARRAY_SIZE(strip->getModeCount()+ 4) + JSON_OBJECT_SIZE(11) + 1500; DynamicJsonDocument jsonBuffer(bufferSize); JsonObject root = jsonBuffer.to(); @@ -1047,7 +1110,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght ha_send_data.detach(); uint16_t packetIdSub2 = mqtt_client->subscribe((char *)mqtt_ha_state_in, qossub); DBG_OUTPUT_PORT.printf("Subscribing at QoS %d, packetId: ", qossub); DBG_OUTPUT_PORT.println(packetIdSub2); - #if defined(MQTT_HOME_ASSISTANT_SUPPORT) + #if defined(MQTT_HOMEASSISTANT_SUPPORT) const size_t bufferSize = JSON_ARRAY_SIZE(strip->getModeCount()+ 4) + JSON_OBJECT_SIZE(11) + 1500; DynamicJsonDocument jsonBuffer(bufferSize); JsonObject root = jsonBuffer.to(); diff --git a/Arduino/McLighting/rest_api.h b/Arduino/McLighting/rest_api.h index 52e3b80b..553b2842 100644 --- a/Arduino/McLighting/rest_api.h +++ b/Arduino/McLighting/rest_api.h @@ -84,6 +84,7 @@ server.on("/restart", []() { DBG_OUTPUT_PORT.printf("/restart\r\n"); server.sendHeader("Access-Control-Allow-Origin", "*"); server.send(200, "text/plain", "restarting..." ); + delay(1000); ESP.restart(); }); @@ -318,8 +319,20 @@ server.on("/config", []() { getConfigJSON(); }); -server.on("/off", []() { - if (State.mode == OFF) { State.mode = SET; } else { State.mode = OFF; }; +server.on("/toggle", []() { + if (State.mode == OFF) { + State.mode = SET; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /%i", segState.mode[State.segment]); + sendmqtt(); + #endif + } else { + State.mode = OFF; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /off", ""); + sendmqtt(); + #endif + } getACK("OK"); #if defined(ENABLE_STATE_SAVE) if(save_state.active()) save_state.detach(); @@ -330,6 +343,10 @@ server.on("/off", []() { server.on("/on", []() { if (prevmode == OFF) { State.mode = SET; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /%i", segState.mode[State.segment]); + sendmqtt(); + #endif getACK("OK"); #if defined(ENABLE_STATE_SAVE) if(save_state.active()) save_state.detach(); @@ -340,6 +357,23 @@ server.on("/on", []() { } }); +server.on("/off", []() { + if (State.mode == SET) { + State.mode = OFF; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /off", ""); + sendmqtt(); + #endif + getACK("OK"); + #if defined(ENABLE_STATE_SAVE) + if(save_state.active()) save_state.detach(); + save_state.once(3, tickerSaveState); + #endif + } else { + getACK("NOK"); + } +}); + server.on("/set", []() { prevmode = HOLD; boolean _updateState = false; @@ -354,6 +388,10 @@ server.on("/set", []() { //memcpy(hexcolors_trans, segState.colors[State.segment], sizeof(hexcolors_trans)); State.mode = SET; _updateState = true; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK Ss%i", _seg); + sendmqtt(); + #endif } } if ((server.arg("start") != "") && (server.arg("start").toInt() >= 0) && (server.arg("start").toInt() <= segState.stop)) { @@ -363,6 +401,10 @@ server.on("/set", []() { segState.start = _seg_start; setSegmentSize(); _updateSegState = true; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK S[%i", _seg_start); + sendmqtt(); + #endif } } if ((server.arg("stop") != "") && (server.arg("stop").toInt() >= segState.start) && (server.arg("stop").toInt() <= Config.stripSize)) { @@ -372,6 +414,10 @@ server.on("/set", []() { segState.stop = _seg_stop; setSegmentSize(); _updateSegState = true; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK S]%i", _seg_stop); + sendmqtt(); + #endif } } @@ -381,6 +427,10 @@ server.on("/set", []() { segState.options = _fx_options; strip->setOptions(State.segment, segState.options); _updateSegState = true; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK So%i", _fx_options); + sendmqtt(); + #endif } } //color wrgb @@ -475,14 +525,24 @@ server.on("/set", []() { // Speed if ((server.arg("s") != "") && (server.arg("s").toInt() >= 0) && (server.arg("s").toInt() <= 255)) { - segState.speed[State.segment] = constrain(server.arg("s").toInt(), 0, 255); + uint8_t _fx_speed = constrain(server.arg("s").toInt(), 0, 255); + segState.speed[State.segment] = _fx_speed; _updateSegState = true; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK ?%i", _fx_speed); + sendmqtt(); + #endif } + //Mode if ((server.arg("m") != "") && (server.arg("m").toInt() >= 0) && (server.arg("m").toInt() <= strip->getModeCount())) { fx_mode = constrain(server.arg("m").toInt(), 0, strip->getModeCount() - 1); if (fx_mode != segState.mode[State.segment]) { _updateSegState = true; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK /%i", fx_mode); + sendmqtt(); + #endif } } @@ -495,6 +555,10 @@ server.on("/set", []() { if (strip->getBrightness() != State.brightness) { State.mode = SET; _updateState = true; + #if defined(ENABLE_MQTT) + snprintf(mqtt_buf, sizeof(mqtt_buf), "OK %%%i", State.brightness); + sendmqtt(); + #endif } //DBG_OUTPUT_PORT.printf("Get Args: %s\r\n", listStateJSONfull()); //possibly causing heap problems getACK("OK"); diff --git a/Arduino/McLighting/version.h b/Arduino/McLighting/version.h index 5aaef448..140ae89a 100644 --- a/Arduino/McLighting/version.h +++ b/Arduino/McLighting/version.h @@ -1 +1 @@ -#define SKETCH_VERSION "3.1.1" \ No newline at end of file +#define SKETCH_VERSION "3.1.3" diff --git a/Arduino/McLighting/version_info.ino b/Arduino/McLighting/version_info.ino index 6b134296..93f67969 100644 --- a/Arduino/McLighting/version_info.ino +++ b/Arduino/McLighting/version_info.ino @@ -261,4 +261,17 @@ * 18 April 2020 * Version Bump to 3.1.1 * bugfixes regarding issue #80 - */ \ No newline at end of file + * + * 19 April 2020 + * Version Bump to 3.1.2 + * Almost finished: bugfixes regarding issue #80 + * ToDo: bugfixes regarding issue #70 + * + * 25.10.2020 + * Updated WS2812FX Lib + * Version Bump to 3.1.3 + * fixed issue #100 + * included pull request from issue #93 + * Fixed a GUI bug on reloading + * ToDo: bugfixes regarding issue #70 + */ diff --git a/clients/web/index.htm b/clients/web/index.htm index b56bd4c1..7b1c6920 100644 --- a/clients/web/index.htm +++ b/clients/web/index.htm @@ -1602,8 +1602,9 @@

warning

else xhr.open("GET", url, true); xhr.send(post); } + function getModes() { - document.getElementById("percentage").innerHTML = "0%"; + document.getElementById("percentage").innerHTML = "0%"; document.getElementById("percentage-done").setAttribute("stroke-dasharray", "0,100"); document.getElementById("modal-content").innerHTML = language.en.loadModes; xhttp("http://" + host + "/get_modes", false, function(e) { @@ -1611,7 +1612,7 @@

warning

if (e && e.substring(0,6) !== "ERROR!") { modes = JSON.parse(e); if (typeof modes[0] !== "undefined") { - modes.forEach(item => { + modes.forEach(item => { if (item.name && item.name.length > 0) { data.modes.push({ title: item.name, id: item.mode }); } @@ -1625,45 +1626,7 @@

warning

}); } -function getConfig() { - document.getElementById("percentage").innerHTML = "75%"; - document.getElementById("percentage-done").setAttribute("stroke-dasharray", "75,100"); - document.getElementById("modal-content").innerHTML = language.en.loadConfig; - xhttp("http://" + host + "/config", false, function(e) { - console.log("Getting config via REST:", e); - if (e && e.substring(0,6) !== "ERROR!") { - var res = JSON.parse(e); - if (res) { - if (typeof res.hostname !== "undefined") config.hostname = res.hostname; - if (typeof res.mqtt_host !== "undefined") config.mqtt_host = res.mqtt_host; - if (typeof res.mqtt_port !== "undefined") config.mqtt_port = res.mqtt_port; - if (typeof res.mqtt_user !== "undefined") config.mqtt_user = res.mqtt_user; - if (typeof res.mqtt_pass !== "undefined") config.mqtt_pass = res.mqtt_pass; - if (typeof res.ws_seg !== "undefined") config.ws_seg = res.ws_seg; - if (typeof res.ws_cnt !== "undefined") config.ws_cnt = res.ws_cnt; - if (typeof res.ws_rgbo !== "undefined") { - config.ws_rgbo = res.ws_rgbo; - config.enable_rgbw = config.ws_rgbo.includes("W"); - } - if (typeof res.ws_pin !== "undefined") config.ws_pin = res.ws_pin; - if (typeof res.ws_trans !== "undefined") config.ws_trans = res.ws_trans; - } - } else { - console.error(e); - document.getElementById("percentage").innerHTML = language.en.error; - showSnackbar(language.en.loadError, "error", 5000); - } - if (config.enable_rgbw) { - document.getElementById("white").parentNode.className = ""; - } else { - document.getElementById("white").parentNode.className = "hidden"; - white.value = 0; - segstate.color.w = 0; - segstate.color.w2 = 0; - segstate.color.w3 = 0; - } - }); -} + function showModes(mode, index) { //console.log("Mode: " + mode.title + " - ID: " + mode.id + " - Hidden: " + mode.hidden); var div = document.createElement("DIV"); @@ -1691,7 +1654,7 @@

warning

document.getElementById("modes").appendChild(div); } function readSettings() { - document.getElementById("percentage").innerHTML = "25%"; + document.getElementById("percentage").innerHTML = "33%"; document.getElementById("percentage-done").setAttribute("stroke-dasharray", "25,100"); document.getElementById("modal-content").innerHTML = language.en.loadSettings; xhttp("http://" + host + "/uistate.json", false, function(e) { @@ -1711,6 +1674,7 @@

warning

} }); } + function applySettings() { // Make sure language contains all the words from English translation. if (settings.lang !== "en") { @@ -1723,6 +1687,7 @@

warning

translate(document.body); document.title = language[settings.lang].title; data.modes.forEach(mode => { + console.log("something"); mode.hidden = false; if (settings.visibility.indexOf(mode.id) > -1) { mode.hidden = true; @@ -2037,8 +2002,6 @@

warning

colmain.dispatchEvent(event); colfont.dispatchEvent(event); colback.dispatchEvent(event); - colbtn.dispatchEvent(event); - colbtns.dispatchEvent(event); document.getElementById("settings-open").addEventListener('click', ()=>{ var icons = document.getElementsByClassName("icon--link"); @@ -2159,7 +2122,7 @@

warning

function ws_connect() { data.connection = new ReconnectingWebSocket(ws_url, "arduino", ws_options); - document.getElementById("percentage").innerHTML = "75%"; + document.getElementById("percentage").innerHTML = "66%"; document.getElementById("percentage-done").setAttribute("stroke-dasharray", "75,100"); document.getElementById("modal-content").innerHTML = language[settings.lang].loadWebsock; @@ -2167,14 +2130,10 @@

warning

data.connection.onopen = function() { console.log("WebSocket open"); data.is_connected = true; - data.refresh_interval = setInterval(() => ws_send("$"), 10000); var con = document.getElementById("disconnected"); con.className = "hidden"; con = document.getElementById("connected"); con.className = con.className = ""; - //setTimeout(function() { ws_send("$"); }, 2000); - //setTimeout(function() { ws_send("C"); }, 3000); - //setTimeout(function() { ws_send("~"); }, 4000); document.getElementById("percentage").innerHTML = "100%"; document.getElementById("percentage-done").setAttribute("stroke-dasharray", "100,100"); document.getElementById("modal-content").innerHTML = language[settings.lang].loadReady; @@ -2205,6 +2164,7 @@

warning

// Log messages from the server data.connection.onmessage = function(e) { console.log("WebSocket from server: ", e.data); + console.log("data.init: ", data.init); try { var res = JSON.parse(e.data); // document.getElementById('modal').style.display = "none"; @@ -2311,10 +2271,9 @@

warning

// init display Colors displayColors(true); console.log("displayColors finished!"); - select_active_button(); - console.log("select_active_button finished!"); + select_active_button(); + console.log("select_active_button finished!"); } - console.log("data.init: ", data.init); if (data.init == true) { console.log("Initializing..."); // Set selected mode button @@ -2323,10 +2282,11 @@

warning

setTimeout(() => { document.getElementById('modal').style.display = "none"; document.getElementById('container').style.display = ""; - }, 500); + }, 50); initSettings(); initcolorSliders(); data.init = false; + data.refresh_interval = setInterval(() => ws_send("$"), 10000); } } catch (e) {} }; @@ -2361,7 +2321,7 @@

warning

function select_active_button() { btns = document.getElementsByClassName("btn"); - for (i = 0; i < btns.length; i++) { + for (i = 0; i < btns.length; i++) { btns[i].style.backgroundColor = settings.theme_btn; } if (state.mode != 1 || (state.mode == 1 && segstate.mode != 57)) { // CUSTOM WS MODE @@ -2374,8 +2334,9 @@

warning

segments.className = segments.className.replace(/\b hidden\b/g, ""); } if (state.mode >= 1) { - document.getElementById(segstate.mode).style.backgroundColor = settings.theme_btnsel; - if (segstate.mode == 56) { // AUTOPLAY + document.getElementById(segstate.mode).style.backgroundColor = settings.theme_btnsel; + document.getElementById("on").style.backgroundColor = settings.theme_btnsel; + if (segstate.mode == 56) { // AUTOPLAY disable_modebuttons(false); disable_color_selection(true); disable_bright_selection(false); @@ -2451,6 +2412,7 @@

warning

} select_active_button(); ws_send("/" + mode_id); + ws_send("$"); } function set_speed() { ws_send("?" + segstate.speed); @@ -2597,7 +2559,7 @@

warning

function drawCircle() { let radius = canvas.width / 2; let image = context.createImageData(2 * radius, 2 * radius); - let data = image.data; + let idata = image.data; for (let x = -radius; x < radius; x++) { for (let y = -radius; y < radius; y++) { @@ -2624,10 +2586,10 @@

warning

let [red, green, blue] = hsv2rgb(hue, saturation, value); let alpha = 255; - data[index] = red; - data[index + 1] = green; - data[index + 2] = blue; - data[index + 3] = alpha; + idata[index] = red; + idata[index + 1] = green; + idata[index + 2] = blue; + idata[index + 3] = alpha; } } this.context.putImageData(image, 0, 0); @@ -2682,15 +2644,17 @@

warning

document.addEventListener("DOMContentLoaded", function(event) { // Code to run since DOM is loaded and ready getModes(); - readSettings(); - ws_connect(); - ws_send("$"); - //ws_send("C"); - getConfig(); - canvas.width = 400; - canvas.height = 400; - redrawColorPicker(); + setTimeout(function() { + readSettings(); + }, 500); + setTimeout(function() { + ws_connect(); + ws_send("$"); + canvas.width = 400; + canvas.height = 400; + redrawColorPicker(); + }, 1000); }); - + \ No newline at end of file diff --git a/clients/web/index.htm.gz b/clients/web/index.htm.gz index c85a8981..c777c419 100644 Binary files a/clients/web/index.htm.gz and b/clients/web/index.htm.gz differ