Preliminary

Check the number of dx


      Normal   Osteopenia Osteoporosis 
          39           57           31 

Create datasets for measurements and grey values

Measurements dataset

add a new variable to mark the outliers. In future models check the model with and without outliers

Check all the dataset

Check how many outliers


  no  yes 
2241   45 

Grey Values dataset

add a new variable to mark the outliers. In future models check the model with and without outliers

Check the grey values dataframe

check the outliers


 no yes 
499   9 

Main result

Demographic tables

Table 1

Characteristic Overall, N = 127 Normal, N = 391 Osteopenia, N = 571 Osteoporosis, N = 311 p-value2
Age 70 (9) 69 (9) 70 (9) 72 (8) 0.24
Height 160.0 (5.9) 160.9 (5.4) 159.3 (6.1) 159.9 (6.0) 0.43
Weight 73 (16) 82 (17) 72 (13) 64 (14) <0.001
BMI 28.6 (5.9) 31.8 (6.0) 28.3 (5.2) 24.9 (4.6) <0.001

1 Statistics presented: mean (SD)

2 Statistical tests performed: One-way ANOVA

Table 2 Measurements

Characteristic Overall, N = 127 Normal, N = 391 Osteopenia, N = 571 Osteoporosis, N = 311 p-value2
viss_mean 101 (23) 100 (24) 102 (21) 101 (24) 0.84
trab_mean 59 (24) 71 (27) 57 (19) 50 (21) <0.001
cor_mean 75 (30) 84 (29) 73 (30) 68 (26) 0.079
baz_viss_mean 67 (21) 62 (20) 72 (19) 65 (23) 0.074
baz_trab_mean 57 (24) 60 (25) 55 (25) 56 (21) 0.62
baz_cor_mean 62 (27) 70 (27) 61 (24) 52 (30) 0.035

1 Statistics presented: mean (SD)

2 Statistical tests performed: One-way ANOVA

Table 2 for reformat

Characteristic Normal, N = 391 Osteopenia, N = 571 Osteoporosis, N = 311 p-value2
md_vol_all 21.2 (4.6) 18.4 (3.6) 18.0 (3.9) <0.001
md_vol_small 9.27 (2.30) 8.03 (1.67) 8.18 (1.97) 0.007
md_vol_forame 2.95 (1.41) 2.44 (1.01) 2.32 (1.22) 0.057
mx_vol 4.70 (1.25) 4.03 (1.40) 3.94 (1.38) 0.029
x1_viss 164 (41) 148 (39) 142 (38) 0.042
x1_trab 71 (33) 71 (29) 71 (32) >0.99
x1_cor 94 (24) 77 (21) 71 (21) <0.001
x1_baz_viss 122 (17) 107 (15) 102 (15) <0.001
x1_baz_trab 50 (13) 51 (9) 55 (12) 0.35
x1_baz_cor 71 (21) 56 (14) 47 (15) <0.001
x1_cort_viss 0.59 (0.14) 0.54 (0.12) 0.52 (0.16) 0.074
x2_viss 151 (44) 136 (39) 130 (40) 0.077
x2_trab 66 (37) 65 (29) 65 (33) 0.98
x2_cor 84 (25) 71 (20) 65 (18) <0.001
x2_baz_viss 117 (20) 105 (15) 103 (15) 0.005
x2_baz_trab 51 (13) 52 (11) 54 (12) 0.69
x2_baz_cor 65 (21) 54 (14) 49 (14) 0.001
x2_cor_viss 0.58 (0.16) 0.54 (0.14) 0.52 (0.14) 0.18
x3_viss 123 (49) 114 (40) 106 (40) 0.24
x3_trab 65 (41) 60 (32) 55 (31) 0.54
x3_cor 59 (22) 54 (19) 51 (18) 0.21
x3_baz_viss 108 (15) 97 (16) 98 (16) 0.039
x3_baz_trab 58 (14) 55 (11) 56 (8) 0.51
x3_baz_cor 50 (13) 43 (14) 42 (13) 0.14
x3_cor_viss 0.52 (0.17) 0.50 (0.15) 0.51 (0.17) 0.84
x4_viss 121 (48) 114 (43) 108 (39) 0.45
x4_trab 64 (38) 62 (34) 58 (34) 0.81
x4_cor 57 (23) 52 (19) 50 (19) 0.24
x4_baz_viss 109 (17) 100 (16) 97 (12) 0.071
x4_baz_trab 60 (11) 59 (11) 61 (10) 0.88
x4_baz_cor 49 (16) 41 (13) 37 (11) 0.032
x4_cor_viss 0.50 (0.17) 0.48 (0.15) 0.49 (0.19) 0.81

1 Statistics presented: mean (SD)

2 Statistical tests performed: One-way ANOVA

IN this table, the comparison aren’t adjusted for any other variable, so please consider as an approximation in order to try to find the signal, that is the true effect or relationship between the bone measurements in CBCT and the DXA status

Now, we will to proceed to create a model that could isolate the signal (relation between measurements and DXA) from the noise (weight? height? age?) ## Measurements With the outliers

Seems to be a positive correlation, that is, more DXA, more mm. Now lets check divided by area and bone

This graph shows that the DXA measured in hip or lumbar vertebrae seems to be correlated to the measurements made in the cortical bone in the CBCT

Is there any association between the DXA values and the measurements? Continuos DXA values

Lets check the effect of the outliers

The outliers only add noise to the signal

Note that the outliers add noise to the signal, hence will be removed from any further analysis


Call:
glm(formula = value ~ dxa_worst, data = .)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-79.842  -27.757   -7.546   24.216  111.524  

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  83.7344     1.2788  65.478  < 2e-16 ***
dxa_worst     2.9702     0.6548   4.536  6.1e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for gaussian family taken to be 1366.118)

    Null deviance: 2582750  on 1871  degrees of freedom
Residual deviance: 2554641  on 1870  degrees of freedom
  (369 observations deleted due to missingness)
AIC: 18832

Number of Fisher Scoring iterations: 2
MODEL INFO:
Observations: 1872 (369 missing obs. deleted)
Dependent Variable: value
Type: Linear regression 

MODEL FIT:
χ²(1) = 28109.04, p = 0.00
Pseudo-R² (Cragg-Uhler) = 0.01
Pseudo-R² (McFadden) = 0.00
AIC = 18831.84, BIC = 18848.44 

Standard errors: MLE
------------------------------------------------
                     Est.   S.E.   t val.      p
----------------- ------- ------ -------- ------
(Intercept)         83.73   1.28    65.48   0.00
dxa_worst            2.97   0.65     4.54   0.00
------------------------------------------------

Estimated dispersion parameter = 1366.12 

The baseline value for measurements is 84 and for every additional point in DXA, the measurement value increase in 2.97 (p<0.01)

This model explain very little of the variance of the measurements, only 1% (see R2), but there is a signal. We are interested in identify if this statistical significance is also clinically relevant.

But it could be that one group is bigger, or heavier, or older. Let’s identify if the difference is kept in check by other factors.

MODEL INFO:
Observations: 1854 (387 missing obs. deleted)
Dependent Variable: value
Type: Linear regression 

MODEL FIT:
χ²(5) = 184133.61, p = 0.00
Pseudo-R² (Cragg-Uhler) = 0.07
Pseudo-R² (McFadden) = 0.01
AIC = 18547.07, BIC = 18585.75 

Standard errors: MLE
------------------------------------------------
                     Est.   S.E.   t val.      p
----------------- ------- ------ -------- ------
(Intercept)         34.51   8.66     3.99   0.00
dxa_worst            0.27   0.70     0.38   0.70
age                 -0.02   0.09    -0.20   0.84
md_vol_all           2.41   0.24     9.92   0.00
mx_vol              -0.27   0.69    -0.39   0.70
ID                   0.01   0.02     0.29   0.77
------------------------------------------------

Estimated dispersion parameter = 1289.01 

Adjusting for all the variables seems that the signal disappear, but we haven’t yet adjusted by zone and clinical_variable_2 (basal, cort, all)

Now explore by zone and type of bone, maybe there are some interaction by zone and what is being measured (cortcal, trabeculae, etc). Let’s check

First, take a look at the graph:

and the regression model is:

MODEL INFO:
Observations: 1872 (369 missing obs. deleted)
Dependent Variable: value
Type: Linear regression 

MODEL FIT:
χ²(5) = 187186.39, p = 0.00
Pseudo-R² (Cragg-Uhler) = 0.07
Pseudo-R² (McFadden) = 0.01
AIC = 18719.48, BIC = 18758.22 

Standard errors: MLE
------------------------------------------------
                     Est.   S.E.   t val.      p
----------------- ------- ------ -------- ------
(Intercept)         44.55   9.62     4.63   0.00
dxa_worst            0.75   0.75     1.00   0.32
age                 -0.02   0.09    -0.24   0.81
bmi                 -0.33   0.16    -2.04   0.04
md_vol_all           2.36   0.22    10.82   0.00
ID                   0.01   0.02     0.40   0.69
------------------------------------------------

Estimated dispersion parameter = 1283.8 

When adjusted for age and mannd/max volume, the signal is lost.

Now, we will make 6 regression models - for every bone type separately.

1. Cortical Basal

MODEL INFO:
Observations: 260 (121 missing obs. deleted)
Dependent Variable: value
Type: Linear regression 

MODEL FIT:
χ²(5) = 27062.44, p = 0.00
Pseudo-R² (Cragg-Uhler) = 0.32
Pseudo-R² (McFadden) = 0.04
AIC = 2153.90, BIC = 2178.82 

Standard errors: MLE
--------------------------------------------------
                      Est.    S.E.   t val.      p
----------------- -------- ------- -------- ------
(Intercept)         111.82   11.53     9.70   0.00
dxa_worst             4.64    0.85     5.44   0.00
age                  -0.78    0.11    -7.39   0.00
bmi                  -0.19    0.18    -1.04   0.30
md_vol_all            0.52    0.26     2.01   0.05
ID                   -0.01    0.03    -0.34   0.74
--------------------------------------------------

Estimated dispersion parameter = 224.94 

2. Trabeculae Basal

MODEL INFO:
Observations: 260 (121 missing obs. deleted)
Dependent Variable: value
Type: Linear regression 

MODEL FIT:
χ²(5) = 7408.24, p = 0.00
Pseudo-R² (Cragg-Uhler) = 0.22
Pseudo-R² (McFadden) = 0.03
AIC = 1958.39, BIC = 1983.32 

Standard errors: MLE
------------------------------------------------
                     Est.   S.E.   t val.      p
