1
1
#!/usr/bin/env python3
2
2
3
3
import asyncio
4
+ import os
4
5
import time
6
+ import urllib .request
7
+ from datetime import datetime
5
8
from typing import List , Dict , Tuple
6
9
from collections import deque
7
10
from datetime import datetime , timedelta
8
- from PIL import ImageFont , Image
11
+ from PIL import ImageFont , Image , ImageDraw
9
12
from lib .sports .sports import Sport
10
13
from matrix .matrix import Matrix
11
14
from lib .sports .baseball .baseball import Baseball
12
15
from lib .sports .basketball .basketball import Basketball
13
16
from lib .sports .hockey .hockey import Hockey
14
-
17
+ from matrix . sport . team_mapping import BASEBALL_TEAMS , BASKETBALL_TEAMS
15
18
class BaseballMatrix (Matrix ):
16
19
def __init__ (self , matrix , api , logger ) -> None :
17
20
self .matrix = matrix
@@ -64,13 +67,17 @@ def baseball_divisions(self, standings: List[Dict]) -> List[str]:
64
67
65
68
def determine_nextgame (self , nextgame_api ):
66
69
now = datetime .now ()
67
- last_16 = now - timedelta (hours = 16 )
68
70
status = ("FT" , "ABD" )
69
71
for game in nextgame_api :
70
- if last_16 <= datetime .fromtimestamp (game ['timestamp' ]) <= now :
72
+ if "IN" in game ['status' ]:
73
+ # During the game
74
+ return game
75
+ if game ['status' ] == "FT" and datetime .fromtimestamp (game ['timestamp' ]).date () == datetime .today ().date ():
76
+ # Same Day will display for the rest of the day
71
77
return game
72
78
if game ['status' ] not in status :
73
79
return game
80
+
74
81
def away_team (self , nextgame_data ):
75
82
away = nextgame_data ['teams' ]['away' ]
76
83
away .update (nextgame_data ['score' ]['away' ])
@@ -79,64 +86,186 @@ def home_team(self, nextgame_data):
79
86
home = nextgame_data ['teams' ]['home' ]
80
87
home .update (nextgame_data ['score' ]['home' ])
81
88
return home
82
- def render_baseball_standings (self , api ):
83
- self .clear ()
84
- self .reload_image ()
85
- scrolling_font = ImageFont .truetype ("/usr/share/fonts/fonts/04B_03B_.TTF" , 8 )
86
- if 'baseball' in api .sport :
87
- self .logger .info ("Found Baseball, Displaying Baseball Matrix" )
88
- color = (156 ,163 ,173 )
89
- # Can't Have multiple images and or buffers
90
- american , national = self .baseball_divisions (api .standings )
91
- american .extend (national )
92
- text = "\n " .join (american )
93
- img_width , img_height = self .get_text_size (text )
94
- self .logger .info ("Displaying Standings" )
95
- ypos = 0
96
- while ypos < 100 :
97
- ypos += 1
98
- if ypos == 1 or ypos % 8 == 0 :
99
- xpos = 0
100
- pause = True
101
- while xpos < img_width :
102
- if xpos > 100 :
103
- break
104
- self .reload_image ()
105
- self .draw_multiline_text ((- xpos , - ypos - ypos ), text , font = scrolling_font , fill = color , spacing = 1 ) if ypos > 1 else self .draw_multiline_text ((- xpos , 0 ), text , font = scrolling_font , fill = color , spacing = 1 )
106
- self .render_image ()
107
- time .sleep (3 ) if pause else time .sleep (0 )
108
- xpos += 1
109
- pause = False
110
- self .reload_image ()
111
- self .image_resize (64 , img_height )
112
- self .draw_multiline_text ((0 , - ypos ), text , font = scrolling_font , fill = color , spacing = 1 )
113
- self .render_image (yoffset = - ypos )
114
- def render_baseball_nextgame (self , api ):
115
- self .clear ()
116
- self .reload_image ()
117
- self .draw_rectangle ([(0 ,0 ), (63 , 31 )])
118
- self .draw_line ([(32 ,0 ), (32 ,32 )])
89
+
90
+ def get_logo (self , logo_url , name ):
91
+ file_name = f"/tmp/{ name } .png"
92
+ if not os .path .isfile (file_name ):
93
+ urllib .request .urlretrieve (logo_url , file_name )
94
+ return file_name
95
+
96
+ def build_in_game_image (self , nextgame ):
97
+ middle_image = self .make_new_image ((34 ,16 ))
98
+ middle_draw = ImageDraw .Draw (middle_image )
119
99
font = ImageFont .truetype ("/usr/share/fonts/fonts/04B_03B_.TTF" , 8 )
120
- self .draw_text ((28 , 14 ), "VS" , font = font )
121
- nextgame = self .determine_nextgame (api .next_game )
122
- away_data = self .away_team (nextgame_data = nextgame )
100
+ status = nextgame ['status' ]
101
+ score = (nextgame ['teams' ]['home' ]['total' ], nextgame ['teams' ]['away' ]['total' ])
102
+ middle_draw .multiline_text ((10 ,0 ), f"{ status } \n { score [0 ]} -{ score [1 ]} " , font = font )
103
+ return middle_image , (15 , 0 )
104
+ def build_finished_game_image (self , nextgame ):
105
+ middle_image = self .make_new_image ((34 ,16 ))
106
+ middle_draw = ImageDraw .Draw (middle_image )
107
+ font = ImageFont .truetype ("/usr/share/fonts/fonts/04B_03B_.TTF" , 8 )
108
+ status = nextgame ['status' ]
109
+ score = (nextgame ['teams' ]['home' ]['total' ], nextgame ['teams' ]['away' ]['total' ])
110
+ middle_draw .multiline_text ((10 ,0 ), f"{ status } \n { score [0 ]} -{ score [1 ]} " , font = font )
111
+ return middle_image , (15 , 0 )
112
+
113
+ def check_offseason (self , api ):
114
+ try :
115
+ start_time , end_time = api .get_timestamps [0 ][1 ], api .get_timestamps [- 1 ][1 ]
116
+ if datetime .fromtimestamp (start_time ) <= datetime .now () <= datetime .fromtimestamp (end_time ):
117
+ return True
118
+ except Exception :
119
+ return False
120
+ def build_next_game_image (self , nextgame ):
121
+ middle_image = self .make_new_image ((34 ,16 ))
122
+ middle_draw = ImageDraw .Draw (middle_image )
123
+ font = ImageFont .truetype ("/usr/share/fonts/fonts/04B_03B_.TTF" , 8 )
124
+ time = datetime .fromtimestamp (nextgame ['timestamp' ]).strftime ("%I:%M%p %a" )
125
+ time = "\n " .join (time .split ())
126
+ middle_draw .multiline_text ((0 ,0 ), f'{ time } ' , font = font )
127
+ return middle_image , (15 , 0 )
128
+
129
+ def build_home_away_image (self , nextgame ):
123
130
home_data = self .home_team (nextgame )
124
- self .render_image ()
125
- breakpoint ()
126
-
131
+ home_logo = Image .open (self .get_logo (home_data ['logo' ], home_data ['id' ]))
132
+ home_logo .thumbnail ((16 ,16 ))
133
+ away_data = self .away_team (nextgame )
134
+ away_logo = Image .open (self .get_logo (away_data ['logo' ], away_data ['id' ]))
135
+ away_logo .thumbnail ((16 ,16 ))
136
+ return (home_logo , (- 2 ,0 )), (away_logo , (50 , 0 ))
137
+
138
+ def build_middle_nextgame (self , api ):
139
+ nextgame = self .determine_nextgame (api .next_game )
140
+ if "IN" in nextgame ['status' ]:
141
+ return self .build_in_game_image (nextgame )
142
+ elif "NS" == nextgame ['status' ]:
143
+ return self .build_next_game_image (nextgame )
144
+ elif "FT" == nextgame ['status' ]:
145
+ return self .build_finished_game_image (nextgame )
146
+
147
+ def build_middle_image (self , api ):
148
+ nextgame = self .determine_nextgame (api .next_game )
149
+ home_image , away_image = self .build_home_away_image (nextgame )
150
+ middle_image = self .build_middle_nextgame (api )
151
+ master_middle_image = self .make_new_image ((64 , 16 ))
152
+ master_middle_image .paste (home_image [0 ], home_image [1 ])
153
+ master_middle_image .paste (away_image [0 ], away_image [1 ])
154
+ master_middle_image .paste (middle_image [0 ], middle_image [1 ])
155
+ return master_middle_image , (0 ,9 )
156
+
157
+ def build_top_home_away_images (self , nextgame , xpos ):
158
+ font = ImageFont .truetype ("/usr/share/fonts/fonts/04B_03B_.TTF" , 8 )
159
+ top_home_image = self .make_new_image ((22 ,8 ))
160
+ top_home_draw = ImageDraw .Draw (top_home_image )
161
+ top_away_image = self .make_new_image ((22 ,8 ))
162
+ top_away_draw = ImageDraw .Draw (top_away_image )
163
+ hometeam = nextgame ['teams' ]['home' ]['name' ]
164
+ awayteam = nextgame ['teams' ]['away' ]['name' ]
165
+ top_home_draw .text ((- xpos ,0 ), hometeam , font = font )
166
+ top_away_draw .text ((- xpos ,0 ), awayteam , font = font )
167
+ return top_home_image , top_away_image
168
+
169
+ def build_top_image (self , api , xpos ):
170
+ nextgame = self .determine_nextgame (api .next_game )
171
+ master_top_image = self .make_new_image ((64 , 8 ))
172
+ home_image , away_image = self .build_top_home_away_images (nextgame , xpos )
173
+ top_middle_image = self .make_new_image ((22 ,8 ))
174
+ top_middle_draw = ImageDraw .Draw (top_middle_image )
175
+ top_middle_draw .text ((5 ,0 ), "VS" , font = ImageFont .truetype ("/usr/share/fonts/fonts/04B_03B_.TTF" , 8 ))
176
+ master_top_image .paste (home_image , (0 ,0 ))
177
+ master_top_image .paste (away_image , (44 ,0 ))
178
+ master_top_image .paste (top_middle_image , (22 ,0 ))
179
+ return master_top_image , (0 ,0 )
180
+
181
+ def build_standings_image (self , api , xpos ) -> Tuple [int , int ]:
182
+ """,
183
+ This is most bottom Image
184
+ """
185
+ standings_image = Image .new ("RGB" , (64 ,8 ))
186
+ standings_draw = ImageDraw .Draw (standings_image )
187
+ scrolling_font = ImageFont .truetype ("/usr/share/fonts/fonts/04B_03B_.TTF" , 8 )
188
+ color = (156 ,163 ,173 )
189
+ # Can't Have multiple images and or buffers
190
+ american , national = self .baseball_divisions (api .standings )
191
+ american .extend (national )
192
+ text = " " .join (american )
193
+ img_width , img_height = self .get_text_size (text )
194
+ standings_draw .text (
195
+ (- xpos , 0 ),
196
+ text ,
197
+ font = scrolling_font ,
198
+ fill = color
199
+ )
200
+ return standings_image , (0 , 25 )
201
+
127
202
def render (self , api ):
128
203
self .clear ()
129
204
self .reload_image ()
130
- scrolling_font = ImageFont .truetype ("/usr/share/fonts/fonts/04B_03B_.TTF" , 8 )
131
205
if 'baseball' in api .sport :
132
206
# Check Data if Offseason if yes Diplay Offseason, Otherwise Display Data
133
207
# Check data if Game is active, if yes Display game -> Score Inning AT bat Maybe?
134
208
# Else Display next game
135
209
# Only do standings right now
136
- self .render_baseball_standings (api )
137
- # self.render_baseball_nextgame(api)
210
+ self .logger .info ("Found Baseball, Displaying Baseball Matrix" )
211
+ if self .check_offseason (api ):
212
+ xpos = 0
213
+ xpos_for_top = 0
214
+ while xpos < 2700 :
215
+ self .reload_image ()
216
+ images = (
217
+ self .build_standings_image (api , xpos ),
218
+ self .build_middle_image (api ),
219
+ self .build_top_image (api , xpos_for_top ),
220
+ )
221
+ for image , position in images :
222
+ self .paste_image (image , position )
223
+ self .render_image ()
224
+ xpos += 1
225
+ xpos_for_top += 1
226
+ if xpos_for_top == 100 :
227
+ xpos_for_top = 0
228
+ time .sleep (3 ) if xpos == 1 else time .sleep (.05 )
229
+ else :
230
+ font = ImageFont .truetype ("/usr/share/fonts/fonts/04b24.otf" , 14 )
231
+ self .draw_multiline_text ((0 , 0 ), "Basketball\n Offseason" , font = font )
232
+ self .render_image ()
233
+ time .sleep (30 )
138
234
if 'basketball' in api .sport :
139
- sportmatrix = BasketballMatrix (self .matrix , api , self .logger )
235
+ # Check Data if Offseason if yes Diplay Offseason, Otherwise Display Data
236
+ # Check data if Game is active, if yes Display game -> Score Inning AT bat Maybe?
237
+ # Else Display next game
238
+ # Only do standings right now
239
+ self .logger .info ("Found Basketball, Displaying Basketball Matrix" )
240
+ if self .check_offseason (api ):
241
+ xpos = 0
242
+ xpos_for_top = 0
243
+ while xpos < 2700 :
244
+ self .reload_image ()
245
+ images = (
246
+ self .build_standings_image (api , xpos ),
247
+ self .build_middle_image (api ),
248
+ self .build_top_image (api , xpos_for_top ),
249
+ )
250
+ for image , position in images :
251
+ self .paste_image (image , position )
252
+ self .render_image ()
253
+ xpos += 1
254
+ xpos_for_top += 1
255
+ if xpos_for_top == 100 :
256
+ xpos_for_top = 0
257
+ time .sleep (3 ) if xpos == 1 else time .sleep (.05 )
258
+ else :
259
+ font = ImageFont .truetype ("/usr/share/fonts/fonts/04b24.otf" , 14 )
260
+ self .draw_multiline_text ((0 , 0 ), "Basketball\n Offseason" , font = font )
261
+ self .render_image ()
262
+ time .sleep (30 )
140
263
if 'hockey' in api .sport :
141
- sportmatrix = HockeyMatrix (self .matrix , api , self .logger )
142
-
264
+ self .logger .info ("Found Hockey, Displaying Hockey Matrix" )
265
+ if self .check_offseason (api ):
266
+ sportmatrix = HockeyMatrix (self .matrix , api , self .logger )
267
+ else :
268
+ font = ImageFont .truetype ("/usr/share/fonts/fonts/04b24.otf" , 14 )
269
+ self .draw_multiline_text ((0 , 0 ), "Hockey\n Offseason" , font = font )
270
+ self .render_image ()
271
+ time .sleep (30 )
0 commit comments