-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy path2018_matches.Rmd
158 lines (132 loc) · 6.85 KB
/
2018_matches.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
---
title: "2018 FRC Match Analysis"
author: "Greg Marra"
output: github_document
---
A notebook to get FRC Match data from The Blue Alliance API.
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(tidyverse)
library(skimr)
source("get_tba_data.R")
events <- getEvents("2018")
# Get Matches
matches <- events$event_code %>%
map(~ getEventMatches(2018, .x)) %>%
bind_rows()
comp_levels <- c("qm", "qf", "sf", "f")
```
# Distribution Of Match Scores
The 2018 FRC game is somewhat unique, in that there is a maximum number of ownership points that can exist in a match, and teams need to tip the accumulation of those points towards their alliance. Early scoring is worth much more in that it can accumulate longer, while a box scored in a Switch or Scale during the last second of the match can only be worth a single point.
Here we look at the results from `r nrow(matches)` matches played so far this year.
```{r match_score_distribution}
matches %>%
gather(alliances.red.score, alliances.blue.score, key = "alliance", value = "score") %>%
filter(score >= 0) %>%
ggplot(aes(parse_factor(comp_level, levels = comp_levels, ordered = TRUE), score)) +
geom_boxplot() +
labs(
title = "Score distribution across 2018 FRC matches",
subtitle = "Scores are higher in elims, andwith a smaller range in finals",
x = "Competition Level",
y = "Score"
)
```
```{r win_margins}
matches %>%
filter(alliances.red.score >= 0) %>%
filter(alliances.blue.score >= 0) %>%
mutate(
win_margin = abs(alliances.red.score - alliances.blue.score)
) %>%
ggplot(aes(parse_factor(comp_level, levels = comp_levels, ordered = TRUE), win_margin)) +
geom_boxplot() +
labs(
title = "Win margins across 2018 FRC matches",
subtitle = "Matches are closer in finals, as expected",
x = "Competition Level",
y = "Win Margin"
)
```
## Ownership Deltas
How big are the swings between ownership?
```{r ownership_deltas}
matches_ownership <- matches %>%
filter(alliances.red.score >= 0) %>%
filter(alliances.blue.score >= 0) %>%
filter(winning_alliance != "") %>%
mutate(
red_switch_ownership_pts = score_breakdown.red.autoSwitchOwnershipSec * 2 + score_breakdown.red.teleopSwitchOwnershipSec,
blue_switch_ownership_pts = score_breakdown.blue.autoSwitchOwnershipSec * 2 + score_breakdown.blue.teleopSwitchOwnershipSec,
red_scale_ownership_pts = score_breakdown.red.autoScaleOwnershipSec * 2 + score_breakdown.red.teleopScaleOwnershipSec,
blue_scale_ownership_pts = score_breakdown.blue.autoScaleOwnershipSec * 2 + score_breakdown.blue.teleopScaleOwnershipSec,
switch_ownership_delta = red_switch_ownership_pts - blue_switch_ownership_pts,
scale_ownership_delta = red_scale_ownership_pts - blue_scale_ownership_pts,
endgame_delta = score_breakdown.red.endgamePoints - score_breakdown.blue.endgamePoints,
vault_delta = score_breakdown.red.vaultPoints - score_breakdown.blue.vaultPoints,
foul_delta = score_breakdown.red.foulPoints - score_breakdown.blue.foulPoints,
auto_delta = score_breakdown.red.autoPoints - score_breakdown.blue.autoPoints,
score_delta = alliances.red.score - alliances.blue.score)
matches_ownership %>%
ggplot(aes(switch_ownership_delta,
scale_ownership_delta,
color = winning_alliance,
shape = parse_factor(comp_level, levels = comp_levels, ordered = TRUE)),
alpha = 0.8) +
geom_point() +
geom_abline(slope = -1) +
labs(
title = "Ownership Points",
x = "Switch Ownership Delta (Red - Blue)",
y = "Scale Ownership Detla (Red - Blue)",
color = "Winner",
shape = "Comp Level"
) +
scale_colour_manual(values = c(red = "red", blue = "blue"))
matches_ownership %>%
gather(switch_ownership_delta, scale_ownership_delta, key = "ownership_object", value = "ownership_delta") %>%
mutate(ownership_object = factor(ownership_object)) %>%
mutate(ownership_object = fct_recode(ownership_object,
"Switch" = "switch_ownership_delta",
"Scale" = "scale_ownership_delta"
)) %>%
ggplot(aes(abs(ownership_delta), color = ownership_object)) +
geom_freqpoly(binwidth = 6) +
labs(
title = "Ownership Points",
x = "Ownership Delta",
y = "Match Count",
color = "Scoring Object"
)
```
## Lose the Scale Win the Match
```{r}
matches_lose_scale_win_match <- matches_ownership %>%
filter(((scale_ownership_delta < 0) & (winning_alliance == "red")) |
((scale_ownership_delta > 0) & (winning_alliance == "blue")))
```
What explains the `r nrow(matches_lose_scale_win_match) / nrow(matches) * 100`% of matches where the team loses the Scale but still wins the Match (`r nrow(matches_lose_scale_win_match)` out of `r nrow(matches)` matches)?
We can look at the "scale deficit" a team had to overcome, and see what percentage of the scale deficit was overcome by deltas in other scoring objectives. We can normalize these deltas by the size of the Scale deficit that had to be overcome vs how large these deltas were. For example, if the Red Alliance Endgame scored more 60 points, and the Scale deficit they had to overcome was 45 points, their Endgame overcame 133% of the deficit.
Looking at the summary statistics for matches where Red lost the Scale but won the match, we can see that the median of the percent of the deficit overcome for the Endgame is about 67%, and the median for Switch ownership is about 122%, while the vault points are only 25%. It's hard to perfectly evaluate the vault points, because they also contribute to the powerups. I haven't totally vetted that I'm looking at the score breakdowns correctly here, so I'm not sure if this is all fully capturing everything. However, this suggests that if you're going to lose the Scale, you better win the Switch and nail your Endgame!
```{r lose_the_scale_win_the_match}
## Thought to explore here:
## In matches where the alliance loses the scale but manages to win, what fraction of the score_delta is explained by climb_delta, vault_delta, etc? What mechanic are teams using to lose the scale but win the match?
matches_lose_scale_win_match %>%
ggplot(aes(scale_ownership_delta, score_delta, color = winning_alliance)) +
geom_point() +
scale_colour_manual(values = c(red = "red", blue = "blue"))
matches_ownership %>%
filter(((scale_ownership_delta < 0) & (winning_alliance == "red")) |
((scale_ownership_delta > 0) & (winning_alliance == "blue"))) %>%
filter(winning_alliance == "red") %>%
filter(foul_delta < score_delta) %>% # remove matches won on fouls
mutate(
switch_ownership_delta_pct_margin = switch_ownership_delta / -scale_ownership_delta,
endgame_delta_pct_margin = endgame_delta / -scale_ownership_delta,
vault_delta_pct_margin = vault_delta / -scale_ownership_delta,
foul_delta_pct_margin = foul_delta / -scale_ownership_delta,
auto_delta_pct_margin = auto_delta / -scale_ownership_delta
) %>%
select(contains("delta")) %>%
skim()
```