Module 3: How to prepare statistical code to share

If you have ever had to go back to a statistical code file you wrote several months earlier and try to figure out what the heck you were doing, you are not alone. Writing well-formatted and organized code is key to making future you happy and for facilitating reproducibility. Sharing clear statistical code not only facilitates reproducibility, but research papers with shared code are cited more,1,2 benefitting you and your field. This module summarizes current recommendations for organizing and formatting statistical code to prepare it for sharing and to improve research collaboration, quality, and reproducibility.

Formatting and organizing code

There are recommendations for clear coding that apply regardless of the statistical language you are using. These practices fall into several categories:

Follow the recommendations below to format your code. We recommend reading through all the recommendations first before you begin to format your code.

Use space wisely

Recommendation #1: Use white space to separate processes

Code that is written without blank lines between procedures can run together and be difficult to interpret. Add an extra line of space before new procedures to make the code easier to follow. For example, this code is dense with little white space, making it difficult to read:

code_data_avail <- cbind(table(r$Q25_2_1),table(r$Q25_2_2))
colnames(code_data_avail) <- c("Did you make your data publicly available?","Did you make your code publicly available?"); code_data_avail <- melt(code_data_avail); colnames(code_data_avail) <- c("avail","data_or_code","number")
fig2 <- ggplot(code_data_avail, aes(x=data_or_code, y=number, fill=avail)) + geom_col(position="dodge") +  coord_flip() +   theme(legend.position = 'top') +   labs(y="Number of participants", x="", fill="") + scale_fill_manual(values=fills)
fig2

Adding some space between procedures starts to make it easier to read:

code_data_avail <- cbind(table(r$Q25_2_1),table(r$Q25_2_2))
colnames(code_data_avail) <- c("Did you make your data publicly available?","Did you make your code publicly available?"); code_data_avail <- melt(code_data_avail); colnames(code_data_avail) <- c("avail","data_or_code","number")

fig2 <- ggplot(code_data_avail, aes(x=data_or_code, y=number, fill=avail)) + geom_col(position="dodge") +  coord_flip() +   theme(legend.position = 'top') +   labs(y="Number of participants", x="", fill="") + scale_fill_manual(values=fills)
fig2

Recommendation #2: Limit line length to 80 characters

Long lines of code are difficult or impossible to see on some computer screens, especially for people using laptop computers. Instead of continuing code on a single line, add hard returns so that code does not go beyond about 80 characters.

code_data_avail <- cbind(table(r$Q25_2_1),table(r$Q25_2_2))
colnames(code_data_avail) <- c("Did you make your data publicly available?", "Did you make your code publicly available?") 
code_data_avail <- melt(code_data_avail)
colnames(code_data_avail) <- c("avail","data_or_code","number")

fig2 <- ggplot(code_data_avail, aes(x=data_or_code, y=number, fill=avail)) + geom_col(position="dodge") +  coord_flip() +   
theme(legend.position = 'top') +   
labs(y="Number of participants", x="", fill="") + scale_fill_manual(values=fills)
fig2

Recommendation #3: Indent to group lines of code that belong together

When a function or procedure is very long, it can take multiple lines of code. To signal that several lines of code go together, indent each line after the first one.

Revise the code to shorten each line and indent lines that go together:

code_data_avail <- cbind(table(r$Q25_2_1),table(r$Q25_2_2))
colnames(code_data_avail) <- c("Did you make your data publicly available?",
                               "Did you make your code publicly available?")
code_data_avail <- melt(code_data_avail)
colnames(code_data_avail) <- c("avail","data_or_code","number")


fig2 <- ggplot(code_data_avail, aes(x=data_or_code, 
                                    y=number, 
                                    fill=avail)) +
  geom_col(position="dodge") +  
  coord_flip() +   
  theme(legend.position = 'top') +   
  labs(y="Number of participants", x="", fill="") +  
  scale_fill_manual(values=fills)
fig2

Choose meaningful names with consistent formatting

Recommendation #4: Use meaningful names for objects

It is common in research for variables to be named something like var1 or vm1q26b during data collection. Often these names are generated automatically from survey software or from using a numbered list in a word processing program. Once data have been collected, however, assigning meaningful names for variables, functions, and files will result in code that is easier to read and use for you and for others.

Meaningful names describe what information is stored in the variable, function, or file. For example, a variable measuring whether or not a participant has ever used a gun would be easier to understand if it were called gun_user or gunUse compared to var1 or even gu. Likewise, a function that multiplies age by packs smoked per day to find pack years for smokers might be called find_pack_years rather than funcpy or even just f or the commonly used foo.

For example, other than -99 representing missing values, there is really nothing to be learned from this code that includes meaningless names:

r$Q11_2[r$Q11_2==-99] <- NA
prop.table(table(r$Q11_2))

Replace r with HEALTH_SURVEY for the data name and Q11_2 with race for the variable name. Now someone otherwise unfamiliar with your code might guess that this bit of code creates a table of race from the health survey data:

HEALTH_SURVEY$race[HEALTH_SURVEY$race==-99] <- NA
prop.table(table(HEALTH_SURVEY$race))

Recommendation #5: Use dot.case, camelCase, or snake_case for multi-part names

Multiword names for variables, functions, and files are are more easily read by humans when they are formatted using dot.case, upper CamelCase, lower camelCase, snake_case, or UPPER_SNAKE_CASE to separate words. Choosing one of these options for variables, another for functions, and another for files will further clarify your code for your collaborators. For example, say your group decides that variables should be named using dot.case, functions with snake_case, data frames with UPPER_SNAKE_CASE, and other objects with lower camelCase.

Even with limited R and programming experience, a new team member could read this code and identify find_mode as a function, HEALTH_SURVEY as data, and insure.status as a variable without knowing anything else:

find_mode(HEALTH_SURVEY$insure.status)

Please note that specific naming conventions may not work in all software. Resources at the bottom of this module provide software-specific recommendations on naming and other conventions.

Recommendation #6: Add meta-data to file names

Including meta-data like the date and project name in file names consistently makes it easier to search for files and process files. There are three key principles for file names:

  1. Machine readable
  2. Human readable
  3. Works with default ordering

Machine readable file names are formatted in a way that can be read into a program and interpreted by the program. This is especially useful if a project includes many data or code files that are used together. Machine readable file names typically include separators, usually an underline, to separate parts of the file name. For example, a CSV data file collected on January 23 of 2017 might be saved as 01232017_projectName.csv. Note that this file name includes a 0 at the beginning rather than a 1 for January. This is important due to default ordering of numbers and letters. If January were coded as simply 1, the file name would be 12317 and default ordering would interpret it as coming after data files from October or November, months 10 and 11. Human readable file names include dates and words formatted in ways that are familiar to people, similar to the meaningful variable names in the section above.

Consider, for example, raw and cleaned data files collected before and after some program was implemented:

  • rprogbdata.csv
  • progbdfinal.csv
  • progdatar.csv
  • cleanprogrdata.csv

You can see some differences in the data names and might try to guess based on these features and maybe the file save date. However, writing the file names like this would allow more certainty:

  • 013018_raw_preProgram.csv
  • 013118_clean_preProgram.csv
  • 022818_raw_postProgram.csv
  • 030218_clean_postProgram.csv

It is clear from these file names which files are raw, which are clean, which are before the program, which are after, and the date the file was saved.

Introduce and explain the code

Recommendation #7: Write a prolog to introduce the code

A prolog is a block of comments at the beginning of a code file offset with special characters as appropriate in the software being used. A prolog is used to provide sufficient information about code for a collaborator (maybe future you!) or someone outside your project to understand the who, what, and why of your code.

For example, here is a prolog formatted for a statistical code file in SAS:

/* PROLOG   ################################################################

   PROJECT: NAME OF PROJECT HERE 
   PURPOSE: MAJOR POINT(S) OF WHAT I AM DOING WITH THE DATA HERE 
   DIR:     list directory(-ies) for files here 
   DATA:    list dataset file names/availability here, e.g., 
            filename.correctextention 
            somewebaddress.com 
   AUTHOR:  AUTHOR NAME(S) 
   CREATED: MONTH dd, YEAR
   LATEST:  MONTH dd, YEAR
   NOTES:   indent all additional lines under each heading, 
            & begin the prolog with a forward slash followed by an asterisk,
            end with an asterisk followed by a forward slash.  
            KEEP PURPOSE, AUTHOR, CREATED & LATEST ENTRIES IN UPPER CASE,  
            with appropriate case for DIR & DATA, lower case for notes 
            If multiple lines become too much, 
            simplify and write code book and readme. 
            HINT #1: Decide what a long prolog is. 
            HINT #2: copy & paste this into new script & replace text.

   PROLOG   ############################################################### */
  

Here is a prolog formatted for a code file in R:

# PROLOG   ################################################################'

# PROJECT: NAME OF PROJECT HERE
# PURPOSE: MAJOR POINT(S) OF WHAT I AM DOING WITH THE DATA HERE
# DIR:     list directory(-ies) for files here
# DATA:    list dataset file names/availability here, e.g.,
#          filename.correctextention 
#          somewebaddress.com 
# AUTHOR:  AUTHOR NAME(S) 
# CREATED: MONTH dd, YEAR 
# LATEST:  MONTH dd, YEAR 
# NOTES:   indent all additional lines under each heading, 
#          & use the apostrophe hashmark bookends that appear  
#          KEEP PURPOSE, AUTHOR, CREATED & LATEST ENTRIES IN UPPER CASE, 
#          with appropriate case for DIR & DATA, lower case for notes 
#          If multiple lines become too much, 
#          simplify and write code book and readme. 
#          HINT #1: Decide what a long prolog is. 
#          HINT #2: copy & paste this into new script & replace text. 

# PROLOG   ###############################################################

Additional prolog templates for SAS, SPSS, Stata, and R are available on GitHub at https://github.com/coding2share/Prolog-templates

Recommendation #8: Annotate to clarify code purpose

While a prolog contains general information about the code, annotation is used throughout the code to describe what is going on. There are different schools of thought on how much or how little annotation is needed. The general goal would be to write clear code that only needs a small amount of annotation.

When commenting, think about what you would want to explain to a new collaborator or how the code reads for someone completely outside your project. With those audiences in mind, add comments to:

  • explain the reason for the code (if needed)
  • explain functionality or choices that are not obvious or are different from expected
  • identify hacks or errors that should be fixed or rewritten; consistently use a word or phrase so this code is easy to find (e.g., HACK or BROKEN)

