#Introduction This project analyzes WNBA 2025 box score data with the
goal of building a regression model to predict team score for the team
Mercury. The variables of interest include field goal percentage, total
rebounds, three-point field goal percentage, and steals.
After finding the best predictive model, we will use it to estimate
team score for a “median” game for team Mercury where all variables are
set to their median values.
Data
The data set was first cleaned by removing non-representative data
including the All-Star team and team USA. The data was then grouped by
team to find the means and standard deviations of the variables being
observed. A subset of the data was created for the Mercury team which
was grouped by game outcome (win/loss) to compare performance
differences between wins and losses.
The league-wide summary table provides context for overall
performance, while the team-specific table highlights how team Mercury
differs from the league.
summary %>%
kbl(digits=2,caption = "WNBA 2025 Stats") %>%
kable_classic(full_width = F, html_font = "Cambria")
WNBA 2025 Stats
|
team_name
|
mean_score
|
sd_score
|
mean_fg_pct
|
sd_fg_pct
|
mean_rbds
|
sd_rbds
|
mean_3pt_pct
|
sd_3pt_pct
|
mean_steals
|
sd_steals
|
|
Aces
|
85.52
|
9.56
|
45.27
|
5.82
|
33.78
|
5.88
|
35.27
|
7.08
|
6.80
|
2.67
|
|
Dream
|
76.93
|
10.59
|
41.28
|
6.78
|
35.95
|
4.41
|
30.83
|
9.32
|
7.14
|
2.82
|
|
Fever
|
84.50
|
10.17
|
45.56
|
5.38
|
35.10
|
5.49
|
35.00
|
8.99
|
5.88
|
2.29
|
|
Liberty
|
84.98
|
9.92
|
44.53
|
5.61
|
36.90
|
5.77
|
35.38
|
10.06
|
7.75
|
2.19
|
|
Lynx
|
82.36
|
11.39
|
45.21
|
6.34
|
33.15
|
5.06
|
37.80
|
9.43
|
8.36
|
3.17
|
|
Mercury
|
81.93
|
12.60
|
44.28
|
7.34
|
32.26
|
5.39
|
32.97
|
10.34
|
6.55
|
2.12
|
|
Mystics
|
79.30
|
8.69
|
43.36
|
4.82
|
31.85
|
4.66
|
36.64
|
8.69
|
7.28
|
2.24
|
|
Sky
|
77.40
|
9.62
|
42.44
|
5.22
|
36.60
|
5.57
|
31.74
|
11.62
|
7.00
|
3.30
|
|
Sparks
|
78.40
|
10.57
|
42.63
|
6.15
|
32.67
|
5.52
|
32.09
|
11.00
|
7.30
|
2.78
|
|
Storm
|
82.67
|
9.65
|
43.43
|
5.39
|
34.67
|
6.02
|
28.35
|
9.03
|
9.24
|
3.27
|
|
Sun
|
80.36
|
9.89
|
44.30
|
5.28
|
33.43
|
4.62
|
32.84
|
11.67
|
7.89
|
3.29
|
|
Wings
|
84.20
|
11.47
|
44.47
|
5.24
|
34.75
|
4.65
|
32.06
|
11.75
|
7.12
|
2.95
|
#Table for entire WNBA League
result %>%
kbl(digits=2,caption = "WNBA 2025 Mercury Stats") %>%
kable_classic(full_width = F, html_font = "Cambria")
WNBA 2025 Mercury Stats
|
result
|
mean_score
|
sd_score
|
mean_fg_pct
|
sd_fg_pct
|
mean_rbds
|
sd_rbds
|
mean_3pt_pct
|
sd_3pt_pct
|
mean_steals
|
sd_steals
|
|
Loss
|
75.65
|
12.42
|
40.68
|
6.66
|
31.39
|
5.25
|
29.33
|
9.99
|
6.13
|
1.82
|
|
Win
|
89.53
|
7.85
|
48.65
|
5.63
|
33.32
|
5.51
|
37.37
|
9.18
|
7.05
|
2.39
|
#Table for my WNBA team.
Box Plot
The following box plot was created to compare the distribution of
team scores between wins and losses. The distributions show that higher
scores are generally associated with wins, while lower scores are more
common in losses. This suggests that teams with higher scoring
capabilities will have higher win rates.
p = my_team %>%
ggplot(aes(x = team_score, fill = result)) +
geom_histogram(color = "#e9ecef", alpha = 0.6, position = "identity", binwidth = 4) +
scale_fill_manual(values = c("#69b3a2", "#404080")) +
labs(
title = "Distribution of Team Scores",
fill = "")
boxplot(team_score ~ result, data = my_team, notch = FALSE,
col = c('lightblue','lightgreen'),
main = "Points Scored by Game Result",
xlab = "result", ylab = "Points")

