Dataset

The dataset is data from the 2021 National Health Interview Adult Survey. The survey contained questions related to household and family composition, demographics about the survey taker, satisfaction with life, health insurance, medication, immunization, preventive screenings, and multiple health problems such as hypertension, cardiovascular conditions, cancer, vision, hearing, mobility, and more.

This survey is important in following the health of American’s based on many different factors of their lives. Looking at previous surveys can also help to see trends in Americans’ health.

For the data used, responses of “refused”,“don’t know” and “not ascertained” were filtered out as these responses had a tendency to be much smaller than the others and were not helpful for what was being looked at.

Columns

General Health

1. Excellent 
2. Very Good 
3. Good 
4. Fair 
5. Poor 

Life Satisfaction

1. Very Satisfied 
2. Satisfied 
3. Dissatisfied 
4. Very Dissatisfied

Race (Single and Multiple Race Groups)

1.  White only
2.  Black/African American only
3.  Asian only
4.  AIAN only (American Indians and Alaska Natives)
5.  AIAN and any other group
6.  Other
7.  Hispanic who did not identify with one of the other categories

Education Level

0. Never attended/Kindergarten only 
1. Grade 1-11 
2. 12th grade, nodiploma 
3. GED or equivalent 
4. High School Graduate 
5. Some college, nodegree 
6. Associate degree: occupational, technical, or vocational program 
7. Associate degree: academic program 
8. Bachelor's degree 
9. Master's degree 
10. Professional School or Doctoral degree

BMI

1. Underweight 
2. Normal 
3. Overweight 
4. Obese

Vision

Do you wear glasses or contact lenses?
1. Yes 
2. No
Do you have difficulty seeing? 
1. No difficulty 
2. Some difficulty 
3. A lot of difficulty 
4. Cannot do at all

Cancer

Separate columns for each type of cancer.

Number of reported types of cancer. 
0. No cancer 
1-3. 1 to 3 
4. 4 or more

Demographics

Looking at demographics can help to give a bit of an idea about what sort of data we should look at.

Sex


dfSexFilter <- adult22 %>% 
  filter(SEX_A == 1 | SEX_A == 2)

dfSexFilter <-
  dfSexFilter |>
    group_by(dfSexFilter$SEX_A) |>
    mutate(Sex_Status = ifelse(SEX_A == 1,
                                 "Male", 
                                 "Female")) |>

  ungroup()
ggplot(dfSexFilter, aes(x = Sex_Status, fill=Sex_Status)) + xlab("Sex") +
  geom_bar()

Age

The far right bar, 85, is for those who are 85+.



dfAgeFilter <- adult22 %>% 
  filter(AGEP_A < 86)

ggplot(dfAgeFilter, aes(x = AGEP_A)) + xlab("Age") +
  geom_bar()

The largest group based on age were those that were 85 or older.

Education Level

dfEduFilter <- adult22 %>% 
  filter(EDUCP_A < 97)


dfEduFilter <-
  dfEduFilter |>
    group_by(dfEduFilter$EDUCP_A) |>
    mutate(Edu_Status = ifelse(EDUCP_A == 1,
                                "Grade 1-11", 
                               ifelse(EDUCP_A == 2,
                                 "12th Grade, no Diploma",
                                 ifelse(EDUCP_A == 3,
                                 "GED or Equivalent",
                                 ifelse(EDUCP_A == 4,
                                 "High School Graduate",
                                 ifelse(EDUCP_A == 5,
                                 "Some College, no Degree",
                                 ifelse(EDUCP_A == 6,
                                 "Associate degree: occupational, technical, or vocational program",
                                 ifelse(EDUCP_A == 7,
                                 "Associate degree: academic program",
                                 ifelse(EDUCP_A == 8,
                                 "Bachelor's degree",
                                 ifelse(EDUCP_A == 9,
                                 "Master's degree ",
                                 ifelse(EDUCP_A == 10,
                                 "Professional School or Doctoral degree",
                                 ifelse(EDUCP_A == 97,
                                 "Refused",
                                "Don't Know")))))))))))) |> 
ungroup()
  
  
dfEduFilter$Edu_Status <- factor(dfEduFilter$Edu_Status, levels = c("Grade 1-11", "12th Grade, no Diploma", "GED or Equivalent","High School Graduate", "Some College, no Degree", "Associate degree: occupational, technical, or vocational program", "Associate degree: academic program", "Bachelor's degree", "Master's degree ", "Professional School or Doctoral degree", "Refused", "Don't Know"))

ggplot(dfEduFilter, aes(x = EDUCP_A, fill=Edu_Status)) +
  geom_bar() + theme(axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank()) + xlab("Education Level")

Race

dfRaceFilter <- adult22 %>% 
  filter(RACEALLP_A <= 8 )

dfRaceFilter2 <- dfRaceFilter  %>% 
  filter(RACEALLP_A != 7 )


dfRaceFilter2 <-
  dfRaceFilter2 |>
    group_by(dfRaceFilter2$RACEALLP_A) |>
    mutate(Race = ifelse(RACEALLP_A == 1,
                                "White", 
                               ifelse(RACEALLP_A == 2,
                                 "African American/Black",
                                 ifelse(RACEALLP_A == 3,
                                 "Asian",
                                 ifelse(RACEALLP_A == 4,
                                 "AIAN*",
                                 ifelse(RACEALLP_A == 5,
                                 "AIAN + Other Group",
                                 ifelse(RACEALLP_A == 6,
                                 "Other",
                                 ifelse(RACEALLP_A == 8,
                                 "Hispanic**",
                                "Don't Know")))))))) |> 
ungroup()
  
ggplot(dfRaceFilter2, aes(x = Race, fill=Race)) +
  geom_bar() + theme(axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank())

There was a much larger amount of those who identified as white who took the survey.

General Physical Health


dfGHFilter <- adult22 %>% 
  filter(PHSTAT_A < '7')

ggplot(dfGHFilter, aes(x = factor(PHSTAT_A))) + scale_x_discrete(labels=c("Excellent", "Very Good", "Good", "Fair", "Poor")) +
  geom_bar() + 
  xlab("General Physical Health")

NA
NA
NA

Most people put their General Physical Health in the more positive side (Excellent, Very good, Good) side of the scale.

Life Satisfaction


dfFilteredLS <- adult22 %>% 
  filter(LSATIS4_A < '5')


ggplot(dfFilteredLS, aes(x = factor(LSATIS4_A))) + scale_x_discrete(labels=c("Very Satisfied", "Satisfied", "Dissatisfied", "Very Dissatisfied")) +
  geom_bar() +
  xlab("Life Satisfaction")

NA
NA
NA
NA

Most people considered themselves to be positively satisfied with life. The difference between the positive and negative side of the scale was larger than for General Physical Health.

BMI

BMI can often be contributed to health and certain levels can be contributed to health issues. However, BMI is fundamentally flawed as it does not take into consideration muscle fat. For example, a body builder could be considered to have an “overweight” BMI, but would be much healthier than someone who had mostly non-muscle fat.

Histogram

hist(dfFilteredBMI$BMICAT_A)

The distribution was relatively equal, except for the Underweight category, so there was a potential for this category to cause problems.

Bootstrap

This is to help us get a better idea of the average Life Satisfaction and General Physical Health based on a person’s BMI category, by creating samples.


dfFilteredLSBMI <- adult22 %>%
  filter(BMICAT_A < 5 & LSATIS4_A <5)

dfFilteredPHBMI <- adult22 %>%
  filter(BMICAT_A < 5 & PHSTAT_A <7)

boot_ci <- function (v, func = median, conf = 0.95, n_iter = 100) {
  boot_func <- \(x, i) func(x[i])
  
  b <- boot(v, boot_func, R = n_iter)
  b <- boot.ci(b, conf = conf, type = "perc")
  
  return(c("lower" = b$percent[4],
           "upper" = b$percent[5]))
}

Bootstrap: Life Satisfaction vs BMI

df_ciLS <- dfFilteredLSBMI |>
  group_by(BMICAT_A) |>
  summarise(ci_lower = boot_ci(LSATIS4_A, mean)['lower'],
            mean_LS = mean(LSATIS4_A),
            ci_upper = boot_ci(LSATIS4_A, mean)['upper'])

df_ciLS |>
  ggplot() +
  geom_errorbarh(mapping = aes(y = BMICAT_A, 
                               xmin=ci_lower, xmax=ci_upper,
                               color = '95% C.I.'), height = 0.5) +
  geom_point(mapping = aes(x = mean_LS, y = BMICAT_A,
                           color = 'Group Mean'),
             shape = '|',
             size = 5) +
  scale_color_manual(values=c('black', 'red')) +
  theme_minimal() +
  labs(title = "Life Satisfaction by BMI Category",
       x = "Life Satisfaction",
       y = "BMI Category",
       color = '')

Category 1, underweight, seems to have a much larger range than the other 3, which like stated above, could be an issue because of how small the distribution was.

Bootstrap: General Physical Health vs BMI

df_ciPH <- dfFilteredPHBMI |>
  group_by(BMICAT_A) |>
  summarise(ci_lower = boot_ci(PHSTAT_A, mean)['lower'],
            mean_PH = mean(PHSTAT_A),
            ci_upper = boot_ci(PHSTAT_A, mean)['upper'])

df_ciPH |>
  ggplot() +
  geom_errorbarh(mapping = aes(y = BMICAT_A, 
                               xmin=ci_lower, xmax=ci_upper,
                               color = '95% C.I.'), height = 0.5) +
  geom_point(mapping = aes(x = mean_PH, y = BMICAT_A,
                           color = 'Group Mean'),
             shape = '|',
             size = 5) +
  scale_color_manual(values=c('black', 'red')) +
  theme_minimal() +
  labs(title = "General Health by BMI Category",
       x = "General Health",
       y = "BMI Category",
       color = '')

There were way less people in the underweight BMI (1) than the other categories, similar to the issue in Life Satisfaction, so that group does not give as much information, or as accurate of information as the others and was removed for the graphs below.

General Health by BMI Status


dfBMIGH <- adult22 %>%
  filter(PHSTAT_A < 7)

dfNormalBMI <- dfBMIGH %>%
  filter(BMICAT_A == 2 )

dfOverBMI <- dfBMIGH %>%
  filter(BMICAT_A == 3 )

dfObeseBMI <- dfBMIGH %>%
  filter(BMICAT_A == 4 )

BMIGH <- data.frame(                                            
   Status  = c(2, 3, 4),       
   Physical_Health= c( mean(dfNormalBMI$PHSTAT_A), mean(dfOverBMI$PHSTAT_A), mean(dfObeseBMI$PHSTAT_A)))

ggplot(BMIGH, aes(x = factor(Status), y = Physical_Health)) + 
  geom_point() +
  scale_x_discrete(labels= c( "Normal", "Overweight", "Obese")) +
  xlab("BMI Status") +
  ylab("Average General Physical Health")

NA
NA

Life Satisfaction by BMI Status


dfBMILS <- adult22 %>%
  filter(LSATIS4_A < 5)

dfNormalBMILS <- dfBMILS %>%
  filter(BMICAT_A == 2 )

dfOverBMILS <- dfBMILS %>%
  filter(BMICAT_A == 3 )

dfObeseBMILS <- dfBMILS %>%
  filter(BMICAT_A == 4 )

BMILS <- data.frame(                                            
   Status  = c(2, 3, 4),       
   Life_Satis= c( mean(dfNormalBMILS$LSATIS4_A), mean(dfOverBMILS$LSATIS4_A), mean(dfObeseBMILS$LSATIS4_A)))

ggplot(BMILS, aes(x = factor(Status), y = Life_Satis)) + 
  geom_point() +
  scale_x_discrete(labels= c("Normal", "Overweight", "Obese")) +
  xlab("BMI Status") +
  ylab("Average Life Satisfaction")

NA
NA

Education Level

Vs General Physical Health


dfFilteredEdu <- dfGHFilter %>%
  filter(EDUCP_A < 97)

df_ciEdu <- dfFilteredEdu |>
  group_by(EDUCP_A) |>
  summarise(ci_lower = boot_ci(PHSTAT_A, mean)['lower'],
            mean_PH = mean(PHSTAT_A),
            ci_upper = boot_ci(PHSTAT_A, mean)['upper'])


df_ciEdu |>
  ggplot() +
  geom_errorbarh(mapping = aes(y = EDUCP_A, 
                               xmin=ci_lower, xmax=ci_upper,
                               color = '95% C.I.'), height = 0.5) +
  geom_point(mapping = aes(x = mean_PH, y = EDUCP_A,
                           color = 'Group Mean'),
             shape = '|',
             size = 5) +
  scale_color_manual(values=c('black', 'red')) +
  theme_minimal() +
  labs(title = "General Physical Health by Education",
       x = "Physical Health",
       y = "Education",
       color = '')

We can see that as a person’s education level decreases, their average physical health generally decreases, however it was still in the same physical health category. There seems to be a few groups forming, such as the bottom 3, the middle 4, and the top 3.

Vs Life Satisfaction


dfFilteredEduLS <- dfFilteredLS %>%
  filter(EDUCP_A < 97)

df_ciEduLS <- dfFilteredEduLS |>
  group_by(EDUCP_A) |>
  summarise(ci_lower = boot_ci(LSATIS4_A, mean)['lower'],
            mean_LS = mean(LSATIS4_A),
            ci_upper = boot_ci(LSATIS4_A, mean)['upper'])


df_ciEduLS |>
  ggplot() +
  geom_errorbarh(mapping = aes(y = EDUCP_A, 
                               xmin=ci_lower, xmax=ci_upper,
                               color = '95% C.I.'), height = 0.5) +
  geom_point(mapping = aes(x = mean_LS, y = EDUCP_A,
                           color = 'Group Mean'),
             shape = '|',
             size = 5) +
  scale_color_manual(values=c('black', 'red')) +
  theme_minimal() +
  labs(title = "Life Satisfaction by Education",
       x = "Life Satisfaction",
       y = "Education",
       color = '')

Similar to general health, there is a trend of as education level decreases, life satisfaction decreases.

Vision

dfFilteredVis <- adult22 %>%
  filter(VISIONDF_A <4)

hist(dfFilteredVis$VISIONDF_A)


hist(dfFilteredVis$WEARGLSS_A)

Vision vs General Physical Health

dfGlasses <- adult22 %>%
  filter(PHSTAT_A < 5)

dfNoGlasses <- dfGlasses %>%
  filter(WEARGLSS_A == '2')

dfWearGlasses <- dfGlasses %>%
  filter(WEARGLSS_A== '1' )

WearGlasses <- data.frame(                                            
   Status  = c(1, 2),       
   Gen_Health= c(mean(dfWearGlasses$PHSTAT_A), mean(dfNoGlasses$PHSTAT_A)))


ggplot(WearGlasses, aes(x = factor(Status), y = Gen_Health)) + 
  geom_point() +
  scale_x_discrete(labels= c("Wear Glasses/Contacts", "No Glasses/Contacts")) +
  xlab("")+
  ylab("Average Physical Health")

dfVision <- dfFilteredVis %>%
  filter(PHSTAT_A < 5)

dfNoneVis <- dfVision %>%
  filter(VISIONDF_A == '1')

dfSomeVis <- dfVision %>%
  filter(VISIONDF_A== '2' )

dfAlotVis <- dfVision %>%
  filter(VISIONDF_A== '3' )

dfCannotVis <- dfVision %>%
  filter(VISIONDF_A== '4' )

VisDifficulty <- data.frame(                                            
   Status  = c(1, 2,3,4),       
   Gen_Health= c(mean(dfNoneVis$PHSTAT_A), mean(dfSomeVis$PHSTAT_A), mean(dfAlotVis$PHSTAT_A), mean(dfCannotVis$PHSTAT_A)))


ggplot(VisDifficulty, aes(x = factor(Status), y = Gen_Health)) + 
  geom_point() +
  scale_x_discrete(labels= c("None", "Some", "A Lot","Cannot See")) +
  xlab("Difficulty Seeing") +
  ylab("Average Physical Health")

Vision vs Life Satisfaction

dfGlassesLS <- adult22 %>%
  filter(LSATIS4_A < 7)

dfNoGlassesLS <- dfGlassesLS %>%
  filter(WEARGLSS_A == '2')

dfWearGlassesLS <- dfGlassesLS %>%
  filter(WEARGLSS_A== '1' )

