File size: 6,231 Bytes
dd64f21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import os
import numpy as np
import pandas as pd
import streamlit as st

from config import DEFAULT_ICON, LEAGUE_NAME, LEAGUE_NUMBER_TEAMS
from shared_page import common_page_config
from streamlit_filter import filter_dataframe


KEEPER_DATA_URL = "../../tests/mocks/2023_keepers.csv"
HEADSHOT_DATA_URL = "../../tests/mocks/2023_player_headshots.csv"


def load_player_ids() -> pd.DataFrame:
    df = pd.read_csv(r"https://raw.githubusercontent.com/dynastyprocess/data/master/files/db_playerids.csv")
    df["merge_id"] = df["yahoo_id"].combine_first(df["stats_id"])
    return df


def load_adp() -> pd.DataFrame:
    df = pd.read_csv(r"https://raw.githubusercontent.com/dynastyprocess/data/master/files/db_fpecr_latest.csv")
    df = df.loc[
        df.fp_page == "/nfl/rankings/ppr-superflex-cheatsheets.php",
        [
            "yahoo_id",
            "ecr",
            "sd",
        ],
    ]
    return df


def convert_ecr_to_round_val(ecr_float: float, round_offset: float = 1.0, pick_offset: float = -1.0) -> float:
    # As a float, store pick 1 of round 1 as 1.0
    return round_offset + (ecr_float + pick_offset) / LEAGUE_NUMBER_TEAMS


def add_opinionated_keeper_value(df: pd.DataFrame):
    # Manual Hack for overranking of backup QBs
    df.loc[
        df["name"].isin(
            [
                "Teddy Bridgewater",
                "Davis Mills",
                "Andy Dalton",
                "Tyler Huntley",
                "Mike White",
                "Gardner Minshew",
                "Colt McCoy",
                "Sam Darnold",
                "Carson Wentz",
                "Trey Lance",
                "Taylor Heinicke",
            ]
        ),
        ["ecr"],
    ] = np.nan

    df["ecr"] = df["ecr"].apply(convert_ecr_to_round_val)
    # Convert sd without offset to show as pure pick diff
    df["sd"] = df["sd"].apply(lambda x: convert_ecr_to_round_val(x, 0, 0))
    # assumes midround keeper
    # fill -99 for players that are not ranked in ecr
    df["value_keeper"] = (df["keeper_cost"] + 0.5 - df["ecr"]).fillna(-99)


@st.cache_data(ttl=60 * 60 * 24)
def load_data():
    data = pd.read_csv(os.path.join(os.path.dirname(__file__), KEEPER_DATA_URL), index_col=0)
    # Hack to get position, replace with better position from yahoo api in future
    data["position"] = data["eligible_positions"].apply(lambda x: eval(x)[0])
    data.columns = data.columns.str.lower()
    teams_list = sorted(list(data["team_name"].unique()))

    # Merge player ids
    df_player_ids = load_player_ids()
    data = data.merge(df_player_ids, how="left", left_on="player_id", right_on="merge_id", suffixes=("", "_ids"))

    # Merge ADP
    df_adp = load_adp()
    data = data.merge(df_adp, how="left", left_on="player_id", right_on="yahoo_id", suffixes=("", "_adp"))
    add_opinionated_keeper_value(data)
    return data, teams_list


def filtered_keeper_dataframe(data: pd.DataFrame, teams_list: list[str]):
    teams_selected = st.multiselect("Team:", teams_list, placeholder="Select a user team to filter")
    teams_filter = data["team_name"].isin(teams_selected) if teams_selected else data["team_name"].isin(teams_list)

    eligible_options = [True, False]
    is_eligible_selected = st.multiselect(
        "Keeper Eligible:", eligible_options, placeholder="Select True to filter eligible only"
    )
    eligible_filter = (
        data["eligible"].isin(is_eligible_selected) if is_eligible_selected else data["eligible"].isin(eligible_options)
    )
    is_advanced = st.checkbox("Show Advanced View")

    id_cols = [
        "team_name",
        "headshot_url",
        "name",
    ]

    id_cols_advanced = [
        "team",
        "position",
    ]

    cost_cols = [
        "keeper_cost",
        "eligible",
    ]

    cost_cols_advanced = [
        "years_eligible",
    ]

    adp_cols: list[str] = []

    adp_cols_advanced = [
        "ecr",
        "value_keeper",
    ]

    if is_advanced:
        show_columns = id_cols + id_cols_advanced + cost_cols + cost_cols_advanced + adp_cols + adp_cols_advanced
    else:
        show_columns = id_cols + cost_cols + adp_cols

    data_with_filters_applied = data.loc[teams_filter & eligible_filter, show_columns]

    filtered_data = filter_dataframe(data_with_filters_applied)
    st.dataframe(
        filtered_data,
        hide_index=True,
        height=35 * (len(filtered_data) + 1) + 12,
        use_container_width=True,
        column_config={
            "team_name": st.column_config.TextColumn(label="League Team", help="Name of fantasy League team."),
            "headshot_url": st.column_config.ImageColumn(label="", help="Player image"),
            "name": st.column_config.TextColumn(label="Name", help="Player's name"),
            "team": st.column_config.TextColumn(label="NFL Team"),
            "position": st.column_config.TextColumn(label="Position", help="Player's position"),
            "keeper_cost": st.column_config.NumberColumn(
                label="Keeper Cost", help="Draft Round Cost to keep player.  See Rules for details."
            ),
            "eligible": st.column_config.CheckboxColumn(label="Eligible", help="Is player eligible to be keeper?"),
            "years_eligible": st.column_config.NumberColumn(
                label="Years Eligible",
                help="Number of further consecutive seasons player can be kept (subject to maximum of 2)",
            ),
            "ecr": st.column_config.NumberColumn(
                label="ECR",
                help="Player's average draft round.pick Expert Consensus Rank (ECR) for PPR - Superflex League",
            ),
            "value_keeper": st.column_config.NumberColumn(
                label="Value Keeper",
                help="Approx. number of draft rounds of keeper value vs ECR PPR - Superflex League",
            ),
        },
    )


def get_keeper_app():
    keeper_title = f"{LEAGUE_NAME} Keeper Options"
    st.set_page_config(page_title=keeper_title, page_icon=DEFAULT_ICON, layout="wide")
    common_page_config()
    st.title(keeper_title)
    data, teams_list = load_data()

    with st.container():
        filtered_keeper_dataframe(data, teams_list)


if __name__ == "__main__":
    get_keeper_app()