Task#1: About this Project


1A) Brief description of your project.

The goal of our project is to analyze the Employee Attrition dataset in order to find patterns and predictions. Based on the information given, we are focusing on the impacts and relationships from age, gender, and educational background in respect to other factors such as number of companies worked at, number of promotions, salary increases, monthly income, and other determinants. Since this data is Human Resources centric, the desired end result is always to identify and alleviate inequities within the company in order to enhance the value creation model of the organization for all stakeholders.

1B) Resources - Packages/software use on the project (R, Tableau, Watson)

Packages used: tidyverse Software used: Tableau, Watson, R, Excel

1C) Data Description source, year, country.

There is no information available regarding the timeline of the data collection, its source, or country.

1D) Potential business cases (hypothesis)

Our hypothesis is that generational stereotypes and gender inequalities will be easily recognizable within the dataset, i.e. younger employees will have worked for more companies and women will be paid less than men, among other considerations. For R studio, we hypothesize that the monthly income for employees increases with their age due to work experience, seniority job level, and skills.


Task#2: Data Collection - INDUSTRY - HR


2A) Brief description and key metrics of the project industry (context)

The industry our project is based on a typical business scenario that involves employees, salaries, education and other factors that may influence each other such as job satisfaction level, job level, martial status. Our project is using data from a Human Resources perspective, which is an important feature of a business’ performance. Some key metrics for this project’s industry (using the data we have been provided with): 1. Job satisfaction 2. Performance Rating 3. Attrition

2B) Explore the dataset, note any interesting patterns highlights

See below for images:

knitr::include_graphics('C:\\Users\\hp\\Documents\\Spring 2018\\BSAD 343H\\BSAD343H Project\\hr\\Gender\\interesting1.png')

knitr::include_graphics('C:\\Users\\hp\\Documents\\Spring 2018\\BSAD 343H\\BSAD343H Project\\hr\\Gender\\interesting2.png')

knitr::include_graphics('C:\\Users\\hp\\Documents\\Spring 2018\\BSAD 343H\\BSAD343H Project\\hr\\Gender\\interesting3.png')

knitr::include_graphics('C:\\Users\\hp\\Documents\\Spring 2018\\BSAD 343H\\BSAD343H Project\\hr\\Gender\\interesting4.png')

knitr::include_graphics('C:\\Users\\hp\\Documents\\Spring 2018\\BSAD 343H\\BSAD343H Project\\hr\\Gender\\interesting5.png')

knitr::include_graphics('C:\\Users\\hp\\Documents\\Spring 2018\\BSAD 343H\\BSAD343H Project\\hr\\Gender\\interesting6.png')

The first figure analyzes average monthly_income and age. It’s interesting that Females earn more than males in general, which was not expected. The second analyzes average work life balance and age. It’s interesting that Females have much lower work life balance during the years 22-24. One theory is that they are entry level grads who are still trying to find their passion or working extremely hard to prove themselves. The third analyzes ave number of companies worked and age. This is interesting, because we were under the impression the previous generation did not have as much fluctuations in careers as our generation. The fourth analyzes average perfomance rating and age, which is compared to average percent salary rate. It’s interesting that the first years have a peak in performance and pay, but tends to stagnant in the following years. The fifth demonstrates age vs. rows, which analyzes the amount of employees in that age group. It’s interesting to note the bell curve shape to this figure, but it makes sense that there are low numbers of entry levels and senior management due to recruiting youth and retiring seniors. The sixth shows the main drivers of monthly income, being job level, job role and total working years. The longer you stay at this company, the more you’ll get paid.

2C) Paragraph using descriptive statistics

These graphs illustrate various ways of analysing our set of data. Using descriptive statistics, Watson provides most insight in this respect. We notice that JobLevel and JobRole are the 2 strongest variables that drive monthly income. When analyzing the monthly income vs. age, there appears to be a general positive trendline. We wanted to integrate a third variable, being gender for comparison. We found that women tend to be paid more in general, which is quite interesting and against our initial hypothesis. This has driven us to discover what are the discrepancies between pay, from job role, number of companies worked at and performance levels.


Task#3: Data Preparation - Cleaning and preparing the data for analysis


3A) Describe the steps to cleaning and prepare the data for analysis. Make an argument of why those steps are necessary.

Data cleansing is an important process, as it makes data more manageable and allows for some variables that are characteristic to be interpreted.

3B) Clean the data

mydata <- read_csv("C:\\Users\\hp\\Documents\\Spring 2018\\BSAD 343H\\BSAD343H Project\\hr\\Gender\\employee_attrition.csv")
Parsed with column specification:
cols(
  .default = col_integer(),
  Attrition = col_character(),
  BusinessTravel = col_character(),
  Department = col_character(),
  EducationField = col_character(),
  JobRole = col_character(),
  MaritalStatus = col_character(),
  Over18 = col_character(),
  OverTime = col_character()
)
See spec(...) for full column specifications.
Warning message:
In file(con, "r") :
  cannot open file 'Lab8.utf8.md': No such file or directory