WearGlassesLS <- data.frame(                                            
   Status  = c(1, 2),       
   Life_Satis= c(mean(dfWearGlassesLS$LSATIS4_A), mean(dfNoGlassesLS$LSATIS4_A)))


ggplot(WearGlassesLS, aes(x = factor(Status), y = Life_Satis)) + 
  geom_point() +
  scale_x_discrete(labels= c("Wear Glasses/Contacts", "No Glasses/Contacts")) +
  xlab("")+
  ylab("Average Life Satisfaction")

Difficulty Seeing and Life Satisfaction

dfVisionLS <- dfFilteredVis %>%
  filter(LSATIS4_A < 7)

dfNoneVisLS <- dfVisionLS %>%
  filter(VISIONDF_A == '1')

dfSomeVisLS <- dfVisionLS %>%
  filter(VISIONDF_A== '2' )

dfAlotVisLS <- dfVisionLS %>%
  filter(VISIONDF_A== '3' )

dfCannotVisLS <- dfVisionLS %>%
  filter(VISIONDF_A== '4' )

VisDifficultyLS <- data.frame(                                            
   Status  = c(1, 2,3,4),       
   Life_Satis= c(mean(dfNoneVisLS$LSATIS4_A), mean(dfSomeVisLS$LSATIS4_A), mean(dfAlotVisLS$LSATIS4_A), mean(dfCannotVisLS$LSATIS4_A)))


ggplot(VisDifficultyLS, aes(x = factor(Status), y = Life_Satis)) + 
  geom_point() +
  scale_x_discrete(labels= c("None", "Some", "A Lot","Cannot See")) +
  xlab("Difficulty Seeing") +
  ylab("Average Life Satisfaction")

For both physical health and life satisfaction, there was a decrease for those who wear glasses/contacts. Since people can be split into positive and negative life satisfaction, we can try a binary response.

dfVisionAll <- dfFilteredVis %>%
  filter(WEARGLSS_A< '3' )

dfVisionAllLS <-
  dfVisionAll |>
    group_by(dfVisionAll$LSATIS4_A) |>
    mutate(LifeSatis_Status = ifelse(LSATIS4_A == 1,
                                0, 
                                ifelse(LSATIS4_A == 2,
                                0, 
                                 1))) |> 
  ungroup()

model <- glm(LifeSatis_Status ~ VISIONDF_A, data = dfVisionAllLS,
             family = binomial(link = 'logit'))

model$coefficients
(Intercept)  VISIONDF_A 
  -4.325735    1.004927 
sigmoid <- \(x) 1 / (1 + exp(-(-4.325735 + 1.004927 * x)))

dfVisionAllLS |>
  ggplot(mapping = aes(x = VISIONDF_A, y = LifeSatis_Status)) +
  geom_jitter(width = 0, height = 0.1, shape = 'O', size = 3) +
  geom_function(fun = sigmoid, color = 'blue', linewidth = 1) +
  labs(title = "Life Satisfaction Binary Response - Difficulty Seeing") +
  scale_y_continuous(breaks = c(0, 1)) +
  theme_minimal()

Between Positive Life Satisfaction(0) and Negative Life Satisfaction(1). We can see that there is a small increase in probability that as someone’s vision gets worst, the life satisfaction will become more negative.

Smoking

Smoking, Life Satisfaction, and General Health

  1. Current, every day smoker
  2. Current, some days smoker
  3. Former smoker
  4. Non-Smoker

dfFilteredLSSmoke <- dfFilteredLS %>%
  filter(SMKCIGST_A < 5)


dfFilteredLSSmoke |>
  ggplot(mapping = aes(x = SMKCIGST_A, y = LSATIS4_A)) +
  geom_point(size = 2) +
  geom_smooth(method = "lm", se = FALSE, color = 'darkblue') + 
  theme_minimal() + xlab("Smoking Status") + ylab("Life Satisfaction")

  

dfFilteredPHSmoke <- dfGHFilter %>%
  filter(SMKCIGST_A < 5)


dfFilteredPHSmoke |>
  ggplot(mapping = aes(x = SMKCIGST_A, y = PHSTAT_A)) +
  geom_point(size = 2) +
  geom_smooth(method = "lm", se = FALSE, color = 'darkblue') + 
  theme_minimal() + xlab("Smoking Status") + ylab("General Health")

NA
NA

There is a bit of a decrease in life satisfaction and general health the more someone smokes.

Smoking and Lung Cancer - Binary Response

We can split people up into someone who has smoked and someone who has not smoked, so we can try a binary response.


dfSmokeCan <- adult22 %>%
  filter(SMKCIGST_A < 5 & LUNGCAN_A <3)

dfSmokeCan <-
  dfSmokeCan |>
    group_by(dfSmokeCan$SMKCIGST_A) |>
    mutate(Smoke = ifelse(SMKCIGST_A == "4",
                                0,
                                 1)) |> 
  ungroup()

model <- glm(Smoke ~ LUNGCAN_A, data = dfSmokeCan,
             family = binomial(link = 'logit'))

model$coefficients
(Intercept)   LUNGCAN_A 
   3.264507   -1.755153 
sigmoid <- \(x) 1 / (1 + exp(-(3.264507 -1.755153 * x)))

dfSmokeCan |>
  ggplot(mapping = aes(x = LUNGCAN_A, y = Smoke)) +
  geom_jitter(width = 0, height = 0.1, shape = 'O', size = 3) +
  geom_function(fun = sigmoid, color = 'blue', linewidth = 1) +
  labs(title = "Binary Response: Lung Cancer and Smoking") +
  scale_y_continuous(breaks = c(0, 1)) +
  theme_minimal()

This graph shows that for those who have lung cancer (1), there is a higher probability of them being a smoker or former smoker(1).

100 Cigarettes Smoked and Lung Cancer - Binary Response

We can also split the smokers up into those who have smoked 100 cigarettes, and those who have not.

dfSmoke100 <- adult22 %>%
  filter(SMKEV_A < 3 & LUNGCAN_A <3)

dfSmoke100Can <-
  dfSmoke100 |>
    group_by(dfSmoke100$SMKEV_A) |>
    mutate(Smoke_100 = ifelse(SMKEV_A == "2",
                                0,
                                 1)) |> 
  ungroup()

model <- glm(Smoke_100 ~ LUNGCAN_A, data = dfSmoke100Can,
             family = binomial(link = 'logit'))

model$coefficients
(Intercept)   LUNGCAN_A 
   3.263094   -1.753740 
sigmoid <- \(x) 1 / (1 + exp(-(3.263094 -1.753740 * x)))

dfSmoke100Can |>
  ggplot(mapping = aes(x = LUNGCAN_A, y = Smoke_100)) +
  geom_jitter(width = 0, height = 0.1, shape = 'O', size = 3) +
  geom_function(fun = sigmoid, color = 'blue', linewidth = 1) +
  labs(title = "Binary Response: Lung Cancer and Smoked 100 Cigarettes") +
  scale_y_continuous(breaks = c(0, 1)) +
  theme_minimal()

This graph shows that for those who have lung cancer (1), there is a higher probability of them having smoked 100 cigarettes(1). The model is extremely close to the previous model. So, how many of the smokers with lung cancer smoked 100 cigarettes?

LungCan <- nrow(dfSmoke100[dfSmoke100$LUNGCAN_A == '1',])
Smoked100 <- nrow(dfSmoke100[dfSmoke100$SMKEV_A == '1',])
Smoked100Can <- nrow(dfSmoke100[dfSmoke100$SMKEV_A == '1' & dfSmoke100$LUNGCAN_A == '1', ])
NotSmoked100Can <- nrow(dfSmoke100[dfSmoke100$SMKEV_A == '2' & dfSmoke100$LUNGCAN_A == '1', ])

LungCan
[1] 116
Smoked100Can
[1] 95
95/116*100
[1] 81.89655
Smoked100
[1] 1511
NotSmoked100Can
[1] 21
95/1511*100
[1] 6.287227

Out of 116 people who stated they have lung cancer, 95 people, or 81.9% had smoked at least 100 cigarettes. But out of 1511 people who have smoked at least 100 cigarettes, only 21, or 6.3% have lung cancer.

Covid

Month of last Covid vaccine for those who got it for the first time.

fCovidVax <- adult22

dfCovidVaxFirst <- dfCovidVax %>%
  filter(CVDVAC1M_A != 'NA' & CVDVAC1Y_A !='NA')

dfCovidVaxLast <- dfCovidVax %>%
  filter(CVDVAC2M_A != 'NA' & CVDVAC2Y_A !='NA')

dfCovidVaxFirst$LastCovidVaxFirstTime <- with(dfCovidVaxFirst, sprintf("%d-01-%02d", CVDVAC1M_A, CVDVAC1Y_A))

dfCovidVaxLast$LastCovidVaxNotFirstTime <- with(dfCovidVaxLast, sprintf("%d-01-%02d", CVDVAC2M_A, CVDVAC2Y_A))

dfCovidVaxFirst_ <- dfCovidVaxFirst %>%
  filter(CVDDIAG_A < 3)

dfCovidVaxLast_ <- dfCovidVaxLast %>%
  filter(CVDDIAG_A < 3)

dfCovidVaxFirst1 <- dfCovidVaxFirst_ |>
  select(LastCovidVaxFirstTime, CVDDIAG_A)

dfCovidVaxLast1 <- dfCovidVaxLast_ |>
  select(LastCovidVaxNotFirstTime, CVDDIAG_A)

dftransf <- dfCovidVaxFirst1 |>
  select(LastCovidVaxFirstTime, CVDDIAG_A)

dftransf['date']<- as.Date(dftransf$LastCovidVaxFirstTime, format="%m-%d-%Y")

dftransfilt <- dftransf %>% filter(!is.na(date))

dfFirstV <- dftransfilt |>
  select(date, CVDDIAG_A)

dffirstVCount<- dfFirstV %>% group_by(date) %>%tally() 

dfMerge <- merge(dffirstVCount, dfFirstVSum, by = "date", all.x=TRUE, all.y=TRUE)

dfMerge['percent'] = dfMerge['Frequency']/dfMerge['n']

dfMerge <- dfMerge %>% filter(percent >.0000001)
dfMerge |>
  ggplot(mapping = aes(x = date, y = n)) +
  geom_line() +
  labs(title = "Date of First Covid Vaccine") +
  theme_hc() +
  scale_x_date(date_labels = "%Y (%b)") + ylab("Number of People")

The first vaccine came out in Dec 2021, which is around where the graph starts to increase. There was an increase in April and May 2021. In June 2021 when it started to decrease, there was a slowdown in people getting the vaccine and a record low number of cases.

Source: https://www.kff.org/coronavirus-covid-19/poll-finding/kff-covid-19-vaccine-monitor-june-2021/

On September 9 2021, Biden made an announcement requiring federal employees to be vaccinated by the end of January 2022, which is around the time of the largest peak between Sept 2021 and January 2022.

Source: https://www.whitehouse.gov/briefing-room/presidential-actions/2021/09/09/executive-order-on-requiring-coronavirus-disease-2019-vaccination-for-federal-employees/

Cancer

Cancer by Sex

Told has cancer.


dfFemale = adult22 %>%
  filter(SEX_A == 2)

dfFemaleCan = dfFemale %>%
  filter(CANEV_A == 1)

dfMale = adult22 %>%
  filter(SEX_A == 1)

dfMaleCan = dfMale %>%
  filter(CANEV_A == 1)

TotalF <- nrow(dfFemale)
TotalM <- nrow(dfMale)
PercentF <- (nrow(dfFemaleCan)/nrow(dfFemale))*100
PercentM <- (nrow(dfMaleCan)/nrow(dfMale))*100

PercentCan <- data.frame(                                            
   Sex  = c("Female", "Male"),       
   Percent= c((PercentF), (PercentM)))

ggplot(PercentCan, aes(x = Sex, y=Percent)) +
  geom_point()

Percent by Type of Cancer

dfCan <- adult22 %>%
  filter(NUMCAN_A < 7 & NUMCAN_A !=0)

dfBlad <- dfCan %>%
  filter(BLADDCAN_A == 1)

dfBlood <- dfCan %>%
  filter(BLOODCAN_A == 1)

dfBrain <- dfCan %>%
  filter(BRAINCAN_A == 1)

dfBone <- dfCan %>%
  filter(BONECAN_A == 1)

dfBreast <- dfCan %>%
  filter(BREASCAN_A == 1)

dfCervical <- dfCan %>%
  filter(CERVICAN_A == 1)

dfEsoph <- dfCan %>%
  filter(BLADDCAN_A == 1)

dfGall <- dfCan %>%
  filter(ESOPHCAN_A == 1)

dfLarynx <- dfCan %>%
  filter(LARYNCAN_A == 1)

dfLeuk <- dfCan %>%
  filter(LEUKECAN_A == 1)

dfLiver <- dfCan %>%
  filter(LIVERCAN_A == 1)

dfLung <- dfCan %>%
  filter(LUNGCAN_A == 1)

dfLymph <- dfCan %>%
  filter(LYMPHCAN_A == 1)

dfMela <- dfCan %>%
  filter(MELANCAN_A == 1)

dfMouth <- dfCan %>%
  filter(MOUTHCAN_A == 1)

dfOvary <- dfCan %>%
  filter(OVARYCAN_A == 1)

dfPanc <- dfCan %>%
  filter(PANCRCAN_A== 1)

dfProst <- dfCan %>%
  filter(PROSTCAN_A == 1)

dfSkinMela <- dfCan %>%
  filter(SKNMCAN_A == 1)

dfSkinNoMela <- dfCan %>%
  filter(SKNNMCAN_A == 1)

dfSkinUnknown <- dfCan %>%
  filter(SKNDKCAN_A == 1)

dfStomach <- dfCan %>%
  filter(STOMACAN_A == 1)

dfThroat <- dfCan %>%
  filter(THROACAN_A == 1)

dfThyroid <- dfCan %>%
  filter(THYROCAN_A == 1)

dfUterus <- dfCan %>%
  filter(UTERUCAN_A == 1)

dfHandNeck <- dfCan %>%
  filter(HDNCKCAN_A == 1)

dfColRec <- dfCan %>%
  filter(COLRCCAN_A == 1)

dfOther <- dfCan %>%
  filter(OTHERCANP_A == 1)
TBladF <- nrow(dfBlad %>%
  filter(SEX_A == 2))/TotalF*100
TBloodF <- nrow(dfBlood %>%
  filter(SEX_A == 2))/TotalF*100
TBoneF <- nrow(dfBone %>%
  filter(SEX_A == 2))/TotalF*100
TBrainF <- nrow(dfBrain %>%
  filter(SEX_A == 2))/TotalF*100
TBreastF <- nrow(dfBreast %>%
  filter(SEX_A == 2))/TotalF*100
TEsophF <- nrow(dfEsoph %>%
  filter(SEX_A == 2))/TotalF*100
TCervF <- nrow(dfCervical %>%
  filter(SEX_A == 2))/TotalF*100
TGallF <- nrow(dfGall %>%
  filter(SEX_A == 2))/TotalF*100
TLarynxF <- nrow(dfLarynx %>%
  filter(SEX_A == 2))/TotalF*100
TLeukF <- nrow(dfLeuk %>%
  filter(SEX_A == 2))/TotalF*100
TLungF <- nrow(dfLung %>%
  filter(SEX_A == 2))/TotalF*100
TLiverF <- nrow(dfLiver %>%
  filter(SEX_A == 2))/TotalF*100
TMelaF <- nrow(dfMela %>%
  filter(SEX_A == 2))/TotalF*100
TMouthF <- nrow(dfMouth %>%
  filter(SEX_A == 2))/TotalF*100
TOvaryF <- nrow(dfOvary %>%
  filter(SEX_A == 2))/TotalF*100
TPancF <- nrow(dfBlad %>%
  filter(SEX_A == 2))/TotalF*100
TSkinMelaF <- nrow(dfSkinMela %>%
  filter(SEX_A == 2))/TotalF*100
TSkinNoMelaF <- nrow(dfSkinNoMela %>%
  filter(SEX_A == 2))/TotalF*100
TSkinUnknownF <- nrow(dfSkinUnknown %>%
  filter(SEX_A == 2))/TotalF*100
TStomachF <- nrow(dfStomach %>%
  filter(SEX_A == 2))/TotalF*100
