uberfastman / fantasy-football-metrics-weekly-report

Command line application to create weekly reports (containing stats, metrics, and rankings) for Fantasy Football leagues on the following platforms: Yahoo, ESPN, CBS, Sleeper, Fleaflicker
GNU General Public License v3.0
202 stars 49 forks source link

weekly and average points by position pie charts have incomplete and incorrect data #147

Closed dave7734 closed 1 year ago

dave7734 commented 3 years ago

Description of Issue

for the teams in my fleaflicker league the pie charts have incorrect and missing data. The problem is because we use flex positions. Our positions are QB, RB, Flex(RB, WR, TE), Flex(WR, TE), K. This results in the QB and K points being correctly graphed but the RB gets the points from the RB position and all the players in the first Flex group. The WR and TE are not reported. Thus the RB position gets too many points and the WR and TE none. I believe the problem is that the slot variable should only contain the unique positions for the league. In this case QB, RB, WR, TE, K. They should be compared to the player's primary_position not the eligible_positions for getting, summing and storing the player points. I believe the counts of positions should be against the unique positions and not include the Flex groups. For our league the pie charts should show the points for all the unique player groups.

My solution for my FLEAFLICKER league: note: not tested for other types of leagues as I have no access to them do not apply unless you test and check the results

points_by_position.py

author = "Wren J. R. (uberfastman)" email = "wrenjr@yahoo.com"

import copy

from dao.base import BaseLeague, BaseTeam, BasePlayer from report.logger import get_logger

logger = get_logger(name, propagate=False)

class PointsByPosition(object): def init(self, league: BaseLeague, week_for_report): logger.debug("Initializing points by position.")

    self.week_for_report = week_for_report
    self.roster_slot_counts = league.roster_position_counts
    self.bench_positions = league.bench_positions
    self.flex_types = list(league.get_flex_positions_dict().keys())
    self.flex_types.remove("FLEX_IDP")  # comment/uncomment line to remove/add FLEX_IDP to team points by position

dave7734 def modded, changed eligible to primary position

note: ONLY TESTED FOR FLEAFLICKER

note: ONLY TESTED FOR FLEAFLICKER

note: ONLY TESTED FOR FLEAFLICKER

note: this solution needed for all position types with or witout FLEX

note: this solution needed for all position types

def get_points_for_position(self, players, position): total_points_by_position = 0 for player in players: # type: BasePlayer if position in player.primary_position and player.selected_position not in self.bench_positions: total_points_by_position += float(player.points)

    return total_points_by_position

@staticmethod
def calculate_points_by_position_season_averages(season_average_points_by_position_dict):
    logger.debug("Calculating points by position season averages.")

    for team in list(season_average_points_by_position_dict.keys()):
        points_by_position = season_average_points_by_position_dict.get(team)
        season_average_points_by_position = {}
        for week in points_by_position:
            for position in week:
                position_points = season_average_points_by_position.get(position[0])
                if position_points:
                    season_average_points_by_position[position[0]] = position_points + position[1]
                else:
                    season_average_points_by_position[position[0]] = position[1]
        season_average_points_by_position_list = []
        for position in list(season_average_points_by_position.keys()):
            season_average_points_by_position_list.append(
                [position, season_average_points_by_position.get(position) / len(points_by_position)])
        season_average_points_by_position_list = sorted(season_average_points_by_position_list, key=lambda x: x[0])
        season_average_points_by_position_dict[team] = season_average_points_by_position_list

    return season_average_points_by_position_dict

def execute_points_by_position(self, team_name, roster):
    logger.debug("Calculating points by position for team \"{0}\".".format(team_name))

    player_points_by_position = []
    starting_players = [p for p in roster if p.selected_position not in self.bench_positions]
    for slot in list(self.roster_slot_counts.keys()):
        if slot not in self.bench_positions and slot not in self.flex_types:
            player_points_by_position.append([slot, self.get_points_for_position(starting_players, slot)])
    player_points_by_position = sorted(player_points_by_position, key=lambda x: x[0])
    return player_points_by_position

dave7734 def modded, added check for FLEX position to add a position with a count so it will be counted

note: ONLY TESTED FOR FLEAFLICKER

note: ONLY TESTED FOR FLEAFLICKER

note: ONLY TESTED FOR FLEAFLICKER

note: this solution works for my league and my be INCOMPLETE for yours

note: this solution works for my league and my be INCOMPLETE for yours

note: if you have other FLEX with a position that is only within the FLEX then

add that to this section. example: FLEX_RB_WR and RB is only in the FLEX

def get_weekly_points_by_position(self, teams_results):
    logger.debug("Retrieving weekly points by position.")

    weekly_points_by_position_data = []
    for team_result in teams_results.values():  # type: BaseTeam
        team_roster_slot_counts = copy.deepcopy(self.roster_slot_counts)
        for slot in list(team_roster_slot_counts.keys()):
            if slot == "FLEX_TE_WR" and self.roster_slot_counts.get(slot) != 0:
                if "WR" not in team_roster_slot_counts:
                    self.roster_slot_counts['WR'] = 1
                if "TE" not in team_roster_slot_counts:
                    self.roster_slot_counts['TE'] = 1
            if self.roster_slot_counts.get(slot) == 0:
                del self.roster_slot_counts[slot]
        player_points_by_position = self.execute_points_by_position(team_result.name, team_result.roster)
        weekly_points_by_position_data.append([team_result.team_id, player_points_by_position])

    return weekly_points_by_position_data

Additional Information as Applicable

Fantasy Football Platform

Fleaflicker

League ID

9959

Operating System

Windows

Other

Any other setup/environment/configuration information you might deem potentially relevant.

uberfastman commented 1 year ago

@dave7734 thank you so much for working out an initial fix here. I used your input to fix this issue for all platforms in a dynamic fashion (so no required updates for each flex type) in #188.