Skip to content

Commit

Permalink
Add update mechanism to rankings data (#66)
Browse files Browse the repository at this point in the history
* rm old dev files

* clean up existing util file

* relocate inst/cache files

* .ffs_cache -> .ffs_cache_example

* move pkgdata to inst and convert to functions

* relocate stuff again

* styler

* readme updates

* add update rankings file

* pkgdown and redoc
  • Loading branch information
tanho63 authored Aug 27, 2023
1 parent 179f357 commit 36be8f8
Show file tree
Hide file tree
Showing 104 changed files with 923 additions and 472 deletions.
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

0 comments on commit 36be8f8

Please sign in to comment.