예제 #1
0
def read_predictions(year, week):

    # Check if the week is 'bowl' week
    num_weeks = the_kick_is_bad.read_number_of_weeks(year)
    week, _ = utils.check_week(week, num_weeks)

    # Open predictions file with absolute path
    absolute_path = utils.get_abs_path(__file__)
    filename = f"{absolute_path}/{year}/predictions-{year}-{week:02}.csv"
    with open(filename) as file:

        predictions = []

        # Remove the header line
        _ = file.readline().strip()

        # Loop through lines to read prediction data
        prediction_line = file.readline().strip()
        while prediction_line:

            # Split the prediction data
            prediction = prediction_line.split(",")
            away_team = prediction[0]
            home_team = prediction[1]
            predicted_winner = prediction[2]
            predicted_margin_of_victory = prediction[3]
            game_interest = prediction[4]

            # Pack prediction structure
            predictions.append({
                "away team":
                away_team,
                "home team":
                home_team,
                "predicted winner":
                predicted_winner,
                "predicted margin of victory":
                float(predicted_margin_of_victory),
                "game interest":
                float(game_interest)
            })

            prediction_line = file.readline().strip()

        return predictions
예제 #2
0
def read_rankings(year, week):

    # Check if the week is 'bowl' week
    num_weeks = the_kick_is_bad.read_number_of_weeks(year)
    week, _ = utils.check_week(week, num_weeks)

    # Open rankings file with absolute path
    absolute_path = utils.get_abs_path(__file__)
    filename = f"{absolute_path}/{year}/team_rankings-{year}-{week:02}.csv"
    with open(filename) as file:

        rankings = {}

        # Remove the header line
        _ = file.readline().strip()

        # Loop through lines to read ranking data
        ranking_line = file.readline().strip()
        while ranking_line:

            # Split the ranking data
            ranking = ranking_line.split(",")
            team = ranking[0]
            rank = ranking[1]
            previous_rank = ranking[2]
            delta_rank = ranking[3]
            team_score = ranking[4]
            strength = ranking[5]
            standard_deviation = ranking[6]

            # Pack ranking structure
            rankings[team] = {
                "rank": int(rank),
                "previous rank": int(previous_rank),
                "delta rank": int(delta_rank),
                "team score": float(team_score),
                "strength": float(strength),
                "standard deviation": float(standard_deviation)
            }

            ranking_line = file.readline().strip()

        return rankings
예제 #3
0
def calculate_division_rankings(year, week, teams, team_rankings):

    # Make lists of all the team scores in each division
    division_rankings = {}
    for team in teams:
        division = teams[team]["division"]
        if division not in division_rankings:
            division_rankings[division] = []
        division_rankings[division].append(team_rankings[team]["team score"])

    # Convert dictionary to averaged list for sorting
    sorted_division_rankings = []
    for division in division_rankings:
        sorted_division_rankings.append({
            "division": division,
            "score": statistics.mean(division_rankings[division])
        })
    
    # Sort division rankings by average team score
    sorted_division_rankings = sorted(sorted_division_rankings, key=lambda p: p["score"], reverse=True)

    # Print division rankings
    rank = 1
    division_rankings_file_string = "Division,Score\n"
    for division_ranking in sorted_division_rankings:

        # Print to file string in csv format
        division = division_ranking["division"]
        score = division_ranking["score"]
        division_rankings_file_string += f"{division},{score:.1f}\n"

        # Print to console in pretty format
        print(f"{rank}: {division}, Score: {score:.1f}")
        rank += 1

    # Create the division rankings file with absolute path
    absolute_path = utils.get_abs_path(__file__)
    filename = f"{absolute_path}/rankings/{year}/division_rankings-{year}-{week:02}.csv"
    utils.write_string(division_rankings_file_string, filename)
예제 #4
0
def calculate_conference_rankings(year, week, teams, team_rankings):

    # Make lists of all the team scores in each conference
    conference_rankings = {}
    for team in teams:
        conference = teams[team]["conference"]
        if conference not in conference_rankings:
            conference_rankings[conference] = []
        conference_rankings[conference].append(team_rankings[team]["team score"])

    # Convert dictionary to averaged list for sorting
    sorted_conference_rankings = []
    for conference in conference_rankings:
        sorted_conference_rankings.append({
            "conference": conference,
            "score": statistics.mean(conference_rankings[conference])
        })
    
    # Sort conference rankings by average team score
    sorted_conference_rankings = sorted(sorted_conference_rankings, key=lambda p: p["score"], reverse=True)

    # Print conference rankings
    rank = 1
    conference_rankings_file_string = "Conference,Score\n"
    for conference_ranking in sorted_conference_rankings:

        # Print to file string in csv format
        conference = conference_ranking["conference"]
        score = conference_ranking["score"]
        conference_rankings_file_string += f"{conference},{score:.1f}\n"

        # Print to console in pretty format
        print(f"{rank}: {conference}, Score: {score:.1f}")
        rank += 1

    # Create the conference rankings file with absolute path
    absolute_path = utils.get_abs_path(__file__)
    filename = f"{absolute_path}/rankings/{year}/conference_rankings-{year}-{week:02}.csv"
    utils.write_string(conference_rankings_file_string, filename)
