Este é um tutorial introdutório, onde veremos algumas funções úteis para trabalhar com dados da COVID-19 usando o R, a partir do repositório da Johns Hopkins University. Os códigos estão comentados, de modo a facilitar a compreensão para leigos, porém, no geral vamos assumir algum conhecimento básico de R.
Se você deseja trabalhar com dados do R internacionalmente, vale a pena conferir o pacote Tidy Covid 19. Aqui, porém, usaremos principalmente o tidyverse
.
Atenção: Tenha cuidado redobrado ao compartilhar conclusões, visualizações e análises sobre dados de saúde pública, especialmente em meio a uma pandemia mundial.
library(tidyverse)
Importando os dados
O primeiro passo é baixar os dados e entender a sua estrutura.
# Vamos chamar o link com o CSV de "url"
url = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv'
# Agora, importamos o CSV no R...
dados = read.csv(url)
#... e o exibimos
dados
Você pode navegar pela tabela utilizando a páginação acima. Podemos ver que temos os seguintes campos:
- Province.State (província, por exemplo, Guiana Francesa)
- Country.Region (país, por exemplo, França)
- Lat (latitude)
- Long (longitude)
- Datas: e na sequência temos várias datas, registrando a série histórica de cada país. Cada dia é uma coluna.
Filtrando dados
Filtrar os registros é bem fácil. Abaixo, vamos criar um novo conjunto de dados (df
) filtrando apenas os registros com Brasil e Itália no campo Country.Region
. Depois, vamos excluir as colunas Province.State
, Lat
e Long
, que não nos interessam.
Repare que podemos selecionar as colunas que não queremos com o sinal de negativo (-
) com o comando select. Usaremos esse recurso novamente no comando seguinte. Veja também que a barra em pé (|
) significa o operador “OU”.
df <- dados %>% filter(Country.Region == 'Italy' | Country.Region == 'Brazil') %>%
select(-Province.State,-Lat,-Long)
df
Transformando textos em datas
Agora, precisamos definir que o campo “dia” deve ser encarado como uma data. Repare bem no padrão da data na tabela acima.
Ela é uma sequência de caraceteres (indicado pela sigla “chr” no cabeçalho). A primeira coisa que faremos é tirar este “X” e depois formatar a coluna como data.
Primeiro, vamos usar uma função para substituir (replace) uma sequência de caracteres (string ou str), a função str_replace. Com ela, vamos trocar no campo “dia” do banco de dados “df” qualquer ocorrência de X por uma sequência vazia, Ou seja, na prática, removeremos todos os “X”.
Depois, vamos mudar o campo para o formato de data com a função as.Data
, explicitando que o formato data que é mês (%m), dia (%d) e ano (%y) - separados por um ponto.
df$Day <- str_replace(df$Day,"X", "") %>%
as.Date(format='%m.%d.%y')
# Vamos checar se funcionou vendo o dia mais recente, já no formato correto
max(df$Day)
[1] "2020-04-20"
Identificando o dia zero a partir de X casos
Uma métrica bastante comum em análise de epidemias é a contagem de quantos dias se passaram desde determinado limar de casos. Isso facilita a comparação de fenômenos que ocorreram em datas distintas. Vamos criar uma nova coluna (Day0
) com o “dia zero” de caada país.
df <- df %>%
# A ordem das datas é fundamental, então, vamos ordenar os dados por dia
arrange(Day) %>%
# Você pode querer contar os dias partir do centésimo caso, por exemplo. Para trocar este parâmetro, basta mudar o número abaixo.
filter(Total > 0) %>%
# Então, vamos usar o group_by para que a operação a seguir seja feita para cada país (Country.Region)
group_by(Country.Region) %>%
# Vamos definir o dia 0 como o menor dia daquele país
mutate(Day0 = min(Day))
df
Contagem de dias desde o caso número X
Já sabemos a data de registro e a data do primeiro caso, para cada registro de nossa tabela. Agora, está fácil calcularmos a diferença entre os dias. Assim, podemos analisar como cada país estava uma semana após a passar o limiar do centésimo caso, por exemplo.
Vamos criar uma nova variável (conta_dia) que vai ser o resultado da diferença entre a data de registro (dia) e o dia 0 (dia0) em dias.
# Vamos adicionar o novo campo
df$CountDays <- difftime(df$Day,df$Day0,units = "days")
# E visualizar os dados ordernados por ele
df %>% arrange(CountDays)
Casos novos por dia e aumento percentual
Repare que a coluna “casos” traz o total de casos acumulado até a data especificada no campo Day
. Mas e se quisermos saber o número de novos casos por dia?
Vamos criar uma nova coluna chamada novos_casos
, que será resultado do número de casos do dia menos o número de casos do dia anterior, em cada país.
Também vamos adicionar novos campos para mostrar o aumento percentual no número acumulado de casos confirmados diariamentee a média móvel de novos casos nos últimos 7 dias.
Para relembrar, para calcular o aumento percentual, pegamos o número de novos casos (NewCases
), dividimos pelo total dia anterior (lag(Total)
) e então multiplicamos por 100 para obter a taxa percentual. Também vamos arredondar o resultado, usando a função round()
.
df <- df %>%
# Vamos remover a coluna day0 pois ela não é mais necessária
select(-Day0) %>%
# Agrupamos por país
group_by(Country.Region) %>%
arrange(Day) %>%
# Lembrando que nossos casos já estão ordenados por dia
# Então, utilizamos a função lag() para retornar o último valor daquela coluna
mutate(NewCases = Total - lag(Total)) %>%
# E por fim o aumento percentual
mutate(Increase = round((NewCases/lag(Total)*100)))
df
NA
Casos por milhão de habitantes
Ainda que alguns especialistas desencorajam o uso de taxas populacionais para avaliação da taxa de contágio nos estágios iniciais de uma pandemia, pois, segundo eles, o número de pessoas contagiadas por cada infectada não seria alterada pelo tamanho da população, à medida que a epidemia progride este número passa a ser útil e atualmente é utilizado inclusive pelo Ministério da Saúde para avaliar o impacto. A taxa é especialmente boa não só para comparar populações de tamanhos distintos, como também para avaliar o impacto na infra-estrutura de saúde. Então, vamos ver como realizá-la.
Para se aprofundar mais nesta discussão, vide o item 4.4.2 deste artigo ou esta matéria do The New York Times.
Aqui, vamos adicionar uma coluna com a população dos países. Como este é apenas um exemplo e temos só 2 casos, podemos usar uma condicional simples. Se o país for a Itália, inserimos a população de 60 milhões (60483538), se não, então, será do Brasil, que tem população de 211 milhões (211376071). Se você for fazer esta operação com vários países, então, é melhor importar uma tabela com os dados populacionais e cruzá-la com os dados da COVID.
df <- df %>% mutate(Pop = ifelse(Country.Region == "Italy",60483538,211376071)) %>%
# Uma vez que você insira a coluna de população, o cálculo da taxa é simples
mutate(taxa = round((Total/Pop) * 1000000))
df
Bônus: plotando o resultado em gráfico
Este não é um tutorial de visualização de dados, mas depois de chegar aqui nós merecemos ver o resultado do trabalho em um gráfico. Então, vamos lá!