Avoid using comments to:

  • explain poorly named objects; improve the object name instead (see Recommendation #4)
  • repeat things that can be easily understood from the code

For example, instead of a confusing graph name and a comment stating the obvious:

#ha stands for histogram of age
ha <- hist(age)
ha

Name your graph something logical and comment on why the code is needed:

#check normality assumption for age variable
histoAge <- hist(age)
histoAge

Complete code examples

R example

This R code does not follow the promising practices above and is difficult to read:

library(RNHANES); library(ggplot2)
dat <- nhanes_load_data("AUQ_G", "2011-2012", demographics = TRUE)
summary(dat$AUQ300)
dat$AUQ300[dat$AUQ300 > 2] <- NA
dat$AUQ300 <- factor(dat$AUQ300,levels=c(1,2),labels=c("Yes","No"))
summary(dat$AUQ300)
ggplot(subset(dat, !is.na(AUQ300)),aes(x=AUQ300, y=(..count..)/sum(..count..),fill=AUQ300)) + geom_bar() + theme_minimal() + scale_y_continuous(labels=scales::percent) +  scale_fill_manual(values=c("orange","gray"), guide=FALSE)

First, use space wisely. Adding white space to separate processes, limiting line length to 80 characters, and indenting to group lines of code that belong together can help make the code easier to follow:

library(RNHANES)
library(ggplot2)

dat <- nhanes_load_data("AUQ_G", "2011-2012", 
                        demographics = TRUE)
summary(dat$AUQ300)

dat$AUQ300[dat$AUQ300 > 2] <- NA
dat$AUQ300 <- factor(dat$AUQ300,
                     levels=c(1,2),            
                     labels=c("Yes","No"))
summary(dat$AUQ300)

ggplot(subset(dat, !is.na(AUQ300)),
       aes(x=AUQ300, 
           y=(..count..)/sum(..count..),
           fill=AUQ300)) + 
  geom_bar() + 
  theme_minimal() + 
  scale_y_continuous(labels=scales::percent) +  
  scale_fill_manual(values=c("orange","gray"), 
                    guide=FALSE)

Second, choose meaningful names for objects. Since the code examines the National Health and Nutrition (NHANES) survey data, naming the data object nhanes makes sense. Likewise, the variable AUQ300 measures whether the participant has ever used a gun, so try naming it gun.user:

library(RNHANES)
library(ggplot2)

nhanes <- nhanes_load_data("AUQ_G", "2011-2012", 
                        demographics = TRUE)
summary(nhanes$AUQ300)

nhanes$AUQ300[nhanes$AUQ300 > 2] <- NA
nhanes$gun.user <- factor(nhanes$AUQ300,
                     levels=c(1,2),            
                     labels=c("Yes","No"))
summary(nhanes$gun.user)

ggplot(subset(nhanes, !is.na(gun.user)),
       aes(x=gun.user, 
           y=(..count..)/sum(..count..),
           fill=gun.user)) + 
  geom_bar() + 
  theme_minimal() + 
  scale_y_continuous(labels=scales::percent) +  
  scale_fill_manual(values=c("orange","gray"), 
                    guide=FALSE)

Finally, introduce and explain the code by adding a prolog and annotation. Compare this final version of the code with the first version above:

################################################################
# PROJECT: Gun use policy brief 
# PURPOSE: Bar graph of percentage of gun use for policy brief 
# DIR:     C:/Users/jenine/Desktop/datacamp
# DATA:    NHANES 2011-2012 data available via RNHANES package
# AUTHOR:  Jenine Harris 
# CREATED: 11/28/17 
# LATEST:  11/28/17 
# NOTES:   For coding2share formatting code module
################################################################

#open NHANES package to bring in data
#open ggplot2 for graphing
library(RNHANES)
library(ggplot2)

#bring in NHANES 2011-12 audiology data
#AUQ300 question asks ever used gun
#where 1 = Yes, 2 = No, 7 = Refused, 9 = Don't know
nhanes <- nhanes_load_data("AUQ_G", "2011-2012", 
                           demographics = TRUE)
summary(nhanes$AUQ300)

#delete Refused and Don't know responses
#rename variable to gunUser, add labels to levels
nhanes$AUQ300[nhanes$AUQ300 > 2] <- NA
nhanes$gun.user <- factor(nhanes$AUQ300,
                        levels=c(1,2),
                        labels=c("Yes","No"))
summary(nhanes$gun.user)

#plot bar graph of percent of 2011-2012 NHANES 
#participants who ever used gun
ggplot(subset(nhanes, 
              !is.na(gun.user)),
       aes(x=gun.user, 
           y=(..count..)/sum(..count..),
           fill=gun.user)) + 
  geom_bar() + 
  theme_minimal() + 
  scale_y_continuous(labels=scales::percent) +  
  scale_fill_manual(values=c("orange","gray"), 
                    guide=FALSE)

SPSS example

This SPSS code file example does not follow the promising practices above and it is difficult to decipher where one line of code stops and the next begins.

GET FILE = 'C:\Your\Filepath\nhanes.sav'.
FREQUENCIES VARIABLES = AUQ300.
MISSING VALUES AUQ300 (7,9).
VARIABLE LEVEL AUQ300 (NOMINAL).
VALUE LABELS AUQ300 1 'Yes' 2 'No'.
FREQUENCIES VARIABLES = AUQ300.
GRAPH /BAR(SIMPLE) = PCT BY AUQ300.

First, use space wisely. Adding white space to separate processes, limiting line length to 80 characters, and indenting to group lines of code that belong together can help make the code easier to follow.

GET FILE = 'C:\Your\Filepath\nhanes.sav'.

FREQUENCIES
VARIABLES = AUQ300.

MISSING VALUES AUQ300 (7,9).
VARIABLE LEVEL AUQ300 (NOMINAL).
VALUE LABELS AUQ300
1 'Yes'
2 'No'.

FREQUENCIES
VARIABLES = AUQ300.

GRAPH
/BAR(SIMPLE) = PCT BY AUQ300.

Second, choose meaningful names for the data set and variable labels. Since the code examines the National Health and Nutrition (NHANES) survey data, naming the data set nhanes makes sense. Naming the data set allows several data sets to be open at the same time. Explicitly activate the data set before continuing so it’s clear which one is being modified or used. Likewise, variable labels enable access to more detail about what the variable actually is, so we can include enough of the questionnaire language for it to make sense: “Ever used firearms for any reason?”

GET FILE = 'C:\Your\Filepath\nhanes.sav'.
DATASET NAME nhanes.
DATASET ACTIVATE nhanes.

FREQUENCIES
VARIABLES = AUQ300.

MISSING VALUES AUQ300 (7,9).
VARIABLE LEVEL AUQ300 (NOMINAL).
VALUE LABELS AUQ300
1 'Yes'
2 'No'.
VARIABLE LABELS
AUQ300 'Ever used firearms for any reason?'.

FREQUENCIES
VARIABLES = AUQ300.

GRAPH
/BAR(SIMPLE) = PCT BY AUQ300.

Finally, introduce and explain the code by adding a prolog and annotation. Be sure to include a period at the end of each comment so that the following code command will not get “commented out” by accident. Compare this final version of the code with the first version above:

*** PROLOG ***********************************************************************
*** PROJECT:  Gun use policy brief 
*** PURPOSE:  Bar graph of percentage of gun use for policy brief
*** DIR:      C:\Your\Filepath\nhanes.sav
*** DATA:     https://wwwn.cdc.gov/nchs/nhanes/continuousnhanes/default.aspx?BeginYear=2011
*** AUTHOR:   Bobbi Carothers
*** CREATED:  02/06/2018
*** LATEST:   02/06/2018
*** NOTES:    For coding2share formatting code module
*** PROLOG   *********************************************************************.
      
* Open, name, and activate data.
GET FILE = 'C:\Your\Filepath\nhanes.sav'.
DATASET NAME nhanes.
DATASET ACTIVATE nhanes.

* 1 = Yes, 2 = No, 7 = Refused, 9 = Don't know.
FREQUENCIES
VARIABLES = AUQ300.

* Clean and format.
* Set 7 and 9 as missing values.
MISSING VALUES AUQ300 (7,9).
VARIABLE LEVEL AUQ300 (NOMINAL).
VALUE LABELS AUQ300
1 'Yes'
2 'No'.
VARIABLE LABELS
AUQ300 'Ever used firearms for any reason?'.

FREQUENCIES
VARIABLES = AUQ300.

* Plot bar graph of percent of 2011-2012 NHANES participants who ever used gun.
GRAPH
/BAR(SIMPLE) = PCT BY AUQ300.

Stata example

This Stata code file example does not follow the promising practices above and it is difficult to decipher where one line of code stops and the next begins.

sysuse uslifeexp
des
tsset year
twoway (tsline le) (tsline le_male) (tsline le_female) (tsline le_w) (tsline le_wmale) ///
(tsline le_wfemale) (tsline le_b) (tsline le_bmale) (tsline le_bfemale)
label var le "Life expectancy, overall"
twoway (tsline le) (tsline le_male) (tsline le_female) (tsline le_w) (tsline le_wmale) ///
(tsline le_wfemale) (tsline le_b) (tsline le_bmale) (tsline le_bfemale)
twoway (tsline le) (tsline le_male) (tsline le_female) (tsline le_w) (tsline le_wmale) ///
(tsline le_wfemale) (tsline le_b) (tsline le_bmale) (tsline le_bfemale), yti("Age in years") ///
ti("Life expectancy in the U.S. by population group, 1900-1999")

First, use space wisely. Adding white space to separate processes, limiting line length to 80 characters, and indenting to group lines of code that belong together can help make the code easier to follow. Notice that Stata’s do-file editor comes with a faint line at 80 characters indicating that you should keep lines of code to this length. Second, notice that our recommendation to choose meaningful names for objects (in this case, variables) is met by the stock data set in Stata. The describe function shows us that “le” stands for “life expectancy” and that “b” & “w” stand for “black/African American” and “white”. With a small data set like this, these short variable names are informative and quick to type.

sysuse uslifeexp

des

tsset year

twoway (tsline le) (tsline le_male) (tsline le_female) (tsline le_w) ///
(tsline le_wmale) (tsline le_wfemale) (tsline le_b) ///
(tsline le_bmale) (tsline le_bfemale)

label var le "Life expectancy, overall"

twoway (tsline le) (tsline le_male) (tsline le_female) (tsline le_w) ///
(tsline le_wmale) (tsline le_wfemale) ///
(tsline le_b) (tsline le_bmale) (tsline le_bfemale)

twoway (tsline le) (tsline le_male) (tsline le_female) (tsline le_w) ///
(tsline le_wmale) (tsline le_wfemale) (tsline le_b) ///
(tsline le_bmale) (tsline le_bfemale), yti("Age in years") ///
ti("Life expectancy in the U.S. by population group, 1900-1999")

Finally, introduce and explain the code by adding a prolog and annotation. Compare this final version of the code with the first version above:

/* PROLOG   ################################################################
   
   PROJECT: Life expectancy in U.S. brief
   PURPOSE: Line graph by gender & race: 1900-1999
   DIR:     C:/Users/Todd/OpenScience/modules 
   DATA:    uslifeexp.dta
   AUTHOR:  Todd Combs 
   CREATED: 1/23/18
   LATEST:  1/23/18
   NOTES:   For coding2share formatting code module 
            
   PROLOG   ############################################################### */
    
**load data (example dataset from Stata)
sysuse uslifeexp

**inspect data - variables, labels
des

**declare dataset as time-series data
tsset year

**preliminary graph; 9 lines on same plot for comparison
twoway (tsline le) (tsline le_male) (tsline le_female) (tsline le_w) ///
(tsline le_wmale) (tsline le_wfemale) (tsline le_b) ///
(tsline le_bmale) (tsline le_bfemale)

**give overall LE variable a descriptive label
label var le "Life expectancy, overall"

**check new label
twoway (tsline le) (tsline le_male) (tsline le_female) (tsline le_w) ///
(tsline le_wmale) (tsline le_wfemale) ///
(tsline le_b) (tsline le_bmale) (tsline le_bfemale)

**add descriptive title & y-axis label
twoway (tsline le) (tsline le_male) (tsline le_female) (tsline le_w) ///
(tsline le_wmale) (tsline le_wfemale) (tsline le_b) ///
(tsline le_bmale) (tsline le_bfemale), yti("Age in years") ///
ti("Life expectancy in the U.S. by population group, 1900-1999")

SAS example

This SAS code file example does not follow the promising practices above and it is difficult to decipher where one line of code stops and the next begins.

libname OpenSci '\\tsclient\G\CPHSS\OpenScience\Modules\Coding\';
data OpenSci.cor;
set OpenSci.new_w4bmi;
if H4WP25 in (0,7) then H4WP25_1=0;
else if H4WP25 in (1,2,3) then H4WP25_1=1;
if H4WP39 in (0,7) then H4WP39_1=0; else if H4WP39 in (6,8) then H4WP39_1=.; else H4WP39_1=1;
if H4WP25_1=1 or H4WP39_1=1 then new=1; else if H4WP25_1=0 and H4WP39_1=0 then new=0;
label new="Cash from parents"; run;
proc format; value new 0="NO" 1="YES";run;
proc freq;
tables new*H4WP25_1*H4WP39_1 /list missprint; run;
proc corr; var new; with fastfood; run;

First, use space wisely. Limit line length to 80 characters, indent group lines of code that belong together, use all CAPS for DATA and PROC functions and end all DATA and PROC steps with RUN statement. Notice that SAS automatically comes up with a faint line signaling that the lines above go together. This step facilitates scanning a page for step boundaries and can help make the code easier to follow.

libname OpenSci '\\tsclient\G\CPHSS\OpenScience\Modules\Coding\';
DATA OpenSci.cor;
set OpenSci.new_w4bmi;
if H4WP25 in (0,7) then H4WP25_1=0;
else if H4WP25 in (1,2,3) then H4WP25_1=1;
if H4WP39 in (0,7) then H4WP39_1=0;
else if H4WP39 in (6,8) then H4WP39_1=.;
else H4WP39_1=1;
if H4WP25_1=1 or H4WP39_1=1 then new=1;
else if H4WP25_1=0 and H4WP39_1=0 then new=0;
label new="Cash from parents";
RUN;
PROC FORMAT;
value new 0="NO" 1="YES";
RUN;
PROC FREQ;
tables new*H4WP25_1*H4WP39_1 /list missprint;
RUN;
PROC CORR;
var new;
with fastfood;
RUN;

Second, choose meaningful names for objects. Since the code examines the data about youth health, naming the data object Youth_Health makes sense. Likewise, the variable H4WP25 and H4WP39 measures the cash mom and dad gave to the youths, so try naming them as Mom_Cash and Dad_Cash, and naming the new combined variable as Parent_Cash.

libname OpenSci '\\tsclient\G\CPHSS\OpenScience\Modules\Coding\';
DATA OpenSci.Youth_Health;
set OpenSci.new_w4bmi;
if H4WP25 in (0,7) then Mom_cash=0;
else if H4WP25 in (1,2,3) then Mom_cash=1;
if H4WP39 in (0,7) then Dad_cash=0;
else if H4WP39 in (6,8) then Dad_cash=.;
else Dad_cash=1;
if Mom_cash=1 or Dad_cash=1 then Parent_cash=1;
else if Mom_cash=0 and Dad_cash=0 then Parent_cash=0;
label Parent_cash = "Cash from parents";
RUN;
PROC FORMAT;
value Parent_cash 0="NO" 1="YES";
RUN;
PROC FREQ;
tables Parent_cash*Mom_cash*Dad_cash /list missprint;
RUN;
PROC CORR;
var Parent_cash;
with fastfood;
RUN;

Finally, introduce and explain the code by adding a prolog and annotation. Compare this final version of the code with the first version above:

/* PROLOG   ################################################################

   PROJECT: Youth Health 
   PURPOSE: Correlation between cash from parents with fastfood eating patterns
   DIR:     G:\CPHSS\OpenScience\Modules\Coding
   DATA:    new_w4bmi.sas7bdat
   AUTHOR:  Xiaoyan Wang
   CREATED: 1/31/2018
   LATEST:  2/5/2018
   NOTES:   For coding2share formatting code module

   PROLOG   ############################################################### */
   
*Create a new SAS library, and assign it to a specific directory;
libname OpenSci '\\tsclient\G\CPHSS\OpenScience\Modules\Coding\';
*Recode variables to binary variables;
*Create a new variable called Parent_Cash;
DATA OpenSci.Youth_Health;
set OpenSci.new_w4bmi;
if H4WP25 in (0,7) then Mom_cash=0;
else if H4WP25 in (1,2,3) then Mom_cash=1;
if H4WP39 in (0,7) then Dad_cash=0;
else if H4WP39 in (6,8) then Dad_cash=.;
else Dad_cash=1;
if Mom_cash=1 or Dad_cash=1 then Parent_cash=1;
else if Mom_cash=0 and Dad_cash=0 then Parent_cash=0;
label Parent_cash = "Cash from parents";
RUN;
*Label the values of the Parent_Cash variable;
PROC FORMAT;
value Parent_cash 0="NO" 1="YES";
RUN;
*Check whether the Parent_Cash variable was created correctly;
PROC FREQ;
tables Parent_cash*Mom_cash*Dad_cash /list missprint;
RUN;
*Explore the correlation between parent cash and fastfood eating frequency;
PROC CORR;
var Parent_cash;
with fastfood;
RUN;
LS0tDQp0aXRsZTogIk1vZHVsZSAzIg0Kb3V0cHV0Og0KICAgDQogIGh0bWxfbm90ZWJvb2s6IA0KICAgIGNvZGVfZm9sZGluZzogbm9uZQ0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBkZl9wcmludDogdGliYmxlDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6IA0KICAgICAgY29sbGFwc2VkOiB0cnVlDQogICAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlDQogICAgaW5jbHVkZXM6DQogICAgICAgYWZ0ZXJfYm9keTogRzpcXENQSFNTXFxPcGVuU2NpZW5jZVxcTW9kdWxlc1xcU3R5bGVzaGVldHNcXEZvb3QuaHRtbA0KYmlibGlvZ3JhcGh5OiBHOi9DUEhTUy9PcGVuU2NpZW5jZS9Xcml0ZVVwcy9haW0xU3VydmV5UGFwZXIvUmVwcm9TdXJ2ZXlQYXBlcl8wMjEyMjAxOC5iaWJ0ZXgNCmNzbDogRzovQ1BIU1MvT3BlblNjaWVuY2UvV3JpdGVVcHMvYWltMVN1cnZleVBhcGVyL2FtZXJpY2FuLW1lZGljYWwtYXNzb2NpYXRpb24tbm8tdXJsLkNTTA0KLS0tDQo8aGVhZHsjdG9wfT4NCg0KPHNjcmlwdCBzcmMgPSAiRzpcXENQSFNTXFxPcGVuU2NpZW5jZVxcTW9kdWxlc1xcU3R5bGVzaGVldHNcXE1haW4uanMiPjwvc2NyaXB0Pg0KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiB0eXBlPSJ0ZXh0L2NzcyIgaHJlZj0iRzpcXENQSFNTXFxPcGVuU2NpZW5jZVxcTW9kdWxlc1xcU3R5bGVzaGVldHNcXE1haW5TdHlsZS5jc3MiPg0KYGBge3IsIGVjaG89RkFMU0V9DQpodG1sdG9vbHM6OmluY2x1ZGVIVE1MKCJHOlxcQ1BIU1NcXE9wZW5TY2llbmNlXFxNb2R1bGVzXFxTdHlsZXNoZWV0c1xcTmF2YmFyLmh0bWwiKQ0KYGBgDQo8aW1nIGNsYXNzPSJsb2dvIiBzcmMgPSAiRzpcXENQSFNTXFxPcGVuU2NpZW5jZVxcTW9kdWxlc1xcYzJzLWxvZ28tZm9yLW1vZHVsZXMuanBnIj4NCiAgIA0KPC9oZWFkPg0KDQpgYGB7ciBzZXR1cE9wdHMsIGVjaG89RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTgsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UpDQojIERvbid0IHNldCBlY2hvIHRvIGZhbHNlIGZvciB0aGUgb3ZlcmFsbCBvcHRpb25zIC0gciBjb2RlIGNodW5rcyBiZWxvdyBuZWVkIHRvIGFwcGVhcg0KYGBgDQojTW9kdWxlIDM6IEhvdyB0byBwcmVwYXJlIHN0YXRpc3RpY2FsIGNvZGUgdG8gc2hhcmUgDQoNCklmIHlvdSBoYXZlIGV2ZXIgaGFkIHRvIGdvIGJhY2sgdG8gYSBzdGF0aXN0aWNhbCBjb2RlIGZpbGUgeW91IHdyb3RlIHNldmVyYWwgbW9udGhzIGVhcmxpZXIgYW5kIHRyeSB0byBmaWd1cmUgb3V0IHdoYXQgdGhlIGhlY2sgeW91IHdlcmUgZG9pbmcsIHlvdSBhcmUgbm90IGFsb25lLiBXcml0aW5nIHdlbGwtZm9ybWF0dGVkIGFuZCBvcmdhbml6ZWQgY29kZSBpcyBrZXkgdG8gbWFraW5nICpmdXR1cmUgeW91KiBoYXBweSBhbmQgZm9yIGZhY2lsaXRhdGluZyByZXByb2R1Y2liaWxpdHkuIFNoYXJpbmcgY2xlYXIgc3RhdGlzdGljYWwgY29kZSBub3Qgb25seSBmYWNpbGl0YXRlcyByZXByb2R1Y2liaWxpdHksIGJ1dCByZXNlYXJjaCBwYXBlcnMgd2l0aCBzaGFyZWQgY29kZSBhcmUgKipjaXRlZCBtb3JlKiosIFtAUmVmV29ya3M6MjE4MTtAUmVmV29ya3M6MjMxNF0gYmVuZWZpdHRpbmcgeW91IGFuZCB5b3VyIGZpZWxkLiBUaGlzIG1vZHVsZSBzdW1tYXJpemVzIGN1cnJlbnQgcmVjb21tZW5kYXRpb25zIGZvciBvcmdhbml6aW5nIGFuZCBmb3JtYXR0aW5nIHN0YXRpc3RpY2FsIGNvZGUgdG8gcHJlcGFyZSBpdCBmb3Igc2hhcmluZyBhbmQgdG8gaW1wcm92ZSByZXNlYXJjaCBjb2xsYWJvcmF0aW9uLCBxdWFsaXR5LCBhbmQgcmVwcm9kdWNpYmlsaXR5LiAgDQoNCiMjRm9ybWF0dGluZyBhbmQgb3JnYW5pemluZyBjb2RlDQoNClRoZXJlIGFyZSByZWNvbW1lbmRhdGlvbnMgZm9yIGNsZWFyIGNvZGluZyB0aGF0IGFwcGx5IHJlZ2FyZGxlc3Mgb2YgdGhlIHN0YXRpc3RpY2FsIGxhbmd1YWdlIHlvdSBhcmUgdXNpbmcuIFRoZXNlIHByYWN0aWNlcyBmYWxsIGludG8gc2V2ZXJhbCBjYXRlZ29yaWVzOiANCg0KKiBbVXNlIHNwYWNlIHdpc2VseV0oI3NwYWNlKSANCiogW0Nob29zZSBtZWFuaW5nZnVsIG5hbWVzIHdpdGggY29uc2lzdGVudCBmb3JtYXR0aW5nXSgjbmFtZXMpIA0KKiBbSW50cm9kdWNlIGFuZCBleHBsYWluIHRoZSBjb2RlXSgjaW50cm8pIA0KDQpGb2xsb3cgdGhlIHJlY29tbWVuZGF0aW9ucyBiZWxvdyB0byBmb3JtYXQgeW91ciBjb2RlLiBXZSByZWNvbW1lbmQgcmVhZGluZyB0aHJvdWdoIGFsbCB0aGUgcmVjb21tZW5kYXRpb25zIGZpcnN0IGJlZm9yZSB5b3UgYmVnaW4gdG8gZm9ybWF0IHlvdXIgY29kZS4NCg0KIyMjVXNlIHNwYWNlIHdpc2VseSB7I3NwYWNlfQ0KDQojIyMjUmVjb21tZW5kYXRpb24gIzE6IFVzZSB3aGl0ZSBzcGFjZSB0byBzZXBhcmF0ZSBwcm9jZXNzZXMgDQoNCkNvZGUgdGhhdCBpcyB3cml0dGVuIHdpdGhvdXQgYmxhbmsgbGluZXMgYmV0d2VlbiBwcm9jZWR1cmVzIGNhbiBydW4gdG9nZXRoZXIgYW5kIGJlIGRpZmZpY3VsdCB0byBpbnRlcnByZXQuIEFkZCBhbiBleHRyYSBsaW5lIG9mIHNwYWNlIGJlZm9yZSBuZXcgcHJvY2VkdXJlcyB0byBtYWtlIHRoZSBjb2RlIGVhc2llciB0byBmb2xsb3cuIEZvciBleGFtcGxlLCB0aGlzIGNvZGUgaXMgZGVuc2Ugd2l0aCBsaXR0bGUgd2hpdGUgc3BhY2UsIG1ha2luZyBpdCBkaWZmaWN1bHQgdG8gcmVhZDoNCg0KYGBge3IgZXZhbD1GQUxTRX0NCmNvZGVfZGF0YV9hdmFpbCA8LSBjYmluZCh0YWJsZShyJFEyNV8yXzEpLHRhYmxlKHIkUTI1XzJfMikpDQpjb2xuYW1lcyhjb2RlX2RhdGFfYXZhaWwpIDwtIGMoIkRpZCB5b3UgbWFrZSB5b3VyIGRhdGEgcHVibGljbHkgYXZhaWxhYmxlPyIsIkRpZCB5b3UgbWFrZSB5b3VyIGNvZGUgcHVibGljbHkgYXZhaWxhYmxlPyIpOyBjb2RlX2RhdGFfYXZhaWwgPC0gbWVsdChjb2RlX2RhdGFfYXZhaWwpOyBjb2xuYW1lcyhjb2RlX2RhdGFfYXZhaWwpIDwtIGMoImF2YWlsIiwiZGF0YV9vcl9jb2RlIiwibnVtYmVyIikNCmZpZzIgPC0gZ2dwbG90KGNvZGVfZGF0YV9hdmFpbCwgYWVzKHg9ZGF0YV9vcl9jb2RlLCB5PW51bWJlciwgZmlsbD1hdmFpbCkpICsgZ2VvbV9jb2wocG9zaXRpb249ImRvZGdlIikgKyAgY29vcmRfZmxpcCgpICsgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAndG9wJykgKyAgIGxhYnMoeT0iTnVtYmVyIG9mIHBhcnRpY2lwYW50cyIsIHg9IiIsIGZpbGw9IiIpICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWZpbGxzKQ0KZmlnMg0KYGBgDQoNCkFkZGluZyBzb21lIHNwYWNlIGJldHdlZW4gcHJvY2VkdXJlcyBzdGFydHMgdG8gbWFrZSBpdCBlYXNpZXIgdG8gcmVhZDoNCg0KYGBge3IgZXZhbCA9IEZBTFNFfQ0KY29kZV9kYXRhX2F2YWlsIDwtIGNiaW5kKHRhYmxlKHIkUTI1XzJfMSksdGFibGUociRRMjVfMl8yKSkNCmNvbG5hbWVzKGNvZGVfZGF0YV9hdmFpbCkgPC0gYygiRGlkIHlvdSBtYWtlIHlvdXIgZGF0YSBwdWJsaWNseSBhdmFpbGFibGU/IiwiRGlkIHlvdSBtYWtlIHlvdXIgY29kZSBwdWJsaWNseSBhdmFpbGFibGU/Iik7IGNvZGVfZGF0YV9hdmFpbCA8LSBtZWx0KGNvZGVfZGF0YV9hdmFpbCk7IGNvbG5hbWVzKGNvZGVfZGF0YV9hdmFpbCkgPC0gYygiYXZhaWwiLCJkYXRhX29yX2NvZGUiLCJudW1iZXIiKQ0KDQpmaWcyIDwtIGdncGxvdChjb2RlX2RhdGFfYXZhaWwsIGFlcyh4PWRhdGFfb3JfY29kZSwgeT1udW1iZXIsIGZpbGw9YXZhaWwpKSArIGdlb21fY29sKHBvc2l0aW9uPSJkb2RnZSIpICsgIGNvb3JkX2ZsaXAoKSArICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ3RvcCcpICsgICBsYWJzKHk9Ik51bWJlciBvZiBwYXJ0aWNpcGFudHMiLCB4PSIiLCBmaWxsPSIiKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1maWxscykNCmZpZzINCmBgYA0KDQojIyMjUmVjb21tZW5kYXRpb24gIzI6IExpbWl0IGxpbmUgbGVuZ3RoIHRvIDgwIGNoYXJhY3RlcnMgDQoNCkxvbmcgbGluZXMgb2YgY29kZSBhcmUgZGlmZmljdWx0IG9yIGltcG9zc2libGUgdG8gc2VlIG9uIHNvbWUgY29tcHV0ZXIgc2NyZWVucywgZXNwZWNpYWxseSBmb3IgcGVvcGxlIHVzaW5nIGxhcHRvcCBjb21wdXRlcnMuIEluc3RlYWQgb2YgY29udGludWluZyBjb2RlIG9uIGEgc2luZ2xlIGxpbmUsIGFkZCBoYXJkIHJldHVybnMgc28gdGhhdCBjb2RlIGRvZXMgbm90IGdvIGJleW9uZCBhYm91dCA4MCBjaGFyYWN0ZXJzLiANCg0KYGBge3IgZXZhbCA9IEZBTFNFfQ0KY29kZV9kYXRhX2F2YWlsIDwtIGNiaW5kKHRhYmxlKHIkUTI1XzJfMSksdGFibGUociRRMjVfMl8yKSkNCmNvbG5hbWVzKGNvZGVfZGF0YV9hdmFpbCkgPC0gYygiRGlkIHlvdSBtYWtlIHlvdXIgZGF0YSBwdWJsaWNseSBhdmFpbGFibGU/IiwgIkRpZCB5b3UgbWFrZSB5b3VyIGNvZGUgcHVibGljbHkgYXZhaWxhYmxlPyIpIA0KY29kZV9kYXRhX2F2YWlsIDwtIG1lbHQoY29kZV9kYXRhX2F2YWlsKQ0KY29sbmFtZXMoY29kZV9kYXRhX2F2YWlsKSA8LSBjKCJhdmFpbCIsImRhdGFfb3JfY29kZSIsIm51bWJlciIpDQoNCmZpZzIgPC0gZ2dwbG90KGNvZGVfZGF0YV9hdmFpbCwgYWVzKHg9ZGF0YV9vcl9jb2RlLCB5PW51bWJlciwgZmlsbD1hdmFpbCkpICsgZ2VvbV9jb2wocG9zaXRpb249ImRvZGdlIikgKyAgY29vcmRfZmxpcCgpICsgICANCnRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICd0b3AnKSArICAgDQpsYWJzKHk9Ik51bWJlciBvZiBwYXJ0aWNpcGFudHMiLCB4PSIiLCBmaWxsPSIiKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1maWxscykNCmZpZzINCmBgYA0KDQojIyMjUmVjb21tZW5kYXRpb24gIzM6IEluZGVudCB0byBncm91cCBsaW5lcyBvZiBjb2RlIHRoYXQgYmVsb25nIHRvZ2V0aGVyIA0KDQpXaGVuIGEgZnVuY3Rpb24gb3IgcHJvY2VkdXJlIGlzIHZlcnkgbG9uZywgaXQgY2FuIHRha2UgbXVsdGlwbGUgbGluZXMgb2YgY29kZS4gVG8gc2lnbmFsIHRoYXQgc2V2ZXJhbCBsaW5lcyBvZiBjb2RlIGdvIHRvZ2V0aGVyLCBpbmRlbnQgZWFjaCBsaW5lIGFmdGVyIHRoZSBmaXJzdCBvbmUuDQoNClJldmlzZSB0aGUgY29kZSB0byBzaG9ydGVuIGVhY2ggbGluZSBhbmQgaW5kZW50IGxpbmVzIHRoYXQgZ28gdG9nZXRoZXI6DQoNCmBgYHtyIGV2YWwgPSBGQUxTRX0NCg0KY29kZV9kYXRhX2F2YWlsIDwtIGNiaW5kKHRhYmxlKHIkUTI1XzJfMSksdGFibGUociRRMjVfMl8yKSkNCmNvbG5hbWVzKGNvZGVfZGF0YV9hdmFpbCkgPC0gYygiRGlkIHlvdSBtYWtlIHlvdXIgZGF0YSBwdWJsaWNseSBhdmFpbGFibGU/IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRGlkIHlvdSBtYWtlIHlvdXIgY29kZSBwdWJsaWNseSBhdmFpbGFibGU/IikNCmNvZGVfZGF0YV9hdmFpbCA8LSBtZWx0KGNvZGVfZGF0YV9hdmFpbCkNCmNvbG5hbWVzKGNvZGVfZGF0YV9hdmFpbCkgPC0gYygiYXZhaWwiLCJkYXRhX29yX2NvZGUiLCJudW1iZXIiKQ0KDQoNCmZpZzIgPC0gZ2dwbG90KGNvZGVfZGF0YV9hdmFpbCwgYWVzKHg9ZGF0YV9vcl9jb2RlLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9bnVtYmVyLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9YXZhaWwpKSArDQogIGdlb21fY29sKHBvc2l0aW9uPSJkb2RnZSIpICsgIA0KICBjb29yZF9mbGlwKCkgKyAgIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAndG9wJykgKyAgIA0KICBsYWJzKHk9Ik51bWJlciBvZiBwYXJ0aWNpcGFudHMiLCB4PSIiLCBmaWxsPSIiKSArICANCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWZpbGxzKQ0KZmlnMg0KYGBgDQoNCiMjI0Nob29zZSBtZWFuaW5nZnVsIG5hbWVzIHdpdGggY29uc2lzdGVudCBmb3JtYXR0aW5nIHsjbmFtZXN9DQoNCiMjIyNSZWNvbW1lbmRhdGlvbiAjNDogVXNlIG1lYW5pbmdmdWwgbmFtZXMgZm9yIG9iamVjdHMgeyNSNH0NCg0KSXQgaXMgY29tbW9uIGluIHJlc2VhcmNoIGZvciB2YXJpYWJsZXMgdG8gYmUgbmFtZWQgc29tZXRoaW5nIGxpa2UgYHZhcjFgIG9yIGB2bTFxMjZiYCBkdXJpbmcgZGF0YSBjb2xsZWN0aW9uLiBPZnRlbiB0aGVzZSBuYW1lcyBhcmUgZ2VuZXJhdGVkIGF1dG9tYXRpY2FsbHkgZnJvbSBzdXJ2ZXkgc29mdHdhcmUgb3IgZnJvbSB1c2luZyBhIG51bWJlcmVkIGxpc3QgaW4gYSB3b3JkIHByb2Nlc3NpbmcgcHJvZ3JhbS4gT25jZSBkYXRhIGhhdmUgYmVlbiBjb2xsZWN0ZWQsIGhvd2V2ZXIsIGFzc2lnbmluZyAqKm1lYW5pbmdmdWwqKiBuYW1lcyBmb3IgdmFyaWFibGVzLCBmdW5jdGlvbnMsIGFuZCBmaWxlcyB3aWxsIHJlc3VsdCBpbiBjb2RlIHRoYXQgaXMgZWFzaWVyIHRvIHJlYWQgYW5kIHVzZSBmb3IgeW91IGFuZCBmb3Igb3RoZXJzLiANCg0KKipNZWFuaW5nZnVsIG5hbWVzKiogZGVzY3JpYmUgd2hhdCBpbmZvcm1hdGlvbiBpcyBzdG9yZWQgaW4gdGhlIHZhcmlhYmxlLCBmdW5jdGlvbiwgb3IgZmlsZS4gRm9yIGV4YW1wbGUsIGEgdmFyaWFibGUgbWVhc3VyaW5nIHdoZXRoZXIgb3Igbm90IGEgcGFydGljaXBhbnQgaGFzIGV2ZXIgdXNlZCBhIGd1biB3b3VsZCBiZSBlYXNpZXIgdG8gdW5kZXJzdGFuZCBpZiBpdCB3ZXJlIGNhbGxlZCBgZ3VuX3VzZXJgIG9yIGBndW5Vc2VgIGNvbXBhcmVkIHRvIGB2YXIxYCBvciBldmVuIGBndWAuIExpa2V3aXNlLCBhIGZ1bmN0aW9uIHRoYXQgbXVsdGlwbGllcyBhZ2UgYnkgcGFja3Mgc21va2VkIHBlciBkYXkgdG8gZmluZCBwYWNrIHllYXJzIGZvciBzbW9rZXJzIG1pZ2h0IGJlIGNhbGxlZCBgZmluZF9wYWNrX3llYXJzYCByYXRoZXIgdGhhbiBgZnVuY3B5YCBvciBldmVuIGp1c3QgYGZgIG9yIHRoZSBjb21tb25seSB1c2VkIGBmb29gLg0KDQpGb3IgZXhhbXBsZSwgb3RoZXIgdGhhbiAtOTkgcmVwcmVzZW50aW5nIG1pc3NpbmcgdmFsdWVzLCB0aGVyZSBpcyByZWFsbHkgbm90aGluZyB0byBiZSBsZWFybmVkIGZyb20gdGhpcyBjb2RlIHRoYXQgaW5jbHVkZXMgbWVhbmluZ2xlc3MgbmFtZXM6DQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpyJFExMV8yW3IkUTExXzI9PS05OV0gPC0gTkENCnByb3AudGFibGUodGFibGUociRRMTFfMikpDQpgYGANCg0KUmVwbGFjZSBgcmAgd2l0aCBgSEVBTFRIX1NVUlZFWWAgZm9yIHRoZSBkYXRhIG5hbWUgYW5kIGBRMTFfMmAgd2l0aCBgcmFjZWAgZm9yIHRoZSB2YXJpYWJsZSBuYW1lLiBOb3cgc29tZW9uZSBvdGhlcndpc2UgdW5mYW1pbGlhciB3aXRoIHlvdXIgY29kZSBtaWdodCBndWVzcyB0aGF0IHRoaXMgYml0IG9mIGNvZGUgY3JlYXRlcyBhIHRhYmxlIG9mIHJhY2UgZnJvbSB0aGUgaGVhbHRoIHN1cnZleSBkYXRhOg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KSEVBTFRIX1NVUlZFWSRyYWNlW0hFQUxUSF9TVVJWRVkkcmFjZT09LTk5XSA8LSBOQQ0KcHJvcC50YWJsZSh0YWJsZShIRUFMVEhfU1VSVkVZJHJhY2UpKQ0KYGBgDQoNCg0KIyMjI1JlY29tbWVuZGF0aW9uICM1OiBVc2UgZG90LmNhc2UsIGNhbWVsQ2FzZSwgb3Igc25ha2VfY2FzZSBmb3IgbXVsdGktcGFydCBuYW1lcw0KDQpNdWx0aXdvcmQgbmFtZXMgZm9yIHZhcmlhYmxlcywgZnVuY3Rpb25zLCBhbmQgZmlsZXMgYXJlIGFyZSBtb3JlIGVhc2lseSByZWFkIGJ5IGh1bWFucyB3aGVuIHRoZXkgYXJlIGZvcm1hdHRlZCB1c2luZyAqKmRvdC5jYXNlKiosICoqdXBwZXIgQ2FtZWxDYXNlKiosICoqbG93ZXIgY2FtZWxDYXNlKiosICoqc25ha2VfY2FzZSoqLCBvciAqKlVQUEVSX1NOQUtFX0NBU0UqKiB0byBzZXBhcmF0ZSB3b3Jkcy4gQ2hvb3Npbmcgb25lIG9mIHRoZXNlIG9wdGlvbnMgZm9yIHZhcmlhYmxlcywgYW5vdGhlciBmb3IgZnVuY3Rpb25zLCBhbmQgYW5vdGhlciBmb3IgZmlsZXMgd2lsbCBmdXJ0aGVyIGNsYXJpZnkgeW91ciBjb2RlIGZvciB5b3VyIGNvbGxhYm9yYXRvcnMuIEZvciBleGFtcGxlLCBzYXkgeW91ciBncm91cCBkZWNpZGVzIHRoYXQgdmFyaWFibGVzIHNob3VsZCBiZSBuYW1lZCB1c2luZyBkb3QuY2FzZSwgZnVuY3Rpb25zIHdpdGggc25ha2VfY2FzZSwgZGF0YSBmcmFtZXMgd2l0aCBVUFBFUl9TTkFLRV9DQVNFLCBhbmQgb3RoZXIgb2JqZWN0cyB3aXRoIGxvd2VyIGNhbWVsQ2FzZS4gDQoNCkV2ZW4gd2l0aCBsaW1pdGVkIFIgYW5kIHByb2dyYW1taW5nIGV4cGVyaWVuY2UsIGEgbmV3IHRlYW0gbWVtYmVyIGNvdWxkIHJlYWQgdGhpcyBjb2RlIGFuZCBpZGVudGlmeSBgZmluZF9tb2RlYCBhcyBhIGZ1bmN0aW9uLCBgSEVBTFRIX1NVUlZFWWAgYXMgZGF0YSwgYW5kIGBpbnN1cmUuc3RhdHVzYCBhcyBhIHZhcmlhYmxlIHdpdGhvdXQga25vd2luZyBhbnl0aGluZyBlbHNlOg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KDQpmaW5kX21vZGUoSEVBTFRIX1NVUlZFWSRpbnN1cmUuc3RhdHVzKQ0KDQpgYGANCg0KUGxlYXNlIG5vdGUgdGhhdCBzcGVjaWZpYyBuYW1pbmcgY29udmVudGlvbnMgbWF5IG5vdCB3b3JrIGluIGFsbCBzb2Z0d2FyZS4gUmVzb3VyY2VzIGF0IHRoZSBib3R0b20gb2YgdGhpcyBtb2R1bGUgcHJvdmlkZSBzb2Z0d2FyZS1zcGVjaWZpYyByZWNvbW1lbmRhdGlvbnMgb24gbmFtaW5nIGFuZCBvdGhlciBjb252ZW50aW9ucy4NCg0KIyMjI1JlY29tbWVuZGF0aW9uICM2OiBBZGQgbWV0YS1kYXRhIHRvIGZpbGUgbmFtZXMgDQoNCkluY2x1ZGluZyBtZXRhLWRhdGEgbGlrZSB0aGUgKipkYXRlKiogYW5kICoqcHJvamVjdCBuYW1lKiogaW4gZmlsZSBuYW1lcyBjb25zaXN0ZW50bHkgbWFrZXMgaXQgZWFzaWVyIHRvIHNlYXJjaCBmb3IgZmlsZXMgYW5kIHByb2Nlc3MgZmlsZXMuIFRoZXJlIGFyZSB0aHJlZSBrZXkgcHJpbmNpcGxlcyBmb3IgZmlsZSBuYW1lczoNCg0KIy4gTWFjaGluZSByZWFkYWJsZQ0KIy4gSHVtYW4gcmVhZGFibGUgDQojLiBXb3JrcyB3aXRoIGRlZmF1bHQgb3JkZXJpbmcNCg0KKipNYWNoaW5lIHJlYWRhYmxlKiogZmlsZSBuYW1lcyBhcmUgZm9ybWF0dGVkIGluIGEgd2F5IHRoYXQgY2FuIGJlIHJlYWQgaW50byBhIHByb2dyYW0gYW5kIGludGVycHJldGVkIGJ5IHRoZSBwcm9ncmFtLiBUaGlzIGlzIGVzcGVjaWFsbHkgdXNlZnVsIGlmIGEgcHJvamVjdCBpbmNsdWRlcyBtYW55IGRhdGEgb3IgY29kZSBmaWxlcyB0aGF0IGFyZSB1c2VkIHRvZ2V0aGVyLiBNYWNoaW5lIHJlYWRhYmxlIGZpbGUgbmFtZXMgdHlwaWNhbGx5IGluY2x1ZGUgc2VwYXJhdG9ycywgdXN1YWxseSBhbiB1bmRlcmxpbmUsIHRvIHNlcGFyYXRlIHBhcnRzIG9mIHRoZSBmaWxlIG5hbWUuIEZvciBleGFtcGxlLCBhIENTViBkYXRhIGZpbGUgY29sbGVjdGVkIG9uIEphbnVhcnkgMjMgb2YgMjAxNyBtaWdodCBiZSBzYXZlZCBhcyAqKjAxMjMyMDE3X3Byb2plY3ROYW1lLmNzdioqLiBOb3RlIHRoYXQgdGhpcyBmaWxlIG5hbWUgaW5jbHVkZXMgYSAwIGF0IHRoZSBiZWdpbm5pbmcgcmF0aGVyIHRoYW4gYSAxIGZvciBKYW51YXJ5LiBUaGlzIGlzIGltcG9ydGFudCBkdWUgdG8gKipkZWZhdWx0IG9yZGVyaW5nKiogb2YgbnVtYmVycyBhbmQgbGV0dGVycy4gSWYgSmFudWFyeSB3ZXJlIGNvZGVkIGFzIHNpbXBseSAqKjEqKiwgdGhlIGZpbGUgbmFtZSB3b3VsZCBiZSAxMjMxNyBhbmQgZGVmYXVsdCBvcmRlcmluZyB3b3VsZCBpbnRlcnByZXQgaXQgYXMgY29taW5nIGFmdGVyIGRhdGEgZmlsZXMgZnJvbSBPY3RvYmVyIG9yIE5vdmVtYmVyLCBtb250aHMgMTAgYW5kIDExLiAqKkh1bWFuIHJlYWRhYmxlKiogZmlsZSBuYW1lcyBpbmNsdWRlIGRhdGVzIGFuZCB3b3JkcyBmb3JtYXR0ZWQgaW4gd2F5cyB0aGF0IGFyZSBmYW1pbGlhciB0byBwZW9wbGUsIHNpbWlsYXIgdG8gdGhlIG1lYW5pbmdmdWwgdmFyaWFibGUgbmFtZXMgaW4gdGhlIHNlY3Rpb24gYWJvdmUuDQoNCkNvbnNpZGVyLCBmb3IgZXhhbXBsZSwgcmF3IGFuZCBjbGVhbmVkIGRhdGEgZmlsZXMgY29sbGVjdGVkIGJlZm9yZSBhbmQgYWZ0ZXIgc29tZSBwcm9ncmFtIHdhcyBpbXBsZW1lbnRlZDoNCg0KKiBycHJvZ2JkYXRhLmNzdiANCiogcHJvZ2JkZmluYWwuY3N2IA0KKiBwcm9nZGF0YXIuY3N2IA0KKiBjbGVhbnByb2dyZGF0YS5jc3YgDQoNCllvdSBjYW4gc2VlIHNvbWUgZGlmZmVyZW5jZXMgaW4gdGhlIGRhdGEgbmFtZXMgYW5kIG1pZ2h0IHRyeSB0byBndWVzcyBiYXNlZCBvbiB0aGVzZSBmZWF0dXJlcyBhbmQgbWF5YmUgdGhlIGZpbGUgc2F2ZSBkYXRlLiBIb3dldmVyLCB3cml0aW5nIHRoZSBmaWxlIG5hbWVzIGxpa2UgdGhpcyB3b3VsZCBhbGxvdyBtb3JlIGNlcnRhaW50eToNCg0KKiAwMTMwMThfcmF3X3ByZVByb2dyYW0uY3N2IA0KKiAwMTMxMThfY2xlYW5fcHJlUHJvZ3JhbS5jc3YgDQoqIDAyMjgxOF9yYXdfcG9zdFByb2dyYW0uY3N2IA0KKiAwMzAyMThfY2xlYW5fcG9zdFByb2dyYW0uY3N2IA0KDQpJdCBpcyBjbGVhciBmcm9tIHRoZXNlIGZpbGUgbmFtZXMgd2hpY2ggZmlsZXMgYXJlIHJhdywgd2hpY2ggYXJlIGNsZWFuLCB3aGljaCBhcmUgYmVmb3JlIHRoZSBwcm9ncmFtLCB3aGljaCBhcmUgYWZ0ZXIsIGFuZCB0aGUgZGF0ZSB0aGUgZmlsZSB3YXMgc2F2ZWQuDQogICAgDQojIyNJbnRyb2R1Y2UgYW5kIGV4cGxhaW4gdGhlIGNvZGUgeyNpbnRyb30NCg0KIyMjI1JlY29tbWVuZGF0aW9uICM3OiBXcml0ZSBhIHByb2xvZyB0byBpbnRyb2R1Y2UgdGhlIGNvZGUNCg0KQSAqcHJvbG9nKiBpcyBhIGJsb2NrIG9mIGNvbW1lbnRzIGF0IHRoZSBiZWdpbm5pbmcgb2YgYSBjb2RlIGZpbGUgb2Zmc2V0IHdpdGggc3BlY2lhbCBjaGFyYWN0ZXJzIGFzIGFwcHJvcHJpYXRlIGluIHRoZSBzb2Z0d2FyZSBiZWluZyB1c2VkLiBBICpwcm9sb2cqIGlzIHVzZWQgdG8gKnByb3ZpZGUgc3VmZmljaWVudCBpbmZvcm1hdGlvbiBhYm91dCBjb2RlKiBmb3IgYSBjb2xsYWJvcmF0b3IgKG1heWJlIGZ1dHVyZSB5b3UhKSBvciBzb21lb25lIG91dHNpZGUgeW91ciBwcm9qZWN0IHRvIHVuZGVyc3RhbmQgdGhlICp3aG8qLCAqd2hhdCosIGFuZCAqd2h5KiBvZiB5b3VyIGNvZGUuIA0KDQpGb3IgZXhhbXBsZSwgaGVyZSBpcyBhIHByb2xvZyBmb3JtYXR0ZWQgZm9yIGEgc3RhdGlzdGljYWwgY29kZSBmaWxlIGluIFNBUzoNCg0KYGBge3IgZWNobz1GQUxTRX0NCmh0bWx0b29sczo6aW5jbHVkZUhUTUwoIlNBU0Jsb2NrMC5odG1sIikNCmBgYA0KDQpIZXJlIGlzIGEgcHJvbG9nIGZvcm1hdHRlZCBmb3IgYSBjb2RlIGZpbGUgaW4gUjoNCg0KYGBge3IgZXZhbD1GQUxTRX0NCiMgUFJPTE9HICAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIycNCg0KIyBQUk9KRUNUOiBOQU1FIE9GIFBST0pFQ1QgSEVSRQ0KIyBQVVJQT1NFOiBNQUpPUiBQT0lOVChTKSBPRiBXSEFUIEkgQU0gRE9JTkcgV0lUSCBUSEUgREFUQSBIRVJFDQojIERJUjogICAgIGxpc3QgZGlyZWN0b3J5KC1pZXMpIGZvciBmaWxlcyBoZXJlDQojIERBVEE6ICAgIGxpc3QgZGF0YXNldCBmaWxlIG5hbWVzL2F2YWlsYWJpbGl0eSBoZXJlLCBlLmcuLA0KIyAgICAgICAgICBmaWxlbmFtZS5jb3JyZWN0ZXh0ZW50aW9uIA0KIyAgICAgICAgICBzb21ld2ViYWRkcmVzcy5jb20gDQojIEFVVEhPUjogIEFVVEhPUiBOQU1FKFMpIA0KIyBDUkVBVEVEOiBNT05USCBkZCwgWUVBUiANCiMgTEFURVNUOiAgTU9OVEggZGQsIFlFQVIgDQojIE5PVEVTOiAgIGluZGVudCBhbGwgYWRkaXRpb25hbCBsaW5lcyB1bmRlciBlYWNoIGhlYWRpbmcsIA0KIyAgICAgICAgICAmIHVzZSB0aGUgYXBvc3Ryb3BoZSBoYXNobWFyayBib29rZW5kcyB0aGF0IGFwcGVhciAgDQojICAgICAgICAgIEtFRVAgUFVSUE9TRSwgQVVUSE9SLCBDUkVBVEVEICYgTEFURVNUIEVOVFJJRVMgSU4gVVBQRVIgQ0FTRSwgDQojICAgICAgICAgIHdpdGggYXBwcm9wcmlhdGUgY2FzZSBmb3IgRElSICYgREFUQSwgbG93ZXIgY2FzZSBmb3Igbm90ZXMgDQojICAgICAgICAgIElmIG11bHRpcGxlIGxpbmVzIGJlY29tZSB0b28gbXVjaCwgDQojICAgICAgICAgIHNpbXBsaWZ5IGFuZCB3cml0ZSBjb2RlIGJvb2sgYW5kIHJlYWRtZS4gDQojICAgICAgICAgIEhJTlQgIzE6IERlY2lkZSB3aGF0IGEgbG9uZyBwcm9sb2cgaXMuIA0KIyAgICAgICAgICBISU5UICMyOiBjb3B5ICYgcGFzdGUgdGhpcyBpbnRvIG5ldyBzY3JpcHQgJiByZXBsYWNlIHRleHQuIA0KDQojIFBST0xPRyAgICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KYGBgDQoNCkFkZGl0aW9uYWwgcHJvbG9nIHRlbXBsYXRlcyBmb3IgU0FTLCBTUFNTLCBTdGF0YSwgYW5kIFIgYXJlIGF2YWlsYWJsZSBvbiBHaXRIdWIgYXQgPGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL2NvZGluZzJzaGFyZS9Qcm9sb2ctdGVtcGxhdGVzIiB0YXJnZXQ9Il9ibGFuayI+aHR0cHM6Ly9naXRodWIuY29tL2NvZGluZzJzaGFyZS9Qcm9sb2ctdGVtcGxhdGVzPC9hPg0KDQojIyMjUmVjb21tZW5kYXRpb24gIzg6IEFubm90YXRlIHRvIGNsYXJpZnkgY29kZSBwdXJwb3NlIA0KDQpXaGlsZSBhIHByb2xvZyBjb250YWlucyBnZW5lcmFsIGluZm9ybWF0aW9uIGFib3V0IHRoZSBjb2RlLCBhbm5vdGF0aW9uIGlzIHVzZWQgdGhyb3VnaG91dCB0aGUgY29kZSB0byBkZXNjcmliZSB3aGF0IGlzIGdvaW5nIG9uLiBUaGVyZSBhcmUgZGlmZmVyZW50IHNjaG9vbHMgb2YgdGhvdWdodCBvbiBob3cgbXVjaCBvciBob3cgbGl0dGxlIGFubm90YXRpb24gaXMgbmVlZGVkLiBUaGUgZ2VuZXJhbCBnb2FsIHdvdWxkIGJlIHRvIHdyaXRlIGNsZWFyIGNvZGUgdGhhdCBvbmx5IG5lZWRzIGEgc21hbGwgYW1vdW50IG9mIGFubm90YXRpb24uIA0KDQpgYGB7ciBmaWcuaGVpZ2h0PTIsIGVjaG89RkFMU0V9DQpwZXJEYXRhIDwtIGRhdGEuZnJhbWUoZ3JvdXAgPSBjKCdZZXMnLCdZZXMsIGJ1dCBpbiBncmVlbicpLA0KICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gYyg5MCwxMCkpDQoNCmxpYnJhcnkoZ2dwbG90MikNCmdncGxvdChwZXJEYXRhLCBhZXMoeD0iIiwgeT12YWx1ZSwgZmlsbD1ncm91cCkpICsNCiAgZ2VvbV9iYXIod2lkdGggPSAxLCBzdGF0ID0gImlkZW50aXR5IikgKw0KICBjb29yZF9wb2xhcigieSIsIHN0YXJ0PTApICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiMwMDAwNjYiLCIjMDA5OTAwIiksIG5hbWU9IiIpICsNCiAgZ2d0aXRsZSgiU2hvdWxkIEkgYW5ub3RhdGUgbXkgY29kZT8iKSsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLA0KICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksDQogIHBhbmVsLmdyaWQ9ZWxlbWVudF9ibGFuaygpLA0KICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLA0KICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksDQogIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpDQoNCmBgYA0KDQpXaGVuIGNvbW1lbnRpbmcsIHRoaW5rIGFib3V0IHdoYXQgeW91IHdvdWxkIHdhbnQgdG8gZXhwbGFpbiB0byBhIG5ldyBjb2xsYWJvcmF0b3Igb3IgaG93IHRoZSBjb2RlIHJlYWRzIGZvciBzb21lb25lIGNvbXBsZXRlbHkgb3V0c2lkZSB5b3VyIHByb2plY3QuIFdpdGggdGhvc2UgYXVkaWVuY2VzIGluIG1pbmQsIGFkZCBjb21tZW50cyB0bzoNCg0KKiBleHBsYWluIHRoZSByZWFzb24gZm9yIHRoZSBjb2RlIChpZiBuZWVkZWQpDQoqIGV4cGxhaW4gZnVuY3Rpb25hbGl0eSBvciBjaG9pY2VzIHRoYXQgYXJlIG5vdCBvYnZpb3VzIG9yIGFyZSBkaWZmZXJlbnQgZnJvbSBleHBlY3RlZA0KKiBpZGVudGlmeSBoYWNrcyBvciBlcnJvcnMgdGhhdCBzaG91bGQgYmUgZml4ZWQgb3IgcmV3cml0dGVuOyBjb25zaXN0ZW50bHkgdXNlIGEgd29yZCBvciBwaHJhc2Ugc28gdGhpcyBjb2RlIGlzIGVhc3kgdG8gZmluZCAoZS5nLiwgSEFDSyBvciBCUk9LRU4pDQoNCkF2b2lkIHVzaW5nIGNvbW1lbnRzIHRvOg0KDQoqIGV4cGxhaW4gcG9vcmx5IG5hbWVkIG9iamVjdHM7IGltcHJvdmUgdGhlIG9iamVjdCBuYW1lIGluc3RlYWQgKHNlZSBbUmVjb21tZW5kYXRpb24gIzRdKCNSNCkpDQoqIHJlcGVhdCB0aGluZ3MgdGhhdCBjYW4gYmUgZWFzaWx5IHVuZGVyc3Rvb2QgZnJvbSB0aGUgY29kZQ0KDQpGb3IgZXhhbXBsZSwgaW5zdGVhZCBvZiBhIGNvbmZ1c2luZyBncmFwaCBuYW1lIGFuZCBhIGNvbW1lbnQgc3RhdGluZyB0aGUgb2J2aW91czoNCg0KYGBge3IgZXZhbD1GQUxTRX0NCg0KI2hhIHN0YW5kcyBmb3IgaGlzdG9ncmFtIG9mIGFnZQ0KaGEgPC0gaGlzdChhZ2UpDQpoYQ0KDQpgYGANCg0KTmFtZSB5b3VyIGdyYXBoIHNvbWV0aGluZyBsb2dpY2FsIGFuZCBjb21tZW50IG9uIHdoeSB0aGUgY29kZSBpcyBuZWVkZWQ6DQoNCmBgYHtyIGV2YWw9RkFMU0V9DQoNCiNjaGVjayBub3JtYWxpdHkgYXNzdW1wdGlvbiBmb3IgYWdlIHZhcmlhYmxlDQpoaXN0b0FnZSA8LSBoaXN0KGFnZSkNCmhpc3RvQWdlDQoNCmBgYA0KDQojI0NvbXBsZXRlIGNvZGUgZXhhbXBsZXMNCg0KIyMjUiBleGFtcGxlDQoNClRoaXMgUiBjb2RlIGRvZXMgbm90IGZvbGxvdyB0aGUgcHJvbWlzaW5nIHByYWN0aWNlcyBhYm92ZSBhbmQgaXMgZGlmZmljdWx0IHRvIHJlYWQ6DQoNCmBgYHtyIGV2YWw9RkFMU0V9DQpsaWJyYXJ5KFJOSEFORVMpOyBsaWJyYXJ5KGdncGxvdDIpDQpkYXQgPC0gbmhhbmVzX2xvYWRfZGF0YSgiQVVRX0ciLCAiMjAxMS0yMDEyIiwgZGVtb2dyYXBoaWNzID0gVFJVRSkNCnN1bW1hcnkoZGF0JEFVUTMwMCkNCmRhdCRBVVEzMDBbZGF0JEFVUTMwMCA+IDJdIDwtIE5BDQpkYXQkQVVRMzAwIDwtIGZhY3RvcihkYXQkQVVRMzAwLGxldmVscz1jKDEsMiksbGFiZWxzPWMoIlllcyIsIk5vIikpDQpzdW1tYXJ5KGRhdCRBVVEzMDApDQpnZ3Bsb3Qoc3Vic2V0KGRhdCwgIWlzLm5hKEFVUTMwMCkpLGFlcyh4PUFVUTMwMCwgeT0oLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSxmaWxsPUFVUTMwMCkpICsgZ2VvbV9iYXIoKSArIHRoZW1lX21pbmltYWwoKSArIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Yygib3JhbmdlIiwiZ3JheSIpLCBndWlkZT1GQUxTRSkNCmBgYA0KDQpGaXJzdCwgKnVzZSBzcGFjZSB3aXNlbHkqLiBBZGRpbmcgKndoaXRlIHNwYWNlIHRvIHNlcGFyYXRlIHByb2Nlc3NlcyosICpsaW1pdGluZyBsaW5lIGxlbmd0aCB0byA4MCBjaGFyYWN0ZXJzKiwgYW5kICppbmRlbnRpbmcgdG8gZ3JvdXAgbGluZXMgb2YgY29kZSB0aGF0IGJlbG9uZyB0b2dldGhlciogY2FuIGhlbHAgbWFrZSB0aGUgY29kZSBlYXNpZXIgdG8gZm9sbG93Og0KDQpgYGB7ciAgZXZhbD1GQUxTRX0NCmxpYnJhcnkoUk5IQU5FUykNCmxpYnJhcnkoZ2dwbG90MikNCg0KZGF0IDwtIG5oYW5lc19sb2FkX2RhdGEoIkFVUV9HIiwgIjIwMTEtMjAxMiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgZGVtb2dyYXBoaWNzID0gVFJVRSkNCnN1bW1hcnkoZGF0JEFVUTMwMCkNCg0KZGF0JEFVUTMwMFtkYXQkQVVRMzAwID4gMl0gPC0gTkENCmRhdCRBVVEzMDAgPC0gZmFjdG9yKGRhdCRBVVEzMDAsDQogICAgICAgICAgICAgICAgICAgICBsZXZlbHM9YygxLDIpLCAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIlllcyIsIk5vIikpDQpzdW1tYXJ5KGRhdCRBVVEzMDApDQoNCmdncGxvdChzdWJzZXQoZGF0LCAhaXMubmEoQVVRMzAwKSksDQogICAgICAgYWVzKHg9QVVRMzAwLCANCiAgICAgICAgICAgeT0oLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSwNCiAgICAgICAgICAgZmlsbD1BVVEzMDApKSArIA0KICBnZW9tX2JhcigpICsgDQogIHRoZW1lX21pbmltYWwoKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudCkgKyAgDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCJvcmFuZ2UiLCJncmF5IiksIA0KICAgICAgICAgICAgICAgICAgICBndWlkZT1GQUxTRSkNCmBgYA0KDQpTZWNvbmQsICpjaG9vc2UgbWVhbmluZ2Z1bCBuYW1lcyogZm9yIG9iamVjdHMuIFNpbmNlIHRoZSBjb2RlIGV4YW1pbmVzIHRoZSBOYXRpb25hbCBIZWFsdGggYW5kIE51dHJpdGlvbiAoTkhBTkVTKSBzdXJ2ZXkgZGF0YSwgbmFtaW5nIHRoZSBkYXRhIG9iamVjdCAqbmhhbmVzKiBtYWtlcyBzZW5zZS4gTGlrZXdpc2UsIHRoZSB2YXJpYWJsZSBBVVEzMDAgbWVhc3VyZXMgd2hldGhlciB0aGUgcGFydGljaXBhbnQgaGFzIGV2ZXIgdXNlZCBhIGd1biwgc28gdHJ5IG5hbWluZyBpdCAqZ3VuLnVzZXIqOg0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KbGlicmFyeShSTkhBTkVTKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQpuaGFuZXMgPC0gbmhhbmVzX2xvYWRfZGF0YSgiQVVRX0ciLCAiMjAxMS0yMDEyIiwgDQogICAgICAgICAgICAgICAgICAgICAgICBkZW1vZ3JhcGhpY3MgPSBUUlVFKQ0Kc3VtbWFyeShuaGFuZXMkQVVRMzAwKQ0KDQpuaGFuZXMkQVVRMzAwW25oYW5lcyRBVVEzMDAgPiAyXSA8LSBOQQ0KbmhhbmVzJGd1bi51c2VyIDwtIGZhY3RvcihuaGFuZXMkQVVRMzAwLA0KICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzPWMoMSwyKSwgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJZZXMiLCJObyIpKQ0Kc3VtbWFyeShuaGFuZXMkZ3VuLnVzZXIpDQoNCmdncGxvdChzdWJzZXQobmhhbmVzLCAhaXMubmEoZ3VuLnVzZXIpKSwNCiAgICAgICBhZXMoeD1ndW4udXNlciwgDQogICAgICAgICAgIHk9KC4uY291bnQuLikvc3VtKC4uY291bnQuLiksDQogICAgICAgICAgIGZpbGw9Z3VuLnVzZXIpKSArIA0KICBnZW9tX2JhcigpICsgDQogIHRoZW1lX21pbmltYWwoKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudCkgKyAgDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCJvcmFuZ2UiLCJncmF5IiksIA0KICAgICAgICAgICAgICAgICAgICBndWlkZT1GQUxTRSkNCmBgYA0KDQpGaW5hbGx5LCAqaW50cm9kdWNlIGFuZCBleHBsYWluIHRoZSBjb2RlKiBieSBhZGRpbmcgYSBwcm9sb2cgYW5kIGFubm90YXRpb24uIENvbXBhcmUgdGhpcyBmaW5hbCB2ZXJzaW9uIG9mIHRoZSBjb2RlIHdpdGggdGhlIGZpcnN0IHZlcnNpb24gYWJvdmU6DQoNCmBgYHtyIGV2YWw9RkFMU0V9DQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFBST0pFQ1Q6IEd1biB1c2UgcG9saWN5IGJyaWVmIA0KIyBQVVJQT1NFOiBCYXIgZ3JhcGggb2YgcGVyY2VudGFnZSBvZiBndW4gdXNlIGZvciBwb2xpY3kgYnJpZWYgDQojIERJUjogICAgIEM6L1VzZXJzL2plbmluZS9EZXNrdG9wL2RhdGFjYW1wDQojIERBVEE6ICAgIE5IQU5FUyAyMDExLTIwMTIgZGF0YSBhdmFpbGFibGUgdmlhIFJOSEFORVMgcGFja2FnZQ0KIyBBVVRIT1I6ICBKZW5pbmUgSGFycmlzIA0KIyBDUkVBVEVEOiAxMS8yOC8xNyANCiMgTEFURVNUOiAgMTEvMjgvMTcgDQojIE5PVEVTOiAgIEZvciBjb2Rpbmcyc2hhcmUgZm9ybWF0dGluZyBjb2RlIG1vZHVsZQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQojb3BlbiBOSEFORVMgcGFja2FnZSB0byBicmluZyBpbiBkYXRhDQojb3BlbiBnZ3Bsb3QyIGZvciBncmFwaGluZw0KbGlicmFyeShSTkhBTkVTKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojYnJpbmcgaW4gTkhBTkVTIDIwMTEtMTIgYXVkaW9sb2d5IGRhdGENCiNBVVEzMDAgcXVlc3Rpb24gYXNrcyBldmVyIHVzZWQgZ3VuDQojd2hlcmUgMSA9IFllcywgMiA9IE5vLCA3ID0gUmVmdXNlZCwgOSA9IERvbid0IGtub3cNCm5oYW5lcyA8LSBuaGFuZXNfbG9hZF9kYXRhKCJBVVFfRyIsICIyMDExLTIwMTIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbW9ncmFwaGljcyA9IFRSVUUpDQpzdW1tYXJ5KG5oYW5lcyRBVVEzMDApDQoNCiNkZWxldGUgUmVmdXNlZCBhbmQgRG9uJ3Qga25vdyByZXNwb25zZXMNCiNyZW5hbWUgdmFyaWFibGUgdG8gZ3VuVXNlciwgYWRkIGxhYmVscyB0byBsZXZlbHMNCm5oYW5lcyRBVVEzMDBbbmhhbmVzJEFVUTMwMCA+IDJdIDwtIE5BDQpuaGFuZXMkZ3VuLnVzZXIgPC0gZmFjdG9yKG5oYW5lcyRBVVEzMDAsDQogICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9YygxLDIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIlllcyIsIk5vIikpDQpzdW1tYXJ5KG5oYW5lcyRndW4udXNlcikNCg0KI3Bsb3QgYmFyIGdyYXBoIG9mIHBlcmNlbnQgb2YgMjAxMS0yMDEyIE5IQU5FUyANCiNwYXJ0aWNpcGFudHMgd2hvIGV2ZXIgdXNlZCBndW4NCmdncGxvdChzdWJzZXQobmhhbmVzLCANCiAgICAgICAgICAgICAgIWlzLm5hKGd1bi51c2VyKSksDQogICAgICAgYWVzKHg9Z3VuLnVzZXIsIA0KICAgICAgICAgICB5PSguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pLA0KICAgICAgICAgICBmaWxsPWd1bi51c2VyKSkgKyANCiAgZ2VvbV9iYXIoKSArIA0KICB0aGVtZV9taW5pbWFsKCkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnQpICsgIA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Yygib3JhbmdlIiwiZ3JheSIpLCANCiAgICAgICAgICAgICAgICAgICAgZ3VpZGU9RkFMU0UpDQpgYGANCg0KIyMjU1BTUyBleGFtcGxlDQoNClRoaXMgU1BTUyBjb2RlIGZpbGUgZXhhbXBsZSBkb2VzIG5vdCBmb2xsb3cgdGhlIHByb21pc2luZyBwcmFjdGljZXMgYWJvdmUgYW5kIGl0IGlzIGRpZmZpY3VsdCB0byBkZWNpcGhlciB3aGVyZSBvbmUgbGluZSBvZiBjb2RlIHN0b3BzIGFuZCB0aGUgbmV4dCBiZWdpbnMuDQoNCmBgYHtyIGVjaG89RkFMU0V9DQojIEtuaXRzIGNzcyBpbnRvIG92ZXJhbGwgbmIuaHRtbCBzbyBpdCdzIHBvcnRhYmxlDQpodG1sdG9vbHM6OmluY2x1ZGVDU1MoIkc6XFxDUEhTU1xcT3BlblNjaWVuY2VcXE1vZHVsZXNcXFN0eWxlc2hlZXRzXFxTUFNTc3R5bGUuY3NzIikgDQpodG1sdG9vbHM6OmluY2x1ZGVIVE1MKCJTUFNTQmxvY2sxLmh0bWwiKQ0KYGBgDQoNCkZpcnN0LCAqdXNlIHNwYWNlIHdpc2VseSouIEFkZGluZyAqd2hpdGUgc3BhY2UgdG8gc2VwYXJhdGUgcHJvY2Vzc2VzKiwgKmxpbWl0aW5nIGxpbmUgbGVuZ3RoIHRvIDgwIGNoYXJhY3RlcnMqLCBhbmQgKmluZGVudGluZyB0byBncm91cCBsaW5lcyBvZiBjb2RlIHRoYXQgYmVsb25nIHRvZ2V0aGVyKiBjYW4gaGVscCBtYWtlIHRoZSBjb2RlIGVhc2llciB0byBmb2xsb3cuICANCg0KYGBge3IgZWNobz1GQUxTRX0NCmh0bWx0b29sczo6aW5jbHVkZUhUTUwoIlNQU1NCbG9jazIuaHRtbCIpDQpgYGANCg0KU2Vjb25kLCAqY2hvb3NlIG1lYW5pbmdmdWwgbmFtZXMqIGZvciB0aGUgZGF0YSBzZXQgYW5kIHZhcmlhYmxlIGxhYmVscy4gU2luY2UgdGhlIGNvZGUgZXhhbWluZXMgdGhlIE5hdGlvbmFsIEhlYWx0aCBhbmQgTnV0cml0aW9uIChOSEFORVMpIHN1cnZleSBkYXRhLCBuYW1pbmcgdGhlIGRhdGEgc2V0ICpuaGFuZXMqIG1ha2VzIHNlbnNlLiBOYW1pbmcgdGhlIGRhdGEgc2V0IGFsbG93cyBzZXZlcmFsIGRhdGEgc2V0cyB0byBiZSBvcGVuIGF0IHRoZSBzYW1lIHRpbWUuIEV4cGxpY2l0bHkgKmFjdGl2YXRlKiB0aGUgZGF0YSBzZXQgYmVmb3JlIGNvbnRpbnVpbmcgc28gaXQncyBjbGVhciB3aGljaCBvbmUgaXMgYmVpbmcgbW9kaWZpZWQgb3IgdXNlZC4gTGlrZXdpc2UsIHZhcmlhYmxlIGxhYmVscyBlbmFibGUgYWNjZXNzIHRvIG1vcmUgZGV0YWlsIGFib3V0IHdoYXQgdGhlIHZhcmlhYmxlIGFjdHVhbGx5IGlzLCBzbyB3ZSBjYW4gaW5jbHVkZSBlbm91Z2ggb2YgdGhlIHF1ZXN0aW9ubmFpcmUgbGFuZ3VhZ2UgZm9yIGl0IHRvIG1ha2Ugc2Vuc2U6ICJFdmVyIHVzZWQgZmlyZWFybXMgZm9yIGFueSByZWFzb24/Ig0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KaHRtbHRvb2xzOjppbmNsdWRlSFRNTCgiU1BTU0Jsb2NrMy5odG1sIikNCmBgYA0KDQpGaW5hbGx5LCAqaW50cm9kdWNlIGFuZCBleHBsYWluIHRoZSBjb2RlKiBieSBhZGRpbmcgYSBwcm9sb2cgYW5kIGFubm90YXRpb24uIEJlIHN1cmUgdG8gaW5jbHVkZSBhIHBlcmlvZCBhdCB0aGUgZW5kIG9mIGVhY2ggY29tbWVudCBzbyB0aGF0IHRoZSBmb2xsb3dpbmcgY29kZSBjb21tYW5kIHdpbGwgbm90IGdldCAiY29tbWVudGVkIG91dCIgYnkgYWNjaWRlbnQuIENvbXBhcmUgdGhpcyBmaW5hbCB2ZXJzaW9uIG9mIHRoZSBjb2RlIHdpdGggdGhlIGZpcnN0IHZlcnNpb24gYWJvdmU6DQoNCmBgYHtyIGVjaG89RkFMU0V9DQpodG1sdG9vbHM6OmluY2x1ZGVIVE1MKCJTUFNTQmxvY2s0Lmh0bWwiKQ0KYGBgDQoNCiMjI1N0YXRhIGV4YW1wbGUNCg0KVGhpcyBTdGF0YSBjb2RlIGZpbGUgZXhhbXBsZSBkb2VzIG5vdCBmb2xsb3cgdGhlIHByb21pc2luZyBwcmFjdGljZXMgYWJvdmUgYW5kIGl0IGlzIGRpZmZpY3VsdCB0byBkZWNpcGhlciB3aGVyZSBvbmUgbGluZSBvZiBjb2RlIHN0b3BzIGFuZCB0aGUgbmV4dCBiZWdpbnMuDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpodG1sdG9vbHM6OmluY2x1ZGVDU1MoIkc6XFxDUEhTU1xcT3BlblNjaWVuY2VcXE1vZHVsZXNcXFN0eWxlc2hlZXRzXFxTVEFUQXN0eWxlLmNzcyIpDQpodG1sdG9vbHM6OmluY2x1ZGVIVE1MKCJTVEFUQUJsb2NrMS5odG1sIikNCmBgYA0KDQpGaXJzdCwgKnVzZSBzcGFjZSB3aXNlbHkqLiBBZGRpbmcgKndoaXRlIHNwYWNlIHRvIHNlcGFyYXRlIHByb2Nlc3NlcyosICpsaW1pdGluZyBsaW5lIGxlbmd0aCB0byA4MCBjaGFyYWN0ZXJzKiwgYW5kICppbmRlbnRpbmcgdG8gZ3JvdXAgbGluZXMgb2YgY29kZSB0aGF0IGJlbG9uZyB0b2dldGhlciogY2FuIGhlbHAgbWFrZSB0aGUgY29kZSBlYXNpZXIgdG8gZm9sbG93LiBOb3RpY2UgdGhhdCBTdGF0YSdzIGRvLWZpbGUgZWRpdG9yIGNvbWVzIHdpdGggYSBmYWludCBsaW5lIGF0IDgwIGNoYXJhY3RlcnMgaW5kaWNhdGluZyB0aGF0IHlvdSBzaG91bGQga2VlcCBsaW5lcyBvZiBjb2RlIHRvIHRoaXMgbGVuZ3RoLiBTZWNvbmQsIG5vdGljZSB0aGF0IG91ciByZWNvbW1lbmRhdGlvbiB0byAqY2hvb3NlIG1lYW5pbmdmdWwgbmFtZXMqIGZvciBvYmplY3RzIChpbiB0aGlzIGNhc2UsIHZhcmlhYmxlcykgaXMgbWV0IGJ5IHRoZSBzdG9jayBkYXRhIHNldCBpbiBTdGF0YS4gVGhlICpkZXNjcmliZSogZnVuY3Rpb24gc2hvd3MgdXMgdGhhdCAibGUiIHN0YW5kcyBmb3IgImxpZmUgZXhwZWN0YW5jeSIgYW5kIHRoYXQgImIiICYgInciIHN0YW5kIGZvciAiYmxhY2svQWZyaWNhbiBBbWVyaWNhbiIgYW5kICJ3aGl0ZSIuIFdpdGggYSBzbWFsbCBkYXRhIHNldCBsaWtlIHRoaXMsIHRoZXNlIHNob3J0IHZhcmlhYmxlIG5hbWVzIGFyZSBpbmZvcm1hdGl2ZSAqYW5kKiBxdWljayB0byB0eXBlLiANCg0KYGBge3IgZWNobz1GQUxTRX0NCmh0bWx0b29sczo6aW5jbHVkZUhUTUwoIlNUQVRBQmxvY2syLmh0bWwiKQ0KYGBgDQoNCkZpbmFsbHksICppbnRyb2R1Y2UgYW5kIGV4cGxhaW4gdGhlIGNvZGUqIGJ5IGFkZGluZyBhIHByb2xvZyBhbmQgYW5ub3RhdGlvbi4gQ29tcGFyZSB0aGlzIGZpbmFsIHZlcnNpb24gb2YgdGhlIGNvZGUgd2l0aCB0aGUgZmlyc3QgdmVyc2lvbiBhYm92ZToNCg0KYGBge3IgZWNobz1GQUxTRX0NCmh0bWx0b29sczo6aW5jbHVkZUhUTUwoIlNUQVRBQmxvY2szLmh0bWwiKQ0KYGBgDQoNCiMjI1NBUyBleGFtcGxlDQoNClRoaXMgU0FTIGNvZGUgZmlsZSBleGFtcGxlIGRvZXMgbm90IGZvbGxvdyB0aGUgcHJvbWlzaW5nIHByYWN0aWNlcyBhYm92ZSBhbmQgaXQgaXMgZGlmZmljdWx0IHRvIGRlY2lwaGVyIHdoZXJlIG9uZSBsaW5lIG9mIGNvZGUgc3RvcHMgYW5kIHRoZSBuZXh0IGJlZ2lucy4NCg0KYGBge3IgZWNobz1GQUxTRX0NCmh0bWx0b29sczo6aW5jbHVkZUNTUygiRzpcXENQSFNTXFxPcGVuU2NpZW5jZVxcTW9kdWxlc1xcU3R5bGVzaGVldHNcXFNBU3N0eWxlLkNTUyIpDQpodG1sdG9vbHM6OmluY2x1ZGVIVE1MKCJTQVNCbG9jazEuaHRtbCIpDQpgYGANCg0KRmlyc3QsICp1c2Ugc3BhY2Ugd2lzZWx5Ki4gKkxpbWl0IGxpbmUgbGVuZ3RoIHRvIDgwIGNoYXJhY3RlcnMqLCAgKmluZGVudCBncm91cCBsaW5lcyBvZiBjb2RlIHRoYXQgYmVsb25nIHRvZ2V0aGVyKiwgKnVzZSBhbGwgQ0FQUyBmb3IgREFUQSBhbmQgUFJPQyBmdW5jdGlvbnMqIGFuZCAqZW5kIGFsbCBEQVRBIGFuZCBQUk9DIHN0ZXBzIHdpdGggUlVOIHN0YXRlbWVudCouIE5vdGljZSB0aGF0IFNBUyBhdXRvbWF0aWNhbGx5IGNvbWVzIHVwIHdpdGggYSBmYWludCBsaW5lIHNpZ25hbGluZyB0aGF0IHRoZSBsaW5lcyBhYm92ZSBnbyB0b2dldGhlci4gVGhpcyBzdGVwIGZhY2lsaXRhdGVzIHNjYW5uaW5nIGEgcGFnZSBmb3Igc3RlcCBib3VuZGFyaWVzIGFuZCBjYW4gaGVscCBtYWtlIHRoZSBjb2RlIGVhc2llciB0byBmb2xsb3cuICANCg0KYGBge3IgZWNobz1GQUxTRX0NCmh0bWx0b29sczo6aW5jbHVkZUhUTUwoIlNBU0Jsb2NrMi5odG1sIikNCmBgYA0KDQpTZWNvbmQsICpjaG9vc2UgbWVhbmluZ2Z1bCBuYW1lcyogZm9yIG9iamVjdHMuIFNpbmNlIHRoZSBjb2RlIGV4YW1pbmVzIHRoZSBkYXRhIGFib3V0IHlvdXRoIGhlYWx0aCwgbmFtaW5nIHRoZSBkYXRhIG9iamVjdCAqWW91dGhfSGVhbHRoKiBtYWtlcyBzZW5zZS4gTGlrZXdpc2UsIHRoZSB2YXJpYWJsZSBINFdQMjUgYW5kIEg0V1AzOSBtZWFzdXJlcyB0aGUgY2FzaCBtb20gYW5kIGRhZCBnYXZlIHRvIHRoZSB5b3V0aHMsIHNvIHRyeSBuYW1pbmcgdGhlbSBhcyAqTW9tX0Nhc2gqIGFuZCAqRGFkX0Nhc2gqLCBhbmQgbmFtaW5nIHRoZSBuZXcgY29tYmluZWQgdmFyaWFibGUgYXMgKlBhcmVudF9DYXNoKi4NCg0KYGBge3IgZWNobz1GQUxTRX0NCmh0bWx0b29sczo6aW5jbHVkZUhUTUwoIlNBU0Jsb2NrMy5odG1sIikNCmBgYA0KRmluYWxseSwgKmludHJvZHVjZSBhbmQgZXhwbGFpbiB0aGUgY29kZSogYnkgYWRkaW5nIGEgcHJvbG9nIGFuZCBhbm5vdGF0aW9uLiBDb21wYXJlIHRoaXMgZmluYWwgdmVyc2lvbiBvZiB0aGUgY29kZSB3aXRoIHRoZSBmaXJzdCB2ZXJzaW9uIGFib3ZlOg0KYGBge3IgZWNobz1GQUxTRX0NCmh0bWx0b29sczo6aW5jbHVkZUhUTUwoIlNBU0Jsb2NrNC5odG1sIikNCmBgYA0KDQojI1Jlc291cmNlcw0KDQotIFtUaGUgQXJ0IG9mIFJlYWRhYmxlIENvZGUgYnkgQm9zd2VsbCAmIEZvdWNoZXJdKGh0dHA6Ly9zaG9wLm9yZWlsbHkuY29tL3Byb2R1Y3QvOTc4MDU5NjgwMjMwMS5kbykNCi0gW1I6IEdvb2dsZSdzIFIgU3R5bGUgR3VpZGVdKGh0dHBzOi8vZ29vZ2xlLmdpdGh1Yi5pby9zdHlsZWd1aWRlL1JndWlkZS54bWwpDQotIFtSOiBCaW9jb25kdWN0b3IncyBDb2RpbmcgU3RhbmRhcmRzXShodHRwOi8vYmlvY29uZHVjdG9yLm9yZy9kZXZlbG9wZXJzL2hvdy10by9jb2Rpbmctc3R5bGUvKQ0KLSBbUjogSGFkbGV5IFdpY2toYW0ncyBTdHlsZSBHdWlkZV0oaHR0cDovL2Fkdi1yLmhhZC5jby5uei9TdHlsZS5odG1sKQ0KLSBbUjogSGVucmlrIEJlbmd0c3NvbidzIFIgQ29kaW5nIENvbnZlbnRpb25zXShodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9kb2N1bWVudC9kLzFlc0RWeHlXdkg4QXNYLVZKYS04b3FXYUhMczRzdEdsSWJrOGtMYzVWbElJL2VkaXQpDQotIFtSOiBDb2xpbiBHaWxsZXNwaWUncyBSIFN0eWxlIEd1aWRlXShodHRwczovL2NzZ2lsbGVzcGllLndvcmRwcmVzcy5jb20vMjAxMC8xMS8yMy9yLXN0eWxlLWd1aWRlLykNCi0gW1NBUzogU0FTIFN0eWxlIEd1aWRlXShodHRwOi8vd3d3Mi5zYXMuY29tL3Byb2NlZWRpbmdzL3N1Z2kyOS8yNTgtMjkucGRmKQ0KLSBbU0FTOiBHdWlkZWxpbmVzIGZvciBDb2Rpbmcgb2YgU0FTIFByb2dyYW1zXShodHRwOi8vd3d3Mi5zYXMuY29tL3Byb2NlZWRpbmdzL3N1Z2kyOS8yNTgtMjkucGRmKQ0KLSBbU3RhdGE6IFN1Z2dlc3Rpb25zIG9uIFN0YXRhIFByb2dyYW1taW5nIFN0eWxlXShodHRwOi8vd3d3LnN0YXRhLWpvdXJuYWwuY29tL3NqcGRmLmh0bWw/YXJ0aWNsZW51bT1wcjAwMTgpIA0KLSBbUHl0aG9uOiBHb29nbGUgUHl0aG9uIFN0eWxlIEd1aWRlXShodHRwczovL2dvb2dsZS5naXRodWIuaW8vc3R5bGVndWlkZS9weWd1aWRlLmh0bWwpDQotIFtQeXRob246IEdOVSBNYWlsbWFuIFN0eWxlIEd1aWRlXShodHRwczovL3B5dGhvbmhvc3RlZC5vcmcvbWFpbG1hbi9zcmMvbWFpbG1hbi9kb2NzL1NUWUxFR1VJREUuaHRtbCkNCi0gW1B5dGhvbjogU3R5bGUgR3VpZGUgZm9yIFB5dGhvbiBDb2RlOiBQRVAgOF0oaHR0cHM6Ly93d3cucHl0aG9uLm9yZy9kZXYvcGVwcy9wZXAtMDAwOC8pDQotIFtFeGNlbC9BY2Nlc3M6IFZpc3VhbCBCYXNpYyBDb2RpbmcgQ29udmVudGlvbnNdKGh0dHBzOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvYWEyNDA4MjIodj12cy42MCkuYXNweCkNCi0gW01BVExBQjogTUFUTEFCIFN0eWxlIEd1aWRlbGluZXNdKGh0dHBzOi8vd3d3Lm1hdGh3b3Jrcy5jb20vbWF0bGFiY2VudHJhbC9maWxlZXhjaGFuZ2UvNDYwNTYtbWF0bGFiLXN0eWxlLWd1aWRlbGluZXMtMi0wKQ==


Reproducibility Toolkit on GitHub

Top