Mapas em R
Agora a meta é gerar um mapa simples em R. Para tanto, primeiro define-se a malha municipal desejada. Para o presente caso, utilizam-se as malhas digitais do pacote geobr
.
Os pacotes (previamente instalados) são aqui carregados:
library(geobr)
## Warning: package 'geobr' was built under R version 3.6.2
## Loading required namespace: sf
library(ggplot2)
library(sf)
## Linking to GEOS 3.6.1, GDAL 2.2.3, PROJ 4.9.3
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(rio)
library(readr)
O pacote geobr
tem as rotinas para o download dos mapas com divisões territoriais variadas. Faremos para os municípios de Mato Grosso do Sul (MS), malha com a estrutura municipal de 2018, contendo 79 municípios. É importante o leitor ter essa estrutura em mente, pois ao longo dos anos, municípios são criados a partir de desmembramentos de outros, não necessariamente respeitando limites de distritos ou outros atributos previamente definidos.
Este rápido exemplo faz uso das funções do pacote geobr
e assim, precisamos saber quais os códigos para cada estado. A função download_metadata()
permite encontrar os códigos para estado e ano e a desagregação desejada (município, estado etc).
library(geobr)
options(timeout= 4000000)
metadata<-download_metadata() # para ver codigos
head(metadata)
Posso verificar que para MS, especificarei 50 e para o ano de 2018. Agora posso baixar os dados (shapes) para os municípios de Mato Grosso do Sul fazendo uso da função read_municipality(code_muni=50, year=2018)
em:
all_mun_ms <- read_municipality(code_muni=50, year=2018)
O usuário que desejar baixar todos os municípios observará alguma demora no download dos dados, devido ao número de municípios e restrito à velocidade de sua internet.
A visualização da saída do objeto all_mun_ms
indica as variáveis armazenadas. É possível verificar que esse objeto é da classe sf
e data.frame
. Um objeto sf
contém uma coleção de recursos incluindo atributos e geometrias que contemplam os aspectos espaciais para desenhar o mapa.
class(all_mun_ms)
[1] "sf" "data.frame"
O dataset pode então ser observado. O dataset contém o código do município, o nome do município, o código do estado, a sigla do estado e aspectos geográficos como latitude, longitude dos vários segmentos que permitirão construir o mapa.
Agora vou construir uma variável para ser plotada no mapa. Preciso ter os meus dados em uma planilha em que uma das colunas será o código do município da mesma forma que consta em code_muni
no objeto all_mun_ms
. Recomendo fazer a associação entre os dados por meio do código, menos sujeito a erros de digitação que para os nomes dos municípios. Para este exemplo, baixei os dados de http://atlasbrasil.org.br/2013/pt/download/, ou mais precisamente em http://atlasbrasil.org.br/2013/data/rawData/atlas2013_dadosbrutos_pt.xlsx, o site oficial do PNUD para o Índice de Desenvolvimento Humano Municipal do Brasil, para 2013, que nesse caso se refere aos dados do censo demográfico 2010. No caso, o arquivo Excel veio com dados de todo o Brasil e para os anos 1991, 2000 e 2010, mas fiz uma extração dos dados para apenas os municípios de MS e 2010. Observar que nesse caso tenho uma estrutura municipal de 78 municípios invés dos 79 de 2018.
# Executei uma vez e gerei dput para executar mais rapidamente conforme próximo chunk
library(readxl)
url <- "http://atlasbrasil.org.br/2013/data/rawData/atlas2013_dadosbrutos_pt.xlsx"
destfile <- "atlas2013_dadosbrutos_pt.xlsx"
#options(timeout= 4000000) # as vezes o site demora conforme sua internet
curl::curl_download(url, destfile)
atlas2013_dadosbrutos_pt <- read_excel(destfile,
sheet = "MUN 91-00-10")
dados_ms <- subset(atlas2013_dadosbrutos_pt, UF == '50' & ANO == '2010',
select=c(Codmun7,IDHM,IDHM_E,IDHM_L,IDHM_R))
print(dados_ms)
Segue o chunk para carregar dados de dados_ms
sem precisar acessar o arquivo mestre do chunk anterior. Gera os mesmos resultados acima, transformados a partir do dput()
de dados_ms
. Esta alternativa acelera a execução do script.
dados_ms<-structure(list(Codmun7 = c(5000203, 5000252, 5000609, 5000708,
5000807, 5000856, 5000906, 5001003, 5001102, 5001243, 5001508,
5001904, 5002001, 5002100, 5002159, 5002209, 5002308, 5002407,
5002605, 5002704, 5002803, 5002902, 5002951, 5003108, 5003157,
5003207, 5003256, 5003306, 5003454, 5003488, 5003504, 5003702,
5003751, 5003801, 5003900, 5004007, 5004106, 5004304, 5004403,
5004502, 5004601, 5004700, 5004809, 5004908, 5005004, 5005103,
5005152, 5005202, 5005251, 5005400, 5005608, 5005681, 5005707,
5005806, 5006002, 5006200, 5006259, 5006309, 5006358, 5006408,
5006606, 5006903, 5007109, 5007208, 5007307, 5007406, 5007505,
5007554, 5007695, 5007703, 5007802, 5007901, 5007935, 5007950,
5007976, 5008008, 5008305, 5008404), IDHM = c(0.67, 0.711, 0.673,
0.663, 0.67, 0.697, 0.643, 0.697, 0.688, 0.633, 0.681, 0.71,
0.684, 0.698, 0.666, 0.67, 0.701, 0.692, 0.703, 0.784, 0.647,
0.727, 0.754, 0.671, 0.589, 0.7, 0.706, 0.703, 0.694, 0.639,
0.699, 0.747, 0.684, 0.714, 0.66, 0.721, 0.675, 0.662, 0.681,
0.654, 0.62, 0.72, 0.526, 0.664, 0.712, 0.708, 0.623, 0.704,
0.672, 0.736, 0.632, 0.686, 0.7, 0.639, 0.694, 0.721, 0.649,
0.721, 0.588, 0.671, 0.701, 0.666, 0.664, 0.715, 0.709, 0.673,
0.651, 0.642, 0.729, 0.614, 0.682, 0.686, 0.681, 0.593, 0.651,
0.658, 0.744, 0.711), IDHM_E = c(0.518, 0.572, 0.546, 0.557,
0.538, 0.582, 0.526, 0.588, 0.562, 0.507, 0.537, 0.606, 0.559,
0.585, 0.573, 0.508, 0.57, 0.592, 0.596, 0.724, 0.522, 0.627,
0.665, 0.531, 0.417, 0.586, 0.606, 0.579, 0.595, 0.528, 0.597,
0.657, 0.577, 0.621, 0.511, 0.648, 0.549, 0.53, 0.531, 0.523,
0.479, 0.615, 0.337, 0.53, 0.595, 0.579, 0.485, 0.618, 0.545,
0.613, 0.507, 0.565, 0.597, 0.483, 0.554, 0.616, 0.523, 0.627,
0.444, 0.562, 0.598, 0.526, 0.519, 0.59, 0.585, 0.521, 0.491,
0.505, 0.608, 0.45, 0.576, 0.561, 0.557, 0.434, 0.545, 0.521,
0.645, 0.626), IDHM_L = c(0.823, 0.858, 0.818, 0.789, 0.826,
0.839, 0.799, 0.804, 0.84, 0.798, 0.848, 0.847, 0.814, 0.83,
0.776, 0.831, 0.837, 0.828, 0.817, 0.844, 0.826, 0.811, 0.85,
0.83, 0.806, 0.834, 0.811, 0.836, 0.81, 0.773, 0.809, 0.843,
0.824, 0.815, 0.83, 0.822, 0.826, 0.817, 0.846, 0.809, 0.772,
0.85, 0.791, 0.827, 0.845, 0.857, 0.77, 0.822, 0.822, 0.873,
0.782, 0.808, 0.803, 0.822, 0.809, 0.85, 0.798, 0.823, 0.811,
0.801, 0.812, 0.83, 0.83, 0.861, 0.869, 0.852, 0.83, 0.8, 0.85,
0.778, 0.825, 0.829, 0.803, 0.782, 0.769, 0.839, 0.849, 0.835
), IDHM_R = c(0.705, 0.733, 0.683, 0.663, 0.676, 0.692, 0.633,
0.717, 0.69, 0.628, 0.694, 0.698, 0.702, 0.699, 0.665, 0.714,
0.721, 0.676, 0.715, 0.79, 0.628, 0.756, 0.758, 0.684, 0.607,
0.701, 0.717, 0.719, 0.693, 0.64, 0.706, 0.753, 0.674, 0.719,
0.677, 0.705, 0.677, 0.671, 0.702, 0.66, 0.645, 0.715, 0.547,
0.668, 0.718, 0.716, 0.646, 0.687, 0.676, 0.744, 0.638, 0.707,
0.715, 0.658, 0.746, 0.716, 0.656, 0.727, 0.566, 0.672, 0.708,
0.677, 0.681, 0.72, 0.702, 0.686, 0.676, 0.655, 0.751, 0.66,
0.668, 0.694, 0.706, 0.615, 0.657, 0.651, 0.752, 0.689)), row.names = c(NA,
-78L), class = c("tbl_df", "tbl", "data.frame"))
Segue o chunk para opção de download manual e armazenamento em seu diretório.
# trazendo os dados do Brasil todo apenas para municipios
library(readxl)
atlas2013_dadosbrutos_pt <- read_excel("atlas2013_dadosbrutos_pt.xlsx",
sheet = "MUN 91-00-10")
# reduzir linhas para 2010 e MS
# usando a funcao subset para pegar as colunas de IDH até a última ()
dados_ms <- subset(atlas2013_dadosbrutos_pt, UF == '50' & ANO == '2010',
select=c(Codmun7,IDHM,IDHM_E,IDHM_L,IDHM_R))
print(dados_ms)
all_mun_ms <- read_municipality(code_muni=50, year=2010)
## Using data from year 2010
Juntarei os datasets pela condição de que o code_muni
do objeto all_mun_ms
é igual ao Codmun7
do objeto dados_ms
.
dataset_final = left_join(all_mun_ms, dados_ms, by=c("code_muni"="Codmun7"))
max(dataset_final$IDHM) # 0.784
## [1] 0.784
min(dataset_final$IDHM) # 0.526
## [1] 0.526
ggplot() +
geom_sf(data=dataset_final, aes(fill=IDHM), color= NA, size=.15)+
labs(title="IDHM 2013 (ano base 2010) dos Municipíos de MS",
caption='Fonte: Elaboração própria', size=8)+
scale_fill_distiller(palette = "Greens", limits=c(0.5, 0.8),
name="Code_muni")+
theme_minimal()

