1 EFA

  • A multivariate method in which to determine the relationships and patterns between variables
  • EFA is different from Confirmatory Factor Analysis (CFA) in which you are trying to confirm a specific set attempts to confirm how things should be related to one another using a SEM model
  • EFA can be used to in many ways (Yong & Pearce, 2013)
  1. Develop Scales: such as Big 5 Personality
  2. Item’s Analysis: which test items go together (to test specific constructs)
  3. Dimensionality reduction: Which items/questions/features are most important (strength of which things bind together) and create “factor scores” representing underlying constructs for use in other analyses.
  • EFA examines a pattern of correlations/covariances between the items and tries to determine if they are influenced by the same or a different underlying factor.

1.1 Collect Items measured in the same units

  • You might need to reverse score the items or recode/transform them

1.1.1 Visualize the patterns in the data

  • helpful to look at the patterns before you go further

  • Take data (BFI228) of the “study on personality and relationship satisfaction (Luo, 2005). The participants were 228 undergraduate students at a large public university in the US. The data were participants’ self-ratings on the 44 items of the Big Five Inventory (John, Donahue, & kentle, 1991). These items are Likert variables: disagree strongly (1), disagree a little (2), neither agree nor disagree (3), agree a little (4), and agree strongly (5)”. Taken from the EFAutilities package.

library(psych)
library(corrplot)
library(EFAutilities)
data(BFI228)
DataSet<-BFI228
corrplot(cor(DataSet), order = "hclust", tl.col='black', tl.cex=.75) 

1.2 Do I have enough data to proceed?

  • Kaiser Meyer Olkin (KMO) Measure of Sampling Adequacy (Howard, 2016)
  • You could remove anything below .6 and if the overall is below .6 you cannot do a EFA
KMO Interpreation Use?
0.00 to 0.50 Unacceptable No
0.50 to 0.60 Miserable No
0.60 to 0.70 Mediocre Yes
0.70 to 0.80 Middling Yes
0.80 to 0.90 Meritorious Yes
0.90 to 1.00 Marvelous Yes
KMO(BFI228)
## Kaiser-Meyer-Olkin factor adequacy
## Call: KMO(r = BFI228)
## Overall MSA =  0.83
## MSA for each item = 
##     talkative    researvedR    fullenergy  enthusiastic        quietR 
##          0.81          0.81          0.81          0.85          0.86 
##     assertive          shyR      outgoing    findfaultR       helpful 
##          0.91          0.78          0.84          0.87          0.83 
##     quarrelsR     forgiving      trusting         coldR   considerate 
##          0.84          0.82          0.81          0.83          0.83 
##         rudeR   cooperative      thorough     carelessR      reliable 
##          0.84          0.82          0.85          0.88          0.81 
## disorganizedR         lazyR     persevere     efficient         plans 
##          0.78          0.81          0.78          0.85          0.84 
##   distractedR          blue      relaxedR         tense       worries 
##          0.85          0.90          0.83          0.87          0.87 
##    emostableR         moody         calmR       nervous         ideas 
##          0.84          0.83          0.86          0.87          0.87 
##       curious     ingenious   imagination     inventive      artistic 
##          0.84          0.85          0.77          0.80          0.72 
##      routineR       reflect  nonartisticR sophisticated 
##          0.56          0.84          0.75          0.67

1.3 Get correlation/covariances matrix

  • The type of correlation is important:
  • If you have ordinal or nominal data you might want to switch from Pearson to poly- or tetra-choric correlations
  • Most psychologists just ignore this and use Pearson
CM<-cor(DataSet, use="complete.obs")

1.4 Select the number of factors

  • You might have a specific number in mind or it can be approximated from the data.
  1. The Kaiser criterion: a number of factors equal to the number of the eigenvalues of the correlation matrix that are greater than one.
  2. The “Scree test” is a lot of the eigenvalues of the correlation matrix in descending order

Selecting from the scree plot can be accomplished in a few different ways:

  • See http://www.empowerstats.com/manuals/paper/scree.pdf#1
  • Visually: When does the plot level off
  • Parallel Analysis: (basically what random correlations would give you for the same number of subjects and items)
  • Optimal Coordinate: extrapolation of the preceding eigenvalue by a regression line between the eigenvalue coordinates and the last eigenvalue coordinates
  • Acceleration Factor: When the slope change most abruptly (elbow)
library(nFactors)

ev <- eigen(CM) # get eigenvalues
ap <- parallel(subject=nrow(DataSet),var=ncol(DataSet),
  rep=100,cent=.05)
nS <- nScree(x=ev$values, aparallel=ap$eigen$qevpea)
plotnScree(nS)

  • Results all say 6, but we will force a 5 factor solution to match the Big 5

1.4.1 Extract your initial solution

  • Extraction methods: maximum likelihood (ML), principal components analysis (PCA), and principal axis factoring (PAF).
  • PCA is not a factor analysis method, but it often used as it tries to put most of the variance into the first factor
  • ML is often used and, but its sensitive to normality violation
  • PAF is less sensitive to normality violation, but less generalizable
  • There are many other types, such as Bayesian methods and methods for specific types of data (best to research each for your specific issue at hand)
mle.Intial <- factanal(covmat=cor(DataSet,use="complete.obs"),
                       factors=5, rotation="none")