TThyroidF <- nrow(dfThyroid %>%
  filter(SEX_A == 2))/TotalF*100
TThroatF <- nrow(dfThroat %>%
  filter(SEX_A == 2))/TotalF*100
TUterusF <- nrow(dfUterus %>%
  filter(SEX_A == 2))/TotalF*100
THandNeckF <- nrow(dfHandNeck %>%
  filter(SEX_A == 2))/TotalF*100
TColRecF <- nrow(dfColRec %>%
  filter(SEX_A == 2))/TotalF*100
TOtherF <- nrow(dfOther %>%
  filter(SEX_A == 2))/TotalF*100
Cancer Among Females
CancerF <- data.frame(                                            
   Cancer  = c("Bladder", "Blood","Brain","Bone","Breast","Esophagus","Cervical","GallBladder","Larynx","Leukemia","Lung","Liver","Melanoma","Mouth","Ovarian","Pancreas","Skin Melanoma","Skin-Not Melanoma","Skin-Unknown","Stomach","Thyroid","Throat","Uterus","Hand and Neck","ColonRectal","Other"),       
   Percent= c((TBladF), (TBloodF),(TBrainF),(TBoneF),(TBreastF),(TEsophF),(TCervF),(TGallF),(TLarynxF),(TLeukF),(TLungF),(TLiverF),(TMelaF),(TMouthF),(TOvaryF),(TPancF),(TSkinMelaF),(TSkinNoMelaF),(TSkinUnknownF),(TStomachF),(TThyroidF),(TThroatF),(TUterusF),(THandNeckF),(TColRecF),(TOtherF)))

ggplot(CancerF, aes(x = Percent, y=Cancer)) +
  geom_point() + labs(title = "Cancer Among Females")

Cancer Among Males
TBladM <- nrow(dfBlad %>%
  filter(SEX_A == 1))/TotalM*100
TBloodM <- nrow(dfBlood %>%
  filter(SEX_A == 1))/TotalM*100
TBoneM <- nrow(dfBone %>%
  filter(SEX_A == 1))/TotalM*100
TBrainM <- nrow(dfBrain %>%
  filter(SEX_A == 1))/TotalM*100
TBreastM <- nrow(dfBreast %>%
  filter(SEX_A == 1))/TotalM*100
TEsophM <- nrow(dfEsoph %>%
  filter(SEX_A == 1))/TotalM*100
TGallM <- nrow(dfGall %>%
  filter(SEX_A == 1))/TotalM*100
TLarynxM <- nrow(dfLarynx %>%
  filter(SEX_A == 1))/TotalM*100
TLeukM <- nrow(dfLeuk %>%
  filter(SEX_A == 1))/TotalM*100
TLungM <- nrow(dfLung %>%
  filter(SEX_A == 1))/TotalM*100
TLiverM <- nrow(dfLiver %>%
  filter(SEX_A == 1))/TotalM*100
TMelaM <- nrow(dfMela %>%
  filter(SEX_A == 1))/TotalM*100
TMouthM <- nrow(dfMouth %>%
  filter(SEX_A == 1))/TotalM*100
TPancM <- nrow(dfPanc %>%
  filter(SEX_A == 1))/TotalM*100
TProstM <- nrow(dfProst %>%
  filter(SEX_A == 1))/TotalM*100
TSkinMelaM <- nrow(dfSkinMela %>%
  filter(SEX_A == 1))/TotalM*100
TSkinNoMelaM <- nrow(dfSkinNoMela %>%
  filter(SEX_A == 1))/TotalM*100
TSkinUnknownM <- nrow(dfSkinUnknown %>%
  filter(SEX_A == 1))/TotalM*100
TStomachM <- nrow(dfStomach %>%
  filter(SEX_A == 1))/TotalM*100
TThyroidM <- nrow(dfThyroid %>%
  filter(SEX_A == 1))/TotalM*100
TThroatM <- nrow(dfThroat %>%
  filter(SEX_A == 1))/TotalM*100
THandNeckM <- nrow(dfHandNeck %>%
  filter(SEX_A == 1))/TotalM*100
TColRecM <- nrow(dfColRec %>%
  filter(SEX_A == 1))/TotalM*100
TOtherM <- nrow(dfOther %>%
  filter(SEX_A == 1))/TotalM*100
CancerM <- data.frame(                                            
   Cancer  = c("Bladder", "Blood","Brain","Bone","Breast","Esophagus","GallBladder","Larynx","Leukemia","Lung","Liver","Melanoma","Mouth","Pancreas","Skin Melanoma","Skin-Not Melanoma","Skin-Unknown","Stomach","Thyroid","Throat","Hand and Neck","ColonRectal","Other"),       
   Percent= c((TBladM), (TBloodM),(TBrainM),(TBoneM),(TBreastM),(TEsophM),(TGallM),(TLarynxM),(TLeukM),(TLungM),(TLiverM),(TMelaM),(TMouthM),(TPancM),(TSkinMelaM),(TSkinNoMelaM),(TSkinUnknownM),(TStomachM),(TThyroidM),(TThroatM),(THandNeckM),(TColRecM),(TOtherM)))

ggplot(CancerM, aes(x = Percent, y=Cancer)) +
  geom_point() + labs(title = "Cancer Among Males")

Cancer Among Both
df_Canmerge <- merge(CancerF,CancerM,by="Cancer", all.x = TRUE) 

names(df_Canmerge)[names(df_Canmerge) == "Percent.x"] <- "Female"
names(df_Canmerge)[names(df_Canmerge) == "Percent.y"] <- "Male"
dfCancerMerged <- melt(df_Canmerge, id.vars="Cancer")
names(dfCancerMerged)[names(dfCancerMerged) == "value"] <- "Percent"
names(dfCancerMerged)[names(dfCancerMerged) == "variable"] <- "Sex"

ggplot(dfCancerMerged, aes(Percent,Cancer, col=Sex)) + 
  geom_point() + labs(title = "Cancer Among Males and Females")

Both males and females had a higher percentage for Skin-Not Melanoma cancer. The highest percentage for cancer was breast cancer in females.In many of the cancer categories, females had a slightly lower percentage.

Summary

While many of the ways to stay healthy are commonly known and advertised, it is interesting to look at the data to get a more specific idea. While many of these did not have much of a difference between categories, there is some information that can be gained that follow many of the health ideas we already know. These include

  1. It is less healthier, mentally and physically, for you to smoke. Smoking at least 100 cigarettes can make this worst and if you end up with lung cancer, it could be contributed to you smoking.
  2. Cancer is important to watch out for, and there are some specifically that are more common based on your sex and overall more common.
  3. While it is mostly unavoidable, those who have difficulty seeing can have worst life satisfaction, so if you can get it fixed by surgery or glasses/contacts, it will be helpful.
  4. It is better to for your mental and physical health to stay around a normal BMI. However, this could be argued based on if your weight comes from non-muscle fat or muscle fat.
  5. A higher education could potentially lead you to feel more satisfied and have better health.
