R/espn_nba_data.R

Defines functions espn_nba_scoreboard espn_nba_teams espn_nba_game_rosters espn_nba_player_box espn_nba_team_box espn_nba_pbp espn_nba_game_all

Documented in espn_nba_game_all espn_nba_game_rosters espn_nba_pbp espn_nba_player_box espn_nba_scoreboard espn_nba_team_box espn_nba_teams

#' **Get ESPN NBA game data (Pbp, Team and Player Box)**
#' @author Saiem Gilani
#' @param game_id Game ID
#' @return A named list of data frames: Plays, Team, Player
#'
#'    **Plays**
#'
#'
#'    |col_name                  |types     |
#'    |:-------------------------|:---------|
#'    |id                        |character |
#'    |sequence_number           |character |
#'    |text                      |character |
#'    |away_score                |integer   |
#'    |home_score                |integer   |
#'    |scoring_play              |logical   |
#'    |score_value               |integer   |
#'    |wallclock                 |character |
#'    |shooting_play             |logical   |
#'    |type_id                   |integer   |
#'    |type_text                 |character |
#'    |period_number             |integer   |
#'    |period_display_value      |character |
#'    |clock_display_value       |character |
#'    |team_id                   |integer   |
#'    |coordinate_x_raw          |numeric   |
#'    |coordinate_y_raw          |numeric   |
#'    |coordinate_x              |numeric   |
#'    |coordinate_y              |numeric   |
#'    |play_id                   |character |
#'    |athlete_id_1              |integer   |
#'    |athlete_id_2              |integer   |
#'    |athlete_id_3              |integer   |
#'    |home_team_id              |integer   |
#'    |home_team_mascot          |character |
#'    |home_team_name            |character |
#'    |home_team_abbrev          |character |
#'    |home_team_logo            |character |
#'    |home_team_logo_dark       |character |
#'    |home_team_full_name       |character |
#'    |home_team_color           |character |
#'    |home_team_alternate_color |character |
#'    |home_team_score           |integer   |
#'    |home_team_winner          |logical   |
#'    |home_team_record          |character |
#'    |away_team_id              |integer   |
#'    |away_team_mascot          |character |
#'    |away_team_name            |character |
#'    |away_team_abbrev          |character |
#'    |away_team_logo            |character |
#'    |away_team_logo_dark       |character |
#'    |away_team_full_name       |character |
#'    |away_team_color           |character |
#'    |away_team_alternate_color |character |
#'    |away_team_score           |integer   |
#'    |away_team_winner          |logical   |
#'    |away_team_record          |character |
#'    |game_id                   |integer   |
#'    |season                    |integer   |
#'    |season_type               |integer   |
#'    |game_date                 |Date      |
#'    |game_date_time            |POSIXct   |
#'
#'    **Team**
#'
#'
#'    |col_name                          |types     |
#'    |:---------------------------------|:---------|
#'    |game_id                           |integer   |
#'    |season                            |integer   |
#'    |season_type                       |integer   |
#'    |game_date                         |Date      |
#'    |game_date_time                    |POSIXct   |
#'    |team_id                           |integer   |
#'    |team_uid                          |character |
#'    |team_slug                         |character |
#'    |team_location                     |character |
#'    |team_name                         |character |
#'    |team_abbreviation                 |character |
#'    |team_display_name                 |character |
#'    |team_short_display_name           |character |
#'    |team_color                        |character |
#'    |team_alternate_color              |character |
#'    |team_logo                         |character |
#'    |team_home_away                    |character |
#'    |team_score                        |integer   |
#'    |team_winner                       |logical   |
#'    |assists                           |integer   |
#'    |blocks                            |integer   |
#'    |defensive_rebounds                |integer   |
#'    |fast_break_points                 |character |
#'    |field_goal_pct                    |numeric   |
#'    |field_goals_made                  |integer   |
#'    |field_goals_attempted             |integer   |
#'    |flagrant_fouls                    |integer   |
#'    |fouls                             |integer   |
#'    |free_throw_pct                    |numeric   |
#'    |free_throws_made                  |integer   |
#'    |free_throws_attempted             |integer   |
#'    |largest_lead                      |character |
#'    |offensive_rebounds                |integer   |
#'    |points_in_paint                   |character |
#'    |steals                            |integer   |
#'    |team_turnovers                    |integer   |
#'    |technical_fouls                   |integer   |
#'    |three_point_field_goal_pct        |numeric   |
#'    |three_point_field_goals_made      |integer   |
#'    |three_point_field_goals_attempted |integer   |
#'    |total_rebounds                    |integer   |
#'    |total_technical_fouls             |integer   |
#'    |total_turnovers                   |integer   |
#'    |turnover_points                   |character |
#'    |turnovers                         |integer   |
#'    |opponent_team_id                  |integer   |
#'    |opponent_team_uid                 |character |
#'    |opponent_team_slug                |character |
#'    |opponent_team_location            |character |
#'    |opponent_team_name                |character |
#'    |opponent_team_abbreviation        |character |
#'    |opponent_team_display_name        |character |
#'    |opponent_team_short_display_name  |character |
#'    |opponent_team_color               |character |
#'    |opponent_team_alternate_color     |character |
#'    |opponent_team_logo                |character |
#'    |opponent_team_score               |integer   |
#'
#'    **Player**
#'
#'
#'    |col_name                          |types     |
#'    |:---------------------------------|:---------|
#'    |game_id                           |integer   |
#'    |season                            |integer   |
#'    |season_type                       |integer   |
#'    |game_date                         |Date      |
#'    |game_date_time                    |POSIXct   |
#'    |athlete_id                        |integer   |
#'    |athlete_display_name              |character |
#'    |team_id                           |integer   |
#'    |team_name                         |character |
#'    |team_location                     |character |
#'    |team_short_display_name           |character |
#'    |minutes                           |numeric   |
#'    |field_goals_made                  |integer   |
#'    |field_goals_attempted             |integer   |
#'    |three_point_field_goals_made      |integer   |
#'    |three_point_field_goals_attempted |integer   |
#'    |free_throws_made                  |integer   |
#'    |free_throws_attempted             |integer   |
#'    |offensive_rebounds                |integer   |
#'    |defensive_rebounds                |integer   |
#'    |rebounds                          |integer   |
#'    |assists                           |integer   |
#'    |steals                            |integer   |
#'    |blocks                            |integer   |
#'    |turnovers                         |integer   |
#'    |fouls                             |integer   |
#'    |plus_minus                        |character |
#'    |points                            |integer   |
#'    |starter                           |logical   |
#'    |ejected                           |logical   |
#'    |did_not_play                      |logical   |
#'    |reason                            |character |
#'    |active                            |logical   |
#'    |athlete_jersey                    |character |
#'    |athlete_short_name                |character |
#'    |athlete_headshot_href             |character |
#'    |athlete_position_name             |character |
#'    |athlete_position_abbreviation     |character |
#'    |team_display_name                 |character |
#'    |team_uid                          |character |
#'    |team_slug                         |character |
#'    |team_logo                         |character |
#'    |team_abbreviation                 |character |
#'    |team_color                        |character |
#'    |team_alternate_color              |character |
#'    |home_away                         |character |
#'    |team_winner                       |logical   |
#'    |team_score                        |integer   |
#'    |opponent_team_id                  |integer   |
#'    |opponent_team_name                |character |
#'    |opponent_team_location            |character |
#'    |opponent_team_display_name        |character |
#'    |opponent_team_abbreviation        |character |
#'    |opponent_team_logo                |character |
#'    |opponent_team_color               |character |
#'    |opponent_team_alternate_color     |character |
#'    |opponent_team_score               |integer   |
#'
#' @importFrom jsonlite fromJSON toJSON
#' @importFrom dplyr filter select rename bind_cols bind_rows
#' @importFrom tidyr unnest unnest_wider everything
#' @import rvest
#' @export
#' @keywords NBA Game
#' @family ESPN NBA Functions
#' @examples
#' \donttest{
#'   try(espn_nba_game_all(game_id = 401283399))
#' }
#'

espn_nba_game_all <- function(game_id) {
  old <- options(list(stringsAsFactors = FALSE, scipen = 999))
  on.exit(options(old))
  summary_url <- "http://site.api.espn.com/apis/site/v2/sports/basketball/nba/summary?"

  ## Inputs
  ## game_id
  full_url <- paste0(summary_url,
                     "event=", game_id)

  res <- httr::RETRY("GET", full_url)

  # Check the result
  check_status(res)

  resp <- res %>%
    httr::content(as = "text", encoding = "UTF-8")

  #---- Play-by-Play ------
  tryCatch(
    expr = {

      plays_df <- helper_espn_nba_pbp(resp)

      if (is.null(plays_df)) {
        message(glue::glue("{Sys.time()}: No play-by-play data for {game_id} available!"))
      }

    },
    error = function(e) {
      message(
        glue::glue(
          "{Sys.time()}: Invalid arguments or no play-by-play data for {game_id} available!"
        )
      )
    },
    warning = function(w) {

    },
    finally = {

    }
  )
  #---- Team Box ------
  tryCatch(
    expr = {

      team_box_score <- helper_espn_nba_team_box(resp)

      if (is.null(team_box_score)) {
        message(glue::glue("{Sys.time()}: No team box score data for {game_id} available!"))
      }

    },
    error = function(e) {
      message(
        glue::glue(
          "{Sys.time()}: Invalid arguments or no team box score data for {game_id} available!"
        )
      )
    },
    warning = function(w) {

    },
    finally = {

    }
  )
  #---- Player Box ------
  tryCatch(
    expr = {

      player_box_score <- helper_espn_nba_player_box(resp)

      if (is.null(player_box_score)) {
        message(glue::glue("{Sys.time()}: No player box score data for {game_id} available!"))
      }

    },
    error = function(e) {
      message(
        glue::glue(
          "{Sys.time()}: Invalid arguments or no player box score data for {game_id} available!"
        )
      )
    },
    warning = function(w) {

    },
    finally = {

    }
  )

  pbp <- c(list(plays_df), list(team_box_score), list(player_box_score))
  names(pbp) <- c("Plays", "Team", "Player")
  return(pbp)
}


#' **Get ESPN NBA PBP data**
#' @author Saiem Gilani
#' @param game_id Game ID
#' @return A play-by-play data frame.
#'
#'    **Plays**
#'
#'
#'    |col_name                  |types     |
#'    |:-------------------------|:---------|
#'    |id                        |character |
#'    |sequence_number           |character |
#'    |text                      |character |
#'    |away_score                |integer   |
#'    |home_score                |integer   |
#'    |scoring_play              |logical   |
#'    |score_value               |integer   |
#'    |wallclock                 |character |
#'    |shooting_play             |logical   |
#'    |type_id                   |integer   |
#'    |type_text                 |character |
#'    |period_number             |integer   |
#'    |period_display_value      |character |
#'    |clock_display_value       |character |
#'    |team_id                   |integer   |
#'    |coordinate_x_raw          |numeric   |
#'    |coordinate_y_raw          |numeric   |
#'    |coordinate_x              |numeric   |
#'    |coordinate_y              |numeric   |
#'    |play_id                   |character |
#'    |athlete_id_1              |integer   |
#'    |athlete_id_2              |integer   |
#'    |athlete_id_3              |integer   |
#'    |home_team_id              |integer   |
#'    |home_team_mascot          |character |
#'    |home_team_name            |character |
#'    |home_team_abbrev          |character |
#'    |home_team_logo            |character |
#'    |home_team_logo_dark       |character |
#'    |home_team_full_name       |character |
#'    |home_team_color           |character |
#'    |home_team_alternate_color |character |
#'    |home_team_score           |integer   |
#'    |home_team_winner          |logical   |
#'    |home_team_record          |character |
#'    |away_team_id              |integer   |
#'    |away_team_mascot          |character |
#'    |away_team_name            |character |
#'    |away_team_abbrev          |character |
#'    |away_team_logo            |character |
#'    |away_team_logo_dark       |character |
#'    |away_team_full_name       |character |
#'    |away_team_color           |character |
#'    |away_team_alternate_color |character |
#'    |away_team_score           |integer   |
#'    |away_team_winner          |logical   |
#'    |away_team_record          |character |
#'    |game_id                   |integer   |
#'    |season                    |integer   |
#'    |season_type               |integer   |
#'    |game_date                 |Date      |
#'    |game_date_time            |POSIXct   |
#'
#' @importFrom jsonlite fromJSON toJSON
#' @importFrom dplyr filter select rename bind_cols bind_rows
#' @importFrom tidyr unnest unnest_wider everything
#' @import rvest
#' @export
#' @keywords NBA PBP
#' @family ESPN NBA Functions
#'
#' @examples
#' \donttest{
#'   try(espn_nba_pbp(game_id = 401071880))
#' }
#'
espn_nba_pbp <- function(game_id){
  old <- options(list(stringsAsFactors = FALSE, scipen = 999))
  on.exit(options(old))
  summary_url <-
    "http://site.api.espn.com/apis/site/v2/sports/basketball/nba/summary?"

  ## Inputs
  ## game_id
  full_url <- paste0(summary_url,
                     "event=", game_id)

  res <- httr::RETRY("GET", full_url)

  # Check the result
  check_status(res)

  resp <- res %>%
    httr::content(as = "text", encoding = "UTF-8")

  #---- Play-by-Play ------
  tryCatch(
    expr = {

      plays_df <- helper_espn_nba_pbp(resp)

      if (is.null(plays_df)) {
        return(message(glue::glue("{Sys.time()}: No play-by-play data for {game_id} available!")))
      }

    },
    error = function(e) {
      message(glue::glue("{Sys.time()}: Invalid arguments or no play-by-play data for {game_id} available!"))
    },
    warning = function(w) {
    },
    finally = {
    }
  )


  return(plays_df)
}


