Um analista de mercado quer estudar as relações estruturais entre quatro indicadores financeiros provenientes de 45 empresas.

Rótulos: Código da empresa (Cód_Emp)

Indicadores: Prazo médio de recebimento de vendas (PMRV, em dias); Endividamento (em %); Vendas (em R$ x mil); Margem líquida de vendas (em %).

# digite o local correto do arquivo
Indic_finan_Fatorial <- read_excel("Indic_finan_Fatorial.xls")
head(Indic_finan_Fatorial)
dados <- Indic_finan_Fatorial[,2:5]
head(dados)
# Estatísticas Descritivas
describe(dados)
dados 

 4  Variables      45  Observations
---------------------------------------------------------------------------------------------------
PMRV 
      n missing  unique    Info    Mean     .05     .10     .25     .50     .75     .90     .95 
     45       0      38       1   53.13   12.20   15.41   25.68   49.22   82.39   96.30   97.16 

lowest :  6.42  7.49 11.77 13.91 14.98, highest: 95.23 96.30 97.37 99.51 99.80 
---------------------------------------------------------------------------------------------------
Endividamento 
      n missing  unique    Info    Mean     .05     .10     .25     .50     .75     .90     .95 
     45       0      44       1   31.71   16.46   17.68   22.00   29.75   39.00   48.49   52.49 

lowest : 14.77 15.09 16.26 17.23 17.55, highest: 48.58 50.61 52.97 53.50 69.44 
---------------------------------------------------------------------------------------------------
Vendas 
      n missing  unique    Info    Mean     .05     .10     .25     .50     .75     .90     .95 
     45       0      45       1    3989    2080    2236    2921    3719    4770    6167    6765 

lowest : 1981 2003 2074 2106 2129, highest: 6390 6637 6797 6953 9641 
---------------------------------------------------------------------------------------------------
Margem_liquida 
      n missing  unique    Info    Mean     .05     .10     .25     .50     .75     .90     .95 
     45       0      37       1   13.22   8.736   9.138  10.165  13.054  16.906  17.848  18.062 

lowest :  8.453  8.560  8.700  8.881  9.095, highest: 17.240 17.655 17.976 18.083 18.190 
---------------------------------------------------------------------------------------------------
boxplot(dados)

dados.pad <- scale(dados)
boxplot(dados.pad)

O box-plot permite a identificação de possíveis outliers (univariados). Pode-se pensar na exclusão desses dados. Cuidado!

# outliers
# Billor, N., Hadi, A. S., and Velleman , P. F. (2000). BACON: Blocked Adaptive Computationally-Efficient Outlier Nominators; Computational Statistics and Data Analysis 34, 279–298.
outliers <- mvBACON(dados)
MV-BACON (subset no. 1): 16 of 45 (35.56 %)
MV-BACON (subset no. 2): 38 of 45 (84.44 %)
MV-BACON (subset no. 3): 40 of 45 (88.89 %)
MV-BACON (subset no. 4): 41 of 45 (91.11 %)
MV-BACON (subset no. 5): 41 of 45 (91.11 %)
# outliers
# table(Indic_finan_Fatorial$Cod_Emp, outliers$subset)
plot(Indic_finan_Fatorial$Cod_Emp, outliers$subset)

# gráfico com o pacote ggplot2
dados2 <- data.frame(Indic_finan_Fatorial$Cod_Emp, outliers$subset)
ggplot(data = dados2, aes(x = Indic_finan_Fatorial.Cod_Emp, y = outliers.subset )) +
  geom_point()+
  geom_text(aes(label=Indic_finan_Fatorial.Cod_Emp))

# Verificação de normalidade 
# http://www.biosoft.hacettepe.edu.tr/MVN/
# testes univariados
uniPlot(dados, type = "qqplot") # creates univariate Q-Q plots

uniPlot(dados, type = "histogram") # creates univariate histograms

# univariate normality tests: 
# SW: Shapiro-Wilk,
# CVM: Cramer-von Mises,
# Lillie: Lilliefors (Kolmogorov-Smirnov),
# SF: Shapiro-Francia,
# AD: Anderson-Darling
uniNorm(dados, type = "SW", desc=F)
$`Descriptive Statistics`
NULL

$`Shapiro-Wilk's Normality Test`
uniNorm(dados, type = "CVM" , desc = F)
$`Descriptive Statistics`
NULL

$`Cramer-von Mises's Normality Test`
uniNorm(dados, type = "Lillie", desc = F)
$`Descriptive Statistics`
NULL

$`Lilliefors (Kolmogorov-Smirnov)'s Normality Test`
uniNorm(dados, type = "SF", desc = F)
$`Descriptive Statistics`
NULL

$`Shapiro-Francia's Normality Test`
uniNorm(dados, type = "AD", desc = F)
$`Descriptive Statistics`
NULL

$`Anderson-Darling's Normality Test`
# testes multivariados
hzTest(dados)
  Henze-Zirkler's Multivariate Normality Test 
--------------------------------------------- 
  data : dados 

  HZ      : 1.2577 
  p-value : 0.0001032643 

  Result  : Data are not multivariate normal. 
