Skip to content

Instantly share code, notes, and snippets.

@k5cents
Created February 1, 2025 01:17
Show Gist options
  • Save k5cents/0d24bc8a1732db18c0b6de9921f2971f to your computer and use it in GitHub Desktop.
Save k5cents/0d24bc8a1732db18c0b6de9921f2971f to your computer and use it in GitHub Desktop.
Fantasy Football Scoreboard
library(httr2)
library(tibble)
library(jsonlite)
# config ------------------------------------------------------------------
league_id <- 252353
season_id <- 2024
team_id <- 6
# request -----------------------------------------------------------------
req <- request("https://lm-api-reads.fantasy.espn.com")
req <- req %>%
req_url_path_append("apis/v3/games/ffl") %>%
req_url_path_append("seasons", season_id) %>%
req_url_path_append("segments", 0) %>%
req_url_path_append("leagues", league_id) %>%
req_url_query(view = "mScoreboard", view = "mRoster") %>%
req_user_agent("https://github.com/k5cents/fflr/") %>%
req_headers("Accept" = "application/json") %>%
req_retry(max_tries = 3)
resp <- req_perform(req)
dat <- resp_body_json(resp, simplifyVector = TRUE)
# format ------------------------------------------------------------------
period_id <- dat$scoringPeriodId
# build data frame from home and away sub-tables
s <- tibble(
currentMatchupPeriod = dat$status$currentMatchupPeriod,
matchupId = c(
dat$schedule$id,
dat$schedule$id
),
teamId = c(
dat$schedule$home$teamId,
dat$schedule$away$teamId
),
totalPointsLive = c(
dat$schedule$home$totalPointsLive,
dat$schedule$away$totalPointsLive
),
totalProjectedPointsLive = c(
dat$schedule$home$totalProjectedPointsLive,
dat$schedule$away$totalProjectedPointsLive
)
)
# filter and order the data frame
s <- s[!is.na(s$totalProjectedPointsLive), ]
# add a TRUE/FALSE if projected score is above median
s$bonusWin <- s$totalProjectedPointsLive > median(s$totalProjectedPointsLive)
# add a ranking of projected score
score_ranked <- sort(s$totalProjectedPointsLive, decreasing = TRUE)
s$scoreRank <- match(s$totalProjectedPointsLive, score_ranked)
# add team abbreviation by team ID
s$abbrev <- dat$teams$abbrev[match(s$teamId, dat$teams$id)]
# find match for the selected team
s <- s[s$matchupId == s$matchupId[s$teamId == team_id], ]
# reorder and remove columns
s <- s[, c("teamId", "abbrev", "totalPointsLive", "totalProjectedPointsLive", "scoreRank")]
# add player status -------------------------------------------------------
# find the players starting on each team
rosters <- dat$teams$roster$entries[dat$teams$id %in% s$teamId]
out <- rep(list(NA), length(rosters))
for (i in seq_along(rosters)) {
out[[i]] <- data.frame(
teamId = rosters[[i]]$playerPoolEntry$onTeamId,
fullName = rosters[[i]]$playerPoolEntry$player$fullName,
proTeamId = rosters[[i]]$playerPoolEntry$player$proTeamId,
slotId = rosters[[i]]$lineupSlotId,
locked = rosters[[i]]$playerPoolEntry$lineupLocked
)
}
# combine the players into a single list
out <- do.call("rbind", out)
# limit data frame to players not on bench (20)
out <- out[out$slotId != 20 & out$slotId != 21, ]
# count the players yet to start on each team
n_locked <- by(out$locked, out$teamId, sum)
n_unlocked <- by(!out$locked, out$teamId, sum)
locked <- data.frame(
teamId = names(n_locked),
locked = as.vector(n_locked),
unlocked = as.vector(n_unlocked)
)
s <- merge(s, locked)
s$timestamp <- Sys.time()
# write to json -----------------------------------------------------------
# [
# {
# "teamId": 4,
# "abbrev": "BILL",
# "totalPointsLive": 130.94,
# "totalProjectedPointsLive": 130.94,
# "scoreRank": 10,
# "locked": 0,
# "unlocked": 9,
# "timestamp": "2025-01-31 20:15:38"
# },
# {
# "teamId": 6,
# "abbrev": "KIER",
# "totalPointsLive": 190.72,
# "totalProjectedPointsLive": 190.72,
# "scoreRank": 6,
# "locked": 0,
# "unlocked": 9,
# "timestamp": "2025-01-31 20:15:38"
# }
# ]
write_json(
x = s,
path = "scoreboard.json",
pretty = TRUE
)
# read from local server on Raspberry Pi
[
{
"teamId": 4,
"abbrev": "BILL",
"totalPointsLive": 130.94,
"totalProjectedPointsLive": 130.94,
"scoreRank": 10,
"locked": 0,
"unlocked": 9,
"timestamp": "2025-01-31 20:15:38"
},
{
"teamId": 6,
"abbrev": "KIER",
"totalPointsLive": 190.72,
"totalProjectedPointsLive": 190.72,
"scoreRank": 6,
"locked": 0,
"unlocked": 9,
"timestamp": "2025-01-31 20:15:38"
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment