Fink, Fiehn & Wald-Fuhrmann (2024). The role of audiovisual
congruence in aesthetic appreciation of contemporary music and visual
art. Scientific Reports, 71399. DOI: https://doi.org/10.1038/s41598-024-71399-y
If using any code or data from this notebook, please cite the
paper.
Load and preprocess data
Turn off warnings for cleaner submission file. N.B. users of this
file should turn warnings on for troubleshooting
Install required packages, if not already installed
list.of.packages <- c("tidyverse", "ggpubr", "ez", "corrplot", "car", "stats","PerformanceAnalytics", "afex", "emmeans", "mlma", "ggplot2", "ggExtra", "psych", "ggpubr", "here", "gridExtra", "ggridges")
new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
if(length(new.packages)) install.packages(new.packages)
Load packages and data
We use the here package so that all file paths are relative.
Users should be sure not to change the directory structure of the
repository. By default, figures will be plotted in line. If you want to
save the figures to a folder on your local machine, set op = 1.
here::i_am("Fink_Kentler_analyses.Rmd")
library(here)
source(here("dependencies.R"))
data <- read.csv(here("data.csv"))
fig_path <- here("figures/") # path to save generated figures to
op = 0 # flag if want to save output plots to files (1) or plot inline (0)
Pre-process the data
Clean up variable names, add combined columns of interest, drop
unnecessary columns
# remove variables we don't need (Labvanced still outputting old vars from earlier exp. version)
data_new <- subset(data, select = - c(Block_Name, Task_Nr, aud_tend_unix, aud_ts, aud_ts_unix, condi3, copy_of_condi2, copy_of_condi, frame_end_unix, frame_rt, Name.Audio._copy_4b49, Name.Audio._copy_93a7, Name.Audio._copy_bd6f, Name.Audio._copy_c958, Name.Audio._copy_c96c, Name.Audio., subj_counter_global, subj_counter_per_group, time_delay_offset, time_measure_std, pixelDensityPerMM,unlocked))
# filter out people who have seen/heard stimuli before (some of our pilots) or who don't have normal hearing / vision
exposed = table(data$prev_exposure)
data_new <- data_new[-c(which(data_new$prev_exposure == "option_0")), ]
normSenses = table(data$Normal.Vision.) # no one without
data_new <- data_new[-c(which(data_new$completed == "no")), ] # remove incompletes
data = data_new # overwrite old data so can't accidentally use it
#create a dataframe just with the task block (for further analysis )
data_task <- data_new %>%
select(Trial_Nr, Trial_Id, correspondence_, enjoy_, Frame.Time., interestingness_, mood.congruency_, move_, subject_code, Block_Nr, group_name, exp_subject_id)
data_task <- data_task[, c("exp_subject_id", "Block_Nr", "Trial_Nr", "Trial_Id","group_name", "Frame.Time.", "correspondence_", "enjoy_", "interestingness_", "mood.congruency_", "move_" )]
# put time spent in secs (instead of ms)
data_task$Frame.Time. = data_task$Frame.Time. / 1000
# Add column for condition
# Trial_Id tells which condition it is (1 - 4 = A; 5 - 8 = V; 9 - 12 = AVI; 13 - 16 = AVR)
# with Trial_Id and the group number we can look which specific stimuli are used
data_task$Trial_Id = as.numeric(data_task$Trial_Id)
data_task$condition = NA
data_task$condition[data_task$Trial_Id <= 4] = 'Audio'
data_task$condition[data_task$Trial_Id >= 5 & data_task$Trial_Id <= 8] = 'Visual'
data_task$condition[data_task$Trial_Id >= 9 & data_task$Trial_Id <= 12] = 'AV-Intended'
data_task$condition[data_task$Trial_Id >= 13] = 'AV-Random'
# create subset data frame of task data
#just keep Block Number = 2 (these are the experimental trials)
data_task <- data_task %>%
filter(Block_Nr == 2)
# create subset data frame with just participant info
data_participant <- data_new %>%
select(exp_subject_id, group_name, age_input, gender, country_current, country_home, Modality_Preference, Ollen, overall_enjoy, "prev_exposure", realWorldLikelihood)
data_participant = na.omit(data_participant)
# calculate area scores for each participant and add to participant data
# AReA scale scoring
#Aesthetic Appreciation: Items 1, 2, 3, 4, 6, 9, 13, 14
#Intense Aesthetic Experience: Items 8, 11, 12, 13
#Creative Behavior: Items 5, 7, 10
area_data = data[data$Task_Name == 'AReA',]
area_data$area_aes_apprec = area_data$area_01 + area_data$area_02 + area_data$area_03 + area_data$area_04 + area_data$area_06 + area_data$area_09 + area_data$area_13 + area_data$area_14
area_data$area_aes_apprec = area_data$area_aes_apprec / 8 # divide by num of items
area_data$area_intense_aes_exp = area_data$area_08 + area_data$area_11 + area_data$area_12 + area_data$area_13
area_data$area_intense_aes_exp = area_data$area_intense_aes_exp / 4
area_data$area_creative_beh = area_data$area_05 + area_data$area_07 + area_data$area_10
area_data$area_creative_beh = area_data$area_creative_beh / 3
area_data$area_composite = (area_data$area_aes_apprec + area_data$area_intense_aes_exp + area_data$area_creative_beh) / 3
# add area scores to mean table (join based on exp_subj_id)
area_data = area_data[,c("exp_subject_id", "area_aes_apprec", "area_intense_aes_exp", "area_creative_beh", "area_composite")]
# merge area with participant df
data_participant = merge(x=data_participant,y=area_data,
by="exp_subject_id", all=TRUE)
# clean up modality pref data to have meaningful labels
temp = data_participant$Modality_Preference
temp = gsub("option_0", "prefer_audio", temp)
temp = gsub("option_1", "prefer_visual", temp)
temp = gsub("option_2", "prefer_audiovisual", temp)
temp = gsub("option_3", "no_preference", temp)
data_participant$Modality_Preference_cat = temp
# join participant info with trial level data for final full data frame
full_data = merge(x=data_task,y=data_participant,
by="exp_subject_id", all=TRUE)
Check participant number discrepencies between task data and demo
data
# something wrong! only 195 obs for people who saw endQs ?! (these were required questions. not sure how labvanced let that through)
# table(data_new$Task_Name)
# check what going on with 6 subs
check = subset(full_data, is.na(full_data$Ollen))
check2 = subset(data, is.na(full_data$Ollen))
nsubs = length(unique(full_data$exp_subject_id))
nsubs_missingDemo = length(unique(check$exp_subject_id))
It seems 6 participants never got the ending questions. We can
include them for all trial analyses but they will be excluded from
person-level analyses
Person-level analyses
Explore demographic data
gender_dist = table(data_participant$gender)
age_mean = mean(data_participant$age_input, na.rm = TRUE)
age_std = sd(data_participant$age_input, na.rm = TRUE)
ncountries = length(unique(data_participant$country_current))
countries = table(data_participant$country_current)
modality_pref = table(data_participant$Modality_Preference_cat)
print("Gender: man, woman, non-binary, prefer not to say")
[1] "Gender: man, woman, non-binary, prefer not to say"
print(gender_dist)
0 1 2 3
117 73 4 1
print("Age (mean, sd, min, max)")
[1] "Age (mean, sd, min, max)"
print(age_mean)
[1] 31.01538
print(age_std)
[1] 11.81973
print(min(data_participant$age_input, na.rm = TRUE))
[1] 18
print(max(data_participant$age_input, na.rm = TRUE))
[1] 68
print("Unique countries:")
[1] "Unique countries:"
print(ncountries)
[1] 23
print(countries)
Australia Belgium Canada Chile Czech Republic Ecuador
2 1 3 1 2 1
Germany Greece Hungary India Ireland Italy
1 9 4 1 2 11
Mexico Nigeria Poland Portugal South Africa Spain
12 2 23 34 15 9
Switzerland Ukraine United Kingdom United States
2 1 47 12
print("AReA (mean, sd, min, max):")
[1] "AReA (mean, sd, min, max):"
print(mean(data_participant$area_composite))
[1] 2.62576
print(sd(data_participant$area_composite))
[1] 0.7410346
print(min(data_participant$area_composite))
[1] 1.125
print(max(data_participant$area_composite))
[1] 4.763889
print("AReA AA (mean, sd, min, max):")
[1] "AReA AA (mean, sd, min, max):"
print(mean(data_participant$area_aes_apprec))
[1] 3.439055
print(sd(data_participant$area_aes_apprec))
[1] 0.69193
print(min(data_participant$area_aes_apprec))
[1] 1.125
print(max(data_participant$area_aes_apprec))
[1] 5
print("AReA IAE (mean, sd, min, max):")
[1] "AReA IAE (mean, sd, min, max):"
print(mean(data_participant$area_intense_aes_exp))
[1] 2.461443
print(sd(data_participant$area_intense_aes_exp))
[1] 0.9202953
print(min(data_participant$area_intense_aes_exp))
[1] 1
print(max(data_participant$area_intense_aes_exp))
[1] 5
print("AReA CB (mean, sd, min, max):")
[1] "AReA CB (mean, sd, min, max):"
print(mean(data_participant$area_creative_beh))
[1] 1.976783
print(sd(data_participant$area_creative_beh))
[1] 0.9174315
print(min(data_participant$area_creative_beh))
[1] 1
print(max(data_participant$area_creative_beh))
[1] 5
Plot experiment-related person-level variables
# clean up and plot ollen data
ollenScale = c("non-musician", "music-loving non-musician", "amateur musician", "serious amateur musician", "semi-professional musician", "professional musician")
ollen = table(data_participant$Ollen)
ollen = data.frame(ollen)
names(ollen) = c("Response","Participants")
ollen$Response = ollenScale[1:5] # nobody chose professional!
print(ollen)
describe(ollen$Participants)
# order Ollen properly
ollen <- within(ollen, Response <- factor(Response, levels=ollenScale))
# create barplot
# png("Kentler_ollen.png", units="in", width=8, height=5, res=300)
ggplot(ollen, aes(x=Response, y=Participants)) +
geom_bar(stat = "identity") + coord_flip() + theme_classic() + theme(text = element_text(size = 20))
# Plot area data
ggplot(data_participant, aes(x=area_composite)) +
geom_histogram(bins = 20) + ggtitle("AReA composite score")
# Plot enjoyment data
ggplot(data_participant, aes(x=overall_enjoy)) +
geom_histogram(bins = 25) + ggtitle("Overall enjoyment of the experiment")
ggplot(data_participant, aes(x=realWorldLikelihood)) +
geom_histogram(bins = 25) + ggtitle("Likelihood of seeking similar pieces in real world")
print("Enjoyment (mean, sd)")
[1] "Enjoyment (mean, sd)"
print(mean(data_participant$overall_enjoy, na.rm=T))
[1] 84.58974
print(sd(data_participant$overall_enjoy, na.rm=T))
[1] 20.67136
print("Likelihood (mean, sd)")
[1] "Likelihood (mean, sd)"
print(mean(data_participant$realWorldLikelihood, na.rm=T))
[1] 54.81026
print(sd(data_participant$realWorldLikelihood, na.rm=T))
[1] 31.5477
# plot relation between enjoyment and likelihood
p <- ggplot(data_participant, aes(x=overall_enjoy, y=realWorldLikelihood)) +
geom_point() + geom_smooth(method=lm , color="black", fill="gray", se=TRUE) +
theme(legend.position="none") + theme_classic()
# Custom marginal plots:
p2 <- ggMarginal(p, type="densigram", fill = "gray")
p2
# Self-reported modality prefs
# create barplot of modality preferences
mpref = data.frame(modality_pref)
names(mpref) = c("Response","Participants")
mpref$percent = mpref$Participants / sum(mpref$Participants)
# png("Kentler_preference.png", units="in", width=8, height=5, res=300)
ggplot(mpref, aes(x=Response, y=Participants)) +
geom_bar(stat = "identity") + coord_flip() + theme_classic() + theme(text = element_text(size = 20))
Plot relationship between all person-level vars
# create data frame for correlation
# need to convert categorical to numeric
corrdf = data_participant[ , which(names(data_participant) %in% c("Ollen", "Modality_Preference", "overall_enjoy", "realWorldLikelihood", "area_aes_apprec", "area_intense_aes_exp", "area_creative_beh", "area_composite"))]
corrdf$Modality_Preference = as.numeric(as.factor(corrdf$Modality_Preference))
corrdf$Ollen = as.numeric(as.factor(corrdf$Ollen))
chart.Correlation(corrdf, histogram=TRUE, pch=25, text.panel=labs)
Condition-level analyses
Create tables of means
Z-score ratings data within scale, participant
Calculate table of means for all participants / conditions - do this for
both z-scored and raw data in case we want to compare
# create zscore function
zscore <- function(input){
out = (input - mean(input))/sd(input)
}
# zscore data
zscored = data_task %>%
group_by(exp_subject_id) %>%
mutate(z_enjoy = zscore(enjoy_), z_interesting = zscore(interestingness_), z_mood_cong = zscore(mood.congruency_), z_moved = zscore(move_))
# NOTE zscoring correspondence needs to be done only for AV conditions
# get means of zscored data
z_means = zscored %>%
group_by(exp_subject_id, condition) %>%
summarise(mean_timespent = mean(Frame.Time.), mean_enjoy = mean(z_enjoy), mean_interesting = mean(z_interesting), mean_mood_cong = mean(z_mood_cong), mean_moved = mean(z_moved))
# get means of zscored data
# z_means_participant = z_means %>%
# group_by(exp_subject_id) %>%
# summarise(mean_timespent = mean(mean_timespent), mean_enjoy = mean(mean_enjoy), mean_interesting = mean(mean_interesting), mean_mood_cong = mean(mean_mood_cong), mean_moved = mean(mean_moved))
#
# get raw means in case want to compare to zscored data
means = data_task %>%
group_by(exp_subject_id, condition) %>%
summarise(mean_timespent = mean(Frame.Time.), mean_enjoy = mean(enjoy_), mean_interesting = mean(interestingness_), mean_mood_cong = mean(mood.congruency_), mean_moved = mean(move_), mean_corresp = mean(correspondence_))
# get raw sds in case want to compare to zscored data
sds = data_task %>%
group_by(exp_subject_id, condition) %>%
summarise(mean_timespent = sd(Frame.Time.), mean_enjoy = sd(enjoy_), mean_interesting = sd(interestingness_), mean_mood_cong = sd(mood.congruency_), mean_moved = sd(move_), mean_corresp = sd(correspondence_))
Create custom functions for analysis and plotting
We have multiple DVs on which we want to run the same type of
analysis
# Function to plot violins for each condition
# Input: dataframe, variable to plot, title for plot
plotViolin = function(data, groupvar, var, titstr, xlab, ylab){
# define colors
AVR = '#8c1aff'
AVI = '#cc99ff'
V = '#ff4d4d'
A = '#6699ff'
ourcolors = c(A, AVI, AVR, V)
# only AV conditions relevant
if (var == "z_corresp"){
ourcolors = c(AVI, AVR)
}
# Plot
var = sym(var)
groupvar = sym(groupvar)
pl = data %>%
ggplot(aes(x=!!groupvar, y=!!var, fill=!!groupvar)) +
geom_violin(legend = FALSE, trim = FALSE, adjust = 1, draw_quantiles = c(0.25, 0.75), size=.5, linetype = "dashed", color="black") + #.8
geom_violin(legend = FALSE, trim = FALSE, adjust = 1, draw_quantiles = 0.5, fill="transparent", size=.85, color="black") + #1.2
geom_jitter(size=0.4, alpha=0.6, color="gray") +
scale_fill_manual(values=ourcolors) +
#theme_classic() +
theme_ridges() +
theme(
legend.position="none",
plot.title = element_text(size=11)
) +
ggtitle(titstr) +
xlab(xlab) +
ylab(ylab)
return(pl)
}
# Function to create density ridge plots for each condition
# Input: dataframe, variable to plot, title for plot
plotRidges = function(data, groupvar, var, titstr, xlab, ylab){
# define colors
AVR = '#CCBB44'
AVI = '#228833'
V = '#CC6677'
A = '#88CCEE'
ourcolors = c(A, AVI, AVR, V)
# only AV conditions relevant
if (var == "z_corresp"){
ourcolors = c(AVI, AVR)
}
# Plot
var = sym(var)
groupvar = sym(groupvar)
pl = data %>%
ggplot(aes(x=!!var, y=!!groupvar, fill=!!groupvar)) +
# stat_density_ridges(quantile_lines=TRUE, quantiles = c(0.025, 0.975), color="black", alpha = 1) +
geom_density_ridges(inherit.aes = TRUE, jittered_points = TRUE, stat ="density_ridges",
position = position_points_jitter(width = 0.05, height = 0),
point_shape = '|', point_size = 3, point_alpha = .9, alpha = 0.7) +
geom_density_ridges(alpha = 0.85, quantile_lines=TRUE,
color="white", quantile_fun=function(var,...)mean(var)) +
scale_fill_manual(values=ourcolors) +
xlab(ylab) +
theme_ridges() + theme(legend.position = "none") +
theme(axis.title.x = element_text(hjust = 0.5)) +
theme(axis.title.y=element_blank())
return(pl)
}
# Function to run rm anova and output stats
runaov = function(id, dv, data, w){
fit = aov_ez(id,dv,data,within=w)
print(fit)
fit2 <- lsmeans(fit,specs = c(w))
contrast(fit2,method="pairwise",adjust="holm")
}
# Conditions to compare after ANOVAs
my_comparisons <- list( c("Audio", "AV-Intended"), c("Audio", "AV-Random"), c("Audio", "Visual"), c("AV-Intended", "AV-Random"), c("AV-Intended", "Visual"), c("AV-Random", "Visual"))
my_comparisons = rev(my_comparisons) # reverse order so more readable on plots
# Choose plotting style (violin or ridge) for future plots
customplot = plotRidges
hide_ns = FALSE
Time spent
How much time did participants spend experiencing the pieces in the
different conditions? Did they spend more time in one condition
vs. another?
z_means$logtime = log(z_means$mean_timespent)
p = customplot(z_means, "condition", "mean_timespent", "", "Condition", "Mean Time Spent (secs)")
plotTimeSecs = p + stat_compare_means(comparisons = my_comparisons, label = "p.signif", method = "t.test", paired = "true", na.rm=TRUE, hide.ns=hide_ns)
p = customplot(z_means, "condition", "logtime", "", "", "Mean Time Spent (log secs)")
plotTimeLog = p + stat_compare_means(comparisons = my_comparisons, label = "p.signif", method = "t.test", paired = "true", na.rm=TRUE, hide.ns=hide_ns)
z_means$exp_subject_id = as.factor(z_means$exp_subject_id)
runaov("exp_subject_id","mean_timespent", z_means, "condition")
Anova Table (Type 3 tests)
Response: mean_timespent
Effect df MSE F ges p.value
1 condition 2.00, 400.21 237.00 96.93 *** .100 <.001
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘+’ 0.1 ‘ ’ 1
Sphericity correction method: GG
contrast estimate SE df t.ratio p.value
AV.Intended - AV.Random -0.616 0.948 200 -0.650 0.5165
AV.Intended - Audio -4.908 0.800 200 -6.134 <.0001
AV.Intended - Visual 15.067 1.469 200 10.256 <.0001
AV.Random - Audio -4.292 0.942 200 -4.554 <.0001
AV.Random - Visual 15.683 1.514 200 10.361 <.0001
Audio - Visual 19.975 1.600 200 12.481 <.0001
P value adjustment: holm method for 6 tests
# print means and sds
cond_means = z_means %>%
group_by(condition) %>%
summarise(mean_timespent = mean(mean_timespent, na.rm=T))
cond_sds = z_means %>%
group_by(condition) %>%
summarise(sd_timespent = sd(mean_timespent, na.rm=T))
print(cond_means)
print(cond_sds)
plotTimeSecs
plotTimeLog
plotTimeSecs = plotTimeSecs + labs(title = "Time Spent", tag = "A") + theme(plot.title = element_text(hjust = 0.5, face='bold'), plot.tag = element_text(face='bold'))
We find a main effect of condition. Post-hoc tests show significant
differences between all conditions, except AVI and AVR. Results do not
change whether we use raw mean time spent or log of it.
Enjoyment
Did enjoyment differ by condition? (Q to participants: I enjoyed the
piece (0-100))
p = customplot(z_means, "condition", "mean_enjoy", "", "Condition", "Mean Enjoyment (z-score)")
plotEnjoy = p + stat_compare_means(comparisons = my_comparisons, label = "p.signif", method = "t.test", paired = "true", na.rm=TRUE, hide.ns=hide_ns)
runaov("exp_subject_id","mean_enjoy", z_means, "condition")
Anova Table (Type 3 tests)
Response: mean_enjoy
Effect df MSE F ges p.value
1 condition 2.76, 552.98 0.33 13.83 *** .065 <.001
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘+’ 0.1 ‘ ’ 1
Sphericity correction method: GG
contrast estimate SE df t.ratio p.value
AV.Intended - AV.Random -0.01486 0.0484 200 -0.307 1.0000
AV.Intended - Audio 0.28382 0.0524 200 5.416 <.0001
AV.Intended - Visual -0.00333 0.0544 200 -0.061 1.0000
AV.Random - Audio 0.29869 0.0546 200 5.475 <.0001
AV.Random - Visual 0.01154 0.0544 200 0.212 1.0000
Audio - Visual -0.28715 0.0654 200 -4.388 0.0001
P value adjustment: holm method for 6 tests
plotEnjoy
plotEnjoy = plotEnjoy + labs(title = "Enjoyment", tag = "C") + theme(plot.title = element_text(hjust = 0.5, face='bold'), plot.tag = element_text(face='bold'))
There is a significant main effect of condition on Enjoyment.
Post-hoc contrasts show that AVI and AVR are higher in enjoyment than A,
but not V, or each other. (V is also higher than A) So, even though
people spent more time with audio, they enjoy more with visual.
Interestingness
Did interestingness differ by condition? (Q to participants: I found
the piece interesting (0-100))
p = customplot(z_means, "condition", "mean_interesting", "", "Condition", "Mean Interestingness (z-score)")
plotInterest = p + stat_compare_means(comparisons = my_comparisons, label = "p.signif", method = "t.test", paired = "true", na.rm=TRUE, hide.ns=hide_ns)
runaov("exp_subject_id","mean_interesting", z_means, "condition")
Anova Table (Type 3 tests)
Response: mean_interesting
Effect df MSE F ges p.value
1 condition 2.65, 526.68 0.35 13.06 *** .062 <.001
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘+’ 0.1 ‘ ’ 1
Sphericity correction method: GG
contrast estimate SE df t.ratio p.value
AV.Intended - AV.Random -0.0412 0.0460 199 -0.897 0.5345
AV.Intended - Audio 0.2781 0.0530 199 5.249 <.0001
AV.Intended - Visual 0.0637 0.0573 199 1.112 0.5345
AV.Random - Audio 0.3193 0.0537 199 5.943 <.0001
AV.Random - Visual 0.1050 0.0532 199 1.973 0.1496
Audio - Visual -0.2144 0.0680 199 -3.154 0.0075
P value adjustment: holm method for 6 tests
plotInterest
plotInterest = plotInterest + labs(title = "Interestingness", tag = "D") + theme(plot.title = element_text(hjust = 0.5, face='bold'), plot.tag = element_text(face='bold'))
These interestingness results are basically identical to the ones
above for enjoyment.
Mood Congruency
Did participants feel the piece matched their current mood more in
certain conditions? (Q to participants: The piece matched my current
mood (0-100))
p = customplot(z_means, "condition", "mean_mood_cong", "", "Condition", "Mean Mood Congruency (z-score)")
plotMood = p + stat_compare_means(comparisons = my_comparisons, label = "p.signif", method = "t.test", paired = "true", na.rm=TRUE, hide.ns=hide_ns)
runaov("exp_subject_id","mean_mood_cong", z_means, "condition")
Anova Table (Type 3 tests)
Response: mean_mood_cong
Effect df MSE F ges p.value
1 condition 2.84, 564.37 0.30 3.61 * .018 .015
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘+’ 0.1 ‘ ’ 1
Sphericity correction method: GG
contrast estimate SE df t.ratio p.value
AV.Intended - AV.Random -0.0256 0.0454 199 -0.563 0.5910
AV.Intended - Audio 0.0896 0.0526 199 1.703 0.3607
AV.Intended - Visual -0.0827 0.0540 199 -1.533 0.3809
AV.Random - Audio 0.1152 0.0519 199 2.219 0.1380
AV.Random - Visual -0.0571 0.0545 199 -1.049 0.5910
Audio - Visual -0.1723 0.0609 199 -2.831 0.0307
P value adjustment: holm method for 6 tests
plotMood
plotMood = plotMood + labs(title = "Mood Congruency", tag = "E") + theme(plot.title = element_text(hjust = 0.5, face='bold'), plot.tag = element_text(face='bold'))
There is a significant main effect of condition with repect to
whether people think the piece matches their current mood. Post-hoc
contrasts show that people are significantly more likely to say the
piece matches their mood in V vs. A conditions. But no other post-hoc
contrasts were significant.
Feeling moved
Did participants feel moved by the piece more in certain conditions?
(Q to participants: The piece moved me (0-100))
p = customplot(z_means, "condition", "mean_moved", "", "Condition", "Mean Feeling Moved (z-score)")
runaov("exp_subject_id","mean_moved", z_means, "condition")
Anova Table (Type 3 tests)
Response: mean_moved
Effect df MSE F ges p.value
1 condition 2.83, 561.24 0.30 9.12 *** .044 <.001
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘+’ 0.1 ‘ ’ 1
Sphericity correction method: GG
contrast estimate SE df t.ratio p.value
AV.Intended - AV.Random -0.0265 0.0453 198 -0.584 1.0000
AV.Intended - Audio 0.1667 0.0539 198 3.092 0.0068
AV.Intended - Visual 0.1987 0.0544 198 3.651 0.0013
AV.Random - Audio 0.1932 0.0520 198 3.714 0.0013
AV.Random - Visual 0.2252 0.0535 198 4.209 0.0002
Audio - Visual 0.0320 0.0611 198 0.523 1.0000
P value adjustment: holm method for 6 tests
plotMoved = p + stat_compare_means(comparisons = my_comparisons, label = "p.signif", method = "t.test", paired = "true", na.rm=TRUE, hide.ns=hide_ns)
plotMoved
plotMoved = plotMoved + labs(title = "Feeling Moved", tag = "F") + theme(plot.title = element_text(hjust = 0.5, face='bold'), plot.tag = element_text(face='bold'))
Significant main effect of condition on feeling moved. Post-hoc tests
shows no significant differences in feeling moved between A vs. V or
between AVI vs. AVR, but all other contrasts were significant. This is
interesting and potentially a “load” effect (i.e., bimodal is generally
more moving than uni-modal)
Audio-visual correspondence
Could participants tell above chance whether the audio and visual
materials corresponded to one another? (Q to participants: To what
degree did you feel there was a correspondence between the audio and
visual sensations you were experiencing?)
# only zscore within relevant AV conditions
correspdata = data_task[data_task$condition == "AV-Intended" | data_task$condition == "AV-Random", ]
zscored_corresp = correspdata %>%
group_by(exp_subject_id) %>%
mutate(z_corresp = zscore(correspondence_))
mean_z_corresp = zscored_corresp %>%
group_by(exp_subject_id, condition) %>%
summarise(z_corresp = mean(z_corresp))
# plot and calculate stats
p <- customplot(mean_z_corresp, "condition", "z_corresp", "", "Condition", "Mean Correspondence (z-score)")
plotAVcorresp = p + stat_compare_means(comparisons = list(c("AV-Intended", "AV-Random")), label = "p.signif", method = "t.test", paired="true", label.x.npc=.5)
compare_means(z_corresp ~ condition, data = mean_z_corresp, method = "t.test", hide.ns=hide_ns)
plotAVcorresp
plotAVcorresp = plotAVcorresp + labs(title = "Audiovisual Correspondence", tag = "B") + theme(plot.title = element_text(hjust = 0.5, face='bold'), plot.tag = element_text(face='bold'))
There is a significant difference between AVI and AVR conditions in
terms of felt correspendence (i.e., particpants felt that the
intentional pairings showed greater A-V correspondence than the random
pairings). It is quite interesting then, that even though they could
tell the difference in correspondence, there were no differences in
terms of enjoyment, interestingness, etc. (see all prior plots and
stats).
Factor analysis on ratings data
Organize all data we want into one table
# merge participants means and demo data
pall = merge(data_participant, z_means, by="exp_subject_id")
# remove columns we don't need
pall = pall[ , -which(names(pall) %in% c("country_current", "country_home","prev_exposure","area_intense_aes_exp","Modality_Preference_cat", "area_creative_beh","area_aes_apprec"))]
# "gender","Modality_Preference","Ollen",, "exp_subject_id","group_name",
pall$mean_timespent = log(pall$mean_timespent)
# make sure variable right type
# Remove the 'option_' prefix and keep only the numbers for the ordered categorical columns
data$Modality_Preference <- gsub('option_', '', data$Modality_Preference)
# Convert the column to numeric
data$Modality_Preference <- as.numeric(data$Modality_Preference)
# Convert to ordered factor
pall$Modality_Preference = factor(pall$Modality_Preference)
# Do same for ollen scale
data$Ollen <- gsub('option_', '', data$Ollen)
data$Ollen <- as.numeric(data$Ollen)
pall$Ollen = factor(pall$Ollen)
# gender is unordered
pall$gender = factor(pall$gender, ordered = F)
#chart.Correlation(pall, histogram=TRUE, pch=25, text.panel=labs)
Check for suitability of FA
# organize data
forfa = z_means[ , -which(names(z_means) %in% c("mean_timespent","logtime", "condition","exp_subject_id", "factor_score"))]
# check for missing values
nna = sum(is.na(forfa)) # 16 nas in the df
# N.B. NAs have been introduced by z-scoring, due to dividing by zero (no variance)
# Since the true mean was zero, it is fair to impute with zero
forfa$mean_enjoy[is.na(forfa$mean_enjoy)] <- 0
forfa$mean_mood_cong[is.na(forfa$mean_mood_cong)] <- 0
forfa$mean_moved[is.na(forfa$mean_moved)] <- 0
forfa$mean_interesting[is.na(forfa$mean_interesting)] <- 0
# Do tests to determine suitability for FA
print("KMO")
[1] "KMO"
KMO(r=cor(forfa))
Kaiser-Meyer-Olkin factor adequacy
Call: KMO(r = cor(forfa))
Overall MSA = 0.8
MSA for each item =
mean_enjoy mean_interesting mean_mood_cong mean_moved
0.73 0.75 0.88 0.90
print("Bartlett")
[1] "Bartlett"
cortest.bartlett(forfa)
$chisq
[1] 2127.938
$p.value
[1] 0
$df
[1] 6
print("Determinant")
[1] "Determinant"
det(cor(forfa))
[1] 0.07014754
Kaiser’s (1974) guidelines, suggest cutoff of KMO ≥ 60 for
determining the factorability of the sample data. Here was are well
above, suggesting suitability for FA. P value for Bartlett’s test is
significant. Determinant is positive, indicating FA will likely run.
Determine number of factors
fafitfree <- fa(forfa, nfactors = ncol(forfa), rotate = "none")
n_factors <- length(fafitfree$e.values)
scree <- data.frame(
Factor_n = as.factor(1:n_factors),
Eigenvalue = fafitfree$e.values)
ggplot(scree, aes(x = Factor_n, y = Eigenvalue, group = 1)) +
geom_point() + geom_line() +
xlab("Number of factors") +
ylab("Initial eigenvalue") +
labs( title = "Scree Plot",
subtitle = "(Based on the unreduced correlation matrix)")
fa.none <- fa(r=forfa,
nfactors = 1,
fm="pa", # type of factor analysis we want to use (“pa” is principal axis factoring)
max.iter=100,
rotate="varimax") # none rotation
print(fa.none)
Factor Analysis using method = pa
Call: fa(r = forfa, nfactors = 1, rotate = "varimax", max.iter = 100,
fm = "pa")
Standardized loadings (pattern matrix) based upon correlation matrix
PA1
SS loadings 2.75
Proportion Var 0.69
Mean item complexity = 1
Test of the hypothesis that 1 factor is sufficient.
df null model = 6 with the objective function = 2.66 with Chi Square = 2127.94
df of the model are 2 and the objective function was 0.07
The root mean square of the residuals (RMSR) is 0.03
The df corrected root mean square of the residuals is 0.05
The harmonic n.obs is 804 with the empirical chi square 9.47 with prob < 0.0088
The total n.obs was 804 with Likelihood Chi Square = 53.1 with prob < 2.9e-12
Tucker Lewis Index of factoring reliability = 0.928
RMSEA index = 0.178 and the 90 % confidence intervals are 0.139 0.221
BIC = 39.72
Fit based upon off diagonal values = 1
Measures of factor score adequacy
PA1
Correlation of (regression) scores with factors 0.96
Multiple R square of scores with factors 0.93
Minimum correlation of possible factor scores 0.85
Concatenate scores with other data
z_means['factor_score'] <- fa.none$scores
Run same anova analyses as above but on factor score
p = plotRidges(z_means, "condition", "factor_score", "", "Condition", "Mean Factor Score")
runaov("exp_subject_id","factor_score", z_means, "condition")
Anova Table (Type 3 tests)
Response: factor_score
Effect df MSE F ges p.value
1 condition 2.72, 543.46 1.29 11.85 *** .056 <.001
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘+’ 0.1 ‘ ’ 1
Sphericity correction method: GG
contrast estimate SE df t.ratio p.value
AV.Intended - AV.Random -0.0506 0.0916 200 -0.552 0.9428
AV.Intended - Audio 0.5237 0.1047 200 5.001 <.0001
AV.Intended - Visual 0.0774 0.1073 200 0.722 0.9428
AV.Random - Audio 0.5743 0.1058 200 5.429 <.0001
AV.Random - Visual 0.1280 0.1047 200 1.222 0.6691
Audio - Visual -0.4463 0.1300 200 -3.434 0.0029
P value adjustment: holm method for 6 tests
factorPlot = p + stat_compare_means(comparisons = my_comparisons, label = "p.signif", method = "t.test", paired="True", na.rm=TRUE)
factorPlot = factorPlot + labs(y = "Mean Factor Score (Aesthetic Experience)")
factorPlot
It basically mimics enjoyment results, as that item has highest
factor loading. But there was clearly something more interesting going
on with all of the small differences in the ANOVAs reported above
ratings = z_means[ , -which(names(z_means) %in% c("exp_subject_id","condition", "mean_corresp"))] # drop label columns and ones not using
ratings$mean_timespent = log(ratings$mean_timespent)
par(mfrow = c(3,1))
chart.Correlation(ratings, histogram=TRUE, pch=25, text.panel=labs)
fa.diagram(fa.none, digits=2, cut = .3, simple=TRUE)
#factorPlot
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayBmb3IgRmluaywgRmllaG4sIFdhbGQtRnVocm1hbm4gKDIwMjQpIGFuYWx5c2VzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKYXV0aG9yczogTGF1cmVuIEZpbmsgJiBIYW5uYWggRmllaG4KY29udGFjdDogZmlua2wxQG1jbWFzdGVyLmNhCi0tLQoKVGhpcyBub3RlYm9vayBhY2NvbXBhbmllcyB0aGUgbWFudXNjcmlwdDoKCkZpbmssIEZpZWhuICYgV2FsZC1GdWhybWFubiAoMjAyNCkuIFRoZSByb2xlIG9mIGF1ZGlvdmlzdWFsIGNvbmdydWVuY2UgaW4gYWVzdGhldGljIGFwcHJlY2lhdGlvbiBvZiBjb250ZW1wb3JhcnkgbXVzaWMgYW5kIHZpc3VhbCBhcnQuICpTY2llbnRpZmljIFJlcG9ydHMqLCA3MTM5OS4gRE9JOiBbaHR0cHM6Ly9kb2kub3JnLzEwLjEwMzgvczQxNTk4LTAyNC03MTM5OS15XShodHRwczovL2RvaS5vcmcvMTAuMTAzOC9zNDE1OTgtMDI0LTcxMzk5LXkpCgoqUHJlLXByaW50IGF2YWlsYWJsZSBhdDoqIFtvc2YuaW8vaGpnYzUvXShvc2YuaW8vaGpnYzUvKQoKSWYgdXNpbmcgYW55IGNvZGUgb3IgZGF0YSBmcm9tIHRoaXMgbm90ZWJvb2ssIHBsZWFzZSBjaXRlIHRoZSBwYXBlci4gCgpBZGRpdGlvbmFsIGNvZGUgYW5kIGluZm9ybWF0aW9uIGFjY29tcGFueWluZyB0aGlzIFIgbm90ZWJvb2sgYXJlIGF2YWlsYWJsZSBpbiB0aGUgYXNzb2NpYXRlZCBHaXRIdWIgcmVwb3NpdG9yeTogW2h0dHBzOi8vZ2l0aHViLmNvbS9sa2ZpbmsvS2VudGxlcl9NSU1fQmVoYXZpb3JdKGh0dHBzOi8vZ2l0aHViLmNvbS9sa2ZpbmsvS2VudGxlcl9NSU1fQmVoYXZpb3IpCgojIExvYWQgYW5kIHByZXByb2Nlc3MgZGF0YQpUdXJuIG9mZiB3YXJuaW5ncyBmb3IgY2xlYW5lciBzdWJtaXNzaW9uIGZpbGUuIE4uQi4gdXNlcnMgb2YgdGhpcyBmaWxlIHNob3VsZCB0dXJuIHdhcm5pbmdzIG9uIGZvciB0cm91Ymxlc2hvb3RpbmcKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9IAprbml0cjo6b3B0c19jaHVuayRzZXQod2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UpIApgYGAKCiMjIyBJbnN0YWxsIHJlcXVpcmVkIHBhY2thZ2VzLCBpZiBub3QgYWxyZWFkeSBpbnN0YWxsZWQKYGBge3J9Cmxpc3Qub2YucGFja2FnZXMgPC0gYygidGlkeXZlcnNlIiwgImdncHViciIsICJleiIsICJjb3JycGxvdCIsICJjYXIiLCAic3RhdHMiLCJQZXJmb3JtYW5jZUFuYWx5dGljcyIsICJhZmV4IiwgImVtbWVhbnMiLCAibWxtYSIsICJnZ3Bsb3QyIiwgImdnRXh0cmEiLCAicHN5Y2giLCAiZ2dwdWJyIiwgImhlcmUiLCAiZ3JpZEV4dHJhIiwgImdncmlkZ2VzIikKbmV3LnBhY2thZ2VzIDwtIGxpc3Qub2YucGFja2FnZXNbIShsaXN0Lm9mLnBhY2thZ2VzICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKClbLCJQYWNrYWdlIl0pXQppZihsZW5ndGgobmV3LnBhY2thZ2VzKSkgaW5zdGFsbC5wYWNrYWdlcyhuZXcucGFja2FnZXMpIApgYGAKCiMjIyBMb2FkIHBhY2thZ2VzIGFuZCBkYXRhCldlIHVzZSB0aGUgKmhlcmUqIHBhY2thZ2Ugc28gdGhhdCBhbGwgZmlsZSBwYXRocyBhcmUgcmVsYXRpdmUuIFVzZXJzIHNob3VsZCBiZSBzdXJlIG5vdCB0byBjaGFuZ2UgdGhlIGRpcmVjdG9yeSBzdHJ1Y3R1cmUgb2YgdGhlIHJlcG9zaXRvcnkuIApCeSBkZWZhdWx0LCBmaWd1cmVzIHdpbGwgYmUgcGxvdHRlZCBpbiBsaW5lLiBJZiB5b3Ugd2FudCB0byBzYXZlIHRoZSBmaWd1cmVzIHRvIGEgZm9sZGVyIG9uIHlvdXIgbG9jYWwgbWFjaGluZSwgc2V0IG9wID0gMS4gCmBgYHtyfQpoZXJlOjppX2FtKCJGaW5rX0tlbnRsZXJfYW5hbHlzZXMuUm1kIikKbGlicmFyeShoZXJlKQpzb3VyY2UoaGVyZSgiZGVwZW5kZW5jaWVzLlIiKSkKZGF0YSA8LSByZWFkLmNzdihoZXJlKCJkYXRhLmNzdiIpKSAKZmlnX3BhdGggPC0gaGVyZSgiZmlndXJlcy8iKSAjIHBhdGggdG8gc2F2ZSBnZW5lcmF0ZWQgZmlndXJlcyB0bwpvcCA9IDAgIyBmbGFnIGlmIHdhbnQgdG8gc2F2ZSBvdXRwdXQgcGxvdHMgdG8gZmlsZXMgKDEpIG9yIHBsb3QgaW5saW5lICgwKQpgYGAKCiMjIyBQcmUtcHJvY2VzcyB0aGUgZGF0YQpDbGVhbiB1cCB2YXJpYWJsZSBuYW1lcywgYWRkIGNvbWJpbmVkIGNvbHVtbnMgb2YgaW50ZXJlc3QsIGRyb3AgdW5uZWNlc3NhcnkgY29sdW1ucwpgYGB7cn0KIyByZW1vdmUgdmFyaWFibGVzIHdlIGRvbid0IG5lZWQgKExhYnZhbmNlZCBzdGlsbCBvdXRwdXR0aW5nIG9sZCB2YXJzIGZyb20gZWFybGllciBleHAuIHZlcnNpb24pCmRhdGFfbmV3IDwtIHN1YnNldChkYXRhLCBzZWxlY3QgPSAtIGMoQmxvY2tfTmFtZSwgVGFza19OciwgYXVkX3RlbmRfdW5peCwgYXVkX3RzLCBhdWRfdHNfdW5peCwgY29uZGkzLCBjb3B5X29mX2NvbmRpMiwgY29weV9vZl9jb25kaSwgZnJhbWVfZW5kX3VuaXgsIGZyYW1lX3J0LCBOYW1lLkF1ZGlvLl9jb3B5XzRiNDksIE5hbWUuQXVkaW8uX2NvcHlfOTNhNywgTmFtZS5BdWRpby5fY29weV9iZDZmLCBOYW1lLkF1ZGlvLl9jb3B5X2M5NTgsIE5hbWUuQXVkaW8uX2NvcHlfYzk2YywgTmFtZS5BdWRpby4sIHN1YmpfY291bnRlcl9nbG9iYWwsIHN1YmpfY291bnRlcl9wZXJfZ3JvdXAsIHRpbWVfZGVsYXlfb2Zmc2V0LCB0aW1lX21lYXN1cmVfc3RkLCBwaXhlbERlbnNpdHlQZXJNTSx1bmxvY2tlZCkpCgojIGZpbHRlciBvdXQgcGVvcGxlIHdobyBoYXZlIHNlZW4vaGVhcmQgc3RpbXVsaSBiZWZvcmUgKHNvbWUgb2Ygb3VyIHBpbG90cykgb3Igd2hvIGRvbid0IGhhdmUgbm9ybWFsIGhlYXJpbmcgLyB2aXNpb24KZXhwb3NlZCA9IHRhYmxlKGRhdGEkcHJldl9leHBvc3VyZSkKZGF0YV9uZXcgPC0gZGF0YV9uZXdbLWMod2hpY2goZGF0YV9uZXckcHJldl9leHBvc3VyZSA9PSAib3B0aW9uXzAiKSksIF0Kbm9ybVNlbnNlcyA9IHRhYmxlKGRhdGEkTm9ybWFsLlZpc2lvbi4pICMgbm8gb25lIHdpdGhvdXQKZGF0YV9uZXcgPC0gZGF0YV9uZXdbLWMod2hpY2goZGF0YV9uZXckY29tcGxldGVkID09ICJubyIpKSwgXSAjIHJlbW92ZSBpbmNvbXBsZXRlcwpkYXRhID0gZGF0YV9uZXcgIyBvdmVyd3JpdGUgb2xkIGRhdGEgc28gY2FuJ3QgYWNjaWRlbnRhbGx5IHVzZSBpdAoKI2NyZWF0ZSBhIGRhdGFmcmFtZSBqdXN0IHdpdGggdGhlIHRhc2sgYmxvY2sgKGZvciBmdXJ0aGVyIGFuYWx5c2lzICkKZGF0YV90YXNrIDwtIGRhdGFfbmV3ICU+JSAKICBzZWxlY3QoVHJpYWxfTnIsIFRyaWFsX0lkLCBjb3JyZXNwb25kZW5jZV8sIGVuam95XywgRnJhbWUuVGltZS4sIGludGVyZXN0aW5nbmVzc18sIG1vb2QuY29uZ3J1ZW5jeV8sIG1vdmVfLCBzdWJqZWN0X2NvZGUsIEJsb2NrX05yLCBncm91cF9uYW1lLCBleHBfc3ViamVjdF9pZCkKCmRhdGFfdGFzayA8LSBkYXRhX3Rhc2tbLCBjKCJleHBfc3ViamVjdF9pZCIsICJCbG9ja19OciIsICJUcmlhbF9OciIsICJUcmlhbF9JZCIsImdyb3VwX25hbWUiLCAiRnJhbWUuVGltZS4iLCAiY29ycmVzcG9uZGVuY2VfIiwgImVuam95XyIsICJpbnRlcmVzdGluZ25lc3NfIiwgIm1vb2QuY29uZ3J1ZW5jeV8iLCAibW92ZV8iICldCgojIHB1dCB0aW1lIHNwZW50IGluIHNlY3MgKGluc3RlYWQgb2YgbXMpCmRhdGFfdGFzayRGcmFtZS5UaW1lLiA9IGRhdGFfdGFzayRGcmFtZS5UaW1lLiAvIDEwMDAKCiMgQWRkIGNvbHVtbiBmb3IgY29uZGl0aW9uIAojIFRyaWFsX0lkIHRlbGxzIHdoaWNoIGNvbmRpdGlvbiBpdCBpcyAoMSAtIDQgPSBBOyA1IC0gOCA9IFY7IDkgLSAxMiA9IEFWSTsgMTMgLSAxNiA9IEFWUikKIyB3aXRoIFRyaWFsX0lkIGFuZCB0aGUgZ3JvdXAgbnVtYmVyIHdlIGNhbiBsb29rIHdoaWNoIHNwZWNpZmljIHN0aW11bGkgYXJlIHVzZWQgCmRhdGFfdGFzayRUcmlhbF9JZCA9IGFzLm51bWVyaWMoZGF0YV90YXNrJFRyaWFsX0lkKQpkYXRhX3Rhc2skY29uZGl0aW9uID0gTkEKZGF0YV90YXNrJGNvbmRpdGlvbltkYXRhX3Rhc2skVHJpYWxfSWQgPD0gNF0gPSAnQXVkaW8nIApkYXRhX3Rhc2skY29uZGl0aW9uW2RhdGFfdGFzayRUcmlhbF9JZCA+PSA1ICYgZGF0YV90YXNrJFRyaWFsX0lkIDw9IDhdID0gJ1Zpc3VhbCcgCmRhdGFfdGFzayRjb25kaXRpb25bZGF0YV90YXNrJFRyaWFsX0lkID49IDkgJiBkYXRhX3Rhc2skVHJpYWxfSWQgPD0gMTJdID0gJ0FWLUludGVuZGVkJyAKZGF0YV90YXNrJGNvbmRpdGlvbltkYXRhX3Rhc2skVHJpYWxfSWQgPj0gMTNdID0gJ0FWLVJhbmRvbScgCgojIGNyZWF0ZSBzdWJzZXQgZGF0YSBmcmFtZSBvZiB0YXNrIGRhdGEKI2p1c3Qga2VlcCBCbG9jayBOdW1iZXIgPSAyICh0aGVzZSBhcmUgdGhlIGV4cGVyaW1lbnRhbCB0cmlhbHMpCmRhdGFfdGFzayA8LSBkYXRhX3Rhc2sgJT4lCiAgZmlsdGVyKEJsb2NrX05yID09IDIpCgojIGNyZWF0ZSBzdWJzZXQgZGF0YSBmcmFtZSB3aXRoIGp1c3QgcGFydGljaXBhbnQgaW5mbwpkYXRhX3BhcnRpY2lwYW50IDwtIGRhdGFfbmV3ICU+JQogIHNlbGVjdChleHBfc3ViamVjdF9pZCwgZ3JvdXBfbmFtZSwgYWdlX2lucHV0LCBnZW5kZXIsIGNvdW50cnlfY3VycmVudCwgY291bnRyeV9ob21lLCBNb2RhbGl0eV9QcmVmZXJlbmNlLCBPbGxlbiwgb3ZlcmFsbF9lbmpveSwgInByZXZfZXhwb3N1cmUiLCByZWFsV29ybGRMaWtlbGlob29kKQoKZGF0YV9wYXJ0aWNpcGFudCA9IG5hLm9taXQoZGF0YV9wYXJ0aWNpcGFudCkKCiMgY2FsY3VsYXRlIGFyZWEgc2NvcmVzIGZvciBlYWNoIHBhcnRpY2lwYW50IGFuZCBhZGQgdG8gcGFydGljaXBhbnQgZGF0YQojIEFSZUEgc2NhbGUgc2NvcmluZwojQWVzdGhldGljIEFwcHJlY2lhdGlvbjogSXRlbXMgMSwgMiwgMywgNCwgNiwgOSwgMTMsIDE0CiNJbnRlbnNlIEFlc3RoZXRpYyBFeHBlcmllbmNlOiBJdGVtcyA4LCAxMSwgMTIsIDEzCiNDcmVhdGl2ZSBCZWhhdmlvcjogSXRlbXMgNSwgNywgMTAKYXJlYV9kYXRhID0gZGF0YVtkYXRhJFRhc2tfTmFtZSA9PSAnQVJlQScsXQphcmVhX2RhdGEkYXJlYV9hZXNfYXBwcmVjID0gYXJlYV9kYXRhJGFyZWFfMDEgKyBhcmVhX2RhdGEkYXJlYV8wMiArIGFyZWFfZGF0YSRhcmVhXzAzICsgYXJlYV9kYXRhJGFyZWFfMDQgKyBhcmVhX2RhdGEkYXJlYV8wNiArIGFyZWFfZGF0YSRhcmVhXzA5ICsgYXJlYV9kYXRhJGFyZWFfMTMgKyBhcmVhX2RhdGEkYXJlYV8xNAphcmVhX2RhdGEkYXJlYV9hZXNfYXBwcmVjID0gYXJlYV9kYXRhJGFyZWFfYWVzX2FwcHJlYyAvIDggIyBkaXZpZGUgYnkgbnVtIG9mIGl0ZW1zCmFyZWFfZGF0YSRhcmVhX2ludGVuc2VfYWVzX2V4cCA9IGFyZWFfZGF0YSRhcmVhXzA4ICsgYXJlYV9kYXRhJGFyZWFfMTEgKyBhcmVhX2RhdGEkYXJlYV8xMiArIGFyZWFfZGF0YSRhcmVhXzEzCmFyZWFfZGF0YSRhcmVhX2ludGVuc2VfYWVzX2V4cCA9IGFyZWFfZGF0YSRhcmVhX2ludGVuc2VfYWVzX2V4cCAvIDQKYXJlYV9kYXRhJGFyZWFfY3JlYXRpdmVfYmVoID0gYXJlYV9kYXRhJGFyZWFfMDUgKyBhcmVhX2RhdGEkYXJlYV8wNyArIGFyZWFfZGF0YSRhcmVhXzEwCmFyZWFfZGF0YSRhcmVhX2NyZWF0aXZlX2JlaCA9IGFyZWFfZGF0YSRhcmVhX2NyZWF0aXZlX2JlaCAvIDMKYXJlYV9kYXRhJGFyZWFfY29tcG9zaXRlID0gKGFyZWFfZGF0YSRhcmVhX2Flc19hcHByZWMgKyBhcmVhX2RhdGEkYXJlYV9pbnRlbnNlX2Flc19leHAgKyBhcmVhX2RhdGEkYXJlYV9jcmVhdGl2ZV9iZWgpIC8gMwoKIyBhZGQgYXJlYSBzY29yZXMgdG8gbWVhbiB0YWJsZSAoam9pbiBiYXNlZCBvbiBleHBfc3Vial9pZCkKYXJlYV9kYXRhID0gYXJlYV9kYXRhWyxjKCJleHBfc3ViamVjdF9pZCIsICJhcmVhX2Flc19hcHByZWMiLCAiYXJlYV9pbnRlbnNlX2Flc19leHAiLCAiYXJlYV9jcmVhdGl2ZV9iZWgiLCAiYXJlYV9jb21wb3NpdGUiKV0KCiMgbWVyZ2UgYXJlYSB3aXRoIHBhcnRpY2lwYW50IGRmCmRhdGFfcGFydGljaXBhbnQgPSBtZXJnZSh4PWRhdGFfcGFydGljaXBhbnQseT1hcmVhX2RhdGEsIAogICAgICAgICAgICAgICAgICAgICAgICAgYnk9ImV4cF9zdWJqZWN0X2lkIiwgYWxsPVRSVUUpCgojIGNsZWFuIHVwIG1vZGFsaXR5IHByZWYgZGF0YSB0byBoYXZlIG1lYW5pbmdmdWwgbGFiZWxzCnRlbXAgPSBkYXRhX3BhcnRpY2lwYW50JE1vZGFsaXR5X1ByZWZlcmVuY2UKdGVtcCA9IGdzdWIoIm9wdGlvbl8wIiwgInByZWZlcl9hdWRpbyIsIHRlbXApCnRlbXAgPSBnc3ViKCJvcHRpb25fMSIsICJwcmVmZXJfdmlzdWFsIiwgdGVtcCkKdGVtcCA9IGdzdWIoIm9wdGlvbl8yIiwgInByZWZlcl9hdWRpb3Zpc3VhbCIsIHRlbXApCnRlbXAgPSBnc3ViKCJvcHRpb25fMyIsICJub19wcmVmZXJlbmNlIiwgdGVtcCkKZGF0YV9wYXJ0aWNpcGFudCRNb2RhbGl0eV9QcmVmZXJlbmNlX2NhdCA9IHRlbXAKCiMgam9pbiBwYXJ0aWNpcGFudCBpbmZvIHdpdGggdHJpYWwgbGV2ZWwgZGF0YSBmb3IgZmluYWwgZnVsbCBkYXRhIGZyYW1lCmZ1bGxfZGF0YSA9IG1lcmdlKHg9ZGF0YV90YXNrLHk9ZGF0YV9wYXJ0aWNpcGFudCwgCiAgICAgICAgICAgICAgICAgIGJ5PSJleHBfc3ViamVjdF9pZCIsIGFsbD1UUlVFKQpgYGAKCkNoZWNrIHBhcnRpY2lwYW50IG51bWJlciBkaXNjcmVwZW5jaWVzIGJldHdlZW4gdGFzayBkYXRhIGFuZCBkZW1vIGRhdGEKYGBge3J9CiMgc29tZXRoaW5nIHdyb25nISBvbmx5IDE5NSBvYnMgZm9yIHBlb3BsZSB3aG8gc2F3IGVuZFFzID8hICh0aGVzZSB3ZXJlIHJlcXVpcmVkIHF1ZXN0aW9ucy4gbm90IHN1cmUgaG93IGxhYnZhbmNlZCBsZXQgdGhhdCB0aHJvdWdoKQojIHRhYmxlKGRhdGFfbmV3JFRhc2tfTmFtZSkKCiMgY2hlY2sgd2hhdCBnb2luZyBvbiB3aXRoIDYgc3VicwpjaGVjayA9IHN1YnNldChmdWxsX2RhdGEsIGlzLm5hKGZ1bGxfZGF0YSRPbGxlbikpCmNoZWNrMiA9IHN1YnNldChkYXRhLCBpcy5uYShmdWxsX2RhdGEkT2xsZW4pKQoKbnN1YnMgPSBsZW5ndGgodW5pcXVlKGZ1bGxfZGF0YSRleHBfc3ViamVjdF9pZCkpCm5zdWJzX21pc3NpbmdEZW1vID0gbGVuZ3RoKHVuaXF1ZShjaGVjayRleHBfc3ViamVjdF9pZCkpCmBgYApJdCBzZWVtcyA2IHBhcnRpY2lwYW50cyBuZXZlciBnb3QgdGhlIGVuZGluZyBxdWVzdGlvbnMuIFdlIGNhbiBpbmNsdWRlIHRoZW0gZm9yIGFsbCB0cmlhbCBhbmFseXNlcyBidXQgdGhleSB3aWxsIGJlIGV4Y2x1ZGVkIGZyb20gcGVyc29uLWxldmVsIGFuYWx5c2VzCgojIFBlcnNvbi1sZXZlbCBhbmFseXNlcwoKIyMjIEV4cGxvcmUgZGVtb2dyYXBoaWMgZGF0YQpgYGB7cn0KZ2VuZGVyX2Rpc3QgPSB0YWJsZShkYXRhX3BhcnRpY2lwYW50JGdlbmRlcikKYWdlX21lYW4gPSBtZWFuKGRhdGFfcGFydGljaXBhbnQkYWdlX2lucHV0LCBuYS5ybSA9IFRSVUUpCmFnZV9zdGQgPSBzZChkYXRhX3BhcnRpY2lwYW50JGFnZV9pbnB1dCwgbmEucm0gPSBUUlVFKQpuY291bnRyaWVzID0gbGVuZ3RoKHVuaXF1ZShkYXRhX3BhcnRpY2lwYW50JGNvdW50cnlfY3VycmVudCkpCmNvdW50cmllcyA9IHRhYmxlKGRhdGFfcGFydGljaXBhbnQkY291bnRyeV9jdXJyZW50KQptb2RhbGl0eV9wcmVmID0gdGFibGUoZGF0YV9wYXJ0aWNpcGFudCRNb2RhbGl0eV9QcmVmZXJlbmNlX2NhdCkgCgpwcmludCgiR2VuZGVyOiBtYW4sIHdvbWFuLCBub24tYmluYXJ5LCBwcmVmZXIgbm90IHRvIHNheSIpCnByaW50KGdlbmRlcl9kaXN0KQoKcHJpbnQoIkFnZSAobWVhbiwgc2QsIG1pbiwgbWF4KSIpCnByaW50KGFnZV9tZWFuKQpwcmludChhZ2Vfc3RkKQpwcmludChtaW4oZGF0YV9wYXJ0aWNpcGFudCRhZ2VfaW5wdXQsIG5hLnJtID0gVFJVRSkpCnByaW50KG1heChkYXRhX3BhcnRpY2lwYW50JGFnZV9pbnB1dCwgbmEucm0gPSBUUlVFKSkKCnByaW50KCJVbmlxdWUgY291bnRyaWVzOiIpCnByaW50KG5jb3VudHJpZXMpCnByaW50KGNvdW50cmllcykKCnByaW50KCJBUmVBIChtZWFuLCBzZCwgbWluLCBtYXgpOiIpCnByaW50KG1lYW4oZGF0YV9wYXJ0aWNpcGFudCRhcmVhX2NvbXBvc2l0ZSkpCnByaW50KHNkKGRhdGFfcGFydGljaXBhbnQkYXJlYV9jb21wb3NpdGUpKQpwcmludChtaW4oZGF0YV9wYXJ0aWNpcGFudCRhcmVhX2NvbXBvc2l0ZSkpCnByaW50KG1heChkYXRhX3BhcnRpY2lwYW50JGFyZWFfY29tcG9zaXRlKSkKCnByaW50KCJBUmVBIEFBIChtZWFuLCBzZCwgbWluLCBtYXgpOiIpCnByaW50KG1lYW4oZGF0YV9wYXJ0aWNpcGFudCRhcmVhX2Flc19hcHByZWMpKQpwcmludChzZChkYXRhX3BhcnRpY2lwYW50JGFyZWFfYWVzX2FwcHJlYykpCnByaW50KG1pbihkYXRhX3BhcnRpY2lwYW50JGFyZWFfYWVzX2FwcHJlYykpCnByaW50KG1heChkYXRhX3BhcnRpY2lwYW50JGFyZWFfYWVzX2FwcHJlYykpCgpwcmludCgiQVJlQSBJQUUgKG1lYW4sIHNkLCBtaW4sIG1heCk6IikKcHJpbnQobWVhbihkYXRhX3BhcnRpY2lwYW50JGFyZWFfaW50ZW5zZV9hZXNfZXhwKSkKcHJpbnQoc2QoZGF0YV9wYXJ0aWNpcGFudCRhcmVhX2ludGVuc2VfYWVzX2V4cCkpCnByaW50KG1pbihkYXRhX3BhcnRpY2lwYW50JGFyZWFfaW50ZW5zZV9hZXNfZXhwKSkKcHJpbnQobWF4KGRhdGFfcGFydGljaXBhbnQkYXJlYV9pbnRlbnNlX2Flc19leHApKQoKcHJpbnQoIkFSZUEgQ0IgKG1lYW4sIHNkLCBtaW4sIG1heCk6IikKcHJpbnQobWVhbihkYXRhX3BhcnRpY2lwYW50JGFyZWFfY3JlYXRpdmVfYmVoKSkKcHJpbnQoc2QoZGF0YV9wYXJ0aWNpcGFudCRhcmVhX2NyZWF0aXZlX2JlaCkpCnByaW50KG1pbihkYXRhX3BhcnRpY2lwYW50JGFyZWFfY3JlYXRpdmVfYmVoKSkKcHJpbnQobWF4KGRhdGFfcGFydGljaXBhbnQkYXJlYV9jcmVhdGl2ZV9iZWgpKQpgYGAKCiMjIyBQbG90IGV4cGVyaW1lbnQtcmVsYXRlZCBwZXJzb24tbGV2ZWwgdmFyaWFibGVzCmBgYHtyfQojIGNsZWFuIHVwIGFuZCBwbG90IG9sbGVuIGRhdGEKb2xsZW5TY2FsZSA9IGMoIm5vbi1tdXNpY2lhbiIsICJtdXNpYy1sb3Zpbmcgbm9uLW11c2ljaWFuIiwgImFtYXRldXIgbXVzaWNpYW4iLCAic2VyaW91cyBhbWF0ZXVyIG11c2ljaWFuIiwgInNlbWktcHJvZmVzc2lvbmFsIG11c2ljaWFuIiwgInByb2Zlc3Npb25hbCBtdXNpY2lhbiIpCgpvbGxlbiA9IHRhYmxlKGRhdGFfcGFydGljaXBhbnQkT2xsZW4pCm9sbGVuID0gZGF0YS5mcmFtZShvbGxlbikKbmFtZXMob2xsZW4pID0gYygiUmVzcG9uc2UiLCJQYXJ0aWNpcGFudHMiKQpvbGxlbiRSZXNwb25zZSA9IG9sbGVuU2NhbGVbMTo1XSAjIG5vYm9keSBjaG9zZSBwcm9mZXNzaW9uYWwhCgpwcmludChvbGxlbikKZGVzY3JpYmUob2xsZW4kUGFydGljaXBhbnRzKQoKIyBvcmRlciBPbGxlbiBwcm9wZXJseQpvbGxlbiA8LSB3aXRoaW4ob2xsZW4sIFJlc3BvbnNlIDwtIGZhY3RvcihSZXNwb25zZSwgbGV2ZWxzPW9sbGVuU2NhbGUpKQoKIyBjcmVhdGUgYmFycGxvdAojIHBuZygiS2VudGxlcl9vbGxlbi5wbmciLCB1bml0cz0iaW4iLCB3aWR0aD04LCBoZWlnaHQ9NSwgcmVzPTMwMCkKZ2dwbG90KG9sbGVuLCBhZXMoeD1SZXNwb25zZSwgeT1QYXJ0aWNpcGFudHMpKSArIAogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArIGNvb3JkX2ZsaXAoKSArIHRoZW1lX2NsYXNzaWMoKSArIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSkKCiMgUGxvdCBhcmVhIGRhdGEKZ2dwbG90KGRhdGFfcGFydGljaXBhbnQsIGFlcyh4PWFyZWFfY29tcG9zaXRlKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMjApICsgZ2d0aXRsZSgiQVJlQSBjb21wb3NpdGUgc2NvcmUiKQoKCiMgUGxvdCBlbmpveW1lbnQgZGF0YQpnZ3Bsb3QoZGF0YV9wYXJ0aWNpcGFudCwgYWVzKHg9b3ZlcmFsbF9lbmpveSkpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDI1KSArIGdndGl0bGUoIk92ZXJhbGwgZW5qb3ltZW50IG9mIHRoZSBleHBlcmltZW50IikKCmdncGxvdChkYXRhX3BhcnRpY2lwYW50LCBhZXMoeD1yZWFsV29ybGRMaWtlbGlob29kKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMjUpICsgZ2d0aXRsZSgiTGlrZWxpaG9vZCBvZiBzZWVraW5nIHNpbWlsYXIgcGllY2VzIGluIHJlYWwgd29ybGQiKQoKcHJpbnQoIkVuam95bWVudCAobWVhbiwgc2QpIikKcHJpbnQobWVhbihkYXRhX3BhcnRpY2lwYW50JG92ZXJhbGxfZW5qb3ksIG5hLnJtPVQpKQpwcmludChzZChkYXRhX3BhcnRpY2lwYW50JG92ZXJhbGxfZW5qb3ksIG5hLnJtPVQpKQoKcHJpbnQoIkxpa2VsaWhvb2QgKG1lYW4sIHNkKSIpCnByaW50KG1lYW4oZGF0YV9wYXJ0aWNpcGFudCRyZWFsV29ybGRMaWtlbGlob29kLCBuYS5ybT1UKSkKcHJpbnQoc2QoZGF0YV9wYXJ0aWNpcGFudCRyZWFsV29ybGRMaWtlbGlob29kLCBuYS5ybT1UKSkKCiMgcGxvdCByZWxhdGlvbiBiZXR3ZWVuIGVuam95bWVudCBhbmQgbGlrZWxpaG9vZApwIDwtIGdncGxvdChkYXRhX3BhcnRpY2lwYW50LCBhZXMoeD1vdmVyYWxsX2Vuam95LCB5PXJlYWxXb3JsZExpa2VsaWhvb2QpKSArCiAgZ2VvbV9wb2ludCgpICsgZ2VvbV9zbW9vdGgobWV0aG9kPWxtICwgY29sb3I9ImJsYWNrIiwgZmlsbD0iZ3JheSIsIHNlPVRSVUUpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArIHRoZW1lX2NsYXNzaWMoKQoKIyBDdXN0b20gbWFyZ2luYWwgcGxvdHM6CnAyIDwtIGdnTWFyZ2luYWwocCwgdHlwZT0iZGVuc2lncmFtIiwgZmlsbCA9ICJncmF5IikgCnAyIAoKIyBTZWxmLXJlcG9ydGVkIG1vZGFsaXR5IHByZWZzCiMgY3JlYXRlIGJhcnBsb3Qgb2YgbW9kYWxpdHkgcHJlZmVyZW5jZXMKbXByZWYgPSBkYXRhLmZyYW1lKG1vZGFsaXR5X3ByZWYpCm5hbWVzKG1wcmVmKSA9IGMoIlJlc3BvbnNlIiwiUGFydGljaXBhbnRzIikKbXByZWYkcGVyY2VudCA9IG1wcmVmJFBhcnRpY2lwYW50cyAvIHN1bShtcHJlZiRQYXJ0aWNpcGFudHMpCgoKIyBwbmcoIktlbnRsZXJfcHJlZmVyZW5jZS5wbmciLCB1bml0cz0iaW4iLCB3aWR0aD04LCBoZWlnaHQ9NSwgcmVzPTMwMCkgCmdncGxvdChtcHJlZiwgYWVzKHg9UmVzcG9uc2UsIHk9UGFydGljaXBhbnRzKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKyBjb29yZF9mbGlwKCkgKyB0aGVtZV9jbGFzc2ljKCkgKyB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCkpCmBgYAojIyMgUGxvdCByZWxhdGlvbnNoaXAgYmV0d2VlbiBhbGwgcGVyc29uLWxldmVsIHZhcnMKYGBge3J9CiMgY3JlYXRlIGRhdGEgZnJhbWUgZm9yIGNvcnJlbGF0aW9uCiMgbmVlZCB0byBjb252ZXJ0IGNhdGVnb3JpY2FsIHRvIG51bWVyaWMgCmNvcnJkZiA9IGRhdGFfcGFydGljaXBhbnRbICwgd2hpY2gobmFtZXMoZGF0YV9wYXJ0aWNpcGFudCkgJWluJSBjKCJPbGxlbiIsICJNb2RhbGl0eV9QcmVmZXJlbmNlIiwgIm92ZXJhbGxfZW5qb3kiLCAicmVhbFdvcmxkTGlrZWxpaG9vZCIsICJhcmVhX2Flc19hcHByZWMiLCAiYXJlYV9pbnRlbnNlX2Flc19leHAiLCAiYXJlYV9jcmVhdGl2ZV9iZWgiLCAiYXJlYV9jb21wb3NpdGUiKSldIAoKY29ycmRmJE1vZGFsaXR5X1ByZWZlcmVuY2UgPSBhcy5udW1lcmljKGFzLmZhY3Rvcihjb3JyZGYkTW9kYWxpdHlfUHJlZmVyZW5jZSkpCmNvcnJkZiRPbGxlbiA9IGFzLm51bWVyaWMoYXMuZmFjdG9yKGNvcnJkZiRPbGxlbikpCgpjaGFydC5Db3JyZWxhdGlvbihjb3JyZGYsIGhpc3RvZ3JhbT1UUlVFLCBwY2g9MjUsIHRleHQucGFuZWw9bGFicykKYGBgCgojIENvbmRpdGlvbi1sZXZlbCBhbmFseXNlcwoKIyMjIENyZWF0ZSB0YWJsZXMgb2YgbWVhbnMKWi1zY29yZSByYXRpbmdzIGRhdGEgd2l0aGluIHNjYWxlLCBwYXJ0aWNpcGFudCAgCkNhbGN1bGF0ZSB0YWJsZSBvZiBtZWFucyBmb3IgYWxsIHBhcnRpY2lwYW50cyAvIGNvbmRpdGlvbnMKLSBkbyB0aGlzIGZvciBib3RoIHotc2NvcmVkIGFuZCByYXcgZGF0YSBpbiBjYXNlIHdlIHdhbnQgdG8gY29tcGFyZQpgYGB7cn0KIyBjcmVhdGUgenNjb3JlIGZ1bmN0aW9uCnpzY29yZSA8LSBmdW5jdGlvbihpbnB1dCl7CiAgb3V0ID0gKGlucHV0IC0gbWVhbihpbnB1dCkpL3NkKGlucHV0KQp9CgojIHpzY29yZSBkYXRhCnpzY29yZWQgPSBkYXRhX3Rhc2sgJT4lCiAgZ3JvdXBfYnkoZXhwX3N1YmplY3RfaWQpICU+JQogIG11dGF0ZSh6X2Vuam95ID0genNjb3JlKGVuam95XyksIHpfaW50ZXJlc3RpbmcgPSB6c2NvcmUoaW50ZXJlc3RpbmduZXNzXyksIHpfbW9vZF9jb25nID0genNjb3JlKG1vb2QuY29uZ3J1ZW5jeV8pLCB6X21vdmVkID0genNjb3JlKG1vdmVfKSkKIyBOT1RFIHpzY29yaW5nIGNvcnJlc3BvbmRlbmNlIG5lZWRzIHRvIGJlIGRvbmUgb25seSBmb3IgQVYgY29uZGl0aW9ucwoKIyBnZXQgbWVhbnMgb2YgenNjb3JlZCBkYXRhCnpfbWVhbnMgPSB6c2NvcmVkICU+JQogIGdyb3VwX2J5KGV4cF9zdWJqZWN0X2lkLCBjb25kaXRpb24pICU+JQogIHN1bW1hcmlzZShtZWFuX3RpbWVzcGVudCA9IG1lYW4oRnJhbWUuVGltZS4pLCBtZWFuX2Vuam95ID0gbWVhbih6X2Vuam95KSwgbWVhbl9pbnRlcmVzdGluZyA9IG1lYW4oel9pbnRlcmVzdGluZyksIG1lYW5fbW9vZF9jb25nID0gbWVhbih6X21vb2RfY29uZyksIG1lYW5fbW92ZWQgPSBtZWFuKHpfbW92ZWQpKQoKCiMgZ2V0IG1lYW5zIG9mIHpzY29yZWQgZGF0YQojIHpfbWVhbnNfcGFydGljaXBhbnQgPSB6X21lYW5zICU+JQojICAgZ3JvdXBfYnkoZXhwX3N1YmplY3RfaWQpICU+JQojICAgc3VtbWFyaXNlKG1lYW5fdGltZXNwZW50ID0gbWVhbihtZWFuX3RpbWVzcGVudCksIG1lYW5fZW5qb3kgPSBtZWFuKG1lYW5fZW5qb3kpLCBtZWFuX2ludGVyZXN0aW5nID0gbWVhbihtZWFuX2ludGVyZXN0aW5nKSwgbWVhbl9tb29kX2NvbmcgPSBtZWFuKG1lYW5fbW9vZF9jb25nKSwgbWVhbl9tb3ZlZCA9IG1lYW4obWVhbl9tb3ZlZCkpCiMgCgojIGdldCByYXcgbWVhbnMgaW4gY2FzZSB3YW50IHRvIGNvbXBhcmUgdG8genNjb3JlZCBkYXRhCm1lYW5zID0gZGF0YV90YXNrICU+JQogIGdyb3VwX2J5KGV4cF9zdWJqZWN0X2lkLCBjb25kaXRpb24pICU+JQogIHN1bW1hcmlzZShtZWFuX3RpbWVzcGVudCA9IG1lYW4oRnJhbWUuVGltZS4pLCBtZWFuX2Vuam95ID0gbWVhbihlbmpveV8pLCBtZWFuX2ludGVyZXN0aW5nID0gbWVhbihpbnRlcmVzdGluZ25lc3NfKSwgbWVhbl9tb29kX2NvbmcgPSBtZWFuKG1vb2QuY29uZ3J1ZW5jeV8pLCBtZWFuX21vdmVkID0gbWVhbihtb3ZlXyksIG1lYW5fY29ycmVzcCA9IG1lYW4oY29ycmVzcG9uZGVuY2VfKSkKCiMgZ2V0IHJhdyBzZHMgaW4gY2FzZSB3YW50IHRvIGNvbXBhcmUgdG8genNjb3JlZCBkYXRhCnNkcyA9IGRhdGFfdGFzayAlPiUKICBncm91cF9ieShleHBfc3ViamVjdF9pZCwgY29uZGl0aW9uKSAlPiUKICBzdW1tYXJpc2UobWVhbl90aW1lc3BlbnQgPSBzZChGcmFtZS5UaW1lLiksIG1lYW5fZW5qb3kgPSBzZChlbmpveV8pLCBtZWFuX2ludGVyZXN0aW5nID0gc2QoaW50ZXJlc3RpbmduZXNzXyksIG1lYW5fbW9vZF9jb25nID0gc2QobW9vZC5jb25ncnVlbmN5XyksIG1lYW5fbW92ZWQgPSBzZChtb3ZlXyksIG1lYW5fY29ycmVzcCA9IHNkKGNvcnJlc3BvbmRlbmNlXykpCgpgYGAKCgojIyMgQ3JlYXRlIGN1c3RvbSBmdW5jdGlvbnMgZm9yIGFuYWx5c2lzIGFuZCBwbG90dGluZwpXZSBoYXZlIG11bHRpcGxlIERWcyBvbiB3aGljaCB3ZSB3YW50IHRvIHJ1biB0aGUgc2FtZSB0eXBlIG9mIGFuYWx5c2lzCmBgYHtyfQojIEZ1bmN0aW9uIHRvIHBsb3QgdmlvbGlucyBmb3IgZWFjaCBjb25kaXRpb24KIyBJbnB1dDogZGF0YWZyYW1lLCB2YXJpYWJsZSB0byBwbG90LCB0aXRsZSBmb3IgcGxvdApwbG90VmlvbGluID0gZnVuY3Rpb24oZGF0YSwgZ3JvdXB2YXIsIHZhciwgdGl0c3RyLCB4bGFiLCB5bGFiKXsKICAKICAjIGRlZmluZSBjb2xvcnMKICBBVlIgPSAnIzhjMWFmZicKICBBVkkgPSAnI2NjOTlmZicKICBWID0gJyNmZjRkNGQnCiAgQSA9ICcjNjY5OWZmJwogIG91cmNvbG9ycyA9IGMoQSwgQVZJLCBBVlIsIFYpCiAgCiAgIyBvbmx5IEFWIGNvbmRpdGlvbnMgcmVsZXZhbnQKICBpZiAodmFyID09ICJ6X2NvcnJlc3AiKXsKICAgIG91cmNvbG9ycyA9IGMoQVZJLCBBVlIpIAogIH0KICAKICAjIFBsb3QKICB2YXIgPSBzeW0odmFyKQogIGdyb3VwdmFyID0gc3ltKGdyb3VwdmFyKQoKICBwbCA9IGRhdGEgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9ISFncm91cHZhciwgeT0hIXZhciwgZmlsbD0hIWdyb3VwdmFyKSkgKwogICAgZ2VvbV92aW9saW4obGVnZW5kID0gRkFMU0UsIHRyaW0gPSBGQUxTRSwgYWRqdXN0ID0gMSwgZHJhd19xdWFudGlsZXMgPSBjKDAuMjUsIDAuNzUpLCBzaXplPS41LCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvcj0iYmxhY2siKSArICMuOCAKICAgIGdlb21fdmlvbGluKGxlZ2VuZCA9IEZBTFNFLCB0cmltID0gRkFMU0UsIGFkanVzdCA9IDEsIGRyYXdfcXVhbnRpbGVzID0gMC41LCBmaWxsPSJ0cmFuc3BhcmVudCIsIHNpemU9Ljg1LCBjb2xvcj0iYmxhY2siKSArICMxLjIKICAgIAogICAgZ2VvbV9qaXR0ZXIoc2l6ZT0wLjQsIGFscGhhPTAuNiwgY29sb3I9ImdyYXkiKSArCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9b3VyY29sb3JzKSArCiAgICAjdGhlbWVfY2xhc3NpYygpICsKICAgIHRoZW1lX3JpZGdlcygpICsKICAgIHRoZW1lKAogICAgICBsZWdlbmQucG9zaXRpb249Im5vbmUiLAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTEpCiAgICApICsKICAgIGdndGl0bGUodGl0c3RyKSArCiAgICB4bGFiKHhsYWIpICsKICAgIHlsYWIoeWxhYikKICAKICByZXR1cm4ocGwpCiAgCn0KCgoKIyBGdW5jdGlvbiB0byBjcmVhdGUgZGVuc2l0eSByaWRnZSBwbG90cyBmb3IgZWFjaCBjb25kaXRpb24KIyBJbnB1dDogZGF0YWZyYW1lLCB2YXJpYWJsZSB0byBwbG90LCB0aXRsZSBmb3IgcGxvdApwbG90UmlkZ2VzID0gZnVuY3Rpb24oZGF0YSwgZ3JvdXB2YXIsIHZhciwgdGl0c3RyLCB4bGFiLCB5bGFiKXsKICAKICAjIGRlZmluZSBjb2xvcnMKICBBVlIgPSAnI0NDQkI0NCcKICBBVkkgPSAnIzIyODgzMycKICBWID0gJyNDQzY2NzcnCiAgQSA9ICcjODhDQ0VFJwogIG91cmNvbG9ycyA9IGMoQSwgQVZJLCBBVlIsIFYpCiAgCiAgIyBvbmx5IEFWIGNvbmRpdGlvbnMgcmVsZXZhbnQKICBpZiAodmFyID09ICJ6X2NvcnJlc3AiKXsKICAgIG91cmNvbG9ycyA9IGMoQVZJLCBBVlIpIAogIH0KICAKICAjIFBsb3QKICB2YXIgPSBzeW0odmFyKQogIGdyb3VwdmFyID0gc3ltKGdyb3VwdmFyKQoKICBwbCA9IGRhdGEgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9ISF2YXIsIHk9ISFncm91cHZhciwgZmlsbD0hIWdyb3VwdmFyKSkgKwogICAgCiAgICMgc3RhdF9kZW5zaXR5X3JpZGdlcyhxdWFudGlsZV9saW5lcz1UUlVFLCBxdWFudGlsZXMgPSBjKDAuMDI1LCAwLjk3NSksIGNvbG9yPSJibGFjayIsIGFscGhhID0gMSkgKwogICAgCiAgICBnZW9tX2RlbnNpdHlfcmlkZ2VzKGluaGVyaXQuYWVzID0gVFJVRSwgaml0dGVyZWRfcG9pbnRzID0gVFJVRSwgc3RhdCA9ImRlbnNpdHlfcmlkZ2VzIiwKICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9wb2ludHNfaml0dGVyKHdpZHRoID0gMC4wNSwgaGVpZ2h0ID0gMCksCiAgICAgIHBvaW50X3NoYXBlID0gJ3wnLCBwb2ludF9zaXplID0gMywgcG9pbnRfYWxwaGEgPSAuOSwgYWxwaGEgPSAwLjcpICsKICAgIAogICAgZ2VvbV9kZW5zaXR5X3JpZGdlcyhhbHBoYSA9IDAuODUsIHF1YW50aWxlX2xpbmVzPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPSJ3aGl0ZSIsIHF1YW50aWxlX2Z1bj1mdW5jdGlvbih2YXIsLi4uKW1lYW4odmFyKSkgKwogICAgCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9b3VyY29sb3JzKSArCiAgICB4bGFiKHlsYWIpICsKICAgIHRoZW1lX3JpZGdlcygpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArIAogICAgICAgICAgdGhlbWUoYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKSkKICAKICByZXR1cm4ocGwpCiAgCn0KCgojIEZ1bmN0aW9uIHRvIHJ1biBybSBhbm92YSBhbmQgb3V0cHV0IHN0YXRzCnJ1bmFvdiA9IGZ1bmN0aW9uKGlkLCBkdiwgZGF0YSwgdyl7CiAgZml0ID0gYW92X2V6KGlkLGR2LGRhdGEsd2l0aGluPXcpCiAgcHJpbnQoZml0KQogIGZpdDIgPC0gbHNtZWFucyhmaXQsc3BlY3MgPSBjKHcpKQogIGNvbnRyYXN0KGZpdDIsbWV0aG9kPSJwYWlyd2lzZSIsYWRqdXN0PSJob2xtIikKfQoKIyBDb25kaXRpb25zIHRvIGNvbXBhcmUgYWZ0ZXIgQU5PVkFzCm15X2NvbXBhcmlzb25zIDwtIGxpc3QoIGMoIkF1ZGlvIiwgIkFWLUludGVuZGVkIiksIGMoIkF1ZGlvIiwgIkFWLVJhbmRvbSIpLCBjKCJBdWRpbyIsICJWaXN1YWwiKSwgYygiQVYtSW50ZW5kZWQiLCAiQVYtUmFuZG9tIiksICBjKCJBVi1JbnRlbmRlZCIsICJWaXN1YWwiKSwgYygiQVYtUmFuZG9tIiwgIlZpc3VhbCIpKQpteV9jb21wYXJpc29ucyA9IHJldihteV9jb21wYXJpc29ucykgIyByZXZlcnNlIG9yZGVyIHNvIG1vcmUgcmVhZGFibGUgb24gcGxvdHMKCiMgQ2hvb3NlIHBsb3R0aW5nIHN0eWxlICh2aW9saW4gb3IgcmlkZ2UpIGZvciBmdXR1cmUgcGxvdHMKY3VzdG9tcGxvdCA9IHBsb3RSaWRnZXMKaGlkZV9ucyA9IEZBTFNFCmBgYAoKIyMgVGltZSBzcGVudApIb3cgbXVjaCB0aW1lIGRpZCBwYXJ0aWNpcGFudHMgc3BlbmQgZXhwZXJpZW5jaW5nIHRoZSBwaWVjZXMgaW4gdGhlIGRpZmZlcmVudCBjb25kaXRpb25zPyBEaWQgdGhleSBzcGVuZCBtb3JlIHRpbWUgaW4gb25lIGNvbmRpdGlvbiB2cy4gYW5vdGhlcj8KYGBge3J9CnpfbWVhbnMkbG9ndGltZSA9IGxvZyh6X21lYW5zJG1lYW5fdGltZXNwZW50KQpwID0gY3VzdG9tcGxvdCh6X21lYW5zLCAiY29uZGl0aW9uIiwgIm1lYW5fdGltZXNwZW50IiwgIiIsICJDb25kaXRpb24iLCAiTWVhbiBUaW1lIFNwZW50IChzZWNzKSIpCnBsb3RUaW1lU2VjcyA9IHAgKyBzdGF0X2NvbXBhcmVfbWVhbnMoY29tcGFyaXNvbnMgPSBteV9jb21wYXJpc29ucywgbGFiZWwgPSAicC5zaWduaWYiLCBtZXRob2QgPSAidC50ZXN0IiwgcGFpcmVkID0gInRydWUiLCBuYS5ybT1UUlVFLCBoaWRlLm5zPWhpZGVfbnMpCgpwID0gY3VzdG9tcGxvdCh6X21lYW5zLCAiY29uZGl0aW9uIiwgImxvZ3RpbWUiLCAiIiwgIiIsICJNZWFuIFRpbWUgU3BlbnQgKGxvZyBzZWNzKSIpCnBsb3RUaW1lTG9nID0gcCArIHN0YXRfY29tcGFyZV9tZWFucyhjb21wYXJpc29ucyA9IG15X2NvbXBhcmlzb25zLCBsYWJlbCA9ICJwLnNpZ25pZiIsIG1ldGhvZCA9ICJ0LnRlc3QiLCBwYWlyZWQgPSAidHJ1ZSIsIG5hLnJtPVRSVUUsIGhpZGUubnM9aGlkZV9ucykKel9tZWFucyRleHBfc3ViamVjdF9pZCA9IGFzLmZhY3Rvcih6X21lYW5zJGV4cF9zdWJqZWN0X2lkKQoKcnVuYW92KCJleHBfc3ViamVjdF9pZCIsIm1lYW5fdGltZXNwZW50Iiwgel9tZWFucywgImNvbmRpdGlvbiIpCgojIHByaW50IG1lYW5zIGFuZCBzZHMKY29uZF9tZWFucyA9IHpfbWVhbnMgJT4lCiAgZ3JvdXBfYnkoY29uZGl0aW9uKSAlPiUKICBzdW1tYXJpc2UobWVhbl90aW1lc3BlbnQgPSBtZWFuKG1lYW5fdGltZXNwZW50LCBuYS5ybT1UKSkgICAKCmNvbmRfc2RzID0gel9tZWFucyAlPiUKICBncm91cF9ieShjb25kaXRpb24pICU+JQogIHN1bW1hcmlzZShzZF90aW1lc3BlbnQgPSBzZChtZWFuX3RpbWVzcGVudCwgbmEucm09VCkpCgpwcmludChjb25kX21lYW5zKQpwcmludChjb25kX3NkcykKCnBsb3RUaW1lU2VjcwpwbG90VGltZUxvZwoKcGxvdFRpbWVTZWNzID0gcGxvdFRpbWVTZWNzICsgbGFicyh0aXRsZSA9ICJUaW1lIFNwZW50IiwgdGFnID0gIkEiKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2U9J2JvbGQnKSwgcGxvdC50YWcgPSBlbGVtZW50X3RleHQoZmFjZT0nYm9sZCcpKQpgYGAKCldlIGZpbmQgYSBtYWluIGVmZmVjdCBvZiBjb25kaXRpb24uIFBvc3QtaG9jIHRlc3RzIHNob3cgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgYmV0d2VlbiBhbGwgY29uZGl0aW9ucywgZXhjZXB0IEFWSSBhbmQgQVZSLiBSZXN1bHRzIGRvIG5vdCBjaGFuZ2Ugd2hldGhlciB3ZSB1c2UgcmF3IG1lYW4gdGltZSBzcGVudCBvciBsb2cgb2YgaXQuIAoKCgojIyBFbmpveW1lbnQKRGlkIGVuam95bWVudCBkaWZmZXIgYnkgY29uZGl0aW9uPyAoUSB0byBwYXJ0aWNpcGFudHM6IEkgZW5qb3llZCB0aGUgcGllY2UgKDAtMTAwKSkKYGBge3J9CnAgPSBjdXN0b21wbG90KHpfbWVhbnMsICJjb25kaXRpb24iLCAibWVhbl9lbmpveSIsICIiLCAiQ29uZGl0aW9uIiwgIk1lYW4gRW5qb3ltZW50ICh6LXNjb3JlKSIpCnBsb3RFbmpveSA9IHAgKyBzdGF0X2NvbXBhcmVfbWVhbnMoY29tcGFyaXNvbnMgPSBteV9jb21wYXJpc29ucywgbGFiZWwgPSAicC5zaWduaWYiLCBtZXRob2QgPSAidC50ZXN0IiwgcGFpcmVkID0gInRydWUiLCBuYS5ybT1UUlVFLCBoaWRlLm5zPWhpZGVfbnMpCnJ1bmFvdigiZXhwX3N1YmplY3RfaWQiLCJtZWFuX2Vuam95Iiwgel9tZWFucywgImNvbmRpdGlvbiIpCnBsb3RFbmpveQpwbG90RW5qb3kgPSBwbG90RW5qb3kgKyBsYWJzKHRpdGxlID0gIkVuam95bWVudCIsIHRhZyA9ICJDIikgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlPSdib2xkJyksIHBsb3QudGFnID0gZWxlbWVudF90ZXh0KGZhY2U9J2JvbGQnKSkKYGBgCgpUaGVyZSBpcyBhIHNpZ25pZmljYW50IG1haW4gZWZmZWN0IG9mIGNvbmRpdGlvbiBvbiBFbmpveW1lbnQuIFBvc3QtaG9jIGNvbnRyYXN0cyBzaG93IHRoYXQgQVZJIGFuZCBBVlIgYXJlIGhpZ2hlciBpbiBlbmpveW1lbnQgdGhhbiBBLCBidXQgbm90IFYsIG9yIGVhY2ggb3RoZXIuIChWIGlzIGFsc28gaGlnaGVyIHRoYW4gQSkKU28sIGV2ZW4gdGhvdWdoIHBlb3BsZSBzcGVudCBtb3JlIHRpbWUgd2l0aCBhdWRpbywgdGhleSBlbmpveSBtb3JlIHdpdGggdmlzdWFsLiAKCiMjIEludGVyZXN0aW5nbmVzcwpEaWQgaW50ZXJlc3RpbmduZXNzIGRpZmZlciBieSBjb25kaXRpb24/IChRIHRvIHBhcnRpY2lwYW50czogSSBmb3VuZCB0aGUgcGllY2UgaW50ZXJlc3RpbmcgKDAtMTAwKSkKYGBge3J9CnAgPSBjdXN0b21wbG90KHpfbWVhbnMsICJjb25kaXRpb24iLCAibWVhbl9pbnRlcmVzdGluZyIsICIiLCAiQ29uZGl0aW9uIiwgIk1lYW4gSW50ZXJlc3RpbmduZXNzICh6LXNjb3JlKSIpCnBsb3RJbnRlcmVzdCA9IHAgKyBzdGF0X2NvbXBhcmVfbWVhbnMoY29tcGFyaXNvbnMgPSBteV9jb21wYXJpc29ucywgbGFiZWwgPSAicC5zaWduaWYiLCBtZXRob2QgPSAidC50ZXN0IiwgcGFpcmVkID0gInRydWUiLCBuYS5ybT1UUlVFLCBoaWRlLm5zPWhpZGVfbnMpCnJ1bmFvdigiZXhwX3N1YmplY3RfaWQiLCJtZWFuX2ludGVyZXN0aW5nIiwgel9tZWFucywgImNvbmRpdGlvbiIpCnBsb3RJbnRlcmVzdApwbG90SW50ZXJlc3QgPSBwbG90SW50ZXJlc3QgKyBsYWJzKHRpdGxlID0gIkludGVyZXN0aW5nbmVzcyIsIHRhZyA9ICJEIikgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlPSdib2xkJyksIHBsb3QudGFnID0gZWxlbWVudF90ZXh0KGZhY2U9J2JvbGQnKSkKCmBgYAoKVGhlc2UgaW50ZXJlc3RpbmduZXNzIHJlc3VsdHMgYXJlIGJhc2ljYWxseSBpZGVudGljYWwgdG8gdGhlIG9uZXMgYWJvdmUgZm9yIGVuam95bWVudC4gCgojIyBNb29kIENvbmdydWVuY3kKRGlkIHBhcnRpY2lwYW50cyBmZWVsIHRoZSBwaWVjZSBtYXRjaGVkIHRoZWlyIGN1cnJlbnQgbW9vZCBtb3JlIGluIGNlcnRhaW4gY29uZGl0aW9ucz8gKFEgdG8gcGFydGljaXBhbnRzOiBUaGUgcGllY2UgbWF0Y2hlZCBteSBjdXJyZW50IG1vb2QgKDAtMTAwKSkKYGBge3J9CnAgPSBjdXN0b21wbG90KHpfbWVhbnMsICJjb25kaXRpb24iLCAibWVhbl9tb29kX2NvbmciLCAiIiwgIkNvbmRpdGlvbiIsICJNZWFuIE1vb2QgQ29uZ3J1ZW5jeSAoei1zY29yZSkiKQpwbG90TW9vZCA9IHAgKyBzdGF0X2NvbXBhcmVfbWVhbnMoY29tcGFyaXNvbnMgPSBteV9jb21wYXJpc29ucywgbGFiZWwgPSAicC5zaWduaWYiLCBtZXRob2QgPSAidC50ZXN0IiwgcGFpcmVkID0gInRydWUiLCBuYS5ybT1UUlVFLCBoaWRlLm5zPWhpZGVfbnMpCnJ1bmFvdigiZXhwX3N1YmplY3RfaWQiLCJtZWFuX21vb2RfY29uZyIsIHpfbWVhbnMsICJjb25kaXRpb24iKQpwbG90TW9vZApwbG90TW9vZCA9IHBsb3RNb29kICsgbGFicyh0aXRsZSA9ICJNb29kIENvbmdydWVuY3kiLCB0YWcgPSAiRSIpICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZT0nYm9sZCcpLCBwbG90LnRhZyA9IGVsZW1lbnRfdGV4dChmYWNlPSdib2xkJykpCmBgYAoKVGhlcmUgaXMgYSBzaWduaWZpY2FudCBtYWluIGVmZmVjdCBvZiBjb25kaXRpb24gd2l0aCByZXBlY3QgdG8gd2hldGhlciBwZW9wbGUgdGhpbmsgdGhlIHBpZWNlIG1hdGNoZXMgdGhlaXIgY3VycmVudCBtb29kLiBQb3N0LWhvYyBjb250cmFzdHMgc2hvdyB0aGF0IHBlb3BsZSBhcmUgc2lnbmlmaWNhbnRseSBtb3JlIGxpa2VseSB0byBzYXkgdGhlIHBpZWNlIG1hdGNoZXMgdGhlaXIgbW9vZCBpbiBWIHZzLiBBIGNvbmRpdGlvbnMuIEJ1dCBubyBvdGhlciBwb3N0LWhvYyBjb250cmFzdHMgd2VyZSBzaWduaWZpY2FudC4KCiMjIEZlZWxpbmcgbW92ZWQKRGlkIHBhcnRpY2lwYW50cyBmZWVsIG1vdmVkIGJ5IHRoZSBwaWVjZSBtb3JlIGluIGNlcnRhaW4gY29uZGl0aW9ucz8gKFEgdG8gcGFydGljaXBhbnRzOiBUaGUgcGllY2UgbW92ZWQgbWUgKDAtMTAwKSkKYGBge3J9CnAgPSBjdXN0b21wbG90KHpfbWVhbnMsICJjb25kaXRpb24iLCAibWVhbl9tb3ZlZCIsICIiLCAiQ29uZGl0aW9uIiwgIk1lYW4gRmVlbGluZyBNb3ZlZCAoei1zY29yZSkiKQpydW5hb3YoImV4cF9zdWJqZWN0X2lkIiwibWVhbl9tb3ZlZCIsIHpfbWVhbnMsICJjb25kaXRpb24iKQpwbG90TW92ZWQgPSBwICsgc3RhdF9jb21wYXJlX21lYW5zKGNvbXBhcmlzb25zID0gbXlfY29tcGFyaXNvbnMsIGxhYmVsID0gInAuc2lnbmlmIiwgbWV0aG9kID0gInQudGVzdCIsIHBhaXJlZCA9ICJ0cnVlIiwgbmEucm09VFJVRSwgaGlkZS5ucz1oaWRlX25zKQpwbG90TW92ZWQKcGxvdE1vdmVkID0gcGxvdE1vdmVkICsgbGFicyh0aXRsZSA9ICJGZWVsaW5nIE1vdmVkIiwgdGFnID0gIkYiKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2U9J2JvbGQnKSwgcGxvdC50YWcgPSBlbGVtZW50X3RleHQoZmFjZT0nYm9sZCcpKQpgYGAKClNpZ25pZmljYW50IG1haW4gZWZmZWN0IG9mIGNvbmRpdGlvbiBvbiBmZWVsaW5nIG1vdmVkLiBQb3N0LWhvYyB0ZXN0cyBzaG93cyBubyBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBpbiBmZWVsaW5nIG1vdmVkIGJldHdlZW4gQSB2cy4gViBvciBiZXR3ZWVuIEFWSSB2cy4gQVZSLCBidXQgYWxsIG90aGVyIGNvbnRyYXN0cyB3ZXJlIHNpZ25pZmljYW50LiBUaGlzIGlzIGludGVyZXN0aW5nIGFuZCBwb3RlbnRpYWxseSBhICJsb2FkIiBlZmZlY3QgKGkuZS4sIGJpbW9kYWwgaXMgZ2VuZXJhbGx5IG1vcmUgbW92aW5nIHRoYW4gdW5pLW1vZGFsKQoKIyMgQXVkaW8tdmlzdWFsIGNvcnJlc3BvbmRlbmNlCkNvdWxkIHBhcnRpY2lwYW50cyB0ZWxsIGFib3ZlIGNoYW5jZSB3aGV0aGVyIHRoZSBhdWRpbyBhbmQgdmlzdWFsIG1hdGVyaWFscyBjb3JyZXNwb25kZWQgdG8gb25lIGFub3RoZXI/IChRIHRvIHBhcnRpY2lwYW50czogVG8gd2hhdCBkZWdyZWUgZGlkIHlvdSBmZWVsIHRoZXJlIHdhcyBhIGNvcnJlc3BvbmRlbmNlIGJldHdlZW4gdGhlIGF1ZGlvIGFuZCB2aXN1YWwgc2Vuc2F0aW9ucyB5b3Ugd2VyZSBleHBlcmllbmNpbmc/KQpgYGB7cn0KIyBvbmx5IHpzY29yZSB3aXRoaW4gcmVsZXZhbnQgQVYgY29uZGl0aW9ucwpjb3JyZXNwZGF0YSA9IGRhdGFfdGFza1tkYXRhX3Rhc2skY29uZGl0aW9uID09ICJBVi1JbnRlbmRlZCIgfCBkYXRhX3Rhc2skY29uZGl0aW9uID09ICJBVi1SYW5kb20iLCBdCnpzY29yZWRfY29ycmVzcCA9IGNvcnJlc3BkYXRhICU+JQogIGdyb3VwX2J5KGV4cF9zdWJqZWN0X2lkKSAlPiUKICBtdXRhdGUoel9jb3JyZXNwID0genNjb3JlKGNvcnJlc3BvbmRlbmNlXykpIAoKbWVhbl96X2NvcnJlc3AgPSB6c2NvcmVkX2NvcnJlc3AgJT4lCiAgZ3JvdXBfYnkoZXhwX3N1YmplY3RfaWQsIGNvbmRpdGlvbikgJT4lCiAgc3VtbWFyaXNlKHpfY29ycmVzcCA9IG1lYW4oel9jb3JyZXNwKSkKCiMgcGxvdCBhbmQgY2FsY3VsYXRlIHN0YXRzCnAgPC0gY3VzdG9tcGxvdChtZWFuX3pfY29ycmVzcCwgImNvbmRpdGlvbiIsICJ6X2NvcnJlc3AiLCAiIiwgIkNvbmRpdGlvbiIsICJNZWFuIENvcnJlc3BvbmRlbmNlICh6LXNjb3JlKSIpCnBsb3RBVmNvcnJlc3AgPSBwICsgc3RhdF9jb21wYXJlX21lYW5zKGNvbXBhcmlzb25zID0gbGlzdChjKCJBVi1JbnRlbmRlZCIsICJBVi1SYW5kb20iKSksIGxhYmVsID0gInAuc2lnbmlmIiwgbWV0aG9kID0gInQudGVzdCIsIHBhaXJlZD0idHJ1ZSIsIGxhYmVsLngubnBjPS41KQpjb21wYXJlX21lYW5zKHpfY29ycmVzcCB+IGNvbmRpdGlvbiwgIGRhdGEgPSBtZWFuX3pfY29ycmVzcCwgbWV0aG9kID0gInQudGVzdCIsIGhpZGUubnM9aGlkZV9ucykKcGxvdEFWY29ycmVzcApwbG90QVZjb3JyZXNwID0gcGxvdEFWY29ycmVzcCArIGxhYnModGl0bGUgPSAiQXVkaW92aXN1YWwgQ29ycmVzcG9uZGVuY2UiLCB0YWcgPSAiQiIpICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZT0nYm9sZCcpLCBwbG90LnRhZyA9IGVsZW1lbnRfdGV4dChmYWNlPSdib2xkJykpCiAKYGBgCgpUaGVyZSBpcyBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiBBVkkgYW5kIEFWUiBjb25kaXRpb25zIGluIHRlcm1zIG9mIGZlbHQgY29ycmVzcGVuZGVuY2UgKGkuZS4sIHBhcnRpY3BhbnRzIGZlbHQgdGhhdCB0aGUgaW50ZW50aW9uYWwgcGFpcmluZ3Mgc2hvd2VkIGdyZWF0ZXIgQS1WIGNvcnJlc3BvbmRlbmNlIHRoYW4gdGhlIHJhbmRvbSBwYWlyaW5ncykuIEl0IGlzIHF1aXRlIGludGVyZXN0aW5nIHRoZW4sIHRoYXQgZXZlbiB0aG91Z2ggdGhleSBjb3VsZCB0ZWxsIHRoZSBkaWZmZXJlbmNlIGluIGNvcnJlc3BvbmRlbmNlLCB0aGVyZSB3ZXJlIG5vIGRpZmZlcmVuY2VzIGluIHRlcm1zIG9mIGVuam95bWVudCwgaW50ZXJlc3RpbmduZXNzLCBldGMuIChzZWUgYWxsIHByaW9yIHBsb3RzIGFuZCBzdGF0cykuCgoKIyBGaWd1cmUgMSBmb3IgcGFwZXIKTm93IGNyZWF0ZSBvbmUgZmlndXJlIHdoaWNoIHRpbGVzIGFsbCBvZiBvdXIgcHJldmlvdXMgZmlndXJlcwpgYGB7cn0KaWYgKG9wKSB7dGlmZihwYXN0ZShmaWdfcGF0aCwgImNvbWJpbmVkX0RWc19yaWRnZV9yMS50aWZmIiwgc2VwPSIiKSwgdW5pdHM9ImluIiwgd2lkdGg9OSwgaGVpZ2h0PTExLCByZXM9MzAwKX0KcGxvdEFsbCA9IGdyaWQuYXJyYW5nZShwbG90VGltZVNlY3MsIHBsb3RBVmNvcnJlc3AsIHBsb3RFbmpveSwgcGxvdEludGVyZXN0LCBwbG90TW9vZCwgcGxvdE1vdmVkLCBuY29sID0gMikKcGxvdEFsbAoKZ2dzYXZlKCJjb21iaW5lZF9EVnNfcmlkZ2VfcjEuc3ZnIiwgcGxvdEFsbCwgd2lkdGg9OSwgaGVpZ2h0PTExLCB1bml0cyA9ICJpbiIpCgpgYGAKCk5PVEU6IEluIGZpbmFsLCBwdWJsaWNhdGlvbi1yZWFkeSBmaWd1cmUsIEkgbWFudWFsbHkgcmVtb3ZlZCBub24tc2lnbmlmaWNhbnQgY29tcGFyaXNvbiBicmFja2V0cywgYXMgd2VsbCBhcyBicmFja2V0cyB3aXRoIHAgdmFsdWVzIHRoYXQgZGlkIG5vdCB3aXRoc3RhbmQgbXVsdGlwbGUgY29tcGFyaXNvbnMuIAoKCgoKCgojIFN1cHBsZW1lbnRhcnkgQW5hbHlzaXMgKG5vdCBpbmNsdWRlZCBpbiB0aGUgcGFwZXIpCgojIyBIb3cgZG8gb3VyIGRpZmZlcmVudCBtZWFzdXJlcyBjb3JyZWxhdGUgd2l0aCBvbmUgYW5vdGhlcj8KTm90ZSwgNCBvYnNlcnZhdGlvbnMgcGVyIGNvbmRpdGlvbiBmb3IgZXZlcnkgcGFydGljaXBhbnQuIENhbiBhdmcgYnkgcGFydGljaXBhbnQuCkNvbnN0cnVjdCA0IHNlcGFyYXRlIGNvcnJlbGF0aW9uIG1hdHJpY2VzIGFuZCBzZWUgaWYgZGlmZmVyZW5jZXMgaW4gc3RydWN0dXJlIGJhc2VkIG9uIG1vZGFsaXR5PwoKIyMjIE92ZXJhbGwgY29ycmVsYXRpb24gd2l0aCBhbGwgY29uZGl0aW9ucyBpbmNsdWRlZApgYGB7cn0KIyByZW1vdmUgcmF0aW8gZGlmZiBhbmQgb3RoZXIgY29sdW1ucyB3ZSBkb24ndCBuZWVkIApyYXRpbmdzID0gel9tZWFuc1sgLCAtd2hpY2gobmFtZXMoel9tZWFucykgJWluJSBjKCJleHBfc3ViamVjdF9pZCIsImNvbmRpdGlvbiIsICJtZWFuX2NvcnJlc3AiLCAibG9ndGltZSIpKV0gIyBkcm9wIGxhYmVsIGNvbHVtbnMgYW5kIG9uZXMgbm90IHVzaW5nCnJhdGluZ3MkbWVhbl90aW1lc3BlbnQgPSBsb2cocmF0aW5ncyRtZWFuX3RpbWVzcGVudCkgIyBUT0RPIGNoZWNrIGlmIHdhbnQgdG8gZG8gdGhpcyBvciBub3QKCiMgQ2FwdHVyZSB0aGUgcGxvdCBzbyB3ZSBjYW4gdXNlIGl0IGFnYWluIGxhdGVyCmNoYXJ0LkNvcnJlbGF0aW9uKHJhdGluZ3MsIGhpc3RvZ3JhbT1UUlVFLCBwY2g9MjUsIHRleHQucGFuZWw9bGFicykKYGBgCgojIyMgQ29ycmVsYXRpb25zIGJ5IGNvbmRpdGlvbgojIyMjIEF1ZGlvCmBgYHtyfQojIHJlbW92ZSByYXRpbyBkaWZmIGFuZCBvdGhlciBjb2x1bW5zIHdlIGRvbid0IG5lZWQgCnJhdGluZ3MgPSBzdWJzZXQoel9tZWFucywgY29uZGl0aW9uID09ICdBdWRpbycpCnJhdGluZ3MgPSByYXRpbmdzWyAsIC13aGljaChuYW1lcyhyYXRpbmdzKSAlaW4lIGMoImV4cF9zdWJqZWN0X2lkIiwiY29uZGl0aW9uIiwgIm1lYW5fY29ycmVzcCIsICJsb2d0aW1lIikpXSAjIGRyb3AgbGFiZWwgY29sdW1ucyBhbmQgb25lcyBub3QgdXNpbmcKcmF0aW5ncyRtZWFuX3RpbWVzcGVudCA9IGxvZyhyYXRpbmdzJG1lYW5fdGltZXNwZW50KQoKY2hhcnQuQ29ycmVsYXRpb24ocmF0aW5ncywgaGlzdG9ncmFtPVRSVUUsIHBjaD0yNSwgdGV4dC5wYW5lbD1sYWJzKQpgYGAKCiMjIyMgVmlzdWFsCmBgYHtyfQojIHJlbW92ZSByYXRpbyBkaWZmIGFuZCBvdGhlciBjb2x1bW5zIHdlIGRvbid0IG5lZWQgCnJhdGluZ3MgPSBzdWJzZXQoel9tZWFucywgY29uZGl0aW9uID09ICdWaXN1YWwnKQpyYXRpbmdzID0gcmF0aW5nc1sgLCAtd2hpY2gobmFtZXMocmF0aW5ncykgJWluJSBjKCJleHBfc3ViamVjdF9pZCIsImNvbmRpdGlvbiIsICJtZWFuX2NvcnJlc3AiLCAibG9ndGltZSIpKV0gIyBkcm9wIGxhYmVsIGNvbHVtbnMgYW5kIG9uZXMgbm90IHVzaW5nCnJhdGluZ3MkbWVhbl90aW1lc3BlbnQgPSBsb2cocmF0aW5ncyRtZWFuX3RpbWVzcGVudCkKCmNoYXJ0LkNvcnJlbGF0aW9uKHJhdGluZ3MsIGhpc3RvZ3JhbT1UUlVFLCBwY2g9MjUsIHRleHQucGFuZWw9bGFicykKYGBgCgojIyMjIEFWLUludGVuZGVkCmBgYHtyfQojIHJlbW92ZSByYXRpbyBkaWZmIGFuZCBvdGhlciBjb2x1bW5zIHdlIGRvbid0IG5lZWQgCnJhdGluZ3MgPSBzdWJzZXQoel9tZWFucywgY29uZGl0aW9uID09ICdBVi1JbnRlbmRlZCcpCmNvcnJlc3AgPSBzdWJzZXQobWVhbl96X2NvcnJlc3AsIGNvbmRpdGlvbiA9PSAnQVYtSW50ZW5kZWQnKQojcmF0aW5ncyRtZWFuX2NvcnJlc3AgPSBtZWFuX3pfY29ycmVzcApyYXRpbmdzIDwtIG1lcmdlKHg9cmF0aW5ncyx5PWNvcnJlc3AsIAogICAgICAgICAgICAgICAgYnk9ImV4cF9zdWJqZWN0X2lkIikKcmF0aW5ncyA8LSByYXRpbmdzICU+JSAjIHJlbmFtZQogIHJlbmFtZShtZWFuX2NvcnJlc3AgPSB6X2NvcnJlc3ApCnJhdGluZ3MgPSByYXRpbmdzWyAsIC13aGljaChuYW1lcyhyYXRpbmdzKSAlaW4lIGMoImV4cF9zdWJqZWN0X2lkIiwiY29uZGl0aW9uIiwgImNvbmRpdGlvbi54IiwgImNvbmRpdGlvbi55IiwgImxvZ3RpbWUiKSldIApyYXRpbmdzJG1lYW5fdGltZXNwZW50ID0gbG9nKHJhdGluZ3MkbWVhbl90aW1lc3BlbnQpCgpjaGFydC5Db3JyZWxhdGlvbihyYXRpbmdzLCBoaXN0b2dyYW09VFJVRSwgcGNoPTI1LCB0ZXh0LnBhbmVsPWxhYnMpCmBgYAoKCiMjIyMgQVYtcmFuZG9tCmBgYHtyfQojIHJlbW92ZSByYXRpbyBkaWZmIGFuZCBvdGhlciBjb2x1bW5zIHdlIGRvbid0IG5lZWQgCnJhdGluZ3MgPSBzdWJzZXQoel9tZWFucywgY29uZGl0aW9uID09ICdBVi1SYW5kb20nKQpjb3JyZXNwID0gc3Vic2V0KG1lYW5fel9jb3JyZXNwLCBjb25kaXRpb24gPT0gJ0FWLVJhbmRvbScpCnJhdGluZ3MgPC0gbWVyZ2UoeD1yYXRpbmdzLHk9Y29ycmVzcCwgCiAgICAgICAgICAgICAgICBieT0iZXhwX3N1YmplY3RfaWQiKQpyYXRpbmdzIDwtIHJhdGluZ3MgJT4lICMgcmVuYW1lCiAgcmVuYW1lKG1lYW5fY29ycmVzcCA9IHpfY29ycmVzcCkKcmF0aW5ncyA9IHJhdGluZ3NbICwgLXdoaWNoKG5hbWVzKHJhdGluZ3MpICVpbiUgYygiZXhwX3N1YmplY3RfaWQiLCJjb25kaXRpb24iLCAiY29uZGl0aW9uLngiLCAiY29uZGl0aW9uLnkiLCAibG9ndGltZSIpKV0gCnJhdGluZ3MkbWVhbl90aW1lc3BlbnQgPSBsb2cocmF0aW5ncyRtZWFuX3RpbWVzcGVudCkKCgpjaGFydC5Db3JyZWxhdGlvbihyYXRpbmdzLCBoaXN0b2dyYW09VFJVRSwgcGNoPTI1LCB0ZXh0LnBhbmVsPWxhYnMpCmBgYApJdCBzZWVtcyBvdXIgcmF0aW5ncyBzY2FsZXMgYW5kIHRpbWUgc3BlbnQgbWVhc3VyZSBzaG93IGRpZmZlcmVudCByZWxhdGlvbnNoaXBzIHdpdGggZWFjaCBvdGhlciwgZGVwZW5kZW50IG9uIHRoZSBjb25kaXRpb24uIE9uIHRoZSBvbmUgaGFuZCB0aGlzIHNwZWFrcyBhZ2FpbnN0IHNvbWV0aGluZyBsaWtlIGZhY3RvciBhbmFseXNpcyB0byByZWR1Y2UgZGltZW5zaW9uYWxpdHkgd2l0aG91dCB0YWtpbmcgY29uZGl0aW9uIGludG8gYWNjb3VudC4gT24gdGhlIG90aGVyIGhhbmQsIHRoZSByYXRpbmcgc2NhbGVzIGNvbnNpc3RlbnRseSBjb3JyZWxhdGUgd2l0aCBlYWNoIG90aGVyIGFjcm9zcyBjb25kaXRpb25zLiBUaGVyZWZvcmUsIHdlIGNvdWxkIHByb2JhYmx5IHJlZHVjZSB0aGUgcmF0aW5ncywgYXMgd2Ugc3VnZ2VzdGVkIGluIG91ciBwcmUtcmVnaXN0cmF0aW9uLiBOb3RlIHRoYXQgdGhlIHJlbGF0aW9uc2hpcCBvZiB0aGUgcmF0aW5ncyB3aXRoIHRpbWUgc3BlbnQgZG9lcyBub3QgY2hhbmdlIHdoZW4gdXNpbmcgbG9nIHRpbWUgc3BlbnQuIAoKCgojIEZhY3RvciBhbmFseXNpcyBvbiByYXRpbmdzIGRhdGEKCiMjIE9yZ2FuaXplIGFsbCBkYXRhIHdlIHdhbnQgaW50byBvbmUgdGFibGUKYGBge3J9CiMgbWVyZ2UgcGFydGljaXBhbnRzIG1lYW5zIGFuZCBkZW1vIGRhdGEKcGFsbCA9IG1lcmdlKGRhdGFfcGFydGljaXBhbnQsIHpfbWVhbnMsIGJ5PSJleHBfc3ViamVjdF9pZCIpCgojIHJlbW92ZSBjb2x1bW5zIHdlIGRvbid0IG5lZWQgCnBhbGwgPSBwYWxsWyAsIC13aGljaChuYW1lcyhwYWxsKSAlaW4lIGMoImNvdW50cnlfY3VycmVudCIsICJjb3VudHJ5X2hvbWUiLCJwcmV2X2V4cG9zdXJlIiwiYXJlYV9pbnRlbnNlX2Flc19leHAiLCJNb2RhbGl0eV9QcmVmZXJlbmNlX2NhdCIsICJhcmVhX2NyZWF0aXZlX2JlaCIsImFyZWFfYWVzX2FwcHJlYyIpKV0gIAojICJnZW5kZXIiLCJNb2RhbGl0eV9QcmVmZXJlbmNlIiwiT2xsZW4iLCwgImV4cF9zdWJqZWN0X2lkIiwiZ3JvdXBfbmFtZSIsCnBhbGwkbWVhbl90aW1lc3BlbnQgPSBsb2cocGFsbCRtZWFuX3RpbWVzcGVudCkKCiMgbWFrZSBzdXJlIHZhcmlhYmxlIHJpZ2h0IHR5cGUKIyBSZW1vdmUgdGhlICdvcHRpb25fJyBwcmVmaXggYW5kIGtlZXAgb25seSB0aGUgbnVtYmVycyBmb3IgdGhlIG9yZGVyZWQgY2F0ZWdvcmljYWwgY29sdW1ucwpkYXRhJE1vZGFsaXR5X1ByZWZlcmVuY2UgPC0gZ3N1Yignb3B0aW9uXycsICcnLCBkYXRhJE1vZGFsaXR5X1ByZWZlcmVuY2UpCiMgQ29udmVydCB0aGUgY29sdW1uIHRvIG51bWVyaWMKZGF0YSRNb2RhbGl0eV9QcmVmZXJlbmNlIDwtIGFzLm51bWVyaWMoZGF0YSRNb2RhbGl0eV9QcmVmZXJlbmNlKQojIENvbnZlcnQgdG8gb3JkZXJlZCBmYWN0b3IKcGFsbCRNb2RhbGl0eV9QcmVmZXJlbmNlID0gZmFjdG9yKHBhbGwkTW9kYWxpdHlfUHJlZmVyZW5jZSkKCiMgRG8gc2FtZSBmb3Igb2xsZW4gc2NhbGUKZGF0YSRPbGxlbiA8LSBnc3ViKCdvcHRpb25fJywgJycsIGRhdGEkT2xsZW4pCmRhdGEkT2xsZW4gPC0gYXMubnVtZXJpYyhkYXRhJE9sbGVuKQpwYWxsJE9sbGVuID0gZmFjdG9yKHBhbGwkT2xsZW4pCgojIGdlbmRlciBpcyB1bm9yZGVyZWQKcGFsbCRnZW5kZXIgPSBmYWN0b3IocGFsbCRnZW5kZXIsIG9yZGVyZWQgPSBGKQoKI2NoYXJ0LkNvcnJlbGF0aW9uKHBhbGwsIGhpc3RvZ3JhbT1UUlVFLCBwY2g9MjUsIHRleHQucGFuZWw9bGFicykKYGBgCgoKCiMjIENoZWNrIGZvciBzdWl0YWJpbGl0eSBvZiBGQQpgYGB7cn0KIyBvcmdhbml6ZSBkYXRhCmZvcmZhID0gel9tZWFuc1sgLCAtd2hpY2gobmFtZXMoel9tZWFucykgJWluJSBjKCJtZWFuX3RpbWVzcGVudCIsImxvZ3RpbWUiLCAiY29uZGl0aW9uIiwiZXhwX3N1YmplY3RfaWQiLCAiZmFjdG9yX3Njb3JlIikpXSAKCiMgY2hlY2sgZm9yIG1pc3NpbmcgdmFsdWVzCm5uYSA9IHN1bShpcy5uYShmb3JmYSkpICMgMTYgbmFzIGluIHRoZSBkZgojIE4uQi4gTkFzIGhhdmUgYmVlbiBpbnRyb2R1Y2VkIGJ5IHotc2NvcmluZywgZHVlIHRvIGRpdmlkaW5nIGJ5IHplcm8gKG5vIHZhcmlhbmNlKQojIFNpbmNlIHRoZSB0cnVlIG1lYW4gd2FzIHplcm8sIGl0IGlzIGZhaXIgdG8gaW1wdXRlIHdpdGggemVybyAKZm9yZmEkbWVhbl9lbmpveVtpcy5uYShmb3JmYSRtZWFuX2Vuam95KV0gPC0gMApmb3JmYSRtZWFuX21vb2RfY29uZ1tpcy5uYShmb3JmYSRtZWFuX21vb2RfY29uZyldIDwtIDAKZm9yZmEkbWVhbl9tb3ZlZFtpcy5uYShmb3JmYSRtZWFuX21vdmVkKV0gPC0gMApmb3JmYSRtZWFuX2ludGVyZXN0aW5nW2lzLm5hKGZvcmZhJG1lYW5faW50ZXJlc3RpbmcpXSA8LSAwCgojIERvIHRlc3RzIHRvIGRldGVybWluZSBzdWl0YWJpbGl0eSBmb3IgRkEKcHJpbnQoIktNTyIpCktNTyhyPWNvcihmb3JmYSkpCnByaW50KCJCYXJ0bGV0dCIpCmNvcnRlc3QuYmFydGxldHQoZm9yZmEpCnByaW50KCJEZXRlcm1pbmFudCIpCmRldChjb3IoZm9yZmEpKQpgYGAKS2Fpc2Vy4oCZcyAoMTk3NCkgZ3VpZGVsaW5lcywgc3VnZ2VzdCBjdXRvZmYgb2YgS01PIOKJpSA2MCBmb3IgZGV0ZXJtaW5pbmcgdGhlIGZhY3RvcmFiaWxpdHkgb2YgdGhlIHNhbXBsZSBkYXRhLiBIZXJlIHdhcyBhcmUgd2VsbCBhYm92ZSwgc3VnZ2VzdGluZyBzdWl0YWJpbGl0eSBmb3IgRkEuIApQIHZhbHVlIGZvciBCYXJ0bGV0dCdzIHRlc3QgaXMgc2lnbmlmaWNhbnQuIERldGVybWluYW50IGlzIHBvc2l0aXZlLCBpbmRpY2F0aW5nIEZBIHdpbGwgbGlrZWx5IHJ1bi4KCiMjIERldGVybWluZSBudW1iZXIgb2YgZmFjdG9ycwpgYGB7cn0KZmFmaXRmcmVlIDwtIGZhKGZvcmZhLCBuZmFjdG9ycyA9IG5jb2woZm9yZmEpLCByb3RhdGUgPSAibm9uZSIpCm5fZmFjdG9ycyA8LSBsZW5ndGgoZmFmaXRmcmVlJGUudmFsdWVzKQpzY3JlZSAgICAgPC0gZGF0YS5mcmFtZSgKICBGYWN0b3JfbiA9ICBhcy5mYWN0b3IoMTpuX2ZhY3RvcnMpLCAKICBFaWdlbnZhbHVlID0gZmFmaXRmcmVlJGUudmFsdWVzKQpnZ3Bsb3Qoc2NyZWUsIGFlcyh4ID0gRmFjdG9yX24sIHkgPSBFaWdlbnZhbHVlLCBncm91cCA9IDEpKSArIAogIGdlb21fcG9pbnQoKSArIGdlb21fbGluZSgpICsKICB4bGFiKCJOdW1iZXIgb2YgZmFjdG9ycyIpICsKICB5bGFiKCJJbml0aWFsIGVpZ2VudmFsdWUiKSArCiAgbGFicyggdGl0bGUgPSAiU2NyZWUgUGxvdCIsIAogICAgICAgIHN1YnRpdGxlID0gIihCYXNlZCBvbiB0aGUgdW5yZWR1Y2VkIGNvcnJlbGF0aW9uIG1hdHJpeCkiKQpgYGAKCgpgYGB7cn0KZmEubm9uZSA8LSBmYShyPWZvcmZhLCAKICAgICAgICAgICAgICBuZmFjdG9ycyA9IDEsIAogICAgICAgICAgICAgIGZtPSJwYSIsICMgdHlwZSBvZiBmYWN0b3IgYW5hbHlzaXMgd2Ugd2FudCB0byB1c2UgKOKAnHBh4oCdIGlzIHByaW5jaXBhbCBheGlzIGZhY3RvcmluZykKICAgICAgICAgICAgICBtYXguaXRlcj0xMDAsCiAgICAgICAgICAgICAgcm90YXRlPSJ2YXJpbWF4IikgIyBub25lIHJvdGF0aW9uCnByaW50KGZhLm5vbmUpCmBgYAoKIyMgQ29uY2F0ZW5hdGUgc2NvcmVzIHdpdGggb3RoZXIgZGF0YQpgYGB7cn0Kel9tZWFuc1snZmFjdG9yX3Njb3JlJ10gPC0gZmEubm9uZSRzY29yZXMKYGBgCgojIyBSdW4gc2FtZSBhbm92YSBhbmFseXNlcyBhcyBhYm92ZSBidXQgb24gZmFjdG9yIHNjb3JlCmBgYHtyfQpwID0gcGxvdFJpZGdlcyh6X21lYW5zLCAiY29uZGl0aW9uIiwgImZhY3Rvcl9zY29yZSIsICIiLCAiQ29uZGl0aW9uIiwgIk1lYW4gRmFjdG9yIFNjb3JlIikKcnVuYW92KCJleHBfc3ViamVjdF9pZCIsImZhY3Rvcl9zY29yZSIsIHpfbWVhbnMsICJjb25kaXRpb24iKSAKZmFjdG9yUGxvdCA9IHAgKyBzdGF0X2NvbXBhcmVfbWVhbnMoY29tcGFyaXNvbnMgPSBteV9jb21wYXJpc29ucywgbGFiZWwgPSAicC5zaWduaWYiLCBtZXRob2QgPSAidC50ZXN0IiwgcGFpcmVkPSJUcnVlIiwgbmEucm09VFJVRSkKZmFjdG9yUGxvdCA9IGZhY3RvclBsb3QgKyBsYWJzKHkgPSAiTWVhbiBGYWN0b3IgU2NvcmUgKEFlc3RoZXRpYyBFeHBlcmllbmNlKSIpCmZhY3RvclBsb3QKYGBgCkl0IGJhc2ljYWxseSBtaW1pY3MgZW5qb3ltZW50IHJlc3VsdHMsIGFzIHRoYXQgaXRlbSBoYXMgaGlnaGVzdCBmYWN0b3IgbG9hZGluZy4gQnV0IHRoZXJlIHdhcyBjbGVhcmx5IHNvbWV0aGluZyBtb3JlIGludGVyZXN0aW5nIGdvaW5nIG9uIHdpdGggYWxsIG9mIHRoZSBzbWFsbCBkaWZmZXJlbmNlcyBpbiB0aGUgQU5PVkFzIHJlcG9ydGVkIGFib3ZlCgoKYGBge3J9CnJhdGluZ3MgPSB6X21lYW5zWyAsIC13aGljaChuYW1lcyh6X21lYW5zKSAlaW4lIGMoImV4cF9zdWJqZWN0X2lkIiwiY29uZGl0aW9uIiwgIm1lYW5fY29ycmVzcCIpKV0gIyBkcm9wIGxhYmVsIGNvbHVtbnMgYW5kIG9uZXMgbm90IHVzaW5nCnJhdGluZ3MkbWVhbl90aW1lc3BlbnQgPSBsb2cocmF0aW5ncyRtZWFuX3RpbWVzcGVudCkKCnBhcihtZnJvdyA9IGMoMywxKSkKY2hhcnQuQ29ycmVsYXRpb24ocmF0aW5ncywgaGlzdG9ncmFtPVRSVUUsIHBjaD0yNSwgdGV4dC5wYW5lbD1sYWJzKQpmYS5kaWFncmFtKGZhLm5vbmUsIGRpZ2l0cz0yLCBjdXQgPSAuMywgc2ltcGxlPVRSVUUpCiNmYWN0b3JQbG90CmBgYAoKCiMgRXhwbG9yYXRvcnkgYW5hbHlzaXMKCiMjIyBSZWxhdGlvbnNoaXAgYmV0d2VlbiBwZXJzb25hbCB2YXJpYWJsZXMgYW5kIHRpbWUgc3BlbnQgLyBmZWVsaW5nIG1vdmVkIChhbGwgY29uZGl0aW9ucykKYGBge3J9CiMgbWVyZ2UgbWVhbiB0YWJsZSBhbmQgcGFydGljaXBhbnQgbGV2ZWwgdGFibGUKZGYgPSBwYWxsCgojIHBsb3QgcmVsYXRpb24gYmV0d2VlbiBhcmVhIGFuZCBmZWVsaW5nIG1vdmVkCnAgPC0gZ2dwbG90KGRmLCBhZXMoeD1hcmVhX2NvbXBvc2l0ZSwgeT1tZWFuX21vdmVkKSkgKwogIGdlb21fcG9pbnQoKSArIGdlb21fc21vb3RoKG1ldGhvZD1sbSAsIGNvbG9yPSJibGFjayIsIGZpbGw9ImdyYXkiLCBzZT1UUlVFKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKyB0aGVtZV9jbGFzc2ljKCkKCiMgQ3VzdG9tIG1hcmdpbmFsIHBsb3RzOgpwMiA8LSBnZ01hcmdpbmFsKHAsIHR5cGU9ImRlbnNpZ3JhbSIsIGZpbGwgPSAiZ3JheSIpIApwMiAKCgojIHBsb3QgcmVsYXRpb24gYmV0d2VlbiBhcmVhIGFuZCB0aW1lc3BlbnQKcCA8LSBnZ3Bsb3QoZGYsIGFlcyh4PWFyZWFfY29tcG9zaXRlLCB5PW1lYW5fdGltZXNwZW50KSkgKwogIGdlb21fcG9pbnQoKSArIGdlb21fc21vb3RoKG1ldGhvZD1sbSAsIGNvbG9yPSJibGFjayIsIGZpbGw9ImdyYXkiLCBzZT1UUlVFKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKyB0aGVtZV9jbGFzc2ljKCkKCiMgQ3VzdG9tIG1hcmdpbmFsIHBsb3RzOgpwMiA8LSBnZ01hcmdpbmFsKHAsIHR5cGU9ImRlbnNpZ3JhbSIsIGZpbGwgPSAiZ3JheSIpIApwMiAKCmBgYApJIHdvdWxkIGhhdmUgZXhwZWN0ZWQgYSByZWxhdGlvbnNoaXAgYmV0d2VlbiBBUmVBIGFuZCBzb21lIG9mIHRoZSBhZXN0aGV0aWMgbWVhc3VyZXMuIApQZXJoYXBzIEFSZUEgbW9yZSByZWxldmFudCBmb3IgdmlzdWFsIG1vZGFsaXR5LiBCcmVhayBvdXQgYnkgbW9kYWxpdHk/IAoKIyMjIFZpc3VhbC1vbmx5IGRhdGEKYGBge3J9CiMgbWVyZ2UgbWVhbiB0YWJsZSBhbmQgcGFydGljaXBhbnQgbGV2ZWwgdGFibGUKIyBwdmlzID0gcGFsbFssIHBhbGwkY29uZGl0aW9uID09ICdWaXN1YWwnXQojIGRmID0gcHZpcwoKCnB2aXMgPC0gcGFsbCAlPiUKICBmaWx0ZXIoY29uZGl0aW9uID09ICJWaXN1YWwiKQoKZGYgPSBwdmlzCgojIHBsb3QgcmVsYXRpb24gYmV0d2VlbiBhcmVhIGFuZCBmZWVsaW5nIG1vdmVkCnAgPC0gZ2dwbG90KGRmLCBhZXMoeD1hcmVhX2NvbXBvc2l0ZSwgeT1tZWFuX21vdmVkKSkgKwogIGdlb21fcG9pbnQoKSArIGdlb21fc21vb3RoKG1ldGhvZD1sbSAsIGNvbG9yPSJibGFjayIsIGZpbGw9ImdyYXkiLCBzZT1UUlVFKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKyB0aGVtZV9jbGFzc2ljKCkKCiMgQ3VzdG9tIG1hcmdpbmFsIHBsb3RzOgpwMiA8LSBnZ01hcmdpbmFsKHAsIHR5cGU9ImRlbnNpZ3JhbSIsIGZpbGwgPSAiZ3JheSIpIApwMiAKCgojIHBsb3QgcmVsYXRpb24gYmV0d2VlbiBhcmVhIGFuZCB0aW1lc3BlbnQKcCA8LSBnZ3Bsb3QoZGYsIGFlcyh4PWFyZWFfY29tcG9zaXRlLCB5PW1lYW5fdGltZXNwZW50KSkgKwogIGdlb21fcG9pbnQoKSArIGdlb21fc21vb3RoKG1ldGhvZD1sbSAsIGNvbG9yPSJibGFjayIsIGZpbGw9ImdyYXkiLCBzZT1UUlVFKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKyB0aGVtZV9jbGFzc2ljKCkKCiMgQ3VzdG9tIG1hcmdpbmFsIHBsb3RzOgpwMiA8LSBnZ01hcmdpbmFsKHAsIHR5cGU9ImRlbnNpZ3JhbSIsIGZpbGwgPSAiZ3JheSIpIApwMiAKCmBgYAoKCgoKCgoK