This is an R Markdown
Notebook. When you execute code within the notebook, the results appear
beneath the code.
Week 8 Data Dive
library(tidyverse)
library(ggplot2)
library(dplyr)
library(tidyverse)
library(ggthemes)
library(ggrepel)
library(effsize)
library(pwrss)
library(tidyverse)
library(ggthemes)
library(ggrepel)
library(AmesHousing)
library(boot)
library(broom)
library(lindia)
# remove scientific notation
options(scipen = 6)
# default theme, unless otherwise noted
theme_set(theme_minimal())
df<- read_delim("/Users/matthewjobe/Downloads/quasi_winshares.csv", delim = ",")
Rows: 98796 Columns: 16── Column specification ───────────────────────────────────
Delimiter: ","
chr (8): name_common, player_ID, team_ID, lg_ID, def_po...
dbl (8): age, year_ID, pct_PT, WAR162, quasi_ws, stint_...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
library(dplyr) #Changing all instances where a player has multiple positions, to "UTL"
library(stringr) #UTL stands for utility player
df |>
filter(year_ID>2004 & year_ID<2019)|>
mutate(def_pos = ifelse(str_detect(def_pos, ","), "UTL", def_pos))|>
group_by(def_pos)|> #Grouping based on defensive position
summarize(count1=n(),#count of player by year
mean(WAR162))
df
df <- df |>
mutate(def_pos = ifelse(str_detect(def_pos, ","), "UTL", def_pos))
# Check if changes were applied
df |> filter(def_pos == "UTL") |> head()
NA
The two columns I will be looking at this week are the “WAR162” and
“def_pos” columns. WAR162 stand Wins Above Replacement per 162 team
games. The def-pos column represents what position they player plays.
Because some players have multiple positions, I changed the pertaining
values to “UTL” (utility player).
WAR162 is the response variable and def_pos is the explanatory
variable. I am interested in whether the position played has any effect
on WAR162.
Null hypothesis: Average WAR162 is equal across all positions.
df <- df |> drop_na() #getting ride of rows with missing values
df_new <- df |> filter(year_ID > 2004)
df_new |>
filter(year_ID>2004 )|>
ggplot() +
geom_boxplot(mapping = aes(y = WAR162, x = def_pos)) +
#scale_y_log10(labels = \(x) paste('$', x / 1000, 'K')) +
annotation_logticks(sides = 'l') +
labs(x = "Position",
y = "WAR162")

Above, we can see that some positions typically have higher WAR162
statistics that others. I want to know if the differences are
significant enough to challenge the hypothesis that they are all
equal.
df_new |> ggplot(aes(x = WAR162)) +
geom_histogram(bins = 40, fill = "blue", alpha = 0.5) +
labs(title = "Histogram of WAR162")

