1 Introduction
In today’s retail industry, direct mail marketing remains an
important channel for driving customer engagement and sales. However,
not all customers respond to promotional offers equally, and identifying
who is most likely to respond can help companies allocate resources more
efficiently.
This project uses the Clothing Store Dataset—a real dataset from a
New England retail chain—to develop a predictive model for customer
response behavior. The primary goal is to determine which customer
characteristics best predict whether an individual will respond (“yes”)
to a direct mail promotion.
To address this, we conduct exploratory data analysis (EDA) to
examine relationships among purchasing, engagement, and demographic
variables, then build a multiple logistic regression model to quantify
how these factors influence response likelihood. By identifying the most
meaningful predictors, this analysis provides actionable insight into
which types of customers are most receptive to future marketing
efforts.
3 Exploratory Data Analysis
To begin, we will make a correlation matrix with all of the numerical
variables to see if any variables are highly correlated with each
other.
# 1) Manually list the numeric variables you want
vars <- c("FRE","MON", "AVRG","GMP","PROMOS","DAYS","CLASSES","STYLES","STORES","HI","PERCRET")
# 2) Keep only the ones that actually exist in your data
vars <- intersect(vars, names(CSDS_clean))
# 3) Correlation matrix (errors if any are non-numeric)
cor_mat <- cor(CSDS_clean[ , vars, drop = FALSE],
use = "pairwise.complete.obs",
method = "pearson")
cor_mat
FRE MON AVRG GMP PROMOS
FRE 1.0000000 0.674209463 -0.152217058 -0.114920260 0.46902853
MON 0.6742095 1.000000000 0.271555910 0.038859950 0.38456147
AVRG -0.1522171 0.271555910 1.000000000 0.287400964 0.04592048
GMP -0.1149203 0.038859950 0.287400964 1.000000000 0.05949538
PROMOS 0.4690285 0.384561473 0.045920482 0.059495381 1.00000000
DAYS 0.3910812 0.261051031 -0.122708281 -0.021326578 0.60409827
CLASSES 0.7948576 0.675174039 0.087937020 -0.105308252 0.52413518
STYLES 0.7931651 0.935759837 0.135948828 -0.076199344 0.40263287
STORES 0.5909190 0.430123659 -0.088488953 -0.103484318 0.37306720
HI -0.4323462 -0.309591043 -0.002372335 0.150835861 -0.33013811
PERCRET 0.1559934 0.009115226 -0.180623484 -0.007074185 0.04475647
DAYS CLASSES STYLES STORES HI
FRE 0.39108118 0.79485761 0.79316506 0.59091903 -0.432346183
MON 0.26105103 0.67517404 0.93575984 0.43012366 -0.309591043
AVRG -0.12270828 0.08793702 0.13594883 -0.08848895 -0.002372335
GMP -0.02132658 -0.10530825 -0.07619934 -0.10348432 0.150835861
PROMOS 0.60409827 0.52413518 0.40263287 0.37306720 -0.330138107
DAYS 1.00000000 0.40606251 0.29344949 0.32782601 -0.277643174
CLASSES 0.40606251 1.00000000 0.75321727 0.60280152 -0.619839913
STYLES 0.29344949 0.75321727 1.00000000 0.51226171 -0.360716264
STORES 0.32782601 0.60280152 0.51226171 1.00000000 -0.414095001
HI -0.27764317 -0.61983991 -0.36071626 -0.41409500 1.000000000
PERCRET 0.03418407 0.10271670 0.06785920 0.09372079 -0.252625218
PERCRET
FRE 0.155993396
MON 0.009115226
AVRG -0.180623484
GMP -0.007074185
PROMOS 0.044756473
DAYS 0.034184072
CLASSES 0.102716699
STYLES 0.067859197
STORES 0.093720788
HI -0.252625218
PERCRET 1.000000000
Pairwise correlations reveal strong relationships among purchasing
activity variables. For example, FRE (visits) correlates highly with
STYLES (items purchased) and CLASSES (product classes), and MON (net
sales) correlates very strongly with STYLES. These patterns are
intuitive—customers who shop more often tend to buy more items across
more classes, leading to higher sales. We retain these variables
initially and address redundancy later during model refinement.
We will now conduct frequency distributions for all of the numerical
variables to identify any patterns and skewness.
par(mfrow=c(1,2))
hist(CSDS_clean$FRE, xlab="# of Purchase Visits", main = "")
hist(CSDS_clean$MON, xlab="Total Net Sales", main = "")

hist(CSDS_clean$AVRG, xlab="Average Spend Per Visit", main = "")
hist(CSDS_clean$GMP, xlab="Gross Margin %", main = "")

hist(CSDS_clean$PROMOS, xlab="# of Marketing Promos", main = "")
hist(CSDS_clean$DAYS, xlab="Days on File", main = "")

hist(CSDS_clean$CLASSES, xlab="# of Different Products Purchased", main = "")
hist(CSDS_clean$STYLES, xlab="# of Individual Items Purchased", main = "")

hist(CSDS_clean$STORES, xlab="# of Stores Shopped At", main = "")
hist(CSDS_clean$HI, xlab="Product Uniformity", main = "")

hist(CSDS_clean$PERCRET, xlab="% of Returns", main = "")

