FACTORS AFFECT SUICIDES PERCENTAGE CHR-2022

Quynh Nguyen

2022-12-17

1 Preliminaries

1.1 My R Packages

This code snippet will list packages that going to be used throughout the proposal.

library(janitor)
library(naniar)
library(tidyverse)
library(mosaic)
library(readr)
library(utils)
library(ggplot2)
library(patchwork)

1.2 Data Ingest

This following code snippet uses to load the data of 2022 County Health Rankings (CHR).

data_url <- 
  "https://www.countyhealthrankings.org/sites/default/files/media/document/analytic_data2022.csv"
chr_2022_raw <- read_csv(data_url, skip = 1, guess_max = 4000,
                         show_col_types = FALSE)

2 Data Development

2.1 Selecting My Data

For this proposal, I will select from the six “states”: Ohio (OH), New York (NY), Pennsylvania (PA), Virginia (VA), Massachusetts (MA), and Maryland (MD). These states are considered as East Seaboard states of the U.S except for Ohio, which is Midwest. I’ve selected five variables freq_mental_distress (v145_rawvalue), unemployment (v023_rawvalue), food_insecurity (v139_rawvalue), suicides (v161_rawvalue), and alcohol_impaired_driving_deaths (v134_rawvalue) since I am interested in how unemployment can make an impact on mental health as well as other aspects in lives.

From that, the chunk of code below would try to complete the following tasks:

  1. Task 1: Filter the data to the actual counties that are ranked in the Rankings (this eliminates state and USA totals, mainly.) This is done by filtering to only keep rows that have county_ranked equal to 1.
  2. Task 2: Filter 6 states that I’ve selected (the %in% command lets us include any state in the list we then create with the c() function), including OH: OH, NY, PA, VA, MA, MD.
  3. Task 3: Select the variables that I’ve chosen to use in this study, including the 3 mandatory variables (fipscode, state, and county): v145, v023, v139, v161, v134
    • Rename the 5 variables into meaningful names. These names are the actual meaning of the variables.
    • Except for the suicides variable, the other four variables are listed in proportions, so I will rescale it to percentage.
  4. Repair the fipscode by converting it into a character variable instead numerical value and factoring the state
chr_2022 <- chr_2022_raw |> 
            filter(county_ranked == 1) |> 
            filter(state %in% c("OH", "NY", "PA", "VA", "MA", "MD")) |>
            select(fipscode, state, county, county_ranked, 
                   v145_rawvalue, v023_rawvalue, v139_rawvalue, v161_rawvalue, v134_rawvalue) |>
            rename(freq_mental_distress  = v145_rawvalue,
                   unemployment = v023_rawvalue,
                   food_insecurity = v139_rawvalue,
                   suicides = v161_rawvalue,
                   alcohol_impaired_driving_deaths = v134_rawvalue) |>
            mutate(freq_mental_distress  = 100*freq_mental_distress ,
                    unemployment = 100*unemployment,
                    food_insecurity = 100*food_insecurity,
                    alcohol_impaired_driving_deaths = 100*alcohol_impaired_driving_deaths) |>
            mutate(fipscode = str_pad(fipscode, 5, pad="0"), 
                   state = factor(state))

2.1.1 Checking Initial Work

After completing the tasks above, we want to check our initial work. This also checks if the total number of counties from our selected states can be around 200 - 400 counties or not.

glimpse(chr_2022) 
Rows: 388
Columns: 9
$ fipscode                        <chr> "24001", "24003", "24005", "24009", "2…
$ state                           <fct> MD, MD, MD, MD, MD, MD, MD, MD, MD, MD…
$ county                          <chr> "Allegany County", "Anne Arundel Count…
$ county_ranked                   <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
$ freq_mental_distress            <dbl> 16.5, 12.2, 13.8, 13.1, 16.3, 13.1, 14…
$ unemployment                    <dbl> 7.776877, 5.832230, 6.827988, 5.226294…
$ food_insecurity                 <dbl> 16.9, 9.0, 10.7, 8.2, 13.3, 9.6, 12.4,…
$ suicides                        <dbl> 16.225499, 12.317121, 10.585320, 10.39…
$ alcohol_impaired_driving_deaths <dbl> 48.48485, 29.18455, 26.78571, 29.54545…

Since the number of rows is 388, it should be accepted as it falls within the required range.

2.1.2 Checking missing values

(Part of Task 6) We will check about the missing values for each variables

chr_2022 |> 
    miss_var_summary() |>
    kable()
variable n_miss pct_miss
suicides 24 6.185567
alcohol_impaired_driving_deaths 6 1.546392
fipscode 0 0.000000
state 0 0.000000
county 0 0.000000
county_ranked 0 0.000000
freq_mental_distress 0 0.000000
unemployment 0 0.000000
food_insecurity 0 0.000000

2.1.3 Checking percentage available of missing-value-containing variables for each state

(Part of Task 7) From the code snippet above, suicides and alcohol_impaired_driving_deaths have missing values. I want to summarize this by the state in order to compare the result.

  1. For suicides variable:
mosaic::favstats(suicides ~ state, data = chr_2022) |>
    select(state, n, missing) |>
    mutate(pct_available = 100*(n - missing)/n) |>
    kable()
state n missing pct_available
MA 13 1 92.30769
MD 24 0 100.00000
NY 61 1 98.36066
OH 87 1 98.85057
PA 64 3 95.31250
VA 115 18 84.34783

Since the pct_variable for each state is higher than 75% for suicide, we would like to go with the next check-up point.

  1. For alcohol_impaired_driving_deaths variable:
mosaic::favstats(alcohol_impaired_driving_deaths ~ state, data = chr_2022) |>
    select(state, n, missing) |>
    mutate(pct_available = 100*(n - missing)/n) |>
    kable()
state n missing pct_available
MA 14 0 100.00000
MD 24 0 100.00000
NY 62 0 100.00000
OH 88 0 100.00000
PA 67 0 100.00000
VA 127 6 95.27559

Since the pct_variable for each state is higher than 75% for alcohol_impaired_driving_deaths, we would like to go with the next check-up point.

2.1.4 Checking numbers of distinct values for each variable

(Part of Task 7) I would like to check if each chosen variable contains at least 10 distinct non-missing values.

chr_2022 |> 
    summarize(across(freq_mental_distress:alcohol_impaired_driving_deaths, ~ n_distinct(.))) |>
    kable()
freq_mental_distress unemployment food_insecurity suicides alcohol_impaired_driving_deaths
90 388 125 365 230

Since all conditions are satisfied, I will keep working on my data selection.

2.2 Create Factors For Two of the Five Variables

For Task 4, I will pick two out of five chosen variables in order to create factors for these variables. I chose unemployment and freq_mental_distress to create factors.

2.2.1 Creating Binary Categorical Variables

  • For freq_mental_distress, it will be named as mental_distress_level and this variable will be used as binary categorical variables:
    • low: frequency is below 13.2.
    • high: frequency is equal to or higher than 13.2.

