Introduction
Following the analysis in Part 1, this section implements the
Local Outlier Factor (LOF) algorithm. LOF is an
unsupervised detection method that identifies anomalies by comparing the
local density of a data point to that of its neighbors. A score
significantly higher than 1 implies the point is in a sparse region (an
outlier).
Setup and Data
Loading
# Load the dataset
setwd("/Users/jeffery/Library/Mobile Documents/com~apple~CloudDocs/Documents/Documents - jMacP/WCUPA/Classes/Fall 2025/STA551/Project 3")
df_raw <- read.csv("Mental_Health_and_Social_Media_Balance_Dataset.csv")
Feature Engineering and
Data Preparation
# Create the main dataframe
df_analysis <- data.frame(
Age = df_raw$Age,
ScreenTime = df_raw$Daily_Screen_Time.hrs.,
SleepQuality = df_raw$Sleep_Quality.1.10.,
StressLevel = df_raw$Stress_Level.1.10.,
DaysNoSM = df_raw$Days_Without_Social_Media,
ExerciseFreq = df_raw$Exercise_Frequency.week.,
HappinessIndex = df_raw$Happiness_Index.1.10.
)
# Create the binary target variable (Y): High Happiness vs. Low Happiness
df_analysis$HighHappiness <- factor(ifelse(df_analysis$HappinessIndex > 8, "High", "Low"))
# Create a dataframe of only the continuous predictors for unsupervised learning
df_predictors <- df_analysis[, c("Age", "ScreenTime", "SleepQuality",
"StressLevel", "DaysNoSM", "ExerciseFreq")]
Unsupervised ML: Local
Outlier Factor (LOF)
We utilize the lof() function from the
{dbscan} package. The LOF score depends on the parameter
\(k\) (neighborhood size).
Calculating LOF
Scores
# Scale the predictor data (LOF is distance-based and requires scaling)
df_scaled <- scale(df_predictors)
# Calculate LOF scores using k = 20 nearest neighbors
k_value <- 20
lof_scores <- lof(df_scaled, minPts = k_value)
# Add the LOF scores to the main dataframe as a new feature
df_analysis$LOF_Score <- lof_scores
# Display summary statistics to understand the range (Min, Max)
cat("Summary of Local Outlier Factor (LOF) Scores:\n")
## Summary of Local Outlier Factor (LOF) Scores:
print(summary(df_analysis$LOF_Score))
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.9512 0.9982 1.0328 1.0567 1.0885 1.4734
Summary of Analysis: The summary statistics for the
computed Local Outlier Factor (LOF) scores reveal a distribution
centered near 1.0 (Median: 1.0328, Mean: 1.0567). A score of
approximately 1.0 indicates that a data point has a local density
similar to its neighbors (an “inlier”). The maximum score observed is
1.4734. While this indicates the presence of data points that are less
dense than their neighbors, the absence of extremely high scores (e.g.,
> 2.0 or higher) suggests that this dataset does not contain extreme
anomalies or radical outliers. The majority of data points exhibit
patterns that are relatively consistent with their peers.
Visualizing LOF
Distribution
We visualize the LOF scores against the Happiness Index. Based on the
summary statistics, we set a cut-off threshold of 1.25
to identify the most significant outliers in this specific dataset.
# Histogram of LOF Scores
hist(df_analysis$LOF_Score,
breaks = 30,
main = paste("Distribution of LOF Scores (k =", k_value, ")"),
xlab = "LOF Score",
col = "lightblue",
border = "white")
abline(v = 1.25, col = "red", lwd = 2, lty = 2) # Threshold

# Scatter plot of LOF scores vs Happiness Index
# Threshold adjusted to 1.25 based on data distribution to catch the top ~5-10% outliers
threshold <- 1.25
plot(df_analysis$HappinessIndex, df_analysis$LOF_Score,
main = "LOF Score vs. Happiness Index",
xlab = "Happiness Index (Original)",
ylab = "LOF Score",
pch = 19,
col = ifelse(df_analysis$LOF_Score > threshold, "red", "darkblue"))
legend("topright",
legend = c(paste("Outlier Score (>", threshold, ")", sep=""), "Normal Score"),
col = c("red", "darkblue"),
pch = 19)