LS0tCnRpdGxlOiAiMjAyMSBOYXRpb25hbCBIZWFsdGggSW50ZXJ2aWV3IEFkdWx0IFN1cnZleSIKb3V0cHV0OiBodG1sX25vdGVib29rCmVkaXRvcl9vcHRpb25zOiAKICBtYXJrZG93bjogCiAgICB3cmFwOiA3MgotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCgogYWR1bHQyMiA8LSByZWFkLmNzdigifi9Eb2N1bWVudHMvRGF0YURpdmUvYWR1bHQyMi5jc3YiKQogCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdhcG1pbmRlcikKbGlicmFyeShnZ3RoZW1lcykKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KG1hZ3JpdHRyKQpsaWJyYXJ5KGVmZnNpemUpCmxpYnJhcnkocHdyc3MpCmxpYnJhcnkoYnJvb20pCmxpYnJhcnkobGluZGlhKQpsaWJyYXJ5KGJvb3QpCmxpYnJhcnkoY2FyKQpsaWJyYXJ5KHh0cykKbGlicmFyeSh0c2liYmxlKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKbGlicmFyeShyZXNoYXBlMikKCgoKIGFkdWx0MjJfcmF3IDwtIGFkdWx0MjIKIApgYGAKCiMgRGF0YXNldAoKVGhlIGRhdGFzZXQgaXMgZGF0YSBmcm9tIHRoZSAyMDIxIE5hdGlvbmFsIEhlYWx0aCBJbnRlcnZpZXcgQWR1bHQKU3VydmV5LiBUaGUgc3VydmV5IGNvbnRhaW5lZCBxdWVzdGlvbnMgcmVsYXRlZCB0byBob3VzZWhvbGQgYW5kIGZhbWlseQpjb21wb3NpdGlvbiwgZGVtb2dyYXBoaWNzIGFib3V0IHRoZSBzdXJ2ZXkgdGFrZXIsIHNhdGlzZmFjdGlvbiB3aXRoCmxpZmUsIGhlYWx0aCBpbnN1cmFuY2UsIG1lZGljYXRpb24sIGltbXVuaXphdGlvbiwgcHJldmVudGl2ZSBzY3JlZW5pbmdzLAphbmQgbXVsdGlwbGUgaGVhbHRoIHByb2JsZW1zIHN1Y2ggYXMgaHlwZXJ0ZW5zaW9uLCBjYXJkaW92YXNjdWxhcgpjb25kaXRpb25zLCBjYW5jZXIsIHZpc2lvbiwgaGVhcmluZywgbW9iaWxpdHksIGFuZCBtb3JlLgoKVGhpcyBzdXJ2ZXkgaXMgaW1wb3J0YW50IGluIGZvbGxvd2luZyB0aGUgaGVhbHRoIG9mIEFtZXJpY2FuJ3MgYmFzZWQgb24KbWFueSBkaWZmZXJlbnQgZmFjdG9ycyBvZiB0aGVpciBsaXZlcy4gTG9va2luZyBhdCBwcmV2aW91cyBzdXJ2ZXlzIGNhbgphbHNvIGhlbHAgdG8gc2VlIHRyZW5kcyBpbiBBbWVyaWNhbnMnIGhlYWx0aC4KCkZvciB0aGUgZGF0YSB1c2VkLCByZXNwb25zZXMgb2YgInJlZnVzZWQiLCJkb24ndCBrbm93IiBhbmQgIm5vdAphc2NlcnRhaW5lZCIgd2VyZSBmaWx0ZXJlZCBvdXQgYXMgdGhlc2UgcmVzcG9uc2VzIGhhZCBhIHRlbmRlbmN5IHRvIGJlCm11Y2ggc21hbGxlciB0aGFuIHRoZSBvdGhlcnMgYW5kIHdlcmUgbm90IGhlbHBmdWwgZm9yIHdoYXQgd2FzIGJlaW5nCmxvb2tlZCBhdC4KCiMgQ29sdW1ucwoKIyMjIEdlbmVyYWwgSGVhbHRoCgpgYGAgICAgICAgICAKMS4gRXhjZWxsZW50IAoyLiBWZXJ5IEdvb2QgCjMuIEdvb2QgCjQuIEZhaXIgCjUuIFBvb3IgCmBgYAoKIyMjIExpZmUgU2F0aXNmYWN0aW9uCgpgYGAgICAgICAgICAKMS4gVmVyeSBTYXRpc2ZpZWQgCjIuIFNhdGlzZmllZCAKMy4gRGlzc2F0aXNmaWVkIAo0LiBWZXJ5IERpc3NhdGlzZmllZApgYGAKCiMjIyBSYWNlIChTaW5nbGUgYW5kIE11bHRpcGxlIFJhY2UgR3JvdXBzKQoKYGBgICAgICAgICAgCjEuICBXaGl0ZSBvbmx5CjIuICBCbGFjay9BZnJpY2FuIEFtZXJpY2FuIG9ubHkKMy4gIEFzaWFuIG9ubHkKNC4gIEFJQU4gb25seSAoQW1lcmljYW4gSW5kaWFucyBhbmQgQWxhc2thIE5hdGl2ZXMpCjUuICBBSUFOIGFuZCBhbnkgb3RoZXIgZ3JvdXAKNi4gIE90aGVyCjcuICBIaXNwYW5pYyB3aG8gZGlkIG5vdCBpZGVudGlmeSB3aXRoIG9uZSBvZiB0aGUgb3RoZXIgY2F0ZWdvcmllcwpgYGAKCiMjIyBFZHVjYXRpb24gTGV2ZWwKCmBgYCAgICAgICAgIAowLiBOZXZlciBhdHRlbmRlZC9LaW5kZXJnYXJ0ZW4gb25seSAKMS4gR3JhZGUgMS0xMSAKMi4gMTJ0aCBncmFkZSwgbm9kaXBsb21hIAozLiBHRUQgb3IgZXF1aXZhbGVudCAKNC4gSGlnaCBTY2hvb2wgR3JhZHVhdGUgCjUuIFNvbWUgY29sbGVnZSwgbm9kZWdyZWUgCjYuIEFzc29jaWF0ZSBkZWdyZWU6IG9jY3VwYXRpb25hbCwgdGVjaG5pY2FsLCBvciB2b2NhdGlvbmFsIHByb2dyYW0gCjcuIEFzc29jaWF0ZSBkZWdyZWU6IGFjYWRlbWljIHByb2dyYW0gCjguIEJhY2hlbG9yJ3MgZGVncmVlIAo5LiBNYXN0ZXIncyBkZWdyZWUgCjEwLiBQcm9mZXNzaW9uYWwgU2Nob29sIG9yIERvY3RvcmFsIGRlZ3JlZQpgYGAKCiMjIyBCTUkKCmBgYCAgICAgICAgIAoxLiBVbmRlcndlaWdodCAKMi4gTm9ybWFsIAozLiBPdmVyd2VpZ2h0IAo0LiBPYmVzZQpgYGAKCiMgVmlzaW9uCgpgYGAgICAgICAgICAKRG8geW91IHdlYXIgZ2xhc3NlcyBvciBjb250YWN0IGxlbnNlcz8KMS4gWWVzIAoyLiBObwpgYGAKCmBgYCAgICAgICAgIApEbyB5b3UgaGF2ZSBkaWZmaWN1bHR5IHNlZWluZz8gCjEuIE5vIGRpZmZpY3VsdHkgCjIuIFNvbWUgZGlmZmljdWx0eSAKMy4gQSBsb3Qgb2YgZGlmZmljdWx0eSAKNC4gQ2Fubm90IGRvIGF0IGFsbApgYGAKCiMjIyBDYW5jZXIKCmBgYCAgICAgICAgIApTZXBhcmF0ZSBjb2x1bW5zIGZvciBlYWNoIHR5cGUgb2YgY2FuY2VyLgoKTnVtYmVyIG9mIHJlcG9ydGVkIHR5cGVzIG9mIGNhbmNlci4gCjAuIE5vIGNhbmNlciAKMS0zLiAxIHRvIDMgCjQuIDQgb3IgbW9yZQpgYGAKCiMgRGVtb2dyYXBoaWNzCgpMb29raW5nIGF0IGRlbW9ncmFwaGljcyBjYW4gaGVscCB0byBnaXZlIGEgYml0IG9mIGFuIGlkZWEgYWJvdXQgd2hhdApzb3J0IG9mIGRhdGEgd2Ugc2hvdWxkIGxvb2sgYXQuCgojIyMgU2V4CgpgYGB7cn0KCmRmU2V4RmlsdGVyIDwtIGFkdWx0MjIgJT4lIAogIGZpbHRlcihTRVhfQSA9PSAxIHwgU0VYX0EgPT0gMikKCmRmU2V4RmlsdGVyIDwtCiAgZGZTZXhGaWx0ZXIgfD4KICAgIGdyb3VwX2J5KGRmU2V4RmlsdGVyJFNFWF9BKSB8PgogICAgbXV0YXRlKFNleF9TdGF0dXMgPSBpZmVsc2UoU0VYX0EgPT0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1hbGUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkZlbWFsZSIpKSB8PgoKICB1bmdyb3VwKCkKZ2dwbG90KGRmU2V4RmlsdGVyLCBhZXMoeCA9IFNleF9TdGF0dXMsIGZpbGw9U2V4X1N0YXR1cykpICsgeGxhYigiU2V4IikgKwogIGdlb21fYmFyKCkKYGBgCgojIyMgQWdlCgpUaGUgZmFyIHJpZ2h0IGJhciwgODUsIGlzIGZvciB0aG9zZSB3aG8gYXJlIDg1Ky4KCmBgYHtyfQoKCmRmQWdlRmlsdGVyIDwtIGFkdWx0MjIgJT4lIAogIGZpbHRlcihBR0VQX0EgPCA4NikKCmdncGxvdChkZkFnZUZpbHRlciwgYWVzKHggPSBBR0VQX0EpKSArIHhsYWIoIkFnZSIpICsKICBnZW9tX2JhcigpCmBgYAoKVGhlIGxhcmdlc3QgZ3JvdXAgYmFzZWQgb24gYWdlIHdlcmUgdGhvc2UgdGhhdCB3ZXJlIDg1IG9yIG9sZGVyLgoKIyMjIEVkdWNhdGlvbiBMZXZlbAoKYGBge3J9CmRmRWR1RmlsdGVyIDwtIGFkdWx0MjIgJT4lIAogIGZpbHRlcihFRFVDUF9BIDwgOTcpCgoKZGZFZHVGaWx0ZXIgPC0KICBkZkVkdUZpbHRlciB8PgogICAgZ3JvdXBfYnkoZGZFZHVGaWx0ZXIkRURVQ1BfQSkgfD4KICAgIG11dGF0ZShFZHVfU3RhdHVzID0gaWZlbHNlKEVEVUNQX0EgPT0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JhZGUgMS0xMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEVEVUNQX0EgPT0gMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjEydGggR3JhZGUsIG5vIERpcGxvbWEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRURVQ1BfQSA9PSAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR0VEIG9yIEVxdWl2YWxlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRURVQ1BfQSA9PSA0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSGlnaCBTY2hvb2wgR3JhZHVhdGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRURVQ1BfQSA9PSA1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU29tZSBDb2xsZWdlLCBubyBEZWdyZWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRURVQ1BfQSA9PSA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQXNzb2NpYXRlIGRlZ3JlZTogb2NjdXBhdGlvbmFsLCB0ZWNobmljYWwsIG9yIHZvY2F0aW9uYWwgcHJvZ3JhbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShFRFVDUF9BID09IDcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBc3NvY2lhdGUgZGVncmVlOiBhY2FkZW1pYyBwcm9ncmFtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEVEVUNQX0EgPT0gOCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJhY2hlbG9yJ3MgZGVncmVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEVEVUNQX0EgPT0gOSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1hc3RlcidzIGRlZ3JlZSAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoRURVQ1BfQSA9PSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlByb2Zlc3Npb25hbCBTY2hvb2wgb3IgRG9jdG9yYWwgZGVncmVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEVEVUNQX0EgPT0gOTcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZWZ1c2VkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRG9uJ3QgS25vdyIpKSkpKSkpKSkpKSkgfD4gCnVuZ3JvdXAoKQogIAogIApkZkVkdUZpbHRlciRFZHVfU3RhdHVzIDwtIGZhY3RvcihkZkVkdUZpbHRlciRFZHVfU3RhdHVzLCBsZXZlbHMgPSBjKCJHcmFkZSAxLTExIiwgIjEydGggR3JhZGUsIG5vIERpcGxvbWEiLCAiR0VEIG9yIEVxdWl2YWxlbnQiLCJIaWdoIFNjaG9vbCBHcmFkdWF0ZSIsICJTb21lIENvbGxlZ2UsIG5vIERlZ3JlZSIsICJBc3NvY2lhdGUgZGVncmVlOiBvY2N1cGF0aW9uYWwsIHRlY2huaWNhbCwgb3Igdm9jYXRpb25hbCBwcm9ncmFtIiwgIkFzc29jaWF0ZSBkZWdyZWU6IGFjYWRlbWljIHByb2dyYW0iLCAiQmFjaGVsb3IncyBkZWdyZWUiLCAiTWFzdGVyJ3MgZGVncmVlICIsICJQcm9mZXNzaW9uYWwgU2Nob29sIG9yIERvY3RvcmFsIGRlZ3JlZSIsICJSZWZ1c2VkIiwgIkRvbid0IEtub3ciKSkKCmdncGxvdChkZkVkdUZpbHRlciwgYWVzKHggPSBFRFVDUF9BLCBmaWxsPUVkdV9TdGF0dXMpKSArCiAgZ2VvbV9iYXIoKSArIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCkpICsgeGxhYigiRWR1Y2F0aW9uIExldmVsIikKCmBgYAoKIyMjIFJhY2UKCmBgYHtyfQpkZlJhY2VGaWx0ZXIgPC0gYWR1bHQyMiAlPiUgCiAgZmlsdGVyKFJBQ0VBTExQX0EgPD0gOCApCgpkZlJhY2VGaWx0ZXIyIDwtIGRmUmFjZUZpbHRlciAgJT4lIAogIGZpbHRlcihSQUNFQUxMUF9BICE9IDcgKQoKCmRmUmFjZUZpbHRlcjIgPC0KICBkZlJhY2VGaWx0ZXIyIHw+CiAgICBncm91cF9ieShkZlJhY2VGaWx0ZXIyJFJBQ0VBTExQX0EpIHw+CiAgICBtdXRhdGUoUmFjZSA9IGlmZWxzZShSQUNFQUxMUF9BID09IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldoaXRlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoUkFDRUFMTFBfQSA9PSAyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQWZyaWNhbiBBbWVyaWNhbi9CbGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShSQUNFQUxMUF9BID09IDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBc2lhbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShSQUNFQUxMUF9BID09IDQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBSUFOKiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShSQUNFQUxMUF9BID09IDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBSUFOICsgT3RoZXIgR3JvdXAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoUkFDRUFMTFBfQSA9PSA2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiT3RoZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoUkFDRUFMTFBfQSA9PSA4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSGlzcGFuaWMqKiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRvbid0IEtub3ciKSkpKSkpKSkgfD4gCnVuZ3JvdXAoKQogIApnZ3Bsb3QoZGZSYWNlRmlsdGVyMiwgYWVzKHggPSBSYWNlLCBmaWxsPVJhY2UpKSArCiAgZ2VvbV9iYXIoKSArIHRoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCkpCgpgYGAKClRoZXJlIHdhcyBhIG11Y2ggbGFyZ2VyIGFtb3VudCBvZiB0aG9zZSB3aG8gaWRlbnRpZmllZCBhcyB3aGl0ZSB3aG8gdG9vawp0aGUgc3VydmV5LgoKIyMjIEdlbmVyYWwgUGh5c2ljYWwgSGVhbHRoCgpgYGB7cn0KCmRmR0hGaWx0ZXIgPC0gYWR1bHQyMiAlPiUgCiAgZmlsdGVyKFBIU1RBVF9BIDwgJzcnKQoKZ2dwbG90KGRmR0hGaWx0ZXIsIGFlcyh4ID0gZmFjdG9yKFBIU1RBVF9BKSkpICsgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9YygiRXhjZWxsZW50IiwgIlZlcnkgR29vZCIsICJHb29kIiwgIkZhaXIiLCAiUG9vciIpKSArCiAgZ2VvbV9iYXIoKSArIAogIHhsYWIoIkdlbmVyYWwgUGh5c2ljYWwgSGVhbHRoIikKYGBgCgpNb3N0IHBlb3BsZSBwdXQgdGhlaXIgR2VuZXJhbCBQaHlzaWNhbCBIZWFsdGggaW4gdGhlIG1vcmUgcG9zaXRpdmUgc2lkZQooRXhjZWxsZW50LCBWZXJ5IGdvb2QsIEdvb2QpIHNpZGUgb2YgdGhlIHNjYWxlLgoKIyMjIExpZmUgU2F0aXNmYWN0aW9uCgpgYGB7cn0KCmRmRmlsdGVyZWRMUyA8LSBhZHVsdDIyICU+JSAKICBmaWx0ZXIoTFNBVElTNF9BIDwgJzUnKQoKCmdncGxvdChkZkZpbHRlcmVkTFMsIGFlcyh4ID0gZmFjdG9yKExTQVRJUzRfQSkpKSArIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPWMoIlZlcnkgU2F0aXNmaWVkIiwgIlNhdGlzZmllZCIsICJEaXNzYXRpc2ZpZWQiLCAiVmVyeSBEaXNzYXRpc2ZpZWQiKSkgKwogIGdlb21fYmFyKCkgKwogIHhsYWIoIkxpZmUgU2F0aXNmYWN0aW9uIikKCmBgYAoKTW9zdCBwZW9wbGUgY29uc2lkZXJlZCB0aGVtc2VsdmVzIHRvIGJlIHBvc2l0aXZlbHkgc2F0aXNmaWVkIHdpdGggbGlmZS4KVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIHNpZGUgb2YgdGhlIHNjYWxlIHdhcwpsYXJnZXIgdGhhbiBmb3IgR2VuZXJhbCBQaHlzaWNhbCBIZWFsdGguCgojIEJNSQoKQk1JIGNhbiBvZnRlbiBiZSBjb250cmlidXRlZCB0byBoZWFsdGggYW5kIGNlcnRhaW4gbGV2ZWxzIGNhbiBiZQpjb250cmlidXRlZCB0byBoZWFsdGggaXNzdWVzLiBIb3dldmVyLCBCTUkgaXMgZnVuZGFtZW50YWxseSBmbGF3ZWQgYXMgaXQKZG9lcyBub3QgdGFrZSBpbnRvIGNvbnNpZGVyYXRpb24gbXVzY2xlIGZhdC4gRm9yIGV4YW1wbGUsIGEgYm9keSBidWlsZGVyCmNvdWxkIGJlIGNvbnNpZGVyZWQgdG8gaGF2ZSBhbiAib3ZlcndlaWdodCIgQk1JLCBidXQgd291bGQgYmUgbXVjaApoZWFsdGhpZXIgdGhhbiBzb21lb25lIHdobyBoYWQgbW9zdGx5IG5vbi1tdXNjbGUgZmF0LgoKIyMjIEhpc3RvZ3JhbQoKYGBge3J9Cmhpc3QoZGZGaWx0ZXJlZEJNSSRCTUlDQVRfQSkKYGBgCgpUaGUgZGlzdHJpYnV0aW9uIHdhcyByZWxhdGl2ZWx5IGVxdWFsLCBleGNlcHQgZm9yIHRoZSBVbmRlcndlaWdodApjYXRlZ29yeSwgc28gdGhlcmUgd2FzIGEgcG90ZW50aWFsIGZvciB0aGlzIGNhdGVnb3J5IHRvIGNhdXNlIHByb2JsZW1zLgoKIyMjIEJvb3RzdHJhcAoKVGhpcyBpcyB0byBoZWxwIHVzIGdldCBhIGJldHRlciBpZGVhIG9mIHRoZSBhdmVyYWdlIExpZmUgU2F0aXNmYWN0aW9uCmFuZCBHZW5lcmFsIFBoeXNpY2FsIEhlYWx0aCBiYXNlZCBvbiBhIHBlcnNvbidzIEJNSSBjYXRlZ29yeSwgYnkKY3JlYXRpbmcgc2FtcGxlcy4KCmBgYHtyfQoKZGZGaWx0ZXJlZExTQk1JIDwtIGFkdWx0MjIgJT4lCiAgZmlsdGVyKEJNSUNBVF9BIDwgNSAmIExTQVRJUzRfQSA8NSkKCmRmRmlsdGVyZWRQSEJNSSA8LSBhZHVsdDIyICU+JQogIGZpbHRlcihCTUlDQVRfQSA8IDUgJiBQSFNUQVRfQSA8NykKCmJvb3RfY2kgPC0gZnVuY3Rpb24gKHYsIGZ1bmMgPSBtZWRpYW4sIGNvbmYgPSAwLjk1LCBuX2l0ZXIgPSAxMDApIHsKICBib290X2Z1bmMgPC0gXCh4LCBpKSBmdW5jKHhbaV0pCiAgCiAgYiA8LSBib290KHYsIGJvb3RfZnVuYywgUiA9IG5faXRlcikKICBiIDwtIGJvb3QuY2koYiwgY29uZiA9IGNvbmYsIHR5cGUgPSAicGVyYyIpCiAgCiAgcmV0dXJuKGMoImxvd2VyIiA9IGIkcGVyY2VudFs0XSwKICAgICAgICAgICAidXBwZXIiID0gYiRwZXJjZW50WzVdKSkKfQpgYGAKCiMjIyMgQm9vdHN0cmFwOiBMaWZlIFNhdGlzZmFjdGlvbiB2cyBCTUkKCmBgYHtyfQpkZl9jaUxTIDwtIGRmRmlsdGVyZWRMU0JNSSB8PgogIGdyb3VwX2J5KEJNSUNBVF9BKSB8PgogIHN1bW1hcmlzZShjaV9sb3dlciA9IGJvb3RfY2koTFNBVElTNF9BLCBtZWFuKVsnbG93ZXInXSwKICAgICAgICAgICAgbWVhbl9MUyA9IG1lYW4oTFNBVElTNF9BKSwKICAgICAgICAgICAgY2lfdXBwZXIgPSBib290X2NpKExTQVRJUzRfQSwgbWVhbilbJ3VwcGVyJ10pCgpgYGAKCmBgYHtyfQoKZGZfY2lMUyB8PgogIGdncGxvdCgpICsKICBnZW9tX2Vycm9yYmFyaChtYXBwaW5nID0gYWVzKHkgPSBCTUlDQVRfQSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4bWluPWNpX2xvd2VyLCB4bWF4PWNpX3VwcGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAnOTUlIEMuSS4nKSwgaGVpZ2h0ID0gMC41KSArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBtZWFuX0xTLCB5ID0gQk1JQ0FUX0EsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gJ0dyb3VwIE1lYW4nKSwKICAgICAgICAgICAgIHNoYXBlID0gJ3wnLAogICAgICAgICAgICAgc2l6ZSA9IDUpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoJ2JsYWNrJywgJ3JlZCcpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gIkxpZmUgU2F0aXNmYWN0aW9uIGJ5IEJNSSBDYXRlZ29yeSIsCiAgICAgICB4ID0gIkxpZmUgU2F0aXNmYWN0aW9uIiwKICAgICAgIHkgPSAiQk1JIENhdGVnb3J5IiwKICAgICAgIGNvbG9yID0gJycpCmBgYAoKQ2F0ZWdvcnkgMSwgdW5kZXJ3ZWlnaHQsIHNlZW1zIHRvIGhhdmUgYSBtdWNoIGxhcmdlciByYW5nZSB0aGFuIHRoZQpvdGhlciAzLCB3aGljaCBsaWtlIHN0YXRlZCBhYm92ZSwgY291bGQgYmUgYW4gaXNzdWUgYmVjYXVzZSBvZiBob3cgc21hbGwKdGhlIGRpc3RyaWJ1dGlvbiB3YXMuCgojIyMjIEJvb3RzdHJhcDogR2VuZXJhbCBQaHlzaWNhbCBIZWFsdGggdnMgQk1JCgpgYGB7cn0KZGZfY2lQSCA8LSBkZkZpbHRlcmVkUEhCTUkgfD4KICBncm91cF9ieShCTUlDQVRfQSkgfD4KICBzdW1tYXJpc2UoY2lfbG93ZXIgPSBib290X2NpKFBIU1RBVF9BLCBtZWFuKVsnbG93ZXInXSwKICAgICAgICAgICAgbWVhbl9QSCA9IG1lYW4oUEhTVEFUX0EpLAogICAgICAgICAgICBjaV91cHBlciA9IGJvb3RfY2koUEhTVEFUX0EsIG1lYW4pWyd1cHBlciddKQoKYGBgCgpgYGB7cn0KCmRmX2NpUEggfD4KICBnZ3Bsb3QoKSArCiAgZ2VvbV9lcnJvcmJhcmgobWFwcGluZyA9IGFlcyh5ID0gQk1JQ0FUX0EsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeG1pbj1jaV9sb3dlciwgeG1heD1jaV91cHBlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gJzk1JSBDLkkuJyksIGhlaWdodCA9IDAuNSkgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gbWVhbl9QSCwgeSA9IEJNSUNBVF9BLAogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICdHcm91cCBNZWFuJyksCiAgICAgICAgICAgICBzaGFwZSA9ICd8JywKICAgICAgICAgICAgIHNpemUgPSA1KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCdibGFjaycsICdyZWQnKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZSA9ICJHZW5lcmFsIEhlYWx0aCBieSBCTUkgQ2F0ZWdvcnkiLAogICAgICAgeCA9ICJHZW5lcmFsIEhlYWx0aCIsCiAgICAgICB5ID0gIkJNSSBDYXRlZ29yeSIsCiAgICAgICBjb2xvciA9ICcnKQpgYGAKClRoZXJlIHdlcmUgd2F5IGxlc3MgcGVvcGxlIGluIHRoZSB1bmRlcndlaWdodCBCTUkgKDEpIHRoYW4gdGhlIG90aGVyCmNhdGVnb3JpZXMsIHNpbWlsYXIgdG8gdGhlIGlzc3VlIGluIExpZmUgU2F0aXNmYWN0aW9uLCBzbyB0aGF0IGdyb3VwCmRvZXMgbm90IGdpdmUgYXMgbXVjaCBpbmZvcm1hdGlvbiwgb3IgYXMgYWNjdXJhdGUgb2YgaW5mb3JtYXRpb24gYXMgdGhlCm90aGVycyBhbmQgd2FzIHJlbW92ZWQgZm9yIHRoZSBncmFwaHMgYmVsb3cuCgojIyMgR2VuZXJhbCBIZWFsdGggYnkgQk1JIFN0YXR1cwoKYGBge3J9CgpkZkJNSUdIIDwtIGFkdWx0MjIgJT4lCiAgZmlsdGVyKFBIU1RBVF9BIDwgNykKCmRmTm9ybWFsQk1JIDwtIGRmQk1JR0ggJT4lCiAgZmlsdGVyKEJNSUNBVF9BID09IDIgKQoKZGZPdmVyQk1JIDwtIGRmQk1JR0ggJT4lCiAgZmlsdGVyKEJNSUNBVF9BID09IDMgKQoKZGZPYmVzZUJNSSA8LSBkZkJNSUdIICU+JQogIGZpbHRlcihCTUlDQVRfQSA9PSA0ICkKCkJNSUdIIDwtIGRhdGEuZnJhbWUoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgU3RhdHVzICA9IGMoMiwgMywgNCksICAgICAgIAogICBQaHlzaWNhbF9IZWFsdGg9IGMoIG1lYW4oZGZOb3JtYWxCTUkkUEhTVEFUX0EpLCBtZWFuKGRmT3ZlckJNSSRQSFNUQVRfQSksIG1lYW4oZGZPYmVzZUJNSSRQSFNUQVRfQSkpKQoKZ2dwbG90KEJNSUdILCBhZXMoeCA9IGZhY3RvcihTdGF0dXMpLCB5ID0gUGh5c2ljYWxfSGVhbHRoKSkgKyAKICBnZW9tX3BvaW50KCkgKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPSBjKCAiTm9ybWFsIiwgIk92ZXJ3ZWlnaHQiLCAiT2Jlc2UiKSkgKwogIHhsYWIoIkJNSSBTdGF0dXMiKSArCiAgeWxhYigiQXZlcmFnZSBHZW5lcmFsIFBoeXNpY2FsIEhlYWx0aCIpCgoKYGBgCgojIyMgTGlmZSBTYXRpc2ZhY3Rpb24gYnkgQk1JIFN0YXR1cwoKYGBge3J9CgpkZkJNSUxTIDwtIGFkdWx0MjIgJT4lCiAgZmlsdGVyKExTQVRJUzRfQSA8IDUpCgpkZk5vcm1hbEJNSUxTIDwtIGRmQk1JTFMgJT4lCiAgZmlsdGVyKEJNSUNBVF9BID09IDIgKQoKZGZPdmVyQk1JTFMgPC0gZGZCTUlMUyAlPiUKICBmaWx0ZXIoQk1JQ0FUX0EgPT0gMyApCgpkZk9iZXNlQk1JTFMgPC0gZGZCTUlMUyAlPiUKICBmaWx0ZXIoQk1JQ0FUX0EgPT0gNCApCgpCTUlMUyA8LSBkYXRhLmZyYW1lKCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgIFN0YXR1cyAgPSBjKDIsIDMsIDQpLCAgICAgICAKICAgTGlmZV9TYXRpcz0gYyggbWVhbihkZk5vcm1hbEJNSUxTJExTQVRJUzRfQSksIG1lYW4oZGZPdmVyQk1JTFMkTFNBVElTNF9BKSwgbWVhbihkZk9iZXNlQk1JTFMkTFNBVElTNF9BKSkpCgpnZ3Bsb3QoQk1JTFMsIGFlcyh4ID0gZmFjdG9yKFN0YXR1cyksIHkgPSBMaWZlX1NhdGlzKSkgKyAKICBnZW9tX3BvaW50KCkgKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzPSBjKCJOb3JtYWwiLCAiT3ZlcndlaWdodCIsICJPYmVzZSIpKSArCiAgeGxhYigiQk1JIFN0YXR1cyIpICsKICB5bGFiKCJBdmVyYWdlIExpZmUgU2F0aXNmYWN0aW9uIikKCgpgYGAKCiMgRWR1Y2F0aW9uIExldmVsCgojIyMgVnMgR2VuZXJhbCBQaHlzaWNhbCBIZWFsdGgKCmBgYHtyfQoKZGZGaWx0ZXJlZEVkdSA8LSBkZkdIRmlsdGVyICU+JQogIGZpbHRlcihFRFVDUF9BIDwgOTcpCgpkZl9jaUVkdSA8LSBkZkZpbHRlcmVkRWR1IHw+CiAgZ3JvdXBfYnkoRURVQ1BfQSkgfD4KICBzdW1tYXJpc2UoY2lfbG93ZXIgPSBib290X2NpKFBIU1RBVF9BLCBtZWFuKVsnbG93ZXInXSwKICAgICAgICAgICAgbWVhbl9QSCA9IG1lYW4oUEhTVEFUX0EpLAogICAgICAgICAgICBjaV91cHBlciA9IGJvb3RfY2koUEhTVEFUX0EsIG1lYW4pWyd1cHBlciddKQoKCmRmX2NpRWR1IHw+CiAgZ2dwbG90KCkgKwogIGdlb21fZXJyb3JiYXJoKG1hcHBpbmcgPSBhZXMoeSA9IEVEVUNQX0EsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeG1pbj1jaV9sb3dlciwgeG1heD1jaV91cHBlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gJzk1JSBDLkkuJyksIGhlaWdodCA9IDAuNSkgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gbWVhbl9QSCwgeSA9IEVEVUNQX0EsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gJ0dyb3VwIE1lYW4nKSwKICAgICAgICAgICAgIHNoYXBlID0gJ3wnLAogICAgICAgICAgICAgc2l6ZSA9IDUpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoJ2JsYWNrJywgJ3JlZCcpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gIkdlbmVyYWwgUGh5c2ljYWwgSGVhbHRoIGJ5IEVkdWNhdGlvbiIsCiAgICAgICB4ID0gIlBoeXNpY2FsIEhlYWx0aCIsCiAgICAgICB5ID0gIkVkdWNhdGlvbiIsCiAgICAgICBjb2xvciA9ICcnKQpgYGAKCldlIGNhbiBzZWUgdGhhdCBhcyBhIHBlcnNvbidzIGVkdWNhdGlvbiBsZXZlbCBkZWNyZWFzZXMsIHRoZWlyIGF2ZXJhZ2UKcGh5c2ljYWwgaGVhbHRoIGdlbmVyYWxseSBkZWNyZWFzZXMsIGhvd2V2ZXIgaXQgd2FzIHN0aWxsIGluIHRoZSBzYW1lCnBoeXNpY2FsIGhlYWx0aCBjYXRlZ29yeS4gVGhlcmUgc2VlbXMgdG8gYmUgYSBmZXcgZ3JvdXBzIGZvcm1pbmcsIHN1Y2gKYXMgdGhlIGJvdHRvbSAzLCB0aGUgbWlkZGxlIDQsIGFuZCB0aGUgdG9wIDMuCgojIyBWcyBMaWZlIFNhdGlzZmFjdGlvbgoKYGBge3J9CgpkZkZpbHRlcmVkRWR1TFMgPC0gZGZGaWx0ZXJlZExTICU+JQogIGZpbHRlcihFRFVDUF9BIDwgOTcpCgpkZl9jaUVkdUxTIDwtIGRmRmlsdGVyZWRFZHVMUyB8PgogIGdyb3VwX2J5KEVEVUNQX0EpIHw+CiAgc3VtbWFyaXNlKGNpX2xvd2VyID0gYm9vdF9jaShMU0FUSVM0X0EsIG1lYW4pWydsb3dlciddLAogICAgICAgICAgICBtZWFuX0xTID0gbWVhbihMU0FUSVM0X0EpLAogICAgICAgICAgICBjaV91cHBlciA9IGJvb3RfY2koTFNBVElTNF9BLCBtZWFuKVsndXBwZXInXSkKCgpkZl9jaUVkdUxTIHw+CiAgZ2dwbG90KCkgKwogIGdlb21fZXJyb3JiYXJoKG1hcHBpbmcgPSBhZXMoeSA9IEVEVUNQX0EsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeG1pbj1jaV9sb3dlciwgeG1heD1jaV91cHBlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gJzk1JSBDLkkuJyksIGhlaWdodCA9IDAuNSkgKwogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gbWVhbl9MUywgeSA9IEVEVUNQX0EsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gJ0dyb3VwIE1lYW4nKSwKICAgICAgICAgICAgIHNoYXBlID0gJ3wnLAogICAgICAgICAgICAgc2l6ZSA9IDUpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoJ2JsYWNrJywgJ3JlZCcpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gIkxpZmUgU2F0aXNmYWN0aW9uIGJ5IEVkdWNhdGlvbiIsCiAgICAgICB4ID0gIkxpZmUgU2F0aXNmYWN0aW9uIiwKICAgICAgIHkgPSAiRWR1Y2F0aW9uIiwKICAgICAgIGNvbG9yID0gJycpCmBgYAoKU2ltaWxhciB0byBnZW5lcmFsIGhlYWx0aCwgdGhlcmUgaXMgYSB0cmVuZCBvZiBhcyBlZHVjYXRpb24gbGV2ZWwKZGVjcmVhc2VzLCBsaWZlIHNhdGlzZmFjdGlvbiBkZWNyZWFzZXMuCgojIFZpc2lvbgoKYGBge3J9CmRmRmlsdGVyZWRWaXMgPC0gYWR1bHQyMiAlPiUKICBmaWx0ZXIoVklTSU9OREZfQSA8NCkKCmhpc3QoZGZGaWx0ZXJlZFZpcyRWSVNJT05ERl9BKQoKaGlzdChkZkZpbHRlcmVkVmlzJFdFQVJHTFNTX0EpCmBgYAoKIyMjIFZpc2lvbiB2cyBHZW5lcmFsIFBoeXNpY2FsIEhlYWx0aAoKYGBge3J9CmRmR2xhc3NlcyA8LSBhZHVsdDIyICU+JQogIGZpbHRlcihQSFNUQVRfQSA8IDUpCgpkZk5vR2xhc3NlcyA8LSBkZkdsYXNzZXMgJT4lCiAgZmlsdGVyKFdFQVJHTFNTX0EgPT0gJzInKQoKZGZXZWFyR2xhc3NlcyA8LSBkZkdsYXNzZXMgJT4lCiAgZmlsdGVyKFdFQVJHTFNTX0E9PSAnMScgKQoKV2VhckdsYXNzZXMgPC0gZGF0YS5mcmFtZSggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICBTdGF0dXMgID0gYygxLCAyKSwgICAgICAgCiAgIEdlbl9IZWFsdGg9IGMobWVhbihkZldlYXJHbGFzc2VzJFBIU1RBVF9BKSwgbWVhbihkZk5vR2xhc3NlcyRQSFNUQVRfQSkpKQoKCmdncGxvdChXZWFyR2xhc3NlcywgYWVzKHggPSBmYWN0b3IoU3RhdHVzKSwgeSA9IEdlbl9IZWFsdGgpKSArIAogIGdlb21fcG9pbnQoKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9IGMoIldlYXIgR2xhc3Nlcy9Db250YWN0cyIsICJObyBHbGFzc2VzL0NvbnRhY3RzIikpICsKICB4bGFiKCIiKSsKICB5bGFiKCJBdmVyYWdlIFBoeXNpY2FsIEhlYWx0aCIpCmBgYAoKYGBge3J9CmRmVmlzaW9uIDwtIGRmRmlsdGVyZWRWaXMgJT4lCiAgZmlsdGVyKFBIU1RBVF9BIDwgNSkKCmRmTm9uZVZpcyA8LSBkZlZpc2lvbiAlPiUKICBmaWx0ZXIoVklTSU9OREZfQSA9PSAnMScpCgpkZlNvbWVWaXMgPC0gZGZWaXNpb24gJT4lCiAgZmlsdGVyKFZJU0lPTkRGX0E9PSAnMicgKQoKZGZBbG90VmlzIDwtIGRmVmlzaW9uICU+JQogIGZpbHRlcihWSVNJT05ERl9BPT0gJzMnICkKCmRmQ2Fubm90VmlzIDwtIGRmVmlzaW9uICU+JQogIGZpbHRlcihWSVNJT05ERl9BPT0gJzQnICkKClZpc0RpZmZpY3VsdHkgPC0gZGF0YS5mcmFtZSggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICBTdGF0dXMgID0gYygxLCAyLDMsNCksICAgICAgIAogICBHZW5fSGVhbHRoPSBjKG1lYW4oZGZOb25lVmlzJFBIU1RBVF9BKSwgbWVhbihkZlNvbWVWaXMkUEhTVEFUX0EpLCBtZWFuKGRmQWxvdFZpcyRQSFNUQVRfQSksIG1lYW4oZGZDYW5ub3RWaXMkUEhTVEFUX0EpKSkKCgpnZ3Bsb3QoVmlzRGlmZmljdWx0eSwgYWVzKHggPSBmYWN0b3IoU3RhdHVzKSwgeSA9IEdlbl9IZWFsdGgpKSArIAogIGdlb21fcG9pbnQoKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9IGMoIk5vbmUiLCAiU29tZSIsICJBIExvdCIsIkNhbm5vdCBTZWUiKSkgKwogIHhsYWIoIkRpZmZpY3VsdHkgU2VlaW5nIikgKwogIHlsYWIoIkF2ZXJhZ2UgUGh5c2ljYWwgSGVhbHRoIikKYGBgCgojIyMgVmlzaW9uIHZzIExpZmUgU2F0aXNmYWN0aW9uCgpgYGB7cn0KZGZHbGFzc2VzTFMgPC0gYWR1bHQyMiAlPiUKICBmaWx0ZXIoTFNBVElTNF9BIDwgNykKCmRmTm9HbGFzc2VzTFMgPC0gZGZHbGFzc2VzTFMgJT4lCiAgZmlsdGVyKFdFQVJHTFNTX0EgPT0gJzInKQoKZGZXZWFyR2xhc3Nlc0xTIDwtIGRmR2xhc3Nlc0xTICU+JQogIGZpbHRlcihXRUFSR0xTU19BPT0gJzEnICkKCldlYXJHbGFzc2VzTFMgPC0gZGF0YS5mcmFtZSggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICBTdGF0dXMgID0gYygxLCAyKSwgICAgICAgCiAgIExpZmVfU2F0aXM9IGMobWVhbihkZldlYXJHbGFzc2VzTFMkTFNBVElTNF9BKSwgbWVhbihkZk5vR2xhc3Nlc0xTJExTQVRJUzRfQSkpKQoKCmdncGxvdChXZWFyR2xhc3Nlc0xTLCBhZXMoeCA9IGZhY3RvcihTdGF0dXMpLCB5ID0gTGlmZV9TYXRpcykpICsgCiAgZ2VvbV9wb2ludCgpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscz0gYygiV2VhciBHbGFzc2VzL0NvbnRhY3RzIiwgIk5vIEdsYXNzZXMvQ29udGFjdHMiKSkgKwogIHhsYWIoIiIpKwogIHlsYWIoIkF2ZXJhZ2UgTGlmZSBTYXRpc2ZhY3Rpb24iKQpgYGAKCiMjIyBEaWZmaWN1bHR5IFNlZWluZyBhbmQgTGlmZSBTYXRpc2ZhY3Rpb24KCmBgYHtyfQpkZlZpc2lvbkxTIDwtIGRmRmlsdGVyZWRWaXMgJT4lCiAgZmlsdGVyKExTQVRJUzRfQSA8IDcpCgpkZk5vbmVWaXNMUyA8LSBkZlZpc2lvbkxTICU+JQogIGZpbHRlcihWSVNJT05ERl9BID09ICcxJykKCmRmU29tZVZpc0xTIDwtIGRmVmlzaW9uTFMgJT4lCiAgZmlsdGVyKFZJU0lPTkRGX0E9PSAnMicgKQoKZGZBbG90VmlzTFMgPC0gZGZWaXNpb25MUyAlPiUKICBmaWx0ZXIoVklTSU9OREZfQT09ICczJyApCgpkZkNhbm5vdFZpc0xTIDwtIGRmVmlzaW9uTFMgJT4lCiAgZmlsdGVyKFZJU0lPTkRGX0E9PSAnNCcgKQoKVmlzRGlmZmljdWx0eUxTIDwtIGRhdGEuZnJhbWUoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgU3RhdHVzICA9IGMoMSwgMiwzLDQpLCAgICAgICAKICAgTGlmZV9TYXRpcz0gYyhtZWFuKGRmTm9uZVZpc0xTJExTQVRJUzRfQSksIG1lYW4oZGZTb21lVmlzTFMkTFNBVElTNF9BKSwgbWVhbihkZkFsb3RWaXNMUyRMU0FUSVM0X0EpLCBtZWFuKGRmQ2Fubm90VmlzTFMkTFNBVElTNF9BKSkpCgoKZ2dwbG90KFZpc0RpZmZpY3VsdHlMUywgYWVzKHggPSBmYWN0b3IoU3RhdHVzKSwgeSA9IExpZmVfU2F0aXMpKSArIAogIGdlb21fcG9pbnQoKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9IGMoIk5vbmUiLCAiU29tZSIsICJBIExvdCIsIkNhbm5vdCBTZWUiKSkgKwogIHhsYWIoIkRpZmZpY3VsdHkgU2VlaW5nIikgKwogIHlsYWIoIkF2ZXJhZ2UgTGlmZSBTYXRpc2ZhY3Rpb24iKQpgYGAKCkZvciBib3RoIHBoeXNpY2FsIGhlYWx0aCBhbmQgbGlmZSBzYXRpc2ZhY3Rpb24sIHRoZXJlIHdhcyBhIGRlY3JlYXNlIGZvcgp0aG9zZSB3aG8gd2VhciBnbGFzc2VzL2NvbnRhY3RzLiBTaW5jZSBwZW9wbGUgY2FuIGJlIHNwbGl0IGludG8gcG9zaXRpdmUKYW5kIG5lZ2F0aXZlIGxpZmUgc2F0aXNmYWN0aW9uLCB3ZSBjYW4gdHJ5IGEgYmluYXJ5IHJlc3BvbnNlLgoKYGBge3J9CmRmVmlzaW9uQWxsIDwtIGRmRmlsdGVyZWRWaXMgJT4lCiAgZmlsdGVyKFdFQVJHTFNTX0E8ICczJyApCgpkZlZpc2lvbkFsbExTIDwtCiAgZGZWaXNpb25BbGwgfD4KICAgIGdyb3VwX2J5KGRmVmlzaW9uQWxsJExTQVRJUzRfQSkgfD4KICAgIG11dGF0ZShMaWZlU2F0aXNfU3RhdHVzID0gaWZlbHNlKExTQVRJUzRfQSA9PSAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShMU0FUSVM0X0EgPT0gMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMSkpKSB8PiAKICB1bmdyb3VwKCkKCm1vZGVsIDwtIGdsbShMaWZlU2F0aXNfU3RhdHVzIH4gVklTSU9OREZfQSwgZGF0YSA9IGRmVmlzaW9uQWxsTFMsCiAgICAgICAgICAgICBmYW1pbHkgPSBiaW5vbWlhbChsaW5rID0gJ2xvZ2l0JykpCgptb2RlbCRjb2VmZmljaWVudHMKCgoKYGBgCgpgYGB7cn0Kc2lnbW9pZCA8LSBcKHgpIDEgLyAoMSArIGV4cCgtKC00LjMyNTczNSArIDEuMDA0OTI3ICogeCkpKQoKZGZWaXNpb25BbGxMUyB8PgogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBWSVNJT05ERl9BLCB5ID0gTGlmZVNhdGlzX1N0YXR1cykpICsKICBnZW9tX2ppdHRlcih3aWR0aCA9IDAsIGhlaWdodCA9IDAuMSwgc2hhcGUgPSAnTycsIHNpemUgPSAzKSArCiAgZ2VvbV9mdW5jdGlvbihmdW4gPSBzaWdtb2lkLCBjb2xvciA9ICdibHVlJywgbGluZXdpZHRoID0gMSkgKwogIGxhYnModGl0bGUgPSAiTGlmZSBTYXRpc2ZhY3Rpb24gQmluYXJ5IFJlc3BvbnNlIC0gRGlmZmljdWx0eSBTZWVpbmciKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoMCwgMSkpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgpCZXR3ZWVuIFBvc2l0aXZlIExpZmUgU2F0aXNmYWN0aW9uKDApIGFuZCBOZWdhdGl2ZSBMaWZlIFNhdGlzZmFjdGlvbigxKS4KV2UgY2FuIHNlZSB0aGF0IHRoZXJlIGlzIGEgc21hbGwgaW5jcmVhc2UgaW4gcHJvYmFiaWxpdHkgdGhhdCBhcwpzb21lb25lJ3MgdmlzaW9uIGdldHMgd29yc3QsIHRoZSBsaWZlIHNhdGlzZmFjdGlvbiB3aWxsIGJlY29tZSBtb3JlCm5lZ2F0aXZlLgoKIyBTbW9raW5nCgojIyMgU21va2luZywgTGlmZSBTYXRpc2ZhY3Rpb24sIGFuZCBHZW5lcmFsIEhlYWx0aAoKMS4gIEN1cnJlbnQsIGV2ZXJ5IGRheSBzbW9rZXIKMi4gIEN1cnJlbnQsIHNvbWUgZGF5cyBzbW9rZXIKMy4gIEZvcm1lciBzbW9rZXIKNC4gIE5vbi1TbW9rZXIKCmBgYHtyfQoKZGZGaWx0ZXJlZExTU21va2UgPC0gZGZGaWx0ZXJlZExTICU+JQogIGZpbHRlcihTTUtDSUdTVF9BIDwgNSkKCgpkZkZpbHRlcmVkTFNTbW9rZSB8PgogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBTTUtDSUdTVF9BLCB5ID0gTFNBVElTNF9BKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICdkYXJrYmx1ZScpICsgCiAgdGhlbWVfbWluaW1hbCgpICsgeGxhYigiU21va2luZyBTdGF0dXMiKSArIHlsYWIoIkxpZmUgU2F0aXNmYWN0aW9uIikKICAKCmRmRmlsdGVyZWRQSFNtb2tlIDwtIGRmR0hGaWx0ZXIgJT4lCiAgZmlsdGVyKFNNS0NJR1NUX0EgPCA1KQoKCmRmRmlsdGVyZWRQSFNtb2tlIHw+CiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeCA9IFNNS0NJR1NUX0EsIHkgPSBQSFNUQVRfQSkpICsKICBnZW9tX3BvaW50KHNpemUgPSAyKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAnZGFya2JsdWUnKSArIAogIHRoZW1lX21pbmltYWwoKSArIHhsYWIoIlNtb2tpbmcgU3RhdHVzIikgKyB5bGFiKCJHZW5lcmFsIEhlYWx0aCIpCgoKYGBgCgpUaGVyZSBpcyBhIGJpdCBvZiBhIGRlY3JlYXNlIGluIGxpZmUgc2F0aXNmYWN0aW9uIGFuZCBnZW5lcmFsIGhlYWx0aCB0aGUKbW9yZSBzb21lb25lIHNtb2tlcy4KCiMjIyBTbW9raW5nIGFuZCBMdW5nIENhbmNlciAtIEJpbmFyeSBSZXNwb25zZQoKV2UgY2FuIHNwbGl0IHBlb3BsZSB1cCBpbnRvIHNvbWVvbmUgd2hvIGhhcyBzbW9rZWQgYW5kIHNvbWVvbmUgd2hvIGhhcwpub3Qgc21va2VkLCBzbyB3ZSBjYW4gdHJ5IGEgYmluYXJ5IHJlc3BvbnNlLgoKYGBge3J9CgpkZlNtb2tlQ2FuIDwtIGFkdWx0MjIgJT4lCiAgZmlsdGVyKFNNS0NJR1NUX0EgPCA1ICYgTFVOR0NBTl9BIDwzKQoKZGZTbW9rZUNhbiA8LQogIGRmU21va2VDYW4gfD4KICAgIGdyb3VwX2J5KGRmU21va2VDYW4kU01LQ0lHU1RfQSkgfD4KICAgIG11dGF0ZShTbW9rZSA9IGlmZWxzZShTTUtDSUdTVF9BID09ICI0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxKSkgfD4gCiAgdW5ncm91cCgpCgptb2RlbCA8LSBnbG0oU21va2UgfiBMVU5HQ0FOX0EsIGRhdGEgPSBkZlNtb2tlQ2FuLAogICAgICAgICAgICAgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICdsb2dpdCcpKQoKbW9kZWwkY29lZmZpY2llbnRzCgpgYGAKCmBgYHtyfQpzaWdtb2lkIDwtIFwoeCkgMSAvICgxICsgZXhwKC0oMy4yNjQ1MDcgLTEuNzU1MTUzICogeCkpKQoKZGZTbW9rZUNhbiB8PgogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBMVU5HQ0FOX0EsIHkgPSBTbW9rZSkpICsKICBnZW9tX2ppdHRlcih3aWR0aCA9IDAsIGhlaWdodCA9IDAuMSwgc2hhcGUgPSAnTycsIHNpemUgPSAzKSArCiAgZ2VvbV9mdW5jdGlvbihmdW4gPSBzaWdtb2lkLCBjb2xvciA9ICdibHVlJywgbGluZXdpZHRoID0gMSkgKwogIGxhYnModGl0bGUgPSAiQmluYXJ5IFJlc3BvbnNlOiBMdW5nIENhbmNlciBhbmQgU21va2luZyIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygwLCAxKSkgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKClRoaXMgZ3JhcGggc2hvd3MgdGhhdCBmb3IgdGhvc2Ugd2hvIGhhdmUgbHVuZyBjYW5jZXIgKDEpLCB0aGVyZSBpcyBhCmhpZ2hlciBwcm9iYWJpbGl0eSBvZiB0aGVtIGJlaW5nIGEgc21va2VyIG9yIGZvcm1lciBzbW9rZXIoMSkuCgojIyMgMTAwIENpZ2FyZXR0ZXMgU21va2VkIGFuZCBMdW5nIENhbmNlciAtIEJpbmFyeSBSZXNwb25zZQoKV2UgY2FuIGFsc28gc3BsaXQgdGhlIHNtb2tlcnMgdXAgaW50byB0aG9zZSB3aG8gaGF2ZSBzbW9rZWQgMTAwCmNpZ2FyZXR0ZXMsIGFuZCB0aG9zZSB3aG8gaGF2ZSBub3QuCgpgYGB7cn0KZGZTbW9rZTEwMCA8LSBhZHVsdDIyICU+JQogIGZpbHRlcihTTUtFVl9BIDwgMyAmIExVTkdDQU5fQSA8MykKCmRmU21va2UxMDBDYW4gPC0KICBkZlNtb2tlMTAwIHw+CiAgICBncm91cF9ieShkZlNtb2tlMTAwJFNNS0VWX0EpIHw+CiAgICBtdXRhdGUoU21va2VfMTAwID0gaWZlbHNlKFNNS0VWX0EgPT0gIjIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEpKSB8PiAKICB1bmdyb3VwKCkKCm1vZGVsIDwtIGdsbShTbW9rZV8xMDAgfiBMVU5HQ0FOX0EsIGRhdGEgPSBkZlNtb2tlMTAwQ2FuLAogICAgICAgICAgICAgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICdsb2dpdCcpKQoKbW9kZWwkY29lZmZpY2llbnRzCgpgYGAKCmBgYHtyfQpzaWdtb2lkIDwtIFwoeCkgMSAvICgxICsgZXhwKC0oMy4yNjMwOTQgLTEuNzUzNzQwICogeCkpKQoKZGZTbW9rZTEwMENhbiB8PgogIGdncGxvdChtYXBwaW5nID0gYWVzKHggPSBMVU5HQ0FOX0EsIHkgPSBTbW9rZV8xMDApKSArCiAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLCBoZWlnaHQgPSAwLjEsIHNoYXBlID0gJ08nLCBzaXplID0gMykgKwogIGdlb21fZnVuY3Rpb24oZnVuID0gc2lnbW9pZCwgY29sb3IgPSAnYmx1ZScsIGxpbmV3aWR0aCA9IDEpICsKICBsYWJzKHRpdGxlID0gIkJpbmFyeSBSZXNwb25zZTogTHVuZyBDYW5jZXIgYW5kIFNtb2tlZCAxMDAgQ2lnYXJldHRlcyIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygwLCAxKSkgKwogIHRoZW1lX21pbmltYWwoKQoKYGBgCgpUaGlzIGdyYXBoIHNob3dzIHRoYXQgZm9yIHRob3NlIHdobyBoYXZlIGx1bmcgY2FuY2VyICgxKSwgdGhlcmUgaXMgYQpoaWdoZXIgcHJvYmFiaWxpdHkgb2YgdGhlbSBoYXZpbmcgc21va2VkIDEwMCBjaWdhcmV0dGVzKDEpLiBUaGUgbW9kZWwgaXMKZXh0cmVtZWx5IGNsb3NlIHRvIHRoZSBwcmV2aW91cyBtb2RlbC4gU28sIGhvdyBtYW55IG9mIHRoZSBzbW9rZXJzIHdpdGgKbHVuZyBjYW5jZXIgc21va2VkIDEwMCBjaWdhcmV0dGVzPwoKYGBge3J9Ckx1bmdDYW4gPC0gbnJvdyhkZlNtb2tlMTAwW2RmU21va2UxMDAkTFVOR0NBTl9BID09ICcxJyxdKQpTbW9rZWQxMDAgPC0gbnJvdyhkZlNtb2tlMTAwW2RmU21va2UxMDAkU01LRVZfQSA9PSAnMScsXSkKU21va2VkMTAwQ2FuIDwtIG5yb3coZGZTbW9rZTEwMFtkZlNtb2tlMTAwJFNNS0VWX0EgPT0gJzEnICYgZGZTbW9rZTEwMCRMVU5HQ0FOX0EgPT0gJzEnLCBdKQpOb3RTbW9rZWQxMDBDYW4gPC0gbnJvdyhkZlNtb2tlMTAwW2RmU21va2UxMDAkU01LRVZfQSA9PSAnMicgJiBkZlNtb2tlMTAwJExVTkdDQU5fQSA9PSAnMScsIF0pCgpMdW5nQ2FuClNtb2tlZDEwMENhbgo5NS8xMTYqMTAwClNtb2tlZDEwMApOb3RTbW9rZWQxMDBDYW4KOTUvMTUxMSoxMDAKYGBgCgpPdXQgb2YgMTE2IHBlb3BsZSB3aG8gc3RhdGVkIHRoZXkgaGF2ZSBsdW5nIGNhbmNlciwgOTUgcGVvcGxlLCBvciA4MS45JQpoYWQgc21va2VkIGF0IGxlYXN0IDEwMCBjaWdhcmV0dGVzLiBCdXQgb3V0IG9mIDE1MTEgcGVvcGxlIHdobyBoYXZlCnNtb2tlZCBhdCBsZWFzdCAxMDAgY2lnYXJldHRlcywgb25seSAyMSwgb3IgNi4zJSBoYXZlIGx1bmcgY2FuY2VyLgoKIyBDb3ZpZAoKTW9udGggb2YgbGFzdCBDb3ZpZCB2YWNjaW5lIGZvciB0aG9zZSB3aG8gZ290IGl0IGZvciB0aGUgZmlyc3QgdGltZS4KCmBgYHtyfQpmQ292aWRWYXggPC0gYWR1bHQyMgoKZGZDb3ZpZFZheEZpcnN0IDwtIGRmQ292aWRWYXggJT4lCiAgZmlsdGVyKENWRFZBQzFNX0EgIT0gJ05BJyAmIENWRFZBQzFZX0EgIT0nTkEnKQoKZGZDb3ZpZFZheExhc3QgPC0gZGZDb3ZpZFZheCAlPiUKICBmaWx0ZXIoQ1ZEVkFDMk1fQSAhPSAnTkEnICYgQ1ZEVkFDMllfQSAhPSdOQScpCgpkZkNvdmlkVmF4Rmlyc3QkTGFzdENvdmlkVmF4Rmlyc3RUaW1lIDwtIHdpdGgoZGZDb3ZpZFZheEZpcnN0LCBzcHJpbnRmKCIlZC0wMS0lMDJkIiwgQ1ZEVkFDMU1fQSwgQ1ZEVkFDMVlfQSkpCgpkZkNvdmlkVmF4TGFzdCRMYXN0Q292aWRWYXhOb3RGaXJzdFRpbWUgPC0gd2l0aChkZkNvdmlkVmF4TGFzdCwgc3ByaW50ZigiJWQtMDEtJTAyZCIsIENWRFZBQzJNX0EsIENWRFZBQzJZX0EpKQoKZGZDb3ZpZFZheEZpcnN0XyA8LSBkZkNvdmlkVmF4Rmlyc3QgJT4lCiAgZmlsdGVyKENWRERJQUdfQSA8IDMpCgpkZkNvdmlkVmF4TGFzdF8gPC0gZGZDb3ZpZFZheExhc3QgJT4lCiAgZmlsdGVyKENWRERJQUdfQSA8IDMpCgpkZkNvdmlkVmF4Rmlyc3QxIDwtIGRmQ292aWRWYXhGaXJzdF8gfD4KICBzZWxlY3QoTGFzdENvdmlkVmF4Rmlyc3RUaW1lLCBDVkRESUFHX0EpCgpkZkNvdmlkVmF4TGFzdDEgPC0gZGZDb3ZpZFZheExhc3RfIHw+CiAgc2VsZWN0KExhc3RDb3ZpZFZheE5vdEZpcnN0VGltZSwgQ1ZERElBR19BKQoKZGZ0cmFuc2YgPC0gZGZDb3ZpZFZheEZpcnN0MSB8PgogIHNlbGVjdChMYXN0Q292aWRWYXhGaXJzdFRpbWUsIENWRERJQUdfQSkKCmRmdHJhbnNmWydkYXRlJ108LSBhcy5EYXRlKGRmdHJhbnNmJExhc3RDb3ZpZFZheEZpcnN0VGltZSwgZm9ybWF0PSIlbS0lZC0lWSIpCgpkZnRyYW5zZmlsdCA8LSBkZnRyYW5zZiAlPiUgZmlsdGVyKCFpcy5uYShkYXRlKSkKCmRmRmlyc3RWIDwtIGRmdHJhbnNmaWx0IHw+CiAgc2VsZWN0KGRhdGUsIENWRERJQUdfQSkKCmRmZmlyc3RWQ291bnQ8LSBkZkZpcnN0ViAlPiUgZ3JvdXBfYnkoZGF0ZSkgJT4ldGFsbHkoKSAKCmRmTWVyZ2UgPC0gbWVyZ2UoZGZmaXJzdFZDb3VudCwgZGZGaXJzdFZTdW0sIGJ5ID0gImRhdGUiLCBhbGwueD1UUlVFLCBhbGwueT1UUlVFKQoKZGZNZXJnZVsncGVyY2VudCddID0gZGZNZXJnZVsnRnJlcXVlbmN5J10vZGZNZXJnZVsnbiddCgpkZk1lcmdlIDwtIGRmTWVyZ2UgJT4lIGZpbHRlcihwZXJjZW50ID4uMDAwMDAwMSkKCmBgYAoKYGBge3J9CmRmTWVyZ2UgfD4KICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gZGF0ZSwgeSA9IG4pKSArCiAgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSAiRGF0ZSBvZiBGaXJzdCBDb3ZpZCBWYWNjaW5lIikgKwogIHRoZW1lX2hjKCkgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2xhYmVscyA9ICIlWSAoJWIpIikgKyB5bGFiKCJOdW1iZXIgb2YgUGVvcGxlIikKCmBgYAoKVGhlIGZpcnN0IHZhY2NpbmUgY2FtZSBvdXQgaW4gRGVjIDIwMjEsIHdoaWNoIGlzIGFyb3VuZCB3aGVyZSB0aGUgZ3JhcGgKc3RhcnRzIHRvIGluY3JlYXNlLiBUaGVyZSB3YXMgYW4gaW5jcmVhc2UgaW4gQXByaWwgYW5kIE1heSAyMDIxLiBJbiBKdW5lCjIwMjEgd2hlbiBpdCBzdGFydGVkIHRvIGRlY3JlYXNlLCB0aGVyZSB3YXMgYSBzbG93ZG93biBpbiBwZW9wbGUgZ2V0dGluZwp0aGUgdmFjY2luZSBhbmQgYSByZWNvcmQgbG93IG51bWJlciBvZiBjYXNlcy4KClNvdXJjZToKPGh0dHBzOi8vd3d3LmtmZi5vcmcvY29yb25hdmlydXMtY292aWQtMTkvcG9sbC1maW5kaW5nL2tmZi1jb3ZpZC0xOS12YWNjaW5lLW1vbml0b3ItanVuZS0yMDIxLz4KCk9uIFNlcHRlbWJlciA5IDIwMjEsIEJpZGVuIG1hZGUgYW4gYW5ub3VuY2VtZW50IHJlcXVpcmluZyBmZWRlcmFsCmVtcGxveWVlcyB0byBiZSB2YWNjaW5hdGVkIGJ5IHRoZSBlbmQgb2YgSmFudWFyeSAyMDIyLCB3aGljaCBpcyBhcm91bmQKdGhlIHRpbWUgb2YgdGhlIGxhcmdlc3QgcGVhayBiZXR3ZWVuIFNlcHQgMjAyMSBhbmQgSmFudWFyeSAyMDIyLgoKU291cmNlOgo8aHR0cHM6Ly93d3cud2hpdGVob3VzZS5nb3YvYnJpZWZpbmctcm9vbS9wcmVzaWRlbnRpYWwtYWN0aW9ucy8yMDIxLzA5LzA5L2V4ZWN1dGl2ZS1vcmRlci1vbi1yZXF1aXJpbmctY29yb25hdmlydXMtZGlzZWFzZS0yMDE5LXZhY2NpbmF0aW9uLWZvci1mZWRlcmFsLWVtcGxveWVlcy8+CgojIENhbmNlcgoKIyMjIENhbmNlciBieSBTZXgKCiMjIyMgVG9sZCBoYXMgY2FuY2VyLgoKYGBge3J9CgpkZkZlbWFsZSA9IGFkdWx0MjIgJT4lCiAgZmlsdGVyKFNFWF9BID09IDIpCgpkZkZlbWFsZUNhbiA9IGRmRmVtYWxlICU+JQogIGZpbHRlcihDQU5FVl9BID09IDEpCgpkZk1hbGUgPSBhZHVsdDIyICU+JQogIGZpbHRlcihTRVhfQSA9PSAxKQoKZGZNYWxlQ2FuID0gZGZNYWxlICU+JQogIGZpbHRlcihDQU5FVl9BID09IDEpCgpUb3RhbEYgPC0gbnJvdyhkZkZlbWFsZSkKVG90YWxNIDwtIG5yb3coZGZNYWxlKQpQZXJjZW50RiA8LSAobnJvdyhkZkZlbWFsZUNhbikvbnJvdyhkZkZlbWFsZSkpKjEwMApQZXJjZW50TSA8LSAobnJvdyhkZk1hbGVDYW4pL25yb3coZGZNYWxlKSkqMTAwCgpQZXJjZW50Q2FuIDwtIGRhdGEuZnJhbWUoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgU2V4ICA9IGMoIkZlbWFsZSIsICJNYWxlIiksICAgICAgIAogICBQZXJjZW50PSBjKChQZXJjZW50RiksIChQZXJjZW50TSkpKQoKZ2dwbG90KFBlcmNlbnRDYW4sIGFlcyh4ID0gU2V4LCB5PVBlcmNlbnQpKSArCiAgZ2VvbV9wb2ludCgpCmBgYAoKIyMjIyBQZXJjZW50IGJ5IFR5cGUgb2YgQ2FuY2VyCgpgYGB7cn0KZGZDYW4gPC0gYWR1bHQyMiAlPiUKICBmaWx0ZXIoTlVNQ0FOX0EgPCA3ICYgTlVNQ0FOX0EgIT0wKQoKZGZCbGFkIDwtIGRmQ2FuICU+JQogIGZpbHRlcihCTEFERENBTl9BID09IDEpCgpkZkJsb29kIDwtIGRmQ2FuICU+JQogIGZpbHRlcihCTE9PRENBTl9BID09IDEpCgpkZkJyYWluIDwtIGRmQ2FuICU+JQogIGZpbHRlcihCUkFJTkNBTl9BID09IDEpCgpkZkJvbmUgPC0gZGZDYW4gJT4lCiAgZmlsdGVyKEJPTkVDQU5fQSA9PSAxKQoKZGZCcmVhc3QgPC0gZGZDYW4gJT4lCiAgZmlsdGVyKEJSRUFTQ0FOX0EgPT0gMSkKCmRmQ2VydmljYWwgPC0gZGZDYW4gJT4lCiAgZmlsdGVyKENFUlZJQ0FOX0EgPT0gMSkKCmRmRXNvcGggPC0gZGZDYW4gJT4lCiAgZmlsdGVyKEJMQUREQ0FOX0EgPT0gMSkKCmRmR2FsbCA8LSBkZkNhbiAlPiUKICBmaWx0ZXIoRVNPUEhDQU5fQSA9PSAxKQoKZGZMYXJ5bnggPC0gZGZDYW4gJT4lCiAgZmlsdGVyKExBUllOQ0FOX0EgPT0gMSkKCmRmTGV1ayA8LSBkZkNhbiAlPiUKICBmaWx0ZXIoTEVVS0VDQU5fQSA9PSAxKQoKZGZMaXZlciA8LSBkZkNhbiAlPiUKICBmaWx0ZXIoTElWRVJDQU5fQSA9PSAxKQoKZGZMdW5nIDwtIGRmQ2FuICU+JQogIGZpbHRlcihMVU5HQ0FOX0EgPT0gMSkKCmRmTHltcGggPC0gZGZDYW4gJT4lCiAgZmlsdGVyKExZTVBIQ0FOX0EgPT0gMSkKCmRmTWVsYSA8LSBkZkNhbiAlPiUKICBmaWx0ZXIoTUVMQU5DQU5fQSA9PSAxKQoKZGZNb3V0aCA8LSBkZkNhbiAlPiUKICBmaWx0ZXIoTU9VVEhDQU5fQSA9PSAxKQoKZGZPdmFyeSA8LSBkZkNhbiAlPiUKICBmaWx0ZXIoT1ZBUllDQU5fQSA9PSAxKQoKZGZQYW5jIDwtIGRmQ2FuICU+JQogIGZpbHRlcihQQU5DUkNBTl9BPT0gMSkKCmRmUHJvc3QgPC0gZGZDYW4gJT4lCiAgZmlsdGVyKFBST1NUQ0FOX0EgPT0gMSkKCmRmU2tpbk1lbGEgPC0gZGZDYW4gJT4lCiAgZmlsdGVyKFNLTk1DQU5fQSA9PSAxKQoKZGZTa2luTm9NZWxhIDwtIGRmQ2FuICU+JQogIGZpbHRlcihTS05OTUNBTl9BID09IDEpCgpkZlNraW5Vbmtub3duIDwtIGRmQ2FuICU+JQogIGZpbHRlcihTS05ES0NBTl9BID09IDEpCgpkZlN0b21hY2ggPC0gZGZDYW4gJT4lCiAgZmlsdGVyKFNUT01BQ0FOX0EgPT0gMSkKCmRmVGhyb2F0IDwtIGRmQ2FuICU+JQogIGZpbHRlcihUSFJPQUNBTl9BID09IDEpCgpkZlRoeXJvaWQgPC0gZGZDYW4gJT4lCiAgZmlsdGVyKFRIWVJPQ0FOX0EgPT0gMSkKCmRmVXRlcnVzIDwtIGRmQ2FuICU+JQogIGZpbHRlcihVVEVSVUNBTl9BID09IDEpCgpkZkhhbmROZWNrIDwtIGRmQ2FuICU+JQogIGZpbHRlcihIRE5DS0NBTl9BID09IDEpCgpkZkNvbFJlYyA8LSBkZkNhbiAlPiUKICBmaWx0ZXIoQ09MUkNDQU5fQSA9PSAxKQoKZGZPdGhlciA8LSBkZkNhbiAlPiUKICBmaWx0ZXIoT1RIRVJDQU5QX0EgPT0gMSkKCmBgYAoKYGBge3J9ClRCbGFkRiA8LSBucm93KGRmQmxhZCAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMikpL1RvdGFsRioxMDAKVEJsb29kRiA8LSBucm93KGRmQmxvb2QgJT4lCiAgZmlsdGVyKFNFWF9BID09IDIpKS9Ub3RhbEYqMTAwClRCb25lRiA8LSBucm93KGRmQm9uZSAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMikpL1RvdGFsRioxMDAKVEJyYWluRiA8LSBucm93KGRmQnJhaW4gJT4lCiAgZmlsdGVyKFNFWF9BID09IDIpKS9Ub3RhbEYqMTAwClRCcmVhc3RGIDwtIG5yb3coZGZCcmVhc3QgJT4lCiAgZmlsdGVyKFNFWF9BID09IDIpKS9Ub3RhbEYqMTAwClRFc29waEYgPC0gbnJvdyhkZkVzb3BoICU+JQogIGZpbHRlcihTRVhfQSA9PSAyKSkvVG90YWxGKjEwMApUQ2VydkYgPC0gbnJvdyhkZkNlcnZpY2FsICU+JQogIGZpbHRlcihTRVhfQSA9PSAyKSkvVG90YWxGKjEwMApUR2FsbEYgPC0gbnJvdyhkZkdhbGwgJT4lCiAgZmlsdGVyKFNFWF9BID09IDIpKS9Ub3RhbEYqMTAwClRMYXJ5bnhGIDwtIG5yb3coZGZMYXJ5bnggJT4lCiAgZmlsdGVyKFNFWF9BID09IDIpKS9Ub3RhbEYqMTAwClRMZXVrRiA8LSBucm93KGRmTGV1ayAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMikpL1RvdGFsRioxMDAKVEx1bmdGIDwtIG5yb3coZGZMdW5nICU+JQogIGZpbHRlcihTRVhfQSA9PSAyKSkvVG90YWxGKjEwMApUTGl2ZXJGIDwtIG5yb3coZGZMaXZlciAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMikpL1RvdGFsRioxMDAKVE1lbGFGIDwtIG5yb3coZGZNZWxhICU+JQogIGZpbHRlcihTRVhfQSA9PSAyKSkvVG90YWxGKjEwMApUTW91dGhGIDwtIG5yb3coZGZNb3V0aCAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMikpL1RvdGFsRioxMDAKVE92YXJ5RiA8LSBucm93KGRmT3ZhcnkgJT4lCiAgZmlsdGVyKFNFWF9BID09IDIpKS9Ub3RhbEYqMTAwClRQYW5jRiA8LSBucm93KGRmQmxhZCAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMikpL1RvdGFsRioxMDAKVFNraW5NZWxhRiA8LSBucm93KGRmU2tpbk1lbGEgJT4lCiAgZmlsdGVyKFNFWF9BID09IDIpKS9Ub3RhbEYqMTAwClRTa2luTm9NZWxhRiA8LSBucm93KGRmU2tpbk5vTWVsYSAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMikpL1RvdGFsRioxMDAKVFNraW5Vbmtub3duRiA8LSBucm93KGRmU2tpblVua25vd24gJT4lCiAgZmlsdGVyKFNFWF9BID09IDIpKS9Ub3RhbEYqMTAwClRTdG9tYWNoRiA8LSBucm93KGRmU3RvbWFjaCAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMikpL1RvdGFsRioxMDAKVFRoeXJvaWRGIDwtIG5yb3coZGZUaHlyb2lkICU+JQogIGZpbHRlcihTRVhfQSA9PSAyKSkvVG90YWxGKjEwMApUVGhyb2F0RiA8LSBucm93KGRmVGhyb2F0ICU+JQogIGZpbHRlcihTRVhfQSA9PSAyKSkvVG90YWxGKjEwMApUVXRlcnVzRiA8LSBucm93KGRmVXRlcnVzICU+JQogIGZpbHRlcihTRVhfQSA9PSAyKSkvVG90YWxGKjEwMApUSGFuZE5lY2tGIDwtIG5yb3coZGZIYW5kTmVjayAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMikpL1RvdGFsRioxMDAKVENvbFJlY0YgPC0gbnJvdyhkZkNvbFJlYyAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMikpL1RvdGFsRioxMDAKVE90aGVyRiA8LSBucm93KGRmT3RoZXIgJT4lCiAgZmlsdGVyKFNFWF9BID09IDIpKS9Ub3RhbEYqMTAwCmBgYAoKIyMjIyMgQ2FuY2VyIEFtb25nIEZlbWFsZXMKCmBgYHtyfQpDYW5jZXJGIDwtIGRhdGEuZnJhbWUoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgQ2FuY2VyICA9IGMoIkJsYWRkZXIiLCAiQmxvb2QiLCJCcmFpbiIsIkJvbmUiLCJCcmVhc3QiLCJFc29waGFndXMiLCJDZXJ2aWNhbCIsIkdhbGxCbGFkZGVyIiwiTGFyeW54IiwiTGV1a2VtaWEiLCJMdW5nIiwiTGl2ZXIiLCJNZWxhbm9tYSIsIk1vdXRoIiwiT3ZhcmlhbiIsIlBhbmNyZWFzIiwiU2tpbiBNZWxhbm9tYSIsIlNraW4tTm90IE1lbGFub21hIiwiU2tpbi1Vbmtub3duIiwiU3RvbWFjaCIsIlRoeXJvaWQiLCJUaHJvYXQiLCJVdGVydXMiLCJIYW5kIGFuZCBOZWNrIiwiQ29sb25SZWN0YWwiLCJPdGhlciIpLCAgICAgICAKICAgUGVyY2VudD0gYygoVEJsYWRGKSwgKFRCbG9vZEYpLChUQnJhaW5GKSwoVEJvbmVGKSwoVEJyZWFzdEYpLChURXNvcGhGKSwoVENlcnZGKSwoVEdhbGxGKSwoVExhcnlueEYpLChUTGV1a0YpLChUTHVuZ0YpLChUTGl2ZXJGKSwoVE1lbGFGKSwoVE1vdXRoRiksKFRPdmFyeUYpLChUUGFuY0YpLChUU2tpbk1lbGFGKSwoVFNraW5Ob01lbGFGKSwoVFNraW5Vbmtub3duRiksKFRTdG9tYWNoRiksKFRUaHlyb2lkRiksKFRUaHJvYXRGKSwoVFV0ZXJ1c0YpLChUSGFuZE5lY2tGKSwoVENvbFJlY0YpLChUT3RoZXJGKSkpCgpnZ3Bsb3QoQ2FuY2VyRiwgYWVzKHggPSBQZXJjZW50LCB5PUNhbmNlcikpICsKICBnZW9tX3BvaW50KCkgKyBsYWJzKHRpdGxlID0gIkNhbmNlciBBbW9uZyBGZW1hbGVzIikKYGBgCgojIyMjIyBDYW5jZXIgQW1vbmcgTWFsZXMKCmBgYHtyfQpUQmxhZE0gPC0gbnJvdyhkZkJsYWQgJT4lCiAgZmlsdGVyKFNFWF9BID09IDEpKS9Ub3RhbE0qMTAwClRCbG9vZE0gPC0gbnJvdyhkZkJsb29kICU+JQogIGZpbHRlcihTRVhfQSA9PSAxKSkvVG90YWxNKjEwMApUQm9uZU0gPC0gbnJvdyhkZkJvbmUgJT4lCiAgZmlsdGVyKFNFWF9BID09IDEpKS9Ub3RhbE0qMTAwClRCcmFpbk0gPC0gbnJvdyhkZkJyYWluICU+JQogIGZpbHRlcihTRVhfQSA9PSAxKSkvVG90YWxNKjEwMApUQnJlYXN0TSA8LSBucm93KGRmQnJlYXN0ICU+JQogIGZpbHRlcihTRVhfQSA9PSAxKSkvVG90YWxNKjEwMApURXNvcGhNIDwtIG5yb3coZGZFc29waCAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMSkpL1RvdGFsTSoxMDAKVEdhbGxNIDwtIG5yb3coZGZHYWxsICU+JQogIGZpbHRlcihTRVhfQSA9PSAxKSkvVG90YWxNKjEwMApUTGFyeW54TSA8LSBucm93KGRmTGFyeW54ICU+JQogIGZpbHRlcihTRVhfQSA9PSAxKSkvVG90YWxNKjEwMApUTGV1a00gPC0gbnJvdyhkZkxldWsgJT4lCiAgZmlsdGVyKFNFWF9BID09IDEpKS9Ub3RhbE0qMTAwClRMdW5nTSA8LSBucm93KGRmTHVuZyAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMSkpL1RvdGFsTSoxMDAKVExpdmVyTSA8LSBucm93KGRmTGl2ZXIgJT4lCiAgZmlsdGVyKFNFWF9BID09IDEpKS9Ub3RhbE0qMTAwClRNZWxhTSA8LSBucm93KGRmTWVsYSAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMSkpL1RvdGFsTSoxMDAKVE1vdXRoTSA8LSBucm93KGRmTW91dGggJT4lCiAgZmlsdGVyKFNFWF9BID09IDEpKS9Ub3RhbE0qMTAwClRQYW5jTSA8LSBucm93KGRmUGFuYyAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMSkpL1RvdGFsTSoxMDAKVFByb3N0TSA8LSBucm93KGRmUHJvc3QgJT4lCiAgZmlsdGVyKFNFWF9BID09IDEpKS9Ub3RhbE0qMTAwClRTa2luTWVsYU0gPC0gbnJvdyhkZlNraW5NZWxhICU+JQogIGZpbHRlcihTRVhfQSA9PSAxKSkvVG90YWxNKjEwMApUU2tpbk5vTWVsYU0gPC0gbnJvdyhkZlNraW5Ob01lbGEgJT4lCiAgZmlsdGVyKFNFWF9BID09IDEpKS9Ub3RhbE0qMTAwClRTa2luVW5rbm93bk0gPC0gbnJvdyhkZlNraW5Vbmtub3duICU+JQogIGZpbHRlcihTRVhfQSA9PSAxKSkvVG90YWxNKjEwMApUU3RvbWFjaE0gPC0gbnJvdyhkZlN0b21hY2ggJT4lCiAgZmlsdGVyKFNFWF9BID09IDEpKS9Ub3RhbE0qMTAwClRUaHlyb2lkTSA8LSBucm93KGRmVGh5cm9pZCAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMSkpL1RvdGFsTSoxMDAKVFRocm9hdE0gPC0gbnJvdyhkZlRocm9hdCAlPiUKICBmaWx0ZXIoU0VYX0EgPT0gMSkpL1RvdGFsTSoxMDAKVEhhbmROZWNrTSA8LSBucm93KGRmSGFuZE5lY2sgJT4lCiAgZmlsdGVyKFNFWF9BID09IDEpKS9Ub3RhbE0qMTAwClRDb2xSZWNNIDwtIG5yb3coZGZDb2xSZWMgJT4lCiAgZmlsdGVyKFNFWF9BID09IDEpKS9Ub3RhbE0qMTAwClRPdGhlck0gPC0gbnJvdyhkZk90aGVyICU+JQogIGZpbHRlcihTRVhfQSA9PSAxKSkvVG90YWxNKjEwMApgYGAKCmBgYHtyfQpDYW5jZXJNIDwtIGRhdGEuZnJhbWUoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgQ2FuY2VyICA9IGMoIkJsYWRkZXIiLCAiQmxvb2QiLCJCcmFpbiIsIkJvbmUiLCJCcmVhc3QiLCJFc29waGFndXMiLCJHYWxsQmxhZGRlciIsIkxhcnlueCIsIkxldWtlbWlhIiwiTHVuZyIsIkxpdmVyIiwiTWVsYW5vbWEiLCJNb3V0aCIsIlBhbmNyZWFzIiwiU2tpbiBNZWxhbm9tYSIsIlNraW4tTm90IE1lbGFub21hIiwiU2tpbi1Vbmtub3duIiwiU3RvbWFjaCIsIlRoeXJvaWQiLCJUaHJvYXQiLCJIYW5kIGFuZCBOZWNrIiwiQ29sb25SZWN0YWwiLCJPdGhlciIpLCAgICAgICAKICAgUGVyY2VudD0gYygoVEJsYWRNKSwgKFRCbG9vZE0pLChUQnJhaW5NKSwoVEJvbmVNKSwoVEJyZWFzdE0pLChURXNvcGhNKSwoVEdhbGxNKSwoVExhcnlueE0pLChUTGV1a00pLChUTHVuZ00pLChUTGl2ZXJNKSwoVE1lbGFNKSwoVE1vdXRoTSksKFRQYW5jTSksKFRTa2luTWVsYU0pLChUU2tpbk5vTWVsYU0pLChUU2tpblVua25vd25NKSwoVFN0b21hY2hNKSwoVFRoeXJvaWRNKSwoVFRocm9hdE0pLChUSGFuZE5lY2tNKSwoVENvbFJlY00pLChUT3RoZXJNKSkpCgpnZ3Bsb3QoQ2FuY2VyTSwgYWVzKHggPSBQZXJjZW50LCB5PUNhbmNlcikpICsKICBnZW9tX3BvaW50KCkgKyBsYWJzKHRpdGxlID0gIkNhbmNlciBBbW9uZyBNYWxlcyIpCmBgYAoKIyMjIyMgQ2FuY2VyIEFtb25nIEJvdGgKCmBgYHtyfQpkZl9DYW5tZXJnZSA8LSBtZXJnZShDYW5jZXJGLENhbmNlck0sYnk9IkNhbmNlciIsIGFsbC54ID0gVFJVRSkgCgpuYW1lcyhkZl9DYW5tZXJnZSlbbmFtZXMoZGZfQ2FubWVyZ2UpID09ICJQZXJjZW50LngiXSA8LSAiRmVtYWxlIgpuYW1lcyhkZl9DYW5tZXJnZSlbbmFtZXMoZGZfQ2FubWVyZ2UpID09ICJQZXJjZW50LnkiXSA8LSAiTWFsZSIKCmBgYAoKYGBge3J9CmRmQ2FuY2VyTWVyZ2VkIDwtIG1lbHQoZGZfQ2FubWVyZ2UsIGlkLnZhcnM9IkNhbmNlciIpCm5hbWVzKGRmQ2FuY2VyTWVyZ2VkKVtuYW1lcyhkZkNhbmNlck1lcmdlZCkgPT0gInZhbHVlIl0gPC0gIlBlcmNlbnQiCm5hbWVzKGRmQ2FuY2VyTWVyZ2VkKVtuYW1lcyhkZkNhbmNlck1lcmdlZCkgPT0gInZhcmlhYmxlIl0gPC0gIlNleCIKCmdncGxvdChkZkNhbmNlck1lcmdlZCwgYWVzKFBlcmNlbnQsQ2FuY2VyLCBjb2w9U2V4KSkgKyAKICBnZW9tX3BvaW50KCkgKyBsYWJzKHRpdGxlID0gIkNhbmNlciBBbW9uZyBNYWxlcyBhbmQgRmVtYWxlcyIpCgpgYGAKCkJvdGggbWFsZXMgYW5kIGZlbWFsZXMgaGFkIGEgaGlnaGVyIHBlcmNlbnRhZ2UgZm9yIFNraW4tTm90IE1lbGFub21hCmNhbmNlci4gVGhlIGhpZ2hlc3QgcGVyY2VudGFnZSBmb3IgY2FuY2VyIHdhcyBicmVhc3QgY2FuY2VyIGluCmZlbWFsZXMuSW4gbWFueSBvZiB0aGUgY2FuY2VyIGNhdGVnb3JpZXMsIGZlbWFsZXMgaGFkIGEgc2xpZ2h0bHkgbG93ZXIKcGVyY2VudGFnZS4KCiMgU3VtbWFyeQoKV2hpbGUgbWFueSBvZiB0aGUgd2F5cyB0byBzdGF5IGhlYWx0aHkgYXJlIGNvbW1vbmx5IGtub3duIGFuZAphZHZlcnRpc2VkLCBpdCBpcyBpbnRlcmVzdGluZyB0byBsb29rIGF0IHRoZSBkYXRhIHRvIGdldCBhIG1vcmUgc3BlY2lmaWMKaWRlYS4gV2hpbGUgbWFueSBvZiB0aGVzZSBkaWQgbm90IGhhdmUgbXVjaCBvZiBhIGRpZmZlcmVuY2UgYmV0d2VlbgpjYXRlZ29yaWVzLCB0aGVyZSBpcyBzb21lIGluZm9ybWF0aW9uIHRoYXQgY2FuIGJlIGdhaW5lZCB0aGF0IGZvbGxvdwptYW55IG9mIHRoZSBoZWFsdGggaWRlYXMgd2UgYWxyZWFkeSBrbm93LiBUaGVzZSBpbmNsdWRlCgoxLiAgSXQgaXMgbGVzcyBoZWFsdGhpZXIsIG1lbnRhbGx5IGFuZCBwaHlzaWNhbGx5LCBmb3IgeW91IHRvIHNtb2tlLgogICAgU21va2luZyBhdCBsZWFzdCAxMDAgY2lnYXJldHRlcyBjYW4gbWFrZSB0aGlzIHdvcnN0IGFuZCBpZiB5b3UgZW5kCiAgICB1cCB3aXRoIGx1bmcgY2FuY2VyLCBpdCBjb3VsZCBiZSBjb250cmlidXRlZCB0byB5b3Ugc21va2luZy4KMi4gIENhbmNlciBpcyBpbXBvcnRhbnQgdG8gd2F0Y2ggb3V0IGZvciwgYW5kIHRoZXJlIGFyZSBzb21lCiAgICBzcGVjaWZpY2FsbHkgdGhhdCBhcmUgbW9yZSBjb21tb24gYmFzZWQgb24geW91ciBzZXggYW5kIG92ZXJhbGwgbW9yZQogICAgY29tbW9uLgozLiAgV2hpbGUgaXQgaXMgbW9zdGx5IHVuYXZvaWRhYmxlLCB0aG9zZSB3aG8gaGF2ZSBkaWZmaWN1bHR5IHNlZWluZyBjYW4KICAgIGhhdmUgd29yc3QgbGlmZSBzYXRpc2ZhY3Rpb24sIHNvIGlmIHlvdSBjYW4gZ2V0IGl0IGZpeGVkIGJ5IHN1cmdlcnkKICAgIG9yIGdsYXNzZXMvY29udGFjdHMsIGl0IHdpbGwgYmUgaGVscGZ1bC4KNC4gIEl0IGlzIGJldHRlciB0byBmb3IgeW91ciBtZW50YWwgYW5kIHBoeXNpY2FsIGhlYWx0aCB0byBzdGF5IGFyb3VuZCBhCiAgICBub3JtYWwgQk1JLiBIb3dldmVyLCB0aGlzIGNvdWxkIGJlIGFyZ3VlZCBiYXNlZCBvbiBpZiB5b3VyIHdlaWdodAogICAgY29tZXMgZnJvbSBub24tbXVzY2xlIGZhdCBvciBtdXNjbGUgZmF0Lgo1LiAgQSBoaWdoZXIgZWR1Y2F0aW9uIGNvdWxkIHBvdGVudGlhbGx5IGxlYWQgeW91IHRvIGZlZWwgbW9yZSBzYXRpc2ZpZWQKICAgIGFuZCBoYXZlIGJldHRlciBoZWFsdGguCg==