The histogram above shows a WAR162 distribution. It seems be centered
at 0, and have a slight right skew. This means most players contribute a
neutral value to their ream, and there are more players with very high
WAR162 stats than low ones.
m <- aov(WAR162 ~ def_pos, data = df_new)
summary(m)
Df Sum Sq Mean Sq F value Pr(>F)
def_pos 9 2822 313.60 159.1 <2e-16 ***
Residuals 21277 41927 1.97
---
Signif. codes:
0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
With the above code we get a very small p-value of essentially zero,
which indicates that is unlikely that all of the mean WAR162’s by
position are the same and at least one is different.
Because the p-value is so small I reject the null hypothesis that
average WAR162 is equal across all positions. This suggests that one or
more position has significantly different WAR162 compared to other.
This is interesting as defensive position is associated with their
WAR162 statistics. When constructing a team, certain positions may have
less value than others. It also ties into salary, as teams may be
willing to pay more for a “premium position”.
pairwise.t.test(df_new$WAR162, df_new$def_pos, p.adjust.method = "bonferroni")
Pairwise comparisons using t tests with pooled SD
data: df_new$WAR162 and df_new$def_pos
1B 2B 3B C CF LF
2B 2.7e-05 - - - - -
3B 1.8e-14 0.14524 - - - -
C < 2e-16 < 2e-16 < 2e-16 - - -
CF < 2e-16 0.00065 1.00000 < 2e-16 - -
LF 1.00000 3.9e-05 1.2e-12 3.8e-11 < 2e-16 -
P < 2e-16 < 2e-16 < 2e-16 0.07561 < 2e-16 1.7e-08
RF 0.02550 1.00000 0.01222 < 2e-16 3.8e-05 0.01178
SS 6.6e-16 0.19170 1.00000 < 2e-16 1.00000 2.6e-13
UTL < 2e-16 < 2e-16 < 2e-16 0.00358 < 2e-16 5.9e-07
P RF SS
2B - - -
3B - - -
C - - -
CF - - -
LF - - -
P - - -
RF < 2e-16 - -
SS < 2e-16 0.01509 -
UTL 1.00000 < 2e-16 < 2e-16
P value adjustment method: bonferroni
Above, a multiple pairwise t-tests to compares each grouping of row
and column. It tells us that there are definitely some significant
differences such as:
Catcher is significantly different from every other
position.
Pitcher is significantly different from all roles except
“utility” players and catchers.
Utility players are significantly different from all roles except
pitcher.
Left Field is significantly different from all positions except
First Base
First Base is significantly different from all positions except
Left Field
# we use a "_" so we don't overwrite the original function
boot_ci <- function (v, func = median, conf = 0.95, n_iter = 100) {
# the function we want to run on each iteration i
boot_func <- \(x, i) func(x[i])
# the boot instance, running the function on each iteration
b <- boot(v, boot_func, R = n_iter)
b <- boot.ci(b, conf = conf, type = "perc")
# return just the lower and upper values
return(c("lower" = b$percent[4],
"upper" = b$percent[5]))
}
df_ci <- df_new |>
group_by(def_pos) |>
summarise(ci_lower = boot_ci(WAR162, mean)['lower'],
mean_war = mean(WAR162),
ci_upper = boot_ci(WAR162, mean)['upper'])
df_ci
df_ci |>
ggplot() +
geom_errorbarh(mapping = aes(y = def_pos,
xmin=ci_lower, xmax=ci_upper,
color = '95% C.I.'), height = 0.5) +
geom_point(mapping = aes(x = mean_war, y = def_pos,
color = 'Group Mean'),
shape = '|',
size = 5) +
scale_color_manual(values=c('black', 'orange')) +
labs(title = "WAR162 By Defensive Position",
x = "WAR162",
y = "Defensive Position",
color = '')

The visual above shows us the WAR162’s by position. It makes it much
easier to spot some of the differences in WAR162 by position. The
visualization supports the statements above:
Catcher is significantly different from every other
position.
Pitcher is significantly different from all roles except
“utility” players and catchers.
Utility players are significantly different from all roles except
pitcher.
Left Field is significantly different from all positions except
First Base
First Base is significantly different from all positions except
Left Field
LINEAR REGRESSION
Next I will build a linear regression model for the variables share
of playing time and “WAR162”. This will estimate a relationship between
the two variables, showing how much WAR162 changes with playing
time.
df_new |>
ggplot(mapping = aes(x = pct_PT, y = WAR162)) +
geom_point(size = 2) +
geom_smooth(method = "lm", se = FALSE, color = 'darkblue') +
labs(title = "Linear Relationship Between Playing Time and WAR162",
x = "Percent of Playing Time",
y = "WAR162") +
theme_minimal()

model <- lm(WAR162 ~ pct_PT, data = df_new)
summary(model)
Call:
lm(formula = WAR162 ~ pct_PT, data = df_new)
Residuals:
Min 1Q Median 3Q Max
-5.2702 -0.4408 0.0741 0.4078 7.9911
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.443377 0.010095 -43.92 <2e-16 ***
pct_PT 0.543718 0.003525 154.26 <2e-16 ***
---
Signif. codes:
0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.9963 on 21285 degrees of freedom
Multiple R-squared: 0.5279, Adjusted R-squared: 0.5278
F-statistic: 2.38e+04 on 1 and 21285 DF, p-value: < 2.2e-16
There does appear to be a linear association between share of playing
time and WAR162. There is an estimated slope of 0.544, which means that
for every 1 percent point in increase in pct_PT, WAR162 increases by
0.544. The small p-value also shows me that pct_PT (playing time) has a
statistically significant relationship with WAR162. Additionally, we can
see that Multiple R-Squared value is about 0.53. This means that
approximately 53% of the variance in WAR162 is explained by pct_PT.
# the line estimated above
lm_ <- \(x) (1 / 2) * x + 3
df_new |>
ggplot(mapping = aes(x = pct_PT, y = WAR162)) +
geom_point(size = 2) +
geom_segment(mapping = aes(xend = pct_PT, y = WAR162, yend = lm_(WAR162),
color = 'error'), linewidth = 1) +
geom_smooth(method = "lm", se = FALSE, color = 'red', linewidth = 0.5) +
scale_color_manual(values = c('darkblue')) +
labs(color = '')

