From 812c77add84b8b8fc2367c4dd855b8e2fe2db7bc Mon Sep 17 00:00:00 2001 From: Chuck <33324927+ChuckBuilds@users.noreply.github.com> Date: Thu, 3 Sep 2026 20:48:37 -0400 Subject: [PATCH] docs(ledmatrix-leaderboard): document all 56 settings, with real renders 31 of the 56 had no named key -- the whole global.appearance block, every per-league entry under enabled_sports, and most of the scroll tuning. All 56 are now documented at the paths the schema expects; additionalProperties is false, so a key at the wrong depth is rejected rather than ignored. Three do nothing: global.scroll_speed_scale, global.scroll_direction and global.enable_scroll_metrics. They appear nowhere in the plugin, and nowhere in the core -- including src/common/scroll_helper.py, which is where a scroll setting would plausibly be consumed. Marked in the README; schema untouched. Corrects the opening description. It said the plugin "shows team rankings, records, and statistics", but each team is drawn as position number, logo and abbreviation. Reading the renderer, the number text is f"{index+1}." for every league except NCAA football, where show_ranking chooses between the AP rank and record_summary. So a record reaches the panel in exactly one configuration, and no statistics do. Adds real rendered screenshots: the ticker, text_outline and logo_scale, the NCAA show_ranking swap, and four panel sizes. Standings are seeded onto the plugin instance; last_update has to be seeded too or update() re-fetches and clears them, and the renderer reads record_summary rather than record -- my first fixture used the latter and no records appeared. check_plugin.py: 8/8 pass. Co-Authored-By: Claude Opus 5 --- README.md | 2 +- .../ledmatrix-leaderboard/appearance.png | Bin 0 -> 23170 bytes docs/assets/ledmatrix-leaderboard/hero.png | Bin 0 -> 4589 bytes .../ledmatrix-leaderboard/ncaa-ranking.png | Bin 0 -> 12792 bytes .../ledmatrix-leaderboard/panel-sizes.png | Bin 0 -> 20036 bytes docs/assets/ledmatrix-leaderboard/shots.json | 402 ++++++++++++++++++ plugins.json | 4 +- plugins/ledmatrix-leaderboard/README.md | 97 +++++ plugins/ledmatrix-leaderboard/manifest.json | 10 +- 9 files changed, 510 insertions(+), 5 deletions(-) create mode 100644 docs/assets/ledmatrix-leaderboard/appearance.png create mode 100644 docs/assets/ledmatrix-leaderboard/hero.png create mode 100644 docs/assets/ledmatrix-leaderboard/ncaa-ranking.png create mode 100644 docs/assets/ledmatrix-leaderboard/panel-sizes.png create mode 100644 docs/assets/ledmatrix-leaderboard/shots.json diff --git a/README.md b/README.md index 812a069d..337f30e2 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ curl -X POST http://your-pi-ip:5000/api/v3/plugins/install \ | [March Madness](./plugins/march-madness/) | NCAA tournament bracket tracker with round branding and live scores | | | [NFL Draft](./plugins/nfl-draft/) | Projected & live NFL draft picks from ESPN | | | [Odds Ticker](./plugins/odds-ticker/) | Betting odds & lines across NFL, NBA, MLB, NHL, NCAA | | -| [Sports Leaderboard](./plugins/ledmatrix-leaderboard/) | League standings, rankings, conference records | | +| [Sports Leaderboard](./plugins/ledmatrix-leaderboard/) | League standings, rankings, conference records | ledmatrix-leaderboard on an LED panel | | [Olympics Countdown](./plugins/olympics/) | Countdown to next Olympics with live medal counts | | ### Financial (2) diff --git a/docs/assets/ledmatrix-leaderboard/appearance.png b/docs/assets/ledmatrix-leaderboard/appearance.png new file mode 100644 index 0000000000000000000000000000000000000000..41e983bb21b9f1c6026e9c754121334a4d8d9962 GIT binary patch literal 23170 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 AU;qFB literal 0 HcmV?d00001 diff --git a/docs/assets/ledmatrix-leaderboard/panel-sizes.png b/docs/assets/ledmatrix-leaderboard/panel-sizes.png new file mode 100644 index 0000000000000000000000000000000000000000..26886979359b12a5c80bb04291441ec313fb8c94 GIT binary patch literal 20036 zcmeIaXIzun+CCb$+e#ZZAW9v#qXcOqN{~LnR>sf*2q-N&7!WBDkP-sKQObxSGx`Wa zH!2`fLJu7kfiVbCdT5~-A_Rzp5<)#IIuqu7$JgVW-+TVQ^Wo$Z#+CJ~b+5Z#*S($_ zC<_yjozgpDFqp`x@Bd>BgYEba4EB#l+y4Q+F=u|;41-w+o%+x5)4{z{tGJYV0jrDa zb*(99_XNr!-n>4IlIVWj@oLL133KCrG=wVe9ye(itf(kiT?TZ{`sz% z=(@EXU=84N5g#+jUk>V;poef;X1dcBW-{B;oQ&UyL&Ht6fU zW1BvFC79`RgJ3Ve75g}WV5XmiXFq-;m}z5>UMkB22Sd_50^p>ESvm{>;>%>7r(}=6F@zp{tv_W~ZZs_iCJf9&!Bo)`01L z-0<^An=Ff(@yz5WPo5;L1wOsHsYx!VKMg-kBV*~dId(O3ZKih>EyHJ9wB)>C_f>Tl zdR(dc+)zT8S=62n)QNX$cx zxAywKIU$A7NEB;+bn0%VSt92Rrgo{5tWZqcW;b=DD*?-lu6ZK zDMhr&v+k*#F)}s5Gb6=R1AKbe!rsF_yznH|#9K>iT=;%{ZM`o0?Fw&Jy?p4Jv8eV1 zAO)|auLIeGVPHN{1nl+Jsj@zwZYO{9_HRh971MiCLME~k&Bo@t(FzE!p2t=XzUUjSR5d4sVyHXN~O^VZPC zPBR71=Mg*ZefYSi;oOj5AN_cC4fukvzD%zQV$1KYooSR&2%CG;nPabhreG*LEA3KD zY;3GKp&T5dLg@QvkwQ}W&Q%N3RcxOau=C3Wo30|@3C%U&cZRFumRXkRE{o*!&>w6Z z9FnX<#uD9kt2!JFn(jYa?562F!E_P=iw0_(vA(>TsFVSgF?PpPEm7Nl?AG2Rt=i0# zJ9qAgN%dUH$+OU%Dv?yS>kp!br5B_*`cyEc$aD)Opjp1)xqA#k7w;dxZjDSphx1}2 zl?@gSW@KdOva4s$N6W=qhwvB)QYvRq<*(GLCfnwszeWEOc5%O3OHx3GmC1l#v#Nqc z^IGb2@nrmTg<{5)#o=f%8N?(Dy}netJl*&D^<|)nx*r65Q7fjK*$AXL*_G#r9QQ;o zJG84uWkHQ`3TOw1rMu}X-()~7Za@Jj91aI4LeYZ3Njhdo8ySB{626|f>uFiF2+t?r#(}G8U-cVp_t#avv7eDPH#>r}PT6NjEj~_n<)_u%(M3L}P5%!(q0^7n%)L?N)+~U~2 zjJZKPJMT>4gWTLn;3)dQ5u|)D-EZovA!~1M?{YY84f2TFt1~4R-_$w!0b8qL*Dn8JBCqY; zTau=acL^SjT%IhZMicN9r7Wj_PFo;nQti@2PoXP1Wc+}MG_2?Q)hh91dHoP4-v&wW z?Aqx{R+N}R`0L}_^w$yb5ggZ_#)mW*BFB-D8= z)#0Z~?b{V@9~=28b2$XeblY%kkvGfKeFb}Zazfm~Ypa;NlZ#85b;x94Q<6n&S}5lw z)OK~#=E^JMBY&6*!>^)AfuNUh1^k}xhr^cU_8xIFLwXEWcx_eMkvO!fvRW(%)#{urW7wCaYO^9Y#>1ky4xP7y!sVUW9c@k>7 zsa_lWY>QM!XQy@}e_3}ez2a3JyXK-t;|yy(yYn5r3LD>-&4t;a@hVVdLRE`vVZFJm{3@UIRqpz`m)6CK2zzk8yG&$vtu0LCkZOVSe?LA;U59(QXreh=;6d(TpSPay;`eIq+C2x?&YkN&7D zT(<2;>YEgTZSRh!CtGL|u%UKY7;L;)25c-XcygESu0VjYQ-#gEp2a7$jKchD5$775btTc(cX@_ssRuJzp?*YDIx1Yj~bZw zzFgHvqq{L~jIo6%yHFEtoH*N6RQ{l{@=Vc;)CFwlyB5@Rs*WObI9m7$3I@CS_75Es zZ2EKix&Qm(Pfk>$^&~0R3CRi+vHVndtX&l%{*Kr7MA4a9zsyJPyU!mPUawoCu!t$R zfNGLSTIdnzmu2iI3gja%@BN-M3v_NnaG#Lw2WfpLGuPwKj_?~SrAGPj=G&83e@#|Z z-;wdSS`P{}P%u@CHxpLy&$;8{+rqA`fzuy}!4RSwEM9^urg535L7cyplNGt>j5KH8(fsV22QW$W7iP~i z60f17TN>Mbec6c72@pL$-zG^sE!nhO$t_%jXSRguLf7l6OBMh1r=$HcBbz!^==`%a zg*n@zcK784M5QL_X8ZttIqYDloo89{rppM17lj5DXPeWq?Wx-_b?jA5=m1tdMvLY2 zFQb=%$3BFa>c=&6RpCXUDm(LHxoIRJOq|Va zQAYkaJAxCfI4HsxQpXN7qM43trhf688n)MOtD~vgVP97WoYa?8Ko^^0x@Q+a(k;Xw zM$7NasH_YTrzP`3YiS@)f5j{xdp<7_AMZWfh^ubXne6O3>wlhhA@B&SH8aIrJJ}D> z+1g3PtJmJv=UKpy$ma+%UbV1{#@p*uAhiHZ;*}@Pdy%}}QX(W-?G~?=6O$fcuZ1q^ z^c>O9^u;6nVu^2`jMQMm->wlm!p3hBg>|RIh?6CrPHyLu2?tBMSpN7h=ayjFKmN3> zFLDzXEoMRn*FfSUjOi`$Al{PEQiDK7R3|rC6>31A)JQbTG|#KRkS~!OJl%8ahaX7h z1~1%0)vjG<_o;rTJM`hul-zC7yJ;Oy(3U$gF1>6+Aumaf`jYZ@V5ZNzM;6&W^Xw2! zbb^a?mJ)%cDFyp(?WHPNN*V;MK?i=CSir%^JzZ`zY_ zvXtDj#YTH|1HItwS(eyQ{GoKJR+ZVoyED)w_padrlDK8;Jb6XSX7Zo+o&EmMOe)K3 zA~hK+av(uRqF*gxL_MPMx=x-~{mN+TfrlpW=E}yR z0^I%G-zE|c@Wpq)lsR}zj zP?XVPhEoyoZNYXnq7h+1-l0zHyj-yipW`aom&~7SqbHs5t9Z`D3eSra9^Ku4NSs{p z*we!adoUl@x>BxhC_@f_Q|Xm6`YeZq80SR_-Gwex{cscPXQ#y9QHQ@e&`-F!qdDL} z(_daN(&oLrYg{oLCDZ#X?NI0=zC}7ps@asM#ShpwcU7zPRjaW)6uQp4hfc0}u=@H9 zM9+DgAfu#P<;10y+G|{1{1}M4J^Y6r%ZzzFp;~M<8rSrzb4#DymNtJ8PFU`n3}z<> z2xk~0e1_eebu_EYd=XL!VU4y?pp^A-Z*yy1>5K46 z;5yd^6O6Loz0rhNtqQv-J?Hy^jsN*41s0?M8;cp+oTolvvf0x5@TH5z&HSWEZVNwY`sjq_ajE8cH}8fY(}c1V!jzyH zH2pB-rIzo`@+J#2ZefMDXW-*nTYRXjEetePO@vXGkJEv;yYqYkTO7G`73ey*_YgEu z8bDl`*j8_(z3NVlEMnhI1-9gs9Jth;x_)a=4)HdpvKxfQPgv;ZPL^r~JW)6WQkpua zenBGc?Vgqn9WffD$=G*ETyB{~vw==5S7j87KV0_@oT-IL7 zOjToBjS16^Huh4idM|Q*;t5LB@NyOEQjVuF&98ZysJGaoOO!2eC%KWCoc5@Qwo=zd zR%jL7h^_Q_6BDT4#!=;c%v5^*DHqWCkl25jo{I_(;t`1{3l9~Iv_sdujVf4Aej%># zy3;!!E_Q0;HLG4luFw7ery8!Ggg4vgi!g4D28v+XBGfhUXlGqFJpjIZE|K|!!QaQk zO#S2B!^<>tYNW>eZG~P{7);e5xpHFc%o=y;p>blUB?dlfA|lG@Wh?YFDlGp>bd2OY zvT;vgBT9?m1U}xfrvpwqeN>UzL zQiT`;89+B?q_+87!Mi4GO2&bV<;$KT5bbw;_8*?&qKn-{IiR(E1Zu*P(_t`&aD?WC ztQKQl%WAPv#ay3mv|oqZ0!SA(GNN;T;Fh1&vy&hj^O8{0@r_2w*A2LAf?ed%I>hQE z6SQ%2K7kT{p70X~FPQqj*r>trgUKT6#g;HwiaEgY1d&LvtIyf?7Y*7t7{LkzVNS5j zjX{DH2nK!85eo)=Lfr(*{GvgBbHjpVeqt|wZ^J#`OOlvVVzN4I7XO4@M(~s0r|$dO zNoWH8BRUPcL!try%l`<@P#~_)ZBno_!Jz-eO-{M^dgi_Bag77Dx_{1-C!)uOu8NHU zh~&2JbUFC07)!6svC9h?&qz3EnYIF;m+&QXM>#r8C7l{TT$jYv!N)BL8YfU=;4ZK+N&hOYhORq)-60(gEt4yw*=N zj{Y45)?0e_FhS+)9cyU-^8);N*6d(=$#+ob{Q41~}<$IK%SF6q*FtpKn!06<#+ z?HvDrt&^9MS_T69rjk7KJ(Au^CK(dewn#a>p0m{JMiau2*?8`>YvV1Cr9K-=ea*Ws z`G7pY#$_}wb#NHX%@m4-&iJGG{zqSchcn)9hNV|o8lWczYw*bN1}U`c$}R<$c(PiS zzG}h$h?K8(W3Kb{@_X+~za}&@27^aq)7R#*Kwhf8(g#q=Igqb9m0uq2E%gMr;B;os zLzB2nLnuBz69SlW;)$EPTL9$Om3!7aVM#LI{d2%~@>(S8;TM7E5v=W-V2En4nM*pI zJfIK;3uP?7-u7$7*&o1m69wm*kojv{gwg3^wuIC7b$cfPl*Z_?g`A z*BrfGJIfATOpRAq+uRP6_^!3i%KQ3g5t)T~5+RHp#`V5<5xzot{s;oFcRZOMuA6bC z-?wT0-5b}%_ruq>iXfGo!+8v4yWH=$(9;t?;OuG@Z|@`?ac}+g@MwyEtCEru@A8j% zWxW$6?G}!OKQsUwjJX$(DRPlaQ}erJ*8yJ0NI<6`+1#4hw!T`E zlNvP0E2tMWRjL61snBkfGYKMF!8X1w&0cpK)RF%7+*5FjDb^0Pp*(=;^-Ex@rpnZu zD^mh{J^17WGP|s7p~J>9Y&cSCC)VY^L*Z>euYa}<;k;B-z`gyY-~u&GKY6WP1HIha zos_>~suZhWSX)vur)bDKg;YvzaltX}0c_Xa1&29tBGMfOdwnu=l4sq1!@S*I>I$pN z8;FFD4Zkr_;G=GCmUxFiMCV(8aRXXu$_5GO3o*U-Px;%t{l{t8kLBI`WxvTFj+rVc zDG7i*aYc)j_syze|1+X(5P0B!0?aQLwx;T8t)6d)k$iYERtLcOfRtcBZ2(3Freclc zvm8UuuDiFU-~ei=y8`=8W`^CG0I*s#VA3uCfKzwmr~UHy$wJ7QNffInWHEO=nWk5Fhl@m_@-@vC0CVL8jIan{%t)IWAoL~OHpV`{& z95nELxLyok!T>t14q^}TX_7j}PIfrA3bIBdn=7>d0_)9#6OqjwU0sOPVZP7lukZ&P z!&0>2%D#-#PEIS4>Y?WW1u)tahpzBr@R;f8RHj@wAn+E0n5Ie@04nY3=s0@xX!Yts zpW)g}T=EE_&#QgX!}2CIGwBw<-MIrnhMeE_XPGB=0pL_fz4|g>#LoV%OWyyfuig)k z@moh)zgNx&pW{!<8JsQY0iKWI;*cP1UuvYk)N|Qxe(p?S0b(HHE6O9pVQ= z7n#6!P6O4BY*qnI8Gy4&8Mozh5%ke2)msK|UVz>Y z*GJUP10_5QB+jPouY z9^*9k^i=B*09f<+yUNPSxV0%jlqRiRUYThMn(7U>sake%>G|V{iHS@?{7yh^_yVdS z1LB`^M@NT*q@;P$(d_X$g;}c#r|Fp{1xqD4Knhe%7MZ3S@Imvt)=65}K|o@S25*LW zQxwzH!H-u)71%(%fioNY;if8|mCZZ`D1hB53%R4T(_mEqybc-&=my(gnCQ$IH+^G+ zG*6h(ta`@Rmy&$5y6{y;%n80q09C5tg=!bCu2)hC9N5E$ABQxN4E(HY4gAkMsh`Sr&in}d1)<{0i z4k9hmgY)*Kh=_<5h!vE3$~H*)@*o!wH@kO-14XRkwO|bZ>jP|EQ&SW8NxiXOU3adZ z5`qo+cTe)#6xJ7;z%N}}k~9G};6L`NfmJxOv}KK)?DU4I0t4Orh>* zKd*RNFTIMwDP<_i<6nRfh)~)lDo2a)^cVa$M>Cl(9~kWC6|KLZJ%7y#ul}FyNDw5C zg1m4e{r>CXJ~2p;bPAGRL1w)%(`N?#znZ?D6F&{gFc_@h2Htg$f||z7b)xL-x+B~0 z#kYyFfv>Nkw$8JCxPKc9e_9DI<8$K|oAS$NXs9$C?l?R;j6IARt1eZ^f1Ixt@3pdp zCZiB?1j1*v?!dg-w^%hP05}4u^HdU z7-br-RHrB@tpxO#Ev}PlIU#U&7dbZT7e%@-=IvVFF$k6iN3ULi`zx>SqFf7-iYyAn z*upCso#4sy?<6Q)eLiv&L{<9aSD%HgK5?8SX8(I!z$0jlM_w0Y5Y`v}1E(M37#ic& zuY17*<}-*;;7_FC0|#cz8P_G}iAOtDuyDojFg8kbapEcJwsgR0xMbh0z{{Jy&;MIJ zKLBq4M~5iTCefagDUJgXwY`%1dIqv4K53-*W1bBSipNcC>6 z9qUxWaQum$))~Bgj~LvDuM4 z)6MHz#!P@Iq&>u#+RQHyQBRY#73*! zYkg0Jy1C)8Md|9jy*U?~%W%enRhDYryqcHKXyvj&gOS8Jl~@INkS{ID2fdi{6@W!Q zhqfF9Y5+b0r}haGJR{W*xC!=@d9lCTm#7Ew9^z?xd+fjQ`+vvUd9vM3&wq(&y8148Dbm)p08M6~j<4o4cxF(6+BCsx5$J+&ixPl*y}YFQQ5rn0qCq-{>jt zpC@M-@uu>~QJjH?al(vd3%ucLjgR7f_X#dXZ{c%X zj@@bq5^if6A7yRbz9$YJU=H^e(^ZD@cDg(a{Ozrg$K!mF3}18eXZ{ashkTDBmW7_s zu2Cy!98Nik-0F)Dxe|weh)qY?1p<8dfHOXVV{s}A6>mSc6GP1!+@29=-fy@(xrfbC zNPF=jC(;|KUpLH%H*s5abRioH18o6K_zBqP6Z)@e<0Vyc=HT5O2hyp1s<5Y7*8c

