library(ggplot2)
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(tidyr)
library(magrittr)
Attaching package: ‘magrittr’
The following object is masked from ‘package:tidyr’:
extract
library(anytime)
library(stringr)
# Define function for generating latin square given the # of items and # of conditions
latin.square <- function(n.items, n.conditions){
# Define the height and width of the table in which the latin square will be stored
ls_table <- matrix(nrow = n.items, ncol = n.conditions)
# Make a vector to store the last cell's value
last_cell <- vector(length = 0)
# For each row associated w/ each item number, ...
for (row in 1:n.items){
# If "last" hasn't received a value yet, ...
if(length(last_cell) == 0){
# Then value the cells in the first row from 1 to n.conditions, and...
ls_table[row,] <- 1:n.conditions
# Assign the value of the last cell in the first row to "last".
last_cell <- ls_table[row, n.conditions]
} else{
# If "last" has a value, assign to row the sequence from last value of last row, ending w/ n.conditions
ls_table[row, 1:length(last_cell:n.conditions)] <- last_cell:n.conditions
# If x is anything other than 1, ...
if(last_cell != 1){
# Then starting w/ the cell after the cell in row whose value matches n.conditions,
# assign values to the remaining cells starting w/ 1 and going to the number before, ...
ls_table[row,(length(last_cell:n.conditions)+1):n.conditions] <- 1:(n.conditions - length(last_cell:n.conditions))
# and assign the value of the last cell in the first row to "last".
last_cell <- ls_table[row, n.conditions]
} else{
# Otherwise (if last_cell is 1), just assign the value of the last cell in the first row to "last" (without )
last_cell <- ls_table[row, n.conditions]
}
}
}
# Convert the matrix into a dataframe
ls_table <- as.data.frame(ls_table)
# Give the conditions letter labels (as column names)
colnames(ls_table) <- letters[1:n.conditions]
# Give the items numeric labels (as row names)
row.names(ls_table) <- 1:n.items
return(ls_table)
}
# Read in "results" file from IBEX (in csv format) for AJT controller
# Supply column names
read.csv("Results/results_2020-01-20(1).csv",
header = FALSE,
col.names = c("epoch_time",
"MD5",
"controller",
"IBEX_ID",
"element",
"type",
"item",
"question",
"rating",
"correct",
"rt")) -> ibex_import
# Replace %2C w/ commas and é w/ é
ibex_import[,"question"] %<>% str_replace("%2C", ",")
ibex_import[,"question"] %<>% str_replace("%0A", ";")
ibex_import[,"question"] %<>% str_replace("é", "é")
# Associate all sentences w/ IBEX_ID, remove duplicate rows
ibex_import %>%
subset(controller == "AcceptabilityJudgment" & question != "NULL",
select = c(IBEX_ID,
question)) %>%
distinct() %>%
arrange(IBEX_ID) -> ID_key
# Get ratings data
ibex_import %>%
subset(controller == "AcceptabilityJudgment" & question == "NULL",
select = c(epoch_time,
IBEX_ID,
type,
rating,
rt)) -> ratings_data_incl
# Add trial order information (trial order at this stage is still preserved in the order)
n <- length(unique(ratings_data_incl$epoch_time))
ratings_data_incl$trial <- rep(1:138, n)
# Get form data (intro and debrief)
ibex_import %>%
subset(controller == "Form",
select = c(epoch_time,
question,
rating)) %>%
droplevels -> participant_data
# Change column names
colnames(participant_data) <- c("epoch_time", "question", "response")
# Change participant data to long format (one row per submission/subject)
participant_data %>%
group_by(epoch_time) %>%
summarize(prolific_id = str_sub(response[question == "prolificid"],
-4, -1),
age = response[question == "age"],
native_eng = response[question == "languageEnglish"],
other_langs = response[question == "otherLanguages"],
ling_major = response[question == "linguistics"],
consent = response[question == "consent"],
what_about = response[question == "debrief1Response"],
strategy = response[question == "debrief2Response"],
patterns_noticed = response[question == "debrief3Response"],
cp_vs_vt = response[question == "debrief4Response"],
cp_vs_ee = response[question == "debrief5Response"],
vt_vs_ee = response[question == "debrief6Response"],
difficulty = response[question == "difficulty"],
form_rts = sum(as.numeric(as.character(response[question == "_REACTION_TIME_"]))),
seps = 500*(138-1)) -> participant_data
# Make epoch_time numeric (agnostic of which column it's in)
ratings_data_incl[,which(colnames(ratings_data_incl) == "epoch_time")] %>%
as.character %>%
as.numeric -> ratings_data_incl[,which(colnames(ratings_data_incl) == "epoch_time")]
# Import items, fillers, practice for both experiments
read.csv("Items/CSVs/exp6_items.csv") -> items
items$frequency <- NULL
items$context <- NULL
items$sentence_w_gaps <- NULL
items$comments <- NULL
read.csv("Items/CSVs/exp6_fillers.csv") -> fillers
read.csv("Items/CSVs/exp6_practice.csv") -> practice
read.csv("Items/CSVs/exp6_burn-in_items.csv") -> burn_in_items
burn_in_items$frequency <- NULL
burn_in_items$context <- NULL
burn_in_items$sentence_w_gaps <- NULL
read.csv("Items/CSVs/exp6_burn-in_fillers.csv") -> burn_in_fillers
burn_in_fillers$mean.z.rating. <- NULL
read.csv("Items/CSVs/exp6_attention.csv") -> attention_checks
# Associate conditions w/ their IBEX ID
merge(items,
ID_key,
by.x = "sentence",
by.y = "question") -> items
merge(fillers,
ID_key,
by.x = "sentence",
by.y = "question") -> fillers
merge(practice,
ID_key,
by.x = "sentence",
by.y = "question") -> practice
merge(burn_in_items,
ID_key,
by.x = "sentence",
by.y = "question") -> burn_in_items
merge(burn_in_fillers,
ID_key,
by.x = "sentence",
by.y = "question") -> burn_in_fillers
merge(attention_checks,
ID_key,
by.x = "sentence",
by.y = "question") -> attention_checks
# Generate latin square for experiment & convert to long format
lsq <- latin.square(n.items = 36, n.conditions = 6)
lsq <- cbind(item = as.numeric(row.names(lsq)), lsq)
lsq %>%
gather(condition, list, a:f, factor_key = TRUE) -> lsq
lsq %>%
arrange(item) -> lsq
# Add list number that conditions appeared in to exp items
items %>%
merge(.,
lsq,
by = c("item", "condition")) -> items
# Create master list of items, fillers, and practice
## Make copies of dfs, and add/remove columns to make columns consistent
items -> items_m
items_m$requested_rating <- NA
fillers -> fillers_m
fillers_m$s_type <- NULL
fillers_m$gramm_s_type <- NULL
fillers_m$only <- NULL
fillers_m$original_source <- NULL
fillers_m$last_used <- NULL
fillers_m$X <- NULL
fillers_m$requested_rating <- NA
fillers_m$condition <- NA
fillers_m$length <- NA
fillers_m$structure <- NA
fillers_m$env <- NA
fillers_m$list <- NA
fillers_m$item <- NA
fillers_m$verb <- NA
burn_in_items -> burn_in_items_m
burn_in_items_m$requested_rating <- NA
burn_in_items_m$list <- NA
burn_in_fillers -> burn_in_fillers_m
burn_in_fillers_m$orig_ID <- NULL
burn_in_fillers_m$orig_sentence <- NULL
burn_in_fillers_m$requested_rating <- NA
burn_in_fillers_m$condition <- NA
burn_in_fillers_m$length <- NA
burn_in_fillers_m$structure <- NA
burn_in_fillers_m$env <- NA
burn_in_fillers_m$list <- NA
burn_in_fillers_m$item <- NA
burn_in_fillers_m$verb <- NA
practice -> practice_m
colnames(practice_m)[3] <- "gramm"
practice_m$requested_rating <- NA
practice_m$condition <- NA
practice_m$length <- NA
practice_m$structure <- NA
practice_m$env <- NA
practice_m$list <- NA
practice_m$item <- NA
practice_m$verb <- NA
attention_checks -> attention_checks_m
attention_checks_m$in_IBEX <- NULL
attention_checks_m$condition <- NA
attention_checks_m$length <- NA
attention_checks_m$structure <- NA
attention_checks_m$env <- NA
attention_checks_m$list <- NA
attention_checks_m$item <- NA
attention_checks_m$gramm <- NA
attention_checks_m$verb <- NA
# Combine items, fillers, practice items, burn-in items, burn-in fillers, and attention checks
master <- rbind(items_m, fillers_m, burn_in_items_m, burn_in_fillers_m, practice_m, attention_checks_m)
# Match master to ratings data
ratings_data_incl %>%
merge(.,
master,
by = "IBEX_ID") -> ratings_data_incl
# Associate epoch_time w/ subject number and native speaker status
ratings_data_incl %>%
merge(.,
participant_data[,1:2],
by = "epoch_time") -> ratings_data_incl
# Save ratings data as csv
write.csv(ratings_data_incl, file = "exp6_ratings.csv")
# Find the list each subject was given
ratings_data_incl %>%
subset(type == "experimental",
select = c(prolific_id,
list)) %>%
droplevels %>%
group_by(prolific_id) %>%
summarize(one_list = length(unique(list)) == 1,
list = if(one_list == TRUE){
min(list)
} else {
NA
}) -> list_key
# Join list_key w/ participant_data
participant_data %>%
merge(.,
list_key,
by = "prolific_id") -> participant_data
# Add sentence RT sums to participant data
ratings_data_incl %>%
group_by(prolific_id) %>%
summarize(stc_rts = sum(rt)) -> participant_rts
# Add RTs to participant_data & sum it up
merge(participant_data,
participant_rts,
by = "prolific_id") -> participant_data
apply(participant_data, 1,
function(x){
sum(as.numeric(as.character(x["form_rts"])),
as.numeric(as.character(x["seps"])),
as.numeric(as.character(x["stc_rts"]))) -> time
return(time)
}) -> participant_data$tot_time_ms
participant_data$tot_time_s <- participant_data$tot_time_ms/1000
participant_data$tot_time_m <- participant_data$tot_time_s/60
# Remove excluded participants from participant_data (SEE EXCLUDED PARTICIPANTS IN LIST BELOW)
participant_data %>%
subset(prolific_id %in% excluded) -> participant_data_rm
participant_data %>%
subset(!(prolific_id %in% excluded)) -> participant_data
# Determine how balanced the lists are. For this experiment, there are 6 lists.
participant_data %>%
group_by(list) %>%
summarize(counter = first(list) - 1,
n = n()) -> list_dist
Exclusion criteria
A participant will be excluded if any of the following conditions are met: 1. They fail at least one of the six attention checks. 2. The proportion of response times lower than one second is greater than or equal to 0.10. 3. Their mean ratings for fillers expected to be ungrammatical and fillers expected to be grammatical are either inverted or are too close. Too close is defined on normalized ratings, where a difference that is more than two standard deviations below the mean difference is too close.
Attention checks
ratings_data_incl %>%
subset(type == "attention") %>%
group_by(epoch_time,
prolific_id) %>%
summarize(first = rating[ID == "a01"],
second = rating[ID == "a02"],
third = rating[ID == "a03"],
fourth = rating[ID == "a04"],
fifth = rating[ID == "a05"],
sixth = rating[ID == "a06"])
Response times
# Generate RT density plots for each participant
for (n in 1:length(unique(ratings_data_incl$prolific_id))) {
participant <- unique(ratings_data_incl$prolific_id)[n]
ratings_data_incl %>%
subset(prolific_id == participant) %>%
group_by(IBEX_ID) %>%
summarize(rt_s = rt/1000) %>%
ggplot(aes(x = rt_s)) +
geom_density() +
geom_vline(aes(xintercept = mean(rt_s))) +
xlim(xmin = 0,
xmax = 10) +
labs(title = paste("Prolific ID", participant, "response times"),
x = "Response time (seconds)",
y = "Density") -> plot
print(plot)
}
# Get RT stats
ratings_data_incl %>%
group_by(epoch_time,
prolific_id) %>%
summarize(mean_rt = mean(rt),
p_below_1000 = length(rt[rt < 1000])/length(rt),
min_rt = min(rt),
max_rt = max(rt),
median_rt = median(rt),
n = n(),
sd = sd(rt),
se = sd/sqrt(n)) -> rt_stats
print(rt_stats)
# Print participants for whom 25% or more of their RTs are less than a second.
rt_stats %>%
subset(p_below_1000 >= 0.10,
select = c(epoch_time, prolific_id))
Filler ratings
# Select filler & experimental sentences and transform ratings to z-scores (grouping by participant)
ratings_data_incl %>%
subset(type == "experimental" | type == "filler") %>%
group_by(prolific_id) %>%
mutate(z_rating = scale(as.numeric(as.character(rating)))) %>%
ungroup() %>%
# Select only the fillers
subset(type == "filler") %>%
# Group by participant and grammaticality & summarize ratings
group_by(prolific_id,
gramm) %>%
summarize(mean_z_rating = mean(z_rating)) -> filler_z_means
print(filler_z_means)
# Get difference in mean z_ratings per participant and join w/ filler_z_means
filler_z_means %>%
group_by(prolific_id) %>%
summarize(diff = mean_z_rating[gramm == "1"] - mean_z_rating[gramm == "0"]) %>%
merge(filler_z_means, .) -> filler_z_means
# Show a list of participants whose difference is over two SDs away from the mean
#filler_z_means %>%
# subset(diff < mean_diff-(2*sd_diff))
filler_z_means %>%
ggplot(aes(x = reorder(prolific_id, diff),
y = mean_z_rating,
color = as.factor(gramm))) +
geom_point() +
labs(x = "Prolific ID (first 4)",
y = "Mean z-score-transformed rating") +
scale_color_discrete("Grammaticality") +
theme(axis.text.x = element_text(angle = 45, vjust = 0.95, hjust = 0.95)) -> filler_ratings_plot
print(filler_ratings_plot)
Make list of excluded participants
excluded <- NULL
excluded <- c(excluded, "134d") # Failed one attention check
excluded <- c(excluded, "d6ad") # Mean gramm and ungramm filler ratings too close; most RTs below 2.5s
excluded <- c(excluded, "d797") # Mean gramm and ungramm filler ratings too close
LS0tCnRpdGxlOiAiUkMgc3ViZXh0cmFjdGlvbiBpbiBFbmdsaXNoOiBTZXQtdXAgbm90ZWJvb2sgZm9yIEV4cGVyaW1lbnQgNiAiCmF1dGhvcjogIkpha2UgVy4gVmluY2VudCAoJiMxMDY7JiMxMTk7JiMxMTg7JiMxMDU7JiMxMTA7JiM5OTsmIzEwMTtuJiM2NDsmIzExNztjJiMxMTU7Yy5lJiMxMDA7dSkiCm91dHB1dDoKICBodG1sX25vdGVib29rOiAKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogZmxhdGx5CiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNzczogc3R5bGUuY3NzCiAgICB0b2M6IHRydWUKICBwZGZfZG9jdW1lbnQ6IAogICAga2VlcF90ZXg6IHllcwpiaWJsaW9ncmFwaHk6IH4vRG9jdW1lbnRzL2xpYnJhcnkuYmliCi0tLQpgYGB7ciBzZXQtdXB9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShhbnl0aW1lKQpsaWJyYXJ5KHN0cmluZ3IpCgojIERlZmluZSBmdW5jdGlvbiBmb3IgZ2VuZXJhdGluZyBsYXRpbiBzcXVhcmUgZ2l2ZW4gdGhlICMgb2YgaXRlbXMgYW5kICMgb2YgY29uZGl0aW9ucwpsYXRpbi5zcXVhcmUgPC0gZnVuY3Rpb24obi5pdGVtcywgbi5jb25kaXRpb25zKXsKICAjIERlZmluZSB0aGUgaGVpZ2h0IGFuZCB3aWR0aCBvZiB0aGUgdGFibGUgaW4gd2hpY2ggdGhlIGxhdGluIHNxdWFyZSB3aWxsIGJlIHN0b3JlZAogIGxzX3RhYmxlIDwtIG1hdHJpeChucm93ID0gbi5pdGVtcywgbmNvbCA9IG4uY29uZGl0aW9ucykKICAjIE1ha2UgYSB2ZWN0b3IgdG8gc3RvcmUgdGhlIGxhc3QgY2VsbCdzIHZhbHVlCiAgbGFzdF9jZWxsIDwtIHZlY3RvcihsZW5ndGggPSAwKQogICMgRm9yIGVhY2ggcm93IGFzc29jaWF0ZWQgdy8gZWFjaCBpdGVtIG51bWJlciwgLi4uCiAgZm9yIChyb3cgaW4gMTpuLml0ZW1zKXsKICAgICMgSWYgImxhc3QiIGhhc24ndCByZWNlaXZlZCBhIHZhbHVlIHlldCwgLi4uCiAgICBpZihsZW5ndGgobGFzdF9jZWxsKSA9PSAwKXsKICAgICAgIyBUaGVuIHZhbHVlIHRoZSBjZWxscyBpbiB0aGUgZmlyc3Qgcm93IGZyb20gMSB0byBuLmNvbmRpdGlvbnMsIGFuZC4uLgogICAgICBsc190YWJsZVtyb3csXSA8LSAxOm4uY29uZGl0aW9ucwogICAgICAjIEFzc2lnbiB0aGUgdmFsdWUgb2YgdGhlIGxhc3QgY2VsbCBpbiB0aGUgZmlyc3Qgcm93IHRvICJsYXN0Ii4KICAgICAgbGFzdF9jZWxsIDwtIGxzX3RhYmxlW3Jvdywgbi5jb25kaXRpb25zXQogICAgfSBlbHNlewogICAgICAjIElmICJsYXN0IiBoYXMgYSB2YWx1ZSwgYXNzaWduIHRvIHJvdyB0aGUgc2VxdWVuY2UgZnJvbSBsYXN0IHZhbHVlIG9mIGxhc3Qgcm93LCBlbmRpbmcgdy8gbi5jb25kaXRpb25zCiAgICAgIGxzX3RhYmxlW3JvdywgMTpsZW5ndGgobGFzdF9jZWxsOm4uY29uZGl0aW9ucyldIDwtIGxhc3RfY2VsbDpuLmNvbmRpdGlvbnMKICAgICAgIyBJZiB4IGlzIGFueXRoaW5nIG90aGVyIHRoYW4gMSwgLi4uCiAgICAgIGlmKGxhc3RfY2VsbCAhPSAxKXsKICAgICAgICAjIFRoZW4gc3RhcnRpbmcgdy8gdGhlIGNlbGwgYWZ0ZXIgdGhlIGNlbGwgaW4gcm93IHdob3NlIHZhbHVlIG1hdGNoZXMgbi5jb25kaXRpb25zLAogICAgICAgICMgYXNzaWduIHZhbHVlcyB0byB0aGUgcmVtYWluaW5nIGNlbGxzIHN0YXJ0aW5nIHcvIDEgYW5kIGdvaW5nIHRvIHRoZSBudW1iZXIgYmVmb3JlLCAuLi4KICAgICAgICBsc190YWJsZVtyb3csKGxlbmd0aChsYXN0X2NlbGw6bi5jb25kaXRpb25zKSsxKTpuLmNvbmRpdGlvbnNdIDwtIDE6KG4uY29uZGl0aW9ucyAtIGxlbmd0aChsYXN0X2NlbGw6bi5jb25kaXRpb25zKSkKICAgICAgICAjIGFuZCBhc3NpZ24gdGhlIHZhbHVlIG9mIHRoZSBsYXN0IGNlbGwgaW4gdGhlIGZpcnN0IHJvdyB0byAibGFzdCIuCiAgICAgICAgbGFzdF9jZWxsIDwtIGxzX3RhYmxlW3Jvdywgbi5jb25kaXRpb25zXQogICAgICB9IGVsc2V7CiAgICAgICAgIyBPdGhlcndpc2UgKGlmIGxhc3RfY2VsbCBpcyAxKSwganVzdCBhc3NpZ24gdGhlIHZhbHVlIG9mIHRoZSBsYXN0IGNlbGwgaW4gdGhlIGZpcnN0IHJvdyB0byAibGFzdCIgKHdpdGhvdXQgKQogICAgICAgIGxhc3RfY2VsbCA8LSBsc190YWJsZVtyb3csIG4uY29uZGl0aW9uc10KICAgICAgfQogICAgfQogIH0KICAjIENvbnZlcnQgdGhlIG1hdHJpeCBpbnRvIGEgZGF0YWZyYW1lCiAgbHNfdGFibGUgPC0gYXMuZGF0YS5mcmFtZShsc190YWJsZSkKICAjIEdpdmUgdGhlIGNvbmRpdGlvbnMgbGV0dGVyIGxhYmVscyAoYXMgY29sdW1uIG5hbWVzKQogIGNvbG5hbWVzKGxzX3RhYmxlKSA8LSBsZXR0ZXJzWzE6bi5jb25kaXRpb25zXQogICMgR2l2ZSB0aGUgaXRlbXMgbnVtZXJpYyBsYWJlbHMgKGFzIHJvdyBuYW1lcykKICByb3cubmFtZXMobHNfdGFibGUpIDwtIDE6bi5pdGVtcwogIHJldHVybihsc190YWJsZSkKfQpgYGAKCmBgYHtyIGltcG9ydF9kYXRhfQojIFJlYWQgaW4gInJlc3VsdHMiIGZpbGUgZnJvbSBJQkVYIChpbiBjc3YgZm9ybWF0KSBmb3IgQUpUIGNvbnRyb2xsZXIKIyBTdXBwbHkgY29sdW1uIG5hbWVzCnJlYWQuY3N2KCJSZXN1bHRzL3Jlc3VsdHNfMjAyMC0wMS0yMCgxKS5jc3YiLAogICAgICAgICBoZWFkZXIgPSBGQUxTRSwKICAgICAgICAgY29sLm5hbWVzID0gYygiZXBvY2hfdGltZSIsCiAgICAgICAgICAgICAgICAgICAgICAgIk1ENSIsCiAgICAgICAgICAgICAgICAgICAgICAgImNvbnRyb2xsZXIiLAogICAgICAgICAgICAgICAgICAgICAgICJJQkVYX0lEIiwKICAgICAgICAgICAgICAgICAgICAgICAiZWxlbWVudCIsCiAgICAgICAgICAgICAgICAgICAgICAgInR5cGUiLAogICAgICAgICAgICAgICAgICAgICAgICJpdGVtIiwKICAgICAgICAgICAgICAgICAgICAgICAicXVlc3Rpb24iLAogICAgICAgICAgICAgICAgICAgICAgICJyYXRpbmciLAogICAgICAgICAgICAgICAgICAgICAgICJjb3JyZWN0IiwKICAgICAgICAgICAgICAgICAgICAgICAicnQiKSkgLT4gaWJleF9pbXBvcnQKCiMgUmVwbGFjZSAlMkMgdy8gY29tbWFzIGFuZCDDg8KpIHcvIMOpCmliZXhfaW1wb3J0WywicXVlc3Rpb24iXSAlPD4lIHN0cl9yZXBsYWNlKCIlMkMiLCAiLCIpCmliZXhfaW1wb3J0WywicXVlc3Rpb24iXSAlPD4lIHN0cl9yZXBsYWNlKCIlMEEiLCAiOyIpCmliZXhfaW1wb3J0WywicXVlc3Rpb24iXSAlPD4lIHN0cl9yZXBsYWNlKCLDg8KpIiwgIsOpIikKCiMgQXNzb2NpYXRlIGFsbCBzZW50ZW5jZXMgdy8gSUJFWF9JRCwgcmVtb3ZlIGR1cGxpY2F0ZSByb3dzCmliZXhfaW1wb3J0ICU+JQogIHN1YnNldChjb250cm9sbGVyID09ICJBY2NlcHRhYmlsaXR5SnVkZ21lbnQiICYgcXVlc3Rpb24gIT0gIk5VTEwiLAogICAgICAgICBzZWxlY3QgPSBjKElCRVhfSUQsCiAgICAgICAgICAgICAgICAgICAgcXVlc3Rpb24pKSAlPiUKICBkaXN0aW5jdCgpICU+JQogIGFycmFuZ2UoSUJFWF9JRCkgLT4gSURfa2V5CgojIEdldCByYXRpbmdzIGRhdGEKaWJleF9pbXBvcnQgJT4lCiAgc3Vic2V0KGNvbnRyb2xsZXIgPT0gIkFjY2VwdGFiaWxpdHlKdWRnbWVudCIgJiBxdWVzdGlvbiA9PSAiTlVMTCIsCiAgICAgICAgIHNlbGVjdCA9IGMoZXBvY2hfdGltZSwKICAgICAgICAgICAgICAgICAgICBJQkVYX0lELAogICAgICAgICAgICAgICAgICAgIHR5cGUsCiAgICAgICAgICAgICAgICAgICAgcmF0aW5nLAogICAgICAgICAgICAgICAgICAgIHJ0KSkgLT4gcmF0aW5nc19kYXRhX2luY2wKCiMgQWRkIHRyaWFsIG9yZGVyIGluZm9ybWF0aW9uICh0cmlhbCBvcmRlciBhdCB0aGlzIHN0YWdlIGlzIHN0aWxsIHByZXNlcnZlZCBpbiB0aGUgb3JkZXIpCm4gPC0gbGVuZ3RoKHVuaXF1ZShyYXRpbmdzX2RhdGFfaW5jbCRlcG9jaF90aW1lKSkKcmF0aW5nc19kYXRhX2luY2wkdHJpYWwgPC0gcmVwKDE6MTM4LCBuKQoKIyBHZXQgZm9ybSBkYXRhIChpbnRybyBhbmQgZGVicmllZikKaWJleF9pbXBvcnQgJT4lCiAgc3Vic2V0KGNvbnRyb2xsZXIgPT0gIkZvcm0iLAogICAgICAgICBzZWxlY3QgPSBjKGVwb2NoX3RpbWUsCiAgICAgICAgICAgICAgICAgICAgcXVlc3Rpb24sCiAgICAgICAgICAgICAgICAgICAgcmF0aW5nKSkgJT4lCiAgZHJvcGxldmVscyAtPiBwYXJ0aWNpcGFudF9kYXRhCgojIENoYW5nZSBjb2x1bW4gbmFtZXMKY29sbmFtZXMocGFydGljaXBhbnRfZGF0YSkgPC0gYygiZXBvY2hfdGltZSIsICJxdWVzdGlvbiIsICJyZXNwb25zZSIpCgojIENoYW5nZSBwYXJ0aWNpcGFudCBkYXRhIHRvIGxvbmcgZm9ybWF0IChvbmUgcm93IHBlciBzdWJtaXNzaW9uL3N1YmplY3QpCnBhcnRpY2lwYW50X2RhdGEgJT4lCiAgZ3JvdXBfYnkoZXBvY2hfdGltZSkgJT4lCiAgc3VtbWFyaXplKHByb2xpZmljX2lkID0gc3RyX3N1YihyZXNwb25zZVtxdWVzdGlvbiA9PSAicHJvbGlmaWNpZCJdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLTQsIC0xKSwKICAgICAgICAgICAgYWdlID0gcmVzcG9uc2VbcXVlc3Rpb24gPT0gImFnZSJdLAogICAgICAgICAgICBuYXRpdmVfZW5nID0gcmVzcG9uc2VbcXVlc3Rpb24gPT0gImxhbmd1YWdlRW5nbGlzaCJdLAogICAgICAgICAgICBvdGhlcl9sYW5ncyA9IHJlc3BvbnNlW3F1ZXN0aW9uID09ICJvdGhlckxhbmd1YWdlcyJdLAogICAgICAgICAgICBsaW5nX21ham9yID0gcmVzcG9uc2VbcXVlc3Rpb24gPT0gImxpbmd1aXN0aWNzIl0sCiAgICAgICAgICAgIGNvbnNlbnQgPSByZXNwb25zZVtxdWVzdGlvbiA9PSAiY29uc2VudCJdLAogICAgICAgICAgICB3aGF0X2Fib3V0ID0gcmVzcG9uc2VbcXVlc3Rpb24gPT0gImRlYnJpZWYxUmVzcG9uc2UiXSwKICAgICAgICAgICAgc3RyYXRlZ3kgPSByZXNwb25zZVtxdWVzdGlvbiA9PSAiZGVicmllZjJSZXNwb25zZSJdLAogICAgICAgICAgICBwYXR0ZXJuc19ub3RpY2VkID0gcmVzcG9uc2VbcXVlc3Rpb24gPT0gImRlYnJpZWYzUmVzcG9uc2UiXSwKICAgICAgICAgICAgY3BfdnNfdnQgPSByZXNwb25zZVtxdWVzdGlvbiA9PSAiZGVicmllZjRSZXNwb25zZSJdLAogICAgICAgICAgICBjcF92c19lZSA9IHJlc3BvbnNlW3F1ZXN0aW9uID09ICJkZWJyaWVmNVJlc3BvbnNlIl0sCiAgICAgICAgICAgIHZ0X3ZzX2VlID0gcmVzcG9uc2VbcXVlc3Rpb24gPT0gImRlYnJpZWY2UmVzcG9uc2UiXSwKICAgICAgICAgICAgZGlmZmljdWx0eSA9IHJlc3BvbnNlW3F1ZXN0aW9uID09ICJkaWZmaWN1bHR5Il0sCiAgICAgICAgICAgIGZvcm1fcnRzID0gc3VtKGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHJlc3BvbnNlW3F1ZXN0aW9uID09ICJfUkVBQ1RJT05fVElNRV8iXSkpKSwKICAgICAgICAgICAgc2VwcyA9IDUwMCooMTM4LTEpKSAtPiBwYXJ0aWNpcGFudF9kYXRhCgojIE1ha2UgZXBvY2hfdGltZSBudW1lcmljIChhZ25vc3RpYyBvZiB3aGljaCBjb2x1bW4gaXQncyBpbikKcmF0aW5nc19kYXRhX2luY2xbLHdoaWNoKGNvbG5hbWVzKHJhdGluZ3NfZGF0YV9pbmNsKSA9PSAiZXBvY2hfdGltZSIpXSAlPiUKICBhcy5jaGFyYWN0ZXIgJT4lCiAgYXMubnVtZXJpYyAtPiByYXRpbmdzX2RhdGFfaW5jbFssd2hpY2goY29sbmFtZXMocmF0aW5nc19kYXRhX2luY2wpID09ICJlcG9jaF90aW1lIildCgojIEltcG9ydCBpdGVtcywgZmlsbGVycywgcHJhY3RpY2UgZm9yIGJvdGggZXhwZXJpbWVudHMKcmVhZC5jc3YoIkl0ZW1zL0NTVnMvZXhwNl9pdGVtcy5jc3YiKSAtPiBpdGVtcwogIGl0ZW1zJGZyZXF1ZW5jeSA8LSBOVUxMCiAgaXRlbXMkY29udGV4dCA8LSBOVUxMCiAgaXRlbXMkc2VudGVuY2Vfd19nYXBzIDwtIE5VTEwKICBpdGVtcyRjb21tZW50cyA8LSBOVUxMCnJlYWQuY3N2KCJJdGVtcy9DU1ZzL2V4cDZfZmlsbGVycy5jc3YiKSAtPiBmaWxsZXJzCnJlYWQuY3N2KCJJdGVtcy9DU1ZzL2V4cDZfcHJhY3RpY2UuY3N2IikgLT4gcHJhY3RpY2UKcmVhZC5jc3YoIkl0ZW1zL0NTVnMvZXhwNl9idXJuLWluX2l0ZW1zLmNzdiIpIC0+IGJ1cm5faW5faXRlbXMKICBidXJuX2luX2l0ZW1zJGZyZXF1ZW5jeSA8LSBOVUxMCiAgYnVybl9pbl9pdGVtcyRjb250ZXh0IDwtIE5VTEwKICBidXJuX2luX2l0ZW1zJHNlbnRlbmNlX3dfZ2FwcyA8LSBOVUxMCnJlYWQuY3N2KCJJdGVtcy9DU1ZzL2V4cDZfYnVybi1pbl9maWxsZXJzLmNzdiIpIC0+IGJ1cm5faW5fZmlsbGVycwogIGJ1cm5faW5fZmlsbGVycyRtZWFuLnoucmF0aW5nLiA8LSBOVUxMCnJlYWQuY3N2KCJJdGVtcy9DU1ZzL2V4cDZfYXR0ZW50aW9uLmNzdiIpIC0+IGF0dGVudGlvbl9jaGVja3MKICAKIyBBc3NvY2lhdGUgY29uZGl0aW9ucyB3LyB0aGVpciBJQkVYIElECm1lcmdlKGl0ZW1zLAogICAgICBJRF9rZXksCiAgICAgIGJ5LnggPSAic2VudGVuY2UiLAogICAgICBieS55ID0gInF1ZXN0aW9uIikgLT4gaXRlbXMKCm1lcmdlKGZpbGxlcnMsCiAgICAgIElEX2tleSwKICAgICAgYnkueCA9ICJzZW50ZW5jZSIsCiAgICAgIGJ5LnkgPSAicXVlc3Rpb24iKSAtPiBmaWxsZXJzCgptZXJnZShwcmFjdGljZSwKICAgICAgSURfa2V5LAogICAgICBieS54ID0gInNlbnRlbmNlIiwKICAgICAgYnkueSA9ICJxdWVzdGlvbiIpIC0+IHByYWN0aWNlCgptZXJnZShidXJuX2luX2l0ZW1zLAogICAgICBJRF9rZXksCiAgICAgIGJ5LnggPSAic2VudGVuY2UiLAogICAgICBieS55ID0gInF1ZXN0aW9uIikgLT4gYnVybl9pbl9pdGVtcwoKbWVyZ2UoYnVybl9pbl9maWxsZXJzLAogICAgICBJRF9rZXksCiAgICAgIGJ5LnggPSAic2VudGVuY2UiLAogICAgICBieS55ID0gInF1ZXN0aW9uIikgLT4gYnVybl9pbl9maWxsZXJzCgptZXJnZShhdHRlbnRpb25fY2hlY2tzLAogICAgICBJRF9rZXksCiAgICAgIGJ5LnggPSAic2VudGVuY2UiLAogICAgICBieS55ID0gInF1ZXN0aW9uIikgLT4gYXR0ZW50aW9uX2NoZWNrcwoKIyBHZW5lcmF0ZSBsYXRpbiBzcXVhcmUgZm9yIGV4cGVyaW1lbnQgJiBjb252ZXJ0IHRvIGxvbmcgZm9ybWF0CmxzcSA8LSBsYXRpbi5zcXVhcmUobi5pdGVtcyA9IDM2LCBuLmNvbmRpdGlvbnMgPSA2KQpsc3EgPC0gY2JpbmQoaXRlbSA9IGFzLm51bWVyaWMocm93Lm5hbWVzKGxzcSkpLCBsc3EpCmxzcSAlPiUKICBnYXRoZXIoY29uZGl0aW9uLCBsaXN0LCBhOmYsIGZhY3Rvcl9rZXkgPSBUUlVFKSAtPiBsc3EKbHNxICU+JQogIGFycmFuZ2UoaXRlbSkgLT4gbHNxCgojIEFkZCBsaXN0IG51bWJlciB0aGF0IGNvbmRpdGlvbnMgYXBwZWFyZWQgaW4gdG8gZXhwIGl0ZW1zCml0ZW1zICU+JQogIG1lcmdlKC4sCiAgICAgICAgbHNxLAogICAgICAgIGJ5ID0gYygiaXRlbSIsICJjb25kaXRpb24iKSkgLT4gaXRlbXMKCiMgQ3JlYXRlIG1hc3RlciBsaXN0IG9mIGl0ZW1zLCBmaWxsZXJzLCBhbmQgcHJhY3RpY2UKIyMgTWFrZSBjb3BpZXMgb2YgZGZzLCBhbmQgYWRkL3JlbW92ZSBjb2x1bW5zIHRvIG1ha2UgY29sdW1ucyBjb25zaXN0ZW50Cml0ZW1zIC0+IGl0ZW1zX20KICBpdGVtc19tJHJlcXVlc3RlZF9yYXRpbmcgPC0gTkEKZmlsbGVycyAtPiBmaWxsZXJzX20KICBmaWxsZXJzX20kc190eXBlIDwtIE5VTEwKICBmaWxsZXJzX20kZ3JhbW1fc190eXBlIDwtIE5VTEwKICBmaWxsZXJzX20kb25seSA8LSBOVUxMCiAgZmlsbGVyc19tJG9yaWdpbmFsX3NvdXJjZSA8LSBOVUxMCiAgZmlsbGVyc19tJGxhc3RfdXNlZCA8LSBOVUxMCiAgZmlsbGVyc19tJFggPC0gTlVMTAogIGZpbGxlcnNfbSRyZXF1ZXN0ZWRfcmF0aW5nIDwtIE5BCiAgZmlsbGVyc19tJGNvbmRpdGlvbiA8LSBOQQogIGZpbGxlcnNfbSRsZW5ndGggPC0gTkEKICBmaWxsZXJzX20kc3RydWN0dXJlIDwtIE5BCiAgZmlsbGVyc19tJGVudiA8LSBOQQogIGZpbGxlcnNfbSRsaXN0IDwtIE5BCiAgZmlsbGVyc19tJGl0ZW0gPC0gTkEKICBmaWxsZXJzX20kdmVyYiA8LSBOQQpidXJuX2luX2l0ZW1zIC0+IGJ1cm5faW5faXRlbXNfbQogIGJ1cm5faW5faXRlbXNfbSRyZXF1ZXN0ZWRfcmF0aW5nIDwtIE5BCiAgYnVybl9pbl9pdGVtc19tJGxpc3QgPC0gTkEKYnVybl9pbl9maWxsZXJzIC0+IGJ1cm5faW5fZmlsbGVyc19tCiAgYnVybl9pbl9maWxsZXJzX20kb3JpZ19JRCA8LSBOVUxMCiAgYnVybl9pbl9maWxsZXJzX20kb3JpZ19zZW50ZW5jZSA8LSBOVUxMCiAgYnVybl9pbl9maWxsZXJzX20kcmVxdWVzdGVkX3JhdGluZyA8LSBOQQogIGJ1cm5faW5fZmlsbGVyc19tJGNvbmRpdGlvbiA8LSBOQQogIGJ1cm5faW5fZmlsbGVyc19tJGxlbmd0aCA8LSBOQQogIGJ1cm5faW5fZmlsbGVyc19tJHN0cnVjdHVyZSA8LSBOQQogIGJ1cm5faW5fZmlsbGVyc19tJGVudiA8LSBOQQogIGJ1cm5faW5fZmlsbGVyc19tJGxpc3QgPC0gTkEKICBidXJuX2luX2ZpbGxlcnNfbSRpdGVtIDwtIE5BCiAgYnVybl9pbl9maWxsZXJzX20kdmVyYiA8LSBOQQpwcmFjdGljZSAtPiBwcmFjdGljZV9tCiAgY29sbmFtZXMocHJhY3RpY2VfbSlbM10gPC0gImdyYW1tIgogIHByYWN0aWNlX20kcmVxdWVzdGVkX3JhdGluZyA8LSBOQQogIHByYWN0aWNlX20kY29uZGl0aW9uIDwtIE5BCiAgcHJhY3RpY2VfbSRsZW5ndGggPC0gTkEKICBwcmFjdGljZV9tJHN0cnVjdHVyZSA8LSBOQQogIHByYWN0aWNlX20kZW52IDwtIE5BCiAgcHJhY3RpY2VfbSRsaXN0IDwtIE5BCiAgcHJhY3RpY2VfbSRpdGVtIDwtIE5BCiAgcHJhY3RpY2VfbSR2ZXJiIDwtIE5BCmF0dGVudGlvbl9jaGVja3MgLT4gYXR0ZW50aW9uX2NoZWNrc19tCiAgYXR0ZW50aW9uX2NoZWNrc19tJGluX0lCRVggPC0gTlVMTAogIGF0dGVudGlvbl9jaGVja3NfbSRjb25kaXRpb24gPC0gTkEKICBhdHRlbnRpb25fY2hlY2tzX20kbGVuZ3RoIDwtIE5BCiAgYXR0ZW50aW9uX2NoZWNrc19tJHN0cnVjdHVyZSA8LSBOQQogIGF0dGVudGlvbl9jaGVja3NfbSRlbnYgPC0gTkEKICBhdHRlbnRpb25fY2hlY2tzX20kbGlzdCA8LSBOQQogIGF0dGVudGlvbl9jaGVja3NfbSRpdGVtIDwtIE5BCiAgYXR0ZW50aW9uX2NoZWNrc19tJGdyYW1tIDwtIE5BCiAgYXR0ZW50aW9uX2NoZWNrc19tJHZlcmIgPC0gTkEKCiMgQ29tYmluZSBpdGVtcywgZmlsbGVycywgcHJhY3RpY2UgaXRlbXMsIGJ1cm4taW4gaXRlbXMsIGJ1cm4taW4gZmlsbGVycywgYW5kIGF0dGVudGlvbiBjaGVja3MKbWFzdGVyIDwtIHJiaW5kKGl0ZW1zX20sIGZpbGxlcnNfbSwgYnVybl9pbl9pdGVtc19tLCBidXJuX2luX2ZpbGxlcnNfbSwgcHJhY3RpY2VfbSwgYXR0ZW50aW9uX2NoZWNrc19tKQoKIyBNYXRjaCBtYXN0ZXIgdG8gcmF0aW5ncyBkYXRhCnJhdGluZ3NfZGF0YV9pbmNsICU+JQogIG1lcmdlKC4sCiAgICAgICAgbWFzdGVyLAogICAgICAgIGJ5ID0gIklCRVhfSUQiKSAtPiByYXRpbmdzX2RhdGFfaW5jbAoKIyBBc3NvY2lhdGUgZXBvY2hfdGltZSB3LyBzdWJqZWN0IG51bWJlciBhbmQgbmF0aXZlIHNwZWFrZXIgc3RhdHVzCnJhdGluZ3NfZGF0YV9pbmNsICU+JQogIG1lcmdlKC4sCiAgICAgICAgcGFydGljaXBhbnRfZGF0YVssMToyXSwKICAgICAgICBieSA9ICJlcG9jaF90aW1lIikgLT4gcmF0aW5nc19kYXRhX2luY2wKCiMgU2F2ZSByYXRpbmdzIGRhdGEgYXMgY3N2CndyaXRlLmNzdihyYXRpbmdzX2RhdGFfaW5jbCwgZmlsZSA9ICJleHA2X3JhdGluZ3MuY3N2IikKCiMgRmluZCB0aGUgbGlzdCBlYWNoIHN1YmplY3Qgd2FzIGdpdmVuCnJhdGluZ3NfZGF0YV9pbmNsICU+JQogIHN1YnNldCh0eXBlID09ICJleHBlcmltZW50YWwiLAogICAgICAgICBzZWxlY3QgPSBjKHByb2xpZmljX2lkLAogICAgICAgICAgICAgICAgICAgIGxpc3QpKSAlPiUKICBkcm9wbGV2ZWxzICU+JQogIGdyb3VwX2J5KHByb2xpZmljX2lkKSAlPiUKICBzdW1tYXJpemUob25lX2xpc3QgPSBsZW5ndGgodW5pcXVlKGxpc3QpKSA9PSAxLAogICAgICAgICAgICBsaXN0ID0gaWYob25lX2xpc3QgPT0gVFJVRSl7CiAgICAgICAgICAgICAgbWluKGxpc3QpCiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIE5BCiAgICAgICAgICAgICAgfSkgLT4gbGlzdF9rZXkKCiMgSm9pbiBsaXN0X2tleSB3LyBwYXJ0aWNpcGFudF9kYXRhCnBhcnRpY2lwYW50X2RhdGEgJT4lCiAgbWVyZ2UoLiwKICAgICAgICBsaXN0X2tleSwKICAgICAgICBieSA9ICJwcm9saWZpY19pZCIpIC0+IHBhcnRpY2lwYW50X2RhdGEKCiMgQWRkIHNlbnRlbmNlIFJUIHN1bXMgdG8gcGFydGljaXBhbnQgZGF0YQpyYXRpbmdzX2RhdGFfaW5jbCAlPiUKICBncm91cF9ieShwcm9saWZpY19pZCkgJT4lCiAgc3VtbWFyaXplKHN0Y19ydHMgPSBzdW0ocnQpKSAtPiBwYXJ0aWNpcGFudF9ydHMKCiMgQWRkIFJUcyB0byBwYXJ0aWNpcGFudF9kYXRhICYgc3VtIGl0IHVwCm1lcmdlKHBhcnRpY2lwYW50X2RhdGEsCiAgICAgIHBhcnRpY2lwYW50X3J0cywKICAgICAgYnkgPSAicHJvbGlmaWNfaWQiKSAtPiBwYXJ0aWNpcGFudF9kYXRhCgphcHBseShwYXJ0aWNpcGFudF9kYXRhLCAxLAogICAgICBmdW5jdGlvbih4KXsKICAgICAgICBzdW0oYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoeFsiZm9ybV9ydHMiXSkpLAogICAgICAgICAgICBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih4WyJzZXBzIl0pKSwKICAgICAgICAgICAgYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoeFsic3RjX3J0cyJdKSkpIC0+IHRpbWUKICAgICAgICByZXR1cm4odGltZSkKICAgICAgfSkgLT4gcGFydGljaXBhbnRfZGF0YSR0b3RfdGltZV9tcwoKcGFydGljaXBhbnRfZGF0YSR0b3RfdGltZV9zIDwtIHBhcnRpY2lwYW50X2RhdGEkdG90X3RpbWVfbXMvMTAwMApwYXJ0aWNpcGFudF9kYXRhJHRvdF90aW1lX20gPC0gcGFydGljaXBhbnRfZGF0YSR0b3RfdGltZV9zLzYwCgojIFJlbW92ZSBleGNsdWRlZCBwYXJ0aWNpcGFudHMgZnJvbSBwYXJ0aWNpcGFudF9kYXRhIChTRUUgRVhDTFVERUQgUEFSVElDSVBBTlRTIElOIExJU1QgQkVMT1cpCnBhcnRpY2lwYW50X2RhdGEgJT4lCiAgc3Vic2V0KHByb2xpZmljX2lkICVpbiUgZXhjbHVkZWQpIC0+IHBhcnRpY2lwYW50X2RhdGFfcm0KCnBhcnRpY2lwYW50X2RhdGEgJT4lCiAgc3Vic2V0KCEocHJvbGlmaWNfaWQgJWluJSBleGNsdWRlZCkpICU+JQogIGRyb3BsZXZlbHMgLT4gcGFydGljaXBhbnRfZGF0YQoKIyBEZXRlcm1pbmUgaG93IGJhbGFuY2VkIHRoZSBsaXN0cyBhcmUuIEZvciB0aGlzIGV4cGVyaW1lbnQsIHRoZXJlIGFyZSA2IGxpc3RzLgpwYXJ0aWNpcGFudF9kYXRhICU+JQogIGdyb3VwX2J5KGxpc3QpICU+JQogIHN1bW1hcml6ZShjb3VudGVyID0gZmlyc3QobGlzdCkgLSAxLAogICAgICAgICAgICBuID0gbigpKSAtPiBsaXN0X2Rpc3QKYGBgCgojIEV4Y2x1c2lvbiBjcml0ZXJpYQoKQSBwYXJ0aWNpcGFudCB3aWxsIGJlIGV4Y2x1ZGVkIGlmIGFueSBvZiB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDoKMS4gVGhleSBmYWlsIGF0IGxlYXN0IG9uZSBvZiB0aGUgc2l4IGF0dGVudGlvbiBjaGVja3MuCjIuIFRoZSBwcm9wb3J0aW9uIG9mIHJlc3BvbnNlIHRpbWVzIGxvd2VyIHRoYW4gb25lIHNlY29uZCBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gMC4xMC4KMy4gVGhlaXIgbWVhbiByYXRpbmdzIGZvciBmaWxsZXJzIGV4cGVjdGVkIHRvIGJlIHVuZ3JhbW1hdGljYWwgYW5kIGZpbGxlcnMgZXhwZWN0ZWQgdG8gYmUgZ3JhbW1hdGljYWwgYXJlIGVpdGhlciBpbnZlcnRlZCBvciBhcmUgdG9vIGNsb3NlLiAqVG9vIGNsb3NlKiBpcyBkZWZpbmVkIG9uIG5vcm1hbGl6ZWQgcmF0aW5ncywgd2hlcmUgYSBkaWZmZXJlbmNlIHRoYXQgaXMgbW9yZSB0aGFuIHR3byBzdGFuZGFyZCBkZXZpYXRpb25zIGJlbG93IHRoZSBtZWFuIGRpZmZlcmVuY2UgaXMgdG9vIGNsb3NlLgoKCiMjIEF0dGVudGlvbiBjaGVja3MKCmBgYHtyIGF0dGVudGlvbl9jaGVja3N9CnJhdGluZ3NfZGF0YV9pbmNsICU+JQogIHN1YnNldCh0eXBlID09ICJhdHRlbnRpb24iKSAlPiUKICBncm91cF9ieShlcG9jaF90aW1lLAogICAgICAgICAgIHByb2xpZmljX2lkKSAlPiUKICBzdW1tYXJpemUoZmlyc3QgPSByYXRpbmdbSUQgPT0gImEwMSJdLAogICAgICAgICAgICBzZWNvbmQgPSByYXRpbmdbSUQgPT0gImEwMiJdLAogICAgICAgICAgICB0aGlyZCA9IHJhdGluZ1tJRCA9PSAiYTAzIl0sCiAgICAgICAgICAgIGZvdXJ0aCA9IHJhdGluZ1tJRCA9PSAiYTA0Il0sCiAgICAgICAgICAgIGZpZnRoID0gcmF0aW5nW0lEID09ICJhMDUiXSwKICAgICAgICAgICAgc2l4dGggPSByYXRpbmdbSUQgPT0gImEwNiJdKQpgYGAKCiMjIFJlc3BvbnNlIHRpbWVzCmBgYHtyIHJ0X3Bsb3RzfQojIEdlbmVyYXRlIFJUIGRlbnNpdHkgcGxvdHMgZm9yIGVhY2ggcGFydGljaXBhbnQKZm9yIChuIGluIDE6bGVuZ3RoKHVuaXF1ZShyYXRpbmdzX2RhdGFfaW5jbCRwcm9saWZpY19pZCkpKSB7CiAgcGFydGljaXBhbnQgPC0gdW5pcXVlKHJhdGluZ3NfZGF0YV9pbmNsJHByb2xpZmljX2lkKVtuXQogIHJhdGluZ3NfZGF0YV9pbmNsICU+JQogICAgc3Vic2V0KHByb2xpZmljX2lkID09IHBhcnRpY2lwYW50KSAlPiUKICAgIGdyb3VwX2J5KElCRVhfSUQpICU+JQogICAgc3VtbWFyaXplKHJ0X3MgPSBydC8xMDAwKSAlPiUKICAgIGdncGxvdChhZXMoeCA9IHJ0X3MpKSArCiAgICBnZW9tX2RlbnNpdHkoKSArCiAgICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVhbihydF9zKSkpICsKICAgIHhsaW0oeG1pbiA9IDAsCiAgICAgICAgIHhtYXggPSAxMCkgKwogICAgbGFicyh0aXRsZSA9IHBhc3RlKCJQcm9saWZpYyBJRCIsIHBhcnRpY2lwYW50LCAicmVzcG9uc2UgdGltZXMiKSwKICAgICAgICAgeCA9ICJSZXNwb25zZSB0aW1lIChzZWNvbmRzKSIsCiAgICAgICAgIHkgPSAiRGVuc2l0eSIpIC0+IHBsb3QKICBwcmludChwbG90KQp9CgojIEdldCBSVCBzdGF0cwpyYXRpbmdzX2RhdGFfaW5jbCAlPiUKICBncm91cF9ieShlcG9jaF90aW1lLAogICAgICAgICAgIHByb2xpZmljX2lkKSAlPiUKICBzdW1tYXJpemUobWVhbl9ydCA9IG1lYW4ocnQpLAogICAgICAgICAgICBwX2JlbG93XzEwMDAgPSBsZW5ndGgocnRbcnQgPCAxMDAwXSkvbGVuZ3RoKHJ0KSwKICAgICAgICAgICAgbWluX3J0ID0gbWluKHJ0KSwKICAgICAgICAgICAgbWF4X3J0ID0gbWF4KHJ0KSwKICAgICAgICAgICAgbWVkaWFuX3J0ID0gbWVkaWFuKHJ0KSwKICAgICAgICAgICAgbiA9IG4oKSwKICAgICAgICAgICAgc2QgPSBzZChydCksCiAgICAgICAgICAgIHNlID0gc2Qvc3FydChuKSkgLT4gcnRfc3RhdHMKcHJpbnQocnRfc3RhdHMpCgojIFByaW50IHBhcnRpY2lwYW50cyBmb3Igd2hvbSAyNSUgb3IgbW9yZSBvZiB0aGVpciBSVHMgYXJlIGxlc3MgdGhhbiBhIHNlY29uZC4KcnRfc3RhdHMgJT4lCiAgc3Vic2V0KHBfYmVsb3dfMTAwMCA+PSAwLjEwLAogICAgICAgICBzZWxlY3QgPSBjKGVwb2NoX3RpbWUsIHByb2xpZmljX2lkKSkKYGBgCgojIyBGaWxsZXIgcmF0aW5ncwpgYGB7ciBmaWxsZXJfcmF0aW5nc30KIyBTZWxlY3QgZmlsbGVyICYgZXhwZXJpbWVudGFsIHNlbnRlbmNlcyBhbmQgdHJhbnNmb3JtIHJhdGluZ3MgdG8gei1zY29yZXMgKGdyb3VwaW5nIGJ5IHBhcnRpY2lwYW50KQpyYXRpbmdzX2RhdGFfaW5jbCAlPiUKICBzdWJzZXQodHlwZSA9PSAiZXhwZXJpbWVudGFsIiB8IHR5cGUgPT0gImZpbGxlciIpICU+JQogIGdyb3VwX2J5KHByb2xpZmljX2lkKSAlPiUKICBtdXRhdGUoel9yYXRpbmcgPSBzY2FsZShhcy5udW1lcmljKGFzLmNoYXJhY3RlcihyYXRpbmcpKSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICAjIFNlbGVjdCBvbmx5IHRoZSBmaWxsZXJzCiAgc3Vic2V0KHR5cGUgPT0gImZpbGxlciIpICU+JQogICMgR3JvdXAgYnkgcGFydGljaXBhbnQgYW5kIGdyYW1tYXRpY2FsaXR5ICYgc3VtbWFyaXplIHJhdGluZ3MKICBncm91cF9ieShwcm9saWZpY19pZCwKICAgICAgICAgICBncmFtbSkgJT4lCiAgc3VtbWFyaXplKG1lYW5fel9yYXRpbmcgPSBtZWFuKHpfcmF0aW5nKSkgLT4gZmlsbGVyX3pfbWVhbnMKcHJpbnQoZmlsbGVyX3pfbWVhbnMpCgojIEdldCBkaWZmZXJlbmNlIGluIG1lYW4gel9yYXRpbmdzIHBlciBwYXJ0aWNpcGFudCBhbmQgam9pbiB3LyBmaWxsZXJfel9tZWFucwpmaWxsZXJfel9tZWFucyAlPiUKICBncm91cF9ieShwcm9saWZpY19pZCkgJT4lCiAgc3VtbWFyaXplKGRpZmYgPSBtZWFuX3pfcmF0aW5nW2dyYW1tID09ICIxIl0gLSBtZWFuX3pfcmF0aW5nW2dyYW1tID09ICIwIl0pICU+JQogIG1lcmdlKGZpbGxlcl96X21lYW5zLCAuKSAtPiBmaWxsZXJfel9tZWFucwoKIyBTaG93IGEgbGlzdCBvZiBwYXJ0aWNpcGFudHMgd2hvc2UgZGlmZmVyZW5jZSBpcyBvdmVyIHR3byBTRHMgYXdheSBmcm9tIHRoZSBtZWFuCiNmaWxsZXJfel9tZWFucyAlPiUKIyAgc3Vic2V0KGRpZmYgPCBtZWFuX2RpZmYtKDIqc2RfZGlmZikpCgpmaWxsZXJfel9tZWFucyAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKHByb2xpZmljX2lkLCBkaWZmKSwKICAgICAgICAgICAgIHkgPSBtZWFuX3pfcmF0aW5nLAogICAgICAgICAgICAgY29sb3IgPSBhcy5mYWN0b3IoZ3JhbW0pKSkgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh4ID0gIlByb2xpZmljIElEIChmaXJzdCA0KSIsCiAgICAgICB5ID0gIk1lYW4gei1zY29yZS10cmFuc2Zvcm1lZCByYXRpbmciKSArCiAgc2NhbGVfY29sb3JfZGlzY3JldGUoIkdyYW1tYXRpY2FsaXR5IikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIHZqdXN0ID0gMC45NSwgaGp1c3QgPSAwLjk1KSkgLT4gZmlsbGVyX3JhdGluZ3NfcGxvdApwcmludChmaWxsZXJfcmF0aW5nc19wbG90KQpgYGAKCiMjIE1ha2UgbGlzdCBvZiBleGNsdWRlZCBwYXJ0aWNpcGFudHMKCmBgYHtyIGV4Y2x1ZGVkX3BhcnRpY2lwYW50c30KZXhjbHVkZWQgPC0gTlVMTApleGNsdWRlZCA8LSBjKGV4Y2x1ZGVkLCAiMTM0ZCIpICMgRmFpbGVkIG9uZSBhdHRlbnRpb24gY2hlY2sKZXhjbHVkZWQgPC0gYyhleGNsdWRlZCwgImQ2YWQiKSAjIE1lYW4gZ3JhbW0gYW5kIHVuZ3JhbW0gZmlsbGVyIHJhdGluZ3MgdG9vIGNsb3NlOyBtb3N0IFJUcyBiZWxvdyAyLjVzCmV4Y2x1ZGVkIDwtIGMoZXhjbHVkZWQsICJkNzk3IikgIyBNZWFuIGdyYW1tIGFuZCB1bmdyYW1tIGZpbGxlciByYXRpbmdzIHRvbyBjbG9zZQpgYGA=