head(mydata)
summary(mydata)
      Age         Attrition         BusinessTravel       DailyRate       Department        DistanceFromHome   Education     EducationField     EmployeeCount
 Min.   :18.00   Length:1470        Length:1470        Min.   : 102.0   Length:1470        Min.   : 1.000   Min.   :1.000   Length:1470        Min.   :1    
 1st Qu.:30.00   Class :character   Class :character   1st Qu.: 465.0   Class :character   1st Qu.: 2.000   1st Qu.:2.000   Class :character   1st Qu.:1    
 Median :36.00   Mode  :character   Mode  :character   Median : 802.0   Mode  :character   Median : 7.000   Median :3.000   Mode  :character   Median :1    
 Mean   :36.92                                         Mean   : 802.5                      Mean   : 9.193   Mean   :2.913                      Mean   :1    
 3rd Qu.:43.00                                         3rd Qu.:1157.0                      3rd Qu.:14.000   3rd Qu.:4.000                      3rd Qu.:1    
 Max.   :60.00                                         Max.   :1499.0                      Max.   :29.000   Max.   :5.000                      Max.   :1    
 EmployeeNumber   EnvironmentSatisfaction     Gender      HourlyRate     JobInvolvement    JobLevel       JobRole          JobSatisfaction MaritalStatus     
 Min.   :   1.0   Min.   :1.000           Min.   :1.0   Min.   : 30.00   Min.   :1.00   Min.   :1.000   Length:1470        Min.   :1.000   Length:1470       
 1st Qu.: 491.2   1st Qu.:2.000           1st Qu.:1.0   1st Qu.: 48.00   1st Qu.:2.00   1st Qu.:1.000   Class :character   1st Qu.:2.000   Class :character  
 Median :1020.5   Median :3.000           Median :2.0   Median : 66.00   Median :3.00   Median :2.000   Mode  :character   Median :3.000   Mode  :character  
 Mean   :1024.9   Mean   :2.722           Mean   :1.6   Mean   : 65.89   Mean   :2.73   Mean   :2.064                      Mean   :2.729                     
 3rd Qu.:1555.8   3rd Qu.:4.000           3rd Qu.:2.0   3rd Qu.: 83.75   3rd Qu.:3.00   3rd Qu.:3.000                      3rd Qu.:4.000                     
 Max.   :2068.0   Max.   :4.000           Max.   :2.0   Max.   :100.00   Max.   :4.00   Max.   :5.000                      Max.   :4.000                     
 MonthlyIncome    MonthlyRate    NumCompaniesWorked    Over18            OverTime         PercentSalaryHike PerformanceRating RelationshipSatisfaction StandardHours
 Min.   : 1009   Min.   : 2094   Min.   :0.000      Length:1470        Length:1470        Min.   :11.00     Min.   :3.000     Min.   :1.000            Min.   :80   
 1st Qu.: 2911   1st Qu.: 8047   1st Qu.:1.000      Class :character   Class :character   1st Qu.:12.00     1st Qu.:3.000     1st Qu.:2.000            1st Qu.:80   
 Median : 4919   Median :14236   Median :2.000      Mode  :character   Mode  :character   Median :14.00     Median :3.000     Median :3.000            Median :80   
 Mean   : 6503   Mean   :14313   Mean   :2.693                                            Mean   :15.21     Mean   :3.154     Mean   :2.712            Mean   :80   
 3rd Qu.: 8379   3rd Qu.:20462   3rd Qu.:4.000                                            3rd Qu.:18.00     3rd Qu.:3.000     3rd Qu.:4.000            3rd Qu.:80   
 Max.   :19999   Max.   :26999   Max.   :9.000                                            Max.   :25.00     Max.   :4.000     Max.   :4.000            Max.   :80   
 StockOptionLevel TotalWorkingYears TrainingTimesLastYear WorkLifeBalance YearsAtCompany   YearsInCurrentRole YearsSinceLastPromotion YearsWithCurrManager
 Min.   :0.0000   Min.   : 0.00     Min.   :0.000         Min.   :1.000   Min.   : 0.000   Min.   : 0.000     Min.   : 0.000          Min.   : 0.000      
 1st Qu.:0.0000   1st Qu.: 6.00     1st Qu.:2.000         1st Qu.:2.000   1st Qu.: 3.000   1st Qu.: 2.000     1st Qu.: 0.000          1st Qu.: 2.000      
 Median :1.0000   Median :10.00     Median :3.000         Median :3.000   Median : 5.000   Median : 3.000     Median : 1.000          Median : 3.000      
 Mean   :0.7939   Mean   :11.28     Mean   :2.799         Mean   :2.761   Mean   : 7.008   Mean   : 4.229     Mean   : 2.188          Mean   : 4.123      
 3rd Qu.:1.0000   3rd Qu.:15.00     3rd Qu.:3.000         3rd Qu.:3.000   3rd Qu.: 9.000   3rd Qu.: 7.000     3rd Qu.: 3.000          3rd Qu.: 7.000      
 Max.   :3.0000   Max.   :40.00     Max.   :6.000         Max.   :4.000   Max.   :40.000   Max.   :18.000     Max.   :15.000          Max.   :17.000      
age <- mydata$Age
education <- mydata$Education
monthly_income <- mydata$MonthlyIncome
gender <-mydata$Gender
YearsAtCompany <- mydata$YearsAtCompany
YearsSinceLastPromotion <-mydata$YearsSinceLastPromotion
WorkLifeBalance <- mydata$WorkLifeBalance
PerformanceRating <- mydata$PerformanceRating
Overtime <- mydata$OverTime
EducationField <- mydata$EducationField
TotalWorkingYears <- mydata$TotalWorkingYears
TrainingTimesLastYear <- mydata$TrainingTimesLastYear

3C) Save a new clean dataset

write_csv(x = mydata, path = "C:\\Users\\hp\\Documents\\Spring 2018\\BSAD 343H\\BSAD343H Project\\hr\\Gender\\clean_employee_attrition.csv")

Data Analysis: Descriptive Statistics, Correlations


4A) Basic descriptive statistics of the new clean dataset (write down any observations)

summary(mydata)
      Age         Attrition         BusinessTravel       DailyRate       Department        DistanceFromHome   Education     EducationField     EmployeeCount
 Min.   :18.00   Length:1470        Length:1470        Min.   : 102.0   Length:1470        Min.   : 1.000   Min.   :1.000   Length:1470        Min.   :1    
 1st Qu.:30.00   Class :character   Class :character   1st Qu.: 465.0   Class :character   1st Qu.: 2.000   1st Qu.:2.000   Class :character   1st Qu.:1    
 Median :36.00   Mode  :character   Mode  :character   Median : 802.0   Mode  :character   Median : 7.000   Median :3.000   Mode  :character   Median :1    
 Mean   :36.92                                         Mean   : 802.5                      Mean   : 9.193   Mean   :2.913                      Mean   :1    
 3rd Qu.:43.00                                         3rd Qu.:1157.0                      3rd Qu.:14.000   3rd Qu.:4.000                      3rd Qu.:1    
 Max.   :60.00                                         Max.   :1499.0                      Max.   :29.000   Max.   :5.000                      Max.   :1    
 EmployeeNumber   EnvironmentSatisfaction     Gender      HourlyRate     JobInvolvement    JobLevel       JobRole          JobSatisfaction MaritalStatus     
 Min.   :   1.0   Min.   :1.000           Min.   :1.0   Min.   : 30.00   Min.   :1.00   Min.   :1.000   Length:1470        Min.   :1.000   Length:1470       
 1st Qu.: 491.2   1st Qu.:2.000           1st Qu.:1.0   1st Qu.: 48.00   1st Qu.:2.00   1st Qu.:1.000   Class :character   1st Qu.:2.000   Class :character  
 Median :1020.5   Median :3.000           Median :2.0   Median : 66.00   Median :3.00   Median :2.000   Mode  :character   Median :3.000   Mode  :character  
 Mean   :1024.9   Mean   :2.722           Mean   :1.6   Mean   : 65.89   Mean   :2.73   Mean   :2.064                      Mean   :2.729                     
 3rd Qu.:1555.8   3rd Qu.:4.000           3rd Qu.:2.0   3rd Qu.: 83.75   3rd Qu.:3.00   3rd Qu.:3.000                      3rd Qu.:4.000                     
 Max.   :2068.0   Max.   :4.000           Max.   :2.0   Max.   :100.00   Max.   :4.00   Max.   :5.000                      Max.   :4.000                     
 MonthlyIncome    MonthlyRate    NumCompaniesWorked    Over18            OverTime         PercentSalaryHike PerformanceRating RelationshipSatisfaction StandardHours
 Min.   : 1009   Min.   : 2094   Min.   :0.000      Length:1470        Length:1470        Min.   :11.00     Min.   :3.000     Min.   :1.000            Min.   :80   
 1st Qu.: 2911   1st Qu.: 8047   1st Qu.:1.000      Class :character   Class :character   1st Qu.:12.00     1st Qu.:3.000     1st Qu.:2.000            1st Qu.:80   
 Median : 4919   Median :14236   Median :2.000      Mode  :character   Mode  :character   Median :14.00     Median :3.000     Median :3.000            Median :80   
 Mean   : 6503   Mean   :14313   Mean   :2.693                                            Mean   :15.21     Mean   :3.154     Mean   :2.712            Mean   :80   
 3rd Qu.: 8379   3rd Qu.:20462   3rd Qu.:4.000                                            3rd Qu.:18.00     3rd Qu.:3.000     3rd Qu.:4.000            3rd Qu.:80   
 Max.   :19999   Max.   :26999   Max.   :9.000                                            Max.   :25.00     Max.   :4.000     Max.   :4.000            Max.   :80   
 StockOptionLevel TotalWorkingYears TrainingTimesLastYear WorkLifeBalance YearsAtCompany   YearsInCurrentRole YearsSinceLastPromotion YearsWithCurrManager
 Min.   :0.0000   Min.   : 0.00     Min.   :0.000         Min.   :1.000   Min.   : 0.000   Min.   : 0.000     Min.   : 0.000          Min.   : 0.000      
 1st Qu.:0.0000   1st Qu.: 6.00     1st Qu.:2.000         1st Qu.:2.000   1st Qu.: 3.000   1st Qu.: 2.000     1st Qu.: 0.000          1st Qu.: 2.000      
 Median :1.0000   Median :10.00     Median :3.000         Median :3.000   Median : 5.000   Median : 3.000     Median : 1.000          Median : 3.000      
 Mean   :0.7939   Mean   :11.28     Mean   :2.799         Mean   :2.761   Mean   : 7.008   Mean   : 4.229     Mean   : 2.188          Mean   : 4.123      
 3rd Qu.:1.0000   3rd Qu.:15.00     3rd Qu.:3.000         3rd Qu.:3.000   3rd Qu.: 9.000   3rd Qu.: 7.000     3rd Qu.: 3.000          3rd Qu.: 7.000      
 Max.   :3.0000   Max.   :40.00     Max.   :6.000         Max.   :4.000   Max.   :40.000   Max.   :18.000     Max.   :15.000          Max.   :17.000      