#' **Get ESPN NBA team box scores**
#' @author Saiem Gilani
#' @param game_id Game ID
#' @return A team boxscore data frame
#'
#'    **Team**
#'
#'
#'    |col_name                          |types     |
#'    |:---------------------------------|:---------|
#'    |game_id                           |integer   |
#'    |season                            |integer   |
#'    |season_type                       |integer   |
#'    |game_date                         |Date      |
#'    |game_date_time                    |POSIXct   |
#'    |team_id                           |integer   |
#'    |team_uid                          |character |
#'    |team_slug                         |character |
#'    |team_location                     |character |
#'    |team_name                         |character |
#'    |team_abbreviation                 |character |
#'    |team_display_name                 |character |
#'    |team_short_display_name           |character |
#'    |team_color                        |character |
#'    |team_alternate_color              |character |
#'    |team_logo                         |character |
#'    |team_home_away                    |character |
#'    |team_score                        |integer   |
#'    |team_winner                       |logical   |
#'    |assists                           |integer   |
#'    |blocks                            |integer   |
#'    |defensive_rebounds                |integer   |
#'    |fast_break_points                 |character |
#'    |field_goal_pct                    |numeric   |
#'    |field_goals_made                  |integer   |
#'    |field_goals_attempted             |integer   |
#'    |flagrant_fouls                    |integer   |
#'    |fouls                             |integer   |
#'    |free_throw_pct                    |numeric   |
#'    |free_throws_made                  |integer   |
#'    |free_throws_attempted             |integer   |
#'    |largest_lead                      |character |
#'    |offensive_rebounds                |integer   |
#'    |points_in_paint                   |character |
#'    |steals                            |integer   |
#'    |team_turnovers                    |integer   |
#'    |technical_fouls                   |integer   |
#'    |three_point_field_goal_pct        |numeric   |
#'    |three_point_field_goals_made      |integer   |
#'    |three_point_field_goals_attempted |integer   |
#'    |total_rebounds                    |integer   |
#'    |total_technical_fouls             |integer   |
#'    |total_turnovers                   |integer   |
#'    |turnover_points                   |character |
#'    |turnovers                         |integer   |
#'    |opponent_team_id                  |integer   |
#'    |opponent_team_uid                 |character |
#'    |opponent_team_slug                |character |
#'    |opponent_team_location            |character |
#'    |opponent_team_name                |character |
#'    |opponent_team_abbreviation        |character |
#'    |opponent_team_display_name        |character |
#'    |opponent_team_short_display_name  |character |
#'    |opponent_team_color               |character |
#'    |opponent_team_alternate_color     |character |
#'    |opponent_team_logo                |character |
#'    |opponent_team_score               |integer   |
#'
#' @importFrom jsonlite fromJSON toJSON
#' @importFrom dplyr filter select rename bind_cols bind_rows
#' @importFrom tidyr unnest unnest_wider everything
#' @import rvest
#' @export
#' @keywords NBA Team Box
#' @family ESPN NBA Functions
#'
#' @examples
#' \donttest{
#'   try(espn_nba_team_box(game_id = 401071880))
#' }
#'
espn_nba_team_box <- function(game_id){
  old <- options(list(stringsAsFactors = FALSE, scipen = 999))
  on.exit(options(old))
  summary_url <-
    "http://site.api.espn.com/apis/site/v2/sports/basketball/nba/summary?"

  ## Inputs
  ## game_id
  full_url <- paste0(summary_url,
                     "event=", game_id)

  res <- httr::RETRY("GET", full_url)

  # Check the result
  check_status(res)

  resp <- res %>%
    httr::content(as = "text", encoding = "UTF-8")

  #---- Team Box ------
  tryCatch(
    expr = {

      team_box_score <- helper_espn_nba_team_box(resp)

      if (is.null(team_box_score)) {
        return(message(glue::glue("{Sys.time()}: No team box score data for {game_id} available!")))
      }

    },
    error = function(e) {
      message(glue::glue("{Sys.time()}: Invalid arguments or no team box score data for {game_id} available!"))
    },
    warning = function(w) {
    },
    finally = {
    }
  )
  return(team_box_score)
}
#' **Get ESPN NBA player box scores**
#' @author Saiem Gilani
#' @param game_id Game ID
#' @return A player boxscore data frame
#'
#'    **Player**
#'
#'
#'    |col_name                          |types     |
#'    |:---------------------------------|:---------|
#'    |game_id                           |integer   |
#'    |season                            |integer   |
#'    |season_type                       |integer   |
#'    |game_date                         |Date      |
#'    |game_date_time                    |POSIXct   |
#'    |athlete_id                        |integer   |
#'    |athlete_display_name              |character |
#'    |team_id                           |integer   |
#'    |team_name                         |character |
#'    |team_location                     |character |
#'    |team_short_display_name           |character |
#'    |minutes                           |numeric   |
#'    |field_goals_made                  |integer   |
#'    |field_goals_attempted             |integer   |
#'    |three_point_field_goals_made      |integer   |
#'    |three_point_field_goals_attempted |integer   |
#'    |free_throws_made                  |integer   |
#'    |free_throws_attempted             |integer   |
#'    |offensive_rebounds                |integer   |
#'    |defensive_rebounds                |integer   |
#'    |rebounds                          |integer   |
#'    |assists                           |integer   |
#'    |steals                            |integer   |
#'    |blocks                            |integer   |
#'    |turnovers                         |integer   |
#'    |fouls                             |integer   |
#'    |plus_minus                        |character |
#'    |points                            |integer   |
#'    |starter                           |logical   |
#'    |ejected                           |logical   |
#'    |did_not_play                      |logical   |
#'    |reason                            |character |
#'    |active                            |logical   |
#'    |athlete_jersey                    |character |
#'    |athlete_short_name                |character |
#'    |athlete_headshot_href             |character |
#'    |athlete_position_name             |character |
#'    |athlete_position_abbreviation     |character |
#'    |team_display_name                 |character |
#'    |team_uid                          |character |
#'    |team_slug                         |character |
#'    |team_logo                         |character |
#'    |team_abbreviation                 |character |
#'    |team_color                        |character |
#'    |team_alternate_color              |character |
#'    |home_away                         |character |
#'    |team_winner                       |logical   |
#'    |team_score                        |integer   |
#'    |opponent_team_id                  |integer   |
#'    |opponent_team_name                |character |
#'    |opponent_team_location            |character |
#'    |opponent_team_display_name        |character |
#'    |opponent_team_abbreviation        |character |
#'    |opponent_team_logo                |character |
#'    |opponent_team_color               |character |
#'    |opponent_team_alternate_color     |character |
#'    |opponent_team_score               |integer   |
#'
#' @importFrom jsonlite fromJSON toJSON
#' @importFrom dplyr filter select rename bind_cols bind_rows
#' @importFrom tidyr unnest unnest_wider everything
#' @import rvest
#' @export
#' @keywords NBA Player Box
#' @family ESPN NBA Functions
#'
#' @examples
#' \donttest{
#'   try(espn_nba_player_box(game_id = 401071880))
#' }
#'
espn_nba_player_box <- function(game_id){
  old <- options(list(stringsAsFactors = FALSE, scipen = 999))
  on.exit(options(old))
  summary_url <-
    "http://site.api.espn.com/apis/site/v2/sports/basketball/nba/summary?"

  ## Inputs
  ## game_id
  full_url <- paste0(summary_url,
                     "event=", game_id)

  res <- httr::RETRY("GET", full_url)

  # Check the result
  check_status(res)

  resp <- res %>%
    httr::content(as = "text", encoding = "UTF-8")

  #---- Player Box ------
  tryCatch(
    expr = {

      player_box_score <- helper_espn_nba_player_box(resp)

      if (is.null(player_box_score)) {
        return(message(glue::glue("{Sys.time()}: No player box score data for {game_id} available!")))
      }

    },
    error = function(e) {
      message(glue::glue("{Sys.time()}: Invalid arguments or no player box score data for {game_id} available!"))
    },
    warning = function(w) {
    },
    finally = {
    }
  )
  return(player_box_score)
}



#' **Get ESPN NBA game rosters**
#' @author Saiem Gilani
#' @param game_id Game ID
#' @return A game rosters data frame
#'
#'    |col_name                                   |types     |
#'    |:------------------------------------------|:---------|
#'    |athlete_id                                 |integer   |
#'    |athlete_uid                                |character |
#'    |athlete_guid                               |character |
#'    |athlete_type                               |character |
#'    |sdr                                        |integer   |
#'    |first_name                                 |character |
#'    |last_name                                  |character |
#'    |full_name                                  |character |
#'    |athlete_display_name                       |character |
#'    |short_name                                 |character |
#'    |weight                                     |integer   |
#'    |display_weight                             |character |
#'    |height                                     |integer   |
#'    |display_height                             |character |
#'    |age                                        |integer   |
#'    |date_of_birth                              |character |
#'    |debut_year                                 |integer   |
#'    |birth_place_city                           |character |
#'    |birth_place_state                          |character |
#'    |birth_place_country                        |character |
#'    |slug                                       |character |
#'    |headshot_href                              |character |
#'    |headshot_alt                               |character |
#'    |jersey                                     |character |
#'    |position_id                                |integer   |
#'    |position_name                              |character |
#'    |position_display_name                      |character |
#'    |position_abbreviation                      |character |
#'    |position_leaf                              |logical   |
#'    |linked                                     |logical   |
#'    |years                                      |integer   |
#'    |active                                     |logical   |
#'    |contract_bird_status                       |integer   |
#'    |contract_active                            |logical   |
#'    |contract_active_1                          |logical   |
#'    |contract_incoming_trade_value              |integer   |
#'    |contract_outgoing_trade_value              |integer   |
#'    |contract_minimum_salary_exception          |logical   |
#'    |contract_option_type                       |integer   |
#'    |contract_salary                            |integer   |
#'    |contract_salary_remaining                  |integer   |
#'    |contract_years_remaining                   |integer   |
#'    |contract_trade_kicker_active               |logical   |
#'    |contract_trade_kicker_percentage           |integer   |
#'    |contract_trade_kicker_value                |integer   |
#'    |contract_trade_kicker_trade_value          |integer   |
#'    |contract_trade_restriction                 |logical   |
#'    |contract_unsigned_foreign_pick             |logical   |
#'    |contract_active_2                          |logical   |
#'    |draft_display_text                         |character |
#'    |draft_round                                |integer   |
#'    |draft_year                                 |integer   |
#'    |draft_selection                            |integer   |
#'    |status_id                                  |integer   |
#'    |status_name                                |character |
#'    |status_type                                |character |
#'    |status_abbreviation                        |character |
#'    |starter                                    |logical   |
#'    |valid                                      |logical   |
#'    |did_not_play                               |logical   |
#'    |display_name                               |character |
#'    |reason                                     |character |
#'    |ejected                                    |logical   |
#'    |team_id                                    |integer   |
#'    |team_guid                                  |character |
#'    |team_uid                                   |character |
#'    |team_slug                                  |character |
#'    |team_location                              |character |
#'    |team_name                                  |character |
#'    |team_abbreviation                          |character |
#'    |team_display_name                          |character |
#'    |team_short_display_name                    |character |
#'    |team_color                                 |character |
#'    |team_alternate_color                       |character |
#'    |team_is_active                             |logical   |
#'    |team_is_all_star                           |logical   |
#'    |logo_href                                  |character |
#'    |logo_dark_href                             |character |
#'    |logos_href_2                               |character |
#'    |logos_href_3                               |character |
#'    |game_id                                    |integer   |
#'    |order                                      |integer   |
#'    |home_away                                  |character |
#'    |winner                                     |logical   |
#'    |citizenship                                |character |
#'    |contract_base_year_compensation_active     |logical   |
#'    |contract_base_year_compensation_expiration |character |
#'    |hand_type                                  |character |
#'    |hand_abbreviation                          |character |
#'    |hand_display_value                         |character |
#'
#'
#' @importFrom jsonlite fromJSON toJSON
#' @importFrom dplyr filter select rename bind_cols bind_rows
#' @importFrom tidyr unnest unnest_wider everything
#' @import rvest
#' @export
#' @keywords NBA Game Roster
#' @family ESPN NBA Functions
#'
#' @examples
#' \donttest{
#'   try(espn_nba_game_rosters(game_id = 401283399))
#' }
espn_nba_game_rosters <- function(game_id) {
  old <- options(list(stringsAsFactors = FALSE, scipen = 999))
  on.exit(options(old))
  tryCatch(
    expr = {
      play_base_url <- paste0(
        "https://sports.core.api.espn.com/v2/sports/basketball/leagues/nba/events/",
        game_id, "/competitions/",
        game_id,"/competitors/")
      game_res <- httr::RETRY("GET", play_base_url)
      # Check the result
      check_status(game_res)

      game_resp <- game_res %>%
        httr::content(as = "text", encoding = "UTF-8")
      game_df <- jsonlite::fromJSON(game_resp)[["items"]] %>%
        jsonlite::toJSON() %>%
        jsonlite::fromJSON(flatten = TRUE) %>%
        dplyr::rename("team_statistics_href" = "statistics.$ref")

      colnames(game_df) <- gsub(".\\$ref","_href", colnames(game_df))

      game_df <- game_df %>%
        dplyr::rename(
          "team_id" = "id",
          "team_uid" = "uid")

      game_df$game_id <- game_id

      teams_df <- purrr::map_dfr(game_df$team_href, function(x){

        res <- httr::RETRY("GET", x)
        # Check the result
        check_status(res)

        team_df <- res %>%
          httr::content(as = "text", encoding = "UTF-8") %>%
          jsonlite::fromJSON(simplifyDataFrame = FALSE, simplifyVector = FALSE, simplifyMatrix = FALSE)

        team_df[["links"]] <- NULL
        team_df[["injuries"]] <- NULL
        team_df[["record"]] <- NULL
        team_df[["athletes"]] <- NULL
        team_df[["venue"]] <- NULL
        team_df[["groups"]] <- NULL
        team_df[["ranks"]] <- NULL
        team_df[["statistics"]] <- NULL
        team_df[["leaders"]] <- NULL
        team_df[["links"]] <- NULL
        team_df[["notes"]] <- NULL
        team_df[["franchise"]] <- NULL
        team_df[["againstTheSpreadRecords"]] <- NULL
        team_df[["oddsRecords"]] <- NULL
        team_df[["college"]] <- NULL
        team_df[["transactions"]] <- NULL
        team_df[["leaders"]] <- NULL
        team_df[["depthCharts"]] <- NULL
        team_df[["awards"]] <- NULL
        team_df[["events"]] <- NULL

        team_df <- team_df %>%
          purrr::map_if(is.list, as.data.frame) %>%
          as.data.frame() %>%
          dplyr::select(
            -dplyr::any_of(
              c("logos.width",
                "logos.height",
                "logos.alt",
                "logos.rel..full.",
                "logos.rel..default.",
                "logos.rel..scoreboard.",
                "logos.rel..scoreboard..1",
                "logos.rel..scoreboard.2",
                "logos.lastUpdated",
                "logos.width.1",
                "logos.height.1",
                "logos.alt.1",
                "logos.rel..full..1",
                "logos.rel..dark.",
                "logos.rel..dark..1",
                "logos.lastUpdated.1",
                "logos.width.2",
                "logos.height.2",
                "logos.alt.2",
                "logos.rel..full..2",
                "logos.rel..scoreboard.",
                "logos.lastUpdated.2",
                "logos.width.3",
                "logos.height.3",
                "logos.alt.3",
                "logos.rel..full..3",
                "logos.lastUpdated.3",
                "X.ref",
                "X.ref.1",
                "X.ref.2"))) %>%
          janitor::clean_names()

        colnames(team_df)[1:13] <- paste0("team_", colnames(team_df)[1:13])

        team_df <- team_df %>%
          dplyr::rename(
            "logo_href" = "logos_href",
            "logo_dark_href" = "logos_href_1") %>%
          dplyr::left_join(
            game_df %>%
              dplyr::select(
                "game_id",
                "team_id",
                "team_uid",
                "order",
                "homeAway",
                "winner",
                "roster_href"),
            by = c("team_id" = "team_id",
                   "team_uid" = "team_uid")
          )

      })

      ## Inputs
      ## game_id
      team_roster_df <- purrr::map_dfr(teams_df$team_id, function(x){

        res <- httr::RETRY("GET", paste0(play_base_url, x, "/roster"))

        # Check the result
        check_status(res)

        resp <- res %>%
          httr::content(as = "text", encoding = "UTF-8")

        raw_play_df <- jsonlite::fromJSON(resp)[["entries"]]

        raw_play_df <- raw_play_df %>%
          jsonlite::toJSON() %>%
          jsonlite::fromJSON(flatten = TRUE) %>%
          dplyr::mutate(team_id = x) %>%
          dplyr::select(-"period", -"forPlayerId", -"active")

        raw_play_df <- raw_play_df %>%
          dplyr::left_join(teams_df, by = c("team_id" = "team_id"))

      })

      colnames(team_roster_df) <- gsub(".\\$ref","_href", colnames(team_roster_df))

      athlete_roster_df <- purrr::map_dfr(team_roster_df$athlete_href, function(x){

        res <- httr::RETRY("GET", x)

        # Check the result
        check_status(res)

        resp <- res %>%
          httr::content(as = "text", encoding = "UTF-8")

        raw_play_df <- jsonlite::fromJSON(resp, flatten = TRUE)
        raw_play_df[["links"]] <- NULL
        raw_play_df[["injuries"]] <- NULL
        raw_play_df[["teams"]] <- NULL
        raw_play_df[["team"]] <- NULL
        raw_play_df[["college"]] <- NULL
        raw_play_df[["proAthlete"]] <- NULL
        raw_play_df[["statistics"]] <- NULL
        raw_play_df[["notes"]] <- NULL
        raw_play_df[["eventLog"]] <- NULL
        raw_play_df[["$ref"]] <- NULL
        raw_play_df[["position"]][["$ref"]] <- NULL


        raw_play_df2 <- raw_play_df %>%
          jsonlite::toJSON() %>%
          jsonlite::fromJSON(flatten = TRUE) %>%
          as.data.frame() %>%
          dplyr::mutate(id = as.integer(.data$id)) %>%
          dplyr::rename(
            "athlete_id" = "id",
            "athlete_uid" = "uid",
            "athlete_guid" = "guid",
            "athlete_type" = "type",
            "athlete_display_name" = "displayName"
          )

        raw_play_df2 <- raw_play_df2 %>%
          dplyr::left_join(team_roster_df, by = c("athlete_id" = "playerId"))

      })

      colnames(athlete_roster_df) <- gsub(".\\$ref","_href", colnames(athlete_roster_df))

      athlete_roster_df <- athlete_roster_df %>%
        janitor::clean_names() %>%
        dplyr::select(-dplyr::any_of(c(
          "x_ref",
          "x_ref_1",
          "contract_ref",
          "contract_ref_1",
          "contract_ref_2",
          "draft_ref",
          "draft_ref_1",
          "athlete_href",
          "position_ref",
          "position_href",
          "roster_href",
          "statistics_href"
        ))) %>%
        dplyr::mutate_at(c(
          "game_id",
          "athlete_id",
          "team_id",
          "position_id",
          "status_id",
          "sdr"), as.integer) %>%
        make_hoopR_data("ESPN NBA Game Roster Information from ESPN.com",Sys.time())

    },
    error = function(e) {
      message(
        glue::glue(
          "{Sys.time()}: Invalid arguments or no game roster data for {game_id} available!"
        )
      )
    },
    warning = function(w) {

    },
    finally = {

    }
  )
  return(athlete_roster_df)
}




