# install.packages("FactoMineR", "gglot2", "readxl")
# install.packages("devtools")
# devtools::install_github("kassambara/factoextra")
library("ggplot2")
library("FactoMineR")
library("factoextra")
library("readxl")
library("gplots")
library("corrplot")
library("graphics")
library("foreign")
library("readxl")
Ler os dados e atribuir ordem para perfil e aplicação
# ler os dados
investidor <- read_excel("perfil investidor aplicacao.xlsx")
investidor
# atribuir níveis ao perfil e tipo sw aplicação
investidor$perfil <- factor(investidor$perfil, levels = c("Conservador", "Moderado", "Agressivo"))
investidor$aplicacao <-factor(investidor$aplicacao, levels = c("Poupança", "CDB", "Ações"))
tab <- table(investidor$perfil, investidor$aplicacao)
tab
Poupança CDB Ações
Conservador 8 4 5
Moderado 5 16 4
Agressivo 2 20 36
# 1. convert the data as a table
dt <- as.table(as.matrix(tab))
# 2. Graph
balloonplot(t(dt), main ="Tabela de contingência - Perfil x Aplicação ", xlab ="", ylab="",
label = T, show.margins = T)

A contribuição (em %) de uma dada célula para a pontuação total do Qui-quadrado
### Contibution in percentage (%)
contrib <- 100*chisq$residuals^2/chisq$statistic
round(contrib, 3)
Poupança CDB Ações
Conservador 36.670 3.630 2.890
Moderado 1.312 11.334 14.709
Agressivo 16.244 1.390 11.822
### Visualize the contribution
corrplot(contrib, is.cor = FALSE)

o valor \(\phi\) > 0,2 indica uma dependência significativa entre linhas e colunas
O gráfico mosaico é usado para visualizar uma tabela de contingência para examinar a associação entre as variáveis categóricas.
### Mosaic plot of observed values
mosaicplot(tab, las=2, col="steelblue",
main = "Países.Disclosure - observed counts")

### Mosaic plot of expected values
mosaicplot(chisq$expected, las=2, col = "gray",
main = "Países.Disclosure - expected counts")

Nessas parcelas, as variáveis de coluna são primeiramente divididas (divisão vertical) e, em seguida, as variáveis de linha são divididas (divisão horizontal).
Para cada célula, a altura das barras é proporcional à frequência relativa observada que contém:
O gráfico azul, é o gráfico de mosaico dos valores observados.
O cinzento é o gráfico em mosaico dos valores esperados sob hipótese nula.
Se as variáveis de linha e coluna fossem completamente independentes, as barras de mosaico para os valores observados (gráfico azul) seriam alinhadas como as barras de mosaico para os valores esperados (gráfico cinza).
Análise de correspondência
Análise de correspondência (ANACOR) é necessária para a tabela de contingência grande.
Aplica-se para visualizar pontos da linha e pontos da coluna em um espaço dimensional reduzido.
ANACOR é um método de redução dimensional aplicado a uma tabela de contingência.
A informação retida por cada dimensão é chamada autovalor.
A análise de correspondência é usada para representar graficamente a tabela de distâncias entre variáveis de linha ou entre variáveis de coluna.
A abordagem ANACOR inclui as seguintes etapas:
1.Calcular os resíduos padronizados
Os resíduos padronizados (S) são:
\(S = \frac{o - e}{\sqrt{e}}\)
De fato, S é apenas a raíz quadrada dos termos que compõem a estatística \(\chi^2\).
2. Calcule a decomposição do valor singular (SVD) dos resíduos padronizados.
\(M = \frac{1}{sqrt(grand.total)} \times S\)
O autovalor de um determinado eixo é:
\(\lambda = \delta^2\)
\(\delta\) É o valor singular
As coordenadas das variáveis de linha em um determinado eixo são:
\(row.coord = \frac{U * \delta }{\sqrt{row.mass}}\)
As coordenadas das colunas são
\(col.coord = \frac{V * \delta }{\sqrt{col.mass}}\)
cálculo SVD
### Grand total
n <- sum(tab)
n
[1] 100
### Standardized residuals
residuals <- chisq$residuals/sqrt(n)
residuals
Poupança CDB Ações
Conservador 0.34129224 -0.10737510 -0.09581095
Moderado 0.06454972 0.18973666 -0.21615324
Agressivo -0.22715127 -0.06643638 0.19378267
### Number of dimensions
nb.axes <- min(nrow(residuals)-1, ncol(residuals)-1)
nb.axes
[1] 2
### Singular value decomposition
res.svd <- svd(residuals, nu = nb.axes, nv = nb.axes)
res.svd
$d
[1] 4.829233e-01 2.905629e-01 1.166671e-18
$u
[,1] [,2]
[1,] -0.6716248 0.6155649
[2,] -0.3980015 -0.7691520
[3,] 0.6249119 0.1717122
$v
[,1] [,2]
[1,] -0.82178847 0.4179279
[2,] -0.09300977 -0.7689923
[3,] 0.56215025 0.4837221
### singular value
sv <- res.svd$d[1:nb.axes]
u <-res.svd$u
v <- res.svd$v
### Eigenvalues
eig <- sv^2
### Variances in percentage
variance <- eig*100/sum(eig)
### Cumulative variances
cumvar <- cumsum(variance)
eig<- data.frame(eig = eig, variance = variance,
cumvariance = cumvar)
head(eig)
barplot(eig[, 2], names.arg=1:nrow(eig),
main = "Variances",
xlab = "Dimensions",
ylab = "Percentage of variances",
col ="steelblue")
### Add connected line segments to the plot
lines(x = 1:nrow(eig), eig[, 2],
type="b", pch=19, col = "red")

Quantas dimensões reter ?
1. O número máximo de eixos na ANACOR é:
\(nb.axes = min(r-1, c-1)\)
r e c são respectivamente o número de linhas e colunas na tabela.
Row coordinates
### row sum
row.sum <- apply(tab, 1, sum)
row.sum
Conservador Moderado Agressivo
17 25 58
### row mass
row.mass <- row.sum/n
row.mass
Conservador Moderado Agressivo
0.17 0.25 0.58
### row coord = sv * u /sqrt(row.mass)
cc <- t(apply(u, 1, '*', sv)) ### each row X sv
row.coord <- apply(cc, 2, '/', sqrt(row.mass))
rownames(row.coord) <- rownames(tab)
colnames(row.coord) <- paste0("Dim.", 1:nb.axes)
round(row.coord,3)
Dim.1 Dim.2
Conservador -0.787 0.434
Moderado -0.384 -0.447
Agressivo 0.396 0.066
### plot
plot(row.coord, pch=19, col = "blue")
text(row.coord, labels =rownames(row.coord), pos = 3, col ="blue")
abline(v=0, h=0, lty = 2)

Column coordinates
### Coordinates of columns
col.sum <- apply(tab, 2, sum)
col.mass <- col.sum/n
### coordinates sv * v /sqrt(col.mass)
cc <- t(apply(v, 1, '*', sv))
col.coord <- apply(cc, 2, '/', sqrt(col.mass))
rownames(col.coord) <- colnames(tab)
colnames(col.coord) <- paste0("Dim", 1:nb.axes)
head(col.coord)
Dim1 Dim2
Poupança -1.02469008 0.3135421
CDB -0.07101935 -0.3532906
Ações 0.40469167 0.2095221
### plot
plot(col.coord, pch=17, col = "red")
text(col.coord, labels =rownames(col.coord), pos = 3, col ="red")
abline(v=0, h=0, lty = 2)

Biplot de linhas e colunas para ver a associação
xlim <- range(c(row.coord[,1], col.coord[,1]))*1.1
ylim <- range(c(row.coord[,2], col.coord[,2]))*1.1
### Plot of rows
plot(row.coord, pch=19, col = "blue", xlim = xlim, ylim = ylim)
text(row.coord, labels =rownames(row.coord), pos = 3, col ="blue")
### plot off columns
points(col.coord, pch=17, col = "red")
text(col.coord, labels =rownames(col.coord), pos = 3, col ="red")
abline(v=0, h=0, lty = 2)

Você pode interpretar a distância entre pontos de linhas ou entre pontos de coluna, mas a distância entre pontos de coluna e pontos de linha não são significativos.
Diagnóstico
Lembre-se que, a inércia total contida nos dados é:
\(\phi^2 = \frac{\chi^2}{n} = 0.3176\)
Nosso gráfico bidimensional captura 100% da inércia total da tabela.
Contribuição de linhas e colunas
As contribuições de uma linha / coluna para a definição de um eixo principal são:
\(row.contrib = \frac{row.mass * row.coord^2}{eigenvalue}\)
\(col.contrib = \frac{col.mass * col.coord^2}{eigenvalue}\)
Contribuição de linhas em %
### contrib <- row.mass * row.coord^2/eigenvalue
cc <- apply(row.coord^2, 2, "*", row.mass)
row.contrib <- t(apply(cc, 1, "/", eig[1:nb.axes,1])) *100
round(row.contrib, 2)
Dim.1 Dim.2
Conservador 45.11 37.89
Moderado 15.84 59.16
Agressivo 39.05 2.95
corrplot(row.contrib, is.cor = FALSE)

Contribuição das colunas em %
### contrib <- col.mass * col.coord^2/eigenvalue
cc <- apply(col.coord^2, 2, "*", col.mass)
col.contrib <- t(apply(cc, 1, "/", eig[1:nb.axes,1])) *100
round(col.contrib, 2)
Dim1 Dim2
Poupança 67.53 17.47
CDB 0.87 59.13
Ações 31.60 23.40
corrplot(col.contrib, is.cor = FALSE)

Qualidade da representação
A qualidade da representação é chamada COS2.
A qualidade da representação de uma linha em um eixo é:
\(row.cos2 = \frac{row.coord^2}{d^2}\)
- Row.coord é a coordenada da linha no eixo
- \(d^2\) É a distância ao quadrado do perfil médio
Lembre-se de que a distância entre cada perfil de linha e o perfil de linha médio é:
\(d^2(row_i, average.profile) = \sum{\frac{(row.profile_i - average.profile)^2}{average.profile}}\)
row.profile <- tab/row.sum
head(round(row.profile, 3))
Poupança CDB Ações
Conservador 0.471 0.235 0.294
Moderado 0.200 0.640 0.160
Agressivo 0.034 0.345 0.621
average.profile <- col.sum/n
head(round(average.profile, 3))
Poupança CDB Ações
0.15 0.40 0.45
O código R abaixo calcula a distância do perfil médio para todas as variáveis de linha
average.rp <- col.sum/n
d2.row <- apply(row.profile, 1,
function(row.p, av.p){sum(((row.p - av.p)^2)/av.p)},
average.rp)
head(round(d2.row,3))
Conservador Moderado Agressivo
0.807 0.348 0.161
O cos2 de linhas no mapa de fatores são:
row.cos2 <- apply(row.coord^2, 2, "/", d2.row)
round(row.cos2, 3)
Dim.1 Dim.2
Conservador 0.767 0.233
Moderado 0.425 0.575
Agressivo 0.973 0.027
corrplot(row.cos2, is.cor = FALSE)

Cos2 das colunas
\(col.cos2 = \frac{col.coord^2}{d^2}\)
col.profile <- t(tab)/col.sum
col.profile <- t(col.profile)
###head(round(col.profile, 3))
average.profile <- row.sum/n
###head(round(average.profile, 3))
O código R abaixo calcula a distância do perfil médio para todas as variáveis da coluna
d2.col <- apply(col.profile, 2,
function(col.p, av.p){sum(((col.p - av.p)^2)/av.p)},
average.profile)
round(d2.col,3)
Poupança CDB Ações
1.148 0.130 0.208
O cos2 das colunas no mapa de fatores são:
col.cos2 <- apply(col.coord^2, 2, "/", d2.col)
round(col.cos2, 3)
Dim1 Dim2
Poupança 0.914 0.086
CDB 0.039 0.961
Ações 0.789 0.211
corrplot(col.cos2, is.cor = FALSE)

Pacotes no R para ANACOR
-FactoMineR -ade4 -ca
library(FactoMineR)
res.ca <- CA(tab, graph = F)
res.ca
**Results of the Correspondence Analysis (CA)**
The row variable has 3 categories; the column variable has 3 categories
The chi square of independence between the two variables is equal to 31.76416 (p-value = 2.137594e-06 ).
*The results are available in the following objects:
name description
1 "$eig" "eigenvalues"
2 "$col" "results for the columns"
3 "$col$coord" "coord. for the columns"
4 "$col$cos2" "cos2 for the columns"
5 "$col$contrib" "contributions of the columns"
6 "$row" "results for the rows"
7 "$row$coord" "coord. for the rows"
8 "$row$cos2" "cos2 for the rows"
9 "$row$contrib" "contributions of the rows"
10 "$call" "summary called parameters"
11 "$call$marge.col" "weights of the columns"
12 "$call$marge.row" "weights of the rows"
### eigenvalue
head(res.ca$eig)[, 1:2]
### barplot of percentage of variance
barplot(res.ca$eig[,2], names.arg = rownames(res.ca$eig))

### Plot row points
plot(res.ca, invisible ="col")

### Plot column points
plot(res.ca, invisible ="row")

### Biplot of rows and columns
plot(res.ca)

LS0tDQp0aXRsZTogJ0Fuw6FsaXNlIGRlIENvcnJlc3BvbmTDqm5jaWEgLSBwZXJmaWwgaW52ZXN0aWRvciBhcGxpY2FjYW8gLSBBTkFDT1IgJw0KYXV0aG9yOiAiTGVvbmksIFIuIEMuIFByb2Zlc3NvciBEci4iDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdA0KLS0tDQoqKioNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IEYpDQpybShsaXN0PWxzKGFsbD1UUlVFKSkNCmBgYA0KDQpgYGB7cn0NCiMgaW5zdGFsbC5wYWNrYWdlcygiRmFjdG9NaW5lUiIsICJnZ2xvdDIiLCAicmVhZHhsIikNCiMgaW5zdGFsbC5wYWNrYWdlcygiZGV2dG9vbHMiKQ0KIyBkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoImthc3NhbWJhcmEvZmFjdG9leHRyYSIpDQpsaWJyYXJ5KCJnZ3Bsb3QyIikNCmxpYnJhcnkoIkZhY3RvTWluZVIiKQ0KbGlicmFyeSgiZmFjdG9leHRyYSIpDQpsaWJyYXJ5KCJyZWFkeGwiKQ0KbGlicmFyeSgiZ3Bsb3RzIikNCmxpYnJhcnkoImNvcnJwbG90IikNCmxpYnJhcnkoImdyYXBoaWNzIikNCmxpYnJhcnkoImZvcmVpZ24iKQ0KbGlicmFyeSgicmVhZHhsIikNCmBgYA0KDQojIyMgTGVyIG9zIGRhZG9zIGUgYXRyaWJ1aXIgb3JkZW0gcGFyYSBwZXJmaWwgZSBhcGxpY2HDp8Ojbw0KYGBge3J9DQojIGxlciBvcyBkYWRvcw0KaW52ZXN0aWRvciA8LSByZWFkX2V4Y2VsKCJwZXJmaWwgaW52ZXN0aWRvciBhcGxpY2FjYW8ueGxzeCIpDQppbnZlc3RpZG9yDQoNCiMgYXRyaWJ1aXIgbsOtdmVpcyBhbyBwZXJmaWwgZSB0aXBvIHN3IGFwbGljYcOnw6NvDQppbnZlc3RpZG9yJHBlcmZpbCA8LSBmYWN0b3IoaW52ZXN0aWRvciRwZXJmaWwsIGxldmVscyA9IGMoIkNvbnNlcnZhZG9yIiwgIk1vZGVyYWRvIiwgIkFncmVzc2l2byIpKQ0KaW52ZXN0aWRvciRhcGxpY2FjYW8gPC1mYWN0b3IoaW52ZXN0aWRvciRhcGxpY2FjYW8sIGxldmVscyA9IGMoIlBvdXBhbsOnYSIsICJDREIiLCAiQcOnw7VlcyIpKQ0KDQp0YWIgPC0gdGFibGUoaW52ZXN0aWRvciRwZXJmaWwsIGludmVzdGlkb3IkYXBsaWNhY2FvKQ0KdGFiDQpgYGANCg0KYGBge3IsIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTh9DQoNCiMgMS4gY29udmVydCB0aGUgZGF0YSBhcyBhIHRhYmxlDQpkdCA8LSBhcy50YWJsZShhcy5tYXRyaXgodGFiKSkNCiMgMi4gR3JhcGgNCmJhbGxvb25wbG90KHQoZHQpLCBtYWluID0iVGFiZWxhIGRlIGNvbnRpbmfDqm5jaWEgLSBQZXJmaWwgeCBBcGxpY2HDp8OjbyAiLCB4bGFiID0iIiwgeWxhYj0iIiwNCiAgICAgICAgICAgIGxhYmVsID0gVCwgc2hvdy5tYXJnaW5zID0gVCkNCg0KYGBgDQoNCiMjIyBBcyBjw6lsdWxhcyBjb20gb3MgcmVzw61kdW9zIHBhZHJvbml6YWRvcyBhYnNvbHV0b3MgbWFpcyBlbGV2YWRvcyBjb250cmlidWVtIG1haXMgcGFyYSBhIHBvbnR1YcOnw6NvIHRvdGFsIGRvIFF1aS1xdWFkcmFkby4NCg0KYGBge3J9DQpjaGlzcSA8LSBjaGlzcS50ZXN0KHRhYikNCmNoaXNxDQojIE9ic2VydmVkIGNvdW50cw0KY2hpc3Ekb2JzZXJ2ZWQNCiMgRXhwZWN0ZWQgY291bnRzIA0Kcm91bmQoY2hpc3EkZXhwZWN0ZWQsMikNCiMgcmVzaWR1YWxzIHBhZHJvbml6YWRvcyANCnJvdW5kKGNoaXNxJHJlc2lkdWFscywgMikNCg0KY29ycnBsb3QoY2hpc3EkcmVzaWR1YWxzLCBpcy5jb3IgPSBGQUxTRSkNCg0KYGBgDQoNCg0KIyMjIEEgY29udHJpYnVpw6fDo28gKGVtICUpIGRlIHVtYSBkYWRhIGPDqWx1bGEgcGFyYSBhIHBvbnR1YcOnw6NvIHRvdGFsIGRvIFF1aS1xdWFkcmFkbw0KDQpgYGB7cn0NCiMjIyBDb250aWJ1dGlvbiBpbiBwZXJjZW50YWdlICglKQ0KY29udHJpYiA8LSAxMDAqY2hpc3EkcmVzaWR1YWxzXjIvY2hpc3Ekc3RhdGlzdGljDQpyb3VuZChjb250cmliLCAzKQ0KIyMjIFZpc3VhbGl6ZSB0aGUgY29udHJpYnV0aW9uDQpjb3JycGxvdChjb250cmliLCBpcy5jb3IgPSBGQUxTRSkNCmBgYA0KDQoNCiMjIyBBIGluw6lyY2lhIHRvdGFsICgkXHBoaV4yJCkgw6kgYSBxdWFudGlkYWRlIGRlIGluZm9ybWHDp8OjbyBjb250aWRhIG5hIHRhYmVsYSBkZSBkYWRvcw0KIA0KYGBge3J9DQpwaGkyIDwtIGFzLm51bWVyaWMoY2hpc3Ekc3RhdGlzdGljL3N1bSh0YWIpKQ0KcGhpMg0KYGBgDQoNCg0KIyMjIG8gdmFsb3IgJFxwaGkkID4gMCwyIGluZGljYSB1bWEgZGVwZW5kw6puY2lhIHNpZ25pZmljYXRpdmEgZW50cmUgbGluaGFzIGUgY29sdW5hcyANCiMjIyBPIGdyw6FmaWNvIG1vc2FpY28gw6kgdXNhZG8gcGFyYSB2aXN1YWxpemFyIHVtYSB0YWJlbGEgZGUgY29udGluZ8OqbmNpYSBwYXJhIGV4YW1pbmFyIGEgYXNzb2NpYcOnw6NvIGVudHJlIGFzIHZhcmnDoXZlaXMgY2F0ZWfDs3JpY2FzLg0KDQpgYGB7cn0NCiMjIyBNb3NhaWMgcGxvdCBvZiBvYnNlcnZlZCB2YWx1ZXMNCm1vc2FpY3Bsb3QodGFiLCAgbGFzPTIsIGNvbD0ic3RlZWxibHVlIiwNCiAgICAgICAgICAgbWFpbiA9ICJQYcOtc2VzLkRpc2Nsb3N1cmUgLSBvYnNlcnZlZCBjb3VudHMiKQ0KDQojIyMgTW9zYWljIHBsb3Qgb2YgZXhwZWN0ZWQgdmFsdWVzDQptb3NhaWNwbG90KGNoaXNxJGV4cGVjdGVkLCAgbGFzPTIsIGNvbCA9ICJncmF5IiwNCiAgICAgICAgICAgbWFpbiA9ICJQYcOtc2VzLkRpc2Nsb3N1cmUgLSBleHBlY3RlZCBjb3VudHMiKQ0KYGBgDQoNCiMjIyBOZXNzYXMgcGFyY2VsYXMsIGFzIHZhcmnDoXZlaXMgZGUgY29sdW5hIHPDo28gcHJpbWVpcmFtZW50ZSBkaXZpZGlkYXMgKGRpdmlzw6NvIHZlcnRpY2FsKSBlLCBlbSBzZWd1aWRhLCBhcyB2YXJpw6F2ZWlzIGRlIGxpbmhhIHPDo28gZGl2aWRpZGFzIChkaXZpc8OjbyBob3Jpem9udGFsKS4gDQojIyMgUGFyYSBjYWRhIGPDqWx1bGEsIGEgYWx0dXJhIGRhcyBiYXJyYXMgw6kgcHJvcG9yY2lvbmFsIMOgIGZyZXF1w6puY2lhIHJlbGF0aXZhIG9ic2VydmFkYSBxdWUgY29udMOpbToNCiMjIyBPIGdyw6FmaWNvIGF6dWwsIMOpIG8gZ3LDoWZpY28gZGUgbW9zYWljbyBkb3MgdmFsb3JlcyBvYnNlcnZhZG9zLg0KIyMjIE8gY2luemVudG8gw6kgbyBncsOhZmljbyBlbSBtb3NhaWNvIGRvcyB2YWxvcmVzIGVzcGVyYWRvcyBzb2IgaGlww7N0ZXNlIG51bGEuDQojIyMgU2UgYXMgdmFyacOhdmVpcyBkZSBsaW5oYSBlIGNvbHVuYSBmb3NzZW0gY29tcGxldGFtZW50ZSBpbmRlcGVuZGVudGVzLCBhcyBiYXJyYXMgZGUgbW9zYWljbyBwYXJhIG9zIHZhbG9yZXMgb2JzZXJ2YWRvcyAoZ3LDoWZpY28gYXp1bCkgc2VyaWFtIGFsaW5oYWRhcyBjb21vIGFzIGJhcnJhcyBkZSBtb3NhaWNvIHBhcmEgb3MgdmFsb3JlcyBlc3BlcmFkb3MgKGdyw6FmaWNvIGNpbnphKS4NCiMjIyBUYW1iw6ltIMOpIHBvc3PDrXZlbCBjb2xvcmlyIG8gbW9zYWljbyBkZSBhY29yZG8gY29tIG8gdmFsb3IgZG9zIHJlc8OtZHVvcyBwYWRyb25pemFkb3M6DQoNCmBgYHtyfQ0KbW9zYWljcGxvdCh0YWIsIHNoYWRlID0gVFJVRSwgbGFzPTIsbWFpbiA9ICJQYcOtc2VzLkRpc2Nsb3N1cmUiKQ0KYGBgDQoNCg0KDQojIyMgIEFuw6FsaXNlIGRlIGNvcnJlc3BvbmTDqm5jaWENCiMjIyBBbsOhbGlzZSBkZSBjb3JyZXNwb25kw6puY2lhIChBTkFDT1IpIMOpIG5lY2Vzc8OhcmlhIHBhcmEgYSB0YWJlbGEgZGUgY29udGluZ8OqbmNpYSBncmFuZGUuDQojIyMgQXBsaWNhLXNlIHBhcmEgdmlzdWFsaXphciBwb250b3MgZGEgbGluaGEgZSBwb250b3MgZGEgY29sdW5hIGVtIHVtIGVzcGHDp28gZGltZW5zaW9uYWwgcmVkdXppZG8uDQojIyMgQU5BQ09SIMOpIHVtIG3DqXRvZG8gZGUgcmVkdcOnw6NvIGRpbWVuc2lvbmFsIGFwbGljYWRvIGEgdW1hIHRhYmVsYSBkZSBjb250aW5nw6puY2lhLiANCiMjIyBBIGluZm9ybWHDp8OjbyByZXRpZGEgcG9yIGNhZGEgZGltZW5zw6NvIMOpIGNoYW1hZGEgYXV0b3ZhbG9yLg0KIyMjIEEgaW5mb3JtYcOnw6NvIHRvdGFsIChvdSBpbsOpcmNpYSkgY29udGlkYSBub3MgZGFkb3Mgw6kgY2hhbWFkYSBwaGkgKCRccGhpXjIkKSBlIHBvZGUgc2VyIGNhbGN1bGFkbyBkYSBzZWd1aW50ZSBmb3JtYToNCg0KJFxwaGleMiA9IFxmcmFje1xjaGleMn17Z3JhbmQudG90YWx9JA0KDQojIyMgQSBhbsOhbGlzZSBkZSBjb3JyZXNwb25kw6puY2lhIMOpIHVzYWRhIHBhcmEgcmVwcmVzZW50YXIgZ3JhZmljYW1lbnRlIGEgdGFiZWxhIGRlIGRpc3TDom5jaWFzIGVudHJlIHZhcmnDoXZlaXMgZGUgbGluaGEgb3UgZW50cmUgdmFyacOhdmVpcyBkZSBjb2x1bmEuDQojIyMgQSBhYm9yZGFnZW0gQU5BQ09SIGluY2x1aSBhcyBzZWd1aW50ZXMgZXRhcGFzOg0KDQojIyMgMS5DYWxjdWxhciBvcyByZXPDrWR1b3MgcGFkcm9uaXphZG9zDQoNCiMjIyBPcyByZXPDrWR1b3MgcGFkcm9uaXphZG9zIChTKSBzw6NvOg0KDQokUyA9IFxmcmFje28gLSBlfXtcc3FydHtlfX0kDQoNCiMjIyBEZSBmYXRvLCBTIMOpIGFwZW5hcyBhIHJhw616IHF1YWRyYWRhIGRvcyB0ZXJtb3MgcXVlIGNvbXDDtWVtIGEgZXN0YXTDrXN0aWNhICRcY2hpXjIkLg0KDQojIyMgMi4gQ2FsY3VsZSBhIGRlY29tcG9zacOnw6NvIGRvIHZhbG9yIHNpbmd1bGFyIChTVkQpIGRvcyByZXPDrWR1b3MgcGFkcm9uaXphZG9zLg0KDQokTSA9IFxmcmFjezF9e3NxcnQoZ3JhbmQudG90YWwpfSBcdGltZXMgUyQNCg0KIyMjIFNWRCBzaWduaWZpY2EgcXVlIHF1ZXJlbW9zIGVuY29udHJhciBtYXRyaXplcyBvcnRvZ29uYWlzIFUgZSBWLCBlbSBjb25qdW50byBjb20gdW1hIG1hdHJpeiBkaWFnb25hbCAkXERlbHRhJCwgdGFsIHF1ZToNCg0KJE0gPSBVIFxEZWx0YSBWXlQkDQoNCi0gVSDDiSB1bWEgbWF0cml6IGNvbnRlbmRvIGF1dG92ZXRvcmVzIGRlIGxpbmhhcw0KLSDOlCDDiSBhIG1hdHJpeiBkaWFnb25hbC4gT3MgbsO6bWVyb3MgbmEgZGlhZ29uYWwgZGEgbWF0cml6IHPDo28gY2hhbWFkb3MgZGUgdmFsb3JlcyBzaW5ndWxhcmVzIChTVikuIE9zIGF1dG92YWxvcmVzIHPDo28gbyBTViBxdWFkcmFkby4NCi0gViDDiSB1bWEgbWF0cml6IGNvbnRlbmRvIGF1dG92ZXRvcmVzIGRlIGNvbHVuYQ0KDQojIyMgTyBhdXRvdmFsb3IgZGUgdW0gZGV0ZXJtaW5hZG8gZWl4byDDqToNCg0KJFxsYW1iZGEgPSBcZGVsdGFeMiQNCg0KJFxkZWx0YSQgw4kgbyB2YWxvciBzaW5ndWxhcg0KDQojIyMgQXMgY29vcmRlbmFkYXMgZGFzIHZhcmnDoXZlaXMgZGUgbGluaGEgZW0gdW0gZGV0ZXJtaW5hZG8gZWl4byBzw6NvOg0KDQokcm93LmNvb3JkID0gXGZyYWN7VSAqIFxkZWx0YSB9e1xzcXJ0e3Jvdy5tYXNzfX0kDQoNCiMjIyBBcyBjb29yZGVuYWRhcyBkYXMgY29sdW5hcyBzw6NvDQoNCiRjb2wuY29vcmQgPSBcZnJhY3tWICogXGRlbHRhIH17XHNxcnR7Y29sLm1hc3N9fSQNCg0KIyMjIGPDoWxjdWxvIFNWRA0KDQpgYGB7cn0NCiMjIyBHcmFuZCB0b3RhbA0KbiA8LSBzdW0odGFiKQ0Kbg0KIyMjIFN0YW5kYXJkaXplZCByZXNpZHVhbHMNCnJlc2lkdWFscyA8LSBjaGlzcSRyZXNpZHVhbHMvc3FydChuKQ0KcmVzaWR1YWxzDQojIyMgTnVtYmVyIG9mIGRpbWVuc2lvbnMNCm5iLmF4ZXMgPC0gbWluKG5yb3cocmVzaWR1YWxzKS0xLCBuY29sKHJlc2lkdWFscyktMSkNCm5iLmF4ZXMNCg0KIyMjIFNpbmd1bGFyIHZhbHVlIGRlY29tcG9zaXRpb24NCnJlcy5zdmQgPC0gc3ZkKHJlc2lkdWFscywgbnUgPSBuYi5heGVzLCBudiA9IG5iLmF4ZXMpDQpyZXMuc3ZkDQoNCiMjIyBzaW5ndWxhciB2YWx1ZQ0Kc3YgPC0gcmVzLnN2ZCRkWzE6bmIuYXhlc10gDQp1IDwtcmVzLnN2ZCR1DQp2IDwtIHJlcy5zdmQkdg0KYGBgDQoNCg0KDQpgYGB7cn0NCiMjIyBFaWdlbnZhbHVlcw0KZWlnIDwtIHN2XjINCiMjIyBWYXJpYW5jZXMgaW4gcGVyY2VudGFnZQ0KdmFyaWFuY2UgPC0gZWlnKjEwMC9zdW0oZWlnKQ0KIyMjIEN1bXVsYXRpdmUgdmFyaWFuY2VzDQpjdW12YXIgPC0gY3Vtc3VtKHZhcmlhbmNlKQ0KZWlnPC0gZGF0YS5mcmFtZShlaWcgPSBlaWcsIHZhcmlhbmNlID0gdmFyaWFuY2UsDQogICAgICAgICAgICAgICAgICAgICBjdW12YXJpYW5jZSA9IGN1bXZhcikNCmhlYWQoZWlnKQ0KYGBgDQoNCg0KYGBge3J9DQpiYXJwbG90KGVpZ1ssIDJdLCBuYW1lcy5hcmc9MTpucm93KGVpZyksIA0KICAgICAgIG1haW4gPSAiVmFyaWFuY2VzIiwNCiAgICAgICB4bGFiID0gIkRpbWVuc2lvbnMiLA0KICAgICAgIHlsYWIgPSAiUGVyY2VudGFnZSBvZiB2YXJpYW5jZXMiLA0KICAgICAgIGNvbCA9InN0ZWVsYmx1ZSIpDQojIyMgQWRkIGNvbm5lY3RlZCBsaW5lIHNlZ21lbnRzIHRvIHRoZSBwbG90DQpsaW5lcyh4ID0gMTpucm93KGVpZyksIGVpZ1ssIDJdLCANCiAgICAgIHR5cGU9ImIiLCBwY2g9MTksIGNvbCA9ICJyZWQiKQ0KYGBgDQojIyMgUXVhbnRhcyBkaW1lbnPDtWVzIHJldGVyID8NCg0KIyMjIDEuIE8gbsO6bWVybyBtw6F4aW1vIGRlIGVpeG9zIG5hIEFOQUNPUiDDqToNCg0KJG5iLmF4ZXMgPSBtaW4oci0xLCBjLTEpJA0KDQojIyNyIGUgYyBzw6NvIHJlc3BlY3RpdmFtZW50ZSBvIG7Dum1lcm8gZGUgbGluaGFzIGUgY29sdW5hcyBuYSB0YWJlbGEuDQoNCiMjIyBSb3cgY29vcmRpbmF0ZXMNCmBgYHtyfQ0KIyMjIHJvdyBzdW0NCnJvdy5zdW0gPC0gYXBwbHkodGFiLCAxLCBzdW0pDQpyb3cuc3VtDQojIyMgcm93IG1hc3MNCnJvdy5tYXNzIDwtIHJvdy5zdW0vbg0Kcm93Lm1hc3MNCiMjIyByb3cgY29vcmQgPSBzdiAqIHUgL3NxcnQocm93Lm1hc3MpDQpjYyA8LSB0KGFwcGx5KHUsIDEsICcqJywgc3YpKSAjIyMgZWFjaCByb3cgWCBzdg0Kcm93LmNvb3JkIDwtIGFwcGx5KGNjLCAyLCAnLycsIHNxcnQocm93Lm1hc3MpKQ0Kcm93bmFtZXMocm93LmNvb3JkKSA8LSByb3duYW1lcyh0YWIpDQpjb2xuYW1lcyhyb3cuY29vcmQpIDwtIHBhc3RlMCgiRGltLiIsIDE6bmIuYXhlcykNCnJvdW5kKHJvdy5jb29yZCwzKQ0KDQoNCiMjIyBwbG90DQpwbG90KHJvdy5jb29yZCwgcGNoPTE5LCBjb2wgPSAiYmx1ZSIpDQp0ZXh0KHJvdy5jb29yZCwgbGFiZWxzID1yb3duYW1lcyhyb3cuY29vcmQpLCBwb3MgPSAzLCBjb2wgPSJibHVlIikNCmFibGluZSh2PTAsIGg9MCwgbHR5ID0gMikNCmBgYA0KDQojIyMgIENvbHVtbiBjb29yZGluYXRlcw0KDQpgYGB7cn0NCiMjIyBDb29yZGluYXRlcyBvZiBjb2x1bW5zDQpjb2wuc3VtIDwtIGFwcGx5KHRhYiwgMiwgc3VtKQ0KY29sLm1hc3MgPC0gY29sLnN1bS9uDQojIyMgY29vcmRpbmF0ZXMgc3YgKiB2IC9zcXJ0KGNvbC5tYXNzKQ0KY2MgPC0gdChhcHBseSh2LCAxLCAnKicsIHN2KSkNCmNvbC5jb29yZCA8LSBhcHBseShjYywgMiwgJy8nLCBzcXJ0KGNvbC5tYXNzKSkNCnJvd25hbWVzKGNvbC5jb29yZCkgPC0gY29sbmFtZXModGFiKQ0KY29sbmFtZXMoY29sLmNvb3JkKSA8LSBwYXN0ZTAoIkRpbSIsIDE6bmIuYXhlcykNCmhlYWQoY29sLmNvb3JkKQ0KDQojIyMgcGxvdA0KcGxvdChjb2wuY29vcmQsIHBjaD0xNywgY29sID0gInJlZCIpDQp0ZXh0KGNvbC5jb29yZCwgbGFiZWxzID1yb3duYW1lcyhjb2wuY29vcmQpLCBwb3MgPSAzLCBjb2wgPSJyZWQiKQ0KYWJsaW5lKHY9MCwgaD0wLCBsdHkgPSAyKQ0KYGBgDQoNCiMjIyBCaXBsb3QgZGUgbGluaGFzIGUgY29sdW5hcyBwYXJhIHZlciBhIGFzc29jaWHDp8Ojbw0KDQpgYGB7cn0NCnhsaW0gPC0gcmFuZ2UoYyhyb3cuY29vcmRbLDFdLCBjb2wuY29vcmRbLDFdKSkqMS4xDQp5bGltIDwtIHJhbmdlKGMocm93LmNvb3JkWywyXSwgY29sLmNvb3JkWywyXSkpKjEuMQ0KIyMjIFBsb3Qgb2Ygcm93cw0KcGxvdChyb3cuY29vcmQsIHBjaD0xOSwgY29sID0gImJsdWUiLCB4bGltID0geGxpbSwgeWxpbSA9IHlsaW0pDQp0ZXh0KHJvdy5jb29yZCwgbGFiZWxzID1yb3duYW1lcyhyb3cuY29vcmQpLCBwb3MgPSAzLCBjb2wgPSJibHVlIikNCiMjIyBwbG90IG9mZiBjb2x1bW5zDQpwb2ludHMoY29sLmNvb3JkLCBwY2g9MTcsIGNvbCA9ICJyZWQiKQ0KdGV4dChjb2wuY29vcmQsIGxhYmVscyA9cm93bmFtZXMoY29sLmNvb3JkKSwgcG9zID0gMywgY29sID0icmVkIikNCmFibGluZSh2PTAsIGg9MCwgbHR5ID0gMikNCmBgYA0KDQojIyMgVm9jw6ogcG9kZSBpbnRlcnByZXRhciBhIGRpc3TDom5jaWEgZW50cmUgcG9udG9zIGRlIGxpbmhhcyBvdSBlbnRyZSBwb250b3MgZGUgY29sdW5hLCBtYXMgYSBkaXN0w6JuY2lhIGVudHJlIHBvbnRvcyBkZSBjb2x1bmEgZSBwb250b3MgZGUgbGluaGEgbsOjbyBzw6NvIHNpZ25pZmljYXRpdm9zLg0KDQojIyMgRGlhZ27Ds3N0aWNvDQoNCiMjI0xlbWJyZS1zZSBxdWUsIGEgaW7DqXJjaWEgdG90YWwgY29udGlkYSBub3MgZGFkb3Mgw6k6DQoNCiRccGhpXjIgPSBcZnJhY3tcY2hpXjJ9e259ID0gMC4zMTc2JA0KDQojIyNOb3NzbyBncsOhZmljbyBiaWRpbWVuc2lvbmFsIGNhcHR1cmEgMTAwJSBkYSBpbsOpcmNpYSB0b3RhbCBkYSB0YWJlbGEuDQoNCiMjIyBDb250cmlidWnDp8OjbyBkZSBsaW5oYXMgZSBjb2x1bmFzDQoNCiMjI0FzIGNvbnRyaWJ1acOnw7VlcyBkZSB1bWEgbGluaGEgLyBjb2x1bmEgcGFyYSBhIGRlZmluacOnw6NvIGRlIHVtIGVpeG8gcHJpbmNpcGFsIHPDo286DQoNCiRyb3cuY29udHJpYiA9IFxmcmFje3Jvdy5tYXNzICogcm93LmNvb3JkXjJ9e2VpZ2VudmFsdWV9JA0KDQokY29sLmNvbnRyaWIgPSBcZnJhY3tjb2wubWFzcyAqIGNvbC5jb29yZF4yfXtlaWdlbnZhbHVlfSQNCg0KIyMjQ29udHJpYnVpw6fDo28gZGUgbGluaGFzIGVtICUNCg0KYGBge3J9DQojIyMgY29udHJpYiA8LSByb3cubWFzcyAqIHJvdy5jb29yZF4yL2VpZ2VudmFsdWUNCmNjIDwtIGFwcGx5KHJvdy5jb29yZF4yLCAyLCAiKiIsIHJvdy5tYXNzKQ0Kcm93LmNvbnRyaWIgPC0gdChhcHBseShjYywgMSwgIi8iLCBlaWdbMTpuYi5heGVzLDFdKSkgKjEwMA0Kcm91bmQocm93LmNvbnRyaWIsIDIpDQoNCmNvcnJwbG90KHJvdy5jb250cmliLCBpcy5jb3IgPSBGQUxTRSkNCmBgYA0KDQojIyNDb250cmlidWnDp8OjbyBkYXMgY29sdW5hcyBlbSAlDQoNCmBgYHtyfQ0KIyMjIGNvbnRyaWIgPC0gY29sLm1hc3MgKiBjb2wuY29vcmReMi9laWdlbnZhbHVlDQpjYyA8LSBhcHBseShjb2wuY29vcmReMiwgMiwgIioiLCBjb2wubWFzcykNCmNvbC5jb250cmliIDwtIHQoYXBwbHkoY2MsIDEsICIvIiwgZWlnWzE6bmIuYXhlcywxXSkpICoxMDANCnJvdW5kKGNvbC5jb250cmliLCAyKQ0KDQpjb3JycGxvdChjb2wuY29udHJpYiwgaXMuY29yID0gRkFMU0UpDQpgYGANCg0KIyMjIFF1YWxpZGFkZSBkYSByZXByZXNlbnRhw6fDo28NCg0KIyMjQSBxdWFsaWRhZGUgZGEgcmVwcmVzZW50YcOnw6NvIMOpIGNoYW1hZGEgQ09TMi4NCg0KIyMjQSBxdWFsaWRhZGUgZGEgcmVwcmVzZW50YcOnw6NvIGRlIHVtYSBsaW5oYSBlbSB1bSBlaXhvIMOpOg0KDQokcm93LmNvczIgPSBcZnJhY3tyb3cuY29vcmReMn17ZF4yfSQNCg0KLSBSb3cuY29vcmQgw6kgYSBjb29yZGVuYWRhIGRhIGxpbmhhIG5vIGVpeG8NCi0gJGReMiQgw4kgYSBkaXN0w6JuY2lhIGFvIHF1YWRyYWRvIGRvIHBlcmZpbCBtw6lkaW8NCg0KIyMjTGVtYnJlLXNlIGRlIHF1ZSBhIGRpc3TDom5jaWEgZW50cmUgY2FkYSBwZXJmaWwgZGUgbGluaGEgZSBvIHBlcmZpbCBkZSBsaW5oYSBtw6lkaW8gw6k6DQoNCiRkXjIocm93X2ksIGF2ZXJhZ2UucHJvZmlsZSkgPSBcc3Vte1xmcmFjeyhyb3cucHJvZmlsZV9pIC0gYXZlcmFnZS5wcm9maWxlKV4yfXthdmVyYWdlLnByb2ZpbGV9fSQNCg0KYGBge3J9DQpyb3cucHJvZmlsZSA8LSB0YWIvcm93LnN1bQ0KaGVhZChyb3VuZChyb3cucHJvZmlsZSwgMykpDQoNCmF2ZXJhZ2UucHJvZmlsZSA8LSBjb2wuc3VtL24NCmhlYWQocm91bmQoYXZlcmFnZS5wcm9maWxlLCAzKSkNCmBgYA0KDQojIyNPIGPDs2RpZ28gUiBhYmFpeG8gY2FsY3VsYSBhIGRpc3TDom5jaWEgZG8gcGVyZmlsIG3DqWRpbyBwYXJhIHRvZGFzIGFzIHZhcmnDoXZlaXMgZGUgbGluaGENCg0KYGBge3J9DQphdmVyYWdlLnJwIDwtIGNvbC5zdW0vbiANCmQyLnJvdyA8LSBhcHBseShyb3cucHJvZmlsZSwgMSwgDQogICAgICAgICAgICAgICAgZnVuY3Rpb24ocm93LnAsIGF2LnApe3N1bSgoKHJvdy5wIC0gYXYucCleMikvYXYucCl9LCANCiAgICAgICAgICAgICAgICBhdmVyYWdlLnJwKQ0KaGVhZChyb3VuZChkMi5yb3csMykpDQpgYGANCg0KIyMjTyBjb3MyIGRlIGxpbmhhcyBubyBtYXBhIGRlIGZhdG9yZXMgc8OjbzoNCg0KYGBge3J9DQpyb3cuY29zMiA8LSBhcHBseShyb3cuY29vcmReMiwgMiwgIi8iLCBkMi5yb3cpDQpyb3VuZChyb3cuY29zMiwgMykNCg0KY29ycnBsb3Qocm93LmNvczIsIGlzLmNvciA9IEZBTFNFKQ0KYGBgDQoNCiMjI0NvczIgZGFzIGNvbHVuYXMNCg0KJGNvbC5jb3MyID0gXGZyYWN7Y29sLmNvb3JkXjJ9e2ReMn0kDQoNCmBgYHtyfQ0KY29sLnByb2ZpbGUgPC0gdCh0YWIpL2NvbC5zdW0NCmNvbC5wcm9maWxlIDwtIHQoY29sLnByb2ZpbGUpDQojIyNoZWFkKHJvdW5kKGNvbC5wcm9maWxlLCAzKSkNCmF2ZXJhZ2UucHJvZmlsZSA8LSByb3cuc3VtL24NCiMjI2hlYWQocm91bmQoYXZlcmFnZS5wcm9maWxlLCAzKSkNCmBgYA0KDQojIyNPIGPDs2RpZ28gUiBhYmFpeG8gY2FsY3VsYSBhIGRpc3TDom5jaWEgZG8gcGVyZmlsIG3DqWRpbyBwYXJhIHRvZGFzIGFzIHZhcmnDoXZlaXMgZGEgY29sdW5hDQoNCmBgYHtyfQ0KDQpkMi5jb2wgPC0gYXBwbHkoY29sLnByb2ZpbGUsIDIsIA0KICAgICAgICBmdW5jdGlvbihjb2wucCwgYXYucCl7c3VtKCgoY29sLnAgLSBhdi5wKV4yKS9hdi5wKX0sIA0KICAgICAgICBhdmVyYWdlLnByb2ZpbGUpDQpyb3VuZChkMi5jb2wsMykNCmBgYA0KDQojIyNPIGNvczIgZGFzIGNvbHVuYXMgbm8gbWFwYSBkZSBmYXRvcmVzIHPDo286DQoNCmBgYHtyfQ0KY29sLmNvczIgPC0gYXBwbHkoY29sLmNvb3JkXjIsIDIsICIvIiwgZDIuY29sKQ0Kcm91bmQoY29sLmNvczIsIDMpDQoNCmNvcnJwbG90KGNvbC5jb3MyLCBpcy5jb3IgPSBGQUxTRSkNCmBgYA0KDQoNCiMjIyBQYWNvdGVzIG5vIFIgcGFyYSBBTkFDT1INCg0KLUZhY3RvTWluZVINCi1hZGU0DQotY2ENCg0KYGBge3J9DQpsaWJyYXJ5KEZhY3RvTWluZVIpDQpyZXMuY2EgPC0gQ0EodGFiLCBncmFwaCA9IEYpDQoNCnJlcy5jYQ0KYGBgDQoNCg0KYGBge3J9DQojIyMgZWlnZW52YWx1ZQ0KaGVhZChyZXMuY2EkZWlnKVssIDE6Ml0NCg0KIyMjIGJhcnBsb3Qgb2YgcGVyY2VudGFnZSBvZiB2YXJpYW5jZQ0KYmFycGxvdChyZXMuY2EkZWlnWywyXSwgbmFtZXMuYXJnID0gcm93bmFtZXMocmVzLmNhJGVpZykpDQpgYGANCg0KYGBge3J9DQojIyMgUGxvdCByb3cgcG9pbnRzDQpwbG90KHJlcy5jYSwgaW52aXNpYmxlID0iY29sIikNCmBgYA0KDQpgYGB7cn0NCiMjIyBQbG90IGNvbHVtbiBwb2ludHMNCnBsb3QocmVzLmNhLCBpbnZpc2libGUgPSJyb3ciKQ0KYGBgDQoNCmBgYHtyfQ0KIyMjIEJpcGxvdCBvZiByb3dzIGFuZCBjb2x1bW5zDQpwbG90KHJlcy5jYSkNCmBgYA0KDQo=