Introduction
The results here accompany the paper “Effective Ways to Build and Evaluate Individual Survival Distributions” by Haider et al. In total, 33 additional datasets were tested to validate the findings given by Table 7 in Section 5 of the paper. For each of (Low-Censoring, Low-Dimensional), (High-Censoring, Low-Dimensional), (Low-Censoring, High-Dimensional), and (High-Censoring, High-Dimensional) we have 16, 12, 4, and 1 additional datasets to check the generalization of the findings. Each following section gives further details about the corresponding datasets used. Here we have defined “High-Censoring” to be \(\geq\) 70%. Additionally, “High-Dimensional” datasets all have at least 274 features.
Low-Censoring, Low-Dimensional
All datasets in this category were collected from the TCGA website (details given in the paper). Specifically, here we have 16 datasets corresponding to survival time from different cancer types: Adrenocortical carcinoma (ACC), Bladder Urothelial Carcinoma (BLCA), Cholangiocarcinoma (CHOL), Esophageal carcinoma (ESCA), Head and Neck squamous cell carcinoma (HNSC), Kidney renal clear cell carcinoma (KIRC), Liver hepatocellular carcinoma (LIHC), Lung adenocarcinoma (LUAD), Lung squamous cell carcinoma (LUSC), Ovarian serous cystadenocarcinoma (OV), Pancreatic adenocarcinoma (PAAD), Sarcoma (SARC), Skin Cutaneous Melanoma (SKCM), Stomach adenocarcinoma (STAD), Stomach and Esophageal carcinoma (STES), and Uterine Carcinosarcoma (UCS). Table 1 gives summary statistics for each of the 16 datasets.
Table 1: Summary statistics for the 16 (Low-Censoring, Low-Dimensional) datasets. From top to bottom we have (1) the total number of patients, (2) the % of censored patients, and (3) the total number of features used (after feature selection).
| |
ACC |
BLCA |
CHOL |
ESCA |
HNSC |
KIRC |
LIHC |
LUAD |
LUSC |
OV |
PAAD |
SARC |
SKCM |
STAD |
STES |
UCS |
| N |
92 |
409 |
45 |
185 |
526 |
537 |
376 |
513 |
498 |
576 |
185 |
261 |
460 |
436 |
621 |
57 |
| % Censored |
63.04 |
55.99 |
51.11 |
58.38 |
57.6 |
67.04 |
64.89 |
64.13 |
56.83 |
40.45 |
45.95 |
62.07 |
51.96 |
61.01 |
60.23 |
38.6 |
| Number of Features |
9 |
13 |
5 |
13 |
20 |
14 |
12 |
14 |
12 |
2 |
10 |
5 |
18 |
17 |
18 |
4 |
Calibration
Concerning calibration for the (Low-Censoring, Low-Dimensional) datasets, our findings were that MTLR was superior to other models. The D-Calibration (Table 2) results support this as MTLR is D-Calibrated for all 16 datasets (though AFT and Cox are also D-Calibrated for all datasets). The 1-Calibration results (Table 3) are more discriminative showing MTLR and CoxEN-KP to outperform all other models. Although CoxEN-KP shows to be competitive with MTLR with these datasets, when combined with the results from the paper, MTLR has a general better performance leading us to recommend MTLR when measuring calibration on (Low-Censoring, Low-Dimensional) datasets.
Note we only include the accumulated 1-Calibration results here (the exact \(p\)-values are available upon request.)
Table 2: D-Calibration results for the 16 (Low-Censoring, Low-Dimensional) datasets. The Total column gives the total number of datasets for which each model was D-Calibrated.
| |
ACC |
BLCA |
CHOL |
ESCA |
HNSC |
KIRC |
LIHC |
LUAD |
LUSC |
OV |
PAAD |
SARC |
SKCM |
STAD |
STES |
UCS |
Total |
| KM |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
0.998 |
16 |
| AFT |
0.985 |
0.471 |
0.456 |
0.948 |
0.136 |
0.934 |
0.959 |
0.970 |
0.947 |
0.134 |
0.641 |
0.939 |
0.412 |
0.726 |
0.826 |
0.817 |
16 |
| Cox-KP |
0.929 |
0.984 |
0.610 |
0.973 |
0.745 |
0.927 |
0.986 |
0.999 |
0.989 |
0.939 |
0.635 |
0.956 |
0.128 |
0.969 |
0.958 |
0.518 |
16 |
| CoxEN-KP |
0.664 |
0.995 |
0.971 |
1.000 |
0.935 |
0.598 |
0.981 |
0.999 |
1.000 |
0.985 |
0.413 |
1.000 |
0.018 |
0.967 |
0.999 |
0.819 |
15 |
| RSF-KM |
0.982 |
0.562 |
0.859 |
0.661 |
0.253 |
0.508 |
0.312 |
0.996 |
0.000 |
0.000 |
0.490 |
0.000 |
0.661 |
0.063 |
0.000 |
0.607 |
12 |
| MTLR |
0.974 |
1.000 |
0.994 |
0.984 |
0.583 |
0.994 |
0.986 |
0.997 |
0.869 |
0.886 |
0.702 |
0.963 |
0.106 |
0.991 |
0.978 |
0.852 |
16 |
Table 3: The 1-Calibration results for the 16 (Low-Censoring, Low-Dimensional) datasets. Each column represents the 10th, 25th, 50th, 75th, and 90th percentiles of event times. Each row represents the total number of datasets for which each model was 1-Calibrated (the maximum being 16).
| |
10th |
25th |
50th |
75th |
90th |
| AFT |
10 |
10 |
5 |
5 |
3 |
| Cox-KP |
12 |
11 |
6 |
4 |
6 |
| CoxEN-KP |
16 |
14 |
12 |
7 |
5 |
| RSF-KM |
0 |
0 |
0 |
0 |
0 |
| MTLR |
16 |
15 |
11 |
10 |
2 |
Discrimination
Since discrimination is primarily evaluated with concordance we only present this result and omit the Integrated Brier score and the L1-loss (though these results are available from the authors upon request). Table 4 presents these concordance results, and we see results consistent with the findings of the paper – although other models (here MTLR and CoxEN-KP) generally outperform AFT and Cox-KP, the performance gain is not significant. Further, we again see the poor performance of RSF-KM on these Low-Dimensional models. Due to model simplicity of AFT and Cox-KP we suggest using these models for discrimination on (Low-Censoring, Low-Dimensional) datasets.
Table 4: Concordance results for the 16 (Low-Censoring, Low-Dimensional) datasets. Here we present the mean and standard deviation of the Concordance across the 5 cross-validation folds. Bolded values represent the best (highest Concordance) performing models.
| |
ACC |
BLCA |
CHOL |
ESCA |
HNSC |
KIRC |
LIHC |
LUAD |
LUSC |
OV |
PAAD |
SARC |
SKCM |
STAD |
STES |
UCS |
| KM |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
| AFT |
0.793 (0.07) |
0.642 (0.032) |
0.568 (0.259) |
0.582 (0.087) |
0.659 (0.02) |
0.742 (0.032) |
0.621 (0.038) |
0.676 (0.021) |
0.578 (0.019) |
0.601 (0.022) |
0.634 (0.052) |
0.646 (0.07) |
0.749 (0.023) |
0.697 (0.039) |
0.646 (0.034) |
0.683 (0.088) |
| Cox-KP |
0.796 (0.084) |
0.648 (0.042) |
0.568 (0.259) |
0.575 (0.085) |
0.662 (0.025) |
0.74 (0.033) |
0.622 (0.035) |
0.675 (0.021) |
0.578 (0.02) |
0.602 (0.023) |
0.635 (0.048) |
0.646 (0.071) |
0.754 (0.021) |
0.697 (0.032) |
0.644 (0.032) |
0.692 (0.084) |
| CoxEN-KP |
0.749 (0.096) |
0.66 (0.045) |
0.69 (0.16) |
0.539 (0.089) |
0.647 (0.029) |
0.752 (0.021) |
0.592 (0.053) |
0.687 (0.027) |
0.508 (0.047) |
0.6 (0.022) |
0.631 (0.056) |
0.623 (0.08) |
0.757 (0.022) |
0.698 (0.033) |
0.623 (0.034) |
0.697 (0.088) |
| RSF-KM |
0.762 (0.131) |
0.589 (0.032) |
0.691 (0.073) |
0.628 (0.113) |
0.641 (0.051) |
0.741 (0.021) |
0.628 (0.044) |
0.642 (0.052) |
0.541 (0.034) |
0.517 (0.016) |
0.619 (0.057) |
0.604 (0.065) |
0.622 (0.011) |
0.634 (0.028) |
0.616 (0.052) |
0.604 (0.086) |
| MTLR |
0.803 (0.097) |
0.661 (0.041) |
0.764 (0.132) |
0.634 (0.083) |
0.676 (0.017) |
0.756 (0.007) |
0.623 (0.029) |
0.694 (0.029) |
0.595 (0.009) |
0.601 (0.021) |
0.618 (0.071) |
0.646 (0.073) |
0.758 (0.027) |
0.709 (0.032) |
0.656 (0.031) |
0.697 (0.089) |
High-Censor, Low Dimensional
All datasets in this category were collected from the TCGA website (details given in the paper). Specifically, here we have 12 datasets corresponding to survival time from different cancer types: Cervical squamous cell carcinoma and endocervical adenocarcinoma [CESC], Colon adenocarcinoma [COAD], Colorectal adenocarcinoma (COADREAD), FFPE Pilot Phase II [FPPP], Kidney Chromophobe [KICH], Pan-kidney cohort (KIPAN), Kidney renal papillary cell carcinoma [KIRP], Lower Grade Glinoma (LGG), Prostate adenocarcinoma [PRAD], Thyroid carcinoma [THCA], Uterine Corpus Endometrial Carcinoma [UCEC], and Uveal Melanoma [UVM]. Table 5 gives summary statistics for each of the 12 datasets.
Table 5: Summary statistics for the 12 (High-Censoring, Low-Dimensional) datasets. From top to bottom we have (1) the total number of patients, (2) the % of censored patients, and (3) the total number of features used (after feature selection).
| |
CESC |
COAD |
COADREAD |
FPPP |
KICH |
KIPAN |
KIRP |
LGG |
PRAD |
THCA |
UCEC |
UVM |
| N |
307 |
456 |
626 |
38 |
112 |
939 |
290 |
513 |
499 |
503 |
546 |
80 |
| % Censored |
76.55 |
77.63 |
79.39 |
81.58 |
89.29 |
75.19 |
84.83 |
75.63 |
98 |
96.82 |
83.33 |
71.25 |
| Number of Features |
15 |
12 |
13 |
3 |
7 |
20 |
12 |
4 |
6 |
14 |
6 |
6 |
Calibration
For calibration on (High-Censoring, Low-Dimensional) datasets, our findings were that MTLR and CoxEN-KP outperformed other models. The D-Calibration (Table 6) results are inconclusive as nearly all models are D-Calibrated for all datasets (recall D-Calibration is optimistic when data is highly censored). The 1-Calibration results (Table 7) show MTLR and CoxEN-KP to outperform all other models with CoxEN-KP slightly outperforming MTLR. Given MTLR’s better performance on the datasets given in the paper, these results support the finding that MTLR and CoxEN-KP are the best (and generally equivalent) models for calibration on (High-Censoring, Low-Dimensional) datasets.
Table 6: D-Calibration results for the 12 (High-Censoring, Low-Dimensional) datasets. The Total column gives the total number of datasets for which each model was D-Calibrated.
| |
CESC |
COAD |
COADREAD |
FPPP |
KICH |
KIPAN |
KIRP |
LGG |
PRAD |
THCA |
UCEC |
UVM |
Total |
| KM |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1 |
1 |
1.000 |
1.000 |
12 |
| AFT |
0.999 |
0.978 |
1.000 |
0.899 |
0.997 |
0.899 |
0.957 |
0.955 |
1 |
1 |
0.966 |
0.988 |
12 |
| Cox-KP |
0.995 |
0.980 |
1.000 |
0.930 |
0.996 |
0.844 |
0.988 |
0.938 |
1 |
0 |
0.998 |
0.969 |
11 |
| CoxEN-KP |
0.979 |
0.904 |
0.987 |
1.000 |
0.999 |
0.593 |
1.000 |
0.819 |
1 |
1 |
0.998 |
0.998 |
12 |
| RSF-KM |
0.934 |
0.800 |
0.897 |
0.999 |
1.000 |
0.441 |
0.940 |
0.556 |
1 |
1 |
0.366 |
0.940 |
12 |
| MTLR |
0.947 |
0.696 |
0.967 |
0.999 |
1.000 |
0.783 |
0.999 |
0.993 |
1 |
1 |
0.965 |
0.994 |
12 |
Table 7: The 1-Calibration results for the 12 (High-Censoring, Low-Dimensional) datasets. Each column represents the 10th, 25th, 50th, 75th, and 90th percentiles of event times. Each row represents the total number of datasets for which each model was 1-Calibrated (the maximum being 12).
| |
10th |
25th |
50th |
75th |
90th |
| AFT |
4 |
7 |
5 |
2 |
1 |
| Cox-KP |
5 |
5 |
6 |
2 |
1 |
| CoxEN-KP |
8 |
10 |
10 |
5 |
3 |
| RSF-KM |
3 |
2 |
1 |
0 |
0 |
| MTLR |
9 |
10 |
6 |
3 |
2 |
Discrimination
Table 8 presents concordance results for (High-Censoring, Low-Dimensional) datasets and we see results consistent with the findings of the paper – (1) CoxEN-KP and MTLR are superior to AFT and Cox and (2) RSF-KM typically sees noticeably worse performance. This supports our recommendation to use MTLR or CoxEN-KP when evaluating discrimination on (High-Censoring, Low-Dimensional) datasets.
Table 8: Concordance results for the 12 (High-Censoring, Low-Dimensional) datasets. Here we present the mean and standard deviation of the Concordance across the 5 cross-validation folds. Bolded values represent the best (highest Concordance) performing models.
| |
CESC |
COAD |
COADREAD |
FPPP |
KICH |
KIPAN |
KIRP |
LGG |
PRAD |
THCA |
UCEC |
UVM |
| KM |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
| AFT |
0.816 (0.015) |
0.73 (0.042) |
0.731 (0.036) |
0.531 (0.386) |
0.752 (0.422) |
0.782 (0.058) |
0.689 (0.169) |
0.781 (0.08) |
0.778 (0.273) |
0.705 (0.285) |
0.696 (0.079) |
0.736 (0.157) |
| Cox-KP |
0.817 (0.018) |
0.731 (0.04) |
0.732 (0.037) |
0.531 (0.386) |
0.836 (0.242) |
0.78 (0.06) |
0.683 (0.165) |
0.781 (0.078) |
0.774 (0.277) |
0.675 (0.3) |
0.695 (0.08) |
0.711 (0.134) |
| CoxEN-KP |
0.826 (0.032) |
0.741 (0.044) |
0.743 (0.038) |
0.641 (0.267) |
0.958 (0.052) |
0.794 (0.051) |
0.787 (0.104) |
0.779 (0.078) |
0.755 (0.282) |
0.955 (0.032) |
0.694 (0.081) |
0.733 (0.145) |
| RSF-KM |
0.829 (0.017) |
0.682 (0.041) |
0.709 (0.062) |
0.539 (0.376) |
0.923 (0.073) |
0.772 (0.058) |
0.801 (0.091) |
0.709 (0.066) |
0.778 (0.291) |
0.950 (0.027) |
0.614 (0.042) |
0.712 (0.077) |
| MTLR |
0.823 (0.036) |
0.746 (0.043) |
0.747 (0.037) |
0.721 (0.287) |
0.952 (0.047) |
0.795 (0.05) |
0.826 (0.069) |
0.781 (0.073) |
0.672 (0.4) |
0.913 (0.08) |
0.693 (0.078) |
0.737 (0.218) |
Low-Censoring, High-Dimensional
Here we examine a number of (Low-Censoring, High-Dimensional) datasets which contain gene-expression data relating the survival of cancer patients – see “A Multi-Task Learning Formulation for Survival Analysis” by Li et al. for details regarding dataset access. Specifically we use (1) the Norway/Stanford breast cancer data (NBSCD) which contains the gene-expression data for 115 female breast cancer patients, (2) the Van de Vijver’s microarray breast cancer data (VDV) which again contains gene-expression data for 78 breast cancer patients, (3) gene-expression data for adult myeloid leukemia (AML) on 116 patients, and (4) gene-expression data for 92 mantle cell lymphoma (MCL) patients. Table 9 gives the summary statistics for each of these 4 datasets.
Table 9: Summary statistics for the 4 (Low-Censoring, High-Dimensional) datasets. From top to bottom we have (1) the total number of patients, (2) the % of censored patients, and (3) the total number of features used (after feature selection).
| |
AML |
MCL |
NSBCD |
VDV |
| N |
116 |
92 |
115 |
78 |
| % Censored |
42.24 |
30.43 |
66.96 |
56.41 |
| Number of Features |
1616 |
2176 |
274 |
1319 |
Calibration
For calibration on (Low-Censoring, High-Dimensional) datasets, our findings were that MTLR, CoxEN-KP, and RSF-KM were all equivalent. The D-Calibration (Table 10) results are show that AFT fails D-Calibration across all datasets (and Cox fails to finish on these datasets). The 1-Calibration results (Table 11) show that MTLR, CoxEN-KP and RSF-KM are roughly equivalent across the different percentiles supporting our initial finding – MTLR, CoxEN-KP, and RSF-KM are equivalent for calibration on (Low-Censoring, High-Dimensional) datasets.
Table 10: D-Calibration results for the 4 (Low-Censoring, High-Dimensional) datasets. The Total column gives the total number of datasets for which each model was D-Calibrated. Note there is no results for Cox as it failed to run for all datasets.
| |
AML |
MCL |
NSBCD |
VDV |
Total |
| KM |
1.000 |
1.000 |
1.000 |
1.000 |
4 |
| AFT |
0.000 |
0.000 |
0.000 |
0.000 |
0 |
| CoxEN-KP |
0.897 |
0.228 |
0.992 |
0.998 |
4 |
| RSF-KM |
0.759 |
0.577 |
0.977 |
0.000 |
3 |
| MTLR |
0.529 |
0.391 |
0.981 |
0.996 |
4 |
Table 11: The 1-Calibration results for the 4 (Low-Censoring, High-Dimensional) datasets. Each column represents the 10th, 25th, 50th, 75th, and 90th percentiles of event times. Each row represents the total number of datasets for which each model was 1-Calibrated (the maximum being 4). Note there are no results for Cox as it failed to run on all datasets.
| |
10th |
25th |
50th |
75th |
90th |
| AFT |
0 |
0 |
0 |
0 |
0 |
| CoxEN-KP |
4 |
4 |
4 |
2 |
1 |
| RSF-KM |
4 |
4 |
3 |
3 |
1 |
| MTLR |
2 |
3 |
4 |
4 |
3 |
Discrimination
Table 12 presents the concordance results for (Low-Censoring, High-Dimensional) datasets. The findings in the paper (that MTLR/CoxEN-KP are superior to AFT and RSF-KM) are generally supported (actually always supported for being better than AFT). Except for VDV CoxEN-KP does better than RSF-KM and MTLR either matches or performs better than RSF-KM for all datasets.
Table 12: Concordance results for the 4 (Low-Censoring, High-Dimensional) datasets. Here we present the mean and standard deviation of the Concordance across the 5 cross-validation folds. Bolded values represent the best (highest Concordance) performing models. Note there are no results for Cox as it failed to run on all datasets.
| |
AML |
MCL |
NSBCD |
VDV |
| KM |
0.5 (0) |
0.5 (0) |
0.5 (0) |
0.5 (0) |
| AFT |
0.531 (0.074) |
0.496 (0.063) |
0.568 (0.129) |
0.469 (0.084) |
| CoxEN-KP |
0.656 (0.124) |
0.788 (0.042) |
0.784 (0.086) |
0.679 (0.187) |
| RSF-KM |
0.652 (0.089) |
0.764 (0.058) |
0.736 (0.101) |
0.725 (0.13) |
| MTLR |
0.651 (0.092) |
0.805 (0.034) |
0.776 (0.071) |
0.733 (0.157) |
High-Censoring, High-Dimensional
Here we examine 1 additional (High-Censoring, High-Dimensional) dataset, namely gene-expression data for 86 early lung adenocarcinoma (Lung) patients. – see “A Multi-Task Learning Formulation for Survival Analysis” by Li et al. for details regarding dataset access. Table 12 gives the summary statistics for this dataset.
Table 12: Summary statistics for the (High-Censoring, High-Dimensional) dataset. From top to bottom we have (1) the total number of patients, (2) the % of censored patients, and (3) the total number of features used (after feature selection).
| |
Lung |
| N |
86 |
| % Censored |
72.09 |
| Number of Features |
1121 |
Calibration
For calibration on (High-Censoring, High-Dimensional) datasets, our findings were that MTLR, CoxEN-KP, and RSF-KM were all equivalent. The D-Calibration results (Table 13) show that AFT is the only model to fail D-Calibration (note Cox failed to finish). Similarly, the 1-Calibration results (Table 14) show that MTLR, CoxEN-KP and RSF-KM are equivalent across the different percentiles suggesting our finding is consistent for this dataset as well.
Table 13: D-Calibration results for the 4 (Low-Censoring, High-Dimensional) datasets. The Total column gives the total number of datasets for which each model was D-Calibrated. Note the Cox model does not appear as it failed to finish on this dataset.
| |
Lung |
| KM |
1.000 |
| AFT |
0.000 |
| CoxEN-KP |
0.922 |
| RSF-KM |
0.887 |
| MTLR |
0.986 |
Table 14: The 1-Calibration results for the 4 (Low-Censoring, High-Dimensional) datasets. Each column represents the 10th, 25th, 50th, 75th, and 90th percentiles of event times. Each row represents the total number of datasets for which each model was 1-Calibrated (the maximum being 4). Note the Cox model does not appear as it failed to finish on this dataset.
| |
10th |
25th |
50th |
75th |
90th |
| AFT |
0 |
0 |
0 |
0 |
0 |
| CoxEN-KP |
1 |
1 |
1 |
1 |
0 |
| RSF-KM |
1 |
1 |
1 |
1 |
0 |
| MTLR |
1 |
1 |
1 |
1 |
0 |
Discrimination
Table 15 presents the concordance results for the (High-Censoring, High-Dimensional) dataset. The findings in the paper (that MTLR, CoxEN-KP, and RSF-KM are equivalent and also superior to AFT) are supported (although RSF-KM has much higher variance).
Table 15: Concordance results for the 4 (Low-Censoring, High-Dimensional) datasets. Here we present the mean and standard deviation of the Concordance across the 5 cross-validation folds. Bolded values represent the best (highest Concordance) performing models. Note the Cox model does not appear as it failed to finish on this dataset.
| |
Lung |
| KM |
0.5 (0) |
| AFT |
0.668 (0.172) |
| CoxEN-KP |
0.932 (0.039) |
| RSF-KM |
0.816 (0.173) |
| MTLR |
0.934 (0.029) |
LS0tCnRpdGxlOiAiSVNEIEV2YWx1YXRpb24gLS0gU3VwcGxlbWVudGFsIERhdGFzZXQgUmVzdWx0cyIKYXV0aG9yOiAiSHVtemEgSGFpZGVyLCBCcmV0IEhvZWhuLCBTYXJhaCBEYXZpcywgUnVzc2VsbCBHcmVpbmVyIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogCiAgICB0b2M6IFRSVUUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQotLS0KCiNJbnRyb2R1Y3Rpb24gCgpUaGUgcmVzdWx0cyBoZXJlIGFjY29tcGFueSB0aGUgcGFwZXIgIkVmZmVjdGl2ZSBXYXlzIHRvIEJ1aWxkIGFuZCBFdmFsdWF0ZSBJbmRpdmlkdWFsIFN1cnZpdmFsIERpc3RyaWJ1dGlvbnMiIGJ5IEhhaWRlciBldCBhbC4gSW4gdG90YWwsIDMzIGFkZGl0aW9uYWwgZGF0YXNldHMgd2VyZSB0ZXN0ZWQgdG8gdmFsaWRhdGUgdGhlIGZpbmRpbmdzIGdpdmVuIGJ5IFRhYmxlIDcgaW4gU2VjdGlvbiA1IG9mIHRoZSBwYXBlci4gRm9yIGVhY2ggb2YgKExvdy1DZW5zb3JpbmcsIExvdy1EaW1lbnNpb25hbCksIChIaWdoLUNlbnNvcmluZywgTG93LURpbWVuc2lvbmFsKSwgKExvdy1DZW5zb3JpbmcsIEhpZ2gtRGltZW5zaW9uYWwpLCBhbmQgKEhpZ2gtQ2Vuc29yaW5nLCBIaWdoLURpbWVuc2lvbmFsKSB3ZSBoYXZlIDE2LCAxMiwgNCwgYW5kIDEgYWRkaXRpb25hbCBkYXRhc2V0cyB0byBjaGVjayB0aGUgZ2VuZXJhbGl6YXRpb24gb2YgdGhlIGZpbmRpbmdzLiBFYWNoIGZvbGxvd2luZyBzZWN0aW9uIGdpdmVzIGZ1cnRoZXIgZGV0YWlscyBhYm91dCB0aGUgY29ycmVzcG9uZGluZyBkYXRhc2V0cyB1c2VkLiBIZXJlIHdlIGhhdmUgZGVmaW5lZCAiSGlnaC1DZW5zb3JpbmciIHRvIGJlICRcZ2VxJCA3MCUuIEFkZGl0aW9uYWxseSwgIkhpZ2gtRGltZW5zaW9uYWwiIGRhdGFzZXRzIGFsbCBoYXZlIGF0IGxlYXN0IDI3NCBmZWF0dXJlcy4KCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBlcnJvcj1GQUxTRSwgd2FybmluZz1GQUxTRX0KTmFtZSA9IGMoKQpOID0gYygpCk51bUZlYXQgPSBjKCkKUGVyY2VuQ2VucyA9IGMoKQpEQ2FsID0gYygpCk9uZUNhbDEgPSBjKCkKT25lQ2FsMiA9IGMoKQpPbmVDYWwzID0gYygpCk9uZUNhbDQgPSBjKCkKT25lQ2FsNSA9IGMoKQpDb25jVW5jZW5zID0gYygpCkNvbmNVbmNlbnNTRCA9IGMoKQpJbnRlZ2VyYXRlZEJyaWVyID0gYygpCkludGVncmVhdGVkQnJpZXJTRD0gYygpCkwxTW9kID0gYygpCkwxTW9kU0QgPSBjKCkKRGF0PWMoKQptb2RlbD1jKCkKZm9yKGkgaW4gbGlzdC5maWxlcygiLi4vUFNTUC9SZXN1bHRzL2V4dHJhRGF0LyIpKXsKICAjZmlyc3RQZXJpb2QgPSBncmVnZXhwcihwYXR0ZXJuID0gJ1xcLicsaSlbWzFdXVsxXQogIGRhdGFzZXQgPSBzdWJzdHIoaSwxLDcpCiAgRGF0ID0gYyhEYXQsZGF0YXNldCkKICByZXBvcnQgPSByZWFkLmNzdihwYXN0ZSgiLi4vUFNTUC9SZXN1bHRzL2V4dHJhRGF0LyIsaSxzZXA9IiIpKQogIE5hbWUgPSBjKE5hbWUsdW5uYW1lKHNhcHBseShhcy5jaGFyYWN0ZXIocmVwb3J0JE1vZGVsKSwgZnVuY3Rpb24oeCkgcGFzdGUoZGF0YXNldCwiOiAiLHgsc2VwPSIiKSkpKQogIG1vZGVsID0gYyhtb2RlbCxhcy5jaGFyYWN0ZXIocmVwb3J0JE1vZGVsKSkKICBOID0gYyhOLCByZXBvcnQkTikKICBOdW1GZWF0ID0gYyhOdW1GZWF0LCByZXBvcnQkTnVtRmVhdHVyZXMpCiAgUGVyY2VuQ2VucyA9IGMoUGVyY2VuQ2VucywgcmVwb3J0JFBlcmNlbnRDZW5zb3JlZCkKICBEQ2FsID0gYyhEQ2FsLCByZXBvcnQkRENhbGlicmF0aW9uQ3VtdWxhdGl2ZSkKICBPbmVDYWwxID0gYyhPbmVDYWwxLCByZXBvcnQkT25lQ2FsaWJyYXRpb25DdW11bGF0aXZlMSkKICBPbmVDYWwyID0gYyhPbmVDYWwyLCByZXBvcnQkT25lQ2FsaWJyYXRpb25DdW11bGF0aXZlMikKICBPbmVDYWwzID0gYyhPbmVDYWwzLCByZXBvcnQkT25lQ2FsaWJyYXRpb25DdW11bGF0aXZlMykKICBPbmVDYWw0ID0gYyhPbmVDYWw0LCByZXBvcnQkT25lQ2FsaWJyYXRpb25DdW11bGF0aXZlNCkKICBPbmVDYWw1ID0gYyhPbmVDYWw1LCByZXBvcnQkT25lQ2FsaWJyYXRpb25DdW11bGF0aXZlNSkKICBDb25jVW5jZW5zID0gYyhDb25jVW5jZW5zLCByZXBvcnQkQ29uY29yZGFuY2VVbmNlbnNvcmVkTSkKICBDb25jVW5jZW5zU0QgPSBjKENvbmNVbmNlbnNTRCwgcmVwb3J0JENvbmNvcmRhbmNlVW5jZW5zb3JlZFNEKQogIEludGVnZXJhdGVkQnJpZXIgPSBjKEludGVnZXJhdGVkQnJpZXIsIHJlcG9ydCRJbnRlZ3JhdGVkQnJpZXJNKQogIEludGVncmVhdGVkQnJpZXJTRD0gYyhJbnRlZ3JlYXRlZEJyaWVyU0QsIHJlcG9ydCRJbnRlZ3JhdGVkQnJpZXJTRCkKICBMMU1vZCA9IGMoTDFNb2QsIHJlcG9ydCRMMU1hcmdpbk5vTG9nTSkKICBMMU1vZFNEID0gYyhMMU1vZFNELCByZXBvcnQkTDFNYXJnaW5Ob0xvZ1NEKQp9CkNvbmNVbmNlbnNDb21ibyA9IHBhc3RlKHJvdW5kKENvbmNVbmNlbnMsMyksIiAoIixyb3VuZChDb25jVW5jZW5zU0QsMyksICIpIiwgc2VwPSIiKQpJbnRlZ3JhdGVkQnJpZXJDb21ibyA9IHBhc3RlKHJvdW5kKEludGVnZXJhdGVkQnJpZXIsNCksIiAoIixyb3VuZChJbnRlZ3JlYXRlZEJyaWVyU0QsMyksICIpIiwgc2VwPSIiKQpMMUNvbWJvID0gcGFzdGUocm91bmQoTDFNb2QsMiksIiAoIixyb3VuZChMMU1vZFNELDIpLCAiKSIsIHNlcD0iIikKdGFiID0gbWF0cml4KGMoTmFtZSxOLE51bUZlYXQscm91bmQoUGVyY2VuQ2VucyoxMDAsMiksIHBhc3RlKHJvdW5kKERDYWwsMykpLHBhc3RlKHJvdW5kKE9uZUNhbDEsMykpLHBhc3RlKHJvdW5kKE9uZUNhbDIsMykpLAogICAgICAgICAgICAgICBwYXN0ZShyb3VuZChPbmVDYWwzLDMpKSxwYXN0ZShyb3VuZChPbmVDYWw0LDMpKSxwYXN0ZShyb3VuZChPbmVDYWw1LDMpKSxDb25jVW5jZW5zQ29tYm8sCiAgICAgICAgICAgICAgIEludGVncmF0ZWRCcmllckNvbWJvLEwxQ29tYm8pLGxlbmd0aChOYW1lKSwxMywKICAgICAgICAgICAgIGRpbW5hbWVzID0gbGlzdChOVUxMLGMoIk5hbWUiLCAiTiIsIk51bUZlYXQiLCAiUENlbnMiLCJEQ2FsIiwiT0NhbDEiLCJPQ2FsMiIsIk9DYWwzIiwiT0NhbDQiLCJPQ2FsNSIsICJDb25TdGFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIklCUyIsICJMMSIpKSkKCmRhdDIgPSBkYXRhLmZyYW1lKHRhYikKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKZGF0YXNldE5hbWVzID0gYygpCmZvcihpIGluIGxpc3QuZmlsZXMoIi4uL1BTU1AvUmVzdWx0cy9leHRyYURhdC8iKSl7CiAgIGZpcnN0UGVyaW9kID0gZ3JlZ2V4cHIocGF0dGVybiA9ICdcXC4nLGkpW1sxXV1bMV0KICAgZGF0YXNldE5hbWVzID0gYyhkYXRhc2V0TmFtZXMsIHN1YnN0cihpLDEsZmlyc3RQZXJpb2QtMSkpCn0KCmFsZ05hbWVzID0gYygiQUZUIiwiQ294LUtQIiwiQ294RU4tS1AiLCJLTSIsIk1UTFIiLCJSU0YtS00iKQoKbGlicmFyeSh4dGFibGUpCmxpYnJhcnkoRGF0YUNvbWJpbmUpCnRvUGxheSA9IGRhdDIKI3RvUGxheSA9IEluc2VydFJvdyh0b1BsYXkscmVwKE5BLDEzKSwyKQojdG9QbGF5ID0gSW5zZXJ0Um93KHRvUGxheSxyZXAoTkEsMTMpLDgpCiN0b1BsYXkgPSB0b1BsYXlbYygxMzozNiwzNzo0OCwgMToxMiksXQpDZW5zID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIodW5pcXVlKHRvUGxheSRQQ2VucylbIWlzLm5hKHVuaXF1ZSh0b1BsYXkkUENlbnMpKV0pKQpOcyAgPSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih0b1BsYXkkTltzZXEoMSxucm93KHRvUGxheSksYnkgID0gNildKSkKRmVhdHVyZXNTZWxlY3RlZCAgPSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih0b1BsYXkkTnVtRmVhdFtzZXEoMSxucm93KHRvUGxheSksYnkgID0gNildKSkKCkhDID0gQ2VucyA+PTcwCgpDZW5zSEMgPSBDZW5zW0hDXQpOc0hDID0gTnNbSENdCkZlYXR1cmVzU2VsZWN0ZWRIQyA9IEZlYXR1cmVzU2VsZWN0ZWRbSENdCgpDZW5zTEMgPSBDZW5zWyFIQ10KTnNMQyA9IE5zWyFIQ10KRmVhdHVyZXNTZWxlY3RlZExDID0gRmVhdHVyZXNTZWxlY3RlZFshSENdCgpoZWFkZXJIQyA9IGFzLmRhdGEuZnJhbWUobWF0cml4KGMoTnNIQyxDZW5zSEMsRmVhdHVyZXNTZWxlY3RlZEhDKSxuY29sID0gc3VtKEhDKSwgYnlyb3c9VCkpCiNoZWFkZXJIQyA9IHJvdW5kKGhlYWRlckhDKQpuYW1lcyhoZWFkZXJIQykgPSBkYXRhc2V0TmFtZXNbSENdCnJvdy5uYW1lcyhoZWFkZXJIQykgPSBjKCJOIiwiJSBDZW5zb3JlZCIsIk51bWJlciBvZiBGZWF0dXJlcyIpCmhlYWRlckhDWzEsXSA9IGZvcm1hdEMoaGVhZGVySENbMSxdLCBmb3JtYXQgPSAiZCIpCmhlYWRlckxDID0gYXMuZGF0YS5mcmFtZShtYXRyaXgoYyhOc0xDLENlbnNMQyxGZWF0dXJlc1NlbGVjdGVkTEMpLG5jb2wgPSBzdW0oIUhDKSwgYnlyb3c9VCkpCiNoZWFkZXJIQyA9IHJvdW5kKGhlYWRlckhDKQpuYW1lcyhoZWFkZXJMQykgPSBkYXRhc2V0TmFtZXNbIUhDXQpyb3cubmFtZXMoaGVhZGVyTEMpID0gYygiTiIsIiUgQ2Vuc29yZWQiLCJOdW1iZXIgb2YgRmVhdHVyZXMiKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmBgYAoKPGhyIHN0eWxlPSJoZWlnaHQ6M3B4O2JvcmRlcjpub25lO2NvbG9yOiMzMzM7YmFja2dyb3VuZC1jb2xvcjojMzMzOyIgLz4KCgojTG93LUNlbnNvcmluZywgTG93LURpbWVuc2lvbmFsCgpBbGwgZGF0YXNldHMgaW4gdGhpcyBjYXRlZ29yeSB3ZXJlIGNvbGxlY3RlZCBmcm9tIHRoZSBUQ0dBIHdlYnNpdGUgKGRldGFpbHMgZ2l2ZW4gaW4gdGhlIHBhcGVyKS4gU3BlY2lmaWNhbGx5LCBoZXJlIHdlIGhhdmUgMTYgZGF0YXNldHMgY29ycmVzcG9uZGluZyB0byBzdXJ2aXZhbCB0aW1lIGZyb20gZGlmZmVyZW50IGNhbmNlciB0eXBlczogQWRyZW5vY29ydGljYWwgY2FyY2lub21hIChBQ0MpLCBCbGFkZGVyIFVyb3RoZWxpYWwgQ2FyY2lub21hIChCTENBKSwgQ2hvbGFuZ2lvY2FyY2lub21hIChDSE9MKSwgRXNvcGhhZ2VhbCBjYXJjaW5vbWEgKEVTQ0EpLCBIZWFkIGFuZCBOZWNrIHNxdWFtb3VzIGNlbGwgY2FyY2lub21hIChITlNDKSwgS2lkbmV5IHJlbmFsIGNsZWFyIGNlbGwgY2FyY2lub21hIChLSVJDKSwgTGl2ZXIgaGVwYXRvY2VsbHVsYXIgY2FyY2lub21hIChMSUhDKSwgTHVuZyBhZGVub2NhcmNpbm9tYSAoTFVBRCksIEx1bmcgc3F1YW1vdXMgY2VsbCBjYXJjaW5vbWEgKExVU0MpLCBPdmFyaWFuIHNlcm91cyBjeXN0YWRlbm9jYXJjaW5vbWEgKE9WKSwgUGFuY3JlYXRpYyBhZGVub2NhcmNpbm9tYSAoUEFBRCksIFNhcmNvbWEgKFNBUkMpLCBTa2luIEN1dGFuZW91cyBNZWxhbm9tYSAoU0tDTSksIFN0b21hY2ggYWRlbm9jYXJjaW5vbWEgKFNUQUQpLCBTdG9tYWNoIGFuZCBFc29waGFnZWFsIGNhcmNpbm9tYSAoU1RFUyksIGFuZCBVdGVyaW5lIENhcmNpbm9zYXJjb21hIChVQ1MpLiBUYWJsZSAxIGdpdmVzIHN1bW1hcnkgc3RhdGlzdGljcyBmb3IgZWFjaCBvZiB0aGUgMTYgZGF0YXNldHMuIAoKCmBgYHtyLCBlY2hvPUZBTFNFLCBlcnJvciA9IEZBTFNFLHdhcm5pbmc9RkFMU0V9CmhlYWRlckxDWzEsXSA9IGZvcm1hdEMoaGVhZGVyTENbMSxdLCBmb3JtYXQgPSAiZCIpCgprYWJsZShoZWFkZXJMQywgZm9ybWF0ID0gImh0bWwiLCBjYXB0aW9uID0gIlRhYmxlIDE6IFN1bW1hcnkgc3RhdGlzdGljcyBmb3IgdGhlIDE2IChMb3ctQ2Vuc29yaW5nLCBMb3ctRGltZW5zaW9uYWwpIGRhdGFzZXRzLiBGcm9tIHRvcCB0byBib3R0b20gd2UgaGF2ZSAoMSkgdGhlIHRvdGFsIG51bWJlciBvZiBwYXRpZW50cywgKDIpIHRoZSAlIG9mIGNlbnNvcmVkIHBhdGllbnRzLCBhbmQgKDMpIHRoZSB0b3RhbCBudW1iZXIgb2YgZmVhdHVyZXMgdXNlZCAoYWZ0ZXIgZmVhdHVyZSBzZWxlY3Rpb24pLiIsYWxpZ24gPSBjKCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnKSkgJT4lCiAgICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCBmdWxsX3dpZHRoID0gRiApICU+JQogIGNvbHVtbl9zcGVjKDEsYm9sZD1ULCB3aWR0aF9taW4gPSAiNGNtIikKYGBgCgo8aHIgc3R5bGU9ImhlaWdodDoxcHg7Ym9yZGVyOm5vbmU7Y29sb3I6IzMzMztiYWNrZ3JvdW5kLWNvbG9yOiMzMzM7IiAvPgoKCiMjQ2FsaWJyYXRpb24KCkNvbmNlcm5pbmcgY2FsaWJyYXRpb24gZm9yIHRoZSAoTG93LUNlbnNvcmluZywgTG93LURpbWVuc2lvbmFsKSBkYXRhc2V0cywgb3VyIGZpbmRpbmdzIHdlcmUgdGhhdCBNVExSIHdhcyBzdXBlcmlvciB0byBvdGhlciBtb2RlbHMuIFRoZSBELUNhbGlicmF0aW9uIChUYWJsZSAyKSByZXN1bHRzIHN1cHBvcnQgdGhpcyBhcyBNVExSIGlzIEQtQ2FsaWJyYXRlZCBmb3IgYWxsIDE2IGRhdGFzZXRzICh0aG91Z2ggQUZUIGFuZCBDb3ggYXJlIGFsc28gRC1DYWxpYnJhdGVkIGZvciBhbGwgZGF0YXNldHMpLiBUaGUgMS1DYWxpYnJhdGlvbiByZXN1bHRzIChUYWJsZSAzKSBhcmUgbW9yZSBkaXNjcmltaW5hdGl2ZSBzaG93aW5nIE1UTFIgYW5kIENveEVOLUtQIHRvIG91dHBlcmZvcm0gYWxsIG90aGVyIG1vZGVscy4gQWx0aG91Z2ggQ294RU4tS1Agc2hvd3MgdG8gYmUgY29tcGV0aXRpdmUgd2l0aCBNVExSIHdpdGggdGhlc2UgZGF0YXNldHMsIHdoZW4gY29tYmluZWQgd2l0aCB0aGUgcmVzdWx0cyBmcm9tIHRoZSBwYXBlciwgTVRMUiBoYXMgYSBnZW5lcmFsIGJldHRlciBwZXJmb3JtYW5jZSBsZWFkaW5nIHVzIHRvIHJlY29tbWVuZCBNVExSIHdoZW4gbWVhc3VyaW5nIGNhbGlicmF0aW9uIG9uIChMb3ctQ2Vuc29yaW5nLCBMb3ctRGltZW5zaW9uYWwpIGRhdGFzZXRzLgoKTm90ZSB3ZSBvbmx5IGluY2x1ZGUgdGhlIGFjY3VtdWxhdGVkIDEtQ2FsaWJyYXRpb24gcmVzdWx0cyBoZXJlICh0aGUgZXhhY3QgJHAkLXZhbHVlcyBhcmUgYXZhaWxhYmxlIHVwb24gcmVxdWVzdC4pCgpgYGB7ciwgZWNobz1GQUxTRX0KSENJbmQgPSByZXAoSEMsZWFjaCA9IDYpCnRvVGFibGUgPSBhcy5kYXRhLmZyYW1lKG1hdHJpeChkYXRhID0gdG9QbGF5JERDYWxbIUhDSW5kXSwgbmNvbCA9IGxlbmd0aChkYXRhc2V0TmFtZXNbIUhDXSkpKQp0b1RhYmxlID0gYXMuZGF0YS5mcmFtZShhcHBseSh0b1RhYmxlLDIsZnVuY3Rpb24oeCkgYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoeCkpKSkKY29sbmFtZXModG9UYWJsZSkgPSBkYXRhc2V0TmFtZXNbIUhDXQp0b1RhYmxlID0gdG9UYWJsZVtjKDQsMSwyLDMsNiw1KSxdCnJvd25hbWVzKHRvVGFibGUpID0gYygiS00iLCJBRlQiLCJDb3gtS1AiLCJDb3hFTi1LUCIsIlJTRi1LTSIsIk1UTFIiKQoKdG9UYWJsZSRUb3RhbCA9IHJvd1N1bXMoYXBwbHkodG9UYWJsZSwgMiwgZnVuY3Rpb24oeCkgYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoeCkpKSA+PSAwLjA1KQprYWJsZSh0b1RhYmxlLCBkaWdpdHMgPSAzLGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJUYWJsZSAyOiBELUNhbGlicmF0aW9uIHJlc3VsdHMgZm9yIHRoZSAxNiAoTG93LUNlbnNvcmluZywgTG93LURpbWVuc2lvbmFsKSBkYXRhc2V0cy4gVGhlIFRvdGFsIGNvbHVtbiBnaXZlcyB0aGUgdG90YWwgbnVtYmVyIG9mIGRhdGFzZXRzIGZvciB3aGljaCBlYWNoIG1vZGVsIHdhcyBELUNhbGlicmF0ZWQuIixhbGlnbiA9IGMoJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnKSkgJT4lCiAgICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCBmdWxsX3dpZHRoID0gVCkgJT4lCiAgICBjb2x1bW5fc3BlYyhjKDEsMTgpLGJvbGQ9VCx3aWR0aF9taW4gPSAiMi41Y20iKQoKYGBgCgpgYGB7cixlY2hvID0gRn0Kb25lQ2FsID0gYXMuZGF0YS5mcmFtZShhcHBseSh0b1BsYXlbNjoxMF1bIUhDSW5kLF0sMixmdW5jdGlvbih4KSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih4KSkpKQpvbmVDYWwkTW9kZWwgPSByZXAoYWxnTmFtZXMsIGxlbmd0aChkYXRhc2V0TmFtZXNbIUhDXSkpCmxpYnJhcnkoZHBseXIpCnRvVGFibGUgPSBvbmVDYWwgJT4lIGdyb3VwX2J5KE1vZGVsKSAlPiUgc3VtbWFyaXplKE9DMSA9IHN1bShPQ2FsMSA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DMiA9IHN1bShPQ2FsMiA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DMyA9IHN1bShPQ2FsMyA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DNCA9IHN1bShPQ2FsNCA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DNSA9IHN1bShPQ2FsNSA+PTAuMDUpKQp0b1RhYmxlID0gYXMuZGF0YS5mcmFtZSh0b1RhYmxlKQp0b1RhYmxlID0gdG9UYWJsZVtjKDEsMywyLDYsNSksLTFdCnJvd25hbWVzKHRvVGFibGUpID0gYygiQUZUIiwiQ294LUtQIiwiQ294RU4tS1AiLCJSU0YtS00iLCJNVExSIikKY29sbmFtZXModG9UYWJsZSkgPSBjKCIxMHRoIiwiMjV0aCIsICI1MHRoIiwiNzV0aCIsIjkwdGgiKQogIAoKa2FibGUodG9UYWJsZSAsIGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJUYWJsZSAzOiBUaGUgMS1DYWxpYnJhdGlvbiByZXN1bHRzIGZvciB0aGUgMTYgKExvdy1DZW5zb3JpbmcsIExvdy1EaW1lbnNpb25hbCkgZGF0YXNldHMuIEVhY2ggY29sdW1uIHJlcHJlc2VudHMgdGhlIDEwdGgsIDI1dGgsIDUwdGgsIDc1dGgsIGFuZCA5MHRoIHBlcmNlbnRpbGVzIG9mIGV2ZW50IHRpbWVzLiBFYWNoIHJvdyByZXByZXNlbnRzIHRoZSB0b3RhbCBudW1iZXIgb2YgZGF0YXNldHMgZm9yIHdoaWNoIGVhY2ggbW9kZWwgd2FzIDEtQ2FsaWJyYXRlZCAodGhlIG1heGltdW0gYmVpbmcgMTYpLiIsYWxpZ24gPSBjKCdjJywnYycsJ2MnLCdjJywnYycpKSAlPiUKICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsIGZ1bGxfd2lkdGggPSBUICkgJT4lCiAgICBjb2x1bW5fc3BlYyhjKDEpLGJvbGQ9VCx3aWR0aF9taW4gPSAiMi41Y20iKQoKYGBgCgo8aHIgc3R5bGU9ImhlaWdodDoxcHg7Ym9yZGVyOm5vbmU7Y29sb3I6IzMzMztiYWNrZ3JvdW5kLWNvbG9yOiMzMzM7IiAvPgoKCiMjRGlzY3JpbWluYXRpb24KClNpbmNlIGRpc2NyaW1pbmF0aW9uIGlzIHByaW1hcmlseSBldmFsdWF0ZWQgd2l0aCBjb25jb3JkYW5jZSB3ZSBvbmx5IHByZXNlbnQgdGhpcyByZXN1bHQgYW5kIG9taXQgdGhlIEludGVncmF0ZWQgQnJpZXIgc2NvcmUgYW5kIHRoZSBMMS1sb3NzICh0aG91Z2ggdGhlc2UgcmVzdWx0cyBhcmUgYXZhaWxhYmxlIGZyb20gdGhlIGF1dGhvcnMgdXBvbiByZXF1ZXN0KS4gVGFibGUgNCBwcmVzZW50cyB0aGVzZSBjb25jb3JkYW5jZSByZXN1bHRzLCBhbmQgd2Ugc2VlIHJlc3VsdHMgY29uc2lzdGVudCB3aXRoIHRoZSBmaW5kaW5ncyBvZiB0aGUgcGFwZXIgLS0gYWx0aG91Z2ggb3RoZXIgbW9kZWxzIChoZXJlIE1UTFIgYW5kIENveEVOLUtQKSBnZW5lcmFsbHkgb3V0cGVyZm9ybSBBRlQgYW5kIENveC1LUCwgdGhlIHBlcmZvcm1hbmNlIGdhaW4gaXMgbm90IHNpZ25pZmljYW50LiBGdXJ0aGVyLCB3ZSBhZ2FpbiBzZWUgdGhlIHBvb3IgcGVyZm9ybWFuY2Ugb2YgUlNGLUtNIG9uIHRoZXNlIExvdy1EaW1lbnNpb25hbCBtb2RlbHMuIER1ZSB0byBtb2RlbCBzaW1wbGljaXR5IG9mIEFGVCBhbmQgQ294LUtQIHdlIHN1Z2dlc3QgdXNpbmcgdGhlc2UgbW9kZWxzIGZvciBkaXNjcmltaW5hdGlvbiBvbiAoTG93LUNlbnNvcmluZywgTG93LURpbWVuc2lvbmFsKSBkYXRhc2V0cy4KCgpgYGB7ciwgZWNobyA9IEZBTFNFLGVycm9yPUZBTFNFLHdhcm5pbmc9RkFMU0V9CnRvVGFibGUgPSBhcy5kYXRhLmZyYW1lKG1hdHJpeChkYXRhID0gdG9QbGF5JENvblN0YW5bIUhDSW5kXSwgbmNvbCA9IGxlbmd0aChkYXRhc2V0TmFtZXNbIUhDXSkpKQoKdG9UYWJsZSA9IHRvVGFibGVbYyg0LDEsMiwzLDYsNSksXQpyb3duYW1lcyh0b1RhYmxlKSA9IGMoIktNIiwiQUZUIiwiQ294LUtQIiwiQ294RU4tS1AiLCJSU0YtS00iLCJNVExSIikKY29sbmFtZXModG9UYWJsZSkgPSBkYXRhc2V0TmFtZXNbIUhDXQoKdG9UYWJsZSAgJT4lCmthYmxlKHRvVGFibGUsIGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJUYWJsZSA0OiBDb25jb3JkYW5jZSByZXN1bHRzIGZvciB0aGUgMTYgKExvdy1DZW5zb3JpbmcsIExvdy1EaW1lbnNpb25hbCkgZGF0YXNldHMuIEhlcmUgd2UgcHJlc2VudCB0aGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSBDb25jb3JkYW5jZSBhY3Jvc3MgdGhlIDUgY3Jvc3MtdmFsaWRhdGlvbiBmb2xkcy4gQm9sZGVkIHZhbHVlcyByZXByZXNlbnQgdGhlIGJlc3QgKGhpZ2hlc3QgQ29uY29yZGFuY2UpIHBlcmZvcm1pbmcgbW9kZWxzLiIsYWxpZ24gPSBjKCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJykpICU+JQogICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IEYgKSAlPiUKICAgICAgY29sdW1uX3NwZWMoYygxKSxib2xkPVQsd2lkdGhfbWluID0gIjIuNWNtIikKCmBgYAoKCjxociBzdHlsZT0iaGVpZ2h0OjNweDtib3JkZXI6bm9uZTtjb2xvcjojMzMzO2JhY2tncm91bmQtY29sb3I6IzMzMzsiIC8+CgoKI0hpZ2gtQ2Vuc29yLCBMb3cgRGltZW5zaW9uYWwKCkFsbCBkYXRhc2V0cyBpbiB0aGlzIGNhdGVnb3J5IHdlcmUgY29sbGVjdGVkIGZyb20gdGhlIFRDR0Egd2Vic2l0ZSAoZGV0YWlscyBnaXZlbiBpbiB0aGUgcGFwZXIpLiBTcGVjaWZpY2FsbHksIGhlcmUgd2UgaGF2ZSAxMiBkYXRhc2V0cyBjb3JyZXNwb25kaW5nIHRvIHN1cnZpdmFsIHRpbWUgZnJvbSBkaWZmZXJlbnQgY2FuY2VyIHR5cGVzOiBDZXJ2aWNhbCBzcXVhbW91cyBjZWxsIGNhcmNpbm9tYSBhbmQgZW5kb2NlcnZpY2FsIGFkZW5vY2FyY2lub21hIFtDRVNDXSwgQ29sb24gYWRlbm9jYXJjaW5vbWEgW0NPQURdLCBDb2xvcmVjdGFsIGFkZW5vY2FyY2lub21hIChDT0FEUkVBRCksIEZGUEUgUGlsb3QgUGhhc2UgSUkgW0ZQUFBdLCBLaWRuZXkgQ2hyb21vcGhvYmUgW0tJQ0hdLCBQYW4ta2lkbmV5IGNvaG9ydCAoS0lQQU4pLCBLaWRuZXkgcmVuYWwgcGFwaWxsYXJ5IGNlbGwgY2FyY2lub21hIFtLSVJQXSwgTG93ZXIgR3JhZGUgR2xpbm9tYSAoTEdHKSwgUHJvc3RhdGUgYWRlbm9jYXJjaW5vbWEgW1BSQURdLCBUaHlyb2lkIGNhcmNpbm9tYSBbVEhDQV0sIFV0ZXJpbmUgQ29ycHVzIEVuZG9tZXRyaWFsIENhcmNpbm9tYSBbVUNFQ10sIGFuZCBVdmVhbCBNZWxhbm9tYSBbVVZNXS4gVGFibGUgNSBnaXZlcyBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIGVhY2ggb2YgdGhlIDEyIGRhdGFzZXRzLiAKCgpgYGB7ciwgZWNobz1GQUxTRSwgZXJyb3IgPSBGQUxTRSx3YXJuaW5nPUZBTFNFfQpoZWFkZXJIQ1sxLF0gPSBmb3JtYXRDKGhlYWRlckhDWzEsXSwgZm9ybWF0ID0gImQiKQoKa2FibGUoaGVhZGVySEMsIGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJUYWJsZSA1OiBTdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIHRoZSAxMiAoSGlnaC1DZW5zb3JpbmcsIExvdy1EaW1lbnNpb25hbCkgZGF0YXNldHMuIEZyb20gdG9wIHRvIGJvdHRvbSB3ZSBoYXZlICgxKSB0aGUgdG90YWwgbnVtYmVyIG9mIHBhdGllbnRzLCAoMikgdGhlICUgb2YgY2Vuc29yZWQgcGF0aWVudHMsIGFuZCAoMykgdGhlIHRvdGFsIG51bWJlciBvZiBmZWF0dXJlcyB1c2VkIChhZnRlciBmZWF0dXJlIHNlbGVjdGlvbikuIixhbGlnbiA9IGMoJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycpKSAlPiUKICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsIGZ1bGxfd2lkdGggPSBUICkgJT4lCiAgY29sdW1uX3NwZWMoMSxib2xkPVQpCmBgYAoKPGhyIHN0eWxlPSJoZWlnaHQ6MXB4O2JvcmRlcjpub25lO2NvbG9yOiMzMzM7YmFja2dyb3VuZC1jb2xvcjojMzMzOyIgLz4KCgojI0NhbGlicmF0aW9uCgpGb3IgY2FsaWJyYXRpb24gb24gKEhpZ2gtQ2Vuc29yaW5nLCBMb3ctRGltZW5zaW9uYWwpIGRhdGFzZXRzLCBvdXIgZmluZGluZ3Mgd2VyZSB0aGF0IE1UTFIgYW5kIENveEVOLUtQIG91dHBlcmZvcm1lZCBvdGhlciBtb2RlbHMuIFRoZSBELUNhbGlicmF0aW9uIChUYWJsZSA2KSByZXN1bHRzIGFyZSBpbmNvbmNsdXNpdmUgYXMgbmVhcmx5IGFsbCBtb2RlbHMgYXJlIEQtQ2FsaWJyYXRlZCBmb3IgYWxsIGRhdGFzZXRzIChyZWNhbGwgRC1DYWxpYnJhdGlvbiBpcyBvcHRpbWlzdGljIHdoZW4gZGF0YSBpcyBoaWdobHkgY2Vuc29yZWQpLiBUaGUgMS1DYWxpYnJhdGlvbiByZXN1bHRzIChUYWJsZSA3KSBzaG93IE1UTFIgYW5kIENveEVOLUtQIHRvIG91dHBlcmZvcm0gYWxsIG90aGVyIG1vZGVscyB3aXRoIENveEVOLUtQIHNsaWdodGx5IG91dHBlcmZvcm1pbmcgTVRMUi4gR2l2ZW4gTVRMUidzIGJldHRlciBwZXJmb3JtYW5jZSBvbiB0aGUgZGF0YXNldHMgZ2l2ZW4gaW4gdGhlIHBhcGVyLCB0aGVzZSByZXN1bHRzIHN1cHBvcnQgdGhlIGZpbmRpbmcgdGhhdCBNVExSIGFuZCBDb3hFTi1LUCBhcmUgdGhlIGJlc3QgKGFuZCBnZW5lcmFsbHkgZXF1aXZhbGVudCkgbW9kZWxzIGZvciBjYWxpYnJhdGlvbiBvbiAoSGlnaC1DZW5zb3JpbmcsIExvdy1EaW1lbnNpb25hbCkgZGF0YXNldHMuCgpgYGB7ciwgZWNobz1GQUxTRX0KSENJbmQgPSByZXAoSEMsZWFjaCA9IDYpCnRvVGFibGUgPSBhcy5kYXRhLmZyYW1lKG1hdHJpeChkYXRhID0gdG9QbGF5JERDYWxbSENJbmRdLCBuY29sID0gbGVuZ3RoKGRhdGFzZXROYW1lc1tIQ10pKSkKdG9UYWJsZSA9IGFzLmRhdGEuZnJhbWUoYXBwbHkodG9UYWJsZSwyLGZ1bmN0aW9uKHgpIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHgpKSkpCmNvbG5hbWVzKHRvVGFibGUpID0gZGF0YXNldE5hbWVzW0hDXQp0b1RhYmxlID0gdG9UYWJsZVtjKDQsMSwyLDMsNiw1KSxdCnJvd25hbWVzKHRvVGFibGUpID0gYygiS00iLCJBRlQiLCJDb3gtS1AiLCJDb3hFTi1LUCIsIlJTRi1LTSIsIk1UTFIiKQoKdG9UYWJsZSRUb3RhbCA9IHJvd1N1bXMoYXBwbHkodG9UYWJsZSwgMiwgZnVuY3Rpb24oeCkgYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoeCkpKSA+PSAwLjA1KQprYWJsZSh0b1RhYmxlLGRpZ2l0cyA9IDMsIGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJUYWJsZSA2OiBELUNhbGlicmF0aW9uIHJlc3VsdHMgZm9yIHRoZSAxMiAoSGlnaC1DZW5zb3JpbmcsIExvdy1EaW1lbnNpb25hbCkgZGF0YXNldHMuIFRoZSBUb3RhbCBjb2x1bW4gZ2l2ZXMgdGhlIHRvdGFsIG51bWJlciBvZiBkYXRhc2V0cyBmb3Igd2hpY2ggZWFjaCBtb2RlbCB3YXMgRC1DYWxpYnJhdGVkLiIsYWxpZ24gPSBjKCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJykpICU+JQogICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IFQgKSAlPiUKICAgIGNvbHVtbl9zcGVjKGMoMSwxNCksYm9sZD1ULHdpZHRoX21pbiA9ICIyLjVjbSIpCgpgYGAKCgpgYGB7ciwgZWNobz1GfQpvbmVDYWwgPSBhcy5kYXRhLmZyYW1lKGFwcGx5KHRvUGxheVs2OjEwXVtIQ0luZCxdLDIsZnVuY3Rpb24oeCkgYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoeCkpKSkKb25lQ2FsJE1vZGVsID0gcmVwKGFsZ05hbWVzLCBsZW5ndGgoZGF0YXNldE5hbWVzW0hDXSkpCmxpYnJhcnkoZHBseXIpCnRvVGFibGUgPSBvbmVDYWwgJT4lIGdyb3VwX2J5KE1vZGVsKSAlPiUgc3VtbWFyaXplKE9DMSA9IHN1bShPQ2FsMSA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DMiA9IHN1bShPQ2FsMiA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DMyA9IHN1bShPQ2FsMyA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DNCA9IHN1bShPQ2FsNCA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DNSA9IHN1bShPQ2FsNSA+PTAuMDUpKQp0b1RhYmxlID0gYXMuZGF0YS5mcmFtZSh0b1RhYmxlKQp0b1RhYmxlID0gdG9UYWJsZVtjKDEsMywyLDYsNSksLTFdCnJvd25hbWVzKHRvVGFibGUpID0gYygiQUZUIiwiQ294LUtQIiwiQ294RU4tS1AiLCJSU0YtS00iLCJNVExSIikKY29sbmFtZXModG9UYWJsZSkgPSBjKCIxMHRoIiwiMjV0aCIsICI1MHRoIiwiNzV0aCIsIjkwdGgiKQogIAoKa2FibGUodG9UYWJsZSAsIGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJUYWJsZSA3OiBUaGUgMS1DYWxpYnJhdGlvbiByZXN1bHRzIGZvciB0aGUgMTIgKEhpZ2gtQ2Vuc29yaW5nLCBMb3ctRGltZW5zaW9uYWwpIGRhdGFzZXRzLiBFYWNoIGNvbHVtbiByZXByZXNlbnRzIHRoZSAxMHRoLCAyNXRoLCA1MHRoLCA3NXRoLCBhbmQgOTB0aCBwZXJjZW50aWxlcyBvZiBldmVudCB0aW1lcy4gRWFjaCByb3cgcmVwcmVzZW50cyB0aGUgdG90YWwgbnVtYmVyIG9mIGRhdGFzZXRzIGZvciB3aGljaCBlYWNoIG1vZGVsIHdhcyAxLUNhbGlicmF0ZWQgKHRoZSBtYXhpbXVtIGJlaW5nIDEyKS4iLGFsaWduID0gYygnYycsJ2MnLCdjJywnYycsJ2MnKSkgJT4lCiAgICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCBmdWxsX3dpZHRoID0gVCApICU+JQogICAgY29sdW1uX3NwZWMoYygxKSxib2xkPVQsd2lkdGhfbWluID0gIjIuNWNtIikKCmBgYAoKPGhyIHN0eWxlPSJoZWlnaHQ6MXB4O2JvcmRlcjpub25lO2NvbG9yOiMzMzM7YmFja2dyb3VuZC1jb2xvcjojMzMzOyIgLz4KCgojI0Rpc2NyaW1pbmF0aW9uCgpUYWJsZSA4IHByZXNlbnRzIGNvbmNvcmRhbmNlIHJlc3VsdHMgZm9yIChIaWdoLUNlbnNvcmluZywgTG93LURpbWVuc2lvbmFsKSBkYXRhc2V0cyBhbmQgd2Ugc2VlIHJlc3VsdHMgY29uc2lzdGVudCB3aXRoIHRoZSBmaW5kaW5ncyBvZiB0aGUgcGFwZXIgLS0gKDEpIENveEVOLUtQIGFuZCBNVExSIGFyZSBzdXBlcmlvciB0byBBRlQgYW5kIENveCBhbmQgKDIpIFJTRi1LTSB0eXBpY2FsbHkgc2VlcyBub3RpY2VhYmx5IHdvcnNlIHBlcmZvcm1hbmNlLiBUaGlzIHN1cHBvcnRzIG91ciByZWNvbW1lbmRhdGlvbiB0byB1c2UgTVRMUiBvciBDb3hFTi1LUCB3aGVuIGV2YWx1YXRpbmcgZGlzY3JpbWluYXRpb24gb24gKEhpZ2gtQ2Vuc29yaW5nLCBMb3ctRGltZW5zaW9uYWwpIGRhdGFzZXRzLgoKYGBge3IsIGVjaG8gPSBGQUxTRSxlcnJvcj1GQUxTRSx3YXJuaW5nPUZBTFNFfQp0b1RhYmxlID0gYXMuZGF0YS5mcmFtZShtYXRyaXgoZGF0YSA9IHRvUGxheSRDb25TdGFuW0hDSW5kXSwgbmNvbCA9IGxlbmd0aChkYXRhc2V0TmFtZXNbSENdKSkpCnRvVGFibGUgPSB0b1RhYmxlW2MoNCwxLDIsMyw2LDUpLF0Kcm93bmFtZXModG9UYWJsZSkgPSBjKCJLTSIsIkFGVCIsIkNveC1LUCIsIkNveEVOLUtQIiwiUlNGLUtNIiwiTVRMUiIpCmNvbG5hbWVzKHRvVGFibGUpID0gZGF0YXNldE5hbWVzW0hDXQoKdG9UYWJsZSAgJT4lCmthYmxlKHRvVGFibGUsIGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJUYWJsZSA4OiBDb25jb3JkYW5jZSByZXN1bHRzIGZvciB0aGUgMTIgKEhpZ2gtQ2Vuc29yaW5nLCBMb3ctRGltZW5zaW9uYWwpIGRhdGFzZXRzLiBIZXJlIHdlIHByZXNlbnQgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgQ29uY29yZGFuY2UgYWNyb3NzIHRoZSA1IGNyb3NzLXZhbGlkYXRpb24gZm9sZHMuIEJvbGRlZCB2YWx1ZXMgcmVwcmVzZW50IHRoZSBiZXN0IChoaWdoZXN0IENvbmNvcmRhbmNlKSBwZXJmb3JtaW5nIG1vZGVscy4iLGFsaWduID0gYygnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycpKSAlPiUKICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsIGZ1bGxfd2lkdGggPSBUICkgJT4lCiAgICAgIGNvbHVtbl9zcGVjKGMoMSksYm9sZD1ULHdpZHRoX21pbiA9ICIyLjVjbSIpCmBgYAoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIGVycm9yPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpOYW1lID0gYygpCk4gPSBjKCkKTnVtRmVhdCA9IGMoKQpQZXJjZW5DZW5zID0gYygpCkRDYWwgPSBjKCkKT25lQ2FsMSA9IGMoKQpPbmVDYWwyID0gYygpCk9uZUNhbDMgPSBjKCkKT25lQ2FsNCA9IGMoKQpPbmVDYWw1ID0gYygpCkNvbmNVbmNlbnMgPSBjKCkKQ29uY1VuY2Vuc1NEID0gYygpCkludGVnZXJhdGVkQnJpZXIgPSBjKCkKSW50ZWdyZWF0ZWRCcmllclNEPSBjKCkKTDFNb2QgPSBjKCkKTDFNb2RTRCA9IGMoKQpEYXQ9YygpCm1vZGVsPWMoKQpmb3IoaSBpbiBsaXN0LmZpbGVzKCIuLi9QU1NQL1Jlc3VsdHMvSEQvIikpewogICNmaXJzdFBlcmlvZCA9IGdyZWdleHByKHBhdHRlcm4gPSAnXFwuJyxpKVtbMV1dWzFdCiAgZGF0YXNldCA9IHN1YnN0cihpLDEsNykKICBEYXQgPSBjKERhdCxkYXRhc2V0KQogIHJlcG9ydCA9IHJlYWQuY3N2KHBhc3RlKCIuLi9QU1NQL1Jlc3VsdHMvSEQvIixpLHNlcD0iIikpCiAgTmFtZSA9IGMoTmFtZSx1bm5hbWUoc2FwcGx5KGFzLmNoYXJhY3RlcihyZXBvcnQkTW9kZWwpLCBmdW5jdGlvbih4KSBwYXN0ZShkYXRhc2V0LCI6ICIseCxzZXA9IiIpKSkpCiAgbW9kZWwgPSBjKG1vZGVsLGFzLmNoYXJhY3RlcihyZXBvcnQkTW9kZWwpKQogIE4gPSBjKE4sIHJlcG9ydCROKQogIE51bUZlYXQgPSBjKE51bUZlYXQsIHJlcG9ydCROdW1GZWF0dXJlcykKICBQZXJjZW5DZW5zID0gYyhQZXJjZW5DZW5zLCByZXBvcnQkUGVyY2VudENlbnNvcmVkKQogIERDYWwgPSBjKERDYWwsIHJlcG9ydCREQ2FsaWJyYXRpb25DdW11bGF0aXZlKQogIE9uZUNhbDEgPSBjKE9uZUNhbDEsIHJlcG9ydCRPbmVDYWxpYnJhdGlvbkN1bXVsYXRpdmUxKQogIE9uZUNhbDIgPSBjKE9uZUNhbDIsIHJlcG9ydCRPbmVDYWxpYnJhdGlvbkN1bXVsYXRpdmUyKQogIE9uZUNhbDMgPSBjKE9uZUNhbDMsIHJlcG9ydCRPbmVDYWxpYnJhdGlvbkN1bXVsYXRpdmUzKQogIE9uZUNhbDQgPSBjKE9uZUNhbDQsIHJlcG9ydCRPbmVDYWxpYnJhdGlvbkN1bXVsYXRpdmU0KQogIE9uZUNhbDUgPSBjKE9uZUNhbDUsIHJlcG9ydCRPbmVDYWxpYnJhdGlvbkN1bXVsYXRpdmU1KQogIENvbmNVbmNlbnMgPSBjKENvbmNVbmNlbnMsIHJlcG9ydCRDb25jb3JkYW5jZVVuY2Vuc29yZWRNKQogIENvbmNVbmNlbnNTRCA9IGMoQ29uY1VuY2Vuc1NELCByZXBvcnQkQ29uY29yZGFuY2VVbmNlbnNvcmVkU0QpCiAgSW50ZWdlcmF0ZWRCcmllciA9IGMoSW50ZWdlcmF0ZWRCcmllciwgcmVwb3J0JEludGVncmF0ZWRCcmllck0pCiAgSW50ZWdyZWF0ZWRCcmllclNEPSBjKEludGVncmVhdGVkQnJpZXJTRCwgcmVwb3J0JEludGVncmF0ZWRCcmllclNEKQogIEwxTW9kID0gYyhMMU1vZCwgcmVwb3J0JEwxTWFyZ2luTm9Mb2dNKQogIEwxTW9kU0QgPSBjKEwxTW9kU0QsIHJlcG9ydCRMMU1hcmdpbk5vTG9nU0QpCn0KQ29uY1VuY2Vuc0NvbWJvID0gcGFzdGUocm91bmQoQ29uY1VuY2VucywzKSwiICgiLHJvdW5kKENvbmNVbmNlbnNTRCwzKSwgIikiLCBzZXA9IiIpCkludGVncmF0ZWRCcmllckNvbWJvID0gcGFzdGUocm91bmQoSW50ZWdlcmF0ZWRCcmllciw0KSwiICgiLHJvdW5kKEludGVncmVhdGVkQnJpZXJTRCwzKSwgIikiLCBzZXA9IiIpCkwxQ29tYm8gPSBwYXN0ZShyb3VuZChMMU1vZCwyKSwiICgiLHJvdW5kKEwxTW9kU0QsMiksICIpIiwgc2VwPSIiKQp0YWIgPSBtYXRyaXgoYyhOYW1lLE4sTnVtRmVhdCxyb3VuZChQZXJjZW5DZW5zKjEwMCwyKSwgcGFzdGUocm91bmQoRENhbCwzKSkscGFzdGUocm91bmQoT25lQ2FsMSwzKSkscGFzdGUocm91bmQoT25lQ2FsMiwzKSksCiAgICAgICAgICAgICAgIHBhc3RlKHJvdW5kKE9uZUNhbDMsMykpLHBhc3RlKHJvdW5kKE9uZUNhbDQsMykpLHBhc3RlKHJvdW5kKE9uZUNhbDUsMykpLENvbmNVbmNlbnNDb21ibywKICAgICAgICAgICAgICAgSW50ZWdyYXRlZEJyaWVyQ29tYm8sTDFDb21ibyksbGVuZ3RoKE5hbWUpLDEzLAogICAgICAgICAgICAgZGltbmFtZXMgPSBsaXN0KE5VTEwsYygiTmFtZSIsICJOIiwiTnVtRmVhdCIsICJQQ2VucyIsIkRDYWwiLCJPQ2FsMSIsIk9DYWwyIiwiT0NhbDMiLCJPQ2FsNCIsIk9DYWw1IiwgIkNvblN0YW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSUJTIiwgIkwxIikpKQoKZGF0MiA9IGRhdGEuZnJhbWUodGFiKQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpkYXRhc2V0TmFtZXMgPSBjKCkKZm9yKGkgaW4gbGlzdC5maWxlcygiLi4vUFNTUC9SZXN1bHRzL0hELyIpKXsKICAgZmlyc3RQZXJpb2QgPSBncmVnZXhwcihwYXR0ZXJuID0gJ1xcLicsaSlbWzFdXVsxXQogICBkYXRhc2V0TmFtZXMgPSBjKGRhdGFzZXROYW1lcywgc3Vic3RyKGksMSxmaXJzdFBlcmlvZC0xKSkKfQoKYWxnTmFtZXMgPSBjKCJBRlQiLCJDb3hFTi1LUCIsIktNIiwiTVRMUiIsIlJTRi1LTSIpCgp0b1BsYXkgPSBkYXQyCgpDZW5zID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIodW5pcXVlKHRvUGxheSRQQ2VucylbIWlzLm5hKHVuaXF1ZSh0b1BsYXkkUENlbnMpKV0pKQpOcyAgPSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih0b1BsYXkkTltzZXEoMSxucm93KHRvUGxheSksYnkgID0gNildKSkKRmVhdHVyZXNTZWxlY3RlZCAgPSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih0b1BsYXkkTnVtRmVhdFtzZXEoMSxucm93KHRvUGxheSksYnkgID0gNildKSkKCkhDID0gQ2VucyA+PTcwCgpDZW5zSEMgPSBDZW5zW0hDXQpOc0hDID0gTnNbSENdCkZlYXR1cmVzU2VsZWN0ZWRIQyA9IEZlYXR1cmVzU2VsZWN0ZWRbSENdCgpDZW5zTEMgPSBDZW5zWyFIQ10KTnNMQyA9IE5zWyFIQ10KRmVhdHVyZXNTZWxlY3RlZExDID0gRmVhdHVyZXNTZWxlY3RlZFshSENdCgpoZWFkZXJIQyA9IGFzLmRhdGEuZnJhbWUobWF0cml4KGMoTnNIQyxDZW5zSEMsRmVhdHVyZXNTZWxlY3RlZEhDKSxuY29sID0gc3VtKEhDKSwgYnlyb3c9VCkpCiNoZWFkZXJIQyA9IHJvdW5kKGhlYWRlckhDKQpuYW1lcyhoZWFkZXJIQykgPSBkYXRhc2V0TmFtZXNbSENdCnJvdy5uYW1lcyhoZWFkZXJIQykgPSBjKCJOIiwiJSBDZW5zb3JlZCIsIk51bWJlciBvZiBGZWF0dXJlcyIpCmhlYWRlckhDWzEsXSA9IGZvcm1hdEMoaGVhZGVySENbMSxdLCBmb3JtYXQgPSAiZCIpCgpgYGAKCjxociBzdHlsZT0iaGVpZ2h0OjNweDtib3JkZXI6bm9uZTtjb2xvcjojMzMzO2JhY2tncm91bmQtY29sb3I6IzMzMzsiIC8+CgoKI0xvdy1DZW5zb3JpbmcsIEhpZ2gtRGltZW5zaW9uYWwKCkhlcmUgd2UgZXhhbWluZSBhIG51bWJlciBvZiAoTG93LUNlbnNvcmluZywgSGlnaC1EaW1lbnNpb25hbCkgZGF0YXNldHMgd2hpY2ggY29udGFpbiBnZW5lLWV4cHJlc3Npb24gZGF0YSByZWxhdGluZyB0aGUgc3Vydml2YWwgb2YgY2FuY2VyIHBhdGllbnRzIC0tIHNlZSAiQSBNdWx0aS1UYXNrIExlYXJuaW5nIEZvcm11bGF0aW9uIGZvciBTdXJ2aXZhbCBBbmFseXNpcyIgYnkgTGkgZXQgYWwuIGZvciBkZXRhaWxzIHJlZ2FyZGluZyBkYXRhc2V0IGFjY2Vzcy4gU3BlY2lmaWNhbGx5IHdlIHVzZSAoMSkgdGhlIE5vcndheS9TdGFuZm9yZCBicmVhc3QgY2FuY2VyIGRhdGEgKE5CU0NEKSB3aGljaCBjb250YWlucyB0aGUgZ2VuZS1leHByZXNzaW9uIGRhdGEgZm9yIDExNSBmZW1hbGUgYnJlYXN0IGNhbmNlciBwYXRpZW50cywgKDIpIHRoZSBWYW4gZGUgVmlqdmVyJ3MgbWljcm9hcnJheSBicmVhc3QgY2FuY2VyIGRhdGEgKFZEVikgd2hpY2ggYWdhaW4gY29udGFpbnMgZ2VuZS1leHByZXNzaW9uIGRhdGEgZm9yIDc4IGJyZWFzdCBjYW5jZXIgcGF0aWVudHMsICgzKSBnZW5lLWV4cHJlc3Npb24gZGF0YSBmb3IgYWR1bHQgbXllbG9pZCBsZXVrZW1pYSAoQU1MKSBvbiAxMTYgcGF0aWVudHMsIGFuZCAoNCkgZ2VuZS1leHByZXNzaW9uIGRhdGEgZm9yIDkyIG1hbnRsZSBjZWxsIGx5bXBob21hIChNQ0wpIHBhdGllbnRzLiBUYWJsZSA5IGdpdmVzIHRoZSBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIGVhY2ggb2YgdGhlc2UgNCBkYXRhc2V0cy4KCmBgYHtyLCBlY2hvPUZBTFNFLCBlcnJvciA9IEZBTFNFLHdhcm5pbmc9RkFMU0V9CmhlYWRlckxDID0gYXMuZGF0YS5mcmFtZShtYXRyaXgoYyhOc0xDLENlbnNMQyxGZWF0dXJlc1NlbGVjdGVkTEMpLG5jb2wgPSBzdW0oIUhDKSwgYnlyb3c9VCkpCiNoZWFkZXJIQyA9IHJvdW5kKGhlYWRlckhDKQpuYW1lcyhoZWFkZXJMQykgPSBkYXRhc2V0TmFtZXNbIUhDXQpyb3cubmFtZXMoaGVhZGVyTEMpID0gYygiTiIsIiUgQ2Vuc29yZWQiLCJOdW1iZXIgb2YgRmVhdHVyZXMiKQpoZWFkZXJMQ1sxLF0gPSBmb3JtYXRDKGhlYWRlckxDWzEsXSwgZm9ybWF0ID0gImQiKQoKa2FibGUoaGVhZGVyTEMsIGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJUYWJsZSA5OiBTdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIHRoZSA0IChMb3ctQ2Vuc29yaW5nLCBIaWdoLURpbWVuc2lvbmFsKSBkYXRhc2V0cy4gRnJvbSB0b3AgdG8gYm90dG9tIHdlIGhhdmUgKDEpIHRoZSB0b3RhbCBudW1iZXIgb2YgcGF0aWVudHMsICgyKSB0aGUgJSBvZiBjZW5zb3JlZCBwYXRpZW50cywgYW5kICgzKSB0aGUgdG90YWwgbnVtYmVyIG9mIGZlYXR1cmVzIHVzZWQgKGFmdGVyIGZlYXR1cmUgc2VsZWN0aW9uKS4iLGFsaWduID0gYygnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJykpICU+JQogICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IFQgKSAlPiUKICBjb2x1bW5fc3BlYygxLGJvbGQ9VCwgd2lkdGhfbWluID0gIjRjbSIpCmBgYAoKPGhyIHN0eWxlPSJoZWlnaHQ6MXB4O2JvcmRlcjpub25lO2NvbG9yOiMzMzM7YmFja2dyb3VuZC1jb2xvcjojMzMzOyIgLz4KCgojI0NhbGlicmF0aW9uCgpGb3IgY2FsaWJyYXRpb24gb24gKExvdy1DZW5zb3JpbmcsIEhpZ2gtRGltZW5zaW9uYWwpIGRhdGFzZXRzLCBvdXIgZmluZGluZ3Mgd2VyZSB0aGF0IE1UTFIsIENveEVOLUtQLCBhbmQgUlNGLUtNIHdlcmUgYWxsIGVxdWl2YWxlbnQuIFRoZSBELUNhbGlicmF0aW9uIChUYWJsZSAxMCkgcmVzdWx0cyBhcmUgc2hvdyB0aGF0IEFGVCBmYWlscyBELUNhbGlicmF0aW9uIGFjcm9zcyBhbGwgZGF0YXNldHMgKGFuZCBDb3ggZmFpbHMgdG8gZmluaXNoIG9uIHRoZXNlIGRhdGFzZXRzKS4gVGhlIDEtQ2FsaWJyYXRpb24gcmVzdWx0cyAoVGFibGUgMTEpIHNob3cgdGhhdCBNVExSLCBDb3hFTi1LUCBhbmQgUlNGLUtNIGFyZSByb3VnaGx5IGVxdWl2YWxlbnQgYWNyb3NzIHRoZSBkaWZmZXJlbnQgcGVyY2VudGlsZXMgc3VwcG9ydGluZyBvdXIgaW5pdGlhbCBmaW5kaW5nIC0tIE1UTFIsIENveEVOLUtQLCBhbmQgUlNGLUtNIGFyZSBlcXVpdmFsZW50IGZvciBjYWxpYnJhdGlvbiBvbiAoTG93LUNlbnNvcmluZywgSGlnaC1EaW1lbnNpb25hbCkgZGF0YXNldHMuCgpgYGB7ciwgZWNobz1GQUxTRX0KSENJbmQgPSByZXAoSEMsZWFjaCA9IDUpCnRvVGFibGUgPSBhcy5kYXRhLmZyYW1lKG1hdHJpeChkYXRhID0gdG9QbGF5JERDYWxbIUhDSW5kXSwgbmNvbCA9IGxlbmd0aChkYXRhc2V0TmFtZXNbIUhDXSkpKQp0b1RhYmxlID0gYXMuZGF0YS5mcmFtZShhcHBseSh0b1RhYmxlLDIsZnVuY3Rpb24oeCkgYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoeCkpKSkKY29sbmFtZXModG9UYWJsZSkgPSBkYXRhc2V0TmFtZXNbIUhDXQp0b1RhYmxlID0gdG9UYWJsZVtjKDMsMSwyLDUsNCksXQpyb3duYW1lcyh0b1RhYmxlKSA9IGMoIktNIiwiQUZUIiwiQ294RU4tS1AiLCJSU0YtS00iLCJNVExSIikKCnRvVGFibGUkVG90YWwgPSByb3dTdW1zKGFwcGx5KHRvVGFibGUsIDIsIGZ1bmN0aW9uKHgpIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHgpKSkgPj0gMC4wNSkKa2FibGUodG9UYWJsZSwgZGlnaXRzID0gMyxmb3JtYXQgPSAiaHRtbCIsIGNhcHRpb24gPSAiVGFibGUgMTA6IEQtQ2FsaWJyYXRpb24gcmVzdWx0cyBmb3IgdGhlIDQgKExvdy1DZW5zb3JpbmcsIEhpZ2gtRGltZW5zaW9uYWwpIGRhdGFzZXRzLiBUaGUgVG90YWwgY29sdW1uIGdpdmVzIHRoZSB0b3RhbCBudW1iZXIgb2YgZGF0YXNldHMgZm9yIHdoaWNoIGVhY2ggbW9kZWwgd2FzIEQtQ2FsaWJyYXRlZC4gTm90ZSB0aGVyZSBpcyBubyByZXN1bHRzIGZvciBDb3ggYXMgaXQgZmFpbGVkIHRvIHJ1biBmb3IgYWxsIGRhdGFzZXRzLiIsYWxpZ24gPSBjKCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJykpICU+JQogICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IFQpICU+JQogICAgY29sdW1uX3NwZWMoYygxLDYpLGJvbGQ9VCx3aWR0aF9taW4gPSAiMi41Y20iKQoKYGBgCgpgYGB7cixlY2hvID0gRn0Kb25lQ2FsID0gYXMuZGF0YS5mcmFtZShhcHBseSh0b1BsYXlbNjoxMF1bIUhDSW5kLF0sMixmdW5jdGlvbih4KSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih4KSkpKQpvbmVDYWwkTW9kZWwgPSByZXAoYWxnTmFtZXMsIGxlbmd0aChkYXRhc2V0TmFtZXNbIUhDXSkpCmxpYnJhcnkoZHBseXIpCnRvVGFibGUgPSBvbmVDYWwgJT4lIGdyb3VwX2J5KE1vZGVsKSAlPiUgc3VtbWFyaXplKE9DMSA9IHN1bShPQ2FsMSA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DMiA9IHN1bShPQ2FsMiA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DMyA9IHN1bShPQ2FsMyA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DNCA9IHN1bShPQ2FsNCA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DNSA9IHN1bShPQ2FsNSA+PTAuMDUpKQp0b1RhYmxlID0gYXMuZGF0YS5mcmFtZSh0b1RhYmxlKQp0b1RhYmxlID0gdG9UYWJsZVtjKDEsMiw1LDQpLC0xXQpyb3duYW1lcyh0b1RhYmxlKSA9IGMoIkFGVCIsIkNveEVOLUtQIiwiUlNGLUtNIiwiTVRMUiIpCmNvbG5hbWVzKHRvVGFibGUpID0gYygiMTB0aCIsIjI1dGgiLCAiNTB0aCIsIjc1dGgiLCI5MHRoIikKICAKCmthYmxlKHRvVGFibGUgLCBmb3JtYXQgPSAiaHRtbCIsIGNhcHRpb24gPSAiVGFibGUgMTE6IFRoZSAxLUNhbGlicmF0aW9uIHJlc3VsdHMgZm9yIHRoZSA0IChMb3ctQ2Vuc29yaW5nLCBIaWdoLURpbWVuc2lvbmFsKSBkYXRhc2V0cy4gRWFjaCBjb2x1bW4gcmVwcmVzZW50cyB0aGUgMTB0aCwgMjV0aCwgNTB0aCwgNzV0aCwgYW5kIDkwdGggcGVyY2VudGlsZXMgb2YgZXZlbnQgdGltZXMuIEVhY2ggcm93IHJlcHJlc2VudHMgdGhlIHRvdGFsIG51bWJlciBvZiBkYXRhc2V0cyBmb3Igd2hpY2ggZWFjaCBtb2RlbCB3YXMgMS1DYWxpYnJhdGVkICh0aGUgbWF4aW11bSBiZWluZyA0KS4gTm90ZSB0aGVyZSBhcmUgbm8gcmVzdWx0cyBmb3IgQ294IGFzIGl0IGZhaWxlZCB0byBydW4gb24gYWxsIGRhdGFzZXRzLiIsYWxpZ24gPSBjKCdjJywnYycsJ2MnLCdjJywnYycpKSAlPiUKICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsIGZ1bGxfd2lkdGggPSBUKSAlPiUKICAgIGNvbHVtbl9zcGVjKGMoMSksYm9sZD1ULHdpZHRoX21pbiA9ICIyLjVjbSIpCgpgYGAKCjxociBzdHlsZT0iaGVpZ2h0OjFweDtib3JkZXI6bm9uZTtjb2xvcjojMzMzO2JhY2tncm91bmQtY29sb3I6IzMzMzsiIC8+CgoKCiMjRGlzY3JpbWluYXRpb24KClRhYmxlIDEyIHByZXNlbnRzIHRoZSBjb25jb3JkYW5jZSByZXN1bHRzIGZvciAoTG93LUNlbnNvcmluZywgSGlnaC1EaW1lbnNpb25hbCkgZGF0YXNldHMuIFRoZSBmaW5kaW5ncyBpbiB0aGUgcGFwZXIgKHRoYXQgTVRMUi9Db3hFTi1LUCBhcmUgc3VwZXJpb3IgdG8gQUZUIGFuZCBSU0YtS00pIGFyZSBnZW5lcmFsbHkgc3VwcG9ydGVkIChhY3R1YWxseSBhbHdheXMgc3VwcG9ydGVkIGZvciBiZWluZyBiZXR0ZXIgdGhhbiBBRlQpLiBFeGNlcHQgZm9yIFZEViBDb3hFTi1LUCBkb2VzIGJldHRlciB0aGFuIFJTRi1LTSBhbmQgTVRMUiBlaXRoZXIgbWF0Y2hlcyBvciBwZXJmb3JtcyBiZXR0ZXIgdGhhbiBSU0YtS00gZm9yIGFsbCBkYXRhc2V0cy4KCmBgYHtyLCBlY2hvID0gRkFMU0UsZXJyb3I9RkFMU0Usd2FybmluZz1GQUxTRX0KdG9UYWJsZSA9IGFzLmRhdGEuZnJhbWUobWF0cml4KGRhdGEgPSB0b1BsYXkkQ29uU3RhblshSENJbmRdLCBuY29sID0gbGVuZ3RoKGRhdGFzZXROYW1lc1shSENdKSkpCgp0b1RhYmxlID0gdG9UYWJsZVtjKDMsMSwyLDUsNCksXQpyb3duYW1lcyh0b1RhYmxlKSA9IGMoIktNIiwiQUZUIiwiQ294RU4tS1AiLCJSU0YtS00iLCJNVExSIikKY29sbmFtZXModG9UYWJsZSkgPSBkYXRhc2V0TmFtZXNbIUhDXQoKdG9UYWJsZSAgJT4lCmthYmxlKHRvVGFibGUsIGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJUYWJsZSAxMjogQ29uY29yZGFuY2UgcmVzdWx0cyBmb3IgdGhlIDQgKExvdy1DZW5zb3JpbmcsIEhpZ2gtRGltZW5zaW9uYWwpIGRhdGFzZXRzLiBIZXJlIHdlIHByZXNlbnQgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgQ29uY29yZGFuY2UgYWNyb3NzIHRoZSA1IGNyb3NzLXZhbGlkYXRpb24gZm9sZHMuIEJvbGRlZCB2YWx1ZXMgcmVwcmVzZW50IHRoZSBiZXN0IChoaWdoZXN0IENvbmNvcmRhbmNlKSBwZXJmb3JtaW5nIG1vZGVscy4gTm90ZSB0aGVyZSBhcmUgbm8gcmVzdWx0cyBmb3IgQ294IGFzIGl0IGZhaWxlZCB0byBydW4gb24gYWxsIGRhdGFzZXRzLiIsYWxpZ24gPSBjKCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJykpICU+JQogICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IFQgKSAlPiUKICAgICAgY29sdW1uX3NwZWMoYygxKSxib2xkPVQsd2lkdGhfbWluID0gIjIuNWNtIikKCmBgYAoKCjxociBzdHlsZT0iaGVpZ2h0OjNweDtib3JkZXI6bm9uZTtjb2xvcjojMzMzO2JhY2tncm91bmQtY29sb3I6IzMzMzsiIC8+CgojSGlnaC1DZW5zb3JpbmcsIEhpZ2gtRGltZW5zaW9uYWwKCkhlcmUgd2UgZXhhbWluZSAxIGFkZGl0aW9uYWwgKEhpZ2gtQ2Vuc29yaW5nLCBIaWdoLURpbWVuc2lvbmFsKSBkYXRhc2V0LCBuYW1lbHkgZ2VuZS1leHByZXNzaW9uIGRhdGEgZm9yIDg2IGVhcmx5IGx1bmcgYWRlbm9jYXJjaW5vbWEgKEx1bmcpIHBhdGllbnRzLiAtLSBzZWUgIkEgTXVsdGktVGFzayBMZWFybmluZyBGb3JtdWxhdGlvbiBmb3IgU3Vydml2YWwgQW5hbHlzaXMiIGJ5IExpIGV0IGFsLiBmb3IgZGV0YWlscyByZWdhcmRpbmcgZGF0YXNldCBhY2Nlc3MuIFRhYmxlIDEyIGdpdmVzIHRoZSBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIHRoaXMgZGF0YXNldC4KCmBgYHtyLCBlY2hvPUZBTFNFLCBlcnJvciA9IEZBTFNFLHdhcm5pbmc9RkFMU0V9CmhlYWRlckhDWzEsXSA9IGZvcm1hdEMoaGVhZGVySENbMSxdLCBmb3JtYXQgPSAiZCIpCm5hbWVzKGhlYWRlckhDKSA9IGRhdGFzZXROYW1lc1tIQ10Kcm93Lm5hbWVzKGhlYWRlckhDKSA9IGMoIk4iLCIlIENlbnNvcmVkIiwiTnVtYmVyIG9mIEZlYXR1cmVzIikKCmthYmxlKGhlYWRlckhDLCBmb3JtYXQgPSAiaHRtbCIsIGNhcHRpb24gPSAiVGFibGUgMTI6IFN1bW1hcnkgc3RhdGlzdGljcyBmb3IgdGhlICAoSGlnaC1DZW5zb3JpbmcsIEhpZ2gtRGltZW5zaW9uYWwpIGRhdGFzZXQuIEZyb20gdG9wIHRvIGJvdHRvbSB3ZSBoYXZlICgxKSB0aGUgdG90YWwgbnVtYmVyIG9mIHBhdGllbnRzLCAoMikgdGhlICUgb2YgY2Vuc29yZWQgcGF0aWVudHMsIGFuZCAoMykgdGhlIHRvdGFsIG51bWJlciBvZiBmZWF0dXJlcyB1c2VkIChhZnRlciBmZWF0dXJlIHNlbGVjdGlvbikuIixhbGlnbiA9IGMoJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycpKSAlPiUKICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsIGZ1bGxfd2lkdGggPSBUICkgJT4lCiAgY29sdW1uX3NwZWMoMSxib2xkPVQpCmBgYAoKPGhyIHN0eWxlPSJoZWlnaHQ6MXB4O2JvcmRlcjpub25lO2NvbG9yOiMzMzM7YmFja2dyb3VuZC1jb2xvcjojMzMzOyIgLz4KCgojI0NhbGlicmF0aW9uCgoKRm9yIGNhbGlicmF0aW9uIG9uIChIaWdoLUNlbnNvcmluZywgSGlnaC1EaW1lbnNpb25hbCkgZGF0YXNldHMsIG91ciBmaW5kaW5ncyB3ZXJlIHRoYXQgTVRMUiwgQ294RU4tS1AsIGFuZCBSU0YtS00gd2VyZSBhbGwgZXF1aXZhbGVudC4gVGhlIEQtQ2FsaWJyYXRpb24gcmVzdWx0cyAoVGFibGUgMTMpIHNob3cgdGhhdCBBRlQgaXMgdGhlIG9ubHkgbW9kZWwgdG8gZmFpbCBELUNhbGlicmF0aW9uIChub3RlIENveCBmYWlsZWQgdG8gZmluaXNoKS4gU2ltaWxhcmx5LCB0aGUgMS1DYWxpYnJhdGlvbiByZXN1bHRzIChUYWJsZSAxNCkgc2hvdyB0aGF0IE1UTFIsIENveEVOLUtQIGFuZCBSU0YtS00gYXJlIGVxdWl2YWxlbnQgYWNyb3NzIHRoZSBkaWZmZXJlbnQgcGVyY2VudGlsZXMgc3VnZ2VzdGluZyBvdXIgZmluZGluZyBpcyBjb25zaXN0ZW50IGZvciB0aGlzIGRhdGFzZXQgYXMgd2VsbC4KCgpgYGB7ciwgZWNobz1GQUxTRX0KSENJbmQgPSByZXAoSEMsZWFjaCA9IDUpCnRvVGFibGUgPSBhcy5kYXRhLmZyYW1lKG1hdHJpeChkYXRhID0gdG9QbGF5JERDYWxbSENJbmRdLCBuY29sID0gbGVuZ3RoKGRhdGFzZXROYW1lc1tIQ10pKSkKdG9UYWJsZSA9IGFzLmRhdGEuZnJhbWUoYXBwbHkodG9UYWJsZSwyLGZ1bmN0aW9uKHgpIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHgpKSkpCmNvbG5hbWVzKHRvVGFibGUpID0gZGF0YXNldE5hbWVzW0hDXQp0b1RhYmxlID0gdG9UYWJsZVtjKDMsMSwyLDUsNCksMSxkcm9wPUZdCnJvd25hbWVzKHRvVGFibGUpID0gYygiS00iLCJBRlQiLCJDb3hFTi1LUCIsIlJTRi1LTSIsIk1UTFIiKQoKa2FibGUodG9UYWJsZSwgZGlnaXRzID0gMyxmb3JtYXQgPSAiaHRtbCIsIGNhcHRpb24gPSAiVGFibGUgMTM6IEQtQ2FsaWJyYXRpb24gcmVzdWx0cyBmb3IgdGhlIDQgKExvdy1DZW5zb3JpbmcsIEhpZ2gtRGltZW5zaW9uYWwpIGRhdGFzZXRzLiBUaGUgVG90YWwgY29sdW1uIGdpdmVzIHRoZSB0b3RhbCBudW1iZXIgb2YgZGF0YXNldHMgZm9yIHdoaWNoIGVhY2ggbW9kZWwgd2FzIEQtQ2FsaWJyYXRlZC4gTm90ZSB0aGUgQ294IG1vZGVsIGRvZXMgbm90IGFwcGVhciBhcyBpdCBmYWlsZWQgdG8gZmluaXNoIG9uIHRoaXMgZGF0YXNldC4iLGFsaWduID0gYygnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycpKSAlPiUKICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsIGZ1bGxfd2lkdGggPSBUKSAlPiUKICAgIGNvbHVtbl9zcGVjKGMoMSksYm9sZD1ULHdpZHRoX21pbiA9ICIyLjVjbSIpCgpgYGAKCmBgYHtyLGVjaG8gPSBGfQpvbmVDYWwgPSBhcy5kYXRhLmZyYW1lKGFwcGx5KHRvUGxheVs2OjEwXVtIQ0luZCxdLDIsZnVuY3Rpb24oeCkgYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoeCkpKSkKb25lQ2FsJE1vZGVsID0gcmVwKGFsZ05hbWVzLCBsZW5ndGgoZGF0YXNldE5hbWVzW0hDXSkpCmxpYnJhcnkoZHBseXIpCnRvVGFibGUgPSBvbmVDYWwgJT4lIGdyb3VwX2J5KE1vZGVsKSAlPiUgc3VtbWFyaXplKE9DMSA9IHN1bShPQ2FsMSA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DMiA9IHN1bShPQ2FsMiA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DMyA9IHN1bShPQ2FsMyA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DNCA9IHN1bShPQ2FsNCA+PTAuMDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9DNSA9IHN1bShPQ2FsNSA+PTAuMDUpKQp0b1RhYmxlID0gYXMuZGF0YS5mcmFtZSh0b1RhYmxlKQp0b1RhYmxlID0gdG9UYWJsZVtjKDMsMSwyLDUsNCksLTFdCnJvd25hbWVzKHRvVGFibGUpID0gYygiS00iLCJBRlQiLCJDb3hFTi1LUCIsIlJTRi1LTSIsIk1UTFIiKQpjb2xuYW1lcyh0b1RhYmxlKSA9IGMoIjEwdGgiLCIyNXRoIiwgIjUwdGgiLCI3NXRoIiwiOTB0aCIpCiAgCgprYWJsZSh0b1RhYmxlICwgZm9ybWF0ID0gImh0bWwiLCBjYXB0aW9uID0gIlRhYmxlIDE0OiBUaGUgMS1DYWxpYnJhdGlvbiByZXN1bHRzIGZvciB0aGUgNCAoTG93LUNlbnNvcmluZywgSGlnaC1EaW1lbnNpb25hbCkgZGF0YXNldHMuIEVhY2ggY29sdW1uIHJlcHJlc2VudHMgdGhlIDEwdGgsIDI1dGgsIDUwdGgsIDc1dGgsIGFuZCA5MHRoIHBlcmNlbnRpbGVzIG9mIGV2ZW50IHRpbWVzLiBFYWNoIHJvdyByZXByZXNlbnRzIHRoZSB0b3RhbCBudW1iZXIgb2YgZGF0YXNldHMgZm9yIHdoaWNoIGVhY2ggbW9kZWwgd2FzIDEtQ2FsaWJyYXRlZCAodGhlIG1heGltdW0gYmVpbmcgNCkuIE5vdGUgdGhlIENveCBtb2RlbCBkb2VzIG5vdCBhcHBlYXIgYXMgaXQgZmFpbGVkIHRvIGZpbmlzaCBvbiB0aGlzIGRhdGFzZXQuIixhbGlnbiA9IGMoJ2MnLCdjJywnYycsJ2MnLCdjJykpICU+JQogICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9ICJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IFQgKSAlPiUKICAgIGNvbHVtbl9zcGVjKGMoMSksYm9sZD1ULHdpZHRoX21pbiA9ICIyLjVjbSIpCgpgYGAKCjxociBzdHlsZT0iaGVpZ2h0OjFweDtib3JkZXI6bm9uZTtjb2xvcjojMzMzO2JhY2tncm91bmQtY29sb3I6IzMzMzsiIC8+CgoKIyNEaXNjcmltaW5hdGlvbgoKVGFibGUgMTUgcHJlc2VudHMgdGhlIGNvbmNvcmRhbmNlIHJlc3VsdHMgZm9yIHRoZSAoSGlnaC1DZW5zb3JpbmcsIEhpZ2gtRGltZW5zaW9uYWwpIGRhdGFzZXQuIFRoZSBmaW5kaW5ncyBpbiB0aGUgcGFwZXIgKHRoYXQgTVRMUiwgQ294RU4tS1AsIGFuZCBSU0YtS00gYXJlIGVxdWl2YWxlbnQgYW5kIGFsc28gc3VwZXJpb3IgdG8gQUZUKSBhcmUgc3VwcG9ydGVkIChhbHRob3VnaCBSU0YtS00gaGFzIG11Y2ggaGlnaGVyIHZhcmlhbmNlKS4gCgpgYGB7ciwgZWNobyA9IEZBTFNFLGVycm9yPUZBTFNFLHdhcm5pbmc9RkFMU0V9CnRvVGFibGUgPSBhcy5kYXRhLmZyYW1lKG1hdHJpeChkYXRhID0gdG9QbGF5JENvblN0YW5bSENJbmRdLCBuY29sID0gbGVuZ3RoKGRhdGFzZXROYW1lc1tIQ10pKSkKCnRvVGFibGUgPSB0b1RhYmxlW2MoMywxLDIsNSw0KSwxLCBkcm9wPUZdCnJvd25hbWVzKHRvVGFibGUpID0gYygiS00iLCJBRlQiLCJDb3hFTi1LUCIsIlJTRi1LTSIsIk1UTFIiKQpjb2xuYW1lcyh0b1RhYmxlKSA9IGRhdGFzZXROYW1lc1tIQ10KCnRvVGFibGUgICU+JQprYWJsZSh0b1RhYmxlLGZvcm1hdCA9ICJodG1sIiwgY2FwdGlvbiA9ICJUYWJsZSAxNTogQ29uY29yZGFuY2UgcmVzdWx0cyBmb3IgdGhlIDQgKExvdy1DZW5zb3JpbmcsIEhpZ2gtRGltZW5zaW9uYWwpIGRhdGFzZXRzLiBIZXJlIHdlIHByZXNlbnQgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgQ29uY29yZGFuY2UgYWNyb3NzIHRoZSA1IGNyb3NzLXZhbGlkYXRpb24gZm9sZHMuIEJvbGRlZCB2YWx1ZXMgcmVwcmVzZW50IHRoZSBiZXN0IChoaWdoZXN0IENvbmNvcmRhbmNlKSBwZXJmb3JtaW5nIG1vZGVscy4gTm90ZSB0aGUgQ294IG1vZGVsIGRvZXMgbm90IGFwcGVhciBhcyBpdCBmYWlsZWQgdG8gZmluaXNoIG9uIHRoaXMgZGF0YXNldC4iLGFsaWduID0gYygnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycsJ2MnLCdjJywnYycpKSAlPiUKICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsIGZ1bGxfd2lkdGggPSBUICkgJT4lCiAgICAgIGNvbHVtbl9zcGVjKGMoMSksYm9sZD1ULHdpZHRoX21pbiA9ICIyLjVjbSIpCgpgYGAK