From 643c0cbc42493fb770e45de954991528d2cf49ce Mon Sep 17 00:00:00 2001 From: Chuck <33324927+ChuckBuilds@users.noreply.github.com> Date: Wed, 2 Sep 2026 18:39:08 -0400 Subject: [PATCH 1/3] fix(tide-display): load bitmap fonts at their own size, and document everything The font picker worked or not by coincidence. A .bdf exists at exactly one pixel size and FreeType rejects any other, so 4x6.bdf loaded because its native 6 happens to equal the default font_size, while 5x7.bdf silently fell back to the default face -- and the two would swap over if font_size were set to 7. Hashing one render per face showed 4x6-font.ttf and 5x7.bdf producing the same image; after the fix all five are distinct. Same fix already landed for clock-simple and news, which share this loader. The README was a 70-line stub with none of the plugin's four screens shown. It now covers all 18 settings with real rendered screenshots of every screen, taken from recorded NOAA responses for station 8443970 on 2 September 2026, and explains the thing you actually have to do first: find your station ID. Two behaviours that were undocumented and look like faults: a station without a live water-level sensor falls back to predictions rather than erroring, which is the common case; and unit conversion is done by NOAA rather than locally, so the metric heights are authoritative rather than a rounding of the imperial ones. The 32-row stats screen draws the range line and the percentage close enough to overlap at some values. Recorded as an observation with the images to show it, not diagnosed -- the chart and schedule screens are unaffected and 64 rows clears it. Tooling: the HTTP replay can now match on query parameters, not just the URL. NOAA puts three endpoints behind one URL and distinguishes them by params, and without this every request returned whichever fixture matched first. It also caught a mistake of mine: with the fixture ignoring the units parameter, metric mode rendered the imperial numbers with an "m" suffix and looked exactly like a missing conversion. Recording both unit systems and matching on the parameter shows the real metric predictions. Co-Authored-By: Claude Opus 5 --- README.md | 2 +- docs/assets/tide-display/colors.png | Bin 0 -> 19964 bytes docs/assets/tide-display/display-modes.png | Bin 0 -> 24876 bytes .../tide-display/fixtures/noaa-boston.json | 1 + docs/assets/tide-display/hero.png | Bin 0 -> 3035 bytes docs/assets/tide-display/moon-phase.png | Bin 0 -> 11940 bytes docs/assets/tide-display/panel-sizes.png | Bin 0 -> 29490 bytes docs/assets/tide-display/shots.json | 442 ++++++++++++++++++ docs/assets/tide-display/taller-panel.png | Bin 0 -> 23195 bytes docs/assets/tide-display/units.png | Bin 0 -> 8718 bytes plugins.json | 4 +- plugins/tide-display/README.md | 314 +++++++++++-- plugins/tide-display/manager.py | 30 ++ plugins/tide-display/manifest.json | 9 +- .../docs_render_support/_docs_http_replay.py | 33 +- 15 files changed, 775 insertions(+), 60 deletions(-) create mode 100644 docs/assets/tide-display/colors.png create mode 100644 docs/assets/tide-display/display-modes.png create mode 100644 docs/assets/tide-display/fixtures/noaa-boston.json create mode 100644 docs/assets/tide-display/hero.png create mode 100644 docs/assets/tide-display/moon-phase.png create mode 100644 docs/assets/tide-display/panel-sizes.png create mode 100644 docs/assets/tide-display/shots.json create mode 100644 docs/assets/tide-display/taller-panel.png create mode 100644 docs/assets/tide-display/units.png diff --git a/README.md b/README.md index 9fae8532..d1dabd94 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ curl -X POST http://your-pi-ip:5000/api/v3/plugins/install \ | Plugin | Description | Preview | |--------|-------------|---------| | [Weather Display](./plugins/ledmatrix-weather/) | Current conditions, hourly & daily forecasts (Open-Meteo) | | -| [Tide Display](./plugins/tide-display/) | Coastal tides with animated wave level, schedule & 24-hour chart (NOAA) | | +| [Tide Display](./plugins/tide-display/) | Coastal tides with animated wave level, schedule & 24-hour chart (NOAA) | tide-display on an LED panel | ### Media (2) diff --git a/docs/assets/tide-display/colors.png b/docs/assets/tide-display/colors.png new file mode 100644 index 0000000000000000000000000000000000000000..f34750b8e6c9e605814f0e2e5ba46891b2851c2f GIT binary patch literal 19964 zcmche#C!Y zT#7kC{P#8=>0hoOuZ(E^c<=kw&n?`<7r(vt?TRE^i}>Q7uPCn+6JPxH-nXku4@`&y z`194RH|@m5`S#x5UcIo>xKf;<5Laf_m6CL{Y+7l((=7+pD*>0%L6X>PC3VyNzI+|{ ziY3hb2-`pIzE&&4>{)Vl^&I5ZDC*>KNERu5BDz&ce52vZNAFx5LaW&1s26sm&NSGv z<}oLxsqbp6P%={Ey2W5yvyl;J<2D;(3O;Yv<0lBZCHETSg`LfnV)U80B)FF`n`P_U zYZOwr^^e}C90vBNHFY;SY`yq>)^S^%Vll)?-_cVv83kjAlzPo9g(u+02@H2!)<2%g zl#fx#-1*>nxDzQwMMEPTe-n}XYym#1QHn*Vag4BTX9xB`jCA~Xve z`}LgF?;mV0oX76Xr-tIE*`=~^`-M#xbxO>XXLz1~fgg?SB6mMA*iunb*WxzYA|-x; z7|q@5mt(I=JO&|IZ5LIjb>H<`E^OM|+`L2LeUjX5yGusupes~EO>M+&DS!N+ubeMN zo+Mc|g00@4f?3$^i*@;End4Glmha(e^_m>)pu4aS31%-t8lRPY-nx5zq8?E(8Q7Xs z?YOj4+3CqEC5762`LPF6=`aVwP15q{l;z<}LoZ4k?5+_u+n{2-kQdzX({9~$;FZ$e!B>ArYSqb-@ zJo$qWPhb(_p1Xy<5lUNn_KnnFqU0>%`_mC^(NGE&+`Nobj#Xy&``g|*gP0qxuCD#M z4jtgC%6V-JECJ=6dOvcp=kr8^>=_v}ERXcW=E6L822Eie8;z}=ry#=W?5JjuE^NCW zIRhCJ(Qg%-#%kTU;9wpUoNzNtR#)L}kxclSo7r%g^$dk&e?dOZpfgb-IY+Z5Q_wMQ zm$*a6Pn{(Tkn&2zqtWkfOhszy(+Sz=M)T@j^jQCh!Y`rlhbY2fO9VS{=iXQ|#Z5~q z2J3f1AUaf{;s^{c`1FZc70~BYNd*((B{8HOnOO?26BNBh;(V zb{we?d$V#nT<)U#a^ZA1Sa0CGW+W59gja`3Ey18r>%LHc+kxKMld-cq#K)AqSNN$FO`dExS7j#+w(ke8f6fe9n=Ds!xyvZ4L zII0Qr6!3YIlr&ypZTC*w(p3_th(MHUl3f zz*1MvMCrI;7u91f243XP^HPljH?5_-)03e9b6ZGn-3cX(_v^c_pvBg#hRascWFzj7 zFbLU*%c^o|X6z}OW9Aea1s z0HA)i*PPR#5<3HzL&Z1ohilQ%(ZD6(3*G7C_?_}x-OVtWi>|=Fc9#cLH8cdRhe{A$ z*jz0k>O1cQEc+d2}f(p1eDa?M+$u~)=@CEq0*%$DZIV0^?SR? zI07>mMtFF5D=OBHGB7BJmRGj|PQVux6;X3(;D%90!}SzW%i_l&&)jRDZ!Xb6UN}4^ zhQRy85cJ{;`fDWnA$H}^{RE+`tWbh`Lm-&DZBe{uh_THyRcOqm{}SYpt>fw-f1uUl z($)|0TLslNkJsO^5C#9E*w=;3WXu>;#sDO_(9 zkB+DhJALqZrZCKnJTjBoDsN)=^%2$SSkIw=Ijn#ASSjtm$r*y*Zjut$aXLg-udWPk z)$MQ1B5~b8VA1FZVZ)-%t2LH$1<^44(Sf67D6Gi5Cqu$be*i@=K9t)f^ruC0d8-#Z z+jKe!6M5eJ#$f-%K7){z%gl__@54Q!V*kEUAu};rB|RWeOX2XozNE9vD1(+SgN}B`vQAU`L0-67)eiak3@MnXkNtH1&IO05j!--b zj_)3q0CCg9nSeja*GUpujnb)pzEI@Y7UkG9TCeixv&G0>=<|gk>p3(NqGtQBBTne* zuvK5){yPR+Xof8DI|qm#Uk`wvp4-y>O^+Ec940)A^~WP0O*G zl9HQ}wYg`A$yTycxR#O>wqZ|)%?fN`Xz}=I!ck5}`-=03R*g%SZPJm#;Z`SMpve}h zg~UDf09G;wKU}^Vy}du*B)KugeDpqL(hM`pZi6x$-mwlPO#AQepP<$K%o5RZIGrh} zSL89+20cQ$Zkd!TzH?b|tT&ZUa>KMS*l)e=->0H1Ud5)M}_=VqpB9 zknIqrOkp^JJv2vm=8@NJfnlHni!Csa@lCF}OX+|y#tP(yGKB>& zS9=mo7`K=WA~$^bd{Uk`D?4my@3{6+Z?5>&Mf^tzr$;&PG?iiVvAliuwTdmES(g2I zF?_DwtE1IQR6m2|sH4j>8K{)&KS@qsv;XO}_o=o%gpQc4O;_Rg7K5PG-Yf%uYa0b} zckI=pb3ol`^M|ul=U!>#<1M?}($mx9glx4xJkbX#PA_0_({l(@RCHX-dDY{nw1v6K z>NkQsbG+5dx;m-ED}(1i##LfIXixfXE=MUGA;XU`p+`&54|Obb~xp1 z_vzR!kE3kcqB^)V^UTKaxT(+wAXb~A-|1^;lzAOh0WHul&DYJ>-=$dHIF)`N!&#az zjysSdEX0kw;Mk=&#UAezhK}2ZUjnnEv{*^dlFipC9ji2KDuiDYw!0*Sy5#dYM|}yn zuqSpY)Q8~piW@#$mfwVM*N+n%F0%nK5@p+Ofz9m0KUZxp&=b=sYnSqhjDUV%UqMHM z`2{lwNbYoID8xoZt#&?*1aTJQRKUoWH=ce3$0nghYTf%6N*q|-cbD;7@8F+5D5p+^ zHixVXhmv=lV)n4ZQ6`uX$KOO@^ZfVi5%JiwBQaPTtBugd*AwtkFmsUHgWw-|yN41? z!iWD|yXYgQ_wV2L7Qz#q$6O<&mZ764`}%_d9X zmzk%2oP@iRCj8~J;p;FxF=zeH$@SpZ;kW(E$6{j|IfLm1fy!N$3AX9W8&pMsWY+2g^f?TPit&Ks% zV!L{+T@;}(>|{O6qrI(9VlbVxH16uIQEZ|h6M9iqO?Ylk9pnhkn3=Gv2yr_mChme7~qSzSW#_uBSeyU38fJk){)%0PPN4A>T{kGM*` zDkm|gdlqKc>1)bD6gH8kX4FD3EgGj;M#PSldbR zKvvSAz?9}PW&5imWx?HuC1l}KPsVFnw9+ACF6vaSsO?)+3x|C;3^EGl?ns@5vmn%u7A;4_&15^rTN5y+%$ z)X}=985$r&mY=+l-7%I)!xPGyuU#&yXW6-$pgetWyEe7?e5X=C=;3d-Ma=2yD&Mwi zUx$yaIC~td;rpZEdq-<(_gmZA;D;l&Hb_?-Hr4hq(rR!dMFi+Q?Hyr{z4c<0>p@20 zlr0DfU<;#pdAw%Q$7S+CPPf;Oa$C%ZYa(<+UmQW%61boQ{CwAC)V{;?Z!eE;%~2oO z?^F|}#3Zd>-lPVRZDE+r%L9WIvKsk-ckYy;y<^ss(a~f}z$n3S^@|7)bAdjOS7BXY z`$Iw@0vjX6C@&CaEy^5fO00A1z_BsOeYRgHwAL8h%># zRbj&=_ID!*Vs>As_fMR#Mc$aY>E5C)#^RGmtAEq%b0o@hRVZ_OHosh9q{h5w*?C;@ za;{hfyGX_ClDnE)a~+=h>9i4q-hB5^E!$fA1HI{-giuA?J(S!bR8Pet)>_bJ zBuyy^NelC6!SrWf>K4zgW?$3=Q@DiLFzPG6xPL&munY1F;T8gZVi!7{7Oh*lRkziN z1X)04&#d0AN11A-B1p}3%B=P~5O@ay-m~;WmA8A&DOzwB5=ZeE=@pm7XelZ0+~eQ{ zpQ<7NT}8$SVNv4%zfiUv%iB-K&o`AA@Mnrn#8>h!1q+P{{0hP7 zB%DXFS+85FNZ5@!)|34N`7I{glxP7z)K|V&ThJ4ejQv@vOft95WW-h~OjFF)Gw>+$qUJ>BrczQ0 zW>Kncu7=2~A)DB2%d5Fuvk%9nixJzZo5c|;gDSAuq!G`P{8}Xux%-)Jkt&usyW^-r z;XwHdbp4ziP%~=jz`lma^Zj|;EwVEW(`Mp?q3Q)5(@BX0?Go|85{pr`(%mj^Xuw>( zo|wlviK%#ux&g_ttfsdvr$B~&8voA_5>thv(l^oywVV&JM)Vn)((-DP zazkPBwfb@xoW)IJCn~LH9mWCP5&93Z^``Ed+Lfa}4f#IGc19tUja)av!8+vITYpaJ zP0!|88?5Dbj4@iN3%qS|UO>%CT}n;_9);~u5Ue?90%dvD>3het9}l+rY{_)+emY;?b?(;3a> ztoyfTk_B!`mJYf*`Nl-h!uu%}nWPh4ydHXtoI2Yo+Xe#Cx5LPvSL*u}@njRf#3!Jp z3hj9>ofVVwtDKB(q_j1Xeq@(>xCQgH%{9A;%iMiG8FR+FMKmC~#Oz{Gww|z#=Z!6; z1S^p^rzl#ef;GEVob9^wO3H)XRr^w8l9UvW<4$hQ$mhra6H&Sbcs@+sfIN}U>JCo*Ica3(bT3k8LR{u@AsO(BzJavR32i^WeL;t#1_Ep7* zXqe}?_M6^QNG+PF2tBcuBkgA$FF3kQKZylY@qbO z3e@>dV;3g8liL5AuYrSfC|Dn`hQHS$zZFKmU%iiIf&5mO@V;%Tc;qwyp6E7giNU>!!il>&8^cJIzfjhO5sR6~@}oI)$=YY8GU(Zz=UB zj;1tMsaxLF?LsIiN{+H1WT`HUEWP4J@8@t9m|SifW0=VdeI`)$VRpx}E-P7NA30Di zRG=qpachn{#9jTe6K^|1BPlJ{7&Us)NJAale}_f@o3nSph<-LrZ7by7TI=&NTH53ckU*r)PW=$IO=+}Z0v$Q~Ws51VO}OKH|C*H4m`U6!bJ&Va1~LDpat zp@h|)4GdDzWW--`JPS8CsJlm9x4oDSRfM)bC5;fE++7)stH3R)1Y7Gr3buBN0d{;5 zsN=uN``@kjd$C{OE+}W0Y4GReXlvlx1!(ZFuJXO+Wq^inO`Y|`mezjT`OZ8y2Ezl?84Kh7J>8br%2 z$UQ-JwfO&}GKuOdb%VTJxC2dg9dt$lSOwK#*}ho@59Ml(?pk-<{I$7GCAoy7oScg; z#!q8JvfI>5Z|3COc_(??s9b}393DIwm@C6cpNaOOmT7&~Eta`hbURum%vXAgjP!pH zMM}l=yoc5n&bNm-iaguS%A9VO!W6yqK6x)}Uz&8WZ=q*iH%rgOt7%8sXeq;50MkF| z+bHRsTyOD|%hZoUIHtN7aefMsAC0xm8+deg1y?VfpxUo3>S0E; zAZDo?9PE*|t3#@~yM5GM)Ijsel8K2wtq)y)v6lBWYp$F|EERgc4S{=A(QMzf*o`T@ zNWi1~Dug%QV4V8$xC2_Ur$7p)(du0c&l=yoy~yXwRhID46M@!l znUbtFQd-nbMJ%f-d6CaMYY{k9YV4E~hU$DB=BoFOLoT_r6Ax7Xq4@)>15#&B^C??; zxO_QpN{1vqcZ*^Ij^WjvcjF+`+F7QN?#tI^m<;ste73o8)>R?pw=ep%M)p9@?FAULcE&iQJm2OP z`U;eDkaA-?l!PFo9eR zptwS35y=Tz9b-vJ;>CSCq(IYd?DV>vE!;`e`diLtJ-4bTVrPEO7 z;UbWgsV0>21)q7wKTRInm+fR>(~v`7uc4I}DU|*wIA68MX=ccc|7py|FXYC*@X)@yr8wDrEc$*}BPk67=)1jYA|qBQ|Gr=LsDl#Z&ArcP zdN;ba%Tt@b1XbS;3-lg7uP5;9@!-xN)}w>n5Z1<^D48%?7(Ca{jY1v68-GrEwR$V6 z0pNOqdoXBw6X0~XZ#2o^+3a|qH{N^zj<;LqPTAT2;haMWar zlj0S$?cxih;tk^R$k!_63zV-hH?nAJ4AM-qG4Q&5n;fgZhmXY=C%RuPNOL;+&{k|_ zy10BIdj%sP7oFGIvVXi%0!}XwG)#wYz`fCTursX@Q5Z_!5iqyftw1Cpqkz>qDm5uS zOuBks>U`%f2>9kEy@h{If3}0}S(~YoGhbdAY48SB_QkL0IQ4Dt{EW7`VQ$fcOYsfS zs9y&tB0yt;u@oiX?)sC;M;zkH3We8QsV z`c-gx*g`0Vurf1=TuSS`)}}5N!!{>&`v#!_b+?S;0oX%YX|~b$ERnrEO997X=?nvb zp%ytc>E)QLzzdzf@UO}yU47OYGB~?!J@TP#MeH_TZd6bu4X+OKlSioShbkk$L(!7R>t-KO18Kbp z1Z8_^Tr7|Zs(n#f-{UBseo;bAx!UeNRplC5XA;@!oLLrcWjYyr8C_MJuY?LpY3`n+ zmh{1F;`k@$Y_C3)Y2v>XL^^aotgEwOW*Ua_yw#lXY_f_&1?j9w<8UV{#cAR-@W^vo zCAtYtV7CA4a`EST8`wr%JgKf}Gxg)Ni!IctVuYRKEqH=yGv$?5a%bHT7B~5{@~MBR z9ls#0|4vXy-(=+R+~wIMHU8Bg(--!ta;Xm%4qQ&YbA=y}eV)^S|H>M7-ZR+K)pe03 z#Dx|Ayc35TunHtK78q`?A$(%Arl7Roj*0Bu?yr$<<4~!v(wqFr%-F-#zNZ-z6-0}8 zFj|Lu^@@J6cKt{oyG?xep|0%8fkCus7aB82sxq8y8O5s=nfi44P1{zca&bk%gi<@j zg1{-~PjNkIdKR#VPfnqS2MdC?eTO*fT-2N#LfC&49sU zphSNcG`?H=ZDP>4vl3N&VPq|wLq)ktP@e;#JmOlcsBBcHAk?t()>=`IOS6_;fzer2 zfHTCH-|u`=sM7L6R0ECEbHAr}S%HP9k#-0_p3f7XtpSr&-yXZ6Z15q&BrXPaefUIa1P-w?wxrk!`pO68qWw8IhqLUPYO9DN{RqWrb!nM^Rqd zN4j`x3mZi+8R7btJno=M6P2}dZ8w+RJieCL%z4%(l-AtMYjjaUE0g8d6Ec+%bw8{dyFqq+3%^bGzOx)pDJ{r;K!3Qo ziQ!?~xQAOv+}|%8#F%$jl*PCbf<=Zd61#4{pXtBr;_o!c_Z}Sd#VN>p8e{qk$A7~e zr(ARqs89QN#2dg$oo+ehyGh@eAhbj!%{KDxET;5XuX}fcy^wn9~lFAlNWUG7)gR!E+UQ7ZS7sw^~b8k9qrI})_)A-`$zw2Ae3K= z3poJ^;d1WfA*?~sYff*8BSI$|X(%YbV`wBCdK8NbOh4?Vg^WU9v&NN2&6z1x3nyor zF81LZ>=91NMq0Ao{KCVSk@zQNAdvsFwq&t6sRYUGWINyQb91z2lz!M3$w0G3aVrb7 z5(8hmS1Wd8So@!cv3#OL`|kg~hyQS2${NT;$cy)}7vdAcu`=-!rdV9hTAc|v9nKt^ z`q{^UCuXMY^!gI>Uo7c+5$Sh;=N9p}@IL;8T@=@#AeUpz@FzIGBmSDcx=qMryvST` zs^(!XxyhrB_1D!U&PyCcF8enAbhra>r2FT3#LqL_5XI%jyJAz>>8wcmiDD?unrgqA z7eObAR*`DcIhVA>67lO5!Dz-0RJ;gvBOyAd-S|I4X`4#&DCL(bY6$yJ=+YlRAX*yhjKjs zoJT3|PeU;4>mVoi(?RXWH0Z0Uk|e_|4M8&+>I+o%%kmDvI{0$%`8Kk>#{QIM_h_Wa zys(^Jk!af3wb4te!E09Ib^k*#0}{DO&u|<-M?hG4kKd=e_vPl1&7$rW1-A9TdC~#@ z;AzZV$rFx4j6m1_ha9b~yZ#fgl&j5WdGwL(Be%jbc+8VAK!e~R7;?~=F`b@ zVE_I@lmB;I?f2vGtt_ElGNF9IUm>@Sx_<-bB0y9SGw*M@|HB}^{|>5`Oy=gEHy9rT z^4`fv)N#>-3jFxPe*S&z_BTIX}RBUa#WuSqI#xBxUYy@svJkG30If!as9I4!ziH7O# zZ-Leb=y6&Z9fPPSB#KvV`U5_SnN-lc+i2i}0gDfyvxo?aFRea6ynZY0l#ClLAaY!` zUR!a1W^n}VOePXwGv!8odmB^yG3|@JxfG1Tpq2J1gvs*jU1RuW046g5XDjw2qXS*j z9?H601d{&F-a$XgYbH{Y$fw-^O#~LrmOLGs%Bw!>0ApzfHAx@JtHmL;)e||n1#W;g z2?`AKIvgJNn!n4u*p=Ee6)GiZijD`s(Kz5*T1;eKU)ZP~Ke7R29HM5k6^tg7fcPtQ zr}w-|S{Vl4poMRM_UuuQ)KP>X83dyx=CsVg%}v&H^+R3Kc^%NPOW-qp7>W1@Sgm>R zQF!8*z*+*%jzWC>766SDG18Hm3Zaq*^M%U;hM^KfsF4d%(>(#e%rhbtxitV{0qs{3 z768~(g8OOeIjV!UC=|IjY1|gYgc<;Ax;Mp4sMwU;k@P$O_~Q6!762Ns_pn%O7^Tkl!0dScg z1+ygBs$rXI>!rT@$fccyp3Kcz9Oz65e}df7+kp|Vu)BU_=G|#6>Y922o(J2Mb$}S8 zz4H#xXaLL#ZyR?Swg%wOgBjmPB*{AEHc5vgbAD%;+&U$8-$qBvkS5LNw0t-YNtPUs zQFqnp1I_1Ibi(1m5`visR$aFlsW2z;=XO`? ziGs@6*r{mS{(?~{!j=>Tljt@eicYf_@x{2WR*5z0^sm+J-Y20em%$H1JE|-Ma(taK3)BTwkRG# zCt+VIM&4xVQ!q1OugRaBVFz$yd_L>R6rS@$YV1MH%M4}RfcY8Jg%%T(+ z-=?TVOZZhlFA@OU=?sXKH+$7j1Q4+xr}vaI(euRi&LueOlT4^49jF-_EVPnl1M$!Y zxM35t5{#jh`7EQboyYWmRO&;~rnzL!wL)9ar+zS9Q)ll84>_s<0}Kp2BSQ-sHcATh z#96Kkmv8!N*`khiz>-JE0YfO;^v5psYvLb)-ngqmZ;pEIn+m8THs>@^BAiV;r!O;$ zbisoegbK2fpAsy) z=Dv0Tku3yNr8V%CtI@ifz|BRXAirr@?5+Z??a+qAV6q_q@R+A4F6Mch_fRn~FwoM{ zBAEc>-a>D#Ca^tbmoG0{Ux~D+D|+=lUq&N9(|B%XM&u09s+>)N>G(4?1+jo)W@1hf zu+%_#9ch=_fQ{1Zj2Gdr{zRlZra3oCGm5227uE;;rnf!UOUA^KzFrrj`0rU zQv7)Vas={V5s-L3lz?{32XLxp?jNE z!l#W$&qDxJu2oEhh^N?zDVEue>+i$S#ITSnn%7>s8a%J^;XN44tFMpqI1$8KCj148D~{ zeqQ^EuK!U=%>_lJ?&%P*H9VlffQq^+>p{Y4#w6H8{nZ7;8#&TP-k5G5hA&rbkC#NyLAy1NgA$ZDj5 z#b^CDZ$h=phP&s%&f$E6lCG4Sd}tzVfo>rV0MINxL_iT3?wD)8gnuiA^+?4;8wK34 zb9FRnZ#to0U+C#LvKGJvNyw!!O9aEYJC9K|)+EUQ%8_CBnw%{x-(GQE$OvZGSsPEX zy0WxVxmDnPxU=G{j2P=DXWnlbT)SyImU7_9wAB@mRDlcp2#`gW(e*HZ!X+lb*28pc zt6fL-058eO!ST4*%~86sE25nL$(Naym!kSheRB%9J@%#$2KYu}G^6m3`<-#PS2|;ZG370_*Cn{yZ&PMnDFp%k1)smD!S;UWw_=bKT+{ zt*S*mmkpxfK^(020$*%w3>qr4bOv{>kyz>gyjhZn;ZXa6>LIqeM183*S0kT{Mb}}) zQ6`k}sJBN6K(`s2Nirc9T~}jZDgf{}Abk!{ei8L`h1R~V5HZEP)ojeSRH6?-r5I@e z;kZjei(M2b&-$P`$ID^_Q1QxV(y}B5t<#zS&{G5WnORpIutFxC+z;!arzoPB4(9+$ z!pp^_Q?pkKkp9m7scH~QVC6O|JJ!Ph3-3>t>j&``3BbC|P4BhZ@=IzyfYnnUY+kTZ zN>^RUeW+LU+#I0f+vcimt!DwAx`pj$gU=ToV;|ZuR74siR6n=={QhH{ZM(3`2dks1 z(ydt<^+Bwx-;K)kLLQN>lSv*jirG-$A}=1vjK!2X%%LyKgn)c8LlY5XT8q68z&vQh zmshJ2ZrtyLgnT}ikEb&qe0~82QEoA6(c4Nu4x0fJZxT|eg2QJh0D=Q_T6N!H@MDo* zFuj1~P@eU$6YS{V@OolA3MGi=ytbpQ~q6QC0VU%$No7)}}f0r$yB?XZNvMgW9`yo~MgmO~=b^{RqhP1DPBJ$zl zt$dy83}Y{RbgVvqlmM2Ya z_*IJ1Jjy1_1EwRT9~CDp2D+xNS-Iw>pEN?>?dIr z?kNIA+_r#$L~cK~6TV?Y%P13yo7Gfuod3LGi`@Q_;Ov=^X0#9BVfRgPMW!s^%0ytB ztKb6e%Uy!|ml^L_ni;!bYQsWSRcisM}@{DXkj0guSx{cLix@TZ#BW~X{u4X=|7Ho zLTnjA>IM(LVe_Vq30kzf3${NW1L)ZEvCTJ}`+j+8qyA@Q!kkpc9&oFN4Jo!XQ^U;-xlUrTn)`=novL4+k@?j4n0WGO(E ziKg{paxVyR28!33yHizK8pv9#wNz=w`0*4y&J}gnR=*P8;`B=?X$19Pj;hS&`asx* zw*S})?Z}y4=|z8;H1&PjLobyE!F8pE})*kGvdJ#{eZ*A@FM(J-u|V$1*`kJzvd}clA2>r6rW!WRQB>n1OI5klS0QLdY-LC7E{_5H zqR7dhG3+>z=cH|F`xnnZsmUUb&_4i3D0kU)t>gCNW3|dgm>0ag1G6W32TTO+pEi|@ zaU6VqTiM7!S($23aIux6yG;2Y%EPenKv<=SH!YIY3w0C!c*oPy%L3Mhs1;A79FLD~ zGy@po;@igs=tPrp3AqBgca0Zj7a!kB$EPy?${M6ku%TH|n_ChW^W}0rLIb@9zQjcX8f-f$oG=X4@DYcix2G>L!Xl!ZT^`RBd^|&ez~AE zMG!{5>K?UXWKlR%gPDpfsl`3A@cn3%&>*LMlVT9G^zxDK_A?dB;uXZ&f}%6ZBJw(f z_EMab)7*C}w8uM>lA=Tp)zxk0TO0TsRHC!dW@_rb*F8@*+vIZ=o&J%0n0On6)l1~) z6M{Z4Nl0@tKnKdQzkQ9fo3z|Z!2FWg(uP3V@-#0VALkC*XemgT_Ts5D0r)QeR6>Jp zbhNgYn3lr_fHm^9|A;l-)y?yaG-#<@mW*s^d;5{LR6$}cmorP8dpd>9(0T`HyOwCT z=o^#kaNB9E;YN0}Sn{NqMax`ZeSqQ6hZt3+AKmGP>Kd`3{Y5t_yYQh$OkNK5YA&mw z6`f+OAgpLvzHuNdTW2enn!zF~0bY^iu&6EPPZ7-OY08sR7#524vNTvsM8dSA2I^e$ zQw{wvL#_j<{l3aZjx7(97970rEng`_jp&R5?A|Ux0HBEiS4tBExBzR@aD%xZ`G}Ky zFly)!>kU=3X0L=%%Sb-Z%dl%K{%JcUk~n(pSh5%S-3rxDb>2Zz^CnS!BLD zQQiAlQ1a*6+4OU}(_HnT~K>JRg?$KZrd zllPM6KQ2Unu#|j&!nNl7;rZub?W)AKzefIW8qA9vc_op;d1d`0sPz6bOgZ;ZB*6lheyQ+ICe=oBWJyP@&FV!A%vZ+s~W1h75^34%X|;Ej=e!5GiD=_>^on z!^YqlSo;EbJ+|sCJI9tBhoZ*{<)qazVWnLCn27yM%T60*qtTpFmV)_ycJ`#zH~m-6 zkgYo2rkV3lr`9YEGhPec?2)OY*Lm!4C~1KC9Pa^J9%kt0WfXYtK+{y4b54wQHh9uE zhoP~tbZpx%r`SEiE&40E=tlC3 z3!PYS3;k(co~g~7lUJ3e3v>{jDOYw9N5y)e&Ong4LKuIA8k}mB&gMD`el?7+fAEEYf|XjLjNmhJ1XdUIc9$ngl2sbtdluL2pi`XRlnb+#*M2=}|3= zNfh+$Zp~$;qrKGCDQfr%+v73DIsEkM>MZg}$BJ}v1J_XZ?HhY9QwOV>q5>})i!6W# z$_L-Kr2^E|)$hdjzVLq$MUqSvjda1%>i5=EgGgil)SqXWEe3zPeLSTZmvX{!Y1{lc zFNRkfWq8O@eJp2>%GdQ zaApoSqv>^9ce=vN(R@)m6i$HM)s1)g55Og3cMvayEN1QSl4DFA^)UJiQqwel+CE9I zh}|*2OLHfi9d&ZMIuA~DO}`>b(R!k;a!U_)?0duH&(;6$S48W8Oxz@$!lZnMNqYDF z*QG3Id7sx8$Px1@v=pxnwSP#| zTvmd2?*O(&o1t)8+f{Y;$|pP9MH;q#QPJ5}jB$||g=Tb~D0^o9AEaY6OwZjZh;>OL zpWI#=B`LE1+`ooR`H3BZv`Ba^H>V;tnA_dSL4Y4$KoqI` zC3gFT7jmi1lP7}6!PA!ijJ7OVhy*RVm>&!)8?86$r9NoHAW}*8^+34qv=cm}#i^qO?Dzr`3KsIdI6AA1ITIQP(rap<{J) ziYCU38j&SV0kRH!|nd z{oJ4)aD_#_&e~rzRjR!PX0%H99d}+~oEBr#@5`Ace2fN4O#l&dRwY5l?yMuhiNxxM!@yW4zR(T%#6 zXuyvx?a};XTK4W{si9Zbou*tGtI?8C;p5+(>RXHSyWITFjS(wp;E@l?qQj|gZ2n8V zNng&8`!8uTni}cY#>6uev66e?iOSRan(Q)Rp&^Wv-HUH$auVbtwi4dIgHMjL=uiQq z4IRW9VWWs)^uU$IRt>WDe4t;MzM8|jBd;d?+BAS}H?8xRN{c2dhXX;Iftj6zOEKzg zjk=`K`4sjda~0g%U#*+t59_{tW5MD-n)m<2Aj~}w36g(sc-c5Z%fI0vdCDzdg&V92 zod}&;_NBL1S$l_ObxV(9z3?KsRnS0r!t?QX4CC_WLUpRa8duoLO7`H%I}#5~jEf%6 zr7zgZgnguSR;aCz)rT0<13@{!t}#gm(t<~=ph&z1Ird^smY(qCz!B#;9(&kKwW^L{ z8UMzobEcz%eVOCZ%0}iJXPEC;xZ>$Hw#t7=Po1KB-+010wRzrj^4TV0T=J5Us))TF z)wS_zt{@SXudEjE$X~g&3lzn`+3}xU4jo|e^t?@tB*5WAEWH5f#~CQkD8^PA^(ja- zBXdXHp;l9XJ|?g4Ou(4!YgVXy90Qc!CU5K9mQoJgZX^G171`;^Y0o{ykGI!Id7hl# z%9pwq))9dGgsc&FB$W|A2d^^q^0E?a^eu|DHW`B(hLoKm5r}GUwK%XGOEIRprd!5q zf2@QLSySd=Fnq+ zzU}8&tiO1es@lWD{W*V6R60>N{^lS!RECoynhfqwW{$2fYFuo$H2lcSk_1cPL6jb+^id zUL!T3=AL>(B4DgGxNl4)Zfmh>uDr8W9REaKJt9H=ol*ZGdHU91U;hd8vlV5$=`DnM zQcP`z%=@rpJBgUWLy*{S^=&e)nA2tgtd3uppgWSQN2R6F{e=uIC?LfC&iYdPgpo#6 zqb`5;?yttNjt}yvl#HlPl{W?5lt9^F6Z2G~epR!KbLc(mbD%GOV7Gwe;5+K^bWm~l zaJNZg1F9Lf+dGyR`&UHhhbI$=h)`A&Cm+7T#X`_pjPaRjI7z#d<5KY!J}^OY^j21J zFB$vau!353|BV%7zj<4r{^tJ$7F;Yb`4=qs2XgaW7k~c>pYJDC;xl27g80Z^AA5p7 zM&ei#Yta40EBanoV0Y=p9oOJVbev-#>v@|h7Mn~faL%e+lrW#Hh|5v7=Z?D(FYM*< zRH^(**@skB#$Ga2g{rGU{J*_M$tS^cdNoz3Yn|oQF63non#|I+3;r>X?;riAfshc3 z3qSWZD7K{6>d1sOwmFMEB#vnA5npab21-6CvC=$KtDk?sU8QLiWNsZgZ4M=wdhwqz z{En7?CF=esZBaWfmfd*u5F>WkvbIVvg!SrDD|yiVsY{q_BMs?KwR)K*J!SO)2ueee zxjNkMd-xCcCDDgaKyE!!AX8LoIk=2oFLuK(I2#lL*nabc{ZDn3QSF;EKks2F{z2%! z9v2>=e-dtsw2F(YYPX(3#fTE95S&6X_UQPn-mcuE-jn=UCN7`!hN>N@v}!!c>&d*1 zj{h(9h*!^OAnaw+3BoF2@3fKo!3gQF(?TdBF=TzX+aQuup_$1VfqZQ{@jli-??Z)A zl4?XAc5z5J@NFKK5cl7G$Pb1^EP5?lf7gwi-*Q~mF|UIj$u=t9*2)W1IZY+W0R-2dyDPvQHjLv zNlL_;zoXyaA^Wjj_5(RcH0gDA*Wln|phFAfH2PR78LM4vpAtTD-`{N}GNnAXP)(Zk zSun|{&&G>Sg5;d8Q15OJ?Xtuzg1`FLUvZngT zzr@Cr?0>r3!svqaSG0;J#!;dA7jN)nEZ5paG@zx3aFx=(()k|>fq(vPFH=o{`ZxW} zmx#~GQI7nVZx8$S?O)jR*onAms1U%bYP+*4Z-Cb8>c6*4|32P5g6Gl+TJSQR1fOz? qr{$0S?SFk-;QzPpDGq1J) literal 0 HcmV?d00001 diff --git a/docs/assets/tide-display/display-modes.png b/docs/assets/tide-display/display-modes.png new file mode 100644 index 0000000000000000000000000000000000000000..79ab4f1ea878c850f181e6c4c9f38bc707a2e1f0 GIT binary patch literal 24876 zcmb^ZcT`hb`vnSP$3jt56e%Ji3IZx3Qlp?CAYh?arT5+g#Dbt8ARr($BAoyc2!s}L z6zNTR57Il48c4k>9({kF_I>w{%NRMs1KE48{j8^~HRm(et9$B7Ob0j)FfcGMDc`yE zfPrC`Aoy%D?gYOH)}el3V0g5qeCwvB_u$fqkDpFYGK9+3@Hr~%_DxUoz9;9KJ`^>K zhv?Uqh?FFI&aV&U^mY^mz+W8lq*nP>@t45Lc*9Sl#>G9q~y7+A3k3|~b5 z{Hz>gU;v*RPFeQCRyvJVw?k;d$$J@|4IuSB z>P}k8Y<+t^ljNpuYnwZCh~cFP1H-sZ(dz0dxBq$vi`>?uwj@b>HEFrO&`j*gmDM%+ z555v#z3SjtF_*a-i^D*JSu^j(N5SE=7O{467lhIk%oDK1LtEj|5)WbxV&)=#J}BCf zAZ|xopVN?8xrKHdX&MqL<+*0xFNCbRV%M7oA&;?SCAq3Fj->{3`_AWNHAz6X#)83< z+NBmQN}OWIJ{Z0pS{})#BuD;UbIjy>iNjE-7akXVPEEyp6pVm{TjqM;o5;xfS`$-o zCe$<@%6WeNj4F$*?_(4a0XrTdbj=B8Snc0eV8jDmEL>%~zR~>jrI3{`Z1{?W0$zn6Kk`aFZ{X(A5Mj1s zqD>lKwb5(PEKxQQE)C3V+4648au>sxH=M$8>CuhmSYZW5EU^cP^Cyh3eqJ0XwrWrD zpS9N(zveKw4h;M@Cg#}Dqnd-)-DkhHw6w5(Zj~7ITWggFRJHJPvQ1{am!Ci!%8k?FzMlk8=>BKq= zln_gE9&$jdrN~H@M_;62E;Bs2$6|@KY)jHJG~|@uBKBeBz<4cN6PQk3nG8DRcwSg| zq{73Facr@;eYrd5VK6h7NabSDSt4A_s_oPBeF}`D)J-&LeJ(mOvICeEc+~Yse<91- zHkq{+#V|67gW(3|rHQoXqW5B9y*y)idAWw%_GA`3fY@w8T}_WxKfwEzCZ~a`1q*K*+kmvQc_Y9-(0$4 z+u2CreaswJHakUMu!es})j%#T8krgK=Z{y|LbL6(wG`qSrp|UaIJ~|gY_yZ%(+7o~ z^Fl(D+GvRMvIw<71KKb!bDW*MJw-fCB;rP`a&Jyr-{x1YK?jG3KU|39U95iF-ZHj5 zxgH=*MBg2sRa(mn4;|Wl;}Yo@Gp!OUzzv&R6)Mnwiv{^Yk2i2}aS>L%L6ceit^oo+ zps~MM%6$>#Pb!r#hB-{sF==^3B`32DtOg}IN=7jYO-`4VO?Ea*yU%{~>Bh&eiUx#~lsYgV3FgXYqg`}qq!OJwf~Y7sATjLToGNfq-g-23q9M}kN^#LD zdrKl1m`bqh=5!smlqd4$^Y&#Nrv4z7i$}g}eO1VFxxXXFElwfASW{DTPEYHQkyacV z;gHbC`|2b4S?(OwFQ>>v55Hqm}I!rXU1K zey5cWxA(DdS8Wnc^%fYd&1&!v-HG)&#vW=aDrtfNPtWmtHuKG0>Rg-GG6D8hh(3o& z?n9eoBqsa062QE;Pq%0Y0lR$`?=yzIpZudsgR$z)ERzyQJLnTnpDgN~&I+ ziQ}fsX~^phy#HjSQvyBHcMKYpmF!7eYnLSrI|ammvCOm?_LQ z+kD5vOgv}%%UmW{GS!4dMD!~yH*SLg+M6ZYi#!H*>g(5QMcUG2jp0U)R-48rOc%! z=);E(Wb$^teo28XVK-7}yoM#~*wMuSl+8rbF(LKqV_$aHi@DCK5CnyV{h{Nh_!Psr z#iyTv{FLU`ChDSPq&_SrGpuxG<#4w5S!OML{e;NK$oLq&=Wz@-zE7EThJ=R7nUohP zwHqUJ{5w!K#o`E^si_USp4<%#LH1sunznXttZ znsaN)@h7G9R&4B-ESH2M4fT4K_Z#bcSvHaul2TSvMcDT9L2ok~^%$G@t@xZ5YQCdE z^P38(@%PTHNGh{>_l^JT<(N&tPkgAn;@p|(!J<* zbF525iB;m)OlbW_nbwo~#s6{yqN{8+g;Jyt(LG`ceImM7Bt?3wA7cyT9Ol3N>>XHQR`ETx-G zDPTXtZWB4~R~D)eyU|pI_7u$V7WgT7-AYRjOYO}kV*4_)vUIR!S_bDv9=`xHV_|8L zEbi>=>#GRXJkSj}{#Rmp7+;Sx#jv(hk`*>xnM;FSvwcVyV`_HxM-UDdE?j^?dK1KX z1J@M8Z9CI#LXQh8M##Z>TTTW`??*X};=)e#2H%T~>%%u7g*MN!o!mSdl?pmW!lI`=#Z*C6{+vSXcmeeR)*#od14?tLMXti^6A3 z4#;}Vemn_RAH~98wJaGK83Ls?L+LhM8kw-8@}NW;ZPd=pBuU%1Y_l_S_^CH*=f?_D z@;cQ+LP7*bu6$x{mTqimsoIW(C2T}sh5WyN`{c3E%Y5pZ>11}t+}z3LIAMp*^tsLq zRY6%=F7thD?F!S{qOSJqZs3MVAUlCTT^cNLYfq7#Im8vP{B^9@vh9THrlgo$vaz9I zmFadTHH+nh8})_1dZPjAJd9Y+6Vo2Z<@=Ib7JBUX@#P`3#HPL1Vt)q)8nGr?mhCoE z0QWCFD}lZpKqaeqnUu_j<`yjQ2uywu@Ua#E%LtY4duvDR`oFI=H8sg?Z>22_p*NP@ zREjNILAiFD?EvdY-BvwtYi(ai7oOC4o>yS`C?K&j*w|w$_(+(e35h5X9C5;9{FMXF zZ(?Jl(o@Tx?!sT+r=#rpa^#FOXjCh63oFl49{Sm8|P=c%bP#E*lq($FiWuF zXFSfelYz0m10vH=?3HqOHv`A}4As?$0W3+}VbEQI;mKYESf)nCdca|hy7QRFHGB7& z$n9j_t$x_# zZ@Zw=SBIPG`=#o2rCHwI($~j|33F0?qng{Lr8xvfsn-Wp8>{a$M;%r$oySkt%4!dM zvhFcfnaEUrt>H@fV%#_GrV)x-PvICjmws!)!}0D58+(6KqIB0pipGTEzO*#ows@r_ z$^X-ehg3DsG8Nzh1wfOkAdu$ttN^7%FPkadKwM@Rk1G}AB zx2U98mznzEpFrX^7G8JrZsKx$F^M*kkajJ1N%C&)6Lq zWu0u+_;eRRe3wBb6hR?rxGmVeb5( z6w$8hc#yZ9sinotEq%-U!MHy{q8l~!>cZ=qqciLAlKdHpy*ZrzmdII>bNw|QnHI3x z{M$POevzVx%%Lo$4ugKJN92 zs9Rhn!p6|Bd;=Y*tV9SDYw9opJMAcLYOiL2oNkTEbtB&re(-VH%xFIC2rqDZ@LilulU_d&uBMUvvZhC^Yyz9S&j)PMW3HOlm?ASfqc)F z4K}KPbJ}d1ZmWpCaF#*pCcMmBOmf~r@XJy9HO>f|a7bQqgdnsw$-O)$EV$Byw6j>B`9M?sV~ZIz3mXsh^@O+xm&u$Mw8aY zw~AFof9cLB$hK8vY`9UHC`ufTRR7kP7q8)^GVz+jXWCB1U)I+Z57)`Mr4xklo4ues zOn8gBDAaO9{)F6m3rLu)V5p!L@BH7G$JxP#O}$`SSK%1Xg&e*5kMLWYD$30T@w`sM z>FOH~p?ul{C#KJ?!4Bi%bJ}J<<{6h)e0r^`ayNM*;cNk>PHseey+zvBp$b-g)zx{Y z-EJ%BQ_YF)F7+_f#U%9CkGqTM$Ow1{_|SJ_bX&2`8&8?3jO1q9j$~@3TP$QcIEr;^ zT(Et#P(aF*4KHz~o`HY**Mz-Gf2}anegri_ zeDd|tmV2L(n^mh9HvC!ZsZx#^`W1giiJmpp!`?m++u=CfSrQqm1xLO_y{>%ZEgbf_ zLx$MwgoSk%9Goxb@TD2bTqf@Aue?Uw>rFdVvLVSuZ6?^w>6Y|~vHokUIoZioQ*la> zv0_lq*QmG0>hsKEI=ym|+&>O66;HI8nwb)FAGC#s=KHoWnI z&Ek=3fLVexFlb7u$~ZaUtc{#a^UV#r7`p>8`CXri+Jd zijgJU6v)IcOC4Q})?5T#C*xsB-#nAMAp^M=mt%~{mSpsoS;(!?BY0ykU*V0KNV`5c zeW%KRk!v+a=+^sN;M};k?frJ=aLPy}pD-WE>!qWnHiymD8ni>aug=IF#2hgmQ=zDD zoU-MaKGn3Q9%|5~`H+%so-}*7p7!*0^+tkKeYa%W{tm6vX7ga;7$L+^z4G#P~Bqp z_0D_RRpJ%O(QFI79cFe3rus*uW)kN2$t#$w6`JEy?leOsHgh70UrGh0Zs}ih9ClkT z=pNepqrTBI+)s@1M|~6IQMgmII;+b5It0~1JfqKpnqO<@6P^%}gE;P=K;Wy`3A!a- z>rIM${5cr;mJZRED6&t};_S6J!^NlPvi)9L%}ac6dZKy`ABI{qI_1Bs3T8)^xPj-P z@OKtnp4Mg8&^=B#q(nYPoC~0th^S{~O6QD`-+Ed%hTN> zP4z`bcPxLm?|*Q_;Y!dwQ5*!G-@n|&^vn5we^J)(4N#ZEn9excd(!}5@Yk$FpZwi1 z5vh(k+{uG{5}ifP1M29L&zh8;{5|E+Uj-zPG^epuS=+Qb`h@Vg$k-{n%~P@OR}Y`2 zS2y}M=%1f+531YY@aic$7T?b`D~8+NO^s@N!lBy7IRyUkZEyws+utr-99``z8#27S z`Kb&KzYWI|!av|-)?Up9e3slR_8%2ATX3gsuTf%}@Z9C0q|HSFpYTETWb@hU>Knu} zUy_+^lA`_?9iSd(rZ1>}8y?*~PXouAbsoI)oRKqC=Un?HHT9+*$z?qra-z6(2mG0o zgW@Gn=>VL?_`ftxFL{9#dfR2C*K1DiRGM!@NBhur<9RrG#qbaBdAU3Ni1B|`n{aKp zAZDMvhZ(GOO9M{O^T5A;=bDPdO9lq|P=Brwenrvg?#QNkCX*Al7~Vg&;r!3*!>!5e z&lwrsl+nHWBna|v%}W1RZT_;t&x!i=h~IYuKmH`-@-XvmV|zPnI^HV$BmAL;tT=@J zL!-l{9Wo*ePkvj4t~YQ$TU|Jp0WKvjjxd`R5%B%fKDX%> zAHs;2&|q^Ix2*5y!2M#DEhiuWeqhThI0$f=zoP$NQeo~jOcGVw(~0y8r($%}rI%0& z(B_7Q^E9oGq~%Iv)l_DpqoC8=NTpXsmQm|d1_oQL`N%~&0%HaDza}PDOomjt&qc+> zNj&}>_>&aK$)OGT43#=S3CptJx2v?pjDqMb=vJMCW93q5$OxVD;FDakWu62BkT*)9a7ejZ z`)pPK?0z3Jr#C>m9fr#;^YKkkNq7x4HR1E;%P5;e`Idvj)*lqkxQoE|&}N^G}t}q@22H{k0*IPX}q793AZj;9^Tl%Ye1S(L=m> zCRl2SP{9c~zpa*dv1qv&Fc2Fs5H2_+_nk-u0SBdR)kCU@^N45x4FK^M8 z25c->;)7T%!KNCzxfp^uE@~{}vpUK8Ink+F()#OrR(W8hO3x+zlu5^GFbhuA<)#yW zLV>%~om5M>x}R5uFzg0ch=aT`fWerOKKJ;KCp)yb8oEG?NXe1JJ?6V5aNc}@UsDx= zrI*XhI@6We4V`ZS5Uh!Yk`b&O#6Z2aSxB2pLNs1s;iW(}^=$Wv*RNk|=j+GNs(d%* zS9t)~7PBs?<91qO7g$1VE$Z0V%#C=BQUDiV9I!p5W8|R)+zpSVQF+MU_Ki7V55#)w zfQc2Rjg<~L3c*hyE}4FLxyqvtm>H@Bs+Aj-x^6)+n|_JKW^ zhu@~%aG48w*tNMWS(?XZGV&FhKdn}ib!J&cfi&d>*peiW))Rc1x7%+0Jw}xLuxMF$$!Bh@@N@= zK3G2wSiwhf9%eCfNf~+$SSWKcg4Dh;fXvIw1GLW?;C}L~eE_v2;W)h2Zx%7)(P#80 zb7Ag7asm_2itlTvi{PP^ApP@|BDh5{>z%1El;cPRF!=;vESA7T`80%5R$YMEC5D|9 ze)1cvpNSg_(briSZWu+F0MIA_0;4txz>^XZD!|3)(SS-nqgp_HAc0rK8aRT`A^?&F zyEPs<*OgVjv@{mX1NP^@|BQzKDFHAKq)}xlnY~$_kwxbFjmMA2_OKfQdTpgci3hXV zBoqOmZl#js{)_)$-pz1t=)qvgg85NUUv3BgCGq{rO#iDaNOLC6tLBRtCb?lLfMG1a zj!jqMw*#`&lkKY303ba|j&qusob3KKrP(ucxPp`d6%!MS*nY01q&_h#v-g!@z!{RZ zl=W1YGTvB8E`_1noXp|6SxzSfv^7>nmx;z_5;q|Je|(CH3Z{~1`No*sOlBh&4-1P7 ztoN!_p`9A{tHIf|eyIa2HHEUo$l)Tssu5*;fW6ZJhLR&#{Sw<`Knb!JoD~wXqYypz zvBY*if_u!&haar>EE~R9vy+wMbJP&v2vqwD1cF)V)C71Aq^q;@AM8VHaO&{zaRAo& zfV_CkX%J=EIv+Bku>d0u%p7WMYtyUrY(>BVYyd}OQoSMs7dF0X*ZZ1P9x#&*qnNc7 zC7yzQ>Y`f^Gw0Ro06$(%(u>CVEPNF!cO4ebN=jgtKjDJQ=8<(a(bo1{j0e{)nmAQX zV5y@Kg6aX&uQlWhinjj2spQYkJCc@@HDsuFZr;496&IbH?Dh}7rU&lEI0h~i#;<|@ z`ftR1C?!O8_G}FcPD9zoeI(B5 zwQRJl$mC>nB?QnjwY9gkjEuHOPTw^HB&U{CkBjVqqRx42sB`_65PT8 z!c1G6fF;MrdvxhkmwK;!D4}h!j{!OeYq1cU1t;nOcL7rvT~>!Ru_r9I%TU%FM|=%s zHj6+`lOrLr3{ciS6Rqfr?;z;+?@w>uZBha7*N2ON_q31a@)UHbOH;OIQXFtq+pTCn zhmOzW9)wOU^L;%%n~jN&j!Oys7)w7X3~kQJeaUwfRB?POshXlLM8i&mosytF8tfh)|4?G5 z-5xKCFpc{=UBk?KQLn1ZsB#n3KqlTKS6f__kDK5%5n%iu(Y-uWsMvS-Xm*@vJbN>ecY^>J;z8eRLS= zedSagU=81&qAc#YG#vlULfb=9QnDP-W7UM}eV=);p{1@Nca*{=q2^w4hwu zU~g{(z<&hMd#5w!7o;rI6Ky?kCGhPk_Qanwk`-g>$LveeBz(`Rus-TME!8ZmEv?>g ztM|)(gKJL9!x^e@xvW^UsO}|zvKK#i@Zh*;6XdFMAnQNbqhRPc5`n%{R0XR=T37~H z6DTw{9jR&o?)1p%6VbyCMnPop4GDO+^$elCoI+!T*~;q<^cdP7v7Hpm<@hkUIp1IS zP$f+f%;%D{yCK@MbxiJ%Qb3S$g!1G2kF`BL7x^@YDs_B4Mk)x|>ppu=cTb7(goYd# zLfIrnMHPYW3)as*d`jXrov7QP$J3PH5WDHute+El5P;Hdm0JOBz6Wti+}0h}&;i;=9QvviKywA6 zqV9mQq5aD>7M?HIkp3|#O>qUyFcpIBa2Y5T#&UDX=*+t*?v4C$;Iz~ia#O4r=GPbds>BV*qW$~}>d z>e`rLA~iFd3aBkzgN?V!89F+b5t?&Tz-VO9Ga^#uz4&fT6!g}ZH%8rds-o(T&lqB! z?^6w+p@jtdAAYY3?8^mi5DYC$ZK?>I)k4`1tj^nE$)N(U<6dQFUS0BhInIsg#I$iq z`K?W>*=ZvW@E+p0YX0p#Zx@8Rkg7C_#a>^oaXxG1eb%eAtZXX-LZ*HQ73Gq&ZCSNY zooP=5EjIU|l{``x3w3mQ)(+js|AG1%NoT3n8CQEO#DXj}x!J8oA;BYKk}021IYHwM zMgg^DVW+O0rJ#7mmKk>2$px`WdCd(L>mYsHX38Wyv_UxrMNxuT={#^Mu<8Vx5&d`A zZ?kx2&@!U6+=M8Y`61%Qvd@1Uw~hi-gr>>0nYsGB>z6eRuu| zi4(}R!prb6GF-i(8aK&P+*F_Q@Z4>EDYUYiYIb+7+P*Ww{-Wf7bc^kznL|fo1cyfOd^Vp;^md+1S)q)cbIJQ1=>4^W2RKcT2yE3X^_;Dz>B4hUDDymp3heZXm>C$lu?yd{*tr54tepr}tgL{c0kzVBa<;zlOxZy(CaRMJ-ruMk`| z-p9Ns;ZDCF=Nu`^Mmv2f39c4esnduX32Flv)i2ci*MkCy2B4=%%KQB#Iu%g(UXJlQ z_36L8I-?*DB1&RjdhC0jsKMsS+MjbXKKiG5wvBVI@_6V7fJSQTu3DkQ`X=Xb61$^vy^V)J2{4Z!Ds_3L1?ql%;Y z@L}0&%f?oIG_+&EPb7ps1HWb=TU({lGdT)ZZiTO+J0OQNT3IYl)3zsbS7dB8djO=f z$gj<9Z-~k*)Pg*sb%>^8qud`@zV#aQ6RyJr@Q?))9lOoyOa9`)PK4>vyvx%p!4AqZx>|-ha zmTh!f!P9;eII24yK6uGz9CfETp#;GvjP{$T4l?uk2f6ujoF&>MB^zcZ&6#a@~9p8G9j`b~If3*yANG+0tjLV9ns@B@3l><2vl-TkBF&Xd8Gw;WQDB z<6g*7@+ulQH}ApC<(v$a8mG|!yCcwAV|F^c`FDE+5+81tt*5O-g1v&Z-=f@Bkn@&@ zVxiXU!upVWv5H%PiUOymmI%3gdyTYY)dJ95J|g(m*u+ zYvpNi;m#}eTT?ECko+R@qd}ATDI>X3U@d81H4F^+`poR93;D{!nBy8GiAu(4wi|hymzx(j7Z7v93Gf?rbenG4&oA(s= z=YAMuGk~9{oYv2Cv@&9|(Yrhmq1>$*v|IZH0tuGOl3xsjFQ2_Pz%EptTi2h4A3|p- z_Qu_9)7z!=B0)E%XzV%|WP+5hnj{EOW^54AI%TY5U6e))V?}OW>IKs|;mBq%b3&;6 z7t;b4P+;#%{dM8o?4bn3V-*P zgovD+Iq{-#^TqA6of?ZxuL}{%y|{#T8#RUgKOHG{*tRq@i&FGd22yAzSD;rZ#Yq(m ze${=c&M~^7BVx(+Rs3bGnOAvHK2s%ed+9{pPhb88s^5cTfc}jObIH)nwnQn52kC`w ziC1e>GPE5+3M%>upYclivF$!>H}29?XZe+9A$xVk5 z)zdS)N5k(l7e&C4k!Bv!3!sUkYq8XY05a+M&LZ!@E@e(k{hLJFxeAV=$h3kG)c;bV z-K4HUu+ecFWw5ZW?0dS4#3#&im!x_`iAQGg8Q_qKxtVe&kPT~#H>1PPm;Vb){Z{#VZ7Bbcyf zpYP}KJ_vQs=Cv|8VG|E3R%EPYYq5M)NbRI8i>iukX3%BMTB-V=hoUD9cuyD<8$QHm zzn&HbH9d&pmi>x2JBfQU_O4g*+N4+aj{>^AfDXQ`pHMn?)aK;62^;8O0eQRoR*VHG zHmM>#lD#Bf<)4J@uQ{fBIqN(=AtKc{kB!~HCoq5OkmZwrs)^nz>ugE@;RJqE8n!Hf;h%*+ju-zk(QOtJRM zPR>Q#%8jbtq?3T#eP9xz|L)~H+{e<@OnolSD)mf(52TzJsM(#?-nEmj{l zb1$;Q9u2NRp1eCLJjSIZFPo2253U1~W~*SIJV9S4*<2V# zfv~O!-nC5gKT;p!VXtHKT2@=uU{B}26bMZry3|4$KV0mE>%I_uCMFiEY=@ zJF24xu{<_Z|t5znN_nKv{sC*!>?K@VtrdSrgx%Jz?~_{=74N zp>bMwEpo5pqz+!3aiis}70jIVy2#y>>#e7|#ptE-9}5S1qPRK5$I#6}$iK9=K6+op z9=h*;ii`M561idR920@K#&s!=>7LpM0c5g6mb)|`5=Kb%q?tR5hF3=(UAs{~S)KTk z_xo*BPac7+#kk?abo1ZdCL2Nrd*80N$wFsN-eh>cL%-rIt)G7R54-(#pWl~K|9{Lm z??q0yVxbZcKox73F?+d#Asjn^1Y1}mm)c|4ty)pVaL&1u9YCv+FFo;EjN9+~C$~09 z0desj*bhw6c$n51r9zyFT$6XeB^fv+QaEAKSUR*;`#5X-cC3q$P(zlpe~u zV;76eN7LF6*3Y0xSOiO61pxl!^fYJ$UP%Vs`m2ospiNkT5m0B6fE3BnfKylMd0-m| z6Mq_o06=Szs_&myaep!dIzYW~Qp~cDw5eSed#1p$rEg4e7Eil)4aq|4`e>@C8Zh0c7JU z51`Mq=k@~8g$V62fNZ89>44$M$dCnO7ue3RT&7jrs%-~w>;)kqHz+7T3p|>4)jZ}p z`ByL^)m!6K3MnooMs|BL8t6Ijz(E1U#5Ir!6f2$n4<9@j7GpSlwSSb7An9i5Q$9{N zHej@_+4b5tyy2x&D;v;c_fBQr!13{Mz!`}cmN^5G$%RGpa;PWZPGf0jAU`JfKO`tc zGDccvpPudE4LqloP(>v!@c4bd3CuLXZ4HDbfSKFRYxt+s1hSA0mLRW zpwg0d!c~FCf*Av#lQob{_25_O0|ZVt3J53wp&A2!S!K|{fNpglCP{9N6NPwxe-GWu zz}ffzo_J{*_HV}k5rooGcf{&gc+vlnEu4KiMqX{607Ebnr94RHh|P7p3_^`lp-qnP zdWRBf=R~{}6S0?8z696+%-l4x)P7+8E2OExdezBm#Em$&i{o1um>0Ufgw809F|SHg zZ|4^XcpsPfIV(2SD;T{Iv>xZ!p0JGFsk+-3-`s#9~qqQUTteqp;ktma;(VE zfIqD8z+blC@_`4eu6*OQ0@T-Xf?c&A0G}C# z?rbcwPz9hFXaz00PQ?!l~NKgG6-M_kQsP4XJ?qXjzh};queZl z9si(O2Y8vY($df#b`zk|0_QM_lIw{x_ z2fFwH(&7n_u4MnVugTJ0i$j$Xjw~}_9MOYiF55YlR#vnH2QNQj<9bU=o~;P2V!_EC zWTs5DQwoeGv^wlnFdFhzN9@EXyRe}%h}YIcX%fJQIKAGmh<|G-)-EtC1Y{+xwJ(e# zS=xOon5W7F^!?)iG!=)Hm>L0ocDwY@Ws^5cgXL=p3yvqG?7yVQRu&f(J5|larq(D1 zvi26}amioLr_JevS6X(@u2s6r`b>pb04DtW=)zat|LY^Cyof9e><5|T7&|-Y z%NI7PI2(yOGr>CKmJy-1;Z+QqK#kT|hr*N&rN_k%6tr4n^OZ(AVO5ZYxj5!yU2anmdS|?fIbu>^&w$~>MRUZ5MuK_Nh0gasy!X-SCof@R zV`FPOzppDZi1qlzcYr8+*_&_RG*Bez2?%p(CawS+7<(!iB3iN4xxF^+h^xvmeGV%7 zh|3J22^K&p(V1>dd^k7O+1ZIpydoJ`1o#{;0SqNW2$?{{P1>q^|0&z~a5BS)w3w7M z1BaHPQ0}0%0)>NhZ=T*TH)wirr@mkZNOwBm&)z;i`sSH*bCd3aX2v7a_0!APGTmbS{rTnK@+4$;ItQ*@0B4KPQ)N zf1s)4fzkLz}XBC)1-aw!QjN`FeO6YO3YzO)T^(yqc9W-eB z1zt_!JAN+-gro}H=p4S}L5!W%Hp`0_qz7G{uCA^ICAR)}e-=&qH$WOn(rExw4+s1e zK0rEPrj3g?@RLFt*zl3oqa#>GEI}cK_MZt7#^LqSc>*TV>kB26~pupngsDJ01HMNmQtjN+^h zj0Mgmg5?^ArLVPYXBj_4P$N%HmSCET4I~;YX{N2C-Og z!ZMA*wDMv6!|L-*$*JyYe+|14Vqns6QoBw;p6#9XQ{vM|9`&JOD-Fifgqc)RA+9Ka@~vJ+S&Ub~m)49S)D{L;9?> zkoT+|sUjZ}iuGC=%-`5A@Pox`ItF6jp|60lfW$mFg`ViHs#b*<7(Q_Q)=)X$pR+c5 znY~)v?{af>Mc}PA=6gU_j$r!>kkjZ|r)RPk4TyRqW-i~&#ga$V;aeh*z>lWeMLVpR z4AG7bjALstLZF!i3ubloP29KB0?X@SZAr=BB_ev7TN_8vPWU>e1%>m?%?moMv5D6l zx0>ychW<+%bVl^du2u9^?NXPCpnl)>FA+fIm)nw;SG<>5U88-rHy?_`WpOrYon3v$ z?=8Xhc1w2$E63nJIHE!rn9tREb`zi-Ei?n|9Dh8G;#WP6Ss~g5JANewvH=^BVWYIi zx0_XAWQvvQaRIL@fbcOPkF2p9U)=;P7ik|qI)mm6c)%45IRcmTJx*1G(kVH^oGk8E zH&|kqi=X-SDQc9K4}T`R$LX%O@F#8+6%|mWBS9GiITEzAFph<`L!5eYdq@wn0$IUa zy^Tqhg;9rVI3{R;9qQS2kiu>3xNJlIuQEg-agny^*_0r@*NEI!E4;vk&aE7exjXGu0zr*UIuS& z%(X)a<*JlC( zxAlETQH{HpaKb%vP{m=jSd(?y2dDH`gfB2YBUo; zS>qZ<_35NhniJ2iY&bqvcT^HWy_U$MW{Kp2rU_$V0`UPya>J_@wxGp5eb|kE?*WE4 z)jM~q_3~xcV5bPMzL~WaPf0ypTf`j9e1jR8`{DK- zI&l4WGUDcx*^4onM0djhyAmCrw}#30U0kjxu_(E{D0wINkwEKG3MZy5V-3QUN_4n< zUXT8lIUZjCLVXqAnH0=grh5F_FX73=(R-?W#TB=a_f&=Qdit8udTn@LY0b+&*f8Ax z`f(N)d|UUyJ|8qE!KqXq8c|zaqD`>@%DFYI=OfV*b8B*h7iB~LKcV0a%hvjyHJYXv z7ZZ&pf28D2WBx~N6QPLk=>vBA^F+&iZ{F=9(Z-%Pbxe;upyBLGHn|a#`NuN*dPjYK zbcO#7AO>t^Z){P~*3j!RiL-^rA2a34WFODjo6Ei%D4 zQ(a$GIaC=`)!UY4N|#pjN(=tp()|nLksrzRyIZh&K2|^7IjN78zi8S_zT{1zX-Z)Z zOPK&u$4gSTSqE{}p4L*PJqQjZrG>KJ#LtD(HM9G-3FF zU5us@j@>IuU0Tj9F5C`bu>N4C;eJ3whTnt`uVb>AF6WwgH5-9zD$KnFch=41NBsQ- z)B_It6^$*53fHYNb)CY!oJkK)U{XL1`=Pq1MaGZY#fd?Lj9Gd5pROd%0 zIGk}x*Y#NB>Ulq^Pk-NESn4lF51hzZy+3t0HC9I#Q5$mxb|ReCl=i;u@I2MFR5{$0=wqZ)-liwv>0dfELo_CPH0-X)DxnHni3oeO^Np!k4zKtq_3MXzp2677$ z&p9!q%SfZd7U|qNoc=`Gf~E);t!7qnhN9H^dJRhWcck>*Hsj5y`*$)| ztvl1Ohr}NgzPrO@mYtegcT4eZGGBK|iCuJFcwQ=6`wolC0%tS`e_v6$4H>KbcK?qn zraM1ST`&qp$meTu$H;Ol30T}_GO}^i3Ty0%-dPX2!X|O|#W#8@mXZgh;2gQLhyD#~ zrmHBPHKo0ApX!hncQeZ6NFB>FGI$6W2~3Ht?TdkbFIR#*LS1M~Wbkgmh}eK5utcZ& z(M*#?tB;u?XZW5v_~C3G5&cQc8{GBQ{q25C(BBv` z*6=JK5Y~?ZEb1+pjpqxta|aTyw!TIUQz2{<%f}3YH)f5@WJQAc)ATHb^UJ4GxbgE; z=tL>}?n~5FhZHt1q!LY*cQ})+e zg8`tZvim)jFp-As5mYD&{`r~F4|?7E+Ib1n$#*~|`JBEC`w=_ziVVW~2fxt$=|}s_ z$y=wp2|Z`w#7`bUd)oKXDFkrH1m9mIj?PEZId(pIAIsFf_g8lMJwpW&?{8l>ojd{b zDXigbQ9}%WN?_<&@n>fI^^$bU{%+l$tmf}GqhG;vZz3-*i33mX$p7n^RaJH9eRR5n z`LBmo**e&>{J8O(H*|drS0mM*xLyua8X6GFIsg)!`ah24WTkLiHvRH~-Pn8fnh9lI z$ExMsWdNEri(;$5@jajgA0P*QGs#{l04oQ;D>#HIyK~75nsVv!vr_<5#fQ%}SA)F` z1VGOKFP)+dWT?hfRaNC);|BVSlU7OhscxWOoh~M@vapZ^2Wq_{Tma zCRDV#3`U~@8UsSxZg;|L^wNk(S}v+4WN89C|10Z6A9!`g@~K#Wamvw&7yHPr5D4H08JF=dFAlQPE%!CR6phTak~jpG;@dnaWmB;R z%Ro_~V1NTG4vd6`*@6CJa4uOQ070mmEXwIwS+sF>Y<9mrXv_uez%0CmfH?xfme3Ju z_d|_*)StKV=}28)UoSAK1kK)607dG_)e;5dfkwb;GypibuRA|#jN%6#)!5i*16T|@ zaIhBmKkz5ItAO)50GZ^yJr!5~`XrnDRt*pJBS1#_mw?IjZQ31A0Hbd~Di1K+_&Ce@ zqq6^U_um5KPeHMkG#%CiBvplvfI%*5FEzH3;N`x0s*GvKQN_Z=-$}> z^m&lEl@*dW9$Hk?X*-Aq(n+(c81 zkctX(AZr_!ls$mE`wZ8nz}Y6?)%2?EZ5YQ;)GQMK!QW47$9HZ_#t8jCwOn~1)Or8c z)34f;E>DMub!9UR$%@=bS*0k(F^*Z;93$5-$^AU74HZ_3vNGD7w<=6O$BJ)W)p{QW(~cRt_G`~5jySJECW-|r)R*@ur(9m6JGI**{{2;fH; zCVQ#?TBx6$TH(yA0J@7iaC`QVgK@(;I9`rMyT?(SZpvp#EAroq7`~_{`A2Qiu?>C? zD6RKWsn<>n&hFyr7MXBC54;HsI}`D?V6%2cPF2)IRPHNcW^h*B`6-Y-RSLw;$ zZ)}R-)(sw8bWtJu!aoMVrrg~>; ztbuv)2LC6*rtlJY4fd-jSG*rQ>DqF8tC8LK(}qcV-r`N^{k+}{G?HC0aoNBvR67iS zg`%Bg2?SW*$&%qrP?Dgs8i(-?#N0AKcam*Z$7)#;K( zHacjT_-9n7_`-7=fyd&*Oc-Lkq^6gYAJZT;w0zC%h^yO3Gr@qvsR`ltKWS5zj=4$X z=FXX&ZXB!pnP0V~HaD9M%;WTOkbhILO(y4unPsV9%(j~56H{jfH*Xe++`T+Aoj5A9 zefxH#135h-;}^)Lf($o6kSX{k1{l@?-@O!i*eLrFfe-@k9)B{UY>BOdjI=<7ly5dj zwYIQ$0ALeLR+-1EL+oe(Lc8Pk^nh|&Cul|oa8oXI4`+p9|GR;^WlG+!A3)sC4*(WJ zHy-^C7)=QYi92=?0!1EB3t3rN;Rn1}eBRRyJDN9~zXuMCTTUM1)pP<4cm_yld&(9s ze+&meN@5#@DS4gRbx8HD^ucC=35e(=R&8e0q`+6MKlLG2jc+ z{}cd4jI=*Qm4?=5(cA#8z7=OX^bdc3T$xudT5UH7Z}WD=!fFoY72tth5ZMK+As5vu zu4OC=wYf+Mqqa#lvbMGs_&RJFFq&Z+y!teVS6NC{weK!=Bf*}Y+L<+Rb-3w^R{)+e zVgpcO_Kz;uO$Ua0UrU0P$3d0>8_KJAFE3MZ!dzcRC%Y}tAm8LqVmKt1L5312^Q^&l1^o=gJu5XXfiJlvffYhOLa6k`eqv1r9AogOJSs zQS&Rzk$zeZ>#Nfy5QSTXj?Pm4zkhx8>XrEfkrv6B?;^Fe{rYts|EZA6NvasGdEY`ZXe*G-1VJmTDcE8_ZwV_yQZ>6tXc&yTxT|u?`K~z% zve+=(x+x)zm2kgdKc+N*Uv(IISvC^z+N4{zyqJ%2Q~tZP%$>*^l|A2E}WvZqF-bl2=754#`T>i zx0bZeo>Z+F8^|es8_qS#$P_%5G@7uwz4t8r_UpxVCQ9UgbnzeWprDK26=!<)jZgUE zuMj1{J+t9XVxokHonWz^9OBhijgSi0>t{~L)c3k}&Cq3?<}q@-`od=04u*4nZeDb6 z*7>GXvR)u->x3Je&7C41`(;f1)Z@ zlNug596TS9aegW#(~qWPjdRl)y?Rj?L{l34y9g^?CIZ1HJ`q|=RzB#{Yk>#hNA=IY zjl6{a%_q(y$(W|Nrcw@>SRHUSC#Jhu^LSQNO3n+j$&KQp690PB;d7|a{2WP8KKUX1 z=Sz-3S;mDjH&f|Xw)jFd!h%YjWcl4sBo_`ToaF^hSAv>;^%@<|j4WJlWeo&S@o1!l z_aeRbwA(s!ICl{owMU6w4fBI+K45o(rk`5=Se z+k?#=F|~O#JH1v*C3I>;Mxm(V^5Cy40oYF$cww~2K)Vrxr%kQcTQ2(izTF?|4SVO_ z_=v?;o)Stcy|`^JzV*e)4kPJ!s&<39;aP;TiliVNHYn;1jg{)krY(PA2T*SA{UyIs z8IVYG`Wz`2(|E1&)Tsgj`Nv%JGvk&6<(})((|SmMOJ?~9x&im}f+|GDgf+9W>Hv@v zNw4NIX$C)?Bdw7{tuO%nx51yO{rHwHmXI_zZY`{YvSaAIVWSF1ZJg^DmVat$Ck-jK z(iAP(CTMn{9a>&bDX`Cl-kxY-DZkc&A`{{1{@RP{w7_$J<&nJZD`IoN>2b|B|2Zxi zg=u2^j_5cyChjt}O5Bg>lWdG;?z$uG(Kz0Ys0Y!0A^Sl2l60KM`J7~N_2w>JBTW0qEDfi#VlgOvg6=-4D;Aopz zThr|W3v2M9LoPI-201Zri`mem07jEr{d0WdG-KVy_4zipQ;muH#U%)x zC+a%WIE8j8^;$}2>9!#zq#2D@#_Wt8>s=ODzqQ2m1q6;LY7M5d-}fOPJRA z+3j)Th_0y0oreZluJeY-k_^QT^Ao0C^A46a36CWhg9{42`qWFISoeDDlyV!b?;T16 z@7T&%i@OKey>=A}24CR*E1vZCqWsE7!iLk*{(lfqe;n+mpYZ)*fkAYyvsLn?R0!k{ P5ivb>+PKi@=ga>A0Svde literal 0 HcmV?d00001 diff --git a/docs/assets/tide-display/fixtures/noaa-boston.json b/docs/assets/tide-display/fixtures/noaa-boston.json new file mode 100644 index 00000000..2e0d0885 --- /dev/null +++ b/docs/assets/tide-display/fixtures/noaa-boston.json @@ -0,0 +1 @@ +{"matches":[{"url_contains":"datagetter","params_contain":{"units":"english","product":"water_level"},"body":{"metadata":{"id":"8443970","name":"Boston","lat":"42.3539","lon":"-71.0503"},"data":[{"t":"2026-09-02 18:30","v":"6.577","s":"0.059","f":"0,0,0,0","q":"p"}]}},{"url_contains":"datagetter","params_contain":{"units":"english","interval":"hilo"},"body":{"predictions":[{"t":"2026-09-02 03:14","v":"9.72","type":"H"},{"t":"2026-09-02 09:21","v":"0.489","type":"L"},{"t":"2026-09-02 15:31","v":"10.599","type":"H"},{"t":"2026-09-02 21:57","v":"0.123","type":"L"}]}},{"url_contains":"datagetter","params_contain":{"units":"english","interval":"h"},"body":{"predictions":[{"t":"2026-09-02 00:00","v":"4.756"},{"t":"2026-09-02 01:00","v":"6.951"},{"t":"2026-09-02 02:00","v":"8.763"},{"t":"2026-09-02 03:00","v":"9.683"},{"t":"2026-09-02 04:00","v":"9.356"},{"t":"2026-09-02 05:00","v":"7.933"},{"t":"2026-09-02 06:00","v":"5.852"},{"t":"2026-09-02 07:00","v":"3.619"},{"t":"2026-09-02 08:00","v":"1.699"},{"t":"2026-09-02 09:00","v":"0.581"},{"t":"2026-09-02 10:00","v":"0.818"},{"t":"2026-09-02 11:00","v":"2.473"},{"t":"2026-09-02 12:00","v":"4.833"},{"t":"2026-09-02 13:00","v":"7.178"},{"t":"2026-09-02 14:00","v":"9.178"},{"t":"2026-09-02 15:00","v":"10.42"},{"t":"2026-09-02 16:00","v":"10.448"},{"t":"2026-09-02 17:00","v":"9.25"},{"t":"2026-09-02 18:00","v":"7.202"},{"t":"2026-09-02 19:00","v":"4.796"},{"t":"2026-09-02 20:00","v":"2.508"},{"t":"2026-09-02 21:00","v":"0.774"},{"t":"2026-09-02 22:00","v":"0.124"},{"t":"2026-09-02 23:00","v":"0.92"}]}},{"url_contains":"datagetter","params_contain":{"units":"metric","product":"water_level"},"body":{"metadata":{"id":"8443970","name":"Boston","lat":"42.3539","lon":"-71.0503"},"data":[{"t":"2026-09-02 18:30","v":"2.005","s":"0.018","f":"0,0,0,0","q":"p"}]}},{"url_contains":"datagetter","params_contain":{"units":"metric","interval":"hilo"},"body":{"predictions":[{"t":"2026-09-02 03:14","v":"2.963","type":"H"},{"t":"2026-09-02 09:21","v":"0.149","type":"L"},{"t":"2026-09-02 15:31","v":"3.231","type":"H"},{"t":"2026-09-02 21:57","v":"0.037","type":"L"}]}},{"url_contains":"datagetter","params_contain":{"units":"metric","interval":"h"},"body":{"predictions":[{"t":"2026-09-02 00:00","v":"1.45"},{"t":"2026-09-02 01:00","v":"2.119"},{"t":"2026-09-02 02:00","v":"2.671"},{"t":"2026-09-02 03:00","v":"2.951"},{"t":"2026-09-02 04:00","v":"2.852"},{"t":"2026-09-02 05:00","v":"2.418"},{"t":"2026-09-02 06:00","v":"1.784"},{"t":"2026-09-02 07:00","v":"1.103"},{"t":"2026-09-02 08:00","v":"0.518"},{"t":"2026-09-02 09:00","v":"0.177"},{"t":"2026-09-02 10:00","v":"0.249"},{"t":"2026-09-02 11:00","v":"0.754"},{"t":"2026-09-02 12:00","v":"1.473"},{"t":"2026-09-02 13:00","v":"2.188"},{"t":"2026-09-02 14:00","v":"2.798"},{"t":"2026-09-02 15:00","v":"3.176"},{"t":"2026-09-02 16:00","v":"3.184"},{"t":"2026-09-02 17:00","v":"2.82"},{"t":"2026-09-02 18:00","v":"2.195"},{"t":"2026-09-02 19:00","v":"1.462"},{"t":"2026-09-02 20:00","v":"0.765"},{"t":"2026-09-02 21:00","v":"0.236"},{"t":"2026-09-02 22:00","v":"0.038"},{"t":"2026-09-02 23:00","v":"0.28"}]}}]} \ No newline at end of file diff --git a/docs/assets/tide-display/hero.png b/docs/assets/tide-display/hero.png new file mode 100644 index 0000000000000000000000000000000000000000..6538d56931df794997c279014120bc187514c22a GIT binary patch literal 3035 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 aS9m|-&mF{HyraN{*RwhXr?RxJ{qa9~86!Xd literal 0 HcmV?d00001 diff --git a/docs/assets/tide-display/panel-sizes.png b/docs/assets/tide-display/panel-sizes.png new file mode 100644 index 0000000000000000000000000000000000000000..858f571252a5570f221beb67b40c25b6b1cad9ec GIT binary patch literal 29490 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 l*2F6K9_sOsj8{nbS44$rjF6*2UngDi&#Kiyr literal 0 HcmV?d00001 diff --git a/docs/assets/tide-display/units.png b/docs/assets/tide-display/units.png new file mode 100644 index 0000000000000000000000000000000000000000..0d1ddc83db1b0369af9e04cb94c0be5716ce78c3 GIT binary patch literal 8718 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 literal 0 HcmV?d00001 diff --git a/plugins.json b/plugins.json index f900d57c..c4acd492 100644 --- a/plugins.json +++ b/plugins.json @@ -877,10 +877,10 @@ "plugin_path": "plugins/tide-display", "stars": 0, "downloads": 0, - "last_updated": "2026-07-31", + "last_updated": "2026-09-02", "verified": true, "screenshot": "", - "latest_version": "1.2.0", + "latest_version": "1.3.0", "icon": "fa-water" }, { diff --git a/plugins/tide-display/README.md b/plugins/tide-display/README.md index 9c77a4b8..c10d5e38 100644 --- a/plugins/tide-display/README.md +++ b/plugins/tide-display/README.md @@ -1,70 +1,290 @@ # Tide Display -Coastal tide information with four auto-rotating display modes. +Live coastal tides on your LED matrix, from NOAA. Four screens — an animated +water level, today's tide schedule, a 24-hour curve, and moon-phase stats — +rotating on their own, for any of the ~3000 NOAA tide stations. -**Data source:** [NOAA Tides & Currents](https://tidesandcurrents.noaa.gov/) — free, no API key required (US stations). +![The current-tide screen on a 128x32 panel: FALLING, 6.8ft, with the next low +tide at 9:57p](../../docs/assets/tide-display/hero.png) + +*Every image in this README is real plugin output, rendered at the true panel +size from recorded NOAA responses for station 8443970 (Boston) on 2 September +2026. The times and heights are the real predictions for that day.* --- -## Display Modes +## Table of Contents -| Mode | Shows | -|------|-------| -| **Current** | Animated wave-level bar, tide direction (rising/falling), current height, next two tide events | -| **Schedule** | Today's full tide schedule in columns (up to 4 high/low tides) with mini height bars | -| **Chart** | 24-hour filled tide curve with current-time marker and H/L labels | -| **Stats** | Moon phase icon + name, spring/neap indicator, tidal range, cycle progress bar | +1. [The Four Screens](#the-four-screens) +2. [Installation](#installation) +3. [Finding Your Station](#finding-your-station) +4. [Configuration Reference](#configuration-reference) + - [Station and units](#station-and-units) + - [Choosing screens](#choosing-screens) + - [Colours](#colours) + - [Fonts](#fonts) +5. [Panel Sizes](#panel-sizes) +6. [Where the Data Comes From](#where-the-data-comes-from) +7. [Troubleshooting](#troubleshooting) +8. [Development](#development) +9. [Support](#support) --- -## Setup +## The Four Screens + +Each is a separate display mode. All four are on by default and rotate every +`display_duration` seconds. + +![The four screens on a 128x32 panel: current, schedule, chart and +stats](../../docs/assets/tide-display/display-modes.png) -1. Find your nearest NOAA tide station at **[tidesandcurrents.noaa.gov/stations.html](https://tidesandcurrents.noaa.gov/stations.html)** -2. Note the 7-digit station ID (e.g., `9447130` for Seattle, `8724580` for Key West) -3. Enter it in the **Station ID** field in the plugin configuration +| Screen | Setting | Shows | +|--------|---------|-------| +| **current** | `show_current` | The live water level with an animated surface, whether the tide is rising or falling, and the next tide either side | +| **schedule** | `show_schedule` | Today's four tides as columns, with the next one highlighted | +| **chart** | `show_chart` | The 24-hour prediction curve with H/L markers and a line at the current time | +| **stats** | `show_stats` | Moon phase, whether tides are spring or neap, and today's range | + +The `current` screen prefers a **live** water-level reading where the station +has a sensor, falling back to the prediction where it does not. Many stations +are prediction-only, which is normal and not an error. --- -## Configuration +## Installation + +**From the Plugin Store (recommended).** Open the LEDMatrix web interface at +`http://:5000`, go to **Plugin Manager**, find **Tide Display** in +the **Plugin Store** section, and click **Install**. -| Option | Default | Description | -|--------|---------|-------------| -| `station_id` | — | **Required.** 7-digit NOAA station ID | -| `station_name` | `""` | Optional display name override | -| `units` | `imperial` | `imperial` (feet) or `metric` (meters) | -| `display_duration` | `12` | Seconds to show each mode before rotating | -| `show_current` | `true` | Show the Current screen (animated wave level) | -| `show_schedule` | `true` | Show the Schedule screen (today's H/L tides) | -| `show_chart` | `true` | Show the Chart screen (24-hour tide curve) | -| `show_stats` | `true` | Show the Stats screen (moon phase, spring/neap, range) | -| `show_moon_phase` | `true` | Show moon phase icon on the stats screen | +**Manually.** Copy this directory into your LEDMatrix `plugin-repos/` and +restart the display service. -> Disabling every screen above falls back to showing all four — the plugin never goes blank. -| `tide_color` | `[0,100,200]` | RGB color for tide water fill | -| `highlight_color` | `[0,220,255]` | RGB color for wave crests and chart line | +`enabled` defaults to **`false`**, and `station_id` is blank — with no station +set the plugin draws a short setup prompt rather than failing, so a blank panel +means it is not enabled at all. --- -## Popular Station IDs - -| Location | Station ID | -|----------|-----------| -| Seattle, WA | 9447130 | -| San Francisco, CA | 9414290 | -| Los Angeles, CA | 9410660 | -| Key West, FL | 8724580 | -| Miami, FL | 8723170 | -| Boston, MA | 8443970 | -| New York, NY | 8518750 | -| Bar Harbor, ME | 8413320 | -| Galveston, TX | 8771341 | -| Honolulu, HI | 1612340 | +## Finding Your Station + +Tide predictions are per-station, so this is the one setting you must supply. + +1. Open . +2. Find the station nearest your stretch of coast. +3. Copy its **7-digit ID** — for example `8443970` for Boston, `9414290` for + San Francisco, `8724580` for Key West. + +```json +{ + "tide-display": { + "enabled": true, + "station_id": "8443970", + "station_name": "BOSTON" + } +} +``` + +`station_name` is only a label. Leave it blank and the ID is shown instead — +useful while you are checking you picked the right station, less so afterwards. + +Stations differ in what they offer. All have tide *predictions*; only some have +a live water-level sensor. A station with no sensor still fills every screen, +using predictions throughout. --- -## Notes +## Configuration Reference + +### Station and units + +| Option | Type | Default | What it does | +|--------|------|---------|--------------| +| `enabled` | boolean | `false` | Whether the plugin runs at all | +| `station_id` | string | `""` | The 7-digit NOAA station ID | +| `station_name` | string | `""` | Label shown instead of the ID | +| `units` | string | `imperial` | `imperial` (feet) or `metric` (metres) | +| `display_duration` | number | `12` | Seconds each screen holds the panel | + +![The schedule screen in feet and in metres](../../docs/assets/tide-display/units.png) + +The unit conversion is done by NOAA rather than locally — the plugin asks the +API for `english` or `metric` and displays what comes back — so the heights are +the authoritative figures either way, not a rounding of one into the other. + +### Choosing screens + +| Option | Default | What it does | +|--------|---------|--------------| +| `show_current` | `true` | The animated water-level screen | +| `show_schedule` | `true` | Today's tide times in columns | +| `show_chart` | `true` | The 24-hour curve | +| `show_stats` | `true` | Moon phase and range | +| `show_moon_phase` | `true` | The moon icon and phase name on the stats screen | + +![The stats screen with the moon phase on and off](../../docs/assets/tide-display/moon-phase.png) + +Turning a screen off shortens the rotation rather than leaving a gap. With all +four on and the default 12 seconds each, a full cycle takes just under a +minute. + +`show_moon_phase` only affects the stats screen — the rest of that screen keeps +its layout, so the phase name is replaced by space rather than everything +shifting up. + +### Colours + +| Option | Default | What it does | +|--------|---------|--------------| +| `tide_color` | `[0, 100, 200]` | The water fill | +| `highlight_color` | `[0, 220, 255]` | Wave crests and the chart line | + +![The current screen in the default blue, teal, amber and +violet](../../docs/assets/tide-display/colors.png) + +The two work together: `tide_color` is the body of the water and +`highlight_color` picks out its surface, so keeping the highlight lighter than +the fill is what makes the water read as water. + +### Fonts + +`customization.tide_text` (the figures) and `customization.label_text` (the +HIGH/LOW captions) each take `font`, `font_size` and `text_color`. + +| Font | Kind | Notes | +|------|------|-------| +| `4x6-font.ttf` | Scalable | The default; fits the small columns well | +| `PressStart2P-Regular.ttf` | Scalable | Chunky; readable further away, at the cost of fitting less | +| `5by7.regular.ttf` | Scalable | A rounder 5×7 face | +| `5x7.bdf` | Bitmap | Crisp; drawn at its native 7px | +| `4x6.bdf` | Bitmap | Native 6px, which matches the default `font_size` | + +**`font_size` only affects the scalable faces.** A `.bdf` is drawn at the one +pixel size its file declares. Defaults are `font_size: 6` with +`tide_text.text_color` `[205, 225, 255]` and `label_text.text_color` +`[120, 150, 200]`. + +--- + +## Panel Sizes + +![The current screen on 64x32, 128x32, 128x64 and 256x32 +panels](../../docs/assets/tide-display/panel-sizes.png) + +Height helps this plugin more than width, because three of the four screens +stack text: + +![The stats screen at 32 and 64 rows, and the chart at 64 +rows](../../docs/assets/tide-display/taller-panel.png) + +- **64×32** fits the level and direction; the schedule columns get tight. +- **128×32** is the size the layouts are tuned for. +- **128×64** is where the chart really pays off — a taller curve is far easier + to read at a glance — and the stats screen stops crowding. +- **256×32** gives the schedule columns and the chart more room horizontally. + +> On a 32-row panel the stats screen draws the range line and the percentage +> close enough to touch, and they overlap at some values. It is legible but +> untidy; the chart and schedule screens are unaffected, and 64 rows clears it. + +--- + +## Where the Data Comes From + +NOAA's Tides and Currents API (`api.tidesandcurrents.noaa.gov`). No API key and +no account are needed. + +Three requests per refresh, all for the configured station: + +| Request | Used by | +|---------|---------| +| High/low predictions for today | schedule, current, stats | +| Hourly predictions for today | chart | +| Latest water level | current, where the station has a sensor | + +Predictions use the **MLLW** datum and the station's local time including +daylight saving, which is why the times shown match published local tide +tables. `update_interval` in the manifest sets the refresh cadence, hourly by +default — tide predictions for a day do not change, so there is nothing to gain +from polling faster. + +--- + +## Troubleshooting + +**Nothing appears.** +`enabled` defaults to `false`. + +**It shows a setup prompt.** +`station_id` is blank. See [Finding Your Station](#finding-your-station). + +**"No data" or empty screens with a station set.** +Check the ID is the 7-digit tide-station number, not a buoy or current-station +ID from a different NOAA product. The log records the API error NOAA returned, +which usually names the problem directly. + +**The current screen shows a prediction rather than a live reading.** +Most stations have no live water-level sensor. This is expected and logged at +debug level rather than as an error. + +**Heights look wrong for my area.** +Check `units`, then check the station — neighbouring stations can differ by +several feet, and the nearest one by road is not always the nearest by water. + +**The times are off by an hour.** +Predictions come back in the station's local time including daylight saving. If +they disagree with a published table, the table may be in standard time +year-round. + +**I picked a font and nothing changed.** +On a current version all five faces work. Older versions loaded a `.bdf` only +when its native pixel size happened to equal `font_size`, so `4x6.bdf` worked +at the default 6 and `5x7.bdf` silently fell back. + +--- + +## Development + +### Project structure + +```text +tide-display/ +├── manifest.json # Plugin metadata and version history +├── manager.py # TideDisplayPlugin — all four screens +├── config_schema.json # Settings schema; source of truth for defaults +├── render_preview.py # Standalone preview generator (see note below) +├── preview_*.png # Its output +├── requirements.txt +└── README.md +``` + +`render_preview.py` draws mock versions of the screens with its own copy of the +palette — its header notes the colours "must match manager.py". The images in +this README are made a different way: `scripts/render_docs_assets.py` runs the +real plugin against recorded NOAA responses, so they cannot drift from what the +plugin actually draws. + +### Regenerating the images in this README + +```bash +python scripts/render_docs_assets.py --plugin tide-display +``` + +`--check` verifies the committed images still match. The fixture under +`docs/assets/tide-display/fixtures/` holds real NOAA responses for both unit +systems, matched on the query parameters, so the metric screens show genuine +metric predictions rather than the same numbers relabelled. + +--- + +## Support + +- YouTube: +- Instagram: +- Discord: +- Sponsor: [GitHub Sponsors](https://github.com/sponsors/ChuckBuilds) · + [Buy Me a Coffee](https://buymeacoffee.com/chuckbuilds) · + [Ko-fi](https://ko-fi.com/chuckbuilds/) -- Tide predictions are cached for 24 hours — minimal API usage -- Live water level (where available) is cached for 6 minutes -- If the station does not provide live observations, the plugin interpolates from hourly predictions -- Not all NOAA stations provide real-time water level data; predictions are always available +Released under the GNU General Public License v3.0 — see [LICENSE](LICENSE). diff --git a/plugins/tide-display/manager.py b/plugins/tide-display/manager.py index d3d8d991..378025a6 100644 --- a/plugins/tide-display/manager.py +++ b/plugins/tide-display/manager.py @@ -211,12 +211,42 @@ def _load_element_font(self, element_cfg: Dict): font = ImageFont.truetype(path, size) break except Exception as e: + # A .bdf exists at exactly one pixel size and FreeType + # rejects any other. That made the picker's behaviour depend + # on font_size by coincidence: 4x6.bdf loaded because its + # native 6 happens to match the default, while 5x7.bdf + # silently fell back to the default face. Retry at the size + # the file declares. + native = self._bdf_pixel_size(path) + if native is not None and native != size: + try: + font = ImageFont.truetype(path, native) + self.logger.debug( + "Loaded bitmap font %s at its native size %d " + "(requested %d)", name, native, size) + break + except Exception: + pass self.logger.warning("Could not load font %s@%d: %s", name, size, e) if font is None and not any(os.path.exists(p) for p in candidates): self.logger.warning("Font file not found: %s; using default font", name) self._font_cache[key] = font return self._font_cache[key] + @staticmethod + def _bdf_pixel_size(path): + """The pixel size a .bdf font declares, or None if it does not.""" + try: + with open(path, "r", encoding="latin-1") as handle: + for line in handle: + if line.startswith("PIXEL_SIZE"): + return int(line.split()[1]) + if line.startswith("CHARS"): + break # past the header + except (OSError, ValueError, IndexError): + return None + return None + def _element_style(self, color, small: bool): """Map a draw call's palette colour to its customization element. diff --git a/plugins/tide-display/manifest.json b/plugins/tide-display/manifest.json index 961781b1..1363edae 100644 --- a/plugins/tide-display/manifest.json +++ b/plugins/tide-display/manifest.json @@ -1,7 +1,7 @@ { "id": "tide-display", "name": "Tide Display", - "version": "1.2.0", + "version": "1.3.0", "author": "ChuckBuilds", "description": "Coastal tide display with animated wave level, tide schedule, 24-hour chart, and tidal statistics. Powered by the free NOAA Tides & Currents API (US stations, no API key required).", "entry_point": "manager.py", @@ -25,6 +25,11 @@ ">=2.0.0" ], "versions": [ + { + "version": "1.3.0", + "released": "2026-09-02", + "ledmatrix_min": "2.0.0" + }, { "version": "1.2.0", "released": "2026-07-31", @@ -83,7 +88,7 @@ "license": "GPL-3.0", "homepage": "https://github.com/ChuckBuilds/ledmatrix-plugins/tree/main/plugins/tide-display", "config_schema": "config_schema.json", - "last_updated": "2026-07-31", + "last_updated": "2026-09-02", "stars": 0, "downloads": 0, "verified": true, diff --git a/scripts/docs_render_support/_docs_http_replay.py b/scripts/docs_render_support/_docs_http_replay.py index 9082ba5f..bdcefb26 100644 --- a/scripts/docs_render_support/_docs_http_replay.py +++ b/scripts/docs_render_support/_docs_http_replay.py @@ -12,6 +12,16 @@ {"url_contains": "baseball/mlb/scoreboard", "body": { ...ESPN JSON... }} ]} +An entry may also carry ``params_contain``, for an API that puts several +endpoints behind one URL and tells them apart by query string:: + + {"url_contains": "datagetter", + "params_contain": {"product": "water_level"}, + "body": { ... }} + +Entries are tried in order and the first whose URL *and* params both match +wins, so put the more specific entries first. + Only matching URLs are intercepted. Everything else -- logo downloads in particular -- goes to the real network untouched. """ @@ -65,24 +75,31 @@ def install(): if not matches: return - def _match(url): + _MISS = object() + + def _match(url, params): + params = params or {} for entry in matches: - if entry.get("url_contains", "") in url: - return entry.get("body") - return None + if entry.get("url_contains", "") not in url: + continue + wanted = entry.get("params_contain") or {} + if any(str(params.get(key)) != str(value) for key, value in wanted.items()): + continue + return entry.get("body") + return _MISS real_session_get = requests.Session.get real_get = requests.get def session_get(self, url, *args, **kwargs): - body = _match(str(url)) - if body is None: + body = _match(str(url), kwargs.get("params")) + if body is _MISS: return real_session_get(self, url, *args, **kwargs) return _ReplayResponse(body) def plain_get(url, *args, **kwargs): - body = _match(str(url)) - if body is None: + body = _match(str(url), kwargs.get("params")) + if body is _MISS: return real_get(url, *args, **kwargs) return _ReplayResponse(body) From 5e8621a2175a0e2a6a3f21f83ce69451feb1bb14 Mon Sep 17 00:00:00 2001 From: Chuck <33324927+ChuckBuilds@users.noreply.github.com> Date: Wed, 2 Sep 2026 18:40:26 -0400 Subject: [PATCH 2/3] docs(tide-display): restore content the section audit missed Comparing against the old README by eye turned up three things my heading heuristic passed over -- it matched incidental words rather than content, so 'Popular Station IDs' looked covered because the new file happens to say 'station' elsewhere. Restored, each verified against the source first: - Disabling every screen shows all four rather than nothing. _build_enabled_modes returns 'modes or list(self.MODES)', with a comment saying the plugin should never go dark. Worth stating, since the obvious reading of four booleans is that turning them all off leaves a blank panel. - The ten-station starter table. Finding a station ID is the one thing a new user has to do, and a handful of known-good IDs saves a trip to NOAA's map. - Caching, and what happens when NOAA is unreachable. Predictions sit under a stable per-station key and refetch on a date change; the live level is cached for six minutes; and STALE_MAX_DAYS serves the last good predictions for up to two days offline before falling back to a placeholder, because tides shift about fifty minutes a day and older times would be confidently wrong. The audit is a floor, not a guarantee -- it catches dropped config keys reliably and dropped prose only sometimes. Co-Authored-By: Claude Opus 5 --- plugins/tide-display/README.md | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/plugins/tide-display/README.md b/plugins/tide-display/README.md index c10d5e38..00faaab3 100644 --- a/plugins/tide-display/README.md +++ b/plugins/tide-display/README.md @@ -25,6 +25,7 @@ size from recorded NOAA responses for station 8443970 (Boston) on 2 September - [Fonts](#fonts) 5. [Panel Sizes](#panel-sizes) 6. [Where the Data Comes From](#where-the-data-comes-from) + - [Caching and what happens offline](#caching-and-what-happens-offline) 7. [Troubleshooting](#troubleshooting) 8. [Development](#development) 9. [Support](#support) @@ -89,6 +90,16 @@ Tide predictions are per-station, so this is the one setting you must supply. `station_name` is only a label. Leave it blank and the ID is shown instead — useful while you are checking you picked the right station, less so afterwards. +Some stations to start from: + +| Location | ID | Location | ID | +|----------|-----|----------|-----| +| Seattle, WA | `9447130` | Boston, MA | `8443970` | +| San Francisco, CA | `9414290` | New York, NY | `8518750` | +| Los Angeles, CA | `9410660` | Bar Harbor, ME | `8413320` | +| Key West, FL | `8724580` | Galveston, TX | `8771341` | +| Miami, FL | `8723170` | Honolulu, HI | `1612340` | + Stations differ in what they offer. All have tide *predictions*; only some have a live water-level sensor. A station with no sensor still fills every screen, using predictions throughout. @@ -129,6 +140,10 @@ Turning a screen off shortens the rotation rather than leaving a gap. With all four on and the default 12 seconds each, a full cycle takes just under a minute. +**Turning all four off shows all four.** The plugin treats an empty selection +as "no preference" rather than "show nothing", so it can never go dark by +configuration alone. + `show_moon_phase` only affects the stats screen — the rest of that screen keeps its layout, so the phase name is replaced by space rather than everything shifting up. @@ -205,9 +220,20 @@ Three requests per refresh, all for the configured station: Predictions use the **MLLW** datum and the station's local time including daylight saving, which is why the times shown match published local tide -tables. `update_interval` in the manifest sets the refresh cadence, hourly by -default — tide predictions for a day do not change, so there is nothing to gain -from polling faster. +tables. + +### Caching and what happens offline + +Requests are kept to a minimum, because a day's predictions do not change once +published: + +- **Predictions** are cached under a stable per-station key and refetched only + when the cached entry is for a different day. +- **The live water level** is cached for 6 minutes. +- **If NOAA is unreachable**, the last good predictions keep being served for up + to **two days**. Past that the plugin shows a placeholder instead: tides shift + roughly 50 minutes a day, so three-day-old times would be confidently wrong, + which is worse than admitting there is no data. --- From a5a507c1816d775326f9339c8767927c9df0fe6c Mon Sep 17 00:00:00 2001 From: Chuck <33324927+ChuckBuilds@users.noreply.github.com> Date: Wed, 2 Sep 2026 18:51:28 -0400 Subject: [PATCH 3/3] refactor(tide-display): remove the preview generator that re-implemented the screens render_preview.py drew its own mock versions of all four screens, with a header asking that its palette "must match manager.py". Nothing enforced that, so its seven committed preview_*.png files could drift from what the plugin actually draws and no check would notice -- and they shipped to every Pi on install, about 115KB of images the display never reads. The README's screenshots now come from scripts/render_docs_assets.py, which runs the real plugin against recorded NOAA responses and is verifiable with --check, so the mock generator no longer buys anything the repo does not have a better version of. Worth contrasting with geochron, which has a render_preview.py of its own and does it correctly: it imports geochron_renderer, the same module manager.py draws with, so its previews cannot disagree with the plugin. That is the pattern to copy if a standalone generator is wanted here again -- factor the drawing out and have both call it, rather than keeping a second copy of the palette. Nothing else in the repo referenced the removed files. Co-Authored-By: Claude Opus 5 --- plugins/tide-display/README.md | 13 +- plugins/tide-display/preview_chart.png | Bin 3328 -> 0 bytes plugins/tide-display/preview_chart_sizes.png | Bin 14222 -> 0 bytes plugins/tide-display/preview_current.png | Bin 6057 -> 0 bytes .../tide-display/preview_current_sizes.png | Bin 17804 -> 0 bytes plugins/tide-display/preview_schedule.png | Bin 3821 -> 0 bytes plugins/tide-display/preview_sheet.png | Bin 66585 -> 0 bytes plugins/tide-display/preview_stats.png | Bin 3001 -> 0 bytes plugins/tide-display/render_preview.py | 569 ------------------ 9 files changed, 6 insertions(+), 576 deletions(-) delete mode 100644 plugins/tide-display/preview_chart.png delete mode 100644 plugins/tide-display/preview_chart_sizes.png delete mode 100644 plugins/tide-display/preview_current.png delete mode 100644 plugins/tide-display/preview_current_sizes.png delete mode 100644 plugins/tide-display/preview_schedule.png delete mode 100644 plugins/tide-display/preview_sheet.png delete mode 100644 plugins/tide-display/preview_stats.png delete mode 100644 plugins/tide-display/render_preview.py diff --git a/plugins/tide-display/README.md b/plugins/tide-display/README.md index 00faaab3..fff87410 100644 --- a/plugins/tide-display/README.md +++ b/plugins/tide-display/README.md @@ -279,17 +279,16 @@ tide-display/ ├── manifest.json # Plugin metadata and version history ├── manager.py # TideDisplayPlugin — all four screens ├── config_schema.json # Settings schema; source of truth for defaults -├── render_preview.py # Standalone preview generator (see note below) -├── preview_*.png # Its output ├── requirements.txt └── README.md ``` -`render_preview.py` draws mock versions of the screens with its own copy of the -palette — its header notes the colours "must match manager.py". The images in -this README are made a different way: `scripts/render_docs_assets.py` runs the -real plugin against recorded NOAA responses, so they cannot drift from what the -plugin actually draws. +Screenshots come from `scripts/render_docs_assets.py`, which runs the **real +plugin** against recorded NOAA responses. An earlier `render_preview.py` drew +mock versions of the screens from its own copy of the palette — its header +asked that the colours "must match manager.py" — so its output could drift from +what the plugin actually draws, with nothing to catch it. It has been removed +now that the images are generated from the plugin itself. ### Regenerating the images in this README diff --git a/plugins/tide-display/preview_chart.png b/plugins/tide-display/preview_chart.png deleted file mode 100644 index 857f03af05646ef29558f389e9dbc022ba03b5b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3328 zcmZ`+XH-+^7QOUHsDgk&$}l4%ObEz;ASeoghzNre=_O)8LX#rhNC}95s2M~I5Q+*x zBZLqjMnZWLS`1Q5C=OML6cL0;7^x3DP&)NIzb8ecQt);jqL=*r3 zajP@t_5dKzxcNR0;@^CpRDZk*0Aj6H=BAEOd9y>Nw>_Pegy)z16KxdF2oSH!6z%y5 zCQ3uqbtZK?}7$h2_q$6xP$SOW$hG<)TjUZ@uXj2Sh%L(~bB zp$+W8UsFBog8R_H9d-!2LM1OzBS&HzM!w8{!9-qVv){D-pt3P_sVcI{o`ro;AM^H8 z>`Gzg2`=|3>=^5P4nI(cdC!g)0D#Iff_?x10(Aj^lvE)fpsM59yceGHcvQ0CLiE=K z<_E^a{iKEpkGQD{??6~q{c`W%Cl+(%wq{CKEuNl=p-QyLKapLB(ZD&!>EjJq=5v%MX|r_CzaEh$VoQwu7K2GK{(Und^C?i&&!%G;V_PjZi|q-~_vR^?u*Qihf24dMK>tK{c*9;3zMio}t@^ zM?>*VPBpBXj?)cmW*oR-I0vsBB)Pm;JK_}pJFzmW-8tv=aDd%ZLdu!RrYK{OG+`zd zPsC&Lyv`0E7|OQUw_Nj$P40Nkv+yBX$TZX0vU26VU;~3ec|{y;RVfHI?X=hb)j64r z@^(*IiYxM2snP4B{#GmlX5w)f^E`;LH=irR34lW!BO!nqT=K}6S{JF(WIJZUZ&rMe}`P*5Kzpc zD6|y?{bY{6#6DPD!db@Sc7vg3knT39Wg6F|jb{a$H}g}aI2_Y7LRHokvqpRR1XE?= zS2#8#sab-MJM5hLc3FP>SJPFR*NtaOEEhX~d~3Y$_bu?I`b`66!R4rcEUo@f`1qFc zb$4>#b`y|wvQDzHF-ks$s_(LgGnR-d(=Ssul;^0#R=3K%tAp!a->TdGZAaL-dq`T> z#M20+2+^t(;IKxI=}Xkip*({0+veN!>%G1-@(uiilPJnku# zXK7Un5OsMv;@MmWs^+EMBJsMEx(E71oeZQTO5|{sz4UfWe{V}|n z_hg#Xji+x3E=>MpQMy7nuE$)qhEU_}xKLhRa!A@tW%;wL zoTE$1c@;1HXaZ^4{!}+4dH?g^Hlh4EX-H6=&l>zp4Puv6#0srTD+`-@a{Qv4&Z`}G zk-{(ba{af^y3WX^^*?2qg5VE+5yrgr439d$b=980&}*uho-fDOW1qi{m`QM8O#J0O zB5oqDK;$zXL0ulfQUcmgN5$ncc2OjpJ)NK3{6-TRF`Gy)SQB|n|4@Oni=HvoHeq^D zhrF)TqnnTP3cfGLH%$?*V(6(sc>yrw*HjU=x%epq{L-{+bI&AU(NiG^2@~tH3<&Ov zmALtgd~AJkioGzwVYz3SAfJ-sV%I`ulh}G5I@_M~?`izVRy{U}J{KL{7|UmJ4Zo&c z-8yA+Kc<(EUIub0LpGqewccX#t6$%a41IGpS|pO#_GwZVXm0wt3Vu(P zrTrGzy-Jk`UM-AHek%$N0wS~d4piCdwrF(#6(df_}gWD%X~AF0%!B#Wgf zV>d~Ay}^!CZGSQlA|{+SbjAeLSke(@vT|nTT0?X_D?HhKs>(C=;(kS5ebQI}3%&~h zP;=OIr?CB*?-H|CXRv)3dQ5Fa)V(0etOMg|>OES|WsxrnlC5^9Zj{m;KBZj_;F;sNh2?%5)^CHqGW|^Fxos-^uVTG&Wr!{wMJ}oltGdmN(xO~`Pk{iE* zp^LnIT{WXEq>^@p7!As$jHhXd)e2x^*c16k95JhUICgQFKnPo2pO5YAZ^;z<_^ni2qbLqD|%WyQ}{bMar4gxu(Gf< Je`)5E_+Q0+KuZ7s diff --git a/plugins/tide-display/preview_chart_sizes.png b/plugins/tide-display/preview_chart_sizes.png deleted file mode 100644 index 6ac93d13a67398ecee379ff4830761bc8f8239e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14222 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 IPaePgAJaD@=l}o! diff --git a/plugins/tide-display/preview_current.png b/plugins/tide-display/preview_current.png deleted file mode 100644 index bf5c7be20397ff0abf1de871b0e15c7094ea43c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6057 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 diff --git a/plugins/tide-display/preview_current_sizes.png b/plugins/tide-display/preview_current_sizes.png deleted file mode 100644 index fef9b79e3c0556c3378592147b787a59cfe92141..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17804 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 diff --git a/plugins/tide-display/preview_sheet.png b/plugins/tide-display/preview_sheet.png deleted file mode 100644 index da728532761ca4300b09ad77c7cf85ae31618b2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66585 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õonnA=N?hD2B$Ok~cCiFi9!S{}3{re8 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 P2nMH5xVuyz3%>aq6YhW5 diff --git a/plugins/tide-display/render_preview.py b/plugins/tide-display/render_preview.py deleted file mode 100644 index 02709fdf..00000000 --- a/plugins/tide-display/render_preview.py +++ /dev/null @@ -1,569 +0,0 @@ -#!/usr/bin/env python3 -""" -Render tide-display plugin preview images without needing the full LEDMatrix system. -Outputs one PNG per mode per display size, plus a composite sheet. - -Usage: python3 render_preview.py -""" - -import math, os -from datetime import datetime, timedelta - -from PIL import Image, ImageDraw, ImageFont - -# ── Palette (must match manager.py) ────────────────────────────────────────── -C_BG = ( 0, 0, 5) -C_SKY_HORIZON = ( 0, 20, 65) -C_WATER_TOP = ( 0, 30, 90) -C_WATER_MID = ( 0, 65, 160) -C_WATER_DEEP = ( 0, 40, 120) -C_WAVE1 = ( 0, 140, 220) -C_WAVE_CREST = (160, 240, 255) -C_CHART_FILL = ( 0, 45, 130) -C_CHART_LINE = ( 0, 215, 255) -C_CHART_GLOW1 = ( 0, 110, 185) -C_CHART_GLOW2 = ( 0, 65, 135) -C_GRID = ( 30, 48, 96) -C_NOW_LINE = (255, 220, 40) -C_HIGH = (255, 195, 45) -C_LOW = ( 75, 190, 255) -C_RISING = ( 45, 230, 95) -C_FALLING = (255, 75, 75) -C_SLACK = (255, 210, 60) -C_TEXT = (205, 225, 255) -C_LABEL = (120, 150, 200) -C_DIM = ( 75, 90, 120) -C_MOON = (245, 238, 200) -C_BAR_OUT = ( 45, 72, 130) -C_COL_HIGH = ( 31, 23, 10) -C_COL_LOW = ( 9, 23, 36) -C_COL_HIGH_NEXT = ( 56, 43, 15) -C_COL_LOW_NEXT = ( 16, 42, 61) -# aliases for backward compat with render helpers -C_BAR_OUTLINE = C_BAR_OUT - - -def _lerp(c1, c2, t): - return tuple(int(a + (b - a) * t) for a, b in zip(c1, c2)) - -def _safe_iso(s): - try: - return datetime.fromisoformat(s) - except (TypeError, ValueError): - return None - -def _layout(dw, dh): - c_ml, c_mr, c_mt = 3, 3, 1 - c_axis = max(9, int(dh * 0.20)) # 9px min: 1px line + 2px gap + 6px font - row1 = 1 - row2 = max(9, int(dh * 0.28)) - row3 = max(18, int(dh * 0.55)) - row4 = max(27, int(dh * 0.78)) - wave_amp = max(2, min(5, dh // 10)) - return dict( - c_x=c_ml, c_y=c_mt, - c_w=dw - c_ml - c_mr, - c_h=dh - c_axis - c_mt - 1, - c_axis=c_axis, - wave_amp=wave_amp, - row1=row1, row2=row2, row3=row3, row4=row4, - half=dw // 2, - small=(dw <= 64), medium=(64 < dw <= 128), large=(dw > 128), - ) - -# ── Fake tide data (Seattle-ish semi-diurnal) ───────────────────────────────── -_BASE = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) - -def _make_hilo(): - """Four typical semi-diurnal tides for today.""" - return [ - {'dt': (_BASE + timedelta(hours=2, minutes=24)).isoformat(), 'height': 5.6, 'type': 'H'}, - {'dt': (_BASE + timedelta(hours=8, minutes=47)).isoformat(), 'height': 0.8, 'type': 'L'}, - {'dt': (_BASE + timedelta(hours=15, minutes=13)).isoformat(), 'height': 4.9, 'type': 'H'}, - {'dt': (_BASE + timedelta(hours=21, minutes=35)).isoformat(), 'height': 1.2, 'type': 'L'}, - ] - -def _make_hourly(): - """24-point cosine curve matching the hilo data.""" - hrs = [] - for h in range(24): - v = (3.2 + 2.4 * math.cos((h - 2.4) * 2 * math.pi / 12.4) - + 0.6 * math.cos((h - 2.4) * 2 * math.pi / 24.8)) - hrs.append(max(0.2, v)) - return hrs - - -# ── Font loader ──────────────────────────────────────────────────────────────── -def _load_fonts(): - search = [ - "/var/home/chuck/Github/LEDMatrix/assets/fonts/4x6-font.ttf", - "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", - "/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf", - ] - for path in search: - if os.path.exists(path): - try: - tiny = ImageFont.truetype(path, 6) - small = ImageFont.truetype(path, 7) - return tiny, small - except OSError: - continue - # Fallback to PIL default - def_ = ImageFont.load_default() - return def_, def_ - -FONT_TINY, FONT_SMALL = _load_fonts() - -def _txt(draw, x, y, text, color=C_TEXT, font=None): - draw.text((x, y), text, fill=color, font=font or FONT_TINY) - -def _txt_c(draw, cx, y, text, color=C_TEXT, font=None): - fnt = font or FONT_TINY - bbox = draw.textbbox((0, 0), text, font=fnt) - w = bbox[2] - bbox[0] - draw.text((cx - w // 2, y), text, fill=color, font=fnt) - - -# ── Drawing helpers (same logic as manager.py) ───────────────────────────────── - -WAVE_PHASE = 24.0 # fixed phase for preview - -def _wave_y(px, wave_phase=WAVE_PHASE): - p = wave_phase - y1 = math.sin((px + p) * 0.28) * 0.85 - y2 = math.sin((px + p * 1.35) * 0.47) * 0.45 - y3 = math.sin((px + p * 0.72) * 0.71) * 0.2 - return y1 + y2 + y3 - -def _draw_stars(draw, dw, sky_h): - n = max(0, (dw * sky_h) // 120) - h = 2654435761 - for i in range(n): - h = (h ^ (i * 2246822519 + 1)) & 0xFFFFFFFF - sx = h % dw - sy = (h >> 16) % max(1, sky_h - 2) - b = 18 + (h >> 8) % 34 - draw.point((sx, sy), fill=(b, b + 8, b + 22)) - -def full_wave(canvas, draw, dw, dh, fill_ratio, wave_phase=WAVE_PHASE): - """Full-display animated water: mirrors manager.py _full_wave().""" - effective = min(fill_ratio, 0.18) - fill_px = max(4, int(dh * effective)) - surf_y = dh - fill_px - - sky_top = (2, 4, 18) - for py in range(surf_y + 1): - t = py / max(surf_y, 1) - draw.line([(0,py),(dw-1,py)], fill=_lerp(sky_top, C_SKY_HORIZON, t*t)) - - _draw_stars(draw, dw, surf_y) - - for py in range(surf_y, dh): - t = (py - surf_y) / max(fill_px, 1) - if t < 0.5: - color = _lerp(C_WATER_TOP, C_WATER_MID, t * 2) - else: - color = _lerp(C_WATER_MID, C_WATER_DEEP, (t - 0.5) * 2) - draw.line([(0,py),(dw-1,py)], fill=color) - - horizon_c = _lerp(_lerp(C_SKY_HORIZON, C_WATER_TOP, 0.5), (80, 140, 220), 0.35) - draw.line([(0, surf_y), (dw-1, surf_y)], fill=horizon_c) - - wave_ys = [surf_y + int(_wave_y(px, wave_phase)) for px in range(dw)] - - for px in range(dw): - wy = wave_ys[px] - if 0 <= wy < surf_y: - bt = (math.sin((px + wave_phase * 1.3) * 0.11) + 1) * 0.5 - draw.point((px, wy), fill=_lerp(C_WAVE1, C_WAVE_CREST, bt * 0.72)) - if wy + 1 < dh: - draw.point((px, wy+1), fill=_lerp(C_WATER_TOP, C_WAVE1, 0.7)) - - for px in range(0, dw): - wy_p = wave_ys[max(0, px-2)] - wy_c = wave_ys[px] - wy_n = wave_ys[min(dw-1, px+2)] - if wy_c <= wy_p and wy_c <= wy_n and wy_c < surf_y: - wy = wy_c - 1 - if 0 <= wy < dh: - draw.point((px, wy), fill=(220, 252, 255)) - - return surf_y - -def _txt_s(draw, x, y, text, color=C_TEXT, font=None): - """Draw text with a 1px drop shadow.""" - fnt = font or FONT_TINY - draw.text((x + 1, y + 1), text, fill=(0, 0, 8), font=fnt) - draw.text((x, y), text, fill=color, font=fnt) - -def draw_arrow(draw, cx, cy, direction, sz=4): - c = C_RISING if direction=='RISING' else C_FALLING if direction=='FALLING' else C_SLACK - if direction == 'RISING': - draw.polygon([(cx,cy-sz),(cx-sz,cy+sz//2),(cx+sz,cy+sz//2)], fill=c) - elif direction == 'FALLING': - draw.polygon([(cx,cy+sz),(cx-sz,cy-sz//2),(cx+sz,cy-sz//2)], fill=c) - else: - draw.line([(cx-sz,cy),(cx+sz,cy)], fill=c, width=2) - -def draw_moon(draw, cx, cy, r, phase): - bbox = [cx-r, cy-r, cx+r, cy+r] - if phase < 0.04 or phase > 0.96: - draw.ellipse(bbox, outline=C_LABEL, width=1); return - if 0.47 < phase < 0.53: - draw.ellipse(bbox, fill=C_MOON, outline=C_MOON); return - draw.ellipse(bbox, fill=C_MOON, outline=C_MOON) - frac = abs(phase - 0.5) * 2 - dark_w = max(0, min(r*2, int(r*2*frac))) - dx = (cx - r) if phase < 0.5 else (cx + r - dark_w) - if dark_w > 0: - draw.ellipse([dx, cy-r, dx+dark_w, cy+r], fill=C_BG) - draw.ellipse(bbox, outline=_lerp(C_BG, C_MOON, 0.4), width=1) - -def _fmth(h, unit='ft'): return f"{h:.1f}{unit}" -def _fmtt(iso): - try: - dt = datetime.fromisoformat(iso) - hr = dt.hour % 12 or 12 - return f"{hr}:{dt.minute:02d}{'a' if dt.hour<12 else 'p'}" - except (TypeError, ValueError): - return '--' - -# ── Mode renderers ───────────────────────────────────────────────────────────── - -def render_current(dw, dh, hilo, hourly, phase=24.0): - canvas = Image.new('RGB', (dw, dh), C_BG) - draw = ImageDraw.Draw(canvas) - L = _layout(dw, dh) - - heights = [e['height'] for e in hilo] - lo_h, hi_h = min(heights), max(heights) - cur_level = lo_h + (hi_h - lo_h) * 0.42 - fill_ratio = (cur_level - lo_h) / max(hi_h - lo_h, 0.01) - direction = 'RISING' - - surf_y = full_wave(canvas, draw, dw, dh, fill_ratio, phase) - sky_h = surf_y - - PAD = 2 - r1 = PAD - r2 = r1 + 8 - r3 = r2 + 8 if (r2 + 8) < sky_h - 4 else None - r4 = r3 + 7 if r3 and (r3 + 7) < sky_h - 4 else None - - dir_c = C_RISING - _txt_s(draw, 3, r1, direction, dir_c) - arr_x = 3 + len(direction) * 4 + 3 - if arr_x < dw // 2 - 6: - draw_arrow(draw, arr_x, r1 + 3, direction, sz=3) - _txt_s(draw, 3, r2, _fmth(cur_level), C_TEXT) - - mid = dw // 2 - 1 - if sky_h > 12: - draw.line([(mid, PAD), (mid, sky_h - PAD)], fill=C_BAR_OUT) - - rx = dw // 2 + 3 - now = datetime.now() - nexts = [e for e in hilo if _safe_iso(e['dt']) and _safe_iso(e['dt']) > now][:2] - - if nexts: - t0 = nexts[0] - sym = 'HI' if t0.get('type','?') == 'H' else 'LO' - _txt_s(draw, rx, r1, f"{sym} {_fmtt(t0['dt'])}", C_TEXT) - tc0 = C_HIGH if t0.get('type','?') == 'H' else C_LOW - _txt_s(draw, rx, r2, _fmth(t0['height']), tc0) - - if len(nexts) >= 2 and r3 is not None: - t1 = nexts[1] - sym2 = 'HI' if t1.get('type','?') == 'H' else 'LO' - tc1 = C_HIGH if t1.get('type','?') == 'H' else C_LOW - _txt_s(draw, rx, r3, f"{sym2} {_fmtt(t1['dt'])}", C_TEXT) - if r4 is not None: - _txt_s(draw, rx, r4, _fmth(t1['height']), tc1) - - last = (r4 or r3 or r2) + 8 - if last + 5 < sky_h: - _txt_s(draw, 3, last + 2, 'Seattle', C_LABEL) - pct_str = f"{int(fill_ratio * 100)}%" - pct_w = len(pct_str) * 4 + 2 - _txt_s(draw, dw - pct_w - 2, last + 2, pct_str, C_LABEL) - - return canvas - - -def render_schedule(dw, dh, hilo): - canvas = Image.new('RGB', (dw, dh), C_BG) - draw = ImageDraw.Draw(canvas) - L = _layout(dw, dh) - now = datetime.now() - tides = hilo[:4] - n = len(tides) - if n == 0: return canvas - - col_w = dw // n - heights = [e['height'] for e in hilo] - lo_h, hi_h = min(heights), max(heights) - h_range = max(hi_h - lo_h, 0.01) - - # simulate next upcoming = index 1 (2nd tide, the low) - next_idx = 1 - - for i, tide in enumerate(tides): - cx = i * col_w + col_w // 2 - is_high = tide.get('type','?') == 'H' - dt = _safe_iso(tide['dt']) - is_past = dt is not None and dt < now - tc = C_HIGH if is_high else C_LOW - - if i == next_idx: - bg = C_COL_HIGH_NEXT if is_high else C_COL_LOW_NEXT - else: - bg = C_COL_HIGH if is_high else C_COL_LOW - draw.rectangle([i*col_w+1, 0, i*col_w+col_w-2, dh-3], fill=bg) - if i == next_idx: - draw.line([(i*col_w+1, 0), (i*col_w+col_w-2, 0)], fill=tc) - - type_label = ('HIGH' if is_high else 'LOW') if not L['small'] else ('H' if is_high else 'L') - _txt_c(draw, cx, L['row1'], type_label, tc if not is_past else C_DIM, FONT_TINY) - _txt_c(draw, cx, L['row2'], _fmtt(tide['dt']), C_TEXT if not is_past else C_DIM, FONT_TINY) - _txt_c(draw, cx, L['row3'], _fmth(tide['height']), - _lerp(C_LOW, C_HIGH, (tide['height']-lo_h)/h_range) if not is_past else C_DIM, - FONT_TINY) - - bar_max = max(3, dh - L['row3'] - 10) - bar_h_px = max(2, int((tide['height']-lo_h)/h_range * bar_max)) - bx1, bx2 = i*col_w+3, i*col_w+col_w-4 - bar_color = tc if not is_past else _lerp(C_DIM, tc, 0.3) - draw.rectangle([bx1, dh-2-bar_h_px, bx2, dh-1], fill=bar_color) - if i == next_idx: - draw.rectangle([bx1, dh-2-bar_h_px, bx2, dh-1], outline=C_TEXT) - - for i in range(1, n): - draw.line([(i*col_w, 0), (i*col_w, dh-1)], fill=C_BAR_OUT) - - return canvas - - -def render_chart(dw, dh, hilo, hourly): - canvas = Image.new('RGB', (dw, dh), C_BG) - draw = ImageDraw.Draw(canvas) - L = _layout(dw, dh) - - cx, cy = L['c_x'], L['c_y'] - cw, ch = L['c_w'], L['c_h'] - - heights = hourly[:24] - lo, hi = min(heights), max(heights) - h_range = hi - lo or 1.0 - - def _py(h): return cy + ch - int((h-lo)/h_range*ch) - def _px(i): return cx + int(i * cw / max(len(heights)-1, 1)) - - for pct in (0.25, 0.5, 0.75): - gy = cy + ch - int(pct*ch) - draw.line([(cx, gy), (cx+cw, gy)], fill=C_GRID) - - pts = [(_px(i), _py(h)) for i,h in enumerate(heights)] - - base_y = cy + ch - poly = pts + [(_px(len(pts)-1), base_y), (_px(0), base_y)] - if len(poly) >= 3: - draw.polygon(poly, fill=C_CHART_FILL) - - for dy, gc in [(2, C_CHART_GLOW2), (1, C_CHART_GLOW1), (0, C_CHART_LINE)]: - for i in range(len(pts)-1): - x1,y1 = pts[i]; x2,y2 = pts[i+1] - draw.line([(x1,y1+dy),(x2,y2+dy)], fill=gc, width=1) - if dy > 0: - draw.line([(x1,y1-dy),(x2,y2-dy)], fill=gc, width=1) - - for tide in hilo: - try: - dt = datetime.fromisoformat(tide['dt']) - frac_hr = dt.hour + dt.minute/60.0 - tx2 = cx + int(frac_hr * cw / 23) - ty2 = _py(tide['height']) - is_high = tide.get('type','?') == 'H' - lc = C_HIGH if is_high else C_LOW - sym = 'H' if is_high else 'L' - lx = max(cx, min(cx+cw-5, tx2-2)) - ly = max(cy, min(cy+ch-8, (ty2-9) if is_high else (ty2+2))) - draw.text((lx, ly), sym, fill=lc, font=FONT_TINY) - draw.line([(tx2, ty2-1),(tx2, ty2+1)], fill=(255,255,255)) - except (KeyError, ValueError, TypeError): - continue - - # Current time — fix at 10:30 for preview - now_frac = 10.5 - now_x = cx + int(now_frac * cw / 23) - draw.line([(now_x, cy),(now_x, cy+ch)], fill=C_NOW_LINE, width=1) - cur_h_idx = min(int(now_frac), len(heights)-1) - cur_py = _py(heights[cur_h_idx]) - r = max(1, dh // 20) - draw.ellipse([now_x-r, cur_py-r, now_x+r, cur_py+r], outline=C_NOW_LINE, width=1) - if r > 1: - draw.ellipse([now_x-r+1, cur_py-r+1, now_x+r-1, cur_py+r-1], - fill=_lerp(C_BG, C_NOW_LINE, 0.45)) - - ax_y = min(dh - 7, cy + ch + 2) # guarantee 7px room to bottom - ax_labels = [(0,'12a'),(6,'6a'),(12,'12p'),(18,'6p')] - if L['small']: ax_labels = [(0,'0'),(12,'12')] - for lh, lt in ax_labels: - lx = cx + int(lh * cw / 23) - tw = len(lt) * 4 - label_x = max(0, min(dw - tw - 1, lx - tw // 2)) - draw.text((label_x, ax_y), lt, fill=C_LABEL, font=FONT_TINY) - - draw.line([(cx, cy+ch+1),(cx+cw, cy+ch+1)], fill=C_BAR_OUTLINE) - return canvas - - -def render_stats(dw, dh, hilo): - canvas = Image.new('RGB', (dw, dh), C_BG) - draw = ImageDraw.Draw(canvas) - L = _layout(dw, dh) - - heights = [e['height'] for e in hilo] - lo_h, hi_h = min(heights), max(heights) - tidal_range = hi_h - lo_h - - # Waxing gibbous for the preview - phase = 0.38 - phase_name = 'Waxing Gibbous' - spring_label = 'NEAP TIDE' - spring_color = C_LOW - cycle_pct = 47 - - moon_r = max(4, min(10, dh // 5)) - moon_cx = moon_r + 3 - moon_cy = dh // 2 - (4 if L['small'] else 6) - - draw_moon(draw, moon_cx, moon_cy, moon_r, phase) - txt_x = moon_cx + moon_r + 5 - - short_name = phase_name.replace(' Moon','').replace(' Quarter',' Qtr') - if L['small']: short_name = short_name[:6] - _txt(draw, txt_x, L['row1'], short_name, C_MOON, FONT_TINY) - _txt(draw, txt_x, L['row2'], spring_label, spring_color, FONT_TINY) - _txt(draw, txt_x, L['row3'], f"Range {tidal_range:.1f}ft", C_LOW, FONT_TINY) - if not L['small']: - _txt(draw, txt_x, L['row4'], f"H {hi_h:.1f} L {lo_h:.1f}ft", C_LABEL, FONT_TINY) - - bar_h = max(2, dh // 16) - bar_y = dh - bar_h - 1 - bar_x0 = txt_x - bar_x1 = dw - 3 - blen = max(1, bar_x1 - bar_x0) - flen = int(blen * cycle_pct / 100) - draw.rectangle([bar_x0, bar_y, bar_x1, bar_y+bar_h], fill=(0, 8, 25)) - if flen > 0: - for px in range(flen): - t2 = px / max(flen, 1) - draw.line([(bar_x0+px, bar_y),(bar_x0+px, bar_y+bar_h)], - fill=_lerp(C_LOW, C_HIGH, t2)) - # % label above the bar so it can't clip past the display bottom - pct_str = f"{cycle_pct}%" - pct_w = len(pct_str) * 4 + 1 - pct_x = max(bar_x0, min(dw - pct_w - 1, bar_x0 + flen - pct_w // 2)) - draw.text((pct_x, max(1, bar_y - 7)), pct_str, fill=C_LABEL, font=FONT_TINY) - - return canvas - - -# ── Composite sheet ──────────────────────────────────────────────────────────── - -def make_sheet(sizes, hilo, hourly): - modes = ['current', 'schedule', 'chart', 'stats'] - mode_names = ['Current', 'Schedule', 'Chart', 'Stats'] - - SCALE = 4 # enlarge each pixel so details are visible - PAD = 6 # padding between cells - LABEL_H = 12 # height of text label above each cell - HEADER_H = 18 # column header height - LEFT_W = 60 # row label area - - cells_w = max(dw for dw,_ in sizes) - cells_h = max(dh for _,dh in sizes) - n_modes = len(modes) - n_sizes = len(sizes) - - sheet_w = LEFT_W + n_modes * (cells_w * SCALE + PAD) + PAD - sheet_h = HEADER_H + n_sizes * (LABEL_H + cells_h * SCALE + PAD) + PAD - - sheet = Image.new('RGB', (sheet_w, sheet_h), (12, 12, 20)) - sdraw = ImageDraw.Draw(sheet) - - # Column headers - for col, (m, mn) in enumerate(zip(modes, mode_names)): - hx = LEFT_W + PAD + col * (cells_w * SCALE + PAD) + (cells_w * SCALE) // 2 - sdraw.text((hx - len(mn)*3, 4), mn, fill=(180, 200, 240), font=FONT_TINY) - - # Rows - for row, (dw, dh) in enumerate(sizes): - ry = HEADER_H + row * (LABEL_H + cells_h * SCALE + PAD) - size_label = f"{dw}×{dh}" - sdraw.text((4, ry + LABEL_H + cells_h * SCALE // 2 - 3), - size_label, fill=(120, 140, 180), font=FONT_TINY) - - for col, mode in enumerate(modes): - cx = LEFT_W + PAD + col * (cells_w * SCALE + PAD) - cy = ry + LABEL_H - - # Render at native size - if mode == 'current': img = render_current(dw, dh, hilo, hourly, phase=22) - elif mode == 'schedule': img = render_schedule(dw, dh, hilo) - elif mode == 'chart': img = render_chart(dw, dh, hilo, hourly) - else: img = render_stats(dw, dh, hilo) - - # Scale up (nearest neighbour to preserve LED pixel look) - big = img.resize((dw * SCALE, dh * SCALE), Image.NEAREST) - - # Centre within column - ox = cx + (cells_w * SCALE - dw * SCALE) // 2 - oy = cy + (cells_h * SCALE - dh * SCALE) // 2 - sheet.paste(big, (ox, oy)) - - # Dim border around cell area - sdraw.rectangle([ox - 1, oy - 1, - ox + dw * SCALE, oy + dh * SCALE], - outline=(30, 40, 60)) - - return sheet - - -if __name__ == '__main__': - out_dir = os.path.dirname(os.path.abspath(__file__)) - hilo = _make_hilo() - hourly = _make_hourly() - - sizes = [ - (64, 32), - (128, 32), - (192, 48), - (256, 64), - ] - - print("Rendering tide display previews …") - - sheet = make_sheet(sizes, hilo, hourly) - out = os.path.join(out_dir, 'preview_sheet.png') - sheet.save(out) - print(f" Saved: {out} ({sheet.width}×{sheet.height})") - - # Also save individual mode PNGs at 192×48 (most common) - dw, dh = 192, 48 - SCALE = 5 - for mode, fn in [('current','preview_current.png'), - ('schedule','preview_schedule.png'), - ('chart','preview_chart.png'), - ('stats','preview_stats.png')]: - if mode == 'current': img = render_current(dw, dh, hilo, hourly, phase=22) - elif mode == 'schedule': img = render_schedule(dw, dh, hilo) - elif mode == 'chart': img = render_chart(dw, dh, hilo, hourly) - else: img = render_stats(dw, dh, hilo) - - big = img.resize((dw*SCALE, dh*SCALE), Image.NEAREST) - path = os.path.join(out_dir, fn) - big.save(path) - print(f" Saved: {path}") - - print("Done.")