Exploring the iris flower dataset

Rudaiba Tarannum
YWCA Higher Secondary Girls’ School
February 27, 2024

Part-1

Introduction

In this notebook, we will take a deep dive into the Iris dataset and apply an array of statistical and machine-learning techniques to uncover the relationships between the various features and the species of the flowers. Additionally, we will harness this dataset to construct and evaluate a classifier that can accurately predict the species of an iris flower based on its measurements. Get ready to explore and understand the Iris flower dataset like never before! The dataset was introduced by British statistician and biologist Ronald Fisher in his 1936 paper, “The use of multiple measurements in taxonomic problems.

Iris Dataset

This data set includes information on the sepal and petal measurements of three different types of irises - Setosa, Versicolour, and Virginica. The data set contains a total of 150 samples, with each sample having 4 different measurements - Sepal Length, Sepal Width, Petal Length, and Petal Width (all in centimeters). The rows represent the individual samples, while the columns contain the measurements of the respective attributes. glimpse(data)

Rows: 150
Columns: 5
$ sepal.length <dbl> 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4, 4.8, 4.8, 4.3, 5.8, 5.7, 5.4, 5.1, 5.7, 5.1…
$ sepal.width  <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.4, 3.0, 3.0, 4.0, 4.4, 3.9, 3.5, 3.8, 3.8…
$ petal.length <dbl> 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.6, 1.4, 1.1, 1.2, 1.5, 1.3, 1.4, 1.7, 1.5…
$ petal.width  <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1, 0.1, 0.2, 0.4, 0.4, 0.3, 0.3, 0.3…
$ variety      <chr> "Setosa", "Setosa", "Setosa", "Setosa", "Setosa", "Setosa", "Setosa", "Setosa", "Setosa", "Setosa"…

The target variable for this dataset is undoubtedly “variety”. Additionally, it is worth noting that all other variables are of type, which in R represents numeric values with double precision.

Variable Description
sepal.length sepal.length = length of the sepal
sepal.width sepal.width = width if the sepal
petal.length petal.length = length of the petal
petal.width petal.width = width of the petal
variety variety = specie of the flower

Based on the absence of any other categorical variables apart from the target variable in the dataset, we can conclude that there is no need to remove any variable from the dataset.

Data exploration

The Data:

Let’s start analyzing the dataset to understand the relationship between various features and flower species. We will be examining the dataset using different plots, and for each plot, a brief explanation will be provided to prevent any misunderstandings and make it easier to comprehend the figure.

Let’s take a look at the data itself. Let’s see the first 5 rows of data for each class:

1)Setosa:

2)Versicolor:

3)Virginica:

Exploratory Data Analysis:

We want to learn more about the data. We can calculate basic statistics on each of the data frame’s columns with summary:

  sepal.length    sepal.width     petal.length    petal.width      variety         
 Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100   Length:150        
 1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300   Class :character  
 Median :5.800   Median :3.000   Median :4.350   Median :1.300   Mode  :character  
 Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199                     
 3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800                     
 Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500                     

Numbers can tell a lot, but sometimes it is better to see the statistics with different plots.

Static plots:

Scatter plot:

1)Sepal Length vs. Sepal Width:

This scatterplot presents the correlation between sepal length and sepal width across three iris varieties, Setosa, Versicolor, and Virginica. Setosa demonstrates a moderate positive correlation (R = 0.46, p = 0.00084), indicating a noteworthy association between sepal length and width in this species. Versicolor exhibits a slightly stronger positive correlation (R = 0.53, p = 8.8e-05), suggesting a pronounced relationship between these attributes, potentially reflecting distinct characteristics unique to Versicolor. On the other hand, Virginica displays a robust positive correlation (R = 0.74, p = 6.7e-10), implying a significant relationship between sepal length and width in this variety, which may signify particular traits specific to Virginica.

2)Petal Length vs. Petal Width:

This scatterplot presents the correlation between petal length and petal width across three iris varieties, Setosa, Versicolor, and Virginica. Setosa exhibits a moderate positive correlation (R = 0.32, p = 0.023), suggesting a modest association between petal length and width in this variety. Versicolor displays a strong positive correlation (R = 0.79, p = 1.3e-11), indicating a pronounced relationship between these attributes, potentially reflecting specific characteristics unique to this species. Virginica shows a moderate positive correlation (R = 0.33, p = 0.019), similar to Setosa but with a slightly stronger correlation.

2)Sepal Length vs. Petal Length:

This scatterplot presents the correlation between sepal length and petal length across three iris varieties, Setosa, Versicolor, and Virginica. Setosa showcases a strong positive correlation (R = 0.86, p = 6.3e-16), indicating a robust association between sepal and petal lengths in this species. Versicolor demonstrates a similarly strong positive correlation (R = 0.75, p = 2.6e-10), implying a significant relationship between these characteristics, possibly reflecting unique traits inherent to Versicolor. In contrast, Virginica exhibits a weaker positive correlation (R = 0.27, p = 0.061), suggesting a less pronounced relationship between sepal and petal lengths compared to the other two varieties.

Box plot:

1)Sepal Length:

Setosa has the smallest sepal length among the three varieties, with Versicolor in the middle, ranging from 5.5 to 6.5 cm. Only one observation deviates with the Virginica variety having the longest sepal length.

2)Sepal Width:

Among the three species, Setosa stands out as the widest, with its sepals spreading out more than those of Versicolor and Virginica. Nevertheless, both Versicolor and Virginica also exhibit a considerable width, following closely behind Setosa.

3)Petal Length:

Among the three species, there is a noticeable difference in the length of their petals. Specifically, Setosa stands out with the smallest petal lengths.

4)Petal Width:

The petal width exhibits a significant variation among the three species of iris. In particular, Setosa stands out for having the smallest petal width, while Verginica shows the highest degree of diversity in petal width.

Violin plot:

1)Sepal Length:

The three varieties of plants - Setosa, Versicolor, and Virginica - have different sepal lengths. Setosa has the smallest sepal length, typically measuring shorter than the other two varieties. The Versicolor variety has a moderate sepal length, ranging from 5.5 to 6.5 cm. On the other hand, the Virginica variety usually has the longest sepal length, except for one observation where it deviates from the norm.

2)Sepal Width:

Among the three species, Setosa stands out with its remarkable width. Its sepals spread out considerably more than those of Versicolor and Virginica, giving it a distinctive appearance. While Versicolor and Virginica do not exhibit the same degree of width as Setosa, they are still quite broad, following closely behind Setosa in terms of their width.

3)Petal Length:

Out of the three species, it is worth noting that there is a distinct variation in the length of their petals. In particular, Setosa species stands out with its remarkably small petals, which are significantly shorter than those of the other two species.

4)Petal Width:

Among the three species of iris, there is a significant variation in petal width. Setosa has the smallest petal width, while Verginica exhibits the highest degree of diversity in petal width.

Part-2

The plots we have been using for data visualization have been helpful so far. They have helped us understand the data better than before. However, to delve deeper into the dataset, we need to interact with the data. Therefore, let us explore some interactive plots.

Interactive plots:

This dataset contains 4 features: Sepal length, Sepal Width, Petal Length, and Petal Width. To display the data, we will use two types of interactive plots: violin plots and box plots. We will begin by displaying the Sepal length and the Sepal Width using the interactive violin plots, followed by the display of the Petal length and the Petal Width using the interactive Box plot.

Interactive Violin plot:

1)Sepal Length:

1)Sepal Width:

Interactive Box plot:

1)Petal Length:

1)Petal Width:

Correlation:

1)Calculating the correlation matrix:

             sepal.length sepal.width petal.length petal.width
sepal.length    1.0000000  -0.1175698    0.8717538   0.8179411
sepal.width    -0.1175698   1.0000000   -0.4284401  -0.3661259
petal.length    0.8717538  -0.4284401    1.0000000   0.9628654
petal.width     0.8179411  -0.3661259    0.9628654   1.0000000

The correlation matrix shows that there are strong positive correlations between sepal length on one hand, and both petal length (0.87) and petal width (0.82) on the other. There is also a strong positive correlation between petal length and width (0.96). These results suggest that there may be linear relationships between these attributes, as they tend to increase together. On the other hand, there is a weak negative correlation between sepal length and width (-0.12). This indicates that sepal width may slightly decrease as sepal length increases, but this relationship is not very strong..

1)Correlation mattrix plot:

Pair plot:

Principal Component Analysis(PCA):

Let’s start by assessing what we have at our disposal.

Standard deviations (1, .., p=4):
[1] 1.7083611 0.9560494 0.3830886 0.1439265

Rotation (n x k) = (4 x 4):
                    PC1         PC2        PC3        PC4
sepal.length  0.5210659 -0.37741762  0.7195664  0.2612863
sepal.width  -0.2693474 -0.92329566 -0.2443818 -0.1235096
petal.length  0.5804131 -0.02449161 -0.1421264 -0.8014492
petal.width   0.5648565 -0.06694199 -0.6342727  0.5235971

Let’s summerise the numbers,

Importance of components:
                          PC1    PC2     PC3     PC4
Standard deviation     1.7084 0.9560 0.38309 0.14393
Proportion of Variance 0.7296 0.2285 0.03669 0.00518
Cumulative Proportion  0.7296 0.9581 0.99482 1.00000

When interpreting the proportion of variance, it is important to determine which components hold the most information and what percentage of the original data’s variability they capture. In this analysis, Components 1 and 2 together explain almost 95.81% of the variance, indicating that they capture a large portion of the information from the original variables. Component 1 alone accounts for 72.96% of the total variance, while Component 2 contributes an additional 22.85%. These results suggest that the first two components are highly informative and capture the majority of the variability present in the dataset. On the other hand, subsequent components such as Components 3 and 4 explain much smaller proportions of variance (3.669% and 0.518% respectively), indicating that their contributions to the overall variability of the data are significantly lower.

1)Bar plot of PCAs:

The scree plot for the principal component analysis (PCA) indicates a significant drop in variance from 73% to 22.9% in the first two components, with the remaining two components contributing very little. This suggests that the first two components account for the majority of the significant variance in the data.

2) Contribution plot for PCs:

2) Cluster plot after PCA:

SVM model:

2)SVM model:

We will now create a machine learning model to predict iris variety based on petal and sepal measurements.

train_data
test_data
predict(svm_model, test_data[15,-5])
        76 
Versicolor 
Levels: Setosa Versicolor Virginica

This machine learning model has been trained using the train_data. Its purpose is to predict the variety of a flower based on the values of its attributes. When we give it values from the test_data without the target variable, it sums up the values of all the other columns and compares them with the data from the train_data. It then identifies which of the three varieties have similar attribute values to the input and returns its prediction. In this specific case, the model detected that test_data[15, -5] belongs to the Versicolor variety, which is correct.