예제 #5
0
def calculate_model(year, week, stats, teams):

    if week < 9:
        prev_stats = the_kick_is_bad.read_stats(year - 1, "bowl")
        prev_model = read_model(year - 1, "bowl")
    else:
        prev_stats = None
        prev_model = None

    games_played = calculate_games_played(week, stats, teams)
    points_margin = calculate_points_margin(week, stats, prev_stats,
                                            games_played, teams)
    rushing_yards_margin = calculate_rushing_yards_margin(
        week, stats, prev_stats, games_played, teams)
    home_field_corrections = calculate_home_field_corrections(
        week, stats, prev_stats, prev_model, games_played, teams)

    games_played_normalization = calculate_games_played_normalization(
        week, stats, games_played, teams)

    strengths = calculate_strengths(week, points_margin, rushing_yards_margin,
                                    home_field_corrections, games_played,
                                    games_played_normalization, prev_model,
                                    teams)
    average_opponent_strengths = np.matmul(games_played_normalization,
                                           strengths)

    standard_deviations = calculate_standard_deviations(
        year, week, prev_model, teams)

    model = {}
    i = 0
    for team in teams:
        model[team] = {
            "strength": strengths[i],
            "standard deviation": standard_deviations[i],
            "points margin": points_margin[i],
            "average opponent strength": average_opponent_strengths[i],
            "rushing yards margin": rushing_yards_margin[i],
            "home field correction": home_field_corrections[i],
            "games played": games_played[i]
        }
        i += 1

    # Print predictions
    model_file_string = "Team,Strength,StandardDeviation,PointsMargin,AverageOpponentStrength,RushingYardsMargin,HomeFieldCorrection,GamesPlayed\n"
    for team in model:

        # Print to file string in csv format
        model_file_string += "{0},{1},{2},{3},{4},{5},{6},{7:.0f}\n".format(
            team, model[team]["strength"], model[team]["standard deviation"],
            model[team]["points margin"],
            model[team]["average opponent strength"],
            model[team]["rushing yards margin"],
            model[team]["home field correction"], model[team]["games played"])

    # Create the predictions file with absolute path
    absolute_path = utils.get_abs_path(__file__)
    filename = f"{absolute_path}/{year}/model-{year}-{week:02}.csv"
    utils.write_string(model_file_string, filename)

    return model, strengths, standard_deviations
