Introduction
This is a template for a data analysis folder that can be easily exported as a webpage or as Supplementary Materials (e.g., as a Word document or a PDF).
How does it look like? Just like this! The README page of this repository, alongside the webpage and the word and PDF documents, were all created from the index.Rmd file.
This means you can easily share your data analysis, either by attaching the PDF or Word file to the publication (as Supplementary Materials), or by directly providing the URL of your GitHub repository: the readers can then enjoy your awesome open-access work in a convenient and transparent way.
Features
Installation
This repository is a template to set up a reproducible, convenient and shareable workflow for your data analysis. It consists of several Rmarkdown files (.Rmd
), that allow you to have R code and text (markdown) in the same document. Importantly, these files can be transformed into other documents formats.
- How to use this template?
Download it (click here to download), unzip it and edit. Alternatively, you click on the Use this template button at the top of this screen to create a GitHub repository with all the content copied (then you just need to clone the repo to your local machine).
The main files you need to edit are the .Rmd
files, that you can open with some editor (e.g., Rstudio), and edit the text and the R chunks of code.
- How to upload it to a website?
If your repo is not already connected to GitHub, then create a new repository and upload all the content (so that it looks like this repo). Then, go to settings of the repo and enable GitHub pages (i.e., that gives you a webpage from an html stored on GitHub), and select the docs/
folder as the location of the webpage. Indeed, rendering (knitting) the files will generate an “index.html” file in the /docs/
folder, which is used as the website. You can see an example at https://realitybending.github.io/TemplateResults/.
In this repo, with have set up a GitHub action that generates all the output files everytime someone commit to the repository. This means that the final documents here are always “up-to-date” with the Rmds (as shown by the green badge). That said, you can remove this GitHub action (just remove the .github/workflows/website.yml
file) if you prefer to generate the documents manually only.
- But I don’t want do upload all my data
In that case, you’ll need to 1) deactivate (i.e., remove the action file) the automatic rendering by GitHub (as no data will be stored on GitHub) and 2) mark the data folder as “to be ignored” (so that it won’t be uploaded). This can be done by adding /data/
to the .gitignore file (that you can open with a notepad). This means that you can still store the data here locally, and generate the documents accordingly, but the data folder will be ignored by git and never uploaded to GitHub. This way, you can still have a cool website, an open-access script, but the data is safe with you. The only down side is that you have to build it manually (cannot use GitHub actions).
References have to be added in bib
format in the utils/bibliography.bib file, and further referenced in the text like this [@ludecke2019insight]
(Lüdecke, Waggoner, & Makowski, 2019).
- I don’t like the Word (.docx) theme
The theme for the word document is defined in the **Template_Word.docx file, in the /utils/
folder. You need to edit the “styles” (not just the content, but the style itself) to your preference.
Thanks to R’s possibilities when it comes to integration with Python, it’s super easy to enable it in your pipeline. Just uncomment the Python installation line in the utils/config.R
file and you’re ready to go!
- It doesn’t work / I have questions / I have ideas
Just open an issue and we’ll be happy to assist ☺
Structure
Most files that you’ll need to create / edit will be written in rmarkdown, which consists of a mix of markdown text and R chunks of code.
The main file is named index.Rmd. However, to avoid having overly long files, the different (and independent) analyses parts are actually split in other documents. For instance, in this template example, the descriptive statistics section is in the 1_descriptive.Rmd file. As you can see in the index file, this file is then integrated as a child document (i.e., it is merged). This makes it very convenient to have a clear structure with well-organized files, that are put together only when merged.
Render and Publish
Importantly, in order to render all the files, do not Knit this document by pressing the ‘Knit’ button. If you do, it will create an output file (for instance index.html
) in the root folder, alongside index.Rmd
. This is not what we want, as we want to keep the output files tidy in separate folders (for instance, the html version should be in the /docs/
folder, as this is where the website will look for).
There an R script, utils/render.R, that contains the lines to render everything in its correct location. So, when you have the “index.Rmd” file opened (and your working directory is at its root), simply run source("utils/render.R")
in the console (or the relevant lines in that file). This will run the rendering file and create all the files.
Contribution
Do not hesitate to improve this template by updating, documenting, or expanding it!
Packages & Data
Packages
This document was prepared on 2021-08-02.
library(bayestestR)
library(parameters)
library(performance)
library(report)
library(see)
library(ggplot2)
summary(report::report(sessionInfo()))
The analysis was done using the R Statistical language (v4.1.0; R Core Team, 2021) on macOS Catalina 10.15.7, using the packages ggplot2 (v3.3.5), stringr (v1.4.0), forcats (v0.5.1), tidyr (v1.1.3), readr (v2.0.0), dplyr (v1.0.7), rmarkdown (v2.9), tibble (v3.1.3), purrr (v0.3.4), parameters (v0.14.0.1), performance (v0.7.3.1), see (v0.6.4), bayestestR (v0.10.5), report (v0.3.5) and tidyverse (v1.3.1).
Data
df <- read.csv("data/data.csv")
cat(paste("The data consists of",
report::report_participants(df,
participants = "Participant",
age = "Age")))
The data consists of 10 participants (Mean age = 29.9, SD = 0.5, range: [29.0, 30.91])
Note that the chunks generating figures in the code below have some arguments specified in their header, such as fig.width
and fig.height
, which controls the figure size. These were filled with an eponym argument defined in utils/config.R
. We also set the resolution, i.e., dpi
, to a low value so that the resulting file is lighter. But don’t forget to crank this value up (to 300-600) to get nice-looking results.
Descriptive Stats
Notice the {.tabset}
tag after the section name. This will show the subsections as different tabs (in the html version only, because the other formats are static).
Part 1
Here’s a cool plot:
ggplot(df, aes(x=V1, y=V2, color=Participant)) +
geom_point() +
see::theme_modern()
Part 2
That’s another great plot:
plot(bayestestR::estimate_density(df[c("V1", "V2")])) +
see::theme_blackboard()
Part 3
Did you ever hear the tragedy of Darth Plagueis The Wise? I thought not. It’s not a story the Jedi would tell you. It’s a Sith legend. Darth Plagueis was a Dark Lord of the Sith, so powerful and so wise he could use the Force to influence the midichlorians to create life… He had such a knowledge of the dark side that he could even keep the ones he cared about from dying. The dark side of the Force is a pathway to many abilities some consider to be unnatural. He became so powerful… the only thing he was afraid of was losing his power, which eventually, of course, he did. Unfortunately, he taught his apprentice everything he knew, then his apprentice killed him in his sleep. Ironic. He could save others from death, but not himself.
LS0tCnRpdGxlOiAnKipSZXN1bHRzIFRlbXBsYXRlKionCnN1YnRpdGxlOiBBIFN1YnRpdGxlCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IGNlcnVsZWFuCiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAzCiAgICB0b2NfZmxvYXQ6IHllcwogICAgbnVtYmVyX3NlY3Rpb25zOiBubwogICAgZGZfcHJpbnQ6IGthYmxlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICByZWZlcmVuY2VfZG9jeDogdXRpbHMvVGVtcGxhdGVfV29yZC5kb2N4CiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzCiAgICB0b2M6IG5vCiAgICB0b2NfZGVwdGg6IDMKICAgIGRmX3ByaW50OiBrYWJsZQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICBybWFya2Rvd246Omh0bWxfdmlnbmV0dGU6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAzCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogJzInCiAgICBsYXRleF9lbmdpbmU6IHhlbGF0ZXgKZWRpdG9yX29wdGlvbnM6CiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUKYmlibGlvZ3JhcGh5OiB1dGlscy9iaWJsaW9ncmFwaHkuYmliCmNzbDogdXRpbHMvYXBhLmNzbAotLS0KCgo8IS0tIAohISEhIElNUE9SVEFOVDogcnVuIGBzb3VyY2UoInV0aWxzL3JlbmRlci5SIilgIHRvIHB1Ymxpc2ggaW5zdGVhZCBvZiBjbGlja2luZyBvbiAnS25pdCcKLS0+CgpgYGB7ciBzZXR1cCwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1UUlVFLCBpbmNsdWRlPUZBTFNFfQojIFNldCB1cCB0aGUgZW52aXJvbm1lbnQgKG9yIHVzZSBsb2NhbCBhbHRlcm5hdGl2ZSBgc291cmNlKCJ1dGlscy9jb25maWcuUiIpYCkKc291cmNlKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vUmVhbGl0eUJlbmRpbmcvVGVtcGxhdGVSZXN1bHRzL21haW4vdXRpbHMvY29uZmlnLlIiKSAgCgpmYXN0IDwtIEZBTFNFICAjIE1ha2UgdGhpcyBmYWxzZSB0byBza2lwIHRoZSBjaHVua3MKYGBgCgojIEludHJvZHVjdGlvbgoKYGBge3IgYmFkZ2VzLCBlY2hvPUZBTFNFLCBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQojIFRoaXMgY2h1bmsgaXMgYSBiaXQgY29tcGxleCBzbyBkb24ndCB3b3JyeSBhYm91dCBpdDogaXQncyBtYWRlIHRvIGFkZCBiYWRnZXMgdG8gdGhlIEhUTUwgdmVyc2lvbnMKIyBOT1RFOiBZb3UgaGF2ZSB0byByZXBsYWNlIHRoZSBsaW5rcyBhY2NvcmRpbmdseSB0byBoYXZlIHdvcmtpbmcgImJ1dHRvbnMiIG9uIHRoZSBIVE1MIHZlcnNpb25zCmlmICgha25pdHI6OmlzX2xhdGV4X291dHB1dCgpICYmIGtuaXRyOjppc19odG1sX291dHB1dCgpKSB7CiAgY2F0KCIhW0J1aWxkXShodHRwczovL2dpdGh1Yi5jb20vUmVhbGl0eUJlbmRpbmcvVGVtcGxhdGVSZXN1bHRzL3dvcmtmbG93cy9CdWlsZC9iYWRnZS5zdmcpCiAgICAgIFshW1dlYnNpdGVdKGh0dHBzOi8vaW1nLnNoaWVsZHMuaW8vYmFkZ2UvcmVwby1SZWFkbWUtMjE5NkYzKV0oaHR0cHM6Ly9naXRodWIuY29tL1JlYWxpdHlCZW5kaW5nL1RlbXBsYXRlUmVzdWx0cykKICAgICAgWyFbV2Vic2l0ZV0oaHR0cHM6Ly9pbWcuc2hpZWxkcy5pby9iYWRnZS92aXNpdC13ZWJzaXRlLUU5MUU2MyldKGh0dHBzOi8vcmVhbGl0eWJlbmRpbmcuZ2l0aHViLmlvL1RlbXBsYXRlUmVzdWx0cy8pCiAgICAgIFshW1dlYnNpdGVdKGh0dHBzOi8vaW1nLnNoaWVsZHMuaW8vYmFkZ2UvZG93bmxvYWQtLmRvY3gtRkY1NzIyKV0oaHR0cHM6Ly9naXRodWIuY29tL1JlYWxpdHlCZW5kaW5nL1RlbXBsYXRlUmVzdWx0cy9yYXcvbWFpbi93b3JkX2FuZF9wZGYvU3VwcGxlbWVudGFyeU1hdGVyaWFscy5kb2N4KQogICAgICBbIVtXZWJzaXRlXShodHRwczovL2ltZy5zaGllbGRzLmlvL2JhZGdlL3NlZS0ucGRmLUZGOTgwMCldKGh0dHBzOi8vZ2l0aHViLmNvbS9SZWFsaXR5QmVuZGluZy9UZW1wbGF0ZVJlc3VsdHMvYmxvYi9tYWluL3dvcmRfYW5kX3BkZi9TdXBwbGVtZW50YXJ5TWF0ZXJpYWxzLnBkZikiKQp9CmBgYAoKVGhpcyBpcyBhIHRlbXBsYXRlIGZvciBhIGRhdGEgYW5hbHlzaXMgZm9sZGVyIHRoYXQgY2FuIGJlIGVhc2lseSBleHBvcnRlZCBhcyBhIFsqKndlYnBhZ2UqKl0oaHR0cHM6Ly9yZWFsaXR5YmVuZGluZy5naXRodWIuaW8vVGVtcGxhdGVSZXN1bHRzLykgb3IgYXMgKipTdXBwbGVtZW50YXJ5IE1hdGVyaWFscyoqIChlLmcuLCBhcyBhIFsqKldvcmQgZG9jdW1lbnQqKl0oaHR0cHM6Ly9naXRodWIuY29tL1JlYWxpdHlCZW5kaW5nL1RlbXBsYXRlUmVzdWx0cy9yYXcvbWFpbi93b3JkX2FuZF9wZGYvU3VwcGxlbWVudGFyeU1hdGVyaWFscy5kb2N4KSBvciBhIFsqKlBERioqXShodHRwczovL2dpdGh1Yi5jb20vUmVhbGl0eUJlbmRpbmcvVGVtcGxhdGVSZXN1bHRzL2Jsb2IvbWFpbi93b3JkX2FuZF9wZGYvU3VwcGxlbWVudGFyeU1hdGVyaWFscy5wZGYpKS4KCkhvdyBkb2VzIGl0IGxvb2sgbGlrZT8gSnVzdCBsaWtlIHRoaXMhIFRoZSBSRUFETUUgcGFnZSBvZiB0aGlzIHJlcG9zaXRvcnksIGFsb25nc2lkZSB0aGUgW3dlYnBhZ2VdKGh0dHBzOi8vcmVhbGl0eWJlbmRpbmcuZ2l0aHViLmlvL1RlbXBsYXRlUmVzdWx0cy8pIGFuZCB0aGUgd29yZCBhbmQgUERGIGRvY3VtZW50cywgd2VyZSBhbGwgY3JlYXRlZCBmcm9tIHRoZSBbaW5kZXguUm1kXShodHRwczovL2dpdGh1Yi5jb20vUmVhbGl0eUJlbmRpbmcvVGVtcGxhdGVSZXN1bHRzL2Jsb2IvbWFpbi9pbmRleC5SbWQpIGZpbGUuCgpUaGlzIG1lYW5zIHlvdSBjYW4gZWFzaWx5ICoqc2hhcmUgeW91ciBkYXRhIGFuYWx5c2lzKiosIGVpdGhlciBieSBhdHRhY2hpbmcgdGhlICpQREYqIG9yICpXb3JkKiBmaWxlIHRvIHRoZSBwdWJsaWNhdGlvbiAoYXMgKipTdXBwbGVtZW50YXJ5IE1hdGVyaWFscyoqKSwgb3IgYnkgZGlyZWN0bHkgcHJvdmlkaW5nIHRoZSBVUkwgb2YgeW91ciBHaXRIdWIgcmVwb3NpdG9yeTogdGhlIHJlYWRlcnMgY2FuIHRoZW4gZW5qb3kgeW91ciBhd2Vzb21lIG9wZW4tYWNjZXNzIHdvcmsgaW4gYSBjb252ZW5pZW50IGFuZCB0cmFuc3BhcmVudCB3YXkuCgojIyBGZWF0dXJlcwoKLSBbeF0gQXV0b21hdGljYWxseSBnZW5lcmF0ZXMgZGlmZmVyZW50IHR5cGVzIG9mIGRvY3VtZW50OgogIC0gWyoqUkVBRE1FIHBhZ2UqKl0oaHR0cHM6Ly9naXRodWIuY29tL1JlYWxpdHlCZW5kaW5nL1RlbXBsYXRlUmVzdWx0cy9ibG9iL21haW4vUkVBRE1FLm1kKQogIC0gWyoqUHVibGlzaGVkIHdlYnNpdGUqKl0oaHR0cHM6Ly9yZWFsaXR5YmVuZGluZy5naXRodWIuaW8vVGVtcGxhdGVSZXN1bHRzLykKICAtIFsqKldvcmQgZG9jdW1lbnQqKl0oaHR0cHM6Ly9naXRodWIuY29tL1JlYWxpdHlCZW5kaW5nL1RlbXBsYXRlUmVzdWx0cy9yYXcvbWFpbi93b3JkX2FuZF9wZGYvU3VwcGxlbWVudGFyeU1hdGVyaWFscy5kb2N4KQogIC0gWyoqUERGIGRvY3VtZW50KipdKGh0dHBzOi8vZ2l0aHViLmNvbS9SZWFsaXR5QmVuZGluZy9UZW1wbGF0ZVJlc3VsdHMvYmxvYi9tYWluL3dvcmRfYW5kX3BkZi9TdXBwbGVtZW50YXJ5TWF0ZXJpYWxzLnBkZikKLSBbeF0gQVBBIGNpdGF0aW9ucwotIFt4XSBBdXRvbWF0aWMgY2l0YXRpb25zIGFuZCBbcmVmZXJlbmNlIGxpc3RdKGh0dHBzOi8vZ2l0aHViLmNvbS9SZWFsaXR5QmVuZGluZy9UZW1wbGF0ZVJlc3VsdHMjcGFja2FnZS1yZWZlcmVuY2VzKSBmb3IgYWxsIHBhY2thZ2VzCi0gW3hdIFRpZHkgb3JnYW5pc2F0aW9uIChzZXBhcmF0ZSBmaWxlcyBmb3IgaW5kZXBlbmRlbnQgYW5hbHlzZXMpCi0gW3hdIEdyZWF0IGRlZmF1bHQgY29uZmlndXJhdGlvbgotIFt4XSBBbmQgbW9yZSEKCmBgYHtyIGRlbW9fZ2lmLCBlY2hvPUZBTFNFLCBtZXNzYWdlPVRSVUUsIHdhcm5pbmc9RkFMU0V9CiMgTGV0J3MgaW5jbHVkZSBhIGRlbW8gR0lGICh0aGlzIGRvZXNuJ3Qgd29yayBpbiBQREYgZG9jdW1lbnRzKQppZiAoIWtuaXRyOjppc19sYXRleF9vdXRwdXQoKSkgewogIGtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJmaWd1cmVzL2RlbW8uZ2lmIikKfQpgYGAKCgojIyBJbnN0YWxsYXRpb24KCi0gKipXaGF0IGlzIHRoaXM/KioKClRoaXMgcmVwb3NpdG9yeSBpcyBhIHRlbXBsYXRlIHRvIHNldCB1cCBhIHJlcHJvZHVjaWJsZSwgY29udmVuaWVudCBhbmQgc2hhcmVhYmxlIHdvcmtmbG93IGZvciB5b3VyIGRhdGEgYW5hbHlzaXMuIEl0IGNvbnNpc3RzIG9mIHNldmVyYWwgWypSbWFya2Rvd24qXShodHRwczovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbS9sZXNzb24tMS5odG1sKSBmaWxlcyAoYC5SbWRgKSwgdGhhdCBhbGxvdyB5b3UgdG8gaGF2ZSBSIGNvZGUgYW5kIHRleHQgKG1hcmtkb3duKSBpbiB0aGUgc2FtZSBkb2N1bWVudC4gSW1wb3J0YW50bHksIHRoZXNlIGZpbGVzIGNhbiBiZSB0cmFuc2Zvcm1lZCBpbnRvIG90aGVyIGRvY3VtZW50cyBmb3JtYXRzLgoKLSAqKkhvdyB0byB1c2UgdGhpcyB0ZW1wbGF0ZT8qKgoKRG93bmxvYWQgaXQgKFsqKmNsaWNrIGhlcmUgdG8gZG93bmxvYWQqKl0oaHR0cHM6Ly9naXRodWIuY29tL1JlYWxpdHlCZW5kaW5nL1RlbXBsYXRlUmVzdWx0cy9hcmNoaXZlL21haW4uemlwKSksIHVuemlwIGl0IGFuZCBlZGl0LgpBbHRlcm5hdGl2ZWx5LCB5b3UgY2xpY2sgb24gdGhlIFsqKlVzZSB0aGlzIHRlbXBsYXRlKipdKGh0dHBzOi8vZ2l0aHViLmNvbS9SZWFsaXR5QmVuZGluZy9UZW1wbGF0ZVJlc3VsdHMvZ2VuZXJhdGUpIGJ1dHRvbiBhdCB0aGUgdG9wIG9mIHRoaXMgc2NyZWVuIHRvIGNyZWF0ZSBhIEdpdEh1YiByZXBvc2l0b3J5IHdpdGggYWxsIHRoZSBjb250ZW50IGNvcGllZCAodGhlbiB5b3UganVzdCBuZWVkIHRvIGNsb25lIHRoZSByZXBvIHRvIHlvdXIgbG9jYWwgbWFjaGluZSkuCgpUaGUgbWFpbiBmaWxlcyB5b3UgbmVlZCB0byBlZGl0IGFyZSB0aGUgYC5SbWRgIGZpbGVzLCB0aGF0IHlvdSBjYW4gb3BlbiB3aXRoIHNvbWUgZWRpdG9yIChlLmcuLCBbUnN0dWRpb10oaHR0cHM6Ly9yc3R1ZGlvLmNvbS8pKSwgYW5kIGVkaXQgdGhlIHRleHQgYW5kIHRoZSBSIGNodW5rcyBvZiBjb2RlLgoKCi0gKipIb3cgdG8gdXBsb2FkIGl0IHRvIGEgd2Vic2l0ZT8qKgoKSWYgeW91ciByZXBvIGlzIG5vdCBhbHJlYWR5IGNvbm5lY3RlZCB0byBHaXRIdWIsIHRoZW4gY3JlYXRlIGEgbmV3IHJlcG9zaXRvcnkgYW5kIHVwbG9hZCBhbGwgdGhlIGNvbnRlbnQgKHNvIHRoYXQgaXQgbG9va3MgbGlrZSB0aGlzIHJlcG8pLiBUaGVuLCBnbyB0byBzZXR0aW5ncyBvZiB0aGUgcmVwbyBhbmQgZW5hYmxlICoqR2l0SHViIHBhZ2VzKiogKGkuZS4sIHRoYXQgZ2l2ZXMgeW91IGEgd2VicGFnZSBmcm9tIGFuIGh0bWwgc3RvcmVkIG9uIEdpdEh1YiksIGFuZCBzZWxlY3QgdGhlIGBkb2NzL2AgZm9sZGVyIGFzIHRoZSBsb2NhdGlvbiBvZiB0aGUgd2VicGFnZS4gSW5kZWVkLCByZW5kZXJpbmcgKGtuaXR0aW5nKSB0aGUgZmlsZXMgd2lsbCBnZW5lcmF0ZSBhbiAiaW5kZXguaHRtbCIgZmlsZSBpbiB0aGUgYC9kb2NzL2AgZm9sZGVyLCB3aGljaCBpcyB1c2VkIGFzIHRoZSB3ZWJzaXRlLiBZb3UgY2FuIHNlZSBhbiBleGFtcGxlIGF0IFtodHRwczovL3JlYWxpdHliZW5kaW5nLmdpdGh1Yi5pby9UZW1wbGF0ZVJlc3VsdHMvXShodHRwczovL3JlYWxpdHliZW5kaW5nLmdpdGh1Yi5pby9UZW1wbGF0ZVJlc3VsdHMvKS4KCi0gKipUbyBrbml0IG9yIG5vdCB0byBrbml0KioKCkluIHRoaXMgcmVwbywgd2l0aCBoYXZlIHNldCB1cCBhIFtHaXRIdWIgYWN0aW9uXShodHRwczovL2dpdGh1Yi5jb20vUmVhbGl0eUJlbmRpbmcvVGVtcGxhdGVSZXN1bHRzL2Jsb2IvbWFpbi8uZ2l0aHViL3dvcmtmbG93cy93ZWJzaXRlLnltbCkgdGhhdCBnZW5lcmF0ZXMgYWxsIHRoZSBvdXRwdXQgZmlsZXMgZXZlcnl0aW1lIHNvbWVvbmUgY29tbWl0IHRvIHRoZSByZXBvc2l0b3J5LiBUaGlzIG1lYW5zIHRoYXQgdGhlIGZpbmFsIGRvY3VtZW50cyBoZXJlIGFyZSBhbHdheXMgInVwLXRvLWRhdGUiIHdpdGggdGhlICpSbWRzKiAoYXMgc2hvd24gYnkgdGhlIGdyZWVuIGJhZGdlKS4gVGhhdCBzYWlkLCB5b3UgY2FuIHJlbW92ZSB0aGlzIEdpdEh1YiBhY3Rpb24gKGp1c3QgcmVtb3ZlIHRoZSBgLmdpdGh1Yi93b3JrZmxvd3Mvd2Vic2l0ZS55bWxgIGZpbGUpIGlmIHlvdSBwcmVmZXIgdG8gZ2VuZXJhdGUgdGhlIGRvY3VtZW50cyBtYW51YWxseSBvbmx5LgoKLSAqKkJ1dCBJIGRvbid0IHdhbnQgZG8gdXBsb2FkIGFsbCBteSBkYXRhKioKCkluIHRoYXQgY2FzZSwgeW91J2xsIG5lZWQgdG8gMSkgZGVhY3RpdmF0ZSAoaS5lLiwgcmVtb3ZlIHRoZSBhY3Rpb24gZmlsZSkgdGhlIGF1dG9tYXRpYyByZW5kZXJpbmcgYnkgR2l0SHViIChhcyBubyBkYXRhIHdpbGwgYmUgc3RvcmVkIG9uIEdpdEh1YikgYW5kIDIpIG1hcmsgdGhlICoqZGF0YSoqIGZvbGRlciBhcyAidG8gYmUgaWdub3JlZCIgKHNvIHRoYXQgaXQgd29uJ3QgYmUgdXBsb2FkZWQpLiBUaGlzIGNhbiBiZSBkb25lIGJ5IGFkZGluZyBgL2RhdGEvYCB0byB0aGUgWyoqLmdpdGlnbm9yZSoqXShodHRwczovL2dpdGh1Yi5jb20vUmVhbGl0eUJlbmRpbmcvVGVtcGxhdGVSZXN1bHRzL2Jsb2IvbWFpbi8uZ2l0aWdub3JlKSBmaWxlICh0aGF0IHlvdSBjYW4gb3BlbiB3aXRoIGEgbm90ZXBhZCkuIFRoaXMgbWVhbnMgdGhhdCB5b3UgY2FuIHN0aWxsIHN0b3JlIHRoZSBkYXRhIGhlcmUgbG9jYWxseSwgYW5kIGdlbmVyYXRlIHRoZSBkb2N1bWVudHMgYWNjb3JkaW5nbHksIGJ1dCB0aGUgZGF0YSBmb2xkZXIgd2lsbCBiZSBpZ25vcmVkIGJ5IGdpdCBhbmQgbmV2ZXIgdXBsb2FkZWQgdG8gR2l0SHViLiBUaGlzIHdheSwgeW91IGNhbiBzdGlsbCBoYXZlIGEgY29vbCB3ZWJzaXRlLCBhbiBvcGVuLWFjY2VzcyBzY3JpcHQsIGJ1dCB0aGUgZGF0YSBpcyBzYWZlIHdpdGggeW91LiBUaGUgb25seSBkb3duIHNpZGUgaXMgdGhhdCB5b3UgaGF2ZSB0byBidWlsZCBpdCBtYW51YWxseSAoY2Fubm90IHVzZSBHaXRIdWIgYWN0aW9ucykuCgotICoqSG93IHRvIGFkZCByZWZlcmVuY2VzPyoqCgpSZWZlcmVuY2VzIGhhdmUgdG8gYmUgYWRkZWQgaW4gYGJpYmAgZm9ybWF0IGluIHRoZSBbKnV0aWxzL2JpYmxpb2dyYXBoeS5iaWIqXShodHRwczovL2dpdGh1Yi5jb20vUmVhbGl0eUJlbmRpbmcvVGVtcGxhdGVSZXN1bHRzL2Jsb2IvbWFpbi91dGlscy9iaWJsaW9ncmFwaHkuYmliKSBmaWxlLCBhbmQgZnVydGhlciByZWZlcmVuY2VkIGluIHRoZSB0ZXh0IGxpa2UgdGhpcyBgW0BsdWRlY2tlMjAxOWluc2lnaHRdYCBbQGx1ZGVja2UyMDE5aW5zaWdodF0uCgotICoqSSBkb24ndCBsaWtlIHRoZSBXb3JkICguZG9jeCkgdGhlbWUqKgoKVGhlIHRoZW1lIGZvciB0aGUgd29yZCBkb2N1bWVudCBpcyBkZWZpbmVkIGluIHRoZSBbKipUZW1wbGF0ZV9Xb3JkLmRvY3hdKGh0dHBzOi8vZ2l0aHViLmNvbS9SZWFsaXR5QmVuZGluZy9UZW1wbGF0ZVJlc3VsdHMvdHJlZS9tYWluL3V0aWxzKSBmaWxlLCBpbiB0aGUgYC91dGlscy9gIGZvbGRlci4gWW91IG5lZWQgdG8gZWRpdCB0aGUgInN0eWxlcyIgKG5vdCBqdXN0IHRoZSBjb250ZW50LCBidXQgdGhlIHN0eWxlIGl0c2VsZikgdG8geW91ciBwcmVmZXJlbmNlLgoKLSAqKkkgaGF2ZSBQeXRob24gY29kZSoqCgpUaGFua3MgdG8gUidzIHBvc3NpYmlsaXRpZXMgd2hlbiBpdCBjb21lcyB0byBpbnRlZ3JhdGlvbiB3aXRoIFB5dGhvbiwgaXQncyBzdXBlciBlYXN5IHRvIGVuYWJsZSBpdCBpbiB5b3VyIHBpcGVsaW5lLiBKdXN0IHVuY29tbWVudCB0aGUgW1B5dGhvbiBpbnN0YWxsYXRpb24gbGluZV0oaHR0cHM6Ly9naXRodWIuY29tL1JlYWxpdHlCZW5kaW5nL1RlbXBsYXRlUmVzdWx0cy9ibG9iL21haW4vdXRpbHMvY29uZmlnLlIjTDI0KSBpbiB0aGUgYHV0aWxzL2NvbmZpZy5SYCBmaWxlIGFuZCB5b3UncmUgcmVhZHkgdG8gZ28hCgotICoqSXQgZG9lc24ndCB3b3JrIC8gSSBoYXZlIHF1ZXN0aW9ucyAvIEkgaGF2ZSBpZGVhcyoqCgpKdXN0IFsqKm9wZW4gYW4gaXNzdWUqKl0oaHR0cHM6Ly9naXRodWIuY29tL1JlYWxpdHlCZW5kaW5nL1RlbXBsYXRlUmVzdWx0cy9pc3N1ZXMpIGFuZCB3ZSdsbCBiZSBoYXBweSB0byBhc3Npc3Qg4pi6CgojIyBTdHJ1Y3R1cmUKCk1vc3QgZmlsZXMgdGhhdCB5b3UnbGwgbmVlZCB0byBjcmVhdGUgLyBlZGl0IHdpbGwgYmUgd3JpdHRlbiBpbiBbKipybWFya2Rvd24qKl0oaHR0cHM6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20vbGVzc29uLTEuaHRtbCksIHdoaWNoIGNvbnNpc3RzIG9mIGEgbWl4IG9mIG1hcmtkb3duIHRleHQgYW5kIFIgY2h1bmtzIG9mIGNvZGUuCgpUaGUgbWFpbiBmaWxlIGlzIG5hbWVkIFsqKmluZGV4LlJtZCoqXShodHRwczovL2dpdGh1Yi5jb20vUmVhbGl0eUJlbmRpbmcvVGVtcGxhdGVSZXN1bHRzL2Jsb2IvbWFpbi9pbmRleC5SbWQpLiBIb3dldmVyLCB0byBhdm9pZCBoYXZpbmcgb3Zlcmx5IGxvbmcgZmlsZXMsIHRoZSBkaWZmZXJlbnQgKGFuZCBpbmRlcGVuZGVudCkgYW5hbHlzZXMgcGFydHMgYXJlIGFjdHVhbGx5IHNwbGl0IGluIG90aGVyIGRvY3VtZW50cy4gRm9yIGluc3RhbmNlLCBpbiB0aGlzIHRlbXBsYXRlIGV4YW1wbGUsIHRoZSBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIHNlY3Rpb24gaXMgaW4gdGhlIFsqKjFfZGVzY3JpcHRpdmUuUm1kKipdKGh0dHBzOi8vZ2l0aHViLmNvbS9SZWFsaXR5QmVuZGluZy9UZW1wbGF0ZVJlc3VsdHMvYmxvYi9tYWluLzFfZGVzY3JpcHRpdmUuUm1kKSBmaWxlLiBBcyB5b3UgY2FuIFtzZWUgaW4gdGhlIGluZGV4IGZpbGVdKGh0dHBzOi8vZ2l0aHViLmNvbS9SZWFsaXR5QmVuZGluZy9UZW1wbGF0ZVJlc3VsdHMvYmxvYi82OTBmNzk0N2RhMGZjOGFjODVlYWY2ZmI4N2ZhZmVhYTQ2ZmIzYzUwL2luZGV4LlJtZCNMODktTDkwKSwgdGhpcyBmaWxlIGlzIHRoZW4gaW50ZWdyYXRlZCBhcyBhIGNoaWxkIGRvY3VtZW50IChpLmUuLCBpdCBpcyBtZXJnZWQpLiBUaGlzIG1ha2VzIGl0IHZlcnkgY29udmVuaWVudCB0byBoYXZlIGEgY2xlYXIgc3RydWN0dXJlIHdpdGggd2VsbC1vcmdhbml6ZWQgZmlsZXMsIHRoYXQgYXJlIHB1dCB0b2dldGhlciBvbmx5IHdoZW4gbWVyZ2VkLgoKIyMgUmVuZGVyIGFuZCBQdWJsaXNoCgpJbXBvcnRhbnRseSwgaW4gb3JkZXIgdG8gcmVuZGVyIGFsbCB0aGUgZmlsZXMsIGRvIG5vdCBLbml0IHRoaXMgZG9jdW1lbnQgYnkgcHJlc3NpbmcgdGhlICdLbml0JyBidXR0b24uIElmIHlvdSBkbywgaXQgd2lsbCBjcmVhdGUgYW4gb3V0cHV0IGZpbGUgKGZvciBpbnN0YW5jZSBgaW5kZXguaHRtbGApIGluIHRoZSByb290IGZvbGRlciwgYWxvbmdzaWRlIGBpbmRleC5SbWRgLiBUaGlzIGlzICoqbm90IHdoYXQgd2Ugd2FudCoqLCBhcyB3ZSB3YW50IHRvIGtlZXAgdGhlIG91dHB1dCBmaWxlcyB0aWR5IGluIHNlcGFyYXRlIGZvbGRlcnMgKGZvciBpbnN0YW5jZSwgdGhlIGh0bWwgdmVyc2lvbiBzaG91bGQgYmUgaW4gdGhlIGAvZG9jcy9gIGZvbGRlciwgYXMgdGhpcyBpcyB3aGVyZSB0aGUgd2Vic2l0ZSB3aWxsIGxvb2sgZm9yKS4KClRoZXJlIGFuIFIgc2NyaXB0LCBbdXRpbHMvcmVuZGVyLlJdKGh0dHBzOi8vZ2l0aHViLmNvbS9SZWFsaXR5QmVuZGluZy9UZW1wbGF0ZVJlc3VsdHMvYmxvYi9tYWluL3V0aWxzL3JlbmRlci5SKSwgdGhhdCBjb250YWlucyB0aGUgbGluZXMgdG8gcmVuZGVyIGV2ZXJ5dGhpbmcgaW4gaXRzIGNvcnJlY3QgbG9jYXRpb24uIFNvLCB3aGVuIHlvdSBoYXZlIHRoZSAiaW5kZXguUm1kIiBmaWxlIG9wZW5lZCAoYW5kIHlvdXIgd29ya2luZyBkaXJlY3RvcnkgaXMgYXQgaXRzIHJvb3QpLCBzaW1wbHkgcnVuICoqYHNvdXJjZSgidXRpbHMvcmVuZGVyLlIiKWAqKiBpbiB0aGUgY29uc29sZSAob3IgdGhlIHJlbGV2YW50IGxpbmVzIGluIHRoYXQgZmlsZSkuIFRoaXMgd2lsbCBydW4gdGhlIHJlbmRlcmluZyBmaWxlIGFuZCBjcmVhdGUgYWxsIHRoZSBmaWxlcy4KCiMjIENvbnRyaWJ1dGlvbgoKRG8gbm90IGhlc2l0YXRlIHRvIGltcHJvdmUgdGhpcyB0ZW1wbGF0ZSBieSB1cGRhdGluZywgZG9jdW1lbnRpbmcsIG9yIGV4cGFuZGluZyBpdCEKCgojIFBhY2thZ2VzICYgRGF0YQoKIyMgUGFja2FnZXMKClRoaXMgZG9jdW1lbnQgd2FzIHByZXBhcmVkIG9uIGByIGZvcm1hdChTeXMuRGF0ZSgpKWAuIAoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1UUlVFLCByZXN1bHRzPSdhc2lzJ30KbGlicmFyeShiYXllc3Rlc3RSKQpsaWJyYXJ5KHBhcmFtZXRlcnMpCmxpYnJhcnkocGVyZm9ybWFuY2UpCmxpYnJhcnkocmVwb3J0KQpsaWJyYXJ5KHNlZSkKbGlicmFyeShnZ3Bsb3QyKQoKc3VtbWFyeShyZXBvcnQ6OnJlcG9ydChzZXNzaW9uSW5mbygpKSkKYGBgCgoKIyMgRGF0YQoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1UUlVFLCByZXN1bHRzPSdhc2lzJ30KZGYgPC0gcmVhZC5jc3YoImRhdGEvZGF0YS5jc3YiKQoKY2F0KHBhc3RlKCJUaGUgZGF0YSBjb25zaXN0cyBvZiIsCiAgICAgICAgICByZXBvcnQ6OnJlcG9ydF9wYXJ0aWNpcGFudHMoZGYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFydGljaXBhbnRzID0gIlBhcnRpY2lwYW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZ2UgPSAiQWdlIikpKQpgYGAKCgoKTm90ZSB0aGF0IHRoZSBjaHVua3MgZ2VuZXJhdGluZyBmaWd1cmVzIGluIHRoZSBjb2RlIGJlbG93IGhhdmUgc29tZSBhcmd1bWVudHMgc3BlY2lmaWVkIGluIHRoZWlyIGhlYWRlciwgc3VjaCBhcyBgZmlnLndpZHRoYCBhbmQgYGZpZy5oZWlnaHRgLCB3aGljaCBjb250cm9scyB0aGUgZmlndXJlIHNpemUuIFRoZXNlIHdlcmUgZmlsbGVkIHdpdGggYW4gZXBvbnltIGFyZ3VtZW50IGRlZmluZWQgaW4gW2B1dGlscy9jb25maWcuUmBdKGh0dHBzOi8vZ2l0aHViLmNvbS9SZWFsaXR5QmVuZGluZy9UZW1wbGF0ZVJlc3VsdHMvYmxvYi9tYWluL3V0aWxzL2NvbmZpZy5SI0wyNi1MMjcpLiBXZSBhbHNvIHNldCB0aGUgcmVzb2x1dGlvbiwgaS5lLiwgYGRwaWAsIHRvIGEgbG93IHZhbHVlIHNvIHRoYXQgdGhlIHJlc3VsdGluZyBmaWxlIGlzIGxpZ2h0ZXIuIEJ1dCAqKmRvbid0IGZvcmdldCB0byBjcmFuayB0aGlzIHZhbHVlIHVwKiogKHRvIDMwMC02MDApIHRvIGdldCBuaWNlLWxvb2tpbmcgcmVzdWx0cy4KCgojIERlc2NyaXB0aXZlIFN0YXRzIHsudGFic2V0fQoKTm90aWNlIHRoZSBgey50YWJzZXR9YCB0YWcgYWZ0ZXIgdGhlIHNlY3Rpb24gbmFtZS4gVGhpcyB3aWxsIHNob3cgdGhlIHN1YnNlY3Rpb25zIGFzIGRpZmZlcmVudCB0YWJzIChpbiB0aGUgW2h0bWwgdmVyc2lvbl0oaHR0cHM6Ly9yZWFsaXR5YmVuZGluZy5naXRodWIuaW8vVGVtcGxhdGVSZXN1bHRzLyNEZXNjcmlwdGl2ZV9TdGF0cykgb25seSwgYmVjYXVzZSB0aGUgb3RoZXIgZm9ybWF0cyBhcmUgc3RhdGljKS4KCgpgYGB7ciBjaGlsZD1pZiAoZmFzdCA9PSBGQUxTRSkgJzFfZGVzY3JpcHRpdmUuUm1kJ30KYGBgCgojIEluZmVyZW50aWFsIFN0YXRzCgpgYGB7ciBjaGlsZD1pZiAoZmFzdCA9PSBGQUxTRSkgJzJfaW5mZXJlbnRpYWwuUm1kJ30KYGBgCgoKIyBGdWxsIENvZGUKClRoZSBmdWxsIHNjcmlwdCBvZiBleGVjdXRpdmUgY29kZSBjb250YWluZWQgaW4gdGhpcyBkb2N1bWVudCBpcyByZXByb2R1Y2VkIGhlcmUuCgpgYGB7ciBmdWxsX2NvZGUsIHJlZi5sYWJlbD1rbml0cjo6YWxsX2xhYmVscygpLCBldmFsPUZBTFNFfQpgYGAKCiMgUGFja2FnZSBSZWZlcmVuY2VzCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30KcmVwb3J0OjpjaXRlX3BhY2thZ2VzKHNlc3Npb25JbmZvKCkpCmBgYAoKCiMgUmVmZXJlbmNlcwo=