print(mle.Intial$loadings, cutoff=0.3)
## 
## Loadings:
##               Factor1 Factor2 Factor3 Factor4 Factor5
## talkative      0.386   0.481  -0.414                 
## researvedR    -0.415           0.349                 
## fullenergy     0.676                                 
## enthusiastic   0.658   0.334                         
## quietR        -0.481  -0.379   0.480                 
## assertive      0.507   0.351                         
## shyR          -0.442           0.440                 
## outgoing       0.551          -0.472                 
## findfaultR    -0.413                                 
## helpful        0.321                   0.306         
## quarrelsR     -0.401   0.383                         
## forgiving      0.320                   0.350         
## trusting       0.378                   0.374         
## coldR         -0.436                  -0.378   0.346 
## considerate    0.339           0.301   0.489         
## rudeR         -0.473   0.321                         
## cooperative    0.463                   0.465         
## thorough       0.464                           0.471 
## carelessR              0.435                         
## reliable       0.396                   0.310   0.313 
## disorganizedR          0.410                  -0.433 
## lazyR         -0.417                                 
## persevere      0.363                           0.393 
## efficient      0.480                           0.363 
## plans          0.392                           0.439 
## distractedR   -0.455   0.305                         
## blue          -0.566   0.347                         
## relaxedR       0.505  -0.329          -0.323         
## tense         -0.474   0.351           0.352         
## worries       -0.567                   0.487         
## emostableR     0.540                                 
## moody         -0.497   0.317           0.311         
## calmR          0.519                                 
## nervous       -0.500                   0.517         
## ideas          0.458   0.432   0.374                 
## curious        0.405                                 
## ingenious      0.334   0.321   0.360                 
## imagination    0.330   0.496   0.375                 
## inventive      0.438   0.404   0.519                 
## artistic                       0.446                 
## routineR                                             
## reflect        0.353   0.507   0.311                 
## nonartisticR                                         
## sophisticated                  0.501                 
## 
##                Factor1 Factor2 Factor3 Factor4 Factor5
## SS loadings      8.263   3.706   2.793   2.594   1.986
## Proportion Var   0.188   0.084   0.063   0.059   0.045
## Cumulative Var   0.188   0.272   0.336   0.394   0.440

1.5 Rotate your factors to a final solution

  • Think of each factor a dimension and the problem is there is a near infinite set of dimensions that could explain your data
  • We need a way to help come up with a solution that is more interpretable
  • By rotating your factors you attempt to find a factor solution that is equal to that obtained in the initial extraction but which has the simplest interpretation
  • The simplest solution has 5 features (Thunderd, 1947; summarized in Abdi, 2003)
  1. each row contains at least one zero;
  2. for each column, there are at least as many zeros as there are columns
  3. for any pair of factors, there are some variables with zero loadings on one factor and large loadings on the other factor;
  4. for any pair of factors, there is a sizable proportion of zero loadings;
  5. for any pair of factors, there is only a small number of large loadings
  • There are many different types of rotation, but they all try get the strongest effect on the small subset of items.

There are two families of rotations: - Orthogonal rotations: uncorrelated factors (e.g., varimax) - Oblique rotations: produce correlated factors (e.g., promax)

  • Varimax is the most popular orthogonal rotation: “simple solution means that each factor has a small number of large loadings and a large number of zero (or small) loadings” (Abdi, 2003)

1.5.1 Orthogonal Rotation

mle.VM <- factanal(DataSet,factors=5, rotation="varimax")
print(mle.VM$loadings, cutoff=0.3)
## 
## Loadings:
##               Factor1 Factor2 Factor3 Factor4 Factor5
## talkative              0.736                         
## researvedR            -0.542                         
## fullenergy             0.563           0.390         
## enthusiastic           0.625           0.418         
## quietR                -0.780                         
## assertive              0.557                         
## shyR                  -0.639                         
## outgoing               0.752                         
## findfaultR                            -0.415         
## helpful                                0.446         
## quarrelsR                             -0.591         
## forgiving                              0.551         
## trusting                               0.538         
## coldR                                 -0.683         
## considerate                            0.656         
## rudeR          0.334                  -0.552         
## cooperative                            0.579         
## thorough                                       0.710 
## carelessR      0.301                          -0.449 
## reliable                                       0.550 
## disorganizedR                                 -0.631 
## lazyR                                         -0.516 
## persevere                                      0.559 
## efficient                                      0.608 
## plans                                          0.628 
## distractedR    0.520                          -0.364 
## blue           0.559                                 
## relaxedR      -0.668                                 
## tense          0.702                                 
## worries        0.749                                 
## emostableR    -0.599                                 
## moody          0.666                                 
## calmR         -0.549                                 
## nervous        0.649                                 
## ideas                          0.698                 
## curious                        0.433                 
## ingenious                      0.571                 
## imagination                    0.683                 
## inventive                      0.785                 
## artistic                       0.568                 
## routineR                                             
## reflect                        0.650                 
## nonartisticR                  -0.374                 
## sophisticated                  0.546                 
## 
##                Factor1 Factor2 Factor3 Factor4 Factor5
## SS loadings      4.382   3.968   3.925   3.711   3.357
## Proportion Var   0.100   0.090   0.089   0.084   0.076
## Cumulative Var   0.100   0.190   0.279   0.363   0.440

1.5.1.1 Useful to examine first two factors visually

  • We will need to extact the factor loading
VM.load = mle.VM$loadings[,1:2]
plot(VM.load, type="n")
text(VM.load,labels=colnames(DataSet),cex=.75) # add variable names

1.5.2 Oblique Rotation

  • When we examine the promax we will need to examine the correlation between factors
mle.PM <- factanal(DataSet, factors=5, 
                   rotation="promax")