#' **Get ESPN NBA team names and IDs**
#' @author Saiem Gilani
#' @return A teams data frame
#'
#'    |col_name        |types     |
#'    |:---------------|:---------|
#'    |team_id         |integer   |
#'    |abbreviation    |character |
#'    |display_name    |character |
#'    |short_name      |character |
#'    |mascot          |character |
#'    |nickname        |character |
#'    |team            |character |
#'    |color           |character |
#'    |alternate_color |character |
#'    |logo            |character |
#'    |logo_dark       |character |
#'    |logos_href_3    |character |
#'    |logos_href_4    |character |
#'
#' @importFrom jsonlite fromJSON toJSON
#' @importFrom dplyr filter select rename bind_cols bind_rows row_number group_by mutate as_tibble ungroup
#' @importFrom tidyr unnest unnest_wider everything pivot_wider
#' @import furrr
#' @import rvest
#' @export
#' @keywords NBA Teams
#' @family ESPN NBA Functions
#'
#' @examples
#' \donttest{
#'   try(espn_nba_teams())
#' }
#'

espn_nba_teams <- function(){
  old <- options(list(stringsAsFactors = FALSE, scipen = 999))
  on.exit(options(old))
  teams_url <- "http://site.api.espn.com/apis/site/v2/sports/basketball/nba/teams?limit=1000"


  res <- httr::RETRY("GET", teams_url)

  # Check the result
  check_status(res)

  resp <- res %>%
    httr::content(as = "text", encoding = "UTF-8")

  tryCatch(
    expr = {

      leagues <- jsonlite::fromJSON(resp)[["sports"]][["leagues"]][[1]][['teams']][[1]][['team']] %>%
        dplyr::group_by(.data$id) %>%
        tidyr::unnest_wider("logos", names_sep = "_") %>%
        tidyr::unnest_wider("logos_href", names_sep = "_") %>%
        dplyr::select(
          -"logos_width",
          -"logos_height",
          -"logos_alt",
          -"logos_rel") %>%
        dplyr::ungroup()

      if("records" %in% colnames(leagues)){
        records <- leagues$record
        records<- records %>%
          tidyr::unnest_wider("items") %>%
          tidyr::unnest_wider("stats", names_sep = "_") %>%
          dplyr::mutate(row = dplyr::row_number())
        stat <- records %>%
          dplyr::group_by(.data$row) %>%
          purrr::map_if(is.data.frame, list)
        stat <- lapply(stat$stats_1,function(x) x %>%
                         purrr::map_if(is.data.frame,list) %>%
                         dplyr::as_tibble())

        s <- lapply(stat, function(x) {
          tidyr::pivot_wider(x)
        })

        s <- tibble::tibble(g = s)
        stats <- s %>%
          tidyr::unnest_wider("g")

        records <- dplyr::bind_cols(records %>% dplyr::select("summary"), stats)
        leagues <- leagues %>%
          dplyr::select(-"record")
      }
      leagues <- leagues %>% dplyr::select(
        -"links",
        -"isActive",
        -"isAllStar",
        -"uid",
        -"slug")
      teams <- leagues %>%
        dplyr::rename(
          "logo" = "logos_href_1",
          "logo_dark" = "logos_href_2",
          "mascot" = "name",
          "team" = "location",
          "team_id" = "id",
          "short_name" = "shortDisplayName",
          "alternate_color" = "alternateColor",
          "display_name" = "displayName"
        ) %>%
        janitor::clean_names() %>%
        dplyr::mutate(team_id = as.integer(.data$team_id)) %>%
        make_hoopR_data("ESPN NBA Teams Information from ESPN.com",Sys.time())
    },
    error = function(e) {
      message(glue::glue("{Sys.time()}: Invalid arguments or no teams data available!"))
    },
    warning = function(w) {
    },
    finally = {
    }
  )
  return(teams)
}


#' **Get ESPN NBA schedule for a specific year**
#'
#' @param season Either numeric or character (YYYYMMDD)
#' @return Returns a tibble with scoreboard data
#'
#'    |col_name            |types     |
#'    |:-------------------|:---------|
#'    |matchup             |character |
#'    |matchup_short       |character |
#'    |season              |integer   |
#'    |season_type         |integer   |
#'    |season_slug         |character |
#'    |game_id             |integer   |
#'    |game_uid            |character |
#'    |game_date           |Date      |
#'    |attendance          |integer   |
#'    |notes               |logical   |
#'    |status_name         |character |
#'    |broadcasts          |logical   |
#'    |start_date          |character |
#'    |geo_broadcasts      |logical   |
#'    |game_date_time      |POSIXct   |
#'    |home_team_name      |character |
#'    |home_team_logo      |character |
#'    |home_team_abb       |character |
#'    |home_team_id        |integer   |
#'    |home_team_location  |character |
#'    |home_team_full_name |character |
#'    |home_team_color     |character |
#'    |home_score          |integer   |
#'    |home_win            |integer   |
#'    |home_record         |character |
#'    |away_team_name      |character |
#'    |away_team_logo      |character |
#'    |away_team_abb       |character |
#'    |away_team_id        |integer   |
#'    |away_team_location  |character |
#'    |away_team_full_name |character |
#'    |away_team_color     |character |
#'    |away_score          |integer   |
#'    |away_win            |integer   |
#'    |away_record         |character |
#'
#' @import utils
#' @importFrom dplyr select rename any_of mutate
#' @importFrom jsonlite fromJSON
#' @importFrom tidyr unnest_wider unchop hoist
#' @importFrom glue glue
#' @importFrom lubridate with_tz ymd_hm
#' @import rvest
#' @export
#' @family ESPN NBA Functions
#' @examples
#'
#' # Get schedule from date 2022-11-17 (returns 1000 results, max allowable.)
#' \donttest{
#'   try(espn_nba_scoreboard(season = 20230423))
#' }

espn_nba_scoreboard <- function(season){

  max_year <- substr(Sys.Date(), 1,4)

  if (!(as.integer(substr(season, 1, 4)) > 2001)) {
    message(paste("Error: Season must be between 2001 and", max_year + 1))
  }

  # year > 2000
  season <- as.character(season)

  season_dates <- season

  schedule_api <- glue::glue("http://site.api.espn.com/apis/site/v2/sports/basketball/nba/scoreboard?limit=1000&dates={season_dates}")

  tryCatch(
    expr = {

      res <- httr::RETRY("GET", schedule_api)

      # Check the result
      check_status(res)

      raw_sched <- res %>%
        httr::content(as = "text", encoding = "UTF-8") %>%
        jsonlite::fromJSON(
          simplifyDataFrame = FALSE,
          simplifyVector = FALSE,
          simplifyMatrix = FALSE
        )

      nba_data <- raw_sched[["events"]] %>%
        tibble::tibble(data = .data$.) %>%
        tidyr::unnest_wider("data") %>%
        tidyr::unchop("competitions") %>%
        dplyr::select(
          -"id",
          -"uid",
          -"date",
          -"status") %>%
        tidyr::unnest_wider("competitions") %>%
        dplyr::rename(
          "matchup" = "name",
          "matchup_short" = "shortName",
          "game_id" = "id",
          "game_uid" = "uid",
          "game_date" = "date"
        ) %>%
        tidyr::hoist("status",
                     status_name = list("type", "name")) %>%
        dplyr::select(!dplyr::any_of(
          c(
            "timeValid",
            "neutralSite",
            "conferenceCompetition",
            "recent",
            "venue",
            "type"
          )
        )) %>%
        tidyr::unnest_wider("season", names_sep = "_") %>%
        dplyr::rename("season" = "season_year") %>%
        dplyr::select(-dplyr::any_of("status"))

      nba_data <- nba_data %>%
        dplyr::mutate(
          game_date_time = lubridate::ymd_hm(substr(.data$game_date, 1, nchar(.data$game_date) - 1)) %>%
            lubridate::with_tz(tzone = "America/New_York"),
          game_date = as.Date(substr(.data$game_date_time, 1, 10)))

      nba_data <- nba_data %>%
        tidyr::hoist(
          "competitors",
          homeAway = list(1,"homeAway")
        )
      nba_data <- nba_data %>%
        tidyr::hoist(
          "competitors",
          team1_team_name = list(1, "team", "name"),
          team1_team_logo = list(1, "team", "logo"),
          team1_team_abb = list(1, "team", "abbreviation"),
          team1_team_id = list(1, "team", "id"),
          team1_team_location = list(1, "team", "location"),
          team1_team_full = list(1, "team", "displayName"),
          team1_team_color = list(1, "team", "color"),
          team1_score = list(1, "score"),
          team1_win = list(1, "winner"),
          team1_record = list(1, "records", 1, "summary"),
          # away team
          team2_team_name = list(2, "team", "name"),
          team2_team_logo = list(2, "team", "logo"),
          team2_team_abb = list(2, "team", "abbreviation"),
          team2_team_id = list(2, "team", "id"),
          team2_team_location = list(2, "team", "location"),
          team2_team_full = list(2, "team", "displayName"),
          team2_team_color = list(2, "team", "color"),
          team2_score = list(2, "score"),
          team2_win = list(2, "winner"),
          team2_record = list(2, "records", 1, "summary"))


      nba_data <- nba_data %>%
        dplyr::mutate(
          home_team_name = ifelse(.data$homeAway=="home",.data$team1_team_name, .data$team2_team_name),
          home_team_logo = ifelse(.data$homeAway=="home",.data$team1_team_logo, .data$team2_team_logo),
          home_team_abb = ifelse(.data$homeAway=="home",.data$team1_team_abb, .data$team2_team_abb),
          home_team_id = ifelse(.data$homeAway=="home",.data$team1_team_id, .data$team2_team_id),
          home_team_location = ifelse(.data$homeAway=="home",.data$team1_team_location, .data$team2_team_location),
          home_team_full_name = ifelse(.data$homeAway=="home",.data$team1_team_full, .data$team2_team_full),
          home_team_color = ifelse(.data$homeAway=="home",.data$team1_team_color, .data$team2_team_color),
          home_score = ifelse(.data$homeAway=="home",.data$team1_score, .data$team2_score),
          home_win = ifelse(.data$homeAway=="home",.data$team1_win, .data$team2_win),
          home_record = ifelse(.data$homeAway=="home",.data$team1_record, .data$team2_record),
          away_team_name = ifelse(.data$homeAway=="away",.data$team1_team_name, .data$team2_team_name),
          away_team_logo = ifelse(.data$homeAway=="away",.data$team1_team_logo, .data$team2_team_logo),
          away_team_abb = ifelse(.data$homeAway=="away",.data$team1_team_abb, .data$team2_team_abb),
          away_team_id = ifelse(.data$homeAway=="away",.data$team1_team_id, .data$team2_team_id),
          away_team_location = ifelse(.data$homeAway=="away",.data$team1_team_location, .data$team2_team_location),
          away_team_full_name = ifelse(.data$homeAway=="away",.data$team1_team_full, .data$team2_team_full),
          away_team_color = ifelse(.data$homeAway=="away",.data$team1_team_color, .data$team2_team_color),
          away_score = ifelse(.data$homeAway=="away",.data$team1_score, .data$team2_score),
          away_win = ifelse(.data$homeAway=="away",.data$team1_win, .data$team2_win),
          away_record = ifelse(.data$homeAway=="away",.data$team1_record, .data$team2_record)
        )

      nba_data <- nba_data %>%
        dplyr::mutate_at(c(
          "game_id",
          "home_team_id",
          "home_win",
          "away_team_id",
          "away_win",
          "home_score",
          "away_score"), as.integer)
      nba_data <- nba_data %>%
        dplyr::select(-dplyr::any_of(dplyr::starts_with("team1")),
                      -dplyr::any_of(dplyr::starts_with("team2")),
                      -dplyr::any_of(c("homeAway")))

      if ("leaders" %in% names(nba_data)) {
        schedule_out <- nba_data %>%
          tidyr::hoist(
            "leaders",
            # points
            points_leader_points = list(1, "leaders", 1, "value"),
            points_leader_stat = list(1, "leaders", 1, "displayValue"),
            points_leader_name = list(1, "leaders", 1, "athlete", "displayName"),
            points_leader_shortname = list(1, "leaders", 1, "athlete", "shortName"),
            points_leader_headshot = list(1, "leaders", 1, "athlete", "headshot"),
            points_leader_team_id = list(1, "leaders", 1, "team", "id"),
            points_leader_pos = list(1, "leaders", 1, "athlete", "position", "abbreviation"),
            # rebounds
            rebounds_leader_rebounds = list(2, "leaders", 1, "value"),
            rebounds_leader_stat = list(2, "leaders", 1, "displayValue"),
            rebounds_leader_name = list(2, "leaders", 1, "athlete", "displayName"),
            rebounds_leader_shortname = list(2, "leaders", 1, "athlete", "shortName"),
            rebounds_leader_headshot = list(2, "leaders", 1, "athlete", "headshot"),
            rebounds_leader_team_id = list(2, "leaders", 1, "team", "id"),
            rebounds_leader_pos = list(2, "leaders", 1, "athlete", "position", "abbreviation"),
            # assists
            assists_leader_assists = list(3, "leaders", 1, "value"),
            assists_leader_stat = list(3, "leaders", 1, "displayValue"),
            assists_leader_name = list(3, "leaders", 1, "athlete", "displayName"),
            assists_leader_shortname = list(3, "leaders", 1, "athlete", "shortName"),
            assists_leader_headshot = list(3, "leaders", 1, "athlete", "headshot"),
            assists_leader_team_id = list(3, "leaders", 1, "team", "id"),
            assists_leader_pos = list(3, "leaders", 1, "athlete", "position", "abbreviation"),
          )

        if ("broadcasts" %in% names(schedule_out) && !any(is.na(schedule_out[['broadcasts']]))) {
          schedule_out %>%
            tidyr::hoist(
              "broadcasts",
              broadcast_market = list(1, "market"),
              broadcast_name = list(1, "names", 1)) %>%
            dplyr::select(!where(is.list)) %>%
            janitor::clean_names() %>%
            make_hoopR_data("ESPN NBA Scoreboard Information from ESPN.com",Sys.time())
        } else {
          schedule_out %>%
            janitor::clean_names() %>%
            make_hoopR_data("ESPN NBA Scoreboard Information from ESPN.com",Sys.time())
        }
      } else {

        if ("broadcasts" %in% names(nba_data) && !any(is.na(nba_data[['broadcasts']]))) {
          nba_data %>%
            tidyr::hoist(
              "broadcasts",
              broadcast_market = list(1, "market"),
              broadcast_name = list(1, "names", 1)) %>%
            dplyr::select(!where(is.list)) %>%
            janitor::clean_names() %>%
            make_hoopR_data("ESPN NBA Scoreboard Information from ESPN.com",Sys.time())
        } else {
          nba_data %>%
            dplyr::select(!where(is.list)) %>%
            janitor::clean_names() %>%
            make_hoopR_data("ESPN NBA Scoreboard Information from ESPN.com",Sys.time())
        }
      }

    },
    error = function(e) {
      message(glue::glue("{Sys.time()}: Invalid arguments or no scoreboard data available!"))
    },
    warning = function(w) {
    },
    finally = {
    }
  )
}

