A linguagem R e o RStudio

Prof. Heron OH

02 March, 2024

     Olá, esta é mais uma de um conjunto de práticas em bioinformática desenvolvidas para o curso de Biomedicina da PUC MG. Você pode encontrar as demais práticas aqui.

     Hoje você vai conhercer a linguagem R e o RStudio.

Introdução

Sobre o R e o RStudio

     A linguagem de programação R, criada por Ross Ihaka e Robert Gentleman na Universidade de Auckland, Nova Zelândia, no início dos anos 90, foi concebida inicialmente como uma linguagem e ambiente para análise estatística e gráficosr-project. Inspirada na linguagem S, desenvolvida nos Laboratórios Bell, o R rapidamente ganhou popularidade devido à sua capacidade de realizar complexas manipulações de dados, análises estatísticas e produzir gráficos de alta qualidade. Com o tempo, a comunidade em torno da R cresceu exponencialmente, contribuindo com uma vasta coleção de pacotes para o Comprehensive R Archive Network (CRAN), expandindo assim suas capacidades para além da estatística básica, para áreas como aprendizado de máquina, visualização de dados, análise de séries temporais, bioinformática, entre outras.

     O RStudio, por sua vez, é um ambiente de desenvolvimento integrado (IDE) para R. Lançado em 2011, que facilitou ainda mais o uso da linguagem R, oferecendo uma interface amigável e diversas ferramentas que melhoram a produtividade dos usuários, como editor de código, console, visualização de dados e gestão de pacotes. A popularidade do R e do RStudio na pesquisa científica e na ciência de dados deve-se à sua natureza open-source, permitindo que pesquisadores e cientistas de dados compartilhem facilmente seus códigos e análises, promovendo a reprodutibilidade e a colaboração na pesquisa. Além disso, a capacidade de R em lidar com grandes volumes de dados, realizar análises complexas e produzir visualizações de dados detalhadas torna-a uma ferramenta indispensável em diversas áreas, desde a genética à economia, reforçando sua posição como uma das principais linguagens na ciência de dados e pesquisa científica contemporâneas. O RStudio e as funcionalidades do R podem ser utilizados para diversas outras aplicações. Por exemplo, este site foi criado no RStudio, utilizando o formato R Mark Down .Rmd.

     A facilidade de transformar vetores e tabelas em gráficos é um dos pontos fortes do R. Veja alguns exemplos possíveis nesta galeria de gráficos, a The R Graph Gallery.

     Recentemente o RStudio passou por uma mudança significativa ao adotar o novo nome Posit. Essa alteração simboliza a expansão dos objetivos da empresa, que agora incluem o suporte a outras linguagens de programação além do R, como Python, outra linguagem também muito utilizada na bioinformática. A mudança reflete o desejo da empresa de abraçar uma comunidade de usuários mais ampla, sem abandonar seu compromisso com a linguagem R.

O R e a Bioinformática

     A comunidade de R dedicada à análise de dados biológicos é vasta e ativa, com diversas iniciativas e projetos que visam o desenvolvimento e compartilhamento de softwares de código aberto para análises precisas e repetíveis de dados biológicos. Um dos projetos mais destacados nesse contexto é o Bioconductor, que se propõe a desenvolver e compartilhar softwares de código aberto para bioinformática. O Bioconductor é conhecido por sua abordagem inclusiva e colaborativa, reunindo uma comunidade de desenvolvedores e cientistas de dados engajados em criar soluções bioinformáticas utilizando o R.

     Além disso, o R oferece uma gama de pacotes adicionais que podem ser utilizados para ampliar suas capacidades centrais. Qualquer usuário pode criar ou publiar funções e pacotes para serem utilizados por outros usuários.

     Esses esforços coletivos dentro da comunidade de R enfatizam não apenas o desenvolvimento técnico de ferramentas analíticas, mas também a promoção de uma cultura de colaboração e compartilhamento de conhecimento, o que é crucial para avançar nas pesquisas biológicas e bioinformáticas.

Instalando o R e o RStudio

     Você encontrar os instaladores do R e do RStudio aqui. Uma vez baixados, você deve executar o instalador da ****linguagem R** primeiro, e em seguida o do RStudio. Pode seguir com a instalação padrão sem modificar nada, apenas clicando sim/ok/avançar.

Pimeiro contato com o R

Conhecendo o RStudio

Os painéis do RStudio

     Antes de mais continuarmos, abra um novo script em R. Você pode fazer isso clicando no quadrado branco com um +** branco e verde, no canto superior esquerdo do RStudio, e sem seguida selecionando a opção R script ou clicando em:

File -> New File -> R script

     A interface do RStudio é dividida em quatro painéis principais, cada um desempenhando um papel distinto para melhorar a produtividade e eficiência nas suas tarefas de programação em R:

  • Janela do Console: Localizada no canto inferior esquerdo, o console é onde você pode inserir comandos R diretamente e visualizar suas saídas. É essencialmente o centro de interação do R, mostrando os Resultados das computações ou execuções de código. Você também pode limpar o console usando um ícone de vassoura para melhorar a legibilidade quando ele fica cheio【28†source】.

  • Janela de Código (Source): Normalmente situada no canto superior esquerdo, esta área é o seu espaço de trabalho para editar e gerenciar arquivos, como R scripts, arquivos de texto, entre outros. É onde você pode escrever, editar e executar seus scripts R. Os arquivos abertos aqui aparecem em abas, facilitando a troca entre múltiplos arquivos. Este painel suporta vários tipos de arquivo, incluindo R scripts(.R), RMarkdown (.Rmd), scripts Python (.py) e mais.

  • Janela de Ambiente/Histórico/Conexões/Tutorial: Localizada tipicamente no canto superior direito, este painel é multifuncional. A aba ‘Ambiente’ mostra os conjuntos de dados e variáveis atualmente na memória, ‘Histórico’ registra todos os comandos anteriores, ‘Conexões’ exibe conexões de banco de dados, e ‘Tutorial’ pode guiar você através de recursos de aprendizagem. É um local central para gerenciar os objetos do seu espaço de trabalho e revisar atividades passadas【28†source】【29†source】.

  • Janela de Arquivos/Gráficos/Pacotes/Ajuda/Visualizador: Geralmente localizada no canto inferior direito, este painel versátil permite que você navegue pelos arquivos do seu projeto, visualize gráficos gerados pelos seus R scripts, gerencie pacotes em R, acesse documentação e arquivos de ajuda do R, e veja conteúdo web ou visualizações geradas pelo R. É uma ferramenta essencial para gerenciar recursos, visualizar dados e acessar ajuda quando necessário.

