#download csv file into a dataframe
hrdata <- read.csv("HR-Employee-Attrition.csv")
#It's nice to preview the data. Previewing the first 6 rows
head(hrdata)
#we want to filter out the data
hrdata[ , c("Age", "DailyRate", "DistanceFromHome", "Education", "HourlyRate", "MonthlyIncome", "MonthlyRate", "NumCompaniesWorked", "TotalWorkingYears", "TrainingTimesLastYear", "Gender")]
NA
#now to create a correlation table, let's pass the filtered data
cor( hrdata[ , c("Age", "DailyRate", "DistanceFromHome", "Education", "HourlyRate", "MonthlyIncome", "MonthlyRate", "NumCompaniesWorked", "TotalWorkingYears", "TrainingTimesLastYear")] )
Age DailyRate DistanceFromHome Education HourlyRate MonthlyIncome MonthlyRate
Age 1.00000000 0.010660943 -0.001686120 0.20803373 0.024286543 0.497854567 0.028051167
DailyRate 0.01066094 1.000000000 -0.004985337 -0.01680643 0.023381422 0.007707059 -0.032181602
DistanceFromHome -0.00168612 -0.004985337 1.000000000 0.02104183 0.031130586 -0.017014445 0.027472864
Education 0.20803373 -0.016806433 0.021041826 1.00000000 0.016774829 0.094960677 -0.026084197
HourlyRate 0.02428654 0.023381422 0.031130586 0.01677483 1.000000000 -0.015794304 -0.015296750
MonthlyIncome 0.49785457 0.007707059 -0.017014445 0.09496068 -0.015794304 1.000000000 0.034813626
MonthlyRate 0.02805117 -0.032181602 0.027472864 -0.02608420 -0.015296750 0.034813626 1.000000000
NumCompaniesWorked 0.29963476 0.038153434 -0.029250804 0.12631656 0.022156883 0.149515216 0.017521353
TotalWorkingYears 0.68038054 0.014514739 0.004628426 0.14827970 -0.002333682 0.772893246 0.026442471
TrainingTimesLastYear -0.01962082 0.002452543 -0.036942234 -0.02510024 -0.008547685 -0.021736277 0.001466881
NumCompaniesWorked TotalWorkingYears TrainingTimesLastYear
Age 0.29963476 0.680380536 -0.019620819
DailyRate 0.03815343 0.014514739 0.002452543
DistanceFromHome -0.02925080 0.004628426 -0.036942234
Education 0.12631656 0.148279697 -0.025100241
HourlyRate 0.02215688 -0.002333682 -0.008547685
MonthlyIncome 0.14951522 0.772893246 -0.021736277
MonthlyRate 0.01752135 0.026442471 0.001466881
NumCompaniesWorked 1.00000000 0.237638590 -0.066054072
TotalWorkingYears 0.23763859 1.000000000 -0.035661571
TrainingTimesLastYear -0.06605407 -0.035661571 1.000000000
#It would be helpful to create pair plots to visually see the relationships with the highest correlation value
pairs(~MonthlyIncome+Age+TotalWorkingYears+Education,data = hrdata, main = "Scatterplot Matrix")

yes_age <- hrdata[(hrdata$Attrition == "Yes"),'Age']
no_age <- hrdata[(hrdata$Attrition != "Yes"),'Age']
t.test(yes_age, no_age)
Welch Two Sample t-test
data: yes_age and no_age
t = -5.828, df = 316.93, p-value = 1.38e-08
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-5.288346 -2.618930
sample estimates:
mean of x mean of y
33.60759 37.56123
#I decided to run hypothesis testing because I didn't want any misconception that the decision to lay employees off were for pragmatic reasons and not due to ageism. Therefore, because p is less than 0.05, there is a statistically significant difference between the two samples. Those who left were younger than those who stayed. We can see that in the mean comparison at the bottom. Note that x is the first array we passed in and y is the second array we passed in. That is also confirmed in the confidence interval, since both those numbers listed below are negative, we know that the first array is smaller than the second, with confidence.
#Creating a linear regression model to display the relationship between monthly income based upon the age
model1 <- lm(MonthlyIncome ~ Age, data = hrdata)
summary(model1)
Call:
lm(formula = MonthlyIncome ~ Age, data = hrdata)
Residuals:
Min 1Q Median 3Q Max
-9990.1 -2592.7 -677.9 1810.5 12540.8
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -2970.67 443.70 -6.695 3.06e-11 ***
Age 256.57 11.67 21.995 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 4084 on 1468 degrees of freedom
Multiple R-squared: 0.2479, Adjusted R-squared: 0.2473
F-statistic: 483.8 on 1 and 1468 DF, p-value: < 2.2e-16
# Create a scatter plot with the regression line
plot(MonthlyIncome ~ Age, data = hrdata,
main = "Monthly Income vs. Age",
xlab = "Age",
ylab = "Monthly Income")
# Add the regression line to the plot
abline(model1, col = "red")

