1 Introduction

Feature selection is a critical and widely used technique in data processing, aimed at selecting the most relevant features from noisy data. This approach not only enhances the execution speed of data processing algorithms but also improves prediction accuracy and reduces variability in results.

2 Feature Selection Methods

Feature selection, a dimensionality reduction technique, focuses on identifying a small subset of relevant features from the original dataset by eliminating irrelevant, redundant, or noisy features. This process typically enhances learning performance, improves model accuracy, reduces computational costs, and increases model interpretability.

Several statistical methods relevant to feature selection have been discussed in various statistics courses. This section provides an overview of feature selection types, methodologies, and techniques commonly employed in both statistics and machine learning. Based on their nature, these methods are categorized into four distinct types, which will be outlined in the following subsections.

2.1 Filter Methods

Filter methods are statistical-based feature selection methods that involve evaluating the relationship between each input variable and the target (response) variable using statistics and selecting those input variables that have the strongest relationship with the target variable. These methods can be fast and effective, although the choice of statistical measures depends on the data type of both the input and output variables. Here are some of these methods with brief descriptions.

2.1.1 Information Gain

Information gain calculates the reduction in entropy from the transformation of a data set. It can be used for feature selection by evaluating the Information gain of each variable in the context of the target variable. We have briefly described this method in decision induction.

2.1.2 Chi-square Test

Let’s consider a scenario where we need to determine the relationship between the independent category feature (predictor) and dependent category feature(response). In feature selection, we aim to select the features which are highly dependent on the response. We calculate Chi-square between each feature and the response variable. and select the desired number of features with the best Chi-square scores.

In order to correctly apply the chi-squared test for the relationship between various features in the data set and the target variable, the following conditions have to be met: the variables have to be categorical, sampled independently and values should have an expected frequency greater than 5.

2.1.3 Fisher’s Score

Fisher score is one of the most widely used supervised feature selection methods. It seeks features with the best discriminant ability. It is based on maximizing the distances between data points of different classes and minimizing the distances among points of the same class. To rank the features in the order of their relevancy, they are sorted in the decreasing order of their obtained fisher score. Thus, as the value of an assigned score to a feature increases, its importance also increases.

Let \(Y\) be the categorical variable with \(C\) categories and \(X\) be a numerical variable. The Fisher’s score of \(X\) is defined by

\[ F_X = \frac{\sum_{i=1}^C N_i(\mu_{X}^i-\mu_{X})^2}{\sum_{i=1}^CN_i\times (\sigma_X^i)^2} \] where \(N_i\) is the number of data points in class \(i\), \(\mu_X\) is the mean of feature variable \(X\), and \(\mu_X^i\) and \((\sigma_X^i)^2\) are the mean and the variance of class \(i\) upon the feature \(X\) respectively.

The algorithm returns the ranks of the variables based on the fisher’s score in descending order. We can then select the variables based on the scores.

2.1.4 Correlation Coefficient

Correlation is a measure of the linear relationship of 2 or more variables. Through correlation, we can predict one variable from the other. The logic behind using correlation for feature selection is that the good variables are highly correlated with the response. Furthermore, variables should be correlated with the response but should be uncorrelated among themselves. This method is valid when both response and feature variables are numeric.

2.1.5 Variance Threshold

The variance threshold is a simple baseline approach to feature selection. It removes all features which variance does not meet some threshold. The logic for this method is that features with a higher variance may contain more useful information.

2.2 Wrapper Methods

Wrappers require some method to search the space of all possible subsets of features, assessing their quality by learning and evaluating a classifier with that feature subset. The feature selection process is based on a specific machine learning algorithm that we are trying to fit on a given data set. It follows a greedy search approach by evaluating all the possible combinations of features against the evaluation criterion. The wrapper methods usually result in better predictive accuracy than filter methods.

The following are a few such methods.

2.2.1 Forward Feature Selection

This is an iterative method we start with the best performing variable against the target. Next, we select another variable that gives the best performance in combination with the first selected variable. This process continues until the preset criterion is achieved.

2.2.2 Backward Feature Elimination

This method works exactly opposite to the Forward Feature Selection method. Here, we start with all the features available and build a model. Next, we the variable from the model which gives the best evaluation measure value. This process is continued until the preset criterion is achieved.

2.2.3 Subset Feature Selection

This is the most robust feature selection method covered so far. This is a brute-force evaluation of each feature subset. This means that it tries every possible combination of the variables and returns the best-performing subset.

2.3 Embedded Methods

These methods encompass the benefits of both the wrapper and filter methods, by including interactions of features but also maintaining reasonable computational cost. Embedded methods are iterative in the sense that takes care of each iteration of the model training process and carefully extract those features which contribute the most to the training for a particular iteration.

2.3.1 LASSO Regularization

Regularization consists of adding a penalty to the different parameters of the machine learning model to reduce the freedom of the model, i.e. to avoid over-fitting. In linear model regularization, the penalty is applied over the coefficients that multiply each of the predictors. From the different types of regularization, Lasso or L1 has the property that can shrink some of the coefficients to zero. Therefore, that feature can be removed from the model.

2.3.2 Random Forest Importance

Random Forests is a kind of a Bagging Algorithm that aggregates a specified number of decision trees. The tree-based strategies used by random forests naturally rank by how well they improve the purity of the node, or in other words a decrease in the impurity (Gini impurity) over all trees. Nodes with the greatest decrease in impurity happen at the start of the trees, while notes with the least decrease in impurity occur at the end of trees. Thus, by pruning trees below a particular node, we can create a subset of the most important features.

2.4 Hybrid Methods

Hybrid methods try to exploit the qualities of both approaches, filter, and wrapper, trying to have a good compromise between efficiency (computational effort) and effectiveness (quality in the associated objective task when using the selected features).

To take advantage of the filter and wrapper approaches, hybrid methods, in a filter stage, the features are ranked or selected applying a measure based on intrinsic properties of the data. While, in a wrapper stage, certain feature subsets are evaluated for finding the best one, through a specific clustering algorithm. We can distinguish two types of hybrid methods: methods based on ranking and methods non-based on the ranking of features.

3 Feature Extraction Methods

By finding a smaller set of new variables, each being a combination of the input variables, containing basically the same information as the input variables. In other words, feature extraction is a procedure that defines new variables by aggregating the information from existing features. For example, the new feature variable could be a function of the existing features. The new set of features will have different values as compared to the original feature values.

The main aim is that fewer features will be required to capture the same information.

3.1 Cluster Analysis

cluster analysis, in statistics, set of tools and algorithms that are used to classify different objects into groups in such a way that the similarity between two objects is maximal if they belong to the same group and minimal otherwise. The cluster ID is a new feature that can be used to capture heterogeneous information across clusters.

3.2 Principal Component Analysis (PCA)

We have introduced linear principal component analysis (PCA). The idea is to map the existing feature space to a new space (principal components space).

Technically, a principal component can be defined as a linear combination of optimally-weighted observed variables. The output of PCA is these principal components. The number of PCs to retain is less than or equal to the number of original variables. The PCs possess some useful properties

  • The PCs are essentially the linear combinations of the original variables, the weights vector in this combination is actually the eigenvector found which in turn satisfies the principle of least squares.

  • The PCs are orthogonal, as already discussed.

  • The variation present in the PCs decrease as we move from the 1st PC to the last one, hence the importance.

  • The least important PCs are also sometimes useful in regression, outlier detection, etc.

Figure 1. Illustration of PCA. The least (2nd) important component can be used for anomaly detection.

Figure 1. Illustration of PCA. The least (2nd) important component can be used for anomaly detection.

3.3 Linear Discriminant Analysis (LDA)

Linear discriminant analysis (LDA) also creates linear combinations of your original features. However, unlike PCA, LDA doesn’t maximize explained variance. Instead, it maximizes the separability between classes.

In other words, the goal of an LDA is to project a feature space (a data set n-dimensional samples) onto a smaller subspace k (where $ k n−1$) while maintaining the class-discriminatory information.

In general, dimensionality reduction does not only help reduce computational costs for a given classification task, but it can also be helpful to avoid overfitting by minimizing the error in parameter estimation (“curse of dimensionality”).

Figure 2. Illustration of LDA.

Figure 2. Illustration of LDA.

Therefore, LDA is a supervised method that can only be used with labeled data. The LDA transformation is also dependent on scale, so we should normalize original features in the data set first.

Strengths: LDA is supervised, which can (but doesn’t always) improve the predictive performance of the extracted features. Furthermore, LDA offers variations (i.e. quadratic LDA) to tackle specific roadblocks.

Weaknesses: As with PCA, the new features are not easily interpretable, and we must still manually set or tune the number of components to keep. LDA also requires labeled data.

PCA vs LDA: Which is better? The results will vary from problem to problem. In other words, the No Free Lunch Theorem applies to this situation. The following figure depicts the difference between PCA and LDA.

Figure 3. Illustration of the difference of PCA and LDA.

Figure 3. Illustration of the difference of PCA and LDA.

3.4 Case-study: LDA with Iris Data

like PCA whose mathematical formulation involves matrix algebra (eigenvector and eigenvalues) and linear programming (optimization with linear constraints), in LDA we still need to use the same tools but with different objective functions for optimization. We will not introduce these mathematical steps to find the linear discriminant components.

Next, we use R function lda() in library {MASS} to find LDA components based on the four numerical features in Iris data.

lda() returns several results:

  • The most important result here is the coefficients, they are values that describe the new feature space where the data will be projected in.

  • LDA reduces dimensionality from the original number of features to C — 1 features, where C is the number of classes. In this case, we have 3 classes, therefore the new feature space will have only 2 features.

data(iris)
# Data partition
training_sample <- sample(c(TRUE, FALSE), nrow(iris), replace = T, prob = c(0.6,0.4))
train <- iris[training_sample, ]
test <- iris[!training_sample, ]
#
lda.iris <- lda(Species ~ ., data = train)#, prior = rep(1/3, 3))
kable(lda.iris$scaling, caption="The scaling coefficients of LDA")  # show results
The scaling coefficients of LDA
LD1 LD2
Sepal.Length 0.4396421 0.6655772
Sepal.Width 2.4101169 -2.5575297
Petal.Length -1.9987919 0.3762129
Petal.Width -2.8783565 -2.5642166

The two new feature variables based on the two LDA are explicitly given by

\[ LDA_1 = (0.51\times Sepal.Length) + (1.96\times Sepal.Width) + (-2.12\times Petal.Length) + (-2.98\times Petal.Width) \] \[ LDA_2 = (-0.76\times Sepal.Length) + (2.85\times Sepal.Width) + (-1.05\times Petal.Length) + (1.92\times Petal.Width) \] Next, we use LDA to make a prediction using the hold-out test data. Note that predict() returns three objects with three different pieces of information:

  • lda.test$class contains the predicted labels.
  • lda.test$posterior contains the predictive class probabilities of new data points.
  • lda.test$x contains the two LDA scores.

In the following code, we extract the predicted labels and then compare them with the actual labels to find the confusion matrix and calculate the accuracy of classification LDA.

lda.test <- predict(lda.iris, newdata = test)
test$lda <- lda.test$class  
confusion.matrix = table(test$lda,test$Species)
kable(confusion.matrix, caption = "Confusion matrix based one LDA.")
Confusion matrix based one LDA.
setosa versicolor virginica
setosa 18 0 0
versicolor 0 15 0
virginica 0 1 23

The accuracy of LDA prediction on the test data set is \(49/50 = 98\%\).

3.5 Remarks

We have introduced two well-known feature extraction methods: PCA and LDA. Both are linear extraction methods. PCA is an unsupervised extraction method and LDA is a supervised method. Both methods are developed for different purposes but both can be used for dimensional reduction.

Both PCA and LDA can be adapted for nonlinear feature extraction by introducing kernel functions (i.e., kernel PCA and kernel LDA) or changing the linear combination of the original features into the polynomial expression to capture the nonlinear patterns (i.e., polynomial PCA and polynomial LDA).

The various variable transformations including the well-known Box-Cox transformation, discretization, and redefining categorical variables by combing categories in meaningful ways are all called feature extraction methods.

4 Feature Extraction with Serial Data

The feature extraction methods introduced in the previous section are based on cross-sectional data. There are only very limited discussions on feature extraction based on serial data including time series and panel data. In particular, no feature extraction method based on panel data has been discussed so far in the literature.

In this section, we first introduce the way and type of features one can extract from a time series. Then we introduce a new method for extracting features from panel data. This method can also be used to define a feature based on the regular time series. The new method borrows the idea of the formulation of the process capability index in statistical process and quality control.

4.1 Feature Extraction with Time Series

Time series data is data that is collected at different points in time. This is opposed to cross-sectional data which observes individuals, companies, etc. at a single point in time.