#' **Get ESPN NBA's Standings**
#'
#' @param year Either numeric or character (YYYY)
#' @return A standings data frame
#'
#'    |col_name           |types     |
#'    |:------------------|:---------|
#'    |team_id            |integer   |
#'    |team               |character |
#'    |avgpointsagainst   |numeric   |
#'    |avgpointsfor       |numeric   |
#'    |clincher           |numeric   |
#'    |differential       |numeric   |
#'    |divisionwinpercent |numeric   |
#'    |gamesbehind        |numeric   |
#'    |leaguewinpercent   |numeric   |
#'    |losses             |numeric   |
#'    |playoffseed        |numeric   |
#'    |streak             |numeric   |
#'    |winpercent         |numeric   |
#'    |wins               |numeric   |
#'    |leaguestandings    |character |
#'    |home               |character |
#'    |road               |character |
#'    |vsdiv              |character |
#'    |vsconf             |character |
#'    |lasttengames       |character |
#'
#' @importFrom rlang .data
#' @importFrom jsonlite fromJSON toJSON
#' @importFrom dplyr select rename
#' @importFrom tidyr pivot_wider
#' @importFrom data.table rbindlist
#' @export
#' @keywords NBA Standings
#' @family ESPN NBA Functions
#' @examples
#' \donttest{
#'   try(espn_nba_standings(year = 2021))
#' }
espn_nba_standings <- function(year){

  standings_url <- "https://site.web.api.espn.com/apis/v2/sports/basketball/nba/standings?region=us&lang=en&contentorigin=espn&type=0&level=1&sort=winpercent%3Adesc%2Cwins%3Adesc%2Cgamesbehind%3Aasc&"

  ## Inputs
  ## year
  full_url <- paste0(standings_url,
                     "season=", year)

  res <- httr::RETRY("GET", full_url)

  # Check the result
  check_status(res)
  tryCatch(
    expr = {
      resp <- res %>%
        httr::content(as = "text", encoding = "UTF-8")

      raw_standings <- jsonlite::fromJSON(resp)[["standings"]]

      #Create a dataframe of all NBA teams by extracting from the raw_standings file

      teams <- raw_standings[["entries"]][["team"]]

      teams <- teams %>%
        dplyr::select("id", "displayName") %>%
        dplyr::rename(
          "team_id" = "id",
          "team" = "displayName")

      #creating a dataframe of the WNBA raw standings table from ESPN

      standings_df <- raw_standings[["entries"]][["stats"]]

      standings_data <- data.table::rbindlist(standings_df, fill = TRUE, idcol = T)

      #Use the following code to replace NA's in the dataframe with the correct corresponding values and removing all unnecessary columns

      standings_data$value <- ifelse(is.na(standings_data$value) & !is.na(standings_data$summary), standings_data$summary, standings_data$value)

      standings_data <- standings_data %>%
        dplyr::select(
          ".id",
          "type",
          "value")

      #Use pivot_wider to transpose the dataframe so that we now have a standings row for each team

      standings_data <- standings_data %>%
        tidyr::pivot_wider(names_from = "type", values_from = "value")

      standings_data <- standings_data %>%
        dplyr::select(-".id")

      #joining the 2 dataframes together to create a standings table

      standings <- cbind(teams, standings_data) %>%
        dplyr::mutate(team_id = as.integer(.data$team_id)) %>%
        dplyr::mutate_at(c(
          "avgpointsagainst",
          "avgpointsfor",
          "clincher",
          "differential",
          "divisionwinpercent",
          "gamesbehind",
          "leaguewinpercent",
          "losses",
          "playoffseed",
          "streak",
          "winpercent",
          "wins"
        ), as.numeric)
      standings <- standings %>%
        make_hoopR_data("ESPN NBA Standings Information from ESPN.com",Sys.time())
    },
    error = function(e) {
      message(glue::glue("{Sys.time()}: Invalid arguments or no standings data available!"))
    },
    warning = function(w) {
    },
    finally = {
    }

  )
  return(standings)
}


#' **Get ESPN NBA's Betting information**
#'
#' @param game_id  Game ID
#' @returns Returns a named list of data frames: pickcenter, againstTheSpread, predictor
#'
#'    **pickcenter**
#'
#'
#'    |col_name                             |types     |
#'    |:------------------------------------|:---------|
#'    |details                              |character |
#'    |over_under                           |numeric   |
#'    |spread                               |numeric   |
#'    |provider_id                          |integer   |
#'    |provider_name                        |character |
#'    |provider_priority                    |integer   |
#'    |away_team_odds_favorite              |logical   |
#'    |away_team_odds_underdog              |logical   |
#'    |away_team_odds_money_line            |integer   |
#'    |away_team_odds_spread_odds           |numeric   |
#'    |away_team_odds_team_id               |integer   |
#'    |away_team_odds_win_percentage        |numeric   |
#'    |away_team_odds_average_score         |numeric   |
#'    |away_team_odds_money_line_odds       |numeric   |
#'    |away_team_odds_spread_return         |numeric   |
#'    |away_team_odds_spread_record_wins    |integer   |
#'    |away_team_odds_spread_record_losses  |integer   |
#'    |away_team_odds_spread_record_pushes  |integer   |
#'    |away_team_odds_spread_record_summary |character |
#'    |home_team_odds_favorite              |logical   |
#'    |home_team_odds_underdog              |logical   |
#'    |home_team_odds_money_line            |integer   |
#'    |home_team_odds_spread_odds           |numeric   |
#'    |home_team_odds_team_id               |integer   |
#'    |home_team_odds_win_percentage        |numeric   |
#'    |home_team_odds_average_score         |numeric   |
#'    |home_team_odds_money_line_odds       |numeric   |
#'    |home_team_odds_spread_return         |numeric   |
#'    |home_team_odds_spread_record_wins    |integer   |
#'    |home_team_odds_spread_record_losses  |integer   |
#'    |home_team_odds_spread_record_pushes  |integer   |
#'    |home_team_odds_spread_record_summary |character |
#'    |game_id                              |integer   |
#'
#'    **againstTheSpread**
#'
#'
#'    |col_name     |types     |
#'    |:------------|:---------|
#'    |id           |integer   |
#'    |uid          |character |
#'    |display_name |character |
#'    |abbreviation |character |
#'    |logo         |character |
#'    |logos        |list      |
#'    |records      |list      |
#'    |game_id      |integer   |
#'    |team_id      |integer   |
#'
#'    **predictor**
#'
#'
#'    |col_name                  |types   |
#'    |:-------------------------|:-------|
#'    |game_id                   |integer |
#'    |home_team_id              |integer |
#'    |away_team_id              |integer |
#'    |away_team_game_projection |numeric |
#'    |away_team_chance_loss     |numeric |
#'
#' @importFrom rlang .data
#' @importFrom jsonlite fromJSON toJSON
#' @importFrom dplyr select rename
#' @export
#' @keywords NBA Betting
#' @family ESPN NBA Functions
#' @examples
#' \donttest{
#'   try(espn_nba_betting(game_id = 401283399))
#' }
espn_nba_betting <- function(game_id){

  old <- options(list(stringsAsFactors = FALSE, scipen = 999))
  on.exit(options(old))
  summary_url <-
    "http://site.api.espn.com/apis/site/v2/sports/basketball/nba/summary?"

  ## Inputs
  ## game_id
  full_url <- paste0(summary_url,
                     "event=", game_id)

  res <- httr::RETRY("GET", full_url)

  # Check the result
  check_status(res)

  resp <- res %>%
    httr::content(as = "text", encoding = "UTF-8")

  pickcenter <- data.frame()
  againstTheSpread <- data.frame()
  predictor_df <- data.frame()

  tryCatch(
    expr = {

      raw_summary <- jsonlite::fromJSON(resp)
      if ("pickcenter" %in% names(raw_summary)) {
        pickcenter <- jsonlite::fromJSON(jsonlite::toJSON(raw_summary$pickcenter), flatten = TRUE) %>%
          janitor::clean_names() %>%
          dplyr::select(-"links") %>%
          dplyr::mutate(game_id = as.integer(game_id)) %>%
          dplyr::mutate_at(c(
            "provider_id",
            "away_team_odds_team_id",
            "home_team_odds_team_id"), as.integer) %>%
          make_hoopR_data("ESPN NBA Pickcenter Information from ESPN.com",Sys.time())
      }
      if ("againstTheSpread" %in% names(raw_summary)) {
        againstTheSpread <- jsonlite::fromJSON(jsonlite::toJSON(raw_summary$againstTheSpread)) %>%
          janitor::clean_names()
        teams <- againstTheSpread$team %>%
          dplyr::select(-"links") %>%
          janitor::clean_names()
        records <- againstTheSpread$records

        teams$records <- records
        againstTheSpread <- teams %>%
          dplyr::mutate(
            game_id = as.integer(game_id),
            id = as.integer(.data$id),
            team_id = as.integer(.data$id)) %>%
          make_hoopR_data("ESPN NBA Against the Spread Information from ESPN.com",Sys.time())
      }
      if ("predictor" %in% names(raw_summary)) {
        predictor_df <- data.frame(
          game_id = as.integer(game_id),
          home_team_id = as.integer(raw_summary$predictor$homeTeam$id),
          away_team_id = as.integer(raw_summary$predictor$awayTeam$id),
          away_team_game_projection = as.numeric(raw_summary$predictor$awayTeam$gameProjection),
          away_team_chance_loss = as.numeric(raw_summary$predictor$awayTeam$teamChanceLoss)
        )
        predictor_df <- predictor_df %>%
          make_hoopR_data("ESPN NBA Predictor Information from ESPN.com",Sys.time())
      }
    },
    error = function(e) {
      message(glue::glue("{Sys.time()}: Invalid arguments or no betting data available!"))
    },
    warning = function(w) {
    },
    finally = {
    }

  )
  betting <- c(list(pickcenter), list(againstTheSpread), list(predictor_df))
  names(betting) <- c("pickcenter", "againstTheSpread", "predictor")
  return(betting)
}


