Lots of changes:

* More animations with generalized code to display them.
  * The hostname will now include a unique id of the ESP.
  * Effect can now be restricted to a smaller "window".
  * Clock is now BigClock, SmallClock is now Clock.
  * Clock shows the time as well as the sinematrix effect. Closes #8.
  * If the loop takes too long too often, the ESP will automatically be rebooted. Closes #12.
  * The text drawing methods are now much more generalized. #5.
This commit is contained in:
Fabian Schlenz 2019-05-23 21:18:15 +02:00
parent deb3a753c8
commit 0e82f94846
8 changed files with 350 additions and 91 deletions

View File

@ -1,14 +1,160 @@
/**
* Animations are structured in AnimationData as follows:
*
* .colors contains .color_count 3-byte-color values. Color #0 is transparent - keep the
* color from the previous frame. Color #1 is the background color of "behind the gif".
*
*
* .offsets contains the frame start offsets within .data + the length of the data. (So
* you can always do something like `for (int i=anim.offsets[i]; i<anim.offsets[i+1]; i++)`.
* Accordingly it has a length of .frame_count+1.
*
* .data contains all frames data with a run-length compression with escape char 255.
* This data references the index of one or multiple pixels in .colors. It starts at the
* top left pixel and walks each row to the right before starting the next row.
* To decode it: Start at a frame (indicated by .offsets). Get one byte as x.
* If x is 0: This is a transparent pixel. On frame 0 this means "show the background
* color", on every other frame "keep the pixel from the previous frame".
* If x is >0 and <255: This pixel has the color indicated by .colors[x].
* if x is 255: Run-length-encoding. The next byte indicates of often the byte after that
* will be repeated. So, {255, 4, 10} is equal to {10, 10, 10, 10}.
* A special case that may happen in larger GIFs is that there are more than 255 repetitions
* of a color. Those will be split, so 355*color #10 will be: {255, 255, 10, 255, 100, 10},
* e.g. 255*10 + 100*10. Usually this shouldn't need special handling within a decoder.
*
* .individual_delays contains either 1 or .frame_count delays. They are given in ms and
* indicate how long the matching frame should be displayed. If all times are equal, then
* it contains only one entry and .individual_delays will be false.
*
* .w and .h contain the dimensions of the image.
**/
typedef struct { typedef struct {
uint32_t *colors; uint32_t *colors;
uint8_t *data; uint8_t *data;
uint16_t *offsets; uint16_t *offsets;
uint16_t *delays;
boolean individual_delays;
int color_count; int color_count;
int frame_count; int frame_count;
int w; int w;
int h; int h;
} AnimationData; } AnimationData;
uint32_t koopa_colors[] = {0x000000, 0x000000, 0xFF00FF, 0xB69A11, 0x303030, 0x8E0406, 0xFEFCFF, 0x03018A, 0x11EF12};
uint8_t koopa_data[] = {255,4,0,6,255,14,0,255,3,6,255,12,0,3,255,3,6,255,11,0,3,3,1,6,6,3,255,10,0,3,3,1,6,6,3,0,0,255,3,8,6,255,3,0,3,1,3,6,6,3,3,0,8,1,8,8,1,6,0,0,255,7,3,0,8,8,1,1,8,8,6,0,255,3,3,4,3,3,4,8,8,1,8,8,1,8,6,0,3,3,4,255,3,3,7,8,1,255,4,8,1,8,255,3,0,255,4,3,7,1,8,1,8,8,1,8,1,3,255,3,0,255,3,3,7,255,3,8,1,1,255,3,8,255,5,0,3,3,7,7,8,1,8,8,1,8,7,7,255,3,0,255,4,5,7,7,255,4,8,7,7,255,3,0,255,3,5,4,3,3,255,6,7,3,255,6,0,255,4,3,0,255,3,5,3,3,255,6,0,255,3,3,255,4,0,255,3,3,0,255,4,0,1,255,14,0,1,0,1,255,12,0,1,255,14,0,1,0,6,0,0,1,255,18,0,255,4,1,255,3,0,1,3,0,1,0,6,0,0,1,8,0,0,6,1,255,3,0,1,0,6,6,255,4,0,1,8,8,1,6,1,255,4,0,3,0,0,3,1,0,8,1,1,8,255,5,0,3,4,0,0,4,0,8,1,0,0,1,8,6,0,3,3,4,255,4,0,8,1,8,0,0,8,1,8,1,0,0,3,255,4,0,1,0,1,8,8,1,0,1,3,255,3,0,3,255,3,0,8,0,8,1,1,8,0,8,1,255,3,0,1,3,3,7,0,8,1,0,0,1,8,0,7,0,0,255,4,1,5,7,0,255,4,8,0,7,255,6,0,5,0,0,255,6,7,255,6,0,5,5,0,0,3,3,0,5,5,0,0,3,255,4,0,6,255,14,0,6,0,6,255,12,0,3,255,14,0,3,0,1,0,0,3,255,25,0,3,1,0,6,0,3,255,11,0,3,0,3,3,255,17,0,1,255,11,0,1,1,0,0,1,255,9,0,255,4,1,255,14,0,1,1,255,14,0,3,255,35,0,3,255,14,0,3,255,14,0,3,3,0,0,1,1,0,1,1,255,3,0,255,73,0,255,3,8,6,255,11,0,8,1,0,0,1,6,255,11,0,8,1,1,8,8,6,255,4,0,4,0,0,4,8,0,1,8,8,1,255,5,0,4,3,0,0,7,0,1,8,0,0,8,1,8,255,3,0,3,3,255,3,0,1,8,1,0,0,1,8,1,3,255,3,0,3,255,3,0,8,0,8,1,1,8,0,8,1,0,0,1,1,255,3,0,7,0,1,8,8,1,0,7,7,255,4,0,1,1,3,0,7,8,0,0,8,7,0,1,255,4,0,3,3,0,3,0,255,4,7,0,3,255,4,0,3,3,0,0,5,5,1,1,255,3,3,5,5,255,4,0,1,1,255,3,5,255,4,0,255,3,5,255,4,0,1,255,14,0,1,0,1,255,12,0,1,255,14,0,1,0,6,0,0,1,255,18,0,255,4,1,255,3,0,1,3,0,1,0,6,0,0,1,8,0,0,6,1,255,3,0,1,0,6,6,255,4,0,1,8,8,1,6,1,255,4,0,3,0,0,3,1,0,8,1,1,8,255,5,0,3,4,0,0,4,0,8,1,0,0,1,8,6,0,3,3,4,255,4,0,8,1,8,0,0,8,1,8,1,0,0,3,255,4,0,1,0,1,8,8,1,0,1,3,255,3,0,3,255,3,0,8,0,8,1,1,8,0,8,8,255,4,0,3,3,7,0,8,1,0,0,1,8,0,7,255,4,0,1,1,0,7,0,255,4,8,0,7,255,4,0,1,255,3,0,3,255,6,7,3,255,4,0,255,4,3,255,4,0,255,3,3,0,0,255,4,0,6,255,14,0,6,0,6,255,12,0,3,255,14,0,3,0,1,0,0,3,255,25,0,3,1,0,6,0,3,255,11,0,3,0,3,3,255,17,0,1,255,11,0,1,1,0,0,1,255,9,0,255,4,1,255,14,0,1,1,255,14,0,3,255,12,0,1,255,36,0,1,255,10,0,1,255,3,0,1,255,3,0,3,1,0,0,1,1,0,3,3}; uint32_t koopa_colors[] = {0x000000, 0x000000, 0xB69A11, 0x000000, 0x303030, 0x8E0406, 0xFEFCFF, 0x03018A, 0x11EF12};
uint8_t koopa_data[] = {
255,4,1,6,255,14,1,6,6,6,255,12,1,2,6,6,6,255,11,1,2,2,3,6,6,2,255,10,1,2,2,3,6,6,2,1,1,8,8,8,6,1,1,1,2,3,2,6,6,2,2,1,8,3,8,8,3,6,1,1,255,7,2,1,8,8,3,3,8,8,6,1,2,2,2,4,2,2,4,8,8,3,8,8,3,8,6,1,2,2,4,2,2,2,7,8,3,255,4,8,3,8,1,1,1,255,4,2,7,3,8,3,8,8,3,8,3,2,1,1,1,2,2,2,7,8,8,8,3,3,8,8,8,255,5,1,2,2,7,7,8,3,8,8,3,8,7,7,1,1,1,255,4,5,7,7,255,4,8,7,7,1,1,1,5,5,5,4,2,2,255,6,7,2,255,6,1,255,4,2,1,5,5,5,2,2,255,6,1,2,2,2,255,4,1,2,2,2,1,
255,4,0,1,255,14,0,1,0,1,255,12,0,1,255,14,0,1,0,6,0,0,1,255,18,0,255,4,1,0,0,0,1,2,0,3,0,6,0,0,1,8,0,0,6,1,0,0,0,3,0,6,6,255,4,0,3,8,8,3,6,1,255,4,0,2,0,0,2,1,0,8,3,3,8,255,5,0,2,4,0,0,4,0,8,3,0,0,3,8,6,0,2,2,4,255,4,0,8,3,8,0,0,8,3,8,1,0,0,2,255,4,0,3,0,3,8,8,3,0,3,2,0,0,0,2,0,0,0,8,0,8,3,3,8,0,8,1,0,0,0,1,2,2,7,0,8,3,0,0,3,8,0,7,0,0,255,4,1,5,7,0,255,4,8,0,7,255,6,0,5,0,0,255,6,7,255,6,0,5,5,0,0,2,2,0,5,5,0,0,2,
255,4,0,6,255,14,0,6,0,6,255,12,0,2,255,14,0,2,0,3,0,0,2,255,25,0,2,3,0,6,0,2,255,11,0,2,0,2,2,255,17,0,1,255,11,0,1,1,0,0,1,255,9,0,255,4,1,255,14,0,1,1,255,14,0,2,255,35,0,2,255,14,0,2,255,14,0,2,2,0,0,1,1,0,1,1,255,3,0,
255,73,0,8,8,8,6,255,11,0,8,3,0,0,3,6,255,11,0,8,3,3,8,8,6,255,4,0,4,0,0,4,8,0,3,8,8,3,255,5,0,4,2,0,0,7,0,3,8,0,0,8,3,8,0,0,0,2,2,0,0,0,3,8,3,0,0,3,8,3,2,0,0,0,2,0,0,0,8,0,8,3,3,8,0,8,1,0,0,1,1,0,0,0,7,0,3,8,8,3,0,7,7,255,4,0,1,1,2,0,7,8,0,0,8,7,0,1,255,4,0,2,2,0,2,0,255,4,7,0,2,255,4,0,2,2,0,0,5,5,1,1,2,2,2,5,5,255,4,0,1,1,5,5,5,255,4,0,255,3,5,
255,4,0,1,255,14,0,1,0,1,255,12,0,1,255,14,0,1,0,6,0,0,1,255,18,0,255,4,1,0,0,0,1,2,0,3,0,6,0,0,1,8,0,0,6,1,0,0,0,3,0,6,6,255,4,0,3,8,8,3,6,1,255,4,0,2,0,0,2,1,0,8,3,3,8,255,5,0,2,4,0,0,4,0,8,3,0,0,3,8,6,0,2,2,4,255,4,0,8,3,8,0,0,8,3,8,1,0,0,2,255,4,0,3,0,3,8,8,3,0,3,2,0,0,0,2,0,0,0,8,0,8,3,3,8,0,8,8,255,4,0,2,2,7,0,8,3,0,0,3,8,0,7,255,4,0,1,1,0,7,0,255,4,8,0,7,255,4,0,1,0,0,0,2,255,6,7,2,255,4,0,255,4,2,255,4,0,2,2,2,0,0,
255,4,0,6,255,14,0,6,0,6,255,12,0,2,255,14,0,2,0,3,0,0,2,255,25,0,2,3,0,6,0,2,255,11,0,2,0,2,2,255,17,0,1,255,11,0,1,1,0,0,1,255,9,0,255,4,1,255,14,0,1,1,255,14,0,2,255,12,0,1,255,36,0,1,255,10,0,1,0,0,0,1,0,0,0,2,1,0,0,1,1,0,2,2
};
uint16_t koopa_delays[] = {100,100,100,100,100,100};
uint16_t koopa_offsets[] = {0,199,390,479,640,832,926}; uint16_t koopa_offsets[] = {0,199,390,479,640,832,926};
AnimationData koopa = {&koopa_colors[0], &koopa_data[0], &koopa_offsets[0], 9, 6, 16, 16}; AnimationData koopa = {&koopa_colors[0], &koopa_data[0], &koopa_offsets[0], &koopa_delays[0], false, 9, 6, 16, 16};
uint32_t couple_rain_colors[] = {0x000000, 0x000000, 0x000000, 0x028BDA, 0xB5ABFF, 0xFFFFFF, 0xFF4C0B, 0xDCCEB4, 0x313131, 0x1501AF, 0x641B00, 0x514225, 0x3319FD, 0x2E0C00, 0xDA0256, 0x25AFFD, 0x80683C};
uint8_t couple_rain_data[] = {
255,6,2,3,255,7,2,3,255,14,2,3,255,8,2,3,255,7,2,3,255,14,2,3,255,25,2,3,255,5,2,3,255,12,2,3,255,12,2,3,255,18,2,3,255,12,2,3,255,18,2,3,255,12,2,3,255,18,2,3,255,12,2,3,255,10,2,3,255,7,2,3,255,23,2,3,255,11,2,3,255,19,2,3,255,11,2,3,255,15,2,3,2,2,2,3,255,11,2,3,255,5,2,15,255,9,2,3,2,2,2,3,255,11,2,3,2,2,2,3,255,11,2,3,255,15,2,3,5,2,15,3,255,7,2,3,2,2,2,3,255,8,2,3,255,4,2,255,7,5,255,7,2,3,2,2,2,3,255,8,2,3,2,2,2,5,5,12,12,5,12,12,5,5,255,6,2,3,255,12,2,3,2,2,5,5,12,12,5,5,5,12,12,5,5,255,5,2,3,255,12,2,3,2,4,4,9,9,12,5,5,5,12,9,9,4,4,255,4,2,3,255,8,2,3,2,2,2,3,2,4,4,9,9,9,4,4,4,9,9,9,4,4,255,13,2,3,255,11,2,9,255,6,2,3,255,12,2,3,255,7,2,6,6,6,2,9,255,6,2,3,255,12,2,3,255,7,2,6,6,6,2,9,2,10,10,10,2,2,3,255,12,2,3,255,7,2,10,10,10,2,9,255,5,10,2,3,255,19,2,255,5,6,12,10,7,7,7,10,2,3,255,6,2,3,255,13,2,11,7,11,2,12,10,11,7,11,10,255,8,2,3,255,13,2,7,7,7,2,7,10,7,7,7,10,255,8,2,3,255,6,2,3,255,6,2,255,5,6,13,13,16,13,13,255,8,2,3,255,6,2,3,255,5,2,255,4,6,2,2,2,14,14,14,255,9,2,3,255,6,2,3,255,5,2,7,10,10,10,2,2,7,14,14,14,7,255,15,2,3,255,6,2,6,6,6,2,2,255,5,14,2,2,2,15,255,11,2,3,255,6,2,6,2,6,2,2,2,7,2,7,255,6,2,15,255,15,2,8,8,2,8,8,2,2,8,2,8,255,6,2,3,255,37,2,
255,19,0,3,255,31,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,14,0,3,0,0,0,2,0,0,0,3,255,8,0,2,255,5,0,3,255,12,0,2,255,18,0,3,255,68,0,2,255,20,0,3,255,10,0,2,255,7,0,3,0,0,0,2,255,8,0,3,255,18,0,3,0,0,0,2,255,15,0,2,255,21,0,2,15,255,8,0,2,255,14,0,15,0,0,0,15,2,255,15,0,3,255,14,0,2,2,255,7,0,2,255,7,0,3,255,4,0,2,255,18,0,2,255,12,0,2,255,22,0,3,255,31,0,3,255,36,0,2,255,22,0,3,255,8,0,2,0,0,0,3,255,14,0,2,0,0,0,3,255,12,0,3,255,14,0,2,255,76,0,3,255,25,0,2,255,5,0,3,255,18,0,3,255,6,0,2,255,24,0,3,255,13,0,2,255,31,0,2,255,50,0,15,255,5,0,3,255,5,0,15,255,20,0,2,0,15,0,0,3,255,7,0,15,255,20,0,2,255,9,0,3,255,21,0,2,255,37,0,
255,6,0,2,255,7,0,2,255,14,0,2,255,31,0,2,255,21,0,3,255,31,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,14,0,3,0,0,0,2,0,0,0,3,255,8,0,2,255,5,0,3,255,12,0,2,255,18,0,3,255,68,0,2,255,20,0,3,255,10,0,2,255,7,0,3,0,15,0,2,15,0,15,0,0,0,2,0,3,255,18,0,3,0,0,2,2,0,0,2,255,4,0,15,255,7,0,2,255,31,0,2,255,35,0,3,255,23,0,2,255,7,0,3,255,4,0,2,255,18,0,2,255,12,0,2,255,22,0,3,255,31,0,3,255,36,0,2,255,22,0,3,255,8,0,2,0,0,0,3,255,14,0,2,0,0,0,3,255,12,0,3,255,14,0,2,255,76,0,3,255,25,0,2,255,5,0,3,255,18,0,3,255,6,0,2,255,24,0,3,255,11,0,15,0,2,255,18,0,2,0,0,15,255,8,0,2,2,0,15,255,19,0,2,255,10,0,2,255,23,0,3,255,31,0,3,255,34,0,
0,0,3,255,16,0,2,255,7,0,3,255,6,0,3,0,0,0,2,255,7,0,2,255,12,0,3,255,10,0,2,255,7,0,2,255,14,0,2,255,31,0,2,255,21,0,3,255,31,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,14,0,3,0,0,0,2,0,0,0,3,255,8,0,2,255,5,0,3,255,12,0,2,255,18,0,3,255,18,0,15,255,26,0,15,2,0,0,2,0,2,255,16,0,2,255,19,0,2,3,255,10,0,2,255,7,0,3,0,0,0,2,255,8,0,3,255,18,0,3,255,19,0,2,255,31,0,2,255,35,0,3,255,23,0,2,255,7,0,3,255,4,0,2,255,18,0,2,255,12,0,2,255,22,0,3,255,31,0,3,255,36,0,2,255,22,0,3,255,8,0,2,0,0,0,3,255,14,0,2,0,0,0,3,255,12,0,3,255,14,0,2,255,76,0,3,255,23,0,15,0,2,0,0,0,15,2,3,255,18,0,3,0,0,0,2,0,0,2,255,8,0,2,15,255,14,0,3,255,5,0,15,255,7,0,2,255,25,0,15,255,5,0,2,255,59,0,
255,10,0,3,255,31,0,3,255,8,0,2,255,14,0,3,255,16,0,2,255,7,0,3,255,6,0,3,0,0,0,2,255,7,0,2,255,12,0,3,255,10,0,2,255,7,0,2,255,14,0,2,255,31,0,2,255,21,0,3,255,31,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,14,0,3,0,0,0,2,0,0,0,3,0,2,15,255,5,0,2,255,5,0,3,255,12,0,15,2,255,17,0,3,255,45,0,15,255,22,0,2,255,6,0,15,255,13,0,3,255,10,0,2,255,7,0,3,255,12,0,3,255,38,0,2,255,31,0,2,255,35,0,3,255,23,0,2,255,7,0,3,255,4,0,2,255,18,0,2,255,12,0,2,255,22,0,3,255,31,0,3,255,36,0,2,255,22,0,3,255,8,0,2,0,0,0,3,255,14,0,2,0,0,0,3,255,12,0,3,255,14,0,2,255,36,0,2,255,5,0,2,255,26,0,15,255,6,0,3,0,0,0,2,255,20,0,2,2,15,255,4,0,3,255,18,0,3,255,6,0,2,2,255,23,0,3,255,41,0,
0,0,2,255,20,0,3,0,0,0,2,255,27,0,3,255,18,0,3,255,31,0,3,255,8,0,2,255,14,0,3,255,16,0,2,255,7,0,3,255,6,0,3,0,0,0,2,255,7,0,2,255,12,0,3,255,10,0,2,255,7,0,2,255,14,0,2,255,31,0,2,255,21,0,3,255,29,0,2,0,3,255,18,0,3,0,0,0,2,0,0,0,3,0,0,0,15,255,4,0,2,255,14,0,3,0,0,15,2,0,15,0,3,255,8,0,2,255,5,0,3,255,12,0,15,2,255,17,0,3,255,10,0,15,2,255,56,0,2,255,20,0,3,255,10,0,2,255,20,0,3,255,38,0,2,255,31,0,2,255,35,0,3,255,23,0,2,255,7,0,3,255,4,0,2,255,18,0,2,255,12,0,2,255,22,0,3,255,31,0,3,255,36,0,2,255,22,0,3,255,8,0,2,0,0,0,3,255,14,0,2,0,0,0,3,15,255,11,0,3,255,14,0,2,255,5,0,2,0,0,15,255,4,0,15,255,25,0,2,0,0,0,15,255,20,0,15,255,11,0,3,255,25,0,2,255,34,0,
255,6,0,3,0,0,0,2,255,5,0,3,255,13,0,3,0,0,0,2,255,13,0,3,255,10,0,2,0,0,3,0,0,0,2,255,20,0,3,0,0,0,2,255,27,0,3,255,18,0,3,255,31,0,3,255,8,0,2,255,14,0,3,255,16,0,2,255,7,0,3,255,6,0,3,0,0,0,2,255,7,0,2,255,12,0,3,255,10,0,2,255,7,0,2,255,14,0,2,255,31,0,2,255,20,0,2,3,255,21,0,2,15,0,2,15,255,5,0,3,255,18,0,3,0,0,0,2,0,0,0,3,255,8,0,2,255,14,0,3,0,2,0,2,255,12,0,2,255,5,0,3,255,9,0,15,0,0,2,255,18,0,3,255,68,0,2,255,20,0,3,255,10,0,2,255,20,0,3,255,38,0,2,255,31,0,2,255,35,0,3,255,23,0,2,255,7,0,3,255,4,0,2,255,18,0,2,255,12,0,2,255,22,0,3,255,31,0,3,255,28,0,2,255,7,0,2,15,255,21,0,3,255,4,0,2,0,15,0,2,2,0,0,3,255,14,0,2,0,15,0,3,255,7,0,2,255,4,0,3,255,14,0,15,2,255,72,0,
255,23,0,2,255,14,0,3,0,0,0,2,255,27,0,3,0,0,0,2,255,5,0,3,255,13,0,3,0,0,0,2,255,13,0,3,255,10,0,2,0,0,3,0,0,0,2,255,20,0,3,0,0,0,2,255,27,0,3,255,18,0,3,255,31,0,3,255,8,0,2,255,14,0,3,255,16,0,2,255,7,0,3,255,6,0,3,0,0,0,2,255,7,0,2,255,12,0,3,255,10,0,2,0,0,0,15,0,15,0,2,15,255,13,0,2,255,12,0,2,0,0,2,255,15,0,2,255,21,0,3,255,31,0,3,255,18,0,3,2,255,15,0,2,255,14,0,3,255,16,0,2,255,5,0,3,255,31,0,3,255,68,0,2,255,20,0,3,255,10,0,2,255,20,0,3,255,38,0,2,255,31,0,2,255,35,0,3,255,23,0,2,255,7,0,3,255,4,0,2,255,18,0,2,255,10,0,15,0,2,255,22,0,3,255,5,0,2,255,20,0,15,255,4,0,3,0,15,2,255,4,0,15,255,15,0,15,0,2,255,10,0,2,255,4,0,15,255,13,0,2,0,0,0,3,255,8,0,2,0,0,0,3,255,14,0,2,0,0,0,3,255,37,0,
255,16,0,2,255,4,0,3,255,8,0,2,255,24,0,2,255,31,0,2,255,14,0,3,0,0,0,2,255,27,0,3,0,0,0,2,255,5,0,3,255,13,0,3,0,0,0,2,255,13,0,3,255,10,0,2,0,0,3,0,0,0,2,255,20,0,3,0,0,0,2,255,27,0,3,255,18,0,3,255,31,0,3,255,8,0,2,255,14,0,3,255,7,0,2,0,2,0,0,2,0,0,0,2,255,7,0,3,255,6,0,3,0,0,0,2,255,7,0,2,255,12,0,3,255,10,0,2,255,7,0,2,255,5,0,15,255,8,0,2,255,31,0,2,255,72,0,3,255,16,0,2,255,14,0,3,255,16,0,2,255,5,0,3,255,31,0,3,255,68,0,2,255,20,0,3,255,10,0,2,255,20,0,3,255,38,0,2,255,31,0,2,255,35,0,3,0,0,2,255,20,0,2,255,7,0,3,0,0,15,0,2,255,14,0,15,0,0,2,2,255,5,0,2,255,5,0,2,15,255,14,0,2,255,7,0,3,255,9,0,2,255,16,0,15,255,4,0,3,255,65,0,
0,0,0,3,0,0,2,255,20,0,3,255,10,0,2,255,9,0,2,255,4,0,3,255,8,0,2,255,17,0,2,255,4,0,3,255,8,0,2,255,24,0,2,255,31,0,2,255,14,0,3,0,0,0,2,255,27,0,3,0,0,0,2,255,5,0,3,255,13,0,3,0,0,0,2,255,13,0,3,255,10,0,2,0,0,3,0,0,0,2,255,20,0,3,0,0,0,2,255,27,0,3,255,18,0,3,255,31,0,3,255,7,0,15,2,0,15,255,12,0,3,255,16,0,2,2,255,6,0,3,255,6,0,3,0,0,0,2,255,20,0,3,255,10,0,2,255,22,0,2,255,31,0,2,255,72,0,3,255,16,0,2,255,14,0,3,255,16,0,2,255,5,0,3,255,31,0,3,255,68,0,2,255,20,0,3,255,10,0,2,255,20,0,3,255,38,0,2,255,31,0,2,255,5,0,15,2,0,15,255,14,0,2,255,11,0,3,255,4,0,2,255,16,0,15,0,2,0,0,15,255,4,0,3,255,4,0,2,255,17,0,2,2,15,0,0,0,15,255,7,0,2,255,22,0,3,255,33,0,
255,11,0,3,255,23,0,3,255,7,0,3,255,15,0,3,255,7,0,3,0,0,2,255,20,0,3,255,10,0,2,255,9,0,2,255,4,0,3,255,8,0,2,255,17,0,2,255,4,0,3,255,8,0,2,255,24,0,2,255,31,0,2,255,14,0,3,0,0,0,2,255,27,0,3,0,0,0,2,255,5,0,3,255,13,0,3,0,0,0,2,255,13,0,3,255,10,0,2,0,0,3,0,0,0,2,255,14,0,15,255,5,0,3,0,0,0,2,255,22,0,2,0,0,2,15,3,255,18,0,3,255,31,0,3,255,8,0,2,255,14,0,3,255,24,0,3,255,6,0,3,0,0,0,2,255,20,0,3,255,10,0,2,255,22,0,2,255,31,0,2,255,72,0,3,255,16,0,2,255,14,0,3,255,16,0,2,255,5,0,3,255,31,0,3,255,68,0,2,255,20,0,3,255,10,0,2,255,4,0,15,255,15,0,3,255,12,0,2,0,0,2,255,21,0,15,2,255,4,0,15,255,19,0,15,2,0,0,0,15,2,2,15,0,15,255,25,0,2,0,0,0,2,0,0,3,255,23,0,2,255,37,0,
255,17,0,3,0,0,0,2,255,31,0,2,255,21,0,3,255,23,0,3,255,7,0,3,255,15,0,3,255,7,0,3,0,0,2,255,20,0,3,255,10,0,2,255,9,0,2,255,4,0,3,255,8,0,2,255,17,0,2,255,4,0,3,255,8,0,2,255,24,0,2,255,31,0,2,255,14,0,3,0,0,0,2,255,27,0,3,0,0,0,2,255,5,0,15,2,255,12,0,3,0,0,0,2,255,13,0,3,255,5,0,2,255,4,0,2,0,0,3,0,0,0,2,255,8,0,15,255,11,0,3,0,0,0,2,255,13,0,15,255,13,0,3,255,18,0,3,255,55,0,3,255,24,0,3,255,6,0,3,0,0,0,2,255,20,0,3,255,10,0,2,255,22,0,2,255,31,0,2,255,72,0,3,255,16,0,2,255,14,0,3,255,16,0,2,255,5,0,3,255,31,0,3,255,41,0,2,255,20,0,15,255,5,0,2,15,255,19,0,3,255,5,0,2,0,0,0,15,2,2,255,19,0,3,255,4,0,2,15,0,2,0,2,255,28,0,2,255,31,0,2,255,33,0,
0,0,0,2,255,7,0,2,255,15,0,2,0,0,3,255,4,0,2,255,13,0,3,255,9,0,2,255,21,0,3,0,0,0,2,255,31,0,2,255,21,0,3,255,23,0,3,255,7,0,3,255,15,0,3,255,7,0,3,0,0,2,255,20,0,3,255,10,0,2,255,9,0,2,255,4,0,3,255,8,0,2,255,17,0,2,255,4,0,3,255,8,0,2,255,24,0,2,255,24,0,3,255,6,0,2,255,14,0,3,0,0,0,2,0,15,255,4,0,15,255,20,0,3,0,15,0,2,2,255,4,0,3,255,13,0,3,0,0,0,2,255,6,0,2,255,17,0,2,0,0,3,0,0,0,2,255,20,0,3,0,0,0,2,255,27,0,3,255,74,0,3,255,24,0,3,255,6,0,3,0,0,0,2,255,20,0,3,255,10,0,2,255,22,0,2,255,31,0,2,255,72,0,3,255,16,0,2,255,14,0,3,255,16,0,2,255,5,0,3,255,6,0,15,255,22,0,15,2,3,0,0,15,0,0,2,255,29,0,2,255,27,0,2,255,4,0,2,255,20,0,3,255,10,0,2,255,20,0,3,255,40,0,
0,3,255,5,0,3,255,31,0,3,0,0,0,2,255,18,0,3,255,4,0,2,255,7,0,2,255,15,0,2,0,0,3,255,4,0,2,255,13,0,3,255,9,0,2,255,21,0,3,0,0,0,2,255,31,0,2,255,21,0,3,255,23,0,3,255,7,0,3,255,15,0,3,255,7,0,3,0,0,2,255,20,0,3,255,10,0,2,255,9,0,2,255,4,0,3,255,8,0,2,255,16,0,15,2,0,15,0,0,3,255,8,0,2,255,13,0,2,15,0,0,0,2,255,5,0,2,255,15,0,15,2,255,14,0,2,255,14,0,3,0,0,0,15,255,27,0,3,0,0,0,2,255,19,0,3,0,0,0,2,255,24,0,2,0,0,3,0,0,0,2,255,20,0,3,0,0,0,2,255,27,0,3,255,74,0,3,255,24,0,3,255,6,0,3,0,0,0,2,255,20,0,3,255,10,0,2,255,22,0,2,255,31,0,2,255,70,0,2,15,3,255,16,0,2,0,0,0,2,255,4,0,2,255,5,0,3,255,16,0,2,15,255,4,0,3,255,31,0,3,255,24,0,15,255,73,0,
255,14,0,3,0,0,2,0,0,0,3,255,11,0,3,255,15,0,2,0,0,0,3,255,11,0,3,255,5,0,3,255,31,0,3,0,0,0,2,255,18,0,3,255,4,0,2,255,7,0,2,255,15,0,2,0,0,3,255,4,0,2,255,13,0,3,255,9,0,2,255,21,0,3,0,0,0,2,255,31,0,2,255,21,0,3,255,23,0,3,255,7,0,3,0,0,15,255,12,0,3,255,7,0,3,0,0,2,255,8,0,2,0,0,2,15,255,7,0,3,255,10,0,2,255,6,0,2,0,0,2,255,4,0,3,255,8,0,2,255,8,0,2,0,0,15,255,5,0,2,255,4,0,3,255,8,0,2,255,11,0,2,255,12,0,2,255,31,0,2,255,14,0,3,255,31,0,3,255,23,0,3,0,0,0,2,255,24,0,2,0,0,3,0,0,0,2,255,20,0,3,0,0,0,2,255,27,0,3,255,74,0,3,255,24,0,3,255,6,0,3,0,0,0,2,255,20,0,3,255,10,0,2,255,22,0,2,255,31,0,2,255,7,0,2,255,19,0,15,255,30,0,2,255,13,0,3,255,15,0,15,2,255,14,0,3,255,15,0,2,2,255,5,0,3,255,31,0,3,255,34,0,
255,7,0,2,255,18,0,3,0,0,0,2,255,15,0,3,255,15,0,2,255,15,0,3,0,0,2,0,0,0,3,255,11,0,3,255,15,0,2,0,0,0,3,255,11,0,3,255,5,0,3,255,31,0,3,0,0,0,2,255,18,0,3,255,4,0,2,255,7,0,2,255,15,0,2,0,0,3,255,4,0,2,255,13,0,3,255,9,0,2,255,21,0,3,0,0,0,2,255,23,0,15,2,255,6,0,2,255,21,0,3,255,7,0,2,255,15,0,3,255,7,0,3,255,8,0,15,255,6,0,3,255,7,0,3,0,0,2,0,0,0,2,255,16,0,3,255,10,0,2,255,14,0,3,255,8,0,2,255,22,0,3,255,8,0,2,255,24,0,2,255,31,0,2,255,14,0,3,255,31,0,3,255,23,0,3,0,0,0,2,255,24,0,2,0,0,3,0,0,0,2,255,20,0,3,0,0,0,2,255,27,0,3,255,74,0,3,255,24,0,3,255,6,0,3,0,0,0,2,255,20,0,3,255,10,0,2,255,18,0,2,15,0,0,2,255,24,0,15,255,6,0,2,255,24,0,2,255,16,0,15,255,20,0,15,255,9,0,3,255,16,0,2,255,40,0,
0,2,255,19,0,2,255,11,0,2,255,5,0,2,255,18,0,3,255,12,0,2,255,18,0,3,0,0,0,2,255,15,0,3,255,15,0,2,255,15,0,3,0,0,2,0,0,0,3,255,11,0,3,255,15,0,2,0,0,0,3,255,11,0,3,255,5,0,3,255,31,0,3,0,0,0,2,255,18,0,3,255,4,0,2,255,7,0,2,255,15,0,2,0,0,3,255,4,0,2,255,9,0,2,0,0,0,3,255,9,0,2,255,21,0,3,0,0,0,2,255,30,0,2,2,255,21,0,3,255,23,0,3,255,7,0,3,255,8,0,15,255,6,0,3,255,7,0,3,0,0,2,255,20,0,3,255,10,0,2,255,14,0,3,255,8,0,2,255,31,0,2,255,24,0,2,255,31,0,2,255,14,0,3,255,31,0,3,255,23,0,3,0,0,0,2,255,24,0,2,0,0,3,0,0,0,2,255,20,0,3,0,0,0,2,255,27,0,3,255,74,0,3,255,23,0,2,3,255,6,0,3,0,0,0,2,255,15,0,2,255,4,0,3,255,9,0,15,2,15,255,19,0,15,0,2,255,9,0,2,255,20,0,2,15,255,66,0,
255,10,0,3,0,0,0,2,255,31,0,2,255,6,0,2,255,11,0,2,255,19,0,2,255,11,0,2,255,5,0,2,255,18,0,3,255,12,0,2,255,18,0,3,0,0,0,2,255,15,0,3,255,15,0,2,255,15,0,3,0,0,2,0,0,0,3,255,11,0,3,255,15,0,2,0,0,0,3,255,11,0,3,255,5,0,3,255,31,0,3,0,0,0,2,255,18,0,3,255,4,0,2,255,7,0,2,255,15,0,2,0,0,3,255,4,0,2,255,13,0,3,255,9,0,2,255,21,0,3,0,0,15,2,255,30,0,2,2,15,255,44,0,3,255,23,0,3,255,7,0,3,0,0,2,255,20,0,3,255,10,0,2,255,23,0,2,255,31,0,2,255,24,0,2,255,31,0,2,255,14,0,3,255,31,0,3,255,23,0,3,0,0,0,2,255,24,0,2,0,0,3,0,0,0,2,255,20,0,3,0,0,0,2,255,27,0,3,255,44,0,15,0,0,15,255,26,0,3,0,0,2,0,2,255,18,0,15,3,0,15,255,4,0,3,0,0,0,2,255,20,0,3,0,2,255,8,0,2,255,22,0,2,255,34,0,
255,4,0,3,255,12,0,3,255,8,0,2,255,9,0,3,255,5,0,3,255,15,0,2,255,15,0,3,0,0,0,2,255,31,0,2,255,6,0,2,255,11,0,2,255,19,0,2,255,11,0,2,255,5,0,2,255,18,0,3,255,12,0,2,255,18,0,3,0,0,0,2,255,15,0,3,255,15,0,2,255,15,0,3,0,0,2,0,0,0,3,255,11,0,3,255,15,0,2,0,0,0,3,255,11,0,3,255,5,0,3,255,31,0,3,0,0,0,2,255,6,0,15,0,15,255,9,0,3,255,4,0,2,255,7,0,2,255,8,0,2,0,0,15,0,0,0,2,0,0,3,255,4,0,2,255,18,0,2,255,4,0,2,255,25,0,2,255,31,0,2,255,45,0,3,255,23,0,3,255,7,0,3,0,0,2,255,20,0,3,255,10,0,2,255,23,0,2,255,31,0,2,255,24,0,2,255,31,0,2,255,14,0,3,255,31,0,3,255,23,0,3,0,0,0,2,255,24,0,2,0,0,3,0,0,0,2,255,5,0,15,255,14,0,3,0,0,0,2,255,7,0,15,2,0,0,2,255,15,0,3,255,5,0,15,255,27,0,15,2,0,0,2,255,5,0,15,255,24,0,15,255,5,0,3,255,24,0,3,255,36,0,
255,29,0,3,255,19,0,3,255,18,0,3,255,12,0,3,255,8,0,2,255,9,0,3,255,5,0,3,255,15,0,2,255,15,0,3,0,0,0,2,255,31,0,2,255,6,0,2,255,11,0,2,255,19,0,2,255,11,0,2,255,5,0,2,255,18,0,3,255,12,0,2,255,18,0,3,0,0,0,2,255,15,0,3,255,15,0,2,255,15,0,3,0,0,2,15,0,0,3,255,11,0,3,255,14,0,15,2,2,0,2,3,255,11,0,3,255,5,0,3,255,15,0,2,15,255,14,0,3,0,0,0,2,255,18,0,3,255,4,0,2,255,23,0,2,0,0,3,255,4,0,2,255,23,0,2,255,103,0,3,255,23,0,3,255,7,0,3,0,0,2,255,20,0,3,255,10,0,2,255,23,0,2,255,31,0,2,255,24,0,2,255,31,0,2,255,14,0,3,255,31,0,3,0,2,255,21,0,3,0,0,0,2,2,255,23,0,2,0,2,3,0,0,0,15,15,255,19,0,3,0,2,0,15,0,15,255,5,0,2,255,19,0,3,255,4,0,2,255,67,0,
255,4,0,2,255,5,0,2,255,31,0,2,255,18,0,3,255,31,0,3,255,19,0,3,255,18,0,3,255,12,0,3,255,8,0,2,255,9,0,3,255,5,0,3,255,15,0,2,255,15,0,3,0,0,0,2,255,31,0,2,255,6,0,2,255,11,0,2,255,19,0,2,255,11,0,2,255,5,0,2,255,11,0,15,255,6,0,3,255,12,0,2,255,8,0,15,0,2,255,7,0,3,0,0,0,2,255,15,0,3,0,2,255,13,0,2,255,15,0,3,0,0,2,0,0,0,3,0,0,2,255,8,0,3,255,19,0,3,255,11,0,3,255,5,0,3,255,31,0,3,255,22,0,3,255,4,0,2,255,23,0,2,0,0,3,255,4,0,2,255,23,0,2,255,103,0,3,255,23,0,3,255,7,0,3,0,0,2,255,20,0,3,255,10,0,2,255,23,0,2,255,31,0,2,255,24,0,2,255,31,0,2,255,10,0,15,0,15,0,3,255,20,0,15,255,6,0,2,2,0,0,3,255,17,0,15,0,0,2,0,2,3,0,0,0,2,255,19,0,15,255,4,0,2,0,0,3,0,0,0,2,255,20,0,3,0,0,0,2,255,36,0,
255,17,0,2,255,4,0,3,255,13,0,2,255,12,0,2,255,18,0,2,255,5,0,2,255,31,0,2,255,18,0,3,255,31,0,3,255,19,0,3,255,18,0,3,255,12,0,3,255,8,0,2,255,9,0,3,255,5,0,3,255,15,0,2,255,15,0,3,0,0,0,2,255,31,0,2,15,0,0,0,2,0,2,255,11,0,2,255,14,0,2,255,4,0,2,255,11,0,2,255,5,0,2,255,5,0,15,255,12,0,3,255,12,0,2,255,18,0,3,0,0,0,2,255,31,0,2,255,22,0,3,255,11,0,3,255,19,0,3,255,11,0,3,255,5,0,3,255,31,0,3,255,22,0,3,255,4,0,2,255,23,0,2,0,0,3,255,4,0,2,255,23,0,2,255,103,0,3,255,23,0,3,255,7,0,3,0,0,2,255,20,0,3,255,10,0,2,255,23,0,2,0,0,0,15,255,23,0,15,0,0,0,2,0,0,0,2,0,2,15,255,17,0,2,15,0,0,2,255,26,0,15,2,2,255,13,0,3,255,15,0,2,255,6,0,15,255,8,0,3,255,23,0,3,255,33,0,
0,0,0,3,255,8,0,3,255,16,0,2,255,5,0,3,255,8,0,3,255,9,0,3,255,6,0,2,255,19,0,2,255,4,0,3,255,13,0,2,255,12,0,2,255,18,0,2,255,5,0,2,255,31,0,2,255,18,0,3,255,31,0,3,255,19,0,3,255,18,0,3,255,12,0,3,255,8,0,2,255,9,0,3,255,5,0,3,0,0,0,15,2,255,10,0,2,255,15,0,3,0,15,0,2,255,30,0,2,15,255,6,0,2,255,11,0,2,255,19,0,15,255,11,0,2,255,5,0,2,255,18,0,3,255,12,0,2,255,18,0,3,0,0,0,2,255,31,0,2,255,34,0,3,255,31,0,3,255,5,0,3,255,31,0,3,255,22,0,3,255,4,0,2,255,23,0,2,0,0,3,255,4,0,2,255,23,0,2,255,103,0,3,255,23,0,3,255,6,0,2,3,0,0,2,255,18,0,15,2,3,255,9,0,2,2,255,15,0,15,0,2,255,5,0,15,255,23,0,2,255,5,0,15,0,2,255,8,0,15,255,15,0,2,255,5,0,2,255,25,0,2,255,40,0,
255,67,0,3,255,8,0,3,255,16,0,2,255,5,0,3,255,8,0,3,255,9,0,3,255,6,0,2,255,19,0,2,255,4,0,3,255,13,0,2,255,12,0,2,255,18,0,2,255,5,0,2,255,31,0,2,255,18,0,3,255,31,0,3,255,16,0,2,0,0,3,255,18,0,3,255,6,0,15,2,0,0,15,0,3,255,8,0,2,255,9,0,3,255,5,0,3,0,0,0,2,255,6,0,15,255,4,0,2,255,15,0,3,0,0,0,2,255,6,0,2,255,31,0,2,255,11,0,2,255,19,0,2,15,255,10,0,2,255,5,0,2,255,18,0,3,255,12,0,2,255,18,0,3,0,0,0,2,255,31,0,2,255,34,0,3,255,31,0,3,255,5,0,3,255,31,0,3,255,22,0,3,255,4,0,2,255,23,0,2,0,0,3,255,4,0,2,255,23,0,2,255,93,0,2,15,0,0,0,15,255,4,0,3,255,18,0,2,255,4,0,3,0,0,2,255,4,0,3,0,0,2,15,255,19,0,3,2,255,9,0,15,2,255,22,0,2,255,31,0,2,255,33,0,
0,0,0,2,0,0,0,3,255,4,0,2,255,9,0,2,0,0,0,3,255,12,0,3,255,14,0,2,255,76,0,3,255,8,0,3,255,16,0,2,255,5,0,3,255,8,0,3,255,9,0,3,255,6,0,2,255,19,0,2,255,4,0,3,255,13,0,2,255,12,0,2,255,18,0,2,255,5,0,2,255,31,0,2,255,5,0,15,255,12,0,3,255,13,0,2,0,0,0,2,255,5,0,15,255,7,0,3,255,12,0,15,255,6,0,3,0,0,0,2,255,14,0,3,255,12,0,3,255,8,0,2,255,9,0,3,255,5,0,3,255,12,0,15,0,0,2,255,15,0,3,255,11,0,2,255,30,0,2,255,11,0,2,255,31,0,2,255,5,0,2,255,18,0,3,255,12,0,2,255,18,0,3,0,0,0,2,255,31,0,2,255,34,0,3,255,31,0,3,255,5,0,3,255,31,0,3,255,22,0,3,255,4,0,2,255,23,0,2,0,0,3,255,4,0,2,255,23,0,2,255,30,0,2,0,0,0,2,255,9,0,15,255,29,0,15,2,255,27,0,3,0,0,2,255,20,0,3,255,7,0,3,0,0,2,255,20,0,3,255,36,0,
255,18,0,3,255,16,0,2,255,8,0,2,255,5,0,3,255,7,0,3,255,8,0,2,0,0,0,3,255,4,0,2,255,9,0,2,0,0,0,3,255,12,0,3,255,14,0,2,255,76,0,3,255,8,0,3,255,16,0,2,255,5,0,3,255,8,0,3,255,9,0,3,255,6,0,2,255,19,0,2,255,4,0,3,255,13,0,2,255,11,0,2,2,255,18,0,2,255,5,0,2,255,10,0,2,255,26,0,15,255,12,0,3,255,31,0,3,255,11,0,15,255,13,0,2,15,255,11,0,3,255,21,0,2,255,9,0,3,255,21,0,2,255,70,0,2,255,31,0,2,255,5,0,2,255,18,0,3,255,12,0,2,255,18,0,3,0,0,0,2,255,31,0,2,255,34,0,3,255,31,0,3,255,5,0,3,255,31,0,3,255,22,0,3,255,4,0,2,0,15,255,21,0,2,0,0,3,255,4,0,15,255,4,0,2,255,17,0,15,2,255,10,0,2,255,29,0,15,255,23,0,15,255,67,0,
255,7,0,2,255,6,0,3,255,15,0,3,255,31,0,3,255,19,0,3,255,16,0,2,255,8,0,2,255,5,0,3,255,7,0,3,255,8,0,2,0,0,0,3,255,4,0,2,255,9,0,2,0,0,0,3,255,12,0,3,255,14,0,2,255,76,0,3,255,8,0,3,255,16,0,2,255,5,0,3,255,8,0,3,255,9,0,3,255,6,0,2,255,12,0,15,255,4,0,15,0,2,255,4,0,3,255,13,0,2,255,5,0,2,255,5,0,2,15,255,18,0,2,0,0,0,15,0,2,15,255,29,0,2,2,255,13,0,2,255,4,0,3,255,27,0,15,0,0,0,3,255,38,0,3,255,21,0,2,255,9,0,3,255,21,0,2,255,70,0,2,255,31,0,2,255,5,0,2,255,18,0,3,255,12,0,2,255,18,0,3,0,0,0,2,255,31,0,2,255,34,0,3,255,31,0,3,0,15,0,2,0,3,255,17,0,15,255,9,0,2,0,0,0,3,255,18,0,2,0,0,0,3,255,4,0,2,0,15,255,21,0,2,15,0,3,255,4,0,2,2,255,22,0,2,2,255,67,0,
0,0,3,255,15,0,2,255,7,0,2,255,7,0,3,255,4,0,2,255,6,0,3,255,11,0,2,255,12,0,2,255,6,0,3,255,15,0,3,255,31,0,3,255,19,0,3,255,16,0,2,255,8,0,2,255,5,0,3,255,7,0,3,255,8,0,2,0,0,0,3,255,4,0,2,255,9,0,2,0,0,0,3,255,12,0,3,255,14,0,2,255,51,0,15,255,24,0,3,255,6,0,2,0,3,0,15,2,0,0,15,255,10,0,2,255,5,0,3,255,8,0,15,255,4,0,2,255,4,0,3,255,6,0,2,255,9,0,15,2,0,0,2,255,5,0,2,255,4,0,3,255,13,0,2,255,31,0,2,255,5,0,2,255,14,0,2,255,35,0,3,255,31,0,3,255,38,0,3,255,21,0,2,255,9,0,3,255,21,0,2,255,70,0,2,255,31,0,2,255,5,0,2,255,18,0,3,255,12,0,2,255,18,0,3,0,0,0,2,255,4,0,15,255,26,0,2,255,4,0,2,255,20,0,15,2,255,7,0,3,255,26,0,15,255,4,0,3,0,0,0,2,15,3,255,20,0,2,255,10,0,3,255,22,0,3,255,4,0,2,255,23,0,2,0,0,3,255,33,0,
255,30,0,2,255,19,0,2,255,15,0,3,255,15,0,2,255,7,0,2,255,7,0,3,255,4,0,2,255,6,0,3,255,11,0,2,255,12,0,2,255,6,0,3,255,15,0,3,255,31,0,3,255,19,0,3,255,16,0,2,255,8,0,2,255,5,0,3,255,7,0,3,255,8,0,2,0,0,0,3,255,4,0,2,255,9,0,2,0,0,0,3,255,12,0,3,0,0,2,255,11,0,2,255,23,0,2,0,0,0,2,15,255,23,0,15,3,15,255,21,0,3,0,0,15,2,255,4,0,3,255,16,0,2,255,5,0,3,255,18,0,3,255,6,0,2,255,24,0,3,255,13,0,2,255,31,0,2,255,56,0,3,255,31,0,3,255,38,0,3,255,21,0,2,255,9,0,3,255,21,0,2,255,70,0,2,255,31,0,2,0,2,0,0,0,2,255,18,0,3,255,12,0,2,255,16,0,2,0,3,0,0,15,2,255,29,0,2,0,2,255,7,0,2,0,15,255,24,0,3,255,4,0,15,255,24,0,15,0,3,255,5,0,3,255,56,0,
0,0,2,255,7,0,3,0,0,0,2,255,8,0,3,255,18,0,3,0,0,0,2,255,15,0,2,255,31,0,2,255,19,0,2,255,15,0,3,255,15,0,2,255,7,0,2,255,7,0,3,255,4,0,2,255,6,0,3,255,11,0,2,255,12,0,2,255,6,0,3,255,15,0,3,255,31,0,3,255,19,0,3,255,16,0,2,255,8,0,2,255,5,0,3,255,7,0,3,255,8,0,2,0,0,0,3,0,0,15,0,15,255,6,0,2,0,0,2,0,0,0,3,255,12,0,3,0,0,0,2,0,2,255,8,0,2,255,15,0,2,255,60,0,3,255,25,0,2,255,5,0,3,255,18,0,3,255,6,0,2,255,24,0,3,255,13,0,2,255,31,0,2,255,56,0,3,255,31,0,3,255,38,0,3,255,21,0,2,255,9,0,3,255,21,0,2,255,70,0,2,255,27,0,2,0,0,0,2,255,5,0,2,255,18,0,3,255,10,0,15,0,15,2,255,17,0,3,0,0,0,2,15,255,6,0,2,255,23,0,15,2,255,64,0,
255,34,0,2,255,20,0,3,255,10,0,2,255,7,0,3,0,0,0,2,255,8,0,3,255,18,0,3,0,0,0,2,255,15,0,2,255,31,0,2,255,19,0,2,255,15,0,3,255,15,0,2,255,7,0,2,255,7,0,3,255,4,0,2,255,6,0,3,255,11,0,2,255,12,0,2,255,6,0,3,255,15,0,3,255,13,0,15,255,17,0,3,255,10,0,15,2,0,2,255,5,0,3,255,16,0,2,255,8,0,2,15,255,4,0,3,255,7,0,3,255,8,0,2,0,0,0,3,255,4,0,2,255,9,0,2,0,0,0,3,255,12,0,3,255,14,0,2,255,76,0,3,255,25,0,2,255,5,0,3,255,18,0,3,255,6,0,2,255,24,0,3,255,13,0,2,255,31,0,2,255,56,0,3,255,31,0,3,255,38,0,3,255,21,0,2,255,9,0,3,255,21,0,2,255,44,0,15,255,25,0,2,0,0,15,2,0,2,255,21,0,15,0,2,0,2,255,5,0,2,255,18,0,3,0,0,0,2,255,8,0,2,255,18,0,3,0,0,0,2,255,33,0,
255,10,0,2,255,18,0,3,255,68,0,2,255,20,0,3,255,10,0,2,255,7,0,3,0,0,0,2,255,8,0,3,255,18,0,3,0,0,0,2,255,15,0,2,255,31,0,2,255,19,0,2,255,15,0,3,255,8,0,15,255,6,0,2,255,7,0,2,255,7,0,3,255,4,0,2,255,4,0,2,0,3,255,11,0,2,255,12,0,2,0,2,255,4,0,15,255,15,0,3,255,14,0,2,255,5,0,15,255,10,0,3,255,19,0,3,255,16,0,2,255,22,0,3,255,8,0,2,0,0,0,3,255,14,0,2,0,0,0,3,255,12,0,3,255,14,0,2,255,76,0,3,255,25,0,2,255,5,0,3,255,18,0,3,255,6,0,2,255,24,0,3,255,13,0,2,255,31,0,2,255,56,0,3,255,31,0,3,255,38,0,3,0,0,15,255,18,0,2,255,9,0,3,0,0,2,255,18,0,2,255,9,0,2,255,23,0,15,2,255,5,0,15,255,21,0,15,255,7,0,2,255,62,0
};
uint16_t couple_rain_delays[] = {60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60};
uint16_t couple_rain_offsets[] = {0,475,718,961,1222,1476,1734,2002,2276,2528,2787,3050,3304,3567,3824,4106,4382,4650,4916,5208,5459,5731,5988,6243,6497,6769,7004,7263,7543,7790,8035,8288,8522};
AnimationData couple_rain = {&couple_rain_colors[0], &couple_rain_data[0], &couple_rain_offsets[0], &couple_rain_delays[0], false, 17, 32, 32, 32};
uint32_t couple_snow_colors[] = {0x000000, 0x000000, 0x000000, 0xFFFFFF, 0xFF3C00, 0xF8E6C4, 0x432F09, 0x22B20A, 0x008EF6, 0xF60049, 0x5C0000, 0x1B00FF};
uint8_t couple_snow_data[] = {
2,3,255,39,2,3,255,14,2,3,255,11,2,3,255,10,2,3,255,45,2,3,255,24,2,3,255,47,2,3,255,6,2,3,255,36,2,3,255,10,2,3,255,4,2,3,255,21,2,3,255,16,2,3,255,84,2,3,255,20,2,3,255,18,2,3,255,7,2,3,255,40,2,3,255,42,2,3,255,25,2,3,255,12,2,3,255,9,2,3,255,27,2,3,255,8,2,3,255,6,2,3,2,2,2,3,255,9,2,5,2,2,2,5,255,25,2,4,4,4,2,2,2,9,9,9,255,22,2,255,5,4,2,255,5,9,255,4,2,3,255,16,2,255,5,4,2,9,10,10,5,9,255,16,2,3,255,4,2,4,6,5,6,4,2,9,6,5,6,9,255,12,2,3,255,9,2,5,5,5,2,2,10,5,5,5,10,255,7,2,3,255,14,2,7,7,7,2,2,2,11,11,11,255,22,2,4,4,7,4,4,2,9,9,11,9,255,4,2,3,255,17,2,4,4,7,4,4,9,9,9,11,9,9,255,8,2,3,2,2,2,3,255,8,2,5,8,8,8,2,5,2,9,9,9,5,255,18,2,3,2,2,2,8,2,8,2,2,2,8,2,8,255,22,2,6,6,2,6,6,2,2,6,2,6,255,12,2,255,32,3,
0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,53,0,2,255,31,0,3,255,11,0,2,255,27,0,2,0,0,0,3,255,22,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,31,0,3,255,4,0,2,0,0,0,2,255,27,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,56,0,
255,15,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,20,0,3,255,6,0,3,0,0,0,3,255,53,0,2,255,31,0,3,255,11,0,2,255,27,0,2,0,0,0,3,255,22,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,31,0,3,255,4,0,2,0,0,0,2,255,27,0,3,0,0,0,3,255,5,0,2,255,56,0,
255,7,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,14,0,2,255,6,0,2,0,0,0,2,255,20,0,3,255,6,0,3,0,0,0,3,255,53,0,2,255,31,0,3,255,11,0,2,255,27,0,2,0,0,0,3,255,22,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,31,0,3,255,4,0,2,0,0,0,2,255,27,0,3,255,34,0,
0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,18,0,3,255,12,0,3,255,14,0,2,255,6,0,2,0,0,0,2,255,20,0,3,255,6,0,3,0,0,0,3,255,53,0,2,255,31,0,3,255,11,0,2,255,27,0,2,0,0,0,3,255,22,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,31,0,3,255,4,0,2,255,34,0,
0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,18,0,3,255,12,0,3,255,14,0,2,255,6,0,2,0,0,0,2,255,20,0,3,255,6,0,3,0,0,0,3,255,53,0,2,255,31,0,3,255,11,0,2,255,27,0,2,0,0,0,3,255,22,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,39,0,
255,12,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,18,0,3,255,12,0,3,255,14,0,2,255,6,0,2,0,0,0,2,255,20,0,3,255,6,0,3,0,0,0,3,255,53,0,2,255,31,0,3,255,11,0,2,255,27,0,2,0,0,0,3,255,22,0,2,255,4,0,3,255,26,0,3,255,35,0,
255,24,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,16,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,18,0,3,255,12,0,3,255,14,0,2,255,6,0,2,0,0,0,2,255,20,0,3,255,6,0,3,0,0,0,3,255,53,0,2,255,31,0,3,255,11,0,2,255,27,0,2,0,0,0,3,255,22,0,2,255,35,0,
0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,31,0,3,255,16,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,18,0,3,255,12,0,3,255,14,0,2,255,6,0,2,0,0,0,2,255,20,0,3,255,6,0,3,0,0,0,3,255,53,0,2,255,31,0,3,255,11,0,2,255,58,0,
0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,31,0,3,255,7,0,2,255,31,0,3,255,16,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,18,0,3,255,12,0,3,255,14,0,2,255,6,0,2,0,0,0,2,255,20,0,3,255,6,0,3,0,0,0,3,255,53,0,2,255,31,0,3,255,38,0,
255,5,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,31,0,3,255,7,0,2,255,31,0,3,255,16,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,18,0,3,255,12,0,3,255,14,0,2,255,6,0,2,0,0,0,2,255,20,0,3,255,6,0,3,0,0,0,3,255,53,0,2,255,38,0,
255,11,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,31,0,3,255,7,0,2,255,31,0,3,255,16,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,18,0,3,255,12,0,3,255,14,0,2,255,6,0,2,0,0,0,2,255,20,0,3,255,6,0,3,0,0,0,3,255,60,0,
255,11,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,31,0,3,255,7,0,2,255,31,0,3,255,16,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,18,0,3,255,12,0,3,255,14,0,2,255,6,0,2,0,0,0,2,255,20,0,3,255,6,0,3,255,32,0,
0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,21,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,31,0,3,255,7,0,2,255,31,0,3,255,16,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,18,0,3,255,12,0,3,255,14,0,2,255,6,0,2,255,32,0,
0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,5,255,24,0,3,255,22,0,2,255,4,0,2,255,21,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,31,0,3,255,7,0,2,255,31,0,3,255,16,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,18,0,3,255,35,0,
255,9,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,31,0,3,255,22,0,2,255,4,0,2,255,21,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,31,0,3,255,7,0,2,255,31,0,3,255,16,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,35,0,
0,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,31,0,3,255,22,0,2,255,4,0,2,255,21,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,31,0,3,255,7,0,2,255,31,0,3,255,16,0,2,255,31,0,3,255,40,0,
0,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,31,0,3,255,22,0,2,255,4,0,2,255,21,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,31,0,3,255,7,0,2,255,31,0,3,255,16,0,2,255,40,0,
255,23,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,31,0,3,255,22,0,2,255,4,0,2,255,21,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,31,0,3,255,7,0,2,255,57,0,
255,6,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,24,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,31,0,3,255,22,0,2,255,4,0,2,255,21,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,31,0,3,255,33,0,
255,6,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,14,0,3,255,11,0,3,255,24,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,31,0,3,255,22,0,2,255,4,0,2,255,21,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,33,0,
255,19,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,13,0,3,255,10,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,14,0,3,255,11,0,3,255,24,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,31,0,3,255,22,0,2,255,4,0,2,255,21,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,54,0,
255,30,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,26,0,2,255,4,0,3,255,5,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,14,0,3,255,11,0,3,255,24,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,31,0,3,255,22,0,2,255,4,0,2,255,21,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,39,0,
255,9,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,12,0,2,255,37,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,14,0,3,255,11,0,3,255,24,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,31,0,3,255,22,0,2,255,4,0,2,255,21,0,2,255,4,0,3,255,34,0,
0,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,10,0,3,255,16,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,50,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,14,0,3,255,11,0,3,255,24,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,31,0,3,255,22,0,2,255,34,0,
0,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,19,0,2,255,11,0,3,255,4,0,2,0,0,0,2,255,27,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,50,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,14,0,3,255,11,0,3,255,24,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,57,0,
255,6,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,31,0,3,255,4,0,2,0,0,0,2,255,27,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,50,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,14,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,41,0,
255,6,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,31,0,3,255,4,0,2,0,0,0,2,255,27,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,50,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,5,0,5,255,8,0,3,255,11,0,3,255,24,0,2,255,24,0,2,255,6,0,3,255,34,0,
255,22,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,13,0,3,255,8,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,31,0,3,255,4,0,2,0,0,0,2,255,27,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,50,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,14,0,3,255,11,0,3,255,24,0,2,255,34,0,
255,22,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,13,0,2,255,13,0,2,0,0,0,3,255,22,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,31,0,3,255,4,0,2,0,0,0,2,255,27,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,50,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,11,0,2,255,4,0,3,255,14,0,3,255,39,0,
255,4,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,17,0,3,0,0,3,255,10,0,3,255,11,0,2,255,27,0,2,0,0,0,3,255,22,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,31,0,3,255,4,0,2,0,0,0,2,255,27,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,50,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,7,0,2,255,14,0,2,255,39,0,
255,4,0,2,255,4,0,3,255,5,0,2,255,8,0,3,255,11,0,3,255,10,0,3,255,13,0,2,255,24,0,2,255,6,0,3,255,24,0,3,255,15,0,2,255,6,0,2,255,24,0,3,255,6,0,3,255,4,0,2,255,10,0,2,255,4,0,2,255,15,0,3,255,5,0,2,255,4,0,3,255,4,0,3,255,6,0,2,255,14,0,3,255,16,0,3,255,52,0,2,255,20,0,2,255,10,0,3,255,7,0,2,255,7,0,2,255,4,0,3,255,18,0,3,255,7,0,3,255,8,0,2,255,31,0,3,255,10,0,2,255,25,0,2,255,5,0,3,255,6,0,2,255,9,0,2,255,8,0,3,255,12,0,3,255,5,0,2,0,0,0,3,255,4,0,2,255,6,0,2,0,0,0,2,255,11,0,3,255,8,0,3,255,6,0,3,0,0,0,3,255,39,0,2,0,0,2,255,10,0,2,255,31,0,3,255,11,0,2,255,27,0,2,0,0,0,3,255,22,0,2,255,4,0,3,255,26,0,3,255,27,0,2,255,31,0,3,255,4,0,2,0,0,0,2,255,27,0,3,0,0,0,3,255,5,0,2,255,31,0,3,255,50,0,2,255,6,0,2,255,24,0,3,255,37,0
};
uint16_t couple_snow_delays[] = {110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110};
uint16_t couple_snow_offsets[] = {0,291,580,875,1162,1443,1728,2023,2310,2583,2864,3151,3445,3746,4035,4320,4609,4905,5205,5502,5803,6108,6417,6722,7011,7295,7583,7884,8189,8486,8779,9068,9354};
AnimationData couple_snow = {&couple_snow_colors[0], &couple_snow_data[0], &couple_snow_offsets[0], &couple_snow_delays[0], false, 12, 32, 32, 32};
uint32_t heart_colors[] = {0x000000, 0x000000, 0x000000, 0xAB2121, 0xFF1E00, 0xFF6A07};
uint8_t heart_data[] = {
255,167,2,3,255,5,4,3,255,4,2,3,255,5,4,3,255,13,2,255,9,4,2,2,255,9,4,255,11,2,4,4,4,5,5,255,17,4,255,9,2,3,4,4,255,4,5,255,16,4,3,255,8,2,4,4,4,255,4,5,255,17,4,255,7,2,3,4,4,4,255,4,5,255,17,4,3,255,6,2,3,255,4,4,5,5,255,18,4,3,255,6,2,3,255,24,4,3,255,6,2,3,255,24,4,3,255,7,2,255,24,4,255,8,2,3,255,22,4,3,255,9,2,3,255,20,4,3,255,11,2,255,20,4,255,13,2,255,18,4,255,15,2,255,16,4,255,17,2,255,14,4,255,19,2,255,12,4,255,21,2,255,10,4,255,23,2,255,8,4,255,25,2,255,6,4,255,27,2,255,4,4,255,29,2,4,4,255,175,2,
255,136,0,255,5,3,255,6,0,255,5,3,255,15,0,4,255,5,0,4,255,4,0,4,255,5,0,4,255,75,0,4,255,22,0,4,255,39,0,4,255,24,0,4,255,6,0,4,255,24,0,4,255,6,0,4,255,24,0,4,255,6,0,4,255,24,0,4,255,62,0,4,255,30,0,4,255,10,0,3,255,32,0,3,255,18,0,3,255,13,0,3,255,16,0,3,255,15,0,3,255,14,0,3,255,17,0,3,255,12,0,3,255,19,0,3,255,10,0,3,255,21,0,3,255,8,0,3,255,23,0,3,255,6,0,3,255,25,0,3,255,4,0,3,255,27,0,3,0,0,3,255,174,0,
255,103,0,255,6,3,255,6,0,255,6,3,255,13,0,255,7,4,3,255,4,0,3,255,6,4,3,255,11,0,4,4,255,7,0,3,0,0,3,255,7,0,4,3,255,9,0,4,4,255,9,0,4,4,255,9,0,4,3,255,8,0,4,0,0,5,0,4,255,17,0,4,255,7,0,3,0,0,5,0,0,0,4,255,17,0,3,255,6,0,4,0,0,5,0,0,0,4,255,17,0,4,255,9,0,5,0,0,0,4,255,28,0,5,0,4,255,89,0,4,255,24,0,4,255,6,0,3,4,255,23,0,3,255,7,0,4,4,255,21,0,4,255,9,0,4,255,20,0,4,255,10,0,4,4,255,18,0,4,4,255,11,0,4,4,255,16,0,4,4,255,12,0,4,4,4,255,14,0,4,4,4,255,13,0,4,4,4,255,12,0,4,4,4,255,15,0,4,4,4,255,10,0,4,4,4,255,17,0,4,4,4,255,8,0,4,4,4,255,19,0,4,4,4,255,6,0,4,4,4,255,21,0,4,4,4,255,4,0,4,4,4,255,23,0,4,4,4,0,0,4,4,4,255,25,0,3,255,4,4,3,255,141,0,
255,103,0,255,6,2,255,6,0,255,6,2,255,13,0,2,2,255,5,3,2,255,4,0,2,255,5,3,2,2,255,11,0,2,2,255,7,0,2,0,0,2,255,7,0,2,2,255,9,0,2,2,255,9,0,2,2,255,9,0,2,2,255,8,0,2,0,0,4,0,5,255,17,0,2,255,7,0,2,0,0,4,0,0,0,5,255,17,0,2,255,6,0,2,0,0,4,0,0,0,5,255,17,0,2,255,9,0,4,0,0,0,5,255,28,0,4,0,5,255,89,0,2,255,24,0,2,255,6,0,2,3,255,22,0,3,2,255,7,0,2,3,255,20,0,3,2,255,9,0,3,255,20,0,3,255,10,0,2,3,255,18,0,3,2,255,11,0,2,3,255,16,0,3,2,255,12,0,2,2,3,255,14,0,3,2,2,255,13,0,2,2,3,255,12,0,3,2,2,255,15,0,2,2,3,255,10,0,3,2,2,255,17,0,2,2,3,255,8,0,3,2,2,255,19,0,2,2,3,255,6,0,3,2,2,255,21,0,2,2,3,255,4,0,3,2,2,255,23,0,2,2,3,0,0,3,2,2,255,25,0,255,6,2,255,141,0,
255,136,0,255,5,2,255,6,0,255,5,2,255,15,0,3,255,5,0,3,255,4,0,3,255,5,0,3,255,75,0,3,255,22,0,3,255,39,0,3,255,24,0,3,255,6,0,3,255,24,0,3,255,6,0,3,255,24,0,3,255,6,0,3,255,24,0,3,255,104,0,2,255,20,0,2,255,11,0,2,255,18,0,2,255,13,0,2,255,16,0,2,255,15,0,2,255,14,0,2,255,17,0,2,255,12,0,2,255,19,0,2,255,10,0,2,255,21,0,2,255,8,0,2,255,23,0,2,255,6,0,2,255,25,0,2,255,4,0,2,255,27,0,2,0,0,2,255,174,0,
255,135,0,3,255,5,4,3,255,4,0,3,255,5,4,3,255,13,0,3,4,255,5,0,4,3,0,0,3,4,255,5,0,4,3,255,11,0,4,255,9,0,4,4,255,9,0,4,255,9,0,4,0,0,5,0,4,255,17,0,4,255,7,0,3,4,0,5,0,0,0,4,255,16,0,4,3,255,6,0,4,0,0,5,0,0,0,4,255,17,0,4,255,6,0,4,0,0,5,0,0,0,4,255,17,0,4,255,6,0,4,0,0,0,5,0,4,255,18,0,4,255,6,0,4,255,24,0,4,255,6,0,4,255,24,0,4,255,6,0,4,255,24,0,4,255,6,0,3,4,255,22,0,4,3,255,7,0,3,4,255,20,0,4,3,255,9,0,4,255,20,0,4,255,11,0,4,255,18,0,4,255,12,0,3,4,255,16,0,4,3,255,13,0,3,4,255,14,0,4,3,255,15,0,3,4,255,12,0,4,3,255,17,0,3,4,255,10,0,4,3,255,19,0,3,4,255,8,0,4,3,255,21,0,3,4,255,6,0,4,3,255,23,0,3,4,255,4,0,4,3,255,26,0,4,0,0,4,255,29,0,3,3,255,143,0,
255,135,0,255,7,2,255,4,0,255,7,2,255,13,0,2,2,255,6,3,2,0,0,2,2,255,5,3,2,2,255,11,0,2,3,255,7,0,3,2,2,3,255,7,0,2,2,255,9,0,2,3,0,4,0,5,255,5,0,3,3,255,9,0,2,2,255,7,0,2,2,0,4,0,0,0,5,255,16,0,2,2,255,6,0,2,3,0,4,0,0,0,5,255,16,0,3,2,255,6,0,2,3,0,4,0,0,0,5,255,16,0,3,2,255,6,0,2,3,0,0,4,0,5,255,17,0,3,2,255,6,0,2,3,255,22,0,3,2,255,6,0,2,3,255,22,0,3,2,255,6,0,2,2,255,22,0,2,2,255,6,0,2,2,255,22,0,2,2,255,7,0,2,2,255,20,0,2,2,255,9,0,2,3,255,18,0,3,2,255,11,0,2,3,255,16,0,3,2,255,12,0,2,2,3,255,14,0,3,2,2,255,13,0,2,2,3,255,12,0,3,2,2,255,15,0,2,2,3,255,10,0,3,2,2,255,17,0,2,2,3,255,8,0,3,2,2,255,19,0,2,2,3,255,6,0,3,2,2,255,21,0,2,2,3,255,4,0,3,2,2,255,23,0,2,2,3,0,0,3,2,2,255,26,0,2,3,3,2,255,29,0,2,2,255,143,0,
255,167,0,3,255,5,4,255,5,0,3,255,5,4,3,255,13,0,4,255,7,0,4,0,0,4,255,7,0,4,255,11,0,4,255,9,0,4,4,255,9,0,4,255,9,0,3,255,22,0,3,255,8,0,4,255,22,0,4,255,7,0,3,4,255,22,0,4,3,255,6,0,3,4,255,22,0,4,3,255,6,0,3,4,255,22,0,4,3,255,6,0,3,4,255,22,0,4,3,255,7,0,4,255,22,0,4,255,8,0,3,255,22,0,3,255,9,0,3,255,20,0,3,255,11,0,4,255,18,0,4,255,13,0,4,255,16,0,4,255,15,0,4,255,14,0,4,255,17,0,4,255,12,0,4,255,19,0,4,255,10,0,4,255,21,0,4,255,8,0,4,255,23,0,4,255,6,0,4,255,25,0,4,255,4,0,4,255,27,0,4,0,0,4,255,29,0,4,4,255,175,0,
255,136,0,255,5,3,255,6,0,255,5,3,255,15,0,4,255,5,0,4,255,4,0,4,255,5,0,4,255,75,0,4,255,22,0,4,255,39,0,4,255,24,0,4,255,6,0,4,255,24,0,4,255,6,0,4,255,24,0,4,255,6,0,4,255,24,0,4,255,62,0,4,255,30,0,4,255,10,0,3,255,32,0,3,255,18,0,3,255,13,0,3,255,16,0,3,255,15,0,3,255,14,0,3,255,17,0,3,255,12,0,3,255,19,0,3,255,10,0,3,255,21,0,3,255,8,0,3,255,23,0,3,255,6,0,3,255,25,0,3,255,4,0,3,255,27,0,3,0,0,3,255,174,0,
255,103,0,255,6,3,255,6,0,255,6,3,255,13,0,255,7,4,3,255,4,0,3,255,6,4,3,255,11,0,4,4,255,7,0,3,0,0,3,255,7,0,4,3,255,9,0,4,4,255,9,0,4,4,255,9,0,4,3,255,8,0,4,0,0,5,0,4,255,17,0,4,255,7,0,3,0,0,5,0,0,0,4,255,17,0,3,255,6,0,4,0,0,5,0,0,0,4,255,17,0,4,255,9,0,5,0,0,0,4,255,28,0,5,0,4,255,89,0,4,255,24,0,4,255,6,0,3,4,255,23,0,3,255,7,0,4,4,255,21,0,4,255,9,0,4,255,20,0,4,255,10,0,4,4,255,18,0,4,4,255,11,0,4,4,255,16,0,4,4,255,12,0,4,4,4,255,14,0,4,4,4,255,13,0,4,4,4,255,12,0,4,4,4,255,15,0,4,4,4,255,10,0,4,4,4,255,17,0,4,4,4,255,8,0,4,4,4,255,19,0,4,4,4,255,6,0,4,4,4,255,21,0,4,4,4,255,4,0,4,4,4,255,23,0,4,4,4,0,0,4,4,4,255,25,0,3,255,4,4,3,255,141,0,
255,103,0,255,6,2,255,6,0,255,6,2,255,13,0,2,2,255,5,3,2,255,4,0,2,255,5,3,2,2,255,11,0,2,2,255,7,0,2,0,0,2,255,7,0,2,2,255,9,0,2,2,255,9,0,2,2,255,9,0,2,2,255,8,0,2,0,0,4,0,5,255,17,0,2,255,7,0,2,0,0,4,0,0,0,5,255,17,0,2,255,6,0,2,0,0,4,0,0,0,5,255,17,0,2,255,9,0,4,0,0,0,5,255,28,0,4,0,5,255,89,0,2,255,24,0,2,255,6,0,2,3,255,23,0,2,255,7,0,2,3,255,21,0,2,255,9,0,3,255,20,0,2,255,10,0,2,3,255,18,0,3,2,255,11,0,2,3,255,16,0,3,2,255,12,0,2,2,3,255,14,0,3,2,2,255,13,0,2,2,3,255,12,0,3,2,2,255,15,0,2,2,3,255,10,0,3,2,2,255,17,0,2,2,3,255,8,0,3,2,2,255,19,0,2,2,3,255,6,0,3,2,2,255,21,0,2,2,3,255,4,0,3,2,2,255,23,0,2,2,3,0,0,3,2,2,255,25,0,255,6,2,255,141,0,
255,136,0,255,5,2,255,6,0,255,5,2,255,15,0,3,255,5,0,3,255,4,0,3,255,5,0,3,255,75,0,3,255,22,0,3,255,39,0,3,255,24,0,3,255,6,0,3,255,24,0,3,255,6,0,3,255,24,0,3,255,6,0,3,255,24,0,3,255,62,0,3,255,30,0,3,255,10,0,2,255,32,0,2,255,18,0,2,255,13,0,2,255,16,0,2,255,15,0,2,255,14,0,2,255,17,0,2,255,12,0,2,255,19,0,2,255,10,0,2,255,21,0,2,255,8,0,2,255,23,0,2,255,6,0,2,255,25,0,2,255,4,0,2,255,27,0,2,0,0,2,255,174,0,
255,135,0,3,255,5,4,3,255,4,0,3,255,5,4,3,255,13,0,3,4,255,5,0,4,3,0,0,3,4,255,5,0,4,3,255,11,0,4,255,9,0,4,4,255,9,0,4,255,9,0,4,0,0,5,0,4,255,17,0,4,255,7,0,3,4,0,5,0,0,0,4,255,16,0,4,3,255,6,0,4,0,0,5,0,0,0,4,255,17,0,4,255,6,0,4,0,0,5,0,0,0,4,255,17,0,4,255,6,0,4,0,0,0,5,0,4,255,18,0,4,255,6,0,4,255,24,0,4,255,6,0,4,255,24,0,4,255,6,0,4,255,24,0,4,255,6,0,3,4,255,22,0,4,3,255,7,0,3,4,255,20,0,4,3,255,9,0,4,255,20,0,4,255,11,0,4,255,18,0,4,255,12,0,3,4,255,16,0,4,3,255,13,0,3,4,255,14,0,4,3,255,15,0,3,4,255,12,0,4,3,255,17,0,3,4,255,10,0,4,3,255,19,0,3,4,255,8,0,4,3,255,21,0,3,4,255,6,0,4,3,255,23,0,3,4,255,4,0,4,3,255,26,0,4,0,0,4,255,29,0,3,3,255,143,0,
255,135,0,255,7,2,255,4,0,255,7,2,255,13,0,2,2,255,6,3,2,0,0,2,2,255,5,3,2,2,255,11,0,2,3,255,7,0,3,2,2,3,255,7,0,2,2,255,9,0,2,3,0,4,0,5,255,5,0,3,3,255,9,0,2,2,255,7,0,2,2,0,4,0,0,0,5,255,16,0,2,2,255,6,0,2,3,0,4,0,0,0,5,255,16,0,3,2,255,6,0,2,3,0,4,0,0,0,5,255,16,0,3,2,255,6,0,2,3,0,0,4,0,5,255,17,0,3,2,255,6,0,2,3,255,22,0,3,2,255,6,0,2,3,255,22,0,3,2,255,6,0,2,2,255,22,0,2,2,255,6,0,2,2,255,22,0,2,2,255,7,0,2,2,255,20,0,2,2,255,9,0,2,3,255,18,0,3,2,255,11,0,2,3,255,16,0,3,2,255,12,0,2,2,3,255,14,0,3,2,2,255,13,0,2,2,3,255,12,0,3,2,2,255,15,0,2,2,3,255,10,0,3,2,2,255,17,0,2,2,3,255,8,0,3,2,2,255,19,0,2,2,3,255,6,0,3,2,2,255,21,0,2,2,3,255,4,0,3,2,2,255,23,0,2,2,3,0,0,3,2,2,255,26,0,2,3,3,2,255,29,0,2,2,255,143,0,
255,167,0,3,255,5,4,255,5,0,3,255,5,4,3,255,13,0,4,255,7,0,4,0,0,4,255,7,0,4,255,11,0,4,255,9,0,4,4,255,9,0,4,255,9,0,3,255,22,0,3,255,8,0,4,255,22,0,4,255,7,0,3,4,255,22,0,4,3,255,6,0,3,4,255,22,0,4,3,255,6,0,3,4,255,22,0,4,3,255,6,0,3,4,255,22,0,4,3,255,7,0,4,255,22,0,4,255,8,0,3,255,22,0,3,255,9,0,3,255,20,0,3,255,11,0,4,255,18,0,4,255,13,0,4,255,16,0,4,255,15,0,4,255,14,0,4,255,17,0,4,255,12,0,4,255,19,0,4,255,10,0,4,255,21,0,4,255,8,0,4,255,23,0,4,255,6,0,4,255,25,0,4,255,4,0,4,255,27,0,4,0,0,4,255,29,0,4,4,255,175,0
};
uint16_t heart_delays[] = {100,100,100,100,100,100,100,400,100,100,100,100,100,100,200};
uint16_t heart_offsets[] = {0,190,344,608,875,1025,1291,1588,1790,1944,2208,2473,2627,2893,3190,3392};
AnimationData heart = {&heart_colors[0], &heart_data[0], &heart_offsets[0], &heart_delays[0], false, 6, 15, 32, 32};

