Download Data Files
This exercise is based on data from a PhD student in cognitive psychology. In his work, this student collects response times (RT) to two simultaneous tasks, and then he has to analyse the response times.
At \(t_0\) , the stimulus S1 is triggered
At \(t_1=t_0 + SOA\) , the stimulus S2 is triggered (SOA is the time between the 2 stimuli)
At \(t_2=t_0 + RT1\) , the subject responds to stimulus S1
At \(t_3=t_1 + RT2\) , the subject responds to stimulus S2
The inter-response interval (IRI) is defined as the time difference between \(t_3\) and \(t_2\) , thus \(IRI=SOA+RT2-RT1\) . Negatives IRI therefore mean that the response to S2 is emitted before the response to S1.
For theoretical reasons, one can consider that if \(SOA=1500\) ms, both stimulis are answered independently. One can thus use the RT1 and RT2 values for SOA=1500 ms to estimate the IRI in the case of independent responses to the stimuli.
Data wrangling
Download the datafiles archive and unzip it, then create a R project in this folder in Rstudio.
Load the tidyverse
and patchwork
packages:
library (tidyverse)
library (patchwork)
Load the .csv file in the Data
folder and save it into raw_data
. Look into the help of read_csv ()
to help you get rid of the error.
raw_data <- read_csv2 ("Data/data exemple.csv" , show_col_types = FALSE )
Using successive pipe operations , we will now create a dataclean
table from raw_data
, where we:
Filter raw_data
so that Procedure[Trial]
is only equal to "EssaisDT"
Mutate the table by adding a column IRI
containing SOAdur + S2Visuel.RT - S1Audio.RT
Filter the table so that some extreme values are excluded:
S1Audio.RT
is smaller or equal to 2500 and larger or equal to 100
S2Visuel.RT
is smaller or equal to 2500 and larger or equal to 100
S1Audio.ACC
, S1response.ACC
and S2Visuel.ACC
are equal to 1
dataclean <- raw_data %>%
filter (` Procedure[Trial] ` == "EssaisDT" ) %>%
mutate (IRI = SOAdur + S2Visuel.RT - S1Audio.RT) %>%
filter (S1Audio.RT <= 2500 & S1Audio.RT >= 100 &
S2Visuel.RT <= 2500 & S2Visuel.RT >= 100 &
S1Audio.ACC == 1 & S1response.ACC == 1 & S2Visuel.ACC == 1 )
Let’s compute the simulated values in the case the responses to the stimuli are independent, i.e. using SOA=1500ms, and save it into a tibble called IRI_sim
. Using successive pipe operations and starting from dataclean
:
Filter rows so that SOAdur
is equal to 1500
Delete the SOAdur
and IRI
columns
Mutate the table to add 3 columns IRI_sim_xx
, where xx
=15, 65 or 250 and IRI_sim_xx = xx + S2Visuel.RT - S1Audio.RT
.
Using pivot_longer ()
and the options names_prefix = "IRI_sim_", names_to = "SOAdur", values_to = "IRI_sim"
, pivot the columns containing "IRI_sim_"
into a long table (you need to add the option to select the corresponding columns).
IRI_sim <- dataclean %>%
filter (SOAdur == 1500 ) %>%
select (- c (SOAdur, IRI)) %>%
mutate (
IRI_sim_15 = 15 + S2Visuel.RT - S1Audio.RT,
IRI_sim_65 = 65 + S2Visuel.RT - S1Audio.RT,
IRI_sim_250 = 250 + S2Visuel.RT - S1Audio.RT
) %>%
pivot_longer (
cols = contains ("IRI_sim_" ),
names_prefix = "IRI_sim_" ,
names_to = "SOAdur" ,
values_to = "IRI_sim"
)
We want now to get the averaged IRI
per subject and per SOA, and its standard deviation. Using group_by ()
and summarise ()
, store the mean and standard deviation of IRI
in a table called stats_obs
, starting from dataclean
. It should look like this:
(stats_obs <- dataclean %>%
group_by (Subject, SOAdur) %>%
summarise (
mean = mean (IRI),
sd = sd (IRI)
))
## # A tibble: 24 × 4
## # Groups: Subject [6]
## Subject SOAdur mean sd
## <dbl> <dbl> <dbl> <dbl>
## 1 1 15 -64.8 291.
## 2 1 65 20.8 297.
## 3 1 250 218. 217.
## 4 1 1500 1019. 228.
## 5 2 15 -159. 193.
## 6 2 65 -156. 236.
## 7 2 250 4.42 191.
## 8 2 1500 1184. 198.
## 9 3 15 -289. 207.
## 10 3 65 -251. 262.
## # … with 14 more rows
We want to do the same for the 3 simulated IRI.
(stats_sim <- IRI_sim %>%
group_by (Subject, SOAdur) %>%
summarise (
mean = mean (IRI_sim),
sd = sd (IRI_sim)
))
## # A tibble: 18 × 4
## # Groups: Subject [6]
## Subject SOAdur mean sd
## <dbl> <chr> <dbl> <dbl>
## 1 1 15 -466. 228.
## 2 1 250 -231. 228.
## 3 1 65 -416. 228.
## 4 2 15 -301. 198.
## 5 2 250 -65.9 198.
## 6 2 65 -251. 198.
## 7 3 15 -99.0 157.
## 8 3 250 136. 157.
## 9 3 65 -49.0 157.
## 10 4 15 -168. 214.
## 11 4 250 66.9 214.
## 12 4 65 -118. 214.
## 13 5 15 -367. 249.
## 14 5 250 -132. 249.
## 15 5 65 -317. 249.
## 16 6 15 -313. 161.
## 17 6 250 -77.9 161.
## 18 6 65 -263. 161.
Plotting
We want now to produce a graph showing the histograms of the observed IRI
column using ggplot2
.
Create a ggplot
using the dataclean
dataset
Set the aesthetics to x = IRI
Create the histograms using geom_histogram ()
, with a fill color depending on SOAdur
Arrange the plots on a grid depending on the Subject
column using facet_wrap ()
Add a vertical lign marking the average value for each subject using geom_vline ()
. The data for these lines are stored in the stats_obs
dataset.
Play with the theme and other ggplot commands to make the plot look like the one below
dataclean %>%
ggplot (aes (x = IRI, fill = factor (SOAdur))) +
geom_histogram (aes (y = stat (count / sum (count))), bins= 20 ) +
scale_y_continuous (labels = scales:: percent_format ())+
facet_wrap (~ paste ("Subject" , Subject)) +
geom_vline (data = stats_obs, aes (xintercept = mean, color= factor (SOAdur)), lty = 2 , show.legend = FALSE ) +
scale_x_continuous (limits = c (- 2000 ,2000 ))+
labs (title = "Observations" ,
x = "IRI [ms]" ,
y = "Occurence" ,
fill= "SOA [ms]" ) +
theme_bw () +
theme (strip.background = element_rect (fill = "transparent" , colour = NA ),
strip.text = element_text (face = "bold" ),
axis.text.x = element_text (angle = 45 , vjust = 1 , hjust = 1 ))
Let’s do the same for the simulated dataset. It should look like this:
IRI_sim %>%
ggplot (aes (x = IRI_sim, fill = factor (SOAdur, levels= c (15 , 65 , 250 )))) +
geom_histogram (aes (y = stat (count / sum (count))), bins = 20 ) +
scale_y_continuous (labels = scales:: percent_format ()) +
facet_wrap (~ paste ("Subject" , Subject)) +
geom_vline (data = stats_sim, aes (xintercept = mean, color= factor (SOAdur)), lty = 2 , show.legend = FALSE ) +
scale_x_continuous (limits = c (- 2000 ,2000 ))+
labs (
title = "Simulations" ,
x = "IRI [ms]" ,
y = "Occurence" ,
fill = "SOA [ms]"
) +
theme_bw () +
theme (
strip.background = element_rect (fill = "transparent" , colour = NA ),
strip.text = element_text (face = "bold" ),
axis.text.x = element_text (angle = 45 , vjust = 1 , hjust = 1 )
)
LS0tCnRpdGxlIDogIlIgRXhlcmNpc2VzIC0gQ29nbml0aXZlIFBzeWNob2xvZ3kiCmRhdGUgIDogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6IAogICAgaHRtbF9kb2N1bWVudDoKICAgICAgICB0b2MgICAgICAgICAgICA6IHRydWUKICAgICAgICB0b2NfZmxvYXQgICAgICA6IHRydWUKICAgICAgICB0b2NfZGVwdGggICAgICA6IDQKICAgICAgICBoaWdobGlnaHQgICAgICA6IHRhbmdvCiAgICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICAgICAgY29kZV9kb3dubG9hZCAgOiBUUlVFCnBhcmFtczogCiAgICBzb2x1dGlvbjoKICAgICAgICB2YWx1ZTogVFJVRQotLS0KCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+CmJsb2NrcXVvdGUgewogIGJhY2tncm91bmQ6ICNFOUY5RkY7CiAgYm9yZGVyLWxlZnQ6IDVweCBzb2xpZCAjMDI2MDg2OwogIG1hcmdpbjogMS41ZW0gMTBweDsKICBwYWRkaW5nOiAwLjVlbSAxMHB4OwogIGZvbnQtc2l6ZTogMWVtOwp9Cjwvc3R5bGU+CgpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBmaWcuYWxpZ249ImNlbnRlciJ9CmxpYnJhcnkoZG93bmxvYWR0aGlzKQpkb3dubG9hZF9saW5rKAogIGxpbmsgPSAiLi9BcmNoaXZlLnppcCIsCiAgb3V0cHV0X25hbWUgPSAiRGF0YSBGaWxlcyIsCiAgYnV0dG9uX2xhYmVsID0gIkRvd25sb2FkIERhdGEgRmlsZXMiLAogIGJ1dHRvbl90eXBlID0gImRlZmF1bHQiLAogIGhhc19pY29uID0gVFJVRSwKICBpY29uID0gImZhIGZhLXNhdmUiLAogIHNlbGZfY29udGFpbmVkID0gRkFMU0UKKQpgYGAKPGJyPgoKYGBge3IgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShrbml0cikKa25pdHI6Om9wdHNfY2h1bmskc2V0KGNhY2hlID0gRkFMU0UsIG91dC53aWR0aD0nMTAwJScsIHdhcm5pbmdzPUZBTFNFLCBtZXNzYWdlPUZBTFNFKQpvcHRpb25zKHdpZHRoID0gODApCmBgYAoKLS0tLQoKVGhpcyBleGVyY2lzZSBpcyBiYXNlZCBvbiBkYXRhIGZyb20gYSBQaEQgc3R1ZGVudCBpbiBjb2duaXRpdmUgcHN5Y2hvbG9neS4gSW4gaGlzIHdvcmssIHRoaXMgc3R1ZGVudCBjb2xsZWN0cyByZXNwb25zZSB0aW1lcyAoUlQpIHRvIHR3byBzaW11bHRhbmVvdXMgdGFza3MsIGFuZCB0aGVuIGhlIGhhcyB0byBhbmFseXNlIHRoZSByZXNwb25zZSB0aW1lcy4KCi0gQXQgJHRfMCQsIHRoZSBzdGltdWx1cyBTMSBpcyB0cmlnZ2VyZWQKLSBBdCAkdF8xPXRfMCArIFNPQSQsIHRoZSBzdGltdWx1cyBTMiBpcyB0cmlnZ2VyZWQgKFNPQSBpcyB0aGUgdGltZSBiZXR3ZWVuIHRoZSAyIHN0aW11bGkpCi0gQXQgJHRfMj10XzAgKyBSVDEkLCB0aGUgc3ViamVjdCByZXNwb25kcyB0byBzdGltdWx1cyBTMQotIEF0ICR0XzM9dF8xICsgUlQyJCwgdGhlIHN1YmplY3QgcmVzcG9uZHMgdG8gc3RpbXVsdXMgUzIKClRoZSBpbnRlci1yZXNwb25zZSBpbnRlcnZhbCAoSVJJKSBpcyBkZWZpbmVkIGFzIHRoZSB0aW1lIGRpZmZlcmVuY2UgYmV0d2VlbiAkdF8zJCBhbmQgJHRfMiQsIHRodXMgJElSST1TT0ErUlQyLVJUMSQuIE5lZ2F0aXZlcyBJUkkgdGhlcmVmb3JlIG1lYW4gdGhhdCB0aGUgcmVzcG9uc2UgdG8gUzIgaXMgZW1pdHRlZCBiZWZvcmUgdGhlIHJlc3BvbnNlIHRvIFMxLgoKRm9yIHRoZW9yZXRpY2FsIHJlYXNvbnMsIG9uZSBjYW4gY29uc2lkZXIgdGhhdCBpZiAkU09BPTE1MDAkIG1zLCBib3RoIHN0aW11bGlzIGFyZSBhbnN3ZXJlZCBpbmRlcGVuZGVudGx5LiBPbmUgY2FuIHRodXMgdXNlIHRoZSBSVDEgYW5kIFJUMiB2YWx1ZXMgZm9yIFNPQT0xNTAwIG1zIHRvIGVzdGltYXRlIHRoZSBJUkkgaW4gdGhlIGNhc2Ugb2YgaW5kZXBlbmRlbnQgcmVzcG9uc2VzIHRvIHRoZSBzdGltdWxpLgoKLS0tCgojIERhdGEgd3JhbmdsaW5nCgotIERvd25sb2FkIHRoZSBkYXRhZmlsZXMgPGEgaHJlZj0iQXJjaGl2ZS56aXAiIGRvd25sb2FkIHRhcmdldD0iX2JsYW5rIj5hcmNoaXZlPC9hPiBhbmQgdW56aXAgaXQsIHRoZW4gY3JlYXRlIGEgUiBwcm9qZWN0IGluIHRoaXMgZm9sZGVyIGluIFJzdHVkaW8uCi0gTG9hZCB0aGUgYHRpZHl2ZXJzZWAgYW5kIGBwYXRjaHdvcmtgIHBhY2thZ2VzOgoKYGBge3IgaW5jbHVkZT1wYXJhbXMkc29sdXRpb24sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHBhdGNod29yaykKYGBgCgotIExvYWQgdGhlIC5jc3YgZmlsZSBpbiB0aGUgYERhdGFgIGZvbGRlciBhbmQgc2F2ZSBpdCBpbnRvIGByYXdfZGF0YWAuIExvb2sgaW50byB0aGUgaGVscCBvZiBgcmVhZF9jc3YoKWB7LlJ9IHRvIGhlbHAgeW91IGdldCByaWQgb2YgdGhlIGVycm9yLgoKYGBge3IgaW5jbHVkZT1wYXJhbXMkc29sdXRpb24sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9RkFMU0V9CnJhd19kYXRhIDwtIHJlYWRfY3N2MigiRGF0YS9kYXRhIGV4ZW1wbGUuY3N2Iiwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkKYGBgCgotIFVzaW5nIHN1Y2Nlc3NpdmUgKipwaXBlIG9wZXJhdGlvbnMqKiwgd2Ugd2lsbCBub3cgY3JlYXRlIGEgYGRhdGFjbGVhbmAgdGFibGUgZnJvbSBgcmF3X2RhdGFgLCB3aGVyZSB3ZToKICAgIC0gKipGaWx0ZXIqKiBgcmF3X2RhdGFgIHNvIHRoYXQgYFByb2NlZHVyZVtUcmlhbF1gIGlzIG9ubHkgZXF1YWwgdG8gYCJFc3NhaXNEVCJgCiAgICAtICoqTXV0YXRlKiogdGhlIHRhYmxlIGJ5IGFkZGluZyBhIGNvbHVtbiBgSVJJYCBjb250YWluaW5nIGBTT0FkdXIgKyBTMlZpc3VlbC5SVCAtIFMxQXVkaW8uUlRgCiAgICAtICoqRmlsdGVyKiogdGhlIHRhYmxlIHNvIHRoYXQgc29tZSBleHRyZW1lIHZhbHVlcyBhcmUgZXhjbHVkZWQ6CiAgICAgICAgLSBgUzFBdWRpby5SVGAgaXMgc21hbGxlciBvciBlcXVhbCB0byAyNTAwIGFuZCBsYXJnZXIgb3IgZXF1YWwgdG8gMTAwCiAgICAgICAgLSBgUzJWaXN1ZWwuUlRgIGlzIHNtYWxsZXIgb3IgZXF1YWwgdG8gMjUwMCBhbmQgbGFyZ2VyIG9yIGVxdWFsIHRvIDEwMAogICAgICAgIC0gYFMxQXVkaW8uQUNDYCwgYFMxcmVzcG9uc2UuQUNDYCBhbmQgYFMyVmlzdWVsLkFDQ2AgYXJlIGVxdWFsIHRvIDEKCmBgYHtyIGluY2x1ZGU9cGFyYW1zJHNvbHV0aW9uLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPUZBTFNFfQpkYXRhY2xlYW4gPC0gcmF3X2RhdGEgJT4lIAogICAgZmlsdGVyKGBQcm9jZWR1cmVbVHJpYWxdYCA9PSAiRXNzYWlzRFQiKSAlPiUKICAgIG11dGF0ZShJUkkgPSBTT0FkdXIgKyBTMlZpc3VlbC5SVCAtIFMxQXVkaW8uUlQpICU+JSAKICAgIGZpbHRlcihTMUF1ZGlvLlJUIDw9IDI1MDAgJiBTMUF1ZGlvLlJUID49IDEwMCAmCiAgICAgICAgUzJWaXN1ZWwuUlQgPD0gMjUwMCAmIFMyVmlzdWVsLlJUID49IDEwMCAmCiAgICAgICAgUzFBdWRpby5BQ0MgPT0gMSAmIFMxcmVzcG9uc2UuQUNDID09IDEgJiBTMlZpc3VlbC5BQ0MgPT0gMSkKYGBgCgotIExldCdzIGNvbXB1dGUgdGhlIHNpbXVsYXRlZCB2YWx1ZXMgaW4gdGhlIGNhc2UgdGhlIHJlc3BvbnNlcyB0byB0aGUgc3RpbXVsaSBhcmUgaW5kZXBlbmRlbnQsIF9pLmUuXyB1c2luZyBTT0E9MTUwMG1zLCBhbmQgc2F2ZSBpdCBpbnRvIGEgdGliYmxlIGNhbGxlZCBgSVJJX3NpbWAuIFVzaW5nIHN1Y2Nlc3NpdmUgcGlwZSBvcGVyYXRpb25zIGFuZCBzdGFydGluZyBmcm9tIGBkYXRhY2xlYW5gOgogICAgLSAqKkZpbHRlcioqIHJvd3Mgc28gdGhhdCBgU09BZHVyYCBpcyBlcXVhbCB0byAxNTAwCiAgICAtIERlbGV0ZSB0aGUgYFNPQWR1cmAgYW5kIGBJUklgIGNvbHVtbnMKICAgIC0gKipNdXRhdGUqKiB0aGUgdGFibGUgdG8gYWRkIDMgY29sdW1ucyBgSVJJX3NpbV94eGAsIHdoZXJlIGB4eGA9MTUsIDY1IG9yIDI1MCBhbmQgYElSSV9zaW1feHggPSB4eCArIFMyVmlzdWVsLlJUIC0gUzFBdWRpby5SVGAuCiAgICAtIFVzaW5nIGBwaXZvdF9sb25nZXIoKWB7LlJ9IGFuZCB0aGUgb3B0aW9ucyBgbmFtZXNfcHJlZml4ID0gIklSSV9zaW1fIiwgbmFtZXNfdG8gPSAiU09BZHVyIiwgdmFsdWVzX3RvID0gIklSSV9zaW0iYCwgcGl2b3QgdGhlIGNvbHVtbnMgY29udGFpbmluZyBgIklSSV9zaW1fImAgaW50byBhIGxvbmcgdGFibGUgKHlvdSBuZWVkIHRvIGFkZCB0aGUgb3B0aW9uIHRvIHNlbGVjdCB0aGUgY29ycmVzcG9uZGluZyBjb2x1bW5zKS4KCmBgYHtyIGluY2x1ZGU9cGFyYW1zJHNvbHV0aW9uLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPUZBTFNFfQpJUklfc2ltIDwtIGRhdGFjbGVhbiAlPiUKICAgIGZpbHRlcihTT0FkdXIgPT0gMTUwMCkgJT4lCiAgICBzZWxlY3QoLWMoU09BZHVyLCBJUkkpKSAlPiUKICAgIG11dGF0ZSgKICAgICAgICBJUklfc2ltXzE1ID0gMTUgKyBTMlZpc3VlbC5SVCAtIFMxQXVkaW8uUlQsCiAgICAgICAgSVJJX3NpbV82NSA9IDY1ICsgUzJWaXN1ZWwuUlQgLSBTMUF1ZGlvLlJULAogICAgICAgIElSSV9zaW1fMjUwID0gMjUwICsgUzJWaXN1ZWwuUlQgLSBTMUF1ZGlvLlJUCiAgICApICU+JQogICAgcGl2b3RfbG9uZ2VyKAogICAgICAgIGNvbHMgPSBjb250YWlucygiSVJJX3NpbV8iKSwKICAgICAgICBuYW1lc19wcmVmaXggPSAiSVJJX3NpbV8iLAogICAgICAgIG5hbWVzX3RvID0gIlNPQWR1ciIsCiAgICAgICAgdmFsdWVzX3RvID0gIklSSV9zaW0iCiAgICApCmBgYAoKLSBXZSB3YW50IG5vdyB0byBnZXQgdGhlIGF2ZXJhZ2VkIGBJUklgIHBlciBzdWJqZWN0IGFuZCBwZXIgU09BLCBhbmQgaXRzIHN0YW5kYXJkIGRldmlhdGlvbi4gVXNpbmcgYGdyb3VwX2J5KClgey5SfSBhbmQgYHN1bW1hcmlzZSgpYHsuUn0sIHN0b3JlIHRoZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgYElSSWAgaW4gYSB0YWJsZSBjYWxsZWQgYHN0YXRzX29ic2AsIHN0YXJ0aW5nIGZyb20gYGRhdGFjbGVhbmAuIEl0IHNob3VsZCBsb29rIGxpa2UgdGhpczoKCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1GQUxTRX0KKHN0YXRzX29icyA8LSBkYXRhY2xlYW4gJT4lCiAgICBncm91cF9ieShTdWJqZWN0LCBTT0FkdXIpICU+JQogICAgc3VtbWFyaXNlKAogICAgICAgIG1lYW4gPSBtZWFuKElSSSksCiAgICAgICAgc2QgPSBzZChJUkkpCiAgICApKQpgYGAKCi0gV2Ugd2FudCB0byBkbyB0aGUgc2FtZSBmb3IgdGhlIDMgc2ltdWxhdGVkIElSSS4gCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1GQUxTRX0KKHN0YXRzX3NpbSA8LSBJUklfc2ltICU+JQogICAgZ3JvdXBfYnkoU3ViamVjdCwgU09BZHVyKSAlPiUKICAgIHN1bW1hcmlzZSgKICAgICAgICBtZWFuID0gbWVhbihJUklfc2ltKSwKICAgICAgICBzZCA9IHNkKElSSV9zaW0pCiAgICApKQpgYGAKCiMgUGxvdHRpbmcKCi0gV2Ugd2FudCBub3cgdG8gcHJvZHVjZSBhIGdyYXBoIHNob3dpbmcgdGhlIGhpc3RvZ3JhbXMgb2YgdGhlIG9ic2VydmVkIGBJUklgIGNvbHVtbiB1c2luZyBgZ2dwbG90MmAuIAogICAgLSBDcmVhdGUgYSBgZ2dwbG90YCB1c2luZyB0aGUgYGRhdGFjbGVhbmAgZGF0YXNldAogICAgLSBTZXQgdGhlIGFlc3RoZXRpY3MgdG8gYHggPSBJUklgCiAgICAtIENyZWF0ZSB0aGUgaGlzdG9ncmFtcyB1c2luZyBgZ2VvbV9oaXN0b2dyYW0oKWB7LlJ9LCB3aXRoIGEgZmlsbCBjb2xvciBkZXBlbmRpbmcgb24gYFNPQWR1cmAKICAgIC0gQXJyYW5nZSB0aGUgcGxvdHMgb24gYSBncmlkIGRlcGVuZGluZyBvbiB0aGUgYFN1YmplY3RgIGNvbHVtbiB1c2luZyBgZmFjZXRfd3JhcCgpYHsuUn0KICAgIC0gQWRkIGEgdmVydGljYWwgbGlnbiBtYXJraW5nIHRoZSBhdmVyYWdlIHZhbHVlIGZvciBlYWNoIHN1YmplY3QgdXNpbmcgYGdlb21fdmxpbmUoKWB7LlJ9LiBUaGUgZGF0YSBmb3IgdGhlc2UgbGluZXMgYXJlIHN0b3JlZCBpbiB0aGUgYHN0YXRzX29ic2AgZGF0YXNldC4KICAgIC0gUGxheSB3aXRoIHRoZSB0aGVtZSBhbmQgb3RoZXIgZ2dwbG90IGNvbW1hbmRzIHRvIG1ha2UgdGhlIHBsb3QgbG9vayBsaWtlIHRoZSBvbmUgYmVsb3cKICAgICAgICAtIFRyeSBwbG90dGluZyBhIG5vcm1hbGl6ZWQgaGlzdG9ncmFtIGJ5IFtsb29raW5nIHVwIG9uIHRoZSBJbnRlcm5ldCBob3cgdG8gZG8gdGhpc10oaHR0cHM6Ly93d3cuZ29vZ2xlLmZyL3NlYXJjaD9zb3VyY2U9aHAmZWk9ZzBNTFhlR3dLTkxQZ3dlVjA0LUlCQSZxPWdncGxvdCtub3JtYWxpemVkK2hpc3RvZ3JhbSZvcT1nZ3Bsb3Qrbm9ybWFsaXplZCtoaXN0b2dyYW0pCgpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9RkFMU0V9CmRhdGFjbGVhbiAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBJUkksIGZpbGwgPSBmYWN0b3IoU09BZHVyKSkpICsKICAgIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gc3RhdChjb3VudCAvIHN1bShjb3VudCkpKSwgYmlucz0yMCkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSkrCiAgICBmYWNldF93cmFwKH4gcGFzdGUoIlN1YmplY3QiLCBTdWJqZWN0KSkgKwogICAgZ2VvbV92bGluZShkYXRhID0gc3RhdHNfb2JzLCBhZXMoeGludGVyY2VwdCA9IG1lYW4sIGNvbG9yPWZhY3RvcihTT0FkdXIpKSwgbHR5ID0gMiwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogICAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTIwMDAsMjAwMCkpKwogICAgbGFicyh0aXRsZSA9ICJPYnNlcnZhdGlvbnMiLAogICAgICAgICB4ID0gIklSSSBbbXNdIiwKICAgICAgICAgeSA9ICJPY2N1cmVuY2UiLCAKICAgICAgICAgZmlsbD0iU09BIFttc10iKSArCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIsIGNvbG91ciA9IE5BKSwKICAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksCiAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCB2anVzdCA9IDEsIGhqdXN0ID0gMSkpCmBgYAoKLSBMZXQncyBkbyB0aGUgc2FtZSBmb3IgdGhlIHNpbXVsYXRlZCBkYXRhc2V0LiBJdCBzaG91bGQgbG9vayBsaWtlIHRoaXM6CgpgYGB7ciBlY2hvPVRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9RkFMU0V9CklSSV9zaW0gJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gSVJJX3NpbSwgZmlsbCA9IGZhY3RvcihTT0FkdXIsIGxldmVscz1jKDE1LCA2NSwgMjUwKSkpKSArCiAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IHN0YXQoY291bnQgLyBzdW0oY291bnQpKSksIGJpbnMgPSAyMCkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSkgKwogICAgZmFjZXRfd3JhcCh+IHBhc3RlKCJTdWJqZWN0IiwgU3ViamVjdCkpICsKICAgIGdlb21fdmxpbmUoZGF0YSA9IHN0YXRzX3NpbSwgYWVzKHhpbnRlcmNlcHQgPSBtZWFuLCBjb2xvcj1mYWN0b3IoU09BZHVyKSksIGx0eSA9IDIsIHNob3cubGVnZW5kID0gRkFMU0UpICsKICAgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0yMDAwLDIwMDApKSsKICAgIGxhYnMoCiAgICAgICAgdGl0bGUgPSAiU2ltdWxhdGlvbnMiLAogICAgICAgIHggPSAiSVJJIFttc10iLAogICAgICAgIHkgPSAiT2NjdXJlbmNlIiwKICAgICAgICBmaWxsID0gIlNPQSBbbXNdIgogICAgKSArCiAgICB0aGVtZV9idygpICsKICAgIHRoZW1lKAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIsIGNvbG91ciA9IE5BKSwKICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIHZqdXN0ID0gMSwgaGp1c3QgPSAxKQogICAgKQpgYGA=