예제 #6
0
def evaluate(year, week):

    predictions = read_predictions(year, week)

    scores = the_kick_is_bad.read_scores(year, week)

    # Loop through predictions to check results
    results = []
    for prediction in predictions:
        away_team = prediction["away team"]
        home_team = prediction["home team"]
        predicted_winner = prediction["predicted winner"]
        predicted_margin_of_victory = prediction["predicted margin of victory"]

        # Loop through all scores to find the matching (completed) game
        for game in scores["games"]:
            if game["game"]["gameState"] != "final":
                continue
            
            # Check if this is the same game by comparing team names
            if game["game"]["away"]["names"]["standard"] == away_team and game["game"]["home"]["names"]["standard"] == home_team:
                away_score = int(game["game"]["away"]["score"])
                home_score = int(game["game"]["home"]["score"])

                # Get the actual results
                if away_score > home_score:
                    actual_winner = away_team
                elif home_score > away_score:
                    actual_winner = home_team
                else:
                    actual_winner = "TIE"
                actual_margin_of_victory = abs(away_score - home_score)
                
                # Save the results data
                results.append({
                    "away team": away_team,
                    "home team": home_team,
                    "predicted winner": predicted_winner,
                    "actual winner": actual_winner,
                    "predicted margin of victory": predicted_margin_of_victory,
                    "actual margin of victory": actual_margin_of_victory
                })
                break

    # Print results
    num_results = len(results)
    num_correct = 0
    results_file_string = "AwayTeam,HomeTeam,PredictedWinner,Result,PredictedMoV,ActualMoV\n"
    for result in results:

        # Determine if prediction was correct
        if result["predicted winner"] == result["actual winner"]:
            result_string = "RIGHT"
            num_correct += 1
        else:
            result_string = "WRONG"
            result["actual margin of victory"] *= -1

        # Print to file string in csv format
        results_file_string += "{0},{1},{2},{3},{4:.1f},{5}\n".format(result["away team"],
                                                                      result["home team"],
                                                                      result["predicted winner"],
                                                                      result_string,
                                                                      result["predicted margin of victory"],
                                                                      result["actual margin of victory"])

        # Print to console strin in pretty format
        if result["predicted winner"] == result["home team"]:
            predicted_loser = result["away team"]
        else:
            predicted_loser = result["home team"]
        results_console_string = "{0}: Predicted {1} over {2} by {3:.1f} (actual: {4})".format(result_string,
                                                                                               result["predicted winner"],
                                                                                               predicted_loser,
                                                                                               result["predicted margin of victory"],
                                                                                               result["actual margin of victory"])
        print(results_console_string)

    # Print statistics to console
    accuracy = num_correct / num_results * 100
    print(f"({num_correct}/{num_results}) {accuracy:.1f}%")

    # Create the results file with absolute path
    absolute_path = utils.get_abs_path(__file__)
    filename = f"{absolute_path}/predictions/{year}/results-{year}-{week:02}.csv"
    utils.write_string(results_file_string, filename)