----------------- ------- ------ -------- ------
(Intercept)         -9.30   7.92    -1.18   0.24
dxa_worst           -1.83   0.59    -3.13   0.00
age                  0.46   0.07     6.40   0.00
bmi                  0.15   0.13     1.21   0.23
md_vol_all           1.05   0.18     5.96   0.00
ID                   0.02   0.02     0.88   0.38
------------------------------------------------

Estimated dispersion parameter = 106.05 

3. All Basal Bone

MODEL INFO:
Observations: 260 (121 missing obs. deleted)
Dependent Variable: value
Type: Linear regression 

MODEL FIT:
χ²(5) = 23101.18, p = 0.00
Pseudo-R² (Cragg-Uhler) = 0.29
Pseudo-R² (McFadden) = 0.04
AIC = 2148.28, BIC = 2173.21 

Standard errors: MLE
--------------------------------------------------
                      Est.    S.E.   t val.      p
----------------- -------- ------- -------- ------
(Intercept)         102.51   11.41     8.99   0.00
dxa_worst             2.80    0.84     3.32   0.00
age                  -0.32    0.10    -3.03   0.00
bmi                  -0.04    0.18    -0.21   0.83
md_vol_all            1.56    0.25     6.17   0.00
ID                    0.01    0.03     0.27   0.79
--------------------------------------------------

Estimated dispersion parameter = 220.14 

4. Cortical

MODEL INFO:
Observations: 379 (2 missing obs. deleted)
Dependent Variable: value
Type: Linear regression 

MODEL FIT:
χ²(5) = 78140.48, p = 0.00
Pseudo-R² (Cragg-Uhler) = 0.34
Pseudo-R² (McFadden) = 0.05
AIC = 3358.43, BIC = 3385.99 

Standard errors: MLE
--------------------------------------------------
                      Est.    S.E.   t val.      p
----------------- -------- ------- -------- ------
(Intercept)         109.15   11.66     9.36   0.00
dxa_worst             3.93    0.94     4.18   0.00
age                  -0.76    0.12    -6.50   0.00
bmi                  -0.94    0.20    -4.76   0.00
md_vol_all            2.39    0.27     8.99   0.00
ID                    0.02    0.03     0.53   0.60
--------------------------------------------------

Estimated dispersion parameter = 404.41 

5. Trabeculae

MODEL INFO:
Observations: 379 (2 missing obs. deleted)
Dependent Variable: value
Type: Linear regression 

MODEL FIT:
χ²(5) = 173114.84, p = 0.00
Pseudo-R² (Cragg-Uhler) = 0.42
Pseudo-R² (McFadden) = 0.06
AIC = 3527.23, BIC = 3554.79 

Standard errors: MLE
--------------------------------------------------
                      Est.    S.E.   t val.      p
----------------- -------- ------- -------- ------
(Intercept)         -96.46   14.57    -6.62   0.00
dxa_worst            -4.54    1.17    -3.87   0.00
age                   0.73    0.15     4.96   0.00
bmi                   0.24    0.25     0.99   0.32
md_vol_all            5.20    0.33    15.70   0.00
ID                   -0.04    0.04    -1.17   0.24
--------------------------------------------------

Estimated dispersion parameter = 631.32 

6. All Bone

MODEL INFO:
Observations: 334 (2 missing obs. deleted)
Dependent Variable: value
Type: Linear regression 

MODEL FIT:
χ²(5) = 177606.12, p = 0.00
Pseudo-R² (Cragg-Uhler) = 0.43
Pseudo-R² (McFadden) = 0.06
AIC = 3146.98, BIC = 3173.66 

Standard errors: MLE
-------------------------------------------------
                     Est.    S.E.   t val.      p
----------------- ------- ------- -------- ------
(Intercept)         29.22   16.46     1.77   0.08
dxa_worst           -0.36    1.34    -0.27   0.79
age                  0.05    0.17     0.32   0.75
bmi                 -0.96    0.28    -3.45   0.00
md_vol_all           6.41    0.43    14.98   0.00
ID                  -0.00    0.04    -0.11   0.92
-------------------------------------------------

Estimated dispersion parameter = 706.58 

And now lets see if all cortical could be better model:

MODEL INFO:
Observations: 639 (123 missing obs. deleted)
Dependent Variable: value
Type: Linear regression 

MODEL FIT:
χ²(5) = 87049.28, p = 0.00
Pseudo-R² (Cragg-Uhler) = 0.25
Pseudo-R² (McFadden) = 0.03
AIC = 5670.54, BIC = 5701.76 

Standard errors: MLE
-------------------------------------------------
                      Est.   S.E.   t val.      p
----------------- -------- ------ -------- ------
(Intercept)         115.23   9.34    12.33   0.00
dxa_worst             4.34   0.73     5.94   0.00
age                  -0.77   0.09    -8.53   0.00
bmi                  -0.62   0.15    -4.04   0.00
md_vol_all            1.33   0.21     6.38   0.00
ID                    0.01   0.02     0.56   0.57
-------------------------------------------------

Estimated dispersion parameter = 413.12 

Looking at graphs we would expect that all trabecular should be worse:

MODEL INFO:
Observations: 639 (123 missing obs. deleted)
Dependent Variable: value
Type: Linear regression 

MODEL FIT:
χ²(5) = 120338.41, p = 0.00
Pseudo-R² (Cragg-Uhler) = 0.26
Pseudo-R² (McFadden) = 0.03
AIC = 5851.48, BIC = 5882.70 

Standard errors: MLE
--------------------------------------------------
                      Est.    S.E.   t val.      p
----------------- -------- ------- -------- ------
(Intercept)         -61.27   10.76    -5.69   0.00
dxa_worst            -3.46    0.84    -4.11   0.00
age                   0.65    0.10     6.21   0.00
bmi                   0.24    0.18     1.37   0.17
md_vol_all            3.29    0.24    13.69   0.00
ID                   -0.02    0.03    -0.61   0.54
--------------------------------------------------

Estimated dispersion parameter = 548.34 

… but it is not true. So, the conclusion could be that the relation between DXA and measurements in CBCT in mandible is statistically significant, but maybe the relation is not clinically significant.

Maybe the models are better in some age group?

MODEL INFO:
Observations: 210 (42 missing obs. deleted)
Dependent Variable: value
Type: Linear regression 

MODEL FIT:
χ²(5) = 27604.91, p = 0.00
Pseudo-R² (Cragg-Uhler) = 0.21
Pseudo-R² (McFadden) = 0.03
AIC = 1907.76, BIC = 1931.19 

Standard errors: MLE
--------------------------------------------------
                      Est.    S.E.   t val.      p
----------------- -------- ------- -------- ------
(Intercept)         144.41   41.00     3.52   0.00
dxa_worst             8.98    1.44     6.25   0.00
age                  -0.56    0.57    -0.98   0.33
bmi                  -1.14    0.30    -3.77   0.00
md_vol_all            0.29    0.40     0.74   0.46
ID                    0.03    0.04     0.81   0.42
--------------------------------------------------

Estimated dispersion parameter = 497.21 

Grey Values

Characteristic Overall, N = 127 Normal, N = 391 Osteopenia, N = 571 Osteoporosis, N = 311 p-value2
C1 Axial 40 (105) 86 (85) 32 (112) -6 (92) <0.001
C1 Sagital 38 (99) 72 (87) 36 (108) -0 (84) 0.009
C2 Axial 140 (100) 185 (86) 129 (105) 104 (90) 0.001
C2 Sagital 132 (102) 166 (99) 126 (109) 98 (78) 0.017

1 Statistics presented: mean (SD)

2 Statistical tests performed: One-way ANOVA

Is there any association between the grey values and the measurements? Continuos DXA values

Visualise the overall correlation

Check the effect of the outliers

Plot without the outliers

MODEL INFO:
Observations: 506 (2 missing obs. deleted)
Dependent Variable: value_grey
Type: Linear regression 

MODEL FIT:
χ²(1) = 529259.41, p = 0.00
Pseudo-R² (Cragg-Uhler) = 0.08
Pseudo-R² (McFadden) = 0.01
AIC = 6175.68, BIC = 6188.36 

Standard errors: MLE
-------------------------------------------------
                      Est.   S.E.   t val.      p
----------------- -------- ------ -------- ------
(Intercept)         123.20   7.16    17.21   0.00
dxa_worst            24.59   3.64     6.75   0.00
-------------------------------------------------

Estimated dispersion parameter = 11604.2 

The baseline grey value is 123 and for each DXA point, the grey values increment +24

Is there any association between the grey values and the measurements? Ordinal Dx values (Normal, Osteopenia, Osteoporosis)

Reliability analysis: are the measurements reliable?

See

Koo, Terry, and Mae Li. 2016. “A Guideline of Selecting and Reporting Intraclass Correlation Coefficients for Reliability Research.” Journal of Chiropractic Medicine 15 (March). doi:10.1016/j.jcm.2016.02.012.

Shrout, P.E., and J.L. Fleiss. 1979. “Intraclass Correlation: Uses in Assessing Rater Reliability.” Psychological Bulletin 86: 420–28.

For x1_viss

 Single Score Intraclass Correlation

   Model: twoway 
   Type : agreement 

   Subjects = 29 
     Raters = 2 
   ICC(A,1) = 0.898

 F-Test, H0: r0 = 0 ; H1: r0 > 0 
   F(28,29) = 18.5 , p = 4.52e-12 

 95%-Confidence Interval for ICC Population Values:
  0.797 < ICC < 0.951

For x1_trab

 Single Score Intraclass Correlation

   Model: twoway 
   Type : agreement 

   Subjects = 29 
     Raters = 2 
   ICC(A,1) = 0.999

 F-Test, H0: r0 = 0 ; H1: r0 > 0 
 F(28,28.9) = 2744 , p = 9.63e-43 

 95%-Confidence Interval for ICC Population Values:
  0.998 < ICC < 1

For x1_baz_viss

 Single Score Intraclass Correlation

   Model: twoway 
   Type : agreement 

   Subjects = 25 
     Raters = 2 
   ICC(A,1) = 0.997

 F-Test, H0: r0 = 0 ; H1: r0 > 0 
 F(24,18.6) = 669 , p = 1.05e-22 

 95%-Confidence Interval for ICC Population Values:
  0.992 < ICC < 0.999

For x1_baz_trab

 Single Score Intraclass Correlation

   Model: twoway 
   Type : agreement 

   Subjects = 25 
     Raters = 2 
   ICC(A,1) = 0.986

 F-Test, H0: r0 = 0 ; H1: r0 > 0 
 F(24,24.9) = 140 , p = 5.04e-21 

 95%-Confidence Interval for ICC Population Values:
  0.969 < ICC < 0.994

For c1_axial

 Single Score Intraclass Correlation

   Model: twoway 
   Type : agreement 

   Subjects = 10 
     Raters = 2 
   ICC(A,1) = 0.968

 F-Test, H0: r0 = 0 ; H1: r0 > 0 
  F(9,9.02) = 56.4 , p = 7.47e-07 

 95%-Confidence Interval for ICC Population Values:
  0.878 < ICC < 0.992