#' @title
#' **Get ESPN NBA team stats data**
#' @author Saiem Gilani
#' @param team_id Team ID
#' @param year Year
#' @param season_type (character, default: regular): Season type - regular or postseason
#' @param total (boolean, default: FALSE): Totals
#' @return Returns a tibble with the team stats data
#'
#'    |col_name                                         |types     |
#'    |:------------------------------------------------|:---------|
#'    |team_id                                          |integer   |
#'    |team_guid                                        |character |
#'    |team_uid                                         |character |
#'    |team_slug                                        |character |
#'    |team_location                                    |character |
#'    |team_name                                        |character |
#'    |team_abbreviation                                |character |
#'    |team_display_name                                |character |
#'    |team_short_display_name                          |character |
#'    |team_color                                       |character |
#'    |team_alternate_color                             |character |
#'    |team_is_active                                   |logical   |
#'    |team_is_all_star                                 |logical   |
#'    |logo_href                                        |character |
#'    |logo_dark_href                                   |character |
#'    |logos_href_2                                     |character |
#'    |logos_href_3                                     |character |
#'    |defensive_blocks                                 |numeric   |
#'    |defensive_defensive_rebounds                     |numeric   |
#'    |defensive_steals                                 |numeric   |
#'    |defensive_turnover_points                        |numeric   |
#'    |defensive_def_rebound_rate                       |numeric   |
#'    |defensive_avg_defensive_rebounds                 |numeric   |
#'    |defensive_avg_blocks                             |numeric   |
#'    |defensive_avg_steals                             |numeric   |
#'    |defensive_avg48defensive_rebounds                |numeric   |
#'    |defensive_avg48blocks                            |numeric   |
#'    |defensive_avg48steals                            |numeric   |
#'    |general_disqualifications                        |numeric   |
#'    |general_flagrant_fouls                           |numeric   |
#'    |general_fouls                                    |numeric   |
#'    |general_rebound_rate                             |numeric   |
#'    |general_ejections                                |numeric   |
#'    |general_technical_fouls                          |numeric   |
#'    |general_rebounds                                 |numeric   |
#'    |general_minutes                                  |numeric   |
#'    |general_avg_minutes                              |numeric   |
#'    |general_fantasy_rating                           |numeric   |
#'    |general_nba_rating                               |numeric   |
#'    |general_plus_minus                               |numeric   |
#'    |general_avg_rebounds                             |numeric   |
#'    |general_avg_fouls                                |numeric   |
#'    |general_avg_flagrant_fouls                       |numeric   |
#'    |general_avg_technical_fouls                      |numeric   |
#'    |general_avg_ejections                            |numeric   |
#'    |general_avg_disqualifications                    |numeric   |
#'    |general_assist_turnover_ratio                    |numeric   |
#'    |general_steal_foul_ratio                         |numeric   |
#'    |general_block_foul_ratio                         |numeric   |
#'    |general_avg_team_rebounds                        |numeric   |
#'    |general_total_rebounds                           |numeric   |
#'    |general_total_technical_fouls                    |numeric   |
#'    |general_team_assist_turnover_ratio               |numeric   |
#'    |general_team_rebounds                            |numeric   |
#'    |general_steal_turnover_ratio                     |numeric   |
#'    |general_avg48rebounds                            |numeric   |
#'    |general_avg48fouls                               |numeric   |
#'    |general_avg48flagrant_fouls                      |numeric   |
#'    |general_avg48technical_fouls                     |numeric   |
#'    |general_avg48ejections                           |numeric   |
#'    |general_avg48disqualifications                   |numeric   |
#'    |general_r40                                      |numeric   |
#'    |general_games_played                             |numeric   |
#'    |general_games_started                            |numeric   |
#'    |general_double_double                            |numeric   |
#'    |general_triple_double                            |numeric   |
#'    |offensive_assists                                |numeric   |
#'    |offensive_effective_fg_pct                       |numeric   |
#'    |offensive_field_goals                            |numeric   |
#'    |offensive_field_goals_attempted                  |numeric   |
#'    |offensive_field_goals_made                       |numeric   |
#'    |offensive_field_goal_pct                         |numeric   |
#'    |offensive_free_throws                            |numeric   |
#'    |offensive_free_throw_pct                         |numeric   |
#'    |offensive_free_throws_attempted                  |numeric   |
#'    |offensive_free_throws_made                       |numeric   |
#'    |offensive_offensive_rebounds                     |numeric   |
#'    |offensive_points                                 |numeric   |
#'    |offensive_turnovers                              |numeric   |
#'    |offensive_three_point_pct                        |numeric   |
#'    |offensive_three_point_field_goals_attempted      |numeric   |
#'    |offensive_three_point_field_goals_made           |numeric   |
#'    |offensive_true_shooting_pct                      |numeric   |
#'    |offensive_team_turnovers                         |numeric   |
#'    |offensive_total_turnovers                        |numeric   |
#'    |offensive_assist_ratio                           |numeric   |
#'    |offensive_points_in_paint                        |numeric   |
#'    |offensive_off_rebound_rate                       |numeric   |
#'    |offensive_turnover_ratio                         |numeric   |
#'    |offensive_fast_break_points                      |numeric   |
#'    |offensive_possessions                            |numeric   |
#'    |offensive_pace_factor                            |numeric   |
#'    |offensive_avg_field_goals_made                   |numeric   |
#'    |offensive_avg_field_goals_attempted              |numeric   |
#'    |offensive_avg_three_point_field_goals_made       |numeric   |
#'    |offensive_avg_three_point_field_goals_attempted  |numeric   |
#'    |offensive_avg_free_throws_made                   |numeric   |
#'    |offensive_avg_free_throws_attempted              |numeric   |
#'    |offensive_avg_points                             |numeric   |
#'    |offensive_avg_offensive_rebounds                 |numeric   |
#'    |offensive_avg_assists                            |numeric   |
#'    |offensive_avg_turnovers                          |numeric   |
#'    |offensive_offensive_rebound_pct                  |numeric   |
#'    |offensive_estimated_possessions                  |numeric   |
#'    |offensive_avg_estimated_possessions              |numeric   |
#'    |offensive_points_per_estimated_possessions       |numeric   |
#'    |offensive_avg_team_turnovers                     |numeric   |
#'    |offensive_avg_total_turnovers                    |numeric   |
#'    |offensive_three_point_field_goal_pct             |numeric   |
#'    |offensive_two_point_field_goals_made             |numeric   |
#'    |offensive_two_point_field_goals_attempted        |numeric   |
#'    |offensive_avg_two_point_field_goals_made         |numeric   |
#'    |offensive_avg_two_point_field_goals_attempted    |numeric   |
#'    |offensive_two_point_field_goal_pct               |numeric   |
#'    |offensive_shooting_efficiency                    |numeric   |
#'    |offensive_scoring_efficiency                     |numeric   |
#'    |offensive_avg48field_goals_made                  |numeric   |
#'    |offensive_avg48field_goals_attempted             |numeric   |
#'    |offensive_avg48three_point_field_goals_made      |numeric   |
#'    |offensive_avg48three_point_field_goals_attempted |numeric   |
#'    |offensive_avg48free_throws_made                  |numeric   |
#'    |offensive_avg48free_throws_attempted             |numeric   |
#'    |offensive_avg48points                            |numeric   |
#'    |offensive_avg48offensive_rebounds                |numeric   |
#'    |offensive_avg48assists                           |numeric   |
#'    |offensive_avg48turnovers                         |numeric   |
#'    |offensive_p40                                    |numeric   |
#'    |offensive_a40                                    |numeric   |
#'
#' @importFrom jsonlite fromJSON toJSON
#' @importFrom dplyr filter select rename bind_cols bind_rows
#' @importFrom tidyr unnest unnest_wider everything
#' @export
#' @keywords NBA Team Stats
#' @family ESPN NBA Functions
#'
#' @examples
#' \donttest{
#'   try(espn_nba_team_stats(team_id = 18, year = 2020))
#' }

espn_nba_team_stats <- function(
    team_id,
    year,
    season_type = "regular",
    total = FALSE) {

  if (!(tolower(season_type) %in% c("regular", "postseason"))) {
    # Check if season_type is appropriate, if not regular
    cli::cli_abort("Enter valid season_type: regular or postseason")
  }
  s_type <- ifelse(season_type == "postseason", 3, 2)

  base_url <- "https://sports.core.api.espn.com/v2/sports/basketball/leagues/nba/seasons/"

  totals <- ifelse(total == TRUE, 0, "")
  full_url <- paste0(
    base_url,
    year,
    '/types/', s_type,
    '/teams/', team_id,
    '/statistics/', totals
  )

  df <- data.frame()
  tryCatch(
    expr = {

      # Create the GET request and set response as res
      res <- httr::RETRY("GET", full_url)

      # Check the result
      check_status(res)

      # Get the content and return result as data.frame
      df <- res %>%
        httr::content(as = "text", encoding = "UTF-8")  %>%
        jsonlite::fromJSON(simplifyDataFrame = FALSE, simplifyVector = FALSE, simplifyMatrix = FALSE)

      team_url <- df[["team"]][["$ref"]]

      # Create the GET request and set response as res
      team_res <- httr::RETRY("GET", team_url)

      # Check the result
      check_status(team_res)

      team_df <- team_res %>%
        httr::content(as = "text", encoding = "UTF-8") %>%
        jsonlite::fromJSON(simplifyDataFrame = FALSE, simplifyVector = FALSE, simplifyMatrix = FALSE)

      team_df[["links"]] <- NULL
      team_df[["injuries"]] <- NULL
      team_df[["record"]] <- NULL
      team_df[["athletes"]] <- NULL
      team_df[["venue"]] <- NULL
      team_df[["groups"]] <- NULL
      team_df[["ranks"]] <- NULL
      team_df[["statistics"]] <- NULL
      team_df[["leaders"]] <- NULL
      team_df[["links"]] <- NULL
      team_df[["notes"]] <- NULL
      team_df[["franchise"]] <- NULL
      team_df[["againstTheSpreadRecords"]] <- NULL
      team_df[["oddsRecords"]] <- NULL
      team_df[["college"]] <- NULL
      team_df[["transactions"]] <- NULL
      team_df[["leaders"]] <- NULL
      team_df[["depthCharts"]] <- NULL
      team_df[["awards"]] <- NULL
      team_df[["events"]] <- NULL


      team_df <- team_df %>%
        purrr::map_if(is.list,as.data.frame) %>%
        as.data.frame() %>%
        dplyr::select(
          -dplyr::any_of(
            c("logos.width",
              "logos.height",
              "logos.alt",
              "logos.rel..full.",
              "logos.rel..default.",
              "logos.rel..scoreboard.",
              "logos.rel..scoreboard..1",
              "logos.rel..scoreboard.2",
              "logos.lastUpdated",
              "logos.width.1",
              "logos.height.1",
              "logos.alt.1",
              "logos.rel..full..1",
              "logos.rel..dark.",
              "logos.rel..dark..1",
              "logos.lastUpdated.1",
              "logos.width.2",
              "logos.height.2",
              "logos.alt.2",
              "logos.rel..full..2",
              "logos.rel..scoreboard.",
              "logos.lastUpdated.2",
              "logos.width.3",
              "logos.height.3",
              "logos.alt.3",
              "logos.rel..full..3",
              "logos.lastUpdated.3",
              "X.ref",
              "X.ref.1",
              "X.ref.2"))) %>%
        janitor::clean_names()

      colnames(team_df)[1:13] <- paste0("team_",colnames(team_df)[1:13])

      team_df <- team_df %>%
        dplyr::rename(
          "logo_href" = "logos_href",
          "logo_dark_href" = "logos_href_1")

      df <- res %>%
        httr::content(as = "text", encoding = "UTF-8") %>%
        jsonlite::fromJSON() %>%
        purrr::pluck("splits") %>%
        purrr::pluck("categories") %>%
        tidyr::unnest("stats", names_sep = "_")
      df <- df %>%
        dplyr::mutate(
          stats_category_name = glue::glue("{.data$name}_{.data$stats_name}")) %>%
        dplyr::select(
          "stats_category_name",
          "stats_value") %>%
        tidyr::pivot_wider(names_from = "stats_category_name",
                           values_from = "stats_value",
                           values_fn = dplyr::first) %>%
        janitor::clean_names()

      df <- team_df %>%
        dplyr::bind_cols(df)


      df <- df %>%
        dplyr::mutate_at(c(
          "team_id"), as.integer) %>%
        make_hoopR_data("ESPN NBA Team Season Stats from ESPN.com",Sys.time())

    },
    error = function(e) {
      message(glue::glue("{Sys.time()}:Invalid arguments or no team season stats data available!"))
    },
    warning = function(w) {
    },
    finally = {
    }
  )
  return(df)
}

#' @title
#' **Get ESPN NBA player stats data**
#' @author Saiem Gilani
#' @param athlete_id Athlete ID
#' @param year Year
#' @param season_type (character, default: regular): Season type - regular or postseason
#' @param total (boolean, default: FALSE): Totals
#' @return Returns a tibble with the player stats data
#'
#'    |col_name                                         |types     |
#'    |:------------------------------------------------|:---------|
#'    |athlete_id                                       |integer   |
#'    |athlete_uid                                      |character |
#'    |athlete_guid                                     |character |
#'    |athlete_type                                     |character |
#'    |sdr                                              |integer   |
#'    |first_name                                       |character |
#'    |last_name                                        |character |
#'    |full_name                                        |character |
#'    |display_name                                     |character |
#'    |short_name                                       |character |
#'    |weight                                           |numeric   |
#'    |display_weight                                   |character |
#'    |height                                           |numeric   |
#'    |display_height                                   |character |
#'    |age                                              |integer   |
#'    |date_of_birth                                    |character |
#'    |slug                                             |character |
#'    |headshot_href                                    |character |
#'    |headshot_alt                                     |character |
#'    |jersey                                           |character |
#'    |position_id                                      |integer   |
#'    |position_name                                    |character |
#'    |position_display_name                            |character |
#'    |position_abbreviation                            |character |
#'    |position_leaf                                    |logical   |
#'    |linked                                           |logical   |
#'    |years                                            |integer   |
#'    |active                                           |logical   |
#'    |contract_x_ref                                   |character |
#'    |contract_bird_status                             |integer   |
#'    |contract_active                                  |logical   |
#'    |contract_active_1                                |logical   |
#'    |contract_incoming_trade_value                    |integer   |
#'    |contract_outgoing_trade_value                    |integer   |
#'    |contract_minimum_salary_exception                |logical   |
#'    |contract_option_type                             |integer   |
#'    |contract_salary                                  |integer   |
#'    |contract_salary_remaining                        |integer   |
#'    |contract_years_remaining                         |integer   |
#'    |contract_x_ref_1                                 |character |
#'    |contract_x_ref_2                                 |character |
#'    |contract_trade_kicker_active                     |logical   |
#'    |contract_trade_kicker_percentage                 |numeric   |
#'    |contract_trade_kicker_value                      |integer   |
#'    |contract_trade_kicker_trade_value                |integer   |
#'    |contract_trade_restriction                       |logical   |
#'    |contract_unsigned_foreign_pick                   |logical   |
#'    |contract_active_2                                |logical   |
#'    |draft_display_text                               |character |
#'    |draft_round                                      |integer   |
#'    |draft_year                                       |integer   |
#'    |draft_selection                                  |integer   |
#'    |draft_x_ref                                      |character |
#'    |draft_x_ref_1                                    |character |
#'    |status_id                                        |integer   |
#'    |status_name                                      |character |
#'    |status_type                                      |character |
#'    |status_abbreviation                              |character |
#'    |defensive_blocks                                 |numeric   |
#'    |defensive_defensive_rebounds                     |numeric   |
#'    |defensive_steals                                 |numeric   |
#'    |defensive_def_rebound_rate                       |numeric   |
#'    |defensive_avg_defensive_rebounds                 |numeric   |
#'    |defensive_avg_blocks                             |numeric   |
#'    |defensive_avg_steals                             |numeric   |
#'    |defensive_avg48defensive_rebounds                |numeric   |
#'    |defensive_avg48blocks                            |numeric   |
#'    |defensive_avg48steals                            |numeric   |
#'    |defensive_drpm                                   |numeric   |
#'    |general_disqualifications                        |numeric   |
#'    |general_flagrant_fouls                           |numeric   |
#'    |general_fouls                                    |numeric   |
#'    |general_per                                      |numeric   |
#'    |general_rebound_rate                             |numeric   |
#'    |general_ejections                                |numeric   |
#'    |general_technical_fouls                          |numeric   |
#'    |general_rebounds                                 |numeric   |
#'    |general_vorp                                     |numeric   |
#'    |general_warp                                     |numeric   |
#'    |general_rpm                                      |numeric   |
#'    |general_minutes                                  |numeric   |
#'    |general_avg_minutes                              |numeric   |
#'    |general_nba_rating                               |numeric   |
#'    |general_plus_minus                               |numeric   |
#'    |general_avg_rebounds                             |numeric   |
#'    |general_avg_fouls                                |numeric   |
#'    |general_avg_flagrant_fouls                       |numeric   |
#'    |general_avg_technical_fouls                      |numeric   |
#'    |general_avg_ejections                            |numeric   |
#'    |general_avg_disqualifications                    |numeric   |
#'    |general_assist_turnover_ratio                    |numeric   |
#'    |general_steal_foul_ratio                         |numeric   |
#'    |general_block_foul_ratio                         |numeric   |
#'    |general_avg_team_rebounds                        |numeric   |
#'    |general_total_rebounds                           |numeric   |
#'    |general_total_technical_fouls                    |numeric   |
#'    |general_team_assist_turnover_ratio               |numeric   |
#'    |general_steal_turnover_ratio                     |numeric   |
#'    |general_avg48rebounds                            |numeric   |
#'    |general_avg48fouls                               |numeric   |
#'    |general_avg48flagrant_fouls                      |numeric   |
#'    |general_avg48technical_fouls                     |numeric   |
#'    |general_avg48ejections                           |numeric   |
#'    |general_avg48disqualifications                   |numeric   |
#'    |general_r40                                      |numeric   |
#'    |general_games_played                             |numeric   |
#'    |general_games_started                            |numeric   |
#'    |general_double_double                            |numeric   |
#'    |general_triple_double                            |numeric   |
#'    |offensive_assists                                |numeric   |
#'    |offensive_effective_fg_pct                       |numeric   |
#'    |offensive_field_goals                            |numeric   |
#'    |offensive_field_goals_attempted                  |numeric   |
#'    |offensive_field_goals_made                       |numeric   |
#'    |offensive_field_goal_pct                         |numeric   |
#'    |offensive_free_throws                            |numeric   |
#'    |offensive_free_throw_pct                         |numeric   |
#'    |offensive_free_throws_attempted                  |numeric   |
#'    |offensive_free_throws_made                       |numeric   |
#'    |offensive_offensive_rebounds                     |numeric   |
#'    |offensive_points                                 |numeric   |
#'    |offensive_turnovers                              |numeric   |
#'    |offensive_three_point_pct                        |numeric   |
#'    |offensive_three_point_field_goals_attempted      |numeric   |
#'    |offensive_three_point_field_goals_made           |numeric   |
#'    |offensive_true_shooting_pct                      |numeric   |
#'    |offensive_total_turnovers                        |numeric   |
#'    |offensive_assist_ratio                           |numeric   |
#'    |offensive_points_in_paint                        |numeric   |
#'    |offensive_off_rebound_rate                       |numeric   |
#'    |offensive_turnover_ratio                         |numeric   |
#'    |offensive_brick_index                            |numeric   |
#'    |offensive_usage_rate                             |numeric   |
#'    |offensive_avg_field_goals_made                   |numeric   |
#'    |offensive_avg_field_goals_attempted              |numeric   |
#'    |offensive_avg_three_point_field_goals_made       |numeric   |
#'    |offensive_avg_three_point_field_goals_attempted  |numeric   |
#'    |offensive_avg_free_throws_made                   |numeric   |
#'    |offensive_avg_free_throws_attempted              |numeric   |
#'    |offensive_avg_points                             |numeric   |
#'    |offensive_avg_offensive_rebounds                 |numeric   |
#'    |offensive_avg_assists                            |numeric   |
#'    |offensive_avg_turnovers                          |numeric   |
#'    |offensive_offensive_rebound_pct                  |numeric   |
#'    |offensive_estimated_possessions                  |numeric   |
#'    |offensive_avg_estimated_possessions              |numeric   |
#'    |offensive_points_per_estimated_possessions       |numeric   |
#'    |offensive_avg_team_turnovers                     |numeric   |
#'    |offensive_avg_total_turnovers                    |numeric   |
#'    |offensive_three_point_field_goal_pct             |numeric   |
#'    |offensive_two_point_field_goals_made             |numeric   |
#'    |offensive_two_point_field_goals_attempted        |numeric   |
#'    |offensive_avg_two_point_field_goals_made         |numeric   |
#'    |offensive_avg_two_point_field_goals_attempted    |numeric   |
#'    |offensive_two_point_field_goal_pct               |numeric   |
#'    |offensive_shooting_efficiency                    |numeric   |
#'    |offensive_scoring_efficiency                     |numeric   |
#'    |offensive_avg48field_goals_made                  |numeric   |
#'    |offensive_avg48field_goals_attempted             |numeric   |
#'    |offensive_avg48three_point_field_goals_made      |numeric   |
#'    |offensive_avg48three_point_field_goals_attempted |numeric   |
#'    |offensive_avg48free_throws_made                  |numeric   |
#'    |offensive_avg48free_throws_attempted             |numeric   |
#'    |offensive_avg48points                            |numeric   |
#'    |offensive_avg48offensive_rebounds                |numeric   |
#'    |offensive_avg48assists                           |numeric   |
#'    |offensive_avg48turnovers                         |numeric   |
#'    |offensive_p40                                    |numeric   |
#'    |offensive_a40                                    |numeric   |
#'    |offensive_orpm                                   |numeric   |
#'    |team_id                                          |integer   |
#'    |team_guid                                        |character |
#'    |team_uid                                         |character |
#'    |team_slug                                        |character |
#'    |team_location                                    |character |
#'    |team_name                                        |character |
#'    |team_abbreviation                                |character |
#'    |team_display_name                                |character |
#'    |team_short_display_name                          |character |
#'    |team_color                                       |character |
#'    |team_alternate_color                             |character |
#'    |team_is_active                                   |logical   |
#'    |team_is_all_star                                 |logical   |
#'    |logo_href                                        |character |
#'    |logo_dark_href                                   |character |
#'    |logos_href_2                                     |character |
#'    |logos_href_3                                     |character |
#'
#' @export
#' @keywords NBA Player Stats
#' @family ESPN NBA Functions
#' @examples
#' \donttest{
#'   try(espn_nba_player_stats(athlete_id = 4433134, year = 2022))
#' }

espn_nba_player_stats <- function(athlete_id, year, season_type='regular', total=FALSE){
  if (!(tolower(season_type) %in% c("regular","postseason"))) {
    # Check if season_type is appropriate, if not regular
    cli::cli_abort("Enter valid season_type: regular or postseason")
  }
  s_type <- ifelse(season_type == "postseason", 3, 2)

  base_url <- "https://sports.core.api.espn.com/v2/sports/basketball/leagues/nba/seasons/"

  totals <- ifelse(total == TRUE, 0, "")
  full_url <- paste0(
    base_url,
    year,
    '/types/',s_type,
    '/athletes/', athlete_id,
    '/statistics/', totals
  )
  athlete_url <- paste0(
    base_url,
    year,
    '/athletes/', athlete_id
  )
  df <- data.frame()
  tryCatch(
    expr = {

      # Create the GET request and set response as res
      res <- httr::RETRY("GET", full_url)

      # Check the result
      check_status(res)
      # Create the GET request and set response as res
      athlete_res <- httr::RETRY("GET", athlete_url)

      # Check the result
      check_status(athlete_res)

      athlete_df <- athlete_res %>%
        httr::content(as = "text", encoding = "UTF-8") %>%
        jsonlite::fromJSON(simplifyDataFrame = FALSE, simplifyVector = FALSE, simplifyMatrix = FALSE)

      team_url <- athlete_df[["team"]][["$ref"]]

      # Create the GET request and set response as res
      team_res <- httr::RETRY("GET", team_url)

      # Check the result
      check_status(team_res)

      team_df <- team_res %>%
        httr::content(as = "text", encoding = "UTF-8") %>%
        jsonlite::fromJSON(simplifyDataFrame = FALSE, simplifyVector = FALSE, simplifyMatrix = FALSE)

      team_df[["links"]] <- NULL
      team_df[["injuries"]] <- NULL
      team_df[["record"]] <- NULL
      team_df[["athletes"]] <- NULL
      team_df[["venue"]] <- NULL
      team_df[["groups"]] <- NULL
      team_df[["ranks"]] <- NULL
      team_df[["statistics"]] <- NULL
      team_df[["leaders"]] <- NULL
      team_df[["links"]] <- NULL
      team_df[["notes"]] <- NULL
      team_df[["franchise"]] <- NULL
      team_df[["againstTheSpreadRecords"]] <- NULL
      team_df[["oddsRecords"]] <- NULL
      team_df[["college"]] <- NULL
      team_df[["transactions"]] <- NULL
      team_df[["leaders"]] <- NULL
      team_df[["depthCharts"]] <- NULL
      team_df[["awards"]] <- NULL
      team_df[["events"]] <- NULL


      team_df <- team_df %>%
        purrr::map_if(is.list,as.data.frame) %>%
        as.data.frame() %>%
        dplyr::select(
          -dplyr::any_of(
            c("logos.width",
              "logos.height",
              "logos.alt",
              "logos.rel..full.",
              "logos.rel..default.",
              "logos.rel..scoreboard.",
              "logos.rel..scoreboard..1",
              "logos.rel..scoreboard.2",
              "logos.lastUpdated",
              "logos.width.1",
              "logos.height.1",
              "logos.alt.1",
              "logos.rel..full..1",
              "logos.rel..dark.",
              "logos.rel..dark..1",
              "logos.lastUpdated.1",
              "logos.width.2",
              "logos.height.2",
              "logos.alt.2",
              "logos.rel..full..2",
              "logos.rel..scoreboard.",
              "logos.lastUpdated.2",
              "logos.width.3",
              "logos.height.3",
              "logos.alt.3",
              "logos.rel..full..3",
              "logos.lastUpdated.3",
              "X.ref",
              "X.ref.1",
              "X.ref.2"))) %>%
        janitor::clean_names()
      colnames(team_df)[1:13] <- paste0("team_",colnames(team_df)[1:13])

      team_df <- team_df %>%
        dplyr::rename(
          "logo_href" = "logos_href",
          "logo_dark_href" = "logos_href_1")


      athlete_df[["links"]] <- NULL
      athlete_df[["injuries"]] <- NULL
      athlete_df[["birthPlace"]] <- NULL

      athlete_df <- athlete_df %>%
        purrr::map_if(is.list, as.data.frame) %>%
        tibble::tibble(data = .data$.)
      athlete_df <- athlete_df$data %>%
        as.data.frame() %>%
        dplyr::select(-dplyr::any_of(c("X.ref","X.ref.1","X.ref.2","X.ref.3","X.ref.4","X.ref.5","X.ref.6","X.ref.7","X.ref.8",
                                       "position.X.ref","position.X.ref.1",
                                       "contract.x.ref","contract.x.ref.1","contract.x.ref.2",
                                       "draft.x.ref","draft.x.ref.1"))) %>%
        janitor::clean_names() %>%
        dplyr::rename(
          "athlete_id" = "id",
          "athlete_uid" = "uid",
          "athlete_guid" = "guid",
          "athlete_type" = "type")


      # Get the content and return result as data.frame
      df <- res %>%
        httr::content(as = "text", encoding = "UTF-8") %>%
        jsonlite::fromJSON() %>%
        purrr::pluck("splits") %>%
        purrr::pluck("categories") %>%
        tidyr::unnest("stats", names_sep = "_")
      df <- df %>%
        dplyr::mutate(
          stats_category_name = glue::glue("{.data$name}_{.data$stats_name}")) %>%
        dplyr::select("stats_category_name", "stats_value") %>%
        tidyr::pivot_wider(names_from = "stats_category_name",
                           values_from = "stats_value",
                           values_fn = dplyr::first) %>%
        janitor::clean_names()
      df <- athlete_df %>%
        dplyr::bind_cols(df) %>%
        dplyr::bind_cols(team_df)
      df <- df %>%
        dplyr::mutate_at(c(
          "athlete_id",
          "team_id",
          "position_id",
          "status_id",
          "sdr"), as.integer) %>%
        make_hoopR_data("ESPN NBA Player Season Stats from ESPN.com",Sys.time())

    },
    error = function(e) {
      message(glue::glue("{Sys.time()}:Invalid arguments or no player season stats data available!"))
    },
    warning = function(w) {
    },
    finally = {
    }
  )
  return(df)
}

#'  **Parse ESPN NBA PBP, helper function**
#' @param resp Response object from the ESPN NBA game summary endpoint
#' @return Returns a tibble
#' @importFrom lubridate with_tz ymd_hm
#' @export
helper_espn_nba_pbp <- function(resp){

  game_json <- resp %>%
    jsonlite::fromJSON()

  pbp_source <- game_json[["header"]][["competitions"]][["playByPlaySource"]]

  plays <- game_json %>%
    purrr::pluck("plays") %>%
    dplyr::as_tibble()

  if (pbp_source != "none" && nrow(plays) > 10) {
    homeAway1 <- jsonlite::fromJSON(resp)[['header']][['competitions']][['competitors']][[1]][['homeAway']][1]

    gameId <- as.integer(game_json[["header"]][["id"]])
    season <- game_json[['header']][['season']][['year']]
    season_type <- game_json[['header']][['season']][['type']]
    game_date_time <- substr(game_json[['header']][['competitions']][['date']], 1,
                             nchar(game_json[['header']][['competitions']][['date']]) - 1) %>%
      lubridate::ymd_hm() %>%
      lubridate::with_tz(tzone = "America/New_York")

    game_date <- as.Date(substr(game_date_time, 0, 10))

    id_vars <- data.frame()
    if (homeAway1 == "home") {

      homeTeamId = as.integer(game_json[["header"]][["competitions"]][["competitors"]][[1]][['team']][['id']] %>%
                                purrr::pluck(1, .default = NA_integer_))
      homeTeamMascot = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['name']] %>%
        purrr::pluck(1, .default = NA_character_)
      homeTeamName = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['location']] %>%
        purrr::pluck(1, .default = NA_character_)
      homeTeamAbbrev = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['abbreviation']] %>%
        purrr::pluck(1, .default = NA_character_)
      homeTeamLogo = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['logos']][[1]][['href']] %>%
        purrr::pluck(1, .default = NA_character_)
      homeTeamLogoDark = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['logos']][[1]][['href']] %>%
        purrr::pluck(2, .default = NA_character_)
      homeTeamFullName = game_json[['header']][['competitions']][['competitors']][[1]][['team']][["displayName"]] %>%
        purrr::pluck(1, .default = NA_character_)
      homeTeamColor = game_json[['header']][['competitions']][['competitors']][[1]][['team']][["color"]] %>%
        purrr::pluck(1, .default = NA_character_)
      homeTeamAlternateColor = game_json[['header']][['competitions']][['competitors']][[1]][['team']][["alternateColor"]] %>%
        purrr::pluck(1, .default = NA_character_)
      homeTeamScore = as.integer(game_json[['header']][['competitions']][['competitors']][[1]][['score']] %>%
                                   purrr::pluck(1, .default = NA_character_))
      homeTeamWinner = game_json[['header']][['competitions']][['competitors']][[1]][['winner']] %>%
        purrr::pluck(1, .default = NA_character_)
      homeTeamRecord = game_json[['header']][['competitions']][['competitors']][[1]][['record']][[1]][['summary']] %>%
        purrr::pluck(1, .default = NA_character_)
      awayTeamId = as.integer(game_json[['header']][['competitions']][['competitors']][[1]][['team']][['id']] %>%
                                purrr::pluck(2, .default = NA_integer_))
      awayTeamMascot = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['name']] %>%
        purrr::pluck(2, .default = NA_character_)
      awayTeamName = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['location']] %>%
        purrr::pluck(2, .default = NA_character_)
      awayTeamAbbrev = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['abbreviation']] %>%
        purrr::pluck(2, .default = NA_character_)
      awayTeamLogo = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['logos']][[2]][['href']] %>%
        purrr::pluck(1, .default = NA_character_)
      awayTeamLogoDark = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['logos']][[2]][['href']] %>%
        purrr::pluck(2, .default = NA_character_)
      awayTeamFullName = game_json[['header']][['competitions']][['competitors']][[1]][['team']][["displayName"]] %>%
        purrr::pluck(2, .default = NA_character_)
      awayTeamColor = game_json[['header']][['competitions']][['competitors']][[1]][['team']][["color"]] %>%
        purrr::pluck(2, .default = NA_character_)
      awayTeamAlternateColor = game_json[['header']][['competitions']][['competitors']][[1]][['team']][["alternateColor"]] %>%
        purrr::pluck(2, .default = NA_character_)
      awayTeamScore = as.integer(game_json[['header']][['competitions']][['competitors']][[1]][['score']] %>%
                                   purrr::pluck(2, .default = NA_integer_))
      awayTeamWinner = game_json[['header']][['competitions']][['competitors']][[1]][['winner']] %>%
        purrr::pluck(2, .default = NA_character_)
      awayTeamRecord = game_json[['header']][['competitions']][['competitors']][[1]][['record']][[1]][['summary']] %>%
        purrr::pluck(2, .default = NA_character_)
      id_vars <- data.frame(
        homeTeamId,
        homeTeamMascot,
        homeTeamName,
        homeTeamAbbrev,
        homeTeamLogo,
        homeTeamLogoDark,
        homeTeamFullName,
        homeTeamColor,
        homeTeamAlternateColor,
        homeTeamScore,
        homeTeamWinner,
        homeTeamRecord,
        awayTeamId,
        awayTeamMascot,
        awayTeamName,
        awayTeamAbbrev,
        awayTeamLogo,
        awayTeamLogoDark,
        awayTeamFullName,
        awayTeamColor,
        awayTeamAlternateColor,
        awayTeamScore,
        awayTeamWinner,
        awayTeamRecord
      )
    } else {

      awayTeamId = as.integer(game_json[["header"]][["competitions"]][["competitors"]][[1]][['team']][['id']] %>%
                                purrr::pluck(1, .default = NA_integer_))
      awayTeamMascot = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['name']] %>%
        purrr::pluck(1, .default = NA_character_)
      awayTeamName = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['location']] %>%
        purrr::pluck(1, .default = NA_character_)
      awayTeamAbbrev = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['abbreviation']] %>%
        purrr::pluck(1, .default = NA_character_)
      awayTeamLogo = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['logos']][[1]][['href']] %>%
        purrr::pluck(1, .default = NA_character_)
      awayTeamLogoDark = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['logos']][[1]][['href']] %>%
        purrr::pluck(2, .default = NA_character_)
      awayTeamFullName = game_json[['header']][['competitions']][['competitors']][[1]][['team']][["displayName"]] %>%
        purrr::pluck(1, .default = NA_character_)
      awayTeamColor = game_json[['header']][['competitions']][['competitors']][[1]][['team']][["color"]] %>%
        purrr::pluck(1, .default = NA_character_)
      awayTeamAlternateColor = game_json[['header']][['competitions']][['competitors']][[1]][['team']][["alternateColor"]] %>%
        purrr::pluck(1, .default = NA_character_)
      awayTeamScore = as.integer(game_json[['header']][['competitions']][['competitors']][[1]][['score']] %>%
                                   purrr::pluck(1, .default = NA_integer_))
      awayTeamWinner = game_json[['header']][['competitions']][['competitors']][[1]][['winner']] %>%
        purrr::pluck(1, .default = NA_character_)
      awayTeamRecord = game_json[['header']][['competitions']][['competitors']][[1]][['record']][[1]][['summary']] %>%
        purrr::pluck(1, .default = NA_character_)
      homeTeamId = as.integer(game_json[['header']][['competitions']][['competitors']][[1]][['team']][['id']] %>%
                                purrr::pluck(2, .default = NA_integer_))
      homeTeamMascot = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['name']] %>%
        purrr::pluck(2, .default = NA_character_)
      homeTeamName = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['location']] %>%
        purrr::pluck(2, .default = NA_character_)
      homeTeamAbbrev = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['abbreviation']] %>%
        purrr::pluck(2, .default = NA_character_)
      homeTeamLogo = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['logos']][[2]][['href']] %>%
        purrr::pluck(2, .default = NA_character_)
      homeTeamLogoDark = game_json[['header']][['competitions']][['competitors']][[1]][['team']][['logos']][[2]][['href']] %>%
        purrr::pluck(2, .default = NA_character_)
      homeTeamFullName = game_json[['header']][['competitions']][['competitors']][[1]][['team']][["displayName"]] %>%
        purrr::pluck(2, .default = NA_character_)
      homeTeamColor = game_json[['header']][['competitions']][['competitors']][[1]][['team']][["color"]] %>%
        purrr::pluck(2, .default = NA_character_)
      homeTeamAlternateColor = game_json[['header']][['competitions']][['competitors']][[1]][['team']][["alternateColor"]] %>%
        purrr::pluck(2, .default = NA_character_)
      homeTeamScore = as.integer(game_json[['header']][['competitions']][['competitors']][[1]][['score']] %>%
                                   purrr::pluck(2, .default = NA_integer_))
      homeTeamWinner = game_json[['header']][['competitions']][['competitors']][[1]][['winner']] %>%
        purrr::pluck(2, .default = NA_character_)
      homeTeamRecord = game_json[['header']][['competitions']][['competitors']][[1]][['record']][[1]][['summary']] %>%
        purrr::pluck(2, .default = NA_character_)
      id_vars <- data.frame(
        homeTeamId,
        homeTeamMascot,
        homeTeamName,
        homeTeamAbbrev,
        homeTeamLogo,
        homeTeamLogoDark,
        homeTeamFullName,
        homeTeamColor,
        homeTeamAlternateColor,
        homeTeamScore,
        homeTeamWinner,
        homeTeamRecord,
        awayTeamId,
        awayTeamMascot,
        awayTeamName,
        awayTeamAbbrev,
        awayTeamLogo,
        awayTeamLogoDark,
        awayTeamFullName,
        awayTeamColor,
        awayTeamAlternateColor,
        awayTeamScore,
        awayTeamWinner,
        awayTeamRecord
      )

    }

    game_json <- game_json %>%
      jsonlite::toJSON() %>%
      jsonlite::fromJSON(flatten = TRUE)


    plays <- game_json %>%
      purrr::pluck("plays")

    if ("coordinate.x" %in% names(plays) & "coordinate.y" %in% names(plays)) {
      plays <- plays %>%
        dplyr::mutate(
          # convert types
          coordinate.x = as.double(.data$coordinate.x),
          coordinate.y = as.double(.data$coordinate.y),
          # Free throws are adjusted automatically to 19' from baseline, which
          # corresponds to 13.75' from the center of the basket (originally
          # the center of the basket is (25, 0))
          coordinate.y = dplyr::case_when(
            stringr::str_detect(.data$type.text, "Free Throw") ~ 13.75,
            TRUE ~ .data$coordinate.y
          ),
          coordinate.x = dplyr::case_when(
            stringr::str_detect(.data$type.text, "Free Throw") ~ 25,
            TRUE ~ .data$coordinate.x
          ),
          coordinate_x_transformed = dplyr::case_when(
            .data$team.id == homeTeamId ~ -1 * (.data$coordinate.y - 41.75),
            TRUE ~ .data$coordinate.y - 41.75
          ),
          coordinate_y_transformed = dplyr::case_when(
            .data$team.id == homeTeamId ~ -1 * (.data$coordinate.x - 25),
            TRUE ~ .data$coordinate.x - 25
          )
        ) %>%
        dplyr::rename(
          "coordinate.x.raw" = "coordinate.x",
          "coordinate.y.raw" = "coordinate.y",
          "coordinate.x" = "coordinate_x_transformed",
          "coordinate.y" = "coordinate_y_transformed"
        )
    }

    ## Written this way for compliance with data repository processing
    if ("participants" %in% names(plays)) {
      plays <- plays %>%
        tidyr::unnest_wider("participants")
      suppressWarnings(
        aths <- plays %>%
          dplyr::group_by(.data$id) %>%
          dplyr::select(
            "id",
            "athlete.id") %>%
          tidyr::unnest_wider("athlete.id", names_sep = "_")
      )
      names(aths) <- c("play.id", "athlete.id.1", "athlete.id.2", "athlete.id.3")
      plays <- plays %>%
        dplyr::bind_cols(aths) %>%
        janitor::clean_names() %>%
        dplyr::mutate(dplyr::across(dplyr::any_of(c(
          "athlete_id_1",
          "athlete_id_2",
          "athlete_id_3"
        )), ~as.integer(.x)))
    }
    ## Written this way for compliance with data repository processing
    if (!("homeTeamName" %in% names(plays))) {
      plays <- plays %>%
        dplyr::bind_cols(id_vars)
    }

    plays <- plays %>%
      dplyr::select(-dplyr::any_of(c("athlete.id", "athlete_id")))  %>%
      janitor::clean_names() %>%
      dplyr::mutate(
        game_id = gameId,
        season = season,
        season_type = season_type,
        game_date = game_date,
        game_date_time = game_date_time) %>%
      dplyr::rename(dplyr::any_of(c(
        "athlete_id_1" = "participants_0_athlete_id",
        "athlete_id_2" = "participants_1_athlete_id",
        "athlete_id_3" = "participants_2_athlete_id")))

    plays <- plays %>%
      dplyr::mutate(dplyr::across(dplyr::any_of(c(
        "athlete_id_1",
        "athlete_id_2",
        "athlete_id_3",
        "type_id",
        "team_id"
      )), ~as.integer(.x)))

    plays_df <- plays %>%
      make_hoopR_data("ESPN NBA Play-by-Play Information from ESPN.com", Sys.time())

    return(plays_df)
  }
}

#'  **Parse ESPN NBA Team Box, helper function**
#' @param resp Response object from the ESPN NBA game summary endpoint
#' @return Returns a tibble
#' @importFrom lubridate with_tz ymd_hm
#' @export
helper_espn_nba_team_box <- function(resp){

  game_json <- resp %>%
    jsonlite::fromJSON()

  gameId <- as.integer(game_json[["header"]][["id"]])
  game_date_time <- substr(game_json[['header']][['competitions']][['date']], 1,
                           nchar(game_json[['header']][['competitions']][['date']]) - 1) %>%
    lubridate::ymd_hm() %>%
    lubridate::with_tz(tzone = "America/New_York")

  game_date <- as.Date(substr(game_date_time, 0, 10))
  box_score_available <- game_json[["header"]][["competitions"]][["boxscoreAvailable"]]
  if (box_score_available == TRUE) {
    teams_box_score_df <- game_json[["boxscore"]][["teams"]] %>%
      jsonlite::toJSON() %>%
      jsonlite::fromJSON(flatten = TRUE)
    if (length(teams_box_score_df[["statistics"]][[1]]) > 0) {
      # Teams info columns and values
      teams_df <- game_json[["header"]][["competitions"]][["competitors"]][[1]]

      homeAway1 <- teams_df[["homeAway"]][1]
      homeAway1_team.id <- as.integer(teams_df[["id"]][1])
      homeAway1_team.score <- as.integer(teams_df[["score"]][1])
      homeAway1_team.winner <- teams_df[["winner"]][1]

      homeAway2 <- teams_df[["homeAway"]][2]
      homeAway2_team.id <- as.integer(teams_df[["id"]][2])
      homeAway2_team.score <- as.integer(teams_df[["score"]][2])
      homeAway2_team.winner <- teams_df[["winner"]][2]

      # Pivoting the table values for each team from long to wide
      statistics_df_1 <- teams_box_score_df[["statistics"]][[1]] %>%
        tibble::tibble() %>%
        dplyr::select("name", "displayValue") %>%
        tidyr::spread("name", "displayValue")

      statistics_df_2 <- teams_box_score_df[["statistics"]][[2]] %>%
        tibble::tibble() %>%
        dplyr::select("name", "displayValue") %>%
        tidyr::spread("name", "displayValue")

      # Assigning values to the correct data frame rows - 1
      statistics_df_1$team.homeAway <- ifelse(
        as.integer(teams_box_score_df[["team.id"]][1]) == as.integer(homeAway1_team.id),
        homeAway1,
        homeAway2
      )
      statistics_df_1$team.score <- ifelse(
        as.integer(teams_box_score_df[["team.id"]][1]) == as.integer(homeAway1_team.id),
        as.integer(homeAway1_team.score),
        as.integer(homeAway2_team.score)
      )
      statistics_df_1$team.winner <- ifelse(
        as.integer(teams_box_score_df[["team.id"]][1]) == as.integer(homeAway1_team.id),
        homeAway1_team.winner,
        homeAway2_team.winner
      )
      statistics_df_1$team.id <- as.integer(teams_box_score_df[["team.id"]][[1]])
      statistics_df_1$team.uid <- teams_box_score_df[["team.uid"]][[1]]
      statistics_df_1$team.slug <- teams_box_score_df[["team.slug"]][[1]]
      statistics_df_1$team.location <- teams_box_score_df[["team.location"]][[1]]
      statistics_df_1$team.name <- teams_box_score_df[["team.name"]][[1]]
      statistics_df_1$team.abbreviation <- teams_box_score_df[["team.abbreviation"]][[1]]
      statistics_df_1$team.displayName <- teams_box_score_df[["team.displayName"]][[1]]
      statistics_df_1$team.shortDisplayName <- teams_box_score_df[["team.shortDisplayName"]][[1]]
      statistics_df_1$team.color <- teams_box_score_df[["team.color"]][[1]]
      statistics_df_1$team.alternateColor <- teams_box_score_df[["team.alternateColor"]][[1]]
      statistics_df_1$team.logo <- teams_box_score_df[["team.logo"]][[1]]
      statistics_df_1$opponent.team.id <- as.integer(teams_box_score_df[["team.id"]][[2]])
      statistics_df_1$opponent.team.uid <- teams_box_score_df[["team.uid"]][[2]]
      statistics_df_1$opponent.team.slug <- teams_box_score_df[["team.slug"]][[2]]
      statistics_df_1$opponent.team.location <- teams_box_score_df[["team.location"]][[2]]
      statistics_df_1$opponent.team.name <- teams_box_score_df[["team.name"]][[2]]
      statistics_df_1$opponent.team.abbreviation <- teams_box_score_df[["team.abbreviation"]][[2]]
      statistics_df_1$opponent.team.displayName <- teams_box_score_df[["team.displayName"]][[2]]
      statistics_df_1$opponent.team.shortDisplayName <- teams_box_score_df[["team.shortDisplayName"]][[2]]
      statistics_df_1$opponent.team.color <- teams_box_score_df[["team.color"]][[2]]
      statistics_df_1$opponent.team.alternateColor <- teams_box_score_df[["team.alternateColor"]][[2]]
      statistics_df_1$opponent.team.logo <- teams_box_score_df[["team.logo"]][[2]]
      statistics_df_1$opponent.team.score <- ifelse(
        as.integer(teams_box_score_df[["team.id"]][1]) == as.integer(homeAway1_team.id),
        as.integer(homeAway2_team.score),
        as.integer(homeAway1_team.score)
      )
      # Assigning values to the correct data frame rows - 2
      statistics_df_2$team.homeAway <- ifelse(
        as.integer(teams_box_score_df[["team.id"]][2]) == as.integer(homeAway2_team.id),
        homeAway2,
        homeAway1
      )
      statistics_df_2$team.score <- ifelse(
        as.integer(teams_box_score_df[["team.id"]][2]) == as.integer(homeAway2_team.id),
        as.integer(homeAway2_team.score),
        as.integer(homeAway1_team.score)
      )
      statistics_df_2$team.winner <- ifelse(
        as.integer(teams_box_score_df[["team.id"]][2]) == as.integer(homeAway2_team.id),
        homeAway2_team.winner,
        homeAway1_team.winner
      )
      statistics_df_2$team.id <- as.integer(teams_box_score_df[["team.id"]][[2]])
      statistics_df_2$team.uid <- teams_box_score_df[["team.uid"]][[2]]
      statistics_df_2$team.slug <- teams_box_score_df[["team.slug"]][[2]]
      statistics_df_2$team.location <- teams_box_score_df[["team.location"]][[2]]
      statistics_df_2$team.name <- teams_box_score_df[["team.name"]][[2]]
      statistics_df_2$team.abbreviation <- teams_box_score_df[["team.abbreviation"]][[2]]
      statistics_df_2$team.displayName <- teams_box_score_df[["team.displayName"]][[2]]
      statistics_df_2$team.shortDisplayName <- teams_box_score_df[["team.shortDisplayName"]][[2]]
      statistics_df_2$team.color <- teams_box_score_df[["team.color"]][[2]]
      statistics_df_2$team.alternateColor <- teams_box_score_df[["team.alternateColor"]][[2]]
      statistics_df_2$team.logo <- teams_box_score_df[["team.logo"]][[2]]
      statistics_df_2$opponent.team.id <- as.integer(teams_box_score_df[["team.id"]][[1]])
      statistics_df_2$opponent.team.uid <- teams_box_score_df[["team.uid"]][[1]]
      statistics_df_2$opponent.team.slug <- teams_box_score_df[["team.slug"]][[1]]
      statistics_df_2$opponent.team.location <- teams_box_score_df[["team.location"]][[1]]
      statistics_df_2$opponent.team.name <- teams_box_score_df[["team.name"]][[1]]
      statistics_df_2$opponent.team.abbreviation <- teams_box_score_df[["team.abbreviation"]][[1]]
      statistics_df_2$opponent.team.displayName <- teams_box_score_df[["team.displayName"]][[1]]
      statistics_df_2$opponent.team.shortDisplayName <- teams_box_score_df[["team.shortDisplayName"]][[1]]
      statistics_df_2$opponent.team.color <- teams_box_score_df[["team.color"]][[1]]
      statistics_df_2$opponent.team.alternateColor <- teams_box_score_df[["team.alternateColor"]][[1]]
      statistics_df_2$opponent.team.logo <- teams_box_score_df[["team.logo"]][[1]]
      statistics_df_2$opponent.team.score <- ifelse(
        as.integer(teams_box_score_df[["team.id"]][2]) == as.integer(homeAway2_team.id),
        as.integer(homeAway1_team.score),
        as.integer(homeAway2_team.score)
      )
      complete_statistics_df <- statistics_df_1 %>%
        dplyr::bind_rows(statistics_df_2)

      # Assigning game/season level data to team box score and converting types
      complete_statistics_df$season <- game_json[["header"]][["season"]][["year"]]
      complete_statistics_df$season_type <- game_json[["header"]][["season"]][["type"]]
      complete_statistics_df$game_date <- as.Date(substr(game_json[["header"]][["competitions"]][["date"]], 0, 10))
      complete_statistics_df$game_id <- as.integer(gameId)
      complete_statistics_df$game_date_time <- game_date_time
      complete_statistics_df$game_date <- game_date

      suppressWarnings(
        complete_statistics_df <- complete_statistics_df %>%
          tidyr::separate("fieldGoalsMade-fieldGoalsAttempted",
                          into = c("fieldGoalsMade", "fieldGoalsAttempted"),
                          sep = "-") %>%
          tidyr::separate("freeThrowsMade-freeThrowsAttempted",
                          into = c("freeThrowsMade", "freeThrowsAttempted"),
                          sep = "-") %>%
          tidyr::separate("threePointFieldGoalsMade-threePointFieldGoalsAttempted",
                          into = c("threePointFieldGoalsMade", "threePointFieldGoalsAttempted"),
                          sep = "-") %>%
          dplyr::mutate(dplyr::across(c(
            "fieldGoalPct",
            "freeThrowPct",
            "threePointFieldGoalPct"
          ), ~as.numeric(.x))) %>%
          dplyr::mutate(dplyr::across(dplyr::any_of(c(
            "assists",
            "blocks",
            "defensiveRebounds",
            "fieldGoalsMade",
            "fieldGoalsAttempted",
            "flagrantFouls",
            "fouls",
            "freeThrowsMade",
            "freeThrowsAttempted",
            "offensiveRebounds",
            "steals",
            "teamTurnovers",
            "technicalFouls",
            "threePointFieldGoalsMade",
            "threePointFieldGoalsAttempted",
            "totalRebounds",
            "totalTechnicalFouls",
            "totalTurnovers",
            "turnovers"
          )), ~as.integer(.x)))
      )
      team_box_score <- complete_statistics_df %>%
        janitor::clean_names() %>%
        dplyr::select(dplyr::any_of(c(
          "game_id",
          "season",
          "season_type",
          "game_date",
          "game_date_time",
          "team_id",
          "team_uid",
          "team_slug",
          "team_location",
          "team_name",
          "team_abbreviation",
          "team_display_name",
          "team_short_display_name",
          "team_color",
          "team_alternate_color",
          "team_logo",
          "team_home_away",
          "team_score",
          "team_winner")),
          tidyr::everything()) %>%
        make_hoopR_data("ESPN NBA Team Box Information from ESPN.com", Sys.time())

      return(team_box_score)
    }
  }
}