?I_A>Tyk7XRw7pW&*l-|T1Q{&V_2_5z79q;TO*)5BSk1_-A2s> zyDPClr33LZl0_z5)D!&NcFfuCGrI%d{fp9<7|h0MK@l1xgu%<*`LS_f<4KJuyBaBU zeS6Y1>$-0vekA4X#Qav<7sbh$jq;8#Wb>%+iUaXD{Srd&^s>cp-sG4iYn3n{Ne_yz zmZN0buapf1s%uq^O_0~WqNFsB>h_9m7Kk1K^o|=RRjVrIjYVt?)8<`@Ndw?zxT8Xe7C?%1P&hNkQuzcx67Lh_%(jjLsU6i^bG_W2_rb5R)}tU{rW3p zmPM*jc3z$c2DEOaeFu9Qa!5(ZBQOyZIjALoL#c638l;OIxcf5rj@N0Ef`G2k0#aS1 z*4jQOX%@R3Q>;oB%cu@I0r%8xq}~#d956oHbs#>-R5zOAmZ=vXRX#?(G^(ClTZJ&l z=h}5eTa&+zKV6zRbRBE1QsFc_s};4hsC`)Ti}^C|$E*E1Y;df^P zX0Qp%?r>%M7xrt{#p2kvxPwPjAy9*;)*h)nq7L<8Z({d=2DW&jtPba=VD|po!i*pL z^0zZ)@U3Eu`-O%xwX@k>w=BP770a`AS?uMzBq7Gj=*$;>O{&BzY??AuU&pz3rcqvo zl7^p@H`I|ZOBE19pYUuOM<(!W1-E0g9(eO%QDbd@2sjj^fu_yqww|6n$g^k9!a)^7 ztOoE6(FtIqL_NR;5+x)XHcjky^xB0)B#U5LQ?%1^VXxHyPmi)N;Jropln+M*^1h$t zg%*-M_6S zg|#XKcReJoOks;hYp`91A<>!r7QMNqS#AkRtz$;C96~gzGDs~p!_;Z4kO`8LHA)g{ z!gIoy7Pve(GZ-`}qi}*7jP9l{Tf-&wE2I1dc=dexOa}YYYc+IzA8Xlyf07qlgj^~Q zKm>#JEYx(>`~y^3uU@T`Sp|z=lxR2a0`C)k97CF=!*^i1JZ~EFSa)aS$}GFz%&g`N zDL66f=6`_Cj(N*df~dOtpyRrYLD8T;InvtEQHBEACPxs43&4Lo83`#$o|2?=DEiD4 z6{n>Kbxqm+8{1tv>{>ZfBju%&9<+0{yM-L(#~_ceChi%oS;6b7R$EcimCEr`++JNs zE=X2_Vh;ef;=wn9MDndC;v>$!QN#ST8YM={hC2RO-U9Bsews>6CyJjk$m@*T)2`KKH3fdH| z=Kcz+C4;!qt!Wv}8GO*$l8cp(!THtN31@)PDAN1gG4biPsWKV%Z|~gkSk%|La9L$j_=PD53eUc4MB;b za-(&jZZ}8kZs$9!9fxCU_R?Ls{n=SuId;e3UXS9mFl7rDi(@O99?H__yB;JqYo}CGp&m;fsjDz2=PF`%>9JFWUg=?Hwf%kw%7I31u zxxyg$VGE{SGW__qIDGNoUD~<6S%8#A`hn*7XigkqWj_Sagoq+P1_c$ba(2XI3(Vlk z(Cc45AOtzRPu*=`>60C%>(Ug6&-A{1bA3dEkSIeLTMdcgtYW8jQI6xoh_+?CxpaLQ zO5NICa)ohL+XmOW;<5AqCE8PL59d1ZN>O%sH_}g41-=Ttv?(<6$zYr!GZio5b5E1x zz@ehnm`||Le$&*Eyo)Wp%I9aqg?{Ag^_%CpDhhpC{;f z!w|klTHTD#?!~;%>OnX>-@y!ENrbVhW1%Qq+$Wy0I!RP1a!>??D4cSyoW-^T` zzLZ8s-S3XSZp528K^Ms=`N2?k=Y7dMpbSva$g#eOo@^VqVa-HL`GXjjef{h2>xum# z^v%Rqpc*R|Bl7cX@lN zB?w`j2KGgA`T@Y`M^z8si#!p1o7lmWHh%fYOeOIQM?{1edOqP9G3D}D&}jW{%w%VO zS6A0(u_JlmgeE!StFV=96w(x#g!X?H-g-gkWOZr4KH>f#HqdQDIsjpQJ=`MS4!m=e zhVRIW#qSC0c*Dmq*!yg~Wy&?wN%XNJ(4SiXW{RIG5PXMDlC=W&79?i<6PEYG(}cz- z>#9K9GixTz3YK@V;}?@Czh}Iedx1-%agl8~LFp(Y`G$B#{lbbh+-8mY3#u|;O4^j< zLcB8Ft_9h|9aDieN8dL4dtnBEO`sEs%j#B#qN1WupbK4=0zg$`9Kg1dYe;|@i7Fbs zf1K!5IDjCgtRGi{Ty?|uL6Wfn#0xf==j<`Y7js>9AsMwoM%jk5RYYiPG=?QJVGLNO z9T;zObNHyD*>()ln2st_X8)`EE~te3twNoYq_lj`wk#8?E8zwUmB39{ckE#+V@BVX zyHnGM{eYq(f{uOz;>uEY9dPj@4gAu$Ni{cTcC#30s{MhKO5V=6lf1r{@^dOejG@J) z?qsxK*|HR?pq?t&`*nM}!FmhWqFL(Y-(I5*($~+y389NbR9Sy`G|Fyl&Q#D@ZtQXK;&z5I znuml7NvR2Aia8cUv+06=L*66*9{-60x-{+|26rV!+E8lExjQklSb2FQB0;&wun>Zv zh@uB&2O;I~KwJ2>1keM+8eAPgBtX%3NG{@($@39aH@B)+^0s%+Uqx=>q|M zT7)rdN)l!aQMM36>w-d^VnO#8n{-B=Qtarxn=)ot35SG4wZDZpBX>}TkQD3L>my!5 zX;u|cQD=7E#+QBLW62(@Np_wEEdYBcZpjTbhk+TprROv>%w%Qe=eL@I63W}@U~(zH zrQYC~rG;TB4U@UL5GClW{zOeBa7O|O3>Dk-Pk82%NMad}9(}`aYDTIhcm}or(xN3E zP>0dhc98co*Vad7aFL2eR7lX2JksM?NT$Bl5lBXz=L>h#UowLmPIah5Ez2Upm=mu3 z)MmRpVMhFFnGohTT2>@ytco4UdA=nf%DVW1hn~w8lL|+=0da1x1Q}OV!xhFv4+IKj zc>2yZxexa~K~av(z=M=kZ<-VwmVX9rZ0JJ-kT!zmHT$}q8DQT+O(*l-&u8&Fcn?;! zu!{6qMX#dzqrKUqS4f;lI`L{ZvuOXI|4yBXPINT@Zk3Yz@+} zfr-Eg1?NEO@a!#ITL)Qg=L&`$?bk<06$enEj}YTlhd!jvl>t7gaS64%J5MCz5nS{K zEp=e|yGgA=jC|6%2|UX#A+pHT_Y_>;RQD*Jtr;6j41K+L4n9j6wF>tq%NdOa_FMTT zCaOoYv0f4)imoi@8SPzvJw?2tawASTp*d0m$9apg0HqXaZL!HPietDwYe=jHtdxrr zf1jW4Li_6t&2%H*98%%qceAozf$eskwQ_asw@KBFw4UvlB~H#JWEt%x^X{XhCnk(= z;k-MGa2+U8<9@jwbPu#_PZar533zWOOJ6JI;`hr}M21ay!Dy^4X=lcv1fh&-phc-w z^PnC4PPu-LTa7q{Wr>!j*kxo8LkkZZV6y_w?nZh8HES}PrN%ow8zrXTIwx=u^Gp2<&gmmq@+6YF-&x`}mvvT-T|f7Tu_1N}NEGVr^j| z=$b_Ii7uF09TZ2}x*Eex0>|Z$aw8$)ZhRv8I{krlc%^^8tgJ94H)hHb?Pe$ zC$#^0Cv6el7%(kEdCQnJs=%`r%av~!&M~+v<)Gky0v*y%i5&GAfLDS z^VS3g`Z+5uG3C2@(2tWTZ)uQj>FczYT!3+OIxVp+T@y5X>RFMGLQ6-QA~o<;wZzlT z3+MhcBY_d zO#Q3`C67#(r#!w%kf0DwtM9;AHv|$Pw~<1)>QZiFTVzvB0ly+Vbm)*#qE5giIJoq5 z0uFBGrX@VGoNpg6a49{v8m`vcwXitD&yW6Y%VYz;i~qz4Z%^4CVy+4_;baUCP@+$U zNFPZ=>2x!Vc&=P8xW3Oy0K7_6T7q(5^A8nA=<3iw<$Mg+<=ep3);spb6&2ju#JOew zm?nD)XOvVM!xd|*;gD_=VL#++<0FJ&wSXd}VKB^?H++^E;n!m?wjIMB-WFZ7xY})$ zcv`w!FQ}miwa|B!TKPQvnv+_$7w?%^_*cmFwN+#7@ke(@juaObf?j_9M{tAY6VZ7i z4;0+kmPs9nz32#_4S1|bEHMS)`vY7z_lXdu%4fhRo60m&qDW0<-zg{AsXNP39Jv-d z7z>)@2*3U(F3?8-e{7fK|Ff2F|3F9zy#jZ z>hKk1zCKQr0Y$TSVpz2xe0Mjv7IvrMqc}}{Y*EbHH)t^iu{6g>J7`YKXxv&N&R)&_ zGITS>;Gz3i)5;@Bt@YxCSZwHi=m-_?8V5|{gK536Cgr;?d#p-+WM1m)l{eg-o(dAa z5`IL2eLux-?R?$(if5mZ%Ku`6#QB5_1POD`)0n==cyO-}6%#Y^&UYb)6zNwlq7~ui z&Yd#We*DN0&SqW`S}?69F%rx5n-GDb7z!P|lR@qT*L1?kYeW_A$G{0??t=_PL8|V8 z?mqM?XZ! zXTvjnk@b_;hd-nnq2!HpM9TMhqn-{!(YbxDGt|(pb_w=SVKE4+?tTWBLVAvPU-}T>AcW*TC z#|9s7HaK9KV`7pNj{4NCE__4;J0!i%t1%oIzql3CP$6@<+c6!jXkf>|%q`iurcBh5 zf%9HU!rH71F=d{tXq4?zs4*QIwRBBa{n)iFcmohCIgEYAM&oC#-duC-MHRd{Mc3Uw z-HBdBK%+KnlzcxntGq>OjVL4%X_Wos$xh7M-+m#2x~cvqpY8th zaSGH^kTCwWabd`YU$`(qwg^&_t$j34R`-*}d#OXr= zYpgjGa%WjqEpeZkje|7O%1Rci?oa}U-aIsk1{j;L`T_43mDOt!wUK!UGS(Tq5=4YYQ z68g?9=f5vZkZ4-PwQ>Q;yw^ltl437I-k#xZbqd~$oG{*7sWZ5I%hx@cQ!hliB~!y} z-FKzWhlQe428d+T8VoK^a1$C-Q$G~MssOBdMxEJ20ISw#5FmF=b+P zQ14;D_crGkD^Vq6xg%%Pz>6qQ;hekaFKQedStp2{rIXCCcA9*gr_E|bf!HKyEd(xA zP)Q47hv0++8xv$eur&oiAqZdqR0wx^U@~vFn$sQ%=uhsM4B>!?176_Z-=7SsonyTK zoTuEA0wHFhPh>lzDq#fec*VGz7glY|Cs9C*E4_cnCqKbXIT>J@N z`H4OJk-OfHrGPu#bq!kb<@G~~>5Kk9$>|0PXMpZOBEQA&10s!}ht8tX!k5NTOWZga z&=6>>bm)@f=H|w0CP}J2&ow=}qx`z-#iBUx>epo`&zbI#)(eBn#JOA#;S9WiI5OJo znY^-^D3MrwRIQzCzg>T!UlZEbbZaN$XJeBnjhrDkS_|g~r`EnV;i-e{ z^Z*yWKJPCC$FgBvB@e&_p)jCe8Q^Urv?8?+N5e1FY2XzTMjm_z{`j%Ch)VI6KAZ9u zx#nhL9(X%RvZ^OQGjOx1K}Kge&x%l&E?r6*7!zg48PWW1sv6VEsADanF`h!xtiI9P zLX6v0Y>w+kwrxY=e|2XY<{(h5kU08IGb72_5{Hm) zNv$n6FV4Wk*VP?`wy~?!p*qWSd5T=n;9km|1Ewoq{kL>TAcN0!LBSfl1DkaMC-+dm zJ2aANY^|&u6)eX$_Dvor8VI7-&@f=853~x%2#z{B0HOcD;W6dQt;} z!L+E^I6KQx+A>UyKPVn}YYy=Oh`?Y|Mu`Y-2e{V26&tvE-HKna1Z6@ueFGRu1Sjz~5S*mWcl4rj)uUW^IK>R6*D3K~8E?NE{9ar+Fbh5DnI7G+T*( z7v#^^djt;e6PpvD8}B_N$uw2)x*j2hC1I(3YZdp&lS7stAb~$=#pjkQkm2VB3G{hm zkYIVA@MVJK2?h!FAeia1mLZU;U?#yb1v7m%)Cp``Fq2@Jf|aRQ4 znDUDj_t!xJ8E(uZ5VT;Mf&8{WvG1qnH4YDdsB2H1u=r2D(Yb5?7XU$m_5c6? literal 0 HcmV?d00001 diff --git a/docs/assets/ledmatrix-leaderboard/shots.json b/docs/assets/ledmatrix-leaderboard/shots.json new file mode 100644 index 00000000..baca8485 --- /dev/null +++ b/docs/assets/ledmatrix-leaderboard/shots.json @@ -0,0 +1,402 @@ +{ + "plugin": "ledmatrix-leaderboard", + "_comment": "Standings are seeded onto the plugin instance rather than fetched from ESPN, and last_update is seeded so update() does not re-fetch and clear them. The ticker scrolls, so shots step frames. Teams and records are invented.", + "defaults": { + "width": 128, + "height": 32, + "scale": 6, + "freeze_time": "2026-09-03T18:00:00+00:00", + "skip_update": true, + "frames": 60, + "config": { + "enabled": true + }, + "attrs": { + "leaderboard_data": [ + { + "league": "nfl", + "league_config": { + "sport": "football", + "league": "nfl", + "logo_dir": "assets/sports/nfl_logos", + "league_logo": "assets/sports/nfl_logos/nfl.png", + "top_teams": 6, + "level": 1, + "show_ranking": false + }, + "teams": [ + { + "rank": 1, + "abbreviation": "KC", + "id": "100", + "record": "13-4", + "wins": 0, + "losses": 0, + "display_value": "13-4" + }, + { + "rank": 2, + "abbreviation": "BUF", + "id": "101", + "record": "12-5", + "wins": 0, + "losses": 0, + "display_value": "12-5" + }, + { + "rank": 3, + "abbreviation": "BAL", + "id": "102", + "record": "11-6", + "wins": 0, + "losses": 0, + "display_value": "11-6" + }, + { + "rank": 4, + "abbreviation": "PHI", + "id": "103", + "record": "11-6", + "wins": 0, + "losses": 0, + "display_value": "11-6" + }, + { + "rank": 5, + "abbreviation": "DET", + "id": "104", + "record": "10-7", + "wins": 0, + "losses": 0, + "display_value": "10-7" + }, + { + "rank": 6, + "abbreviation": "SF", + "id": "105", + "record": "9-8", + "wins": 0, + "losses": 0, + "display_value": "9-8" + } + ] + } + ], + "last_update": 1788458400.0 + } + }, + "shots": [ + { + "name": "hero", + "frames": 160, + "width": 256 + }, + { + "name": "outline-on", + "frames": 160, + "width": 256, + "standalone": false, + "config": { + "global": { + "appearance": { + "text_outline": true + } + } + } + }, + { + "name": "outline-off", + "frames": 160, + "width": 256, + "standalone": false, + "config": { + "global": { + "appearance": { + "text_outline": false + } + } + } + }, + { + "name": "scale-1", + "frames": 160, + "width": 256, + "standalone": false, + "config": { + "global": { + "appearance": { + "logo_scale": 1.0 + } + } + } + }, + { + "name": "scale-06", + "frames": 160, + "width": 256, + "standalone": false, + "config": { + "global": { + "appearance": { + "logo_scale": 0.6 + } + } + } + }, + { + "name": "ncaa-rank", + "frames": 160, + "width": 256, + "standalone": false, + "attrs": { + "leaderboard_data": [ + { + "league": "ncaa_fb", + "league_config": { + "sport": "football", + "league": "ncaa_fb", + "logo_dir": "assets/sports/ncaa_logos", + "league_logo": "assets/sports/ncaa_logos/ncaa_fb.png", + "top_teams": 6, + "level": 1, + "show_ranking": true + }, + "teams": [ + { + "rank": 1, + "abbreviation": "KC", + "id": "100", + "record": "13-4", + "wins": 0, + "losses": 0, + "display_value": "13-4", + "record_summary": "12-1" + }, + { + "rank": 2, + "abbreviation": "BUF", + "id": "101", + "record": "12-5", + "wins": 0, + "losses": 0, + "display_value": "12-5", + "record_summary": "11-2" + }, + { + "rank": 3, + "abbreviation": "BAL", + "id": "102", + "record": "11-6", + "wins": 0, + "losses": 0, + "display_value": "11-6", + "record_summary": "11-2" + }, + { + "rank": 4, + "abbreviation": "PHI", + "id": "103", + "record": "11-6", + "wins": 0, + "losses": 0, + "display_value": "11-6", + "record_summary": "10-3" + }, + { + "rank": 5, + "abbreviation": "DET", + "id": "104", + "record": "10-7", + "wins": 0, + "losses": 0, + "display_value": "10-7", + "record_summary": "10-3" + }, + { + "rank": 6, + "abbreviation": "SF", + "id": "105", + "record": "9-8", + "wins": 0, + "losses": 0, + "display_value": "9-8", + "record_summary": "9-4" + } + ] + } + ], + "last_update": 1788458400.0 + } + }, + { + "name": "ncaa-record", + "frames": 160, + "width": 256, + "standalone": false, + "attrs": { + "leaderboard_data": [ + { + "league": "ncaa_fb", + "league_config": { + "sport": "football", + "league": "ncaa_fb", + "logo_dir": "assets/sports/ncaa_logos", + "league_logo": "assets/sports/ncaa_logos/ncaa_fb.png", + "top_teams": 6, + "level": 1, + "show_ranking": false + }, + "teams": [ + { + "rank": 1, + "abbreviation": "KC", + "id": "100", + "record": "13-4", + "wins": 0, + "losses": 0, + "display_value": "13-4", + "record_summary": "12-1" + }, + { + "rank": 2, + "abbreviation": "BUF", + "id": "101", + "record": "12-5", + "wins": 0, + "losses": 0, + "display_value": "12-5", + "record_summary": "11-2" + }, + { + "rank": 3, + "abbreviation": "BAL", + "id": "102", + "record": "11-6", + "wins": 0, + "losses": 0, + "display_value": "11-6", + "record_summary": "11-2" + }, + { + "rank": 4, + "abbreviation": "PHI", + "id": "103", + "record": "11-6", + "wins": 0, + "losses": 0, + "display_value": "11-6", + "record_summary": "10-3" + }, + { + "rank": 5, + "abbreviation": "DET", + "id": "104", + "record": "10-7", + "wins": 0, + "losses": 0, + "display_value": "10-7", + "record_summary": "10-3" + }, + { + "rank": 6, + "abbreviation": "SF", + "id": "105", + "record": "9-8", + "wins": 0, + "losses": 0, + "display_value": "9-8", + "record_summary": "9-4" + } + ] + } + ], + "last_update": 1788458400.0 + } + }, + { + "name": "size-64x32", + "width": 64, + "frames": 160, + "standalone": false + }, + { + "name": "size-128x32", + "width": 128, + "frames": 160, + "standalone": false + }, + { + "name": "size-128x64", + "width": 128, + "height": 64, + "frames": 160, + "standalone": false + }, + { + "name": "size-256x32", + "width": 256, + "frames": 160, + "standalone": false + } + ], + "composites": [ + { + "name": "appearance", + "columns": 1, + "cells": [ + { + "shot": "outline-on", + "label": "text_outline: true", + "sublabel": "the default" + }, + { + "shot": "outline-off", + "label": "text_outline: false" + }, + { + "shot": "scale-06", + "label": "logo_scale: 0.6", + "sublabel": "against the default 1.0 above" + } + ] + }, + { + "name": "ncaa-ranking", + "columns": 1, + "cells": [ + { + "shot": "ncaa-rank", + "label": "ncaa_fb show_ranking: true", + "sublabel": "the AP rank" + }, + { + "shot": "ncaa-record", + "label": "ncaa_fb show_ranking: false", + "sublabel": "the record instead" + } + ] + }, + { + "name": "panel-sizes", + "columns": 2, + "cells": [ + { + "shot": "size-64x32", + "label": "64 x 32" + }, + { + "shot": "size-128x32", + "label": "128 x 32" + }, + { + "shot": "size-128x64", + "label": "128 x 64" + }, + { + "shot": "size-256x32", + "label": "256 x 32" + } + ] + } + ] +} diff --git a/plugins.json b/plugins.json index f818927f..20d4d264 100644 --- a/plugins.json +++ b/plugins.json @@ -409,10 +409,10 @@ "plugin_path": "plugins/ledmatrix-leaderboard", "stars": 0, "downloads": 0, - "last_updated": "2026-08-05", + "last_updated": "2026-09-03", "verified": true, "screenshot": "", - "latest_version": "1.3.2" + "latest_version": "1.3.3" }, { "id": "ledmatrix-flights", diff --git a/plugins/ledmatrix-leaderboard/README.md b/plugins/ledmatrix-leaderboard/README.md index 624bafc1..f681ea68 100644 --- a/plugins/ledmatrix-leaderboard/README.md +++ b/plugins/ledmatrix-leaderboard/README.md @@ -13,6 +13,18 @@ # Leaderboard Plugin +![The NFL standings scrolling across a 256x32 panel: position number, team logo +and abbreviation for each team in +order](../../docs/assets/ledmatrix-leaderboard/hero.png) + +*Every image in this README is real plugin output, rendered at the true panel +size from seeded standings so it reproduces exactly. Teams and records are +invented.* + +Each team is drawn as **position number, logo, abbreviation**. Records are not +shown for the major leagues — the only place a record replaces the number is +NCAA football with `show_ranking` off, below. + A plugin for LEDMatrix that displays scrolling leaderboards and standings for multiple sports leagues including NFL, NBA, MLB, NCAA Football, NCAA Basketball, NHL, and more. ## Features @@ -171,6 +183,91 @@ reached. Raise that cap, increase the scroll speed } ``` +### Top level + +| Key | Default | Notes | +|---|---|---| +| `enabled` | `false` | Enable or disable the leaderboard plugin. | +| `display_duration` | `30` | How long to display the leaderboard in seconds (10–300). | +| `update_interval` | `3600` | How often to fetch new leaderboard data in seconds (300–86400). | + +### `global` + +| Key | Default | Notes | +|---|---|---| +| `global.display_duration` | `30` | Duration in seconds to display the leaderboard (10–300). | +| `global.scroll_speed` | `1` | Scrolling speed multiplier (0.1–10). | +| `global.target_fps` | `100` | Target frames per second for scrolling (30–200). | +| `global.scroll_speed_scale` | `8` | Scroll speed scale factor (1–20). **Not implemented**. | +| `global.request_timeout` | `30` | Request timeout in seconds (5–120). | +| `global.dynamic_duration.enabled` | `true` | Enable dynamic duration based on content width. | +| `global.dynamic_duration.min_duration_seconds` | `45` | Minimum display duration when dynamic duration is enabled (10–300). | +| `global.dynamic_duration.max_duration_seconds` | `600` | Maximum display duration when dynamic duration is enabled (30–1200). | +| `global.dynamic_duration.buffer_ratio` | `0.1` | Extra buffer applied to the calculated duration (percentage expressed as 0-1). | +| `global.dynamic_duration.controller_cap_seconds` | `600` | Failsafe cap for the display controller when dynamic duration is enabled (60–1800). | +| `global.min_duration` | `45` | [Deprecated] Use dynamic_duration.min_duration_seconds instead (10–300). | +| `global.max_duration` | `600` | [Deprecated] Use dynamic_duration.max_duration_seconds instead (30–1200). | +| `global.duration_buffer` | `0.1` | [Deprecated] Use dynamic_duration.buffer_ratio instead (0.01–1.0). | +| `global.max_display_time` | `600` | [Deprecated] Use dynamic_duration.controller_cap_seconds instead (60–1800). | +| `global.scroll_pixels_per_second` | `15.0` | [Deprecated] Scroll speed in pixels per second. Use display.scroll_speed and display.scroll_delay for finer control (5.0–50.0). | +| `global.display.scroll_speed` | `1.0` | Scrolling speed in pixels per frame (0.5–5.0). | +| `global.display.scroll_delay` | `0.01` | Delay between scroll steps in seconds (0.001–0.1). | +| `global.scroll_target_fps` | `100.0` | Target FPS for scrolling (30.0–200.0). | +| `global.scroll_mode` | `"one_shot"` | Scrolling mode — one of `one_shot`, `continuous`. | +| `global.scroll_direction` | `"left"` | Scroll direction — one of `left`, `right`. **Not implemented**. | +| `global.enable_scroll_metrics` | `false` | Enable scroll performance metrics. **Not implemented**. | +| `global.scroll_delay` | `0.01` | Delay between scroll steps in seconds (0.001–0.1). | +| `global.loop` | `false` | Continuously loop the leaderboard. | +| `global.appearance.pixel_perfect_text` | `true` | Render text with hard pixel edges. Disable only if you prefer the older anti-aliased (softer, blurrier) look. | +| `global.appearance.crisp_logos` | `true` | Give logos hard edges instead of a ring of half-lit pixels. | +| `global.appearance.text_outline` | `true` | Draw a black outline around text so it stays readable over logos. | +| `global.appearance.logo_scale` | `1.0` | Logo height as a fraction of the panel height. 1.0 fits the panel exactly; above 1.0 crops the top and bottom of every logo (0.5–1.5). | +| `global.appearance.font_size` | `0` | Font size in pixels. 0 picks a size that suits the panel height. Values are snapped to the font's pixel grid (multiples of 8 for Press Start 2P) to keep text sharp (0–32). | + +### `enabled_sports` + +Each league takes the same four or five keys. + +| Key | Default | Notes | +|---|---|---| +| `enabled_sports.nfl.enabled` | `true` | Enable NFL standings. | +| `enabled_sports.nfl.top_teams` | `10` | Number of top NFL teams to display. 0 shows every team the standings return (up to 32). Long lists need a matching display duration - see the README (0–32). | +| `enabled_sports.nba.enabled` | `true` | Enable NBA standings. | +| `enabled_sports.nba.top_teams` | `10` | Number of top NBA teams to display. 0 shows every team the standings return (up to 30). Long lists need a matching display duration - see the README (0–30). | +| `enabled_sports.mlb.enabled` | `true` | Enable MLB standings. | +| `enabled_sports.mlb.top_teams` | `10` | Number of top MLB teams to display. 0 shows every team the standings return (up to 30). Long lists need a matching display duration - see the README (0–30). | +| `enabled_sports.ncaa_fb.enabled` | `true` | Enable NCAA Football rankings. | +| `enabled_sports.ncaa_fb.top_teams` | `25` | Number of top NCAA Football teams to display. 0 shows every team the standings return (up to 130). Long lists need a matching display duration - see the README (0–130). | +| `enabled_sports.ncaa_fb.show_ranking` | `true` | Show NCAA Football rankings instead of standings. | +| `enabled_sports.nhl.enabled` | `true` | Enable NHL standings. | +| `enabled_sports.nhl.top_teams` | `10` | Number of top NHL teams to display. 0 shows every team the standings return (up to 32). Long lists need a matching display duration - see the README (0–32). | +| `enabled_sports.ncaam_basketball.enabled` | `false` | Enable NCAA Men's Basketball rankings. | +| `enabled_sports.ncaam_basketball.top_teams` | `25` | Number of top NCAA Men's Basketball teams to display. 0 shows every team the standings return (up to 350). Long lists need a matching display duration - see the README (0–350). | +| `enabled_sports.ncaam_basketball.show_ranking` | `true` | Show rankings/seeds instead of sequential numbering. During March Madness, automatically shows tournament seeds. | +| `enabled_sports.ncaam_hockey.enabled` | `false` | Enable NCAA Men's Hockey rankings. | +| `enabled_sports.ncaam_hockey.top_teams` | `10` | Number of top NCAA Men's Hockey teams to display. 0 shows every team the standings return (up to 60). Long lists need a matching display duration - see the README (0–60). | +| `enabled_sports.ncaam_hockey.show_ranking` | `true` | Show NCAA Men's Hockey rankings instead of standings. | +| `enabled_sports.ncaaw_basketball.enabled` | `false` | Enable NCAA Women's Basketball rankings. | +| `enabled_sports.ncaaw_basketball.top_teams` | `25` | Number of top NCAA Women's Basketball teams to display. 0 shows every team the standings return (up to 350). Long lists need a matching display duration - see the README (0–350). | +| `enabled_sports.ncaaw_basketball.show_ranking` | `true` | Show rankings/seeds instead of sequential numbering. During March Madness, automatically shows tournament seeds. | +| `enabled_sports.ncaa_baseball.enabled` | `false` | Enable NCAA Baseball standings. | +| `enabled_sports.ncaa_baseball.top_teams` | `25` | Number of top NCAA Baseball teams to display. 0 shows every team the standings return (up to 350). Long lists need a matching display duration - see the README (0–350). | +| `enabled_sports.ncaa_baseball.season` | — | Season identifier (e.g. '2026'). Omit to use the current ESPN season. | +| `enabled_sports.ncaa_baseball.level` | `1` | Competition level (1 = Division I, 2 = Division II, 3 = Division III) (1–3). | +| `enabled_sports.ncaa_baseball.sort` | `"winpercent:desc,gamesbehind:asc"` | Sort key and order for standings. | + + +### What the settings look like + +![text_outline and logo_scale](../../docs/assets/ledmatrix-leaderboard/appearance.png) + +`show_ranking` is the one setting that changes *what information* appears +rather than how it looks, and only for NCAA football: + +![show_ranking on and off](../../docs/assets/ledmatrix-leaderboard/ncaa-ranking.png) + +![The same standings on four panel sizes](../../docs/assets/ledmatrix-leaderboard/panel-sizes.png) + ## Display Format The leaderboard displays information in a scrolling format showing: diff --git a/plugins/ledmatrix-leaderboard/manifest.json b/plugins/ledmatrix-leaderboard/manifest.json index c8a93d23..5a4c03a1 100644 --- a/plugins/ledmatrix-leaderboard/manifest.json +++ b/plugins/ledmatrix-leaderboard/manifest.json @@ -1,7 +1,7 @@ { "id": "ledmatrix-leaderboard", "name": "Sports Leaderboard", - "version": "1.3.2", + "version": "1.3.3", "description": "Displays scrolling leaderboards and standings for multiple sports leagues including NFL, NBA, MLB, NCAA Football, NCAA Basketball, and more", "author": "ChuckBuilds", "entry_point": "manager.py", @@ -31,6 +31,12 @@ "requirements_file": "requirements.txt", "min_ledmatrix_version": "2.0.0", "versions": [ + { + "version": "1.3.3", + "released": "2026-09-03", + "notes": "Documentation. 31 of the 56 settings had no named key, including the whole appearance block and every per-league entry. All 56 are now documented at the paths the schema expects, with global.scroll_speed_scale, global.scroll_direction and global.enable_scroll_metrics marked as not implemented -- they appear nowhere in the plugin and nowhere in the core's scroll helper. Corrects the opening description: each team is drawn as position number, logo and abbreviation, and a record replaces the number only for NCAA football with show_ranking off, so 'rankings, records, and statistics' overstated what reaches the panel. Adds real rendered screenshots.", + "ledmatrix_min_version": "2.0.0" + }, { "released": "2026-08-12", "version": "1.3.2", @@ -91,7 +97,7 @@ "ledmatrix_min_version": "2.0.0" } ], - "last_updated": "2026-08-05", + "last_updated": "2026-09-03", "compatible_versions": [ ">=2.0.0" ]