예제 #7
0
def evaluate_model():

    results = {}

    start_year = 2013
    end_year = 2020
    max_num_weeks = 16

    all_num_games = 0
    all_num_correct = 0
    conf_num_games = 0
    conf_num_correct = 0
    nonconf_num_games = 0
    nonconf_num_correct = 0
    champ_num_games = 0
    champ_num_correct = 0
    fcs_num_games = 0
    fcs_num_correct = 0
    bowl_num_games = 0
    bowl_num_correct = 0
    yearly_num_games = []
    for _ in range(0, end_year - start_year + 1):
        yearly_num_games.append(0)
    yearly_num_correct = []
    for _ in range(0, end_year - start_year + 1):
        yearly_num_correct.append(0)
    weekly_num_games = []
    for _ in range(0, max_num_weeks):
        weekly_num_games.append(0)
    weekly_num_correct = []
    for _ in range(0, max_num_weeks):
        weekly_num_correct.append(0)

    for year in range(start_year, end_year + 1):

        year_idx = year - start_year

        teams, _ = the_kick_is_bad.read_teams(year)

        num_weeks = the_kick_is_bad.read_number_of_weeks(year)

        for week in range(1, num_weeks + 1):

            week_idx = week - 1

            print(
                f"Processing evaluation data from year {year}, week {week:02}..."
            )

            rankings = read_rankings(year, week - 1)

            scores = the_kick_is_bad.read_scores(year, week)

            # Loop through scores to make predictions
            for game in scores["games"]:

                # Get the team names
                away_team = game["game"]["away"]["names"]["standard"]
                home_team = game["game"]["home"]["names"]["standard"]

                # Check if this is a valid game
                if game["game"]["gameState"] != "final":
                    continue

                # Get the actual results
                away_score = int(game["game"]["away"]["score"])
                home_score = int(game["game"]["home"]["score"])
                if away_score > home_score:
                    home_won = 0
                elif away_score < home_score:
                    home_won = 1
                else:
                    continue

                # Determine home field advantage
                # Assume all bowl games are neutral site
                home_field_advantage = 4

                # Get away team strength
                away_team_strength = rankings[away_team]["strength"]

                # Get home team strength and add home field advantage
                home_team_strength = rankings[home_team][
                    "strength"] + home_field_advantage

                # Pick the winner based on team strength
                if home_team_strength >= away_team_strength:
                    prediction = 1
                else:
                    prediction = 0

                # Determine if the result was right
                if home_won == prediction:
                    is_correct = 1
                else:
                    is_correct = 0

                # Increment relevant result counters
                all_num_games += 1
                all_num_correct += is_correct
                # Conference/non-conference
                away_team_conference = teams[away_team]["conference"]
                home_team_conference = teams[home_team]["conference"]
                if away_team_conference == home_team_conference:
                    conf_num_games += 1
                    conf_num_correct += is_correct
                elif away_team != "FCS" and home_team != "FCS":
                    nonconf_num_games += 1
                    nonconf_num_correct += is_correct
                # Championship
                if (week == num_weeks - 1) and (away_team_conference
                                                == home_team_conference):
                    champ_num_games += 1
                    champ_num_correct += is_correct
                # FCS
                if away_team == "FCS" or home_team == "FCS":
                    fcs_num_games += 1
                    fcs_num_correct += is_correct
                # Yearly
                yearly_num_games[year_idx] += 1
                yearly_num_correct[year_idx] += is_correct
                # Weekly
                weekly_num_games[week_idx] += 1
                weekly_num_correct[week_idx] += is_correct

        # Add bowl week
        week_idx = num_weeks

        print(f"Processing evaluation data from year {year}, week 'bowl'...")

        scores = the_kick_is_bad.read_scores(year, "bowl")

        for game in scores["games"]:

            # Get the team names
            away_team = game["game"]["away"]["names"]["standard"]
            home_team = game["game"]["home"]["names"]["standard"]

            # Check if this is a valid game
            if game["game"]["gameState"] != "final":
                continue

            # Get the actual results
            away_score = int(game["game"]["away"]["score"])
            home_score = int(game["game"]["home"]["score"])
            if away_score > home_score:
                home_won = 0
            elif away_score < home_score:
                home_won = 1
            else:
                continue

            # Determine home field advantage
            # Assume all bowl games are neutral site
            home_field_advantage = 0

            # Get away team strength
            away_team_strength = rankings[away_team]["strength"]

            # Get home team strength and add home field advantage
            home_team_strength = rankings[home_team][
                "strength"] + home_field_advantage

            # Pick the winner based on team strength
            if home_team_strength >= away_team_strength:
                prediction = 1
            else:
                prediction = 0

            # Determine if the result was right
            if home_won == prediction:
                is_correct = 1
            else:
                is_correct = 0

            # Increment relevant result counters
            all_num_games += 1
            all_num_correct += is_correct
            # Bowl
            bowl_num_games += 1
            bowl_num_correct += is_correct
            # Yearly
            yearly_num_games[year_idx] += 1
            yearly_num_correct[year_idx] += is_correct

    # Calculate final results
    results["all"] = (all_num_correct / all_num_games) * 100
    results["conference"] = (conf_num_correct / conf_num_games) * 100
    results["non_conference"] = (nonconf_num_correct / nonconf_num_games) * 100
    results["championship"] = (champ_num_correct / champ_num_games) * 100
    results["fcs"] = (fcs_num_correct / fcs_num_games) * 100
    results["bowl"] = (bowl_num_correct / bowl_num_games) * 100
    for year_idx in range(0, end_year - start_year + 1):
        results[f"year {start_year + year_idx}"] = (
            yearly_num_correct[year_idx] / yearly_num_games[year_idx]) * 100
    for week_idx in range(0, max_num_weeks):
        results[f"week {1 + week_idx}"] = (weekly_num_correct[week_idx] /
                                           weekly_num_games[week_idx]) * 100

    # Save the evaluation results to file
    absolute_path = utils.get_abs_path(__file__)
    results_filename = f"{absolute_path}/model_evalation.json"
    utils.write_json(results, results_filename)
