# Load and process data
lv.data <- read.csv("/Users/sritejpadmanabhan/Desktop/Research/ShareWithSritej/Exp1/Exp1_lvdata_7June2024.csv", header = TRUE, sep = ',')
print("Data loaded successfully")
[1] "Data loaded successfully"
print(head(lv.data))

if(nrow(lv.data) == 0) stop("Data not loaded correctly or file is empty")
# Summarize the data
lv.sum.data <- lv.data %>%
  filter(CN %in% c(11:15, 16:20, 61:65, 66:70)) %>%
  mutate(Phase = case_when(
    CN >= 11 & CN <= 15 ~ 'Baseline',
    CN >= 16 & CN <= 20 ~ 'Early Adapt',
    CN >= 61 & CN <= 65 ~ 'Late Adapt',
    CN >= 66 & CN <= 70 ~ 'Aftereffect'
  )) %>%
  group_by(SN, Phase, Group, Subject.ID, Gender, YOE_pro, age, Road_Signs, Handedness, VF_central, VF_peripheral, Acuity_RE, Acuity_LE, Cause_of_Impairment, Diagnosis, Duration_of_LV, Low_Vision_Onset, Diagnosis_Category, Technology_Proficiency, Device, Difficulty_with_steps, Difficulty_with_Stairs, Difficulty_with_pouring, Difficulty_with_Obstacles) %>%
  summarise(
    Hand_mean = mean(HandFlip, na.rm = TRUE),
    RT = mean(RT, na.rm = TRUE),
    RTb = mean(RTb, na.rm = TRUE),
    MT = mean(MT, na.rm = TRUE),
    ST = mean(ST, na.rm = TRUE)
  ) %>%
  ungroup() %>%
  mutate(
    Acuity_RE = log10(Acuity_RE / 20),
    Acuity_LE = log10(Acuity_LE / 20),
    min_Acuity = pmin(Acuity_RE, Acuity_LE),
    mean_Acuity = (Acuity_RE + Acuity_LE) / 2
  ) %>%
  mutate(
    VF_P = ifelse(as.character(VF_peripheral) == 'No Impairment', 'Per. Intact', 'Per. Impaired'),
    VF_C = ifelse(as.character(VF_central) == 'No Impairment', 'Cen. Intact', 'Cen. Impaired'),
    VF_P = ifelse(Group == 'Control', 'Per. Intact', VF_P),
    VF_C = ifelse(Group == 'Control', 'Cen. Intact', VF_C),
    Acuity = ifelse(min_Acuity > 0.8890756, 'Low Acuity', 'High Acuity'),
    Acuity = ifelse(Group == 'Control', 'Control', Acuity)
  ) %>%
  mutate(Road_Acuity = ifelse(Road_Signs > 3, 'Higher Acuity', 'Lower Acuity')) %>%
  mutate(Split_age = case_when(
    Group == 'Control' & age > 41 ~ 'Old',
    Group == 'Control' & age <= 41 ~ 'Young',
    Group == 'LV' & age > 59 ~ 'Old',
    Group == 'LV' & age <= 59 ~ 'Young'
  )) %>%
  mutate(ChangeRT = RT - lag(RT))  # only works for early RT