The cut-off (13.2) was determined based on the frequency mental distress in U.S value (https://www.americashealthrankings.org/explore/annual/measure/mental_distress).

chr_2022 <- chr_2022 |>
            mutate(mental_distress_level = case_when(
                  freq_mental_distress < 13.2 ~ "low",
                  TRUE ~"high"), 
                  mental_distress_level = factor(mental_distress_level)) 

After creating the mental_distress_level, I would like to check whether they can be factored or not. In addition, I also want to check if it has at least 10 rows for each level of factor or not.

levels(as.factor(chr_2022$mental_distress_level)) 
[1] "high" "low" 
mosaic::favstats(freq_mental_distress ~ mental_distress_level, data = chr_2022) |> kable(digits = 3) 
mental_distress_level min Q1 median Q3 max mean sd n missing
high 13.2 15.100 16.1 17.2 20.8 16.232 1.668 346 0
low 9.7 11.825 12.3 13.0 13.1 12.119 0.996 42 0

2.2.2 Creating a Three-Category Variable

  • For unemployment, I would name it as unemployment_level and factor it into three different levels:
    • low: percentage is under 5%
    • normal: percentage is higher than 5% but lower than 7%.
    • high: percentage is equal to or higher than 7%

Usually, it is said that the normal unemployment rate should be from 4% to 6%. Therefore, I would like to indicate that any unemployment percentage under 5%, which is the mean of the normal unemployment rate, should be considered a low employment rate. Then, the percentage that is higher than this range should be considered as a high unemployment rate. Therefore, I came up with the normal unemployment rate from 5% to 7%, and anything higher than this range would be a high rate.

chr_2022 <- chr_2022 |>
            mutate(unemployment_level = case_when(
                  unemployment < 5 ~ "low",
                  unemployment < 7 ~ "normal",
                  TRUE ~ "high"),
                  unemployment_level = factor(unemployment_level))

I will do the same thing as above to check if it is possible to factor in the unemployment_level column or not. If yes, I also want to know whether it contains at least 10 rows at each level.

levels(as.factor(chr_2022$unemployment_level))
[1] "high"   "low"    "normal"
mosaic::favstats(unemployment ~ unemployment_level, data = chr_2022) |> kable(digits = 3) 
unemployment_level min Q1 median Q3 max mean sd n missing
high 7.004 7.790 8.487 9.405 16.031 8.743 1.309 239 0
low 3.713 4.479 4.621 4.835 4.954 4.542 0.385 24 0
normal 5.074 5.614 6.129 6.544 6.984 6.084 0.579 125 0

2.2.3 Checking factors of state variable

(Part of Task 7) Finally, I would like to check if the state variable is already factored as well as if it contains at least 10 counties for each level, or state.

levels(as.factor(chr_2022$state))
[1] "MA" "MD" "NY" "OH" "PA" "VA"
chr_2022 |> tabyl(state) |> adorn_pct_formatting() |> kable()
state n percent
MA 14 3.6%
MD 24 6.2%
NY 62 16.0%
OH 88 22.7%
PA 67 17.3%
VA 133 34.3%

2.3 Structure and Summarize of My Tibble

(Task 5) This section would print out the structure of my tibble. I’m checking to see that:

  • The first rows tell me that this is a tibble with specification about its dimensions

  • I will have a complete set of 388 rows

  • I have included only 11 variables which include:

    • Three required variables (fipscode, county, and state). For the fipscode and county, it should be characterized as <chr>. For state, it should be considered as Factor variables with an appropriate number of levels, 6, followed by numerical code.
    • My five original chosen variables should be specified as <num>.
    • My other two categorical variables, unemployment_rate and mental_distress_level are characterized as Factor, followed by numerical codes.
    str(chr_2022)
    tibble [388 × 11] (S3: tbl_df/tbl/data.frame)
     $ fipscode                       : chr [1:388] "24001" "24003" "24005" "24009" ...
     $ state                          : Factor w/ 6 levels "MA","MD","NY",..: 2 2 2 2 2 2 2 2 2 2 ...
     $ county                         : chr [1:388] "Allegany County" "Anne Arundel County" "Baltimore County" "Calvert County" ...
     $ county_ranked                  : num [1:388] 1 1 1 1 1 1 1 1 1 1 ...
     $ freq_mental_distress           : num [1:388] 16.5 12.2 13.8 13.1 16.3 13.1 14.9 13.1 15.8 12.8 ...
     $ unemployment                   : num [1:388] 7.78 5.83 6.83 5.23 5.55 ...
     $ food_insecurity                : num [1:388] 16.9 9 10.7 8.2 13.3 9.6 12.4 6.9 14.7 9.7 ...
     $ suicides                       : num [1:388] 16.2 12.3 10.6 10.4 14.3 ...
     $ alcohol_impaired_driving_deaths: num [1:388] 48.5 29.2 26.8 29.5 23.7 ...
     $ mental_distress_level          : Factor w/ 2 levels "high","low": 1 2 1 2 1 2 1 2 1 2 ...
     $ unemployment_level             : Factor w/ 3 levels "high","low","normal": 1 3 3 3 3 3 3 3 3 3 ...

The following code snippet will save the tibble into .Rds file

saveRDS(chr_2022, "chr_2022_Quynh_Nguyen.rds")

We can try to load it with this command

chr_2022_load <- readRDS("chr_2022_Quynh_Nguyen.rds")
chr_2022_load
# A tibble: 388 × 11
   fipscode state county count…¹ freq_…² unemp…³ food_…⁴ suici…⁵ alcoh…⁶ menta…⁷
   <chr>    <fct> <chr>    <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl> <fct>  
 1 24001    MD    Alleg…       1    16.5    7.78    16.9    16.2    48.5 high   
 2 24003    MD    Anne …       1    12.2    5.83     9      12.3    29.2 low    
 3 24005    MD    Balti…       1    13.8    6.83    10.7    10.6    26.8 high   
 4 24009    MD    Calve…       1    13.1    5.23     8.2    10.4    29.5 low    
 5 24011    MD    Carol…       1    16.3    5.55    13.3    14.3    23.7 high   
 6 24013    MD    Carro…       1    13.1    5.09     9.6    12.5    24.1 low    
 7 24015    MD    Cecil…       1    14.9    5.94    12.4    17.1    25.4 high   
 8 24017    MD    Charl…       1    13.1    6.72     6.9    10.5    35.4 low    
 9 24019    MD    Dorch…       1    15.8    6.67    14.7    13.7    30.4 high   
10 24021    MD    Frede…       1    12.8    5.94     9.7    12.3    27.4 low    
# … with 378 more rows, 1 more variable: unemployment_level <fct>, and
#   abbreviated variable names ¹​county_ranked, ²​freq_mental_distress,
#   ³​unemployment, ⁴​food_insecurity, ⁵​suicides,
#   ⁶​alcohol_impaired_driving_deaths, ⁷​mental_distress_level

Or we can save it as .csv file

write.csv(chr_2022, file ="chr_2022_Quynh_Nguyen.csv", col.names = TRUE)
Warning in write.csv(chr_2022, file = "chr_2022_Quynh_Nguyen.csv", col.names =
TRUE): attempt to set 'col.names' ignored

3 Codebook

(Task 6) This section will display the codebooks for each name of variables in my tibble and their definitions. This section will contain two parts: (1) for states and (2) for variables.

3.1 Codebook for states

State Name Abbreviation Numbers of counties
Massachusetts MA 14
Maryland MD 24
New York NY 62
Ohio OH 88
Pennsylvania PA 67
Virginia VA 115
Total - 388

3.2 Codebook for variables

Variable Original code Description Number of missing
fipscode N/A FIPS code 0
state N/A Including 6 chosen states: MA, MD, NJ, NY, OH, PA 0
county N/A County name: including 388 counties from 6 chosen states 0
county_ranked N/A It is county ranked. All of them should equals 1 0
freq_mental_distress v145 Frequent Mental Distress Rate
unemployment v023 Unemployment Rate 0
food_insecurity v139 Food Insecurity Rate 0
suicides v161_rawvalue Suicides raw value 24
alcohol_impaired_driving_deaths v134 Alcohol-impaired driving deaths
unemployment_level N/A 3 levels: low = unemployment < 5%; normal = 5% <= unemployment rate < 7%; high = unemployment >= 7% 0
mental_distress_level N/A 2 levels: low = freq_mental_distress < 13.2%, and high for freq_mental_distress >= 13.2% 0

More details about the five chosen variables are specified below:

  • freq_mental_distress was originally variable v145_rawvalue, and it is listed in the Quality of Life subcategory of Health Outcome at County Health Rankings. It describes the percentage of adults reporting 14 or more days of poor mental health per month. This data was obtained from Behavioral Risk Factor Surveillance System from 2019. This might be my outcome variable.
  • unemployment was originally variable v023_rawvalue, and it is listed in the Unemployment of Social & Economic Factors subcategory of Health Factors at County Health Rankings. It describes percentage of population ages 16 and older unemployed but seeking work. This data was obtained from Bureau of Labor Statistics from 2020.
  • food_insecurity was originally variable v139_rawvalue, and it is listed in the Diet and Exercise of Health Behaviors subcategory of Health Factors at County Health Rankings. It describes percentage of population who lack adequate access to food.. This data was obtained from Map the Meal Gap from 2019.
  • suicides was originally variable v161_rawvalue, and it is listed in the Community Safety of Social & Economic Factors subcategory of Health Factors at County Health Rankings. It describes number of deaths due to suicide per 100,000 population (age-adjusted). This data was obtained from National Center for Health Statistics - Mortality Files from 2016 - 2020.
  • alcohol_impaired_driving_deaths was originally variable v34_rawvalue, and it is listed in the Alcohol and Drug Use of Health Behaviors subcategory of Health Factors at County Health Rankings. It describes percentage of driving deaths with alcohol involvement.. This data was obtained from Fatality Analysis Reporting System from 2016 - 2020. # Print and Summarize Tibble

(Task 7)

3.4 Report of Numerical Summaries

Then, I would like to report the numerical summaries.

Hmisc::describe(chr_2022) 
chr_2022 

 11  Variables      388  Observations
--------------------------------------------------------------------------------
fipscode 
       n  missing distinct 
     388        0      388 

lowest : 24001 24003 24005 24009 24011, highest: 51800 51810 51820 51830 51840
--------------------------------------------------------------------------------
state 
       n  missing distinct 
     388        0        6 

lowest : MA MD NY OH PA, highest: MD NY OH PA VA
                                              
Value         MA    MD    NY    OH    PA    VA
Frequency     14    24    62    88    67   133
Proportion 0.036 0.062 0.160 0.227 0.173 0.343
--------------------------------------------------------------------------------
county 
       n  missing distinct 
     388        0      316 

lowest : Accomack County  Adams County     Albany County    Albemarle County Alexandria city 
highest: Wyandot County   Wyoming County   Wythe County     Yates County     York County     
--------------------------------------------------------------------------------
county_ranked 
       n  missing distinct     Info     Mean      Gmd 
     388        0        1        0        1        0 
              
Value        1
Frequency  388
Proportion   1
--------------------------------------------------------------------------------
freq_mental_distress 
       n  missing distinct     Info     Mean      Gmd      .05      .10 
     388        0       90        1    15.79    2.306    12.30    13.10 
     .25      .50      .75      .90      .95 
   14.50    15.95    17.10    18.33    19.10 

lowest :  9.7  9.8 10.1 10.2 10.3, highest: 20.1 20.2 20.4 20.5 20.8
--------------------------------------------------------------------------------
unemployment 
       n  missing distinct     Info     Mean      Gmd      .05      .10 
     388        0      388        1    7.627    2.032    4.865    5.276 
     .25      .50      .75      .90      .95 
   6.379    7.628    8.778    9.778   10.456 

lowest :  3.712672  3.790439  3.832466  3.880440  4.176668
highest: 12.532384 12.533597 12.573674 13.946058 16.030909
--------------------------------------------------------------------------------
food_insecurity 
       n  missing distinct     Info     Mean      Gmd      .05      .10 
     388        0      125        1    11.55    3.443    6.335    7.570 
     .25      .50      .75      .90      .95 
   9.500   11.600   13.400   15.430   17.065 

lowest :  4.0  4.8  4.9  5.0  5.5, highest: 19.1 19.5 19.7 19.8 20.3
--------------------------------------------------------------------------------
suicides 
       n  missing distinct     Info     Mean      Gmd      .05      .10 
     364       24      364        1    15.58    5.588    8.280    9.768 
     .25      .50      .75      .90      .95 
  12.077   15.014   18.638   21.598   24.377 

lowest :  5.272063  5.324782  5.823285  6.109052  6.143075
highest: 31.216651 31.466973 32.802466 38.058005 43.755493
--------------------------------------------------------------------------------
alcohol_impaired_driving_deaths 
       n  missing distinct     Info     Mean      Gmd      .05      .10 
     382        6      229        1    28.29     12.4    10.54    15.62 
     .25      .50      .75      .90      .95 
   21.43    27.61    33.33    41.38    47.04 

lowest :   0.000000   2.500000   3.225806   4.166667   4.347826
highest:  58.181818  63.636364  76.923077  77.777778 100.000000
--------------------------------------------------------------------------------
mental_distress_level 
       n  missing distinct 
     388        0        2 
                      
Value       high   low
Frequency    346    42
Proportion 0.892 0.108
--------------------------------------------------------------------------------
unemployment_level 
       n  missing distinct 
     388        0        3 
                               
Value        high    low normal
Frequency     239     24    125
Proportion  0.616  0.062  0.322
--------------------------------------------------------------------------------

3.4.1 For freq_mental_distress variable

mosaic::favstats(~freq_mental_distress, data = chr_2022) |>
    kable(digits = 3)
min Q1 median Q3 max mean sd n missing
9.7 14.5 15.95 17.1 20.8 15.787 2.055 388 0

3.4.2 For unemployment variable

mosaic::favstats(~unemployment, data = chr_2022) |>
    kable(digits = 3)
min Q1 median Q3 max mean sd n missing
3.713 6.379 7.628 8.778 16.031 7.627 1.816 388 0

3.4.3 For food_insecurity variable

mosaic::favstats(~food_insecurity, data = chr_2022) |>
    kable(digits = 3)
min Q1 median Q3 max mean sd n missing
4 9.5 11.6 13.4 20.3 11.555 3.059 388 0

3.4.4 For suicides variable

mosaic::favstats(~suicides, data = chr_2022) |>
    kable(digits = 3)
min Q1 median Q3 max mean sd n missing
5.272 12.077 15.014 18.638 43.755 15.584 5.164 364 24

3.4.5 For alcohol_impaired_driving_deaths variable

mosaic::favstats(~alcohol_impaired_driving_deaths, data = chr_2022) |>
    kable(digits = 3)
min Q1 median Q3 max mean sd n missing
0 21.429 27.609 33.333 100 28.292 11.753 382 6

3.4.6 For mental_distress_level variable

chr_2022 |> tabyl(mental_distress_level) |> adorn_pct_formatting() |> kable()
mental_distress_level n percent
high 346 89.2%
low 42 10.8%

3.4.7 For unemployment_level variable

chr_2022 |> tabyl(unemployment_level) |> adorn_pct_formatting() |> kable()
unemployment_level n percent
high 239 61.6%
low 24 6.2%
normal 125 32.2%

3.4.8 For state variable

I already included this in 2.2.3: Checking factors of state variable

4 Report Writeup

I did my project proposal by following it step-by-step as it was listed on the class website. However, I think that caused me a lot of trouble. First of all, I only saw other requirements for my data selection until I reached the end of the report. In the original work, instead of choosing Virginia, I chose Georgia. This original work resulted in more states and added more rows for me. However, when checking about the available percentage of non-missing values for the variable that contains missing values, it turned out this percentage was under 75% for Georgia. Therefore, I had to make another state selection and chose Virginia as an alternative selection. However, when I replaced it with Virginia, it gave me another variable that contains missing value instead only having one variable that has missing value as my original work. I did not recognize this in the first place until I went through my result again, which made me add another small code snippet. Therefore, I wish these checks could be placed somewhere at the beginning instead of in the latest task. Besides this part, I feel the instruction was well-organized and easy to follow.

5 Analyses 1

5.1 The Variables

  • The outcome in this analysis should be the suicides. As indicated above, the suicides were in percentage, so its unit would be %. Since our outcome has some missing values, we would use complete case on it.
  • Besides two categorical predictor variables, unemployment and freq_mental_distress, the other two predictors are alcohol_impaired_driving_deaths and food_insecurity. In this analysis, I would like to use food_insecurity as the predictor variables.
  • From the table above, food _insecurity has no missing values, and it was calculated as percentage. Therefore, food_insecurity unit woule be %.
  • The following is the tibble of the variables.
data1 <- chr_2022 %>% select('food_insecurity', 'suicides', 'state', 'county')
miss_var_summary(data1) |> kable()
variable n_miss pct_miss
suicides 24 6.185567
food_insecurity 0 0.000000
state 0 0.000000
county 0 0.000000
#complete case for the suicides
data1 <- data1 %>% filter(complete.cases(data1))
data1 
# A tibble: 364 × 4
   food_insecurity suicides state county             
             <dbl>    <dbl> <fct> <chr>              
 1            16.9     16.2 MD    Allegany County    
 2             9       12.3 MD    Anne Arundel County
 3            10.7     10.6 MD    Baltimore County   
 4             8.2     10.4 MD    Calvert County     
 5            13.3     14.3 MD    Caroline County    
 6             9.6     12.5 MD    Carroll County     
 7            12.4     17.1 MD    Cecil County       
 8             6.9     10.5 MD    Charles County     
 9            14.7     13.7 MD    Dorchester County  
10             9.7     12.3 MD    Frederick County   
# … with 354 more rows

The structure of the table, which have

str(data1)
tibble [364 × 4] (S3: tbl_df/tbl/data.frame)
 $ food_insecurity: num [1:364] 16.9 9 10.7 8.2 13.3 9.6 12.4 6.9 14.7 9.7 ...
 $ suicides       : num [1:364] 16.2 12.3 10.6 10.4 14.3 ...
 $ state          : Factor w/ 6 levels "MA","MD","NY",..: 2 2 2 2 2 2 2 2 2 2 ...
 $ county         : chr [1:364] "Allegany County" "Anne Arundel County" "Baltimore County" "Calvert County" ...

The number of counties that have complete cases for both variables are 364 counties.

Value of predictor (food_insecurity) and outcome (suicides) for Cuyahoga County: food_insecurity is 13.9% and suicides is 13.41873.

data1[data1$state =="OH" & data1$county=="Cuyahoga County",] |> kable()
food_insecurity suicides state county
13.9 13.41873 OH Cuyahoga County

5.2 Research Question

What is the nature of the association between the food insecurity and suicides, in 364 counties across 6 different states?

5.3 Visualizing the Data

ggplot(data1, aes(x=food_insecurity, y =suicides)) + geom_point() + 
  labs(x ="Food Insecurity (%)", 
       y = "Suicides (%)",
       title = "How closely associated are food insecurity and suicides?",
       subtitle = "Food insecurity as predictors and suicides as outcomes")

Based on the figure above, it seems like they are somewhat having a positive association with each other as the food_insecurity percentage increases, the suicides percentage also increase.

ggplot(data1, aes(x=food_insecurity, y =suicides)) + geom_point(alpha = 0.6) +
  geom_smooth(method="lm", col ="red", se = FALSE, formula = y ~ x) +
  geom_smooth(method="loess", col ="blue", se=FALSE, formula = y ~x) +
  labs(x ="Food Insecurity (%)", 
       y = "Suicides (%)",
       title = "Positive association between food insecurity and suicides",
       subtitle = "OLS model in red, loess smooth in blue")

From the plot, it seems like they actually have a positive association between food_insecurity and suicides as points follow the straight line’s path. Moreover, there are couples of outliners in the graph. In addition, the association is not a stronf correlation.

5.4 Transformation Assessment

In order to investigate as if I should do the transformation or not, I would like to investigate suicides variable, which is my outcome.

p1 <-  ggplot(data1, aes(sample = suicides)) +
  geom_qq() + # plot the points
  geom_qq_line(col = "blue") + # plot the Y = X line
  theme(aspect.ratio = 1) + # make the plot square
  labs(title = "Normal Q-Q plot: Simulated suicides")
p2 <- ggplot(data1, aes(x=suicides)) +
      geom_histogram(aes(y=stat(density)), bins = 20, fill ="royalblue", col ="white") +
      stat_function(fun = dnorm, args = list(mean = mean(data1$suicides), sd = sd(data1$suicides)), col ="red", lwd = 1.5) +
      labs(title="Density Function: Suicides")
p3 <- ggplot(data1, aes(x = suicides, y = "")) +
      geom_boxplot(fill = "royalblue",
      outlier.color = "royalblue") +
      labs(title = "Boxplot:Suicides", y = "")
p1 + (p2 / p3 + plot_layout(heights = c(4,1)))

mosaic::favstats(~ suicides, data = data1) %>% kable(digits = 1)
min Q1 median Q3 max mean sd n missing
5.3 12.1 15 18.6 43.8 15.6 5.2 364 0

As the above graph, we can see that our suicides has right-skewed distribution.

p1 <-  ggplot(data1, aes(sample = food_insecurity)) +
  geom_qq() + # plot the points
  geom_qq_line(col = "blue") + # plot the Y = X line
  theme(aspect.ratio = 1) + # make the plot square
  labs(title = "Normal Q-Q plot: Simulated food insecurity")
p2 <- ggplot(data1, aes(x=food_insecurity)) +
      geom_histogram(aes(y=stat(density)), bins = 20, fill ="royalblue", col ="white") +
      stat_function(fun = dnorm, args = list(mean = mean(data1$food_insecurity), sd = sd(data1$food_insecurity)), col ="red", lwd = 1.5) +
      labs(title="Density Function: Food insecurity")
p3 <- ggplot(data1, aes(x = food_insecurity, y = "")) +
      geom_boxplot(fill = "royalblue",
      outlier.color = "royalblue") +
      labs(title = "Boxplot: Food insecurity", y = "")
p1 + (p2 / p3 + plot_layout(heights = c(4,1)))

mosaic::favstats(~ food_insecurity, data = data1) %>% kable(digits = 1)
min Q1 median Q3 max mean sd n missing
4 9.5 11.6 13.3 20.3 11.5 3 364 0

Comparing to the suicides, food_insecurity is normally distributed.

Because of this, I want to investigate the transformation on suicides variable by applying logarithm base 10 on this variable.

data2 <- mutate(data1, suicides = log(suicides))
p1 <-  ggplot(data2, aes(sample = suicides)) +
  geom_qq() + # plot the points
  geom_qq_line(col = "blue") + # plot the Y = X line
  theme(aspect.ratio = 1) + # make the plot square
  labs(title = "Normal Q-Q plot: Simulated suicides")
p2 <- ggplot(data2, aes(x=suicides)) +
      geom_histogram(aes(y=stat(density)), bins = 20, fill ="royalblue", col ="white") +
      stat_function(fun = dnorm, args = list(mean = mean(data2$suicides), sd = sd(data2$suicides)), col ="red", lwd = 1.5) +
      labs(title="Density Function: Suicides")
p3 <- ggplot(data2, aes(x = suicides, y = "")) +
      geom_boxplot(fill = "royalblue",
      outlier.color = "royalblue") +
      labs(title = "Boxplot: Suicides", y = "")
p1 + (p2 / p3 + plot_layout(heights = c(4,1)))

mosaic::favstats(~ suicides, data = data1) %>% kable(digits = 1)
min Q1 median Q3 max mean sd n missing
5.3 12.1 15 18.6 43.8 15.6 5.2 364 0

After applying transformation on the suicides variable, it looks more normally distributed comparing being right-skewed distribution as before. Therefore, I decide to perform transformation by using logarithm on on my suicides outcome.

Due to this, the association between food_insecurity and suicides will be redone.

ggplot(data2, aes(x=food_insecurity, y =suicides)) + geom_point(alpha = 0.6) +
  geom_smooth(method="lm", col ="red", se = FALSE, formula = y ~ x) +
  geom_smooth(method="loess", col ="blue", se=FALSE, formula = y ~x) +
  labs(x ="Food Insecurity (%)", 
       y = "Log of Suicides Percentage",
       title = "Positive association between food insecurity and log of suicides percentage",
       subtitle = "OLS model in red, loess smooth in blue")

5.5 The Fitted Model

Now, we would like to create our fitted model:

model1 <- lm(suicides ~ food_insecurity, data = data2)
broom::tidy(model1, conf.int = TRUE, conf.level = 0.90) %>% select(term, estimate, conf.low, conf.high, p.value ) %>%
kable(digits = 3)
term estimate conf.low conf.high p.value
(Intercept) 2.225 2.120 2.330 0
food_insecurity 0.040 0.032 0.049 0

Based on the summary of the model, the coefficients are: food_insecurity = 0.04 and intercept is 2.23. Because the coefficient for food_insecurity is larger than 0, it means that we have a positive association between food_insecurity and suicides. The intercept coefficient means where our line will intersects with the y-axis.This coefficients gives equation for my model is Log(Suicides) = 0.04 * food_insecurity + 2.23. In addition, these coefficients are significant as the low confidences of the interval are above 0 for both food_insecurity and intercept.

broom::glance(model1) %>% select(nobs, r.squared, adj.r.squared, sigma) %>% kable(digits = 3)
nobs r.squared adj.r.squared sigma
364 0.137 0.135 0.309

From the table above, it indicates that the R-squared is 0.137 and residual standard error is 0.309.

Finally, we obtain the Pearson correlatio is 0.37

cor(y = data2$suicides, x = data2$food_insecurity)
[1] 0.3704226

5.6 Residual Analysis

Here is using the augment function to get the fitted and residual values.

model1aug <- broom::augment(model1, data = data2)

Here is plot for Normality in the residuals

p1 <- ggplot(model1aug, aes(sample = .resid)) +
  geom_qq(col = "seagreen") + geom_qq_line(col = "black") + 
  theme(aspect.ratio = 1) + 
  labs(title = "Normal Q-Q: Model 1 Residuals")

p2 <- ggplot(model1aug, aes(x = .resid)) +
  geom_histogram(aes(y = stat(density)), 
                 bins = 20, fill = "seagreen", col = "yellow") +
  stat_function(fun = dnorm, 
                args = list(mean = mean(model1aug$.resid), 
                            sd = sd(model1aug$.resid)),
                col = "black", lwd = 1.5) +
  labs(title = "Hist + Normal Density: Model 1 Residuals")

p3 <- ggplot(model1aug, aes(x = .resid, y = "")) +
  geom_boxplot(fill = "seagreen", outlier.color = "seagreen") + 
  labs(title = "Boxplot: Model 1 Residuals", y = "")

p1 + (p2 / p3 + plot_layout(heights = c(4,1)))

mosaic::favstats(~ .resid, data = model1aug) %>% kable(digits = 1)
min Q1 median Q3 max mean sd n missing
-1.2 -0.2 0 0.2 1.1 0 0.3 364 0

From the histogram, we might agree that it is normally distributed. However, we can notice that each end of the histogram extends much further than the normal distribution, so it can be considered as heavy-tailed distribution. And this can be confirmed by our QQ-Plot. However, with that, the Normal model may still be reasonable for a batch of data.

And here is the plot for assess residuals vs fitted values for non-linearty

ggplot(model1aug, aes(x = .fitted, y = .resid)) +
  geom_point() +
  geom_smooth(method = "lm", col = "red",
              formula = y ~ x, se = FALSE) + 
  geom_smooth(method = "loess", col = "blue",
              formula = y ~ x, se = FALSE) +
  labs(title = "Model 1: Residuals vs. Fitted Values", 
       x = "Fitted suicides values", y = "Residuals")

From the plot, we do not see any significant curve when plotting the residuals against the fitted values. However, this is not given the ‘fuzzy football’ pattern, which it seems like the variance across levels of the fitted values are not really similar to each other.

Since I use transform model, I will create another model here to get the models’ prediction for the original outcome and compare to each actual outcome for Cuyahoga County in Ohio. The code is displayed below, with the predicted value as 17.05 while the actual value is 13.42

org <- lm(suicides ~ food_insecurity, data = data1)
orgaug <- broom::augment(org, data = data1)

tibble(actual_value = data1[data1$state=="OH" & data1$county =="Cuyahoga County",]$suicides, predicted_value = orgaug[orgaug$state=="OH" & orgaug$county =="Cuyahoga County",]$.fitted) |> kable(digits = 3)
actual_value predicted_value
13.419 17.054

The two counties have the least successful at predicting outcome are Bronx County in New York with absolute residual values are 1.22 and Kings County in New York with absolute residual value as 1.11

model1augorder <- mutate(model1aug, .resid = abs(.resid))
model1augorder <- model1augorder[order(-model1augorder$.resid),]
model1augorder[1:2,] |> kable(digits = 3)
food_insecurity suicides state county .fitted .resid .hat .sigma .cooksd .std.resid
16.4 1.672 NY Bronx County 2.889 1.217 0.010 0.303 0.077 -3.954
13.5 1.662 NY Kings County 2.772 1.110 0.004 0.304 0.025 -3.594

5.7 Conclusions and Limitations

For this analysis, we are interested in the nature of association between the food insecurity and suicides in 364 counties. From the analysis above, instead of using the percentage of suicides, we use its log to make sure it has the normal distribution because the original values are right-skewed. Based on the analysis, it appears that there is a positive association between the food insecurity and suicides. It appears that the association is moderate, as the Pearson’s correlation is only 0.37. However, it appears to be a significant linear regression as both the estimation for the food insecurity and suicides have their confidence low level are above 0. With that, the association between the food insecurity and suicides can be expressed as: Log(Suicides) = 0.04 * food_insecurity + 2.23.

From the residual plot, we actually don’t see any ‘fuzzy football’ pattern, which is understandable since the distribution of our residuals are not normality as it is a heavy-tailed distribution. Therefore, we can conclude that the variance variance across levels of the fitted values are not really similar to each other. In addition, another limitations in this study is that the states I chose cannot use to be a representative sample of the U.S. Since I selected it based on my favorite, instead of making random choices, and they all place in the Eastern of the U.S. If I want to make a representative sample of the U.S, I would better choose them randomly or I should pick one state from different coast.

6 Analysis 2

6.1 The variables

I choose unemployment and freq_mental_distress to be my two categorical predictors. In this report, I would like to use freq_mental_distress as my choice for categorical predictor. It was calculated in percentage (%) .The outcome would be the same, which is suicides (%)

data3 <- chr_2022 %>% select('freq_mental_distress', 'mental_distress_level' ,'suicides', 'state', 'county')
miss_var_summary(data3) |> kable()
variable n_miss pct_miss
suicides 24 6.185567
freq_mental_distress 0 0.000000
mental_distress_level 0 0.000000
state 0 0.000000
county 0 0.000000
#complete case for the suicides
data3 <- data3 %>% filter(complete.cases(data3))
data3
# A tibble: 364 × 5
   freq_mental_distress mental_distress_level suicides state county             
                  <dbl> <fct>                    <dbl> <fct> <chr>              
 1                 16.5 high                      16.2 MD    Allegany County    
 2                 12.2 low                       12.3 MD    Anne Arundel County
 3                 13.8 high                      10.6 MD    Baltimore County   
 4                 13.1 low                       10.4 MD    Calvert County     
 5                 16.3 high                      14.3 MD    Caroline County    
 6                 13.1 low                       12.5 MD    Carroll County     
 7                 14.9 high                      17.1 MD    Cecil County       
 8                 13.1 low                       10.5 MD    Charles County     
 9                 15.8 high                      13.7 MD    Dorchester County  
10                 12.8 low                       12.3 MD    Frederick County   
# … with 354 more rows

The structure of the table, which have

str(data3)
tibble [364 × 5] (S3: tbl_df/tbl/data.frame)
 $ freq_mental_distress : num [1:364] 16.5 12.2 13.8 13.1 16.3 13.1 14.9 13.1 15.8 12.8 ...
 $ mental_distress_level: Factor w/ 2 levels "high","low": 1 2 1 2 1 2 1 2 1 2 ...
 $ suicides             : num [1:364] 16.2 12.3 10.6 10.4 14.3 ...
 $ state                : Factor w/ 6 levels "MA","MD","NY",..: 2 2 2 2 2 2 2 2 2 2 ...
 $ county               : chr [1:364] "Allegany County" "Anne Arundel County" "Baltimore County" "Calvert County" ...

The number of counties that have complete cases for both variables are 364 counties.

Value of predictor (freq_mental_distress) and outcome (suicides) for Cuyahoga County: freq_mental_distress is 16.7% and suicides is 13.419%.

data3[data3$state =="OH" & data3$county=="Cuyahoga County",] |> kable(digits = 3)
freq_mental_distress mental_distress_level suicides state county
16.7 high 13.419 OH Cuyahoga County

6.2 Research Question

Does low or high frequency of mental distress show higher levels of suicides, in 364 counties in the states of?

6.3 Visualizing Data

From the first analysis, we already know that the original distribution of suicides - our outcome - is right-skewed. Due to the normal assumption, I decide to use transformation by using logarithm again on the outcome.

data4 <- mutate(data3, suicides = log(suicides))
str(data4)
tibble [364 × 5] (S3: tbl_df/tbl/data.frame)
 $ freq_mental_distress : num [1:364] 16.5 12.2 13.8 13.1 16.3 13.1 14.9 13.1 15.8 12.8 ...
 $ mental_distress_level: Factor w/ 2 levels "high","low": 1 2 1 2 1 2 1 2 1 2 ...
 $ suicides             : num [1:364] 2.79 2.51 2.36 2.34 2.66 ...
 $ state                : Factor w/ 6 levels "MA","MD","NY",..: 2 2 2 2 2 2 2 2 2 2 ...
 $ county               : chr [1:364] "Allegany County" "Anne Arundel County" "Baltimore County" "Calvert County" ...
ggplot(data = data4, aes(x = mental_distress_level , y = suicides, color = mental_distress_level)) +
    geom_boxplot() +
    labs(title = "Suicides by Levels of Mental Distress",
         subtitle = "Log of Percentage of Suicides",
         x = "Levels of Mental Distress",
         y = "Log of Percentage of Suicides") +
  labs(color="Mental Distress Level")

From the box plot above, we can see a quite big shift of log of percentage of suicides in high level of mental distress comparing to the low level of mental distress as the log of percentage of suicides in high level of mental distress is higher.

6.4 The Fitted Model

If we don’t consider about the baseline state:

model2 <- lm(suicides ~ freq_mental_distress, data = data4)
broom::tidy(model2, conf.int = TRUE, conf.level = 0.90) %>% select(term, estimate, conf.low, conf.high, p.value ) %>%
kable(digits = 3)
term estimate conf.low conf.high p.value
(Intercept) 1.415 1.224 1.606 0
freq_mental_distress 0.081 0.069 0.093 0

Based on the summary of the model, the coefficients are: freq_mental_distress = 0.081 and intercept is 2.23. Because the coefficient for freq_mental_distress is larger than 0, it means that we have a positive association between freq_mental_distress and suicides. The intercept coefficient means where our line will intersects with the y-axis. This coefficients gives equation for my model is Log(Suicides) = 0.081 * freq_mental_distress + 1.42. In addition, these coefficients are significant as the low confidences of the interval are above 0 for both food_insecurity and intercept.

We also want to see how the association varies by the freq_mental_distress

data4 %>% group_by(mental_distress_level) %>% summarize(n = n(), pearson_r = cor(suicides, freq_mental_distress), r.squared = pearson_r^2) %>%
  kable(digits = 3)
mental_distress_level n pearson_r r.squared
high 324 0.369 0.137
low 40 0.125 0.016

From the table, only high level of mental distress has higher Pearson’s correlation comparing to low. Therefore, it is more fitted in this model comparing to the low.

For the baseline reference, I will choose “high” as default, and replace the previous model that we have:

model2 <- lm(suicides ~ freq_mental_distress + mental_distress_level, data = data4)
broom::tidy(model2, conf.int = TRUE, conf.level = 0.90) %>% select(term, estimate, conf.low, conf.high, p.value ) %>%
kable(digits = 3)
term estimate conf.low conf.high p.value
(Intercept) 1.700 1.453 1.946 0.000
freq_mental_distress 0.064 0.049 0.079 0.000
mental_distress_levellow -0.180 -0.280 -0.080 0.003

Based on the summary of the model, the coefficients are: freq_mental_distress = 0.064 and intercept is 1.7. The fitted model can be written as: (1) for low level of mental distress, it is Log(Suicides) = 0.064 * freq_mental_distress + 1.52 and (2) for high level of mental distress, it is Log(Suicides) = 0.064 * freq_mental_distress + 1.7 Because the coefficient for freq_mental_distress is larger than 0, it means that we have a positive association between freq_mental_distress and suicides. The intercept coefficient means where our line will intersects with the y-axis. In addition, these coefficients are significant as the low confidences of the interval are above 0 for both food_insecurity and intercept. However, the baseline reference is not that significant important, as the interval of coefficient for the baseline reference includes 0.

broom::glance(model2) %>% select(nobs, r.squared, adj.r.squared, sigma) %>% kable(digits = 3)
nobs r.squared adj.r.squared sigma
364 0.273 0.268 0.284

From the table above, it indicates that the R-squared is 0.273 and residual standard error is 0.284 with 364 observations

6.5 Prediction Analysis

Here is using the augment function to get the fitted and residual values.

model2aug <- broom::augment(model2, data = data4)

Here is the plot for Normality

p1 <- ggplot(model2aug, aes(sample = .resid)) +
  geom_qq(col = "seagreen") + geom_qq_line(col = "black") + 
  theme(aspect.ratio = 1) + 
  labs(title = "Normal Q-Q: Model 2 Residuals")

p2 <- ggplot(model2aug, aes(x = .resid)) +
  geom_histogram(aes(y = stat(density)), 
                 bins = 20, fill = "seagreen", col = "yellow") +
  stat_function(fun = dnorm, 
                args = list(mean = mean(model2aug$.resid), 
                            sd = sd(model2aug$.resid)),
                col = "black", lwd = 1.5) +
  labs(title = "Hist + Normal Density: Model 2 Residuals")

p3 <- ggplot(model2aug, aes(x = .resid, y = "")) +
  geom_boxplot(fill = "seagreen", outlier.color = "seagreen") + 
  labs(title = "Boxplot: Model 2 Residuals", y = "")

p1 + (p2 / p3 + plot_layout(heights = c(4,1)))

mosaic::favstats(~ .resid, data = model2aug) %>% kable(digits = 1)
min Q1 median Q3 max mean sd n missing
-1.2 -0.2 0 0.2 1 0 0.3 364 0

From the histogram, we might agree that it is normally distributed. However, we can notice that each end of the histogram extends much further than the normal distribution, so it can be considered as heavy-tailed distribution. And this can be confirmed by our QQ-Plot. However, with that, the Normal model may still be reasonable for a batch of data.

ggplot(model2aug, aes(x = .fitted, y = .resid)) +
  geom_point() +
  geom_smooth(method = "lm", col = "red",
              formula = y ~ x, se = FALSE) + 
  geom_smooth(method = "loess", col = "blue",
              formula = y ~ x, se = FALSE) +
  labs(title = "Model 2: Residuals vs. Fitted Values", 
       x = "Fitted suicides values", y = "Residuals")

From the plot, we can see the curve when plotting the residuals against the fitted values. In addition, this is not given the ‘fuzzy football’ pattern, which it seems like the variance across levels of the fitted values are not really similar to each other.

Since I use transform model, I will create another model here to get the models’ prediction for the original outcome and compare to each actual outcome for Cuyahoga County in Ohio. The code is displayed below, with the predicted value as 16.70 while the actual value is 16.723

org2 <- lm(suicides ~ freq_mental_distress + mental_distress_level, data = data3)
org2aug <- broom::augment(org2, data = data3)

tibble(actual_value = data3[data3$state=="OH" & data3$county =="Cuyahoga County",]$freq_mental_distress, predicted_value = org2aug[org2aug$state=="OH" & org2aug$county =="Cuyahoga County",]$.fitted) |> kable(digits = 3)
actual_value predicted_value
16.7 16.723

The two counties have the least successful at predicting outcome are Holmes County in Ohio with absolute residual values are 1.239 and Covington city in Virginia with absolute residual value as 0.992

model2augorder <- mutate(model2aug, .resid = abs(.resid))
model2augorder <- model2augorder[order(-model2augorder$.resid),]
model2augorder[1:2,] |> kable(digits = 3)
freq_mental_distress mental_distress_level suicides state county .fitted .resid .hat .sigma .cooksd .std.resid
20.2 high 1.815 OH Holmes County 2.999 1.183 0.020 0.278 0.119 -4.203
15.3 high 1.672 NY Bronx County 2.684 1.011 0.004 0.280 0.017 -3.563

6.6 Conclusion and Limitations

In this section, we want to know which levels of frequency of mental distress show higher levels of suicides in 364 counties in 6 states that we are investigated. From the box plot and the R-squared, it seems like the high level of mental distress has a higher positive association with the suicides.In addition, we also use ‘high’ as our baseline for the model. However, after our analysis, we would like to say that the even there are significant in positive association between the frequency of mental distress and suicides, the levels of the mental distress doesn’t really matter. The limitations are same as the above, which my states cannot be a presentative for the whole U.S in total as it was not picked randomly. Since the variance of residuals are not similarity to each otheras well as the normality of residuals is very heavy-tailed, I don’t think we have a good model afterall.

7 Analysis 3

7.1 The Variables

  • The outcome in this analysis should be the suicides. As indicated above, the suicides were in percentage, so its unit would be %. Since our outcome has some missing values, we would use complete case on it.
  • Besides two categorical predictor variables, unemployment and freq_mental_distress, the other two predictors are alcohol_impaired_driving_deaths and food_insecurity. In this analysis, I would like to use food_insecurity as the predictor variables.
  • From the table above, food _insecurity has no missing values, and it was calculated as percentage. Therefore, food_insecurity unit woule be %.
  • The following is the tibble of the variables:
data1 <- chr_2022 %>% select('food_insecurity', 'suicides', 'state', 'county')
miss_var_summary(data1) |> kable()
variable n_miss pct_miss
suicides 24 6.185567
food_insecurity 0 0.000000
state 0 0.000000
county 0 0.000000
data1 <- data1 %>% filter(complete.cases(data1))
data1 
# A tibble: 364 × 4
   food_insecurity suicides state county             
             <dbl>    <dbl> <fct> <chr>              
 1            16.9     16.2 MD    Allegany County    
 2             9       12.3 MD    Anne Arundel County
 3            10.7     10.6 MD    Baltimore County   
 4             8.2     10.4 MD    Calvert County     
 5            13.3     14.3 MD    Caroline County    
 6             9.6     12.5 MD    Carroll County     
 7            12.4     17.1 MD    Cecil County       
 8             6.9     10.5 MD    Charles County     
 9            14.7     13.7 MD    Dorchester County  
10             9.7     12.3 MD    Frederick County   
# … with 354 more rows

The structure of the table, which have

str(data1)
tibble [364 × 4] (S3: tbl_df/tbl/data.frame)
 $ food_insecurity: num [1:364] 16.9 9 10.7 8.2 13.3 9.6 12.4 6.9 14.7 9.7 ...
 $ suicides       : num [1:364] 16.2 12.3 10.6 10.4 14.3 ...
 $ state          : Factor w/ 6 levels "MA","MD","NY",..: 2 2 2 2 2 2 2 2 2 2 ...
 $ county         : chr [1:364] "Allegany County" "Anne Arundel County" "Baltimore County" "Calvert County" ...

The number of counties that have complete cases for both variables are 364 counties.

Value of predictor (food_insecurity) and outcome (suicides) for Cuyahoga County, OH: food_insecurity is 13.9% and suicides is 13.41873.

7.2 Research Question

How well does food insecurity predict suicides after accounting for differences between states?

7.3 Visualizing the Data

From the first analysis, we already know that the original distribution of suicides - our outcome - is right-skewed. Due to the normal assumption, I decide to use transformation by using logarithm again on the outcome.

data2 <- mutate(data1, suicides = log(suicides))

The following graph represents all the association plot between food_insecurity and suicides of all states together.

ggplot(data2, aes(x=food_insecurity, y =suicides, color=state)) + geom_point() +
  geom_smooth(method="lm", col ="red", se = FALSE, formula = y ~ x) +
  geom_smooth(method="loess", col ="blue", se=FALSE, formula = y ~x) +
  labs(x ="Food Insecurity (%)", 
       y = "Log of Suicides Percentage",
       title = "Positive association between food insecurity and log of suicides percentage",
       subtitle = "OLS model in red, loess smooth in blue") +
  labs(color="State")

Since this one is the same as the one in Analysis 1, we already know that there is a positive association between food insecurity and suicides. However, it seems like different states have different representation. For example, we see most of pink dots, representing for Virginia, are clustering more on the left side. The red dots, representing for Massachusetts, are more likely to be on the left, below the line. And the green and blue dots, representing for New York and Ohio, respectively, are more likely to accumulate in the middle. Yellow dots, for Maryland, is spreading around.

This graph will represent the association between food_insecurity and suicides by each state.

ggplot(data2, aes(x=food_insecurity, y =suicides, color = state)) +
  geom_point() +
  geom_smooth(method="lm", col ="red", se = FALSE, formula = y ~ x) +
  geom_smooth(method="loess", col ="blue", se=FALSE, formula = y ~x) +
  facet_wrap(state ~ ., ncol = 3) +
   labs(x ="Food Insecurity (%)", 
       y = "Log of Suicides Percentage",
       title = "Association between food insecurity and log of suicides percentage",
       subtitle = "OLS model in red, loess smooth in blue", color = "State")

When we view each of those states separately, we can see that all the states, except for Massachusetts, have a positive association for our variables. For Massachusetts, it is a weak negative association for our variables.

7.4 The Fitted Model

data2 %>% group_by(state) %>% summarize(n = n(), pearson_r = cor(suicides, food_insecurity), r.squared = pearson_r^2) %>% kable(digits = 3)
state n pearson_r r.squared
MA 13 -0.022 0.000
MD 24 0.510 0.260
NY 61 0.378 0.143
OH 87 0.499 0.249
PA 64 0.428 0.183
VA 115 0.444 0.197

In order to use OH as the baseline state, we have to re-level it due to the default settings may have another level of state to be the reference state.

data2 <- mutate(data2, state = relevel(state, "OH"))
model <- lm(suicides ~ food_insecurity + state, data = data2)
broom::tidy(model, conf.int = TRUE, conf.level = 0.90) %>% select(term, estimate, conf.low, conf.high, p.value ) %>% kable(digits = 3)
term estimate conf.low conf.high p.value
(Intercept) 2.123 2.003 2.244 0.000
food_insecurity 0.045 0.037 0.053 0.000
stateMA -0.163 -0.299 -0.027 0.048
stateMD -0.178 -0.279 -0.077 0.004
stateNY -0.200 -0.275 -0.125 0.000
statePA 0.162 0.088 0.236 0.000
stateVA 0.223 0.157 0.289 0.000

Based on the summary of the model, the coefficients are: food_insecurity = 0.045 and intercept is 2.123. The fitted model can be written as: (1) For OH, it is Log(Suicides) = 0.045 * food_insecurity + 2.123 (2) For MA, it is Log(Suicides) = 0.045 * food_insecurity + 1.96 (3) For MD, it is Log(Suicides) = 0.045 * food_insecurity + 1.945 (4) For NY, it is Log(Suicides) = 0.045 * food_insecurity + 1.923 (5) For PA, it is Log(Suicides) = 0.045 * food_insecurity + 2.285 (5) For VA, it is Log(Suicides) = 0.045 * food_insecurity + 2.346 Because the coefficient for food_insecurity is larger than 0, it means that we have a positive association between food_insecurity and suicides. The intercept coefficient means where our line will intersects with the y-axis. And finally, the coefficient for each state is the difference of the intercept compared to the baseline referece, i.e OH.In addition, these coefficients are significant as the low confidences of the interval are above 0 if it is positive number or as the high confidences of the interval are lower than 0 if it is negative number. In this case, for every coefficient, we have them to be significant.

broom::glance(model) %>% select(nobs, r.squared, adj.r.squared, sigma) %>% kable(digits = 3)
nobs r.squared adj.r.squared sigma
364 0.387 0.377 0.262

From the table above, it indicates that the R-squared is 0.387 and residual standard error is 0.262 with 364 observations ## Residual Analysis Here is using the augment function to get the fitted and residual values.

modelaug <- broom::augment(model, data = data2)

Here is plot for Normality in the residuals

p1 <- ggplot(modelaug, aes(sample = .resid)) +
  geom_qq(col = "seagreen") + geom_qq_line(col = "black") + 
  theme(aspect.ratio = 1) + 
  labs(title = "Normal Q-Q: Model 1 Residuals")

p2 <- ggplot(modelaug, aes(x = .resid)) +
  geom_histogram(aes(y = stat(density)), 
                 bins = 20, fill = "seagreen", col = "yellow") +
  stat_function(fun = dnorm, 
                args = list(mean = mean(modelaug$.resid), 
                            sd = sd(modelaug$.resid)),
                col = "black", lwd = 1.5) +
  labs(title = "Hist + Normal Density: Model 1 Residuals")

p3 <- ggplot(modelaug, aes(x = .resid, y = "")) +
  geom_boxplot(fill = "seagreen", outlier.color = "seagreen") + 
  labs(title = "Boxplot: Model 1 Residuals", y = "")

p1 + (p2 / p3 + plot_layout(heights = c(4,1)))

mosaic::favstats(~ .resid, data = modelaug) %>% kable(digits = 1)
min Q1 median Q3 max mean sd n missing
-1 -0.1 0 0.2 0.9 0 0.3 364 0

From the histogram, we might agree that it is normally distributed. However, we can notice that each end of the histogram extends much further than the normal distribution, so it can be considered as heavy-tailed distribution. And this can be confirmed by our QQ-Plot. However, with that, the Normal model may still be reasonable for a batch of data.

And here is the plot for assess residuals vs fitted values for non-linearty

ggplot(modelaug, aes(x = .fitted, y = .resid)) +
  geom_point() +
  geom_smooth(method = "lm", col = "red",
              formula = y ~ x, se = FALSE) + 
  geom_smooth(method = "loess", col = "blue",
              formula = y ~ x, se = FALSE) +
  labs(title = "Model: Residuals vs. Fitted Values", 
       x = "Fitted suicides values", y = "Residuals")

From the plot, we do not see any significant curve when plotting the residuals against the fitted values. However, this is not given the ‘fuzzy football’ pattern, which it seems like the variance across levels of the fitted values are not really similar to each other.

Since I use transform model, I will create another model here to get the models’ prediction for the original outcome and compare to each actual outcome for Cuyahoga County in Ohio. The code is displayed below, with the predicted value as 13.49 while the actual value is 17.054

state1 <- mutate(data1, relevel(state, "OH"))
orgf <- lm(suicides ~ food_insecurity + state, data = data1)
orgfaug <- broom::augment(org, data = data1)

tibble(actual_value = data1[data1$state=="OH" & data1$county =="Cuyahoga County",]$suicides, predicted_value = orgfaug[orgfaug$state=="OH" & orgfaug$county =="Cuyahoga County",]$.fitted) |> kable(digits = 3)
actual_value predicted_value
13.419 17.054

The two counties have the least successful at predicting outcome are Bronx County in New York with absolute residual values are 0.992 and Charlottesville city in Virginia with absolute residual value as 0.971.

modelaugorder <- mutate(modelaug, .resid = abs(.resid))
modelaugorder <- modelaugorder[order(-modelaugorder$.resid),]
modelaugorder[1:2,] |> kable(digits = 3)
food_insecurity suicides state county .fitted .resid .hat .sigma .cooksd .std.resid
16.4 1.672 NY Bronx County 2.664 0.992 0.026 0.257 0.055 -3.829
12.4 1.935 VA Charlottesville city 2.907 0.971 0.010 0.258 0.019 -3.719

7.5 Conclusion and Analysis

For this analysis, I use the same predictor variable as in analysis 1, except that I will consider the association for each 6 states of my choice in order to investigate how well does food insecurity predict the suicides. From the scatter plot above, we could see that even though the overall combination of 6 states gives us a positive association between food insecurity and suicides, when we break it up into different states, Massachusetts returns a negative association while others still positive. With that interest, we furhter fitting our model with using Ohio as the baseline reference. From our model, even the coefficient for food insecurity as other intercepts are significant, but the coefficient is too low (0.045). This indicates that there are only a very weak positive interaction between the food insecurity and suicides, but surprisingly to be a little bit higher than the coefficient when combining all states together (0.040). This may be account to the fact that we use Ohio as the reference state since it has the highest Pearson’s correlation score after all. Moreover, comparing to the original model in analysis 1, breaking up into states doesn’t make a lot of difference as the coefficients of food insecurity as well as the intercept are quite similar. In addition to that, I barely agree that this would give us a right prediction for each state, since for Massachusetts, it still yields a positive association when it is supposed to be a negative one. The limitations are same as above, as mine cannot be considered to be a representative sample for the U.S due to bias. In addition to that, for the normalty of residuals, it seems to be heavy-tailed and almost left-skewed. Therefore, it is very hard to assume that we have a normal distribution for the residuals.

8 Session Information

sessionInfo()
R version 4.2.1 (2022-06-23)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Big Sur ... 10.16

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.2/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.2/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] patchwork_1.1.2.9000 mosaic_1.8.4.2       mosaicData_0.20.3   
 [4] ggformula_0.10.2     Matrix_1.5-3         lattice_0.20-45     
 [7] forcats_0.5.2        stringr_1.4.1        dplyr_1.0.10        
