From b24fc9d03ebf6e29b5a6a02cde90ef4465e43f52 Mon Sep 17 00:00:00 2001 From: Alex Oladele Date: Fri, 20 Mar 2026 13:02:28 -0400 Subject: [PATCH 1/2] fix(frcteamrank): handle null qual data from The Blue Alliance API The Blue Alliance returns "qual": null when an event is active but matches haven't started yet. The existing checks only verified key existence, not whether the value was None, causing a crash on the `in` operator. --- apps/frcteamrank/frc_team_rank.star | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/frcteamrank/frc_team_rank.star b/apps/frcteamrank/frc_team_rank.star index a7ac70a76..6cbafb6a5 100644 --- a/apps/frcteamrank/frc_team_rank.star +++ b/apps/frcteamrank/frc_team_rank.star @@ -158,12 +158,14 @@ def get_team_ranking(team_number, event_key, tba_api_key): fail("%s - Status code: %s" % (team_ranking_error, team_ranking_resp.status_code)) # Parse the team ranking data + # TBA returns qual/ranking/rank as nested objects, but any level can be + # None (not just missing) when the event hasn't started matches yet. ranking_data = team_ranking_resp.json() - if "qual" not in ranking_data: + if "qual" not in ranking_data or ranking_data["qual"] == None: return -1, 999 - if "ranking" not in ranking_data["qual"]: + if "ranking" not in ranking_data["qual"] or ranking_data["qual"]["ranking"] == None: return -1, 999 - if "rank" not in ranking_data["qual"]["ranking"]: + if "rank" not in ranking_data["qual"]["ranking"] or ranking_data["qual"]["ranking"]["rank"] == None: return -1, 999 team_ranking = ranking_data["qual"]["ranking"]["rank"] total_teams = ranking_data["qual"]["num_teams"] From 8d638a45085a6b8cd9cec01d9a8fa4d4ea4c1b8a Mon Sep 17 00:00:00 2001 From: Alex Oladele Date: Fri, 20 Mar 2026 13:11:14 -0400 Subject: [PATCH 2/2] refactor(frcteamrank): use intermediate variables and .get() for ranking data Simplifies nested dict access for readability and safety. --- apps/frcteamrank/frc_team_rank.star | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/frcteamrank/frc_team_rank.star b/apps/frcteamrank/frc_team_rank.star index 6cbafb6a5..d6c436d9f 100644 --- a/apps/frcteamrank/frc_team_rank.star +++ b/apps/frcteamrank/frc_team_rank.star @@ -157,19 +157,23 @@ def get_team_ranking(team_number, event_key, tba_api_key): team_ranking_error = MSG_TEAM_RANKING_ERROR % team_number fail("%s - Status code: %s" % (team_ranking_error, team_ranking_resp.status_code)) - # Parse the team ranking data + # Parse the team ranking data using intermediate variables. # TBA returns qual/ranking/rank as nested objects, but any level can be # None (not just missing) when the event hasn't started matches yet. ranking_data = team_ranking_resp.json() - if "qual" not in ranking_data or ranking_data["qual"] == None: + qual_data = ranking_data.get("qual") + if not qual_data: return -1, 999 - if "ranking" not in ranking_data["qual"] or ranking_data["qual"]["ranking"] == None: + + ranking_info = qual_data.get("ranking") + if not ranking_info: return -1, 999 - if "rank" not in ranking_data["qual"]["ranking"] or ranking_data["qual"]["ranking"]["rank"] == None: + + team_ranking = ranking_info.get("rank") + if team_ranking == None: return -1, 999 - team_ranking = ranking_data["qual"]["ranking"]["rank"] - total_teams = ranking_data["qual"]["num_teams"] + total_teams = ranking_info.get("num_teams", 999) return team_ranking, total_teams def build_avatar_url(team_number):