--------------------------------------------- 
roystonTest(dados)
  Royston's Multivariate Normality Test 
--------------------------------------------- 
  data : dados 

  H       : 35.05432 
  p-value : 4.837587e-07 

  Result  : Data are not multivariate normal. 
--------------------------------------------- 
mardiaTest(dados)
   Mardia's Multivariate Normality Test 
--------------------------------------- 
   data : dados 

   g1p            : 4.203704 
   chi.skew       : 31.52778 
   p.value.skew   : 0.04859737 

   g2p            : 23.68478 
   z.kurtosis     : -0.1526065 
   p.value.kurt   : 0.8787086 

   chi.small.skew : 34.53042 
   p.value.small  : 0.02275265 

   Result          : Data are not multivariate normal. 
--------------------------------------- 
# correlação 
mcor <- rcorr(as.matrix(dados))
mcor
               PMRV Endividamento Vendas Margem_liquida
PMRV           1.00          0.23   0.63           0.60
Endividamento  0.23          1.00   0.24          -0.10
Vendas         0.63          0.24   1.00           0.58
Margem_liquida 0.60         -0.10   0.58           1.00

n= 45 


P
               PMRV   Endividamento Vendas Margem_liquida
PMRV                  0.1210        0.0000 0.0000        
Endividamento  0.1210               0.1148 0.5227        
Vendas         0.0000 0.1148               0.0000        
Margem_liquida 0.0000 0.5227        0.0000               
R <- cor(dados)
corrplot(R, method="number",type="upper", order = "hclust", tl.srt = 45)

corrplot(R, method="circle",type="full", order = "hclust", tl.srt = 45)

# ?corrplot

Observa-se que há altas correlações entre as variáveis Vendas, PMRV e Margem_líquida (p-valor < 5%) Existe considerável número de correlações superiores a 0,30 a normalidade multivariada não pode ser evidenciada, contudo podemos usar métodos robustos para estrair os fatores, como por exemplo o método dos componentes principais.

################################################################
#Partial correlation matrix
################################################################
partial.cor <- function (x)
{
R <- cor(x)
RI <- solve(R)
D <- 1/sqrt(diag(RI))
Rp <- -RI * (D %o% D)
diag(Rp) <- 0
rownames(Rp) <- colnames(Rp) <- colnames(x)
Rp
}
mat_anti_imagem <- -partial.cor(dados)
mat_anti_imagem
                     PMRV Endividamento     Vendas Margem_liquida
PMRV            0.0000000    -0.2520021 -0.3380240     -0.4265296
Endividamento  -0.2520021     0.0000000 -0.2462634      0.3685448
Vendas         -0.3380240    -0.2462634  0.0000000     -0.3869238
Margem_liquida -0.4265296     0.3685448 -0.3869238      0.0000000
################################################################
# The Bartlett's test statistic indicates to what extent we deviate from the reference situation |R| = 1.
################################################################
Bartlett.sphericity.test <- function(x)
{
  method <- "Bartlett's test of sphericity"
  data.name <- deparse(substitute(x))
  x <- subset(x, complete.cases(x)) # Omit missing values
  n <- nrow(x)
  p <- ncol(x)
  chisq <- (1-n+(2*p+5)/6)*log(det(cor(x)))
  df <- p*(p-1)/2
  p.value <- pchisq(chisq, df, lower.tail=FALSE)
  names(chisq) <- "X-squared"
  names(df) <- "df"
  return(structure(list(statistic=chisq, parameter=df, p.value=p.value,
                        method=method, data.name=data.name), class="htest"))
}
Bartlett.sphericity.test(dados)

    Bartlett's test of sphericity

data:  dados
X-squared = 53.165, df = 6, p-value = 1.087e-09
################################################################
# KMO index
################################################################
kmo <- function(x)
{
  x <- subset(x, complete.cases(x)) # Omit missing values
  r <- cor(x) # Correlation matrix
  r2 <- r^2 # Squared correlation coefficients
  i <- solve(r) # Inverse matrix of correlation matrix
  d <- diag(i) # Diagonal elements of inverse matrix
  p2 <- (-i/sqrt(outer(d, d)))^2 # Squared partial correlation coefficients
  diag(r2) <- diag(p2) <- 0 # Delete diagonal elements
  KMO <- sum(r2)/(sum(r2)+sum(p2))
  MSA <- colSums(r2)/(colSums(r2)+colSums(p2))
  return(list(KMO=KMO, MSA=MSA))
}
kmo(dados)
$KMO
[1] 0.6309025

$MSA
          PMRV  Endividamento         Vendas Margem_liquida 
     0.6909296      0.3183487      0.7071779      0.6008364 

o KMO torna razoável a aplicação da AF o teste de esfericidade de Bartlett rejeita a hipótese de a matriz de correlações ser identidade
O MSA é adequado, com exceção da variável individamento (0,318). Se a comunalidade for alta, esta variável pode ser sozinha um Fator.

