1 Part 1: Data Preparation

1.1 Load Data

Here we load the diabetes prediction dataset.

setwd("/Users/jeffery/Library/Mobile Documents/com~apple~CloudDocs/Documents/Documents - jMacP/WCUPA/Classes/Fall 2025/STA551/Project 2/Data")
diabetes.data <- read_csv("diabetes_prediction_dataset.csv")

1.2 Clean Data

We will remove the ‘Other’ category from gender since it has few observations. We also convert our target variable diabetes and categorical predictors (gender, smoking_history) into factors so the classification models can interpret them correctly.

# Filter out other gender category
diabetes.data <- diabetes.data %>%
  filter(gender != "Other")

# Convert character columns and target to factors
diabetes.data <- diabetes.data %>%
  mutate(
    diabetes = as.factor(diabetes),
    gender = as.factor(gender),
    smoking_history = as.factor(smoking_history)
  )

# Set factor levels for clarity (0 = No, 1 = Yes)
levels(diabetes.data$diabetes) <- c("No", "Yes")

# Check the structure of the prepared data
summary(diabetes.data)
##     gender           age         hypertension     heart_disease    
##  Female:58552   Min.   : 0.08   Min.   :0.00000   Min.   :0.00000  
##  Male  :41430   1st Qu.:24.00   1st Qu.:0.00000   1st Qu.:0.00000  
##                 Median :43.00   Median :0.00000   Median :0.00000  
##                 Mean   :41.89   Mean   :0.07486   Mean   :0.03943  
##                 3rd Qu.:60.00   3rd Qu.:0.00000   3rd Qu.:0.00000  
##                 Max.   :80.00   Max.   :1.00000   Max.   :1.00000  
##     smoking_history       bmi         HbA1c_level    blood_glucose_level
##  current    : 9286   Min.   :10.01   Min.   :3.500   Min.   : 80.0      
##  ever       : 4003   1st Qu.:23.63   1st Qu.:4.800   1st Qu.:100.0      
##  former     : 9352   Median :27.32   Median :5.800   Median :140.0      
##  never      :35092   Mean   :27.32   Mean   :5.528   Mean   :138.1      
##  No Info    :35810   3rd Qu.:29.58   3rd Qu.:6.200   3rd Qu.:159.0      
##  not current: 6439   Max.   :95.69   Max.   :9.000   Max.   :300.0      
##  diabetes   
##  No :91482  
##  Yes: 8500  
##             
##             
##             
## 

2 Part 2: Model Development

2.1 Build Tree with rpart

We will use the rpart library to build our decision tree. We fit a model using all available predictors to predict the diabetes outcome.

# Build the decision tree model
# We use method = "class" for a classification tree
tree_model <- rpart(
  formula = diabetes ~ .,
  data = diabetes.data,
  method = "class" 
)

# Print the model summary
print(tree_model)
## n= 99982 
## 
## node), split, n, loss, yval, (yprob)
##       * denotes terminal node
## 
## 1) root 99982 8500 No (0.91498470 0.08501530)  
##   2) HbA1c_level< 6.7 96087 4605 No (0.95207468 0.04792532)  
##     4) blood_glucose_level< 210 94295 2813 No (0.97016809 0.02983191) *
##     5) blood_glucose_level>=210 1792    0 Yes (0.00000000 1.00000000) *
##   3) HbA1c_level>=6.7 3895    0 Yes (0.00000000 1.00000000) *

2.2 Visualize the Tree

We can use the rpart.plot package to create a clean visual of the tree structure. This helps in understanding the rules the model learned.

# Plot the tree
rpart.plot(tree_model, main = "Decision Tree for Diabetes Prediction")

In the plot, the tree first splits the data based on an HbA1c_level threshold of 6.7. If a patient’s level is 6.7 or higher (the ‘no’ path, accounting for 4% of the data), the model immediately predicts ‘Yes’ for diabetes. For the 96% of patients with a lower HbA1c level, the model asks a second question: is their blood_glucose_level less than 210? This final split results in a ‘No’ prediction for 94% of the total dataset and a ‘Yes’ prediction for the remaining 2%.

3 Part 3: Model Comparison (ROC/AUC)

We will evaluate the new model using ROC-AUC. For comparison, we will also build the Full Logistic Model and plot both ROC curves together.

3.1 Logistic Model

This chunk builds the full logistic regression model to use as a baseline.

# Build the full logistic model
glm_full <- glm(
  formula = diabetes ~ .,
  data = diabetes.data,
  family = "binomial"
)

