404 lines
12 KiB
Python
404 lines
12 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]) -> dict[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_event2 = event.total
|
|
points_event2_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, sheet_name: str, 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)
|
|
|
|
headers = ['team']
|
|
prefix_list = seasons.copy()
|
|
prefix_list.append('Avg')
|
|
suffix_list = ['Rank', 'Point Total',
|
|
'Points District', 'Points District No Awards']
|
|
|
|
for suffix in suffix_list:
|
|
for prefix in prefix_list:
|
|
headers.append(f'{prefix} {suffix}')
|
|
|
|
write_result(path, results_list, sheet_name, headers=headers)
|
|
|
|
|
|
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)
|
|
|
|
if sheet_name is None or sheet_name in wb.sheetnames:
|
|
wb.remove(wb[sheet_name])
|
|
|
|
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')
|
|
|
|
skip_years = [2020,2021]
|
|
|
|
seasons = [f'{year}fim' for year in range(2022, 2025) if year not in skip_years]
|
|
|
|
root_dir = Path('results')
|
|
|
|
|
|
event_details_path = root_dir / f'{run_time_str} - Event Details.xlsx'
|
|
|
|
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_rankings: dict[dict] = {}
|
|
|
|
for team in event['teams']:
|
|
if team in rankings:
|
|
event_rankings[team] = rankings[team]
|
|
else:
|
|
event_rankings[team] = {}
|
|
|
|
|
|
if team in rankings:
|
|
for season in seasons:
|
|
if season in rankings[team]:
|
|
team_season = rankings[team][season]
|
|
|
|
rank_sum += team_season['rank']
|
|
point_total_sum += team_season['point_total']
|
|
|
|
if team_season['points_event1'] is not None:
|
|
point_district_sum += team_season['points_event1']
|
|
|
|
if team_season['points_event2'] is not None:
|
|
point_district_sum += team_season['points_event2']
|
|
|
|
if team_season['points_event1_na'] is not None:
|
|
point_district_na_sum += team_season['points_event1_na']
|
|
|
|
if team_season['points_event2_na'] is not None:
|
|
point_district_na_sum += team_season['points_event2_na']
|
|
|
|
entry_count += 1
|
|
|
|
write_power_rank(event_details_path, event['key'], event_rankings, seasons)
|
|
|
|
# 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
|
|
print('Writing Event Summary')
|
|
write_result(event_details_path, event_summary, "Summary", 0)
|
|
|
|
# Write Power Rankings
|
|
print('Writing Power Ranking')
|
|
write_power_rank(
|
|
root_dir / f"Power Ranking.xlsx", 'Power Ranking', rankings, seasons)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|