Because data points in time series are collected at adjacent time periods there is potential for correlation between observations. This is one of the features that distinguishes time-series data from cross-sectional data.

Time series data can be found in economics, social sciences, finance, epidemiology, and the physical sciences.

Figure 4. Illustration of times patterns.

Figure 4. Illustration of times patterns.

There are two main goals of time series analysis: identifying the nature of the phenomenon represented by the sequence of observations, and forecasting (predicting future values of the time series variable).

4.1.1 Statistical Models

The most common and effective statistical methods of Forecasting are Simple Moving Average (SMA), Exponential Smoothing (SES), Auto-regressive Integration Moving Average (ARIMA).

We will not discuss these methods in this note but will introduce the exponential smoothing method for the time series next week.

4.1.2 Machine Learning Algorithms

One of the most important properties an algorithm needs in order to be considered a time-series algorithm is the ability to extrapolate patterns outside of the domain of training data. Many machine learning algorithms do not have this capability, as they tend to be restricted to a domain that is defined by training data. Therefore, they are not suited for time series, as the objective of time series is to project into the future.

Another important property of a time series algorithm is the ability to derive confidence intervals. While this is a default property of time series models, most machine learning models do not have this ability because they are not all based on statistical distributions.

There are also machine learning models such as neural network models that can be applied to time series which use lagged predictors and can handle extracted features, such as Neural Networks Autoregression (NNAR). There are even time-series models borrowed from deep learning, specifically in the RNN (Recurrent Neural Network) family. The following figure shows how to use extracted features in a neural network model for forecasting.

Figure 5. How to ANN to model time series.

Figure 5. How to ANN to model time series.

4.1.3 Feature Extraction for Time Series

Since the machine learning method can incorporate both lagged predictors and additional features to improve the forecast accuracy, we can extract some features from the underlying features. The following figure illustrates the process of how to extract features from time-series data.

Figure 6. How to extract features from time series.

Figure 6. How to extract features from time series.

As shown in the above figure, three types of features can be extracted from time-series data.

  • Temporal features (time-domain features) are simple to extract and have an easy physical interpretation.

  • Statistical features are mainly descriptive statistics such as windowed mean, median, skewness, etc.

  • Spectral features (frequency-based features) are obtained by converting the time-based signal into the frequency domain.

These features are descriptive and can be easily automated. Some software programs have been made to extract these types of features automatically in practice.

4.2 Model-based Feature Extraction with Panel Data

This subsection focuses on a new feature extraction method that extracts information based on models and algorithms from sequential data. The algorithm borrows the idea of measuring the process information (such as capability and quality) through the sequence data generated by the process.

Since this is a model-based algorithm, it is more powerful than those features extracted from the time series discussed in the previous subsection.

4.2.1 Concepts Process Capability and Control Chart

Process control is the ability to monitor and adjust a process to give the desired output. It is used in the industry to maintain quality and improve performance. Key tools in process control include control chart, process capability index, etc.

Both control chart and process capability index use the same key characteristics of the underlying process in their construction:

  • Specification limits can be defined as targets that are set for a particular process or a product either by the customer or based on the performance of the market. In other words, it can also be defined as a result that is expected from a particular metric. Specification limits are set by customers or the management.

  • Control limits on the other hand help in indicating the changes which occur in the performance of a particular process. Control limits also provide real-time value. Control limits are dependent on the underlying process.

Control limits can be either upper control limit (UCL) or lower control limit (LCL). Similarly, specification limits can be either upper specification limit (USL) or lower specification limit (LSL).

Figure 7. Structure of a control chart.

Figure 7. Structure of a control chart.

Understanding the control chart

Several concepts will be used in the definition of the process capability index.

Control charts are one of the most popular SPC tools used by manufacturers. They are used to determine whether a process is in- or out-of-control.

When points on a control chart move outside the upper or lower control limit, the process are said to be “out-of-control.” As long as the points are within control limits, the process is “in-control”. An out-of-control process could produce defective parts. However, if a point is outside the specification limits, the process produces defective products.

Figure 8. In-control and out-of-control processes.

Figure 8. In-control and out-of-control processes.

Control charts are visual tools for monitoring the process capability. With a control chart, we can see the potential shift of process mean and variation at the same time. A numerical measure that can be defined to capture both aforementioned shifts of a process in a single number is the process capability index (PCI).

4.2.2 Concept of Process Capability Index (PCI)

Process capability index measures the degree of variation an in-control process experiences relative to its specification limits. It can also be used to compare different processes with respect to the optimal situation or if they come up to our expectations.

The first process capability index is defined by \(C_p\),

\[ C_p = \frac{USL-LSL}{6\sigma} \]

which is an estimate of what the process is capable of producing if the process mean were to be centered between the specification limits, assuming that the process output is approximately normally distributed. This first \(C_p\) was invented and used in the Japanese semiconductor industry in the 1970s.

Figure 9. First and second generation PCIs.

Figure 9. First and second generation PCIs.

Since \(C_p\) does not consider process means and process target, several major families of PCIs were defined after \(C_p\). The following table lists major PCIs used in the industry for various purposes.

In the manufacturing industry, PCIs are used to measure the quality of a process (product), USL, and LSL and T (target) are given by customers or the management. When applying PCI in other fields such as fraud detection, USL, LSL and T are not given, we need to figure out a way to obtain reasonable USL, LSL, and T in order to define the PCI. The next subsection explains the idea of using PCI to define fraud index.

4.2.3 Framework of Fraud Index Based on PCI

We can consider a credit card as a process that produces transactions. This process characterizes the card holder’s spending behavior. For an established credit card account, we can segment the spending in different subcategories and define different sub-processes. A PCI can be defined for each sub-process. The question is that there are no specification limits set to these types of “processes”. We need to use historical data to obtain optimal specification limits in order to define quality PCIs.

The following chart explains the idea of how to define PCI for a process without being given pre-set process limits.

Figure 10. Illustration of defining PCI of a process without given process limits

Figure 10. Illustration of defining PCI of a process without given process limits

Since fraud detection is a real-time process, the fraud index must also be defined in real-time. The above explains how real-time PCI can be defined. The PCI defined in the above illustration is a rolling PCI since its specification limits are changing over time. The specification limits can also be set as hyperparameters. We can then search for optimal hyperparameters to define optimal PCI for fraud detection.