예제 #8
0
def predict(year, week):

    scores = the_kick_is_bad.read_scores(year, week)

    rankings = read_rankings(year, week - 1)

    # Check if the week is 'bowl' week
    num_weeks = the_kick_is_bad.read_number_of_weeks(year)
    week, _ = utils.check_week(week, num_weeks)

    # Loop through scores to make predictions
    predictions = []
    for game in scores["games"]:

        # Get the team names
        away_team = game["game"]["away"]["names"]["standard"]
        home_team = game["game"]["home"]["names"]["standard"]

        # Determine home field advantage
        # Assume all bowl games are neutral site
        if week <= num_weeks:
            home_field_advantage = 4
        else:
            home_field_advantage = 0

        # Get away team strength
        away_team_strength = rankings[away_team]["strength"]

        # Get home team strength and add home field advantage
        home_team_strength = rankings[home_team][
            "strength"] + home_field_advantage

        # Pick the winner based on team strength
        if home_team_strength >= away_team_strength:
            predicted_winner = home_team
            predicted_margin_of_victory = home_team_strength - away_team_strength
        else:
            predicted_winner = away_team
            predicted_margin_of_victory = away_team_strength - home_team_strength

        # Calculate the game interest score
        game_interest = rankings[away_team]["team score"] + rankings[
            home_team]["team score"] - predicted_margin_of_victory

        # Pack predictions
        predictions.append({
            "away team": away_team,
            "home team": home_team,
            "predicted winner": predicted_winner,
            "predicted margin of victory": predicted_margin_of_victory,
            "game interest": game_interest
        })

    # Sort predictions by game interest
    predictions = sorted(predictions,
                         key=lambda p: p["game interest"],
                         reverse=True)

    # Print predictions
    predictions_file_string = "AwayTeam,HomeTeam,PredictedWinner,PredictedMoV,GameInterest\n"
    for prediction in predictions:

        # Print to console in pretty format
        print(
            "{0} @ {1}: Predicted Winner: {2}, Predicted MoV: {3:.1f}, Game Interest: {4:.1f}"
            .format(prediction["away team"], prediction["home team"],
                    prediction["predicted winner"],
                    prediction["predicted margin of victory"],
                    prediction["game interest"]))

        # Print to file string in csv format
        predictions_file_string += "{0},{1},{2},{3:.1f},{4:.1f}\n".format(
            prediction["away team"], prediction["home team"],
            prediction["predicted winner"],
            prediction["predicted margin of victory"],
            prediction["game interest"])

    # Create the predictions file with absolute path
    absolute_path = utils.get_abs_path(__file__)
    filename = f"{absolute_path}/predictions/{year}/predictions-{year}-{week:02}.csv"
    utils.write_string(predictions_file_string, filename)
예제 #9
0
def calculate_team_rankings(year, week, stats, teams):
    
    _, strengths, standard_deviations = calculate_model(year, week, stats, teams)

    # strengths = get_model_array(model, "strength")
    normalized_strengths = strengths - min(strengths)
    # standard_deviations = get_model_array(model, "standard deviation")
    if week > 0:
        prev_rankings = read_rankings(year, week - 1)

    if week == 0:
        team_scores = normalized_strengths * 0.5
    else:
        wins = get_wins_array(stats, teams)
        games_played = get_games_played_array(stats, teams)
        team_scores = normalized_strengths * (wins + 2) / (games_played + 4)

    sort_indexes = np.argsort(-team_scores)

    rankings = {}
    i = 0
    if week > 0:
        for team in teams:
            rankings[team] = {
                "rank": np.where(sort_indexes == i)[0][0] + 1,
                "previous rank": prev_rankings[team]["rank"],
                "delta rank": prev_rankings[team]["rank"] - (np.where(sort_indexes == i)[0][0] + 1),
                "team score": team_scores[i],
                "strength": strengths[i],
                "standard deviation": standard_deviations[i]
            }
            i += 1
    else:
        for team in teams:
            rankings[team] = {
                "rank": np.where(sort_indexes == i)[0][0] + 1,
                "previous rank": 0,
                "delta rank": 0 - (np.where(sort_indexes == i)[0][0] + 1),
                "team score": team_scores[i],
                "strength": strengths[i],
                "standard deviation": standard_deviations[i]
            }
            i += 1

    # Print teamrankings
    team_rankings_file_string = "Team,Rank,PrevRank,DeltaRank,TeamScore,Strength,StandardDeviation\n"
    for team in rankings:

        # Print to file string in csv format
        team_rankings_file_string += "{0},{1:.0f},{2:.0f},{3:.0f},{4:.1f},{5:.1f},{6:.1f}\n".format(team,
                                                                                                    rankings[team]["rank"],
                                                                                                    rankings[team]["previous rank"],
                                                                                                    rankings[team]["delta rank"],
                                                                                                    rankings[team]["team score"],
                                                                                                    rankings[team]["strength"],
                                                                                                    rankings[team]["standard deviation"])
        
    teams_list = []
    for team in teams:
        teams_list.append(team)

    for index in sort_indexes:
        team = teams_list[index]
        team_rankings_string = "{0:.0f} ({1:.0f}): {2}, Team Score: {3:.1f}, Strength: {4:.1f}, Std: {5:.1f}".format(rankings[team]["rank"],
                                                                                                                     rankings[team]["delta rank"],
                                                                                                                     team,
                                                                                                                     rankings[team]["team score"],
                                                                                                                     rankings[team]["strength"],
                                                                                                                     rankings[team]["standard deviation"])
        print(team_rankings_string)

    # Create the predictions file with absolute path
    absolute_path = utils.get_abs_path(__file__)
    filename = f"{absolute_path}/rankings/{year}/team_rankings-{year}-{week:02}.csv"
    utils.write_string(team_rankings_file_string, filename)

    return rankings