2)Confusion matrix:

Confusion Matrix and Statistics

            Reference
Prediction   Setosa Versicolor Virginica
  Setosa         10          0         0
  Versicolor      0         10         0
  Virginica       0          0        10

Overall Statistics
                                     
               Accuracy : 1          
                 95% CI : (0.8843, 1)
    No Information Rate : 0.3333     
    P-Value [Acc > NIR] : 4.857e-15  
                                     
                  Kappa : 1          
                                     
 Mcnemar's Test P-Value : NA         

Statistics by Class:

                     Class: Setosa Class: Versicolor Class: Virginica
Sensitivity                 1.0000            1.0000           1.0000
Specificity                 1.0000            1.0000           1.0000
Pos Pred Value              1.0000            1.0000           1.0000
Neg Pred Value              1.0000            1.0000           1.0000
Prevalence                  0.3333            0.3333           0.3333
Detection Rate              0.3333            0.3333           0.3333
Detection Prevalence        0.3333            0.3333           0.3333
Balanced Accuracy           1.0000            1.0000           1.0000

US Admission Dataset

a)removing Serial No column:

b)Pair plot:

c)Linear regression:

1) GRE Score:

2) TOEFL Score:

3) University rating:

4) SOP:

5) LOR:

6) CGPA:

7) Research:

The plots show a binary dependent variable, making linear regression unsuitable. Instead, logistic regression can estimate probabilities. All factors examined for university admission display a positive association. Increasing these factors increases the probability of admission.

d)Polynomial regression:

1) GRE Score:

2) TOEFL Score:

3) University rating:

4) SOP:

5) LOR:

6) CGPA:

7) Research:

The plotted polynomial graphs above provide a clear and accurate representation that indicates a positive correlation between GRE and TOEFL scores, strong recommendation letters, high CGPA, and research experience with increased admission chances to US universities. These findings emphasize the importance of academic performance, language proficiency, strong endorsements, consistent grades, and research engagement in securing admission.

Conclsion

To sum up, our data science project has been a success thanks to the insights we gained from analyzing the Iris flower dataset. We were able to develop an accurate machine learning model that can predict the species of iris based on sepal and petal measurements. This project has demonstrated the power of data analysis and machine learning and how it can be applied to solve real-world problems.

Reference

1.Exploring the Iris flower dataset, Emine Bozkus, Medium - eminebozkus.medium.com/exploring-the-iris-flower-dataset-4e000bcc266c

  1. Data Science Example - Iris dataset, lac.inpe - http://www.lac.inpe.br/~rafael.santos/Docs/CAP394/WholeStory-Iris.html

3.Iris flower data set, wikipedia - https://en.wikipedia.org/wiki/Iris_flower_data_set

4.Explore diabetes-related factors and predictive modeling of admittance into a masters graduate program at the United States University: Machine learning approaches, Nasif Hossain, Department of Global Health Policy, Graduate School of Medicine, The University of Tokyo - https://rpubs.com/Nasif/1136525

