diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2b16c31
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+.pio
+.vscode/.browse.c_cpp.db*
+.vscode/c_cpp_properties.json
+.vscode/launch.json
+.vscode/ipch
+.DS_Store
\ No newline at end of file
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..080e70d
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,10 @@
+{
+ // See http://go.microsoft.com/fwlink/?LinkId=827846
+ // for the documentation about the extensions.json format
+ "recommendations": [
+ "platformio.platformio-ide"
+ ],
+ "unwantedRecommendations": [
+ "ms-vscode.cpptools-extension-pack"
+ ]
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..cbe5ad1
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,437 @@
+Attribution-NonCommercial-ShareAlike 4.0 International
+
+=======================================================================
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and
+does not provide legal services or legal advice. Distribution of
+Creative Commons public licenses does not create a lawyer-client or
+other relationship. Creative Commons makes its licenses and related
+information available on an "as-is" basis. Creative Commons gives no
+warranties regarding its licenses, any material licensed under their
+terms and conditions, or any related information. Creative Commons
+disclaims all liability for damages resulting from their use to the
+fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and
+conditions that creators and other rights holders may use to share
+original works of authorship and other material subject to copyright
+and certain other rights specified in the public license below. The
+following considerations are for informational purposes only, are not
+exhaustive, and do not form part of our licenses.
+
+ Considerations for licensors: Our public licenses are
+ intended for use by those authorized to give the public
+ permission to use material in ways otherwise restricted by
+ copyright and certain other rights. Our licenses are
+ irrevocable. Licensors should read and understand the terms
+ and conditions of the license they choose before applying it.
+ Licensors should also secure all rights necessary before
+ applying our licenses so that the public can reuse the
+ material as expected. Licensors should clearly mark any
+ material not subject to the license. This includes other CC-
+ licensed material, or material used under an exception or
+ limitation to copyright. More considerations for licensors:
+ wiki.creativecommons.org/Considerations_for_licensors
+
+ Considerations for the public: By using one of our public
+ licenses, a licensor grants the public permission to use the
+ licensed material under specified terms and conditions. If
+ the licensor's permission is not necessary for any reason--for
+ example, because of any applicable exception or limitation to
+ copyright--then that use is not regulated by the license. Our
+ licenses grant only permissions under copyright and certain
+ other rights that a licensor has authority to grant. Use of
+ the licensed material may still be restricted for other
+ reasons, including because others have copyright or other
+ rights in the material. A licensor may make special requests,
+ such as asking that all changes be marked or described.
+ Although not required by our licenses, you are encouraged to
+ respect those requests where reasonable. More considerations
+ for the public:
+ wiki.creativecommons.org/Considerations_for_licensees
+
+=======================================================================
+
+Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
+Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree
+to be bound by the terms and conditions of this Creative Commons
+Attribution-NonCommercial-ShareAlike 4.0 International Public License
+("Public License"). To the extent this Public License may be
+interpreted as a contract, You are granted the Licensed Rights in
+consideration of Your acceptance of these terms and conditions, and the
+Licensor grants You such rights in consideration of benefits the
+Licensor receives from making the Licensed Material available under
+these terms and conditions.
+
+
+Section 1 -- Definitions.
+
+ a. Adapted Material means material subject to Copyright and Similar
+ Rights that is derived from or based upon the Licensed Material
+ and in which the Licensed Material is translated, altered,
+ arranged, transformed, or otherwise modified in a manner requiring
+ permission under the Copyright and Similar Rights held by the
+ Licensor. For purposes of this Public License, where the Licensed
+ Material is a musical work, performance, or sound recording,
+ Adapted Material is always produced where the Licensed Material is
+ synched in timed relation with a moving image.
+
+ b. Adapter's License means the license You apply to Your Copyright
+ and Similar Rights in Your contributions to Adapted Material in
+ accordance with the terms and conditions of this Public License.
+
+ c. BY-NC-SA Compatible License means a license listed at
+ creativecommons.org/compatiblelicenses, approved by Creative
+ Commons as essentially the equivalent of this Public License.
+
+ d. Copyright and Similar Rights means copyright and/or similar rights
+ closely related to copyright including, without limitation,
+ performance, broadcast, sound recording, and Sui Generis Database
+ Rights, without regard to how the rights are labeled or
+ categorized. For purposes of this Public License, the rights
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar
+ Rights.
+
+ e. Effective Technological Measures means those measures that, in the
+ absence of proper authority, may not be circumvented under laws
+ fulfilling obligations under Article 11 of the WIPO Copyright
+ Treaty adopted on December 20, 1996, and/or similar international
+ agreements.
+
+ f. Exceptions and Limitations means fair use, fair dealing, and/or
+ any other exception or limitation to Copyright and Similar Rights
+ that applies to Your use of the Licensed Material.
+
+ g. License Elements means the license attributes listed in the name
+ of a Creative Commons Public License. The License Elements of this
+ Public License are Attribution, NonCommercial, and ShareAlike.
+
+ h. Licensed Material means the artistic or literary work, database,
+ or other material to which the Licensor applied this Public
+ License.
+
+ i. Licensed Rights means the rights granted to You subject to the
+ terms and conditions of this Public License, which are limited to
+ all Copyright and Similar Rights that apply to Your use of the
+ Licensed Material and that the Licensor has authority to license.
+
+ j. Licensor means the individual(s) or entity(ies) granting rights
+ under this Public License.
+
+ k. NonCommercial means not primarily intended for or directed towards
+ commercial advantage or monetary compensation. For purposes of
+ this Public License, the exchange of the Licensed Material for
+ other material subject to Copyright and Similar Rights by digital
+ file-sharing or similar means is NonCommercial provided there is
+ no payment of monetary compensation in connection with the
+ exchange.
+
+ l. Share means to provide material to the public by any means or
+ process that requires permission under the Licensed Rights, such
+ as reproduction, public display, public performance, distribution,
+ dissemination, communication, or importation, and to make material
+ available to the public including in ways that members of the
+ public may access the material from a place and at a time
+ individually chosen by them.
+
+ m. Sui Generis Database Rights means rights other than copyright
+ resulting from Directive 96/9/EC of the European Parliament and of
+ the Council of 11 March 1996 on the legal protection of databases,
+ as amended and/or succeeded, as well as other essentially
+ equivalent rights anywhere in the world.
+
+ n. You means the individual or entity exercising the Licensed Rights
+ under this Public License. Your has a corresponding meaning.
+
+
+Section 2 -- Scope.
+
+ a. License grant.
+
+ 1. Subject to the terms and conditions of this Public License,
+ the Licensor hereby grants You a worldwide, royalty-free,
+ non-sublicensable, non-exclusive, irrevocable license to
+ exercise the Licensed Rights in the Licensed Material to:
+
+ a. reproduce and Share the Licensed Material, in whole or
+ in part, for NonCommercial purposes only; and
+
+ b. produce, reproduce, and Share Adapted Material for
+ NonCommercial purposes only.
+
+ 2. Exceptions and Limitations. For the avoidance of doubt, where
+ Exceptions and Limitations apply to Your use, this Public
+ License does not apply, and You do not need to comply with
+ its terms and conditions.
+
+ 3. Term. The term of this Public License is specified in Section
+ 6(a).
+
+ 4. Media and formats; technical modifications allowed. The
+ Licensor authorizes You to exercise the Licensed Rights in
+ all media and formats whether now known or hereafter created,
+ and to make technical modifications necessary to do so. The
+ Licensor waives and/or agrees not to assert any right or
+ authority to forbid You from making technical modifications
+ necessary to exercise the Licensed Rights, including
+ technical modifications necessary to circumvent Effective
+ Technological Measures. For purposes of this Public License,
+ simply making modifications authorized by this Section 2(a)
+ (4) never produces Adapted Material.
+
+ 5. Downstream recipients.
+
+ a. Offer from the Licensor -- Licensed Material. Every
+ recipient of the Licensed Material automatically
+ receives an offer from the Licensor to exercise the
+ Licensed Rights under the terms and conditions of this
+ Public License.
+
+ b. Additional offer from the Licensor -- Adapted Material.
+ Every recipient of Adapted Material from You
+ automatically receives an offer from the Licensor to
+ exercise the Licensed Rights in the Adapted Material
+ under the conditions of the Adapter's License You apply.
+
+ c. No downstream restrictions. You may not offer or impose
+ any additional or different terms or conditions on, or
+ apply any Effective Technological Measures to, the
+ Licensed Material if doing so restricts exercise of the
+ Licensed Rights by any recipient of the Licensed
+ Material.
+
+ 6. No endorsement. Nothing in this Public License constitutes or
+ may be construed as permission to assert or imply that You
+ are, or that Your use of the Licensed Material is, connected
+ with, or sponsored, endorsed, or granted official status by,
+ the Licensor or others designated to receive attribution as
+ provided in Section 3(a)(1)(A)(i).
+
+ b. Other rights.
+
+ 1. Moral rights, such as the right of integrity, are not
+ licensed under this Public License, nor are publicity,
+ privacy, and/or other similar personality rights; however, to
+ the extent possible, the Licensor waives and/or agrees not to
+ assert any such rights held by the Licensor to the limited
+ extent necessary to allow You to exercise the Licensed
+ Rights, but not otherwise.
+
+ 2. Patent and trademark rights are not licensed under this
+ Public License.
+
+ 3. To the extent possible, the Licensor waives any right to
+ collect royalties from You for the exercise of the Licensed
+ Rights, whether directly or through a collecting society
+ under any voluntary or waivable statutory or compulsory
+ licensing scheme. In all other cases the Licensor expressly
+ reserves any right to collect such royalties, including when
+ the Licensed Material is used other than for NonCommercial
+ purposes.
+
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the
+following conditions.
+
+ a. Attribution.
+
+ 1. If You Share the Licensed Material (including in modified
+ form), You must:
+
+ a. retain the following if it is supplied by the Licensor
+ with the Licensed Material:
+
+ i. identification of the creator(s) of the Licensed
+ Material and any others designated to receive
+ attribution, in any reasonable manner requested by
+ the Licensor (including by pseudonym if
+ designated);
+
+ ii. a copyright notice;
+
+ iii. a notice that refers to this Public License;
+
+ iv. a notice that refers to the disclaimer of
+ warranties;
+
+ v. a URI or hyperlink to the Licensed Material to the
+ extent reasonably practicable;
+
+ b. indicate if You modified the Licensed Material and
+ retain an indication of any previous modifications; and
+
+ c. indicate the Licensed Material is licensed under this
+ Public License, and include the text of, or the URI or
+ hyperlink to, this Public License.
+
+ 2. You may satisfy the conditions in Section 3(a)(1) in any
+ reasonable manner based on the medium, means, and context in
+ which You Share the Licensed Material. For example, it may be
+ reasonable to satisfy the conditions by providing a URI or
+ hyperlink to a resource that includes the required
+ information.
+ 3. If requested by the Licensor, You must remove any of the
+ information required by Section 3(a)(1)(A) to the extent
+ reasonably practicable.
+
+ b. ShareAlike.
+
+ In addition to the conditions in Section 3(a), if You Share
+ Adapted Material You produce, the following conditions also apply.
+
+ 1. The Adapter's License You apply must be a Creative Commons
+ license with the same License Elements, this version or
+ later, or a BY-NC-SA Compatible License.
+
+ 2. You must include the text of, or the URI or hyperlink to, the
+ Adapter's License You apply. You may satisfy this condition
+ in any reasonable manner based on the medium, means, and
+ context in which You Share Adapted Material.
+
+ 3. You may not offer or impose any additional or different terms
+ or conditions on, or apply any Effective Technological
+ Measures to, Adapted Material that restrict exercise of the
+ rights granted under the Adapter's License You apply.
+
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that
+apply to Your use of the Licensed Material:
+
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+ to extract, reuse, reproduce, and Share all or a substantial
+ portion of the contents of the database for NonCommercial purposes
+ only;
+
+ b. if You include all or a substantial portion of the database
+ contents in a database in which You have Sui Generis Database
+ Rights, then the database in which You have Sui Generis Database
+ Rights (but not its individual contents) is Adapted Material,
+ including for purposes of Section 3(b); and
+
+ c. You must comply with the conditions in Section 3(a) if You Share
+ all or a substantial portion of the contents of the database.
+
+For the avoidance of doubt, this Section 4 supplements and does not
+replace Your obligations under this Public License where the Licensed
+Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+
+ c. The disclaimer of warranties and limitation of liability provided
+ above shall be interpreted in a manner that, to the extent
+ possible, most closely approximates an absolute disclaimer and
+ waiver of all liability.
+
+
+Section 6 -- Term and Termination.
+
+ a. This Public License applies for the term of the Copyright and
+ Similar Rights licensed here. However, if You fail to comply with
+ this Public License, then Your rights under this Public License
+ terminate automatically.
+
+ b. Where Your right to use the Licensed Material has terminated under
+ Section 6(a), it reinstates:
+
+ 1. automatically as of the date the violation is cured, provided
+ it is cured within 30 days of Your discovery of the
+ violation; or
+
+ 2. upon express reinstatement by the Licensor.
+
+ For the avoidance of doubt, this Section 6(b) does not affect any
+ right the Licensor may have to seek remedies for Your violations
+ of this Public License.
+
+ c. For the avoidance of doubt, the Licensor may also offer the
+ Licensed Material under separate terms or conditions or stop
+ distributing the Licensed Material at any time; however, doing so
+ will not terminate this Public License.
+
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+ License.
+
+
+Section 7 -- Other Terms and Conditions.
+
+ a. The Licensor shall not be bound by any additional or different
+ terms or conditions communicated by You unless expressly agreed.
+
+ b. Any arrangements, understandings, or agreements regarding the
+ Licensed Material not stated herein are separate from and
+ independent of the terms and conditions of this Public License.
+
+
+Section 8 -- Interpretation.
+
+ a. For the avoidance of doubt, this Public License does not, and
+ shall not be interpreted to, reduce, limit, restrict, or impose
+ conditions on any use of the Licensed Material that could lawfully
+ be made without permission under this Public License.
+
+ b. To the extent possible, if any provision of this Public License is
+ deemed unenforceable, it shall be automatically reformed to the
+ minimum extent necessary to make it enforceable. If the provision
+ cannot be reformed, it shall be severed from this Public License
+ without affecting the enforceability of the remaining terms and
+ conditions.
+
+ c. No term or condition of this Public License will be waived and no
+ failure to comply consented to unless expressly agreed to by the
+ Licensor.
+
+ d. Nothing in this Public License constitutes or may be interpreted
+ as a limitation upon, or waiver of, any privileges and immunities
+ that apply to the Licensor or You, including from the legal
+ processes of any jurisdiction or authority.
+
+=======================================================================
+
+Creative Commons is not a party to its public
+licenses. Notwithstanding, Creative Commons may elect to apply one of
+its public licenses to material it publishes and in those instances
+will be considered the “Licensor.” The text of the Creative Commons
+public licenses is dedicated to the public domain under the CC0 Public
+Domain Dedication. Except for the limited purpose of indicating that
+material is shared under a Creative Commons public license or as
+otherwise permitted by the Creative Commons policies published at
+creativecommons.org/policies, Creative Commons does not authorize the
+use of the trademark "Creative Commons" or any other trademark or logo
+of Creative Commons without its prior written consent including,
+without limitation, in connection with any unauthorized modifications
+to any of its public licenses or any other arrangements,
+understandings, or agreements concerning use of licensed material. For
+the avoidance of doubt, this paragraph does not form part of the
+public licenses.
+
+Creative Commons may be contacted at creativecommons.org.
diff --git a/README.md b/README.md
index ed07541..dfa0405 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,19 @@
-# focus-dial
\ No newline at end of file
+
+
+
+
+Watch the build video ↓
+
+[ ](https://youtu.be/nZa-Vqu-_fU)
+
+Tired of constant distractions, I built the Focus Dial—a DIY take on the failed TimeChi crowdfunding project. It helps me work in time blocks by activating a Do Not Disturb mode on my phone and integrates with Home Assistant via webhook triggers to set lighting scenes and block distracting apps at the network level during focus sessions.
+
+Build instructions → (coming soon)
+
+[![CC BY-NC-SA 4.0][cc-by-nc-sa-shield]][cc-by-nc-sa]
+
+[![CC BY-NC-SA 4.0][cc-by-nc-sa-image]][cc-by-nc-sa]
+
+[cc-by-nc-sa]: http://creativecommons.org/licenses/by-nc-sa/4.0/
+[cc-by-nc-sa-image]: https://licensebuttons.net/l/by-nc-sa/4.0/88x31.png
+[cc-by-nc-sa-shield]: https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg
\ No newline at end of file
diff --git a/cad/Focus Dial.f3z b/cad/Focus Dial.f3z
new file mode 100644
index 0000000..99cde02
Binary files /dev/null and b/cad/Focus Dial.f3z differ
diff --git a/cad/STLs/Bezel.stl b/cad/STLs/Bezel.stl
new file mode 100644
index 0000000..bf79ef0
Binary files /dev/null and b/cad/STLs/Bezel.stl differ
diff --git a/cad/STLs/Bottom Button.stl b/cad/STLs/Bottom Button.stl
new file mode 100644
index 0000000..eba8b2e
Binary files /dev/null and b/cad/STLs/Bottom Button.stl differ
diff --git a/cad/STLs/Bottom.stl b/cad/STLs/Bottom.stl
new file mode 100644
index 0000000..f1a4d88
Binary files /dev/null and b/cad/STLs/Bottom.stl differ
diff --git a/cad/STLs/Button Cap.stl b/cad/STLs/Button Cap.stl
new file mode 100644
index 0000000..1defd51
Binary files /dev/null and b/cad/STLs/Button Cap.stl differ
diff --git a/cad/STLs/Button Holder.stl b/cad/STLs/Button Holder.stl
new file mode 100644
index 0000000..7684d73
Binary files /dev/null and b/cad/STLs/Button Holder.stl differ
diff --git a/cad/STLs/Central Ring.stl b/cad/STLs/Central Ring.stl
new file mode 100644
index 0000000..2a1aaa0
Binary files /dev/null and b/cad/STLs/Central Ring.stl differ
diff --git a/cad/STLs/Central Shaft.stl b/cad/STLs/Central Shaft.stl
new file mode 100644
index 0000000..2e47ab0
Binary files /dev/null and b/cad/STLs/Central Shaft.stl differ
diff --git a/cad/STLs/Diffuser Mold.stl b/cad/STLs/Diffuser Mold.stl
new file mode 100644
index 0000000..9b7dfe2
Binary files /dev/null and b/cad/STLs/Diffuser Mold.stl differ
diff --git a/cad/STLs/Encoder Bottom.stl b/cad/STLs/Encoder Bottom.stl
new file mode 100644
index 0000000..76fc269
Binary files /dev/null and b/cad/STLs/Encoder Bottom.stl differ
diff --git a/cad/STLs/Face.stl b/cad/STLs/Face.stl
new file mode 100644
index 0000000..7e90f90
Binary files /dev/null and b/cad/STLs/Face.stl differ
diff --git a/cad/STLs/Screen Backing.stl b/cad/STLs/Screen Backing.stl
new file mode 100644
index 0000000..40ec2ae
Binary files /dev/null and b/cad/STLs/Screen Backing.stl differ
diff --git a/firmware/include/Animation.h b/firmware/include/Animation.h
new file mode 100644
index 0000000..7129af5
--- /dev/null
+++ b/firmware/include/Animation.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include
+#include
+
+#define DEFAULT_FRAME_WIDTH 48
+#define DEFAULT_FRAME_HEIGHT 48
+#define DEFAULT_FRAME_DELAY 42
+
+class Animation
+{
+public:
+ Animation(Adafruit_SSD1306 *display);
+ void start(const byte *frames, int frameCount, bool loop, bool reverse, unsigned long durationMs, int width, int height); // Moved reverse parameter
+ void update();
+ bool isRunning();
+
+private:
+ Adafruit_SSD1306 *oled;
+ const byte *animationFrames;
+ int totalFrames;
+ int currentFrame;
+ int frameWidth;
+ int frameHeight;
+ int frameX;
+ int frameY;
+ bool animationRunning;
+ bool loopAnimation;
+ bool playInReverse;
+ unsigned long animationStartTime;
+ unsigned long lastFrameTime;
+ unsigned long animationDuration;
+ unsigned long frameDelay;
+};
\ No newline at end of file
diff --git a/firmware/include/Config.h b/firmware/include/Config.h
new file mode 100644
index 0000000..fe0c348
--- /dev/null
+++ b/firmware/include/Config.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include
+
+// --- Hardware ---
+#define OLED_WIDTH 128
+#define OLED_HEIGHT 64
+#define OLED_ADDR 0x3C
+
+#define LED_PIN 15
+#define NUM_LEDS 16
+#define LED_BRIGHTNESS 100
+
+#define ENCODER_A_PIN 27
+#define ENCODER_B_PIN 25
+#define BUTTON_PIN 26
+
+// --- LED Colors ---
+#define BLUE 0x0000FF
+#define AMBER 0xFFBF00
+#define RED 0xFF0000
+#define GREEN 0x00FF00
+#define YELLOW 0xFFFF00
+#define MAGENTA 0xFF00FF
+#define TEAL 0x008080
+
+// --- Defaults ---
+#define DEFAULT_TIMER 25 // min - Default to 25 minutes if no value in NVS
+#define MIN_TIMER 5 // min - Minimum timer
+#define MAX_TIMER 240 // min - Maximum timer (4 hours)
+
+#define SPLASH_DURATION 2 // sec - 2 seconds splash state
+#define CHANGE_TIMEOUT 5 // sec - 5 seconds adjust timeout
+#define SLEEP_TIMOUT 5 // min - 5 minutes to transition to sleep
+#define PAUSE_TIMEOUT 10 // min - 10 minutes to cancel the timer if stayed paused
\ No newline at end of file
diff --git a/firmware/include/Controllers.h b/firmware/include/Controllers.h
new file mode 100644
index 0000000..e4ee0fb
--- /dev/null
+++ b/firmware/include/Controllers.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "controllers/DisplayController.h"
+#include "controllers/LEDController.h"
+#include "controllers/InputController.h"
+#include "controllers/NetworkController.h"
+#include
+
+// Declare global controller instances
+extern DisplayController displayController;
+extern LEDController ledController;
+extern InputController inputController;
+extern NetworkController networkController;
+extern Preferences preferences;
\ No newline at end of file
diff --git a/firmware/include/State.h b/firmware/include/State.h
new file mode 100644
index 0000000..e939d6a
--- /dev/null
+++ b/firmware/include/State.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "Config.h"
+
+// Base class
+class State {
+public:
+ virtual ~State() {}
+
+ virtual void enter() = 0;
+ virtual void update() = 0;
+ virtual void exit() = 0;
+};
\ No newline at end of file
diff --git a/firmware/include/StateMachine.h b/firmware/include/StateMachine.h
new file mode 100644
index 0000000..41a6aea
--- /dev/null
+++ b/firmware/include/StateMachine.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include
+#include "State.h"
+#include "states/AdjustState.h"
+#include "states/DoneState.h"
+#include "states/IdleState.h"
+#include "states/PausedState.h"
+#include "states/ProvisionState.h"
+#include "states/ResetState.h"
+#include "states/SleepState.h"
+#include "states/StartupState.h"
+#include "states/TimerState.h"
+
+class StateMachine {
+public:
+ StateMachine();
+ ~StateMachine();
+
+ void changeState(State* newState);
+ void update();
+
+ // Static states
+ static AdjustState adjustState;
+ static SleepState sleepState;
+ static DoneState doneState;
+ static IdleState idleState;
+ static PausedState pausedState;
+ static ProvisionState provisionState;
+ static ResetState resetState;
+ static StartupState startupState;
+ static TimerState timerState;
+
+private:
+ State* currentState; // Pointer to the current state
+ SemaphoreHandle_t stateMutex; // Mutex to protect transitions
+ bool transition = false;
+};
+
+extern StateMachine stateMachine; // Global instance of the StateMachine
\ No newline at end of file
diff --git a/firmware/include/bitmaps.h b/firmware/include/bitmaps.h
new file mode 100644
index 0000000..29e1a21
--- /dev/null
+++ b/firmware/include/bitmaps.h
@@ -0,0 +1,198 @@
+#pragma once
+
+#include
+
+// --- Bitmap icons and UI elements ---
+
+static const unsigned char PROGMEM icon_wifi_on[] = {0xe0, 0x10, 0xc8, 0x28, 0xa8};
+static const unsigned char PROGMEM icon_wifi_off[] = {0x88, 0x50, 0x20, 0x50, 0x88};
+static const unsigned char PROGMEM icon_star[] = {0x92, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x92};
+static const unsigned char PROGMEM icon_pause[] = {0x3e, 0x00, 0x41, 0x00, 0x80, 0x80, 0x94, 0x80, 0x94, 0x80, 0x94, 0x80, 0x80, 0x80, 0x41, 0x00, 0x3e, 0x00};
+static const unsigned char PROGMEM icon_reset[] = {0x00, 0x00, 0x00, 0x00, 0x04, 0xf8, 0x18, 0xe0, 0x20, 0xe0, 0x40, 0x90, 0x40, 0x90, 0x80, 0x08, 0x80, 0x08, 0x80, 0x08, 0x40, 0x10, 0x40, 0x10, 0x20, 0x20, 0x18, 0xc0, 0x07, 0x00, 0x00, 0x00};
+static const unsigned char PROGMEM icon_arrow_down[] = {0x20, 0x20, 0x20, 0x20, 0xa8, 0x70, 0x20};
+static const unsigned char PROGMEM image_change_left[] = {0x0c, 0x1e, 0x1e, 0x3e, 0x3c, 0x3c, 0x3c, 0x3c, 0x78, 0x78, 0x78, 0x78, 0x78, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf8, 0x78, 0x78, 0x78, 0x78, 0x78, 0x3c, 0x3c, 0x3c, 0x3c, 0x1e, 0x1e, 0x0c};
+static const unsigned char PROGMEM image_change_right[] = {0x60, 0xf0, 0xf0, 0xf8, 0x78, 0x78, 0x78, 0x78, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x3e, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x78, 0x78, 0x78, 0x78, 0xf0, 0xf0, 0x60};
+static const unsigned char PROGMEM provision_logo[] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x40, 0x18, 0x30, 0x00, 0x02, 0x00, 0x40, 0x40, 0x20, 0x08, 0x00, 0x03, 0x00, 0x40, 0xc0, 0x43, 0x84, 0x00, 0x12, 0x80, 0x60, 0x80, 0x8c, 0x62, 0x08, 0x0a, 0x40, 0x20, 0x80, 0x10, 0x10, 0x08, 0x06, 0x80, 0x20, 0x80, 0x21, 0x08, 0x3e, 0x03, 0x00, 0x20, 0x80, 0x06, 0xc0, 0x08, 0x06, 0x80, 0x20, 0x80, 0x08, 0x20, 0x08, 0x0a, 0x40, 0x20, 0x80, 0x01, 0x00, 0x00, 0x12, 0x80, 0x20, 0x40, 0x02, 0x80, 0x00, 0x03, 0x00, 0x40, 0x40, 0x01, 0x00, 0x00, 0x02, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00};
+static const unsigned char PROGMEM focusdial_logo[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xe3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xe3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xe3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xe3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xe3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xe3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x81, 0xf8, 0x1f, 0x8e, 0x38, 0x1f, 0x8f, 0xc0, 0xe0, 0x70, 0x38, 0x00, 0x1f, 0x81, 0xf8, 0x1f, 0x8e, 0x38, 0x1f, 0x8f, 0xc0, 0xe0, 0x70, 0x38, 0x00, 0x1f, 0x81, 0xf8, 0x1f, 0x8e, 0x38, 0x1f, 0x8f, 0xc0, 0xe0, 0x70, 0x38, 0x00, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xff, 0x8e, 0x38, 0xe0, 0x0e, 0x38, 0xff, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xff, 0x8e, 0x38, 0xe0, 0x0e, 0x38, 0xff, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xff, 0x8e, 0x38, 0xe0, 0x0e, 0x38, 0xff, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0x03, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0x03, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xe0, 0x0e, 0x38, 0xe0, 0x0e, 0x38, 0x03, 0x8e, 0x38, 0xe3, 0x8e, 0x38, 0x00, 0xe0, 0x0f, 0xc0, 0x1f, 0x81, 0xc0, 0xfc, 0x0f, 0xc0, 0xe3, 0x8e, 0x3f, 0xe0, 0xe0, 0x0f, 0xc0, 0x1f, 0x81, 0xc0, 0xfc, 0x0f, 0xc0, 0xe3, 0x8e, 0x3f, 0xe0, 0xe0, 0x0f, 0xc0, 0x1f, 0x81, 0xc0, 0xfc, 0x0f, 0xc0, 0xe3, 0x8e, 0x3f, 0xe0};
+
+// --- Animation frames ---
+
+static const byte PROGMEM animation_tick[][288] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 4, 0, 0, 0, 48, 28, 6, 0, 0, 0, 48, 28, 6, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 6, 0, 0, 0, 48, 28, 6, 0, 0, 0, 24, 24, 7, 0, 0, 0, 24, 24, 3, 128, 0, 0, 24, 24, 1, 128, 0, 0, 24, 24, 1, 192, 0, 0, 24, 24, 0, 192, 0, 0, 24, 24, 0, 64, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 6, 0, 0, 0, 24, 24, 6, 0, 0, 0, 24, 24, 7, 0, 0, 0, 24, 24, 3, 128, 0, 0, 24, 24, 1, 192, 0, 0, 24, 24, 0, 224, 0, 0, 24, 24, 0, 99, 0, 0, 24, 24, 0, 119, 0, 0, 24, 24, 0, 62, 0, 0, 24, 24, 0, 28, 0, 0, 56, 12, 0, 8, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 2, 0, 0, 0, 24, 24, 7, 0, 48, 0, 24, 24, 3, 128, 112, 0, 24, 24, 1, 192, 112, 0, 24, 24, 0, 224, 224, 0, 24, 24, 0, 225, 192, 0, 24, 24, 0, 115, 128, 0, 24, 24, 0, 63, 0, 0, 24, 24, 0, 30, 0, 0, 56, 12, 0, 14, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 7, 0, 48, 28, 0, 0, 14, 0, 24, 24, 0, 0, 12, 0, 24, 24, 2, 0, 28, 0, 24, 24, 3, 0, 56, 0, 24, 24, 3, 128, 112, 0, 24, 24, 1, 192, 112, 0, 24, 24, 0, 224, 224, 0, 24, 24, 0, 113, 192, 0, 24, 24, 0, 59, 128, 0, 24, 24, 0, 31, 128, 0, 56, 12, 0, 15, 0, 0, 56, 12, 0, 6, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 1, 128, 112, 12, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 0, 28, 0, 24, 24, 3, 128, 56, 0, 24, 24, 1, 192, 112, 0, 24, 24, 0, 224, 96, 0, 24, 24, 0, 112, 224, 0, 24, 24, 0, 57, 192, 0, 24, 24, 0, 31, 128, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 0, 0, 48, 14, 0, 2, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 192, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 128, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 14, 0, 24, 24, 1, 0, 28, 0, 24, 24, 3, 128, 56, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 224, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 3, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 1, 128, 28, 0, 24, 24, 1, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 192, 56, 0, 24, 24, 0, 224, 112, 0, 24, 24, 0, 112, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 0, 56, 0, 24, 24, 0, 32, 112, 0, 24, 24, 0, 48, 96, 0, 24, 24, 0, 56, 224, 0, 24, 24, 0, 29, 192, 0, 56, 12, 0, 15, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 0, 56, 0, 24, 24, 0, 0, 112, 0, 24, 24, 0, 0, 96, 0, 24, 24, 0, 0, 224, 0, 24, 24, 0, 5, 192, 0, 56, 12, 0, 7, 128, 0, 56, 12, 0, 7, 128, 0, 48, 14, 0, 3, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 14, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 0, 28, 0, 24, 24, 0, 0, 56, 0, 24, 24, 0, 0, 112, 0, 24, 24, 0, 0, 96, 0, 24, 24, 0, 0, 96, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 1, 192, 112, 12, 0, 0, 1, 192, 48, 28, 0, 0, 3, 128, 48, 28, 0, 0, 7, 0, 24, 24, 0, 0, 7, 0, 24, 24, 0, 0, 6, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 224, 96, 14, 0, 0, 0, 192, 112, 12, 0, 0, 0, 128, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 224, 0, 0, 15, 128, 1, 240, 0, 0, 28, 0, 0, 120, 0, 0, 56, 0, 0, 30, 0, 0, 240, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 48, 28, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 56, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 15, 0, 0, 120, 0, 0, 28, 0, 0, 30, 0, 0, 56, 0, 0, 15, 128, 1, 240, 0, 0, 7, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+static const byte PROGMEM animation_reset[][288] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 7, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 0, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 204, 3, 56, 0, 0, 0, 220, 7, 24, 0, 0, 14, 252, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 240, 12, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 15, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 0, 120, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 4, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 7, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 0, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 204, 3, 56, 0, 0, 0, 220, 7, 24, 0, 0, 14, 252, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 240, 12, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 15, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 0, 120, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 4, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 7, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 0, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 204, 3, 56, 0, 0, 0, 220, 7, 24, 0, 0, 14, 252, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 240, 12, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 15, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 0, 120, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 4, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 7, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 0, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 204, 3, 56, 0, 0, 0, 220, 7, 24, 0, 0, 14, 252, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 240, 12, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 15, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 0, 120, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 4, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 4, 0, 0, 120, 0, 0, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 15, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 132, 3, 176, 0, 0, 1, 220, 3, 48, 0, 0, 0, 220, 7, 16, 0, 0, 14, 248, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 240, 14, 0, 0, 0, 0, 240, 12, 0, 0, 0, 0, 32, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 16, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 7, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 2, 60, 7, 192, 0, 0, 0, 63, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 6, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 240, 15, 192, 0, 0, 15, 128, 1, 240, 0, 0, 6, 0, 0, 120, 0, 0, 0, 0, 0, 60, 0, 15, 224, 0, 0, 14, 0, 15, 224, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 152, 3, 176, 0, 0, 1, 216, 3, 48, 0, 0, 0, 248, 7, 48, 0, 0, 15, 248, 6, 0, 0, 0, 15, 240, 14, 0, 0, 0, 3, 240, 14, 0, 0, 0, 0, 96, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 1, 128, 28, 0, 0, 30, 7, 128, 120, 0, 0, 15, 15, 1, 240, 0, 0, 3, 28, 7, 192, 0, 0, 0, 31, 255, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 2, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 240, 15, 192, 0, 0, 15, 128, 1, 240, 0, 0, 14, 0, 0, 120, 0, 0, 0, 0, 0, 60, 0, 3, 224, 0, 0, 14, 0, 15, 224, 0, 0, 7, 0, 15, 224, 0, 0, 3, 128, 1, 224, 0, 0, 1, 152, 3, 176, 0, 0, 1, 248, 7, 48, 0, 0, 0, 248, 7, 48, 0, 0, 15, 240, 6, 32, 0, 0, 15, 240, 6, 0, 0, 0, 1, 224, 14, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 16, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 1, 128, 28, 0, 0, 30, 3, 128, 120, 0, 0, 15, 135, 1, 240, 0, 0, 3, 158, 15, 192, 0, 0, 0, 31, 255, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 240, 15, 192, 0, 0, 15, 128, 1, 240, 0, 0, 6, 0, 0, 120, 0, 0, 0, 0, 0, 60, 0, 7, 224, 0, 0, 14, 0, 15, 224, 0, 0, 7, 0, 13, 224, 0, 0, 3, 128, 1, 240, 0, 0, 1, 152, 3, 176, 0, 0, 1, 216, 3, 48, 0, 0, 0, 248, 7, 48, 0, 0, 15, 240, 6, 0, 0, 0, 15, 240, 14, 0, 0, 0, 1, 240, 14, 0, 0, 0, 0, 96, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 1, 128, 28, 0, 0, 30, 3, 128, 120, 0, 0, 15, 15, 1, 240, 0, 0, 3, 158, 15, 192, 0, 0, 0, 31, 255, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 4, 0, 0, 120, 0, 0, 112, 0, 0, 60, 0, 7, 240, 0, 0, 14, 0, 7, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 220, 3, 48, 0, 0, 0, 216, 7, 48, 0, 0, 14, 248, 6, 0, 0, 0, 7, 248, 14, 0, 0, 0, 3, 240, 14, 0, 0, 0, 0, 240, 12, 0, 0, 0, 0, 32, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 1, 0, 28, 0, 0, 30, 7, 128, 120, 0, 0, 14, 15, 1, 240, 0, 0, 2, 60, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 1, 0, 1, 240, 0, 0, 24, 0, 0, 120, 0, 3, 248, 0, 0, 28, 0, 7, 248, 0, 0, 14, 0, 0, 248, 0, 0, 7, 0, 1, 248, 0, 0, 3, 0, 1, 184, 0, 0, 1, 128, 3, 176, 0, 0, 1, 192, 3, 16, 0, 0, 0, 204, 7, 0, 0, 0, 2, 124, 6, 0, 0, 0, 7, 124, 6, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 248, 12, 0, 0, 0, 0, 240, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 1, 128, 0, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 7, 0, 120, 0, 0, 12, 62, 0, 224, 0, 0, 0, 248, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 127, 248, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 255, 255, 128, 0, 0, 0, 240, 15, 192, 0, 0, 126, 0, 1, 240, 0, 1, 254, 0, 0, 120, 0, 1, 252, 0, 0, 60, 0, 0, 124, 0, 0, 14, 0, 0, 252, 0, 0, 7, 0, 1, 220, 0, 0, 3, 128, 1, 216, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 100, 6, 0, 0, 0, 3, 110, 14, 0, 0, 0, 3, 252, 12, 0, 0, 0, 1, 252, 12, 0, 0, 0, 0, 248, 12, 0, 0, 0, 0, 120, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 24, 60, 0, 120, 0, 0, 3, 252, 1, 240, 0, 0, 3, 240, 15, 192, 0, 0, 1, 255, 255, 0, 0, 0, 0, 255, 248, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 31, 255, 0, 0, 0, 127, 128, 15, 192, 0, 0, 127, 128, 1, 240, 0, 0, 31, 0, 0, 120, 0, 0, 63, 0, 0, 28, 0, 0, 119, 0, 0, 14, 0, 0, 230, 0, 0, 7, 0, 1, 198, 0, 0, 3, 0, 1, 128, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 3, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 48, 12, 0, 0, 0, 3, 54, 12, 0, 0, 0, 3, 190, 12, 0, 0, 0, 1, 252, 12, 0, 0, 0, 0, 252, 12, 0, 0, 0, 0, 120, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 16, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 96, 0, 0, 14, 0, 0, 0, 240, 0, 28, 0, 0, 15, 248, 0, 120, 0, 0, 7, 128, 1, 224, 0, 0, 7, 240, 7, 192, 0, 0, 3, 255, 255, 0, 0, 0, 1, 191, 248, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 7, 248, 0, 0, 0, 31, 231, 255, 128, 0, 0, 3, 224, 15, 192, 0, 0, 15, 224, 1, 240, 0, 0, 31, 192, 0, 120, 0, 0, 57, 128, 0, 60, 0, 0, 115, 128, 0, 14, 0, 0, 225, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 1, 192, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 7, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 3, 176, 12, 0, 0, 0, 1, 182, 12, 0, 0, 0, 1, 254, 12, 0, 0, 0, 0, 254, 12, 0, 0, 0, 0, 124, 12, 0, 0, 0, 0, 120, 14, 0, 0, 0, 0, 48, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 192, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 128, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 63, 192, 0, 14, 0, 0, 63, 192, 0, 28, 0, 0, 30, 128, 0, 120, 0, 0, 31, 128, 1, 240, 0, 0, 15, 240, 15, 192, 0, 0, 13, 255, 255, 0, 0, 0, 6, 31, 248, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 3, 224, 0, 0, 0, 0, 1, 252, 248, 0, 0, 0, 0, 252, 255, 0, 0, 0, 3, 248, 15, 192, 0, 0, 7, 120, 1, 240, 0, 0, 30, 112, 0, 120, 0, 0, 56, 224, 0, 28, 0, 0, 112, 64, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 0, 1, 128, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 3, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 1, 48, 12, 0, 0, 0, 1, 176, 12, 0, 0, 0, 1, 178, 12, 0, 0, 0, 1, 254, 12, 0, 0, 0, 0, 254, 6, 0, 0, 0, 0, 248, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 3, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 0, 240, 0, 0, 3, 128, 0, 255, 0, 0, 7, 0, 0, 127, 0, 0, 14, 0, 0, 120, 0, 0, 28, 0, 0, 126, 0, 0, 120, 0, 0, 63, 128, 0, 224, 0, 0, 51, 240, 7, 192, 0, 0, 48, 255, 255, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 31, 140, 0, 0, 0, 0, 255, 159, 0, 0, 0, 3, 239, 15, 192, 0, 0, 15, 142, 1, 240, 0, 0, 30, 28, 0, 120, 0, 0, 56, 24, 0, 60, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 1, 192, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 3, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 3, 48, 12, 0, 0, 0, 3, 112, 6, 0, 0, 0, 3, 240, 4, 0, 0, 0, 1, 236, 0, 0, 0, 0, 1, 252, 3, 0, 0, 0, 1, 248, 3, 224, 0, 0, 1, 224, 1, 248, 0, 0, 0, 128, 1, 252, 0, 0, 0, 0, 1, 232, 0, 0, 6, 0, 1, 240, 0, 0, 14, 0, 1, 188, 0, 0, 28, 0, 1, 158, 0, 0, 120, 0, 0, 15, 128, 1, 240, 0, 0, 3, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 224, 0, 0, 0, 0, 31, 240, 0, 0, 0, 0, 255, 249, 0, 0, 0, 3, 241, 227, 192, 0, 0, 15, 131, 193, 240, 0, 0, 30, 3, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 1, 192, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 3, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 112, 6, 0, 0, 0, 6, 96, 7, 0, 0, 0, 6, 96, 7, 192, 0, 0, 6, 224, 7, 240, 0, 0, 6, 192, 7, 240, 0, 0, 7, 200, 7, 160, 0, 0, 7, 248, 7, 192, 0, 0, 7, 240, 6, 224, 0, 0, 3, 128, 4, 112, 0, 0, 0, 0, 0, 56, 0, 0, 16, 0, 0, 30, 0, 0, 120, 0, 0, 15, 128, 1, 240, 0, 0, 3, 240, 15, 192, 0, 0, 1, 255, 255, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 254, 0, 0, 0, 3, 224, 31, 0, 0, 0, 7, 0, 252, 112, 0, 0, 30, 0, 96, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 0, 1, 128, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 3, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 48, 15, 0, 0, 0, 0, 112, 15, 192, 0, 0, 0, 112, 31, 224, 0, 0, 0, 96, 30, 224, 0, 0, 4, 224, 27, 0, 0, 0, 12, 192, 27, 128, 0, 0, 13, 192, 1, 128, 0, 0, 13, 128, 0, 192, 0, 0, 31, 128, 0, 224, 0, 0, 31, 0, 0, 112, 0, 0, 31, 224, 0, 56, 0, 0, 31, 192, 0, 30, 0, 0, 24, 0, 0, 15, 128, 1, 192, 0, 0, 3, 240, 7, 192, 0, 0, 0, 255, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 31, 255, 128, 0, 0, 0, 255, 255, 128, 0, 0, 3, 224, 15, 192, 0, 0, 15, 128, 7, 224, 0, 0, 30, 0, 31, 128, 0, 0, 56, 0, 24, 12, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 1, 192, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 3, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 48, 31, 0, 0, 0, 0, 48, 31, 0, 0, 0, 0, 48, 63, 128, 0, 0, 0, 48, 61, 192, 0, 0, 0, 112, 54, 192, 0, 0, 0, 112, 38, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 51, 128, 1, 192, 0, 0, 51, 128, 0, 224, 0, 0, 55, 0, 0, 112, 0, 0, 126, 0, 0, 60, 0, 0, 124, 0, 0, 30, 0, 0, 127, 0, 0, 15, 128, 0, 255, 0, 0, 3, 240, 14, 30, 0, 0, 0, 255, 254, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 31, 248, 96, 0, 0, 0, 255, 255, 96, 0, 0, 3, 240, 15, 240, 0, 0, 15, 128, 1, 240, 0, 0, 30, 0, 1, 248, 0, 0, 56, 0, 7, 248, 0, 0, 112, 0, 3, 0, 0, 0, 224, 0, 0, 3, 0, 1, 192, 0, 0, 3, 128, 1, 128, 0, 0, 1, 128, 3, 128, 0, 0, 1, 192, 3, 0, 0, 0, 0, 192, 7, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 96, 4, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 48, 30, 0, 0, 0, 0, 48, 63, 0, 0, 0, 0, 48, 63, 0, 0, 0, 0, 48, 125, 128, 0, 0, 0, 48, 109, 128, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 1, 128, 1, 192, 0, 0, 67, 128, 0, 224, 0, 0, 231, 0, 0, 112, 0, 0, 206, 0, 0, 56, 0, 1, 220, 0, 0, 30, 0, 1, 248, 0, 0, 15, 128, 3, 240, 0, 0, 3, 240, 3, 240, 0, 0, 0, 255, 243, 248, 0, 0, 0, 31, 240, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 8, 0, 0, 0, 255, 255, 12, 0, 0, 3, 224, 15, 204, 0, 0, 15, 128, 1, 252, 0, 0, 30, 0, 0, 124, 0, 0, 56, 0, 0, 62, 0, 0, 112, 0, 1, 254, 0, 0, 224, 0, 0, 254, 0, 1, 192, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 192, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 224, 6, 0, 0, 0, 0, 96, 14, 0, 0, 0, 0, 96, 30, 0, 0, 0, 0, 48, 63, 0, 0, 0, 0, 48, 127, 0, 0, 0, 0, 48, 125, 128, 0, 0, 0, 48, 77, 128, 0, 0, 0, 48, 13, 128, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 3, 14, 0, 0, 60, 0, 7, 28, 0, 0, 30, 0, 7, 120, 0, 0, 15, 128, 15, 240, 0, 0, 3, 240, 31, 192, 0, 0, 0, 255, 159, 0, 0, 0, 0, 63, 159, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 248, 0, 0, 0, 0, 255, 255, 128, 0, 0, 3, 240, 15, 193, 0, 0, 15, 128, 1, 243, 0, 0, 30, 0, 0, 123, 0, 0, 56, 0, 0, 63, 0, 0, 112, 0, 0, 15, 0, 0, 224, 0, 0, 127, 128, 0, 192, 0, 0, 63, 128, 0, 0, 0, 0, 31, 128, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 96, 31, 0, 0, 0, 0, 96, 63, 128, 0, 0, 0, 96, 127, 128, 0, 0, 0, 112, 13, 128, 0, 0, 0, 48, 13, 128, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 224, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 4, 14, 0, 0, 60, 0, 12, 28, 0, 0, 30, 0, 28, 120, 0, 0, 15, 128, 57, 240, 0, 0, 3, 240, 127, 192, 0, 0, 0, 252, 255, 0, 0, 0, 0, 28, 248, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 15, 128, 1, 240, 0, 0, 30, 0, 0, 120, 64, 0, 56, 0, 0, 60, 192, 0, 48, 0, 0, 14, 192, 0, 0, 0, 0, 7, 192, 0, 128, 0, 0, 11, 192, 3, 128, 0, 0, 31, 192, 7, 128, 0, 0, 31, 192, 31, 128, 0, 0, 3, 192, 63, 128, 0, 0, 0, 128, 55, 192, 0, 0, 0, 0, 14, 192, 0, 0, 0, 32, 14, 192, 0, 0, 0, 48, 12, 128, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 0, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 0, 16, 28, 0, 0, 30, 0, 120, 120, 0, 0, 15, 128, 241, 240, 0, 0, 3, 225, 199, 192, 0, 0, 0, 243, 255, 0, 0, 0, 0, 3, 248, 0, 0, 0, 0, 1, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 240, 15, 192, 0, 0, 15, 128, 1, 240, 0, 0, 30, 0, 0, 120, 0, 0, 24, 0, 0, 28, 0, 0, 0, 0, 0, 14, 32, 0, 192, 0, 0, 7, 112, 3, 192, 0, 0, 3, 240, 15, 192, 0, 0, 1, 224, 31, 192, 0, 0, 15, 224, 19, 192, 0, 0, 15, 224, 7, 192, 0, 0, 7, 224, 6, 192, 0, 0, 0, 224, 6, 64, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 14, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 1, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 96, 28, 0, 0, 30, 0, 224, 120, 0, 0, 15, 131, 193, 240, 0, 0, 3, 199, 135, 192, 0, 0, 0, 207, 255, 0, 0, 0, 0, 15, 248, 0, 0, 0, 0, 7, 128, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 240, 15, 192, 0, 0, 15, 128, 1, 240, 0, 0, 6, 0, 0, 120, 0, 0, 0, 0, 0, 60, 0, 0, 224, 0, 0, 14, 0, 7, 224, 0, 0, 7, 0, 15, 224, 0, 0, 3, 152, 9, 224, 0, 0, 1, 184, 3, 224, 0, 0, 1, 248, 3, 96, 0, 0, 14, 240, 7, 96, 0, 0, 15, 240, 6, 32, 0, 0, 7, 240, 14, 0, 0, 0, 1, 224, 14, 0, 0, 0, 0, 96, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 0, 128, 28, 0, 0, 30, 3, 192, 120, 0, 0, 15, 7, 1, 240, 0, 0, 3, 158, 7, 192, 0, 0, 0, 31, 255, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 0, 112, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 15, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 136, 3, 176, 0, 0, 1, 220, 3, 48, 0, 0, 0, 220, 7, 48, 0, 0, 14, 248, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 3, 240, 14, 0, 0, 0, 0, 240, 12, 0, 0, 0, 0, 32, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 128, 28, 0, 0, 30, 7, 128, 120, 0, 0, 14, 30, 1, 240, 0, 0, 2, 60, 7, 192, 0, 0, 0, 63, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 6, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 7, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 0, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 204, 3, 56, 0, 0, 0, 220, 7, 24, 0, 0, 14, 252, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 240, 12, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 15, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 0, 120, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 4, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 7, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 0, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 204, 3, 56, 0, 0, 0, 220, 7, 24, 0, 0, 14, 252, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 240, 12, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 15, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 0, 120, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 4, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 15, 192, 0, 0, 7, 128, 1, 240, 0, 0, 0, 0, 0, 120, 0, 7, 240, 0, 0, 60, 0, 15, 240, 0, 0, 14, 0, 0, 240, 0, 0, 7, 0, 1, 240, 0, 0, 3, 128, 1, 240, 0, 0, 1, 128, 3, 176, 0, 0, 1, 204, 3, 56, 0, 0, 0, 220, 7, 24, 0, 0, 14, 252, 6, 0, 0, 0, 15, 248, 14, 0, 0, 0, 7, 248, 14, 0, 0, 0, 1, 240, 12, 0, 0, 0, 0, 112, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 48, 12, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 96, 7, 0, 0, 0, 0, 224, 3, 0, 0, 0, 0, 192, 3, 128, 0, 0, 1, 192, 1, 128, 0, 0, 3, 128, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 60, 3, 0, 28, 0, 0, 30, 15, 0, 120, 0, 0, 14, 30, 1, 240, 0, 0, 0, 120, 7, 192, 0, 0, 0, 127, 255, 0, 0, 0, 0, 63, 248, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 4, 0, 0, 0}};
+
+static const byte PROGMEM animation_cancel[][288] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 48, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 2, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 2, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 6, 0, 0, 0, 0, 56, 4, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 24, 28, 0, 0, 0, 0, 16, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 48, 0, 0, 14, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 128, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 128, 3, 128, 0, 0, 1, 192, 1, 192, 0, 0, 3, 128, 0, 224, 0, 0, 7, 0, 0, 112, 0, 0, 14, 0, 0, 56, 0, 0, 28, 0, 0, 28, 0, 0, 56, 0, 0, 14, 0, 0, 112, 0, 0, 7, 0, 0, 224, 0, 0, 3, 128, 1, 192, 0, 0, 1, 192, 3, 128, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 224, 7, 0, 0, 0, 1, 192, 3, 128, 0, 0, 3, 128, 1, 192, 0, 0, 7, 0, 0, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 0, 0, 56, 0, 0, 56, 0, 0, 28, 0, 0, 112, 0, 0, 14, 0, 0, 224, 0, 0, 7, 0, 1, 192, 0, 0, 3, 128, 3, 128, 0, 0, 1, 192, 1, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+static const byte PROGMEM animation_resume[][288] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 31, 248, 62, 0, 0, 0, 24, 24, 63, 224, 0, 0, 24, 24, 55, 248, 0, 0, 24, 24, 48, 124, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 28, 0, 0, 24, 24, 48, 60, 0, 0, 24, 24, 51, 252, 0, 0, 24, 24, 63, 192, 0, 0, 31, 248, 60, 0, 0, 0, 31, 248, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 31, 192, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 24, 124, 192, 0, 0, 0, 24, 12, 240, 0, 0, 0, 24, 12, 252, 0, 0, 0, 24, 12, 255, 0, 0, 0, 24, 12, 199, 224, 0, 0, 24, 12, 193, 248, 0, 0, 24, 12, 192, 126, 0, 0, 24, 12, 192, 30, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 6, 0, 0, 24, 12, 192, 14, 0, 0, 24, 12, 192, 62, 0, 0, 24, 12, 193, 240, 0, 0, 24, 12, 199, 192, 0, 0, 24, 12, 223, 0, 0, 0, 24, 12, 252, 0, 0, 0, 24, 12, 224, 0, 0, 0, 24, 60, 128, 0, 0, 0, 27, 248, 0, 0, 0, 0, 31, 192, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 63, 128, 0, 0, 0, 0, 55, 224, 0, 0, 0, 0, 49, 248, 0, 0, 0, 0, 48, 63, 0, 0, 0, 0, 48, 15, 128, 0, 0, 0, 48, 7, 224, 0, 0, 0, 48, 7, 248, 0, 0, 0, 48, 7, 190, 0, 0, 0, 48, 7, 143, 128, 0, 0, 48, 7, 131, 224, 0, 0, 48, 7, 1, 248, 0, 0, 48, 7, 0, 124, 0, 0, 48, 7, 0, 31, 0, 0, 48, 7, 0, 7, 0, 0, 48, 7, 0, 3, 0, 0, 48, 7, 0, 3, 0, 0, 48, 7, 0, 3, 0, 0, 48, 7, 0, 3, 0, 0, 48, 7, 0, 3, 0, 0, 48, 7, 0, 15, 0, 0, 48, 7, 0, 60, 0, 0, 48, 15, 0, 240, 0, 0, 48, 15, 3, 192, 0, 0, 48, 15, 15, 128, 0, 0, 48, 15, 62, 0, 0, 0, 48, 15, 248, 0, 0, 0, 48, 15, 224, 0, 0, 0, 48, 15, 128, 0, 0, 0, 48, 62, 0, 0, 0, 0, 48, 248, 0, 0, 0, 0, 51, 224, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 55, 192, 0, 0, 0, 0, 49, 240, 0, 0, 0, 0, 48, 124, 0, 0, 0, 0, 48, 62, 0, 0, 0, 0, 48, 15, 128, 0, 0, 0, 48, 7, 224, 0, 0, 0, 48, 7, 248, 0, 0, 0, 48, 7, 124, 0, 0, 0, 48, 7, 31, 0, 0, 0, 48, 7, 7, 192, 0, 0, 48, 7, 1, 224, 0, 0, 48, 7, 0, 248, 0, 0, 48, 7, 0, 62, 0, 0, 48, 7, 0, 15, 128, 0, 48, 7, 0, 7, 128, 0, 48, 7, 0, 3, 128, 0, 48, 7, 0, 15, 0, 0, 48, 7, 0, 30, 0, 0, 48, 7, 0, 120, 0, 0, 48, 7, 1, 224, 0, 0, 48, 7, 7, 128, 0, 0, 48, 7, 15, 0, 0, 0, 48, 7, 60, 0, 0, 0, 48, 7, 240, 0, 0, 0, 48, 7, 224, 0, 0, 0, 48, 7, 128, 0, 0, 0, 48, 30, 0, 0, 0, 0, 48, 120, 0, 0, 0, 0, 49, 240, 0, 0, 0, 0, 55, 192, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 124, 0, 0, 0, 112, 7, 62, 0, 0, 0, 112, 7, 15, 128, 0, 0, 112, 7, 3, 224, 0, 0, 112, 7, 0, 240, 0, 0, 112, 7, 0, 124, 0, 0, 112, 6, 0, 31, 0, 0, 112, 2, 0, 7, 128, 0, 112, 6, 0, 7, 128, 0, 112, 6, 0, 31, 0, 0, 112, 6, 0, 60, 0, 0, 112, 6, 0, 240, 0, 0, 112, 6, 3, 192, 0, 0, 112, 6, 7, 128, 0, 0, 112, 6, 30, 0, 0, 0, 112, 6, 120, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 124, 0, 0, 0, 112, 7, 62, 0, 0, 0, 112, 7, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 2, 3, 192, 0, 0, 112, 6, 7, 128, 0, 0, 112, 6, 30, 0, 0, 0, 112, 6, 120, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 1, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 56, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 30, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 62, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 30, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 3, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 120, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 60, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 62, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 30, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 3, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 120, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 60, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 62, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 30, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 3, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 120, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 60, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 62, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 30, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 3, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 120, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 60, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 62, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 30, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 3, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 120, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 60, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 62, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 30, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 3, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 120, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 60, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 0, 124, 0, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 1, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 0, 30, 0, 0, 0, 112, 0, 56, 0, 0, 0, 112, 1, 240, 0, 0, 0, 112, 3, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 30, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 124, 0, 0, 0, 112, 3, 62, 0, 0, 0, 112, 0, 15, 128, 0, 0, 112, 0, 3, 224, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 60, 0, 0, 112, 0, 0, 240, 0, 0, 112, 0, 3, 192, 0, 0, 112, 0, 7, 128, 0, 0, 112, 2, 30, 0, 0, 0, 112, 6, 120, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 124, 0, 0, 0, 112, 7, 62, 0, 0, 0, 112, 7, 15, 128, 0, 0, 112, 7, 3, 224, 0, 0, 112, 3, 0, 240, 0, 0, 112, 0, 0, 124, 0, 0, 112, 0, 0, 31, 0, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 7, 128, 0, 112, 0, 0, 31, 0, 0, 112, 2, 0, 60, 0, 0, 112, 6, 0, 240, 0, 0, 112, 6, 3, 192, 0, 0, 112, 6, 7, 128, 0, 0, 112, 6, 30, 0, 0, 0, 112, 6, 120, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 119, 192, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 112, 248, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 15, 128, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 124, 0, 0, 0, 112, 7, 62, 0, 0, 0, 112, 7, 15, 128, 0, 0, 112, 7, 3, 224, 0, 0, 112, 7, 0, 240, 0, 0, 112, 7, 0, 124, 0, 0, 112, 6, 0, 31, 0, 0, 112, 6, 0, 7, 128, 0, 112, 6, 0, 7, 128, 0, 112, 6, 0, 31, 0, 0, 112, 6, 0, 60, 0, 0, 112, 6, 0, 240, 0, 0, 112, 6, 3, 192, 0, 0, 112, 6, 7, 128, 0, 0, 112, 6, 30, 0, 0, 0, 112, 6, 120, 0, 0, 0, 112, 7, 240, 0, 0, 0, 112, 7, 192, 0, 0, 0, 112, 15, 0, 0, 0, 0, 112, 62, 0, 0, 0, 0, 112, 120, 0, 0, 0, 0, 113, 224, 0, 0, 0, 0, 119, 128, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 55, 192, 0, 0, 0, 0, 49, 240, 0, 0, 0, 0, 48, 124, 0, 0, 0, 0, 48, 30, 0, 0, 0, 0, 48, 7, 128, 0, 0, 0, 48, 7, 224, 0, 0, 0, 48, 7, 248, 0, 0, 0, 48, 7, 124, 0, 0, 0, 48, 7, 31, 0, 0, 0, 48, 7, 7, 192, 0, 0, 48, 7, 1, 224, 0, 0, 48, 7, 0, 248, 0, 0, 48, 7, 0, 62, 0, 0, 48, 7, 0, 15, 0, 0, 48, 7, 0, 7, 128, 0, 48, 7, 0, 3, 128, 0, 48, 7, 0, 15, 0, 0, 48, 7, 0, 62, 0, 0, 48, 7, 0, 120, 0, 0, 48, 7, 1, 224, 0, 0, 48, 7, 7, 128, 0, 0, 48, 7, 15, 0, 0, 0, 48, 7, 60, 0, 0, 0, 48, 7, 240, 0, 0, 0, 48, 7, 192, 0, 0, 0, 48, 7, 128, 0, 0, 0, 48, 30, 0, 0, 0, 0, 48, 124, 0, 0, 0, 0, 49, 240, 0, 0, 0, 0, 55, 192, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 63, 128, 0, 0, 0, 0, 55, 224, 0, 0, 0, 0, 49, 252, 0, 0, 0, 0, 48, 62, 0, 0, 0, 0, 48, 15, 128, 0, 0, 0, 48, 15, 224, 0, 0, 0, 48, 15, 248, 0, 0, 0, 48, 15, 62, 0, 0, 0, 48, 15, 31, 128, 0, 0, 48, 15, 7, 192, 0, 0, 48, 15, 1, 240, 0, 0, 48, 15, 0, 124, 0, 0, 48, 15, 0, 31, 0, 0, 48, 15, 0, 7, 0, 0, 48, 15, 0, 3, 0, 0, 48, 15, 0, 3, 0, 0, 48, 15, 0, 3, 0, 0, 48, 15, 0, 3, 0, 0, 48, 15, 0, 7, 0, 0, 48, 15, 0, 31, 0, 0, 48, 15, 0, 124, 0, 0, 48, 15, 0, 240, 0, 0, 48, 15, 3, 192, 0, 0, 48, 15, 15, 0, 0, 0, 48, 15, 60, 0, 0, 0, 48, 15, 248, 0, 0, 0, 48, 15, 224, 0, 0, 0, 48, 15, 128, 0, 0, 0, 48, 62, 0, 0, 0, 0, 48, 248, 0, 0, 0, 0, 51, 224, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 31, 192, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 24, 253, 128, 0, 0, 0, 24, 13, 224, 0, 0, 0, 24, 13, 248, 0, 0, 0, 24, 13, 254, 0, 0, 0, 24, 13, 207, 192, 0, 0, 24, 13, 195, 240, 0, 0, 24, 13, 192, 252, 0, 0, 24, 13, 192, 62, 0, 0, 24, 13, 192, 14, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 6, 0, 0, 24, 13, 192, 30, 0, 0, 24, 13, 192, 120, 0, 0, 24, 13, 195, 224, 0, 0, 24, 13, 207, 128, 0, 0, 24, 13, 254, 0, 0, 0, 24, 13, 248, 0, 0, 0, 24, 13, 224, 0, 0, 0, 24, 124, 0, 0, 0, 0, 27, 248, 0, 0, 0, 0, 31, 128, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 31, 252, 120, 0, 0, 0, 24, 28, 127, 128, 0, 0, 24, 28, 127, 240, 0, 0, 24, 28, 97, 252, 0, 0, 24, 28, 96, 28, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 12, 0, 0, 24, 28, 96, 28, 0, 0, 24, 28, 96, 252, 0, 0, 24, 28, 127, 240, 0, 0, 24, 28, 127, 0, 0, 0, 31, 252, 112, 0, 0, 0, 31, 248, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 28, 24, 24, 56, 0, 0, 31, 248, 31, 248, 0, 0, 31, 248, 31, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+static const byte PROGMEM animation_timer_start[][288] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 3, 224, 15, 255, 255, 240, 0, 240, 31, 255, 255, 224, 0, 56, 63, 255, 255, 192, 0, 28, 63, 255, 255, 128, 0, 12, 127, 255, 255, 128, 0, 14, 127, 255, 255, 0, 0, 6, 255, 255, 255, 0, 0, 7, 255, 255, 255, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 6, 127, 255, 255, 128, 0, 14, 63, 255, 255, 128, 0, 12, 63, 255, 255, 192, 0, 28, 31, 255, 255, 224, 0, 56, 15, 255, 255, 248, 0, 112, 7, 255, 255, 254, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 3, 224, 15, 255, 255, 240, 0, 240, 31, 255, 255, 224, 0, 56, 63, 255, 255, 192, 0, 28, 63, 255, 255, 128, 0, 12, 127, 255, 255, 128, 0, 14, 127, 255, 255, 0, 0, 6, 255, 255, 255, 0, 0, 7, 255, 255, 255, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 6, 127, 255, 255, 128, 0, 14, 63, 255, 255, 128, 0, 12, 63, 255, 255, 192, 0, 28, 31, 255, 255, 224, 0, 56, 15, 255, 255, 248, 0, 112, 7, 255, 255, 254, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 3, 224, 15, 255, 255, 240, 0, 240, 31, 255, 255, 224, 0, 56, 63, 255, 255, 192, 0, 28, 63, 255, 255, 128, 0, 12, 127, 255, 255, 128, 0, 14, 127, 255, 255, 0, 0, 6, 255, 255, 255, 0, 0, 7, 255, 255, 255, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 6, 127, 255, 255, 128, 0, 14, 63, 255, 255, 128, 0, 12, 63, 255, 255, 192, 0, 28, 31, 255, 255, 224, 0, 56, 15, 255, 255, 248, 0, 112, 7, 255, 255, 254, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 3, 224, 15, 255, 255, 240, 0, 240, 31, 255, 255, 224, 0, 56, 63, 255, 255, 192, 0, 28, 63, 255, 255, 128, 0, 12, 127, 255, 255, 128, 0, 14, 127, 255, 255, 0, 0, 6, 255, 255, 255, 0, 0, 7, 255, 255, 255, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 6, 127, 255, 255, 128, 0, 14, 63, 255, 255, 128, 0, 12, 63, 255, 255, 192, 0, 28, 31, 255, 255, 224, 0, 56, 15, 255, 255, 248, 0, 112, 7, 255, 255, 254, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 240, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 254, 3, 224, 15, 255, 255, 248, 0, 240, 31, 255, 255, 240, 0, 56, 63, 255, 255, 224, 0, 28, 63, 255, 255, 224, 0, 12, 127, 255, 255, 192, 0, 14, 127, 255, 255, 192, 0, 6, 255, 255, 255, 128, 0, 6, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 7, 127, 255, 255, 128, 0, 7, 127, 255, 255, 192, 0, 6, 127, 255, 255, 192, 0, 14, 63, 255, 255, 224, 0, 12, 63, 255, 255, 224, 0, 28, 31, 255, 255, 240, 0, 56, 15, 255, 255, 252, 0, 112, 7, 255, 255, 255, 1, 224, 3, 255, 255, 255, 255, 192, 0, 255, 255, 255, 255, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 232, 0, 0, 127, 255, 255, 255, 128, 1, 255, 255, 255, 255, 192, 7, 255, 255, 255, 3, 224, 15, 255, 255, 254, 0, 240, 31, 255, 255, 252, 0, 56, 63, 255, 255, 248, 0, 28, 63, 255, 255, 240, 0, 12, 127, 255, 255, 240, 0, 14, 127, 255, 255, 224, 0, 6, 255, 255, 255, 224, 0, 6, 255, 255, 255, 224, 0, 3, 255, 255, 255, 224, 0, 3, 255, 255, 255, 192, 0, 3, 255, 255, 255, 192, 0, 3, 255, 255, 255, 192, 0, 3, 255, 255, 255, 224, 0, 7, 127, 255, 255, 224, 0, 7, 127, 255, 255, 224, 0, 6, 127, 255, 255, 240, 0, 14, 63, 255, 255, 240, 0, 12, 63, 255, 255, 248, 0, 28, 31, 255, 255, 252, 0, 56, 15, 255, 255, 254, 0, 112, 7, 255, 255, 255, 129, 224, 3, 255, 255, 255, 255, 192, 0, 255, 255, 255, 255, 0, 0, 7, 255, 255, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 240, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 255, 3, 224, 15, 255, 255, 252, 0, 240, 31, 255, 255, 248, 0, 56, 63, 255, 255, 240, 0, 28, 63, 255, 255, 240, 0, 28, 127, 255, 255, 224, 0, 14, 127, 255, 255, 224, 0, 14, 255, 255, 255, 192, 0, 6, 255, 255, 255, 192, 0, 7, 255, 255, 255, 192, 0, 7, 255, 255, 255, 192, 0, 7, 255, 255, 255, 192, 0, 7, 255, 255, 255, 192, 0, 7, 255, 255, 255, 192, 0, 7, 127, 255, 255, 192, 0, 7, 127, 255, 255, 192, 0, 14, 127, 255, 255, 224, 0, 14, 63, 255, 255, 224, 0, 28, 63, 255, 255, 240, 0, 28, 31, 255, 255, 248, 0, 56, 15, 255, 255, 252, 0, 112, 7, 255, 255, 255, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 255, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 248, 15, 224, 15, 255, 255, 224, 7, 240, 31, 255, 255, 192, 1, 184, 63, 255, 255, 128, 0, 220, 63, 255, 255, 0, 0, 204, 127, 255, 255, 0, 0, 110, 127, 255, 254, 0, 0, 102, 255, 255, 254, 0, 0, 38, 255, 255, 254, 0, 0, 51, 255, 255, 254, 0, 0, 51, 255, 255, 254, 0, 0, 51, 255, 255, 252, 0, 0, 51, 255, 255, 254, 0, 0, 51, 255, 255, 254, 0, 0, 55, 127, 255, 254, 0, 0, 103, 127, 255, 254, 0, 0, 102, 127, 255, 255, 0, 0, 110, 63, 255, 255, 0, 0, 204, 63, 255, 255, 128, 1, 220, 31, 255, 255, 192, 1, 184, 15, 255, 255, 224, 3, 240, 7, 255, 255, 248, 15, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 254, 3, 192, 3, 224, 15, 252, 0, 224, 0, 240, 31, 248, 0, 112, 0, 56, 63, 240, 0, 56, 0, 28, 63, 224, 0, 24, 0, 12, 127, 224, 0, 24, 0, 14, 127, 192, 0, 12, 0, 6, 255, 192, 0, 12, 0, 6, 255, 192, 0, 12, 0, 3, 255, 128, 0, 4, 0, 3, 255, 128, 0, 6, 0, 3, 255, 128, 0, 6, 0, 3, 255, 128, 0, 12, 0, 3, 255, 128, 0, 12, 0, 7, 127, 192, 0, 12, 0, 7, 127, 192, 0, 12, 0, 6, 127, 192, 0, 28, 0, 14, 63, 224, 0, 24, 0, 12, 63, 240, 0, 56, 0, 28, 31, 248, 0, 112, 0, 56, 15, 252, 0, 224, 0, 112, 7, 255, 1, 192, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 192, 60, 0, 3, 224, 15, 128, 30, 0, 0, 240, 31, 0, 6, 0, 0, 56, 62, 0, 3, 0, 0, 28, 60, 0, 3, 0, 0, 12, 124, 0, 1, 128, 0, 14, 120, 0, 1, 128, 0, 6, 248, 0, 0, 128, 0, 6, 248, 0, 0, 128, 0, 3, 248, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 3, 240, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 7, 120, 0, 1, 128, 0, 7, 120, 0, 1, 128, 0, 6, 124, 0, 3, 128, 0, 14, 60, 0, 3, 0, 0, 12, 62, 0, 7, 0, 0, 28, 31, 0, 6, 0, 0, 56, 15, 128, 14, 0, 0, 112, 7, 224, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 255, 255, 255, 255, 0, 3, 255, 255, 255, 255, 192, 7, 128, 248, 0, 3, 224, 14, 0, 60, 0, 0, 240, 28, 0, 12, 0, 0, 56, 56, 0, 6, 0, 0, 28, 48, 0, 6, 0, 0, 12, 112, 0, 3, 0, 0, 14, 96, 0, 3, 0, 0, 6, 224, 0, 1, 128, 0, 6, 224, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 7, 96, 0, 1, 128, 0, 7, 96, 0, 3, 128, 0, 6, 112, 0, 3, 0, 0, 14, 48, 0, 7, 0, 0, 12, 56, 0, 14, 0, 0, 28, 28, 0, 14, 0, 0, 56, 15, 0, 60, 0, 0, 112, 7, 192, 120, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 15, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 128, 124, 0, 3, 224, 14, 0, 30, 0, 0, 240, 28, 0, 7, 0, 0, 56, 56, 0, 3, 128, 0, 28, 48, 0, 1, 128, 0, 12, 112, 0, 1, 192, 0, 14, 96, 0, 0, 192, 0, 6, 224, 0, 0, 192, 0, 6, 224, 0, 0, 224, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 224, 0, 7, 224, 0, 0, 224, 0, 7, 96, 0, 0, 192, 0, 6, 112, 0, 1, 192, 0, 14, 48, 0, 1, 128, 0, 12, 56, 0, 3, 128, 0, 28, 28, 0, 7, 0, 0, 56, 15, 0, 14, 0, 0, 112, 7, 192, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 128, 124, 0, 3, 224, 14, 0, 30, 0, 0, 240, 28, 0, 7, 0, 0, 56, 56, 0, 3, 128, 0, 28, 48, 0, 1, 128, 0, 12, 112, 0, 1, 192, 0, 14, 96, 0, 0, 192, 0, 6, 224, 0, 0, 192, 0, 6, 224, 0, 0, 224, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 224, 0, 7, 224, 0, 0, 224, 0, 7, 96, 0, 0, 192, 0, 6, 112, 0, 1, 192, 0, 14, 48, 0, 1, 128, 0, 12, 56, 0, 3, 128, 0, 28, 28, 0, 7, 0, 0, 56, 15, 0, 14, 0, 0, 112, 7, 192, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 128, 124, 0, 3, 224, 14, 0, 30, 0, 0, 240, 28, 0, 7, 0, 0, 56, 56, 0, 3, 128, 0, 28, 48, 0, 1, 128, 0, 12, 112, 0, 1, 192, 0, 14, 96, 0, 0, 192, 0, 6, 224, 0, 0, 192, 0, 6, 224, 0, 0, 224, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 224, 0, 7, 224, 0, 0, 224, 0, 7, 96, 0, 0, 192, 0, 6, 112, 0, 1, 192, 0, 14, 48, 0, 1, 128, 0, 12, 56, 0, 3, 128, 0, 28, 28, 0, 7, 0, 0, 56, 15, 0, 14, 0, 0, 112, 7, 192, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 128, 124, 0, 3, 224, 14, 0, 30, 0, 0, 240, 28, 0, 7, 0, 0, 56, 56, 0, 3, 128, 0, 28, 48, 0, 1, 128, 0, 12, 112, 0, 1, 192, 0, 14, 96, 0, 0, 192, 0, 6, 224, 0, 0, 192, 0, 6, 224, 0, 0, 224, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 224, 0, 7, 224, 0, 0, 224, 0, 7, 96, 0, 0, 192, 0, 6, 112, 0, 1, 192, 0, 14, 48, 0, 1, 128, 0, 12, 56, 0, 3, 128, 0, 28, 28, 0, 7, 0, 0, 56, 15, 0, 14, 0, 0, 112, 7, 192, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 128, 124, 0, 3, 224, 14, 0, 30, 0, 0, 240, 28, 0, 7, 0, 0, 56, 56, 0, 3, 128, 0, 28, 48, 0, 1, 128, 0, 12, 112, 0, 1, 192, 0, 14, 96, 0, 0, 192, 0, 6, 224, 0, 0, 192, 0, 6, 224, 0, 0, 224, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 224, 0, 7, 224, 0, 0, 224, 0, 7, 96, 0, 0, 192, 0, 6, 112, 0, 1, 192, 0, 14, 48, 0, 1, 128, 0, 12, 56, 0, 3, 128, 0, 28, 28, 0, 7, 0, 0, 56, 15, 0, 14, 0, 0, 112, 7, 192, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 128, 124, 0, 3, 224, 14, 0, 30, 0, 0, 240, 28, 0, 7, 0, 0, 56, 56, 0, 3, 128, 0, 28, 48, 0, 1, 128, 0, 12, 112, 0, 1, 192, 0, 14, 96, 0, 0, 192, 0, 6, 224, 0, 0, 192, 0, 6, 224, 0, 0, 224, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 224, 0, 7, 224, 0, 0, 224, 0, 7, 96, 0, 0, 192, 0, 6, 112, 0, 1, 192, 0, 14, 48, 0, 1, 128, 0, 12, 56, 0, 3, 128, 0, 28, 28, 0, 7, 0, 0, 56, 15, 0, 14, 0, 0, 112, 7, 192, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 128, 124, 0, 3, 224, 14, 0, 30, 0, 0, 240, 28, 0, 7, 0, 0, 56, 56, 0, 3, 128, 0, 28, 48, 0, 1, 128, 0, 12, 112, 0, 1, 192, 0, 14, 96, 0, 0, 192, 0, 6, 224, 0, 0, 192, 0, 6, 224, 0, 0, 224, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 96, 0, 3, 192, 0, 0, 224, 0, 7, 224, 0, 0, 224, 0, 7, 96, 0, 0, 192, 0, 6, 112, 0, 1, 192, 0, 14, 48, 0, 1, 128, 0, 12, 56, 0, 3, 128, 0, 28, 28, 0, 7, 0, 0, 56, 15, 0, 14, 0, 0, 112, 7, 192, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 255, 255, 255, 255, 0, 3, 255, 255, 255, 255, 192, 7, 128, 248, 0, 3, 224, 14, 0, 60, 0, 0, 240, 28, 0, 12, 0, 0, 56, 56, 0, 6, 0, 0, 28, 48, 0, 6, 0, 0, 12, 112, 0, 3, 0, 0, 14, 96, 0, 3, 0, 0, 6, 224, 0, 1, 128, 0, 6, 224, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 3, 192, 0, 1, 128, 0, 7, 96, 0, 1, 128, 0, 7, 96, 0, 3, 128, 0, 6, 112, 0, 3, 0, 0, 14, 48, 0, 7, 0, 0, 12, 56, 0, 14, 0, 0, 28, 28, 0, 14, 0, 0, 56, 15, 0, 60, 0, 0, 112, 7, 192, 120, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 15, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 224, 60, 0, 3, 224, 15, 128, 30, 0, 0, 240, 31, 0, 6, 0, 0, 56, 62, 0, 3, 0, 0, 28, 60, 0, 3, 0, 0, 12, 124, 0, 1, 128, 0, 14, 124, 0, 1, 128, 0, 6, 248, 0, 0, 128, 0, 6, 248, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 3, 248, 0, 0, 192, 0, 7, 120, 0, 1, 192, 0, 7, 120, 0, 1, 128, 0, 6, 124, 0, 1, 128, 0, 14, 60, 0, 3, 128, 0, 12, 62, 0, 7, 0, 0, 28, 31, 0, 6, 0, 0, 56, 15, 128, 14, 0, 0, 112, 7, 224, 60, 0, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 252, 7, 128, 3, 224, 15, 248, 1, 192, 0, 240, 31, 224, 0, 224, 0, 56, 63, 224, 0, 96, 0, 28, 63, 192, 0, 48, 0, 12, 127, 192, 0, 48, 0, 14, 127, 128, 0, 24, 0, 6, 255, 128, 0, 24, 0, 6, 255, 128, 0, 24, 0, 3, 255, 0, 0, 8, 0, 3, 255, 0, 0, 8, 0, 3, 255, 0, 0, 12, 0, 3, 255, 0, 0, 24, 0, 3, 255, 0, 0, 24, 0, 7, 127, 128, 0, 24, 0, 7, 127, 128, 0, 24, 0, 6, 127, 128, 0, 56, 0, 14, 63, 192, 0, 48, 0, 12, 63, 224, 0, 112, 0, 28, 31, 224, 0, 224, 0, 56, 15, 248, 1, 192, 0, 112, 7, 254, 3, 128, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 248, 15, 3, 224, 15, 255, 240, 3, 128, 240, 31, 255, 224, 1, 192, 56, 63, 255, 192, 0, 224, 28, 63, 255, 128, 0, 96, 12, 127, 255, 128, 0, 32, 14, 127, 255, 0, 0, 48, 6, 255, 255, 0, 0, 48, 6, 255, 255, 0, 0, 48, 3, 255, 254, 0, 0, 16, 3, 255, 254, 0, 0, 24, 3, 255, 254, 0, 0, 24, 3, 255, 254, 0, 0, 24, 3, 255, 255, 0, 0, 48, 7, 127, 255, 0, 0, 48, 7, 127, 255, 0, 0, 48, 6, 127, 255, 0, 0, 112, 14, 63, 255, 128, 0, 96, 12, 63, 255, 192, 0, 224, 28, 31, 255, 224, 1, 192, 56, 15, 255, 240, 3, 128, 112, 7, 255, 252, 7, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 7, 224, 15, 255, 255, 240, 3, 240, 31, 255, 255, 224, 0, 248, 63, 255, 255, 192, 0, 124, 63, 255, 255, 192, 0, 44, 127, 255, 255, 128, 0, 62, 127, 255, 255, 128, 0, 54, 255, 255, 255, 0, 0, 30, 255, 255, 255, 0, 0, 27, 255, 255, 255, 0, 0, 27, 255, 255, 255, 0, 0, 27, 255, 255, 255, 0, 0, 27, 255, 255, 255, 0, 0, 27, 255, 255, 255, 0, 0, 31, 127, 255, 255, 0, 0, 31, 127, 255, 255, 0, 0, 62, 127, 255, 255, 128, 0, 62, 63, 255, 255, 128, 0, 124, 63, 255, 255, 192, 0, 124, 31, 255, 255, 224, 0, 248, 15, 255, 255, 240, 1, 240, 7, 255, 255, 252, 7, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 232, 0, 0, 127, 255, 255, 255, 128, 1, 255, 255, 255, 255, 192, 7, 255, 255, 255, 3, 224, 15, 255, 255, 254, 0, 240, 31, 255, 255, 252, 0, 56, 63, 255, 255, 248, 0, 28, 63, 255, 255, 240, 0, 12, 127, 255, 255, 240, 0, 14, 127, 255, 255, 224, 0, 6, 255, 255, 255, 224, 0, 6, 255, 255, 255, 224, 0, 3, 255, 255, 255, 224, 0, 3, 255, 255, 255, 192, 0, 3, 255, 255, 255, 192, 0, 3, 255, 255, 255, 192, 0, 3, 255, 255, 255, 224, 0, 7, 127, 255, 255, 224, 0, 7, 127, 255, 255, 224, 0, 6, 127, 255, 255, 240, 0, 14, 63, 255, 255, 240, 0, 12, 63, 255, 255, 248, 0, 28, 31, 255, 255, 252, 0, 56, 15, 255, 255, 254, 0, 112, 7, 255, 255, 255, 129, 224, 3, 255, 255, 255, 255, 192, 0, 255, 255, 255, 255, 0, 0, 7, 255, 255, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 240, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 254, 3, 224, 15, 255, 255, 248, 0, 240, 31, 255, 255, 240, 0, 56, 63, 255, 255, 224, 0, 28, 63, 255, 255, 224, 0, 12, 127, 255, 255, 192, 0, 14, 127, 255, 255, 192, 0, 6, 255, 255, 255, 128, 0, 6, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 3, 255, 255, 255, 128, 0, 7, 127, 255, 255, 128, 0, 7, 127, 255, 255, 192, 0, 6, 127, 255, 255, 192, 0, 14, 63, 255, 255, 224, 0, 12, 63, 255, 255, 224, 0, 28, 31, 255, 255, 240, 0, 56, 15, 255, 255, 252, 0, 112, 7, 255, 255, 255, 1, 224, 3, 255, 255, 255, 255, 192, 0, 255, 255, 255, 255, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 3, 224, 15, 255, 255, 240, 0, 240, 31, 255, 255, 224, 0, 56, 63, 255, 255, 192, 0, 28, 63, 255, 255, 128, 0, 12, 127, 255, 255, 128, 0, 14, 127, 255, 255, 0, 0, 6, 255, 255, 255, 0, 0, 7, 255, 255, 255, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 6, 127, 255, 255, 128, 0, 14, 63, 255, 255, 128, 0, 12, 63, 255, 255, 192, 0, 28, 31, 255, 255, 224, 0, 56, 15, 255, 255, 248, 0, 112, 7, 255, 255, 254, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 3, 224, 15, 255, 255, 240, 0, 240, 31, 255, 255, 224, 0, 56, 63, 255, 255, 192, 0, 28, 63, 255, 255, 128, 0, 12, 127, 255, 255, 128, 0, 14, 127, 255, 255, 0, 0, 6, 255, 255, 255, 0, 0, 7, 255, 255, 255, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 6, 127, 255, 255, 128, 0, 14, 63, 255, 255, 128, 0, 12, 63, 255, 255, 192, 0, 28, 31, 255, 255, 224, 0, 56, 15, 255, 255, 248, 0, 112, 7, 255, 255, 254, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 255, 255, 224, 0, 0, 127, 255, 255, 255, 0, 1, 255, 255, 255, 255, 192, 7, 255, 255, 252, 3, 224, 15, 255, 255, 240, 0, 240, 31, 255, 255, 224, 0, 56, 63, 255, 255, 192, 0, 28, 63, 255, 255, 128, 0, 12, 127, 255, 255, 128, 0, 14, 127, 255, 255, 0, 0, 6, 255, 255, 255, 0, 0, 7, 255, 255, 255, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 254, 0, 0, 3, 255, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 7, 127, 255, 255, 0, 0, 6, 127, 255, 255, 128, 0, 14, 63, 255, 255, 128, 0, 12, 63, 255, 255, 192, 0, 28, 31, 255, 255, 224, 0, 56, 15, 255, 255, 248, 0, 112, 7, 255, 255, 254, 1, 224, 3, 255, 255, 255, 255, 128, 0, 255, 255, 255, 254, 0, 0, 7, 255, 255, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
+
+static const byte PROGMEM animation_wifi[][288] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 1, 128, 7, 158, 63, 128, 127, 255, 1, 252, 31, 1, 252, 127, 192, 248, 12, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 1, 128, 7, 158, 63, 128, 127, 255, 1, 252, 31, 1, 252, 127, 192, 248, 12, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 1, 128, 7, 158, 63, 128, 127, 255, 1, 252, 31, 1, 252, 127, 192, 248, 12, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 1, 128, 7, 158, 63, 128, 127, 255, 1, 252, 31, 1, 252, 127, 192, 248, 12, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 63, 254, 7, 158, 63, 129, 255, 255, 129, 252, 31, 7, 192, 7, 224, 248, 12, 31, 0, 0, 248, 112, 0, 60, 0, 0, 60, 0, 0, 112, 3, 224, 30, 0, 0, 224, 63, 252, 7, 0, 0, 112, 254, 127, 14, 0, 0, 59, 224, 7, 220, 0, 0, 31, 128, 1, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 254, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 192, 7, 252, 0, 0, 124, 0, 0, 126, 0, 1, 240, 0, 0, 15, 128, 7, 192, 0, 0, 3, 224, 15, 0, 127, 255, 0, 240, 28, 1, 255, 255, 192, 56, 120, 15, 128, 3, 248, 30, 240, 62, 0, 0, 124, 15, 240, 240, 7, 192, 31, 15, 113, 224, 127, 255, 7, 142, 63, 131, 248, 63, 227, 252, 31, 15, 128, 1, 240, 248, 14, 28, 0, 0, 120, 112, 0, 120, 0, 0, 30, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 15, 142, 0, 0, 59, 128, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 15, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 254, 0, 0, 0, 3, 255, 255, 192, 0, 0, 31, 224, 15, 248, 0, 0, 126, 0, 0, 126, 0, 1, 240, 0, 0, 15, 128, 7, 192, 0, 0, 3, 224, 15, 0, 63, 254, 0, 240, 28, 1, 255, 255, 192, 56, 56, 15, 224, 15, 240, 30, 240, 62, 0, 0, 252, 15, 224, 120, 0, 0, 31, 7, 113, 224, 3, 128, 7, 142, 59, 192, 127, 255, 3, 220, 31, 3, 252, 63, 192, 248, 14, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 120, 0, 0, 30, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 248, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 62, 254, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 127, 0, 1, 224, 0, 0, 15, 192, 7, 128, 0, 0, 3, 224, 14, 0, 127, 255, 0, 240, 60, 1, 255, 255, 192, 60, 120, 15, 192, 7, 248, 30, 224, 62, 0, 0, 254, 15, 224, 240, 0, 0, 31, 7, 113, 224, 0, 0, 7, 142, 59, 128, 0, 0, 1, 252, 31, 0, 0, 0, 0, 248, 14, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 224, 0, 0, 0, 0, 127, 255, 0, 0, 0, 1, 224, 15, 192, 0, 0, 7, 128, 3, 224, 0, 0, 14, 0, 0, 112, 0, 0, 28, 15, 248, 56, 0, 0, 28, 127, 254, 56, 0, 0, 14, 240, 15, 112, 0, 0, 7, 192, 3, 224, 0, 0, 3, 128, 129, 192, 0, 0, 0, 15, 248, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 240, 31, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 254, 0, 0, 0, 1, 254, 255, 192, 0, 0, 7, 128, 3, 240, 0, 0, 30, 0, 0, 124, 0, 0, 112, 15, 248, 30, 0, 0, 224, 127, 255, 7, 0, 1, 195, 224, 7, 195, 192, 3, 143, 0, 1, 241, 192, 1, 156, 0, 0, 121, 128, 0, 248, 0, 0, 31, 0, 0, 112, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 62, 124, 0, 0, 0, 0, 127, 254, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 30, 252, 0, 0, 0, 0, 97, 206, 0, 0, 0, 0, 223, 251, 128, 0, 0, 1, 179, 239, 128, 0, 0, 0, 223, 255, 0, 0, 0, 0, 60, 126, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 49, 156, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 252, 0, 0, 0, 0, 255, 255, 0, 0, 0, 3, 224, 7, 192, 0, 0, 15, 1, 193, 240, 0, 0, 28, 63, 252, 120, 0, 0, 56, 252, 127, 156, 0, 0, 115, 192, 7, 206, 0, 0, 63, 0, 0, 252, 0, 0, 30, 0, 0, 120, 0, 0, 8, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 248, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 124, 126, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 7, 255, 255, 224, 0, 0, 31, 128, 3, 248, 0, 0, 124, 0, 0, 62, 0, 1, 240, 0, 0, 15, 128, 3, 192, 63, 254, 3, 192, 7, 1, 255, 255, 192, 224, 30, 7, 192, 7, 240, 120, 28, 30, 0, 0, 252, 56, 28, 120, 0, 0, 62, 56, 14, 240, 0, 0, 15, 112, 7, 192, 0, 0, 7, 224, 3, 128, 0, 0, 1, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 254, 0, 0, 0, 0, 248, 63, 0, 0, 0, 1, 192, 7, 192, 0, 0, 7, 135, 241, 224, 0, 0, 7, 63, 252, 224, 0, 0, 3, 248, 63, 192, 0, 0, 1, 239, 255, 128, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 127, 0, 1, 224, 0, 0, 15, 192, 7, 128, 0, 0, 3, 224, 14, 0, 127, 255, 0, 240, 60, 1, 255, 255, 192, 60, 120, 15, 192, 7, 248, 30, 224, 62, 0, 0, 254, 15, 224, 240, 0, 0, 31, 7, 113, 224, 0, 0, 7, 142, 59, 128, 0, 0, 1, 252, 31, 0, 0, 0, 0, 248, 14, 0, 0, 0, 0, 112, 0, 0, 15, 224, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 240, 31, 192, 0, 0, 7, 128, 3, 240, 0, 0, 30, 0, 0, 120, 0, 0, 60, 7, 240, 60, 0, 0, 56, 63, 254, 30, 0, 0, 60, 252, 127, 60, 0, 0, 31, 224, 7, 248, 0, 0, 15, 128, 1, 240, 0, 0, 2, 0, 0, 64, 0, 0, 0, 0, 128, 0, 0, 0, 0, 15, 248, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 240, 31, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 254, 0, 0, 0, 3, 255, 255, 192, 0, 0, 31, 224, 15, 248, 0, 0, 126, 0, 0, 126, 0, 1, 240, 0, 0, 15, 128, 7, 192, 0, 0, 3, 224, 15, 0, 63, 254, 0, 240, 28, 1, 255, 255, 192, 56, 56, 15, 224, 15, 240, 30, 240, 62, 0, 0, 252, 15, 224, 120, 0, 0, 31, 7, 113, 224, 3, 128, 7, 142, 59, 192, 127, 255, 3, 220, 31, 3, 252, 63, 192, 248, 14, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 120, 0, 0, 30, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 248, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 192, 0, 0, 0, 0, 31, 248, 0, 0, 0, 0, 62, 254, 0, 0, 0, 0, 240, 15, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 254, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 192, 7, 252, 0, 0, 124, 0, 0, 126, 0, 1, 240, 0, 0, 15, 128, 7, 192, 0, 0, 3, 224, 15, 0, 127, 255, 0, 240, 28, 1, 255, 255, 192, 56, 120, 15, 128, 3, 248, 30, 240, 62, 0, 0, 124, 15, 240, 240, 7, 192, 31, 15, 113, 224, 127, 255, 7, 142, 63, 131, 248, 63, 227, 252, 31, 15, 128, 1, 240, 248, 14, 28, 0, 0, 120, 112, 0, 120, 0, 0, 30, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 15, 142, 0, 0, 59, 128, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 15, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 63, 254, 7, 158, 63, 129, 255, 255, 129, 252, 31, 7, 192, 7, 224, 248, 12, 31, 0, 0, 248, 112, 0, 60, 0, 0, 60, 0, 0, 112, 3, 224, 30, 0, 0, 224, 63, 252, 7, 0, 0, 112, 254, 127, 14, 0, 0, 59, 224, 7, 220, 0, 0, 31, 128, 1, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 1, 128, 7, 158, 63, 128, 127, 255, 1, 252, 31, 1, 252, 127, 192, 248, 12, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 1, 128, 7, 158, 63, 128, 127, 255, 1, 252, 31, 1, 252, 127, 192, 248, 12, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 255, 0, 0, 0, 3, 255, 255, 224, 0, 0, 31, 128, 3, 252, 0, 0, 124, 0, 0, 63, 0, 1, 224, 0, 0, 15, 192, 7, 128, 1, 128, 3, 224, 14, 0, 127, 255, 0, 240, 28, 3, 255, 255, 192, 60, 120, 15, 128, 1, 248, 30, 240, 60, 0, 0, 126, 15, 112, 240, 0, 0, 31, 14, 121, 192, 1, 128, 7, 158, 63, 128, 127, 255, 1, 252, 31, 1, 252, 127, 192, 248, 12, 15, 128, 3, 240, 112, 0, 30, 0, 0, 120, 0, 0, 56, 0, 0, 28, 0, 0, 240, 15, 248, 15, 0, 0, 224, 127, 254, 7, 0, 0, 113, 240, 31, 142, 0, 0, 59, 192, 3, 220, 0, 0, 31, 0, 0, 248, 0, 0, 14, 0, 0, 112, 0, 0, 0, 15, 240, 0, 0, 0, 0, 63, 252, 0, 0, 0, 0, 120, 30, 0, 0, 0, 0, 224, 7, 0, 0, 0, 0, 112, 14, 0, 0, 0, 0, 56, 28, 0, 0, 0, 0, 28, 56, 0, 0, 0, 0, 14, 112, 0, 0, 0, 0, 7, 224, 0, 0, 0, 0, 3, 192, 0, 0, 0, 0, 1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
\ No newline at end of file
diff --git a/firmware/include/controllers/DisplayController.h b/firmware/include/controllers/DisplayController.h
new file mode 100644
index 0000000..b285cd1
--- /dev/null
+++ b/firmware/include/controllers/DisplayController.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include
+#include
+#include "Animation.h"
+
+class DisplayController
+{
+public:
+ DisplayController(uint8_t oledWidth, uint8_t oledHeight, uint8_t oledAddress = 0x3C);
+
+ void begin();
+
+ void drawSplashScreen();
+ void drawIdleScreen(int duration, bool wifi);
+ void drawTimerScreen(int remainingSeconds);
+ void drawPausedScreen(int remainingSeconds);
+ void drawResetScreen(bool resetSelected);
+ void drawDoneScreen();
+ void drawAdjustScreen(int duration);
+ void drawProvisionScreen();
+ void clear();
+
+ void showAnimation(const byte frames[][288], int frameCount, bool loop = false, bool reverse = false, unsigned long durationMs = 0, int width = 48, int height = 48);
+ void updateAnimation();
+ bool isAnimationRunning();
+
+ void showConfirmation();
+ void showCancel();
+ void showReset();
+ void showConnected();
+ void showTimerDone();
+ void showTimerStart();
+ void showTimerPause();
+ void showTimerResume();
+
+private:
+ Adafruit_SSD1306 oled;
+ Animation animation;
+};
diff --git a/firmware/include/controllers/InputController.h b/firmware/include/controllers/InputController.h
new file mode 100644
index 0000000..7c9c93a
--- /dev/null
+++ b/firmware/include/controllers/InputController.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+class InputController
+{
+public:
+ InputController(uint8_t buttonPin, uint8_t encoderPinA, uint8_t encoderPinB);
+ void begin();
+ void update();
+
+ void onPressHandler(std::function handler);
+ void onDoublePressHandler(std::function handler);
+ void onLongPressHandler(std::function handler);
+ void onEncoderRotateHandler(std::function handler);
+
+ void releaseHandlers();
+
+private:
+ OneButton button;
+ RotaryEncoder encoder;
+
+ uint8_t buttonPin;
+ uint8_t encoderPinA;
+ uint8_t encoderPinB;
+
+ std::function pressHandler = nullptr;
+ std::function doublePressHandler = nullptr;
+ std::function longPressHandler = nullptr;
+ std::function encoderRotateHandler = nullptr;
+
+ int lastPosition;
+
+ void onButtonClick();
+ void onButtonDoubleClick();
+ void onButtonLongPress();
+ void onEncoderRotate(int delta);
+
+ static void handleEncoderInterrupt();
+ static void handleButtonInterrupt();
+};
+
+extern InputController inputController;
diff --git a/firmware/include/controllers/LedController.h b/firmware/include/controllers/LedController.h
new file mode 100644
index 0000000..29fe4a0
--- /dev/null
+++ b/firmware/include/controllers/LedController.h
@@ -0,0 +1,57 @@
+#pragma once
+
+#include
+
+class LEDController
+{
+public:
+ LEDController(uint8_t ledPin, uint16_t numLeds, uint8_t brightness = 255);
+
+ void begin();
+ void update();
+
+ void startFillAndDecay(uint32_t color, uint32_t totalDuration);
+ void setSpinner(uint32_t color, int cycles);
+ void setBreath(uint32_t color, int cycles, bool endFilled, uint32_t speed);
+ void setSolid(uint32_t color);
+
+ void turnOff();
+ void printDebugInfo();
+
+private:
+ Adafruit_NeoPixel leds;
+ uint16_t numLeds;
+ uint8_t brightness;
+ int brightnessLevel;
+
+ enum AnimationType
+ {
+ None,
+ FillAndDecay,
+ Spinner,
+ Breath
+ } currentAnimation;
+ unsigned long lastUpdateTime;
+
+ uint32_t animationColor;
+ uint32_t animationDuration;
+ uint32_t animationSpeed;
+
+ int currentStep;
+ int currentCycle;
+ int pixelIndex;
+ int animationCycles;
+ bool endFilled;
+ bool decayStarted;
+
+ // Animation handling methods
+ void handleFillAndDecay();
+ void handleSpinner();
+ void handleBreath();
+
+ // Reset animation state
+ void stopCurrentAnimation();
+
+ // Helper to scale color by brightness
+ uint32_t scaleColor(uint32_t color, uint8_t brightness);
+};
\ No newline at end of file
diff --git a/firmware/include/controllers/NetworkController.h b/firmware/include/controllers/NetworkController.h
new file mode 100644
index 0000000..9272c75
--- /dev/null
+++ b/firmware/include/controllers/NetworkController.h
@@ -0,0 +1,56 @@
+#pragma once
+
+#include
+#include
+#include
+
+class NetworkController
+{
+public:
+ NetworkController();
+ void begin();
+ void update();
+ void startProvisioning();
+ void stopProvisioning();
+ void reset();
+ bool isWiFiProvisioned();
+ bool isWiFiConnected();
+ bool isBluetoothPaired();
+ void initializeBluetooth();
+ void startBluetooth();
+ void stopBluetooth();
+ void sendWebhookAction(const String &action);
+
+private:
+ BluetoothA2DPSink a2dp_sink;
+ Preferences preferences;
+ WiFiProvisioner::WiFiProvisioner wifiProvisioner; // Instance of WiFiProvisioner
+
+ String webhookURL;
+ bool btPaired; // Paired state loaded from NVS
+ bool bluetoothActive;
+ bool bluetoothAttempted;
+ bool provisioningMode;
+ unsigned long lastBluetoothtAttempt;
+
+ void WiFiProvisionerSettings();
+ void saveBluetoothPairedState(bool paired);
+ static void btConnectionStateCallback(esp_a2d_connection_state_t state, void *obj);
+
+ // Tasks
+ TaskHandle_t bluetoothTaskHandle;
+ TaskHandle_t webhookTaskHandle;
+ QueueHandle_t webhookQueue;
+
+ static void bluetoothTask(void *param);
+ static void webhookTask(void *param);
+ bool sendWebhookRequest(const String &action);
+
+ static NetworkController *instance;
+
+ static bool validateInputCallback(const String &input);
+ static void factoryResetCallback();
+
+ bool validateInput(const String &input);
+ void handleFactoryReset();
+};
diff --git a/firmware/include/fonts/Org_01.h b/firmware/include/fonts/Org_01.h
new file mode 100644
index 0000000..9b80258
--- /dev/null
+++ b/firmware/include/fonts/Org_01.h
@@ -0,0 +1,131 @@
+#pragma once
+#include
+
+// Org_v01 by Orgdot (www.orgdot.com/aliasfonts). A tiny,
+// stylized font with all characters within a 6 pixel height.
+
+const uint8_t Org_01Bitmaps[] PROGMEM = {
+ 0xE8, 0xA0, 0x57, 0xD5, 0xF5, 0x00, 0xFD, 0x3E, 0x5F, 0x80, 0x88, 0x88,
+ 0x88, 0x80, 0xF4, 0xBF, 0x2E, 0x80, 0x80, 0x6A, 0x40, 0x95, 0x80, 0xAA,
+ 0x80, 0x5D, 0x00, 0xC0, 0xF0, 0x80, 0x08, 0x88, 0x88, 0x00, 0xFC, 0x63,
+ 0x1F, 0x80, 0xF8, 0xF8, 0x7F, 0x0F, 0x80, 0xF8, 0x7E, 0x1F, 0x80, 0x8C,
+ 0x7E, 0x10, 0x80, 0xFC, 0x3E, 0x1F, 0x80, 0xFC, 0x3F, 0x1F, 0x80, 0xF8,
+ 0x42, 0x10, 0x80, 0xFC, 0x7F, 0x1F, 0x80, 0xFC, 0x7E, 0x1F, 0x80, 0x90,
+ 0xB0, 0x2A, 0x22, 0xF0, 0xF0, 0x88, 0xA8, 0xF8, 0x4E, 0x02, 0x00, 0xFD,
+ 0x6F, 0x0F, 0x80, 0xFC, 0x7F, 0x18, 0x80, 0xF4, 0x7D, 0x1F, 0x00, 0xFC,
+ 0x21, 0x0F, 0x80, 0xF4, 0x63, 0x1F, 0x00, 0xFC, 0x3F, 0x0F, 0x80, 0xFC,
+ 0x3F, 0x08, 0x00, 0xFC, 0x2F, 0x1F, 0x80, 0x8C, 0x7F, 0x18, 0x80, 0xF9,
+ 0x08, 0x4F, 0x80, 0x78, 0x85, 0x2F, 0x80, 0x8D, 0xB1, 0x68, 0x80, 0x84,
+ 0x21, 0x0F, 0x80, 0xFD, 0x6B, 0x5A, 0x80, 0xFC, 0x63, 0x18, 0x80, 0xFC,
+ 0x63, 0x1F, 0x80, 0xFC, 0x7F, 0x08, 0x00, 0xFC, 0x63, 0x3F, 0x80, 0xFC,
+ 0x7F, 0x29, 0x00, 0xFC, 0x3E, 0x1F, 0x80, 0xF9, 0x08, 0x42, 0x00, 0x8C,
+ 0x63, 0x1F, 0x80, 0x8C, 0x62, 0xA2, 0x00, 0xAD, 0x6B, 0x5F, 0x80, 0x8A,
+ 0x88, 0xA8, 0x80, 0x8C, 0x54, 0x42, 0x00, 0xF8, 0x7F, 0x0F, 0x80, 0xEA,
+ 0xC0, 0x82, 0x08, 0x20, 0x80, 0xD5, 0xC0, 0x54, 0xF8, 0x80, 0xF1, 0xFF,
+ 0x8F, 0x99, 0xF0, 0xF8, 0x8F, 0x1F, 0x99, 0xF0, 0xFF, 0x8F, 0x6B, 0xA4,
+ 0xF9, 0x9F, 0x10, 0x8F, 0x99, 0x90, 0xF0, 0x55, 0xC0, 0x8A, 0xF9, 0x90,
+ 0xF8, 0xFD, 0x63, 0x10, 0xF9, 0x99, 0xF9, 0x9F, 0xF9, 0x9F, 0x80, 0xF9,
+ 0x9F, 0x20, 0xF8, 0x88, 0x47, 0x1F, 0x27, 0xC8, 0x42, 0x00, 0x99, 0x9F,
+ 0x99, 0x97, 0x8C, 0x6B, 0xF0, 0x96, 0x69, 0x99, 0x9F, 0x10, 0x2E, 0x8F,
+ 0x2B, 0x22, 0xF8, 0x89, 0xA8, 0x0F, 0xE0};
+
+const GFXglyph Org_01Glyphs[] PROGMEM = {{0, 0, 0, 6, 0, 1}, // 0x20 ' '
+ {0, 1, 5, 2, 0, -4}, // 0x21 '!'
+ {1, 3, 1, 4, 0, -4}, // 0x22 '"'
+ {2, 5, 5, 6, 0, -4}, // 0x23 '#'
+ {6, 5, 5, 6, 0, -4}, // 0x24 '$'
+ {10, 5, 5, 6, 0, -4}, // 0x25 '%'
+ {14, 5, 5, 6, 0, -4}, // 0x26 '&'
+ {18, 1, 1, 2, 0, -4}, // 0x27 '''
+ {19, 2, 5, 3, 0, -4}, // 0x28 '('
+ {21, 2, 5, 3, 0, -4}, // 0x29 ')'
+ {23, 3, 3, 4, 0, -3}, // 0x2A '*'
+ {25, 3, 3, 4, 0, -3}, // 0x2B '+'
+ {27, 1, 2, 2, 0, 0}, // 0x2C ','
+ {28, 4, 1, 5, 0, -2}, // 0x2D '-'
+ {29, 1, 1, 2, 0, 0}, // 0x2E '.'
+ {30, 5, 5, 6, 0, -4}, // 0x2F '/'
+ {34, 5, 5, 6, 0, -4}, // 0x30 '0'
+ {38, 1, 5, 2, 0, -4}, // 0x31 '1'
+ {39, 5, 5, 6, 0, -4}, // 0x32 '2'
+ {43, 5, 5, 6, 0, -4}, // 0x33 '3'
+ {47, 5, 5, 6, 0, -4}, // 0x34 '4'
+ {51, 5, 5, 6, 0, -4}, // 0x35 '5'
+ {55, 5, 5, 6, 0, -4}, // 0x36 '6'
+ {59, 5, 5, 6, 0, -4}, // 0x37 '7'
+ {63, 5, 5, 6, 0, -4}, // 0x38 '8'
+ {67, 5, 5, 6, 0, -4}, // 0x39 '9'
+ {71, 1, 4, 2, 0, -3}, // 0x3A ':'
+ {72, 1, 4, 2, 0, -3}, // 0x3B ';'
+ {73, 3, 5, 4, 0, -4}, // 0x3C '<'
+ {75, 4, 3, 5, 0, -3}, // 0x3D '='
+ {77, 3, 5, 4, 0, -4}, // 0x3E '>'
+ {79, 5, 5, 6, 0, -4}, // 0x3F '?'
+ {83, 5, 5, 6, 0, -4}, // 0x40 '@'
+ {87, 5, 5, 6, 0, -4}, // 0x41 'A'
+ {91, 5, 5, 6, 0, -4}, // 0x42 'B'
+ {95, 5, 5, 6, 0, -4}, // 0x43 'C'
+ {99, 5, 5, 6, 0, -4}, // 0x44 'D'
+ {103, 5, 5, 6, 0, -4}, // 0x45 'E'
+ {107, 5, 5, 6, 0, -4}, // 0x46 'F'
+ {111, 5, 5, 6, 0, -4}, // 0x47 'G'
+ {115, 5, 5, 6, 0, -4}, // 0x48 'H'
+ {119, 5, 5, 6, 0, -4}, // 0x49 'I'
+ {123, 5, 5, 6, 0, -4}, // 0x4A 'J'
+ {127, 5, 5, 6, 0, -4}, // 0x4B 'K'
+ {131, 5, 5, 6, 0, -4}, // 0x4C 'L'
+ {135, 5, 5, 6, 0, -4}, // 0x4D 'M'
+ {139, 5, 5, 6, 0, -4}, // 0x4E 'N'
+ {143, 5, 5, 6, 0, -4}, // 0x4F 'O'
+ {147, 5, 5, 6, 0, -4}, // 0x50 'P'
+ {151, 5, 5, 6, 0, -4}, // 0x51 'Q'
+ {155, 5, 5, 6, 0, -4}, // 0x52 'R'
+ {159, 5, 5, 6, 0, -4}, // 0x53 'S'
+ {163, 5, 5, 6, 0, -4}, // 0x54 'T'
+ {167, 5, 5, 6, 0, -4}, // 0x55 'U'
+ {171, 5, 5, 6, 0, -4}, // 0x56 'V'
+ {175, 5, 5, 6, 0, -4}, // 0x57 'W'
+ {179, 5, 5, 6, 0, -4}, // 0x58 'X'
+ {183, 5, 5, 6, 0, -4}, // 0x59 'Y'
+ {187, 5, 5, 6, 0, -4}, // 0x5A 'Z'
+ {191, 2, 5, 3, 0, -4}, // 0x5B '['
+ {193, 5, 5, 6, 0, -4}, // 0x5C '\'
+ {197, 2, 5, 3, 0, -4}, // 0x5D ']'
+ {199, 3, 2, 4, 0, -4}, // 0x5E '^'
+ {200, 5, 1, 6, 0, 1}, // 0x5F '_'
+ {201, 1, 1, 2, 0, -4}, // 0x60 '`'
+ {202, 4, 4, 5, 0, -3}, // 0x61 'a'
+ {204, 4, 5, 5, 0, -4}, // 0x62 'b'
+ {207, 4, 4, 5, 0, -3}, // 0x63 'c'
+ {209, 4, 5, 5, 0, -4}, // 0x64 'd'
+ {212, 4, 4, 5, 0, -3}, // 0x65 'e'
+ {214, 3, 5, 4, 0, -4}, // 0x66 'f'
+ {216, 4, 5, 5, 0, -3}, // 0x67 'g'
+ {219, 4, 5, 5, 0, -4}, // 0x68 'h'
+ {222, 1, 4, 2, 0, -3}, // 0x69 'i'
+ {223, 2, 5, 3, 0, -3}, // 0x6A 'j'
+ {225, 4, 5, 5, 0, -4}, // 0x6B 'k'
+ {228, 1, 5, 2, 0, -4}, // 0x6C 'l'
+ {229, 5, 4, 6, 0, -3}, // 0x6D 'm'
+ {232, 4, 4, 5, 0, -3}, // 0x6E 'n'
+ {234, 4, 4, 5, 0, -3}, // 0x6F 'o'
+ {236, 4, 5, 5, 0, -3}, // 0x70 'p'
+ {239, 4, 5, 5, 0, -3}, // 0x71 'q'
+ {242, 4, 4, 5, 0, -3}, // 0x72 'r'
+ {244, 4, 4, 5, 0, -3}, // 0x73 's'
+ {246, 5, 5, 6, 0, -4}, // 0x74 't'
+ {250, 4, 4, 5, 0, -3}, // 0x75 'u'
+ {252, 4, 4, 5, 0, -3}, // 0x76 'v'
+ {254, 5, 4, 6, 0, -3}, // 0x77 'w'
+ {257, 4, 4, 5, 0, -3}, // 0x78 'x'
+ {259, 4, 5, 5, 0, -3}, // 0x79 'y'
+ {262, 4, 4, 5, 0, -3}, // 0x7A 'z'
+ {264, 3, 5, 4, 0, -4}, // 0x7B '{'
+ {266, 1, 5, 2, 0, -4}, // 0x7C '|'
+ {267, 3, 5, 4, 0, -4}, // 0x7D '}'
+ {269, 5, 3, 6, 0, -3}}; // 0x7E '~'
+
+const GFXfont Org_01 PROGMEM = {(uint8_t *)Org_01Bitmaps,
+ (GFXglyph *)Org_01Glyphs, 0x20, 0x7E, 7};
+
+// Approx. 943 bytes
diff --git a/firmware/include/fonts/Picopixel.h b/firmware/include/fonts/Picopixel.h
new file mode 100644
index 0000000..463b1b5
--- /dev/null
+++ b/firmware/include/fonts/Picopixel.h
@@ -0,0 +1,123 @@
+#pragma once
+#include
+
+// Picopixel by Sebastian Weber. A tiny font
+// with all characters within a 6 pixel height.
+
+const uint8_t PicopixelBitmaps[] PROGMEM = {
+ 0xE8, 0xB4, 0x57, 0xD5, 0xF5, 0x00, 0x4E, 0x3E, 0x80, 0xA5, 0x4A, 0x4A,
+ 0x5A, 0x50, 0xC0, 0x6A, 0x40, 0x95, 0x80, 0xAA, 0x80, 0x5D, 0x00, 0x60,
+ 0xE0, 0x80, 0x25, 0x48, 0x56, 0xD4, 0x75, 0x40, 0xC5, 0x4E, 0xC5, 0x1C,
+ 0x97, 0x92, 0xF3, 0x1C, 0x53, 0x54, 0xE5, 0x48, 0x55, 0x54, 0x55, 0x94,
+ 0xA0, 0x46, 0x64, 0xE3, 0x80, 0x98, 0xC5, 0x04, 0x56, 0xC6, 0x57, 0xDA,
+ 0xD7, 0x5C, 0x72, 0x46, 0xD6, 0xDC, 0xF3, 0xCE, 0xF3, 0x48, 0x72, 0xD4,
+ 0xB7, 0xDA, 0xF8, 0x24, 0xD4, 0xBB, 0x5A, 0x92, 0x4E, 0x8E, 0xEB, 0x58,
+ 0x80, 0x9D, 0xB9, 0x90, 0x56, 0xD4, 0xD7, 0x48, 0x56, 0xD4, 0x40, 0xD7,
+ 0x5A, 0x71, 0x1C, 0xE9, 0x24, 0xB6, 0xD4, 0xB6, 0xA4, 0x8C, 0x6B, 0x55,
+ 0x00, 0xB5, 0x5A, 0xB5, 0x24, 0xE5, 0x4E, 0xEA, 0xC0, 0x91, 0x12, 0xD5,
+ 0xC0, 0x54, 0xF0, 0x90, 0xC7, 0xF0, 0x93, 0x5E, 0x71, 0x80, 0x25, 0xDE,
+ 0x5E, 0x30, 0x6E, 0x80, 0x77, 0x9C, 0x93, 0x5A, 0xB8, 0x45, 0x60, 0x92,
+ 0xEA, 0xAA, 0x40, 0xD5, 0x6A, 0xD6, 0x80, 0x55, 0x00, 0xD7, 0x40, 0x75,
+ 0x90, 0xE8, 0x71, 0xE0, 0xBA, 0x40, 0xB5, 0x80, 0xB5, 0x00, 0x8D, 0x54,
+ 0xAA, 0x80, 0xAC, 0xE0, 0xE5, 0x70, 0x6A, 0x26, 0xFC, 0xC8, 0xAC, 0x5A};
+
+const GFXglyph PicopixelGlyphs[] PROGMEM = {{0, 0, 0, 2, 0, 1}, // 0x20 ' '
+ {0, 1, 5, 2, 0, -4}, // 0x21 '!'
+ {1, 3, 2, 4, 0, -4}, // 0x22 '"'
+ {2, 5, 5, 6, 0, -4}, // 0x23 '#'
+ {6, 3, 6, 4, 0, -4}, // 0x24 '$'
+ {9, 3, 5, 4, 0, -4}, // 0x25 '%'
+ {11, 4, 5, 5, 0, -4}, // 0x26 '&'
+ {14, 1, 2, 2, 0, -4}, // 0x27 '''
+ {15, 2, 5, 3, 0, -4}, // 0x28 '('
+ {17, 2, 5, 3, 0, -4}, // 0x29 ')'
+ {19, 3, 3, 4, 0, -3}, // 0x2A '*'
+ {21, 3, 3, 4, 0, -3}, // 0x2B '+'
+ {23, 2, 2, 3, 0, 0}, // 0x2C ','
+ {24, 3, 1, 4, 0, -2}, // 0x2D '-'
+ {25, 1, 1, 2, 0, 0}, // 0x2E '.'
+ {26, 3, 5, 4, 0, -4}, // 0x2F '/'
+ {28, 3, 5, 4, 0, -4}, // 0x30 '0'
+ {30, 2, 5, 3, 0, -4}, // 0x31 '1'
+ {32, 3, 5, 4, 0, -4}, // 0x32 '2'
+ {34, 3, 5, 4, 0, -4}, // 0x33 '3'
+ {36, 3, 5, 4, 0, -4}, // 0x34 '4'
+ {38, 3, 5, 4, 0, -4}, // 0x35 '5'
+ {40, 3, 5, 4, 0, -4}, // 0x36 '6'
+ {42, 3, 5, 4, 0, -4}, // 0x37 '7'
+ {44, 3, 5, 4, 0, -4}, // 0x38 '8'
+ {46, 3, 5, 4, 0, -4}, // 0x39 '9'
+ {48, 1, 3, 2, 0, -3}, // 0x3A ':'
+ {49, 2, 4, 3, 0, -3}, // 0x3B ';'
+ {50, 2, 3, 3, 0, -3}, // 0x3C '<'
+ {51, 3, 3, 4, 0, -3}, // 0x3D '='
+ {53, 2, 3, 3, 0, -3}, // 0x3E '>'
+ {54, 3, 5, 4, 0, -4}, // 0x3F '?'
+ {56, 3, 5, 4, 0, -4}, // 0x40 '@'
+ {58, 3, 5, 4, 0, -4}, // 0x41 'A'
+ {60, 3, 5, 4, 0, -4}, // 0x42 'B'
+ {62, 3, 5, 4, 0, -4}, // 0x43 'C'
+ {64, 3, 5, 4, 0, -4}, // 0x44 'D'
+ {66, 3, 5, 4, 0, -4}, // 0x45 'E'
+ {68, 3, 5, 4, 0, -4}, // 0x46 'F'
+ {70, 3, 5, 4, 0, -4}, // 0x47 'G'
+ {72, 3, 5, 4, 0, -4}, // 0x48 'H'
+ {74, 1, 5, 2, 0, -4}, // 0x49 'I'
+ {75, 3, 5, 4, 0, -4}, // 0x4A 'J'
+ {77, 3, 5, 4, 0, -4}, // 0x4B 'K'
+ {79, 3, 5, 4, 0, -4}, // 0x4C 'L'
+ {81, 5, 5, 6, 0, -4}, // 0x4D 'M'
+ {85, 4, 5, 5, 0, -4}, // 0x4E 'N'
+ {88, 3, 5, 4, 0, -4}, // 0x4F 'O'
+ {90, 3, 5, 4, 0, -4}, // 0x50 'P'
+ {92, 3, 6, 4, 0, -4}, // 0x51 'Q'
+ {95, 3, 5, 4, 0, -4}, // 0x52 'R'
+ {97, 3, 5, 4, 0, -4}, // 0x53 'S'
+ {99, 3, 5, 4, 0, -4}, // 0x54 'T'
+ {101, 3, 5, 4, 0, -4}, // 0x55 'U'
+ {103, 3, 5, 4, 0, -4}, // 0x56 'V'
+ {105, 5, 5, 6, 0, -4}, // 0x57 'W'
+ {109, 3, 5, 4, 0, -4}, // 0x58 'X'
+ {111, 3, 5, 4, 0, -4}, // 0x59 'Y'
+ {113, 3, 5, 4, 0, -4}, // 0x5A 'Z'
+ {115, 2, 5, 3, 0, -4}, // 0x5B '['
+ {117, 3, 5, 4, 0, -4}, // 0x5C '\'
+ {119, 2, 5, 3, 0, -4}, // 0x5D ']'
+ {121, 3, 2, 4, 0, -4}, // 0x5E '^'
+ {122, 4, 1, 4, 0, 1}, // 0x5F '_'
+ {123, 2, 2, 3, 0, -4}, // 0x60 '`'
+ {124, 3, 4, 4, 0, -3}, // 0x61 'a'
+ {126, 3, 5, 4, 0, -4}, // 0x62 'b'
+ {128, 3, 3, 4, 0, -2}, // 0x63 'c'
+ {130, 3, 5, 4, 0, -4}, // 0x64 'd'
+ {132, 3, 4, 4, 0, -3}, // 0x65 'e'
+ {134, 2, 5, 3, 0, -4}, // 0x66 'f'
+ {136, 3, 5, 4, 0, -3}, // 0x67 'g'
+ {138, 3, 5, 4, 0, -4}, // 0x68 'h'
+ {140, 1, 5, 2, 0, -4}, // 0x69 'i'
+ {141, 2, 6, 3, 0, -4}, // 0x6A 'j'
+ {143, 3, 5, 4, 0, -4}, // 0x6B 'k'
+ {145, 2, 5, 3, 0, -4}, // 0x6C 'l'
+ {147, 5, 3, 6, 0, -2}, // 0x6D 'm'
+ {149, 3, 3, 4, 0, -2}, // 0x6E 'n'
+ {151, 3, 3, 4, 0, -2}, // 0x6F 'o'
+ {153, 3, 4, 4, 0, -2}, // 0x70 'p'
+ {155, 3, 4, 4, 0, -2}, // 0x71 'q'
+ {157, 2, 3, 3, 0, -2}, // 0x72 'r'
+ {158, 3, 4, 4, 0, -3}, // 0x73 's'
+ {160, 2, 5, 3, 0, -4}, // 0x74 't'
+ {162, 3, 3, 4, 0, -2}, // 0x75 'u'
+ {164, 3, 3, 4, 0, -2}, // 0x76 'v'
+ {166, 5, 3, 6, 0, -2}, // 0x77 'w'
+ {168, 3, 3, 4, 0, -2}, // 0x78 'x'
+ {170, 3, 4, 4, 0, -2}, // 0x79 'y'
+ {172, 3, 4, 4, 0, -3}, // 0x7A 'z'
+ {174, 3, 5, 4, 0, -4}, // 0x7B '{'
+ {176, 1, 6, 2, 0, -4}, // 0x7C '|'
+ {177, 3, 5, 4, 0, -4}, // 0x7D '}'
+ {179, 4, 2, 5, 0, -3}}; // 0x7E '~'
+
+const GFXfont Picopixel PROGMEM = {(uint8_t *)PicopixelBitmaps,
+ (GFXglyph *)PicopixelGlyphs, 0x20, 0x7E, 7};
+
+// Approx. 852 bytes
diff --git a/firmware/include/states/AdjustState.h b/firmware/include/states/AdjustState.h
new file mode 100644
index 0000000..3245c54
--- /dev/null
+++ b/firmware/include/states/AdjustState.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "State.h"
+
+class AdjustState : public State
+{
+public:
+ void enter() override;
+ void update() override;
+ void exit() override;
+ void adjustTimer(int duration);
+
+private:
+ int adjustDuration;
+ unsigned long lastActivity;
+};
\ No newline at end of file
diff --git a/firmware/include/states/DoneState.h b/firmware/include/states/DoneState.h
new file mode 100644
index 0000000..a740bb9
--- /dev/null
+++ b/firmware/include/states/DoneState.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "State.h"
+
+class DoneState : public State
+{
+public:
+ DoneState();
+ void enter() override;
+ void update() override;
+ void exit() override;
+
+private:
+ unsigned long doneEnter;
+};
\ No newline at end of file
diff --git a/firmware/include/states/IdleState.h b/firmware/include/states/IdleState.h
new file mode 100644
index 0000000..9ceb1dc
--- /dev/null
+++ b/firmware/include/states/IdleState.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "State.h"
+
+class IdleState : public State
+{
+public:
+ IdleState();
+ void enter() override;
+ void update() override;
+ void exit() override;
+ void setTimer(int duration);
+
+private:
+ int defaultDuration;
+ unsigned long lastActivity;
+};
diff --git a/firmware/include/states/PausedState.h b/firmware/include/states/PausedState.h
new file mode 100644
index 0000000..954e332
--- /dev/null
+++ b/firmware/include/states/PausedState.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "State.h"
+
+class PausedState : public State
+{
+public:
+ PausedState();
+ void enter() override;
+ void update() override;
+ void exit() override;
+
+ void setPause(int duration, unsigned long elapsedTime);
+
+private:
+ int duration;
+ unsigned long pauseEnter;
+ unsigned long elapsedTime;
+};
\ No newline at end of file
diff --git a/firmware/include/states/ProvisionState.h b/firmware/include/states/ProvisionState.h
new file mode 100644
index 0000000..8b79bb3
--- /dev/null
+++ b/firmware/include/states/ProvisionState.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "State.h"
+
+class ProvisionState : public State
+{
+public:
+ void enter() override;
+ void update() override;
+ void exit() override;
+};
\ No newline at end of file
diff --git a/firmware/include/states/ResetState.h b/firmware/include/states/ResetState.h
new file mode 100644
index 0000000..3411658
--- /dev/null
+++ b/firmware/include/states/ResetState.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "State.h"
+
+class ResetState : public State
+{
+public:
+ void enter() override;
+ void update() override;
+ void exit() override;
+
+ unsigned long resetStartTime = 0;
+};
\ No newline at end of file
diff --git a/firmware/include/states/SleepState.h b/firmware/include/states/SleepState.h
new file mode 100644
index 0000000..547b03f
--- /dev/null
+++ b/firmware/include/states/SleepState.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "State.h"
+
+class SleepState : public State
+{
+public:
+ void enter() override;
+ void update() override;
+ void exit() override;
+};
\ No newline at end of file
diff --git a/firmware/include/states/StartupState.h b/firmware/include/states/StartupState.h
new file mode 100644
index 0000000..10fecdc
--- /dev/null
+++ b/firmware/include/states/StartupState.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "State.h"
+
+class StartupState : public State
+{
+public:
+ StartupState();
+ void enter() override;
+ void update() override;
+ void exit() override;
+
+private:
+ unsigned long startEnter;
+};
diff --git a/firmware/include/states/TimerState.h b/firmware/include/states/TimerState.h
new file mode 100644
index 0000000..69a91ac
--- /dev/null
+++ b/firmware/include/states/TimerState.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "State.h"
+
+class TimerState : public State
+{
+public:
+ TimerState();
+
+ void enter() override;
+ void update() override;
+ void exit() override;
+
+ void setTimer(int duration, unsigned long elapsedTime);
+
+private:
+ int duration;
+ unsigned long startTime;
+ unsigned long elapsedTime;
+};
\ No newline at end of file
diff --git a/firmware/lib/README b/firmware/lib/README
new file mode 100644
index 0000000..2593a33
--- /dev/null
+++ b/firmware/lib/README
@@ -0,0 +1,46 @@
+
+This directory is intended for project specific (private) libraries.
+PlatformIO will compile them to static libraries and link into executable file.
+
+The source code of each library should be placed in an own separate directory
+("lib/your_library_name/[here are source files]").
+
+For example, see a structure of the following two libraries `Foo` and `Bar`:
+
+|--lib
+| |
+| |--Bar
+| | |--docs
+| | |--examples
+| | |--src
+| | |- Bar.c
+| | |- Bar.h
+| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
+| |
+| |--Foo
+| | |- Foo.c
+| | |- Foo.h
+| |
+| |- README --> THIS FILE
+|
+|- platformio.ini
+|--src
+ |- main.c
+
+and a contents of `src/main.c`:
+```
+#include
+#include
+
+int main (void)
+{
+ ...
+}
+
+```
+
+PlatformIO Library Dependency Finder will find automatically dependent
+libraries scanning project source files.
+
+More information about PlatformIO Library Dependency Finder
+- https://docs.platformio.org/page/librarymanager/ldf.html
diff --git a/firmware/partitions.csv b/firmware/partitions.csv
new file mode 100644
index 0000000..828a596
--- /dev/null
+++ b/firmware/partitions.csv
@@ -0,0 +1,5 @@
+# Name, Type, SubType, Offset, Size, Flags
+nvs, data, nvs, 0x9000, 0x5000,
+otadata, data, ota, 0xe000, 0x2000,
+app0, app, ota_0, 0x10000, 0x7C0000,
+spiffs, data, spiffs, 0x7D0000,0x30000,
\ No newline at end of file
diff --git a/firmware/src/Animation.cpp b/firmware/src/Animation.cpp
new file mode 100644
index 0000000..25c4f67
--- /dev/null
+++ b/firmware/src/Animation.cpp
@@ -0,0 +1,82 @@
+#include "Animation.h"
+
+Animation::Animation(Adafruit_SSD1306* display) : oled(display), animationRunning(false), playInReverse(false) {}
+
+void Animation::start(const byte* frames, int frameCount, bool loop, bool reverse, unsigned long durationMs, int width, int height) {
+ animationFrames = frames;
+ totalFrames = frameCount;
+ loopAnimation = loop;
+ playInReverse = reverse; // Set reverse playback flag
+ animationRunning = true;
+
+ // Initialize current frame correctly based on direction
+ currentFrame = playInReverse ? totalFrames - 1 : 0;
+
+ frameWidth = width;
+ frameHeight = height;
+ frameDelay = DEFAULT_FRAME_DELAY;
+
+ if (durationMs == 0) {
+ animationDuration = totalFrames * frameDelay;
+ } else {
+ animationDuration = durationMs;
+ }
+
+ animationStartTime = millis();
+ lastFrameTime = millis();
+
+ frameX = (oled->width() - frameWidth) / 2;
+ frameY = (oled->height() - frameHeight) / 2;
+
+ oled->clearDisplay();
+ oled->drawBitmap(frameX, frameY, &animationFrames[currentFrame * 288], frameWidth, frameHeight, 1);
+ oled->display();
+}
+
+void Animation::update() {
+ if (!animationRunning) return;
+
+ unsigned long currentTime = millis();
+
+ if (currentTime - animationStartTime >= animationDuration) {
+ animationRunning = false;
+ return;
+ }
+
+ // Check if it's time to advance to the next frame
+ if (currentTime - lastFrameTime >= frameDelay) {
+ lastFrameTime = currentTime;
+
+ // Adjust current frame based on direction
+ if (playInReverse) {
+ currentFrame--;
+ if (currentFrame < 0) {
+ if (loopAnimation) {
+ currentFrame = totalFrames - 1; // Wrap around to last frame
+ } else {
+ animationRunning = false;
+ return;
+ }
+ }
+ } else {
+ currentFrame++;
+ if (currentFrame >= totalFrames) {
+ if (loopAnimation) {
+ currentFrame = 0; // Wrap around to first frame
+ } else {
+ animationRunning = false;
+ return;
+ }
+ }
+ }
+
+ // Display the current frame
+ oled->clearDisplay();
+ oled->drawBitmap(frameX, frameY, &animationFrames[currentFrame * 288], frameWidth, frameHeight, 1);
+ oled->display();
+ }
+}
+
+bool Animation::isRunning() {
+ return animationRunning;
+}
diff --git a/firmware/src/StateMachine.cpp b/firmware/src/StateMachine.cpp
new file mode 100644
index 0000000..7ef7bcb
--- /dev/null
+++ b/firmware/src/StateMachine.cpp
@@ -0,0 +1,47 @@
+#include "StateMachine.h"
+
+// Global state machine instance
+StateMachine stateMachine;
+
+// Initialize static states
+AdjustState StateMachine::adjustState;
+SleepState StateMachine::sleepState;
+DoneState StateMachine::doneState;
+IdleState StateMachine::idleState;
+PausedState StateMachine::pausedState;
+ProvisionState StateMachine::provisionState;
+ResetState StateMachine::resetState;
+StartupState StateMachine::startupState;
+TimerState StateMachine::timerState;
+
+StateMachine::StateMachine() {
+ currentState = &startupState; // Start with StartupState
+ stateMutex = xSemaphoreCreateMutex(); // Initialize the mutex
+}
+
+// Clean up the state and delete the mutex
+StateMachine::~StateMachine() {
+ if (stateMutex != NULL) {
+ vSemaphoreDelete(stateMutex); // Delete the mutex
+ }
+}
+
+void StateMachine::changeState(State* newState) {
+ // Lock the mutex
+ if (xSemaphoreTake(stateMutex, portMAX_DELAY) == pdTRUE) {
+ transition = true;
+ if (currentState != nullptr) {
+ currentState->exit();
+ }
+ currentState = newState; // Assign the new state (static state)
+ currentState->enter();
+ transition = false;
+ xSemaphoreGive(stateMutex); // Release the mutex
+ }
+}
+
+void StateMachine::update() {
+ if (!transition && currentState != nullptr) {
+ currentState->update(); // Call update on the current state
+ }
+}
\ No newline at end of file
diff --git a/firmware/src/controllers/DisplayController.cpp b/firmware/src/controllers/DisplayController.cpp
new file mode 100644
index 0000000..8dbe684
--- /dev/null
+++ b/firmware/src/controllers/DisplayController.cpp
@@ -0,0 +1,458 @@
+#include "controllers/DisplayController.h"
+
+#include "fonts/Picopixel.h"
+#include "fonts/Org_01.h"
+#include "bitmaps.h"
+
+DisplayController::DisplayController(uint8_t oledWidth, uint8_t oledHeight, uint8_t oledAddress)
+ : oled(oledWidth, oledHeight, &Wire, -1), animation(&oled) {}
+
+void DisplayController::begin() {
+ if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
+ Serial.println(F("SSD1306 allocation failed"));
+ for (;;); // Loop forever if initialization fails
+ }
+
+ // oled.ssd1306_command(SSD1306_SETCONTRAST);
+ // oled.ssd1306_command(128);
+
+ oled.clearDisplay();
+ oled.display();
+ Serial.println("DisplayController initialized.");
+}
+
+void DisplayController::drawSplashScreen() {
+ oled.clearDisplay();
+
+ oled.drawBitmap(16, 3, focusdial_logo, 99, 45, 1);
+ oled.setTextColor(1);
+ oled.setTextSize(1);
+ oled.setFont(&Picopixel);
+ oled.setCursor(21, 60);
+ oled.print("YOUTUBE/ @SALIMBENBOUZ");
+
+ oled.display();
+}
+
+void DisplayController::drawIdleScreen(int duration, bool wifi) {
+ if (isAnimationRunning()) return;
+
+ static unsigned long lastBlinkTime = 0;
+ static bool blinkState = true;
+
+ unsigned long currentTime = millis();
+
+ // Toggle blink state if WiFi is off
+ if (!wifi && (currentTime - lastBlinkTime >= 500)) {
+ blinkState = !blinkState;
+ lastBlinkTime = currentTime;
+ }
+
+ oled.clearDisplay();
+
+ // "PRESS TO START"
+ oled.setFont(&Picopixel);
+ oled.setTextSize(1);
+ oled.setTextColor(1);
+ oled.setCursor(40, 58);
+ oled.print("PRESS TO START");
+ oled.drawRoundRect(35, 51, 60, 11, 1, 1);
+
+ // Display WiFi icon based on WiFi state
+ if (wifi) {
+ oled.drawBitmap(70, 3, icon_wifi_on, 5, 5, 1);
+ oled.setCursor(54, 7);
+ oled.print("WIFI");
+ } else if (blinkState) {
+ oled.drawBitmap(70, 3, icon_wifi_off, 5, 5, 1);
+ oled.setCursor(54, 7);
+ oled.print("WIFI");
+ }
+
+ char left[3], right[3];
+ int xLeft = 1;
+ int xRight = 73;
+
+ if (duration < 60) {
+ sprintf(left, "%02d", duration);
+ strcpy(right, "00");
+ } else {
+ int hours = duration / 60;
+ int minutes = duration % 60;
+ sprintf(left, "%02d", hours);
+ sprintf(right, "%02d", minutes);
+ }
+
+ // Adjust position if the first character is '1'
+ if (left[0] == '1') {
+ xLeft += 20;
+ }
+ if (right[0] == '1') {
+ xRight += 20;
+ }
+
+ oled.setTextSize(5);
+ oled.setFont(&Org_01);
+ oled.setCursor(xLeft, 36);
+ oled.print(left);
+
+ oled.setCursor(xRight, 36);
+ oled.print(right);
+
+ // Separator dots
+ oled.fillRect(62, 21, 5, 5, 1);
+ oled.fillRect(62, 31, 5, 5, 1);
+
+ oled.display();
+}
+
+void DisplayController::drawTimerScreen(int remainingSeconds) {
+ if (isAnimationRunning()) return;
+
+ oled.clearDisplay();
+
+ if (remainingSeconds < 0) {
+ remainingSeconds = 0;
+ }
+
+ int hours = remainingSeconds / 3600;
+ int minutes = (remainingSeconds % 3600) / 60;
+ int seconds = remainingSeconds % 60;
+
+ char left[3], right[3], secondsStr[3];
+ int xLeft = 1;
+ int xRight = 73;
+
+ // Format left and right
+ if (hours > 0) {
+ sprintf(left, "%02d", hours);
+ sprintf(right, "%02d", minutes);
+ } else {
+ sprintf(left, "%02d", minutes);
+ sprintf(right, "%02d", seconds);
+ }
+
+ // Adjust position if the first character is '1'
+ if (left[0] == '1') {
+ xLeft += 20;
+ }
+ if (right[0] == '1') {
+ xRight += 20;
+ }
+
+ // Draw the left value (hours or minutes)
+ oled.setTextColor(1);
+ oled.setTextSize(5);
+ oled.setFont(&Org_01);
+ oled.setCursor(xLeft, 36);
+ oled.print(left);
+
+ // Draw the right value (minutes or seconds)
+ oled.setCursor(xRight, 36);
+ oled.print(right);
+
+ // Separator dots
+ oled.fillRect(62, 31, 5, 5, 1);
+ oled.fillRect(62, 21, 5, 5, 1);
+
+ sprintf(secondsStr, "%02d", seconds);
+
+ int xSeconds = 54;
+ if (secondsStr[0] == '1') {
+ xSeconds += 8; // Offset by 8 if the first char is '1'
+ }
+
+ oled.setTextSize(2);
+ oled.setCursor(xSeconds, 58);
+ oled.print(secondsStr);
+
+ // Draw icons and labels
+ oled.drawBitmap(61, 3, icon_star, 7, 7, 1);
+ oled.setTextSize(1);
+ oled.setCursor(27, 54);
+ oled.print(hours > 0 ? "H" : "M");
+ oled.setCursor(98, 54);
+ oled.print(hours > 0 ? "M" : "S");
+
+ oled.display();
+}
+
+void DisplayController::drawPausedScreen(int remainingSeconds) {
+ if (isAnimationRunning()) return;
+
+ oled.clearDisplay();
+
+ if (remainingSeconds < 0) {
+ remainingSeconds = 0;
+ }
+
+ int hours = remainingSeconds / 3600;
+ int minutes = (remainingSeconds % 3600) / 60;
+ int seconds = remainingSeconds % 60;
+
+ char left[3], right[3];
+ int xLeft = 1;
+ int xRight = 73;
+
+ // Format left and right
+ if (hours > 0) {
+ sprintf(left, "%02d", hours);
+ sprintf(right, "%02d", minutes);
+ } else {
+ sprintf(left, "%02d", minutes);
+ sprintf(right, "%02d", seconds);
+ }
+
+ // Adjust position if the first character is '1'
+ if (left[0] == '1') {
+ xLeft += 20;
+ }
+ if (right[0] == '1') {
+ xRight += 20;
+ }
+
+ if ((millis() / 400) % 2 == 0) {
+ oled.setTextColor(1);
+ oled.setTextSize(5);
+ oled.setFont(&Org_01);
+ oled.setCursor(xLeft, 36);
+ oled.print(left);
+ oled.setCursor(xRight, 36);
+ oled.print(right);
+
+ oled.fillRect(62, 31, 5, 5, 1);
+ oled.fillRect(62, 22, 5, 5, 1);
+
+ oled.setFont(&Org_01);
+ oled.setTextSize(1);
+ oled.setCursor(27, 54);
+ oled.print(hours > 0 ? "H" : "M");
+ oled.setCursor(98, 54);
+ oled.print(hours > 0 ? "M" : "S");
+ }
+
+ // Draw label and icon
+ oled.drawRoundRect(47, 51, 35, 11, 1, 1);
+ oled.setTextColor(1);
+ oled.setTextSize(1);
+ oled.setFont(&Picopixel);
+ oled.setCursor(53, 58);
+ oled.print("PAUSED");
+ oled.drawBitmap(60, 2, icon_pause, 9, 9, 1);
+
+ oled.display();
+}
+
+void DisplayController::drawResetScreen(bool resetSelected) {
+ if (isAnimationRunning()) return;
+ oled.clearDisplay();
+
+ // Static UI elements
+ oled.setTextColor(1);
+ oled.setTextSize(2);
+ oled.setFont(&Picopixel);
+ oled.setCursor(54, 15);
+ oled.print("RESET");
+ oled.setTextSize(1);
+ oled.setCursor(20, 30);
+ oled.print("ALL STORED SETTINGS WILL ");
+ oled.setCursor(21, 40);
+ oled.print("BE PERMANENTLY ERASED.");
+ oled.drawBitmap(35, 4, icon_reset, 13, 16, 1);
+
+ // Change only the rectangle fill and text color based on selection
+ if (resetSelected) {
+ // "RESET" filled, "CANCEL" outlined
+ oled.fillRoundRect(67, 49, 37, 11, 1, 1);
+ oled.setTextColor(0);
+ oled.setCursor(76, 56);
+ oled.print("RESET");
+
+ oled.drawRoundRect(24, 49, 37, 11, 1, 1);
+ oled.setTextColor(1);
+ oled.setCursor(31, 56);
+ oled.print("CANCEL");
+ } else {
+ // "CANCEL" filled, "RESET" outlined
+ oled.fillRoundRect(24, 49, 37, 11, 1, 1);
+ oled.setTextColor(0);
+ oled.setCursor(31, 56);
+ oled.print("CANCEL");
+
+ oled.drawRoundRect(67, 49, 37, 11, 1, 1);
+ oled.setTextColor(1);
+ oled.setCursor(76, 56);
+ oled.print("RESET");
+ }
+
+ oled.display();
+}
+
+void DisplayController::drawDoneScreen() {
+ if (isAnimationRunning()) return;
+
+ static unsigned long lastBlinkTime = 0;
+ static bool blinkState = true;
+
+ unsigned long currentTime = millis();
+
+ // Toggle blink every 500 ms
+ if (currentTime - lastBlinkTime >= 500) {
+ blinkState = !blinkState;
+ lastBlinkTime = currentTime;
+ }
+
+ oled.clearDisplay();
+
+ if (blinkState) {
+ oled.setTextColor(1);
+ oled.setTextSize(5);
+ oled.setFont(&Org_01);
+ oled.setCursor(1, 36);
+ oled.print("00");
+ oled.setCursor(73, 36);
+ oled.print("00");
+ oled.fillRect(62, 31, 5, 5, 1);
+ oled.fillRect(62, 21, 5, 5, 1);
+ }
+
+ // Draw label and icon
+ oled.fillRoundRect(46, 51, 35, 11, 1, 1);
+ oled.setTextColor(0);
+ oled.setTextSize(1);
+ oled.setFont(&Picopixel);
+ oled.setCursor(56, 58);
+ oled.print("DONE");
+ oled.drawBitmap(61, 3, icon_star, 7, 7, 1);
+
+ oled.display();
+}
+
+
+void DisplayController::drawAdjustScreen(int duration) {
+ if (isAnimationRunning()) return;
+
+ oled.clearDisplay();
+
+ oled.setTextColor(1);
+ oled.setTextSize(4);
+ oled.setFont(&Org_01);
+
+ int hours = duration / 60;
+ int minutes = duration % 60;
+
+ char hourStr[3];
+ char minuteStr[3];
+
+ // Format hour and minute strings with leading zeros
+ sprintf(hourStr, "%02d", hours);
+ sprintf(minuteStr, "%02d", minutes);
+
+ // Default positions for hours and minutes
+ int xHour = 13;
+ int xMinute = 72;
+
+ // Check the first character and adjust position if '1'
+ if (hourStr[0] == '1') {
+ xHour += 15;
+ }
+ if (minuteStr[0] == '1') {
+ xMinute += 15;
+ }
+
+ // Display hours
+ oled.setCursor(xHour, 37);
+ oled.print(hourStr);
+
+ // Display minutes
+ oled.setCursor(xMinute, 37);
+ oled.print(minuteStr);
+
+ // Display labels
+ oled.setTextSize(1);
+ oled.setCursor(26, 55);
+ oled.print("HRS");
+ oled.setCursor(86, 55);
+ oled.print("MIN");
+
+ // Additional UI elements
+ oled.drawBitmap(0, 12, image_change_left, 7, 40, 1);
+ oled.drawRoundRect(36, 1, 57, 11, 1, 1);
+ oled.drawBitmap(121, 12, image_change_right, 7, 40, 1);
+ oled.setFont(&Picopixel);
+ oled.setCursor(41, 8);
+ oled.print("PRESS TO SAVE");
+ oled.drawBitmap(103, 3, icon_arrow_down, 5, 7, 1);
+ oled.drawBitmap(21, 3, icon_arrow_down, 5, 7, 1);
+
+ oled.display();
+}
+
+
+void DisplayController::drawProvisionScreen() {
+ if (isAnimationRunning()) return;
+
+ oled.clearDisplay();
+
+ oled.setTextColor(1);
+ oled.setTextSize(1);
+ oled.setFont(&Picopixel);
+ oled.setCursor(12, 38);
+ oled.print("PLEASE CONNECT TO BLUETOOTH");
+ oled.setCursor(14, 48);
+ oled.print("AND THIS FOCUSDIAL NETWORK");
+ oled.setCursor(35, 58);
+ oled.print("TO PROVISION WIFI");
+ oled.drawBitmap(39, 4, provision_logo, 51, 23, 1);
+
+ oled.display();
+}
+
+void DisplayController::clear() {
+ oled.clearDisplay();
+ oled.display();
+}
+
+void DisplayController::showAnimation(const byte frames[][288], int frameCount, bool loop, bool reverse, unsigned long durationMs, int width, int height) {
+ animation.start(&frames[0][0], frameCount, loop, reverse, durationMs, width, height); // Pass array as pointer
+}
+
+void DisplayController::updateAnimation() {
+ animation.update();
+}
+
+bool DisplayController::isAnimationRunning() {
+ return animation.isRunning();
+}
+
+void DisplayController::showConfirmation() {
+ showAnimation(animation_tick, 20);
+}
+
+void DisplayController::showCancel() {
+ showAnimation(animation_cancel, 18, false, true);
+}
+
+void DisplayController::showReset() {
+ showAnimation(animation_reset, 28, true, false);
+}
+
+void DisplayController::showConnected() {
+ showAnimation(animation_wifi, 28);
+}
+
+void DisplayController::showTimerStart() {
+ showAnimation(animation_timer_start, 20, false, true);
+}
+
+void DisplayController::showTimerDone() {
+ showAnimation(animation_timer_start, 20);
+}
+
+void DisplayController::showTimerPause() {
+ showAnimation(animation_resume, 18, false, true);
+}
+
+void DisplayController::showTimerResume() {
+ showAnimation(animation_resume, 18);
+}
diff --git a/firmware/src/controllers/InputController.cpp b/firmware/src/controllers/InputController.cpp
new file mode 100644
index 0000000..98841a6
--- /dev/null
+++ b/firmware/src/controllers/InputController.cpp
@@ -0,0 +1,141 @@
+#include "controllers/InputController.h"
+#include
+
+static InputController *instancePtr = nullptr; // Global pointer for the ISR
+
+void InputController::handleEncoderInterrupt()
+{
+ if (instancePtr)
+ {
+ instancePtr->encoder.tick();
+ }
+}
+
+void InputController::handleButtonInterrupt()
+{
+ if (instancePtr)
+ {
+ instancePtr->button.tick();
+ }
+}
+
+InputController::InputController(uint8_t buttonPin, uint8_t encoderPinA, uint8_t encoderPinB)
+ : button(buttonPin, true),
+ encoder(encoderPinA, encoderPinB, RotaryEncoder::LatchMode::TWO03),
+ lastPosition(0),
+ buttonPin(buttonPin),
+ encoderPinA(encoderPinA),
+ encoderPinB(encoderPinB)
+{
+
+ // Attach click, double-click, and long-press handlers using OneButton library
+ button.attachClick([](void *scope)
+ { static_cast(scope)->onButtonClick(); }, this);
+ button.attachDoubleClick([](void *scope)
+ { static_cast(scope)->onButtonDoubleClick(); }, this);
+ button.attachLongPressStart([](void *scope)
+ { static_cast(scope)->onButtonLongPress(); }, this);
+
+ instancePtr = this; // Set the global instance pointer to this instance
+}
+
+void InputController::begin()
+{
+ button.setDebounceMs(20);
+ button.setClickMs(150);
+ button.setPressMs(400);
+ lastPosition = encoder.getPosition();
+
+ pinMode(buttonPin, INPUT_PULLUP);
+ pinMode(encoderPinA, INPUT_PULLUP);
+ pinMode(encoderPinB, INPUT_PULLUP);
+
+ // Set up interrupts for encoder handling
+ attachInterrupt(digitalPinToInterrupt(encoderPinA), handleEncoderInterrupt, CHANGE);
+ attachInterrupt(digitalPinToInterrupt(encoderPinB), handleEncoderInterrupt, CHANGE);
+
+ // Set up interrupt for button handling
+ attachInterrupt(digitalPinToInterrupt(buttonPin), handleButtonInterrupt, CHANGE); // Interrupt on button state change
+}
+
+void InputController::update()
+{
+ button.tick();
+ encoder.tick();
+
+ // Check encoder position and calculate delta
+ int currentPosition = encoder.getPosition();
+ int delta = currentPosition - lastPosition;
+
+ if (delta != 0)
+ {
+ onEncoderRotate(delta);
+ lastPosition = currentPosition;
+ }
+}
+
+// Register state-specific handlers
+void InputController::onPressHandler(std::function handler)
+{
+ pressHandler = handler;
+}
+
+void InputController::onDoublePressHandler(std::function handler)
+{
+ doublePressHandler = handler;
+}
+
+void InputController::onLongPressHandler(std::function handler)
+{
+ longPressHandler = handler;
+}
+
+void InputController::onEncoderRotateHandler(std::function handler)
+{
+ encoderRotateHandler = handler;
+}
+
+// Method to release all handlers
+void InputController::releaseHandlers()
+{
+ pressHandler = nullptr;
+ doublePressHandler = nullptr;
+ longPressHandler = nullptr;
+ encoderRotateHandler = nullptr;
+
+ button.reset(); // Reset button state machine
+ lastPosition = encoder.getPosition(); // Reset encoder position tracking
+}
+
+// Internal event handlers that call the registered state handlers
+void InputController::onButtonClick()
+{
+ if (pressHandler != nullptr)
+ {
+ pressHandler();
+ }
+}
+
+void InputController::onButtonDoubleClick()
+{
+ if (doublePressHandler != nullptr)
+ {
+ doublePressHandler();
+ }
+}
+
+void InputController::onButtonLongPress()
+{
+ if (longPressHandler != nullptr)
+ {
+ longPressHandler();
+ }
+}
+
+void InputController::onEncoderRotate(int delta)
+{
+ if (encoderRotateHandler != nullptr)
+ {
+ encoderRotateHandler(delta); // Pass delta to the handler
+ }
+}
diff --git a/firmware/src/controllers/LedController.cpp b/firmware/src/controllers/LedController.cpp
new file mode 100644
index 0000000..ce49d01
--- /dev/null
+++ b/firmware/src/controllers/LedController.cpp
@@ -0,0 +1,241 @@
+#include "controllers/LedController.h"
+
+LEDController::LEDController(uint8_t ledPin, uint16_t numLeds, uint8_t brightness)
+ : leds(numLeds, ledPin),
+ numLeds(numLeds),
+ brightness(brightness),
+ currentAnimation(None),
+ lastUpdateTime(0),
+ currentStep(0),
+ currentCycle(0),
+ decayStarted(false) {}
+
+void LEDController::begin()
+{
+ leds.begin();
+ leds.setBrightness(brightness);
+ leds.show();
+}
+
+void LEDController::update()
+{
+ switch (currentAnimation)
+ {
+ case FillAndDecay:
+ handleFillAndDecay();
+ break;
+ case Spinner:
+ handleSpinner();
+ break;
+ case Breath:
+ handleBreath();
+ break;
+ default:
+ break;
+ }
+}
+
+void LEDController::startFillAndDecay(uint32_t color, uint32_t totalDuration)
+{
+ stopCurrentAnimation();
+ currentAnimation = FillAndDecay;
+ animationColor = color;
+ animationDuration = totalDuration;
+ currentStep = 0;
+ pixelIndex = 0;
+ brightnessLevel = brightness;
+ lastUpdateTime = millis();
+}
+
+void LEDController::setSpinner(uint32_t color, int cycles)
+{
+ stopCurrentAnimation();
+ currentAnimation = Spinner;
+ animationColor = color;
+ animationCycles = cycles;
+ currentCycle = 0;
+ currentStep = 0;
+ lastUpdateTime = millis();
+}
+
+void LEDController::setBreath(uint32_t color, int cycles, bool endFilled, uint32_t speed)
+{
+ stopCurrentAnimation();
+ currentAnimation = Breath;
+ animationColor = color;
+ animationCycles = cycles;
+ this->endFilled = endFilled;
+ animationSpeed = speed;
+ currentCycle = 0;
+ currentStep = 0;
+ lastUpdateTime = millis();
+}
+
+void LEDController::setSolid(uint32_t color)
+{
+ stopCurrentAnimation();
+ leds.fill(color);
+ leds.show();
+}
+
+void LEDController::turnOff()
+{
+ stopCurrentAnimation();
+ leds.clear();
+ leds.show();
+}
+
+uint32_t LEDController::scaleColor(uint32_t color, uint8_t brightnessLevel)
+{
+ uint8_t r = (color >> 16 & 0xFF) * brightnessLevel / 255;
+ uint8_t g = (color >> 8 & 0xFF) * brightnessLevel / 255;
+ uint8_t b = (color & 0xFF) * brightnessLevel / 255;
+ return leds.Color(r, g, b);
+}
+
+void LEDController::handleFillAndDecay()
+{
+ uint32_t fillDuration = 300; // Initial fill duration
+ uint32_t decayDuration = animationDuration - fillDuration;
+ uint32_t totalSteps = (numLeds + 1) * brightness;
+ uint32_t stepDuration = decayDuration / totalSteps;
+
+ if (currentStep < numLeds)
+ {
+ // Quick fill phase
+ uint32_t stepDurationFill = fillDuration / numLeds;
+ if (millis() - lastUpdateTime >= stepDurationFill)
+ {
+ leds.setPixelColor(currentStep, scaleColor(animationColor, brightness));
+ leds.show();
+ currentStep++;
+ lastUpdateTime = millis();
+ }
+ }
+ else
+ {
+ // Initialize decay phase
+ if (!decayStarted)
+ {
+ decayStarted = true;
+ pixelIndex = 1;
+ brightnessLevel = brightness;
+ lastUpdateTime = millis();
+ }
+
+ // Decay phase
+ if (millis() - lastUpdateTime >= stepDuration)
+ {
+ lastUpdateTime = millis();
+
+ if (brightnessLevel > 0)
+ {
+ brightnessLevel--;
+ leds.setPixelColor(pixelIndex, scaleColor(animationColor, brightnessLevel));
+ leds.show();
+ }
+ else
+ {
+ leds.setPixelColor(pixelIndex, 0);
+ leds.show();
+ pixelIndex++;
+ brightnessLevel = brightness;
+ }
+
+ if (pixelIndex > numLeds)
+ {
+ stopCurrentAnimation();
+ }
+ }
+ }
+}
+
+void LEDController::handleSpinner()
+{
+ uint32_t stepDuration = 100;
+ if (millis() - lastUpdateTime >= stepDuration)
+ {
+ leds.clear();
+ for (int i = 0; i < numLeds; i++)
+ {
+ leds.setPixelColor((i + currentStep) % numLeds, scaleColor(animationColor, i * 255 / numLeds));
+ }
+ leds.show();
+ currentStep++;
+ lastUpdateTime = millis();
+
+ if (currentStep >= numLeds)
+ {
+ currentStep = 0;
+ currentCycle++;
+ if (animationCycles != -1 && currentCycle >= animationCycles)
+ {
+ stopCurrentAnimation();
+ }
+ }
+ }
+}
+
+void LEDController::handleBreath()
+{
+ if (millis() - lastUpdateTime >= animationSpeed)
+ {
+ uint8_t fadeBrightness = (currentStep <= 127) ? currentStep * 2 : (255 - currentStep) * 2;
+
+ for (int i = 0; i < numLeds; i++)
+ {
+ leds.setPixelColor(i, scaleColor(animationColor, fadeBrightness));
+ }
+ leds.show();
+ currentStep++;
+
+ if (currentStep >= 255)
+ {
+ currentStep = 0;
+ currentCycle++;
+
+ // Adjust the number of cycles if `endFilled` is true
+ int effectiveCycles = animationCycles;
+ if (endFilled && effectiveCycles > 0)
+ {
+ effectiveCycles--;
+ }
+
+ if (effectiveCycles != -1 && currentCycle >= effectiveCycles)
+ {
+ if (endFilled)
+ {
+ // Additional half cycle to fill the LEDs
+ for (int i = 0; i < numLeds; i++)
+ {
+ leds.setPixelColor(i, animationColor);
+ }
+ leds.show();
+ }
+ else
+ {
+ turnOff();
+ }
+ stopCurrentAnimation();
+ }
+ }
+ lastUpdateTime = millis();
+ }
+}
+
+void LEDController::stopCurrentAnimation()
+{
+ currentAnimation = None;
+ currentStep = 0;
+ currentCycle = 0;
+ pixelIndex = 0;
+ brightnessLevel = brightness;
+ decayStarted = false;
+ lastUpdateTime = millis();
+}
+
+void LEDController::printDebugInfo()
+{
+ Serial.printf("Anim: %d, Step: %d, Cycle: %d, PixelIdx: %d, Leds numb: %d, Brightness: %d, Color: 0x%06X, Dur: %lu, Speed: %lu, Cycles: %d, EndFilled: %d\n",
+ currentAnimation, currentStep, currentCycle, pixelIndex, numLeds, brightness, animationColor, animationDuration, animationSpeed, animationCycles, endFilled);
+}
\ No newline at end of file
diff --git a/firmware/src/controllers/NetworkController.cpp b/firmware/src/controllers/NetworkController.cpp
new file mode 100644
index 0000000..d5c3f37
--- /dev/null
+++ b/firmware/src/controllers/NetworkController.cpp
@@ -0,0 +1,511 @@
+#include "Config.h"
+#include "controllers/NetworkController.h"
+
+#include
+#include
+#include
+#include
+#include
+
+NetworkController *NetworkController::instance = nullptr;
+
+NetworkController::NetworkController()
+ : a2dp_sink(),
+ btPaired(false),
+ bluetoothActive(false),
+ bluetoothAttempted(false),
+ lastBluetoothtAttempt(0),
+ bluetoothTaskHandle(nullptr),
+ webhookQueue(nullptr),
+ webhookTaskHandle(nullptr),
+ provisioningMode(false)
+{
+
+ instance = this;
+}
+
+void NetworkController::begin()
+{
+ WiFiProvisionerSettings();
+
+ if (isWiFiProvisioned())
+ {
+ Serial.println("Stored WiFi credentials found. Connecting...");
+ wifiProvisioner.connectToWiFi();
+ }
+
+ // Load bluetooth paired state from nvs
+ preferences.begin("network", true);
+ btPaired = preferences.getBool("bt_paired", false);
+ preferences.end();
+
+ if (btPaired)
+ {
+ Serial.println("Previously paired with a device. Initializing Bluetooth.");
+ initializeBluetooth(); // Initialize Bluetooth if previously paired
+ }
+ else
+ {
+ Serial.println("No previous Bluetooth pairing found. Skipping Bluetooth initialization.");
+ }
+
+ // Load Webhook URL from NVS under the "focusdial" namespace
+ preferences.begin("focusdial", true);
+ webhookURL = preferences.getString("webhook_url", "");
+ preferences.end();
+
+ if (!webhookURL.isEmpty())
+ {
+ Serial.println("Loaded Webhook URL: " + webhookURL);
+ }
+
+ if (webhookQueue == nullptr)
+ {
+ webhookQueue = xQueueCreate(5, sizeof(char *));
+ }
+
+ if (webhookTaskHandle == nullptr)
+ {
+ xTaskCreatePinnedToCore(webhookTask, "Webhook Task", 4096, this, 0, &webhookTaskHandle, 1);
+ Serial.println("Persistent webhook task started.");
+ }
+}
+
+void NetworkController::update()
+{
+ if (WiFi.status() != WL_CONNECTED)
+ {
+ WiFi.reconnect();
+ }
+}
+
+bool NetworkController::isWiFiProvisioned()
+{
+ // Check for stored WiFi credentials
+ preferences.begin("network", true);
+ String storedSSID = preferences.getString("ssid", "");
+ preferences.end();
+
+ return !storedSSID.isEmpty(); // Return true if credentials are found
+}
+
+bool NetworkController::isWiFiConnected()
+{
+ return (WiFi.status() == WL_CONNECTED);
+}
+
+bool NetworkController::isBluetoothPaired()
+{
+ return btPaired;
+}
+
+void NetworkController::startProvisioning()
+{
+ Serial.println("Starting provisioning mode...");
+ btPaired = false; // Reset paired state for new provisioning
+ bluetoothActive = true; // Enable Bluetooth for pairing
+ provisioningMode = true; // Indicate we are in provisioning mode
+ initializeBluetooth();
+ wifiProvisioner.setupAccessPointAndServer();
+}
+
+void NetworkController::stopProvisioning()
+{
+ Serial.println("Stopping provisioning mode...");
+ bluetoothActive = false; // Disable Bluetooth after provisioning
+ provisioningMode = false; // Exit provisioning mode
+ stopBluetooth();
+}
+
+void NetworkController::reset()
+{
+ wifiProvisioner.resetCredentials();
+ if (btPaired)
+ {
+ a2dp_sink.clean_last_connection();
+ saveBluetoothPairedState(false);
+ }
+ Serial.println("Reset complete. WiFi credentials and paired state cleared.");
+}
+
+void NetworkController::initializeBluetooth()
+{
+ if (bluetoothTaskHandle == nullptr)
+ {
+
+ // Configure the A2DP sink with empty callbacks to use it for the trigger only
+ a2dp_sink.set_stream_reader(nullptr, false);
+ a2dp_sink.set_raw_stream_reader(nullptr);
+ a2dp_sink.set_on_volumechange(nullptr);
+ a2dp_sink.set_avrc_connection_state_callback(nullptr);
+ a2dp_sink.set_avrc_metadata_callback(nullptr);
+ a2dp_sink.set_avrc_rn_playstatus_callback(nullptr);
+ a2dp_sink.set_avrc_rn_track_change_callback(nullptr);
+ a2dp_sink.set_avrc_rn_play_pos_callback(nullptr);
+ a2dp_sink.set_spp_active(false);
+ a2dp_sink.set_output_active(false);
+ a2dp_sink.set_rssi_active(false);
+
+ a2dp_sink.set_on_connection_state_changed(btConnectionStateCallback, this);
+
+ Serial.println("Bluetooth A2DP Sink configured.");
+
+ // Create task for handling Bluetooth
+ xTaskCreate(bluetoothTask, "Bluetooth Task", 4096, this, 0, &bluetoothTaskHandle);
+ }
+}
+
+void NetworkController::startBluetooth()
+{
+ if (btPaired)
+ { // Only start if paired
+ bluetoothActive = true;
+ }
+}
+
+void NetworkController::stopBluetooth()
+{
+ bluetoothActive = false; // Stop Bluetooth activity
+}
+
+void NetworkController::btConnectionStateCallback(esp_a2d_connection_state_t state, void *obj)
+{
+ auto *self = static_cast(obj);
+
+ if (state == ESP_A2D_CONNECTION_STATE_CONNECTED)
+ {
+ Serial.println("Bluetooth device connected.");
+
+ // Save paired state only in provisioning mode
+ if (self->provisioningMode)
+ {
+ self->saveBluetoothPairedState(true);
+ self->btPaired = true;
+ Serial.println("Paired state saved during provisioning.");
+ }
+ }
+ else if (state == ESP_A2D_CONNECTION_STATE_DISCONNECTED)
+ {
+ Serial.println("Bluetooth device disconnected.");
+ // No need to set flags; task loop will handle reconnection logic based on is_connected()
+ }
+}
+
+void NetworkController::saveBluetoothPairedState(bool paired)
+{
+ preferences.begin("network", false);
+ preferences.putBool("bt_paired", paired);
+ preferences.end();
+ btPaired = paired;
+ Serial.println("Bluetooth pairing state saved in NVS.");
+}
+
+void NetworkController::bluetoothTask(void *param)
+{
+ NetworkController *self = static_cast(param);
+
+ while (true)
+ {
+ // If in provisioning mode, start Bluetooth only once
+ if (self->provisioningMode)
+ {
+ if (!self->bluetoothAttempted)
+ {
+ Serial.println("Starting Bluetooth for provisioning...");
+ self->a2dp_sink.start("Focus Dial", true);
+ self->bluetoothAttempted = true; // Mark as attempted to prevent repeated starts
+ }
+ }
+ else
+ {
+ // Normal operation mode
+ if (self->bluetoothActive && !self->bluetoothAttempted)
+ {
+ Serial.println("Starting Bluetooth...");
+ self->a2dp_sink.start("Focus Dial", true); // Auto-reconnect enabled
+ self->bluetoothAttempted = true;
+ self->lastBluetoothtAttempt = millis(); // Record the time of the start attempt
+ }
+
+ // If Bluetooth is active but not connected, attempt reconnect every 2 seconds
+ if (self->bluetoothActive && !self->a2dp_sink.is_connected() && (millis() - self->lastBluetoothtAttempt >= 2000))
+ {
+ Serial.println("Attempting Bluetooth reconnect...");
+ self->a2dp_sink.start("Focus Dial", true);
+ self->lastBluetoothtAttempt = millis(); // Update last attempt time
+ }
+
+ // If Bluetooth is not supposed to be active but is connected, disconnect
+ if (!self->bluetoothActive && self->a2dp_sink.is_connected())
+ {
+ Serial.println("Stopping Bluetooth...");
+ self->a2dp_sink.disconnect();
+ self->bluetoothAttempted = false; // Allow re-attempt later
+ }
+ }
+
+ vTaskDelay(100 / portTICK_PERIOD_MS);
+ }
+}
+
+void NetworkController::sendWebhookAction(const String &action)
+{
+ if (webhookQueue == nullptr)
+ {
+ webhookQueue = xQueueCreate(5, sizeof(char *));
+ }
+
+ char *actionCopy = strdup(action.c_str());
+ if (actionCopy == nullptr)
+ {
+ Serial.println("Failed to allocate memory for webhook action.");
+ return;
+ }
+
+ if (xQueueSend(webhookQueue, &actionCopy, 0) == pdPASS)
+ {
+ Serial.println("Webhook action enqueued: " + String(actionCopy));
+ }
+ else
+ {
+ Serial.println("Failed to enqueue webhook action: Queue is full.");
+ free(actionCopy); // Free the memory if not enqueued
+ }
+}
+
+void NetworkController::webhookTask(void *param)
+{
+ NetworkController *self = static_cast(param);
+ char *action;
+
+ while (true)
+ {
+ // Wait for a webhook action to arrive in the queue
+ if (xQueueReceive(self->webhookQueue, &action, portMAX_DELAY) == pdPASS)
+ {
+ Serial.println("Processing webhook action: " + String(action));
+
+ // Send the webhook request and check the response
+ bool success = self->sendWebhookRequest(String(action));
+ if (success)
+ {
+ Serial.println("Webhook action sent successfully.");
+ }
+ else
+ {
+ Serial.println("Failed to send webhook action.");
+ }
+
+ free(action); // Free the allocated memory for action
+
+ Serial.println("Finished processing webhook action.");
+ }
+
+ // Small delay to yield
+ vTaskDelay(10 / portTICK_PERIOD_MS);
+ }
+}
+
+bool NetworkController::sendWebhookRequest(const String &action)
+{
+ if (webhookURL.isEmpty())
+ {
+ Serial.println("Webhook URL is not set. Cannot send action.");
+ return false;
+ }
+
+ std::unique_ptr client;
+ if (webhookURL.startsWith("https://"))
+ {
+ client.reset(new WiFiClientSecure());
+ if (!client)
+ {
+ Serial.println("Memory allocation for WiFiClientSecure failed.");
+ return false;
+ }
+ static_cast(client.get())->setInsecure(); // Not verifying server certificate
+ }
+ else
+ {
+ client.reset(new WiFiClient());
+ if (!client)
+ {
+ Serial.println("Memory allocation for WiFiClient failed.");
+ return false;
+ }
+ }
+
+ HTTPClient http;
+ bool result = false;
+
+ if (http.begin(*client, webhookURL))
+ {
+ http.addHeader("Content-Type", "application/json");
+
+ String jsonPayload = "{\"action\":\"" + action + "\"}";
+
+ // Send the POST request
+ int httpResponseCode = http.POST(jsonPayload);
+
+ if (httpResponseCode > 0)
+ {
+ String response = http.getString();
+ Serial.println("HTTP Response code: " + String(httpResponseCode));
+ Serial.println("Response: " + response);
+ result = true;
+ }
+ else
+ {
+ Serial.println("Error in sending POST: " + String(httpResponseCode));
+ }
+
+ http.end(); // Close the connection
+ }
+ else
+ {
+ Serial.println("Unable to connect to server.");
+ }
+
+ return result;
+}
+
+void NetworkController::WiFiProvisionerSettings()
+{
+ wifiProvisioner.enableSerialDebug(true);
+ wifiProvisioner.AP_NAME = "Focus Dial";
+ wifiProvisioner.SVG_LOGO =
+ R"rawliteral(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )rawliteral";
+
+ wifiProvisioner.HTML_TITLE = "Focus Dial - Provisioning";
+ wifiProvisioner.PROJECT_TITLE = " Focus Dial — Setup";
+ wifiProvisioner.PROJECT_INFO = R"rawliteral(
+ 1. Connect to Bluetooth if you want to use the phone automation trigger.
+ 2. Select a WiFi network to save and allow Focus Dial to trigger webhook automations.
+ 3. Enter the webhook URL below to trigger it when a focus session starts.)rawliteral";
+
+ wifiProvisioner.FOOTER_INFO = R"rawliteral(
+ Focus Dial - Made by Salim Benbouziyane )rawliteral";
+
+ wifiProvisioner.CONNECTION_SUCCESSFUL =
+ "Provision Complete. Focus Dial will now start and status led will turn to blue.";
+
+ wifiProvisioner.RESET_CONFIRMATION_TEXT =
+ "This will erase all settings and require re-provisioning. Confirm on the device.";
+
+ wifiProvisioner.setShowInputField(true);
+ wifiProvisioner.INPUT_TEXT = "Webhook URL to Trigger Automation:";
+ wifiProvisioner.INPUT_PLACEHOLDER = "e.g., https://example.com/webhook";
+ wifiProvisioner.INPUT_INVALID_LENGTH = "The URL appears incomplete. Please enter the valid URL to trigger the automation.";
+ wifiProvisioner.INPUT_NOT_VALID = "The URL entered is not valid. Please verify it and try again.";
+
+ // Set the static methods as callbacks
+ wifiProvisioner.setInputCheckCallback(validateInputCallback);
+ wifiProvisioner.setFactoryResetCallback(factoryResetCallback);
+}
+
+// Static method for input validation callback
+bool NetworkController::validateInputCallback(const String &input)
+{
+ if (instance)
+ {
+ return instance->validateInput(input);
+ }
+ return false;
+}
+
+// Static method for factory reset callback
+void NetworkController::factoryResetCallback()
+{
+ if (instance)
+ {
+ instance->handleFactoryReset();
+ }
+}
+
+bool NetworkController::validateInput(const String &input)
+{
+ String modifiedInput = input;
+
+ // Check if URL starts with "http://" or "https://"
+ if (!(modifiedInput.startsWith("http://") || modifiedInput.startsWith("https://")))
+ {
+ // If none supplied assume "http://"
+ modifiedInput = "http://" + modifiedInput;
+ Serial.println("Protocol missing, defaulting to http://");
+ }
+
+ // Basic validation
+ int protocolEnd = modifiedInput.indexOf("://") + 3;
+ int dotPosition = modifiedInput.indexOf('.', protocolEnd);
+
+ bool isValid = (dotPosition != -1);
+
+ Serial.print("Validating input: ");
+ Serial.println(modifiedInput);
+
+ // Save URL to NVS here if valid
+ if (isValid)
+ {
+ Serial.println("URL is valid. Saving to NVS...");
+
+ if (preferences.begin("focusdial", false))
+ { // false means open for writing
+ preferences.putString("webhook_url", modifiedInput);
+ preferences.end();
+ webhookURL = modifiedInput;
+ Serial.println("Webhook URL saved: " + webhookURL);
+ }
+ else
+ {
+ Serial.println("Failed to open NVS for writing.");
+ }
+ }
+ else
+ {
+ Serial.println("Invalid URL. Not saving to NVS.");
+ }
+
+ return isValid;
+}
+
+void NetworkController::handleFactoryReset()
+{
+ Serial.println("Factory reset initiated.");
+ reset();
+}
\ No newline at end of file
diff --git a/firmware/src/main.cpp b/firmware/src/main.cpp
new file mode 100644
index 0000000..4da8621
--- /dev/null
+++ b/firmware/src/main.cpp
@@ -0,0 +1,31 @@
+#include
+#include "Config.h"
+#include "StateMachine.h"
+#include "Controllers.h"
+
+// Global instances of controllers
+DisplayController displayController(OLED_WIDTH, OLED_HEIGHT, OLED_ADDR);
+LEDController ledController(LED_PIN, NUM_LEDS, LED_BRIGHTNESS);
+InputController inputController(BUTTON_PIN, ENCODER_A_PIN, ENCODER_B_PIN);
+NetworkController networkController;
+Preferences preferences;
+
+void setup() {
+ Serial.begin(115200);
+
+ // Initialize controllers
+ inputController.begin();
+ displayController.begin();
+ ledController.begin();
+ networkController.begin();
+
+ // Startup state
+ stateMachine.changeState(&StateMachine::startupState);
+}
+
+void loop() {
+ // Update state machine
+ stateMachine.update();
+ // If any animation needs to run
+ displayController.updateAnimation();
+}
diff --git a/firmware/src/states/AdjustState.cpp b/firmware/src/states/AdjustState.cpp
new file mode 100644
index 0000000..b656628
--- /dev/null
+++ b/firmware/src/states/AdjustState.cpp
@@ -0,0 +1,57 @@
+#include "StateMachine.h"
+#include "Controllers.h"
+
+void AdjustState::enter()
+{
+ Serial.println("Entering Adjust State");
+
+ lastActivity = millis();
+ ledController.setSolid(AMBER);
+
+ // Register state-specific handlers
+ inputController.onPressHandler([this]()
+ {
+ Serial.println("Adjust State: Button pressed");
+
+ StateMachine::idleState.setTimer(this->adjustDuration);
+ displayController.showConfirmation();
+ stateMachine.changeState(&StateMachine::idleState); });
+
+ inputController.onEncoderRotateHandler([this](int delta)
+ {
+ Serial.println("Adjust State: Encoder turned");
+ Serial.println(delta);
+
+ // Update duration with delta and enforce bounds
+ this->adjustDuration += (delta * 5);
+ if (this->adjustDuration < MIN_TIMER) {
+ this->adjustDuration = MIN_TIMER;
+ } else if (this->adjustDuration > MAX_TIMER) {
+ this->adjustDuration = MAX_TIMER;
+ }
+
+ this->lastActivity = millis(); });
+}
+
+void AdjustState::update()
+{
+ inputController.update();
+ displayController.drawAdjustScreen(adjustDuration);
+
+ if (millis() - lastActivity >= (CHANGE_TIMEOUT * 1000))
+ {
+ // Transition to Idle
+ stateMachine.changeState(&StateMachine::idleState);
+ }
+}
+
+void AdjustState::exit()
+{
+ Serial.println("Exiting Adjust State");
+ inputController.releaseHandlers();
+}
+
+void AdjustState::adjustTimer(int duration)
+{
+ adjustDuration = duration;
+}
diff --git a/firmware/src/states/DoneState.cpp b/firmware/src/states/DoneState.cpp
new file mode 100644
index 0000000..9d76922
--- /dev/null
+++ b/firmware/src/states/DoneState.cpp
@@ -0,0 +1,41 @@
+#include "StateMachine.h"
+#include "Controllers.h"
+
+DoneState::DoneState() : doneEnter(0) {}
+
+void DoneState::enter()
+{
+ Serial.println("Entering Done State");
+
+ doneEnter = millis();
+ ledController.setBreath(GREEN, -1, true, 2);
+
+ // Register state-specific handlers
+ inputController.onPressHandler([]()
+ {
+ Serial.println("Done State: Button pressed");
+ stateMachine.changeState(&StateMachine::idleState); });
+
+ // Send 'Stop' webhook
+ networkController.sendWebhookAction("stop");
+}
+
+void DoneState::update()
+{
+ inputController.update();
+ ledController.update();
+
+ displayController.drawDoneScreen();
+
+ if (millis() - doneEnter >= (CHANGE_TIMEOUT * 1000))
+ {
+ // Transition to Idle after timeout
+ stateMachine.changeState(&StateMachine::idleState);
+ }
+}
+
+void DoneState::exit()
+{
+ Serial.println("Exiting Done State");
+ inputController.releaseHandlers();
+}
diff --git a/firmware/src/states/IdleState.cpp b/firmware/src/states/IdleState.cpp
new file mode 100644
index 0000000..c36f087
--- /dev/null
+++ b/firmware/src/states/IdleState.cpp
@@ -0,0 +1,87 @@
+#include "StateMachine.h"
+#include "Controllers.h"
+
+IdleState::IdleState() : defaultDuration(0), lastActivity(0)
+{
+
+ if (nvs_flash_init() != ESP_OK)
+ {
+ Serial.println("NVS Flash Init Failed");
+ }
+ else
+ {
+ Serial.println("NVS initialized successfully.");
+ }
+
+ // Load the default duration
+ if (preferences.begin("focusdial", true))
+ {
+ defaultDuration = preferences.getInt("timer", DEFAULT_TIMER);
+ preferences.end();
+ }
+}
+
+void IdleState::enter()
+{
+ Serial.println("Entering Idle State");
+ ledController.setBreath(BLUE, -1, false, 5);
+
+ // Register state-specific handlers
+ inputController.onPressHandler([this]()
+ {
+ Serial.println("Idle State: Button pressed");
+ StateMachine::timerState.setTimer(this->defaultDuration, 0);
+ displayController.showTimerStart();
+ stateMachine.changeState(&StateMachine::timerState); // Start timer
+ });
+
+ inputController.onLongPressHandler([this]()
+ {
+ Serial.println("Idle State: Button long pressed");
+ stateMachine.changeState(&StateMachine::resetState); // Transition to Reset State
+ });
+
+ inputController.onEncoderRotateHandler([this](int delta)
+ {
+ Serial.println("Idle State: Encoder turned");
+ StateMachine::adjustState.adjustTimer(this->defaultDuration);
+ stateMachine.changeState(&StateMachine::adjustState); // Transition to Adjust State
+ });
+
+ lastActivity = millis(); // Activity timer
+}
+
+void IdleState::update()
+{
+ static unsigned long lastUpdateTime = 0;
+
+ // Controllers updates
+ inputController.update();
+ ledController.update();
+ networkController.update();
+
+ displayController.drawIdleScreen(defaultDuration, networkController.isWiFiConnected());
+
+ // Check if sleep timeout is reached
+ if (millis() - lastActivity >= (SLEEP_TIMOUT * 60 * 1000))
+ {
+ Serial.println("Idle State: Activity timeout");
+ stateMachine.changeState(&StateMachine::sleepState); // Transition to Sleep State
+ }
+}
+
+void IdleState::exit()
+{
+ Serial.println("Exiting Idle State");
+ inputController.releaseHandlers();
+ ledController.turnOff();
+}
+
+void IdleState::setTimer(int duration)
+{
+ defaultDuration = duration;
+
+ preferences.begin("focusdial", true);
+ preferences.putInt("timer", defaultDuration);
+ preferences.end();
+}
\ No newline at end of file
diff --git a/firmware/src/states/PausedState.cpp b/firmware/src/states/PausedState.cpp
new file mode 100644
index 0000000..e9d4e86
--- /dev/null
+++ b/firmware/src/states/PausedState.cpp
@@ -0,0 +1,71 @@
+#include "StateMachine.h"
+#include "Controllers.h"
+
+PausedState::PausedState() : duration(0), elapsedTime(0), pauseEnter(0) {}
+
+void PausedState::enter()
+{
+ Serial.println("Entering Paused State");
+ pauseEnter = millis(); // Record the time when the pause started
+ ledController.setBreath(YELLOW, -1, false, 20);
+
+ // Register state-specific handlers
+ inputController.onPressHandler([this]()
+ {
+ Serial.println("Paused State: Button Pressed");
+
+ // Send 'Start' webhook (resume)
+ networkController.sendWebhookAction("start");
+
+ // Transition back to TimerState with the stored duration and elapsed time
+ StateMachine::timerState.setTimer(duration, elapsedTime);
+ displayController.showTimerResume();
+ stateMachine.changeState(&StateMachine::timerState); // Transition back to Timer State
+ });
+
+ inputController.onDoublePressHandler([]()
+ {
+ Serial.println("Paused State: Button Double Pressed");
+
+ // Send 'Stop' webhook (canceled)
+ networkController.sendWebhookAction("stop");
+ displayController.showCancel();
+ stateMachine.changeState(&StateMachine::idleState); // Transition back to Idle State
+ });
+}
+
+void PausedState::update()
+{
+ inputController.update();
+ ledController.update();
+
+ // Redraw the paused screen with remaining time
+ int remainingTime = (duration * 60) - elapsedTime;
+ displayController.drawPausedScreen(remainingTime);
+
+ unsigned long currentTime = millis();
+
+ // Check if the pause timeout has been reached
+ if (currentTime - pauseEnter >= (PAUSE_TIMEOUT * 60 * 1000))
+ {
+ // Timeout reached, transition to Idle State
+ Serial.println("Paused State: Timout");
+
+ // Send 'Stop' webhook (timeout)
+ networkController.sendWebhookAction("stop");
+ displayController.showCancel();
+ stateMachine.changeState(&StateMachine::idleState); // Transition back to Idle State
+ }
+}
+
+void PausedState::exit()
+{
+ Serial.println("Exiting Paused State");
+ inputController.releaseHandlers();
+}
+
+void PausedState::setPause(int duration, unsigned long elapsedTime)
+{
+ this->duration = duration;
+ this->elapsedTime = elapsedTime;
+}
\ No newline at end of file
diff --git a/firmware/src/states/ProvisionState.cpp b/firmware/src/states/ProvisionState.cpp
new file mode 100644
index 0000000..2d6b7ad
--- /dev/null
+++ b/firmware/src/states/ProvisionState.cpp
@@ -0,0 +1,29 @@
+#include "StateMachine.h"
+#include "Controllers.h"
+
+void ProvisionState::enter()
+{
+ Serial.println("Entering Provision State");
+ inputController.releaseHandlers();
+ displayController.drawProvisionScreen();
+ ledController.setSolid(AMBER);
+ networkController.startProvisioning();
+}
+
+void ProvisionState::update()
+{
+ ledController.update();
+ if (networkController.isWiFiProvisioned() && networkController.isWiFiConnected())
+ {
+ Serial.println("Provisioning Complete, WiFi Connected");
+ displayController.showConnected();
+ networkController.stopProvisioning();
+ stateMachine.changeState(&StateMachine::idleState);
+ }
+}
+
+void ProvisionState::exit()
+{
+ Serial.println("Exiting Provision State");
+ networkController.stopProvisioning();
+}
diff --git a/firmware/src/states/ResetState.cpp b/firmware/src/states/ResetState.cpp
new file mode 100644
index 0000000..6132494
--- /dev/null
+++ b/firmware/src/states/ResetState.cpp
@@ -0,0 +1,54 @@
+#include "StateMachine.h"
+#include "Controllers.h"
+
+bool resetSelected = false; // button selection
+
+void ResetState::enter()
+{
+ Serial.println("Entering Reset State");
+
+ ledController.setBreath(MAGENTA, -1, false, 10);
+
+ // Register state-specific handlers
+ inputController.onEncoderRotateHandler([this](int delta)
+ {
+ if (delta > 0) {
+ resetSelected = true; // Select "RESET"
+ } else if (delta < 0) {
+ resetSelected = false; // Select "CANCEL"
+ } });
+
+ inputController.onPressHandler([this]()
+ {
+ if (resetSelected) {
+ Serial.println("Reset State: RESET button pressed, rebooting.");
+ displayController.showReset();
+ networkController.reset();
+ resetStartTime = millis();
+ } else {
+ Serial.println("Reset State: CANCEL button pressed, returning to Idle.");
+ displayController.showCancel();
+ stateMachine.changeState(&StateMachine::idleState);
+ } });
+}
+
+void ResetState::update()
+{
+
+ inputController.update();
+ ledController.update();
+ displayController.drawResetScreen(resetSelected);
+
+ if (resetStartTime > 0 && (millis() - resetStartTime >= 1000))
+ {
+ Serial.println("Restarting ...");
+ ESP.restart(); // Restart after 1 second
+ }
+}
+
+void ResetState::exit()
+{
+ Serial.println("Exiting Reset State");
+ inputController.releaseHandlers();
+ ledController.turnOff();
+}
diff --git a/firmware/src/states/SleepState.cpp b/firmware/src/states/SleepState.cpp
new file mode 100644
index 0000000..c0c643d
--- /dev/null
+++ b/firmware/src/states/SleepState.cpp
@@ -0,0 +1,37 @@
+#include "StateMachine.h"
+#include "Controllers.h"
+
+void SleepState::enter()
+{
+ Serial.println("Entering Sleep State");
+
+ ledController.turnOff();
+ displayController.clear();
+
+ // Register state-specific handlers
+ inputController.onPressHandler([]()
+ {
+ Serial.println("Sleep State: Button pressed");
+ stateMachine.changeState(&StateMachine::idleState); });
+
+ inputController.onLongPressHandler([]()
+ {
+ Serial.println("Sleep State: long pressed");
+ stateMachine.changeState(&StateMachine::idleState); });
+
+ inputController.onEncoderRotateHandler([this](int delta)
+ {
+ Serial.println("Sleep State: Encoder turned");
+ stateMachine.changeState(&StateMachine::idleState); });
+}
+
+void SleepState::update()
+{
+ inputController.update();
+}
+
+void SleepState::exit()
+{
+ Serial.println("Exiting Sleep State");
+ inputController.releaseHandlers();
+}
diff --git a/firmware/src/states/StartupState.cpp b/firmware/src/states/StartupState.cpp
new file mode 100644
index 0000000..a0459cc
--- /dev/null
+++ b/firmware/src/states/StartupState.cpp
@@ -0,0 +1,37 @@
+#include "StateMachine.h"
+#include "Controllers.h"
+
+StartupState::StartupState() : startEnter(0) {}
+
+void StartupState::enter()
+{
+ Serial.println("Entering Splash State");
+
+ displayController.drawSplashScreen();
+ ledController.setSpinner(TEAL, -1);
+
+ startEnter = millis();
+}
+
+void StartupState::update()
+{
+ ledController.update();
+
+ if (millis() - startEnter >= (SPLASH_DURATION * 1000))
+ {
+ if (networkController.isWiFiProvisioned())
+ {
+ stateMachine.changeState(&StateMachine::idleState); // Transition to Idle
+ }
+ else
+ {
+ stateMachine.changeState(&StateMachine::provisionState); // Trigger Provision
+ }
+ }
+}
+
+void StartupState::exit()
+{
+ ledController.turnOff();
+ Serial.println("Exiting Splash State");
+}
diff --git a/firmware/src/states/TimerState.cpp b/firmware/src/states/TimerState.cpp
new file mode 100644
index 0000000..0d5a695
--- /dev/null
+++ b/firmware/src/states/TimerState.cpp
@@ -0,0 +1,77 @@
+#include "StateMachine.h"
+#include "Controllers.h"
+
+TimerState::TimerState() : duration(0), elapsedTime(0), startTime(0) {}
+
+void TimerState::enter()
+{
+ Serial.println("Entering Timer State");
+
+ // Start time based on the elapsed time
+ startTime = millis() - (elapsedTime * 1000);
+
+ displayController.drawTimerScreen(duration * 60);
+ ledController.startFillAndDecay(RED, ((duration * 60) - elapsedTime) * 1000);
+
+ // Register state-specific handlers
+ inputController.onPressHandler([this]()
+ {
+ Serial.println("Timer State: Button Pressed");
+
+ // Send 'Stop' webhook (pause)
+ networkController.sendWebhookAction("stop");
+ displayController.showTimerPause();
+
+ // Transition to PausedState and set elapsed time
+ StateMachine::pausedState.setPause(this->duration, this->elapsedTime); // Save current elapsed time
+ stateMachine.changeState(&StateMachine::pausedState); // Transition to Paused State
+ });
+
+ inputController.onDoublePressHandler([this]()
+ {
+ Serial.println("Timer State: Button Double Pressed");
+
+ // Send 'Stop' webhook (canceled)
+ networkController.sendWebhookAction("stop");
+ displayController.showCancel();
+ stateMachine.changeState(&StateMachine::idleState); // Transition to IdleState
+ });
+
+ networkController.startBluetooth();
+ networkController.sendWebhookAction("start");
+}
+
+void TimerState::update()
+{
+ inputController.update();
+ ledController.update();
+
+ unsigned long currentTime = millis();
+ elapsedTime = (currentTime - startTime) / 1000;
+
+ int remainingSeconds = duration * 60 - elapsedTime;
+
+ displayController.drawTimerScreen(remainingSeconds);
+
+ // Check if the timer is done
+ if (remainingSeconds <= 0)
+ {
+ Serial.println("Timer State: Done");
+ displayController.showTimerDone();
+ stateMachine.changeState(&StateMachine::doneState); // Transition to Done State
+ }
+}
+
+void TimerState::exit()
+{
+ inputController.releaseHandlers();
+ networkController.stopBluetooth();
+ ledController.turnOff();
+ Serial.println("Exiting Timer State");
+}
+
+void TimerState::setTimer(int duration, unsigned long elapsedTime)
+{
+ this->duration = duration;
+ this->elapsedTime = elapsedTime;
+}
\ No newline at end of file
diff --git a/firmware/test/README b/firmware/test/README
new file mode 100644
index 0000000..9b1e87b
--- /dev/null
+++ b/firmware/test/README
@@ -0,0 +1,11 @@
+
+This directory is intended for PlatformIO Test Runner and project tests.
+
+Unit Testing is a software testing method by which individual units of
+source code, sets of one or more MCU program modules together with associated
+control data, usage procedures, and operating procedures, are tested to
+determine whether they are fit for use. Unit testing finds problems early
+in the development cycle.
+
+More information about PlatformIO Unit Testing:
+- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
diff --git a/images/Focus-Dial_Logo.svg b/images/Focus-Dial_Logo.svg
new file mode 100644
index 0000000..e61f576
--- /dev/null
+++ b/images/Focus-Dial_Logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/images/Focus-Dial_Thumbnail.jpg b/images/Focus-Dial_Thumbnail.jpg
new file mode 100644
index 0000000..75a76bb
Binary files /dev/null and b/images/Focus-Dial_Thumbnail.jpg differ
diff --git a/platformio.ini b/platformio.ini
new file mode 100644
index 0000000..df85ed2
--- /dev/null
+++ b/platformio.ini
@@ -0,0 +1,36 @@
+; PlatformIO Project Configuration File
+;
+; Build options: build flags, source filter
+; Upload options: custom upload port, speed and extra flags
+; Library options: dependencies, extra library storages
+; Advanced options: extra scripting
+;
+; Please visit documentation for the other options and examples
+; https://docs.platformio.org/page/projectconf.html
+
+[platformio]
+default_envs = adafruit_qtpy_esp32
+src_dir = firmware/src
+include_dir = firmware/include
+lib_dir = firmware/lib
+data_dir = firmware/data
+test_dir = firmware/test
+
+[env:adafruit_qtpy_esp32]
+build_flags = -Os
+platform = espressif32
+board = adafruit_qtpy_esp32
+framework = arduino
+lib_deps =
+ mathertel/OneButton@^2.6.1
+ mathertel/RotaryEncoder@^1.5.3
+ adafruit/Adafruit GFX Library@^1.11.10
+ adafruit/Adafruit NeoPixel@^1.12.3
+ adafruit/Adafruit SSD1306@^2.5.11
+ santerilindfors/WiFiProvisioner@^1.0.0
+ https://github.com/pschatzmann/ESP32-A2DP
+ https://github.com/pschatzmann/arduino-audio-tools.git
+
+board_build.flash_size = 8MB
+board_build.partitions = firmware/partitions.csv
+monitor_speed = 115200
diff --git a/resources/ref/Adafruit QT Py ESP32-Pico Pinout.pdf b/resources/ref/Adafruit QT Py ESP32-Pico Pinout.pdf
new file mode 100644
index 0000000..328c300
Binary files /dev/null and b/resources/ref/Adafruit QT Py ESP32-Pico Pinout.pdf differ
diff --git a/resources/ref/Encoder_per56.pdf b/resources/ref/Encoder_per56.pdf
new file mode 100644
index 0000000..4fae908
Binary files /dev/null and b/resources/ref/Encoder_per56.pdf differ
diff --git a/resources/unifi_script.sh b/resources/unifi_script.sh
new file mode 100644
index 0000000..ba86196
--- /dev/null
+++ b/resources/unifi_script.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+
+# Enable or disable logging based on an input argument (0 = no debug, 1 = debug)
+debug=$7 # Pass 1 for debugging, 0 for no debugging
+
+if [[ $debug -eq 1 ]]; then
+ # Enable logging
+ exec > /config/scripts/unifi_traffic_rules.log 2>&1
+else
+ exec > /dev/null 2>&1 # Disable logging if debug is not enabled
+fi
+
+unifi_username=$2
+unifi_password=$3
+unifi_controller=$4
+target_rule_id=$5 # The rule ID you're targeting
+action=$6 # 'enable' or 'disable'
+cookie=$(mktemp)
+headers=$(mktemp)
+
+curl_cmd="curl -s -S --cookie ${cookie} --cookie-jar ${cookie} --insecure "
+
+unifi_login() {
+ # Log in to the UniFi controller and capture CSRF token from headers
+ if [[ $debug -eq 1 ]]; then echo "Logging in to UniFi Controller..."; fi
+ login_response=$(${curl_cmd} -H "Content-Type: application/json" -D ${headers} -d "{\"password\":\"$unifi_password\",\"username\":\"$unifi_username\"}" $unifi_controller/api/auth/login)
+ if [[ $debug -eq 1 ]]; then echo "Login Response: $login_response"; fi
+ csrf_token=$(awk -v IGNORECASE=1 -v FS=': ' '/^X-CSRF-Token/ {print $2}' "${headers}" | tr -d '\r')
+ if [[ $debug -eq 1 ]]; then echo "CSRF Token: $csrf_token"; fi
+}
+
+unifi_logout() {
+ # Log out from the UniFi controller
+ if [[ $debug -eq 1 ]]; then echo "Logging out of UniFi Controller..."; fi
+ logout_response=$(${curl_cmd} $unifi_controller/api/auth/logout)
+ if [[ $debug -eq 1 ]]; then echo "Logout Response: $logout_response"; fi
+}
+
+get_traffic_rules() {
+ # Fetch traffic rules
+ if [[ $debug -eq 1 ]]; then echo "Fetching traffic rules..."; fi
+ traffic_rules_response=$(${curl_cmd} "$unifi_controller/proxy/network/v2/api/site/default/trafficrules" -H "Content-Type: application/json" --compressed)
+ if [[ $debug -eq 1 ]]; then echo "Traffic Rules Response: $traffic_rules_response"; fi
+}
+
+find_and_modify_rule() {
+ # Extract the rule that matches the target rule ID
+ if [[ $debug -eq 1 ]]; then echo "Searching for rule with ID: $target_rule_id"; fi
+ rule=$(echo "$traffic_rules_response" | jq --arg rule_id "$target_rule_id" '.[] | select(._id == $rule_id)')
+
+ if [ -z "$rule" ]; then
+ echo "No matching rule found with ID: $target_rule_id"
+ exit 1
+ else
+ # Set the action based on 'enable' or 'disable'
+ if [ "$action" == "enable" ]; then
+ new_enabled_value=true
+ elif [ "$action" == "disable" ]; then
+ new_enabled_value=false
+ else
+ echo "Error: Action must be 'enable' or 'disable'."
+ exit 1
+ fi
+
+ # Modify the rule by setting 'enabled' to true or false
+ if [[ $debug -eq 1 ]]; then echo "Found rule: $rule"; fi
+ updated_rule=$(echo "$rule" | jq --argjson action "$new_enabled_value" '.enabled = $action')
+
+ # Send PUT request to modify the rule, including CSRF token in the headers
+ if [[ $debug -eq 1 ]]; then echo "Modifying rule with ID: $target_rule_id"; fi
+
+ modify_response=$(${curl_cmd} "$unifi_controller/proxy/network/v2/api/site/default/trafficrules/$target_rule_id" -X PUT \
+ -H "Content-Type: application/json" \
+ -H "X-CSRF-Token: $csrf_token" \
+ -d "$updated_rule" --compressed)
+
+ if [[ $debug -eq 1 ]]; then echo "Modify Response: $modify_response"; fi
+ fi
+}
+
+# Ensure all required parameters are provided
+if [[ $# < 7 ]]; then
+ echo "Error: Must include parameters [fwrule] [username] [password] [UDM address] [rule_id] [enable or disable] [0=debug off, 1=debug on]."
+ exit -1
+fi
+
+# Log in, get traffic rules, find the rule by ID, modify it, and log out
+unifi_login
+get_traffic_rules
+find_and_modify_rule
+unifi_logout
\ No newline at end of file