n.dados <- length(dados)
fit <- principal(dados, nfactors=n.dados, rotate="none")
fit
Principal Components Analysis
Call: principal(r = dados, nfactors = n.dados, rotate = "none")
Standardized loadings (pattern matrix) based upon correlation matrix
                PC1   PC2   PC3   PC4 h2      u2 com
PMRV           0.88  0.04  0.40 -0.27  1 2.2e-16 1.6
Endividamento  0.27  0.94  0.04  0.21  1 1.1e-16 1.3
Vendas         0.87  0.06 -0.46 -0.17  1 1.0e-15 1.6
Margem_liquida 0.81 -0.43  0.06  0.41  1 0.0e+00 2.1

                       PC1  PC2  PC3  PC4
SS loadings           2.24 1.07 0.38 0.31
Proportion Var        0.56 0.27 0.09 0.08
Cumulative Var        0.56 0.83 0.92 1.00
Proportion Explained  0.56 0.27 0.09 0.08
Cumulative Proportion 0.56 0.83 0.92 1.00

Mean item complexity =  1.6
Test of the hypothesis that 4 components are sufficient.

The root mean square of the residuals (RMSR) is  0 
 with the empirical chi square  0  with prob <  NA 

Fit based upon off diagonal values = 1
fit$values
[1] 2.2424292 1.0708642 0.3757126 0.3109940
#fit$scores
fit$weights
                     PC1         PC2         PC3        PC4
PMRV           0.3905627  0.04124629  1.05293484 -0.8777025
Endividamento  0.1197428  0.87756939  0.09898185  0.6696605
Vendas         0.3872237  0.05679122 -1.23298856 -0.5353488
Margem_liquida 0.3593400 -0.39846036  0.15125762  1.3077046
fit$loadings

Loadings:
               PC1    PC2    PC3    PC4   
PMRV            0.876         0.396 -0.273
Endividamento   0.269  0.940         0.208
Vendas          0.868        -0.463 -0.166
Margem_liquida  0.806 -0.427         0.407

                 PC1   PC2   PC3   PC4
SS loadings    2.242 1.071 0.376 0.311
Proportion Var 0.561 0.268 0.094 0.078
Cumulative Var 0.561 0.828 0.922 1.000
fit$communality
          PMRV  Endividamento         Vendas Margem_liquida 
             1              1              1              1 
# Escolha a quantidade de fatores
fit1 <- principal(dados, nfactors=2, rotate="none")
fit1 
Principal Components Analysis
Call: principal(r = dados, nfactors = 2, rotate = "none")
Standardized loadings (pattern matrix) based upon correlation matrix
                PC1   PC2   h2    u2 com
PMRV           0.88  0.04 0.77 0.231 1.0
Endividamento  0.27  0.94 0.96 0.045 1.2
Vendas         0.87  0.06 0.76 0.242 1.0
Margem_liquida 0.81 -0.43 0.83 0.169 1.5

                       PC1  PC2
SS loadings           2.24 1.07
Proportion Var        0.56 0.27
Cumulative Var        0.56 0.83
Proportion Explained  0.68 0.32
Cumulative Proportion 0.68 1.00

Mean item complexity =  1.2
Test of the hypothesis that 2 components are sufficient.

The root mean square of the residuals (RMSR) is  0.09 
 with the empirical chi square  4.29  with prob <  NA 

Fit based upon off diagonal values = 0.96
#fit1$values
#fit1$scores
#fit1$weights
fit1$loadings

Loadings:
               PC1    PC2   
PMRV            0.876       
Endividamento   0.269  0.940
Vendas          0.868       
Margem_liquida  0.806 -0.427

                 PC1   PC2
SS loadings    2.242 1.071
Proportion Var 0.561 0.268
Cumulative Var 0.561 0.828
fit1$communality
          PMRV  Endividamento         Vendas Margem_liquida 
     0.7689927      0.9552446      0.7576810      0.8313751 

Observando as comunalidades, há forte relação com os fatores extraídos. Comente! A variável endividamento possui alta comunalidade. Sendo possível considerá-la como um Fator. A extração de dois Fatores explicam cerca de 82,8% da variabilidade total dos dados Há evidência de que no Fator 1 seja predominante as variáveis: PMRV, vendas e Margem_líquida e no Fator 2 variável endividamento. Não é trivial, porém é possível sugerir um nome para o Fator 1 (volume de negócios-faturamento) e para o Fator 2 (estrutura de capital)

biplot(fit1)

O biplot representa representa a relação entre as variáveis e os fatores (após a rotação Varimax nesse caso). Endividamento possui elevada carga no Fator 2 e as demais variáveis no Fator 1

# varimax rotation
fit2 <- principal(dados, nfactors=2, rotate="varimax")
fit2 
Principal Components Analysis
Call: principal(r = dados, nfactors = 2, rotate = "varimax")
Standardized loadings (pattern matrix) based upon correlation matrix
                RC1   RC2   h2    u2 com
PMRV           0.85  0.21 0.77 0.231 1.1
Endividamento  0.08  0.97 0.96 0.045 1.0
Vendas         0.84  0.23 0.76 0.242 1.1
Margem_liquida 0.87 -0.26 0.83 0.169 1.2

                       RC1  RC2