Estes painéis são projetados para trabalhar juntos de forma integrada, fornecendo um ambiente de desenvolvimento abrangente para programação em R. Você pode personalizar o layout de acordo com suas preferências e necessidades de fluxo de trabalho, melhorando sua eficiência em tarefas de análise de dados e desenvolvimento.

Prática

     Vamos ter o nosso primeiro contato com o R

##                 Introdução à introdução ao **R** e ao **RStudio**                  ##
##                                                                            ##
##                             Prof. Heron Hilário                            ##
####                               março/2024                               ####
##                                                                            ##
#_______________________________________________________________________________

## 0 - **RStudio**! ----
#        0a - Console/Terminal

#        0b - Source (arquivos abertos, variáveis, tabelas)

#        0c - Global environment/...

#        0d - Files/Plots/Help/...

# Tools -> Global Options (tudo pode ser configurável)

## 1 - a **linguagem **R**  ----
#          <-              atribuir o que está na esquerda ao que está na direita   
 
#       function()         executar a função "function" no que está dentro do ()

#        %>% ou |>         pipe!  este é o pipe (|) do **R**   (dplyr)

#      ?function()         abrir o manual/documentação da função  (ou, aperte F1
#                          com o cursor na função)

## 0f - atalhos!

#             ctrl  +    ENTER               Executar linha com o cursor ou pró-
#                                            ximo bloco de código
#             ctrl  +    s                   salvar
#             tab                            autocompleta coisas existentes
#             ctrl  +    d                   deletar a linha com o cursor/
#                                            selecionada
#             ctrl  +  shift +  c            comentar/descomentar a linha com o 
#                                            cursor/selecionada
#             ctrl  +  shift +  d            duplicar a linha com o cursor/
#                                            selecionada
#             ctrl  +  setas(l/r)            caminhar pelas palavras
#             ctrl  +  shift + setas(l/r)    caminhar pelas palavras
#             ctrl  +  alt   + setas(u/d)    caminhar pelas palavras
#             ctrl  +  z                     desfazer
#             ,   ou  \   ou  +              continua na próxima linha

Você pode encontrar a lista de todos os atalhos do RStudio aqui.

Primeiro contato

     Como você pode ver, existem diversas configurações e formatos de saída possíveis. Vamos aprender a fazer uma busca simples. Para isto você precisa de:

  • Uma ou alguamas sequências a serem buscadas, no formato fasta, que chamamos de query;

Copie todo o conteúdo a seguir para o seu R script. Coloque o cursor (esta barra | que pisca onde você está digitando) na primeira linha. Aperte ctrl + ENTER para executar a instrução escrita nessa linha, ou na próxima ativa

DICA: Linhas que começam com **#** são ignoradas pelo computador. Servem apenas para os humanos. Você pode inserir comentários em qualquer parte do código, e escrever lembretes ou explicações que podem te ajudar a estudar, ou ajudar futuros usuários a entender como o código funciona.

# neste código vamos criar objetos e tabelas

# objetos ----
## criar objeto a ----
# este comando cria um objeto objA

objA <- 3
# objA <- 238
# objA <- c(238, 55, 10)
# objA <- c(238, 55, 10, 3, 28, -1, 0.33)

objA

## criar objeto objB ----
objB <- 35

objB

## operações matemáticas com os objetos ---

objA*objB
## criar o objeto objD ----
objD <- objA*objB
objD


## testando funções ----
mean(objD)
max(objD)
min(objD)
sum(objD)


######-> repita todos os passos anteriores com diferentes valores armazenados no objA


# trabalhando com tabelas ----

# vamos criar uma tabela com a função data.frame()
tabela <- data.frame(antes = c(130, 100, 90,150,130,120),
                     depois = c(56,  88, 32, 28, 40, 20),
                     controle = c(0,  5,  2,  1,  5,  1))

tabela$antes
tabela$depois


# gráficos ----
## o mais simples ----

# veja o poder do R, de uma tabela a um gráfico em uma linha!

boxplot(tabela)






## outras possibilidades


# fazer um grafico customizável com o ggplot ---- 
install.packages("ggplot2") # este só precisa ser executado uma vez!

library(ggplot2)


tabela
stack(tabela1)

ggplot(stack(tabela1),
       aes(x = ind,
           y = values,
           fill = ind,
           # col = ind 
           )) +
         geom_boxplot() +
  geom_point()+
  scale_fill_manual(values = c("#ab3310","#2000b0"))+
  theme_bw()

Voltar para a página inicial