Based on this data, we ca see max and min values for the data set variables. However, not all of them add value/provide meaningful implications. The variables that are meaningful are as follows: -Age -Monthly_Income/Hourly Rate/Monthly Rate (and other means of pay) -Performance Rating -Job Satisfaction

With this new clean data set, we can now analyze gender and another variable, like age or monthly_income. ### 4B) Using descriptive statistics explore dataset investigate min and max values

min(age)
[1] 18
max(age)
[1] 60
min(monthly_income)
[1] 1009
max(monthly_income)
[1] 19999

4C) Create a correlation table ( only numeric data ). Note any significant values

data_corr <- cor(monthly_income,education)
data_corr
[1] 0.09496068
Corr <- cor(age, monthly_income)
Corr
[1] 0.4978546

It’s interesting to see that age and monthly_income are better correlated than monthly_income and education, which means age and monthly_income are better predictors of each other than the other relationship.

4D) Create a correlation table ( only numeric data ). Give a brief explanation/guess of why some variables are correlated

The correlation between age and monthly_income indicates that they are positively related, which makes sense as age increases monthly_income increases. If an employee works there or in the business industry for longer, the more he/she will be paid due to experience and skills learned. We could only use age and monthly_income as the other variables are not numeric, but rather ordinal (ranked).


Visual Analytics: Use Table or R to create plots

p <- qplot( x = age, y = monthly_income, data = mydata) +geom_point()
p

p + geom_smooth(method="lm")



Task#5: Visual Analytics - Create a Predictive Model


5A) Based on your hypothesis and observations create a predictive model

linear_model <- lm( monthly_income ~ age, data =mydata ) 
 summary( linear_model )

Call:
lm(formula = monthly_income ~ age, data = mydata)

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

Equation of the line = y = -2970.67 + 256.57x

If two new employees were signed on, one being entry level at 18 years old and the other being senior at 50 years old, we can predict their monthly incomes:

age = 18
y = -2970.67 + 256.57*(age)
y
[1] 1647.59
age = 50
y= -2970.67+256.57*(age)
y
[1] 9857.83

5B) Evaluate the efficiency of model. Note R Square and Adjusted R Square, be suspicious of very high R Squares.

Multiple R-squared:  0.2479,    Adjusted R-squared:  0.2473

The model suggests that these data points are not very suited to the regression line as the R squared value is under 0.5, which is typically a benchmark.Hence, this means that age is not a very good predictor of montly income.Because of this, it is advisable to add other variables to find a better suited relationship.  

5C) Try different models (combination of independent variables). To find a better model if possible.

See images below from various sources:

knitr::include_graphics('C:\\Users\\hp\\Documents\\Spring 2018\\BSAD 343H\\BSAD343H Project\\hr\\Gender\\interesting8.png')

knitr::include_graphics('C:\\Users\\hp\\Documents\\Spring 2018\\BSAD 343H\\BSAD343H Project\\hr\\Gender\\interesting9.png')

5D) Describe your findings. How accurately your model predicts the dependent (target) variable

We couldn’t use other numerical data because the other variables were categorical or ordinal, we decided that a bar graph would be most suitable to illustrate the relationships. In fact, these figures, while they do not offer a better prediction of the dependent variable, definitely offer more insight into our original findings between age and monthly income. For instance, analyzing education field and monthly income, we can identify that employees who have degrees in life sciences are paid more than other degrees. It’s interesting to note how little HR is paid in comparison. Our theory is that there is only a few employees who have that degree. In the other figure that compares gender and pay, it appears that there is a significant gender pay discrepancy. However, this goes against our initial finding. Upon refelction and more analysis, we identified the cause of these two conlficting ideas. This set of data comprises of approximately 60% males and 40% females. Rather than concluding these two findings are unrelated, they actually depict an important attribute about our data, such that females, while there are less, tend to be paid higher due to their seniority roles in the company. Overall, these extra findings provide more insight into our intial finding of monthly income and age, such that education and number of employees who are males or females can affect our first findings. Hence, these extra findings do not predict the dependent variable more accurately, but rather give us more explanation of our current model.