SS loadings           2.20 1.12
Proportion Var        0.55 0.28
Cumulative Var        0.55 0.83
Proportion Explained  0.66 0.34
Cumulative Proportion 0.66 1.00

Mean item complexity =  1.1
Test of the hypothesis that 2 components are sufficient.

The root mean square of the residuals (RMSR) is  0.09 
 with the empirical chi square  4.29  with prob <  NA 

Fit based upon off diagonal values = 0.96
#fit2$values
fit2$scores
              RC1         RC2
 [1,]  0.21399479 -0.65575882
 [2,]  1.55410548  0.18021964
 [3,]  0.90652014  0.32533142
 [4,]  1.27155963 -0.92876502
 [5,]  1.45483704 -1.41169129
 [6,]  1.60845440  1.22298871
 [7,]  1.31555933  0.04129477
 [8,]  1.76312063 -0.39205557
 [9,]  2.49839731  0.30008576
[10,]  0.51881067 -1.45715479
[11,]  0.81519748 -1.24500621
[12,]  0.46002693  2.88534978
[13,] -0.30263148  1.46152848
[14,] -0.27371587 -0.69354358
[15,] -0.07300781  0.23224939
[16,] -0.69430520 -0.66951638
[17,] -0.17537610  0.27031820
[18,] -0.94052968 -0.21279441
[19,] -0.76839192  0.11621117
[20,] -1.15962650 -1.31196319
[21,] -0.88577481 -0.63487636
[22,] -1.10850722 -0.95735728
[23,] -1.25273882  0.18741700
[24,] -1.32608825 -0.60682797
[25,] -1.39461142  1.30963062
[26,] -1.57925069 -0.63108176
[27,] -0.64085654  1.58960822
[28,] -0.16416555 -1.02997919
[29,] -0.82328567 -0.91571359
[30,] -0.02856916  0.90416662
[31,] -1.46292835  0.96211786
[32,] -0.94329724  1.83186078
[33,] -0.58827902  0.81001784
[34,]  0.28426546  0.42583701
[35,]  0.27062217  0.08429988
[36,]  0.52442472 -1.24506751
[37,] -0.34776942 -1.35261727
[38,]  0.11098684 -0.17599485
[39,] -0.54662546  0.13336865
[40,]  1.12134352  0.64673045
[41,] -0.40943545 -0.85208333
[42,]  0.46099025 -0.94715611
[43,] -0.65654291  0.42121750
[44,]  0.20005872  0.85079334
[45,]  1.19303503  1.13436142
fit2$weights
                       RC1        RC2
PMRV            0.37496743  0.1167900
Endividamento  -0.05409636  0.8840475
Vendas          0.36865439  0.1313825
Margem_liquida  0.43029192 -0.3205382
fit2$loadings

Loadings:
               RC1    RC2   
PMRV            0.850  0.215
Endividamento          0.974
Vendas          0.840  0.229
Margem_liquida  0.874 -0.261

                 RC1   RC2
SS loadings    2.198 1.116
Proportion Var 0.549 0.279
Cumulative Var 0.549 0.828
fit2$communality
          PMRV  Endividamento         Vendas Margem_liquida 
     0.7689927      0.9552446      0.7576810      0.8313751 
biplot(fit1)

biplot(fit2)

