Files
FIM_EventStrength/get_rankings.py
2024-10-10 14:14:55 -04:00

404 lines
13 KiB
Python

from pathlib import Path
from typing import Optional
import tbaapiv3client
from tbaapiv3client.rest import ApiException
from pprint import pprint
from datetime import datetime as dt
from openpyxl import Workbook, worksheet, load_workbook
from openpyxl.worksheet.table import Table, TableStyleInfo
from csv import DictWriter
# Setup Config
config = tbaapiv3client.Configuration(
host='https://www.thebluealliance.com/api/v3',
api_key={
'X-TBA-Auth-Key': '7SvEHOaVwj3HXwnSyxLatIDWBMN3QPPvhJxzQ7m9DnuD94OzLUu0yp56YguLa1KF'
})
config.verify_ssl = False
def get_rankings(api_client: tbaapiv3client.ApiClient, seasons: list[str]) -> list[dict]:
# Create an instance of the API class
api_instance = tbaapiv3client.DistrictApi(api_client)
rankings = {}
for season in seasons:
try:
results = api_instance.get_district_rankings(season)
except ApiException as e:
print("Exception when calling DistrictApi->get_district_rankings: %s\n" % e)
else:
for result in results:
team = result.team_key
if team not in rankings:
rankings[team] = {}
points_event1 = None
points_event1_na = None
points_event2 = None
points_event2_na = None
if len(result.event_points) > 0:
event = result.event_points[0]
points_event1 = event.total
points_event1_na = event.qual_points + event.elim_points + event.alliance_points
if len(result.event_points) > 1:
event = result.event_points[1]
points_event1 = event.total
points_event1_na = event.qual_points + event.elim_points + event.alliance_points
rankings[team][season] = {
"rank": result.rank,
"point_total": result.point_total,
"points_event1": points_event1,
"points_event2": points_event2,
"points_event1_na": points_event1_na,
"points_event2_na": points_event2_na
}
return rankings
def get_event_teams(api_client: tbaapiv3client.ApiClient, season: str) -> dict[dict]:
api_district = tbaapiv3client.DistrictApi(api_client)
api_event = tbaapiv3client.EventApi(api_client)
try:
district_results = api_district.get_district_events(season)
except ApiException as e:
print("Exception when calling EventApi->get_district_events: %s\n" % e)
else:
event_teams: dict = {}
for district_result in district_results:
key = district_result.key
name = district_result.name
if 'cmp' not in key:
try:
team_results = api_event.get_event_teams_keys(key)
except ApiException as e:
print(
"Exception when calling EventApi->get_event_teams_keys: %s\n" % e)
else:
event_teams[key] = {
'key': key,
'name': name,
'teams': team_results,
'start date': district_result.start_date,
'week': district_result.start_date.isocalendar()[1] - 8
}
return event_teams
def write_power_rank(path: str | Path, rankings: list[dict], seasons: list[str]) -> None:
# Create annual rank CSV
results_list: list[dict] = []
for team, ranks in rankings.items():
result = {
'team': team
}
rank_sum = 0
point_total_sum = 0
point_district_sum = 0
point_district_na_sum = 0
entry_count = 0
for season in seasons:
rank = ''
point_total = ''
point_district = ''
point_district_na = ''
if season in ranks:
rank = ranks[season]['rank']
point_total = ranks[season]['point_total']
point_district = 0
if ranks[season]['points_event1'] is not None:
point_district += ranks[season]['points_event1']
if ranks[season]['points_event2'] is not None:
point_district += ranks[season]['points_event2']
point_district_na = 0
if ranks[season]['points_event1_na'] is not None:
point_district_na += ranks[season]['points_event1_na']
if ranks[season]['points_event2_na'] is not None:
point_district_na += ranks[season]['points_event2_na']
rank_sum += rank
point_total_sum += point_total
point_district_sum += point_district
point_district_na_sum += point_district_na
entry_count += 1
result[f'{season} Rank'] = rank
result[f'{season} Point Total'] = point_total
result[f'{season} Points District'] = point_district
result[f'{season} Points District No Awards'] = point_district_na
rank_avg = ''
point_total_avg = ''
point_district_avg = ''
point_district_na_avg = ''
if entry_count > 0:
rank_avg = rank_sum / entry_count
point_total_avg = point_total_sum / entry_count
point_district_avg = point_district_sum / entry_count
point_district_na_avg = point_district_na_sum / entry_count
result[f'Avg Rank'] = rank_avg
result[f'Avg Point Total'] = point_total_avg
result[f'Avg Points District'] = point_district_avg
result[f'Avg Points District No Awards'] = point_district_na_avg
results_list.append(result)
write_result(path, results_list,"Power Ranking")
def write_rank(path: str | Path, rankings: list[dict], seasons: list[str]) -> None:
# Create annual rank CSV
results_list: list[dict] = []
for team, ranks in rankings.items():
result = {
'team': team
}
for season in seasons:
value = ''
if season in ranks:
value = ranks[season]['rank']
result[season] = value
results_list.append(result)
write_result(path, results_list)
def write_point_total(path: str | Path, rankings: list[dict], seasons: list[str]) -> None:
# Create annual rank CSV
results_list: list[dict] = []
for team, ranks in rankings.items():
result = {
'team': team
}
for season in seasons:
value = ''
if season in ranks:
value = ranks[season]['point_total']
result[season] = value
results_list.append(result)
write_result(path, results_list)
def write_points_events(path: str | Path, rankings: list[dict], seasons: list[str]) -> None:
# Create annual rank CSV
results_list: list[dict] = []
for team, ranks in rankings.items():
result = {
'team': team
}
for season in seasons:
value = ''
if season in ranks:
value = 0
if ranks[season]['points_event1'] is not None:
value += ranks[season]['points_event1']
if ranks[season]['points_event2'] is not None:
value += ranks[season]['points_event2']
result[season] = value
results_list.append(result)
write_result(path, results_list)
def write_result(path: str | Path, results_list: list[dict], sheet_name:Optional[str] = None, sheet_index:Optional[int]=None, headers:Optional[list[str]]=None) -> None:
# Convert path to Path type if it isn't already
if not isinstance(path, Path):
path = Path(path)
# Get headers
if headers is None:
headers = list(results_list[0].keys())
# Open workbook
wb:Workbook = None
ws = None
if path.exists():
wb = load_workbook(path)
ws = wb.create_sheet(sheet_name,sheet_index)
else:
wb = Workbook()
ws = wb.active
if sheet_name is not None:
ws.title = sheet_name
# Write Header
ws.append(headers)
# Write Results
for row in results_list:
values = []
for header in headers:
if header in row:
values.append(row[header])
else:
values.append(None)
ws.append(values)
# Enable Filter
ws.auto_filter.ref = ws.dimensions
# Save Workbook
wb.save(path)
def main():
run_time = dt.now()
run_time_str = run_time.strftime('%Y%m%d_%H%M')
seasons = ['2022fim', '2023fim', '2024fim']
root_dir = Path('results')
with tbaapiv3client.ApiClient(config) as api_client:
rankings = get_rankings(api_client, seasons)
event_teams = get_event_teams(api_client, '2025fim')
event_summary: list[dict] = []
for key, event in event_teams.items():
rank_sum = 0
point_total_sum = 0
point_district_sum = 0
point_district_na_sum = 0
entry_count = 0
event_details: list[dict] = []
for team in event['teams']:
team_details = {
'team': team
}
if team in rankings:
for season in seasons:
rank = ''
point_total = ''
point_district = ''
point_district_na = ''
if season in rankings[team]:
team_season = rankings[team][season]
rank = team_season['rank']
point_total = team_season['point_total']
point_district = 0
point_district_na = 0
if team_season['points_event1'] is not None:
point_district += team_season['points_event1']
if team_season['points_event2'] is not None:
point_district += team_season['points_event2']
if team_season['points_event1_na'] is not None:
point_district_na += team_season['points_event1_na']
if team_season['points_event2_na'] is not None:
point_district_na += team_season['points_event2_na']
rank_sum += rank
point_total_sum += point_total
point_district_sum += point_district
point_district_na_sum += point_district_na
entry_count += 1
team_details[f'{season} rank'] = rank
team_details[f'{season} point total'] = point_total
team_details[f'{season} point district'] = point_district
team_details[f'{season} point district no awards'] = point_district
else:
for season in seasons:
team_details[f'{season} rank'] = ''
team_details[f'{season} point total'] = ''
team_details[f'{season} point district'] = ''
team_details[f'{season} point district no awards'] = ''
event_details.append(team_details)
if len(event_details):
write_result(root_dir / f'{run_time_str} - Event Details.xlsx', event_details, key)
# Generate Event Summary
rank_avg = ''
point_total_avg = ''
point_district_avg = ''
point_district_na_avg = ''
if entry_count > 0:
rank_avg = rank_sum / entry_count
point_total_avg = point_total_sum / entry_count
point_district_avg = point_district_sum / entry_count
point_district_na_avg = point_district_na_sum / entry_count
event_summary.append({
'key': key,
'name': event['name'],
'start date': event['start date'],
'week': event['week'],
'average rank': rank_avg,
'average point total': point_total_avg,
'average point district': point_district_avg,
'average point district no awards': point_district_na_avg,
'entries': entry_count,
'team count': len(event['teams'])
})
# Write Event Summary
write_result(root_dir / f'{run_time_str} - Event Details.xlsx', event_summary, "Summary", 0)
# Write Power Rankings
write_power_rank(
root_dir / f"Power Ranking.xlsx", rankings, seasons)
if __name__ == '__main__':
main()