Introduction
This report presents Part II of the project focusing on classical
regression modeling. Building upon the exploratory data analysis (EDA)
and feature engineering from Part I, we will now construct and interpret
both linear and logistic regression models. The goal is to find:
identifying factors associated with the borrower’s
Credit Score
and predicting the likelihood of loan
Default
.
Data Preparation
Before modeling, we first load the raw data and process it using the
feature engineering function developed in Part I.
# Load the raw dataset
setwd("/Users/jeffery/Library/Mobile Documents/com~apple~CloudDocs/Documents/Documents - jMacP/WCUPA/Classes/Fall 2025/STA551/Homework/Data")
loan_data <- read.csv("BankLoanDefaultDataset.csv")
# Define the feature engineering function from Part I
create_analytical_features <- function(raw_data) {
# Step 1: Clean data
data_cleaned <- raw_data
data_cleaned$Checking_amount[data_cleaned$Checking_amount < 0] <- 0
# Step 2: Convert to factors
data_cleaned$Gender <- as.factor(data_cleaned$Gender)
data_cleaned$Marital_status <- as.factor(data_cleaned$Marital_status)
data_cleaned$Emp_status <- as.factor(data_cleaned$Emp_status)
# Step 3: Scale numerical predictors
vars_to_scale <- c("Checking_amount", "Term", "Credit_score",
"Saving_amount", "Emp_duration", "Age", "No_of_credit_acc")
scaled_data <- scale(data_cleaned[, vars_to_scale])
colnames(scaled_data) <- paste0(vars_to_scale, "_scaled")
# Step 4: Create dummy variables
dummy_vars <- model.matrix(~ Gender + Marital_status + Emp_status - 1, data = data_cleaned)
# Step 5: Combine all parts, retaining original Credit_score for transformation
binary_vars <- data_cleaned[, c("Car_loan", "Personal_loan", "Home_loan", "Education_loan", "Default")]
final_data <- cbind(Amount = data_cleaned$Amount,
Credit_score = data_cleaned$Credit_score, # Keep original Credit_score
scaled_data,
dummy_vars,
binary_vars)
return(as.data.frame(final_data))
}
# Create the final dataset for regression in a single step
regression_data <- create_analytical_features(loan_data)
Linear Regression
Analysis
Statement of the
Question
The primary goal of this linear regression analysis is
association analysis. We aim to answer the question:
What customer and loan characteristics are associated with a
customer’s Credit score
?
Understanding these associations can help identify factors linked to
better financial health.
Model Building and
Selection Process
Initial Model and
Diagnostics
We begin by fitting a full model using the original
Credit_score
as the response. We exclude
Amount
, Default
, and the scaled version of
Credit_score
from the predictors. We then assess the
model’s assumptions using diagnostic plots.
# Build the initial model using the original Credit_score
ini.model <- lm(Credit_score ~ . - Amount - Default - Credit_score_scaled, data = regression_data)
# Assess the assumptions of the initial linear model
par(mfrow = c(2, 2))
plot(ini.model)
Observations:
The diagnostic plots show a slight curve in the Residuals vs
Fitted plot, suggesting potential non-linearity. To address
this, we will use a Box-Cox plot to investigate if a power
transformation of the response variable could improve the model’s
fit.
Model
Comparison
We now have three candidate models to compare:
ini.model
: The full model on the original
Credit_score
.
transform.model
: The full model on
log(Credit_score)
.
final.model
: A simplified version of the transformed
model selected via step()
.
# Build a transformed model using log(Credit_score)
transform.model <- lm(log(Credit_score) ~ . - Amount - Default - Credit_score_scaled, data = regression_data)
# Use backward elimination to find final model from the transformed model
final.model <- step(transform.model, direction = "backward", trace = 0)
# Compare the R-squared of all three candidate models
r.ini.model <- summary(ini.model)$r.squared
r.transfd.model <- summary(transform.model)$r.squared
r.final.model <- summary(final.model)$r.squared
# Create a data frame for comparison and display it as a table
Rsquare <- data.frame(
ini.model = r.ini.model,
transfd.model = r.transfd.model,
final.model = r.final.model
)
kable(Rsquare, caption = "Coefficients of Determination (R-squared) for the Three Candidate Models")
Coefficients of Determination (R-squared) for the Three
Candidate Models
0.1425433 |
0.1491919 |
0.1456441 |
Interpretation of the
Final Model
The comparison table shows that all three models have very similar
R-squared values. The transformed model and the final simplified model
offer a slightly better fit than the initial model. Given that the
final.model
uses less variables while maintaining the
highest R-squared we select it as our final working model.
# Display the summary of the final selected model
final_lm_summary <- summary(final.model)
pander(final_lm_summary$coefficients, caption = "Summary of Final Linear Regression Model Coefficients")
Summary of Final Linear Regression Model Coefficients
(Intercept) |
6.63 |
0.003393 |
1954 |
0 |
Checking_amount_scaled |
0.008597 |
0.003408 |
2.522 |
0.01182 |
Term_scaled |
-0.01069 |
0.003346 |
-3.196 |
0.001438 |
Saving_amount_scaled |
0.00971 |
0.00345 |
2.814 |
0.004984 |
Age_scaled |
0.02693 |
0.003594 |
7.495 |
1.466e-13 |
Education_loan |
-0.0186 |
0.01039 |
-1.791 |
0.07362 |
The model’s Adjusted R-squared value is .1456, which
means that about 14.6% of the variability in the
log of Credit_score
is explained by the
predictors.
Key Findings:
- Checking_amount_scaled: The coefficient is positive
and significant. This indicates that applicants with higher checkings
tend to have a higher credit score.
- Saving_amount_scaled: This is also positively
associated with credit score. Having higher savings is linked to a
higher score.
- Term_scaled: Longer loan durations is negatively
associated with a higher credit score, suggesting longer term loans are
taken by people with lower credit scores.
- Age_scaled As borrower’s age increases, their
credit score increases.
Logistic Regression
Analysis
Statement of the
Question
The purpose of this analysis is primarily
association. We want to answer: What are the
key characteristics of a loan applicant that influence their likelihood
of defaulting?
The dataset contains the Default
variable and numerous
potential predictors.
Model Building
Full and Optimized
Models
We will start with a “full model” that includes all predictors. For
the variable selection process, we will also have a “optimized model”
containing only predictors we believe may be important.
# define the full model
full_logistic_model <- glm(Default ~ . - Amount - Credit_score, data = regression_data, family = "binomial")
# define the reduced model with practically important variables
optimized_logistic_model <- glm(Default ~ Credit_score_scaled + Checking_amount_scaled, data = regression_data, family = "binomial")
# using step() for backward selection to find the final model
# the scope is defined by the optimized and full models
final_logistic_model <- step(full_logistic_model,
scope = list(lower = formula(optimized_logistic_model), upper = formula(full_logistic_model)),
direction = "backward",
trace = 0)
Interpretation of the
Final Model
The step()
function has identified the best model based
on AIC.
# Get the summary and display it using pander for clean formatting
final_summary <- summary(final_logistic_model)
pander(final_summary$coefficients, caption = "Summary of Final Logistic Regression Model Coefficients")
Summary of Final Logistic Regression Model
Coefficients
(Intercept) |
-2.632 |
0.3837 |
-6.86 |
6.895e-12 |
Checking_amount_scaled |
-1.709 |
0.225 |
-7.595 |
3.077e-14 |
Term_scaled |
0.5333 |
0.1677 |
3.18 |
0.001474 |
Credit_score_scaled |
-0.8611 |
0.1614 |
-5.334 |
9.593e-08 |
Saving_amount_scaled |
-1.58 |
0.2073 |
-7.623 |
2.487e-14 |
Age_scaled |
-2.643 |
0.2607 |
-10.14 |
3.725e-24 |
Emp_statusunemployed |
0.6117 |
0.3375 |
1.813 |
0.06991 |
Personal_loan |
-0.8951 |
0.3335 |
-2.684 |
0.007272 |
Home_loan |
-2.79 |
0.7782 |
-3.585 |
0.0003368 |
Education_loan |
1.42 |
0.5542 |
2.563 |
0.01038 |
Key Findings:
The final model highlights several factors significantly associated
with defaulting:
- Credit_score_scaled: The coefficient is
-0.86. This is a strong negative association. A higher
credit score makes a default much less likely.
- Term_scaled: The positive coefficient
(0.53) implies that longer loan terms are associated
with higher log-odds of default.
- Checking_amount_scaled: A larger amount in the
checking account is associated with lower odds of default
(-1.7).
- Age_scaled: Younger borrowers are more likely to
default than older borrowers (-2.6).
Summary and
Discussion
The logistic regression analysis successfully identified key
predictors of loan default. Factors like a low credit
score, a low checking account balance and
a longer loan term are all associated with an increased
likelihood of default.
Conclusion
In this part of the project we successfully built both linear and
logistic regression models. The linear regression revealed that factors
like checking and savings are associated with the borrower’s
Credit_score
. The logistic regression provided strong
evidence that Credit_score
, Checking_amount
,
and Term
are critical predictors for Default
.
These statistical models have provided a foundation for understanding
the relationships within the data.
LS0tCnRpdGxlOiAnUHJvamVjdCBPbmU6IFBhcnQgSUkgLSBSZWdyZXNzaW9uIEFuYWx5c2lzJwphdXRob3I6ICdKZWZmIERlbHZhJwpkYXRlOiAiT2N0b2JlciA4LCAyMDI1IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfd2lkdGg6IDgKICAgIGZpZ19oZWlnaHQ6IDUKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMKICAgIHRoZW1lOiBsdW1lbgogICAgaGlnaGxpZ2h0OiB0YW5nbwotLS0KCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0KaDEudGl0bGUgewogIGZvbnQtc2l6ZTogMjRweDsKICBmb250LXdlaWdodDogYm9sZDsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KaDQuYXV0aG9yLCBoNC5kYXRlIHsKICBmb250LXNpemU6IDE4cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgY29sb3I6IERhcmtCbHVlOwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQpoMSB7CiAgICBmb250LXNpemU6IDIwcHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KaDIgewogICAgZm9udC1zaXplOiAxOHB4OwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBuYXZ5OwogICAgdGV4dC1hbGlnbjogbGVmdDsKfQpoMyB7CiAgICBmb250LXNpemU6IDE2cHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IG5hdnk7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9Ci5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsKICBjb250ZW50OiAiLiI7Cn0KYGBgCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7CiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikKICAgbGlicmFyeShrbml0cikKfQppZiAoIXJlcXVpcmUoInBhbmRlciIpKSB7CiAgIGluc3RhbGwucGFja2FnZXMoInBhbmRlciIpCiAgIGxpYnJhcnkocGFuZGVyKQp9CmlmICghcmVxdWlyZSgiTUFTUyIpKSB7CiAgIGluc3RhbGwucGFja2FnZXMoIk1BU1MiKQogICBsaWJyYXJ5KE1BU1MpCn0KCgprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSBOQQogICAgICAgICAgICAgICAgICAgICAgKQpgYGAKCiMgSW50cm9kdWN0aW9uCgpUaGlzIHJlcG9ydCBwcmVzZW50cyBQYXJ0IElJIG9mIHRoZSBwcm9qZWN0IGZvY3VzaW5nIG9uIGNsYXNzaWNhbCByZWdyZXNzaW9uIG1vZGVsaW5nLiBCdWlsZGluZyB1cG9uIHRoZSBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIChFREEpIGFuZCBmZWF0dXJlIGVuZ2luZWVyaW5nIGZyb20gUGFydCBJLCB3ZSB3aWxsIG5vdyBjb25zdHJ1Y3QgYW5kIGludGVycHJldCBib3RoIGxpbmVhciBhbmQgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbHMuIFRoZSBnb2FsIGlzIHRvIGZpbmQ6IGlkZW50aWZ5aW5nIGZhY3RvcnMgYXNzb2NpYXRlZCB3aXRoIHRoZSBib3Jyb3dlcidzIGBDcmVkaXQgU2NvcmVgIGFuZCBwcmVkaWN0aW5nIHRoZSBsaWtlbGlob29kIG9mIGxvYW4gYERlZmF1bHRgLgoKLS0tLS0KCiMgRGF0YSBQcmVwYXJhdGlvbgoKQmVmb3JlIG1vZGVsaW5nLCB3ZSBmaXJzdCBsb2FkIHRoZSByYXcgZGF0YSBhbmQgcHJvY2VzcyBpdCB1c2luZyB0aGUgZmVhdHVyZSBlbmdpbmVlcmluZyBmdW5jdGlvbiBkZXZlbG9wZWQgaW4gUGFydCBJLiAKCmBgYHtyIHByZXBhcmUtZGF0YX0KIyBMb2FkIHRoZSByYXcgZGF0YXNldApzZXR3ZCgiL1VzZXJzL2plZmZlcnkvTGlicmFyeS9Nb2JpbGUgRG9jdW1lbnRzL2NvbX5hcHBsZX5DbG91ZERvY3MvRG9jdW1lbnRzL0RvY3VtZW50cyAtIGpNYWNQL1dDVVBBL0NsYXNzZXMvRmFsbCAyMDI1L1NUQTU1MS9Ib21ld29yay9EYXRhIikKbG9hbl9kYXRhIDwtIHJlYWQuY3N2KCJCYW5rTG9hbkRlZmF1bHREYXRhc2V0LmNzdiIpCgojIERlZmluZSB0aGUgZmVhdHVyZSBlbmdpbmVlcmluZyBmdW5jdGlvbiBmcm9tIFBhcnQgSQpjcmVhdGVfYW5hbHl0aWNhbF9mZWF0dXJlcyA8LSBmdW5jdGlvbihyYXdfZGF0YSkgewogICMgU3RlcCAxOiBDbGVhbiBkYXRhCiAgZGF0YV9jbGVhbmVkIDwtIHJhd19kYXRhCiAgZGF0YV9jbGVhbmVkJENoZWNraW5nX2Ftb3VudFtkYXRhX2NsZWFuZWQkQ2hlY2tpbmdfYW1vdW50IDwgMF0gPC0gMAogIAogICMgU3RlcCAyOiBDb252ZXJ0IHRvIGZhY3RvcnMKICBkYXRhX2NsZWFuZWQkR2VuZGVyIDwtIGFzLmZhY3RvcihkYXRhX2NsZWFuZWQkR2VuZGVyKQogIGRhdGFfY2xlYW5lZCRNYXJpdGFsX3N0YXR1cyA8LSBhcy5mYWN0b3IoZGF0YV9jbGVhbmVkJE1hcml0YWxfc3RhdHVzKQogIGRhdGFfY2xlYW5lZCRFbXBfc3RhdHVzIDwtIGFzLmZhY3RvcihkYXRhX2NsZWFuZWQkRW1wX3N0YXR1cykKICAKICAjIFN0ZXAgMzogU2NhbGUgbnVtZXJpY2FsIHByZWRpY3RvcnMKICB2YXJzX3RvX3NjYWxlIDwtIGMoIkNoZWNraW5nX2Ftb3VudCIsICJUZXJtIiwgIkNyZWRpdF9zY29yZSIsCiAgICAgICAgICAgICAgICAgICAgICJTYXZpbmdfYW1vdW50IiwgIkVtcF9kdXJhdGlvbiIsICJBZ2UiLCAiTm9fb2ZfY3JlZGl0X2FjYyIpCiAgc2NhbGVkX2RhdGEgPC0gc2NhbGUoZGF0YV9jbGVhbmVkWywgdmFyc190b19zY2FsZV0pCiAgY29sbmFtZXMoc2NhbGVkX2RhdGEpIDwtIHBhc3RlMCh2YXJzX3RvX3NjYWxlLCAiX3NjYWxlZCIpCiAgCiAgIyBTdGVwIDQ6IENyZWF0ZSBkdW1teSB2YXJpYWJsZXMKICBkdW1teV92YXJzIDwtIG1vZGVsLm1hdHJpeCh+IEdlbmRlciArIE1hcml0YWxfc3RhdHVzICsgRW1wX3N0YXR1cyAtIDEsIGRhdGEgPSBkYXRhX2NsZWFuZWQpCiAgCiAgIyBTdGVwIDU6IENvbWJpbmUgYWxsIHBhcnRzLCByZXRhaW5pbmcgb3JpZ2luYWwgQ3JlZGl0X3Njb3JlIGZvciB0cmFuc2Zvcm1hdGlvbgogIGJpbmFyeV92YXJzIDwtIGRhdGFfY2xlYW5lZFssIGMoIkNhcl9sb2FuIiwgIlBlcnNvbmFsX2xvYW4iLCAiSG9tZV9sb2FuIiwgIkVkdWNhdGlvbl9sb2FuIiwgIkRlZmF1bHQiKV0KICBmaW5hbF9kYXRhIDwtIGNiaW5kKEFtb3VudCA9IGRhdGFfY2xlYW5lZCRBbW91bnQsIAogICAgICAgICAgICAgICAgICAgICAgQ3JlZGl0X3Njb3JlID0gZGF0YV9jbGVhbmVkJENyZWRpdF9zY29yZSwgIyBLZWVwIG9yaWdpbmFsIENyZWRpdF9zY29yZQogICAgICAgICAgICAgICAgICAgICAgc2NhbGVkX2RhdGEsIAogICAgICAgICAgICAgICAgICAgICAgZHVtbXlfdmFycywgCiAgICAgICAgICAgICAgICAgICAgICBiaW5hcnlfdmFycykKICAKICByZXR1cm4oYXMuZGF0YS5mcmFtZShmaW5hbF9kYXRhKSkKfQoKIyBDcmVhdGUgdGhlIGZpbmFsIGRhdGFzZXQgZm9yIHJlZ3Jlc3Npb24gaW4gYSBzaW5nbGUgc3RlcApyZWdyZXNzaW9uX2RhdGEgPC0gY3JlYXRlX2FuYWx5dGljYWxfZmVhdHVyZXMobG9hbl9kYXRhKQpgYGAKCi0tLS0tCgojIExpbmVhciBSZWdyZXNzaW9uIEFuYWx5c2lzCgojIyBTdGF0ZW1lbnQgb2YgdGhlIFF1ZXN0aW9uCgpUaGUgcHJpbWFyeSBnb2FsIG9mIHRoaXMgbGluZWFyIHJlZ3Jlc3Npb24gYW5hbHlzaXMgaXMgKiphc3NvY2lhdGlvbiBhbmFseXNpcyoqLiBXZSBhaW0gdG8gYW5zd2VyIHRoZSBxdWVzdGlvbjogKipXaGF0IGN1c3RvbWVyIGFuZCBsb2FuIGNoYXJhY3RlcmlzdGljcyBhcmUgYXNzb2NpYXRlZCB3aXRoIGEgY3VzdG9tZXIncyBgQ3JlZGl0IHNjb3JlYD8qKgoKVW5kZXJzdGFuZGluZyB0aGVzZSBhc3NvY2lhdGlvbnMgY2FuIGhlbHAgaWRlbnRpZnkgZmFjdG9ycyBsaW5rZWQgdG8gYmV0dGVyIGZpbmFuY2lhbCBoZWFsdGguCgojIyBNb2RlbCBCdWlsZGluZyBhbmQgU2VsZWN0aW9uIFByb2Nlc3MKCiMjIyBJbml0aWFsIE1vZGVsIGFuZCBEaWFnbm9zdGljcwoKV2UgYmVnaW4gYnkgZml0dGluZyBhIGZ1bGwgbW9kZWwgdXNpbmcgdGhlIG9yaWdpbmFsIGBDcmVkaXRfc2NvcmVgIGFzIHRoZSByZXNwb25zZS4gV2UgZXhjbHVkZSBgQW1vdW50YCwgYERlZmF1bHRgLCBhbmQgdGhlIHNjYWxlZCB2ZXJzaW9uIG9mIGBDcmVkaXRfc2NvcmVgIGZyb20gdGhlIHByZWRpY3RvcnMuIFdlIHRoZW4gYXNzZXNzIHRoZSBtb2RlbCdzIGFzc3VtcHRpb25zIHVzaW5nIGRpYWdub3N0aWMgcGxvdHMuCgpgYGB7ciBpbml0aWFsLWxtLCBmaWcuY2FwPSJEaWFnbm9zdGljIFBsb3RzIGZvciB0aGUgSW5pdGlhbCBMaW5lYXIgTW9kZWwifQojIEJ1aWxkIHRoZSBpbml0aWFsIG1vZGVsIHVzaW5nIHRoZSBvcmlnaW5hbCBDcmVkaXRfc2NvcmUKaW5pLm1vZGVsIDwtIGxtKENyZWRpdF9zY29yZSB+IC4gLSBBbW91bnQgLSBEZWZhdWx0IC0gQ3JlZGl0X3Njb3JlX3NjYWxlZCwgZGF0YSA9IHJlZ3Jlc3Npb25fZGF0YSkKCiMgQXNzZXNzIHRoZSBhc3N1bXB0aW9ucyBvZiB0aGUgaW5pdGlhbCBsaW5lYXIgbW9kZWwKcGFyKG1mcm93ID0gYygyLCAyKSkKcGxvdChpbmkubW9kZWwpCnBhcihtZnJvdyA9IGMoMSwgMSkpCmBgYAoKKipPYnNlcnZhdGlvbnM6KioKClRoZSBkaWFnbm9zdGljIHBsb3RzIHNob3cgYSBzbGlnaHQgY3VydmUgaW4gdGhlICoqUmVzaWR1YWxzIHZzIEZpdHRlZCoqIHBsb3QsIHN1Z2dlc3RpbmcgcG90ZW50aWFsIG5vbi1saW5lYXJpdHkuIFRvIGFkZHJlc3MgdGhpcywgd2Ugd2lsbCB1c2UgYSBCb3gtQ294IHBsb3QgdG8gaW52ZXN0aWdhdGUgaWYgYSBwb3dlciB0cmFuc2Zvcm1hdGlvbiBvZiB0aGUgcmVzcG9uc2UgdmFyaWFibGUgY291bGQgaW1wcm92ZSB0aGUgbW9kZWwncyBmaXQuCgojIyMgVHJhbnNmb3JtYXRpb24KCmBgYHtyIGJveC1jb3gtdHJhbnNmb3JtYXRpb24sIGZpZy5jYXA9IkJveC1Db3ggUGxvdCBmb3IgUG93ZXIgVHJhbnNmb3JtYXRpb24ifQojIFVzZSBCb3gtQ294IHRvIGZpbmQgYSBwb3RlbnRpYWwgdHJhbnNmb3JtYXRpb24gZm9yIHRoZSByZXNwb25zZSB2YXJpYWJsZQpib3hjb3goaW5pLm1vZGVsLCBsYW1iZGEgPSBzZXEoLTIsIDIsIDAuMSkpCmBgYAoKVGhlIEJveC1Db3ggcGxvdCBpbmRpY2F0ZXMgdGhhdCBhIGxhbWJkYSB2YWx1ZSBuZWFyIDAgbWF5IGJlIG9wdGltYWwsIHN1Z2dlc3RpbmcgYSAqKmxvZyB0cmFuc2Zvcm1hdGlvbioqIGNvdWxkIGJlIGJlbmVmaWNpYWwuIFdlIHdpbGwgY3JlYXRlIGEgbmV3IG1vZGVsIHdpdGggYGxvZyhDcmVkaXRfc2NvcmUpYCBhcyB0aGUgcmVzcG9uc2UuCgojIyMgTW9kZWwgQ29tcGFyaXNvbgoKV2Ugbm93IGhhdmUgdGhyZWUgY2FuZGlkYXRlIG1vZGVscyB0byBjb21wYXJlOgoKMS4gIGBpbmkubW9kZWxgOiBUaGUgZnVsbCBtb2RlbCBvbiB0aGUgb3JpZ2luYWwgYENyZWRpdF9zY29yZWAuCjIuICBgdHJhbnNmb3JtLm1vZGVsYDogVGhlIGZ1bGwgbW9kZWwgb24gYGxvZyhDcmVkaXRfc2NvcmUpYC4KMy4gIGBmaW5hbC5tb2RlbGA6IEEgc2ltcGxpZmllZCB2ZXJzaW9uIG9mIHRoZSB0cmFuc2Zvcm1lZCBtb2RlbCBzZWxlY3RlZCB2aWEgYHN0ZXAoKWAuCgpgYGB7ciBjb21wYXJpc29uLWNyZWRpdC1zY29yZX0KIyBCdWlsZCBhIHRyYW5zZm9ybWVkIG1vZGVsIHVzaW5nIGxvZyhDcmVkaXRfc2NvcmUpCnRyYW5zZm9ybS5tb2RlbCA8LSBsbShsb2coQ3JlZGl0X3Njb3JlKSB+IC4gLSBBbW91bnQgLSBEZWZhdWx0IC0gQ3JlZGl0X3Njb3JlX3NjYWxlZCwgZGF0YSA9IHJlZ3Jlc3Npb25fZGF0YSkKCiMgVXNlIGJhY2t3YXJkIGVsaW1pbmF0aW9uIHRvIGZpbmQgZmluYWwgbW9kZWwgZnJvbSB0aGUgdHJhbnNmb3JtZWQgbW9kZWwKZmluYWwubW9kZWwgPC0gc3RlcCh0cmFuc2Zvcm0ubW9kZWwsIGRpcmVjdGlvbiA9ICJiYWNrd2FyZCIsIHRyYWNlID0gMCkKCiMgQ29tcGFyZSB0aGUgUi1zcXVhcmVkIG9mIGFsbCB0aHJlZSBjYW5kaWRhdGUgbW9kZWxzCnIuaW5pLm1vZGVsIDwtIHN1bW1hcnkoaW5pLm1vZGVsKSRyLnNxdWFyZWQKci50cmFuc2ZkLm1vZGVsIDwtIHN1bW1hcnkodHJhbnNmb3JtLm1vZGVsKSRyLnNxdWFyZWQKci5maW5hbC5tb2RlbCA8LSBzdW1tYXJ5KGZpbmFsLm1vZGVsKSRyLnNxdWFyZWQKCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSBmb3IgY29tcGFyaXNvbiBhbmQgZGlzcGxheSBpdCBhcyBhIHRhYmxlClJzcXVhcmUgPC0gZGF0YS5mcmFtZSgKICBpbmkubW9kZWwgPSByLmluaS5tb2RlbCwKICB0cmFuc2ZkLm1vZGVsID0gci50cmFuc2ZkLm1vZGVsLAogIGZpbmFsLm1vZGVsID0gci5maW5hbC5tb2RlbAopCgprYWJsZShSc3F1YXJlLCBjYXB0aW9uID0gIkNvZWZmaWNpZW50cyBvZiBEZXRlcm1pbmF0aW9uIChSLXNxdWFyZWQpIGZvciB0aGUgVGhyZWUgQ2FuZGlkYXRlIE1vZGVscyIpCmBgYAoKIyMgSW50ZXJwcmV0YXRpb24gb2YgdGhlIEZpbmFsIE1vZGVsCgpUaGUgY29tcGFyaXNvbiB0YWJsZSBzaG93cyB0aGF0IGFsbCB0aHJlZSBtb2RlbHMgaGF2ZSB2ZXJ5IHNpbWlsYXIgUi1zcXVhcmVkIHZhbHVlcy4gVGhlIHRyYW5zZm9ybWVkIG1vZGVsIGFuZCB0aGUgZmluYWwgc2ltcGxpZmllZCBtb2RlbCBvZmZlciBhIHNsaWdodGx5IGJldHRlciBmaXQgdGhhbiB0aGUgaW5pdGlhbCBtb2RlbC4gR2l2ZW4gdGhhdCB0aGUgYGZpbmFsLm1vZGVsYCB1c2VzIGxlc3MgdmFyaWFibGVzIHdoaWxlIG1haW50YWluaW5nIHRoZSBoaWdoZXN0IFItc3F1YXJlZCB3ZSBzZWxlY3QgaXQgYXMgb3VyIGZpbmFsIHdvcmtpbmcgbW9kZWwuCgpgYGB7ciBmaW5hbC1saW5lYXItc3VtbWFyeSwgcmVzdWx0cz0nYXNpcyd9CiMgRGlzcGxheSB0aGUgc3VtbWFyeSBvZiB0aGUgZmluYWwgc2VsZWN0ZWQgbW9kZWwKZmluYWxfbG1fc3VtbWFyeSA8LSBzdW1tYXJ5KGZpbmFsLm1vZGVsKQpwYW5kZXIoZmluYWxfbG1fc3VtbWFyeSRjb2VmZmljaWVudHMsIGNhcHRpb24gPSAiU3VtbWFyeSBvZiBGaW5hbCBMaW5lYXIgUmVncmVzc2lvbiBNb2RlbCBDb2VmZmljaWVudHMiKQpgYGAKClRoZSBtb2RlbCdzIEFkanVzdGVkIFItc3F1YXJlZCB2YWx1ZSBpcyAqKi4xNDU2KiosIHdoaWNoIG1lYW5zIHRoYXQgYWJvdXQgKioxNC42JSoqIG9mIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgKipsb2cgb2YgYENyZWRpdF9zY29yZWAqKiBpcyBleHBsYWluZWQgYnkgdGhlIHByZWRpY3RvcnMuCgoqKktleSBGaW5kaW5nczoqKgoKICAqICoqQ2hlY2tpbmdfYW1vdW50X3NjYWxlZDoqKiBUaGUgY29lZmZpY2llbnQgaXMgcG9zaXRpdmUgYW5kIHNpZ25pZmljYW50LiBUaGlzIGluZGljYXRlcyB0aGF0IGFwcGxpY2FudHMgd2l0aCBoaWdoZXIgY2hlY2tpbmdzIHRlbmQgdG8gaGF2ZSBhIGhpZ2hlciBjcmVkaXQgc2NvcmUuCiAgKiAqKlNhdmluZ19hbW91bnRfc2NhbGVkOioqIFRoaXMgaXMgYWxzbyBwb3NpdGl2ZWx5IGFzc29jaWF0ZWQgd2l0aCBjcmVkaXQgc2NvcmUuIEhhdmluZyBoaWdoZXIgc2F2aW5ncyBpcyBsaW5rZWQgdG8gYSBoaWdoZXIgc2NvcmUuCiAgKiAqKlRlcm1fc2NhbGVkOioqIExvbmdlciBsb2FuIGR1cmF0aW9ucyBpcyBuZWdhdGl2ZWx5IGFzc29jaWF0ZWQgd2l0aCBhIGhpZ2hlciBjcmVkaXQgc2NvcmUsIHN1Z2dlc3RpbmcgbG9uZ2VyIHRlcm0gbG9hbnMgYXJlIHRha2VuIGJ5IHBlb3BsZSB3aXRoIGxvd2VyIGNyZWRpdCBzY29yZXMuCiAgKiAqKkFnZV9zY2FsZWQqKiBBcyBib3Jyb3dlcidzIGFnZSBpbmNyZWFzZXMsIHRoZWlyIGNyZWRpdCBzY29yZSBpbmNyZWFzZXMuCgotLS0tLQoKIyBMb2dpc3RpYyBSZWdyZXNzaW9uIEFuYWx5c2lzCgojIyBTdGF0ZW1lbnQgb2YgdGhlIFF1ZXN0aW9uCgpUaGUgcHVycG9zZSBvZiB0aGlzIGFuYWx5c2lzIGlzIHByaW1hcmlseSAqKmFzc29jaWF0aW9uKiouIFdlIHdhbnQgdG8gYW5zd2VyOiAqKldoYXQgYXJlIHRoZSBrZXkgY2hhcmFjdGVyaXN0aWNzIG9mIGEgbG9hbiBhcHBsaWNhbnQgdGhhdCBpbmZsdWVuY2UgdGhlaXIgbGlrZWxpaG9vZCBvZiBkZWZhdWx0aW5nPyoqCgpUaGUgZGF0YXNldCBjb250YWlucyB0aGUgYERlZmF1bHRgIHZhcmlhYmxlIGFuZCBudW1lcm91cyBwb3RlbnRpYWwgcHJlZGljdG9ycy4KCiMjIE1vZGVsIEJ1aWxkaW5nCgojIyMgRnVsbCBhbmQgT3B0aW1pemVkIE1vZGVscwoKV2Ugd2lsbCBzdGFydCB3aXRoIGEgImZ1bGwgbW9kZWwiIHRoYXQgaW5jbHVkZXMgYWxsIHByZWRpY3RvcnMuIEZvciB0aGUgdmFyaWFibGUgc2VsZWN0aW9uIHByb2Nlc3MsIHdlIHdpbGwgYWxzbyBoYXZlIGEgIm9wdGltaXplZCBtb2RlbCIgY29udGFpbmluZyBvbmx5IHByZWRpY3RvcnMgd2UgYmVsaWV2ZSBtYXkgYmUgaW1wb3J0YW50LgoKYGBge3IgbG9naXN0aWMtbW9kZWwtYnVpbGRpbmd9CiMgZGVmaW5lIHRoZSBmdWxsIG1vZGVsCmZ1bGxfbG9naXN0aWNfbW9kZWwgPC0gZ2xtKERlZmF1bHQgfiAuIC0gQW1vdW50IC0gQ3JlZGl0X3Njb3JlLCBkYXRhID0gcmVncmVzc2lvbl9kYXRhLCBmYW1pbHkgPSAiYmlub21pYWwiKQoKIyBkZWZpbmUgdGhlIHJlZHVjZWQgbW9kZWwgd2l0aCBwcmFjdGljYWxseSBpbXBvcnRhbnQgdmFyaWFibGVzCm9wdGltaXplZF9sb2dpc3RpY19tb2RlbCA8LSBnbG0oRGVmYXVsdCB+IENyZWRpdF9zY29yZV9zY2FsZWQgKyBDaGVja2luZ19hbW91bnRfc2NhbGVkLCBkYXRhID0gcmVncmVzc2lvbl9kYXRhLCBmYW1pbHkgPSAiYmlub21pYWwiKQoKIyB1c2luZyBzdGVwKCkgZm9yIGJhY2t3YXJkIHNlbGVjdGlvbiB0byBmaW5kIHRoZSBmaW5hbCBtb2RlbAojIHRoZSBzY29wZSBpcyBkZWZpbmVkIGJ5IHRoZSBvcHRpbWl6ZWQgYW5kIGZ1bGwgbW9kZWxzCmZpbmFsX2xvZ2lzdGljX21vZGVsIDwtIHN0ZXAoZnVsbF9sb2dpc3RpY19tb2RlbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY29wZSA9IGxpc3QobG93ZXIgPSBmb3JtdWxhKG9wdGltaXplZF9sb2dpc3RpY19tb2RlbCksIHVwcGVyID0gZm9ybXVsYShmdWxsX2xvZ2lzdGljX21vZGVsKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0gImJhY2t3YXJkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjZSA9IDApCmBgYAoKIyMgSW50ZXJwcmV0YXRpb24gb2YgdGhlIEZpbmFsIE1vZGVsCgpUaGUgYHN0ZXAoKWAgZnVuY3Rpb24gaGFzIGlkZW50aWZpZWQgdGhlIGJlc3QgbW9kZWwgYmFzZWQgb24gQUlDLgoKYGBge3IgZmluYWwtbG9naXN0aWMtc3VtbWFyeSwgcmVzdWx0cz0nYXNpcyd9CiMgR2V0IHRoZSBzdW1tYXJ5IGFuZCBkaXNwbGF5IGl0IHVzaW5nIHBhbmRlciBmb3IgY2xlYW4gZm9ybWF0dGluZwpmaW5hbF9zdW1tYXJ5IDwtIHN1bW1hcnkoZmluYWxfbG9naXN0aWNfbW9kZWwpCnBhbmRlcihmaW5hbF9zdW1tYXJ5JGNvZWZmaWNpZW50cywgY2FwdGlvbiA9ICJTdW1tYXJ5IG9mIEZpbmFsIExvZ2lzdGljIFJlZ3Jlc3Npb24gTW9kZWwgQ29lZmZpY2llbnRzIikKYGBgCgoqKktleSBGaW5kaW5nczoqKgoKVGhlIGZpbmFsIG1vZGVsIGhpZ2hsaWdodHMgc2V2ZXJhbCBmYWN0b3JzIHNpZ25pZmljYW50bHkgYXNzb2NpYXRlZCB3aXRoIGRlZmF1bHRpbmc6CgogICogKipDcmVkaXRfc2NvcmVfc2NhbGVkOioqIFRoZSBjb2VmZmljaWVudCBpcyAqKi0wLjg2KiouIFRoaXMgaXMgYSBzdHJvbmcgbmVnYXRpdmUgYXNzb2NpYXRpb24uIEEgaGlnaGVyIGNyZWRpdCBzY29yZSBtYWtlcyBhIGRlZmF1bHQgbXVjaCBsZXNzIGxpa2VseS4KICAqICoqVGVybV9zY2FsZWQ6KiogVGhlIHBvc2l0aXZlIGNvZWZmaWNpZW50ICgqKjAuNTMqKikgaW1wbGllcyB0aGF0IGxvbmdlciBsb2FuIHRlcm1zIGFyZSBhc3NvY2lhdGVkIHdpdGggaGlnaGVyIGxvZy1vZGRzIG9mIGRlZmF1bHQuCiAgKiAqKkNoZWNraW5nX2Ftb3VudF9zY2FsZWQ6KiogQSBsYXJnZXIgYW1vdW50IGluIHRoZSBjaGVja2luZyBhY2NvdW50IGlzIGFzc29jaWF0ZWQgd2l0aCBsb3dlciBvZGRzIG9mIGRlZmF1bHQgKCoqLTEuNyoqKS4KICAqICoqQWdlX3NjYWxlZDoqKiBZb3VuZ2VyIGJvcnJvd2VycyBhcmUgbW9yZSBsaWtlbHkgdG8gZGVmYXVsdCB0aGFuIG9sZGVyIGJvcnJvd2VycyAoKiotMi42KiopLgoKIyMgU3VtbWFyeSBhbmQgRGlzY3Vzc2lvbgoKVGhlIGxvZ2lzdGljIHJlZ3Jlc3Npb24gYW5hbHlzaXMgc3VjY2Vzc2Z1bGx5IGlkZW50aWZpZWQga2V5IHByZWRpY3RvcnMgb2YgbG9hbiBkZWZhdWx0LiBGYWN0b3JzIGxpa2UgYSAqKmxvdyBjcmVkaXQgc2NvcmUqKiwgKiphIGxvdyBjaGVja2luZyBhY2NvdW50IGJhbGFuY2UqKiBhbmQgKiphIGxvbmdlciBsb2FuIHRlcm0qKiBhcmUgYWxsIGFzc29jaWF0ZWQgd2l0aCBhbiBpbmNyZWFzZWQgbGlrZWxpaG9vZCBvZiBkZWZhdWx0LgoKLS0tLS0KCiMgQ29uY2x1c2lvbgoKSW4gdGhpcyBwYXJ0IG9mIHRoZSBwcm9qZWN0IHdlIHN1Y2Nlc3NmdWxseSBidWlsdCBib3RoIGxpbmVhciBhbmQgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbHMuIFRoZSBsaW5lYXIgcmVncmVzc2lvbiByZXZlYWxlZCB0aGF0IGZhY3RvcnMgbGlrZSBjaGVja2luZyBhbmQgc2F2aW5ncyBhcmUgYXNzb2NpYXRlZCB3aXRoIHRoZSBib3Jyb3dlcidzIGBDcmVkaXRfc2NvcmVgLiBUaGUgbG9naXN0aWMgcmVncmVzc2lvbiBwcm92aWRlZCBzdHJvbmcgZXZpZGVuY2UgdGhhdCBgQ3JlZGl0X3Njb3JlYCwgYENoZWNraW5nX2Ftb3VudGAsIGFuZCBgVGVybWAgYXJlIGNyaXRpY2FsIHByZWRpY3RvcnMgZm9yIGBEZWZhdWx0YC4gVGhlc2Ugc3RhdGlzdGljYWwgbW9kZWxzIGhhdmUgcHJvdmlkZWQgYSBmb3VuZGF0aW9uIGZvciB1bmRlcnN0YW5kaW5nIHRoZSByZWxhdGlvbnNoaXBzIHdpdGhpbiB0aGUgZGF0YS4K