Spaces:
Running
Running
Update app.R
Browse files
app.R
CHANGED
|
@@ -173,7 +173,7 @@ spring26_ncaa <- download_master_dataset("CoastalBaseball/2026MasterDataset", "n
|
|
| 173 |
college_join <- download_private_csv("CoastalBaseball/DefenseAppDataset", "college_join.csv")
|
| 174 |
|
| 175 |
# Load Catcher 2026 data
|
| 176 |
-
Catcher2026 <-
|
| 177 |
Catcher2026 <- Catcher2026 %>%
|
| 178 |
mutate(
|
| 179 |
Date = as.Date(Date),
|
|
@@ -1044,11 +1044,14 @@ app_ui <- fluidPage(
|
|
| 1044 |
uiOutput("throw_header_stats"),
|
| 1045 |
hr(),
|
| 1046 |
fluidRow(
|
| 1047 |
-
column(
|
| 1048 |
-
selectInput("throw_view_mode", "
|
| 1049 |
-
choices = c("Points (by Result)","Heatmap","Color by Throw Speed",
|
| 1050 |
-
|
| 1051 |
-
|
|
|
|
|
|
|
|
|
|
| 1052 |
),
|
| 1053 |
fluidRow(
|
| 1054 |
column(6,
|
|
@@ -1059,14 +1062,8 @@ app_ui <- fluidPage(
|
|
| 1059 |
plotlyOutput("throw_safe_plot", height = "520px"))
|
| 1060 |
),
|
| 1061 |
hr(),
|
| 1062 |
-
|
| 1063 |
-
|
| 1064 |
-
h4("Release Point (Side View)", class = "section-header"),
|
| 1065 |
-
plotlyOutput("throw_release_side", height = "420px")),
|
| 1066 |
-
column(6,
|
| 1067 |
-
h4("Release Point (Overhead)", class = "section-header"),
|
| 1068 |
-
plotlyOutput("throw_release_overhead", height = "420px"))
|
| 1069 |
-
),
|
| 1070 |
hr(),
|
| 1071 |
h4("Throwing Log", class = "section-header"),
|
| 1072 |
DTOutput("throw_log_table")
|
|
@@ -1711,65 +1708,87 @@ server <- function(input, output, session) {
|
|
| 1711 |
})
|
| 1712 |
|
| 1713 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1714 |
make_recv_plot <- function(data, title_text, view_mode) {
|
| 1715 |
-
if (nrow(data) == 0)
|
| 1716 |
-
|
| 1717 |
-
|
|
|
|
|
|
|
|
|
|
| 1718 |
if (view_mode == "Catch Position (Overhead)") {
|
| 1719 |
data <- data %>% filter(!is.na(CatchPositionX) & !is.na(CatchPositionZ))
|
| 1720 |
-
if (nrow(data) == 0) return(
|
| 1721 |
-
data <- data %>% mutate(row_num = row_number())
|
| 1722 |
-
|
| 1723 |
-
|
| 1724 |
-
|
| 1725 |
-
|
| 1726 |
-
|
| 1727 |
-
|
| 1728 |
-
|
| 1729 |
-
|
| 1730 |
-
|
| 1731 |
-
|
| 1732 |
-
|
| 1733 |
-
|
| 1734 |
-
|
| 1735 |
-
|
| 1736 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1737 |
}
|
| 1738 |
-
|
| 1739 |
if (view_mode == "Heatmap") {
|
| 1740 |
data <- data %>% filter(!is.na(PlateLocSide) & !is.na(PlateLocHeight))
|
| 1741 |
-
if (nrow(data) < 3) return(
|
| 1742 |
-
p <-
|
| 1743 |
-
|
| 1744 |
-
|
| 1745 |
-
|
| 1746 |
-
|
| 1747 |
-
|
| 1748 |
-
|
| 1749 |
-
|
| 1750 |
-
return(ggplotly(p))
|
| 1751 |
}
|
| 1752 |
-
|
| 1753 |
-
# Default: Points
|
| 1754 |
data <- data %>% mutate(row_num = row_number())
|
| 1755 |
-
|
| 1756 |
-
|
| 1757 |
-
|
| 1758 |
-
|
| 1759 |
-
|
| 1760 |
-
|
| 1761 |
-
|
| 1762 |
-
|
| 1763 |
-
|
| 1764 |
-
|
| 1765 |
-
|
| 1766 |
-
|
| 1767 |
-
|
| 1768 |
-
|
| 1769 |
-
|
| 1770 |
-
|
| 1771 |
-
|
| 1772 |
-
|
|
|
|
| 1773 |
}
|
| 1774 |
|
| 1775 |
output$recv_strikes_added <- renderPlotly({
|
|
@@ -1867,23 +1886,19 @@ server <- function(input, output, session) {
|
|
| 1867 |
|
| 1868 |
if (view_mode == "Heatmap") {
|
| 1869 |
data <- data %>% filter(!is.na(BasePositionZ) & !is.na(BasePositionY))
|
| 1870 |
-
if (nrow(data)
|
| 1871 |
-
p <-
|
| 1872 |
-
|
| 1873 |
-
|
| 1874 |
-
|
| 1875 |
-
|
| 1876 |
-
|
| 1877 |
-
|
| 1878 |
-
|
| 1879 |
-
|
| 1880 |
-
|
| 1881 |
-
|
| 1882 |
-
|
| 1883 |
-
axis.ticks=element_blank(), panel.grid=element_blank(),
|
| 1884 |
-
plot.title=element_text(size=11,face='bold',hjust=.5)) +
|
| 1885 |
-
ggtitle(title_text)
|
| 1886 |
-
return(ggplotly(p))
|
| 1887 |
}
|
| 1888 |
|
| 1889 |
if (view_mode == "Color by Throw Speed") {
|
|
@@ -1977,38 +1992,45 @@ server <- function(input, output, session) {
|
|
| 1977 |
make_throw_base_plot(td, paste0(input$ct_catcher, " - Safe"), input$throw_view_mode)
|
| 1978 |
})
|
| 1979 |
|
| 1980 |
-
output$
|
| 1981 |
td <- throw_data() %>%
|
| 1982 |
filter(!is.na(ThrowPositionX) & !is.na(ThrowPositionY))
|
| 1983 |
-
if (nrow(td) == 0)
|
| 1984 |
-
|
| 1985 |
-
|
| 1986 |
-
|
| 1987 |
-
|
| 1988 |
-
|
| 1989 |
-
|
| 1990 |
-
|
| 1991 |
-
|
| 1992 |
-
|
| 1993 |
-
|
| 1994 |
-
|
| 1995 |
-
|
| 1996 |
-
|
| 1997 |
-
|
| 1998 |
-
|
| 1999 |
-
|
| 2000 |
-
|
| 2001 |
-
|
| 2002 |
-
|
| 2003 |
-
|
| 2004 |
-
|
| 2005 |
-
|
| 2006 |
-
|
| 2007 |
-
|
| 2008 |
-
|
| 2009 |
-
|
| 2010 |
-
|
| 2011 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2012 |
})
|
| 2013 |
|
| 2014 |
output$throw_log_table <- renderDT({
|
|
@@ -2081,22 +2103,18 @@ server <- function(input, output, session) {
|
|
| 2081 |
bi <- 1; bo <- 4; bymin <- -2.5; bymax <- 3.7
|
| 2082 |
|
| 2083 |
if (view_mode == "Heatmap" && nrow(bd) >= 3) {
|
| 2084 |
-
p <-
|
| 2085 |
-
|
| 2086 |
-
|
| 2087 |
-
|
| 2088 |
-
|
| 2089 |
-
|
| 2090 |
-
|
| 2091 |
-
|
| 2092 |
-
|
| 2093 |
-
|
| 2094 |
-
|
| 2095 |
-
|
| 2096 |
-
coord_fixed() + labs(title="Blocking (Overhead) - Heatmap", x=NULL, y=NULL) +
|
| 2097 |
-
theme_void(base_size=9) +
|
| 2098 |
-
theme(plot.title=element_text(size=11,face="bold",hjust=.5), legend.position="bottom")
|
| 2099 |
-
return(ggplotly(p))
|
| 2100 |
}
|
| 2101 |
|
| 2102 |
# Points mode
|
|
@@ -2134,48 +2152,44 @@ server <- function(input, output, session) {
|
|
| 2134 |
bd <- block_data() %>%
|
| 2135 |
filter(!is.na(PlateLocSide) & !is.na(PlateLocHeight)) %>%
|
| 2136 |
mutate(row_num = row_number())
|
| 2137 |
-
|
| 2138 |
view_mode <- input$block_view_mode
|
| 2139 |
-
|
| 2140 |
if (nrow(bd) == 0) {
|
| 2141 |
-
return(
|
| 2142 |
-
theme(plot.title=element_text(hjust=.5,size=11,face="bold"))))
|
| 2143 |
}
|
| 2144 |
-
|
| 2145 |
if (view_mode == "Heatmap" && nrow(bd) >= 3) {
|
| 2146 |
-
p <-
|
| 2147 |
-
|
| 2148 |
-
|
| 2149 |
-
|
| 2150 |
-
|
| 2151 |
-
|
| 2152 |
-
|
| 2153 |
-
|
| 2154 |
-
plot.title=element_text(hjust=0.5, size=11, face="bold"))
|
| 2155 |
-
return(ggplotly(p))
|
| 2156 |
}
|
| 2157 |
-
|
| 2158 |
-
|
| 2159 |
-
|
| 2160 |
-
|
| 2161 |
-
|
| 2162 |
-
|
| 2163 |
-
|
| 2164 |
-
|
| 2165 |
-
|
| 2166 |
-
|
| 2167 |
-
|
| 2168 |
-
|
| 2169 |
-
|
| 2170 |
-
|
| 2171 |
-
|
| 2172 |
-
|
| 2173 |
-
|
| 2174 |
-
|
| 2175 |
-
|
| 2176 |
-
|
| 2177 |
-
|
| 2178 |
-
ggplotly(p, tooltip="text")
|
| 2179 |
})
|
| 2180 |
|
| 2181 |
output$block_log_table <- renderDT({
|
|
|
|
| 173 |
college_join <- download_private_csv("CoastalBaseball/DefenseAppDataset", "college_join.csv")
|
| 174 |
|
| 175 |
# Load Catcher 2026 data
|
| 176 |
+
Catcher2026 <- download_private_parquet("CoastalBaseball/DefenseAppDataset", "Catcher2026.parquet")
|
| 177 |
Catcher2026 <- Catcher2026 %>%
|
| 178 |
mutate(
|
| 179 |
Date = as.Date(Date),
|
|
|
|
| 1044 |
uiOutput("throw_header_stats"),
|
| 1045 |
hr(),
|
| 1046 |
fluidRow(
|
| 1047 |
+
column(4,
|
| 1048 |
+
selectInput("throw_view_mode", "Base Arrival View:",
|
| 1049 |
+
choices = c("Points (by Result)","Heatmap","Color by Throw Speed"),
|
| 1050 |
+
selected = "Points (by Result)", width = "100%")),
|
| 1051 |
+
column(4,
|
| 1052 |
+
selectInput("throw_release_color", "Release Point Color By:",
|
| 1053 |
+
choices = c("Result","Throw Speed"),
|
| 1054 |
+
selected = "Result", width = "100%"))
|
| 1055 |
),
|
| 1056 |
fluidRow(
|
| 1057 |
column(6,
|
|
|
|
| 1062 |
plotlyOutput("throw_safe_plot", height = "520px"))
|
| 1063 |
),
|
| 1064 |
hr(),
|
| 1065 |
+
h4("Catcher Release Point", class = "section-header"),
|
| 1066 |
+
plotlyOutput("throw_release_plot", height = "480px"),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1067 |
hr(),
|
| 1068 |
h4("Throwing Log", class = "section-header"),
|
| 1069 |
DTOutput("throw_log_table")
|
|
|
|
| 1708 |
})
|
| 1709 |
|
| 1710 |
|
| 1711 |
+
# Pure plotly zone plot helper — no ggplotly conversion issues
|
| 1712 |
+
plotly_zone_shapes <- function() {
|
| 1713 |
+
list(
|
| 1714 |
+
list(type="rect", x0=-.83083, x1=.83083, y0=1.5, y1=3.3775,
|
| 1715 |
+
line=list(color="black", width=2), fillcolor="rgba(0,0,0,0)", layer="above"),
|
| 1716 |
+
list(type="rect", x0=-.9975, x1=.9975, y0=1.3775, y1=3.5,
|
| 1717 |
+
line=list(color="gray", width=1, dash="dot"), fillcolor="rgba(0,0,0,0)", layer="above"),
|
| 1718 |
+
list(type="path",
|
| 1719 |
+
path="M -0.60 0.15 L 0.60 0.15 L 0.60 0.27 L 0 0.42 L -0.60 0.27 Z",
|
| 1720 |
+
line=list(color="gray40", width=1.5), fillcolor="rgba(0,0,0,0)", layer="above")
|
| 1721 |
+
)
|
| 1722 |
+
}
|
| 1723 |
+
|
| 1724 |
make_recv_plot <- function(data, title_text, view_mode) {
|
| 1725 |
+
if (nrow(data) == 0) {
|
| 1726 |
+
return(plot_ly() %>% layout(title=list(text=title_text, font=list(size=14)),
|
| 1727 |
+
xaxis=list(visible=FALSE), yaxis=list(visible=FALSE),
|
| 1728 |
+
annotations=list(list(text="No data", showarrow=FALSE, font=list(size=16)))))
|
| 1729 |
+
}
|
| 1730 |
+
|
| 1731 |
if (view_mode == "Catch Position (Overhead)") {
|
| 1732 |
data <- data %>% filter(!is.na(CatchPositionX) & !is.na(CatchPositionZ))
|
| 1733 |
+
if (nrow(data) == 0) return(plot_ly() %>% layout(title="No catch position data"))
|
| 1734 |
+
data <- data %>% mutate(row_num = row_number(), cpx = as.numeric(CatchPositionX), cpz = as.numeric(CatchPositionZ))
|
| 1735 |
+
pt_colors <- sapply(data$TaggedPitchType, function(pt) {
|
| 1736 |
+
if (!is.na(pt) && pt %in% names(pitch_colors)) pitch_colors[pt] else "grey60"
|
| 1737 |
+
})
|
| 1738 |
+
p <- plot_ly(data, x=~cpx, y=~cpz, type="scatter", mode="markers",
|
| 1739 |
+
marker=list(size=10, color=pt_colors, line=list(color="black", width=1)),
|
| 1740 |
+
text=~paste0("#",row_num,"<br>Pitch: ",TaggedPitchType,
|
| 1741 |
+
"<br>Pitcher: ",Pitcher,"<br>Batter: ",Batter,"<br>Date: ",Date),
|
| 1742 |
+
hoverinfo="text") %>%
|
| 1743 |
+
layout(title=list(text=paste(title_text,"- Catch Position"), font=list(size=14)),
|
| 1744 |
+
xaxis=list(title="X (ft)", range=c(-4,4), scaleanchor="y"),
|
| 1745 |
+
yaxis=list(title="Z (ft)", range=c(-5,3)),
|
| 1746 |
+
shapes=list(
|
| 1747 |
+
list(type="rect", x0=-3.5, x1=-0.708, y0=-4.5, y1=0.15,
|
| 1748 |
+
line=list(color="black",width=1), fillcolor="rgba(200,200,200,0.3)"),
|
| 1749 |
+
list(type="rect", x0=0.708, x1=3.5, y0=-4.5, y1=0.15,
|
| 1750 |
+
line=list(color="black",width=1), fillcolor="rgba(200,200,200,0.3)"),
|
| 1751 |
+
list(type="path",
|
| 1752 |
+
path="M -0.708 0.15 L 0.708 0.15 L 0.708 0.3 L 0 0.5 L -0.708 0.3 Z",
|
| 1753 |
+
line=list(color="black",width=1.5), fillcolor="rgba(240,240,240,0.5)"))
|
| 1754 |
+
)
|
| 1755 |
+
return(p)
|
| 1756 |
}
|
| 1757 |
+
|
| 1758 |
if (view_mode == "Heatmap") {
|
| 1759 |
data <- data %>% filter(!is.na(PlateLocSide) & !is.na(PlateLocHeight))
|
| 1760 |
+
if (nrow(data) < 3) return(plot_ly() %>% layout(title=paste(title_text,"- Not enough data")))
|
| 1761 |
+
p <- plot_ly(data, x=~PlateLocSide, y=~PlateLocHeight, type="histogram2dcontour",
|
| 1762 |
+
colorscale=list(c(0,"white"),c(0.25,"#0551bc"),c(0.5,"#03ff00"),c(0.75,"#fbff00"),c(1,"#dc1100")),
|
| 1763 |
+
contours=list(showlabels=FALSE), showscale=FALSE) %>%
|
| 1764 |
+
layout(title=list(text=title_text, font=list(size=14)),
|
| 1765 |
+
xaxis=list(title="", range=c(-2,2), scaleanchor="y", showticklabels=FALSE),
|
| 1766 |
+
yaxis=list(title="", range=c(0,4.5), showticklabels=FALSE),
|
| 1767 |
+
shapes=plotly_zone_shapes())
|
| 1768 |
+
return(p)
|
|
|
|
| 1769 |
}
|
| 1770 |
+
|
| 1771 |
+
# Default: Points mode — pure plotly
|
| 1772 |
data <- data %>% mutate(row_num = row_number())
|
| 1773 |
+
pt_colors <- sapply(data$TaggedPitchType, function(pt) {
|
| 1774 |
+
if (!is.na(pt) && pt %in% names(pitch_colors)) pitch_colors[pt] else "grey60"
|
| 1775 |
+
})
|
| 1776 |
+
p <- plot_ly(data, x=~PlateLocSide, y=~PlateLocHeight, type="scatter", mode="markers+text",
|
| 1777 |
+
marker=list(size=14, color=pt_colors, line=list(color="black", width=1.2)),
|
| 1778 |
+
text=~as.character(row_num), textfont=list(size=8, color="white"),
|
| 1779 |
+
textposition="middle center",
|
| 1780 |
+
hovertext=~paste0("#",row_num,"<br>Pitch: ",TaggedPitchType,
|
| 1781 |
+
"<br>Pitcher: ",Pitcher,"<br>Batter: ",Batter,
|
| 1782 |
+
"<br>Velo: ",round(RelSpeed,1)," mph",
|
| 1783 |
+
"<br>Count: ",Balls,"-",Strikes,
|
| 1784 |
+
"<br>RV: ",round(mean_DRE,3),"<br>Date: ",Date),
|
| 1785 |
+
hoverinfo="text") %>%
|
| 1786 |
+
layout(title=list(text=title_text, font=list(size=14)),
|
| 1787 |
+
xaxis=list(title="", range=c(-1.8,1.8), zeroline=FALSE, showticklabels=FALSE, scaleanchor="y"),
|
| 1788 |
+
yaxis=list(title="", range=c(0,4.5), zeroline=FALSE, showticklabels=FALSE),
|
| 1789 |
+
shapes=plotly_zone_shapes(),
|
| 1790 |
+
showlegend=FALSE)
|
| 1791 |
+
p
|
| 1792 |
}
|
| 1793 |
|
| 1794 |
output$recv_strikes_added <- renderPlotly({
|
|
|
|
| 1886 |
|
| 1887 |
if (view_mode == "Heatmap") {
|
| 1888 |
data <- data %>% filter(!is.na(BasePositionZ) & !is.na(BasePositionY))
|
| 1889 |
+
if (nrow(data) < 3) return(plot_ly() %>% layout(title="Not enough data for heatmap"))
|
| 1890 |
+
p <- plot_ly(data, x=~BasePositionZ, y=~BasePositionY, type="histogram2dcontour",
|
| 1891 |
+
colorscale=list(c(0,"rgba(0,0,0,0)"),c(0.25,"#02fbff"),c(0.5,"#03ff00"),c(0.75,"#fbff00"),c(1,"#dc1100")),
|
| 1892 |
+
showscale=FALSE) %>%
|
| 1893 |
+
layout(title=list(text=title_text, font=list(size=14)),
|
| 1894 |
+
xaxis=list(title="", range=c(-10,10)),
|
| 1895 |
+
yaxis=list(title="", range=c(-5,9), scaleanchor="x"),
|
| 1896 |
+
shapes=list(
|
| 1897 |
+
list(type="rect", x0=-10,x1=10,y0=0.25,y1=8, fillcolor="rgba(0,139,139,0.15)", line=list(width=0), layer="below"),
|
| 1898 |
+
list(type="rect", x0=-10,x1=10,y0=8,y1=9, fillcolor="rgba(255,255,0,0.2)", line=list(width=0), layer="below"),
|
| 1899 |
+
list(type="rect", x0=-10,x1=10,y0=-2,y1=0.25, fillcolor="rgba(139,69,19,0.2)", line=list(width=0), layer="below"),
|
| 1900 |
+
list(type="rect", x0=-1,x1=1,y0=0,y1=0.45, fillcolor="white", line=list(color="black",width=1), layer="above")))
|
| 1901 |
+
return(p)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1902 |
}
|
| 1903 |
|
| 1904 |
if (view_mode == "Color by Throw Speed") {
|
|
|
|
| 1992 |
make_throw_base_plot(td, paste0(input$ct_catcher, " - Safe"), input$throw_view_mode)
|
| 1993 |
})
|
| 1994 |
|
| 1995 |
+
output$throw_release_plot <- renderPlotly({
|
| 1996 |
td <- throw_data() %>%
|
| 1997 |
filter(!is.na(ThrowPositionX) & !is.na(ThrowPositionY))
|
| 1998 |
+
if (nrow(td) == 0) {
|
| 1999 |
+
return(plot_ly() %>% layout(title="No release point data",
|
| 2000 |
+
xaxis=list(visible=FALSE), yaxis=list(visible=FALSE)))
|
| 2001 |
+
}
|
| 2002 |
+
td <- td %>% mutate(tpx = as.numeric(ThrowPositionX), tpy = as.numeric(ThrowPositionY))
|
| 2003 |
+
color_by <- input$throw_release_color
|
| 2004 |
+
|
| 2005 |
+
if (color_by == "Throw Speed") {
|
| 2006 |
+
p <- plot_ly(td, x=~tpx, y=~tpy, type="scatter", mode="markers",
|
| 2007 |
+
marker=list(size=12, color=~ThrowSpeed,
|
| 2008 |
+
colorscale=list(c(0,"#0551bc"),c(0.25,"#02fbff"),c(0.5,"#03ff00"),c(0.75,"#fbff00"),c(1,"#ff1f02")),
|
| 2009 |
+
colorbar=list(title="Velo (mph)"),
|
| 2010 |
+
line=list(color="black", width=1)),
|
| 2011 |
+
text=~paste0("Result: ",throw_label,"<br>Speed: ",round(ThrowSpeed,1)," mph",
|
| 2012 |
+
"<br>Pop: ",round(PopTime,3),"s","<br>Exchange: ",round(ExchangeTime,3),"s",
|
| 2013 |
+
"<br>Date: ",Date),
|
| 2014 |
+
hoverinfo="text")
|
| 2015 |
+
} else {
|
| 2016 |
+
throw_color_map <- c('2B Out'='#339a1d','2B Safe'='red','3B Out'='#1a5d1a','3B Safe'='#ff6b6b')
|
| 2017 |
+
td$pt_color <- sapply(td$throw_label, function(tl) {
|
| 2018 |
+
if (!is.na(tl) && tl %in% names(throw_color_map)) throw_color_map[tl] else "gray"
|
| 2019 |
+
})
|
| 2020 |
+
p <- plot_ly(td, x=~tpx, y=~tpy, type="scatter", mode="markers",
|
| 2021 |
+
marker=list(size=12, color=~pt_color, line=list(color="black", width=1)),
|
| 2022 |
+
text=~paste0("Result: ",throw_label,"<br>Speed: ",round(ThrowSpeed,1)," mph",
|
| 2023 |
+
"<br>Pop: ",round(PopTime,3),"s","<br>Exchange: ",round(ExchangeTime,3),"s",
|
| 2024 |
+
"<br>Date: ",Date),
|
| 2025 |
+
hoverinfo="text", name=~throw_label)
|
| 2026 |
+
}
|
| 2027 |
+
p %>% layout(
|
| 2028 |
+
title=list(text=paste0(input$ct_catcher," - Catcher Release Point"), font=list(size=15)),
|
| 2029 |
+
xaxis=list(title="Release X (ft)", range=c(-8,8), zeroline=TRUE,
|
| 2030 |
+
zerolinecolor="gray80", gridcolor="gray90"),
|
| 2031 |
+
yaxis=list(title="Release Y (ft)", range=c(-8,8), zeroline=TRUE,
|
| 2032 |
+
zerolinecolor="gray80", gridcolor="gray90", scaleanchor="x"),
|
| 2033 |
+
showlegend=(color_by == "Result"))
|
| 2034 |
})
|
| 2035 |
|
| 2036 |
output$throw_log_table <- renderDT({
|
|
|
|
| 2103 |
bi <- 1; bo <- 4; bymin <- -2.5; bymax <- 3.7
|
| 2104 |
|
| 2105 |
if (view_mode == "Heatmap" && nrow(bd) >= 3) {
|
| 2106 |
+
p <- plot_ly(bd, x=~plot_x, y=~plot_y, type="histogram2dcontour",
|
| 2107 |
+
colorscale=list(c(0,"white"),c(0.25,"#0551bc"),c(0.5,"#03ff00"),c(0.75,"#fbff00"),c(1,"#dc1100")),
|
| 2108 |
+
showscale=FALSE) %>%
|
| 2109 |
+
layout(title=list(text="Blocking (Overhead) - Heatmap", font=list(size=14)),
|
| 2110 |
+
xaxis=list(title=""), yaxis=list(title="", scaleanchor="x"),
|
| 2111 |
+
shapes=list(
|
| 2112 |
+
list(type="rect", x0=bi,x1=bo,y0=bymin,y1=bymax, line=list(color="black",width=2), fillcolor="rgba(0,0,0,0)"),
|
| 2113 |
+
list(type="rect", x0=-bo,x1=-bi,y0=bymin,y1=bymax, line=list(color="black",width=2), fillcolor="rgba(0,0,0,0)"),
|
| 2114 |
+
list(type="path",
|
| 2115 |
+
path="M -0.708 1.417 L 0.708 1.417 L 0.708 0.708 L 0 0 L -0.708 0.708 Z",
|
| 2116 |
+
line=list(color="black",width=2), fillcolor="rgba(0,0,0,0)")))
|
| 2117 |
+
return(p)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2118 |
}
|
| 2119 |
|
| 2120 |
# Points mode
|
|
|
|
| 2152 |
bd <- block_data() %>%
|
| 2153 |
filter(!is.na(PlateLocSide) & !is.na(PlateLocHeight)) %>%
|
| 2154 |
mutate(row_num = row_number())
|
| 2155 |
+
|
| 2156 |
view_mode <- input$block_view_mode
|
| 2157 |
+
|
| 2158 |
if (nrow(bd) == 0) {
|
| 2159 |
+
return(plot_ly() %>% layout(title="Blocking (Zone)", xaxis=list(visible=FALSE), yaxis=list(visible=FALSE)))
|
|
|
|
| 2160 |
}
|
| 2161 |
+
|
| 2162 |
if (view_mode == "Heatmap" && nrow(bd) >= 3) {
|
| 2163 |
+
p <- plot_ly(bd, x=~PlateLocSide, y=~PlateLocHeight, type="histogram2dcontour",
|
| 2164 |
+
colorscale=list(c(0,"white"),c(0.25,"#0551bc"),c(0.5,"#03ff00"),c(0.75,"#fbff00"),c(1,"#dc1100")),
|
| 2165 |
+
showscale=FALSE) %>%
|
| 2166 |
+
layout(title=list(text="Blocking (Zone) - Heatmap", font=list(size=14)),
|
| 2167 |
+
xaxis=list(title="", range=c(-2.5,2.5), scaleanchor="y", showticklabels=FALSE),
|
| 2168 |
+
yaxis=list(title="", range=c(-1,4.5), showticklabels=FALSE),
|
| 2169 |
+
shapes=plotly_zone_shapes())
|
| 2170 |
+
return(p)
|
|
|
|
|
|
|
| 2171 |
}
|
| 2172 |
+
|
| 2173 |
+
# Points mode — pure plotly
|
| 2174 |
+
pt_colors <- sapply(bd$TaggedPitchType, function(pt) {
|
| 2175 |
+
if (!is.na(pt) && pt %in% names(pitch_colors)) pitch_colors[pt] else "grey60"
|
| 2176 |
+
})
|
| 2177 |
+
symbols <- ifelse(bd$block_type == "PB/WP", "triangle-up", "circle")
|
| 2178 |
+
p <- plot_ly(bd, x=~PlateLocSide, y=~PlateLocHeight, type="scatter", mode="markers+text",
|
| 2179 |
+
marker=list(size=14, color=pt_colors, symbol=symbols, line=list(color="black", width=1.2)),
|
| 2180 |
+
text=~as.character(row_num), textfont=list(size=8, color="white"),
|
| 2181 |
+
textposition="middle center",
|
| 2182 |
+
hovertext=~paste0("#",row_num,"<br>Pitch: ",TaggedPitchType,
|
| 2183 |
+
"<br>Type: ",block_type,
|
| 2184 |
+
"<br>Pitcher: ",Pitcher,"<br>Batter: ",Batter,
|
| 2185 |
+
"<br>Velo: ",round(RelSpeed,1)," mph",
|
| 2186 |
+
"<br>RV: ",round(mean_DRE,3),"<br>Date: ",Date),
|
| 2187 |
+
hoverinfo="text") %>%
|
| 2188 |
+
layout(title=list(text="Blocking (Zone)", font=list(size=14)),
|
| 2189 |
+
xaxis=list(title="", range=c(-2.5,2.5), scaleanchor="y", showticklabels=FALSE),
|
| 2190 |
+
yaxis=list(title="", range=c(-1,4.5), showticklabels=FALSE),
|
| 2191 |
+
shapes=plotly_zone_shapes(), showlegend=FALSE)
|
| 2192 |
+
p
|
|
|
|
| 2193 |
})
|
| 2194 |
|
| 2195 |
output$block_log_table <- renderDT({
|