LS0tCnRpdGxlOiAiQSAqKmxpbmd1YWdlbSBSKiogZSBvICoqUlN0dWRpbyoqIgphdXRob3I6ICJQcm9mLiBIZXJvbiBPSCIKcGxhY2U6ICJCaW9tZWRpY2luYSAtIFBVQyBNaW5hcyIKZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJUIsICVZJylgIgpvdXRwdXQ6IAogIHJtZGZvcm1hdHM6OmRvd25jdXRlOgogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogICAgdG9jX2RlcHRoOiA1CiAgICB0b2NfZmxvYXQ6IHllcwogICAgaGlnaGxpZ2h0OiB6ZW5idXJuCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgpgYGB7ciBjb2xvciwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9CiNjb25maWd1cmFyIHByb3MgKipSKiplc3VsdGFkb3MgZG8gYmFzaCBzYWlyZW0gY29sb3JpZG9zIGUgbsOjbyBBTlNJCgpvbGRfaG9va3MgPC0gZmFuc2k6OnNldF9rbml0X2hvb2tzKAogIGtuaXRyOjprbml0X2hvb2tzLCAKICB3aGljaCA9IGMoIm91dHB1dCIsICJtZXNzYWdlIiwgImVycm9yIikKKQpgYGAKCjxzdHlsZT4KYm9keSB7CnRleHQtYWxpZ246IGp1c3RpZnl9Cjwvc3R5bGU+Cgo8c3R5bGU+CiN0b2MgdWwubmF2IGxpIHVsIGxpIHsKICAgIGRpc3BsYXk6IG5vbmU7CiAgICBtYXgtaGVpZ2h0OiBub25lOwp9CgojdG9jIHVsLm5hdiBsaS5hY3RpdmUgdWwgbGkgIHsKICAgIGRpc3BsYXk6IGJsb2NrOwogICAgbWF4LWhlaWdodDogbm9uZTsKfQoKI3RvYyB1bC5uYXYgbGkgdWwgbGkgdWwgbGkgewogICAgbWF4LWhlaWdodDogbm9uZTsKICAgIGRpc3BsYXk6IG5vbmUgIWltcG9ydGFudDsKfQoKI3RvYyB1bC5uYXYgbGkgdWwgbGkuYWN0aXZlIHVsIGxpIHsKICAgIG1heC1oZWlnaHQ6IG5vbmU7CiAgICBkaXNwbGF5OiBibG9jayAhaW1wb3J0YW50Owp9Cjwvc3R5bGU+CgoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Ck9sw6EsIGVzdGEgw6kgbWFpcyB1bWEgZGUgdW0gY29uanVudG8gZGUgcHLDoXRpY2FzIGVtIGJpb2luZm9ybcOhdGljYSBkZXNlbnZvbHZpZGFzIHBhcmEgbyBjdXJzbyBkZSBCaW9tZWRpY2luYSBkYSBQVUMgTUcuClZvY8OqIHBvZGUgZW5jb250cmFyIGFzIGRlbWFpcyBwcsOhdGljYXMgWyphcXVpKl0oaHR0cHM6Ly9oZXJvbm9oLmdpdGh1Yi5pby9iaW9pbmZvKS4KCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpIb2plIHZvY8OqIHZhaSBjb25oZXJjZXIgYSAqKmxpbmd1YWdlbSBSKiogZSBvICoqUlN0dWRpbyoqLiAKCgojIEludHJvZHXDp8OjbwoKIyMgU29icmUgbyAqKlIqKiBlIG8gKipSU3R1ZGlvKioKCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpBICoqbGluZ3VhZ2VtIGRlIHByb2dyYW1hw6fDo28gUioqLCBjcmlhZGEgcG9yICpSb3NzIEloYWthKiBlICpSb2JlcnQgR2VudGxlbWFuKiBuYSAqVW5pdmVyc2lkYWRlIGRlIEF1Y2tsYW5kKiwgTm92YSBaZWzDom5kaWEsIG5vIGluw61jaW8gZG9zIGFub3MgOTAsIGZvaSBjb25jZWJpZGEgaW5pY2lhbG1lbnRlIGNvbW8gdW1hIGxpbmd1YWdlbSBlIGFtYmllbnRlIHBhcmEgYW7DoWxpc2UgZXN0YXTDrXN0aWNhIGUgZ3LDoWZpY29zW3ItcHJvamVjdF0oaHR0cHM6Ly93d3cuci1wcm9qZWN0Lm9yZy9hYm91dC5odG1sKS4gSW5zcGlyYWRhIG5hICpsaW5ndWFnZW0gUyosIGRlc2Vudm9sdmlkYSBub3MgTGFib3JhdMOzcmlvcyBCZWxsLCBvICoqUioqIHJhcGlkYW1lbnRlIGdhbmhvdSBwb3B1bGFyaWRhZGUgZGV2aWRvIMOgIHN1YSBjYXBhY2lkYWRlIGRlIHJlYWxpemFyIGNvbXBsZXhhcyBtYW5pcHVsYcOnw7VlcyBkZSBkYWRvcywgYW7DoWxpc2VzIGVzdGF0w61zdGljYXMgZSBwcm9kdXppciBncsOhZmljb3MgZGUgYWx0YSBxdWFsaWRhZGUuIENvbSBvIHRlbXBvLCBhIGNvbXVuaWRhZGUgZW0gdG9ybm8gZGEgKipSKiogY3Jlc2NldSBleHBvbmVuY2lhbG1lbnRlLCBjb250cmlidWluZG8gY29tIHVtYSB2YXN0YSBjb2xlw6fDo28gZGUgcGFjb3RlcyBwYXJhIG8gWyoqQ29tcHJlaGVuc2l2ZSBSIEFyY2hpdmUgTmV0d29yayAoQ1JBTikqKl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvKSwgZXhwYW5kaW5kbyBhc3NpbSBzdWFzIGNhcGFjaWRhZGVzIHBhcmEgYWzDqW0gZGEgZXN0YXTDrXN0aWNhIGLDoXNpY2EsIHBhcmEgw6FyZWFzIGNvbW8gYXByZW5kaXphZG8gZGUgbcOhcXVpbmEsIHZpc3VhbGl6YcOnw6NvIGRlIGRhZG9zLCBhbsOhbGlzZSBkZSBzw6lyaWVzIHRlbXBvcmFpcywgYmlvaW5mb3Jtw6F0aWNhLCBlbnRyZSBvdXRyYXMuCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKTyAqKlJTdHVkaW8qKiwgcG9yIHN1YSB2ZXosIMOpIHVtIGFtYmllbnRlIGRlIGRlc2Vudm9sdmltZW50byBpbnRlZ3JhZG8gKElERSkgcGFyYSAqKlIqKi4gTGFuw6dhZG8gZW0gMjAxMSwgcXVlIGZhY2lsaXRvdSBhaW5kYSBtYWlzIG8gdXNvIGRhICoqbGluZ3VhZ2VtIFIqKiwgb2ZlcmVjZW5kbyB1bWEgaW50ZXJmYWNlIGFtaWfDoXZlbCBlIGRpdmVyc2FzIGZlcnJhbWVudGFzIHF1ZSBtZWxob3JhbSBhIHByb2R1dGl2aWRhZGUgZG9zIHVzdcOhcmlvcywgY29tbyBlZGl0b3IgZGUgY8OzZGlnbywgY29uc29sZSwgdmlzdWFsaXphw6fDo28gZGUgZGFkb3MgZSBnZXN0w6NvIGRlIHBhY290ZXMuIEEgcG9wdWxhcmlkYWRlIGRvICoqUioqIGUgZG8gKipSU3R1ZGlvKiogbmEgcGVzcXVpc2EgY2llbnTDrWZpY2EgZSBuYSBjacOqbmNpYSBkZSBkYWRvcyBkZXZlLXNlIMOgIHN1YSBuYXR1cmV6YSBfb3Blbi1zb3VyY2VfLCBwZXJtaXRpbmRvIHF1ZSBwZXNxdWlzYWRvcmVzIGUgY2llbnRpc3RhcyBkZSBkYWRvcyBjb21wYXJ0aWxoZW0gZmFjaWxtZW50ZSBzZXVzIGPDs2RpZ29zIGUgYW7DoWxpc2VzLCBwcm9tb3ZlbmRvIGEgcmVwcm9kdXRpYmlsaWRhZGUgZSBhIGNvbGFib3Jhw6fDo28gbmEgcGVzcXVpc2EuIEFsw6ltIGRpc3NvLCBhIGNhcGFjaWRhZGUgZGUgKipSKiogZW0gbGlkYXIgY29tIGdyYW5kZXMgdm9sdW1lcyBkZSBkYWRvcywgcmVhbGl6YXIgYW7DoWxpc2VzIGNvbXBsZXhhcyBlIHByb2R1emlyIHZpc3VhbGl6YcOnw7VlcyBkZSBkYWRvcyBkZXRhbGhhZGFzIHRvcm5hLWEgdW1hIGZlcnJhbWVudGEgaW5kaXNwZW5zw6F2ZWwgZW0gZGl2ZXJzYXMgw6FyZWFzLCBkZXNkZSBhIGdlbsOpdGljYSDDoCBlY29ub21pYSwgcmVmb3LDp2FuZG8gc3VhIHBvc2nDp8OjbyBjb21vIHVtYSBkYXMgcHJpbmNpcGFpcyBsaW5ndWFnZW5zIG5hIGNpw6puY2lhIGRlIGRhZG9zIGUgcGVzcXVpc2EgY2llbnTDrWZpY2EgY29udGVtcG9yw6JuZWFzLiBPICoqUlN0dWRpbyoqIGUgYXMgZnVuY2lvbmFsaWRhZGVzIGRvICoqUioqIHBvZGVtIHNlciB1dGlsaXphZG9zIHBhcmEgZGl2ZXJzYXMgb3V0cmFzIGFwbGljYcOnw7Vlcy4gUG9yIGV4ZW1wbG8sIGVzdGUgc2l0ZSBmb2kgY3JpYWRvIG5vICoqUlN0dWRpbyoqLCB1dGlsaXphbmRvIG8gZm9ybWF0byAqKlIgTWFyayBEb3duKiogWyoqLlJtZCoqXShodHRwczovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbS8pLgoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7CkEgZmFjaWxpZGFkZSBkZSB0cmFuc2Zvcm1hciB2ZXRvcmVzIGUgdGFiZWxhcyBlbSBncsOhZmljb3Mgw6kgdW0gZG9zIHBvbnRvcyBmb3J0ZXMgZG8gKipSKiouIFZlamEgYWxndW5zIGV4ZW1wbG9zIHBvc3PDrXZlaXMgbmVzdGEgZ2FsZXJpYSBkZSBncsOhZmljb3MsIGEgWypUaGUgUiBHcmFwaCBHYWxsZXJ5Kl0oaHR0cHM6Ly9yLWdyYXBoLWdhbGxlcnkuY29tLykuCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKUmVjZW50ZW1lbnRlIG8gKipSU3R1ZGlvKiogcGFzc291IHBvciB1bWEgbXVkYW7Dp2Egc2lnbmlmaWNhdGl2YSBhbyBhZG90YXIgbyBub3ZvIG5vbWUgWyoqUG9zaXQqKl0oaHR0cHM6Ly9wb3NpdC5jby9ibG9nL3JzdHVkaW8taXMtbm93LXBvc2l0LykuIEVzc2EgYWx0ZXJhw6fDo28gc2ltYm9saXphIGEgZXhwYW5zw6NvIGRvcyBvYmpldGl2b3MgZGEgZW1wcmVzYSwgcXVlIGFnb3JhIGluY2x1ZW0gbyBzdXBvcnRlIGEgb3V0cmFzIGxpbmd1YWdlbnMgZGUgcHJvZ3JhbWHDp8OjbyBhbMOpbSBkbyAqKlIqKiwgY29tbyBbKipQeXRob24qKl0oaHR0cHM6Ly93d3cucHl0aG9uLm9yZy8pLCBvdXRyYSBsaW5ndWFnZW0gdGFtYsOpbSBtdWl0byB1dGlsaXphZGEgbmEgYmlvaW5mb3Jtw6F0aWNhLiBBIG11ZGFuw6dhIHJlZmxldGUgbyBkZXNlam8gZGEgZW1wcmVzYSBkZSBhYnJhw6dhciB1bWEgY29tdW5pZGFkZSBkZSB1c3XDoXJpb3MgbWFpcyBhbXBsYSwgc2VtIGFiYW5kb25hciBzZXUgY29tcHJvbWlzc28gY29tIGEgKipsaW5ndWFnZW0gUioqLgoKIyMgTyAqKlIqKiBlIGEgKipCaW9pbmZvcm3DoXRpY2EqKgoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7CkEgY29tdW5pZGFkZSBkZSAqKlIqKiBkZWRpY2FkYSDDoCBhbsOhbGlzZSBkZSBkYWRvcyBiaW9sw7NnaWNvcyDDqSB2YXN0YSBlIGF0aXZhLCBjb20gZGl2ZXJzYXMgaW5pY2lhdGl2YXMgZSBwcm9qZXRvcyBxdWUgdmlzYW0gbyBkZXNlbnZvbHZpbWVudG8gZSBjb21wYXJ0aWxoYW1lbnRvIGRlIHNvZnR3YXJlcyBkZSBjw7NkaWdvIGFiZXJ0byBwYXJhIGFuw6FsaXNlcyBwcmVjaXNhcyBlIHJlcGV0w612ZWlzIGRlIGRhZG9zIGJpb2zDs2dpY29zLiBVbSBkb3MgcHJvamV0b3MgbWFpcyBkZXN0YWNhZG9zIG5lc3NlIGNvbnRleHRvIMOpIG8gQmlvY29uZHVjdG9yLCBxdWUgc2UgcHJvcMO1ZSBhIGRlc2Vudm9sdmVyIGUgY29tcGFydGlsaGFyIHNvZnR3YXJlcyBkZSBjw7NkaWdvIGFiZXJ0byBwYXJhIGJpb2luZm9ybcOhdGljYS4gTyAqKkJpb2NvbmR1Y3RvcioqIMOpIGNvbmhlY2lkbyBwb3Igc3VhIGFib3JkYWdlbSBpbmNsdXNpdmEgZSBjb2xhYm9yYXRpdmEsIHJldW5pbmRvIHVtYSBjb211bmlkYWRlIGRlIGRlc2Vudm9sdmVkb3JlcyBlIGNpZW50aXN0YXMgZGUgZGFkb3MgZW5nYWphZG9zIGVtIGNyaWFyIHNvbHXDp8O1ZXMgYmlvaW5mb3Jtw6F0aWNhcyB1dGlsaXphbmRvIG8gKipSKiouCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKQWzDqW0gZGlzc28sIG8gKipSKiogb2ZlcmVjZSB1bWEgZ2FtYSBkZSBwYWNvdGVzIGFkaWNpb25haXMgcXVlIHBvZGVtIHNlciB1dGlsaXphZG9zIHBhcmEgYW1wbGlhciBzdWFzIGNhcGFjaWRhZGVzIGNlbnRyYWlzLiBRdWFscXVlciB1c3XDoXJpbyBwb2RlIGNyaWFyIG91IHB1YmxpYXIgZnVuw6fDtWVzIGUgcGFjb3RlcyBwYXJhIHNlcmVtIHV0aWxpemFkb3MgcG9yIG91dHJvcyB1c3XDoXJpb3MuCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKRXNzZXMgZXNmb3LDp29zIGNvbGV0aXZvcyBkZW50cm8gZGEgY29tdW5pZGFkZSBkZSAqKlIqKiBlbmZhdGl6YW0gbsOjbyBhcGVuYXMgbyBkZXNlbnZvbHZpbWVudG8gdMOpY25pY28gZGUgZmVycmFtZW50YXMgYW5hbMOtdGljYXMsIG1hcyB0YW1iw6ltIGEgcHJvbW/Dp8OjbyBkZSB1bWEgY3VsdHVyYSBkZSBjb2xhYm9yYcOnw6NvIGUgY29tcGFydGlsaGFtZW50byBkZSBjb25oZWNpbWVudG8sIG8gcXVlIMOpIGNydWNpYWwgcGFyYSBhdmFuw6dhciBuYXMgcGVzcXVpc2FzIGJpb2zDs2dpY2FzIGUgYmlvaW5mb3Jtw6F0aWNhcy4KCgoKIyMgSW5zdGFsYW5kbyBvICoqUioqIGUgbyAqKlJTdHVkaW8qKgoKJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7ClZvY8OqIGVuY29udHJhciBvcyBpbnN0YWxhZG9yZXMgZG8gKipSKiogZSBkbyAqKlJTdHVkaW8qKiBbKmFxdWkqXShodHRwczovL3Bvc2l0LmNvL2Rvd25sb2FkL3JzdHVkaW8tZGVza3RvcC8pLiBVbWEgdmV6IGJhaXhhZG9zLCB2b2PDqiBkZXZlCmV4ZWN1dGFyIG8gaW5zdGFsYWRvciBkYSAqKioqbGluZ3VhZ2VtICoqUioqKiogX3ByaW1laXJvXywgZSBlbSBzZWd1aWRhIG8gZG8gKipSU3R1ZGlvKiouIFBvZGUgc2VndWlyIGNvbSBhIGluc3RhbGHDp8OjbyBwYWRyw6NvIHNlbSBtb2RpZmljYXIgbmFkYSwgYXBlbmFzIGNsaWNhbmRvIF9zaW0vb2svYXZhbsOnYXJfLgoKIyMgUGltZWlybyBjb250YXRvIGNvbSBvICoqUioqCgojIyMgQ29uaGVjZW5kbyBvICoqUlN0dWRpbyoqCgojIyMjIE9zIHBhaW7DqWlzIGRvICoqUlN0dWRpbyoqCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKQW50ZXMgZGUgbWFpcyBjb250aW51YXJtb3MsIGFicmEgdW0gbm92byAqKnNjcmlwdCBlbSAqKlIqKi4gVm9jw6ogcG9kZSBmYXplciBpc3NvIGNsaWNhbmRvIG5vIHF1YWRyYWRvIGJyYW5jbyBjb20gdW0gKiorKiogYnJhbmNvIGUgdmVyZGUsIG5vIGNhbnRvIHN1cGVyaW9yIGVzcXVlcmRvIGRvICoqUlN0dWRpbyoqLCBlIHNlbSBzZWd1aWRhIHNlbGVjaW9uYW5kbyBhIG9ww6fDo28gYFIgc2NyaXB0YCBvdSBjbGljYW5kbyBlbToKCj4gYEZpbGVgICoqLT4qKiBgTmV3IEZpbGVgICoqLT4qKiBgUiBzY3JpcHRgCgombmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsKQSBpbnRlcmZhY2UgZG8gKipSU3R1ZGlvKiogw6kgZGl2aWRpZGEgZW0gcXVhdHJvIHBhaW7DqWlzIHByaW5jaXBhaXMsIGNhZGEgdW0gZGVzZW1wZW5oYW5kbyB1bSBwYXBlbCBkaXN0aW50byBwYXJhIG1lbGhvcmFyIGEgcHJvZHV0aXZpZGFkZSBlIGVmaWNpw6puY2lhIG5hcyBzdWFzIHRhcmVmYXMgZGUgcHJvZ3JhbWHDp8OjbyBlbSAqKlIqKjoKCiAgKiAqKkphbmVsYSBkbyBDb25zb2xlKio6IExvY2FsaXphZGEgbm8gY2FudG8gaW5mZXJpb3IgZXNxdWVyZG8sIG8gX2NvbnNvbGVfIMOpIG9uZGUgdm9jw6ogcG9kZSBpbnNlcmlyIGNvbWFuZG9zICoqUioqIGRpcmV0YW1lbnRlIGUgdmlzdWFsaXphciBzdWFzIHNhw61kYXMuIMOJIGVzc2VuY2lhbG1lbnRlIG8gY2VudHJvIGRlIGludGVyYcOnw6NvIGRvICoqUioqLCBtb3N0cmFuZG8gb3MgKipSKiplc3VsdGFkb3MgZGFzIGNvbXB1dGHDp8O1ZXMgb3UgZXhlY3XDp8O1ZXMgZGUgY8OzZGlnby4gVm9jw6ogdGFtYsOpbSBwb2RlIGxpbXBhciBvIGNvbnNvbGUgdXNhbmRvIHVtIMOtY29uZSBkZSB2YXNzb3VyYSBwYXJhIG1lbGhvcmFyIGEgbGVnaWJpbGlkYWRlIHF1YW5kbyBlbGUgZmljYSBjaGVpb+OAkDI44oCgc291cmNl44CRLgoKICAqICoqSmFuZWxhIGRlIEPDs2RpZ28gKFNvdXJjZSkqKjogTm9ybWFsbWVudGUgc2l0dWFkYSBubyBjYW50byBzdXBlcmlvciBlc3F1ZXJkbywgZXN0YSDDoXJlYSDDqSBvIHNldSBlc3Bhw6dvIGRlIHRyYWJhbGhvIHBhcmEgZWRpdGFyIGUgZ2VyZW5jaWFyIGFycXVpdm9zLCBjb21vICoqUiBzY3JpcHRzKiosIGFycXVpdm9zIGRlIHRleHRvLCBlbnRyZSBvdXRyb3MuIMOJIG9uZGUgdm9jw6ogcG9kZSBlc2NyZXZlciwgZWRpdGFyIGUgZXhlY3V0YXIgc2V1cyBzY3JpcHRzICoqUioqLiBPcyBhcnF1aXZvcyBhYmVydG9zIGFxdWkgYXBhcmVjZW0gZW0gYWJhcywgZmFjaWxpdGFuZG8gYSB0cm9jYSBlbnRyZSBtw7psdGlwbG9zIGFycXVpdm9zLiBFc3RlIHBhaW5lbCBzdXBvcnRhIHbDoXJpb3MgdGlwb3MgZGUgYXJxdWl2bywgaW5jbHVpbmRvICAqKlIgc2NyaXB0cyoqKC5SKSwgKipSTWFya2Rvd24qKiAoLlJtZCksIHNjcmlwdHMgKipQeXRob24qKiAoLnB5KSBlIG1haXMuCgogICogKipKYW5lbGEgZGUgQW1iaWVudGUvSGlzdMOzcmljby9Db25leMO1ZXMvVHV0b3JpYWwqKjogTG9jYWxpemFkYSB0aXBpY2FtZW50ZSBubyBjYW50byBzdXBlcmlvciBkaXJlaXRvLCBlc3RlIHBhaW5lbCDDqSBtdWx0aWZ1bmNpb25hbC4gQSBhYmEgJ0FtYmllbnRlJyBtb3N0cmEgb3MgY29uanVudG9zIGRlIGRhZG9zIGUgdmFyacOhdmVpcyBhdHVhbG1lbnRlIG5hIG1lbcOzcmlhLCAnSGlzdMOzcmljbycgcmVnaXN0cmEgdG9kb3Mgb3MgY29tYW5kb3MgYW50ZXJpb3JlcywgJ0NvbmV4w7VlcycgZXhpYmUgY29uZXjDtWVzIGRlIGJhbmNvIGRlIGRhZG9zLCBlICdUdXRvcmlhbCcgcG9kZSBndWlhciB2b2PDqiBhdHJhdsOpcyBkZSByZWN1cnNvcyBkZSBhcHJlbmRpemFnZW0uIMOJIHVtIGxvY2FsIGNlbnRyYWwgcGFyYSBnZXJlbmNpYXIgb3Mgb2JqZXRvcyBkbyBzZXUgZXNwYcOnbyBkZSB0cmFiYWxobyBlIHJldmlzYXIgYXRpdmlkYWRlcyBwYXNzYWRhc+OAkDI44oCgc291cmNl44CR44CQMjnigKBzb3VyY2XjgJEuCgogICogKipKYW5lbGEgZGUgQXJxdWl2b3MvR3LDoWZpY29zL1BhY290ZXMvQWp1ZGEvVmlzdWFsaXphZG9yKio6IEdlcmFsbWVudGUgbG9jYWxpemFkYSBubyBjYW50byBpbmZlcmlvciBkaXJlaXRvLCBlc3RlIHBhaW5lbCB2ZXJzw6F0aWwgcGVybWl0ZSBxdWUgdm9jw6ogbmF2ZWd1ZSBwZWxvcyBhcnF1aXZvcyBkbyBzZXUgcHJvamV0bywgdmlzdWFsaXplIGdyw6FmaWNvcyBnZXJhZG9zIHBlbG9zIHNldXMgICoqUiBzY3JpcHRzKiosIGdlcmVuY2llIHBhY290ZXMgZW0gKipSKiosIGFjZXNzZSBkb2N1bWVudGHDp8OjbyBlIGFycXVpdm9zIGRlIGFqdWRhIGRvICoqUioqLCBlIHZlamEgY29udGXDumRvIHdlYiBvdSB2aXN1YWxpemHDp8O1ZXMgZ2VyYWRhcyBwZWxvICoqUioqLiDDiSB1bWEgZmVycmFtZW50YSBlc3NlbmNpYWwgcGFyYSBnZXJlbmNpYXIgcmVjdXJzb3MsIHZpc3VhbGl6YXIgZGFkb3MgZSBhY2Vzc2FyIGFqdWRhIHF1YW5kbyBuZWNlc3PDoXJpby4KCkVzdGVzIHBhaW7DqWlzIHPDo28gcHJvamV0YWRvcyBwYXJhIHRyYWJhbGhhciBqdW50b3MgZGUgZm9ybWEgaW50ZWdyYWRhLCBmb3JuZWNlbmRvIHVtIGFtYmllbnRlIGRlIGRlc2Vudm9sdmltZW50byBhYnJhbmdlbnRlIHBhcmEgcHJvZ3JhbWHDp8OjbyBlbSAqKlIqKi4gVm9jw6ogcG9kZSBwZXJzb25hbGl6YXIgbyAqbGF5b3V0KiBkZSBhY29yZG8gY29tIHN1YXMgcHJlZmVyw6puY2lhcyBlIG5lY2Vzc2lkYWRlcyBkZSBmbHV4byBkZSB0cmFiYWxobywgbWVsaG9yYW5kbyBzdWEgZWZpY2nDqm5jaWEgZW0gdGFyZWZhcyBkZSBhbsOhbGlzZSBkZSBkYWRvcyBlIGRlc2Vudm9sdmltZW50by4KCgoKCiMgUHLDoXRpY2EKCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpWYW1vcyB0ZXIgbyBub3NzbyBwcmltZWlybyBjb250YXRvIGNvbSBvIFIKCmBgYHtSLCBlY2hvPVRSVUUsZXZhbD1GQUxTRX0KIyMgICAgICAgICAgICAgICAgIEludHJvZHXDp8OjbyDDoCBpbnRyb2R1w6fDo28gYW8gKipSKiogZSBhbyAqKlJTdHVkaW8qKiAgICAgICAgICAgICAgICAgICMjCiMjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMjCiMjICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQcm9mLiBIZXJvbiBIaWzDoXJpbyAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIwojIyMjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcsOnby8yMDI0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMjIyMKIyMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyMKI19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KCiMjIDAgLSAqKlJTdHVkaW8qKiEgLS0tLQojICAgICAgICAwYSAtIENvbnNvbGUvVGVybWluYWwKCiMgICAgICAgIDBiIC0gU291cmNlIChhcnF1aXZvcyBhYmVydG9zLCB2YXJpw6F2ZWlzLCB0YWJlbGFzKQoKIyAgICAgICAgMGMgLSBHbG9iYWwgZW52aXJvbm1lbnQvLi4uCgojICAgICAgICAwZCAtIEZpbGVzL1Bsb3RzL0hlbHAvLi4uCgojIFRvb2xzIC0+IEdsb2JhbCBPcHRpb25zICh0dWRvIHBvZGUgc2VyIGNvbmZpZ3Vyw6F2ZWwpCgojIyAxIC0gYSAqKmxpbmd1YWdlbSAqKlIqKiAgLS0tLQojICAgICAgICAgIDwtICAgICAgICAgICAgICBhdHJpYnVpciBvIHF1ZSBlc3TDoSBuYSBlc3F1ZXJkYSBhbyBxdWUgZXN0w6EgbmEgZGlyZWl0YSAgIAogCiMgICAgICAgZnVuY3Rpb24oKSAgICAgICAgIGV4ZWN1dGFyIGEgZnVuw6fDo28gImZ1bmN0aW9uIiBubyBxdWUgZXN0w6EgZGVudHJvIGRvICgpCgojICAgICAgICAlPiUgb3UgfD4gICAgICAgICBwaXBlISAgZXN0ZSDDqSBvIHBpcGUgKHwpIGRvICoqUioqICAgKGRwbHlyKQoKIyAgICAgID9mdW5jdGlvbigpICAgICAgICAgYWJyaXIgbyBtYW51YWwvZG9jdW1lbnRhw6fDo28gZGEgZnVuw6fDo28gIChvdSwgYXBlcnRlIEYxCiMgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbSBvIGN1cnNvciBuYSBmdW7Dp8OjbykKCiMjIDBmIC0gYXRhbGhvcyEKCiMgICAgICAgICAgICAgY3RybCAgKyAgICBFTlRFUiAgICAgICAgICAgICAgIEV4ZWN1dGFyIGxpbmhhIGNvbSBvIGN1cnNvciBvdSBwcsOzLQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4aW1vIGJsb2NvIGRlIGPDs2RpZ28KIyAgICAgICAgICAgICBjdHJsICArICAgIHMgICAgICAgICAgICAgICAgICAgc2FsdmFyCiMgICAgICAgICAgICAgdGFiICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9jb21wbGV0YSBjb2lzYXMgZXhpc3RlbnRlcwojICAgICAgICAgICAgIGN0cmwgICsgICAgZCAgICAgICAgICAgICAgICAgICBkZWxldGFyIGEgbGluaGEgY29tIG8gY3Vyc29yLwojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY2lvbmFkYQojICAgICAgICAgICAgIGN0cmwgICsgIHNoaWZ0ICsgIGMgICAgICAgICAgICBjb21lbnRhci9kZXNjb21lbnRhciBhIGxpbmhhIGNvbSBvIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJzb3Ivc2VsZWNpb25hZGEKIyAgICAgICAgICAgICBjdHJsICArICBzaGlmdCArICBkICAgICAgICAgICAgZHVwbGljYXIgYSBsaW5oYSBjb20gbyBjdXJzb3IvCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjaW9uYWRhCiMgICAgICAgICAgICAgY3RybCAgKyAgc2V0YXMobC9yKSAgICAgICAgICAgIGNhbWluaGFyIHBlbGFzIHBhbGF2cmFzCiMgICAgICAgICAgICAgY3RybCAgKyAgc2hpZnQgKyBzZXRhcyhsL3IpICAgIGNhbWluaGFyIHBlbGFzIHBhbGF2cmFzCiMgICAgICAgICAgICAgY3RybCAgKyAgYWx0ICAgKyBzZXRhcyh1L2QpICAgIGNhbWluaGFyIHBlbGFzIHBhbGF2cmFzCiMgICAgICAgICAgICAgY3RybCAgKyAgeiAgICAgICAgICAgICAgICAgICAgIGRlc2ZhemVyCiMgICAgICAgICAgICAgLCAgIG91ICBcICAgb3UgICsgICAgICAgICAgICAgIGNvbnRpbnVhIG5hIHByw7N4aW1hIGxpbmhhCgoKYGBgCgpWb2PDqiBwb2RlIGVuY29udHJhciBhIGxpc3RhIGRlIHRvZG9zIG9zIGF0YWxob3MgZG8gKipSU3R1ZGlvKiogWyoqYXF1aSoqXShodHRwczovL3N1cHBvcnQucG9zaXQuY28vaGMvZW4tdXMvYXJ0aWNsZXMvMjAwNzExODUzLUtleWJvYXJkLVNob3J0Y3V0cy1pbi10aGUtUlN0dWRpby1JREUpLgoKIyMjIFByaW1laXJvIGNvbnRhdG8KCiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOwpDb21vIHZvY8OqIHBvZGUgdmVyLCBleGlzdGVtIGRpdmVyc2FzIGNvbmZpZ3VyYcOnw7VlcyBlIGZvcm1hdG9zIGRlIHNhw61kYSBwb3Nzw612ZWlzLiBWYW1vcyBhcHJlbmRlciBhIGZhemVyIHVtYSBidXNjYSBzaW1wbGVzLiBQYXJhIGlzdG8gdm9jw6ogcHJlY2lzYSBkZToKCiAtIFVtYSBvdSBhbGd1YW1hcyBzZXF1w6puY2lhcyBhIHNlcmVtIGJ1c2NhZGFzLCBubyBmb3JtYXRvIGZhc3RhLCBxdWUgY2hhbWFtb3MgZGUgKioqcXVlcnkqKio7CiAKCgo+IENvcGllIHRvZG8gbyBjb250ZcO6ZG8gYSBzZWd1aXIgcGFyYSBvIHNldSAqKlIgc2NyaXB0KiouIENvbG9xdWUgbyBjdXJzb3IgKGVzdGEgYmFycmEgfCBxdWUgcGlzY2Egb25kZSB2b2PDqiBlc3TDoSBkaWdpdGFuZG8pIG5hIHByaW1laXJhIGxpbmhhLiBBcGVydGUgYGN0cmwgKyBFTlRFUmAgcGFyYSBleGVjdXRhciBhIGluc3RydcOnw6NvIGVzY3JpdGEgbmVzc2EgbGluaGEsIG91IG5hIHByw7N4aW1hIGF0aXZhCgo+PiBESUNBOiBMaW5oYXMgcXVlIGNvbWXDp2FtIGNvbSBgKiojKipgIHPDo28gaWdub3JhZGFzIHBlbG8gY29tcHV0YWRvci4gU2VydmVtIGFwZW5hcyBwYXJhIG9zICoqaHVtYW5vcyoqLiAgVm9jw6ogcG9kZSBpbnNlcmlyIGNvbWVudMOhcmlvcyBlbSBxdWFscXVlciBwYXJ0ZSBkbyBjw7NkaWdvLCBlIGVzY3JldmVyIGxlbWJyZXRlcyBvdSBleHBsaWNhw6fDtWVzIHF1ZSBwb2RlbSB0ZSBhanVkYXIgYSBlc3R1ZGFyLCBvdSBhanVkYXIgZnV0dXJvcyB1c3XDoXJpb3MgYSBlbnRlbmRlciBjb21vIG8gY8OzZGlnbyBmdW5jaW9uYS4KCmBgYHtyLCBlY2hvPVRSVUUsZXZhbD1GQUxTRX0KCiMgbmVzdGUgY8OzZGlnbyB2YW1vcyBjcmlhciBvYmpldG9zIGUgdGFiZWxhcwoKIyBvYmpldG9zIC0tLS0KIyMgY3JpYXIgb2JqZXRvIGEgLS0tLQojIGVzdGUgY29tYW5kbyBjcmlhIHVtIG9iamV0byBvYmpBCgpvYmpBIDwtIDMKIyBvYmpBIDwtIDIzOAojIG9iakEgPC0gYygyMzgsIDU1LCAxMCkKIyBvYmpBIDwtIGMoMjM4LCA1NSwgMTAsIDMsIDI4LCAtMSwgMC4zMykKCm9iakEKCiMjIGNyaWFyIG9iamV0byBvYmpCIC0tLS0Kb2JqQiA8LSAzNQoKb2JqQgoKIyMgb3BlcmHDp8O1ZXMgbWF0ZW3DoXRpY2FzIGNvbSBvcyBvYmpldG9zIC0tLQoKb2JqQSpvYmpCCiMjIGNyaWFyIG8gb2JqZXRvIG9iakQgLS0tLQpvYmpEIDwtIG9iakEqb2JqQgpvYmpECgoKIyMgdGVzdGFuZG8gZnVuw6fDtWVzIC0tLS0KbWVhbihvYmpEKQptYXgob2JqRCkKbWluKG9iakQpCnN1bShvYmpEKQoKCiMjIyMjIy0+IHJlcGl0YSB0b2RvcyBvcyBwYXNzb3MgYW50ZXJpb3JlcyBjb20gZGlmZXJlbnRlcyB2YWxvcmVzIGFybWF6ZW5hZG9zIG5vIG9iakEKCgojIHRyYWJhbGhhbmRvIGNvbSB0YWJlbGFzIC0tLS0KCiMgdmFtb3MgY3JpYXIgdW1hIHRhYmVsYSBjb20gYSBmdW7Dp8OjbyBkYXRhLmZyYW1lKCkKdGFiZWxhIDwtIGRhdGEuZnJhbWUoYW50ZXMgPSBjKDEzMCwgMTAwLCA5MCwxNTAsMTMwLDEyMCksCiAgICAgICAgICAgICAgICAgICAgIGRlcG9pcyA9IGMoNTYsICA4OCwgMzIsIDI4LCA0MCwgMjApLAogICAgICAgICAgICAgICAgICAgICBjb250cm9sZSA9IGMoMCwgIDUsICAyLCAgMSwgIDUsICAxKSkKCnRhYmVsYSRhbnRlcwp0YWJlbGEkZGVwb2lzCgoKIyBncsOhZmljb3MgLS0tLQojIyBvIG1haXMgc2ltcGxlcyAtLS0tCgojIHZlamEgbyBwb2RlciBkbyBSLCBkZSB1bWEgdGFiZWxhIGEgdW0gZ3LDoWZpY28gZW0gdW1hIGxpbmhhIQoKYm94cGxvdCh0YWJlbGEpCgoKCgoKCiMjIG91dHJhcyBwb3NzaWJpbGlkYWRlcwoKCiMgZmF6ZXIgdW0gZ3JhZmljbyBjdXN0b21pesOhdmVsIGNvbSBvIGdncGxvdCAtLS0tIAppbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikgIyBlc3RlIHPDsyBwcmVjaXNhIHNlciBleGVjdXRhZG8gdW1hIHZleiEKCmxpYnJhcnkoZ2dwbG90MikKCgp0YWJlbGEKc3RhY2sodGFiZWxhMSkKCmdncGxvdChzdGFjayh0YWJlbGExKSwKICAgICAgIGFlcyh4ID0gaW5kLAogICAgICAgICAgIHkgPSB2YWx1ZXMsCiAgICAgICAgICAgZmlsbCA9IGluZCwKICAgICAgICAgICAjIGNvbCA9IGluZCAKICAgICAgICAgICApKSArCiAgICAgICAgIGdlb21fYm94cGxvdCgpICsKICBnZW9tX3BvaW50KCkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI2FiMzMxMCIsIiMyMDAwYjAiKSkrCiAgdGhlbWVfYncoKQoKYGBgCgoKKioqCgo+Pj4+IFZvbHRhciBwYXJhIGEgWypww6FnaW5hIGluaWNpYWwqXShodHRwczovL2hlcm9ub2guZ2l0aHViLmlvL2Jpb2luZm8pCgoKCgoKCg==