View File

@ -1,3 +1,5 @@
//#define DEBUG
#define WIFI_SSID "....." #define WIFI_SSID "....."
#define WIFI_PASS "....." #define WIFI_PASS "....."
@ -20,8 +22,9 @@
#define MQTT_TOPIC_STATUS "pitrix/status" #define MQTT_TOPIC_STATUS "pitrix/status"
#define MQTT_TOPIC_LOG "pitrix/log" #define MQTT_TOPIC_LOG "pitrix/log"
#define OTA_HOSTNAME "pitrix" #define HOSTNAME "pitrix-%08X"
#define OTA_STARTUP_DELAY 5 // How many seconds to wait at startup. Set to 0 to disable. #define OTA_STARTUP_DELAY 5 // How many seconds to wait at startup. Set to 0 to disable.
#define FPS 50 #define FPS 50
#define SHOW_TEXT_DELAY 100 #define SHOW_TEXT_DELAY 100
#define EFFECT_CYCLE_TIME 60000

142
effects.h
View File

@ -1,21 +1,33 @@
class Effect { class Effect {
protected:
Window window = {0, 0, LED_WIDTH, LED_HEIGHT}; // Use a full screen window per default.
public: public:
virtual void loop() {}; virtual void loop() = 0;
boolean supports_window = false;
void setWindow(Window win) {
window = win;
};
};
struct EffectEntry {
char* name;
Effect* effect;
}; };
class Bell : public Effect { class Bell : public Effect {
private: private:
CRGB color_on = CRGB(0xFFFF00); CRGB color_on = CRGB(0xFFFF00);
CRGB color_off= CRGB(0x000000); CRGB color_off = CRGB(0x000000);
boolean invert = false; boolean invert = false;
public: public:
void loop() { void loop() {
for(int y=0; y<16; y++) { Serial.println("This is Bell.loop()");
for(int x=0; x<2; x++) { for (int y = 0; y < 16; y++) {
for(int z=0; z<8; z++) { for (int x = 0; x < 2; x++) {
leds[XYsafe(x*8+z, y)] = sprite_bell[y*2+x]>>(7-z) & 1 ^ invert ? color_on : color_off; for (int z = 0; z < 8; z++) {
leds[XYsafe(x * 8 + z, y)] = sprite_bell[y * 2 + x] >> (7 - z) & 1 ^ invert ? color_on : color_off;
} }
} }
} }
@ -26,7 +38,7 @@ class Bell : public Effect {
} }
}; };
class Clock : public Effect { class BigClock : public Effect {
private: private:
CRGB color_h = CRGB(0xFF0000); CRGB color_h = CRGB(0xFF0000);
CRGB color_m = CRGB(0x00FF00); CRGB color_m = CRGB(0x00FF00);
@ -59,7 +71,7 @@ class Clock : public Effect {
} }
} }
public: public:
Clock() {} BigClock() {}
void loop() { void loop() {
clear(); clear();
drawNumber(ntpClient.getHours(), 0, 0, color_h); drawNumber(ntpClient.getHours(), 0, 0, color_h);
@ -72,27 +84,44 @@ class Clock : public Effect {
} }
}; };
class SmallClock : public Effect { class Clock : public Effect {
private: private:
CRGB color_h = CRGB(0xFF0000); CRGB color_h = CRGB(0xFF0000);
CRGB color_m = CRGB(0x00FF00); CRGB color_m = CRGB(0x00FF00);
CRGB color_colon = CRGB(0xFFFF00); CRGB color_colon = CRGB(0xFFFF00);
Effect* secondary_effect = 0;
Window window = {0, LED_HEIGHT - 5, LED_WIDTH, 5};
Window secondary_window = {0, 0, LED_WIDTH, LED_HEIGHT - 6};
long secondary_effect_started_at = 0;
public: public:
SmallClock() {} EffectEntry* effects;
void setEffects(EffectEntry* e) {
effects = e;
}
Clock() {}
void loop() { void loop() {
clear(); clear(window);
int h = ntpClient.getHours(); int h = ntpClient.getHours();
drawDigit(numbers3x5, 3, 5, 0, 11, h/10, color_h); drawDigit(window, numbers3x5, 3, 5, 0, 0, h / 10, color_h);
drawDigit(numbers3x5, 3, 5, 4, 11, h%10, color_h); drawDigit(window, numbers3x5, 3, 5, 4, 0, h % 10, color_h);
int m = ntpClient.getMinutes(); int m = ntpClient.getMinutes();
drawDigit(numbers3x5, 3, 5, 9, 11, m/10, color_m); drawDigit(window, numbers3x5, 3, 5, 9, 0, m / 10, color_m);
drawDigit(numbers3x5, 3, 5, 13, 11, m%10, color_m); drawDigit(window, numbers3x5, 3, 5, 13, 0, m % 10, color_m);
if (ntpClient.getSeconds() & 1) { if (ntpClient.getSeconds() & 1) {
leds[XYsafe(7, 12)] = color_colon; setPixel(window, 7, 1, color_colon);
leds[XYsafe(7, 14)] = color_colon; setPixel(window, 7, 3, color_colon);
} }
// Change effect?
if (secondary_effect == 0 || secondary_effect_started_at == 0 || millis() - secondary_effect_started_at > EFFECT_CYCLE_TIME) {
secondary_effect = effects[0].effect;
secondary_effect_started_at = millis();
secondary_effect->setWindow(secondary_window);
}
secondary_effect->loop();
} }
}; };
@ -114,14 +143,15 @@ class Sinematrix3 : public Effect {
double tx2 = 0; double tx2 = 0;
double ty2 = 0; double ty2 = 0;
double basecol = 0; double basecol = 0;
double fx = 1.0/(LED_WIDTH/PI); double fx = 1.0 / (LED_WIDTH / PI);
double fy = 1.0/(LED_HEIGHT/PI); double fy = 1.0 / (LED_HEIGHT / PI);
Matrix rotate; Matrix rotate;
public: public:
boolean supports_window = true;
Sinematrix3() {} Sinematrix3() {}
void loop() { void loop() {
pangle = addmodpi( pangle, 0.0133 + (angle/256) ); pangle = addmodpi( pangle, 0.0133 + (angle / 256) );
angle = cos(pangle) * PI; angle = cos(pangle) * PI;
sx = addmodpi( sx, 0.00673 ); sx = addmodpi( sx, 0.00673 );
sy = addmodpi( sy, 0.00437 ); sy = addmodpi( sy, 0.00437 );
@ -129,8 +159,8 @@ class Sinematrix3 : public Effect {
ty = addmodpi( ty, 0.00293 ); ty = addmodpi( ty, 0.00293 );
cx = addmodpi( cx, 0.00197 ); cx = addmodpi( cx, 0.00197 );
cy = addmodpi( cy, 0.00227 ); cy = addmodpi( cy, 0.00227 );
rcx = (LED_WIDTH/2) + (sin(cx) * LED_WIDTH); rcx = (LED_WIDTH / 2) + (sin(cx) * LED_WIDTH);
rcy = (LED_HEIGHT/2) + (sin(cy) * LED_HEIGHT); rcy = (LED_HEIGHT / 2) + (sin(cy) * LED_HEIGHT);
angle2 = addmodpi( angle2, 0.0029 ); angle2 = addmodpi( angle2, 0.0029 );
sx2 = addmodpi( sx2, 0.0041); sx2 = addmodpi( sx2, 0.0041);
sy2 = addmodpi( sy2, 0.0031); sy2 = addmodpi( sy2, 0.0031);
@ -145,21 +175,22 @@ class Sinematrix3 : public Effect {
.a22 = cos(angle) .a22 = cos(angle)
}; };
Matrix zoom = { Matrix zoom = {
.a11 = sin(sx)/4.0 + 0.15, .a11 = sin(sx) / 4.0 + 0.15,
.a12 = 0, //atan(cos(sx2)), .a12 = 0, //atan(cos(sx2)),
.a21 = 0, //atan(cos(sy2)), .a21 = 0, //atan(cos(sy2)),
.a22 = cos(sy)/4.0 + 0.15 .a22 = cos(sy) / 4.0 + 0.15
}; };
Vector translate = { Vector translate = {
.x1 = sin(tx) * LED_WIDTH, .x1 = sin(tx) * LED_WIDTH,
.x2 = sin(ty) * LED_HEIGHT .x2 = sin(ty) * LED_HEIGHT
}; };
for( int x = 0; x < LED_WIDTH; x++ ) { for ( int x = 0; x < LED_WIDTH; x++ ) {
for( int y = 0; y < LED_HEIGHT; y++ ) { for ( int y = 0; y < LED_HEIGHT; y++ ) {
Vector c = add(multiply( multiply(rotate, zoom), { .x1 = x-rcx, .x2 = y-rcy } ), translate); Vector c = add(multiply( multiply(rotate, zoom), { .x1 = x - rcx, .x2 = y - rcy } ), translate);
//Vector c2 = add(multiply( multiply(zoom2, rotate2), { .x1 = x, .x2 = y } ), translate2); //Vector c2 = add(multiply( multiply(zoom2, rotate2), { .x1 = x, .x2 = y } ), translate2);
leds[XYsafe(x,y)] = CHSV((basecol+basefield(c.x1, c.x2))*255, 255, 255); //31+(sines(c2.x1-10, c2.x2-10)*224)); setPixel(window, x, y, CHSV((basecol + basefield(c.x1, c.x2)) * 255, 255, 255));
//leds[XYsafe(x,y)] = CHSV((basecol+basefield(c.x1, c.x2))*255, 255, 255); //31+(sines(c2.x1-10, c2.x2-10)*224));
} }
} }
} }
@ -172,12 +203,10 @@ class Static : public Effect {
Static(CRGB col) { Static(CRGB col) {
color = col; color = col;
} }
boolean supports_window = true;
void loop() { void loop() {
EVERY_N_SECONDS(1) { EVERY_N_SECONDS(1) {
for ( int i = 0; i < LED_COUNT; i++) { clear(window, color);
leds[i] = color;
}
FastLED.show();
} }
} }
}; };
@ -186,40 +215,59 @@ class Animation : public Effect {
private: private:
AnimationData *animation; AnimationData *animation;
int frame = 0; int frame = 0;
CRGB background_color;
int xOffset, yOffset;
long frameSince = 0;
public: public:
Animation(AnimationData *anim) { Animation(AnimationData *anim) {
Animation(anim, CRGB(0), 0, 0);
}
Animation(AnimationData *anim, CRGB background_color) {
Animation(anim, background_color, 0, 0);
}
Animation(AnimationData *anim, CRGB bg_color, int x, int y) {
animation = anim; animation = anim;
background_color = bg_color;
xOffset = x;
yOffset = y;
} }
void loop() { void loop() {
Serial.printf("Animation.loop. Animation is %p.", (void *)animation);
CRGB colors[animation->color_count]; CRGB colors[animation->color_count];
int led_index = 0; int led_index = 0;
for(int i=0; i<animation->color_count; i++) colors[i] = CRGB(animation->colors[i]); for (int i = 0; i < animation->color_count; i++) colors[i] = CRGB(animation->colors[i]);
for(int i=animation->offsets[frame]; i<animation->offsets[frame+1]; i++) { for (int i = animation->offsets[frame]; i < animation->offsets[frame + 1]; i++) {
if (animation->data[i]==255) { // Run-length encoded data if (animation->data[i] == 255) { // Run-length encoded data
for (int j=0; j<animation->data[i+1]; j++) { uint8_t color = animation->data[i + 2];
if (frame==0 || animation->data[i+2]>0) { for (int j = 0; j < animation->data[i + 1]; j++) {
set(led_index, colors[animation->data[i+2]]); if (color > 1) {
set(led_index, colors[animation->data[i + 2]]);
} else if (color==1) {
set(led_index, background_color);
} }
led_index++; led_index++;
} }
i+=2; i += 2;
} else { } else {
if (frame==0 || animation->data[i]>0) { uint8_t color = animation->data[i];
if (color > 1) {
set(led_index, colors[animation->data[i]]); set(led_index, colors[animation->data[i]]);
} else if (color == 1) {
set(led_index, background_color);
} }
led_index++; led_index++;
} }
} }
EVERY_N_MILLISECONDS(250) { if (frameSince == 0 || frameSince + frameDelay(animation, frame) < millis() || frameSince > millis()) {
frame = (frame + 1) % animation->frame_count; frame = (frame + 1) % animation->frame_count;
frameSince = millis();
} }
} }
void set(int i, CRGB color) { void set(int i, CRGB color) {
setPixel(i % animation->w, i / animation->h, color); setPixel(xOffset + (i % animation->w), yOffset + (i / animation->h), color);
}
uint16_t frameDelay(AnimationData* animation, int frame) {
if (animation->individual_delays) return animation->delays[frame];
return animation->delays[0];
} }
}; };
struct EffectEntry {
char* name;
Effect* effect;
};

