Analysis of Survey Data

In this document, we will analyze the survey data to extract meaningful insights

Vectors

To start, we import the dataset and extract the vector of satisfaction ratings and calculate the mean and median.

names(survey_data)
[1] "RespondentID" "Age"          "Gender"       "Satisfaction" "Department"  
###We would like to extract the vector of satisfaction ratings.
satisfaction_ratings <- survey_data$Satisfaction
head(satisfaction_ratings)
[1] 8 6 7 5 7 7
# Calculate the mean
mean_satisfaction <- mean(satisfaction_ratings, na.rm = TRUE)
# Display the mean
mean_satisfaction
[1] 6.65
# Calculate the median
median_satisfaction <- median(satisfaction_ratings, na.rm = TRUE)

# Display the median
median_satisfaction
[1] 7
mean_satisfaction
[1] 6.65
median_satisfaction
[1] 7
### The mean of the satisfaction ratings is 6.65 and the median is 7.

If we need to look specifically at satisfaction ratings for the HR department, we need to create a vector for the ages of respondents in the HR department specifically, and then calculate the mean of just those respondents.

names(survey_data)
[1] "RespondentID" "Age"          "Gender"       "Satisfaction" "Department"  
# Create a vector of ages for respondents in the 'HR' department
ages_in_HR <- survey_data$Age[survey_data$Department == "HR"]
ages_in_HR
[1] 25 29 27 39
# Calculate the average age of HR respondents
average_age_HR <- mean(ages_in_HR, na.rm = TRUE)

# Display the average age
average_age_HR
[1] 30
# Extract ages of respondents in the 'HR' department
ages_in_HR <- survey_data$Age[survey_data$Department == "HR"]

# Calculate the average age
average_age_HR <- mean(ages_in_HR, na.rm = TRUE)

# Display the average age
average_age_HR
[1] 30
# Print a formatted message
print(paste("The average age of HR respondents is", round(average_age_HR, 2), "years."))
[1] "The average age of HR respondents is 30 years."

Matrices
Next we will create a matrix of satisfaction ratings and then transpose it.

# Extract Age and Satisfaction columns
age <- survey_data$Age
satisfaction <- survey_data$Satisfaction
# Combine Age and Satisfaction into a matrix
age_satisfaction_matrix <- cbind(age, satisfaction)
# View the first few rows of the matrix
head(age_satisfaction_matrix)
     age satisfaction
[1,]  25            8
[2,]  34            6
[3,]  28            7
[4,]  45            5
[5,]  30            7
[6,]  22            7
# Extract Age and Satisfaction from the matrix
ages <- age_satisfaction_matrix[, "age"]
satisfactions <- age_satisfaction_matrix[, "satisfaction"]
# Compute the mean satisfaction rating for each age group
mean_satisfaction_by_age <- tapply(satisfactions, ages, mean, na.rm = TRUE)

# Display the results
mean_satisfaction_by_age
 22  25  26  27  28  29  30  31  33  34  35  38  39  40  42  45  46  50 
7.0 8.0 5.0 7.0 6.5 8.0 7.0 7.0 8.0 6.0 6.0 6.0 7.0 4.0 8.0 5.0 7.0 7.0 
# Set column name
colnames(mean_satisfaction_matrix) <- "Mean_Satisfaction"
mean_satisfaction_matrix
          Mean_Satisfaction
Finance                 6.4
HR                      7.5
IT                      6.5
Marketing               6.4
# Transpose the matrix
transposed_matrix <- t(mean_satisfaction_matrix)

# Display the transposed matrix
transposed_matrix
                  Finance  HR  IT Marketing
Mean_Satisfaction     6.4 7.5 6.5       6.4
# Create a matrix with multiple metrics
dept_metrics_matrix <- cbind(
  Mean_Satisfaction = mean_satisfaction_by_dept,
  Mean_Age = tapply(survey_data$Age, department, mean, na.rm = TRUE),
  Employee_Count = tapply(rep(1, length(department)), department, sum)
)

# Convert to matrix
dept_metrics_matrix <- as.matrix(dept_metrics_matrix)

# Display the matrix
dept_metrics_matrix
          Mean_Satisfaction Mean_Age Employee_Count
Finance                 6.4 37.60000              5
HR                      7.5 30.00000              4
IT                      6.5 31.33333              6
Marketing               6.4 36.60000              5
# Transpose the matrix
transposed_matrix <- t(dept_metrics_matrix)

# Display the transposed matrix
transposed_matrix
                  Finance   HR       IT Marketing
Mean_Satisfaction     6.4  7.5  6.50000       6.4
Mean_Age             37.6 30.0 31.33333      36.6
Employee_Count        5.0  4.0  6.00000       5.0
# Calculate the mean of each column (department)
mean_per_department <- colMeans(transposed_matrix, na.rm = TRUE)

# Display the results
mean_per_department
  Finance        HR        IT Marketing 
 16.33333  13.83333  14.61111  16.00000 

Dataframes

# Step 1: Compute metrics for each department
mean_satisfaction_by_dept <- tapply(survey_data$Satisfaction, survey_data$Department, mean, na.rm = TRUE)
mean_age_by_dept <- tapply(survey_data$Age, survey_data$Department, mean, na.rm = TRUE)
employee_count_by_dept <- tapply(rep(1, nrow(survey_data)), survey_data$Department, sum)
# Convert the results into a data frame
mean_satisfaction_df <- data.frame(
  Age = as.numeric(names(mean_satisfaction_by_age)),
  Mean_Satisfaction = as.numeric(mean_satisfaction_by_age)
)

# Display the data frame
mean_satisfaction_df
# Extract Department and Satisfaction columns
department <- survey_data$Department
satisfaction <- survey_data$Satisfaction
# Compute mean satisfaction rating for each department
mean_satisfaction_by_dept <- tapply(satisfaction, department, mean, na.rm = TRUE)
# Convert the result into a matrix
mean_satisfaction_matrix <- as.matrix(mean_satisfaction_by_dept)
# Set row names (departments)
rownames(mean_satisfaction_matrix) <- names(mean_satisfaction_by_dept)


# Get the dimensions of the data frame
dimensions <- dim(survey_data)

# Number of rows
num_rows <- nrow(survey_data)

# Number of columns
num_columns <- ncol(survey_data)

# Display the results
cat("The data frame has", num_rows, "rows and", num_columns, "columns.\n")
The data frame has 20 rows and 5 columns.
# Summary of the Gender column
gender_summary <- summary(survey_data$Gender)
cat("\nSummary of Gender:\n")

Summary of Gender:
print(gender_summary)
    Female       Male Non-Binary 
         8          8          4 
# Summary of the Department column
department_summary <- summary(survey_data$Department)
cat("\nSummary of Department:\n")

Summary of Department:
print(department_summary)
  Finance        HR        IT Marketing 
        5         4         6         5 
str(survey_data$Gender)
 Factor w/ 3 levels "Female","Male",..: 1 2 3 2 1 1 2 3 1 2 ...
str(survey_data$Department)
 Factor w/ 4 levels "Finance","HR",..: 2 3 1 4 3 3 1 4 2 1 ...