For c1_sagital

 Single Score Intraclass Correlation

   Model: twoway 
   Type : agreement 

   Subjects = 9 
     Raters = 2 
   ICC(A,1) = 0.972

 F-Test, H0: r0 = 0 ; H1: r0 > 0 
  F(8,8.49) = 77.5 , p = 4.43e-07 

 95%-Confidence Interval for ICC Population Values:
  0.887 < ICC < 0.994

Every measurement has almost perfect reliability

BLand Altman plots for grey values

NULL

NULL

LS0tCnRpdGxlOiAiT3N0ZW9wb3Jvc2lzIEFTIEp1bmUgMjAyMCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0aGVtZTogY2VydWxlYW4KICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCi0tLQoKIyBQcmVsaW1pbmFyeQoKCmBgYHtyIHBhY2thZ2VzfQpwYWNtYW46OnBfbG9hZCh0aWR5dmVyc2UsICAjIGZvciBkYXRhIHZpc3VhbGl6YXRpb24gYW5kIHdyYW5nbGluZyAKICAgICAgICAgICAgICAgZ2dwdmFsLCAgICAgIyBmb3IgcCB2YWx1ZXMgaW4gcGxvdHMKICAgICAgICAgICAgICAganRvb2xzLCAgICAgIyB0byB2aXN1YWxpemUgbW9kZWxzCiAgICAgICAgICAgICAgIGNhciwgICAgICAgICMgZm9yIHJlZ3Jlc3Npb24KICAgICAgICAgICAgICAgIyBocmJydGhlbWVzLCAjIG5pY2UgZ2dwbG90MiB0aGVtZXMgd2l0aCBSb2JvdG8gZm9udAogICAgICAgICAgICAgICBicm9vbSwgICAgICAjIGZvciBtb2RlbCBldmFsdWF0aW9uCiAgICAgICAgICAgICAgIHB1YmgsICAgICAgICMgZm9yIGdsbV9jb2VmcwogICAgICAgICAgICAgICBzalBsb3QsICAgICAjIHBsb3RfbW9kZWwKICAgICAgICAgICAgICAgdGlkeW1vZGVscywgIyBmb3IgbW9kZWxsaW5nIHdpdGggYnJvb20KICAgICAgICAgICAgICAgcnN0YXRpeCwgICAgIyBmb3IgYW5vdmEgaW4gdGhlIHBpcGUKICAgICAgICAgICAgICAgZW1tZWFucywgICAgIyBwbG90dGluZwogICAgICAgICAgICAgICBCbGFuZEFsdG1hbkxlaCwgIyBCQSBQbG90CiAgICAgICAgICAgICAgIGdnc2lnbmlmLCAgICAjIGZvciBzaWduaWZpY2FuY2UgbGluZXMgaW4gZ2dwbG90MiAKICAgICAgICAgICAgICAgZ2dwdWJyLCAgICAgIyBmb3IgZGF0YSB2aXN1YWxpemF0aW9uIGVuaGFuY2VtZW50cwogICAgICAgICAgICAgICBnZ3N0YXRzcGxvdCwgIyBDSEVDSyBUT0RPCiAgICAgICAgICAgICAgIGphbml0b3IsICAgICMgZm9yIGRhdGEgY2xlYW5pbmcgCiAgICAgICAgICAgICAgIHZpc2RhdCwgICAgICMgdG8gdml6dWFsaXNlIG1pc3NpbmcgZGF0YSAKICAgICAgICAgICAgICAgZ3RzdW1tYXJ5KSAgIyBmb3Igc3VtbWFyeSB0YWJsZXMsIHRoaXMgcmVwbGFjZXMgdGFibGUxCmBgYAoKYGBge3IgZ2xvYmFsX29wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UpCnRoZW1lX3NldChnZ3B1YnI6OnRoZW1lX3B1YmNsZWFuKCkpCgpgYGAKCmBgYHtyIGRhdGFzZXR9CmRmIDwtIHJlYWRfY3N2KCJodHRwOi8vdGlueS5jYy9xMmxkcXoiKSAlPiUgCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUgICMgc3RhbmRhcml6ZSBhbGwgbmFtZXMgZnJvbSBjb2x1bW5zLCBtb3JlIGVhc2llciB0byB3b3JrIHdpdGgKICBzZWxlY3QoLXZhcmRzX3V6dmFyZHMpICU+JQogIGphbml0b3I6OmNsZWFuX25hbWVzKCkKYGBgCgpgYGB7ciBjaGFuZ2Ugc29tZSBjb2x1bW4gbmFtZXN9CmRmIDwtIGRmICU+JSAKICByZW5hbWUoeDFfYmF6X2NvciA9IHgxX2Jhc19jb3IsIAogICAgICAgICB4MV9iYXpfdmlzc18yID0geDFfYmF6X3Zpc3MyLCAKICAgICAgICAgeDFfdHJhYl8yID0geDFfdHJhYjIsIAogICAgICAgICB4MV92aXNzXzIgPSB4MV92aXNzMikKYGBgCgpgYGB7ciBjcmVhdGUgbmV3IHZhciBkeH0KIyBDbGVhbiB0aGUgbmFtZXMKIyBJIHdpbGwgY2hhbmdlIGZyb20gZHhhIGx1YmFyIHRvIHdvcnN0CgpkZiA8LSBkZiAlPiUKICBtdXRhdGUoZHggPSBjYXNlX3doZW4oCiAgICBkeGFfd29yc3QgPCAtMi40IH4gIk9zdGVvcG9yb3NpcyIsICMgY2hhbmdlZCBBcHJpbCAyM3RoLCAyMDIwCiAgICBkeGFfd29yc3QgPiAtMC45OSB+ICJOb3JtYWwiLAogICAgVFJVRSB+ICJPc3Rlb3BlbmlhIgogICkpCmBgYAoKQ2hlY2sgdGhlIG51bWJlciBvZiBkeApgYGB7ciwgaW5jbHVkZT1UUlVFfQp0YWJsZShkZiRkeCkKYGBgCgoKIyBDcmVhdGUgZGF0YXNldHMgZm9yIG1lYXN1cmVtZW50cyBhbmQgZ3JleSB2YWx1ZXMKIyMjIE1lYXN1cmVtZW50cyBkYXRhc2V0CgoKCmBgYHtyfQptZWFzdXJlbWVudHNfZGF0YSA8LSAgZGYgJT4lCiAgIyBjcmVhdGUgYSBuZXcgSUQgY29sdW1uCiAgdGliYmxlOjpyb3dpZF90b19jb2x1bW4oLiwgIklEIikgJT4lCiMgd2lkZSB0byBsb25nIGRhdGFzZXQKICBwaXZvdF9sb25nZXIoeDFfdmlzczp4NF9jb3JfdmlzcywKICAgICAgICAgICAgICAgIyBjb2x1bW5zIHRvIG1lcmdlCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gImNsaW5pY2FsX3ZhcmlhYmxlIiwKICAgICAgICAgICAgICAgI25hbWUgb2YgdGhlIG5ldyBjb2x1bSB3aXRoIHRoZSBuYW1lcwogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUgICNuYW1lIG9mIHRoZSBuZXcgY29sdW1uIHdpdGggdmFsdWVzCgojIGxlYXZlIG9ubHkgc2VsZWN0ZWQgdmFyaWFibGUKICBzZWxlY3QoY2xpbmljYWxfdmFyaWFibGUsCiAgICAgICAgIHZhbHVlLAogICAgICAgICBkeCwKICAgICAgICAgZHhhX3dvcnN0LAogICAgICAgICBJRCwgCiAgICAgICAgIGFnZSwgCiAgICAgICAgIG1kX3ZvbF9hbGwsIAogICAgICAgICBteF92b2wsIAogICAgICAgICBibWkpICU+JQogIAogICMgbGVhdmUgb3V0IHNvbWUgdmFyaWFibGVzLCBhcyB0aGUgc2Vjb25kIG1lYXN1cmVtZW50cyBhbmQgdGhlIHByb3BvcnRpb24KICAgIGZpbHRlcighc3RyX2RldGVjdChjbGluaWNhbF92YXJpYWJsZSwgIjIkIikpICU+JSAgIyBhZ2FpbgogICAgZmlsdGVyKCFzdHJfZGV0ZWN0KGNsaW5pY2FsX3ZhcmlhYmxlLCAiY29yX3Zpc3MiKSkgJT4lICAjIHdlIGZpbHRlciBPVVQgICghKQogICAgZmlsdGVyKCFzdHJfZGV0ZWN0KGNsaW5pY2FsX3ZhcmlhYmxlLCAiX2NvcnRfdmlzcyIpKSAlPiUgICMgZmlsdGVyIG91dCB0aGUgX2NvcnRfdmlzcyBzaW5jZSBpcyBhIHByb3BvcnRpb24KCiAgIyByZXBsYWNlIHRoZSBfYmF6X3Zpc3MsIF9iYXpfdHJhYiBhbmQgX2Jhel9jb3IgdG8gZml4IHRoZSBpc3N1ZSB3aGVuIHJlY29kZSBsYXRlcgogIG11dGF0ZShjbGluaWNhbF92YXJpYWJsZSA9IGdzdWIoInpfIiwgInNhbCIsIGNsaW5pY2FsX3ZhcmlhYmxlKSkgJT4lIAoKICBzZXBhcmF0ZShjbGluaWNhbF92YXJpYWJsZSwKICAgICAgICAgICBpbnRvID0gYygiem9uZSIsICJjbGluaWNhbF92YXJpYWJsZV8yIikpICU+JQogIAoKICBtdXRhdGUoem9uZSA9IGZjdF9yZWNvZGUoCiAgICB6b25lLAogICAgIkluY2lzb3IiID0gIngxIiwKICAgICJDYW5pbmUvUHJlTW9sIiA9ICJ4MiIsCiAgICAiMXN0IE1vbGFyIiA9ICJ4MyIsCiAgICAiMmQgTW9sYXIiID0gIng0IgogICkpICU+JQogIGZpbHRlcih6b25lICE9ICIyZCBNb2xhciIpICU+JSAgIyAyZCBNb2xhcgogIG11dGF0ZSgKICAgIGR4ID0gZmN0X3JlY29kZSgKICAgICAgZHgsCiAgICAgICJOb3JtYWwiID0gIm5vcm1hbCIsCiAgICAgICJPc3Rlb3BlbmlhIiA9ICJvc3Rlb3BlbmlhIiwKICAgICAgIk9zdGVvcG9yb3NpcyIgPSAib3N0ZW9wb3Jvc2lzIgogICAgKQogICkgJT4lCiAgbXV0YXRlKGNsaW5pY2FsX3ZhcmlhYmxlXzIgPSBmY3RfcmVjb2RlKAogICAgY2xpbmljYWxfdmFyaWFibGVfMiwKICAgICJDb3J0aWNhbCIgPSAiY29yIiwKICAgICJUcmFiZWN1bGFlIiA9ICJ0cmFiIiwgCiAgICAiQWxsIEJvbmUiID0gInZpc3MiLCAKICAgICAiQWxsIEJhc2FsIEJvbmUiID0gImJhc2FsdmlzcyIsIAogICAgIlRyYWJlY3VsYWUgQmFzYWwiID0gImJhc2FsdHJhYiIsIAogICAgIkNvcnRpY2FsIEJhc2FsIiA9ICJiYXNhbGNvciIKICApKQpgYGAKCmFkZCBhIG5ldyB2YXJpYWJsZSB0byBtYXJrIHRoZSBvdXRsaWVycy4gSW4gZnV0dXJlIG1vZGVscyBjaGVjayB0aGUgbW9kZWwgd2l0aCBhbmQgd2l0aG91dCBvdXRsaWVycwoKYGBge3J9Cm1lYXN1cmVtZW50c19kYXRhIDwtIG1lYXN1cmVtZW50c19kYXRhICU+JSAKICBtdXRhdGUoel92YWx1ZSA9IHNjYWxlKHZhbHVlKSkgJT4lIAogIG11dGF0ZShvdXRsaWVyID0gY2FzZV93aGVuKAogICAgel92YWx1ZSA+ICsyLjUgfiAieWVzIiwgCiAgICB6X3ZhbHVlIDwgLTIuNSB+ICJ5ZXMiLCAKICAgIFRSVUUgfiAibm8iCiAgKSkKYGBgCgpDaGVjayBhbGwgdGhlIGRhdGFzZXQKYGBge3IsIGluY2x1ZGU9VFJVRX0KaGVhZChtZWFzdXJlbWVudHNfZGF0YSkKYGBgCkNoZWNrIGhvdyBtYW55IG91dGxpZXJzCmBgYHtyLCBpbmNsdWRlPVRSVUV9CnRhYmxlKG1lYXN1cmVtZW50c19kYXRhJG91dGxpZXIpCmBgYAoKIyMjIEdyZXkgVmFsdWVzIGRhdGFzZXQKYGBge3J9CmdyZXlfdmFsdWVzIDwtIGRmICU+JQogIHBpdm90X2xvbmdlcihjMV9heGlhbDpjMV9zYWdpdGFsXzIsCiAgICAgICAgICAgICAgICMgY29sdW1ucyB0byBtZXJnZQogICAgICAgICAgICAgICBuYW1lc190byA9ICJjbGluaWNhbF92YXJpYWJsZSIsCiAgICAgICAgICAgICAgICNuYW1lIG9mIHRoZSBuZXcgY29sdW0gd2l0aCB0aGUgbmFtZXMKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInZhbHVlX2dyZXkiKSAlPiUgICNuYW1lIG9mIHRoZSBuZXcgY29sdW1uIHdpdGggdmFsdWVzCiAgdGliYmxlOjpyb3dpZF90b19jb2x1bW4oLiwgIklEIikgJT4lIAojIHNlbGVjdCBvbmx5IHNvbWUgY29sdW1ucwogIHNlbGVjdChjbGluaWNhbF92YXJpYWJsZSwKICAgICAgICAgdmFsdWVfZ3JleSwKICAgICAgICAgZHgsCiAgICAgICAgIGR4YV93b3JzdCwgCiAgICAgICAgIElELCAKICAgICAgICAgYWdlLCAKICAgICAgICAgbWRfdm9sX2FsbCwgCiAgICAgICAgIG14X3ZvbCkgJT4lCiMgbm9ybWFsaXplIG5hbWVzCiAgbXV0YXRlKGNsaW5pY2FsX3ZhcmlhYmxlID0gY2FzZV93aGVuKAogICAgY2xpbmljYWxfdmFyaWFibGUgPT0gImMxc2FnaXRhbCIgfiAiYzFfc2FnaXRhbCIsIAogICAgY2xpbmljYWxfdmFyaWFibGUgPT0gImMyc2FnaXRhbCIgfiAiYzJfc2FnaXRhbCIsIAogICAgVFJVRSB+IGFzLmNoYXJhY3RlciguJGNsaW5pY2FsX3ZhcmlhYmxlKQogICkpICU+JSAKIyBmaWx0ZXIgb3V0IHNlY29uZCBtZWFzdXJlbWVudHMKICBmaWx0ZXIoIXN0cl9kZXRlY3QoY2xpbmljYWxfdmFyaWFibGUsICIyJCIpKSAlPiUgICMgYWdhaW4KIyBzZXBhcmF0ZSBjbGluaWNhbCB2YXJpYWJsZSBpbiB0d28KICBzZXBhcmF0ZShjbGluaWNhbF92YXJpYWJsZSwKICAgICAgICAgICBpbnRvID0gYygiem9uZSIsICJjbGluaWNhbF92YXJpYWJsZV8yIikpICU+JQogIG11dGF0ZSh6b25lID0gZmN0X3JlY29kZSgKICAgIHpvbmUsCiAgICAiQzEiID0gImMxIiwKICAgICJDMiIgPSAiYzIiCiAgKSkgJT4lCiAgbXV0YXRlKAogICAgZHggPSBmY3RfcmVjb2RlKAogICAgICBkeCwKICAgICAgIk5vcm1hbCIgPSAibm9ybWFsIiwKICAgICAgIk9zdGVvcGVuaWEiID0gIm9zdGVvcGVuaWEiLAogICAgICAiT3N0ZW9wb3Jvc2lzIiA9ICJvc3Rlb3Bvcm9zaXMiCiAgICApCiAgKSAlPiUKICBtdXRhdGUoY2xpbmljYWxfdmFyaWFibGVfMiA9IGZjdF9yZWNvZGUoCiAgICBjbGluaWNhbF92YXJpYWJsZV8yLAogICAgIkF4aWFsIiA9ICJheGlhbCIsCiAgICAiU2FnaXRhbCIgPSAic2FnaXRhbCIKICApKSAlPiUgCiAgbXV0YXRlKG91dGxpZXJfdmFsdWUgPSBzY2FsZSh2YWx1ZV9ncmV5KSkgJT4lIAogIG11dGF0ZShvdXRsaWVyID0gY2FzZV93aGVuKAogICAgb3V0bGllcl92YWx1ZSA8IC0yLjUgfiAieWVzIiwgCiAgICBvdXRsaWVyX3ZhbHVlID4gMi41IH4gInllcyIsIAogICAgVFJVRSB+ICJubyIKICApKQpgYGAKYWRkIGEgbmV3IHZhcmlhYmxlIHRvIG1hcmsgdGhlIG91dGxpZXJzLiBJbiBmdXR1cmUgbW9kZWxzIGNoZWNrIHRoZSBtb2RlbCB3aXRoIGFuZCB3aXRob3V0IG91dGxpZXJzCgoKQ2hlY2sgdGhlIGdyZXkgdmFsdWVzIGRhdGFmcmFtZQpgYGB7ciwgaW5jbHVkZT1UUlVFfQpoZWFkKGdyZXlfdmFsdWVzKQpgYGAKY2hlY2sgdGhlIG91dGxpZXJzCmBgYHtyLCBpbmNsdWRlPVRSVUV9CnRhYmxlKGdyZXlfdmFsdWVzJG91dGxpZXIpCmBgYAoKIyBNYWluIHJlc3VsdAoKIyMgRGVtb2dyYXBoaWMgdGFibGVzCgojIyMgVGFibGUgMQoKYGBge3IsIGluY2x1ZGU9VFJVRX0KZGYgJT4lCiAgIyBzZWxlY3Qgc29tZSB2YXJpYWJsZXMKICBzZWxlY3QoCiAgICBBZ2UgPSBhZ2UsCiAgICBIZWlnaHQgPSBoZWlnaHQsCiAgICBXZWlnaHQgPSB3ZWlnaHQsCiAgICBCTUkgPSBibWksCiAgICBEeCA9IGR4CiAgKSAlPiUKICAjIENyZWF0ZSBzdW1tYXJ5IHRhYmxlCiAgZ3RzdW1tYXJ5Ojp0Ymxfc3VtbWFyeSggCiAgICBieSA9IER4LAogICAgc3RhdGlzdGljID0gbGlzdCgKICAgICAgYWxsX2NvbnRpbnVvdXMoKSB+ICJ7bWVhbn0gKHtzZH0pIiwKICAgICAgYWxsX2NhdGVnb3JpY2FsKCkgfiAie259IC8ge059ICh7cH0lKSIKICAgICkpICU+JQogICMgIyBhZGQgcC12YWx1ZXMsIHJlcG9ydCB0LXRlc3QsIHJvdW5kIGxhcmdlIHB2YWx1ZXMgdG8gdHdvIGRlY2ltYWwgcGxhY2UKICAgICAgZ3RzdW1tYXJ5OjphZGRfcCh0ZXN0ID0gbGlzdChhbGxfY29udGludW91cygpIH4gImFvdiIpLAogICAgICAgICAgICAgICAgIHB2YWx1ZV9mdW4gPSBmdW5jdGlvbih4KSBzdHlsZV9wdmFsdWUoeCwgZGlnaXRzID0gMikpICU+JSAKICBndHN1bW1hcnk6OmFkZF9vdmVyYWxsKCkKYGBgCgoKIyMjIFRhYmxlIDIgTWVhc3VyZW1lbnRzCgoKCmBgYHtyfQp0YWJsZTJiIDwtIHJlYWRfY3N2KCJ0YWJsZTJiLmNzdiIpCmBgYApgYGB7ciwgaW5jbHVkZT1UUlVFfQp0YWJsZTJiICU+JQogICNzZWxlY3QodmlzczpkeCkgJT4lIAogICMgQ3JlYXRlIHN1bW1hcnkgdGFibGUKICBndHN1bW1hcnk6OnRibF9zdW1tYXJ5KCAKICAgIGJ5ID0gZHgsCiAgICBtaXNzaW5nID0gIm5vIiwgCiAgICBzdGF0aXN0aWMgPSBsaXN0KAogICAgICBhbGxfY29udGludW91cygpIH4gInttZWFufSAoe3NkfSkiLAogICAgICBhbGxfY2F0ZWdvcmljYWwoKSB+ICJ7bn0gLyB7Tn0gKHtwfSUpIgogICAgKSkgJT4lCiAgIyAjIGFkZCBwLXZhbHVlcywgcmVwb3J0IHQtdGVzdCwgcm91bmQgbGFyZ2UgcHZhbHVlcyB0byB0d28gZGVjaW1hbCBwbGFjZQogICAgICBndHN1bW1hcnk6OmFkZF9wKHRlc3QgPSBsaXN0KGFsbF9jb250aW51b3VzKCkgfiAiYW92IiksCiAgICAgICAgICAgICAgICAgcHZhbHVlX2Z1biA9IGZ1bmN0aW9uKHgpIHN0eWxlX3B2YWx1ZSh4LCBkaWdpdHMgPSAyKSkgJT4lIAogIGd0c3VtbWFyeTo6YWRkX292ZXJhbGwoKQpgYGAKCgoKCgoKYGBge3IsIGluY2x1ZGU9VFJVRX0KbWVhc3VyZW1lbnRzX2RhdGEgJT4lIAogIGZpbHRlcihvdXRsaWVyID09ICJubyIpICU+JSAKICBmaWx0ZXIoc3RyX2RldGVjdChjbGluaWNhbF92YXJpYWJsZV8yLCAnQmFzYWwnKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGR4LCAKICAgICAgICAgICAgIHkgPSB2YWx1ZSwgCiAgICAgICAgICAgICBjb2xvciA9IGR4KSkgKyAKICBnZW9tX3Zpb2xpbigpICsgCiAgZ2VvbV9ib3hwbG90KHdpZHRoID0gMC4xKSArCiAgZmFjZXRfZ3JpZCh6b25lIH4gY2xpbmljYWxfdmFyaWFibGVfMiApICsgCiAgbGFicyh0aXRsZSA9ICJDb21wYXJpc29uIG9mIG1lYXN1cmVtZW50cyBieSB6b25lIGFuZCBib25lIGZvciBCYXNhbCIsIAogICAgICAgeCA9ICJEeCIsIAogICAgICAgeSA9ICJ2YWx1ZSAobW0pIikgKyAKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCkpICMgb21pdCB0aGUgeCBheGlzIHRleHQKICAgIApgYGAKYGBge3IsIGluY2x1ZGU9VFJVRX0KbWVhc3VyZW1lbnRzX2RhdGEgJT4lIAogIGZpbHRlcihvdXRsaWVyID09ICJubyIpICU+JSAKICBmaWx0ZXIoIXN0cl9kZXRlY3QoY2xpbmljYWxfdmFyaWFibGVfMiwgJ0Jhc2FsJykpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkeCwgCiAgICAgICAgICAgICB5ID0gdmFsdWUsIAogICAgICAgICAgICAgY29sb3IgPSBkeCkpICsgCiAgZ2VvbV92aW9saW4oKSArIAogIGdlb21fYm94cGxvdCh3aWR0aCA9IDAuMSkgKwogIGZhY2V0X2dyaWQoem9uZSB+IGNsaW5pY2FsX3ZhcmlhYmxlXzIgKSArIAogIGxhYnModGl0bGUgPSAiQ29tcGFyaXNvbiBvZiBtZWFzdXJlbWVudHMgYnkgem9uZSBhbmQgYm9uZSBmb3IgQWxsIEJvbmUiLCAKICAgICAgIHggPSAiRHgiLCAKICAgICAgIHkgPSAidmFsdWUgKG1tKSIpICsgCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpKSAjIG9taXQgdGhlIHggYXhpcyB0ZXh0CmBgYAoKVGFibGUgMiBmb3IgcmVmb3JtYXQKYGBge3IsIGluY2x1ZGU9VFJVRX0KZGYgJT4lCiAgc2VsZWN0KAogICAgbWRfdm9sX2FsbCAsCiAgICBtZF92b2xfc21hbGwgLAogICAgbWRfdm9sX2ZvcmFtZSAsCiAgICBteF92b2wgLAogICAgc3RhcnRzX3dpdGgoIngiKSwtZW5kc193aXRoKCJfMiIpLAogICAgRHggPSBkeAogICkgJT4lCiAgZ3RzdW1tYXJ5Ojp0Ymxfc3VtbWFyeSgKICAgIGJ5ID0gRHgsCiAgICBtaXNzaW5nID0gIm5vIiwKICAgIHN0YXRpc3RpYyA9IGxpc3QoCiAgICAgIGFsbF9jb250aW51b3VzKCkgfiAie21lYW59ICh7c2R9KSIsCiAgICAgIGFsbF9jYXRlZ29yaWNhbCgpIH4gIntufSAvIHtOfSAoe3B9JSkiCiAgICApCiAgKSAlPiUKICAjICMgYWRkIHAtdmFsdWVzLCByZXBvcnQgdC10ZXN0LCByb3VuZCBsYXJnZSBwdmFsdWVzIHRvIHR3byBkZWNpbWFsIHBsYWNlCiAgZ3RzdW1tYXJ5OjphZGRfcCgKICAgIHRlc3QgICAgICAgPSBsaXN0KGFsbF9jb250aW51b3VzKCkgfiAiYW92IiksCiAgICBwdmFsdWVfZnVuID0gZnVuY3Rpb24oeCkKICAgICAgc3R5bGVfcHZhbHVlKHgsIGRpZ2l0cyA9IDIpCiAgKQoKCmBgYApJTiB0aGlzIHRhYmxlLCB0aGUgY29tcGFyaXNvbiBhcmVuJ3QgYWRqdXN0ZWQgZm9yIGFueSBvdGhlciB2YXJpYWJsZSwgc28gcGxlYXNlIGNvbnNpZGVyIGFzIGFuIGFwcHJveGltYXRpb24gaW4gb3JkZXIgdG8gdHJ5IHRvIGZpbmQgdGhlIHNpZ25hbCwgdGhhdCBpcyB0aGUgdHJ1ZSBlZmZlY3Qgb3IgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGJvbmUgbWVhc3VyZW1lbnRzIGluIENCQ1QgYW5kIHRoZSBEWEEgc3RhdHVzIAoKTm93LCB3ZSB3aWxsIHRvIHByb2NlZWQgdG8gY3JlYXRlIGEgbW9kZWwgdGhhdCBjb3VsZCBpc29sYXRlIHRoZSBzaWduYWwgKHJlbGF0aW9uIGJldHdlZW4gbWVhc3VyZW1lbnRzIGFuZCBEWEEpIGZyb20gdGhlIG5vaXNlICh3ZWlnaHQ/IGhlaWdodD8gYWdlPykKIyMgTWVhc3VyZW1lbnRzCiBXaXRoIHRoZSBvdXRsaWVycwogCmBgYHtyLCBpbmNsdWRlPVRSVUV9Cm1lYXN1cmVtZW50c19kYXRhICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkeGFfd29yc3QsIAogICAgICAgICAgICAgeSA9IHZhbHVlKSkgKyAKICBnZW9tX2ppdHRlcihhbHBoYSA9IC4wMSkgKyAKICBnZW9tX3Ntb290aCgpIApgYGAKU2VlbXMgdG8gYmUgYSBwb3NpdGl2ZSBjb3JyZWxhdGlvbiwgdGhhdCBpcywgbW9yZSBEWEEsIG1vcmUgbW0uIE5vdyBsZXRzIGNoZWNrIGRpdmlkZWQgYnkgYXJlYSBhbmQgYm9uZSAKYGBge3IsIGluY2x1ZGU9VFJVRX0KbWVhc3VyZW1lbnRzX2RhdGEgJT4lIAogIGdncGxvdChhZXMoeCA9IGR4YV93b3JzdCwgCiAgICAgICAgICAgICB5ID0gdmFsdWUpKSArIAogIGdlb21faml0dGVyKGFscGhhID0gLjEpICsgCiAgZ2VvbV9zbW9vdGgoKSArIAogIGZhY2V0X2dyaWQoem9uZSB+IGNsaW5pY2FsX3ZhcmlhYmxlXzIgICkKYGBgCioqVGhpcyBncmFwaCBzaG93cyB0aGF0IHRoZSBEWEEgbWVhc3VyZWQgaW4gaGlwIG9yIGx1bWJhciB2ZXJ0ZWJyYWUgc2VlbXMgdG8gYmUgY29ycmVsYXRlZCB0byAgdGhlIG1lYXN1cmVtZW50cyBtYWRlIGluIHRoZSBjb3J0aWNhbCBib25lIGluIHRoZSBDQkNUKioKCgojIyMgSXMgdGhlcmUgYW55IGFzc29jaWF0aW9uIGJldHdlZW4gdGhlIERYQSB2YWx1ZXMgYW5kIHRoZSBtZWFzdXJlbWVudHM/IENvbnRpbnVvcyBEWEEgdmFsdWVzCkxldHMgY2hlY2sgdGhlIGVmZmVjdCBvZiB0aGUgb3V0bGllcnMKCmBgYHtyLCBpbmNsdWRlPVRSVUV9Cm1lYXN1cmVtZW50c19kYXRhICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkeGFfd29yc3QsIAogICAgICAgICAgICAgeSA9IHZhbHVlLCAKICAgICAgICAgICAgIGNvbG9yID0gb3V0bGllcikpICsgCiAgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAuNCkgKyAKICBnZW9tX3Ntb290aCgpIApgYGAKVGhlIG91dGxpZXJzIG9ubHkgYWRkIG5vaXNlIHRvIHRoZSBzaWduYWwKCmBgYHtyLCBpbmNsdWRlPVRSVUV9Cm1lYXN1cmVtZW50c19kYXRhICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkeGFfd29yc3QsIAogICAgICAgICAgICAgeSA9IHZhbHVlLCAKICAgICAgICAgICAgIGNvbG9yID0gb3V0bGllcikpICsgCiAgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAuMikgKyAKICBnZW9tX3Ntb290aCgpICsgCiAgZmFjZXRfZ3JpZCh6b25lfmNsaW5pY2FsX3ZhcmlhYmxlXzIpCmBgYApOb3RlIHRoYXQgdGhlIG91dGxpZXJzIGFkZCBub2lzZSB0byB0aGUgc2lnbmFsLCBoZW5jZSB3aWxsIGJlIHJlbW92ZWQgZnJvbSBhbnkgZnVydGhlciBhbmFseXNpcwpgYGB7ciwgaW5jbHVkZT1UUlVFfQptZWFzdXJlbWVudHNfZGF0YSAlPiUgCiAgZmlsdGVyKG91dGxpZXIgPT0gIm5vIikgJT4lIAogICBnbG0odmFsdWUgfiBkeGFfd29yc3QsIGRhdGEgPSAuKSAlPiUgCiAgc3VtbWFyeSgpCmBgYAoKYGBge3IsIGluY2x1ZGU9VFJVRX0KbWVhc3VyZW1lbnRzX2RhdGEgJT4lIAogIGZpbHRlcihvdXRsaWVyID09ICJubyIpICU+JSAKICAgZ2xtKHZhbHVlIH4gZHhhX3dvcnN0LCBkYXRhID0gLikgJT4lIAogIGp0b29sczo6c3VtbSguKQpgYGAKVGhlIGJhc2VsaW5lIHZhbHVlIGZvciBtZWFzdXJlbWVudHMgaXMgODQgYW5kIGZvciBldmVyeSBhZGRpdGlvbmFsIHBvaW50IGluIERYQSwgdGhlIG1lYXN1cmVtZW50IHZhbHVlIGluY3JlYXNlIGluIDIuOTcgKHA8MC4wMSkKClRoaXMgbW9kZWwgZXhwbGFpbiAqKnZlcnkgbGl0dGxlKiogb2YgdGhlIHZhcmlhbmNlIG9mIHRoZSBtZWFzdXJlbWVudHMsIG9ubHkgMSUgKHNlZSBSMiksICpidXQqIHRoZXJlIGlzIGEgc2lnbmFsLiBXZSBhcmUgaW50ZXJlc3RlZCBpbiBpZGVudGlmeSBpZiB0aGlzIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSBpcyBhbHNvIGNsaW5pY2FsbHkgcmVsZXZhbnQuIAoKQnV0IGl0IGNvdWxkIGJlIHRoYXQgb25lIGdyb3VwIGlzIGJpZ2dlciwgb3IgaGVhdmllciwgb3Igb2xkZXIuICBMZXQncyBpZGVudGlmeSBpZiB0aGUgZGlmZmVyZW5jZSBpcyBrZXB0IGluIGNoZWNrIGJ5IG90aGVyIGZhY3RvcnMuIAoKYGBge3IsIGluY2x1ZGU9VFJVRX0KbWVhc3VyZW1lbnRzX2RhdGEgJT4lCiAgZmlsdGVyKG91dGxpZXIgPT0gIm5vIikgJT4lCiAgZ2xtKHZhbHVlIH4gZHhhX3dvcnN0ICsgCiAgICAgICAgYWdlICsKICAgICAgICBtZF92b2xfYWxsICsKICAgICAgICBteF92b2wgKwogICAgICAgIElELAogICAgICBkYXRhID0gLikgJT4lIAogIGp0b29sczo6c3VtbSgpCmBgYApBZGp1c3RpbmcgZm9yIGFsbCB0aGUgdmFyaWFibGVzIHNlZW1zIHRoYXQgdGhlIHNpZ25hbCBkaXNhcHBlYXIsIGJ1dCB3ZSBoYXZlbid0IHlldCBhZGp1c3RlZCBieSB6b25lIGFuZCBjbGluaWNhbF92YXJpYWJsZV8yIChiYXNhbCwgY29ydCwgYWxsKQoKTm93IGV4cGxvcmUgYnkgem9uZSBhbmQgdHlwZSBvZiBib25lLCBtYXliZSB0aGVyZSBhcmUgc29tZSBpbnRlcmFjdGlvbiBieSB6b25lIGFuZCB3aGF0IGlzIGJlaW5nIG1lYXN1cmVkIChjb3J0Y2FsLCB0cmFiZWN1bGFlLCBldGMpLiBMZXQncyBjaGVjawoKRmlyc3QsIHRha2UgYSBsb29rIGF0IHRoZSBncmFwaDogCgpgYGB7ciwgaW5jbHVkZT1UUlVFfQptZWFzdXJlbWVudHNfZGF0YSAlPiUKICBmaWx0ZXIob3V0bGllciA9PSAibm8iKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkeGFfd29yc3QsCiAgICAgICAgICAgICB5ID0gdmFsdWUpKSArCiAgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAuMDEpICsKICBnZW9tX3Ntb290aCgpICsKICBmYWNldF9ncmlkKHpvbmUgfiBjbGluaWNhbF92YXJpYWJsZV8yKSArIAogIGxhYnModGl0bGUgPSAiTWVhc3VyZW1lbnRzIGJ5IGFyZWEgYW5kIGJvbmUgKG91dGxpZXJzIGV4Y2x1ZGVkKSIpCgpgYGAKCmFuZCB0aGUgcmVncmVzc2lvbiBtb2RlbCBpczogCmBgYHtyLCBpbmNsdWRlPVRSVUV9Cm1lYXN1cmVtZW50c19kYXRhICU+JQogIGZpbHRlcihvdXRsaWVyID09ICJubyIpICU+JQogIHJlbmFtZSgiQm9uZSIgPSBjbGluaWNhbF92YXJpYWJsZV8yLCAKICAgICAgICAgIlpvbmUiID0gem9uZSkgJT4lIAogIGdsbSgKICAgIHZhbHVlIH4KICAgICAgZHhhX3dvcnN0ICsKICAgICAgYWdlICsKICAgICAgYm1pICsKICAgICAgbWRfdm9sX2FsbCArCiAgICAgIElELAogICAgZGF0YSA9IC4sCiAgICBmYW1pbHkgPSBnYXVzc2lhbigpCiAgKSAlPiUKICAganRvb2xzOjpzdW1tKCkKCmBgYApXaGVuIGFkanVzdGVkIGZvciBhZ2UgYW5kIG1hbm5kL21heCB2b2x1bWUsIHRoZSBzaWduYWwgaXMgbG9zdC4gCgpOb3csIHdlIHdpbGwgbWFrZSA2IHJlZ3Jlc3Npb24gbW9kZWxzIC0gZm9yIGV2ZXJ5IGJvbmUgdHlwZSBzZXBhcmF0ZWx5LgoKIyMjIDEuIENvcnRpY2FsIEJhc2FsCgpgYGB7ciwgaW5jbHVkZT1UUlVFfQptZWFzdXJlbWVudHNfZGF0YSAlPiUKICBmaWx0ZXIob3V0bGllciA9PSAibm8iKSAlPiUKICByZW5hbWUoIkJvbmUiID0gY2xpbmljYWxfdmFyaWFibGVfMiwgCiAgICAgICAgICJab25lIiA9IHpvbmUpICU+JSAKICBmaWx0ZXIoQm9uZSA9PSAiQ29ydGljYWwgQmFzYWwiKSAlPiUgICMgb25seSBjb3J0aWNhbAogIGdsbSgKICAgIHZhbHVlIH4KICAgICAgZHhhX3dvcnN0ICsKICAgICAgYWdlICsKICAgICAgYm1pICsKICAgICAgbWRfdm9sX2FsbCArCiAgICAgIElELAogICAgZGF0YSA9IC4sCiAgICBmYW1pbHkgPSBnYXVzc2lhbigpCiAgKSAlPiUKICAganRvb2xzOjpzdW1tKCkKCgpgYGAKIyMjIDIuIFRyYWJlY3VsYWUgQmFzYWwKCmBgYHtyLCBpbmNsdWRlPVRSVUV9Cm1lYXN1cmVtZW50c19kYXRhICU+JQogIGZpbHRlcihvdXRsaWVyID09ICJubyIpICU+JQogIHJlbmFtZSgiQm9uZSIgPSBjbGluaWNhbF92YXJpYWJsZV8yLCAKICAgICAgICAgIlpvbmUiID0gem9uZSkgJT4lIAogIGZpbHRlcihCb25lID09ICJUcmFiZWN1bGFlIEJhc2FsIikgJT4lICAjIG9ubHkgdHJhYmVjdWxhciBiYXNhbAogIGdsbSgKICAgIHZhbHVlIH4KICAgICAgZHhhX3dvcnN0ICsKICAgICAgYWdlICsKICAgICAgYm1pICsKICAgICAgbWRfdm9sX2FsbCArCiAgICAgIElELAogICAgZGF0YSA9IC4sCiAgICBmYW1pbHkgPSBnYXVzc2lhbigpCiAgKSAlPiUKICAganRvb2xzOjpzdW1tKCkKCmBgYAojIyMgMy4gQWxsIEJhc2FsIEJvbmUKCmBgYHtyLCBpbmNsdWRlPVRSVUV9Cm1lYXN1cmVtZW50c19kYXRhICU+JQogIGZpbHRlcihvdXRsaWVyID09ICJubyIpICU+JQogIHJlbmFtZSgiQm9uZSIgPSBjbGluaWNhbF92YXJpYWJsZV8yLCAKICAgICAgICAgIlpvbmUiID0gem9uZSkgJT4lIAogIGZpbHRlcihCb25lID09ICJBbGwgQmFzYWwgQm9uZSIpICU+JSAgIyBhbGwgYmFzYWwKICBnbG0oCiAgICB2YWx1ZSB+CiAgICAgIGR4YV93b3JzdCArCiAgICAgIGFnZSArCiAgICAgIGJtaSArCiAgICAgIG1kX3ZvbF9hbGwgKwogICAgICBJRCwKICAgIGRhdGEgPSAuLAogICAgZmFtaWx5ID0gZ2F1c3NpYW4oKQogICkgJT4lCiAganRvb2xzOjpzdW1tKCkKCgpgYGAKCiMjIyA0LiBDb3J0aWNhbAoKYGBge3IsIGluY2x1ZGU9VFJVRX0KbWVhc3VyZW1lbnRzX2RhdGEgJT4lCiAgZmlsdGVyKG91dGxpZXIgPT0gIm5vIikgJT4lCiAgcmVuYW1lKCJCb25lIiA9IGNsaW5pY2FsX3ZhcmlhYmxlXzIsIAogICAgICAgICAiWm9uZSIgPSB6b25lKSAlPiUgCiAgZmlsdGVyKEJvbmUgPT0gIkNvcnRpY2FsIikgJT4lICAjIG9ubHkgY29ydGljYWwKICBnbG0oCiAgICB2YWx1ZSB+CiAgICAgIGR4YV93b3JzdCArCiAgICAgIGFnZSArCiAgICAgIGJtaSArCiAgICAgIG1kX3ZvbF9hbGwgKwogICAgICBJRCwKICAgIGRhdGEgPSAuLAogICAgZmFtaWx5ID0gZ2F1c3NpYW4oKQogICkgJT4lCiAgIGp0b29sczo6c3VtbSgpCgoKYGBgCgojIyMgNS4gVHJhYmVjdWxhZQoKYGBge3IsIGluY2x1ZGU9VFJVRX0KbWVhc3VyZW1lbnRzX2RhdGEgJT4lCiAgZmlsdGVyKG91dGxpZXIgPT0gIm5vIikgJT4lCiAgcmVuYW1lKCJCb25lIiA9IGNsaW5pY2FsX3ZhcmlhYmxlXzIsIAogICAgICAgICAiWm9uZSIgPSB6b25lKSAlPiUgCiAgZmlsdGVyKEJvbmUgPT0gIlRyYWJlY3VsYWUiKSAlPiUgICMgb25seSB0cmFiZWN1bGFyCiAgZ2xtKAogICAgdmFsdWUgfgogICAgICBkeGFfd29yc3QgKwogICAgICBhZ2UgKwogICAgICBibWkgKwogICAgICBtZF92b2xfYWxsICsKICAgICAgSUQsCiAgICBkYXRhID0gLiwKICAgIGZhbWlseSA9IGdhdXNzaWFuKCkKICApICU+JQogICBqdG9vbHM6OnN1bW0oKQoKCmBgYAoKIyMjIDYuIEFsbCBCb25lCgpgYGB7ciwgaW5jbHVkZT1UUlVFfQptZWFzdXJlbWVudHNfZGF0YSAlPiUKICBmaWx0ZXIob3V0bGllciA9PSAibm8iKSAlPiUKICByZW5hbWUoIkJvbmUiID0gY2xpbmljYWxfdmFyaWFibGVfMiwgCiAgICAgICAgICJab25lIiA9IHpvbmUpICU+JSAKICBmaWx0ZXIoQm9uZSA9PSAiQWxsIEJvbmUiKSAlPiUgICMgQWxsIEJvbmUKICBnbG0oCiAgICB2YWx1ZSB+CiAgICAgIGR4YV93b3JzdCArCiAgICAgIGFnZSArCiAgICAgIGJtaSArCiAgICAgIG1kX3ZvbF9hbGwgKwogICAgICBJRCwKICAgIGRhdGEgPSAuLAogICAgZmFtaWx5ID0gZ2F1c3NpYW4oKQogICkgJT4lCiAgIGp0b29sczo6c3VtbSgpCgoKYGBgCiMjIyBBbmQgbm93IGxldHMgc2VlIGlmIGFsbCBjb3J0aWNhbCBjb3VsZCBiZSBiZXR0ZXIgbW9kZWw6CgpgYGB7ciwgaW5jbHVkZT1UUlVFfQptZWFzdXJlbWVudHNfZGF0YSAlPiUKICBmaWx0ZXIob3V0bGllciA9PSAibm8iKSAlPiUKICByZW5hbWUoIkJvbmUiID0gY2xpbmljYWxfdmFyaWFibGVfMiwgCiAgICAgICAgICJab25lIiA9IHpvbmUpICU+JSAKICBmaWx0ZXIoQm9uZSAlaW4lIGMoIkNvcnRpY2FsIiwgIkNvcnRpY2FsIEJhc2FsIikpICU+JSAgIyBBbGwgQ29ydGljYWwKICBnbG0oCiAgICB2YWx1ZSB+CiAgICAgIGR4YV93b3JzdCArCiAgICAgIGFnZSArCiAgICAgIGJtaSArCiAgICAgIG1kX3ZvbF9hbGwgKwogICAgICBJRCwKICAgIGRhdGEgPSAuLAogICAgZmFtaWx5ID0gZ2F1c3NpYW4oKQogICkgJT4lCiAgIGp0b29sczo6c3VtbSgpCgoKYGBgCkxvb2tpbmcgYXQgZ3JhcGhzIHdlIHdvdWxkIGV4cGVjdCB0aGF0IGFsbCB0cmFiZWN1bGFyIHNob3VsZCBiZSB3b3JzZToKCmBgYHtyLCBpbmNsdWRlPVRSVUV9Cm1lYXN1cmVtZW50c19kYXRhICU+JQogIGZpbHRlcihvdXRsaWVyID09ICJubyIpICU+JQogIHJlbmFtZSgiQm9uZSIgPSBjbGluaWNhbF92YXJpYWJsZV8yLCAKICAgICAgICAgIlpvbmUiID0gem9uZSkgJT4lIAogIGZpbHRlcihCb25lICVpbiUgYygiVHJhYmVjdWxhZSIsICJUcmFiZWN1bGFlIEJhc2FsIikpICU+JSAgIyBBbGwgdHJhYmVjdWxhcgogIGdsbSgKICAgIHZhbHVlIH4KICAgICAgZHhhX3dvcnN0ICsKICAgICAgYWdlICsKICAgICAgYm1pICsKICAgICAgbWRfdm9sX2FsbCArCiAgICAgIElELAogICAgZGF0YSA9IC4sCiAgICBmYW1pbHkgPSBnYXVzc2lhbigpCiAgKSAlPiUKICAganRvb2xzOjpzdW1tKCkKCgpgYGAKLi4uIGJ1dCBpdCBpcyBub3QgdHJ1ZS4KU28sIHRoZSBjb25jbHVzaW9uIGNvdWxkIGJlIHRoYXQgdGhlIHJlbGF0aW9uIGJldHdlZW4gRFhBIGFuZCBtZWFzdXJlbWVudHMgaW4gQ0JDVCBpbiBtYW5kaWJsZSBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LCBidXQgbWF5YmUgdGhlIHJlbGF0aW9uIGlzIG5vdCBjbGluaWNhbGx5IHNpZ25pZmljYW50LgoKTWF5YmUgdGhlIG1vZGVscyBhcmUgYmV0dGVyIGluIHNvbWUgYWdlIGdyb3VwPwoKYGBge3IsIGluY2x1ZGU9VFJVRX0KbWVhc3VyZW1lbnRzX2RhdGEgJT4lCiAgZmlsdGVyKG91dGxpZXIgPT0gIm5vIikgJT4lCiAgcmVuYW1lKCJCb25lIiA9IGNsaW5pY2FsX3ZhcmlhYmxlXzIsIAogICAgICAgICAiWm9uZSIgPSB6b25lKSAlPiUgCiAgZmlsdGVyKEJvbmUgJWluJSBjKCJDb3J0aWNhbCIsICJDb3J0aWNhbCBCYXNhbCIpKSAlPiUgICMgQWxsIENvcnRpY2FsCiAgZmlsdGVyKGFnZSA+PSAiNjUiICYgYWdlIDw9ICI3NCIpICU+JSAKICBnbG0oCiAgICB2YWx1ZSB+CiAgICAgIGR4YV93b3JzdCArCiAgICAgIGFnZSArCiAgICAgIGJtaSArCiAgICAgIG1kX3ZvbF9hbGwgKwogICAgICBJRCwKICAgIGRhdGEgPSAuLAogICAgZmFtaWx5ID0gZ2F1c3NpYW4oKQogICkgJT4lCiAgIGp0b29sczo6c3VtbSgpCgoKYGBgCgoKCgoKIyMgR3JleSBWYWx1ZXMKCmBgYHtyLCBpbmNsdWRlPVRSVUV9CmRmICU+JQogIHNlbGVjdCgiQzEgQXhpYWwiID0gYzFfYXhpYWwgLAogICAgICAgICAiQzEgU2FnaXRhbCIgPSBjMXNhZ2l0YWwgLAogICAgICAgICAiQzIgQXhpYWwiID0gYzJfYXhpYWwgLAogICAgICAgICAiQzIgU2FnaXRhbCIgPSBjMnNhZ2l0YWwsCiAgICAgICAgICJEeCIgPSBkeCkgJT4lCiAgZ3RzdW1tYXJ5Ojp0Ymxfc3VtbWFyeShieSA9IER4LCBtaXNzaW5nID0gIm5vIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGlzdGljID0gbGlzdChhbGxfY29udGludW91cygpIH4gInttZWFufSAoe3NkfSkiLAogICAgICAgICAgICAgICAgICAgICBhbGxfY2F0ZWdvcmljYWwoKSB+ICJ7cH0lIikgIyBzZWxlY3QgYnkgc3VtbWFyeSB0eXBlCiAgKSAlPiUKICAjICMgYWRkIHAtdmFsdWVzLCByZXBvcnQgdC10ZXN0LCByb3VuZCBsYXJnZSBwdmFsdWVzIHRvIHR3byBkZWNpbWFsIHBsYWNlCiAgICAgIGd0c3VtbWFyeTo6YWRkX3AodGVzdCA9IGxpc3QoYWxsX2NvbnRpbnVvdXMoKSB+ICJhb3YiKSwKICAgICAgICAgICAgICAgICBwdmFsdWVfZnVuID0gZnVuY3Rpb24oeCkgc3R5bGVfcHZhbHVlKHgsIGRpZ2l0cyA9IDIpKSAlPiUgCiAgZ3RzdW1tYXJ5OjphZGRfb3ZlcmFsbCgpCmBgYAoKIyMjIElzIHRoZXJlIGFueSBhc3NvY2lhdGlvbiBiZXR3ZWVuIHRoZSBncmV5IHZhbHVlcyBhbmQgdGhlIG1lYXN1cmVtZW50cz8gQ29udGludW9zIERYQSB2YWx1ZXMKClZpc3VhbGlzZSB0aGUgb3ZlcmFsbCBjb3JyZWxhdGlvbgpgYGB7ciwgaW5jbHVkZT1UUlVFfQpncmV5X3ZhbHVlcyAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZHhhX3dvcnN0LCAKICAgICAgICAgICAgIHkgPSB2YWx1ZV9ncmV5KSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gLjMpICsgCiAgZ2VvbV9zbW9vdGgoKQpgYGAKCkNoZWNrIHRoZSBlZmZlY3Qgb2YgdGhlIG91dGxpZXJzCmBgYHtyLCBpbmNsdWRlPVRSVUV9CmdyZXlfdmFsdWVzICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkeGFfd29yc3QsIAogICAgICAgICAgICAgeSA9ICB2YWx1ZV9ncmV5LCAKICAgICAgICAgICAgIGNvbG9yID0gb3V0bGllcikpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykgKyAKICBnZW9tX3Ntb290aCgpCmBgYApQbG90IHdpdGhvdXQgdGhlIG91dGxpZXJzCmBgYHtyLCBpbmNsdWRlPVRSVUV9CmdyZXlfdmFsdWVzICU+JQogIGZpbHRlcihvdXRsaWVyID09ICJubyIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkeGFfd29yc3QsIAogICAgICAgICAgICAgeSA9ICB2YWx1ZV9ncmV5KSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gLjMpICsgCiAgZ2VvbV9zbW9vdGgoKQpgYGAKYGBge3IsIGluY2x1ZGU9VFJVRX0KZ3JleV92YWx1ZXMgJT4lCiAgZmlsdGVyKG91dGxpZXIgPT0gIm5vIikgJT4lIAogIGdncGxvdChhZXMoeCA9IGR4YV93b3JzdCwgCiAgICAgICAgICAgICB5ID0gIHZhbHVlX2dyZXkpKSArIAogIGdlb21fcG9pbnQoYWxwaGEgPSAuMykgKyAKICBnZW9tX3Ntb290aCgpICsgCiAgZmFjZXRfZ3JpZChjbGluaWNhbF92YXJpYWJsZV8yIH4gem9uZSkKYGBgCmBgYHtyLCBpbmNsdWRlPVRSVUV9CmdyZXlfdmFsdWVzICU+JSAKICBnbG0odmFsdWVfZ3JleSB+IGR4YV93b3JzdCwgZGF0YSA9IC4pICU+JSAKICAjIHN1bW1hcnkoKQogIGp0b29sczo6c3VtbSgpCmBgYApUaGUgYmFzZWxpbmUgZ3JleSB2YWx1ZSBpcyAxMjMgYW5kIGZvciBlYWNoIERYQSBwb2ludCwgdGhlIGdyZXkgdmFsdWVzIGluY3JlbWVudCArMjQKCiMjIyBJcyB0aGVyZSBhbnkgYXNzb2NpYXRpb24gYmV0d2VlbiB0aGUgZ3JleSB2YWx1ZXMgYW5kIHRoZSBtZWFzdXJlbWVudHM/IE9yZGluYWwgRHggdmFsdWVzIChOb3JtYWwsIE9zdGVvcGVuaWEsIE9zdGVvcG9yb3NpcykKCmBgYHtyLCBpbmNsdWRlPVRSVUV9CmdyZXlfdmFsdWVzICU+JSAKICBmaWx0ZXIob3V0bGllciA9PSAibm8iKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZHgsIAogICAgICAgICAgICAgeSA9IHZhbHVlX2dyZXksIAogICAgICAgICAgICAgY29sb3IgPSBkeCkpICsgCiAgZ2VvbV92aW9saW4oKSArIAogIGdlb21fYm94cGxvdCh3aWR0aCA9IDAuMikgKyAKICBsYWJzKHRpdGxlID0gIkdyZXkgdmFsdWVzIGFuZCBkeCBzdGF0dXMiLCAKICAgICAgIHkgPSAiR3JleSBWYWx1ZSIsIAogICAgICAgeCA9ICJEeCIpCiAgCmBgYApgYGB7ciwgaW5jbHVkZT1UUlVFfQpncmV5X3ZhbHVlcyAlPiUgCiAgZmlsdGVyKG91dGxpZXIgPT0gIm5vIikgJT4lIAogIGdncGxvdChhZXMoeCA9IGR4LCAKICAgICAgICAgICAgIHkgPSB2YWx1ZV9ncmV5LCAKICAgICAgICAgICAgIGNvbG9yID0gZHgpKSArIAogIGdlb21fdmlvbGluKCkgKyAKICBnZW9tX2JveHBsb3Qod2lkdGggPSAwLjIpICsgCiAgZmFjZXRfZ3JpZChjbGluaWNhbF92YXJpYWJsZV8yIH4gem9uZSkgKyAKICBsYWJzKHRpdGxlID0gIkdyZXkgdmFsdWVzIGFuZCBEeCBieSBWZXJ0ZWJyYWUgYW5kIEF4aXMgKFNhZ2l0YWwsIEF4aWFsKSAiLCAKICAgICAgIHkgPSAiR3JleSBWYWx1ZSIsIAogICAgICAgeCA9ICJEeCIpCmBgYAoKCgojIFJlbGlhYmlsaXR5IGFuYWx5c2lzOiBhcmUgdGhlIG1lYXN1cmVtZW50cyByZWxpYWJsZT8KCgpTZWUgCgpLb28sIFRlcnJ5LCBhbmQgTWFlIExpLiAyMDE2LiDigJxBIEd1aWRlbGluZSBvZiBTZWxlY3RpbmcgYW5kIFJlcG9ydGluZyBJbnRyYWNsYXNzIENvcnJlbGF0aW9uIENvZWZmaWNpZW50cyBmb3IgUmVsaWFiaWxpdHkgUmVzZWFyY2gu4oCdIEpvdXJuYWwgb2YgQ2hpcm9wcmFjdGljIE1lZGljaW5lIDE1IChNYXJjaCkuIGRvaToxMC4xMDE2L2ouamNtLjIwMTYuMDIuMDEyLgoKU2hyb3V0LCBQLkUuLCBhbmQgSi5MLiBGbGVpc3MuIDE5NzkuIOKAnEludHJhY2xhc3MgQ29ycmVsYXRpb246IFVzZXMgaW4gQXNzZXNzaW5nIFJhdGVyIFJlbGlhYmlsaXR5LuKAnSBQc3ljaG9sb2dpY2FsIEJ1bGxldGluIDg2OiA0MjDigJMyOC4KCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQpwYWNtYW46OnBfbG9hZChpcnIpICMgcGFja2FnZSB0byBjYWxjdWxhdGUgdGhlIElDQwoKYGBgCgpgYGB7cn0KYWdyZWVtZW50IDwtIGRmICU+JQogIHNlbGVjdCgKICAgICJ4MV92aXNzIiwKICAgICJ4MV92aXNzXzIiLAogICAgIngxX3RyYWIiLAogICAgIngxX3RyYWJfMiIsCiAgICAieDFfYmF6X3Zpc3MiLAogICAgIngxX2Jhel92aXNzXzIiLAogICAgIngxX2Jhel90cmFiIiwKICAgICJ4MV9iYXpfdHJhYl8yIiwKICAgICJjMV9heGlhbCIsCiAgICAiYzFfYXhpYWxfMiIsCiAgICAiYzFzYWdpdGFsIiwKICAgICJjMV9zYWdpdGFsXzIiCiAgKQpgYGAKIyMjIEZvciB4MV92aXNzCmBgYHtyLCBpbmNsdWRlPVRSVUV9CgphZ3JlZW1lbnQgJT4lCiAgc2VsZWN0KCJ4MV92aXNzIiwKICAgICAgICAgIngxX3Zpc3NfMiIpICU+JQogIGZpbHRlcih4MV92aXNzXzIgPiAwKSAlPiUKICBpcnI6OmljYyguLAogICAgICAgICAgIG1vZGVsID0gInR3b3dheSIsCiAgICAgICAgICAgdHlwZSA9ICJhZ3JlZW1lbnQiLAogICAgICAgICAgIHVuaXQgPSAic2luZ2xlIikKYGBgCiMjIyBGb3IgeDFfdHJhYgpgYGB7ciwgaW5jbHVkZT1UUlVFfQogIAphZ3JlZW1lbnQgJT4lCiAgc2VsZWN0KCAgICAieDFfdHJhYiIsCiAgICAieDFfdHJhYl8yIikgJT4lCiAgZmlsdGVyKHgxX3RyYWJfMiA+IDApICU+JQogIGlycjo6aWNjKC4sCiAgICAgICAgICAgbW9kZWwgPSAidHdvd2F5IiwKICAgICAgICAgICB0eXBlID0gImFncmVlbWVudCIsCiAgICAgICAgICAgdW5pdCA9ICJzaW5nbGUiKQoKCmBgYAojIyMgRm9yIHgxX2Jhel92aXNzCmBgYHtyLCBpbmNsdWRlPVRSVUV9CmFncmVlbWVudCAlPiUKICBzZWxlY3QoIngxX2Jhel92aXNzIiwKICAgICJ4MV9iYXpfdmlzc18yIikgJT4lCiAgZmlsdGVyKHgxX2Jhel92aXNzXzIgPiAwKSAlPiUKICBpcnI6OmljYyguLAogICAgICAgICAgIG1vZGVsID0gInR3b3dheSIsCiAgICAgICAgICAgdHlwZSA9ICJhZ3JlZW1lbnQiLAogICAgICAgICAgIHVuaXQgPSAic2luZ2xlIikKCmBgYAojIyMgRm9yIHgxX2Jhel90cmFiCmBgYHtyLCBpbmNsdWRlPVRSVUV9CgphZ3JlZW1lbnQgJT4lCiAgc2VsZWN0KCJ4MV9iYXpfdHJhYiIsCiAgICAieDFfYmF6X3RyYWJfMiIpICU+JQogIGZpbHRlcih4MV9iYXpfdHJhYl8yID4gMCkgJT4lCiAgaXJyOjppY2MoLiwKICAgICAgICAgICBtb2RlbCA9ICJ0d293YXkiLAogICAgICAgICAgIHR5cGUgPSAiYWdyZWVtZW50IiwKICAgICAgICAgICB1bml0ID0gInNpbmdsZSIpCgpgYGAKCiMjIyBGb3IgYzFfYXhpYWwKYGBge3IsIGluY2x1ZGU9VFJVRX0KCmFncmVlbWVudCAlPiUKICBzZWxlY3QoImMxX2F4aWFsIiwKICAgICJjMV9heGlhbF8yIikgJT4lCiAgZmlsdGVyKGMxX2F4aWFsXzIgPiAwKSAlPiUKICBpcnI6OmljYyguLAogICAgICAgICAgIG1vZGVsID0gInR3b3dheSIsCiAgICAgICAgICAgdHlwZSA9ICJhZ3JlZW1lbnQiLAogICAgICAgICAgIHVuaXQgPSAic2luZ2xlIikKCmBgYAoKIyMjIEZvciBjMV9zYWdpdGFsCmBgYHtyLCBpbmNsdWRlPVRSVUV9CmFncmVlbWVudCAlPiUKICBzZWxlY3QoImMxc2FnaXRhbCIsCiAgICAiYzFfc2FnaXRhbF8yIikgJT4lCiAgZmlsdGVyKGMxX3NhZ2l0YWxfMiA+IDApICU+JQogIGlycjo6aWNjKC4sCiAgICAgICAgICAgbW9kZWwgPSAidHdvd2F5IiwKICAgICAgICAgICB0eXBlID0gImFncmVlbWVudCIsCiAgICAgICAgICAgdW5pdCA9ICJzaW5nbGUiKQpgYGAKYGBge3J9CnJtKGFncmVlbWVudCkKYGBgCgpFdmVyeSBtZWFzdXJlbWVudCBoYXMgYWxtb3N0IHBlcmZlY3QgcmVsaWFiaWxpdHkKCiMjIyBCTGFuZCBBbHRtYW4gcGxvdHMgZm9yIGdyZXkgdmFsdWVzCgpgYGB7ciwgaW5jbHVkZT1UUlVFfQpCbGFuZEFsdG1hbkxlaDo6YmxhbmQuYWx0bWFuLnBsb3QoZGYkYzFfYXhpYWwsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGYkYzFfYXhpYWxfMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYWluPSJDMSBheGlhbCIpCmBgYApgYGB7ciwgaW5jbHVkZT1UUlVFfQpCbGFuZEFsdG1hbkxlaDo6YmxhbmQuYWx0bWFuLnBsb3QoZGYkYzFzYWdpdGFsLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRmJGMxX3NhZ2l0YWxfMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYWluPSJDMSBTYWdpdGFsIikKYGBgCgoK