View File

@ -15,6 +15,8 @@ int XYsafe(int x, int y) {
return y*LED_WIDTH+x; return y*LED_WIDTH+x;
} }
void setPixel(int x, int y, CRGB color) { void setPixel(int x, int y, CRGB color) {
if ( x >= LED_WIDTH) return; if ( x >= LED_WIDTH) return;
if ( y >= LED_HEIGHT) return; if ( y >= LED_HEIGHT) return;
@ -38,12 +40,26 @@ void setPixel(int i, CRGB color) {
setPixel(x, y, color); setPixel(x, y, color);
} }
void setPixel(Window win, int x, int y, CRGB color) {
if (x >= win.w || y >= win.h || x < 0 || y < 0) return;
setPixel(win.x + x, win.y + y, color);
}
void clear(Window window, CRGB color) {
for ( byte y = 0; y < window.h; y++) {
for ( byte x = 0; x < window.w; x++) {
setPixel(window, x, y, color);
}
}
}
void clear(Window window) {
clear(window, CRGB(0));
}
void clear() { void clear() {
for ( byte y = 0; y < LED_HEIGHT; y++) { Window w = {0, 0, LED_WIDTH, LED_HEIGHT};
for ( byte x = 0; x < LED_WIDTH; x++) { clear(w);
leds[ XYsafe(x, y)] = CHSV((16*y)+(47*x), 255, 42);
}
}
} }
inline double sines(double x, double y) { inline double sines(double x, double y) {

14
mqtt.h
View File

@ -3,11 +3,11 @@ long mqtt_last_reconnect_attempt = 0;
void mqtt_callback(char* topic, byte* payload, unsigned int length) { void mqtt_callback(char* topic, byte* payload, unsigned int length) {
payload[length] = '\0'; payload[length] = '\0';
for (int i=0; i<NUM_EFFECTS; i++) { for (int i=0; i<NUM_EFFECTS; i++) {
EffectEntry e = effects[i]; EffectEntry* e = &effects[i];
if (strcmp(e.name, (char*)payload)==0) { if (strcmp(e->name, (char*)payload)==0) {
current_effect = e.effect; //Serial.printf("Effect found in mqtt_callback: %p\n", (void *)&e->effect);
current_effect = e->effect;
clear(); clear();
return; return;
} }
@ -15,7 +15,11 @@ void mqtt_callback(char* topic, byte* payload, unsigned int length) {
} }
boolean mqtt_connect() { boolean mqtt_connect() {
if (mqtt_client.connect("pitrix", MQTT_USER, MQTT_PASS)) { char client_id[30];
snprintf(client_id, 30, HOSTNAME, ESP.getChipId());
LOG("MQTT * Connecting to MQTT server with client id "); LOGln(client_id);
if (mqtt_client.connect(client_id, MQTT_USER, MQTT_PASS)) {
LOGln("MQTT * Connected.");
mqtt_client.subscribe(MQTT_TOPIC_MODE); mqtt_client.subscribe(MQTT_TOPIC_MODE);
mqtt_client.publish(MQTT_TOPIC_STATUS, "ONLINE"); mqtt_client.publish(MQTT_TOPIC_STATUS, "ONLINE");
} }

View File

@ -23,7 +23,10 @@ void ota_setup() {
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed"); else if (error == OTA_END_ERROR) Serial.println("End Failed");
}); });
ArduinoOTA.setHostname(OTA_HOSTNAME); char client_id[30];
snprintf(client_id, 30, HOSTNAME, ESP.getChipId());
LOG("OTA * Starting OTA with client_id "); LOGln(client_id);
ArduinoOTA.setHostname(client_id);
ArduinoOTA.begin(); ArduinoOTA.begin();
} }

View File

@ -12,6 +12,21 @@ WiFiClient wifi;
WiFiUDP ntpUDP; WiFiUDP ntpUDP;
NTPClient ntpClient(ntpUDP, NTP_SERVER, NTP_OFFSET, NTP_INTERVAL); NTPClient ntpClient(ntpUDP, NTP_SERVER, NTP_OFFSET, NTP_INTERVAL);
#ifdef DEBUG
#define LOG(x) Serial.print(x);
#define LOGln(x) Serial.println(x);
#else
#define LOG(x) ""
#define LOGln(x) ""
#endif
typedef struct {
uint8_t x;
uint8_t y;
uint8_t w;
uint8_t h;
} Window;
#include "functions.h" #include "functions.h"
#include "text.h" #include "text.h"
#include "sprites.h" #include "sprites.h"
@ -19,6 +34,27 @@ NTPClient ntpClient(ntpUDP, NTP_SERVER, NTP_OFFSET, NTP_INTERVAL);
#include "tools.h" #include "tools.h"
#include "effects.h" #include "effects.h"
#define NUM_EFFECTS 7
//EffectEntry effects[NUM_EFFECTS];
Sinematrix3 sinematrix3;
BigClock big_clock;
Clock clock;
Bell bell;
Static off(CRGB(0x000000));
Animation anim_koopa(&koopa, CRGB(0x000000), 0, 0);
Animation anim_couple_rain(&couple_rain, CRGB(0x000000), -8, -16);
EffectEntry effects[NUM_EFFECTS] = {
{"sinematrix3", (Effect *)&sinematrix3},
{"big_clock", (Effect *)&big_clock},
{"clock", (Effect *)&clock},
{"bell", (Effect *)&bell},
{"off", (Effect *)&off},
{"koopa", (Effect *)&anim_koopa},
{"couple_rain", (Effect *)&anim_couple_rain}
};
void setup() { void setup() {
// put your setup code here, to run once: // put your setup code here, to run once:
Serial.begin(74880); Serial.begin(74880);
@ -29,36 +65,25 @@ void setup() {
ntp_setup(); ntp_setup();
mqtt_setup(); mqtt_setup();
Serial.println("Core * Setup complete"); Serial.println("Core * Setup complete");
clock.setEffects(&effects[0]);
} }
Sinematrix3 effect_sinematrix3; Effect* current_effect = &clock;
Clock effect_clock;
SmallClock effect_small_clock;
Bell effect_bell;
Static effect_off(CRGB(0x000000));
Animation effect_koopa(&koopa);
Effect* current_effect = &effect_small_clock;
#define NUM_EFFECTS 6
EffectEntry effects[NUM_EFFECTS] = {
{"bell", &effect_bell},
{"sinematrix3", &effect_sinematrix3},
{"clock", &effect_clock},
{"small_clock", &effect_small_clock},
{"koopa", &effect_koopa},
{"off", &effect_off}
};
#include "mqtt.h" #include "mqtt.h"
uint8_t starting_up = OTA_STARTUP_DELAY; uint8_t starting_up = OTA_STARTUP_DELAY;
int loop_timeouts = 0;
long loop_started_at = 0;
void loop() { void loop() {
// put your main code here, to run repeatedly: loop_started_at = millis();
ota_loop(); ota_loop();
if (starting_up > 0) { if (starting_up > 0) {
EVERY_N_SECONDS(1) { EVERY_N_SECONDS(1) {
Serial.print("Core * Waiting for OTA... "); Serial.println(starting_up);
starting_up--; starting_up--;
clear(); clear();
for (int i=0; i<starting_up; i++) { for (int i=0; i<starting_up; i++) {
@ -73,7 +98,21 @@ void loop() {
mqtt_loop(); mqtt_loop();
EVERY_N_MILLISECONDS(1000 / FPS) { EVERY_N_MILLISECONDS(1000 / FPS) {
Serial.println("Core * loop running");
//Serial.printf("Core * current_effect: %p\n", (void *)&current_effect);
current_effect->loop(); current_effect->loop();
FastLED.show(); FastLED.show();
} }
if (MONITOR_LOOP_TIMES && millis()-loop_started_at>=MONITOR_LOOP_TIME_THRESHOLD) {
LOG("Core * Loop took "); LOG(millis()-loop_started_at); LOGln("ms.");
loop_timeouts++;
LOG("Core * Timeout counter is now "); LOGln(loop_timeouts);
if (loop_timeouts >= MONITOR_LOOP_TIME_COUNT_MAX) {
ESP.restart();
}
} else if (loop_timeouts > 0) {
loop_timeouts--;
}
} }

16
text.h
View File

@ -123,25 +123,25 @@ static unsigned char numbers3x5[] = {
B11101, B10101, B11111, // 9 B11101, B10101, B11111, // 9
}; };
void drawTextSprite(unsigned char* sprite, int w, int h, int xPos, int yPos, CRGB color) { void drawTextSprite(Window window, unsigned char* sprite, int w, int h, int xPos, int yPos, CRGB color) {
for (byte y=0; y<h; y++) for (byte x=0; x<w; x++) { for (byte y=0; y<h; y++) for (byte x=0; x<w; x++) {
bool on = (sprite[x]>>(h-1-y)&1)*255; bool on = (sprite[x]>>(h-1-y)&1)*255;
if (on) leds[XYsafe(x+xPos, y+yPos)] = color; if (on) setPixel(window, x+xPos, y+yPos, color);
} }
} }
void drawChar(unsigned char* font, int w, int h, int x, int y, char c, CRGB color) { void drawChar(Window window, unsigned char* font, int w, int h, int x, int y, char c, CRGB color) {
unsigned char* sprite = &font[(c-32)*w]; unsigned char* sprite = &font[(c-32)*w];
drawTextSprite(sprite, w, h, x, y, color); drawTextSprite(window, sprite, w, h, x, y, color);
} }
void drawDigit(unsigned char* font, int w, int h, int x, int y, int digit, CRGB color) { void drawDigit(Window window, unsigned char* font, int w, int h, int x, int y, int digit, CRGB color) {
unsigned char* sprite = &font[digit*w]; unsigned char* sprite = &font[digit*w];
drawTextSprite(sprite, w, h, x, y, color); drawTextSprite(window, sprite, w, h, x, y, color);
} }
void drawText(char *font, int w, int h, char *text, int x, int y, CRGB color) { void drawText(Window window, char *font, int w, int h, char *text, int x, int y, CRGB color) {
for (int i = 0; i < strlen(text); i++) { for (int i = 0; i < strlen(text); i++) {
drawChar(font5x7, 5, 7, x+i*(w+1), y, text[i], color); drawChar(window, font5x7, 5, 7, x+i*(w+1), y, text[i], color);
} }
} }