mle.PM
## 
## Call:
## factanal(x = DataSet, factors = 5, rotation = "promax")
## 
## Uniquenesses:
##     talkative    researvedR    fullenergy  enthusiastic        quietR 
##         0.434         0.658         0.443         0.347         0.377 
##     assertive          shyR      outgoing    findfaultR       helpful 
##         0.545         0.520         0.376         0.732         0.759 
##     quarrelsR     forgiving      trusting         coldR   considerate 
##         0.544         0.686         0.665         0.472         0.483 
##         rudeR   cooperative      thorough     carelessR      reliable 
##         0.549         0.552         0.441         0.664         0.613 
## disorganizedR         lazyR     persevere     efficient         plans 
##         0.559         0.653         0.610         0.543         0.568 
##   distractedR          blue      relaxedR         tense       worries 
##         0.588         0.527         0.512         0.459         0.383 
##    emostableR         moody         calmR       nervous         ideas 
##         0.549         0.510         0.619         0.473         0.447 
##       curious     ingenious   imagination     inventive      artistic 
##         0.721         0.628         0.500         0.347         0.655 
##      routineR       reflect  nonartisticR sophisticated 
##         0.914         0.520         0.842         0.669 
## 
## Loadings:
##               Factor1 Factor2 Factor3 Factor4 Factor5
## talkative      0.187           0.778                 
## researvedR     0.175          -0.538                 
## fullenergy                     0.528   0.327         
## enthusiastic           0.190   0.598   0.379         
## quietR                        -0.805                 
## assertive     -0.115   0.262   0.518  -0.191   0.105 
## shyR           0.177          -0.643   0.189         
## outgoing                       0.775   0.158         
## findfaultR     0.232                  -0.403         
## helpful                                0.449         
## quarrelsR      0.206           0.155  -0.603         
## forgiving                              0.588         
## trusting              -0.101   0.145   0.552         
## coldR                  0.195  -0.112  -0.721         
## considerate    0.166   0.194  -0.140   0.697         
## rudeR          0.270           0.146  -0.544         
## cooperative    0.164           0.194   0.571   0.183 
## thorough                                       0.752 
## carelessR      0.225   0.228                  -0.444 
## reliable       0.167                   0.174   0.572 
## disorganizedR          0.171                  -0.685 
## lazyR                                         -0.515 
## persevere              0.238  -0.106           0.606 
## efficient              0.119                   0.627 
## plans          0.122                           0.674 
## distractedR    0.492                   0.153  -0.320 
## blue           0.515   0.126          -0.135  -0.159 
## relaxedR      -0.696                                 
## tense          0.750   0.148                   0.141 
## worries        0.798  -0.140           0.111         
## emostableR    -0.619   0.156           0.144         
## moody          0.704           0.106  -0.122         
## calmR         -0.540                                 
## nervous        0.707  -0.130  -0.156   0.220         
## ideas                  0.699   0.106                 
## curious                0.406   0.168   0.137         
## ingenious              0.580          -0.108   0.196 
## imagination            0.689                         
## inventive     -0.153   0.799                         
## artistic               0.577  -0.125   0.124         
## routineR       0.139  -0.243                   0.191 
## reflect                0.648   0.153                 
## nonartisticR          -0.380                         
## sophisticated          0.567  -0.239                 
## 
##                Factor1 Factor2 Factor3 Factor4 Factor5
## SS loadings      4.384   3.869   3.847   3.635   3.408
## Proportion Var   0.100   0.088   0.087   0.083   0.077
## Cumulative Var   0.100   0.188   0.275   0.358   0.435
## 
## Factor Correlations:
##         Factor1 Factor2 Factor3 Factor4 Factor5
## Factor1   1.000   0.309   0.129   0.326  -0.426
## Factor2   0.309   1.000   0.242   0.209  -0.211
## Factor3   0.129   0.242   1.000   0.207  -0.114
## Factor4   0.326   0.209   0.207   1.000  -0.392
## Factor5  -0.426  -0.211  -0.114  -0.392   1.000
## 
## Test of the hypothesis that 5 factors are sufficient.
## The chi square statistic is 1329.56 on 736 degrees of freedom.
## The p-value is 1.08e-36

1.5.2.1 Useful to examine first two factors visually

  • We will need to extract the factor loading
PM.load = mle.PM$loadings[,1:2]
plot(PM.load, type="n")
text(PM.load,labels=colnames(DataSet),cex=.75) # add variable names

1.6 Interpret the Loadings

  • This loading can be interpreted as like a part correlations (the variables are all controlled for)
  • You have to name the construct based on the pattern of positive and negative loadings
  • You could reverse score the loadings to make it easier
  • Lets name our factors from the varimax and promax and see what our 5 personality constructs might be

1.7 Extract factor scores

  • You can construct factor scores for each subject and conduct additional analysis
  • For example, you boiled down these items to 5 factors, you can run 5 regression on these constructs (they could be predictors or predicted)
  • There are many ways to extract scores per person (how much each person fits with the construct), most common are: Regression and Bartlett
  • Regression: use the estimated parameters from a factor analysis to define linear combinations of observed variables that generate factor scores. The scores may be correlated even when factors are orthogonal
  • Bartlett method corrects for bias
  • Other methods try to correct the correlation issue
mle.VM.Score.R <- factanal(DataSet,factors=5, rotation="varimax",  scores = "regression")$scores
#Cor
round(cor(mle.VM.Score.R),3)
##         Factor1 Factor2 Factor3 Factor4 Factor5
## Factor1   1.000  -0.023  -0.011  -0.027  -0.045
## Factor2  -0.023   1.000   0.030   0.023   0.007
## Factor3  -0.011   0.030   1.000   0.013   0.008
## Factor4  -0.027   0.023   0.013   1.000   0.051
## Factor5  -0.045   0.007   0.008   0.051   1.000
# Mean
round(apply(mle.VM.Score.R,2, mean),3)
## Factor1 Factor2 Factor3 Factor4 Factor5 
##       0       0       0       0       0
# SD
round(apply(mle.VM.Score.R,2, sd),3)
## Factor1 Factor2 Factor3 Factor4 Factor5 
##   0.934   0.939   0.935   0.918   0.907
mle.VM.Score.B <- factanal(DataSet,factors=5, rotation="varimax",  scores = "Bartlett")$scores
#Cor
round(cor(mle.VM.Score.B),3)
##         Factor1 Factor2 Factor3 Factor4 Factor5
## Factor1   1.000   0.022   0.009   0.024   0.044
## Factor2   0.022   1.000  -0.029  -0.022  -0.004
## Factor3   0.009  -0.029   1.000  -0.011  -0.007
## Factor4   0.024  -0.022  -0.011   1.000  -0.050
## Factor5   0.044  -0.004  -0.007  -0.050   1.000
# Mean
round(apply(mle.VM.Score.B,2, mean),3)
## Factor1 Factor2 Factor3 Factor4 Factor5 
##       0       0       0       0       0
# SD
round(apply(mle.VM.Score.B,2, sd),3)
## Factor1 Factor2 Factor3 Factor4 Factor5 
##   1.072   1.066   1.070   1.091   1.104

2 References

Abdi, H. (2003). Factor rotations in factor analyses. Encyclopedia for Research Methods for the Social Sciences. Sage: Thousand Oaks, CA, 792-795.

Howard, M. C. (2016). A Review of Exploratory Factor Analysis Decisions and Overview of Current Practices: What We Are Doing and How Can We Improve?. International Journal of Human-Computer Interaction, 32(1), 51-62.