# Convert Gender and Department to factors
survey_data$Gender <- as.factor(survey_data$Gender)
survey_data$Department <- as.factor(survey_data$Department)
# Check the structure of the Gender column
str(survey_data$Gender)
 Factor w/ 3 levels "Female","Male",..: 1 2 3 2 1 1 2 3 1 2 ...
# Check the structure of the Department column
str(survey_data$Department)
 Factor w/ 4 levels "Finance","HR",..: 2 3 1 4 3 3 1 4 2 1 ...
# Summary of the Gender column
cat("\nSummary of Gender:\n")

Summary of Gender:
print(summary(survey_data$Gender))
    Female       Male Non-Binary 
         8          8          4 
# Filter the data frame to include respondents aged between 30 and 40
filtered_data <- subset(survey_data, Age >= 30 & Age <= 40)
# Calculate the average satisfaction rating for the filtered data
average_satisfaction <- mean(filtered_data$Satisfaction, na.rm = TRUE)

# Display the result
cat("The average satisfaction rating for respondents aged between 30 and 40 is:", round(average_satisfaction, 2), "\n")
The average satisfaction rating for respondents aged between 30 and 40 is: 6.44 
num_respondents <- nrow(filtered_data)
cat("Number of respondents aged between 30 and 40:", num_respondents, "\n")
Number of respondents aged between 30 and 40: 9 
cat("The average satisfaction rating for respondents aged between 30 and 40 is:", round(average_satisfaction, 2), "\n")
The average satisfaction rating for respondents aged between 30 and 40 is: 6.44 

Histograms

# install.packages("ggplot2")

# Load ggplot2
library(ggplot2)

# Create a histogram of the Age column using ggplot2
ggplot(survey_data, aes(x = Age)) +
  geom_histogram(binwidth = 5, fill = "lightblue", color = "black") +
  labs(
    title = "Distribution of Ages",
    x = "Age",
    y = "Frequency"
  ) +
  theme_minimal()

# Create a histogram of the Satisfaction ratings using ggplot2
ggplot(survey_data, aes(x = Satisfaction)) +
  geom_histogram(binwidth = 1, fill = "lightgreen", color = "black", boundary = 0.5) +
  scale_x_continuous(breaks = seq(min(survey_data$Satisfaction, na.rm = TRUE), max(survey_data$Satisfaction, na.rm = TRUE), by = 1)) +
  labs(
    title = "Distribution of Satisfaction Ratings",
    x = "Satisfaction Rating",
    y = "Frequency"
  ) +
  theme_minimal()

The histogram shows us that there are more 30 year-old employees than any other age bracket, with most employees falling between 25 and 45 years old. There are very few employees under 25 or older than 45. The histogram of satisfaction ratings in green indicates that most people are somewhat satisfied with their job and few people are extremely satisfied or dissatisfied.

Boxplots
We will create a boxplot of satisfaction ratings by department and a second one by gender.

# Create a boxplot of Satisfaction ratings by Department
ggplot(survey_data, aes(x = Department, y = Satisfaction)) +
  geom_boxplot(fill = "lightblue", color = "darkblue") +
  labs(
    title = "Satisfaction Ratings by Department",
    x = "Department",
    y = "Satisfaction Rating"
  ) +
  theme_minimal()

When looking at the boxplot by department, it is clear that HR employees are happiest in their positions. Marketing has a high IQR (interquartile range), meaning the spread of satisfaction ratings, indicated by the light blue box, is spread out over a larger range showing that the middle 50% of satisfaction varies over a larger rating area. We can also say that Finance, HR, and IT have tighter spreads than in Marketing, meaning their satisfaction variability is close to the median and other scores within their IQR. The median is the dark black line in the boxplot. The median is relatively similar in all departments, between 6.5 and 7.5. The boxplot indicates there is a single outlier in Finance who is extremely dissatisfied in their position.. The boxplot for age by gender indicates that there far fewer female-identifying employees and that they are younger than male or non-binary employees.

# Create a boxplot of Age by Gender
ggplot(survey_data, aes(x = Gender, y = Age)) +
  geom_boxplot(fill = "pink", color = "darkred") +
  labs(
    title = "Age Distribution by Gender",
    x = "Gender",
    y = "Age"
  ) +
  theme_minimal()

# Extract the Satisfaction ratings
satisfaction_ratings <- survey_data$Satisfaction

Outliers
We will identify and list any outliers.
There was a single outlier in Finance in the satisfaction ratings, which correlates to the findings in the IQR method.I do not think that a single employee would effect the overall satisfaction of employees.

# Calculate Q1 (25th percentile) and Q3 (75th percentile)
Q1 <- quantile(satisfaction_ratings, 0.25, na.rm = TRUE)
Q3 <- quantile(satisfaction_ratings, 0.75, na.rm = TRUE)

# Calculate IQR
IQR_value <- IQR(satisfaction_ratings, na.rm = TRUE)

# Display the results
cat("Q1 (25th percentile):", Q1, "\n")
Q1 (25th percentile): 6 
cat("Q3 (75th percentile):", Q3, "\n")
Q3 (75th percentile): 7.25 
cat("Interquartile Range (IQR):", IQR_value, "\n")
Interquartile Range (IQR): 1.25 
# Calculate the lower and upper bounds
lower_bound <- Q1 - 1.5 * IQR_value
upper_bound <- Q3 + 1.5 * IQR_value

# Display the bounds
cat("Lower Bound for Outliers:", lower_bound, "\n")
Lower Bound for Outliers: 4.125 
cat("Upper Bound for Outliers:", upper_bound, "\n")
Upper Bound for Outliers: 9.125 
# Identify outliers
outliers <- satisfaction_ratings[satisfaction_ratings < lower_bound | satisfaction_ratings > upper_bound]

# Display the outliers
cat("Outliers in Satisfaction Ratings:\n")
Outliers in Satisfaction Ratings:
print(outliers)
[1] 4
# Get indices of outliers
outlier_indices <- which(satisfaction_ratings < lower_bound | satisfaction_ratings > upper_bound)

# Create a data frame of outliers
outliers_df <- data.frame(
  Index = outlier_indices,
  Satisfaction_Rating = satisfaction_ratings[outlier_indices]
)

# Display the data frame
print(outliers_df)
# Create a boxplot of Satisfaction ratings by Department
ggplot(survey_data, aes(x = Department, y = Satisfaction)) +
  geom_boxplot(fill = "lightblue", color = "darkblue", outlier.color = "red", outlier.shape = 16, outlier.size = 2) +
  labs(
    title = "Satisfaction Ratings by Department",
    x = "Department",
    y = "Satisfaction Rating"
  ) +
  theme_minimal()

# Load necessary library
library(dplyr)

# Function to identify outliers using IQR method
identify_outliers <- function(data) {
  Q1 <- quantile(data$Satisfaction, 0.25, na.rm = TRUE)
  Q3 <- quantile(data$Satisfaction, 0.75, na.rm = TRUE)
  IQR_value <- Q3 - Q1
  lower_bound <- Q1 - 1.5 * IQR_value
  upper_bound <- Q3 + 1.5 * IQR_value
  data %>%
    filter(Satisfaction < lower_bound | Satisfaction > upper_bound)
}