Sendo um mapa feito em ggplot2
pelos comandos ggplot() + geom_sf(data=dataset_final, aes(fill=IDHM), color= NA, size=.15)
, o padrão é um mapa na escala azul. Ou seja, fazendo agora um mapa para o IDHM_E (IDHM Educação), recomendo o usuário fazer o passo a passo de modo a ver exatamente o que o código realiza:
#dataset_final = left_join(all_mun_ms, dados_ms, by=c("code_muni"="Codmun7"))
max(dataset_final$IDHM_E) # 0.724
## [1] 0.724
min(dataset_final$IDHM_E) # 0.337
## [1] 0.337
ggplot() +
geom_sf(data=dataset_final, aes(fill=IDHM_E), color= NA, size=.15)

Veja que o mapa anterior saiu em azul, sem rótulos. Observe que nesse caso e no próximo, não fiz nenhuma restrição à legenda.
O próximo sai com rótulos do título e nota ao final do mapa.
ggplot() +
geom_sf(data=dataset_final, aes(fill=IDHM_E), color= NA, size=.15)+
labs(title="IDHM Educação 2013 (ano base 2010) dos Municipíos de MS",
caption='Fonte: Elaboração própria', size=8)

Para o próximo mapa, coloco a paleta de cores em vermelho e os limites para as classes, agora de 0 a 1.
ggplot() +
geom_sf(data=dataset_final, aes(fill=IDHM_E), color= NA, size=.15)+
labs(title="IDHM Educação 2013 (ano base 2010) dos Municipíos de MS",
caption='Fonte: Elaboração própria', size=8)+
scale_fill_distiller(palette = "Reds", limits=c(0.0, 1.0),
name="Code_muni")

No exemplo abaixo faço um caso particular em que um município, o de máximo IDHM_E ficou excluído por uma restrição ao delimitar o máximo da palheta em 0.7 (o valor seria de Campo Grande, 0.724, maior que 0.7). Portanto, o município ficou em preto.
ggplot() +
geom_sf(data=dataset_final, aes(fill=IDHM_E), color= NA, size=.15)+
labs(title="IDHM Educação 2013 (ano base 2010) dos Municipíos de MS",
caption='Fonte: Elaboração própria', size=8)+
scale_fill_distiller(limits=c(0.3, 0.7))+
theme_minimal()

Outras palhetas de cores pode ser visualizada em http://www.sthda.com/english/wiki/ggplot2-colors-how-to-change-colors-automatically-and-manually.
# dataset_final = left_join(all_mun_ms, dados_ms, by=c("code_muni"="Codmun7"))
# max(dataset_final$IDHM) # 0.784
# min(dataset_final$IDHM) # 0.526
ggplot() +
geom_sf(data=dataset_final, aes(fill=IDHM), color= NA, size=.15)+
labs(title="IDHM 2013 (ano base 2010) dos Municipíos de MS",
caption='Fonte: Elaboração própria', size=8)+
scale_fill_distiller(palette = "RdGy", limits=c(0.5, 0.8),
name="Code_muni")+
theme_minimal()

