diff --git a/DESCRIPTION b/DESCRIPTION index 3ee3a38..69a42f7 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -8,7 +8,7 @@ Authors@R: email = "tan@tanho.ca", 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, diff --git a/NAMESPACE b/NAMESPACE index 2d400e2..7b1c41e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -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) @@ -45,11 +46,20 @@ 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) @@ -57,7 +67,7 @@ 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,`%||%`) diff --git a/NEWS.md b/NEWS.md index a4baab4..721d0f8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -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. --- diff --git a/R/00-ff_simulate.R b/R/00-ff_simulate.R index 846a677..f028d30 100644 --- a/R/00-ff_simulate.R +++ b/R/00-ff_simulate.R @@ -38,7 +38,7 @@ 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") ) { @@ -46,45 +46,43 @@ ff_simulate <- function(conn, #### 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") @@ -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)}") } @@ -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( @@ -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, @@ -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( @@ -235,7 +238,7 @@ ff_simulate <- function(conn, ) } - if(return == "all"){ + if (return == "all") { out <- structure( list( @@ -268,7 +271,7 @@ ff_simulate <- function(conn, ) } - vcli_rule("Simulation complete! {Sys.time()}") + vcli_rule("Simulation complete! {format(Sys.time())}") return(out) } diff --git a/R/00-ff_simulate_week.R b/R/00-ff_simulate_week.R index f7c60e8..4e3856b 100644 --- a/R/00-ff_simulate_week.R +++ b/R/00-ff_simulate_week.R @@ -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 @@ -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) @@ -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, @@ -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, @@ -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, @@ -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( @@ -214,7 +214,7 @@ ff_simulate_week <- function(conn, ) } - if(return == "all"){ + if (return == "all") { out <- structure( list( diff --git a/R/00-ff_wins_added.R b/R/00-ff_wins_added.R index c6b90bf..62e8163 100644 --- a/R/00-ff_wins_added.R +++ b/R/00-ff_wins_added.R @@ -19,14 +19,14 @@ #' \donttest{ #' try({ # try block to prevent CRAN-related issues #' # n_seasons set so that the example runs more quickly -#' ff_wins_added(mfl_connect(2021,54040), n_seasons = 5) +#' ff_wins_added(mfl_connect(2021, 54040), n_seasons = 5) #' }) #' } #' #' @return a dataframe summarising the net effect of each player on their team's wins #' #' @export -ff_wins_added <- function(conn, ...){ +ff_wins_added <- function(conn, ...) { #### TEST STUFF #### # conn <- mfl_connect(2021,54040) @@ -46,14 +46,14 @@ ff_wins_added <- function(conn, ...){ rosters <- data.table::as.data.table(base_simulation$rosters)[ pos %in% base_simulation$simulation_params$pos_filter[[1]], - c("player_id","player_name","league_id","franchise_name","franchise_id","pos") + c("player_id", "player_name", "league_id", "franchise_name", "franchise_id", "pos") ] vcli_rule("Start WAR calcs {Sys.time()}") - progress_flag <- rlang::is_installed("progressr") && getOption("ffsimulator.verbose", default = TRUE) + progress_flag <- rlang::is_installed("progressr") && getOption("ffsimulator.verbose", default = TRUE) - if(getOption("ffsimulator.verbose", default = TRUE) & !progress_flag) { + if (getOption("ffsimulator.verbose", default = TRUE) & !progress_flag) { cli::cli_warn("{.pkg progressr} package not found - please install for detailed progress updates!") } @@ -62,13 +62,13 @@ ff_wins_added <- function(conn, ...){ war <- with_progress({ - if(progress_flag) p <- progressr::progressor(nrow(rosters)) + if (progress_flag) p <- progressr::progressor(nrow(rosters)) rosters[ , - .ffs_win_add(.SD, base_simulation,p), - by = c("league_id","franchise_id","franchise_name","player_id","player_name","pos"), - .SDcols = c("player_id","player_name","franchise_id") + .ffs_win_add(.SD, base_simulation, p), + by = c("league_id", "franchise_id", "franchise_name", "player_id", "player_name", "pos"), + .SDcols = c("player_id", "player_name", "franchise_id") ][ order(-allplay_winpct) ] @@ -78,13 +78,13 @@ ff_wins_added <- function(conn, ...){ out <- structure( .Data = c(list(war = war), base_simulation), - class = c("ff_war","ff_simulation") + class = c("ff_war", "ff_simulation") ) return(out) } -.ffs_win_add <- function(rosters, base_simulation, p = NULL){ +.ffs_win_add <- function(rosters, base_simulation, p = NULL) { p_id <- rosters$player_id p_name <- rosters$player_name f_id <- rosters$franchise_id @@ -131,7 +131,7 @@ ff_wins_added <- function(conn, ...){ potential_points = o_sim$potential_points - potential_points )] - if(!is.null(p)) p() + if (!is.null(p)) p() return(war_simulation) } diff --git a/R/01-outcomes.R b/R/01-outcomes.R index 26a6704..f794bf1 100644 --- a/R/01-outcomes.R +++ b/R/01-outcomes.R @@ -1,6 +1,6 @@ #' Connects ff_scoringhistory to past ADP rankings #' -#' The backbone of the ffsimulator resampling process is coming up with a population of weekly outcomes for every preseason positional rank. This function creates that dataframe by connecting historical FantasyPros.com rankings to nflfastR-based scoring data, as created by `ffscrapr::ff_scoringhistory()`. +#' The backbone of the ffsimulator resampling process is coming up with a population of weekly outcomes for every preseason positional rank. This function creates that dataframe by connecting historical FantasyPros.com rankings to nflverse-based scoring data, as created by `ffscrapr::ff_scoringhistory()`. #' #' #' @param scoring_history a scoring history table as created by `ffscrapr::ff_scoringhistory()` @@ -12,7 +12,7 @@ #' @examples #' \donttest{ #' # cached data -#' scoring_history <- .ffs_cache("mfl_scoring_history.rds") +#' scoring_history <- .ffs_cache_example("mfl_scoring_history.rds") #' #' ffs_adp_outcomes(scoring_history, gp_model = "simple") #' ffs_adp_outcomes(scoring_history, gp_model = "none") @@ -30,7 +30,7 @@ ffs_adp_outcomes <- function(scoring_history, checkmate::assert_choice(gp_model, choices = c("simple", "none")) checkmate::assert_character(pos_filter) checkmate::assert_data_frame(scoring_history) - assert_columns(scoring_history, c("gsis_id", "team", "season", "points")) + assert_df(scoring_history, c("gsis_id", "team", "season", "points")) gsis_id <- NULL fantasypros_id <- NULL @@ -47,10 +47,10 @@ ffs_adp_outcomes <- function(scoring_history, !is.na(gsis_id) & week <= 17 , c("gsis_id", "team", "season", "points") ] - fp_rh <- data.table::as.data.table(ffsimulator::fp_rankings_history)[,-"page_pos"] + fp_rh <- data.table::as.data.table(fp_rankings_history())[, -"page_pos"] dp_id <- data.table::as.data.table(ffscrapr::dp_playerids())[ !is.na(gsis_id) & !is.na(fantasypros_id) - ,c("fantasypros_id","gsis_id") + , c("fantasypros_id", "gsis_id") ] ao <- fp_rh[ @@ -61,17 +61,17 @@ ffs_adp_outcomes <- function(scoring_history, !is.na(gsis_id) & pos %in% pos_filter ][ sh - , on = c("season","gsis_id") + , on = c("season", "gsis_id") , nomatch = 0 ][ - ,list(week_outcomes = list(points), games_played = .N) - , by = c("season","pos","rank","fantasypros_id","player_name") + , list(week_outcomes = list(points), games_played = .N) + , by = c("season", "pos", "rank", "fantasypros_id", "player_name") ][ , list( season = rep(season, each = 5), pos = rep(pos, each = 5), fantasypros_id = rep(fantasypros_id, each = 5), - player_name = rep(player_name,each = 5), + player_name = rep(player_name, each = 5), games_played = rep(games_played, each = 5), week_outcomes = rep(week_outcomes, each = 5), rank = unlist(lapply(rank, .ff_rank_expand)) @@ -81,14 +81,14 @@ ffs_adp_outcomes <- function(scoring_history, ao <- .ff_apply_gp_model(ao, gp_model) ao <- ao[ - ,list( + , list( week_outcomes = list(c(unlist(week_outcomes))), player_name = list(player_name), fantasypros_id = list(fantasypros_id) ) - , by = c("pos","rank","prob_gp") + , by = c("pos", "rank", "prob_gp") ][ - order(pos,rank) + order(pos, rank) ][ !is.na(fantasypros_id) ] @@ -106,7 +106,7 @@ ffs_adp_outcomes <- function(scoring_history, } if (model_type == "simple") { - adp_outcomes <- adp_outcomes[data.table::as.data.table(ffsimulator::fp_injury_table),on = c("pos","rank")] + adp_outcomes <- adp_outcomes[data.table::as.data.table(fp_injury_table()), on = c("pos", "rank")] } adp_outcomes @@ -114,7 +114,7 @@ ffs_adp_outcomes <- function(scoring_history, #' Expand one rank into a vector of five ranks to broaden population of possible outcomes #' @keywords internal -.ff_rank_expand <- function(.x){ +.ff_rank_expand <- function(.x) { .x <- seq.int(from = .x - 2, to = .x + 2, by = 1) ifelse(.x <= 0, 1, .x) } diff --git a/R/01-outcomes_week.R b/R/01-outcomes_week.R index 59db194..406629b 100644 --- a/R/01-outcomes_week.R +++ b/R/01-outcomes_week.R @@ -11,8 +11,8 @@ #' @examples #' \donttest{ #' # cached data -#' scoring_history <- .ffs_cache("mfl_scoring_history.rds") -#' ffs_adp_outcomes_week(scoring_history, pos_filter = c("QB","RB","WR","TE")) +#' scoring_history <- .ffs_cache_example("mfl_scoring_history.rds") +#' ffs_adp_outcomes_week(scoring_history, pos_filter = c("QB", "RB", "WR", "TE")) #' } #' #' @seealso `fp_rankings_history_week` for the included historical rankings @@ -21,9 +21,8 @@ ffs_adp_outcomes_week <- function(scoring_history, pos_filter = c("QB", "RB", "WR", "TE")) { # ASSERTIONS # - checkmate::assert_character(pos_filter) - checkmate::assert_data_frame(scoring_history) - assert_columns(scoring_history, c("gsis_id", "week", "season", "points")) + assert_character(pos_filter) + assert_df(scoring_history, c("gsis_id", "week", "season", "points")) gsis_id <- NULL fantasypros_id <- NULL @@ -38,9 +37,9 @@ ffs_adp_outcomes_week <- function(scoring_history, season <- NULL games_played <- NULL - sh <- data.table::as.data.table(scoring_history)[!is.na(gsis_id) & week <= 16,c("gsis_id","week", "season", "points")] - fp_rh <- data.table::as.data.table(ffsimulator::fp_rankings_history_week)[,-"page_pos"] - dp_id <- data.table::as.data.table(ffscrapr::dp_playerids())[!is.na(gsis_id) & !is.na(fantasypros_id),c("fantasypros_id","gsis_id")] + sh <- data.table::as.data.table(scoring_history)[!is.na(gsis_id) & week <= 16, c("gsis_id", "week", "season", "points")] + fp_rh <- data.table::as.data.table(fp_rankings_history_week())[, -"page_pos"] + dp_id <- data.table::as.data.table(ffscrapr::dp_playerids())[!is.na(gsis_id) & !is.na(fantasypros_id), c("fantasypros_id", "gsis_id")] ao <- fp_rh[ dp_id @@ -50,17 +49,17 @@ ffs_adp_outcomes_week <- function(scoring_history, !is.na(gsis_id) & pos %in% pos_filter ][ sh - , on = c("season","week","gsis_id") + , on = c("season", "week", "gsis_id") , nomatch = 0 ][ , list(week_outcomes = list(points), games_played = .N) - , by = c("season","pos","rank","fantasypros_id","player_name") + , by = c("season", "pos", "rank", "fantasypros_id", "player_name") ][ , list( season = rep(season, each = 5), pos = rep(pos, each = 5), fantasypros_id = rep(fantasypros_id, each = 5), - player_name = rep(player_name,each = 5), + player_name = rep(player_name, each = 5), games_played = rep(games_played, each = 5), week_outcomes = rep(week_outcomes, each = 5), rank = unlist(lapply(rank, .ff_rank_expand)) @@ -70,20 +69,20 @@ ffs_adp_outcomes_week <- function(scoring_history, player_name = list(player_name), fantasypros_id = list(fantasypros_id) ), - by = c("pos","rank") + by = c("pos", "rank") ][ - , len := sapply(week_outcomes,length) + , len := sapply(week_outcomes, length) ][ - , len := max(len)-len + , len := max(len) - len ][ - ,`:=`(week_outcomes = mapply(.ff_rep_na, week_outcomes, len, SIMPLIFY = FALSE), len = NULL) + , `:=`(week_outcomes = mapply(.ff_rep_na, week_outcomes, len, SIMPLIFY = FALSE), len = NULL) ][ - order(pos,rank) + order(pos, rank) ] return(ao) } -.ff_rep_na <- function(week_outcomes,len){ +.ff_rep_na <- function(week_outcomes, len) { c(unlist(week_outcomes), rep(NA, times = len)) } diff --git a/R/02-rankings.R b/R/02-rankings.R index 6f4c674..b274c5e 100644 --- a/R/02-rankings.R +++ b/R/02-rankings.R @@ -19,15 +19,15 @@ #' @return a dataframe with a copy of the latest FP rankings from DynastyProcess's data repository #' #' @export -ffs_latest_rankings <- function(type = c("draft","week")) { +ffs_latest_rankings <- function(type = c("draft", "week")) { - type <- rlang::arg_match0(type, c("draft","week")) + type <- rlang::arg_match0(type, c("draft", "week")) - if(type == "draft"){ + if (type == "draft") { fp_latest <- nflreadr::load_ff_rankings() fp_cleaned <- fp_latest[ - fp_latest$ecr_type == "rp" & mapply(grepl,x = fp_latest$page_type,pattern = paste0(tolower(fp_latest$pos), "$")), + fp_latest$ecr_type == "rp" & mapply(grepl, x = fp_latest$page_type, pattern = paste0(tolower(fp_latest$pos), "$")), c("player", "fantasypros_id" = "id", "pos", @@ -42,15 +42,15 @@ ffs_latest_rankings <- function(type = c("draft","week")) { names(fp_cleaned)[4] <- "team" names(fp_cleaned)[8] <- "sportradar_id" - if(all(is.na(fp_cleaned$bye))) fp_cleaned$bye <- 0 + if (all(is.na(fp_cleaned$bye))) fp_cleaned$bye <- 0 } - if(type == "week"){ + if (type == "week") { fp_latest <- nflreadr::rds_from_url("https://github.com/dynastyprocess/data/raw/master/files/fp_latest_weekly.rds") - fp_cleaned <- fp_latest[,c("player_name", + fp_cleaned <- fp_latest[, c("player_name", "fantasypros_id", "pos", "team", diff --git a/R/03-rosters.R b/R/03-rosters.R index 01e073f..6c46bcc 100644 --- a/R/03-rosters.R +++ b/R/03-rosters.R @@ -11,7 +11,7 @@ #' @examples #' \donttest{ #' # cached examples -#' conn <- .ffs_cache("mfl_conn.rds") +#' conn <- .ffs_cache_example("mfl_conn.rds") #' #' try({ # prevents CRAN connectivity issues, not actually required in normal usage #' ffs_rosters(conn) @@ -33,7 +33,7 @@ ffs_rosters.mfl_conn <- function(conn) { r$player_id <- as.character(r$player_id) r <- merge(r, - ffscrapr::dp_playerids()[,c("mfl_id","fantasypros_id")], + ffscrapr::dp_playerids()[, c("mfl_id", "fantasypros_id")], by.x = "player_id", by.y = "mfl_id", all.x = TRUE) @@ -51,7 +51,7 @@ ffs_rosters.sleeper_conn <- function(conn) { r$player_id <- as.character(r$player_id) r <- merge(r, - ffscrapr::dp_playerids()[,c("sleeper_id","fantasypros_id")], + ffscrapr::dp_playerids()[, c("sleeper_id", "fantasypros_id")], by.x = "player_id", by.y = "sleeper_id", all.x = TRUE) @@ -69,7 +69,7 @@ ffs_rosters.flea_conn <- function(conn) { r$player_id <- as.character(r$player_id) r <- merge(r, - ffscrapr::dp_playerids()[,c("sportradar_id","fantasypros_id")], + ffscrapr::dp_playerids()[, c("sportradar_id", "fantasypros_id")], by.x = "sportradar_id", by.y = "sportradar_id", all.x = TRUE) @@ -87,7 +87,7 @@ ffs_rosters.espn_conn <- function(conn) { r$player_id <- as.character(r$player_id) r <- merge(r, - ffscrapr::dp_playerids()[,c("espn_id","fantasypros_id")], + ffscrapr::dp_playerids()[, c("espn_id", "fantasypros_id")], by.x = "player_id", by.y = "espn_id", all.x = TRUE) @@ -119,7 +119,7 @@ ffs_rosters.default <- function(conn) { #' @examples #' \donttest{ #' # cached examples -#' conn <- .ffs_cache("mfl_conn.rds") +#' conn <- .ffs_cache_example("mfl_conn.rds") #' #' try({ # prevents CRAN connectivity issues, not actually required in normal usage #' ffs_franchises(conn) @@ -129,11 +129,10 @@ ffs_rosters.default <- function(conn) { #' @seealso vignette("Custom Simulations") for more detailed example usage #' #' @export -ffs_franchises <- function(conn){ +ffs_franchises <- function(conn) { f <- ffscrapr::ff_franchises(conn) f$league_id <- as.character(conn$league_id) f$franchise_id <- as.character(f$franchise_id) return(f) } - diff --git a/R/03-rosters_replacementlevel.R b/R/03-rosters_replacementlevel.R index 71ea9d7..7739545 100644 --- a/R/03-rosters_replacementlevel.R +++ b/R/03-rosters_replacementlevel.R @@ -1,5 +1,9 @@ #' Add replacement level players to each roster #' +#' Adds the same N free-agent starters to each roster to represent being able to +#' churn the waiver wire for starters, where N is the maximum number of players +#' that could start in a given position +#' #' @param rosters a dataframe of rosters as created by `ffs_rosters()` #' @param franchises a dataframe of franchises as created by `ffs_franchises()` #' @param latest_rankings a dataframe of latest rankings as created by `ff_latest_rankings()` @@ -12,16 +16,13 @@ ffs_add_replacement_level <- function(rosters, latest_rankings, franchises, lineup_constraints, - pos_filter = c("QB","RB","WR","TE") - ){ + pos_filter = c("QB", "RB", "WR", "TE") + ) { - checkmate::assert_data_frame(rosters) - checkmate::assert_data_frame(latest_rankings) - checkmate::assert_data_frame(lineup_constraints) - checkmate::assert_data_frame(franchises) - assert_columns(rosters, c("pos","fantasypros_id")) - assert_columns(latest_rankings, c("fantasypros_id")) - assert_columns(lineup_constraints, c("pos","min","max")) + assert_df(franchises, c("franchise_id", "franchise_name", "league_id")) + assert_df(rosters, c("pos", "fantasypros_id", "franchise_id", "franchise_name")) + assert_df(latest_rankings, c("fantasypros_id")) + assert_df(lineup_constraints, c("pos", "min", "max")) pos <- NULL franchise_id <- NULL @@ -33,25 +34,25 @@ ffs_add_replacement_level <- function(rosters, r <- data.table::as.data.table(rosters) f <- data.table::as.data.table(franchises)[ - ,c("franchise_id","franchise_name","league_id") - ][,`:=`(joinkey = 1)] + , c("franchise_id", "franchise_name", "league_id") + ][, `:=`(joinkey = 1)] lr <- data.table::as.data.table(latest_rankings)[pos %in% pos_filter] lc <- data.table::as.data.table(lineup_constraints)[ pos %in% pos_filter, - c("pos","min","max")] + c("pos", "min", "max")] fa <- r[ - ,c("fantasypros_id","franchise_id") + , c("fantasypros_id", "franchise_id") ][lr, on = c("fantasypros_id") ][is.na(franchise_id) - ][order(pos,ecr) - ][,pos_rank := seq_len(.N), by = c("pos") + ][order(pos, ecr) + ][, pos_rank := seq_len(.N), by = c("pos") ][lc, on = "pos" ][pos_rank <= max - ][,list( + ][, list( player_id = paste(pos, pos_rank, sep = "_"), - player_name = paste("Replacement",pos, "-", pos_rank, player), + player_name = paste("Replacement", pos, "-", pos_rank, player), pos, team = NA, age = NA, @@ -59,7 +60,7 @@ ffs_add_replacement_level <- function(rosters, joinkey = 1 )] - fa <- merge(f, fa, by = "joinkey", allow.cartesian = TRUE)[,-"joinkey"] + fa <- merge(f, fa, by = "joinkey", allow.cartesian = TRUE)[, -"joinkey"] out <- data.table::rbindlist(list(r, fa), use.names = TRUE, fill = TRUE) diff --git a/R/04-projections.R b/R/04-projections.R index bc0c129..98957b9 100644 --- a/R/04-projections.R +++ b/R/04-projections.R @@ -10,8 +10,8 @@ #' #' @examples \donttest{ #' # cached examples -#' adp_outcomes <- .ffs_cache("adp_outcomes.rds") -#' latest_rankings <- .ffs_cache("latest_rankings.rds") +#' adp_outcomes <- .ffs_cache_example("adp_outcomes.rds") +#' latest_rankings <- .ffs_cache_example("latest_rankings.rds") #' #' ffs_generate_projections(adp_outcomes, latest_rankings) #' } @@ -28,21 +28,21 @@ ffs_generate_projections <- function(adp_outcomes, ) { checkmate::assert_number(n_seasons, lower = 1) - checkmate::assert_numeric(weeks, lower = 1, min.len=1) + checkmate::assert_numeric(weeks, lower = 1, min.len = 1) weeks <- unique(weeks) n_weeks <- length(weeks) checkmate::assert_data_frame(adp_outcomes) - assert_columns(adp_outcomes, c("pos", "rank", "prob_gp", "week_outcomes")) + assert_df(adp_outcomes, c("pos", "rank", "prob_gp", "week_outcomes")) adp_outcomes <- data.table::as.data.table(adp_outcomes)[, c("pos", "rank", "prob_gp", "week_outcomes")] checkmate::assert_data_frame(latest_rankings) - assert_columns(latest_rankings, c("player", "pos", "team", "ecr", "sd", "bye", "fantasypros_id","scrape_date")) - latest_rankings <- data.table::as.data.table(latest_rankings)[, c("player", "pos", "team", "ecr", "sd", "bye", "fantasypros_id","scrape_date")] + assert_df(latest_rankings, c("player", "pos", "team", "ecr", "sd", "bye", "fantasypros_id", "scrape_date")) + latest_rankings <- data.table::as.data.table(latest_rankings)[, c("player", "pos", "team", "ecr", "sd", "bye", "fantasypros_id", "scrape_date")] if (is.null(rosters)) rosters <- latest_rankings[, "fantasypros_id"] checkmate::assert_data_frame(rosters) - assert_columns(rosters, "fantasypros_id") + assert_df(rosters, "fantasypros_id") rosters <- data.table::as.data.table(rosters) rankings <- latest_rankings[latest_rankings$fantasypros_id %in% rosters$fantasypros_id] @@ -74,7 +74,7 @@ ffs_generate_projections <- function(adp_outcomes, gp_model = stats::rbinom(n = n_weeks, size = 1, prob = .SD$prob_gp) ), by = c("season", "fantasypros_id", "player", "pos", - "team", "bye", "ecr", "sd", "rank","scrape_date"), + "team", "bye", "ecr", "sd", "rank", "scrape_date"), .SDcols = c("week_outcomes", "prob_gp") ] diff --git a/R/04-projections_week.R b/R/04-projections_week.R index 53555ef..891a9ef 100644 --- a/R/04-projections_week.R +++ b/R/04-projections_week.R @@ -9,8 +9,8 @@ #' #' @examples \donttest{ #' # cached examples -#' adp_outcomes_week <- .ffs_cache("adp_outcomes_week.rds") -#' latest_rankings_week <- .ffs_cache("latest_rankings_week.rds") +#' adp_outcomes_week <- .ffs_cache_example("adp_outcomes_week.rds") +#' latest_rankings_week <- .ffs_cache_example("latest_rankings_week.rds") #' #' ffs_generate_projections_week(adp_outcomes_week, latest_rankings_week) #' } @@ -27,19 +27,19 @@ ffs_generate_projections_week <- function(adp_outcomes, checkmate::assert_number(n, lower = 1) checkmate::assert_data_frame(adp_outcomes) - assert_columns(adp_outcomes, c("pos", "rank", "week_outcomes")) + assert_df(adp_outcomes, c("pos", "rank", "week_outcomes")) adp_outcomes <- data.table::as.data.table(adp_outcomes)[, c("pos", "rank", "week_outcomes")] checkmate::assert_data_frame(latest_rankings) - assert_columns(latest_rankings, c("player", "pos", "team", + assert_df(latest_rankings, c("player", "pos", "team", "ecr", "sd", "fantasypros_id", "scrape_date")) - latest_rankings <- data.table::as.data.table(latest_rankings)[, c("player", "pos", "team", "ecr", "sd", "fantasypros_id","scrape_date")] + latest_rankings <- data.table::as.data.table(latest_rankings)[, c("player", "pos", "team", "ecr", "sd", "fantasypros_id", "scrape_date")] if (is.null(rosters)) rosters <- latest_rankings[, "fantasypros_id"] checkmate::assert_data_frame(rosters) - assert_columns(rosters, "fantasypros_id") + assert_df(rosters, "fantasypros_id") rosters <- data.table::as.data.table(rosters) rankings <- latest_rankings[latest_rankings$fantasypros_id %in% rosters$fantasypros_id] @@ -68,10 +68,10 @@ ffs_generate_projections_week <- function(adp_outcomes, size = 1, replace = TRUE)) ), by = c("week", "fantasypros_id", "player", "pos", - "team", "ecr", "sd", "rank","scrape_date"), + "team", "ecr", "sd", "rank", "scrape_date"), .SDcols = c("week_outcomes") ] - ps <- ps[,`:=`( + ps <- ps[, `:=`( projection = ps$projected_score, gp_model = 1, season = 1 diff --git a/R/05-roster_scores.R b/R/05-roster_scores.R index 809003d..29f3be7 100644 --- a/R/05-roster_scores.R +++ b/R/05-roster_scores.R @@ -7,8 +7,8 @@ #' #' @examples \donttest{ #' # cached examples -#' projected_scores <- .ffs_cache("projected_scores.rds") -#' rosters <- .ffs_cache("mfl_rosters.rds") +#' projected_scores <- .ffs_cache_example("projected_scores.rds") +#' rosters <- .ffs_cache_example("mfl_rosters.rds") #' #' ffs_score_rosters(projected_scores, rosters) #' } @@ -22,7 +22,7 @@ ffs_score_rosters <- function(projected_scores, rosters) { checkmate::assert_data_frame(projected_scores) checkmate::assert_data_frame(rosters) - assert_columns( + assert_df( projected_scores, c( "fantasypros_id", "ecr", "rank", "projection", @@ -31,7 +31,7 @@ ffs_score_rosters <- function(projected_scores, rosters) { ) ) - assert_columns( + assert_df( rosters, c("fantasypros_id", "league_id", "franchise_id", "pos") ) diff --git a/R/06-optimise.R b/R/06-optimise.R index 4294fe1..f0f6c75 100644 --- a/R/06-optimise.R +++ b/R/06-optimise.R @@ -17,8 +17,8 @@ #' #' @examples \donttest{ #' # cached examples -#' roster_scores <- .ffs_cache("roster_scores.rds") -#' lineup_constraints <- .ffs_cache("mfl_lineup_constraints.rds") +#' roster_scores <- .ffs_cache_example("roster_scores.rds") +#' lineup_constraints <- .ffs_cache_example("mfl_lineup_constraints.rds") #' #' ffs_optimise_lineups(roster_scores, lineup_constraints) #' } @@ -40,7 +40,7 @@ ffs_optimise_lineups <- function(roster_scores, checkmate::assert_flag(best_ball) checkmate::assert_data_frame(roster_scores) - assert_columns( + assert_df( roster_scores, c( "pos", "pos_rank", "league_id", "franchise_id", @@ -50,7 +50,7 @@ ffs_optimise_lineups <- function(roster_scores, roster_scores <- data.table::as.data.table(roster_scores) checkmate::assert_data_frame(lineup_constraints, any.missing = FALSE) - assert_columns(lineup_constraints, c("pos", "min", "max", "offense_starters")) + assert_df(lineup_constraints, c("pos", "min", "max", "offense_starters")) lineup_constraints <- data.table::as.data.table(lineup_constraints) lineup_constraints <- lineup_constraints[lineup_constraints$pos %in% pos_filter] @@ -119,7 +119,7 @@ ffs_optimize_lineups <- ffs_optimise_lineups pos_ids, # pos minimums pos_ids, # pos maximums as.integer(franchise_scores$pos %in% c("QB", "RB", "WR", "TE")), rep.int(1L, min_req), # total offensive starters - rep.int(1L,length(player_scores)) + rep.int(1L, length(player_scores)) ), nrow = nrow(lineup_constraints) * 2 + 2, byrow = TRUE diff --git a/R/07-schedule.R b/R/07-schedule.R index 249e010..7ee4cfb 100644 --- a/R/07-schedule.R +++ b/R/07-schedule.R @@ -25,9 +25,9 @@ ffs_build_schedules <- function(n_teams = NULL, seed = NULL) { if (!is.null(franchises)) { checkmate::assert_data_frame(franchises) - assert_columns(franchises, c("league_id", "franchise_id")) + assert_df(franchises, c("league_id", "franchise_id")) f <- data.table::as.data.table(franchises) - f <- f[,c("league_id","franchise_id")] + f <- f[, c("league_id", "franchise_id")] n_teams <- nrow(franchises) } checkmate::assert_number(n_teams) @@ -69,15 +69,15 @@ ffs_build_schedules <- function(n_teams = NULL, if (!is.null(franchises)) { schedule_id <- NULL franchise_id <- NULL - data.table::setorderv(f,c("league_id","franchise_id")) - f[,`:=`(schedule_id = seq_len(.N))] - o <- f[,.(schedule_id,opponent_id=franchise_id)] + data.table::setorderv(f, c("league_id", "franchise_id")) + f[, `:=`(schedule_id = seq_len(.N))] + o <- f[, .(schedule_id, opponent_id = franchise_id)] - schedules <- schedules[f, on = c("team"="schedule_id") - ][o, on = c("opponent"="schedule_id") - ][,c("season", "week", "league_id", "franchise_id", "opponent_id") + schedules <- schedules[f, on = c("team" = "schedule_id") + ][o, on = c("opponent" = "schedule_id") + ][, c("season", "week", "league_id", "franchise_id", "opponent_id") ] - data.table::setorderv(schedules, c("season","week","franchise_id")) + data.table::setorderv(schedules, c("season", "week", "franchise_id")) } data.table::setcolorder(schedules, c("season", "week", "franchise_id", "opponent_id")) @@ -121,7 +121,7 @@ ffs_build_schedules <- function(n_teams = NULL, week <- NULL team <- NULL opponent <- NULL - df_schedule <- data.table::rbindlist(lapply(schedule,.ff_enframe))[ + df_schedule <- data.table::rbindlist(lapply(schedule, .ff_enframe))[ , week := rep(seq_len(n_teams - 1), each = n_teams) ][ order(week, team) @@ -130,7 +130,7 @@ ffs_build_schedules <- function(n_teams = NULL, if (bye) { # remove additional team df_schedule <- df_schedule[ - team == n_teams , team := NA_integer_ + team == n_teams, team := NA_integer_ ][ opponent == n_teams, opponent := NA_integer_ ][ @@ -142,7 +142,7 @@ ffs_build_schedules <- function(n_teams = NULL, } #' @keywords internal -.ff_enframe <- function(vec){ +.ff_enframe <- function(vec) { data.table::data.table( team = as.integer(names(vec)), opponent = vec @@ -160,8 +160,8 @@ ffs_build_schedules <- function(n_teams = NULL, week <- NULL if (schedule_max < n_weeks) { - x <- df_schedule[week <=(n_weeks-schedule_max)][,`:=`(week = week + schedule_max)] - df_schedule <- data.table::rbindlist(list(df_schedule,x)) + x <- df_schedule[week <= (n_weeks - schedule_max)][, `:=`(week = week + schedule_max)] + df_schedule <- data.table::rbindlist(list(df_schedule, x)) } if (schedule_max > n_weeks) { @@ -177,7 +177,7 @@ ffs_build_schedules <- function(n_teams = NULL, opponent <- NULL week <- NULL - x <- schedule_template[,`:=`( + x <- schedule_template[, `:=`( team = team_order[team], opponent = team_order[opponent], week = week_order[week]) @@ -198,7 +198,7 @@ ffs_build_schedules <- function(n_teams = NULL, #' \donttest{ #' # cached examples #' try({ # try block to prevent CRAN-related issues -#' conn <- .ffs_cache("mfl_conn.rds") +#' conn <- .ffs_cache_example("mfl_conn.rds") #' ffs_schedule(conn) #' }) #' } @@ -206,16 +206,16 @@ ffs_build_schedules <- function(n_teams = NULL, #' @seealso vignette("Custom Simulations") for more detailed example usage #' #' @export -ffs_schedule <- function(conn){ +ffs_schedule <- function(conn) { schedule <- ffscrapr::ff_schedule(conn) - if("spread" %in% names(schedule)){ - schedule$result[(!is.na(schedule$spread)|schedule$spread==0) & schedule$result == "T"] <- NA + if ("spread" %in% names(schedule)) { + schedule$result[(!is.na(schedule$spread) | schedule$spread == 0) & schedule$result == "T"] <- NA } - schedule <- schedule[is.na(schedule$result),c("week","franchise_id","opponent_id")] + schedule <- schedule[is.na(schedule$result), c("week", "franchise_id", "opponent_id")] schedule$league_id <- as.character(conn$league_id) schedule$franchise_id <- as.character(schedule$franchise_id) - schedule$opponent_id <- as.character(schedule$opponent_id) + schedule$opponent_id <- as.character(schedule$opponent_id) return(schedule) @@ -230,7 +230,7 @@ ffs_schedule <- function(conn){ #' #' @examples \donttest{ #' try({ # try block to prevent CRAN-related issues -#' conn <- .ffs_cache("mfl_conn.rds") # cached connection +#' conn <- .ffs_cache_example("mfl_conn.rds") # cached connection #' actual_schedule <- ffs_schedule(conn) #' #' ffs_repeat_schedules(actual_schedule = actual_schedule, n_seasons = 10) @@ -241,14 +241,13 @@ ffs_schedule <- function(conn){ #' #' @seealso `vignette("Custom Simulations")` for example usage #' @export -ffs_repeat_schedules <- function(actual_schedule, n_seasons){ +ffs_repeat_schedules <- function(actual_schedule, n_seasons) { data.table::setDT(actual_schedule) merge( data.table::data.table(season = seq_len(n_seasons), k = 1), - actual_schedule[,c(k = 1,.SD)], - allow.cartesian = TRUE)[,`:=`(k = NULL)][] + actual_schedule[, c(k = 1, .SD)], + allow.cartesian = TRUE)[, `:=`(k = NULL)][] } - diff --git a/R/08-summaries.R b/R/08-summaries.R index 96a067b..b331cac 100644 --- a/R/08-summaries.R +++ b/R/08-summaries.R @@ -9,8 +9,8 @@ #' #' @examples \donttest{ #' # cached examples -#' optimal_scores <- .ffs_cache("optimal_scores.rds") -#' schedules <- .ffs_cache("schedules.rds") +#' optimal_scores <- .ffs_cache_example("optimal_scores.rds") +#' schedules <- .ffs_cache_example("schedules.rds") #' #' summary_week <- ffs_summarise_week(optimal_scores, schedules) #' summary_week @@ -25,16 +25,16 @@ #' @export ffs_summarise_week <- function(optimal_scores, schedules) { checkmate::assert_data_frame(optimal_scores) - assert_columns( + assert_df( optimal_scores, c("season", "week", "season", "week", "actual_score", "league_id", "franchise_id") ) data.table::setDT(optimal_scores) checkmate::assert_data_frame(schedules) - assert_columns( + assert_df( schedules, - c("league_id","franchise_id","opponent_id","season", "week") + c("league_id", "franchise_id", "opponent_id", "season", "week") ) data.table::setDT(schedules) @@ -47,18 +47,18 @@ ffs_summarise_week <- function(optimal_scores, schedules) { team[ , - `:=`(allplay_wins = data.table::frank(actual_score)-1, - allplay_games = .N -1), - by = c("season","week") - ][,`:=`(allplay_pct = round(allplay_wins / allplay_games, 3))] + `:=`(allplay_wins = data.table::frank(actual_score) - 1, + allplay_games = .N - 1), + by = c("season", "week") + ][, `:=`(allplay_pct = round(allplay_wins / allplay_games, 3))] opponent <- data.table::copy(team) - data.table::setnames(team,old = "actual_score",new = "team_score") + data.table::setnames(team, old = "actual_score", new = "team_score") data.table::setnames(opponent, - old = c("actual_score","franchise_id","franchise_name"), - new = c("opponent_score","opponent_id","opponent_name")) + old = c("actual_score", "franchise_id", "franchise_name"), + new = c("opponent_score", "opponent_id", "opponent_name")) - opponent <- opponent[,c("opponent_score","opponent_id","opponent_name","league_id","season","week")] + opponent <- opponent[, c("opponent_score", "opponent_id", "opponent_name", "league_id", "season", "week")] team_score <- NULL opponent_score <- NULL @@ -66,17 +66,17 @@ ffs_summarise_week <- function(optimal_scores, schedules) { lineup_efficiency <- NULL summary_week <- schedules[ - team, on = c("league_id","franchise_id", "season", "week"), nomatch = 0 - ][opponent, on = c("league_id","opponent_id", "season", "week"), nomatch = 0 - ][,`:=`(result = data.table::fcase(team_score > opponent_score, "W", + team, on = c("league_id", "franchise_id", "season", "week"), nomatch = 0 + ][opponent, on = c("league_id", "opponent_id", "season", "week"), nomatch = 0 + ][, `:=`(result = data.table::fcase(team_score > opponent_score, "W", team_score < opponent_score, "L", team_score == opponent_score, "T", TRUE, NA_character_), - team_score = round(team_score,2), - optimal_score = round(optimal_score,2), - opponent_score = round(opponent_score,2), - lineup_efficiency = round(lineup_efficiency,3)) - ][,c("season", + team_score = round(team_score, 2), + optimal_score = round(optimal_score, 2), + opponent_score = round(opponent_score, 2), + lineup_efficiency = round(lineup_efficiency, 3)) + ][, c("season", "week", "franchise_name", "optimal_score", @@ -93,7 +93,7 @@ ffs_summarise_week <- function(optimal_scores, schedules) { "optimal_player_id", "optimal_player_score")] - data.table::setorderv(summary_week,c("season","week","franchise_id")) + data.table::setorderv(summary_week, c("season", "week", "franchise_id")) return(summary_week) } @@ -106,7 +106,7 @@ ffs_summarise_week <- function(optimal_scores, schedules) { #' @export ffs_summarise_season <- function(summary_week) { checkmate::assert_data_frame(summary_week) - assert_columns( + assert_df( summary_week, c( "season", "league_id", "franchise_id", "franchise_name", @@ -126,15 +126,15 @@ ffs_summarise_season <- function(summary_week) { summary_season <- summary_week[ , .(h2h_wins = sum(result == "W", na.rm = TRUE), - h2h_winpct = round(sum(result == "W", na.rm = TRUE) / .N,3), + h2h_winpct = round(sum(result == "W", na.rm = TRUE) / .N, 3), allplay_wins = sum(allplay_wins, na.rm = TRUE), allplay_games = sum(allplay_games, na.rm = TRUE), - allplay_winpct = round(sum(allplay_wins, na.rm = TRUE) / sum(allplay_games, na.rm = TRUE),3), + allplay_winpct = round(sum(allplay_wins, na.rm = TRUE) / sum(allplay_games, na.rm = TRUE), 3), points_for = sum(team_score, na.rm = TRUE), points_against = sum(opponent_score, na.rm = TRUE), potential_points = sum(optimal_score, na.rm = TRUE) ), - by = c("season","league_id","franchise_id","franchise_name") + by = c("season", "league_id", "franchise_id", "franchise_name") ] return(summary_season) @@ -148,7 +148,7 @@ ffs_summarise_season <- function(summary_week) { #' @export ffs_summarise_simulation <- function(summary_season) { checkmate::assert_data_frame(summary_season) - assert_columns( + assert_df( summary_season, c( "league_id", "franchise_id", "franchise_name", @@ -161,16 +161,16 @@ ffs_summarise_simulation <- function(summary_season) { allplay_winpct <- NULL summary_simulation <- summary_season[ - ,c(list(seasons = .N), + , c(list(seasons = .N), lapply(.SD, ffs_mean)), - by = c("league_id","franchise_id","franchise_name"), + by = c("league_id", "franchise_id", "franchise_name"), .SDcols = c("h2h_wins", "h2h_winpct", "allplay_wins", "allplay_winpct", "points_for", "points_against", "potential_points") ][order(-allplay_winpct)] return(summary_simulation) } -ffs_mean <- function(...){round(mean(...,na.rm = TRUE),3)} +ffs_mean <- function(...) {round(mean(..., na.rm = TRUE), 3)} #' Summarise Inseason Simulation #' @@ -179,10 +179,10 @@ ffs_mean <- function(...){round(mean(...,na.rm = TRUE),3)} #' @rdname ffs_summaries #' @return ffs_summarise_inseason: a dataframe summarising franchise results for the inseason simulation #' @export -ffs_summarise_inseason <- function(summary_week,n) { +ffs_summarise_inseason <- function(summary_week, n) { checkmate::assert_number(n) checkmate::assert_data_frame(summary_week) - assert_columns( + assert_df( summary_week, c( "league_id", "franchise_id", "franchise_name", @@ -202,15 +202,15 @@ ffs_summarise_inseason <- function(summary_week,n) { summary_season <- summary_week[ , .(h2h_wins = sum(result == "W", na.rm = TRUE), - h2h_winpct = round(sum(result == "W", na.rm = TRUE) / .N,3), + h2h_winpct = round(sum(result == "W", na.rm = TRUE) / .N, 3), allplay_wins = sum(allplay_wins, na.rm = TRUE), allplay_games = sum(allplay_games, na.rm = TRUE), - allplay_winpct = round(sum(allplay_wins, na.rm = TRUE) / sum(allplay_games, na.rm = TRUE),3), - points_for = round(sum(team_score, na.rm = TRUE)/n,2), - points_against = round(sum(opponent_score, na.rm = TRUE)/n,2), - potential_points = round(sum(optimal_score, na.rm = TRUE)/n,2) + allplay_winpct = round(sum(allplay_wins, na.rm = TRUE) / sum(allplay_games, na.rm = TRUE), 3), + points_for = round(sum(team_score, na.rm = TRUE) / n, 2), + points_against = round(sum(opponent_score, na.rm = TRUE) / n, 2), + potential_points = round(sum(optimal_score, na.rm = TRUE) / n, 2) ), - by = c("league_id","franchise_id","franchise_name") + by = c("league_id", "franchise_id", "franchise_name") ] return(summary_season) diff --git a/R/09-autoplot.R b/R/09-autoplot.R index 6b423cd..4b03c38 100644 --- a/R/09-autoplot.R +++ b/R/09-autoplot.R @@ -1,4 +1,3 @@ - #' Automatically Plot ff_simulation Object #' #' Creates automatic plots for wins, ranks, or points for an `ff_simulation` object as created by `ff_simulate()`. @@ -12,7 +11,7 @@ #' @examples #' \donttest{ #' -#' simulation <- .ffs_cache("foureight_sim.rds") +#' simulation <- .ffs_cache_example("foureight_sim.rds") #' #' ggplot2::autoplot(simulation) # default is type = "wins" #' ggplot2::autoplot(simulation, type = "rank") @@ -47,8 +46,8 @@ autoplot.ff_simulation <- function(object, franchise_name <- NULL ss_levels <- ss[ - , list(franchise_name,h2h_wins = stats::median(h2h_wins, na.rm = TRUE)) - ,by = "franchise_name" + , list(franchise_name, h2h_wins = stats::median(h2h_wins, na.rm = TRUE)) + , by = "franchise_name" ][ order(h2h_wins) ] @@ -99,7 +98,7 @@ autoplot.ff_simulation <- function(object, season_rank <- NULL ss[ - ,`:=`(season_rank = rank(-h2h_wins, ties.method = "min")) + , `:=`(season_rank = rank(-h2h_wins, ties.method = "min")) , by = "season" ] @@ -117,7 +116,7 @@ autoplot.ff_simulation <- function(object, ss, ggplot2::aes(x = .data$franchise_name, color = .data$franchise_name, fill = .data$franchise_name)) + ggplot2::geom_bar() + - ggplot2::scale_x_discrete(guide = ggplot2::guide_axis(position = "none"))+ + ggplot2::scale_x_discrete(guide = ggplot2::guide_axis(position = "none")) + ggplot2::facet_wrap(~ .data$rank_label) + ggplot2::xlab(NULL) + ggplot2::ylab("Number of Seasons") + @@ -144,7 +143,7 @@ autoplot.ff_simulation <- function(object, team_score <- NULL sw_levels <- sw[ , list(team_score = stats::median(team_score, na.rm = TRUE)) - ,by = c("franchise_name") + , by = c("franchise_name") ][ order(team_score) ] diff --git a/R/09-autoplot_week.R b/R/09-autoplot_week.R index 15b210f..96022a1 100644 --- a/R/09-autoplot_week.R +++ b/R/09-autoplot_week.R @@ -1,4 +1,3 @@ - #' Automatically Plot ff_simulation Object #' #' Creates automatic plots for wins, ranks, or points for an `ff_simulation` object as created by `ff_simulate()`. @@ -12,7 +11,7 @@ #' @examples #' \donttest{ #' -#' simulation <- .ffs_cache("foureight_sim_week.rds") +#' simulation <- .ffs_cache_example("foureight_sim_week.rds") #' #' ggplot2::autoplot(simulation) # default is type = "luck" #' ggplot2::autoplot(simulation, type = "points") @@ -23,7 +22,7 @@ #' @return a ggplot object #' @export autoplot.ff_simulation_week <- function(object, - type = c("luck","points"), + type = c("luck", "points"), ...) { type <- rlang::arg_match(type) @@ -38,7 +37,7 @@ autoplot.ff_simulation_week <- function(object, .ffs_plot_week_luck <- function(object, ..., caller_env = rlang::caller_env()) { - if(!object$simulation_params$actual_schedule) { + if (!object$simulation_params$actual_schedule) { cli::cli_abort("Schedule luck plot not available if `actual_schedule` is FALSE", call = caller_env) } @@ -49,9 +48,9 @@ autoplot.ff_simulation_week <- function(object, luck_pct <- NULL luck <- luck[ - ,`:=`(luck_pct = h2h_winpct - allplay_winpct) + , `:=`(luck_pct = h2h_winpct - allplay_winpct) ][ - ,`:=`( + , `:=`( luck_label = scales::percent(luck_pct, accuracy = 0.1), ap_hjust = ifelse(luck_pct > 0, 1.1, -0.1), h2h_hjust = ifelse(luck_pct > 0, -0.1, 1.1) @@ -82,10 +81,10 @@ autoplot.ff_simulation_week <- function(object, alpha = 0.75, lineend = "round", linejoin = "mitre", - arrow = ggplot2::arrow(angle = 30,length = ggplot2::unit(6, "points"),type = "closed")) + + arrow = ggplot2::arrow(angle = 30, length = ggplot2::unit(6, "points"), type = "closed")) + ggplot2::geom_text( ggplot2::aes( - x = (.data$allplay_winpct + .data$h2h_winpct)/2, + x = (.data$allplay_winpct + .data$h2h_winpct) / 2, label = .data$luck_label), hjust = 0.5, vjust = -0.75 @@ -109,8 +108,8 @@ autoplot.ff_simulation_week <- function(object, label = "AllPlay Win %", data = luck[.N] ) + - ggplot2::scale_x_continuous(labels = scales::percent_format(),limits = c(0, 1))+ - ggplot2::scale_color_discrete(guide = "none")+ + ggplot2::scale_x_continuous(labels = scales::percent_format(), limits = c(0, 1)) + + ggplot2::scale_color_discrete(guide = "none") + ggplot2::xlab("Win Percentage") + ggplot2::ylab(NULL) + ggplot2::theme_minimal() + diff --git a/R/ffsimulator-package.R b/R/ffsimulator-package.R new file mode 100644 index 0000000..c5406e8 --- /dev/null +++ b/R/ffsimulator-package.R @@ -0,0 +1,24 @@ +#' @keywords internal +"_PACKAGE" + +## usethis namespace: start +#' +#' @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 data.table +#' @importFrom magrittr `%>%` +#' @importFrom rlang .data `%||%` .env +#' @importFrom stats median +#' @importFrom utils str +## usethis namespace: end +NULL + +## data.table-related stuff +globalVariables(".") +.datatable.aware <- TRUE diff --git a/R/utils-assert.R b/R/utils-assert.R index f594e68..9d7ccdf 100644 --- a/R/utils-assert.R +++ b/R/utils-assert.R @@ -1,26 +1,45 @@ -#' Check that dataframe has x column names +#' Check that df has x column names #' -#' @param dataframe dataframe to check +#' @param df df to check #' @param required_columns required column names +#' @param .env caller environment to complain from #' #' @return silent if ok or else an error if something is missing. #' #' @keywords internal -assert_columns <- function(dataframe, required_columns) { - d <- as.character(rlang::enexpr(dataframe)) +assert_df <- function(df, required_columns, .env = rlang::caller_env()) { - n <- names(dataframe) - r <- required_columns %in% n - if (all(r)) { - return(NULL) + if (!inherits(df, "data.frame")) { + cli::cli_abort( + "{.arg {rlang::caller_arg(df)}} must be coercible to a data.frame", + call = .env + ) } - rlang::abort( - glue::glue( - "Assertion on `{d}` failed: requires columns ", - "({paste(required_columns, collapse = ', ')})", - " and is missing ({paste(required_columns[!r],collapse = ';')})" - ) + if (length(required_columns) == 0) return(invisible(TRUE)) + + n <- names(df) + r <- required_columns %in% n + + if (all(r)) return(invisible(TRUE)) + + missing <- required_columns[!r] + d <- rlang::caller_arg(df) + + cli::cli_abort( + c( + "!" = "Assertion on {.arg {d}} failed", + "i" = "Requires columns ({.val {required_columns}})", + "i" = "and is missing: ({.val {missing}})" + ), + call = .env ) } +assert_character <- function(x, .env = rlang::caller_env()) { + if (is.character(x)) return(invisible(TRUE)) + cli::cli_abort( + "Assertion on {.arg {rlang::caller_arg(x)} failed: must be a character vector", + call = .env + ) +} diff --git a/R/utils-data.R b/R/utils-data.R index 62b9f30..654d3d5 100644 --- a/R/utils-data.R +++ b/R/utils-data.R @@ -1,17 +1,118 @@ #' FP injury table #' -#' This dataframe contains a column (`prob_gp`) for each positional ranking that describes the probability of a player with that preseason ADP playing in a given game. It is modelled from historical rankings data and the number of games played per season for a given positional rank. +#' This dataframe contains a column (`prob_gp`) for each positional ranking that +#' describes the probability of a player with that preseason ADP playing in a +#' given game. It is modelled from historical rankings data and the number of +#' games played per season for a given positional rank. #' -"fp_injury_table" +#' By default, it returns bundled package data unless the `ffsimulator.cache_directory` +#' option is configured, in which case it will look for a rds file named +#' `fp_injury_table.rds` in that directory. +#' +#' To update, use `ffs_copy_template("rankings_update")` to find the bundled update script +#' +#' @return dataframe of injury probability by position rank +#' @export +fp_injury_table <- function() { + .fp_injury_table <- .ffs_read_data("fp_injury_table.rds") + + assert_df(.fp_injury_table, c("pos", "rank", "prob_gp")) + return(.fp_injury_table) +} #' Historical draft position ranks #' -#' This dataframe has historical positional draft rankings for 2012-2020 QB/RB/WR/TE/PK and 2015-2020 DL/LB/DB, as gathered by the ffpros package. +#' This dataframe has historical positional draft rankings starting in 2012 for +#' QB/RB/WR/TE/PK and 2015 DL/LB/DB, as gathered by the ffpros package. +#' +#' By default, it returns bundled package data unless the `ffsimulator.cache_directory` +#' option is configured, in which case it will look for a rds file named +#' `fp_rankings_history.rds` in that directory. +#' +#' To update, use `ffs_copy_template("rankings_update")` to find the bundled update script #' -"fp_rankings_history" +#' @return dataframe of preseason/draft rankings from ffpros +#' @export +#' +fp_rankings_history <- function() { + .fp_rankings_history <- .ffs_read_data("fp_rankings_history.rds") + assert_df( + .fp_rankings_history, + c("season", "fantasypros_id", "sportradar_id", + "player_name", "pos", "team", "rank", "ecr", "sd") + ) + return(.fp_rankings_history) +} #' Historical position ranks #' -#' This dataframe has historical positional in-season rankings for 2012-2020 QB/RB/WR/TE/PK and 2015-2020 DL/LB/DB, as gathered by the ffpros package. +#' This dataframe has historical positional in-season rankings starting in 2012 for +#' QB/RB/WR/TE/PK and 2015 for DL/LB/DB, as gathered by the ffpros package. +#' +#' By default, it returns bundled package data unless the `ffsimulator.cache_directory` +#' option is configured, in which case it will look for a rds file named +#' `fp_rankings_history_week.rds` in that directory. #' -"fp_rankings_history_week" +#' To update, use `ffs_copy_template("rankings_update")` to find the bundled update script +#' +#' @return dataframe of in-season positional rankings +#' @export +fp_rankings_history_week <- function() { + .fp_rankings_history_week <- .ffs_read_data("fp_rankings_history_week.rds") + assert_df( + .fp_rankings_history_week, + c("season", "week", "fantasypros_id", "sportradar_id", + "player_name", "pos", "team", "rank", "ecr", "sd") + ) + return(.fp_rankings_history_week) +} + +#' Read data from cache or pkg data +#' +#' @param file_name filename to find +#' @param .env for internal use in error messages +#' +#' @rdname data-cache +#' @export +.ffs_read_data <- function(file_name, .env = rlang::caller_env()) { + cache_file <- .ffs_cache_dir(file_name) + + if (!checkmate::test_file_exists(cache_file)) { + out <- readRDS(.ffs_cache_pkgdir(file_name)) + return(out) + } + + cli::cli_inform( + "Using {.file {file_name}} found in cache directory {.path { .ffs_cache_dir()}}", + .frequency = "regularly", + .frequency_id = paste0("ffsimulator_cache_", file_name) + ) + + rlang::try_fetch( + out <- readRDS(cache_file), + error = function(e) { + cli::cli_abort("Could not parse file {cache_file} as RDS!", call = .env) + } + ) + + return(out) +} + +#' @export +#' @rdname data-cache +.ffs_cache_dir <- function(...) { + dir <- getOption( + "ffsimulator.cache_directory", + default = rappdirs::user_cache_dir("ffsimulator", "ffverse") + ) + file.path(dir, ...) +} + +.ffs_cache_pkgdir <- function(...) { + system.file( + "data", + ..., + package = "ffsimulator", + mustWork = TRUE + ) +} diff --git a/R/utils-ffscrapr.R b/R/utils-ffscrapr.R index 94462a2..d1da152 100644 --- a/R/utils-ffscrapr.R +++ b/R/utils-ffscrapr.R @@ -87,14 +87,14 @@ NULL #' \donttest{ #' # cached examples #' try({ # try block to prevent CRAN-related issues -#' conn <- .ffs_cache("mfl_conn.rds") +#' conn <- .ffs_cache_example("mfl_conn.rds") #' ffs_starter_positions(conn) #' }) #' } #' #' @export -ffs_starter_positions <- function(conn){ +ffs_starter_positions <- function(conn) { sp <- ffscrapr::ff_starter_positions(conn) - sp$pos <- replace(sp$pos,sp$pos == "PK","K") + sp$pos <- replace(sp$pos, sp$pos == "PK", "K") sp } diff --git a/R/utils-template.R b/R/utils-template.R index 43e9d5a..1538aa5 100644 --- a/R/utils-template.R +++ b/R/utils-template.R @@ -13,11 +13,9 @@ #' @export #' @return a success message signalling success/failure. -ffs_copy_template <- function( - filename = "ff_simulation.R", - template = c("season", "week"), - overwrite = NULL - ) { +ffs_copy_template <- function(template = c("season", "week", "rankings_update"), + filename = glue::glue("ff_simulator_{template}.R"), + overwrite = NULL) { template <- rlang::arg_match(template) checkmate::assert_flag(overwrite, null.ok = TRUE) @@ -25,6 +23,7 @@ ffs_copy_template <- function( template, "season" = "simulation_template_season.R", "week" = "simulation_template_week.R", + "rankings_update" = "update_rankings_data.R", stop("No template found") ) @@ -45,7 +44,7 @@ ffs_copy_template <- function( return(cli::cli_alert_info("Did not copy template to {filename} - found existing file!")) } - from <- system.file("simulation_template_season.R", package = "ffsimulator") + from <- system.file(template_file, package = "ffsimulator") file.copy(from, filename, overwrite = TRUE) diff --git a/R/utils.R b/R/utils.R index 11e6148..b6b0006 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,93 +1,46 @@ #### UTILS ### -# External functions imported and sometimes re-exported - -# data.table is generally careful to minimize the scope for namespace -# conflicts (i.e., functions with the same name as in other packages); -# a more conservative approach using @importFrom should be careful to -# import any needed data.table special symbols as well, e.g., if you -# run DT[ , .N, by='grp'] in your package, you'll need to add -# @importFrom data.table .N to prevent the NOTE from R CMD check. -# See ?data.table::`special-symbols` for the list of such symbols -# data.table defines; see the 'Importing data.table' vignette for more -# advice (vignette('datatable-importing', 'data.table')). -# -#' @importFrom data.table .N .SD `:=` -#' @keywords internal -NULL - -globalVariables(".") -.datatable.aware <- TRUE - -#' @keywords internal -#' @importFrom rlang .data `%||%` .env -#' @importFrom utils str -#' @importFrom stats median -NULL - -#' Pipe operator -#' -#' See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. -#' -#' @name %>% -#' @rdname pipe -#' @keywords internal -#' @export -#' @importFrom magrittr %>% -#' @usage lhs \%>\% rhs -#' @param lhs A value or the magrittr placeholder. -#' @param rhs A function call using the magrittr semantics. -#' @return The result of calling `rhs(lhs)`. -NULL - -#' @keywords internal -"_PACKAGE" - -# The following block is used by usethis to automatically manage -# roxygen namespace tags. Modify with care! -## usethis namespace: start -## usethis namespace: end -NULL #' Access cached function data #' -#' @noRd +#' @keywords internal #' @export -.ffs_cache <- function(filename) { +.ffs_cache_example <- function(filename) { readRDS( system.file( - file.path("cache", filename), - package = "ffsimulator") + file.path("examples", filename), + package = "ffsimulator" + ) ) } set_verbose <- function(verbose = NULL) { - if(isTRUE(verbose)) options(ffsimulator.verbose = TRUE) - if(!isTRUE(verbose)) options(ffsimulator.verbose = FALSE) + if (isTRUE(verbose)) options(ffsimulator.verbose = TRUE) + if (!isTRUE(verbose)) options(ffsimulator.verbose = FALSE) return(NULL) } -vcli_start <- function(...){ +vcli_start <- function(...) { v <- getOption("ffsimulator.verbose", default = TRUE) - if(!v) return(NULL) + if (!v) return(NULL) cli::cli_process_start(...) } -vcli_end <- function(...){ +vcli_end <- function(...) { v <- getOption("ffsimulator.verbose", default = TRUE) - if(!v) return(NULL) + if (!v) return(NULL) cli::cli_process_done(...) } -vcli_rule <- function(...){ +vcli_rule <- function(...) { v <- getOption("ffsimulator.verbose", default = TRUE) - if(!v) return(NULL) + if (!v) return(NULL) cli::cli_rule(...) } diff --git a/README.Rmd b/README.Rmd index 0fa9077..d74d840 100644 --- a/README.Rmd +++ b/README.Rmd @@ -44,13 +44,16 @@ This package is part of the [ffverse](https://www.ffverse.com) family of R packa Install the stable version of this package from CRAN: ```{r} -install.packages("ffsimulator") # CRAN +install.packages("ffsimulator") ``` Install the development version from either [r-universe](https://ffverse.r-universe.dev) or GitHub: ```{r} -install.packages("ffsimulator", repos = "https://ffverse.r-universe.dev") +install.packages( + "ffsimulator", + repos = c("https://ffverse.r-universe.dev", getOption("repos")) +) # pak is recommended, see https://github.com/r-lib/pak pak::pak("ffverse/ffsimulator") # can also use remotes @@ -71,8 +74,8 @@ library(ggridges) mfl_conn <- mfl_connect(season = 2021, league_id = 22627) ## OTHER PLATFORM CONNECTIONS MAY BE USED, FOR EXAMPLE: -# sleeper_conn <- sleeper_connect(season = 2021, league_id = "652582284720971776") -# flea_conn <- fleaflicker_connect(season = 2021, league_id = 312861) +# sleeper_conn <- sleeper_connect(season = 2021, league_id = "652582284720971776") +# flea_conn <- fleaflicker_connect(season = 2021, league_id = 312861) # espn_conn <- espn_connect(season = 2021, league_id = 899513) mfl_sim <- ff_simulate(conn = mfl_conn, n_seasons = 100) diff --git a/README.md b/README.md index 585600e..3593732 100644 --- a/README.md +++ b/README.md @@ -40,14 +40,17 @@ R packages for fantasy football analysis. Install the stable version of this package from CRAN: ``` r -install.packages("ffsimulator") # CRAN +install.packages("ffsimulator") ``` Install the development version from either [r-universe](https://ffverse.r-universe.dev) or GitHub: ``` r -install.packages("ffsimulator", repos = "https://ffverse.r-universe.dev") +install.packages( + "ffsimulator", + repos = c("https://ffverse.r-universe.dev", getOption("repos")) +) # pak is recommended, see https://github.com/r-lib/pak pak::pak("ffverse/ffsimulator") # can also use remotes @@ -69,8 +72,8 @@ library(ggridges) mfl_conn <- mfl_connect(season = 2021, league_id = 22627) ## OTHER PLATFORM CONNECTIONS MAY BE USED, FOR EXAMPLE: -# sleeper_conn <- sleeper_connect(season = 2021, league_id = "652582284720971776") -# flea_conn <- fleaflicker_connect(season = 2021, league_id = 312861) +# sleeper_conn <- sleeper_connect(season = 2021, league_id = "652582284720971776") +# flea_conn <- fleaflicker_connect(season = 2021, league_id = 312861) # espn_conn <- espn_connect(season = 2021, league_id = 899513) mfl_sim <- ff_simulate(conn = mfl_conn, n_seasons = 100) diff --git a/data-raw/build_test_fixtures.R b/data-raw/build_test_fixtures.R index ff05652..b613592 100644 --- a/data-raw/build_test_fixtures.R +++ b/data-raw/build_test_fixtures.R @@ -83,7 +83,7 @@ saveRDS(adp_outcomes, "inst/cache/adp_outcomes.rds") adp_outcomes_week <- ffs_adp_outcomes_week( scoring_history = mfl_scoring_history, - pos_filter = c("QB","RB","WR") + pos_filter = c("QB", "RB", "WR") ) saveRDS(adp_outcomes_week, "inst/cache/adp_outcomes_week.rds") @@ -131,5 +131,5 @@ foureight_sim <- ff_simulate(foureight, n_seasons = 10) saveRDS(foureight_sim, "inst/cache/foureight_sim.rds") -foureight_sim_week <- ff_simulate_week(foureight,n = 25) +foureight_sim_week <- ff_simulate_week(foureight, n = 25) saveRDS(foureight_sim_week, "inst/cache/foureight_sim_week.rds") diff --git a/data-raw/fp_injury_table.R b/data-raw/fp_injury_table.R index ba53933..4404789 100644 --- a/data-raw/fp_injury_table.R +++ b/data-raw/fp_injury_table.R @@ -15,7 +15,7 @@ fp_injury_table <- ffsimulator::fp_rankings_history %>% dplyr::select("fantasypros_id", "gsis_id"), by = "fantasypros_id" ) %>% - dplyr::filter(!is.na(.data$gsis_id), pos %in% c("QB", "RB", "WR", "TE","K")) %>% + dplyr::filter(!is.na(.data$gsis_id), pos %in% c("QB", "RB", "WR", "TE", "K")) %>% dplyr::left_join( scoring_history %>% dplyr::filter(!is.na(.data$gsis_id), .data$week <= 17) %>% @@ -48,4 +48,4 @@ fp_injury_table <- ffsimulator::fp_rankings_history %>% distinct(pos, rank, prob_gp) %>% arrange(pos, rank) -usethis::use_data(fp_injury_table, overwrite = TRUE) +saveRDS(fp_injury_table, "inst/data/fp_injury_table.rds") diff --git a/data-raw/fp_rankings_history.R b/data-raw/fp_rankings_history.R index 00555ff..de1ba58 100644 --- a/data-raw/fp_rankings_history.R +++ b/data-raw/fp_rankings_history.R @@ -73,6 +73,6 @@ fp_rankings_history2 <- crossing(pages2, seasons2) %>% ) %>% filter(page_pos == pos) -.fp_rankings_history <- bind_rows(fp_rankings_history2, fp_rankings_history) +fp_rankings_history <- bind_rows(fp_rankings_history2, fp_rankings_history) -usethis::use_data(.fp_rankings_history, overwrite = TRUE) +saveRDS(fp_rankings_history, file = "inst/data/fp_rankings_history.rds") diff --git a/data-raw/weekly_rankings_history.R b/data-raw/weekly_rankings_history.R index 007dbd8..091ff65 100644 --- a/data-raw/weekly_rankings_history.R +++ b/data-raw/weekly_rankings_history.R @@ -27,7 +27,7 @@ pages <- c( fp_rankings_history <- crossing(pages, seasons, weeks) %>% mutate(rankings = future_pmap( list(pages, seasons, weeks), - possibly(~fp_rankings(page = ..1, year = ..2, week = ..3), + possibly(~ fp_rankings(page = ..1, year = ..2, week = ..3), tibble()) )) %>% unnest(rankings) %>% @@ -70,7 +70,7 @@ pages2 <- c( fp_rankings_history2 <- crossing(pages2, seasons2, weeks) %>% mutate(rankings = future_pmap( list(pages2, seasons2, weeks), - possibly(~fp_rankings(page = ..1, year = ..2, week = ..3), + possibly(~ fp_rankings(page = ..1, year = ..2, week = ..3), tibble()) )) %>% unnest(rankings) %>% @@ -94,4 +94,4 @@ fp_rankings_history2 <- crossing(pages2, seasons2, weeks) %>% fp_rankings_history_week <- bind_rows(fp_rankings_history, fp_rankings_history2) -usethis::use_data(fp_rankings_history_week, overwrite = TRUE) +saveRDS(fp_rankings_history_week, "inst/data/fp_rankings_history_week.rds") diff --git a/data/fp_injury_table.rda b/data/fp_injury_table.rda deleted file mode 100644 index 6ec8861..0000000 Binary files a/data/fp_injury_table.rda and /dev/null differ diff --git a/data/fp_rankings_history.rda b/data/fp_rankings_history.rda deleted file mode 100644 index 412efb9..0000000 Binary files a/data/fp_rankings_history.rda and /dev/null differ diff --git a/data/fp_rankings_history_week.rda b/data/fp_rankings_history_week.rda deleted file mode 100644 index 0f6b4a7..0000000 Binary files a/data/fp_rankings_history_week.rda and /dev/null differ diff --git a/dev/archive_ffs_optimise.R b/dev/archive_ffs_optimise.R index 3a66aba..c494be2 100644 --- a/dev/archive_ffs_optimise.R +++ b/dev/archive_ffs_optimise.R @@ -62,14 +62,14 @@ ffs_score_rosters <- function(projected_scores, rosters) { checkmate::assert_data_frame(projected_scores) checkmate::assert_data_frame(rosters) - assert_columns( + assert_df( projected_scores, c("fantasypros_id", "ecr", "rank", "projection", "gp_model", "season", "week", "projected_score", "scrape_date") ) - assert_columns( + assert_df( rosters, c("fantasypros_id", "league_id", "franchise_id", "pos") ) @@ -106,12 +106,12 @@ ffs_optimise_lineups_dplyr <- function(roster_scores, checkmate::assert_flag(parallel) checkmate::assert_data_frame(roster_scores) - assert_columns(roster_scores, + assert_df(roster_scores, c("pos", "pos_rank", "league_id", "franchise_id", "franchise_name", "season", "week", "projected_score")) checkmate::assert_data_frame(lineup_constraints, any.missing = FALSE) - assert_columns(lineup_constraints, c("pos", "min", "max", "offense_starters")) + assert_df(lineup_constraints, c("pos", "min", "max", "offense_starters")) if (!parallel) ffs_map <- purrr::map diff --git a/dev/sfb_rosters.rds b/dev/sfb_rosters.rds deleted file mode 100644 index e7112ff..0000000 Binary files a/dev/sfb_rosters.rds and /dev/null differ diff --git a/dev/sfb_summary_season.parquet b/dev/sfb_summary_season.parquet deleted file mode 100644 index 7996582..0000000 Binary files a/dev/sfb_summary_season.parquet and /dev/null differ diff --git a/dev/sfb_summary_simulation.parquet b/dev/sfb_summary_simulation.parquet deleted file mode 100644 index 40946fd..0000000 Binary files a/dev/sfb_summary_simulation.parquet and /dev/null differ diff --git a/inst/data/fp_injury_table.rds b/inst/data/fp_injury_table.rds new file mode 100644 index 0000000..f10a69b Binary files /dev/null and b/inst/data/fp_injury_table.rds differ diff --git a/inst/data/fp_rankings_history.rds b/inst/data/fp_rankings_history.rds new file mode 100644 index 0000000..cb5e835 Binary files /dev/null and b/inst/data/fp_rankings_history.rds differ diff --git a/inst/data/fp_rankings_history_week.rds b/inst/data/fp_rankings_history_week.rds new file mode 100644 index 0000000..f542602 Binary files /dev/null and b/inst/data/fp_rankings_history_week.rds differ diff --git a/inst/cache/adp_outcomes.rds b/inst/examples/adp_outcomes.rds similarity index 100% rename from inst/cache/adp_outcomes.rds rename to inst/examples/adp_outcomes.rds diff --git a/inst/cache/adp_outcomes_week.rds b/inst/examples/adp_outcomes_week.rds similarity index 100% rename from inst/cache/adp_outcomes_week.rds rename to inst/examples/adp_outcomes_week.rds diff --git a/inst/cache/espn_conn.rds b/inst/examples/espn_conn.rds similarity index 100% rename from inst/cache/espn_conn.rds rename to inst/examples/espn_conn.rds diff --git a/inst/cache/espn_franchises.rds b/inst/examples/espn_franchises.rds similarity index 100% rename from inst/cache/espn_franchises.rds rename to inst/examples/espn_franchises.rds diff --git a/inst/cache/espn_lineup_constraints.rds b/inst/examples/espn_lineup_constraints.rds similarity index 100% rename from inst/cache/espn_lineup_constraints.rds rename to inst/examples/espn_lineup_constraints.rds diff --git a/inst/cache/espn_rosters.rds b/inst/examples/espn_rosters.rds similarity index 100% rename from inst/cache/espn_rosters.rds rename to inst/examples/espn_rosters.rds diff --git a/inst/cache/espn_scoring_history.rds b/inst/examples/espn_scoring_history.rds similarity index 100% rename from inst/cache/espn_scoring_history.rds rename to inst/examples/espn_scoring_history.rds diff --git a/inst/cache/fleaflicker_conn.rds b/inst/examples/fleaflicker_conn.rds similarity index 100% rename from inst/cache/fleaflicker_conn.rds rename to inst/examples/fleaflicker_conn.rds diff --git a/inst/cache/fleaflicker_franchises.rds b/inst/examples/fleaflicker_franchises.rds similarity index 100% rename from inst/cache/fleaflicker_franchises.rds rename to inst/examples/fleaflicker_franchises.rds diff --git a/inst/cache/fleaflicker_lineup_constraints.rds b/inst/examples/fleaflicker_lineup_constraints.rds similarity index 100% rename from inst/cache/fleaflicker_lineup_constraints.rds rename to inst/examples/fleaflicker_lineup_constraints.rds diff --git a/inst/cache/fleaflicker_rosters.rds b/inst/examples/fleaflicker_rosters.rds similarity index 100% rename from inst/cache/fleaflicker_rosters.rds rename to inst/examples/fleaflicker_rosters.rds diff --git a/inst/cache/fleaflicker_scoring_history.rds b/inst/examples/fleaflicker_scoring_history.rds similarity index 100% rename from inst/cache/fleaflicker_scoring_history.rds rename to inst/examples/fleaflicker_scoring_history.rds diff --git a/inst/cache/foureight_sim.rds b/inst/examples/foureight_sim.rds similarity index 100% rename from inst/cache/foureight_sim.rds rename to inst/examples/foureight_sim.rds diff --git a/inst/cache/foureight_sim_week.rds b/inst/examples/foureight_sim_week.rds similarity index 100% rename from inst/cache/foureight_sim_week.rds rename to inst/examples/foureight_sim_week.rds diff --git a/inst/cache/latest_rankings.rds b/inst/examples/latest_rankings.rds similarity index 100% rename from inst/cache/latest_rankings.rds rename to inst/examples/latest_rankings.rds diff --git a/inst/cache/latest_rankings_week.rds b/inst/examples/latest_rankings_week.rds similarity index 100% rename from inst/cache/latest_rankings_week.rds rename to inst/examples/latest_rankings_week.rds diff --git a/inst/cache/mfl_conn.rds b/inst/examples/mfl_conn.rds similarity index 100% rename from inst/cache/mfl_conn.rds rename to inst/examples/mfl_conn.rds diff --git a/inst/cache/mfl_franchises.rds b/inst/examples/mfl_franchises.rds similarity index 100% rename from inst/cache/mfl_franchises.rds rename to inst/examples/mfl_franchises.rds diff --git a/inst/cache/mfl_lineup_constraints.rds b/inst/examples/mfl_lineup_constraints.rds similarity index 100% rename from inst/cache/mfl_lineup_constraints.rds rename to inst/examples/mfl_lineup_constraints.rds diff --git a/inst/cache/mfl_rosters.rds b/inst/examples/mfl_rosters.rds similarity index 100% rename from inst/cache/mfl_rosters.rds rename to inst/examples/mfl_rosters.rds diff --git a/inst/cache/mfl_scoring_history.rds b/inst/examples/mfl_scoring_history.rds similarity index 100% rename from inst/cache/mfl_scoring_history.rds rename to inst/examples/mfl_scoring_history.rds diff --git a/inst/cache/optimal_scores.rds b/inst/examples/optimal_scores.rds similarity index 100% rename from inst/cache/optimal_scores.rds rename to inst/examples/optimal_scores.rds diff --git a/inst/cache/projected_scores.rds b/inst/examples/projected_scores.rds similarity index 100% rename from inst/cache/projected_scores.rds rename to inst/examples/projected_scores.rds diff --git a/inst/cache/projected_scores_week.rds b/inst/examples/projected_scores_week.rds similarity index 100% rename from inst/cache/projected_scores_week.rds rename to inst/examples/projected_scores_week.rds diff --git a/inst/cache/roster_scores.rds b/inst/examples/roster_scores.rds similarity index 100% rename from inst/cache/roster_scores.rds rename to inst/examples/roster_scores.rds diff --git a/inst/cache/schedules.rds b/inst/examples/schedules.rds similarity index 100% rename from inst/cache/schedules.rds rename to inst/examples/schedules.rds diff --git a/inst/cache/sleeper_conn.rds b/inst/examples/sleeper_conn.rds similarity index 100% rename from inst/cache/sleeper_conn.rds rename to inst/examples/sleeper_conn.rds diff --git a/inst/cache/sleeper_franchises.rds b/inst/examples/sleeper_franchises.rds similarity index 100% rename from inst/cache/sleeper_franchises.rds rename to inst/examples/sleeper_franchises.rds diff --git a/inst/cache/sleeper_lineup_constraints.rds b/inst/examples/sleeper_lineup_constraints.rds similarity index 100% rename from inst/cache/sleeper_lineup_constraints.rds rename to inst/examples/sleeper_lineup_constraints.rds diff --git a/inst/cache/sleeper_rosters.rds b/inst/examples/sleeper_rosters.rds similarity index 100% rename from inst/cache/sleeper_rosters.rds rename to inst/examples/sleeper_rosters.rds diff --git a/inst/cache/sleeper_scoring_history.rds b/inst/examples/sleeper_scoring_history.rds similarity index 100% rename from inst/cache/sleeper_scoring_history.rds rename to inst/examples/sleeper_scoring_history.rds diff --git a/inst/update_rankings_data.R b/inst/update_rankings_data.R new file mode 100644 index 0000000..2bf5d94 --- /dev/null +++ b/inst/update_rankings_data.R @@ -0,0 +1,310 @@ +rlang::check_installed( + c("ffpros", "ffscrapr","ffsimulator", "nflreadr", + "dplyr", "purrr", "tidyr", "stringr", + "furrr", "future", "mgcv"), + action = function(pkg, ...) { + install.packages( + pkg, + repos = c("https://ffverse.r-universe.dev", getOption("repos")), + ... + ) + } +) + +library(magrittr) + +options(future.rng.onMisuse = "ignore", ffpros.cache = "filesystem") +future::plan(future::multisession) + +build_draft_rankings <- function(build_seasons = 2012:nflreadr::most_recent_season(), + directory = ffsimulator::.ffs_cache_dir()) { + + checkmate::check_numeric( + build_seasons, + lower = 2012, + upper = nflreadr::most_recent_season(), + any.missing = FALSE, + min.len = 1 + ) + + dir.create(directory, recursive = TRUE, showWarnings = FALSE) + + cli::cli_alert_info("Building {length(build_seasons)} seasons of draft rankings into directory {directory}") + + seasons <- intersect(2016:nflreadr::most_recent_season(), build_seasons) + fp_rankings_history <- tibble::tibble() + if(length(seasons) > 0 ){ + + cli::cli_alert_info("Building: {seasons}") + + pages <- c( + "qb-cheatsheets", + "ppr-rb-cheatsheets", + "ppr-wr-cheatsheets", + "ppr-te-cheatsheets", + "k-cheatsheets", + "dst-cheatsheets", + "dl-cheatsheets", + "lb-cheatsheets", + "db-cheatsheets" + ) + + fp_rankings_history <- tidyr::crossing(pages, seasons) %>% + dplyr::mutate( + rankings = furrr::future_map2(pages, seasons, + ~ ffpros::fp_rankings(page = .x, year = .y), + .progress = TRUE) + ) %>% + tidyr::unnest(rankings) %>% + dplyr::transmute( + page_pos = + stringr::str_remove_all(pages, "cheatsheets|^ppr|\\-") %>% + toupper() %>% + stringr::str_squish(), + season = seasons, + fantasypros_id = as.character(fantasypros_id), + sportradar_id, + player_name = nflreadr::clean_player_names(player_name), + pos = dplyr::case_when( + pos %in% c("CB", "S") ~ "DB", + pos %in% c("OLB", "LB") ~ "LB", + pos %in% c("DE", "DT", "NT") ~ "DL", + TRUE ~ pos + ), + team, + rank, + ecr, + sd + ) %>% + dplyr::filter(page_pos == pos) + } + + seasons2 <- intersect(2012:2015, build_seasons) + fp_rankings_history2 <- tibble::tibble() + if(length(seasons2) > 0) { + + cli::cli_alert_info("Building {seasons2} (no IDP or PPR available)") + pages2 <- c( + "qb-cheatsheets", + "rb-cheatsheets", + "wr-cheatsheets", + "te-cheatsheets", + "k-cheatsheets", + "dst-cheatsheets" + ) + + fp_rankings_history2 <- tidyr::crossing(pages2, seasons2) %>% + dplyr::mutate( + rankings = furrr::future_map2(pages2, seasons2, + ~ ffpros::fp_rankings(page = .x, year = .y), + .progress = TRUE) + ) %>% + tidyr::unnest(rankings) %>% + dplyr::transmute( + page_pos = + stringr::str_remove_all(pages2, "cheatsheets|^ppr|\\-") %>% + toupper() %>% + stringr::str_squish(), + season = seasons2, + fantasypros_id = as.character(fantasypros_id), + sportradar_id, + player_name = nflreadr::clean_player_names(player_name), + pos, + team, + rank, + ecr, + sd + ) %>% + dplyr::filter(page_pos == pos) + } + + fp_rankings_history <- bind_rows(fp_rankings_history2, fp_rankings_history) + + if(nrow(fp_rankings_history) == 0) { + cli::cli_abort("No rows from scrape - something went wrong!") + } + saveRDS(fp_rankings_history, file = file.path(directory, "fp_rankings_history.rds")) + + cli::cli_alert_success("Completed draft rankings history") + invisible(file.path(directory, "fp_rankings_history.rds")) +} + +build_weekly_rankings <- function(build_seasons = 2012:nflreadr::most_recent_season(), + directory = ffsimulator::.ffs_cache_dir()){ + checkmate::check_numeric( + build_seasons, + lower = 2012, + upper = nflreadr::most_recent_season(), + any.missing = FALSE, + min.len = 1 + ) + + dir.create(directory, recursive = TRUE, showWarnings = FALSE) + weeks <- 1:16 + + cli::cli_alert_info("Building {length(build_seasons)} seasons of inseason weekly rankings into directory {directory}") + + seasons <- intersect(2012:2015, build_seasons) + fp_rankings_history <- tibble::tibble() + if (length(seasons) > 0) { + cli::cli_alert_info("Building {seasons}") + pages <- c( + "qb", + "rb", + "wr", + "te", + "k", + "dst", + "dl", + "lb", + "db" + ) + fp_rankings_history <- tidyr::crossing(pages, seasons, weeks) %>% + dplyr::mutate( + rankings = furrr::future_pmap( + list(pages, seasons, weeks), + ~ ffpros::fp_rankings(page = ..1, year = ..2, week = ..3), + .progress = TRUE + ) + ) %>% + tidyr::unnest(rankings) %>% + dplyr::transmute( + page_pos = + stringr::str_remove_all(pages, "cheatsheets|^ppr|\\-") %>% + toupper() %>% + stringr::str_squish(), + season = seasons, + week = weeks, + fantasypros_id = as.character(fantasypros_id), + sportradar_id, + player_name = nflreadr::clean_player_names(player_name), + pos = dplyr::case_when( + pos %in% c("CB", "S") ~ "DB", + pos %in% c("OLB", "LB") ~ "LB", + pos %in% c("DE", "DT", "NT") ~ "DL", + TRUE ~ pos + ), + team, + rank, + ecr, + sd + ) %>% + dplyr::filter(page_pos == pos) + } + + seasons2 <- intersect(2016:nflreadr::most_recent_season(), build_seasons) + fp_rankings_history2 <- tibble::tibble() + if(length(seasons2) > 0) { + cli::cli_alert_info("Building {seasons2}") + pages2 <- c( + "qb", + "ppr-rb", + "ppr-wr", + "ppr-te", + "k", + "dst", + "dl", + "lb", + "db" + ) + + fp_rankings_history2 <- tidyr::crossing(pages2, seasons2, weeks) %>% + dplyr::mutate( + rankings = furrr::future_pmap( + list(pages2, seasons2, weeks), + ~ ffpros::fp_rankings(page = ..1, year = ..2, week = ..3), + .progress = TRUE + ) + ) %>% + tidyr::unnest(rankings) %>% + dplyr::transmute( + page_pos = + stringr::str_remove_all(pages2, "cheatsheets|^ppr|\\-") %>% + toupper() %>% + stringr::str_squish(), + season = seasons2, + week = weeks, + fantasypros_id = as.character(fantasypros_id), + sportradar_id, + player_name = nflreadr::clean_player_names(player_name), + pos, + team, + rank, + ecr, + sd + ) %>% + dplyr::filter(page_pos == pos) + } + + fp_rankings_history_week <- dplyr::bind_rows(fp_rankings_history, fp_rankings_history2) + + saveRDS(fp_rankings_history_week, file.path(directory, "fp_rankings_history_week.rds")) + cli::cli_alert_success("Completed inseason weekly rankings history") + invisible(file.path(directory, "fp_rankings_history_week.rds")) +} + +build_injury_model <- function(base_seasons = seq(2012, nflreadr::most_recent_season()), + directory = ffsimulator::.ffs_cache_dir()) { + checkmate::check_numeric( + base_seasons, + lower = 2012, + upper = nflreadr::most_recent_season(), + any.missing = FALSE, + min.len = 1 + ) + + dir.create(directory, recursive = TRUE, showWarnings = FALSE) + + conn <- ffscrapr::mfl_connect(2021, 47747) + cli::cli_alert_info("Retrieving ") + scoring_history <- ffscrapr::ff_scoringhistory(conn, base_seasons) + model_gam <- function(data) mgcv::gam(games_played_rate ~ mgcv::s(rank, bs = "cs"), data = data) + + fp_injury_table <- ffsimulator::fp_rankings_history() %>% + dplyr::select(-"page_pos") %>% + dplyr::left_join( + ffscrapr::dp_playerids() %>% + dplyr::select("fantasypros_id", "gsis_id"), + by = "fantasypros_id" + ) %>% + dplyr::filter(!is.na(.data$gsis_id), pos %in% c("QB", "RB", "WR", "TE", "K")) %>% + dplyr::left_join( + scoring_history %>% + dplyr::filter(!is.na(.data$gsis_id), .data$week <= 17) %>% + dplyr::select("season", "gsis_id", "team", "points"), + by = c("season", "gsis_id") + ) %>% + dplyr::group_by( + .data$season, + .data$pos, + .data$rank, + .data$fantasypros_id, + .data$player_name + ) %>% + dplyr::summarise( + week_outcomes = list(points), + games_played = dplyr::n(), + games_missed = 16 - games_played, + games_played_rate = games_played / 16 + ) %>% + dplyr::ungroup() %>% + dplyr::group_by(pos) %>% + tidyr::nest() %>% + dplyr::mutate( + model = purrr::map(data, model_gam), + prob_gp = purrr::map2(model, data, ~ as.numeric(stats::predict(.x, new_data = .y))), + model = NULL + ) %>% + dplyr::ungroup() %>% + tidyr::unnest(c(data, prob_gp)) %>% + dplyr::distinct(pos, rank, prob_gp) %>% + dplyr::arrange(pos, rank) + + saveRDS(fp_injury_table, file.path(directory, "fp_injury_table.rds")) + cli::cli_alert_success("Completed injury model recalculation") + invisible(file.path(directory, "fp_injury_table.rds")) +} + +build_draft_rankings(2012:nflreadr::most_recent_season()) +build_weekly_rankings(2012:nflreadr::most_recent_season()) +build_injury_model(2012:nflreadr::most_recent_season()) diff --git a/man/assert_columns.Rd b/man/assert_df.Rd similarity index 52% rename from man/assert_columns.Rd rename to man/assert_df.Rd index 15be15d..0a289f4 100644 --- a/man/assert_columns.Rd +++ b/man/assert_df.Rd @@ -1,20 +1,22 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/utils-assert.R -\name{assert_columns} -\alias{assert_columns} -\title{Check that dataframe has x column names} +\name{assert_df} +\alias{assert_df} +\title{Check that df has x column names} \usage{ -assert_columns(dataframe, required_columns) +assert_df(df, required_columns, .env = rlang::caller_env()) } \arguments{ -\item{dataframe}{dataframe to check} +\item{df}{df to check} \item{required_columns}{required column names} + +\item{.env}{caller environment to complain from} } \value{ silent if ok or else an error if something is missing. } \description{ -Check that dataframe has x column names +Check that df has x column names } \keyword{internal} diff --git a/man/autoplot.ff_simulation.Rd b/man/autoplot.ff_simulation.Rd index efb0700..d5a3943 100644 --- a/man/autoplot.ff_simulation.Rd +++ b/man/autoplot.ff_simulation.Rd @@ -32,7 +32,7 @@ Usage of this function/method requires the ggplot2 package and (for wins and poi \examples{ \donttest{ -simulation <- .ffs_cache("foureight_sim.rds") +simulation <- .ffs_cache_example("foureight_sim.rds") ggplot2::autoplot(simulation) # default is type = "wins" ggplot2::autoplot(simulation, type = "rank") diff --git a/man/autoplot.ff_simulation_week.Rd b/man/autoplot.ff_simulation_week.Rd index 8eda972..b57248b 100644 --- a/man/autoplot.ff_simulation_week.Rd +++ b/man/autoplot.ff_simulation_week.Rd @@ -32,7 +32,7 @@ Usage of this function/method requires the ggplot2 package and (for wins and poi \examples{ \donttest{ -simulation <- .ffs_cache("foureight_sim_week.rds") +simulation <- .ffs_cache_example("foureight_sim_week.rds") ggplot2::autoplot(simulation) # default is type = "luck" ggplot2::autoplot(simulation, type = "points") diff --git a/man/data-cache.Rd b/man/data-cache.Rd new file mode 100644 index 0000000..4dd76dc --- /dev/null +++ b/man/data-cache.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils-data.R +\name{.ffs_read_data} +\alias{.ffs_read_data} +\alias{.ffs_cache_dir} +\title{Read data from cache or pkg data} +\usage{ +.ffs_read_data(file_name, .env = rlang::caller_env()) + +.ffs_cache_dir(...) +} +\arguments{ +\item{file_name}{filename to find} + +\item{.env}{for internal use in error messages} +} +\description{ +Read data from cache or pkg data +} diff --git a/man/dot-ffs_cache_example.Rd b/man/dot-ffs_cache_example.Rd new file mode 100644 index 0000000..3b5fca2 --- /dev/null +++ b/man/dot-ffs_cache_example.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{.ffs_cache_example} +\alias{.ffs_cache_example} +\title{Access cached function data} +\usage{ +.ffs_cache_example(filename) +} +\description{ +Access cached function data +} +\keyword{internal} diff --git a/man/ff_wins_added.Rd b/man/ff_wins_added.Rd index 0b244cb..9f4e1d7 100644 --- a/man/ff_wins_added.Rd +++ b/man/ff_wins_added.Rd @@ -46,7 +46,7 @@ Summarise wins added as the difference between the sim with the player and the s \donttest{ try({ # try block to prevent CRAN-related issues # n_seasons set so that the example runs more quickly -ff_wins_added(mfl_connect(2021,54040), n_seasons = 5) +ff_wins_added(mfl_connect(2021, 54040), n_seasons = 5) }) } diff --git a/man/ffs_add_replacement_level.Rd b/man/ffs_add_replacement_level.Rd index ab76717..1674b19 100644 --- a/man/ffs_add_replacement_level.Rd +++ b/man/ffs_add_replacement_level.Rd @@ -27,5 +27,7 @@ ffs_add_replacement_level( a dataframe of rosters with replacements } \description{ -Add replacement level players to each roster +Adds the same N free-agent starters to each roster to represent being able to +churn the waiver wire for starters, where N is the maximum number of players +that could start in a given position } diff --git a/man/ffs_adp_outcomes.Rd b/man/ffs_adp_outcomes.Rd index a9f8b2f..7c32c9b 100644 --- a/man/ffs_adp_outcomes.Rd +++ b/man/ffs_adp_outcomes.Rd @@ -21,12 +21,12 @@ ffs_adp_outcomes( a dataframe with position, rank, probability of games played, and a corresponding nested list per row of all week score outcomes. } \description{ -The backbone of the ffsimulator resampling process is coming up with a population of weekly outcomes for every preseason positional rank. This function creates that dataframe by connecting historical FantasyPros.com rankings to nflfastR-based scoring data, as created by \code{ffscrapr::ff_scoringhistory()}. +The backbone of the ffsimulator resampling process is coming up with a population of weekly outcomes for every preseason positional rank. This function creates that dataframe by connecting historical FantasyPros.com rankings to nflverse-based scoring data, as created by \code{ffscrapr::ff_scoringhistory()}. } \examples{ \donttest{ # cached data -scoring_history <- .ffs_cache("mfl_scoring_history.rds") +scoring_history <- .ffs_cache_example("mfl_scoring_history.rds") ffs_adp_outcomes(scoring_history, gp_model = "simple") ffs_adp_outcomes(scoring_history, gp_model = "none") diff --git a/man/ffs_adp_outcomes_week.Rd b/man/ffs_adp_outcomes_week.Rd index 449cb84..605747e 100644 --- a/man/ffs_adp_outcomes_week.Rd +++ b/man/ffs_adp_outcomes_week.Rd @@ -20,8 +20,8 @@ The backbone of the ffsimulator resampling process is coming up with a populatio \examples{ \donttest{ # cached data -scoring_history <- .ffs_cache("mfl_scoring_history.rds") -ffs_adp_outcomes_week(scoring_history, pos_filter = c("QB","RB","WR","TE")) +scoring_history <- .ffs_cache_example("mfl_scoring_history.rds") +ffs_adp_outcomes_week(scoring_history, pos_filter = c("QB", "RB", "WR", "TE")) } } diff --git a/man/ffs_copy_template.Rd b/man/ffs_copy_template.Rd index 608adfe..f56f90a 100644 --- a/man/ffs_copy_template.Rd +++ b/man/ffs_copy_template.Rd @@ -5,16 +5,16 @@ \title{Copy simulation template to filename} \usage{ ffs_copy_template( - filename = "ff_simulation.R", - template = c("season", "week"), + template = c("season", "week", "rankings_update"), + filename = glue::glue("ff_simulator_{template}.R"), overwrite = NULL ) } \arguments{ -\item{filename}{New file name, defaults to putting "ff_simulation.R" into your current directory} - \item{template}{choice of template: one of "season" or "week"} +\item{filename}{New file name, defaults to putting "ff_simulation.R" into your current directory} + \item{overwrite}{a logical (or NULL) - overwrite if existing file found?} } \value{ diff --git a/man/ffs_franchises.Rd b/man/ffs_franchises.Rd index 0b9f592..16d9bf4 100644 --- a/man/ffs_franchises.Rd +++ b/man/ffs_franchises.Rd @@ -18,7 +18,7 @@ This function lightly wraps \code{ffscrapr::ff_franchises()} and adds league_id, \examples{ \donttest{ # cached examples -conn <- .ffs_cache("mfl_conn.rds") +conn <- .ffs_cache_example("mfl_conn.rds") try({ # prevents CRAN connectivity issues, not actually required in normal usage ffs_franchises(conn) diff --git a/man/ffs_generate_projections.Rd b/man/ffs_generate_projections.Rd index 41d680b..296612a 100644 --- a/man/ffs_generate_projections.Rd +++ b/man/ffs_generate_projections.Rd @@ -32,8 +32,8 @@ Runs the bootstrapped resampling of player week outcomes on the latest rankings \examples{ \donttest{ # cached examples -adp_outcomes <- .ffs_cache("adp_outcomes.rds") -latest_rankings <- .ffs_cache("latest_rankings.rds") +adp_outcomes <- .ffs_cache_example("adp_outcomes.rds") +latest_rankings <- .ffs_cache_example("latest_rankings.rds") ffs_generate_projections(adp_outcomes, latest_rankings) } diff --git a/man/ffs_generate_projections_week.Rd b/man/ffs_generate_projections_week.Rd index 6f12955..236b0c1 100644 --- a/man/ffs_generate_projections_week.Rd +++ b/man/ffs_generate_projections_week.Rd @@ -29,8 +29,8 @@ Runs the bootstrapped resampling of player week outcomes on the latest rankings \examples{ \donttest{ # cached examples -adp_outcomes_week <- .ffs_cache("adp_outcomes_week.rds") -latest_rankings_week <- .ffs_cache("latest_rankings_week.rds") +adp_outcomes_week <- .ffs_cache_example("adp_outcomes_week.rds") +latest_rankings_week <- .ffs_cache_example("latest_rankings_week.rds") ffs_generate_projections_week(adp_outcomes_week, latest_rankings_week) } diff --git a/man/ffs_optimise_lineups.Rd b/man/ffs_optimise_lineups.Rd index 51c4222..fb7a3ce 100644 --- a/man/ffs_optimise_lineups.Rd +++ b/man/ffs_optimise_lineups.Rd @@ -48,8 +48,8 @@ Lineup efficiency is the percentage of optimal/best-ball score that is used as t \examples{ \donttest{ # cached examples -roster_scores <- .ffs_cache("roster_scores.rds") -lineup_constraints <- .ffs_cache("mfl_lineup_constraints.rds") +roster_scores <- .ffs_cache_example("roster_scores.rds") +lineup_constraints <- .ffs_cache_example("mfl_lineup_constraints.rds") ffs_optimise_lineups(roster_scores, lineup_constraints) } diff --git a/man/ffs_repeat_schedules.Rd b/man/ffs_repeat_schedules.Rd index 877844b..69337fd 100644 --- a/man/ffs_repeat_schedules.Rd +++ b/man/ffs_repeat_schedules.Rd @@ -20,7 +20,7 @@ This function repeats an actual \code{ffs_schedule()} by the appropriate number \examples{ \donttest{ try({ # try block to prevent CRAN-related issues -conn <- .ffs_cache("mfl_conn.rds") # cached connection +conn <- .ffs_cache_example("mfl_conn.rds") # cached connection actual_schedule <- ffs_schedule(conn) ffs_repeat_schedules(actual_schedule = actual_schedule, n_seasons = 10) diff --git a/man/ffs_rosters.Rd b/man/ffs_rosters.Rd index 2309e49..962c5ed 100644 --- a/man/ffs_rosters.Rd +++ b/man/ffs_rosters.Rd @@ -30,7 +30,7 @@ This function lightly wraps \code{ffscrapr::ff_rosters()} and adds fantasypros_i \examples{ \donttest{ # cached examples -conn <- .ffs_cache("mfl_conn.rds") +conn <- .ffs_cache_example("mfl_conn.rds") try({ # prevents CRAN connectivity issues, not actually required in normal usage ffs_rosters(conn) diff --git a/man/ffs_schedule.Rd b/man/ffs_schedule.Rd index cfb4ea4..b71c913 100644 --- a/man/ffs_schedule.Rd +++ b/man/ffs_schedule.Rd @@ -19,7 +19,7 @@ This function lightly wraps \code{ffscrapr::ff_schedule()} and adds league_id, w \donttest{ # cached examples try({ # try block to prevent CRAN-related issues -conn <- .ffs_cache("mfl_conn.rds") +conn <- .ffs_cache_example("mfl_conn.rds") ffs_schedule(conn) }) } diff --git a/man/ffs_score_rosters.Rd b/man/ffs_score_rosters.Rd index 0a54a84..5ad48d1 100644 --- a/man/ffs_score_rosters.Rd +++ b/man/ffs_score_rosters.Rd @@ -20,8 +20,8 @@ Attaches projected scores to rosters (via an inner-join) and creates a positiona \examples{ \donttest{ # cached examples -projected_scores <- .ffs_cache("projected_scores.rds") -rosters <- .ffs_cache("mfl_rosters.rds") +projected_scores <- .ffs_cache_example("projected_scores.rds") +rosters <- .ffs_cache_example("mfl_rosters.rds") ffs_score_rosters(projected_scores, rosters) } diff --git a/man/ffs_starter_positions.Rd b/man/ffs_starter_positions.Rd index 05f3069..3bdcc8a 100644 --- a/man/ffs_starter_positions.Rd +++ b/man/ffs_starter_positions.Rd @@ -19,7 +19,7 @@ This function lightly wraps \code{ffscrapr::ff_starter_positions()} and cleans u \donttest{ # cached examples try({ # try block to prevent CRAN-related issues -conn <- .ffs_cache("mfl_conn.rds") +conn <- .ffs_cache_example("mfl_conn.rds") ffs_starter_positions(conn) }) } diff --git a/man/ffs_summaries.Rd b/man/ffs_summaries.Rd index dbf4291..06a3a95 100644 --- a/man/ffs_summaries.Rd +++ b/man/ffs_summaries.Rd @@ -50,8 +50,8 @@ These functions are used to summarise the simulation outputs, typically by joini \examples{ \donttest{ # cached examples -optimal_scores <- .ffs_cache("optimal_scores.rds") -schedules <- .ffs_cache("schedules.rds") +optimal_scores <- .ffs_cache_example("optimal_scores.rds") +schedules <- .ffs_cache_example("schedules.rds") summary_week <- ffs_summarise_week(optimal_scores, schedules) summary_week diff --git a/man/ffsimulator-package.Rd b/man/ffsimulator-package.Rd index 2bc861c..baf5e34 100644 --- a/man/ffsimulator-package.Rd +++ b/man/ffsimulator-package.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R +% Please edit documentation in R/ffsimulator-package.R \docType{package} \name{ffsimulator-package} \alias{ffsimulator} @@ -8,7 +8,7 @@ \description{ \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} -Uses bootstrap resampling to run fantasy football season simulations supported by historical rankings and 'nflfastR' data, calculating optimal lineups, and returning aggregated results. +Uses bootstrap resampling to run fantasy football season simulations supported by historical 'FantasyPros' rankings and 'nflverse' data, calculating optimal lineups, and returning aggregated results. } \seealso{ Useful links: diff --git a/man/fp_injury_table.Rd b/man/fp_injury_table.Rd index 177c042..8feffda 100644 --- a/man/fp_injury_table.Rd +++ b/man/fp_injury_table.Rd @@ -1,16 +1,24 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/utils-data.R -\docType{data} \name{fp_injury_table} \alias{fp_injury_table} \title{FP injury table} -\format{ -An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 692 rows and 3 columns. -} \usage{ -fp_injury_table +fp_injury_table() +} +\value{ +dataframe of injury probability by position rank } \description{ -This dataframe contains a column (\code{prob_gp}) for each positional ranking that describes the probability of a player with that preseason ADP playing in a given game. It is modelled from historical rankings data and the number of games played per season for a given positional rank. +This dataframe contains a column (\code{prob_gp}) for each positional ranking that +describes the probability of a player with that preseason ADP playing in a +given game. It is modelled from historical rankings data and the number of +games played per season for a given positional rank. +} +\details{ +By default, it returns bundled package data unless the \code{ffsimulator.cache_directory} +option is configured, in which case it will look for a rds file named +\code{fp_injury_table.rds} in that directory. + +To update, use \code{ffs_copy_template("rankings_update")} to find the bundled update script } -\keyword{datasets} diff --git a/man/fp_rankings_history.Rd b/man/fp_rankings_history.Rd index f54adc4..c6c71c4 100644 --- a/man/fp_rankings_history.Rd +++ b/man/fp_rankings_history.Rd @@ -1,16 +1,22 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/utils-data.R -\docType{data} \name{fp_rankings_history} \alias{fp_rankings_history} \title{Historical draft position ranks} -\format{ -An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 11336 rows and 10 columns. -} \usage{ -fp_rankings_history +fp_rankings_history() +} +\value{ +dataframe of preseason/draft rankings from ffpros } \description{ -This dataframe has historical positional draft rankings for 2012-2020 QB/RB/WR/TE/PK and 2015-2020 DL/LB/DB, as gathered by the ffpros package. +This dataframe has historical positional draft rankings starting in 2012 for +QB/RB/WR/TE/PK and 2015 DL/LB/DB, as gathered by the ffpros package. +} +\details{ +By default, it returns bundled package data unless the \code{ffsimulator.cache_directory} +option is configured, in which case it will look for a rds file named +\code{fp_rankings_history.rds} in that directory. + +To update, use \code{ffs_copy_template("rankings_update")} to find the bundled update script } -\keyword{datasets} diff --git a/man/fp_rankings_history_week.Rd b/man/fp_rankings_history_week.Rd index 3e67388..3cbbc5e 100644 --- a/man/fp_rankings_history_week.Rd +++ b/man/fp_rankings_history_week.Rd @@ -1,16 +1,22 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/utils-data.R -\docType{data} \name{fp_rankings_history_week} \alias{fp_rankings_history_week} \title{Historical position ranks} -\format{ -An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 94257 rows and 11 columns. -} \usage{ -fp_rankings_history_week +fp_rankings_history_week() +} +\value{ +dataframe of in-season positional rankings } \description{ -This dataframe has historical positional in-season rankings for 2012-2020 QB/RB/WR/TE/PK and 2015-2020 DL/LB/DB, as gathered by the ffpros package. +This dataframe has historical positional in-season rankings starting in 2012 for +QB/RB/WR/TE/PK and 2015 for DL/LB/DB, as gathered by the ffpros package. +} +\details{ +By default, it returns bundled package data unless the \code{ffsimulator.cache_directory} +option is configured, in which case it will look for a rds file named +\code{fp_rankings_history_week.rds} in that directory. + +To update, use \code{ffs_copy_template("rankings_update")} to find the bundled update script } -\keyword{datasets} diff --git a/man/pipe.Rd b/man/pipe.Rd deleted file mode 100644 index 5fa90fe..0000000 --- a/man/pipe.Rd +++ /dev/null @@ -1,20 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R -\name{\%>\%} -\alias{\%>\%} -\title{Pipe operator} -\usage{ -lhs \%>\% rhs -} -\arguments{ -\item{lhs}{A value or the magrittr placeholder.} - -\item{rhs}{A function call using the magrittr semantics.} -} -\value{ -The result of calling \code{rhs(lhs)}. -} -\description{ -See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. -} -\keyword{internal} diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index e9aacf0..a7d5f17 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -11,10 +11,10 @@ reference: - "ff_simulate_week" - "plot.ff_simulation_week" - "ff_wins_added" - - "ffs_copy_template" - title: Customized Simulations - desc: Subfunctions used by ff_simulate + desc: Useful subfunctions for running your own simulation scripts contents: + - "ffs_copy_template" - "ffs_adp_outcomes" - "ffs_adp_outcomes_week" - "ffs_latest_rankings" @@ -30,6 +30,13 @@ reference: - "ffs_schedule" - "ffs_repeat_schedules" - starts_with("ffs_summarise") +- title: ffpros Rankings + desc: Core rankings data used to power ffsimulator + contents: + - "fp_rankings_history" + - "fp_injury_table" + - "fp_rankings_history_week" + - "data-cache" - title: ffscrapr Imports desc: Functions imported from ffscrapr contents: @@ -38,9 +45,6 @@ reference: desc: Additional helper functions and data contents: - "`%>%`" - - "fp_rankings_history" - - "fp_injury_table" - - "fp_rankings_history_week" authors: Tan Ho: @@ -50,7 +54,7 @@ home: title: ffsimulator • Simulate Fantasy Football Seasons description: > An R package that helps simulate fantasy football seasons, - using nflfastR data and FantasyPros rankings. + using nflverse data and FantasyPros rankings. navbar: bg: dark @@ -74,26 +78,17 @@ navbar: href: https://www.github.com/ffverse - text: ------- - text: "nflverse" - - text: nflfastR package - href: https://www.nflfastr.com - text: nflverse GitHub href: https://github.com/nflverse - - text: ------- - - text: "DynastyProcess.com" - href: https://dynastyprocess.com template: bootstrap: 5 params: bootswatch: zephyr - # docsearch: - # api_key: 7abddd2aa591d955b365235f35d75a38 - # index_name: dynastyprocess opengraph: image: src: "https://ffsimulator.ffverse.com/reference/figures/logo.png" alt: "ffsimulator - An R Package For Simulating Fantasy Football Seasons" twitter: creator: "@_TanHo" - site: "@DynastyProcess" card: summary diff --git a/tests/testthat/test-ffs_autoplot.R b/tests/testthat/test-ffs_autoplot.R index 60b1e69..8a1c973 100644 --- a/tests/testthat/test-ffs_autoplot.R +++ b/tests/testthat/test-ffs_autoplot.R @@ -1,7 +1,6 @@ - test_that("autoplot works", { - foureight_sim <- .ffs_cache("foureight_sim.rds") - foureight_sim_week <- .ffs_cache("foureight_sim_week.rds") + foureight_sim <- .ffs_cache_example("foureight_sim.rds") + foureight_sim_week <- .ffs_cache_example("foureight_sim_week.rds") wins <- plot(foureight_sim, type = "wins") rank <- plot(foureight_sim, type = "rank") diff --git a/tests/testthat/test-ffs_components.R b/tests/testthat/test-ffs_components.R index 1e87415..ff83cb5 100644 --- a/tests/testthat/test-ffs_components.R +++ b/tests/testthat/test-ffs_components.R @@ -1,6 +1,5 @@ - -cache_names <- list.files(system.file("cache", package = "ffsimulator")) -cache <- lapply(cache_names, .ffs_cache) +cache_names <- list.files(system.file("examples", package = "ffsimulator")) +cache <- lapply(cache_names, .ffs_cache_example) cache_names <- gsub(pattern = "\\.rds$", replacement = "", x = cache_names) names(cache) <- cache_names @@ -17,7 +16,7 @@ test_that("ffs_adp_outcomes() works for both the simple and none injury models", adp_outcomes_week <- ffs_adp_outcomes_week( scoring_history = cache$mfl_scoring_history, - pos_filter = c("QB","RB","WR","TE") + pos_filter = c("QB", "RB", "WR", "TE") ) checkmate::expect_data_frame(adp_outcomes, min.rows = 500) @@ -69,7 +68,7 @@ test_that("ffs_generate_projections() returns a tibble and specific columns", { ) }) -test_that("ffs_add_replacement_level() works",{ +test_that("ffs_add_replacement_level() works", { rosters_rl <- ffs_add_replacement_level( rosters = cache$mfl_rosters, @@ -79,7 +78,7 @@ test_that("ffs_add_replacement_level() works",{ ) rosters <- cache$mfl_rosters - checkmate::expect_data_frame(rosters_rl, min.rows = nrow(rosters)+12) + checkmate::expect_data_frame(rosters_rl, min.rows = nrow(rosters) + 12) }) @@ -176,7 +175,7 @@ test_that("summary functions return tibbles", { "season", "week", "franchise_name", "optimal_score", "lineup_efficiency", "team_score", "opponent_score", "result", "opponent_name", "allplay_wins", "allplay_games", "allplay_pct", - "franchise_id", "optimal_player_id", "optimal_player_score","league_id" + "franchise_id", "optimal_player_id", "optimal_player_score", "league_id" ), names(summary_week), label = "summary_week names check" @@ -184,7 +183,7 @@ test_that("summary functions return tibbles", { checkmate::expect_subset( c( - "season","league_id", "franchise_id", "franchise_name", "h2h_wins", "h2h_winpct", + "season", "league_id", "franchise_id", "franchise_name", "h2h_wins", "h2h_winpct", "allplay_wins", "allplay_games", "allplay_winpct", "points_for", "points_against", "potential_points" ), diff --git a/tests/testthat/test-integration.R b/tests/testthat/test-integration.R index 2d8f64b..0676f62 100644 --- a/tests/testthat/test-integration.R +++ b/tests/testthat/test-integration.R @@ -3,10 +3,10 @@ test_that("MFL simulation works", { foureight <- mfl_connect(2021, 22627, user_agent = "asdf23409lkjsafd") foureight_sim <- ff_simulate(foureight, n_seasons = 2) - week_sim <- ff_simulate_week(foureight,n = 10, verbose = FALSE, actual_schedule = FALSE) + week_sim <- ff_simulate_week(foureight, n = 10, verbose = FALSE, actual_schedule = FALSE) checkmate::expect_list(foureight_sim, len = 7) - checkmate::expect_list(week_sim,len = 6) + checkmate::expect_list(week_sim, len = 6) checkmate::expect_data_frame(week_sim$summary_week, nrows = 120, any.missing = FALSE) checkmate::expect_data_frame(foureight_sim$summary_simulation, nrows = 12, any.missing = FALSE) checkmate::expect_data_frame(foureight_sim$summary_season, nrows = 24, any.missing = FALSE) @@ -66,9 +66,9 @@ test_that("Actual Schedule - completed_season = no sim", { checkmate::expect_list(ssb_sim, len = 3) }) -test_that("wins added works",{ +test_that("wins added works", { skip_on_cran() - ssb <- mfl_connect(2021,54040) + ssb <- mfl_connect(2021, 54040) ssb_wa <- ff_wins_added(ssb, n_seasons = 2) checkmate::expect_list(ssb_wa, len = 15) diff --git a/vignettes/basic.Rmd b/vignettes/basic.Rmd index 416662c..7946820 100644 --- a/vignettes/basic.Rmd +++ b/vignettes/basic.Rmd @@ -39,7 +39,7 @@ foureight_sim <- ff_simulate(conn = foureight_conn, n_seasons = 10, n_weeks = 14 foureight_sim ``` ```{r echo = FALSE, message = FALSE} -foureight_sim <- readRDS(system.file("cache/foureight_sim.rds", package = "ffsimulator")) +foureight_sim <- .ffs_cache_example("foureight_sim.rds") foureight_sim ``` ffsimulator includes a few automatic plots that can be run on this ff_simulation object to get a quick sense of the simulation output: @@ -88,7 +88,7 @@ foureight_sim_week <- ff_simulate_week(conn = foureight_conn, n = 10) foureight_sim_week ``` ```{r echo = FALSE} -foureight_sim_week <- .ffs_cache("foureight_sim_week.rds") +foureight_sim_week <- .ffs_cache_example("foureight_sim_week.rds") foureight_sim_week ``` @@ -97,7 +97,7 @@ This simulation object has many of the same dataframes, including a summary_simu It also has some different automatic plots, including one for schedule luck: ```{r} -plot(foureight_sim_week,type = "luck") +plot(foureight_sim_week, type = "luck") ``` and the usual points distribution: diff --git a/vignettes/custom.Rmd b/vignettes/custom.Rmd index b85c72d..d73e827 100644 --- a/vignettes/custom.Rmd +++ b/vignettes/custom.Rmd @@ -85,7 +85,7 @@ This brings in league information that is primarily used for plot names. adp_outcomes <- ffs_adp_outcomes( scoring_history = scoring_history, gp_model = "simple", # or "none" - pos_filter = c("QB","RB","WR","TE","K") + pos_filter = c("QB", "RB", "WR", "TE", "K") ) ``` @@ -123,7 +123,7 @@ optimal_scores <- ffs_optimise_lineups( lineup_efficiency_mean = 0.775, lineup_efficiency_sd = 0.05, best_ball = FALSE, # or TRUE - pos_filter = c("QB","RB","WR","TE","K") + pos_filter = c("QB", "RB", "WR", "TE", "K") ) ``` @@ -138,7 +138,7 @@ There are options to use parallel processing - in my experience, 100 seasons of In order to calculate head to head wins, you need a schedule! Enter `ffs_build_schedules()`: ```{r eval = FALSE} - schedules <- ffs_build_schedules( +schedules <- ffs_build_schedules( n_seasons = n_seasons, n_weeks = n_weeks, seed = NULL, @@ -187,7 +187,7 @@ league_info <- ffscrapr::ff_league(conn) scoring_history <- ffscrapr::ff_scoringhistory(conn, 2012:2020) -adp_outcomes <- ffs_adp_outcomes(scoring_history = scoring_history, gp_model = "simple",pos_filter = c("QB","RB","WR","TE","K")) +adp_outcomes <- ffs_adp_outcomes(scoring_history = scoring_history, gp_model = "simple", pos_filter = c("QB", "RB", "WR", "TE", "K")) latest_rankings <- ffs_latest_rankings() lineup_constraints <- ffs_starter_positions(conn) @@ -199,17 +199,17 @@ We can use one league ID here to grab most of the historical scoring data and ru conn2 <- mfl_connect(2021) leagues <- mfl_getendpoint(conn2, "leagueSearch", SEARCH = "#SFB11") %>% - pluck("content","leagues","league") %>% + pluck("content", "leagues", "league") %>% tibble() %>% unnest_wider(1) %>% - filter(str_detect(name,"Mock|Copy|Satellite|Template",negate = TRUE)) + filter(str_detect(name, "Mock|Copy|Satellite|Template", negate = TRUE)) -get_rosters <- function(league_id){ +get_rosters <- function(league_id) { mfl_connect(2021, league_id) %>% ffs_rosters() } -get_franchises <- function(league_id){ +get_franchises <- function(league_id) { mfl_connect(2021, league_id) %>% ff_franchises() } @@ -229,7 +229,7 @@ franchises <- rosters_raw %>% rosters <- rosters_raw %>% select(rosters) %>% unnest(rosters) %>% - left_join(franchises,by = c("league_id","franchise_id")) + left_join(franchises, by = c("league_id", "franchise_id")) ``` Because SFB is spread over multiple league IDs, we need to get a list of IDs from the leagueSearch endpoint, map over them with the get_rosters and get_franchises helper functions we just defined, and attach the division name. @@ -251,7 +251,7 @@ tictoc::tic("ffs_optimize_lineups {Sys.time()}") optimal_scores <- ffs_optimize_lineups( roster_scores = roster_scores, lineup_constraints = lineup_constraints, - pos_filter = c("QB","RB","WR","TE","K"), + pos_filter = c("QB", "RB", "WR", "TE", "K"), best_ball = FALSE) tictoc::toc() ```