Spaces:
Sleeping
Sleeping
| library(shiny) | |
| library(plotly) | |
| library(gridlayout) | |
| library(bslib) | |
| library(DT) | |
| library(rsconnect) | |
| library(baseballr) | |
| library(dplyr) | |
| library(tidyverse) | |
| library(rvest) | |
| library(ggplot2) | |
| library(janitor) | |
| library(ggthemes) | |
| library(ggpubr) | |
| library(jsonlite) | |
| library(utils) | |
| library(grid) | |
| library(gridExtra) | |
| library(png) | |
| library(xgboost) | |
| library(httr) | |
| pdf(file = NULL) | |
| Sys.setenv(TZ='EST') | |
| is_barrel <- function(df) { | |
| df$barrel <- with(df, ifelse(hit_angle <= 50 & hit_speed >= 97 & hit_speed * 1.5 - | |
| hit_angle >= 117 & hit_speed + hit_angle >= 123, 1, 0)) | |
| return(df) | |
| } | |
| VAA <- function(milbtotal){ | |
| milbtotal <- milbtotal |> | |
| mutate(VAA = -atan((vz0+(az*(-sqrt((vy0*vy0)-(2*ay*(y0-(17/12))))-vy0)/ | |
| ay))/(-sqrt((vy0*vy0)-(2*ay*(y0-(17/12))))))*(180/pi)) | |
| } | |
| pitcher_summary <- function(game_pk,date){ | |
| gdate <- as.Date.character(date) | |
| gdate <- as.Date(gdate) | |
| tmilb <- mlb_pbp(game_pk) | |
| tmilb <- tmilb |> | |
| filter(type == "pitch") | |
| tmilb <- tmilb |> | |
| select(matchup.batter.fullName,matchup.batter.id,matchup.pitcher.fullName, | |
| matchup.pitcher.id,result.event,details.description,details.type.description, | |
| result.description,pitchData.startSpeed,pitchData.plateTime,pitchData.zone, | |
| pitchData.breaks.spinRate,pitchData.extension, pitchData.coordinates.pX, | |
| pitchData.coordinates.pZ,pitchData.coordinates.x0, pitchData.coordinates.y0, | |
| pitchData.coordinates.z0,pitchData.coordinates.aX,pitchData.coordinates.aY, | |
| pitchData.coordinates.aZ,pitchData.coordinates.vX0,pitchData.coordinates.vZ0, | |
| pitchData.coordinates.vY0,pitchData.coordinates.pfxX,pitchData.coordinates.pfxZ, | |
| pitchData.breaks.breakVerticalInduced,pitchData.breaks.breakHorizontal, | |
| hitData.launchSpeed,hitData.launchAngle,hitData.totalDistance,details.isInPlay, | |
| last.pitch.of.ab,pitchData.breaks.spinDirection,matchup.pitchHand.code) | |
| colnames(tmilb) <- c("Batter Name","Batter ID","Pitcher Name","Pitcher ID", | |
| "result","description","pitch_name","des","start_speed", | |
| "plateTime","zone","spin_rate","extension","px","pz","x0", | |
| "y0","z0","ax","ay","az","vx0","vz0","vy0","pfxX","pfxZ", | |
| "IVB","HB","hit_speed","hit_angle","hit_distance","inPlay", | |
| "lastPitch","spinDirection","phand") | |
| tmilb <- is_barrel(tmilb) | |
| tmilb <- tmilb |> | |
| mutate(is_strike_swinging = ifelse(description == "Swinging Strike" | | |
| description == "Foul Tip",TRUE,FALSE)) | |
| tmilb <- tmilb |> | |
| mutate(date = gdate) | |
| return(tmilb) | |
| } | |
| break_plot <- function(game){ | |
| ggplot()+ | |
| geom_point(game,mapping = | |
| aes(x=HB, y = IVB,color = pitch_name),size = 4) + | |
| geom_vline(xintercept = 0, color = "lightblue",linewidth = 1,linetype = 4)+ | |
| geom_hline(yintercept = 0, color = "lightblue",linewidth = 1,linetype = 4)+ | |
| xlab("Horizontal Break from Pitcher's Perspective (in) ")+ | |
| ylab("Induced Verical Break (in)") + | |
| xlim(-25,25) + | |
| ylim(-25,25) + | |
| ggthemes::theme_igray()+ | |
| theme(panel.grid.minor = element_line(color = "gray", | |
| size = 0.25, | |
| linetype = 1))+ | |
| guides(color = guide_legend(title = "Pitch Type")) | |
| } | |
| pitch_plot <- function(game){ | |
| ggplot()+ | |
| geom_point(game,mapping = | |
| aes(x=px, y = pz,color = pitch_name),size = 3.5) + | |
| geom_segment(aes(x=-0.71,xend = 0.71, y = 1.5,yend = 1.5))+ | |
| geom_segment(aes(x=-0.71,xend = 0.71, y = 3.6,yend = 3.6))+ | |
| geom_segment(aes(x= 0.71,xend = 0.71, y = 1.5,yend = 3.6))+ | |
| geom_segment(aes(x=-0.71,xend = -0.71, y = 1.5,yend =3.6))+ | |
| xlab(" ")+ | |
| ylab(" ") + | |
| xlim(-3,3)+ | |
| ylim(0.2,4)+ | |
| coord_fixed(ratio = 1) + | |
| ggthemes::theme_few()+ | |
| guides(color = guide_legend(title = "Pitch Type"))+ | |
| theme(axis.text.x=element_blank(), | |
| axis.ticks.x=element_blank(), | |
| axis.text.y=element_blank(), | |
| axis.ticks.y=element_blank()) | |
| } | |
| # Assume FB.model, Off.model, and Break.model are already loaded in the environment | |
| # Function to calculate VAA (Vertical Approach Angle) | |
| calculate_VAA <- function(vz0, ay, az, vy0, y0) { | |
| -atan((vz0+(az*(-sqrt((vy0*vy0)-(2*ay*(y0-(17/12))))-vy0)/ | |
| ay))/(-sqrt((vy0*vy0)-(2*ay*(y0-(17/12))))))*(180/pi) | |
| } | |
| # Function to calculate EAA (Effective Approach Angle) | |
| calculate_EAA <- function(extension) { | |
| extension / 6.3 | |
| } | |
| # Function to calculate SADiff (Spin Axis Differential) | |
| calculate_SADiff <- function(pfxX, pfxZ, spinDirection) { | |
| # Calculate initial inSA | |
| inSA <- atan2(pfxZ, pfxX) * 180/pi + 90 | |
| # Adjust inSA if it's negative | |
| inSA <- ifelse(inSA < 0, inSA + 360, inSA) | |
| # Calculate SADiff | |
| SADiff <- spinDirection - inSA | |
| # Adjust SADiff to be within -180 to 180 range | |
| SADiff <- ifelse(SADiff > 180, SADiff - 360, SADiff) | |
| SADiff <- ifelse(SADiff < -180, SADiff + 360, SADiff) | |
| return(SADiff) | |
| } | |
| # Function to scale TimStuff | |
| scale_TimStuff <- function(raw_score, model_mean, model_sd) { | |
| scaled_score <- (raw_score - model_mean) / model_sd | |
| result <- 50 - (scaled_score * 10) | |
| # Add logging | |
| # cat("Raw score:", raw_score, "\n") | |
| # cat("Model mean:", model_mean, "\n") | |
| # cat("Model SD:", model_sd, "\n") | |
| # cat("Scaled score:", scaled_score, "\n") | |
| # cat("Final result:", result, "\n") | |
| # Ensure the result is within a reasonable range | |
| # result <- max(min(result, 100), 0) | |
| return(result) | |
| } | |
| FB <- xgb.load('FB.model') | |
| Off <- xgb.load('Off.model') | |
| Break <- xgb.load('Break.model') | |
| # Modify the summary_table function | |
| summary_table <- function(game) { | |
| rows <- nrow(game) | |
| sumtable <- game |> | |
| mutate( | |
| VAA = calculate_VAA(vz0, ay, vy0, y0), | |
| EAA = calculate_EAA(extension), | |
| SADiff = calculate_SADiff(pfxX, pfxZ,spinDirection) | |
| ) |> | |
| mutate(team_fielding_id = ifelse(description == "Called Strike" | | |
| description == "Swinging Strike" | | |
| description == "Swinging Strike (Blocked)", 1, 0)) |> | |
| mutate(swing = ifelse(description == "Foul" | | |
| description == "Foul Pitchout" | | |
| description == "In play, no out" | | |
| description == "In play, out(s)" | | |
| description == "In play, run(s)" | | |
| description == "Swinging Strike" | | |
| description == "swinging Strike (Blocked)" | | |
| description == "Foul Tip", 1, 0)) |> | |
| mutate(is_strike_swinging = ifelse(is_strike_swinging == TRUE, 1, 0)) |> | |
| mutate(Pitch = pitch_name) |> | |
| rowwise() |> | |
| mutate(TimStuff = if (phand == 'L') { | |
| case_when( | |
| Pitch %in% c("Four-Seam Fastball", "Sinker", "Cutter", "Fastball") ~ | |
| ifelse(any(is.na(c(start_speed, IVB, -HB, EAA, -x0, z0, spin_rate, SADiff))), | |
| NA_real_, | |
| scale_TimStuff(predict(FB, matrix(c(start_speed, IVB, -HB, EAA, -x0, z0, spin_rate, SADiff), nrow = 1, ncol = 8)), | |
| -0.0011801, 0.007989927)), | |
| Pitch %in% c("Changeup", "Splitter", "Screwball", "Forkball") ~ | |
| ifelse(any(is.na(c(start_speed, IVB, -HB, EAA, -x0, z0, spin_rate, SADiff))), | |
| NA_real_, | |
| scale_TimStuff(predict(Off, matrix(c(start_speed, IVB, -HB, EAA, -x0, z0, spin_rate, SADiff), nrow = 1, ncol = 8)), | |
| -0.002239657, 0.01043216)), | |
| Pitch %in% c("Slider", "Slurve", "Sweeper", "Curveball", "Knuckle Curve", "Slow Curve", "Knuckleball") ~ | |
| ifelse(any(is.na(c(start_speed, IVB, -HB, EAA, -x0, z0, spin_rate, SADiff))), | |
| NA_real_, | |
| scale_TimStuff(predict(Break, matrix(c(start_speed, IVB, -HB, EAA, -x0, z0, spin_rate, SADiff), nrow = 1, ncol = 8)), | |
| -0.004822031, 0.007912765)), | |
| TRUE ~ NA_real_ | |
| ) | |
| } else { | |
| case_when( | |
| Pitch %in% c("Four-Seam Fastball", "Sinker", "Cutter", "Fastball") ~ | |
| ifelse(any(is.na(c(start_speed, IVB, HB, EAA, x0, z0, spin_rate, SADiff))), | |
| NA_real_, | |
| scale_TimStuff(predict(FB, matrix(c(start_speed, IVB, HB, EAA, x0, z0, spin_rate, SADiff), nrow = 1, ncol = 8)), | |
| -0.0011801, 0.007989927)), | |
| Pitch %in% c("Changeup", "Splitter", "Screwball", "Forkball") ~ | |
| ifelse(any(is.na(c(start_speed, IVB, HB, EAA, x0, z0, spin_rate, SADiff))), | |
| NA_real_, | |
| scale_TimStuff(predict(Off, matrix(c(start_speed, IVB, HB, EAA, x0, z0, spin_rate, SADiff), nrow = 1, ncol = 8)), | |
| -0.002239657, 0.01043216)), | |
| Pitch %in% c("Slider", "Slurve", "Sweeper", "Curveball", "Knuckle Curve", "Slow Curve", "Knuckleball") ~ | |
| ifelse(any(is.na(c(start_speed, IVB, HB, EAA, x0, z0, spin_rate, SADiff))), | |
| NA_real_, | |
| scale_TimStuff(predict(Break, matrix(c(start_speed, IVB, HB, EAA, x0, z0, spin_rate, SADiff), nrow = 1, ncol = 8)), | |
| -0.004822031, 0.007912765)), | |
| TRUE ~ NA_real_ | |
| ) | |
| }) |> | |
| group_by(Pitch) |> | |
| summarize( | |
| Pitches = n(), | |
| 'Pitch%' = round(sum(Pitches)/sum(rows) * 100, digits = 1), | |
| 'Avg. Velo' = round(mean(start_speed, na.rm = TRUE), digits = 1), | |
| 'Spin Rate' = round(mean(spin_rate, na.rm = TRUE), digits = 0), | |
| 'Extension' = round(mean(extension, na.rm = TRUE), digits = 1), | |
| 'IVB' = round(mean(IVB, na.rm = TRUE), digits = 1), | |
| 'HB' = round(mean(HB, na.rm = TRUE), digits = 1), | |
| 'VAA' = round(mean(VAA, na.rm = TRUE), digits = 1), | |
| # 'EAA' = round(mean(EAA, na.rm = TRUE), digits = 2), | |
| # 'x0' = round(mean(x0, na.rm = TRUE), digits = 2), | |
| # 'z0' = round(mean(z0, na.rm = TRUE), digits = 2), | |
| # 'SADiff' = round(mean(SADiff, na.rm = TRUE), digits = 2), | |
| 'CSW%' = round(sum(team_fielding_id, na.rm = TRUE) / sum(!is.na(team_fielding_id)) * 100, digits = 1), | |
| 'Whiff%' = round(sum(is_strike_swinging, na.rm = TRUE) / sum(swing, na.rm = TRUE) * 100, digits = 1), | |
| 'TimStuff' = round(mean(TimStuff, na.rm = TRUE), digits = 0) | |
| ) |> | |
| arrange(-Pitches) | |
| return(sumtable) | |
| } | |
| # The rest of your code remains the same | |
| mlbid <- mlb_schedule(season = 2024, level_ids = "1") | |
| mlbteamH <- mlbid |> | |
| select(teams_home_team_name) | |
| mlbteamH <- distinct(mlbteamH) | |
| mlbteamA <- mlbid |> | |
| select(teams_away_team_name) | |
| mlbteamA <- distinct(mlbteamA) | |
| aaaid <- mlb_schedule(season = 2024, level_ids = "11") | |
| aaateamH <- aaaid |> | |
| select(teams_home_team_name) | |
| aaateamH <- distinct(aaateamH) | |
| aaateamA <- aaaid |> | |
| select(teams_away_team_name) | |
| aaateamA <- distinct(aaateamA) | |
| fslid <- mlb_schedule(season = 2024, level_ids = "14") | |
| fslid <- fslid |> | |
| filter(teams_home_team_name == "Daytona Tortugas" | | |
| teams_home_team_name == "Jupiter Hammerheads" | | |
| teams_home_team_name == "Palm Beach Cardinals" | | |
| teams_home_team_name == "St. Lucie Mets" | | |
| teams_home_team_name == "Bradenton Marauders" | | |
| teams_home_team_name == "Clearwater Threshers" | | |
| teams_home_team_name == "Dunedin Blue Jays" | | |
| teams_home_team_name == "Fort Myers Mighty Mussels" | | |
| teams_home_team_name == "Lakeland Flying Tigers" | | |
| teams_home_team_name == "Tampa Tarpons") | |
| fslteamH <- fslid |> | |
| select(teams_home_team_name) | |
| fslteamH <- distinct(fslteamH) | |
| fslteamA <- fslid |> | |
| select(teams_away_team_name) | |
| fslteamA <- distinct(fslteamA) | |
| sbid <- mlb_schedule(season = 2024, level_ids = "22") | |
| sbteamH <- sbid |> | |
| select(teams_home_team_name) | |
| sbteamH <- distinct(sbteamH) | |
| sbteamA <- sbid |> | |
| select(teams_away_team_name) | |
| sbteamA <- distinct(sbteamA) | |
| ui <- fluidPage( | |
| tags$head( | |
| tags$style(HTML(" | |
| @media (max-width: 768px) { | |
| .sidebar { width: 100%; float: none; } | |
| .main-content { margin-left: 0; } | |
| .selectize-input { font-size: 14px; } | |
| .form-group { margin-bottom: 10px; } | |
| .action-button { width: 100%; } | |
| } | |
| ")) | |
| ), | |
| titlePanel("2024 MLB/AAA/FSL Summary Cards"), | |
| sidebarLayout( | |
| sidebarPanel( | |
| width = 2, | |
| dateInput("date", "Date:"), | |
| selectizeInput("level", "Level:", c("MLB", "AAA", "FSL", "College (Statcast Parks Only)")), | |
| selectizeInput("homeT", "Home Team:", mlbteamH[,1]), | |
| selectizeInput("awayT", "Away Team:", mlbteamA[,1]), | |
| selectizeInput("gamenum", "Game Number (For Doubleheaders):", c("1", "2")), | |
| actionButton("update", "Find Pitcher", icon("magnifying-glass"), | |
| style = "color: #FFFFFF; background-color: #0077B6; width: 100%;"), | |
| selectizeInput("pitcher", "Pitcher Name:", c(" ")), | |
| # selectizeInput("league", "MLB or MiLB Photo", c("MLB", "MiLB")), | |
| textInput("title", "Card Title"), | |
| actionButton("update1", "Make Card", icon("plus"), | |
| style = "color: #FFFFFF; background-color: #0077B6; width: 100%;"), | |
| downloadButton("downloadPlot", "Download Card") | |
| ), | |
| mainPanel( | |
| plotOutput("combinedPlot", height = "900px",width = "1350px") | |
| ) | |
| ) | |
| ) | |
| server <- function(input, output, session) { | |
| observeEvent(input$level, { | |
| if(input$level == "AAA"){ | |
| updateSelectizeInput(session = getDefaultReactiveDomain(),"homeT","Home Team:",choices = aaateamH[,1]) | |
| updateSelectizeInput(session = getDefaultReactiveDomain(),"awayT","Away Team:",choices = aaateamA[,1]) | |
| } | |
| if(input$level == "FSL"){ | |
| updateSelectizeInput(session = getDefaultReactiveDomain(),"homeT","Home Team:",choices = fslteamH[,1]) | |
| updateSelectizeInput(session = getDefaultReactiveDomain(),"awayT","Away Team:",choices = fslteamA[,1]) | |
| } | |
| if(input$level == "MLB"){ | |
| updateSelectizeInput(session = getDefaultReactiveDomain(),"homeT","Home Team:",choices = mlbteamH[,1]) | |
| updateSelectizeInput(session = getDefaultReactiveDomain(),"awayT","Away Team:",choices = mlbteamA[,1]) | |
| } | |
| if(input$level == "College (Statcast Parks Only)"){ | |
| updateSelectizeInput(session = getDefaultReactiveDomain(),"homeT","Home Team:",choices = sbteamH[,1]) | |
| updateSelectizeInput(session = getDefaultReactiveDomain(),"awayT","Away Team:",choices = sbteamA[,1]) | |
| } | |
| }) | |
| observeEvent(input$update, { | |
| if(input$level == "AAA"){ | |
| pname <- aaaid |> | |
| filter(date == input$date) |> | |
| filter(teams_home_team_name == input$homeT) |> | |
| filter(teams_away_team_name == input$awayT) |> | |
| filter(game_number == input$gamenum) | |
| pname <- tryCatch({pitcher_summary(pname[,6],input$date)},error=function(e){cat("ERROR :",conditionMessage(e), "\n")}) | |
| updateSelectizeInput(session = getDefaultReactiveDomain(),"pitcher","Pitcher:",choices = pname[,3]) | |
| } | |
| if(input$level == "FSL"){ | |
| pname <- fslid |> | |
| filter(date == input$date) |> | |
| filter(teams_home_team_name == input$homeT) |> | |
| filter(teams_away_team_name == input$awayT) |> | |
| filter(game_number == input$gamenum) | |
| pname <- tryCatch({pitcher_summary(pname[,6],input$date)},error=function(e){cat("ERROR :",conditionMessage(e), "\n")}) | |
| updateSelectizeInput(session = getDefaultReactiveDomain(),"pitcher","Pitcher:",choices = pname[,3]) | |
| } | |
| if(input$level == "MLB"){ | |
| pname <- mlbid |> | |
| filter(date == as.character.Date(input$date)) |> | |
| filter(teams_home_team_name == input$homeT) |> | |
| filter(teams_away_team_name == input$awayT) |> | |
| filter(game_number == input$gamenum) | |
| pname <- tryCatch({pitcher_summary(pname[,6],input$date)},error=function(e){cat("ERROR :",conditionMessage(e), "\n")}) | |
| updateSelectizeInput(session = getDefaultReactiveDomain(),"pitcher","Pitcher:",choices = pname[,3]) | |
| } | |
| if(input$level == "College (Statcast Parks Only)"){ | |
| pname <- sbid |> | |
| filter(date == input$date) |> | |
| filter(teams_home_team_name == input$homeT) |> | |
| filter(teams_away_team_name == input$awayT) |> | |
| filter(game_number == input$gamenum) | |
| pname <- tryCatch({pitcher_summary(pname[,6],input$date)},error=function(e){cat("ERROR :",conditionMessage(e), "\n")}) | |
| updateSelectizeInput(session = getDefaultReactiveDomain(),"pitcher","Pitcher:",choices = pname[,3]) | |
| } | |
| }) | |
| combinedPlot <- reactiveVal() | |
| observeEvent(input$update1, { | |
| if(input$level == "MLB"){ | |
| id <- mlbid |> | |
| filter(date == as.character.Date(input$date)) |> | |
| filter(teams_home_team_name == input$homeT) |> | |
| filter(teams_away_team_name == input$awayT) |> | |
| filter(game_number == input$gamenum) | |
| game <- tryCatch({pitcher_summary(id[,6],input$date)},error=function(e){cat("ERROR :",conditionMessage(e), "\n")}) | |
| game <- game |> | |
| filter(`Pitcher Name` == input$pitcher) | |
| id <- as.character(game[1,4]) | |
| } | |
| if(input$level == "FSL"){ | |
| id <- fslid |> | |
| filter(date == as.character.Date(input$date)) |> | |
| filter(teams_home_team_name == input$homeT) |> | |
| filter(teams_away_team_name == input$awayT) |> | |
| filter(game_number == input$gamenum) | |
| game <- tryCatch({pitcher_summary(id[,6],input$date)},error=function(e){cat("ERROR :",conditionMessage(e), "\n")}) | |
| game <- game |> | |
| filter(`Pitcher Name` == input$pitcher) | |
| id <- as.character(game[1,4]) | |
| } | |
| if(input$level == "AAA"){ | |
| id <- aaaid |> | |
| filter(date == as.character.Date(input$date)) |> | |
| filter(teams_home_team_name == input$homeT) |> | |
| filter(teams_away_team_name == input$awayT) |> | |
| filter(game_number == input$gamenum) | |
| game <- tryCatch({pitcher_summary(id[,6],input$date)},error=function(e){cat("ERROR :",conditionMessage(e), "\n")}) | |
| game <- game |> | |
| filter(`Pitcher Name` == input$pitcher) | |
| id <- as.character(game[1,4]) | |
| } | |
| if(input$level == "College (Statcast Parks Only)"){ | |
| id <- sbid |> | |
| filter(date == as.character.Date(input$date)) |> | |
| filter(teams_home_team_name == input$homeT) |> | |
| filter(teams_away_team_name == input$awayT) |> | |
| filter(game_number == input$gamenum) | |
| game <- tryCatch({pitcher_summary(id[,6],input$date)},error=function(e){cat("ERROR :",conditionMessage(e), "\n")}) | |
| game <- game |> | |
| filter(`Pitcher Name` == input$pitcher) | |
| id <- as.character(game[1,4]) | |
| } | |
| break_plot <- break_plot(game) | |
| pitch_plot <- pitch_plot(game) | |
| # Create table plot | |
| # Update the tableGrob in the observeEvent(input$update1, {...}) block | |
| table_plot <- tableGrob(summary_table(game), theme = ttheme_default( | |
| core = list(fg_params = list(cex = 1.7)), | |
| colhead = list(fg_params = list(cex = 1.2)), | |
| rowhead = list(fg_params = list(cex = 2.5)))) | |
| table_plot$widths[[1]] <- unit(0, "cm") | |
| # Find the text grobs in the first column | |
| text_grobs <- which(sapply(table_plot$grobs, function(g) { | |
| g$name == "core-fg-1" && inherits(g$children[[1]], "text") | |
| })) | |
| # Remove the numbers from these text grobs | |
| for (i in text_grobs) { | |
| text <- table_plot$grobs[[i]]$children[[1]]$label | |
| table_plot$grobs[[i]]$children[[1]]$label <- sub("^\\d+\\s*", "", text) | |
| } | |
| # Draw the modified table | |
| grid.newpage() | |
| grid.draw(table_plot) | |
| # Download and process image | |
| # if(input$league == "MLB"){ | |
| # y <- paste("https://midfield.mlbstatic.com/v1/people/","/mlb/300?circle=false",sep = id) | |
| # } else { | |
| # y <- paste("https://midfield.mlbstatic.com/v1/people/","/milb/300?circle=false",sep = id) | |
| # } | |
| #if (input$league == "MLB") { | |
| y <- paste0("https://midfield.mlbstatic.com/v1/people/", id, "/mlb/300?circle=false") | |
| # } else { | |
| # y <- paste0("https://midfield.mlbstatic.com/v1/people/", id, "/milb/300?circle=false") | |
| # } | |
| # Initialize the URL to NULL | |
| y <- NULL | |
| # Try the MLB URL first | |
| mlb_url <- paste0("https://midfield.mlbstatic.com/v1/people/", id, "/mlb/300?circle=false") | |
| response <- httr::GET(mlb_url) | |
| if (httr::status_code(response) == 200) { | |
| y <- mlb_url # Use MLB URL if it returns a 200 status code | |
| } else if (httr::status_code(response) == 404) { | |
| # If MLB URL fails with a 404, try the MiLB URL | |
| milb_url <- paste0("https://midfield.mlbstatic.com/v1/people/", id, "/milb/300?circle=false") | |
| response <- httr::GET(milb_url) | |
| if (httr::status_code(response) == 200) { | |
| y <- milb_url # Use MiLB URL if it returns a 200 status code | |
| } else { | |
| stop("Both MLB and MiLB URLs failed with 404 error") | |
| } | |
| } else { | |
| stop("MLB URL failed with an unexpected error") | |
| } | |
| photo <- tempfile() | |
| download.file(y, photo, mode = 'wb') | |
| img <- readPNG(photo) | |
| img_grob <- rasterGrob(img, interpolate = TRUE) | |
| # Combine all elements into one plot | |
| combined <- grid.arrange( | |
| arrangeGrob(table_plot, img_grob, ncol = 2, widths = c(2/3, 1/3)), | |
| arrangeGrob(break_plot, pitch_plot, ncol = 2), | |
| nrow = 2, | |
| top = textGrob(paste(input$title, "Made by @TimStats", sep = " "), gp = gpar(fontsize = 20, font = 2)) | |
| ) | |
| combinedPlot(combined) | |
| output$combinedPlot <- renderPlot({ | |
| grid.draw(combinedPlot()) | |
| }) | |
| }) | |
| output$downloadPlot <- downloadHandler( | |
| filename = function() { | |
| paste("baseball_card_", Sys.Date(), ".png", sep = "") | |
| }, | |
| content = function(file) { | |
| ggsave(file, plot = combinedPlot(), width = 18, height = 12, dpi = 300) | |
| } | |
| ) | |
| } | |
| shinyApp(ui, server) |