LS0tDQp0aXRsZTogIk1hcGFzIGVtIFIgY29tIGBnZW9icmAiDQphdXRob3I6ICdBZHJpYW5vIE1hcmNvcyBSb2RyaWd1ZXMgRmlndWVpcmVkbywgKmUtbWFpbDogYWRyaWFuby5maWd1ZWlyZWRvQHVmbXMuYnIqJw0KZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJWQgJUIgJVknKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQogIHBkZl9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KYWJzdHJhY3Q6ICJJbiB0aGlzIGV4ZXJjaXNlIEkgdXNlIFIgYW5kIGdncGxvdDIgYW5kIGdlb2JyIHBhY2thZ2VzIHRvIG1hcCB0aGUgSHVtYW4gRGV2ZWxvcG1lbnQgSW5kaWNlcyBmb3IgbXVuaWNpcGFsaXRpZXMgaW4gdGhlIEJyYXppbGlhbiBTdGF0ZSBvZiBNYXRvIEdyb3NzbyBkbyBTdWwuIEl0J3Mgd3JpdHRlbiBpbiBwb3J0dWd1ZXNlIGFuZCwgc28sIEkgZW5jb3VyYWdlIG5vbi1wb3J0dWd1ZXNlIHNwZWFrZXJzIHRvIG9wZW4gdGhlIGh0bWwgcG9zdCBpbiBHb29nbGUgQ2hyb21lIG9yIHNpbWlsYXIgd2l0aCB0aGUgdHJhbnNsYXRlIG9wdGlvbi4iDQotLS0NCg0KTGljZW7Dp2Egey0jTGljZW7Dp2F9DQo9PT09PT09PT09PT09PT09PT09DQoNClRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciB0aGUgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIDQuMCBJbnRlcm5hdGlvbmFsIExpY2Vuc2UuIFRvIHZpZXcgYSBjb3B5IG9mIHRoaXMgbGljZW5zZSwgdmlzaXQgPGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzQuMC8+IG9yIHNlbmQgYSBsZXR0ZXIgdG8gQ3JlYXRpdmUgQ29tbW9ucywgUE8gQm94IDE4NjYsIE1vdW50YWluIFZpZXcsIENBIDk0MDQyLCBVU0EuDQoNCiFbTGljZW5zZTogQ0MgQlktU0EgNC4wXShjY19ieV9zYS5wbmcpeyB3aWR0aD0yNSUgfQ0KDQpBcyBpZGVpYXMgYXF1aSBleHByZXNzYXMgc8OjbyBkZSByZXNwb25zYWJpbGlkYWRlIGV4Y2x1c2l2YSBkbyBhdXRvciwgZSBuw6NvIHJlcHJlc2VudGFtIGFzIG9waW5pw7VlcyBkYSBpbnN0aXR1acOnw6NvIGEgcXVlIHBlcnRlbmNlLg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQpDaXRhw6fDo28gey0jQ2l0YcOnw6NvfQ0KPT09PT09PT09PT09PT09PT09PQ0KDQpTdWdlc3TDo28gcGFyYSBjaXRhw6fDo286IA0KRklHVUVJUkVETywgQWRyaWFubyBNYXJjb3MgUm9kcmlndWVzLiBNYXBhcyBlbSBSIGNvbSBgZ2VvYnJgLiBDYW1wbyBHcmFuZGUtTVMsQnJhc2lsOiBSU3R1ZGlvL1JwdWJzLCAyMDIwLiBEaXNwb27DrXZlbCBlbSA8aHR0cHM6Ly9hZHJpYW5vZmlndWVpcmVkby5uZXRsaWZ5LmNvbS9wb3N0L21hcGFzLWVtLXItY29tLWdlb2JyLz4uIA0KDQoNCkludHJvZHXDp8OjbyANCj09PT09PT09PT09PT09PT09PQ0KDQpQYXJhIHJlYWxpemFyIHNldSBtYXBhIGVtIFIsIGluaWNpYWxtZW50ZSBvIGxlaXRvciBkZXZlIGJhaXhhciBvcyBwcm9ncmFtYXMgZSBwYWNvdGVzIG5lY2Vzc8OhcmlvcyBhbyBwcm9qZXRvLiBOZXN0ZSBjYXNvLCBzdWdlcmUtc2UgcXVlIHV0aWxpemUgbyBSU3R1ZGlvIGUgbyBSIGF0dWFsaXphZG9zLCBhIHBhcnRpciBkZTogaHR0cDovL2NyYW4uci1wcm9qZWN0Lm9yZy9iaW4vd2luZG93cy9iYXNlLyBlIGh0dHBzOi8vd3d3LnJzdHVkaW8uY29tL3Byb2R1Y3RzL3JzdHVkaW8vZG93bmxvYWQzLy4gUXVhbmRvIGVzdGEgcmV2aXPDo28gZm9pIGZlaXRhLCBhIHZlcnPDo28gZG8gUlN0dWRpbyBlcmEgYSAqUlN0dWRpbyBEZXNrdG9wIDEuMi41MDMzKiBlIGRvICpSLTMuNi4xIGZvciBXaW5kb3dzICgzMi82NCBiaXQpKi4gDQoNClByaW1laXJvIGluc3RhbGUgbyBSIGUgcG9zdGVyaW9ybWVudGUgbyBSU3R1ZGlvLCBkZSBtb2RvIHF1ZSBvIHNlZ3VuZG8gcmVjb25oZcOnYSBhdXRvbWF0aWNhbWVudGUgbyBwcmltZWlyby4gU2UgdHVkbyBlc3RpdmVyIHBlcmZlaXRvLCBhIHRlbGEgaW5pY2lhbCBkbyBSU3R1ZGlvIG1vc3RyYXLDoSBjb3JyZXRhbWVudGUgYSB2ZXJzw6NvIGRvIFIuDQoNCg0KTWFwYXMgZW0gUg0KPT09PT09PT09PT09PT09PT09DQoNCkFnb3JhIGEgbWV0YSDDqSBnZXJhciB1bSBtYXBhIHNpbXBsZXMgZW0gUi4gUGFyYSB0YW50bywgcHJpbWVpcm8gZGVmaW5lLXNlIGEgbWFsaGEgbXVuaWNpcGFsIGRlc2VqYWRhLiBQYXJhIG8gcHJlc2VudGUgY2FzbywgdXRpbGl6YW0tc2UgYXMgbWFsaGFzIGRpZ2l0YWlzIGRvIHBhY290ZSBgZ2VvYnJgLiAgICAgDQoNCk9zIHBhY290ZXMgKHByZXZpYW1lbnRlIGluc3RhbGFkb3MpIHPDo28gYXF1aSBjYXJyZWdhZG9zOg0KDQpgYGB7ciBlY2hvID0gVCwgcmVzdWx0cyA9ICdoaWRlJywgd2FybmluZ3M9RkFMU0V9DQpsaWJyYXJ5KGdlb2JyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShzZikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHJpbykNCmxpYnJhcnkocmVhZHIpDQpgYGANCg0KTyBwYWNvdGUgYGdlb2JyYCB0ZW0gYXMgcm90aW5hcyBwYXJhIG8gZG93bmxvYWQgZG9zIG1hcGFzIGNvbSBkaXZpc8O1ZXMgdGVycml0b3JpYWlzIHZhcmlhZGFzLiBGYXJlbW9zIHBhcmEgb3MgbXVuaWPDrXBpb3MgZGUgTWF0byBHcm9zc28gZG8gU3VsIChNUyksIG1hbGhhIGNvbSBhIGVzdHJ1dHVyYSBtdW5pY2lwYWwgZGUgMjAxOCwgY29udGVuZG8gNzkgbXVuaWPDrXBpb3MuIMOJIGltcG9ydGFudGUgbyBsZWl0b3IgdGVyIGVzc2EgZXN0cnV0dXJhIGVtIG1lbnRlLCBwb2lzIGFvIGxvbmdvIGRvcyBhbm9zLCBtdW5pY8OtcGlvcyBzw6NvIGNyaWFkb3MgYSBwYXJ0aXIgZGUgZGVzbWVtYnJhbWVudG9zIGRlIG91dHJvcywgbsOjbyBuZWNlc3NhcmlhbWVudGUgcmVzcGVpdGFuZG8gbGltaXRlcyBkZSBkaXN0cml0b3Mgb3Ugb3V0cm9zIGF0cmlidXRvcyBwcmV2aWFtZW50ZSBkZWZpbmlkb3MuICAgICANCiAgICANCg0KRXN0ZSByw6FwaWRvIGV4ZW1wbG8gZmF6IHVzbyBkYXMgZnVuw6fDtWVzIGRvIHBhY290ZSBgZ2VvYnJgIGUgYXNzaW0sIHByZWNpc2Ftb3Mgc2FiZXIgcXVhaXMgb3MgY8OzZGlnb3MgcGFyYSBjYWRhIGVzdGFkby4gQSBmdW7Dp8OjbyBgZG93bmxvYWRfbWV0YWRhdGEoKWAgcGVybWl0ZSBlbmNvbnRyYXIgb3MgY8OzZGlnb3MgcGFyYSBlc3RhZG8gZSBhbm8gZSBhIGRlc2FncmVnYcOnw6NvIGRlc2VqYWRhIChtdW5pY8OtcGlvLCBlc3RhZG8gZXRjKS4NCg0KYGBge3IgZWNobyA9IFQsIHJlc3VsdHMgPSAnaGlkZSd9DQpsaWJyYXJ5KGdlb2JyKQ0Kb3B0aW9ucyh0aW1lb3V0PSA0MDAwMDAwKQ0KbWV0YWRhdGE8LWRvd25sb2FkX21ldGFkYXRhKCkgIyBwYXJhIHZlciBjb2RpZ29zDQpoZWFkKG1ldGFkYXRhKQ0KDQpgYGANCg0KUG9zc28gdmVyaWZpY2FyIHF1ZSBwYXJhIE1TLCBlc3BlY2lmaWNhcmVpIDUwIGUgcGFyYSBvIGFubyBkZSAyMDE4LiBBZ29yYSBwb3NzbyBiYWl4YXIgb3MgZGFkb3MgKHNoYXBlcykgcGFyYSBvcyBtdW5pY8OtcGlvcyBkZSBNYXRvIEdyb3NzbyBkbyBTdWwgZmF6ZW5kbyB1c28gZGEgZnVuw6fDo28gYHJlYWRfbXVuaWNpcGFsaXR5KGNvZGVfbXVuaT01MCwgeWVhcj0yMDE4KWAgZW06DQoNCmBgYA0KYWxsX211bl9tcyA8LSByZWFkX211bmljaXBhbGl0eShjb2RlX211bmk9NTAsIHllYXI9MjAxOCkNCmBgYA0KDQpPIHVzdcOhcmlvIHF1ZSBkZXNlamFyIGJhaXhhciB0b2RvcyBvcyBtdW5pY8OtcGlvcyBvYnNlcnZhcsOhIGFsZ3VtYSBkZW1vcmEgbm8gZG93bmxvYWQgZG9zIGRhZG9zLCBkZXZpZG8gYW8gbsO6bWVybyBkZSBtdW5pY8OtcGlvcyBlIHJlc3RyaXRvIMOgIHZlbG9jaWRhZGUgZGUgc3VhIGludGVybmV0LiAgICANCkEgdmlzdWFsaXphw6fDo28gZGEgc2HDrWRhIGRvIG9iamV0byBgYWxsX211bl9tc2AgaW5kaWNhIGFzIHZhcmnDoXZlaXMgYXJtYXplbmFkYXMuIMOJIHBvc3PDrXZlbCB2ZXJpZmljYXIgcXVlIGVzc2Ugb2JqZXRvIMOpIGRhIGNsYXNzZSBgc2ZgIGUgYGRhdGEuZnJhbWVgLiBVbSBvYmpldG8gYHNmYCBjb250w6ltIHVtYSBjb2xlw6fDo28gZGUgcmVjdXJzb3MgaW5jbHVpbmRvIGF0cmlidXRvcyBlIGdlb21ldHJpYXMgcXVlIGNvbnRlbXBsYW0gb3MgYXNwZWN0b3MgZXNwYWNpYWlzIHBhcmEgZGVzZW5oYXIgbyBtYXBhLg0KDQpgYGANCmNsYXNzKGFsbF9tdW5fbXMpDQpbMV0gInNmIiAgICAgICAgICJkYXRhLmZyYW1lIg0KYGBgDQoNCk8gZGF0YXNldCBwb2RlIGVudMOjbyBzZXIgb2JzZXJ2YWRvLiBPIGRhdGFzZXQgY29udMOpbSBvIGPDs2RpZ28gZG8gbXVuaWPDrXBpbywgbyBub21lIGRvIG11bmljw61waW8sIG8gY8OzZGlnbyBkbyBlc3RhZG8sIGEgc2lnbGEgZG8gZXN0YWRvIGUgYXNwZWN0b3MgZ2VvZ3LDoWZpY29zIGNvbW8gbGF0aXR1ZGUsIGxvbmdpdHVkZSBkb3MgdsOhcmlvcyBzZWdtZW50b3MgcXVlIHBlcm1pdGlyw6NvIGNvbnN0cnVpciBvIG1hcGEuDQoNCiFbKkltYWdlbSBkbyBvYmpldG8gYGFsbF9tdW5fbXNgLipdKHNhaWRhX2FsbF9tdW5fbXMuUE5HKQ0KDQpBZ29yYSB2b3UgY29uc3RydWlyIHVtYSB2YXJpw6F2ZWwgcGFyYSBzZXIgcGxvdGFkYSBubyBtYXBhLiBQcmVjaXNvIHRlciBvcyBtZXVzIGRhZG9zIGVtIHVtYSBwbGFuaWxoYSBlbSBxdWUgdW1hIGRhcyBjb2x1bmFzIHNlcsOhIG8gY8OzZGlnbyBkbyBtdW5pY8OtcGlvIGRhIG1lc21hIGZvcm1hIHF1ZSBjb25zdGEgZW0gYGNvZGVfbXVuaWAgbm8gb2JqZXRvIGBhbGxfbXVuX21zYC4gUmVjb21lbmRvIGZhemVyIGEgYXNzb2NpYcOnw6NvIGVudHJlIG9zIGRhZG9zIHBvciBtZWlvIGRvIGPDs2RpZ28sIG1lbm9zIHN1amVpdG8gYSBlcnJvcyBkZSBkaWdpdGHDp8OjbyBxdWUgcGFyYSBvcyBub21lcyBkb3MgbXVuaWPDrXBpb3MuIFBhcmEgZXN0ZSBleGVtcGxvLCBiYWl4ZWkgb3MgZGFkb3MgZGUgPGh0dHA6Ly9hdGxhc2JyYXNpbC5vcmcuYnIvMjAxMy9wdC9kb3dubG9hZC8+LCBvdSBtYWlzIHByZWNpc2FtZW50ZSBlbSA8aHR0cDovL2F0bGFzYnJhc2lsLm9yZy5ici8yMDEzL2RhdGEvcmF3RGF0YS9hdGxhczIwMTNfZGFkb3NicnV0b3NfcHQueGxzeD4sIG8gc2l0ZSBvZmljaWFsIGRvIFBOVUQgcGFyYSBvIMONbmRpY2UgZGUgRGVzZW52b2x2aW1lbnRvIEh1bWFubyBNdW5pY2lwYWwgZG8gQnJhc2lsLCBwYXJhIDIwMTMsIHF1ZSBuZXNzZSBjYXNvIHNlIHJlZmVyZSBhb3MgZGFkb3MgZG8gY2Vuc28gZGVtb2dyw6FmaWNvIDIwMTAuIA0KTm8gY2FzbywgbyBhcnF1aXZvIEV4Y2VsIHZlaW8gY29tIGRhZG9zIGRlIHRvZG8gbyBCcmFzaWwgZSBwYXJhIG9zIGFub3MgMTk5MSwgMjAwMCBlIDIwMTAsIG1hcyBmaXogdW1hIGV4dHJhw6fDo28gZG9zIGRhZG9zIHBhcmEgYXBlbmFzIG9zIG11bmljw61waW9zIGRlIE1TIGUgMjAxMC4gT2JzZXJ2YXIgcXVlIG5lc3NlIGNhc28gdGVuaG8gdW1hIGVzdHJ1dHVyYSBtdW5pY2lwYWwgZGUgNzggbXVuaWPDrXBpb3MgaW52w6lzIGRvcyA3OSBkZSAyMDE4LiANCg0KYGBge3IsIGV2YWw9RkFMU0V9DQojIEV4ZWN1dGVpIHVtYSB2ZXogZSBnZXJlaSBkcHV0IHBhcmEgZXhlY3V0YXIgbWFpcyByYXBpZGFtZW50ZSBjb25mb3JtZSBwcsOzeGltbyBjaHVuaw0KbGlicmFyeShyZWFkeGwpDQp1cmwgPC0gImh0dHA6Ly9hdGxhc2JyYXNpbC5vcmcuYnIvMjAxMy9kYXRhL3Jhd0RhdGEvYXRsYXMyMDEzX2RhZG9zYnJ1dG9zX3B0Lnhsc3giDQpkZXN0ZmlsZSA8LSAiYXRsYXMyMDEzX2RhZG9zYnJ1dG9zX3B0Lnhsc3giDQojb3B0aW9ucyh0aW1lb3V0PSA0MDAwMDAwKSAjIGFzIHZlemVzIG8gc2l0ZSBkZW1vcmEgY29uZm9ybWUgc3VhIGludGVybmV0DQpjdXJsOjpjdXJsX2Rvd25sb2FkKHVybCwgZGVzdGZpbGUpDQphdGxhczIwMTNfZGFkb3NicnV0b3NfcHQgPC0gcmVhZF9leGNlbChkZXN0ZmlsZSwgDQogICAgc2hlZXQgPSAiTVVOIDkxLTAwLTEwIikNCmRhZG9zX21zIDwtIHN1YnNldChhdGxhczIwMTNfZGFkb3NicnV0b3NfcHQsIFVGID09ICc1MCcgJiBBTk8gPT0gJzIwMTAnLA0KICAgICAgICAgICAgICAgICAgIHNlbGVjdD1jKENvZG11bjcsSURITSxJREhNX0UsSURITV9MLElESE1fUikpDQpwcmludChkYWRvc19tcykNCmBgYA0KDQpTZWd1ZSBvIGNodW5rIHBhcmEgY2FycmVnYXIgZGFkb3MgZGUgYGRhZG9zX21zYCBzZW0gcHJlY2lzYXIgYWNlc3NhciBvIGFycXVpdm8gbWVzdHJlIGRvIGNodW5rIGFudGVyaW9yLiBHZXJhIG9zIG1lc21vcyByZXN1bHRhZG9zIGFjaW1hLCB0cmFuc2Zvcm1hZG9zIGEgcGFydGlyIGRvIGBkcHV0KClgIGRlIGBkYWRvc19tc2AuIEVzdGEgYWx0ZXJuYXRpdmEgYWNlbGVyYSBhIGV4ZWN1w6fDo28gZG8gc2NyaXB0LiAgICANCg0KYGBge3J9DQpkYWRvc19tczwtc3RydWN0dXJlKGxpc3QoQ29kbXVuNyA9IGMoNTAwMDIwMywgNTAwMDI1MiwgNTAwMDYwOSwgNTAwMDcwOCwgDQo1MDAwODA3LCA1MDAwODU2LCA1MDAwOTA2LCA1MDAxMDAzLCA1MDAxMTAyLCA1MDAxMjQzLCA1MDAxNTA4LCANCjUwMDE5MDQsIDUwMDIwMDEsIDUwMDIxMDAsIDUwMDIxNTksIDUwMDIyMDksIDUwMDIzMDgsIDUwMDI0MDcsIA0KNTAwMjYwNSwgNTAwMjcwNCwgNTAwMjgwMywgNTAwMjkwMiwgNTAwMjk1MSwgNTAwMzEwOCwgNTAwMzE1NywgDQo1MDAzMjA3LCA1MDAzMjU2LCA1MDAzMzA2LCA1MDAzNDU0LCA1MDAzNDg4LCA1MDAzNTA0LCA1MDAzNzAyLCANCjUwMDM3NTEsIDUwMDM4MDEsIDUwMDM5MDAsIDUwMDQwMDcsIDUwMDQxMDYsIDUwMDQzMDQsIDUwMDQ0MDMsIA0KNTAwNDUwMiwgNTAwNDYwMSwgNTAwNDcwMCwgNTAwNDgwOSwgNTAwNDkwOCwgNTAwNTAwNCwgNTAwNTEwMywgDQo1MDA1MTUyLCA1MDA1MjAyLCA1MDA1MjUxLCA1MDA1NDAwLCA1MDA1NjA4LCA1MDA1NjgxLCA1MDA1NzA3LCANCjUwMDU4MDYsIDUwMDYwMDIsIDUwMDYyMDAsIDUwMDYyNTksIDUwMDYzMDksIDUwMDYzNTgsIDUwMDY0MDgsIA0KNTAwNjYwNiwgNTAwNjkwMywgNTAwNzEwOSwgNTAwNzIwOCwgNTAwNzMwNywgNTAwNzQwNiwgNTAwNzUwNSwgDQo1MDA3NTU0LCA1MDA3Njk1LCA1MDA3NzAzLCA1MDA3ODAyLCA1MDA3OTAxLCA1MDA3OTM1LCA1MDA3OTUwLCANCjUwMDc5NzYsIDUwMDgwMDgsIDUwMDgzMDUsIDUwMDg0MDQpLCBJREhNID0gYygwLjY3LCAwLjcxMSwgMC42NzMsIA0KMC42NjMsIDAuNjcsIDAuNjk3LCAwLjY0MywgMC42OTcsIDAuNjg4LCAwLjYzMywgMC42ODEsIDAuNzEsIA0KMC42ODQsIDAuNjk4LCAwLjY2NiwgMC42NywgMC43MDEsIDAuNjkyLCAwLjcwMywgMC43ODQsIDAuNjQ3LCANCjAuNzI3LCAwLjc1NCwgMC42NzEsIDAuNTg5LCAwLjcsIDAuNzA2LCAwLjcwMywgMC42OTQsIDAuNjM5LCANCjAuNjk5LCAwLjc0NywgMC42ODQsIDAuNzE0LCAwLjY2LCAwLjcyMSwgMC42NzUsIDAuNjYyLCAwLjY4MSwgDQowLjY1NCwgMC42MiwgMC43MiwgMC41MjYsIDAuNjY0LCAwLjcxMiwgMC43MDgsIDAuNjIzLCAwLjcwNCwgDQowLjY3MiwgMC43MzYsIDAuNjMyLCAwLjY4NiwgMC43LCAwLjYzOSwgMC42OTQsIDAuNzIxLCAwLjY0OSwgDQowLjcyMSwgMC41ODgsIDAuNjcxLCAwLjcwMSwgMC42NjYsIDAuNjY0LCAwLjcxNSwgMC43MDksIDAuNjczLCANCjAuNjUxLCAwLjY0MiwgMC43MjksIDAuNjE0LCAwLjY4MiwgMC42ODYsIDAuNjgxLCAwLjU5MywgMC42NTEsIA0KMC42NTgsIDAuNzQ0LCAwLjcxMSksIElESE1fRSA9IGMoMC41MTgsIDAuNTcyLCAwLjU0NiwgMC41NTcsIA0KMC41MzgsIDAuNTgyLCAwLjUyNiwgMC41ODgsIDAuNTYyLCAwLjUwNywgMC41MzcsIDAuNjA2LCAwLjU1OSwgDQowLjU4NSwgMC41NzMsIDAuNTA4LCAwLjU3LCAwLjU5MiwgMC41OTYsIDAuNzI0LCAwLjUyMiwgMC42MjcsIA0KMC42NjUsIDAuNTMxLCAwLjQxNywgMC41ODYsIDAuNjA2LCAwLjU3OSwgMC41OTUsIDAuNTI4LCAwLjU5NywgDQowLjY1NywgMC41NzcsIDAuNjIxLCAwLjUxMSwgMC42NDgsIDAuNTQ5LCAwLjUzLCAwLjUzMSwgMC41MjMsIA0KMC40NzksIDAuNjE1LCAwLjMzNywgMC41MywgMC41OTUsIDAuNTc5LCAwLjQ4NSwgMC42MTgsIDAuNTQ1LCANCjAuNjEzLCAwLjUwNywgMC41NjUsIDAuNTk3LCAwLjQ4MywgMC41NTQsIDAuNjE2LCAwLjUyMywgMC42MjcsIA0KMC40NDQsIDAuNTYyLCAwLjU5OCwgMC41MjYsIDAuNTE5LCAwLjU5LCAwLjU4NSwgMC41MjEsIDAuNDkxLCANCjAuNTA1LCAwLjYwOCwgMC40NSwgMC41NzYsIDAuNTYxLCAwLjU1NywgMC40MzQsIDAuNTQ1LCAwLjUyMSwgDQowLjY0NSwgMC42MjYpLCBJREhNX0wgPSBjKDAuODIzLCAwLjg1OCwgMC44MTgsIDAuNzg5LCAwLjgyNiwgDQowLjgzOSwgMC43OTksIDAuODA0LCAwLjg0LCAwLjc5OCwgMC44NDgsIDAuODQ3LCAwLjgxNCwgMC44MywgDQowLjc3NiwgMC44MzEsIDAuODM3LCAwLjgyOCwgMC44MTcsIDAuODQ0LCAwLjgyNiwgMC44MTEsIDAuODUsIA0KMC44MywgMC44MDYsIDAuODM0LCAwLjgxMSwgMC44MzYsIDAuODEsIDAuNzczLCAwLjgwOSwgMC44NDMsIA0KMC44MjQsIDAuODE1LCAwLjgzLCAwLjgyMiwgMC44MjYsIDAuODE3LCAwLjg0NiwgMC44MDksIDAuNzcyLCANCjAuODUsIDAuNzkxLCAwLjgyNywgMC44NDUsIDAuODU3LCAwLjc3LCAwLjgyMiwgMC44MjIsIDAuODczLCANCjAuNzgyLCAwLjgwOCwgMC44MDMsIDAuODIyLCAwLjgwOSwgMC44NSwgMC43OTgsIDAuODIzLCAwLjgxMSwgDQowLjgwMSwgMC44MTIsIDAuODMsIDAuODMsIDAuODYxLCAwLjg2OSwgMC44NTIsIDAuODMsIDAuOCwgMC44NSwgDQowLjc3OCwgMC44MjUsIDAuODI5LCAwLjgwMywgMC43ODIsIDAuNzY5LCAwLjgzOSwgMC44NDksIDAuODM1DQopLCBJREhNX1IgPSBjKDAuNzA1LCAwLjczMywgMC42ODMsIDAuNjYzLCAwLjY3NiwgMC42OTIsIDAuNjMzLCANCjAuNzE3LCAwLjY5LCAwLjYyOCwgMC42OTQsIDAuNjk4LCAwLjcwMiwgMC42OTksIDAuNjY1LCAwLjcxNCwgDQowLjcyMSwgMC42NzYsIDAuNzE1LCAwLjc5LCAwLjYyOCwgMC43NTYsIDAuNzU4LCAwLjY4NCwgMC42MDcsIA0KMC43MDEsIDAuNzE3LCAwLjcxOSwgMC42OTMsIDAuNjQsIDAuNzA2LCAwLjc1MywgMC42NzQsIDAuNzE5LCANCjAuNjc3LCAwLjcwNSwgMC42NzcsIDAuNjcxLCAwLjcwMiwgMC42NiwgMC42NDUsIDAuNzE1LCAwLjU0NywgDQowLjY2OCwgMC43MTgsIDAuNzE2LCAwLjY0NiwgMC42ODcsIDAuNjc2LCAwLjc0NCwgMC42MzgsIDAuNzA3LCANCjAuNzE1LCAwLjY1OCwgMC43NDYsIDAuNzE2LCAwLjY1NiwgMC43MjcsIDAuNTY2LCAwLjY3MiwgMC43MDgsIA0KMC42NzcsIDAuNjgxLCAwLjcyLCAwLjcwMiwgMC42ODYsIDAuNjc2LCAwLjY1NSwgMC43NTEsIDAuNjYsIA0KMC42NjgsIDAuNjk0LCAwLjcwNiwgMC42MTUsIDAuNjU3LCAwLjY1MSwgMC43NTIsIDAuNjg5KSksIHJvdy5uYW1lcyA9IGMoTkEsIA0KLTc4TCksIGNsYXNzID0gYygidGJsX2RmIiwgInRibCIsICJkYXRhLmZyYW1lIikpDQpgYGANCg0KU2VndWUgbyBjaHVuayBwYXJhIG9ww6fDo28gZGUgZG93bmxvYWQgbWFudWFsIGUgYXJtYXplbmFtZW50byBlbSBzZXUgZGlyZXTDs3Jpby4gICAgDQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KIyB0cmF6ZW5kbyBvcyBkYWRvcyBkbyBCcmFzaWwgdG9kbyBhcGVuYXMgcGFyYSBtdW5pY2lwaW9zDQpsaWJyYXJ5KHJlYWR4bCkNCmF0bGFzMjAxM19kYWRvc2JydXRvc19wdCA8LSByZWFkX2V4Y2VsKCJhdGxhczIwMTNfZGFkb3NicnV0b3NfcHQueGxzeCIsIA0KICAgIHNoZWV0ID0gIk1VTiA5MS0wMC0xMCIpDQojIHJlZHV6aXIgbGluaGFzIHBhcmEgMjAxMCBlIE1TDQojIHVzYW5kbyBhIGZ1bmNhbyBzdWJzZXQgcGFyYSBwZWdhciBhcyBjb2x1bmFzIGRlIElESCBhdMOpIGEgw7psdGltYSAoKQ0KZGFkb3NfbXMgPC0gc3Vic2V0KGF0bGFzMjAxM19kYWRvc2JydXRvc19wdCwgVUYgPT0gJzUwJyAmIEFOTyA9PSAnMjAxMCcsDQogICAgICAgICAgICAgICAgICAgc2VsZWN0PWMoQ29kbXVuNyxJREhNLElESE1fRSxJREhNX0wsSURITV9SKSkNCnByaW50KGRhZG9zX21zKQ0KYGBgDQoNCmBgYHtyIGVjaG8gPSBULCByZXN1bHRzID0gJ2hpZGUnfQ0KYWxsX211bl9tcyA8LSByZWFkX211bmljaXBhbGl0eShjb2RlX211bmk9NTAsIHllYXI9MjAxMCkNCmBgYA0KDQpKdW50YXJlaSBvcyBkYXRhc2V0cyBwZWxhIGNvbmRpw6fDo28gZGUgcXVlIG8gYGNvZGVfbXVuaWAgZG8gb2JqZXRvIGBhbGxfbXVuX21zYCDDqSBpZ3VhbCBhbyBgQ29kbXVuN2AgZG8gb2JqZXRvIGBkYWRvc19tc2AuICAgIA0KDQpgYGB7cn0NCmRhdGFzZXRfZmluYWwgPSBsZWZ0X2pvaW4oYWxsX211bl9tcywgZGFkb3NfbXMsIGJ5PWMoImNvZGVfbXVuaSI9IkNvZG11bjciKSkNCm1heChkYXRhc2V0X2ZpbmFsJElESE0pICMgMC43ODQNCm1pbihkYXRhc2V0X2ZpbmFsJElESE0pICMgMC41MjYNCmdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhPWRhdGFzZXRfZmluYWwsIGFlcyhmaWxsPUlESE0pLCBjb2xvcj0gTkEsIHNpemU9LjE1KSsNCiAgbGFicyh0aXRsZT0iSURITSAyMDEzIChhbm8gYmFzZSAyMDEwKSBkb3MgTXVuaWNpcMOtb3MgZGUgTVMiLA0KICAgICAgIGNhcHRpb249J0ZvbnRlOiBFbGFib3Jhw6fDo28gcHLDs3ByaWEnLCBzaXplPTgpKw0KICBzY2FsZV9maWxsX2Rpc3RpbGxlcihwYWxldHRlID0gIkdyZWVucyIsIGxpbWl0cz1jKDAuNSwgMC44KSwNCiAgICAgICAgICAgICAgICAgICAgICAgbmFtZT0iQ29kZV9tdW5pIikrDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KU2VuZG8gdW0gbWFwYSBmZWl0byBlbSBgZ2dwbG90MmAgcGVsb3MgY29tYW5kb3MgYGdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhPWRhdGFzZXRfZmluYWwsIGFlcyhmaWxsPUlESE0pLCBjb2xvcj0gTkEsIHNpemU9LjE1KWAsIG8gcGFkcsOjbyDDqSB1bSBtYXBhIG5hIGVzY2FsYSBhenVsLiBPdSBzZWphLCBmYXplbmRvIGFnb3JhIHVtIG1hcGEgcGFyYSBvIElESE1fRSAoSURITSBFZHVjYcOnw6NvKSwgcmVjb21lbmRvIG8gdXN1w6FyaW8gZmF6ZXIgbyBwYXNzbyBhIHBhc3NvIGRlIG1vZG8gYSB2ZXIgZXhhdGFtZW50ZSBvIHF1ZSBvIGPDs2RpZ28gcmVhbGl6YTogICAgDQogIA0KYGBge3J9DQojZGF0YXNldF9maW5hbCA9IGxlZnRfam9pbihhbGxfbXVuX21zLCBkYWRvc19tcywgYnk9YygiY29kZV9tdW5pIj0iQ29kbXVuNyIpKQ0KbWF4KGRhdGFzZXRfZmluYWwkSURITV9FKSAjIDAuNzI0DQptaW4oZGF0YXNldF9maW5hbCRJREhNX0UpICMgMC4zMzcNCmBgYA0KDQpgYGB7cn0NCmdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhPWRhdGFzZXRfZmluYWwsIGFlcyhmaWxsPUlESE1fRSksIGNvbG9yPSBOQSwgc2l6ZT0uMTUpDQpgYGANCg0KVmVqYSBxdWUgbyBtYXBhIGFudGVyaW9yIHNhaXUgZW0gYXp1bCwgc2VtIHLDs3R1bG9zLiBPYnNlcnZlIHF1ZSBuZXNzZSBjYXNvIGUgbm8gcHLDs3hpbW8sIG7Do28gZml6IG5lbmh1bWEgcmVzdHJpw6fDo28gw6AgbGVnZW5kYS4gICAgIA0KDQpPIHByw7N4aW1vIHNhaSBjb20gcsOzdHVsb3MgZG8gdMOtdHVsbyBlIG5vdGEgYW8gZmluYWwgZG8gbWFwYS4NCg0KYGBge3J9DQpnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YT1kYXRhc2V0X2ZpbmFsLCBhZXMoZmlsbD1JREhNX0UpLCBjb2xvcj0gTkEsIHNpemU9LjE1KSsNCiAgbGFicyh0aXRsZT0iSURITSBFZHVjYcOnw6NvIDIwMTMgKGFubyBiYXNlIDIwMTApIGRvcyBNdW5pY2lww61vcyBkZSBNUyIsDQogICAgICAgY2FwdGlvbj0nRm9udGU6IEVsYWJvcmHDp8OjbyBwcsOzcHJpYScsIHNpemU9OCkNCmBgYA0KDQpQYXJhIG8gcHLDs3hpbW8gbWFwYSwgY29sb2NvIGEgcGFsZXRhIGRlIGNvcmVzIGVtIHZlcm1lbGhvIGUgb3MgbGltaXRlcyBwYXJhIGFzIGNsYXNzZXMsIGFnb3JhIGRlIDAgYSAxLiAgICANCg0KYGBge3J9DQpnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YT1kYXRhc2V0X2ZpbmFsLCBhZXMoZmlsbD1JREhNX0UpLCBjb2xvcj0gTkEsIHNpemU9LjE1KSsNCiAgbGFicyh0aXRsZT0iSURITSBFZHVjYcOnw6NvIDIwMTMgKGFubyBiYXNlIDIwMTApIGRvcyBNdW5pY2lww61vcyBkZSBNUyIsDQogICAgICAgY2FwdGlvbj0nRm9udGU6IEVsYWJvcmHDp8OjbyBwcsOzcHJpYScsIHNpemU9OCkrDQogIHNjYWxlX2ZpbGxfZGlzdGlsbGVyKHBhbGV0dGUgPSAiUmVkcyIsIGxpbWl0cz1jKDAuMCwgMS4wKSwNCiAgICAgICAgICAgICAgICAgICAgICAgbmFtZT0iQ29kZV9tdW5pIikNCmBgYA0KDQpObyBleGVtcGxvIGFiYWl4byBmYcOnbyB1bSBjYXNvIHBhcnRpY3VsYXIgZW0gcXVlIHVtIG11bmljw61waW8sIG8gZGUgbcOheGltbyBJREhNX0UgZmljb3UgZXhjbHXDrWRvIHBvciB1bWEgcmVzdHJpw6fDo28gYW8gZGVsaW1pdGFyIG8gbcOheGltbyBkYSBwYWxoZXRhIGVtIDAuNyAobyB2YWxvciBzZXJpYSBkZSBDYW1wbyBHcmFuZGUsIDAuNzI0LCBtYWlvciBxdWUgMC43KS4gUG9ydGFudG8sIG8gbXVuaWPDrXBpbyBmaWNvdSBlbSBwcmV0by4gICAgDQoNCmBgYHtyfQ0KZ2dwbG90KCkgKw0KICBnZW9tX3NmKGRhdGE9ZGF0YXNldF9maW5hbCwgYWVzKGZpbGw9SURITV9FKSwgY29sb3I9IE5BLCBzaXplPS4xNSkrDQogIGxhYnModGl0bGU9IklESE0gRWR1Y2HDp8OjbyAyMDEzIChhbm8gYmFzZSAyMDEwKSBkb3MgTXVuaWNpcMOtb3MgZGUgTVMiLA0KICAgICAgIGNhcHRpb249J0ZvbnRlOiBFbGFib3Jhw6fDo28gcHLDs3ByaWEnLCBzaXplPTgpKw0KICBzY2FsZV9maWxsX2Rpc3RpbGxlcihsaW1pdHM9YygwLjMsIDAuNykpKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCk91dHJhcyBwYWxoZXRhcyBkZSBjb3JlcyBwb2RlIHNlciB2aXN1YWxpemFkYSBlbSA8aHR0cDovL3d3dy5zdGhkYS5jb20vZW5nbGlzaC93aWtpL2dncGxvdDItY29sb3JzLWhvdy10by1jaGFuZ2UtY29sb3JzLWF1dG9tYXRpY2FsbHktYW5kLW1hbnVhbGx5Pi4gICAgDQoNCg0KYGBge3J9DQojIGRhdGFzZXRfZmluYWwgPSBsZWZ0X2pvaW4oYWxsX211bl9tcywgZGFkb3NfbXMsIGJ5PWMoImNvZGVfbXVuaSI9IkNvZG11bjciKSkNCiMgbWF4KGRhdGFzZXRfZmluYWwkSURITSkgIyAwLjc4NA0KIyBtaW4oZGF0YXNldF9maW5hbCRJREhNKSAjIDAuNTI2DQpnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YT1kYXRhc2V0X2ZpbmFsLCBhZXMoZmlsbD1JREhNKSwgY29sb3I9IE5BLCBzaXplPS4xNSkrDQogIGxhYnModGl0bGU9IklESE0gMjAxMyAoYW5vIGJhc2UgMjAxMCkgZG9zIE11bmljaXDDrW9zIGRlIE1TIiwNCiAgICAgICBjYXB0aW9uPSdGb250ZTogRWxhYm9yYcOnw6NvIHByw7NwcmlhJywgc2l6ZT04KSsNCiAgc2NhbGVfZmlsbF9kaXN0aWxsZXIocGFsZXR0ZSA9ICJSZEd5IiwgbGltaXRzPWMoMC41LCAwLjgpLA0KICAgICAgICAgICAgICAgICAgICAgICBuYW1lPSJDb2RlX211bmkiKSsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCmBgYA0KDQpSZWZlcsOqbmNpYXMgey0jUmVmZXLDqm5jaWFzfQ0KPT09PT09PT09PT09PT09PT09PT09DQoNClBFUkVJUkEsIFJhZmFlbCBILiBNLjsgR09Ow4dBTFZFUywgQ2FpbyBOb2d1ZWlyYTsgQ0FSVkFMSE8sIEd1aWxoZXJtZSBEdWFydGU7IEFSQcOaSk8sIFBhdWxvIEhlbnJpcXVlIEZlcm5hbmRlcyBkZTtBUlJVREEsIFJvZHJpZ28gQWxtZWlkYSBkZS4gKmdlb2JyOiBMb2FkcyBTaGFwZWZpbGVzIG9mIE9mZmljaWFsIFNwYXRpYWwgRGF0YSBTZXRzIG9mIEJyYXppbCouIFIgcGFja2FnZSB2ZXJzaW9uIDEuMS4gQ1JBTi4gMjAxOS4gRGlzcG9uw612ZWwgZW06IDxodHRwczovL0NSQU4uUi1wcm9qZWN0Lm9yZy9wYWNrYWdlPWdlb2JyPi4NCg0KV0lDS0hBTSwgSC4gICpnZ3Bsb3QyOiBFbGVnYW50IEdyYXBoaWNzIGZvciBEYXRhIEFuYWx5c2lzKi4gU3ByaW5nZXItVmVybGFnIE5ldyBZb3JrLCAyMDE2Lg0KICA=