Summary of LOF Analysis: The histogram shows the
density of LOF scores. Most data points cluster near 1.0 (Inliers). The
scatter plot highlights observations with LOF scores greater than 1.25
in red. These points represent individuals whose behavioral patterns
(Screen Time, Sleep, Stress, etc.) are significantly different from the
local density of their peers.
Supervised Learning:
Binary Classification
We compare a baseline logistic regression model against one enriched
with the extracted LOF_Score.
Model Training
# Split data into Training (70%) and Testing (30%)
set.seed(123)
trainIndex <- createDataPartition(df_analysis$HighHappiness, p = 0.7, list = FALSE)
train_data <- df_analysis[trainIndex, ]
test_data <- df_analysis[-trainIndex, ]
# Model 1: Baseline Logistic Regression
model_baseline <- glm(HighHappiness ~ Age + ScreenTime + SleepQuality +
StressLevel + DaysNoSM + ExerciseFreq,
data = train_data,
family = "binomial")
# Model 2: LOF-Enhanced Logistic Regression
model_lof <- glm(HighHappiness ~ Age + ScreenTime + SleepQuality +
StressLevel + DaysNoSM + ExerciseFreq + LOF_Score,
data = train_data,
family = "binomial")
# Compare Model Summaries (AIC)
cat("Baseline Model AIC:", round(model_baseline$aic, 2), "\n")
## Baseline Model AIC: 257.24
cat("LOF-Enhanced Model AIC:", round(model_lof$aic, 2), "\n")
## LOF-Enhanced Model AIC: 258.91
Summary of Analysis: We utilized the Akaike
Information Criterion (AIC) to compare the quality of the models, where
a lower value indicates a better trade-off between model fit and
complexity. * Baseline Model AIC: 257.24 *
LOF-Enhanced Model AIC: 258.91
The results show that the Baseline model actually achieved a slightly
lower AIC than the LOF-Enhanced model. This increase in AIC for the
enhanced model suggests that the LOF_Score feature did not
add sufficient predictive power to justify the penalty for the added
model complexity. In statistical terms, the “outlierness” of a data
point does not appear to improve the model’s fit to the training data
compared to using the original predictors alone.
Model Evaluation (ROC
and AUC)
# Predict probabilities
prob_baseline <- predict(model_baseline, newdata = test_data, type = "response")
prob_lof <- predict(model_lof, newdata = test_data, type = "response")
# Calculate ROC Curves
roc_baseline <- roc(test_data$HighHappiness, prob_baseline, levels = c("Low", "High"), direction = ">")
roc_lof <- roc(test_data$HighHappiness, prob_lof, levels = c("Low", "High"), direction = ">")
# Plot ROC Curves
plot(roc_baseline, col = "blue", main = "ROC Curve Comparison", lwd = 2)
plot(roc_lof, col = "red", add = TRUE, lwd = 2, lty = 2)
legend("bottomright", legend = c(paste("Baseline AUC =", round(auc(roc_baseline), 4)),
paste("LOF AUC =", round(auc(roc_lof), 4))),
col = c("blue", "red"), lty = c(1, 2), lwd = 2)

