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 00000000..41e983bb Binary files /dev/null and b/docs/assets/ledmatrix-leaderboard/appearance.png differ diff --git a/docs/assets/ledmatrix-leaderboard/hero.png b/docs/assets/ledmatrix-leaderboard/hero.png new file mode 100644 index 00000000..920d86c8 Binary files /dev/null and b/docs/assets/ledmatrix-leaderboard/hero.png differ diff --git a/docs/assets/ledmatrix-leaderboard/ncaa-ranking.png b/docs/assets/ledmatrix-leaderboard/ncaa-ranking.png new file mode 100644 index 00000000..1cf66885 Binary files /dev/null and b/docs/assets/ledmatrix-leaderboard/ncaa-ranking.png differ diff --git a/docs/assets/ledmatrix-leaderboard/panel-sizes.png b/docs/assets/ledmatrix-leaderboard/panel-sizes.png new file mode 100644 index 00000000..26886979 Binary files /dev/null and b/docs/assets/ledmatrix-leaderboard/panel-sizes.png differ 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" ]