Yong, A. G., & Pearce, S. (2013). A beginner’s guide to factor analysis: Focusing on exploratory factor analysis. Tutorials in Quantitative Methods for Psychology, 9(2), 79-94.

LS0tDQp0aXRsZTogJ0V4cGxvcmF0b3J5IEZhY3RvciBBbmFseXNpcycNCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBmb250c2l6ZTogOHB0DQogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6IGZsYXRseQ0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBubw0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KG1lc3NhZ2UgPSBGQUxTRSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldCh3YXJuaW5nID0gIEZBTFNFKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy53aWR0aD01Ljc1KQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy5oZWlnaHQ9NS43NSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcuYWxpZ249J2NlbnRlcicpIA0KYGBgDQoNCiMgRUZBDQotIEEgbXVsdGl2YXJpYXRlIG1ldGhvZCBpbiB3aGljaCB0byBkZXRlcm1pbmUgdGhlIHJlbGF0aW9uc2hpcHMgYW5kIHBhdHRlcm5zIGJldHdlZW4gdmFyaWFibGVzDQotIEVGQSBpcyBkaWZmZXJlbnQgZnJvbSBDb25maXJtYXRvcnkgRmFjdG9yIEFuYWx5c2lzIChDRkEpIGluIHdoaWNoIHlvdSBhcmUgdHJ5aW5nIHRvIGNvbmZpcm0gYSBzcGVjaWZpYyBzZXQgYXR0ZW1wdHMgdG8gY29uZmlybSBob3cgdGhpbmdzIHNob3VsZCBiZSByZWxhdGVkIHRvIG9uZSBhbm90aGVyIHVzaW5nIGEgU0VNIG1vZGVsDQotIEVGQSBjYW4gYmUgdXNlZCB0byBpbiBtYW55IHdheXMgKFlvbmcgJiBQZWFyY2UsIDIwMTMpDQoNCjEuIERldmVsb3AgU2NhbGVzOiBzdWNoIGFzIEJpZyA1IFBlcnNvbmFsaXR5IA0KMi4gSXRlbSdzIEFuYWx5c2lzOiB3aGljaCB0ZXN0IGl0ZW1zIGdvIHRvZ2V0aGVyICh0byB0ZXN0IHNwZWNpZmljIGNvbnN0cnVjdHMpDQozLiBEaW1lbnNpb25hbGl0eSByZWR1Y3Rpb246IFdoaWNoIGl0ZW1zL3F1ZXN0aW9ucy9mZWF0dXJlcyBhcmUgbW9zdCBpbXBvcnRhbnQgKHN0cmVuZ3RoIG9mIHdoaWNoIHRoaW5ncyBiaW5kIHRvZ2V0aGVyKSBhbmQgY3JlYXRlICJmYWN0b3Igc2NvcmVzIiByZXByZXNlbnRpbmcgdW5kZXJseWluZyBjb25zdHJ1Y3RzIGZvciB1c2UgaW4gb3RoZXIgYW5hbHlzZXMuDQoNCi0gRUZBIGV4YW1pbmVzIGEgcGF0dGVybiBvZiBjb3JyZWxhdGlvbnMvY292YXJpYW5jZXMgYmV0d2VlbiB0aGUgaXRlbXMgYW5kIHRyaWVzIHRvIGRldGVybWluZSBpZiB0aGV5IGFyZSBpbmZsdWVuY2VkIGJ5IHRoZSBzYW1lIG9yIGEgZGlmZmVyZW50IHVuZGVybHlpbmcgZmFjdG9yLg0KDQoNCiMjIENvbGxlY3QgSXRlbXMgbWVhc3VyZWQgaW4gdGhlIHNhbWUgdW5pdHMNCi0gWW91IG1pZ2h0IG5lZWQgdG8gcmV2ZXJzZSBzY29yZSB0aGUgaXRlbXMgb3IgcmVjb2RlL3RyYW5zZm9ybSB0aGVtDQoNCiMjIyBWaXN1YWxpemUgdGhlIHBhdHRlcm5zIGluIHRoZSBkYXRhIA0KLSBoZWxwZnVsIHRvIGxvb2sgYXQgdGhlIHBhdHRlcm5zIGJlZm9yZSB5b3UgZ28gZnVydGhlcg0KDQotIFRha2UgZGF0YSAoQkZJMjI4KSBvZiB0aGUgInN0dWR5IG9uIHBlcnNvbmFsaXR5IGFuZCByZWxhdGlvbnNoaXAgc2F0aXNmYWN0aW9uIChMdW8sIDIwMDUpLiBUaGUNCnBhcnRpY2lwYW50cyB3ZXJlIDIyOCB1bmRlcmdyYWR1YXRlIHN0dWRlbnRzIGF0IGEgbGFyZ2UgcHVibGljIHVuaXZlcnNpdHkgaW4gdGhlIFVTLiBUaGUgZGF0YSB3ZXJlDQpwYXJ0aWNpcGFudHMnIHNlbGYtcmF0aW5ncyBvbiB0aGUgNDQgaXRlbXMgb2YgdGhlIEJpZyBGaXZlIEludmVudG9yeSAoSm9obiwgRG9uYWh1ZSwgJiBrZW50bGUsIDE5OTEpLg0KVGhlc2UgaXRlbXMgYXJlIExpa2VydCB2YXJpYWJsZXM6IGRpc2FncmVlIHN0cm9uZ2x5ICgxKSwgZGlzYWdyZWUgYSBsaXR0bGUgKDIpLCBuZWl0aGVyIGFncmVlIG5vciBkaXNhZ3JlZQ0KKDMpLCBhZ3JlZSBhIGxpdHRsZSAoNCksIGFuZCBhZ3JlZSBzdHJvbmdseSAoNSkiLiBUYWtlbiBmcm9tIHRoZSBFRkF1dGlsaXRpZXMgcGFja2FnZS4NCg0KYGBge3IsZmlnLndpZHRoPTcuNzUsIGZpZy5oZWlnaHQ9Ny43NSB9DQpsaWJyYXJ5KHBzeWNoKQ0KbGlicmFyeShjb3JycGxvdCkNCmxpYnJhcnkoRUZBdXRpbGl0aWVzKQ0KZGF0YShCRkkyMjgpDQpEYXRhU2V0PC1CRkkyMjgNCmNvcnJwbG90KGNvcihEYXRhU2V0KSwgb3JkZXIgPSAiaGNsdXN0IiwgdGwuY29sPSdibGFjaycsIHRsLmNleD0uNzUpIA0KYGBgDQoNClxwYWdlYnJlYWsNCg0KIyMgRG8gSSBoYXZlIGVub3VnaCBkYXRhIHRvIHByb2NlZWQ/IA0KLSBLYWlzZXIgTWV5ZXIgT2xraW4gKEtNTykgTWVhc3VyZSBvZiBTYW1wbGluZyBBZGVxdWFjeSAoSG93YXJkLCAyMDE2KQ0KLSBZb3UgY291bGQgcmVtb3ZlIGFueXRoaW5nIGJlbG93IC42IGFuZCBpZiB0aGUgb3ZlcmFsbCBpcyBiZWxvdyAuNiB5b3UgY2Fubm90IGRvIGEgRUZBDQoNCktNTyAgICAgICAgICB8ICBJbnRlcnByZWF0aW9uIHwgVXNlPw0KLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tfC0tLS0tDQowLjAwIHRvIDAuNTAgfCAgVW5hY2NlcHRhYmxlICB8ICBObw0KMC41MCB0byAwLjYwIHwgIE1pc2VyYWJsZSAgICAgfCBObw0KMC42MCB0byAwLjcwIHwgIE1lZGlvY3JlICAgICAgfCBZZXMNCjAuNzAgdG8gMC44MCB8ICBNaWRkbGluZyAgICAgIHwgWWVzDQowLjgwIHRvIDAuOTAgfCAgTWVyaXRvcmlvdXMgICB8IFllcw0KMC45MCB0byAxLjAwIHwgIE1hcnZlbG91cyAgICAgfCBZZXMNCg0KYGBge3J9DQpLTU8oQkZJMjI4KQ0KYGBgDQoNCiMjIEdldCBjb3JyZWxhdGlvbi9jb3ZhcmlhbmNlcyBtYXRyaXgNCi0gVGhlIHR5cGUgb2YgY29ycmVsYXRpb24gaXMgaW1wb3J0YW50OiANCi0gSWYgeW91IGhhdmUgb3JkaW5hbCBvciBub21pbmFsIGRhdGEgeW91IG1pZ2h0IHdhbnQgdG8gc3dpdGNoIGZyb20gUGVhcnNvbiB0byBwb2x5LSBvciB0ZXRyYS1jaG9yaWMgY29ycmVsYXRpb25zIA0KLSBNb3N0IHBzeWNob2xvZ2lzdHMganVzdCBpZ25vcmUgdGhpcyBhbmQgdXNlIFBlYXJzb24NCg0KYGBge3J9DQpDTTwtY29yKERhdGFTZXQsIHVzZT0iY29tcGxldGUub2JzIikNCmBgYA0KDQojIyBTZWxlY3QgdGhlIG51bWJlciBvZiBmYWN0b3JzIA0KLSBZb3UgbWlnaHQgaGF2ZSBhIHNwZWNpZmljIG51bWJlciBpbiBtaW5kIG9yIGl0IGNhbiBiZSBhcHByb3hpbWF0ZWQgZnJvbSB0aGUgZGF0YS4gDQoNCkEpIFRoZSBLYWlzZXIgY3JpdGVyaW9uOiBhIG51bWJlciBvZiBmYWN0b3JzIGVxdWFsIHRvIHRoZSBudW1iZXIgb2YgdGhlICoqZWlnZW52YWx1ZXMqKiBvZiB0aGUgY29ycmVsYXRpb24gbWF0cml4IHRoYXQgYXJlIGdyZWF0ZXIgdGhhbiBvbmUuDQpCKSBUaGUgIlNjcmVlIHRlc3QiIGlzIGEgbG90IG9mIHRoZSBlaWdlbnZhbHVlcyBvZiB0aGUgY29ycmVsYXRpb24gbWF0cml4IGluIGRlc2NlbmRpbmcgb3JkZXINCg0KLSBXaGF0IGFyZSAqKmVpZ2VudmFsdWVzKio/IGh0dHA6Ly9zZXRvc2EuaW8vZXYvZWlnZW52ZWN0b3JzLWFuZC1laWdlbnZhbHVlcy8NCg0KU2VsZWN0aW5nIGZyb20gdGhlIHNjcmVlIHBsb3QgY2FuIGJlIGFjY29tcGxpc2hlZCBpbiBhIGZldyBkaWZmZXJlbnQgd2F5czoNCg0KLSBTZWUgaHR0cDovL3d3dy5lbXBvd2Vyc3RhdHMuY29tL21hbnVhbHMvcGFwZXIvc2NyZWUucGRmIzENCi0gVmlzdWFsbHk6IFdoZW4gZG9lcyB0aGUgcGxvdCBsZXZlbCBvZmYgDQotIFBhcmFsbGVsIEFuYWx5c2lzOiAoYmFzaWNhbGx5IHdoYXQgcmFuZG9tIGNvcnJlbGF0aW9ucyB3b3VsZCBnaXZlIHlvdSBmb3IgdGhlIHNhbWUgbnVtYmVyIG9mIHN1YmplY3RzIGFuZCBpdGVtcykNCi0gIE9wdGltYWwgQ29vcmRpbmF0ZTogZXh0cmFwb2xhdGlvbiBvZiB0aGUgcHJlY2VkaW5nIGVpZ2VudmFsdWUgYnkgYSByZWdyZXNzaW9uIGxpbmUgYmV0d2VlbiB0aGUgZWlnZW52YWx1ZSBjb29yZGluYXRlcyBhbmQgdGhlIGxhc3QgZWlnZW52YWx1ZSBjb29yZGluYXRlcw0KLSBBY2NlbGVyYXRpb24gRmFjdG9yOiBXaGVuIHRoZSBzbG9wZSBjaGFuZ2UgbW9zdCBhYnJ1cHRseSAoZWxib3cpDQoNCmBgYHtyfQ0KbGlicmFyeShuRmFjdG9ycykNCg0KZXYgPC0gZWlnZW4oQ00pICMgZ2V0IGVpZ2VudmFsdWVzDQphcCA8LSBwYXJhbGxlbChzdWJqZWN0PW5yb3coRGF0YVNldCksdmFyPW5jb2woRGF0YVNldCksDQogIHJlcD0xMDAsY2VudD0uMDUpDQpuUyA8LSBuU2NyZWUoeD1ldiR2YWx1ZXMsIGFwYXJhbGxlbD1hcCRlaWdlbiRxZXZwZWEpDQpwbG90blNjcmVlKG5TKQ0KYGBgDQoNCi0gUmVzdWx0cyBhbGwgc2F5IDYsIGJ1dCB3ZSB3aWxsIGZvcmNlIGEgNSBmYWN0b3Igc29sdXRpb24gdG8gbWF0Y2ggdGhlIEJpZyA1DQoNCiMjIyBFeHRyYWN0IHlvdXIgaW5pdGlhbCBzb2x1dGlvbg0KLSBFeHRyYWN0aW9uIG1ldGhvZHM6ICBtYXhpbXVtIGxpa2VsaWhvb2QgKE1MKSwgcHJpbmNpcGFsIGNvbXBvbmVudHMgYW5hbHlzaXMgKFBDQSksIGFuZCBwcmluY2lwYWwgYXhpcyBmYWN0b3JpbmcgKFBBRikuIA0KLSBQQ0EgaXMgbm90IGEgZmFjdG9yIGFuYWx5c2lzIG1ldGhvZCwgYnV0IGl0IG9mdGVuIHVzZWQgYXMgaXQgdHJpZXMgdG8gcHV0IG1vc3Qgb2YgdGhlIHZhcmlhbmNlIGludG8gdGhlIGZpcnN0IGZhY3RvciANCi0gTUwgaXMgb2Z0ZW4gdXNlZCBhbmQsIGJ1dCBpdHMgc2Vuc2l0aXZlIHRvIG5vcm1hbGl0eSB2aW9sYXRpb24NCi0gUEFGIGlzIGxlc3Mgc2Vuc2l0aXZlIHRvIG5vcm1hbGl0eSB2aW9sYXRpb24sIGJ1dCBsZXNzIGdlbmVyYWxpemFibGUNCi0gVGhlcmUgYXJlIG1hbnkgb3RoZXIgdHlwZXMsIHN1Y2ggYXMgQmF5ZXNpYW4gbWV0aG9kcyBhbmQgbWV0aG9kcyBmb3Igc3BlY2lmaWMgdHlwZXMgb2YgZGF0YSAoYmVzdCB0byByZXNlYXJjaCBlYWNoIGZvciB5b3VyIHNwZWNpZmljIGlzc3VlIGF0IGhhbmQpDQoNCmBgYHtyfQ0KbWxlLkludGlhbCA8LSBmYWN0YW5hbChjb3ZtYXQ9Y29yKERhdGFTZXQsdXNlPSJjb21wbGV0ZS5vYnMiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgZmFjdG9ycz01LCByb3RhdGlvbj0ibm9uZSIpDQpwcmludChtbGUuSW50aWFsJGxvYWRpbmdzLCBjdXRvZmY9MC4zKQ0KYGBgDQoNCg0KIyMgUm90YXRlIHlvdXIgZmFjdG9ycyB0byBhIGZpbmFsIHNvbHV0aW9uDQotIFRoaW5rIG9mIGVhY2ggZmFjdG9yIGEgZGltZW5zaW9uIGFuZCB0aGUgcHJvYmxlbSBpcyB0aGVyZSBpcyBhIG5lYXIgaW5maW5pdGUgc2V0IG9mIGRpbWVuc2lvbnMgdGhhdCBjb3VsZCBleHBsYWluIHlvdXIgZGF0YQ0KLSBXZSBuZWVkIGEgd2F5IHRvIGhlbHAgY29tZSB1cCB3aXRoIGEgc29sdXRpb24gdGhhdCBpcyBtb3JlIGludGVycHJldGFibGUNCi0gQnkgcm90YXRpbmcgeW91ciBmYWN0b3JzIHlvdSBhdHRlbXB0IHRvIGZpbmQgYSBmYWN0b3Igc29sdXRpb24gdGhhdCBpcyBlcXVhbA0KdG8gdGhhdCBvYnRhaW5lZCBpbiB0aGUgaW5pdGlhbCBleHRyYWN0aW9uIGJ1dCB3aGljaCBoYXMgdGhlIHNpbXBsZXN0IGludGVycHJldGF0aW9uDQotIFRoZSBzaW1wbGVzdCBzb2x1dGlvbiBoYXMgNSBmZWF0dXJlcyAoVGh1bmRlcmQsIDE5NDc7IHN1bW1hcml6ZWQgaW4gIEFiZGksIDIwMDMpDQoNCjEuIGVhY2ggcm93IGNvbnRhaW5zIGF0IGxlYXN0IG9uZSB6ZXJvOw0KMi4gZm9yIGVhY2ggY29sdW1uLCB0aGVyZSBhcmUgYXQgbGVhc3QgYXMgbWFueSB6ZXJvcyBhcyB0aGVyZSBhcmUgY29sdW1ucw0KMy4gZm9yIGFueSBwYWlyIG9mIGZhY3RvcnMsIHRoZXJlIGFyZSBzb21lIHZhcmlhYmxlcyB3aXRoIHplcm8gbG9hZGluZ3Mgb24gb25lDQpmYWN0b3IgYW5kIGxhcmdlIGxvYWRpbmdzIG9uIHRoZSBvdGhlciBmYWN0b3I7DQo0LiBmb3IgYW55IHBhaXIgb2YgZmFjdG9ycywgdGhlcmUgaXMgYSBzaXphYmxlIHByb3BvcnRpb24gb2YgemVybyBsb2FkaW5nczsNCjUuIGZvciBhbnkgcGFpciBvZiBmYWN0b3JzLCB0aGVyZSBpcyBvbmx5IGEgc21hbGwgbnVtYmVyIG9mIGxhcmdlIGxvYWRpbmdzDQoNCi0gVGhlcmUgYXJlIG1hbnkgZGlmZmVyZW50IHR5cGVzIG9mIHJvdGF0aW9uLCBidXQgdGhleSBhbGwgdHJ5IGdldCB0aGUgc3Ryb25nZXN0IGVmZmVjdCBvbiB0aGUgc21hbGwgc3Vic2V0IG9mICBpdGVtcy4gDQoNClRoZXJlIGFyZSB0d28gZmFtaWxpZXMgb2Ygcm90YXRpb25zOiANCi0gT3J0aG9nb25hbCByb3RhdGlvbnM6ICB1bmNvcnJlbGF0ZWQgZmFjdG9ycyAoZS5nLiwgKip2YXJpbWF4KiopDQotIE9ibGlxdWUgcm90YXRpb25zOiBwcm9kdWNlIGNvcnJlbGF0ZWQgZmFjdG9ycyAoZS5nLiwgKipwcm9tYXgqKikNCg0KLSBWYXJpbWF4IGlzIHRoZSBtb3N0IHBvcHVsYXIgb3J0aG9nb25hbCByb3RhdGlvbjogInNpbXBsZSBzb2x1dGlvbiBtZWFucyB0aGF0IGVhY2ggZmFjdG9yIGhhcyBhIHNtYWxsIG51bWJlciBvZiBsYXJnZSBsb2FkaW5ncyBhbmQgYSBsYXJnZSBudW1iZXIgb2YgemVybyAob3Igc21hbGwpIGxvYWRpbmdzIiAoQWJkaSwgMjAwMykNCg0KIyMjIE9ydGhvZ29uYWwgUm90YXRpb24NCmBgYHtyfQ0KbWxlLlZNIDwtIGZhY3RhbmFsKERhdGFTZXQsZmFjdG9ycz01LCByb3RhdGlvbj0idmFyaW1heCIpDQpwcmludChtbGUuVk0kbG9hZGluZ3MsIGN1dG9mZj0wLjMpDQpgYGANCg0KDQojIyMjIFVzZWZ1bCB0byBleGFtaW5lIGZpcnN0IHR3byBmYWN0b3JzIHZpc3VhbGx5DQotIFdlIHdpbGwgbmVlZCB0byBleHRhY3QgdGhlIGZhY3RvciBsb2FkaW5nDQoNCmBgYHtyfQ0KVk0ubG9hZCA9IG1sZS5WTSRsb2FkaW5nc1ssMToyXQ0KcGxvdChWTS5sb2FkLCB0eXBlPSJuIikNCnRleHQoVk0ubG9hZCxsYWJlbHM9Y29sbmFtZXMoRGF0YVNldCksY2V4PS43NSkgIyBhZGQgdmFyaWFibGUgbmFtZXMNCmBgYA0KDQojIyMgT2JsaXF1ZSBSb3RhdGlvbg0KLSBXaGVuIHdlIGV4YW1pbmUgdGhlIHByb21heCB3ZSB3aWxsIG5lZWQgdG8gZXhhbWluZSB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBmYWN0b3JzDQoNCmBgYHtyfQ0KbWxlLlBNIDwtIGZhY3RhbmFsKERhdGFTZXQsIGZhY3RvcnM9NSwgDQogICAgICAgICAgICAgICAgICAgcm90YXRpb249InByb21heCIpDQptbGUuUE0NCg0KYGBgDQoNCiMjIyMgVXNlZnVsIHRvIGV4YW1pbmUgZmlyc3QgdHdvIGZhY3RvcnMgdmlzdWFsbHkNCi0gV2Ugd2lsbCBuZWVkIHRvIGV4dHJhY3QgdGhlIGZhY3RvciBsb2FkaW5nDQoNCmBgYHtyfQ0KUE0ubG9hZCA9IG1sZS5QTSRsb2FkaW5nc1ssMToyXQ0KcGxvdChQTS5sb2FkLCB0eXBlPSJuIikNCnRleHQoUE0ubG9hZCxsYWJlbHM9Y29sbmFtZXMoRGF0YVNldCksY2V4PS43NSkgIyBhZGQgdmFyaWFibGUgbmFtZXMNCmBgYA0KDQojIyBJbnRlcnByZXQgdGhlIExvYWRpbmdzDQotIFRoaXMgbG9hZGluZyBjYW4gYmUgaW50ZXJwcmV0ZWQgYXMgbGlrZSBhIHBhcnQgY29ycmVsYXRpb25zICh0aGUgdmFyaWFibGVzIGFyZSBhbGwgY29udHJvbGxlZCBmb3IpDQotIFlvdSBoYXZlIHRvIG5hbWUgdGhlIGNvbnN0cnVjdCBiYXNlZCBvbiB0aGUgcGF0dGVybiBvZiBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgbG9hZGluZ3MNCi0gWW91IGNvdWxkIHJldmVyc2Ugc2NvcmUgdGhlIGxvYWRpbmdzIHRvIG1ha2UgaXQgZWFzaWVyDQotIExldHMgbmFtZSBvdXIgZmFjdG9ycyBmcm9tIHRoZSB2YXJpbWF4IGFuZCBwcm9tYXggYW5kIHNlZSB3aGF0IG91ciA1IHBlcnNvbmFsaXR5IGNvbnN0cnVjdHMgbWlnaHQgYmUNCg0KIyMgIEV4dHJhY3QgZmFjdG9yIHNjb3Jlcw0KLSBZb3UgY2FuIGNvbnN0cnVjdCBmYWN0b3Igc2NvcmVzIGZvciBlYWNoIHN1YmplY3QgYW5kIGNvbmR1Y3QgYWRkaXRpb25hbCBhbmFseXNpcw0KLSBGb3IgZXhhbXBsZSwgeW91IGJvaWxlZCBkb3duIHRoZXNlIGl0ZW1zIHRvIDUgZmFjdG9ycywgeW91IGNhbiBydW4gNSByZWdyZXNzaW9uIG9uIHRoZXNlIGNvbnN0cnVjdHMgKHRoZXkgY291bGQgYmUgcHJlZGljdG9ycyBvciBwcmVkaWN0ZWQpDQotIFRoZXJlIGFyZSBtYW55IHdheXMgdG8gZXh0cmFjdCBzY29yZXMgcGVyIHBlcnNvbiAoaG93IG11Y2ggZWFjaCBwZXJzb24gZml0cyB3aXRoIHRoZSBjb25zdHJ1Y3QpLCBtb3N0IGNvbW1vbiBhcmU6IFJlZ3Jlc3Npb24gYW5kIEJhcnRsZXR0DQotIFJlZ3Jlc3Npb246IHVzZSB0aGUgZXN0aW1hdGVkIHBhcmFtZXRlcnMgZnJvbSBhIGZhY3RvciBhbmFseXNpcyB0byBkZWZpbmUgbGluZWFyIGNvbWJpbmF0aW9ucyBvZiBvYnNlcnZlZCB2YXJpYWJsZXMgdGhhdCBnZW5lcmF0ZSBmYWN0b3Igc2NvcmVzLiBUaGUgc2NvcmVzIG1heSBiZSBjb3JyZWxhdGVkIGV2ZW4gd2hlbiBmYWN0b3JzIGFyZSBvcnRob2dvbmFsDQotIEJhcnRsZXR0IG1ldGhvZCBjb3JyZWN0cyBmb3IgYmlhcw0KLSBPdGhlciBtZXRob2RzIHRyeSB0byBjb3JyZWN0IHRoZSBjb3JyZWxhdGlvbiBpc3N1ZSANCg0KYGBge3J9DQptbGUuVk0uU2NvcmUuUiA8LSBmYWN0YW5hbChEYXRhU2V0LGZhY3RvcnM9NSwgcm90YXRpb249InZhcmltYXgiLCAgc2NvcmVzID0gInJlZ3Jlc3Npb24iKSRzY29yZXMNCiNDb3INCnJvdW5kKGNvcihtbGUuVk0uU2NvcmUuUiksMykNCiMgTWVhbg0Kcm91bmQoYXBwbHkobWxlLlZNLlNjb3JlLlIsMiwgbWVhbiksMykNCiMgU0QNCnJvdW5kKGFwcGx5KG1sZS5WTS5TY29yZS5SLDIsIHNkKSwzKQ0KDQptbGUuVk0uU2NvcmUuQiA8LSBmYWN0YW5hbChEYXRhU2V0LGZhY3RvcnM9NSwgcm90YXRpb249InZhcmltYXgiLCAgc2NvcmVzID0gIkJhcnRsZXR0Iikkc2NvcmVzDQojQ29yDQpyb3VuZChjb3IobWxlLlZNLlNjb3JlLkIpLDMpDQojIE1lYW4NCnJvdW5kKGFwcGx5KG1sZS5WTS5TY29yZS5CLDIsIG1lYW4pLDMpDQojIFNEDQpyb3VuZChhcHBseShtbGUuVk0uU2NvcmUuQiwyLCBzZCksMykNCmBgYA0KDQojIFJlZmVyZW5jZXMNCg0KQWJkaSwgSC4gKDIwMDMpLiBGYWN0b3Igcm90YXRpb25zIGluIGZhY3RvciBhbmFseXNlcy4gRW5jeWNsb3BlZGlhIGZvciBSZXNlYXJjaCBNZXRob2RzIGZvciB0aGUgU29jaWFsIFNjaWVuY2VzLiBTYWdlOiBUaG91c2FuZCBPYWtzLCBDQSwgNzkyLTc5NS4NCg0KSG93YXJkLCBNLiBDLiAoMjAxNikuIEEgUmV2aWV3IG9mIEV4cGxvcmF0b3J5IEZhY3RvciBBbmFseXNpcyBEZWNpc2lvbnMgYW5kIE92ZXJ2aWV3IG9mIEN1cnJlbnQgUHJhY3RpY2VzOiBXaGF0IFdlIEFyZSBEb2luZyBhbmQgSG93IENhbiBXZSBJbXByb3ZlPy4gSW50ZXJuYXRpb25hbCBKb3VybmFsIG9mIEh1bWFuLUNvbXB1dGVyIEludGVyYWN0aW9uLCAzMigxKSwgNTEtNjIuDQoNCllvbmcsIEEuIEcuLCAmIFBlYXJjZSwgUy4gKDIwMTMpLiBBIGJlZ2lubmVyJ3MgZ3VpZGUgdG8gZmFjdG9yIGFuYWx5c2lzOiBGb2N1c2luZyBvbiBleHBsb3JhdG9yeSBmYWN0b3IgYW5hbHlzaXMuIFR1dG9yaWFscyBpbiBRdWFudGl0YXRpdmUgTWV0aG9kcyBmb3IgUHN5Y2hvbG9neSwgOSgyKSwgNzktOTQuDQoNCg0KDQoNCjxzY3JpcHQ+DQogIChmdW5jdGlvbihpLHMsbyxnLHIsYSxtKXtpWydHb29nbGVBbmFseXRpY3NPYmplY3QnXT1yO2lbcl09aVtyXXx8ZnVuY3Rpb24oKXsNCiAgKGlbcl0ucT1pW3JdLnF8fFtdKS5wdXNoKGFyZ3VtZW50cyl9LGlbcl0ubD0xKm5ldyBEYXRlKCk7YT1zLmNyZWF0ZUVsZW1lbnQobyksDQogIG09cy5nZXRFbGVtZW50c0J5VGFnTmFtZShvKVswXTthLmFzeW5jPTE7YS5zcmM9ZzttLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGEsbSkNCiAgfSkod2luZG93LGRvY3VtZW50LCdzY3JpcHQnLCdodHRwczovL3d3dy5nb29nbGUtYW5hbHl0aWNzLmNvbS9hbmFseXRpY3MuanMnLCdnYScpOw0KDQogIGdhKCdjcmVhdGUnLCAnVUEtOTA0MTUxNjAtMScsICdhdXRvJyk7DQogIGdhKCdzZW5kJywgJ3BhZ2V2aWV3Jyk7DQoNCjwvc2NyaXB0Pg==