Introduction
The data for this test comes from Innovations for Poverty Actions Stata test, which I took in December. In the challenge, I began with some unclean data from a fictional randomized trial in which subjects were given dietary supplements and asked to complete mental math problems. The project demonstrates my data cleaning skills and my ability to explain the results of statistical tests to general audiences.
Problem Statement
A company marketing dietary supplement has carried out an experiment on the relationship between supplement consumption and formal reasoning speed. Study participants took one of four supplements (or none) and executed a series of mental math problems. The company would like to know if their data shows that the supplements make people smarter. Unfortunately, their data is not neatly organized. For example, the time is mm.ss format.
Packages and data loading
In this demonstration, I will use the Tidyverse library. To learn more about the packages, I recommend Wickham and Grolemund 2016, “R for Data Science”.
library(tidyverse)
library(ggthemes)
library(kableExtra)
library(ggplot2)
setwd("C:\\Users\\liptr\\Documents\\R\\vitamins")
vit <- read_csv("vitamins\\vitamins.csv")
Data cleaning
First, let us take a look at this data. We can use the kable package to make easy to read tables.
kable(head(vit)) %>% kable_styling(bootstrap_options = c("striped", "hover", "responsive")) %>% scroll_box(width = "100%", height = "250px")
| treat |
time |
supplement |
| 1 |
2.35 |
B |
| 1 |
4.13 |
B |
| 0 |
5.26 |
NA |
| 1 |
3.45 |
B |
| 1 |
3.29 |
A |
| 1 |
5.36 |
C |
Already, I can see three glaring problems in the data. * One is that the time isn in mm.ss, rather than number of seconds. Our t-test tools will need time in number of seconds. * There are several misnamed treatments (with names like b, n, r, 1 and 2). * It is reduntant to have one variable labeled treatment and one variable for the type of treatment. I will later collapse them into one file with control, A, B, C and D as the variables.
The Time Variable
First I calculate the new time variable as an integer number of se.
vit <- mutate(vit,
min = time%/%1,
sec = (time - min)*100 + 60*min,
position = rownames(vit))
#print(filter(vit, position=))
It’s important to check that this formula is working correctly. The easiest way to do so is to make a quick histogram of the times.
p <- ggplot(vit, mapping = aes(sec))
p + geom_histogram(color="black", fill="lightblue") + theme_pander()

