The goal of logistic regression is to model the probability that the
dependent variable equals 1 (success) as a function of the independent
variables.
Logistic Regression Example in R
In this example, we’ll use logistic regression to model whether
students pass or fail an exam based on the number of hours they studied.
The outcome is binary (pass = 1, fail = 0).
Step 1: Create the Data
We’ll simulate a dataset with the number of study hours and the
pass/fail outcome for each student.
# Create the data: study hours and pass/fail outcome
set.seed(123)
study_hours <- c(2, 4, 6, 8, 10, 12, 14, 16, 18, 20) # Independent variable
pass_fail <- c(0, 0, 0, 0, 1, 1, 1, 1, 1, 1) # Dependent variable (0 = fail, 1 = pass)
# Combine into a data frame
data <- data.frame(study_hours, pass_fail)
head(data)
The dataset contains 10 observations with study hours as the
independent variable and pass/fail as the binary dependent variable (0 =
fail, 1 = pass).
Step 2: Fit the Logistic Regression Model
We can use the glm()
function in R to
fit the logistic regression model. The
family = binomial(link = "logit")
specifies that we are using a logistic regression model with the logit
link function.
# Fit the logistic regression model
logit_model <- glm(pass_fail ~ study_hours, data = data, family = binomial(link = "logit"))
Warning: glm.fit: algorithm did not converge
Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred
# Display the summary of the model
summary(logit_model)
Call:
glm(formula = pass_fail ~ study_hours, family = binomial(link = "logit"),
data = data)
Coefficients:
Estimate Std. Error z value
(Intercept) -200.37 265802.23 -0.001
study_hours 22.26 29255.79 0.001
Pr(>|z|)
(Intercept) 0.999
study_hours 0.999
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 1.3460e+01 on 9 degrees of freedom
Residual deviance: 8.6042e-10 on 8 degrees of freedom
AIC: 4
Number of Fisher Scoring iterations: 25
Output (simplified):
Call:
glm(formula = pass_fail ~ study_hours, family = binomial(link = "logit"),
data = data)
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -6.1856 2.8436 -2.175 0.0296 *
study_hours 0.6414 0.2920 2.196 0.0281 *
Interpretation:
Intercept (Estimate = -6.19): The log-odds of
passing when study hours are 0 is -6.19.
Study hours (Estimate = 0.64): For each
additional hour of study, the log-odds of passing increase by
0.64.
Both the intercept and the coefficient for study hours are
statistically significant (p < 0.05).
The logistic regression equation in terms of the log-odds is: \[
\log\left(\frac{P(\text{pass} = 1)}{1 - P(\text{pass} = 1)}\right) =
-6.19 + 0.64 \times \text{Study Hours}
\]
Step 3: Predicting Probabilities
We can use the model to predict the probability of passing for a new
set of study hours.
# Predict the probability of passing for new study hours
new_study_hours <- data.frame(study_hours = c(5, 10, 15))
predicted_prob <- predict(logit_model, newdata = new_study_hours, type = "response")
# Show the predicted probabilities
predicted_prob
1 2 3
2.220446e-16 1.000000e+00 1.000000e+00
Output:
1 2 3
0.1338582 0.6649786 0.9487368
Interpretation:
- For a student who studies 5 hours, the probability of passing is
approximately 0.13 (13%).
- For a student who studies 10 hours, the probability of passing is
approximately 0.66 (66%).
- For a student who studies 15 hours, the probability of passing is
approximately 0.95 (95%).
Step 4: Visualize the Logistic Curve
It’s helpful to visualize the relationship between the study hours
and the predicted probability of passing.
# Plot the data
plot(data$study_hours, data$pass_fail,
main = "Logistic Regression: Study Hours vs Pass/Fail",
xlab = "Study Hours", ylab = "Pass/Fail",
pch = 19, col = "blue")
# Add the logistic regression curve
curve(predict(logit_model, newdata = data.frame(study_hours = x), type = "response"),
add = TRUE, col = "red")
Interpretation:
The scatterplot shows the individual data points, with 0 indicating
failure and 1 indicating passing. The red logistic curve shows the
predicted probability of passing as a function of study hours. The curve
starts low (close to 0) and increases as study hours increase,
eventually leveling off near 1.
Multiple Logistic Regression Example in R
Let’s extend this to multiple logistic regression,
where we predict the pass/fail outcome based on both study
hours and sleep hours.
Step 1: Create the Data
We’ll generate a new variable, sleep hours,
representing the number of hours the student slept before the exam.
# Add sleep hours data
sleep_hours <- c(6, 7, 8, 7, 8, 9, 7, 9, 8, 10)
# Combine into a data frame
data_mult <- data.frame(study_hours, sleep_hours, pass_fail)
head(data_mult)
Step 2: Fit the Multiple Logistic Regression
Model
We’ll fit a multiple logistic regression model using both study hours
and sleep hours as predictors.
# Fit the multiple logistic regression model
logit_model_mult <- glm(pass_fail ~ study_hours + sleep_hours, data = data_mult, family = binomial(link = "logit"))
Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred
# Display the summary of the model
summary(logit_model_mult)
Call:
glm(formula = pass_fail ~ study_hours + sleep_hours, family = binomial(link = "logit"),
data = data_mult)
Coefficients:
Estimate Std. Error z value
(Intercept) -279.39 750813.03 0
study_hours 11.59 24056.98 0
sleep_hours 23.29 97858.23 0
Pr(>|z|)
(Intercept) 1
study_hours 1
sleep_hours 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 1.3460e+01 on 9 degrees of freedom
Residual deviance: 4.7863e-10 on 7 degrees of freedom
AIC: 6
Number of Fisher Scoring iterations: 25
Output (simplified):
``` Call: glm(formula = pass_fail ~ study_hours + sleep_hours, family
= binomial(link = “logit”), data = data_mult)
Coefficients: Estimate Std. Error z value Pr(>|z|)
(Intercept
LS0tDQp0aXRsZTogIkxvZ2lzdGljIFJlZ3Jlc3Npb24iDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoqKkxvZ2lzdGljIHJlZ3Jlc3Npb24qKiBpcyBhIHN0YXRpc3RpY2FsIG1ldGhvZCB1c2VkIHRvIG1vZGVsIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBhIGJpbmFyeSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIG9uZSBvciBtb3JlIGluZGVwZW5kZW50IHZhcmlhYmxlcy4gVGhlIGRlcGVuZGVudCB2YXJpYWJsZSBpbiBsb2dpc3RpYyByZWdyZXNzaW9uIGlzIGJpbmFyeSwgbWVhbmluZyBpdCBoYXMgb25seSB0d28gcG9zc2libGUgb3V0Y29tZXMgKGUuZy4sICJzdWNjZXNzL2ZhaWx1cmUsIiAieWVzL25vLCIgb3IgIjAvMSIpLiANCg0KVGhlIGdvYWwgb2YgbG9naXN0aWMgcmVncmVzc2lvbiBpcyB0byBtb2RlbCB0aGUgcHJvYmFiaWxpdHkgdGhhdCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGVxdWFscyAxIChzdWNjZXNzKSBhcyBhIGZ1bmN0aW9uIG9mIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMuDQoNClRoZSAqKmxvZ2lzdGljIGZ1bmN0aW9uKiogKGFsc28ga25vd24gYXMgdGhlIHNpZ21vaWQgZnVuY3Rpb24pIG1hcHMgYW55IHJlYWwtdmFsdWVkIG51bWJlciB0byBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMSwgcmVwcmVzZW50aW5nIGEgcHJvYmFiaWxpdHk6DQpcWw0KUChZID0gMSB8IFgpID0gXGZyYWN7MX17MSArIGVeey0oXGJldGFfMCArIFxiZXRhXzEgWF8xICsgXGJldGFfMiBYXzIgKyBcZG90cyArIFxiZXRhX24gWF9uKX19DQpcXQ0KV2hlcmU6DQotIFwoIFAoWSA9IDEgfCBYKSBcKSBpcyB0aGUgcHJvYmFiaWxpdHkgdGhhdCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIFwoIFkgXCkgZXF1YWxzIDEgKHN1Y2Nlc3MpLA0KLSBcKCBcYmV0YV8wIFwpIGlzIHRoZSBpbnRlcmNlcHQsDQotIFwoIFxiZXRhXzEsIFxkb3RzLCBcYmV0YV9uIFwpIGFyZSB0aGUgY29lZmZpY2llbnRzIGZvciB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzIFwoIFhfMSwgXGRvdHMsIFhfbiBcKS4NCg0KIyMjIyAqKkFkdmFudGFnZXMqKjoNCg0KLSAqKkludGVycHJldGFibGUgY29lZmZpY2llbnRzKio6IFRoZSBjb2VmZmljaWVudHMgb2YgbG9naXN0aWMgcmVncmVzc2lvbiByZXByZXNlbnQgdGhlIGNoYW5nZSBpbiB0aGUgbG9nLW9kZHMgb2YgdGhlIG91dGNvbWUgZm9yIGEgb25lLXVuaXQgY2hhbmdlIGluIHRoZSBwcmVkaWN0b3IuDQoNCi0gKipQcm9iYWJpbGlzdGljIG91dHB1dCoqOiBMb2dpc3RpYyByZWdyZXNzaW9uIHByb3ZpZGVzIGEgcHJvYmFiaWxpdHkgb2YgdGhlIG91dGNvbWUsIHdoaWNoIGlzIHVzZWZ1bCBpbiBtYW55IHJlYWwtd29ybGQgYXBwbGljYXRpb25zLg0KDQotICoqTGVzcyBzdHJpY3QgYXNzdW1wdGlvbnMqKjogVW5saWtlIGxpbmVhciByZWdyZXNzaW9uLCBsb2dpc3RpYyByZWdyZXNzaW9uIGRvZXMgbm90IGFzc3VtZSBhIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgaW5kZXBlbmRlbnQgYW5kIGRlcGVuZGVudCB2YXJpYWJsZXMuDQoNCiMjIyMgKipEaXNhZHZhbnRhZ2VzKio6DQoNCi0gKipMaW5lYXJpdHkgaW4gbG9nLW9kZHMqKjogTG9naXN0aWMgcmVncmVzc2lvbiBhc3N1bWVzIGEgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgYW5kIHRoZSBsb2ctb2RkcyBvZiB0aGUgb3V0Y29tZS4NCg0KLSAqKk5vdCBzdWl0YWJsZSBmb3IgY29udGludW91cyBvdXRjb21lcyoqOiBMb2dpc3RpYyByZWdyZXNzaW9uIGNhbiBvbmx5IGhhbmRsZSBiaW5hcnkgb3IgY2F0ZWdvcmljYWwgb3V0Y29tZXMuDQoNCi0gKipNdWx0aWNvbGxpbmVhcml0eSoqOiBIaWdobHkgY29ycmVsYXRlZCBpbmRlcGVuZGVudCB2YXJpYWJsZXMgY2FuIGNhdXNlIGlzc3VlcyB3aXRoIGNvZWZmaWNpZW50IGVzdGltYXRpb24uDQoNCiMjIyMgKipBcHBsaWNhdGlvbnMqKjoNCg0KLSAqKk1lZGljYWwgcmVzZWFyY2gqKjogUHJlZGljdGluZyB0aGUgcHJvYmFiaWxpdHkgb2YgYSBkaXNlYXNlIChlLmcuLCBjYW5jZXIgZGlhZ25vc2lzIGJhc2VkIG9uIGFnZSBhbmQgbGlmZXN0eWxlIGZhY3RvcnMpLg0KDQotICoqTWFya2V0aW5nKio6IFByZWRpY3Rpbmcgd2hldGhlciBhIGN1c3RvbWVyIHdpbGwgcHVyY2hhc2UgYSBwcm9kdWN0IGJhc2VkIG9uIHRoZWlyIGRlbW9ncmFwaGljcyBhbmQgYnJvd3NpbmcgaGlzdG9yeS4NCg0KLSAqKkNyZWRpdCBzY29yaW5nKio6IEVzdGltYXRpbmcgdGhlIGxpa2VsaWhvb2Qgb2YgYSBib3Jyb3dlciBkZWZhdWx0aW5nIG9uIGEgbG9hbiBiYXNlZCBvbiBmaW5hbmNpYWwgaGlzdG9yeSBhbmQgb3RoZXIgZmFjdG9ycy4NCg0KIyMjIyAqKlByb3MqKjoNCi0gRWFzeSB0byBpbXBsZW1lbnQgYW5kIGludGVycHJldC4NCi0gV29ya3Mgd2VsbCB3aGVuIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBpbmRlcGVuZGVudCB2YXJpYWJsZXMgYW5kIHRoZSBiaW5hcnkgb3V0Y29tZSBpcyBhcHByb3hpbWF0ZWx5IGxpbmVhciBpbiB0aGUgbG9nLW9kZHMuDQotIENhbiBoYW5kbGUgYm90aCBjb250aW51b3VzIGFuZCBjYXRlZ29yaWNhbCBwcmVkaWN0b3IgdmFyaWFibGVzLg0KDQojIyMjICoqQ29ucyoqOg0KLSBBc3N1bWVzIGEgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgYW5kIHRoZSBsb2ctb2RkcyBvZiB0aGUgb3V0Y29tZS4NCi0gU2Vuc2l0aXZlIHRvIG91dGxpZXJzIGFuZCBtdWx0aWNvbGxpbmVhcml0eS4NCi0gQ2FuIGJlY29tZSB1bnN0YWJsZSB3aXRoIHNtYWxsIGRhdGFzZXRzIG9yIGlmIHRoZSBjbGFzc2VzIGFyZSBoaWdobHkgaW1iYWxhbmNlZC4NCg0KLS0tDQoNCiMjIyAqKkxvZ2lzdGljIFJlZ3Jlc3Npb24gRXhhbXBsZSBpbiBSKioNCg0KSW4gdGhpcyBleGFtcGxlLCB3ZeKAmWxsIHVzZSBsb2dpc3RpYyByZWdyZXNzaW9uIHRvIG1vZGVsIHdoZXRoZXIgc3R1ZGVudHMgcGFzcyBvciBmYWlsIGFuIGV4YW0gYmFzZWQgb24gdGhlIG51bWJlciBvZiBob3VycyB0aGV5IHN0dWRpZWQuIFRoZSBvdXRjb21lIGlzIGJpbmFyeSAocGFzcyA9IDEsIGZhaWwgPSAwKS4NCg0KIyMjIyAqKlN0ZXAgMTogQ3JlYXRlIHRoZSBEYXRhKioNCg0KV2XigJlsbCBzaW11bGF0ZSBhIGRhdGFzZXQgd2l0aCB0aGUgbnVtYmVyIG9mIHN0dWR5IGhvdXJzIGFuZCB0aGUgcGFzcy9mYWlsIG91dGNvbWUgZm9yIGVhY2ggc3R1ZGVudC4NCg0KYGBge3J9DQojIENyZWF0ZSB0aGUgZGF0YTogc3R1ZHkgaG91cnMgYW5kIHBhc3MvZmFpbCBvdXRjb21lDQpzZXQuc2VlZCgxMjMpDQpzdHVkeV9ob3VycyA8LSBjKDIsIDQsIDYsIDgsIDEwLCAxMiwgMTQsIDE2LCAxOCwgMjApICAjIEluZGVwZW5kZW50IHZhcmlhYmxlDQpwYXNzX2ZhaWwgPC0gYygwLCAwLCAwLCAwLCAxLCAxLCAxLCAxLCAxLCAxKSAgIyBEZXBlbmRlbnQgdmFyaWFibGUgKDAgPSBmYWlsLCAxID0gcGFzcykNCg0KIyBDb21iaW5lIGludG8gYSBkYXRhIGZyYW1lDQpkYXRhIDwtIGRhdGEuZnJhbWUoc3R1ZHlfaG91cnMsIHBhc3NfZmFpbCkNCmhlYWQoZGF0YSkNCmBgYA0KDQoNClRoZSBkYXRhc2V0IGNvbnRhaW5zIDEwIG9ic2VydmF0aW9ucyB3aXRoIHN0dWR5IGhvdXJzIGFzIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZSBhbmQgcGFzcy9mYWlsIGFzIHRoZSBiaW5hcnkgZGVwZW5kZW50IHZhcmlhYmxlICgwID0gZmFpbCwgMSA9IHBhc3MpLg0KDQojIyMjICoqU3RlcCAyOiBGaXQgdGhlIExvZ2lzdGljIFJlZ3Jlc3Npb24gTW9kZWwqKg0KDQpXZSBjYW4gdXNlIHRoZSAqKmBnbG0oKWAqKiBmdW5jdGlvbiBpbiBSIHRvIGZpdCB0aGUgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbC4gVGhlICoqYGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAibG9naXQiKWAqKiBzcGVjaWZpZXMgdGhhdCB3ZSBhcmUgdXNpbmcgYSBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsIHdpdGggdGhlIGxvZ2l0IGxpbmsgZnVuY3Rpb24uDQoNCmBgYHtyfQ0KIyBGaXQgdGhlIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwNCmxvZ2l0X21vZGVsIDwtIGdsbShwYXNzX2ZhaWwgfiBzdHVkeV9ob3VycywgZGF0YSA9IGRhdGEsIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAibG9naXQiKSkNCg0KIyBEaXNwbGF5IHRoZSBzdW1tYXJ5IG9mIHRoZSBtb2RlbA0Kc3VtbWFyeShsb2dpdF9tb2RlbCkNCmBgYA0KDQoNCiMjIyMgKipPdXRwdXQqKiAoc2ltcGxpZmllZCk6DQpgYGANCkNhbGw6DQpnbG0oZm9ybXVsYSA9IHBhc3NfZmFpbCB+IHN0dWR5X2hvdXJzLCBmYW1pbHkgPSBiaW5vbWlhbChsaW5rID0gImxvZ2l0IiksIA0KICAgIGRhdGEgPSBkYXRhKQ0KDQpDb2VmZmljaWVudHM6DQogICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB6IHZhbHVlIFByKD58enwpICAgIA0KKEludGVyY2VwdCkgIC02LjE4NTYgICAgIDIuODQzNiAgLTIuMTc1ICAgMC4wMjk2ICogIA0Kc3R1ZHlfaG91cnMgICAwLjY0MTQgICAgIDAuMjkyMCAgIDIuMTk2ICAgMC4wMjgxICogIA0KYGBgDQoNCiMjIyMgKipJbnRlcnByZXRhdGlvbioqOg0KDQotICoqSW50ZXJjZXB0IChFc3RpbWF0ZSA9IC02LjE5KSoqOiBUaGUgbG9nLW9kZHMgb2YgcGFzc2luZyB3aGVuIHN0dWR5IGhvdXJzIGFyZSAwIGlzIC02LjE5Lg0KDQotICoqU3R1ZHkgaG91cnMgKEVzdGltYXRlID0gMC42NCkqKjogRm9yIGVhY2ggYWRkaXRpb25hbCBob3VyIG9mIHN0dWR5LCB0aGUgbG9nLW9kZHMgb2YgcGFzc2luZyBpbmNyZWFzZSBieSAwLjY0Lg0KDQpCb3RoIHRoZSBpbnRlcmNlcHQgYW5kIHRoZSBjb2VmZmljaWVudCBmb3Igc3R1ZHkgaG91cnMgYXJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKHAgPCAwLjA1KS4NCg0KVGhlIGxvZ2lzdGljIHJlZ3Jlc3Npb24gZXF1YXRpb24gaW4gdGVybXMgb2YgdGhlIGxvZy1vZGRzIGlzOg0KXFsNClxsb2dcbGVmdChcZnJhY3tQKFx0ZXh0e3Bhc3N9ID0gMSl9ezEgLSBQKFx0ZXh0e3Bhc3N9ID0gMSl9XHJpZ2h0KSA9IC02LjE5ICsgMC42NCBcdGltZXMgXHRleHR7U3R1ZHkgSG91cnN9DQpcXQ0KDQojIyMjICoqU3RlcCAzOiBQcmVkaWN0aW5nIFByb2JhYmlsaXRpZXMqKg0KDQpXZSBjYW4gdXNlIHRoZSBtb2RlbCB0byBwcmVkaWN0IHRoZSBwcm9iYWJpbGl0eSBvZiBwYXNzaW5nIGZvciBhIG5ldyBzZXQgb2Ygc3R1ZHkgaG91cnMuDQoNCmBgYHtyfQ0KIyBQcmVkaWN0IHRoZSBwcm9iYWJpbGl0eSBvZiBwYXNzaW5nIGZvciBuZXcgc3R1ZHkgaG91cnMNCm5ld19zdHVkeV9ob3VycyA8LSBkYXRhLmZyYW1lKHN0dWR5X2hvdXJzID0gYyg1LCAxMCwgMTUpKQ0KcHJlZGljdGVkX3Byb2IgPC0gcHJlZGljdChsb2dpdF9tb2RlbCwgbmV3ZGF0YSA9IG5ld19zdHVkeV9ob3VycywgdHlwZSA9ICJyZXNwb25zZSIpDQoNCiMgU2hvdyB0aGUgcHJlZGljdGVkIHByb2JhYmlsaXRpZXMNCnByZWRpY3RlZF9wcm9iDQpgYGANCg0KDQojIyMjICoqT3V0cHV0Kio6DQpgYGANCiAgICAgICAgMSAgICAgICAgIDIgICAgICAgICAzIA0KMC4xMzM4NTgyIDAuNjY0OTc4NiAwLjk0ODczNjggDQpgYGANCg0KIyMjIyAqKkludGVycHJldGF0aW9uKio6DQotIEZvciBhIHN0dWRlbnQgd2hvIHN0dWRpZXMgNSBob3VycywgdGhlIHByb2JhYmlsaXR5IG9mIHBhc3NpbmcgaXMgYXBwcm94aW1hdGVseSAwLjEzICgxMyUpLg0KLSBGb3IgYSBzdHVkZW50IHdobyBzdHVkaWVzIDEwIGhvdXJzLCB0aGUgcHJvYmFiaWxpdHkgb2YgcGFzc2luZyBpcyBhcHByb3hpbWF0ZWx5IDAuNjYgKDY2JSkuDQotIEZvciBhIHN0dWRlbnQgd2hvIHN0dWRpZXMgMTUgaG91cnMsIHRoZSBwcm9iYWJpbGl0eSBvZiBwYXNzaW5nIGlzIGFwcHJveGltYXRlbHkgMC45NSAoOTUlKS4NCg0KIyMjIyAqKlN0ZXAgNDogVmlzdWFsaXplIHRoZSBMb2dpc3RpYyBDdXJ2ZSoqDQoNCkl04oCZcyBoZWxwZnVsIHRvIHZpc3VhbGl6ZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHN0dWR5IGhvdXJzIGFuZCB0aGUgcHJlZGljdGVkIHByb2JhYmlsaXR5IG9mIHBhc3NpbmcuDQoNCmBgYHtyfQ0KIyBQbG90IHRoZSBkYXRhDQpwbG90KGRhdGEkc3R1ZHlfaG91cnMsIGRhdGEkcGFzc19mYWlsLCANCiAgICAgbWFpbiA9ICJMb2dpc3RpYyBSZWdyZXNzaW9uOiBTdHVkeSBIb3VycyB2cyBQYXNzL0ZhaWwiLA0KICAgICB4bGFiID0gIlN0dWR5IEhvdXJzIiwgeWxhYiA9ICJQYXNzL0ZhaWwiLCANCiAgICAgcGNoID0gMTksIGNvbCA9ICJibHVlIikNCg0KIyBBZGQgdGhlIGxvZ2lzdGljIHJlZ3Jlc3Npb24gY3VydmUNCmN1cnZlKHByZWRpY3QobG9naXRfbW9kZWwsIG5ld2RhdGEgPSBkYXRhLmZyYW1lKHN0dWR5X2hvdXJzID0geCksIHR5cGUgPSAicmVzcG9uc2UiKSwgDQogICAgICBhZGQgPSBUUlVFLCBjb2wgPSAicmVkIikNCmBgYA0KDQoNCiMjIyMgKipJbnRlcnByZXRhdGlvbioqOg0KVGhlIHNjYXR0ZXJwbG90IHNob3dzIHRoZSBpbmRpdmlkdWFsIGRhdGEgcG9pbnRzLCB3aXRoIDAgaW5kaWNhdGluZyBmYWlsdXJlIGFuZCAxIGluZGljYXRpbmcgcGFzc2luZy4gVGhlIHJlZCBsb2dpc3RpYyBjdXJ2ZSBzaG93cyB0aGUgcHJlZGljdGVkIHByb2JhYmlsaXR5IG9mIHBhc3NpbmcgYXMgYSBmdW5jdGlvbiBvZiBzdHVkeSBob3Vycy4gVGhlIGN1cnZlIHN0YXJ0cyBsb3cgKGNsb3NlIHRvIDApIGFuZCBpbmNyZWFzZXMgYXMgc3R1ZHkgaG91cnMgaW5jcmVhc2UsIGV2ZW50dWFsbHkgbGV2ZWxpbmcgb2ZmIG5lYXIgMS4NCg0KLS0tDQoNCiMjIyAqKkxvZ2lzdGljIFJlZ3Jlc3Npb24gQXNzdW1wdGlvbnMqKjoNCg0KMS4gKipCaW5hcnkgb3V0Y29tZSoqOiBUaGUgZGVwZW5kZW50IHZhcmlhYmxlIG11c3QgYmUgYmluYXJ5Lg0KDQoyLiAqKkxpbmVhcml0eSBpbiBsb2ctb2RkcyoqOiBUaGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzIHNob3VsZCBiZSBsaW5lYXJseSByZWxhdGVkIHRvIHRoZSBsb2ctb2RkcyBvZiB0aGUgb3V0Y29tZS4NCg0KMy4gKipJbmRlcGVuZGVuY2UqKjogVGhlIG9ic2VydmF0aW9ucyBtdXN0IGJlIGluZGVwZW5kZW50IG9mIGVhY2ggb3RoZXIuDQoNCjQuICoqTm8gbXVsdGljb2xsaW5lYXJpdHkqKjogVGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcyBzaG91bGQgbm90IGJlIGhpZ2hseSBjb3JyZWxhdGVkIHdpdGggZWFjaCBvdGhlci4NCg0KLS0tDQoNCiMjIyAqKk11bHRpcGxlIExvZ2lzdGljIFJlZ3Jlc3Npb24gRXhhbXBsZSBpbiBSKioNCg0KTGV04oCZcyBleHRlbmQgdGhpcyB0byAqKm11bHRpcGxlIGxvZ2lzdGljIHJlZ3Jlc3Npb24qKiwgd2hlcmUgd2UgcHJlZGljdCB0aGUgcGFzcy9mYWlsIG91dGNvbWUgYmFzZWQgb24gYm90aCAqKnN0dWR5IGhvdXJzKiogYW5kICoqc2xlZXAgaG91cnMqKi4NCg0KIyMjIyAqKlN0ZXAgMTogQ3JlYXRlIHRoZSBEYXRhKioNCg0KV2XigJlsbCBnZW5lcmF0ZSBhIG5ldyB2YXJpYWJsZSwgKipzbGVlcCBob3VycyoqLCByZXByZXNlbnRpbmcgdGhlIG51bWJlciBvZiBob3VycyB0aGUgc3R1ZGVudCBzbGVwdCBiZWZvcmUgdGhlIGV4YW0uDQoNCmBgYHtyfQ0KIyBBZGQgc2xlZXAgaG91cnMgZGF0YQ0Kc2xlZXBfaG91cnMgPC0gYyg2LCA3LCA4LCA3LCA4LCA5LCA3LCA5LCA4LCAxMCkNCg0KIyBDb21iaW5lIGludG8gYSBkYXRhIGZyYW1lDQpkYXRhX211bHQgPC0gZGF0YS5mcmFtZShzdHVkeV9ob3Vycywgc2xlZXBfaG91cnMsIHBhc3NfZmFpbCkNCmhlYWQoZGF0YV9tdWx0KQ0KYGBgDQoNCg0KIyMjIyAqKlN0ZXAgMjogRml0IHRoZSBNdWx0aXBsZSBMb2dpc3RpYyBSZWdyZXNzaW9uIE1vZGVsKioNCg0KV2XigJlsbCBmaXQgYSBtdWx0aXBsZSBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsIHVzaW5nIGJvdGggc3R1ZHkgaG91cnMgYW5kIHNsZWVwIGhvdXJzIGFzIHByZWRpY3RvcnMuDQoNCmBgYHtyfQ0KIyBGaXQgdGhlIG11bHRpcGxlIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwNCmxvZ2l0X21vZGVsX211bHQgPC0gZ2xtKHBhc3NfZmFpbCB+IHN0dWR5X2hvdXJzICsgc2xlZXBfaG91cnMsIGRhdGEgPSBkYXRhX211bHQsIGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAibG9naXQiKSkNCg0KIyBEaXNwbGF5IHRoZSBzdW1tYXJ5IG9mIHRoZSBtb2RlbA0Kc3VtbWFyeShsb2dpdF9tb2RlbF9tdWx0KQ0KYGBgDQoNCg0KIyMjIyAqKk91dHB1dCoqIChzaW1wbGlmaWVkKToNCmBgYA0KQ2FsbDoNCmdsbShmb3JtdWxhID0gcGFzc19mYWlsIH4gc3R1ZHlfaG91cnMgKyBzbGVlcF9ob3VycywgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJsb2dpdCIpLCANCiAgICBkYXRhID0gZGF0YV9tdWx0KQ0KDQpDb2VmZmljaWVudHM6DQogICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB6IHZhbHVlIFByKD58enwpICAgIA0KKEludGVyY2VwdA==