LS0tDQp0aXRsZTogIl9fRGF0YSBTY2llbmNlIFByb2plY3RfXyINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBmYWxzZQ0KICAgICAgc21vb3RoX3Njcm9sbDogZmFsc2UNCi0tLQ0KDQojIyBfX0V4cGxvcmluZyB0aGUgaXJpcyBmbG93ZXIgZGF0YXNldF9fDQojIyMjIyA8c3BhbiBzdHlsZT0iY29sb3I6Z3JheTsiPlJ1ZGFpYmEgVGFyYW5udW08L3NwYW4+ICANCiMjIyMjIyA8c3BhbiBzdHlsZT0iY29sb3I6Z3JheTsiPllXQ0EgSGlnaGVyIFNlY29uZGFyeSBHaXJscycgU2Nob29sIDwvc3Bhbj4NCiMjIyMjIyA8c3BhbiBzdHlsZT0iY29sb3I6Z3JheTsiPkZlYnJ1YXJ5IDI3LCAyMDI0IDwvc3Bhbj4NCg0KIyBQYXJ0LTENCiMjIDxzcGFuIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lIj5fX0ludHJvZHVjdGlvbl9fPC9zcGFuPg0KSW4gdGhpcyBub3RlYm9vaywgd2Ugd2lsbCB0YWtlIGEgZGVlcCBkaXZlIGludG8gdGhlIElyaXMgZGF0YXNldCBhbmQgYXBwbHkgYW4gYXJyYXkgb2Ygc3RhdGlzdGljYWwgYW5kIG1hY2hpbmUtbGVhcm5pbmcgdGVjaG5pcXVlcyB0byB1bmNvdmVyIHRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gdGhlIHZhcmlvdXMgZmVhdHVyZXMgYW5kIHRoZSBzcGVjaWVzIG9mIHRoZSBmbG93ZXJzLiBBZGRpdGlvbmFsbHksIHdlIHdpbGwgaGFybmVzcyB0aGlzIGRhdGFzZXQgdG8gY29uc3RydWN0IGFuZCBldmFsdWF0ZSBhIGNsYXNzaWZpZXIgdGhhdCBjYW4gYWNjdXJhdGVseSBwcmVkaWN0IHRoZSBzcGVjaWVzIG9mIGFuIGlyaXMgZmxvd2VyIGJhc2VkIG9uIGl0cyBtZWFzdXJlbWVudHMuIEdldCByZWFkeSB0byBleHBsb3JlIGFuZCB1bmRlcnN0YW5kIHRoZSBJcmlzIGZsb3dlciBkYXRhc2V0IGxpa2UgbmV2ZXIgYmVmb3JlISBUaGUgZGF0YXNldCB3YXMgaW50cm9kdWNlZCBieSBCcml0aXNoIHN0YXRpc3RpY2lhbiBhbmQgYmlvbG9naXN0IFJvbmFsZCBGaXNoZXIgaW4gaGlzIDE5MzYgcGFwZXIsIOKAnFRoZSB1c2Ugb2YgbXVsdGlwbGUgbWVhc3VyZW1lbnRzIGluIHRheG9ub21pYyBwcm9ibGVtcy4NCg0KDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KbGlicmFyeShpbWFnZXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShndCkNCmxpYnJhcnkoZ2dwdWJyKSANCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShHR2FsbHkpDQpsaWJyYXJ5KHN0YXRzKQ0KbGlicmFyeShmYWN0b2V4dHJhKQ0KbGlicmFyeShlMTA3MSkNCmxpYnJhcnkoY2FyZXQpDQpsaWJyYXJ5KGxhdHRpY2UpDQoNCmlyaXMgPC0gcmVhZC5jc3YoImlyaXMuY3N2IikNClVTX0FkbWlzc2lvbiA9IHJlYWQuY3N2KCJVUyBBZG1pc3Npb24uY3N2IikNCg0KYGBgDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KVVNfQWRtaXNzaW9uJFJlc2VhcmNoPC1mYWN0b3IoVVNfQWRtaXNzaW9uJFJlc2VhcmNoLA0KICAgICAgICAgICAgICAgbGV2ZWxzID0gYygwLCAxKSwgbGFiZWxzID0gYygiTm8iLCAiWWVzIikpDQpgYGANCg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJDOi9Vc2Vycy84ODAxOC9Eb3dubG9hZHMvaXJpcy5wbmciKQ0KYGBgDQoNCg0KIyMgPHNwYW4gc3R5bGU9InRleHQtZGVjb3JhdGlvbjp1bmRlcmxpbmUiPl9fSXJpcyBEYXRhc2V0X188L3NwYW4+DQpUaGlzIGRhdGEgc2V0IGluY2x1ZGVzIGluZm9ybWF0aW9uIG9uIHRoZSBzZXBhbCBhbmQgcGV0YWwgbWVhc3VyZW1lbnRzIG9mIHRocmVlIGRpZmZlcmVudCB0eXBlcyBvZiBpcmlzZXMgLSBTZXRvc2EsIFZlcnNpY29sb3VyLCBhbmQgVmlyZ2luaWNhLiBUaGUgZGF0YSBzZXQgY29udGFpbnMgYSB0b3RhbCBvZiAxNTAgc2FtcGxlcywgd2l0aCBlYWNoIHNhbXBsZSBoYXZpbmcgNCBkaWZmZXJlbnQgbWVhc3VyZW1lbnRzIC0gU2VwYWwgTGVuZ3RoLCBTZXBhbCBXaWR0aCwgUGV0YWwgTGVuZ3RoLCBhbmQgUGV0YWwgV2lkdGggKGFsbCBpbiBjZW50aW1ldGVycykuIFRoZSByb3dzIHJlcHJlc2VudCB0aGUgaW5kaXZpZHVhbCBzYW1wbGVzLCB3aGlsZSB0aGUgY29sdW1ucyBjb250YWluIHRoZSBtZWFzdXJlbWVudHMgb2YgdGhlIHJlc3BlY3RpdmUgYXR0cmlidXRlcy4NCmdsaW1wc2UoZGF0YSkNCg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmdsaW1wc2UoaXJpcykNCmBgYA0KDQoNClRoZSB0YXJnZXQgdmFyaWFibGUgZm9yIHRoaXMgZGF0YXNldCBpcyB1bmRvdWJ0ZWRseSAidmFyaWV0eSIuIEFkZGl0aW9uYWxseSwgaXQgaXMgd29ydGggbm90aW5nIHRoYXQgYWxsIG90aGVyIHZhcmlhYmxlcyBhcmUgb2YgPGRibD4gdHlwZSwgd2hpY2ggaW4gUiByZXByZXNlbnRzIG51bWVyaWMgdmFsdWVzIHdpdGggZG91YmxlIHByZWNpc2lvbi4gDQoNCg0KYGBge3IsIGVjaG89RkFMU0V9DQppcmlzX3RhYmxlID0gZGF0YS5mcmFtZSgNCiAgVmFyaWFibGUgPSBjKCJzZXBhbC5sZW5ndGgiLCAic2VwYWwud2lkdGgiLCAicGV0YWwubGVuZ3RoIiwgInBldGFsLndpZHRoIiwgInZhcmlldHkiKSwNCiAgRGVzY3JpcHRpb24gPSBjKCJzZXBhbC5sZW5ndGggPSBsZW5ndGggb2YgdGhlIHNlcGFsIiwgInNlcGFsLndpZHRoID0gd2lkdGggaWYgdGhlIHNlcGFsIiwgInBldGFsLmxlbmd0aCA9IGxlbmd0aCBvZiB0aGUgcGV0YWwiLCAicGV0YWwud2lkdGggPSB3aWR0aCBvZiB0aGUgcGV0YWwiLCAidmFyaWV0eSA9IHNwZWNpZSBvZiB0aGUgZmxvd2VyIikNCikNCmd0KGlyaXNfdGFibGUpDQoNCmBgYA0KDQoNCg0KQmFzZWQgb24gdGhlIGFic2VuY2Ugb2YgYW55IG90aGVyIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBhcGFydCBmcm9tIHRoZSB0YXJnZXQgdmFyaWFibGUgaW4gdGhlIGRhdGFzZXQsIHdlIGNhbiBjb25jbHVkZSB0aGF0IHRoZXJlIGlzIG5vIG5lZWQgdG8gcmVtb3ZlIGFueSB2YXJpYWJsZSBmcm9tIHRoZSBkYXRhc2V0Lg0KDQoNCiMjIDxzcGFuIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lIj5fX0RhdGEgZXhwbG9yYXRpb25fXzwvc3Bhbj4NCg0KIyMjIDxzcGFuIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lIj5UaGUgRGF0YTogPC9zcGFuPg0KDQpMZXQncyBzdGFydCBhbmFseXppbmcgdGhlIGRhdGFzZXQgdG8gdW5kZXJzdGFuZCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdmFyaW91cyBmZWF0dXJlcyBhbmQgZmxvd2VyIHNwZWNpZXMuIFdlIHdpbGwgYmUgZXhhbWluaW5nIHRoZSBkYXRhc2V0IHVzaW5nIGRpZmZlcmVudCBwbG90cywgYW5kIGZvciBlYWNoIHBsb3QsIGEgYnJpZWYgZXhwbGFuYXRpb24gd2lsbCBiZSBwcm92aWRlZCB0byBwcmV2ZW50IGFueSBtaXN1bmRlcnN0YW5kaW5ncyBhbmQgbWFrZSBpdCBlYXNpZXIgdG8gY29tcHJlaGVuZCB0aGUgZmlndXJlLg0KDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KaXJpcw0KYGBgDQoNCkxldCdzIHRha2UgYSBsb29rIGF0IHRoZSBkYXRhIGl0c2VsZi4gTGV0J3Mgc2VlIHRoZSBmaXJzdCA1IHJvd3Mgb2YgZGF0YSBmb3IgZWFjaCBjbGFzczoNCg0KIyMjIyAxKVNldG9zYToNCg0KYGBge3IsIGVjaG89RkFMU0V9DQpzdWJzZXQoaXJpcywgdmFyaWV0eSA9PSAiU2V0b3NhIilbMTo1LF0NCmBgYA0KDQoNCiMjIyMgMilWZXJzaWNvbG9yOg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnN1YnNldChpcmlzLCB2YXJpZXR5ID09ICJWZXJzaWNvbG9yIilbMTo1LF0NCmBgYA0KDQoNCg0KIyMjIyAzKVZpcmdpbmljYToNCg0KYGBge3IsIGVjaG89RkFMU0V9DQpzdWJzZXQoaXJpcywgdmFyaWV0eSA9PSAiVmlyZ2luaWNhIilbMTo1LF0NCmBgYA0KDQoNCiMjIyA8c3BhbiBzdHlsZT0idGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZSI+RXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpczogPC9zcGFuPg0KDQoNCldlIHdhbnQgdG8gbGVhcm4gbW9yZSBhYm91dCB0aGUgZGF0YS4gV2UgY2FuIGNhbGN1bGF0ZSBiYXNpYyBzdGF0aXN0aWNzIG9uIGVhY2ggb2YgdGhlIGRhdGEgZnJhbWUncyBjb2x1bW5zIHdpdGggc3VtbWFyeToNCg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnN1bW1hcnkoaXJpcykNCmBgYA0KDQpOdW1iZXJzIGNhbiB0ZWxsIGEgbG90LCBidXQgc29tZXRpbWVzIGl0IGlzIGJldHRlciB0byBzZWUgdGhlIHN0YXRpc3RpY3Mgd2l0aCBkaWZmZXJlbnQgcGxvdHMuDQoNCiMjIyA8c3BhbiBzdHlsZT0idGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZSI+U3RhdGljIHBsb3RzOiA8L3NwYW4+DQoNCiMjIyMgPHNwYW4gc3R5bGU9InRleHQtZGVjb3JhdGlvbjp1bmRlcmxpbmUiPl9fU2NhdHRlciBwbG90OiBfXzwvc3Bhbj4NCg0KIyMjIyAxKVNlcGFsIExlbmd0aCB2cy4gU2VwYWwgV2lkdGg6IA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnNjYXR0ZXJfcGxvdCA8LSBnZ3Bsb3QoaXJpcywgYWVzKHggPSBzZXBhbC5sZW5ndGgsIHkgPSBzZXBhbC53aWR0aCwgY29sb3IgPSB2YXJpZXR5KSkgKw0KICBnZW9tX3BvaW50KCkgKyANCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJTZXBhbCBMZW5ndGggdnMuIFNlcGFsIFdpZHRoIiwNCiAgICAgICB4ID0gIlNlcGFsIExlbmd0aCIsIHkgPSAiU2VwYWwgV2lkdGgiKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGE9IHl+cG9seSh4LDIpLCBzZSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJywgbGV2ZWw9MC45NSkgKw0KICBzdGF0X2NvcihkYXRhID0gc3Vic2V0KGlyaXMsIHZhcmlldHkgPT0gIlNldG9zYSIpLCBtZXRob2QgPSAicGVhcnNvbiIsIGxhYmVsLnggPSA1LCBsYWJlbC55ID0gNC4yKSArDQogIHN0YXRfY29yKGRhdGEgPSBzdWJzZXQoaXJpcywgdmFyaWV0eSA9PSAiVmVyc2ljb2xvciIpLCBtZXRob2QgPSAicGVhcnNvbiIsIGxhYmVsLnggPSA1LCBsYWJlbC55ID0gNC40KSArDQogIHN0YXRfY29yKGRhdGEgPSBzdWJzZXQoaXJpcywgdmFyaWV0eSA9PSAiVmlyZ2luaWNhIiksIG1ldGhvZCA9ICJwZWFyc29uIiwgbGFiZWwueCA9IDUsIGxhYmVsLnkgPSA0LjYpDQoNCnNjYXR0ZXJfcGxvdA0KYGBgDQoNCg0KVGhpcyBzY2F0dGVycGxvdCBwcmVzZW50cyB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBzZXBhbCBsZW5ndGggYW5kIHNlcGFsIHdpZHRoIGFjcm9zcyB0aHJlZSBpcmlzIHZhcmlldGllcywgU2V0b3NhLCBWZXJzaWNvbG9yLCBhbmQgVmlyZ2luaWNhLiBTZXRvc2EgZGVtb25zdHJhdGVzIGEgbW9kZXJhdGUgcG9zaXRpdmUgY29ycmVsYXRpb24gKFIgPSAwLjQ2LCBwID0gMC4wMDA4NCksIGluZGljYXRpbmcgYSBub3Rld29ydGh5IGFzc29jaWF0aW9uIGJldHdlZW4gc2VwYWwgbGVuZ3RoIGFuZCB3aWR0aCBpbiB0aGlzIHNwZWNpZXMuIFZlcnNpY29sb3IgZXhoaWJpdHMgYSBzbGlnaHRseSBzdHJvbmdlciBwb3NpdGl2ZSBjb3JyZWxhdGlvbiAoUiA9IDAuNTMsIHAgPSA4LjhlLTA1KSwgc3VnZ2VzdGluZyBhIHByb25vdW5jZWQgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlc2UgYXR0cmlidXRlcywgcG90ZW50aWFsbHkgcmVmbGVjdGluZyBkaXN0aW5jdCBjaGFyYWN0ZXJpc3RpY3MgdW5pcXVlIHRvIFZlcnNpY29sb3IuIE9uIHRoZSBvdGhlciBoYW5kLCBWaXJnaW5pY2EgZGlzcGxheXMgYSByb2J1c3QgcG9zaXRpdmUgY29ycmVsYXRpb24gKFIgPSAwLjc0LCBwID0gNi43ZS0xMCksIGltcGx5aW5nIGEgc2lnbmlmaWNhbnQgcmVsYXRpb25zaGlwIGJldHdlZW4gc2VwYWwgbGVuZ3RoIGFuZCB3aWR0aCBpbiB0aGlzIHZhcmlldHksIHdoaWNoIG1heSBzaWduaWZ5IHBhcnRpY3VsYXIgdHJhaXRzIHNwZWNpZmljIHRvIFZpcmdpbmljYS4NCg0KIyMjIyAyKVBldGFsIExlbmd0aCB2cy4gUGV0YWwgV2lkdGg6IA0KDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0Kc2NhdHRlcl9wbG90IDwtIGdncGxvdChpcmlzLCBhZXMoeCA9IHBldGFsLmxlbmd0aCwgeSA9IHBldGFsLndpZHRoLCBjb2xvciA9IHZhcmlldHkpKSArDQogIGdlb21fcG9pbnQoKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiUGV0YWwgTGVuZ3RoIHZzLiBQZXRhbCBXaWR0aCIsDQogICAgICAgeCA9ICJQZXRhbCBMZW5ndGgiLCB5ID0gIlBldGFsIFdpZHRoIikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhPSB5fnBvbHkoeCwyKSwgc2UgPSBUUlVFLCBjb2xvciA9ICdibGFjaycsIGxldmVsPTAuOTUpICsNCiAgc3RhdF9jb3IoZGF0YSA9IHN1YnNldChpcmlzLCB2YXJpZXR5ID09ICJTZXRvc2EiKSwgbWV0aG9kID0gInBlYXJzb24iLCBsYWJlbC54ID0gMiwgbGFiZWwueSA9IDIpICsNCiAgc3RhdF9jb3IoZGF0YSA9IHN1YnNldChpcmlzLCB2YXJpZXR5ID09ICJWZXJzaWNvbG9yIiksIG1ldGhvZCA9ICJwZWFyc29uIiwgbGFiZWwueCA9IDIsIGxhYmVsLnkgPSAyLjIpICsNCiAgc3RhdF9jb3IoZGF0YSA9IHN1YnNldChpcmlzLCB2YXJpZXR5ID09ICJWaXJnaW5pY2EiKSwgbWV0aG9kID0gInBlYXJzb24iLCBsYWJlbC54ID0gMiwgbGFiZWwueSA9IDIuNCkNCg0Kc2NhdHRlcl9wbG90DQpgYGANCg0KDQpUaGlzIHNjYXR0ZXJwbG90IHByZXNlbnRzIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHBldGFsIGxlbmd0aCBhbmQgcGV0YWwgd2lkdGggYWNyb3NzIHRocmVlIGlyaXMgdmFyaWV0aWVzLCBTZXRvc2EsIFZlcnNpY29sb3IsIGFuZCBWaXJnaW5pY2EuIFNldG9zYSBleGhpYml0cyBhIG1vZGVyYXRlIHBvc2l0aXZlIGNvcnJlbGF0aW9uIChSID0gMC4zMiwgcCA9IDAuMDIzKSwgc3VnZ2VzdGluZyBhIG1vZGVzdCBhc3NvY2lhdGlvbiBiZXR3ZWVuIHBldGFsIGxlbmd0aCBhbmQgd2lkdGggaW4gdGhpcyB2YXJpZXR5LiBWZXJzaWNvbG9yIGRpc3BsYXlzIGEgc3Ryb25nIHBvc2l0aXZlIGNvcnJlbGF0aW9uIChSID0gMC43OSwgcCA9IDEuM2UtMTEpLCBpbmRpY2F0aW5nIGEgcHJvbm91bmNlZCByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGVzZSBhdHRyaWJ1dGVzLCBwb3RlbnRpYWxseSByZWZsZWN0aW5nIHNwZWNpZmljIGNoYXJhY3RlcmlzdGljcyB1bmlxdWUgdG8gdGhpcyBzcGVjaWVzLiBWaXJnaW5pY2Egc2hvd3MgYSBtb2RlcmF0ZSBwb3NpdGl2ZSBjb3JyZWxhdGlvbiAoUiA9IDAuMzMsIHAgPSAwLjAxOSksIHNpbWlsYXIgdG8gU2V0b3NhIGJ1dCB3aXRoIGEgc2xpZ2h0bHkgc3Ryb25nZXIgY29ycmVsYXRpb24uDQoNCg0KDQojIyMjIDIpU2VwYWwgTGVuZ3RoIHZzLiBQZXRhbCBMZW5ndGg6IA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnNjYXR0ZXJfcGxvdCA8LSBnZ3Bsb3QoaXJpcywgYWVzKHggPSBzZXBhbC5sZW5ndGgsIHkgPSBwZXRhbC5sZW5ndGgsIGNvbG9yID0gdmFyaWV0eSkpICsNCiAgZ2VvbV9wb2ludCgpICsgDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiU2VwYWwgTGVuZ3RoIHZzLiBQZXRhbCBMZW5ndGgiLA0KICAgICAgIHggPSAiU2VwYWwgTGVuZ3RoIiwgeSA9ICJQZXRhbCBMZW5ndGgiKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGE9IHl+cG9seSh4LDIpLCBzZSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJywgbGV2ZWw9MC45NSkgKw0KICBzdGF0X2NvcihkYXRhID0gc3Vic2V0KGlyaXMsIHZhcmlldHkgPT0gIlNldG9zYSIpLCBtZXRob2QgPSAicGVhcnNvbiIsIGxhYmVsLnggPSA1LCBsYWJlbC55ID0gNikgKw0KICBzdGF0X2NvcihkYXRhID0gc3Vic2V0KGlyaXMsIHZhcmlldHkgPT0gIlZlcnNpY29sb3IiKSwgbWV0aG9kID0gInBlYXJzb24iLCBsYWJlbC54ID0gNSwgbGFiZWwueSA9IDYuNSkgKw0KICBzdGF0X2NvcihkYXRhID0gc3Vic2V0KGlyaXMsIHZhcmlldHkgPT0gIlZpcmdpbmljYSIpLCBtZXRob2QgPSAicGVhcnNvbiIsIGxhYmVsLnggPSA1LCBsYWJlbC55ID0gNykNCg0Kc2NhdHRlcl9wbG90DQpgYGANCg0KVGhpcyBzY2F0dGVycGxvdCBwcmVzZW50cyB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBzZXBhbCBsZW5ndGggYW5kIHBldGFsIGxlbmd0aCBhY3Jvc3MgdGhyZWUgaXJpcyB2YXJpZXRpZXMsIFNldG9zYSwgVmVyc2ljb2xvciwgYW5kIFZpcmdpbmljYS4gU2V0b3NhIHNob3djYXNlcyBhIHN0cm9uZyBwb3NpdGl2ZSBjb3JyZWxhdGlvbiAoUiA9IDAuODYsIHAgPSA2LjNlLTE2KSwgaW5kaWNhdGluZyBhIHJvYnVzdCBhc3NvY2lhdGlvbiBiZXR3ZWVuIHNlcGFsIGFuZCBwZXRhbCBsZW5ndGhzIGluIHRoaXMgc3BlY2llcy4gVmVyc2ljb2xvciBkZW1vbnN0cmF0ZXMgYSBzaW1pbGFybHkgc3Ryb25nIHBvc2l0aXZlIGNvcnJlbGF0aW9uIChSID0gMC43NSwgcCA9IDIuNmUtMTApLCBpbXBseWluZyBhIHNpZ25pZmljYW50IHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZXNlIGNoYXJhY3RlcmlzdGljcywgcG9zc2libHkgcmVmbGVjdGluZyB1bmlxdWUgdHJhaXRzIGluaGVyZW50IHRvIFZlcnNpY29sb3IuIEluIGNvbnRyYXN0LCBWaXJnaW5pY2EgZXhoaWJpdHMgYSB3ZWFrZXIgcG9zaXRpdmUgY29ycmVsYXRpb24gKFIgPSAwLjI3LCBwID0gMC4wNjEpLCBzdWdnZXN0aW5nIGEgbGVzcyBwcm9ub3VuY2VkIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHNlcGFsIGFuZCBwZXRhbCBsZW5ndGhzIGNvbXBhcmVkIHRvIHRoZSBvdGhlciB0d28gdmFyaWV0aWVzLg0KDQoNCiMjIyMgPHNwYW4gc3R5bGU9InRleHQtZGVjb3JhdGlvbjp1bmRlcmxpbmUiPl9fQm94IHBsb3Q6IF9fPC9zcGFuPg0KDQojIyMjIDEpU2VwYWwgTGVuZ3RoOiANCg0KYGBge3IsIGVjaG89RkFMU0V9DQpnZ3Bsb3QoaXJpcywgYWVzKHkgPSBzZXBhbC5sZW5ndGgsIHggPSB2YXJpZXR5LCBmaWxsID0gdmFyaWV0eSkpICsNCiAgZ2VvbV9ib3hwbG90KCkgKyANCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANClNldG9zYSBoYXMgdGhlIHNtYWxsZXN0IHNlcGFsIGxlbmd0aCBhbW9uZyB0aGUgdGhyZWUgdmFyaWV0aWVzLCB3aXRoIFZlcnNpY29sb3IgaW4gdGhlIG1pZGRsZSwgcmFuZ2luZyBmcm9tIDUuNSB0byA2LjUgY20uIE9ubHkgb25lIG9ic2VydmF0aW9uIGRldmlhdGVzIHdpdGggdGhlIFZpcmdpbmljYSB2YXJpZXR5IGhhdmluZyB0aGUgbG9uZ2VzdCBzZXBhbCBsZW5ndGguDQoNCiMjIyMgMilTZXBhbCBXaWR0aDogDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KZ2dwbG90KGlyaXMsIGFlcyh5ID0gc2VwYWwud2lkdGgsIHggPSB2YXJpZXR5LCBmaWxsID0gdmFyaWV0eSkpICsNCiAgZ2VvbV9ib3hwbG90KCkgKyANCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCkFtb25nIHRoZSB0aHJlZSBzcGVjaWVzLCBTZXRvc2Egc3RhbmRzIG91dCBhcyB0aGUgd2lkZXN0LCB3aXRoIGl0cyBzZXBhbHMgc3ByZWFkaW5nIG91dCBtb3JlIHRoYW4gdGhvc2Ugb2YgVmVyc2ljb2xvciBhbmQgVmlyZ2luaWNhLiBOZXZlcnRoZWxlc3MsIGJvdGggVmVyc2ljb2xvciBhbmQgVmlyZ2luaWNhIGFsc28gZXhoaWJpdCBhIGNvbnNpZGVyYWJsZSB3aWR0aCwgZm9sbG93aW5nIGNsb3NlbHkgYmVoaW5kIFNldG9zYS4NCg0KIyMjIyAzKVBldGFsIExlbmd0aDogDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KZ2dwbG90KGlyaXMsIGFlcyh5ID0gcGV0YWwubGVuZ3RoLCB4ID0gdmFyaWV0eSwgZmlsbCA9IHZhcmlldHkpKSArDQogIGdlb21fYm94cGxvdCgpICsgDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQpBbW9uZyB0aGUgdGhyZWUgc3BlY2llcywgdGhlcmUgaXMgYSBub3RpY2VhYmxlIGRpZmZlcmVuY2UgaW4gdGhlIGxlbmd0aCBvZiB0aGVpciBwZXRhbHMuIFNwZWNpZmljYWxseSwgU2V0b3NhIHN0YW5kcyBvdXQgd2l0aCB0aGUgc21hbGxlc3QgcGV0YWwgbGVuZ3Rocy4NCg0KIyMjIyA0KVBldGFsIFdpZHRoOiANCg0KYGBge3IsIGVjaG89RkFMU0V9DQpnZ3Bsb3QoaXJpcywgYWVzKHkgPSBwZXRhbC53aWR0aCwgeCA9IHZhcmlldHksIGZpbGwgPSB2YXJpZXR5KSkgKw0KICBnZW9tX2JveHBsb3QoKSArIA0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KVGhlIHBldGFsIHdpZHRoIGV4aGliaXRzIGEgc2lnbmlmaWNhbnQgdmFyaWF0aW9uIGFtb25nIHRoZSB0aHJlZSBzcGVjaWVzIG9mIGlyaXMuIEluIHBhcnRpY3VsYXIsIFNldG9zYSBzdGFuZHMgb3V0IGZvciBoYXZpbmcgdGhlIHNtYWxsZXN0IHBldGFsIHdpZHRoLCB3aGlsZSBWZXJnaW5pY2Egc2hvd3MgdGhlIGhpZ2hlc3QgZGVncmVlIG9mIGRpdmVyc2l0eSBpbiBwZXRhbCB3aWR0aC4NCg0KIyMjIyA8c3BhbiBzdHlsZT0idGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZSI+X19WaW9saW4gcGxvdDogX188L3NwYW4+DQoNCiMjIyMgMSlTZXBhbCBMZW5ndGg6DQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KZ2dwbG90KGlyaXMsIGFlcyh5ID0gc2VwYWwubGVuZ3RoLCB4ID0gdmFyaWV0eSwgZmlsbCA9IHZhcmlldHkpKSArDQogIGdlb21fdmlvbGluKCkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KVGhlIHRocmVlIHZhcmlldGllcyBvZiBwbGFudHMgLSBTZXRvc2EsIFZlcnNpY29sb3IsIGFuZCBWaXJnaW5pY2EgLSBoYXZlIGRpZmZlcmVudCBzZXBhbCBsZW5ndGhzLiBTZXRvc2EgaGFzIHRoZSBzbWFsbGVzdCBzZXBhbCBsZW5ndGgsIHR5cGljYWxseSBtZWFzdXJpbmcgc2hvcnRlciB0aGFuIHRoZSBvdGhlciB0d28gdmFyaWV0aWVzLiBUaGUgVmVyc2ljb2xvciB2YXJpZXR5IGhhcyBhIG1vZGVyYXRlIHNlcGFsIGxlbmd0aCwgcmFuZ2luZyBmcm9tIDUuNSB0byA2LjUgY20uIE9uIHRoZSBvdGhlciBoYW5kLCB0aGUgVmlyZ2luaWNhIHZhcmlldHkgdXN1YWxseSBoYXMgdGhlIGxvbmdlc3Qgc2VwYWwgbGVuZ3RoLCBleGNlcHQgZm9yIG9uZSBvYnNlcnZhdGlvbiB3aGVyZSBpdCBkZXZpYXRlcyBmcm9tIHRoZSBub3JtLiANCg0KIyMjIyAyKVNlcGFsIFdpZHRoOg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmdncGxvdChpcmlzLCBhZXMoeSA9IHNlcGFsLndpZHRoLCB4ID0gdmFyaWV0eSwgZmlsbCA9IHZhcmlldHkpKSArDQogIGdlb21fdmlvbGluKCkgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KQW1vbmcgdGhlIHRocmVlIHNwZWNpZXMsIFNldG9zYSBzdGFuZHMgb3V0IHdpdGggaXRzIHJlbWFya2FibGUgd2lkdGguIEl0cyBzZXBhbHMgc3ByZWFkIG91dCBjb25zaWRlcmFibHkgbW9yZSB0aGFuIHRob3NlIG9mIFZlcnNpY29sb3IgYW5kIFZpcmdpbmljYSwgZ2l2aW5nIGl0IGEgZGlzdGluY3RpdmUgYXBwZWFyYW5jZS4gV2hpbGUgVmVyc2ljb2xvciBhbmQgVmlyZ2luaWNhIGRvIG5vdCBleGhpYml0IHRoZSBzYW1lIGRlZ3JlZSBvZiB3aWR0aCBhcyBTZXRvc2EsIHRoZXkgYXJlIHN0aWxsIHF1aXRlIGJyb2FkLCBmb2xsb3dpbmcgY2xvc2VseSBiZWhpbmQgU2V0b3NhIGluIHRlcm1zIG9mIHRoZWlyIHdpZHRoLg0KDQojIyMjIDMpUGV0YWwgTGVuZ3RoOg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmdncGxvdChpcmlzLCBhZXMoeSA9IHBldGFsLmxlbmd0aCwgeCA9IHZhcmlldHksIGZpbGwgPSB2YXJpZXR5KSkgKw0KICBnZW9tX3Zpb2xpbigpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCk91dCBvZiB0aGUgdGhyZWUgc3BlY2llcywgaXQgaXMgd29ydGggbm90aW5nIHRoYXQgdGhlcmUgaXMgYSBkaXN0aW5jdCB2YXJpYXRpb24gaW4gdGhlIGxlbmd0aCBvZiB0aGVpciBwZXRhbHMuIEluIHBhcnRpY3VsYXIsIFNldG9zYSBzcGVjaWVzIHN0YW5kcyBvdXQgd2l0aCBpdHMgcmVtYXJrYWJseSBzbWFsbCBwZXRhbHMsIHdoaWNoIGFyZSBzaWduaWZpY2FudGx5IHNob3J0ZXIgdGhhbiB0aG9zZSBvZiB0aGUgb3RoZXIgdHdvIHNwZWNpZXMuDQoNCiMjIyMgNClQZXRhbCBXaWR0aDoNCg0KYGBge3IsIGVjaG89RkFMU0V9DQpnZ3Bsb3QoaXJpcywgYWVzKHkgPSBwZXRhbC53aWR0aCwgeCA9IHZhcmlldHksIGZpbGwgPSB2YXJpZXR5KSkgKw0KICBnZW9tX3Zpb2xpbigpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCkFtb25nIHRoZSB0aHJlZSBzcGVjaWVzIG9mIGlyaXMsIHRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgdmFyaWF0aW9uIGluIHBldGFsIHdpZHRoLiBTZXRvc2EgaGFzIHRoZSBzbWFsbGVzdCBwZXRhbCB3aWR0aCwgd2hpbGUgVmVyZ2luaWNhIGV4aGliaXRzIHRoZSBoaWdoZXN0IGRlZ3JlZSBvZiBkaXZlcnNpdHkgaW4gcGV0YWwgd2lkdGguIA0KDQojIFBhcnQtMg0KDQpUaGUgcGxvdHMgd2UgaGF2ZSBiZWVuIHVzaW5nIGZvciBkYXRhIHZpc3VhbGl6YXRpb24gaGF2ZSBiZWVuIGhlbHBmdWwgc28gZmFyLiBUaGV5IGhhdmUgaGVscGVkIHVzIHVuZGVyc3RhbmQgdGhlIGRhdGEgYmV0dGVyIHRoYW4gYmVmb3JlLiBIb3dldmVyLCB0byBkZWx2ZSBkZWVwZXIgaW50byB0aGUgZGF0YXNldCwgd2UgbmVlZCB0byBpbnRlcmFjdCB3aXRoIHRoZSBkYXRhLiBUaGVyZWZvcmUsIGxldCB1cyBleHBsb3JlIHNvbWUgaW50ZXJhY3RpdmUgcGxvdHMuDQoNCg0KIyMjIDxzcGFuIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lIj5JbnRlcmFjdGl2ZSBwbG90czogPC9zcGFuPg0KDQpUaGlzIGRhdGFzZXQgY29udGFpbnMgNCBmZWF0dXJlczogU2VwYWwgbGVuZ3RoLCBTZXBhbCBXaWR0aCwgUGV0YWwgTGVuZ3RoLCBhbmQgUGV0YWwgV2lkdGguIFRvIGRpc3BsYXkgdGhlIGRhdGEsIHdlIHdpbGwgdXNlIHR3byB0eXBlcyBvZiBpbnRlcmFjdGl2ZSBwbG90czogdmlvbGluIHBsb3RzIGFuZCBib3ggcGxvdHMuIFdlIHdpbGwgYmVnaW4gYnkgZGlzcGxheWluZyB0aGUgU2VwYWwgbGVuZ3RoIGFuZCB0aGUgU2VwYWwgV2lkdGggdXNpbmcgdGhlIGludGVyYWN0aXZlIHZpb2xpbiBwbG90cywgZm9sbG93ZWQgYnkgdGhlIGRpc3BsYXkgb2YgdGhlIFBldGFsIGxlbmd0aCBhbmQgdGhlIFBldGFsIFdpZHRoIHVzaW5nIHRoZSBpbnRlcmFjdGl2ZSBCb3ggcGxvdC4NCg0KIyMjIyA8c3BhbiBzdHlsZT0idGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZSI+X19JbnRlcmFjdGl2ZSBWaW9saW4gcGxvdDogX188L3NwYW4+DQoNCiMjIyMgMSlTZXBhbCBMZW5ndGg6DQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KcGxvdF9seShkYXRhID0gaXJpcywNCiAgICAgICAgeT0gfnNlcGFsLmxlbmd0aCwNCiAgICAgICAgc3BsaXQgPSB+dmFyaWV0eSwNCiAgICAgICAgdHlwZT0idmlvbGluIiwNCiAgICAgICAgeCA9IH52YXJpZXR5KSANCiAgDQpgYGANCg0KIyMjIyAxKVNlcGFsIFdpZHRoOg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnBsb3RfbHkoZGF0YSA9IGlyaXMsDQogICAgICAgIHk9IH5zZXBhbC53aWR0aCwNCiAgICAgICAgc3BsaXQgPSB+dmFyaWV0eSwNCiAgICAgICAgdHlwZT0idmlvbGluIiwNCiAgICAgICAgeCA9IH52YXJpZXR5KSANCiAgDQpgYGANCg0KIyMjIyA8c3BhbiBzdHlsZT0idGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZSI+X19JbnRlcmFjdGl2ZSBCb3ggcGxvdDogX188L3NwYW4+DQoNCiMjIyMgMSlQZXRhbCBMZW5ndGg6DQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KcGxvdF9seShkYXRhID0gaXJpcywNCiAgICAgICAgeSA9IH5wZXRhbC5sZW5ndGgsDQogICAgICAgIHNwbGl0ID0gfnZhcmlldHksDQogICAgICAgIHg9IH52YXJpZXR5LA0KICAgICAgICB0eXBlID0gJ2JveCcpDQpgYGANCg0KIyMjIyAxKVBldGFsIFdpZHRoOg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCnBsb3RfbHkoZGF0YSA9IGlyaXMsDQogICAgICAgIHkgPSB+cGV0YWwud2lkdGgsDQogICAgICAgIHNwbGl0ID0gfnZhcmlldHksDQogICAgICAgIHg9IH52YXJpZXR5LA0KICAgICAgICB0eXBlID0gJ2JveCcpDQpgYGANCg0KDQoNCg0KIyMjIDxzcGFuIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lIj5Db3JyZWxhdGlvbjogPC9zcGFuPg0KDQojIyMjIDEpQ2FsY3VsYXRpbmcgdGhlIGNvcnJlbGF0aW9uIG1hdHJpeDoNCg0KYGBge3IsIGVjaG89RkFMU0V9DQpjb3JfbWF0ID0gY29yKGlyaXNbLCBjKDE6NCldKQ0KY29yX21hdA0KYGBgDQpUaGUgY29ycmVsYXRpb24gbWF0cml4IHNob3dzIHRoYXQgdGhlcmUgYXJlIHN0cm9uZyBwb3NpdGl2ZSBjb3JyZWxhdGlvbnMgYmV0d2VlbiBzZXBhbCBsZW5ndGggb24gb25lIGhhbmQsIGFuZCBib3RoIHBldGFsIGxlbmd0aCAoMC44NykgYW5kIHBldGFsIHdpZHRoICgwLjgyKSBvbiB0aGUgb3RoZXIuIFRoZXJlIGlzIGFsc28gYSBzdHJvbmcgcG9zaXRpdmUgY29ycmVsYXRpb24gYmV0d2VlbiBwZXRhbCBsZW5ndGggYW5kIHdpZHRoICgwLjk2KS4gVGhlc2UgcmVzdWx0cyBzdWdnZXN0IHRoYXQgdGhlcmUgbWF5IGJlIGxpbmVhciByZWxhdGlvbnNoaXBzIGJldHdlZW4gdGhlc2UgYXR0cmlidXRlcywgYXMgdGhleSB0ZW5kIHRvIGluY3JlYXNlIHRvZ2V0aGVyLiBPbiB0aGUgb3RoZXIgaGFuZCwgdGhlcmUgaXMgYSB3ZWFrIG5lZ2F0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gc2VwYWwgbGVuZ3RoIGFuZCB3aWR0aCAoLTAuMTIpLiBUaGlzIGluZGljYXRlcyB0aGF0IHNlcGFsIHdpZHRoIG1heSBzbGlnaHRseSBkZWNyZWFzZSBhcyBzZXBhbCBsZW5ndGggaW5jcmVhc2VzLCBidXQgdGhpcyByZWxhdGlvbnNoaXAgaXMgbm90IHZlcnkgc3Ryb25nLi4NCg0KDQojIyMjIDEpQ29ycmVsYXRpb24gbWF0dHJpeCBwbG90Og0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KZ2djb3JycGxvdChjb3JfbWF0LCANCiAgICAgICAgICAgdHlwZSA9ICdsb3dlcicsDQogICAgICAgICAgIGxhYiA9IFRSVUUpDQpgYGANCg0KIyMjIDxzcGFuIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lIj5QYWlyIHBsb3Q6IDwvc3Bhbj4NCg0KYGBge3IsIGVjaG89RkFMU0V9DQpnZ3BhaXJzKGlyaXMsIGFlcyhjb2xvciA9IHZhcmlldHkpKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCiMjIyA8c3BhbiBzdHlsZT0idGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZSI+UHJpbmNpcGFsIENvbXBvbmVudCBBbmFseXNpcyhQQ0EpOiA8L3NwYW4+DQoNCg0KDQpMZXQncyBzdGFydCBieSBhc3Nlc3Npbmcgd2hhdCB3ZSBoYXZlIGF0IG91ciBkaXNwb3NhbC4NCg0KYGBge3IsIGVjaG89RkFMU0V9DQppcmlzX3BjYSA9IHByY29tcChpcmlzWzE6NF0sIGNlbnRlciA9IFRSVUUsIHNjYWxlID0gVFJVRSkNCmlyaXNfcGNhDQpgYGANCkxldCdzIHN1bW1lcmlzZSB0aGUgbnVtYmVycywNCg0KYGBge3IsIGVjaG89RkFMU0V9DQpzdW1tYXJ5KGlyaXNfcGNhKQ0KYGBgDQpXaGVuIGludGVycHJldGluZyB0aGUgcHJvcG9ydGlvbiBvZiB2YXJpYW5jZSwgaXQgaXMgaW1wb3J0YW50IHRvIGRldGVybWluZSB3aGljaCBjb21wb25lbnRzIGhvbGQgdGhlIG1vc3QgaW5mb3JtYXRpb24gYW5kIHdoYXQgcGVyY2VudGFnZSBvZiB0aGUgb3JpZ2luYWwgZGF0YSdzIHZhcmlhYmlsaXR5IHRoZXkgY2FwdHVyZS4gSW4gdGhpcyBhbmFseXNpcywgQ29tcG9uZW50cyAxIGFuZCAyIHRvZ2V0aGVyIGV4cGxhaW4gYWxtb3N0IDk1LjgxJSBvZiB0aGUgdmFyaWFuY2UsIGluZGljYXRpbmcgdGhhdCB0aGV5IGNhcHR1cmUgYSBsYXJnZSBwb3J0aW9uIG9mIHRoZSBpbmZvcm1hdGlvbiBmcm9tIHRoZSBvcmlnaW5hbCB2YXJpYWJsZXMuIENvbXBvbmVudCAxIGFsb25lIGFjY291bnRzIGZvciA3Mi45NiUgb2YgdGhlIHRvdGFsIHZhcmlhbmNlLCB3aGlsZSBDb21wb25lbnQgMiBjb250cmlidXRlcyBhbiBhZGRpdGlvbmFsIDIyLjg1JS4gVGhlc2UgcmVzdWx0cyBzdWdnZXN0IHRoYXQgdGhlIGZpcnN0IHR3byBjb21wb25lbnRzIGFyZSBoaWdobHkgaW5mb3JtYXRpdmUgYW5kIGNhcHR1cmUgdGhlIG1ham9yaXR5IG9mIHRoZSB2YXJpYWJpbGl0eSBwcmVzZW50IGluIHRoZSBkYXRhc2V0LiBPbiB0aGUgb3RoZXIgaGFuZCwgc3Vic2VxdWVudCBjb21wb25lbnRzIHN1Y2ggYXMgQ29tcG9uZW50cyAzIGFuZCA0IGV4cGxhaW4gbXVjaCBzbWFsbGVyIHByb3BvcnRpb25zIG9mIHZhcmlhbmNlICgzLjY2OSUgYW5kIDAuNTE4JSByZXNwZWN0aXZlbHkpLCBpbmRpY2F0aW5nIHRoYXQgdGhlaXIgY29udHJpYnV0aW9ucyB0byB0aGUgb3ZlcmFsbCB2YXJpYWJpbGl0eSBvZiB0aGUgZGF0YSBhcmUgc2lnbmlmaWNhbnRseSBsb3dlci4NCg0KIyMjIyAxKUJhciBwbG90IG9mIFBDQXM6DQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KZnZpel9laWcoaXJpc19wY2EsDQogICAgICAgICBhZGRsYWJlbHMgPSBUUlVFLA0KICAgICAgICAgeWxpbSA9IGMoMCwgODApLA0KICAgICAgICAgbWFpbj0iQmFyIHBsb3Qgb2YgUENBcyIpDQpgYGANClRoZSBzY3JlZSBwbG90IGZvciB0aGUgcHJpbmNpcGFsIGNvbXBvbmVudCBhbmFseXNpcyAoUENBKSBpbmRpY2F0ZXMgYSBzaWduaWZpY2FudCBkcm9wIGluIHZhcmlhbmNlIGZyb20gNzMlIHRvIDIyLjklIGluIHRoZSBmaXJzdCB0d28gY29tcG9uZW50cywgd2l0aCB0aGUgcmVtYWluaW5nIHR3byBjb21wb25lbnRzIGNvbnRyaWJ1dGluZyB2ZXJ5IGxpdHRsZS4gVGhpcyBzdWdnZXN0cyB0aGF0IHRoZSBmaXJzdCB0d28gY29tcG9uZW50cyBhY2NvdW50IGZvciB0aGUgbWFqb3JpdHkgb2YgdGhlIHNpZ25pZmljYW50IHZhcmlhbmNlIGluIHRoZSBkYXRhLg0KDQoNCiMjIyMgMikgQ29udHJpYnV0aW9uIHBsb3QgZm9yIFBDczoNCg0KYGBge3IsIGVjaG89RkFMU0V9DQpmdml6X3BjYV92YXIoaXJpc19wY2EsIGNvbC52YXIgPSAiY29udHJpYiIsDQogICAgICAgICAgICAgZ3JhZGllbnQuY29scyA9IGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpDQpgYGANCg0KIyMjIyAyKSBDbHVzdGVyIHBsb3QgYWZ0ZXIgUENBOg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmZ2aXpfcGNhX2luZChpcmlzX3BjYSwgY29sLmluZCA9IGlyaXMkdmFyaWV0eSwgYWRkRWxsaXBzZXMgPSBUUlVFLCBnZW9tLmluZCA9ICJwb2ludCIpDQpgYGANCg0KIyMjIDxzcGFuIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lIj5TVk0gbW9kZWw6IDwvc3Bhbj4NCg0KDQojIyMjIDIpU1ZNIG1vZGVsOg0KDQpXZSB3aWxsIG5vdyBjcmVhdGUgYSBtYWNoaW5lIGxlYXJuaW5nIG1vZGVsIHRvIHByZWRpY3QgaXJpcyB2YXJpZXR5IGJhc2VkIG9uIHBldGFsIGFuZCBzZXBhbCBtZWFzdXJlbWVudHMuDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KdHJhaW5faWR4ID0gY3JlYXRlRGF0YVBhcnRpdGlvbihpcmlzJHZhcmlldHksIHA9MC44LCBsaXN0ID0gRkFMU0UpDQp0cmFpbl9kYXRhID0gaXJpc1t0cmFpbl9pZHgsIF0NCnRlc3RfZGF0YSA9IGlyaXNbLXRyYWluX2lkeCwgXQ0KDQpgYGANCg0KYGBge3J9DQp0cmFpbl9kYXRhDQpgYGANCg0KDQpgYGB7cn0NCnRlc3RfZGF0YQ0KYGBgDQoNCg0KYGBge3IsIGVjaG89RkFMU0V9DQpzdm1fbW9kZWwgPSBzdm0oYXMuZmFjdG9yKHZhcmlldHkpIH4gc2VwYWwubGVuZ3RoK3NlcGFsLndpZHRoK3BldGFsLmxlbmd0aCtwZXRhbC53aWR0aCwgZGF0YSA9IHRyYWluX2RhdGEsIGtlcm5lbCA9ICJsaW5lYXIiKQ0KYGBgDQoNCmBgYHtyfQ0KcHJlZGljdChzdm1fbW9kZWwsIHRlc3RfZGF0YVsxNSwtNV0pDQpgYGANClRoaXMgbWFjaGluZSBsZWFybmluZyBtb2RlbCBoYXMgYmVlbiB0cmFpbmVkIHVzaW5nIHRoZSB0cmFpbl9kYXRhLiBJdHMgcHVycG9zZSBpcyB0byBwcmVkaWN0IHRoZSB2YXJpZXR5IG9mIGEgZmxvd2VyIGJhc2VkIG9uIHRoZSB2YWx1ZXMgb2YgaXRzIGF0dHJpYnV0ZXMuIFdoZW4gd2UgZ2l2ZSBpdCB2YWx1ZXMgZnJvbSB0aGUgdGVzdF9kYXRhIHdpdGhvdXQgdGhlIHRhcmdldCB2YXJpYWJsZSwgaXQgc3VtcyB1cCB0aGUgdmFsdWVzIG9mIGFsbCB0aGUgb3RoZXIgY29sdW1ucyBhbmQgY29tcGFyZXMgdGhlbSB3aXRoIHRoZSBkYXRhIGZyb20gdGhlIHRyYWluX2RhdGEuIEl0IHRoZW4gaWRlbnRpZmllcyB3aGljaCBvZiB0aGUgdGhyZWUgdmFyaWV0aWVzIGhhdmUgc2ltaWxhciBhdHRyaWJ1dGUgdmFsdWVzIHRvIHRoZSBpbnB1dCBhbmQgcmV0dXJucyBpdHMgcHJlZGljdGlvbi4gSW4gdGhpcyBzcGVjaWZpYyBjYXNlLCB0aGUgbW9kZWwgZGV0ZWN0ZWQgdGhhdCB0ZXN0X2RhdGFbMTUsIC01XSBiZWxvbmdzIHRvIHRoZSBWZXJzaWNvbG9yIHZhcmlldHksIHdoaWNoIGlzIGNvcnJlY3QuDQoNCg0KDQojIyMjIDIpQ29uZnVzaW9uIG1hdHJpeDoNCg0KYGBge3IsIGVjaG89RkFMU0V9DQpwcmVkID0gcHJlZGljdChzdm1fbW9kZWwsIG5ld2RhdGEgPSB0ZXN0X2RhdGEpDQoNCmNvbmZfbWF0ID0gY29uZnVzaW9uTWF0cml4KHByZWQsIGFzLmZhY3Rvcih0ZXN0X2RhdGEkdmFyaWV0eSkpDQpjb25mX21hdA0KYGBgDQoNCg0KYGBge3IsIGVjaG89RkFMU0V9DQpwcmVkID0gYXMuZGF0YS5mcmFtZShjb25mX21hdCR0YWJsZSkNCg0KZ2dwbG90KHByZWQsIGFlcyhQcmVkaWN0aW9uLCBSZWZlcmVuY2UsIGZpbGwgPSBGcmVxKSkgKyANCiAgZ2VvbV90aWxlKCkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSkpICsgDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93PSJ3aGl0ZSIsIGhpZ2g9ImJsdWUiKQ0KYGBgDQoNCiMjIyA8c3BhbiBzdHlsZT0idGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZSI+X19VUyBBZG1pc3Npb24gRGF0YXNldF9fPC9zcGFuPg0KDQojIyMjIGEpcmVtb3ZpbmcgU2VyaWFsIE5vIGNvbHVtbjoNCg0KYGBge3IsIGVjaG89RkFMU0V9DQpVU19BZG1pc3Npb24kYFNlcmlhbCBOby5gPC1OVUxMDQoNClVTX0FkbWlzc2lvbg0KYGBgDQoNCiMjIyMgYilQYWlyIHBsb3Q6DQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KZ2dwYWlycyhVU19BZG1pc3Npb24sIGFlcyhjb2xvdXIgPSBSZXNlYXJjaCkpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KIyMjIyBjKUxpbmVhciByZWdyZXNzaW9uOg0KDQojIyMjIyAxKSBHUkUgU2NvcmU6DQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KZ2dwbG90KFVTX0FkbWlzc2lvbiwgYWVzKHggPSBgQ2hhbmNlLm9mLkFkbWl0YCwgeSA9IGBHUkUuU2NvcmVgLCBjb2xvdXIgPSBSZXNlYXJjaCkpICsgDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGxldmVsID0gMC45NSwgY29sb3IgPSAnYmxhY2snKSArDQogIGxhYnModGl0bGUgPSAiUmVncmVzc2lvbiBwbG90IGZvciBjaGFuY2Ugb2YgYWRtaXNzaW9uIGFuZCBHUkUgU2NvcmUiLCB4ID0gIkNoYW5jZSBvZiBhZG1pc3Npb24iLA0KICAgICAgIHkgPSAiR1JFIFNjb3JlIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KIyMjIyMgMikgVE9FRkwgU2NvcmU6DQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KZ2dwbG90KFVTX0FkbWlzc2lvbiwgYWVzKHggPSBgQ2hhbmNlLm9mLkFkbWl0YCwgeSA9IGBUT0VGTC5TY29yZWAsIGNvbG91ciA9IFJlc2VhcmNoKSkgKyANCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgbGV2ZWwgPSAwLjk1LCBjb2xvciA9ICdibGFjaycpICsNCiAgbGFicyh0aXRsZSA9ICJSZWdyZXNzaW9uIHBsb3QgZm9yIGNoYW5jZSBvZiBhZG1pc3Npb24gYW5kIEdSRSBTY29yZSIsIHggPSAiQ2hhbmNlIG9mIGFkbWlzc2lvbiIsDQogICAgICAgeSA9ICJHUkUgU2NvcmUiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KIyMjIyMgMykgVW5pdmVyc2l0eSByYXRpbmc6DQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KZ2dwbG90KFVTX0FkbWlzc2lvbiwgYWVzKHggPSBgQ2hhbmNlLm9mLkFkbWl0YCwgeSA9IGBVbml2ZXJzaXR5LlJhdGluZ2AsIGNvbG91ciA9IFJlc2VhcmNoKSkgKyANCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgbGV2ZWwgPSAwLjk1LCBjb2xvciA9ICdibGFjaycpICsNCiAgbGFicyh0aXRsZSA9ICJSZWdyZXNzaW9uIHBsb3QgZm9yIGNoYW5jZSBvZiBhZG1pc3Npb24gYW5kIEdSRSBTY29yZSIsIHggPSAiQ2hhbmNlIG9mIGFkbWlzc2lvbiIsDQogICAgICAgeSA9ICJHUkUgU2NvcmUiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KIyMjIyMgNCkgU09QOg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmdncGxvdChVU19BZG1pc3Npb24sIGFlcyh4ID0gYENoYW5jZS5vZi5BZG1pdGAsIHkgPSBgU09QYCwgY29sb3VyID0gUmVzZWFyY2gpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBsZXZlbCA9IDAuOTUsIGNvbG9yID0gJ2JsYWNrJykgKw0KICBsYWJzKHRpdGxlID0gIlJlZ3Jlc3Npb24gcGxvdCBmb3IgY2hhbmNlIG9mIGFkbWlzc2lvbiBhbmQgR1JFIFNjb3JlIiwgeCA9ICJDaGFuY2Ugb2YgYWRtaXNzaW9uIiwNCiAgICAgICB5ID0gIkdSRSBTY29yZSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KDQojIyMjIyA1KSBMT1I6DQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KZ2dwbG90KFVTX0FkbWlzc2lvbiwgYWVzKHggPSBgQ2hhbmNlLm9mLkFkbWl0YCwgeSA9IGBMT1JgLCBjb2xvdXIgPSBSZXNlYXJjaCkpICsgDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGxldmVsID0gMC45NSwgY29sb3IgPSAnYmxhY2snKSArDQogIGxhYnModGl0bGUgPSAiUmVncmVzc2lvbiBwbG90IGZvciBjaGFuY2Ugb2YgYWRtaXNzaW9uIGFuZCBHUkUgU2NvcmUiLCB4ID0gIkNoYW5jZSBvZiBhZG1pc3Npb24iLA0KICAgICAgIHkgPSAiR1JFIFNjb3JlIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQoNCiMjIyMjIDYpIENHUEE6DQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KZ2dwbG90KFVTX0FkbWlzc2lvbiwgYWVzKHggPSBgQ2hhbmNlLm9mLkFkbWl0YCwgeSA9IGBDR1BBYCwgY29sb3VyID0gUmVzZWFyY2gpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBsZXZlbCA9IDAuOTUsIGNvbG9yID0gJ2JsYWNrJykgKw0KICBsYWJzKHRpdGxlID0gIlJlZ3Jlc3Npb24gcGxvdCBmb3IgY2hhbmNlIG9mIGFkbWlzc2lvbiBhbmQgR1JFIFNjb3JlIiwgeCA9ICJDaGFuY2Ugb2YgYWRtaXNzaW9uIiwNCiAgICAgICB5ID0gIkdSRSBTY29yZSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KDQojIyMjIyA3KSBSZXNlYXJjaDoNCg0KYGBge3IsIGVjaG89RkFMU0V9DQpnZ3Bsb3QoVVNfQWRtaXNzaW9uLCBhZXMoeCA9IGBDaGFuY2Uub2YuQWRtaXRgLCB5ID0gYFJlc2VhcmNoYCwgY29sb3VyID0gUmVzZWFyY2gpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBsZXZlbCA9IDAuOTUsIGNvbG9yID0gJ2JsYWNrJykgKw0KICBsYWJzKHRpdGxlID0gIlJlZ3Jlc3Npb24gcGxvdCBmb3IgY2hhbmNlIG9mIGFkbWlzc2lvbiBhbmQgR1JFIFNjb3JlIiwgeCA9ICJDaGFuY2Ugb2YgYWRtaXNzaW9uIiwNCiAgICAgICB5ID0gIkdSRSBTY29yZSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANClRoZSBwbG90cyBzaG93IGEgYmluYXJ5IGRlcGVuZGVudCB2YXJpYWJsZSwgbWFraW5nIGxpbmVhciByZWdyZXNzaW9uIHVuc3VpdGFibGUuIEluc3RlYWQsIGxvZ2lzdGljIHJlZ3Jlc3Npb24gY2FuIGVzdGltYXRlIHByb2JhYmlsaXRpZXMuIEFsbCBmYWN0b3JzIGV4YW1pbmVkIGZvciB1bml2ZXJzaXR5IGFkbWlzc2lvbiBkaXNwbGF5IGEgcG9zaXRpdmUgYXNzb2NpYXRpb24uIEluY3JlYXNpbmcgdGhlc2UgZmFjdG9ycyBpbmNyZWFzZXMgdGhlIHByb2JhYmlsaXR5IG9mIGFkbWlzc2lvbi4NCg0KIyMjIyBkKVBvbHlub21pYWwgcmVncmVzc2lvbjoNCg0KIyMjIyMgMSkgR1JFIFNjb3JlOg0KYGBge3IsIGVjaG89RkFMU0V9DQpnZ3Bsb3QoVVNfQWRtaXNzaW9uLCBhZXMoeCA9IENoYW5jZS5vZi5BZG1pdCwgeT0gR1JFLlNjb3JlLCBjb2xvdXIgPSBSZXNlYXJjaCkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgZm9ybXVsYT0geX5wb2x5KHgsMiksIHNlID0gVFJVRSwgY29sb3IgPSAnYmxhY2snLCBsZXZlbD0wLjk1KSArDQogIGxhYnModGl0bGUgPSAiUG9seW5vbWlhbCByZWdyZXNzaW9uIHBsb3QgZm9yIGNoYW5jZSBvZiBhZG1pc3Npb24gYW5kIEdSRSBTY29yZSIsIHggPSAiQ2hhbmNlIG9mIGFkbWlzc2lvbiIsDQogICAgICAgeSA9ICJHUkUgU2NvcmUiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KDQoNCiMjIyMjIDIpIFRPRUZMIFNjb3JlOg0KYGBge3IsIGVjaG89RkFMU0V9DQpnZ3Bsb3QoVVNfQWRtaXNzaW9uLCBhZXMoeCA9IENoYW5jZS5vZi5BZG1pdCwgeT0gVE9FRkwuU2NvcmUsIGNvbG91ciA9IFJlc2VhcmNoKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhPSB5fnBvbHkoeCwyKSwgc2UgPSBUUlVFLCBjb2xvciA9ICdibGFjaycsIGxldmVsPTAuOTUpICsNCiAgbGFicyh0aXRsZSA9ICJQb2x5bm9taWFsIHJlZ3Jlc3Npb24gcGxvdCBmb3IgY2hhbmNlIG9mIGFkbWlzc2lvbiBhbmQgVE9FRkwgU2NvcmUiLCB4ID0gIkNoYW5jZSBvZiBhZG1pc3Npb24iLA0KICAgICAgIHkgPSAiR1JFIFNjb3JlIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCg0KIyMjIyMgMykgVW5pdmVyc2l0eSByYXRpbmc6DQpgYGB7ciwgZWNobz1GQUxTRX0NCmdncGxvdChVU19BZG1pc3Npb24sIGFlcyh4ID0gQ2hhbmNlLm9mLkFkbWl0LCB5PSBVbml2ZXJzaXR5LlJhdGluZywgY29sb3VyID0gUmVzZWFyY2gpKSArDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGE9IHl+cG9seSh4LDIpLCBzZSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJywgbGV2ZWw9MC45NSkgKw0KICBsYWJzKHRpdGxlID0gIlBvbHlub21pYWwgcmVncmVzc2lvbiBwbG90IGZvciBjaGFuY2Ugb2YgYWRtaXNzaW9uIGFuZCBVbml2ZXJzaXR5IHJhdGluZyIsIHggPSAiQ2hhbmNlIG9mIGFkbWlzc2lvbiIsDQogICAgICAgeSA9ICJHUkUgU2NvcmUiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KDQojIyMjIyA0KSBTT1A6DQpgYGB7ciwgZWNobz1GQUxTRX0NCmdncGxvdChVU19BZG1pc3Npb24sIGFlcyh4ID0gQ2hhbmNlLm9mLkFkbWl0LCB5PSBTT1AsIGNvbG91ciA9IFJlc2VhcmNoKSkgKyAgDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGE9IHl+cG9seSh4LDIpLCBzZSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJywgbGV2ZWw9MC45NSkgKw0KICBsYWJzKHRpdGxlID0gIlBvbHlub21pYWwgcmVncmVzc2lvbiBwbG90IGZvciBjaGFuY2Ugb2YgYWRtaXNzaW9uIGFuZCBTT1AiLCB4ID0gIkNoYW5jZSBvZiBhZG1pc3Npb24iLA0KICAgICAgIHkgPSAiR1JFIFNjb3JlIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCg0KIyMjIyMgNSkgTE9SOg0KYGBge3IsIGVjaG89RkFMU0V9DQpnZ3Bsb3QoVVNfQWRtaXNzaW9uLCBhZXMoeCA9IENoYW5jZS5vZi5BZG1pdCwgeT0gTE9SLCBjb2xvdXIgPSBSZXNlYXJjaCkpICsgIA0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhPSB5fnBvbHkoeCwyKSwgc2UgPSBUUlVFLCBjb2xvciA9ICdibGFjaycsIGxldmVsPTAuOTUpICsNCiAgbGFicyh0aXRsZSA9ICJQb2x5bm9taWFsIHJlZ3Jlc3Npb24gcGxvdCBmb3IgY2hhbmNlIG9mIGFkbWlzc2lvbiBhbmQgTE9SIiwgeCA9ICJDaGFuY2Ugb2YgYWRtaXNzaW9uIiwNCiAgICAgICB5ID0gIkdSRSBTY29yZSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQoNCiMjIyMjIDYpIENHUEE6DQpgYGB7ciwgZWNobz1GQUxTRX0NCmdncGxvdChVU19BZG1pc3Npb24sIGFlcyh4ID0gQ2hhbmNlLm9mLkFkbWl0LCB5PSBDR1BBLCBjb2xvdXIgPSBSZXNlYXJjaCkpICsgIA0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhPSB5fnBvbHkoeCwyKSwgc2UgPSBUUlVFLCBjb2xvciA9ICdibGFjaycsIGxldmVsPTAuOTUpICsNCiAgbGFicyh0aXRsZSA9ICJQb2x5bm9taWFsIHJlZ3Jlc3Npb24gcGxvdCBmb3IgY2hhbmNlIG9mIGFkbWlzc2lvbiBhbmQgQ0dQQSIsIHggPSAiQ2hhbmNlIG9mIGFkbWlzc2lvbiIsDQogICAgICAgeSA9ICJHUkUgU2NvcmUiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KDQojIyMjIyA3KSBSZXNlYXJjaDoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KZ2dwbG90KFVTX0FkbWlzc2lvbiwgYWVzKHggPSBDaGFuY2Uub2YuQWRtaXQsIHk9IFJlc2VhcmNoLCBjb2xvdXIgPSBSZXNlYXJjaCkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgZm9ybXVsYT0geX5wb2x5KHgsMiksIHNlID0gVFJVRSwgY29sb3IgPSAnYmxhY2snLCBsZXZlbD0wLjk1KSArDQogIGxhYnModGl0bGUgPSAiUG9seW5vbWlhbCByZWdyZXNzaW9uIHBsb3QgZm9yIGNoYW5jZSBvZiBhZG1pc3Npb24gYW5kIFJlc2VhcmNoIiwgeCA9ICJDaGFuY2Ugb2YgYWRtaXNzaW9uIiwNCiAgICAgICB5ID0gIkdSRSBTY29yZSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KVGhlIHBsb3R0ZWQgcG9seW5vbWlhbCBncmFwaHMgYWJvdmUgcHJvdmlkZSBhIGNsZWFyIGFuZCBhY2N1cmF0ZSByZXByZXNlbnRhdGlvbiB0aGF0IGluZGljYXRlcyBhIHBvc2l0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gR1JFIGFuZCBUT0VGTCBzY29yZXMsIHN0cm9uZyByZWNvbW1lbmRhdGlvbiBsZXR0ZXJzLCBoaWdoIENHUEEsIGFuZCByZXNlYXJjaCBleHBlcmllbmNlIHdpdGggaW5jcmVhc2VkIGFkbWlzc2lvbiBjaGFuY2VzIHRvIFVTIHVuaXZlcnNpdGllcy4gVGhlc2UgZmluZGluZ3MgZW1waGFzaXplIHRoZSBpbXBvcnRhbmNlIG9mIGFjYWRlbWljIHBlcmZvcm1hbmNlLCBsYW5ndWFnZSBwcm9maWNpZW5jeSwgc3Ryb25nIGVuZG9yc2VtZW50cywgY29uc2lzdGVudCBncmFkZXMsIGFuZCByZXNlYXJjaCBlbmdhZ2VtZW50IGluIHNlY3VyaW5nIGFkbWlzc2lvbi4NCg0KIyMjIDxzcGFuIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lIj5fX0NvbmNsc2lvbl9fPC9zcGFuPg0KDQpUbyBzdW0gdXAsIG91ciBkYXRhIHNjaWVuY2UgcHJvamVjdCBoYXMgYmVlbiBhIHN1Y2Nlc3MgdGhhbmtzIHRvIHRoZSBpbnNpZ2h0cyB3ZSBnYWluZWQgZnJvbSBhbmFseXppbmcgdGhlIElyaXMgZmxvd2VyIGRhdGFzZXQuIFdlIHdlcmUgYWJsZSB0byBkZXZlbG9wIGFuIGFjY3VyYXRlIG1hY2hpbmUgbGVhcm5pbmcgbW9kZWwgdGhhdCBjYW4gcHJlZGljdCB0aGUgc3BlY2llcyBvZiBpcmlzIGJhc2VkIG9uIHNlcGFsIGFuZCBwZXRhbCBtZWFzdXJlbWVudHMuIFRoaXMgcHJvamVjdCBoYXMgZGVtb25zdHJhdGVkIHRoZSBwb3dlciBvZiBkYXRhIGFuYWx5c2lzIGFuZCBtYWNoaW5lIGxlYXJuaW5nIGFuZCBob3cgaXQgY2FuIGJlIGFwcGxpZWQgdG8gc29sdmUgcmVhbC13b3JsZCBwcm9ibGVtcy4gDQoNCiMjIyA8c3BhbiBzdHlsZT0idGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZSI+X19SZWZlcmVuY2VfXzwvc3Bhbj4NCg0KMS5FeHBsb3JpbmcgdGhlIElyaXMgZmxvd2VyIGRhdGFzZXQsIEVtaW5lIEJvemt1cywgTWVkaXVtIC0gZW1pbmVib3prdXMubWVkaXVtLmNvbS9leHBsb3JpbmctdGhlLWlyaXMtZmxvd2VyLWRhdGFzZXQtNGUwMDBiY2MyNjZjDQoNCjIuIERhdGEgU2NpZW5jZSBFeGFtcGxlIC0gSXJpcyBkYXRhc2V0LCBsYWMuaW5wZSAtIGh0dHA6Ly93d3cubGFjLmlucGUuYnIvfnJhZmFlbC5zYW50b3MvRG9jcy9DQVAzOTQvV2hvbGVTdG9yeS1JcmlzLmh0bWwNCg0KMy5JcmlzIGZsb3dlciBkYXRhIHNldCwgd2lraXBlZGlhIC0gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSXJpc19mbG93ZXJfZGF0YV9zZXQNCg0KNC5FeHBsb3JlIGRpYWJldGVzLXJlbGF0ZWQgZmFjdG9ycyBhbmQgcHJlZGljdGl2ZSBtb2RlbGluZyBvZiBhZG1pdHRhbmNlIGludG8gYSBtYXN0ZXJzIGdyYWR1YXRlIHByb2dyYW0gYXQgdGhlIFVuaXRlZCBTdGF0ZXMgVW5pdmVyc2l0eTogTWFjaGluZSBsZWFybmluZyBhcHByb2FjaGVzLCBOYXNpZiBIb3NzYWluLCBEZXBhcnRtZW50IG9mIEdsb2JhbCBIZWFsdGggUG9saWN5LCBHcmFkdWF0ZSBTY2hvb2wgb2YgTWVkaWNpbmUsIFRoZSBVbml2ZXJzaXR5IG9mIFRva3lvIC0gaHR0cHM6Ly9ycHVicy5jb20vTmFzaWYvMTEzNjUyNQ==