# Install needed packages to create a violin plot, a more detailed distribution visualization
install.packages("ggplot2")
trying URL 'https://cran.rstudio.com/bin/macosx/big-sur-arm64/contrib/4.4/ggplot2_3.5.1.tgz'
Content type 'application/x-gzip' length 4974305 bytes (4.7 MB)
==================================================
downloaded 4.7 MB
The downloaded binary packages are in
/var/folders/x3/54ss49b16vj4lr0y1qs2rk8w0000gn/T//RtmpPh1IO9/downloaded_packages
install.packages("readr")
trying URL 'https://cran.rstudio.com/bin/macosx/big-sur-arm64/contrib/4.4/readr_2.1.5.tgz'
Content type 'application/x-gzip' length 1970418 bytes (1.9 MB)
==================================================
downloaded 1.9 MB
The downloaded binary packages are in
/var/folders/x3/54ss49b16vj4lr0y1qs2rk8w0000gn/T//RtmpPh1IO9/downloaded_packages
library(ggplot2)
library(readr)
# Create the violin plot
ggplot(hrdata, aes(x = Attrition, y = MonthlyIncome, fill = Attrition)) +
geom_violin() +
geom_boxplot(width = 0.1, fill = "white") +
labs(title = "Monthly Income vs. Attrition Rates",
x = "Attrition",
y = "Monthly Income")

#Shape of Distribution: For the 'No Attrition' plot, the violin plot for this group is slightly right-skewed, indicating that a majority of employees with no attrition have lower to moderate monthly incomes, with a smaller proportion having higher incomes.For the 'Yes Attrition' plot, the violin plot for this group appears more symmetrical, suggesting a more even distribution of monthly incomes among employees who have left the company.
#Central Tendency:The median monthly income (indicated by the white line within the box) appears to be higher for the "No Attrition" group compared to the "Yes Attrition" group. This suggests that employees with higher monthly incomes are less likely to leave the company.
#Spread:The interquartile range (IQR, represented by the box) is wider for the "No Attrition" group, indicating a greater variability in monthly incomes among employees who stay with the company. The "Yes Attrition" group shows a narrower IQR, suggesting a more concentrated range of monthly incomes among those who leave.
#Outliers:There appear to be a few potential outliers on the higher end of the income range for both groups, but they are more prominent in the "No Attrition" group.
#The violin plot suggests a potential relationship between monthly income and employee attrition. Employees with higher monthly incomes tend to stay with the company more often, while those with lower to moderate incomes are more likely to leave. The wider spread of incomes among those who stay might indicate that the company offers a wider range of compensation packages to retain its higher-earning employees.
#By looking at the box plot, we can see that the employees who left or was let go from IBM has an average income of about $4500 per month, while the employees who stayed have an average income of about $5000. Furthermore, the the employees who stayed with IBM have a 25% quartile value and a 75% quartile value that's higher than the 25% and 75% quartile of the employees who left IBM. And there happen to be some anomalies displayed in this graph, with some employees above the the 75% quartile range, having an income of $20000 a month that left the company. This analysis satisfy the assumption that I had that people with higher monthly income will stay. However, down the line, I want to see what the cause of these employees leaving or getting let go.
#Let's also see the relationship between the age and the attrition rate
# Create the violin plot
ggplot(hrdata, aes(x = Attrition, y = Age, fill = Attrition)) +
geom_violin() +
geom_boxplot(width = 0.1, fill = "white") +
labs(title = "Age vs. Attrition Rates",
x = "Attrition",
y = "Age")

#You can see that most employees were either let go or they left around the early thirties.
#we're going to do a hypothesis test with what's called a Welch Two Sample t-test
#After finding the relationship between the age and attrition rates, and monthly income and attrition rate.
#Creating a linear regression model to display multiple x variables at once to predict a y variable
model2 = lm(MonthlyIncome ~ Age + TotalWorkingYears, data=hrdata)
summary(model2)
Call:
lm(formula = MonthlyIncome ~ Age + TotalWorkingYears, data = hrdata)
Residuals:
Min 1Q Median 3Q Max
-11310.8 -1690.8 -91.4 1428.3 11461.5
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1978.08 352.36 5.614 2.36e-08 ***
Age -26.87 11.63 -2.311 0.021 *
TotalWorkingYears 489.13 13.65 35.824 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2984 on 1467 degrees of freedom
Multiple R-squared: 0.5988, Adjusted R-squared: 0.5983
F-statistic: 1095 on 2 and 1467 DF, p-value: < 2.2e-16
#The R squared value has significantly increased with multiple x variables, with a value of 0.5983. However, with a p-value of 2.2e-16, this values suggests that the relationship is not significant.
library(ggplot2)
# Create the horizontal bar plot using ggplot2
ggplot(hrdata, aes(x = JobRole, fill = factor(JobSatisfaction))) +
geom_bar(position = "dodge") +
coord_flip() + # This line flips the x and y axes to make it horizontal
labs(title = "Job Satisfaction Distribution by Job Role",
x = "Job Role",
y = "Satisfaction Count") +
scale_fill_discrete(name = "Job Satisfaction") + # Changed legend title
theme_bw()

