1 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.


2 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)

3 Linear Regression Analysis

3.1 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.

3.2 Model Building and Selection Process

3.2.1 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)
Diagnostic Plots for the Initial Linear Model

Diagnostic Plots for the Initial Linear Model

par(mfrow = c(1, 1))

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.

3.2.2 Transformation

# Use Box-Cox to find a potential transformation for the response variable
boxcox(ini.model, lambda = seq(-2, 2, 0.1))
Box-Cox Plot for Power Transformation

Box-Cox Plot for Power Transformation

The Box-Cox plot indicates that a lambda value near 0 may be optimal, suggesting a log transformation could be beneficial. We will create a new model with log(Credit_score) as the response.

3.2.3 Model Comparison

We now have three candidate models to compare:

  1. ini.model: The full model on the original Credit_score.
  2. transform.model: The full model on log(Credit_score).
  3. 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
ini.model transfd.model final.model
0.1425433 0.1491919 0.1456441

3.3 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
  Estimate Std. Error t value Pr(>|t|)
(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.

4 Logistic Regression Analysis

4.1 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.

4.2 Model Building

4.2.1 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)

4.3 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
  Estimate Std. Error z value Pr(>|z|)
(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).

4.4 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.


5 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