First Order Models
A first-order multiple linear regression model (Model 1) was
constructed using field goal percentage, total rebounds, three-point
field goal percentage, and steals as predictors of team score.
Correlation coefficients and Variance Inflation Factor (VIF) values
were used to determine if there was any multicollinearity in the
variables. Since no pairs of variables exhibited extremely high
correlation (|r| > 0.8) and VIF values were within acceptable limits,
no variables were removed. As a result, Model 2 remained the same as
Model 1.
model1 = lm(team_score~field_goal_pct+total_rebounds+
three_point_field_goal_pct+steals, data = my_team)
cor_data = my_team %>%
select(team_score, field_goal_pct, total_rebounds,
three_point_field_goal_pct, steals)
cor(cor_data)
vif(model1)
model2 = lm(team_score~field_goal_pct+total_rebounds+
three_point_field_goal_pct+steals, data = my_team)
Interaction Model
A full interaction model (Model 3) was constructed including all
interaction terms. Each interaction term was evaluated at the 15%
significance level.
Only the interaction between field goal percentage and three-point
field goal percentage was found to be statistically significant. All
other interaction terms were removed, resulting in the reduced
interaction model (Model 4), which retains all variables and the
significant interaction term.
model3 = lm(team_score ~ (field_goal_pct + total_rebounds +
three_point_field_goal_pct + steals)^2,
data = my_team)
model4 = lm(team_score ~ field_goal_pct + total_rebounds +
three_point_field_goal_pct + steals +
field_goal_pct:three_point_field_goal_pct,
data = my_team)
model4sum = summary(model4)
library(stargazer)
stargazer(model4, type="html")
|
|
|
|
Dependent variable:
|
|
|
|
|
|
team_score
|
|
|
|
field_goal_pct
|
1.510***
|
|
|
(0.345)
|
|
|
|
|
total_rebounds
|
0.036
|
|
|
(0.195)
|
|
|
|
|
three_point_field_goal_pct
|
0.934**
|
|
|
(0.385)
|
|
|
|
|
steals
|
1.282***
|
|
|
(0.442)
|
|
|
|
|
field_goal_pct:three_point_field_goal_pct
|
-0.013
|
|
|
(0.009)
|
|
|
|
|
Constant
|
-5.582
|
|
|
(17.205)
|
|
|
|
|
|
|
Observations
|
42
|
|
R2
|
0.810
|
|
Adjusted R2
|
0.784
|
|
Residual Std. Error
|
5.860 (df = 36)
|
|
F Statistic
|
30.693*** (df = 5; 36)
|
|
|
|
Note:
|
p<0.1; p<0.05;
p<0.01
|
\(~\) \(~\)
After all models were run and a reduction completed, my model
is
team_score= -5.5822088 + 1.5104082 * field_goal_pct + 0.0358159 *
total_rebounds + 0.9335949 * three_point_field_goal_pct + 1.2823549 *
steals + -0.0130526 * field_goal_pct:three_point_field_goal_pct
This model significantly predicts team score, F(5,36) = 30.6931812,
p<.0001, adjusted R^2= 0.7836022
Residual Analysis
Residual analysis was conducted to evaluate the assumptions of the
regression model.
The histogram of residuals indicates that the residuals slightly
skewn to the right but are approximately normally distributed. The
residuals versus fitted plot shows no clear pattern and a consistent
spread, suggesting that the assumption of linearity and constant
variance is reasonable.
The studentized residual plot was used to identify potential
outliers, with a majority of observations falling within acceptable
bounds. The points that fell out of bounds are the 2024-08-15 game
against chicago-sky and the 2024-06-09 game against dallas-wings.
The leverage plot indicates that two observations have relatively
high leverage, suggesting they fall outside the normal range of the
data. These points could influence the regression model and are notable.
The points with high leverage are the 2024-07-01 game against
connecticut-sun, the 2024-06-02 game against los-angeles-sparks, and the
2024-05-28 game against connecticut-sun.
The Cook’s distance plot identifies two observations with relatively
high influence. These points have a notable impact on the fitted
regression model and may disproportionately affect the estimated
coefficients. The points with high impact include 2024-08-15 game
against chicago-sky and 2024-05-25 game against dallas-wings. Despite
the presence of these influential and high-leverage points, their small
number means they do not substantially distort the overall model.
hist(residuals(model4),
main = "Histogram of Residuals",
xlab = "Residuals")

plot(fitted(model4), residuals(model4),
main = "Residuals vs Fitted",
xlab = "Fitted Values",
ylab = "Residuals")
abline(h = 0)

plot(fitted(model4), rstudent(model4),
main = "Studentized Residuals vs Fitted",
xlab = "Fitted Values",
ylab = "Studentized Residuals")
abline(h = 0)
abline(h = c(-2, 2), lty = 2)

plot(hatvalues(model4),
main = "Leverage Values",
ylab = "Leverage",
xlab = "Observation")
abline(h = 2*mean(hatvalues(model4)), lty = 2)

plot(cooks.distance(model4),
type = "h",
main = "Cook's Distance",
ylab = "Cook's Distance",
xlab = "Observation")
abline(h = 4/length(cooks.distance(model4)), lty = 2)

