diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..159dff7f --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,35 @@ + + +## This issue is a + +- [ ] Bug Report +- [ ] Feature Request + + + +## Hardware Configuration + +- Raspberry Pi Revision (4B+/3B+/Zero/etc.): +- Operating System: +- Matrix size: +- Display adapter (HAT/Bonnet/etc.): + - Additional information: +- Power source(s): + + + +## Software Configuration + + + +- MLB LED Scoreboard Version: +- Commands/arguments used to start the scoreboard: + +## Expected behavior + + +## Actual behavior + + +## Additional Information + diff --git a/README.md b/README.md index 0bbb0d9d..2a3ca395 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# mlb-led-scoreboard [![Join Slack](https://img.shields.io/badge/slack-join-blue.svg)](https://mlb-led-scoreboard.herokuapp.com/) +# mlb-led-scoreboard +![Current Version](https://img.shields.io/github/v/release/MLB-LED-Scoreboard/MLB-LED-Scoreboard) [![Join Slack](https://img.shields.io/badge/slack-join-blue.svg)](https://mlb-led-scoreboard.herokuapp.com/) --------------- @@ -104,6 +105,12 @@ It will also install the following python libraries that are required for certai That should be it! Your latest version should now be working with whatever new fangled features were just added. +#### Version Information + +You can check the version information for your installation of mlb-led-scoreboard by running `python3 version.py`. + +The latest version of the software is available [here](https://github.com/MLB-LED-Scoreboard/mlb-led-scoreboard/releases). + #### Time Zones Make sure your Raspberry Pi's timezone is configured to your local time zone. They'll often have London time on them by default. You can change the timezone of your raspberry pi by running `sudo raspi-config`. @@ -161,6 +168,7 @@ A default `config.json.example` file is included for reference. Copy this file t "time_format" String Sets the preferred hour format for displaying time. Accepted values are "12h" or "24h" depending on which you prefer. "end_of_day" String A 24-hour time you wish to consider the end of the previous day before starting to display the current day's games. Uses local time from your pi. "full_team_names" Bool If true and on a 64-wide board, displays the full team name on the scoreboard instead of their abbreviation. This config option is ignored on 32-wide boards. Defaults to true when on a 64-wide board. +"short_team_names_for_runs_hits" Bool If true and full_team_names is true and Runs Hits Errors is enabled, will use abreviated team names when Runs or Hits > 9 "scrolling_speed" Integer Supports an integer between 0 and 4. Sets how fast the scrolling text scrolls. "debug" Bool Game and other debug data is written to your console. "demo_date" String A date in the format YYYY-MM-DD from which to pull data to demonstrate the scoreboard. A value of `false` will disable demo mode. diff --git a/config.json.example b/config.json.example index cd37681b..64acf580 100644 --- a/config.json.example +++ b/config.json.example @@ -42,6 +42,8 @@ "time_format": "12h", "end_of_day": "00:00", "full_team_names": true, + "short_team_names_for_runs_hits": true, + "pregame_weather": true, "scrolling_speed": 2, "debug": false, "demo_date": false diff --git a/data/config/__init__.py b/data/config/__init__.py index 6c25d2e2..f8db6031 100644 --- a/data/config/__init__.py +++ b/data/config/__init__.py @@ -62,6 +62,8 @@ def __init__(self, filename_base, width, height): self.time_format = json["time_format"] self.end_of_day = json["end_of_day"] self.full_team_names = json["full_team_names"] + self.short_team_names_for_runs_hits = json["short_team_names_for_runs_hits"] + self.pregame_weather = json["pregame_weather"] self.debug = json["debug"] self.demo_date = json["demo_date"] # Make sure the scrolling speed setting is in range so we don't crash diff --git a/data/game.py b/data/game.py index 9278c750..200a078c 100644 --- a/data/game.py +++ b/data/game.py @@ -12,7 +12,7 @@ + "currentPlay,result,eventType,playEvents,isPitch,pitchData,startSpeed,details,type,code,description,decisions," + "winner,loser,save,id,linescore,outs,balls,strikes,note,inningState,currentInning,currentInningOrdinal,offense," + "batter,inHole,onDeck,first,second,third,defense,pitcher,boxscore,teams,runs,players,seasonStats,pitching,wins," - + "losses,saves,era,hits,errors" + + "losses,saves,era,hits,errors,weather,condition,temp,wind" ) SCHEDULE_API_FIELDS = "dates,date,games,status,detailedState,abstractGameState,reason" @@ -67,10 +67,18 @@ def datetime(self): def home_name(self): return self._data["gameData"]["teams"]["home"]["teamName"] - + def home_abbreviation(self): return self._data["gameData"]["teams"]["home"]["abbreviation"] - + + def pregame_weather(self): + try: + wx = self._data["gameData"]["weather"]["condition"] + " and " + self._data["gameData"]["weather"]["temp"] + u"\N{DEGREE SIGN}" + " wind " + self._data["gameData"]["weather"]["wind"] + except KeyError: + return None + else: + return wx + def away_name(self): return self._data["gameData"]["teams"]["away"]["teamName"] diff --git a/data/scoreboard/pregame.py b/data/scoreboard/pregame.py index 7ae0e466..121ca767 100644 --- a/data/scoreboard/pregame.py +++ b/data/scoreboard/pregame.py @@ -9,6 +9,7 @@ class Pregame: def __init__(self, game: Game, time_format): self.home_team = game.home_abbreviation() self.away_team = game.away_abbreviation() + self.pregame_weather = game.pregame_weather() self.time_format = time_format try: diff --git a/debug.py b/debug.py index d628bbb5..6c6cc12d 100644 --- a/debug.py +++ b/debug.py @@ -5,6 +5,7 @@ strmhdl = logging.StreamHandler() strmhdl.setFormatter(fmter) logger.addHandler(strmhdl) +logger.propagate = False info = logger.info diff --git a/main.py b/main.py index 51adcc4f..58d372b5 100755 --- a/main.py +++ b/main.py @@ -16,6 +16,7 @@ from data.config import Config from renderers.main import MainRenderer from utils import args, led_matrix_options +from version import SCRIPT_NAME, SCRIPT_VERSION try: from rgbmatrix import RGBMatrix, __version__ @@ -27,10 +28,6 @@ emulated = True -SCRIPT_NAME = "MLB LED Scoreboard" -SCRIPT_VERSION = "5.0.4" - - def main(matrix, config_base): # Read scoreboard options from config.json if it exists diff --git a/renderers/games/pregame.py b/renderers/games/pregame.py index 0613de0f..9f75354b 100644 --- a/renderers/games/pregame.py +++ b/renderers/games/pregame.py @@ -10,8 +10,8 @@ from utils import center_text_position -def render_pregame(canvas, layout: Layout, colors: Color, pregame: Pregame, probable_starter_pos): - text_len = _render_probable_starters(canvas, layout, colors, pregame, probable_starter_pos) +def render_pregame(canvas, layout: Layout, colors: Color, pregame: Pregame, probable_starter_pos, pregame_weather): + text_len = _render_probable_starters(canvas, layout, colors, pregame, probable_starter_pos, pregame_weather) if layout.state_is_warmup(): _render_warmup(canvas, layout, colors, pregame) @@ -39,12 +39,15 @@ def _render_warmup(canvas, layout, colors, pregame): graphics.DrawText(canvas, font["font"], warmup_x, coords["y"], color, warmup_text) -def _render_probable_starters(canvas, layout, colors, pregame, probable_starter_pos): +def _render_probable_starters(canvas, layout, colors, pregame, probable_starter_pos, pregame_weather): coords = layout.coords("pregame.scrolling_text") font = layout.font("pregame.scrolling_text") color = colors.graphics_color("pregame.scrolling_text") bgcolor = colors.graphics_color("default.background") - pitchers_text = pregame.away_starter + " vs " + pregame.home_starter + if pregame_weather and pregame.pregame_weather: + pitchers_text = pregame.away_starter + " vs " + pregame.home_starter + " Weather: " + pregame.pregame_weather + else : + pitchers_text = pregame.away_starter + " vs " + pregame.home_starter return scrollingtext.render_text( canvas, coords["x"], coords["y"], coords["width"], font, color, bgcolor, pitchers_text, probable_starter_pos ) diff --git a/renderers/games/teams.py b/renderers/games/teams.py index 290a5403..5f595006 100644 --- a/renderers/games/teams.py +++ b/renderers/games/teams.py @@ -3,8 +3,7 @@ except ImportError: from RGBMatrixEmulator import graphics - -def render_team_banner(canvas, layout, team_colors, home_team, away_team, full_team_names): +def render_team_banner(canvas, layout, team_colors, home_team, away_team, full_team_names, short_team_names_for_runs_hits): default_colors = team_colors.color("default") away_colors = __team_colors(team_colors, away_team.abbrev) @@ -53,8 +52,10 @@ def render_team_banner(canvas, layout, team_colors, home_team, away_team, full_t y_offset = accent_coords[team]["y"] canvas.SetPixel(x + x_offset, y + y_offset, color["r"], color["g"], color["b"]) - __render_team_text(canvas, layout, away_colors, away_team, "away", full_team_names, default_colors) - __render_team_text(canvas, layout, home_colors, home_team, "home", full_team_names, default_colors) + use_full_team_names = can_use_full_team_names(canvas, full_team_names, short_team_names_for_runs_hits, [home_team, away_team]) + + __render_team_text(canvas, layout, away_colors, away_team, "away", use_full_team_names, default_colors) + __render_team_text(canvas, layout, home_colors, home_team, "home", use_full_team_names, default_colors) # Number of characters in each score. score_spacing = { @@ -65,6 +66,27 @@ def render_team_banner(canvas, layout, team_colors, home_team, away_team, full_t __render_team_score(canvas, layout, away_colors, away_team, "away", default_colors, score_spacing) __render_team_score(canvas, layout, home_colors, home_team, "home", default_colors, score_spacing) +def can_use_full_team_names(canvas, enabled, abbreviate_on_overflow, teams): + # Settings enabled and size is able to display it + if enabled and canvas.width > 32: + + # If config enabled for abbreviating if runs or hits takes up an additional column (i.e. 9 -> 10) + if abbreviate_on_overflow: + + # Iterate through the teams to see if we should abbreviate + for team in teams: + if team.runs > 9 or team.hits > 9: + return False + + # Else use full names if no stats column has overflowed + return True + + # If config for abbreviating is not set, use full name + else: + return True + + # Fallback to abbreviated names for all cases + return False def __team_colors(team_colors, team_abbrev): try: @@ -80,11 +102,10 @@ def __render_team_text(canvas, layout, colors, team, homeaway, full_team_names, coords = layout.coords("teams.name.{}".format(homeaway)) font = layout.font("teams.name.{}".format(homeaway)) team_text = "{:3s}".format(team.abbrev.upper()) - if full_team_names and canvas.width > 32: + if full_team_names: team_text = "{:13s}".format(team.name) graphics.DrawText(canvas, font["font"], coords["x"], coords["y"], text_color_graphic, team_text) - def __render_score_component(canvas, layout, colors, homeaway, default_colors, coords, component_val, width_chars): # The coords passed in are the rightmost pixel. font = layout.font(f"teams.runs.{homeaway}") diff --git a/renderers/main.py b/renderers/main.py index 7768ad0e..45ec63f7 100644 --- a/renderers/main.py +++ b/renderers/main.py @@ -156,12 +156,13 @@ def __draw_game(self): scoreboard.home_team, scoreboard.away_team, self.data.config.full_team_names, + self.data.config.short_team_names_for_runs_hits, ) if status.is_pregame(game.status()): # Draw the pregame information self.__max_scroll_x(layout.coords("pregame.scrolling_text")) pregame = Pregame(game, self.data.config.time_format) - pos = pregamerender.render_pregame(self.canvas, layout, colors, pregame, self.scrolling_text_pos) + pos = pregamerender.render_pregame(self.canvas, layout, colors, pregame, self.scrolling_text_pos, self.data.config.pregame_weather) self.__update_scrolling_text_pos(pos, self.canvas.width) elif status.is_complete(game.status()): # Draw the game summary diff --git a/version.py b/version.py new file mode 100644 index 00000000..1322e7b0 --- /dev/null +++ b/version.py @@ -0,0 +1,6 @@ +SCRIPT_NAME = "MLB LED Scoreboard" +SCRIPT_VERSION = "5.0.4" + + +if __name__ == "__main__": + print(f"{SCRIPT_NAME} v{SCRIPT_VERSION}")