diff --git a/deathclock/app.py b/deathclock/app.py index e180b3b..cbd328a 100644 --- a/deathclock/app.py +++ b/deathclock/app.py @@ -7,41 +7,48 @@ from clock_module import ClockModule def create_app(): app = Dash(__name__) - + app.layout = html.Div([ html.H1(id='clock-display', style={'textAlign': 'center', 'cursor': 'pointer'}), dcc.Input(id='time-input', type='time', style={'display': 'none', 'margin': '0 auto'}), html.Div(id='output-selected-time', style={'textAlign': 'center', 'marginBottom': '20px'}), - + html.Div([ html.Div([ - html.Div([ - html.H2("NBA Scores"), - html.Div(id='nba-scores-display', className='score-container') - ]), - html.Div(id='weather-display', style={"display": "flex", "justify-content": "center", "margin-bottom":"20px"}) - ], id='scores-weather-container', style={"display": "flex", "gap": "20px"}), - ]), - + html.H2("NBA Scores"), + html.Div(id='nba-scores-display', className='score-container') + ], id='nba-container', style={'flex': '1'}), + + html.Div(id='weather-display', style={"display": "flex", "justify-content": "center", "margin-bottom":"20px", 'flex':'1'}), + + html.Div([ + html.H2("MLB Scores"), + html.Div(id='mlb-scores-display', className='score-container',style={'column-count': '2', 'column-gap': '10px'}) + ], id='mlb-container', style={'flex': '1'}), + + ], id='main-content-container', style={"display": "flex", "gap": "20px", 'flex-wrap': 'wrap'}), + html.Div(id='news-ticker'), - + dcc.Interval(id='clock-interval', interval=60000, n_intervals=0), dcc.Interval(id='weather-interval', interval=550000, n_intervals=0), dcc.Interval(id='news-interval', interval=300000, n_intervals=0), - dcc.Interval(id='nba-interval', interval=300000, n_intervals=0) + dcc.Interval(id='nba-interval', interval=300000, n_intervals=0), + dcc.Interval(id='mlb-interval', interval=300000, n_intervals=0) ]) - + ClockModule(app) WeatherModule(app) NewsModule(app) - ScoresModule(app) + scores_module = ScoresModule(app) + scores_module.setup_mlb_callbacks() alarm_module = AlarmModule(app) - + def check_alarms(): trigg = alarm_module.alarm_obj.check_alarm() if trigg: print("ALARM TRIGGERED!") - + check_alarms() return app diff --git a/deathclock/assets/style.css b/deathclock/assets/style.css index 64887fc..0bf4be7 100644 --- a/deathclock/assets/style.css +++ b/deathclock/assets/style.css @@ -3,28 +3,50 @@ body { color: #e6e6fa; font-family: 'Arial', sans-serif; margin: 0; - padding: 20px; -} - -/* Container for the scores and weather */ -#scores-weather-container { - display: flex; - justify-content: space-between; - align-items: flex-start; - width: 100%; -} - -/* Scores Styles */ -.score-container { - max-width: 300px; padding: 10px; + font-size: 16px; + overflow-x: hidden; + min-width: 360px; /* Minimum width to prevent extreme squishing */ +} + +h1 { + font-size: 2rem; + margin-bottom: 10px; +} + +h2 { + font-size: 1.5rem; + margin-bottom: 10px; +} + +/* Main Content Container (Scores and Weather) */ +#main-content-container { + display: flex; + flex-wrap: wrap; + gap: 20px; + width: 100%; + justify-content: center; /* Center items on small screens */ +} + +#nba-container, +#mlb-container{ flex: 1; + min-width: 300px; /* Minimum width for the containers */ +} +/* Individual Score Containers */ +.score-container { + width: 100%; + padding: 5px; +} + +#mlb-scores-display { + column-count: 1; } .score-box { background-color: #232338; - padding: 8px; - margin-bottom: 8px; + padding: 5px; + margin-bottom: 5px; border-radius: 6px; border: 1px solid #4a4a82; } @@ -45,13 +67,13 @@ body { #weather-display { background-color: #232338; border-radius: 10px; - padding: 20px; - margin: 20px auto; - max-width: 600px; + padding: 10px; + margin: 10px auto; + max-width: 100%; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2); border: 1px solid #4a4a82; transition: all 0.3s ease; - flex: 2; + flex: 1; /* Each section takes equal width */ } #weather-display:hover { @@ -62,8 +84,9 @@ body { #weather-display img { width: 100%; border-radius: 8px; - margin-top: 10px; + margin-top: 5px; } + /* News Ticker Styles */ .ticker { position: fixed; @@ -72,14 +95,14 @@ body { overflow: hidden; white-space: nowrap; background-color: #232338; - padding: 15px; + padding: 5px; border-radius: 8px; border: 1px solid #4a4a82; } .news-item { display: inline-block; - padding-right: 50px; + padding-right: 30px; color: #d1c4e9; animation: ticker linear infinite; } @@ -93,5 +116,91 @@ body { } } +/* Media Queries */ +@media (min-width: 1000px) { + /* Landscape layout */ + body { + padding: 20px; + font-size: 18px; + max-width: 1500px; + margin: 0 auto; + } + #main-content-container { + flex-wrap: nowrap; /* No wrapping on landscape */ + justify-content: space-around; + } + #mlb-scores-display { + column-count: 2; + } + + .score-container { + padding: 10px; + } + + .score-box { + padding: 8px; + margin-bottom: 8px; + } + + #weather-display { + padding: 20px; + margin: 0; /* Remove vertical margin on landscape */ + max-width: 400px; + + } + + .ticker { + padding: 15px; + } + + .news-item { + padding-right: 50px; + } +} + +@media (max-width: 480px) { + /* Phone screens */ + body { + font-size: 14px; + padding: 0; + transform-origin: top left; + transform: scale(0.6); + width: 166.66%; + margin-left: -33.33%; + min-width: 0; + } + + h1 { + font-size: 1.5rem; + } + + h2 { + font-size: 1.2rem; + } + + #main-content-container { + gap: 1px; + } + #nba-container, + #mlb-container{ + min-width: 0; + } + + .game-score { + font-size: 0.8em; + } + + .game-period { + font-size: 0.7em; + } + + .ticker { + padding: 5px; + } + + .news-item { + padding-right: 15px; + } +} diff --git a/deathclock/scores.py b/deathclock/scores.py index 0038b95..9cb7be5 100644 --- a/deathclock/scores.py +++ b/deathclock/scores.py @@ -64,6 +64,9 @@ class mlbScores: def get_scores(self): games = self.get_games() scores_list = [] + if not games: + print("No mlb games found") + return [] for game in games: try: game_data = { @@ -77,8 +80,7 @@ class mlbScores: except KeyError as e: print(f"Error processing game data: {e}") continue - - + return scores_list # RETURN THE LIST if __name__ == "__main__": scores = NBAScores() diff --git a/deathclock/scores_module.py b/deathclock/scores_module.py index 0c5ad43..33fa784 100644 --- a/deathclock/scores_module.py +++ b/deathclock/scores_module.py @@ -1,11 +1,14 @@ from dash import html, Input, Output from scores import NBAScores # Import NBAScores class +from scores import mlbScores # Import mlbScores class class ScoresModule: def __init__(self, app): self.app = app self.scores_obj = self.get_scores_object() + self.mlb_scores_obj = self.get_mlb_scores_object() self.setup_callbacks() + def get_scores_object(self): return NBAScores() @@ -19,6 +22,7 @@ class ScoresModule: try: games = self.scores_obj.get_scores() if not games: + print("no nba games found") return html.Div("No games available", className='text-center') return html.Div([ html.Div([ @@ -33,3 +37,33 @@ class ScoresModule: ], className='score-container') except Exception as e: return html.Div("Scores unavailable") + def get_mlb_scores_object(self): + return mlbScores() + + def setup_mlb_callbacks(self): + @self.app.callback( + Output('mlb-scores-display', 'children'), + Input('mlb-interval', 'n_intervals') + ) + def update_mlb_scores(n): + try: + games = self.mlb_scores_obj.get_scores() + print("Updating MLB Scores") + + if not games: + print("no mlb games found") + return html.Div("No games available", className='text-center') + return html.Div([ + html.Div([ + html.Div([ + html.Span(f"{game['away_team']} {game['away_score']}"), + html.Span(" @ "), + html.Span(f"{game['home_team']} {game['home_score']}") + ], className='game-score'), + html.Div(f"Status: {game['status']}", className='game-period') + ], className='score-box') + for game in games + ], className='score-container') + except Exception as e: + print(f"Error updating MLB Scores: {e}") + return html.Div("Scores unavailable") diff --git a/deathclock/weather.py b/deathclock/weather.py index 217976c..95accfd 100644 --- a/deathclock/weather.py +++ b/deathclock/weather.py @@ -38,7 +38,7 @@ class Weather: curl_command = [ "curl", "-s", # Silent mode - "wttr.in/Sacramento.png?u", + "v2.wttr.in/Sacramento.png?0pq&scale=2", # Fetch weather data for Sacramento "-o", screenshot_path, ]