3.2 Calculate Predictions & AUC

Now we get the probabilities for both models and calculate their respective AUC scores.

# Get probabilities for the GLM model
glm_probs <- predict(glm_full, type = "response")

# Get probabilities for the Decision Tree model
tree_probs <- predict(tree_model, type = "prob")[, "Yes"]

# Calculate ROC curves
roc_glm <- roc(diabetes.data$diabetes, glm_probs, quiet = TRUE)
roc_tree <- roc(diabetes.data$diabetes, tree_probs, quiet = TRUE)

# Get AUC values
auc_glm <- auc(roc_glm)
auc_tree <- auc(roc_tree)

print(paste("Full GLM AUC:", round(auc_glm, 4)))
## [1] "Full GLM AUC: 0.9619"
print(paste("Decision Tree AUC:", round(auc_tree, 4)))
## [1] "Decision Tree AUC: 0.8345"

3.3 Plot ROC Curves

Finally, we plot both curves on the same graph to visually compare their performance.

# Plot the ROC curves
plot(roc_glm, col = "blue", main = "Model Comparison: GLM vs. Decision Tree")
plot(roc_tree, col = "darkgreen", add = TRUE)

legend("bottomright", 
       legend = c(paste("GLM Full (AUC:", round(auc_glm, 4), ")"),
                  paste("Decision Tree (AUC:", round(auc_tree, 4), ")")),
       col = c("blue", "darkgreen"),
       lwd = 2)

The plot compares the predictive performance of two models: the full linear model and the decision tree. The graph plots Sensitivity (true positive rate) against 1 - Specificity (false positive rate). A model’s curve bending closer to the top-left corner signifies better performance. This is quantified by the Area Under the Curve (AUC), where the GLM AUC = 0.9619 clearly outperforms the Decision Tree AUC = 0.8345, indicating it is much more accurate at correctly classifying cases.

4 Conclusion

  • Part 1 (Data Prep): The data was loaded and prepped. The gender variable was cleaned by removing the ‘Other’ category, and diabetes, gender, and smoking_history were converted to factors.

  • Part 2 (Model Development): We developed one new model:

    • Decision Tree: We built a classification tree using the rpart library to predict diabetes based on all other features. We see that two variables both HbA1c_level and blood_glucose_level can predict a segment of the data as having diabetes.
  • Part 3 (Model Comparison): We evaluated the new model by calculating its ROC-AUC on the entire dataset and compared it to the Full Logistic Model. The final AUC scores were:

    • Full GLM AUC: 0.9619
    • Decision Tree AUC: 0.8345

Based on this analysis, the Full Logistic Model continues to show stronger predictive performance (higher AUC) than the default rpart Decision Tree model. The tree model provides a simpler overview of the predictions.

