diff --git a/.Rbuildignore b/.Rbuildignore new file mode 100644 index 0000000..ada55b7 --- /dev/null +++ b/.Rbuildignore @@ -0,0 +1,4 @@ +^rotc\.Rproj$ +^\.Rproj\.user$ +^LICENSE\.md$ +^data-raw$ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..565f2b6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.Rproj.user +.Rhistory +.Rdata +.httr-oauth +.DS_Store diff --git a/DESCRIPTION b/DESCRIPTION new file mode 100644 index 0000000..c232ac0 --- /dev/null +++ b/DESCRIPTION @@ -0,0 +1,24 @@ +Package: rotc +Title: Functions to Access OTC Data +Version: 0.0.0.9000 +Authors@R: + person("Carl", "Sebastian", , "mrcaseb@gmail.com", role = c("aut", "cre")) +Description: A set of functions to access over the cap data. +License: MIT + file LICENSE +Depends: + R (>= 3.6) +Imports: + cli (>= 3.2.0), + dplyr (>= 1.0.8), + httr2 (>= 0.1.1), + janitor (>= 2.1.0), + purrr (>= 0.3.4), + readr (>= 2.1.2), + rlang (>= 1.0.2), + rvest (>= 1.0.2), + stringr (>= 1.4.0), + tidyr (>= 1.2.0), + xml2 (>= 1.3.3) +Encoding: UTF-8 +Roxygen: list(markdown = TRUE) +RoxygenNote: 7.1.2 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..091beaf --- /dev/null +++ b/LICENSE @@ -0,0 +1,2 @@ +YEAR: 2022 +COPYRIGHT HOLDER: rotc authors diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..0c22051 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# MIT License + +Copyright (c) 2022 rotc authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/NAMESPACE b/NAMESPACE new file mode 100644 index 0000000..d62affb --- /dev/null +++ b/NAMESPACE @@ -0,0 +1,5 @@ +# Generated by roxygen2: do not edit by hand + +export(otc_historical_contracts) +export(otc_historical_contracts_all) +import(dplyr) diff --git a/R/otc_historical_contracts.R b/R/otc_historical_contracts.R new file mode 100644 index 0000000..966018d --- /dev/null +++ b/R/otc_historical_contracts.R @@ -0,0 +1,82 @@ +#' Scrape Historical Contracts By Position +#' +#' @param position A valid character string naming the position to scrape +#' historical contracts for. +#' +#' @return A tibble +#' @export +#' +#' @examples +#' \donttest{ +#' otc_historical_contracts("QB") +#' } +otc_historical_contracts <- function(position = c("QB", "RB", "FB", "WR", + "TE", "LT", "LG", "C", + "RG", "RT", "IDL", "ED", + "LB", "CB", "S", "K", + "P", "LS")){ + position <- rlang::arg_match(position) + + cli::cli_progress_step("Scrape {.val {position}}") + + html_scrape <- httr2::request("https://overthecap.com/contract-history/") %>% + httr2::req_url_path_append(available_positions[position]) %>% + httr2::req_retry(max_tries = 5) %>% + httr2::req_perform() %>% + httr2::resp_body_html() + + hrefs <- xml2::xml_find_all(html_scrape, ".//a") %>% + xml2::xml_attrs() %>% + dplyr::bind_rows() %>% + dplyr::filter(stringr::str_detect(href, "/player/")) %>% + dplyr::pull(href) + + contratct_status <- xml2::xml_find_all(html_scrape, ".//tr[.//td]") %>% + xml2::xml_attr("class") + + tbl <- rvest::html_table(html_scrape)[[1]] %>% + janitor::remove_empty("cols") %>% + janitor::clean_names() %>% + dplyr::mutate(dplyr::across( + .cols = c( + dplyr::ends_with("value"), + dplyr::ends_with("apy"), + dplyr::starts_with("apy"), + dplyr::ends_with("guaranteed") + ), + .fns = readr::parse_number + )) %>% + dplyr::rename(apy_cap_pct = apy_as_percent_of_cap_at_signing) %>% + dplyr::mutate( + apy_cap_pct = apy_cap_pct / 100, + position = position, + player_page = paste0("https://overthecap.com", hrefs), + otc_id = as.integer(stringr::str_extract(hrefs, "[:digit:]+")), + is_active = contratct_status == "active" + ) %>% + dplyr::select(player, position, team, is_active, dplyr::everything()) %>% + tidyr::replace_na(list(is_active = FALSE)) + + tbl +} + + +#' Scrape Historical Contracts for Multiple Positions +#' +#' @description This is a wrapper around [otc_historical_contracts()] that +#' scrapes and binds multiple positions. +#' +#' @param positions A character vector with valid position names forwarded to +#' [otc_historical_contracts()]. +#' +#' @return A tibble +#' @export +#' +#' @examples +#' \donttest{ +#' # otc_historical_contracts_all() +#' } +otc_historical_contracts_all <- function(positions = NULL){ + if(is.null(positions)) positions <- names(available_positions) + purrr::map_dfr(positions, otc_historical_contracts) +} diff --git a/R/rotc-package.R b/R/rotc-package.R new file mode 100644 index 0000000..fea7845 --- /dev/null +++ b/R/rotc-package.R @@ -0,0 +1,7 @@ +#' @keywords internal +"_PACKAGE" + +## usethis namespace: start +#' @import dplyr +## usethis namespace: end +NULL diff --git a/R/silence_tidy_eval_notes.R b/R/silence_tidy_eval_notes.R new file mode 100644 index 0000000..6a95362 --- /dev/null +++ b/R/silence_tidy_eval_notes.R @@ -0,0 +1,11 @@ +utils::globalVariables( + names = c( + "href", + "apy_as_percent_of_cap_at_signing", + "apy_cap_pct", + "player", + "team", + "is_active" + ), + package = "rotc" +) diff --git a/R/sysdata.rda b/R/sysdata.rda new file mode 100644 index 0000000..54c0359 Binary files /dev/null and b/R/sysdata.rda differ diff --git a/data-raw/available_positions.R b/data-raw/available_positions.R new file mode 100644 index 0000000..033ab86 --- /dev/null +++ b/data-raw/available_positions.R @@ -0,0 +1,16 @@ +## code to prepare `available_positions` dataset goes here + +available_positions <- httr2::request("https://overthecap.com/contract-history/") |> + httr2::req_perform() |> + httr2::resp_body_html() |> + rvest::html_elements("ul") |> + rvest::html_elements(xpath = ".//a") |> + xml2::xml_attrs() |> + stringr::str_extract("(?<=/position/)[:graph:]+") |> + stats::na.omit() |> + as.character() |> + rlang::set_names( + "QB", "RB", "FB", "WR", "TE", "LT", "LG", "C", "RG", "RT", "IDL", "ED", + "LB", "CB", "S", "K", "P", "LS" + ) +usethis::use_data(available_positions, overwrite = TRUE, internal = TRUE) diff --git a/man/otc_historical_contracts.Rd b/man/otc_historical_contracts.Rd new file mode 100644 index 0000000..88ebbff --- /dev/null +++ b/man/otc_historical_contracts.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/otc_historical_contracts.R +\name{otc_historical_contracts} +\alias{otc_historical_contracts} +\title{Scrape Historical Contracts By Position} +\usage{ +otc_historical_contracts( + position = c("QB", "RB", "FB", "WR", "TE", "LT", "LG", "C", "RG", "RT", "IDL", "ED", + "LB", "CB", "S", "K", "P", "LS") +) +} +\arguments{ +\item{position}{A valid character string naming the position to scrape +historical contracts for.} +} +\value{ +A tibble +} +\description{ +Scrape Historical Contracts By Position +} +\examples{ +\donttest{ +otc_historical_contracts("QB") +} +} diff --git a/man/otc_historical_contracts_all.Rd b/man/otc_historical_contracts_all.Rd new file mode 100644 index 0000000..28d2a62 --- /dev/null +++ b/man/otc_historical_contracts_all.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/otc_historical_contracts.R +\name{otc_historical_contracts_all} +\alias{otc_historical_contracts_all} +\title{Scrape Historical Contracts for Multiple Positions} +\usage{ +otc_historical_contracts_all(positions = NULL) +} +\arguments{ +\item{positions}{A character vector with valid position names forwarded to +\code{\link[=otc_historical_contracts]{otc_historical_contracts()}}.} +} +\value{ +A tibble +} +\description{ +This is a wrapper around \code{\link[=otc_historical_contracts]{otc_historical_contracts()}} that +scrapes and binds multiple positions. +} +\examples{ +\donttest{ +# otc_historical_contracts_all() +} +} diff --git a/man/rotc-package.Rd b/man/rotc-package.Rd new file mode 100644 index 0000000..a8aef05 --- /dev/null +++ b/man/rotc-package.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/rotc-package.R +\docType{package} +\name{rotc-package} +\alias{rotc} +\alias{rotc-package} +\title{rotc: Functions to Access OTC Data} +\description{ +A set of functions to access over the cap data. +} +\author{ +\strong{Maintainer}: Carl Sebastian \email{mrcaseb@gmail.com} + +} +\keyword{internal} diff --git a/rotc.Rproj b/rotc.Rproj new file mode 100644 index 0000000..69fafd4 --- /dev/null +++ b/rotc.Rproj @@ -0,0 +1,22 @@ +Version: 1.0 + +RestoreWorkspace: No +SaveWorkspace: No +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX + +AutoAppendNewline: Yes +StripTrailingWhitespace: Yes +LineEndingConversion: Posix + +BuildType: Package +PackageUseDevtools: Yes +PackageInstallArgs: --no-multiarch --with-keep.source +PackageRoxygenize: rd,collate,namespace