Commit c112ed86ba

c112ed86bafa47aa2141b626a5592bd06cbc81f6

parent: e98e9dd641

Verified · cmc

cmc <hello@cleberg.net> · 2026-05-07 04:26 UTC

feat: add playoff bracket status accents

Layout: unified · split

build/lib/nba/__pycache__/bracket.cpython-314.pyc added

Binary file not shown.

build/lib/nba/bracket.py +32 −4
@@ -3,6 +3,7 @@ Fetches and formats the NBA playoff bracket.
3""" 3"""
4 4
5import json 5import json
6import re
6from collections import defaultdict 7from collections import defaultdict
7from typing import Optional 8from typing import Optional
8 9
@@ -13,6 +14,10 @@ from nba_api.stats.static import teams
13BOLD = "\033[1m" 14BOLD = "\033[1m"
14END = "\033[0m" 15END = "\033[0m"
15GREEN = "\033[32m" 16GREEN = "\033[32m"
17RED = "\033[91m"
18YELLOW = "\033[33m"
19CYAN = "\033[36m"
20ANSI_RE = re.compile(r"\033\[[0-9;]*m")
16 21
17ROUND_LABELS = { 22ROUND_LABELS = {
18 1: "First Round", 23 1: "First Round",
@@ -54,6 +59,8 @@ def get_bracket_table(data: dict) -> str:
54 return "\n".join( 59 return "\n".join(
55 [ 60 [
56 _center(f"{BOLD}NBA Playoff Bracket{END}", 74), 61 _center(f"{BOLD}NBA Playoff Bracket{END}", 74),
62 f"{GREEN}* Advanced{END} {RED}x Eliminated{END} "
63 f"{CYAN}> Series lead{END} {YELLOW}! Can clinch next win{END}",
57 "", 64 "",
58 _render_conference("Western", summaries), 65 _render_conference("Western", summaries),
59 "", 66 "",
@@ -182,7 +189,7 @@ def _render_finals(summaries: dict) -> str:
182 if final is None: 189 if final is None:
183 lines.append("Winner TBD") 190 lines.append("Winner TBD")
184 elif final["winner"]: 191 elif final["winner"]:
185 lines.append(f"{GREEN}{final['winner']} wins the Finals{END}") 192 lines.append(f"{BOLD}{GREEN}{final['winner']} wins the Finals{END}")
186 return "\n".join(lines) 193 return "\n".join(lines)
187 194
188 195
@@ -209,20 +216,36 @@ def _series_box(summary: Optional[dict], width: int) -> str:
209 visitor = _team_line( 216 visitor = _team_line(
210 summary["visitor_abbr"], 217 summary["visitor_abbr"],
211 summary["visitor_wins"], 218 summary["visitor_wins"],
219 summary["home_wins"],
212 summary["winner"] == summary["visitor_abbr"], 220 summary["winner"] == summary["visitor_abbr"],
221 summary["winner"] == summary["home_abbr"],
213 ) 222 )
214 home = _team_line( 223 home = _team_line(
215 summary["home_abbr"], 224 summary["home_abbr"],
216 summary["home_wins"], 225 summary["home_wins"],
226 summary["visitor_wins"],
217 summary["winner"] == summary["home_abbr"], 227 summary["winner"] == summary["home_abbr"],
228 summary["winner"] == summary["visitor_abbr"],
218 ) 229 )
219 return f"{visitor} / {home}".ljust(width) 230 return _pad_ansi(f"{visitor} / {home}", width)
220 231
221 232
222def _team_line(abbr: str, wins: int, won_series: bool) -> str: 233def _team_line(
234 abbr: str,
235 wins: int,
236 opponent_wins: int,
237 won_series: bool,
238 lost_series: bool,
239) -> str:
223 label = f"{abbr} {wins}" 240 label = f"{abbr} {wins}"
224 if won_series: 241 if won_series:
225 return f"{label}*" 242 return f"{BOLD}{GREEN}{label}*{END}"
243 if lost_series:
244 return f"{RED}{label}x{END}"
245 if wins == 3:
246 return f"{BOLD}{YELLOW}{label}!{END}"
247 if wins > opponent_wins:
248 return f"{CYAN}{label}>{END}"
226 return label 249 return label
227 250
228 251
@@ -248,6 +271,11 @@ def _center(text: str, width: int) -> str:
248 return text.center(width) 271 return text.center(width)
249 272
250 273
274def _pad_ansi(text: str, width: int) -> str:
275 visible_length = len(ANSI_RE.sub("", text))
276 return text + " " * max(width - visible_length, 0)
277
278
251def _round_number(series_id: str) -> int: 279def _round_number(series_id: str) -> int:
252 try: 280 try:
253 return int(series_id[-3:-1]) 281 return int(series_id[-3:-1])
nba/bracket.py +32 −4
@@ -3,6 +3,7 @@ Fetches and formats the NBA playoff bracket.
3""" 3"""
4 4
5import json 5import json
6import re
6from collections import defaultdict 7from collections import defaultdict
7from typing import Optional 8from typing import Optional
8 9
@@ -13,6 +14,10 @@ from nba_api.stats.static import teams
13BOLD = "\033[1m" 14BOLD = "\033[1m"
14END = "\033[0m" 15END = "\033[0m"
15GREEN = "\033[32m" 16GREEN = "\033[32m"
17RED = "\033[91m"
18YELLOW = "\033[33m"
19CYAN = "\033[36m"
20ANSI_RE = re.compile(r"\033\[[0-9;]*m")
16 21
17ROUND_LABELS = { 22ROUND_LABELS = {
18 1: "First Round", 23 1: "First Round",
@@ -54,6 +59,8 @@ def get_bracket_table(data: dict) -> str:
54 return "\n".join( 59 return "\n".join(
55 [ 60 [
56 _center(f"{BOLD}NBA Playoff Bracket{END}", 74), 61 _center(f"{BOLD}NBA Playoff Bracket{END}", 74),
62 f"{GREEN}* Advanced{END} {RED}x Eliminated{END} "
63 f"{CYAN}> Series lead{END} {YELLOW}! Can clinch next win{END}",
57 "", 64 "",
58 _render_conference("Western", summaries), 65 _render_conference("Western", summaries),
59 "", 66 "",
@@ -182,7 +189,7 @@ def _render_finals(summaries: dict) -> str:
182 if final is None: 189 if final is None:
183 lines.append("Winner TBD") 190 lines.append("Winner TBD")
184 elif final["winner"]: 191 elif final["winner"]:
185 lines.append(f"{GREEN}{final['winner']} wins the Finals{END}") 192 lines.append(f"{BOLD}{GREEN}{final['winner']} wins the Finals{END}")
186 return "\n".join(lines) 193 return "\n".join(lines)
187 194
188 195
@@ -209,20 +216,36 @@ def _series_box(summary: Optional[dict], width: int) -> str:
209 visitor = _team_line( 216 visitor = _team_line(
210 summary["visitor_abbr"], 217 summary["visitor_abbr"],
211 summary["visitor_wins"], 218 summary["visitor_wins"],
219 summary["home_wins"],
212 summary["winner"] == summary["visitor_abbr"], 220 summary["winner"] == summary["visitor_abbr"],
221 summary["winner"] == summary["home_abbr"],
213 ) 222 )
214 home = _team_line( 223 home = _team_line(
215 summary["home_abbr"], 224 summary["home_abbr"],
216 summary["home_wins"], 225 summary["home_wins"],
226 summary["visitor_wins"],
217 summary["winner"] == summary["home_abbr"], 227 summary["winner"] == summary["home_abbr"],
228 summary["winner"] == summary["visitor_abbr"],
218 ) 229 )
219 return f"{visitor} / {home}".ljust(width) 230 return _pad_ansi(f"{visitor} / {home}", width)
220 231
221 232
222def _team_line(abbr: str, wins: int, won_series: bool) -> str: 233def _team_line(
234 abbr: str,
235 wins: int,
236 opponent_wins: int,
237 won_series: bool,
238 lost_series: bool,
239) -> str:
223 label = f"{abbr} {wins}" 240 label = f"{abbr} {wins}"
224 if won_series: 241 if won_series:
225 return f"{label}*" 242 return f"{BOLD}{GREEN}{label}*{END}"
243 if lost_series:
244 return f"{RED}{label}x{END}"
245 if wins == 3:
246 return f"{BOLD}{YELLOW}{label}!{END}"
247 if wins > opponent_wins:
248 return f"{CYAN}{label}>{END}"
226 return label 249 return label
227 250
228 251
@@ -248,6 +271,11 @@ def _center(text: str, width: int) -> str:
248 return text.center(width) 271 return text.center(width)
249 272
250 273
274def _pad_ansi(text: str, width: int) -> str:
275 visible_length = len(ANSI_RE.sub("", text))
276 return text + " " * max(width - visible_length, 0)
277
278
251def _round_number(series_id: str) -> int: 279def _round_number(series_id: str) -> int:
252 try: 280 try:
253 return int(series_id[-3:-1]) 281 return int(series_id[-3:-1])
nba_scores.egg-info/PKG-INFO +1 −1
@@ -1,6 +1,6 @@
1Metadata-Version: 2.4 1Metadata-Version: 2.4
2Name: nba-scores 2Name: nba-scores
3Version: 0.2.2 3Version: 0.2.3
4Summary: A CLI interface to get current NBA scores and standings. 4Summary: A CLI interface to get current NBA scores and standings.
5Author-email: Christian Cleberg <hello@cleberg.net> 5Author-email: Christian Cleberg <hello@cleberg.net>
6License-Expression: GPL-3.0-or-later 6License-Expression: GPL-3.0-or-later
pyproject.toml +1 −1
@@ -1,6 +1,6 @@
1[project] 1[project]
2name = "nba-scores" 2name = "nba-scores"
3version = "0.2.2" 3version = "0.2.3"
4authors = [ 4authors = [
5 { name="Christian Cleberg", email="hello@cleberg.net" }, 5 { name="Christian Cleberg", email="hello@cleberg.net" },
6] 6]