#'  **Parse ESPN NBA Player Box, helper function**
#' @param resp Response object from the ESPN NBA game summary endpoint
#' @return Returns a tibble
#' @importFrom lubridate with_tz ymd_hm
#' @export
helper_espn_nba_player_box <- function(resp){

  game_json <- resp %>%
    jsonlite::fromJSON(flatten = TRUE)

  players_box_score_df <- game_json[["boxscore"]][["players"]] %>%
    jsonlite::toJSON() %>%
    jsonlite::fromJSON(flatten = TRUE) %>%
    as.data.frame()

  gameId <- as.integer(game_json[["header"]][["id"]])
  season <- game_json[["header"]][["season"]][["year"]]
  season_type <- game_json[["header"]][["season"]][["type"]]
  game_date_time <- substr(game_json[['header']][['competitions']][['date']], 1,
                           nchar(game_json[['header']][['competitions']][['date']]) - 1) %>%
    lubridate::ymd_hm() %>%
    lubridate::with_tz(tzone = "America/New_York")

  game_date <- as.Date(substr(game_date_time, 0, 10))

  boxScoreAvailable <- game_json[["header"]][["competitions"]][["boxscoreAvailable"]]

  boxScoreSource <- game_json[["header"]][["competitions"]][["boxscoreSource"]]

  # This is checking if  [[athletes]][[1]]'s stat rebounds is able to be converted to a numeric value
  #  without introducing NA's
  suppressWarnings(
    valid_stats <- players_box_score_df[["statistics"]][[1]][["athletes"]][[1]][["stats"]][[1]] %>%
      purrr::pluck(7) %>%
      as.numeric()
  )
  if (boxScoreAvailable == TRUE &&
      length(players_box_score_df[["statistics"]][[1]][["athletes"]][[1]]) > 1 &&
      !is.na(valid_stats)) {
    players_df <- players_box_score_df %>%
      tidyr::unnest("statistics") %>%
      tidyr::unnest("athletes")
    if (length(players_box_score_df[["statistics"]]) > 1 &&
        length(players_df$stats[[1]]) > 0) {

      players_df <- jsonlite::fromJSON(jsonlite::toJSON(game_json[["boxscore"]][["players"]]), flatten = TRUE) %>%
        tidyr::unnest("statistics") %>%
        tidyr::unnest("athletes")

      stat_cols <- players_df$keys[[1]]
      stats <- players_df$stats

      stats_df <- as.data.frame(do.call(rbind,stats))
      colnames(stats_df) <- stat_cols
      suppressWarnings(
        stats_df <- stats_df %>%
          tidyr::separate("fieldGoalsMade-fieldGoalsAttempted",
                          into = c("fieldGoalsMade", "fieldGoalsAttempted"),
                          sep = "-") %>%
          tidyr::separate("freeThrowsMade-freeThrowsAttempted",
                          into = c("freeThrowsMade", "freeThrowsAttempted"),
                          sep = "-") %>%
          tidyr::separate("threePointFieldGoalsMade-threePointFieldGoalsAttempted",
                          into = c("threePointFieldGoalsMade", "threePointFieldGoalsAttempted"),
                          sep = "-") %>%
          dplyr::mutate(dplyr::across(dplyr::any_of(c(
            "minutes",
            "fieldGoalPct",
            "freeThrowPct",
            "threePointFieldGoalPct"
          )), ~as.numeric(.x))) %>%
          dplyr::mutate(dplyr::across(dplyr::any_of(c(
            "assists",
            "blocks",
            "defensiveRebounds",
            "fieldGoalsMade",
            "fieldGoalsAttempted",
            "flagrantFouls",
            "fouls",
            "freeThrowsMade",
            "freeThrowsAttempted",
            "offensiveRebounds",
            "steals",
            "teamTurnovers",
            "technicalFouls",
            "threePointFieldGoalsMade",
            "threePointFieldGoalsAttempted",
            "rebounds",
            "totalTechnicalFouls",
            "totalTurnovers",
            "turnovers",
            "points"
          )), ~as.integer(.x)))
      )
      players_df_did_not_play <- players_df %>%
        dplyr::filter(.data$didNotPlay) %>%
        dplyr::select(dplyr::any_of(c(
          "starter",
          "ejected",
          "didNotPlay",
          "reason",
          "active",
          "athlete.displayName",
          "athlete.jersey",
          "athlete.id",
          "athlete.shortName",
          "athlete.headshot.href",
          "athlete.position.name",
          "athlete.position.abbreviation",
          "team.displayName",
          "team.shortDisplayName",
          "team.location",
          "team.name",
          "team.logo",
          "team.id",
          "team.uid",
          "team.slug",
          "team.abbreviation",
          "team.color",
          "team.alternateColor"
        )))

      players_df <- players_df %>%
        dplyr::filter(!.data$didNotPlay) %>%
        dplyr::select(dplyr::any_of(c(
          "starter",
          "ejected",
          "didNotPlay",
          "reason",
          "active",
          "athlete.displayName",
          "athlete.jersey",
          "athlete.id",
          "athlete.shortName",
          "athlete.headshot.href",
          "athlete.position.name",
          "athlete.position.abbreviation",
          "team.displayName",
          "team.shortDisplayName",
          "team.location",
          "team.name",
          "team.logo",
          "team.id",
          "team.uid",
          "team.slug",
          "team.abbreviation",
          "team.color",
          "team.alternateColor"
        )))

      players_df <- stats_df %>%
        dplyr::bind_cols(players_df) %>%
        dplyr::bind_rows(players_df_did_not_play)

      players_df <- players_df %>%
        dplyr::select(dplyr::any_of(c(
          "athlete.displayName",
          "team.shortDisplayName")),
          tidyr::everything()) %>%
        janitor::clean_names() %>%
        dplyr::mutate(
          game_id = gameId,
          season = season,
          season_type = season_type,
          game_date = game_date,
          game_date_time = game_date_time)


      teams_df <- game_json[["header"]][["competitions"]][["competitors"]][[1]]

      homeAway1 <- teams_df[["homeAway"]] %>%
        purrr::pluck(1, .default = NA_character_)
      homeAway1_team.id <- as.integer(teams_df[["id"]] %>%
                                        purrr::pluck(1, .default = NA_integer_))
      homeAway1_team.location <- teams_df[["team.location"]] %>%
        purrr::pluck(1, .default = NA_character_)
      homeAway1_team.name <- teams_df[["team.name"]] %>%
        purrr::pluck(1, .default = NA_character_)
      homeAway1_team.abbreviation <- teams_df[["team.abbreviation"]] %>%
        purrr::pluck(1, .default = NA_character_)
      homeAway1_team.displayName <- teams_df[["team.displayName"]] %>%
        purrr::pluck(1, .default = NA_character_)
      homeAway1_team.logos <- teams_df[["team.logos"]][[1]][["href"]] %>%
        purrr::pluck(1, .default = NA_character_)
      homeAway1_team.color <- teams_df[["team.color"]] %>%
        purrr::pluck(1, .default = NA_character_)
      homeAway1_team.alternateColor <- teams_df[["team.alternateColor"]] %>%
        purrr::pluck(1, .default = NA_character_)
      homeAway1_team.winner <- teams_df[["winner"]] %>%
        purrr::pluck(1, .default = NA_character_)
      homeAway1_team.score <- as.integer(teams_df[["score"]] %>%
        purrr::pluck(1, .default = NA_integer_))

      homeAway2 <- teams_df[["homeAway"]] %>%
        purrr::pluck(2, .default = NA_character_)
      homeAway2_team.id <- as.integer(teams_df[["id"]] %>%
                                        purrr::pluck(2, .default = NA_integer_))
      homeAway2_team.location <- teams_df[["team.location"]] %>%
        purrr::pluck(2, .default = NA_character_)
      homeAway2_team.name <- teams_df[["team.name"]] %>%
        purrr::pluck(2, .default = NA_character_)
      homeAway2_team.abbreviation <- teams_df[["team.abbreviation"]] %>%
        purrr::pluck(2, .default = NA_character_)
      homeAway2_team.displayName <- teams_df[["team.displayName"]] %>%
        purrr::pluck(2, .default = NA_character_)
      homeAway2_team.logos <- teams_df[["team.logos"]][[2]][["href"]] %>%
        purrr::pluck(1, .default = NA_character_)
      homeAway2_team.color <- teams_df[["team.color"]] %>%
        purrr::pluck(2, .default = NA_character_)
      homeAway2_team.alternateColor <- teams_df[["team.alternateColor"]] %>%
        purrr::pluck(2, .default = NA_character_)
      homeAway2_team.winner <- teams_df[["winner"]] %>%
        purrr::pluck(2, .default = NA_character_)
      homeAway2_team.score <- as.integer(teams_df[["score"]] %>%
                                           purrr::pluck(2, .default = NA_integer_))

      players_df <- players_df %>%
        dplyr::mutate(
          home_away = ifelse(.data$team_id == homeAway1_team.id, homeAway1, homeAway2),
          team_winner = ifelse(.data$team_id == homeAway1_team.id, homeAway1_team.winner, homeAway2_team.winner),
          team_score = ifelse(.data$team_id == homeAway1_team.id, homeAway1_team.score, homeAway2_team.score),
          opponent_team_id = ifelse(.data$team_id == homeAway1_team.id, homeAway2_team.id, homeAway1_team.id),
          opponent_team_name = ifelse(.data$team_id == homeAway1_team.id, homeAway2_team.name, homeAway1_team.name),
          opponent_team_location = ifelse(.data$team_id == homeAway1_team.id, homeAway2_team.location, homeAway1_team.location),
          opponent_team_display_name = ifelse(.data$team_id == homeAway1_team.id, homeAway2_team.displayName, homeAway1_team.displayName),
          opponent_team_abbreviation = ifelse(.data$team_id == homeAway1_team.id, homeAway2_team.abbreviation, homeAway1_team.abbreviation),
          opponent_team_logo = ifelse(.data$team_id == homeAway1_team.id, homeAway2_team.logos, homeAway1_team.logos),
          opponent_team_color = ifelse(.data$team_id == homeAway1_team.id, homeAway2_team.color, homeAway1_team.color),
          opponent_team_alternate_color = ifelse(.data$team_id == homeAway1_team.id, homeAway2_team.alternateColor, homeAway1_team.alternateColor),
          opponent_team_score = ifelse(.data$team_id == homeAway1_team.id, homeAway2_team.score, homeAway1_team.score),
        ) %>%
        dplyr::arrange(.data$home_away)

      player_box_score <- players_df %>%
        dplyr::select(dplyr::any_of(c(
          "game_id",
          "season",
          "season_type",
          "game_date",
          "game_date_time",
          "athlete_id",
          "athlete_display_name",
          "team_id",
          "team_name",
          "team_location",
          "team_short_display_name",
          "minutes",
          "field_goals_made",
          "field_goals_attempted",
          "three_point_field_goals_made",
          "three_point_field_goals_attempted",
          "free_throws_made",
          "free_throws_attempted",
          "offensive_rebounds",
          "defensive_rebounds",
          "rebounds",
          "assists",
          "steals",
          "blocks",
          "turnovers",
          "fouls",
          "plus_minus",
          "points",
          "starter",
          "ejected",
          "did_not_play",
          "reason",
          "active",
          "athlete_jersey",
          "athlete_short_name",
          "athlete_headshot_href",
          "athlete_position_name",
          "athlete_position_abbreviation",
          "team_display_name",
          "team_uid",
          "team_slug",
          "team_logo",
          "team_abbreviation",
          "team_color",
          "team_alternate_color",
          "home_away",
          "team_winner",
          "team_score",
          "opponent_team_id",
          "opponent_team_name",
          "opponent_team_location",
          "opponent_team_display_name",
          "opponent_team_abbreviation",
          "opponent_team_logo",
          "opponent_team_color",
          "opponent_team_alternate_color",
          "opponent_team_score"
        ))) %>%
        dplyr::mutate_at(c(
          "athlete_id",
          "team_id",
          "team_score",
          "opponent_team_score"
        ), as.integer) %>%
        make_hoopR_data("ESPN NBA Player Box Information from ESPN.com", Sys.time())

      return(player_box_score)
    }
  }
}

Try the hoopR package in your browser

Any scripts or data that you put into this service are public.

hoopR documentation built on Nov. 26, 2023, 1:07 a.m.