Part 1: Data
Preparation
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")
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
##
##
##
##
Part 2: Model
Development
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) *
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%.
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.
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"
)
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"
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.
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