LS0tDQp0aXRsZTogIkhSIFByb2plY3QiDQphdXRob3I6ICJDaGV5ZW5uZSBhbmQgSmF4Ig0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQNCmRhdGU6ICJBcHJpbCAxMCAyMDE4Ig0Kc3VidGl0bGU6ICJCdXNpbmVzcyBBbmFseXRpY3MgSG9ub3JzIC0gRmluYWwgUHJvamVjdCINCi0tLQ0KDQoNCi0tLS0tLS0tLS0tLS0tDQoNCiMjIFRhc2sjMTogQWJvdXQgdGhpcyBQcm9qZWN0DQoNCi0tLS0tLS0tLS0tLS0tDQoNCiMjIyAxQSkgQnJpZWYgZGVzY3JpcHRpb24gb2YgeW91ciBwcm9qZWN0Lg0KVGhlIGdvYWwgb2Ygb3VyIHByb2plY3QgaXMgdG8gYW5hbHl6ZSB0aGUgRW1wbG95ZWUgQXR0cml0aW9uIGRhdGFzZXQgaW4gb3JkZXIgdG8gZmluZCBwYXR0ZXJucyBhbmQgcHJlZGljdGlvbnMuIEJhc2VkIG9uIHRoZSBpbmZvcm1hdGlvbiBnaXZlbiwgd2UgYXJlIGZvY3VzaW5nIG9uIHRoZSBpbXBhY3RzIGFuZCByZWxhdGlvbnNoaXBzIGZyb20gYWdlLCBnZW5kZXIsIGFuZCBlZHVjYXRpb25hbCBiYWNrZ3JvdW5kIGluIHJlc3BlY3QgdG8gb3RoZXIgZmFjdG9ycyBzdWNoIGFzIG51bWJlciBvZiBjb21wYW5pZXMgd29ya2VkIGF0LCBudW1iZXIgb2YgcHJvbW90aW9ucywgc2FsYXJ5IGluY3JlYXNlcywgbW9udGhseSBpbmNvbWUsIGFuZCBvdGhlciBkZXRlcm1pbmFudHMuIFNpbmNlIHRoaXMgZGF0YSBpcyBIdW1hbiBSZXNvdXJjZXMgY2VudHJpYywgdGhlIGRlc2lyZWQgZW5kIHJlc3VsdCBpcyBhbHdheXMgdG8gaWRlbnRpZnkgYW5kIGFsbGV2aWF0ZSBpbmVxdWl0aWVzIHdpdGhpbiB0aGUgY29tcGFueSBpbiBvcmRlciB0byBlbmhhbmNlIHRoZSB2YWx1ZSBjcmVhdGlvbiBtb2RlbCBvZiB0aGUgb3JnYW5pemF0aW9uIGZvciBhbGwgc3Rha2Vob2xkZXJzLg0KDQojIyMgMUIpIFJlc291cmNlcyAtIFBhY2thZ2VzL3NvZnR3YXJlIHVzZSBvbiB0aGUgcHJvamVjdCAoUiwgVGFibGVhdSwgV2F0c29uKQ0KUGFja2FnZXMgdXNlZDogdGlkeXZlcnNlDQpTb2Z0d2FyZSB1c2VkOiBUYWJsZWF1LCBXYXRzb24sIFIsIEV4Y2VsDQoNCiMjIyAxQykgRGF0YSBEZXNjcmlwdGlvbiBzb3VyY2UsIHllYXIsIGNvdW50cnkuDQpUaGVyZSBpcyBubyBpbmZvcm1hdGlvbiBhdmFpbGFibGUgcmVnYXJkaW5nIHRoZSB0aW1lbGluZSBvZiB0aGUgZGF0YSBjb2xsZWN0aW9uLCBpdHMgc291cmNlLCBvciBjb3VudHJ5Lg0KDQojIyMgMUQpIFBvdGVudGlhbCBidXNpbmVzcyBjYXNlcyAoaHlwb3RoZXNpcykNCk91ciBoeXBvdGhlc2lzIGlzIHRoYXQgZ2VuZXJhdGlvbmFsIHN0ZXJlb3R5cGVzIGFuZCBnZW5kZXIgaW5lcXVhbGl0aWVzIHdpbGwgYmUgZWFzaWx5IHJlY29nbml6YWJsZSB3aXRoaW4gdGhlIGRhdGFzZXQsIGkuZS4geW91bmdlciBlbXBsb3llZXMgd2lsbCBoYXZlIHdvcmtlZCBmb3IgbW9yZSBjb21wYW5pZXMgYW5kIHdvbWVuIHdpbGwgYmUgcGFpZCBsZXNzIHRoYW4gbWVuLCBhbW9uZyBvdGhlciBjb25zaWRlcmF0aW9ucy4NCkZvciBSIHN0dWRpbywgd2UgaHlwb3RoZXNpemUgdGhhdCB0aGUgbW9udGhseSBpbmNvbWUgZm9yIGVtcGxveWVlcyBpbmNyZWFzZXMgd2l0aCB0aGVpciBhZ2UgZHVlIHRvIHdvcmsgZXhwZXJpZW5jZSwgc2VuaW9yaXR5IGpvYiBsZXZlbCwgYW5kIHNraWxscy4gDQoNCg0KLS0tLS0tLS0tLS0tLS0NCg0KIyMgVGFzayMyOiBEYXRhIENvbGxlY3Rpb24gLSBJTkRVU1RSWSAtIEhSIA0KDQotLS0tLS0tLS0tLS0tLQ0KDQojIyMgMkEpIEJyaWVmIGRlc2NyaXB0aW9uIGFuZCBrZXkgbWV0cmljcyBvZiB0aGUgcHJvamVjdCBpbmR1c3RyeSAoY29udGV4dCkNClRoZSBpbmR1c3RyeSBvdXIgcHJvamVjdCBpcyBiYXNlZCBvbiBhIHR5cGljYWwgYnVzaW5lc3Mgc2NlbmFyaW8gdGhhdCBpbnZvbHZlcyBlbXBsb3llZXMsIHNhbGFyaWVzLCBlZHVjYXRpb24gYW5kIG90aGVyIGZhY3RvcnMgdGhhdCBtYXkgaW5mbHVlbmNlIGVhY2ggb3RoZXIgc3VjaCBhcyBqb2Igc2F0aXNmYWN0aW9uIGxldmVsLCBqb2IgbGV2ZWwsIG1hcnRpYWwgc3RhdHVzLiBPdXIgcHJvamVjdCBpcyB1c2luZyBkYXRhIGZyb20gYSBIdW1hbiBSZXNvdXJjZXMgcGVyc3BlY3RpdmUsIHdoaWNoIGlzIGFuIGltcG9ydGFudCBmZWF0dXJlIG9mIGEgYnVzaW5lc3MnIHBlcmZvcm1hbmNlLg0KU29tZSBrZXkgbWV0cmljcyBmb3IgdGhpcyBwcm9qZWN0J3MgaW5kdXN0cnkgKHVzaW5nIHRoZSBkYXRhIHdlIGhhdmUgYmVlbiBwcm92aWRlZCB3aXRoKTogDQoxLiBKb2Igc2F0aXNmYWN0aW9uDQoyLiBQZXJmb3JtYW5jZSBSYXRpbmcNCjMuIEF0dHJpdGlvbg0KDQojIyMgMkIpIEV4cGxvcmUgdGhlIGRhdGFzZXQsIG5vdGUgYW55IGludGVyZXN0aW5nIHBhdHRlcm5zIGhpZ2hsaWdodHMNClNlZSBiZWxvdyBmb3IgaW1hZ2VzOg0KDQpgYGB7cn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCdDOlxcVXNlcnNcXGhwXFxEb2N1bWVudHNcXFNwcmluZyAyMDE4XFxCU0FEIDM0M0hcXEJTQUQzNDNIIFByb2plY3RcXGhyXFxHZW5kZXJcXGludGVyZXN0aW5nMS5wbmcnKQ0KDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnQzpcXFVzZXJzXFxocFxcRG9jdW1lbnRzXFxTcHJpbmcgMjAxOFxcQlNBRCAzNDNIXFxCU0FEMzQzSCBQcm9qZWN0XFxoclxcR2VuZGVyXFxpbnRlcmVzdGluZzIucG5nJykNCg0KDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnQzpcXFVzZXJzXFxocFxcRG9jdW1lbnRzXFxTcHJpbmcgMjAxOFxcQlNBRCAzNDNIXFxCU0FEMzQzSCBQcm9qZWN0XFxoclxcR2VuZGVyXFxpbnRlcmVzdGluZzMucG5nJykNCg0KDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnQzpcXFVzZXJzXFxocFxcRG9jdW1lbnRzXFxTcHJpbmcgMjAxOFxcQlNBRCAzNDNIXFxCU0FEMzQzSCBQcm9qZWN0XFxoclxcR2VuZGVyXFxpbnRlcmVzdGluZzQucG5nJykNCg0KDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnQzpcXFVzZXJzXFxocFxcRG9jdW1lbnRzXFxTcHJpbmcgMjAxOFxcQlNBRCAzNDNIXFxCU0FEMzQzSCBQcm9qZWN0XFxoclxcR2VuZGVyXFxpbnRlcmVzdGluZzUucG5nJykNCg0KDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnQzpcXFVzZXJzXFxocFxcRG9jdW1lbnRzXFxTcHJpbmcgMjAxOFxcQlNBRCAzNDNIXFxCU0FEMzQzSCBQcm9qZWN0XFxoclxcR2VuZGVyXFxpbnRlcmVzdGluZzYucG5nJykNCmBgYA0KVGhlIGZpcnN0IGZpZ3VyZSBhbmFseXplcyBhdmVyYWdlIG1vbnRobHlfaW5jb21lIGFuZCBhZ2UuIEl0J3MgaW50ZXJlc3RpbmcgdGhhdCBGZW1hbGVzIGVhcm4gbW9yZSB0aGFuIG1hbGVzIGluIGdlbmVyYWwsIHdoaWNoIHdhcyBub3QgZXhwZWN0ZWQuDQpUaGUgc2Vjb25kIGFuYWx5emVzIGF2ZXJhZ2Ugd29yayBsaWZlIGJhbGFuY2UgYW5kIGFnZS4gSXQncyBpbnRlcmVzdGluZyB0aGF0IEZlbWFsZXMgaGF2ZSBtdWNoIGxvd2VyIHdvcmsgbGlmZSBiYWxhbmNlIGR1cmluZyB0aGUgeWVhcnMgMjItMjQuIE9uZSB0aGVvcnkgaXMgdGhhdCB0aGV5IGFyZSBlbnRyeSBsZXZlbCBncmFkcyB3aG8gYXJlIHN0aWxsIHRyeWluZyB0byBmaW5kIHRoZWlyIHBhc3Npb24gb3Igd29ya2luZyBleHRyZW1lbHkgaGFyZCB0byBwcm92ZSB0aGVtc2VsdmVzLg0KVGhlIHRoaXJkIGFuYWx5emVzIGF2ZSBudW1iZXIgb2YgY29tcGFuaWVzIHdvcmtlZCBhbmQgYWdlLiBUaGlzIGlzIGludGVyZXN0aW5nLCBiZWNhdXNlIHdlIHdlcmUgdW5kZXIgdGhlIGltcHJlc3Npb24gdGhlIHByZXZpb3VzIGdlbmVyYXRpb24gZGlkIG5vdCBoYXZlIGFzIG11Y2ggZmx1Y3R1YXRpb25zIGluIGNhcmVlcnMgYXMgb3VyIGdlbmVyYXRpb24uIA0KVGhlIGZvdXJ0aCBhbmFseXplcyBhdmVyYWdlIHBlcmZvbWFuY2UgcmF0aW5nIGFuZCBhZ2UsIHdoaWNoIGlzIGNvbXBhcmVkIHRvIGF2ZXJhZ2UgcGVyY2VudCBzYWxhcnkgcmF0ZS4gSXQncyBpbnRlcmVzdGluZyB0aGF0IHRoZSBmaXJzdCB5ZWFycyBoYXZlIGEgcGVhayBpbiBwZXJmb3JtYW5jZSBhbmQgcGF5LCBidXQgdGVuZHMgdG8gc3RhZ25hbnQgaW4gdGhlIGZvbGxvd2luZyB5ZWFycy4NClRoZSBmaWZ0aCBkZW1vbnN0cmF0ZXMgYWdlIHZzLiByb3dzLCB3aGljaCBhbmFseXplcyB0aGUgYW1vdW50IG9mIGVtcGxveWVlcyBpbiB0aGF0IGFnZSBncm91cC4gSXQncyBpbnRlcmVzdGluZyB0byBub3RlIHRoZSBiZWxsIGN1cnZlIHNoYXBlIHRvIHRoaXMgZmlndXJlLCBidXQgaXQgbWFrZXMgc2Vuc2UgdGhhdCB0aGVyZSBhcmUgbG93IG51bWJlcnMgb2YgZW50cnkgbGV2ZWxzIGFuZCBzZW5pb3IgbWFuYWdlbWVudCBkdWUgdG8gcmVjcnVpdGluZyB5b3V0aCBhbmQgcmV0aXJpbmcgc2VuaW9ycy4gDQpUaGUgc2l4dGggc2hvd3MgdGhlIG1haW4gZHJpdmVycyBvZiBtb250aGx5IGluY29tZSwgYmVpbmcgam9iIGxldmVsLCBqb2Igcm9sZSBhbmQgdG90YWwgd29ya2luZyB5ZWFycy4gVGhlIGxvbmdlciB5b3Ugc3RheSBhdCB0aGlzIGNvbXBhbnksIHRoZSBtb3JlIHlvdSdsbCBnZXQgcGFpZC4gDQoNCiMjIyAyQykgUGFyYWdyYXBoIHVzaW5nIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3MNClRoZXNlIGdyYXBocyBpbGx1c3RyYXRlIHZhcmlvdXMgd2F5cyBvZiBhbmFseXNpbmcgb3VyIHNldCBvZiBkYXRhLiBVc2luZyBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzLCBXYXRzb24gcHJvdmlkZXMgbW9zdCBpbnNpZ2h0IGluIHRoaXMgcmVzcGVjdC4gV2Ugbm90aWNlIHRoYXQgSm9iTGV2ZWwgYW5kIEpvYlJvbGUgYXJlIHRoZSAyIHN0cm9uZ2VzdCB2YXJpYWJsZXMgdGhhdCBkcml2ZSBtb250aGx5IGluY29tZS4gV2hlbiBhbmFseXppbmcgdGhlIG1vbnRobHkgaW5jb21lIHZzLiBhZ2UsIHRoZXJlIGFwcGVhcnMgdG8gYmUgYSBnZW5lcmFsIHBvc2l0aXZlIHRyZW5kbGluZS4gV2Ugd2FudGVkIHRvIGludGVncmF0ZSBhIHRoaXJkIHZhcmlhYmxlLCBiZWluZyBnZW5kZXIgZm9yIGNvbXBhcmlzb24uIFdlIGZvdW5kIHRoYXQgd29tZW4gdGVuZCB0byBiZSBwYWlkIG1vcmUgaW4gZ2VuZXJhbCwgd2hpY2ggaXMgcXVpdGUgaW50ZXJlc3RpbmcgYW5kIGFnYWluc3Qgb3VyIGluaXRpYWwgaHlwb3RoZXNpcy4gVGhpcyBoYXMgZHJpdmVuIHVzIHRvIGRpc2NvdmVyIHdoYXQgYXJlIHRoZSBkaXNjcmVwYW5jaWVzIGJldHdlZW4gcGF5LCBmcm9tIGpvYiByb2xlLCBudW1iZXIgb2YgY29tcGFuaWVzIHdvcmtlZCBhdCBhbmQgcGVyZm9ybWFuY2UgbGV2ZWxzLg0KDQotLS0tLS0tLS0tLS0tLQ0KDQojIyBUYXNrIzM6IERhdGEgUHJlcGFyYXRpb24gLSBDbGVhbmluZyBhbmQgcHJlcGFyaW5nIHRoZSBkYXRhIGZvciBhbmFseXNpcw0KDQotLS0tLS0tLS0tLS0tLQ0KDQojIyMgM0EpIERlc2NyaWJlIHRoZSBzdGVwcyB0byBjbGVhbmluZyBhbmQgcHJlcGFyZSB0aGUgZGF0YSBmb3IgYW5hbHlzaXMuIE1ha2UgYW4gYXJndW1lbnQgb2Ygd2h5IHRob3NlIHN0ZXBzIGFyZSBuZWNlc3NhcnkuDQoNCkRhdGEgY2xlYW5zaW5nIGlzIGFuIGltcG9ydGFudCBwcm9jZXNzLCBhcyBpdCBtYWtlcyBkYXRhIG1vcmUgbWFuYWdlYWJsZSBhbmQgYWxsb3dzIGZvciBzb21lIHZhcmlhYmxlcyB0aGF0IGFyZSBjaGFyYWN0ZXJpc3RpYyB0byBiZSBpbnRlcnByZXRlZC4gDQoNCiMjIyAzQikgQ2xlYW4gdGhlIGRhdGENCmBgYHtyfQ0KbXlkYXRhIDwtIHJlYWRfY3N2KCJDOlxcVXNlcnNcXGhwXFxEb2N1bWVudHNcXFNwcmluZyAyMDE4XFxCU0FEIDM0M0hcXEJTQUQzNDNIIFByb2plY3RcXGhyXFxHZW5kZXJcXGVtcGxveWVlX2F0dHJpdGlvbi5jc3YiKQ0KDQpoZWFkKG15ZGF0YSkNCnN1bW1hcnkobXlkYXRhKQ0KYGBgDQoNCg0KYGBge3J9DQphZ2UgPC0gbXlkYXRhJEFnZQ0KZWR1Y2F0aW9uIDwtIG15ZGF0YSRFZHVjYXRpb24NCm1vbnRobHlfaW5jb21lIDwtIG15ZGF0YSRNb250aGx5SW5jb21lDQpnZW5kZXIgPC1teWRhdGEkR2VuZGVyDQpZZWFyc0F0Q29tcGFueSA8LSBteWRhdGEkWWVhcnNBdENvbXBhbnkNClllYXJzU2luY2VMYXN0UHJvbW90aW9uIDwtbXlkYXRhJFllYXJzU2luY2VMYXN0UHJvbW90aW9uDQpXb3JrTGlmZUJhbGFuY2UgPC0gbXlkYXRhJFdvcmtMaWZlQmFsYW5jZQ0KUGVyZm9ybWFuY2VSYXRpbmcgPC0gbXlkYXRhJFBlcmZvcm1hbmNlUmF0aW5nDQpPdmVydGltZSA8LSBteWRhdGEkT3ZlclRpbWUNCkVkdWNhdGlvbkZpZWxkIDwtIG15ZGF0YSRFZHVjYXRpb25GaWVsZA0KVG90YWxXb3JraW5nWWVhcnMgPC0gbXlkYXRhJFRvdGFsV29ya2luZ1llYXJzDQpUcmFpbmluZ1RpbWVzTGFzdFllYXIgPC0gbXlkYXRhJFRyYWluaW5nVGltZXNMYXN0WWVhcg0KDQoNCg0KYGBgDQoNCiMjIyAzQykgU2F2ZSBhIG5ldyBjbGVhbiBkYXRhc2V0DQpgYGB7cn0NCndyaXRlX2Nzdih4ID0gbXlkYXRhLCBwYXRoID0gIkM6XFxVc2Vyc1xcaHBcXERvY3VtZW50c1xcU3ByaW5nIDIwMThcXEJTQUQgMzQzSFxcQlNBRDM0M0ggUHJvamVjdFxcaHJcXEdlbmRlclxcY2xlYW5fZW1wbG95ZWVfYXR0cml0aW9uLmNzdiIpDQpgYGANCg0KLS0tLS0tLS0tLS0tLS0NCg0KIyMgRGF0YSBBbmFseXNpczogRGVzY3JpcHRpdmUgU3RhdGlzdGljcywgQ29ycmVsYXRpb25zDQoNCi0tLS0tLS0tLS0tLS0tDQoNCiMjIyA0QSkgQmFzaWMgZGVzY3JpcHRpdmUgc3RhdGlzdGljcyBvZiB0aGUgbmV3IGNsZWFuIGRhdGFzZXQgKHdyaXRlIGRvd24gYW55IG9ic2VydmF0aW9ucykNCmBgYHtyfQ0Kc3VtbWFyeShteWRhdGEpDQoNCmBgYA0KDQpCYXNlZCBvbiB0aGlzIGRhdGEsIHdlIGNhIHNlZSBtYXggYW5kIG1pbiB2YWx1ZXMgZm9yIHRoZSBkYXRhIHNldCB2YXJpYWJsZXMuIEhvd2V2ZXIsIG5vdCBhbGwgb2YgdGhlbSBhZGQgdmFsdWUvcHJvdmlkZSBtZWFuaW5nZnVsIGltcGxpY2F0aW9ucy4gVGhlIHZhcmlhYmxlcyB0aGF0IGFyZSBtZWFuaW5nZnVsIGFyZSBhcyBmb2xsb3dzOg0KLUFnZSANCi1Nb250aGx5X0luY29tZS9Ib3VybHkgUmF0ZS9Nb250aGx5IFJhdGUgKGFuZCBvdGhlciBtZWFucyBvZiBwYXkpDQotUGVyZm9ybWFuY2UgUmF0aW5nIA0KLUpvYiBTYXRpc2ZhY3Rpb24NCg0KV2l0aCB0aGlzIG5ldyBjbGVhbiBkYXRhIHNldCwgd2UgY2FuIG5vdyBhbmFseXplIGdlbmRlciBhbmQgYW5vdGhlciB2YXJpYWJsZSwgbGlrZSBhZ2Ugb3IgbW9udGhseV9pbmNvbWUuIA0KIyMjIDRCKSBVc2luZyBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGV4cGxvcmUgZGF0YXNldCBpbnZlc3RpZ2F0ZSBtaW4gYW5kIG1heCB2YWx1ZXMNCmBgYHtyfQ0KbWluKGFnZSkNCm1heChhZ2UpDQpgYGANCmBgYHtyfQ0KbWluKG1vbnRobHlfaW5jb21lKQ0KbWF4KG1vbnRobHlfaW5jb21lKQ0KYGBgDQoNCg0KIyMjIDRDKSBDcmVhdGUgYSBjb3JyZWxhdGlvbiB0YWJsZSAoIG9ubHkgbnVtZXJpYyBkYXRhICkuIE5vdGUgYW55IHNpZ25pZmljYW50IHZhbHVlcw0KDQpgYGB7cn0NCmRhdGFfY29yciA8LSBjb3IobW9udGhseV9pbmNvbWUsZWR1Y2F0aW9uKQ0KZGF0YV9jb3JyDQoNCkNvcnIgPC0gY29yKGFnZSwgbW9udGhseV9pbmNvbWUpDQpDb3JyDQoNCmBgYA0KDQoNCkl0J3MgaW50ZXJlc3RpbmcgdG8gc2VlIHRoYXQgYWdlIGFuZCBtb250aGx5X2luY29tZSBhcmUgYmV0dGVyIGNvcnJlbGF0ZWQgdGhhbiBtb250aGx5X2luY29tZSBhbmQgZWR1Y2F0aW9uLCB3aGljaCBtZWFucyBhZ2UgYW5kIG1vbnRobHlfaW5jb21lIGFyZSBiZXR0ZXIgcHJlZGljdG9ycyBvZiBlYWNoIG90aGVyIHRoYW4gdGhlIG90aGVyIHJlbGF0aW9uc2hpcC4NCg0KIyMjIDREKSBDcmVhdGUgYSBjb3JyZWxhdGlvbiB0YWJsZSAoIG9ubHkgbnVtZXJpYyBkYXRhICkuIEdpdmUgYSBicmllZiBleHBsYW5hdGlvbi9ndWVzcyBvZiB3aHkgc29tZSB2YXJpYWJsZXMgYXJlIGNvcnJlbGF0ZWQNCg0KVGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gYWdlIGFuZCBtb250aGx5X2luY29tZSBpbmRpY2F0ZXMgdGhhdCB0aGV5IGFyZSBwb3NpdGl2ZWx5IHJlbGF0ZWQsIHdoaWNoIG1ha2VzIHNlbnNlIGFzIGFnZSBpbmNyZWFzZXMgbW9udGhseV9pbmNvbWUgaW5jcmVhc2VzLiBJZiBhbiBlbXBsb3llZSB3b3JrcyB0aGVyZSBvciBpbiB0aGUgYnVzaW5lc3MgaW5kdXN0cnkgZm9yIGxvbmdlciwgdGhlIG1vcmUgaGUvc2hlIHdpbGwgYmUgcGFpZCBkdWUgdG8gZXhwZXJpZW5jZSBhbmQgc2tpbGxzIGxlYXJuZWQuIFdlIGNvdWxkIG9ubHkgdXNlIGFnZSBhbmQgbW9udGhseV9pbmNvbWUgYXMgdGhlIG90aGVyIHZhcmlhYmxlcyBhcmUgbm90IG51bWVyaWMsIGJ1dCByYXRoZXIgb3JkaW5hbCAocmFua2VkKS4NCg0KDQotLS0tLS0tLS0tLS0tLQ0KDQojIyBWaXN1YWwgQW5hbHl0aWNzOiBVc2UgVGFibGUgb3IgUiB0byBjcmVhdGUgcGxvdHMgDQoNCg0KYGBge3J9DQoNCnAgPC0gcXBsb3QoIHggPSBhZ2UsIHkgPSBtb250aGx5X2luY29tZSwgZGF0YSA9IG15ZGF0YSkgK2dlb21fcG9pbnQoKQ0KcA0KDQpwICsgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpDQoNCmBgYA0KDQoNCi0tLS0tLS0tLS0tLS0tDQoNCi0tLS0tLS0tLS0tLS0tDQoNCiMjIFRhc2sjNTogVmlzdWFsIEFuYWx5dGljcyAtIENyZWF0ZSBhIFByZWRpY3RpdmUgTW9kZWwNCg0KLS0tLS0tLS0tLS0tLS0NCg0KIyMjIDVBKSBCYXNlZCBvbiB5b3VyIGh5cG90aGVzaXMgYW5kIG9ic2VydmF0aW9ucyBjcmVhdGUgYSBwcmVkaWN0aXZlIG1vZGVsDQoNCg0KYGBge3J9DQpsaW5lYXJfbW9kZWwgPC0gbG0oIG1vbnRobHlfaW5jb21lIH4gYWdlLCBkYXRhID1teWRhdGEgKSANCmBgYA0KYGBge3J9DQogc3VtbWFyeSggbGluZWFyX21vZGVsICkNCg0KYGBgDQpFcXVhdGlvbiBvZiB0aGUgbGluZSA9IHkgPSAtMjk3MC42NyArIDI1Ni41N3gNCiAgDQoNCg0KSWYgdHdvIG5ldyBlbXBsb3llZXMgd2VyZSBzaWduZWQgb24sIG9uZSBiZWluZyBlbnRyeSBsZXZlbCBhdCAxOCB5ZWFycyBvbGQgYW5kIHRoZSBvdGhlciBiZWluZyBzZW5pb3IgYXQgNTAgeWVhcnMgb2xkLCB3ZSBjYW4gcHJlZGljdCB0aGVpciBtb250aGx5IGluY29tZXM6DQoNCmBgYHtyfQ0KYWdlID0gMTgNCg0KeSA9IC0yOTcwLjY3ICsgMjU2LjU3KihhZ2UpDQp5DQpgYGANCmBgYHtyfQ0KYWdlID0gNTANCg0KeT0gLTI5NzAuNjcrMjU2LjU3KihhZ2UpDQp5DQpgYGANCg0KDQojIyMgNUIpIEV2YWx1YXRlIHRoZSBlZmZpY2llbmN5IG9mIG1vZGVsLiBOb3RlIFIgU3F1YXJlIGFuZCBBZGp1c3RlZCBSIFNxdWFyZSwgYmUgc3VzcGljaW91cyBvZiB2ZXJ5IGhpZ2ggUiBTcXVhcmVzLg0KYGBge3J9DQpNdWx0aXBsZSBSLXNxdWFyZWQ6ICAwLjI0NzksCUFkanVzdGVkIFItc3F1YXJlZDogIDAuMjQ3Mw0KDQpUaGUgbW9kZWwgc3VnZ2VzdHMgdGhhdCB0aGVzZSBkYXRhIHBvaW50cyBhcmUgbm90IHZlcnkgc3VpdGVkIHRvIHRoZSByZWdyZXNzaW9uIGxpbmUgYXMgdGhlIFIgc3F1YXJlZCB2YWx1ZSBpcyB1bmRlciAwLjUsIHdoaWNoIGlzIHR5cGljYWxseSBhIGJlbmNobWFyay5IZW5jZSwgdGhpcyBtZWFucyB0aGF0IGFnZSBpcyBub3QgYSB2ZXJ5IGdvb2QgcHJlZGljdG9yIG9mIG1vbnRseSBpbmNvbWUuQmVjYXVzZSBvZiB0aGlzLCBpdCBpcyBhZHZpc2FibGUgdG8gYWRkIG90aGVyIHZhcmlhYmxlcyB0byBmaW5kIGEgYmV0dGVyIHN1aXRlZCByZWxhdGlvbnNoaXAuICANCg0KYGBgDQoNCg0KIyMjIDVDKSBUcnkgZGlmZmVyZW50IG1vZGVscyAoY29tYmluYXRpb24gb2YgaW5kZXBlbmRlbnQgdmFyaWFibGVzKS4gVG8gZmluZCBhIGJldHRlciBtb2RlbCBpZiBwb3NzaWJsZS4NClNlZSBpbWFnZXMgYmVsb3cgZnJvbSB2YXJpb3VzIHNvdXJjZXM6IA0KDQpgYGB7cn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCdDOlxcVXNlcnNcXGhwXFxEb2N1bWVudHNcXFNwcmluZyAyMDE4XFxCU0FEIDM0M0hcXEJTQUQzNDNIIFByb2plY3RcXGhyXFxHZW5kZXJcXGludGVyZXN0aW5nOC5wbmcnKQ0KDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnQzpcXFVzZXJzXFxocFxcRG9jdW1lbnRzXFxTcHJpbmcgMjAxOFxcQlNBRCAzNDNIXFxCU0FEMzQzSCBQcm9qZWN0XFxoclxcR2VuZGVyXFxpbnRlcmVzdGluZzkucG5nJykNCg0KDQpgYGANCg0KDQojIyMgNUQpIERlc2NyaWJlIHlvdXIgZmluZGluZ3MuIEhvdyBhY2N1cmF0ZWx5IHlvdXIgbW9kZWwgcHJlZGljdHMgdGhlIGRlcGVuZGVudCAodGFyZ2V0KSB2YXJpYWJsZQ0KDQpXZSBjb3VsZG4ndCB1c2Ugb3RoZXIgbnVtZXJpY2FsIGRhdGEgYmVjYXVzZSB0aGUgb3RoZXIgdmFyaWFibGVzIHdlcmUgY2F0ZWdvcmljYWwgb3Igb3JkaW5hbCwgd2UgZGVjaWRlZCB0aGF0IGEgYmFyIGdyYXBoIHdvdWxkIGJlIG1vc3Qgc3VpdGFibGUgdG8gaWxsdXN0cmF0ZSB0aGUgcmVsYXRpb25zaGlwcy4gSW4gZmFjdCwgdGhlc2UgZmlndXJlcywgd2hpbGUgdGhleSBkbyBub3Qgb2ZmZXIgYSBiZXR0ZXIgcHJlZGljdGlvbiBvZiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLCBkZWZpbml0ZWx5IG9mZmVyIG1vcmUgaW5zaWdodCBpbnRvIG91ciBvcmlnaW5hbCBmaW5kaW5ncyBiZXR3ZWVuIGFnZSBhbmQgbW9udGhseSBpbmNvbWUuIEZvciBpbnN0YW5jZSwgYW5hbHl6aW5nIGVkdWNhdGlvbiBmaWVsZCBhbmQgbW9udGhseSBpbmNvbWUsIHdlIGNhbiBpZGVudGlmeSB0aGF0IGVtcGxveWVlcyB3aG8gaGF2ZSBkZWdyZWVzIGluIGxpZmUgc2NpZW5jZXMgYXJlIHBhaWQgbW9yZSB0aGFuIG90aGVyIGRlZ3JlZXMuIEl0J3MgaW50ZXJlc3RpbmcgdG8gbm90ZSBob3cgbGl0dGxlIEhSIGlzIHBhaWQgaW4gY29tcGFyaXNvbi4gT3VyIHRoZW9yeSBpcyB0aGF0IHRoZXJlIGlzIG9ubHkgYSBmZXcgZW1wbG95ZWVzIHdobyBoYXZlIHRoYXQgZGVncmVlLiBJbiB0aGUgb3RoZXIgZmlndXJlIHRoYXQgY29tcGFyZXMgZ2VuZGVyIGFuZCBwYXksIGl0IGFwcGVhcnMgdGhhdCB0aGVyZSBpcyBhIHNpZ25pZmljYW50IGdlbmRlciBwYXkgZGlzY3JlcGFuY3kuIEhvd2V2ZXIsIHRoaXMgZ29lcyBhZ2FpbnN0IG91ciBpbml0aWFsIGZpbmRpbmcuIFVwb24gcmVmZWxjdGlvbiBhbmQgbW9yZSBhbmFseXNpcywgd2UgaWRlbnRpZmllZCB0aGUgY2F1c2Ugb2YgdGhlc2UgdHdvIGNvbmxmaWN0aW5nIGlkZWFzLiBUaGlzIHNldCBvZiBkYXRhIGNvbXByaXNlcyBvZiBhcHByb3hpbWF0ZWx5IDYwJSBtYWxlcyBhbmQgNDAlIGZlbWFsZXMuIFJhdGhlciB0aGFuIGNvbmNsdWRpbmcgdGhlc2UgdHdvIGZpbmRpbmdzIGFyZSB1bnJlbGF0ZWQsIHRoZXkgYWN0dWFsbHkgZGVwaWN0IGFuIGltcG9ydGFudCBhdHRyaWJ1dGUgYWJvdXQgb3VyIGRhdGEsIHN1Y2ggdGhhdCBmZW1hbGVzLCB3aGlsZSB0aGVyZSBhcmUgbGVzcywgdGVuZCB0byBiZSBwYWlkIGhpZ2hlciBkdWUgdG8gdGhlaXIgc2VuaW9yaXR5IHJvbGVzIGluIHRoZSBjb21wYW55LiANCk92ZXJhbGwsIHRoZXNlIGV4dHJhIGZpbmRpbmdzIHByb3ZpZGUgbW9yZSBpbnNpZ2h0IGludG8gb3VyIGludGlhbCBmaW5kaW5nIG9mIG1vbnRobHkgaW5jb21lIGFuZCBhZ2UsIHN1Y2ggdGhhdCBlZHVjYXRpb24gYW5kIG51bWJlciBvZiBlbXBsb3llZXMgd2hvIGFyZSBtYWxlcyBvciBmZW1hbGVzIGNhbiBhZmZlY3Qgb3VyIGZpcnN0IGZpbmRpbmdzLiBIZW5jZSwgdGhlc2UgZXh0cmEgZmluZGluZ3MgZG8gbm90IHByZWRpY3QgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBtb3JlIGFjY3VyYXRlbHksIGJ1dCByYXRoZXIgZ2l2ZSB1cyBtb3JlIGV4cGxhbmF0aW9uIG9mIG91ciBjdXJyZW50IG1vZGVsLg0K