library(ggplot2)
# Assuming your DataFrame is named 'hrdata'
# Create the horizontal violin plot using ggplot2
ggplot(hrdata, aes(x = JobRole, y = DistanceFromHome, fill = JobRole)) +
geom_violin() +
coord_flip() +
labs(title = "Distance From Home by Job Role",
x = "Job Role",
y = "Distance From Home") +
theme_bw() +
theme(legend.position = "none") # Remove the legend as JobRole is already on the y-axis

library(ggplot2)
library(RColorBrewer)
# Calculate average years since last promotion for each job role
hrdata_summary <- aggregate(YearsSinceLastPromotion ~ JobRole, data = hrdata, FUN = mean)
# Create the horizontal bar plot
ggplot(hrdata_summary, aes(x = YearsSinceLastPromotion, y = JobRole)) +
geom_col(fill = "salmon") +
labs(x = "Average Years Since Last Promotion", y = "Job Role",
title = "Years Since Last Promotion by Job Role") +
theme_bw()

library(ggplot2)
# Create the horizontal bar plot using ggplot2
ggplot(hrdata, aes(x = JobRole, fill = factor(Attrition))) +
geom_bar(position = "dodge") +
coord_flip() + # This line flips the x and y axes to make it horizontal
labs(title = "Attrition Count by Job Role",
x = "Job Role",
y = "Attrition Count") +
scale_fill_discrete(name = "Attrition") + # Changed legend title
theme_bw()

library(ggplot2)
# Create the horizontal bar plot using ggplot2
ggplot(hrdata, aes(x = JobRole, fill = factor(OverTime))) +
geom_bar(position = "dodge") +
coord_flip() + # This line flips the x and y axes to make it horizontal
labs(title = "Overtime Count by Job Role",
x = "Job Role",
y = "Overtime Count") +
scale_fill_discrete(name = "Overtime") + # Changed legend title
theme_bw()