LS0tCnRpdGxlOiAnUHJvamVjdCBUd286IFBhcnQgMiAtIERlY2lzaW9uIFRyZWVzJwphdXRob3I6ICdKZWZmIERlbHZhJwpkYXRlOiAiT2N0b2JlciAyOSwgMjAyNSIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIHRvY19kZXB0aDogNAogICAgZmlnX3dpZHRoOiA4CiAgICBmaWdfaGVpZ2h0OiA1CiAgICBmaWdfY2FwdGlvbjogeWVzCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgdG9jX2NvbGxhcHNlZDogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgc21vb3RoX3Njcm9sbDogeWVzCiAgICB0aGVtZTogbHVtZW4KICAgIGhpZ2hsaWdodDogdGFuZ28KLS0tCgpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9CmgxLnRpdGxlIHsKICBmb250LXNpemU6IDI0cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgY29sb3I6IERhcmtSZWQ7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9Cmg0LmF1dGhvciwgaDQuZGF0ZSB7CiAgZm9udC1zaXplOiAxOHB4OwogIGZvbnQtd2VpZ2h0OiBib2xkOwogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogIGNvbG9yOiBEYXJrQmx1ZTsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KaDEgewogICAgZm9udC1zaXplOiAyMHB4OwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBkYXJrcmVkOwogICAgdGV4dC1hbGlnbjogY2VudGVyOwp9CmgyIHsKICAgIGZvbnQtc2l6ZTogMThweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KaDMgewogICAgZm9udC1zaXplOiAxNnB4OwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBuYXZ5OwogICAgdGV4dC1hbGlnbjogbGVmdDsKfQouaGVhZGVyLXNlY3Rpb24tbnVtYmVyOjphZnRlciB7CiAgY29udGVudDogIi4iOwp9CmBgYAoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UpCgpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJwYXJ0KSAgICAgIApsaWJyYXJ5KHJwYXJ0LnBsb3QpCmxpYnJhcnkocFJPQykgICAgICAgCmBgYAoKIyBQYXJ0IDE6IERhdGEgUHJlcGFyYXRpb24KCiMjIExvYWQgRGF0YQoKSGVyZSB3ZSBsb2FkIHRoZSBkaWFiZXRlcyBwcmVkaWN0aW9uIGRhdGFzZXQuCgpgYGB7ciBsb2FkLWRhdGF9CnNldHdkKCIvVXNlcnMvamVmZmVyeS9MaWJyYXJ5L01vYmlsZSBEb2N1bWVudHMvY29tfmFwcGxlfkNsb3VkRG9jcy9Eb2N1bWVudHMvRG9jdW1lbnRzIC0gak1hY1AvV0NVUEEvQ2xhc3Nlcy9GYWxsIDIwMjUvU1RBNTUxL1Byb2plY3QgMi9EYXRhIikKZGlhYmV0ZXMuZGF0YSA8LSByZWFkX2NzdigiZGlhYmV0ZXNfcHJlZGljdGlvbl9kYXRhc2V0LmNzdiIpCmBgYAoKIyMgQ2xlYW4gRGF0YQoKV2Ugd2lsbCByZW1vdmUgdGhlICdPdGhlcicgY2F0ZWdvcnkgZnJvbSBgZ2VuZGVyYCBzaW5jZSBpdCBoYXMgZmV3IG9ic2VydmF0aW9ucy4gV2UgYWxzbyBjb252ZXJ0IG91ciB0YXJnZXQgdmFyaWFibGUgYGRpYWJldGVzYCBhbmQgY2F0ZWdvcmljYWwgcHJlZGljdG9ycyAoYGdlbmRlcmAsIGBzbW9raW5nX2hpc3RvcnlgKSBpbnRvIGZhY3RvcnMgc28gdGhlIGNsYXNzaWZpY2F0aW9uIG1vZGVscyBjYW4gaW50ZXJwcmV0IHRoZW0gY29ycmVjdGx5LgoKYGBge3IgY2xlYW4tZGF0YX0KIyBGaWx0ZXIgb3V0IG90aGVyIGdlbmRlciBjYXRlZ29yeQpkaWFiZXRlcy5kYXRhIDwtIGRpYWJldGVzLmRhdGEgJT4lCiAgZmlsdGVyKGdlbmRlciAhPSAiT3RoZXIiKQoKIyBDb252ZXJ0IGNoYXJhY3RlciBjb2x1bW5zIGFuZCB0YXJnZXQgdG8gZmFjdG9ycwpkaWFiZXRlcy5kYXRhIDwtIGRpYWJldGVzLmRhdGEgJT4lCiAgbXV0YXRlKAogICAgZGlhYmV0ZXMgPSBhcy5mYWN0b3IoZGlhYmV0ZXMpLAogICAgZ2VuZGVyID0gYXMuZmFjdG9yKGdlbmRlciksCiAgICBzbW9raW5nX2hpc3RvcnkgPSBhcy5mYWN0b3Ioc21va2luZ19oaXN0b3J5KQogICkKCiMgU2V0IGZhY3RvciBsZXZlbHMgZm9yIGNsYXJpdHkgKDAgPSBObywgMSA9IFllcykKbGV2ZWxzKGRpYWJldGVzLmRhdGEkZGlhYmV0ZXMpIDwtIGMoIk5vIiwgIlllcyIpCgojIENoZWNrIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIHByZXBhcmVkIGRhdGEKc3VtbWFyeShkaWFiZXRlcy5kYXRhKQpgYGAKCiMgUGFydCAyOiBNb2RlbCBEZXZlbG9wbWVudAoKIyMgQnVpbGQgVHJlZSB3aXRoIHJwYXJ0CgpXZSB3aWxsIHVzZSB0aGUgYHJwYXJ0YCBsaWJyYXJ5IHRvIGJ1aWxkIG91ciBkZWNpc2lvbiB0cmVlLiBXZSBmaXQgYSBtb2RlbCB1c2luZyBhbGwgYXZhaWxhYmxlIHByZWRpY3RvcnMgdG8gcHJlZGljdCB0aGUgYGRpYWJldGVzYCBvdXRjb21lLgoKYGBge3IgYnVpbGQtdHJlZX0KIyBCdWlsZCB0aGUgZGVjaXNpb24gdHJlZSBtb2RlbAojIFdlIHVzZSBtZXRob2QgPSAiY2xhc3MiIGZvciBhIGNsYXNzaWZpY2F0aW9uIHRyZWUKdHJlZV9tb2RlbCA8LSBycGFydCgKICBmb3JtdWxhID0gZGlhYmV0ZXMgfiAuLAogIGRhdGEgPSBkaWFiZXRlcy5kYXRhLAogIG1ldGhvZCA9ICJjbGFzcyIgCikKCiMgUHJpbnQgdGhlIG1vZGVsIHN1bW1hcnkKcHJpbnQodHJlZV9tb2RlbCkKYGBgCgojIyBWaXN1YWxpemUgdGhlIFRyZWUKCldlIGNhbiB1c2UgdGhlIGBycGFydC5wbG90YCBwYWNrYWdlIHRvIGNyZWF0ZSBhIGNsZWFuIHZpc3VhbCBvZiB0aGUgdHJlZSBzdHJ1Y3R1cmUuIFRoaXMgaGVscHMgaW4gdW5kZXJzdGFuZGluZyB0aGUgcnVsZXMgdGhlIG1vZGVsIGxlYXJuZWQuCgpgYGB7ciBwbG90LXRyZWV9CiMgUGxvdCB0aGUgdHJlZQpycGFydC5wbG90KHRyZWVfbW9kZWwsIG1haW4gPSAiRGVjaXNpb24gVHJlZSBmb3IgRGlhYmV0ZXMgUHJlZGljdGlvbiIpCmBgYAoKSW4gdGhlIHBsb3QsIHRoZSB0cmVlIGZpcnN0IHNwbGl0cyB0aGUgZGF0YSBiYXNlZCBvbiBhbiBgSGJBMWNfbGV2ZWxgIHRocmVzaG9sZCBvZiA2LjcuIElmIGEgcGF0aWVudCdzIGxldmVsIGlzIDYuNyBvciBoaWdoZXIgKHRoZSAnbm8nIHBhdGgsIGFjY291bnRpbmcgZm9yIDQlIG9mIHRoZSBkYXRhKSwgdGhlIG1vZGVsIGltbWVkaWF0ZWx5IHByZWRpY3RzICdZZXMnIGZvciBkaWFiZXRlcy4gRm9yIHRoZSA5NiUgb2YgcGF0aWVudHMgd2l0aCBhIGxvd2VyIGBIYkExY2AgbGV2ZWwsIHRoZSBtb2RlbCBhc2tzIGEgc2Vjb25kIHF1ZXN0aW9uOiBpcyB0aGVpciBgYmxvb2RfZ2x1Y29zZV9sZXZlbGAgbGVzcyB0aGFuIDIxMD8gVGhpcyBmaW5hbCBzcGxpdCByZXN1bHRzIGluIGEgJ05vJyBwcmVkaWN0aW9uIGZvciA5NCUgb2YgdGhlIHRvdGFsIGRhdGFzZXQgYW5kIGEgJ1llcycgcHJlZGljdGlvbiBmb3IgdGhlIHJlbWFpbmluZyAyJS4KCgojIFBhcnQgMzogTW9kZWwgQ29tcGFyaXNvbiAoUk9DL0FVQykKCldlIHdpbGwgZXZhbHVhdGUgdGhlIG5ldyBtb2RlbCB1c2luZyBST0MtQVVDLiBGb3IgY29tcGFyaXNvbiwgd2Ugd2lsbCBhbHNvIGJ1aWxkIHRoZSBGdWxsIExvZ2lzdGljIE1vZGVsIGFuZCBwbG90IGJvdGggUk9DIGN1cnZlcyB0b2dldGhlci4KCiMjIExvZ2lzdGljIE1vZGVsCgpUaGlzIGNodW5rIGJ1aWxkcyB0aGUgZnVsbCBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsIHRvIHVzZSBhcyBhIGJhc2VsaW5lLgoKYGBge3IgZ2xtLW1vZGVsfQojIEJ1aWxkIHRoZSBmdWxsIGxvZ2lzdGljIG1vZGVsCmdsbV9mdWxsIDwtIGdsbSgKICBmb3JtdWxhID0gZGlhYmV0ZXMgfiAuLAogIGRhdGEgPSBkaWFiZXRlcy5kYXRhLAogIGZhbWlseSA9ICJiaW5vbWlhbCIKKQpgYGAKCiMjIENhbGN1bGF0ZSBQcmVkaWN0aW9ucyAmIEFVQwoKTm93IHdlIGdldCB0aGUgcHJvYmFiaWxpdGllcyBmb3IgYm90aCBtb2RlbHMgYW5kIGNhbGN1bGF0ZSB0aGVpciByZXNwZWN0aXZlIEFVQyBzY29yZXMuCgpgYGB7ciB0cmVlLWF1Y30KIyBHZXQgcHJvYmFiaWxpdGllcyBmb3IgdGhlIEdMTSBtb2RlbApnbG1fcHJvYnMgPC0gcHJlZGljdChnbG1fZnVsbCwgdHlwZSA9ICJyZXNwb25zZSIpCgojIEdldCBwcm9iYWJpbGl0aWVzIGZvciB0aGUgRGVjaXNpb24gVHJlZSBtb2RlbAp0cmVlX3Byb2JzIDwtIHByZWRpY3QodHJlZV9tb2RlbCwgdHlwZSA9ICJwcm9iIilbLCAiWWVzIl0KCiMgQ2FsY3VsYXRlIFJPQyBjdXJ2ZXMKcm9jX2dsbSA8LSByb2MoZGlhYmV0ZXMuZGF0YSRkaWFiZXRlcywgZ2xtX3Byb2JzLCBxdWlldCA9IFRSVUUpCnJvY190cmVlIDwtIHJvYyhkaWFiZXRlcy5kYXRhJGRpYWJldGVzLCB0cmVlX3Byb2JzLCBxdWlldCA9IFRSVUUpCgojIEdldCBBVUMgdmFsdWVzCmF1Y19nbG0gPC0gYXVjKHJvY19nbG0pCmF1Y190cmVlIDwtIGF1Yyhyb2NfdHJlZSkKCnByaW50KHBhc3RlKCJGdWxsIEdMTSBBVUM6Iiwgcm91bmQoYXVjX2dsbSwgNCkpKQpwcmludChwYXN0ZSgiRGVjaXNpb24gVHJlZSBBVUM6Iiwgcm91bmQoYXVjX3RyZWUsIDQpKSkKYGBgCgojIyBQbG90IFJPQyBDdXJ2ZXMKCkZpbmFsbHksIHdlIHBsb3QgYm90aCBjdXJ2ZXMgb24gdGhlIHNhbWUgZ3JhcGggdG8gdmlzdWFsbHkgY29tcGFyZSB0aGVpciBwZXJmb3JtYW5jZS4KCmBgYHtyIHBsb3Qtcm9jfQojIFBsb3QgdGhlIFJPQyBjdXJ2ZXMKcGxvdChyb2NfZ2xtLCBjb2wgPSAiYmx1ZSIsIG1haW4gPSAiTW9kZWwgQ29tcGFyaXNvbjogR0xNIHZzLiBEZWNpc2lvbiBUcmVlIikKcGxvdChyb2NfdHJlZSwgY29sID0gImRhcmtncmVlbiIsIGFkZCA9IFRSVUUpCgpsZWdlbmQoImJvdHRvbXJpZ2h0IiwgCiAgICAgICBsZWdlbmQgPSBjKHBhc3RlKCJHTE0gRnVsbCAoQVVDOiIsIHJvdW5kKGF1Y19nbG0sIDQpLCAiKSIpLAogICAgICAgICAgICAgICAgICBwYXN0ZSgiRGVjaXNpb24gVHJlZSAoQVVDOiIsIHJvdW5kKGF1Y190cmVlLCA0KSwgIikiKSksCiAgICAgICBjb2wgPSBjKCJibHVlIiwgImRhcmtncmVlbiIpLAogICAgICAgbHdkID0gMikKYGBgCgpUaGUgcGxvdCBjb21wYXJlcyB0aGUgcHJlZGljdGl2ZSBwZXJmb3JtYW5jZSBvZiB0d28gbW9kZWxzOiB0aGUgZnVsbCBsaW5lYXIgbW9kZWwgYW5kIHRoZSBkZWNpc2lvbiB0cmVlLiBUaGUgZ3JhcGggcGxvdHMgU2Vuc2l0aXZpdHkgKHRydWUgcG9zaXRpdmUgcmF0ZSkgYWdhaW5zdCAxIC0gU3BlY2lmaWNpdHkgKGZhbHNlIHBvc2l0aXZlIHJhdGUpLiBBIG1vZGVsJ3MgY3VydmUgYmVuZGluZyBjbG9zZXIgdG8gdGhlIHRvcC1sZWZ0IGNvcm5lciBzaWduaWZpZXMgYmV0dGVyIHBlcmZvcm1hbmNlLiBUaGlzIGlzIHF1YW50aWZpZWQgYnkgdGhlIEFyZWEgVW5kZXIgdGhlIEN1cnZlIChBVUMpLCB3aGVyZSB0aGUgR0xNIGBBVUNgID0gMC45NjE5IGNsZWFybHkgb3V0cGVyZm9ybXMgdGhlIERlY2lzaW9uIFRyZWUgYEFVQ2AgPSAwLjgzNDUsIGluZGljYXRpbmcgaXQgaXMgbXVjaCBtb3JlIGFjY3VyYXRlIGF0IGNvcnJlY3RseSBjbGFzc2lmeWluZyBjYXNlcy4KCiMgQ29uY2x1c2lvbgoKICAqICoqUGFydCAxIChEYXRhIFByZXApKio6IFRoZSBkYXRhIHdhcyBsb2FkZWQgYW5kIHByZXBwZWQuIFRoZSBgZ2VuZGVyYCB2YXJpYWJsZSB3YXMgY2xlYW5lZCBieSByZW1vdmluZyB0aGUgJ090aGVyJyBjYXRlZ29yeSwgYW5kIGBkaWFiZXRlc2AsIGBnZW5kZXJgLCBhbmQgYHNtb2tpbmdfaGlzdG9yeWAgd2VyZSBjb252ZXJ0ZWQgdG8gZmFjdG9ycy4KCiAgKiAqKlBhcnQgMiAoTW9kZWwgRGV2ZWxvcG1lbnQpKio6IFdlIGRldmVsb3BlZCBvbmUgbmV3IG1vZGVsOgoKICAgICAgKiAqKkRlY2lzaW9uIFRyZWUqKjogV2UgYnVpbHQgYSBjbGFzc2lmaWNhdGlvbiB0cmVlIHVzaW5nIHRoZSBgcnBhcnRgIGxpYnJhcnkgdG8gcHJlZGljdCBgZGlhYmV0ZXNgIGJhc2VkIG9uIGFsbCBvdGhlciBmZWF0dXJlcy4gV2Ugc2VlIHRoYXQgdHdvIHZhcmlhYmxlcyBib3RoIGBIYkExY19sZXZlbGAgYW5kIGBibG9vZF9nbHVjb3NlX2xldmVsYCBjYW4gcHJlZGljdCBhIHNlZ21lbnQgb2YgdGhlIGRhdGEgYXMgaGF2aW5nIGRpYWJldGVzLgoKICAqICoqUGFydCAzIChNb2RlbCBDb21wYXJpc29uKSoqOiBXZSBldmFsdWF0ZWQgdGhlIG5ldyBtb2RlbCBieSBjYWxjdWxhdGluZyBpdHMgUk9DLUFVQyBvbiB0aGUgKmVudGlyZSBkYXRhc2V0KiBhbmQgY29tcGFyZWQgaXQgdG8gdGhlIEZ1bGwgTG9naXN0aWMgTW9kZWwuIFRoZSBmaW5hbCBBVUMgc2NvcmVzIHdlcmU6CgogICAgICAqICoqRnVsbCBHTE0gQVVDKio6IGByIHJvdW5kKGF1Y19nbG0sIDQpYAogICAgICAqICoqRGVjaXNpb24gVHJlZSBBVUMqKjogYHIgcm91bmQoYXVjX3RyZWUsIDQpYAoKQmFzZWQgb24gdGhpcyBhbmFseXNpcywgdGhlICoqRnVsbCBMb2dpc3RpYyBNb2RlbCoqIGNvbnRpbnVlcyB0byBzaG93IHN0cm9uZ2VyIHByZWRpY3RpdmUgcGVyZm9ybWFuY2UgKGhpZ2hlciBBVUMpIHRoYW4gdGhlIGRlZmF1bHQgYHJwYXJ0YCAqKkRlY2lzaW9uIFRyZWUqKiBtb2RlbC4gVGhlIHRyZWUgbW9kZWwgcHJvdmlkZXMgYSBzaW1wbGVyIG92ZXJ2aWV3IG9mIHRoZSBwcmVkaWN0aW9ucy4K