Last updated: July 15 2023

Description of Example

The SF-36 questionnaire measures self-reported functional status. Its 36 items are combined to form 8 subscales yielding two summary measures: physical and mental health.

The physical health measure includes four subscales: physical functioning (10 items), role-physical (4 items), bodily pain (2 items), and general health (5 items).
The mental health measure includes the other four subscales: vitality (4 items), social functioning (2 items), role-emotional (3 items), and mental health (5 items).
This example uses data from 249 women (age 31 to 87, median 64) who completed the SF-36 following heart surgery. The subscale variable names are: MENHLTH, SOCFUNC, ROLEEMO, VITAL, PHSFUNC, ROLPHYS, BODPAIN, and GENHLTH.
First, an Exploratory Factor Analysis with 2 uncorrelated factors is run using the psych package in which each subscale loads on both factors.
Second, a Confirmatory Factor Analysis with 2 correlated factors is run using the lavaan package in which each subscale loads on only one hypothesized factor.

Setup

Required Packages

knitr::opts_chunk$set(error = TRUE, message = FALSE, warning = TRUE)

library(rio)
library(readr)
library(here)
library(dplyr)
library(lavaan)
library(psych)
library(semoutput)
library(semPlot)
library(sjPlot)
library(GPArotation)
library(semTools)

Import Data

## Import Data
hrtsrg <- rio::import("C:/Users/jbeckste/Desktop/WOMEN_HRTSRG_noLabels.SAV")
attach(hrtsrg)
data <- data.frame(MENHLTH, SOCFUNC, ROLEEMO, VITAL,   PHSFUNC, ROLPHYS, BODPAIN, GENHLTH)

Descriptives

# Prints basic descriptive statistics
sem_descriptives(data)
Descriptive Statistics
Variable n Mean SD min max Skewness Kurtosis % Missing
MENHLTH 249 18.09 4.43 6 25 -0.68 -0.18 0
SOCFUNC 249 7.15 2.17 2 10 -0.34 -0.74 0
ROLEEMO 249 10.59 3.44 3 15 -0.31 -0.87 0
VITAL 249 11.30 3.34 4 20 -0.16 -0.48 0
PHSFUNC 249 19.69 4.93 10 30 0.17 -0.81 0
ROLPHYS 249 10.83 3.88 4 20 0.23 -0.44 0
BODPAIN 249 7.21 2.38 2 12 0.20 -0.45 0
GENHLTH 249 16.44 4.03 7 25 -0.13 -0.68 0

Total N = 249

Correlation Matrix

Bivariate Summary Display

Histograms are shown on the diagonal, scatterplots showing bivariate regression line and centroid are below the diagnonal, correlations are above the diagonal.

psych::pairs.panels(data, lm=T, cex.cor=.7, jiggle=T, factor=3,
                    show.points = T, ellipses=T, pch=".")

Heatmap

Larger correlations are more darkly shaded. Ideally, subscales within each measure should show stronger correlations than subscales from different measures.

#makes heatmap of corr mtx; SORT df first based on FA
psych::cor.plot(data, pval=F,diag=T, scale=F, show.legend=F, upper=F, n=51,
                main="", cex=.8, xlas=2)

Nice Table

# Uses sjPlot to print a nice looking correlation table
tab_corr(data, na.deletion = "listwise", digits = 2, triangle = "lower",
         title="Correlations among SF-36 Scales",
         string.diag=c('1','1','1','1','1','1','1','1'))
Correlations among SF-36 Scales
  MENHLTH SOCFUNC ROLEEMO VITAL PHSFUNC ROLPHYS BODPAIN GENHLTH
MENHLTH 1              
SOCFUNC 0.60*** 1            
ROLEEMO 0.63*** 0.55*** 1          
VITAL 0.58*** 0.58*** 0.42*** 1        
PHSFUNC 0.20** 0.40*** 0.31*** 0.43*** 1      
ROLPHYS 0.35*** 0.51*** 0.53*** 0.48*** 0.55*** 1    
BODPAIN 0.34*** 0.45*** 0.33*** 0.36*** 0.46*** 0.45*** 1  
GENHLTH 0.51*** 0.48*** 0.39*** 0.54*** 0.36*** 0.34*** 0.34*** 1
Computed correlation used pearson-method with listwise-deletion.

EFA Results

Based on the scree plot below, a 2-factor solution seems reasonable. This plot was generated by psych::VSS.scree

efa_data <- data
## Determine the number of factors to extract by inspection of scree plot
psych::VSS.scree(efa_data)

## Conduct EFA analysis with 2 factors determined from scree plot
efa_fit <- psych::fa(efa_data, fm = "ml", nfactors = 2, rotate = "varimax")

Summary Output

efa_method(efa_fit)
Extraction Method
Sample.Size Method Factors.Extracted Rotation
249 ml 2 Varimax
efa_var(efa_fit)
Total Variance Explained
Factor Eigenvalue Proportion Var Cumulative Var
ML1 2.391 0.299 0.299
ML2 2.030 0.254 0.553
efa_loadings(efa_fit)
Factor Loadings
Factors
Variable ML1 ML2 h2
MENHLTH 0.956 0.094 0.923
SOCFUNC 0.580 0.487 0.574
ROLEEMO 0.622 0.351 0.510
VITAL 0.558 0.461 0.523
PHSFUNC 0.133 0.735 0.558
ROLPHYS 0.297 0.702 0.581
BODPAIN 0.293 0.532 0.369
GENHLTH 0.501 0.365 0.384
efa_rotmatrix(efa_fit)
Factor Rotation Matrix
Factor 1 2
1 0.946 0.324
2 -0.324 0.946

Diagram Output

psych::fa.diagram(efa_fit, cut=.01, simple=F, adj=2, digits=2,
                  main="Exploratory Factor Analysis using ML")

Full Output