None of our variables are distributed normally. Number of purchase
visits, Total Net Sales, Average Spend Per Visit, Number of Marketing
Promos, Number of Different Products Purchased, Number of Individual
Items Purchased, Number of Stores Shopped At, Product Uniformity, and
Percent of Returns are all skewed to the right. Gross Margin Percentage
and Days on File are skewed left. We will apply appropriate
transformations prior to modeling.
4 Multiple Logistic Regression Model
Before building our multiple logistic regression model, we need to
address the high levels of skewness observed in many of our numerical
predictors. Variables such as Total Net Sales (MON), Number of Purchase
Visits (FRE), Number of Individual Items Purchased (STYLES), and Percent
of Returns (PERCRET) were found to be strongly right-skewed, while Gross
Margin Percentage (GMP) showed moderate left skew. To ensure more stable
coefficient estimates and improve linearity with the log-odds of the
response variable, we apply several transformations. Right-skewed,
strictly positive variables are transformed using the log1p() function,
which safely handles zeros and reduces the influence of large outliers.
The percentage variable PERCRET is first converted to a proportion and
then transformed using the logit (qlogis()) function, allowing it to
vary smoothly on the real number line. We also drop Average Spend per
Visit (AVRG) due to redundancy with MON and FRE, which helps minimize
multicollinearity. The resulting dataset provides a more balanced
distribution of predictors and creates a stronger foundation for
modeling customer response probabilities.
dat <- CSDS_clean %>%
# ensure RESP is a proper factor first
dplyr::mutate(
RESP = case_when(
RESP %in% c("Yes","yes",1) ~ "yes",
RESP %in% c("No","no",0) ~ "no",
TRUE ~ NA_character_
),
RESP = factor(RESP, levels = c("no","yes"))
) %>%
# transforms
dplyr::mutate(
PERCRET_p = pmin(pmax(PERCRET/100, 1e-6), 1 - 1e-6),
PERCRET_logit = qlogis(PERCRET_p),
dplyr::across(
tidyselect::any_of(c("MON","FRE","STYLES","CLASSES","STORES","HI")),
~ log1p(.),
.names = "{.col}_log"
)
) %>%
# select ONLY with fully-qualified dplyr
dplyr::select(dplyr::all_of(
c("RESP","MON_log","FRE_log","STYLES_log","CLASSES_log","STORES_log",
"HI_log","PERCRET_logit","PROMOS","DAYS","GMP")
)) %>%
tidyr::drop_na()
Here we fit the multiple logistic regression model predicting RESP
(yes/no) using the transformed predictors from Section 4.1. The
specification includes log-transformed behavioral measures (e.g.,
MON_log, FRE_log, STYLES_log, CLASSES_log, STORES_log, HI_log), the
logit-transformed return rate (PERCRET_logit), and untransformed
controls (PROMOS, DAYS, GMP). This model estimates how each feature is
associated with the log-odds of responding while mitigating skew and
multicollinearity. We report coefficient summaries and odds ratios to
aid interpretation.
# Ensure RESP exists and is a factor with correct levels
dat$RESP <- factor(dat$RESP, levels = c("no", "yes"))
# Check that it worked
table(dat$RESP)
no yes
2231 388
4.1 Larger Model
We first fit a larger model, including MON_log, FRE_log, STYLES_log,
CLASSES_log, STORES_log, HI_log, PERCRET_logit, PROMOS, DAYS, and
GMP.
fit <- glm(RESP ~ MON_log + FRE_log + STYLES_log + CLASSES_log + STORES_log +
HI_log + PERCRET_logit + PROMOS + DAYS + GMP,
data = dat, family = binomial)
summary(fit)
Call:
glm(formula = RESP ~ MON_log + FRE_log + STYLES_log + CLASSES_log +
STORES_log + HI_log + PERCRET_logit + PROMOS + DAYS + GMP,
family = binomial, data = dat)
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -3.6743606 0.8398896 -4.375 1.22e-05 ***
MON_log 0.1250662 0.2160837 0.579 0.5627
FRE_log 1.2066864 0.2003772 6.022 1.72e-09 ***
STYLES_log 0.4930412 0.2729314 1.806 0.0708 .
CLASSES_log -0.5104403 0.3201110 -1.595 0.1108
STORES_log 0.1785903 0.1983969 0.900 0.3680
HI_log -0.2125468 0.1905018 -1.116 0.2645
PERCRET_logit -0.0176444 0.0237950 -0.742 0.4584
PROMOS -0.0250798 0.0124755 -2.010 0.0444 *
DAYS -0.0004144 0.0004243 -0.977 0.3287
GMP -0.6865513 0.4597422 -1.493 0.1353
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 2197.3 on 2618 degrees of freedom
Residual deviance: 1791.3 on 2608 degrees of freedom
AIC: 1813.3
Number of Fisher Scoring iterations: 5
The logistic regression model predicts the likelihood that a customer
responds (RESP = yes) to a marketing promotion based on purchasing and
engagement variables. The negative intercept (–3.67, p < .001)
suggests a low baseline probability of response.
The number of purchase visits (FRE_log) is the strongest and most
significant predictor (β = 1.21, p < .001), meaning customers who
shop more frequently are much more likely to respond. A one-unit
increase in log-transformed purchase visits multiplies the odds of
responding by about 3.35 times.
Number of items purchased (STYLES_log) shows a weak positive effect
(p = .07), while number of promotions (PROMOS) has a small negative
effect (β = –0.025, p = .04), suggesting that overexposure to promotions
slightly reduces responsiveness.
All other variables were not statistically significant, indicating
that frequent shoppers are the most reliable predictors of promotional
response.
Before shortening our model, let’s see if there is multicollinearity
within our predictor variables. We will run a VIF matrix.
MON_log FRE_log STYLES_log CLASSES_log STORES_log
12.263902 5.681323 16.487958 10.226876 1.557732
HI_log PERCRET_logit PROMOS DAYS GMP
3.822498 2.126597 2.151240 1.752150 1.656215
Variance inflation factors (VIF) indicate substantial
multicollinearity among purchase-activity variables: MON_log,
STYLES_log, and CLASSES_log are inflated (VIF > 10), and FRE_log is
moderately inflated. Because MON_log and CLASSES_log are also not
statistically significant, we remove them. We keep STYLES_log
temporarily to reassess its signal after reducing multicollinearity.
4.2 Reduced Model
Here is our improved, new fitted model:
# Fit the reduced model
fit2 <- glm(RESP ~ FRE_log + PROMOS + STYLES_log,
data = dat, family = binomial)
# Inspect results
summary(fit2)
Call:
glm(formula = RESP ~ FRE_log + PROMOS + STYLES_log, family = binomial,
data = dat)
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -4.51609 0.20694 -21.823 < 2e-16 ***
FRE_log 1.18762 0.17543 6.770 1.29e-11 ***
PROMOS -0.03314 0.01078 -3.074 0.00211 **
STYLES_log 0.43305 0.14092 3.073 0.00212 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 2197.3 on 2618 degrees of freedom
Residual deviance: 1797.9 on 2615 degrees of freedom
AIC: 1805.9
Number of Fisher Scoring iterations: 5
All predictors are statistically significant at the 0.01 level,
indicating that shopping frequency, purchase variety, and promotion
exposure meaningfully influence response likelihood.
FRE_log (β = 1.19, p < .001) → Customers who visit the store more
frequently are much more likely to respond to a promotion. Each one-unit
increase in log-transformed purchase frequency increases the odds of
response by about 3.3× (e¹·¹⁹).
PROMOS (β = –0.033, p = .002) → Each additional promotion on file
slightly reduces the odds of responding, suggesting that over-exposure
to promotions may lead to lower engagement.
STYLES_log (β = 0.43, p = .002) → Customers who buy a greater number
of individual items are also more likely to respond. A one-unit increase
in log-transformed styles purchased increases the odds of response by
about 1.5× (e⁰·⁴³).
Let’s take a look at the VIF matrix of our new fitted model to see if
there’s still any multicollinearity.
FRE_log PROMOS STYLES_log
4.384577 1.604865 4.441630
All three VIF values are below 5, meaning multicollinearity is no
longer a serious issue.
4.4 Likelihood Ratio Chi-Squared Test
We test whether the larger model improves fit beyond the reduced
model. The deviance difference is:
ΔG2=Devianc\(ereduced\)−Deviance\(larger\)=1798−1791=7
with df = 10 − 3 = 7 (difference in parameters). This yields a
non-significant LRT (p ≈ 0.42), so the larger model does not provide a
statistically meaningful improvement. We therefore retain the reduced
model.
5 Final Model
Above, we explored two potential models that could predict whether a
customer responds to a mail marketing promotion. Our first model, the
larger model, consisted of all the numerical variables in the dataset.
Our second model, the reduced model, consisted of only our VIF-free,
statistically significant variables. These variables were FRE_log
(number of purchase visits), number of marketing promotions on file
(PROMOS), and number of different items purchased (STYLES_log). Here are
our summary statistics for our final model, but this time we will
include odds ratios to fully encapsulate the impact of this model.
model.coef.stats <- summary(fit2)$coef # Estimate, SE, z, p
odds.ratio <- exp(coef(fit2)) # exponentiate coefficients
out.stats <- cbind(model.coef.stats, `Odds Ratio` = odds.ratio)
knitr::kable(out.stats, caption = "Summary Stats with Odds Ratios")
Summary Stats with Odds Ratios
| (Intercept) |
-4.5160854 |
0.2069388 |
-21.823293 |
0.0000000 |
0.0109317 |
| FRE_log |
1.1876206 |
0.1754269 |
6.769888 |
0.0000000 |
3.2792693 |
| PROMOS |
-0.0331400 |
0.0107794 |
-3.074371 |
0.0021095 |
0.9674031 |
| STYLES_log |
0.4330499 |
0.1409193 |
3.073034 |
0.0021189 |
1.5419531 |
Predictor Interpretation (Intercept) = –4.52, OR = 0.01, p < .001
The baseline odds of responding are very low when all predictors are at
zero (i.e., for an infrequent shopper with no promotions and few
purchases).
FRE_log = 1.19, OR = 3.28, p < .001 Each one-unit increase in
log-transformed purchase frequency multiplies the odds of responding by
about 3.3×, making it the strongest predictor. Frequent shoppers are
much more likely to respond.
PROMOS = –0.033, OR = 0.97, p = .002 Each additional promotion
slightly reduces the odds of responding by about 3%, suggesting that too
many promotions may lead to fatigue or diminished engagement.
STYLES_log = 0.43, OR = 1.54, p = .002 Each one-unit increase in
log-transformed number of items purchased increases the odds of
responding by about 54%, indicating that customers who buy a wider
variety of items tend to be more responsive.
LS0tDQp0aXRsZTogIlByZWRpY3RpbmcgQ3VzdG9tZXIgUmVzcG9uc2UgdG8gRGlyZWN0IE1haWwgUHJvbW90aW9ucyINCmF1dGhvcjogIkx1a2UgVm9sbSINCmRhdGU6ICIyMDI1LTEwLTEwIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiAgICAgICAgICAgIyBvdXRwdXQgZG9jdW1lbnQgZm9ybWF0DQogICAgdG9jOiB5ZXMgICAgICAgICAgICAgICAjIGFkZCB0YWJsZSBjb250ZW50cw0KICAgIHRvY19mbG9hdDogeWVzICAgICAgICAgIyB0b2NfcHJvcGVydHk6IGZsb2F0aW5nDQogICAgdG9jX2RlcHRoOiA0ICAgICAgICAgICAjIGRlcHRoIG9mIFRPQyBoZWFkaW5ncw0KICAgIGZpZ193aWR0aDogNiAgICAgICAgICAgIyBnbG9iYWwgZmlndXJlIHdpZHRoDQogICAgZmlnX2hlaWdodDogNCAgICAgICAgICAjIGdsb2JhbCBmaWd1cmUgaGVpZ2h0DQogICAgZmlnX2NhcHRpb246IHllcyAgICAgICAjIGFkZCBmaWd1cmUgY2FwdGlvbg0KICAgIG51bWJlcl9zZWN0aW9uczogbm8gICAjIG51bWJlcmluZyBzZWN0aW9uIGhlYWRpbmdzDQogICAgdG9jX2NvbGxhcHNlZDogeWVzICAgICAjIFRPQyBzdWJoZWFkaW5nIGNvbGxhcHNpbmcNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUgICAgICMgZm9sZGluZy9zaG93aW5nIGNvZGUgDQogICAgY29kZV9kb3dubG9hZDogeWVzICAgICAjIGFsbG93IHRvIGRvd25sb2FkIGNvbXBsZXRlIFJNYXJrZG93biBzb3VyY2UgY29kZQ0KICAgIHNtb290aF9zY3JvbGw6IHllcyAgICAgIyBzY3JvbGxpbmcgdGV4dCBvZiB0aGUgZG9jdW1lbnQNCiAgICB0aGVtZTogbHVtZW4gICAgICAgICAgICMgdmlzdWFsIHRoZW1lIGZvciBIVE1MIGRvY3VtZW50IG9ubHkNCiAgICBoaWdobGlnaHQ6IHRhbmdvICAgICAgICMgY29kZSBzeW50YXggaGlnaGxpZ2h0aW5nIHN0eWxlcw0KICBwZGZfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogIHdvcmRfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6ICc0Jw0KLS0tDQoNCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0NCmRpdiNUT0MgbHdleyAgICAgLyogdGFibGUgb2YgY29udGVudCAgKi8NCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOw0KICAgIGJhY2tncm91bmQtaW1hZ2U6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXJlcGVhdDpub25lOw0KICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsNCn0NCg0KaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8NCiAgZm9udC1zaXplOiAyNHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgY29sb3I6IERhcmtCbHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmgxIHsgLyogSGVhZGVyIDEgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDIwcHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMiB7IC8qIEhlYWRlciAyIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE2cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KLyogQWRkIGRvdHMgYWZ0ZXIgbnVtYmVyZWQgaGVhZGVycyAqLw0KLmhlYWRlci1zZWN0aW9uLW51bWJlcjo6YWZ0ZXIgew0KICBjb250ZW50OiAiLiI7DQp9DQpgYGANCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkoYm9vdCkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeShwc3ljaCkNCmxpYnJhcnkoTUFTUykNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGNhcikNCmxpYnJhcnkocGFuZGVyKQ0KDQojIFNldCBzZWVkIGZvciByZXByb2R1Y2liaWxpdHkNCnNldC5zZWVkKDEyMykNCg0KIyBSZWFkIGluIGRhdGEgKGRyb3AgZmlyc3QgY29sdW1uIGlmIGl0J3MganVzdCBhbiBpbmRleC9JRCkNCnNldHdkKCJDOi9Vc2Vycy92b2xtMS9PbmVEcml2ZS9EZXNrdG9wL1NUQTMyMSBuZXciKQ0KQ1NEUyA8LSByZWFkLmNzdigiQ2xvdGhpbmcgU3RvcmUgRGF0YSBTZXQuY3N2IikNCiMgR2xvYmFsIGNodW5rIG9wdGlvbnMNCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgZWNobyA9IFRSVUUsICAgICAgIyBzaG93IGNvZGUNCiAgd2FybmluZyA9IEZBTFNFLCAgIyBzdXBwcmVzcyB3YXJuaW5ncw0KICBtZXNzYWdlID0gRkFMU0UsICAjIHN1cHByZXNzIG1lc3NhZ2VzDQogIHJlc3VsdHMgPSBUUlVFLCAgICMgc2hvdyByZXN1bHRzDQogIGNvbW1lbnQgPSBOQSAgICAgICMgY2xlYW5lciBvdXRwdXQgKG5vICIjIyIgcHJlZml4KQ0KKQ0KYGBgDQoNCiMgMSBJbnRyb2R1Y3Rpb24NCg0KSW4gdG9kYXnigJlzIHJldGFpbCBpbmR1c3RyeSwgZGlyZWN0IG1haWwgbWFya2V0aW5nIHJlbWFpbnMgYW4gaW1wb3J0YW50IGNoYW5uZWwgZm9yIGRyaXZpbmcgY3VzdG9tZXIgZW5nYWdlbWVudCBhbmQgc2FsZXMuIEhvd2V2ZXIsIG5vdCBhbGwgY3VzdG9tZXJzIHJlc3BvbmQgdG8gcHJvbW90aW9uYWwgb2ZmZXJzIGVxdWFsbHksIGFuZCBpZGVudGlmeWluZyB3aG8gaXMgbW9zdCBsaWtlbHkgdG8gcmVzcG9uZCBjYW4gaGVscCBjb21wYW5pZXMgYWxsb2NhdGUgcmVzb3VyY2VzIG1vcmUgZWZmaWNpZW50bHkuDQoNClRoaXMgcHJvamVjdCB1c2VzIHRoZSBDbG90aGluZyBTdG9yZSBEYXRhc2V04oCUYSByZWFsIGRhdGFzZXQgZnJvbSBhIE5ldyBFbmdsYW5kIHJldGFpbCBjaGFpbuKAlHRvIGRldmVsb3AgYSBwcmVkaWN0aXZlIG1vZGVsIGZvciBjdXN0b21lciByZXNwb25zZSBiZWhhdmlvci4gVGhlIHByaW1hcnkgZ29hbCBpcyB0byBkZXRlcm1pbmUgd2hpY2ggY3VzdG9tZXIgY2hhcmFjdGVyaXN0aWNzIGJlc3QgcHJlZGljdCB3aGV0aGVyIGFuIGluZGl2aWR1YWwgd2lsbCByZXNwb25kICjigJx5ZXPigJ0pIHRvIGEgZGlyZWN0IG1haWwgcHJvbW90aW9uLg0KDQpUbyBhZGRyZXNzIHRoaXMsIHdlIGNvbmR1Y3QgZXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpcyAoRURBKSB0byBleGFtaW5lIHJlbGF0aW9uc2hpcHMgYW1vbmcgcHVyY2hhc2luZywgZW5nYWdlbWVudCwgYW5kIGRlbW9ncmFwaGljIHZhcmlhYmxlcywgdGhlbiBidWlsZCBhIG11bHRpcGxlIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwgdG8gcXVhbnRpZnkgaG93IHRoZXNlIGZhY3RvcnMgaW5mbHVlbmNlIHJlc3BvbnNlIGxpa2VsaWhvb2QuIEJ5IGlkZW50aWZ5aW5nIHRoZSBtb3N0IG1lYW5pbmdmdWwgcHJlZGljdG9ycywgdGhpcyBhbmFseXNpcyBwcm92aWRlcyBhY3Rpb25hYmxlIGluc2lnaHQgaW50byB3aGljaCB0eXBlcyBvZiBjdXN0b21lcnMgYXJlIG1vc3QgcmVjZXB0aXZlIHRvIGZ1dHVyZSBtYXJrZXRpbmcgZWZmb3J0cy4NCg0KIyAyIERlc2NyaXB0aW9uIG9mIERhdGFzZXQNCg0KVGhlc2UgYXJlIDIwIGV4cGxhbmF0b3J5IHZhcmlhYmxlcyBpbiB0aGlzIGRhdGFzZXQ6IA0KDQoxLiBISEtFWSAoY2F0ZWdvcmlhbCkg4oaSIFVuaXF1ZSBlbmNyeXB0ZWQgY3VzdG9tZXIgSUQNCjIuIFpJUF9DT0RFIChjYXRlZ29yaWFsKSDihpIgQ3VzdG9tZXLigJlzIFpJUCBjb2RlDQozLiBGUkUgKG51bWVyaWNhbCkg4oaSIE51bWJlciBvZiBwdXJjaGFzZSB2aXNpdHMNCjQuIE1PTiAobnVtZXJpY2FsKSDihpIgVG90YWwgbmV0IHNhbGVzDQo1LiBBVlJHIChudW1lcmljYWwpIOKGkiBBdmVyYWdlIHNwZW5kIHBlciB2aXNpdA0KNi4gQU1TUEVORCwgUFNTUEVORCwgQ1NTUEVORCwgQVhTUEVORCAoY2F0ZWdvcmlhbCkg4oaSIFNwZW5kIGFjcm9zcyBmb3VyIGRpZmZlcmVudCBmcmFuY2hpc2UgYnJhbmRzDQo3LiBPTU9OU1BFTkQsIFRNT05TUEVORCwgU01PU1BFTkQgKGNhdGVnb3JpYWwpIOKGkiBTcGVuZCBvdmVyIHBhc3QgMSwgMywgYW5kIDYgbW9udGhzDQo4LiBQUkVWUEQgKGNhdGVnb3JpYWwpIOKGkiBTcGVuZCBpbiB0aGUgc2FtZSBwZXJpb2QgbGFzdCB5ZWFyDQo5LiBHTVAgKG51bWVyaWNhbCkg4oaSIEdyb3NzIG1hcmdpbiBwZXJjZW50YWdlDQoxMC4gUFJPTU9TIChudW1lcmljYWwpIOKGkiBOdW1iZXIgb2YgbWFya2V0aW5nIHByb21vdGlvbnMgb24gZmlsZQ0KMTEuIERBWVMgKG51bWVyaWNhbCkg4oaSIE51bWJlciBvZiBkYXlzIGN1c3RvbWVyIGhhcyBiZWVuIG9uIGZpbGUNCjEyLiBGUkVEQVlTLCBMVEZSRURBWSAoY2F0ZWdvcmlhbCkg4oaSIFRpbWUgYmV0d2VlbiBwdXJjaGFzZXMgKHJlY2VudCAmIGxpZmV0aW1lIGF2ZXJhZ2UpDQoxMy4gQ0xBU1NFUyAobnVtZXJpY2FsKSDihpIgTnVtYmVyIG9mIGRpZmZlcmVudCBwcm9kdWN0IGNsYXNzZXMgcHVyY2hhc2VkDQoxNC4gU1RZTEVTIChudW1lcmljYWwpIOKGkiBOdW1iZXIgb2YgaW5kaXZpZHVhbCBpdGVtcyBwdXJjaGFzZWQNCjE1LiBTVE9SRVMgKG51bWVyaWNhbCkg4oaSIE51bWJlciBvZiBzdG9yZXMgc2hvcHBlZCBhdA0KMTYuIE1BUktET1dOLCBDT1VQT05TLCBNQUlMRUQsIFJFU1BPTkRFLCBSRVNQT05TRVJBVEUgKGNhdGVnb3JpYWwpIOKGkiBQcm9tb3Rpb24gYW5kIGRpc2NvdW50IGVuZ2FnZW1lbnQNCjE3LiBISSAobnVtZXJpY2FsKSDihpIgUHJvZHVjdCB1bmlmb3JtaXR5IChsb3dlciA9IG1vcmUgZGl2ZXJzZSBwdXJjaGFzZXMpDQoxOC4gQ0xVU1RZUEUgKGNhdGVnb3JpY2FsKSDihpIgTGlmZXN0eWxlIGNsdXN0ZXIgdHlwZSAoZW5jcnlwdGVkKQ0KMTkuIFBFUkNSRVQgKG51bWVyaWNhbCkg4oaSIFBlcmNlbnQgb2YgcmV0dXJucw0KMjAuIENDX0NBUkQsIFZBTFBIT04sIFdFQiAoY2F0ZWdvcmlhbCkg4oaSIEZsYWdzIGZvciBjcmVkaXQgY2FyZCwgdmFsaWQgcGhvbmUgbnVtYmVyLCBhbmQgd2ViIHNob3BwZXIgc3RhdHVzDQoNCk91ciByZXNwb25zZSB2YXJpYWJsZSBpczoNCg0KUkVTUCDihpIgd2hldGhlciBhIGN1c3RvbWVyIHJlc3BvbmRlZCB0byBhIHByb21vdGlvbiAoeWVzL25vKQ0KDQpXZSBoYXZlIDI4NDcgb2JzZXJ2YXRpb25zLCBvciBjdXN0b21lcnMsIGluIHRoaXMgZGF0YXNldC4gV2Ugd2lsbCBub3cgcmVtb3ZlIGFsbCBvYnNlcnZhdGlvbnMgd2l0aCBtaXNzaW5nIHZhbHVlcy4NCg0KYGBge3J9DQoNCg0KQ1NEU19jbGVhbiA8LSBuYS5vbWl0KENTRFMpIA0KcmVzcG9uc2UgPC0gZmFjdG9yKENTRFNfY2xlYW4kUkVTUCwgbGV2ZWxzID0gYygibm8iLCJ5ZXMiKSkNCg0KYGBgDQoNCkFmdGVyIHJlbW92aW5nIG1pc3NpbmcgdmFsdWVzLCAyNjE5IGN1c3RvbWVycyByZW1haW4gZm9yIG1vZGVsaW5nLg0KDQojIDMgRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcw0KDQpUbyBiZWdpbiwgd2Ugd2lsbCBtYWtlIGEgY29ycmVsYXRpb24gbWF0cml4IHdpdGggYWxsIG9mIHRoZSBudW1lcmljYWwgdmFyaWFibGVzIHRvIHNlZSBpZiBhbnkgdmFyaWFibGVzIGFyZSBoaWdobHkgY29ycmVsYXRlZCB3aXRoIGVhY2ggb3RoZXIuDQoNCmBgYHtyfQ0KDQojIDEpIE1hbnVhbGx5IGxpc3QgdGhlIG51bWVyaWMgdmFyaWFibGVzIHlvdSB3YW50DQp2YXJzIDwtIGMoIkZSRSIsIk1PTiIsICJBVlJHIiwiR01QIiwiUFJPTU9TIiwiREFZUyIsIkNMQVNTRVMiLCJTVFlMRVMiLCJTVE9SRVMiLCJISSIsIlBFUkNSRVQiKQ0KDQojIDIpIEtlZXAgb25seSB0aGUgb25lcyB0aGF0IGFjdHVhbGx5IGV4aXN0IGluIHlvdXIgZGF0YQ0KdmFycyA8LSBpbnRlcnNlY3QodmFycywgbmFtZXMoQ1NEU19jbGVhbikpDQoNCiMgMykgQ29ycmVsYXRpb24gbWF0cml4IChlcnJvcnMgaWYgYW55IGFyZSBub24tbnVtZXJpYykNCmNvcl9tYXQgPC0gY29yKENTRFNfY2xlYW5bICwgdmFycywgZHJvcCA9IEZBTFNFXSwNCiAgICAgICAgICAgICAgIHVzZSA9ICJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiLA0KICAgICAgICAgICAgICAgbWV0aG9kID0gInBlYXJzb24iKQ0KY29yX21hdA0KDQoNCmBgYA0KDQpQYWlyd2lzZSBjb3JyZWxhdGlvbnMgcmV2ZWFsIHN0cm9uZyByZWxhdGlvbnNoaXBzIGFtb25nIHB1cmNoYXNpbmcgYWN0aXZpdHkgdmFyaWFibGVzLiBGb3IgZXhhbXBsZSwgRlJFICh2aXNpdHMpIGNvcnJlbGF0ZXMgaGlnaGx5IHdpdGggU1RZTEVTIChpdGVtcyBwdXJjaGFzZWQpIGFuZCBDTEFTU0VTIChwcm9kdWN0IGNsYXNzZXMpLCBhbmQgTU9OIChuZXQgc2FsZXMpIGNvcnJlbGF0ZXMgdmVyeSBzdHJvbmdseSB3aXRoIFNUWUxFUy4gVGhlc2UgcGF0dGVybnMgYXJlIGludHVpdGl2ZeKAlGN1c3RvbWVycyB3aG8gc2hvcCBtb3JlIG9mdGVuIHRlbmQgdG8gYnV5IG1vcmUgaXRlbXMgYWNyb3NzIG1vcmUgY2xhc3NlcywgbGVhZGluZyB0byBoaWdoZXIgc2FsZXMuIFdlIHJldGFpbiB0aGVzZSB2YXJpYWJsZXMgaW5pdGlhbGx5IGFuZCBhZGRyZXNzIHJlZHVuZGFuY3kgbGF0ZXIgZHVyaW5nIG1vZGVsIHJlZmluZW1lbnQuDQoNCldlIHdpbGwgbm93IGNvbmR1Y3QgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbnMgZm9yIGFsbCBvZiB0aGUgbnVtZXJpY2FsIHZhcmlhYmxlcyB0byBpZGVudGlmeSBhbnkgcGF0dGVybnMgYW5kIHNrZXduZXNzLiANCg0KYGBge3J9DQoNCnBhcihtZnJvdz1jKDEsMikpDQoNCmhpc3QoQ1NEU19jbGVhbiRGUkUsIHhsYWI9IiMgb2YgUHVyY2hhc2UgVmlzaXRzIiwgbWFpbiA9ICIiKQ0KDQpoaXN0KENTRFNfY2xlYW4kTU9OLCB4bGFiPSJUb3RhbCBOZXQgU2FsZXMiLCBtYWluID0gIiIpDQoNCmhpc3QoQ1NEU19jbGVhbiRBVlJHLCB4bGFiPSJBdmVyYWdlIFNwZW5kIFBlciBWaXNpdCIsIG1haW4gPSAiIikNCg0KaGlzdChDU0RTX2NsZWFuJEdNUCwgeGxhYj0iR3Jvc3MgTWFyZ2luICUiLCBtYWluID0gIiIpDQoNCmhpc3QoQ1NEU19jbGVhbiRQUk9NT1MsIHhsYWI9IiMgb2YgTWFya2V0aW5nIFByb21vcyIsIG1haW4gPSAiIikNCg0KaGlzdChDU0RTX2NsZWFuJERBWVMsIHhsYWI9IkRheXMgb24gRmlsZSIsIG1haW4gPSAiIikNCg0KaGlzdChDU0RTX2NsZWFuJENMQVNTRVMsIHhsYWI9IiMgb2YgRGlmZmVyZW50IFByb2R1Y3RzIFB1cmNoYXNlZCIsIG1haW4gPSAiIikNCg0KaGlzdChDU0RTX2NsZWFuJFNUWUxFUywgeGxhYj0iIyBvZiBJbmRpdmlkdWFsIEl0ZW1zIFB1cmNoYXNlZCIsIG1haW4gPSAiIikNCg0KaGlzdChDU0RTX2NsZWFuJFNUT1JFUywgeGxhYj0iIyBvZiBTdG9yZXMgU2hvcHBlZCBBdCIsIG1haW4gPSAiIikNCg0KaGlzdChDU0RTX2NsZWFuJEhJLCB4bGFiPSJQcm9kdWN0IFVuaWZvcm1pdHkiLCBtYWluID0gIiIpDQoNCmhpc3QoQ1NEU19jbGVhbiRQRVJDUkVULCB4bGFiPSIlIG9mIFJldHVybnMiLCBtYWluID0gIiIpDQoNCmBgYA0KDQpOb25lIG9mIG91ciB2YXJpYWJsZXMgYXJlIGRpc3RyaWJ1dGVkIG5vcm1hbGx5LiBOdW1iZXIgb2YgcHVyY2hhc2UgdmlzaXRzLCBUb3RhbCBOZXQgU2FsZXMsIEF2ZXJhZ2UgU3BlbmQgUGVyIFZpc2l0LCBOdW1iZXIgb2YgTWFya2V0aW5nIFByb21vcywgTnVtYmVyIG9mIERpZmZlcmVudCBQcm9kdWN0cyBQdXJjaGFzZWQsIE51bWJlciBvZiBJbmRpdmlkdWFsIEl0ZW1zIFB1cmNoYXNlZCwgTnVtYmVyIG9mIFN0b3JlcyBTaG9wcGVkIEF0LCBQcm9kdWN0IFVuaWZvcm1pdHksIGFuZCBQZXJjZW50IG9mIFJldHVybnMgYXJlIGFsbCBza2V3ZWQgdG8gdGhlIHJpZ2h0LiBHcm9zcyBNYXJnaW4gUGVyY2VudGFnZSBhbmQgRGF5cyBvbiBGaWxlIGFyZSBza2V3ZWQgbGVmdC4gV2Ugd2lsbCBhcHBseSBhcHByb3ByaWF0ZSB0cmFuc2Zvcm1hdGlvbnMgcHJpb3IgdG8gbW9kZWxpbmcuDQoNCiMgNCBNdWx0aXBsZSBMb2dpc3RpYyBSZWdyZXNzaW9uIE1vZGVsDQoNCkJlZm9yZSBidWlsZGluZyBvdXIgbXVsdGlwbGUgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbCwgd2UgbmVlZCB0byBhZGRyZXNzIHRoZSBoaWdoIGxldmVscyBvZiBza2V3bmVzcyBvYnNlcnZlZCBpbiBtYW55IG9mIG91ciBudW1lcmljYWwgcHJlZGljdG9ycy4gVmFyaWFibGVzIHN1Y2ggYXMgVG90YWwgTmV0IFNhbGVzIChNT04pLCBOdW1iZXIgb2YgUHVyY2hhc2UgVmlzaXRzIChGUkUpLCBOdW1iZXIgb2YgSW5kaXZpZHVhbCBJdGVtcyBQdXJjaGFzZWQgKFNUWUxFUyksIGFuZCBQZXJjZW50IG9mIFJldHVybnMgKFBFUkNSRVQpIHdlcmUgZm91bmQgdG8gYmUgc3Ryb25nbHkgcmlnaHQtc2tld2VkLCB3aGlsZSBHcm9zcyBNYXJnaW4gUGVyY2VudGFnZSAoR01QKSBzaG93ZWQgbW9kZXJhdGUgbGVmdCBza2V3LiBUbyBlbnN1cmUgbW9yZSBzdGFibGUgY29lZmZpY2llbnQgZXN0aW1hdGVzIGFuZCBpbXByb3ZlIGxpbmVhcml0eSB3aXRoIHRoZSBsb2ctb2RkcyBvZiB0aGUgcmVzcG9uc2UgdmFyaWFibGUsIHdlIGFwcGx5IHNldmVyYWwgdHJhbnNmb3JtYXRpb25zLiBSaWdodC1za2V3ZWQsIHN0cmljdGx5IHBvc2l0aXZlIHZhcmlhYmxlcyBhcmUgdHJhbnNmb3JtZWQgdXNpbmcgdGhlIGxvZzFwKCkgZnVuY3Rpb24sIHdoaWNoIHNhZmVseSBoYW5kbGVzIHplcm9zIGFuZCByZWR1Y2VzIHRoZSBpbmZsdWVuY2Ugb2YgbGFyZ2Ugb3V0bGllcnMuIFRoZSBwZXJjZW50YWdlIHZhcmlhYmxlIFBFUkNSRVQgaXMgZmlyc3QgY29udmVydGVkIHRvIGEgcHJvcG9ydGlvbiBhbmQgdGhlbiB0cmFuc2Zvcm1lZCB1c2luZyB0aGUgbG9naXQgKHFsb2dpcygpKSBmdW5jdGlvbiwgYWxsb3dpbmcgaXQgdG8gdmFyeSBzbW9vdGhseSBvbiB0aGUgcmVhbCBudW1iZXIgbGluZS4gV2UgYWxzbyBkcm9wIEF2ZXJhZ2UgU3BlbmQgcGVyIFZpc2l0IChBVlJHKSBkdWUgdG8gcmVkdW5kYW5jeSB3aXRoIE1PTiBhbmQgRlJFLCB3aGljaCBoZWxwcyBtaW5pbWl6ZSBtdWx0aWNvbGxpbmVhcml0eS4gVGhlIHJlc3VsdGluZyBkYXRhc2V0IHByb3ZpZGVzIGEgbW9yZSBiYWxhbmNlZCBkaXN0cmlidXRpb24gb2YgcHJlZGljdG9ycyBhbmQgY3JlYXRlcyBhIHN0cm9uZ2VyIGZvdW5kYXRpb24gZm9yIG1vZGVsaW5nIGN1c3RvbWVyIHJlc3BvbnNlIHByb2JhYmlsaXRpZXMuDQoNCmBgYHtyfQ0KDQoNCmRhdCA8LSBDU0RTX2NsZWFuICU+JQ0KICAjIGVuc3VyZSBSRVNQIGlzIGEgcHJvcGVyIGZhY3RvciBmaXJzdA0KICBkcGx5cjo6bXV0YXRlKA0KICAgIFJFU1AgPSBjYXNlX3doZW4oDQogICAgICBSRVNQICVpbiUgYygiWWVzIiwieWVzIiwxKSB+ICJ5ZXMiLA0KICAgICAgUkVTUCAlaW4lIGMoIk5vIiwibm8iLDApICAgfiAibm8iLA0KICAgICAgVFJVRSB+IE5BX2NoYXJhY3Rlcl8NCiAgICApLA0KICAgIFJFU1AgPSBmYWN0b3IoUkVTUCwgbGV2ZWxzID0gYygibm8iLCJ5ZXMiKSkNCiAgKSAlPiUNCiAgIyB0cmFuc2Zvcm1zDQogIGRwbHlyOjptdXRhdGUoDQogICAgUEVSQ1JFVF9wICAgICA9IHBtaW4ocG1heChQRVJDUkVULzEwMCwgMWUtNiksIDEgLSAxZS02KSwNCiAgICBQRVJDUkVUX2xvZ2l0ID0gcWxvZ2lzKFBFUkNSRVRfcCksDQogICAgZHBseXI6OmFjcm9zcygNCiAgICAgIHRpZHlzZWxlY3Q6OmFueV9vZihjKCJNT04iLCJGUkUiLCJTVFlMRVMiLCJDTEFTU0VTIiwiU1RPUkVTIiwiSEkiKSksDQogICAgICB+IGxvZzFwKC4pLA0KICAgICAgLm5hbWVzID0gInsuY29sfV9sb2ciDQogICAgKQ0KICApICU+JQ0KICAjIHNlbGVjdCBPTkxZIHdpdGggZnVsbHktcXVhbGlmaWVkIGRwbHlyDQogIGRwbHlyOjpzZWxlY3QoZHBseXI6OmFsbF9vZigNCiAgICBjKCJSRVNQIiwiTU9OX2xvZyIsIkZSRV9sb2ciLCJTVFlMRVNfbG9nIiwiQ0xBU1NFU19sb2ciLCJTVE9SRVNfbG9nIiwNCiAgICAgICJISV9sb2ciLCJQRVJDUkVUX2xvZ2l0IiwiUFJPTU9TIiwiREFZUyIsIkdNUCIpDQogICkpICU+JQ0KICB0aWR5cjo6ZHJvcF9uYSgpDQoNCmBgYA0KDQpIZXJlIHdlIGZpdCB0aGUgbXVsdGlwbGUgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbCBwcmVkaWN0aW5nIFJFU1AgKHllcy9ubykgdXNpbmcgdGhlIHRyYW5zZm9ybWVkIHByZWRpY3RvcnMgZnJvbSBTZWN0aW9uIDQuMS4gVGhlIHNwZWNpZmljYXRpb24gaW5jbHVkZXMgbG9nLXRyYW5zZm9ybWVkIGJlaGF2aW9yYWwgbWVhc3VyZXMgKGUuZy4sIE1PTl9sb2csIEZSRV9sb2csIFNUWUxFU19sb2csIENMQVNTRVNfbG9nLCBTVE9SRVNfbG9nLCBISV9sb2cpLCB0aGUgbG9naXQtdHJhbnNmb3JtZWQgcmV0dXJuIHJhdGUgKFBFUkNSRVRfbG9naXQpLCBhbmQgdW50cmFuc2Zvcm1lZCBjb250cm9scyAoUFJPTU9TLCBEQVlTLCBHTVApLiBUaGlzIG1vZGVsIGVzdGltYXRlcyBob3cgZWFjaCBmZWF0dXJlIGlzIGFzc29jaWF0ZWQgd2l0aCB0aGUgbG9nLW9kZHMgb2YgcmVzcG9uZGluZyB3aGlsZSBtaXRpZ2F0aW5nIHNrZXcgYW5kIG11bHRpY29sbGluZWFyaXR5LiBXZSByZXBvcnQgY29lZmZpY2llbnQgc3VtbWFyaWVzIGFuZCBvZGRzIHJhdGlvcyB0byBhaWQgaW50ZXJwcmV0YXRpb24uDQoNCmBgYHtyLCBtZXNzYWdlID0gRkFMU0V9DQoNCiMgRW5zdXJlIFJFU1AgZXhpc3RzIGFuZCBpcyBhIGZhY3RvciB3aXRoIGNvcnJlY3QgbGV2ZWxzDQpkYXQkUkVTUCA8LSBmYWN0b3IoZGF0JFJFU1AsIGxldmVscyA9IGMoIm5vIiwgInllcyIpKQ0KDQojIENoZWNrIHRoYXQgaXQgd29ya2VkDQp0YWJsZShkYXQkUkVTUCkNCmBgYA0KDQojIyA0LjEgTGFyZ2VyIE1vZGVsDQoNCldlIGZpcnN0IGZpdCBhIGxhcmdlciBtb2RlbCwgaW5jbHVkaW5nIE1PTl9sb2csIEZSRV9sb2csIFNUWUxFU19sb2csIENMQVNTRVNfbG9nLCBTVE9SRVNfbG9nLCBISV9sb2csIFBFUkNSRVRfbG9naXQsIFBST01PUywgREFZUywgYW5kIEdNUC4NCg0KYGBge3J9DQoNCmZpdCA8LSBnbG0oUkVTUCB+IE1PTl9sb2cgKyBGUkVfbG9nICsgU1RZTEVTX2xvZyArIENMQVNTRVNfbG9nICsgU1RPUkVTX2xvZyArDQogICAgICAgICAgICAgSElfbG9nICsgUEVSQ1JFVF9sb2dpdCArIFBST01PUyArIERBWVMgKyBHTVAsDQogICAgICAgICAgIGRhdGEgPSBkYXQsIGZhbWlseSA9IGJpbm9taWFsKQ0KDQpzdW1tYXJ5KGZpdCkNCmBgYA0KDQpUaGUgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbCBwcmVkaWN0cyB0aGUgbGlrZWxpaG9vZCB0aGF0IGEgY3VzdG9tZXIgcmVzcG9uZHMgKFJFU1AgPSB5ZXMpIHRvIGEgbWFya2V0aW5nIHByb21vdGlvbiBiYXNlZCBvbiBwdXJjaGFzaW5nIGFuZCBlbmdhZ2VtZW50IHZhcmlhYmxlcy4gVGhlIG5lZ2F0aXZlIGludGVyY2VwdCAo4oCTMy42NywgcCA8IC4wMDEpIHN1Z2dlc3RzIGEgbG93IGJhc2VsaW5lIHByb2JhYmlsaXR5IG9mIHJlc3BvbnNlLg0KDQpUaGUgbnVtYmVyIG9mIHB1cmNoYXNlIHZpc2l0cyAoRlJFX2xvZykgaXMgdGhlIHN0cm9uZ2VzdCBhbmQgbW9zdCBzaWduaWZpY2FudCBwcmVkaWN0b3IgKM6yID0gMS4yMSwgcCA8IC4wMDEpLCBtZWFuaW5nIGN1c3RvbWVycyB3aG8gc2hvcCBtb3JlIGZyZXF1ZW50bHkgYXJlIG11Y2ggbW9yZSBsaWtlbHkgdG8gcmVzcG9uZC4gQSBvbmUtdW5pdCBpbmNyZWFzZSBpbiBsb2ctdHJhbnNmb3JtZWQgcHVyY2hhc2UgdmlzaXRzIG11bHRpcGxpZXMgdGhlIG9kZHMgb2YgcmVzcG9uZGluZyBieSBhYm91dCAzLjM1IHRpbWVzLg0KDQpOdW1iZXIgb2YgaXRlbXMgcHVyY2hhc2VkIChTVFlMRVNfbG9nKSBzaG93cyBhIHdlYWsgcG9zaXRpdmUgZWZmZWN0IChwID0gLjA3KSwgd2hpbGUgbnVtYmVyIG9mIHByb21vdGlvbnMgKFBST01PUykgaGFzIGEgc21hbGwgbmVnYXRpdmUgZWZmZWN0ICjOsiA9IOKAkzAuMDI1LCBwID0gLjA0KSwgc3VnZ2VzdGluZyB0aGF0IG92ZXJleHBvc3VyZSB0byBwcm9tb3Rpb25zIHNsaWdodGx5IHJlZHVjZXMgcmVzcG9uc2l2ZW5lc3MuDQoNCkFsbCBvdGhlciB2YXJpYWJsZXMgd2VyZSBub3Qgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCwgaW5kaWNhdGluZyB0aGF0IGZyZXF1ZW50IHNob3BwZXJzIGFyZSB0aGUgbW9zdCByZWxpYWJsZSBwcmVkaWN0b3JzIG9mIHByb21vdGlvbmFsIHJlc3BvbnNlLg0KDQpCZWZvcmUgc2hvcnRlbmluZyBvdXIgbW9kZWwsIGxldCdzIHNlZSBpZiB0aGVyZSBpcyBtdWx0aWNvbGxpbmVhcml0eSB3aXRoaW4gb3VyIHByZWRpY3RvciB2YXJpYWJsZXMuIFdlIHdpbGwgcnVuIGEgVklGIG1hdHJpeC4gDQoNCmBgYHtyfQ0KDQp2aWYoZml0KQ0KDQpgYGANCg0KVmFyaWFuY2UgaW5mbGF0aW9uIGZhY3RvcnMgKFZJRikgaW5kaWNhdGUgc3Vic3RhbnRpYWwgbXVsdGljb2xsaW5lYXJpdHkgYW1vbmcgcHVyY2hhc2UtYWN0aXZpdHkgdmFyaWFibGVzOiBNT05fbG9nLCBTVFlMRVNfbG9nLCBhbmQgQ0xBU1NFU19sb2cgYXJlIGluZmxhdGVkIChWSUYgPiAxMCksIGFuZCBGUkVfbG9nIGlzIG1vZGVyYXRlbHkgaW5mbGF0ZWQuIEJlY2F1c2UgTU9OX2xvZyBhbmQgQ0xBU1NFU19sb2cgYXJlIGFsc28gbm90IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQsIHdlIHJlbW92ZSB0aGVtLiBXZSBrZWVwIFNUWUxFU19sb2cgdGVtcG9yYXJpbHkgdG8gcmVhc3Nlc3MgaXRzIHNpZ25hbCBhZnRlciByZWR1Y2luZyBtdWx0aWNvbGxpbmVhcml0eS4NCg0KIyMgNC4yIFJlZHVjZWQgTW9kZWwNCg0KSGVyZSBpcyBvdXIgaW1wcm92ZWQsIG5ldyBmaXR0ZWQgbW9kZWw6DQoNCmBgYHtyfQ0KDQojIEZpdCB0aGUgcmVkdWNlZCBtb2RlbA0KZml0MiA8LSBnbG0oUkVTUCB+IEZSRV9sb2cgKyBQUk9NT1MgKyBTVFlMRVNfbG9nLA0KICAgICAgICAgICAgZGF0YSA9IGRhdCwgZmFtaWx5ID0gYmlub21pYWwpDQoNCiMgSW5zcGVjdCByZXN1bHRzDQpzdW1tYXJ5KGZpdDIpDQoNCmBgYA0KDQpBbGwgcHJlZGljdG9ycyBhcmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBhdCB0aGUgMC4wMSBsZXZlbCwgaW5kaWNhdGluZyB0aGF0IHNob3BwaW5nIGZyZXF1ZW5jeSwgcHVyY2hhc2UgdmFyaWV0eSwgYW5kIHByb21vdGlvbiBleHBvc3VyZSBtZWFuaW5nZnVsbHkgaW5mbHVlbmNlIHJlc3BvbnNlIGxpa2VsaWhvb2QuDQoNCkZSRV9sb2cgKM6yID0gMS4xOSwgcCA8IC4wMDEpIOKGkiBDdXN0b21lcnMgd2hvIHZpc2l0IHRoZSBzdG9yZSBtb3JlIGZyZXF1ZW50bHkgYXJlIG11Y2ggbW9yZSBsaWtlbHkgdG8gcmVzcG9uZCB0byBhIHByb21vdGlvbi4gRWFjaCBvbmUtdW5pdCBpbmNyZWFzZSBpbiBsb2ctdHJhbnNmb3JtZWQgcHVyY2hhc2UgZnJlcXVlbmN5IGluY3JlYXNlcyB0aGUgb2RkcyBvZiByZXNwb25zZSBieSBhYm91dCAzLjPDlyAoZcK5wrfCueKBuSkuDQoNClBST01PUyAozrIgPSDigJMwLjAzMywgcCA9IC4wMDIpIOKGkiBFYWNoIGFkZGl0aW9uYWwgcHJvbW90aW9uIG9uIGZpbGUgc2xpZ2h0bHkgcmVkdWNlcyB0aGUgb2RkcyBvZiByZXNwb25kaW5nLCBzdWdnZXN0aW5nIHRoYXQgb3Zlci1leHBvc3VyZSB0byBwcm9tb3Rpb25zIG1heSBsZWFkIHRvIGxvd2VyIGVuZ2FnZW1lbnQuDQoNClNUWUxFU19sb2cgKM6yID0gMC40MywgcCA9IC4wMDIpIOKGkiBDdXN0b21lcnMgd2hvIGJ1eSBhIGdyZWF0ZXIgbnVtYmVyIG9mIGluZGl2aWR1YWwgaXRlbXMgYXJlIGFsc28gbW9yZSBsaWtlbHkgdG8gcmVzcG9uZC4gQSBvbmUtdW5pdCBpbmNyZWFzZSBpbiBsb2ctdHJhbnNmb3JtZWQgc3R5bGVzIHB1cmNoYXNlZCBpbmNyZWFzZXMgdGhlIG9kZHMgb2YgcmVzcG9uc2UgYnkgYWJvdXQgMS41w5cgKGXigbDCt+KBtMKzKS4NCg0KTGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIFZJRiBtYXRyaXggb2Ygb3VyIG5ldyBmaXR0ZWQgbW9kZWwgdG8gc2VlIGlmIHRoZXJlJ3Mgc3RpbGwgYW55IG11bHRpY29sbGluZWFyaXR5Lg0KDQpgYGB7cn0NCg0KdmlmKGZpdDIpDQoNCmBgYA0KDQpBbGwgdGhyZWUgVklGIHZhbHVlcyBhcmUgYmVsb3cgNSwgbWVhbmluZyBtdWx0aWNvbGxpbmVhcml0eSBpcyBubyBsb25nZXIgYSBzZXJpb3VzIGlzc3VlLg0KDQojIyA0LjMgUGVyZm9ybWFuY2UgQ29tcGFyaXNvbg0KDQpXZSB3aWxsIG5vdyB1c2UgZGV2aWFuY2UgYW5kIEFJQyB0byBhc3Nlc3MgdGhlIHBlcmZvcm1hbmNlIG9mIG91ciB0d28gbW9kZWxzLiBXZSBhcmUgbG9va2luZyBmb3IgdGhlIG1vZGVsIHdpdGggdGhlIGxvd2VzdCBBSUMgdmFsdWUuIERldmlhbmNlIGFsbG93cyB1cyB0byBtZWFzdXJlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIG1vZGVsIGFuZCBvYnNlcnZlZCB2YWx1ZXMuIEEgbG93IEFJQyB2YWx1ZSBpbmRpY2F0ZXMgYSBiZXR0ZXIgYmFsYW5jZSBiZXR3ZWVuIGdvb2RuZXNzLW9mLWZpdCBhbmQgbW9kZWwgY29tcGxleGl0eS4NCg0KYGBge3J9DQoNCiMjIE90aGVyIGdsb2JhbCBnb29kbmVzcy1vZi1maXQNCmdsb2JhbC5tZWFzdXJlPWZ1bmN0aW9uKHMubG9naXQpew0KZGV2LnJlc2lkID0gcy5sb2dpdCRkZXZpYW5jZQ0KZGV2LjAucmVzaWQgPSBzLmxvZ2l0JG51bGwuZGV2aWFuY2UNCmFpYyA9IHMubG9naXQkYWljDQpnb29kbmVzcyA9IGNiaW5kKERldmlhbmNlLnJlc2lkdWFsID1kZXYucmVzaWQsIE51bGwuRGV2aWFuY2UuUmVzaWR1YWwgPSBkZXYuMC5yZXNpZCwNCiAgICAgIEFJQyA9IGFpYykNCmdvb2RuZXNzDQp9DQpnb29kbmVzcz1yYmluZChmaXQgPSBnbG9iYWwubWVhc3VyZShmaXQpLA0KICAgICAgZml0Mj1nbG9iYWwubWVhc3VyZShmaXQyKQ0KICAgICApDQpyb3cubmFtZXMoZ29vZG5lc3MpID0gYygibGFyZ2VyLm1vZGVsIiwgInJlZHVjZWQubW9kZWwiKQ0KcGFuZGVyKGdvb2RuZXNzLCBjYXB0aW9uID0iQ29tcGFyaXNvbiBvZiBnbG9iYWwgZ29vZG5lc3Mtb2YtZml0IHN0YXRpc3RpY3MiKQ0KYGBgDQoNCldlIGNvbXBhcmUgbW9kZWwgZml0IHVzaW5nIEFJQyBhbmQgZGV2aWFuY2UuIFRoZSByZWR1Y2VkIG1vZGVsIGFjaGlldmVzIGEgbG93ZXIgQUlDICjiiYggMTgwNikgdGhhbiB0aGUgbGFyZ2VyIG1vZGVsICjiiYggMTgxMyksIGluZGljYXRpbmcgYSBiZXR0ZXIgYmFsYW5jZSBvZiBmaXQgYW5kIHBhcnNpbW9ueS4gV2hpbGUgdGhlIHJlZHVjZWQgbW9kZWzigJlzIHJlc2lkdWFsIGRldmlhbmNlIGlzIHNsaWdodGx5IGhpZ2hlciAod29yc2UgcmF3IGZpdCksIEFJQyBwZW5hbGl6ZXMgdW5uZWNlc3NhcnkgY29tcGxleGl0eeKAlHRodXMsIG92ZXJhbGwsIHRoZSByZWR1Y2VkIG1vZGVsIGlzIHByZWZlcnJlZC4NCg0KIyMgNC40IExpa2VsaWhvb2QgUmF0aW8gQ2hpLVNxdWFyZWQgVGVzdA0KDQpXZSB0ZXN0IHdoZXRoZXIgdGhlIGxhcmdlciBtb2RlbCBpbXByb3ZlcyBmaXQgYmV5b25kIHRoZSByZWR1Y2VkIG1vZGVsLiBUaGUgZGV2aWFuY2UgZGlmZmVyZW5jZSBpczoNCg0KzpRHMj1EZXZpYW5jJGVyZWR1Y2VkJOKIkkRldmlhbmNlJGxhcmdlciQ9MTc5OOKIkjE3OTE9Nw0KDQp3aXRoIGRmID0gMTAg4oiSIDMgPSA3IChkaWZmZXJlbmNlIGluIHBhcmFtZXRlcnMpLiBUaGlzIHlpZWxkcyBhIG5vbi1zaWduaWZpY2FudCBMUlQgKHAg4omIIDAuNDIpLCBzbyB0aGUgbGFyZ2VyIG1vZGVsIGRvZXMgbm90IHByb3ZpZGUgYSBzdGF0aXN0aWNhbGx5IG1lYW5pbmdmdWwgaW1wcm92ZW1lbnQuIFdlIHRoZXJlZm9yZSByZXRhaW4gdGhlIHJlZHVjZWQgbW9kZWwuDQoNCiMgNSBGaW5hbCBNb2RlbA0KDQpBYm92ZSwgd2UgZXhwbG9yZWQgdHdvIHBvdGVudGlhbCBtb2RlbHMgdGhhdCBjb3VsZCBwcmVkaWN0IHdoZXRoZXIgYSBjdXN0b21lciByZXNwb25kcyB0byBhIG1haWwgbWFya2V0aW5nIHByb21vdGlvbi4gT3VyIGZpcnN0IG1vZGVsLCB0aGUgbGFyZ2VyIG1vZGVsLCBjb25zaXN0ZWQgb2YgYWxsIHRoZSBudW1lcmljYWwgdmFyaWFibGVzIGluIHRoZSBkYXRhc2V0LiBPdXIgc2Vjb25kIG1vZGVsLCB0aGUgcmVkdWNlZCBtb2RlbCwgY29uc2lzdGVkIG9mIG9ubHkgb3VyIFZJRi1mcmVlLCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IHZhcmlhYmxlcy4gVGhlc2UgdmFyaWFibGVzIHdlcmUgRlJFX2xvZyAobnVtYmVyIG9mIHB1cmNoYXNlIHZpc2l0cyksIG51bWJlciBvZiBtYXJrZXRpbmcgcHJvbW90aW9ucyBvbiBmaWxlIChQUk9NT1MpLCBhbmQgbnVtYmVyIG9mIGRpZmZlcmVudCBpdGVtcyBwdXJjaGFzZWQgKFNUWUxFU19sb2cpLiBIZXJlIGFyZSBvdXIgc3VtbWFyeSBzdGF0aXN0aWNzIGZvciBvdXIgZmluYWwgbW9kZWwsIGJ1dCB0aGlzIHRpbWUgd2Ugd2lsbCBpbmNsdWRlIG9kZHMgcmF0aW9zIHRvIGZ1bGx5IGVuY2Fwc3VsYXRlIHRoZSBpbXBhY3Qgb2YgdGhpcyBtb2RlbC4NCg0KYGBge3J9DQptb2RlbC5jb2VmLnN0YXRzIDwtIHN1bW1hcnkoZml0MikkY29lZiAgICAgICAgICAgICAgIyBFc3RpbWF0ZSwgU0UsIHosIHANCm9kZHMucmF0aW8gICAgICAgPC0gZXhwKGNvZWYoZml0MikpICAgICAgICAgICAgICAgICAjIGV4cG9uZW50aWF0ZSBjb2VmZmljaWVudHMNCg0Kb3V0LnN0YXRzIDwtIGNiaW5kKG1vZGVsLmNvZWYuc3RhdHMsIGBPZGRzIFJhdGlvYCA9IG9kZHMucmF0aW8pDQprbml0cjo6a2FibGUob3V0LnN0YXRzLCBjYXB0aW9uID0gIlN1bW1hcnkgU3RhdHMgd2l0aCBPZGRzIFJhdGlvcyIpDQpgYGANCg0KUHJlZGljdG9yCUludGVycHJldGF0aW9uDQooSW50ZXJjZXB0KSA9IOKAkzQuNTIsIE9SID0gMC4wMSwgcCA8IC4wMDEJVGhlIGJhc2VsaW5lIG9kZHMgb2YgcmVzcG9uZGluZyBhcmUgdmVyeSBsb3cgd2hlbiBhbGwgcHJlZGljdG9ycyBhcmUgYXQgemVybyAoaS5lLiwgZm9yIGFuIGluZnJlcXVlbnQgc2hvcHBlciB3aXRoIG5vIHByb21vdGlvbnMgYW5kIGZldyBwdXJjaGFzZXMpLg0KDQpGUkVfbG9nID0gMS4xOSwgT1IgPSAzLjI4LCBwIDwgLjAwMQlFYWNoIG9uZS11bml0IGluY3JlYXNlIGluIGxvZy10cmFuc2Zvcm1lZCBwdXJjaGFzZSBmcmVxdWVuY3kgbXVsdGlwbGllcyB0aGUgb2RkcyBvZiByZXNwb25kaW5nIGJ5IGFib3V0IDMuM8OXLCBtYWtpbmcgaXQgdGhlIHN0cm9uZ2VzdCBwcmVkaWN0b3IuIEZyZXF1ZW50IHNob3BwZXJzIGFyZSBtdWNoIG1vcmUgbGlrZWx5IHRvIHJlc3BvbmQuDQoNClBST01PUyA9IOKAkzAuMDMzLCBPUiA9IDAuOTcsIHAgPSAuMDAyCUVhY2ggYWRkaXRpb25hbCBwcm9tb3Rpb24gc2xpZ2h0bHkgcmVkdWNlcyB0aGUgb2RkcyBvZiByZXNwb25kaW5nIGJ5IGFib3V0IDMlLCBzdWdnZXN0aW5nIHRoYXQgdG9vIG1hbnkgcHJvbW90aW9ucyBtYXkgbGVhZCB0byBmYXRpZ3VlIG9yIGRpbWluaXNoZWQgZW5nYWdlbWVudC4NCg0KU1RZTEVTX2xvZyA9IDAuNDMsIE9SID0gMS41NCwgcCA9IC4wMDIJRWFjaCBvbmUtdW5pdCBpbmNyZWFzZSBpbiBsb2ctdHJhbnNmb3JtZWQgbnVtYmVyIG9mIGl0ZW1zIHB1cmNoYXNlZCBpbmNyZWFzZXMgdGhlIG9kZHMgb2YgcmVzcG9uZGluZyBieSBhYm91dCA1NCUsIGluZGljYXRpbmcgdGhhdCBjdXN0b21lcnMgd2hvIGJ1eSBhIHdpZGVyIHZhcmlldHkgb2YgaXRlbXMgdGVuZCB0byBiZSBtb3JlIHJlc3BvbnNpdmUuDQoNCiMgNiBDb25jbHVzaW9uDQoNCldlIHNldCBvdXQgdG8gaWRlbnRpZnkgd2hpY2ggYmVoYXZpb3JzIGJlc3QgcHJlZGljdCByZXNwb25zZSB0byBhIGRpcmVjdCBtYWlsIHByb21vdGlvbi4gQWZ0ZXIgY2xlYW5pbmcsIHRyYW5zZm9ybWluZywgYW5kIGFkZHJlc3NpbmcgbXVsdGljb2xsaW5lYXJpdHksIGEgcGFyc2ltb25pb3VzIGxvZ2lzdGljIG1vZGVsIHdpdGggRlJFX2xvZywgU1RZTEVTX2xvZywgYW5kIFBST01PUyBvdXRwZXJmb3JtZWQgdGhlIGxhcmdlciBzcGVjaWZpY2F0aW9uIG9uIEFJQyBhbmQgd2FzIG5vdCBzaWduaWZpY2FudGx5IHdvcnNlIGJ5IGFuIExSVC4gUmVzdWx0cyBzaG93IHRoYXQgc2hvcHBpbmcgZnJlcXVlbmN5IGFuZCBicmVhZHRoIG9mIGl0ZW1zIHB1cmNoYXNlZCBhcmUgc3Ryb25nLCBwb3NpdGl2ZSBkcml2ZXJzIG9mIHJlc3BvbnNlLCB3aGVyZWFzIHByb21vdGlvbiBzYXR1cmF0aW9uIHNsaWdodGx5IHJlZHVjZXMgZW5nYWdlbWVudC4gVGhlc2UgZmluZGluZ3Mgc3VnZ2VzdCBhIHByYWN0aWNhbCBzdHJhdGVneTogcHJpb3JpdGl6ZSBvdXRyZWFjaCB0byBoaWdoLWZyZXF1ZW5jeSwgaGlnaC12YXJpZXR5IHNob3BwZXJzIHdoaWxlIG1vZGVyYXRpbmcgcHJvbW90aW9uIHZvbHVtZSB0byBhdm9pZCBmYXRpZ3VlLCB0aGVyZWJ5IGltcHJvdmluZyB0YXJnZXRpbmcgZWZmaWNpZW5jeSBhbmQgY2FtcGFpZ24gbGlmdC4=