There does appear to be quite a bit of error in the visualization
above.
beta_0 <- 3
beta_1 <- 1/2
lm_ <- \(x) beta_1 * x + beta_0
df_new |>
ggplot() +
geom_point(mapping = aes(x = pct_PT, y = WAR162), size = 2) +
geom_smooth(mapping = aes(x = pct_PT, y = WAR162), method = "lm", se = FALSE, color = 'red', linewidth = 0.5) +
geom_rect(mapping = aes(xmin = pct_PT,
xmax = pct_PT + abs(WAR162 - lm_(pct_PT)),
ymin = lm_(pct_PT),
ymax = WAR162),
fill = NA, color = 'darkblue') +
labs(color = '')

There are so many data points which makes it very hard to understand
the two visualizations above.
model <- lm(WAR162 ~ pct_PT, df_new)
model$coefficients
(Intercept) pct_PT
-0.4433769 0.5437183
From this output, we see that the expected WAR162, when the share of
playing time is zero, is -0.44. For every 1 percent point in increase in
pct_PT, WAR162 increases by 0.544.
I believe this is a good fit because the slope of 0.544 indicates a
meaning relationship. Additionally, there was a very small p-value which
shows that the predictor (pct_PT) is statistically significant.
However, the multiple R-squared value of 0.53 tells us that pct_PT
explains 53% of the variance in WAR162. This leaves the rest of the
variance unexplained, and there could be other factors influencing
WAR162.
I think that using multiple explanatory variables would have be an
optimal way of building this model. Other factors such as team and age
could also influence WAR162. Originally I was going to look at the
relationship with age and WAR162, but it was not linear. As players get
older, their WAR162 stats start to become lower.
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4KCiMjIFdlZWsgOCBEYXRhIERpdmUKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3RoZW1lcykKbGlicmFyeShnZ3JlcGVsKQpsaWJyYXJ5KGVmZnNpemUpCmxpYnJhcnkocHdyc3MpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdndGhlbWVzKQpsaWJyYXJ5KGdncmVwZWwpCmxpYnJhcnkoQW1lc0hvdXNpbmcpCmxpYnJhcnkoYm9vdCkKbGlicmFyeShicm9vbSkKbGlicmFyeShsaW5kaWEpCgojIHJlbW92ZSBzY2llbnRpZmljIG5vdGF0aW9uCm9wdGlvbnMoc2NpcGVuID0gNikKCiMgZGVmYXVsdCB0aGVtZSwgdW5sZXNzIG90aGVyd2lzZSBub3RlZAp0aGVtZV9zZXQodGhlbWVfbWluaW1hbCgpKQoKZGY8LSByZWFkX2RlbGltKCIvVXNlcnMvbWF0dGhld2pvYmUvRG93bmxvYWRzL3F1YXNpX3dpbnNoYXJlcy5jc3YiLCBkZWxpbSA9ICIsIikKYGBgCgpgYGB7cn0KbGlicmFyeShkcGx5cikgI0NoYW5naW5nIGFsbCBpbnN0YW5jZXMgd2hlcmUgYSBwbGF5ZXIgaGFzIG11bHRpcGxlIHBvc2l0aW9ucywgdG8gIlVUTCIKbGlicmFyeShzdHJpbmdyKSAjVVRMIHN0YW5kcyBmb3IgdXRpbGl0eSBwbGF5ZXIKCgoKCmRmIHw+CiAgZmlsdGVyKHllYXJfSUQ+MjAwNCAmIHllYXJfSUQ8MjAxOSl8PgogIG11dGF0ZShkZWZfcG9zID0gaWZlbHNlKHN0cl9kZXRlY3QoZGVmX3BvcywgIiwiKSwgIlVUTCIsIGRlZl9wb3MpKXw+CiAgZ3JvdXBfYnkoZGVmX3Bvcyl8PiAjR3JvdXBpbmcgYmFzZWQgb24gZGVmZW5zaXZlIHBvc2l0aW9uCiAgc3VtbWFyaXplKGNvdW50MT1uKCksI2NvdW50IG9mIHBsYXllciBieSB5ZWFyCiAgbWVhbihXQVIxNjIpKQpkZgpgYGAKCmBgYHtyfQpkZiA8LSBkZiB8PiAKICBtdXRhdGUoZGVmX3BvcyA9IGlmZWxzZShzdHJfZGV0ZWN0KGRlZl9wb3MsICIsIiksICJVVEwiLCBkZWZfcG9zKSkKCiMgQ2hlY2sgaWYgY2hhbmdlcyB3ZXJlIGFwcGxpZWQKZGYgfD4gZmlsdGVyKGRlZl9wb3MgPT0gIlVUTCIpIHw+IGhlYWQoKQoKYGBgCgpUaGUgdHdvIGNvbHVtbnMgSSB3aWxsIGJlIGxvb2tpbmcgYXQgdGhpcyB3ZWVrIGFyZSB0aGUgIldBUjE2MiIgYW5kICJkZWZfcG9zIiBjb2x1bW5zLiBXQVIxNjIgc3RhbmQgV2lucyBBYm92ZSBSZXBsYWNlbWVudCBwZXIgMTYyIHRlYW0gZ2FtZXMuIFRoZSBkZWYtcG9zIGNvbHVtbiByZXByZXNlbnRzIHdoYXQgcG9zaXRpb24gdGhleSBwbGF5ZXIgcGxheXMuIEJlY2F1c2Ugc29tZSBwbGF5ZXJzIGhhdmUgbXVsdGlwbGUgcG9zaXRpb25zLCBJIGNoYW5nZWQgdGhlIHBlcnRhaW5pbmcgdmFsdWVzIHRvICJVVEwiICh1dGlsaXR5IHBsYXllcikuCgpXQVIxNjIgaXMgdGhlIHJlc3BvbnNlIHZhcmlhYmxlIGFuZCBkZWZfcG9zIGlzIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZS4gSSBhbSBpbnRlcmVzdGVkIGluIHdoZXRoZXIgdGhlIHBvc2l0aW9uIHBsYXllZCBoYXMgYW55IGVmZmVjdCBvbiBXQVIxNjIuCgpOdWxsIGh5cG90aGVzaXM6IEF2ZXJhZ2UgV0FSMTYyIGlzIGVxdWFsIGFjcm9zcyBhbGwgcG9zaXRpb25zLgoKYGBge3J9CmRmIDwtIGRmIHw+IGRyb3BfbmEoKSAjZ2V0dGluZyByaWRlIG9mIHJvd3Mgd2l0aCBtaXNzaW5nIHZhbHVlcwpkZl9uZXcgPC0gZGYgfD4gZmlsdGVyKHllYXJfSUQgPiAyMDA0KQoKYGBgCgpgYGB7cn0KZGZfbmV3IHw+CiAgZmlsdGVyKHllYXJfSUQ+MjAwNCApfD4KICBnZ3Bsb3QoKSArCiAgZ2VvbV9ib3hwbG90KG1hcHBpbmcgPSBhZXMoeSA9IFdBUjE2MiwgeCA9IGRlZl9wb3MpKSArCiAgI3NjYWxlX3lfbG9nMTAobGFiZWxzID0gXCh4KSBwYXN0ZSgnJCcsIHggLyAxMDAwLCAnSycpKSArCiAgYW5ub3RhdGlvbl9sb2d0aWNrcyhzaWRlcyA9ICdsJykgKwogIGxhYnMoeCA9ICJQb3NpdGlvbiIsCiAgICAgICB5ID0gIldBUjE2MiIpCmBgYAoKQWJvdmUsIHdlIGNhbiBzZWUgdGhhdCBzb21lIHBvc2l0aW9ucyB0eXBpY2FsbHkgaGF2ZSBoaWdoZXIgV0FSMTYyIHN0YXRpc3RpY3MgdGhhdCBvdGhlcnMuIEkgd2FudCB0byBrbm93IGlmIHRoZSBkaWZmZXJlbmNlcyBhcmUgc2lnbmlmaWNhbnQgZW5vdWdoIHRvIGNoYWxsZW5nZSB0aGUgaHlwb3RoZXNpcyB0aGF0IHRoZXkgYXJlIGFsbCBlcXVhbC4KCmBgYHtyfQpkZl9uZXcgfD4gZ2dwbG90KGFlcyh4ID0gV0FSMTYyKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gNDAsIGZpbGwgPSAiYmx1ZSIsIGFscGhhID0gMC41KSArCiAgbGFicyh0aXRsZSA9ICJIaXN0b2dyYW0gb2YgV0FSMTYyIikKYGBgCgpUaGUgaGlzdG9ncmFtIGFib3ZlIHNob3dzIGEgV0FSMTYyIGRpc3RyaWJ1dGlvbi4gSXQgc2VlbXMgYmUgY2VudGVyZWQgYXQgMCwgYW5kIGhhdmUgYSBzbGlnaHQgcmlnaHQgc2tldy4gVGhpcyBtZWFucyBtb3N0IHBsYXllcnMgY29udHJpYnV0ZSBhIG5ldXRyYWwgdmFsdWUgdG8gdGhlaXIgcmVhbSwgYW5kIHRoZXJlIGFyZSBtb3JlIHBsYXllcnMgd2l0aCB2ZXJ5IGhpZ2ggV0FSMTYyIHN0YXRzIHRoYW4gbG93IG9uZXMuCgpgYGB7cn0KbSA8LSBhb3YoV0FSMTYyIH4gZGVmX3BvcywgZGF0YSA9IGRmX25ldykKc3VtbWFyeShtKQpgYGAKCldpdGggdGhlIGFib3ZlIGNvZGUgd2UgZ2V0IGEgdmVyeSBzbWFsbCBwLXZhbHVlIG9mIGVzc2VudGlhbGx5IHplcm8sIHdoaWNoIGluZGljYXRlcyB0aGF0IGlzIHVubGlrZWx5IHRoYXQgYWxsIG9mIHRoZSBtZWFuIFdBUjE2MidzIGJ5IHBvc2l0aW9uIGFyZSB0aGUgc2FtZSBhbmQgYXQgbGVhc3Qgb25lIGlzIGRpZmZlcmVudC4KCkJlY2F1c2UgdGhlIHAtdmFsdWUgaXMgc28gc21hbGwgSSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IGF2ZXJhZ2UgV0FSMTYyIGlzIGVxdWFsIGFjcm9zcyBhbGwgcG9zaXRpb25zLiBUaGlzIHN1Z2dlc3RzIHRoYXQgb25lIG9yIG1vcmUgcG9zaXRpb24gaGFzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IFdBUjE2MiBjb21wYXJlZCB0byBvdGhlci4KClRoaXMgaXMgaW50ZXJlc3RpbmcgYXMgZGVmZW5zaXZlIHBvc2l0aW9uIGlzIGFzc29jaWF0ZWQgd2l0aCB0aGVpciBXQVIxNjIgc3RhdGlzdGljcy4gV2hlbiBjb25zdHJ1Y3RpbmcgYSB0ZWFtLCBjZXJ0YWluIHBvc2l0aW9ucyBtYXkgaGF2ZSBsZXNzIHZhbHVlIHRoYW4gb3RoZXJzLiBJdCBhbHNvIHRpZXMgaW50byBzYWxhcnksIGFzIHRlYW1zIG1heSBiZSB3aWxsaW5nIHRvIHBheSBtb3JlIGZvciBhICJwcmVtaXVtIHBvc2l0aW9uIi4KCmBgYHtyfQpwYWlyd2lzZS50LnRlc3QoZGZfbmV3JFdBUjE2MiwgZGZfbmV3JGRlZl9wb3MsIHAuYWRqdXN0Lm1ldGhvZCA9ICJib25mZXJyb25pIikKYGBgCgpBYm92ZSwgYSBtdWx0aXBsZSBwYWlyd2lzZSB0LXRlc3RzIHRvIGNvbXBhcmVzIGVhY2ggZ3JvdXBpbmcgb2Ygcm93IGFuZCBjb2x1bW4uIEl0IHRlbGxzIHVzIHRoYXQgdGhlcmUgYXJlIGRlZmluaXRlbHkgc29tZSBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBzdWNoIGFzOgoKMSkgIENhdGNoZXIgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSBldmVyeSBvdGhlciBwb3NpdGlvbi4KCjIpICBQaXRjaGVyIGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gYWxsIHJvbGVzIGV4Y2VwdCAidXRpbGl0eSIgcGxheWVycyBhbmQgY2F0Y2hlcnMuCgozKSAgVXRpbGl0eSBwbGF5ZXJzIGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIGFsbCByb2xlcyBleGNlcHQgcGl0Y2hlci4KCjQpICBMZWZ0IEZpZWxkIGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gYWxsIHBvc2l0aW9ucyBleGNlcHQgRmlyc3QgQmFzZQoKNSkgIEZpcnN0IEJhc2UgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSBhbGwgcG9zaXRpb25zIGV4Y2VwdCBMZWZ0IEZpZWxkCgpgYGB7cn0KIyB3ZSB1c2UgYSAiXyIgc28gd2UgZG9uJ3Qgb3ZlcndyaXRlIHRoZSBvcmlnaW5hbCBmdW5jdGlvbgpib290X2NpIDwtIGZ1bmN0aW9uICh2LCBmdW5jID0gbWVkaWFuLCBjb25mID0gMC45NSwgbl9pdGVyID0gMTAwKSB7CiAgIyB0aGUgZnVuY3Rpb24gd2Ugd2FudCB0byBydW4gb24gZWFjaCBpdGVyYXRpb24gaQogIGJvb3RfZnVuYyA8LSBcKHgsIGkpIGZ1bmMoeFtpXSkKICAKICAjIHRoZSBib290IGluc3RhbmNlLCBydW5uaW5nIHRoZSBmdW5jdGlvbiBvbiBlYWNoIGl0ZXJhdGlvbgogIGIgPC0gYm9vdCh2LCBib290X2Z1bmMsIFIgPSBuX2l0ZXIpCiAgYiA8LSBib290LmNpKGIsIGNvbmYgPSBjb25mLCB0eXBlID0gInBlcmMiKQogIAogICMgcmV0dXJuIGp1c3QgdGhlIGxvd2VyIGFuZCB1cHBlciB2YWx1ZXMKICByZXR1cm4oYygibG93ZXIiID0gYiRwZXJjZW50WzRdLAogICAgICAgICAgICJ1cHBlciIgPSBiJHBlcmNlbnRbNV0pKQp9CmBgYAoKYGBge3J9CmRmX2NpIDwtIGRmX25ldyB8PgogIGdyb3VwX2J5KGRlZl9wb3MpIHw+CiAgc3VtbWFyaXNlKGNpX2xvd2VyID0gYm9vdF9jaShXQVIxNjIsIG1lYW4pWydsb3dlciddLAogICAgICAgICAgICBtZWFuX3dhciA9IG1lYW4oV0FSMTYyKSwKICAgICAgICAgICAgY2lfdXBwZXIgPSBib290X2NpKFdBUjE2MiwgbWVhbilbJ3VwcGVyJ10pCgpkZl9jaQpgYGAKCmBgYHtyfQpkZl9jaSB8PgogIGdncGxvdCgpICsKICBnZW9tX2Vycm9yYmFyaChtYXBwaW5nID0gYWVzKHkgPSBkZWZfcG9zLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhtaW49Y2lfbG93ZXIsIHhtYXg9Y2lfdXBwZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICc5NSUgQy5JLicpLCBoZWlnaHQgPSAwLjUpICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IG1lYW5fd2FyLCB5ID0gZGVmX3BvcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAnR3JvdXAgTWVhbicpLAogICAgICAgICAgICAgc2hhcGUgPSAnfCcsCiAgICAgICAgICAgICBzaXplID0gNSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygnYmxhY2snLCAnb3JhbmdlJykpICsKICBsYWJzKHRpdGxlID0gIldBUjE2MiBCeSBEZWZlbnNpdmUgUG9zaXRpb24iLAogICAgICAgeCA9ICJXQVIxNjIiLAogICAgICAgeSA9ICJEZWZlbnNpdmUgUG9zaXRpb24iLAogICAgICAgY29sb3IgPSAnJykKYGBgCgpUaGUgdmlzdWFsIGFib3ZlIHNob3dzIHVzIHRoZSBXQVIxNjIncyBieSBwb3NpdGlvbi4gSXQgbWFrZXMgaXQgbXVjaCBlYXNpZXIgdG8gc3BvdCBzb21lIG9mIHRoZSBkaWZmZXJlbmNlcyBpbiBXQVIxNjIgYnkgcG9zaXRpb24uIFRoZSB2aXN1YWxpemF0aW9uIHN1cHBvcnRzIHRoZSBzdGF0ZW1lbnRzIGFib3ZlOgoKMSkgIENhdGNoZXIgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSBldmVyeSBvdGhlciBwb3NpdGlvbi4KCjIpICBQaXRjaGVyIGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gYWxsIHJvbGVzIGV4Y2VwdCAidXRpbGl0eSIgcGxheWVycyBhbmQgY2F0Y2hlcnMuCgozKSAgVXRpbGl0eSBwbGF5ZXJzIGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIGFsbCByb2xlcyBleGNlcHQgcGl0Y2hlci4KCjQpICBMZWZ0IEZpZWxkIGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gYWxsIHBvc2l0aW9ucyBleGNlcHQgRmlyc3QgQmFzZQoKNSkgIEZpcnN0IEJhc2UgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSBhbGwgcG9zaXRpb25zIGV4Y2VwdCBMZWZ0IEZpZWxkCgojIyBMSU5FQVIgUkVHUkVTU0lPTgoKTmV4dCBJIHdpbGwgYnVpbGQgYSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBmb3IgdGhlIHZhcmlhYmxlcyBzaGFyZSBvZiBwbGF5aW5nIHRpbWUgYW5kICJXQVIxNjIiLiBUaGlzIHdpbGwgZXN0aW1hdGUgYSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdHdvIHZhcmlhYmxlcywgc2hvd2luZyBob3cgbXVjaCBXQVIxNjIgY2hhbmdlcyB3aXRoIHBsYXlpbmcgdGltZS4KCmBgYHtyfQpkZl9uZXcgfD4gIAogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBwY3RfUFQsIHkgPSBXQVIxNjIpKSArICAKICBnZW9tX3BvaW50KHNpemUgPSAyKSArICAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICdkYXJrYmx1ZScpICsgIAogIGxhYnModGl0bGUgPSAiTGluZWFyIFJlbGF0aW9uc2hpcCBCZXR3ZWVuIFBsYXlpbmcgVGltZSBhbmQgV0FSMTYyIiwgIAogICAgICAgeCA9ICJQZXJjZW50IG9mIFBsYXlpbmcgVGltZSIsICAKICAgICAgIHkgPSAiV0FSMTYyIikgKyAgCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKYGBge3J9Cm1vZGVsIDwtIGxtKFdBUjE2MiB+IHBjdF9QVCwgZGF0YSA9IGRmX25ldykKc3VtbWFyeShtb2RlbCkKYGBgCgpUaGVyZSBkb2VzIGFwcGVhciB0byBiZSBhIGxpbmVhciBhc3NvY2lhdGlvbiBiZXR3ZWVuIHNoYXJlIG9mIHBsYXlpbmcgdGltZSBhbmQgV0FSMTYyLiBUaGVyZSBpcyBhbiBlc3RpbWF0ZWQgc2xvcGUgb2YgMC41NDQsIHdoaWNoIG1lYW5zIHRoYXQgZm9yIGV2ZXJ5IDEgcGVyY2VudCBwb2ludCBpbiBpbmNyZWFzZSBpbiBwY3RfUFQsIFdBUjE2MiBpbmNyZWFzZXMgYnkgMC41NDQuIFRoZSBzbWFsbCBwLXZhbHVlIGFsc28gc2hvd3MgbWUgdGhhdCBwY3RfUFQgKHBsYXlpbmcgdGltZSkgaGFzIGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCByZWxhdGlvbnNoaXAgd2l0aCBXQVIxNjIuIEFkZGl0aW9uYWxseSwgd2UgY2FuIHNlZSB0aGF0IE11bHRpcGxlIFItU3F1YXJlZCB2YWx1ZSBpcyBhYm91dCAwLjUzLiBUaGlzIG1lYW5zIHRoYXQgYXBwcm94aW1hdGVseSA1MyUgb2YgdGhlIHZhcmlhbmNlIGluIFdBUjE2MiBpcyBleHBsYWluZWQgYnkgcGN0X1BULgoKYGBge3J9CiMgdGhlIGxpbmUgZXN0aW1hdGVkIGFib3ZlCmxtXyA8LSBcKHgpICgxIC8gMikgKiB4ICsgMwoKZGZfbmV3IHw+CiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IHBjdF9QVCwgeSA9IFdBUjE2MikpICsKICBnZW9tX3BvaW50KHNpemUgPSAyKSArCiAgZ2VvbV9zZWdtZW50KG1hcHBpbmcgPSBhZXMoeGVuZCA9IHBjdF9QVCwgeSA9IFdBUjE2MiwgeWVuZCA9IGxtXyhXQVIxNjIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICdlcnJvcicpLCBsaW5ld2lkdGggPSAxKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAncmVkJywgbGluZXdpZHRoID0gMC41KSArIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCdkYXJrYmx1ZScpKSArCiAgbGFicyhjb2xvciA9ICcnKQpgYGAKClRoZXJlIGRvZXMgYXBwZWFyIHRvIGJlIHF1aXRlIGEgYml0IG9mIGVycm9yIGluIHRoZSB2aXN1YWxpemF0aW9uIGFib3ZlLgoKYGBge3J9CmJldGFfMCA8LSAzCmJldGFfMSA8LSAxLzIKCmxtXyA8LSBcKHgpIGJldGFfMSAqIHggKyBiZXRhXzAKCmRmX25ldyB8PgogIGdncGxvdCgpICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IHBjdF9QVCwgeSA9IFdBUjE2MiksIHNpemUgPSAyKSArCiAgZ2VvbV9zbW9vdGgobWFwcGluZyA9IGFlcyh4ID0gcGN0X1BULCB5ID0gV0FSMTYyKSwgbWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAncmVkJywgbGluZXdpZHRoID0gMC41KSArIAogIGdlb21fcmVjdChtYXBwaW5nID0gYWVzKHhtaW4gPSBwY3RfUFQsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHhtYXggPSBwY3RfUFQgKyBhYnMoV0FSMTYyIC0gbG1fKHBjdF9QVCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsbV8ocGN0X1BUKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgeW1heCA9IFdBUjE2MiksIAogICAgICAgICAgICBmaWxsID0gTkEsIGNvbG9yID0gJ2RhcmtibHVlJykgKwogIGxhYnMoY29sb3IgPSAnJykKYGBgCgpUaGVyZSBhcmUgc28gbWFueSBkYXRhIHBvaW50cyB3aGljaCBtYWtlcyBpdCB2ZXJ5IGhhcmQgdG8gdW5kZXJzdGFuZCB0aGUgdHdvIHZpc3VhbGl6YXRpb25zIGFib3ZlLgoKYGBge3J9Cm1vZGVsIDwtIGxtKFdBUjE2MiB+IHBjdF9QVCwgZGZfbmV3KQptb2RlbCRjb2VmZmljaWVudHMKYGBgCgpGcm9tIHRoaXMgb3V0cHV0LCB3ZSBzZWUgdGhhdCB0aGUgZXhwZWN0ZWQgV0FSMTYyLCB3aGVuIHRoZSBzaGFyZSBvZiBwbGF5aW5nIHRpbWUgaXMgemVybywgaXMgLTAuNDQuIEZvciBldmVyeSAxIHBlcmNlbnQgcG9pbnQgaW4gaW5jcmVhc2UgaW4gcGN0X1BULCBXQVIxNjIgaW5jcmVhc2VzIGJ5IDAuNTQ0LgoKSSBiZWxpZXZlIHRoaXMgaXMgYSBnb29kIGZpdCBiZWNhdXNlIHRoZSBzbG9wZSBvZiAwLjU0NCBpbmRpY2F0ZXMgYSBtZWFuaW5nIHJlbGF0aW9uc2hpcC4gQWRkaXRpb25hbGx5LCB0aGVyZSB3YXMgYSB2ZXJ5IHNtYWxsIHAtdmFsdWUgd2hpY2ggc2hvd3MgdGhhdCB0aGUgcHJlZGljdG9yIChwY3RfUFQpIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuCgpIb3dldmVyLCB0aGUgbXVsdGlwbGUgUi1zcXVhcmVkIHZhbHVlIG9mIDAuNTMgdGVsbHMgdXMgdGhhdCBwY3RfUFQgZXhwbGFpbnMgNTMlIG9mIHRoZSB2YXJpYW5jZSBpbiBXQVIxNjIuIFRoaXMgbGVhdmVzIHRoZSByZXN0IG9mIHRoZSB2YXJpYW5jZSB1bmV4cGxhaW5lZCwgYW5kIHRoZXJlIGNvdWxkIGJlIG90aGVyIGZhY3RvcnMgaW5mbHVlbmNpbmcgV0FSMTYyLgoKSSB0aGluayB0aGF0IHVzaW5nIG11bHRpcGxlIGV4cGxhbmF0b3J5IHZhcmlhYmxlcyB3b3VsZCBoYXZlIGJlIGFuIG9wdGltYWwgd2F5IG9mIGJ1aWxkaW5nIHRoaXMgbW9kZWwuIE90aGVyIGZhY3RvcnMgc3VjaCBhcyB0ZWFtIGFuZCBhZ2UgY291bGQgYWxzbyBpbmZsdWVuY2UgV0FSMTYyLiBPcmlnaW5hbGx5IEkgd2FzIGdvaW5nIHRvIGxvb2sgYXQgdGhlIHJlbGF0aW9uc2hpcCB3aXRoIGFnZSBhbmQgV0FSMTYyLCBidXQgaXQgd2FzIG5vdCBsaW5lYXIuIEFzIHBsYXllcnMgZ2V0IG9sZGVyLCB0aGVpciBXQVIxNjIgc3RhdHMgc3RhcnQgdG8gYmVjb21lIGxvd2VyLgo=