# Apply the function to each department
outliers_by_dept <- survey_data %>%
  group_by(Department) %>%
  do(identify_outliers(.))

# Display the outliers
print(outliers_by_dept)

There is a single outlier, male age 40, in Finance.

Linear Regression

Y’ corresponds to the predicted value (satisfaction value), X corresponds to the independent variable (age), b is the slope in the graph (-0.0268), and A (or β0) is the intercept, representing the value of the dependent variable when the independent variable is 0 (A= 7.559).


# Perform the linear regression
lm_model <- lm(Satisfaction ~ Age, data = survey_data)

# View the summary of the regression model
summary(lm_model)

Call:
lm(formula = Satisfaction ~ Age, data = survey_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.4879 -0.6888  0.1772  0.8625  2.2710 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  7.55947    1.32790   5.693 2.13e-05 ***
Age         -0.02679    0.03819  -0.702    0.492    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.285 on 18 degrees of freedom
Multiple R-squared:  0.02661,   Adjusted R-squared:  -0.02746 
F-statistic: 0.4921 on 1 and 18 DF,  p-value: 0.4919
# Extract the coefficients
coefficients <- coef(lm_model)

# Display the regression equation
cat("Regression Equation: Satisfaction =", round(coefficients[1], 4), "+", round(coefficients[2], 4), "* Age\n")
Regression Equation: Satisfaction = 7.5595 + -0.0268 * Age
# View the summary of the regression model
summary(lm_model)

Call:
lm(formula = Satisfaction ~ Age, data = survey_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.4879 -0.6888  0.1772  0.8625  2.2710 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  7.55947    1.32790   5.693 2.13e-05 ***
Age         -0.02679    0.03819  -0.702    0.492    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.285 on 18 degrees of freedom
Multiple R-squared:  0.02661,   Adjusted R-squared:  -0.02746 
F-statistic: 0.4921 on 1 and 18 DF,  p-value: 0.4919
# Scatter plot with regression line
ggplot(survey_data, aes(x = Age, y = Satisfaction)) +
  geom_point(color = "blue", alpha = 0.6) +
  geom_smooth(method = "lm", se = TRUE, color = "red") +
  labs(
    title = "Scatter Plot of Satisfaction vs. Age",
    x = "Age",
    y = "Satisfaction Rating"
  ) +
  theme_minimal()
`geom_smooth()` using formula = 'y ~ x'

The regression line indicates that satisfaction decreases very slightly with age because it has a negative slope. The scatter plot shows a visual representation of the regression line. Because the dots are far from the regression line, age may not be the correct indicator for satisfaction. We may need to use a more complex model because this does not seem to be a good fit.

LS0tDQp0aXRsZTogIlByZXNlbnRhdGlvbiAzIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KLS0tDQojIEFuYWx5c2lzIG9mIFN1cnZleSBEYXRhDQoNCkluIHRoaXMgZG9jdW1lbnQsIHdlIHdpbGwgYW5hbHl6ZSB0aGUgc3VydmV5IGRhdGEgdG8gZXh0cmFjdCBtZWFuaW5nZnVsIGluc2lnaHRzICANCiAgDQogIA0KX19WZWN0b3JzX18gIA0KDQpUbyBzdGFydCwgd2UgaW1wb3J0IHRoZSBkYXRhc2V0IGFuZCBleHRyYWN0IHRoZSB2ZWN0b3Igb2Ygc2F0aXNmYWN0aW9uIHJhdGluZ3MgYW5kIGNhbGN1bGF0ZSB0aGUgbWVhbiBhbmQgbWVkaWFuLiANCg0KYGBge3J9DQpuYW1lcyhzdXJ2ZXlfZGF0YSkNCiMjI1dlIHdvdWxkIGxpa2UgdG8gZXh0cmFjdCB0aGUgdmVjdG9yIG9mIHNhdGlzZmFjdGlvbiByYXRpbmdzLg0Kc2F0aXNmYWN0aW9uX3JhdGluZ3MgPC0gc3VydmV5X2RhdGEkU2F0aXNmYWN0aW9uDQpoZWFkKHNhdGlzZmFjdGlvbl9yYXRpbmdzKQ0KIyBDYWxjdWxhdGUgdGhlIG1lYW4NCm1lYW5fc2F0aXNmYWN0aW9uIDwtIG1lYW4oc2F0aXNmYWN0aW9uX3JhdGluZ3MsIG5hLnJtID0gVFJVRSkNCiMgRGlzcGxheSB0aGUgbWVhbg0KbWVhbl9zYXRpc2ZhY3Rpb24NCiMgQ2FsY3VsYXRlIHRoZSBtZWRpYW4NCm1lZGlhbl9zYXRpc2ZhY3Rpb24gPC0gbWVkaWFuKHNhdGlzZmFjdGlvbl9yYXRpbmdzLCBuYS5ybSA9IFRSVUUpDQoNCiMgRGlzcGxheSB0aGUgbWVkaWFuDQptZWRpYW5fc2F0aXNmYWN0aW9uDQptZWFuX3NhdGlzZmFjdGlvbg0KbWVkaWFuX3NhdGlzZmFjdGlvbg0KIyMjIFRoZSBtZWFuIG9mIHRoZSBzYXRpc2ZhY3Rpb24gcmF0aW5ncyBpcyA2LjY1IGFuZCB0aGUgbWVkaWFuIGlzIDcuDQoNCmBgYA0KSWYgd2UgbmVlZCB0byBsb29rIHNwZWNpZmljYWxseSBhdCBzYXRpc2ZhY3Rpb24gcmF0aW5ncyBmb3IgdGhlIEhSIGRlcGFydG1lbnQsIHdlIG5lZWQgdG8gY3JlYXRlIGEgdmVjdG9yIGZvciB0aGUgYWdlcyBvZiByZXNwb25kZW50cyBpbiB0aGUgSFIgZGVwYXJ0bWVudCBzcGVjaWZpY2FsbHksIGFuZCB0aGVuIGNhbGN1bGF0ZSB0aGUgbWVhbiBvZiBqdXN0IHRob3NlIHJlc3BvbmRlbnRzLg0KYGBge3J9DQpuYW1lcyhzdXJ2ZXlfZGF0YSkNCiMgQ3JlYXRlIGEgdmVjdG9yIG9mIGFnZXMgZm9yIHJlc3BvbmRlbnRzIGluIHRoZSAnSFInIGRlcGFydG1lbnQNCmFnZXNfaW5fSFIgPC0gc3VydmV5X2RhdGEkQWdlW3N1cnZleV9kYXRhJERlcGFydG1lbnQgPT0gIkhSIl0NCmFnZXNfaW5fSFINCiMgQ2FsY3VsYXRlIHRoZSBhdmVyYWdlIGFnZSBvZiBIUiByZXNwb25kZW50cw0KYXZlcmFnZV9hZ2VfSFIgPC0gbWVhbihhZ2VzX2luX0hSLCBuYS5ybSA9IFRSVUUpDQoNCiMgRGlzcGxheSB0aGUgYXZlcmFnZSBhZ2UNCmF2ZXJhZ2VfYWdlX0hSDQojIEV4dHJhY3QgYWdlcyBvZiByZXNwb25kZW50cyBpbiB0aGUgJ0hSJyBkZXBhcnRtZW50DQphZ2VzX2luX0hSIDwtIHN1cnZleV9kYXRhJEFnZVtzdXJ2ZXlfZGF0YSREZXBhcnRtZW50ID09ICJIUiJdDQoNCiMgQ2FsY3VsYXRlIHRoZSBhdmVyYWdlIGFnZQ0KYXZlcmFnZV9hZ2VfSFIgPC0gbWVhbihhZ2VzX2luX0hSLCBuYS5ybSA9IFRSVUUpDQoNCiMgRGlzcGxheSB0aGUgYXZlcmFnZSBhZ2UNCmF2ZXJhZ2VfYWdlX0hSDQoNCiMgUHJpbnQgYSBmb3JtYXR0ZWQgbWVzc2FnZQ0KcHJpbnQocGFzdGUoIlRoZSBhdmVyYWdlIGFnZSBvZiBIUiByZXNwb25kZW50cyBpcyIsIHJvdW5kKGF2ZXJhZ2VfYWdlX0hSLCAyKSwgInllYXJzLiIpKQ0KYGBgDQpfX01hdHJpY2VzX18gIA0KTmV4dCB3ZSB3aWxsIGNyZWF0ZSBhIG1hdHJpeCBvZiBzYXRpc2ZhY3Rpb24gcmF0aW5ncyBhbmQgdGhlbiB0cmFuc3Bvc2UgaXQuICANCg0KYGBge3J9DQojIEV4dHJhY3QgQWdlIGFuZCBTYXRpc2ZhY3Rpb24gY29sdW1ucw0KYWdlIDwtIHN1cnZleV9kYXRhJEFnZQ0Kc2F0aXNmYWN0aW9uIDwtIHN1cnZleV9kYXRhJFNhdGlzZmFjdGlvbg0KIyBDb21iaW5lIEFnZSBhbmQgU2F0aXNmYWN0aW9uIGludG8gYSBtYXRyaXgNCmFnZV9zYXRpc2ZhY3Rpb25fbWF0cml4IDwtIGNiaW5kKGFnZSwgc2F0aXNmYWN0aW9uKQ0KIyBWaWV3IHRoZSBmaXJzdCBmZXcgcm93cyBvZiB0aGUgbWF0cml4DQpoZWFkKGFnZV9zYXRpc2ZhY3Rpb25fbWF0cml4KQ0KIyBFeHRyYWN0IEFnZSBhbmQgU2F0aXNmYWN0aW9uIGZyb20gdGhlIG1hdHJpeA0KYWdlcyA8LSBhZ2Vfc2F0aXNmYWN0aW9uX21hdHJpeFssICJhZ2UiXQ0Kc2F0aXNmYWN0aW9ucyA8LSBhZ2Vfc2F0aXNmYWN0aW9uX21hdHJpeFssICJzYXRpc2ZhY3Rpb24iXQ0KIyBDb21wdXRlIHRoZSBtZWFuIHNhdGlzZmFjdGlvbiByYXRpbmcgZm9yIGVhY2ggYWdlIGdyb3VwDQptZWFuX3NhdGlzZmFjdGlvbl9ieV9hZ2UgPC0gdGFwcGx5KHNhdGlzZmFjdGlvbnMsIGFnZXMsIG1lYW4sIG5hLnJtID0gVFJVRSkNCg0KIyBEaXNwbGF5IHRoZSByZXN1bHRzDQptZWFuX3NhdGlzZmFjdGlvbl9ieV9hZ2UNCg0KIyBTZXQgY29sdW1uIG5hbWUNCmNvbG5hbWVzKG1lYW5fc2F0aXNmYWN0aW9uX21hdHJpeCkgPC0gIk1lYW5fU2F0aXNmYWN0aW9uIg0KbWVhbl9zYXRpc2ZhY3Rpb25fbWF0cml4DQojIFRyYW5zcG9zZSB0aGUgbWF0cml4DQp0cmFuc3Bvc2VkX21hdHJpeCA8LSB0KG1lYW5fc2F0aXNmYWN0aW9uX21hdHJpeCkNCg0KIyBEaXNwbGF5IHRoZSB0cmFuc3Bvc2VkIG1hdHJpeA0KdHJhbnNwb3NlZF9tYXRyaXgNCiMgQ3JlYXRlIGEgbWF0cml4IHdpdGggbXVsdGlwbGUgbWV0cmljcw0KZGVwdF9tZXRyaWNzX21hdHJpeCA8LSBjYmluZCgNCiAgTWVhbl9TYXRpc2ZhY3Rpb24gPSBtZWFuX3NhdGlzZmFjdGlvbl9ieV9kZXB0LA0KICBNZWFuX0FnZSA9IHRhcHBseShzdXJ2ZXlfZGF0YSRBZ2UsIGRlcGFydG1lbnQsIG1lYW4sIG5hLnJtID0gVFJVRSksDQogIEVtcGxveWVlX0NvdW50ID0gdGFwcGx5KHJlcCgxLCBsZW5ndGgoZGVwYXJ0bWVudCkpLCBkZXBhcnRtZW50LCBzdW0pDQopDQoNCiMgQ29udmVydCB0byBtYXRyaXgNCmRlcHRfbWV0cmljc19tYXRyaXggPC0gYXMubWF0cml4KGRlcHRfbWV0cmljc19tYXRyaXgpDQoNCiMgRGlzcGxheSB0aGUgbWF0cml4DQpkZXB0X21ldHJpY3NfbWF0cml4DQojIFRyYW5zcG9zZSB0aGUgbWF0cml4DQp0cmFuc3Bvc2VkX21hdHJpeCA8LSB0KGRlcHRfbWV0cmljc19tYXRyaXgpDQoNCiMgRGlzcGxheSB0aGUgdHJhbnNwb3NlZCBtYXRyaXgNCnRyYW5zcG9zZWRfbWF0cml4DQojIENhbGN1bGF0ZSB0aGUgbWVhbiBvZiBlYWNoIGNvbHVtbiAoZGVwYXJ0bWVudCkNCm1lYW5fcGVyX2RlcGFydG1lbnQgPC0gY29sTWVhbnModHJhbnNwb3NlZF9tYXRyaXgsIG5hLnJtID0gVFJVRSkNCg0KIyBEaXNwbGF5IHRoZSByZXN1bHRzDQptZWFuX3Blcl9kZXBhcnRtZW50DQpgYGANCl9fRGF0YWZyYW1lc19fICANCg0KYGBge3J9DQojIFN0ZXAgMTogQ29tcHV0ZSBtZXRyaWNzIGZvciBlYWNoIGRlcGFydG1lbnQNCm1lYW5fc2F0aXNmYWN0aW9uX2J5X2RlcHQgPC0gdGFwcGx5KHN1cnZleV9kYXRhJFNhdGlzZmFjdGlvbiwgc3VydmV5X2RhdGEkRGVwYXJ0bWVudCwgbWVhbiwgbmEucm0gPSBUUlVFKQ0KbWVhbl9hZ2VfYnlfZGVwdCA8LSB0YXBwbHkoc3VydmV5X2RhdGEkQWdlLCBzdXJ2ZXlfZGF0YSREZXBhcnRtZW50LCBtZWFuLCBuYS5ybSA9IFRSVUUpDQplbXBsb3llZV9jb3VudF9ieV9kZXB0IDwtIHRhcHBseShyZXAoMSwgbnJvdyhzdXJ2ZXlfZGF0YSkpLCBzdXJ2ZXlfZGF0YSREZXBhcnRtZW50LCBzdW0pDQojIENvbnZlcnQgdGhlIHJlc3VsdHMgaW50byBhIGRhdGEgZnJhbWUNCm1lYW5fc2F0aXNmYWN0aW9uX2RmIDwtIGRhdGEuZnJhbWUoDQogIEFnZSA9IGFzLm51bWVyaWMobmFtZXMobWVhbl9zYXRpc2ZhY3Rpb25fYnlfYWdlKSksDQogIE1lYW5fU2F0aXNmYWN0aW9uID0gYXMubnVtZXJpYyhtZWFuX3NhdGlzZmFjdGlvbl9ieV9hZ2UpDQopDQoNCiMgRGlzcGxheSB0aGUgZGF0YSBmcmFtZQ0KbWVhbl9zYXRpc2ZhY3Rpb25fZGYNCiMgRXh0cmFjdCBEZXBhcnRtZW50IGFuZCBTYXRpc2ZhY3Rpb24gY29sdW1ucw0KZGVwYXJ0bWVudCA8LSBzdXJ2ZXlfZGF0YSREZXBhcnRtZW50DQpzYXRpc2ZhY3Rpb24gPC0gc3VydmV5X2RhdGEkU2F0aXNmYWN0aW9uDQojIENvbXB1dGUgbWVhbiBzYXRpc2ZhY3Rpb24gcmF0aW5nIGZvciBlYWNoIGRlcGFydG1lbnQNCm1lYW5fc2F0aXNmYWN0aW9uX2J5X2RlcHQgPC0gdGFwcGx5KHNhdGlzZmFjdGlvbiwgZGVwYXJ0bWVudCwgbWVhbiwgbmEucm0gPSBUUlVFKQ0KIyBDb252ZXJ0IHRoZSByZXN1bHQgaW50byBhIG1hdHJpeA0KbWVhbl9zYXRpc2ZhY3Rpb25fbWF0cml4IDwtIGFzLm1hdHJpeChtZWFuX3NhdGlzZmFjdGlvbl9ieV9kZXB0KQ0KIyBTZXQgcm93IG5hbWVzIChkZXBhcnRtZW50cykNCnJvd25hbWVzKG1lYW5fc2F0aXNmYWN0aW9uX21hdHJpeCkgPC0gbmFtZXMobWVhbl9zYXRpc2ZhY3Rpb25fYnlfZGVwdCkNCg0KDQojIEdldCB0aGUgZGltZW5zaW9ucyBvZiB0aGUgZGF0YSBmcmFtZQ0KZGltZW5zaW9ucyA8LSBkaW0oc3VydmV5X2RhdGEpDQoNCiMgTnVtYmVyIG9mIHJvd3MNCm51bV9yb3dzIDwtIG5yb3coc3VydmV5X2RhdGEpDQoNCiMgTnVtYmVyIG9mIGNvbHVtbnMNCm51bV9jb2x1bW5zIDwtIG5jb2woc3VydmV5X2RhdGEpDQoNCiMgRGlzcGxheSB0aGUgcmVzdWx0cw0KY2F0KCJUaGUgZGF0YSBmcmFtZSBoYXMiLCBudW1fcm93cywgInJvd3MgYW5kIiwgbnVtX2NvbHVtbnMsICJjb2x1bW5zLlxuIikNCiMgU3VtbWFyeSBvZiB0aGUgR2VuZGVyIGNvbHVtbg0KZ2VuZGVyX3N1bW1hcnkgPC0gc3VtbWFyeShzdXJ2ZXlfZGF0YSRHZW5kZXIpDQpjYXQoIlxuU3VtbWFyeSBvZiBHZW5kZXI6XG4iKQ0KcHJpbnQoZ2VuZGVyX3N1bW1hcnkpDQoNCiMgU3VtbWFyeSBvZiB0aGUgRGVwYXJ0bWVudCBjb2x1bW4NCmRlcGFydG1lbnRfc3VtbWFyeSA8LSBzdW1tYXJ5KHN1cnZleV9kYXRhJERlcGFydG1lbnQpDQpjYXQoIlxuU3VtbWFyeSBvZiBEZXBhcnRtZW50OlxuIikNCnByaW50KGRlcGFydG1lbnRfc3VtbWFyeSkNCnN0cihzdXJ2ZXlfZGF0YSRHZW5kZXIpDQpzdHIoc3VydmV5X2RhdGEkRGVwYXJ0bWVudCkNCiMgQ29udmVydCBHZW5kZXIgYW5kIERlcGFydG1lbnQgdG8gZmFjdG9ycw0Kc3VydmV5X2RhdGEkR2VuZGVyIDwtIGFzLmZhY3RvcihzdXJ2ZXlfZGF0YSRHZW5kZXIpDQpzdXJ2ZXlfZGF0YSREZXBhcnRtZW50IDwtIGFzLmZhY3RvcihzdXJ2ZXlfZGF0YSREZXBhcnRtZW50KQ0KIyBDaGVjayB0aGUgc3RydWN0dXJlIG9mIHRoZSBHZW5kZXIgY29sdW1uDQpzdHIoc3VydmV5X2RhdGEkR2VuZGVyKQ0KDQojIENoZWNrIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIERlcGFydG1lbnQgY29sdW1uDQpzdHIoc3VydmV5X2RhdGEkRGVwYXJ0bWVudCkNCiMgU3VtbWFyeSBvZiB0aGUgR2VuZGVyIGNvbHVtbg0KY2F0KCJcblN1bW1hcnkgb2YgR2VuZGVyOlxuIikNCnByaW50KHN1bW1hcnkoc3VydmV5X2RhdGEkR2VuZGVyKSkNCg0KIyBGaWx0ZXIgdGhlIGRhdGEgZnJhbWUgdG8gaW5jbHVkZSByZXNwb25kZW50cyBhZ2VkIGJldHdlZW4gMzAgYW5kIDQwDQpmaWx0ZXJlZF9kYXRhIDwtIHN1YnNldChzdXJ2ZXlfZGF0YSwgQWdlID49IDMwICYgQWdlIDw9IDQwKQ0KIyBDYWxjdWxhdGUgdGhlIGF2ZXJhZ2Ugc2F0aXNmYWN0aW9uIHJhdGluZyBmb3IgdGhlIGZpbHRlcmVkIGRhdGENCmF2ZXJhZ2Vfc2F0aXNmYWN0aW9uIDwtIG1lYW4oZmlsdGVyZWRfZGF0YSRTYXRpc2ZhY3Rpb24sIG5hLnJtID0gVFJVRSkNCg0KIyBEaXNwbGF5IHRoZSByZXN1bHQNCmNhdCgiVGhlIGF2ZXJhZ2Ugc2F0aXNmYWN0aW9uIHJhdGluZyBmb3IgcmVzcG9uZGVudHMgYWdlZCBiZXR3ZWVuIDMwIGFuZCA0MCBpczoiLCByb3VuZChhdmVyYWdlX3NhdGlzZmFjdGlvbiwgMiksICJcbiIpDQpudW1fcmVzcG9uZGVudHMgPC0gbnJvdyhmaWx0ZXJlZF9kYXRhKQ0KY2F0KCJOdW1iZXIgb2YgcmVzcG9uZGVudHMgYWdlZCBiZXR3ZWVuIDMwIGFuZCA0MDoiLCBudW1fcmVzcG9uZGVudHMsICJcbiIpDQpjYXQoIlRoZSBhdmVyYWdlIHNhdGlzZmFjdGlvbiByYXRpbmcgZm9yIHJlc3BvbmRlbnRzIGFnZWQgYmV0d2VlbiAzMCBhbmQgNDAgaXM6Iiwgcm91bmQoYXZlcmFnZV9zYXRpc2ZhY3Rpb24sIDIpLCAiXG4iKQ0KYGBgDQpfX0hpc3RvZ3JhbXNfXyAgDQoNCmBgYHtyfQ0KIyBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCg0KIyBMb2FkIGdncGxvdDINCmxpYnJhcnkoZ2dwbG90MikNCg0KIyBDcmVhdGUgYSBoaXN0b2dyYW0gb2YgdGhlIEFnZSBjb2x1bW4gdXNpbmcgZ2dwbG90Mg0KZ2dwbG90KHN1cnZleV9kYXRhLCBhZXMoeCA9IEFnZSkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA1LCBmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG9yID0gImJsYWNrIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBBZ2VzIiwNCiAgICB4ID0gIkFnZSIsDQogICAgeSA9ICJGcmVxdWVuY3kiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkNCiMgQ3JlYXRlIGEgaGlzdG9ncmFtIG9mIHRoZSBTYXRpc2ZhY3Rpb24gcmF0aW5ncyB1c2luZyBnZ3Bsb3QyDQpnZ3Bsb3Qoc3VydmV5X2RhdGEsIGFlcyh4ID0gU2F0aXNmYWN0aW9uKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGZpbGwgPSAibGlnaHRncmVlbiIsIGNvbG9yID0gImJsYWNrIiwgYm91bmRhcnkgPSAwLjUpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oc3VydmV5X2RhdGEkU2F0aXNmYWN0aW9uLCBuYS5ybSA9IFRSVUUpLCBtYXgoc3VydmV5X2RhdGEkU2F0aXNmYWN0aW9uLCBuYS5ybSA9IFRSVUUpLCBieSA9IDEpKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFNhdGlzZmFjdGlvbiBSYXRpbmdzIiwNCiAgICB4ID0gIlNhdGlzZmFjdGlvbiBSYXRpbmciLA0KICAgIHkgPSAiRnJlcXVlbmN5Ig0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANClRoZSBoaXN0b2dyYW0gc2hvd3MgdXMgdGhhdCB0aGVyZSBhcmUgbW9yZSAzMCB5ZWFyLW9sZCBlbXBsb3llZXMgdGhhbiBhbnkgb3RoZXIgYWdlIGJyYWNrZXQsIHdpdGggbW9zdCBlbXBsb3llZXMgZmFsbGluZyBiZXR3ZWVuIDI1IGFuZCA0NSB5ZWFycyBvbGQuIFRoZXJlIGFyZSB2ZXJ5IGZldyBlbXBsb3llZXMgdW5kZXIgMjUgb3Igb2xkZXIgdGhhbiA0NS4NClRoZSBoaXN0b2dyYW0gb2Ygc2F0aXNmYWN0aW9uIHJhdGluZ3MgaW4gZ3JlZW4gaW5kaWNhdGVzIHRoYXQgbW9zdCBwZW9wbGUgYXJlIHNvbWV3aGF0IHNhdGlzZmllZCB3aXRoIHRoZWlyIGpvYiBhbmQgZmV3IHBlb3BsZSBhcmUgZXh0cmVtZWx5IHNhdGlzZmllZCBvciBkaXNzYXRpc2ZpZWQuDQogIA0KX19Cb3hwbG90c19fICANCldlIHdpbGwgY3JlYXRlIGEgYm94cGxvdCBvZiBzYXRpc2ZhY3Rpb24gcmF0aW5ncyBieSBkZXBhcnRtZW50IGFuZCBhIHNlY29uZCBvbmUgYnkgZ2VuZGVyLg0KYGBge3J9DQojIENyZWF0ZSBhIGJveHBsb3Qgb2YgU2F0aXNmYWN0aW9uIHJhdGluZ3MgYnkgRGVwYXJ0bWVudA0KZ2dwbG90KHN1cnZleV9kYXRhLCBhZXMoeCA9IERlcGFydG1lbnQsIHkgPSBTYXRpc2ZhY3Rpb24pKSArDQogIGdlb21fYm94cGxvdChmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG9yID0gImRhcmtibHVlIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlNhdGlzZmFjdGlvbiBSYXRpbmdzIGJ5IERlcGFydG1lbnQiLA0KICAgIHggPSAiRGVwYXJ0bWVudCIsDQogICAgeSA9ICJTYXRpc2ZhY3Rpb24gUmF0aW5nIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCldoZW4gbG9va2luZyBhdCB0aGUgYm94cGxvdCBieSBkZXBhcnRtZW50LCBpdCBpcyBjbGVhciB0aGF0IEhSIGVtcGxveWVlcyBhcmUgaGFwcGllc3QgaW4gdGhlaXIgcG9zaXRpb25zLiBNYXJrZXRpbmcgaGFzIGEgaGlnaCBJUVIgKGludGVycXVhcnRpbGUgcmFuZ2UpLCBtZWFuaW5nIHRoZSBzcHJlYWQgb2Ygc2F0aXNmYWN0aW9uIHJhdGluZ3MsIGluZGljYXRlZCBieSB0aGUgbGlnaHQgYmx1ZSBib3gsIGlzIHNwcmVhZCBvdXQgb3ZlciBhIGxhcmdlciByYW5nZSBzaG93aW5nIHRoYXQgdGhlIG1pZGRsZSA1MCUgb2Ygc2F0aXNmYWN0aW9uIHZhcmllcyBvdmVyIGEgbGFyZ2VyIHJhdGluZyBhcmVhLiBXZSBjYW4gYWxzbyBzYXkgdGhhdCBGaW5hbmNlLCBIUiwgYW5kIElUIGhhdmUgdGlnaHRlciBzcHJlYWRzIHRoYW4gaW4gTWFya2V0aW5nLCBtZWFuaW5nIHRoZWlyIHNhdGlzZmFjdGlvbiB2YXJpYWJpbGl0eSBpcyBjbG9zZSB0byB0aGUgbWVkaWFuIGFuZCBvdGhlciBzY29yZXMgd2l0aGluIHRoZWlyIElRUi4gVGhlIG1lZGlhbiBpcyB0aGUgZGFyayBibGFjayBsaW5lIGluIHRoZSBib3hwbG90LiBUaGUgbWVkaWFuIGlzIHJlbGF0aXZlbHkgc2ltaWxhciBpbiBhbGwgZGVwYXJ0bWVudHMsIGJldHdlZW4gNi41IGFuZCA3LjUuIFRoZSBib3hwbG90IGluZGljYXRlcyB0aGVyZSBpcyBhIHNpbmdsZSBvdXRsaWVyIGluIEZpbmFuY2Ugd2hvIGlzIGV4dHJlbWVseSBkaXNzYXRpc2ZpZWQgaW4gdGhlaXIgcG9zaXRpb24uLiBUaGUgYm94cGxvdCBmb3IgYWdlIGJ5IGdlbmRlciBpbmRpY2F0ZXMgdGhhdCB0aGVyZSBmYXIgZmV3ZXIgZmVtYWxlLWlkZW50aWZ5aW5nIGVtcGxveWVlcyBhbmQgdGhhdCB0aGV5IGFyZSB5b3VuZ2VyIHRoYW4gbWFsZSBvciBub24tYmluYXJ5IGVtcGxveWVlcy4NCmBgYHtyfQ0KIyBDcmVhdGUgYSBib3hwbG90IG9mIEFnZSBieSBHZW5kZXINCmdncGxvdChzdXJ2ZXlfZGF0YSwgYWVzKHggPSBHZW5kZXIsIHkgPSBBZ2UpKSArDQogIGdlb21fYm94cGxvdChmaWxsID0gInBpbmsiLCBjb2xvciA9ICJkYXJrcmVkIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkFnZSBEaXN0cmlidXRpb24gYnkgR2VuZGVyIiwNCiAgICB4ID0gIkdlbmRlciIsDQogICAgeSA9ICJBZ2UiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkNCiMgRXh0cmFjdCB0aGUgU2F0aXNmYWN0aW9uIHJhdGluZ3MNCnNhdGlzZmFjdGlvbl9yYXRpbmdzIDwtIHN1cnZleV9kYXRhJFNhdGlzZmFjdGlvbg0KYGBgDQpfX091dGxpZXJzX18gIA0KV2Ugd2lsbCBpZGVudGlmeSBhbmQgbGlzdCBhbnkgb3V0bGllcnMuICANClRoZXJlIHdhcyBhIHNpbmdsZSBvdXRsaWVyIGluIEZpbmFuY2UgaW4gdGhlIHNhdGlzZmFjdGlvbiByYXRpbmdzLCB3aGljaCBjb3JyZWxhdGVzIHRvIHRoZSBmaW5kaW5ncyBpbiB0aGUgSVFSIG1ldGhvZC5JIGRvIG5vdCB0aGluayB0aGF0IGEgc2luZ2xlIGVtcGxveWVlIHdvdWxkIGVmZmVjdCB0aGUgb3ZlcmFsbCBzYXRpc2ZhY3Rpb24gb2YgZW1wbG95ZWVzLg0KYGBge3J9DQojIENhbGN1bGF0ZSBRMSAoMjV0aCBwZXJjZW50aWxlKSBhbmQgUTMgKDc1dGggcGVyY2VudGlsZSkNClExIDwtIHF1YW50aWxlKHNhdGlzZmFjdGlvbl9yYXRpbmdzLCAwLjI1LCBuYS5ybSA9IFRSVUUpDQpRMyA8LSBxdWFudGlsZShzYXRpc2ZhY3Rpb25fcmF0aW5ncywgMC43NSwgbmEucm0gPSBUUlVFKQ0KDQojIENhbGN1bGF0ZSBJUVINCklRUl92YWx1ZSA8LSBJUVIoc2F0aXNmYWN0aW9uX3JhdGluZ3MsIG5hLnJtID0gVFJVRSkNCg0KIyBEaXNwbGF5IHRoZSByZXN1bHRzDQpjYXQoIlExICgyNXRoIHBlcmNlbnRpbGUpOiIsIFExLCAiXG4iKQ0KY2F0KCJRMyAoNzV0aCBwZXJjZW50aWxlKToiLCBRMywgIlxuIikNCmNhdCgiSW50ZXJxdWFydGlsZSBSYW5nZSAoSVFSKToiLCBJUVJfdmFsdWUsICJcbiIpDQojIENhbGN1bGF0ZSB0aGUgbG93ZXIgYW5kIHVwcGVyIGJvdW5kcw0KbG93ZXJfYm91bmQgPC0gUTEgLSAxLjUgKiBJUVJfdmFsdWUNCnVwcGVyX2JvdW5kIDwtIFEzICsgMS41ICogSVFSX3ZhbHVlDQoNCiMgRGlzcGxheSB0aGUgYm91bmRzDQpjYXQoIkxvd2VyIEJvdW5kIGZvciBPdXRsaWVyczoiLCBsb3dlcl9ib3VuZCwgIlxuIikNCmNhdCgiVXBwZXIgQm91bmQgZm9yIE91dGxpZXJzOiIsIHVwcGVyX2JvdW5kLCAiXG4iKQ0KIyBJZGVudGlmeSBvdXRsaWVycw0Kb3V0bGllcnMgPC0gc2F0aXNmYWN0aW9uX3JhdGluZ3Nbc2F0aXNmYWN0aW9uX3JhdGluZ3MgPCBsb3dlcl9ib3VuZCB8IHNhdGlzZmFjdGlvbl9yYXRpbmdzID4gdXBwZXJfYm91bmRdDQoNCiMgRGlzcGxheSB0aGUgb3V0bGllcnMNCmNhdCgiT3V0bGllcnMgaW4gU2F0aXNmYWN0aW9uIFJhdGluZ3M6XG4iKQ0KcHJpbnQob3V0bGllcnMpDQojIEdldCBpbmRpY2VzIG9mIG91dGxpZXJzDQpvdXRsaWVyX2luZGljZXMgPC0gd2hpY2goc2F0aXNmYWN0aW9uX3JhdGluZ3MgPCBsb3dlcl9ib3VuZCB8IHNhdGlzZmFjdGlvbl9yYXRpbmdzID4gdXBwZXJfYm91bmQpDQoNCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSBvZiBvdXRsaWVycw0Kb3V0bGllcnNfZGYgPC0gZGF0YS5mcmFtZSgNCiAgSW5kZXggPSBvdXRsaWVyX2luZGljZXMsDQogIFNhdGlzZmFjdGlvbl9SYXRpbmcgPSBzYXRpc2ZhY3Rpb25fcmF0aW5nc1tvdXRsaWVyX2luZGljZXNdDQopDQoNCiMgRGlzcGxheSB0aGUgZGF0YSBmcmFtZQ0KcHJpbnQob3V0bGllcnNfZGYpDQojIENyZWF0ZSBhIGJveHBsb3Qgb2YgU2F0aXNmYWN0aW9uIHJhdGluZ3MgYnkgRGVwYXJ0bWVudA0KZ2dwbG90KHN1cnZleV9kYXRhLCBhZXMoeCA9IERlcGFydG1lbnQsIHkgPSBTYXRpc2ZhY3Rpb24pKSArDQogIGdlb21fYm94cGxvdChmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG9yID0gImRhcmtibHVlIiwgb3V0bGllci5jb2xvciA9ICJyZWQiLCBvdXRsaWVyLnNoYXBlID0gMTYsIG91dGxpZXIuc2l6ZSA9IDIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJTYXRpc2ZhY3Rpb24gUmF0aW5ncyBieSBEZXBhcnRtZW50IiwNCiAgICB4ID0gIkRlcGFydG1lbnQiLA0KICAgIHkgPSAiU2F0aXNmYWN0aW9uIFJhdGluZyINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKQ0KIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJ5DQpsaWJyYXJ5KGRwbHlyKQ0KDQojIEZ1bmN0aW9uIHRvIGlkZW50aWZ5IG91dGxpZXJzIHVzaW5nIElRUiBtZXRob2QNCmlkZW50aWZ5X291dGxpZXJzIDwtIGZ1bmN0aW9uKGRhdGEpIHsNCiAgUTEgPC0gcXVhbnRpbGUoZGF0YSRTYXRpc2ZhY3Rpb24sIDAuMjUsIG5hLnJtID0gVFJVRSkNCiAgUTMgPC0gcXVhbnRpbGUoZGF0YSRTYXRpc2ZhY3Rpb24sIDAuNzUsIG5hLnJtID0gVFJVRSkNCiAgSVFSX3ZhbHVlIDwtIFEzIC0gUTENCiAgbG93ZXJfYm91bmQgPC0gUTEgLSAxLjUgKiBJUVJfdmFsdWUNCiAgdXBwZXJfYm91bmQgPC0gUTMgKyAxLjUgKiBJUVJfdmFsdWUNCiAgZGF0YSAlPiUNCiAgICBmaWx0ZXIoU2F0aXNmYWN0aW9uIDwgbG93ZXJfYm91bmQgfCBTYXRpc2ZhY3Rpb24gPiB1cHBlcl9ib3VuZCkNCn0NCg0KIyBBcHBseSB0aGUgZnVuY3Rpb24gdG8gZWFjaCBkZXBhcnRtZW50DQpvdXRsaWVyc19ieV9kZXB0IDwtIHN1cnZleV9kYXRhICU+JQ0KICBncm91cF9ieShEZXBhcnRtZW50KSAlPiUNCiAgZG8oaWRlbnRpZnlfb3V0bGllcnMoLikpDQoNCiMgRGlzcGxheSB0aGUgb3V0bGllcnMNCnByaW50KG91dGxpZXJzX2J5X2RlcHQpDQpgYGANClRoZXJlIGlzIGEgc2luZ2xlIG91dGxpZXIsIG1hbGUgYWdlIDQwLCBpbiBGaW5hbmNlLiAgDQogIA0KICANCl9fTGluZWFyIFJlZ3Jlc3Npb25fXyAgDQoNClnigJkgY29ycmVzcG9uZHMgdG8gdGhlIHByZWRpY3RlZCB2YWx1ZSAoc2F0aXNmYWN0aW9uIHZhbHVlKSwgWCBjb3JyZXNwb25kcyB0byB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGUgKGFnZSksIGIgaXMgdGhlIHNsb3BlIGluIHRoZSBncmFwaCAoLTAuMDI2OCksIGFuZCBBIChvciDOsjApIGlzIHRoZSBpbnRlcmNlcHQsIHJlcHJlc2VudGluZyB0aGUgdmFsdWUgb2YgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSB3aGVuIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZSBpcyAwIChBPSA3LjU1OSkuIA0KDQpgYGB7cn0NCg0KIyBQZXJmb3JtIHRoZSBsaW5lYXIgcmVncmVzc2lvbg0KbG1fbW9kZWwgPC0gbG0oU2F0aXNmYWN0aW9uIH4gQWdlLCBkYXRhID0gc3VydmV5X2RhdGEpDQoNCiMgVmlldyB0aGUgc3VtbWFyeSBvZiB0aGUgcmVncmVzc2lvbiBtb2RlbA0Kc3VtbWFyeShsbV9tb2RlbCkNCiMgRXh0cmFjdCB0aGUgY29lZmZpY2llbnRzDQpjb2VmZmljaWVudHMgPC0gY29lZihsbV9tb2RlbCkNCg0KIyBEaXNwbGF5IHRoZSByZWdyZXNzaW9uIGVxdWF0aW9uDQpjYXQoIlJlZ3Jlc3Npb24gRXF1YXRpb246IFNhdGlzZmFjdGlvbiA9Iiwgcm91bmQoY29lZmZpY2llbnRzWzFdLCA0KSwgIisiLCByb3VuZChjb2VmZmljaWVudHNbMl0sIDQpLCAiKiBBZ2VcbiIpDQojIFZpZXcgdGhlIHN1bW1hcnkgb2YgdGhlIHJlZ3Jlc3Npb24gbW9kZWwNCnN1bW1hcnkobG1fbW9kZWwpDQojIFNjYXR0ZXIgcGxvdCB3aXRoIHJlZ3Jlc3Npb24gbGluZQ0KZ2dwbG90KHN1cnZleV9kYXRhLCBhZXMoeCA9IEFnZSwgeSA9IFNhdGlzZmFjdGlvbikpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibHVlIiwgYWxwaGEgPSAwLjYpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFLCBjb2xvciA9ICJyZWQiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiU2NhdHRlciBQbG90IG9mIFNhdGlzZmFjdGlvbiB2cy4gQWdlIiwNCiAgICB4ID0gIkFnZSIsDQogICAgeSA9ICJTYXRpc2ZhY3Rpb24gUmF0aW5nIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCg0KDQoNCmBgYA0KVGhlIHJlZ3Jlc3Npb24gbGluZSBpbmRpY2F0ZXMgdGhhdCBzYXRpc2ZhY3Rpb24gZGVjcmVhc2VzIHZlcnkgc2xpZ2h0bHkgd2l0aCBhZ2UgYmVjYXVzZSBpdCBoYXMgYSBuZWdhdGl2ZSBzbG9wZS4gVGhlIHNjYXR0ZXIgcGxvdCBzaG93cyBhIHZpc3VhbCByZXByZXNlbnRhdGlvbiBvZiB0aGUgcmVncmVzc2lvbiBsaW5lLiBCZWNhdXNlIHRoZSBkb3RzIGFyZSBmYXIgZnJvbSB0aGUgcmVncmVzc2lvbiBsaW5lLCBhZ2UgbWF5IG5vdCBiZSB0aGUgY29ycmVjdCBpbmRpY2F0b3IgZm9yIHNhdGlzZmFjdGlvbi4gV2UgbWF5IG5lZWQgdG8gdXNlIGEgbW9yZSBjb21wbGV4IG1vZGVsIGJlY2F1c2UgdGhpcyBkb2VzIG5vdCBzZWVtIHRvIGJlIGEgZ29vZCBmaXQuDQo=