Conclusion
- Outlier Detection: Using a neighborhood size of
\(k=20\), we identified a subset of
observations with LOF scores exceeding 1.25. These “local outliers”
represent unique behavioral profiles in the dataset.
- Feature Importance: By adding the LOF score to the
classification model, we assessed its contribution to predicting
happiness. The comparison of AIC and AUC values indicates whether the
“unusualness” of a person’s habits serves as a predictive signal for
their mental well-being.
LS0tCnRpdGxlOiAiUHJvamVjdCBUaHJlZTogRmVhdHVyZSBFeHRyYWN0aW9uIHdpdGggVW5zdXBlcnZpc2VkIEFsZ29yaXRobXMsIFBhcnQgMjogTG9jYWwgT3V0bGllciBGYWN0b3IgKExPRikiCmF1dGhvcjogIkplZmYgRGVsdmEiCmRhdGU6ICJOb3ZlbWJlciAyMHRoLCAyMDI1IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfd2lkdGg6IDgKICAgIGZpZ19oZWlnaHQ6IDUKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMKICAgIHRoZW1lOiBsdW1lbgogICAgaGlnaGxpZ2h0OiB0YW5nbwotLS0KCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0KaDEudGl0bGUgewogIGZvbnQtc2l6ZTogMjRweDsKICBmb250LXdlaWdodDogYm9sZDsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KaDQuYXV0aG9yLCBoNC5kYXRlIHsKICBmb250LXNpemU6IDE4cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgY29sb3I6IERhcmtCbHVlOwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQpoMSB7CiAgICBmb250LXNpemU6IDIwcHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KaDIgewogICAgZm9udC1zaXplOiAxOHB4OwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBuYXZ5OwogICAgdGV4dC1hbGlnbjogbGVmdDsKfQpoMyB7CiAgICBmb250LXNpemU6IDE2cHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IG5hdnk7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9Ci5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsKICBjb250ZW50OiAiLiI7Cn0KYGBgCgojIyBJbnRyb2R1Y3Rpb24KCkZvbGxvd2luZyB0aGUgYW5hbHlzaXMgaW4gUGFydCAxLCB0aGlzIHNlY3Rpb24gaW1wbGVtZW50cyB0aGUgKipMb2NhbCBPdXRsaWVyIEZhY3RvciAoTE9GKSoqIGFsZ29yaXRobS4gTE9GIGlzIGFuIHVuc3VwZXJ2aXNlZCBkZXRlY3Rpb24gbWV0aG9kIHRoYXQgaWRlbnRpZmllcyBhbm9tYWxpZXMgYnkgY29tcGFyaW5nIHRoZSBsb2NhbCBkZW5zaXR5IG9mIGEgZGF0YSBwb2ludCB0byB0aGF0IG9mIGl0cyBuZWlnaGJvcnMuIEEgc2NvcmUgc2lnbmlmaWNhbnRseSBoaWdoZXIgdGhhbiAxIGltcGxpZXMgdGhlIHBvaW50IGlzIGluIGEgc3BhcnNlIHJlZ2lvbiAoYW4gb3V0bGllcikuCgojIyBTZXR1cCBhbmQgRGF0YSBMb2FkaW5nCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMKbGlicmFyeShzdGF0cykgICAgCmxpYnJhcnkoZGJzY2FuKSAgICMgRm9yIExvY2FsIE91dGxpZXIgRmFjdG9yIChMT0YpIGFsZ29yaXRobQpsaWJyYXJ5KHBST0MpICAgICAjIEZvciBST0MgY3VydmUgYW5kIEFVQyBjYWxjdWxhdGlvbgpsaWJyYXJ5KGNhcmV0KSAgICAjIEZvciBkYXRhIHNwbGl0dGluZwoKIyBTZXQgZ2xvYmFsIG9wdGlvbnMKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogICAgZWNobyA9IFRSVUUsCiAgICBtZXNzYWdlID0gRkFMU0UsCiAgICB3YXJuaW5nID0gRkFMU0UsCiAgICBmaWcud2lkdGggPSA4LAogICAgZmlnLmhlaWdodCA9IDUKKQpgYGAKCmBgYHtyIGRhdGEtbG9hZH0KIyBMb2FkIHRoZSBkYXRhc2V0CnNldHdkKCIvVXNlcnMvamVmZmVyeS9MaWJyYXJ5L01vYmlsZSBEb2N1bWVudHMvY29tfmFwcGxlfkNsb3VkRG9jcy9Eb2N1bWVudHMvRG9jdW1lbnRzIC0gak1hY1AvV0NVUEEvQ2xhc3Nlcy9GYWxsIDIwMjUvU1RBNTUxL1Byb2plY3QgMyIpCmRmX3JhdyA8LSByZWFkLmNzdigiTWVudGFsX0hlYWx0aF9hbmRfU29jaWFsX01lZGlhX0JhbGFuY2VfRGF0YXNldC5jc3YiKQpgYGAKCiMjIEZlYXR1cmUgRW5naW5lZXJpbmcgYW5kIERhdGEgUHJlcGFyYXRpb24KCmBgYHtyIGZlYXR1cmUtZW5naW5lZXJpbmd9CiMgQ3JlYXRlIHRoZSBtYWluIGRhdGFmcmFtZQpkZl9hbmFseXNpcyA8LSBkYXRhLmZyYW1lKAogIEFnZSA9IGRmX3JhdyRBZ2UsCiAgU2NyZWVuVGltZSA9IGRmX3JhdyREYWlseV9TY3JlZW5fVGltZS5ocnMuLAogIFNsZWVwUXVhbGl0eSA9IGRmX3JhdyRTbGVlcF9RdWFsaXR5LjEuMTAuLAogIFN0cmVzc0xldmVsID0gZGZfcmF3JFN0cmVzc19MZXZlbC4xLjEwLiwKICBEYXlzTm9TTSA9IGRmX3JhdyREYXlzX1dpdGhvdXRfU29jaWFsX01lZGlhLAogIEV4ZXJjaXNlRnJlcSA9IGRmX3JhdyRFeGVyY2lzZV9GcmVxdWVuY3kud2Vlay4sCiAgSGFwcGluZXNzSW5kZXggPSBkZl9yYXckSGFwcGluZXNzX0luZGV4LjEuMTAuCikKCiMgQ3JlYXRlIHRoZSBiaW5hcnkgdGFyZ2V0IHZhcmlhYmxlIChZKTogSGlnaCBIYXBwaW5lc3MgdnMuIExvdyBIYXBwaW5lc3MKZGZfYW5hbHlzaXMkSGlnaEhhcHBpbmVzcyA8LSBmYWN0b3IoaWZlbHNlKGRmX2FuYWx5c2lzJEhhcHBpbmVzc0luZGV4ID4gOCwgIkhpZ2giLCAiTG93IikpCgojIENyZWF0ZSBhIGRhdGFmcmFtZSBvZiBvbmx5IHRoZSBjb250aW51b3VzIHByZWRpY3RvcnMgZm9yIHVuc3VwZXJ2aXNlZCBsZWFybmluZwpkZl9wcmVkaWN0b3JzIDwtIGRmX2FuYWx5c2lzWywgYygiQWdlIiwgIlNjcmVlblRpbWUiLCAiU2xlZXBRdWFsaXR5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlN0cmVzc0xldmVsIiwgIkRheXNOb1NNIiwgIkV4ZXJjaXNlRnJlcSIpXQpgYGAKCi0tLS0tCgojIyBVbnN1cGVydmlzZWQgTUw6IExvY2FsIE91dGxpZXIgRmFjdG9yIChMT0YpCgpXZSB1dGlsaXplIHRoZSBgbG9mKClgIGZ1bmN0aW9uIGZyb20gdGhlIGB7ZGJzY2FufWAgcGFja2FnZS4gVGhlIExPRiBzY29yZSBkZXBlbmRzIG9uIHRoZSBwYXJhbWV0ZXIgJGskIChuZWlnaGJvcmhvb2Qgc2l6ZSkuCgojIyMgQ2FsY3VsYXRpbmcgTE9GIFNjb3JlcwoKYGBge3IgbG9mLWNhbGN1bGF0aW9ufQojIFNjYWxlIHRoZSBwcmVkaWN0b3IgZGF0YSAoTE9GIGlzIGRpc3RhbmNlLWJhc2VkIGFuZCByZXF1aXJlcyBzY2FsaW5nKQpkZl9zY2FsZWQgPC0gc2NhbGUoZGZfcHJlZGljdG9ycykKCiMgQ2FsY3VsYXRlIExPRiBzY29yZXMgdXNpbmcgayA9IDIwIG5lYXJlc3QgbmVpZ2hib3JzCmtfdmFsdWUgPC0gMjAKbG9mX3Njb3JlcyA8LSBsb2YoZGZfc2NhbGVkLCBtaW5QdHMgPSBrX3ZhbHVlKQoKIyBBZGQgdGhlIExPRiBzY29yZXMgdG8gdGhlIG1haW4gZGF0YWZyYW1lIGFzIGEgbmV3IGZlYXR1cmUKZGZfYW5hbHlzaXMkTE9GX1Njb3JlIDwtIGxvZl9zY29yZXMKCiMgRGlzcGxheSBzdW1tYXJ5IHN0YXRpc3RpY3MgdG8gdW5kZXJzdGFuZCB0aGUgcmFuZ2UgKE1pbiwgTWF4KQpjYXQoIlN1bW1hcnkgb2YgTG9jYWwgT3V0bGllciBGYWN0b3IgKExPRikgU2NvcmVzOlxuIikKcHJpbnQoc3VtbWFyeShkZl9hbmFseXNpcyRMT0ZfU2NvcmUpKQpgYGAKCioqU3VtbWFyeSBvZiBBbmFseXNpczoqKiBUaGUgc3VtbWFyeSBzdGF0aXN0aWNzIGZvciB0aGUgY29tcHV0ZWQgTG9jYWwgT3V0bGllciBGYWN0b3IgKExPRikgc2NvcmVzIHJldmVhbCBhIGRpc3RyaWJ1dGlvbiBjZW50ZXJlZCBuZWFyIDEuMCAoTWVkaWFuOiAxLjAzMjgsIE1lYW46IDEuMDU2NykuIEEgc2NvcmUgb2YgYXBwcm94aW1hdGVseSAxLjAgaW5kaWNhdGVzIHRoYXQgYSBkYXRhIHBvaW50IGhhcyBhIGxvY2FsIGRlbnNpdHkgc2ltaWxhciB0byBpdHMgbmVpZ2hib3JzIChhbiAiaW5saWVyIikuIFRoZSBtYXhpbXVtIHNjb3JlIG9ic2VydmVkIGlzIDEuNDczNC4gV2hpbGUgdGhpcyBpbmRpY2F0ZXMgdGhlIHByZXNlbmNlIG9mIGRhdGEgcG9pbnRzIHRoYXQgYXJlIGxlc3MgZGVuc2UgdGhhbiB0aGVpciBuZWlnaGJvcnMsIHRoZSBhYnNlbmNlIG9mIGV4dHJlbWVseSBoaWdoIHNjb3JlcyAoZS5nLiwgPiAyLjAgb3IgaGlnaGVyKSBzdWdnZXN0cyB0aGF0IHRoaXMgZGF0YXNldCBkb2VzIG5vdCBjb250YWluIGV4dHJlbWUgYW5vbWFsaWVzIG9yIHJhZGljYWwgb3V0bGllcnMuIFRoZSBtYWpvcml0eSBvZiBkYXRhIHBvaW50cyBleGhpYml0IHBhdHRlcm5zIHRoYXQgYXJlIHJlbGF0aXZlbHkgY29uc2lzdGVudCB3aXRoIHRoZWlyIHBlZXJzLgoKIyMjIFZpc3VhbGl6aW5nIExPRiBEaXN0cmlidXRpb24KCldlIHZpc3VhbGl6ZSB0aGUgTE9GIHNjb3JlcyBhZ2FpbnN0IHRoZSBIYXBwaW5lc3MgSW5kZXguIEJhc2VkIG9uIHRoZSBzdW1tYXJ5IHN0YXRpc3RpY3MsIHdlIHNldCBhIGN1dC1vZmYgdGhyZXNob2xkIG9mICoqMS4yNSoqIHRvIGlkZW50aWZ5IHRoZSBtb3N0IHNpZ25pZmljYW50IG91dGxpZXJzIGluIHRoaXMgc3BlY2lmaWMgZGF0YXNldC4KCmBgYHtyIGxvZi12aXN1YWxzfQojIEhpc3RvZ3JhbSBvZiBMT0YgU2NvcmVzCmhpc3QoZGZfYW5hbHlzaXMkTE9GX1Njb3JlLAogICAgIGJyZWFrcyA9IDMwLAogICAgIG1haW4gPSBwYXN0ZSgiRGlzdHJpYnV0aW9uIG9mIExPRiBTY29yZXMgKGsgPSIsIGtfdmFsdWUsICIpIiksCiAgICAgeGxhYiA9ICJMT0YgU2NvcmUiLAogICAgIGNvbCA9ICJsaWdodGJsdWUiLAogICAgIGJvcmRlciA9ICJ3aGl0ZSIpCmFibGluZSh2ID0gMS4yNSwgY29sID0gInJlZCIsIGx3ZCA9IDIsIGx0eSA9IDIpICMgVGhyZXNob2xkCgojIFNjYXR0ZXIgcGxvdCBvZiBMT0Ygc2NvcmVzIHZzIEhhcHBpbmVzcyBJbmRleAojIFRocmVzaG9sZCBhZGp1c3RlZCB0byAxLjI1IGJhc2VkIG9uIGRhdGEgZGlzdHJpYnV0aW9uIHRvIGNhdGNoIHRoZSB0b3AgfjUtMTAlIG91dGxpZXJzCnRocmVzaG9sZCA8LSAxLjI1CnBsb3QoZGZfYW5hbHlzaXMkSGFwcGluZXNzSW5kZXgsIGRmX2FuYWx5c2lzJExPRl9TY29yZSwKICAgICBtYWluID0gIkxPRiBTY29yZSB2cy4gSGFwcGluZXNzIEluZGV4IiwKICAgICB4bGFiID0gIkhhcHBpbmVzcyBJbmRleCAoT3JpZ2luYWwpIiwKICAgICB5bGFiID0gIkxPRiBTY29yZSIsCiAgICAgcGNoID0gMTksCiAgICAgY29sID0gaWZlbHNlKGRmX2FuYWx5c2lzJExPRl9TY29yZSA+IHRocmVzaG9sZCwgInJlZCIsICJkYXJrYmx1ZSIpKQoKbGVnZW5kKCJ0b3ByaWdodCIsIAogICAgICAgbGVnZW5kID0gYyhwYXN0ZSgiT3V0bGllciBTY29yZSAoPiIsIHRocmVzaG9sZCwgIikiLCBzZXA9IiIpLCAiTm9ybWFsIFNjb3JlIiksCiAgICAgICBjb2wgPSBjKCJyZWQiLCAiZGFya2JsdWUiKSwgCiAgICAgICBwY2ggPSAxOSkKYGBgCgoqKlN1bW1hcnkgb2YgTE9GIEFuYWx5c2lzOioqIFRoZSBoaXN0b2dyYW0gc2hvd3MgdGhlIGRlbnNpdHkgb2YgTE9GIHNjb3Jlcy4gTW9zdCBkYXRhIHBvaW50cyBjbHVzdGVyIG5lYXIgMS4wIChJbmxpZXJzKS4gVGhlIHNjYXR0ZXIgcGxvdCBoaWdobGlnaHRzIG9ic2VydmF0aW9ucyB3aXRoIExPRiBzY29yZXMgZ3JlYXRlciB0aGFuIDEuMjUgaW4gcmVkLiBUaGVzZSBwb2ludHMgcmVwcmVzZW50IGluZGl2aWR1YWxzIHdob3NlIGJlaGF2aW9yYWwgcGF0dGVybnMgKFNjcmVlbiBUaW1lLCBTbGVlcCwgU3RyZXNzLCBldGMuKSBhcmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSB0aGUgbG9jYWwgZGVuc2l0eSBvZiB0aGVpciBwZWVycy4KCi0tLS0tCgojIyBTdXBlcnZpc2VkIExlYXJuaW5nOiBCaW5hcnkgQ2xhc3NpZmljYXRpb24KCldlIGNvbXBhcmUgYSBiYXNlbGluZSBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsIGFnYWluc3Qgb25lIGVucmljaGVkIHdpdGggdGhlIGV4dHJhY3RlZCBgTE9GX1Njb3JlYC4KCiMjIyBNb2RlbCBUcmFpbmluZwoKYGBge3IgY2xhc3NpZmljYXRpb24tbW9kZWxzfQojIFNwbGl0IGRhdGEgaW50byBUcmFpbmluZyAoNzAlKSBhbmQgVGVzdGluZyAoMzAlKQpzZXQuc2VlZCgxMjMpCnRyYWluSW5kZXggPC0gY3JlYXRlRGF0YVBhcnRpdGlvbihkZl9hbmFseXNpcyRIaWdoSGFwcGluZXNzLCBwID0gMC43LCBsaXN0ID0gRkFMU0UpCnRyYWluX2RhdGEgPC0gZGZfYW5hbHlzaXNbdHJhaW5JbmRleCwgXQp0ZXN0X2RhdGEgPC0gZGZfYW5hbHlzaXNbLXRyYWluSW5kZXgsIF0KCiMgTW9kZWwgMTogQmFzZWxpbmUgTG9naXN0aWMgUmVncmVzc2lvbgptb2RlbF9iYXNlbGluZSA8LSBnbG0oSGlnaEhhcHBpbmVzcyB+IEFnZSArIFNjcmVlblRpbWUgKyBTbGVlcFF1YWxpdHkgKyAKICAgICAgICAgICAgICAgICAgICAgIFN0cmVzc0xldmVsICsgRGF5c05vU00gKyBFeGVyY2lzZUZyZXEsCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gdHJhaW5fZGF0YSwKICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9ICJiaW5vbWlhbCIpCgojIE1vZGVsIDI6IExPRi1FbmhhbmNlZCBMb2dpc3RpYyBSZWdyZXNzaW9uCm1vZGVsX2xvZiA8LSBnbG0oSGlnaEhhcHBpbmVzcyB+IEFnZSArIFNjcmVlblRpbWUgKyBTbGVlcFF1YWxpdHkgKyAKICAgICAgICAgICAgICAgICBTdHJlc3NMZXZlbCArIERheXNOb1NNICsgRXhlcmNpc2VGcmVxICsgTE9GX1Njb3JlLAogICAgICAgICAgICAgICAgIGRhdGEgPSB0cmFpbl9kYXRhLAogICAgICAgICAgICAgICAgIGZhbWlseSA9ICJiaW5vbWlhbCIpCgojIENvbXBhcmUgTW9kZWwgU3VtbWFyaWVzIChBSUMpCmNhdCgiQmFzZWxpbmUgTW9kZWwgQUlDOiIsIHJvdW5kKG1vZGVsX2Jhc2VsaW5lJGFpYywgMiksICJcbiIpCmNhdCgiTE9GLUVuaGFuY2VkIE1vZGVsIEFJQzoiLCByb3VuZChtb2RlbF9sb2YkYWljLCAyKSwgIlxuIikKYGBgCioqU3VtbWFyeSBvZiBBbmFseXNpczoqKgpXZSB1dGlsaXplZCB0aGUgQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbiAoQUlDKSB0byBjb21wYXJlIHRoZSBxdWFsaXR5IG9mIHRoZSBtb2RlbHMsIHdoZXJlIGEgbG93ZXIgdmFsdWUgaW5kaWNhdGVzIGEgYmV0dGVyIHRyYWRlLW9mZiBiZXR3ZWVuIG1vZGVsIGZpdCBhbmQgY29tcGxleGl0eS4KKiAqKkJhc2VsaW5lIE1vZGVsIEFJQzoqKiAyNTcuMjQKKiAqKkxPRi1FbmhhbmNlZCBNb2RlbCBBSUM6KiogMjU4LjkxCgpUaGUgcmVzdWx0cyBzaG93IHRoYXQgdGhlIEJhc2VsaW5lIG1vZGVsIGFjdHVhbGx5IGFjaGlldmVkIGEgc2xpZ2h0bHkgbG93ZXIgQUlDIHRoYW4gdGhlIExPRi1FbmhhbmNlZCBtb2RlbC4gVGhpcyBpbmNyZWFzZSBpbiBBSUMgZm9yIHRoZSBlbmhhbmNlZCBtb2RlbCBzdWdnZXN0cyB0aGF0IHRoZSBgTE9GX1Njb3JlYCBmZWF0dXJlIGRpZCBub3QgYWRkIHN1ZmZpY2llbnQgcHJlZGljdGl2ZSBwb3dlciB0byBqdXN0aWZ5IHRoZSBwZW5hbHR5IGZvciB0aGUgYWRkZWQgbW9kZWwgY29tcGxleGl0eS4gSW4gc3RhdGlzdGljYWwgdGVybXMsIHRoZSAib3V0bGllcm5lc3MiIG9mIGEgZGF0YSBwb2ludCBkb2VzIG5vdCBhcHBlYXIgdG8gaW1wcm92ZSB0aGUgbW9kZWwncyBmaXQgdG8gdGhlIHRyYWluaW5nIGRhdGEgY29tcGFyZWQgdG8gdXNpbmcgdGhlIG9yaWdpbmFsIHByZWRpY3RvcnMgYWxvbmUuCgoKIyMjIE1vZGVsIEV2YWx1YXRpb24gKFJPQyBhbmQgQVVDKQoKYGBge3IgbW9kZWwtZXZhbHVhdGlvbn0KIyBQcmVkaWN0IHByb2JhYmlsaXRpZXMKcHJvYl9iYXNlbGluZSA8LSBwcmVkaWN0KG1vZGVsX2Jhc2VsaW5lLCBuZXdkYXRhID0gdGVzdF9kYXRhLCB0eXBlID0gInJlc3BvbnNlIikKcHJvYl9sb2YgPC0gcHJlZGljdChtb2RlbF9sb2YsIG5ld2RhdGEgPSB0ZXN0X2RhdGEsIHR5cGUgPSAicmVzcG9uc2UiKQoKIyBDYWxjdWxhdGUgUk9DIEN1cnZlcwpyb2NfYmFzZWxpbmUgPC0gcm9jKHRlc3RfZGF0YSRIaWdoSGFwcGluZXNzLCBwcm9iX2Jhc2VsaW5lLCBsZXZlbHMgPSBjKCJMb3ciLCAiSGlnaCIpLCBkaXJlY3Rpb24gPSAiPiIpCnJvY19sb2YgPC0gcm9jKHRlc3RfZGF0YSRIaWdoSGFwcGluZXNzLCBwcm9iX2xvZiwgbGV2ZWxzID0gYygiTG93IiwgIkhpZ2giKSwgZGlyZWN0aW9uID0gIj4iKQoKIyBQbG90IFJPQyBDdXJ2ZXMKcGxvdChyb2NfYmFzZWxpbmUsIGNvbCA9ICJibHVlIiwgbWFpbiA9ICJST0MgQ3VydmUgQ29tcGFyaXNvbiIsIGx3ZCA9IDIpCnBsb3Qocm9jX2xvZiwgY29sID0gInJlZCIsIGFkZCA9IFRSVUUsIGx3ZCA9IDIsIGx0eSA9IDIpCmxlZ2VuZCgiYm90dG9tcmlnaHQiLCBsZWdlbmQgPSBjKHBhc3RlKCJCYXNlbGluZSBBVUMgPSIsIHJvdW5kKGF1Yyhyb2NfYmFzZWxpbmUpLCA0KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCJMT0YgQVVDID0iLCByb3VuZChhdWMocm9jX2xvZiksIDQpKSksCiAgICAgICBjb2wgPSBjKCJibHVlIiwgInJlZCIpLCBsdHkgPSBjKDEsIDIpLCBsd2QgPSAyKQpgYGAKCiMjIENvbmNsdXNpb24KCjEuICAqKk91dGxpZXIgRGV0ZWN0aW9uOioqIFVzaW5nIGEgbmVpZ2hib3Job29kIHNpemUgb2YgJGs9MjAkLCB3ZSBpZGVudGlmaWVkIGEgc3Vic2V0IG9mIG9ic2VydmF0aW9ucyB3aXRoIExPRiBzY29yZXMgZXhjZWVkaW5nIDEuMjUuIFRoZXNlICJsb2NhbCBvdXRsaWVycyIgcmVwcmVzZW50IHVuaXF1ZSBiZWhhdmlvcmFsIHByb2ZpbGVzIGluIHRoZSBkYXRhc2V0LgoyLiAgKipGZWF0dXJlIEltcG9ydGFuY2U6KiogQnkgYWRkaW5nIHRoZSBMT0Ygc2NvcmUgdG8gdGhlIGNsYXNzaWZpY2F0aW9uIG1vZGVsLCB3ZSBhc3Nlc3NlZCBpdHMgY29udHJpYnV0aW9uIHRvIHByZWRpY3RpbmcgaGFwcGluZXNzLiBUaGUgY29tcGFyaXNvbiBvZiBBSUMgYW5kIEFVQyB2YWx1ZXMgaW5kaWNhdGVzIHdoZXRoZXIgdGhlICJ1bnVzdWFsbmVzcyIgb2YgYSBwZXJzb24ncyBoYWJpdHMgc2VydmVzIGFzIGEgcHJlZGljdGl2ZSBzaWduYWwgZm9yIHRoZWlyIG1lbnRhbCB3ZWxsLWJlaW5nLgoK