LS0tDQp0aXRsZTogIkZlYXR1cmUgU2VsZWN0aW9uIGFuZCBFeHRyYWN0aW9uIg0KYXV0aG9yOiAiQ2hlbmcgUGVuZyINCmRhdGU6ICJTVEEgNTUxIEZvdW5kYXRpb25zIG9mIERhdGEgU2NpZW5jZSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ193aWR0aDogNg0KICAgIGZpZ19oZWlnaHQ6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICB0aGVtZTogbHVtZW4NCiAgICBkZl9wcmludDoga2FibGUNCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgZmlnX3dpZHRoOiA1DQogICAgZmlnX2hlaWdodDogNA0KICB3b3JkX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBrZWVwX21kOiB5ZXMNCi0tLQ0KDQpgYGB7PWh0bWx9DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KDQpkaXYjVE9DIGxpIHsNCiAgICBsaXN0LXN0eWxlOm5vbmU7DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KfQ0KDQpoMS50aXRsZSB7DQogIGZvbnQtc2l6ZTogMjRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDEgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMjJweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoMiB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE1cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KPC9zdHlsZT4NCmBgYA0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgY29kZSBjaHVuayBzcGVjaWZpZXMgd2hldGhlciB0aGUgUiBjb2RlLCB3YXJuaW5ncywgYW5kIG91dHB1dCANCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLg0KaWYgKCFyZXF1aXJlKCJ3ZWJzaG90IikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoIndlYnNob3QiKQ0KICAgbGlicmFyeSh3ZWJzaG90KQ0KfQ0KaWYgKCFyZXF1aXJlKCJnZ3Bsb3QyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KICAgbGlicmFyeShnZ3Bsb3QyKQ0KfQ0KIyMjIGxvYWQgJ01BU1MnIHBhY2thZ2UNCmlmKCFyZXF1aXJlKE1BU1MpKXsNCiAgaW5zdGFsbC5wYWNrYWdlcygiTUFTUyIpDQogIGxpYnJhcnkoTUFTUykNCn0NCiMjIyBsb2FkICdrbGFSJyBwYWNrYWdlDQppZighcmVxdWlyZShrbGFSKSl7DQogIGluc3RhbGwucGFja2FnZXMoImtsYVIiKQ0KICBsaWJyYXJ5KGtsYVIpDQp9DQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQoNCiMga25pdHI6Om9wdHNfa25pdCRzZXQocm9vdC5kaXIgPSAiQzovVXNlcnMvNzVDUEVORy9PbmVEcml2ZSAtIFdlc3QgQ2hlc3RlciBVbml2ZXJzaXR5IG9mIFBBL0RvY3VtZW50cyIpDQojIGtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gIkM6XFxTVEE0OTBcXHcwNSIpDQoNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IFRSVUUsICAgDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFKQ0KYGBgDQoNCiMgSW50cm9kdWN0aW9uDQoNCkZlYXR1cmUgc2VsZWN0aW9uIGlzIGEgY3JpdGljYWwgYW5kIHdpZGVseSB1c2VkIHRlY2huaXF1ZSBpbiBkYXRhIHByb2Nlc3NpbmcsIGFpbWVkIGF0IHNlbGVjdGluZyB0aGUgbW9zdCByZWxldmFudCBmZWF0dXJlcyBmcm9tIG5vaXN5IGRhdGEuIFRoaXMgYXBwcm9hY2ggbm90IG9ubHkgZW5oYW5jZXMgdGhlIGV4ZWN1dGlvbiBzcGVlZCBvZiBkYXRhIHByb2Nlc3NpbmcgYWxnb3JpdGhtcyBidXQgYWxzbyBpbXByb3ZlcyBwcmVkaWN0aW9uIGFjY3VyYWN5IGFuZCByZWR1Y2VzIHZhcmlhYmlsaXR5IGluIHJlc3VsdHMuIA0KDQoNCiMgRmVhdHVyZSBTZWxlY3Rpb24gTWV0aG9kcw0KDQpGZWF0dXJlIHNlbGVjdGlvbiwgYSBkaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24gdGVjaG5pcXVlLCBmb2N1c2VzIG9uIGlkZW50aWZ5aW5nIGEgc21hbGwgc3Vic2V0IG9mIHJlbGV2YW50IGZlYXR1cmVzIGZyb20gdGhlIG9yaWdpbmFsIGRhdGFzZXQgYnkgZWxpbWluYXRpbmcgaXJyZWxldmFudCwgcmVkdW5kYW50LCBvciBub2lzeSBmZWF0dXJlcy4gVGhpcyBwcm9jZXNzIHR5cGljYWxseSBlbmhhbmNlcyBsZWFybmluZyBwZXJmb3JtYW5jZSwgaW1wcm92ZXMgbW9kZWwgYWNjdXJhY3ksIHJlZHVjZXMgY29tcHV0YXRpb25hbCBjb3N0cywgYW5kIGluY3JlYXNlcyBtb2RlbCBpbnRlcnByZXRhYmlsaXR5Lg0KDQpTZXZlcmFsIHN0YXRpc3RpY2FsIG1ldGhvZHMgcmVsZXZhbnQgdG8gZmVhdHVyZSBzZWxlY3Rpb24gaGF2ZSBiZWVuIGRpc2N1c3NlZCBpbiB2YXJpb3VzIHN0YXRpc3RpY3MgY291cnNlcy4gVGhpcyBzZWN0aW9uIHByb3ZpZGVzIGFuIG92ZXJ2aWV3IG9mIGZlYXR1cmUgc2VsZWN0aW9uIHR5cGVzLCBtZXRob2RvbG9naWVzLCBhbmQgdGVjaG5pcXVlcyBjb21tb25seSBlbXBsb3llZCBpbiBib3RoIHN0YXRpc3RpY3MgYW5kIG1hY2hpbmUgbGVhcm5pbmcuIEJhc2VkIG9uIHRoZWlyIG5hdHVyZSwgdGhlc2UgbWV0aG9kcyBhcmUgY2F0ZWdvcml6ZWQgaW50byBmb3VyIGRpc3RpbmN0IHR5cGVzLCB3aGljaCB3aWxsIGJlIG91dGxpbmVkIGluIHRoZSBmb2xsb3dpbmcgc3Vic2VjdGlvbnMuDQoNCg0KIyMgRmlsdGVyIE1ldGhvZHMNCg0KRmlsdGVyIG1ldGhvZHMgYXJlIHN0YXRpc3RpY2FsLWJhc2VkIGZlYXR1cmUgc2VsZWN0aW9uIG1ldGhvZHMgdGhhdCBpbnZvbHZlIGV2YWx1YXRpbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGVhY2ggaW5wdXQgdmFyaWFibGUgYW5kIHRoZSB0YXJnZXQgKHJlc3BvbnNlKSB2YXJpYWJsZSB1c2luZyBzdGF0aXN0aWNzIGFuZCBzZWxlY3RpbmcgdGhvc2UgaW5wdXQgdmFyaWFibGVzIHRoYXQgaGF2ZSB0aGUgc3Ryb25nZXN0IHJlbGF0aW9uc2hpcCB3aXRoIHRoZSB0YXJnZXQgdmFyaWFibGUuIFRoZXNlIG1ldGhvZHMgY2FuIGJlIGZhc3QgYW5kIGVmZmVjdGl2ZSwgYWx0aG91Z2ggdGhlIGNob2ljZSBvZiBzdGF0aXN0aWNhbCBtZWFzdXJlcyBkZXBlbmRzIG9uIHRoZSBkYXRhIHR5cGUgb2YgYm90aCB0aGUgaW5wdXQgYW5kIG91dHB1dCB2YXJpYWJsZXMuIEhlcmUgYXJlIHNvbWUgb2YgdGhlc2UgbWV0aG9kcyB3aXRoIGJyaWVmIGRlc2NyaXB0aW9ucy4NCg0KIyMjIEluZm9ybWF0aW9uIEdhaW4NCg0KSW5mb3JtYXRpb24gZ2FpbiBjYWxjdWxhdGVzIHRoZSByZWR1Y3Rpb24gaW4gZW50cm9weSBmcm9tIHRoZSB0cmFuc2Zvcm1hdGlvbiBvZiBhIGRhdGEgc2V0LiBJdCBjYW4gYmUgdXNlZCBmb3IgZmVhdHVyZSBzZWxlY3Rpb24gYnkgZXZhbHVhdGluZyB0aGUgSW5mb3JtYXRpb24gZ2FpbiBvZiBlYWNoIHZhcmlhYmxlIGluIHRoZSBjb250ZXh0IG9mIHRoZSB0YXJnZXQgdmFyaWFibGUuIFdlIGhhdmUgYnJpZWZseSBkZXNjcmliZWQgdGhpcyBtZXRob2QgaW4gZGVjaXNpb24gaW5kdWN0aW9uLg0KDQojIyMgQ2hpLXNxdWFyZSBUZXN0DQoNCkxldOKAmXMgY29uc2lkZXIgYSBzY2VuYXJpbyB3aGVyZSB3ZSBuZWVkIHRvIGRldGVybWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGluZGVwZW5kZW50IGNhdGVnb3J5IGZlYXR1cmUgKHByZWRpY3RvcikgYW5kIGRlcGVuZGVudCBjYXRlZ29yeSBmZWF0dXJlKHJlc3BvbnNlKS4gSW4gZmVhdHVyZSBzZWxlY3Rpb24sIHdlIGFpbSB0byBzZWxlY3QgdGhlIGZlYXR1cmVzIHdoaWNoIGFyZSBoaWdobHkgZGVwZW5kZW50IG9uIHRoZSByZXNwb25zZS4gV2UgY2FsY3VsYXRlIENoaS1zcXVhcmUgYmV0d2VlbiBlYWNoIGZlYXR1cmUgYW5kIHRoZSByZXNwb25zZSB2YXJpYWJsZS4gYW5kIHNlbGVjdCB0aGUgZGVzaXJlZCBudW1iZXIgb2YgZmVhdHVyZXMgd2l0aCB0aGUgYmVzdCBDaGktc3F1YXJlIHNjb3Jlcy4gDQoNCkluIG9yZGVyIHRvIGNvcnJlY3RseSBhcHBseSB0aGUgY2hpLXNxdWFyZWQgdGVzdCBmb3IgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHZhcmlvdXMgZmVhdHVyZXMgaW4gdGhlIGRhdGEgc2V0IGFuZCB0aGUgdGFyZ2V0IHZhcmlhYmxlLCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgaGF2ZSB0byBiZSBtZXQ6IHRoZSB2YXJpYWJsZXMgaGF2ZSB0byBiZSBjYXRlZ29yaWNhbCwgc2FtcGxlZCBpbmRlcGVuZGVudGx5IGFuZCB2YWx1ZXMgc2hvdWxkIGhhdmUgYW4gZXhwZWN0ZWQgZnJlcXVlbmN5IGdyZWF0ZXIgdGhhbiA1LiANCg0KIyMjIEZpc2hlcidzIFNjb3JlIA0KDQpGaXNoZXIgc2NvcmUgaXMgb25lIG9mIHRoZSBtb3N0IHdpZGVseSB1c2VkIHN1cGVydmlzZWQgZmVhdHVyZSBzZWxlY3Rpb24gbWV0aG9kcy4gSXQgc2Vla3MgZmVhdHVyZXMgd2l0aCB0aGUgYmVzdCBkaXNjcmltaW5hbnQgYWJpbGl0eS4gSXQgaXMgYmFzZWQgb24gbWF4aW1pemluZyB0aGUgZGlzdGFuY2VzIGJldHdlZW4gZGF0YSBwb2ludHMgb2YgZGlmZmVyZW50IGNsYXNzZXMgYW5kIG1pbmltaXppbmcgdGhlIGRpc3RhbmNlcyBhbW9uZyBwb2ludHMgb2YgdGhlIHNhbWUgY2xhc3MuIFRvIHJhbmsgdGhlIGZlYXR1cmVzIGluIHRoZSBvcmRlciBvZiB0aGVpciByZWxldmFuY3ksIHRoZXkgYXJlIHNvcnRlZCBpbiB0aGUgZGVjcmVhc2luZyBvcmRlciBvZiB0aGVpciBvYnRhaW5lZCBmaXNoZXIgc2NvcmUuIFRodXMsIGFzIHRoZSB2YWx1ZSBvZiBhbiBhc3NpZ25lZCBzY29yZSB0byBhIGZlYXR1cmUgaW5jcmVhc2VzLCBpdHMgaW1wb3J0YW5jZSBhbHNvIGluY3JlYXNlcy4NCg0KTGV0ICRZJCBiZSB0aGUgY2F0ZWdvcmljYWwgdmFyaWFibGUgd2l0aCAkQyQgY2F0ZWdvcmllcyBhbmQgJFgkIGJlIGEgbnVtZXJpY2FsIHZhcmlhYmxlLiBUaGUgRmlzaGVyJ3Mgc2NvcmUgb2YgJFgkIGlzIGRlZmluZWQgYnkNCg0KJCQNCkZfWCA9IFxmcmFje1xzdW1fe2k9MX1eQyBOX2koXG11X3tYfV5pLVxtdV97WH0pXjJ9e1xzdW1fe2k9MX1eQ05faVx0aW1lcyAoXHNpZ21hX1heaSleMn0NCiQkDQp3aGVyZSAkTl9pJCBpcyB0aGUgbnVtYmVyIG9mIGRhdGEgcG9pbnRzIGluIGNsYXNzICRpJCwgJFxtdV9YJCBpcyB0aGUgbWVhbiBvZiBmZWF0dXJlIHZhcmlhYmxlICRYJCwgYW5kICRcbXVfWF5pJCBhbmQgJChcc2lnbWFfWF5pKV4yJCBhcmUgdGhlIG1lYW4gYW5kIHRoZSB2YXJpYW5jZSBvZg0KY2xhc3MgJGkkIHVwb24gdGhlIGZlYXR1cmUgJFgkIHJlc3BlY3RpdmVseS4NCg0KVGhlIGFsZ29yaXRobSByZXR1cm5zIHRoZSByYW5rcyBvZiB0aGUgdmFyaWFibGVzIGJhc2VkIG9uIHRoZSBmaXNoZXLigJlzIHNjb3JlIGluIGRlc2NlbmRpbmcgb3JkZXIuIFdlIGNhbiB0aGVuIHNlbGVjdCB0aGUgdmFyaWFibGVzIGJhc2VkIG9uIHRoZSBzY29yZXMuDQoNCg0KIyMjIENvcnJlbGF0aW9uIENvZWZmaWNpZW50DQoNCkNvcnJlbGF0aW9uIGlzIGEgbWVhc3VyZSBvZiB0aGUgbGluZWFyIHJlbGF0aW9uc2hpcCBvZiAyIG9yIG1vcmUgdmFyaWFibGVzLiBUaHJvdWdoIGNvcnJlbGF0aW9uLCB3ZSBjYW4gcHJlZGljdCBvbmUgdmFyaWFibGUgZnJvbSB0aGUgb3RoZXIuIFRoZSBsb2dpYyBiZWhpbmQgdXNpbmcgY29ycmVsYXRpb24gZm9yIGZlYXR1cmUgc2VsZWN0aW9uIGlzIHRoYXQgdGhlIGdvb2QgdmFyaWFibGVzIGFyZSBoaWdobHkgY29ycmVsYXRlZCB3aXRoIHRoZSByZXNwb25zZS4gRnVydGhlcm1vcmUsIHZhcmlhYmxlcyBzaG91bGQgYmUgY29ycmVsYXRlZCB3aXRoIHRoZSByZXNwb25zZSBidXQgc2hvdWxkIGJlIHVuY29ycmVsYXRlZCBhbW9uZyB0aGVtc2VsdmVzLiBUaGlzIG1ldGhvZCBpcyB2YWxpZCB3aGVuIGJvdGggcmVzcG9uc2UgYW5kIGZlYXR1cmUgdmFyaWFibGVzIGFyZSBudW1lcmljLg0KDQojIyMgVmFyaWFuY2UgVGhyZXNob2xkDQoNClRoZSB2YXJpYW5jZSB0aHJlc2hvbGQgaXMgYSBzaW1wbGUgYmFzZWxpbmUgYXBwcm9hY2ggdG8gZmVhdHVyZSBzZWxlY3Rpb24uIEl0IHJlbW92ZXMgYWxsIGZlYXR1cmVzIHdoaWNoIHZhcmlhbmNlIGRvZXMgbm90IG1lZXQgc29tZSB0aHJlc2hvbGQuIFRoZSBsb2dpYyBmb3IgdGhpcyBtZXRob2QgaXMgdGhhdCBmZWF0dXJlcyB3aXRoIGEgaGlnaGVyIHZhcmlhbmNlIG1heSBjb250YWluIG1vcmUgdXNlZnVsIGluZm9ybWF0aW9uLiANCg0KDQojIyBXcmFwcGVyIE1ldGhvZHMNCg0KV3JhcHBlcnMgcmVxdWlyZSBzb21lIG1ldGhvZCB0byBzZWFyY2ggdGhlIHNwYWNlIG9mIGFsbCBwb3NzaWJsZSBzdWJzZXRzIG9mIGZlYXR1cmVzLCBhc3Nlc3NpbmcgdGhlaXIgcXVhbGl0eSBieSBsZWFybmluZyBhbmQgZXZhbHVhdGluZyBhIGNsYXNzaWZpZXIgd2l0aCB0aGF0IGZlYXR1cmUgc3Vic2V0LiBUaGUgZmVhdHVyZSBzZWxlY3Rpb24gcHJvY2VzcyBpcyBiYXNlZCBvbiBhIHNwZWNpZmljIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtIHRoYXQgd2UgYXJlIHRyeWluZyB0byBmaXQgb24gYSBnaXZlbiBkYXRhIHNldC4gSXQgZm9sbG93cyBhIGdyZWVkeSBzZWFyY2ggYXBwcm9hY2ggYnkgZXZhbHVhdGluZyBhbGwgdGhlIHBvc3NpYmxlIGNvbWJpbmF0aW9ucyBvZiBmZWF0dXJlcyBhZ2FpbnN0IHRoZSBldmFsdWF0aW9uIGNyaXRlcmlvbi4gVGhlIHdyYXBwZXIgbWV0aG9kcyB1c3VhbGx5IHJlc3VsdCBpbiBiZXR0ZXIgcHJlZGljdGl2ZSBhY2N1cmFjeSB0aGFuIGZpbHRlciBtZXRob2RzLg0KDQpUaGUgZm9sbG93aW5nIGFyZSBhIGZldyBzdWNoIG1ldGhvZHMuDQoNCiMjIyBGb3J3YXJkIEZlYXR1cmUgU2VsZWN0aW9uDQoNClRoaXMgaXMgYW4gaXRlcmF0aXZlIG1ldGhvZCB3ZSBzdGFydCB3aXRoIHRoZSBiZXN0IHBlcmZvcm1pbmcgdmFyaWFibGUgYWdhaW5zdCB0aGUgdGFyZ2V0LiBOZXh0LCB3ZSBzZWxlY3QgYW5vdGhlciB2YXJpYWJsZSB0aGF0IGdpdmVzIHRoZSBiZXN0IHBlcmZvcm1hbmNlIGluIGNvbWJpbmF0aW9uIHdpdGggdGhlIGZpcnN0IHNlbGVjdGVkIHZhcmlhYmxlLiBUaGlzIHByb2Nlc3MgY29udGludWVzIHVudGlsIHRoZSBwcmVzZXQgY3JpdGVyaW9uIGlzIGFjaGlldmVkLg0KDQojIyMgQmFja3dhcmQgRmVhdHVyZSBFbGltaW5hdGlvbg0KDQpUaGlzIG1ldGhvZCB3b3JrcyBleGFjdGx5IG9wcG9zaXRlIHRvIHRoZSBGb3J3YXJkIEZlYXR1cmUgU2VsZWN0aW9uIG1ldGhvZC4gSGVyZSwgd2Ugc3RhcnQgd2l0aCBhbGwgdGhlIGZlYXR1cmVzIGF2YWlsYWJsZSBhbmQgYnVpbGQgYSBtb2RlbC4gTmV4dCwgd2UgdGhlIHZhcmlhYmxlIGZyb20gdGhlIG1vZGVsIHdoaWNoIGdpdmVzIHRoZSBiZXN0IGV2YWx1YXRpb24gbWVhc3VyZSB2YWx1ZS4gVGhpcyBwcm9jZXNzIGlzIGNvbnRpbnVlZCB1bnRpbCB0aGUgcHJlc2V0IGNyaXRlcmlvbiBpcyBhY2hpZXZlZC4NCg0KIyMjIFN1YnNldCBGZWF0dXJlIFNlbGVjdGlvbg0KDQpUaGlzIGlzIHRoZSBtb3N0IHJvYnVzdCBmZWF0dXJlIHNlbGVjdGlvbiBtZXRob2QgY292ZXJlZCBzbyBmYXIuIFRoaXMgaXMgYSBicnV0ZS1mb3JjZSBldmFsdWF0aW9uIG9mIGVhY2ggZmVhdHVyZSBzdWJzZXQuIFRoaXMgbWVhbnMgdGhhdCBpdCB0cmllcyBldmVyeSBwb3NzaWJsZSBjb21iaW5hdGlvbiBvZiB0aGUgdmFyaWFibGVzIGFuZCByZXR1cm5zIHRoZSBiZXN0LXBlcmZvcm1pbmcgc3Vic2V0Lg0KDQoNCiMjIEVtYmVkZGVkIE1ldGhvZHMNCg0KVGhlc2UgbWV0aG9kcyBlbmNvbXBhc3MgdGhlIGJlbmVmaXRzIG9mIGJvdGggdGhlIHdyYXBwZXIgYW5kIGZpbHRlciBtZXRob2RzLCBieSBpbmNsdWRpbmcgaW50ZXJhY3Rpb25zIG9mIGZlYXR1cmVzIGJ1dCBhbHNvIG1haW50YWluaW5nIHJlYXNvbmFibGUgY29tcHV0YXRpb25hbCBjb3N0LiBFbWJlZGRlZCBtZXRob2RzIGFyZSBpdGVyYXRpdmUgaW4gdGhlIHNlbnNlIHRoYXQgdGFrZXMgY2FyZSBvZiBlYWNoIGl0ZXJhdGlvbiBvZiB0aGUgbW9kZWwgdHJhaW5pbmcgcHJvY2VzcyBhbmQgY2FyZWZ1bGx5IGV4dHJhY3QgdGhvc2UgZmVhdHVyZXMgd2hpY2ggY29udHJpYnV0ZSB0aGUgbW9zdCB0byB0aGUgdHJhaW5pbmcgZm9yIGEgcGFydGljdWxhciBpdGVyYXRpb24uDQoNCiMjIyBMQVNTTyBSZWd1bGFyaXphdGlvbiANCg0KUmVndWxhcml6YXRpb24gY29uc2lzdHMgb2YgYWRkaW5nIGEgcGVuYWx0eSB0byB0aGUgZGlmZmVyZW50IHBhcmFtZXRlcnMgb2YgdGhlIG1hY2hpbmUgbGVhcm5pbmcgbW9kZWwgdG8gcmVkdWNlIHRoZSBmcmVlZG9tIG9mIHRoZSBtb2RlbCwgaS5lLiB0byBhdm9pZCBvdmVyLWZpdHRpbmcuIEluIGxpbmVhciBtb2RlbCByZWd1bGFyaXphdGlvbiwgdGhlIHBlbmFsdHkgaXMgYXBwbGllZCBvdmVyIHRoZSBjb2VmZmljaWVudHMgdGhhdCBtdWx0aXBseSBlYWNoIG9mIHRoZSBwcmVkaWN0b3JzLiBGcm9tIHRoZSBkaWZmZXJlbnQgdHlwZXMgb2YgcmVndWxhcml6YXRpb24sIExhc3NvIG9yIEwxIGhhcyB0aGUgcHJvcGVydHkgdGhhdCBjYW4gc2hyaW5rIHNvbWUgb2YgdGhlIGNvZWZmaWNpZW50cyB0byB6ZXJvLiBUaGVyZWZvcmUsIHRoYXQgZmVhdHVyZSBjYW4gYmUgcmVtb3ZlZCBmcm9tIHRoZSBtb2RlbC4NCg0KIyMjIFJhbmRvbSBGb3Jlc3QgSW1wb3J0YW5jZQ0KDQpSYW5kb20gRm9yZXN0cyBpcyBhIGtpbmQgb2YgYSBCYWdnaW5nIEFsZ29yaXRobSB0aGF0IGFnZ3JlZ2F0ZXMgYSBzcGVjaWZpZWQgbnVtYmVyIG9mIGRlY2lzaW9uIHRyZWVzLiBUaGUgdHJlZS1iYXNlZCBzdHJhdGVnaWVzIHVzZWQgYnkgcmFuZG9tIGZvcmVzdHMgbmF0dXJhbGx5IHJhbmsgYnkgaG93IHdlbGwgdGhleSBpbXByb3ZlIHRoZSBwdXJpdHkgb2YgdGhlIG5vZGUsIG9yIGluIG90aGVyIHdvcmRzIGEgZGVjcmVhc2UgaW4gdGhlIGltcHVyaXR5IChHaW5pIGltcHVyaXR5KSBvdmVyIGFsbCB0cmVlcy4gTm9kZXMgd2l0aCB0aGUgZ3JlYXRlc3QgZGVjcmVhc2UgaW4gaW1wdXJpdHkgaGFwcGVuIGF0IHRoZSBzdGFydCBvZiB0aGUgdHJlZXMsIHdoaWxlIG5vdGVzIHdpdGggdGhlIGxlYXN0IGRlY3JlYXNlIGluIGltcHVyaXR5IG9jY3VyIGF0IHRoZSBlbmQgb2YgdHJlZXMuIFRodXMsIGJ5IHBydW5pbmcgdHJlZXMgYmVsb3cgYSBwYXJ0aWN1bGFyIG5vZGUsIHdlIGNhbiBjcmVhdGUgYSBzdWJzZXQgb2YgdGhlIG1vc3QgaW1wb3J0YW50IGZlYXR1cmVzLg0KDQoNCiMjIEh5YnJpZCBNZXRob2RzDQoNCkh5YnJpZCBtZXRob2RzIHRyeSB0byBleHBsb2l0IHRoZSBxdWFsaXRpZXMgb2YgYm90aCBhcHByb2FjaGVzLCBmaWx0ZXIsIGFuZCB3cmFwcGVyLCB0cnlpbmcgdG8gaGF2ZSBhIGdvb2QgY29tcHJvbWlzZSBiZXR3ZWVuIGVmZmljaWVuY3kgKGNvbXB1dGF0aW9uYWwgZWZmb3J0KSBhbmQgZWZmZWN0aXZlbmVzcyAocXVhbGl0eSBpbiB0aGUgYXNzb2NpYXRlZCBvYmplY3RpdmUgdGFzayB3aGVuIHVzaW5nIHRoZSBzZWxlY3RlZCBmZWF0dXJlcykuDQoNClRvIHRha2UgYWR2YW50YWdlIG9mIHRoZSBmaWx0ZXIgYW5kIHdyYXBwZXIgYXBwcm9hY2hlcywgaHlicmlkIG1ldGhvZHMsIGluIGEgZmlsdGVyIHN0YWdlLCB0aGUgZmVhdHVyZXMgYXJlIHJhbmtlZCBvciBzZWxlY3RlZCBhcHBseWluZyBhIG1lYXN1cmUgYmFzZWQgb24gaW50cmluc2ljIHByb3BlcnRpZXMgb2YgdGhlIGRhdGEuIFdoaWxlLCBpbiBhIHdyYXBwZXIgc3RhZ2UsIGNlcnRhaW4gZmVhdHVyZSBzdWJzZXRzIGFyZSBldmFsdWF0ZWQgZm9yIGZpbmRpbmcgdGhlIGJlc3Qgb25lLCB0aHJvdWdoIGEgc3BlY2lmaWMgY2x1c3RlcmluZyBhbGdvcml0aG0uIFdlIGNhbiBkaXN0aW5ndWlzaCB0d28gdHlwZXMgb2YgaHlicmlkIG1ldGhvZHM6IG1ldGhvZHMgYmFzZWQgb24gcmFua2luZyBhbmQgbWV0aG9kcyBub24tYmFzZWQgb24gdGhlIHJhbmtpbmcgb2YgZmVhdHVyZXMuDQoNCiMgRmVhdHVyZSBFeHRyYWN0aW9uIE1ldGhvZHMNCg0KQnkgZmluZGluZyBhIHNtYWxsZXIgc2V0IG9mIG5ldyB2YXJpYWJsZXMsIGVhY2ggYmVpbmcgYSBjb21iaW5hdGlvbiBvZiB0aGUgaW5wdXQgdmFyaWFibGVzLCBjb250YWluaW5nIGJhc2ljYWxseSB0aGUgc2FtZSBpbmZvcm1hdGlvbiBhcyB0aGUgaW5wdXQgdmFyaWFibGVzLiBJbiBvdGhlciB3b3JkcywgZmVhdHVyZSBleHRyYWN0aW9uIGlzIGEgcHJvY2VkdXJlIHRoYXQgZGVmaW5lcyBuZXcgdmFyaWFibGVzIGJ5IGFnZ3JlZ2F0aW5nIHRoZSBpbmZvcm1hdGlvbiBmcm9tIGV4aXN0aW5nIGZlYXR1cmVzLiBGb3IgZXhhbXBsZSwgdGhlIG5ldyBmZWF0dXJlIHZhcmlhYmxlIGNvdWxkIGJlIGEgZnVuY3Rpb24gb2YgdGhlIGV4aXN0aW5nIGZlYXR1cmVzLiBUaGUgbmV3IHNldCBvZiBmZWF0dXJlcyB3aWxsIGhhdmUgZGlmZmVyZW50IHZhbHVlcyBhcyBjb21wYXJlZCB0byB0aGUgb3JpZ2luYWwgZmVhdHVyZSB2YWx1ZXMuIA0KDQpUaGUgbWFpbiBhaW0gaXMgdGhhdCBmZXdlciBmZWF0dXJlcyB3aWxsIGJlIHJlcXVpcmVkIHRvIGNhcHR1cmUgdGhlIHNhbWUgaW5mb3JtYXRpb24uIA0KDQojIyBDbHVzdGVyIEFuYWx5c2lzDQoNCmNsdXN0ZXIgYW5hbHlzaXMsIGluIHN0YXRpc3RpY3MsIHNldCBvZiB0b29scyBhbmQgYWxnb3JpdGhtcyB0aGF0IGFyZSB1c2VkIHRvIGNsYXNzaWZ5IGRpZmZlcmVudCBvYmplY3RzIGludG8gZ3JvdXBzIGluIHN1Y2ggYSB3YXkgdGhhdCB0aGUgc2ltaWxhcml0eSBiZXR3ZWVuIHR3byBvYmplY3RzIGlzIG1heGltYWwgaWYgdGhleSBiZWxvbmcgdG8gdGhlIHNhbWUgZ3JvdXAgYW5kIG1pbmltYWwgb3RoZXJ3aXNlLiBUaGUgY2x1c3RlciBJRCBpcyBhIG5ldyBmZWF0dXJlIHRoYXQgY2FuIGJlIHVzZWQgdG8gY2FwdHVyZSBoZXRlcm9nZW5lb3VzIGluZm9ybWF0aW9uIGFjcm9zcyBjbHVzdGVycy4NCg0KDQojIyBQcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2lzIChQQ0EpDQoNCldlIGhhdmUgaW50cm9kdWNlZCBsaW5lYXIgcHJpbmNpcGFsIGNvbXBvbmVudCBhbmFseXNpcyAoUENBKS4gVGhlIGlkZWEgaXMgdG8gbWFwIHRoZSBleGlzdGluZyBmZWF0dXJlIHNwYWNlIHRvIGEgbmV3IHNwYWNlIChwcmluY2lwYWwgY29tcG9uZW50cyBzcGFjZSkuDQoNClRlY2huaWNhbGx5LCBhIHByaW5jaXBhbCBjb21wb25lbnQgY2FuIGJlIGRlZmluZWQgYXMgYSBsaW5lYXIgY29tYmluYXRpb24gb2Ygb3B0aW1hbGx5LXdlaWdodGVkIG9ic2VydmVkIHZhcmlhYmxlcy4gVGhlIG91dHB1dCBvZiBQQ0EgaXMgdGhlc2UgcHJpbmNpcGFsIGNvbXBvbmVudHMuIFRoZSBudW1iZXIgb2YgUENzIHRvIHJldGFpbiBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gdGhlIG51bWJlciBvZiBvcmlnaW5hbCB2YXJpYWJsZXMuIFRoZSBQQ3MgcG9zc2VzcyBzb21lIHVzZWZ1bCBwcm9wZXJ0aWVzDQoNCiogVGhlIFBDcyBhcmUgZXNzZW50aWFsbHkgdGhlIGxpbmVhciBjb21iaW5hdGlvbnMgb2YgdGhlIG9yaWdpbmFsIHZhcmlhYmxlcywgdGhlIHdlaWdodHMgdmVjdG9yIGluIHRoaXMgY29tYmluYXRpb24gaXMgYWN0dWFsbHkgdGhlIGVpZ2VudmVjdG9yIGZvdW5kIHdoaWNoIGluIHR1cm4gc2F0aXNmaWVzIHRoZSBwcmluY2lwbGUgb2YgbGVhc3Qgc3F1YXJlcy4NCg0KKiBUaGUgUENzIGFyZSBvcnRob2dvbmFsLCBhcyBhbHJlYWR5IGRpc2N1c3NlZC4NCg0KKiBUaGUgdmFyaWF0aW9uIHByZXNlbnQgaW4gdGhlIFBDcyBkZWNyZWFzZSBhcyB3ZSBtb3ZlIGZyb20gdGhlIDFzdCBQQyB0byB0aGUgbGFzdCBvbmUsIGhlbmNlIHRoZSBpbXBvcnRhbmNlLg0KDQoqIFRoZSBsZWFzdCBpbXBvcnRhbnQgUENzIGFyZSBhbHNvIHNvbWV0aW1lcyB1c2VmdWwgaW4gcmVncmVzc2lvbiwgb3V0bGllciBkZXRlY3Rpb24sIGV0Yy4NCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zLCBmaWcuY2FwPSJGaWd1cmUgMS4gSWxsdXN0cmF0aW9uIG9mIFBDQS4gVGhlIGxlYXN0ICgybmQpIGltcG9ydGFudCBjb21wb25lbnQgY2FuIGJlIHVzZWQgZm9yIGFub21hbHkgZGV0ZWN0aW9uLiJ9DQppbmNsdWRlX2dyYXBoaWNzKCJpbWcvdzEwLVBDQS5qcGciKQ0KYGBgDQoNCiMjIExpbmVhciBEaXNjcmltaW5hbnQgQW5hbHlzaXMgKExEQSkNCg0KTGluZWFyIGRpc2NyaW1pbmFudCBhbmFseXNpcyAoTERBKSBhbHNvIGNyZWF0ZXMgbGluZWFyIGNvbWJpbmF0aW9ucyBvZiB5b3VyIG9yaWdpbmFsIGZlYXR1cmVzLiBIb3dldmVyLCB1bmxpa2UgUENBLCBMREEgZG9lc24ndCBtYXhpbWl6ZSBleHBsYWluZWQgdmFyaWFuY2UuIEluc3RlYWQsIGl0IG1heGltaXplcyB0aGUgc2VwYXJhYmlsaXR5IGJldHdlZW4gY2xhc3Nlcy4NCg0KSW4gb3RoZXIgd29yZHMsIHRoZSBnb2FsIG9mIGFuIExEQSBpcyB0byBwcm9qZWN0IGEgZmVhdHVyZSBzcGFjZSAoYSBkYXRhIHNldCBuLWRpbWVuc2lvbmFsIHNhbXBsZXMpIG9udG8gYSBzbWFsbGVyIHN1YnNwYWNlIGsgKHdoZXJlICQgayBcbGUgbuKIkjEkKSB3aGlsZSBtYWludGFpbmluZyB0aGUgY2xhc3MtZGlzY3JpbWluYXRvcnkgaW5mb3JtYXRpb24uDQoNCkluIGdlbmVyYWwsIGRpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbiBkb2VzIG5vdCBvbmx5IGhlbHAgcmVkdWNlIGNvbXB1dGF0aW9uYWwgY29zdHMgZm9yIGEgZ2l2ZW4gY2xhc3NpZmljYXRpb24gdGFzaywgYnV0IGl0IGNhbiBhbHNvIGJlIGhlbHBmdWwgdG8gYXZvaWQgb3ZlcmZpdHRpbmcgYnkgbWluaW1pemluZyB0aGUgZXJyb3IgaW4gcGFyYW1ldGVyIGVzdGltYXRpb24gKOKAnGN1cnNlIG9mIGRpbWVuc2lvbmFsaXR54oCdKS4NCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD0zLCBmaWcuaGVpZ2h0PTMsIGZpZy5jYXA9IkZpZ3VyZSAyLiBJbGx1c3RyYXRpb24gb2YgTERBLiJ9DQppbmNsdWRlX2dyYXBoaWNzKCJpbWcvdzEwLUxEQS5qcGciKQ0KYGBgDQoNClRoZXJlZm9yZSwgTERBIGlzIGEgc3VwZXJ2aXNlZCBtZXRob2QgdGhhdCBjYW4gb25seSBiZSB1c2VkIHdpdGggbGFiZWxlZCBkYXRhLiBUaGUgTERBIHRyYW5zZm9ybWF0aW9uIGlzIGFsc28gZGVwZW5kZW50IG9uIHNjYWxlLCBzbyB3ZSBzaG91bGQgbm9ybWFsaXplIG9yaWdpbmFsIGZlYXR1cmVzIGluIHRoZSBkYXRhIHNldCBmaXJzdC4NCg0KKipTdHJlbmd0aHMqKjogTERBIGlzIHN1cGVydmlzZWQsIHdoaWNoIGNhbiAoYnV0IGRvZXNuJ3QgYWx3YXlzKSBpbXByb3ZlIHRoZSBwcmVkaWN0aXZlIHBlcmZvcm1hbmNlIG9mIHRoZSBleHRyYWN0ZWQgZmVhdHVyZXMuIEZ1cnRoZXJtb3JlLCBMREEgb2ZmZXJzIHZhcmlhdGlvbnMgKGkuZS4gcXVhZHJhdGljIExEQSkgdG8gdGFja2xlIHNwZWNpZmljIHJvYWRibG9ja3MuDQoNCioqV2Vha25lc3NlcyoqOiBBcyB3aXRoIFBDQSwgdGhlIG5ldyBmZWF0dXJlcyBhcmUgbm90IGVhc2lseSBpbnRlcnByZXRhYmxlLCBhbmQgd2UgbXVzdCBzdGlsbCBtYW51YWxseSBzZXQgb3IgdHVuZSB0aGUgbnVtYmVyIG9mIGNvbXBvbmVudHMgdG8ga2VlcC4gTERBIGFsc28gcmVxdWlyZXMgbGFiZWxlZCBkYXRhLg0KDQoNCioqUENBIHZzIExEQSoqOiBXaGljaCBpcyBiZXR0ZXI/IFRoZSByZXN1bHRzIHdpbGwgdmFyeSBmcm9tIHByb2JsZW0gdG8gcHJvYmxlbS4gSW4gb3RoZXIgd29yZHMsIHRoZSAqKk5vIEZyZWUgTHVuY2gqKiBUaGVvcmVtIGFwcGxpZXMgdG8gdGhpcyBzaXR1YXRpb24uIFRoZSBmb2xsb3dpbmcgZmlndXJlIGRlcGljdHMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBQQ0EgYW5kIExEQS4NCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zLCBmaWcuY2FwPSJGaWd1cmUgMy4gSWxsdXN0cmF0aW9uIG9mIHRoZSBkaWZmZXJlbmNlIG9mIFBDQSBhbmQgTERBLiJ9DQppbmNsdWRlX2dyYXBoaWNzKCJpbWcvdzEwLUxEQS12cy1MREEuanBnIikNCmBgYA0KDQojIyBDYXNlLXN0dWR5OiBMREEgd2l0aCBJcmlzIERhdGEgDQoNCmxpa2UgUENBIHdob3NlIG1hdGhlbWF0aWNhbCBmb3JtdWxhdGlvbiBpbnZvbHZlcyBtYXRyaXggYWxnZWJyYSAoZWlnZW52ZWN0b3IgYW5kIGVpZ2VudmFsdWVzKSBhbmQgbGluZWFyIHByb2dyYW1taW5nIChvcHRpbWl6YXRpb24gd2l0aCBsaW5lYXIgY29uc3RyYWludHMpLCBpbiBMREEgd2Ugc3RpbGwgbmVlZCB0byB1c2UgdGhlIHNhbWUgdG9vbHMgYnV0IHdpdGggZGlmZmVyZW50IG9iamVjdGl2ZSBmdW5jdGlvbnMgZm9yIG9wdGltaXphdGlvbi4gV2Ugd2lsbCBub3QgaW50cm9kdWNlIHRoZXNlIG1hdGhlbWF0aWNhbCBzdGVwcyB0byBmaW5kIHRoZSBsaW5lYXIgZGlzY3JpbWluYW50IGNvbXBvbmVudHMuIA0KDQpOZXh0LCB3ZSB1c2UgUiBmdW5jdGlvbiAqKmxkYSgpKiogaW4gbGlicmFyeSAqKntNQVNTfSoqIHRvIGZpbmQgTERBIGNvbXBvbmVudHMgYmFzZWQgb24gdGhlIGZvdXIgbnVtZXJpY2FsIGZlYXR1cmVzIGluIElyaXMgZGF0YS4NCg0KKipsZGEoKSoqIHJldHVybnMgc2V2ZXJhbCByZXN1bHRzOg0KDQoqIFRoZSBtb3N0IGltcG9ydGFudCByZXN1bHQgaGVyZSBpcyB0aGUgY29lZmZpY2llbnRzLCB0aGV5IGFyZSB2YWx1ZXMgdGhhdCBkZXNjcmliZSB0aGUgbmV3IGZlYXR1cmUgc3BhY2Ugd2hlcmUgdGhlIGRhdGEgd2lsbCBiZSBwcm9qZWN0ZWQgaW4uIA0KDQoqIExEQSByZWR1Y2VzIGRpbWVuc2lvbmFsaXR5IGZyb20gdGhlIG9yaWdpbmFsIG51bWJlciBvZiBmZWF0dXJlcyB0byBDIOKAlCAxIGZlYXR1cmVzLCB3aGVyZSBDIGlzIHRoZSBudW1iZXIgb2YgY2xhc3Nlcy4gSW4gdGhpcyBjYXNlLCB3ZSBoYXZlIDMgY2xhc3NlcywgdGhlcmVmb3JlIHRoZSBuZXcgZmVhdHVyZSBzcGFjZSB3aWxsIGhhdmUgb25seSAyIGZlYXR1cmVzLiANCg0KDQpgYGB7cn0NCmRhdGEoaXJpcykNCiMgRGF0YSBwYXJ0aXRpb24NCnRyYWluaW5nX3NhbXBsZSA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIG5yb3coaXJpcyksIHJlcGxhY2UgPSBULCBwcm9iID0gYygwLjYsMC40KSkNCnRyYWluIDwtIGlyaXNbdHJhaW5pbmdfc2FtcGxlLCBdDQp0ZXN0IDwtIGlyaXNbIXRyYWluaW5nX3NhbXBsZSwgXQ0KIw0KbGRhLmlyaXMgPC0gbGRhKFNwZWNpZXMgfiAuLCBkYXRhID0gdHJhaW4pIywgcHJpb3IgPSByZXAoMS8zLCAzKSkNCmthYmxlKGxkYS5pcmlzJHNjYWxpbmcsIGNhcHRpb249IlRoZSBzY2FsaW5nIGNvZWZmaWNpZW50cyBvZiBMREEiKSAgIyBzaG93IHJlc3VsdHMNCmBgYA0KDQpUaGUgdHdvIG5ldyBmZWF0dXJlIHZhcmlhYmxlcyBiYXNlZCBvbiB0aGUgdHdvIExEQSBhcmUgZXhwbGljaXRseSBnaXZlbiBieQ0KDQokJA0KTERBXzEgPSAoMC41MVx0aW1lcyBTZXBhbC5MZW5ndGgpICsgKDEuOTZcdGltZXMgU2VwYWwuV2lkdGgpICsgKC0yLjEyXHRpbWVzIFBldGFsLkxlbmd0aCkgKyAoLTIuOThcdGltZXMgUGV0YWwuV2lkdGgpIA0KJCQNCiQkDQpMREFfMiA9ICgtMC43Nlx0aW1lcyBTZXBhbC5MZW5ndGgpICsgKDIuODVcdGltZXMgU2VwYWwuV2lkdGgpICsgKC0xLjA1XHRpbWVzIFBldGFsLkxlbmd0aCkgKyAoMS45Mlx0aW1lcyBQZXRhbC5XaWR0aCkNCiQkDQpOZXh0LCB3ZSB1c2UgTERBIHRvIG1ha2UgYSBwcmVkaWN0aW9uIHVzaW5nIHRoZSBob2xkLW91dCB0ZXN0IGRhdGEuIE5vdGUgdGhhdCBwcmVkaWN0KCkgcmV0dXJucyB0aHJlZSBvYmplY3RzIHdpdGggdGhyZWUgZGlmZmVyZW50IHBpZWNlcyBvZiBpbmZvcm1hdGlvbjoNCg0KKiAqKmxkYS50ZXN0JGNsYXNzKiogY29udGFpbnMgdGhlIHByZWRpY3RlZCBsYWJlbHMuDQoqICoqbGRhLnRlc3QkcG9zdGVyaW9yKiogY29udGFpbnMgdGhlIHByZWRpY3RpdmUgY2xhc3MgcHJvYmFiaWxpdGllcyBvZiBuZXcgZGF0YSBwb2ludHMuDQoqICoqbGRhLnRlc3QkeCoqIGNvbnRhaW5zIHRoZSB0d28gTERBIHNjb3Jlcy4NCg0KSW4gdGhlIGZvbGxvd2luZyBjb2RlLCB3ZSBleHRyYWN0IHRoZSBwcmVkaWN0ZWQgbGFiZWxzIGFuZCB0aGVuIGNvbXBhcmUgdGhlbSB3aXRoIHRoZSBhY3R1YWwgbGFiZWxzIHRvIGZpbmQgdGhlIGNvbmZ1c2lvbiBtYXRyaXggYW5kIGNhbGN1bGF0ZSB0aGUgYWNjdXJhY3kgb2YgY2xhc3NpZmljYXRpb24gTERBLg0KDQoNCmBgYHtyfQ0KbGRhLnRlc3QgPC0gcHJlZGljdChsZGEuaXJpcywgbmV3ZGF0YSA9IHRlc3QpDQp0ZXN0JGxkYSA8LSBsZGEudGVzdCRjbGFzcyAgDQpjb25mdXNpb24ubWF0cml4ID0gdGFibGUodGVzdCRsZGEsdGVzdCRTcGVjaWVzKQ0Ka2FibGUoY29uZnVzaW9uLm1hdHJpeCwgY2FwdGlvbiA9ICJDb25mdXNpb24gbWF0cml4IGJhc2VkIG9uZSBMREEuIikNCmBgYA0KDQpUaGUgYWNjdXJhY3kgb2YgTERBIHByZWRpY3Rpb24gb24gdGhlIHRlc3QgZGF0YSBzZXQgaXMgJDQ5LzUwID0gOThcJSQuDQoNCiMjIFJlbWFya3MNCg0KV2UgaGF2ZSBpbnRyb2R1Y2VkIHR3byB3ZWxsLWtub3duIGZlYXR1cmUgZXh0cmFjdGlvbiBtZXRob2RzOiBQQ0EgYW5kIExEQS4gQm90aCBhcmUgbGluZWFyIGV4dHJhY3Rpb24gbWV0aG9kcy4gUENBIGlzIGFuIHVuc3VwZXJ2aXNlZCBleHRyYWN0aW9uIG1ldGhvZCBhbmQgTERBIGlzIGEgc3VwZXJ2aXNlZCBtZXRob2QuIEJvdGggbWV0aG9kcyBhcmUgZGV2ZWxvcGVkIGZvciBkaWZmZXJlbnQgcHVycG9zZXMgYnV0IGJvdGggY2FuIGJlIHVzZWQgZm9yIGRpbWVuc2lvbmFsIHJlZHVjdGlvbi4NCg0KQm90aCBQQ0EgYW5kIExEQSBjYW4gYmUgYWRhcHRlZCBmb3Igbm9ubGluZWFyIGZlYXR1cmUgZXh0cmFjdGlvbiBieSBpbnRyb2R1Y2luZyBrZXJuZWwgZnVuY3Rpb25zIChpLmUuLCBrZXJuZWwgUENBIGFuZCBrZXJuZWwgTERBKSBvciBjaGFuZ2luZyB0aGUgbGluZWFyIGNvbWJpbmF0aW9uIG9mIHRoZSBvcmlnaW5hbCBmZWF0dXJlcyBpbnRvIHRoZSBwb2x5bm9taWFsIGV4cHJlc3Npb24gdG8gY2FwdHVyZSB0aGUgbm9ubGluZWFyIHBhdHRlcm5zIChpLmUuLCBwb2x5bm9taWFsIFBDQSBhbmQgcG9seW5vbWlhbCBMREEpLg0KDQpUaGUgdmFyaW91cyB2YXJpYWJsZSB0cmFuc2Zvcm1hdGlvbnMgaW5jbHVkaW5nIHRoZSB3ZWxsLWtub3duIEJveC1Db3ggdHJhbnNmb3JtYXRpb24sIGRpc2NyZXRpemF0aW9uLCBhbmQgcmVkZWZpbmluZyBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYnkgY29tYmluZyBjYXRlZ29yaWVzIGluIG1lYW5pbmdmdWwgd2F5cyBhcmUgYWxsIGNhbGxlZCBmZWF0dXJlIGV4dHJhY3Rpb24gbWV0aG9kcy4gDQoNCg0KIyBGZWF0dXJlIEV4dHJhY3Rpb24gd2l0aCBTZXJpYWwgRGF0YQ0KDQpUaGUgZmVhdHVyZSBleHRyYWN0aW9uIG1ldGhvZHMgaW50cm9kdWNlZCBpbiB0aGUgcHJldmlvdXMgc2VjdGlvbiBhcmUgYmFzZWQgb24gY3Jvc3Mtc2VjdGlvbmFsIGRhdGEuIFRoZXJlIGFyZSBvbmx5IHZlcnkgbGltaXRlZCBkaXNjdXNzaW9ucyBvbiBmZWF0dXJlIGV4dHJhY3Rpb24gYmFzZWQgb24gc2VyaWFsIGRhdGEgaW5jbHVkaW5nIHRpbWUgc2VyaWVzIGFuZCBwYW5lbCBkYXRhLiBJbiBwYXJ0aWN1bGFyLCBubyBmZWF0dXJlIGV4dHJhY3Rpb24gbWV0aG9kIGJhc2VkIG9uIHBhbmVsIGRhdGEgaGFzIGJlZW4gZGlzY3Vzc2VkIHNvIGZhciBpbiB0aGUgbGl0ZXJhdHVyZS4NCg0KSW4gdGhpcyBzZWN0aW9uLCB3ZSBmaXJzdCBpbnRyb2R1Y2UgdGhlIHdheSBhbmQgdHlwZSBvZiBmZWF0dXJlcyBvbmUgY2FuIGV4dHJhY3QgZnJvbSBhIHRpbWUgc2VyaWVzLiBUaGVuIHdlIGludHJvZHVjZSBhIG5ldyBtZXRob2QgZm9yIGV4dHJhY3RpbmcgZmVhdHVyZXMgZnJvbSBwYW5lbCBkYXRhLiBUaGlzIG1ldGhvZCBjYW4gYWxzbyBiZSB1c2VkIHRvIGRlZmluZSBhIGZlYXR1cmUgYmFzZWQgb24gdGhlIHJlZ3VsYXIgdGltZSBzZXJpZXMuIFRoZSBuZXcgbWV0aG9kIGJvcnJvd3MgdGhlIGlkZWEgb2YgdGhlIGZvcm11bGF0aW9uIG9mIHRoZSBwcm9jZXNzIGNhcGFiaWxpdHkgaW5kZXggaW4gc3RhdGlzdGljYWwgcHJvY2VzcyBhbmQgcXVhbGl0eSBjb250cm9sLg0KDQojIyBGZWF0dXJlIEV4dHJhY3Rpb24gd2l0aCBUaW1lIFNlcmllcw0KDQpUaW1lIHNlcmllcyBkYXRhIGlzIGRhdGEgdGhhdCBpcyBjb2xsZWN0ZWQgYXQgZGlmZmVyZW50IHBvaW50cyBpbiB0aW1lLiBUaGlzIGlzIG9wcG9zZWQgdG8gY3Jvc3Mtc2VjdGlvbmFsIGRhdGEgd2hpY2ggb2JzZXJ2ZXMgaW5kaXZpZHVhbHMsIGNvbXBhbmllcywgZXRjLiBhdCBhIHNpbmdsZSBwb2ludCBpbiB0aW1lLg0KDQpCZWNhdXNlIGRhdGEgcG9pbnRzIGluIHRpbWUgc2VyaWVzIGFyZSBjb2xsZWN0ZWQgYXQgYWRqYWNlbnQgdGltZSBwZXJpb2RzIHRoZXJlIGlzIHBvdGVudGlhbCBmb3IgY29ycmVsYXRpb24gYmV0d2VlbiBvYnNlcnZhdGlvbnMuIFRoaXMgaXMgb25lIG9mIHRoZSBmZWF0dXJlcyB0aGF0IGRpc3Rpbmd1aXNoZXMgdGltZS1zZXJpZXMgZGF0YSBmcm9tIGNyb3NzLXNlY3Rpb25hbCBkYXRhLg0KDQpUaW1lIHNlcmllcyBkYXRhIGNhbiBiZSBmb3VuZCBpbiBlY29ub21pY3MsIHNvY2lhbCBzY2llbmNlcywgZmluYW5jZSwgZXBpZGVtaW9sb2d5LCBhbmQgdGhlIHBoeXNpY2FsIHNjaWVuY2VzLiANCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zLCBmaWcuY2FwPSJGaWd1cmUgNC4gSWxsdXN0cmF0aW9uIG9mIHRpbWVzIHBhdHRlcm5zLiJ9DQppbmNsdWRlX2dyYXBoaWNzKCJpbWcvdzEwLVdoYXQtaXMtVFMuanBnIikNCmBgYA0KDQpUaGVyZSBhcmUgdHdvIG1haW4gZ29hbHMgb2YgdGltZSBzZXJpZXMgYW5hbHlzaXM6IGlkZW50aWZ5aW5nIHRoZSBuYXR1cmUgb2YgdGhlIHBoZW5vbWVub24gcmVwcmVzZW50ZWQgYnkgdGhlIHNlcXVlbmNlIG9mIG9ic2VydmF0aW9ucywgYW5kIGZvcmVjYXN0aW5nIChwcmVkaWN0aW5nIGZ1dHVyZSB2YWx1ZXMgb2YgdGhlIHRpbWUgc2VyaWVzIHZhcmlhYmxlKS4gIA0KDQojIyMgU3RhdGlzdGljYWwgTW9kZWxzDQoNClRoZSBtb3N0IGNvbW1vbiBhbmQgZWZmZWN0aXZlIHN0YXRpc3RpY2FsIG1ldGhvZHMgb2YgRm9yZWNhc3RpbmcgYXJlIFNpbXBsZSBNb3ZpbmcgQXZlcmFnZSAoU01BKSwgRXhwb25lbnRpYWwgU21vb3RoaW5nIChTRVMpLCBBdXRvLXJlZ3Jlc3NpdmUgSW50ZWdyYXRpb24gTW92aW5nIEF2ZXJhZ2UgKEFSSU1BKS4NCg0KV2Ugd2lsbCBub3QgZGlzY3VzcyB0aGVzZSBtZXRob2RzIGluIHRoaXMgbm90ZSBidXQgd2lsbCBpbnRyb2R1Y2UgdGhlIGV4cG9uZW50aWFsIHNtb290aGluZyBtZXRob2QgZm9yIHRoZSB0aW1lIHNlcmllcyBuZXh0IHdlZWsuDQoNCiMjIyBNYWNoaW5lIExlYXJuaW5nIEFsZ29yaXRobXMNCg0KT25lIG9mIHRoZSBtb3N0IGltcG9ydGFudCBwcm9wZXJ0aWVzIGFuIGFsZ29yaXRobSBuZWVkcyBpbiBvcmRlciB0byBiZSBjb25zaWRlcmVkIGEgdGltZS1zZXJpZXMgYWxnb3JpdGhtIGlzIHRoZSBhYmlsaXR5IHRvIGV4dHJhcG9sYXRlIHBhdHRlcm5zIG91dHNpZGUgb2YgdGhlIGRvbWFpbiBvZiB0cmFpbmluZyBkYXRhLiBNYW55IG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtcyBkbyBub3QgaGF2ZSB0aGlzIGNhcGFiaWxpdHksIGFzIHRoZXkgdGVuZCB0byBiZSByZXN0cmljdGVkIHRvIGEgZG9tYWluIHRoYXQgaXMgZGVmaW5lZCBieSB0cmFpbmluZyBkYXRhLiBUaGVyZWZvcmUsIHRoZXkgYXJlIG5vdCBzdWl0ZWQgZm9yIHRpbWUgc2VyaWVzLCBhcyB0aGUgb2JqZWN0aXZlIG9mIHRpbWUgc2VyaWVzIGlzIHRvIHByb2plY3QgaW50byB0aGUgZnV0dXJlLg0KDQpBbm90aGVyIGltcG9ydGFudCBwcm9wZXJ0eSBvZiBhIHRpbWUgc2VyaWVzIGFsZ29yaXRobSBpcyB0aGUgYWJpbGl0eSB0byBkZXJpdmUgY29uZmlkZW5jZSBpbnRlcnZhbHMuIFdoaWxlIHRoaXMgaXMgYSBkZWZhdWx0IHByb3BlcnR5IG9mIHRpbWUgc2VyaWVzIG1vZGVscywgbW9zdCBtYWNoaW5lIGxlYXJuaW5nIG1vZGVscyBkbyBub3QgaGF2ZSB0aGlzIGFiaWxpdHkgYmVjYXVzZSB0aGV5IGFyZSBub3QgYWxsIGJhc2VkIG9uIHN0YXRpc3RpY2FsIGRpc3RyaWJ1dGlvbnMuIA0KDQpUaGVyZSBhcmUgYWxzbyBtYWNoaW5lIGxlYXJuaW5nIG1vZGVscyBzdWNoIGFzIG5ldXJhbCBuZXR3b3JrIG1vZGVscyB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIHRpbWUgc2VyaWVzIHdoaWNoIHVzZSBgbGFnZ2VkIHByZWRpY3RvcnNgIGFuZCBjYW4gaGFuZGxlIGBleHRyYWN0ZWQgZmVhdHVyZXNgLCBzdWNoIGFzIE5ldXJhbCBOZXR3b3JrcyBBdXRvcmVncmVzc2lvbiAoTk5BUikuIFRoZXJlIGFyZSBldmVuIHRpbWUtc2VyaWVzIG1vZGVscyBib3Jyb3dlZCBmcm9tIGRlZXAgbGVhcm5pbmcsIHNwZWNpZmljYWxseSBpbiB0aGUgUk5OIChSZWN1cnJlbnQgTmV1cmFsIE5ldHdvcmspIGZhbWlseS4gIFRoZSBmb2xsb3dpbmcgZmlndXJlIHNob3dzIGhvdyB0byB1c2UgZXh0cmFjdGVkIGZlYXR1cmVzIGluIGEgbmV1cmFsIG5ldHdvcmsgbW9kZWwgZm9yIGZvcmVjYXN0aW5nLiANCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD0zLCBmaWcuaGVpZ2h0PTMsIGZpZy5jYXA9IkZpZ3VyZSA1LiBIb3cgdG8gQU5OIHRvIG1vZGVsIHRpbWUgc2VyaWVzLiJ9DQppbmNsdWRlX2dyYXBoaWNzKCJpbWcvdzEwLUFOTi1UUy5qcGciKQ0KYGBgDQoNCg0KIyMjIEZlYXR1cmUgRXh0cmFjdGlvbiBmb3IgVGltZSBTZXJpZXMNCg0KU2luY2UgdGhlIG1hY2hpbmUgbGVhcm5pbmcgbWV0aG9kIGNhbiBpbmNvcnBvcmF0ZSBib3RoIGxhZ2dlZCBwcmVkaWN0b3JzIGFuZCBhZGRpdGlvbmFsIGZlYXR1cmVzIHRvIGltcHJvdmUgdGhlIGZvcmVjYXN0IGFjY3VyYWN5LCB3ZSBjYW4gZXh0cmFjdCBzb21lIGZlYXR1cmVzIGZyb20gdGhlIHVuZGVybHlpbmcgZmVhdHVyZXMuIFRoZSBmb2xsb3dpbmcgZmlndXJlIGlsbHVzdHJhdGVzIHRoZSBwcm9jZXNzIG9mIGhvdyB0byBleHRyYWN0IGZlYXR1cmVzIGZyb20gdGltZS1zZXJpZXMgZGF0YS4NCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zLCBmaWcuY2FwPSJGaWd1cmUgNi4gSG93IHRvIGV4dHJhY3QgZmVhdHVyZXMgZnJvbSB0aW1lIHNlcmllcy4ifQ0KaW5jbHVkZV9ncmFwaGljcygiaW1nL3cxMC1TZXJpYWwtRmVhdHVyZS1FeHRyYWN0aW9uLmpwZyIpDQpgYGANCg0KQXMgc2hvd24gaW4gdGhlIGFib3ZlIGZpZ3VyZSwgdGhyZWUgdHlwZXMgb2YgZmVhdHVyZXMgY2FuIGJlIGV4dHJhY3RlZCBmcm9tIHRpbWUtc2VyaWVzIGRhdGEuDQoNCiogKipUZW1wb3JhbCBmZWF0dXJlcyAodGltZS1kb21haW4gZmVhdHVyZXMpKiogYXJlIHNpbXBsZSB0byBleHRyYWN0IGFuZCBoYXZlIGFuIGVhc3kgcGh5c2ljYWwgaW50ZXJwcmV0YXRpb24uIA0KDQoqICoqU3RhdGlzdGljYWwgZmVhdHVyZXMqKiBhcmUgbWFpbmx5IGRlc2NyaXB0aXZlIHN0YXRpc3RpY3Mgc3VjaCBhcyB3aW5kb3dlZCBtZWFuLCBtZWRpYW4sIHNrZXduZXNzLCBldGMuIA0KDQoqICoqU3BlY3RyYWwgZmVhdHVyZXMgKGZyZXF1ZW5jeS1iYXNlZCBmZWF0dXJlcykqKiBhcmUgb2J0YWluZWQgYnkgY29udmVydGluZyB0aGUgdGltZS1iYXNlZCBzaWduYWwgaW50byB0aGUgZnJlcXVlbmN5IGRvbWFpbi4gDQoNClRoZXNlIGZlYXR1cmVzIGFyZSBkZXNjcmlwdGl2ZSBhbmQgY2FuIGJlIGVhc2lseSBhdXRvbWF0ZWQuIFNvbWUgc29mdHdhcmUgcHJvZ3JhbXMgaGF2ZSBiZWVuIG1hZGUgdG8gZXh0cmFjdCB0aGVzZSB0eXBlcyBvZiBmZWF0dXJlcyBhdXRvbWF0aWNhbGx5IGluIHByYWN0aWNlLg0KDQoNCiMjIE1vZGVsLWJhc2VkIEZlYXR1cmUgRXh0cmFjdGlvbiB3aXRoIFBhbmVsIERhdGENCg0KVGhpcyBzdWJzZWN0aW9uIGZvY3VzZXMgb24gYSBuZXcgZmVhdHVyZSBleHRyYWN0aW9uIG1ldGhvZCB0aGF0IGV4dHJhY3RzIGluZm9ybWF0aW9uIGJhc2VkIG9uIG1vZGVscyBhbmQgYWxnb3JpdGhtcyBmcm9tIHNlcXVlbnRpYWwgZGF0YS4gVGhlIGFsZ29yaXRobSBib3Jyb3dzIHRoZSBpZGVhIG9mIG1lYXN1cmluZyB0aGUgcHJvY2VzcyBpbmZvcm1hdGlvbiAoc3VjaCBhcyBjYXBhYmlsaXR5IGFuZCBxdWFsaXR5KSB0aHJvdWdoIHRoZSBzZXF1ZW5jZSBkYXRhIGdlbmVyYXRlZCBieSB0aGUgcHJvY2Vzcy4gDQoNClNpbmNlIHRoaXMgaXMgYSBtb2RlbC1iYXNlZCBhbGdvcml0aG0sIGl0IGlzIG1vcmUgcG93ZXJmdWwgdGhhbiB0aG9zZSBmZWF0dXJlcyBleHRyYWN0ZWQgZnJvbSB0aGUgdGltZSBzZXJpZXMgZGlzY3Vzc2VkIGluIHRoZSBwcmV2aW91cyBzdWJzZWN0aW9uLg0KDQojIyMgQ29uY2VwdHMgUHJvY2VzcyBDYXBhYmlsaXR5IGFuZCBDb250cm9sIENoYXJ0DQoNClByb2Nlc3MgY29udHJvbCBpcyB0aGUgYWJpbGl0eSB0byBtb25pdG9yIGFuZCBhZGp1c3QgYSBwcm9jZXNzIHRvIGdpdmUgdGhlIGRlc2lyZWQgb3V0cHV0LiBJdCBpcyB1c2VkIGluIHRoZSBpbmR1c3RyeSB0byBtYWludGFpbiBxdWFsaXR5IGFuZCBpbXByb3ZlIHBlcmZvcm1hbmNlLiBLZXkgdG9vbHMgaW4gcHJvY2VzcyBjb250cm9sIGluY2x1ZGUgY29udHJvbCBjaGFydCwgcHJvY2VzcyBjYXBhYmlsaXR5IGluZGV4LCBldGMuDQoNCkJvdGggY29udHJvbCBjaGFydCBhbmQgcHJvY2VzcyBjYXBhYmlsaXR5IGluZGV4IHVzZSB0aGUgc2FtZSBrZXkgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSB1bmRlcmx5aW5nIHByb2Nlc3MgaW4gdGhlaXIgY29uc3RydWN0aW9uOg0KDQoqICoqU3BlY2lmaWNhdGlvbiBsaW1pdHMqKiBjYW4gYmUgZGVmaW5lZCBhcyB0YXJnZXRzIHRoYXQgYXJlIHNldCBmb3IgYSBwYXJ0aWN1bGFyIHByb2Nlc3Mgb3IgYSBwcm9kdWN0IGVpdGhlciBieSB0aGUgY3VzdG9tZXIgb3IgYmFzZWQgb24gdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSBtYXJrZXQuIEluIG90aGVyIHdvcmRzLCBpdCBjYW4gYWxzbyBiZSBkZWZpbmVkIGFzIGEgcmVzdWx0IHRoYXQgaXMgZXhwZWN0ZWQgZnJvbSBhIHBhcnRpY3VsYXIgbWV0cmljLiBTcGVjaWZpY2F0aW9uIGxpbWl0cyBhcmUgc2V0IGJ5IGN1c3RvbWVycyBvciB0aGUgbWFuYWdlbWVudC4NCg0KKiAqKkNvbnRyb2wgbGltaXRzKiogb24gdGhlIG90aGVyIGhhbmQgaGVscCBpbiBpbmRpY2F0aW5nIHRoZSBjaGFuZ2VzIHdoaWNoIG9jY3VyIGluIHRoZSBwZXJmb3JtYW5jZSBvZiBhIHBhcnRpY3VsYXIgcHJvY2Vzcy4gQ29udHJvbCBsaW1pdHMgYWxzbyBwcm92aWRlIHJlYWwtdGltZSB2YWx1ZS4gQ29udHJvbCBsaW1pdHMgYXJlIGRlcGVuZGVudCBvbiB0aGUgdW5kZXJseWluZyBwcm9jZXNzLg0KDQpDb250cm9sIGxpbWl0cyBjYW4gYmUgZWl0aGVyIHVwcGVyIGNvbnRyb2wgbGltaXQgKFVDTCkgb3IgbG93ZXIgY29udHJvbCBsaW1pdCAoTENMKS4gU2ltaWxhcmx5LCBzcGVjaWZpY2F0aW9uIGxpbWl0cyBjYW4gYmUgZWl0aGVyIHVwcGVyIHNwZWNpZmljYXRpb24gbGltaXQgKFVTTCkgb3IgbG93ZXIgc3BlY2lmaWNhdGlvbiBsaW1pdCAoTFNMKS4NCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zLCBmaWcuY2FwPSJGaWd1cmUgNy4gU3RydWN0dXJlIG9mIGEgY29udHJvbCBjaGFydC4ifQ0KaW5jbHVkZV9ncmFwaGljcygiaW1nL3cxMC1jb250cm9sLXNwZWMtbGltaXRzLmpwZyIpDQpgYGANCg0KKipVbmRlcnN0YW5kaW5nIHRoZSBjb250cm9sIGNoYXJ0KiogDQoNClNldmVyYWwgY29uY2VwdHMgd2lsbCBiZSB1c2VkIGluIHRoZSBkZWZpbml0aW9uIG9mIHRoZSBwcm9jZXNzIGNhcGFiaWxpdHkgaW5kZXguDQoNCkNvbnRyb2wgY2hhcnRzIGFyZSBvbmUgb2YgdGhlIG1vc3QgcG9wdWxhciBTUEMgdG9vbHMgdXNlZCBieSBtYW51ZmFjdHVyZXJzLiBUaGV5IGFyZSB1c2VkIHRvIGRldGVybWluZSAqKndoZXRoZXIgYSBwcm9jZXNzIGlzIGluLSBvciBvdXQtb2YtY29udHJvbCoqLg0KDQpXaGVuIHBvaW50cyBvbiBhIGNvbnRyb2wgY2hhcnQgbW92ZSBvdXRzaWRlIHRoZSB1cHBlciBvciBsb3dlciBjb250cm9sIGxpbWl0LCB0aGUgcHJvY2VzcyBhcmUgc2FpZCB0byBiZSAqKuKAnG91dC1vZi1jb250cm9sLuKAnSoqIEFzIGxvbmcgYXMgdGhlIHBvaW50cyBhcmUgd2l0aGluIGNvbnRyb2wgbGltaXRzLCB0aGUgcHJvY2VzcyBpcyAqKuKAnGluLWNvbnRyb2zigJ0qKi4gQW4gKipvdXQtb2YtY29udHJvbCBwcm9jZXNzKiogY291bGQgcHJvZHVjZSBkZWZlY3RpdmUgcGFydHMuIEhvd2V2ZXIsIGlmIGEgcG9pbnQgaXMgb3V0c2lkZSB0aGUgKipzcGVjaWZpY2F0aW9uIGxpbWl0cyoqLCB0aGUgcHJvY2VzcyBwcm9kdWNlcyBkZWZlY3RpdmUgcHJvZHVjdHMuIA0KDQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTMsIGZpZy5oZWlnaHQ9MywgZmlnLmNhcD0iRmlndXJlIDguIEluLWNvbnRyb2wgYW5kIG91dC1vZi1jb250cm9sIHByb2Nlc3Nlcy4ifQ0KaW5jbHVkZV9ncmFwaGljcygiaW1nL3cxMC1jb250cm9sLWNoYXJ0LmpwZyIpDQpgYGANCg0KQ29udHJvbCBjaGFydHMgYXJlIHZpc3VhbCB0b29scyBmb3IgbW9uaXRvcmluZyB0aGUgcHJvY2VzcyBjYXBhYmlsaXR5LiBXaXRoIGEgY29udHJvbCBjaGFydCwgd2UgY2FuIHNlZSB0aGUgcG90ZW50aWFsIHNoaWZ0IG9mIHByb2Nlc3MgbWVhbiBhbmQgdmFyaWF0aW9uIGF0IHRoZSBzYW1lIHRpbWUuIEEgbnVtZXJpY2FsIG1lYXN1cmUgdGhhdCBjYW4gYmUgZGVmaW5lZCB0byBjYXB0dXJlIGJvdGggYWZvcmVtZW50aW9uZWQgc2hpZnRzIG9mIGEgcHJvY2VzcyBpbiBhIHNpbmdsZSBudW1iZXIgaXMgdGhlIHByb2Nlc3MgY2FwYWJpbGl0eSBpbmRleCAoUENJKS4NCg0KIyMjIENvbmNlcHQgb2YgUHJvY2VzcyBDYXBhYmlsaXR5IEluZGV4IChQQ0kpDQoNClByb2Nlc3MgY2FwYWJpbGl0eSBpbmRleCBtZWFzdXJlcyB0aGUgZGVncmVlIG9mIHZhcmlhdGlvbiBhbiBpbi1jb250cm9sIHByb2Nlc3MgZXhwZXJpZW5jZXMgcmVsYXRpdmUgdG8gaXRzIHNwZWNpZmljYXRpb24gbGltaXRzLiBJdCBjYW4gYWxzbyBiZSB1c2VkIHRvIGNvbXBhcmUgZGlmZmVyZW50IHByb2Nlc3NlcyB3aXRoIHJlc3BlY3QgdG8gdGhlIG9wdGltYWwgc2l0dWF0aW9uIG9yIGlmIHRoZXkgY29tZSB1cCB0byBvdXIgZXhwZWN0YXRpb25zLiANCg0KVGhlIGZpcnN0IHByb2Nlc3MgY2FwYWJpbGl0eSBpbmRleCBpcyBkZWZpbmVkIGJ5ICRDX3AkLCANCg0KJCQNCkNfcCA9IFxmcmFje1VTTC1MU0x9ezZcc2lnbWF9DQokJA0KDQp3aGljaCBpcyBhbiBlc3RpbWF0ZSBvZiB3aGF0IHRoZSBwcm9jZXNzIGlzIGNhcGFibGUgb2YgcHJvZHVjaW5nIGlmIHRoZSBwcm9jZXNzIG1lYW4gd2VyZSB0byBiZSBjZW50ZXJlZCBiZXR3ZWVuIHRoZSBzcGVjaWZpY2F0aW9uIGxpbWl0cywgYXNzdW1pbmcgdGhhdCB0aGUgcHJvY2VzcyBvdXRwdXQgaXMgYXBwcm94aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRlZC4gVGhpcyBmaXJzdCAkQ19wJCB3YXMgaW52ZW50ZWQgYW5kIHVzZWQgaW4gdGhlIEphcGFuZXNlIHNlbWljb25kdWN0b3IgaW5kdXN0cnkgaW4gdGhlIDE5NzBzLiANCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zLCBmaWcuY2FwPSJGaWd1cmUgOS4gRmlyc3QgYW5kIHNlY29uZCBnZW5lcmF0aW9uIFBDSXMuIn0NCmluY2x1ZGVfZ3JhcGhpY3MoImltZy93MTAtMXN0LTJuZC1nZW5lcmF0aW9uLVBDSXMuanBnIikNCmBgYA0KDQoNClNpbmNlICRDX3AkIGRvZXMgbm90IGNvbnNpZGVyIHByb2Nlc3MgbWVhbnMgYW5kIHByb2Nlc3MgdGFyZ2V0LCBzZXZlcmFsIG1ham9yIGZhbWlsaWVzIG9mIFBDSXMgd2VyZSBkZWZpbmVkIGFmdGVyICRDX3AkLiBUaGUgZm9sbG93aW5nIHRhYmxlIGxpc3RzIG1ham9yIFBDSXMgdXNlZCBpbiB0aGUgaW5kdXN0cnkgZm9yIHZhcmlvdXMgcHVycG9zZXMuDQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTMsIGZpZy5oZWlnaHQ9M30NCmluY2x1ZGVfZ3JhcGhpY3MoImltZy93MTAtbGlzdC1vZi1QQ0lzLmpwZyIpDQpgYGANCg0KSW4gdGhlIG1hbnVmYWN0dXJpbmcgaW5kdXN0cnksIFBDSXMgYXJlIHVzZWQgdG8gbWVhc3VyZSB0aGUgcXVhbGl0eSBvZiBhIHByb2Nlc3MgKHByb2R1Y3QpLCBVU0wsIGFuZCBMU0wgYW5kIFQgKHRhcmdldCkgYXJlIGdpdmVuIGJ5IGN1c3RvbWVycyBvciB0aGUgbWFuYWdlbWVudC4gV2hlbiBhcHBseWluZyBQQ0kgaW4gb3RoZXIgZmllbGRzIHN1Y2ggYXMgZnJhdWQgZGV0ZWN0aW9uLCBVU0wsIExTTCBhbmQgVCBhcmUgbm90IGdpdmVuLCB3ZSBuZWVkIHRvIGZpZ3VyZSBvdXQgYSB3YXkgdG8gb2J0YWluIHJlYXNvbmFibGUgVVNMLCBMU0wsIGFuZCBUIGluIG9yZGVyIHRvIGRlZmluZSB0aGUgUENJLiBUaGUgbmV4dCBzdWJzZWN0aW9uIGV4cGxhaW5zIHRoZSBpZGVhIG9mIHVzaW5nIFBDSSB0byBkZWZpbmUgZnJhdWQgaW5kZXguDQoNCiMjIyBGcmFtZXdvcmsgb2YgRnJhdWQgSW5kZXggQmFzZWQgb24gUENJDQoNCldlIGNhbiBjb25zaWRlciBhIGNyZWRpdCBjYXJkIGFzICoqYSBwcm9jZXNzKiogdGhhdCBwcm9kdWNlcyB0cmFuc2FjdGlvbnMuIFRoaXMgcHJvY2VzcyBjaGFyYWN0ZXJpemVzIHRoZSBjYXJkIGhvbGRlcidzIHNwZW5kaW5nIGJlaGF2aW9yLiBGb3IgYW4gZXN0YWJsaXNoZWQgY3JlZGl0IGNhcmQgYWNjb3VudCwgd2UgY2FuIHNlZ21lbnQgdGhlIHNwZW5kaW5nIGluIGRpZmZlcmVudCBzdWJjYXRlZ29yaWVzIGFuZCBkZWZpbmUgZGlmZmVyZW50IHN1Yi1wcm9jZXNzZXMuIEEgUENJIGNhbiBiZSBkZWZpbmVkIGZvciBlYWNoIHN1Yi1wcm9jZXNzLiBUaGUgcXVlc3Rpb24gaXMgdGhhdCB0aGVyZSBhcmUgbm8gc3BlY2lmaWNhdGlvbiBsaW1pdHMgc2V0IHRvIHRoZXNlIHR5cGVzIG9mICJwcm9jZXNzZXMiLiBXZSBuZWVkIHRvIHVzZSBoaXN0b3JpY2FsIGRhdGEgdG8gb2J0YWluIG9wdGltYWwgc3BlY2lmaWNhdGlvbiBsaW1pdHMgaW4gb3JkZXIgdG8gZGVmaW5lIHF1YWxpdHkgUENJcy4NCg0KVGhlIGZvbGxvd2luZyBjaGFydCBleHBsYWlucyB0aGUgaWRlYSBvZiBob3cgdG8gZGVmaW5lIFBDSSBmb3IgYSBwcm9jZXNzIHdpdGhvdXQgYmVpbmcgZ2l2ZW4gcHJlLXNldCBwcm9jZXNzIGxpbWl0cy4NCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD0zLCBmaWcuaGVpZ2h0PTMsIGZpZy5jYXA9IkZpZ3VyZSAxMC4gSWxsdXN0cmF0aW9uIG9mIGRlZmluaW5nIFBDSSBvZiBhIHByb2Nlc3Mgd2l0aG91dCBnaXZlbiBwcm9jZXNzIGxpbWl0cyJ9DQppbmNsdWRlX2dyYXBoaWNzKCJpbWcvdzEwLVJvbGxpbmctUENJcy5qcGciKQ0KYGBgDQoNClNpbmNlIGZyYXVkIGRldGVjdGlvbiBpcyBhIHJlYWwtdGltZSBwcm9jZXNzLCB0aGUgZnJhdWQgaW5kZXggbXVzdCBhbHNvIGJlIGRlZmluZWQgaW4gcmVhbC10aW1lLiBUaGUgYWJvdmUgZXhwbGFpbnMgaG93IHJlYWwtdGltZSBQQ0kgY2FuIGJlIGRlZmluZWQuIFRoZSBQQ0kgZGVmaW5lZCBpbiB0aGUgYWJvdmUgaWxsdXN0cmF0aW9uIGlzIGEgcm9sbGluZyBQQ0kgc2luY2UgaXRzIHNwZWNpZmljYXRpb24gbGltaXRzIGFyZSBjaGFuZ2luZyBvdmVyIHRpbWUuIFRoZSBzcGVjaWZpY2F0aW9uIGxpbWl0cyBjYW4gYWxzbyBiZSBzZXQgYXMgaHlwZXJwYXJhbWV0ZXJzLiBXZSBjYW4gdGhlbiBzZWFyY2ggZm9yIG9wdGltYWwgaHlwZXJwYXJhbWV0ZXJzIHRvIGRlZmluZSBvcHRpbWFsIFBDSSBmb3IgZnJhdWQgZGV0ZWN0aW9uLiANCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=