efa_fit
## Factor Analysis using method =  ml
## Call: psych::fa(r = efa_data, nfactors = 2, rotate = "varimax", fm = "ml")
## Standardized loadings (pattern matrix) based upon correlation matrix
##          ML1  ML2   h2    u2 com
## MENHLTH 0.96 0.09 0.92 0.077 1.0
## SOCFUNC 0.58 0.49 0.57 0.426 1.9
## ROLEEMO 0.62 0.35 0.51 0.490 1.6
## VITAL   0.56 0.46 0.52 0.477 1.9
## PHSFUNC 0.13 0.73 0.56 0.442 1.1
## ROLPHYS 0.30 0.70 0.58 0.419 1.3
## BODPAIN 0.29 0.53 0.37 0.631 1.6
## GENHLTH 0.50 0.36 0.38 0.616 1.8
## 
##                        ML1  ML2
## SS loadings           2.39 2.03
## Proportion Var        0.30 0.25
## Cumulative Var        0.30 0.55
## Proportion Explained  0.54 0.46
## Cumulative Proportion 0.54 1.00
## 
## Mean item complexity =  1.5
## Test of the hypothesis that 2 factors are sufficient.
## 
## df null model =  28  with the objective function =  3.43 with Chi Square =  838.42
## df of  the model are 13  and the objective function was  0.17 
## 
## The root mean square of the residuals (RMSR) is  0.04 
## The df corrected root mean square of the residuals is  0.06 
## 
## The harmonic n.obs is  249 with the empirical chi square  20.96  with prob <  0.074 
## The total n.obs was  249  with Likelihood Chi Square =  41.84  with prob <  7e-05 
## 
## Tucker Lewis Index of factoring reliability =  0.923
## RMSEA index =  0.094  and the 90 % confidence intervals are  0.063 0.127
## BIC =  -29.89
## Fit based upon off diagonal values = 0.99
## Measures of factor score adequacy             
##                                                    ML1  ML2
## Correlation of (regression) scores with factors   0.96 0.88
## Multiple R square of scores with factors          0.92 0.77
## Minimum correlation of possible factor scores     0.84 0.54

CFA in LISREL Notation

The goal of CFA is to reproduce the covariance matrix, \(\mathbf\Sigma\), among the observed variables. This is done using a hypothesized model that consists of three types of parameters contained in three matrices:

\[ \mathbf{\Sigma^* = \Lambda_x \Phi \Lambda'_x + \Theta_\delta} \] where \(\mathbf\Sigma^*\) is the estimated covariance matrix among the eight subscales, \(\mathbf\Lambda_x\) is a matrix of factor loadings, \(\mathbf\Phi\) is the covariance matrix of the latent variables (factors), and \(\mathbf\Theta_\delta\) is a matrix of measurement error variances.

Here is the \(\mathbf\Lambda_x\) for our model of the SF-36 subscales:

\[\mathbf\Lambda_x = \begin{bmatrix} \lambda_{1,1} & 0\\ \lambda_{2,1} & 0\\ \lambda_{3,1} & 0\\ \lambda_{4,1} & 0\\ 0 & \lambda_{5,2}\\ 0 & \lambda_{6,2}\\ 0 & \lambda_{7,2}\\ 0 & \lambda_{8,2}\\ \end{bmatrix} \] The rows correspond to the eight subscales and the columns to the two latent variables (MH and GH). Note the first four subscales load on the first factor (MH) and have zero loadings on the second factor (PH). The reverse pattern is true for the last four subscales.

Here is the \(\mathbf\Phi\) matrix for our model:

\[\mathbf\Phi = \begin{bmatrix} \phi_{1,1} & \phi_{1,2}\\ \phi_{2,1} & \phi_{2,2}\\ \end{bmatrix} \] with the factor variances on the diagonal and their covariance in the off-diagonal. Note that this is a symmetric matrix.

Finally, here is the \(\mathbf\Theta_\delta\) matrix for our model:

\[\mathbf\Theta_\delta = \begin{bmatrix} \theta_{1,1} & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 0 & \theta_{2,2} & 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & \theta_{3,3} & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & \theta_{4,4} & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & \theta_{5,5} & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & \theta_{6,6} & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0 & \theta_{7,7} & 0\\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & \theta_{8,8}\\ \end{bmatrix} \] Note that \(\mathbf\Theta_\delta\) is a diagonal matrix. This reflects our hypothesis that the measurement error terms for the subscales are uncorreleated (i.e., all off-diagonal elements are hypothesized to be zero).

CFA Results

Based on the results of the exploratory analysis, we decide to run a confirmatory model specifying that the first 4 subscales load on one factor and the last 4 subscales load on a second factor.

# specify the 2-factor CFA model
model <- '
# latent factors
MH =~  MENHLTH + SOCFUNC + ROLEEMO + VITAL
PH =~  PHSFUNC + ROLPHYS + BODPAIN + GENHLTH'
# fit the model
fit <- lavaan::cfa(model = model, data = data, mimic = "lavaan", 
           estimator = "ML", missing = "listwise", check.post=T,
           std.lv = TRUE, std.ov = FALSE, test = "standard", 
           se = "standard", bootstrap = 1000)

Summary Output

sem_tables(fit)
Model Significance
Sample.Size Chi.Square df p.value
249 125.511 19 0
Model Fit Measures
CFI RMSEA RMSEA.Lower RMSEA.Upper SRMR AIC BIC
0.871 0.15 0.126 0.176 0.07 9891.606 9951.403
Factor Loadings
Standardized
Latent Factor Indicator Loadings sig p Lower.CI Upper.CI SE z
MH MENHLTH 0.756 *** 0 0.690 0.822 0.034 22.416
MH SOCFUNC 0.798 *** 0 0.738 0.857 0.030 26.228
MH ROLEEMO 0.711 *** 0 0.637 0.784 0.037 18.985
MH VITAL 0.730 *** 0 0.659 0.800 0.036 20.338
PH PHSFUNC 0.643 *** 0 0.553 0.732 0.046 14.080
PH ROLPHYS 0.728 *** 0 0.650 0.806 0.040 18.279
PH BODPAIN 0.618 *** 0 0.525 0.711 0.047 13.046
PH GENHLTH 0.607 *** 0 0.513 0.701 0.048 12.629
Latent Factor Correlations
Factor 1 Factor 2 r sig p Lower.CI Upper.CI SE
MH PH 0.846 *** 0 0.771 0.921 0.038

Diagram Output

factors <- fit@pta$vnames$lv[[1]]
size <- .65
semPaths(fit, latents = factors, whatLabels = "std", layout = "tree2", 
         rotation = 4, style = "lisrel", optimizeLatRes = TRUE, 
         structural = FALSE, layoutSplit = FALSE,
         intercepts = FALSE, residuals = T, 
         curve = 1, curvature = 3, nCharNodes = 8, 
         sizeLat = 11 * size, sizeMan = 11 * size, sizeMan2 = 4 * size, 
         edge.label.cex = 1.2 * size, 
         edge.color = "#000000", edge.label.position = .40)

Residual Correlation Matrix

The values below are the residual correlations (i.e., observed correlation - model estimated correlation). Note the largest residual is |-.21| for the correlation between MENHLTH & PHSFUNC. The average of these residuals is provided by the standarized root mean square residual (SRMR).

sem_residuals(fit)
MENHLTH SOCFUNC ROLEEMO VITAL PHSFUNC ROLPHYS BODPAIN GENHLTH
MENHLTH
SOCFUNC -0.01
ROLEEMO 0.10 -0.02
VITAL 0.03 0.00 -0.10
PHSFUNC -0.21 -0.03 -0.07 0.03
ROLPHYS -0.12 0.02 0.09 0.03 0.09
BODPAIN -0.06 0.03 -0.04 -0.02 0.06 0.0
GENHLTH 0.12 0.07 0.03 0.17 -0.03 -0.1 -0.04

Full Output

Summary

summary(fit, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6.15 ended normally after 22 iterations
## 
##   Estimator                                         ML
##   Optimization method                           NLMINB
##   Number of model parameters                        17
## 
##   Number of observations                           249
## 
## Model Test User Model:
##                                                       
##   Test statistic                               125.511
##   Degrees of freedom                                19
##   P-value (Chi-square)                           0.000
## 
## Model Test Baseline Model:
## 
##   Test statistic                               853.850
##   Degrees of freedom                                28
##   P-value                                        0.000
## 
## User Model versus Baseline Model:
## 
##   Comparative Fit Index (CFI)                    0.871
##   Tucker-Lewis Index (TLI)                       0.810
## 
## Loglikelihood and Information Criteria:
## 
##   Loglikelihood user model (H0)              -4928.803
##   Loglikelihood unrestricted model (H1)      -4866.048
##                                                       
##   Akaike (AIC)                                9891.606
##   Bayesian (BIC)                              9951.403
##   Sample-size adjusted Bayesian (SABIC)       9897.512
## 
## Root Mean Square Error of Approximation:
## 
##   RMSEA                                          0.150
##   90 Percent confidence interval - lower         0.126
##   90 Percent confidence interval - upper         0.176
##   P-value H_0: RMSEA <= 0.050                    0.000
##   P-value H_0: RMSEA >= 0.080                    1.000
## 
## Standardized Root Mean Square Residual:
## 
##   SRMR                                           0.070
## 
## Parameter Estimates:
## 
##   Standard errors                             Standard
##   Information                                 Expected
##   Information saturated (h1) model          Structured
## 
## Latent Variables:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##   MH =~                                                                 
##     MENHLTH           3.345    0.253   13.224    0.000    3.345    0.756
##     SOCFUNC           1.730    0.121   14.252    0.000    1.730    0.798
##     ROLEEMO           2.438    0.201   12.153    0.000    2.438    0.711
##     VITAL             2.436    0.193   12.596    0.000    2.436    0.730
##   PH =~                                                                 
##     PHSFUNC           3.160    0.307   10.308    0.000    3.160    0.643
##     ROLPHYS           2.818    0.234   12.046    0.000    2.818    0.728
##     BODPAIN           1.470    0.150    9.822    0.000    1.470    0.618
##     GENHLTH           2.442    0.254    9.617    0.000    2.442    0.607
## 
## Covariances:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##   MH ~~                                                                 
##     PH                0.846    0.038   22.119    0.000    0.846    0.846
## 
## Variances:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##    .MENHLTH           8.387    0.957    8.762    0.000    8.387    0.428
##    .SOCFUNC           1.713    0.214    8.013    0.000    1.713    0.364
##    .ROLEEMO           5.826    0.624    9.339    0.000    5.826    0.495
##    .VITAL             5.210    0.571    9.121    0.000    5.210    0.468
##    .PHSFUNC          14.202    1.515    9.375    0.000   14.202    0.587
##    .ROLPHYS           7.064    0.855    8.258    0.000    7.064    0.471
##    .BODPAIN           3.500    0.365    9.599    0.000    3.500    0.618
##    .GENHLTH          10.210    1.054    9.686    0.000   10.210    0.631
##     MH                1.000                               1.000    1.000
##     PH                1.000                               1.000    1.000

Standarized Parameter Estimates

standardizedSolution(fit)
##        lhs op     rhs est.std    se      z pvalue ci.lower ci.upper
## 1       MH =~ MENHLTH   0.756 0.034 22.416      0    0.690    0.822
## 2       MH =~ SOCFUNC   0.798 0.030 26.228      0    0.738    0.857
## 3       MH =~ ROLEEMO   0.711 0.037 18.985      0    0.637    0.784
## 4       MH =~   VITAL   0.730 0.036 20.338      0    0.659    0.800
## 5       PH =~ PHSFUNC   0.643 0.046 14.080      0    0.553    0.732
## 6       PH =~ ROLPHYS   0.728 0.040 18.279      0    0.650    0.806
## 7       PH =~ BODPAIN   0.618 0.047 13.046      0    0.525    0.711
## 8       PH =~ GENHLTH   0.607 0.048 12.629      0    0.513    0.701
## 9  MENHLTH ~~ MENHLTH   0.428 0.051  8.399      0    0.328    0.528
## 10 SOCFUNC ~~ SOCFUNC   0.364 0.049  7.504      0    0.269    0.459
## 11 ROLEEMO ~~ ROLEEMO   0.495 0.053  9.306      0    0.391    0.599
## 12   VITAL ~~   VITAL   0.468 0.052  8.930      0    0.365    0.570
## 13 PHSFUNC ~~ PHSFUNC   0.587 0.059 10.011      0    0.472    0.702
## 14 ROLPHYS ~~ ROLPHYS   0.471 0.058  8.128      0    0.357    0.584
## 15 BODPAIN ~~ BODPAIN   0.618 0.059 10.570      0    0.504    0.733
## 16 GENHLTH ~~ GENHLTH   0.631 0.058 10.815      0    0.517    0.746
## 17      MH ~~      MH   1.000 0.000     NA     NA    1.000    1.000
## 18      PH ~~      PH   1.000 0.000     NA     NA    1.000    1.000
## 19      MH ~~      PH   0.846 0.038 22.119      0    0.771    0.921

Residuals Analysis

Displays residual correlations and z-scores indicating the magnitude of the residuals. Typically, z values > |2.54| are interpreted as significant and indicate where the model is doing a poor job of reproducing the observed correlations. Note that the largest residual correlation and |z| is between MENHLTH & PHSFUNC.

lavResiduals(fit)
## $type
## [1] "cor.bentler"
## 
## $cov
##         MENHLT SOCFUN ROLEEM  VITAL PHSFUN ROLPHY BODPAI GENHLT
## MENHLTH  0.000                                                 
## SOCFUNC -0.007  0.000                                          
## ROLEEMO  0.096 -0.018  0.000                                   
## VITAL    0.026 -0.004 -0.097  0.000                            
## PHSFUNC -0.212 -0.034 -0.074  0.034  0.000                     
## ROLPHYS -0.119  0.020  0.090  0.026  0.088  0.000              
## BODPAIN -0.060  0.034 -0.038 -0.017  0.065  0.002  0.000       
## GENHLTH  0.122  0.074  0.027  0.169 -0.031 -0.103 -0.038  0.000
## 
## $cov.z
##         MENHLT SOCFUN ROLEEM  VITAL PHSFUN ROLPHY BODPAI GENHLT
## MENHLTH  0.000                                                 
## SOCFUNC -0.492  0.000                                          
## ROLEEMO  3.736 -1.037  0.000                                   
## VITAL    1.211 -0.225 -4.729  0.000                            
## PHSFUNC -6.474 -1.156 -2.090  0.948  0.000                     
## ROLPHYS -4.326  0.791  2.692  0.861  3.310  0.000              
## BODPAIN -1.739  1.120 -1.049 -0.509  2.006  0.086  0.000       
## GENHLTH  3.183  2.327  0.754  4.582 -0.998 -4.531 -1.187  0.000
## 
## $summary
##                           cov
## srmr                    0.070
## srmr.se                 0.005
## srmr.exactfit.z         8.834
## srmr.exactfit.pvalue    0.000
## usrmr                   0.065
## usrmr.se                0.009
## usrmr.ci.lower          0.051
## usrmr.ci.upper          0.080
## usrmr.closefit.h0.value 0.050
## usrmr.closefit.z        1.769
## usrmr.closefit.pvalue   0.038

Modification Indices

The values below indicate the drop in chi-square (i.e., model improvement) anticipated if parameters currently fixed at 0.0 are freed to be estimated. Note that =~ indicates a crossloading of a subscale on its unintended factor, and ~~ indicates a correlation between the residual variances of two subscales. In this example they help us pinpoint why the fit of the hypothesized model was not great. GENHLTH “wants” to load on MH, and the correlation between MENHLTH & PHYSFUNC, which load on different factors, “wants” to be stronger than the model specifies.

modificationIndices(fit, sort. = TRUE, minimum.value = 3)
##        lhs op     rhs     mi    epc sepc.lv sepc.all sepc.nox
## 23      MH =~ GENHLTH 32.527  4.270   4.270    1.062    1.062
## 31 MENHLTH ~~ PHSFUNC 26.178 -4.306  -4.306   -0.395   -0.395
## 24      PH =~ MENHLTH 25.898 -3.608  -3.608   -0.816   -0.816
## 20      MH =~ PHSFUNC 21.195 -4.291  -4.291   -0.873   -0.873
## 29 MENHLTH ~~ ROLEEMO 20.032  2.690   2.690    0.385    0.385
## 41 ROLEEMO ~~   VITAL 17.170 -1.890  -1.890   -0.343   -0.343
## 54 ROLPHYS ~~ GENHLTH 16.933 -3.053  -3.053   -0.360   -0.360
## 50 PHSFUNC ~~ ROLPHYS 14.352  3.468   3.468    0.346    0.346
## 32 MENHLTH ~~ ROLPHYS 13.047 -2.280  -2.280   -0.296   -0.296
## 34 MENHLTH ~~ GENHLTH 12.376  2.468   2.468    0.267    0.267
## 43 ROLEEMO ~~ ROLPHYS 11.784  1.741   1.741    0.271    0.271
## 49   VITAL ~~ GENHLTH  9.706  1.689   1.689    0.232    0.232
## 27      PH =~   VITAL  8.440  1.558   1.558    0.467    0.467
## 51 PHSFUNC ~~ BODPAIN  4.492  1.180   1.180    0.167    0.167
## 46   VITAL ~~ PHSFUNC  3.711  1.252   1.252    0.146    0.146

Reliability Analysis

The semTools package has a function that reads the lavaan output and returns the reliability estimates for each latent variable. Setting the options ‘tau.eq=T’ and ‘obs.var=T’ produces equivalent to Cronbach’s reliability coefficient alpha. Setting ‘tau.eq=F’ produces the omega coefficient of reliability.

relests<-semTools::compRelSEM(fit, tau.eq=T, obs.var=T, return.total=T)
The reliability of MH is 0.8138296.
The reliability of PH is 0.7192983.
The overall reliability of the measurement model is 0.846431.

LS0tDQp0aXRsZTogIkV4cGxvcmF0b3J5IGFuZCBDb25maXJtYXRvcnkgRmFjdG9yIEFuYWx5c2lzIG9uIFNGLTM2IFNjYWxlcyINCmF1dGhvcjogIkphc29uIEJlY2tzdGVhZCINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBmYWxzZQ0KICAgIHRvY19kZXB0aDogMg0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUNCi0tLQ0KDQpMYXN0IHVwZGF0ZWQ6IGByIGZvcm1hdChTeXMuRGF0ZSgpLCAiJUIgJWQgJVkiKWANCg0KIyBEZXNjcmlwdGlvbiBvZiBFeGFtcGxlDQoNClRoZSAqKlNGLTM2KiogcXVlc3Rpb25uYWlyZSBtZWFzdXJlcyAqKnNlbGYtcmVwb3J0ZWQgZnVuY3Rpb25hbCBzdGF0dXMqKi4gSXRzIDM2IGl0ZW1zIGFyZSBjb21iaW5lZCB0byBmb3JtIDggc3Vic2NhbGVzIHlpZWxkaW5nICp0d28gc3VtbWFyeSBtZWFzdXJlczoqIHBoeXNpY2FsIGFuZCBtZW50YWwgaGVhbHRoLiANCiANCnwgVGhlICpwaHlzaWNhbCBoZWFsdGggbWVhc3VyZSogaW5jbHVkZXMgZm91ciBzdWJzY2FsZXM6IHBoeXNpY2FsIGZ1bmN0aW9uaW5nICgxMCBpdGVtcyksIHJvbGUtcGh5c2ljYWwgKDQgaXRlbXMpLCBib2RpbHkgcGFpbiAoMiBpdGVtcyksIGFuZCBnZW5lcmFsIGhlYWx0aCAoNSBpdGVtcykuIA0KIA0KfCBUaGUgKm1lbnRhbCBoZWFsdGggbWVhc3VyZSogaW5jbHVkZXMgdGhlIG90aGVyIGZvdXIgc3Vic2NhbGVzOiB2aXRhbGl0eSAoNCBpdGVtcyksIHNvY2lhbCBmdW5jdGlvbmluZyAoMiBpdGVtcyksIHJvbGUtZW1vdGlvbmFsICgzIGl0ZW1zKSwgYW5kIG1lbnRhbCBoZWFsdGggKDUgaXRlbXMpLg0KIA0KfCAqKlRoaXMgZXhhbXBsZSoqIHVzZXMgZGF0YSBmcm9tIDI0OSB3b21lbiAoYWdlIDMxIHRvIDg3LCBtZWRpYW4gNjQpIHdobyBjb21wbGV0ZWQgdGhlIFNGLTM2IGZvbGxvd2luZyBoZWFydCBzdXJnZXJ5LiBUaGUgc3Vic2NhbGUgdmFyaWFibGUgbmFtZXMgYXJlOiBNRU5ITFRILCBTT0NGVU5DLCBST0xFRU1PLCBWSVRBTCwgICBQSFNGVU5DLCBST0xQSFlTLCBCT0RQQUlOLCBhbmQgR0VOSExUSC4NCiANCnwgRmlyc3QsIGFuIEV4cGxvcmF0b3J5IEZhY3RvciBBbmFseXNpcyB3aXRoIDIgdW5jb3JyZWxhdGVkIGZhY3RvcnMgaXMgcnVuIHVzaW5nIHRoZSAqcHN5Y2ggcGFja2FnZSogaW4gd2hpY2ggZWFjaCBzdWJzY2FsZSBsb2FkcyBvbiBib3RoIGZhY3RvcnMuIA0KfCBTZWNvbmQsIGEgQ29uZmlybWF0b3J5IEZhY3RvciBBbmFseXNpcyB3aXRoIDIgY29ycmVsYXRlZCBmYWN0b3JzIGlzIHJ1biB1c2luZyB0aGUgKmxhdmFhbiBwYWNrYWdlKiBpbiB3aGljaCBlYWNoIHN1YnNjYWxlIGxvYWRzIG9uIG9ubHkgb25lIGh5cG90aGVzaXplZCBmYWN0b3IuDQoNCiMgU2V0dXANCg0KUmVxdWlyZWQgUGFja2FnZXMNCg0KYGBge3Igc2V0dXAsIG1lc3NhZ2UgPSBGQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvciA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IFRSVUUpDQoNCmxpYnJhcnkocmlvKQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGxhdmFhbikNCmxpYnJhcnkocHN5Y2gpDQpsaWJyYXJ5KHNlbW91dHB1dCkNCmxpYnJhcnkoc2VtUGxvdCkNCmxpYnJhcnkoc2pQbG90KQ0KbGlicmFyeShHUEFyb3RhdGlvbikNCmxpYnJhcnkoc2VtVG9vbHMpDQpgYGANCg0KSW1wb3J0IERhdGENCg0KYGBge3Igd2FybmluZz1GQUxTRX0NCiMjIEltcG9ydCBEYXRhDQpocnRzcmcgPC0gcmlvOjppbXBvcnQoIkM6L1VzZXJzL2piZWNrc3RlL0Rlc2t0b3AvV09NRU5fSFJUU1JHX25vTGFiZWxzLlNBViIpDQphdHRhY2goaHJ0c3JnKQ0KZGF0YSA8LSBkYXRhLmZyYW1lKE1FTkhMVEgsIFNPQ0ZVTkMsIFJPTEVFTU8sIFZJVEFMLCAgIFBIU0ZVTkMsIFJPTFBIWVMsIEJPRFBBSU4sIEdFTkhMVEgpDQoNCmBgYA0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgRGVzY3JpcHRpdmVzDQoNCmBgYHtyfQ0KIyBQcmludHMgYmFzaWMgZGVzY3JpcHRpdmUgc3RhdGlzdGljcw0Kc2VtX2Rlc2NyaXB0aXZlcyhkYXRhKQ0KYGBgDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIENvcnJlbGF0aW9uIE1hdHJpeA0KIyMgQml2YXJpYXRlIFN1bW1hcnkgRGlzcGxheQ0KSGlzdG9ncmFtcyBhcmUgc2hvd24gb24gdGhlIGRpYWdvbmFsLCBzY2F0dGVycGxvdHMgc2hvd2luZyBiaXZhcmlhdGUgcmVncmVzc2lvbiBsaW5lIGFuZCBjZW50cm9pZCBhcmUgYmVsb3cgdGhlIGRpYWdub25hbCwgY29ycmVsYXRpb25zIGFyZSBhYm92ZSB0aGUgZGlhZ29uYWwuDQoNCmBgYHtyfQ0KcHN5Y2g6OnBhaXJzLnBhbmVscyhkYXRhLCBsbT1ULCBjZXguY29yPS43LCBqaWdnbGU9VCwgZmFjdG9yPTMsDQogICAgICAgICAgICAgICAgICAgIHNob3cucG9pbnRzID0gVCwgZWxsaXBzZXM9VCwgcGNoPSIuIikNCmBgYA0KDQoNCiMjIEhlYXRtYXANCkxhcmdlciBjb3JyZWxhdGlvbnMgYXJlIG1vcmUgZGFya2x5IHNoYWRlZC4gSWRlYWxseSwgc3Vic2NhbGVzIHdpdGhpbiBlYWNoIG1lYXN1cmUgc2hvdWxkIHNob3cgc3Ryb25nZXIgY29ycmVsYXRpb25zIHRoYW4gc3Vic2NhbGVzIGZyb20gZGlmZmVyZW50IG1lYXN1cmVzLg0KYGBge3J9DQojbWFrZXMgaGVhdG1hcCBvZiBjb3JyIG10eDsgU09SVCBkZiBmaXJzdCBiYXNlZCBvbiBGQQ0KcHN5Y2g6OmNvci5wbG90KGRhdGEsIHB2YWw9RixkaWFnPVQsIHNjYWxlPUYsIHNob3cubGVnZW5kPUYsIHVwcGVyPUYsIG49NTEsDQogICAgICAgICAgICAgICAgbWFpbj0iIiwgY2V4PS44LCB4bGFzPTIpDQpgYGANCg0KIyMgTmljZSBUYWJsZQ0KYGBge3J9DQojIFVzZXMgc2pQbG90IHRvIHByaW50IGEgbmljZSBsb29raW5nIGNvcnJlbGF0aW9uIHRhYmxlDQp0YWJfY29ycihkYXRhLCBuYS5kZWxldGlvbiA9ICJsaXN0d2lzZSIsIGRpZ2l0cyA9IDIsIHRyaWFuZ2xlID0gImxvd2VyIiwNCiAgICAgICAgIHRpdGxlPSJDb3JyZWxhdGlvbnMgYW1vbmcgU0YtMzYgU2NhbGVzIiwNCiAgICAgICAgIHN0cmluZy5kaWFnPWMoJzEnLCcxJywnMScsJzEnLCcxJywnMScsJzEnLCcxJykpDQpgYGANCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgRUZBIFJlc3VsdHMgey50YWJzZXQgLnRhYnNldH0NCkJhc2VkIG9uIHRoZSBzY3JlZSBwbG90IGJlbG93LCBhIDItZmFjdG9yIHNvbHV0aW9uIHNlZW1zIHJlYXNvbmFibGUuIFRoaXMgcGxvdCB3YXMgZ2VuZXJhdGVkIGJ5IHBzeWNoOjpWU1Muc2NyZWUNCg0KYGBge3IsIGNsYXNzLnNvdXJjZSA9ICJmb2xkLWhpZGUifQ0KZWZhX2RhdGEgPC0gZGF0YQ0KIyMgRGV0ZXJtaW5lIHRoZSBudW1iZXIgb2YgZmFjdG9ycyB0byBleHRyYWN0IGJ5IGluc3BlY3Rpb24gb2Ygc2NyZWUgcGxvdA0KcHN5Y2g6OlZTUy5zY3JlZShlZmFfZGF0YSkNCiMjIENvbmR1Y3QgRUZBIGFuYWx5c2lzIHdpdGggMiBmYWN0b3JzIGRldGVybWluZWQgZnJvbSBzY3JlZSBwbG90DQplZmFfZml0IDwtIHBzeWNoOjpmYShlZmFfZGF0YSwgZm0gPSAibWwiLCBuZmFjdG9ycyA9IDIsIHJvdGF0ZSA9ICJ2YXJpbWF4IikNCmBgYA0KDQpgYGB7Y3NzLCBlY2hvPUZBTFNFfQ0KLnNjcm9sbC01MDAgew0KICBtYXgtaGVpZ2h0OiA1MDBweDsNCiAgb3ZlcmZsb3cteTogYXV0bzsNCiAgYmFja2dyb3VuZC1jb2xvcjogaW5oZXJpdDsNCn0NCmBgYA0KDQojIyBTdW1tYXJ5IE91dHB1dA0KDQpgYGB7cn0NCmVmYV9tZXRob2QoZWZhX2ZpdCkNCmVmYV92YXIoZWZhX2ZpdCkNCmVmYV9sb2FkaW5ncyhlZmFfZml0KQ0KZWZhX3JvdG1hdHJpeChlZmFfZml0KQ0KYGBgDQoNCiMjIERpYWdyYW0gT3V0cHV0IHsuYWN0aXZlfQ0KDQpgYGB7cn0NCnBzeWNoOjpmYS5kaWFncmFtKGVmYV9maXQsIGN1dD0uMDEsIHNpbXBsZT1GLCBhZGo9MiwgZGlnaXRzPTIsDQogICAgICAgICAgICAgICAgICBtYWluPSJFeHBsb3JhdG9yeSBGYWN0b3IgQW5hbHlzaXMgdXNpbmcgTUwiKQ0KDQpgYGANCg0KIyMgRnVsbCBPdXRwdXQNCg0KYGBge3IsIGNsYXNzLm91dHB1dD0ic2Nyb2xsLTUwMCJ9DQplZmFfZml0DQpgYGANCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgQ0ZBIGluIExJU1JFTCBOb3RhdGlvbg0KVGhlIGdvYWwgb2YgQ0ZBIGlzIHRvIHJlcHJvZHVjZSB0aGUgY292YXJpYW5jZSBtYXRyaXgsICRcbWF0aGJmXFNpZ21hJCwgYW1vbmcgdGhlIG9ic2VydmVkIHZhcmlhYmxlcy4gVGhpcyBpcyBkb25lIHVzaW5nIGEgaHlwb3RoZXNpemVkIG1vZGVsIHRoYXQgY29uc2lzdHMgb2YgdGhyZWUgdHlwZXMgb2YgcGFyYW1ldGVycyBjb250YWluZWQgaW4gdGhyZWUgbWF0cmljZXM6DQoNCiQkDQpcbWF0aGJme1xTaWdtYV4qID0gXExhbWJkYV94IFxQaGkgXExhbWJkYSdfeCArIFxUaGV0YV9cZGVsdGF9DQokJA0Kd2hlcmUgJFxtYXRoYmZcU2lnbWFeKiQgaXMgdGhlIGVzdGltYXRlZCBjb3ZhcmlhbmNlIG1hdHJpeCBhbW9uZyB0aGUgZWlnaHQgc3Vic2NhbGVzLCAkXG1hdGhiZlxMYW1iZGFfeCQgaXMgYSBtYXRyaXggb2YgZmFjdG9yIGxvYWRpbmdzLCAkXG1hdGhiZlxQaGkkIGlzIHRoZSBjb3ZhcmlhbmNlIG1hdHJpeCBvZiB0aGUgbGF0ZW50IHZhcmlhYmxlcyAoZmFjdG9ycyksIGFuZCAkXG1hdGhiZlxUaGV0YV9cZGVsdGEkIGlzIGEgbWF0cml4IG9mIG1lYXN1cmVtZW50IGVycm9yIHZhcmlhbmNlcy4gICANCiAgDQpIZXJlIGlzIHRoZSAkXG1hdGhiZlxMYW1iZGFfeCQgZm9yIG91ciBtb2RlbCBvZiB0aGUgU0YtMzYgc3Vic2NhbGVzOiAgDQoNCiQkXG1hdGhiZlxMYW1iZGFfeCA9DQpcYmVnaW57Ym1hdHJpeH0NClxsYW1iZGFfezEsMX0gJiAwXFwNClxsYW1iZGFfezIsMX0gJiAwXFwNClxsYW1iZGFfezMsMX0gJiAwXFwNClxsYW1iZGFfezQsMX0gJiAwXFwNCjAgJiBcbGFtYmRhX3s1LDJ9XFwNCjAgJiBcbGFtYmRhX3s2LDJ9XFwNCjAgJiBcbGFtYmRhX3s3LDJ9XFwNCjAgJiBcbGFtYmRhX3s4LDJ9XFwNClxlbmR7Ym1hdHJpeH0NCiQkDQpUaGUgcm93cyBjb3JyZXNwb25kIHRvIHRoZSBlaWdodCBzdWJzY2FsZXMgYW5kIHRoZSBjb2x1bW5zIHRvIHRoZSB0d28gbGF0ZW50IHZhcmlhYmxlcyAoTUggYW5kIEdIKS4gTm90ZSB0aGUgZmlyc3QgZm91ciBzdWJzY2FsZXMgbG9hZCBvbiB0aGUgZmlyc3QgZmFjdG9yIChNSCkgYW5kIGhhdmUgemVybyBsb2FkaW5ncyBvbiB0aGUgc2Vjb25kIGZhY3RvciAoUEgpLiBUaGUgcmV2ZXJzZSBwYXR0ZXJuIGlzIHRydWUgZm9yIHRoZSBsYXN0IGZvdXIgc3Vic2NhbGVzLiAgDQogIA0KSGVyZSBpcyB0aGUgJFxtYXRoYmZcUGhpJCBtYXRyaXggZm9yIG91ciBtb2RlbDoNCg0KJCRcbWF0aGJmXFBoaSA9IFxiZWdpbntibWF0cml4fQ0KXHBoaV97MSwxfSAmIFxwaGlfezEsMn1cXA0KXHBoaV97MiwxfSAmIFxwaGlfezIsMn1cXA0KXGVuZHtibWF0cml4fQ0KJCQNCndpdGggdGhlIGZhY3RvciB2YXJpYW5jZXMgb24gdGhlIGRpYWdvbmFsIGFuZCB0aGVpciBjb3ZhcmlhbmNlIGluIHRoZSBvZmYtZGlhZ29uYWwuIE5vdGUgdGhhdCB0aGlzIGlzIGEgc3ltbWV0cmljIG1hdHJpeC4gIA0KICANCiAgDQpGaW5hbGx5LCBoZXJlIGlzIHRoZSAkXG1hdGhiZlxUaGV0YV9cZGVsdGEkIG1hdHJpeCBmb3Igb3VyIG1vZGVsOg0KDQokJFxtYXRoYmZcVGhldGFfXGRlbHRhID0gXGJlZ2lue2JtYXRyaXh9DQpcdGhldGFfezEsMX0gJiAwICYgMCAmIDAgJiAwICYgMCAmIDAgJiAwXFwNCjAgJiBcdGhldGFfezIsMn0gJiAwICYgMCAmIDAgJiAwICYgMCAmIDBcXA0KMCAmIDAgJiBcdGhldGFfezMsM30gJiAwICYgMCAmIDAgJiAwICYgMFxcDQowICYgMCAmIDAgJiBcdGhldGFfezQsNH0gJiAwICYgMCAmIDAgJiAwXFwNCjAgJiAwICYgMCAmIDAgJiBcdGhldGFfezUsNX0gJiAwICYgMCAmIDBcXA0KMCAmIDAgJiAwICYgMCAmIDAgJiBcdGhldGFfezYsNn0gJiAwICYgMFxcDQowICYgMCAmIDAgJiAwICYgMCAmIDAgJiBcdGhldGFfezcsN30gJiAwXFwNCjAgJiAwICYgMCAmIDAgJiAwICYgMCAmIDAgJiBcdGhldGFfezgsOH1cXA0KXGVuZHtibWF0cml4fQ0KJCQNCk5vdGUgdGhhdCAkXG1hdGhiZlxUaGV0YV9cZGVsdGEkIGlzIGEgZGlhZ29uYWwgbWF0cml4LiBUaGlzIHJlZmxlY3RzIG91ciBoeXBvdGhlc2lzIHRoYXQgdGhlIG1lYXN1cmVtZW50IGVycm9yIHRlcm1zIGZvciB0aGUgc3Vic2NhbGVzIGFyZSB1bmNvcnJlbGVhdGVkIChpLmUuLCBhbGwgb2ZmLWRpYWdvbmFsIGVsZW1lbnRzIGFyZSBoeXBvdGhlc2l6ZWQgdG8gYmUgemVybykuICANCiAgDQogIA0KDQojIENGQSBSZXN1bHRzIHsudGFic2V0IH0NCkJhc2VkIG9uIHRoZSByZXN1bHRzIG9mIHRoZSBleHBsb3JhdG9yeSBhbmFseXNpcywgd2UgZGVjaWRlIHRvIHJ1biBhIGNvbmZpcm1hdG9yeSBtb2RlbCBzcGVjaWZ5aW5nIHRoYXQgdGhlIGZpcnN0IDQgc3Vic2NhbGVzIGxvYWQgb24gb25lIGZhY3RvciBhbmQgdGhlIGxhc3QgNCBzdWJzY2FsZXMgbG9hZCBvbiBhIHNlY29uZCBmYWN0b3IuDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLWhpZGUifQ0KIyBzcGVjaWZ5IHRoZSAyLWZhY3RvciBDRkEgbW9kZWwNCm1vZGVsIDwtICcNCiMgbGF0ZW50IGZhY3RvcnMNCk1IID1+ICBNRU5ITFRIICsgU09DRlVOQyArIFJPTEVFTU8gKyBWSVRBTA0KUEggPX4gIFBIU0ZVTkMgKyBST0xQSFlTICsgQk9EUEFJTiArIEdFTkhMVEgnDQojIGZpdCB0aGUgbW9kZWwNCmZpdCA8LSBsYXZhYW46OmNmYShtb2RlbCA9IG1vZGVsLCBkYXRhID0gZGF0YSwgbWltaWMgPSAibGF2YWFuIiwgDQogICAgICAgICAgIGVzdGltYXRvciA9ICJNTCIsIG1pc3NpbmcgPSAibGlzdHdpc2UiLCBjaGVjay5wb3N0PVQsDQogICAgICAgICAgIHN0ZC5sdiA9IFRSVUUsIHN0ZC5vdiA9IEZBTFNFLCB0ZXN0ID0gInN0YW5kYXJkIiwgDQogICAgICAgICAgIHNlID0gInN0YW5kYXJkIiwgYm9vdHN0cmFwID0gMTAwMCkNCg0KYGBgDQoNCiMjIFN1bW1hcnkgT3V0cHV0DQoNCmBgYHtyIHJlc3VsdHM9J2FzaXMnfQ0Kc2VtX3RhYmxlcyhmaXQpDQpgYGANCg0KIyMgRGlhZ3JhbSBPdXRwdXQgey5hY3RpdmV9DQoNCmBgYHtyIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTh9DQpmYWN0b3JzIDwtIGZpdEBwdGEkdm5hbWVzJGx2W1sxXV0NCnNpemUgPC0gLjY1DQpzZW1QYXRocyhmaXQsIGxhdGVudHMgPSBmYWN0b3JzLCB3aGF0TGFiZWxzID0gInN0ZCIsIGxheW91dCA9ICJ0cmVlMiIsIA0KICAgICAgICAgcm90YXRpb24gPSA0LCBzdHlsZSA9ICJsaXNyZWwiLCBvcHRpbWl6ZUxhdFJlcyA9IFRSVUUsIA0KICAgICAgICAgc3RydWN0dXJhbCA9IEZBTFNFLCBsYXlvdXRTcGxpdCA9IEZBTFNFLA0KICAgICAgICAgaW50ZXJjZXB0cyA9IEZBTFNFLCByZXNpZHVhbHMgPSBULCANCiAgICAgICAgIGN1cnZlID0gMSwgY3VydmF0dXJlID0gMywgbkNoYXJOb2RlcyA9IDgsIA0KICAgICAgICAgc2l6ZUxhdCA9IDExICogc2l6ZSwgc2l6ZU1hbiA9IDExICogc2l6ZSwgc2l6ZU1hbjIgPSA0ICogc2l6ZSwgDQogICAgICAgICBlZGdlLmxhYmVsLmNleCA9IDEuMiAqIHNpemUsIA0KICAgICAgICAgZWRnZS5jb2xvciA9ICIjMDAwMDAwIiwgZWRnZS5sYWJlbC5wb3NpdGlvbiA9IC40MCkNCmBgYA0KDQojIyBSZXNpZHVhbCBDb3JyZWxhdGlvbiBNYXRyaXgNClRoZSB2YWx1ZXMgYmVsb3cgYXJlIHRoZSByZXNpZHVhbCBjb3JyZWxhdGlvbnMgKGkuZS4sIG9ic2VydmVkIGNvcnJlbGF0aW9uIC0gbW9kZWwgZXN0aW1hdGVkIGNvcnJlbGF0aW9uKS4gTm90ZSB0aGUgbGFyZ2VzdCByZXNpZHVhbCBpcyB8LS4yMXwgZm9yIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIE1FTkhMVEggJiBQSFNGVU5DLiBUaGUgYXZlcmFnZSBvZiB0aGVzZSByZXNpZHVhbHMgaXMgcHJvdmlkZWQgYnkgdGhlIHN0YW5kYXJpemVkIHJvb3QgbWVhbiBzcXVhcmUgcmVzaWR1YWwgKFNSTVIpLg0KDQpgYGB7cn0NCnNlbV9yZXNpZHVhbHMoZml0KQ0KYGBgDQoNCiMjIEZ1bGwgT3V0cHV0DQoNCiMjIyBTdW1tYXJ5DQoNCmBgYHtyLCBjbGFzcy5vdXRwdXQ9InNjcm9sbC01MDAifQ0Kc3VtbWFyeShmaXQsIGZpdC5tZWFzdXJlcyA9IFRSVUUsIHN0YW5kYXJkaXplZCA9IFRSVUUpDQpgYGANCg0KIyMjIFN0YW5kYXJpemVkIFBhcmFtZXRlciBFc3RpbWF0ZXMNCg0KYGBge3IsIGNsYXNzLm91dHB1dD0ic2Nyb2xsLTUwMCJ9DQpzdGFuZGFyZGl6ZWRTb2x1dGlvbihmaXQpDQpgYGANCiMjIyBSZXNpZHVhbHMgQW5hbHlzaXMNCkRpc3BsYXlzIHJlc2lkdWFsIGNvcnJlbGF0aW9ucyBhbmQgei1zY29yZXMgaW5kaWNhdGluZyB0aGUgbWFnbml0dWRlIG9mIHRoZSByZXNpZHVhbHMuIFR5cGljYWxseSwgeiB2YWx1ZXMgPiB8Mi41NHwgYXJlIGludGVycHJldGVkIGFzIHNpZ25pZmljYW50IGFuZCBpbmRpY2F0ZSB3aGVyZSB0aGUgbW9kZWwgaXMgZG9pbmcgYSBwb29yIGpvYiBvZiByZXByb2R1Y2luZyB0aGUgb2JzZXJ2ZWQgY29ycmVsYXRpb25zLiBOb3RlIHRoYXQgdGhlIGxhcmdlc3QgcmVzaWR1YWwgY29ycmVsYXRpb24gYW5kIHx6fCBpcyBiZXR3ZWVuIE1FTkhMVEggJiBQSFNGVU5DLg0KYGBge3IsY2xhc3Mub3V0cHV0PSJzY3JvbGwtNTAwIn0NCmxhdlJlc2lkdWFscyhmaXQpDQpgYGANCg0KIyMjIE1vZGlmaWNhdGlvbiBJbmRpY2VzDQpUaGUgdmFsdWVzIGJlbG93IGluZGljYXRlIHRoZSBkcm9wIGluIGNoaS1zcXVhcmUgKGkuZS4sIG1vZGVsIGltcHJvdmVtZW50KSBhbnRpY2lwYXRlZCBpZiBwYXJhbWV0ZXJzIGN1cnJlbnRseSBmaXhlZCBhdCAwLjAgYXJlIGZyZWVkIHRvIGJlIGVzdGltYXRlZC4gTm90ZSB0aGF0ICoqPX4qKiBpbmRpY2F0ZXMgYSBjcm9zc2xvYWRpbmcgb2YgYSBzdWJzY2FsZSBvbiBpdHMgdW5pbnRlbmRlZCBmYWN0b3IsIGFuZCAqKn5+KiogaW5kaWNhdGVzIGEgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgcmVzaWR1YWwgdmFyaWFuY2VzIG9mIHR3byBzdWJzY2FsZXMuIEluIHRoaXMgZXhhbXBsZSB0aGV5IGhlbHAgdXMgcGlucG9pbnQgd2h5IHRoZSBmaXQgb2YgdGhlIGh5cG90aGVzaXplZCBtb2RlbCB3YXMgbm90IGdyZWF0LiBHRU5ITFRIICJ3YW50cyIgdG8gbG9hZCBvbiBNSCwgYW5kIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIE1FTkhMVEggJiBQSFlTRlVOQywgd2hpY2ggbG9hZCBvbiBkaWZmZXJlbnQgZmFjdG9ycywgIndhbnRzIiB0byBiZSBzdHJvbmdlciB0aGFuIHRoZSBtb2RlbCBzcGVjaWZpZXMuIA0KYGBge3IsIGNsYXNzLm91dHB1dD0ic2Nyb2xsLTUwMCJ9DQptb2RpZmljYXRpb25JbmRpY2VzKGZpdCwgc29ydC4gPSBUUlVFLCBtaW5pbXVtLnZhbHVlID0gMykNCmBgYA0KIyMgUmVsaWFiaWxpdHkgQW5hbHlzaXMNClRoZSAqKnNlbVRvb2xzKiogcGFja2FnZSBoYXMgYSBmdW5jdGlvbiB0aGF0IHJlYWRzIHRoZSBsYXZhYW4gb3V0cHV0IGFuZCByZXR1cm5zIHRoZSByZWxpYWJpbGl0eSBlc3RpbWF0ZXMgZm9yIGVhY2ggbGF0ZW50IHZhcmlhYmxlLiBTZXR0aW5nIHRoZSBvcHRpb25zICd0YXUuZXE9VCcgYW5kICdvYnMudmFyPVQnIHByb2R1Y2VzIGVxdWl2YWxlbnQgdG8gKkNyb25iYWNoJ3MgcmVsaWFiaWxpdHkgY29lZmZpY2llbnQgYWxwaGEqLiBTZXR0aW5nICd0YXUuZXE9RicgcHJvZHVjZXMgdGhlIG9tZWdhIGNvZWZmaWNpZW50IG9mIHJlbGlhYmlsaXR5Lg0KYGBge3IsIHJlc3VsdHM9J2hvbGQnfQ0KcmVsZXN0czwtc2VtVG9vbHM6OmNvbXBSZWxTRU0oZml0LCB0YXUuZXE9VCwgb2JzLnZhcj1ULCByZXR1cm4udG90YWw9VCkNCmBgYA0KfCBUaGUgcmVsaWFiaWxpdHkgb2YgTUggaXMgYHIgcmVsZXN0cyBbMV1gLg0KfCBUaGUgcmVsaWFiaWxpdHkgb2YgUEggaXMgYHIgcmVsZXN0cyBbMl1gLg0KfCBUaGUgb3ZlcmFsbCByZWxpYWJpbGl0eSBvZiB0aGUgbWVhc3VyZW1lbnQgbW9kZWwgaXMgYHIgcmVsZXN0cyBbM11gLg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg==