Dados
Os dados USArrests
foram utilizados na aula para
realizar a análise.
data("USArrests")
dados <- USArrests
knitr::kable(head(dados, 10)) |>
kableExtra::kable_styling(full_width = TRUE,
bootstrap_options = c("striped", "hover", "condensed", "responsive")
)
|
Murder
|
Assault
|
UrbanPop
|
Rape
|
Alabama
|
13.2
|
236
|
58
|
21.2
|
Alaska
|
10.0
|
263
|
48
|
44.5
|
Arizona
|
8.1
|
294
|
80
|
31.0
|
Arkansas
|
8.8
|
190
|
50
|
19.5
|
California
|
9.0
|
276
|
91
|
40.6
|
Colorado
|
7.9
|
204
|
78
|
38.7
|
Connecticut
|
3.3
|
110
|
77
|
11.1
|
Delaware
|
5.9
|
238
|
72
|
15.8
|
Florida
|
15.4
|
335
|
80
|
31.9
|
Georgia
|
17.4
|
211
|
60
|
25.8
|
De acordo com o chat gpt, o USArrests
é um famoso
conjunto de dados embutido no R, que contém informações sobre os crimes
violentos cometidos nos Estados Unidos nos anos 1970. As colunas
representam estatísticas sobre a taxa de crimes por estado. Cada linha
do conjunto de dados corresponde a um estado dos EUA. Segue o que
representa cada uma das colunas do conjunto de dados:
- Murder: Taxa de homicídios (assassinatos) por
100.000 habitantes.
- Assault: Taxa de agressões (assaltos) por 100.000
habitantes.
- UrbanPop: Percentual da população do estado que
vive em áreas urbanas.
- Rape: Taxa de estupros por 100.000 habitantes.
Análise Exploratória
Cálculo de medidas descritivas
Inicialmente, vamos calcular as medidas descritivas dos dados.
resumo <- summary(dados); resumo
## Murder Assault UrbanPop Rape
## Min. : 0.800 Min. : 45.0 Min. :32.00 Min. : 7.30
## 1st Qu.: 4.075 1st Qu.:109.0 1st Qu.:54.50 1st Qu.:15.07
## Median : 7.250 Median :159.0 Median :66.00 Median :20.10
## Mean : 7.788 Mean :170.8 Mean :65.54 Mean :21.23
## 3rd Qu.:11.250 3rd Qu.:249.0 3rd Qu.:77.75 3rd Qu.:26.18
## Max. :17.400 Max. :337.0 Max. :91.00 Max. :46.00
Agora vamos calcular medidas de variabilidade.
var(dados$Murder); var(dados$Assault); var(dados$UrbanPop); var(dados$Rape) # variâncias
## [1] 18.97047
## [1] 6945.166
## [1] 209.5188
## [1] 87.72916
s1 <- sd(dados$Murder); s1 # desvios padroes
## [1] 4.35551
s2 <- sd(dados$Assault); s2
## [1] 83.33766
s3 <- sd(dados$UrbanPop);s3
## [1] 14.47476
s4 <- sd(dados$Rape); s4
## [1] 9.366385
s1/mean(dados$Murder) # coeficientes de variação
## [1] 0.5592591
s2/mean(dados$Assault)
## [1] 0.4880397
s3/mean(dados$UrbanPop)
## [1] 0.2208539
s4/mean(dados$Rape)
## [1] 0.4411447
Plotagem de gráficos
Agora vamos fazer histogramas para verificar a assimetria dos
dados.
opar <- par(mfrow = c(2, 2))
hist(dados$Murder, main = "Taxa de homicídios", col = "lightgreen")
hist(dados$Assault, main = "Taxa de agressões", col = "red")
hist(dados$UrbanPop, main = "Percentual da população de áreas urbanas", col = "blue")
hist(dados$Rape, main = "Taxa de estupros", col = "orange")

Agora vamos verificar a presença de dados atípicos e de assimetria
por meio de boxplots.
opar <- par(mfrow = c(2, 2))
boxplot(dados$Murder, main = "Taxa de homicidios", col = "lightgreen")
boxplot(dados$Assault, main = "Taxa de agressoes", col = "red")
boxplot(dados$UrbanPop, main = "Percentual da populacao de areas urbanas", col = "blue")
boxplot(dados$Rape, main = "Taxa de estupros", col = "orange")

## Os outliers do boxplot da taxa de estupros é referente aos estados: Alaska e Nevada
Em
busca do estado mais violento e menos violento
Ranqueamento para cada
variável
Homicídios
Vamos ordernar os dados e verificar os 5 estados com maior e menor
taxa de homícidios.
maior <- head(arrange(dados, desc(Murder)), 5)
menor <- head(arrange(dados, Murder), 5)
cat("5 estados com maior taxa de homicídios:\n",
paste(rownames(maior), collapse = "\n"))
## 5 estados com maior taxa de homicídios:
## Georgia
## Mississippi
## Florida
## Louisiana
## South Carolina
cat("5 estados com menor taxa de homicídios:\n",
paste(rownames(menor), collapse = "\n"))
## 5 estados com menor taxa de homicídios:
## North Dakota
## Maine
## New Hampshire
## Iowa
## Vermont
Agressões
Vamos verificar os 5 estados com maior e menor taxa de agressões.
maior <- head(arrange(dados, desc(Assault)), 5)
menor <- head(arrange(dados, Assault), 5)
cat("5 estados com maior taxa de agressões:\n",
paste(rownames(maior), collapse = "\n"))
## 5 estados com maior taxa de agressões:
## North Carolina
## Florida
## Maryland
## Arizona
## New Mexico
cat("5 estados com menor taxa de agressões:\n",
paste(rownames(menor), collapse = "\n"))
## 5 estados com menor taxa de agressões:
## North Dakota
## Hawaii
## Vermont
## Wisconsin
## Iowa
população de áreas hurbanas
Agora vamos verificar quais os 5 estados com maior e menor percentual
da população do estado que vive em áreas hurbanas.
menor <- head(arrange(dados, UrbanPop), 5)
maior <- head(arrange(dados, desc(UrbanPop)), 5)
cat("5 estados com maior percentual da população que vive em áreas hurbanas:\n",
paste(rownames(maior), collapse = "\n"))
## 5 estados com maior percentual da população que vive em áreas hurbanas:
## California
## New Jersey
## Rhode Island
## New York
## Massachusetts
cat("5 estados com menor percentual da população que vive em áreas hurbanas:\n",
paste(rownames(menor), collapse = "\n"))
## 5 estados com menor percentual da população que vive em áreas hurbanas:
## Vermont
## West Virginia
## Mississippi
## North Dakota
## North Carolina
Estupros
Vamos verificar quais os 5 estados com maior e menor taxa de
estupros.
menor <- head(arrange(dados, Rape), 5)
maior <- head(arrange(dados, desc(Rape)), 5)
cat("5 estados com maior taxa de estupros:\n",
paste(rownames(maior), collapse = "\n"))
## 5 estados com maior taxa de estupros:
## Nevada
## Alaska
## California
## Colorado
## Michigan
cat("5 estados com menor taxa de estupros:\n",
paste(rownames(menor), collapse = "\n"))
## 5 estados com menor taxa de estupros:
## North Dakota
## Maine
## Rhode Island
## West Virginia
## New Hampshire
Criando a variável que mede o nível de violência
Vamos iniciar padronizando cada uma das variáveis.
z_murder <- (dados$Murder - mean(dados$Murder))/s1
z_assault <- (dados$Assault - mean(dados$Assault))/s2
z_urbanpop <- (dados$UrbanPop - mean(dados$UrbanPop))/s3
z_rape <- (dados$Rape - mean(dados$Rape))/s4
dados_pad <- cbind(z_murder, z_assault, z_urbanpop, z_rape)
Vamos criar a partir desses dados a variável violencia
por meio da média das variáveis.
violencia <- rowMeans(dados_pad)
dados <- cbind(dados, violencia)
knitr::kable(head(dados, 10)) |>
kableExtra::kable_styling(full_width = TRUE,
bootstrap_options = c("striped", "hover", "condensed", "responsive")
)
|
Murder
|
Assault
|
UrbanPop
|
Rape
|
violencia
|
Alabama
|
13.2
|
236
|
58
|
21.2
|
0.3752701
|
Alaska
|
10.0
|
263
|
48
|
44.5
|
0.7217809
|
Arizona
|
8.1
|
294
|
80
|
31.0
|
0.8980738
|
Arkansas
|
8.8
|
190
|
50
|
19.5
|
-0.1988230
|
California
|
9.0
|
276
|
91
|
40.6
|
1.3419566
|
Colorado
|
7.9
|
204
|
78
|
38.7
|
0.7875874
|
Connecticut
|
3.3
|
110
|
77
|
11.1
|
-0.5123798
|
Delaware
|
5.9
|
238
|
72
|
15.8
|
0.0599280
|
Florida
|
15.4
|
335
|
80
|
31.9
|
1.4640990
|
Georgia
|
17.4
|
211
|
60
|
25.8
|
0.6986703
|
Ordenando os estados com maior e menor nível de violência.
Vamos criar um ranking dos estados mais violentas de acordo com a
variável criada.
menor <- head(arrange(dados, violencia), 5)
maior <- head(arrange(dados, desc(violencia)), 5)
cat("5 estados mais violentos:\n",
paste(rownames(maior), collapse = "\n"))
## 5 estados mais violentos:
## Florida
## Nevada
## California
## Michigan
## New York
cat("5 estados menos violentos:\n",
paste(rownames(menor), collapse = "\n"))
## 5 estados menos violentos:
## Vermont
## North Dakota
## Maine
## West Virginia
## New Hampshire
Como eu não acho razoável fazer uma média (porque estamos atribuindo
o mesmo peso a variáveis que podem impactar em diferentes níveis na
violência do estado), então será feito uma árvore de decisão para saber
quais as variáveis que mais impactaram no nível de violência.
# divisao em treino e teste
set.seed(321)
indice_treino <- sample(1:nrow(dados), size = 0.7 * nrow(dados)) # 70% do bd é para treino
bd_treino <- dados[indice_treino, ]
bd_teste <- dados[-indice_treino, ]
# arvore de decisao
arvore_cart_completa <- rpart(
formula = violencia ~ .,
data = bd_treino,
method = "anova" # regressao
)
# Plotando
rpart.plot(arvore_cart_completa,
type = 0,
extra = 101,
fallen.leaves = TRUE)

# variaveis mais importantes
importancia <- arvore_cart_completa$variable.importance; importancia
## Assault Murder Rape UrbanPop
## 13.695968 10.801362 8.040694 2.385421
As duas variáveis mais importantes foram Assault
e
Murder
. Serão consideradas todas as variáveis na criação da
variável violencia
, atribuindo como peso a contribuição
delas na árvore.
importancia <- importancia/sum(importancia)
violencia <-
z_assault*importancia[1] +
z_murder*importancia[2] +
z_rape*importancia[3] +
z_urbanpop*importancia[4]
dados$violencia <- violencia
knitr::kable(head(dados, 10)) |>
kableExtra::kable_styling(full_width = TRUE,
bootstrap_options = c("striped", "hover", "condensed", "responsive")
)
|
Murder
|
Assault
|
UrbanPop
|
Rape
|
violencia
|
Alabama
|
13.2
|
236
|
58
|
21.2
|
0.6549490
|
Alaska
|
10.0
|
263
|
48
|
44.5
|
1.0803276
|
Arizona
|
8.1
|
294
|
80
|
31.0
|
0.9104438
|
Arkansas
|
8.8
|
190
|
50
|
19.5
|
0.0464966
|
California
|
9.0
|
276
|
91
|
40.6
|
1.1775363
|
Colorado
|
7.9
|
204
|
78
|
38.7
|
0.6525570
|
Connecticut
|
3.3
|
110
|
77
|
11.1
|
-0.7995995
|
Delaware
|
5.9
|
238
|
72
|
15.8
|
0.0793091
|
Florida
|
15.4
|
335
|
80
|
31.9
|
1.6438816
|
Georgia
|
17.4
|
211
|
60
|
25.8
|
0.9580594
|
Essa nova variável violencia
resulta nos seguintes
rankings.
menor <- head(arrange(dados, violencia), 5)
maior <- head(arrange(dados, desc(violencia)), 5)
cat("5 estados mais violentos:\n",
paste(rownames(maior), collapse = "\n"))
## 5 estados mais violentos:
## Florida
## Nevada
## California
## Michigan
## New Mexico
cat("5 estados menos violentos:\n",
paste(rownames(menor), collapse = "\n"))
## 5 estados menos violentos:
## North Dakota
## Vermont
## New Hampshire
## Iowa
## Maine
Análise de Cluster
Agora vamos fazer uma breve análise de cluster para verificar quais
os estados mais semelhantes. Primeiramente calculamos a matriz de
distâncias euclidianas.
dados_num <- as.matrix(dados)
D_E <- dist(dados_num, method = "euclidian")
O vizinho mais próximo
Vamos iniciar com o método do vizinho mais próximo.
# O vizinho mais proximo
m <- hclust(D_E, method = "single")
m$height
## [1] 2.291863 3.842566 3.932045 6.238535 6.641778 7.356842 7.934484
## [8] 8.031794 8.540646 8.766984 9.508521 10.305404 10.579231 10.922844
## [15] 11.071967 11.256321 11.461496 11.528739 11.766781 12.625298 13.045817
## [22] 13.300617 13.897105 14.501039 15.016435 15.068436 15.456981 15.504785
## [29] 16.068275 16.652992 16.816104 17.163838 18.715460 18.854213 19.701654
## [36] 19.920486 20.829570 21.167561 22.853147 23.195718 23.430697 23.643593
## [43] 24.708653 24.923564 25.747428 25.843604 27.556912 37.788912 38.534538
plot(m, cex = 0.7, hang = -1,
main = "Dendograma - O vizinho mais próximo",
xlab = "Estados", ylab = "")

O vizinho mais distante
Agora vamos para o método do vizinho mais distante.
m <- hclust(D_E, method = "complete")
m$height
## [1] 2.291863 3.842566 3.932045 6.238535 6.641778 7.356842
## [7] 8.031794 8.540646 10.860441 11.461496 12.425773 12.625298
## [13] 12.777374 13.045817 13.300617 13.354127 13.897105 14.501039
## [19] 15.416320 15.456981 15.631725 15.890349 16.998284 18.265170
## [25] 19.438594 19.904697 21.167561 22.376177 22.767529 24.895798
## [31] 25.094887 28.636468 29.251698 31.477346 31.621581 32.722227
## [37] 36.739860 36.848995 38.534538 41.491541 48.732526 53.594343
## [43] 57.271719 64.994674 68.775142 87.331230 102.865070 168.629805
## [49] 293.639928
plot(m, cex = 0.7, hang = -1,
main = "Dendograma - O vizinho mais distante",
xlab = "Estados", ylab = "")

Centroide
Agora utilizando o método do centroide.
m <- hclust(D_E, method = "centroid")
m$height
## [1] 2.291863 3.842566 3.932045 6.238535 6.641778 7.356842
## [7] 8.031794 8.540646 8.637018 8.899426 9.611515 9.675119
## [13] 10.364569 9.378527 11.461496 11.480792 11.808084 11.959271
## [19] 12.209114 12.625298 13.045817 13.300617 13.538437 13.897105
## [25] 11.979116 14.501039 15.262767 15.316522 16.477143 16.816104
## [31] 15.146299 17.043967 19.542440 19.969351 16.733851 21.027665
## [37] 21.167561 22.369746 22.804800 21.434675 23.034681 22.596466
## [43] 25.145353 29.478992 34.027865 38.534538 51.321137 54.450146
## [49] 100.090001
plot(m, cex = 0.7, hang = -1,
main = "Dendograma - Centroide",
xlab = "Estados", ylab = "")

Ligação média
E, para finalizar os método de clustering hierárquico vistos em sala,
vamos fazer o método da ligação média.
m <- hclust(D_E, method = "average")
m$height
## [1] 2.291863 3.842566 3.932045 6.238535 6.641778 7.356842
## [7] 8.031794 8.540646 10.184481 10.738637 10.772179 11.461496
## [13] 12.441433 12.625298 12.878910 13.045817 13.300617 13.355529
## [19] 13.897105 14.501039 15.030098 15.125594 15.453392 15.456981
## [25] 16.426042 16.907194 18.423225 18.995012 20.200291 20.600798
## [31] 21.167561 22.599234 23.974017 26.370293 26.715015 27.781761
## [37] 28.012891 28.096690 29.058723 33.118936 38.534538 39.396599
## [43] 41.098395 44.285491 44.845174 54.751110 77.607316 89.237776
## [49] 152.321117
plot(m, cex = 0.7, hang = -1,
main = "Dendograma - Ligação Média",
xlab = "Estados", ylab = "")

K-means
Para a análise de cluster, também podemos utilizar o método do
k-means. Porém, como a plotagem necessita de componentes principais,
então não vamos fazê-la. O número de grupos igual a 2 vem da ideia de
criar o cluster de estados perigosos e o cluster de estados seguros. O
grupo que conter Florida será considerado perigoso (por conta dos
rankings) e o grupo que conter North Dakota será considerado seguro.
set.seed(548254)
km <- kmeans(dados_num, centers = 2)
# Cluster 1
cat("Cluster 1:\n", paste(rownames(dados_num)[km$cluster == 1], collapse = "\n"), "\n\n")
## Cluster 1:
## Connecticut
## Hawaii
## Idaho
## Indiana
## Iowa
## Kansas
## Kentucky
## Maine
## Massachusetts
## Minnesota
## Missouri
## Montana
## Nebraska
## New Hampshire
## New Jersey
## North Dakota
## Ohio
## Oklahoma
## Oregon
## Pennsylvania
## Rhode Island
## South Dakota
## Utah
## Vermont
## Virginia
## Washington
## West Virginia
## Wisconsin
## Wyoming
# Cluster 2
cat("Cluster 2:\n", paste(rownames(dados_num)[km$cluster == 2], collapse = "\n"), "\n\n")
## Cluster 2:
## Alabama
## Alaska
## Arizona
## Arkansas
## California
## Colorado
## Delaware
## Florida
## Georgia
## Illinois
## Louisiana
## Maryland
## Michigan
## Mississippi
## Nevada
## New Mexico
## New York
## North Carolina
## South Carolina
## Tennessee
## Texas
Conclusão
De forma respectiva, os estados mais perigosos para se morar é
Florida
e Nevada
, enquanto os mais seguros são
Vermont
e North Dakota
.
LS0tDQp0aXRsZTogJ0Fuw6FsaXNlIE11bHRpdmFyaWFkYScNCmF1dGhvcjogJypKb25hcyBGcmVpcmUgUmliZWlybyAtIDU0ODI1NConDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICcqJWQgZGUgJUIsICAlWSonKWAiDQpsaW5rLWNpdGF0aW9uczogdHJ1ZQ0KbGFuZzogInB0LWJyIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRoZW1lOg0KICAgICAgYm9vdHN3YXRjaDogZmxhdGx5DQogICAgaGlnaGxpZ2h0OiBicmVlemVkYXJrDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdG9jX2RlcHRoOiA0DQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgYW5jaG9yX3NlY3Rpb25zOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGZpZ19jYXB0aW9uOiB0cnVlDQogICAgY2l0YXRpb25fcGFja2FnZTogYmlibGF0ZXgNCi0tLQ0KDQojIERhZG9zDQoNCk9zIGRhZG9zIGBVU0FycmVzdHNgIGZvcmFtIHV0aWxpemFkb3MgbmEgYXVsYSBwYXJhIHJlYWxpemFyIGEgYW7DoWxpc2UuDQoNCmBgYHtyIHJlc3VsdHM9J2hpZGUnLCBlY2hvPUZBTFNFfQ0KaW5zdGFsbC5wYWNrYWdlcygia2FibGVFeHRyYSIpDQoNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkoa25pdHIpDQpgYGANCg0KDQpgYGB7cn0NCmRhdGEoIlVTQXJyZXN0cyIpDQpkYWRvcyA8LSBVU0FycmVzdHMNCg0Ka25pdHI6OmthYmxlKGhlYWQoZGFkb3MsIDEwKSkgfD4gDQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIikgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQ0KYGBgDQoNCkRlIGFjb3JkbyBjb20gbyBjaGF0IGdwdCwgbyBgVVNBcnJlc3RzYCDDqSB1bSBmYW1vc28gY29uanVudG8gZGUgZGFkb3MgZW1idXRpZG8gbm8gUiwgcXVlIGNvbnTDqW0gaW5mb3JtYcOnw7VlcyBzb2JyZSBvcyBjcmltZXMgdmlvbGVudG9zIGNvbWV0aWRvcyBub3MgRXN0YWRvcyBVbmlkb3Mgbm9zIGFub3MgMTk3MC4gQXMgY29sdW5hcyByZXByZXNlbnRhbSBlc3RhdMOtc3RpY2FzIHNvYnJlIGEgdGF4YSBkZSBjcmltZXMgcG9yIGVzdGFkby4gQ2FkYSBsaW5oYSBkbyBjb25qdW50byBkZSBkYWRvcyBjb3JyZXNwb25kZSBhIHVtIGVzdGFkbyBkb3MgRVVBLiBTZWd1ZSBvIHF1ZSByZXByZXNlbnRhIGNhZGEgdW1hIGRhcyBjb2x1bmFzIGRvIGNvbmp1bnRvIGRlIGRhZG9zOg0KDQoxLiAqKk11cmRlcioqOiBUYXhhIGRlIGhvbWljw61kaW9zIChhc3Nhc3NpbmF0b3MpIHBvciAxMDAuMDAwIGhhYml0YW50ZXMuDQoxLiAqKkFzc2F1bHQqKjogVGF4YSBkZSBhZ3Jlc3PDtWVzIChhc3NhbHRvcykgcG9yIDEwMC4wMDAgaGFiaXRhbnRlcy4NCjEuICoqVXJiYW5Qb3AqKjogUGVyY2VudHVhbCBkYSBwb3B1bGHDp8OjbyBkbyBlc3RhZG8gcXVlIHZpdmUgZW0gw6FyZWFzIHVyYmFuYXMuDQoxLiAqKlJhcGUqKjogVGF4YSBkZSBlc3R1cHJvcyBwb3IgMTAwLjAwMCBoYWJpdGFudGVzLg0KDQojIEFuw6FsaXNlIEV4cGxvcmF0w7NyaWENCg0KIyMgQ8OhbGN1bG8gZGUgbWVkaWRhcyBkZXNjcml0aXZhcw0KDQpJbmljaWFsbWVudGUsIHZhbW9zIGNhbGN1bGFyIGFzIG1lZGlkYXMgZGVzY3JpdGl2YXMgZG9zIGRhZG9zLg0KYGBge3J9DQpyZXN1bW8gPC0gc3VtbWFyeShkYWRvcyk7IHJlc3Vtbw0KYGBgDQpBZ29yYSB2YW1vcyBjYWxjdWxhciBtZWRpZGFzIGRlIHZhcmlhYmlsaWRhZGUuDQpgYGB7ciBjb2xsYXBzZT1UUlVFfQ0KdmFyKGRhZG9zJE11cmRlcik7IHZhcihkYWRvcyRBc3NhdWx0KTsgdmFyKGRhZG9zJFVyYmFuUG9wKTsgdmFyKGRhZG9zJFJhcGUpICMgdmFyacOibmNpYXMNCg0KczEgPC0gc2QoZGFkb3MkTXVyZGVyKTsgczEgICMgZGVzdmlvcyBwYWRyb2VzDQpzMiA8LSBzZChkYWRvcyRBc3NhdWx0KTsgczINCnMzIDwtIHNkKGRhZG9zJFVyYmFuUG9wKTtzMw0KczQgPC0gc2QoZGFkb3MkUmFwZSk7IHM0DQoNCnMxL21lYW4oZGFkb3MkTXVyZGVyKSAjIGNvZWZpY2llbnRlcyBkZSB2YXJpYcOnw6NvDQpzMi9tZWFuKGRhZG9zJEFzc2F1bHQpDQpzMy9tZWFuKGRhZG9zJFVyYmFuUG9wKQ0KczQvbWVhbihkYWRvcyRSYXBlKQ0KYGBgDQoNCiMjIFBsb3RhZ2VtIGRlIGdyw6FmaWNvcw0KDQpBZ29yYSB2YW1vcyBmYXplciBoaXN0b2dyYW1hcyBwYXJhIHZlcmlmaWNhciBhIGFzc2ltZXRyaWEgZG9zIGRhZG9zLg0KYGBge3IgY29sbGFwc2U9VFJVRX0NCm9wYXIgPC0gcGFyKG1mcm93ID0gYygyLCAyKSkNCmhpc3QoZGFkb3MkTXVyZGVyLCBtYWluID0gIlRheGEgZGUgaG9taWPDrWRpb3MiLCBjb2wgPSAibGlnaHRncmVlbiIpDQpoaXN0KGRhZG9zJEFzc2F1bHQsIG1haW4gPSAiVGF4YSBkZSBhZ3Jlc3PDtWVzIiwgY29sID0gInJlZCIpDQpoaXN0KGRhZG9zJFVyYmFuUG9wLCBtYWluID0gIlBlcmNlbnR1YWwgZGEgcG9wdWxhw6fDo28gZGUgw6FyZWFzIHVyYmFuYXMiLCBjb2wgPSAiYmx1ZSIpDQpoaXN0KGRhZG9zJFJhcGUsIG1haW4gPSAiVGF4YSBkZSBlc3R1cHJvcyIsIGNvbCA9ICJvcmFuZ2UiKQ0KYGBgDQoNCkFnb3JhIHZhbW9zIHZlcmlmaWNhciBhIHByZXNlbsOnYSBkZSBkYWRvcyBhdMOtcGljb3MgZSBkZSBhc3NpbWV0cmlhIHBvciBtZWlvIGRlIGJveHBsb3RzLg0KYGBge3J9DQpvcGFyIDwtIHBhcihtZnJvdyA9IGMoMiwgMikpDQpib3hwbG90KGRhZG9zJE11cmRlciwgbWFpbiA9ICJUYXhhIGRlIGhvbWljaWRpb3MiLCBjb2wgPSAibGlnaHRncmVlbiIpDQpib3hwbG90KGRhZG9zJEFzc2F1bHQsIG1haW4gPSAiVGF4YSBkZSBhZ3Jlc3NvZXMiLCBjb2wgPSAicmVkIikNCmJveHBsb3QoZGFkb3MkVXJiYW5Qb3AsIG1haW4gPSAiUGVyY2VudHVhbCBkYSBwb3B1bGFjYW8gZGUgYXJlYXMgdXJiYW5hcyIsIGNvbCA9ICJibHVlIikNCmJveHBsb3QoZGFkb3MkUmFwZSwgbWFpbiA9ICJUYXhhIGRlIGVzdHVwcm9zIiwgY29sID0gIm9yYW5nZSIpDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmIgPC0gYm94cGxvdChkYWRvcyRSYXBlLCBtYWluID0gIlRheGEgZGUgZXN0dXByb3MiLCBjb2wgPSAib3JhbmdlIikNCm91dF92YWx1ZXMgPC0gYiRvdXQNCm91dF9zdGF0ZXMgPC0gcm93bmFtZXMoZGFkb3MpW2RhZG9zJFJhcGUgJWluJSBvdXRfdmFsdWVzXQ0KYGBgDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpjYXQoIk9zIG91dGxpZXJzIGRvIGJveHBsb3QgZGEgdGF4YSBkZSBlc3R1cHJvcyDDqSByZWZlcmVudGUgYW9zIGVzdGFkb3M6Iiwgb3V0X3N0YXRlc1sxXSwgImUiLCBvdXRfc3RhdGVzWzJdLCJcbiIpDQpgYGANCg0KDQojIyBFbSBidXNjYSBkbyBlc3RhZG8gbWFpcyB2aW9sZW50byBlIG1lbm9zIHZpb2xlbnRvDQoNCiMjIyBSYW5xdWVhbWVudG8gcGFyYSBjYWRhIHZhcmnDoXZlbCB7LnRhYnNldCAudGFic2V0LWZhZGV9DQoNCiMjIyMgSG9taWPDrWRpb3Mgey51bmxpc3RlZCAudW5udW1iZXJlZH0NCg0KVmFtb3Mgb3JkZXJuYXIgb3MgZGFkb3MgZSB2ZXJpZmljYXIgb3MgNSBlc3RhZG9zIGNvbSBtYWlvciBlIG1lbm9yIHRheGEgZGUgaG9tw61jaWRpb3MuDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30NCmluc3RhbGwucGFja2FnZXMoImRwbHlyIikNCmxpYnJhcnkoImRwbHlyIikNCmBgYA0KDQpgYGB7cn0NCm1haW9yIDwtIGhlYWQoYXJyYW5nZShkYWRvcywgZGVzYyhNdXJkZXIpKSwgNSkNCm1lbm9yIDwtIGhlYWQoYXJyYW5nZShkYWRvcywgTXVyZGVyKSwgNSkNCg0KY2F0KCI1IGVzdGFkb3MgY29tIG1haW9yIHRheGEgZGUgaG9taWPDrWRpb3M6XG4iLA0KICAgIHBhc3RlKHJvd25hbWVzKG1haW9yKSwgY29sbGFwc2UgPSAiXG4iKSkNCg0KDQpjYXQoIjUgZXN0YWRvcyBjb20gbWVub3IgdGF4YSBkZSBob21pY8OtZGlvczpcbiIsDQogICAgcGFzdGUocm93bmFtZXMobWVub3IpLCBjb2xsYXBzZSA9ICJcbiIpKQ0KYGBgDQoNCiMjIyMgQWdyZXNzw7VlcyB7LnVubGlzdGVkIC51bm51bWJlcmVkfQ0KDQpWYW1vcyB2ZXJpZmljYXIgb3MgNSBlc3RhZG9zIGNvbSBtYWlvciBlIG1lbm9yIHRheGEgZGUgYWdyZXNzw7Vlcy4NCg0KYGBge3J9DQptYWlvciA8LSBoZWFkKGFycmFuZ2UoZGFkb3MsIGRlc2MoQXNzYXVsdCkpLCA1KQ0KbWVub3IgPC0gaGVhZChhcnJhbmdlKGRhZG9zLCBBc3NhdWx0KSwgNSkNCg0KY2F0KCI1IGVzdGFkb3MgY29tIG1haW9yIHRheGEgZGUgYWdyZXNzw7VlczpcbiIsDQogICAgcGFzdGUocm93bmFtZXMobWFpb3IpLCBjb2xsYXBzZSA9ICJcbiIpKQ0KDQoNCmNhdCgiNSBlc3RhZG9zIGNvbSBtZW5vciB0YXhhIGRlIGFncmVzc8O1ZXM6XG4iLA0KICAgIHBhc3RlKHJvd25hbWVzKG1lbm9yKSwgY29sbGFwc2UgPSAiXG4iKSkNCmBgYA0KDQojIyMjIHBvcHVsYcOnw6NvIGRlIMOhcmVhcyBodXJiYW5hcyB7LnVubGlzdGVkIC51bm51bWJlcmVkfQ0KDQpBZ29yYSB2YW1vcyB2ZXJpZmljYXIgcXVhaXMgb3MgNSBlc3RhZG9zIGNvbSBtYWlvciBlIG1lbm9yIHBlcmNlbnR1YWwgZGEgcG9wdWxhw6fDo28gZG8gZXN0YWRvIHF1ZSB2aXZlIGVtIMOhcmVhcyBodXJiYW5hcy4NCmBgYHtyfQ0KbWVub3IgPC0gaGVhZChhcnJhbmdlKGRhZG9zLCBVcmJhblBvcCksIDUpDQptYWlvciA8LSBoZWFkKGFycmFuZ2UoZGFkb3MsIGRlc2MoVXJiYW5Qb3ApKSwgNSkNCg0KY2F0KCI1IGVzdGFkb3MgY29tIG1haW9yIHBlcmNlbnR1YWwgZGEgcG9wdWxhw6fDo28gcXVlIHZpdmUgZW0gw6FyZWFzIGh1cmJhbmFzOlxuIiwNCiAgICBwYXN0ZShyb3duYW1lcyhtYWlvciksIGNvbGxhcHNlID0gIlxuIikpDQoNCg0KY2F0KCI1IGVzdGFkb3MgY29tIG1lbm9yIHBlcmNlbnR1YWwgZGEgcG9wdWxhw6fDo28gcXVlIHZpdmUgZW0gw6FyZWFzIGh1cmJhbmFzOlxuIiwNCiAgICBwYXN0ZShyb3duYW1lcyhtZW5vciksIGNvbGxhcHNlID0gIlxuIikpDQpgYGANCg0KIyMjIyBFc3R1cHJvcyB7LnVubGlzdGVkIC51bm51bWJlcmVkfQ0KVmFtb3MgdmVyaWZpY2FyIHF1YWlzIG9zIDUgZXN0YWRvcyBjb20gbWFpb3IgZSBtZW5vciB0YXhhIGRlIGVzdHVwcm9zLg0KYGBge3J9DQptZW5vciA8LSBoZWFkKGFycmFuZ2UoZGFkb3MsIFJhcGUpLCA1KQ0KbWFpb3IgPC0gaGVhZChhcnJhbmdlKGRhZG9zLCBkZXNjKFJhcGUpKSwgNSkNCg0KY2F0KCI1IGVzdGFkb3MgY29tIG1haW9yIHRheGEgZGUgZXN0dXByb3M6XG4iLA0KICAgIHBhc3RlKHJvd25hbWVzKG1haW9yKSwgY29sbGFwc2UgPSAiXG4iKSkNCg0KDQpjYXQoIjUgZXN0YWRvcyBjb20gbWVub3IgdGF4YSBkZSBlc3R1cHJvczpcbiIsDQogICAgcGFzdGUocm93bmFtZXMobWVub3IpLCBjb2xsYXBzZSA9ICJcbiIpKQ0KYGBgDQoNCiMjIyBDcmlhbmRvIGEgdmFyacOhdmVsIHF1ZSBtZWRlIG8gbsOtdmVsIGRlIHZpb2zDqm5jaWENCg0KVmFtb3MgaW5pY2lhciBwYWRyb25pemFuZG8gY2FkYSB1bWEgZGFzIHZhcmnDoXZlaXMuDQoNCmBgYHtyfQ0Kel9tdXJkZXIgPC0gKGRhZG9zJE11cmRlciAtIG1lYW4oZGFkb3MkTXVyZGVyKSkvczENCnpfYXNzYXVsdCA8LSAoZGFkb3MkQXNzYXVsdCAtIG1lYW4oZGFkb3MkQXNzYXVsdCkpL3MyDQp6X3VyYmFucG9wCSA8LSAoZGFkb3MkVXJiYW5Qb3AJIC0gbWVhbihkYWRvcyRVcmJhblBvcCkpL3MzDQp6X3JhcGUJIDwtIChkYWRvcyRSYXBlCSAtIG1lYW4oZGFkb3MkUmFwZSkpL3M0DQoNCmRhZG9zX3BhZCA8LSBjYmluZCh6X211cmRlciwgel9hc3NhdWx0LCB6X3VyYmFucG9wLCB6X3JhcGUpDQpgYGANCg0KVmFtb3MgY3JpYXIgYSBwYXJ0aXIgZGVzc2VzIGRhZG9zIGEgdmFyacOhdmVsIGB2aW9sZW5jaWFgIHBvciBtZWlvIGRhIG3DqWRpYSBkYXMgdmFyacOhdmVpcy4NCmBgYHtyfQ0KdmlvbGVuY2lhIDwtIHJvd01lYW5zKGRhZG9zX3BhZCkNCg0KZGFkb3MgPC0gY2JpbmQoZGFkb3MsIHZpb2xlbmNpYSkNCg0Ka25pdHI6OmthYmxlKGhlYWQoZGFkb3MsIDEwKSkgfD4gDQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIikgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQ0KYGBgDQoNCiMjIyBPcmRlbmFuZG8gb3MgZXN0YWRvcyBjb20gbWFpb3IgZSBtZW5vciBuw612ZWwgZGUgdmlvbMOqbmNpYS4NCg0KVmFtb3MgY3JpYXIgdW0gcmFua2luZyBkb3MgZXN0YWRvcyBtYWlzIHZpb2xlbnRhcyBkZSBhY29yZG8gY29tIGEgdmFyacOhdmVsIGNyaWFkYS4NCmBgYHtyfQ0KbWVub3IgPC0gaGVhZChhcnJhbmdlKGRhZG9zLCB2aW9sZW5jaWEpLCA1KQ0KbWFpb3IgPC0gaGVhZChhcnJhbmdlKGRhZG9zLCBkZXNjKHZpb2xlbmNpYSkpLCA1KQ0KDQpjYXQoIjUgZXN0YWRvcyBtYWlzIHZpb2xlbnRvczpcbiIsDQogICAgcGFzdGUocm93bmFtZXMobWFpb3IpLCBjb2xsYXBzZSA9ICJcbiIpKQ0KDQoNCmNhdCgiNSBlc3RhZG9zIG1lbm9zIHZpb2xlbnRvczpcbiIsDQogICAgcGFzdGUocm93bmFtZXMobWVub3IpLCBjb2xsYXBzZSA9ICJcbiIpKQ0KYGBgDQoNCkNvbW8gZXUgbsOjbyBhY2hvIHJhem/DoXZlbCBmYXplciB1bWEgbcOpZGlhIChwb3JxdWUgZXN0YW1vcyBhdHJpYnVpbmRvIG8gbWVzbW8gcGVzbyBhIHZhcmnDoXZlaXMgcXVlIHBvZGVtIGltcGFjdGFyIGVtIGRpZmVyZW50ZXMgbsOtdmVpcyBuYSB2aW9sw6puY2lhIGRvIGVzdGFkbyksIGVudMOjbyBzZXLDoSBmZWl0byB1bWEgw6Fydm9yZSBkZSBkZWNpc8OjbyBwYXJhIHNhYmVyIHF1YWlzIGFzIHZhcmnDoXZlaXMgcXVlIG1haXMgaW1wYWN0YXJhbSBubyBuw612ZWwgZGUgdmlvbMOqbmNpYS4NCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9DQppbnN0YWxsLnBhY2thZ2VzKCJycGFydCIpDQppbnN0YWxsLnBhY2thZ2VzKCJycGFydC5wbG90IikNCmxpYnJhcnkocnBhcnQpDQpsaWJyYXJ5KHJwYXJ0LnBsb3QpDQpgYGANCg0KDQpgYGB7cn0NCiMgZGl2aXNhbyBlbSB0cmVpbm8gZSB0ZXN0ZQ0KDQpzZXQuc2VlZCgzMjEpDQoNCmluZGljZV90cmVpbm8gPC0gc2FtcGxlKDE6bnJvdyhkYWRvcyksIHNpemUgPSAwLjcgKiBucm93KGRhZG9zKSkgIyA3MCUgZG8gYmQgw6kgcGFyYSB0cmVpbm8NCg0KYmRfdHJlaW5vIDwtIGRhZG9zW2luZGljZV90cmVpbm8sIF0NCmJkX3Rlc3RlICA8LSBkYWRvc1staW5kaWNlX3RyZWlubywgXQ0KDQojIGFydm9yZSBkZSBkZWNpc2FvDQoNCmFydm9yZV9jYXJ0X2NvbXBsZXRhIDwtIHJwYXJ0KA0KICBmb3JtdWxhID0gdmlvbGVuY2lhIH4gLiwgICAgICAgIA0KICBkYXRhID0gYmRfdHJlaW5vLCAgICAgICAgICAgICAgICAgICANCiAgbWV0aG9kID0gImFub3ZhIiAjIHJlZ3Jlc3Nhbw0KKQ0KDQojIFBsb3RhbmRvDQpycGFydC5wbG90KGFydm9yZV9jYXJ0X2NvbXBsZXRhLA0KICAgICAgICAgICB0eXBlID0gMCwNCiAgICAgICAgICAgZXh0cmEgPSAxMDEsDQogICAgICAgICAgIGZhbGxlbi5sZWF2ZXMgPSBUUlVFKQ0KDQojIHZhcmlhdmVpcyBtYWlzIGltcG9ydGFudGVzDQppbXBvcnRhbmNpYSA8LSBhcnZvcmVfY2FydF9jb21wbGV0YSR2YXJpYWJsZS5pbXBvcnRhbmNlOyBpbXBvcnRhbmNpYQ0KYGBgDQoNCg0KQXMgZHVhcyB2YXJpw6F2ZWlzIG1haXMgaW1wb3J0YW50ZXMgZm9yYW0gYEFzc2F1bHRgIGUgYE11cmRlcmAuIFNlcsOjbyBjb25zaWRlcmFkYXMgdG9kYXMgYXMgdmFyacOhdmVpcyBuYSBjcmlhw6fDo28gZGEgdmFyacOhdmVsIGB2aW9sZW5jaWFgLCBhdHJpYnVpbmRvIGNvbW8gcGVzbyBhIGNvbnRyaWJ1acOnw6NvIGRlbGFzIG5hIMOhcnZvcmUuDQoNCmBgYHtyfQ0KaW1wb3J0YW5jaWEgPC0gaW1wb3J0YW5jaWEvc3VtKGltcG9ydGFuY2lhKQ0KDQp2aW9sZW5jaWEgPC0gDQogIHpfYXNzYXVsdCppbXBvcnRhbmNpYVsxXSArDQogIHpfbXVyZGVyKmltcG9ydGFuY2lhWzJdICsNCiAgel9yYXBlKmltcG9ydGFuY2lhWzNdICsNCiAgel91cmJhbnBvcCppbXBvcnRhbmNpYVs0XSAJDQoNCmRhZG9zJHZpb2xlbmNpYSA8LSB2aW9sZW5jaWENCg0Ka25pdHI6OmthYmxlKGhlYWQoZGFkb3MsIDEwKSkgfD4gDQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIikgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQ0KYGBgDQoNCkVzc2Egbm92YSB2YXJpw6F2ZWwgYHZpb2xlbmNpYWAgcmVzdWx0YSBub3Mgc2VndWludGVzIHJhbmtpbmdzLg0KYGBge3J9DQptZW5vciA8LSBoZWFkKGFycmFuZ2UoZGFkb3MsIHZpb2xlbmNpYSksIDUpDQptYWlvciA8LSBoZWFkKGFycmFuZ2UoZGFkb3MsIGRlc2ModmlvbGVuY2lhKSksIDUpDQoNCmNhdCgiNSBlc3RhZG9zIG1haXMgdmlvbGVudG9zOlxuIiwNCiAgICBwYXN0ZShyb3duYW1lcyhtYWlvciksIGNvbGxhcHNlID0gIlxuIikpDQoNCg0KY2F0KCI1IGVzdGFkb3MgbWVub3MgdmlvbGVudG9zOlxuIiwNCiAgICBwYXN0ZShyb3duYW1lcyhtZW5vciksIGNvbGxhcHNlID0gIlxuIikpDQpgYGANCg0KDQojIEFuw6FsaXNlIGRlIENsdXN0ZXIgey50YWJzZXQgLnRhYnNldC1mYWRlfQ0KDQpBZ29yYSB2YW1vcyBmYXplciB1bWEgYnJldmUgYW7DoWxpc2UgZGUgY2x1c3RlciBwYXJhIHZlcmlmaWNhciBxdWFpcyBvcyBlc3RhZG9zIG1haXMgc2VtZWxoYW50ZXMuIFByaW1laXJhbWVudGUgY2FsY3VsYW1vcyBhIG1hdHJpeiBkZSBkaXN0w6JuY2lhcyBldWNsaWRpYW5hcy4NCmBgYHtyfQ0KZGFkb3NfbnVtIDwtIGFzLm1hdHJpeChkYWRvcykNCkRfRSA8LSBkaXN0KGRhZG9zX251bSwgbWV0aG9kID0gImV1Y2xpZGlhbiIpDQpgYGANCg0KIyMgTyB2aXppbmhvIG1haXMgcHLDs3hpbW8gey51bmxpc3RlZCAudW5udW1iZXJlZH0NCg0KVmFtb3MgaW5pY2lhciBjb20gbyBtw6l0b2RvIGRvIHZpemluaG8gbWFpcyBwcsOzeGltby4NCmBgYHtyIGNvbGxhcHNlPVRSVUV9DQojIE8gdml6aW5obyBtYWlzIHByb3hpbW8NCm0gPC0gaGNsdXN0KERfRSwgbWV0aG9kID0gInNpbmdsZSIpDQptJGhlaWdodA0KcGxvdChtLCBjZXggPSAwLjcsIGhhbmcgPSAtMSwNCiAgICAgbWFpbiA9ICJEZW5kb2dyYW1hIC0gTyB2aXppbmhvIG1haXMgcHLDs3hpbW8iLA0KICAgICB4bGFiID0gIkVzdGFkb3MiLCB5bGFiID0gIiIpDQpgYGANCg0KIyMgTyB2aXppbmhvIG1haXMgZGlzdGFudGUgey51bmxpc3RlZCAudW5udW1iZXJlZH0NCg0KQWdvcmEgdmFtb3MgcGFyYSBvIG3DqXRvZG8gZG8gdml6aW5obyBtYWlzIGRpc3RhbnRlLg0KYGBge3IgY29sbGFwc2U9VFJVRX0NCm0gPC0gaGNsdXN0KERfRSwgbWV0aG9kID0gImNvbXBsZXRlIikNCm0kaGVpZ2h0DQpwbG90KG0sIGNleCA9IDAuNywgaGFuZyA9IC0xLA0KICAgICBtYWluID0gIkRlbmRvZ3JhbWEgLSBPIHZpemluaG8gbWFpcyBkaXN0YW50ZSIsDQogICAgIHhsYWIgPSAiRXN0YWRvcyIsIHlsYWIgPSAiIikNCmBgYA0KDQojIyBDZW50cm9pZGUgey51bmxpc3RlZCAudW5udW1iZXJlZH0NCg0KQWdvcmEgdXRpbGl6YW5kbyBvIG3DqXRvZG8gZG8gY2VudHJvaWRlLg0KYGBge3IgY29sbGFwc2U9VFJVRX0NCm0gPC0gaGNsdXN0KERfRSwgbWV0aG9kID0gImNlbnRyb2lkIikNCm0kaGVpZ2h0DQpwbG90KG0sIGNleCA9IDAuNywgaGFuZyA9IC0xLA0KICAgICBtYWluID0gIkRlbmRvZ3JhbWEgLSBDZW50cm9pZGUiLA0KICAgICB4bGFiID0gIkVzdGFkb3MiLCB5bGFiID0gIiIpDQpgYGANCg0KIyMgTGlnYcOnw6NvIG3DqWRpYSB7LnVubGlzdGVkIC51bm51bWJlcmVkfQ0KDQpFLCBwYXJhIGZpbmFsaXphciBvcyBtw6l0b2RvIGRlIGNsdXN0ZXJpbmcgaGllcsOhcnF1aWNvIHZpc3RvcyBlbSBzYWxhLCB2YW1vcyBmYXplciBvIG3DqXRvZG8gZGEgbGlnYcOnw6NvIG3DqWRpYS4NCmBgYHtyIGNvbGxhcHNlPVRSVUV9DQptIDwtIGhjbHVzdChEX0UsIG1ldGhvZCA9ICJhdmVyYWdlIikNCm0kaGVpZ2h0DQpwbG90KG0sIGNleCA9IDAuNywgaGFuZyA9IC0xLA0KICAgICBtYWluID0gIkRlbmRvZ3JhbWEgLSBMaWdhw6fDo28gTcOpZGlhIiwNCiAgICAgeGxhYiA9ICJFc3RhZG9zIiwgeWxhYiA9ICIiKQ0KYGBgDQoNCiMjIEstbWVhbnMgey51bmxpc3RlZCAudW5udW1iZXJlZH0NCg0KUGFyYSBhIGFuw6FsaXNlIGRlIGNsdXN0ZXIsIHRhbWLDqW0gcG9kZW1vcyB1dGlsaXphciBvIG3DqXRvZG8gZG8gay1tZWFucy4gUG9yw6ltLCBjb21vIGEgcGxvdGFnZW0gbmVjZXNzaXRhIGRlIGNvbXBvbmVudGVzIHByaW5jaXBhaXMsIGVudMOjbyBuw6NvIHZhbW9zIGZhesOqLWxhLiBPIG7Dum1lcm8gZGUgZ3J1cG9zIGlndWFsIGEgMiB2ZW0gZGEgaWRlaWEgZGUgY3JpYXIgbyBjbHVzdGVyIGRlIGVzdGFkb3MgcGVyaWdvc29zIGUgbyBjbHVzdGVyIGRlIGVzdGFkb3Mgc2VndXJvcy4gTyBncnVwbyBxdWUgY29udGVyIEZsb3JpZGEgc2Vyw6EgY29uc2lkZXJhZG8gcGVyaWdvc28gKHBvciBjb250YSBkb3MgcmFua2luZ3MpIGUgbyBncnVwbyBxdWUgY29udGVyIE5vcnRoIERha290YSBzZXLDoSBjb25zaWRlcmFkbyBzZWd1cm8uDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCBpbmNsdWRlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQppbnN0YWxsLnBhY2thZ2VzKCJmYWN0b2V4dHJhIikNCnJlcXVpcmUoZ2dwbG90MikNCnJlcXVpcmUoZmFjdG9leHRyYSkNCmBgYA0KDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoNTQ4MjU0KQ0Ka20gPC0ga21lYW5zKGRhZG9zX251bSwgY2VudGVycyA9IDIpDQoNCiMgQ2x1c3RlciAxDQpjYXQoIkNsdXN0ZXIgMTpcbiIsIHBhc3RlKHJvd25hbWVzKGRhZG9zX251bSlba20kY2x1c3RlciA9PSAxXSwgY29sbGFwc2UgPSAiXG4iKSwgIlxuXG4iKQ0KDQojIENsdXN0ZXIgMg0KY2F0KCJDbHVzdGVyIDI6XG4iLCBwYXN0ZShyb3duYW1lcyhkYWRvc19udW0pW2ttJGNsdXN0ZXIgPT0gMl0sIGNvbGxhcHNlID0gIlxuIiksICJcblxuIikNCmBgYA0KDQojIENvbmNsdXPDo28NCg0KRGUgZm9ybWEgcmVzcGVjdGl2YSwgb3MgZXN0YWRvcyBtYWlzIHBlcmlnb3NvcyBwYXJhIHNlIG1vcmFyIMOpIGBGbG9yaWRhYCBlIGBOZXZhZGFgLCBlbnF1YW50byBvcyBtYWlzIHNlZ3Vyb3Mgc8OjbyBgVmVybW9udGAgZSBgTm9ydGggRGFrb3RhYC4=