# Converting to numeric dummy variables
hrdata$Attrition_values <- ifelse(hrdata$Attrition == "Yes", 1, 0)
hrdata$Overtime_values <- ifelse(hrdata$OverTime == "Yes", 1, 0)
hrdata$Gender_values<-ifelse(hrdata$Gender == "Female", 1, 0)
# Create the logistic regression model
model_logistic <- glm(Attrition_values ~ Gender_values + Overtime_values,
data = hrdata,
family = binomial)
# Print the summary
summary(model_logistic)
Call:
glm(formula = Attrition_values ~ Gender_values + Overtime_values,
family = binomial, data = hrdata)
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -2.0629 0.1135 -18.182 <2e-16 ***
Gender_values -0.2378 0.1517 -1.568 0.117
Overtime_values 1.3408 0.1471 9.117 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 1298.6 on 1469 degrees of freedom
Residual deviance: 1214.7 on 1467 degrees of freedom
AIC: 1220.7
Number of Fisher Scoring iterations: 4
# Extract the coefficient for Overtime_numeric
odds_ratio <- exp(coef(model_logistic)["Overtime_values"])
print(odds_ratio)
Overtime_values
3.821998
# Print the odds ratio
cat("Odds Ratio for Attrition rates based on Overtime responses:", odds_ratio, "\n")
Odds Ratio for Attrition rates based on Overtime responses: 3.821998
LS0tCnRpdGxlOiAiSFIgQW5hbHlzaXMiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAotLS0KCmBgYHtyfQojZG93bmxvYWQgY3N2IGZpbGUgaW50byBhIGRhdGFmcmFtZQpocmRhdGEgPC0gcmVhZC5jc3YoIkhSLUVtcGxveWVlLUF0dHJpdGlvbi5jc3YiKQpgYGAKCmBgYHtyfQojSXQncyBuaWNlIHRvIHByZXZpZXcgdGhlIGRhdGEuIFByZXZpZXdpbmcgdGhlIGZpcnN0IDYgcm93cwpoZWFkKGhyZGF0YSkKYGBgCgpgYGB7cn0KI3dlIHdhbnQgdG8gZmlsdGVyIG91dCB0aGUgZGF0YQpocmRhdGFbICwgYygiQWdlIiwgIkRhaWx5UmF0ZSIsICJEaXN0YW5jZUZyb21Ib21lIiwgIkVkdWNhdGlvbiIsICJIb3VybHlSYXRlIiwgIk1vbnRobHlJbmNvbWUiLCAiTW9udGhseVJhdGUiLCAiTnVtQ29tcGFuaWVzV29ya2VkIiwgIlRvdGFsV29ya2luZ1llYXJzIiwgIlRyYWluaW5nVGltZXNMYXN0WWVhciIsICJHZW5kZXIiKV0KCmBgYAoKYGBge3J9CiNub3cgdG8gY3JlYXRlIGEgY29ycmVsYXRpb24gdGFibGUsIGxldCdzIHBhc3MgdGhlIGZpbHRlcmVkIGRhdGEKY29yKCBocmRhdGFbICwgYygiQWdlIiwgIkRhaWx5UmF0ZSIsICJEaXN0YW5jZUZyb21Ib21lIiwgIkVkdWNhdGlvbiIsICJIb3VybHlSYXRlIiwgIk1vbnRobHlJbmNvbWUiLCAiTW9udGhseVJhdGUiLCAiTnVtQ29tcGFuaWVzV29ya2VkIiwgIlRvdGFsV29ya2luZ1llYXJzIiwgIlRyYWluaW5nVGltZXNMYXN0WWVhciIpXSApCmBgYAoKYGBge3J9CiNJdCB3b3VsZCBiZSBoZWxwZnVsIHRvIGNyZWF0ZSBwYWlyIHBsb3RzIHRvIHZpc3VhbGx5IHNlZSB0aGUgcmVsYXRpb25zaGlwcyB3aXRoIHRoZSBoaWdoZXN0IGNvcnJlbGF0aW9uIHZhbHVlCnBhaXJzKH5Nb250aGx5SW5jb21lK0FnZStUb3RhbFdvcmtpbmdZZWFycytFZHVjYXRpb24sZGF0YSA9IGhyZGF0YSwgbWFpbiA9ICJTY2F0dGVycGxvdCBNYXRyaXgiKQpgYGAKCgpgYGB7cn0KeWVzX2FnZSA8LSBocmRhdGFbKGhyZGF0YSRBdHRyaXRpb24gPT0gIlllcyIpLCdBZ2UnXSAKbm9fYWdlIDwtIGhyZGF0YVsoaHJkYXRhJEF0dHJpdGlvbiAhPSAiWWVzIiksJ0FnZSddCgp0LnRlc3QoeWVzX2FnZSwgbm9fYWdlKQpgYGAKCgpgYGB7cn0KI0kgZGVjaWRlZCB0byBydW4gaHlwb3RoZXNpcyB0ZXN0aW5nIGJlY2F1c2UgSSBkaWRuJ3Qgd2FudCBhbnkgbWlzY29uY2VwdGlvbiB0aGF0IHRoZSBkZWNpc2lvbiB0byBsYXkgZW1wbG95ZWVzIG9mZiB3ZXJlIGZvciBwcmFnbWF0aWMgcmVhc29ucyBhbmQgbm90IGR1ZSB0byBhZ2Vpc20uIFRoZXJlZm9yZSwgYmVjYXVzZSBwIGlzIGxlc3MgdGhhbiAwLjA1LCB0aGVyZSBpcyBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0d28gc2FtcGxlcy4gVGhvc2Ugd2hvIGxlZnQgd2VyZSB5b3VuZ2VyIHRoYW4gdGhvc2Ugd2hvIHN0YXllZC4gV2UgY2FuIHNlZSB0aGF0IGluIHRoZSBtZWFuIGNvbXBhcmlzb24gYXQgdGhlIGJvdHRvbS4gTm90ZSB0aGF0IHggaXMgdGhlIGZpcnN0IGFycmF5IHdlIHBhc3NlZCBpbiBhbmQgeSBpcyB0aGUgc2Vjb25kIGFycmF5IHdlIHBhc3NlZCBpbi4gVGhhdCBpcyBhbHNvIGNvbmZpcm1lZCBpbiB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCwgc2luY2UgYm90aCB0aG9zZSBudW1iZXJzIGxpc3RlZCBiZWxvdyBhcmUgbmVnYXRpdmUsIHdlIGtub3cgdGhhdCB0aGUgZmlyc3QgYXJyYXkgaXMgc21hbGxlciB0aGFuIHRoZSBzZWNvbmQsIHdpdGggY29uZmlkZW5jZS4KYGBgCgpgYGB7cn0KI0NyZWF0aW5nIGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgdG8gZGlzcGxheSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gbW9udGhseSBpbmNvbWUgYmFzZWQgdXBvbiB0aGUgYWdlCm1vZGVsMSA8LSBsbShNb250aGx5SW5jb21lIH4gQWdlLCBkYXRhID0gaHJkYXRhKSAKc3VtbWFyeShtb2RlbDEpIApgYGAKCmBgYHtyfQojIENyZWF0ZSBhIHNjYXR0ZXIgcGxvdCB3aXRoIHRoZSByZWdyZXNzaW9uIGxpbmUKcGxvdChNb250aGx5SW5jb21lIH4gQWdlLCBkYXRhID0gaHJkYXRhLCAKICAgICBtYWluID0gIk1vbnRobHkgSW5jb21lIHZzLiBBZ2UiLCAKICAgICB4bGFiID0gIkFnZSIsIAogICAgIHlsYWIgPSAiTW9udGhseSBJbmNvbWUiKQoKIyBBZGQgdGhlIHJlZ3Jlc3Npb24gbGluZSB0byB0aGUgcGxvdAphYmxpbmUobW9kZWwxLCBjb2wgPSAicmVkIikgCmBgYAoKYGBge3J9CiMgSW5zdGFsbCBuZWVkZWQgcGFja2FnZXMgdG8gY3JlYXRlIGEgdmlvbGluIHBsb3QsIGEgbW9yZSBkZXRhaWxlZCBkaXN0cmlidXRpb24gdmlzdWFsaXphdGlvbgppbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikKaW5zdGFsbC5wYWNrYWdlcygicmVhZHIiKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocmVhZHIpCgojIENyZWF0ZSB0aGUgdmlvbGluIHBsb3QKZ2dwbG90KGhyZGF0YSwgYWVzKHggPSBBdHRyaXRpb24sIHkgPSBNb250aGx5SW5jb21lLCBmaWxsID0gQXR0cml0aW9uKSkgKwogIGdlb21fdmlvbGluKCkgKwogIGdlb21fYm94cGxvdCh3aWR0aCA9IDAuMSwgZmlsbCA9ICJ3aGl0ZSIpICsgCiAgbGFicyh0aXRsZSA9ICJNb250aGx5IEluY29tZSB2cy4gQXR0cml0aW9uIFJhdGVzIiwKICAgICAgIHggPSAiQXR0cml0aW9uIiwKICAgICAgIHkgPSAiTW9udGhseSBJbmNvbWUiKQpgYGAKCmBgYHtyfQojU2hhcGUgb2YgRGlzdHJpYnV0aW9uOiBGb3IgdGhlICdObyBBdHRyaXRpb24nIHBsb3QsIHRoZSB2aW9saW4gcGxvdCBmb3IgdGhpcyBncm91cCBpcyBzbGlnaHRseSByaWdodC1za2V3ZWQsIGluZGljYXRpbmcgdGhhdCBhIG1ham9yaXR5IG9mIGVtcGxveWVlcyB3aXRoIG5vIGF0dHJpdGlvbiBoYXZlIGxvd2VyIHRvIG1vZGVyYXRlIG1vbnRobHkgaW5jb21lcywgd2l0aCBhIHNtYWxsZXIgcHJvcG9ydGlvbiBoYXZpbmcgaGlnaGVyIGluY29tZXMuRm9yIHRoZSAnWWVzIEF0dHJpdGlvbicgcGxvdCwgdGhlIHZpb2xpbiBwbG90IGZvciB0aGlzIGdyb3VwIGFwcGVhcnMgbW9yZSBzeW1tZXRyaWNhbCwgc3VnZ2VzdGluZyBhIG1vcmUgZXZlbiBkaXN0cmlidXRpb24gb2YgbW9udGhseSBpbmNvbWVzIGFtb25nIGVtcGxveWVlcyB3aG8gaGF2ZSBsZWZ0IHRoZSBjb21wYW55LgoKI0NlbnRyYWwgVGVuZGVuY3k6VGhlIG1lZGlhbiBtb250aGx5IGluY29tZSAoaW5kaWNhdGVkIGJ5IHRoZSB3aGl0ZSBsaW5lIHdpdGhpbiB0aGUgYm94KSBhcHBlYXJzIHRvIGJlIGhpZ2hlciBmb3IgdGhlICJObyBBdHRyaXRpb24iIGdyb3VwIGNvbXBhcmVkIHRvIHRoZSAiWWVzIEF0dHJpdGlvbiIgZ3JvdXAuIFRoaXMgc3VnZ2VzdHMgdGhhdCBlbXBsb3llZXMgd2l0aCBoaWdoZXIgbW9udGhseSBpbmNvbWVzIGFyZSBsZXNzIGxpa2VseSB0byBsZWF2ZSB0aGUgY29tcGFueS4KCiNTcHJlYWQ6VGhlIGludGVycXVhcnRpbGUgcmFuZ2UgKElRUiwgcmVwcmVzZW50ZWQgYnkgdGhlIGJveCkgaXMgd2lkZXIgZm9yIHRoZSAiTm8gQXR0cml0aW9uIiBncm91cCwgaW5kaWNhdGluZyBhIGdyZWF0ZXIgdmFyaWFiaWxpdHkgaW4gbW9udGhseSBpbmNvbWVzIGFtb25nIGVtcGxveWVlcyB3aG8gc3RheSB3aXRoIHRoZSBjb21wYW55LiBUaGUgIlllcyBBdHRyaXRpb24iIGdyb3VwIHNob3dzIGEgbmFycm93ZXIgSVFSLCBzdWdnZXN0aW5nIGEgbW9yZSBjb25jZW50cmF0ZWQgcmFuZ2Ugb2YgbW9udGhseSBpbmNvbWVzIGFtb25nIHRob3NlIHdobyBsZWF2ZS4KCiNPdXRsaWVyczpUaGVyZSBhcHBlYXIgdG8gYmUgYSBmZXcgcG90ZW50aWFsIG91dGxpZXJzIG9uIHRoZSBoaWdoZXIgZW5kIG9mIHRoZSBpbmNvbWUgcmFuZ2UgZm9yIGJvdGggZ3JvdXBzLCBidXQgdGhleSBhcmUgbW9yZSBwcm9taW5lbnQgaW4gdGhlICJObyBBdHRyaXRpb24iIGdyb3VwLgoKI1RoZSB2aW9saW4gcGxvdCBzdWdnZXN0cyBhIHBvdGVudGlhbCByZWxhdGlvbnNoaXAgYmV0d2VlbiBtb250aGx5IGluY29tZSBhbmQgZW1wbG95ZWUgYXR0cml0aW9uLiBFbXBsb3llZXMgd2l0aCBoaWdoZXIgbW9udGhseSBpbmNvbWVzIHRlbmQgdG8gc3RheSB3aXRoIHRoZSBjb21wYW55IG1vcmUgb2Z0ZW4sIHdoaWxlIHRob3NlIHdpdGggbG93ZXIgdG8gbW9kZXJhdGUgaW5jb21lcyBhcmUgbW9yZSBsaWtlbHkgdG8gbGVhdmUuIFRoZSB3aWRlciBzcHJlYWQgb2YgaW5jb21lcyBhbW9uZyB0aG9zZSB3aG8gc3RheSBtaWdodCBpbmRpY2F0ZSB0aGF0IHRoZSBjb21wYW55IG9mZmVycyBhIHdpZGVyIHJhbmdlIG9mIGNvbXBlbnNhdGlvbiBwYWNrYWdlcyB0byByZXRhaW4gaXRzIGhpZ2hlci1lYXJuaW5nIGVtcGxveWVlcy4KCmBgYAoKYGBge3J9CiAgI0J5IGxvb2tpbmcgYXQgdGhlIGJveCBwbG90LCB3ZSBjYW4gc2VlIHRoYXQgdGhlIGVtcGxveWVlcyB3aG8gbGVmdCBvciB3YXMgbGV0IGdvIGZyb20gSUJNIGhhcyBhbiBhdmVyYWdlIGluY29tZSBvZiBhYm91dCAkNDUwMCBwZXIgbW9udGgsIHdoaWxlIHRoZSBlbXBsb3llZXMgd2hvIHN0YXllZCBoYXZlIGFuIGF2ZXJhZ2UgaW5jb21lIG9mIGFib3V0ICQ1MDAwLiBGdXJ0aGVybW9yZSwgdGhlIHRoZSBlbXBsb3llZXMgd2hvIHN0YXllZCB3aXRoIElCTSBoYXZlIGEgMjUlIHF1YXJ0aWxlIHZhbHVlIGFuZCBhIDc1JSBxdWFydGlsZSB2YWx1ZSB0aGF0J3MgaGlnaGVyIHRoYW4gdGhlIDI1JSBhbmQgNzUlIHF1YXJ0aWxlIG9mIHRoZSBlbXBsb3llZXMgd2hvIGxlZnQgSUJNLiBBbmQgdGhlcmUgaGFwcGVuIHRvIGJlIHNvbWUgYW5vbWFsaWVzIGRpc3BsYXllZCBpbiB0aGlzIGdyYXBoLCB3aXRoIHNvbWUgZW1wbG95ZWVzIGFib3ZlIHRoZSB0aGUgNzUlIHF1YXJ0aWxlIHJhbmdlLCBoYXZpbmcgYW4gaW5jb21lIG9mICQyMDAwMCBhIG1vbnRoIHRoYXQgbGVmdCB0aGUgY29tcGFueS4gVGhpcyBhbmFseXNpcyBzYXRpc2Z5IHRoZSBhc3N1bXB0aW9uIHRoYXQgSSBoYWQgdGhhdCBwZW9wbGUgd2l0aCBoaWdoZXIgbW9udGhseSBpbmNvbWUgd2lsbCBzdGF5LiBIb3dldmVyLCBkb3duIHRoZSBsaW5lLCBJIHdhbnQgdG8gc2VlIHdoYXQgdGhlIGNhdXNlIG9mIHRoZXNlIGVtcGxveWVlcyBsZWF2aW5nIG9yIGdldHRpbmcgbGV0IGdvLiAKYGBgCgpgYGB7cn0KI0xldCdzIGFsc28gc2VlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgYWdlIGFuZCB0aGUgYXR0cml0aW9uIHJhdGUKIyBDcmVhdGUgdGhlIHZpb2xpbiBwbG90CmdncGxvdChocmRhdGEsIGFlcyh4ID0gQXR0cml0aW9uLCB5ID0gQWdlLCBmaWxsID0gQXR0cml0aW9uKSkgKwogIGdlb21fdmlvbGluKCkgKwogIGdlb21fYm94cGxvdCh3aWR0aCA9IDAuMSwgZmlsbCA9ICJ3aGl0ZSIpICsgCiAgbGFicyh0aXRsZSA9ICJBZ2UgdnMuIEF0dHJpdGlvbiBSYXRlcyIsCiAgICAgICB4ID0gIkF0dHJpdGlvbiIsCiAgICAgICB5ID0gIkFnZSIpCmBgYAoKYGBge3J9CiNZb3UgY2FuIHNlZSB0aGF0IG1vc3QgZW1wbG95ZWVzIHdlcmUgZWl0aGVyIGxldCBnbyBvciB0aGV5IGxlZnQgYXJvdW5kIHRoZSBlYXJseSB0aGlydGllcy4gCmBgYAoKYGBge3J9CiNXZSdyZSBnb2luZyB0byBkbyBhIGh5cG90aGVzaXMgdGVzdCB3aXRoIHdoYXQncyBjYWxsZWQgYSBXZWxjaCBUd28gU2FtcGxlIHQtdGVzdAoKI0NyZWF0aW5nIGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgdG8gZGlzcGxheSBtdWx0aXBsZSB4IHZhcmlhYmxlcyBhdCBvbmNlIHRvIHByZWRpY3QgYSB5IHZhcmlhYmxlCm1vZGVsMiA9IGxtKE1vbnRobHlJbmNvbWUgfiBBZ2UgKyBUb3RhbFdvcmtpbmdZZWFycywgZGF0YT1ocmRhdGEpIApzdW1tYXJ5KG1vZGVsMikKYGBgCgpgYGB7cn0KI1RoZSBSIHNxdWFyZWQgdmFsdWUgaGFzIHNpZ25pZmljYW50bHkgaW5jcmVhc2VkIHdpdGggbXVsdGlwbGUgeCB2YXJpYWJsZXMsIHdpdGggYSB2YWx1ZSBvZiAwLjU5ODMuIEhvd2V2ZXIsIHdpdGggYSBwLXZhbHVlIG9mIDIuMmUtMTYsIHRoaXMgdmFsdWVzIHN1Z2dlc3RzIHRoYXQgdGhlIHJlbGF0aW9uc2hpcCBpcyBub3Qgc2lnbmlmaWNhbnQuIApgYGAKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCgojIENyZWF0ZSB0aGUgaG9yaXpvbnRhbCBiYXIgcGxvdCB1c2luZyBnZ3Bsb3QyCmdncGxvdChocmRhdGEsIGFlcyh4ID0gSm9iUm9sZSwgZmlsbCA9IGZhY3RvcihKb2JTYXRpc2ZhY3Rpb24pKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikgKwogIGNvb3JkX2ZsaXAoKSArICAjIFRoaXMgbGluZSBmbGlwcyB0aGUgeCBhbmQgeSBheGVzIHRvIG1ha2UgaXQgaG9yaXpvbnRhbAogIGxhYnModGl0bGUgPSAiSm9iIFNhdGlzZmFjdGlvbiBEaXN0cmlidXRpb24gYnkgSm9iIFJvbGUiLAogICAgICAgeCA9ICJKb2IgUm9sZSIsIAogICAgICAgeSA9ICJTYXRpc2ZhY3Rpb24gQ291bnQiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIkpvYiBTYXRpc2ZhY3Rpb24iKSArICAjIENoYW5nZWQgbGVnZW5kIHRpdGxlCiAgdGhlbWVfYncoKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCgojIEFzc3VtaW5nIHlvdXIgRGF0YUZyYW1lIGlzIG5hbWVkICdocmRhdGEnCgojIENyZWF0ZSB0aGUgaG9yaXpvbnRhbCB2aW9saW4gcGxvdCB1c2luZyBnZ3Bsb3QyCmdncGxvdChocmRhdGEsIGFlcyh4ID0gSm9iUm9sZSwgeSA9IERpc3RhbmNlRnJvbUhvbWUsIGZpbGwgPSBKb2JSb2xlKSkgKwogIGdlb21fdmlvbGluKCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh0aXRsZSA9ICJEaXN0YW5jZSBGcm9tIEhvbWUgYnkgSm9iIFJvbGUiLAogICAgICAgeCA9ICJKb2IgUm9sZSIsCiAgICAgICB5ID0gIkRpc3RhbmNlIEZyb20gSG9tZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICAjIFJlbW92ZSB0aGUgbGVnZW5kIGFzIEpvYlJvbGUgaXMgYWxyZWFkeSBvbiB0aGUgeS1heGlzCmBgYAoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShSQ29sb3JCcmV3ZXIpCgojIENhbGN1bGF0ZSBhdmVyYWdlIHllYXJzIHNpbmNlIGxhc3QgcHJvbW90aW9uIGZvciBlYWNoIGpvYiByb2xlCmhyZGF0YV9zdW1tYXJ5IDwtIGFnZ3JlZ2F0ZShZZWFyc1NpbmNlTGFzdFByb21vdGlvbiB+IEpvYlJvbGUsIGRhdGEgPSBocmRhdGEsIEZVTiA9IG1lYW4pCgojIENyZWF0ZSB0aGUgaG9yaXpvbnRhbCBiYXIgcGxvdApnZ3Bsb3QoaHJkYXRhX3N1bW1hcnksIGFlcyh4ID0gWWVhcnNTaW5jZUxhc3RQcm9tb3Rpb24sIHkgPSBKb2JSb2xlKSkgKyAKICBnZW9tX2NvbChmaWxsID0gInNhbG1vbiIpICsgCiAgbGFicyh4ID0gIkF2ZXJhZ2UgWWVhcnMgU2luY2UgTGFzdCBQcm9tb3Rpb24iLCB5ID0gIkpvYiBSb2xlIiwgCiAgICAgICB0aXRsZSA9ICJZZWFycyBTaW5jZSBMYXN0IFByb21vdGlvbiBieSBKb2IgUm9sZSIpICsgCiAgdGhlbWVfYncoKSAKYGBgCgoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKCiMgQ3JlYXRlIHRoZSBob3Jpem9udGFsIGJhciBwbG90IHVzaW5nIGdncGxvdDIKZ2dwbG90KGhyZGF0YSwgYWVzKHggPSBKb2JSb2xlLCBmaWxsID0gZmFjdG9yKEF0dHJpdGlvbikpKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgY29vcmRfZmxpcCgpICsgICMgVGhpcyBsaW5lIGZsaXBzIHRoZSB4IGFuZCB5IGF4ZXMgdG8gbWFrZSBpdCBob3Jpem9udGFsCiAgbGFicyh0aXRsZSA9ICJBdHRyaXRpb24gQ291bnQgYnkgSm9iIFJvbGUiLAogICAgICAgeCA9ICJKb2IgUm9sZSIsIAogICAgICAgeSA9ICJBdHRyaXRpb24gQ291bnQiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIkF0dHJpdGlvbiIpICsgICMgQ2hhbmdlZCBsZWdlbmQgdGl0bGUKICB0aGVtZV9idygpCmBgYAoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKCiMgQ3JlYXRlIHRoZSBob3Jpem9udGFsIGJhciBwbG90IHVzaW5nIGdncGxvdDIKZ2dwbG90KGhyZGF0YSwgYWVzKHggPSBKb2JSb2xlLCBmaWxsID0gZmFjdG9yKE92ZXJUaW1lKSkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBjb29yZF9mbGlwKCkgKyAgIyBUaGlzIGxpbmUgZmxpcHMgdGhlIHggYW5kIHkgYXhlcyB0byBtYWtlIGl0IGhvcml6b250YWwKICBsYWJzKHRpdGxlID0gIk92ZXJ0aW1lIENvdW50IGJ5IEpvYiBSb2xlIiwKICAgICAgIHggPSAiSm9iIFJvbGUiLCAKICAgICAgIHkgPSAiT3ZlcnRpbWUgQ291bnQiKSArCiAgc2NhbGVfZmlsbF9kaXNjcmV0ZShuYW1lID0gIk92ZXJ0aW1lIikgKyAgIyBDaGFuZ2VkIGxlZ2VuZCB0aXRsZQogIHRoZW1lX2J3KCkKYGBgCgpgYGB7cn0KIyBDb252ZXJ0aW5nIHRvIG51bWVyaWMgZHVtbXkgdmFyaWFibGVzCmhyZGF0YSRBdHRyaXRpb25fdmFsdWVzIDwtIGlmZWxzZShocmRhdGEkQXR0cml0aW9uID09ICJZZXMiLCAxLCAwKQpocmRhdGEkT3ZlcnRpbWVfdmFsdWVzIDwtIGlmZWxzZShocmRhdGEkT3ZlclRpbWUgPT0gIlllcyIsIDEsIDApCmhyZGF0YSRHZW5kZXJfdmFsdWVzPC1pZmVsc2UoaHJkYXRhJEdlbmRlciA9PSAiRmVtYWxlIiwgMSwgMCkKCiMgQ3JlYXRlIHRoZSBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsCm1vZGVsX2xvZ2lzdGljIDwtIGdsbShBdHRyaXRpb25fdmFsdWVzIH4gR2VuZGVyX3ZhbHVlcyArIE92ZXJ0aW1lX3ZhbHVlcywgCiAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBocmRhdGEsIAogICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBiaW5vbWlhbCkKCiMgUHJpbnQgdGhlIHN1bW1hcnkKc3VtbWFyeShtb2RlbF9sb2dpc3RpYykgCmBgYAoKYGBge3J9CiMgRXh0cmFjdCB0aGUgY29lZmZpY2llbnQgZm9yIE92ZXJ0aW1lX251bWVyaWMKb2Rkc19yYXRpbyA8LSBleHAoY29lZihtb2RlbF9sb2dpc3RpYylbIk92ZXJ0aW1lX3ZhbHVlcyJdKQpwcmludChvZGRzX3JhdGlvKQoKIyBQcmludCB0aGUgb2RkcyByYXRpbwpjYXQoIk9kZHMgUmF0aW8gZm9yIEF0dHJpdGlvbiByYXRlcyBiYXNlZCBvbiBPdmVydGltZSByZXNwb25zZXM6Iiwgb2Rkc19yYXRpbywgIlxuIikgCmBgYAo=