Since there are no suspicious gaps or shapes in this histogram, it looks like my equation is working just fine.
Cleaning the Treatment Categories
Now let us look at our labeling of the subjects. Firstly, there is a redundancy between the treatment column, which shows a binary for whether the subject is in the control group, and the supplement column. I simplify this by simply changing the sup category to “Control” for all subjects in the control group. I also rename that variable sup, to shorten the code later.
Then I count all of the different values in the sup variable.
vit <- rename(vit, sup = supplement)
vit <- mutate(vit, sup = replace(sup, treat ==0, "CONTROL"))
count(vit, sup)
From this count we can see there are many poorly labeled treatments. Most treaments are labeled with a single capital letter, but some are lower case, some are numbers, and some are even other random letters (n and r). To solve this, I remove all spaces and uppercase all the letters, then remove any unclear values. Then I rename them Control, and Treatment_X, to make the final outputs easier to read.
vit <- mutate(vit,
sup = str_to_upper(sup),
sup = str_trim(sup)
)
vit <- filter(vit, sup == "A" | sup == "B" | sup == "C" | sup == "D" | sup == "CONTROL")
vit <- mutate(vit,
sup = replace(sup, treat ==0, "Control"),
sup = replace(sup, sup == "A", "Treatment_A"),
sup = replace(sup, sup == "B", "Treatment_B"),
sup = replace(sup, sup == "C", "Treatment_C"),
sup = replace(sup, sup == "D", "Treatment_D")
)
Checking for Duplicates
It is best practice to attach a unique observation id for each entry in a survey, often a housheold ID or respondent ID. Unfortunately, this experimenter did not create an id for every observation (respondent in this case). This makes it impossible to be sure I have found all duplicate observations, since two subjects could have received the same treatment and used the same number of seconds by chance. However, I can check for consecutive duplicates with the following code that finds consecutive duplicates then prints those observations.
vit<- mutate(vit,
dup = FALSE,
dup = replace(dup, sup==lead(sup) & sec==lead(sec), TRUE))
print(filter(vit, dup == TRUE | lag(dup==TRUE)))
Good, only one value is a duplicate. But is this value a duplicate? Let’s check the original values.
vit2 <- read_csv("vitamins\\vitamins.csv")
Parsed with column specification:
cols(
treat = [32mcol_double()[39m,
time = [32mcol_double()[39m,
supplement = [31mcol_character()[39m
)
print(filter(vit2, rownames(vit2) == 337 | rownames(vit2) == 338))
These two observations are suspicious, as it woudl be easy for an enumerator to accidentally enter the same value twice. But since these enumerators are fictional, I cannot call them up and ask about the observations. Therefore, I will keep it in the data.
After cleaning, out cleaned data looks like this.
kable(head(vit)) %>% kable_styling(bootstrap_options = c("striped", "hover", "responsive")) %>% scroll_box(width = "100%", height = "250px")
| treat |
time |
sup |
min |
sec |
position |
dup |
| 1 |
2.35 |
Treatment_B |
2 |
155 |
1 |
FALSE |
| 1 |
4.13 |
Treatment_B |
4 |
253 |
2 |
FALSE |
| 0 |
5.26 |
Control |
5 |
326 |
3 |
FALSE |
| 1 |
3.45 |
Treatment_B |
3 |
225 |
4 |
FALSE |
| 1 |
3.29 |
Treatment_A |
3 |
209 |
5 |
FALSE |
| 1 |
5.36 |
Treatment_C |
5 |
336 |
6 |
FALSE |
Data Analysis
Visualizing the Results
Now that the data is clean, I can begin analysis. But, before begining any formal tests of significance, it is valuable to visualize our results. This will help us to check that everything is running smoothly and to contextualize any findings. Because this data set is quite narrow, a simple boxplot provides the most important information.
g <- ggplot(vit, mapping = aes(sup, sec))
g + geom_boxplot() +
labs(title="Time to complete problem set by supplement provided", x="Time taken to coplete mental math problems", y= "Supplement category") +
theme_pander() + scale_fill_pander()

Just from reading the boxplot, I can make a few preliminary conclusions.
Subjects who took supplements A, B, and D all performed the test faster than subjects who took the control. In the next section, I will determine if this result is significant.
Subjects who took supplement C actually performed the mental math more slowly. I know that our test will not present evidence that it is effective.
The variance in the control group seems to higher than the treatment groups. Several participants in the control group completed the trial in less than 50 seconds. This may suggest problems in the experimental design, and would normally be reason to contact the enumerators.
Testing for Signficance
To test the effectiveness of the supplements, I use an independent two-sample t-test. By convention, I set my signficance threshold a to \(\alpha\) = .05. Each t-test compares a supplement, independent of the others, to our control group.
attach(vit)
t.test(sec[sup=="Control"], sec[sup=="Treatment_A"], alternative = "less", data = vit)
Welch Two Sample t-test
data: sec[sup == "Control"] and sec[sup == "Treatment_A"]
t = 2.4718, df = 74.33, p-value = 0.9921
alternative hypothesis: true difference in means is less than 0
95 percent confidence interval:
-Inf 29.55953
sample estimates:
mean of x mean of y
240.7346 223.0750
t.test(sec[sup=="Control"], sec[sup=="Treatment_B"], alternative = "less", data = vit)
Welch Two Sample t-test
data: sec[sup == "Control"] and sec[sup == "Treatment_B"]
t = 1.874, df = 204.54, p-value = 0.9688
alternative hypothesis: true difference in means is less than 0
95 percent confidence interval:
-Inf 20.84217
sample estimates:
mean of x mean of y
240.7346 229.6585
t.test(sec[sup=="Control"], sec[sup=="Treatment_C"], alternative = "less", data = vit)
Welch Two Sample t-test
data: sec[sup == "Control"] and sec[sup == "Treatment_C"]
t = -0.0019088, df = 167.2, p-value =
0.4992
alternative hypothesis: true difference in means is less than 0
95 percent confidence interval:
-Inf 10.43069
sample estimates:
mean of x mean of y
240.7346 240.7467
t.test(sec[sup=="Control"], sec[sup=="Treatment_D"], alternative = "less", data = vit)
Welch Two Sample t-test
data: sec[sup == "Control"] and sec[sup == "Treatment_D"]
t = 0.50729, df = 52.518, p-value = 0.693
alternative hypothesis: true difference in means is less than 0
95 percent confidence interval:
-Inf 18.64161
sample estimates:
mean of x mean of y
240.7346 236.4000
For each t-test there is a hypothesis and a null hypothesis. The hypothesis is that the supplements improved mental math speed (reduced the number of seconds) and the null hypothesis is that there was no effect. The quickest number to look at here is the p-value, which is that chance of these results occuring if the null value is true.
Supplements A and B both have p-values above .95. This means these results would be unlikely (occuring in only one int twenty trials), if the supplement was not improving math ability. It does not prove the supplements are effective, but it suggests that they are. That these results are also dependent n the fairness fo the trial and soundness of the design.
For C and D, I cannot eliminate the null hypothesis that the supplements have no effect. It is unlikely, but not impossible, that this result was an aberration of our study and future, more detailed work would find a different result.
LS0tDQp0aXRsZTogIkRhdGEgQW5hbHlzaXMgZm9yIGEgRmljdGlvbmFsIFRyaWFsIG9mIERpZXRhcnkgU3VwcGxlbWVudHMiDQphdXRob3I6ICJUaW0gTGlwdHJvdCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICB0b2M6IHllcw0KICBwZGZfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICB0b2M6IHllcw0KLS0tDQoNCmBgYHtyLCBjb2xsYXBzZT1UUlVFLCBldmFsPVRSVUUsIGluY2x1ZGU9RkFMU0UsIGVjaG89RkFMU0UsIHJlc3VsdHMgPSAnaGlkZSd9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KI0ludHJvZHVjdGlvbg0KDQpUaGUgZGF0YSBmb3IgdGhpcyB0ZXN0IGNvbWVzIGZyb20gSW5ub3ZhdGlvbnMgZm9yIFBvdmVydHkgQWN0aW9ucyBTdGF0YSB0ZXN0LCB3aGljaCBJIHRvb2sgaW4gRGVjZW1iZXIuIEluIHRoZSBjaGFsbGVuZ2UsIEkgYmVnYW4gd2l0aCBzb21lIHVuY2xlYW4gZGF0YSBmcm9tIGEgZmljdGlvbmFsIHJhbmRvbWl6ZWQgdHJpYWwgaW4gd2hpY2ggc3ViamVjdHMgd2VyZSBnaXZlbiBkaWV0YXJ5IHN1cHBsZW1lbnRzIGFuZCBhc2tlZCB0byBjb21wbGV0ZSBtZW50YWwgbWF0aCBwcm9ibGVtcy4gVGhlIHByb2plY3QgZGVtb25zdHJhdGVzIG15IGRhdGEgY2xlYW5pbmcgc2tpbGxzIGFuZCBteSBhYmlsaXR5IHRvIGV4cGxhaW4gdGhlIHJlc3VsdHMgb2Ygc3RhdGlzdGljYWwgdGVzdHMgdG8gZ2VuZXJhbCBhdWRpZW5jZXMuDQoNCiMjIyBQcm9ibGVtIFN0YXRlbWVudA0KDQpBIGNvbXBhbnkgbWFya2V0aW5nIGRpZXRhcnkgc3VwcGxlbWVudCBoYXMgY2FycmllZCBvdXQgYW4gZXhwZXJpbWVudCBvbiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gc3VwcGxlbWVudCBjb25zdW1wdGlvbiBhbmQgZm9ybWFsIHJlYXNvbmluZyBzcGVlZC4gU3R1ZHkgcGFydGljaXBhbnRzIHRvb2sgb25lIG9mIGZvdXIgc3VwcGxlbWVudHMgKG9yIG5vbmUpIGFuZCBleGVjdXRlZCBhIHNlcmllcyBvZiBtZW50YWwgbWF0aCBwcm9ibGVtcy4gVGhlIGNvbXBhbnkgd291bGQgbGlrZSB0byBrbm93IGlmIHRoZWlyIGRhdGEgc2hvd3MgdGhhdCB0aGUgc3VwcGxlbWVudHMgbWFrZSBwZW9wbGUgc21hcnRlci4gVW5mb3J0dW5hdGVseSwgdGhlaXIgZGF0YSBpcyBub3QgbmVhdGx5IG9yZ2FuaXplZC4gRm9yIGV4YW1wbGUsIHRoZSB0aW1lIGlzIG1tLnNzIGZvcm1hdC4NCg0KIyMjIFBhY2thZ2VzIGFuZCBkYXRhIGxvYWRpbmcNCg0KSW4gdGhpcyBkZW1vbnN0cmF0aW9uLCBJIHdpbGwgdXNlIHRoZSBUaWR5dmVyc2UgbGlicmFyeS4gVG8gbGVhcm4gbW9yZSBhYm91dCB0aGUgcGFja2FnZXMsIEkgcmVjb21tZW5kIFdpY2toYW0gYW5kIEdyb2xlbXVuZCAyMDE2LCAiUiBmb3IgRGF0YSBTY2llbmNlIi4NCg0KYGBge3IsIGNvbGxhcHNlPVRSVUUsIGluY2x1ZGU9VFJVRSwgZWNobz1UUlVFLCByZXN1bHRzPSdob2xkJywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCg0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGdndGhlbWVzKQ0KbGlicmFyeShrYWJsZUV4dHJhKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQoNCnNldHdkKCJDOlxcVXNlcnNcXGxpcHRyXFxEb2N1bWVudHNcXFJcXHZpdGFtaW5zIikNCnZpdCA8LSByZWFkX2Nzdigidml0YW1pbnNcXHZpdGFtaW5zLmNzdiIpDQoNCg0KYGBgDQoNCiMgRGF0YSBjbGVhbmluZw0KDQpGaXJzdCwgbGV0IHVzIHRha2UgYSBsb29rIGF0IHRoaXMgZGF0YS4gV2UgY2FuIHVzZSB0aGUga2FibGUgcGFja2FnZSB0byBtYWtlIGVhc3kgdG8gcmVhZCB0YWJsZXMuDQoNCmBgYHtyfQ0Ka2FibGUoaGVhZCh2aXQpKSAgJT4lIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgInJlc3BvbnNpdmUiKSkgJT4lIHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICIyNTBweCIpDQoNCmBgYA0KDQpBbHJlYWR5LCBJIGNhbiBzZWUgdGhyZWUgZ2xhcmluZyBwcm9ibGVtcyBpbiB0aGUgZGF0YS4gDQoqIE9uZSBpcyB0aGF0IHRoZSB0aW1lIGlzbiBpbiBtbS5zcywgcmF0aGVyIHRoYW4gbnVtYmVyIG9mIHNlY29uZHMuIE91ciB0LXRlc3QgdG9vbHMgd2lsbCBuZWVkIHRpbWUgaW4gbnVtYmVyIG9mIHNlY29uZHMuIA0KKiBUaGVyZSBhcmUgc2V2ZXJhbCBtaXNuYW1lZCB0cmVhdG1lbnRzICh3aXRoIG5hbWVzIGxpa2UgYiwgbiwgciwgMSBhbmQgMikuIA0KKiBJdCBpcyByZWR1bnRhbnQgdG8gaGF2ZSBvbmUgdmFyaWFibGUgbGFiZWxlZCB0cmVhdG1lbnQgYW5kIG9uZSB2YXJpYWJsZSBmb3IgdGhlIHR5cGUgb2YgdHJlYXRtZW50LiBJIHdpbGwgbGF0ZXIgY29sbGFwc2UgdGhlbSBpbnRvIG9uZSBmaWxlIHdpdGggY29udHJvbCwgQSwgQiwgQyBhbmQgRCBhcyB0aGUgdmFyaWFibGVzLg0KDQojIyMgVGhlIFRpbWUgVmFyaWFibGUNCg0KRmlyc3QgSSBjYWxjdWxhdGUgdGhlIG5ldyB0aW1lIHZhcmlhYmxlIGFzIGFuIGludGVnZXIgbnVtYmVyIG9mIHNlLg0KDQpgYGB7cn0NCg0Kdml0IDwtIG11dGF0ZSh2aXQsIA0KICAgICAgIG1pbiA9IHRpbWUlLyUxLA0KICAgICAgIHNlYyA9ICh0aW1lIC0gbWluKSoxMDAgKyA2MCptaW4sDQogICAgICAgcG9zaXRpb24gPSByb3duYW1lcyh2aXQpKQ0KDQojcHJpbnQoZmlsdGVyKHZpdCwgcG9zaXRpb249KSkNCg0KYGBgDQoNCkl0J3MgaW1wb3J0YW50IHRvIGNoZWNrIHRoYXQgdGhpcyBmb3JtdWxhIGlzIHdvcmtpbmcgY29ycmVjdGx5LiBUaGUgZWFzaWVzdCB3YXkgdG8gZG8gc28gaXMgdG8gbWFrZSBhIHF1aWNrIGhpc3RvZ3JhbSBvZiB0aGUgdGltZXMuIA0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCg0KcCA8LSBnZ3Bsb3Qodml0LCBtYXBwaW5nID0gYWVzKHNlYykpDQpwICsgZ2VvbV9oaXN0b2dyYW0oY29sb3I9ImJsYWNrIiwgZmlsbD0ibGlnaHRibHVlIikgKyB0aGVtZV9wYW5kZXIoKQ0KDQpgYGANCg0KU2luY2UgdGhlcmUgYXJlIG5vIHN1c3BpY2lvdXMgZ2FwcyBvciBzaGFwZXMgaW4gdGhpcyBoaXN0b2dyYW0sIGl0IGxvb2tzIGxpa2UgbXkgZXF1YXRpb24gaXMgd29ya2luZyBqdXN0IGZpbmUuDQoNCiMjIyBDbGVhbmluZyB0aGUgVHJlYXRtZW50IENhdGVnb3JpZXMNCg0KTm93IGxldCB1cyBsb29rIGF0IG91ciBsYWJlbGluZyBvZiB0aGUgc3ViamVjdHMuIEZpcnN0bHksIHRoZXJlIGlzIGEgcmVkdW5kYW5jeSBiZXR3ZWVuIHRoZSB0cmVhdG1lbnQgY29sdW1uLCB3aGljaCBzaG93cyBhIGJpbmFyeSBmb3Igd2hldGhlciB0aGUgc3ViamVjdCBpcyBpbiB0aGUgY29udHJvbCBncm91cCwgYW5kIHRoZSBzdXBwbGVtZW50IGNvbHVtbi4gSSBzaW1wbGlmeSB0aGlzIGJ5IHNpbXBseSBjaGFuZ2luZyB0aGUgc3VwIGNhdGVnb3J5IHRvICJDb250cm9sIiBmb3IgYWxsIHN1YmplY3RzIGluIHRoZSBjb250cm9sIGdyb3VwLiBJIGFsc28gcmVuYW1lIHRoYXQgdmFyaWFibGUgc3VwLCB0byBzaG9ydGVuIHRoZSBjb2RlIGxhdGVyLg0KDQpUaGVuIEkgY291bnQgYWxsIG9mIHRoZSBkaWZmZXJlbnQgdmFsdWVzIGluIHRoZSBzdXAgdmFyaWFibGUuDQoNCmBgYHtyfQ0KDQp2aXQgPC0gcmVuYW1lKHZpdCwgc3VwID0gc3VwcGxlbWVudCkNCg0Kdml0IDwtIG11dGF0ZSh2aXQsIHN1cCA9IHJlcGxhY2Uoc3VwLCB0cmVhdCA9PTAsICJDT05UUk9MIikpDQoNCmNvdW50KHZpdCwgc3VwKQ0KDQpgYGANCg0KRnJvbSB0aGlzIGNvdW50IHdlIGNhbiBzZWUgdGhlcmUgYXJlIG1hbnkgcG9vcmx5IGxhYmVsZWQgdHJlYXRtZW50cy4gTW9zdCB0cmVhbWVudHMgYXJlIGxhYmVsZWQgd2l0aCBhIHNpbmdsZSBjYXBpdGFsIGxldHRlciwgYnV0IHNvbWUgYXJlIGxvd2VyIGNhc2UsIHNvbWUgYXJlIG51bWJlcnMsIGFuZCBzb21lIGFyZSBldmVuIG90aGVyIHJhbmRvbSBsZXR0ZXJzIChuIGFuZCByKS4gVG8gc29sdmUgdGhpcywgSSByZW1vdmUgYWxsIHNwYWNlcyBhbmQgdXBwZXJjYXNlIGFsbCB0aGUgbGV0dGVycywgdGhlbiByZW1vdmUgYW55IHVuY2xlYXIgdmFsdWVzLiBUaGVuIEkgcmVuYW1lIHRoZW0gQ29udHJvbCwgYW5kIFRyZWF0bWVudF9YLCB0byBtYWtlIHRoZSBmaW5hbCBvdXRwdXRzIGVhc2llciB0byByZWFkLg0KDQpgYGB7cn0NCg0Kdml0IDwtIG11dGF0ZSh2aXQsDQogICAgICAgICAgIHN1cCA9IHN0cl90b191cHBlcihzdXApLA0KICAgICAgICAgICBzdXAgPSBzdHJfdHJpbShzdXApDQogICAgICAgICAgICkNCg0Kdml0IDwtIGZpbHRlcih2aXQsIHN1cCA9PSAiQSIgfCBzdXAgPT0gIkIiIHwgc3VwID09ICJDIiB8IHN1cCA9PSAiRCIgfCBzdXAgPT0gIkNPTlRST0wiKQ0KDQp2aXQgPC0gbXV0YXRlKHZpdCwNCiAgICAgICAgICAgICAgc3VwID0gcmVwbGFjZShzdXAsIHRyZWF0ID09MCwgIkNvbnRyb2wiKSwNCiAgICAgICAgICAgICAgc3VwID0gcmVwbGFjZShzdXAsIHN1cCA9PSAiQSIsICJUcmVhdG1lbnRfQSIpLA0KICAgICAgICAgICAgICBzdXAgPSByZXBsYWNlKHN1cCwgc3VwID09ICJCIiwgIlRyZWF0bWVudF9CIiksDQogICAgICAgICAgICAgIHN1cCA9IHJlcGxhY2Uoc3VwLCBzdXAgPT0gIkMiLCAiVHJlYXRtZW50X0MiKSwNCiAgICAgICAgICAgICAgc3VwID0gcmVwbGFjZShzdXAsIHN1cCA9PSAiRCIsICJUcmVhdG1lbnRfRCIpDQogICAgICAgICAgICAgICkNCg0KYGBgDQoNCiMjIyBDaGVja2luZyBmb3IgRHVwbGljYXRlcw0KDQpJdCBpcyBiZXN0IHByYWN0aWNlIHRvIGF0dGFjaCBhIHVuaXF1ZSBvYnNlcnZhdGlvbiBpZCBmb3IgZWFjaCBlbnRyeSBpbiBhIHN1cnZleSwgb2Z0ZW4gYSBob3VzaGVvbGQgSUQgb3IgcmVzcG9uZGVudCBJRC4gVW5mb3J0dW5hdGVseSwgdGhpcyBleHBlcmltZW50ZXIgZGlkIG5vdCBjcmVhdGUgYW4gaWQgZm9yIGV2ZXJ5IG9ic2VydmF0aW9uIChyZXNwb25kZW50IGluIHRoaXMgY2FzZSkuIFRoaXMgbWFrZXMgaXQgaW1wb3NzaWJsZSB0byBiZSBzdXJlIEkgaGF2ZSBmb3VuZCBhbGwgZHVwbGljYXRlIG9ic2VydmF0aW9ucywgc2luY2UgdHdvIHN1YmplY3RzIGNvdWxkIGhhdmUgcmVjZWl2ZWQgdGhlIHNhbWUgdHJlYXRtZW50IGFuZCB1c2VkIHRoZSBzYW1lIG51bWJlciBvZiBzZWNvbmRzIGJ5IGNoYW5jZS4gSG93ZXZlciwgSSBjYW4gY2hlY2sgZm9yIGNvbnNlY3V0aXZlIGR1cGxpY2F0ZXMgd2l0aCB0aGUgZm9sbG93aW5nIGNvZGUgdGhhdCBmaW5kcyBjb25zZWN1dGl2ZSBkdXBsaWNhdGVzIHRoZW4gcHJpbnRzIHRob3NlIG9ic2VydmF0aW9ucy4NCg0KYGBge3J9DQoNCnZpdDwtIG11dGF0ZSh2aXQsDQogICAgICAgICAgICAgZHVwID0gRkFMU0UsDQogICAgICAgICAgICAgZHVwID0gcmVwbGFjZShkdXAsIHN1cD09bGVhZChzdXApICYgc2VjPT1sZWFkKHNlYyksIFRSVUUpKQ0KDQpwcmludChmaWx0ZXIodml0LCBkdXAgPT0gVFJVRSB8IGxhZyhkdXA9PVRSVUUpKSkNCg0KYGBgDQoNCkdvb2QsIG9ubHkgb25lIHZhbHVlIGlzIGEgZHVwbGljYXRlLiBCdXQgaXMgdGhpcyB2YWx1ZSBhIGR1cGxpY2F0ZT8gTGV0J3MgY2hlY2sgdGhlIG9yaWdpbmFsIHZhbHVlcy4NCg0KYGBge3J9DQoNCnZpdDIgPC0gcmVhZF9jc3YoInZpdGFtaW5zXFx2aXRhbWlucy5jc3YiKQ0KDQpwcmludChmaWx0ZXIodml0Miwgcm93bmFtZXModml0MikgPT0gMzM3IHwgcm93bmFtZXModml0MikgPT0gMzM4KSkNCg0KYGBgDQoNClRoZXNlIHR3byBvYnNlcnZhdGlvbnMgYXJlIHN1c3BpY2lvdXMsIGFzIGl0IHdvdWRsIGJlIGVhc3kgZm9yIGFuIGVudW1lcmF0b3IgdG8gYWNjaWRlbnRhbGx5IGVudGVyIHRoZSBzYW1lIHZhbHVlIHR3aWNlLiBCdXQgc2luY2UgdGhlc2UgZW51bWVyYXRvcnMgYXJlIGZpY3Rpb25hbCwgSSBjYW5ub3QgY2FsbCB0aGVtIHVwIGFuZCBhc2sgYWJvdXQgdGhlIG9ic2VydmF0aW9ucy4gVGhlcmVmb3JlLCBJIHdpbGwga2VlcCBpdCBpbiB0aGUgZGF0YS4NCg0KQWZ0ZXIgY2xlYW5pbmcsIG91dCBjbGVhbmVkIGRhdGEgbG9va3MgbGlrZSB0aGlzLg0KDQpgYGB7cn0NCmthYmxlKGhlYWQodml0KSkgICU+JSBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJyZXNwb25zaXZlIikpICU+JSBzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiLCBoZWlnaHQgPSAiMjUwcHgiKQ0KYGBgDQoNCiMgRGF0YSBBbmFseXNpcw0KDQojIyMgVmlzdWFsaXppbmcgdGhlIFJlc3VsdHMNCg0KTm93IHRoYXQgdGhlIGRhdGEgaXMgY2xlYW4sIEkgY2FuIGJlZ2luIGFuYWx5c2lzLiBCdXQsIGJlZm9yZSBiZWdpbmluZyBhbnkgZm9ybWFsIHRlc3RzIG9mIHNpZ25pZmljYW5jZSwgaXQgaXMgdmFsdWFibGUgdG8gdmlzdWFsaXplIG91ciByZXN1bHRzLiBUaGlzIHdpbGwgaGVscCB1cyB0byBjaGVjayB0aGF0IGV2ZXJ5dGhpbmcgaXMgcnVubmluZyBzbW9vdGhseSBhbmQgdG8gY29udGV4dHVhbGl6ZSBhbnkgZmluZGluZ3MuIEJlY2F1c2UgdGhpcyBkYXRhIHNldCBpcyBxdWl0ZSBuYXJyb3csIGEgc2ltcGxlIGJveHBsb3QgcHJvdmlkZXMgdGhlIG1vc3QgaW1wb3J0YW50IGluZm9ybWF0aW9uLg0KDQpgYGB7cn0NCg0KZyA8LSBnZ3Bsb3Qodml0LCBtYXBwaW5nID0gYWVzKHN1cCwgc2VjKSkNCmcgKyBnZW9tX2JveHBsb3QoKSArDQogIGxhYnModGl0bGU9IlRpbWUgdG8gY29tcGxldGUgcHJvYmxlbSBzZXQgYnkgc3VwcGxlbWVudCBwcm92aWRlZCIsIHg9IlRpbWUgdGFrZW4gdG8gY29wbGV0ZSBtZW50YWwgbWF0aCBwcm9ibGVtcyIsIHk9ICJTdXBwbGVtZW50IGNhdGVnb3J5IikgKw0KICB0aGVtZV9wYW5kZXIoKSArIHNjYWxlX2ZpbGxfcGFuZGVyKCkNCg0KYGBgDQoNCkp1c3QgZnJvbSByZWFkaW5nIHRoZSBib3hwbG90LCBJIGNhbiBtYWtlIGEgZmV3IHByZWxpbWluYXJ5IGNvbmNsdXNpb25zLg0KDQoxLiBTdWJqZWN0cyB3aG8gdG9vayBzdXBwbGVtZW50cyBBLCBCLCBhbmQgRCBhbGwgcGVyZm9ybWVkIHRoZSB0ZXN0IGZhc3RlciB0aGFuIHN1YmplY3RzIHdobyB0b29rIHRoZSBjb250cm9sLiBJbiB0aGUgbmV4dCBzZWN0aW9uLCBJIHdpbGwgZGV0ZXJtaW5lIGlmIHRoaXMgcmVzdWx0IGlzIHNpZ25pZmljYW50Lg0KDQoyLiBTdWJqZWN0cyB3aG8gdG9vayBzdXBwbGVtZW50IEMgYWN0dWFsbHkgcGVyZm9ybWVkIHRoZSBtZW50YWwgbWF0aCBtb3JlIHNsb3dseS4gSSBrbm93IHRoYXQgb3VyIHRlc3Qgd2lsbCBub3QgcHJlc2VudCBldmlkZW5jZSB0aGF0IGl0IGlzIGVmZmVjdGl2ZS4NCg0KMy4gVGhlIHZhcmlhbmNlIGluIHRoZSBjb250cm9sIGdyb3VwIHNlZW1zIHRvIGhpZ2hlciB0aGFuIHRoZSB0cmVhdG1lbnQgZ3JvdXBzLiBTZXZlcmFsIHBhcnRpY2lwYW50cyBpbiB0aGUgY29udHJvbCBncm91cCBjb21wbGV0ZWQgdGhlIHRyaWFsIGluIGxlc3MgdGhhbiA1MCBzZWNvbmRzLiBUaGlzIG1heSBzdWdnZXN0IHByb2JsZW1zIGluIHRoZSBleHBlcmltZW50YWwgZGVzaWduLCBhbmQgd291bGQgbm9ybWFsbHkgYmUgcmVhc29uIHRvIGNvbnRhY3QgdGhlIGVudW1lcmF0b3JzLg0KDQojIyMgVGVzdGluZyBmb3IgU2lnbmZpY2FuY2UNCg0KVG8gdGVzdCB0aGUgZWZmZWN0aXZlbmVzcyBvZiB0aGUgc3VwcGxlbWVudHMsIEkgdXNlIGFuIGluZGVwZW5kZW50IHR3by1zYW1wbGUgdC10ZXN0LiBCeSBjb252ZW50aW9uLCBJIHNldCBteSBzaWduZmljYW5jZSB0aHJlc2hvbGQgYSB0byAkXGFscGhhJCA9IC4wNS4gRWFjaCB0LXRlc3QgY29tcGFyZXMgYSBzdXBwbGVtZW50LCBpbmRlcGVuZGVudCBvZiB0aGUgb3RoZXJzLCB0byBvdXIgY29udHJvbCBncm91cC4NCg0KYGBge3IsIGNvbGxhcHNlPVRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQoNCmF0dGFjaCh2aXQpDQoNCnQudGVzdChzZWNbc3VwPT0iQ29udHJvbCJdLCBzZWNbc3VwPT0iVHJlYXRtZW50X0EiXSwgYWx0ZXJuYXRpdmUgPSAibGVzcyIsIGRhdGEgPSB2aXQpDQp0LnRlc3Qoc2VjW3N1cD09IkNvbnRyb2wiXSwgc2VjW3N1cD09IlRyZWF0bWVudF9CIl0sIGFsdGVybmF0aXZlID0gImxlc3MiLCBkYXRhID0gdml0KQ0KdC50ZXN0KHNlY1tzdXA9PSJDb250cm9sIl0sIHNlY1tzdXA9PSJUcmVhdG1lbnRfQyJdLCBhbHRlcm5hdGl2ZSA9ICJsZXNzIiwgZGF0YSA9IHZpdCkNCnQudGVzdChzZWNbc3VwPT0iQ29udHJvbCJdLCBzZWNbc3VwPT0iVHJlYXRtZW50X0QiXSwgYWx0ZXJuYXRpdmUgPSAibGVzcyIsIGRhdGEgPSB2aXQpDQoNCmBgYA0KDQpGb3IgZWFjaCB0LXRlc3QgdGhlcmUgaXMgYSBoeXBvdGhlc2lzIGFuZCBhIG51bGwgaHlwb3RoZXNpcy4gVGhlIGh5cG90aGVzaXMgaXMgdGhhdCB0aGUgc3VwcGxlbWVudHMgaW1wcm92ZWQgbWVudGFsIG1hdGggc3BlZWQgKHJlZHVjZWQgdGhlIG51bWJlciBvZiBzZWNvbmRzKSBhbmQgdGhlIG51bGwgaHlwb3RoZXNpcyBpcyB0aGF0IHRoZXJlIHdhcyBubyBlZmZlY3QuIFRoZSBxdWlja2VzdCBudW1iZXIgdG8gbG9vayBhdCBoZXJlIGlzIHRoZSBwLXZhbHVlLCB3aGljaCBpcyB0aGF0IGNoYW5jZSBvZiB0aGVzZSByZXN1bHRzIG9jY3VyaW5nIGlmIHRoZSBudWxsIHZhbHVlIGlzIHRydWUuDQoNClN1cHBsZW1lbnRzIEEgYW5kIEIgYm90aCBoYXZlIHAtdmFsdWVzIGFib3ZlIC45NS4gVGhpcyBtZWFucyB0aGVzZSByZXN1bHRzIHdvdWxkIGJlIHVubGlrZWx5IChvY2N1cmluZyBpbiBvbmx5IG9uZSBpbnQgdHdlbnR5IHRyaWFscyksIGlmIHRoZSBzdXBwbGVtZW50IHdhcyBub3QgaW1wcm92aW5nIG1hdGggYWJpbGl0eS4gSXQgZG9lcyBub3QgcHJvdmUgdGhlIHN1cHBsZW1lbnRzIGFyZSBlZmZlY3RpdmUsIGJ1dCBpdCBzdWdnZXN0cyB0aGF0IHRoZXkgYXJlLiBUaGF0IHRoZXNlIHJlc3VsdHMgYXJlIGFsc28gZGVwZW5kZW50IG4gdGhlIGZhaXJuZXNzIGZvIHRoZSB0cmlhbCBhbmQgc291bmRuZXNzIG9mIHRoZSBkZXNpZ24uDQoNCkZvciBDIGFuZCBELCBJIGNhbm5vdCBlbGltaW5hdGUgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZSBzdXBwbGVtZW50cyBoYXZlIG5vIGVmZmVjdC4gSXQgaXMgdW5saWtlbHksIGJ1dCBub3QgaW1wb3NzaWJsZSwgdGhhdCB0aGlzIHJlc3VsdCB3YXMgYW4gYWJlcnJhdGlvbiBvZiBvdXIgc3R1ZHkgYW5kIGZ1dHVyZSwgbW9yZSBkZXRhaWxlZCB3b3JrIHdvdWxkIGZpbmQgYSBkaWZmZXJlbnQgcmVzdWx0Lg0K