[10] purrr_0.3.5          readr_2.1.3          tidyr_1.2.1         
[13] tibble_3.1.8         ggplot2_3.3.6        tidyverse_1.3.2     
[16] naniar_0.6.1         janitor_2.1.0        rmdformats_1.0.4    
[19] knitr_1.40          

loaded via a namespace (and not attached):
 [1] googledrive_2.0.0   colorspace_2.0-3    deldir_1.0-6       
 [4] ellipsis_0.3.2      ggridges_0.5.4      visdat_0.5.3       
 [7] ggstance_0.3.5      snakecase_0.11.0    htmlTable_2.4.1    
[10] base64enc_0.1-3     fs_1.5.2            rstudioapi_0.14    
[13] farver_2.1.1        bit64_4.0.5         fansi_1.0.3        
[16] lubridate_1.8.0     xml2_1.3.3          splines_4.2.1      
[19] cachem_1.0.6        polyclip_1.10-0     Formula_1.2-4      
[22] jsonlite_1.8.2      broom_1.0.1         cluster_2.1.3      
[25] dbplyr_2.2.1        png_0.1-7           ggforce_0.4.1      
[28] compiler_4.2.1      httr_1.4.4          backports_1.4.1    
[31] assertthat_0.2.1    fastmap_1.1.0       gargle_1.2.1       
[34] cli_3.4.1           tweenr_2.0.2        htmltools_0.5.3    
[37] tools_4.2.1         gtable_0.3.1        glue_1.6.2         
[40] Rcpp_1.0.9          cellranger_1.1.0    jquerylib_0.1.4    
[43] vctrs_0.5.0         nlme_3.1-157        xfun_0.33          
[46] rvest_1.0.3         lifecycle_1.0.3     mosaicCore_0.9.2.1 
[49] googlesheets4_1.0.1 MASS_7.3-57         scales_1.2.1       
[52] vroom_1.6.0         hms_1.1.2           parallel_4.2.1     
[55] RColorBrewer_1.1-3  yaml_2.3.5          curl_4.3.3         
[58] gridExtra_2.3       sass_0.4.2          labelled_2.10.0    
[61] rpart_4.1.16        latticeExtra_0.6-30 stringi_1.7.8      
[64] highr_0.9           checkmate_2.1.0     rlang_1.0.6        
[67] pkgconfig_2.0.3     evaluate_0.16       labeling_0.4.2     
[70] htmlwidgets_1.5.4   bit_4.0.4           tidyselect_1.1.2   
[73] magrittr_2.0.3      bookdown_0.29       R6_2.5.1           
[76] generics_0.1.3      Hmisc_4.7-1         DBI_1.1.3          
[79] mgcv_1.8-40         pillar_1.8.1        haven_2.5.1        
[82] foreign_0.8-82      withr_2.5.0         survival_3.3-1     
[85] nnet_7.3-17         modelr_0.1.9        crayon_1.5.2       
[88] interp_1.1-3        utf8_1.2.2          tzdb_0.3.0         
[91] rmarkdown_2.16      jpeg_0.1-9          grid_4.2.1         
[94] readxl_1.4.1        data.table_1.14.2   reprex_2.0.2       
[97] digest_0.6.30       munsell_0.5.0       bslib_0.4.0        
LS0tCnRpdGxlOiAiRkFDVE9SUyBBRkZFQ1QgU1VJQ0lERVMgUEVSQ0VOVEFHRSBDSFItMjAyMiIKYXV0aG9yOiAiUXV5bmggTmd1eWVuIgpwYXJhbXM6CmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIHJtZGZvcm1hdHM6OmRvd25jdXRlOgogICAgbnVtYmVyX3NlY3Rpb25zOiBUUlVFCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUKLS0tCgojIFByZWxpbWluYXJpZXMKCmBgYHtyIHNldHVwLCBlY2hvPUZBTFNFLCBjYWNoZT1GQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQojIyBEciBMb3ZlIHJlY29tbWVuZHMgeW91IGxlYXZlIHRoaXMgY29kZSBjaHVuayBleGFjdGx5IGFzIGl0IGlzCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkocm1kZm9ybWF0cykKIyMgR2xvYmFsIG9wdGlvbnMKb3B0aW9ucyhtYXgucHJpbnQ9IjEwMCIpCm9wdHNfY2h1bmskc2V0KGNvbW1lbnQ9TkEpCm9wdHNfa25pdCRzZXQod2lkdGg9NzUpCmBgYAoKIyMgTXkgUiBQYWNrYWdlcwoKVGhpcyBjb2RlIHNuaXBwZXQgd2lsbCBsaXN0IHBhY2thZ2VzIHRoYXQgZ29pbmcgdG8gYmUgdXNlZCB0aHJvdWdob3V0IHRoZSBwcm9wb3NhbC4KCmBgYHtyIGxvYWRfcGFja2FnZXNfaGVyZSwgbWVzc2FnZSA9IEZBTFNFfQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkobmFuaWFyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShtb3NhaWMpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkodXRpbHMpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwYXRjaHdvcmspCmBgYAoKIyMgRGF0YSBJbmdlc3QKClRoaXMgZm9sbG93aW5nIGNvZGUgc25pcHBldCB1c2VzIHRvIGxvYWQgdGhlIGRhdGEgb2YgMjAyMiBDb3VudHkgSGVhbHRoIFJhbmtpbmdzIChDSFIpLgoKYGBge3IgcmVhZF9pbl9kYXRhX2hlcmUsIG1lc3NhZ2UgPSBGQUxTRX0KZGF0YV91cmwgPC0gCiAgImh0dHBzOi8vd3d3LmNvdW50eWhlYWx0aHJhbmtpbmdzLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL21lZGlhL2RvY3VtZW50L2FuYWx5dGljX2RhdGEyMDIyLmNzdiIKY2hyXzIwMjJfcmF3IDwtIHJlYWRfY3N2KGRhdGFfdXJsLCBza2lwID0gMSwgZ3Vlc3NfbWF4ID0gNDAwMCwKICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sX3R5cGVzID0gRkFMU0UpCmBgYAoKIyBEYXRhIERldmVsb3BtZW50CgojIyBTZWxlY3RpbmcgTXkgRGF0YQoKRm9yIHRoaXMgcHJvcG9zYWwsIEkgd2lsbCBzZWxlY3QgZnJvbSB0aGUgc2l4ICJzdGF0ZXMiOiAqKk9oaW8gKE9IKSoqLCAqKk5ldyBZb3JrIChOWSkqKiwgKipQZW5uc3lsdmFuaWEgKFBBKSoqLCAqKlZpcmdpbmlhIChWQSkqKiwgKipNYXNzYWNodXNldHRzIChNQSkqKiwgYW5kICoqTWFyeWxhbmQgKE1EKSoqLiBUaGVzZSBzdGF0ZXMgYXJlIGNvbnNpZGVyZWQgYXMgRWFzdCBTZWFib2FyZCBzdGF0ZXMgb2YgdGhlIFUuUyBleGNlcHQgZm9yIE9oaW8sIHdoaWNoIGlzIE1pZHdlc3QuIEkndmUgc2VsZWN0ZWQgZml2ZSB2YXJpYWJsZXMgKipgZnJlcV9tZW50YWxfZGlzdHJlc3NgICh2MTQ1X3Jhd3ZhbHVlKSoqLCAqKmB1bmVtcGxveW1lbnRgICh2MDIzX3Jhd3ZhbHVlKSoqLCAqKmBmb29kX2luc2VjdXJpdHlgICh2MTM5X3Jhd3ZhbHVlKSoqLCAqKmBzdWljaWRlc2AgKHYxNjFfcmF3dmFsdWUpKiosIGFuZCAqKmBhbGNvaG9sX2ltcGFpcmVkX2RyaXZpbmdfZGVhdGhzYCAodjEzNF9yYXd2YWx1ZSkqKiBzaW5jZSBJIGFtIGludGVyZXN0ZWQgaW4gaG93IHVuZW1wbG95bWVudCBjYW4gbWFrZSBhbiBpbXBhY3Qgb24gbWVudGFsIGhlYWx0aCBhcyB3ZWxsIGFzIG90aGVyIGFzcGVjdHMgaW4gbGl2ZXMuCgpGcm9tIHRoYXQsIHRoZSBjaHVuayBvZiBjb2RlIGJlbG93IHdvdWxkIHRyeSB0byBjb21wbGV0ZSB0aGUgZm9sbG93aW5nIHRhc2tzOgoKMS4gICoqVGFzayAxKio6IEZpbHRlciB0aGUgZGF0YSB0byB0aGUgYWN0dWFsIGNvdW50aWVzIHRoYXQgYXJlIHJhbmtlZCBpbiB0aGUgUmFua2luZ3MgKHRoaXMgZWxpbWluYXRlcyBzdGF0ZSBhbmQgVVNBIHRvdGFscywgbWFpbmx5LikgVGhpcyBpcyBkb25lIGJ5IGZpbHRlcmluZyB0byBvbmx5IGtlZXAgcm93cyB0aGF0IGhhdmUgYGNvdW50eV9yYW5rZWRgIGVxdWFsIHRvIGAxYC4KMi4gICoqVGFzayAyKio6IEZpbHRlciA2IHN0YXRlcyB0aGF0IEkndmUgc2VsZWN0ZWQgKHRoZSBgJWluJWAgY29tbWFuZCBsZXRzIHVzIGluY2x1ZGUgYW55IHN0YXRlIGluIHRoZSBsaXN0IHdlIHRoZW4gY3JlYXRlIHdpdGggdGhlIGMoKSBmdW5jdGlvbiksIGluY2x1ZGluZyBPSDogYE9IYCwgYE5ZYCwgYFBBYCwgYFZBYCwgYE1BYCwgYE1EYC4KMy4gICoqVGFzayAzKio6IFNlbGVjdCB0aGUgdmFyaWFibGVzIHRoYXQgSSd2ZSBjaG9zZW4gdG8gdXNlIGluIHRoaXMgc3R1ZHksIGluY2x1ZGluZyB0aGUgMyBtYW5kYXRvcnkgdmFyaWFibGVzIChgZmlwc2NvZGVgLCBgc3RhdGVgLCBhbmQgYGNvdW50eWApOiBgdjE0NWAsIGB2MDIzYCwgYHYxMzlgLCBgdjE2MWAsIGB2MTM0YAogICAgLSAgIFJlbmFtZSB0aGUgNSB2YXJpYWJsZXMgaW50byBtZWFuaW5nZnVsIG5hbWVzLiBUaGVzZSBuYW1lcyBhcmUgdGhlIGFjdHVhbCBtZWFuaW5nIG9mIHRoZSB2YXJpYWJsZXMuCiAgICAtICAgRXhjZXB0IGZvciB0aGUgYHN1aWNpZGVzYCB2YXJpYWJsZSwgdGhlIG90aGVyIGZvdXIgdmFyaWFibGVzIGFyZSBsaXN0ZWQgaW4gcHJvcG9ydGlvbnMsIHNvIEkgd2lsbCByZXNjYWxlIGl0IHRvIHBlcmNlbnRhZ2UuCjQuICBSZXBhaXIgdGhlIGBmaXBzY29kZWAgYnkgY29udmVydGluZyBpdCBpbnRvIGEgY2hhcmFjdGVyIHZhcmlhYmxlIGluc3RlYWQgbnVtZXJpY2FsIHZhbHVlIGFuZCBmYWN0b3JpbmcgdGhlIGBzdGF0ZWAKCmBgYHtyfQpjaHJfMjAyMiA8LSBjaHJfMjAyMl9yYXcgfD4gCiAgICAgICAgICAgIGZpbHRlcihjb3VudHlfcmFua2VkID09IDEpIHw+IAogICAgICAgICAgICBmaWx0ZXIoc3RhdGUgJWluJSBjKCJPSCIsICJOWSIsICJQQSIsICJWQSIsICJNQSIsICJNRCIpKSB8PgogICAgICAgICAgICBzZWxlY3QoZmlwc2NvZGUsIHN0YXRlLCBjb3VudHksIGNvdW50eV9yYW5rZWQsIAogICAgICAgICAgICAgICAgICAgdjE0NV9yYXd2YWx1ZSwgdjAyM19yYXd2YWx1ZSwgdjEzOV9yYXd2YWx1ZSwgdjE2MV9yYXd2YWx1ZSwgdjEzNF9yYXd2YWx1ZSkgfD4KICAgICAgICAgICAgcmVuYW1lKGZyZXFfbWVudGFsX2Rpc3RyZXNzICA9IHYxNDVfcmF3dmFsdWUsCiAgICAgICAgICAgICAgICAgICB1bmVtcGxveW1lbnQgPSB2MDIzX3Jhd3ZhbHVlLAogICAgICAgICAgICAgICAgICAgZm9vZF9pbnNlY3VyaXR5ID0gdjEzOV9yYXd2YWx1ZSwKICAgICAgICAgICAgICAgICAgIHN1aWNpZGVzID0gdjE2MV9yYXd2YWx1ZSwKICAgICAgICAgICAgICAgICAgIGFsY29ob2xfaW1wYWlyZWRfZHJpdmluZ19kZWF0aHMgPSB2MTM0X3Jhd3ZhbHVlKSB8PgogICAgICAgICAgICBtdXRhdGUoZnJlcV9tZW50YWxfZGlzdHJlc3MgID0gMTAwKmZyZXFfbWVudGFsX2Rpc3RyZXNzICwKICAgICAgICAgICAgICAgICAgICB1bmVtcGxveW1lbnQgPSAxMDAqdW5lbXBsb3ltZW50LAogICAgICAgICAgICAgICAgICAgIGZvb2RfaW5zZWN1cml0eSA9IDEwMCpmb29kX2luc2VjdXJpdHksCiAgICAgICAgICAgICAgICAgICAgYWxjb2hvbF9pbXBhaXJlZF9kcml2aW5nX2RlYXRocyA9IDEwMCphbGNvaG9sX2ltcGFpcmVkX2RyaXZpbmdfZGVhdGhzKSB8PgogICAgICAgICAgICBtdXRhdGUoZmlwc2NvZGUgPSBzdHJfcGFkKGZpcHNjb2RlLCA1LCBwYWQ9IjAiKSwgCiAgICAgICAgICAgICAgICAgICBzdGF0ZSA9IGZhY3RvcihzdGF0ZSkpCmBgYAoKIyMjIENoZWNraW5nIEluaXRpYWwgV29yawoKQWZ0ZXIgY29tcGxldGluZyB0aGUgdGFza3MgYWJvdmUsIHdlIHdhbnQgdG8gY2hlY2sgb3VyIGluaXRpYWwgd29yay4gVGhpcyBhbHNvIGNoZWNrcyBpZiB0aGUgdG90YWwgbnVtYmVyIG9mIGNvdW50aWVzIGZyb20gb3VyIHNlbGVjdGVkIHN0YXRlcyBjYW4gYmUgYXJvdW5kIDIwMCAtIDQwMCBjb3VudGllcyBvciBub3QuCgpgYGB7cn0KZ2xpbXBzZShjaHJfMjAyMikgCmBgYAoKU2luY2UgdGhlIG51bWJlciBvZiByb3dzIGlzIDM4OCwgaXQgc2hvdWxkIGJlIGFjY2VwdGVkIGFzIGl0IGZhbGxzIHdpdGhpbiB0aGUgcmVxdWlyZWQgcmFuZ2UuCgojIyMgQ2hlY2tpbmcgbWlzc2luZyB2YWx1ZXMKCigqKlBhcnQgb2YgVGFzayA2KiopIFdlIHdpbGwgY2hlY2sgYWJvdXQgdGhlIG1pc3NpbmcgdmFsdWVzIGZvciBlYWNoIHZhcmlhYmxlcwoKYGBge3J9CmNocl8yMDIyIHw+IAogICAgbWlzc192YXJfc3VtbWFyeSgpIHw+CiAgICBrYWJsZSgpCmBgYAoKIyMjIENoZWNraW5nIHBlcmNlbnRhZ2UgYXZhaWxhYmxlIG9mIG1pc3NpbmctdmFsdWUtY29udGFpbmluZyB2YXJpYWJsZXMgZm9yIGVhY2ggc3RhdGUKCigqKlBhcnQgb2YgVGFzayA3KiopIEZyb20gdGhlIGNvZGUgc25pcHBldCBhYm92ZSwgYHN1aWNpZGVzYCBhbmQgYGFsY29ob2xfaW1wYWlyZWRfZHJpdmluZ19kZWF0aHNgIGhhdmUgbWlzc2luZyB2YWx1ZXMuIEkgd2FudCB0byBzdW1tYXJpemUgdGhpcyBieSB0aGUgc3RhdGUgaW4gb3JkZXIgdG8gY29tcGFyZSB0aGUgcmVzdWx0LgoKMS4gIEZvciBgc3VpY2lkZXNgIHZhcmlhYmxlOgoKYGBge3IgbWVzc2FnZSA9IEZBTFNFfQptb3NhaWM6OmZhdnN0YXRzKHN1aWNpZGVzIH4gc3RhdGUsIGRhdGEgPSBjaHJfMjAyMikgfD4KICAgIHNlbGVjdChzdGF0ZSwgbiwgbWlzc2luZykgfD4KICAgIG11dGF0ZShwY3RfYXZhaWxhYmxlID0gMTAwKihuIC0gbWlzc2luZykvbikgfD4KICAgIGthYmxlKCkKYGBgCgpTaW5jZSB0aGUgYHBjdF92YXJpYWJsZWAgZm9yIGVhY2ggc3RhdGUgaXMgaGlnaGVyIHRoYW4gNzUlIGZvciBgc3VpY2lkZWAsIHdlIHdvdWxkIGxpa2UgdG8gZ28gd2l0aCB0aGUgbmV4dCBjaGVjay11cCBwb2ludC4KCjIuICBGb3IgYGFsY29ob2xfaW1wYWlyZWRfZHJpdmluZ19kZWF0aHNgIHZhcmlhYmxlOgoKYGBge3IgbWVzc2FnZSA9IEZBTFNFfQptb3NhaWM6OmZhdnN0YXRzKGFsY29ob2xfaW1wYWlyZWRfZHJpdmluZ19kZWF0aHMgfiBzdGF0ZSwgZGF0YSA9IGNocl8yMDIyKSB8PgogICAgc2VsZWN0KHN0YXRlLCBuLCBtaXNzaW5nKSB8PgogICAgbXV0YXRlKHBjdF9hdmFpbGFibGUgPSAxMDAqKG4gLSBtaXNzaW5nKS9uKSB8PgogICAga2FibGUoKQpgYGAKClNpbmNlIHRoZSBgcGN0X3ZhcmlhYmxlYCBmb3IgZWFjaCBzdGF0ZSBpcyBoaWdoZXIgdGhhbiA3NSUgZm9yIGBhbGNvaG9sX2ltcGFpcmVkX2RyaXZpbmdfZGVhdGhzYCwgd2Ugd291bGQgbGlrZSB0byBnbyB3aXRoIHRoZSBuZXh0IGNoZWNrLXVwIHBvaW50LgoKIyMjIENoZWNraW5nIG51bWJlcnMgb2YgZGlzdGluY3QgdmFsdWVzIGZvciBlYWNoIHZhcmlhYmxlCgooKipQYXJ0IG9mIFRhc2sgNyoqKSBJIHdvdWxkIGxpa2UgdG8gY2hlY2sgaWYgZWFjaCBjaG9zZW4gdmFyaWFibGUgY29udGFpbnMgYXQgbGVhc3QgMTAgZGlzdGluY3Qgbm9uLW1pc3NpbmcgdmFsdWVzLgoKYGBge3J9CmNocl8yMDIyIHw+IAogICAgc3VtbWFyaXplKGFjcm9zcyhmcmVxX21lbnRhbF9kaXN0cmVzczphbGNvaG9sX2ltcGFpcmVkX2RyaXZpbmdfZGVhdGhzLCB+IG5fZGlzdGluY3QoLikpKSB8PgogICAga2FibGUoKQpgYGAKClNpbmNlIGFsbCBjb25kaXRpb25zIGFyZSBzYXRpc2ZpZWQsIEkgd2lsbCBrZWVwIHdvcmtpbmcgb24gbXkgZGF0YSBzZWxlY3Rpb24uCgojIyBDcmVhdGUgRmFjdG9ycyBGb3IgVHdvIG9mIHRoZSBGaXZlIFZhcmlhYmxlcwoKRm9yICoqVGFzayA0KiosIEkgd2lsbCBwaWNrIHR3byBvdXQgb2YgZml2ZSBjaG9zZW4gdmFyaWFibGVzIGluIG9yZGVyIHRvIGNyZWF0ZSBmYWN0b3JzIGZvciB0aGVzZSB2YXJpYWJsZXMuIEkgY2hvc2UgYHVuZW1wbG95bWVudGAgYW5kIGBmcmVxX21lbnRhbF9kaXN0cmVzc2AgdG8gY3JlYXRlIGZhY3RvcnMuCgojIyMgQ3JlYXRpbmcgQmluYXJ5IENhdGVnb3JpY2FsIFZhcmlhYmxlcwoKLSAgIEZvciBgZnJlcV9tZW50YWxfZGlzdHJlc3NgLCBpdCB3aWxsIGJlIG5hbWVkIGFzIGBtZW50YWxfZGlzdHJlc3NfbGV2ZWxgIGFuZCB0aGlzIHZhcmlhYmxlIHdpbGwgYmUgdXNlZCBhcyBiaW5hcnkgY2F0ZWdvcmljYWwgdmFyaWFibGVzOgogICAgLSAgIGBsb3dgOiBmcmVxdWVuY3kgaXMgYmVsb3cgMTMuMi4KICAgIC0gICBgaGlnaGA6IGZyZXF1ZW5jeSBpcyBlcXVhbCB0byBvciBoaWdoZXIgdGhhbiAxMy4yLgoKVGhlIGN1dC1vZmYgKDEzLjIpIHdhcyBkZXRlcm1pbmVkIGJhc2VkIG9uIHRoZSBmcmVxdWVuY3kgbWVudGFsIGRpc3RyZXNzIGluIFUuUyB2YWx1ZSAoPGh0dHBzOi8vd3d3LmFtZXJpY2FzaGVhbHRocmFua2luZ3Mub3JnL2V4cGxvcmUvYW5udWFsL21lYXN1cmUvbWVudGFsX2Rpc3RyZXNzPikuCgpgYGB7cn0KY2hyXzIwMjIgPC0gY2hyXzIwMjIgfD4KICAgICAgICAgICAgbXV0YXRlKG1lbnRhbF9kaXN0cmVzc19sZXZlbCA9IGNhc2Vfd2hlbigKICAgICAgICAgICAgICAgICAgZnJlcV9tZW50YWxfZGlzdHJlc3MgPCAxMy4yIH4gImxvdyIsCiAgICAgICAgICAgICAgICAgIFRSVUUgfiJoaWdoIiksIAogICAgICAgICAgICAgICAgICBtZW50YWxfZGlzdHJlc3NfbGV2ZWwgPSBmYWN0b3IobWVudGFsX2Rpc3RyZXNzX2xldmVsKSkgCgpgYGAKCkFmdGVyIGNyZWF0aW5nIHRoZSBgbWVudGFsX2Rpc3RyZXNzX2xldmVsYCwgSSB3b3VsZCBsaWtlIHRvIGNoZWNrIHdoZXRoZXIgdGhleSBjYW4gYmUgZmFjdG9yZWQgb3Igbm90LiBJbiBhZGRpdGlvbiwgSSBhbHNvIHdhbnQgdG8gY2hlY2sgaWYgaXQgaGFzIGF0IGxlYXN0IDEwIHJvd3MgZm9yIGVhY2ggbGV2ZWwgb2YgZmFjdG9yIG9yIG5vdC4KCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRX0KbGV2ZWxzKGFzLmZhY3RvcihjaHJfMjAyMiRtZW50YWxfZGlzdHJlc3NfbGV2ZWwpKSAKbW9zYWljOjpmYXZzdGF0cyhmcmVxX21lbnRhbF9kaXN0cmVzcyB+IG1lbnRhbF9kaXN0cmVzc19sZXZlbCwgZGF0YSA9IGNocl8yMDIyKSB8PiBrYWJsZShkaWdpdHMgPSAzKSAKYGBgCgojIyMgQ3JlYXRpbmcgYSBUaHJlZS1DYXRlZ29yeSBWYXJpYWJsZQoKLSAgIEZvciBgdW5lbXBsb3ltZW50YCwgSSB3b3VsZCBuYW1lIGl0IGFzIGB1bmVtcGxveW1lbnRfbGV2ZWxgIGFuZCBmYWN0b3IgaXQgaW50byB0aHJlZSBkaWZmZXJlbnQgbGV2ZWxzOgogICAgLSAgIGBsb3dgOiBwZXJjZW50YWdlIGlzIHVuZGVyIDUlCiAgICAtICAgYG5vcm1hbGA6IHBlcmNlbnRhZ2UgaXMgaGlnaGVyIHRoYW4gNSUgYnV0IGxvd2VyIHRoYW4gNyUuCiAgICAtICAgYGhpZ2hgOiBwZXJjZW50YWdlIGlzIGVxdWFsIHRvIG9yIGhpZ2hlciB0aGFuIDclCgpVc3VhbGx5LCBpdCBpcyBzYWlkIHRoYXQgdGhlIG5vcm1hbCB1bmVtcGxveW1lbnQgcmF0ZSBzaG91bGQgYmUgZnJvbSA0JSB0byA2JS4gVGhlcmVmb3JlLCBJIHdvdWxkIGxpa2UgdG8gaW5kaWNhdGUgdGhhdCBhbnkgdW5lbXBsb3ltZW50IHBlcmNlbnRhZ2UgdW5kZXIgNSUsIHdoaWNoIGlzIHRoZSBtZWFuIG9mIHRoZSBub3JtYWwgdW5lbXBsb3ltZW50IHJhdGUsIHNob3VsZCBiZSBjb25zaWRlcmVkIGEgbG93IGVtcGxveW1lbnQgcmF0ZS4gVGhlbiwgdGhlIHBlcmNlbnRhZ2UgdGhhdCBpcyBoaWdoZXIgdGhhbiB0aGlzIHJhbmdlIHNob3VsZCBiZSBjb25zaWRlcmVkIGFzIGEgaGlnaCB1bmVtcGxveW1lbnQgcmF0ZS4gVGhlcmVmb3JlLCBJIGNhbWUgdXAgd2l0aCB0aGUgbm9ybWFsIHVuZW1wbG95bWVudCByYXRlIGZyb20gNSUgdG8gNyUsIGFuZCBhbnl0aGluZyBoaWdoZXIgdGhhbiB0aGlzIHJhbmdlIHdvdWxkIGJlIGEgaGlnaCByYXRlLgoKYGBge3J9CmNocl8yMDIyIDwtIGNocl8yMDIyIHw+CiAgICAgICAgICAgIG11dGF0ZSh1bmVtcGxveW1lbnRfbGV2ZWwgPSBjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgIHVuZW1wbG95bWVudCA8IDUgfiAibG93IiwKICAgICAgICAgICAgICAgICAgdW5lbXBsb3ltZW50IDwgNyB+ICJub3JtYWwiLAogICAgICAgICAgICAgICAgICBUUlVFIH4gImhpZ2giKSwKICAgICAgICAgICAgICAgICAgdW5lbXBsb3ltZW50X2xldmVsID0gZmFjdG9yKHVuZW1wbG95bWVudF9sZXZlbCkpCmBgYAoKSSB3aWxsIGRvIHRoZSBzYW1lIHRoaW5nIGFzIGFib3ZlIHRvIGNoZWNrIGlmIGl0IGlzIHBvc3NpYmxlIHRvIGZhY3RvciBpbiB0aGUgYHVuZW1wbG95bWVudF9sZXZlbGAgY29sdW1uIG9yIG5vdC4gSWYgeWVzLCBJIGFsc28gd2FudCB0byBrbm93IHdoZXRoZXIgaXQgY29udGFpbnMgYXQgbGVhc3QgMTAgcm93cyBhdCBlYWNoIGxldmVsLgoKYGBge3IgbWVzc2FnZSA9IEZBTFNFfQpsZXZlbHMoYXMuZmFjdG9yKGNocl8yMDIyJHVuZW1wbG95bWVudF9sZXZlbCkpCm1vc2FpYzo6ZmF2c3RhdHModW5lbXBsb3ltZW50IH4gdW5lbXBsb3ltZW50X2xldmVsLCBkYXRhID0gY2hyXzIwMjIpIHw+IGthYmxlKGRpZ2l0cyA9IDMpIApgYGAKCiMjIyBDaGVja2luZyBmYWN0b3JzIG9mIGBzdGF0ZWAgdmFyaWFibGUKCigqKlBhcnQgb2YgVGFzayA3KiopIEZpbmFsbHksIEkgd291bGQgbGlrZSB0byBjaGVjayBpZiB0aGUgYHN0YXRlYCB2YXJpYWJsZSBpcyBhbHJlYWR5IGZhY3RvcmVkIGFzIHdlbGwgYXMgaWYgaXQgY29udGFpbnMgYXQgbGVhc3QgMTAgY291bnRpZXMgZm9yIGVhY2ggbGV2ZWwsIG9yIHN0YXRlLgoKYGBge3IgfQpsZXZlbHMoYXMuZmFjdG9yKGNocl8yMDIyJHN0YXRlKSkKY2hyXzIwMjIgfD4gdGFieWwoc3RhdGUpIHw+IGFkb3JuX3BjdF9mb3JtYXR0aW5nKCkgfD4ga2FibGUoKQpgYGAKCiMjIFN0cnVjdHVyZSBhbmQgU3VtbWFyaXplIG9mIE15IFRpYmJsZQoKKCoqVGFzayA1KiopIFRoaXMgc2VjdGlvbiB3b3VsZCBwcmludCBvdXQgdGhlIHN0cnVjdHVyZSBvZiBteSB0aWJibGUuIEknbSBjaGVja2luZyB0byBzZWUgdGhhdDoKCi0gICBUaGUgZmlyc3Qgcm93cyB0ZWxsIG1lIHRoYXQgdGhpcyBpcyBhIHRpYmJsZSB3aXRoIHNwZWNpZmljYXRpb24gYWJvdXQgaXRzIGRpbWVuc2lvbnMKCi0gICBJIHdpbGwgaGF2ZSBhIGNvbXBsZXRlIHNldCBvZiAzODggcm93cwoKLSAgIEkgaGF2ZSBpbmNsdWRlZCBvbmx5IDExIHZhcmlhYmxlcyB3aGljaCBpbmNsdWRlOgoKICAgIC0gICBUaHJlZSByZXF1aXJlZCB2YXJpYWJsZXMgKGBmaXBzY29kZWAsIGBjb3VudHlgLCBhbmQgYHN0YXRlYCkuIEZvciB0aGUgYGZpcHNjb2RlYCBhbmQgYGNvdW50eWAsIGl0IHNob3VsZCBiZSBjaGFyYWN0ZXJpemVkIGFzIGA8Y2hyPmAuIEZvciBgc3RhdGVgLCBpdCBzaG91bGQgYmUgY29uc2lkZXJlZCBhcyBgRmFjdG9yYCB2YXJpYWJsZXMgd2l0aCBhbiBhcHByb3ByaWF0ZSBudW1iZXIgb2YgbGV2ZWxzLCBgNmAsIGZvbGxvd2VkIGJ5IG51bWVyaWNhbCBjb2RlLlwKICAgIC0gICBNeSBmaXZlIG9yaWdpbmFsIGNob3NlbiB2YXJpYWJsZXMgc2hvdWxkIGJlIHNwZWNpZmllZCBhcyBgPG51bT5gLgogICAgLSAgIE15IG90aGVyIHR3byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMsIGB1bmVtcGxveW1lbnRfcmF0ZWAgYW5kIGBtZW50YWxfZGlzdHJlc3NfbGV2ZWxgIGFyZSBjaGFyYWN0ZXJpemVkIGFzIGBGYWN0b3JgLCBmb2xsb3dlZCBieSBudW1lcmljYWwgY29kZXMuCgogICAgYGBge3IgfQogICAgc3RyKGNocl8yMDIyKQogICAgYGBgCgpUaGUgZm9sbG93aW5nIGNvZGUgc25pcHBldCB3aWxsIHNhdmUgdGhlIHRpYmJsZSBpbnRvIC5SZHMgZmlsZQoKYGBge3J9CnNhdmVSRFMoY2hyXzIwMjIsICJjaHJfMjAyMl9RdXluaF9OZ3V5ZW4ucmRzIikKYGBgCgpXZSBjYW4gdHJ5IHRvIGxvYWQgaXQgd2l0aCB0aGlzIGNvbW1hbmQKCmBgYHtyfQpjaHJfMjAyMl9sb2FkIDwtIHJlYWRSRFMoImNocl8yMDIyX1F1eW5oX05ndXllbi5yZHMiKQpjaHJfMjAyMl9sb2FkCmBgYAoKT3Igd2UgY2FuIHNhdmUgaXQgYXMgLmNzdiBmaWxlCgpgYGB7ciBtZXNzYWdlPUZBTFNFfQp3cml0ZS5jc3YoY2hyXzIwMjIsIGZpbGUgPSJjaHJfMjAyMl9RdXluaF9OZ3V5ZW4uY3N2IiwgY29sLm5hbWVzID0gVFJVRSkKYGBgCgojIENvZGVib29rCgooKipUYXNrIDYqKikgVGhpcyBzZWN0aW9uIHdpbGwgZGlzcGxheSB0aGUgY29kZWJvb2tzIGZvciBlYWNoIG5hbWUgb2YgdmFyaWFibGVzIGluIG15IHRpYmJsZSBhbmQgdGhlaXIgZGVmaW5pdGlvbnMuIFRoaXMgc2VjdGlvbiB3aWxsIGNvbnRhaW4gdHdvIHBhcnRzOiAoMSkgZm9yIHN0YXRlcyBhbmQgKDIpIGZvciB2YXJpYWJsZXMuCgojIyBDb2RlYm9vayBmb3Igc3RhdGVzCgp8IFN0YXRlIE5hbWUgICAgfCBBYmJyZXZpYXRpb24gfCBOdW1iZXJzIG9mIGNvdW50aWVzIHwKfC0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS18CnwgTWFzc2FjaHVzZXR0cyB8IE1BICAgICAgICAgICB8IDE0ICAgICAgICAgICAgICAgICAgfAp8IE1hcnlsYW5kICAgICAgfCBNRCAgICAgICAgICAgfCAyNCAgICAgICAgICAgICAgICAgIHwKfCBOZXcgWW9yayAgICAgIHwgTlkgICAgICAgICAgIHwgNjIgICAgICAgICAgICAgICAgICB8CnwgT2hpbyAgICAgICAgICB8IE9IICAgICAgICAgICB8IDg4ICAgICAgICAgICAgICAgICAgfAp8IFBlbm5zeWx2YW5pYSAgfCBQQSAgICAgICAgICAgfCA2NyAgICAgICAgICAgICAgICAgIHwKfCBWaXJnaW5pYSAgICAgIHwgVkEgICAgICAgICAgIHwgMTE1ICAgICAgICAgICAgICAgICB8CnwgKipUb3RhbCoqICAgICB8IFwtICAgICAgICAgICB8IDM4OCAgICAgICAgICAgICAgICAgfAoKIyMgQ29kZWJvb2sgZm9yIHZhcmlhYmxlcwoKfCBWYXJpYWJsZSAgICAgICAgICAgICAgICAgICAgICAgICAgfCBPcmlnaW5hbCBjb2RlIHwgRGVzY3JpcHRpb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IE51bWJlciBvZiBtaXNzaW5nIHwKfC0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tfAp8IGBmaXBzY29kZWAgICAgICAgICAgICAgICAgICAgICAgICB8IE4vQSAgICAgICAgICAgfCBGSVBTIGNvZGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCAgICAgICAgICAgICAgICAgfAp8IGBzdGF0ZWAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IE4vQSAgICAgICAgICAgfCBJbmNsdWRpbmcgKjYqIGNob3NlbiBzdGF0ZXM6IE1BLCBNRCwgTkosIE5ZLCBPSCwgUEEgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCAgICAgICAgICAgICAgICAgfAp8IGBjb3VudHlgICAgICAgICAgICAgICAgICAgICAgICAgICB8IE4vQSAgICAgICAgICAgfCBDb3VudHkgbmFtZTogaW5jbHVkaW5nIDM4OCBjb3VudGllcyBmcm9tIDYgY2hvc2VuIHN0YXRlcyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCAgICAgICAgICAgICAgICAgfAp8IGBjb3VudHlfcmFua2VkYCAgICAgICAgICAgICAgICAgICB8IE4vQSAgICAgICAgICAgfCBJdCBpcyBjb3VudHkgcmFua2VkLiBBbGwgb2YgdGhlbSBzaG91bGQgZXF1YWxzIDEgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCAgICAgICAgICAgICAgICAgfAp8IGBmcmVxX21lbnRhbF9kaXN0cmVzc2AgICAgICAgICAgICB8IHYxNDUgICAgICAgICAgfCBGcmVxdWVudCBNZW50YWwgRGlzdHJlc3MgUmF0ZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgfAp8IGB1bmVtcGxveW1lbnRgICAgICAgICAgICAgICAgICAgICB8IHYwMjMgICAgICAgICAgfCBVbmVtcGxveW1lbnQgUmF0ZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCAgICAgICAgICAgICAgICAgfAp8IGBmb29kX2luc2VjdXJpdHlgICAgICAgICAgICAgICAgICB8IHYxMzkgICAgICAgICAgfCBGb29kIEluc2VjdXJpdHkgUmF0ZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMCAgICAgICAgICAgICAgICAgfAp8IGBzdWljaWRlc2AgICAgICAgICAgICAgICAgICAgICAgICB8IHYxNjFfcmF3dmFsdWUgfCBTdWljaWRlcyByYXcgdmFsdWUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgMjQgICAgICAgICAgICAgICAgfAp8IGBhbGNvaG9sX2ltcGFpcmVkX2RyaXZpbmdfZGVhdGhzYCB8IHYxMzQgICAgICAgICAgfCBBbGNvaG9sLWltcGFpcmVkIGRyaXZpbmcgZGVhdGhzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgfAp8IGB1bmVtcGxveW1lbnRfbGV2ZWxgICAgICAgICAgICAgICB8IE4vQSAgICAgICAgICAgfCAzIGxldmVsczogKmxvdyogPSB1bmVtcGxveW1lbnQgXDwgNSU7ICpub3JtYWwqID0gNSUgXDw9IHVuZW1wbG95bWVudCByYXRlIFw8IDclOyAqaGlnaCogPSB1bmVtcGxveW1lbnQgXD49IDclIHwgMCAgICAgICAgICAgICAgICAgfAp8IGBtZW50YWxfZGlzdHJlc3NfbGV2ZWxgICAgICAgICAgICB8IE4vQSAgICAgICAgICAgfCAyIGxldmVsczogKmxvdyogPSBmcmVxX21lbnRhbF9kaXN0cmVzcyBcPCAxMy4yJSwgYW5kICpoaWdoKiBmb3IgZnJlcV9tZW50YWxfZGlzdHJlc3MgXD49IDEzLjIlICAgICAgICAgICAgICAgIHwgMCAgICAgICAgICAgICAgICAgfAoKTW9yZSBkZXRhaWxzIGFib3V0IHRoZSBmaXZlIGNob3NlbiB2YXJpYWJsZXMgYXJlIHNwZWNpZmllZCBiZWxvdzoKCi0gICBgZnJlcV9tZW50YWxfZGlzdHJlc3NgIHdhcyBvcmlnaW5hbGx5IHZhcmlhYmxlIGB2MTQ1X3Jhd3ZhbHVlYCwgYW5kIGl0IGlzIGxpc3RlZCBpbiB0aGUgKlF1YWxpdHkgb2YgTGlmZSogc3ViY2F0ZWdvcnkgb2YgKkhlYWx0aCBPdXRjb21lKiBhdCBDb3VudHkgSGVhbHRoIFJhbmtpbmdzLiBJdCBkZXNjcmliZXMgdGhlIHBlcmNlbnRhZ2Ugb2YgYWR1bHRzIHJlcG9ydGluZyAxNCBvciBtb3JlIGRheXMgb2YgcG9vciBtZW50YWwgaGVhbHRoIHBlciBtb250aC4gVGhpcyBkYXRhIHdhcyBvYnRhaW5lZCBmcm9tIEJlaGF2aW9yYWwgUmlzayBGYWN0b3IgU3VydmVpbGxhbmNlIFN5c3RlbSBmcm9tIDIwMTkuIFRoaXMgbWlnaHQgYmUgbXkgKipvdXRjb21lKiogdmFyaWFibGUuCi0gICBgdW5lbXBsb3ltZW50YCB3YXMgb3JpZ2luYWxseSB2YXJpYWJsZSBgdjAyM19yYXd2YWx1ZWAsIGFuZCBpdCBpcyBsaXN0ZWQgaW4gdGhlICpVbmVtcGxveW1lbnQqIG9mICpTb2NpYWwgJiBFY29ub21pYyBGYWN0b3JzKiBzdWJjYXRlZ29yeSBvZiAqSGVhbHRoIEZhY3RvcnMqIGF0IENvdW50eSBIZWFsdGggUmFua2luZ3MuIEl0IGRlc2NyaWJlcyBwZXJjZW50YWdlIG9mIHBvcHVsYXRpb24gYWdlcyAxNiBhbmQgb2xkZXIgdW5lbXBsb3llZCBidXQgc2Vla2luZyB3b3JrLiBUaGlzIGRhdGEgd2FzIG9idGFpbmVkIGZyb20gQnVyZWF1IG9mIExhYm9yIFN0YXRpc3RpY3MgZnJvbSAyMDIwLgotICAgYGZvb2RfaW5zZWN1cml0eWAgd2FzIG9yaWdpbmFsbHkgdmFyaWFibGUgYHYxMzlfcmF3dmFsdWVgLCBhbmQgaXQgaXMgbGlzdGVkIGluIHRoZSAqRGlldCBhbmQgRXhlcmNpc2UqIG9mICpIZWFsdGggQmVoYXZpb3JzKiBzdWJjYXRlZ29yeSBvZiAqSGVhbHRoIEZhY3RvcnMqIGF0IENvdW50eSBIZWFsdGggUmFua2luZ3MuIEl0IGRlc2NyaWJlcyBwZXJjZW50YWdlIG9mIHBvcHVsYXRpb24gd2hvIGxhY2sgYWRlcXVhdGUgYWNjZXNzIHRvIGZvb2QuLiBUaGlzIGRhdGEgd2FzIG9idGFpbmVkIGZyb20gTWFwIHRoZSBNZWFsIEdhcCBmcm9tIDIwMTkuCi0gICBgc3VpY2lkZXNgIHdhcyBvcmlnaW5hbGx5IHZhcmlhYmxlIGB2MTYxX3Jhd3ZhbHVlYCwgYW5kIGl0IGlzIGxpc3RlZCBpbiB0aGUgKkNvbW11bml0eSBTYWZldHkqIG9mICpTb2NpYWwgJiBFY29ub21pYyBGYWN0b3JzKiBzdWJjYXRlZ29yeSBvZiAqSGVhbHRoIEZhY3RvcnMqIGF0IENvdW50eSBIZWFsdGggUmFua2luZ3MuIEl0IGRlc2NyaWJlcyBudW1iZXIgb2YgZGVhdGhzIGR1ZSB0byBzdWljaWRlIHBlciAxMDAsMDAwIHBvcHVsYXRpb24gKGFnZS1hZGp1c3RlZCkuIFRoaXMgZGF0YSB3YXMgb2J0YWluZWQgZnJvbSBOYXRpb25hbCBDZW50ZXIgZm9yIEhlYWx0aCBTdGF0aXN0aWNzIC0gTW9ydGFsaXR5IEZpbGVzIGZyb20gMjAxNiAtIDIwMjAuCi0gICBgYWxjb2hvbF9pbXBhaXJlZF9kcml2aW5nX2RlYXRoc2Agd2FzIG9yaWdpbmFsbHkgdmFyaWFibGUgYHYzNF9yYXd2YWx1ZWAsIGFuZCBpdCBpcyBsaXN0ZWQgaW4gdGhlICpBbGNvaG9sIGFuZCBEcnVnIFVzZSogb2YgKkhlYWx0aCBCZWhhdmlvcnMqIHN1YmNhdGVnb3J5IG9mICpIZWFsdGggRmFjdG9ycyogYXQgQ291bnR5IEhlYWx0aCBSYW5raW5ncy4gSXQgZGVzY3JpYmVzIHBlcmNlbnRhZ2Ugb2YgZHJpdmluZyBkZWF0aHMgd2l0aCBhbGNvaG9sIGludm9sdmVtZW50Li4gVGhpcyBkYXRhIHdhcyBvYnRhaW5lZCBmcm9tIEZhdGFsaXR5IEFuYWx5c2lzIFJlcG9ydGluZyBTeXN0ZW0gZnJvbSAyMDE2IC0gMjAyMC4gXCMgUHJpbnQgYW5kIFN1bW1hcml6ZSBUaWJibGUKCigqKlRhc2sgNyoqKQoKIyMgUHJpbnQgdGhlIFRpYmJsZQoKYGBge3J9CmNocl8yMDIyCmBgYAoKIyMgUmVwb3J0IG9mIE51bWVyaWNhbCBTdW1tYXJpZXMKClRoZW4sIEkgd291bGQgbGlrZSB0byByZXBvcnQgdGhlIG51bWVyaWNhbCBzdW1tYXJpZXMuCgpgYGB7cn0KSG1pc2M6OmRlc2NyaWJlKGNocl8yMDIyKSAKYGBgCgojIyMgRm9yIGBmcmVxX21lbnRhbF9kaXN0cmVzc2AgdmFyaWFibGUKCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRX0KbW9zYWljOjpmYXZzdGF0cyh+ZnJlcV9tZW50YWxfZGlzdHJlc3MsIGRhdGEgPSBjaHJfMjAyMikgfD4KICAgIGthYmxlKGRpZ2l0cyA9IDMpCmBgYAoKIyMjIEZvciBgdW5lbXBsb3ltZW50YCB2YXJpYWJsZQoKYGBge3IgbWVzc2FnZSA9IEZBTFNFfQptb3NhaWM6OmZhdnN0YXRzKH51bmVtcGxveW1lbnQsIGRhdGEgPSBjaHJfMjAyMikgfD4KICAgIGthYmxlKGRpZ2l0cyA9IDMpCmBgYAoKIyMjIEZvciBgZm9vZF9pbnNlY3VyaXR5YCB2YXJpYWJsZQoKYGBge3IgbWVzc2FnZSA9IEZBTFNFfQptb3NhaWM6OmZhdnN0YXRzKH5mb29kX2luc2VjdXJpdHksIGRhdGEgPSBjaHJfMjAyMikgfD4KICAgIGthYmxlKGRpZ2l0cyA9IDMpCmBgYAoKIyMjIEZvciBgc3VpY2lkZXNgIHZhcmlhYmxlCgpgYGB7ciBtZXNzYWdlID0gRkFMU0V9Cm1vc2FpYzo6ZmF2c3RhdHMofnN1aWNpZGVzLCBkYXRhID0gY2hyXzIwMjIpIHw+CiAgICBrYWJsZShkaWdpdHMgPSAzKQpgYGAKCiMjIyBGb3IgYGFsY29ob2xfaW1wYWlyZWRfZHJpdmluZ19kZWF0aHNgIHZhcmlhYmxlCgpgYGB7ciBtZXNzYWdlID0gRkFMU0V9Cm1vc2FpYzo6ZmF2c3RhdHMofmFsY29ob2xfaW1wYWlyZWRfZHJpdmluZ19kZWF0aHMsIGRhdGEgPSBjaHJfMjAyMikgfD4KICAgIGthYmxlKGRpZ2l0cyA9IDMpCgpgYGAKCiMjIyBGb3IgYG1lbnRhbF9kaXN0cmVzc19sZXZlbGAgdmFyaWFibGUKCmBgYHtyfQpjaHJfMjAyMiB8PiB0YWJ5bChtZW50YWxfZGlzdHJlc3NfbGV2ZWwpIHw+IGFkb3JuX3BjdF9mb3JtYXR0aW5nKCkgfD4ga2FibGUoKQpgYGAKCiMjIyBGb3IgYHVuZW1wbG95bWVudF9sZXZlbGAgdmFyaWFibGUKCmBgYHtyfQpjaHJfMjAyMiB8PiB0YWJ5bCh1bmVtcGxveW1lbnRfbGV2ZWwpIHw+IGFkb3JuX3BjdF9mb3JtYXR0aW5nKCkgfD4ga2FibGUoKQpgYGAKCiMjIyBGb3IgYHN0YXRlYCB2YXJpYWJsZQoKSSBhbHJlYWR5IGluY2x1ZGVkIHRoaXMgaW4gYDIuMi4zOiBDaGVja2luZyBmYWN0b3JzIG9mIHN0YXRlIHZhcmlhYmxlYAoKIyBSZXBvcnQgV3JpdGV1cAoKSSBkaWQgbXkgcHJvamVjdCBwcm9wb3NhbCBieSBmb2xsb3dpbmcgaXQgc3RlcC1ieS1zdGVwIGFzIGl0IHdhcyBsaXN0ZWQgb24gdGhlIGNsYXNzIHdlYnNpdGUuIEhvd2V2ZXIsIEkgdGhpbmsgdGhhdCBjYXVzZWQgbWUgYSBsb3Qgb2YgdHJvdWJsZS4gRmlyc3Qgb2YgYWxsLCBJIG9ubHkgc2F3IG90aGVyIHJlcXVpcmVtZW50cyBmb3IgbXkgZGF0YSBzZWxlY3Rpb24gdW50aWwgSSByZWFjaGVkIHRoZSBlbmQgb2YgdGhlIHJlcG9ydC4gSW4gdGhlIG9yaWdpbmFsIHdvcmssIGluc3RlYWQgb2YgY2hvb3NpbmcgVmlyZ2luaWEsIEkgY2hvc2UgR2VvcmdpYS4gVGhpcyBvcmlnaW5hbCB3b3JrIHJlc3VsdGVkIGluIG1vcmUgc3RhdGVzIGFuZCBhZGRlZCBtb3JlIHJvd3MgZm9yIG1lLiBIb3dldmVyLCB3aGVuIGNoZWNraW5nIGFib3V0IHRoZSBhdmFpbGFibGUgcGVyY2VudGFnZSBvZiBub24tbWlzc2luZyB2YWx1ZXMgZm9yIHRoZSB2YXJpYWJsZSB0aGF0IGNvbnRhaW5zIG1pc3NpbmcgdmFsdWVzLCBpdCB0dXJuZWQgb3V0IHRoaXMgcGVyY2VudGFnZSB3YXMgdW5kZXIgNzUlIGZvciBHZW9yZ2lhLiBUaGVyZWZvcmUsIEkgaGFkIHRvIG1ha2UgYW5vdGhlciBzdGF0ZSBzZWxlY3Rpb24gYW5kIGNob3NlIFZpcmdpbmlhIGFzIGFuIGFsdGVybmF0aXZlIHNlbGVjdGlvbi4gSG93ZXZlciwgd2hlbiBJIHJlcGxhY2VkIGl0IHdpdGggVmlyZ2luaWEsIGl0IGdhdmUgbWUgYW5vdGhlciB2YXJpYWJsZSB0aGF0IGNvbnRhaW5zIG1pc3NpbmcgdmFsdWUgaW5zdGVhZCBvbmx5IGhhdmluZyBvbmUgdmFyaWFibGUgdGhhdCBoYXMgbWlzc2luZyB2YWx1ZSBhcyBteSBvcmlnaW5hbCB3b3JrLiBJIGRpZCBub3QgcmVjb2duaXplIHRoaXMgaW4gdGhlIGZpcnN0IHBsYWNlIHVudGlsIEkgd2VudCB0aHJvdWdoIG15IHJlc3VsdCBhZ2Fpbiwgd2hpY2ggbWFkZSBtZSBhZGQgYW5vdGhlciBzbWFsbCBjb2RlIHNuaXBwZXQuIFRoZXJlZm9yZSwgSSB3aXNoIHRoZXNlIGNoZWNrcyBjb3VsZCBiZSBwbGFjZWQgc29tZXdoZXJlIGF0IHRoZSBiZWdpbm5pbmcgaW5zdGVhZCBvZiBpbiB0aGUgbGF0ZXN0IHRhc2suIEJlc2lkZXMgdGhpcyBwYXJ0LCBJIGZlZWwgdGhlIGluc3RydWN0aW9uIHdhcyB3ZWxsLW9yZ2FuaXplZCBhbmQgZWFzeSB0byBmb2xsb3cuCgojIEFuYWx5c2VzIDEKCiMjIFRoZSBWYXJpYWJsZXMKCi0gICBUaGUgb3V0Y29tZSBpbiB0aGlzIGFuYWx5c2lzIHNob3VsZCBiZSB0aGUgYHN1aWNpZGVzYC4gQXMgaW5kaWNhdGVkIGFib3ZlLCB0aGUgc3VpY2lkZXMgd2VyZSBpbiBwZXJjZW50YWdlLCBzbyBpdHMgdW5pdCB3b3VsZCBiZSBgJWAuIFNpbmNlIG91ciBvdXRjb21lIGhhcyBzb21lIG1pc3NpbmcgdmFsdWVzLCB3ZSB3b3VsZCB1c2UgY29tcGxldGUgY2FzZSBvbiBpdC4KLSAgIEJlc2lkZXMgdHdvIGNhdGVnb3JpY2FsIHByZWRpY3RvciB2YXJpYWJsZXMsIGB1bmVtcGxveW1lbnRgIGFuZCBgZnJlcV9tZW50YWxfZGlzdHJlc3NgLCB0aGUgb3RoZXIgdHdvIHByZWRpY3RvcnMgYXJlIGBhbGNvaG9sX2ltcGFpcmVkX2RyaXZpbmdfZGVhdGhzYCBhbmQgYGZvb2RfaW5zZWN1cml0eWAuIEluIHRoaXMgYW5hbHlzaXMsIEkgd291bGQgbGlrZSB0byB1c2UgYGZvb2RfaW5zZWN1cml0eWAgYXMgdGhlIHByZWRpY3RvciB2YXJpYWJsZXMuCi0gICBGcm9tIHRoZSB0YWJsZSBhYm92ZSwgYGZvb2QgX2luc2VjdXJpdHlgIGhhcyBubyBtaXNzaW5nIHZhbHVlcywgYW5kIGl0IHdhcyBjYWxjdWxhdGVkIGFzIHBlcmNlbnRhZ2UuIFRoZXJlZm9yZSwgYGZvb2RfaW5zZWN1cml0eWAgdW5pdCB3b3VsZSBiZSBgJWAuCi0gICBUaGUgZm9sbG93aW5nIGlzIHRoZSB0aWJibGUgb2YgdGhlIHZhcmlhYmxlcy4KCmBgYHtyfQpkYXRhMSA8LSBjaHJfMjAyMiAlPiUgc2VsZWN0KCdmb29kX2luc2VjdXJpdHknLCAnc3VpY2lkZXMnLCAnc3RhdGUnLCAnY291bnR5JykKbWlzc192YXJfc3VtbWFyeShkYXRhMSkgfD4ga2FibGUoKQpgYGAKCmBgYHtyfQojY29tcGxldGUgY2FzZSBmb3IgdGhlIHN1aWNpZGVzCmRhdGExIDwtIGRhdGExICU+JSBmaWx0ZXIoY29tcGxldGUuY2FzZXMoZGF0YTEpKQpkYXRhMSAKYGBgCgpUaGUgc3RydWN0dXJlIG9mIHRoZSB0YWJsZSwgd2hpY2ggaGF2ZQoKYGBge3J9CnN0cihkYXRhMSkKYGBgCgpUaGUgbnVtYmVyIG9mIGNvdW50aWVzIHRoYXQgaGF2ZSBjb21wbGV0ZSBjYXNlcyBmb3IgYm90aCB2YXJpYWJsZXMgYXJlIDM2NCBjb3VudGllcy4KClZhbHVlIG9mIHByZWRpY3RvciAoYGZvb2RfaW5zZWN1cml0eWApIGFuZCBvdXRjb21lIChgc3VpY2lkZXNgKSBmb3IgQ3V5YWhvZ2EgQ291bnR5OiBgZm9vZF9pbnNlY3VyaXR5YCBpcyAxMy45JSBhbmQgYHN1aWNpZGVzYCBpcyAxMy40MTg3My4KCmBgYHtyfQpkYXRhMVtkYXRhMSRzdGF0ZSA9PSJPSCIgJiBkYXRhMSRjb3VudHk9PSJDdXlhaG9nYSBDb3VudHkiLF0gfD4ga2FibGUoKQpgYGAKCiMjIFJlc2VhcmNoIFF1ZXN0aW9uCgoqKldoYXQgaXMgdGhlIG5hdHVyZSBvZiB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiB0aGUgYGZvb2QgaW5zZWN1cml0eWAgYW5kIGBzdWljaWRlc2AsIGluIDM2NCBjb3VudGllcyBhY3Jvc3MgNiBkaWZmZXJlbnQgc3RhdGVzPyoqCgojIyBWaXN1YWxpemluZyB0aGUgRGF0YQpgYGB7cn0KZ2dwbG90KGRhdGExLCBhZXMoeD1mb29kX2luc2VjdXJpdHksIHkgPXN1aWNpZGVzKSkgKyBnZW9tX3BvaW50KCkgKyAKICBsYWJzKHggPSJGb29kIEluc2VjdXJpdHkgKCUpIiwgCiAgICAgICB5ID0gIlN1aWNpZGVzICglKSIsCiAgICAgICB0aXRsZSA9ICJIb3cgY2xvc2VseSBhc3NvY2lhdGVkIGFyZSBmb29kIGluc2VjdXJpdHkgYW5kIHN1aWNpZGVzPyIsCiAgICAgICBzdWJ0aXRsZSA9ICJGb29kIGluc2VjdXJpdHkgYXMgcHJlZGljdG9ycyBhbmQgc3VpY2lkZXMgYXMgb3V0Y29tZXMiKQpgYGAKCkJhc2VkIG9uIHRoZSBmaWd1cmUgYWJvdmUsIGl0IHNlZW1zIGxpa2UgdGhleSBhcmUgc29tZXdoYXQgaGF2aW5nIGEgcG9zaXRpdmUgYXNzb2NpYXRpb24gd2l0aCBlYWNoIG90aGVyIGFzIHRoZSBgZm9vZF9pbnNlY3VyaXR5YCBwZXJjZW50YWdlIGluY3JlYXNlcywgdGhlIGBzdWljaWRlc2AgcGVyY2VudGFnZSBhbHNvIGluY3JlYXNlLiAKYGBge3J9CmdncGxvdChkYXRhMSwgYWVzKHg9Zm9vZF9pbnNlY3VyaXR5LCB5ID1zdWljaWRlcykpICsgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKwogIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iLCBjb2wgPSJyZWQiLCBzZSA9IEZBTFNFLCBmb3JtdWxhID0geSB+IHgpICsKICBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIiwgY29sID0iYmx1ZSIsIHNlPUZBTFNFLCBmb3JtdWxhID0geSB+eCkgKwogIGxhYnMoeCA9IkZvb2QgSW5zZWN1cml0eSAoJSkiLCAKICAgICAgIHkgPSAiU3VpY2lkZXMgKCUpIiwKICAgICAgIHRpdGxlID0gIlBvc2l0aXZlIGFzc29jaWF0aW9uIGJldHdlZW4gZm9vZCBpbnNlY3VyaXR5IGFuZCBzdWljaWRlcyIsCiAgICAgICBzdWJ0aXRsZSA9ICJPTFMgbW9kZWwgaW4gcmVkLCBsb2VzcyBzbW9vdGggaW4gYmx1ZSIpCmBgYApGcm9tIHRoZSBwbG90LCBpdCBzZWVtcyBsaWtlIHRoZXkgYWN0dWFsbHkgaGF2ZSBhIHBvc2l0aXZlIGFzc29jaWF0aW9uIGJldHdlZW4gYGZvb2RfaW5zZWN1cml0eWAgYW5kIGBzdWljaWRlc2AgYXMgcG9pbnRzIGZvbGxvdyB0aGUgc3RyYWlnaHQgbGluZSdzIHBhdGguIE1vcmVvdmVyLCB0aGVyZSBhcmUgY291cGxlcyBvZiBvdXRsaW5lcnMgaW4gdGhlIGdyYXBoLiBJbiBhZGRpdGlvbiwgdGhlIGFzc29jaWF0aW9uIGlzIG5vdCBhIHN0cm9uZiBjb3JyZWxhdGlvbi4gCgojIyBUcmFuc2Zvcm1hdGlvbiBBc3Nlc3NtZW50CkluIG9yZGVyIHRvIGludmVzdGlnYXRlIGFzIGlmIEkgc2hvdWxkIGRvIHRoZSB0cmFuc2Zvcm1hdGlvbiBvciBub3QsIEkgd291bGQgbGlrZSB0byBpbnZlc3RpZ2F0ZSBgc3VpY2lkZXNgIHZhcmlhYmxlLCB3aGljaCBpcyBteSBvdXRjb21lLiAKCmBgYHtyfQpwMSA8LSAgZ2dwbG90KGRhdGExLCBhZXMoc2FtcGxlID0gc3VpY2lkZXMpKSArCiAgZ2VvbV9xcSgpICsgIyBwbG90IHRoZSBwb2ludHMKICBnZW9tX3FxX2xpbmUoY29sID0gImJsdWUiKSArICMgcGxvdCB0aGUgWSA9IFggbGluZQogIHRoZW1lKGFzcGVjdC5yYXRpbyA9IDEpICsgIyBtYWtlIHRoZSBwbG90IHNxdWFyZQogIGxhYnModGl0bGUgPSAiTm9ybWFsIFEtUSBwbG90OiBTaW11bGF0ZWQgc3VpY2lkZXMiKQpwMiA8LSBnZ3Bsb3QoZGF0YTEsIGFlcyh4PXN1aWNpZGVzKSkgKwogICAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeT1zdGF0KGRlbnNpdHkpKSwgYmlucyA9IDIwLCBmaWxsID0icm95YWxibHVlIiwgY29sID0id2hpdGUiKSArCiAgICAgIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIGFyZ3MgPSBsaXN0KG1lYW4gPSBtZWFuKGRhdGExJHN1aWNpZGVzKSwgc2QgPSBzZChkYXRhMSRzdWljaWRlcykpLCBjb2wgPSJyZWQiLCBsd2QgPSAxLjUpICsKICAgICAgbGFicyh0aXRsZT0iRGVuc2l0eSBGdW5jdGlvbjogU3VpY2lkZXMiKQpwMyA8LSBnZ3Bsb3QoZGF0YTEsIGFlcyh4ID0gc3VpY2lkZXMsIHkgPSAiIikpICsKICAgICAgZ2VvbV9ib3hwbG90KGZpbGwgPSAicm95YWxibHVlIiwKICAgICAgb3V0bGllci5jb2xvciA9ICJyb3lhbGJsdWUiKSArCiAgICAgIGxhYnModGl0bGUgPSAiQm94cGxvdDpTdWljaWRlcyIsIHkgPSAiIikKcDEgKyAocDIgLyBwMyArIHBsb3RfbGF5b3V0KGhlaWdodHMgPSBjKDQsMSkpKQptb3NhaWM6OmZhdnN0YXRzKH4gc3VpY2lkZXMsIGRhdGEgPSBkYXRhMSkgJT4lIGthYmxlKGRpZ2l0cyA9IDEpCmBgYAoKQXMgdGhlIGFib3ZlIGdyYXBoLCB3ZSBjYW4gc2VlIHRoYXQgb3VyIGBzdWljaWRlc2AgaGFzIHJpZ2h0LXNrZXdlZCBkaXN0cmlidXRpb24uIAoKYGBge3J9CnAxIDwtICBnZ3Bsb3QoZGF0YTEsIGFlcyhzYW1wbGUgPSBmb29kX2luc2VjdXJpdHkpKSArCiAgZ2VvbV9xcSgpICsgIyBwbG90IHRoZSBwb2ludHMKICBnZW9tX3FxX2xpbmUoY29sID0gImJsdWUiKSArICMgcGxvdCB0aGUgWSA9IFggbGluZQogIHRoZW1lKGFzcGVjdC5yYXRpbyA9IDEpICsgIyBtYWtlIHRoZSBwbG90IHNxdWFyZQogIGxhYnModGl0bGUgPSAiTm9ybWFsIFEtUSBwbG90OiBTaW11bGF0ZWQgZm9vZCBpbnNlY3VyaXR5IikKcDIgPC0gZ2dwbG90KGRhdGExLCBhZXMoeD1mb29kX2luc2VjdXJpdHkpKSArCiAgICAgIGdlb21faGlzdG9ncmFtKGFlcyh5PXN0YXQoZGVuc2l0eSkpLCBiaW5zID0gMjAsIGZpbGwgPSJyb3lhbGJsdWUiLCBjb2wgPSJ3aGl0ZSIpICsKICAgICAgc3RhdF9mdW5jdGlvbihmdW4gPSBkbm9ybSwgYXJncyA9IGxpc3QobWVhbiA9IG1lYW4oZGF0YTEkZm9vZF9pbnNlY3VyaXR5KSwgc2QgPSBzZChkYXRhMSRmb29kX2luc2VjdXJpdHkpKSwgY29sID0icmVkIiwgbHdkID0gMS41KSArCiAgICAgIGxhYnModGl0bGU9IkRlbnNpdHkgRnVuY3Rpb246IEZvb2QgaW5zZWN1cml0eSIpCnAzIDwtIGdncGxvdChkYXRhMSwgYWVzKHggPSBmb29kX2luc2VjdXJpdHksIHkgPSAiIikpICsKICAgICAgZ2VvbV9ib3hwbG90KGZpbGwgPSAicm95YWxibHVlIiwKICAgICAgb3V0bGllci5jb2xvciA9ICJyb3lhbGJsdWUiKSArCiAgICAgIGxhYnModGl0bGUgPSAiQm94cGxvdDogRm9vZCBpbnNlY3VyaXR5IiwgeSA9ICIiKQpwMSArIChwMiAvIHAzICsgcGxvdF9sYXlvdXQoaGVpZ2h0cyA9IGMoNCwxKSkpCm1vc2FpYzo6ZmF2c3RhdHMofiBmb29kX2luc2VjdXJpdHksIGRhdGEgPSBkYXRhMSkgJT4lIGthYmxlKGRpZ2l0cyA9IDEpCmBgYApDb21wYXJpbmcgdG8gdGhlIGBzdWljaWRlcyAgYCwgYGZvb2RfaW5zZWN1cml0eWAgaXMgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIAoKQmVjYXVzZSBvZiB0aGlzLCBJIHdhbnQgdG8gaW52ZXN0aWdhdGUgdGhlIHRyYW5zZm9ybWF0aW9uIG9uIGBzdWljaWRlc2AgdmFyaWFibGUgYnkgYXBwbHlpbmcgbG9nYXJpdGhtIGJhc2UgMTAgb24gdGhpcyB2YXJpYWJsZS4gCmBgYHtyfQpkYXRhMiA8LSBtdXRhdGUoZGF0YTEsIHN1aWNpZGVzID0gbG9nKHN1aWNpZGVzKSkKYGBgCgpgYGB7cn0KcDEgPC0gIGdncGxvdChkYXRhMiwgYWVzKHNhbXBsZSA9IHN1aWNpZGVzKSkgKwogIGdlb21fcXEoKSArICMgcGxvdCB0aGUgcG9pbnRzCiAgZ2VvbV9xcV9saW5lKGNvbCA9ICJibHVlIikgKyAjIHBsb3QgdGhlIFkgPSBYIGxpbmUKICB0aGVtZShhc3BlY3QucmF0aW8gPSAxKSArICMgbWFrZSB0aGUgcGxvdCBzcXVhcmUKICBsYWJzKHRpdGxlID0gIk5vcm1hbCBRLVEgcGxvdDogU2ltdWxhdGVkIHN1aWNpZGVzIikKcDIgPC0gZ2dwbG90KGRhdGEyLCBhZXMoeD1zdWljaWRlcykpICsKICAgICAgZ2VvbV9oaXN0b2dyYW0oYWVzKHk9c3RhdChkZW5zaXR5KSksIGJpbnMgPSAyMCwgZmlsbCA9InJveWFsYmx1ZSIsIGNvbCA9IndoaXRlIikgKwogICAgICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGRub3JtLCBhcmdzID0gbGlzdChtZWFuID0gbWVhbihkYXRhMiRzdWljaWRlcyksIHNkID0gc2QoZGF0YTIkc3VpY2lkZXMpKSwgY29sID0icmVkIiwgbHdkID0gMS41KSArCiAgICAgIGxhYnModGl0bGU9IkRlbnNpdHkgRnVuY3Rpb246IFN1aWNpZGVzIikKcDMgPC0gZ2dwbG90KGRhdGEyLCBhZXMoeCA9IHN1aWNpZGVzLCB5ID0gIiIpKSArCiAgICAgIGdlb21fYm94cGxvdChmaWxsID0gInJveWFsYmx1ZSIsCiAgICAgIG91dGxpZXIuY29sb3IgPSAicm95YWxibHVlIikgKwogICAgICBsYWJzKHRpdGxlID0gIkJveHBsb3Q6IFN1aWNpZGVzIiwgeSA9ICIiKQpwMSArIChwMiAvIHAzICsgcGxvdF9sYXlvdXQoaGVpZ2h0cyA9IGMoNCwxKSkpCm1vc2FpYzo6ZmF2c3RhdHMofiBzdWljaWRlcywgZGF0YSA9IGRhdGExKSAlPiUga2FibGUoZGlnaXRzID0gMSkKYGBgCkFmdGVyIGFwcGx5aW5nIHRyYW5zZm9ybWF0aW9uIG9uIHRoZSBgc3VpY2lkZXNgIHZhcmlhYmxlLCBpdCBsb29rcyBtb3JlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGNvbXBhcmluZyBiZWluZyByaWdodC1za2V3ZWQgZGlzdHJpYnV0aW9uIGFzIGJlZm9yZS4gVGhlcmVmb3JlLCBJIGRlY2lkZSB0byBwZXJmb3JtIHRyYW5zZm9ybWF0aW9uIGJ5IHVzaW5nIGxvZ2FyaXRobSBvbiBvbiBteSBgc3VpY2lkZXNgIG91dGNvbWUuIAoKRHVlIHRvIHRoaXMsIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIGBmb29kX2luc2VjdXJpdHlgIGFuZCBgc3VpY2lkZXNgIHdpbGwgYmUgcmVkb25lLiAKYGBge3J9CmdncGxvdChkYXRhMiwgYWVzKHg9Zm9vZF9pbnNlY3VyaXR5LCB5ID1zdWljaWRlcykpICsgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKwogIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iLCBjb2wgPSJyZWQiLCBzZSA9IEZBTFNFLCBmb3JtdWxhID0geSB+IHgpICsKICBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIiwgY29sID0iYmx1ZSIsIHNlPUZBTFNFLCBmb3JtdWxhID0geSB+eCkgKwogIGxhYnMoeCA9IkZvb2QgSW5zZWN1cml0eSAoJSkiLCAKICAgICAgIHkgPSAiTG9nIG9mIFN1aWNpZGVzIFBlcmNlbnRhZ2UiLAogICAgICAgdGl0bGUgPSAiUG9zaXRpdmUgYXNzb2NpYXRpb24gYmV0d2VlbiBmb29kIGluc2VjdXJpdHkgYW5kIGxvZyBvZiBzdWljaWRlcyBwZXJjZW50YWdlIiwKICAgICAgIHN1YnRpdGxlID0gIk9MUyBtb2RlbCBpbiByZWQsIGxvZXNzIHNtb290aCBpbiBibHVlIikKYGBgCgojIyBUaGUgRml0dGVkIE1vZGVsCk5vdywgd2Ugd291bGQgbGlrZSB0byBjcmVhdGUgb3VyIGZpdHRlZCBtb2RlbDoKYGBge3J9Cm1vZGVsMSA8LSBsbShzdWljaWRlcyB+IGZvb2RfaW5zZWN1cml0eSwgZGF0YSA9IGRhdGEyKQpicm9vbTo6dGlkeShtb2RlbDEsIGNvbmYuaW50ID0gVFJVRSwgY29uZi5sZXZlbCA9IDAuOTApICU+JSBzZWxlY3QodGVybSwgZXN0aW1hdGUsIGNvbmYubG93LCBjb25mLmhpZ2gsIHAudmFsdWUgKSAlPiUKa2FibGUoZGlnaXRzID0gMykKYGBgCkJhc2VkIG9uIHRoZSBzdW1tYXJ5IG9mIHRoZSBtb2RlbCwgdGhlIGNvZWZmaWNpZW50cyBhcmU6IGBmb29kX2luc2VjdXJpdHlgID0gYDAuMDRgIGFuZCBgaW50ZXJjZXB0YCBpcyBgMi4yM2AuIEJlY2F1c2UgdGhlIGNvZWZmaWNpZW50IGZvciBgZm9vZF9pbnNlY3VyaXR5YCBpcyBsYXJnZXIgdGhhbiAwLCBpdCBtZWFucyB0aGF0IHdlIGhhdmUgYSAqKnBvc2l0aXZlIGFzc29jaWF0aW9uKiogYmV0d2VlbiBgZm9vZF9pbnNlY3VyaXR5YCBhbmQgYHN1aWNpZGVzYC4gVGhlIGludGVyY2VwdCBjb2VmZmljaWVudCBtZWFucyB3aGVyZSBvdXIgbGluZSB3aWxsIGludGVyc2VjdHMgd2l0aCB0aGUgeS1heGlzLlRoaXMgY29lZmZpY2llbnRzIGdpdmVzIGVxdWF0aW9uIGZvciBteSBtb2RlbCBpcyBMb2coU3VpY2lkZXMpID0gMC4wNCAqIGBmb29kX2luc2VjdXJpdHlgICsgMi4yMy4gSW4gYWRkaXRpb24sIHRoZXNlIGNvZWZmaWNpZW50cyBhcmUgc2lnbmlmaWNhbnQgYXMgdGhlIGxvdyBjb25maWRlbmNlcyBvZiB0aGUgaW50ZXJ2YWwgYXJlIGFib3ZlIDAgZm9yIGJvdGggYGZvb2RfaW5zZWN1cml0eWAgYW5kIGBpbnRlcmNlcHRgLgoKYGBge3J9CmJyb29tOjpnbGFuY2UobW9kZWwxKSAlPiUgc2VsZWN0KG5vYnMsIHIuc3F1YXJlZCwgYWRqLnIuc3F1YXJlZCwgc2lnbWEpICU+JSBrYWJsZShkaWdpdHMgPSAzKQpgYGAKRnJvbSB0aGUgdGFibGUgYWJvdmUsIGl0IGluZGljYXRlcyB0aGF0IHRoZSBSLXNxdWFyZWQgaXMgMC4xMzcgYW5kIHJlc2lkdWFsIHN0YW5kYXJkIGVycm9yIGlzIDAuMzA5LiAKCkZpbmFsbHksIHdlIG9idGFpbiB0aGUgUGVhcnNvbiBjb3JyZWxhdGlvIGlzIDAuMzcKYGBge3J9CmNvcih5ID0gZGF0YTIkc3VpY2lkZXMsIHggPSBkYXRhMiRmb29kX2luc2VjdXJpdHkpCmBgYAojIyBSZXNpZHVhbCBBbmFseXNpcyAKSGVyZSBpcyB1c2luZyB0aGUgYGF1Z21lbnRgIGZ1bmN0aW9uIHRvIGdldCB0aGUgZml0dGVkIGFuZCByZXNpZHVhbCB2YWx1ZXMuIApgYGB7cn0KbW9kZWwxYXVnIDwtIGJyb29tOjphdWdtZW50KG1vZGVsMSwgZGF0YSA9IGRhdGEyKQpgYGAKCkhlcmUgaXMgcGxvdCBmb3IgTm9ybWFsaXR5IGluIHRoZSByZXNpZHVhbHMgCmBgYHtyLCBtZXNzYWdlID0gRkFMU0V9CnAxIDwtIGdncGxvdChtb2RlbDFhdWcsIGFlcyhzYW1wbGUgPSAucmVzaWQpKSArCiAgZ2VvbV9xcShjb2wgPSAic2VhZ3JlZW4iKSArIGdlb21fcXFfbGluZShjb2wgPSAiYmxhY2siKSArIAogIHRoZW1lKGFzcGVjdC5yYXRpbyA9IDEpICsgCiAgbGFicyh0aXRsZSA9ICJOb3JtYWwgUS1ROiBNb2RlbCAxIFJlc2lkdWFscyIpCgpwMiA8LSBnZ3Bsb3QobW9kZWwxYXVnLCBhZXMoeCA9IC5yZXNpZCkpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IHN0YXQoZGVuc2l0eSkpLCAKICAgICAgICAgICAgICAgICBiaW5zID0gMjAsIGZpbGwgPSAic2VhZ3JlZW4iLCBjb2wgPSAieWVsbG93IikgKwogIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIAogICAgICAgICAgICAgICAgYXJncyA9IGxpc3QobWVhbiA9IG1lYW4obW9kZWwxYXVnJC5yZXNpZCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2QgPSBzZChtb2RlbDFhdWckLnJlc2lkKSksCiAgICAgICAgICAgICAgICBjb2wgPSAiYmxhY2siLCBsd2QgPSAxLjUpICsKICBsYWJzKHRpdGxlID0gIkhpc3QgKyBOb3JtYWwgRGVuc2l0eTogTW9kZWwgMSBSZXNpZHVhbHMiKQoKcDMgPC0gZ2dwbG90KG1vZGVsMWF1ZywgYWVzKHggPSAucmVzaWQsIHkgPSAiIikpICsKICBnZW9tX2JveHBsb3QoZmlsbCA9ICJzZWFncmVlbiIsIG91dGxpZXIuY29sb3IgPSAic2VhZ3JlZW4iKSArIAogIGxhYnModGl0bGUgPSAiQm94cGxvdDogTW9kZWwgMSBSZXNpZHVhbHMiLCB5ID0gIiIpCgpwMSArIChwMiAvIHAzICsgcGxvdF9sYXlvdXQoaGVpZ2h0cyA9IGMoNCwxKSkpCgptb3NhaWM6OmZhdnN0YXRzKH4gLnJlc2lkLCBkYXRhID0gbW9kZWwxYXVnKSAlPiUga2FibGUoZGlnaXRzID0gMSkKYGBgCkZyb20gdGhlIGhpc3RvZ3JhbSwgd2UgbWlnaHQgYWdyZWUgdGhhdCBpdCBpcyBub3JtYWxseSBkaXN0cmlidXRlZC4gSG93ZXZlciwgd2UgY2FuIG5vdGljZSB0aGF0IGVhY2ggZW5kIG9mIHRoZSBoaXN0b2dyYW0gZXh0ZW5kcyBtdWNoIGZ1cnRoZXIgdGhhbiB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiwgc28gaXQgY2FuIGJlIGNvbnNpZGVyZWQgYXMgaGVhdnktdGFpbGVkIGRpc3RyaWJ1dGlvbi4gQW5kIHRoaXMgY2FuIGJlIGNvbmZpcm1lZCBieSBvdXIgUVEtUGxvdC4gSG93ZXZlciwgd2l0aCB0aGF0LCB0aGUgTm9ybWFsIG1vZGVsIG1heSBzdGlsbCBiZSByZWFzb25hYmxlIGZvciBhIGJhdGNoIG9mIGRhdGEuIAoKQW5kIGhlcmUgaXMgdGhlIHBsb3QgZm9yIGFzc2VzcyByZXNpZHVhbHMgdnMgZml0dGVkIHZhbHVlcyBmb3Igbm9uLWxpbmVhcnR5CgpgYGB7cn0KZ2dwbG90KG1vZGVsMWF1ZywgYWVzKHggPSAuZml0dGVkLCB5ID0gLnJlc2lkKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sID0gInJlZCIsCiAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiB4LCBzZSA9IEZBTFNFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIGNvbCA9ICJibHVlIiwKICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHgsIHNlID0gRkFMU0UpICsKICBsYWJzKHRpdGxlID0gIk1vZGVsIDE6IFJlc2lkdWFscyB2cy4gRml0dGVkIFZhbHVlcyIsIAogICAgICAgeCA9ICJGaXR0ZWQgc3VpY2lkZXMgdmFsdWVzIiwgeSA9ICJSZXNpZHVhbHMiKQpgYGAKRnJvbSB0aGUgcGxvdCwgd2UgZG8gbm90IHNlZSBhbnkgc2lnbmlmaWNhbnQgY3VydmUgd2hlbiBwbG90dGluZyB0aGUgcmVzaWR1YWxzIGFnYWluc3QgdGhlIGZpdHRlZCB2YWx1ZXMuIEhvd2V2ZXIsIHRoaXMgaXMgbm90IGdpdmVuIHRoZSAnZnV6enkgZm9vdGJhbGwnIHBhdHRlcm4sIHdoaWNoIGl0IHNlZW1zIGxpa2UgdGhlIHZhcmlhbmNlIGFjcm9zcyBsZXZlbHMgb2YgdGhlIGZpdHRlZCB2YWx1ZXMgYXJlIG5vdCByZWFsbHkgc2ltaWxhciB0byBlYWNoIG90aGVyLiAKClNpbmNlIEkgdXNlIHRyYW5zZm9ybSBtb2RlbCwgSSB3aWxsIGNyZWF0ZSBhbm90aGVyIG1vZGVsIGhlcmUgdG8gZ2V0IHRoZSBtb2RlbHMnIHByZWRpY3Rpb24gZm9yIHRoZSBvcmlnaW5hbCBvdXRjb21lIGFuZCBjb21wYXJlIHRvIGVhY2ggYWN0dWFsIG91dGNvbWUgZm9yIEN1eWFob2dhIENvdW50eSBpbiBPaGlvLiBUaGUgY29kZSBpcyBkaXNwbGF5ZWQgYmVsb3csIHdpdGggdGhlIHByZWRpY3RlZCB2YWx1ZSBhcyAxNy4wNSB3aGlsZSB0aGUgYWN0dWFsIHZhbHVlIGlzIDEzLjQyCmBgYHtyfQpvcmcgPC0gbG0oc3VpY2lkZXMgfiBmb29kX2luc2VjdXJpdHksIGRhdGEgPSBkYXRhMSkKb3JnYXVnIDwtIGJyb29tOjphdWdtZW50KG9yZywgZGF0YSA9IGRhdGExKQoKdGliYmxlKGFjdHVhbF92YWx1ZSA9IGRhdGExW2RhdGExJHN0YXRlPT0iT0giICYgZGF0YTEkY291bnR5ID09IkN1eWFob2dhIENvdW50eSIsXSRzdWljaWRlcywgcHJlZGljdGVkX3ZhbHVlID0gb3JnYXVnW29yZ2F1ZyRzdGF0ZT09Ik9IIiAmIG9yZ2F1ZyRjb3VudHkgPT0iQ3V5YWhvZ2EgQ291bnR5IixdJC5maXR0ZWQpIHw+IGthYmxlKGRpZ2l0cyA9IDMpCgpgYGAKVGhlIHR3byBjb3VudGllcyBoYXZlIHRoZSBsZWFzdCBzdWNjZXNzZnVsIGF0IHByZWRpY3Rpbmcgb3V0Y29tZSBhcmUgQnJvbnggQ291bnR5IGluIE5ldyBZb3JrIHdpdGggYWJzb2x1dGUgcmVzaWR1YWwgdmFsdWVzIGFyZSAxLjIyIGFuZCBLaW5ncyBDb3VudHkgaW4gTmV3IFlvcmsgd2l0aCBhYnNvbHV0ZSByZXNpZHVhbCB2YWx1ZSBhcyAxLjExCmBgYHtyfQptb2RlbDFhdWdvcmRlciA8LSBtdXRhdGUobW9kZWwxYXVnLCAucmVzaWQgPSBhYnMoLnJlc2lkKSkKbW9kZWwxYXVnb3JkZXIgPC0gbW9kZWwxYXVnb3JkZXJbb3JkZXIoLW1vZGVsMWF1Z29yZGVyJC5yZXNpZCksXQptb2RlbDFhdWdvcmRlclsxOjIsXSB8PiBrYWJsZShkaWdpdHMgPSAzKQpgYGAKIyMgQ29uY2x1c2lvbnMgYW5kIExpbWl0YXRpb25zCkZvciB0aGlzIGFuYWx5c2lzLCB3ZSBhcmUgaW50ZXJlc3RlZCBpbiB0aGUgbmF0dXJlIG9mIGFzc29jaWF0aW9uIGJldHdlZW4gdGhlIGZvb2QgaW5zZWN1cml0eSBhbmQgc3VpY2lkZXMgaW4gMzY0IGNvdW50aWVzLiBGcm9tIHRoZSBhbmFseXNpcyBhYm92ZSwgaW5zdGVhZCBvZiB1c2luZyB0aGUgcGVyY2VudGFnZSBvZiBzdWljaWRlcywgd2UgdXNlIGl0cyBsb2cgdG8gbWFrZSBzdXJlIGl0IGhhcyB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiBiZWNhdXNlIHRoZSBvcmlnaW5hbCB2YWx1ZXMgYXJlIHJpZ2h0LXNrZXdlZC4gQmFzZWQgb24gdGhlIGFuYWx5c2lzLCAgaXQgYXBwZWFycyB0aGF0IHRoZXJlIGlzIGEgcG9zaXRpdmUgYXNzb2NpYXRpb24gYmV0d2VlbiB0aGUgZm9vZCBpbnNlY3VyaXR5IGFuZCBzdWljaWRlcy4gSXQgYXBwZWFycyB0aGF0IHRoZSBhc3NvY2lhdGlvbiBpcyBtb2RlcmF0ZSwgYXMgdGhlIFBlYXJzb24ncyBjb3JyZWxhdGlvbiBpcyBvbmx5IDAuMzcuIEhvd2V2ZXIsIGl0IGFwcGVhcnMgdG8gYmUgYSBzaWduaWZpY2FudCBsaW5lYXIgcmVncmVzc2lvbiBhcyBib3RoIHRoZSBlc3RpbWF0aW9uIGZvciB0aGUgZm9vZCBpbnNlY3VyaXR5IGFuZCBzdWljaWRlcyBoYXZlIHRoZWlyIGNvbmZpZGVuY2UgbG93IGxldmVsIGFyZSBhYm92ZSAwLiBXaXRoIHRoYXQsIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIHRoZSBmb29kIGluc2VjdXJpdHkgYW5kIHN1aWNpZGVzIGNhbiBiZSBleHByZXNzZWQgYXM6IGBMb2coU3VpY2lkZXMpID0gMC4wNCAqIGZvb2RfaW5zZWN1cml0eSArIDIuMjNgLiAKCkZyb20gdGhlIHJlc2lkdWFsIHBsb3QsIHdlIGFjdHVhbGx5IGRvbid0IHNlZSBhbnkgJ2Z1enp5IGZvb3RiYWxsJyBwYXR0ZXJuLCB3aGljaCBpcyB1bmRlcnN0YW5kYWJsZSBzaW5jZSB0aGUgZGlzdHJpYnV0aW9uIG9mIG91ciByZXNpZHVhbHMgYXJlIG5vdCBub3JtYWxpdHkgYXMgaXQgaXMgYSBoZWF2eS10YWlsZWQgZGlzdHJpYnV0aW9uLiBUaGVyZWZvcmUsIHdlIGNhbiBjb25jbHVkZSB0aGF0IHRoZSB2YXJpYW5jZSB2YXJpYW5jZSBhY3Jvc3MgbGV2ZWxzIG9mIHRoZSBmaXR0ZWQgdmFsdWVzIGFyZSBub3QgcmVhbGx5IHNpbWlsYXIgdG8gZWFjaCBvdGhlci4gSW4gYWRkaXRpb24sIGFub3RoZXIgbGltaXRhdGlvbnMgaW4gdGhpcyBzdHVkeSBpcyB0aGF0IHRoZSBzdGF0ZXMgSSBjaG9zZSBjYW5ub3QgdXNlIHRvIGJlIGEgcmVwcmVzZW50YXRpdmUgc2FtcGxlIG9mIHRoZSBVLlMuIFNpbmNlIEkgc2VsZWN0ZWQgaXQgYmFzZWQgb24gbXkgZmF2b3JpdGUsIGluc3RlYWQgb2YgbWFraW5nIHJhbmRvbSBjaG9pY2VzLCBhbmQgdGhleSBhbGwgcGxhY2UgaW4gdGhlIEVhc3Rlcm4gb2YgdGhlIFUuUy4gSWYgSSB3YW50IHRvIG1ha2UgYSByZXByZXNlbnRhdGl2ZSBzYW1wbGUgb2YgdGhlIFUuUywgSSB3b3VsZCBiZXR0ZXIgY2hvb3NlIHRoZW0gcmFuZG9tbHkgb3IgSSBzaG91bGQgcGljayBvbmUgc3RhdGUgZnJvbSBkaWZmZXJlbnQgY29hc3QuIAoKIyBBbmFseXNpcyAyCgojIyBUaGUgdmFyaWFibGVzCkkgY2hvb3NlIGB1bmVtcGxveW1lbnRgIGFuZCBgZnJlcV9tZW50YWxfZGlzdHJlc3NgIHRvIGJlIG15IHR3byBjYXRlZ29yaWNhbCBwcmVkaWN0b3JzLiBJbiB0aGlzIHJlcG9ydCwgSSB3b3VsZCBsaWtlIHRvIHVzZSBgZnJlcV9tZW50YWxfZGlzdHJlc3NgIGFzIG15IGNob2ljZSBmb3IgY2F0ZWdvcmljYWwgcHJlZGljdG9yLiBJdCB3YXMgY2FsY3VsYXRlZCBpbiBwZXJjZW50YWdlIChgJWApIC5UaGUgb3V0Y29tZSB3b3VsZCBiZSB0aGUgc2FtZSwgd2hpY2ggaXMgYHN1aWNpZGVzYCAoJSkKCmBgYHtyfQpkYXRhMyA8LSBjaHJfMjAyMiAlPiUgc2VsZWN0KCdmcmVxX21lbnRhbF9kaXN0cmVzcycsICdtZW50YWxfZGlzdHJlc3NfbGV2ZWwnICwnc3VpY2lkZXMnLCAnc3RhdGUnLCAnY291bnR5JykKbWlzc192YXJfc3VtbWFyeShkYXRhMykgfD4ga2FibGUoKQpgYGAKCmBgYHtyfQojY29tcGxldGUgY2FzZSBmb3IgdGhlIHN1aWNpZGVzCmRhdGEzIDwtIGRhdGEzICU+JSBmaWx0ZXIoY29tcGxldGUuY2FzZXMoZGF0YTMpKQpkYXRhMwpgYGAKVGhlIHN0cnVjdHVyZSBvZiB0aGUgdGFibGUsIHdoaWNoIGhhdmUKCmBgYHtyfQpzdHIoZGF0YTMpCmBgYApUaGUgbnVtYmVyIG9mIGNvdW50aWVzIHRoYXQgaGF2ZSBjb21wbGV0ZSBjYXNlcyBmb3IgYm90aCB2YXJpYWJsZXMgYXJlIDM2NCBjb3VudGllcy4KClZhbHVlIG9mIHByZWRpY3RvciAoYGZyZXFfbWVudGFsX2Rpc3RyZXNzYCkgYW5kIG91dGNvbWUgKGBzdWljaWRlc2ApIGZvciBDdXlhaG9nYSBDb3VudHk6IGZyZXFfbWVudGFsX2Rpc3RyZXNzIGlzIDE2LjclIGFuZCBzdWljaWRlcyBpcyAxMy40MTklLgpgYGB7cn0KZGF0YTNbZGF0YTMkc3RhdGUgPT0iT0giICYgZGF0YTMkY291bnR5PT0iQ3V5YWhvZ2EgQ291bnR5IixdIHw+IGthYmxlKGRpZ2l0cyA9IDMpCmBgYAojIyBSZXNlYXJjaCBRdWVzdGlvbgoKKipEb2VzIGxvdyBvciBoaWdoIGZyZXF1ZW5jeSBvZiBtZW50YWwgZGlzdHJlc3Mgc2hvdyBoaWdoZXIgbGV2ZWxzIG9mIHN1aWNpZGVzLCBpbiAzNjQgY291bnRpZXMgaW4gdGhlIHN0YXRlcyBvZj8qKgoKIyMgVmlzdWFsaXppbmcgRGF0YSAKRnJvbSB0aGUgZmlyc3QgYW5hbHlzaXMsIHdlIGFscmVhZHkga25vdyB0aGF0IHRoZSBvcmlnaW5hbCBkaXN0cmlidXRpb24gb2YgYHN1aWNpZGVzYCAtIG91ciBvdXRjb21lIC0gaXMgcmlnaHQtc2tld2VkLiBEdWUgdG8gdGhlIG5vcm1hbCBhc3N1bXB0aW9uLCBJIGRlY2lkZSB0byB1c2UgdHJhbnNmb3JtYXRpb24gYnkgdXNpbmcgbG9nYXJpdGhtIGFnYWluIG9uIHRoZSBvdXRjb21lLiAKCmBgYHtyfQpkYXRhNCA8LSBtdXRhdGUoZGF0YTMsIHN1aWNpZGVzID0gbG9nKHN1aWNpZGVzKSkKc3RyKGRhdGE0KQpgYGAKYGBge3J9CmdncGxvdChkYXRhID0gZGF0YTQsIGFlcyh4ID0gbWVudGFsX2Rpc3RyZXNzX2xldmVsICwgeSA9IHN1aWNpZGVzLCBjb2xvciA9IG1lbnRhbF9kaXN0cmVzc19sZXZlbCkpICsKICAgIGdlb21fYm94cGxvdCgpICsKICAgIGxhYnModGl0bGUgPSAiU3VpY2lkZXMgYnkgTGV2ZWxzIG9mIE1lbnRhbCBEaXN0cmVzcyIsCiAgICAgICAgIHN1YnRpdGxlID0gIkxvZyBvZiBQZXJjZW50YWdlIG9mIFN1aWNpZGVzIiwKICAgICAgICAgeCA9ICJMZXZlbHMgb2YgTWVudGFsIERpc3RyZXNzIiwKICAgICAgICAgeSA9ICJMb2cgb2YgUGVyY2VudGFnZSBvZiBTdWljaWRlcyIpICsKICBsYWJzKGNvbG9yPSJNZW50YWwgRGlzdHJlc3MgTGV2ZWwiKQpgYGAKRnJvbSB0aGUgYm94IHBsb3QgYWJvdmUsIHdlIGNhbiBzZWUgYSBxdWl0ZSBiaWcgc2hpZnQgb2YgbG9nIG9mIHBlcmNlbnRhZ2Ugb2Ygc3VpY2lkZXMgaW4gYGhpZ2hgIGxldmVsIG9mIG1lbnRhbCBkaXN0cmVzcyBjb21wYXJpbmcgdG8gdGhlIGBsb3dgIGxldmVsIG9mIG1lbnRhbCBkaXN0cmVzcyBhcyB0aGUgbG9nIG9mIHBlcmNlbnRhZ2Ugb2Ygc3VpY2lkZXMgaW4gYGhpZ2hgIGxldmVsIG9mIG1lbnRhbCBkaXN0cmVzcyBpcyBoaWdoZXIuIAoKIyMgVGhlIEZpdHRlZCBNb2RlbApJZiB3ZSBkb24ndCBjb25zaWRlciBhYm91dCB0aGUgYmFzZWxpbmUgc3RhdGU6CmBgYHtyfQptb2RlbDIgPC0gbG0oc3VpY2lkZXMgfiBmcmVxX21lbnRhbF9kaXN0cmVzcywgZGF0YSA9IGRhdGE0KQpicm9vbTo6dGlkeShtb2RlbDIsIGNvbmYuaW50ID0gVFJVRSwgY29uZi5sZXZlbCA9IDAuOTApICU+JSBzZWxlY3QodGVybSwgZXN0aW1hdGUsIGNvbmYubG93LCBjb25mLmhpZ2gsIHAudmFsdWUgKSAlPiUKa2FibGUoZGlnaXRzID0gMykKYGBgCkJhc2VkIG9uIHRoZSBzdW1tYXJ5IG9mIHRoZSBtb2RlbCwgdGhlIGNvZWZmaWNpZW50cyBhcmU6IGBmcmVxX21lbnRhbF9kaXN0cmVzc2AgPSBgMC4wODFgIGFuZCBgaW50ZXJjZXB0YCBpcyBgMi4yM2AuIEJlY2F1c2UgdGhlIGNvZWZmaWNpZW50IGZvciBmcmVxX21lbnRhbF9kaXN0cmVzcyBpcyBsYXJnZXIgdGhhbiAwLCBpdCBtZWFucyB0aGF0IHdlIGhhdmUgYSAqKnBvc2l0aXZlIGFzc29jaWF0aW9uKiogYmV0d2VlbiBgZnJlcV9tZW50YWxfZGlzdHJlc3NgIGFuZCBgc3VpY2lkZXNgLiBUaGUgaW50ZXJjZXB0IGNvZWZmaWNpZW50IG1lYW5zIHdoZXJlIG91ciBsaW5lIHdpbGwgaW50ZXJzZWN0cyB3aXRoIHRoZSB5LWF4aXMuIFRoaXMgY29lZmZpY2llbnRzIGdpdmVzIGVxdWF0aW9uIGZvciBteSBtb2RlbCBpcyBgTG9nKFN1aWNpZGVzKSA9IDAuMDgxICogZnJlcV9tZW50YWxfZGlzdHJlc3MgKyAxLjQyYC4gSW4gYWRkaXRpb24sIHRoZXNlIGNvZWZmaWNpZW50cyBhcmUgc2lnbmlmaWNhbnQgYXMgdGhlIGxvdyBjb25maWRlbmNlcyBvZiB0aGUgaW50ZXJ2YWwgYXJlIGFib3ZlIDAgZm9yIGJvdGggZm9vZF9pbnNlY3VyaXR5IGFuZCBpbnRlcmNlcHQuCgpXZSBhbHNvIHdhbnQgdG8gc2VlIGhvdyB0aGUgYXNzb2NpYXRpb24gdmFyaWVzIGJ5IHRoZSBmcmVxX21lbnRhbF9kaXN0cmVzcwpgYGB7cn0KZGF0YTQgJT4lIGdyb3VwX2J5KG1lbnRhbF9kaXN0cmVzc19sZXZlbCkgJT4lIHN1bW1hcml6ZShuID0gbigpLCBwZWFyc29uX3IgPSBjb3Ioc3VpY2lkZXMsIGZyZXFfbWVudGFsX2Rpc3RyZXNzKSwgci5zcXVhcmVkID0gcGVhcnNvbl9yXjIpICU+JQogIGthYmxlKGRpZ2l0cyA9IDMpCmBgYApGcm9tIHRoZSB0YWJsZSwgb25seSBgaGlnaGAgbGV2ZWwgb2YgbWVudGFsIGRpc3RyZXNzIGhhcyBoaWdoZXIgUGVhcnNvbidzIGNvcnJlbGF0aW9uIGNvbXBhcmluZyB0byBgbG93YC4gVGhlcmVmb3JlLCBpdCBpcyBtb3JlIGZpdHRlZCBpbiB0aGlzIG1vZGVsIGNvbXBhcmluZyB0byB0aGUgYGxvd2AuIAoKRm9yIHRoZSBiYXNlbGluZSByZWZlcmVuY2UsIEkgd2lsbCBjaG9vc2UgImhpZ2giIGFzIGRlZmF1bHQsIGFuZCByZXBsYWNlIHRoZSBwcmV2aW91cyBtb2RlbCB0aGF0IHdlIGhhdmU6CmBgYHtyfQptb2RlbDIgPC0gbG0oc3VpY2lkZXMgfiBmcmVxX21lbnRhbF9kaXN0cmVzcyArIG1lbnRhbF9kaXN0cmVzc19sZXZlbCwgZGF0YSA9IGRhdGE0KQpicm9vbTo6dGlkeShtb2RlbDIsIGNvbmYuaW50ID0gVFJVRSwgY29uZi5sZXZlbCA9IDAuOTApICU+JSBzZWxlY3QodGVybSwgZXN0aW1hdGUsIGNvbmYubG93LCBjb25mLmhpZ2gsIHAudmFsdWUgKSAlPiUKa2FibGUoZGlnaXRzID0gMykKYGBgCkJhc2VkIG9uIHRoZSBzdW1tYXJ5IG9mIHRoZSBtb2RlbCwgdGhlIGNvZWZmaWNpZW50cyBhcmU6IGBmcmVxX21lbnRhbF9kaXN0cmVzc2AgPSBgMC4wNjRgIGFuZCBgaW50ZXJjZXB0YCBpcyBgMS43YC4KVGhlIGZpdHRlZCBtb2RlbCBjYW4gYmUgd3JpdHRlbiBhczogKDEpIGZvciBsb3cgbGV2ZWwgb2YgbWVudGFsIGRpc3RyZXNzLCBpdCBpcyBgTG9nKFN1aWNpZGVzKSA9IDAuMDY0ICogZnJlcV9tZW50YWxfZGlzdHJlc3MgKyAxLjUyIGAgYW5kICgyKSBmb3IgaGlnaCBsZXZlbCBvZiBtZW50YWwgZGlzdHJlc3MsIGl0IGlzIGBMb2coU3VpY2lkZXMpID0gMC4wNjQgKiBmcmVxX21lbnRhbF9kaXN0cmVzcyArIDEuNyBgCkJlY2F1c2UgdGhlIGNvZWZmaWNpZW50IGZvciBmcmVxX21lbnRhbF9kaXN0cmVzcyBpcyBsYXJnZXIgdGhhbiAwLCBpdCBtZWFucyB0aGF0IHdlIGhhdmUgYSAqKnBvc2l0aXZlIGFzc29jaWF0aW9uKiogYmV0d2VlbiBgZnJlcV9tZW50YWxfZGlzdHJlc3NgIGFuZCBgc3VpY2lkZXNgLiBUaGUgaW50ZXJjZXB0IGNvZWZmaWNpZW50IG1lYW5zIHdoZXJlIG91ciBsaW5lIHdpbGwgaW50ZXJzZWN0cyB3aXRoIHRoZSB5LWF4aXMuIEluIGFkZGl0aW9uLCB0aGVzZSBjb2VmZmljaWVudHMgYXJlIHNpZ25pZmljYW50IGFzIHRoZSBsb3cgY29uZmlkZW5jZXMgb2YgdGhlIGludGVydmFsIGFyZSBhYm92ZSAwIGZvciBib3RoIGZvb2RfaW5zZWN1cml0eSBhbmQgaW50ZXJjZXB0LiBIb3dldmVyLCB0aGUgYmFzZWxpbmUgcmVmZXJlbmNlIGlzIG5vdCB0aGF0IHNpZ25pZmljYW50IGltcG9ydGFudCwgYXMgdGhlIGludGVydmFsIG9mICBjb2VmZmljaWVudCBmb3IgdGhlIGJhc2VsaW5lIHJlZmVyZW5jZSBpbmNsdWRlcyAwLiAKCmBgYHtyfQpicm9vbTo6Z2xhbmNlKG1vZGVsMikgJT4lIHNlbGVjdChub2JzLCByLnNxdWFyZWQsIGFkai5yLnNxdWFyZWQsIHNpZ21hKSAlPiUga2FibGUoZGlnaXRzID0gMykKYGBgCkZyb20gdGhlIHRhYmxlIGFib3ZlLCBpdCBpbmRpY2F0ZXMgdGhhdCB0aGUgYFItc3F1YXJlZGAgaXMgYDAuMjczYCBhbmQgYHJlc2lkdWFsIHN0YW5kYXJkIGVycm9yYCBpcyBgMC4yODRgIHdpdGggYDM2NCBvYnNlcnZhdGlvbnNgCgojIyBQcmVkaWN0aW9uIEFuYWx5c2lzIApIZXJlIGlzIHVzaW5nIHRoZSBhdWdtZW50IGZ1bmN0aW9uIHRvIGdldCB0aGUgZml0dGVkIGFuZCByZXNpZHVhbCB2YWx1ZXMuCmBgYHtyfQptb2RlbDJhdWcgPC0gYnJvb206OmF1Z21lbnQobW9kZWwyLCBkYXRhID0gZGF0YTQpCmBgYAoKSGVyZSBpcyB0aGUgcGxvdCBmb3IgTm9ybWFsaXR5CmBgYHtyfQpwMSA8LSBnZ3Bsb3QobW9kZWwyYXVnLCBhZXMoc2FtcGxlID0gLnJlc2lkKSkgKwogIGdlb21fcXEoY29sID0gInNlYWdyZWVuIikgKyBnZW9tX3FxX2xpbmUoY29sID0gImJsYWNrIikgKyAKICB0aGVtZShhc3BlY3QucmF0aW8gPSAxKSArIAogIGxhYnModGl0bGUgPSAiTm9ybWFsIFEtUTogTW9kZWwgMiBSZXNpZHVhbHMiKQoKcDIgPC0gZ2dwbG90KG1vZGVsMmF1ZywgYWVzKHggPSAucmVzaWQpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSBzdGF0KGRlbnNpdHkpKSwgCiAgICAgICAgICAgICAgICAgYmlucyA9IDIwLCBmaWxsID0gInNlYWdyZWVuIiwgY29sID0gInllbGxvdyIpICsKICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGRub3JtLCAKICAgICAgICAgICAgICAgIGFyZ3MgPSBsaXN0KG1lYW4gPSBtZWFuKG1vZGVsMmF1ZyQucmVzaWQpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkID0gc2QobW9kZWwyYXVnJC5yZXNpZCkpLAogICAgICAgICAgICAgICAgY29sID0gImJsYWNrIiwgbHdkID0gMS41KSArCiAgbGFicyh0aXRsZSA9ICJIaXN0ICsgTm9ybWFsIERlbnNpdHk6IE1vZGVsIDIgUmVzaWR1YWxzIikKCnAzIDwtIGdncGxvdChtb2RlbDJhdWcsIGFlcyh4ID0gLnJlc2lkLCB5ID0gIiIpKSArCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAic2VhZ3JlZW4iLCBvdXRsaWVyLmNvbG9yID0gInNlYWdyZWVuIikgKyAKICBsYWJzKHRpdGxlID0gIkJveHBsb3Q6IE1vZGVsIDIgUmVzaWR1YWxzIiwgeSA9ICIiKQoKcDEgKyAocDIgLyBwMyArIHBsb3RfbGF5b3V0KGhlaWdodHMgPSBjKDQsMSkpKQptb3NhaWM6OmZhdnN0YXRzKH4gLnJlc2lkLCBkYXRhID0gbW9kZWwyYXVnKSAlPiUga2FibGUoZGlnaXRzID0gMSkKYGBgCkZyb20gdGhlIGhpc3RvZ3JhbSwgd2UgbWlnaHQgYWdyZWUgdGhhdCBpdCBpcyBub3JtYWxseSBkaXN0cmlidXRlZC4gSG93ZXZlciwgd2UgY2FuIG5vdGljZSB0aGF0IGVhY2ggZW5kIG9mIHRoZSBoaXN0b2dyYW0gZXh0ZW5kcyBtdWNoIGZ1cnRoZXIgdGhhbiB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiwgc28gaXQgY2FuIGJlIGNvbnNpZGVyZWQgYXMgaGVhdnktdGFpbGVkIGRpc3RyaWJ1dGlvbi4gQW5kIHRoaXMgY2FuIGJlIGNvbmZpcm1lZCBieSBvdXIgUVEtUGxvdC4gSG93ZXZlciwgd2l0aCB0aGF0LCB0aGUgTm9ybWFsIG1vZGVsIG1heSBzdGlsbCBiZSByZWFzb25hYmxlIGZvciBhIGJhdGNoIG9mIGRhdGEuIAoKYGBge3J9CmdncGxvdChtb2RlbDJhdWcsIGFlcyh4ID0gLmZpdHRlZCwgeSA9IC5yZXNpZCkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbCA9ICJyZWQiLAogICAgICAgICAgICAgIGZvcm11bGEgPSB5IH4geCwgc2UgPSBGQUxTRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiLCBjb2wgPSAiYmx1ZSIsCiAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiB4LCBzZSA9IEZBTFNFKSArCiAgbGFicyh0aXRsZSA9ICJNb2RlbCAyOiBSZXNpZHVhbHMgdnMuIEZpdHRlZCBWYWx1ZXMiLCAKICAgICAgIHggPSAiRml0dGVkIHN1aWNpZGVzIHZhbHVlcyIsIHkgPSAiUmVzaWR1YWxzIikKYGBgCkZyb20gdGhlIHBsb3QsIHdlIGNhbiBzZWUgdGhlIGN1cnZlIHdoZW4gcGxvdHRpbmcgdGhlIHJlc2lkdWFscyBhZ2FpbnN0IHRoZSBmaXR0ZWQgdmFsdWVzLiBJbiBhZGRpdGlvbiwgdGhpcyBpcyBub3QgZ2l2ZW4gdGhlIOKAmGZ1enp5IGZvb3RiYWxs4oCZIHBhdHRlcm4sIHdoaWNoIGl0IHNlZW1zIGxpa2UgdGhlIHZhcmlhbmNlIGFjcm9zcyBsZXZlbHMgb2YgdGhlIGZpdHRlZCB2YWx1ZXMgYXJlIG5vdCByZWFsbHkgc2ltaWxhciB0byBlYWNoIG90aGVyLgoKU2luY2UgSSB1c2UgdHJhbnNmb3JtIG1vZGVsLCBJIHdpbGwgY3JlYXRlIGFub3RoZXIgbW9kZWwgaGVyZSB0byBnZXQgdGhlIG1vZGVsc+KAmSBwcmVkaWN0aW9uIGZvciB0aGUgb3JpZ2luYWwgb3V0Y29tZSBhbmQgY29tcGFyZSB0byBlYWNoIGFjdHVhbCBvdXRjb21lIGZvciBDdXlhaG9nYSBDb3VudHkgaW4gT2hpby4gVGhlIGNvZGUgaXMgZGlzcGxheWVkIGJlbG93LCB3aXRoIHRoZSBwcmVkaWN0ZWQgdmFsdWUgYXMgMTYuNzAgd2hpbGUgdGhlIGFjdHVhbCB2YWx1ZSBpcyAxNi43MjMKCmBgYHtyfQpvcmcyIDwtIGxtKHN1aWNpZGVzIH4gZnJlcV9tZW50YWxfZGlzdHJlc3MgKyBtZW50YWxfZGlzdHJlc3NfbGV2ZWwsIGRhdGEgPSBkYXRhMykKb3JnMmF1ZyA8LSBicm9vbTo6YXVnbWVudChvcmcyLCBkYXRhID0gZGF0YTMpCgp0aWJibGUoYWN0dWFsX3ZhbHVlID0gZGF0YTNbZGF0YTMkc3RhdGU9PSJPSCIgJiBkYXRhMyRjb3VudHkgPT0iQ3V5YWhvZ2EgQ291bnR5IixdJGZyZXFfbWVudGFsX2Rpc3RyZXNzLCBwcmVkaWN0ZWRfdmFsdWUgPSBvcmcyYXVnW29yZzJhdWckc3RhdGU9PSJPSCIgJiBvcmcyYXVnJGNvdW50eSA9PSJDdXlhaG9nYSBDb3VudHkiLF0kLmZpdHRlZCkgfD4ga2FibGUoZGlnaXRzID0gMykKYGBgClRoZSB0d28gY291bnRpZXMgaGF2ZSB0aGUgbGVhc3Qgc3VjY2Vzc2Z1bCBhdCBwcmVkaWN0aW5nIG91dGNvbWUgYXJlIEhvbG1lcyBDb3VudHkgaW4gT2hpbyB3aXRoIGFic29sdXRlIHJlc2lkdWFsIHZhbHVlcyBhcmUgMS4yMzkgYW5kIENvdmluZ3RvbiBjaXR5IGluIFZpcmdpbmlhIHdpdGggYWJzb2x1dGUgcmVzaWR1YWwgdmFsdWUgYXMgMC45OTIKCmBgYHtyfQptb2RlbDJhdWdvcmRlciA8LSBtdXRhdGUobW9kZWwyYXVnLCAucmVzaWQgPSBhYnMoLnJlc2lkKSkKbW9kZWwyYXVnb3JkZXIgPC0gbW9kZWwyYXVnb3JkZXJbb3JkZXIoLW1vZGVsMmF1Z29yZGVyJC5yZXNpZCksXQptb2RlbDJhdWdvcmRlclsxOjIsXSB8PiBrYWJsZShkaWdpdHMgPSAzKQpgYGAKIyMgQ29uY2x1c2lvbiBhbmQgTGltaXRhdGlvbnMKSW4gdGhpcyBzZWN0aW9uLCB3ZSB3YW50IHRvIGtub3cgd2hpY2ggbGV2ZWxzIG9mIGZyZXF1ZW5jeSBvZiBtZW50YWwgZGlzdHJlc3Mgc2hvdyBoaWdoZXIgbGV2ZWxzIG9mIHN1aWNpZGVzIGluIDM2NCBjb3VudGllcyBpbiA2IHN0YXRlcyB0aGF0IHdlIGFyZSBpbnZlc3RpZ2F0ZWQuIEZyb20gdGhlIGJveCBwbG90IGFuZCB0aGUgUi1zcXVhcmVkLCBpdCBzZWVtcyBsaWtlIHRoZSBoaWdoIGxldmVsIG9mIG1lbnRhbCBkaXN0cmVzcyBoYXMgYSBoaWdoZXIgcG9zaXRpdmUgYXNzb2NpYXRpb24gd2l0aCB0aGUgc3VpY2lkZXMuSW4gYWRkaXRpb24sIHdlIGFsc28gdXNlICdoaWdoJyBhcyBvdXIgYmFzZWxpbmUgZm9yIHRoZSBtb2RlbC4gSG93ZXZlciwgYWZ0ZXIgb3VyIGFuYWx5c2lzLCB3ZSB3b3VsZCBsaWtlIHRvIHNheSB0aGF0IHRoZSBldmVuIHRoZXJlIGFyZSBzaWduaWZpY2FudCBpbiBwb3NpdGl2ZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIHRoZSBmcmVxdWVuY3kgb2YgbWVudGFsIGRpc3RyZXNzIGFuZCBzdWljaWRlcywgdGhlIGxldmVscyBvZiB0aGUgbWVudGFsIGRpc3RyZXNzIGRvZXNuJ3QgcmVhbGx5IG1hdHRlci4gClRoZSBsaW1pdGF0aW9ucyBhcmUgc2FtZSBhcyB0aGUgYWJvdmUsIHdoaWNoIG15IHN0YXRlcyBjYW5ub3QgYmUgYSBwcmVzZW50YXRpdmUgZm9yIHRoZSB3aG9sZSBVLlMgaW4gdG90YWwgYXMgaXQgd2FzIG5vdCBwaWNrZWQgcmFuZG9tbHkuIFNpbmNlIHRoZSB2YXJpYW5jZSBvZiByZXNpZHVhbHMgYXJlIG5vdCBzaW1pbGFyaXR5IHRvIGVhY2ggb3RoZXJhcyB3ZWxsIGFzIHRoZSBub3JtYWxpdHkgb2YgcmVzaWR1YWxzIGlzIHZlcnkgaGVhdnktdGFpbGVkLCBJIGRvbid0IHRoaW5rIHdlIGhhdmUgYSBnb29kIG1vZGVsIGFmdGVyYWxsLiAKCiMgQW5hbHlzaXMgMwoKIyMgVGhlIFZhcmlhYmxlcyAKLSAgIFRoZSBvdXRjb21lIGluIHRoaXMgYW5hbHlzaXMgc2hvdWxkIGJlIHRoZSBgc3VpY2lkZXNgLiBBcyBpbmRpY2F0ZWQgYWJvdmUsIHRoZSBzdWljaWRlcyB3ZXJlIGluIHBlcmNlbnRhZ2UsIHNvIGl0cyB1bml0IHdvdWxkIGJlIGAlYC4gU2luY2Ugb3VyIG91dGNvbWUgaGFzIHNvbWUgbWlzc2luZyB2YWx1ZXMsIHdlIHdvdWxkIHVzZSBjb21wbGV0ZSBjYXNlIG9uIGl0LgotICAgQmVzaWRlcyB0d28gY2F0ZWdvcmljYWwgcHJlZGljdG9yIHZhcmlhYmxlcywgYHVuZW1wbG95bWVudGAgYW5kIGBmcmVxX21lbnRhbF9kaXN0cmVzc2AsIHRoZSBvdGhlciB0d28gcHJlZGljdG9ycyBhcmUgYGFsY29ob2xfaW1wYWlyZWRfZHJpdmluZ19kZWF0aHNgIGFuZCBgZm9vZF9pbnNlY3VyaXR5YC4gSW4gdGhpcyBhbmFseXNpcywgSSB3b3VsZCBsaWtlIHRvIHVzZSBgZm9vZF9pbnNlY3VyaXR5YCBhcyB0aGUgcHJlZGljdG9yIHZhcmlhYmxlcy4KLSAgIEZyb20gdGhlIHRhYmxlIGFib3ZlLCBgZm9vZCBfaW5zZWN1cml0eWAgaGFzIG5vIG1pc3NpbmcgdmFsdWVzLCBhbmQgaXQgd2FzIGNhbGN1bGF0ZWQgYXMgcGVyY2VudGFnZS4gVGhlcmVmb3JlLCBgZm9vZF9pbnNlY3VyaXR5YCB1bml0IHdvdWxlIGJlIGAlYC4KLSAgIFRoZSBmb2xsb3dpbmcgaXMgdGhlIHRpYmJsZSBvZiB0aGUgdmFyaWFibGVzOgpgYGB7cn0KZGF0YTEgPC0gY2hyXzIwMjIgJT4lIHNlbGVjdCgnZm9vZF9pbnNlY3VyaXR5JywgJ3N1aWNpZGVzJywgJ3N0YXRlJywgJ2NvdW50eScpCm1pc3NfdmFyX3N1bW1hcnkoZGF0YTEpIHw+IGthYmxlKCkKYGBgCgpgYGB7cn0KZGF0YTEgPC0gZGF0YTEgJT4lIGZpbHRlcihjb21wbGV0ZS5jYXNlcyhkYXRhMSkpCmRhdGExIApgYGAKClRoZSBzdHJ1Y3R1cmUgb2YgdGhlIHRhYmxlLCB3aGljaCBoYXZlCmBgYHtyfQpzdHIoZGF0YTEpCmBgYAoKVGhlIG51bWJlciBvZiBjb3VudGllcyB0aGF0IGhhdmUgY29tcGxldGUgY2FzZXMgZm9yIGJvdGggdmFyaWFibGVzIGFyZSAzNjQgY291bnRpZXMuCgpWYWx1ZSBvZiBwcmVkaWN0b3IgKGBmb29kX2luc2VjdXJpdHlgKSBhbmQgb3V0Y29tZSAoYHN1aWNpZGVzYCkgZm9yIEN1eWFob2dhIENvdW50eSwgT0g6IGBmb29kX2luc2VjdXJpdHlgIGlzIGAxMy45JWAgYW5kIGBzdWljaWRlc2AgaXMgYDEzLjQxODczYC4KCiMjIFJlc2VhcmNoIFF1ZXN0aW9uCioqSG93IHdlbGwgZG9lcyBmb29kIGluc2VjdXJpdHkgcHJlZGljdCBzdWljaWRlcyBhZnRlciBhY2NvdW50aW5nIGZvciBkaWZmZXJlbmNlcyBiZXR3ZWVuIHN0YXRlcz8qKgoKIyMgVmlzdWFsaXppbmcgdGhlIERhdGEgCkZyb20gdGhlIGZpcnN0IGFuYWx5c2lzLCB3ZSBhbHJlYWR5IGtub3cgdGhhdCB0aGUgb3JpZ2luYWwgZGlzdHJpYnV0aW9uIG9mIHN1aWNpZGVzIC0gb3VyIG91dGNvbWUgLSBpcyByaWdodC1za2V3ZWQuIER1ZSB0byB0aGUgbm9ybWFsIGFzc3VtcHRpb24sIEkgZGVjaWRlIHRvIHVzZSB0cmFuc2Zvcm1hdGlvbiBieSB1c2luZyBsb2dhcml0aG0gYWdhaW4gb24gdGhlIG91dGNvbWUuCmBgYHtyfQpkYXRhMiA8LSBtdXRhdGUoZGF0YTEsIHN1aWNpZGVzID0gbG9nKHN1aWNpZGVzKSkKYGBgCgpUaGUgZm9sbG93aW5nIGdyYXBoIHJlcHJlc2VudHMgYWxsIHRoZSBhc3NvY2lhdGlvbiBwbG90IGJldHdlZW4gYGZvb2RfaW5zZWN1cml0eWAgYW5kIGBzdWljaWRlc2Agb2YgYWxsIHN0YXRlcyB0b2dldGhlci4gCmBgYHtyfQpnZ3Bsb3QoZGF0YTIsIGFlcyh4PWZvb2RfaW5zZWN1cml0eSwgeSA9c3VpY2lkZXMsIGNvbG9yPXN0YXRlKSkgKyBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iLCBjb2wgPSJyZWQiLCBzZSA9IEZBTFNFLCBmb3JtdWxhID0geSB+IHgpICsKICBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIiwgY29sID0iYmx1ZSIsIHNlPUZBTFNFLCBmb3JtdWxhID0geSB+eCkgKwogIGxhYnMoeCA9IkZvb2QgSW5zZWN1cml0eSAoJSkiLCAKICAgICAgIHkgPSAiTG9nIG9mIFN1aWNpZGVzIFBlcmNlbnRhZ2UiLAogICAgICAgdGl0bGUgPSAiUG9zaXRpdmUgYXNzb2NpYXRpb24gYmV0d2VlbiBmb29kIGluc2VjdXJpdHkgYW5kIGxvZyBvZiBzdWljaWRlcyBwZXJjZW50YWdlIiwKICAgICAgIHN1YnRpdGxlID0gIk9MUyBtb2RlbCBpbiByZWQsIGxvZXNzIHNtb290aCBpbiBibHVlIikgKwogIGxhYnMoY29sb3I9IlN0YXRlIikKYGBgClNpbmNlIHRoaXMgb25lIGlzIHRoZSBzYW1lIGFzIHRoZSBvbmUgaW4gQW5hbHlzaXMgMSwgd2UgYWxyZWFkeSBrbm93IHRoYXQgdGhlcmUgaXMgYSBwb3NpdGl2ZSBhc3NvY2lhdGlvbiBiZXR3ZWVuICAgICBgZm9vZCBpbnNlY3VyaXR5YCBhbmQgYHN1aWNpZGVzYC4gSG93ZXZlciwgaXQgc2VlbXMgbGlrZSBkaWZmZXJlbnQgc3RhdGVzIGhhdmUgZGlmZmVyZW50IHJlcHJlc2VudGF0aW9uLiBGb3IgZXhhbXBsZSwgd2Ugc2VlIG1vc3Qgb2YgcGluayBkb3RzLCByZXByZXNlbnRpbmcgZm9yIFZpcmdpbmlhLCBhcmUgY2x1c3RlcmluZyBtb3JlIG9uIHRoZSBsZWZ0IHNpZGUuIFRoZSByZWQgZG90cywgcmVwcmVzZW50aW5nIGZvciBNYXNzYWNodXNldHRzLCBhcmUgbW9yZSBsaWtlbHkgdG8gYmUgb24gdGhlIGxlZnQsIGJlbG93IHRoZSBsaW5lLiBBbmQgdGhlIGdyZWVuIGFuZCBibHVlIGRvdHMsIHJlcHJlc2VudGluZyBmb3IgTmV3IFlvcmsgYW5kIE9oaW8sIHJlc3BlY3RpdmVseSwgYXJlIG1vcmUgbGlrZWx5IHRvIGFjY3VtdWxhdGUgaW4gdGhlIG1pZGRsZS4gWWVsbG93IGRvdHMsIGZvciBNYXJ5bGFuZCwgaXMgc3ByZWFkaW5nIGFyb3VuZC4gCgpUaGlzIGdyYXBoIHdpbGwgcmVwcmVzZW50IHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIGBmb29kX2luc2VjdXJpdHlgIGFuZCBgc3VpY2lkZXNgIGJ5IGVhY2ggc3RhdGUuIApgYGB7cn0KZ2dwbG90KGRhdGEyLCBhZXMoeD1mb29kX2luc2VjdXJpdHksIHkgPXN1aWNpZGVzLCBjb2xvciA9IHN0YXRlKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsIGNvbCA9InJlZCIsIHNlID0gRkFMU0UsIGZvcm11bGEgPSB5IH4geCkgKwogIGdlb21fc21vb3RoKG1ldGhvZD0ibG9lc3MiLCBjb2wgPSJibHVlIiwgc2U9RkFMU0UsIGZvcm11bGEgPSB5IH54KSArCiAgZmFjZXRfd3JhcChzdGF0ZSB+IC4sIG5jb2wgPSAzKSArCiAgIGxhYnMoeCA9IkZvb2QgSW5zZWN1cml0eSAoJSkiLCAKICAgICAgIHkgPSAiTG9nIG9mIFN1aWNpZGVzIFBlcmNlbnRhZ2UiLAogICAgICAgdGl0bGUgPSAiQXNzb2NpYXRpb24gYmV0d2VlbiBmb29kIGluc2VjdXJpdHkgYW5kIGxvZyBvZiBzdWljaWRlcyBwZXJjZW50YWdlIiwKICAgICAgIHN1YnRpdGxlID0gIk9MUyBtb2RlbCBpbiByZWQsIGxvZXNzIHNtb290aCBpbiBibHVlIiwgY29sb3IgPSAiU3RhdGUiKQpgYGAKV2hlbiB3ZSB2aWV3IGVhY2ggb2YgdGhvc2Ugc3RhdGVzIHNlcGFyYXRlbHksIHdlIGNhbiBzZWUgdGhhdCBhbGwgdGhlIHN0YXRlcywgZXhjZXB0IGZvciBNYXNzYWNodXNldHRzLCBoYXZlIGEgcG9zaXRpdmUgYXNzb2NpYXRpb24gZm9yIG91ciB2YXJpYWJsZXMuIEZvciBNYXNzYWNodXNldHRzLCBpdCBpcyBhIHdlYWsgbmVnYXRpdmUgYXNzb2NpYXRpb24gZm9yIG91ciB2YXJpYWJsZXMuIAoKIyMgVGhlIEZpdHRlZCBNb2RlbApgYGB7cn0KZGF0YTIgJT4lIGdyb3VwX2J5KHN0YXRlKSAlPiUgc3VtbWFyaXplKG4gPSBuKCksIHBlYXJzb25fciA9IGNvcihzdWljaWRlcywgZm9vZF9pbnNlY3VyaXR5KSwgci5zcXVhcmVkID0gcGVhcnNvbl9yXjIpICU+JSBrYWJsZShkaWdpdHMgPSAzKQpgYGAKCkluIG9yZGVyIHRvIHVzZSBgT0hgIGFzIHRoZSBiYXNlbGluZSBzdGF0ZSwgd2UgaGF2ZSB0byByZS1sZXZlbCBpdCBkdWUgdG8gdGhlIGRlZmF1bHQgc2V0dGluZ3MgbWF5IGhhdmUgYW5vdGhlciBsZXZlbCBvZiBzdGF0ZSB0byBiZSB0aGUgcmVmZXJlbmNlIHN0YXRlLgpgYGB7cn0KZGF0YTIgPC0gbXV0YXRlKGRhdGEyLCBzdGF0ZSA9IHJlbGV2ZWwoc3RhdGUsICJPSCIpKQptb2RlbCA8LSBsbShzdWljaWRlcyB+IGZvb2RfaW5zZWN1cml0eSArIHN0YXRlLCBkYXRhID0gZGF0YTIpCmJyb29tOjp0aWR5KG1vZGVsLCBjb25mLmludCA9IFRSVUUsIGNvbmYubGV2ZWwgPSAwLjkwKSAlPiUgc2VsZWN0KHRlcm0sIGVzdGltYXRlLCBjb25mLmxvdywgY29uZi5oaWdoLCBwLnZhbHVlICkgJT4lIGthYmxlKGRpZ2l0cyA9IDMpCmBgYApCYXNlZCBvbiB0aGUgc3VtbWFyeSBvZiB0aGUgbW9kZWwsIHRoZSBjb2VmZmljaWVudHMgYXJlOiBgZm9vZF9pbnNlY3VyaXR5YCA9IGAwLjA0NWAgYW5kIGBpbnRlcmNlcHRgIGlzIGAyLjEyM2AuClRoZSBmaXR0ZWQgbW9kZWwgY2FuIGJlIHdyaXR0ZW4gYXM6IAooMSkgRm9yIE9ILCBpdCBpcyBgTG9nKFN1aWNpZGVzKSA9IDAuMDQ1ICogZm9vZF9pbnNlY3VyaXR5ICsgMi4xMjMgYCAKKDIpIEZvciBNQSwgaXQgaXMgYExvZyhTdWljaWRlcykgPSAwLjA0NSAqIGZvb2RfaW5zZWN1cml0eSArIDEuOTZgCigzKSBGb3IgTUQsIGl0IGlzIGBMb2coU3VpY2lkZXMpID0gMC4wNDUgKiBmb29kX2luc2VjdXJpdHkgKyAxLjk0NWAKKDQpIEZvciBOWSwgaXQgaXMgYExvZyhTdWljaWRlcykgPSAwLjA0NSAqIGZvb2RfaW5zZWN1cml0eSArIDEuOTIzYAooNSkgRm9yIFBBLCBpdCBpcyBgTG9nKFN1aWNpZGVzKSA9IDAuMDQ1ICogZm9vZF9pbnNlY3VyaXR5ICsgMi4yODVgCig1KSBGb3IgVkEsIGl0IGlzIGBMb2coU3VpY2lkZXMpID0gMC4wNDUgKiBmb29kX2luc2VjdXJpdHkgKyAyLjM0NmAKQmVjYXVzZSB0aGUgY29lZmZpY2llbnQgZm9yIGZvb2RfaW5zZWN1cml0eSBpcyBsYXJnZXIgdGhhbiAwLCBpdCBtZWFucyB0aGF0IHdlIGhhdmUgYSAqKnBvc2l0aXZlIGFzc29jaWF0aW9uKiogYmV0d2VlbiBgZm9vZF9pbnNlY3VyaXR5YCBhbmQgYHN1aWNpZGVzYC4gVGhlIGludGVyY2VwdCBjb2VmZmljaWVudCBtZWFucyB3aGVyZSBvdXIgbGluZSB3aWxsIGludGVyc2VjdHMgd2l0aCB0aGUgeS1heGlzLiBBbmQgZmluYWxseSwgdGhlIGNvZWZmaWNpZW50IGZvciBlYWNoIHN0YXRlIGlzIHRoZSBkaWZmZXJlbmNlIG9mIHRoZSBpbnRlcmNlcHQgY29tcGFyZWQgdG8gdGhlIGJhc2VsaW5lIHJlZmVyZWNlLCBpLmUgYE9IYC5JbiBhZGRpdGlvbiwgdGhlc2UgY29lZmZpY2llbnRzIGFyZSBzaWduaWZpY2FudCBhcyB0aGUgbG93IGNvbmZpZGVuY2VzIG9mIHRoZSBpbnRlcnZhbCBhcmUgYWJvdmUgMCBpZiBpdCBpcyBwb3NpdGl2ZSBudW1iZXIgb3IgYXMgdGhlIGhpZ2ggY29uZmlkZW5jZXMgb2YgdGhlIGludGVydmFsIGFyZSBsb3dlciB0aGFuIDAgaWYgaXQgaXMgbmVnYXRpdmUgbnVtYmVyLiBJbiB0aGlzIGNhc2UsIGZvciBldmVyeSBjb2VmZmljaWVudCwgd2UgaGF2ZSB0aGVtIHRvIGJlIHNpZ25pZmljYW50LiAKCmBgYHtyfQpicm9vbTo6Z2xhbmNlKG1vZGVsKSAlPiUgc2VsZWN0KG5vYnMsIHIuc3F1YXJlZCwgYWRqLnIuc3F1YXJlZCwgc2lnbWEpICU+JSBrYWJsZShkaWdpdHMgPSAzKQoKYGBgCkZyb20gdGhlIHRhYmxlIGFib3ZlLCBpdCBpbmRpY2F0ZXMgdGhhdCB0aGUgUi1zcXVhcmVkIGlzIDAuMzg3IGFuZCByZXNpZHVhbCBzdGFuZGFyZCBlcnJvciBpcyAwLjI2MiB3aXRoIDM2NCBvYnNlcnZhdGlvbnMKIyMgUmVzaWR1YWwgQW5hbHlzaXMgCkhlcmUgaXMgdXNpbmcgdGhlIGBhdWdtZW50YCBmdW5jdGlvbiB0byBnZXQgdGhlIGZpdHRlZCBhbmQgcmVzaWR1YWwgdmFsdWVzLgoKCmBgYHtyfQptb2RlbGF1ZyA8LSBicm9vbTo6YXVnbWVudChtb2RlbCwgZGF0YSA9IGRhdGEyKQpgYGAKCkhlcmUgaXMgcGxvdCBmb3IgTm9ybWFsaXR5IGluIHRoZSByZXNpZHVhbHMKYGBge3J9CnAxIDwtIGdncGxvdChtb2RlbGF1ZywgYWVzKHNhbXBsZSA9IC5yZXNpZCkpICsKICBnZW9tX3FxKGNvbCA9ICJzZWFncmVlbiIpICsgZ2VvbV9xcV9saW5lKGNvbCA9ICJibGFjayIpICsgCiAgdGhlbWUoYXNwZWN0LnJhdGlvID0gMSkgKyAKICBsYWJzKHRpdGxlID0gIk5vcm1hbCBRLVE6IE1vZGVsIDEgUmVzaWR1YWxzIikKCnAyIDwtIGdncGxvdChtb2RlbGF1ZywgYWVzKHggPSAucmVzaWQpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSBzdGF0KGRlbnNpdHkpKSwgCiAgICAgICAgICAgICAgICAgYmlucyA9IDIwLCBmaWxsID0gInNlYWdyZWVuIiwgY29sID0gInllbGxvdyIpICsKICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGRub3JtLCAKICAgICAgICAgICAgICAgIGFyZ3MgPSBsaXN0KG1lYW4gPSBtZWFuKG1vZGVsYXVnJC5yZXNpZCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2QgPSBzZChtb2RlbGF1ZyQucmVzaWQpKSwKICAgICAgICAgICAgICAgIGNvbCA9ICJibGFjayIsIGx3ZCA9IDEuNSkgKwogIGxhYnModGl0bGUgPSAiSGlzdCArIE5vcm1hbCBEZW5zaXR5OiBNb2RlbCAxIFJlc2lkdWFscyIpCgpwMyA8LSBnZ3Bsb3QobW9kZWxhdWcsIGFlcyh4ID0gLnJlc2lkLCB5ID0gIiIpKSArCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAic2VhZ3JlZW4iLCBvdXRsaWVyLmNvbG9yID0gInNlYWdyZWVuIikgKyAKICBsYWJzKHRpdGxlID0gIkJveHBsb3Q6IE1vZGVsIDEgUmVzaWR1YWxzIiwgeSA9ICIiKQoKcDEgKyAocDIgLyBwMyArIHBsb3RfbGF5b3V0KGhlaWdodHMgPSBjKDQsMSkpKQptb3NhaWM6OmZhdnN0YXRzKH4gLnJlc2lkLCBkYXRhID0gbW9kZWxhdWcpICU+JSBrYWJsZShkaWdpdHMgPSAxKQpgYGAKRnJvbSB0aGUgaGlzdG9ncmFtLCB3ZSBtaWdodCBhZ3JlZSB0aGF0IGl0IGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBIb3dldmVyLCB3ZSBjYW4gbm90aWNlIHRoYXQgZWFjaCBlbmQgb2YgdGhlIGhpc3RvZ3JhbSBleHRlbmRzIG11Y2ggZnVydGhlciB0aGFuIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uLCBzbyBpdCBjYW4gYmUgY29uc2lkZXJlZCBhcyBoZWF2eS10YWlsZWQgZGlzdHJpYnV0aW9uLiBBbmQgdGhpcyBjYW4gYmUgY29uZmlybWVkIGJ5IG91ciBRUS1QbG90LiBIb3dldmVyLCB3aXRoIHRoYXQsIHRoZSBOb3JtYWwgbW9kZWwgbWF5IHN0aWxsIGJlIHJlYXNvbmFibGUgZm9yIGEgYmF0Y2ggb2YgZGF0YS4KCkFuZCBoZXJlIGlzIHRoZSBwbG90IGZvciBhc3Nlc3MgcmVzaWR1YWxzIHZzIGZpdHRlZCB2YWx1ZXMgZm9yIG5vbi1saW5lYXJ0eQoKYGBge3J9CmdncGxvdChtb2RlbGF1ZywgYWVzKHggPSAuZml0dGVkLCB5ID0gLnJlc2lkKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sID0gInJlZCIsCiAgICAgICAgICAgICAgZm9ybXVsYSA9IHkgfiB4LCBzZSA9IEZBTFNFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIGNvbCA9ICJibHVlIiwKICAgICAgICAgICAgICBmb3JtdWxhID0geSB+IHgsIHNlID0gRkFMU0UpICsKICBsYWJzKHRpdGxlID0gIk1vZGVsOiBSZXNpZHVhbHMgdnMuIEZpdHRlZCBWYWx1ZXMiLCAKICAgICAgIHggPSAiRml0dGVkIHN1aWNpZGVzIHZhbHVlcyIsIHkgPSAiUmVzaWR1YWxzIikKYGBgCkZyb20gdGhlIHBsb3QsIHdlIGRvIG5vdCBzZWUgYW55IHNpZ25pZmljYW50IGN1cnZlIHdoZW4gcGxvdHRpbmcgdGhlIHJlc2lkdWFscyBhZ2FpbnN0IHRoZSBmaXR0ZWQgdmFsdWVzLiBIb3dldmVyLCB0aGlzIGlzIG5vdCBnaXZlbiB0aGUg4oCYZnV6enkgZm9vdGJhbGzigJkgcGF0dGVybiwgd2hpY2ggaXQgc2VlbXMgbGlrZSB0aGUgdmFyaWFuY2UgYWNyb3NzIGxldmVscyBvZiB0aGUgZml0dGVkIHZhbHVlcyBhcmUgbm90IHJlYWxseSBzaW1pbGFyIHRvIGVhY2ggb3RoZXIuCgpTaW5jZSBJIHVzZSB0cmFuc2Zvcm0gbW9kZWwsIEkgd2lsbCBjcmVhdGUgYW5vdGhlciBtb2RlbCBoZXJlIHRvIGdldCB0aGUgbW9kZWxz4oCZIHByZWRpY3Rpb24gZm9yIHRoZSBvcmlnaW5hbCBvdXRjb21lIGFuZCBjb21wYXJlIHRvIGVhY2ggYWN0dWFsIG91dGNvbWUgZm9yIEN1eWFob2dhIENvdW50eSBpbiBPaGlvLiBUaGUgY29kZSBpcyBkaXNwbGF5ZWQgYmVsb3csIHdpdGggdGhlIHByZWRpY3RlZCB2YWx1ZSBhcyAxMy40OSB3aGlsZSB0aGUgYWN0dWFsIHZhbHVlIGlzIDE3LjA1NAoKYGBge3J9CnN0YXRlMSA8LSBtdXRhdGUoZGF0YTEsIHJlbGV2ZWwoc3RhdGUsICJPSCIpKQpvcmdmIDwtIGxtKHN1aWNpZGVzIH4gZm9vZF9pbnNlY3VyaXR5ICsgc3RhdGUsIGRhdGEgPSBkYXRhMSkKb3JnZmF1ZyA8LSBicm9vbTo6YXVnbWVudChvcmcsIGRhdGEgPSBkYXRhMSkKCnRpYmJsZShhY3R1YWxfdmFsdWUgPSBkYXRhMVtkYXRhMSRzdGF0ZT09Ik9IIiAmIGRhdGExJGNvdW50eSA9PSJDdXlhaG9nYSBDb3VudHkiLF0kc3VpY2lkZXMsIHByZWRpY3RlZF92YWx1ZSA9IG9yZ2ZhdWdbb3JnZmF1ZyRzdGF0ZT09Ik9IIiAmIG9yZ2ZhdWckY291bnR5ID09IkN1eWFob2dhIENvdW50eSIsXSQuZml0dGVkKSB8PiBrYWJsZShkaWdpdHMgPSAzKQpgYGAKVGhlIHR3byBjb3VudGllcyBoYXZlIHRoZSBsZWFzdCBzdWNjZXNzZnVsIGF0IHByZWRpY3Rpbmcgb3V0Y29tZSBhcmUgQnJvbnggQ291bnR5IGluIE5ldyBZb3JrIHdpdGggYWJzb2x1dGUgcmVzaWR1YWwgdmFsdWVzIGFyZSAwLjk5MiBhbmQgQ2hhcmxvdHRlc3ZpbGxlIGNpdHkgaW4gVmlyZ2luaWEgd2l0aCBhYnNvbHV0ZSByZXNpZHVhbCB2YWx1ZSBhcyAwLjk3MS4gCmBgYGB7cn0KbW9kZWxhdWdvcmRlciA8LSBtdXRhdGUobW9kZWxhdWcsIC5yZXNpZCA9IGFicygucmVzaWQpKQptb2RlbGF1Z29yZGVyIDwtIG1vZGVsYXVnb3JkZXJbb3JkZXIoLW1vZGVsYXVnb3JkZXIkLnJlc2lkKSxdCm1vZGVsYXVnb3JkZXJbMToyLF0gfD4ga2FibGUoZGlnaXRzID0gMykKYGBgCiMjIENvbmNsdXNpb24gYW5kIEFuYWx5c2lzIApGb3IgdGhpcyBhbmFseXNpcywgSSB1c2UgdGhlIHNhbWUgcHJlZGljdG9yIHZhcmlhYmxlIGFzIGluIGFuYWx5c2lzIDEsIGV4Y2VwdCB0aGF0IEkgd2lsbCBjb25zaWRlciB0aGUgYXNzb2NpYXRpb24gZm9yIGVhY2ggNiBzdGF0ZXMgb2YgbXkgY2hvaWNlIGluIG9yZGVyIHRvIGludmVzdGlnYXRlIGhvdyB3ZWxsIGRvZXMgZm9vZCBpbnNlY3VyaXR5IHByZWRpY3QgdGhlIHN1aWNpZGVzLiBGcm9tIHRoZSBzY2F0dGVyIHBsb3QgYWJvdmUsIHdlIGNvdWxkIHNlZSB0aGF0IGV2ZW4gdGhvdWdoIHRoZSBvdmVyYWxsIGNvbWJpbmF0aW9uIG9mIDYgc3RhdGVzIGdpdmVzIHVzIGEgcG9zaXRpdmUgYXNzb2NpYXRpb24gYmV0d2VlbiBmb29kIGluc2VjdXJpdHkgYW5kIHN1aWNpZGVzLCB3aGVuIHdlIGJyZWFrIGl0IHVwIGludG8gZGlmZmVyZW50IHN0YXRlcywgTWFzc2FjaHVzZXR0cyByZXR1cm5zIGEgbmVnYXRpdmUgYXNzb2NpYXRpb24gd2hpbGUgb3RoZXJzIHN0aWxsIHBvc2l0aXZlLiBXaXRoIHRoYXQgaW50ZXJlc3QsIHdlIGZ1cmh0ZXIgZml0dGluZyBvdXIgbW9kZWwgd2l0aCB1c2luZyBPaGlvIGFzIHRoZSBiYXNlbGluZSByZWZlcmVuY2UuIEZyb20gb3VyIG1vZGVsLCBldmVuIHRoZSBjb2VmZmljaWVudCBmb3IgZm9vZCBpbnNlY3VyaXR5IGFzIG90aGVyIGludGVyY2VwdHMgYXJlIHNpZ25pZmljYW50LCBidXQgdGhlIGNvZWZmaWNpZW50IGlzIHRvbyBsb3cgKGAwLjA0NWApLiBUaGlzIGluZGljYXRlcyB0aGF0IHRoZXJlIGFyZSBvbmx5IGEgdmVyeSB3ZWFrIHBvc2l0aXZlIGludGVyYWN0aW9uIGJldHdlZW4gdGhlIGZvb2QgaW5zZWN1cml0eSBhbmQgc3VpY2lkZXMsIGJ1dCBzdXJwcmlzaW5nbHkgdG8gYmUgYSBsaXR0bGUgYml0IGhpZ2hlciB0aGFuIHRoZSBjb2VmZmljaWVudCB3aGVuIGNvbWJpbmluZyBhbGwgc3RhdGVzIHRvZ2V0aGVyIChgMC4wNDBgKS4gVGhpcyBtYXkgYmUgYWNjb3VudCB0byB0aGUgZmFjdCB0aGF0IHdlIHVzZSBgT2hpb2AgYXMgdGhlIHJlZmVyZW5jZSBzdGF0ZSBzaW5jZSBpdCBoYXMgdGhlIGhpZ2hlc3QgUGVhcnNvbidzIGNvcnJlbGF0aW9uIHNjb3JlIGFmdGVyIGFsbC4gTW9yZW92ZXIsIGNvbXBhcmluZyB0byB0aGUgb3JpZ2luYWwgbW9kZWwgaW4gYW5hbHlzaXMgMSwgYnJlYWtpbmcgdXAgaW50byBzdGF0ZXMgZG9lc24ndCBtYWtlIGEgbG90IG9mIGRpZmZlcmVuY2UgYXMgdGhlIGNvZWZmaWNpZW50cyBvZiBmb29kIGluc2VjdXJpdHkgYXMgd2VsbCBhcyB0aGUgaW50ZXJjZXB0IGFyZSBxdWl0ZSBzaW1pbGFyLiBJbiBhZGRpdGlvbiB0byB0aGF0LCBJIGJhcmVseSBhZ3JlZSB0aGF0IHRoaXMgd291bGQgZ2l2ZSB1cyBhIHJpZ2h0IHByZWRpY3Rpb24gZm9yIGVhY2ggc3RhdGUsIHNpbmNlIGZvciBNYXNzYWNodXNldHRzLCBpdCBzdGlsbCB5aWVsZHMgYSBwb3NpdGl2ZSBhc3NvY2lhdGlvbiB3aGVuIGl0IGlzIHN1cHBvc2VkIHRvIGJlIGEgbmVnYXRpdmUgb25lLiAKVGhlIGxpbWl0YXRpb25zIGFyZSBzYW1lIGFzIGFib3ZlLCBhcyBtaW5lIGNhbm5vdCBiZSBjb25zaWRlcmVkIHRvIGJlIGEgcmVwcmVzZW50YXRpdmUgc2FtcGxlIGZvciB0aGUgVS5TIGR1ZSB0byBiaWFzLiBJbiBhZGRpdGlvbiB0byB0aGF0LCBmb3IgdGhlIG5vcm1hbHR5IG9mIHJlc2lkdWFscywgaXQgc2VlbXMgdG8gYmUgaGVhdnktdGFpbGVkIGFuZCBhbG1vc3QgbGVmdC1za2V3ZWQuIFRoZXJlZm9yZSwgaXQgaXMgdmVyeSBoYXJkIHRvIGFzc3VtZSB0aGF0IHdlIGhhdmUgYSBub3JtYWwgZGlzdHJpYnV0aW9uIGZvciB0aGUgcmVzaWR1YWxzLiAKCiMgU2Vzc2lvbiBJbmZvcm1hdGlvbgoKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBgCg==