Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add update mechanism to rankings data #66

Merged
merged 10 commits into from
Aug 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Authors@R:
email = "[email protected]",
comment = c(ORCID = "0000-0001-8388-5155"))
Description: Uses bootstrap resampling to run fantasy football season
simulations supported by historical rankings and 'nflfastR' data,
simulations supported by historical 'FantasyPros' rankings and 'nflverse' data,
calculating optimal lineups, and returning aggregated results.
License: MIT + file LICENSE
URL: https://ffsimulator.ffverse.com,
Expand Down
18 changes: 14 additions & 4 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ S3method(plot,ff_simulation_week)
S3method(print,ff_simulation)
S3method(print,ff_simulation_week)
S3method(print,ff_war)
export("%>%")
export(.ffs_cache)
export(.ffs_cache_dir)
export(.ffs_cache_example)
export(.ffs_read_data)
export(autoplot.ff_simulation)
export(autoplot.ff_simulation_week)
export(espn_connect)
Expand Down Expand Up @@ -45,19 +46,28 @@ export(ffs_summarize_season)
export(ffs_summarize_simulation)
export(ffs_summarize_week)
export(fleaflicker_connect)
export(fp_injury_table)
export(fp_rankings_history)
export(fp_rankings_history_week)
export(mfl_connect)
export(sleeper_connect)
importFrom(data.table,":=")
importFrom(data.table,.BY)
importFrom(data.table,.EACHI)
importFrom(data.table,.GRP)
importFrom(data.table,.I)
importFrom(data.table,.N)
importFrom(data.table,.NGRP)
importFrom(data.table,.SD)
importFrom(data.table,`:=`)
importFrom(data.table,data.table)
importFrom(ffscrapr,espn_connect)
importFrom(ffscrapr,ff_connect)
importFrom(ffscrapr,ff_scoringhistory)
importFrom(ffscrapr,ff_starter_positions)
importFrom(ffscrapr,fleaflicker_connect)
importFrom(ffscrapr,mfl_connect)
importFrom(ffscrapr,sleeper_connect)
importFrom(magrittr,"%>%")
importFrom(magrittr,`%>%`)
importFrom(rlang,.data)
importFrom(rlang,.env)
importFrom(rlang,`%||%`)
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
- Update available fantasypros rankings to include 2022
- Require ggplot2 3.4.0 for plotting features
- Draws from a slightly broader sample of players for season outcomes
- Remove packaged rankings built-in in favour of reading files from user cache,
falling back to system.file() internal data. Adds script for updating.


---
Expand Down
87 changes: 45 additions & 42 deletions R/00-ff_simulate.R
Original file line number Diff line number Diff line change
Expand Up @@ -38,53 +38,51 @@ ff_simulate <- function(conn,
base_seasons = 2012:2022,
actual_schedule = FALSE,
replacement_level = TRUE,
pos_filter = c("QB","RB","WR","TE","K"),
pos_filter = c("QB", "RB", "WR", "TE", "K"),
verbose = NULL,
return = c("default", "all")
) {

#### TEST ####

# conn <- mfl_connect(2021,54040)
# conn <- sleeper_connect(2021,"734442977157603328")
# verbose <- NULL
# base_seasons = 2012:2020
# conn <- sleeper_connect(2023,"995578537426030592")
# base_seasons = 2012:2022
# gp_model = "simple"
# pos_filter = c("QB","RB","WR","TE","K")
# n_seasons = 100
# n_weeks = 14
# best_ball = FALSE
# seed = NULL
# base_seasons = 2012:2020
# actual_schedule = TRUE
# pos_filter = c("QB","RB","WR","TE","K")
# actual_schedule = FALSE
# replacement_level = TRUE
# verbose = TRUE
# return = "all"

#### Assertions ####

if (!class(conn) %in% c("mfl_conn", "sleeper_conn", "flea_conn", "espn_conn")) {
stop("conn should be a connection object created by `ff_connect()` and friends!",
call. = FALSE
cli::cli_abort(
"conn should be a connection object created by `ff_connect()` and friends!"
)
}

gp_model <- rlang::arg_match0(gp_model, c("simple","none"))
return <- rlang::arg_match0(return, c("default","all"))
checkmate::assert_subset(pos_filter, c("QB","RB","WR","TE","K"))
gp_model <- rlang::arg_match0(gp_model, c("simple", "none"))
return <- rlang::arg_match0(return, c("default", "all"))
pos_filter <- rlang::arg_match(pos_filter, c("QB", "RB", "WR", "TE", "K"), multiple = TRUE)
checkmate::assert_numeric(base_seasons, lower = 2012, upper = 2022)
checkmate::assert_int(n_seasons, lower = 1)
checkmate::assert_int(n_weeks, lower = 1)
checkmate::assert_int(seed, null.ok = TRUE)
if (!is.null(seed)) set.seed(seed)
checkmate::assert_flag(best_ball)
if(!is.null(verbose)) set_verbose(verbose)
if (!is.null(verbose)) set_verbose(verbose)
checkmate::assert_flag(actual_schedule)
checkmate::assert_flag(replacement_level)

#### Import Data ####

vcli_rule("Starting simulation {Sys.time()}")
vcli_rule("Starting simulation {format(Sys.time())}")

vcli_start(msg = "Importing data")

Expand All @@ -101,34 +99,37 @@ ff_simulate <- function(conn,

weeks <- seq_len(n_weeks)

if(actual_schedule) {
if (actual_schedule) {
schedule <- ffs_schedule(conn)

weeks <- unique(schedule$week)

if(length(weeks)==0) {
if (length(weeks) == 0) {

cli::cli_alert_danger("No unplayed weeks to simulate!")
out <- structure(list(schedule = ffscrapr::ff_schedule(conn),
league_info = league_info,
simulation_params = list(
n_seasons = n_seasons,
n_weeks = n_weeks,
scrape_date = latest_rankings$scrape_date[[1]],
best_ball = best_ball,
seed = seed,
gp_model = gp_model,
actual_schedule = actual_schedule,
base_seasons = list(base_seasons)
)),
class = "ff_simulation")
out <- structure(
list(
schedule = ffscrapr::ff_schedule(conn),
league_info = league_info,
simulation_params = list(
n_seasons = n_seasons,
n_weeks = n_weeks,
scrape_date = latest_rankings$scrape_date[[1]],
best_ball = best_ball,
seed = seed,
gp_model = gp_model,
actual_schedule = actual_schedule,
base_seasons = list(base_seasons)
)
),
class = "ff_simulation")

return(out)

}

cli::cli_alert_info("Simulating only unplayed weeks: {
min(weeks,na.rm = TRUE)}-{
min(weeks, na.rm = TRUE)}-{
max(weeks, na.rm = TRUE)}")
}

Expand All @@ -138,14 +139,16 @@ ff_simulate <- function(conn,

vcli_start(msg = "Generating Projections")

if(!replacement_level) rosters_rl <- rosters
if (!replacement_level) rosters_rl <- rosters

if(replacement_level){
rosters_rl <- ffs_add_replacement_level(rosters = rosters,
latest_rankings = latest_rankings,
franchises = franchises,
lineup_constraints = lineup_constraints,
pos_filter = pos_filter)
if (replacement_level) {
rosters_rl <- ffs_add_replacement_level(
rosters = rosters,
latest_rankings = latest_rankings,
franchises = franchises,
lineup_constraints = lineup_constraints,
pos_filter = pos_filter
)
}

adp_outcomes <- ffs_adp_outcomes(
Expand Down Expand Up @@ -186,12 +189,12 @@ ff_simulate <- function(conn,

vcli_start(msg = "Building Schedules")

if(actual_schedule) {
if (actual_schedule) {
schedules <- ffs_repeat_schedules(n_seasons = n_seasons,
actual_schedule = schedule)
}

if(!actual_schedule){
if (!actual_schedule) {
schedules <- ffs_build_schedules(
n_seasons = n_seasons,
n_weeks = n_weeks,
Expand All @@ -209,7 +212,7 @@ ff_simulate <- function(conn,

vcli_end(msg_done = "Summarising Simulation Data...done! {Sys.time()}")

if(return == "default"){
if (return == "default") {

out <- structure(
list(
Expand All @@ -235,7 +238,7 @@ ff_simulate <- function(conn,
)
}

if(return == "all"){
if (return == "all") {

out <- structure(
list(
Expand Down Expand Up @@ -268,7 +271,7 @@ ff_simulate <- function(conn,
)
}

vcli_rule("Simulation complete! {Sys.time()}")
vcli_rule("Simulation complete! {format(Sys.time())}")

return(out)
}
Expand Down
28 changes: 14 additions & 14 deletions R/00-ff_simulate_week.R
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ ff_simulate_week <- function(conn,
base_seasons = 2012:2022,
actual_schedule = TRUE,
replacement_level = FALSE,
pos_filter = c("QB","RB","WR","TE","K"),
pos_filter = c("QB", "RB", "WR", "TE", "K"),
verbose = NULL,
return = c("default","all")) {
return = c("default", "all")) {

# conn <- mfl_connect(2021,54040)
# verbose <- NULL
Expand All @@ -61,13 +61,13 @@ ff_simulate_week <- function(conn,
}

return <- rlang::arg_match(return)
checkmate::assert_subset(pos_filter, c("QB","RB","WR","TE","K"))
checkmate::assert_subset(pos_filter, c("QB", "RB", "WR", "TE", "K"))
checkmate::assert_numeric(base_seasons, lower = 2012, upper = 2022)
checkmate::assert_int(n, lower = 1)
checkmate::assert_int(seed, null.ok = TRUE)
if (!is.null(seed)) set.seed(seed)
checkmate::assert_flag(best_ball)
if(!is.null(verbose)) set_verbose(verbose)
if (!is.null(verbose)) set_verbose(verbose)
checkmate::assert_flag(actual_schedule)
checkmate::assert_flag(replacement_level)

Expand All @@ -87,11 +87,11 @@ ff_simulate_week <- function(conn,

lineup_constraints <- ffs_starter_positions(conn)

if(actual_schedule) {
if (actual_schedule) {
schedule <- ffs_schedule(conn)
schedule <- schedule[schedule$week == min(schedule$week),] # simulate first unplayed week
schedule <- schedule[schedule$week == min(schedule$week), ] # simulate first unplayed week

if(nrow(schedule)==0) {
if (nrow(schedule) == 0) {
cli::cli_alert_danger("No unplayed weeks to simulate!")
out <- structure(list(schedule = ffscrapr::ff_schedule(conn),
league_info = league_info,
Expand All @@ -114,9 +114,9 @@ ff_simulate_week <- function(conn,

vcli_start(msg = "Generating Projections")

if(!replacement_level) rosters_rl <- rosters
if (!replacement_level) rosters_rl <- rosters

if(replacement_level){
if (replacement_level) {
rosters_rl <- ffs_add_replacement_level(rosters = rosters,
latest_rankings = latest_rankings,
franchises = franchises,
Expand Down Expand Up @@ -163,13 +163,13 @@ ff_simulate_week <- function(conn,

vcli_start(msg = "Building Schedules")

if(actual_schedule) {
if (actual_schedule) {
schedules <- ffs_repeat_schedules(n_seasons = n, actual_schedule = schedule)
schedules$week <- schedules$season
schedules$season <- 1
}

if(!actual_schedule){
if (!actual_schedule) {
schedules <- ffs_build_schedules(
n_seasons = n,
n_weeks = 1,
Expand All @@ -185,13 +185,13 @@ ff_simulate_week <- function(conn,
vcli_start(msg = "Summarising Simulation Data")

summary_week <- ffs_summarise_week(optimal_scores, schedules)
summary_simulation <- ffs_summarise_inseason(summary_week,n)
summary_simulation <- ffs_summarise_inseason(summary_week, n)

vcli_end(msg_done = "Summarising Simulation Data...done! {Sys.time()}")

#### Build and Return ####

if(return == "default"){
if (return == "default") {

out <- structure(
list(
Expand All @@ -214,7 +214,7 @@ ff_simulate_week <- function(conn,
)
}

if(return == "all"){
if (return == "all") {

out <- structure(
list(
Expand Down
Loading
Loading