LS0tCnRpdGxlOiAiRnVuw6fDtWVzIMO6dGVpcyBwYXJhIG9yZ2FuaXphciBkYWRvcyBkYSBDT1ZJRC0xOSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKRXN0ZSDDqSB1bSB0dXRvcmlhbCBpbnRyb2R1dMOzcmlvLCBvbmRlIHZlcmVtb3MgYWxndW1hcyBmdW7Dp8O1ZXMgw7p0ZWlzIHBhcmEgdHJhYmFsaGFyIGNvbSBkYWRvcyBkYSBDT1ZJRC0xOSB1c2FuZG8gbyBSLCBhIHBhcnRpciBkbyByZXBvc2l0w7NyaW8gZGEgW0pvaG5zIEhvcGtpbnMgVW5pdmVyc2l0eV0oaHR0cHM6Ly9naXRodWIuY29tL0NTU0VHSVNhbmREYXRhL0NPVklELTE5KS4gT3MgY8OzZGlnb3MgZXN0w6NvIGNvbWVudGFkb3MsIGRlIG1vZG8gYSBmYWNpbGl0YXIgYSBjb21wcmVlbnPDo28gcGFyYSBsZWlnb3MsIHBvcsOpbSwgbm8gZ2VyYWwgdmFtb3MgYXNzdW1pciBhbGd1bSBjb25oZWNpbWVudG8gYsOhc2ljbyBkZSBSLiAKClNlIHZvY8OqIGRlc2VqYSB0cmFiYWxoYXIgY29tIGRhZG9zIGRvIFIgaW50ZXJuYWNpb25hbG1lbnRlLCB2YWxlIGEgcGVuYSBjb25mZXJpciBvIHBhY290ZSBbVGlkeSBDb3ZpZCAxOV0oaHR0cHM6Ly9naXRodWIuY29tL2pvYWNoaW0tZ2Fzc2VuL3RpZHlfY292aWQxOSkuIEFxdWksIHBvcsOpbSwgdXNhcmVtb3MgcHJpbmNpcGFsbWVudGUgbyBgdGlkeXZlcnNlYC4KCioqQXRlbsOnw6NvOioqIFRlbmhhIGN1aWRhZG8gcmVkb2JyYWRvIGFvIGNvbXBhcnRpbGhhciBjb25jbHVzw7VlcywgdmlzdWFsaXphw6fDtWVzIGUgYW7DoWxpc2VzIHNvYnJlIGRhZG9zIGRlIHNhw7pkZSBww7pibGljYSwgZXNwZWNpYWxtZW50ZSBlbSBtZWlvIGEgdW1hIHBhbmRlbWlhIG11bmRpYWwuCgpgYGB7ciByZXN1bHRzPSdoaWRlJ30KbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKIyBJbXBvcnRhbmRvIG9zIGRhZG9zCk8gcHJpbWVpcm8gcGFzc28gw6kgYmFpeGFyIG9zIGRhZG9zIGUgZW50ZW5kZXIgYSBzdWEgZXN0cnV0dXJhLgpgYGB7cn0KCiMgVmFtb3MgY2hhbWFyIG8gbGluayBjb20gbyBDU1YgZGUgInVybCIKdXJsID0gJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9DU1NFR0lTYW5kRGF0YS9DT1ZJRC0xOS9tYXN0ZXIvY3NzZV9jb3ZpZF8xOV9kYXRhL2Nzc2VfY292aWRfMTlfdGltZV9zZXJpZXMvdGltZV9zZXJpZXNfY292aWQxOV9jb25maXJtZWRfZ2xvYmFsLmNzdicKCiMgQWdvcmEsIGltcG9ydGFtb3MgbyBDU1Ygbm8gUi4uLgpkYWRvcyA9IHJlYWQuY3N2KHVybCkKCiMuLi4gZSBvIGV4aWJpbW9zCmRhZG9zCmBgYAoKVm9jw6ogcG9kZSBuYXZlZ2FyIHBlbGEgdGFiZWxhIHV0aWxpemFuZG8gYSBww6FnaW5hw6fDo28gYWNpbWEuIFBvZGVtb3MgdmVyIHF1ZSB0ZW1vcyBvcyBzZWd1aW50ZXMgY2FtcG9zOgoKKiAqKlByb3ZpbmNlLlN0YXRlKiogKHByb3bDrW5jaWEsIHBvciBleGVtcGxvLCBHdWlhbmEgRnJhbmNlc2EpCiogKipDb3VudHJ5LlJlZ2lvbioqIChwYcOtcywgcG9yIGV4ZW1wbG8sIEZyYW7Dp2EpCiogKipMYXQqKiAobGF0aXR1ZGUpCiogKipMb25nKiogKGxvbmdpdHVkZSkKKiAqKkRhdGFzKio6IGUgbmEgc2VxdcOqbmNpYSB0ZW1vcyB2w6FyaWFzIGRhdGFzLCByZWdpc3RyYW5kbyBhIHPDqXJpZSBoaXN0w7NyaWNhIGRlIGNhZGEgcGHDrXMuIENhZGEgZGlhIMOpIHVtYSBjb2x1bmEuCgoKIyBGaWx0cmFuZG8gZGFkb3MKCkZpbHRyYXIgb3MgcmVnaXN0cm9zIMOpIGJlbSBmw6FjaWwuIEFiYWl4bywgdmFtb3MgY3JpYXIgdW0gbm92byBjb25qdW50byBkZSBkYWRvcyAoYGRmYCkgZmlsdHJhbmRvIGFwZW5hcyBvcyByZWdpc3Ryb3MgY29tIEJyYXNpbCBlIEl0w6FsaWEgbm8gY2FtcG8gYENvdW50cnkuUmVnaW9uYC4gCkRlcG9pcywgdmFtb3MgZXhjbHVpciBhcyBjb2x1bmFzIGBQcm92aW5jZS5TdGF0ZWAsIGBMYXRgIGUgYExvbmdgLCBxdWUgbsOjbyBub3MgaW50ZXJlc3NhbS4gCgpSZXBhcmUgcXVlIHBvZGVtb3Mgc2VsZWNpb25hciBhcyBjb2x1bmFzIHF1ZSBuw6NvIHF1ZXJlbW9zIGNvbSBvIHNpbmFsIGRlIG5lZ2F0aXZvIChgLWApIGNvbSBvIGNvbWFuZG8gc2VsZWN0LiBVc2FyZW1vcyBlc3NlIHJlY3Vyc28gbm92YW1lbnRlIG5vIGNvbWFuZG8gc2VndWludGUuIFZlamEgdGFtYsOpbSBxdWUgYSBiYXJyYSBlbSBww6kgKGB8YCkgc2lnbmlmaWNhIG8gb3BlcmFkb3IgIk9VIi4KCmBgYHtyfQpkZiA8LSBkYWRvcyAlPiUgZmlsdGVyKENvdW50cnkuUmVnaW9uID09ICdJdGFseScgfCBDb3VudHJ5LlJlZ2lvbiA9PSAnQnJhemlsJykgJT4lIAogIHNlbGVjdCgtUHJvdmluY2UuU3RhdGUsLUxhdCwtTG9uZykKCmRmCgpgYGAKCgojIFRyYW5zZm9ybWFuZG8gY29sdW5hcyBlbSBsaW5oYXMKClBhcmEgZmFjaWxpdGFyIGEgYW7DoWxpc2UgZSB2aXN1YWxpemHDp8OjbyBkb3MgZGFkb3MsIGFvIGludsOpcyBkZSB0ZXIgdsOhcmlhcyBjb2x1bmFzLCB2YW1vcyBjcmlhciB1bWEgdmFyacOhdmVsIChvdSB1bWEgbm92YSBjb2x1bmEpIHF1ZSBjb250ZW5oYSBvIGRpYSBlIG91dHJhIGNvbSBvIG7Dum1lcm8gZGUgY2Fzb3MuIEFzc2ltLCBwb2RlbW9zIHJlc3VtaXIgYXF1ZWxhcyB2w6FyaWFzIGNvbHVuYXMgZW0gYXBlbmFzIGR1YXMuCgpWb2PDqiBwb2RlIHV0aWxpemFyIGRpdmVyc2FzIGZ1bsOnw7VlcywgY29tbyBhIGBnYXRoZXJgIG91IGEgYHBpdm90X2xvbmdlcmAuIFBhcmEgbm9zc28gZXhlbXBsbywgYW1iYXMgc8OjbyBtdWl0b3Mgc2VtZWxoYW50ZXMsIG1hcyBhIHByaW1laXJhIHNlcsOhIGRlc2NvbnRpbnVhZGEgcGVsYSBlcXVpcGUgZGUgZGVzZW52b2x2ZWRvcmVzLCBlbnTDo28sIHJlY29tZW5kYW1vcyB1dGlsaXphciBhIGBwaXZvdF9sb25nZXJgLiAKCkJhc2ljYW1lbnRlLCBwcmVjaXNhbW9zIGRlZmluaXIgdHLDqnMgcGFyw6JtZXRyb3MgcGFyYSBlbGFzIHJlYWxpemFyZW0gc2V1IHRyYWJhbGhvOgoKKiBEYWRvczogUXVhaXMgYXMgY29sdW5hcyBzZXLDo28gYWx2b3MgZGEgdHJhbnNmb3JtYcOnw6NvPyBObyBub3NzbyBjYXNvLCBhcyBxdWUgcG9zc3VlbSBhIGNvbnRhZ2VtIGRlIGNhc29zIHBvciBkaWEsIG91IHNlamEsIHRvZGFzIG1lbm9zIGEgZG8gcGHDrXMuIAoKKiBDaGF2ZTogQ29tbyBzZXLDoSBjaGFtYWRhIGEgdmFyacOhdmVsIHF1ZSBndWFyZGFyw6EgbyBub21lIGRhcyBjb2x1bmFzPyBObyBub3NzbyBjYXNvLCB2YW1vcyBjaGFtYXIgZGUgIkRheSIuCgoqIFZhbG9yZXM6IENvbW8gc2Vyw6EgY2hhbWFkYSBhIHZhcmnDoXZlbCBxdWUgZ3VhcmRhcsOhIG9zIHZhbG9yZXMgZGFzIGPDqWx1bGFzPyBWYW1vcyBub21lw6EtbGEgZGUgIlRvdGFsIi4KClZlamEgYWJhaXhvIGNvbW8gdXRpbGl6YW1vcyBlc3RlcyBwYXLDom1ldHJvcyBlbSBhbWJhcyBhcyBmdW7Dp8O1ZXMuCgpgYGB7cn0KIyBTZSB2b2PDqiBuw6NvIGNvbnNlZ3VpciByb2RhciBhIGZ1bsOnw6NvIGFiYWl4bywgdGFsdmV6IHByZWNpc2UgYXR1YWxpemFyIG8gcGFjb3RlICJ0aWR5ciIKIyBOZXN0ZSBjYXNvLCB2b29jw6ogcG9kZSByb2RhciBvIGNvbWFuZG8gaW5zdGFsbC5wYWNrYWdlcygidGlkeXIiKSAKIyBPdSB1dGlsaXphciBhIGZ1bsOnw6NvIGdhdGhlciwgZGVzY29tZW50YW5kbyBhIGxpbmhhIGFiYWl4bwojIGRmICU+JSBnYXRoZXIoZGlhLGNhc29zLC1Db3VudHJ5LlJlZ2lvbikKCmRmIDwtIGRmICU+JSBwaXZvdF9sb25nZXIoLUNvdW50cnkuUmVnaW9uLCJEYXkiLHZhbHVlc190byA9ICJUb3RhbCIpCgpkZgpgYGAKCiMgVHJhbnNmb3JtYW5kbyB0ZXh0b3MgZW0gZGF0YXMKCkFnb3JhLCBwcmVjaXNhbW9zIGRlZmluaXIgcXVlIG8gY2FtcG8gImRpYSIgZGV2ZSBzZXIgZW5jYXJhZG8gY29tbyB1bWEgZGF0YS4gUmVwYXJlIGJlbSBubyBwYWRyw6NvIGRhIGRhdGEgbmEgdGFiZWxhIGFjaW1hLgoKRWxhIMOpIHVtYSBzZXF1w6puY2lhIGRlIGNhcmFjZXRlcmVzIChpbmRpY2FkbyBwZWxhIHNpZ2xhICJjaHIiIG5vIGNhYmXDp2FsaG8pLiBBIHByaW1laXJhIGNvaXNhIHF1ZSBmYXJlbW9zIMOpIHRpcmFyIGVzdGUgIlgiIGUgZGVwb2lzIGZvcm1hdGFyIGEgY29sdW5hIGNvbW8gZGF0YS4KClByaW1laXJvLCB2YW1vcyB1c2FyIHVtYSBmdW7Dp8OjbyBwYXJhIHN1YnN0aXR1aXIgKHJlcGxhY2UpIHVtYSBzZXF1w6puY2lhIGRlIGNhcmFjdGVyZXMgKHN0cmluZyBvdSBzdHIpLCBhIGZ1bsOnw6NvIHN0cl9yZXBsYWNlLiBDb20gZWxhLCB2YW1vcyB0cm9jYXIgbm8gY2FtcG8gImRpYSIgZG8gYmFuY28gZGUgZGFkb3MgImRmIiBxdWFscXVlciBvY29ycsOqbmNpYSBkZSBYIHBvciB1bWEgc2VxdcOqbmNpYSB2YXppYSwgT3Ugc2VqYSwgbmEgcHLDoXRpY2EsIHJlbW92ZXJlbW9zIHRvZG9zIG9zICJYIi4KCkRlcG9pcywgdmFtb3MgbXVkYXIgbyBjYW1wbyBwYXJhIG8gZm9ybWF0byBkZSBkYXRhIGNvbSBhIGZ1bsOnw6NvIGBhcy5EYXRhYCwgZXhwbGljaXRhbmRvIHF1ZSBvIGZvcm1hdG8gZGF0YSBxdWUgw6kgbcOqcyAoJW0pLCBkaWEgKCVkKSBlIGFubyAoJXkpIC0gc2VwYXJhZG9zIHBvciB1bSBwb250by4KCmBgYHtyfQpkZiREYXkgPC0gc3RyX3JlcGxhY2UoZGYkRGF5LCJYIiwgIiIpICU+JQogIGFzLkRhdGUoZm9ybWF0PSclbS4lZC4leScpCgojIFZhbW9zIGNoZWNhciBzZSBmdW5jaW9ub3UgdmVuZG8gbyBkaWEgbWFpcyByZWNlbnRlLCBqw6Egbm8gZm9ybWF0byBjb3JyZXRvCm1heChkZiREYXkpCmBgYAoKCiMgSWRlbnRpZmljYW5kbyBvIGRpYSB6ZXJvIGEgcGFydGlyIGRlIFggY2Fzb3MKClVtYSBtw6l0cmljYSBiYXN0YW50ZSBjb211bSBlbSBhbsOhbGlzZSBkZSBlcGlkZW1pYXMgw6kgYSBjb250YWdlbSBkZSBxdWFudG9zIGRpYXMgc2UgcGFzc2FyYW0gZGVzZGUgZGV0ZXJtaW5hZG8gbGltYXIgZGUgY2Fzb3MuIElzc28gZmFjaWxpdGEgYSBjb21wYXJhw6fDo28gZGUgZmVuw7RtZW5vcyBxdWUgb2NvcnJlcmFtIGVtIGRhdGFzIGRpc3RpbnRhcy4gVmFtb3MgY3JpYXIgdW1hIG5vdmEgY29sdW5hIChgRGF5MGApIGNvbSBvICJkaWEgemVybyIgZGUgY2FhZGEgcGHDrXMuCgpgYGB7cn0KZGYgPC0gZGYgJT4lIAogICMgQSBvcmRlbSBkYXMgZGF0YXMgw6kgZnVuZGFtZW50YWwsIGVudMOjbywgdmFtb3Mgb3JkZW5hciBvcyBkYWRvcyBwb3IgZGlhCiAgYXJyYW5nZShEYXkpICU+JQogICMgVm9jw6ogcG9kZSBxdWVyZXIgY29udGFyIG9zIGRpYXMgcGFydGlyIGRvIGNlbnTDqXNpbW8gY2FzbywgcG9yIGV4ZW1wbG8uIFBhcmEgdHJvY2FyIGVzdGUgcGFyw6JtZXRybywgYmFzdGEgbXVkYXIgbyBuw7ptZXJvIGFiYWl4by4KICBmaWx0ZXIoVG90YWwgPiAwKSAgJT4lCiAgIyBFbnTDo28sIHZhbW9zIHVzYXIgbyBncm91cF9ieSBwYXJhIHF1ZSBhIG9wZXJhw6fDo28gYSBzZWd1aXIgc2VqYSBmZWl0YSBwYXJhIGNhZGEgcGHDrXMgKENvdW50cnkuUmVnaW9uKQogIGdyb3VwX2J5KENvdW50cnkuUmVnaW9uKSAlPiUKICAjIFZhbW9zIGRlZmluaXIgbyBkaWEgMCBjb21vIG8gbWVub3IgZGlhIGRhcXVlbGUgcGHDrXMKICBtdXRhdGUoRGF5MCA9IG1pbihEYXkpKSAKCmRmCmBgYAoKIyBDb250YWdlbSBkZSBkaWFzIGRlc2RlIG8gY2FzbyBuw7ptZXJvIFgKCkrDoSBzYWJlbW9zIGEgZGF0YSBkZSByZWdpc3RybyBlIGEgZGF0YSBkbyBwcmltZWlybyBjYXNvLCBwYXJhIGNhZGEgcmVnaXN0cm8gZGUgbm9zc2EgdGFiZWxhLiBBZ29yYSwgZXN0w6EgZsOhY2lsIGNhbGN1bGFybW9zIGEgZGlmZXJlbsOnYSBlbnRyZSBvcyBkaWFzLiBBc3NpbSwgcG9kZW1vcyBhbmFsaXNhciBjb21vIGNhZGEgcGHDrXMgZXN0YXZhIHVtYSBzZW1hbmEgYXDDs3MgYSBwYXNzYXIgbyBsaW1pYXIgZG8gY2VudMOpc2ltbyBjYXNvLCBwb3IgZXhlbXBsby4gCgpWYW1vcyBjcmlhciB1bWEgbm92YSB2YXJpw6F2ZWwgKGNvbnRhX2RpYSkgcXVlIHZhaSBzZXIgbyByZXN1bHRhZG8gZGEgZGlmZXJlbsOnYSBlbnRyZSBhIGRhdGEgZGUgcmVnaXN0cm8gKGRpYSkgZSBvIGRpYSAwIChkaWEwKSBlbSBkaWFzLgoKYGBge3J9CiMgVmFtb3MgYWRpY2lvbmFyIG8gbm92byBjYW1wbwpkZiRDb3VudERheXMgPC0gZGlmZnRpbWUoZGYkRGF5LGRmJERheTAsdW5pdHMgPSAiZGF5cyIpCgojIEUgdmlzdWFsaXphciBvcyBkYWRvcyBvcmRlcm5hZG9zIHBvciBlbGUKZGYgJT4lIGFycmFuZ2UoQ291bnREYXlzKSAKCmBgYAoKIyBDYXNvcyBub3ZvcyBwb3IgZGlhIGUgYXVtZW50byBwZXJjZW50dWFsCgpSZXBhcmUgcXVlIGEgY29sdW5hICJjYXNvcyIgdHJheiBvIHRvdGFsIGRlIGNhc29zIGFjdW11bGFkbyBhdMOpIGEgZGF0YSBlc3BlY2lmaWNhZGEgbm8gY2FtcG8gYERheWAuIE1hcyBlIHNlIHF1aXNlcm1vcyBzYWJlciBvIG7Dum1lcm8gZGUgbm92b3MgY2Fzb3MgcG9yIGRpYT8KClZhbW9zIGNyaWFyIHVtYSBub3ZhIGNvbHVuYSBjaGFtYWRhIGBub3Zvc19jYXNvc2AsIHF1ZSBzZXLDoSByZXN1bHRhZG8gZG8gbsO6bWVybyBkZSBjYXNvcyBkbyBkaWEgbWVub3MgbyBuw7ptZXJvIGRlIGNhc29zIGRvIGRpYSBhbnRlcmlvciwgZW0gY2FkYSBwYcOtcy4KClRhbWLDqW0gdmFtb3MgYWRpY2lvbmFyIG5vdm9zIGNhbXBvcyBwYXJhIG1vc3RyYXIgbyBhdW1lbnRvIHBlcmNlbnR1YWwgbm8gbsO6bWVybyBhY3VtdWxhZG8gZGUgY2Fzb3MgY29uZmlybWFkb3MgZGlhcmlhbWVudGVlIGEgbcOpZGlhIG3Ds3ZlbCBkZSBub3ZvcyBjYXNvcyBub3Mgw7psdGltb3MgNyBkaWFzLgoKUGFyYSByZWxlbWJyYXIsIHBhcmEgY2FsY3VsYXIgbyBhdW1lbnRvIHBlcmNlbnR1YWwsIHBlZ2Ftb3MgbyBuw7ptZXJvIGRlIG5vdm9zIGNhc29zIChgTmV3Q2FzZXNgKSwgZGl2aWRpbW9zIHBlbG8gdG90YWwgZGlhIGFudGVyaW9yIChgbGFnKFRvdGFsKWApIGUgZW50w6NvIG11bHRpcGxpY2Ftb3MgcG9yIDEwMCBwYXJhIG9idGVyIGEgdGF4YSBwZXJjZW50dWFsLiBUYW1iw6ltIHZhbW9zIGFycmVkb25kYXIgbyByZXN1bHRhZG8sIHVzYW5kbyBhIGZ1bsOnw6NvIGByb3VuZCgpYC4KCmBgYHtyfQpkZiA8LSBkZiAlPiUgCiAgIyBWYW1vcyByZW1vdmVyIGEgY29sdW5hIGRheTAgcG9pcyBlbGEgbsOjbyDDqSBtYWlzIG5lY2Vzc8OhcmlhCiAgc2VsZWN0KC1EYXkwKSAlPiUKICAjIEFncnVwYW1vcyBwb3IgcGHDrXMKICBncm91cF9ieShDb3VudHJ5LlJlZ2lvbikgJT4lIAogIGFycmFuZ2UoRGF5KSAlPiUKICAjIExlbWJyYW5kbyBxdWUgbm9zc29zIGNhc29zIGrDoSBlc3TDo28gb3JkZW5hZG9zIHBvciBkaWEKICAjIEVudMOjbywgdXRpbGl6YW1vcyBhIGZ1bsOnw6NvIGxhZygpIHBhcmEgcmV0b3JuYXIgbyDDumx0aW1vIHZhbG9yIGRhcXVlbGEgY29sdW5hCiAgbXV0YXRlKE5ld0Nhc2VzID0gVG90YWwgLSBsYWcoVG90YWwpKSAlPiUKICAjIEUgcG9yIGZpbSBvIGF1bWVudG8gcGVyY2VudHVhbAogIG11dGF0ZShJbmNyZWFzZSA9IHJvdW5kKChOZXdDYXNlcy9sYWcoVG90YWwpKjEwMCkpKSAKCmRmCiAgICAgICAgIApgYGAKCiMgTcOpZGlhIG3Ds3ZlbCBzaW1wbGVzCgpQYXJhIG9ic2VydmFybW9zIGFzIHRlbmTDqm5jaWFzIGRlIHPDqXJpZSB0ZW1wb3JhaXMsIHVtYSBtw6l0cmljYSDDunRpbCBhIG3DqWRpYSBtw7N2ZWwsIHF1ZSAic3Vhdml6YSIgb3NjaWxhw6fDtWVzIGRpw6FyaWFzLiBWYW1vcyBhZGljaW9uYXIgdW0gY2FtcG8gcXVlIGlyw6EgaW5jbHXDrS1sYSwgcG9yIG1laW8gZGUgdW0gZnVuw6fDo28gcXVlIGlyw6Egc29tYXIgb3MgcmVnaXN0cm9zIGRlIG5vdm9zIGNhc29zIG5vcyDDumx0aW1vcyA3IGRpYXMgcGFyYSBjYWRhIHBhw61zIGUgZmF6ZXIgdW0gbcOpZGlhLgoKYGBge3J9CmRmIDwtIGRmICU+JSAgCiAjIEFnb3JhLCB2YW1vcyBhZGljaW9uYXIgdW1hIGNvbHVuYSBjb20gYSBtw6lkaWEgbcOzdmVsIGRhIMO6bHRpbWEgc2VtYW5hcwogIG11dGF0ZShSb2xsX21lYW4gPSByb3VuZCh6b286OnJvbGxtZWFucihOZXdDYXNlcywgNywgZmlsbCA9IE5BKSkpCgpkZgpgYGAKCiMgQ2Fzb3MgcG9yIG1pbGjDo28gZGUgaGFiaXRhbnRlcwpBaW5kYSBxdWUgYWxndW5zIGVzcGVjaWFsaXN0YXMgZGVzZW5jb3JhamFtIG8gdXNvIGRlIHRheGFzIHBvcHVsYWNpb25haXMgcGFyYSBhdmFsaWHDp8OjbyBkYSB0YXhhIGRlIGNvbnTDoWdpbyBub3MgZXN0w6FnaW9zIGluaWNpYWlzIGRlIHVtYSBwYW5kZW1pYSwgcG9pcywgc2VndW5kbyBlbGVzLCBvIG7Dum1lcm8gZGUgcGVzc29hcyBjb250YWdpYWRhcyBwb3IgY2FkYSBpbmZlY3RhZGEgbsOjbyBzZXJpYSBhbHRlcmFkYSBwZWxvIHRhbWFuaG8gZGEgcG9wdWxhw6fDo28sIMOgIG1lZGlkYSBxdWUgYSBlcGlkZW1pYSBwcm9ncmlkZSBlc3RlIG7Dum1lcm8gcGFzc2EgYSBzZXIgw7p0aWwgZSBhdHVhbG1lbnRlIMOpIHV0aWxpemFkbyBpbmNsdXNpdmUgcGVsbyBNaW5pc3TDqXJpbyBkYSBTYcO6ZGUgcGFyYSBhdmFsaWFyIG8gaW1wYWN0by4gQSB0YXhhIMOpIGVzcGVjaWFsbWVudGUgYm9hIG7Do28gc8OzIHBhcmEgY29tcGFyYXIgcG9wdWxhw6fDtWVzIGRlIHRhbWFuaG9zIGRpc3RpbnRvcywgY29tbyB0YW1iw6ltIHBhcmEgYXZhbGlhciBvIGltcGFjdG8gbmEgaW5mcmEtZXN0cnV0dXJhIGRlIHNhw7pkZS4gRW50w6NvLCB2YW1vcyB2ZXIgY29tbyByZWFsaXrDoS1sYS4gCgpQYXJhIHNlIGFwcm9mdW5kYXIgbWFpcyBuZXN0YSBkaXNjdXNzw6NvLCB2aWRlIG8gW2l0ZW0gNC40LjIgZGVzdGUgYXJ0aWdvXShodHRwczovL2dpdGh1Yi5jb20vcGF1bG9odWJlcnQvY292aWRfZGlzY3Vzc2FvL2Jsb2IvbWFzdGVyL2NvbXBhcmFuZG9fcGFpc2VzX2NvdmlkLnBkZikgb3UgZXN0YSBtYXTDqXJpYSBkbyBbVGhlIE5ldyBZb3JrIFRpbWVzXShodHRwczovL3d3dy5ueXRpbWVzLmNvbS9pbnRlcmFjdGl2ZS8yMDIwLzAzLzI3L3Vwc2hvdC9jb3JvbmF2aXJ1cy1uZXcteW9yay1jb21wYXJpc29uLmh0bWwpLgoKQXF1aSwgdmFtb3MgYWRpY2lvbmFyIHVtYSBjb2x1bmEgY29tIGEgcG9wdWxhw6fDo28gZG9zIHBhw61zZXMuIENvbW8gZXN0ZSDDqSBhcGVuYXMgdW0gZXhlbXBsbyBlIHRlbW9zIHPDsyAyIGNhc29zLCBwb2RlbW9zIHVzYXIgdW1hIGNvbmRpY2lvbmFsIHNpbXBsZXMuIFNlIG8gcGHDrXMgZm9yIGEgSXTDoWxpYSwgaW5zZXJpbW9zIGEgcG9wdWxhw6fDo28gZGUgNjAgbWlsaMO1ZXMgKDYwNDgzNTM4KSwgc2UgbsOjbywgZW50w6NvLCBzZXLDoSBkbyBCcmFzaWwsIHF1ZSB0ZW0gcG9wdWxhw6fDo28gZGUgMjExIG1pbGjDtWVzICgyMTEzNzYwNzEpLiBTZSB2b2PDqiBmb3IgZmF6ZXIgZXN0YSBvcGVyYcOnw6NvIGNvbSB2w6FyaW9zIHBhw61zZXMsIGVudMOjbywgw6kgbWVsaG9yIGltcG9ydGFyIHVtYSB0YWJlbGEgY29tIG9zIGRhZG9zIHBvcHVsYWNpb25haXMgZSBjcnV6w6EtbGEgY29tIG9zIGRhZG9zIGRhIENPVklELgoKYGBge3J9CmRmIDwtIGRmICU+JSBtdXRhdGUoUG9wID0gaWZlbHNlKENvdW50cnkuUmVnaW9uID09ICJJdGFseSIsNjA0ODM1MzgsMjExMzc2MDcxKSkgJT4lCiAgIyBVbWEgdmV6IHF1ZSB2b2PDqiBpbnNpcmEgYSBjb2x1bmEgZGUgcG9wdWxhw6fDo28sIG8gY8OhbGN1bG8gZGEgdGF4YSDDqSBzaW1wbGVzCm11dGF0ZSh0YXhhID0gcm91bmQoKFRvdGFsL1BvcCkgKiAxMDAwMDAwKSkKCmRmCmBgYAoKCiMgQsO0bnVzOiBwbG90YW5kbyBvIHJlc3VsdGFkbyBlbSBncsOhZmljbwpFc3RlIG7Do28gw6kgdW0gdHV0b3JpYWwgZGUgdmlzdWFsaXphw6fDo28gZGUgZGFkb3MsIG1hcyBkZXBvaXMgZGUgY2hlZ2FyIGFxdWkgbsOzcyBtZXJlY2Vtb3MgdmVyIG8gcmVzdWx0YWRvIGRvIHRyYWJhbGhvIGVtIHVtIGdyw6FmaWNvLiBFbnTDo28sIHZhbW9zIGzDoSEKCmBgYHtyfQojIFZhbW9zIHVzYXIgbyB0ZW1hIGRhIFRoZSBFY29ub21pc3QgcGFyYSBkZWl4YXIgbyBncsOhZmljbyBib25pdG8gOikKbGlicmFyeShnZ3RoZW1lcykKCiMgUG9kZW1vcyB1c2FyIGEgb3DDp8OjbyBhYmFpeG8gcGFyYSBkZXNhYmlsaXRhciBhIG5vdGHDp8OjbyBjaWVudMOtZmljYSBub3MgbsO6bWVyb3MgZG8gZ3LDoWZpY28Kb3B0aW9ucyhzY2lwZW4gPSA5OSkKCgpncmFmaWNvIDwtIGdncGxvdChkZiwgYWVzKHg9RGF5LHk9Um9sbF9tZWFuLCBncm91cCA9IENvdW50cnkuUmVnaW9uLCBjb2xvdXIgPSBDb3VudHJ5LlJlZ2lvbikpICsgCiAgZ2VvbV9saW5lKCkgKwogIHRoZW1lX2Vjb25vbWlzdF93aGl0ZSgpICsKICBsYWJzKGNhcHRpb24gPSAiR3LDoWZpY28gZWxhYm9yYWRvIGFwZW5hcyBwYXJhIGZpbnMgZGlkw6F0aWNvcyBwZWxhIEVzY29sYSBkZSBEYWRvcyBcbiBEYWRvczogSm9obiBIb3BraW5zIikgKwogICAgbGFicyh4ID0gIkRpYXMiLCB5ID0gIlRvdGFsIGRlIGNhc29zIiwKICAgICAgICAgdGl0bGUgPSAiTcOpZGlhIG3Ds3ZlbCBkZSBub3ZvcyBjYXNvcyByZXBvcnRhZG9zIGRlIENPVklELTE5IikKZ3JhZmljbwpgYGAKCg==