`summarise()` has grouped output by 'SN', 'Phase', 'Group', 'Subject.ID', 'Gender', 'YOE_pro', 'age',
'Road_Signs', 'Handedness', 'VF_central', 'VF_peripheral', 'Acuity_RE', 'Acuity_LE', 'Cause_of_Impairment',
'Diagnosis', 'Duration_of_LV', 'Low_Vision_Onset', 'Diagnosis_Category', 'Technology_Proficiency', 'Device',
'Difficulty_with_steps', 'Difficulty_with_Stairs', 'Difficulty_with_pouring'. You can override using the
`.groups` argument.
print("Data summarized successfully")
[1] "Data summarized successfully"
print(head(lv.sum.data))
NA
NA
# Factor levels for various columns
lv.sum.data$VF_central <- factor(lv.sum.data$VF_central, levels = c('No Impairment', 'Mild', 'Moderate', 'Severe', ' '))
lv.sum.data$VF_peripheral <- factor(lv.sum.data$VF_peripheral, levels = c('No Impairment', 'Mild', 'Moderate', 'Severe', ' '))
lv.sum.data$Phase <- factor(lv.sum.data$Phase, levels = c('Baseline', 'Early Adapt', 'Late Adapt', 'Aftereffect'))
lv.sum.data$VF_C <- factor(lv.sum.data$VF_C, levels = c('Cen. Intact', 'Cen. Impaired'))
lv.sum.data$VF_P <- factor(lv.sum.data$VF_P, levels = c('Per. Intact', 'Per. Impaired'))
lv.sum.data$Road_Acuity <- factor(lv.sum.data$Road_Acuity, levels = c('Higher Acuity', 'Lower Acuity'))
# Summarize individual data
lv.ind.data <- lv.data %>%
  group_by(SN, CN, Block, Group) %>%
  summarise(
    Hand_ind_mean = mean(HandFlip, na.rm = TRUE),
    RT_ind_mean = mean(RT, na.rm = TRUE),
    MT_ind_mean = mean(MT, na.rm = TRUE),
    ST_ind_mean = mean(ST, na.rm = TRUE)
)
`summarise()` has grouped output by 'SN', 'CN', 'Block'. You can override using the `.groups` argument.
print("Individual data summarized successfully")
[1] "Individual data summarized successfully"
print(head(lv.ind.data))
NA
# Summarize group-level data
lv.grp.data <- lv.ind.data %>%
  group_by(CN, Block, Group) %>%
  summarise(
    Hand_grp_mean = mean(Hand_ind_mean, na.rm = TRUE),
    Hand_grp_sem = std.error(Hand_ind_mean, na.rm = TRUE),
    RT_grp_mean = mean(RT_ind_mean, na.rm = TRUE),
    RT_grp_sem = std.error(RT_ind_mean, na.rm = TRUE),
    MT_grp_mean = mean(MT_ind_mean, na.rm = TRUE),
    MT_grp_sem = std.error(MT_ind_mean, na.rm = TRUE),
    ST_grp_mean = mean(ST_ind_mean, na.rm = TRUE),
    ST_grp_sem = std.error(ST_ind_mean, na.rm = TRUE)
)
`summarise()` has grouped output by 'CN', 'Block'. You can override using the `.groups` argument.
print("Group data summarized successfully")
[1] "Group data summarized successfully"
print(head(lv.grp.data))
NA
# Plot all group data
lv.all.plot <- lv.grp.data %>%
  ggplot(aes(x = CN, y = Hand_grp_mean, group = interaction(factor(Block), Group), color = Group, fill = Group)) +
  annotate('segment', x = c(0, 0, 15.5, 65.5), xend = c(75, 75, 15.5, 65.5), y = c(0, 45, -5, -5), yend = c(0, 45, 50, 50), color = 'lightgrey') +
  geom_line() +
  geom_ribbon(aes(ymin = Hand_grp_mean - Hand_grp_sem, ymax = Hand_grp_mean + Hand_grp_sem), alpha = 0.2, color = NA) +
  th + theme(legend.position = 'none') +
  scale_y_continuous(limits = c(-5, 50), breaks = seq(0, 45, 15)) +
  scale_x_continuous(limits = c(0, 75), breaks = c(0, 15, 66, 75)) +
  scale_color_manual(values = c('darkgreen', 'darkmagenta')) +
  scale_fill_manual(values = c('darkgreen', 'darkmagenta')) +
  labs(x = 'Movement Cycle (3 Reaches)', y = 'Hand Angle (°)')

print("Plotting all group data")
[1] "Plotting all group data"
print(lv.all.plot)

# Plot summarized hand data
lv.hand.sum.plot <- lv.sum.data %>%
  filter(Phase != 'Baseline') %>%
  gather(Cond, Value, Hand_mean:ST) %>%
  filter(Cond == 'Hand_mean') %>%
  ggplot(aes(x = Phase, group = interaction(Phase, Group), y = Value, color = Group)) +
  geom_hline(yintercept = c(0), color = "grey") +
  geom_boxplot(outlier.shape = NA) +
  th +
  theme(legend.position = "none") +
  geom_point(position = position_jitterdodge(0.75, jitter.width = 0.2), alpha = 0.3, size = 0.8) +
  stat_summary(fun = "mean", geom = "errorbar", position = position_dodge(0.75), aes(ymax = ..y.., ymin = ..y..), linetype = "dashed", width = 0.70) +
  scale_y_continuous(breaks = seq(-60, 60, 30)) +
  coord_capped_cart(ylim = c(-60, 80)) +
  scale_color_manual(values = my.colors2) +
  labs(x = '', y = 'Hand Angle (°)')

print("Plotting summarized hand data")
[1] "Plotting summarized hand data"
print(lv.hand.sum.plot)

# Enhanced Analysis: Calculate correlations and perform t-tests
cor_test_results <- cor.test(lv.sum.data$Hand_mean, lv.sum.data$RT, method = "pearson")
t_test_results <- t.test(lv.sum.data$Hand_mean ~ lv.sum.data$Group)

# Print statistical test results
print("Correlation Test Results")
[1] "Correlation Test Results"
print(cor_test_results)

    Pearson's product-moment correlation

data:  lv.sum.data$Hand_mean and lv.sum.data$RT
t = 0.61504, df = 318, p-value = 0.539
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 -0.07545585  0.14356679
sample estimates:
       cor 
0.03446934 
print("T-Test Results")
[1] "T-Test Results"
print(t_test_results)

    Welch Two Sample t-test

data:  lv.sum.data$Hand_mean by lv.sum.data$Group
t = -0.41174, df = 317.94, p-value = 0.6808
alternative hypothesis: true difference in means between group Control and group LV is not equal to 0
95 percent confidence interval:
 -3.730268  2.439163
sample estimates:
mean in group Control      mean in group LV 
             14.74431              15.38986 
# Additional plot: Relationship between Hand Mean and Reaction Time
lv.hand_vs_rt.plot <- lv.sum.data %>%
  ggplot(aes(x = Hand_mean, y = RT, color = Group)) +
  geom_point(alpha = 0.7) +
  geom_smooth(method = "lm", se = FALSE) +
  th +
  labs(x = 'Hand Mean (°)', y = 'Reaction Time (ms)', title = 'Relationship between Hand Mean and Reaction Time') +
  scale_color_manual(values = my.colors2)

print("Plotting relationship between Hand Mean and Reaction Time")
[1] "Plotting relationship between Hand Mean and Reaction Time"
print(lv.hand_vs_rt.plot)
`geom_smooth()` using formula = 'y ~ x'