#########
# critério da soma ponderada e ordenamento 
# formação de rankings das empresas / indicador de desempenho
# cálculo com a rotação varimax
fit2$values
[1] 2.2424292 1.0708642 0.3757126 0.3109940
peso1 <- fit2$values[1]/sum(fit2$values)
peso2 <- fit2$values[2]/sum(fit2$values)
classificacao <- fit2$scores[,1]*peso1+fit2$scores[,2]*peso2
desempenho_emp <- cbind.data.frame(Indic_finan_Fatorial,classificacao)
desempenho_emp[order(desempenho_emp$classificacao,decreasing=c(TRUE)),] 
LS0tDQp0aXRsZTogIkFuw6FsaXNlIEZhdG9yaWFsIC0gSW5kaWNhZG9yZXMgRmluYW5jZWlyb3MiDQphdXRob3I6ICJMZW9uaSwgUi4gQy4gUHJvZmVzc29yIERyLiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoqKioNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IEYpDQpgYGANCg0KPiBVbSBhbmFsaXN0YSBkZSBtZXJjYWRvIHF1ZXIgZXN0dWRhciBhcyByZWxhw6fDtWVzIGVzdHJ1dHVyYWlzIGVudHJlIHF1YXRybyBpbmRpY2Fkb3JlcyBmaW5hbmNlaXJvcyBwcm92ZW5pZW50ZXMgZGUgNDUgZW1wcmVzYXMuDQoNCj4JUsOzdHVsb3M6DQpDw7NkaWdvIGRhIGVtcHJlc2EgKEPDs2RfRW1wKQ0KDQo+CUluZGljYWRvcmVzOg0KUHJhem8gbcOpZGlvIGRlIHJlY2ViaW1lbnRvIGRlIHZlbmRhcyAoUE1SViwgZW0gZGlhcyk7DQpFbmRpdmlkYW1lbnRvIChlbSAlKTsNClZlbmRhcyAoZW0gUiQgeCBtaWwpOw0KTWFyZ2VtIGzDrXF1aWRhIGRlIHZlbmRhcyAoZW0gJSkuDQoNCg0KYGBge3IgcGFjb3RlcywgZWNobz1GQUxTRX0NCnJtKGxpc3Q9bHMoYWxsPVRSVUUpKQ0KbGlicmFyeShwc3ljaCkgIyBjYXJyZWdhbmRvIG9zIHBhY290ZXMgbmVjZXNzw6FyaW9zIHBhcmEgbyBDQVNFDQpsaWJyYXJ5KE1WTikNCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KEhtaXNjKQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KHJvYnVzdFgpDQpsaWJyYXJ5KGdncGxvdDIpDQpgYGANCg0KYGBge3IgZGFkb3MsIG1lc3NhZ2U9RkFMU0V9DQojIGRpZ2l0ZSBvIGxvY2FsIGNvcnJldG8gZG8gYXJxdWl2bw0KDQpJbmRpY19maW5hbl9GYXRvcmlhbCA8LSByZWFkX2V4Y2VsKCJJbmRpY19maW5hbl9GYXRvcmlhbC54bHMiKQ0KaGVhZChJbmRpY19maW5hbl9GYXRvcmlhbCkNCg0KZGFkb3MgPC0gSW5kaWNfZmluYW5fRmF0b3JpYWxbLDI6NV0NCmhlYWQoZGFkb3MpDQpgYGANCg0KYGBge3J9DQojIEVzdGF0w61zdGljYXMgRGVzY3JpdGl2YXMNCmRlc2NyaWJlKGRhZG9zKQ0KDQpib3hwbG90KGRhZG9zKQ0KDQpkYWRvcy5wYWQgPC0gc2NhbGUoZGFkb3MpDQpib3hwbG90KGRhZG9zLnBhZCkNCmBgYA0KDQo+IE8gYm94LXBsb3QgcGVybWl0ZSBhIGlkZW50aWZpY2HDp8OjbyBkZSBwb3Nzw612ZWlzIG91dGxpZXJzICh1bml2YXJpYWRvcykuIFBvZGUtc2UgcGVuc2FyIG5hIGV4Y2x1c8OjbyBkZXNzZXMgZGFkb3MuIEN1aWRhZG8hICANCg0KYGBge3J9DQojIG91dGxpZXJzDQoNCiMgQmlsbG9yLCBOLiwgSGFkaSwgQS4gUy4sIGFuZCBWZWxsZW1hbiAsIFAuIEYuICgyMDAwKS4gQkFDT046IEJsb2NrZWQgQWRhcHRpdmUgQ29tcHV0YXRpb25hbGx5LUVmZmljaWVudCBPdXRsaWVyIE5vbWluYXRvcnM7IENvbXB1dGF0aW9uYWwgU3RhdGlzdGljcyBhbmQgRGF0YSBBbmFseXNpcyAzNCwgMjc54oCTMjk4Lg0KDQpvdXRsaWVycyA8LSBtdkJBQ09OKGRhZG9zKQ0KIyBvdXRsaWVycw0KIyB0YWJsZShJbmRpY19maW5hbl9GYXRvcmlhbCRDb2RfRW1wLCBvdXRsaWVycyRzdWJzZXQpDQpwbG90KEluZGljX2ZpbmFuX0ZhdG9yaWFsJENvZF9FbXAsIG91dGxpZXJzJHN1YnNldCkNCg0KDQojIGdyw6FmaWNvIGNvbSBvIHBhY290ZSBnZ3Bsb3QyDQpkYWRvczIgPC0gZGF0YS5mcmFtZShJbmRpY19maW5hbl9GYXRvcmlhbCRDb2RfRW1wLCBvdXRsaWVycyRzdWJzZXQpDQpnZ3Bsb3QoZGF0YSA9IGRhZG9zMiwgYWVzKHggPSBJbmRpY19maW5hbl9GYXRvcmlhbC5Db2RfRW1wLCB5ID0gb3V0bGllcnMuc3Vic2V0ICkpICsNCiAgZ2VvbV9wb2ludCgpKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsPUluZGljX2ZpbmFuX0ZhdG9yaWFsLkNvZF9FbXApKQ0KYGBgDQoNCg0KDQoNCmBgYHtyIE5vcm1hbGlkYWRlfQ0KIyBWZXJpZmljYcOnw6NvIGRlIG5vcm1hbGlkYWRlIA0KIyBodHRwOi8vd3d3LmJpb3NvZnQuaGFjZXR0ZXBlLmVkdS50ci9NVk4vDQoNCiMgdGVzdGVzIHVuaXZhcmlhZG9zDQp1bmlQbG90KGRhZG9zLCB0eXBlID0gInFxcGxvdCIpICMgY3JlYXRlcyB1bml2YXJpYXRlIFEtUSBwbG90cw0KdW5pUGxvdChkYWRvcywgdHlwZSA9ICJoaXN0b2dyYW0iKSAjIGNyZWF0ZXMgdW5pdmFyaWF0ZSBoaXN0b2dyYW1zDQoNCg0KIyB1bml2YXJpYXRlIG5vcm1hbGl0eSB0ZXN0czogDQojIFNXOiBTaGFwaXJvLVdpbGssDQojIENWTTogQ3JhbWVyLXZvbiBNaXNlcywNCiMgTGlsbGllOiBMaWxsaWVmb3JzIChLb2xtb2dvcm92LVNtaXJub3YpLA0KIyBTRjogU2hhcGlyby1GcmFuY2lhLA0KIyBBRDogQW5kZXJzb24tRGFybGluZw0KDQp1bmlOb3JtKGRhZG9zLCB0eXBlID0gIlNXIiwgZGVzYz1GKQ0KdW5pTm9ybShkYWRvcywgdHlwZSA9ICJDVk0iICwgZGVzYyA9IEYpDQp1bmlOb3JtKGRhZG9zLCB0eXBlID0gIkxpbGxpZSIsIGRlc2MgPSBGKQ0KdW5pTm9ybShkYWRvcywgdHlwZSA9ICJTRiIsIGRlc2MgPSBGKQ0KdW5pTm9ybShkYWRvcywgdHlwZSA9ICJBRCIsIGRlc2MgPSBGKQ0KDQojIHRlc3RlcyBtdWx0aXZhcmlhZG9zDQpoelRlc3QoZGFkb3MpDQpyb3lzdG9uVGVzdChkYWRvcykNCm1hcmRpYVRlc3QoZGFkb3MpDQpgYGANCg0KYGBge3IsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTh9DQojIGNvcnJlbGHDp8OjbyANCm1jb3IgPC0gcmNvcnIoYXMubWF0cml4KGRhZG9zKSkNCm1jb3INCg0KUiA8LSBjb3IoZGFkb3MpDQpjb3JycGxvdChSLCBtZXRob2Q9Im51bWJlciIsdHlwZT0idXBwZXIiLCBvcmRlciA9ICJoY2x1c3QiLCB0bC5zcnQgPSA0NSkNCg0KY29ycnBsb3QoUiwgbWV0aG9kPSJjaXJjbGUiLHR5cGU9ImZ1bGwiLCBvcmRlciA9ICJoY2x1c3QiLCB0bC5zcnQgPSA0NSkNCiMgP2NvcnJwbG90DQpgYGANCg0KDQo+IE9ic2VydmEtc2UgcXVlIGjDoSBhbHRhcyBjb3JyZWxhw6fDtWVzIGVudHJlIGFzIHZhcmnDoXZlaXMgVmVuZGFzLCBQTVJWIGUgTWFyZ2VtX2zDrXF1aWRhIChwLXZhbG9yIDwgNSUpDQo+IEV4aXN0ZSBjb25zaWRlcsOhdmVsIG7Dum1lcm8gZGUgY29ycmVsYcOnw7VlcyBzdXBlcmlvcmVzIGEgMCwzMA0KPiBhIG5vcm1hbGlkYWRlIG11bHRpdmFyaWFkYSBuw6NvIHBvZGUgc2VyIGV2aWRlbmNpYWRhLCBjb250dWRvIHBvZGVtb3MgdXNhciBtw6l0b2RvcyByb2J1c3RvcyBwYXJhIGVzdHJhaXIgb3MgZmF0b3JlcywgY29tbyBwb3IgZXhlbXBsbyBvIG3DqXRvZG8gZG9zIGNvbXBvbmVudGVzIHByaW5jaXBhaXMuDQoNCg0KDQpgYGB7cn0NCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KI1BhcnRpYWwgY29ycmVsYXRpb24gbWF0cml4DQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCnBhcnRpYWwuY29yIDwtIGZ1bmN0aW9uICh4KQ0Kew0KUiA8LSBjb3IoeCkNClJJIDwtIHNvbHZlKFIpDQpEIDwtIDEvc3FydChkaWFnKFJJKSkNClJwIDwtIC1SSSAqIChEICVvJSBEKQ0KZGlhZyhScCkgPC0gMA0Kcm93bmFtZXMoUnApIDwtIGNvbG5hbWVzKFJwKSA8LSBjb2xuYW1lcyh4KQ0KUnANCn0NCm1hdF9hbnRpX2ltYWdlbSA8LSAtcGFydGlhbC5jb3IoZGFkb3MpDQptYXRfYW50aV9pbWFnZW0NCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgQmFydGxldHQncyB0ZXN0IHN0YXRpc3RpYyBpbmRpY2F0ZXMgdG8gd2hhdCBleHRlbnQgd2UgZGV2aWF0ZSBmcm9tIHRoZSByZWZlcmVuY2Ugc2l0dWF0aW9uIHxSfCA9IDEuDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCkJhcnRsZXR0LnNwaGVyaWNpdHkudGVzdCA8LSBmdW5jdGlvbih4KQ0Kew0KICBtZXRob2QgPC0gIkJhcnRsZXR0J3MgdGVzdCBvZiBzcGhlcmljaXR5Ig0KICBkYXRhLm5hbWUgPC0gZGVwYXJzZShzdWJzdGl0dXRlKHgpKQ0KICB4IDwtIHN1YnNldCh4LCBjb21wbGV0ZS5jYXNlcyh4KSkgIyBPbWl0IG1pc3NpbmcgdmFsdWVzDQogIG4gPC0gbnJvdyh4KQ0KICBwIDwtIG5jb2woeCkNCiAgY2hpc3EgPC0gKDEtbisoMipwKzUpLzYpKmxvZyhkZXQoY29yKHgpKSkNCiAgZGYgPC0gcCoocC0xKS8yDQogIHAudmFsdWUgPC0gcGNoaXNxKGNoaXNxLCBkZiwgbG93ZXIudGFpbD1GQUxTRSkNCiAgbmFtZXMoY2hpc3EpIDwtICJYLXNxdWFyZWQiDQogIG5hbWVzKGRmKSA8LSAiZGYiDQogIHJldHVybihzdHJ1Y3R1cmUobGlzdChzdGF0aXN0aWM9Y2hpc3EsIHBhcmFtZXRlcj1kZiwgcC52YWx1ZT1wLnZhbHVlLA0KICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kPW1ldGhvZCwgZGF0YS5uYW1lPWRhdGEubmFtZSksIGNsYXNzPSJodGVzdCIpKQ0KfQ0KDQoNCkJhcnRsZXR0LnNwaGVyaWNpdHkudGVzdChkYWRvcykNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBLTU8gaW5kZXgNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCmttbyA8LSBmdW5jdGlvbih4KQ0Kew0KICB4IDwtIHN1YnNldCh4LCBjb21wbGV0ZS5jYXNlcyh4KSkgIyBPbWl0IG1pc3NpbmcgdmFsdWVzDQogIHIgPC0gY29yKHgpICMgQ29ycmVsYXRpb24gbWF0cml4DQogIHIyIDwtIHJeMiAjIFNxdWFyZWQgY29ycmVsYXRpb24gY29lZmZpY2llbnRzDQogIGkgPC0gc29sdmUocikgIyBJbnZlcnNlIG1hdHJpeCBvZiBjb3JyZWxhdGlvbiBtYXRyaXgNCiAgZCA8LSBkaWFnKGkpICMgRGlhZ29uYWwgZWxlbWVudHMgb2YgaW52ZXJzZSBtYXRyaXgNCiAgcDIgPC0gKC1pL3NxcnQob3V0ZXIoZCwgZCkpKV4yICMgU3F1YXJlZCBwYXJ0aWFsIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50cw0KICBkaWFnKHIyKSA8LSBkaWFnKHAyKSA8LSAwICMgRGVsZXRlIGRpYWdvbmFsIGVsZW1lbnRzDQogIEtNTyA8LSBzdW0ocjIpLyhzdW0ocjIpK3N1bShwMikpDQogIE1TQSA8LSBjb2xTdW1zKHIyKS8oY29sU3VtcyhyMikrY29sU3VtcyhwMikpDQogIHJldHVybihsaXN0KEtNTz1LTU8sIE1TQT1NU0EpKQ0KfQ0KDQoNCmttbyhkYWRvcykNCmBgYA0KDQo+IG8gS01PIHRvcm5hIHJhem/DoXZlbCBhIGFwbGljYcOnw6NvIGRhIEFGDQo+IG8gdGVzdGUgZGUgZXNmZXJpY2lkYWRlIGRlIEJhcnRsZXR0IHJlamVpdGEgYSBoaXDDs3Rlc2UgZGUgYSBtYXRyaXogZGUgY29ycmVsYcOnw7VlcyBzZXIgaWRlbnRpZGFkZSAgDQo+IE8gTVNBIMOpIGFkZXF1YWRvLCBjb20gZXhjZcOnw6NvIGRhIHZhcmnDoXZlbCBpbmRpdmlkYW1lbnRvICgwLDMxOCkuIFNlIGEgY29tdW5hbGlkYWRlIGZvciBhbHRhLCBlc3RhIHZhcmnDoXZlbCBwb2RlIHNlciBzb3ppbmhhIHVtIEZhdG9yLg0KDQpgYGB7ciBBRn0NCm4uZGFkb3MgPC0gbGVuZ3RoKGRhZG9zKQ0KDQpmaXQgPC0gcHJpbmNpcGFsKGRhZG9zLCBuZmFjdG9ycz1uLmRhZG9zLCByb3RhdGU9Im5vbmUiKQ0KZml0DQoNCmZpdCR2YWx1ZXMNCiNmaXQkc2NvcmVzDQpmaXQkd2VpZ2h0cw0KZml0JGxvYWRpbmdzDQpmaXQkY29tbXVuYWxpdHkNCg0KIyBFc2NvbGhhIGEgcXVhbnRpZGFkZSBkZSBmYXRvcmVzDQpmaXQxIDwtIHByaW5jaXBhbChkYWRvcywgbmZhY3RvcnM9Miwgcm90YXRlPSJub25lIikNCmZpdDEgDQoNCiNmaXQxJHZhbHVlcw0KI2ZpdDEkc2NvcmVzDQojZml0MSR3ZWlnaHRzDQpmaXQxJGxvYWRpbmdzDQpmaXQxJGNvbW11bmFsaXR5DQpgYGANCg0KPiBPYnNlcnZhbmRvIGFzIGNvbXVuYWxpZGFkZXMsIGjDoSBmb3J0ZSByZWxhw6fDo28gY29tIG9zIGZhdG9yZXMgZXh0cmHDrWRvcy4gQ29tZW50ZSENCj4gQSB2YXJpw6F2ZWwgZW5kaXZpZGFtZW50byBwb3NzdWkgYWx0YSBjb211bmFsaWRhZGUuIFNlbmRvIHBvc3PDrXZlbCBjb25zaWRlcsOhLWxhIGNvbW8gdW0gRmF0b3IuDQo+IEEgZXh0cmHDp8OjbyBkZSBkb2lzIEZhdG9yZXMgZXhwbGljYW0gY2VyY2EgZGUgODIsOCUgZGEgdmFyaWFiaWxpZGFkZSB0b3RhbCBkb3MgZGFkb3MNCj4gSMOhIGV2aWTDqm5jaWEgZGUgcXVlIG5vIEZhdG9yIDEgc2VqYSBwcmVkb21pbmFudGUgYXMgdmFyacOhdmVpczogUE1SViwgdmVuZGFzIGUgTWFyZ2VtX2zDrXF1aWRhIGUgbm8gRmF0b3IgMiAgdmFyacOhdmVsIGVuZGl2aWRhbWVudG8uDQo+IE7Do28gw6kgdHJpdmlhbCwgcG9yw6ltIMOpIHBvc3PDrXZlbCBzdWdlcmlyIHVtIG5vbWUgcGFyYSBvIEZhdG9yIDEgKHZvbHVtZSBkZSBuZWfDs2Npb3MtZmF0dXJhbWVudG8pIGUgcGFyYSBvIEZhdG9yIDIgKGVzdHJ1dHVyYSBkZSBjYXBpdGFsKSANCg0KYGBge3IsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTh9DQpiaXBsb3QoZml0MSkNCmBgYA0KPiBPIGJpcGxvdCByZXByZXNlbnRhIHJlcHJlc2VudGEgYSByZWxhw6fDo28gZW50cmUgYXMgdmFyacOhdmVpcyBlIG9zIGZhdG9yZXMgKGFww7NzIGEgcm90YcOnw6NvIFZhcmltYXggbmVzc2UgY2FzbykuIEVuZGl2aWRhbWVudG8gcG9zc3VpIGVsZXZhZGEgY2FyZ2Egbm8gRmF0b3IgMiBlIGFzIGRlbWFpcyB2YXJpw6F2ZWlzIG5vIEZhdG9yIDENCg0KYGBge3J9DQojIHZhcmltYXggcm90YXRpb24NCmZpdDIgPC0gcHJpbmNpcGFsKGRhZG9zLCBuZmFjdG9ycz0yLCByb3RhdGU9InZhcmltYXgiKQ0KZml0MiANCg0KI2ZpdDIkdmFsdWVzDQpmaXQyJHNjb3Jlcw0KZml0MiR3ZWlnaHRzDQpmaXQyJGxvYWRpbmdzDQpmaXQyJGNvbW11bmFsaXR5DQpgYGANCg0KYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTd9DQpiaXBsb3QoZml0MSkNCmJpcGxvdChmaXQyKQ0KDQpgYGANCg0KYGBge3J9DQojIyMjIyMjIyMNCiMgY3JpdMOpcmlvIGRhIHNvbWEgcG9uZGVyYWRhIGUgb3JkZW5hbWVudG8gDQojIGZvcm1hw6fDo28gZGUgcmFua2luZ3MgZGFzIGVtcHJlc2FzIC8gaW5kaWNhZG9yIGRlIGRlc2VtcGVuaG8NCg0KIyBjw6FsY3VsbyBjb20gYSByb3Rhw6fDo28gdmFyaW1heA0KDQpmaXQyJHZhbHVlcw0KDQpwZXNvMSA8LSBmaXQyJHZhbHVlc1sxXS9zdW0oZml0MiR2YWx1ZXMpDQpwZXNvMiA8LSBmaXQyJHZhbHVlc1syXS9zdW0oZml0MiR2YWx1ZXMpDQoNCmNsYXNzaWZpY2FjYW8gPC0gZml0MiRzY29yZXNbLDFdKnBlc28xK2ZpdDIkc2NvcmVzWywyXSpwZXNvMg0KDQpkZXNlbXBlbmhvX2VtcCA8LSBjYmluZC5kYXRhLmZyYW1lKEluZGljX2ZpbmFuX0ZhdG9yaWFsLGNsYXNzaWZpY2FjYW8pDQpkZXNlbXBlbmhvX2VtcFtvcmRlcihkZXNlbXBlbmhvX2VtcCRjbGFzc2lmaWNhY2FvLGRlY3JlYXNpbmc9YyhUUlVFKSksXSANCg0KYGBgDQoNCg==