#olsrr plots and more
#correlation cant correlate character variables, take out
# Add diagnostic values to your dataset
my_team_diag = my_team %>%
mutate(
residuals = resid(model1),
student_resid = rstudent(model1),
leverage = hatvalues(model1),
cooks = cooks.distance(model1)
)
# Get sample size and number of predictors
n <- nrow(my_team_diag)
k <- length(coef(model1)) - 1
# 1. Outliers (studentized residuals)
outliers <- my_team_diag %>%
filter(abs(student_resid) > 2) %>%
select(game_date, opponent_team_slug, student_resid)
# 2. High leverage points
high_leverage <- my_team_diag %>%
filter(leverage > 2 * (k + 1) / n) %>%
select(game_date, opponent_team_slug, leverage)
# 3. Influential points (Cook's Distance)
influential <- my_team_diag %>%
filter(cooks > 4 / n) %>%
select(game_date, opponent_team_slug, cooks)
# View outliers, high leverage, influential points for analysis
outliers
high_leverage
influential
Prediction
The median values of each predictor variable were computed and used
to estimate the team score for a “median” game using Model 4.
All median values fall within the experimental region and are
therefore reliable.
I built the model to predict my teams points for a game in which they
achieve the median value for each variable. The predicted score is
81.6448743, with 95% confidence interval (79.5058191,83.7839294)
LS0tDQp0aXRsZTogIklTUCBTdGF0aXN0aWNhbCBBbmFseXNpcyBSZXBvcnQiDQphdXRob3I6ICJEaXZhbiBkdSBUb2l0Ig0KZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJUIgJWQsICVZJylgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICB0aGVtZTogbHVtZW4NCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ193aWR0aDogMw0KICAgIGZpZ19oZWlnaHQ6IDMNCiAgd29yZF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAga2VlcF9tZDogeWVzDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9DQojVE9DOjpiZWZvcmUgew0KICBjb250ZW50OiAiVGFibGUgb2YgQ29udGVudHMiOw0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1zaXplOiAxLjJlbTsNCiAgZGlzcGxheTogYmxvY2s7DQogIGNvbG9yOiBuYXZ5Ow0KICBtYXJnaW4tYm90dG9tOiAxMHB4Ow0KfQ0KDQoNCmRpdiNUT0MgbGkgeyAgICAgLyogdGFibGUgb2YgY29udGVudCAgKi8NCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOw0KICAgIGJhY2tncm91bmQtaW1hZ2U6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXJlcGVhdDpub25lOw0KICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsNCn0NCg0KaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8NCiAgZm9udC1zaXplOiAyMnB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOw0KfQ0KDQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE1cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogc3lzdGVtLXVpOw0KICBjb2xvcjogbmF2eTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDEgeyAvKiBIZWFkZXIgMSAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMjBweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMiB7IC8qIEhlYWRlciAyIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE2cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KLyogQWRkIGRvdHMgYWZ0ZXIgbnVtYmVyZWQgaGVhZGVycyAqLw0KLmhlYWRlci1zZWN0aW9uLW51bWJlcjo6YWZ0ZXIgew0KICBjb250ZW50OiAiLiI7DQoNCmJvZHkgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9DQoNCi5oaWdobGlnaHRtZSB7IGJhY2tncm91bmQtY29sb3I6eWVsbG93OyB9DQoNCnAgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9DQoNCn0NCmBgYA0KDQojSW50cm9kdWN0aW9uDQpUaGlzIHByb2plY3QgYW5hbHl6ZXMgV05CQSAyMDI1IGJveCBzY29yZSBkYXRhIHdpdGggdGhlIGdvYWwgb2YgYnVpbGRpbmcgYSByZWdyZXNzaW9uIG1vZGVsIHRvIHByZWRpY3QgdGVhbSBzY29yZSBmb3IgdGhlIHRlYW0gTWVyY3VyeS4gVGhlIHZhcmlhYmxlcyBvZiBpbnRlcmVzdCBpbmNsdWRlIGZpZWxkIGdvYWwgcGVyY2VudGFnZSwgdG90YWwgcmVib3VuZHMsIHRocmVlLXBvaW50IGZpZWxkIGdvYWwgcGVyY2VudGFnZSwgYW5kIHN0ZWFscy4gDQoNCkFmdGVyIGZpbmRpbmcgdGhlIGJlc3QgcHJlZGljdGl2ZSBtb2RlbCwgd2Ugd2lsbCB1c2UgaXQgdG8gZXN0aW1hdGUgdGVhbSBzY29yZSBmb3IgYSDigJxtZWRpYW7igJ0gZ2FtZSBmb3IgdGVhbSBNZXJjdXJ5IHdoZXJlIGFsbCB2YXJpYWJsZXMgYXJlIHNldCB0byB0aGVpciBtZWRpYW4gdmFsdWVzLg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GfQ0Kc2V0d2QoIkM6L1VzZXJzL0RpdmFuL0Rvd25sb2Fkcy9QZXJzb25hbCBGb2xkZXJzL1NwcmluZyAyMDI2L1NUQTMxOS0gQXBwbGllZCBTdGF0aXN0aWNzL1NUQTMxOSBQcm9qZWN0IEZpbGUiKQ0KDQpkYXRhPXJlYWQuY3N2KCJXTkJBXzIwMjVfYm94LXNjb3Jlcy5jc3YiLCBoZWFkZXI9VCkNCg0KbGlicmFyeShnZ3Bsb3QyKQ0KI2hpc3RvZ3JhbSBtYWRlIHVzaW5nIGdncGxvdDINCmxpYnJhcnkoY2FyKQ0KI1ZJRiBmdW5jdGlvbiBpbiB0aGUgY2FyIHBhY2thZ2UNCmxpYnJhcnkoZHBseXIpDQojc2VsZWN0IGZ1bmN0aW9uIGluIGRwbHlyDQpsaWJyYXJ5KG9sc3JyKQ0KI2NoZWNraW5nIGZvciB2aWYgYW5kIG1vZGVsIGFzc3VtcHRpb25zDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQojd2VsbCBmb3JtYXR0ZWQgZ3JhcGhzIGluIGthYmxlRXh0cmENCg0KYGBgDQoNCg0KDQpgYGB7ciB3cmFuZ2luZywgaW5jbHVkZT1GfQ0Kc3VtbWFyeShkYXRhKQ0KDQojQWxsIFdOQkEgdGVhbXMgaW5jbHVkZWQsIHJlbW92ZSBzY29yZXMgZnJvbSBBbGwgc3RhciBnYW1lDQpkYXRhID0gZGF0YSAlPiUgDQogIGZpbHRlcih0ZWFtX25hbWUgIT0gIlRlYW0gV05CQSIgJiB0ZWFtX25hbWUgIT0gIlRlYW0gVVNBIikNCg0KI0dyb3VwIGRhdGEgYnkgdGVhbSwgZmluZCBtZWFuIGFuZCBTVEQgb2YgYWxsIHZhcmlhYmxlDQpzdW1tYXJ5ID0gZGF0YSAlPiUNCiAgZ3JvdXBfYnkodGVhbV9uYW1lKSAlPiUNCiAgc3VtbWFyaXNlKG1lYW5fc2NvcmU9bWVhbih0ZWFtX3Njb3JlKSwgc2Rfc2NvcmU9c2QodGVhbV9zY29yZSksDQogICAgICAgICAgICBtZWFuX2ZnX3BjdD1tZWFuKGZpZWxkX2dvYWxfcGN0KSwgc2RfZmdfcGN0PXNkKGZpZWxkX2dvYWxfcGN0KSwNCiAgICAgICAgICAgIG1lYW5fcmJkcz1tZWFuKHRvdGFsX3JlYm91bmRzKSwgc2RfcmJkcz1zZCh0b3RhbF9yZWJvdW5kcyksDQogICAgICAgICAgICBtZWFuXzNwdF9wY3Q9bWVhbih0aHJlZV9wb2ludF9maWVsZF9nb2FsX3BjdCksIA0KICAgICAgICAgICAgc2RfM3B0X3BjdD1zZCh0aHJlZV9wb2ludF9maWVsZF9nb2FsX3BjdCksDQogICAgICAgICAgICBtZWFuX3N0ZWFscz1tZWFuKHN0ZWFscyksIHNkX3N0ZWFscz1zZChzdGVhbHMpKQ0KICANCiNTZWxlY3Qgb25seSB2YXJpYWJsZXMgd2UgbmVlZCBhbmQgZmlsdGVyIG9uIG15IHRlYW0NCg0KbXlfdGVhbSA9IGRhdGEgJT4lDQogICAgbXV0YXRlKHJlc3VsdCA9IGNhc2Vfd2hlbih0ZWFtX3dpbm5lciA9PSBUUlVFIH4gIldpbiIsdGVhbV93aW5uZXIgPT0gRkFMU0UgfiAiTG9zcyIpKSAlPiUNCiAgZmlsdGVyKHRlYW1fbmFtZSA9PSAiTWVyY3VyeSIpICU+JQ0KICBzZWxlY3QodGVhbV9uYW1lLCB0ZWFtX3Njb3JlLCBmaWVsZF9nb2FsX3BjdCwgdG90YWxfcmVib3VuZHMsDQogICAgICAgICB0aHJlZV9wb2ludF9maWVsZF9nb2FsX3BjdCwgc3RlYWxzLCB0ZWFtX3dpbm5lciwgZ2FtZV9kYXRlLA0KICAgICAgICAgb3Bwb25lbnRfdGVhbV9zbHVnLCByZXN1bHQpDQogIA0KICANCg0KDQojU3VtbWFyaXNlIGFsbCB2YXJpYWJsZXMgd2l0aCBtZWFuIGFuZCBzZA0KcmVzdWx0ID0gbXlfdGVhbSAlPiUNCiAgZ3JvdXBfYnkocmVzdWx0KSAlPiUNCiAgc3VtbWFyaXNlKG1lYW5fc2NvcmU9bWVhbih0ZWFtX3Njb3JlKSwgc2Rfc2NvcmU9c2QodGVhbV9zY29yZSksDQogICAgICAgICAgICBtZWFuX2ZnX3BjdD1tZWFuKGZpZWxkX2dvYWxfcGN0KSwgc2RfZmdfcGN0PXNkKGZpZWxkX2dvYWxfcGN0KSwNCiAgICAgICAgICAgIG1lYW5fcmJkcz1tZWFuKHRvdGFsX3JlYm91bmRzKSwgc2RfcmJkcz1zZCh0b3RhbF9yZWJvdW5kcyksDQogICAgICAgICAgICBtZWFuXzNwdF9wY3Q9bWVhbih0aHJlZV9wb2ludF9maWVsZF9nb2FsX3BjdCksIA0KICAgICAgICAgICAgc2RfM3B0X3BjdD1zZCh0aHJlZV9wb2ludF9maWVsZF9nb2FsX3BjdCksDQogICAgICAgICAgICBtZWFuX3N0ZWFscz1tZWFuKHN0ZWFscyksIHNkX3N0ZWFscz1zZChzdGVhbHMpKQ0KDQoNCg0KYGBgDQoNCiMgRGF0YQ0KDQpUaGUgZGF0YSBzZXQgd2FzIGZpcnN0IGNsZWFuZWQgYnkgcmVtb3Zpbmcgbm9uLXJlcHJlc2VudGF0aXZlIGRhdGEgaW5jbHVkaW5nIHRoZSBBbGwtU3RhciB0ZWFtIGFuZCB0ZWFtIFVTQS4gVGhlIGRhdGEgd2FzIHRoZW4gZ3JvdXBlZCBieSB0ZWFtIHRvIGZpbmQgdGhlIG1lYW5zIGFuZCBzdGFuZGFyZCBkZXZpYXRpb25zIG9mIHRoZSB2YXJpYWJsZXMgYmVpbmcgb2JzZXJ2ZWQuDQpBIHN1YnNldCBvZiB0aGUgZGF0YSB3YXMgY3JlYXRlZCBmb3IgdGhlIE1lcmN1cnkgdGVhbSB3aGljaCB3YXMgZ3JvdXBlZCBieSBnYW1lIG91dGNvbWUgKHdpbi9sb3NzKSB0byBjb21wYXJlIHBlcmZvcm1hbmNlIGRpZmZlcmVuY2VzIGJldHdlZW4gd2lucyBhbmQgbG9zc2VzLg0KDQpUaGUgbGVhZ3VlLXdpZGUgc3VtbWFyeSB0YWJsZSBwcm92aWRlcyBjb250ZXh0IGZvciBvdmVyYWxsIHBlcmZvcm1hbmNlLCB3aGlsZSB0aGUgdGVhbS1zcGVjaWZpYyB0YWJsZSBoaWdobGlnaHRzIGhvdyB0ZWFtIE1lcmN1cnkgZGlmZmVycyBmcm9tIHRoZSBsZWFndWUuDQoNCmBgYHtyIFRhYmxlc30NCg0Kc3VtbWFyeSAlPiUNCiAga2JsKGRpZ2l0cz0yLGNhcHRpb24gPSAiV05CQSAyMDI1IFN0YXRzIikgJT4lDQogIGthYmxlX2NsYXNzaWMoZnVsbF93aWR0aCA9IEYsIGh0bWxfZm9udCA9ICJDYW1icmlhIikNCiNUYWJsZSBmb3IgZW50aXJlIFdOQkEgTGVhZ3VlDQoNCnJlc3VsdCAlPiUNCiAga2JsKGRpZ2l0cz0yLGNhcHRpb24gPSAiV05CQSAyMDI1IE1lcmN1cnkgU3RhdHMiKSAlPiUNCiAga2FibGVfY2xhc3NpYyhmdWxsX3dpZHRoID0gRiwgaHRtbF9mb250ID0gIkNhbWJyaWEiKQ0KDQojVGFibGUgZm9yIG15IFdOQkEgdGVhbS4NCg0KYGBgDQoNCiMgQm94IFBsb3QNCg0KVGhlIGZvbGxvd2luZyBib3ggcGxvdCB3YXMgY3JlYXRlZCB0byBjb21wYXJlIHRoZSBkaXN0cmlidXRpb24gb2YgdGVhbSBzY29yZXMgYmV0d2VlbiB3aW5zIGFuZCBsb3NzZXMuIFRoZSBkaXN0cmlidXRpb25zIHNob3cgdGhhdCBoaWdoZXIgc2NvcmVzIGFyZSBnZW5lcmFsbHkgYXNzb2NpYXRlZCB3aXRoIHdpbnMsIHdoaWxlIGxvd2VyIHNjb3JlcyBhcmUgbW9yZSBjb21tb24gaW4gbG9zc2VzLiBUaGlzIHN1Z2dlc3RzIHRoYXQgdGVhbXMgd2l0aCBoaWdoZXIgc2NvcmluZyBjYXBhYmlsaXRpZXMgd2lsbCBoYXZlIGhpZ2hlciB3aW4gcmF0ZXMuIA0KDQpgYGB7ciBHcmFwaHMsIEluY2x1ZGU9VCwgZmlnLndpZHRoPTUgLCBmaWcuaGVpZ2h0PTV9DQoNCnAgPSBteV90ZWFtICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB0ZWFtX3Njb3JlLCBmaWxsID0gcmVzdWx0KSkgKw0KICBnZW9tX2hpc3RvZ3JhbShjb2xvciA9ICIjZTllY2VmIiwgYWxwaGEgPSAwLjYsIHBvc2l0aW9uID0gImlkZW50aXR5IiwgYmlud2lkdGggPSA0KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiM2OWIzYTIiLCAiIzQwNDA4MCIpKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFRlYW0gU2NvcmVzIiwNCiAgICBmaWxsID0gIiIpDQoNCmJveHBsb3QodGVhbV9zY29yZSB+IHJlc3VsdCwgZGF0YSA9IG15X3RlYW0sIG5vdGNoID0gRkFMU0UsDQogICAgICAgIGNvbCA9IGMoJ2xpZ2h0Ymx1ZScsJ2xpZ2h0Z3JlZW4nKSwNCiAgICAgICAgbWFpbiA9ICJQb2ludHMgU2NvcmVkIGJ5IEdhbWUgUmVzdWx0IiwNCiAgICAgICAgeGxhYiA9ICJyZXN1bHQiLCB5bGFiID0gIlBvaW50cyIpDQoNCmBgYA0KDQojIEZpcnN0IE9yZGVyIE1vZGVscw0KDQpBIGZpcnN0LW9yZGVyIG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIChNb2RlbCAxKSB3YXMgY29uc3RydWN0ZWQgdXNpbmcgZmllbGQgZ29hbCBwZXJjZW50YWdlLCB0b3RhbCByZWJvdW5kcywgdGhyZWUtcG9pbnQgZmllbGQgZ29hbCBwZXJjZW50YWdlLCBhbmQgc3RlYWxzIGFzIHByZWRpY3RvcnMgb2YgdGVhbSBzY29yZS4NCg0KQ29ycmVsYXRpb24gY29lZmZpY2llbnRzIGFuZCBWYXJpYW5jZSBJbmZsYXRpb24gRmFjdG9yIChWSUYpIHZhbHVlcyB3ZXJlIHVzZWQgdG8gZGV0ZXJtaW5lIGlmIHRoZXJlIHdhcyBhbnkgbXVsdGljb2xsaW5lYXJpdHkgaW4gdGhlIHZhcmlhYmxlcy4gU2luY2Ugbm8gcGFpcnMgb2YgdmFyaWFibGVzIGV4aGliaXRlZCBleHRyZW1lbHkgaGlnaCBjb3JyZWxhdGlvbiAofHJ8ID4gMC44KSBhbmQgVklGIHZhbHVlcyB3ZXJlIHdpdGhpbiBhY2NlcHRhYmxlIGxpbWl0cywgbm8gdmFyaWFibGVzIHdlcmUgcmVtb3ZlZC4gQXMgYSByZXN1bHQsIE1vZGVsIDIgcmVtYWluZWQgdGhlIHNhbWUgYXMgTW9kZWwgMS4NCg0KYGBge3IgRmlyc3QgT3JkZXIgTW9kZWwsIHJlc3VsdHMgPSAnaGlkZScsIElubGN1ZGU9Rn0NCg0KDQptb2RlbDEgPSBsbSh0ZWFtX3Njb3JlfmZpZWxkX2dvYWxfcGN0K3RvdGFsX3JlYm91bmRzKw0KICAgICAgICAgICAgdGhyZWVfcG9pbnRfZmllbGRfZ29hbF9wY3Qrc3RlYWxzLCBkYXRhID0gbXlfdGVhbSkNCg0KY29yX2RhdGEgPSBteV90ZWFtICU+JQ0KICBzZWxlY3QodGVhbV9zY29yZSwgZmllbGRfZ29hbF9wY3QsIHRvdGFsX3JlYm91bmRzLCANCiAgICAgICAgIHRocmVlX3BvaW50X2ZpZWxkX2dvYWxfcGN0LCBzdGVhbHMpDQoNCmNvcihjb3JfZGF0YSkNCg0KdmlmKG1vZGVsMSkNCg0KbW9kZWwyID0gbG0odGVhbV9zY29yZX5maWVsZF9nb2FsX3BjdCt0b3RhbF9yZWJvdW5kcysNCiAgICAgICAgICAgIHRocmVlX3BvaW50X2ZpZWxkX2dvYWxfcGN0K3N0ZWFscywgZGF0YSA9IG15X3RlYW0pDQoNCmBgYA0KDQojIEludGVyYWN0aW9uIE1vZGVsDQoNCkEgZnVsbCBpbnRlcmFjdGlvbiBtb2RlbCAoTW9kZWwgMykgd2FzIGNvbnN0cnVjdGVkIGluY2x1ZGluZyBhbGwgaW50ZXJhY3Rpb24gdGVybXMuIEVhY2ggaW50ZXJhY3Rpb24gdGVybSB3YXMgZXZhbHVhdGVkIGF0IHRoZSAxNSUgc2lnbmlmaWNhbmNlIGxldmVsLg0KDQpPbmx5IHRoZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIGZpZWxkIGdvYWwgcGVyY2VudGFnZSBhbmQgdGhyZWUtcG9pbnQgZmllbGQgZ29hbCBwZXJjZW50YWdlIHdhcyBmb3VuZCB0byBiZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LiBBbGwgb3RoZXIgaW50ZXJhY3Rpb24gdGVybXMgd2VyZSByZW1vdmVkLCByZXN1bHRpbmcgaW4gdGhlIHJlZHVjZWQgaW50ZXJhY3Rpb24gbW9kZWwgKE1vZGVsIDQpLCB3aGljaCByZXRhaW5zIGFsbCB2YXJpYWJsZXMgYW5kIHRoZSBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiB0ZXJtLg0KDQpgYGB7ciBJbnRlcmFjdGlvbiBNb2RlbCwgcmVzdWx0cz0nYXNpcycsIEluY2x1ZGU9RiwgbWVzc2FnZT1GfQ0KDQptb2RlbDMgPSBsbSh0ZWFtX3Njb3JlIH4gKGZpZWxkX2dvYWxfcGN0ICsgdG90YWxfcmVib3VuZHMgKyANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocmVlX3BvaW50X2ZpZWxkX2dvYWxfcGN0ICsgc3RlYWxzKV4yLCANCiAgICAgICAgICAgICAgICAgZGF0YSA9IG15X3RlYW0pDQoNCm1vZGVsNCA9IGxtKHRlYW1fc2NvcmUgfiBmaWVsZF9nb2FsX3BjdCArIHRvdGFsX3JlYm91bmRzICsgDQogICAgICAgICAgICAgICAgICAgIHRocmVlX3BvaW50X2ZpZWxkX2dvYWxfcGN0ICsgc3RlYWxzICsNCiAgICAgICAgICAgICAgICAgICAgZmllbGRfZ29hbF9wY3Q6dGhyZWVfcG9pbnRfZmllbGRfZ29hbF9wY3QsDQogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBteV90ZWFtKQ0KDQptb2RlbDRzdW0gPSBzdW1tYXJ5KG1vZGVsNCkNCg0KbGlicmFyeShzdGFyZ2F6ZXIpDQpzdGFyZ2F6ZXIobW9kZWw0LCB0eXBlPSJodG1sIikNCg0KYGBgDQoNCiR+JA0KJH4kDQoNCkFmdGVyIGFsbCBtb2RlbHMgd2VyZSBydW4gYW5kIGEgcmVkdWN0aW9uIGNvbXBsZXRlZCwgbXkgbW9kZWwgaXMgIA0KdGVhbV9zY29yZT0gYHIgbW9kZWw0JGNvZWZmaWNpZW50c1sxXWAgKyBgciBtb2RlbDQkY29lZmZpY2llbnRzWzJdYCAqIGZpZWxkX2dvYWxfcGN0ICArIA0KYHIgbW9kZWw0JGNvZWZmaWNpZW50c1szXWAgKiB0b3RhbF9yZWJvdW5kcyArIGByIG1vZGVsNCRjb2VmZmljaWVudHNbNF1gICogdGhyZWVfcG9pbnRfZmllbGRfZ29hbF9wY3QgKyBgciBtb2RlbDQkY29lZmZpY2llbnRzWzVdYCAqIHN0ZWFscyArIGByIG1vZGVsNCRjb2VmZmljaWVudHNbNl1gICogZmllbGRfZ29hbF9wY3Q6dGhyZWVfcG9pbnRfZmllbGRfZ29hbF9wY3QNCg0KVGhpcyBtb2RlbCBzaWduaWZpY2FudGx5IHByZWRpY3RzIHRlYW0gc2NvcmUsIEYoYHIgbW9kZWw0c3VtJGZzdGF0aXN0aWNbMl1gLGByIG1vZGVsNHN1bSRmc3RhdGlzdGljWzNdYCkgPSBgciBtb2RlbDRzdW0kZnN0YXRpc3RpY1sxXWAsIHA8LjAwMDEsIGFkanVzdGVkIFJeMj0gYHIgbW9kZWw0c3VtJGFkai5yLnNxdWFyZWRgDQoNCiMgUmVzaWR1YWwgQW5hbHlzaXMNCg0KUmVzaWR1YWwgYW5hbHlzaXMgd2FzIGNvbmR1Y3RlZCB0byBldmFsdWF0ZSB0aGUgYXNzdW1wdGlvbnMgb2YgdGhlIHJlZ3Jlc3Npb24gbW9kZWwuIA0KDQpUaGUgaGlzdG9ncmFtIG9mIHJlc2lkdWFscyBpbmRpY2F0ZXMgdGhhdCB0aGUgcmVzaWR1YWxzIHNsaWdodGx5IHNrZXduIHRvIHRoZSByaWdodCBidXQgYXJlIGFwcHJveGltYXRlbHkgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIFRoZSByZXNpZHVhbHMgdmVyc3VzIGZpdHRlZCBwbG90IHNob3dzIG5vIGNsZWFyIHBhdHRlcm4gYW5kIGEgY29uc2lzdGVudCBzcHJlYWQsIHN1Z2dlc3RpbmcgdGhhdCB0aGUgYXNzdW1wdGlvbiBvZiBsaW5lYXJpdHkgYW5kIGNvbnN0YW50IHZhcmlhbmNlIGlzIHJlYXNvbmFibGUuDQoNClRoZSBzdHVkZW50aXplZCByZXNpZHVhbCBwbG90IHdhcyB1c2VkIHRvIGlkZW50aWZ5IHBvdGVudGlhbCBvdXRsaWVycywgd2l0aCBhIG1ham9yaXR5IG9mIG9ic2VydmF0aW9ucyBmYWxsaW5nIHdpdGhpbiBhY2NlcHRhYmxlIGJvdW5kcy4gVGhlIHBvaW50cyB0aGF0IGZlbGwgb3V0IG9mIGJvdW5kcyBhcmUgdGhlIDIwMjQtMDgtMTUgZ2FtZSBhZ2FpbnN0IGNoaWNhZ28tc2t5IGFuZCB0aGUgMjAyNC0wNi0wOSBnYW1lIGFnYWluc3QJZGFsbGFzLXdpbmdzLg0KDQpUaGUgbGV2ZXJhZ2UgcGxvdCBpbmRpY2F0ZXMgdGhhdCB0d28gb2JzZXJ2YXRpb25zIGhhdmUgcmVsYXRpdmVseSBoaWdoIGxldmVyYWdlLCBzdWdnZXN0aW5nIHRoZXkgZmFsbCBvdXRzaWRlIHRoZSBub3JtYWwgcmFuZ2Ugb2YgdGhlIGRhdGEuIFRoZXNlIHBvaW50cyBjb3VsZCBpbmZsdWVuY2UgdGhlIHJlZ3Jlc3Npb24gbW9kZWwgYW5kIGFyZSBub3RhYmxlLiBUaGUgcG9pbnRzIHdpdGggaGlnaCBsZXZlcmFnZSBhcmUgdGhlIDIwMjQtMDctMDEJZ2FtZSBhZ2FpbnN0IGNvbm5lY3RpY3V0LXN1biwgdGhlIDIwMjQtMDYtMDIJZ2FtZSBhZ2FpbnN0IGxvcy1hbmdlbGVzLXNwYXJrcywgYW5kIHRoZSAyMDI0LTA1LTI4CWdhbWUgYWdhaW5zdCBjb25uZWN0aWN1dC1zdW4uDQoNClRoZSBDb29r4oCZcyBkaXN0YW5jZSBwbG90IGlkZW50aWZpZXMgdHdvIG9ic2VydmF0aW9ucyB3aXRoIHJlbGF0aXZlbHkgaGlnaCBpbmZsdWVuY2UuIFRoZXNlIHBvaW50cyBoYXZlIGEgbm90YWJsZSBpbXBhY3Qgb24gdGhlIGZpdHRlZCByZWdyZXNzaW9uIG1vZGVsIGFuZCBtYXkgZGlzcHJvcG9ydGlvbmF0ZWx5IGFmZmVjdCB0aGUgZXN0aW1hdGVkIGNvZWZmaWNpZW50cy4gVGhlIHBvaW50cyB3aXRoIGhpZ2ggaW1wYWN0IGluY2x1ZGUgMjAyNC0wOC0xNSBnYW1lIGFnYWluc3QJY2hpY2Fnby1za3kgYW5kIDIwMjQtMDUtMjUgZ2FtZSBhZ2FpbnN0IGRhbGxhcy13aW5ncy4gRGVzcGl0ZSB0aGUgcHJlc2VuY2Ugb2YgdGhlc2UgaW5mbHVlbnRpYWwgYW5kIGhpZ2gtbGV2ZXJhZ2UgcG9pbnRzLCB0aGVpciBzbWFsbCBudW1iZXIgbWVhbnMgdGhleSBkbyBub3Qgc3Vic3RhbnRpYWxseSBkaXN0b3J0IHRoZSBvdmVyYWxsIG1vZGVsLg0KDQpgYGB7ciBSZXNpZHVhbHMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2hpZGUnLGZpZy53aWR0aD01LGZpZy5oZWlnaHQ9NX0NCg0KaGlzdChyZXNpZHVhbHMobW9kZWw0KSwNCiAgICAgbWFpbiA9ICJIaXN0b2dyYW0gb2YgUmVzaWR1YWxzIiwNCiAgICAgeGxhYiA9ICJSZXNpZHVhbHMiKQ0KDQpwbG90KGZpdHRlZChtb2RlbDQpLCByZXNpZHVhbHMobW9kZWw0KSwNCiAgICAgbWFpbiA9ICJSZXNpZHVhbHMgdnMgRml0dGVkIiwNCiAgICAgeGxhYiA9ICJGaXR0ZWQgVmFsdWVzIiwNCiAgICAgeWxhYiA9ICJSZXNpZHVhbHMiKQ0KYWJsaW5lKGggPSAwKQ0KcGxvdChmaXR0ZWQobW9kZWw0KSwgcnN0dWRlbnQobW9kZWw0KSwNCiAgICAgbWFpbiA9ICJTdHVkZW50aXplZCBSZXNpZHVhbHMgdnMgRml0dGVkIiwNCiAgICAgeGxhYiA9ICJGaXR0ZWQgVmFsdWVzIiwNCiAgICAgeWxhYiA9ICJTdHVkZW50aXplZCBSZXNpZHVhbHMiKQ0KYWJsaW5lKGggPSAwKQ0KYWJsaW5lKGggPSBjKC0yLCAyKSwgbHR5ID0gMikNCnBsb3QoaGF0dmFsdWVzKG1vZGVsNCksDQogICAgIG1haW4gPSAiTGV2ZXJhZ2UgVmFsdWVzIiwNCiAgICAgeWxhYiA9ICJMZXZlcmFnZSIsDQogICAgIHhsYWIgPSAiT2JzZXJ2YXRpb24iKQ0KYWJsaW5lKGggPSAyKm1lYW4oaGF0dmFsdWVzKG1vZGVsNCkpLCBsdHkgPSAyKQ0KcGxvdChjb29rcy5kaXN0YW5jZShtb2RlbDQpLA0KICAgICB0eXBlID0gImgiLA0KICAgICBtYWluID0gIkNvb2sncyBEaXN0YW5jZSIsDQogICAgIHlsYWIgPSAiQ29vaydzIERpc3RhbmNlIiwNCiAgICAgeGxhYiA9ICJPYnNlcnZhdGlvbiIpDQphYmxpbmUoaCA9IDQvbGVuZ3RoKGNvb2tzLmRpc3RhbmNlKG1vZGVsNCkpLCBsdHkgPSAyKQ0KI29sc3JyIHBsb3RzIGFuZCBtb3JlDQojY29ycmVsYXRpb24gY2FudCBjb3JyZWxhdGUgY2hhcmFjdGVyIHZhcmlhYmxlcywgdGFrZSBvdXQgDQojIEFkZCBkaWFnbm9zdGljIHZhbHVlcyB0byB5b3VyIGRhdGFzZXQNCm15X3RlYW1fZGlhZyA9IG15X3RlYW0gJT4lDQogIG11dGF0ZSgNCiAgICByZXNpZHVhbHMgPSByZXNpZChtb2RlbDEpLA0KICAgIHN0dWRlbnRfcmVzaWQgPSByc3R1ZGVudChtb2RlbDEpLA0KICAgIGxldmVyYWdlID0gaGF0dmFsdWVzKG1vZGVsMSksDQogICAgY29va3MgPSBjb29rcy5kaXN0YW5jZShtb2RlbDEpDQogICkNCg0KIyBHZXQgc2FtcGxlIHNpemUgYW5kIG51bWJlciBvZiBwcmVkaWN0b3JzDQpuIDwtIG5yb3cobXlfdGVhbV9kaWFnKQ0KayA8LSBsZW5ndGgoY29lZihtb2RlbDEpKSAtIDENCg0KIyAxLiBPdXRsaWVycyAoc3R1ZGVudGl6ZWQgcmVzaWR1YWxzKQ0Kb3V0bGllcnMgPC0gbXlfdGVhbV9kaWFnICU+JQ0KICBmaWx0ZXIoYWJzKHN0dWRlbnRfcmVzaWQpID4gMikgJT4lDQogIHNlbGVjdChnYW1lX2RhdGUsIG9wcG9uZW50X3RlYW1fc2x1Zywgc3R1ZGVudF9yZXNpZCkNCg0KIyAyLiBIaWdoIGxldmVyYWdlIHBvaW50cw0KaGlnaF9sZXZlcmFnZSA8LSBteV90ZWFtX2RpYWcgJT4lDQogIGZpbHRlcihsZXZlcmFnZSA+IDIgKiAoayArIDEpIC8gbikgJT4lDQogIHNlbGVjdChnYW1lX2RhdGUsIG9wcG9uZW50X3RlYW1fc2x1ZywgbGV2ZXJhZ2UpDQoNCiMgMy4gSW5mbHVlbnRpYWwgcG9pbnRzIChDb29rJ3MgRGlzdGFuY2UpDQppbmZsdWVudGlhbCA8LSBteV90ZWFtX2RpYWcgJT4lDQogIGZpbHRlcihjb29rcyA+IDQgLyBuKSAlPiUNCiAgc2VsZWN0KGdhbWVfZGF0ZSwgb3Bwb25lbnRfdGVhbV9zbHVnLCBjb29rcykNCg0KIyBWaWV3IG91dGxpZXJzLCBoaWdoIGxldmVyYWdlLCBpbmZsdWVudGlhbCBwb2ludHMgZm9yIGFuYWx5c2lzDQpvdXRsaWVycw0KaGlnaF9sZXZlcmFnZQ0KaW5mbHVlbnRpYWwNCmBgYA0KDQojIFByZWRpY3Rpb24NCg0KVGhlIG1lZGlhbiB2YWx1ZXMgb2YgZWFjaCBwcmVkaWN0b3IgdmFyaWFibGUgd2VyZSBjb21wdXRlZCBhbmQgdXNlZCB0byBlc3RpbWF0ZSB0aGUgdGVhbSBzY29yZSBmb3IgYSDigJxtZWRpYW7igJ0gZ2FtZSB1c2luZyBNb2RlbCA0Lg0KDQpBbGwgbWVkaWFuIHZhbHVlcyBmYWxsIHdpdGhpbiB0aGUgZXhwZXJpbWVudGFsIHJlZ2lvbiBhbmQgYXJlIHRoZXJlZm9yZSByZWxpYWJsZS4NCg0KYGBge3IgUHJlZGljdGlvbixyZXN1bHRzID0gJ2hpZGUnLGluY2x1ZGU9Rn0NCg0KYXBwbHkobXlfdGVhbVssIGMoImZpZWxkX2dvYWxfcGN0IiwidG90YWxfcmVib3VuZHMiLA0KICAgICAgICAgICAgICAgICAgInRocmVlX3BvaW50X2ZpZWxkX2dvYWxfcGN0Iiwic3RlYWxzIildLA0KICAgICAgMiwgbWVkaWFuKQ0KDQpzdW1tYXJ5KG1vZGVsNCkNCg0KbmV3ZGF0YT1kYXRhLmZyYW1lKGZpZWxkX2dvYWxfcGN0PTQyLjk1LHRvdGFsX3JlYm91bmRzPTMzLA0KICAgICAgICAgICAgICAgICAgIHRocmVlX3BvaW50X2ZpZWxkX2dvYWxfcGN0PTMyLjcwLHN0ZWFscz03KQ0KDQpwcmVkaWN0aW9uPXByZWRpY3QobW9kZWw0LG5ld2RhdGEsIGludGVydmFsID0gImNvbmZpZGVuY2UiLCBsZXZlbD0uOTUpDQoNCmBgYA0KDQpJIGJ1aWx0IHRoZSBtb2RlbCB0byBwcmVkaWN0IG15IHRlYW1zIHBvaW50cyBmb3IgYSBnYW1lIGluIHdoaWNoIHRoZXkgYWNoaWV2ZSB0aGUgbWVkaWFuIHZhbHVlIGZvciBlYWNoIHZhcmlhYmxlLiBUaGUgcHJlZGljdGVkIHNjb3JlIGlzIGByIHByZWRpY3Rpb25bMV1gLCB3aXRoIDk1JSBjb25maWRlbmNlIGludGVydmFsIChgciBwcmVkaWN0aW9uWzJdYCxgciBwcmVkaWN0aW9uWzNdYCkg