Programação literada e R markdown
Programação literada é a tradução livre do termo em inglês
literate programming, que significa criar documentos que são
possíveis de serem lidos tanto por humanos quanto por máquinas
(computadores). No contexto deste curso, programação literada significa
basicamente a possibilidade de misturar em um mesmo documento textos e
pedaços de códigos.
Se ainda é muito abstrato este conceito, um exemplo de texto
produzido usando programação literada é… este texto que você lê nesse
momento. Ao longo de todo o curso vimos textos misturados com pedaços de
código, de modo que a cada vez que precisasse acessar um código e o
significado do que ele faz você pode encontrar tudo em um mesmo
lugar.
R markdown
R markdown é, nas palavras dos próprios criadores, um conjunto de
ferramentas que possibilita produzir documentos que seguem as bases do
literate programming. O R markdown pode ser utilizado tanto para a
simples produção de documentos onde incluímos códigos no meio para nossa
própria conveniência, como para produzir documentos em outros formatos
(html, docx, latex etc) para estender a comunicação dos achados
científicos (ou produzir um site).
Portanto, podemos dizer, de maneira geral, que o R markdown
possibilita a produção de documentos em linguagens que nós nem sabemos
escrever (e.g. não sei escrever em html, consigo produzir sites a partir
de Rmarkdow). Para quem gosta da famosa trilogia de cinco
livros do grande Douglas Adams, O
Guia do Mochileiro das Galáxias, o R markdown (juntamente com os
pacotes knitr
, pandoc
) funciona como o peixe
Babel, mesmo que você não fale (neste caso, escreva) uma dada língua, o
peixe faz o trabalho de tradução para você. A vantagem é que com o R
markdown não há nenhuma necessidade de introduzir nada desagradável na
sua orelha.
Produzindo um documento R markdown
Produzir um documento R markdown é extremamente simples. Basta clicar
na parte superior do RStudio em File, depois New File e selecionar R
Markdown. Isso vai fazer com que ele abra um documento R Markdown (.Rmd)
numa nova aba do seu RStudio. Agora vamos ver os componentes de um
documento .Rmd
o documento yml
O yml é o regente do seu documento markdown. Nele vamos encontrar
todas as instruções sobre o documento que estamos produzindo, incluindo
o nome, a data, o autor e qual será o documento que será gerado a partir
daquele .Rmd. Nesse caso, como podemos ver na figura abaixo, o yml é bem
simples, e derá origem a um documento no formato .html
O yml pode ser simples como o que vimos anteriormente, ou pode ser
mais complicado, com mais elementos, tal como o yml que passa as
instruções para construir o site deste material
De maneira geral, o importante é entender que o yml é o elemento que
rege a forma que o documento será construído. Para construção de sites
(meu principal uso do R markdown), o output no formato
html_document
já é suficiente.
chuncks de código
A imagem abaixo oferece um bom exemplo do que são
chunks
Nesta imagem acima os pedaços de chocolate inseridos no meio da massa
de cookie são chamados em inglês de chunks. Da mesma forma, mas menos
saborosa (ou tão saboroso quanto, mas não para o estômago), os códigos
inseridos no meio de pedaços de texto são chamados de chunks.
Para gerar chuncks de códigos você pode usar um atalho no teclado que
é Cmd
+ option
+ I
(Mac), ou
Crtl
+ option
+ I
(Windows)
um chunck como esse vai aparecer
knitr::include_graphics("figs/rmarkdown-chunck.png")
Os dois pedaços indicados com setas no meio do texto são os chunks de
código, repare que eles apresentam “argumentos” depois da letra
r
, esses argumentos são instruções para dizer como o código
vai aparecer no texto final (que será produzido em formato .html neste
caso). Alguns argumentos importantes:
echo
é um argumento lógico, se TRUE
indica que o código deve aparecer no documento gerado, se
FALSE
indica que o código deve ser ocultado
eval
argumento lógico, se TRUE
quer
dizer que o chunk deve ser avaliado, se FALSE
ele não
rodará
Estes são os argumentos mais importantes geralmente dentro de um
chunk. Outros argumentos existem, você pode checar eles ao inserir um
chunk e dentro dele apertar a tecla Tab
do seu computador
no RStudio. Uma lista com todos os argumentos possíveis vai
aparecer.
Renderizando
Após finalizado o documento, ou se você quer ver o resultado parcial,
precisamos renderizar o documento. Isso é feito utilizando a função
knit
do pacote {knitr}
. Isso pode ser feito
através do console
Ou ainda pode ser feito direto no RStudio clicando no botão knit na
parte superior do RStudio, como mostrado na figura abaixo
knitr::include_graphics("figs/rmarkdown-knit-button.png")
Ao clicar no botão Knit o RStudio renderizará o documento R Markdown
para o formato estipulado no cabeçalho yml. Uma janela irá se abrir com
a demonstração do documento renderizado.
knitr::include_graphics("figs/knitr-puppy.jpeg")
Documentos em R markdown auxiliam no processo de tornar a pesquisa
mais aberta e reprodutível, pois oferecem a possibilidade de produzir
documentos altamente explicativos com textos e códigos, que podem ser
utilizados posteriormente como suplemento para artigos ou ainda para
comunicar com seus colaboradores durante a elaboração de um estudo. Para
finalizar essa seção, um vídeo lembrando a importância da
reprodutibilidade em pesquisa.
LS0tDQp0aXRsZTogIlIgbWFya2Rvd24iDQphdXRob3I6ICJHYWJyaWVsIE5ha2FtdXJhIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0OiBodG1sX2RvY3VtZW50DQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KIyBQcm9ncmFtYcOnw6NvIGxpdGVyYWRhIGUgUiBtYXJrZG93bg0KDQpQcm9ncmFtYcOnw6NvIGxpdGVyYWRhIMOpIGEgdHJhZHXDp8OjbyBsaXZyZSBkbyB0ZXJtbyBlbSBpbmdsw6pzICpsaXRlcmF0ZSBwcm9ncmFtbWluZyosIHF1ZSBzaWduaWZpY2EgY3JpYXIgZG9jdW1lbnRvcyBxdWUgc8OjbyBwb3Nzw612ZWlzIGRlIHNlcmVtIGxpZG9zIHRhbnRvIHBvciBodW1hbm9zIHF1YW50byBwb3IgbcOhcXVpbmFzIChjb21wdXRhZG9yZXMpLiBObyBjb250ZXh0byBkZXN0ZSBjdXJzbywgcHJvZ3JhbWHDp8OjbyBsaXRlcmFkYSBzaWduaWZpY2EgYmFzaWNhbWVudGUgYSBwb3NzaWJpbGlkYWRlIGRlIG1pc3R1cmFyIGVtIHVtIG1lc21vIGRvY3VtZW50byB0ZXh0b3MgZSBwZWRhw6dvcyBkZSBjw7NkaWdvcy4NCg0KU2UgYWluZGEgw6kgbXVpdG8gYWJzdHJhdG8gZXN0ZSBjb25jZWl0bywgdW0gZXhlbXBsbyBkZSB0ZXh0byBwcm9kdXppZG8gdXNhbmRvIHByb2dyYW1hw6fDo28gbGl0ZXJhZGEgw6kuLi4gZXN0ZSB0ZXh0byBxdWUgdm9jw6ogbMOqIG5lc3NlIG1vbWVudG8uIEFvIGxvbmdvIGRlIHRvZG8gbyBjdXJzbyB2aW1vcyB0ZXh0b3MgbWlzdHVyYWRvcyBjb20gcGVkYcOnb3MgZGUgY8OzZGlnbywgZGUgbW9kbyBxdWUgYSBjYWRhIHZleiBxdWUgcHJlY2lzYXNzZSBhY2Vzc2FyIHVtIGPDs2RpZ28gZSBvIHNpZ25pZmljYWRvIGRvIHF1ZSBlbGUgZmF6IHZvY8OqIHBvZGUgZW5jb250cmFyIHR1ZG8gZW0gdW0gbWVzbW8gbHVnYXIuDQoNCiMgUiBtYXJrZG93biANCg0KUiBtYXJrZG93biDDqSwgbmFzIHBhbGF2cmFzIGRvcyBwcsOzcHJpb3MgY3JpYWRvcmVzLCB1bSBjb25qdW50byBkZSBmZXJyYW1lbnRhcyBxdWUgcG9zc2liaWxpdGEgcHJvZHV6aXIgZG9jdW1lbnRvcyBxdWUgc2VndWVtIGFzIGJhc2VzIGRvIGxpdGVyYXRlIHByb2dyYW1taW5nLiBPIFIgbWFya2Rvd24gcG9kZSBzZXIgdXRpbGl6YWRvIHRhbnRvIHBhcmEgYSBzaW1wbGVzIHByb2R1w6fDo28gZGUgZG9jdW1lbnRvcyBvbmRlIGluY2x1w61tb3MgY8OzZGlnb3Mgbm8gbWVpbyBwYXJhIG5vc3NhIHByw7NwcmlhIGNvbnZlbmnDqm5jaWEsIGNvbW8gcGFyYSBwcm9kdXppciBkb2N1bWVudG9zIGVtIG91dHJvcyBmb3JtYXRvcyAoaHRtbCwgZG9jeCwgbGF0ZXggZXRjKSBwYXJhIGVzdGVuZGVyIGEgY29tdW5pY2HDp8OjbyBkb3MgYWNoYWRvcyBjaWVudMOtZmljb3MgKG91IHByb2R1emlyIHVtIHNpdGUpLg0KDQpQb3J0YW50bywgcG9kZW1vcyBkaXplciwgZGUgbWFuZWlyYSBnZXJhbCwgcXVlIG8gUiBtYXJrZG93biBwb3NzaWJpbGl0YSBhIHByb2R1w6fDo28gZGUgZG9jdW1lbnRvcyBlbSBsaW5ndWFnZW5zIHF1ZSBuw7NzIG5lbSBzYWJlbW9zIGVzY3JldmVyIChlLmcuIG7Do28gc2VpIGVzY3JldmVyIGVtIGh0bWwsIGNvbnNpZ28gcHJvZHV6aXIgc2l0ZXMgYSBwYXJ0aXIgZGUgUm1hcmtkb3cpLiBQYXJhIHF1ZW0gZ29zdGEgZGEgZmFtb3NhICoqdHJpbG9naWEgZGUgY2luY28gbGl2cm9zKiogZG8gZ3JhbmRlIFtEb3VnbGFzIEFkYW1zXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Eb3VnbGFzX0FkYW1zKSwgW08gR3VpYSBkbyBNb2NoaWxlaXJvIGRhcyBHYWzDoXhpYXNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1RoZV9IaXRjaGhpa2VyJTI3c19HdWlkZV90b190aGVfR2FsYXh5KSwgbyBSIG1hcmtkb3duIChqdW50YW1lbnRlIGNvbSBvcyBwYWNvdGVzIGBrbml0cmAsIGBwYW5kb2NgKSBmdW5jaW9uYSBjb21vIG8gcGVpeGUgQmFiZWwsIG1lc21vIHF1ZSB2b2PDqiBuw6NvIGZhbGUgKG5lc3RlIGNhc28sIGVzY3JldmEpIHVtYSBkYWRhIGzDrW5ndWEsIG8gcGVpeGUgZmF6IG8gdHJhYmFsaG8gZGUgdHJhZHXDp8OjbyBwYXJhIHZvY8OqLiBBIHZhbnRhZ2VtIMOpIHF1ZSBjb20gbyBSIG1hcmtkb3duIG7Do28gaMOhIG5lbmh1bWEgbmVjZXNzaWRhZGUgZGUgaW50cm9kdXppciBuYWRhIGRlc2FncmFkw6F2ZWwgbmEgc3VhIG9yZWxoYS4NCg0KYGBge3IgZWNobz1GQUxTRSxldmFsPVRSVUUsZmlnLmNhcD0iUiBtYXJrZG93biDDqSBjb21vIHVtIHBlaXhlIEJhYmVsLCBlbGUgZmF6IHZvY8OqIGZhbGFyIHVtYSBsaW5ndWFnZW0gbWVzbW8gbsOjbyBzYWJlbmRvIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJmaWdzL2JhYmVsLWZpc2hfYW5hdG9teS5qcGciKQ0KYGBgDQoNCiMjIFByb2R1emluZG8gdW0gZG9jdW1lbnRvIFIgbWFya2Rvd24NCg0KUHJvZHV6aXIgdW0gZG9jdW1lbnRvIFIgbWFya2Rvd24gw6kgZXh0cmVtYW1lbnRlIHNpbXBsZXMuIEJhc3RhIGNsaWNhciBuYSBwYXJ0ZSBzdXBlcmlvciBkbyBSU3R1ZGlvIGVtIEZpbGUsIGRlcG9pcyBOZXcgRmlsZSBlIHNlbGVjaW9uYXIgUiBNYXJrZG93bi4gSXNzbyB2YWkgZmF6ZXIgY29tIHF1ZSBlbGUgYWJyYSB1bSBkb2N1bWVudG8gUiBNYXJrZG93biAoLlJtZCkgbnVtYSBub3ZhIGFiYSBkbyBzZXUgUlN0dWRpby4gQWdvcmEgdmFtb3MgdmVyIG9zIGNvbXBvbmVudGVzIGRlIHVtIGRvY3VtZW50byAuUm1kDQoNCiMjIyBvIGRvY3VtZW50byB5bWwNCg0KTyB5bWwgw6kgbyByZWdlbnRlIGRvIHNldSBkb2N1bWVudG8gbWFya2Rvd24uIE5lbGUgdmFtb3MgZW5jb250cmFyIHRvZGFzIGFzIGluc3RydcOnw7VlcyBzb2JyZSBvIGRvY3VtZW50byBxdWUgZXN0YW1vcyBwcm9kdXppbmRvLCBpbmNsdWluZG8gbyBub21lLCBhIGRhdGEsIG8gYXV0b3IgZSBxdWFsIHNlcsOhIG8gZG9jdW1lbnRvIHF1ZSBzZXLDoSBnZXJhZG8gYSBwYXJ0aXIgZGFxdWVsZSAuUm1kLiBOZXNzZSBjYXNvLCBjb21vIHBvZGVtb3MgdmVyIG5hIGZpZ3VyYSBhYmFpeG8sIG8geW1sIMOpIGJlbSBzaW1wbGVzLCBlIGRlcsOhIG9yaWdlbSBhIHVtIGRvY3VtZW50byBubyBmb3JtYXRvIC5odG1sDQoNCmBgYHtyIGVjaG89RkFMU0UsZXZhbD1UUlVFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImZpZ3Mvcm1hcmtkb3duLXltbC5wbmciKQ0KYGBgDQoNCk8geW1sIHBvZGUgc2VyIHNpbXBsZXMgY29tbyBvIHF1ZSB2aW1vcyBhbnRlcmlvcm1lbnRlLCBvdSBwb2RlIHNlciBtYWlzIGNvbXBsaWNhZG8sIGNvbSBtYWlzIGVsZW1lbnRvcywgdGFsIGNvbW8gbyB5bWwgcXVlIHBhc3NhIGFzIGluc3RydcOnw7VlcyBwYXJhIGNvbnN0cnVpciBvIHNpdGUgZGVzdGUgbWF0ZXJpYWwNCg0KYGBge3IgZWNobz1GQUxTRSxldmFsPVRSVUV9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiZmlncy9ybWFya2Rvd24teW1sLW1vcmVjb21wbGljYXRlZC5wbmciKQ0KYGBgDQoNCkRlIG1hbmVpcmEgZ2VyYWwsIG8gaW1wb3J0YW50ZSDDqSBlbnRlbmRlciBxdWUgbyB5bWwgw6kgbyBlbGVtZW50byBxdWUgcmVnZSBhIGZvcm1hIHF1ZSBvIGRvY3VtZW50byBzZXLDoSBjb25zdHJ1w61kby4gUGFyYSBjb25zdHJ1w6fDo28gZGUgc2l0ZXMgKG1ldSBwcmluY2lwYWwgdXNvIGRvIFIgbWFya2Rvd24pLCBvIG91dHB1dCBubyBmb3JtYXRvIGBodG1sX2RvY3VtZW50YCBqw6Egw6kgc3VmaWNpZW50ZS4NCg0KYGBge3IgZWNobz1GQUxTRSxldmFsPVRSVUUsZmlnLmNhcD0iTyB5bWwgw6kgbyByZWdlbnRlIGRvIHNldSBzaXRlIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJmaWdzL29ycXVlc3RyYS1ybWFya2Rvd24uanBnIikNCmBgYA0KDQojIyMgY2h1bmNrcyBkZSBjw7NkaWdvDQoNCkEgaW1hZ2VtIGFiYWl4byBvZmVyZWNlIHVtIGJvbSBleGVtcGxvIGRvIHF1ZSBzw6NvICoqY2h1bmtzKioNCg0KYGBge3IgZWNobz1GQUxTRSxldmFsPVRSVUUsZmlnLmNhcD0iVW0gZXhlbXBsbyBkZSBjaHVua3MsIG1hcyBuw6NvIGNvbW8gdm9jw6ogZXN0w6EgcGVuc2FuZG8iLG91dC53aWR0aD0iNjAlIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJmaWdzL2NodW5jay1jaG9jb2xhdGUuanBlZyIpDQpgYGANCg0KTmVzdGEgaW1hZ2VtIGFjaW1hIG9zIHBlZGHDp29zIGRlIGNob2NvbGF0ZSBpbnNlcmlkb3Mgbm8gbWVpbyBkYSBtYXNzYSBkZSBjb29raWUgc8OjbyBjaGFtYWRvcyBlbSBpbmdsw6pzIGRlIGNodW5rcy4gRGEgbWVzbWEgZm9ybWEsIG1hcyBtZW5vcyBzYWJvcm9zYSAob3UgdMOjbyBzYWJvcm9zbyBxdWFudG8sIG1hcyBuw6NvIHBhcmEgbyBlc3TDtG1hZ28pLCBvcyBjw7NkaWdvcyBpbnNlcmlkb3Mgbm8gbWVpbyBkZSBwZWRhw6dvcyBkZSB0ZXh0byBzw6NvIGNoYW1hZG9zIGRlIGNodW5rcy4gDQoNClBhcmEgZ2VyYXIgY2h1bmNrcyBkZSBjw7NkaWdvcyB2b2PDqiBwb2RlIHVzYXIgdW0gYXRhbGhvIG5vIHRlY2xhZG8gcXVlIMOpIGBDbWRgICsgYG9wdGlvbmAgKyBgSWAgKE1hYyksIG91IGBDcnRsYCArIGBvcHRpb25gICsgYElgIChXaW5kb3dzKQ0KDQp1bSBjaHVuY2sgY29tbyBlc3NlIHZhaSBhcGFyZWNlcg0KDQpgYGB7ciBlY2hvPVRSVUUsZXZhbD1UUlVFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImZpZ3Mvcm1hcmtkb3duLWNodW5jay5wbmciKQ0KYGBgDQoNCk9zIGRvaXMgcGVkYcOnb3MgaW5kaWNhZG9zIGNvbSBzZXRhcyBubyBtZWlvIGRvIHRleHRvIHPDo28gb3MgY2h1bmtzIGRlIGPDs2RpZ28sIHJlcGFyZSBxdWUgZWxlcyBhcHJlc2VudGFtICJhcmd1bWVudG9zIiBkZXBvaXMgZGEgbGV0cmEgYHJgLCBlc3NlcyBhcmd1bWVudG9zIHPDo28gaW5zdHJ1w6fDtWVzIHBhcmEgZGl6ZXIgY29tbyBvIGPDs2RpZ28gdmFpIGFwYXJlY2VyIG5vIHRleHRvIGZpbmFsIChxdWUgc2Vyw6EgcHJvZHV6aWRvIGVtIGZvcm1hdG8gLmh0bWwgbmVzdGUgY2FzbykuIEFsZ3VucyBhcmd1bWVudG9zIGltcG9ydGFudGVzOg0KDQotIGBlY2hvYCDDqSB1bSBhcmd1bWVudG8gbMOzZ2ljbywgc2UgYFRSVUVgIGluZGljYSBxdWUgbyBjw7NkaWdvIGRldmUgYXBhcmVjZXIgbm8gZG9jdW1lbnRvIGdlcmFkbywgc2UgYEZBTFNFYCBpbmRpY2EgcXVlIG8gY8OzZGlnbyBkZXZlIHNlciBvY3VsdGFkbw0KDQotIGBldmFsYCBhcmd1bWVudG8gbMOzZ2ljbywgc2UgYFRSVUVgIHF1ZXIgZGl6ZXIgcXVlIG8gY2h1bmsgZGV2ZSBzZXIgYXZhbGlhZG8sIHNlIGBGQUxTRWAgZWxlIG7Do28gcm9kYXLDoQ0KDQpFc3RlcyBzw6NvIG9zIGFyZ3VtZW50b3MgbWFpcyBpbXBvcnRhbnRlcyBnZXJhbG1lbnRlIGRlbnRybyBkZSB1bSBjaHVuay4gT3V0cm9zIGFyZ3VtZW50b3MgZXhpc3RlbSwgdm9jw6ogcG9kZSBjaGVjYXIgZWxlcyBhbyBpbnNlcmlyIHVtIGNodW5rIGUgZGVudHJvIGRlbGUgYXBlcnRhciBhIHRlY2xhIGBUYWJgIGRvIHNldSBjb21wdXRhZG9yIG5vIFJTdHVkaW8uIFVtYSBsaXN0YSBjb20gdG9kb3Mgb3MgYXJndW1lbnRvcyBwb3Nzw612ZWlzIHZhaSBhcGFyZWNlci4NCg0KIyMjIFJlbmRlcml6YW5kbyANCg0KQXDDs3MgZmluYWxpemFkbyBvIGRvY3VtZW50bywgb3Ugc2Ugdm9jw6ogcXVlciB2ZXIgbyByZXN1bHRhZG8gcGFyY2lhbCwgcHJlY2lzYW1vcyByZW5kZXJpemFyIG8gZG9jdW1lbnRvLiBJc3NvIMOpIGZlaXRvIHV0aWxpemFuZG8gYSBmdW7Dp8OjbyBga25pdGAgZG8gcGFjb3RlIGB7a25pdHJ9YC4gSXNzbyBwb2RlIHNlciBmZWl0byBhdHJhdsOpcyBkbyBjb25zb2xlDQoNCmBgYHtyIGVjaG89VFJVRSxldmFsPUZBTFNFfQ0KbGlicmFyeShrbml0cikNCmtuaXQoKQ0KYGBgDQoNCk91IGFpbmRhIHBvZGUgc2VyIGZlaXRvIGRpcmV0byBubyBSU3R1ZGlvIGNsaWNhbmRvIG5vIGJvdMOjbyBrbml0IG5hIHBhcnRlIHN1cGVyaW9yIGRvIFJTdHVkaW8sIGNvbW8gbW9zdHJhZG8gbmEgZmlndXJhIGFiYWl4bw0KDQpgYGB7ciBlY2hvPVRSVUUsZXZhbD1UUlVFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImZpZ3Mvcm1hcmtkb3duLWtuaXQtYnV0dG9uLnBuZyIpDQpgYGANCg0KQW8gY2xpY2FyIG5vIGJvdMOjbyBLbml0IG8gUlN0dWRpbyByZW5kZXJpemFyw6EgbyBkb2N1bWVudG8gUiBNYXJrZG93biBwYXJhIG8gZm9ybWF0byBlc3RpcHVsYWRvIG5vIGNhYmXDp2FsaG8geW1sLiBVbWEgamFuZWxhIGlyw6Egc2UgYWJyaXIgY29tIGEgZGVtb25zdHJhw6fDo28gZG8gZG9jdW1lbnRvIHJlbmRlcml6YWRvLg0KDQpgYGB7ciBlY2hvPVRSVUUsZXZhbD1UUlVFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImZpZ3Mva25pdHItcHVwcHkuanBlZyIpDQpgYGANCg0KRG9jdW1lbnRvcyBlbSBSIG1hcmtkb3duIGF1eGlsaWFtIG5vIHByb2Nlc3NvIGRlIHRvcm5hciBhIHBlc3F1aXNhIG1haXMgYWJlcnRhIGUgcmVwcm9kdXTDrXZlbCwgcG9pcyBvZmVyZWNlbSBhIHBvc3NpYmlsaWRhZGUgZGUgcHJvZHV6aXIgZG9jdW1lbnRvcyBhbHRhbWVudGUgZXhwbGljYXRpdm9zIGNvbSB0ZXh0b3MgZSBjw7NkaWdvcywgcXVlIHBvZGVtIHNlciB1dGlsaXphZG9zIHBvc3Rlcmlvcm1lbnRlIGNvbW8gc3VwbGVtZW50byBwYXJhIGFydGlnb3Mgb3UgYWluZGEgcGFyYSBjb211bmljYXIgY29tIHNldXMgY29sYWJvcmFkb3JlcyBkdXJhbnRlIGEgZWxhYm9yYcOnw6NvIGRlIHVtIGVzdHVkby4gUGFyYSBmaW5hbGl6YXIgZXNzYSBzZcOnw6NvLCB1bSB2w61kZW8gbGVtYnJhbmRvIGEgaW1wb3J0w6JuY2lhIGRhIHJlcHJvZHV0aWJpbGlkYWRlIGVtIHBlc3F1aXNhLg0KDQpgYGB7ciBlY2hvPUZBTFNFLGV2YWw9VFJVRX0NCnZlbWJlZHI6OmVtYmVkX3VybCgiaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj03Z1lJczd1WWJNbyIpDQpgYGANCg0KDQo=