# Additional plot: Distribution of Hand Mean by Group
lv.hand_mean_dist.plot <- lv.sum.data %>%
  ggplot(aes(x = Hand_mean, fill = Group)) +
  geom_histogram(binwidth = 1, alpha = 0.7, position = "identity") +
  th +
  labs(x = 'Hand Mean (°)', y = 'Count', title = 'Distribution of Hand Mean by Group') +
  scale_fill_manual(values = my.colors2)

print("Plotting distribution of Hand Mean by Group")
[1] "Plotting distribution of Hand Mean by Group"
print(lv.hand_mean_dist.plot)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CiMgQ2xlYXIgdGhlIGVudmlyb25tZW50IGFuZCBsb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMKcm0obGlzdCA9IGxzKCkpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocHJhY21hKQpsaWJyYXJ5KHBsb3RyaXgpCmxpYnJhcnkobGVtb24pCgojIERlZmluZSBhIGZ1bmN0aW9uIHRvIHNldCB1cCBwbG90IGFlc3RoZXRpY3MKY2FsbF9hZXN0aGV0aWNzIDwtIGZ1bmN0aW9uKHRleHRfc2l6ZSkgewogIHRoZW1lKAogICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKHNpemUgPSAwLjUpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gJ3JpZ2h0JywKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSB0ZXh0X3NpemUsIGZhbWlseSA9ICJzYW5zIiksCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSB0ZXh0X3NpemUsIGZhbWlseSA9ICJzYW5zIiksCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgwLjkwKSksCiAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgwLjkwKSksCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQodmp1c3QgPSAtMC4zKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHZqdXN0ID0gMCksCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKHNpemUgPSAwLjQpLAogICAgYXhpcy50ZXh0LnguYm90dG9tID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC45MCksIG1hcmdpbiA9IHVuaXQoYyh0ID0gMi41LCByID0gMCwgYiA9IDAsIGwgPSAwKSwgIm1tIikpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHZqdXN0ID0gMSksCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDAuOTApLCBtYXJnaW4gPSB1bml0KGModCA9IDAsIHIgPSAyLjUsIGIgPSAwLCBsID0gMCksICJtbSIpKSwKICAgIGF4aXMudGlja3MubGVuZ3RoID0gdW5pdCgtMS4yLCAibW0iKSwKICAgIGF4aXMudGV4dC54LnRvcCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDAuOTApLCBtYXJnaW4gPSB1bml0KGModCA9IDAsIHIgPSAwLCBiID0gMi41LCBsID0gMCksICJtbSIpKQogICkKfQoKIyBEZWZpbmUgY29sb3JzIGFuZCB0ZXh0IHNpemUKbXkuY29sb3JzIDwtIGMoJ2RhcmtyZWQnLCAiIzAwNjYwMCIsICIjODAwMDgwIikKbXkuY29sb3JzMiA8LSBjKCIjMDA2NjAwIiwgIiM4MDAwODAiLCAiI0ZGOTkwMCIsICdkZWVwc2t5Ymx1ZTQnKQp0ZXh0X3NpemUgPC0gMTQKdGggPC0gY2FsbF9hZXN0aGV0aWNzKHRleHRfc2l6ZSkKCgoKbHYuZGF0YSA8LSByZWFkLmNzdigiL1VzZXJzL3NyaXRlanBhZG1hbmFiaGFuL0Rlc2t0b3AvU2hhcmVXaXRoU3JpdGVqIDQvRXhwMS9FeHAxX2x2ZGF0YV83SnVuZTIwMjQuY3N2IiwgaGVhZGVyID0gVFJVRSwgc2VwID0gJywnKSAKCgpsdi5zdW0uZGF0YSA8LSBsdi5kYXRhICU+JQogIGZpbHRlciggQ04gJWluJSBjKDExOjE1LCAxNjoyMCwgNjE6NjUsIDY2OjcwKSApICU+JQogIG11dGF0ZShQaGFzZSA9IGNhc2Vfd2hlbihDTiA+PSAxMSAmIENOIDw9IDE1IH4gJ0Jhc2VsaW5lJywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENOID49IDE2ICYgQ04gPD0gMjAgfiAnRWFybHkgQWRhcHQnLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgQ04gPj0gNjEgJiBDTiA8PSA2NSB+ICdMYXRlIEFkYXB0JywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENOID49IDY2ICYgQ04gPD0gNzAgfiAnQWZ0ZXJlZmZlY3QnKSkgJT4lIAogIGdyb3VwX2J5KFNOLCBQaGFzZSwgR3JvdXAsIFN1YmplY3QuSUQsR2VuZGVyLAogICAgICAgICAgIFlPRV9wcm8sIGFnZSwgUm9hZF9TaWducywgSGFuZGVkbmVzcywgCiAgICAgICAgICAgVkZfY2VudHJhbCwgVkZfcGVyaXBoZXJhbCwgQWN1aXR5X1JFLCBBY3VpdHlfTEUsIENhdXNlX29mX0ltcGFpcm1lbnQsIAogICAgICAgICAgIERpYWdub3NpcywgRHVyYXRpb25fb2ZfTFYsIExvd19WaXNpb25fT25zZXQsIERpYWdub3Npc19DYXRlZ29yeSwgCiAgICAgICAgICAgVGVjaG5vbG9neV9Qcm9maWNpZW5jeSwgRGV2aWNlLCAKICAgICAgICAgICBEaWZmaWN1bHR5X3dpdGhfc3RlcHMsIERpZmZpY3VsdHlfd2l0aF9TdGFpcnMsIAogICAgICAgICAgIERpZmZpY3VsdHlfd2l0aF9wb3VyaW5nLCBEaWZmaWN1bHR5X3dpdGhfT2JzdGFjbGVzKSAlPiUKICBkcGx5cjo6c3VtbWFyaXNlKEhhbmRfbWVhbiA9IG1lYW4oSGFuZEZsaXAsIG5hLnJtID0gVFJVRSksIAogICAgICAgICAgICAgICAgICAgUlQgPSBtZWFuKFJULCBuYS5ybSA9IFRSVUUpLCAKICAgICAgICAgICAgICAgICAgIFJUYiA9IG1lYW4oUlRiLCBuYS5ybSA9IFRSVUUpLCAKICAgICAgICAgICAgICAgICAgIE1UID0gbWVhbihNVCwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgIFNUID0gbWVhbihTVCwgbmEucm0gPSBUUlVFKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIG11dGF0ZShBY3VpdHlfUkUgPSBsb2cxMChBY3VpdHlfUkUvMjApLCAKICAgICAgICAgQWN1aXR5X0xFID0gbG9nMTAoQWN1aXR5X0xFLzIwKSwgCiAgICAgICAgIG1pbl9BY3VpdHkgPSBwbWluKEFjdWl0eV9SRSwgQWN1aXR5X0xFKSwgCiAgICAgICAgIG1lYW5fQWN1aXR5ID0gKEFjdWl0eV9SRSArIEFjdWl0eV9MRSkvMikgJT4lCiAgbXV0YXRlKFZGX1AgPSBpZmVsc2UoYXMuY2hhcmFjdGVyKFZGX3BlcmlwaGVyYWwpID09ICdObyBJbXBhaXJtZW50JywgJ1Blci4gSW50YWN0JywgJ1Blci4gSW1wYWlyZWQnKSwgCiAgICAgICAgIFZGX0MgPSBpZmVsc2UoYXMuY2hhcmFjdGVyKFZGX2NlbnRyYWwpID09ICdObyBJbXBhaXJtZW50JywgJ0Nlbi4gSW50YWN0JywgJ0Nlbi4gSW1wYWlyZWQnKSwKICAgICAgICAgVkZfUCA9IGlmZWxzZShHcm91cCA9PSAnQ29udHJvbCcsICdQZXIuIEludGFjdCcsIFZGX1ApLAogICAgICAgICBWRl9DID0gaWZlbHNlKEdyb3VwID09ICdDb250cm9sJywgJ0Nlbi4gSW50YWN0JywgVkZfQyksCiAgICAgICAgIEFjdWl0eSA9IGlmZWxzZShtaW5fQWN1aXR5ID4gIDAuODg5MDc1NiwgJ0xvdyBBY3VpdHknLCAnSGlnaCBBY3VpdHknKSwgCiAgICAgICAgIEFjdWl0eSA9IGlmZWxzZShHcm91cCA9PSAnQ29udHJvbCcsICdDb250cm9sJywgQWN1aXR5KSkgJT4lCiAgbXV0YXRlKFJvYWRfQWN1aXR5PSBpZmVsc2UoUm9hZF9TaWducyA+IDMsICdIaWdoZXIgQWN1aXR5JywgJ0xvd2VyIEFjdWl0eScpKSAlPiUKICBtdXRhdGUoU3BsaXRfYWdlID0gY2FzZV93aGVuKEdyb3VwID09ICdDb250cm9sJyAmIGFnZSA+IDQxIH4gJ09sZCcsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR3JvdXAgPT0gJ0NvbnRyb2wnICYgYWdlIDw9IDQxIH4gJ1lvdW5nJywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHcm91cCA9PSAnTFYnICYgYWdlID4gNTkgfiAnT2xkJywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHcm91cCA9PSAnTFYnICYgYWdlIDw9IDU5IH4gJ1lvdW5nJykpICU+JQogIG11dGF0ZShDaGFuZ2VSVCA9IFJUIC0gbGFnKFJUKSkgIyBvbmx5IHdvcmtzIGZvciBlYXJseSBSVCAKCgpsdi5zdW0uZGF0YSRWRl9jZW50cmFsIDwtIGZhY3Rvcihsdi5zdW0uZGF0YSRWRl9jZW50cmFsLCBsZXZlbHMgPSBjKCdObyBJbXBhaXJtZW50JywgJ01pbGQnLCAnTW9kZXJhdGUnLCAnU2V2ZXJlJywgJyAnKSkKbHYuc3VtLmRhdGEkVkZfcGVyaXBoZXJhbCA8LSBmYWN0b3IobHYuc3VtLmRhdGEkVkZfcGVyaXBoZXJhbCwgbGV2ZWxzID0gYygnTm8gSW1wYWlybWVudCcsICdNaWxkJywgJ01vZGVyYXRlJywgJ1NldmVyZScsICcgJykpCmx2LnN1bS5kYXRhJFBoYXNlIDwtIGZhY3Rvcihsdi5zdW0uZGF0YSRQaGFzZSwgbGV2ZWxzID0gYygnQmFzZWxpbmUnLCAnRWFybHkgQWRhcHQnLCAnTGF0ZSBBZGFwdCcsICdBZnRlcmVmZmVjdCcpKQpsdi5zdW0uZGF0YSRWRl9DIDwtIGZhY3Rvcihsdi5zdW0uZGF0YSRWRl9DLCBsZXZlbHMgPSBjKCdDZW4uIEludGFjdCcsICdDZW4uIEltcGFpcmVkJykpCmx2LnN1bS5kYXRhJFZGX1AgPC0gZmFjdG9yKGx2LnN1bS5kYXRhJFZGX1AsIGxldmVscyA9IGMoJ1Blci4gSW50YWN0JywgJ1Blci4gSW1wYWlyZWQnKSkKbHYuc3VtLmRhdGEkUm9hZF9BY3VpdHkgPC0gZmFjdG9yKGx2LnN1bS5kYXRhJFJvYWRfQWN1aXR5LCBsZXZlbHMgPSBjKCdIaWdoZXIgQWN1aXR5JywgJ0xvd2VyIEFjdWl0eScpKQoKYGBgCgpgYGB7cn0KCiMgTG9hZCBhbmQgcHJvY2VzcyBkYXRhCmx2LmRhdGEgPC0gcmVhZC5jc3YoIi9Vc2Vycy9zcml0ZWpwYWRtYW5hYmhhbi9EZXNrdG9wL1Jlc2VhcmNoL1NoYXJlV2l0aFNyaXRlai9FeHAxL0V4cDFfbHZkYXRhXzdKdW5lMjAyNC5jc3YiLCBoZWFkZXIgPSBUUlVFLCBzZXAgPSAnLCcpCnByaW50KCJEYXRhIGxvYWRlZCBzdWNjZXNzZnVsbHkiKQpwcmludChoZWFkKGx2LmRhdGEpKQoKaWYobnJvdyhsdi5kYXRhKSA9PSAwKSBzdG9wKCJEYXRhIG5vdCBsb2FkZWQgY29ycmVjdGx5IG9yIGZpbGUgaXMgZW1wdHkiKQoKCmBgYAoKCmBgYHtyfQojIFN1bW1hcml6ZSB0aGUgZGF0YQpsdi5zdW0uZGF0YSA8LSBsdi5kYXRhICU+JQogIGZpbHRlcihDTiAlaW4lIGMoMTE6MTUsIDE2OjIwLCA2MTo2NSwgNjY6NzApKSAlPiUKICBtdXRhdGUoUGhhc2UgPSBjYXNlX3doZW4oCiAgICBDTiA+PSAxMSAmIENOIDw9IDE1IH4gJ0Jhc2VsaW5lJywKICAgIENOID49IDE2ICYgQ04gPD0gMjAgfiAnRWFybHkgQWRhcHQnLAogICAgQ04gPj0gNjEgJiBDTiA8PSA2NSB+ICdMYXRlIEFkYXB0JywKICAgIENOID49IDY2ICYgQ04gPD0gNzAgfiAnQWZ0ZXJlZmZlY3QnCiAgKSkgJT4lCiAgZ3JvdXBfYnkoU04sIFBoYXNlLCBHcm91cCwgU3ViamVjdC5JRCwgR2VuZGVyLCBZT0VfcHJvLCBhZ2UsIFJvYWRfU2lnbnMsIEhhbmRlZG5lc3MsIFZGX2NlbnRyYWwsIFZGX3BlcmlwaGVyYWwsIEFjdWl0eV9SRSwgQWN1aXR5X0xFLCBDYXVzZV9vZl9JbXBhaXJtZW50LCBEaWFnbm9zaXMsIER1cmF0aW9uX29mX0xWLCBMb3dfVmlzaW9uX09uc2V0LCBEaWFnbm9zaXNfQ2F0ZWdvcnksIFRlY2hub2xvZ3lfUHJvZmljaWVuY3ksIERldmljZSwgRGlmZmljdWx0eV93aXRoX3N0ZXBzLCBEaWZmaWN1bHR5X3dpdGhfU3RhaXJzLCBEaWZmaWN1bHR5X3dpdGhfcG91cmluZywgRGlmZmljdWx0eV93aXRoX09ic3RhY2xlcykgJT4lCiAgc3VtbWFyaXNlKAogICAgSGFuZF9tZWFuID0gbWVhbihIYW5kRmxpcCwgbmEucm0gPSBUUlVFKSwKICAgIFJUID0gbWVhbihSVCwgbmEucm0gPSBUUlVFKSwKICAgIFJUYiA9IG1lYW4oUlRiLCBuYS5ybSA9IFRSVUUpLAogICAgTVQgPSBtZWFuKE1ULCBuYS5ybSA9IFRSVUUpLAogICAgU1QgPSBtZWFuKFNULCBuYS5ybSA9IFRSVUUpCiAgKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKAogICAgQWN1aXR5X1JFID0gbG9nMTAoQWN1aXR5X1JFIC8gMjApLAogICAgQWN1aXR5X0xFID0gbG9nMTAoQWN1aXR5X0xFIC8gMjApLAogICAgbWluX0FjdWl0eSA9IHBtaW4oQWN1aXR5X1JFLCBBY3VpdHlfTEUpLAogICAgbWVhbl9BY3VpdHkgPSAoQWN1aXR5X1JFICsgQWN1aXR5X0xFKSAvIDIKICApICU+JQogIG11dGF0ZSgKICAgIFZGX1AgPSBpZmVsc2UoYXMuY2hhcmFjdGVyKFZGX3BlcmlwaGVyYWwpID09ICdObyBJbXBhaXJtZW50JywgJ1Blci4gSW50YWN0JywgJ1Blci4gSW1wYWlyZWQnKSwKICAgIFZGX0MgPSBpZmVsc2UoYXMuY2hhcmFjdGVyKFZGX2NlbnRyYWwpID09ICdObyBJbXBhaXJtZW50JywgJ0Nlbi4gSW50YWN0JywgJ0Nlbi4gSW1wYWlyZWQnKSwKICAgIFZGX1AgPSBpZmVsc2UoR3JvdXAgPT0gJ0NvbnRyb2wnLCAnUGVyLiBJbnRhY3QnLCBWRl9QKSwKICAgIFZGX0MgPSBpZmVsc2UoR3JvdXAgPT0gJ0NvbnRyb2wnLCAnQ2VuLiBJbnRhY3QnLCBWRl9DKSwKICAgIEFjdWl0eSA9IGlmZWxzZShtaW5fQWN1aXR5ID4gMC44ODkwNzU2LCAnTG93IEFjdWl0eScsICdIaWdoIEFjdWl0eScpLAogICAgQWN1aXR5ID0gaWZlbHNlKEdyb3VwID09ICdDb250cm9sJywgJ0NvbnRyb2wnLCBBY3VpdHkpCiAgKSAlPiUKICBtdXRhdGUoUm9hZF9BY3VpdHkgPSBpZmVsc2UoUm9hZF9TaWducyA+IDMsICdIaWdoZXIgQWN1aXR5JywgJ0xvd2VyIEFjdWl0eScpKSAlPiUKICBtdXRhdGUoU3BsaXRfYWdlID0gY2FzZV93aGVuKAogICAgR3JvdXAgPT0gJ0NvbnRyb2wnICYgYWdlID4gNDEgfiAnT2xkJywKICAgIEdyb3VwID09ICdDb250cm9sJyAmIGFnZSA8PSA0MSB+ICdZb3VuZycsCiAgICBHcm91cCA9PSAnTFYnICYgYWdlID4gNTkgfiAnT2xkJywKICAgIEdyb3VwID09ICdMVicgJiBhZ2UgPD0gNTkgfiAnWW91bmcnCiAgKSkgJT4lCiAgbXV0YXRlKENoYW5nZVJUID0gUlQgLSBsYWcoUlQpKSAgIyBvbmx5IHdvcmtzIGZvciBlYXJseSBSVAoKcHJpbnQoIkRhdGEgc3VtbWFyaXplZCBzdWNjZXNzZnVsbHkiKQpwcmludChoZWFkKGx2LnN1bS5kYXRhKSkKCgpgYGAKCmBgYHtyfQojIEZhY3RvciBsZXZlbHMgZm9yIHZhcmlvdXMgY29sdW1ucwpsdi5zdW0uZGF0YSRWRl9jZW50cmFsIDwtIGZhY3Rvcihsdi5zdW0uZGF0YSRWRl9jZW50cmFsLCBsZXZlbHMgPSBjKCdObyBJbXBhaXJtZW50JywgJ01pbGQnLCAnTW9kZXJhdGUnLCAnU2V2ZXJlJywgJyAnKSkKbHYuc3VtLmRhdGEkVkZfcGVyaXBoZXJhbCA8LSBmYWN0b3IobHYuc3VtLmRhdGEkVkZfcGVyaXBoZXJhbCwgbGV2ZWxzID0gYygnTm8gSW1wYWlybWVudCcsICdNaWxkJywgJ01vZGVyYXRlJywgJ1NldmVyZScsICcgJykpCmx2LnN1bS5kYXRhJFBoYXNlIDwtIGZhY3Rvcihsdi5zdW0uZGF0YSRQaGFzZSwgbGV2ZWxzID0gYygnQmFzZWxpbmUnLCAnRWFybHkgQWRhcHQnLCAnTGF0ZSBBZGFwdCcsICdBZnRlcmVmZmVjdCcpKQpsdi5zdW0uZGF0YSRWRl9DIDwtIGZhY3Rvcihsdi5zdW0uZGF0YSRWRl9DLCBsZXZlbHMgPSBjKCdDZW4uIEludGFjdCcsICdDZW4uIEltcGFpcmVkJykpCmx2LnN1bS5kYXRhJFZGX1AgPC0gZmFjdG9yKGx2LnN1bS5kYXRhJFZGX1AsIGxldmVscyA9IGMoJ1Blci4gSW50YWN0JywgJ1Blci4gSW1wYWlyZWQnKSkKbHYuc3VtLmRhdGEkUm9hZF9BY3VpdHkgPC0gZmFjdG9yKGx2LnN1bS5kYXRhJFJvYWRfQWN1aXR5LCBsZXZlbHMgPSBjKCdIaWdoZXIgQWN1aXR5JywgJ0xvd2VyIEFjdWl0eScpKQoKYGBgCgpgYGB7cn0KIyBTdW1tYXJpemUgaW5kaXZpZHVhbCBkYXRhCmx2LmluZC5kYXRhIDwtIGx2LmRhdGEgJT4lCiAgZ3JvdXBfYnkoU04sIENOLCBCbG9jaywgR3JvdXApICU+JQogIHN1bW1hcmlzZSgKICAgIEhhbmRfaW5kX21lYW4gPSBtZWFuKEhhbmRGbGlwLCBuYS5ybSA9IFRSVUUpLAogICAgUlRfaW5kX21lYW4gPSBtZWFuKFJULCBuYS5ybSA9IFRSVUUpLAogICAgTVRfaW5kX21lYW4gPSBtZWFuKE1ULCBuYS5ybSA9IFRSVUUpLAogICAgU1RfaW5kX21lYW4gPSBtZWFuKFNULCBuYS5ybSA9IFRSVUUpCikKcHJpbnQoIkluZGl2aWR1YWwgZGF0YSBzdW1tYXJpemVkIHN1Y2Nlc3NmdWxseSIpCnByaW50KGhlYWQobHYuaW5kLmRhdGEpKQoKYGBgCgpgYGB7cn0KIyBTdW1tYXJpemUgZ3JvdXAtbGV2ZWwgZGF0YQpsdi5ncnAuZGF0YSA8LSBsdi5pbmQuZGF0YSAlPiUKICBncm91cF9ieShDTiwgQmxvY2ssIEdyb3VwKSAlPiUKICBzdW1tYXJpc2UoCiAgICBIYW5kX2dycF9tZWFuID0gbWVhbihIYW5kX2luZF9tZWFuLCBuYS5ybSA9IFRSVUUpLAogICAgSGFuZF9ncnBfc2VtID0gc3RkLmVycm9yKEhhbmRfaW5kX21lYW4sIG5hLnJtID0gVFJVRSksCiAgICBSVF9ncnBfbWVhbiA9IG1lYW4oUlRfaW5kX21lYW4sIG5hLnJtID0gVFJVRSksCiAgICBSVF9ncnBfc2VtID0gc3RkLmVycm9yKFJUX2luZF9tZWFuLCBuYS5ybSA9IFRSVUUpLAogICAgTVRfZ3JwX21lYW4gPSBtZWFuKE1UX2luZF9tZWFuLCBuYS5ybSA9IFRSVUUpLAogICAgTVRfZ3JwX3NlbSA9IHN0ZC5lcnJvcihNVF9pbmRfbWVhbiwgbmEucm0gPSBUUlVFKSwKICAgIFNUX2dycF9tZWFuID0gbWVhbihTVF9pbmRfbWVhbiwgbmEucm0gPSBUUlVFKSwKICAgIFNUX2dycF9zZW0gPSBzdGQuZXJyb3IoU1RfaW5kX21lYW4sIG5hLnJtID0gVFJVRSkKKQpwcmludCgiR3JvdXAgZGF0YSBzdW1tYXJpemVkIHN1Y2Nlc3NmdWxseSIpCnByaW50KGhlYWQobHYuZ3JwLmRhdGEpKQoKYGBgCgpgYGB7cn0KIyBQbG90IGFsbCBncm91cCBkYXRhCmx2LmFsbC5wbG90IDwtIGx2LmdycC5kYXRhICU+JQogIGdncGxvdChhZXMoeCA9IENOLCB5ID0gSGFuZF9ncnBfbWVhbiwgZ3JvdXAgPSBpbnRlcmFjdGlvbihmYWN0b3IoQmxvY2spLCBHcm91cCksIGNvbG9yID0gR3JvdXAsIGZpbGwgPSBHcm91cCkpICsKICBhbm5vdGF0ZSgnc2VnbWVudCcsIHggPSBjKDAsIDAsIDE1LjUsIDY1LjUpLCB4ZW5kID0gYyg3NSwgNzUsIDE1LjUsIDY1LjUpLCB5ID0gYygwLCA0NSwgLTUsIC01KSwgeWVuZCA9IGMoMCwgNDUsIDUwLCA1MCksIGNvbG9yID0gJ2xpZ2h0Z3JleScpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBIYW5kX2dycF9tZWFuIC0gSGFuZF9ncnBfc2VtLCB5bWF4ID0gSGFuZF9ncnBfbWVhbiArIEhhbmRfZ3JwX3NlbSksIGFscGhhID0gMC4yLCBjb2xvciA9IE5BKSArCiAgdGggKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnbm9uZScpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNSwgNTApLCBicmVha3MgPSBzZXEoMCwgNDUsIDE1KSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDc1KSwgYnJlYWtzID0gYygwLCAxNSwgNjYsIDc1KSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCdkYXJrZ3JlZW4nLCAnZGFya21hZ2VudGEnKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoJ2RhcmtncmVlbicsICdkYXJrbWFnZW50YScpKSArCiAgbGFicyh4ID0gJ01vdmVtZW50IEN5Y2xlICgzIFJlYWNoZXMpJywgeSA9ICdIYW5kIEFuZ2xlICjCsCknKQoKcHJpbnQoIlBsb3R0aW5nIGFsbCBncm91cCBkYXRhIikKcHJpbnQobHYuYWxsLnBsb3QpCgpgYGAKCmBgYHtyfQojIFBsb3Qgc3VtbWFyaXplZCBoYW5kIGRhdGEKbHYuaGFuZC5zdW0ucGxvdCA8LSBsdi5zdW0uZGF0YSAlPiUKICBmaWx0ZXIoUGhhc2UgIT0gJ0Jhc2VsaW5lJykgJT4lCiAgZ2F0aGVyKENvbmQsIFZhbHVlLCBIYW5kX21lYW46U1QpICU+JQogIGZpbHRlcihDb25kID09ICdIYW5kX21lYW4nKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBQaGFzZSwgZ3JvdXAgPSBpbnRlcmFjdGlvbihQaGFzZSwgR3JvdXApLCB5ID0gVmFsdWUsIGNvbG9yID0gR3JvdXApKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gYygwKSwgY29sb3IgPSAiZ3JleSIpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArCiAgdGggKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZSgwLjc1LCBqaXR0ZXIud2lkdGggPSAwLjIpLCBhbHBoYSA9IDAuMywgc2l6ZSA9IDAuOCkgKwogIHN0YXRfc3VtbWFyeShmdW4gPSAibWVhbiIsIGdlb20gPSAiZXJyb3JiYXIiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNzUpLCBhZXMoeW1heCA9IC4ueS4uLCB5bWluID0gLi55Li4pLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCB3aWR0aCA9IDAuNzApICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKC02MCwgNjAsIDMwKSkgKwogIGNvb3JkX2NhcHBlZF9jYXJ0KHlsaW0gPSBjKC02MCwgODApKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15LmNvbG9yczIpICsKICBsYWJzKHggPSAnJywgeSA9ICdIYW5kIEFuZ2xlICjCsCknKQoKcHJpbnQoIlBsb3R0aW5nIHN1bW1hcml6ZWQgaGFuZCBkYXRhIikKcHJpbnQobHYuaGFuZC5zdW0ucGxvdCkKCmBgYAoKYGBge3J9CiMgRW5oYW5jZWQgQW5hbHlzaXM6IENhbGN1bGF0ZSBjb3JyZWxhdGlvbnMgYW5kIHBlcmZvcm0gdC10ZXN0cwpjb3JfdGVzdF9yZXN1bHRzIDwtIGNvci50ZXN0KGx2LnN1bS5kYXRhJEhhbmRfbWVhbiwgbHYuc3VtLmRhdGEkUlQsIG1ldGhvZCA9ICJwZWFyc29uIikKdF90ZXN0X3Jlc3VsdHMgPC0gdC50ZXN0KGx2LnN1bS5kYXRhJEhhbmRfbWVhbiB+IGx2LnN1bS5kYXRhJEdyb3VwKQoKIyBQcmludCBzdGF0aXN0aWNhbCB0ZXN0IHJlc3VsdHMKcHJpbnQoIkNvcnJlbGF0aW9uIFRlc3QgUmVzdWx0cyIpCnByaW50KGNvcl90ZXN0X3Jlc3VsdHMpCnByaW50KCJULVRlc3QgUmVzdWx0cyIpCnByaW50KHRfdGVzdF9yZXN1bHRzKQoKYGBgCgpgYGB7cn0KIyBBZGRpdGlvbmFsIHBsb3Q6IFJlbGF0aW9uc2hpcCBiZXR3ZWVuIEhhbmQgTWVhbiBhbmQgUmVhY3Rpb24gVGltZQpsdi5oYW5kX3ZzX3J0LnBsb3QgPC0gbHYuc3VtLmRhdGEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gSGFuZF9tZWFuLCB5ID0gUlQsIGNvbG9yID0gR3JvdXApKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNykgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsKICB0aCArCiAgbGFicyh4ID0gJ0hhbmQgTWVhbiAowrApJywgeSA9ICdSZWFjdGlvbiBUaW1lIChtcyknLCB0aXRsZSA9ICdSZWxhdGlvbnNoaXAgYmV0d2VlbiBIYW5kIE1lYW4gYW5kIFJlYWN0aW9uIFRpbWUnKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15LmNvbG9yczIpCgpwcmludCgiUGxvdHRpbmcgcmVsYXRpb25zaGlwIGJldHdlZW4gSGFuZCBNZWFuIGFuZCBSZWFjdGlvbiBUaW1lIikKcHJpbnQobHYuaGFuZF92c19ydC5wbG90KQoKYGBgCgpgYGB7cn0KIyBBZGRpdGlvbmFsIHBsb3Q6IERpc3RyaWJ1dGlvbiBvZiBIYW5kIE1lYW4gYnkgR3JvdXAKbHYuaGFuZF9tZWFuX2Rpc3QucGxvdCA8LSBsdi5zdW0uZGF0YSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBIYW5kX21lYW4sIGZpbGwgPSBHcm91cCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEsIGFscGhhID0gMC43LCBwb3NpdGlvbiA9ICJpZGVudGl0eSIpICsKICB0aCArCiAgbGFicyh4ID0gJ0hhbmQgTWVhbiAowrApJywgeSA9ICdDb3VudCcsIHRpdGxlID0gJ0Rpc3RyaWJ1dGlvbiBvZiBIYW5kIE1lYW4gYnkgR3JvdXAnKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbXkuY29sb3JzMikKCnByaW50KCJQbG90dGluZyBkaXN0cmlidXRpb24gb2YgSGFuZCBNZWFuIGJ5IEdyb3VwIikKcHJpbnQobHYuaGFuZF9tZWFuX2Rpc3QucGxvdCkKCmBgYAo=